aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Hernandez <chernand@google.com>2014-08-05 17:53:32 -0700
committerCarlos Hernandez <chernand@google.com>2014-08-05 17:54:05 -0700
commit7faaa9f3f0df9d23790277834d426c3d992ac3ba (patch)
treeb788ae3b96daf9f5a79d8ec434e1e9edd56b3a72
parent810535bb0c575a003b32076e5352ab8fd3f23a1c (diff)
downloadeigen-l-preview.tar.gz
Update Eigen to the latest stable release, 3.2.2android-wear-5.1.1_r1android-wear-5.1.0_r1android-wear-5.0.0_r1android-l-preview_r2android-cts-5.1_r9android-cts-5.1_r8android-cts-5.1_r7android-cts-5.1_r6android-cts-5.1_r5android-cts-5.1_r4android-cts-5.1_r3android-cts-5.1_r28android-cts-5.1_r27android-cts-5.1_r26android-cts-5.1_r25android-cts-5.1_r24android-cts-5.1_r23android-cts-5.1_r22android-cts-5.1_r21android-cts-5.1_r20android-cts-5.1_r2android-cts-5.1_r19android-cts-5.1_r18android-cts-5.1_r17android-cts-5.1_r16android-cts-5.1_r15android-cts-5.1_r14android-cts-5.1_r13android-cts-5.1_r10android-cts-5.1_r1android-cts-5.0_r9android-cts-5.0_r8android-cts-5.0_r7android-cts-5.0_r6android-cts-5.0_r5android-cts-5.0_r4android-cts-5.0_r3android-5.1.1_r9android-5.1.1_r8android-5.1.1_r7android-5.1.1_r6android-5.1.1_r5android-5.1.1_r4android-5.1.1_r38android-5.1.1_r37android-5.1.1_r36android-5.1.1_r35android-5.1.1_r34android-5.1.1_r33android-5.1.1_r30android-5.1.1_r3android-5.1.1_r29android-5.1.1_r28android-5.1.1_r26android-5.1.1_r25android-5.1.1_r24android-5.1.1_r23android-5.1.1_r22android-5.1.1_r20android-5.1.1_r2android-5.1.1_r19android-5.1.1_r18android-5.1.1_r17android-5.1.1_r16android-5.1.1_r15android-5.1.1_r14android-5.1.1_r13android-5.1.1_r12android-5.1.1_r10android-5.1.1_r1android-5.1.0_r5android-5.1.0_r4android-5.1.0_r3android-5.1.0_r1android-5.0.2_r3android-5.0.2_r1android-5.0.1_r1android-5.0.0_r7android-5.0.0_r6android-5.0.0_r5.1android-5.0.0_r5android-5.0.0_r4android-5.0.0_r3android-5.0.0_r2android-5.0.0_r1lollipop-wear-releaselollipop-releaselollipop-mr1-wfc-releaselollipop-mr1-releaselollipop-mr1-fi-releaselollipop-mr1-devlollipop-mr1-cts-releaselollipop-devlollipop-cts-releasel-preview
./Eigen/src/Core/util/NonMPL2.h is left untouched, so that usage of non MPL2 code is disabled. Change-Id: I86fc9257b3c30d0ca15b268d4ef07bf038bba7ca
-rw-r--r--CMakeLists.txt78
-rw-r--r--COPYING.LGPL655
-rw-r--r--COPYING.README3
-rw-r--r--CTestConfig.cmake4
-rw-r--r--CTestCustom.cmake.in5
-rw-r--r--Eigen/Core50
-rw-r--r--Eigen/Eigen2Support15
-rw-r--r--Eigen/Eigenvalues2
-rw-r--r--Eigen/IterativeLinearSolvers2
-rw-r--r--Eigen/MetisSupport28
-rw-r--r--Eigen/OrderingMethods51
-rw-r--r--Eigen/SPQRSupport29
-rw-r--r--Eigen/Sparse14
-rw-r--r--Eigen/SparseCholesky21
-rw-r--r--Eigen/SparseCore4
-rw-r--r--Eigen/SparseLU49
-rw-r--r--Eigen/SparseQR33
-rw-r--r--Eigen/src/Cholesky/LDLT.h122
-rw-r--r--Eigen/src/Cholesky/LLT.h20
-rw-r--r--Eigen/src/CholmodSupport/CholmodSupport.h66
-rw-r--r--Eigen/src/Core/Array.h34
-rw-r--r--Eigen/src/Core/ArrayBase.h2
-rw-r--r--Eigen/src/Core/ArrayWrapper.h66
-rw-r--r--Eigen/src/Core/Assign.h32
-rw-r--r--Eigen/src/Core/Assign_MKL.h2
-rw-r--r--Eigen/src/Core/Block.h184
-rw-r--r--Eigen/src/Core/BooleanRedux.h36
-rw-r--r--Eigen/src/Core/CommaInitializer.h15
-rw-r--r--Eigen/src/Core/CoreIterators.h (renamed from Eigen/src/SparseCore/CoreIterators.h)0
-rw-r--r--Eigen/src/Core/CwiseBinaryOp.h22
-rw-r--r--Eigen/src/Core/CwiseNullaryOp.h134
-rw-r--r--Eigen/src/Core/CwiseUnaryOp.h8
-rw-r--r--Eigen/src/Core/CwiseUnaryView.h15
-rw-r--r--Eigen/src/Core/DenseBase.h72
-rw-r--r--Eigen/src/Core/DenseCoeffsBase.h12
-rw-r--r--Eigen/src/Core/DenseStorage.h122
-rw-r--r--Eigen/src/Core/Diagonal.h41
-rw-r--r--Eigen/src/Core/DiagonalMatrix.h26
-rw-r--r--Eigen/src/Core/DiagonalProduct.h51
-rw-r--r--Eigen/src/Core/Dot.h12
-rw-r--r--Eigen/src/Core/EigenBase.h29
-rw-r--r--Eigen/src/Core/Functors.h132
-rw-r--r--Eigen/src/Core/Fuzzy.h22
-rw-r--r--Eigen/src/Core/GeneralProduct.h100
-rw-r--r--Eigen/src/Core/GenericPacketMath.h50
-rw-r--r--Eigen/src/Core/GlobalFunctions.h49
-rw-r--r--Eigen/src/Core/IO.h13
-rw-r--r--Eigen/src/Core/Map.h30
-rw-r--r--Eigen/src/Core/MapBase.h52
-rw-r--r--Eigen/src/Core/MathFunctions.h354
-rw-r--r--Eigen/src/Core/Matrix.h10
-rw-r--r--Eigen/src/Core/MatrixBase.h79
-rw-r--r--Eigen/src/Core/NoAlias.h9
-rw-r--r--Eigen/src/Core/NumTraits.h3
-rw-r--r--Eigen/src/Core/PermutationMatrix.h46
-rw-r--r--Eigen/src/Core/PlainObjectBase.h179
-rw-r--r--Eigen/src/Core/Product.h98
-rw-r--r--Eigen/src/Core/ProductBase.h20
-rw-r--r--Eigen/src/Core/Random.h14
-rw-r--r--Eigen/src/Core/Redux.h6
-rw-r--r--Eigen/src/Core/Ref.h260
-rw-r--r--Eigen/src/Core/Replicate.h28
-rw-r--r--Eigen/src/Core/ReturnByValue.h2
-rw-r--r--Eigen/src/Core/Select.h14
-rw-r--r--Eigen/src/Core/SelfAdjointView.h16
-rw-r--r--Eigen/src/Core/SelfCwiseBinaryOp.h5
-rw-r--r--Eigen/src/Core/StableNorm.h192
-rw-r--r--Eigen/src/Core/Swap.h34
-rw-r--r--Eigen/src/Core/Transpose.h45
-rw-r--r--Eigen/src/Core/Transpositions.h18
-rw-r--r--Eigen/src/Core/TriangularMatrix.h25
-rw-r--r--Eigen/src/Core/VectorBlock.h189
-rw-r--r--Eigen/src/Core/VectorwiseOp.h52
-rw-r--r--Eigen/src/Core/Visitor.h28
-rw-r--r--Eigen/src/Core/arch/AltiVec/PacketMath.h3
-rw-r--r--Eigen/src/Core/arch/NEON/Complex.h10
-rw-r--r--Eigen/src/Core/arch/NEON/PacketMath.h50
-rw-r--r--Eigen/src/Core/arch/SSE/Complex.h22
-rw-r--r--Eigen/src/Core/arch/SSE/MathFunctions.h101
-rw-r--r--Eigen/src/Core/arch/SSE/PacketMath.h29
-rw-r--r--Eigen/src/Core/products/CoeffBasedProduct.h2
-rw-r--r--Eigen/src/Core/products/GeneralBlockPanelKernel.h302
-rw-r--r--Eigen/src/Core/products/GeneralMatrixMatrix.h7
-rw-r--r--Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h112
-rw-r--r--Eigen/src/Core/products/GeneralMatrixVector.h54
-rw-r--r--Eigen/src/Core/products/GeneralMatrixVector_MKL.h6
-rw-r--r--Eigen/src/Core/products/SelfadjointMatrixMatrix.h66
-rw-r--r--Eigen/src/Core/products/SelfadjointMatrixMatrix_MKL.h10
-rw-r--r--Eigen/src/Core/products/SelfadjointMatrixVector.h33
-rw-r--r--Eigen/src/Core/products/SelfadjointMatrixVector_MKL.h4
-rw-r--r--Eigen/src/Core/products/SelfadjointProduct.h20
-rw-r--r--Eigen/src/Core/products/SelfadjointRank2Update.h18
-rw-r--r--Eigen/src/Core/products/TriangularMatrixMatrix.h40
-rw-r--r--Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h24
-rw-r--r--Eigen/src/Core/products/TriangularMatrixVector.h32
-rw-r--r--Eigen/src/Core/products/TriangularMatrixVector_MKL.h16
-rw-r--r--Eigen/src/Core/products/TriangularSolverMatrix.h18
-rw-r--r--Eigen/src/Core/products/TriangularSolverMatrix_MKL.h4
-rw-r--r--Eigen/src/Core/util/BlasUtil.h10
-rw-r--r--Eigen/src/Core/util/Constants.h15
-rw-r--r--Eigen/src/Core/util/ForwardDeclarations.h7
-rw-r--r--Eigen/src/Core/util/MKL_support.h19
-rw-r--r--Eigen/src/Core/util/Macros.h42
-rw-r--r--Eigen/src/Core/util/Memory.h96
-rw-r--r--Eigen/src/Core/util/Meta.h20
-rw-r--r--Eigen/src/Core/util/StaticAssert.h3
-rw-r--r--Eigen/src/Core/util/XprHelper.h28
-rw-r--r--Eigen/src/Eigen2Support/Geometry/AlignedBox.h4
-rw-r--r--Eigen/src/Eigen2Support/Geometry/AngleAxis.h2
-rw-r--r--Eigen/src/Eigen2Support/Geometry/Hyperplane.h4
-rw-r--r--Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h4
-rw-r--r--Eigen/src/Eigen2Support/Geometry/Quaternion.h2
-rw-r--r--Eigen/src/Eigen2Support/Geometry/Rotation2D.h2
-rw-r--r--Eigen/src/Eigen2Support/Geometry/RotationBase.h2
-rw-r--r--Eigen/src/Eigen2Support/Geometry/Scaling.h2
-rw-r--r--Eigen/src/Eigen2Support/Geometry/Transform.h2
-rw-r--r--Eigen/src/Eigen2Support/Geometry/Translation.h2
-rw-r--r--Eigen/src/Eigen2Support/LeastSquares.h2
-rw-r--r--Eigen/src/Eigen2Support/MathFunctions.h24
-rw-r--r--Eigen/src/Eigen2Support/SVD.h13
-rw-r--r--Eigen/src/Eigenvalues/ComplexEigenSolver.h26
-rw-r--r--Eigen/src/Eigenvalues/ComplexSchur.h102
-rw-r--r--Eigen/src/Eigenvalues/ComplexSchur_MKL.h4
-rw-r--r--Eigen/src/Eigenvalues/EigenSolver.h71
-rw-r--r--Eigen/src/Eigenvalues/GeneralizedEigenSolver.h341
-rw-r--r--Eigen/src/Eigenvalues/HessenbergDecomposition.h6
-rw-r--r--Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h3
-rw-r--r--Eigen/src/Eigenvalues/RealQZ.h624
-rw-r--r--Eigen/src/Eigenvalues/RealSchur.h123
-rw-r--r--Eigen/src/Eigenvalues/RealSchur_MKL.h2
-rw-r--r--Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h33
-rw-r--r--Eigen/src/Eigenvalues/SelfAdjointEigenSolver_MKL.h4
-rw-r--r--Eigen/src/Eigenvalues/Tridiagonalization.h12
-rw-r--r--Eigen/src/Geometry/AlignedBox.h14
-rw-r--r--Eigen/src/Geometry/AngleAxis.h13
-rw-r--r--Eigen/src/Geometry/EulerAngles.h60
-rw-r--r--Eigen/src/Geometry/Homogeneous.h2
-rw-r--r--Eigen/src/Geometry/Hyperplane.h11
-rw-r--r--Eigen/src/Geometry/OrthoMethods.h30
-rw-r--r--Eigen/src/Geometry/ParametrizedLine.h8
-rw-r--r--Eigen/src/Geometry/Quaternion.h108
-rw-r--r--Eigen/src/Geometry/Rotation2D.h15
-rw-r--r--Eigen/src/Geometry/Scaling.h6
-rw-r--r--Eigen/src/Geometry/Transform.h26
-rw-r--r--Eigen/src/Geometry/Umeyama.h31
-rw-r--r--Eigen/src/Householder/BlockHouseholder.h2
-rw-r--r--Eigen/src/Householder/Householder.h13
-rw-r--r--Eigen/src/Householder/HouseholderSequence.h14
-rw-r--r--Eigen/src/IterativeLinearSolvers/BiCGSTAB.h32
-rw-r--r--Eigen/src/IterativeLinearSolvers/ConjugateGradient.h26
-rw-r--r--Eigen/src/IterativeLinearSolvers/IncompleteLUT.h215
-rw-r--r--Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h2
-rw-r--r--Eigen/src/Jacobi/Jacobi.h99
-rw-r--r--Eigen/src/LU/Determinant.h2
-rw-r--r--Eigen/src/LU/FullPivLU.h23
-rw-r--r--Eigen/src/LU/Inverse.h6
-rw-r--r--Eigen/src/LU/PartialPivLU.h9
-rw-r--r--Eigen/src/MetisSupport/CMakeLists.txt6
-rw-r--r--Eigen/src/MetisSupport/MetisSupport.h137
-rw-r--r--Eigen/src/OrderingMethods/Amd.h6
-rw-r--r--Eigen/src/OrderingMethods/Eigen_Colamd.h1850
-rw-r--r--Eigen/src/OrderingMethods/Ordering.h154
-rw-r--r--Eigen/src/PaStiXSupport/PaStiXSupport.h23
-rw-r--r--Eigen/src/PardisoSupport/PardisoSupport.h30
-rw-r--r--Eigen/src/QR/ColPivHouseholderQR.h110
-rw-r--r--Eigen/src/QR/ColPivHouseholderQR_MKL.h7
-rw-r--r--Eigen/src/QR/FullPivHouseholderQR.h92
-rw-r--r--Eigen/src/QR/HouseholderQR.h47
-rw-r--r--Eigen/src/SPQRSupport/CMakeLists.txt6
-rw-r--r--Eigen/src/SPQRSupport/SuiteSparseQRSupport.h314
-rw-r--r--Eigen/src/SVD/JacobiSVD.h182
-rw-r--r--Eigen/src/SVD/JacobiSVD_MKL.h2
-rw-r--r--Eigen/src/SVD/UpperBidiagonalization.h4
-rw-r--r--Eigen/src/SparseCholesky/SimplicialCholesky.h256
-rw-r--r--Eigen/src/SparseCholesky/SimplicialCholesky_impl.h199
-rw-r--r--Eigen/src/SparseCore/AmbiVector.h10
-rw-r--r--Eigen/src/SparseCore/CompressedStorage.h16
-rw-r--r--Eigen/src/SparseCore/ConservativeSparseSparseProduct.h40
-rw-r--r--Eigen/src/SparseCore/MappedSparseMatrix.h2
-rw-r--r--Eigen/src/SparseCore/SparseAssign.h0
-rw-r--r--Eigen/src/SparseCore/SparseBlock.h436
-rw-r--r--Eigen/src/SparseCore/SparseColEtree.h206
-rw-r--r--Eigen/src/SparseCore/SparseCwiseBinaryOp.h7
-rw-r--r--Eigen/src/SparseCore/SparseDenseProduct.h52
-rw-r--r--Eigen/src/SparseCore/SparseDiagonalProduct.h34
-rw-r--r--Eigen/src/SparseCore/SparseDot.h19
-rw-r--r--Eigen/src/SparseCore/SparseMatrix.h617
-rw-r--r--Eigen/src/SparseCore/SparseMatrixBase.h77
-rw-r--r--Eigen/src/SparseCore/SparsePermutation.h4
-rw-r--r--Eigen/src/SparseCore/SparseProduct.h12
-rw-r--r--Eigen/src/SparseCore/SparseSelfAdjointView.h45
-rw-r--r--Eigen/src/SparseCore/SparseSparseProductWithPruning.h23
-rw-r--r--Eigen/src/SparseCore/SparseTranspose.h14
-rw-r--r--Eigen/src/SparseCore/SparseTriangularView.h31
-rw-r--r--Eigen/src/SparseCore/SparseUtil.h30
-rw-r--r--Eigen/src/SparseCore/SparseVector.h159
-rw-r--r--Eigen/src/SparseCore/SparseView.h5
-rw-r--r--Eigen/src/SparseLU/CMakeLists.txt6
-rw-r--r--Eigen/src/SparseLU/SparseLU.h758
-rw-r--r--Eigen/src/SparseLU/SparseLUImpl.h64
-rw-r--r--Eigen/src/SparseLU/SparseLU_Memory.h227
-rw-r--r--Eigen/src/SparseLU/SparseLU_Structs.h111
-rw-r--r--Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h298
-rw-r--r--Eigen/src/SparseLU/SparseLU_Utils.h80
-rw-r--r--Eigen/src/SparseLU/SparseLU_column_bmod.h180
-rw-r--r--Eigen/src/SparseLU/SparseLU_column_dfs.h177
-rw-r--r--Eigen/src/SparseLU/SparseLU_copy_to_ucol.h106
-rw-r--r--Eigen/src/SparseLU/SparseLU_gemm_kernel.h279
-rw-r--r--Eigen/src/SparseLU/SparseLU_heap_relax_snode.h127
-rw-r--r--Eigen/src/SparseLU/SparseLU_kernel_bmod.h130
-rw-r--r--Eigen/src/SparseLU/SparseLU_panel_bmod.h223
-rw-r--r--Eigen/src/SparseLU/SparseLU_panel_dfs.h258
-rw-r--r--Eigen/src/SparseLU/SparseLU_pivotL.h134
-rw-r--r--Eigen/src/SparseLU/SparseLU_pruneL.h135
-rw-r--r--Eigen/src/SparseLU/SparseLU_relax_snode.h83
-rw-r--r--Eigen/src/SparseQR/CMakeLists.txt6
-rw-r--r--Eigen/src/SparseQR/SparseQR.h685
-rw-r--r--Eigen/src/StlSupport/StdDeque.h2
-rw-r--r--Eigen/src/StlSupport/StdList.h2
-rw-r--r--Eigen/src/StlSupport/StdVector.h2
-rw-r--r--Eigen/src/SuperLUSupport/SuperLUSupport.h29
-rw-r--r--Eigen/src/UmfPackSupport/UmfPackSupport.h37
-rw-r--r--Eigen/src/misc/SparseSolve.h17
-rw-r--r--Eigen/src/plugins/ArrayCwiseBinaryOps.h20
-rw-r--r--Eigen/src/plugins/ArrayCwiseUnaryOps.h1
-rw-r--r--Eigen/src/plugins/BlockMethods.h435
-rw-r--r--Eigen/src/plugins/MatrixCwiseBinaryOps.h4
-rw-r--r--README.android6
-rw-r--r--bench/benchGeometry.cpp134
-rw-r--r--bench/bench_gemm.cpp2
-rw-r--r--bench/spbench/CMakeLists.txt13
-rw-r--r--bench/spbench/sp_solver.cpp125
-rw-r--r--bench/spbench/spbench.dtd31
-rw-r--r--bench/spbench/spbenchsolver.cpp15
-rw-r--r--bench/spbench/spbenchsolver.h475
-rw-r--r--bench/spbench/spbenchstyle.h94
-rw-r--r--bench/spbench/test_sparseLU.cpp93
-rw-r--r--bench/spmv.cpp2
-rw-r--r--blas/CMakeLists.txt11
-rw-r--r--blas/GeneralRank1Update.h44
-rw-r--r--blas/PackedSelfadjointProduct.h53
-rw-r--r--blas/PackedTriangularMatrixVector.h79
-rw-r--r--blas/PackedTriangularSolverVector.h88
-rw-r--r--blas/README.txt3
-rw-r--r--blas/Rank2Update.h57
-rw-r--r--blas/chpr.f220
-rw-r--r--blas/chpr2.f255
-rw-r--r--blas/common.h13
-rw-r--r--blas/ctpmv.f329
-rw-r--r--blas/ctpsv.f332
-rw-r--r--blas/double.cpp14
-rw-r--r--blas/dspr.f202
-rw-r--r--blas/dspr2.f233
-rw-r--r--blas/dtpmv.f293
-rw-r--r--blas/dtpsv.f296
-rw-r--r--blas/level1_cplx_impl.h2
-rw-r--r--blas/level1_impl.h21
-rw-r--r--blas/level2_cplx_impl.h178
-rw-r--r--blas/level2_impl.h147
-rw-r--r--blas/level2_real_impl.h210
-rw-r--r--blas/level3_impl.h22
-rw-r--r--blas/single.cpp3
-rw-r--r--blas/sspr.f202
-rw-r--r--blas/sspr2.f233
-rw-r--r--blas/stpmv.f293
-rw-r--r--blas/stpsv.f296
-rw-r--r--blas/testing/dblat1.f476
-rw-r--r--blas/testing/sblat1.f430
-rw-r--r--blas/zhpr.f220
-rw-r--r--blas/zhpr2.f255
-rw-r--r--blas/ztpmv.f329
-rw-r--r--blas/ztpsv.f332
-rw-r--r--cmake/CMakeDetermineVSServicePack.cmake103
-rw-r--r--cmake/EigenConfigureTesting.cmake16
-rw-r--r--cmake/EigenDetermineVSServicePack.cmake27
-rw-r--r--cmake/EigenTesting.cmake35
-rw-r--r--cmake/FindCholmod.cmake11
-rw-r--r--cmake/FindMetis.cmake3
-rw-r--r--cmake/FindSPQR.cmake36
-rw-r--r--cmake/FindSuperLU.cmake3
-rw-r--r--cmake/FindUmfpack.cmake28
-rw-r--r--cmake/language_support.cmake4
-rw-r--r--debug/gdb/printers.py4
-rw-r--r--debug/msvc/eigen.natvis235
-rw-r--r--demos/opengl/CMakeLists.txt34
-rw-r--r--doc/A05_PortingFrom2To3.dox25
-rw-r--r--doc/A10_Eigen2SupportModes.dox12
-rw-r--r--doc/AsciiQuickReference.txt109
-rw-r--r--doc/B01_Experimental.dox5
-rw-r--r--doc/CMakeLists.txt52
-rw-r--r--doc/ClassHierarchy.dox (renamed from doc/I12_ClassHierarchy.dox)6
-rw-r--r--doc/CustomizingEigen.dox (renamed from doc/I00_CustomizingEigen.dox)9
-rw-r--r--doc/Doxyfile.in741
-rw-r--r--doc/FixedSizeVectorizable.dox (renamed from doc/I05_FixedSizeVectorizable.dox)2
-rw-r--r--doc/FunctionsTakingEigenTypes.dox (renamed from doc/I13_FunctionsTakingEigenTypes.dox)57
-rw-r--r--doc/HiPerformance.dox (renamed from doc/I02_HiPerformance.dox)2
-rw-r--r--doc/I10_Assertions.dox13
-rw-r--r--doc/InsideEigenExample.dox (renamed from doc/I03_InsideEigenExample.dox)7
-rw-r--r--doc/Manual.dox159
-rw-r--r--doc/Overview.dox66
-rw-r--r--doc/PassingByValue.dox (renamed from doc/D07_PassingByValue.dox)2
-rw-r--r--doc/PreprocessorDirectives.dox (renamed from doc/I14_PreprocessorDirectives.dox)33
-rw-r--r--doc/QuickReference.dox48
-rw-r--r--doc/QuickStartGuide.dox (renamed from doc/C00_QuickStartGuide.dox)3
-rw-r--r--doc/SparseLinearSystems.dox183
-rw-r--r--doc/SparseQuickReference.dox243
-rw-r--r--doc/StlContainers.dox (renamed from doc/D01_StlContainers.dox)11
-rw-r--r--doc/StorageOrders.dox (renamed from doc/I15_StorageOrders.dox)7
-rw-r--r--doc/StructHavingEigenMembers.dox (renamed from doc/D09_StructHavingEigenMembers.dox)14
-rw-r--r--doc/TemplateKeyword.dox (renamed from doc/I16_TemplateKeyword.dox)6
-rw-r--r--doc/TopicAliasing.dox (renamed from doc/I11_Aliasing.dox)59
-rw-r--r--doc/TopicAssertions.dox108
-rw-r--r--doc/TopicEigenExpressionTemplates.dox (renamed from doc/I06_TopicEigenExpressionTemplates.dox)0
-rw-r--r--doc/TopicLazyEvaluation.dox (renamed from doc/I01_TopicLazyEvaluation.dox)0
-rw-r--r--doc/TopicLinearAlgebraDecompositions.dox5
-rw-r--r--doc/TopicResizing.dox (renamed from doc/I08_Resizing.dox)0
-rw-r--r--doc/TopicScalarTypes.dox (renamed from doc/I07_TopicScalarTypes.dox)0
-rw-r--r--doc/TopicVectorization.dox (renamed from doc/I09_Vectorization.dox)0
-rw-r--r--doc/TutorialAdvancedInitialization.dox (renamed from doc/C05_TutorialAdvancedInitialization.dox)14
-rw-r--r--doc/TutorialArrayClass.dox (renamed from doc/C03_TutorialArrayClass.dox)27
-rw-r--r--doc/TutorialBlockOperations.dox (renamed from doc/C04_TutorialBlockOperations.dox)17
-rw-r--r--doc/TutorialGeometry.dox (renamed from doc/C08_TutorialGeometry.dox)20
-rw-r--r--doc/TutorialLinearAlgebra.dox (renamed from doc/C06_TutorialLinearAlgebra.dox)24
-rw-r--r--doc/TutorialMapClass.dox (renamed from doc/C10_TutorialMapClass.dox)26
-rw-r--r--doc/TutorialMatrixArithmetic.dox (renamed from doc/C02_TutorialMatrixArithmetic.dox)21
-rw-r--r--doc/TutorialMatrixClass.dox (renamed from doc/C01_TutorialMatrixClass.dox)37
-rw-r--r--doc/TutorialReductionsVisitorsBroadcasting.dox (renamed from doc/C07_TutorialReductionsVisitorsBroadcasting.dox)22
-rw-r--r--doc/TutorialSparse.dox (renamed from doc/C09_TutorialSparse.dox)156
-rw-r--r--doc/UnalignedArrayAssert.dox (renamed from doc/D11_UnalignedArrayAssert.dox)11
-rw-r--r--doc/UsingIntelMKL.dox6
-rw-r--r--doc/WrongStackAlignment.dox (renamed from doc/D03_WrongStackAlignment.dox)2
-rw-r--r--doc/eigen_navtree_hacks.js240
-rw-r--r--doc/eigendoxy.css792
-rw-r--r--doc/eigendoxy_footer.html.in37
-rw-r--r--doc/eigendoxy_header.html.in63
-rw-r--r--doc/eigendoxy_layout.xml.in178
-rw-r--r--doc/examples/CMakeLists.txt2
-rw-r--r--doc/examples/QuickStart_example2_dynamic.cpp6
-rw-r--r--doc/examples/QuickStart_example2_fixed.cpp6
-rw-r--r--doc/examples/function_taking_ref.cpp19
-rw-r--r--doc/snippets/Cwise_asin.cpp2
-rw-r--r--doc/snippets/DenseBase_setLinSpaced.cpp2
-rw-r--r--doc/snippets/GeneralizedEigenSolver.cpp7
-rw-r--r--doc/snippets/HouseholderQR_householderQ.cpp7
-rw-r--r--doc/snippets/MatrixBase_applyOnTheLeft.cpp7
-rw-r--r--doc/snippets/MatrixBase_applyOnTheRight.cpp9
-rw-r--r--doc/snippets/MatrixBase_template_int_int_block_int_int_int_int.cpp5
-rw-r--r--doc/snippets/MatrixBase_template_int_int_bottomLeftCorner_int_int.cpp6
-rw-r--r--doc/snippets/MatrixBase_template_int_int_bottomRightCorner_int_int.cpp6
-rw-r--r--doc/snippets/MatrixBase_template_int_int_topLeftCorner_int_int.cpp6
-rw-r--r--doc/snippets/MatrixBase_template_int_int_topRightCorner_int_int.cpp6
-rw-r--r--doc/snippets/RealQZ_compute.cpp17
-rw-r--r--doc/special_examples/CMakeLists.txt7
-rw-r--r--doc/special_examples/Tutorial_sparse_example_details.cpp4
-rw-r--r--lapack/CMakeLists.txt745
-rw-r--r--lapack/cholesky.cpp4
-rw-r--r--lapack/clacgv.f116
-rw-r--r--lapack/cladiv.f97
-rw-r--r--lapack/clarf.f232
-rw-r--r--lapack/clarfb.f771
-rw-r--r--lapack/clarfg.f203
-rw-r--r--lapack/clarft.f328
-rw-r--r--lapack/dladiv.f128
-rw-r--r--lapack/dlamch.f189
-rw-r--r--lapack/dlapy2.f104
-rw-r--r--lapack/dlapy3.f111
-rw-r--r--lapack/dlarf.f227
-rw-r--r--lapack/dlarfb.f762
-rw-r--r--lapack/dlarfg.f196
-rw-r--r--lapack/dlarft.f326
-rw-r--r--lapack/dsecnd_NONE.f52
-rw-r--r--lapack/ilaclc.f118
-rw-r--r--lapack/ilaclr.f121
-rw-r--r--lapack/iladlc.f118
-rw-r--r--lapack/iladlr.f121
-rw-r--r--lapack/ilaslc.f118
-rw-r--r--lapack/ilaslr.f121
-rw-r--r--lapack/ilazlc.f118
-rw-r--r--lapack/ilazlr.f121
-rw-r--r--lapack/lu.cpp4
-rw-r--r--lapack/second_NONE.f52
-rw-r--r--lapack/sladiv.f128
-rw-r--r--lapack/slamch.f192
-rw-r--r--lapack/slapy2.f104
-rw-r--r--lapack/slapy3.f111
-rw-r--r--lapack/slarf.f227
-rw-r--r--lapack/slarfb.f763
-rw-r--r--lapack/slarfg.f196
-rw-r--r--lapack/slarft.f326
-rw-r--r--lapack/zlacgv.f116
-rw-r--r--lapack/zladiv.f97
-rw-r--r--lapack/zlarf.f232
-rw-r--r--lapack/zlarfb.f774
-rw-r--r--lapack/zlarfg.f203
-rw-r--r--lapack/zlarft.f327
-rw-r--r--scripts/cdashtesting.cmake.in49
-rw-r--r--scripts/eigen_gen_docs6
-rw-r--r--test/CMakeLists.txt51
-rw-r--r--test/adjoint.cpp83
-rw-r--r--test/array.cpp81
-rw-r--r--test/array_for_matrix.cpp74
-rw-r--r--test/array_replicate.cpp1
-rw-r--r--test/basicstuff.cpp11
-rw-r--r--test/block.cpp39
-rw-r--r--test/cholesky.cpp132
-rw-r--r--test/conservative_resize.cpp66
-rw-r--r--test/corners.cpp20
-rw-r--r--test/cwiseop.cpp63
-rw-r--r--test/denseLM.cpp190
-rw-r--r--test/determinant.cpp6
-rw-r--r--test/diagonal.cpp16
-rw-r--r--test/diagonalmatrices.cpp10
-rw-r--r--test/dynalloc.cpp3
-rw-r--r--test/eigen2support.cpp4
-rw-r--r--test/eigensolver_complex.cpp21
-rw-r--r--test/eigensolver_generalized_real.cpp59
-rw-r--r--test/eigensolver_generic.cpp20
-rw-r--r--test/eigensolver_selfadjoint.cpp11
-rw-r--r--test/exceptions.cpp4
-rw-r--r--test/geo_alignedbox.cpp11
-rw-r--r--test/geo_eulerangles.cpp100
-rw-r--r--test/geo_hyperplane.cpp4
-rw-r--r--test/geo_parametrizedline.cpp5
-rw-r--r--test/geo_quaternion.cpp63
-rw-r--r--test/geo_transformations.cpp34
-rw-r--r--test/householder.cpp29
-rw-r--r--test/inverse.cpp14
-rw-r--r--test/jacobi.cpp12
-rw-r--r--test/jacobisvd.cpp154
-rw-r--r--test/linearstructure.cpp3
-rw-r--r--test/lu.cpp4
-rw-r--r--test/main.h73
-rw-r--r--test/mapped_matrix.cpp (renamed from test/map.cpp)5
-rw-r--r--test/mapstride.cpp4
-rw-r--r--test/meta.cpp5
-rw-r--r--test/metis_support.cpp39
-rw-r--r--test/miscmatrices.cpp1
-rw-r--r--test/nesting_ops.cpp12
-rw-r--r--test/nomalloc.cpp7
-rw-r--r--test/nullary.cpp6
-rw-r--r--test/packetmath.cpp54
-rw-r--r--test/pastix_support.cpp2
-rw-r--r--test/permutationmatrices.cpp1
-rw-r--r--test/prec_inverse_4x4.cpp4
-rw-r--r--test/product.h1
-rw-r--r--test/product_extra.cpp35
-rw-r--r--test/product_mmtr.cpp2
-rw-r--r--test/product_notemporary.cpp5
-rw-r--r--test/product_selfadjoint.cpp9
-rw-r--r--test/product_symm.cpp2
-rw-r--r--test/product_syrk.cpp47
-rw-r--r--test/product_trmm.cpp5
-rw-r--r--test/product_trmv.cpp4
-rw-r--r--test/qr.cpp7
-rw-r--r--test/qr_colpivoting.cpp8
-rw-r--r--test/qr_fullpivoting.cpp11
-rw-r--r--test/real_qz.cpp65
-rw-r--r--test/redux.cpp39
-rw-r--r--test/ref.cpp252
-rw-r--r--test/schur_complex.cpp19
-rw-r--r--test/schur_real.cpp21
-rw-r--r--test/selfadjoint.cpp5
-rw-r--r--test/simplicial_cholesky.cpp41
-rw-r--r--test/sizeof.cpp2
-rw-r--r--test/sparse.h53
-rw-r--r--test/sparseLM.cpp176
-rw-r--r--test/sparse_basic.cpp350
-rw-r--r--test/sparse_product.cpp82
-rw-r--r--test/sparse_solver.h143
-rw-r--r--test/sparse_vector.cpp31
-rw-r--r--test/sparselu.cpp55
-rw-r--r--test/sparseqr.cpp99
-rw-r--r--test/special_numbers.cpp58
-rw-r--r--test/spqr_support.cpp62
-rw-r--r--test/stable_norm.cpp38
-rw-r--r--test/triangular.cpp9
-rw-r--r--test/umeyama.cpp18
-rw-r--r--test/unalignedcount.cpp2
-rw-r--r--test/upperbidiagonalization.cpp4
-rw-r--r--test/vectorwiseop.cpp35
-rw-r--r--test/visitor.cpp16
-rw-r--r--test/zerosized.cpp31
-rw-r--r--unsupported/Eigen/AdolcForward2
-rw-r--r--unsupported/Eigen/AlignedVector35
-rw-r--r--unsupported/Eigen/ArpackSupport31
-rw-r--r--unsupported/Eigen/AutoDiff2
-rw-r--r--unsupported/Eigen/BVH2
-rw-r--r--unsupported/Eigen/CMakeLists.txt2
-rw-r--r--unsupported/Eigen/FFT2
-rw-r--r--unsupported/Eigen/IterativeSolvers7
-rw-r--r--unsupported/Eigen/KroneckerProduct10
-rw-r--r--unsupported/Eigen/LevenbergMarquardt45
-rw-r--r--unsupported/Eigen/MPRealSupport179
-rw-r--r--unsupported/Eigen/MatrixFunctions93
-rw-r--r--unsupported/Eigen/MoreVectorization10
-rw-r--r--unsupported/Eigen/NonLinearOptimization4
-rw-r--r--unsupported/Eigen/NumericalDiff2
-rw-r--r--unsupported/Eigen/OpenGLSupport9
-rw-r--r--unsupported/Eigen/Polynomials13
-rw-r--r--unsupported/Eigen/SVD39
-rw-r--r--unsupported/Eigen/Skyline10
-rw-r--r--unsupported/Eigen/SparseExtra11
-rw-r--r--unsupported/Eigen/Splines2
-rw-r--r--unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h38
-rw-r--r--unsupported/Eigen/src/AutoDiff/AutoDiffVector.h4
-rw-r--r--unsupported/Eigen/src/BVH/BVAlgorithms.h2
-rw-r--r--unsupported/Eigen/src/Eigenvalues/ArpackSelfAdjointEigenSolver.h805
-rw-r--r--unsupported/Eigen/src/FFT/ei_kissfft_impl.h2
-rw-r--r--unsupported/Eigen/src/IterativeSolvers/ConstrainedConjGrad.h14
-rw-r--r--unsupported/Eigen/src/IterativeSolvers/DGMRES.h542
-rw-r--r--unsupported/Eigen/src/IterativeSolvers/GMRES.h16
-rw-r--r--unsupported/Eigen/src/IterativeSolvers/IncompleteCholesky.h278
-rw-r--r--unsupported/Eigen/src/IterativeSolvers/IterationController.h7
-rw-r--r--unsupported/Eigen/src/IterativeSolvers/MINRES.h302
-rw-r--r--unsupported/Eigen/src/IterativeSolvers/Scaling.h22
-rw-r--r--unsupported/Eigen/src/KroneckerProduct/KroneckerTensorProduct.h281
-rw-r--r--unsupported/Eigen/src/LevenbergMarquardt/CMakeLists.txt6
-rw-r--r--unsupported/Eigen/src/LevenbergMarquardt/CopyrightMINPACK.txt52
-rw-r--r--unsupported/Eigen/src/LevenbergMarquardt/LMcovar.h85
-rw-r--r--unsupported/Eigen/src/LevenbergMarquardt/LMonestep.h202
-rw-r--r--unsupported/Eigen/src/LevenbergMarquardt/LMpar.h160
-rw-r--r--unsupported/Eigen/src/LevenbergMarquardt/LMqrsolv.h189
-rw-r--r--unsupported/Eigen/src/LevenbergMarquardt/LevenbergMarquardt.h377
-rw-r--r--unsupported/Eigen/src/MatrixFunctions/MatrixExponential.h47
-rw-r--r--unsupported/Eigen/src/MatrixFunctions/MatrixFunction.h19
-rw-r--r--unsupported/Eigen/src/MatrixFunctions/MatrixLogarithm.h111
-rw-r--r--unsupported/Eigen/src/MatrixFunctions/MatrixPower.h509
-rw-r--r--unsupported/Eigen/src/MatrixFunctions/MatrixSquareRoot.h58
-rw-r--r--unsupported/Eigen/src/NonLinearOptimization/HybridNonLinearSolver.h29
-rw-r--r--unsupported/Eigen/src/NonLinearOptimization/LevenbergMarquardt.h52
-rw-r--r--unsupported/Eigen/src/NonLinearOptimization/chkder.h4
-rw-r--r--unsupported/Eigen/src/NonLinearOptimization/covar.h5
-rw-r--r--unsupported/Eigen/src/NonLinearOptimization/dogleg.h13
-rw-r--r--unsupported/Eigen/src/NonLinearOptimization/fdjac1.h5
-rw-r--r--unsupported/Eigen/src/NonLinearOptimization/lmpar.h18
-rw-r--r--unsupported/Eigen/src/NonLinearOptimization/r1updt.h8
-rw-r--r--unsupported/Eigen/src/NonLinearOptimization/rwupdt.h2
-rw-r--r--unsupported/Eigen/src/NumericalDiff/NumericalDiff.h10
-rw-r--r--unsupported/Eigen/src/Polynomials/Companion.h1
-rw-r--r--unsupported/Eigen/src/Polynomials/PolynomialSolver.h25
-rw-r--r--unsupported/Eigen/src/Polynomials/PolynomialUtils.h10
-rw-r--r--unsupported/Eigen/src/SVD/BDCSVD.h748
-rw-r--r--unsupported/Eigen/src/SVD/CMakeLists.txt6
-rw-r--r--unsupported/Eigen/src/SVD/JacobiSVD.h782
-rw-r--r--unsupported/Eigen/src/SVD/SVDBase.h236
-rw-r--r--unsupported/Eigen/src/SVD/TODOBdcsvd.txt29
-rw-r--r--unsupported/Eigen/src/SVD/doneInBDCSVD.txt21
-rw-r--r--unsupported/Eigen/src/SparseExtra/BlockOfDynamicSparseMatrix.h8
-rw-r--r--unsupported/Eigen/src/SparseExtra/MarketIO.h6
-rw-r--r--unsupported/Eigen/src/SparseExtra/MatrixMarketIterator.h13
-rw-r--r--unsupported/Eigen/src/Splines/Spline.h22
-rw-r--r--unsupported/Eigen/src/Splines/SplineFitting.h3
-rw-r--r--unsupported/bench/bench_svd.cpp123
-rw-r--r--unsupported/doc/Doxyfile.in1460
-rw-r--r--unsupported/doc/Overview.dox3
-rw-r--r--unsupported/doc/eigendoxy_layout.xml.in177
-rw-r--r--unsupported/doc/examples/MatrixPower.cpp16
-rw-r--r--unsupported/doc/examples/MatrixPower_optimal.cpp17
-rw-r--r--unsupported/doc/examples/PolynomialSolver1.cpp2
-rw-r--r--unsupported/test/CMakeLists.txt10
-rw-r--r--unsupported/test/FFTW.cpp13
-rw-r--r--unsupported/test/NonLinearOptimization.cpp27
-rw-r--r--unsupported/test/autodiff.cpp45
-rw-r--r--unsupported/test/bdcsvd.cpp213
-rw-r--r--unsupported/test/dgmres.cpp31
-rw-r--r--unsupported/test/gmres.cpp6
-rw-r--r--unsupported/test/jacobisvd.cpp198
-rw-r--r--unsupported/test/kronecker_product.cpp76
-rw-r--r--unsupported/test/levenberg_marquardt.cpp1448
-rw-r--r--unsupported/test/matrix_exponential.cpp12
-rw-r--r--unsupported/test/matrix_function.cpp1
-rw-r--r--unsupported/test/matrix_functions.h47
-rw-r--r--unsupported/test/matrix_power.cpp133
-rw-r--r--unsupported/test/matrix_square_root.cpp33
-rw-r--r--unsupported/test/minres.cpp32
-rwxr-xr-xunsupported/test/mpreal/dlmalloc.c5703
-rwxr-xr-xunsupported/test/mpreal/dlmalloc.h562
-rw-r--r--unsupported/test/mpreal/mpreal.cpp597
-rw-r--r--unsupported/test/mpreal/mpreal.h3417
-rw-r--r--unsupported/test/mpreal_support.cpp9
-rw-r--r--unsupported/test/polynomialsolver.cpp14
-rw-r--r--unsupported/test/sparse_extra.cpp1
-rw-r--r--unsupported/test/splines.cpp4
-rw-r--r--unsupported/test/svd_common.h261
584 files changed, 41366 insertions, 22026 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3ba310a27..76a11b9d2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
project(Eigen)
-cmake_minimum_required(VERSION 2.6.2)
+cmake_minimum_required(VERSION 2.8.2)
# guard against in-source builds
@@ -105,26 +105,66 @@ if(EIGEN_DEFAULT_TO_ROW_MAJOR)
add_definitions("-DEIGEN_DEFAULT_TO_ROW_MAJOR")
endif()
-add_definitions("-DEIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS")
-
set(EIGEN_TEST_MAX_SIZE "320" CACHE STRING "Maximal matrix/vector size, default is 320")
-if(CMAKE_COMPILER_IS_GNUCXX)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Wno-long-long -ansi -Wundef -Wcast-align -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -fexceptions -fno-check-new -fno-common -fstrict-aliasing")
+macro(ei_add_cxx_compiler_flag FLAG)
+ string(REGEX REPLACE "-" "" SFLAG ${FLAG})
+ check_cxx_compiler_flag(${FLAG} COMPILER_SUPPORT_${SFLAG})
+ if(COMPILER_SUPPORT_${SFLAG})
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG}")
+ endif()
+endmacro(ei_add_cxx_compiler_flag)
+
+if(NOT MSVC)
+ # We assume that other compilers are partly compatible with GNUCC
+
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions")
set(CMAKE_CXX_FLAGS_DEBUG "-g3")
set(CMAKE_CXX_FLAGS_RELEASE "-g0 -O2")
-
- check_cxx_compiler_flag("-Wno-variadic-macros" COMPILER_SUPPORT_WNOVARIADICMACRO)
- if(COMPILER_SUPPORT_WNOVARIADICMACRO)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-variadic-macros")
+
+ # clang outputs some warnings for unknwon flags that are not caught by check_cxx_compiler_flag
+ # adding -Werror turns such warnings into errors
+ check_cxx_compiler_flag("-Werror" COMPILER_SUPPORT_WERROR)
+ if(COMPILER_SUPPORT_WERROR)
+ set(CMAKE_REQUIRED_FLAGS "-Werror")
endif()
-
- check_cxx_compiler_flag("-Wextra" COMPILER_SUPPORT_WEXTRA)
- if(COMPILER_SUPPORT_WEXTRA)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
+
+ ei_add_cxx_compiler_flag("-pedantic")
+ ei_add_cxx_compiler_flag("-Wall")
+ ei_add_cxx_compiler_flag("-Wextra")
+ #ei_add_cxx_compiler_flag("-Weverything") # clang
+
+ ei_add_cxx_compiler_flag("-Wundef")
+ ei_add_cxx_compiler_flag("-Wcast-align")
+ ei_add_cxx_compiler_flag("-Wchar-subscripts")
+ ei_add_cxx_compiler_flag("-Wnon-virtual-dtor")
+ ei_add_cxx_compiler_flag("-Wunused-local-typedefs")
+ ei_add_cxx_compiler_flag("-Wpointer-arith")
+ ei_add_cxx_compiler_flag("-Wwrite-strings")
+ ei_add_cxx_compiler_flag("-Wformat-security")
+
+ ei_add_cxx_compiler_flag("-Wno-psabi")
+ ei_add_cxx_compiler_flag("-Wno-variadic-macros")
+ ei_add_cxx_compiler_flag("-Wno-long-long")
+
+ ei_add_cxx_compiler_flag("-fno-check-new")
+ ei_add_cxx_compiler_flag("-fno-common")
+ ei_add_cxx_compiler_flag("-fstrict-aliasing")
+ ei_add_cxx_compiler_flag("-wd981") # disable ICC's "operands are evaluated in unspecified order" remark
+ ei_add_cxx_compiler_flag("-wd2304") # disbale ICC's "warning #2304: non-explicit constructor with single argument may cause implicit type conversion" produced by -Wnon-virtual-dtor
+
+ # The -ansi flag must be added last, otherwise it is also used as a linker flag by check_cxx_compiler_flag making it fails
+ # Moreover we should not set both -strict-ansi and -ansi
+ check_cxx_compiler_flag("-strict-ansi" COMPILER_SUPPORT_STRICTANSI)
+ ei_add_cxx_compiler_flag("-Qunused-arguments") # disable clang warning: argument unused during compilation: '-ansi'
+
+ if(COMPILER_SUPPORT_STRICTANSI)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -strict-ansi")
+ else()
+ ei_add_cxx_compiler_flag("-ansi")
endif()
-
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
+
+ set(CMAKE_REQUIRED_FLAGS "")
option(EIGEN_TEST_SSE2 "Enable/Disable SSE2 in tests/examples" OFF)
if(EIGEN_TEST_SSE2)
@@ -177,9 +217,8 @@ if(CMAKE_COMPILER_IS_GNUCXX)
endif()
endif()
-endif(CMAKE_COMPILER_IS_GNUCXX)
+else(NOT MSVC)
-if(MSVC)
# C4127 - conditional expression is constant
# C4714 - marked as __forceinline not inlined (I failed to deactivate it selectively)
# We can disable this warning in the unit tests since it is clear that it occurs
@@ -209,7 +248,7 @@ if(MSVC)
endif(NOT CMAKE_CL_64)
message(STATUS "Enabling SSE2 in tests/examples")
endif(EIGEN_TEST_SSE2)
-endif(MSVC)
+endif(NOT MSVC)
option(EIGEN_TEST_NO_EXPLICIT_VECTORIZATION "Disable explicit vectorization in tests/examples" OFF)
option(EIGEN_TEST_X87 "Force using X87 instructions. Implies no vectorization." OFF)
@@ -308,6 +347,7 @@ add_subdirectory(Eigen)
add_subdirectory(doc EXCLUDE_FROM_ALL)
include(EigenConfigureTesting)
+
# fixme, not sure this line is still needed:
enable_testing() # must be called from the root CMakeLists, see man page
@@ -342,6 +382,8 @@ if(NOT WIN32)
add_subdirectory(bench/spbench EXCLUDE_FROM_ALL)
endif(NOT WIN32)
+configure_file(scripts/cdashtesting.cmake.in cdashtesting.cmake @ONLY)
+
ei_testing_print_summary()
message(STATUS "")
diff --git a/COPYING.LGPL b/COPYING.LGPL
index 0e4fa8aaf..4362b4915 100644
--- a/COPYING.LGPL
+++ b/COPYING.LGPL
@@ -1,165 +1,502 @@
GNU LESSER GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
+ Version 2.1, February 1999
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
-
- This version of the GNU Lesser General Public License incorporates
-the terms and conditions of version 3 of the GNU General Public
-License, supplemented by the additional permissions listed below.
-
- 0. Additional Definitions.
-
- As used herein, "this License" refers to version 3 of the GNU Lesser
-General Public License, and the "GNU GPL" refers to version 3 of the GNU
-General Public License.
-
- "The Library" refers to a covered work governed by this License,
-other than an Application or a Combined Work as defined below.
-
- An "Application" is any work that makes use of an interface provided
-by the Library, but which is not otherwise based on the Library.
-Defining a subclass of a class defined by the Library is deemed a mode
-of using an interface provided by the Library.
-
- A "Combined Work" is a work produced by combining or linking an
-Application with the Library. The particular version of the Library
-with which the Combined Work was made is also called the "Linked
-Version".
-
- The "Minimal Corresponding Source" for a Combined Work means the
-Corresponding Source for the Combined Work, excluding any source code
-for portions of the Combined Work that, considered in isolation, are
-based on the Application, and not on the Linked Version.
-
- The "Corresponding Application Code" for a Combined Work means the
-object code and/or source code for the Application, including any data
-and utility programs needed for reproducing the Combined Work from the
-Application, but excluding the System Libraries of the Combined Work.
-
- 1. Exception to Section 3 of the GNU GPL.
-
- You may convey a covered work under sections 3 and 4 of this License
-without being bound by section 3 of the GNU GPL.
-
- 2. Conveying Modified Versions.
-
- If you modify a copy of the Library, and, in your modifications, a
-facility refers to a function or data to be supplied by an Application
-that uses the facility (other than as an argument passed when the
-facility is invoked), then you may convey a copy of the modified
-version:
-
- a) under this License, provided that you make a good faith effort to
- ensure that, in the event an Application does not supply the
- function or data, the facility still operates, and performs
- whatever part of its purpose remains meaningful, or
-
- b) under the GNU GPL, with none of the additional permissions of
- this License applicable to that copy.
-
- 3. Object Code Incorporating Material from Library Header Files.
-
- The object code form of an Application may incorporate material from
-a header file that is part of the Library. You may convey such object
-code under terms of your choice, provided that, if the incorporated
-material is not limited to numerical parameters, data structure
-layouts and accessors, or small macros, inline functions and templates
-(ten or fewer lines in length), you do both of the following:
-
- a) Give prominent notice with each copy of the object code that the
- Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the object code with a copy of the GNU GPL and this license
- document.
-
- 4. Combined Works.
-
- You may convey a Combined Work under terms of your choice that,
-taken together, effectively do not restrict modification of the
-portions of the Library contained in the Combined Work and reverse
-engineering for debugging such modifications, if you also do each of
-the following:
-
- a) Give prominent notice with each copy of the Combined Work that
- the Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the Combined Work with a copy of the GNU GPL and this license
- document.
-
- c) For a Combined Work that displays copyright notices during
- execution, include the copyright notice for the Library among
- these notices, as well as a reference directing the user to the
- copies of the GNU GPL and this license document.
-
- d) Do one of the following:
-
- 0) Convey the Minimal Corresponding Source under the terms of this
- License, and the Corresponding Application Code in a form
- suitable for, and under terms that permit, the user to
- recombine or relink the Application with a modified version of
- the Linked Version to produce a modified Combined Work, in the
- manner specified by section 6 of the GNU GPL for conveying
- Corresponding Source.
-
- 1) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (a) uses at run time
- a copy of the Library already present on the user's computer
- system, and (b) will operate properly with a modified version
- of the Library that is interface-compatible with the Linked
- Version.
-
- e) Provide Installation Information, but only if you would otherwise
- be required to provide such information under section 6 of the
- GNU GPL, and only to the extent that such information is
- necessary to install and execute a modified version of the
- Combined Work produced by recombining or relinking the
- Application with a modified version of the Linked Version. (If
- you use option 4d0, the Installation Information must accompany
- the Minimal Corresponding Source and Corresponding Application
- Code. If you use option 4d1, you must provide the Installation
- Information in the manner specified by section 6 of the GNU GPL
- for conveying Corresponding Source.)
-
- 5. Combined Libraries.
-
- You may place library facilities that are a work based on the
-Library side by side in a single library together with other library
-facilities that are not Applications and are not covered by this
-License, and convey such a combined library under terms of your
-choice, if you do both of the following:
-
- a) Accompany the combined library with a copy of the same work based
- on the Library, uncombined with any other library facilities,
- conveyed under the terms of this License.
-
- b) Give prominent notice with the combined library that part of it
- is a work based on the Library, and explaining where to find the
- accompanying uncombined form of the same work.
-
- 6. Revised Versions of the GNU Lesser General Public License.
-
- The Free Software Foundation may publish revised and/or new versions
-of the GNU Lesser General Public License from time to time. Such new
-versions will be similar in spirit to the present version, but may
-differ in detail to address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Library as you received it specifies that a certain numbered version
-of the GNU Lesser General Public License "or any later version"
-applies to it, you have the option of following the terms and
-conditions either of that published version or of any later version
-published by the Free Software Foundation. If the Library as you
-received it does not specify a version number of the GNU Lesser
-General Public License, you may choose any version of the GNU Lesser
-General Public License ever published by the Free Software Foundation.
-
- If the Library as you received it specifies that a proxy can decide
-whether future versions of the GNU Lesser General Public License shall
-apply, that proxy's public statement of acceptance of any version is
-permanent authorization for you to choose that version for the
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/COPYING.README b/COPYING.README
index 1d706784d..de5b63215 100644
--- a/COPYING.README
+++ b/COPYING.README
@@ -5,6 +5,9 @@ Eigen is primarily MPL2 licensed. See COPYING.MPL2 and these links:
Some files contain third-party code under BSD or LGPL licenses, whence the other
COPYING.* files here.
+All the LGPL code is either LGPL 2.1-only, or LGPL 2.1-or-later.
+For this reason, the COPYING.LGPL file contains the LGPL 2.1 text.
+
If you want to guarantee that the Eigen code that you are #including is licensed
under the MPL2 and possibly more permissive licenses (like BSD), #define this
preprocessor symbol:
diff --git a/CTestConfig.cmake b/CTestConfig.cmake
index a5a4eb012..0557c491a 100644
--- a/CTestConfig.cmake
+++ b/CTestConfig.cmake
@@ -4,10 +4,10 @@
## # The following are required to uses Dart and the Cdash dashboard
## ENABLE_TESTING()
## INCLUDE(CTest)
-set(CTEST_PROJECT_NAME "Eigen")
+set(CTEST_PROJECT_NAME "Eigen3.2")
set(CTEST_NIGHTLY_START_TIME "00:00:00 UTC")
set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "manao.inria.fr")
-set(CTEST_DROP_LOCATION "/CDash/submit.php?project=Eigen")
+set(CTEST_DROP_LOCATION "/CDash/submit.php?project=Eigen3.2")
set(CTEST_DROP_SITE_CDASH TRUE)
diff --git a/CTestCustom.cmake.in b/CTestCustom.cmake.in
index 3b2bacaa0..9fed9d327 100644
--- a/CTestCustom.cmake.in
+++ b/CTestCustom.cmake.in
@@ -1,4 +1,3 @@
-## A tribute to Dynamic!
-set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS "33331")
-set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS "33331")
+set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS "2000")
+set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS "2000")
diff --git a/Eigen/Core b/Eigen/Core
index d48017022..c87f99df3 100644
--- a/Eigen/Core
+++ b/Eigen/Core
@@ -19,6 +19,12 @@
// defined e.g. EIGEN_DONT_ALIGN) so it needs to be done before we do anything with vectorization.
#include "src/Core/util/Macros.h"
+// Disable the ipa-cp-clone optimization flag with MinGW 6.x or newer (enabled by default with -O3)
+// See http://eigen.tuxfamily.org/bz/show_bug.cgi?id=556 for details.
+#if defined(__MINGW32__) && EIGEN_GNUC_AT_LEAST(4,6)
+ #pragma GCC optimize ("-fno-ipa-cp-clone")
+#endif
+
#include <complex>
// this include file manages BLAS and MKL related macros
@@ -44,7 +50,7 @@
#endif
#else
// Remember that usage of defined() in a #define is undefined by the standard
- #if (defined __SSE2__) && ( (!defined __GNUC__) || EIGEN_GNUC_AT_LEAST(4,2) )
+ #if (defined __SSE2__) && ( (!defined __GNUC__) || (defined __INTEL_COMPILER) || EIGEN_GNUC_AT_LEAST(4,2) )
#define EIGEN_SSE2_ON_NON_MSVC_BUT_NOT_OLD_GCC
#endif
#endif
@@ -87,19 +93,25 @@
// so, to avoid compile errors when windows.h is included after Eigen/Core, ensure intrinsics are extern "C" here too.
// notice that since these are C headers, the extern "C" is theoretically needed anyways.
extern "C" {
- #include <emmintrin.h>
- #include <xmmintrin.h>
- #ifdef EIGEN_VECTORIZE_SSE3
- #include <pmmintrin.h>
- #endif
- #ifdef EIGEN_VECTORIZE_SSSE3
- #include <tmmintrin.h>
- #endif
- #ifdef EIGEN_VECTORIZE_SSE4_1
- #include <smmintrin.h>
- #endif
- #ifdef EIGEN_VECTORIZE_SSE4_2
- #include <nmmintrin.h>
+ // In theory we should only include immintrin.h and not the other *mmintrin.h header files directly.
+ // Doing so triggers some issues with ICC. However old gcc versions seems to not have this file, thus:
+ #if defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1110
+ #include <immintrin.h>
+ #else
+ #include <emmintrin.h>
+ #include <xmmintrin.h>
+ #ifdef EIGEN_VECTORIZE_SSE3
+ #include <pmmintrin.h>
+ #endif
+ #ifdef EIGEN_VECTORIZE_SSSE3
+ #include <tmmintrin.h>
+ #endif
+ #ifdef EIGEN_VECTORIZE_SSE4_1
+ #include <smmintrin.h>
+ #endif
+ #ifdef EIGEN_VECTORIZE_SSE4_2
+ #include <nmmintrin.h>
+ #endif
#endif
} // end extern "C"
#elif defined __ALTIVEC__
@@ -153,7 +165,7 @@
#endif
// required for __cpuid, needs to be included after cmath
-#if defined(_MSC_VER) && (defined(_M_IX86)||defined(_M_X64))
+#if defined(_MSC_VER) && (defined(_M_IX86)||defined(_M_X64)) && (!defined(_WIN32_WCE))
#include <intrin.h>
#endif
@@ -236,15 +248,11 @@ using std::ptrdiff_t;
* \endcode
*/
-/** \defgroup Support_modules Support modules [category]
- * Category of modules which add support for external libraries.
- */
-
#include "src/Core/util/Constants.h"
#include "src/Core/util/ForwardDeclarations.h"
#include "src/Core/util/Meta.h"
-#include "src/Core/util/XprHelper.h"
#include "src/Core/util/StaticAssert.h"
+#include "src/Core/util/XprHelper.h"
#include "src/Core/util/Memory.h"
#include "src/Core/NumTraits.h"
@@ -297,6 +305,7 @@ using std::ptrdiff_t;
#include "src/Core/Map.h"
#include "src/Core/Block.h"
#include "src/Core/VectorBlock.h"
+#include "src/Core/Ref.h"
#include "src/Core/Transpose.h"
#include "src/Core/DiagonalMatrix.h"
#include "src/Core/Diagonal.h"
@@ -330,6 +339,7 @@ using std::ptrdiff_t;
#include "src/Core/products/TriangularSolverMatrix.h"
#include "src/Core/products/TriangularSolverVector.h"
#include "src/Core/BandMatrix.h"
+#include "src/Core/CoreIterators.h"
#include "src/Core/BooleanRedux.h"
#include "src/Core/Select.h"
diff --git a/Eigen/Eigen2Support b/Eigen/Eigen2Support
index 36156d29a..6aa009d20 100644
--- a/Eigen/Eigen2Support
+++ b/Eigen/Eigen2Support
@@ -14,12 +14,25 @@
#error Eigen2 support must be enabled by defining EIGEN2_SUPPORT before including any Eigen header
#endif
+#ifndef EIGEN_NO_EIGEN2_DEPRECATED_WARNING
+
+#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
+#warning "Eigen2 support is deprecated in Eigen 3.2.x and it will be removed in Eigen 3.3. (Define EIGEN_NO_EIGEN2_DEPRECATED_WARNING to disable this warning)"
+#else
+#pragma message ("Eigen2 support is deprecated in Eigen 3.2.x and it will be removed in Eigen 3.3. (Define EIGEN_NO_EIGEN2_DEPRECATED_WARNING to disable this warning)")
+#endif
+
+#endif // EIGEN_NO_EIGEN2_DEPRECATED_WARNING
+
#include "src/Core/util/DisableStupidWarnings.h"
/** \ingroup Support_modules
* \defgroup Eigen2Support_Module Eigen2 support module
- * This module provides a couple of deprecated functions improving the compatibility with Eigen2.
*
+ * \warning Eigen2 support is deprecated in Eigen 3.2.x and it will be removed in Eigen 3.3.
+ *
+ * This module provides a couple of deprecated functions improving the compatibility with Eigen2.
+ *
* To use it, define EIGEN2_SUPPORT before including any Eigen header
* \code
* #define EIGEN2_SUPPORT
diff --git a/Eigen/Eigenvalues b/Eigen/Eigenvalues
index af99ccd1f..53c5a73a2 100644
--- a/Eigen/Eigenvalues
+++ b/Eigen/Eigenvalues
@@ -33,6 +33,8 @@
#include "src/Eigenvalues/HessenbergDecomposition.h"
#include "src/Eigenvalues/ComplexSchur.h"
#include "src/Eigenvalues/ComplexEigenSolver.h"
+#include "src/Eigenvalues/RealQZ.h"
+#include "src/Eigenvalues/GeneralizedEigenSolver.h"
#include "src/Eigenvalues/MatrixBaseEigenvalues.h"
#ifdef EIGEN_USE_LAPACKE
#include "src/Eigenvalues/RealSchur_MKL.h"
diff --git a/Eigen/IterativeLinearSolvers b/Eigen/IterativeLinearSolvers
index 315c2dd1e..0f4159dc1 100644
--- a/Eigen/IterativeLinearSolvers
+++ b/Eigen/IterativeLinearSolvers
@@ -6,7 +6,7 @@
#include "src/Core/util/DisableStupidWarnings.h"
-/** \ingroup Sparse_modules
+/**
* \defgroup IterativeLinearSolvers_Module IterativeLinearSolvers module
*
* This module currently provides iterative methods to solve problems of the form \c A \c x = \c b, where \c A is a squared matrix, usually very large and sparse.
diff --git a/Eigen/MetisSupport b/Eigen/MetisSupport
new file mode 100644
index 000000000..6a113f7a8
--- /dev/null
+++ b/Eigen/MetisSupport
@@ -0,0 +1,28 @@
+#ifndef EIGEN_METISSUPPORT_MODULE_H
+#define EIGEN_METISSUPPORT_MODULE_H
+
+#include "SparseCore"
+
+#include "src/Core/util/DisableStupidWarnings.h"
+
+extern "C" {
+#include <metis.h>
+}
+
+
+/** \ingroup Support_modules
+ * \defgroup MetisSupport_Module MetisSupport module
+ *
+ * \code
+ * #include <Eigen/MetisSupport>
+ * \endcode
+ * This module defines an interface to the METIS reordering package (http://glaros.dtc.umn.edu/gkhome/views/metis).
+ * It can be used just as any other built-in method as explained in \link OrderingMethods_Module here. \endlink
+ */
+
+
+#include "src/MetisSupport/MetisSupport.h"
+
+#include "src/Core/util/ReenableStupidWarnings.h"
+
+#endif // EIGEN_METISSUPPORT_MODULE_H
diff --git a/Eigen/OrderingMethods b/Eigen/OrderingMethods
index 1e2d87452..7c0f1ffff 100644
--- a/Eigen/OrderingMethods
+++ b/Eigen/OrderingMethods
@@ -5,19 +5,62 @@
#include "src/Core/util/DisableStupidWarnings.h"
-/** \ingroup Sparse_modules
+/**
* \defgroup OrderingMethods_Module OrderingMethods module
*
- * This module is currently for internal use only.
- *
- *
+ * This module is currently for internal use only
+ *
+ * It defines various built-in and external ordering methods for sparse matrices.
+ * They are typically used to reduce the number of elements during
+ * the sparse matrix decomposition (LLT, LU, QR).
+ * Precisely, in a preprocessing step, a permutation matrix P is computed using
+ * those ordering methods and applied to the columns of the matrix.
+ * Using for instance the sparse Cholesky decomposition, it is expected that
+ * the nonzeros elements in LLT(A*P) will be much smaller than that in LLT(A).
+ *
+ *
+ * Usage :
* \code
* #include <Eigen/OrderingMethods>
* \endcode
+ *
+ * A simple usage is as a template parameter in the sparse decomposition classes :
+ *
+ * \code
+ * SparseLU<MatrixType, COLAMDOrdering<int> > solver;
+ * \endcode
+ *
+ * \code
+ * SparseQR<MatrixType, COLAMDOrdering<int> > solver;
+ * \endcode
+ *
+ * It is possible as well to call directly a particular ordering method for your own purpose,
+ * \code
+ * AMDOrdering<int> ordering;
+ * PermutationMatrix<Dynamic, Dynamic, int> perm;
+ * SparseMatrix<double> A;
+ * //Fill the matrix ...
+ *
+ * ordering(A, perm); // Call AMD
+ * \endcode
+ *
+ * \note Some of these methods (like AMD or METIS), need the sparsity pattern
+ * of the input matrix to be symmetric. When the matrix is structurally unsymmetric,
+ * Eigen computes internally the pattern of \f$A^T*A\f$ before calling the method.
+ * If your matrix is already symmetric (at leat in structure), you can avoid that
+ * by calling the method with a SelfAdjointView type.
+ *
+ * \code
+ * // Call the ordering on the pattern of the lower triangular matrix A
+ * ordering(A.selfadjointView<Lower>(), perm);
+ * \endcode
*/
+#ifndef EIGEN_MPL2_ONLY
#include "src/OrderingMethods/Amd.h"
+#endif
+#include "src/OrderingMethods/Ordering.h"
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_ORDERINGMETHODS_MODULE_H
diff --git a/Eigen/SPQRSupport b/Eigen/SPQRSupport
new file mode 100644
index 000000000..77016442e
--- /dev/null
+++ b/Eigen/SPQRSupport
@@ -0,0 +1,29 @@
+#ifndef EIGEN_SPQRSUPPORT_MODULE_H
+#define EIGEN_SPQRSUPPORT_MODULE_H
+
+#include "SparseCore"
+
+#include "src/Core/util/DisableStupidWarnings.h"
+
+#include "SuiteSparseQR.hpp"
+
+/** \ingroup Support_modules
+ * \defgroup SPQRSupport_Module SuiteSparseQR module
+ *
+ * This module provides an interface to the SPQR library, which is part of the <a href="http://www.cise.ufl.edu/research/sparse/SuiteSparse/">suitesparse</a> package.
+ *
+ * \code
+ * #include <Eigen/SPQRSupport>
+ * \endcode
+ *
+ * In order to use this module, the SPQR headers must be accessible from the include paths, and your binary must be linked to the SPQR library and its dependencies (Cholmod, AMD, COLAMD,...).
+ * For a cmake based project, you can use our FindSPQR.cmake and FindCholmod.Cmake modules
+ *
+ */
+
+#include "src/misc/Solve.h"
+#include "src/misc/SparseSolve.h"
+#include "src/CholmodSupport/CholmodSupport.h"
+#include "src/SPQRSupport/SuiteSparseQRSupport.h"
+
+#endif
diff --git a/Eigen/Sparse b/Eigen/Sparse
index 2d1757172..7cc9c0913 100644
--- a/Eigen/Sparse
+++ b/Eigen/Sparse
@@ -1,13 +1,15 @@
#ifndef EIGEN_SPARSE_MODULE_H
#define EIGEN_SPARSE_MODULE_H
-/** \defgroup Sparse_modules Sparse modules
+/** \defgroup Sparse_Module Sparse meta-module
*
* Meta-module including all related modules:
- * - SparseCore
- * - OrderingMethods
- * - SparseCholesky
- * - IterativeLinearSolvers
+ * - \ref SparseCore_Module
+ * - \ref OrderingMethods_Module
+ * - \ref SparseCholesky_Module
+ * - \ref SparseLU_Module
+ * - \ref SparseQR_Module
+ * - \ref IterativeLinearSolvers_Module
*
* \code
* #include <Eigen/Sparse>
@@ -17,6 +19,8 @@
#include "SparseCore"
#include "OrderingMethods"
#include "SparseCholesky"
+#include "SparseLU"
+#include "SparseQR"
#include "IterativeLinearSolvers"
#endif // EIGEN_SPARSE_MODULE_H
diff --git a/Eigen/SparseCholesky b/Eigen/SparseCholesky
index 5f82742f7..9f5056aa1 100644
--- a/Eigen/SparseCholesky
+++ b/Eigen/SparseCholesky
@@ -1,11 +1,21 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2013 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
#ifndef EIGEN_SPARSECHOLESKY_MODULE_H
#define EIGEN_SPARSECHOLESKY_MODULE_H
#include "SparseCore"
+#include "OrderingMethods"
#include "src/Core/util/DisableStupidWarnings.h"
-/** \ingroup Sparse_modules
+/**
* \defgroup SparseCholesky_Module SparseCholesky module
*
* This module currently provides two variants of the direct sparse Cholesky decomposition for selfadjoint (hermitian) matrices.
@@ -20,11 +30,18 @@
* \endcode
*/
+#ifdef EIGEN_MPL2_ONLY
+#error The SparseCholesky module has nothing to offer in MPL2 only mode
+#endif
+
#include "src/misc/Solve.h"
#include "src/misc/SparseSolve.h"
-
#include "src/SparseCholesky/SimplicialCholesky.h"
+#ifndef EIGEN_MPL2_ONLY
+#include "src/SparseCholesky/SimplicialCholesky_impl.h"
+#endif
+
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_SPARSECHOLESKY_MODULE_H
diff --git a/Eigen/SparseCore b/Eigen/SparseCore
index 41d28c928..9b5be5e15 100644
--- a/Eigen/SparseCore
+++ b/Eigen/SparseCore
@@ -11,7 +11,7 @@
#include <cstring>
#include <algorithm>
-/** \ingroup Sparse_modules
+/**
* \defgroup SparseCore_Module SparseCore module
*
* This module provides a sparse matrix representation, and basic associatd matrix manipulations
@@ -40,14 +40,12 @@ struct Sparse {};
#include "src/SparseCore/SparseMatrix.h"
#include "src/SparseCore/MappedSparseMatrix.h"
#include "src/SparseCore/SparseVector.h"
-#include "src/SparseCore/CoreIterators.h"
#include "src/SparseCore/SparseBlock.h"
#include "src/SparseCore/SparseTranspose.h"
#include "src/SparseCore/SparseCwiseUnaryOp.h"
#include "src/SparseCore/SparseCwiseBinaryOp.h"
#include "src/SparseCore/SparseDot.h"
#include "src/SparseCore/SparsePermutation.h"
-#include "src/SparseCore/SparseAssign.h"
#include "src/SparseCore/SparseRedux.h"
#include "src/SparseCore/SparseFuzzy.h"
#include "src/SparseCore/ConservativeSparseSparseProduct.h"
diff --git a/Eigen/SparseLU b/Eigen/SparseLU
new file mode 100644
index 000000000..8527a49bd
--- /dev/null
+++ b/Eigen/SparseLU
@@ -0,0 +1,49 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+// Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef EIGEN_SPARSELU_MODULE_H
+#define EIGEN_SPARSELU_MODULE_H
+
+#include "SparseCore"
+
+/**
+ * \defgroup SparseLU_Module SparseLU module
+ * This module defines a supernodal factorization of general sparse matrices.
+ * The code is fully optimized for supernode-panel updates with specialized kernels.
+ * Please, see the documentation of the SparseLU class for more details.
+ */
+
+#include "src/misc/Solve.h"
+#include "src/misc/SparseSolve.h"
+
+// Ordering interface
+#include "OrderingMethods"
+
+#include "src/SparseLU/SparseLU_gemm_kernel.h"
+
+#include "src/SparseLU/SparseLU_Structs.h"
+#include "src/SparseLU/SparseLU_SupernodalMatrix.h"
+#include "src/SparseLU/SparseLUImpl.h"
+#include "src/SparseCore/SparseColEtree.h"
+#include "src/SparseLU/SparseLU_Memory.h"
+#include "src/SparseLU/SparseLU_heap_relax_snode.h"
+#include "src/SparseLU/SparseLU_relax_snode.h"
+#include "src/SparseLU/SparseLU_pivotL.h"
+#include "src/SparseLU/SparseLU_panel_dfs.h"
+#include "src/SparseLU/SparseLU_kernel_bmod.h"
+#include "src/SparseLU/SparseLU_panel_bmod.h"
+#include "src/SparseLU/SparseLU_column_dfs.h"
+#include "src/SparseLU/SparseLU_column_bmod.h"
+#include "src/SparseLU/SparseLU_copy_to_ucol.h"
+#include "src/SparseLU/SparseLU_pruneL.h"
+#include "src/SparseLU/SparseLU_Utils.h"
+#include "src/SparseLU/SparseLU.h"
+
+#endif // EIGEN_SPARSELU_MODULE_H
diff --git a/Eigen/SparseQR b/Eigen/SparseQR
new file mode 100644
index 000000000..4ee42065e
--- /dev/null
+++ b/Eigen/SparseQR
@@ -0,0 +1,33 @@
+#ifndef EIGEN_SPARSEQR_MODULE_H
+#define EIGEN_SPARSEQR_MODULE_H
+
+#include "SparseCore"
+#include "OrderingMethods"
+#include "src/Core/util/DisableStupidWarnings.h"
+
+/** \defgroup SparseQR_Module SparseQR module
+ * \brief Provides QR decomposition for sparse matrices
+ *
+ * This module provides a simplicial version of the left-looking Sparse QR decomposition.
+ * The columns of the input matrix should be reordered to limit the fill-in during the
+ * decomposition. Built-in methods (COLAMD, AMD) or external methods (METIS) can be used to this end.
+ * See the \link OrderingMethods_Module OrderingMethods\endlink module for the list
+ * of built-in and external ordering methods.
+ *
+ * \code
+ * #include <Eigen/SparseQR>
+ * \endcode
+ *
+ *
+ */
+
+#include "src/misc/Solve.h"
+#include "src/misc/SparseSolve.h"
+
+#include "OrderingMethods"
+#include "src/SparseCore/SparseColEtree.h"
+#include "src/SparseQR/SparseQR.h"
+
+#include "src/Core/util/ReenableStupidWarnings.h"
+
+#endif
diff --git a/Eigen/src/Cholesky/LDLT.h b/Eigen/src/Cholesky/LDLT.h
index 68e54b1d4..c52b7d1a6 100644
--- a/Eigen/src/Cholesky/LDLT.h
+++ b/Eigen/src/Cholesky/LDLT.h
@@ -16,7 +16,10 @@
namespace Eigen {
namespace internal {
-template<typename MatrixType, int UpLo> struct LDLT_Traits;
+ template<typename MatrixType, int UpLo> struct LDLT_Traits;
+
+ // PositiveSemiDef means positive semi-definite and non-zero; same for NegativeSemiDef
+ enum SignMatrix { PositiveSemiDef, NegativeSemiDef, ZeroSign, Indefinite };
}
/** \ingroup Cholesky_Module
@@ -69,7 +72,12 @@ template<typename _MatrixType, int _UpLo> class LDLT
* The default constructor is useful in cases in which the user intends to
* perform decompositions via LDLT::compute(const MatrixType&).
*/
- LDLT() : m_matrix(), m_transpositions(), m_isInitialized(false) {}
+ LDLT()
+ : m_matrix(),
+ m_transpositions(),
+ m_sign(internal::ZeroSign),
+ m_isInitialized(false)
+ {}
/** \brief Default Constructor with memory preallocation
*
@@ -81,6 +89,7 @@ template<typename _MatrixType, int _UpLo> class LDLT
: m_matrix(size, size),
m_transpositions(size),
m_temporary(size),
+ m_sign(internal::ZeroSign),
m_isInitialized(false)
{}
@@ -93,6 +102,7 @@ template<typename _MatrixType, int _UpLo> class LDLT
: m_matrix(matrix.rows(), matrix.cols()),
m_transpositions(matrix.rows()),
m_temporary(matrix.rows()),
+ m_sign(internal::ZeroSign),
m_isInitialized(false)
{
compute(matrix);
@@ -139,7 +149,7 @@ template<typename _MatrixType, int _UpLo> class LDLT
inline bool isPositive() const
{
eigen_assert(m_isInitialized && "LDLT is not initialized.");
- return m_sign == 1;
+ return m_sign == internal::PositiveSemiDef || m_sign == internal::ZeroSign;
}
#ifdef EIGEN2_SUPPORT
@@ -153,7 +163,7 @@ template<typename _MatrixType, int _UpLo> class LDLT
inline bool isNegative(void) const
{
eigen_assert(m_isInitialized && "LDLT is not initialized.");
- return m_sign == -1;
+ return m_sign == internal::NegativeSemiDef || m_sign == internal::ZeroSign;
}
/** \returns a solution x of \f$ A x = b \f$ using the current decomposition of A.
@@ -196,7 +206,7 @@ template<typename _MatrixType, int _UpLo> class LDLT
LDLT& compute(const MatrixType& matrix);
template <typename Derived>
- LDLT& rankUpdate(const MatrixBase<Derived>& w,RealScalar alpha=1);
+ LDLT& rankUpdate(const MatrixBase<Derived>& w, const RealScalar& alpha=1);
/** \returns the internal LDLT decomposition matrix
*
@@ -235,7 +245,7 @@ template<typename _MatrixType, int _UpLo> class LDLT
MatrixType m_matrix;
TranspositionType m_transpositions;
TmpMatrixType m_temporary;
- int m_sign;
+ internal::SignMatrix m_sign;
bool m_isInitialized;
};
@@ -246,8 +256,9 @@ template<int UpLo> struct ldlt_inplace;
template<> struct ldlt_inplace<Lower>
{
template<typename MatrixType, typename TranspositionType, typename Workspace>
- static bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, int* sign=0)
+ static bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, SignMatrix& sign)
{
+ using std::abs;
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
typedef typename MatrixType::Index Index;
@@ -257,38 +268,19 @@ template<> struct ldlt_inplace<Lower>
if (size <= 1)
{
transpositions.setIdentity();
- if(sign)
- *sign = real(mat.coeff(0,0))>0 ? 1:-1;
+ if (numext::real(mat.coeff(0,0)) > 0) sign = PositiveSemiDef;
+ else if (numext::real(mat.coeff(0,0)) < 0) sign = NegativeSemiDef;
+ else sign = ZeroSign;
return true;
}
- RealScalar cutoff(0), biggest_in_corner;
-
for (Index k = 0; k < size; ++k)
{
// Find largest diagonal element
Index index_of_biggest_in_corner;
- biggest_in_corner = mat.diagonal().tail(size-k).cwiseAbs().maxCoeff(&index_of_biggest_in_corner);
+ mat.diagonal().tail(size-k).cwiseAbs().maxCoeff(&index_of_biggest_in_corner);
index_of_biggest_in_corner += k;
- if(k == 0)
- {
- // The biggest overall is the point of reference to which further diagonals
- // are compared; if any diagonal is negligible compared
- // to the largest overall, the algorithm bails.
- cutoff = abs(NumTraits<Scalar>::epsilon() * biggest_in_corner);
-
- if(sign)
- *sign = real(mat.diagonal().coeff(index_of_biggest_in_corner)) > 0 ? 1 : -1;
- }
-
- // Finish early if the matrix is not full rank.
- if(biggest_in_corner < cutoff)
- {
- for(Index i = k; i < size; i++) transpositions.coeffRef(i) = i;
- break;
- }
-
transpositions.coeffRef(k) = index_of_biggest_in_corner;
if(k != index_of_biggest_in_corner)
{
@@ -301,11 +293,11 @@ template<> struct ldlt_inplace<Lower>
for(int i=k+1;i<index_of_biggest_in_corner;++i)
{
Scalar tmp = mat.coeffRef(i,k);
- mat.coeffRef(i,k) = conj(mat.coeffRef(index_of_biggest_in_corner,i));
- mat.coeffRef(index_of_biggest_in_corner,i) = conj(tmp);
+ mat.coeffRef(i,k) = numext::conj(mat.coeffRef(index_of_biggest_in_corner,i));
+ mat.coeffRef(index_of_biggest_in_corner,i) = numext::conj(tmp);
}
if(NumTraits<Scalar>::IsComplex)
- mat.coeffRef(index_of_biggest_in_corner,k) = conj(mat.coeff(index_of_biggest_in_corner,k));
+ mat.coeffRef(index_of_biggest_in_corner,k) = numext::conj(mat.coeff(index_of_biggest_in_corner,k));
}
// partition the matrix:
@@ -319,13 +311,28 @@ template<> struct ldlt_inplace<Lower>
if(k>0)
{
- temp.head(k) = mat.diagonal().head(k).asDiagonal() * A10.adjoint();
+ temp.head(k) = mat.diagonal().real().head(k).asDiagonal() * A10.adjoint();
mat.coeffRef(k,k) -= (A10 * temp.head(k)).value();
if(rs>0)
A21.noalias() -= A20 * temp.head(k);
}
- if((rs>0) && (abs(mat.coeffRef(k,k)) > cutoff))
- A21 /= mat.coeffRef(k,k);
+
+ // In some previous versions of Eigen (e.g., 3.2.1), the scaling was omitted if the pivot
+ // was smaller than the cutoff value. However, soince LDLT is not rank-revealing
+ // we should only make sure we do not introduce INF or NaN values.
+ // LAPACK also uses 0 as the cutoff value.
+ RealScalar realAkk = numext::real(mat.coeffRef(k,k));
+ if((rs>0) && (abs(realAkk) > RealScalar(0)))
+ A21 /= realAkk;
+
+ if (sign == PositiveSemiDef) {
+ if (realAkk < 0) sign = Indefinite;
+ } else if (sign == NegativeSemiDef) {
+ if (realAkk > 0) sign = Indefinite;
+ } else if (sign == ZeroSign) {
+ if (realAkk > 0) sign = PositiveSemiDef;
+ else if (realAkk < 0) sign = NegativeSemiDef;
+ }
}
return true;
@@ -339,9 +346,9 @@ template<> struct ldlt_inplace<Lower>
// Here only rank-1 updates are implemented, to reduce the
// requirement for intermediate storage and improve accuracy
template<typename MatrixType, typename WDerived>
- static bool updateInPlace(MatrixType& mat, MatrixBase<WDerived>& w, typename MatrixType::RealScalar sigma=1)
+ static bool updateInPlace(MatrixType& mat, MatrixBase<WDerived>& w, const typename MatrixType::RealScalar& sigma=1)
{
- using internal::isfinite;
+ using numext::isfinite;
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
typedef typename MatrixType::Index Index;
@@ -359,9 +366,9 @@ template<> struct ldlt_inplace<Lower>
break;
// Update the diagonal terms
- RealScalar dj = real(mat.coeff(j,j));
+ RealScalar dj = numext::real(mat.coeff(j,j));
Scalar wj = w.coeff(j);
- RealScalar swj2 = sigma*abs2(wj);
+ RealScalar swj2 = sigma*numext::abs2(wj);
RealScalar gamma = dj*alpha + swj2;
mat.coeffRef(j,j) += swj2/alpha;
@@ -372,13 +379,13 @@ template<> struct ldlt_inplace<Lower>
Index rs = size-j-1;
w.tail(rs) -= wj * mat.col(j).tail(rs);
if(gamma != 0)
- mat.col(j).tail(rs) += (sigma*conj(wj)/gamma)*w.tail(rs);
+ mat.col(j).tail(rs) += (sigma*numext::conj(wj)/gamma)*w.tail(rs);
}
return true;
}
template<typename MatrixType, typename TranspositionType, typename Workspace, typename WType>
- static bool update(MatrixType& mat, const TranspositionType& transpositions, Workspace& tmp, const WType& w, typename MatrixType::RealScalar sigma=1)
+ static bool update(MatrixType& mat, const TranspositionType& transpositions, Workspace& tmp, const WType& w, const typename MatrixType::RealScalar& sigma=1)
{
// Apply the permutation to the input w
tmp = transpositions * w;
@@ -390,14 +397,14 @@ template<> struct ldlt_inplace<Lower>
template<> struct ldlt_inplace<Upper>
{
template<typename MatrixType, typename TranspositionType, typename Workspace>
- static EIGEN_STRONG_INLINE bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, int* sign=0)
+ static EIGEN_STRONG_INLINE bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, SignMatrix& sign)
{
Transpose<MatrixType> matt(mat);
return ldlt_inplace<Lower>::unblocked(matt, transpositions, temp, sign);
}
template<typename MatrixType, typename TranspositionType, typename Workspace, typename WType>
- static EIGEN_STRONG_INLINE bool update(MatrixType& mat, TranspositionType& transpositions, Workspace& tmp, WType& w, typename MatrixType::RealScalar sigma=1)
+ static EIGEN_STRONG_INLINE bool update(MatrixType& mat, TranspositionType& transpositions, Workspace& tmp, WType& w, const typename MatrixType::RealScalar& sigma=1)
{
Transpose<MatrixType> matt(mat);
return ldlt_inplace<Lower>::update(matt, transpositions, tmp, w.conjugate(), sigma);
@@ -436,7 +443,7 @@ LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::compute(const MatrixType& a)
m_isInitialized = false;
m_temporary.resize(size);
- internal::ldlt_inplace<UpLo>::unblocked(m_matrix, m_transpositions, m_temporary, &m_sign);
+ internal::ldlt_inplace<UpLo>::unblocked(m_matrix, m_transpositions, m_temporary, m_sign);
m_isInitialized = true;
return *this;
@@ -449,7 +456,7 @@ LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::compute(const MatrixType& a)
*/
template<typename MatrixType, int _UpLo>
template<typename Derived>
-LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::rankUpdate(const MatrixBase<Derived>& w,typename NumTraits<typename MatrixType::Scalar>::Real sigma)
+LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::rankUpdate(const MatrixBase<Derived>& w, const typename NumTraits<typename MatrixType::Scalar>::Real& sigma)
{
const Index size = w.rows();
if (m_isInitialized)
@@ -464,7 +471,7 @@ LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::rankUpdate(const MatrixBase<Deri
for (Index i = 0; i < size; i++)
m_transpositions.coeffRef(i) = i;
m_temporary.resize(size);
- m_sign = sigma>=0 ? 1 : -1;
+ m_sign = sigma>=0 ? internal::PositiveSemiDef : internal::NegativeSemiDef;
m_isInitialized = true;
}
@@ -497,14 +504,20 @@ struct solve_retval<LDLT<_MatrixType,_UpLo>, Rhs>
typedef typename LDLTType::MatrixType MatrixType;
typedef typename LDLTType::Scalar Scalar;
typedef typename LDLTType::RealScalar RealScalar;
- const Diagonal<const MatrixType> vectorD = dec().vectorD();
- RealScalar tolerance = (max)(vectorD.array().abs().maxCoeff() * NumTraits<Scalar>::epsilon(),
- RealScalar(1) / NumTraits<RealScalar>::highest()); // motivated by LAPACK's xGELSS
+ const typename Diagonal<const MatrixType>::RealReturnType vectorD(dec().vectorD());
+ // In some previous versions, tolerance was set to the max of 1/highest and the maximal diagonal entry * epsilon
+ // as motivated by LAPACK's xGELSS:
+ // RealScalar tolerance = (max)(vectorD.array().abs().maxCoeff() *NumTraits<RealScalar>::epsilon(),RealScalar(1) / NumTraits<RealScalar>::highest());
+ // However, LDLT is not rank revealing, and so adjusting the tolerance wrt to the highest
+ // diagonal element is not well justified and to numerical issues in some cases.
+ // Moreover, Lapack's xSYTRS routines use 0 for the tolerance.
+ RealScalar tolerance = RealScalar(1) / NumTraits<RealScalar>::highest();
+
for (Index i = 0; i < vectorD.size(); ++i) {
if(abs(vectorD(i)) > tolerance)
- dst.row(i) /= vectorD(i);
+ dst.row(i) /= vectorD(i);
else
- dst.row(i).setZero();
+ dst.row(i).setZero();
}
// dst = L^-T (D^-1 L^-1 P b)
@@ -534,8 +547,7 @@ template<typename Derived>
bool LDLT<MatrixType,_UpLo>::solveInPlace(MatrixBase<Derived> &bAndX) const
{
eigen_assert(m_isInitialized && "LDLT is not initialized.");
- const Index size = m_matrix.rows();
- eigen_assert(size == bAndX.rows());
+ eigen_assert(m_matrix.rows() == bAndX.rows());
bAndX = this->solve(bAndX);
@@ -558,7 +570,7 @@ MatrixType LDLT<MatrixType,_UpLo>::reconstructedMatrix() const
// L^* P
res = matrixU() * res;
// D(L^*P)
- res = vectorD().asDiagonal() * res;
+ res = vectorD().real().asDiagonal() * res;
// L(DL^*P)
res = matrixL() * res;
// P^T (LDL^*P)
diff --git a/Eigen/src/Cholesky/LLT.h b/Eigen/src/Cholesky/LLT.h
index 41d14e532..2e6189f7d 100644
--- a/Eigen/src/Cholesky/LLT.h
+++ b/Eigen/src/Cholesky/LLT.h
@@ -190,6 +190,7 @@ template<typename Scalar, int UpLo> struct llt_inplace;
template<typename MatrixType, typename VectorType>
static typename MatrixType::Index llt_rank_update_lower(MatrixType& mat, const VectorType& vec, const typename MatrixType::RealScalar& sigma)
{
+ using std::sqrt;
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
typedef typename MatrixType::Index Index;
@@ -199,7 +200,7 @@ static typename MatrixType::Index llt_rank_update_lower(MatrixType& mat, const V
typedef Matrix<Scalar,Dynamic,1> TempVectorType;
typedef typename TempVectorType::SegmentReturnType TempVecSegment;
- int n = mat.cols();
+ Index n = mat.cols();
eigen_assert(mat.rows()==n && vec.size()==n);
TempVectorType temp;
@@ -211,12 +212,12 @@ static typename MatrixType::Index llt_rank_update_lower(MatrixType& mat, const V
// i.e., for sigma > 0
temp = sqrt(sigma) * vec;
- for(int i=0; i<n; ++i)
+ for(Index i=0; i<n; ++i)
{
JacobiRotation<Scalar> g;
g.makeGivens(mat(i,i), -temp(i), &mat(i,i));
- int rs = n-i-1;
+ Index rs = n-i-1;
if(rs>0)
{
ColXprSegment x(mat.col(i).tail(rs));
@@ -229,12 +230,12 @@ static typename MatrixType::Index llt_rank_update_lower(MatrixType& mat, const V
{
temp = vec;
RealScalar beta = 1;
- for(int j=0; j<n; ++j)
+ for(Index j=0; j<n; ++j)
{
- RealScalar Ljj = real(mat.coeff(j,j));
- RealScalar dj = abs2(Ljj);
+ RealScalar Ljj = numext::real(mat.coeff(j,j));
+ RealScalar dj = numext::abs2(Ljj);
Scalar wj = temp.coeff(j);
- RealScalar swj2 = sigma*abs2(wj);
+ RealScalar swj2 = sigma*numext::abs2(wj);
RealScalar gamma = dj*beta + swj2;
RealScalar x = dj + swj2/beta;
@@ -250,7 +251,7 @@ static typename MatrixType::Index llt_rank_update_lower(MatrixType& mat, const V
{
temp.tail(rs) -= (wj/Ljj) * mat.col(j).tail(rs);
if(gamma != 0)
- mat.col(j).tail(rs) = (nLjj/Ljj) * mat.col(j).tail(rs) + (nLjj * sigma*conj(wj)/gamma)*temp.tail(rs);
+ mat.col(j).tail(rs) = (nLjj/Ljj) * mat.col(j).tail(rs) + (nLjj * sigma*numext::conj(wj)/gamma)*temp.tail(rs);
}
}
}
@@ -263,6 +264,7 @@ template<typename Scalar> struct llt_inplace<Scalar, Lower>
template<typename MatrixType>
static typename MatrixType::Index unblocked(MatrixType& mat)
{
+ using std::sqrt;
typedef typename MatrixType::Index Index;
eigen_assert(mat.rows()==mat.cols());
@@ -275,7 +277,7 @@ template<typename Scalar> struct llt_inplace<Scalar, Lower>
Block<MatrixType,1,Dynamic> A10(mat,k,0,1,k);
Block<MatrixType,Dynamic,Dynamic> A20(mat,k+1,0,rs,k);
- RealScalar x = real(mat.coeff(k,k));
+ RealScalar x = numext::real(mat.coeff(k,k));
if (k>0) x -= A10.squaredNorm();
if (x<=RealScalar(0))
return k;
diff --git a/Eigen/src/CholmodSupport/CholmodSupport.h b/Eigen/src/CholmodSupport/CholmodSupport.h
index 37f142150..c449960de 100644
--- a/Eigen/src/CholmodSupport/CholmodSupport.h
+++ b/Eigen/src/CholmodSupport/CholmodSupport.h
@@ -51,7 +51,6 @@ void cholmod_configure_matrix(CholmodType& mat)
template<typename _Scalar, int _Options, typename _Index>
cholmod_sparse viewAsCholmod(SparseMatrix<_Scalar,_Options,_Index>& mat)
{
- typedef SparseMatrix<_Scalar,_Options,_Index> MatrixType;
cholmod_sparse res;
res.nzmax = mat.nonZeros();
res.nrow = mat.rows();;
@@ -59,10 +58,12 @@ cholmod_sparse viewAsCholmod(SparseMatrix<_Scalar,_Options,_Index>& mat)
res.p = mat.outerIndexPtr();
res.i = mat.innerIndexPtr();
res.x = mat.valuePtr();
+ res.z = 0;
res.sorted = 1;
if(mat.isCompressed())
{
res.packed = 1;
+ res.nz = 0;
}
else
{
@@ -77,9 +78,13 @@ cholmod_sparse viewAsCholmod(SparseMatrix<_Scalar,_Options,_Index>& mat)
{
res.itype = CHOLMOD_INT;
}
+ else if (internal::is_same<_Index,UF_long>::value)
+ {
+ res.itype = CHOLMOD_LONG;
+ }
else
{
- eigen_assert(false && "Index type different than int is not supported yet");
+ eigen_assert(false && "Index type not supported yet");
}
// setup res.xtype
@@ -123,7 +128,7 @@ cholmod_dense viewAsCholmod(MatrixBase<Derived>& mat)
res.ncol = mat.cols();
res.nzmax = res.nrow * res.ncol;
res.d = Derived::IsVectorAtCompileTime ? mat.derived().size() : mat.derived().outerStride();
- res.x = mat.derived().data();
+ res.x = (void*)(mat.derived().data());
res.z = 0;
internal::cholmod_configure_matrix<Scalar>(res);
@@ -137,8 +142,8 @@ template<typename Scalar, int Flags, typename Index>
MappedSparseMatrix<Scalar,Flags,Index> viewAsEigen(cholmod_sparse& cm)
{
return MappedSparseMatrix<Scalar,Flags,Index>
- (cm.nrow, cm.ncol, reinterpret_cast<Index*>(cm.p)[cm.ncol],
- reinterpret_cast<Index*>(cm.p), reinterpret_cast<Index*>(cm.i),reinterpret_cast<Scalar*>(cm.x) );
+ (cm.nrow, cm.ncol, static_cast<Index*>(cm.p)[cm.ncol],
+ static_cast<Index*>(cm.p), static_cast<Index*>(cm.i),static_cast<Scalar*>(cm.x) );
}
enum CholmodMode {
@@ -167,12 +172,14 @@ class CholmodBase : internal::noncopyable
CholmodBase()
: m_cholmodFactor(0), m_info(Success), m_isInitialized(false)
{
+ m_shiftOffset[0] = m_shiftOffset[1] = RealScalar(0.0);
cholmod_start(&m_cholmod);
}
CholmodBase(const MatrixType& matrix)
: m_cholmodFactor(0), m_info(Success), m_isInitialized(false)
{
+ m_shiftOffset[0] = m_shiftOffset[1] = RealScalar(0.0);
cholmod_start(&m_cholmod);
compute(matrix);
}
@@ -237,7 +244,7 @@ class CholmodBase : internal::noncopyable
return internal::sparse_solve_retval<CholmodBase, Rhs>(*this, b.derived());
}
- /** Performs a symbolic decomposition on the sparcity of \a matrix.
+ /** Performs a symbolic decomposition on the sparsity pattern of \a matrix.
*
* This function is particularly useful when solving for several problems having the same structure.
*
@@ -261,7 +268,7 @@ class CholmodBase : internal::noncopyable
/** Performs a numeric decomposition of \a matrix
*
- * The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed.
+ * The given matrix must have the same sparsity pattern as the matrix on which the symbolic decomposition has been performed.
*
* \sa analyzePattern()
*/
@@ -269,9 +276,10 @@ class CholmodBase : internal::noncopyable
{
eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
- cholmod_factorize(&A, m_cholmodFactor, &m_cholmod);
+ cholmod_factorize_p(&A, m_shiftOffset, 0, 0, m_cholmodFactor, &m_cholmod);
- this->m_info = Success;
+ // If the factorization failed, minor is the column at which it did. On success minor == n.
+ this->m_info = (m_cholmodFactor->minor == m_cholmodFactor->n ? Success : NumericalIssue);
m_factorizationIsOk = true;
}
@@ -286,16 +294,18 @@ class CholmodBase : internal::noncopyable
{
eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
const Index size = m_cholmodFactor->n;
+ EIGEN_UNUSED_VARIABLE(size);
eigen_assert(size==b.rows());
// note: cd stands for Cholmod Dense
- cholmod_dense b_cd = viewAsCholmod(b.const_cast_derived());
+ Rhs& b_ref(b.const_cast_derived());
+ cholmod_dense b_cd = viewAsCholmod(b_ref);
cholmod_dense* x_cd = cholmod_solve(CHOLMOD_A, m_cholmodFactor, &b_cd, &m_cholmod);
if(!x_cd)
{
this->m_info = NumericalIssue;
}
- // TODO optimize this copy by swapping when possible (be carreful with alignment, etc.)
+ // TODO optimize this copy by swapping when possible (be careful with alignment, etc.)
dest = Matrix<Scalar,Dest::RowsAtCompileTime,Dest::ColsAtCompileTime>::Map(reinterpret_cast<Scalar*>(x_cd->x),b.rows(),b.cols());
cholmod_free_dense(&x_cd, &m_cholmod);
}
@@ -306,6 +316,7 @@ class CholmodBase : internal::noncopyable
{
eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
const Index size = m_cholmodFactor->n;
+ EIGEN_UNUSED_VARIABLE(size);
eigen_assert(size==b.rows());
// note: cs stands for Cholmod Sparse
@@ -315,19 +326,36 @@ class CholmodBase : internal::noncopyable
{
this->m_info = NumericalIssue;
}
- // TODO optimize this copy by swapping when possible (be carreful with alignment, etc.)
+ // TODO optimize this copy by swapping when possible (be careful with alignment, etc.)
dest = viewAsEigen<DestScalar,DestOptions,DestIndex>(*x_cs);
cholmod_free_sparse(&x_cs, &m_cholmod);
}
#endif // EIGEN_PARSED_BY_DOXYGEN
+
+ /** Sets the shift parameter that will be used to adjust the diagonal coefficients during the numerical factorization.
+ *
+ * During the numerical factorization, an offset term is added to the diagonal coefficients:\n
+ * \c d_ii = \a offset + \c d_ii
+ *
+ * The default is \a offset=0.
+ *
+ * \returns a reference to \c *this.
+ */
+ Derived& setShift(const RealScalar& offset)
+ {
+ m_shiftOffset[0] = offset;
+ return derived();
+ }
+
template<typename Stream>
- void dumpMemory(Stream& s)
+ void dumpMemory(Stream& /*s*/)
{}
protected:
mutable cholmod_common m_cholmod;
cholmod_factor* m_cholmodFactor;
+ RealScalar m_shiftOffset[2];
mutable ComputationInfo m_info;
bool m_isInitialized;
int m_factorizationIsOk;
@@ -340,8 +368,8 @@ class CholmodBase : internal::noncopyable
*
* This class allows to solve for A.X = B sparse linear problems via a simplicial LL^T Cholesky factorization
* using the Cholmod library.
- * This simplicial variant is equivalent to Eigen's built-in SimplicialLLT class. Thefore, it has little practical interest.
- * The sparse matrix A must be selfajoint and positive definite. The vectors or matrices
+ * This simplicial variant is equivalent to Eigen's built-in SimplicialLLT class. Therefore, it has little practical interest.
+ * The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices
* X and B can be either dense or sparse.
*
* \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
@@ -387,8 +415,8 @@ class CholmodSimplicialLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimpl
*
* This class allows to solve for A.X = B sparse linear problems via a simplicial LDL^T Cholesky factorization
* using the Cholmod library.
- * This simplicial variant is equivalent to Eigen's built-in SimplicialLDLT class. Thefore, it has little practical interest.
- * The sparse matrix A must be selfajoint and positive definite. The vectors or matrices
+ * This simplicial variant is equivalent to Eigen's built-in SimplicialLDLT class. Therefore, it has little practical interest.
+ * The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices
* X and B can be either dense or sparse.
*
* \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
@@ -433,7 +461,7 @@ class CholmodSimplicialLDLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimp
* This class allows to solve for A.X = B sparse linear problems via a supernodal LL^T Cholesky factorization
* using the Cholmod library.
* This supernodal variant performs best on dense enough problems, e.g., 3D FEM, or very high order 2D FEM.
- * The sparse matrix A must be selfajoint and positive definite. The vectors or matrices
+ * The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices
* X and B can be either dense or sparse.
*
* \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
@@ -476,7 +504,7 @@ class CholmodSupernodalLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSuper
* \brief A general Cholesky factorization and solver based on Cholmod
*
* This class allows to solve for A.X = B sparse linear problems via a LL^T or LDL^T Cholesky factorization
- * using the Cholmod library. The sparse matrix A must be selfajoint and positive definite. The vectors or matrices
+ * using the Cholmod library. The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices
* X and B can be either dense or sparse.
*
* This variant permits to change the underlying Cholesky method at runtime.
diff --git a/Eigen/src/Core/Array.h b/Eigen/src/Core/Array.h
index aaa389978..0ab03eff0 100644
--- a/Eigen/src/Core/Array.h
+++ b/Eigen/src/Core/Array.h
@@ -107,10 +107,10 @@ class Array
*
* \sa resize(Index,Index)
*/
- EIGEN_STRONG_INLINE explicit Array() : Base()
+ EIGEN_STRONG_INLINE Array() : Base()
{
Base::_check_template_params();
- EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
+ EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
}
#ifndef EIGEN_PARSED_BY_DOXYGEN
@@ -120,7 +120,7 @@ class Array
: Base(internal::constructor_without_unaligned_array_assert())
{
Base::_check_template_params();
- EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
+ EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
}
#endif
@@ -137,15 +137,15 @@ class Array
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Array)
eigen_assert(dim >= 0);
eigen_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == dim);
- EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
+ EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
}
#ifndef EIGEN_PARSED_BY_DOXYGEN
template<typename T0, typename T1>
- EIGEN_STRONG_INLINE Array(const T0& x, const T1& y)
+ EIGEN_STRONG_INLINE Array(const T0& val0, const T1& val1)
{
Base::_check_template_params();
- this->template _init2<T0,T1>(x, y);
+ this->template _init2<T0,T1>(val0, val1);
}
#else
/** constructs an uninitialized matrix with \a rows rows and \a cols columns.
@@ -155,27 +155,27 @@ class Array
* Matrix() instead. */
Array(Index rows, Index cols);
/** constructs an initialized 2D vector with given coefficients */
- Array(const Scalar& x, const Scalar& y);
+ Array(const Scalar& val0, const Scalar& val1);
#endif
/** constructs an initialized 3D vector with given coefficients */
- EIGEN_STRONG_INLINE Array(const Scalar& x, const Scalar& y, const Scalar& z)
+ EIGEN_STRONG_INLINE Array(const Scalar& val0, const Scalar& val1, const Scalar& val2)
{
Base::_check_template_params();
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Array, 3)
- m_storage.data()[0] = x;
- m_storage.data()[1] = y;
- m_storage.data()[2] = z;
+ m_storage.data()[0] = val0;
+ m_storage.data()[1] = val1;
+ m_storage.data()[2] = val2;
}
/** constructs an initialized 4D vector with given coefficients */
- EIGEN_STRONG_INLINE Array(const Scalar& x, const Scalar& y, const Scalar& z, const Scalar& w)
+ EIGEN_STRONG_INLINE Array(const Scalar& val0, const Scalar& val1, const Scalar& val2, const Scalar& val3)
{
Base::_check_template_params();
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Array, 4)
- m_storage.data()[0] = x;
- m_storage.data()[1] = y;
- m_storage.data()[2] = z;
- m_storage.data()[3] = w;
+ m_storage.data()[0] = val0;
+ m_storage.data()[1] = val1;
+ m_storage.data()[2] = val2;
+ m_storage.data()[3] = val3;
}
explicit Array(const Scalar *data);
@@ -210,7 +210,7 @@ class Array
: Base(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols())
{
Base::_check_template_params();
- Base::resize(other.rows(), other.cols());
+ Base::_resize_to_match(other);
*this = other;
}
diff --git a/Eigen/src/Core/ArrayBase.h b/Eigen/src/Core/ArrayBase.h
index 004b117c9..38852600d 100644
--- a/Eigen/src/Core/ArrayBase.h
+++ b/Eigen/src/Core/ArrayBase.h
@@ -143,7 +143,7 @@ template<typename Derived> class ArrayBase
ArrayBase<Derived>& array() { return *this; }
const ArrayBase<Derived>& array() const { return *this; }
- /** \returns an \link MatrixBase Matrix \endlink expression of this array
+ /** \returns an \link Eigen::MatrixBase Matrix \endlink expression of this array
* \sa MatrixBase::array() */
MatrixWrapper<Derived> matrix() { return derived(); }
const MatrixWrapper<const Derived> matrix() const { return derived(); }
diff --git a/Eigen/src/Core/ArrayWrapper.h b/Eigen/src/Core/ArrayWrapper.h
index 98f677d74..a791bc358 100644
--- a/Eigen/src/Core/ArrayWrapper.h
+++ b/Eigen/src/Core/ArrayWrapper.h
@@ -55,22 +55,22 @@ class ArrayWrapper : public ArrayBase<ArrayWrapper<ExpressionType> >
inline Index outerStride() const { return m_expression.outerStride(); }
inline Index innerStride() const { return m_expression.innerStride(); }
- inline ScalarWithConstIfNotLvalue* data() { return m_expression.data(); }
+ inline ScalarWithConstIfNotLvalue* data() { return m_expression.const_cast_derived().data(); }
inline const Scalar* data() const { return m_expression.data(); }
- inline CoeffReturnType coeff(Index row, Index col) const
+ inline CoeffReturnType coeff(Index rowId, Index colId) const
{
- return m_expression.coeff(row, col);
+ return m_expression.coeff(rowId, colId);
}
- inline Scalar& coeffRef(Index row, Index col)
+ inline Scalar& coeffRef(Index rowId, Index colId)
{
- return m_expression.const_cast_derived().coeffRef(row, col);
+ return m_expression.const_cast_derived().coeffRef(rowId, colId);
}
- inline const Scalar& coeffRef(Index row, Index col) const
+ inline const Scalar& coeffRef(Index rowId, Index colId) const
{
- return m_expression.const_cast_derived().coeffRef(row, col);
+ return m_expression.const_cast_derived().coeffRef(rowId, colId);
}
inline CoeffReturnType coeff(Index index) const
@@ -89,15 +89,15 @@ class ArrayWrapper : public ArrayBase<ArrayWrapper<ExpressionType> >
}
template<int LoadMode>
- inline const PacketScalar packet(Index row, Index col) const
+ inline const PacketScalar packet(Index rowId, Index colId) const
{
- return m_expression.template packet<LoadMode>(row, col);
+ return m_expression.template packet<LoadMode>(rowId, colId);
}
template<int LoadMode>
- inline void writePacket(Index row, Index col, const PacketScalar& x)
+ inline void writePacket(Index rowId, Index colId, const PacketScalar& val)
{
- m_expression.const_cast_derived().template writePacket<LoadMode>(row, col, x);
+ m_expression.const_cast_derived().template writePacket<LoadMode>(rowId, colId, val);
}
template<int LoadMode>
@@ -107,9 +107,9 @@ class ArrayWrapper : public ArrayBase<ArrayWrapper<ExpressionType> >
}
template<int LoadMode>
- inline void writePacket(Index index, const PacketScalar& x)
+ inline void writePacket(Index index, const PacketScalar& val)
{
- m_expression.const_cast_derived().template writePacket<LoadMode>(index, x);
+ m_expression.const_cast_derived().template writePacket<LoadMode>(index, val);
}
template<typename Dest>
@@ -121,6 +121,13 @@ class ArrayWrapper : public ArrayBase<ArrayWrapper<ExpressionType> >
return m_expression;
}
+ /** Forwards the resizing request to the nested expression
+ * \sa DenseBase::resize(Index) */
+ void resize(Index newSize) { m_expression.const_cast_derived().resize(newSize); }
+ /** Forwards the resizing request to the nested expression
+ * \sa DenseBase::resize(Index,Index)*/
+ void resize(Index nbRows, Index nbCols) { m_expression.const_cast_derived().resize(nbRows,nbCols); }
+
protected:
NestedExpressionType m_expression;
};
@@ -161,7 +168,7 @@ class MatrixWrapper : public MatrixBase<MatrixWrapper<ExpressionType> >
typedef typename internal::nested<ExpressionType>::type NestedExpressionType;
- inline MatrixWrapper(ExpressionType& matrix) : m_expression(matrix) {}
+ inline MatrixWrapper(ExpressionType& a_matrix) : m_expression(a_matrix) {}
inline Index rows() const { return m_expression.rows(); }
inline Index cols() const { return m_expression.cols(); }
@@ -171,19 +178,19 @@ class MatrixWrapper : public MatrixBase<MatrixWrapper<ExpressionType> >
inline ScalarWithConstIfNotLvalue* data() { return m_expression.const_cast_derived().data(); }
inline const Scalar* data() const { return m_expression.data(); }
- inline CoeffReturnType coeff(Index row, Index col) const
+ inline CoeffReturnType coeff(Index rowId, Index colId) const
{
- return m_expression.coeff(row, col);
+ return m_expression.coeff(rowId, colId);
}
- inline Scalar& coeffRef(Index row, Index col)
+ inline Scalar& coeffRef(Index rowId, Index colId)
{
- return m_expression.const_cast_derived().coeffRef(row, col);
+ return m_expression.const_cast_derived().coeffRef(rowId, colId);
}
- inline const Scalar& coeffRef(Index row, Index col) const
+ inline const Scalar& coeffRef(Index rowId, Index colId) const
{
- return m_expression.derived().coeffRef(row, col);
+ return m_expression.derived().coeffRef(rowId, colId);
}
inline CoeffReturnType coeff(Index index) const
@@ -202,15 +209,15 @@ class MatrixWrapper : public MatrixBase<MatrixWrapper<ExpressionType> >
}
template<int LoadMode>
- inline const PacketScalar packet(Index row, Index col) const
+ inline const PacketScalar packet(Index rowId, Index colId) const
{
- return m_expression.template packet<LoadMode>(row, col);
+ return m_expression.template packet<LoadMode>(rowId, colId);
}
template<int LoadMode>
- inline void writePacket(Index row, Index col, const PacketScalar& x)
+ inline void writePacket(Index rowId, Index colId, const PacketScalar& val)
{
- m_expression.const_cast_derived().template writePacket<LoadMode>(row, col, x);
+ m_expression.const_cast_derived().template writePacket<LoadMode>(rowId, colId, val);
}
template<int LoadMode>
@@ -220,9 +227,9 @@ class MatrixWrapper : public MatrixBase<MatrixWrapper<ExpressionType> >
}
template<int LoadMode>
- inline void writePacket(Index index, const PacketScalar& x)
+ inline void writePacket(Index index, const PacketScalar& val)
{
- m_expression.const_cast_derived().template writePacket<LoadMode>(index, x);
+ m_expression.const_cast_derived().template writePacket<LoadMode>(index, val);
}
const typename internal::remove_all<NestedExpressionType>::type&
@@ -231,6 +238,13 @@ class MatrixWrapper : public MatrixBase<MatrixWrapper<ExpressionType> >
return m_expression;
}
+ /** Forwards the resizing request to the nested expression
+ * \sa DenseBase::resize(Index) */
+ void resize(Index newSize) { m_expression.const_cast_derived().resize(newSize); }
+ /** Forwards the resizing request to the nested expression
+ * \sa DenseBase::resize(Index,Index)*/
+ void resize(Index nbRows, Index nbCols) { m_expression.const_cast_derived().resize(nbRows,nbCols); }
+
protected:
NestedExpressionType m_expression;
};
diff --git a/Eigen/src/Core/Assign.h b/Eigen/src/Core/Assign.h
index cd29a88f0..1dccc2f42 100644
--- a/Eigen/src/Core/Assign.h
+++ b/Eigen/src/Core/Assign.h
@@ -155,7 +155,7 @@ struct assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, Stop, Stop>
template<typename Derived1, typename Derived2, int Index, int Stop>
struct assign_DefaultTraversal_InnerUnrolling
{
- static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src, int outer)
+ static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src, typename Derived1::Index outer)
{
dst.copyCoeffByOuterInner(outer, Index, src);
assign_DefaultTraversal_InnerUnrolling<Derived1, Derived2, Index+1, Stop>::run(dst, src, outer);
@@ -165,7 +165,7 @@ struct assign_DefaultTraversal_InnerUnrolling
template<typename Derived1, typename Derived2, int Stop>
struct assign_DefaultTraversal_InnerUnrolling<Derived1, Derived2, Stop, Stop>
{
- static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &, int) {}
+ static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &, typename Derived1::Index) {}
};
/***********************
@@ -218,7 +218,7 @@ struct assign_innervec_CompleteUnrolling<Derived1, Derived2, Stop, Stop>
template<typename Derived1, typename Derived2, int Index, int Stop>
struct assign_innervec_InnerUnrolling
{
- static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src, int outer)
+ static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src, typename Derived1::Index outer)
{
dst.template copyPacketByOuterInner<Derived2, Aligned, Aligned>(outer, Index, src);
assign_innervec_InnerUnrolling<Derived1, Derived2,
@@ -229,7 +229,7 @@ struct assign_innervec_InnerUnrolling
template<typename Derived1, typename Derived2, int Stop>
struct assign_innervec_InnerUnrolling<Derived1, Derived2, Stop, Stop>
{
- static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &, int) {}
+ static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &, typename Derived1::Index) {}
};
/***************************************************************************
@@ -507,19 +507,19 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>
namespace internal {
template<typename Derived, typename OtherDerived,
- bool EvalBeforeAssigning = (int(OtherDerived::Flags) & EvalBeforeAssigningBit) != 0,
- bool NeedToTranspose = Derived::IsVectorAtCompileTime
- && OtherDerived::IsVectorAtCompileTime
- && ((int(Derived::RowsAtCompileTime) == 1 && int(OtherDerived::ColsAtCompileTime) == 1)
- | // FIXME | instead of || to please GCC 4.4.0 stupid warning "suggest parentheses around &&".
- // revert to || as soon as not needed anymore.
- (int(Derived::ColsAtCompileTime) == 1 && int(OtherDerived::RowsAtCompileTime) == 1))
- && int(Derived::SizeAtCompileTime) != 1>
+ bool EvalBeforeAssigning = (int(internal::traits<OtherDerived>::Flags) & EvalBeforeAssigningBit) != 0,
+ bool NeedToTranspose = ((int(Derived::RowsAtCompileTime) == 1 && int(OtherDerived::ColsAtCompileTime) == 1)
+ | // FIXME | instead of || to please GCC 4.4.0 stupid warning "suggest parentheses around &&".
+ // revert to || as soon as not needed anymore.
+ (int(Derived::ColsAtCompileTime) == 1 && int(OtherDerived::RowsAtCompileTime) == 1))
+ && int(Derived::SizeAtCompileTime) != 1>
struct assign_selector;
template<typename Derived, typename OtherDerived>
struct assign_selector<Derived,OtherDerived,false,false> {
static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.derived()); }
+ template<typename ActualDerived, typename ActualOtherDerived>
+ static EIGEN_STRONG_INLINE Derived& evalTo(ActualDerived& dst, const ActualOtherDerived& other) { other.evalTo(dst); return dst; }
};
template<typename Derived, typename OtherDerived>
struct assign_selector<Derived,OtherDerived,true,false> {
@@ -528,6 +528,8 @@ struct assign_selector<Derived,OtherDerived,true,false> {
template<typename Derived, typename OtherDerived>
struct assign_selector<Derived,OtherDerived,false,true> {
static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose()); }
+ template<typename ActualDerived, typename ActualOtherDerived>
+ static EIGEN_STRONG_INLINE Derived& evalTo(ActualDerived& dst, const ActualOtherDerived& other) { Transpose<ActualDerived> dstTrans(dst); other.evalTo(dstTrans); return dst; }
};
template<typename Derived, typename OtherDerived>
struct assign_selector<Derived,OtherDerived,true,true> {
@@ -566,16 +568,14 @@ template<typename Derived>
template <typename OtherDerived>
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const EigenBase<OtherDerived>& other)
{
- other.derived().evalTo(derived());
- return derived();
+ return internal::assign_selector<Derived,OtherDerived,false>::evalTo(derived(), other.derived());
}
template<typename Derived>
template<typename OtherDerived>
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const ReturnByValue<OtherDerived>& other)
{
- other.evalTo(derived());
- return derived();
+ return internal::assign_selector<Derived,OtherDerived,false>::evalTo(derived(), other.derived());
}
} // end namespace Eigen
diff --git a/Eigen/src/Core/Assign_MKL.h b/Eigen/src/Core/Assign_MKL.h
index 428c6367b..7772951b9 100644
--- a/Eigen/src/Core/Assign_MKL.h
+++ b/Eigen/src/Core/Assign_MKL.h
@@ -210,7 +210,7 @@ EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(sqrt, Sqrt)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(square, Sqr)
// The vm*powx functions are not avaibale in the windows version of MKL.
-#ifdef _WIN32
+#ifndef _WIN32
EIGEN_MKL_VML_DECLARE_POW_CALL(pow, vmspowx_, float, float)
EIGEN_MKL_VML_DECLARE_POW_CALL(pow, vmdpowx_, double, double)
EIGEN_MKL_VML_DECLARE_POW_CALL(pow, vmcpowx_, scomplex, MKL_Complex8)
diff --git a/Eigen/src/Core/Block.h b/Eigen/src/Core/Block.h
index 5f29cb3d1..87bedfa46 100644
--- a/Eigen/src/Core/Block.h
+++ b/Eigen/src/Core/Block.h
@@ -21,7 +21,6 @@ namespace Eigen {
* \param XprType the type of the expression in which we are taking a block
* \param BlockRows the number of rows of the block we are taking at compile time (optional)
* \param BlockCols the number of columns of the block we are taking at compile time (optional)
- * \param _DirectAccessStatus \internal used for partial specialization
*
* This class represents an expression of either a fixed-size or dynamic-size block. It is the return
* type of DenseBase::block(Index,Index,Index,Index) and DenseBase::block<int,int>(Index,Index) and
@@ -47,8 +46,8 @@ namespace Eigen {
*/
namespace internal {
-template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess>
-struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess> > : traits<XprType>
+template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
+struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel> > : traits<XprType>
{
typedef typename traits<XprType>::Scalar Scalar;
typedef typename traits<XprType>::StorageKind StorageKind;
@@ -82,7 +81,7 @@ struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess>
&& (InnerStrideAtCompileTime == 1)
? PacketAccessBit : 0,
MaskAlignedBit = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic) && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % 16) == 0)) ? AlignedBit : 0,
- FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? LinearAccessBit : 0,
+ FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1 || (InnerPanel && (traits<XprType>::Flags&LinearAccessBit))) ? LinearAccessBit : 0,
FlagsLvalueBit = is_lvalue<XprType>::value ? LvalueBit : 0,
FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0,
Flags0 = traits<XprType>::Flags & ( (HereditaryBits & ~RowMajorBit) |
@@ -92,30 +91,27 @@ struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess>
Flags = Flags0 | FlagsLinearAccessBit | FlagsLvalueBit | FlagsRowMajorBit
};
};
-}
-
-template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess> class Block
- : public internal::dense_xpr_base<Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess> >::type
-{
- public:
- typedef typename internal::dense_xpr_base<Block>::type Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(Block)
+template<typename XprType, int BlockRows=Dynamic, int BlockCols=Dynamic, bool InnerPanel = false,
+ bool HasDirectAccess = internal::has_direct_access<XprType>::ret> class BlockImpl_dense;
+
+} // end namespace internal
- class InnerIterator;
+template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, typename StorageKind> class BlockImpl;
+template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel> class Block
+ : public BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, typename internal::traits<XprType>::StorageKind>
+{
+ typedef BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, typename internal::traits<XprType>::StorageKind> Impl;
+ public:
+ //typedef typename Impl::Base Base;
+ typedef Impl Base;
+ EIGEN_GENERIC_PUBLIC_INTERFACE(Block)
+ EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)
+
/** Column or Row constructor
*/
- inline Block(XprType& xpr, Index i)
- : m_xpr(xpr),
- // It is a row if and only if BlockRows==1 and BlockCols==XprType::ColsAtCompileTime,
- // and it is a column if and only if BlockRows==XprType::RowsAtCompileTime and BlockCols==1,
- // all other cases are invalid.
- // The case a 1x1 matrix seems ambiguous, but the result is the same anyway.
- m_startRow( (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0),
- m_startCol( (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0),
- m_blockRows(BlockRows==1 ? 1 : xpr.rows()),
- m_blockCols(BlockCols==1 ? 1 : xpr.cols())
+ inline Block(XprType& xpr, Index i) : Impl(xpr,i)
{
eigen_assert( (i>=0) && (
((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && i<xpr.rows())
@@ -124,50 +120,109 @@ template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool H
/** Fixed-size constructor
*/
- inline Block(XprType& xpr, Index startRow, Index startCol)
- : m_xpr(xpr), m_startRow(startRow), m_startCol(startCol),
- m_blockRows(BlockRows), m_blockCols(BlockCols)
+ inline Block(XprType& xpr, Index a_startRow, Index a_startCol)
+ : Impl(xpr, a_startRow, a_startCol)
{
EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic,THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE)
- eigen_assert(startRow >= 0 && BlockRows >= 1 && startRow + BlockRows <= xpr.rows()
- && startCol >= 0 && BlockCols >= 1 && startCol + BlockCols <= xpr.cols());
+ eigen_assert(a_startRow >= 0 && BlockRows >= 1 && a_startRow + BlockRows <= xpr.rows()
+ && a_startCol >= 0 && BlockCols >= 1 && a_startCol + BlockCols <= xpr.cols());
}
/** Dynamic-size constructor
*/
inline Block(XprType& xpr,
- Index startRow, Index startCol,
+ Index a_startRow, Index a_startCol,
Index blockRows, Index blockCols)
- : m_xpr(xpr), m_startRow(startRow), m_startCol(startCol),
- m_blockRows(blockRows), m_blockCols(blockCols)
+ : Impl(xpr, a_startRow, a_startCol, blockRows, blockCols)
{
eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows)
&& (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols));
- eigen_assert(startRow >= 0 && blockRows >= 0 && startRow + blockRows <= xpr.rows()
- && startCol >= 0 && blockCols >= 0 && startCol + blockCols <= xpr.cols());
+ eigen_assert(a_startRow >= 0 && blockRows >= 0 && a_startRow <= xpr.rows() - blockRows
+ && a_startCol >= 0 && blockCols >= 0 && a_startCol <= xpr.cols() - blockCols);
}
+};
+
+// The generic default implementation for dense block simplu forward to the internal::BlockImpl_dense
+// that must be specialized for direct and non-direct access...
+template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
+class BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, Dense>
+ : public internal::BlockImpl_dense<XprType, BlockRows, BlockCols, InnerPanel>
+{
+ typedef internal::BlockImpl_dense<XprType, BlockRows, BlockCols, InnerPanel> Impl;
+ typedef typename XprType::Index Index;
+ public:
+ typedef Impl Base;
+ EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl)
+ inline BlockImpl(XprType& xpr, Index i) : Impl(xpr,i) {}
+ inline BlockImpl(XprType& xpr, Index a_startRow, Index a_startCol) : Impl(xpr, a_startRow, a_startCol) {}
+ inline BlockImpl(XprType& xpr, Index a_startRow, Index a_startCol, Index blockRows, Index blockCols)
+ : Impl(xpr, a_startRow, a_startCol, blockRows, blockCols) {}
+};
- EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)
+namespace internal {
+
+/** \internal Internal implementation of dense Blocks in the general case. */
+template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess> class BlockImpl_dense
+ : public internal::dense_xpr_base<Block<XprType, BlockRows, BlockCols, InnerPanel> >::type
+{
+ typedef Block<XprType, BlockRows, BlockCols, InnerPanel> BlockType;
+ public:
+
+ typedef typename internal::dense_xpr_base<BlockType>::type Base;
+ EIGEN_DENSE_PUBLIC_INTERFACE(BlockType)
+ EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl_dense)
+
+ class InnerIterator;
+
+ /** Column or Row constructor
+ */
+ inline BlockImpl_dense(XprType& xpr, Index i)
+ : m_xpr(xpr),
+ // It is a row if and only if BlockRows==1 and BlockCols==XprType::ColsAtCompileTime,
+ // and it is a column if and only if BlockRows==XprType::RowsAtCompileTime and BlockCols==1,
+ // all other cases are invalid.
+ // The case a 1x1 matrix seems ambiguous, but the result is the same anyway.
+ m_startRow( (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0),
+ m_startCol( (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0),
+ m_blockRows(BlockRows==1 ? 1 : xpr.rows()),
+ m_blockCols(BlockCols==1 ? 1 : xpr.cols())
+ {}
+
+ /** Fixed-size constructor
+ */
+ inline BlockImpl_dense(XprType& xpr, Index a_startRow, Index a_startCol)
+ : m_xpr(xpr), m_startRow(a_startRow), m_startCol(a_startCol),
+ m_blockRows(BlockRows), m_blockCols(BlockCols)
+ {}
+
+ /** Dynamic-size constructor
+ */
+ inline BlockImpl_dense(XprType& xpr,
+ Index a_startRow, Index a_startCol,
+ Index blockRows, Index blockCols)
+ : m_xpr(xpr), m_startRow(a_startRow), m_startCol(a_startCol),
+ m_blockRows(blockRows), m_blockCols(blockCols)
+ {}
inline Index rows() const { return m_blockRows.value(); }
inline Index cols() const { return m_blockCols.value(); }
- inline Scalar& coeffRef(Index row, Index col)
+ inline Scalar& coeffRef(Index rowId, Index colId)
{
EIGEN_STATIC_ASSERT_LVALUE(XprType)
return m_xpr.const_cast_derived()
- .coeffRef(row + m_startRow.value(), col + m_startCol.value());
+ .coeffRef(rowId + m_startRow.value(), colId + m_startCol.value());
}
- inline const Scalar& coeffRef(Index row, Index col) const
+ inline const Scalar& coeffRef(Index rowId, Index colId) const
{
return m_xpr.derived()
- .coeffRef(row + m_startRow.value(), col + m_startCol.value());
+ .coeffRef(rowId + m_startRow.value(), colId + m_startCol.value());
}
- EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index row, Index col) const
+ EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index rowId, Index colId) const
{
- return m_xpr.coeff(row + m_startRow.value(), col + m_startCol.value());
+ return m_xpr.coeff(rowId + m_startRow.value(), colId + m_startCol.value());
}
inline Scalar& coeffRef(Index index)
@@ -193,17 +248,17 @@ template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool H
}
template<int LoadMode>
- inline PacketScalar packet(Index row, Index col) const
+ inline PacketScalar packet(Index rowId, Index colId) const
{
return m_xpr.template packet<Unaligned>
- (row + m_startRow.value(), col + m_startCol.value());
+ (rowId + m_startRow.value(), colId + m_startCol.value());
}
template<int LoadMode>
- inline void writePacket(Index row, Index col, const PacketScalar& x)
+ inline void writePacket(Index rowId, Index colId, const PacketScalar& val)
{
m_xpr.const_cast_derived().template writePacket<Unaligned>
- (row + m_startRow.value(), col + m_startCol.value(), x);
+ (rowId + m_startRow.value(), colId + m_startCol.value(), val);
}
template<int LoadMode>
@@ -215,11 +270,11 @@ template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool H
}
template<int LoadMode>
- inline void writePacket(Index index, const PacketScalar& x)
+ inline void writePacket(Index index, const PacketScalar& val)
{
m_xpr.const_cast_derived().template writePacket<Unaligned>
(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
- m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0), x);
+ m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0), val);
}
#ifdef EIGEN_PARSED_BY_DOXYGEN
@@ -253,21 +308,21 @@ template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool H
const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_blockCols;
};
-/** \internal */
+/** \internal Internal implementation of dense Blocks in the direct access case.*/
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
-class Block<XprType,BlockRows,BlockCols, InnerPanel,true>
- : public MapBase<Block<XprType, BlockRows, BlockCols, InnerPanel, true> >
+class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
+ : public MapBase<Block<XprType, BlockRows, BlockCols, InnerPanel> >
{
+ typedef Block<XprType, BlockRows, BlockCols, InnerPanel> BlockType;
public:
- typedef MapBase<Block> Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(Block)
-
- EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)
+ typedef MapBase<BlockType> Base;
+ EIGEN_DENSE_PUBLIC_INTERFACE(BlockType)
+ EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl_dense)
/** Column or Row constructor
*/
- inline Block(XprType& xpr, Index i)
+ inline BlockImpl_dense(XprType& xpr, Index i)
: Base(internal::const_cast_ptr(&xpr.coeffRef(
(BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0,
(BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0)),
@@ -275,34 +330,25 @@ class Block<XprType,BlockRows,BlockCols, InnerPanel,true>
BlockCols==1 ? 1 : xpr.cols()),
m_xpr(xpr)
{
- eigen_assert( (i>=0) && (
- ((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && i<xpr.rows())
- ||((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && i<xpr.cols())));
init();
}
/** Fixed-size constructor
*/
- inline Block(XprType& xpr, Index startRow, Index startCol)
+ inline BlockImpl_dense(XprType& xpr, Index startRow, Index startCol)
: Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol))), m_xpr(xpr)
{
- eigen_assert(startRow >= 0 && BlockRows >= 1 && startRow + BlockRows <= xpr.rows()
- && startCol >= 0 && BlockCols >= 1 && startCol + BlockCols <= xpr.cols());
init();
}
/** Dynamic-size constructor
*/
- inline Block(XprType& xpr,
+ inline BlockImpl_dense(XprType& xpr,
Index startRow, Index startCol,
Index blockRows, Index blockCols)
: Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol)), blockRows, blockCols),
m_xpr(xpr)
{
- eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows)
- && (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols));
- eigen_assert(startRow >= 0 && blockRows >= 0 && startRow + blockRows <= xpr.rows()
- && startCol >= 0 && blockCols >= 0 && startCol + blockCols <= xpr.cols());
init();
}
@@ -314,7 +360,7 @@ class Block<XprType,BlockRows,BlockCols, InnerPanel,true>
/** \sa MapBase::innerStride() */
inline Index innerStride() const
{
- return internal::traits<Block>::HasSameStorageOrderAsXprType
+ return internal::traits<BlockType>::HasSameStorageOrderAsXprType
? m_xpr.innerStride()
: m_xpr.outerStride();
}
@@ -333,7 +379,7 @@ class Block<XprType,BlockRows,BlockCols, InnerPanel,true>
#ifndef EIGEN_PARSED_BY_DOXYGEN
/** \internal used by allowAligned() */
- inline Block(XprType& xpr, const Scalar* data, Index blockRows, Index blockCols)
+ inline BlockImpl_dense(XprType& xpr, const Scalar* data, Index blockRows, Index blockCols)
: Base(data, blockRows, blockCols), m_xpr(xpr)
{
init();
@@ -343,7 +389,7 @@ class Block<XprType,BlockRows,BlockCols, InnerPanel,true>
protected:
void init()
{
- m_outerStride = internal::traits<Block>::HasSameStorageOrderAsXprType
+ m_outerStride = internal::traits<BlockType>::HasSameStorageOrderAsXprType
? m_xpr.outerStride()
: m_xpr.innerStride();
}
@@ -352,6 +398,8 @@ class Block<XprType,BlockRows,BlockCols, InnerPanel,true>
Index m_outerStride;
};
+} // end namespace internal
+
} // end namespace Eigen
#endif // EIGEN_BLOCK_H
diff --git a/Eigen/src/Core/BooleanRedux.h b/Eigen/src/Core/BooleanRedux.h
index 57efd8e69..be9f48a8c 100644
--- a/Eigen/src/Core/BooleanRedux.h
+++ b/Eigen/src/Core/BooleanRedux.h
@@ -29,9 +29,9 @@ struct all_unroller
};
template<typename Derived>
-struct all_unroller<Derived, 1>
+struct all_unroller<Derived, 0>
{
- static inline bool run(const Derived &mat) { return mat.coeff(0, 0); }
+ static inline bool run(const Derived &/*mat*/) { return true; }
};
template<typename Derived>
@@ -55,9 +55,9 @@ struct any_unroller
};
template<typename Derived>
-struct any_unroller<Derived, 1>
+struct any_unroller<Derived, 0>
{
- static inline bool run(const Derived &mat) { return mat.coeff(0, 0); }
+ static inline bool run(const Derived & /*mat*/) { return false; }
};
template<typename Derived>
@@ -85,9 +85,7 @@ inline bool DenseBase<Derived>::all() const
&& SizeAtCompileTime * (CoeffReadCost + NumTraits<Scalar>::AddCost) <= EIGEN_UNROLLING_LIMIT
};
if(unroll)
- return internal::all_unroller<Derived,
- unroll ? int(SizeAtCompileTime) : Dynamic
- >::run(derived());
+ return internal::all_unroller<Derived, unroll ? int(SizeAtCompileTime) : Dynamic>::run(derived());
else
{
for(Index j = 0; j < cols(); ++j)
@@ -111,9 +109,7 @@ inline bool DenseBase<Derived>::any() const
&& SizeAtCompileTime * (CoeffReadCost + NumTraits<Scalar>::AddCost) <= EIGEN_UNROLLING_LIMIT
};
if(unroll)
- return internal::any_unroller<Derived,
- unroll ? int(SizeAtCompileTime) : Dynamic
- >::run(derived());
+ return internal::any_unroller<Derived, unroll ? int(SizeAtCompileTime) : Dynamic>::run(derived());
else
{
for(Index j = 0; j < cols(); ++j)
@@ -133,6 +129,26 @@ inline typename DenseBase<Derived>::Index DenseBase<Derived>::count() const
return derived().template cast<bool>().template cast<Index>().sum();
}
+/** \returns true is \c *this contains at least one Not A Number (NaN).
+ *
+ * \sa allFinite()
+ */
+template<typename Derived>
+inline bool DenseBase<Derived>::hasNaN() const
+{
+ return !((derived().array()==derived().array()).all());
+}
+
+/** \returns true if \c *this contains only finite numbers, i.e., no NaN and no +/-INF values.
+ *
+ * \sa hasNaN()
+ */
+template<typename Derived>
+inline bool DenseBase<Derived>::allFinite() const
+{
+ return !((derived()-derived()).hasNaN());
+}
+
} // end namespace Eigen
#endif // EIGEN_ALLANDANY_H
diff --git a/Eigen/src/Core/CommaInitializer.h b/Eigen/src/Core/CommaInitializer.h
index 4adce6414..a036d8c3b 100644
--- a/Eigen/src/Core/CommaInitializer.h
+++ b/Eigen/src/Core/CommaInitializer.h
@@ -43,6 +43,17 @@ struct CommaInitializer
m_xpr.block(0, 0, other.rows(), other.cols()) = other;
}
+ /* Copy/Move constructor which transfers ownership. This is crucial in
+ * absence of return value optimization to avoid assertions during destruction. */
+ // FIXME in C++11 mode this could be replaced by a proper RValue constructor
+ inline CommaInitializer(const CommaInitializer& o)
+ : m_xpr(o.m_xpr), m_row(o.m_row), m_col(o.m_col), m_currentBlockRows(o.m_currentBlockRows) {
+ // Mark original object as finished. In absence of R-value references we need to const_cast:
+ const_cast<CommaInitializer&>(o).m_row = m_xpr.rows();
+ const_cast<CommaInitializer&>(o).m_col = m_xpr.cols();
+ const_cast<CommaInitializer&>(o).m_currentBlockRows = 0;
+ }
+
/* inserts a scalar value in the target matrix */
CommaInitializer& operator,(const Scalar& s)
{
@@ -65,6 +76,8 @@ struct CommaInitializer
template<typename OtherDerived>
CommaInitializer& operator,(const DenseBase<OtherDerived>& other)
{
+ if(other.cols()==0 || other.rows()==0)
+ return *this;
if (m_col==m_xpr.cols())
{
m_row+=m_currentBlockRows;
@@ -116,6 +129,8 @@ struct CommaInitializer
*
* Example: \include MatrixBase_set.cpp
* Output: \verbinclude MatrixBase_set.out
+ *
+ * \note According the c++ standard, the argument expressions of this comma initializer are evaluated in arbitrary order.
*
* \sa CommaInitializer::finished(), class CommaInitializer
*/
diff --git a/Eigen/src/SparseCore/CoreIterators.h b/Eigen/src/Core/CoreIterators.h
index 6da4683d2..6da4683d2 100644
--- a/Eigen/src/SparseCore/CoreIterators.h
+++ b/Eigen/src/Core/CoreIterators.h
diff --git a/Eigen/src/Core/CwiseBinaryOp.h b/Eigen/src/Core/CwiseBinaryOp.h
index 1b93af31b..586f77aaf 100644
--- a/Eigen/src/Core/CwiseBinaryOp.h
+++ b/Eigen/src/Core/CwiseBinaryOp.h
@@ -94,8 +94,8 @@ struct traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
// So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to
// add together a float matrix and a double matrix.
#define EIGEN_CHECK_BINARY_COMPATIBILIY(BINOP,LHS,RHS) \
- EIGEN_STATIC_ASSERT((internal::functor_allows_mixing_real_and_complex<BINOP>::ret \
- ? int(internal::is_same<typename NumTraits<LHS>::Real, typename NumTraits<RHS>::Real>::value) \
+ EIGEN_STATIC_ASSERT((internal::functor_is_product_like<BINOP>::ret \
+ ? int(internal::scalar_product_traits<LHS, RHS>::Defined) \
: int(internal::is_same<LHS, RHS>::value)), \
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
@@ -122,13 +122,13 @@ class CwiseBinaryOp : internal::no_assignment_operator,
typedef typename internal::remove_reference<LhsNested>::type _LhsNested;
typedef typename internal::remove_reference<RhsNested>::type _RhsNested;
- EIGEN_STRONG_INLINE CwiseBinaryOp(const Lhs& lhs, const Rhs& rhs, const BinaryOp& func = BinaryOp())
- : m_lhs(lhs), m_rhs(rhs), m_functor(func)
+ EIGEN_STRONG_INLINE CwiseBinaryOp(const Lhs& aLhs, const Rhs& aRhs, const BinaryOp& func = BinaryOp())
+ : m_lhs(aLhs), m_rhs(aRhs), m_functor(func)
{
EIGEN_CHECK_BINARY_COMPATIBILIY(BinaryOp,typename Lhs::Scalar,typename Rhs::Scalar);
// require the sizes to match
EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Lhs, Rhs)
- eigen_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
+ eigen_assert(aLhs.rows() == aRhs.rows() && aLhs.cols() == aRhs.cols());
}
EIGEN_STRONG_INLINE Index rows() const {
@@ -169,17 +169,17 @@ class CwiseBinaryOpImpl<BinaryOp, Lhs, Rhs, Dense>
typedef typename internal::dense_xpr_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type Base;
EIGEN_DENSE_PUBLIC_INTERFACE( Derived )
- EIGEN_STRONG_INLINE const Scalar coeff(Index row, Index col) const
+ EIGEN_STRONG_INLINE const Scalar coeff(Index rowId, Index colId) const
{
- return derived().functor()(derived().lhs().coeff(row, col),
- derived().rhs().coeff(row, col));
+ return derived().functor()(derived().lhs().coeff(rowId, colId),
+ derived().rhs().coeff(rowId, colId));
}
template<int LoadMode>
- EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const
+ EIGEN_STRONG_INLINE PacketScalar packet(Index rowId, Index colId) const
{
- return derived().functor().packetOp(derived().lhs().template packet<LoadMode>(row, col),
- derived().rhs().template packet<LoadMode>(row, col));
+ return derived().functor().packetOp(derived().lhs().template packet<LoadMode>(rowId, colId),
+ derived().rhs().template packet<LoadMode>(rowId, colId));
}
EIGEN_STRONG_INLINE const Scalar coeff(Index index) const
diff --git a/Eigen/src/Core/CwiseNullaryOp.h b/Eigen/src/Core/CwiseNullaryOp.h
index 2635a62b0..a93bab2d0 100644
--- a/Eigen/src/Core/CwiseNullaryOp.h
+++ b/Eigen/src/Core/CwiseNullaryOp.h
@@ -54,27 +54,27 @@ class CwiseNullaryOp : internal::no_assignment_operator,
typedef typename internal::dense_xpr_base<CwiseNullaryOp>::type Base;
EIGEN_DENSE_PUBLIC_INTERFACE(CwiseNullaryOp)
- CwiseNullaryOp(Index rows, Index cols, const NullaryOp& func = NullaryOp())
- : m_rows(rows), m_cols(cols), m_functor(func)
+ CwiseNullaryOp(Index nbRows, Index nbCols, const NullaryOp& func = NullaryOp())
+ : m_rows(nbRows), m_cols(nbCols), m_functor(func)
{
- eigen_assert(rows >= 0
- && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
- && cols >= 0
- && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
+ eigen_assert(nbRows >= 0
+ && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == nbRows)
+ && nbCols >= 0
+ && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == nbCols));
}
EIGEN_STRONG_INLINE Index rows() const { return m_rows.value(); }
EIGEN_STRONG_INLINE Index cols() const { return m_cols.value(); }
- EIGEN_STRONG_INLINE const Scalar coeff(Index rows, Index cols) const
+ EIGEN_STRONG_INLINE const Scalar coeff(Index rowId, Index colId) const
{
- return m_functor(rows, cols);
+ return m_functor(rowId, colId);
}
template<int LoadMode>
- EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const
+ EIGEN_STRONG_INLINE PacketScalar packet(Index rowId, Index colId) const
{
- return m_functor.packetOp(row, col);
+ return m_functor.packetOp(rowId, colId);
}
EIGEN_STRONG_INLINE const Scalar coeff(Index index) const
@@ -163,11 +163,11 @@ DenseBase<Derived>::NullaryExpr(const CustomNullaryOp& func)
/** \returns an expression of a constant matrix of value \a value
*
- * The parameters \a rows and \a cols are the number of rows and of columns of
+ * The parameters \a nbRows and \a nbCols are the number of rows and of columns of
* the returned matrix. Must be compatible with this DenseBase type.
*
* This variant is meant to be used for dynamic-size matrix types. For fixed-size types,
- * it is redundant to pass \a rows and \a cols as arguments, so Zero() should be used
+ * it is redundant to pass \a nbRows and \a nbCols as arguments, so Zero() should be used
* instead.
*
* The template parameter \a CustomNullaryOp is the type of the functor.
@@ -176,9 +176,9 @@ DenseBase<Derived>::NullaryExpr(const CustomNullaryOp& func)
*/
template<typename Derived>
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
-DenseBase<Derived>::Constant(Index rows, Index cols, const Scalar& value)
+DenseBase<Derived>::Constant(Index nbRows, Index nbCols, const Scalar& value)
{
- return DenseBase<Derived>::NullaryExpr(rows, cols, internal::scalar_constant_op<Scalar>(value));
+ return DenseBase<Derived>::NullaryExpr(nbRows, nbCols, internal::scalar_constant_op<Scalar>(value));
}
/** \returns an expression of a constant matrix of value \a value
@@ -292,14 +292,14 @@ DenseBase<Derived>::LinSpaced(const Scalar& low, const Scalar& high)
return DenseBase<Derived>::NullaryExpr(Derived::SizeAtCompileTime, internal::linspaced_op<Scalar,true>(low,high,Derived::SizeAtCompileTime));
}
-/** \returns true if all coefficients in this matrix are approximately equal to \a value, to within precision \a prec */
+/** \returns true if all coefficients in this matrix are approximately equal to \a val, to within precision \a prec */
template<typename Derived>
bool DenseBase<Derived>::isApproxToConstant
-(const Scalar& value, RealScalar prec) const
+(const Scalar& val, const RealScalar& prec) const
{
for(Index j = 0; j < cols(); ++j)
for(Index i = 0; i < rows(); ++i)
- if(!internal::isApprox(this->coeff(i, j), value, prec))
+ if(!internal::isApprox(this->coeff(i, j), val, prec))
return false;
return true;
}
@@ -309,19 +309,19 @@ bool DenseBase<Derived>::isApproxToConstant
* \returns true if all coefficients in this matrix are approximately equal to \a value, to within precision \a prec */
template<typename Derived>
bool DenseBase<Derived>::isConstant
-(const Scalar& value, RealScalar prec) const
+(const Scalar& val, const RealScalar& prec) const
{
- return isApproxToConstant(value, prec);
+ return isApproxToConstant(val, prec);
}
-/** Alias for setConstant(): sets all coefficients in this expression to \a value.
+/** Alias for setConstant(): sets all coefficients in this expression to \a val.
*
* \sa setConstant(), Constant(), class CwiseNullaryOp
*/
template<typename Derived>
-EIGEN_STRONG_INLINE void DenseBase<Derived>::fill(const Scalar& value)
+EIGEN_STRONG_INLINE void DenseBase<Derived>::fill(const Scalar& val)
{
- setConstant(value);
+ setConstant(val);
}
/** Sets all coefficients in this expression to \a value.
@@ -329,9 +329,9 @@ EIGEN_STRONG_INLINE void DenseBase<Derived>::fill(const Scalar& value)
* \sa fill(), setConstant(Index,const Scalar&), setConstant(Index,Index,const Scalar&), setZero(), setOnes(), Constant(), class CwiseNullaryOp, setZero(), setOnes()
*/
template<typename Derived>
-EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setConstant(const Scalar& value)
+EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setConstant(const Scalar& val)
{
- return derived() = Constant(rows(), cols(), value);
+ return derived() = Constant(rows(), cols(), val);
}
/** Resizes to the given \a size, and sets all coefficients in this expression to the given \a value.
@@ -345,17 +345,17 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setConstant(const Scalar& value
*/
template<typename Derived>
EIGEN_STRONG_INLINE Derived&
-PlainObjectBase<Derived>::setConstant(Index size, const Scalar& value)
+PlainObjectBase<Derived>::setConstant(Index size, const Scalar& val)
{
resize(size);
- return setConstant(value);
+ return setConstant(val);
}
/** Resizes to the given size, and sets all coefficients in this expression to the given \a value.
*
- * \param rows the new number of rows
- * \param cols the new number of columns
- * \param value the value to which all coefficients are set
+ * \param nbRows the new number of rows
+ * \param nbCols the new number of columns
+ * \param val the value to which all coefficients are set
*
* Example: \include Matrix_setConstant_int_int.cpp
* Output: \verbinclude Matrix_setConstant_int_int.out
@@ -364,10 +364,10 @@ PlainObjectBase<Derived>::setConstant(Index size, const Scalar& value)
*/
template<typename Derived>
EIGEN_STRONG_INLINE Derived&
-PlainObjectBase<Derived>::setConstant(Index rows, Index cols, const Scalar& value)
+PlainObjectBase<Derived>::setConstant(Index nbRows, Index nbCols, const Scalar& val)
{
- resize(rows, cols);
- return setConstant(value);
+ resize(nbRows, nbCols);
+ return setConstant(val);
}
/**
@@ -384,10 +384,10 @@ PlainObjectBase<Derived>::setConstant(Index rows, Index cols, const Scalar& valu
* \sa CwiseNullaryOp
*/
template<typename Derived>
-EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setLinSpaced(Index size, const Scalar& low, const Scalar& high)
+EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setLinSpaced(Index newSize, const Scalar& low, const Scalar& high)
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return derived() = Derived::NullaryExpr(size, internal::linspaced_op<Scalar,false>(low,high,size));
+ return derived() = Derived::NullaryExpr(newSize, internal::linspaced_op<Scalar,false>(low,high,newSize));
}
/**
@@ -425,9 +425,9 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setLinSpaced(const Scalar& low,
*/
template<typename Derived>
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
-DenseBase<Derived>::Zero(Index rows, Index cols)
+DenseBase<Derived>::Zero(Index nbRows, Index nbCols)
{
- return Constant(rows, cols, Scalar(0));
+ return Constant(nbRows, nbCols, Scalar(0));
}
/** \returns an expression of a zero vector.
@@ -479,7 +479,7 @@ DenseBase<Derived>::Zero()
* \sa class CwiseNullaryOp, Zero()
*/
template<typename Derived>
-bool DenseBase<Derived>::isZero(RealScalar prec) const
+bool DenseBase<Derived>::isZero(const RealScalar& prec) const
{
for(Index j = 0; j < cols(); ++j)
for(Index i = 0; i < rows(); ++i)
@@ -512,16 +512,16 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setZero()
*/
template<typename Derived>
EIGEN_STRONG_INLINE Derived&
-PlainObjectBase<Derived>::setZero(Index size)
+PlainObjectBase<Derived>::setZero(Index newSize)
{
- resize(size);
+ resize(newSize);
return setConstant(Scalar(0));
}
/** Resizes to the given size, and sets all coefficients in this expression to zero.
*
- * \param rows the new number of rows
- * \param cols the new number of columns
+ * \param nbRows the new number of rows
+ * \param nbCols the new number of columns
*
* Example: \include Matrix_setZero_int_int.cpp
* Output: \verbinclude Matrix_setZero_int_int.out
@@ -530,9 +530,9 @@ PlainObjectBase<Derived>::setZero(Index size)
*/
template<typename Derived>
EIGEN_STRONG_INLINE Derived&
-PlainObjectBase<Derived>::setZero(Index rows, Index cols)
+PlainObjectBase<Derived>::setZero(Index nbRows, Index nbCols)
{
- resize(rows, cols);
+ resize(nbRows, nbCols);
return setConstant(Scalar(0));
}
@@ -540,7 +540,7 @@ PlainObjectBase<Derived>::setZero(Index rows, Index cols)
/** \returns an expression of a matrix where all coefficients equal one.
*
- * The parameters \a rows and \a cols are the number of rows and of columns of
+ * The parameters \a nbRows and \a nbCols are the number of rows and of columns of
* the returned matrix. Must be compatible with this MatrixBase type.
*
* This variant is meant to be used for dynamic-size matrix types. For fixed-size types,
@@ -554,14 +554,14 @@ PlainObjectBase<Derived>::setZero(Index rows, Index cols)
*/
template<typename Derived>
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
-DenseBase<Derived>::Ones(Index rows, Index cols)
+DenseBase<Derived>::Ones(Index nbRows, Index nbCols)
{
- return Constant(rows, cols, Scalar(1));
+ return Constant(nbRows, nbCols, Scalar(1));
}
/** \returns an expression of a vector where all coefficients equal one.
*
- * The parameter \a size is the size of the returned vector.
+ * The parameter \a newSize is the size of the returned vector.
* Must be compatible with this MatrixBase type.
*
* \only_for_vectors
@@ -577,9 +577,9 @@ DenseBase<Derived>::Ones(Index rows, Index cols)
*/
template<typename Derived>
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
-DenseBase<Derived>::Ones(Index size)
+DenseBase<Derived>::Ones(Index newSize)
{
- return Constant(size, Scalar(1));
+ return Constant(newSize, Scalar(1));
}
/** \returns an expression of a fixed-size matrix or vector where all coefficients equal one.
@@ -609,7 +609,7 @@ DenseBase<Derived>::Ones()
*/
template<typename Derived>
bool DenseBase<Derived>::isOnes
-(RealScalar prec) const
+(const RealScalar& prec) const
{
return isApproxToConstant(Scalar(1), prec);
}
@@ -627,7 +627,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setOnes()
return setConstant(Scalar(1));
}
-/** Resizes to the given \a size, and sets all coefficients in this expression to one.
+/** Resizes to the given \a newSize, and sets all coefficients in this expression to one.
*
* \only_for_vectors
*
@@ -638,16 +638,16 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setOnes()
*/
template<typename Derived>
EIGEN_STRONG_INLINE Derived&
-PlainObjectBase<Derived>::setOnes(Index size)
+PlainObjectBase<Derived>::setOnes(Index newSize)
{
- resize(size);
+ resize(newSize);
return setConstant(Scalar(1));
}
/** Resizes to the given size, and sets all coefficients in this expression to one.
*
- * \param rows the new number of rows
- * \param cols the new number of columns
+ * \param nbRows the new number of rows
+ * \param nbCols the new number of columns
*
* Example: \include Matrix_setOnes_int_int.cpp
* Output: \verbinclude Matrix_setOnes_int_int.out
@@ -656,9 +656,9 @@ PlainObjectBase<Derived>::setOnes(Index size)
*/
template<typename Derived>
EIGEN_STRONG_INLINE Derived&
-PlainObjectBase<Derived>::setOnes(Index rows, Index cols)
+PlainObjectBase<Derived>::setOnes(Index nbRows, Index nbCols)
{
- resize(rows, cols);
+ resize(nbRows, nbCols);
return setConstant(Scalar(1));
}
@@ -666,7 +666,7 @@ PlainObjectBase<Derived>::setOnes(Index rows, Index cols)
/** \returns an expression of the identity matrix (not necessarily square).
*
- * The parameters \a rows and \a cols are the number of rows and of columns of
+ * The parameters \a nbRows and \a nbCols are the number of rows and of columns of
* the returned matrix. Must be compatible with this MatrixBase type.
*
* This variant is meant to be used for dynamic-size matrix types. For fixed-size types,
@@ -680,9 +680,9 @@ PlainObjectBase<Derived>::setOnes(Index rows, Index cols)
*/
template<typename Derived>
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::IdentityReturnType
-MatrixBase<Derived>::Identity(Index rows, Index cols)
+MatrixBase<Derived>::Identity(Index nbRows, Index nbCols)
{
- return DenseBase<Derived>::NullaryExpr(rows, cols, internal::scalar_identity_op<Scalar>());
+ return DenseBase<Derived>::NullaryExpr(nbRows, nbCols, internal::scalar_identity_op<Scalar>());
}
/** \returns an expression of the identity matrix (not necessarily square).
@@ -714,7 +714,7 @@ MatrixBase<Derived>::Identity()
*/
template<typename Derived>
bool MatrixBase<Derived>::isIdentity
-(RealScalar prec) const
+(const RealScalar& prec) const
{
for(Index j = 0; j < cols(); ++j)
{
@@ -776,8 +776,8 @@ EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity()
/** \brief Resizes to the given size, and writes the identity expression (not necessarily square) into *this.
*
- * \param rows the new number of rows
- * \param cols the new number of columns
+ * \param nbRows the new number of rows
+ * \param nbCols the new number of columns
*
* Example: \include Matrix_setIdentity_int_int.cpp
* Output: \verbinclude Matrix_setIdentity_int_int.out
@@ -785,9 +785,9 @@ EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity()
* \sa MatrixBase::setIdentity(), class CwiseNullaryOp, MatrixBase::Identity()
*/
template<typename Derived>
-EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity(Index rows, Index cols)
+EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity(Index nbRows, Index nbCols)
{
- derived().resize(rows, cols);
+ derived().resize(nbRows, nbCols);
return setIdentity();
}
@@ -798,10 +798,10 @@ EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity(Index rows, Index
* \sa MatrixBase::Unit(Index), MatrixBase::UnitX(), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW()
*/
template<typename Derived>
-EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::Unit(Index size, Index i)
+EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::Unit(Index newSize, Index i)
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return BasisReturnType(SquareMatrixType::Identity(size,size), i);
+ return BasisReturnType(SquareMatrixType::Identity(newSize,newSize), i);
}
/** \returns an expression of the i-th unit (basis) vector.
diff --git a/Eigen/src/Core/CwiseUnaryOp.h b/Eigen/src/Core/CwiseUnaryOp.h
index 063355ae5..f2de749f9 100644
--- a/Eigen/src/Core/CwiseUnaryOp.h
+++ b/Eigen/src/Core/CwiseUnaryOp.h
@@ -98,15 +98,15 @@ class CwiseUnaryOpImpl<UnaryOp,XprType,Dense>
typedef typename internal::dense_xpr_base<CwiseUnaryOp<UnaryOp, XprType> >::type Base;
EIGEN_DENSE_PUBLIC_INTERFACE(Derived)
- EIGEN_STRONG_INLINE const Scalar coeff(Index row, Index col) const
+ EIGEN_STRONG_INLINE const Scalar coeff(Index rowId, Index colId) const
{
- return derived().functor()(derived().nestedExpression().coeff(row, col));
+ return derived().functor()(derived().nestedExpression().coeff(rowId, colId));
}
template<int LoadMode>
- EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const
+ EIGEN_STRONG_INLINE PacketScalar packet(Index rowId, Index colId) const
{
- return derived().functor().packetOp(derived().nestedExpression().template packet<LoadMode>(row, col));
+ return derived().functor().packetOp(derived().nestedExpression().template packet<LoadMode>(rowId, colId));
}
EIGEN_STRONG_INLINE const Scalar coeff(Index index) const
diff --git a/Eigen/src/Core/CwiseUnaryView.h b/Eigen/src/Core/CwiseUnaryView.h
index 9a56debaf..b2638d326 100644
--- a/Eigen/src/Core/CwiseUnaryView.h
+++ b/Eigen/src/Core/CwiseUnaryView.h
@@ -44,9 +44,10 @@ struct traits<CwiseUnaryView<ViewOp, MatrixType> >
// "error: no integral type can represent all of the enumerator values
InnerStrideAtCompileTime = MatrixTypeInnerStride == Dynamic
? int(Dynamic)
- : int(MatrixTypeInnerStride)
- * int(sizeof(typename traits<MatrixType>::Scalar) / sizeof(Scalar)),
- OuterStrideAtCompileTime = outer_stride_at_compile_time<MatrixType>::ret
+ : int(MatrixTypeInnerStride) * int(sizeof(typename traits<MatrixType>::Scalar) / sizeof(Scalar)),
+ OuterStrideAtCompileTime = outer_stride_at_compile_time<MatrixType>::ret == Dynamic
+ ? int(Dynamic)
+ : outer_stride_at_compile_time<MatrixType>::ret * int(sizeof(typename traits<MatrixType>::Scalar) / sizeof(Scalar))
};
};
}
@@ -55,8 +56,7 @@ template<typename ViewOp, typename MatrixType, typename StorageKind>
class CwiseUnaryViewImpl;
template<typename ViewOp, typename MatrixType>
-class CwiseUnaryView : internal::no_assignment_operator,
- public CwiseUnaryViewImpl<ViewOp, MatrixType, typename internal::traits<MatrixType>::StorageKind>
+class CwiseUnaryView : public CwiseUnaryViewImpl<ViewOp, MatrixType, typename internal::traits<MatrixType>::StorageKind>
{
public:
@@ -98,7 +98,8 @@ class CwiseUnaryViewImpl<ViewOp,MatrixType,Dense>
typedef typename internal::dense_xpr_base< CwiseUnaryView<ViewOp, MatrixType> >::type Base;
EIGEN_DENSE_PUBLIC_INTERFACE(Derived)
-
+ EIGEN_INHERIT_ASSIGNMENT_OPERATORS(CwiseUnaryViewImpl)
+
inline Scalar* data() { return &coeffRef(0); }
inline const Scalar* data() const { return &coeff(0); }
@@ -109,7 +110,7 @@ class CwiseUnaryViewImpl<ViewOp,MatrixType,Dense>
inline Index outerStride() const
{
- return derived().nestedExpression().outerStride();
+ return derived().nestedExpression().outerStride() * sizeof(typename internal::traits<MatrixType>::Scalar) / sizeof(Scalar);
}
EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const
diff --git a/Eigen/src/Core/DenseBase.h b/Eigen/src/Core/DenseBase.h
index 1cc0314ef..c5800f6c8 100644
--- a/Eigen/src/Core/DenseBase.h
+++ b/Eigen/src/Core/DenseBase.h
@@ -13,6 +13,16 @@
namespace Eigen {
+namespace internal {
+
+// The index type defined by EIGEN_DEFAULT_DENSE_INDEX_TYPE must be a signed type.
+// This dummy function simply aims at checking that at compile time.
+static inline void check_DenseIndex_is_signed() {
+ EIGEN_STATIC_ASSERT(NumTraits<DenseIndex>::IsSigned,THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE);
+}
+
+} // end namespace internal
+
/** \class DenseBase
* \ingroup Core_Module
*
@@ -204,21 +214,21 @@ template<typename Derived> class DenseBase
* Matrix::resize() and Array::resize(). The present method only asserts that the new size equals the old size, and does
* nothing else.
*/
- void resize(Index size)
+ void resize(Index newSize)
{
- EIGEN_ONLY_USED_FOR_DEBUG(size);
- eigen_assert(size == this->size()
+ EIGEN_ONLY_USED_FOR_DEBUG(newSize);
+ eigen_assert(newSize == this->size()
&& "DenseBase::resize() does not actually allow to resize.");
}
/** Only plain matrices/arrays, not expressions, may be resized; therefore the only useful resize methods are
* Matrix::resize() and Array::resize(). The present method only asserts that the new size equals the old size, and does
* nothing else.
*/
- void resize(Index rows, Index cols)
+ void resize(Index nbRows, Index nbCols)
{
- EIGEN_ONLY_USED_FOR_DEBUG(rows);
- EIGEN_ONLY_USED_FOR_DEBUG(cols);
- eigen_assert(rows == this->rows() && cols == this->cols()
+ EIGEN_ONLY_USED_FOR_DEBUG(nbRows);
+ EIGEN_ONLY_USED_FOR_DEBUG(nbCols);
+ eigen_assert(nbRows == this->rows() && nbCols == this->cols()
&& "DenseBase::resize() does not actually allow to resize.");
}
@@ -271,7 +281,7 @@ template<typename Derived> class DenseBase
CommaInitializer<Derived> operator<< (const DenseBase<OtherDerived>& other);
Eigen::Transpose<Derived> transpose();
- typedef const Transpose<const Derived> ConstTransposeReturnType;
+ typedef typename internal::add_const<Transpose<const Derived> >::type ConstTransposeReturnType;
ConstTransposeReturnType transpose() const;
void transposeInPlace();
#ifndef EIGEN_NO_DEBUG
@@ -281,29 +291,6 @@ template<typename Derived> class DenseBase
public:
#endif
- typedef VectorBlock<Derived> SegmentReturnType;
- typedef const VectorBlock<const Derived> ConstSegmentReturnType;
- template<int Size> struct FixedSegmentReturnType { typedef VectorBlock<Derived, Size> Type; };
- template<int Size> struct ConstFixedSegmentReturnType { typedef const VectorBlock<const Derived, Size> Type; };
-
- // Note: The "DenseBase::" prefixes are added to help MSVC9 to match these declarations with the later implementations.
- SegmentReturnType segment(Index start, Index size);
- typename DenseBase::ConstSegmentReturnType segment(Index start, Index size) const;
-
- SegmentReturnType head(Index size);
- typename DenseBase::ConstSegmentReturnType head(Index size) const;
-
- SegmentReturnType tail(Index size);
- typename DenseBase::ConstSegmentReturnType tail(Index size) const;
-
- template<int Size> typename FixedSegmentReturnType<Size>::Type head();
- template<int Size> typename ConstFixedSegmentReturnType<Size>::Type head() const;
-
- template<int Size> typename FixedSegmentReturnType<Size>::Type tail();
- template<int Size> typename ConstFixedSegmentReturnType<Size>::Type tail() const;
-
- template<int Size> typename FixedSegmentReturnType<Size>::Type segment(Index start);
- template<int Size> typename ConstFixedSegmentReturnType<Size>::Type segment(Index start) const;
static const ConstantReturnType
Constant(Index rows, Index cols, const Scalar& value);
@@ -348,17 +335,20 @@ template<typename Derived> class DenseBase
template<typename OtherDerived>
bool isApprox(const DenseBase<OtherDerived>& other,
- RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
+ const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
bool isMuchSmallerThan(const RealScalar& other,
- RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
+ const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
template<typename OtherDerived>
bool isMuchSmallerThan(const DenseBase<OtherDerived>& other,
- RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
+ const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
- bool isApproxToConstant(const Scalar& value, RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
- bool isConstant(const Scalar& value, RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
- bool isZero(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
- bool isOnes(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
+ bool isApproxToConstant(const Scalar& value, const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
+ bool isConstant(const Scalar& value, const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
+ bool isZero(const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
+ bool isOnes(const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
+
+ inline bool hasNaN() const;
+ inline bool allFinite() const;
inline Derived& operator*=(const Scalar& other);
inline Derived& operator/=(const Scalar& other);
@@ -438,8 +428,6 @@ template<typename Derived> class DenseBase
return derived().coeff(0,0);
}
-/////////// Array module ///////////
-
bool all(void) const;
bool any(void) const;
Index count() const;
@@ -465,11 +453,11 @@ template<typename Derived> class DenseBase
template<typename ThenDerived>
inline const Select<Derived,ThenDerived, typename ThenDerived::ConstantReturnType>
- select(const DenseBase<ThenDerived>& thenMatrix, typename ThenDerived::Scalar elseScalar) const;
+ select(const DenseBase<ThenDerived>& thenMatrix, const typename ThenDerived::Scalar& elseScalar) const;
template<typename ElseDerived>
inline const Select<Derived, typename ElseDerived::ConstantReturnType, ElseDerived >
- select(typename ElseDerived::Scalar thenScalar, const DenseBase<ElseDerived>& elseMatrix) const;
+ select(const typename ElseDerived::Scalar& thenScalar, const DenseBase<ElseDerived>& elseMatrix) const;
template<int p> RealScalar lpNorm() const;
diff --git a/Eigen/src/Core/DenseCoeffsBase.h b/Eigen/src/Core/DenseCoeffsBase.h
index 72704c2d7..3c890f215 100644
--- a/Eigen/src/Core/DenseCoeffsBase.h
+++ b/Eigen/src/Core/DenseCoeffsBase.h
@@ -427,22 +427,22 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
template<int StoreMode>
EIGEN_STRONG_INLINE void writePacket
- (Index row, Index col, const typename internal::packet_traits<Scalar>::type& x)
+ (Index row, Index col, const typename internal::packet_traits<Scalar>::type& val)
{
eigen_internal_assert(row >= 0 && row < rows()
&& col >= 0 && col < cols());
- derived().template writePacket<StoreMode>(row,col,x);
+ derived().template writePacket<StoreMode>(row,col,val);
}
/** \internal */
template<int StoreMode>
EIGEN_STRONG_INLINE void writePacketByOuterInner
- (Index outer, Index inner, const typename internal::packet_traits<Scalar>::type& x)
+ (Index outer, Index inner, const typename internal::packet_traits<Scalar>::type& val)
{
writePacket<StoreMode>(rowIndexByOuterInner(outer, inner),
colIndexByOuterInner(outer, inner),
- x);
+ val);
}
/** \internal
@@ -456,10 +456,10 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
*/
template<int StoreMode>
EIGEN_STRONG_INLINE void writePacket
- (Index index, const typename internal::packet_traits<Scalar>::type& x)
+ (Index index, const typename internal::packet_traits<Scalar>::type& val)
{
eigen_internal_assert(index >= 0 && index < size());
- derived().template writePacket<StoreMode>(index,x);
+ derived().template writePacket<StoreMode>(index,val);
}
#ifndef EIGEN_PARSED_BY_DOXYGEN
diff --git a/Eigen/src/Core/DenseStorage.h b/Eigen/src/Core/DenseStorage.h
index 1fc2daf2c..a72738e55 100644
--- a/Eigen/src/Core/DenseStorage.h
+++ b/Eigen/src/Core/DenseStorage.h
@@ -24,6 +24,14 @@ namespace internal {
struct constructor_without_unaligned_array_assert {};
+template<typename T, int Size> void check_static_allocation_size()
+{
+ // if EIGEN_STACK_ALLOCATION_LIMIT is defined to 0, then no limit
+ #if EIGEN_STACK_ALLOCATION_LIMIT
+ EIGEN_STATIC_ASSERT(Size * sizeof(T) <= EIGEN_STACK_ALLOCATION_LIMIT, OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG);
+ #endif
+}
+
/** \internal
* Static array. If the MatrixOrArrayOptions require auto-alignment, the array will be automatically aligned:
* to 16 bytes boundary if the total size is a multiple of 16 bytes.
@@ -35,17 +43,36 @@ template <typename T, int Size, int MatrixOrArrayOptions,
struct plain_array
{
T array[Size];
- plain_array() {}
- plain_array(constructor_without_unaligned_array_assert) {}
+
+ plain_array()
+ {
+ check_static_allocation_size<T,Size>();
+ }
+
+ plain_array(constructor_without_unaligned_array_assert)
+ {
+ check_static_allocation_size<T,Size>();
+ }
};
-#ifdef EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
+#if defined(EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT)
#define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask)
+#elif EIGEN_GNUC_AT_LEAST(4,7)
+ // GCC 4.7 is too aggressive in its optimizations and remove the alignement test based on the fact the array is declared to be aligned.
+ // See this bug report: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53900
+ // Hiding the origin of the array pointer behind a function argument seems to do the trick even if the function is inlined:
+ template<typename PtrType>
+ EIGEN_ALWAYS_INLINE PtrType eigen_unaligned_array_assert_workaround_gcc47(PtrType array) { return array; }
+ #define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask) \
+ eigen_assert((reinterpret_cast<size_t>(eigen_unaligned_array_assert_workaround_gcc47(array)) & sizemask) == 0 \
+ && "this assertion is explained here: " \
+ "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" \
+ " **** READ THIS WEB PAGE !!! ****");
#else
#define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask) \
eigen_assert((reinterpret_cast<size_t>(array) & sizemask) == 0 \
&& "this assertion is explained here: " \
- "http://eigen.tuxfamily.org/dox-devel/TopicUnalignedArrayAssert.html" \
+ "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" \
" **** READ THIS WEB PAGE !!! ****");
#endif
@@ -53,8 +80,17 @@ template <typename T, int Size, int MatrixOrArrayOptions>
struct plain_array<T, Size, MatrixOrArrayOptions, 16>
{
EIGEN_USER_ALIGN16 T array[Size];
- plain_array() { EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(0xf) }
- plain_array(constructor_without_unaligned_array_assert) {}
+
+ plain_array()
+ {
+ EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(0xf);
+ check_static_allocation_size<T,Size>();
+ }
+
+ plain_array(constructor_without_unaligned_array_assert)
+ {
+ check_static_allocation_size<T,Size>();
+ }
};
template <typename T, int MatrixOrArrayOptions, int Alignment>
@@ -86,7 +122,7 @@ template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseSt
{
internal::plain_array<T,Size,_Options> m_data;
public:
- inline explicit DenseStorage() {}
+ inline DenseStorage() {}
inline DenseStorage(internal::constructor_without_unaligned_array_assert)
: m_data(internal::constructor_without_unaligned_array_assert()) {}
inline DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
@@ -103,7 +139,7 @@ template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseSt
template<typename T, int _Rows, int _Cols, int _Options> class DenseStorage<T, 0, _Rows, _Cols, _Options>
{
public:
- inline explicit DenseStorage() {}
+ inline DenseStorage() {}
inline DenseStorage(internal::constructor_without_unaligned_array_assert) {}
inline DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
inline void swap(DenseStorage& ) {}
@@ -132,16 +168,16 @@ template<typename T, int Size, int _Options> class DenseStorage<T, Size, Dynamic
DenseIndex m_rows;
DenseIndex m_cols;
public:
- inline explicit DenseStorage() : m_rows(0), m_cols(0) {}
+ inline DenseStorage() : m_rows(0), m_cols(0) {}
inline DenseStorage(internal::constructor_without_unaligned_array_assert)
: m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0), m_cols(0) {}
- inline DenseStorage(DenseIndex, DenseIndex rows, DenseIndex cols) : m_rows(rows), m_cols(cols) {}
+ inline DenseStorage(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) : m_rows(nbRows), m_cols(nbCols) {}
inline void swap(DenseStorage& other)
{ std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); }
- inline DenseIndex rows(void) const {return m_rows;}
- inline DenseIndex cols(void) const {return m_cols;}
- inline void conservativeResize(DenseIndex, DenseIndex rows, DenseIndex cols) { m_rows = rows; m_cols = cols; }
- inline void resize(DenseIndex, DenseIndex rows, DenseIndex cols) { m_rows = rows; m_cols = cols; }
+ inline DenseIndex rows() const {return m_rows;}
+ inline DenseIndex cols() const {return m_cols;}
+ inline void conservativeResize(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) { m_rows = nbRows; m_cols = nbCols; }
+ inline void resize(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) { m_rows = nbRows; m_cols = nbCols; }
inline const T *data() const { return m_data.array; }
inline T *data() { return m_data.array; }
};
@@ -152,15 +188,15 @@ template<typename T, int Size, int _Cols, int _Options> class DenseStorage<T, Si
internal::plain_array<T,Size,_Options> m_data;
DenseIndex m_rows;
public:
- inline explicit DenseStorage() : m_rows(0) {}
+ inline DenseStorage() : m_rows(0) {}
inline DenseStorage(internal::constructor_without_unaligned_array_assert)
: m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0) {}
- inline DenseStorage(DenseIndex, DenseIndex rows, DenseIndex) : m_rows(rows) {}
+ inline DenseStorage(DenseIndex, DenseIndex nbRows, DenseIndex) : m_rows(nbRows) {}
inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
inline DenseIndex rows(void) const {return m_rows;}
inline DenseIndex cols(void) const {return _Cols;}
- inline void conservativeResize(DenseIndex, DenseIndex rows, DenseIndex) { m_rows = rows; }
- inline void resize(DenseIndex, DenseIndex rows, DenseIndex) { m_rows = rows; }
+ inline void conservativeResize(DenseIndex, DenseIndex nbRows, DenseIndex) { m_rows = nbRows; }
+ inline void resize(DenseIndex, DenseIndex nbRows, DenseIndex) { m_rows = nbRows; }
inline const T *data() const { return m_data.array; }
inline T *data() { return m_data.array; }
};
@@ -171,15 +207,15 @@ template<typename T, int Size, int _Rows, int _Options> class DenseStorage<T, Si
internal::plain_array<T,Size,_Options> m_data;
DenseIndex m_cols;
public:
- inline explicit DenseStorage() : m_cols(0) {}
+ inline DenseStorage() : m_cols(0) {}
inline DenseStorage(internal::constructor_without_unaligned_array_assert)
: m_data(internal::constructor_without_unaligned_array_assert()), m_cols(0) {}
- inline DenseStorage(DenseIndex, DenseIndex, DenseIndex cols) : m_cols(cols) {}
+ inline DenseStorage(DenseIndex, DenseIndex, DenseIndex nbCols) : m_cols(nbCols) {}
inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
inline DenseIndex rows(void) const {return _Rows;}
inline DenseIndex cols(void) const {return m_cols;}
- inline void conservativeResize(DenseIndex, DenseIndex, DenseIndex cols) { m_cols = cols; }
- inline void resize(DenseIndex, DenseIndex, DenseIndex cols) { m_cols = cols; }
+ inline void conservativeResize(DenseIndex, DenseIndex, DenseIndex nbCols) { m_cols = nbCols; }
+ inline void resize(DenseIndex, DenseIndex, DenseIndex nbCols) { m_cols = nbCols; }
inline const T *data() const { return m_data.array; }
inline T *data() { return m_data.array; }
};
@@ -191,24 +227,24 @@ template<typename T, int _Options> class DenseStorage<T, Dynamic, Dynamic, Dynam
DenseIndex m_rows;
DenseIndex m_cols;
public:
- inline explicit DenseStorage() : m_data(0), m_rows(0), m_cols(0) {}
+ inline DenseStorage() : m_data(0), m_rows(0), m_cols(0) {}
inline DenseStorage(internal::constructor_without_unaligned_array_assert)
: m_data(0), m_rows(0), m_cols(0) {}
- inline DenseStorage(DenseIndex size, DenseIndex rows, DenseIndex cols)
- : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(rows), m_cols(cols)
+ inline DenseStorage(DenseIndex size, DenseIndex nbRows, DenseIndex nbCols)
+ : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(nbRows), m_cols(nbCols)
{ EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
inline ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, m_rows*m_cols); }
inline void swap(DenseStorage& other)
{ std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); }
inline DenseIndex rows(void) const {return m_rows;}
inline DenseIndex cols(void) const {return m_cols;}
- inline void conservativeResize(DenseIndex size, DenseIndex rows, DenseIndex cols)
+ inline void conservativeResize(DenseIndex size, DenseIndex nbRows, DenseIndex nbCols)
{
m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*m_cols);
- m_rows = rows;
- m_cols = cols;
+ m_rows = nbRows;
+ m_cols = nbCols;
}
- void resize(DenseIndex size, DenseIndex rows, DenseIndex cols)
+ void resize(DenseIndex size, DenseIndex nbRows, DenseIndex nbCols)
{
if(size != m_rows*m_cols)
{
@@ -219,8 +255,8 @@ template<typename T, int _Options> class DenseStorage<T, Dynamic, Dynamic, Dynam
m_data = 0;
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
}
- m_rows = rows;
- m_cols = cols;
+ m_rows = nbRows;
+ m_cols = nbCols;
}
inline const T *data() const { return m_data; }
inline T *data() { return m_data; }
@@ -232,20 +268,20 @@ template<typename T, int _Rows, int _Options> class DenseStorage<T, Dynamic, _Ro
T *m_data;
DenseIndex m_cols;
public:
- inline explicit DenseStorage() : m_data(0), m_cols(0) {}
+ inline DenseStorage() : m_data(0), m_cols(0) {}
inline DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_cols(0) {}
- inline DenseStorage(DenseIndex size, DenseIndex, DenseIndex cols) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_cols(cols)
+ inline DenseStorage(DenseIndex size, DenseIndex, DenseIndex nbCols) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_cols(nbCols)
{ EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
inline ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Rows*m_cols); }
inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
static inline DenseIndex rows(void) {return _Rows;}
inline DenseIndex cols(void) const {return m_cols;}
- inline void conservativeResize(DenseIndex size, DenseIndex, DenseIndex cols)
+ inline void conservativeResize(DenseIndex size, DenseIndex, DenseIndex nbCols)
{
m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, _Rows*m_cols);
- m_cols = cols;
+ m_cols = nbCols;
}
- EIGEN_STRONG_INLINE void resize(DenseIndex size, DenseIndex, DenseIndex cols)
+ EIGEN_STRONG_INLINE void resize(DenseIndex size, DenseIndex, DenseIndex nbCols)
{
if(size != _Rows*m_cols)
{
@@ -256,7 +292,7 @@ template<typename T, int _Rows, int _Options> class DenseStorage<T, Dynamic, _Ro
m_data = 0;
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
}
- m_cols = cols;
+ m_cols = nbCols;
}
inline const T *data() const { return m_data; }
inline T *data() { return m_data; }
@@ -268,20 +304,20 @@ template<typename T, int _Cols, int _Options> class DenseStorage<T, Dynamic, Dyn
T *m_data;
DenseIndex m_rows;
public:
- inline explicit DenseStorage() : m_data(0), m_rows(0) {}
+ inline DenseStorage() : m_data(0), m_rows(0) {}
inline DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_rows(0) {}
- inline DenseStorage(DenseIndex size, DenseIndex rows, DenseIndex) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(rows)
+ inline DenseStorage(DenseIndex size, DenseIndex nbRows, DenseIndex) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(nbRows)
{ EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
inline ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Cols*m_rows); }
inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
inline DenseIndex rows(void) const {return m_rows;}
static inline DenseIndex cols(void) {return _Cols;}
- inline void conservativeResize(DenseIndex size, DenseIndex rows, DenseIndex)
+ inline void conservativeResize(DenseIndex size, DenseIndex nbRows, DenseIndex)
{
m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*_Cols);
- m_rows = rows;
+ m_rows = nbRows;
}
- EIGEN_STRONG_INLINE void resize(DenseIndex size, DenseIndex rows, DenseIndex)
+ EIGEN_STRONG_INLINE void resize(DenseIndex size, DenseIndex nbRows, DenseIndex)
{
if(size != m_rows*_Cols)
{
@@ -292,7 +328,7 @@ template<typename T, int _Cols, int _Options> class DenseStorage<T, Dynamic, Dyn
m_data = 0;
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
}
- m_rows = rows;
+ m_rows = nbRows;
}
inline const T *data() const { return m_data; }
inline T *data() { return m_data; }
diff --git a/Eigen/src/Core/Diagonal.h b/Eigen/src/Core/Diagonal.h
index 16261968a..aab8007b3 100644
--- a/Eigen/src/Core/Diagonal.h
+++ b/Eigen/src/Core/Diagonal.h
@@ -41,12 +41,12 @@ struct traits<Diagonal<MatrixType,DiagIndex> >
typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested;
typedef typename MatrixType::StorageKind StorageKind;
enum {
- RowsAtCompileTime = (int(DiagIndex) == Dynamic || int(MatrixType::SizeAtCompileTime) == Dynamic) ? Dynamic
- : (EIGEN_PLAIN_ENUM_MIN(MatrixType::RowsAtCompileTime - EIGEN_PLAIN_ENUM_MAX(-DiagIndex, 0),
- MatrixType::ColsAtCompileTime - EIGEN_PLAIN_ENUM_MAX( DiagIndex, 0))),
+ RowsAtCompileTime = (int(DiagIndex) == DynamicIndex || int(MatrixType::SizeAtCompileTime) == Dynamic) ? Dynamic
+ : (EIGEN_PLAIN_ENUM_MIN(MatrixType::RowsAtCompileTime - EIGEN_PLAIN_ENUM_MAX(-DiagIndex, 0),
+ MatrixType::ColsAtCompileTime - EIGEN_PLAIN_ENUM_MAX( DiagIndex, 0))),
ColsAtCompileTime = 1,
MaxRowsAtCompileTime = int(MatrixType::MaxSizeAtCompileTime) == Dynamic ? Dynamic
- : DiagIndex == Dynamic ? EIGEN_SIZE_MIN_PREFER_FIXED(MatrixType::MaxRowsAtCompileTime,
+ : DiagIndex == DynamicIndex ? EIGEN_SIZE_MIN_PREFER_FIXED(MatrixType::MaxRowsAtCompileTime,
MatrixType::MaxColsAtCompileTime)
: (EIGEN_PLAIN_ENUM_MIN(MatrixType::MaxRowsAtCompileTime - EIGEN_PLAIN_ENUM_MAX(-DiagIndex, 0),
MatrixType::MaxColsAtCompileTime - EIGEN_PLAIN_ENUM_MAX( DiagIndex, 0))),
@@ -61,20 +61,21 @@ struct traits<Diagonal<MatrixType,DiagIndex> >
};
}
-template<typename MatrixType, int DiagIndex> class Diagonal
- : public internal::dense_xpr_base< Diagonal<MatrixType,DiagIndex> >::type
+template<typename MatrixType, int _DiagIndex> class Diagonal
+ : public internal::dense_xpr_base< Diagonal<MatrixType,_DiagIndex> >::type
{
public:
+ enum { DiagIndex = _DiagIndex };
typedef typename internal::dense_xpr_base<Diagonal>::type Base;
EIGEN_DENSE_PUBLIC_INTERFACE(Diagonal)
- inline Diagonal(MatrixType& matrix, Index index = DiagIndex) : m_matrix(matrix), m_index(index) {}
+ inline Diagonal(MatrixType& matrix, Index a_index = DiagIndex) : m_matrix(matrix), m_index(a_index) {}
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Diagonal)
inline Index rows() const
- { return m_index.value()<0 ? (std::min)(m_matrix.cols(),m_matrix.rows()+m_index.value()) : (std::min)(m_matrix.rows(),m_matrix.cols()-m_index.value()); }
+ { return m_index.value()<0 ? (std::min<Index>)(m_matrix.cols(),m_matrix.rows()+m_index.value()) : (std::min<Index>)(m_matrix.rows(),m_matrix.cols()-m_index.value()); }
inline Index cols() const { return 1; }
@@ -113,20 +114,20 @@ template<typename MatrixType, int DiagIndex> class Diagonal
return m_matrix.coeff(row+rowOffset(), row+colOffset());
}
- inline Scalar& coeffRef(Index index)
+ inline Scalar& coeffRef(Index idx)
{
EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
- return m_matrix.const_cast_derived().coeffRef(index+rowOffset(), index+colOffset());
+ return m_matrix.const_cast_derived().coeffRef(idx+rowOffset(), idx+colOffset());
}
- inline const Scalar& coeffRef(Index index) const
+ inline const Scalar& coeffRef(Index idx) const
{
- return m_matrix.const_cast_derived().coeffRef(index+rowOffset(), index+colOffset());
+ return m_matrix.const_cast_derived().coeffRef(idx+rowOffset(), idx+colOffset());
}
- inline CoeffReturnType coeff(Index index) const
+ inline CoeffReturnType coeff(Index idx) const
{
- return m_matrix.coeff(index+rowOffset(), index+colOffset());
+ return m_matrix.coeff(idx+rowOffset(), idx+colOffset());
}
const typename internal::remove_all<typename MatrixType::Nested>::type&
@@ -142,7 +143,7 @@ template<typename MatrixType, int DiagIndex> class Diagonal
protected:
typename MatrixType::Nested m_matrix;
- const internal::variable_if_dynamic<Index, DiagIndex> m_index;
+ const internal::variable_if_dynamicindex<Index, DiagIndex> m_index;
private:
// some compilers may fail to optimize std::max etc in case of compile-time constants...
@@ -171,7 +172,7 @@ MatrixBase<Derived>::diagonal()
/** This is the const version of diagonal(). */
template<typename Derived>
-inline const typename MatrixBase<Derived>::ConstDiagonalReturnType
+inline typename MatrixBase<Derived>::ConstDiagonalReturnType
MatrixBase<Derived>::diagonal() const
{
return ConstDiagonalReturnType(derived());
@@ -189,18 +190,18 @@ MatrixBase<Derived>::diagonal() const
*
* \sa MatrixBase::diagonal(), class Diagonal */
template<typename Derived>
-inline typename MatrixBase<Derived>::template DiagonalIndexReturnType<Dynamic>::Type
+inline typename MatrixBase<Derived>::template DiagonalIndexReturnType<DynamicIndex>::Type
MatrixBase<Derived>::diagonal(Index index)
{
- return typename DiagonalIndexReturnType<Dynamic>::Type(derived(), index);
+ return typename DiagonalIndexReturnType<DynamicIndex>::Type(derived(), index);
}
/** This is the const version of diagonal(Index). */
template<typename Derived>
-inline typename MatrixBase<Derived>::template ConstDiagonalIndexReturnType<Dynamic>::Type
+inline typename MatrixBase<Derived>::template ConstDiagonalIndexReturnType<DynamicIndex>::Type
MatrixBase<Derived>::diagonal(Index index) const
{
- return typename ConstDiagonalIndexReturnType<Dynamic>::Type(derived(), index);
+ return typename ConstDiagonalIndexReturnType<DynamicIndex>::Type(derived(), index);
}
/** \returns an expression of the \a DiagIndex-th sub or super diagonal of the matrix \c *this
diff --git a/Eigen/src/Core/DiagonalMatrix.h b/Eigen/src/Core/DiagonalMatrix.h
index 88190da68..e6c220f41 100644
--- a/Eigen/src/Core/DiagonalMatrix.h
+++ b/Eigen/src/Core/DiagonalMatrix.h
@@ -20,6 +20,7 @@ class DiagonalBase : public EigenBase<Derived>
public:
typedef typename internal::traits<Derived>::DiagonalVectorType DiagonalVectorType;
typedef typename DiagonalVectorType::Scalar Scalar;
+ typedef typename DiagonalVectorType::RealScalar RealScalar;
typedef typename internal::traits<Derived>::StorageKind StorageKind;
typedef typename internal::traits<Derived>::Index Index;
@@ -55,9 +56,14 @@ class DiagonalBase : public EigenBase<Derived>
inline Index rows() const { return diagonal().size(); }
inline Index cols() const { return diagonal().size(); }
+ /** \returns the diagonal matrix product of \c *this by the matrix \a matrix.
+ */
template<typename MatrixDerived>
const DiagonalProduct<MatrixDerived, Derived, OnTheLeft>
- operator*(const MatrixBase<MatrixDerived> &matrix) const;
+ operator*(const MatrixBase<MatrixDerived> &matrix) const
+ {
+ return DiagonalProduct<MatrixDerived, Derived, OnTheLeft>(matrix.derived(), derived());
+ }
inline const DiagonalWrapper<const CwiseUnaryOp<internal::scalar_inverse_op<Scalar>, const DiagonalVectorType> >
inverse() const
@@ -65,6 +71,17 @@ class DiagonalBase : public EigenBase<Derived>
return diagonal().cwiseInverse();
}
+ inline const DiagonalWrapper<const CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const DiagonalVectorType> >
+ operator*(const Scalar& scalar) const
+ {
+ return diagonal() * scalar;
+ }
+ friend inline const DiagonalWrapper<const CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const DiagonalVectorType> >
+ operator*(const Scalar& scalar, const DiagonalBase& other)
+ {
+ return other.diagonal() * scalar;
+ }
+
#ifdef EIGEN2_SUPPORT
template<typename OtherDerived>
bool isApprox(const DiagonalBase<OtherDerived>& other, typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) const
@@ -238,7 +255,7 @@ class DiagonalWrapper
#endif
/** Constructor from expression of diagonal coefficients to wrap. */
- inline DiagonalWrapper(DiagonalVectorType& diagonal) : m_diagonal(diagonal) {}
+ inline DiagonalWrapper(DiagonalVectorType& a_diagonal) : m_diagonal(a_diagonal) {}
/** \returns a const reference to the wrapped expression of diagonal coefficients. */
const DiagonalVectorType& diagonal() const { return m_diagonal; }
@@ -272,13 +289,14 @@ MatrixBase<Derived>::asDiagonal() const
* \sa asDiagonal()
*/
template<typename Derived>
-bool MatrixBase<Derived>::isDiagonal(RealScalar prec) const
+bool MatrixBase<Derived>::isDiagonal(const RealScalar& prec) const
{
+ using std::abs;
if(cols() != rows()) return false;
RealScalar maxAbsOnDiagonal = static_cast<RealScalar>(-1);
for(Index j = 0; j < cols(); ++j)
{
- RealScalar absOnDiagonal = internal::abs(coeff(j,j));
+ RealScalar absOnDiagonal = abs(coeff(j,j));
if(absOnDiagonal > maxAbsOnDiagonal) maxAbsOnDiagonal = absOnDiagonal;
}
for(Index j = 0; j < cols(); ++j)
diff --git a/Eigen/src/Core/DiagonalProduct.h b/Eigen/src/Core/DiagonalProduct.h
index 598c6b3e1..c03a0c2e1 100644
--- a/Eigen/src/Core/DiagonalProduct.h
+++ b/Eigen/src/Core/DiagonalProduct.h
@@ -26,14 +26,15 @@ struct traits<DiagonalProduct<MatrixType, DiagonalType, ProductOrder> >
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
_StorageOrder = MatrixType::Flags & RowMajorBit ? RowMajor : ColMajor,
- _PacketOnDiag = !((int(_StorageOrder) == RowMajor && int(ProductOrder) == OnTheLeft)
- ||(int(_StorageOrder) == ColMajor && int(ProductOrder) == OnTheRight)),
+ _ScalarAccessOnDiag = !((int(_StorageOrder) == ColMajor && int(ProductOrder) == OnTheLeft)
+ ||(int(_StorageOrder) == RowMajor && int(ProductOrder) == OnTheRight)),
_SameTypes = is_same<typename MatrixType::Scalar, typename DiagonalType::Scalar>::value,
// FIXME currently we need same types, but in the future the next rule should be the one
- //_Vectorizable = bool(int(MatrixType::Flags)&PacketAccessBit) && ((!_PacketOnDiag) || (_SameTypes && bool(int(DiagonalType::Flags)&PacketAccessBit))),
- _Vectorizable = bool(int(MatrixType::Flags)&PacketAccessBit) && _SameTypes && ((!_PacketOnDiag) || (bool(int(DiagonalType::Flags)&PacketAccessBit))),
+ //_Vectorizable = bool(int(MatrixType::Flags)&PacketAccessBit) && ((!_PacketOnDiag) || (_SameTypes && bool(int(DiagonalType::DiagonalVectorType::Flags)&PacketAccessBit))),
+ _Vectorizable = bool(int(MatrixType::Flags)&PacketAccessBit) && _SameTypes && (_ScalarAccessOnDiag || (bool(int(DiagonalType::DiagonalVectorType::Flags)&PacketAccessBit))),
+ _LinearAccessMask = (RowsAtCompileTime==1 || ColsAtCompileTime==1) ? LinearAccessBit : 0,
- Flags = (HereditaryBits & (unsigned int)(MatrixType::Flags)) | (_Vectorizable ? PacketAccessBit : 0),
+ Flags = ((HereditaryBits|_LinearAccessMask) & (unsigned int)(MatrixType::Flags)) | (_Vectorizable ? PacketAccessBit : 0) | AlignedBit,//(int(MatrixType::Flags)&int(DiagonalType::DiagonalVectorType::Flags)&AlignedBit),
CoeffReadCost = NumTraits<Scalar>::MulCost + MatrixType::CoeffReadCost + DiagonalType::DiagonalVectorType::CoeffReadCost
};
};
@@ -54,13 +55,21 @@ class DiagonalProduct : internal::no_assignment_operator,
eigen_assert(diagonal.diagonal().size() == (ProductOrder == OnTheLeft ? matrix.rows() : matrix.cols()));
}
- inline Index rows() const { return m_matrix.rows(); }
- inline Index cols() const { return m_matrix.cols(); }
+ EIGEN_STRONG_INLINE Index rows() const { return m_matrix.rows(); }
+ EIGEN_STRONG_INLINE Index cols() const { return m_matrix.cols(); }
- const Scalar coeff(Index row, Index col) const
+ EIGEN_STRONG_INLINE const Scalar coeff(Index row, Index col) const
{
return m_diagonal.diagonal().coeff(ProductOrder == OnTheLeft ? row : col) * m_matrix.coeff(row, col);
}
+
+ EIGEN_STRONG_INLINE const Scalar coeff(Index idx) const
+ {
+ enum {
+ StorageOrder = int(MatrixType::Flags) & RowMajorBit ? RowMajor : ColMajor
+ };
+ return coeff(int(StorageOrder)==ColMajor?idx:0,int(StorageOrder)==ColMajor?0:idx);
+ }
template<int LoadMode>
EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const
@@ -69,11 +78,19 @@ class DiagonalProduct : internal::no_assignment_operator,
StorageOrder = Flags & RowMajorBit ? RowMajor : ColMajor
};
const Index indexInDiagonalVector = ProductOrder == OnTheLeft ? row : col;
-
return packet_impl<LoadMode>(row,col,indexInDiagonalVector,typename internal::conditional<
((int(StorageOrder) == RowMajor && int(ProductOrder) == OnTheLeft)
||(int(StorageOrder) == ColMajor && int(ProductOrder) == OnTheRight)), internal::true_type, internal::false_type>::type());
}
+
+ template<int LoadMode>
+ EIGEN_STRONG_INLINE PacketScalar packet(Index idx) const
+ {
+ enum {
+ StorageOrder = int(MatrixType::Flags) & RowMajorBit ? RowMajor : ColMajor
+ };
+ return packet<LoadMode>(int(StorageOrder)==ColMajor?idx:0,int(StorageOrder)==ColMajor?0:idx);
+ }
protected:
template<int LoadMode>
@@ -88,7 +105,7 @@ class DiagonalProduct : internal::no_assignment_operator,
{
enum {
InnerSize = (MatrixType::Flags & RowMajorBit) ? MatrixType::ColsAtCompileTime : MatrixType::RowsAtCompileTime,
- DiagonalVectorPacketLoadMode = (LoadMode == Aligned && ((InnerSize%16) == 0)) ? Aligned : Unaligned
+ DiagonalVectorPacketLoadMode = (LoadMode == Aligned && (((InnerSize%16) == 0) || (int(DiagonalType::DiagonalVectorType::Flags)&AlignedBit)==AlignedBit) ? Aligned : Unaligned)
};
return internal::pmul(m_matrix.template packet<LoadMode>(row, col),
m_diagonal.diagonal().template packet<DiagonalVectorPacketLoadMode>(id));
@@ -103,19 +120,9 @@ class DiagonalProduct : internal::no_assignment_operator,
template<typename Derived>
template<typename DiagonalDerived>
inline const DiagonalProduct<Derived, DiagonalDerived, OnTheRight>
-MatrixBase<Derived>::operator*(const DiagonalBase<DiagonalDerived> &diagonal) const
-{
- return DiagonalProduct<Derived, DiagonalDerived, OnTheRight>(derived(), diagonal.derived());
-}
-
-/** \returns the diagonal matrix product of \c *this by the matrix \a matrix.
- */
-template<typename DiagonalDerived>
-template<typename MatrixDerived>
-inline const DiagonalProduct<MatrixDerived, DiagonalDerived, OnTheLeft>
-DiagonalBase<DiagonalDerived>::operator*(const MatrixBase<MatrixDerived> &matrix) const
+MatrixBase<Derived>::operator*(const DiagonalBase<DiagonalDerived> &a_diagonal) const
{
- return DiagonalProduct<MatrixDerived, DiagonalDerived, OnTheLeft>(matrix.derived(), derived());
+ return DiagonalProduct<Derived, DiagonalDerived, OnTheRight>(derived(), a_diagonal.derived());
}
} // end namespace Eigen
diff --git a/Eigen/src/Core/Dot.h b/Eigen/src/Core/Dot.h
index ae9274e36..9d7651f1f 100644
--- a/Eigen/src/Core/Dot.h
+++ b/Eigen/src/Core/Dot.h
@@ -112,7 +112,7 @@ MatrixBase<Derived>::eigen2_dot(const MatrixBase<OtherDerived>& other) const
template<typename Derived>
EIGEN_STRONG_INLINE typename NumTraits<typename internal::traits<Derived>::Scalar>::Real MatrixBase<Derived>::squaredNorm() const
{
- return internal::real((*this).cwiseAbs2().sum());
+ return numext::real((*this).cwiseAbs2().sum());
}
/** \returns, for vectors, the \em l2 norm of \c *this, and for matrices the Frobenius norm.
@@ -124,7 +124,8 @@ EIGEN_STRONG_INLINE typename NumTraits<typename internal::traits<Derived>::Scala
template<typename Derived>
inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real MatrixBase<Derived>::norm() const
{
- return internal::sqrt(squaredNorm());
+ using std::sqrt;
+ return sqrt(squaredNorm());
}
/** \returns an expression of the quotient of *this by its own norm.
@@ -165,6 +166,7 @@ struct lpNorm_selector
typedef typename NumTraits<typename traits<Derived>::Scalar>::Real RealScalar;
static inline RealScalar run(const MatrixBase<Derived>& m)
{
+ using std::pow;
return pow(m.cwiseAbs().array().pow(p).sum(), RealScalar(1)/p);
}
};
@@ -223,11 +225,11 @@ MatrixBase<Derived>::lpNorm() const
template<typename Derived>
template<typename OtherDerived>
bool MatrixBase<Derived>::isOrthogonal
-(const MatrixBase<OtherDerived>& other, RealScalar prec) const
+(const MatrixBase<OtherDerived>& other, const RealScalar& prec) const
{
typename internal::nested<Derived,2>::type nested(derived());
typename internal::nested<OtherDerived,2>::type otherNested(other.derived());
- return internal::abs2(nested.dot(otherNested)) <= prec * prec * nested.squaredNorm() * otherNested.squaredNorm();
+ return numext::abs2(nested.dot(otherNested)) <= prec * prec * nested.squaredNorm() * otherNested.squaredNorm();
}
/** \returns true if *this is approximately an unitary matrix,
@@ -242,7 +244,7 @@ bool MatrixBase<Derived>::isOrthogonal
* Output: \verbinclude MatrixBase_isUnitary.out
*/
template<typename Derived>
-bool MatrixBase<Derived>::isUnitary(RealScalar prec) const
+bool MatrixBase<Derived>::isUnitary(const RealScalar& prec) const
{
typename Derived::Nested nested(derived());
for(Index i = 0; i < cols(); ++i)
diff --git a/Eigen/src/Core/EigenBase.h b/Eigen/src/Core/EigenBase.h
index 0bbd28bec..fadb45852 100644
--- a/Eigen/src/Core/EigenBase.h
+++ b/Eigen/src/Core/EigenBase.h
@@ -126,35 +126,6 @@ Derived& DenseBase<Derived>::operator-=(const EigenBase<OtherDerived> &other)
return derived();
}
-/** replaces \c *this by \c *this * \a other.
- *
- * \returns a reference to \c *this
- */
-template<typename Derived>
-template<typename OtherDerived>
-inline Derived&
-MatrixBase<Derived>::operator*=(const EigenBase<OtherDerived> &other)
-{
- other.derived().applyThisOnTheRight(derived());
- return derived();
-}
-
-/** replaces \c *this by \c *this * \a other. It is equivalent to MatrixBase::operator*=() */
-template<typename Derived>
-template<typename OtherDerived>
-inline void MatrixBase<Derived>::applyOnTheRight(const EigenBase<OtherDerived> &other)
-{
- other.derived().applyThisOnTheRight(derived());
-}
-
-/** replaces \c *this by \c *this * \a other. */
-template<typename Derived>
-template<typename OtherDerived>
-inline void MatrixBase<Derived>::applyOnTheLeft(const EigenBase<OtherDerived> &other)
-{
- other.derived().applyThisOnTheLeft(derived());
-}
-
} // end namespace Eigen
#endif // EIGEN_EIGENBASE_H
diff --git a/Eigen/src/Core/Functors.h b/Eigen/src/Core/Functors.h
index 278c46c6b..b08b967ff 100644
--- a/Eigen/src/Core/Functors.h
+++ b/Eigen/src/Core/Functors.h
@@ -154,6 +154,7 @@ template<typename Scalar> struct scalar_hypot_op {
{
using std::max;
using std::min;
+ using std::sqrt;
Scalar p = (max)(_x, _y);
Scalar q = (min)(_x, _y);
Scalar qp = q/p;
@@ -170,7 +171,7 @@ struct functor_traits<scalar_hypot_op<Scalar> > {
*/
template<typename Scalar, typename OtherScalar> struct scalar_binary_pow_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_binary_pow_op)
- inline Scalar operator() (const Scalar& a, const OtherScalar& b) const { return internal::pow(a, b); }
+ inline Scalar operator() (const Scalar& a, const OtherScalar& b) const { return numext::pow(a, b); }
};
template<typename Scalar, typename OtherScalar>
struct functor_traits<scalar_binary_pow_op<Scalar,OtherScalar> > {
@@ -204,21 +205,28 @@ struct functor_traits<scalar_difference_op<Scalar> > {
*
* \sa class CwiseBinaryOp, Cwise::operator/()
*/
-template<typename Scalar> struct scalar_quotient_op {
+template<typename LhsScalar,typename RhsScalar> struct scalar_quotient_op {
+ enum {
+ // TODO vectorize mixed product
+ Vectorizable = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasDiv && packet_traits<RhsScalar>::HasDiv
+ };
+ typedef typename scalar_product_traits<LhsScalar,RhsScalar>::ReturnType result_type;
EIGEN_EMPTY_STRUCT_CTOR(scalar_quotient_op)
- EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a / b; }
+ EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a / b; }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
{ return internal::pdiv(a,b); }
};
-template<typename Scalar>
-struct functor_traits<scalar_quotient_op<Scalar> > {
+template<typename LhsScalar,typename RhsScalar>
+struct functor_traits<scalar_quotient_op<LhsScalar,RhsScalar> > {
enum {
- Cost = 2 * NumTraits<Scalar>::MulCost,
- PacketAccess = packet_traits<Scalar>::HasDiv
+ Cost = (NumTraits<LhsScalar>::MulCost + NumTraits<RhsScalar>::MulCost), // rough estimate!
+ PacketAccess = scalar_quotient_op<LhsScalar,RhsScalar>::Vectorizable
};
};
+
+
/** \internal
* \brief Template functor to compute the and of two booleans
*
@@ -280,7 +288,7 @@ struct functor_traits<scalar_opposite_op<Scalar> >
template<typename Scalar> struct scalar_abs_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_abs_op)
typedef typename NumTraits<Scalar>::Real result_type;
- EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return internal::abs(a); }
+ EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { using std::abs; return abs(a); }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
{ return internal::pabs(a); }
@@ -302,7 +310,7 @@ struct functor_traits<scalar_abs_op<Scalar> >
template<typename Scalar> struct scalar_abs2_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_abs2_op)
typedef typename NumTraits<Scalar>::Real result_type;
- EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return internal::abs2(a); }
+ EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return numext::abs2(a); }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
{ return internal::pmul(a,a); }
@@ -318,7 +326,7 @@ struct functor_traits<scalar_abs2_op<Scalar> >
*/
template<typename Scalar> struct scalar_conjugate_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_conjugate_op)
- EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return internal::conj(a); }
+ EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { using numext::conj; return conj(a); }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const { return internal::pconj(a); }
};
@@ -355,7 +363,7 @@ template<typename Scalar>
struct scalar_real_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_real_op)
typedef typename NumTraits<Scalar>::Real result_type;
- EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return internal::real(a); }
+ EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return numext::real(a); }
};
template<typename Scalar>
struct functor_traits<scalar_real_op<Scalar> >
@@ -370,7 +378,7 @@ template<typename Scalar>
struct scalar_imag_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_op)
typedef typename NumTraits<Scalar>::Real result_type;
- EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return internal::imag(a); }
+ EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return numext::imag(a); }
};
template<typename Scalar>
struct functor_traits<scalar_imag_op<Scalar> >
@@ -385,7 +393,7 @@ template<typename Scalar>
struct scalar_real_ref_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_real_ref_op)
typedef typename NumTraits<Scalar>::Real result_type;
- EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return internal::real_ref(*const_cast<Scalar*>(&a)); }
+ EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return numext::real_ref(*const_cast<Scalar*>(&a)); }
};
template<typename Scalar>
struct functor_traits<scalar_real_ref_op<Scalar> >
@@ -400,7 +408,7 @@ template<typename Scalar>
struct scalar_imag_ref_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_ref_op)
typedef typename NumTraits<Scalar>::Real result_type;
- EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return internal::imag_ref(*const_cast<Scalar*>(&a)); }
+ EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return numext::imag_ref(*const_cast<Scalar*>(&a)); }
};
template<typename Scalar>
struct functor_traits<scalar_imag_ref_op<Scalar> >
@@ -414,7 +422,7 @@ struct functor_traits<scalar_imag_ref_op<Scalar> >
*/
template<typename Scalar> struct scalar_exp_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_exp_op)
- inline const Scalar operator() (const Scalar& a) const { return internal::exp(a); }
+ inline const Scalar operator() (const Scalar& a) const { using std::exp; return exp(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::pexp(a); }
};
@@ -430,7 +438,7 @@ struct functor_traits<scalar_exp_op<Scalar> >
*/
template<typename Scalar> struct scalar_log_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_log_op)
- inline const Scalar operator() (const Scalar& a) const { return internal::log(a); }
+ inline const Scalar operator() (const Scalar& a) const { using std::log; return log(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::plog(a); }
};
@@ -447,7 +455,7 @@ struct functor_traits<scalar_log_op<Scalar> >
* indeed it seems better to declare m_other as a Packet and do the pset1() once
* in the constructor. However, in practice:
* - GCC does not like m_other as a Packet and generate a load every time it needs it
- * - on the other hand GCC is able to moves the pset1() away the loop :)
+ * - on the other hand GCC is able to moves the pset1() outside the loop :)
* - simpler code ;)
* (ICC and gcc 4.4 seems to perform well in both cases, the issue is visible with y = a*x + b*y)
*/
@@ -478,33 +486,6 @@ template<typename Scalar1,typename Scalar2>
struct functor_traits<scalar_multiple2_op<Scalar1,Scalar2> >
{ enum { Cost = NumTraits<Scalar1>::MulCost, PacketAccess = false }; };
-template<typename Scalar, bool IsInteger>
-struct scalar_quotient1_impl {
- typedef typename packet_traits<Scalar>::type Packet;
- // FIXME default copy constructors seems bugged with std::complex<>
- EIGEN_STRONG_INLINE scalar_quotient1_impl(const scalar_quotient1_impl& other) : m_other(other.m_other) { }
- EIGEN_STRONG_INLINE scalar_quotient1_impl(const Scalar& other) : m_other(static_cast<Scalar>(1) / other) {}
- EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a * m_other; }
- EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
- { return internal::pmul(a, pset1<Packet>(m_other)); }
- const Scalar m_other;
-};
-template<typename Scalar>
-struct functor_traits<scalar_quotient1_impl<Scalar,false> >
-{ enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
-
-template<typename Scalar>
-struct scalar_quotient1_impl<Scalar,true> {
- // FIXME default copy constructors seems bugged with std::complex<>
- EIGEN_STRONG_INLINE scalar_quotient1_impl(const scalar_quotient1_impl& other) : m_other(other.m_other) { }
- EIGEN_STRONG_INLINE scalar_quotient1_impl(const Scalar& other) : m_other(other) {}
- EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a / m_other; }
- typename add_const_on_value_type<typename NumTraits<Scalar>::Nested>::type m_other;
-};
-template<typename Scalar>
-struct functor_traits<scalar_quotient1_impl<Scalar,true> >
-{ enum { Cost = 2 * NumTraits<Scalar>::MulCost, PacketAccess = false }; };
-
/** \internal
* \brief Template functor to divide a scalar by a fixed other one
*
@@ -514,14 +495,19 @@ struct functor_traits<scalar_quotient1_impl<Scalar,true> >
* \sa class CwiseUnaryOp, MatrixBase::operator/
*/
template<typename Scalar>
-struct scalar_quotient1_op : scalar_quotient1_impl<Scalar, NumTraits<Scalar>::IsInteger > {
- EIGEN_STRONG_INLINE scalar_quotient1_op(const Scalar& other)
- : scalar_quotient1_impl<Scalar, NumTraits<Scalar>::IsInteger >(other) {}
+struct scalar_quotient1_op {
+ typedef typename packet_traits<Scalar>::type Packet;
+ // FIXME default copy constructors seems bugged with std::complex<>
+ EIGEN_STRONG_INLINE scalar_quotient1_op(const scalar_quotient1_op& other) : m_other(other.m_other) { }
+ EIGEN_STRONG_INLINE scalar_quotient1_op(const Scalar& other) : m_other(other) {}
+ EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a / m_other; }
+ EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
+ { return internal::pdiv(a, pset1<Packet>(m_other)); }
+ typename add_const_on_value_type<typename NumTraits<Scalar>::Nested>::type m_other;
};
template<typename Scalar>
struct functor_traits<scalar_quotient1_op<Scalar> >
-: functor_traits<scalar_quotient1_impl<Scalar, NumTraits<Scalar>::IsInteger> >
-{};
+{ enum { Cost = 2 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasDiv }; };
// nullary functors
@@ -555,20 +541,28 @@ template <typename Scalar, bool RandomAccess> struct linspaced_op_impl;
// linear access for packet ops:
// 1) initialization
// base = [low, ..., low] + ([step, ..., step] * [-size, ..., 0])
-// 2) each step
+// 2) each step (where size is 1 for coeff access or PacketSize for packet access)
// base += [size*step, ..., size*step]
+//
+// TODO: Perhaps it's better to initialize lazily (so not in the constructor but in packetOp)
+// in order to avoid the padd() in operator() ?
template <typename Scalar>
struct linspaced_op_impl<Scalar,false>
{
typedef typename packet_traits<Scalar>::type Packet;
- linspaced_op_impl(Scalar low, Scalar step) :
+ linspaced_op_impl(const Scalar& low, const Scalar& step) :
m_low(low), m_step(step),
m_packetStep(pset1<Packet>(packet_traits<Scalar>::size*step)),
- m_base(padd(pset1<Packet>(low),pmul(pset1<Packet>(step),plset<Scalar>(-packet_traits<Scalar>::size)))) {}
+ m_base(padd(pset1<Packet>(low), pmul(pset1<Packet>(step),plset<Scalar>(-packet_traits<Scalar>::size)))) {}
template<typename Index>
- EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return m_low+i*m_step; }
+ EIGEN_STRONG_INLINE const Scalar operator() (Index i) const
+ {
+ m_base = padd(m_base, pset1<Packet>(m_step));
+ return m_low+Scalar(i)*m_step;
+ }
+
template<typename Index>
EIGEN_STRONG_INLINE const Packet packetOp(Index) const { return m_base = padd(m_base,m_packetStep); }
@@ -586,7 +580,7 @@ struct linspaced_op_impl<Scalar,true>
{
typedef typename packet_traits<Scalar>::type Packet;
- linspaced_op_impl(Scalar low, Scalar step) :
+ linspaced_op_impl(const Scalar& low, const Scalar& step) :
m_low(low), m_step(step),
m_lowPacket(pset1<Packet>(m_low)), m_stepPacket(pset1<Packet>(m_step)), m_interPacket(plset<Scalar>(0)) {}
@@ -595,7 +589,7 @@ struct linspaced_op_impl<Scalar,true>
template<typename Index>
EIGEN_STRONG_INLINE const Packet packetOp(Index i) const
- { return internal::padd(m_lowPacket, pmul(m_stepPacket, padd(pset1<Packet>(i),m_interPacket))); }
+ { return internal::padd(m_lowPacket, pmul(m_stepPacket, padd(pset1<Packet>(Scalar(i)),m_interPacket))); }
const Scalar m_low;
const Scalar m_step;
@@ -615,7 +609,7 @@ template <typename Scalar, bool RandomAccess> struct functor_traits< linspaced_o
template <typename Scalar, bool RandomAccess> struct linspaced_op
{
typedef typename packet_traits<Scalar>::type Packet;
- linspaced_op(Scalar low, Scalar high, int num_steps) : impl((num_steps==1 ? high : low), (num_steps==1 ? Scalar() : (high-low)/(num_steps-1))) {}
+ linspaced_op(const Scalar& low, const Scalar& high, DenseIndex num_steps) : impl((num_steps==1 ? high : low), (num_steps==1 ? Scalar() : (high-low)/Scalar(num_steps-1))) {}
template<typename Index>
EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return impl(i); }
@@ -654,12 +648,14 @@ template <typename Scalar, bool RandomAccess> struct linspaced_op
template<typename Functor> struct functor_has_linear_access { enum { ret = 1 }; };
template<typename Scalar> struct functor_has_linear_access<scalar_identity_op<Scalar> > { enum { ret = 0 }; };
-// in CwiseBinaryOp, we require the Lhs and Rhs to have the same scalar type, except for multiplication
-// where we only require them to have the same _real_ scalar type so one may multiply, say, float by complex<float>.
+// In Eigen, any binary op (Product, CwiseBinaryOp) require the Lhs and Rhs to have the same scalar type, except for multiplication
+// where the mixing of different types is handled by scalar_product_traits
+// In particular, real * complex<real> is allowed.
// FIXME move this to functor_traits adding a functor_default
-template<typename Functor> struct functor_allows_mixing_real_and_complex { enum { ret = 0 }; };
-template<typename LhsScalar,typename RhsScalar> struct functor_allows_mixing_real_and_complex<scalar_product_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
-template<typename LhsScalar,typename RhsScalar> struct functor_allows_mixing_real_and_complex<scalar_conj_product_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
+template<typename Functor> struct functor_is_product_like { enum { ret = 0 }; };
+template<typename LhsScalar,typename RhsScalar> struct functor_is_product_like<scalar_product_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
+template<typename LhsScalar,typename RhsScalar> struct functor_is_product_like<scalar_conj_product_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
+template<typename LhsScalar,typename RhsScalar> struct functor_is_product_like<scalar_quotient_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
/** \internal
@@ -688,7 +684,7 @@ struct functor_traits<scalar_add_op<Scalar> >
*/
template<typename Scalar> struct scalar_sqrt_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_sqrt_op)
- inline const Scalar operator() (const Scalar& a) const { return internal::sqrt(a); }
+ inline const Scalar operator() (const Scalar& a) const { using std::sqrt; return sqrt(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::psqrt(a); }
};
@@ -706,7 +702,7 @@ struct functor_traits<scalar_sqrt_op<Scalar> >
*/
template<typename Scalar> struct scalar_cos_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_cos_op)
- inline Scalar operator() (const Scalar& a) const { return internal::cos(a); }
+ inline Scalar operator() (const Scalar& a) const { using std::cos; return cos(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::pcos(a); }
};
@@ -725,7 +721,7 @@ struct functor_traits<scalar_cos_op<Scalar> >
*/
template<typename Scalar> struct scalar_sin_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_sin_op)
- inline const Scalar operator() (const Scalar& a) const { return internal::sin(a); }
+ inline const Scalar operator() (const Scalar& a) const { using std::sin; return sin(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::psin(a); }
};
@@ -745,7 +741,7 @@ struct functor_traits<scalar_sin_op<Scalar> >
*/
template<typename Scalar> struct scalar_tan_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_tan_op)
- inline const Scalar operator() (const Scalar& a) const { return internal::tan(a); }
+ inline const Scalar operator() (const Scalar& a) const { using std::tan; return tan(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::ptan(a); }
};
@@ -764,7 +760,7 @@ struct functor_traits<scalar_tan_op<Scalar> >
*/
template<typename Scalar> struct scalar_acos_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_acos_op)
- inline const Scalar operator() (const Scalar& a) const { return internal::acos(a); }
+ inline const Scalar operator() (const Scalar& a) const { using std::acos; return acos(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::pacos(a); }
};
@@ -783,7 +779,7 @@ struct functor_traits<scalar_acos_op<Scalar> >
*/
template<typename Scalar> struct scalar_asin_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_asin_op)
- inline const Scalar operator() (const Scalar& a) const { return internal::asin(a); }
+ inline const Scalar operator() (const Scalar& a) const { using std::asin; return asin(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::pasin(a); }
};
@@ -805,7 +801,7 @@ struct scalar_pow_op {
// FIXME default copy constructors seems bugged with std::complex<>
inline scalar_pow_op(const scalar_pow_op& other) : m_exponent(other.m_exponent) { }
inline scalar_pow_op(const Scalar& exponent) : m_exponent(exponent) {}
- inline Scalar operator() (const Scalar& a) const { return internal::pow(a, m_exponent); }
+ inline Scalar operator() (const Scalar& a) const { return numext::pow(a, m_exponent); }
const Scalar m_exponent;
};
template<typename Scalar>
diff --git a/Eigen/src/Core/Fuzzy.h b/Eigen/src/Core/Fuzzy.h
index d74edcfdb..fe63bd298 100644
--- a/Eigen/src/Core/Fuzzy.h
+++ b/Eigen/src/Core/Fuzzy.h
@@ -19,7 +19,7 @@ namespace internal
template<typename Derived, typename OtherDerived, bool is_integer = NumTraits<typename Derived::Scalar>::IsInteger>
struct isApprox_selector
{
- static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar prec)
+ static bool run(const Derived& x, const OtherDerived& y, const typename Derived::RealScalar& prec)
{
using std::min;
typename internal::nested<Derived,2>::type nested(x);
@@ -31,7 +31,7 @@ struct isApprox_selector
template<typename Derived, typename OtherDerived>
struct isApprox_selector<Derived, OtherDerived, true>
{
- static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar)
+ static bool run(const Derived& x, const OtherDerived& y, const typename Derived::RealScalar&)
{
return x.matrix() == y.matrix();
}
@@ -40,16 +40,16 @@ struct isApprox_selector<Derived, OtherDerived, true>
template<typename Derived, typename OtherDerived, bool is_integer = NumTraits<typename Derived::Scalar>::IsInteger>
struct isMuchSmallerThan_object_selector
{
- static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar prec)
+ static bool run(const Derived& x, const OtherDerived& y, const typename Derived::RealScalar& prec)
{
- return x.cwiseAbs2().sum() <= abs2(prec) * y.cwiseAbs2().sum();
+ return x.cwiseAbs2().sum() <= numext::abs2(prec) * y.cwiseAbs2().sum();
}
};
template<typename Derived, typename OtherDerived>
struct isMuchSmallerThan_object_selector<Derived, OtherDerived, true>
{
- static bool run(const Derived& x, const OtherDerived&, typename Derived::RealScalar)
+ static bool run(const Derived& x, const OtherDerived&, const typename Derived::RealScalar&)
{
return x.matrix() == Derived::Zero(x.rows(), x.cols()).matrix();
}
@@ -58,16 +58,16 @@ struct isMuchSmallerThan_object_selector<Derived, OtherDerived, true>
template<typename Derived, bool is_integer = NumTraits<typename Derived::Scalar>::IsInteger>
struct isMuchSmallerThan_scalar_selector
{
- static bool run(const Derived& x, const typename Derived::RealScalar& y, typename Derived::RealScalar prec)
+ static bool run(const Derived& x, const typename Derived::RealScalar& y, const typename Derived::RealScalar& prec)
{
- return x.cwiseAbs2().sum() <= abs2(prec * y);
+ return x.cwiseAbs2().sum() <= numext::abs2(prec * y);
}
};
template<typename Derived>
struct isMuchSmallerThan_scalar_selector<Derived, true>
{
- static bool run(const Derived& x, const typename Derived::RealScalar&, typename Derived::RealScalar)
+ static bool run(const Derived& x, const typename Derived::RealScalar&, const typename Derived::RealScalar&)
{
return x.matrix() == Derived::Zero(x.rows(), x.cols()).matrix();
}
@@ -97,7 +97,7 @@ template<typename Derived>
template<typename OtherDerived>
bool DenseBase<Derived>::isApprox(
const DenseBase<OtherDerived>& other,
- RealScalar prec
+ const RealScalar& prec
) const
{
return internal::isApprox_selector<Derived, OtherDerived>::run(derived(), other.derived(), prec);
@@ -119,7 +119,7 @@ bool DenseBase<Derived>::isApprox(
template<typename Derived>
bool DenseBase<Derived>::isMuchSmallerThan(
const typename NumTraits<Scalar>::Real& other,
- RealScalar prec
+ const RealScalar& prec
) const
{
return internal::isMuchSmallerThan_scalar_selector<Derived>::run(derived(), other, prec);
@@ -139,7 +139,7 @@ template<typename Derived>
template<typename OtherDerived>
bool DenseBase<Derived>::isMuchSmallerThan(
const DenseBase<OtherDerived>& other,
- RealScalar prec
+ const RealScalar& prec
) const
{
return internal::isMuchSmallerThan_object_selector<Derived, OtherDerived>::run(derived(), other.derived(), prec);
diff --git a/Eigen/src/Core/GeneralProduct.h b/Eigen/src/Core/GeneralProduct.h
index bfc2a67b1..2a59d9464 100644
--- a/Eigen/src/Core/GeneralProduct.h
+++ b/Eigen/src/Core/GeneralProduct.h
@@ -222,7 +222,29 @@ class GeneralProduct<Lhs, Rhs, InnerProduct>
***********************************************************************/
namespace internal {
-template<int StorageOrder> struct outer_product_selector;
+
+// Column major
+template<typename ProductType, typename Dest, typename Func>
+EIGEN_DONT_INLINE void outer_product_selector_run(const ProductType& prod, Dest& dest, const Func& func, const false_type&)
+{
+ typedef typename Dest::Index Index;
+ // FIXME make sure lhs is sequentially stored
+ // FIXME not very good if rhs is real and lhs complex while alpha is real too
+ const Index cols = dest.cols();
+ for (Index j=0; j<cols; ++j)
+ func(dest.col(j), prod.rhs().coeff(j) * prod.lhs());
+}
+
+// Row major
+template<typename ProductType, typename Dest, typename Func>
+EIGEN_DONT_INLINE void outer_product_selector_run(const ProductType& prod, Dest& dest, const Func& func, const true_type&) {
+ typedef typename Dest::Index Index;
+ // FIXME make sure rhs is sequentially stored
+ // FIXME not very good if lhs is real and rhs complex while alpha is real too
+ const Index rows = dest.rows();
+ for (Index i=0; i<rows; ++i)
+ func(dest.row(i), prod.lhs().coeff(i) * prod.rhs());
+}
template<typename Lhs, typename Rhs>
struct traits<GeneralProduct<Lhs,Rhs,OuterProduct> >
@@ -235,6 +257,8 @@ template<typename Lhs, typename Rhs>
class GeneralProduct<Lhs, Rhs, OuterProduct>
: public ProductBase<GeneralProduct<Lhs,Rhs,OuterProduct>, Lhs, Rhs>
{
+ template<typename T> struct IsRowMajor : internal::conditional<(int(T::Flags)&RowMajorBit), internal::true_type, internal::false_type>::type {};
+
public:
EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct)
@@ -243,41 +267,39 @@ class GeneralProduct<Lhs, Rhs, OuterProduct>
EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::RealScalar, typename Rhs::RealScalar>::value),
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
}
-
- template<typename Dest> void scaleAndAddTo(Dest& dest, Scalar alpha) const
- {
- internal::outer_product_selector<(int(Dest::Flags)&RowMajorBit) ? RowMajor : ColMajor>::run(*this, dest, alpha);
+
+ struct set { template<typename Dst, typename Src> void operator()(const Dst& dst, const Src& src) const { dst.const_cast_derived() = src; } };
+ struct add { template<typename Dst, typename Src> void operator()(const Dst& dst, const Src& src) const { dst.const_cast_derived() += src; } };
+ struct sub { template<typename Dst, typename Src> void operator()(const Dst& dst, const Src& src) const { dst.const_cast_derived() -= src; } };
+ struct adds {
+ Scalar m_scale;
+ adds(const Scalar& s) : m_scale(s) {}
+ template<typename Dst, typename Src> void operator()(const Dst& dst, const Src& src) const {
+ dst.const_cast_derived() += m_scale * src;
+ }
+ };
+
+ template<typename Dest>
+ inline void evalTo(Dest& dest) const {
+ internal::outer_product_selector_run(*this, dest, set(), IsRowMajor<Dest>());
+ }
+
+ template<typename Dest>
+ inline void addTo(Dest& dest) const {
+ internal::outer_product_selector_run(*this, dest, add(), IsRowMajor<Dest>());
}
-};
-
-namespace internal {
-template<> struct outer_product_selector<ColMajor> {
- template<typename ProductType, typename Dest>
- static EIGEN_DONT_INLINE void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) {
- typedef typename Dest::Index Index;
- // FIXME make sure lhs is sequentially stored
- // FIXME not very good if rhs is real and lhs complex while alpha is real too
- const Index cols = dest.cols();
- for (Index j=0; j<cols; ++j)
- dest.col(j) += (alpha * prod.rhs().coeff(j)) * prod.lhs();
- }
-};
+ template<typename Dest>
+ inline void subTo(Dest& dest) const {
+ internal::outer_product_selector_run(*this, dest, sub(), IsRowMajor<Dest>());
+ }
-template<> struct outer_product_selector<RowMajor> {
- template<typename ProductType, typename Dest>
- static EIGEN_DONT_INLINE void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) {
- typedef typename Dest::Index Index;
- // FIXME make sure rhs is sequentially stored
- // FIXME not very good if lhs is real and rhs complex while alpha is real too
- const Index rows = dest.rows();
- for (Index i=0; i<rows; ++i)
- dest.row(i) += (alpha * prod.lhs().coeff(i)) * prod.rhs();
- }
+ template<typename Dest> void scaleAndAddTo(Dest& dest, const Scalar& alpha) const
+ {
+ internal::outer_product_selector_run(*this, dest, adds(alpha), IsRowMajor<Dest>());
+ }
};
-} // end namespace internal
-
/***********************************************************************
* Implementation of General Matrix Vector Product
***********************************************************************/
@@ -311,7 +333,7 @@ class GeneralProduct<Lhs, Rhs, GemvProduct>
typedef typename Lhs::Scalar LhsScalar;
typedef typename Rhs::Scalar RhsScalar;
- GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
+ GeneralProduct(const Lhs& a_lhs, const Rhs& a_rhs) : Base(a_lhs,a_rhs)
{
// EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::Scalar, typename Rhs::Scalar>::value),
// YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
@@ -320,7 +342,7 @@ class GeneralProduct<Lhs, Rhs, GemvProduct>
enum { Side = Lhs::IsVectorAtCompileTime ? OnTheLeft : OnTheRight };
typedef typename internal::conditional<int(Side)==OnTheRight,_LhsNested,_RhsNested>::type MatrixType;
- template<typename Dest> void scaleAndAddTo(Dest& dst, Scalar alpha) const
+ template<typename Dest> void scaleAndAddTo(Dest& dst, const Scalar& alpha) const
{
eigen_assert(m_lhs.rows() == dst.rows() && m_rhs.cols() == dst.cols());
internal::gemv_selector<Side,(int(MatrixType::Flags)&RowMajorBit) ? RowMajor : ColMajor,
@@ -335,7 +357,7 @@ template<int StorageOrder, bool BlasCompatible>
struct gemv_selector<OnTheLeft,StorageOrder,BlasCompatible>
{
template<typename ProductType, typename Dest>
- static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
+ static void run(const ProductType& prod, Dest& dest, const typename ProductType::Scalar& alpha)
{
Transpose<Dest> destT(dest);
enum { OtherStorageOrder = StorageOrder == RowMajor ? ColMajor : RowMajor };
@@ -384,7 +406,7 @@ struct gemv_static_vector_if<Scalar,Size,MaxSize,true>
template<> struct gemv_selector<OnTheRight,ColMajor,true>
{
template<typename ProductType, typename Dest>
- static inline void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
+ static inline void run(const ProductType& prod, Dest& dest, const typename ProductType::Scalar& alpha)
{
typedef typename ProductType::Index Index;
typedef typename ProductType::LhsScalar LhsScalar;
@@ -413,7 +435,7 @@ template<> struct gemv_selector<OnTheRight,ColMajor,true>
gemv_static_vector_if<ResScalar,Dest::SizeAtCompileTime,Dest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;
- bool alphaIsCompatible = (!ComplexByReal) || (imag(actualAlpha)==RealScalar(0));
+ bool alphaIsCompatible = (!ComplexByReal) || (numext::imag(actualAlpha)==RealScalar(0));
bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;
RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha);
@@ -457,7 +479,7 @@ template<> struct gemv_selector<OnTheRight,ColMajor,true>
template<> struct gemv_selector<OnTheRight,RowMajor,true>
{
template<typename ProductType, typename Dest>
- static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
+ static void run(const ProductType& prod, Dest& dest, const typename ProductType::Scalar& alpha)
{
typedef typename ProductType::LhsScalar LhsScalar;
typedef typename ProductType::RhsScalar RhsScalar;
@@ -508,7 +530,7 @@ template<> struct gemv_selector<OnTheRight,RowMajor,true>
template<> struct gemv_selector<OnTheRight,ColMajor,false>
{
template<typename ProductType, typename Dest>
- static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
+ static void run(const ProductType& prod, Dest& dest, const typename ProductType::Scalar& alpha)
{
typedef typename Dest::Index Index;
// TODO makes sure dest is sequentially stored in memory, otherwise use a temp
@@ -521,7 +543,7 @@ template<> struct gemv_selector<OnTheRight,ColMajor,false>
template<> struct gemv_selector<OnTheRight,RowMajor,false>
{
template<typename ProductType, typename Dest>
- static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
+ static void run(const ProductType& prod, Dest& dest, const typename ProductType::Scalar& alpha)
{
typedef typename Dest::Index Index;
// TODO makes sure rhs is sequentially stored in memory, otherwise use a temp
diff --git a/Eigen/src/Core/GenericPacketMath.h b/Eigen/src/Core/GenericPacketMath.h
index 858fb243e..5f783ebee 100644
--- a/Eigen/src/Core/GenericPacketMath.h
+++ b/Eigen/src/Core/GenericPacketMath.h
@@ -106,7 +106,7 @@ pnegate(const Packet& a) { return -a; }
/** \internal \returns conj(a) (coeff-wise) */
template<typename Packet> inline Packet
-pconj(const Packet& a) { return conj(a); }
+pconj(const Packet& a) { return numext::conj(a); }
/** \internal \returns a * b (coeff-wise) */
template<typename Packet> inline Packet
@@ -130,7 +130,7 @@ pmax(const Packet& a,
/** \internal \returns the absolute value of \a a */
template<typename Packet> inline Packet
-pabs(const Packet& a) { return abs(a); }
+pabs(const Packet& a) { using std::abs; return abs(a); }
/** \internal \returns the bitwise and of \a a and \a b */
template<typename Packet> inline Packet
@@ -156,7 +156,11 @@ pload(const typename unpacket_traits<Packet>::type* from) { return *from; }
template<typename Packet> inline Packet
ploadu(const typename unpacket_traits<Packet>::type* from) { return *from; }
-/** \internal \returns a packet with elements of \a *from duplicated, e.g.: (from[0],from[0],from[1],from[1]) */
+/** \internal \returns a packet with elements of \a *from duplicated.
+ * For instance, for a packet of 8 elements, 4 scalar will be read from \a *from and
+ * duplicated to form: {from[0],from[0],from[1],from[1],,from[2],from[2],,from[3],from[3]}
+ * Currently, this function is only used for scalar * complex products.
+ */
template<typename Packet> inline Packet
ploaddup(const typename unpacket_traits<Packet>::type* from) { return *from; }
@@ -215,7 +219,12 @@ template<typename Packet> inline Packet preverse(const Packet& a)
/** \internal \returns \a a with real and imaginary part flipped (for complex type only) */
template<typename Packet> inline Packet pcplxflip(const Packet& a)
-{ return Packet(imag(a),real(a)); }
+{
+ // FIXME: uncomment the following in case we drop the internal imag and real functions.
+// using std::imag;
+// using std::real;
+ return Packet(imag(a),real(a));
+}
/**************************
* Special math functions
@@ -223,35 +232,35 @@ template<typename Packet> inline Packet pcplxflip(const Packet& a)
/** \internal \returns the sine of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
-Packet psin(const Packet& a) { return sin(a); }
+Packet psin(const Packet& a) { using std::sin; return sin(a); }
/** \internal \returns the cosine of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
-Packet pcos(const Packet& a) { return cos(a); }
+Packet pcos(const Packet& a) { using std::cos; return cos(a); }
/** \internal \returns the tan of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
-Packet ptan(const Packet& a) { return tan(a); }
+Packet ptan(const Packet& a) { using std::tan; return tan(a); }
/** \internal \returns the arc sine of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
-Packet pasin(const Packet& a) { return asin(a); }
+Packet pasin(const Packet& a) { using std::asin; return asin(a); }
/** \internal \returns the arc cosine of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
-Packet pacos(const Packet& a) { return acos(a); }
+Packet pacos(const Packet& a) { using std::acos; return acos(a); }
/** \internal \returns the exp of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
-Packet pexp(const Packet& a) { return exp(a); }
+Packet pexp(const Packet& a) { using std::exp; return exp(a); }
/** \internal \returns the log of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
-Packet plog(const Packet& a) { return log(a); }
+Packet plog(const Packet& a) { using std::log; return log(a); }
/** \internal \returns the square-root of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
-Packet psqrt(const Packet& a) { return sqrt(a); }
+Packet psqrt(const Packet& a) { using std::sqrt; return sqrt(a); }
/***************************************************************************
* The following functions might not have to be overwritten for vectorized types
@@ -302,8 +311,21 @@ struct palign_impl
static inline void run(PacketType&, const PacketType&) {}
};
-/** \internal update \a first using the concatenation of the \a Offset last elements
- * of \a first and packet_size minus \a Offset first elements of \a second */
+/** \internal update \a first using the concatenation of the packet_size minus \a Offset last elements
+ * of \a first and \a Offset first elements of \a second.
+ *
+ * This function is currently only used to optimize matrix-vector products on unligned matrices.
+ * It takes 2 packets that represent a contiguous memory array, and returns a packet starting
+ * at the position \a Offset. For instance, for packets of 4 elements, we have:
+ * Input:
+ * - first = {f0,f1,f2,f3}
+ * - second = {s0,s1,s2,s3}
+ * Output:
+ * - if Offset==0 then {f0,f1,f2,f3}
+ * - if Offset==1 then {f1,f2,f3,s0}
+ * - if Offset==2 then {f2,f3,s0,s1}
+ * - if Offset==3 then {f3,s0,s1,s3}
+ */
template<int Offset,typename PacketType>
inline void palign(PacketType& first, const PacketType& second)
{
diff --git a/Eigen/src/Core/GlobalFunctions.h b/Eigen/src/Core/GlobalFunctions.h
index e63726c47..2acf97723 100644
--- a/Eigen/src/Core/GlobalFunctions.h
+++ b/Eigen/src/Core/GlobalFunctions.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
-// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2010-2012 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2010 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
@@ -11,7 +11,7 @@
#ifndef EIGEN_GLOBAL_FUNCTIONS_H
#define EIGEN_GLOBAL_FUNCTIONS_H
-#define EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(NAME,FUNCTOR) \
+#define EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(NAME,FUNCTOR) \
template<typename Derived> \
inline const Eigen::CwiseUnaryOp<Eigen::internal::FUNCTOR<typename Derived::Scalar>, const Derived> \
NAME(const Eigen::ArrayBase<Derived>& x) { \
@@ -35,20 +35,21 @@
};
-namespace std
+namespace Eigen
{
- EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(real,scalar_real_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(imag,scalar_imag_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(sin,scalar_sin_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(cos,scalar_cos_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(asin,scalar_asin_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(acos,scalar_acos_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(tan,scalar_tan_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(exp,scalar_exp_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(log,scalar_log_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(abs,scalar_abs_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(sqrt,scalar_sqrt_op)
-
+ EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(real,scalar_real_op)
+ EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(imag,scalar_imag_op)
+ EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(conj,scalar_conjugate_op)
+ EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(sin,scalar_sin_op)
+ EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(cos,scalar_cos_op)
+ EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(asin,scalar_asin_op)
+ EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(acos,scalar_acos_op)
+ EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(tan,scalar_tan_op)
+ EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(exp,scalar_exp_op)
+ EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(log,scalar_log_op)
+ EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(abs,scalar_abs_op)
+ EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(sqrt,scalar_sqrt_op)
+
template<typename Derived>
inline const Eigen::CwiseUnaryOp<Eigen::internal::scalar_pow_op<typename Derived::Scalar>, const Derived>
pow(const Eigen::ArrayBase<Derived>& x, const typename Derived::Scalar& exponent) {
@@ -64,16 +65,13 @@ namespace std
exponents.derived()
);
}
-}
-
-namespace Eigen
-{
+
/**
* \brief Component-wise division of a scalar by array elements.
**/
template <typename Derived>
inline const Eigen::CwiseUnaryOp<Eigen::internal::scalar_inverse_mult_op<typename Derived::Scalar>, const Derived>
- operator/(typename Derived::Scalar s, const Eigen::ArrayBase<Derived>& a)
+ operator/(const typename Derived::Scalar& s, const Eigen::ArrayBase<Derived>& a)
{
return Eigen::CwiseUnaryOp<Eigen::internal::scalar_inverse_mult_op<typename Derived::Scalar>, const Derived>(
a.derived(),
@@ -85,19 +83,10 @@ namespace Eigen
{
EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(real,scalar_real_op)
EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(imag,scalar_imag_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(sin,scalar_sin_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(cos,scalar_cos_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(asin,scalar_asin_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(acos,scalar_acos_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(tan,scalar_tan_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(exp,scalar_exp_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(log,scalar_log_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(abs,scalar_abs_op)
EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(abs2,scalar_abs2_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(sqrt,scalar_sqrt_op)
}
}
-// TODO: cleanly disable those functions that are not supported on Array (internal::real_ref, internal::random, internal::isApprox...)
+// TODO: cleanly disable those functions that are not supported on Array (numext::real_ref, internal::random, internal::isApprox...)
#endif // EIGEN_GLOBAL_FUNCTIONS_H
diff --git a/Eigen/src/Core/IO.h b/Eigen/src/Core/IO.h
index cc8e18a00..8d4bc59e9 100644
--- a/Eigen/src/Core/IO.h
+++ b/Eigen/src/Core/IO.h
@@ -55,9 +55,8 @@ struct IOFormat
const std::string& _rowSeparator = "\n", const std::string& _rowPrefix="", const std::string& _rowSuffix="",
const std::string& _matPrefix="", const std::string& _matSuffix="")
: matPrefix(_matPrefix), matSuffix(_matSuffix), rowPrefix(_rowPrefix), rowSuffix(_rowSuffix), rowSeparator(_rowSeparator),
- coeffSeparator(_coeffSeparator), precision(_precision), flags(_flags)
+ rowSpacer(""), coeffSeparator(_coeffSeparator), precision(_precision), flags(_flags)
{
- rowSpacer = "";
int i = int(matSuffix.length())-1;
while (i>=0 && matSuffix[i]!='\n')
{
@@ -129,6 +128,7 @@ struct significant_decimals_default_impl
static inline int run()
{
using std::ceil;
+ using std::log;
return cast<RealScalar,int>(ceil(-log(NumTraits<RealScalar>::epsilon())/log(RealScalar(10))));
}
};
@@ -185,21 +185,22 @@ std::ostream & print_matrix(std::ostream & s, const Derived& _m, const IOFormat&
explicit_precision = fmt.precision;
}
+ std::streamsize old_precision = 0;
+ if(explicit_precision) old_precision = s.precision(explicit_precision);
+
bool align_cols = !(fmt.flags & DontAlignCols);
if(align_cols)
{
// compute the largest width
- for(Index j = 1; j < m.cols(); ++j)
+ for(Index j = 0; j < m.cols(); ++j)
for(Index i = 0; i < m.rows(); ++i)
{
std::stringstream sstr;
- if(explicit_precision) sstr.precision(explicit_precision);
+ sstr.copyfmt(s);
sstr << m.coeff(i,j);
width = std::max<Index>(width, Index(sstr.str().length()));
}
}
- std::streamsize old_precision = 0;
- if(explicit_precision) old_precision = s.precision(explicit_precision);
s << fmt.matPrefix;
for(Index i = 0; i < m.rows(); ++i)
{
diff --git a/Eigen/src/Core/Map.h b/Eigen/src/Core/Map.h
index 15a19226e..f804c89d6 100644
--- a/Eigen/src/Core/Map.h
+++ b/Eigen/src/Core/Map.h
@@ -133,36 +133,36 @@ template<typename PlainObjectType, int MapOptions, typename StrideType> class Ma
/** Constructor in the fixed-size case.
*
- * \param data pointer to the array to map
- * \param stride optional Stride object, passing the strides.
+ * \param dataPtr pointer to the array to map
+ * \param a_stride optional Stride object, passing the strides.
*/
- inline Map(PointerArgType data, const StrideType& stride = StrideType())
- : Base(cast_to_pointer_type(data)), m_stride(stride)
+ inline Map(PointerArgType dataPtr, const StrideType& a_stride = StrideType())
+ : Base(cast_to_pointer_type(dataPtr)), m_stride(a_stride)
{
PlainObjectType::Base::_check_template_params();
}
/** Constructor in the dynamic-size vector case.
*
- * \param data pointer to the array to map
- * \param size the size of the vector expression
- * \param stride optional Stride object, passing the strides.
+ * \param dataPtr pointer to the array to map
+ * \param a_size the size of the vector expression
+ * \param a_stride optional Stride object, passing the strides.
*/
- inline Map(PointerArgType data, Index size, const StrideType& stride = StrideType())
- : Base(cast_to_pointer_type(data), size), m_stride(stride)
+ inline Map(PointerArgType dataPtr, Index a_size, const StrideType& a_stride = StrideType())
+ : Base(cast_to_pointer_type(dataPtr), a_size), m_stride(a_stride)
{
PlainObjectType::Base::_check_template_params();
}
/** Constructor in the dynamic-size matrix case.
*
- * \param data pointer to the array to map
- * \param rows the number of rows of the matrix expression
- * \param cols the number of columns of the matrix expression
- * \param stride optional Stride object, passing the strides.
+ * \param dataPtr pointer to the array to map
+ * \param nbRows the number of rows of the matrix expression
+ * \param nbCols the number of columns of the matrix expression
+ * \param a_stride optional Stride object, passing the strides.
*/
- inline Map(PointerArgType data, Index rows, Index cols, const StrideType& stride = StrideType())
- : Base(cast_to_pointer_type(data), rows, cols), m_stride(stride)
+ inline Map(PointerArgType dataPtr, Index nbRows, Index nbCols, const StrideType& a_stride = StrideType())
+ : Base(cast_to_pointer_type(dataPtr), nbRows, nbCols), m_stride(a_stride)
{
PlainObjectType::Base::_check_template_params();
}
diff --git a/Eigen/src/Core/MapBase.h b/Eigen/src/Core/MapBase.h
index a388d61ea..ab50c9b81 100644
--- a/Eigen/src/Core/MapBase.h
+++ b/Eigen/src/Core/MapBase.h
@@ -87,9 +87,9 @@ template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
*/
inline const Scalar* data() const { return m_data; }
- inline const Scalar& coeff(Index row, Index col) const
+ inline const Scalar& coeff(Index rowId, Index colId) const
{
- return m_data[col * colStride() + row * rowStride()];
+ return m_data[colId * colStride() + rowId * rowStride()];
}
inline const Scalar& coeff(Index index) const
@@ -98,9 +98,9 @@ template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
return m_data[index * innerStride()];
}
- inline const Scalar& coeffRef(Index row, Index col) const
+ inline const Scalar& coeffRef(Index rowId, Index colId) const
{
- return this->m_data[col * colStride() + row * rowStride()];
+ return this->m_data[colId * colStride() + rowId * rowStride()];
}
inline const Scalar& coeffRef(Index index) const
@@ -110,10 +110,10 @@ template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
}
template<int LoadMode>
- inline PacketScalar packet(Index row, Index col) const
+ inline PacketScalar packet(Index rowId, Index colId) const
{
return internal::ploadt<PacketScalar, LoadMode>
- (m_data + (col * colStride() + row * rowStride()));
+ (m_data + (colId * colStride() + rowId * rowStride()));
}
template<int LoadMode>
@@ -123,29 +123,29 @@ template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
return internal::ploadt<PacketScalar, LoadMode>(m_data + index * innerStride());
}
- inline MapBase(PointerType data) : m_data(data), m_rows(RowsAtCompileTime), m_cols(ColsAtCompileTime)
+ inline MapBase(PointerType dataPtr) : m_data(dataPtr), m_rows(RowsAtCompileTime), m_cols(ColsAtCompileTime)
{
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
checkSanity();
}
- inline MapBase(PointerType data, Index size)
- : m_data(data),
- m_rows(RowsAtCompileTime == Dynamic ? size : Index(RowsAtCompileTime)),
- m_cols(ColsAtCompileTime == Dynamic ? size : Index(ColsAtCompileTime))
+ inline MapBase(PointerType dataPtr, Index vecSize)
+ : m_data(dataPtr),
+ m_rows(RowsAtCompileTime == Dynamic ? vecSize : Index(RowsAtCompileTime)),
+ m_cols(ColsAtCompileTime == Dynamic ? vecSize : Index(ColsAtCompileTime))
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- eigen_assert(size >= 0);
- eigen_assert(data == 0 || SizeAtCompileTime == Dynamic || SizeAtCompileTime == size);
+ eigen_assert(vecSize >= 0);
+ eigen_assert(dataPtr == 0 || SizeAtCompileTime == Dynamic || SizeAtCompileTime == vecSize);
checkSanity();
}
- inline MapBase(PointerType data, Index rows, Index cols)
- : m_data(data), m_rows(rows), m_cols(cols)
+ inline MapBase(PointerType dataPtr, Index nbRows, Index nbCols)
+ : m_data(dataPtr), m_rows(nbRows), m_cols(nbCols)
{
- eigen_assert( (data == 0)
- || ( rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
- && cols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols)));
+ eigen_assert( (dataPtr == 0)
+ || ( nbRows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == nbRows)
+ && nbCols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == nbCols)));
checkSanity();
}
@@ -210,23 +210,23 @@ template<typename Derived> class MapBase<Derived, WriteAccessors>
}
template<int StoreMode>
- inline void writePacket(Index row, Index col, const PacketScalar& x)
+ inline void writePacket(Index row, Index col, const PacketScalar& val)
{
internal::pstoret<Scalar, PacketScalar, StoreMode>
- (this->m_data + (col * colStride() + row * rowStride()), x);
+ (this->m_data + (col * colStride() + row * rowStride()), val);
}
template<int StoreMode>
- inline void writePacket(Index index, const PacketScalar& x)
+ inline void writePacket(Index index, const PacketScalar& val)
{
EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived)
internal::pstoret<Scalar, PacketScalar, StoreMode>
- (this->m_data + index * innerStride(), x);
+ (this->m_data + index * innerStride(), val);
}
- explicit inline MapBase(PointerType data) : Base(data) {}
- inline MapBase(PointerType data, Index size) : Base(data, size) {}
- inline MapBase(PointerType data, Index rows, Index cols) : Base(data, rows, cols) {}
+ explicit inline MapBase(PointerType dataPtr) : Base(dataPtr) {}
+ inline MapBase(PointerType dataPtr, Index vecSize) : Base(dataPtr, vecSize) {}
+ inline MapBase(PointerType dataPtr, Index nbRows, Index nbCols) : Base(dataPtr, nbRows, nbCols) {}
Derived& operator=(const MapBase& other)
{
@@ -237,6 +237,8 @@ template<typename Derived> class MapBase<Derived, WriteAccessors>
using Base::Base::operator=;
};
+#undef EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS
+
} // end namespace Eigen
#endif // EIGEN_MAPBASE_H
diff --git a/Eigen/src/Core/MathFunctions.h b/Eigen/src/Core/MathFunctions.h
index 05e913f2f..2bfc5ebd9 100644
--- a/Eigen/src/Core/MathFunctions.h
+++ b/Eigen/src/Core/MathFunctions.h
@@ -51,16 +51,15 @@ struct global_math_functions_filtering_base
typedef typename T::Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl type;
};
-#define EIGEN_MATHFUNC_IMPL(func, scalar) func##_impl<typename global_math_functions_filtering_base<scalar>::type>
-#define EIGEN_MATHFUNC_RETVAL(func, scalar) typename func##_retval<typename global_math_functions_filtering_base<scalar>::type>::type
-
+#define EIGEN_MATHFUNC_IMPL(func, scalar) Eigen::internal::func##_impl<typename Eigen::internal::global_math_functions_filtering_base<scalar>::type>
+#define EIGEN_MATHFUNC_RETVAL(func, scalar) typename Eigen::internal::func##_retval<typename Eigen::internal::global_math_functions_filtering_base<scalar>::type>::type
/****************************************************************************
* Implementation of real *
****************************************************************************/
-template<typename Scalar>
-struct real_impl
+template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex>
+struct real_default_impl
{
typedef typename NumTraits<Scalar>::Real RealScalar;
static inline RealScalar run(const Scalar& x)
@@ -69,34 +68,32 @@ struct real_impl
}
};
-template<typename RealScalar>
-struct real_impl<std::complex<RealScalar> >
+template<typename Scalar>
+struct real_default_impl<Scalar,true>
{
- static inline RealScalar run(const std::complex<RealScalar>& x)
+ typedef typename NumTraits<Scalar>::Real RealScalar;
+ static inline RealScalar run(const Scalar& x)
{
using std::real;
return real(x);
}
};
+template<typename Scalar> struct real_impl : real_default_impl<Scalar> {};
+
template<typename Scalar>
struct real_retval
{
typedef typename NumTraits<Scalar>::Real type;
};
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(real, Scalar) real(const Scalar& x)
-{
- return EIGEN_MATHFUNC_IMPL(real, Scalar)::run(x);
-}
/****************************************************************************
* Implementation of imag *
****************************************************************************/
-template<typename Scalar>
-struct imag_impl
+template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex>
+struct imag_default_impl
{
typedef typename NumTraits<Scalar>::Real RealScalar;
static inline RealScalar run(const Scalar&)
@@ -105,28 +102,25 @@ struct imag_impl
}
};
-template<typename RealScalar>
-struct imag_impl<std::complex<RealScalar> >
+template<typename Scalar>
+struct imag_default_impl<Scalar,true>
{
- static inline RealScalar run(const std::complex<RealScalar>& x)
+ typedef typename NumTraits<Scalar>::Real RealScalar;
+ static inline RealScalar run(const Scalar& x)
{
using std::imag;
return imag(x);
}
};
+template<typename Scalar> struct imag_impl : imag_default_impl<Scalar> {};
+
template<typename Scalar>
struct imag_retval
{
typedef typename NumTraits<Scalar>::Real type;
};
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(imag, Scalar) imag(const Scalar& x)
-{
- return EIGEN_MATHFUNC_IMPL(imag, Scalar)::run(x);
-}
-
/****************************************************************************
* Implementation of real_ref *
****************************************************************************/
@@ -151,18 +145,6 @@ struct real_ref_retval
typedef typename NumTraits<Scalar>::Real & type;
};
-template<typename Scalar>
-inline typename add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) >::type real_ref(const Scalar& x)
-{
- return real_ref_impl<Scalar>::run(x);
-}
-
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) real_ref(Scalar& x)
-{
- return EIGEN_MATHFUNC_IMPL(real_ref, Scalar)::run(x);
-}
-
/****************************************************************************
* Implementation of imag_ref *
****************************************************************************/
@@ -203,23 +185,11 @@ struct imag_ref_retval
typedef typename NumTraits<Scalar>::Real & type;
};
-template<typename Scalar>
-inline typename add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) >::type imag_ref(const Scalar& x)
-{
- return imag_ref_impl<Scalar>::run(x);
-}
-
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) imag_ref(Scalar& x)
-{
- return EIGEN_MATHFUNC_IMPL(imag_ref, Scalar)::run(x);
-}
-
/****************************************************************************
* Implementation of conj *
****************************************************************************/
-template<typename Scalar>
+template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex>
struct conj_impl
{
static inline Scalar run(const Scalar& x)
@@ -228,10 +198,10 @@ struct conj_impl
}
};
-template<typename RealScalar>
-struct conj_impl<std::complex<RealScalar> >
+template<typename Scalar>
+struct conj_impl<Scalar,true>
{
- static inline std::complex<RealScalar> run(const std::complex<RealScalar>& x)
+ static inline Scalar run(const Scalar& x)
{
using std::conj;
return conj(x);
@@ -244,39 +214,6 @@ struct conj_retval
typedef Scalar type;
};
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(conj, Scalar) conj(const Scalar& x)
-{
- return EIGEN_MATHFUNC_IMPL(conj, Scalar)::run(x);
-}
-
-/****************************************************************************
-* Implementation of abs *
-****************************************************************************/
-
-template<typename Scalar>
-struct abs_impl
-{
- typedef typename NumTraits<Scalar>::Real RealScalar;
- static inline RealScalar run(const Scalar& x)
- {
- using std::abs;
- return abs(x);
- }
-};
-
-template<typename Scalar>
-struct abs_retval
-{
- typedef typename NumTraits<Scalar>::Real type;
-};
-
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(abs, Scalar) abs(const Scalar& x)
-{
- return EIGEN_MATHFUNC_IMPL(abs, Scalar)::run(x);
-}
-
/****************************************************************************
* Implementation of abs2 *
****************************************************************************/
@@ -306,12 +243,6 @@ struct abs2_retval
typedef typename NumTraits<Scalar>::Real type;
};
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(abs2, Scalar) abs2(const Scalar& x)
-{
- return EIGEN_MATHFUNC_IMPL(abs2, Scalar)::run(x);
-}
-
/****************************************************************************
* Implementation of norm1 *
****************************************************************************/
@@ -322,6 +253,7 @@ struct norm1_default_impl
typedef typename NumTraits<Scalar>::Real RealScalar;
static inline RealScalar run(const Scalar& x)
{
+ using std::abs;
return abs(real(x)) + abs(imag(x));
}
};
@@ -331,6 +263,7 @@ struct norm1_default_impl<Scalar, false>
{
static inline Scalar run(const Scalar& x)
{
+ using std::abs;
return abs(x);
}
};
@@ -344,12 +277,6 @@ struct norm1_retval
typedef typename NumTraits<Scalar>::Real type;
};
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(norm1, Scalar) norm1(const Scalar& x)
-{
- return EIGEN_MATHFUNC_IMPL(norm1, Scalar)::run(x);
-}
-
/****************************************************************************
* Implementation of hypot *
****************************************************************************/
@@ -362,9 +289,12 @@ struct hypot_impl
{
using std::max;
using std::min;
+ using std::abs;
+ using std::sqrt;
RealScalar _x = abs(x);
RealScalar _y = abs(y);
RealScalar p = (max)(_x, _y);
+ if(p==RealScalar(0)) return 0;
RealScalar q = (min)(_x, _y);
RealScalar qp = q/p;
return p * sqrt(RealScalar(1) + qp*qp);
@@ -377,12 +307,6 @@ struct hypot_retval
typedef typename NumTraits<Scalar>::Real type;
};
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(hypot, Scalar) hypot(const Scalar& x, const Scalar& y)
-{
- return EIGEN_MATHFUNC_IMPL(hypot, Scalar)::run(x, y);
-}
-
/****************************************************************************
* Implementation of cast *
****************************************************************************/
@@ -405,97 +329,29 @@ inline NewType cast(const OldType& x)
}
/****************************************************************************
-* Implementation of sqrt *
+* Implementation of atanh2 *
****************************************************************************/
template<typename Scalar, bool IsInteger>
-struct sqrt_default_impl
-{
- static inline Scalar run(const Scalar& x)
- {
- using std::sqrt;
- return sqrt(x);
- }
-};
-
-template<typename Scalar>
-struct sqrt_default_impl<Scalar, true>
-{
- static inline Scalar run(const Scalar&)
- {
-#ifdef EIGEN2_SUPPORT
- eigen_assert(!NumTraits<Scalar>::IsInteger);
-#else
- EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
-#endif
- return Scalar(0);
- }
-};
-
-template<typename Scalar>
-struct sqrt_impl : sqrt_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {};
-
-template<typename Scalar>
-struct sqrt_retval
-{
- typedef Scalar type;
-};
-
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(sqrt, Scalar) sqrt(const Scalar& x)
-{
- return EIGEN_MATHFUNC_IMPL(sqrt, Scalar)::run(x);
-}
-
-/****************************************************************************
-* Implementation of standard unary real functions (exp, log, sin, cos, ... *
-****************************************************************************/
-
-// This macro instanciate all the necessary template mechanism which is common to all unary real functions.
-#define EIGEN_MATHFUNC_STANDARD_REAL_UNARY(NAME) \
- template<typename Scalar, bool IsInteger> struct NAME##_default_impl { \
- static inline Scalar run(const Scalar& x) { using std::NAME; return NAME(x); } \
- }; \
- template<typename Scalar> struct NAME##_default_impl<Scalar, true> { \
- static inline Scalar run(const Scalar&) { \
- EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) \
- return Scalar(0); \
- } \
- }; \
- template<typename Scalar> struct NAME##_impl \
- : NAME##_default_impl<Scalar, NumTraits<Scalar>::IsInteger> \
- {}; \
- template<typename Scalar> struct NAME##_retval { typedef Scalar type; }; \
- template<typename Scalar> \
- inline EIGEN_MATHFUNC_RETVAL(NAME, Scalar) NAME(const Scalar& x) { \
- return EIGEN_MATHFUNC_IMPL(NAME, Scalar)::run(x); \
- }
-
-EIGEN_MATHFUNC_STANDARD_REAL_UNARY(exp)
-EIGEN_MATHFUNC_STANDARD_REAL_UNARY(log)
-EIGEN_MATHFUNC_STANDARD_REAL_UNARY(sin)
-EIGEN_MATHFUNC_STANDARD_REAL_UNARY(cos)
-EIGEN_MATHFUNC_STANDARD_REAL_UNARY(tan)
-EIGEN_MATHFUNC_STANDARD_REAL_UNARY(asin)
-EIGEN_MATHFUNC_STANDARD_REAL_UNARY(acos)
-
-/****************************************************************************
-* Implementation of atan2 *
-****************************************************************************/
-
-template<typename Scalar, bool IsInteger>
-struct atan2_default_impl
+struct atanh2_default_impl
{
typedef Scalar retval;
+ typedef typename NumTraits<Scalar>::Real RealScalar;
static inline Scalar run(const Scalar& x, const Scalar& y)
{
- using std::atan2;
- return atan2(x, y);
+ using std::abs;
+ using std::log;
+ using std::sqrt;
+ Scalar z = x / y;
+ if (y == Scalar(0) || abs(z) > sqrt(NumTraits<RealScalar>::epsilon()))
+ return RealScalar(0.5) * log((y + x) / (y - x));
+ else
+ return z + z*z*z / RealScalar(3);
}
};
template<typename Scalar>
-struct atan2_default_impl<Scalar, true>
+struct atanh2_default_impl<Scalar, true>
{
static inline Scalar run(const Scalar&, const Scalar&)
{
@@ -505,20 +361,14 @@ struct atan2_default_impl<Scalar, true>
};
template<typename Scalar>
-struct atan2_impl : atan2_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {};
+struct atanh2_impl : atanh2_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {};
template<typename Scalar>
-struct atan2_retval
+struct atanh2_retval
{
typedef Scalar type;
};
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(atan2, Scalar) atan2(const Scalar& x, const Scalar& y)
-{
- return EIGEN_MATHFUNC_IMPL(atan2, Scalar)::run(x, y);
-}
-
/****************************************************************************
* Implementation of pow *
****************************************************************************/
@@ -562,12 +412,6 @@ struct pow_retval
typedef Scalar type;
};
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(pow, Scalar) pow(const Scalar& x, const Scalar& y)
-{
- return EIGEN_MATHFUNC_IMPL(pow, Scalar)::run(x, y);
-}
-
/****************************************************************************
* Implementation of random *
****************************************************************************/
@@ -666,11 +510,10 @@ struct random_default_impl<Scalar, false, true>
#else
enum { rand_bits = floor_log2<(unsigned int)(RAND_MAX)+1>::value,
scalar_bits = sizeof(Scalar) * CHAR_BIT,
- shift = EIGEN_PLAIN_ENUM_MAX(0, int(rand_bits) - int(scalar_bits))
+ shift = EIGEN_PLAIN_ENUM_MAX(0, int(rand_bits) - int(scalar_bits)),
+ offset = NumTraits<Scalar>::IsSigned ? (1 << (EIGEN_PLAIN_ENUM_MIN(rand_bits,scalar_bits)-1)) : 0
};
- Scalar x = Scalar(std::rand() >> shift);
- Scalar offset = NumTraits<Scalar>::IsSigned ? Scalar(1 << (rand_bits-1)) : Scalar(0);
- return x - offset;
+ return Scalar((std::rand() >> shift) - offset);
#endif
}
};
@@ -702,6 +545,97 @@ inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random()
return EIGEN_MATHFUNC_IMPL(random, Scalar)::run();
}
+} // end namespace internal
+
+/****************************************************************************
+* Generic math function *
+****************************************************************************/
+
+namespace numext {
+
+template<typename Scalar>
+inline EIGEN_MATHFUNC_RETVAL(real, Scalar) real(const Scalar& x)
+{
+ return EIGEN_MATHFUNC_IMPL(real, Scalar)::run(x);
+}
+
+template<typename Scalar>
+inline typename internal::add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) >::type real_ref(const Scalar& x)
+{
+ return internal::real_ref_impl<Scalar>::run(x);
+}
+
+template<typename Scalar>
+inline EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) real_ref(Scalar& x)
+{
+ return EIGEN_MATHFUNC_IMPL(real_ref, Scalar)::run(x);
+}
+
+template<typename Scalar>
+inline EIGEN_MATHFUNC_RETVAL(imag, Scalar) imag(const Scalar& x)
+{
+ return EIGEN_MATHFUNC_IMPL(imag, Scalar)::run(x);
+}
+
+template<typename Scalar>
+inline typename internal::add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) >::type imag_ref(const Scalar& x)
+{
+ return internal::imag_ref_impl<Scalar>::run(x);
+}
+
+template<typename Scalar>
+inline EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) imag_ref(Scalar& x)
+{
+ return EIGEN_MATHFUNC_IMPL(imag_ref, Scalar)::run(x);
+}
+
+template<typename Scalar>
+inline EIGEN_MATHFUNC_RETVAL(conj, Scalar) conj(const Scalar& x)
+{
+ return EIGEN_MATHFUNC_IMPL(conj, Scalar)::run(x);
+}
+
+template<typename Scalar>
+inline EIGEN_MATHFUNC_RETVAL(abs2, Scalar) abs2(const Scalar& x)
+{
+ return EIGEN_MATHFUNC_IMPL(abs2, Scalar)::run(x);
+}
+
+template<typename Scalar>
+inline EIGEN_MATHFUNC_RETVAL(norm1, Scalar) norm1(const Scalar& x)
+{
+ return EIGEN_MATHFUNC_IMPL(norm1, Scalar)::run(x);
+}
+
+template<typename Scalar>
+inline EIGEN_MATHFUNC_RETVAL(hypot, Scalar) hypot(const Scalar& x, const Scalar& y)
+{
+ return EIGEN_MATHFUNC_IMPL(hypot, Scalar)::run(x, y);
+}
+
+template<typename Scalar>
+inline EIGEN_MATHFUNC_RETVAL(atanh2, Scalar) atanh2(const Scalar& x, const Scalar& y)
+{
+ return EIGEN_MATHFUNC_IMPL(atanh2, Scalar)::run(x, y);
+}
+
+template<typename Scalar>
+inline EIGEN_MATHFUNC_RETVAL(pow, Scalar) pow(const Scalar& x, const Scalar& y)
+{
+ return EIGEN_MATHFUNC_IMPL(pow, Scalar)::run(x, y);
+}
+
+// std::isfinite is non standard, so let's define our own version,
+// even though it is not very efficient.
+template<typename T> bool (isfinite)(const T& x)
+{
+ return x<NumTraits<T>::highest() && x>NumTraits<T>::lowest();
+}
+
+} // end namespace numext
+
+namespace internal {
+
/****************************************************************************
* Implementation of fuzzy comparisons *
****************************************************************************/
@@ -718,11 +652,13 @@ struct scalar_fuzzy_default_impl<Scalar, false, false>
template<typename OtherScalar>
static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec)
{
+ using std::abs;
return abs(x) <= abs(y) * prec;
}
static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec)
{
using std::min;
+ using std::abs;
return abs(x - y) <= (min)(abs(x), abs(y)) * prec;
}
static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar& prec)
@@ -757,12 +693,12 @@ struct scalar_fuzzy_default_impl<Scalar, true, false>
template<typename OtherScalar>
static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec)
{
- return abs2(x) <= abs2(y) * prec * prec;
+ return numext::abs2(x) <= numext::abs2(y) * prec * prec;
}
static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec)
{
using std::min;
- return abs2(x - y) <= (min)(abs2(x), abs2(y)) * prec * prec;
+ return numext::abs2(x - y) <= (min)(numext::abs2(x), numext::abs2(y)) * prec * prec;
}
};
@@ -824,17 +760,7 @@ template<> struct scalar_fuzzy_impl<bool>
};
-/****************************************************************************
-* Special functions *
-****************************************************************************/
-
-// std::isfinite is non standard, so let's define our own version,
-// even though it is not very efficient.
-template<typename T> bool (isfinite)(const T& x)
-{
- return x<NumTraits<T>::highest() && x>NumTraits<T>::lowest();
-}
-
+
} // end namespace internal
} // end namespace Eigen
diff --git a/Eigen/src/Core/Matrix.h b/Eigen/src/Core/Matrix.h
index 99160b591..d7d0b5b9a 100644
--- a/Eigen/src/Core/Matrix.h
+++ b/Eigen/src/Core/Matrix.h
@@ -200,16 +200,16 @@ class Matrix
*
* \sa resize(Index,Index)
*/
- EIGEN_STRONG_INLINE explicit Matrix() : Base()
+ EIGEN_STRONG_INLINE Matrix() : Base()
{
Base::_check_template_params();
- EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
+ EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
}
// FIXME is it still needed
Matrix(internal::constructor_without_unaligned_array_assert)
: Base(internal::constructor_without_unaligned_array_assert())
- { Base::_check_template_params(); EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED }
+ { Base::_check_template_params(); EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED }
/** \brief Constructs a vector or row-vector with given dimension. \only_for_vectors
*
@@ -224,7 +224,7 @@ class Matrix
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Matrix)
eigen_assert(dim >= 0);
eigen_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == dim);
- EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
+ EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
}
#ifndef EIGEN_PARSED_BY_DOXYGEN
@@ -304,7 +304,7 @@ class Matrix
: Base(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols())
{
Base::_check_template_params();
- Base::resize(other.rows(), other.cols());
+ Base::_resize_to_match(other);
// FIXME/CHECK: isn't *this = other.derived() more efficient. it allows to
// go for pure _set() implementations, right?
*this = other;
diff --git a/Eigen/src/Core/MatrixBase.h b/Eigen/src/Core/MatrixBase.h
index c1e0ed132..344b38f2f 100644
--- a/Eigen/src/Core/MatrixBase.h
+++ b/Eigen/src/Core/MatrixBase.h
@@ -162,6 +162,9 @@ template<typename Derived> class MatrixBase
#ifndef EIGEN_PARSED_BY_DOXYGEN
template<typename ProductDerived, typename Lhs, typename Rhs>
Derived& lazyAssign(const ProductBase<ProductDerived, Lhs,Rhs>& other);
+
+ template<typename MatrixPower, typename Lhs, typename Rhs>
+ Derived& lazyAssign(const MatrixPowerProduct<MatrixPower, Lhs,Rhs>& other);
#endif // not EIGEN_PARSED_BY_DOXYGEN
template<typename OtherDerived>
@@ -212,8 +215,8 @@ template<typename Derived> class MatrixBase
typedef Diagonal<Derived> DiagonalReturnType;
DiagonalReturnType diagonal();
- typedef const Diagonal<const Derived> ConstDiagonalReturnType;
- const ConstDiagonalReturnType diagonal() const;
+ typedef typename internal::add_const<Diagonal<const Derived> >::type ConstDiagonalReturnType;
+ ConstDiagonalReturnType diagonal() const;
template<int Index> struct DiagonalIndexReturnType { typedef Diagonal<Derived,Index> Type; };
template<int Index> struct ConstDiagonalIndexReturnType { typedef const Diagonal<const Derived,Index> Type; };
@@ -224,11 +227,11 @@ template<typename Derived> class MatrixBase
// Note: The "MatrixBase::" prefixes are added to help MSVC9 to match these declarations with the later implementations.
// On the other hand they confuse MSVC8...
#if (defined _MSC_VER) && (_MSC_VER >= 1500) // 2008 or later
- typename MatrixBase::template DiagonalIndexReturnType<Dynamic>::Type diagonal(Index index);
- typename MatrixBase::template ConstDiagonalIndexReturnType<Dynamic>::Type diagonal(Index index) const;
+ typename MatrixBase::template DiagonalIndexReturnType<DynamicIndex>::Type diagonal(Index index);
+ typename MatrixBase::template ConstDiagonalIndexReturnType<DynamicIndex>::Type diagonal(Index index) const;
#else
- typename DiagonalIndexReturnType<Dynamic>::Type diagonal(Index index);
- typename ConstDiagonalIndexReturnType<Dynamic>::Type diagonal(Index index) const;
+ typename DiagonalIndexReturnType<DynamicIndex>::Type diagonal(Index index);
+ typename ConstDiagonalIndexReturnType<DynamicIndex>::Type diagonal(Index index) const;
#endif
#ifdef EIGEN2_SUPPORT
@@ -237,7 +240,7 @@ template<typename Derived> class MatrixBase
// huuuge hack. make Eigen2's matrix.part<Diagonal>() work in eigen3. Problem: Diagonal is now a class template instead
// of an integer constant. Solution: overload the part() method template wrt template parameters list.
- template<template<typename T, int n> class U>
+ template<template<typename T, int N> class U>
const DiagonalWrapper<ConstDiagonalReturnType> part() const
{ return diagonal().asDiagonal(); }
#endif // EIGEN2_SUPPORT
@@ -255,7 +258,7 @@ template<typename Derived> class MatrixBase
template<unsigned int UpLo> typename ConstSelfAdjointViewReturnType<UpLo>::Type selfadjointView() const;
const SparseView<Derived> sparseView(const Scalar& m_reference = Scalar(0),
- typename NumTraits<Scalar>::Real m_epsilon = NumTraits<Scalar>::dummy_precision()) const;
+ const typename NumTraits<Scalar>::Real& m_epsilon = NumTraits<Scalar>::dummy_precision()) const;
static const IdentityReturnType Identity();
static const IdentityReturnType Identity(Index rows, Index cols);
static const BasisReturnType Unit(Index size, Index i);
@@ -271,16 +274,16 @@ template<typename Derived> class MatrixBase
Derived& setIdentity();
Derived& setIdentity(Index rows, Index cols);
- bool isIdentity(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
- bool isDiagonal(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
+ bool isIdentity(const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
+ bool isDiagonal(const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
- bool isUpperTriangular(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
- bool isLowerTriangular(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
+ bool isUpperTriangular(const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
+ bool isLowerTriangular(const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
template<typename OtherDerived>
bool isOrthogonal(const MatrixBase<OtherDerived>& other,
- RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
- bool isUnitary(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
+ const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
+ bool isUnitary(const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
/** \returns true if each coefficients of \c *this and \a other are all exactly equal.
* \warning When using floating point scalar values you probably should rather use a
@@ -314,7 +317,7 @@ template<typename Derived> class MatrixBase
MatrixBase<Derived>& matrix() { return *this; }
const MatrixBase<Derived>& matrix() const { return *this; }
- /** \returns an \link ArrayBase Array \endlink expression of this matrix
+ /** \returns an \link Eigen::ArrayBase Array \endlink expression of this matrix
* \sa ArrayBase::matrix() */
ArrayWrapper<Derived> array() { return derived(); }
const ArrayWrapper<const Derived> array() const { return derived(); }
@@ -454,6 +457,7 @@ template<typename Derived> class MatrixBase
const MatrixFunctionReturnValue<Derived> sin() const;
const MatrixSquareRootReturnValue<Derived> sqrt() const;
const MatrixLogarithmReturnValue<Derived> log() const;
+ const MatrixPowerReturnValue<Derived> pow(const RealScalar& p) const;
#ifdef EIGEN2_SUPPORT
template<typename ProductDerived, typename Lhs, typename Rhs>
@@ -506,6 +510,51 @@ template<typename Derived> class MatrixBase
{EIGEN_STATIC_ASSERT(std::ptrdiff_t(sizeof(typename OtherDerived::Scalar))==-1,YOU_CANNOT_MIX_ARRAYS_AND_MATRICES); return *this;}
};
+
+/***************************************************************************
+* Implementation of matrix base methods
+***************************************************************************/
+
+/** replaces \c *this by \c *this * \a other.
+ *
+ * \returns a reference to \c *this
+ *
+ * Example: \include MatrixBase_applyOnTheRight.cpp
+ * Output: \verbinclude MatrixBase_applyOnTheRight.out
+ */
+template<typename Derived>
+template<typename OtherDerived>
+inline Derived&
+MatrixBase<Derived>::operator*=(const EigenBase<OtherDerived> &other)
+{
+ other.derived().applyThisOnTheRight(derived());
+ return derived();
+}
+
+/** replaces \c *this by \c *this * \a other. It is equivalent to MatrixBase::operator*=().
+ *
+ * Example: \include MatrixBase_applyOnTheRight.cpp
+ * Output: \verbinclude MatrixBase_applyOnTheRight.out
+ */
+template<typename Derived>
+template<typename OtherDerived>
+inline void MatrixBase<Derived>::applyOnTheRight(const EigenBase<OtherDerived> &other)
+{
+ other.derived().applyThisOnTheRight(derived());
+}
+
+/** replaces \c *this by \a other * \c *this.
+ *
+ * Example: \include MatrixBase_applyOnTheLeft.cpp
+ * Output: \verbinclude MatrixBase_applyOnTheLeft.out
+ */
+template<typename Derived>
+template<typename OtherDerived>
+inline void MatrixBase<Derived>::applyOnTheLeft(const EigenBase<OtherDerived> &other)
+{
+ other.derived().applyThisOnTheLeft(derived());
+}
+
} // end namespace Eigen
#endif // EIGEN_MATRIXBASE_H
diff --git a/Eigen/src/Core/NoAlias.h b/Eigen/src/Core/NoAlias.h
index ecb3fa285..768bfb18c 100644
--- a/Eigen/src/Core/NoAlias.h
+++ b/Eigen/src/Core/NoAlias.h
@@ -80,8 +80,17 @@ class NoAlias
template<typename Lhs, typename Rhs, int NestingFlags>
EIGEN_STRONG_INLINE ExpressionType& operator-=(const CoeffBasedProduct<Lhs,Rhs,NestingFlags>& other)
{ return m_expression.derived() -= CoeffBasedProduct<Lhs,Rhs,NestByRefBit>(other.lhs(), other.rhs()); }
+
+ template<typename OtherDerived>
+ ExpressionType& operator=(const ReturnByValue<OtherDerived>& func)
+ { return m_expression = func; }
#endif
+ ExpressionType& expression() const
+ {
+ return m_expression;
+ }
+
protected:
ExpressionType& m_expression;
};
diff --git a/Eigen/src/Core/NumTraits.h b/Eigen/src/Core/NumTraits.h
index c94ef026b..bac9e50b8 100644
--- a/Eigen/src/Core/NumTraits.h
+++ b/Eigen/src/Core/NumTraits.h
@@ -140,6 +140,9 @@ struct NumTraits<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> >
AddCost = ArrayType::SizeAtCompileTime==Dynamic ? Dynamic : ArrayType::SizeAtCompileTime * NumTraits<Scalar>::AddCost,
MulCost = ArrayType::SizeAtCompileTime==Dynamic ? Dynamic : ArrayType::SizeAtCompileTime * NumTraits<Scalar>::MulCost
};
+
+ static inline RealScalar epsilon() { return NumTraits<RealScalar>::epsilon(); }
+ static inline RealScalar dummy_precision() { return NumTraits<RealScalar>::dummy_precision(); }
};
} // end namespace Eigen
diff --git a/Eigen/src/Core/PermutationMatrix.h b/Eigen/src/Core/PermutationMatrix.h
index bc29f8142..1297b8413 100644
--- a/Eigen/src/Core/PermutationMatrix.h
+++ b/Eigen/src/Core/PermutationMatrix.h
@@ -105,13 +105,13 @@ class PermutationBase : public EigenBase<Derived>
#endif
/** \returns the number of rows */
- inline Index rows() const { return indices().size(); }
+ inline Index rows() const { return Index(indices().size()); }
/** \returns the number of columns */
- inline Index cols() const { return indices().size(); }
+ inline Index cols() const { return Index(indices().size()); }
/** \returns the size of a side of the respective square matrix, i.e., the number of indices */
- inline Index size() const { return indices().size(); }
+ inline Index size() const { return Index(indices().size()); }
#ifndef EIGEN_PARSED_BY_DOXYGEN
template<typename DenseDerived>
@@ -139,9 +139,9 @@ class PermutationBase : public EigenBase<Derived>
/** Resizes to given size.
*/
- inline void resize(Index size)
+ inline void resize(Index newSize)
{
- indices().resize(size);
+ indices().resize(newSize);
}
/** Sets *this to be the identity permutation matrix */
@@ -153,9 +153,9 @@ class PermutationBase : public EigenBase<Derived>
/** Sets *this to be the identity permutation matrix of given size.
*/
- void setIdentity(Index size)
+ void setIdentity(Index newSize)
{
- resize(size);
+ resize(newSize);
setIdentity();
}
@@ -317,7 +317,7 @@ class PermutationMatrix : public PermutationBase<PermutationMatrix<SizeAtCompile
* array's size.
*/
template<typename Other>
- explicit inline PermutationMatrix(const MatrixBase<Other>& indices) : m_indices(indices)
+ explicit inline PermutationMatrix(const MatrixBase<Other>& a_indices) : m_indices(a_indices)
{}
/** Convert the Transpositions \a tr to a permutation matrix */
@@ -406,12 +406,12 @@ class Map<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, IndexType>,
typedef typename IndicesType::Scalar Index;
#endif
- inline Map(const Index* indices)
- : m_indices(indices)
+ inline Map(const Index* indicesPtr)
+ : m_indices(indicesPtr)
{}
- inline Map(const Index* indices, Index size)
- : m_indices(indices,size)
+ inline Map(const Index* indicesPtr, Index size)
+ : m_indices(indicesPtr,size)
{}
/** Copies the other permutation into *this */
@@ -490,8 +490,8 @@ class PermutationWrapper : public PermutationBase<PermutationWrapper<_IndicesTyp
typedef typename Traits::IndicesType IndicesType;
#endif
- inline PermutationWrapper(const IndicesType& indices)
- : m_indices(indices)
+ inline PermutationWrapper(const IndicesType& a_indices)
+ : m_indices(a_indices)
{}
/** const version of indices(). */
@@ -541,24 +541,26 @@ struct permut_matrix_product_retval
: public ReturnByValue<permut_matrix_product_retval<PermutationType, MatrixType, Side, Transposed> >
{
typedef typename remove_all<typename MatrixType::Nested>::type MatrixTypeNestedCleaned;
+ typedef typename MatrixType::Index Index;
permut_matrix_product_retval(const PermutationType& perm, const MatrixType& matrix)
: m_permutation(perm), m_matrix(matrix)
{}
- inline int rows() const { return m_matrix.rows(); }
- inline int cols() const { return m_matrix.cols(); }
+ inline Index rows() const { return m_matrix.rows(); }
+ inline Index cols() const { return m_matrix.cols(); }
template<typename Dest> inline void evalTo(Dest& dst) const
{
- const int n = Side==OnTheLeft ? rows() : cols();
-
+ const Index n = Side==OnTheLeft ? rows() : cols();
+ // FIXME we need an is_same for expression that is not sensitive to constness. For instance
+ // is_same_xpr<Block<const Matrix>, Block<Matrix> >::value should be true.
if(is_same<MatrixTypeNestedCleaned,Dest>::value && extract_data(dst) == extract_data(m_matrix))
{
// apply the permutation inplace
Matrix<bool,PermutationType::RowsAtCompileTime,1,0,PermutationType::MaxRowsAtCompileTime> mask(m_permutation.size());
mask.fill(false);
- int r = 0;
+ Index r = 0;
while(r < m_permutation.size())
{
// search for the next seed
@@ -566,10 +568,10 @@ struct permut_matrix_product_retval
if(r>=m_permutation.size())
break;
// we got one, let's follow it until we are back to the seed
- int k0 = r++;
- int kPrev = k0;
+ Index k0 = r++;
+ Index kPrev = k0;
mask.coeffRef(k0) = true;
- for(int k=m_permutation.indices().coeff(k0); k!=k0; k=m_permutation.indices().coeff(k))
+ for(Index k=m_permutation.indices().coeff(k0); k!=k0; k=m_permutation.indices().coeff(k))
{
Block<Dest, Side==OnTheLeft ? 1 : Dest::RowsAtCompileTime, Side==OnTheRight ? 1 : Dest::ColsAtCompileTime>(dst, k)
.swap(Block<Dest, Side==OnTheLeft ? 1 : Dest::RowsAtCompileTime, Side==OnTheRight ? 1 : Dest::ColsAtCompileTime>
diff --git a/Eigen/src/Core/PlainObjectBase.h b/Eigen/src/Core/PlainObjectBase.h
index 71c74309a..dd34b59e5 100644
--- a/Eigen/src/Core/PlainObjectBase.h
+++ b/Eigen/src/Core/PlainObjectBase.h
@@ -11,30 +11,46 @@
#ifndef EIGEN_DENSESTORAGEBASE_H
#define EIGEN_DENSESTORAGEBASE_H
-#ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
-# define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED for(int i=0;i<base().size();++i) coeffRef(i)=Scalar(0);
+#if defined(EIGEN_INITIALIZE_MATRICES_BY_ZERO)
+# define EIGEN_INITIALIZE_COEFFS
+# define EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED for(int i=0;i<base().size();++i) coeffRef(i)=Scalar(0);
+#elif defined(EIGEN_INITIALIZE_MATRICES_BY_NAN)
+# define EIGEN_INITIALIZE_COEFFS
+# define EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED for(int i=0;i<base().size();++i) coeffRef(i)=std::numeric_limits<Scalar>::quiet_NaN();
#else
-# define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
+# undef EIGEN_INITIALIZE_COEFFS
+# define EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
#endif
namespace Eigen {
namespace internal {
-template<typename Index>
-EIGEN_ALWAYS_INLINE void check_rows_cols_for_overflow(Index rows, Index cols)
-{
- // http://hg.mozilla.org/mozilla-central/file/6c8a909977d3/xpcom/ds/CheckedInt.h#l242
- // we assume Index is signed
- Index max_index = (size_t(1) << (8 * sizeof(Index) - 1)) - 1; // assume Index is signed
- bool error = (rows < 0 || cols < 0) ? true
- : (rows == 0 || cols == 0) ? false
- : (rows > max_index / cols);
- if (error)
- throw_std_bad_alloc();
-}
-
-template <typename Derived, typename OtherDerived = Derived, bool IsVector = bool(Derived::IsVectorAtCompileTime)> struct conservative_resize_like_impl;
+template<int MaxSizeAtCompileTime> struct check_rows_cols_for_overflow {
+ template<typename Index>
+ static EIGEN_ALWAYS_INLINE void run(Index, Index)
+ {
+ }
+};
+
+template<> struct check_rows_cols_for_overflow<Dynamic> {
+ template<typename Index>
+ static EIGEN_ALWAYS_INLINE void run(Index rows, Index cols)
+ {
+ // http://hg.mozilla.org/mozilla-central/file/6c8a909977d3/xpcom/ds/CheckedInt.h#l242
+ // we assume Index is signed
+ Index max_index = (size_t(1) << (8 * sizeof(Index) - 1)) - 1; // assume Index is signed
+ bool error = (rows == 0 || cols == 0) ? false
+ : (rows > max_index / cols);
+ if (error)
+ throw_std_bad_alloc();
+ }
+};
+
+template <typename Derived,
+ typename OtherDerived = Derived,
+ bool IsVector = bool(Derived::IsVectorAtCompileTime) && bool(OtherDerived::IsVectorAtCompileTime)>
+struct conservative_resize_like_impl;
template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> struct matrix_swap_impl;
@@ -119,12 +135,12 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
EIGEN_STRONG_INLINE Index rows() const { return m_storage.rows(); }
EIGEN_STRONG_INLINE Index cols() const { return m_storage.cols(); }
- EIGEN_STRONG_INLINE const Scalar& coeff(Index row, Index col) const
+ EIGEN_STRONG_INLINE const Scalar& coeff(Index rowId, Index colId) const
{
if(Flags & RowMajorBit)
- return m_storage.data()[col + row * m_storage.cols()];
+ return m_storage.data()[colId + rowId * m_storage.cols()];
else // column-major
- return m_storage.data()[row + col * m_storage.rows()];
+ return m_storage.data()[rowId + colId * m_storage.rows()];
}
EIGEN_STRONG_INLINE const Scalar& coeff(Index index) const
@@ -132,12 +148,12 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
return m_storage.data()[index];
}
- EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col)
+ EIGEN_STRONG_INLINE Scalar& coeffRef(Index rowId, Index colId)
{
if(Flags & RowMajorBit)
- return m_storage.data()[col + row * m_storage.cols()];
+ return m_storage.data()[colId + rowId * m_storage.cols()];
else // column-major
- return m_storage.data()[row + col * m_storage.rows()];
+ return m_storage.data()[rowId + colId * m_storage.rows()];
}
EIGEN_STRONG_INLINE Scalar& coeffRef(Index index)
@@ -145,12 +161,12 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
return m_storage.data()[index];
}
- EIGEN_STRONG_INLINE const Scalar& coeffRef(Index row, Index col) const
+ EIGEN_STRONG_INLINE const Scalar& coeffRef(Index rowId, Index colId) const
{
if(Flags & RowMajorBit)
- return m_storage.data()[col + row * m_storage.cols()];
+ return m_storage.data()[colId + rowId * m_storage.cols()];
else // column-major
- return m_storage.data()[row + col * m_storage.rows()];
+ return m_storage.data()[rowId + colId * m_storage.rows()];
}
EIGEN_STRONG_INLINE const Scalar& coeffRef(Index index) const
@@ -160,12 +176,12 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
/** \internal */
template<int LoadMode>
- EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const
+ EIGEN_STRONG_INLINE PacketScalar packet(Index rowId, Index colId) const
{
return internal::ploadt<PacketScalar, LoadMode>
(m_storage.data() + (Flags & RowMajorBit
- ? col + row * m_storage.cols()
- : row + col * m_storage.rows()));
+ ? colId + rowId * m_storage.cols()
+ : rowId + colId * m_storage.rows()));
}
/** \internal */
@@ -177,19 +193,19 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
/** \internal */
template<int StoreMode>
- EIGEN_STRONG_INLINE void writePacket(Index row, Index col, const PacketScalar& x)
+ EIGEN_STRONG_INLINE void writePacket(Index rowId, Index colId, const PacketScalar& val)
{
internal::pstoret<Scalar, PacketScalar, StoreMode>
(m_storage.data() + (Flags & RowMajorBit
- ? col + row * m_storage.cols()
- : row + col * m_storage.rows()), x);
+ ? colId + rowId * m_storage.cols()
+ : rowId + colId * m_storage.rows()), val);
}
/** \internal */
template<int StoreMode>
- EIGEN_STRONG_INLINE void writePacket(Index index, const PacketScalar& x)
+ EIGEN_STRONG_INLINE void writePacket(Index index, const PacketScalar& val)
{
- internal::pstoret<Scalar, PacketScalar, StoreMode>(m_storage.data() + index, x);
+ internal::pstoret<Scalar, PacketScalar, StoreMode>(m_storage.data() + index, val);
}
/** \returns a const pointer to the data array of this matrix */
@@ -216,17 +232,22 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
*
* \sa resize(Index) for vectors, resize(NoChange_t, Index), resize(Index, NoChange_t)
*/
- EIGEN_STRONG_INLINE void resize(Index rows, Index cols)
- {
- #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
- internal::check_rows_cols_for_overflow(rows, cols);
- Index size = rows*cols;
+ EIGEN_STRONG_INLINE void resize(Index nbRows, Index nbCols)
+ {
+ eigen_assert( EIGEN_IMPLIES(RowsAtCompileTime!=Dynamic,nbRows==RowsAtCompileTime)
+ && EIGEN_IMPLIES(ColsAtCompileTime!=Dynamic,nbCols==ColsAtCompileTime)
+ && EIGEN_IMPLIES(RowsAtCompileTime==Dynamic && MaxRowsAtCompileTime!=Dynamic,nbRows<=MaxRowsAtCompileTime)
+ && EIGEN_IMPLIES(ColsAtCompileTime==Dynamic && MaxColsAtCompileTime!=Dynamic,nbCols<=MaxColsAtCompileTime)
+ && nbRows>=0 && nbCols>=0 && "Invalid sizes when resizing a matrix or array.");
+ internal::check_rows_cols_for_overflow<MaxSizeAtCompileTime>::run(nbRows, nbCols);
+ #ifdef EIGEN_INITIALIZE_COEFFS
+ Index size = nbRows*nbCols;
bool size_changed = size != this->size();
- m_storage.resize(size, rows, cols);
- if(size_changed) EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
+ m_storage.resize(size, nbRows, nbCols);
+ if(size_changed) EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
#else
- internal::check_rows_cols_for_overflow(rows, cols);
- m_storage.resize(rows*cols, rows, cols);
+ internal::check_rows_cols_for_overflow<MaxSizeAtCompileTime>::run(nbRows, nbCols);
+ m_storage.resize(nbRows*nbCols, nbRows, nbCols);
#endif
}
@@ -244,16 +265,16 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
inline void resize(Index size)
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(PlainObjectBase)
- eigen_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == size);
- #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
+ eigen_assert(((SizeAtCompileTime == Dynamic && (MaxSizeAtCompileTime==Dynamic || size<=MaxSizeAtCompileTime)) || SizeAtCompileTime == size) && size>=0);
+ #ifdef EIGEN_INITIALIZE_COEFFS
bool size_changed = size != this->size();
#endif
if(RowsAtCompileTime == 1)
m_storage.resize(size, 1, size);
else
m_storage.resize(size, size, 1);
- #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
- if(size_changed) EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
+ #ifdef EIGEN_INITIALIZE_COEFFS
+ if(size_changed) EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
#endif
}
@@ -265,9 +286,9 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
*
* \sa resize(Index,Index)
*/
- inline void resize(NoChange_t, Index cols)
+ inline void resize(NoChange_t, Index nbCols)
{
- resize(rows(), cols);
+ resize(rows(), nbCols);
}
/** Resizes the matrix, changing only the number of rows. For the parameter of type NoChange_t, just pass the special value \c NoChange
@@ -278,9 +299,9 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
*
* \sa resize(Index,Index)
*/
- inline void resize(Index rows, NoChange_t)
+ inline void resize(Index nbRows, NoChange_t)
{
- resize(rows, cols());
+ resize(nbRows, cols());
}
/** Resizes \c *this to have the same dimensions as \a other.
@@ -294,7 +315,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
EIGEN_STRONG_INLINE void resizeLike(const EigenBase<OtherDerived>& _other)
{
const OtherDerived& other = _other.derived();
- internal::check_rows_cols_for_overflow(other.rows(), other.cols());
+ internal::check_rows_cols_for_overflow<MaxSizeAtCompileTime>::run(other.rows(), other.cols());
const Index othersize = other.rows()*other.cols();
if(RowsAtCompileTime == 1)
{
@@ -318,9 +339,9 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
* Matrices are resized relative to the top-left element. In case values need to be
* appended to the matrix they will be uninitialized.
*/
- EIGEN_STRONG_INLINE void conservativeResize(Index rows, Index cols)
+ EIGEN_STRONG_INLINE void conservativeResize(Index nbRows, Index nbCols)
{
- internal::conservative_resize_like_impl<Derived>::run(*this, rows, cols);
+ internal::conservative_resize_like_impl<Derived>::run(*this, nbRows, nbCols);
}
/** Resizes the matrix to \a rows x \a cols while leaving old values untouched.
@@ -330,10 +351,10 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
*
* In case the matrix is growing, new rows will be uninitialized.
*/
- EIGEN_STRONG_INLINE void conservativeResize(Index rows, NoChange_t)
+ EIGEN_STRONG_INLINE void conservativeResize(Index nbRows, NoChange_t)
{
// Note: see the comment in conservativeResize(Index,Index)
- conservativeResize(rows, cols());
+ conservativeResize(nbRows, cols());
}
/** Resizes the matrix to \a rows x \a cols while leaving old values untouched.
@@ -343,10 +364,10 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
*
* In case the matrix is growing, new columns will be uninitialized.
*/
- EIGEN_STRONG_INLINE void conservativeResize(NoChange_t, Index cols)
+ EIGEN_STRONG_INLINE void conservativeResize(NoChange_t, Index nbCols)
{
// Note: see the comment in conservativeResize(Index,Index)
- conservativeResize(rows(), cols);
+ conservativeResize(rows(), nbCols);
}
/** Resizes the vector to \a size while retaining old values.
@@ -400,10 +421,10 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
return Base::operator=(func);
}
- EIGEN_STRONG_INLINE explicit PlainObjectBase() : m_storage()
+ EIGEN_STRONG_INLINE PlainObjectBase() : m_storage()
{
// _check_template_params();
-// EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
+// EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
}
#ifndef EIGEN_PARSED_BY_DOXYGEN
@@ -412,15 +433,15 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
PlainObjectBase(internal::constructor_without_unaligned_array_assert)
: m_storage(internal::constructor_without_unaligned_array_assert())
{
-// _check_template_params(); EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
+// _check_template_params(); EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
}
#endif
- EIGEN_STRONG_INLINE PlainObjectBase(Index size, Index rows, Index cols)
- : m_storage(size, rows, cols)
+ EIGEN_STRONG_INLINE PlainObjectBase(Index a_size, Index nbRows, Index nbCols)
+ : m_storage(a_size, nbRows, nbCols)
{
// _check_template_params();
-// EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
+// EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
}
/** \copydoc MatrixBase::operator=(const EigenBase<OtherDerived>&)
@@ -439,7 +460,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
: m_storage(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols())
{
_check_template_params();
- internal::check_rows_cols_for_overflow(other.derived().rows(), other.derived().cols());
+ internal::check_rows_cols_for_overflow<MaxSizeAtCompileTime>::run(other.derived().rows(), other.derived().cols());
Base::operator=(other.derived());
}
@@ -551,6 +572,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
eigen_assert((this->size()==0 || (IsVectorAtCompileTime ? (this->size() == other.size())
: (rows() == other.rows() && cols() == other.cols())))
&& "Size mismatch. Automatic resizing is disabled because EIGEN_NO_AUTOMATIC_RESIZING is defined");
+ EIGEN_ONLY_USED_FOR_DEBUG(other);
#else
resizeLike(other);
#endif
@@ -600,23 +622,19 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
}
template<typename T0, typename T1>
- EIGEN_STRONG_INLINE void _init2(Index rows, Index cols, typename internal::enable_if<Base::SizeAtCompileTime!=2,T0>::type* = 0)
+ EIGEN_STRONG_INLINE void _init2(Index nbRows, Index nbCols, typename internal::enable_if<Base::SizeAtCompileTime!=2,T0>::type* = 0)
{
EIGEN_STATIC_ASSERT(bool(NumTraits<T0>::IsInteger) &&
bool(NumTraits<T1>::IsInteger),
FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED)
- eigen_assert(rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
- && cols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
- internal::check_rows_cols_for_overflow(rows, cols);
- m_storage.resize(rows*cols,rows,cols);
- EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
+ resize(nbRows,nbCols);
}
template<typename T0, typename T1>
- EIGEN_STRONG_INLINE void _init2(const Scalar& x, const Scalar& y, typename internal::enable_if<Base::SizeAtCompileTime==2,T0>::type* = 0)
+ EIGEN_STRONG_INLINE void _init2(const Scalar& val0, const Scalar& val1, typename internal::enable_if<Base::SizeAtCompileTime==2,T0>::type* = 0)
{
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 2)
- m_storage.data()[0] = x;
- m_storage.data()[1] = y;
+ m_storage.data()[0] = val0;
+ m_storage.data()[1] = val1;
}
template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers>
@@ -653,8 +671,10 @@ private:
enum { ThisConstantIsPrivateInPlainObjectBase };
};
+namespace internal {
+
template <typename Derived, typename OtherDerived, bool IsVector>
-struct internal::conservative_resize_like_impl
+struct conservative_resize_like_impl
{
typedef typename Derived::Index Index;
static void run(DenseBase<Derived>& _this, Index rows, Index cols)
@@ -665,7 +685,7 @@ struct internal::conservative_resize_like_impl
if ( ( Derived::IsRowMajor && _this.cols() == cols) || // row-major and we change only the number of rows
(!Derived::IsRowMajor && _this.rows() == rows) ) // column-major and we change only the number of columns
{
- internal::check_rows_cols_for_overflow(rows, cols);
+ internal::check_rows_cols_for_overflow<Derived::MaxSizeAtCompileTime>::run(rows, cols);
_this.derived().m_storage.conservativeResize(rows*cols,rows,cols);
}
else
@@ -714,11 +734,14 @@ struct internal::conservative_resize_like_impl
}
};
-namespace internal {
-
+// Here, the specialization for vectors inherits from the general matrix case
+// to allow calling .conservativeResize(rows,cols) on vectors.
template <typename Derived, typename OtherDerived>
struct conservative_resize_like_impl<Derived,OtherDerived,true>
+ : conservative_resize_like_impl<Derived,OtherDerived,false>
{
+ using conservative_resize_like_impl<Derived,OtherDerived,false>::run;
+
typedef typename Derived::Index Index;
static void run(DenseBase<Derived>& _this, Index size)
{
diff --git a/Eigen/src/Core/Product.h b/Eigen/src/Core/Product.h
deleted file mode 100644
index 30aa8943b..000000000
--- a/Eigen/src/Core/Product.h
+++ /dev/null
@@ -1,98 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2011 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef EIGEN_PRODUCT_H
-#define EIGEN_PRODUCT_H
-
-template<typename Lhs, typename Rhs> class Product;
-template<typename Lhs, typename Rhs, typename StorageKind> class ProductImpl;
-
-/** \class Product
- * \ingroup Core_Module
- *
- * \brief Expression of the product of two arbitrary matrices or vectors
- *
- * \param Lhs the type of the left-hand side expression
- * \param Rhs the type of the right-hand side expression
- *
- * This class represents an expression of the product of two arbitrary matrices.
- *
- */
-
-namespace internal {
-template<typename Lhs, typename Rhs>
-struct traits<Product<Lhs, Rhs> >
-{
- typedef MatrixXpr XprKind;
- typedef typename remove_all<Lhs>::type LhsCleaned;
- typedef typename remove_all<Rhs>::type RhsCleaned;
- typedef typename scalar_product_traits<typename traits<LhsCleaned>::Scalar, typename traits<RhsCleaned>::Scalar>::ReturnType Scalar;
- typedef typename promote_storage_type<typename traits<LhsCleaned>::StorageKind,
- typename traits<RhsCleaned>::StorageKind>::ret StorageKind;
- typedef typename promote_index_type<typename traits<LhsCleaned>::Index,
- typename traits<RhsCleaned>::Index>::type Index;
- enum {
- RowsAtCompileTime = LhsCleaned::RowsAtCompileTime,
- ColsAtCompileTime = RhsCleaned::ColsAtCompileTime,
- MaxRowsAtCompileTime = LhsCleaned::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = RhsCleaned::MaxColsAtCompileTime,
- Flags = (MaxRowsAtCompileTime==1 ? RowMajorBit : 0), // TODO should be no storage order
- CoeffReadCost = 0 // TODO CoeffReadCost should not be part of the expression traits
- };
-};
-} // end namespace internal
-
-
-template<typename Lhs, typename Rhs>
-class Product : public ProductImpl<Lhs,Rhs,typename internal::promote_storage_type<typename internal::traits<Lhs>::StorageKind,
- typename internal::traits<Rhs>::StorageKind>::ret>
-{
- public:
-
- typedef typename ProductImpl<
- Lhs, Rhs,
- typename internal::promote_storage_type<typename Lhs::StorageKind,
- typename Rhs::StorageKind>::ret>::Base Base;
- EIGEN_GENERIC_PUBLIC_INTERFACE(Product)
-
- typedef typename Lhs::Nested LhsNested;
- typedef typename Rhs::Nested RhsNested;
- typedef typename internal::remove_all<LhsNested>::type LhsNestedCleaned;
- typedef typename internal::remove_all<RhsNested>::type RhsNestedCleaned;
-
- Product(const Lhs& lhs, const Rhs& rhs) : m_lhs(lhs), m_rhs(rhs)
- {
- eigen_assert(lhs.cols() == rhs.rows()
- && "invalid matrix product"
- && "if you wanted a coeff-wise or a dot product use the respective explicit functions");
- }
-
- inline Index rows() const { return m_lhs.rows(); }
- inline Index cols() const { return m_rhs.cols(); }
-
- const LhsNestedCleaned& lhs() const { return m_lhs; }
- const RhsNestedCleaned& rhs() const { return m_rhs; }
-
- protected:
-
- const LhsNested m_lhs;
- const RhsNested m_rhs;
-};
-
-template<typename Lhs, typename Rhs>
-class ProductImpl<Lhs,Rhs,Dense> : public internal::dense_xpr_base<Product<Lhs,Rhs> >::type
-{
- typedef Product<Lhs, Rhs> Derived;
- public:
-
- typedef typename internal::dense_xpr_base<Product<Lhs, Rhs> >::type Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(Derived)
-};
-
-#endif // EIGEN_PRODUCT_H
diff --git a/Eigen/src/Core/ProductBase.h b/Eigen/src/Core/ProductBase.h
index ec12e5c9f..a494b5f87 100644
--- a/Eigen/src/Core/ProductBase.h
+++ b/Eigen/src/Core/ProductBase.h
@@ -87,10 +87,10 @@ class ProductBase : public MatrixBase<Derived>
typedef typename Base::PlainObject PlainObject;
- ProductBase(const Lhs& lhs, const Rhs& rhs)
- : m_lhs(lhs), m_rhs(rhs)
+ ProductBase(const Lhs& a_lhs, const Rhs& a_rhs)
+ : m_lhs(a_lhs), m_rhs(a_rhs)
{
- eigen_assert(lhs.cols() == rhs.rows()
+ eigen_assert(a_lhs.cols() == a_rhs.rows()
&& "invalid matrix product"
&& "if you wanted a coeff-wise or a dot product use the respective explicit functions");
}
@@ -108,7 +108,7 @@ class ProductBase : public MatrixBase<Derived>
inline void subTo(Dest& dst) const { scaleAndAddTo(dst,Scalar(-1)); }
template<typename Dest>
- inline void scaleAndAddTo(Dest& dst,Scalar alpha) const { derived().scaleAndAddTo(dst,alpha); }
+ inline void scaleAndAddTo(Dest& dst, const Scalar& alpha) const { derived().scaleAndAddTo(dst,alpha); }
const _LhsNested& lhs() const { return m_lhs; }
const _RhsNested& rhs() const { return m_rhs; }
@@ -195,25 +195,25 @@ class ScaledProduct;
// Also note that here we accept any compatible scalar types
template<typename Derived,typename Lhs,typename Rhs>
const ScaledProduct<Derived>
-operator*(const ProductBase<Derived,Lhs,Rhs>& prod, typename Derived::Scalar x)
+operator*(const ProductBase<Derived,Lhs,Rhs>& prod, const typename Derived::Scalar& x)
{ return ScaledProduct<Derived>(prod.derived(), x); }
template<typename Derived,typename Lhs,typename Rhs>
typename internal::enable_if<!internal::is_same<typename Derived::Scalar,typename Derived::RealScalar>::value,
const ScaledProduct<Derived> >::type
-operator*(const ProductBase<Derived,Lhs,Rhs>& prod, typename Derived::RealScalar x)
+operator*(const ProductBase<Derived,Lhs,Rhs>& prod, const typename Derived::RealScalar& x)
{ return ScaledProduct<Derived>(prod.derived(), x); }
template<typename Derived,typename Lhs,typename Rhs>
const ScaledProduct<Derived>
-operator*(typename Derived::Scalar x,const ProductBase<Derived,Lhs,Rhs>& prod)
+operator*(const typename Derived::Scalar& x,const ProductBase<Derived,Lhs,Rhs>& prod)
{ return ScaledProduct<Derived>(prod.derived(), x); }
template<typename Derived,typename Lhs,typename Rhs>
typename internal::enable_if<!internal::is_same<typename Derived::Scalar,typename Derived::RealScalar>::value,
const ScaledProduct<Derived> >::type
-operator*(typename Derived::RealScalar x,const ProductBase<Derived,Lhs,Rhs>& prod)
+operator*(const typename Derived::RealScalar& x,const ProductBase<Derived,Lhs,Rhs>& prod)
{ return ScaledProduct<Derived>(prod.derived(), x); }
namespace internal {
@@ -241,7 +241,7 @@ class ScaledProduct
typedef typename Base::PlainObject PlainObject;
// EIGEN_PRODUCT_PUBLIC_INTERFACE(ScaledProduct)
- ScaledProduct(const NestedProduct& prod, Scalar x)
+ ScaledProduct(const NestedProduct& prod, const Scalar& x)
: Base(prod.lhs(),prod.rhs()), m_prod(prod), m_alpha(x) {}
template<typename Dest>
@@ -254,7 +254,7 @@ class ScaledProduct
inline void subTo(Dest& dst) const { scaleAndAddTo(dst, Scalar(-1)); }
template<typename Dest>
- inline void scaleAndAddTo(Dest& dst,Scalar alpha) const { m_prod.derived().scaleAndAddTo(dst,alpha * m_alpha); }
+ inline void scaleAndAddTo(Dest& dst, const Scalar& a_alpha) const { m_prod.derived().scaleAndAddTo(dst,a_alpha * m_alpha); }
const Scalar& alpha() const { return m_alpha; }
diff --git a/Eigen/src/Core/Random.h b/Eigen/src/Core/Random.h
index a9f7f4346..480fea408 100644
--- a/Eigen/src/Core/Random.h
+++ b/Eigen/src/Core/Random.h
@@ -112,7 +112,7 @@ inline Derived& DenseBase<Derived>::setRandom()
return *this = Random(rows(), cols());
}
-/** Resizes to the given \a size, and sets all coefficients in this expression to random values.
+/** Resizes to the given \a newSize, and sets all coefficients in this expression to random values.
*
* \only_for_vectors
*
@@ -123,16 +123,16 @@ inline Derived& DenseBase<Derived>::setRandom()
*/
template<typename Derived>
EIGEN_STRONG_INLINE Derived&
-PlainObjectBase<Derived>::setRandom(Index size)
+PlainObjectBase<Derived>::setRandom(Index newSize)
{
- resize(size);
+ resize(newSize);
return setRandom();
}
/** Resizes to the given size, and sets all coefficients in this expression to random values.
*
- * \param rows the new number of rows
- * \param cols the new number of columns
+ * \param nbRows the new number of rows
+ * \param nbCols the new number of columns
*
* Example: \include Matrix_setRandom_int_int.cpp
* Output: \verbinclude Matrix_setRandom_int_int.out
@@ -141,9 +141,9 @@ PlainObjectBase<Derived>::setRandom(Index size)
*/
template<typename Derived>
EIGEN_STRONG_INLINE Derived&
-PlainObjectBase<Derived>::setRandom(Index rows, Index cols)
+PlainObjectBase<Derived>::setRandom(Index nbRows, Index nbCols)
{
- resize(rows, cols);
+ resize(nbRows, nbCols);
return setRandom();
}
diff --git a/Eigen/src/Core/Redux.h b/Eigen/src/Core/Redux.h
index b7ce7c658..50548fa9a 100644
--- a/Eigen/src/Core/Redux.h
+++ b/Eigen/src/Core/Redux.h
@@ -330,7 +330,8 @@ DenseBase<Derived>::redux(const Func& func) const
::run(derived(), func);
}
-/** \returns the minimum of all coefficients of *this
+/** \returns the minimum of all coefficients of \c *this.
+ * \warning the result is undefined if \c *this contains NaN.
*/
template<typename Derived>
EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
@@ -339,7 +340,8 @@ DenseBase<Derived>::minCoeff() const
return this->redux(Eigen::internal::scalar_min_op<Scalar>());
}
-/** \returns the maximum of all coefficients of *this
+/** \returns the maximum of all coefficients of \c *this.
+ * \warning the result is undefined if \c *this contains NaN.
*/
template<typename Derived>
EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
diff --git a/Eigen/src/Core/Ref.h b/Eigen/src/Core/Ref.h
new file mode 100644
index 000000000..cd6d949c4
--- /dev/null
+++ b/Eigen/src/Core/Ref.h
@@ -0,0 +1,260 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef EIGEN_REF_H
+#define EIGEN_REF_H
+
+namespace Eigen {
+
+template<typename Derived> class RefBase;
+template<typename PlainObjectType, int Options = 0,
+ typename StrideType = typename internal::conditional<PlainObjectType::IsVectorAtCompileTime,InnerStride<1>,OuterStride<> >::type > class Ref;
+
+/** \class Ref
+ * \ingroup Core_Module
+ *
+ * \brief A matrix or vector expression mapping an existing expressions
+ *
+ * \tparam PlainObjectType the equivalent matrix type of the mapped data
+ * \tparam Options specifies whether the pointer is \c #Aligned, or \c #Unaligned.
+ * The default is \c #Unaligned.
+ * \tparam StrideType optionally specifies strides. By default, Ref implies a contiguous storage along the inner dimension (inner stride==1),
+ * but accept a variable outer stride (leading dimension).
+ * This can be overridden by specifying strides.
+ * The type passed here must be a specialization of the Stride template, see examples below.
+ *
+ * This class permits to write non template functions taking Eigen's object as parameters while limiting the number of copies.
+ * A Ref<> object can represent either a const expression or a l-value:
+ * \code
+ * // in-out argument:
+ * void foo1(Ref<VectorXf> x);
+ *
+ * // read-only const argument:
+ * void foo2(const Ref<const VectorXf>& x);
+ * \endcode
+ *
+ * In the in-out case, the input argument must satisfies the constraints of the actual Ref<> type, otherwise a compilation issue will be triggered.
+ * By default, a Ref<VectorXf> can reference any dense vector expression of float having a contiguous memory layout.
+ * Likewise, a Ref<MatrixXf> can reference any column major dense matrix expression of float whose column's elements are contiguously stored with
+ * the possibility to have a constant space inbetween each column, i.e.: the inner stride mmust be equal to 1, but the outer-stride (or leading dimension),
+ * can be greater than the number of rows.
+ *
+ * In the const case, if the input expression does not match the above requirement, then it is evaluated into a temporary before being passed to the function.
+ * Here are some examples:
+ * \code
+ * MatrixXf A;
+ * VectorXf a;
+ * foo1(a.head()); // OK
+ * foo1(A.col()); // OK
+ * foo1(A.row()); // compilation error because here innerstride!=1
+ * foo2(A.row()); // The row is copied into a contiguous temporary
+ * foo2(2*a); // The expression is evaluated into a temporary
+ * foo2(A.col().segment(2,4)); // No temporary
+ * \endcode
+ *
+ * The range of inputs that can be referenced without temporary can be enlarged using the last two template parameter.
+ * Here is an example accepting an innerstride!=1:
+ * \code
+ * // in-out argument:
+ * void foo3(Ref<VectorXf,0,InnerStride<> > x);
+ * foo3(A.row()); // OK
+ * \endcode
+ * The downside here is that the function foo3 might be significantly slower than foo1 because it won't be able to exploit vectorization, and will involved more
+ * expensive address computations even if the input is contiguously stored in memory. To overcome this issue, one might propose to overloads internally calling a
+ * template function, e.g.:
+ * \code
+ * // in the .h:
+ * void foo(const Ref<MatrixXf>& A);
+ * void foo(const Ref<MatrixXf,0,Stride<> >& A);
+ *
+ * // in the .cpp:
+ * template<typename TypeOfA> void foo_impl(const TypeOfA& A) {
+ * ... // crazy code goes here
+ * }
+ * void foo(const Ref<MatrixXf>& A) { foo_impl(A); }
+ * void foo(const Ref<MatrixXf,0,Stride<> >& A) { foo_impl(A); }
+ * \endcode
+ *
+ *
+ * \sa PlainObjectBase::Map(), \ref TopicStorageOrders
+ */
+
+namespace internal {
+
+template<typename _PlainObjectType, int _Options, typename _StrideType>
+struct traits<Ref<_PlainObjectType, _Options, _StrideType> >
+ : public traits<Map<_PlainObjectType, _Options, _StrideType> >
+{
+ typedef _PlainObjectType PlainObjectType;
+ typedef _StrideType StrideType;
+ enum {
+ Options = _Options,
+ Flags = traits<Map<_PlainObjectType, _Options, _StrideType> >::Flags | NestByRefBit
+ };
+
+ template<typename Derived> struct match {
+ enum {
+ HasDirectAccess = internal::has_direct_access<Derived>::ret,
+ StorageOrderMatch = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime || ((PlainObjectType::Flags&RowMajorBit)==(Derived::Flags&RowMajorBit)),
+ InnerStrideMatch = int(StrideType::InnerStrideAtCompileTime)==int(Dynamic)
+ || int(StrideType::InnerStrideAtCompileTime)==int(Derived::InnerStrideAtCompileTime)
+ || (int(StrideType::InnerStrideAtCompileTime)==0 && int(Derived::InnerStrideAtCompileTime)==1),
+ OuterStrideMatch = Derived::IsVectorAtCompileTime
+ || int(StrideType::OuterStrideAtCompileTime)==int(Dynamic) || int(StrideType::OuterStrideAtCompileTime)==int(Derived::OuterStrideAtCompileTime),
+ AlignmentMatch = (_Options!=Aligned) || ((PlainObjectType::Flags&AlignedBit)==0) || ((traits<Derived>::Flags&AlignedBit)==AlignedBit),
+ MatchAtCompileTime = HasDirectAccess && StorageOrderMatch && InnerStrideMatch && OuterStrideMatch && AlignmentMatch
+ };
+ typedef typename internal::conditional<MatchAtCompileTime,internal::true_type,internal::false_type>::type type;
+ };
+
+};
+
+template<typename Derived>
+struct traits<RefBase<Derived> > : public traits<Derived> {};
+
+}
+
+template<typename Derived> class RefBase
+ : public MapBase<Derived>
+{
+ typedef typename internal::traits<Derived>::PlainObjectType PlainObjectType;
+ typedef typename internal::traits<Derived>::StrideType StrideType;
+
+public:
+
+ typedef MapBase<Derived> Base;
+ EIGEN_DENSE_PUBLIC_INTERFACE(RefBase)
+
+ inline Index innerStride() const
+ {
+ return StrideType::InnerStrideAtCompileTime != 0 ? m_stride.inner() : 1;
+ }
+
+ inline Index outerStride() const
+ {
+ return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer()
+ : IsVectorAtCompileTime ? this->size()
+ : int(Flags)&RowMajorBit ? this->cols()
+ : this->rows();
+ }
+
+ RefBase()
+ : Base(0,RowsAtCompileTime==Dynamic?0:RowsAtCompileTime,ColsAtCompileTime==Dynamic?0:ColsAtCompileTime),
+ // Stride<> does not allow default ctor for Dynamic strides, so let' initialize it with dummy values:
+ m_stride(StrideType::OuterStrideAtCompileTime==Dynamic?0:StrideType::OuterStrideAtCompileTime,
+ StrideType::InnerStrideAtCompileTime==Dynamic?0:StrideType::InnerStrideAtCompileTime)
+ {}
+
+ EIGEN_INHERIT_ASSIGNMENT_OPERATORS(RefBase)
+
+protected:
+
+ typedef Stride<StrideType::OuterStrideAtCompileTime,StrideType::InnerStrideAtCompileTime> StrideBase;
+
+ template<typename Expression>
+ void construct(Expression& expr)
+ {
+ if(PlainObjectType::RowsAtCompileTime==1)
+ {
+ eigen_assert(expr.rows()==1 || expr.cols()==1);
+ ::new (static_cast<Base*>(this)) Base(expr.data(), 1, expr.size());
+ }
+ else if(PlainObjectType::ColsAtCompileTime==1)
+ {
+ eigen_assert(expr.rows()==1 || expr.cols()==1);
+ ::new (static_cast<Base*>(this)) Base(expr.data(), expr.size(), 1);
+ }
+ else
+ ::new (static_cast<Base*>(this)) Base(expr.data(), expr.rows(), expr.cols());
+
+ if(Expression::IsVectorAtCompileTime && (!PlainObjectType::IsVectorAtCompileTime) && ((Expression::Flags&RowMajorBit)!=(PlainObjectType::Flags&RowMajorBit)))
+ ::new (&m_stride) StrideBase(expr.innerStride(), StrideType::InnerStrideAtCompileTime==0?0:1);
+ else
+ ::new (&m_stride) StrideBase(StrideType::OuterStrideAtCompileTime==0?0:expr.outerStride(),
+ StrideType::InnerStrideAtCompileTime==0?0:expr.innerStride());
+ }
+
+ StrideBase m_stride;
+};
+
+
+template<typename PlainObjectType, int Options, typename StrideType> class Ref
+ : public RefBase<Ref<PlainObjectType, Options, StrideType> >
+{
+ typedef internal::traits<Ref> Traits;
+ public:
+
+ typedef RefBase<Ref> Base;
+ EIGEN_DENSE_PUBLIC_INTERFACE(Ref)
+
+
+ #ifndef EIGEN_PARSED_BY_DOXYGEN
+ template<typename Derived>
+ inline Ref(PlainObjectBase<Derived>& expr,
+ typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0)
+ {
+ Base::construct(expr);
+ }
+ template<typename Derived>
+ inline Ref(const DenseBase<Derived>& expr,
+ typename internal::enable_if<bool(internal::is_lvalue<Derived>::value&&bool(Traits::template match<Derived>::MatchAtCompileTime)),Derived>::type* = 0,
+ int = Derived::ThisConstantIsPrivateInPlainObjectBase)
+ #else
+ template<typename Derived>
+ inline Ref(DenseBase<Derived>& expr)
+ #endif
+ {
+ Base::construct(expr.const_cast_derived());
+ }
+
+ EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Ref)
+
+};
+
+// this is the const ref version
+template<typename TPlainObjectType, int Options, typename StrideType> class Ref<const TPlainObjectType, Options, StrideType>
+ : public RefBase<Ref<const TPlainObjectType, Options, StrideType> >
+{
+ typedef internal::traits<Ref> Traits;
+ public:
+
+ typedef RefBase<Ref> Base;
+ EIGEN_DENSE_PUBLIC_INTERFACE(Ref)
+
+ template<typename Derived>
+ inline Ref(const DenseBase<Derived>& expr)
+ {
+// std::cout << match_helper<Derived>::HasDirectAccess << "," << match_helper<Derived>::OuterStrideMatch << "," << match_helper<Derived>::InnerStrideMatch << "\n";
+// std::cout << int(StrideType::OuterStrideAtCompileTime) << " - " << int(Derived::OuterStrideAtCompileTime) << "\n";
+// std::cout << int(StrideType::InnerStrideAtCompileTime) << " - " << int(Derived::InnerStrideAtCompileTime) << "\n";
+ construct(expr.derived(), typename Traits::template match<Derived>::type());
+ }
+
+ protected:
+
+ template<typename Expression>
+ void construct(const Expression& expr,internal::true_type)
+ {
+ Base::construct(expr);
+ }
+
+ template<typename Expression>
+ void construct(const Expression& expr, internal::false_type)
+ {
+ m_object.lazyAssign(expr);
+ Base::construct(m_object);
+ }
+
+ protected:
+ TPlainObjectType m_object;
+};
+
+} // end namespace Eigen
+
+#endif // EIGEN_REF_H
diff --git a/Eigen/src/Core/Replicate.h b/Eigen/src/Core/Replicate.h
index b61fdc29e..dde86a834 100644
--- a/Eigen/src/Core/Replicate.h
+++ b/Eigen/src/Core/Replicate.h
@@ -70,8 +70,8 @@ template<typename MatrixType,int RowFactor,int ColFactor> class Replicate
EIGEN_DENSE_PUBLIC_INTERFACE(Replicate)
template<typename OriginalMatrixType>
- inline explicit Replicate(const OriginalMatrixType& matrix)
- : m_matrix(matrix), m_rowFactor(RowFactor), m_colFactor(ColFactor)
+ inline explicit Replicate(const OriginalMatrixType& a_matrix)
+ : m_matrix(a_matrix), m_rowFactor(RowFactor), m_colFactor(ColFactor)
{
EIGEN_STATIC_ASSERT((internal::is_same<typename internal::remove_const<MatrixType>::type,OriginalMatrixType>::value),
THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE)
@@ -79,8 +79,8 @@ template<typename MatrixType,int RowFactor,int ColFactor> class Replicate
}
template<typename OriginalMatrixType>
- inline Replicate(const OriginalMatrixType& matrix, Index rowFactor, Index colFactor)
- : m_matrix(matrix), m_rowFactor(rowFactor), m_colFactor(colFactor)
+ inline Replicate(const OriginalMatrixType& a_matrix, Index rowFactor, Index colFactor)
+ : m_matrix(a_matrix), m_rowFactor(rowFactor), m_colFactor(colFactor)
{
EIGEN_STATIC_ASSERT((internal::is_same<typename internal::remove_const<MatrixType>::type,OriginalMatrixType>::value),
THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE)
@@ -89,27 +89,27 @@ template<typename MatrixType,int RowFactor,int ColFactor> class Replicate
inline Index rows() const { return m_matrix.rows() * m_rowFactor.value(); }
inline Index cols() const { return m_matrix.cols() * m_colFactor.value(); }
- inline Scalar coeff(Index row, Index col) const
+ inline Scalar coeff(Index rowId, Index colId) const
{
// try to avoid using modulo; this is a pure optimization strategy
const Index actual_row = internal::traits<MatrixType>::RowsAtCompileTime==1 ? 0
- : RowFactor==1 ? row
- : row%m_matrix.rows();
+ : RowFactor==1 ? rowId
+ : rowId%m_matrix.rows();
const Index actual_col = internal::traits<MatrixType>::ColsAtCompileTime==1 ? 0
- : ColFactor==1 ? col
- : col%m_matrix.cols();
+ : ColFactor==1 ? colId
+ : colId%m_matrix.cols();
return m_matrix.coeff(actual_row, actual_col);
}
template<int LoadMode>
- inline PacketScalar packet(Index row, Index col) const
+ inline PacketScalar packet(Index rowId, Index colId) const
{
const Index actual_row = internal::traits<MatrixType>::RowsAtCompileTime==1 ? 0
- : RowFactor==1 ? row
- : row%m_matrix.rows();
+ : RowFactor==1 ? rowId
+ : rowId%m_matrix.rows();
const Index actual_col = internal::traits<MatrixType>::ColsAtCompileTime==1 ? 0
- : ColFactor==1 ? col
- : col%m_matrix.cols();
+ : ColFactor==1 ? colId
+ : colId%m_matrix.cols();
return m_matrix.template packet<LoadMode>(actual_row, actual_col);
}
diff --git a/Eigen/src/Core/ReturnByValue.h b/Eigen/src/Core/ReturnByValue.h
index 613912ffa..d66c24ba0 100644
--- a/Eigen/src/Core/ReturnByValue.h
+++ b/Eigen/src/Core/ReturnByValue.h
@@ -48,7 +48,7 @@ struct nested<ReturnByValue<Derived>, n, PlainObject>
} // end namespace internal
template<typename Derived> class ReturnByValue
- : public internal::dense_xpr_base< ReturnByValue<Derived> >::type
+ : internal::no_assignment_operator, public internal::dense_xpr_base< ReturnByValue<Derived> >::type
{
public:
typedef typename internal::traits<Derived>::ReturnType ReturnType;
diff --git a/Eigen/src/Core/Select.h b/Eigen/src/Core/Select.h
index 2bf6e91d0..87993bbb5 100644
--- a/Eigen/src/Core/Select.h
+++ b/Eigen/src/Core/Select.h
@@ -60,10 +60,10 @@ class Select : internal::no_assignment_operator,
typedef typename internal::dense_xpr_base<Select>::type Base;
EIGEN_DENSE_PUBLIC_INTERFACE(Select)
- Select(const ConditionMatrixType& conditionMatrix,
- const ThenMatrixType& thenMatrix,
- const ElseMatrixType& elseMatrix)
- : m_condition(conditionMatrix), m_then(thenMatrix), m_else(elseMatrix)
+ Select(const ConditionMatrixType& a_conditionMatrix,
+ const ThenMatrixType& a_thenMatrix,
+ const ElseMatrixType& a_elseMatrix)
+ : m_condition(a_conditionMatrix), m_then(a_thenMatrix), m_else(a_elseMatrix)
{
eigen_assert(m_condition.rows() == m_then.rows() && m_condition.rows() == m_else.rows());
eigen_assert(m_condition.cols() == m_then.cols() && m_condition.cols() == m_else.cols());
@@ -136,7 +136,7 @@ template<typename Derived>
template<typename ThenDerived>
inline const Select<Derived,ThenDerived, typename ThenDerived::ConstantReturnType>
DenseBase<Derived>::select(const DenseBase<ThenDerived>& thenMatrix,
- typename ThenDerived::Scalar elseScalar) const
+ const typename ThenDerived::Scalar& elseScalar) const
{
return Select<Derived,ThenDerived,typename ThenDerived::ConstantReturnType>(
derived(), thenMatrix.derived(), ThenDerived::Constant(rows(),cols(),elseScalar));
@@ -150,8 +150,8 @@ DenseBase<Derived>::select(const DenseBase<ThenDerived>& thenMatrix,
template<typename Derived>
template<typename ElseDerived>
inline const Select<Derived, typename ElseDerived::ConstantReturnType, ElseDerived >
-DenseBase<Derived>::select(typename ElseDerived::Scalar thenScalar,
- const DenseBase<ElseDerived>& elseMatrix) const
+DenseBase<Derived>::select(const typename ElseDerived::Scalar& thenScalar,
+ const DenseBase<ElseDerived>& elseMatrix) const
{
return Select<Derived,typename ElseDerived::ConstantReturnType,ElseDerived>(
derived(), ElseDerived::Constant(rows(),cols(),thenScalar), elseMatrix.derived());
diff --git a/Eigen/src/Core/SelfAdjointView.h b/Eigen/src/Core/SelfAdjointView.h
index 82cc4da73..6fa7cd15e 100644
--- a/Eigen/src/Core/SelfAdjointView.h
+++ b/Eigen/src/Core/SelfAdjointView.h
@@ -132,7 +132,7 @@ template<typename MatrixType, unsigned int UpLo> class SelfAdjointView
* \sa rankUpdate(const MatrixBase<DerivedU>&, Scalar)
*/
template<typename DerivedU, typename DerivedV>
- SelfAdjointView& rankUpdate(const MatrixBase<DerivedU>& u, const MatrixBase<DerivedV>& v, Scalar alpha = Scalar(1));
+ SelfAdjointView& rankUpdate(const MatrixBase<DerivedU>& u, const MatrixBase<DerivedV>& v, const Scalar& alpha = Scalar(1));
/** Perform a symmetric rank K update of the selfadjoint matrix \c *this:
* \f$ this = this + \alpha ( u u^* ) \f$ where \a u is a vector or matrix.
@@ -145,7 +145,7 @@ template<typename MatrixType, unsigned int UpLo> class SelfAdjointView
* \sa rankUpdate(const MatrixBase<DerivedU>&, const MatrixBase<DerivedV>&, Scalar)
*/
template<typename DerivedU>
- SelfAdjointView& rankUpdate(const MatrixBase<DerivedU>& u, Scalar alpha = Scalar(1));
+ SelfAdjointView& rankUpdate(const MatrixBase<DerivedU>& u, const Scalar& alpha = Scalar(1));
/////////// Cholesky module ///////////
@@ -214,9 +214,9 @@ struct triangular_assignment_selector<Derived1, Derived2, (SelfAdjoint|Upper), U
triangular_assignment_selector<Derived1, Derived2, (SelfAdjoint|Upper), UnrollCount-1, ClearOpposite>::run(dst, src);
if(row == col)
- dst.coeffRef(row, col) = real(src.coeff(row, col));
+ dst.coeffRef(row, col) = numext::real(src.coeff(row, col));
else if(row < col)
- dst.coeffRef(col, row) = conj(dst.coeffRef(row, col) = src.coeff(row, col));
+ dst.coeffRef(col, row) = numext::conj(dst.coeffRef(row, col) = src.coeff(row, col));
}
};
@@ -239,9 +239,9 @@ struct triangular_assignment_selector<Derived1, Derived2, (SelfAdjoint|Lower), U
triangular_assignment_selector<Derived1, Derived2, (SelfAdjoint|Lower), UnrollCount-1, ClearOpposite>::run(dst, src);
if(row == col)
- dst.coeffRef(row, col) = real(src.coeff(row, col));
+ dst.coeffRef(row, col) = numext::real(src.coeff(row, col));
else if(row > col)
- dst.coeffRef(col, row) = conj(dst.coeffRef(row, col) = src.coeff(row, col));
+ dst.coeffRef(col, row) = numext::conj(dst.coeffRef(row, col) = src.coeff(row, col));
}
};
@@ -262,7 +262,7 @@ struct triangular_assignment_selector<Derived1, Derived2, SelfAdjoint|Upper, Dyn
for(Index i = 0; i < j; ++i)
{
dst.copyCoeff(i, j, src);
- dst.coeffRef(j,i) = conj(dst.coeff(i,j));
+ dst.coeffRef(j,i) = numext::conj(dst.coeff(i,j));
}
dst.copyCoeff(j, j, src);
}
@@ -280,7 +280,7 @@ struct triangular_assignment_selector<Derived1, Derived2, SelfAdjoint|Lower, Dyn
for(Index j = 0; j < i; ++j)
{
dst.copyCoeff(i, j, src);
- dst.coeffRef(j,i) = conj(dst.coeff(i,j));
+ dst.coeffRef(j,i) = numext::conj(dst.coeff(i,j));
}
dst.copyCoeff(i, i, src);
}
diff --git a/Eigen/src/Core/SelfCwiseBinaryOp.h b/Eigen/src/Core/SelfCwiseBinaryOp.h
index 0caf2bab1..22f3047b4 100644
--- a/Eigen/src/Core/SelfCwiseBinaryOp.h
+++ b/Eigen/src/Core/SelfCwiseBinaryOp.h
@@ -185,7 +185,10 @@ inline Derived& DenseBase<Derived>::operator/=(const Scalar& other)
internal::scalar_product_op<Scalar> >::type BinOp;
typedef typename Derived::PlainObject PlainObject;
SelfCwiseBinaryOp<BinOp, Derived, typename PlainObject::ConstantReturnType> tmp(derived());
- tmp = PlainObject::Constant(rows(),cols(), NumTraits<Scalar>::IsInteger ? other : Scalar(1)/other);
+ Scalar actual_other;
+ if(NumTraits<Scalar>::IsInteger) actual_other = other;
+ else actual_other = Scalar(1)/other;
+ tmp = PlainObject::Constant(rows(),cols(), actual_other);
return derived();
}
diff --git a/Eigen/src/Core/StableNorm.h b/Eigen/src/Core/StableNorm.h
index d8bf7db70..389d94275 100644
--- a/Eigen/src/Core/StableNorm.h
+++ b/Eigen/src/Core/StableNorm.h
@@ -13,131 +13,105 @@
namespace Eigen {
namespace internal {
+
template<typename ExpressionType, typename Scalar>
inline void stable_norm_kernel(const ExpressionType& bl, Scalar& ssq, Scalar& scale, Scalar& invScale)
{
- Scalar max = bl.cwiseAbs().maxCoeff();
- if (max>scale)
+ using std::max;
+ Scalar maxCoeff = bl.cwiseAbs().maxCoeff();
+
+ if (maxCoeff>scale)
{
- ssq = ssq * abs2(scale/max);
- scale = max;
- invScale = Scalar(1)/scale;
+ ssq = ssq * numext::abs2(scale/maxCoeff);
+ Scalar tmp = Scalar(1)/maxCoeff;
+ if(tmp > NumTraits<Scalar>::highest())
+ {
+ invScale = NumTraits<Scalar>::highest();
+ scale = Scalar(1)/invScale;
+ }
+ else
+ {
+ scale = maxCoeff;
+ invScale = tmp;
+ }
}
- // TODO if the max is much much smaller than the current scale,
+
+ // TODO if the maxCoeff is much much smaller than the current scale,
// then we can neglect this sub vector
- ssq += (bl*invScale).squaredNorm();
-}
-}
-
-/** \returns the \em l2 norm of \c *this avoiding underflow and overflow.
- * This version use a blockwise two passes algorithm:
- * 1 - find the absolute largest coefficient \c s
- * 2 - compute \f$ s \Vert \frac{*this}{s} \Vert \f$ in a standard way
- *
- * For architecture/scalar types supporting vectorization, this version
- * is faster than blueNorm(). Otherwise the blueNorm() is much faster.
- *
- * \sa norm(), blueNorm(), hypotNorm()
- */
-template<typename Derived>
-inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
-MatrixBase<Derived>::stableNorm() const
-{
- using std::min;
- const Index blockSize = 4096;
- RealScalar scale(0);
- RealScalar invScale(1);
- RealScalar ssq(0); // sum of square
- enum {
- Alignment = (int(Flags)&DirectAccessBit) || (int(Flags)&AlignedBit) ? 1 : 0
- };
- Index n = size();
- Index bi = internal::first_aligned(derived());
- if (bi>0)
- internal::stable_norm_kernel(this->head(bi), ssq, scale, invScale);
- for (; bi<n; bi+=blockSize)
- internal::stable_norm_kernel(this->segment(bi,(min)(blockSize, n - bi)).template forceAlignedAccessIf<Alignment>(), ssq, scale, invScale);
- return scale * internal::sqrt(ssq);
+ if(scale>Scalar(0)) // if scale==0, then bl is 0
+ ssq += (bl*invScale).squaredNorm();
}
-/** \returns the \em l2 norm of \c *this using the Blue's algorithm.
- * A Portable Fortran Program to Find the Euclidean Norm of a Vector,
- * ACM TOMS, Vol 4, Issue 1, 1978.
- *
- * For architecture/scalar types without vectorization, this version
- * is much faster than stableNorm(). Otherwise the stableNorm() is faster.
- *
- * \sa norm(), stableNorm(), hypotNorm()
- */
template<typename Derived>
-inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
-MatrixBase<Derived>::blueNorm() const
+inline typename NumTraits<typename traits<Derived>::Scalar>::Real
+blueNorm_impl(const EigenBase<Derived>& _vec)
{
+ typedef typename Derived::RealScalar RealScalar;
+ typedef typename Derived::Index Index;
using std::pow;
using std::min;
using std::max;
- static Index nmax = -1;
+ using std::sqrt;
+ using std::abs;
+ const Derived& vec(_vec.derived());
+ static bool initialized = false;
static RealScalar b1, b2, s1m, s2m, overfl, rbig, relerr;
- if(nmax <= 0)
+ if(!initialized)
{
- int nbig, ibeta, it, iemin, iemax, iexp;
- RealScalar abig, eps;
+ int ibeta, it, iemin, iemax, iexp;
+ RealScalar eps;
// This program calculates the machine-dependent constants
- // bl, b2, slm, s2m, relerr overfl, nmax
+ // bl, b2, slm, s2m, relerr overfl
// from the "basic" machine-dependent numbers
// nbig, ibeta, it, iemin, iemax, rbig.
// The following define the basic machine-dependent constants.
// For portability, the PORT subprograms "ilmaeh" and "rlmach"
// are used. For any specific computer, each of the assignment
// statements can be replaced
- nbig = (std::numeric_limits<Index>::max)(); // largest integer
- ibeta = std::numeric_limits<RealScalar>::radix; // base for floating-point numbers
- it = std::numeric_limits<RealScalar>::digits; // number of base-beta digits in mantissa
- iemin = std::numeric_limits<RealScalar>::min_exponent; // minimum exponent
- iemax = std::numeric_limits<RealScalar>::max_exponent; // maximum exponent
- rbig = (std::numeric_limits<RealScalar>::max)(); // largest floating-point number
+ ibeta = std::numeric_limits<RealScalar>::radix; // base for floating-point numbers
+ it = std::numeric_limits<RealScalar>::digits; // number of base-beta digits in mantissa
+ iemin = std::numeric_limits<RealScalar>::min_exponent; // minimum exponent
+ iemax = std::numeric_limits<RealScalar>::max_exponent; // maximum exponent
+ rbig = (std::numeric_limits<RealScalar>::max)(); // largest floating-point number
iexp = -((1-iemin)/2);
- b1 = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // lower boundary of midrange
+ b1 = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // lower boundary of midrange
iexp = (iemax + 1 - it)/2;
- b2 = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // upper boundary of midrange
+ b2 = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // upper boundary of midrange
iexp = (2-iemin)/2;
- s1m = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // scaling factor for lower range
+ s1m = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // scaling factor for lower range
iexp = - ((iemax+it)/2);
- s2m = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // scaling factor for upper range
+ s2m = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // scaling factor for upper range
- overfl = rbig*s2m; // overflow boundary for abig
+ overfl = rbig*s2m; // overflow boundary for abig
eps = RealScalar(pow(double(ibeta), 1-it));
- relerr = internal::sqrt(eps); // tolerance for neglecting asml
- abig = RealScalar(1.0/eps - 1.0);
- if (RealScalar(nbig)>abig) nmax = int(abig); // largest safe n
- else nmax = nbig;
+ relerr = sqrt(eps); // tolerance for neglecting asml
+ initialized = true;
}
- Index n = size();
+ Index n = vec.size();
RealScalar ab2 = b2 / RealScalar(n);
RealScalar asml = RealScalar(0);
RealScalar amed = RealScalar(0);
RealScalar abig = RealScalar(0);
- for(Index j=0; j<n; ++j)
+ for(typename Derived::InnerIterator it(vec, 0); it; ++it)
{
- RealScalar ax = internal::abs(coeff(j));
- if(ax > ab2) abig += internal::abs2(ax*s2m);
- else if(ax < b1) asml += internal::abs2(ax*s1m);
- else amed += internal::abs2(ax);
+ RealScalar ax = abs(it.value());
+ if(ax > ab2) abig += numext::abs2(ax*s2m);
+ else if(ax < b1) asml += numext::abs2(ax*s1m);
+ else amed += numext::abs2(ax);
}
if(abig > RealScalar(0))
{
- abig = internal::sqrt(abig);
+ abig = sqrt(abig);
if(abig > overfl)
{
- eigen_assert(false && "overflow");
return rbig;
}
if(amed > RealScalar(0))
{
abig = abig/s2m;
- amed = internal::sqrt(amed);
+ amed = sqrt(amed);
}
else
return abig/s2m;
@@ -146,20 +120,70 @@ MatrixBase<Derived>::blueNorm() const
{
if (amed > RealScalar(0))
{
- abig = internal::sqrt(amed);
- amed = internal::sqrt(asml) / s1m;
+ abig = sqrt(amed);
+ amed = sqrt(asml) / s1m;
}
else
- return internal::sqrt(asml)/s1m;
+ return sqrt(asml)/s1m;
}
else
- return internal::sqrt(amed);
+ return sqrt(amed);
asml = (min)(abig, amed);
abig = (max)(abig, amed);
if(asml <= abig*relerr)
return abig;
else
- return abig * internal::sqrt(RealScalar(1) + internal::abs2(asml/abig));
+ return abig * sqrt(RealScalar(1) + numext::abs2(asml/abig));
+}
+
+} // end namespace internal
+
+/** \returns the \em l2 norm of \c *this avoiding underflow and overflow.
+ * This version use a blockwise two passes algorithm:
+ * 1 - find the absolute largest coefficient \c s
+ * 2 - compute \f$ s \Vert \frac{*this}{s} \Vert \f$ in a standard way
+ *
+ * For architecture/scalar types supporting vectorization, this version
+ * is faster than blueNorm(). Otherwise the blueNorm() is much faster.
+ *
+ * \sa norm(), blueNorm(), hypotNorm()
+ */
+template<typename Derived>
+inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
+MatrixBase<Derived>::stableNorm() const
+{
+ using std::min;
+ using std::sqrt;
+ const Index blockSize = 4096;
+ RealScalar scale(0);
+ RealScalar invScale(1);
+ RealScalar ssq(0); // sum of square
+ enum {
+ Alignment = (int(Flags)&DirectAccessBit) || (int(Flags)&AlignedBit) ? 1 : 0
+ };
+ Index n = size();
+ Index bi = internal::first_aligned(derived());
+ if (bi>0)
+ internal::stable_norm_kernel(this->head(bi), ssq, scale, invScale);
+ for (; bi<n; bi+=blockSize)
+ internal::stable_norm_kernel(this->segment(bi,(min)(blockSize, n - bi)).template forceAlignedAccessIf<Alignment>(), ssq, scale, invScale);
+ return scale * sqrt(ssq);
+}
+
+/** \returns the \em l2 norm of \c *this using the Blue's algorithm.
+ * A Portable Fortran Program to Find the Euclidean Norm of a Vector,
+ * ACM TOMS, Vol 4, Issue 1, 1978.
+ *
+ * For architecture/scalar types without vectorization, this version
+ * is much faster than stableNorm(). Otherwise the stableNorm() is faster.
+ *
+ * \sa norm(), stableNorm(), hypotNorm()
+ */
+template<typename Derived>
+inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
+MatrixBase<Derived>::blueNorm() const
+{
+ return internal::blueNorm_impl(*this);
}
/** \returns the \em l2 norm of \c *this avoiding undeflow and overflow.
diff --git a/Eigen/src/Core/Swap.h b/Eigen/src/Core/Swap.h
index fd73cf3ad..bf58bd599 100644
--- a/Eigen/src/Core/Swap.h
+++ b/Eigen/src/Core/Swap.h
@@ -49,9 +49,9 @@ template<typename ExpressionType> class SwapWrapper
inline ScalarWithConstIfNotLvalue* data() { return m_expression.data(); }
inline const Scalar* data() const { return m_expression.data(); }
- inline Scalar& coeffRef(Index row, Index col)
+ inline Scalar& coeffRef(Index rowId, Index colId)
{
- return m_expression.const_cast_derived().coeffRef(row, col);
+ return m_expression.const_cast_derived().coeffRef(rowId, colId);
}
inline Scalar& coeffRef(Index index)
@@ -59,9 +59,9 @@ template<typename ExpressionType> class SwapWrapper
return m_expression.const_cast_derived().coeffRef(index);
}
- inline Scalar& coeffRef(Index row, Index col) const
+ inline Scalar& coeffRef(Index rowId, Index colId) const
{
- return m_expression.coeffRef(row, col);
+ return m_expression.coeffRef(rowId, colId);
}
inline Scalar& coeffRef(Index index) const
@@ -70,14 +70,14 @@ template<typename ExpressionType> class SwapWrapper
}
template<typename OtherDerived>
- void copyCoeff(Index row, Index col, const DenseBase<OtherDerived>& other)
+ void copyCoeff(Index rowId, Index colId, const DenseBase<OtherDerived>& other)
{
OtherDerived& _other = other.const_cast_derived();
- eigen_internal_assert(row >= 0 && row < rows()
- && col >= 0 && col < cols());
- Scalar tmp = m_expression.coeff(row, col);
- m_expression.coeffRef(row, col) = _other.coeff(row, col);
- _other.coeffRef(row, col) = tmp;
+ eigen_internal_assert(rowId >= 0 && rowId < rows()
+ && colId >= 0 && colId < cols());
+ Scalar tmp = m_expression.coeff(rowId, colId);
+ m_expression.coeffRef(rowId, colId) = _other.coeff(rowId, colId);
+ _other.coeffRef(rowId, colId) = tmp;
}
template<typename OtherDerived>
@@ -91,16 +91,16 @@ template<typename ExpressionType> class SwapWrapper
}
template<typename OtherDerived, int StoreMode, int LoadMode>
- void copyPacket(Index row, Index col, const DenseBase<OtherDerived>& other)
+ void copyPacket(Index rowId, Index colId, const DenseBase<OtherDerived>& other)
{
OtherDerived& _other = other.const_cast_derived();
- eigen_internal_assert(row >= 0 && row < rows()
- && col >= 0 && col < cols());
- Packet tmp = m_expression.template packet<StoreMode>(row, col);
- m_expression.template writePacket<StoreMode>(row, col,
- _other.template packet<LoadMode>(row, col)
+ eigen_internal_assert(rowId >= 0 && rowId < rows()
+ && colId >= 0 && colId < cols());
+ Packet tmp = m_expression.template packet<StoreMode>(rowId, colId);
+ m_expression.template writePacket<StoreMode>(rowId, colId,
+ _other.template packet<LoadMode>(rowId, colId)
);
- _other.template writePacket<LoadMode>(row, col, tmp);
+ _other.template writePacket<LoadMode>(rowId, colId, tmp);
}
template<typename OtherDerived, int StoreMode, int LoadMode>
diff --git a/Eigen/src/Core/Transpose.h b/Eigen/src/Core/Transpose.h
index 045a1cce6..22096ea2f 100644
--- a/Eigen/src/Core/Transpose.h
+++ b/Eigen/src/Core/Transpose.h
@@ -62,7 +62,7 @@ template<typename MatrixType> class Transpose
typedef typename TransposeImpl<MatrixType,typename internal::traits<MatrixType>::StorageKind>::Base Base;
EIGEN_GENERIC_PUBLIC_INTERFACE(Transpose)
- inline Transpose(MatrixType& matrix) : m_matrix(matrix) {}
+ inline Transpose(MatrixType& a_matrix) : m_matrix(a_matrix) {}
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Transpose)
@@ -104,6 +104,7 @@ template<typename MatrixType> class TransposeImpl<MatrixType,Dense>
typedef typename internal::TransposeImpl_base<MatrixType>::type Base;
EIGEN_DENSE_PUBLIC_INTERFACE(Transpose<MatrixType>)
+ EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TransposeImpl)
inline Index innerStride() const { return derived().nestedExpression().innerStride(); }
inline Index outerStride() const { return derived().nestedExpression().outerStride(); }
@@ -117,10 +118,10 @@ template<typename MatrixType> class TransposeImpl<MatrixType,Dense>
inline ScalarWithConstIfNotLvalue* data() { return derived().nestedExpression().data(); }
inline const Scalar* data() const { return derived().nestedExpression().data(); }
- inline ScalarWithConstIfNotLvalue& coeffRef(Index row, Index col)
+ inline ScalarWithConstIfNotLvalue& coeffRef(Index rowId, Index colId)
{
EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
- return derived().nestedExpression().const_cast_derived().coeffRef(col, row);
+ return derived().nestedExpression().const_cast_derived().coeffRef(colId, rowId);
}
inline ScalarWithConstIfNotLvalue& coeffRef(Index index)
@@ -129,9 +130,9 @@ template<typename MatrixType> class TransposeImpl<MatrixType,Dense>
return derived().nestedExpression().const_cast_derived().coeffRef(index);
}
- inline const Scalar& coeffRef(Index row, Index col) const
+ inline const Scalar& coeffRef(Index rowId, Index colId) const
{
- return derived().nestedExpression().coeffRef(col, row);
+ return derived().nestedExpression().coeffRef(colId, rowId);
}
inline const Scalar& coeffRef(Index index) const
@@ -139,9 +140,9 @@ template<typename MatrixType> class TransposeImpl<MatrixType,Dense>
return derived().nestedExpression().coeffRef(index);
}
- inline CoeffReturnType coeff(Index row, Index col) const
+ inline CoeffReturnType coeff(Index rowId, Index colId) const
{
- return derived().nestedExpression().coeff(col, row);
+ return derived().nestedExpression().coeff(colId, rowId);
}
inline CoeffReturnType coeff(Index index) const
@@ -150,15 +151,15 @@ template<typename MatrixType> class TransposeImpl<MatrixType,Dense>
}
template<int LoadMode>
- inline const PacketScalar packet(Index row, Index col) const
+ inline const PacketScalar packet(Index rowId, Index colId) const
{
- return derived().nestedExpression().template packet<LoadMode>(col, row);
+ return derived().nestedExpression().template packet<LoadMode>(colId, rowId);
}
template<int LoadMode>
- inline void writePacket(Index row, Index col, const PacketScalar& x)
+ inline void writePacket(Index rowId, Index colId, const PacketScalar& x)
{
- derived().nestedExpression().const_cast_derived().template writePacket<LoadMode>(col, row, x);
+ derived().nestedExpression().const_cast_derived().template writePacket<LoadMode>(colId, rowId, x);
}
template<int LoadMode>
@@ -206,7 +207,7 @@ DenseBase<Derived>::transpose()
*
* \sa transposeInPlace(), adjoint() */
template<typename Derived>
-inline const typename DenseBase<Derived>::ConstTransposeReturnType
+inline typename DenseBase<Derived>::ConstTransposeReturnType
DenseBase<Derived>::transpose() const
{
return ConstTransposeReturnType(derived());
@@ -252,7 +253,7 @@ struct inplace_transpose_selector;
template<typename MatrixType>
struct inplace_transpose_selector<MatrixType,true> { // square matrix
static void run(MatrixType& m) {
- m.template triangularView<StrictlyUpper>().swap(m.transpose());
+ m.matrix().template triangularView<StrictlyUpper>().swap(m.matrix().transpose());
}
};
@@ -260,7 +261,7 @@ template<typename MatrixType>
struct inplace_transpose_selector<MatrixType,false> { // non square matrix
static void run(MatrixType& m) {
if (m.rows()==m.cols())
- m.template triangularView<StrictlyUpper>().swap(m.transpose());
+ m.matrix().template triangularView<StrictlyUpper>().swap(m.matrix().transpose());
else
m = m.transpose().eval();
}
@@ -278,17 +279,20 @@ struct inplace_transpose_selector<MatrixType,false> { // non square matrix
* m = m.transpose().eval();
* \endcode
* and is faster and also safer because in the latter line of code, forgetting the eval() results
- * in a bug caused by aliasing.
+ * in a bug caused by \ref TopicAliasing "aliasing".
*
* Notice however that this method is only useful if you want to replace a matrix by its own transpose.
* If you just need the transpose of a matrix, use transpose().
*
- * \note if the matrix is not square, then \c *this must be a resizable matrix.
+ * \note if the matrix is not square, then \c *this must be a resizable matrix.
+ * This excludes (non-square) fixed-size matrices, block-expressions and maps.
*
* \sa transpose(), adjoint(), adjointInPlace() */
template<typename Derived>
inline void DenseBase<Derived>::transposeInPlace()
{
+ eigen_assert((rows() == cols() || (RowsAtCompileTime == Dynamic && ColsAtCompileTime == Dynamic))
+ && "transposeInPlace() called on a non-square non-resizable matrix");
internal::inplace_transpose_selector<Derived>::run(derived());
}
@@ -312,6 +316,7 @@ inline void DenseBase<Derived>::transposeInPlace()
* If you just need the adjoint of a matrix, use adjoint().
*
* \note if the matrix is not square, then \c *this must be a resizable matrix.
+ * This excludes (non-square) fixed-size matrices, block-expressions and maps.
*
* \sa transpose(), adjoint(), transposeInPlace() */
template<typename Derived>
@@ -353,7 +358,7 @@ struct check_transpose_aliasing_run_time_selector
{
static bool run(const Scalar* dest, const OtherDerived& src)
{
- return (bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed) && (dest!=0 && dest==(Scalar*)extract_data(src));
+ return (bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src));
}
};
@@ -362,8 +367,8 @@ struct check_transpose_aliasing_run_time_selector<Scalar,DestIsTransposed,CwiseB
{
static bool run(const Scalar* dest, const CwiseBinaryOp<BinOp,DerivedA,DerivedB>& src)
{
- return ((blas_traits<DerivedA>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(Scalar*)extract_data(src.lhs())))
- || ((blas_traits<DerivedB>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(Scalar*)extract_data(src.rhs())));
+ return ((blas_traits<DerivedA>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src.lhs())))
+ || ((blas_traits<DerivedB>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src.rhs())));
}
};
@@ -385,7 +390,7 @@ struct checkTransposeAliasing_impl
eigen_assert((!check_transpose_aliasing_run_time_selector
<typename Derived::Scalar,blas_traits<Derived>::IsTransposed,OtherDerived>
::run(extract_data(dst), other))
- && "aliasing detected during tranposition, use transposeInPlace() "
+ && "aliasing detected during transposition, use transposeInPlace() "
"or evaluate the rhs into a temporary using .eval()");
}
diff --git a/Eigen/src/Core/Transpositions.h b/Eigen/src/Core/Transpositions.h
index 2cd268a5f..e4ba0756f 100644
--- a/Eigen/src/Core/Transpositions.h
+++ b/Eigen/src/Core/Transpositions.h
@@ -99,9 +99,9 @@ class TranspositionsBase
IndicesType& indices() { return derived().indices(); }
/** Resizes to given size. */
- inline void resize(int size)
+ inline void resize(int newSize)
{
- indices().resize(size);
+ indices().resize(newSize);
}
/** Sets \c *this to represents an identity transformation */
@@ -177,7 +177,7 @@ class Transpositions : public TranspositionsBase<Transpositions<SizeAtCompileTim
/** Generic constructor from expression of the transposition indices. */
template<typename Other>
- explicit inline Transpositions(const MatrixBase<Other>& indices) : m_indices(indices)
+ explicit inline Transpositions(const MatrixBase<Other>& a_indices) : m_indices(a_indices)
{}
/** Copies the \a other transpositions into \c *this */
@@ -234,12 +234,12 @@ class Map<Transpositions<SizeAtCompileTime,MaxSizeAtCompileTime,IndexType>,Packe
typedef typename Traits::IndicesType IndicesType;
typedef typename IndicesType::Scalar Index;
- inline Map(const Index* indices)
- : m_indices(indices)
+ inline Map(const Index* indicesPtr)
+ : m_indices(indicesPtr)
{}
- inline Map(const Index* indices, Index size)
- : m_indices(indices,size)
+ inline Map(const Index* indicesPtr, Index size)
+ : m_indices(indicesPtr,size)
{}
/** Copies the \a other transpositions into \c *this */
@@ -291,8 +291,8 @@ class TranspositionsWrapper
typedef typename Traits::IndicesType IndicesType;
typedef typename IndicesType::Scalar Index;
- inline TranspositionsWrapper(IndicesType& indices)
- : m_indices(indices)
+ inline TranspositionsWrapper(IndicesType& a_indices)
+ : m_indices(a_indices)
{}
/** Copies the \a other transpositions into \c *this */
diff --git a/Eigen/src/Core/TriangularMatrix.h b/Eigen/src/Core/TriangularMatrix.h
index de9540063..845ae1aec 100644
--- a/Eigen/src/Core/TriangularMatrix.h
+++ b/Eigen/src/Core/TriangularMatrix.h
@@ -278,21 +278,21 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView
/** Efficient triangular matrix times vector/matrix product */
template<typename OtherDerived>
- TriangularProduct<Mode,true,MatrixType,false,OtherDerived, OtherDerived::IsVectorAtCompileTime>
+ TriangularProduct<Mode, true, MatrixType, false, OtherDerived, OtherDerived::ColsAtCompileTime==1>
operator*(const MatrixBase<OtherDerived>& rhs) const
{
return TriangularProduct
- <Mode,true,MatrixType,false,OtherDerived,OtherDerived::IsVectorAtCompileTime>
+ <Mode, true, MatrixType, false, OtherDerived, OtherDerived::ColsAtCompileTime==1>
(m_matrix, rhs.derived());
}
/** Efficient vector/matrix times triangular matrix product */
template<typename OtherDerived> friend
- TriangularProduct<Mode,false,OtherDerived,OtherDerived::IsVectorAtCompileTime,MatrixType,false>
+ TriangularProduct<Mode, false, OtherDerived, OtherDerived::RowsAtCompileTime==1, MatrixType, false>
operator*(const MatrixBase<OtherDerived>& lhs, const TriangularView& rhs)
{
return TriangularProduct
- <Mode,false,OtherDerived,OtherDerived::IsVectorAtCompileTime,MatrixType,false>
+ <Mode, false, OtherDerived, OtherDerived::RowsAtCompileTime==1, MatrixType, false>
(lhs.derived(),rhs.m_matrix);
}
@@ -511,6 +511,7 @@ template<typename Derived1, typename Derived2, bool ClearOpposite>
struct triangular_assignment_selector<Derived1, Derived2, StrictlyUpper, Dynamic, ClearOpposite>
{
typedef typename Derived1::Index Index;
+ typedef typename Derived1::Scalar Scalar;
static inline void run(Derived1 &dst, const Derived2 &src)
{
for(Index j = 0; j < dst.cols(); ++j)
@@ -520,7 +521,7 @@ struct triangular_assignment_selector<Derived1, Derived2, StrictlyUpper, Dynamic
dst.copyCoeff(i, j, src);
if (ClearOpposite)
for(Index i = maxi; i < dst.rows(); ++i)
- dst.coeffRef(i, j) = 0;
+ dst.coeffRef(i, j) = Scalar(0);
}
}
};
@@ -778,22 +779,23 @@ MatrixBase<Derived>::triangularView() const
* \sa isLowerTriangular()
*/
template<typename Derived>
-bool MatrixBase<Derived>::isUpperTriangular(RealScalar prec) const
+bool MatrixBase<Derived>::isUpperTriangular(const RealScalar& prec) const
{
+ using std::abs;
RealScalar maxAbsOnUpperPart = static_cast<RealScalar>(-1);
for(Index j = 0; j < cols(); ++j)
{
Index maxi = (std::min)(j, rows()-1);
for(Index i = 0; i <= maxi; ++i)
{
- RealScalar absValue = internal::abs(coeff(i,j));
+ RealScalar absValue = abs(coeff(i,j));
if(absValue > maxAbsOnUpperPart) maxAbsOnUpperPart = absValue;
}
}
RealScalar threshold = maxAbsOnUpperPart * prec;
for(Index j = 0; j < cols(); ++j)
for(Index i = j+1; i < rows(); ++i)
- if(internal::abs(coeff(i, j)) > threshold) return false;
+ if(abs(coeff(i, j)) > threshold) return false;
return true;
}
@@ -803,13 +805,14 @@ bool MatrixBase<Derived>::isUpperTriangular(RealScalar prec) const
* \sa isUpperTriangular()
*/
template<typename Derived>
-bool MatrixBase<Derived>::isLowerTriangular(RealScalar prec) const
+bool MatrixBase<Derived>::isLowerTriangular(const RealScalar& prec) const
{
+ using std::abs;
RealScalar maxAbsOnLowerPart = static_cast<RealScalar>(-1);
for(Index j = 0; j < cols(); ++j)
for(Index i = j; i < rows(); ++i)
{
- RealScalar absValue = internal::abs(coeff(i,j));
+ RealScalar absValue = abs(coeff(i,j));
if(absValue > maxAbsOnLowerPart) maxAbsOnLowerPart = absValue;
}
RealScalar threshold = maxAbsOnLowerPart * prec;
@@ -817,7 +820,7 @@ bool MatrixBase<Derived>::isLowerTriangular(RealScalar prec) const
{
Index maxi = (std::min)(j, rows()-1);
for(Index i = 0; i < maxi; ++i)
- if(internal::abs(coeff(i, j)) > threshold) return false;
+ if(abs(coeff(i, j)) > threshold) return false;
}
return true;
}
diff --git a/Eigen/src/Core/VectorBlock.h b/Eigen/src/Core/VectorBlock.h
index 6f4effca0..1a7330f3c 100644
--- a/Eigen/src/Core/VectorBlock.h
+++ b/Eigen/src/Core/VectorBlock.h
@@ -90,195 +90,6 @@ template<typename VectorType, int Size> class VectorBlock
};
-/** \returns a dynamic-size expression of a segment (i.e. a vector block) in *this.
- *
- * \only_for_vectors
- *
- * \param start the first coefficient in the segment
- * \param size the number of coefficients in the segment
- *
- * Example: \include MatrixBase_segment_int_int.cpp
- * Output: \verbinclude MatrixBase_segment_int_int.out
- *
- * \note Even though the returned expression has dynamic size, in the case
- * when it is applied to a fixed-size vector, it inherits a fixed maximal size,
- * which means that evaluating it does not cause a dynamic memory allocation.
- *
- * \sa class Block, segment(Index)
- */
-template<typename Derived>
-inline typename DenseBase<Derived>::SegmentReturnType
-DenseBase<Derived>::segment(Index start, Index size)
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return SegmentReturnType(derived(), start, size);
-}
-
-/** This is the const version of segment(Index,Index).*/
-template<typename Derived>
-inline typename DenseBase<Derived>::ConstSegmentReturnType
-DenseBase<Derived>::segment(Index start, Index size) const
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return ConstSegmentReturnType(derived(), start, size);
-}
-
-/** \returns a dynamic-size expression of the first coefficients of *this.
- *
- * \only_for_vectors
- *
- * \param size the number of coefficients in the block
- *
- * Example: \include MatrixBase_start_int.cpp
- * Output: \verbinclude MatrixBase_start_int.out
- *
- * \note Even though the returned expression has dynamic size, in the case
- * when it is applied to a fixed-size vector, it inherits a fixed maximal size,
- * which means that evaluating it does not cause a dynamic memory allocation.
- *
- * \sa class Block, block(Index,Index)
- */
-template<typename Derived>
-inline typename DenseBase<Derived>::SegmentReturnType
-DenseBase<Derived>::head(Index size)
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return SegmentReturnType(derived(), 0, size);
-}
-
-/** This is the const version of head(Index).*/
-template<typename Derived>
-inline typename DenseBase<Derived>::ConstSegmentReturnType
-DenseBase<Derived>::head(Index size) const
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return ConstSegmentReturnType(derived(), 0, size);
-}
-
-/** \returns a dynamic-size expression of the last coefficients of *this.
- *
- * \only_for_vectors
- *
- * \param size the number of coefficients in the block
- *
- * Example: \include MatrixBase_end_int.cpp
- * Output: \verbinclude MatrixBase_end_int.out
- *
- * \note Even though the returned expression has dynamic size, in the case
- * when it is applied to a fixed-size vector, it inherits a fixed maximal size,
- * which means that evaluating it does not cause a dynamic memory allocation.
- *
- * \sa class Block, block(Index,Index)
- */
-template<typename Derived>
-inline typename DenseBase<Derived>::SegmentReturnType
-DenseBase<Derived>::tail(Index size)
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return SegmentReturnType(derived(), this->size() - size, size);
-}
-
-/** This is the const version of tail(Index).*/
-template<typename Derived>
-inline typename DenseBase<Derived>::ConstSegmentReturnType
-DenseBase<Derived>::tail(Index size) const
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return ConstSegmentReturnType(derived(), this->size() - size, size);
-}
-
-/** \returns a fixed-size expression of a segment (i.e. a vector block) in \c *this
- *
- * \only_for_vectors
- *
- * The template parameter \a Size is the number of coefficients in the block
- *
- * \param start the index of the first element of the sub-vector
- *
- * Example: \include MatrixBase_template_int_segment.cpp
- * Output: \verbinclude MatrixBase_template_int_segment.out
- *
- * \sa class Block
- */
-template<typename Derived>
-template<int Size>
-inline typename DenseBase<Derived>::template FixedSegmentReturnType<Size>::Type
-DenseBase<Derived>::segment(Index start)
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return typename FixedSegmentReturnType<Size>::Type(derived(), start);
-}
-
-/** This is the const version of segment<int>(Index).*/
-template<typename Derived>
-template<int Size>
-inline typename DenseBase<Derived>::template ConstFixedSegmentReturnType<Size>::Type
-DenseBase<Derived>::segment(Index start) const
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return typename ConstFixedSegmentReturnType<Size>::Type(derived(), start);
-}
-
-/** \returns a fixed-size expression of the first coefficients of *this.
- *
- * \only_for_vectors
- *
- * The template parameter \a Size is the number of coefficients in the block
- *
- * Example: \include MatrixBase_template_int_start.cpp
- * Output: \verbinclude MatrixBase_template_int_start.out
- *
- * \sa class Block
- */
-template<typename Derived>
-template<int Size>
-inline typename DenseBase<Derived>::template FixedSegmentReturnType<Size>::Type
-DenseBase<Derived>::head()
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return typename FixedSegmentReturnType<Size>::Type(derived(), 0);
-}
-
-/** This is the const version of head<int>().*/
-template<typename Derived>
-template<int Size>
-inline typename DenseBase<Derived>::template ConstFixedSegmentReturnType<Size>::Type
-DenseBase<Derived>::head() const
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return typename ConstFixedSegmentReturnType<Size>::Type(derived(), 0);
-}
-
-/** \returns a fixed-size expression of the last coefficients of *this.
- *
- * \only_for_vectors
- *
- * The template parameter \a Size is the number of coefficients in the block
- *
- * Example: \include MatrixBase_template_int_end.cpp
- * Output: \verbinclude MatrixBase_template_int_end.out
- *
- * \sa class Block
- */
-template<typename Derived>
-template<int Size>
-inline typename DenseBase<Derived>::template FixedSegmentReturnType<Size>::Type
-DenseBase<Derived>::tail()
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return typename FixedSegmentReturnType<Size>::Type(derived(), size() - Size);
-}
-
-/** This is the const version of tail<int>.*/
-template<typename Derived>
-template<int Size>
-inline typename DenseBase<Derived>::template ConstFixedSegmentReturnType<Size>::Type
-DenseBase<Derived>::tail() const
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return typename ConstFixedSegmentReturnType<Size>::Type(derived(), size() - Size);
-}
-
} // end namespace Eigen
#endif // EIGEN_VECTORBLOCK_H
diff --git a/Eigen/src/Core/VectorwiseOp.h b/Eigen/src/Core/VectorwiseOp.h
index 862c0f336..d5ab03664 100644
--- a/Eigen/src/Core/VectorwiseOp.h
+++ b/Eigen/src/Core/VectorwiseOp.h
@@ -50,7 +50,7 @@ struct traits<PartialReduxExpr<MatrixType, MemberOp, Direction> >
MaxColsAtCompileTime = Direction==Horizontal ? 1 : MatrixType::MaxColsAtCompileTime,
Flags0 = (unsigned int)_MatrixTypeNested::Flags & HereditaryBits,
Flags = (Flags0 & ~RowMajorBit) | (RowsAtCompileTime == 1 ? RowMajorBit : 0),
- TraversalSize = Direction==Vertical ? RowsAtCompileTime : ColsAtCompileTime
+ TraversalSize = Direction==Vertical ? MatrixType::RowsAtCompileTime : MatrixType::ColsAtCompileTime
};
#if EIGEN_GNUC_AT_LEAST(3,4)
typedef typename MemberOp::template Cost<InputScalar,int(TraversalSize)> CostOpType;
@@ -58,7 +58,8 @@ struct traits<PartialReduxExpr<MatrixType, MemberOp, Direction> >
typedef typename MemberOp::template Cost<InputScalar,TraversalSize> CostOpType;
#endif
enum {
- CoeffReadCost = TraversalSize * traits<_MatrixTypeNested>::CoeffReadCost + int(CostOpType::value)
+ CoeffReadCost = TraversalSize==Dynamic ? Dynamic
+ : TraversalSize * traits<_MatrixTypeNested>::CoeffReadCost + int(CostOpType::value)
};
};
}
@@ -103,8 +104,8 @@ class PartialReduxExpr : internal::no_assignment_operator,
#define EIGEN_MEMBER_FUNCTOR(MEMBER,COST) \
template <typename ResultType> \
- struct member_##MEMBER { \
- EIGEN_EMPTY_STRUCT_CTOR(member_##MEMBER) \
+ struct member_##MEMBER { \
+ EIGEN_EMPTY_STRUCT_CTOR(member_##MEMBER) \
typedef ResultType result_type; \
template<typename Scalar, int Size> struct Cost \
{ enum { value = COST }; }; \
@@ -233,6 +234,28 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
Direction==Vertical ? 1 : m_matrix.rows(),
Direction==Horizontal ? 1 : m_matrix.cols());
}
+
+ template<typename OtherDerived> struct OppositeExtendedType {
+ typedef Replicate<OtherDerived,
+ Direction==Horizontal ? 1 : ExpressionType::RowsAtCompileTime,
+ Direction==Vertical ? 1 : ExpressionType::ColsAtCompileTime> Type;
+ };
+
+ /** \internal
+ * Replicates a vector in the opposite direction to match the size of \c *this */
+ template<typename OtherDerived>
+ typename OppositeExtendedType<OtherDerived>::Type
+ extendedToOpposite(const DenseBase<OtherDerived>& other) const
+ {
+ EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(Direction==Horizontal, OtherDerived::MaxColsAtCompileTime==1),
+ YOU_PASSED_A_ROW_VECTOR_BUT_A_COLUMN_VECTOR_WAS_EXPECTED)
+ EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(Direction==Vertical, OtherDerived::MaxRowsAtCompileTime==1),
+ YOU_PASSED_A_COLUMN_VECTOR_BUT_A_ROW_VECTOR_WAS_EXPECTED)
+ return typename OppositeExtendedType<OtherDerived>::Type
+ (other.derived(),
+ Direction==Horizontal ? 1 : m_matrix.rows(),
+ Direction==Vertical ? 1 : m_matrix.cols());
+ }
public:
@@ -255,6 +278,8 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
/** \returns a row (or column) vector expression of the smallest coefficient
* of each column (or row) of the referenced expression.
+ *
+ * \warning the result is undefined if \c *this contains NaN.
*
* Example: \include PartialRedux_minCoeff.cpp
* Output: \verbinclude PartialRedux_minCoeff.out
@@ -265,6 +290,8 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
/** \returns a row (or column) vector expression of the largest coefficient
* of each column (or row) of the referenced expression.
+ *
+ * \warning the result is undefined if \c *this contains NaN.
*
* Example: \include PartialRedux_maxCoeff.cpp
* Output: \verbinclude PartialRedux_maxCoeff.out
@@ -504,6 +531,23 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
return m_matrix / extendedTo(other.derived());
}
+
+ /** \returns an expression where each column of row of the referenced matrix are normalized.
+ * The referenced matrix is \b not modified.
+ * \sa MatrixBase::normalized(), normalize()
+ */
+ CwiseBinaryOp<internal::scalar_quotient_op<Scalar>,
+ const ExpressionTypeNestedCleaned,
+ const typename OppositeExtendedType<typename ReturnType<internal::member_norm,RealScalar>::Type>::Type>
+ normalized() const { return m_matrix.cwiseQuotient(extendedToOpposite(this->norm())); }
+
+
+ /** Normalize in-place each row or columns of the referenced matrix.
+ * \sa MatrixBase::normalize(), normalized()
+ */
+ void normalize() {
+ m_matrix = this->normalized();
+ }
/////////// Geometry module ///////////
diff --git a/Eigen/src/Core/Visitor.h b/Eigen/src/Core/Visitor.h
index 916bfd096..64867b7a2 100644
--- a/Eigen/src/Core/Visitor.h
+++ b/Eigen/src/Core/Visitor.h
@@ -164,25 +164,25 @@ struct functor_traits<max_coeff_visitor<Scalar> > {
} // end namespace internal
-/** \returns the minimum of all coefficients of *this
- * and puts in *row and *col its location.
+/** \returns the minimum of all coefficients of *this and puts in *row and *col its location.
+ * \warning the result is undefined if \c *this contains NaN.
*
* \sa DenseBase::minCoeff(Index*), DenseBase::maxCoeff(Index*,Index*), DenseBase::visitor(), DenseBase::minCoeff()
*/
template<typename Derived>
template<typename IndexType>
typename internal::traits<Derived>::Scalar
-DenseBase<Derived>::minCoeff(IndexType* row, IndexType* col) const
+DenseBase<Derived>::minCoeff(IndexType* rowId, IndexType* colId) const
{
internal::min_coeff_visitor<Derived> minVisitor;
this->visit(minVisitor);
- *row = minVisitor.row;
- if (col) *col = minVisitor.col;
+ *rowId = minVisitor.row;
+ if (colId) *colId = minVisitor.col;
return minVisitor.res;
}
-/** \returns the minimum of all coefficients of *this
- * and puts in *index its location.
+/** \returns the minimum of all coefficients of *this and puts in *index its location.
+ * \warning the result is undefined if \c *this contains NaN.
*
* \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::minCoeff()
*/
@@ -198,25 +198,25 @@ DenseBase<Derived>::minCoeff(IndexType* index) const
return minVisitor.res;
}
-/** \returns the maximum of all coefficients of *this
- * and puts in *row and *col its location.
+/** \returns the maximum of all coefficients of *this and puts in *row and *col its location.
+ * \warning the result is undefined if \c *this contains NaN.
*
* \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::maxCoeff()
*/
template<typename Derived>
template<typename IndexType>
typename internal::traits<Derived>::Scalar
-DenseBase<Derived>::maxCoeff(IndexType* row, IndexType* col) const
+DenseBase<Derived>::maxCoeff(IndexType* rowPtr, IndexType* colPtr) const
{
internal::max_coeff_visitor<Derived> maxVisitor;
this->visit(maxVisitor);
- *row = maxVisitor.row;
- if (col) *col = maxVisitor.col;
+ *rowPtr = maxVisitor.row;
+ if (colPtr) *colPtr = maxVisitor.col;
return maxVisitor.res;
}
-/** \returns the maximum of all coefficients of *this
- * and puts in *index its location.
+/** \returns the maximum of all coefficients of *this and puts in *index its location.
+ * \warning the result is undefined if \c *this contains NaN.
*
* \sa DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::maxCoeff()
*/
diff --git a/Eigen/src/Core/arch/AltiVec/PacketMath.h b/Eigen/src/Core/arch/AltiVec/PacketMath.h
index 75de19311..e4089962d 100644
--- a/Eigen/src/Core/arch/AltiVec/PacketMath.h
+++ b/Eigen/src/Core/arch/AltiVec/PacketMath.h
@@ -173,6 +173,9 @@ template<> EIGEN_STRONG_INLINE Packet4i psub<Packet4i>(const Packet4i& a, const
template<> EIGEN_STRONG_INLINE Packet4f pnegate(const Packet4f& a) { return psub<Packet4f>(p4f_ZERO, a); }
template<> EIGEN_STRONG_INLINE Packet4i pnegate(const Packet4i& a) { return psub<Packet4i>(p4i_ZERO, a); }
+template<> EIGEN_STRONG_INLINE Packet4f pconj(const Packet4f& a) { return a; }
+template<> EIGEN_STRONG_INLINE Packet4i pconj(const Packet4i& a) { return a; }
+
template<> EIGEN_STRONG_INLINE Packet4f pmul<Packet4f>(const Packet4f& a, const Packet4f& b) { return vec_madd(a,b,p4f_ZERO); }
/* Commented out: it's actually slower than processing it scalar
*
diff --git a/Eigen/src/Core/arch/NEON/Complex.h b/Eigen/src/Core/arch/NEON/Complex.h
index 795b4be73..f183d31de 100644
--- a/Eigen/src/Core/arch/NEON/Complex.h
+++ b/Eigen/src/Core/arch/NEON/Complex.h
@@ -68,7 +68,6 @@ template<> EIGEN_STRONG_INLINE Packet2cf pconj(const Packet2cf& a)
template<> EIGEN_STRONG_INLINE Packet2cf pmul<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
{
Packet4f v1, v2;
- float32x2_t a_lo, a_hi;
// Get the real values of a | a1_re | a1_re | a2_re | a2_re |
v1 = vcombine_f32(vdup_lane_f32(vget_low_f32(a.v), 0), vdup_lane_f32(vget_high_f32(a.v), 0));
@@ -81,9 +80,7 @@ template<> EIGEN_STRONG_INLINE Packet2cf pmul<Packet2cf>(const Packet2cf& a, con
// Conjugate v2
v2 = vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(v2), p4ui_CONJ_XOR));
// Swap real/imag elements in v2.
- a_lo = vrev64_f32(vget_low_f32(v2));
- a_hi = vrev64_f32(vget_high_f32(v2));
- v2 = vcombine_f32(a_lo, a_hi);
+ v2 = vrev64q_f32(v2);
// Add and return the result
return Packet2cf(vaddq_f32(v1, v2));
}
@@ -241,13 +238,10 @@ template<> EIGEN_STRONG_INLINE Packet2cf pdiv<Packet2cf>(const Packet2cf& a, con
// TODO optimize it for AltiVec
Packet2cf res = conj_helper<Packet2cf,Packet2cf,false,true>().pmul(a,b);
Packet4f s, rev_s;
- float32x2_t a_lo, a_hi;
// this computes the norm
s = vmulq_f32(b.v, b.v);
- a_lo = vrev64_f32(vget_low_f32(s));
- a_hi = vrev64_f32(vget_high_f32(s));
- rev_s = vcombine_f32(a_lo, a_hi);
+ rev_s = vrev64q_f32(s);
return Packet2cf(pdiv(res.v, vaddq_f32(s,rev_s)));
}
diff --git a/Eigen/src/Core/arch/NEON/PacketMath.h b/Eigen/src/Core/arch/NEON/PacketMath.h
index a20250f7c..163bac215 100644
--- a/Eigen/src/Core/arch/NEON/PacketMath.h
+++ b/Eigen/src/Core/arch/NEON/PacketMath.h
@@ -115,6 +115,9 @@ template<> EIGEN_STRONG_INLINE Packet4i psub<Packet4i>(const Packet4i& a, const
template<> EIGEN_STRONG_INLINE Packet4f pnegate(const Packet4f& a) { return vnegq_f32(a); }
template<> EIGEN_STRONG_INLINE Packet4i pnegate(const Packet4i& a) { return vnegq_s32(a); }
+template<> EIGEN_STRONG_INLINE Packet4f pconj(const Packet4f& a) { return a; }
+template<> EIGEN_STRONG_INLINE Packet4i pconj(const Packet4i& a) { return a; }
+
template<> EIGEN_STRONG_INLINE Packet4f pmul<Packet4f>(const Packet4f& a, const Packet4f& b) { return vmulq_f32(a,b); }
template<> EIGEN_STRONG_INLINE Packet4i pmul<Packet4i>(const Packet4i& a, const Packet4i& b) { return vmulq_s32(a,b); }
@@ -188,15 +191,15 @@ template<> EIGEN_STRONG_INLINE Packet4i ploadu<Packet4i>(const int* from) { EI
template<> EIGEN_STRONG_INLINE Packet4f ploaddup<Packet4f>(const float* from)
{
float32x2_t lo, hi;
- lo = vdup_n_f32(*from);
- hi = vdup_n_f32(*(from+1));
+ lo = vld1_dup_f32(from);
+ hi = vld1_dup_f32(from+1);
return vcombine_f32(lo, hi);
}
template<> EIGEN_STRONG_INLINE Packet4i ploaddup<Packet4i>(const int* from)
{
int32x2_t lo, hi;
- lo = vdup_n_s32(*from);
- hi = vdup_n_s32(*(from+1));
+ lo = vld1_dup_s32(from);
+ hi = vld1_dup_s32(from+1);
return vcombine_s32(lo, hi);
}
@@ -237,15 +240,12 @@ template<> EIGEN_STRONG_INLINE Packet4i pabs(const Packet4i& a) { return vabsq_s
template<> EIGEN_STRONG_INLINE float predux<Packet4f>(const Packet4f& a)
{
float32x2_t a_lo, a_hi, sum;
- float s[2];
a_lo = vget_low_f32(a);
a_hi = vget_high_f32(a);
sum = vpadd_f32(a_lo, a_hi);
sum = vpadd_f32(sum, sum);
- vst1_f32(s, sum);
-
- return s[0];
+ return vget_lane_f32(sum, 0);
}
template<> EIGEN_STRONG_INLINE Packet4f preduxp<Packet4f>(const Packet4f* vecs)
@@ -271,15 +271,12 @@ template<> EIGEN_STRONG_INLINE Packet4f preduxp<Packet4f>(const Packet4f* vecs)
template<> EIGEN_STRONG_INLINE int predux<Packet4i>(const Packet4i& a)
{
int32x2_t a_lo, a_hi, sum;
- int32_t s[2];
a_lo = vget_low_s32(a);
a_hi = vget_high_s32(a);
sum = vpadd_s32(a_lo, a_hi);
sum = vpadd_s32(sum, sum);
- vst1_s32(s, sum);
-
- return s[0];
+ return vget_lane_s32(sum, 0);
}
template<> EIGEN_STRONG_INLINE Packet4i preduxp<Packet4i>(const Packet4i* vecs)
@@ -307,7 +304,6 @@ template<> EIGEN_STRONG_INLINE Packet4i preduxp<Packet4i>(const Packet4i* vecs)
template<> EIGEN_STRONG_INLINE float predux_mul<Packet4f>(const Packet4f& a)
{
float32x2_t a_lo, a_hi, prod;
- float s[2];
// Get a_lo = |a1|a2| and a_hi = |a3|a4|
a_lo = vget_low_f32(a);
@@ -316,14 +312,12 @@ template<> EIGEN_STRONG_INLINE float predux_mul<Packet4f>(const Packet4f& a)
prod = vmul_f32(a_lo, a_hi);
// Multiply prod with its swapped value |a2*a4|a1*a3|
prod = vmul_f32(prod, vrev64_f32(prod));
- vst1_f32(s, prod);
- return s[0];
+ return vget_lane_f32(prod, 0);
}
template<> EIGEN_STRONG_INLINE int predux_mul<Packet4i>(const Packet4i& a)
{
int32x2_t a_lo, a_hi, prod;
- int32_t s[2];
// Get a_lo = |a1|a2| and a_hi = |a3|a4|
a_lo = vget_low_s32(a);
@@ -332,65 +326,57 @@ template<> EIGEN_STRONG_INLINE int predux_mul<Packet4i>(const Packet4i& a)
prod = vmul_s32(a_lo, a_hi);
// Multiply prod with its swapped value |a2*a4|a1*a3|
prod = vmul_s32(prod, vrev64_s32(prod));
- vst1_s32(s, prod);
- return s[0];
+ return vget_lane_s32(prod, 0);
}
// min
template<> EIGEN_STRONG_INLINE float predux_min<Packet4f>(const Packet4f& a)
{
float32x2_t a_lo, a_hi, min;
- float s[2];
a_lo = vget_low_f32(a);
a_hi = vget_high_f32(a);
min = vpmin_f32(a_lo, a_hi);
min = vpmin_f32(min, min);
- vst1_f32(s, min);
- return s[0];
+ return vget_lane_f32(min, 0);
}
+
template<> EIGEN_STRONG_INLINE int predux_min<Packet4i>(const Packet4i& a)
{
int32x2_t a_lo, a_hi, min;
- int32_t s[2];
a_lo = vget_low_s32(a);
a_hi = vget_high_s32(a);
min = vpmin_s32(a_lo, a_hi);
min = vpmin_s32(min, min);
- vst1_s32(s, min);
-
- return s[0];
+
+ return vget_lane_s32(min, 0);
}
// max
template<> EIGEN_STRONG_INLINE float predux_max<Packet4f>(const Packet4f& a)
{
float32x2_t a_lo, a_hi, max;
- float s[2];
a_lo = vget_low_f32(a);
a_hi = vget_high_f32(a);
max = vpmax_f32(a_lo, a_hi);
max = vpmax_f32(max, max);
- vst1_f32(s, max);
- return s[0];
+ return vget_lane_f32(max, 0);
}
+
template<> EIGEN_STRONG_INLINE int predux_max<Packet4i>(const Packet4i& a)
{
int32x2_t a_lo, a_hi, max;
- int32_t s[2];
a_lo = vget_low_s32(a);
a_hi = vget_high_s32(a);
max = vpmax_s32(a_lo, a_hi);
- max = vpmax_s32(max, max);
- vst1_s32(s, max);
- return s[0];
+ return vget_lane_s32(max, 0);
}
// this PALIGN_NEON business is to work around a bug in LLVM Clang 3.0 causing incorrect compilation errors,
diff --git a/Eigen/src/Core/arch/SSE/Complex.h b/Eigen/src/Core/arch/SSE/Complex.h
index 12df98775..91bba5e38 100644
--- a/Eigen/src/Core/arch/SSE/Complex.h
+++ b/Eigen/src/Core/arch/SSE/Complex.h
@@ -81,25 +81,31 @@ template<> EIGEN_STRONG_INLINE Packet2cf por <Packet2cf>(const Packet2cf& a,
template<> EIGEN_STRONG_INLINE Packet2cf pxor <Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(_mm_xor_ps(a.v,b.v)); }
template<> EIGEN_STRONG_INLINE Packet2cf pandnot<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(_mm_andnot_ps(a.v,b.v)); }
-template<> EIGEN_STRONG_INLINE Packet2cf pload <Packet2cf>(const std::complex<float>* from) { EIGEN_DEBUG_ALIGNED_LOAD return Packet2cf(pload<Packet4f>(&real_ref(*from))); }
-template<> EIGEN_STRONG_INLINE Packet2cf ploadu<Packet2cf>(const std::complex<float>* from) { EIGEN_DEBUG_UNALIGNED_LOAD return Packet2cf(ploadu<Packet4f>(&real_ref(*from))); }
+template<> EIGEN_STRONG_INLINE Packet2cf pload <Packet2cf>(const std::complex<float>* from) { EIGEN_DEBUG_ALIGNED_LOAD return Packet2cf(pload<Packet4f>(&numext::real_ref(*from))); }
+template<> EIGEN_STRONG_INLINE Packet2cf ploadu<Packet2cf>(const std::complex<float>* from) { EIGEN_DEBUG_UNALIGNED_LOAD return Packet2cf(ploadu<Packet4f>(&numext::real_ref(*from))); }
template<> EIGEN_STRONG_INLINE Packet2cf pset1<Packet2cf>(const std::complex<float>& from)
{
Packet2cf res;
- #if EIGEN_GNUC_AT_MOST(4,2)
- // workaround annoying "may be used uninitialized in this function" warning with gcc 4.2
+#if EIGEN_GNUC_AT_MOST(4,2)
+ // Workaround annoying "may be used uninitialized in this function" warning with gcc 4.2
res.v = _mm_loadl_pi(_mm_set1_ps(0.0f), reinterpret_cast<const __m64*>(&from));
- #else
+#elif EIGEN_GNUC_AT_LEAST(4,6)
+ // Suppress annoying "may be used uninitialized in this function" warning with gcc >= 4.6
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wuninitialized"
res.v = _mm_loadl_pi(res.v, (const __m64*)&from);
- #endif
+ #pragma GCC diagnostic pop
+#else
+ res.v = _mm_loadl_pi(res.v, (const __m64*)&from);
+#endif
return Packet2cf(_mm_movelh_ps(res.v,res.v));
}
template<> EIGEN_STRONG_INLINE Packet2cf ploaddup<Packet2cf>(const std::complex<float>* from) { return pset1<Packet2cf>(*from); }
-template<> EIGEN_STRONG_INLINE void pstore <std::complex<float> >(std::complex<float> * to, const Packet2cf& from) { EIGEN_DEBUG_ALIGNED_STORE pstore(&real_ref(*to), from.v); }
-template<> EIGEN_STRONG_INLINE void pstoreu<std::complex<float> >(std::complex<float> * to, const Packet2cf& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu(&real_ref(*to), from.v); }
+template<> EIGEN_STRONG_INLINE void pstore <std::complex<float> >(std::complex<float> * to, const Packet2cf& from) { EIGEN_DEBUG_ALIGNED_STORE pstore(&numext::real_ref(*to), from.v); }
+template<> EIGEN_STRONG_INLINE void pstoreu<std::complex<float> >(std::complex<float> * to, const Packet2cf& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu(&numext::real_ref(*to), from.v); }
template<> EIGEN_STRONG_INLINE void prefetch<std::complex<float> >(const std::complex<float> * addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
diff --git a/Eigen/src/Core/arch/SSE/MathFunctions.h b/Eigen/src/Core/arch/SSE/MathFunctions.h
index 3f41a4e26..99cbd0d95 100644
--- a/Eigen/src/Core/arch/SSE/MathFunctions.h
+++ b/Eigen/src/Core/arch/SSE/MathFunctions.h
@@ -31,7 +31,8 @@ Packet4f plog<Packet4f>(const Packet4f& _x)
/* the smallest non denormalized float number */
_EIGEN_DECLARE_CONST_Packet4f_FROM_INT(min_norm_pos, 0x00800000);
-
+ _EIGEN_DECLARE_CONST_Packet4f_FROM_INT(minus_inf, 0xff800000);//-1.f/0.f);
+
/* natural logarithm computed for 4 simultaneous float
return NaN for x <= 0
*/
@@ -51,7 +52,8 @@ Packet4f plog<Packet4f>(const Packet4f& _x)
Packet4i emm0;
- Packet4f invalid_mask = _mm_cmple_ps(x, _mm_setzero_ps());
+ Packet4f invalid_mask = _mm_cmplt_ps(x, _mm_setzero_ps());
+ Packet4f iszero_mask = _mm_cmpeq_ps(x, _mm_setzero_ps());
x = pmax(x, p4f_min_norm_pos); /* cut off denormalized stuff */
emm0 = _mm_srli_epi32(_mm_castps_si128(x), 23);
@@ -96,7 +98,9 @@ Packet4f plog<Packet4f>(const Packet4f& _x)
y2 = pmul(e, p4f_cephes_log_q2);
x = padd(x, y);
x = padd(x, y2);
- return _mm_or_ps(x, invalid_mask); // negative arg will be NAN
+ // negative arg will be NAN, 0 will be -INF
+ return _mm_or_ps(_mm_andnot_ps(iszero_mask, _mm_or_ps(x, invalid_mask)),
+ _mm_and_ps(iszero_mask, p4f_minus_inf));
}
template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
@@ -131,13 +135,16 @@ Packet4f pexp<Packet4f>(const Packet4f& _x)
/* express exp(x) as exp(g + n*log(2)) */
fx = pmadd(x, p4f_cephes_LOG2EF, p4f_half);
- /* how to perform a floorf with SSE: just below */
+#ifdef EIGEN_VECTORIZE_SSE4_1
+ fx = _mm_floor_ps(fx);
+#else
emm0 = _mm_cvttps_epi32(fx);
tmp = _mm_cvtepi32_ps(emm0);
/* if greater, substract 1 */
Packet4f mask = _mm_cmpgt_ps(tmp, fx);
mask = _mm_and_ps(mask, p4f_1);
fx = psub(tmp, mask);
+#endif
tmp = pmul(fx, p4f_cephes_exp_C1);
Packet4f z = pmul(fx, p4f_cephes_exp_C2);
@@ -161,6 +168,79 @@ Packet4f pexp<Packet4f>(const Packet4f& _x)
emm0 = _mm_slli_epi32(emm0, 23);
return pmul(y, _mm_castsi128_ps(emm0));
}
+template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
+Packet2d pexp<Packet2d>(const Packet2d& _x)
+{
+ Packet2d x = _x;
+
+ _EIGEN_DECLARE_CONST_Packet2d(1 , 1.0);
+ _EIGEN_DECLARE_CONST_Packet2d(2 , 2.0);
+ _EIGEN_DECLARE_CONST_Packet2d(half, 0.5);
+
+ _EIGEN_DECLARE_CONST_Packet2d(exp_hi, 709.437);
+ _EIGEN_DECLARE_CONST_Packet2d(exp_lo, -709.436139303);
+
+ _EIGEN_DECLARE_CONST_Packet2d(cephes_LOG2EF, 1.4426950408889634073599);
+
+ _EIGEN_DECLARE_CONST_Packet2d(cephes_exp_p0, 1.26177193074810590878e-4);
+ _EIGEN_DECLARE_CONST_Packet2d(cephes_exp_p1, 3.02994407707441961300e-2);
+ _EIGEN_DECLARE_CONST_Packet2d(cephes_exp_p2, 9.99999999999999999910e-1);
+
+ _EIGEN_DECLARE_CONST_Packet2d(cephes_exp_q0, 3.00198505138664455042e-6);
+ _EIGEN_DECLARE_CONST_Packet2d(cephes_exp_q1, 2.52448340349684104192e-3);
+ _EIGEN_DECLARE_CONST_Packet2d(cephes_exp_q2, 2.27265548208155028766e-1);
+ _EIGEN_DECLARE_CONST_Packet2d(cephes_exp_q3, 2.00000000000000000009e0);
+
+ _EIGEN_DECLARE_CONST_Packet2d(cephes_exp_C1, 0.693145751953125);
+ _EIGEN_DECLARE_CONST_Packet2d(cephes_exp_C2, 1.42860682030941723212e-6);
+ static const __m128i p4i_1023_0 = _mm_setr_epi32(1023, 1023, 0, 0);
+
+ Packet2d tmp = _mm_setzero_pd(), fx;
+ Packet4i emm0;
+
+ // clamp x
+ x = pmax(pmin(x, p2d_exp_hi), p2d_exp_lo);
+ /* express exp(x) as exp(g + n*log(2)) */
+ fx = pmadd(p2d_cephes_LOG2EF, x, p2d_half);
+
+#ifdef EIGEN_VECTORIZE_SSE4_1
+ fx = _mm_floor_pd(fx);
+#else
+ emm0 = _mm_cvttpd_epi32(fx);
+ tmp = _mm_cvtepi32_pd(emm0);
+ /* if greater, substract 1 */
+ Packet2d mask = _mm_cmpgt_pd(tmp, fx);
+ mask = _mm_and_pd(mask, p2d_1);
+ fx = psub(tmp, mask);
+#endif
+
+ tmp = pmul(fx, p2d_cephes_exp_C1);
+ Packet2d z = pmul(fx, p2d_cephes_exp_C2);
+ x = psub(x, tmp);
+ x = psub(x, z);
+
+ Packet2d x2 = pmul(x,x);
+
+ Packet2d px = p2d_cephes_exp_p0;
+ px = pmadd(px, x2, p2d_cephes_exp_p1);
+ px = pmadd(px, x2, p2d_cephes_exp_p2);
+ px = pmul (px, x);
+
+ Packet2d qx = p2d_cephes_exp_q0;
+ qx = pmadd(qx, x2, p2d_cephes_exp_q1);
+ qx = pmadd(qx, x2, p2d_cephes_exp_q2);
+ qx = pmadd(qx, x2, p2d_cephes_exp_q3);
+
+ x = pdiv(px,psub(qx,px));
+ x = pmadd(p2d_2,x,p2d_1);
+
+ // build 2^n
+ emm0 = _mm_cvttpd_epi32(fx);
+ emm0 = _mm_add_epi32(emm0, p4i_1023_0);
+ emm0 = _mm_slli_epi32(emm0, 20);
+ emm0 = _mm_shuffle_epi32(emm0, _MM_SHUFFLE(1,2,0,3));
+ return pmul(x, _mm_castsi128_pd(emm0));
+}
/* evaluation of 4 sines at onces, using SSE2 intrinsics.
@@ -362,21 +442,32 @@ Packet4f pcos<Packet4f>(const Packet4f& _x)
return _mm_xor_ps(y, sign_bit);
}
+#if EIGEN_FAST_MATH
+
// This is based on Quake3's fast inverse square root.
// For detail see here: http://www.beyond3d.com/content/articles/8/
+// It lacks 1 (or 2 bits in some rare cases) of precision, and does not handle negative, +inf, or denormalized numbers correctly.
template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
Packet4f psqrt<Packet4f>(const Packet4f& _x)
{
Packet4f half = pmul(_x, pset1<Packet4f>(.5f));
/* select only the inverse sqrt of non-zero inputs */
- Packet4f non_zero_mask = _mm_cmpgt_ps(_x, pset1<Packet4f>(std::numeric_limits<float>::epsilon()));
+ Packet4f non_zero_mask = _mm_cmpge_ps(_x, pset1<Packet4f>((std::numeric_limits<float>::min)()));
Packet4f x = _mm_and_ps(non_zero_mask, _mm_rsqrt_ps(_x));
x = pmul(x, psub(pset1<Packet4f>(1.5f), pmul(half, pmul(x,x))));
return pmul(_x,x);
}
+#else
+
+template<> EIGEN_STRONG_INLINE Packet4f psqrt<Packet4f>(const Packet4f& x) { return _mm_sqrt_ps(x); }
+
+#endif
+
+template<> EIGEN_STRONG_INLINE Packet2d psqrt<Packet2d>(const Packet2d& x) { return _mm_sqrt_pd(x); }
+
} // end namespace internal
} // end namespace Eigen
diff --git a/Eigen/src/Core/arch/SSE/PacketMath.h b/Eigen/src/Core/arch/SSE/PacketMath.h
index 10d918219..fc8ae50fe 100644
--- a/Eigen/src/Core/arch/SSE/PacketMath.h
+++ b/Eigen/src/Core/arch/SSE/PacketMath.h
@@ -48,6 +48,9 @@ template<> struct is_arithmetic<__m128d> { enum { value = true }; };
#define _EIGEN_DECLARE_CONST_Packet4f(NAME,X) \
const Packet4f p4f_##NAME = pset1<Packet4f>(X)
+#define _EIGEN_DECLARE_CONST_Packet2d(NAME,X) \
+ const Packet2d p2d_##NAME = pset1<Packet2d>(X)
+
#define _EIGEN_DECLARE_CONST_Packet4f_FROM_INT(NAME,X) \
const Packet4f p4f_##NAME = _mm_castsi128_ps(pset1<Packet4i>(X))
@@ -63,7 +66,7 @@ template<> struct packet_traits<float> : default_packet_traits
AlignedOnScalar = 1,
size=4,
- HasDiv = 1,
+ HasDiv = 1,
HasSin = EIGEN_FAST_MATH,
HasCos = EIGEN_FAST_MATH,
HasLog = 1,
@@ -79,7 +82,9 @@ template<> struct packet_traits<double> : default_packet_traits
AlignedOnScalar = 1,
size=2,
- HasDiv = 1
+ HasDiv = 1,
+ HasExp = 1,
+ HasSqrt = 1
};
};
template<> struct packet_traits<int> : default_packet_traits
@@ -137,6 +142,10 @@ template<> EIGEN_STRONG_INLINE Packet4i pnegate(const Packet4i& a)
return psub(_mm_setr_epi32(0,0,0,0), a);
}
+template<> EIGEN_STRONG_INLINE Packet4f pconj(const Packet4f& a) { return a; }
+template<> EIGEN_STRONG_INLINE Packet2d pconj(const Packet2d& a) { return a; }
+template<> EIGEN_STRONG_INLINE Packet4i pconj(const Packet4i& a) { return a; }
+
template<> EIGEN_STRONG_INLINE Packet4f pmul<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_mul_ps(a,b); }
template<> EIGEN_STRONG_INLINE Packet2d pmul<Packet2d>(const Packet2d& a, const Packet2d& b) { return _mm_mul_pd(a,b); }
template<> EIGEN_STRONG_INLINE Packet4i pmul<Packet4i>(const Packet4i& a, const Packet4i& b)
@@ -169,18 +178,26 @@ template<> EIGEN_STRONG_INLINE Packet4f pmin<Packet4f>(const Packet4f& a, const
template<> EIGEN_STRONG_INLINE Packet2d pmin<Packet2d>(const Packet2d& a, const Packet2d& b) { return _mm_min_pd(a,b); }
template<> EIGEN_STRONG_INLINE Packet4i pmin<Packet4i>(const Packet4i& a, const Packet4i& b)
{
+#ifdef EIGEN_VECTORIZE_SSE4_1
+ return _mm_min_epi32(a,b);
+#else
// after some bench, this version *is* faster than a scalar implementation
Packet4i mask = _mm_cmplt_epi32(a,b);
return _mm_or_si128(_mm_and_si128(mask,a),_mm_andnot_si128(mask,b));
+#endif
}
template<> EIGEN_STRONG_INLINE Packet4f pmax<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_max_ps(a,b); }
template<> EIGEN_STRONG_INLINE Packet2d pmax<Packet2d>(const Packet2d& a, const Packet2d& b) { return _mm_max_pd(a,b); }
template<> EIGEN_STRONG_INLINE Packet4i pmax<Packet4i>(const Packet4i& a, const Packet4i& b)
{
+#ifdef EIGEN_VECTORIZE_SSE4_1
+ return _mm_max_epi32(a,b);
+#else
// after some bench, this version *is* faster than a scalar implementation
Packet4i mask = _mm_cmpgt_epi32(a,b);
return _mm_or_si128(_mm_and_si128(mask,a),_mm_andnot_si128(mask,b));
+#endif
}
template<> EIGEN_STRONG_INLINE Packet4f pand<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_and_ps(a,b); }
@@ -491,8 +508,8 @@ template<> EIGEN_STRONG_INLINE int predux_min<Packet4i>(const Packet4i& a)
// for GCC (eg., it does not like using std::min after the pstore !!)
EIGEN_ALIGN16 int aux[4];
pstore(aux, a);
- register int aux0 = aux[0]<aux[1] ? aux[0] : aux[1];
- register int aux2 = aux[2]<aux[3] ? aux[2] : aux[3];
+ int aux0 = aux[0]<aux[1] ? aux[0] : aux[1];
+ int aux2 = aux[2]<aux[3] ? aux[2] : aux[3];
return aux0<aux2 ? aux0 : aux2;
}
@@ -512,8 +529,8 @@ template<> EIGEN_STRONG_INLINE int predux_max<Packet4i>(const Packet4i& a)
// for GCC (eg., it does not like using std::min after the pstore !!)
EIGEN_ALIGN16 int aux[4];
pstore(aux, a);
- register int aux0 = aux[0]>aux[1] ? aux[0] : aux[1];
- register int aux2 = aux[2]>aux[3] ? aux[2] : aux[3];
+ int aux0 = aux[0]>aux[1] ? aux[0] : aux[1];
+ int aux2 = aux[2]>aux[3] ? aux[2] : aux[3];
return aux0>aux2 ? aux0 : aux2;
}
diff --git a/Eigen/src/Core/products/CoeffBasedProduct.h b/Eigen/src/Core/products/CoeffBasedProduct.h
index 403d25fa9..c06a0df1c 100644
--- a/Eigen/src/Core/products/CoeffBasedProduct.h
+++ b/Eigen/src/Core/products/CoeffBasedProduct.h
@@ -150,7 +150,7 @@ class CoeffBasedProduct
{
// we don't allow taking products of matrices of different real types, as that wouldn't be vectorizable.
// We still allow to mix T and complex<T>.
- EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::RealScalar, typename Rhs::RealScalar>::value),
+ EIGEN_STATIC_ASSERT((internal::scalar_product_traits<typename Lhs::RealScalar, typename Rhs::RealScalar>::Defined),
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
eigen_assert(lhs.cols() == rhs.rows()
&& "invalid matrix product"
diff --git a/Eigen/src/Core/products/GeneralBlockPanelKernel.h b/Eigen/src/Core/products/GeneralBlockPanelKernel.h
index 5eb03c98c..bcdca5b0d 100644
--- a/Eigen/src/Core/products/GeneralBlockPanelKernel.h
+++ b/Eigen/src/Core/products/GeneralBlockPanelKernel.h
@@ -69,8 +69,8 @@ inline void manage_caching_sizes(Action action, std::ptrdiff_t* l1=0, std::ptrdi
* - the number of scalars that fit into a packet (when vectorization is enabled).
*
* \sa setCpuCacheSizes */
-template<typename LhsScalar, typename RhsScalar, int KcFactor>
-void computeProductBlockingSizes(std::ptrdiff_t& k, std::ptrdiff_t& m, std::ptrdiff_t& n)
+template<typename LhsScalar, typename RhsScalar, int KcFactor, typename SizeType>
+void computeProductBlockingSizes(SizeType& k, SizeType& m, SizeType& n)
{
EIGEN_UNUSED_VARIABLE(n);
// Explanations:
@@ -91,13 +91,13 @@ void computeProductBlockingSizes(std::ptrdiff_t& k, std::ptrdiff_t& m, std::ptrd
};
manage_caching_sizes(GetAction, &l1, &l2);
- k = std::min<std::ptrdiff_t>(k, l1/kdiv);
- std::ptrdiff_t _m = k>0 ? l2/(4 * sizeof(LhsScalar) * k) : 0;
+ k = std::min<SizeType>(k, l1/kdiv);
+ SizeType _m = k>0 ? l2/(4 * sizeof(LhsScalar) * k) : 0;
if(_m<m) m = _m & mr_mask;
}
-template<typename LhsScalar, typename RhsScalar>
-inline void computeProductBlockingSizes(std::ptrdiff_t& k, std::ptrdiff_t& m, std::ptrdiff_t& n)
+template<typename LhsScalar, typename RhsScalar, typename SizeType>
+inline void computeProductBlockingSizes(SizeType& k, SizeType& m, SizeType& n)
{
computeProductBlockingSizes<LhsScalar,RhsScalar,1>(k, m, n);
}
@@ -527,9 +527,16 @@ struct gebp_kernel
ResPacketSize = Traits::ResPacketSize
};
- EIGEN_DONT_INLINE EIGEN_FLATTEN_ATTRIB
+ EIGEN_DONT_INLINE
void operator()(ResScalar* res, Index resStride, const LhsScalar* blockA, const RhsScalar* blockB, Index rows, Index depth, Index cols, ResScalar alpha,
- Index strideA=-1, Index strideB=-1, Index offsetA=0, Index offsetB=0, RhsScalar* unpackedB = 0)
+ Index strideA=-1, Index strideB=-1, Index offsetA=0, Index offsetB=0, RhsScalar* unpackedB=0);
+};
+
+template<typename LhsScalar, typename RhsScalar, typename Index, int mr, int nr, bool ConjugateLhs, bool ConjugateRhs>
+EIGEN_DONT_INLINE
+void gebp_kernel<LhsScalar,RhsScalar,Index,mr,nr,ConjugateLhs,ConjugateRhs>
+ ::operator()(ResScalar* res, Index resStride, const LhsScalar* blockA, const RhsScalar* blockB, Index rows, Index depth, Index cols, ResScalar alpha,
+ Index strideA, Index strideB, Index offsetA, Index offsetB, RhsScalar* unpackedB)
{
Traits traits;
@@ -1089,7 +1096,7 @@ EIGEN_ASM_COMMENT("mybegin4");
}
}
}
-};
+
#undef CJMADD
@@ -1110,80 +1117,85 @@ EIGEN_ASM_COMMENT("mybegin4");
template<typename Scalar, typename Index, int Pack1, int Pack2, int StorageOrder, bool Conjugate, bool PanelMode>
struct gemm_pack_lhs
{
- EIGEN_DONT_INLINE void operator()(Scalar* blockA, const Scalar* EIGEN_RESTRICT _lhs, Index lhsStride, Index depth, Index rows,
- Index stride=0, Index offset=0)
+ EIGEN_DONT_INLINE void operator()(Scalar* blockA, const Scalar* EIGEN_RESTRICT _lhs, Index lhsStride, Index depth, Index rows, Index stride=0, Index offset=0);
+};
+
+template<typename Scalar, typename Index, int Pack1, int Pack2, int StorageOrder, bool Conjugate, bool PanelMode>
+EIGEN_DONT_INLINE void gemm_pack_lhs<Scalar, Index, Pack1, Pack2, StorageOrder, Conjugate, PanelMode>
+ ::operator()(Scalar* blockA, const Scalar* EIGEN_RESTRICT _lhs, Index lhsStride, Index depth, Index rows, Index stride, Index offset)
+{
+ typedef typename packet_traits<Scalar>::type Packet;
+ enum { PacketSize = packet_traits<Scalar>::size };
+
+ EIGEN_ASM_COMMENT("EIGEN PRODUCT PACK LHS");
+ EIGEN_UNUSED_VARIABLE(stride)
+ EIGEN_UNUSED_VARIABLE(offset)
+ eigen_assert(((!PanelMode) && stride==0 && offset==0) || (PanelMode && stride>=depth && offset<=stride));
+ eigen_assert( (StorageOrder==RowMajor) || ((Pack1%PacketSize)==0 && Pack1<=4*PacketSize) );
+ conj_if<NumTraits<Scalar>::IsComplex && Conjugate> cj;
+ const_blas_data_mapper<Scalar, Index, StorageOrder> lhs(_lhs,lhsStride);
+ Index count = 0;
+ Index peeled_mc = (rows/Pack1)*Pack1;
+ for(Index i=0; i<peeled_mc; i+=Pack1)
{
- typedef typename packet_traits<Scalar>::type Packet;
- enum { PacketSize = packet_traits<Scalar>::size };
-
- EIGEN_ASM_COMMENT("EIGEN PRODUCT PACK LHS");
- eigen_assert(((!PanelMode) && stride==0 && offset==0) || (PanelMode && stride>=depth && offset<=stride));
- eigen_assert( (StorageOrder==RowMajor) || ((Pack1%PacketSize)==0 && Pack1<=4*PacketSize) );
- conj_if<NumTraits<Scalar>::IsComplex && Conjugate> cj;
- const_blas_data_mapper<Scalar, Index, StorageOrder> lhs(_lhs,lhsStride);
- Index count = 0;
- Index peeled_mc = (rows/Pack1)*Pack1;
- for(Index i=0; i<peeled_mc; i+=Pack1)
- {
- if(PanelMode) count += Pack1 * offset;
+ if(PanelMode) count += Pack1 * offset;
- if(StorageOrder==ColMajor)
+ if(StorageOrder==ColMajor)
+ {
+ for(Index k=0; k<depth; k++)
{
- for(Index k=0; k<depth; k++)
- {
- Packet A, B, C, D;
- if(Pack1>=1*PacketSize) A = ploadu<Packet>(&lhs(i+0*PacketSize, k));
- if(Pack1>=2*PacketSize) B = ploadu<Packet>(&lhs(i+1*PacketSize, k));
- if(Pack1>=3*PacketSize) C = ploadu<Packet>(&lhs(i+2*PacketSize, k));
- if(Pack1>=4*PacketSize) D = ploadu<Packet>(&lhs(i+3*PacketSize, k));
- if(Pack1>=1*PacketSize) { pstore(blockA+count, cj.pconj(A)); count+=PacketSize; }
- if(Pack1>=2*PacketSize) { pstore(blockA+count, cj.pconj(B)); count+=PacketSize; }
- if(Pack1>=3*PacketSize) { pstore(blockA+count, cj.pconj(C)); count+=PacketSize; }
- if(Pack1>=4*PacketSize) { pstore(blockA+count, cj.pconj(D)); count+=PacketSize; }
- }
+ Packet A, B, C, D;
+ if(Pack1>=1*PacketSize) A = ploadu<Packet>(&lhs(i+0*PacketSize, k));
+ if(Pack1>=2*PacketSize) B = ploadu<Packet>(&lhs(i+1*PacketSize, k));
+ if(Pack1>=3*PacketSize) C = ploadu<Packet>(&lhs(i+2*PacketSize, k));
+ if(Pack1>=4*PacketSize) D = ploadu<Packet>(&lhs(i+3*PacketSize, k));
+ if(Pack1>=1*PacketSize) { pstore(blockA+count, cj.pconj(A)); count+=PacketSize; }
+ if(Pack1>=2*PacketSize) { pstore(blockA+count, cj.pconj(B)); count+=PacketSize; }
+ if(Pack1>=3*PacketSize) { pstore(blockA+count, cj.pconj(C)); count+=PacketSize; }
+ if(Pack1>=4*PacketSize) { pstore(blockA+count, cj.pconj(D)); count+=PacketSize; }
}
- else
+ }
+ else
+ {
+ for(Index k=0; k<depth; k++)
{
- for(Index k=0; k<depth; k++)
+ // TODO add a vectorized transpose here
+ Index w=0;
+ for(; w<Pack1-3; w+=4)
{
- // TODO add a vectorized transpose here
- Index w=0;
- for(; w<Pack1-3; w+=4)
- {
- Scalar a(cj(lhs(i+w+0, k))),
- b(cj(lhs(i+w+1, k))),
- c(cj(lhs(i+w+2, k))),
- d(cj(lhs(i+w+3, k)));
- blockA[count++] = a;
- blockA[count++] = b;
- blockA[count++] = c;
- blockA[count++] = d;
- }
- if(Pack1%4)
- for(;w<Pack1;++w)
- blockA[count++] = cj(lhs(i+w, k));
+ Scalar a(cj(lhs(i+w+0, k))),
+ b(cj(lhs(i+w+1, k))),
+ c(cj(lhs(i+w+2, k))),
+ d(cj(lhs(i+w+3, k)));
+ blockA[count++] = a;
+ blockA[count++] = b;
+ blockA[count++] = c;
+ blockA[count++] = d;
}
+ if(Pack1%4)
+ for(;w<Pack1;++w)
+ blockA[count++] = cj(lhs(i+w, k));
}
- if(PanelMode) count += Pack1 * (stride-offset-depth);
- }
- if(rows-peeled_mc>=Pack2)
- {
- if(PanelMode) count += Pack2*offset;
- for(Index k=0; k<depth; k++)
- for(Index w=0; w<Pack2; w++)
- blockA[count++] = cj(lhs(peeled_mc+w, k));
- if(PanelMode) count += Pack2 * (stride-offset-depth);
- peeled_mc += Pack2;
- }
- for(Index i=peeled_mc; i<rows; i++)
- {
- if(PanelMode) count += offset;
- for(Index k=0; k<depth; k++)
- blockA[count++] = cj(lhs(i, k));
- if(PanelMode) count += (stride-offset-depth);
}
+ if(PanelMode) count += Pack1 * (stride-offset-depth);
}
-};
+ if(rows-peeled_mc>=Pack2)
+ {
+ if(PanelMode) count += Pack2*offset;
+ for(Index k=0; k<depth; k++)
+ for(Index w=0; w<Pack2; w++)
+ blockA[count++] = cj(lhs(peeled_mc+w, k));
+ if(PanelMode) count += Pack2 * (stride-offset-depth);
+ peeled_mc += Pack2;
+ }
+ for(Index i=peeled_mc; i<rows; i++)
+ {
+ if(PanelMode) count += offset;
+ for(Index k=0; k<depth; k++)
+ blockA[count++] = cj(lhs(i, k));
+ if(PanelMode) count += (stride-offset-depth);
+ }
+}
// copy a complete panel of the rhs
// this version is optimized for column major matrices
@@ -1197,92 +1209,102 @@ struct gemm_pack_rhs<Scalar, Index, nr, ColMajor, Conjugate, PanelMode>
{
typedef typename packet_traits<Scalar>::type Packet;
enum { PacketSize = packet_traits<Scalar>::size };
- EIGEN_DONT_INLINE void operator()(Scalar* blockB, const Scalar* rhs, Index rhsStride, Index depth, Index cols,
- Index stride=0, Index offset=0)
+ EIGEN_DONT_INLINE void operator()(Scalar* blockB, const Scalar* rhs, Index rhsStride, Index depth, Index cols, Index stride=0, Index offset=0);
+};
+
+template<typename Scalar, typename Index, int nr, bool Conjugate, bool PanelMode>
+EIGEN_DONT_INLINE void gemm_pack_rhs<Scalar, Index, nr, ColMajor, Conjugate, PanelMode>
+ ::operator()(Scalar* blockB, const Scalar* rhs, Index rhsStride, Index depth, Index cols, Index stride, Index offset)
+{
+ EIGEN_ASM_COMMENT("EIGEN PRODUCT PACK RHS COLMAJOR");
+ EIGEN_UNUSED_VARIABLE(stride)
+ EIGEN_UNUSED_VARIABLE(offset)
+ eigen_assert(((!PanelMode) && stride==0 && offset==0) || (PanelMode && stride>=depth && offset<=stride));
+ conj_if<NumTraits<Scalar>::IsComplex && Conjugate> cj;
+ Index packet_cols = (cols/nr) * nr;
+ Index count = 0;
+ for(Index j2=0; j2<packet_cols; j2+=nr)
{
- EIGEN_ASM_COMMENT("EIGEN PRODUCT PACK RHS COLMAJOR");
- eigen_assert(((!PanelMode) && stride==0 && offset==0) || (PanelMode && stride>=depth && offset<=stride));
- conj_if<NumTraits<Scalar>::IsComplex && Conjugate> cj;
- Index packet_cols = (cols/nr) * nr;
- Index count = 0;
- for(Index j2=0; j2<packet_cols; j2+=nr)
+ // skip what we have before
+ if(PanelMode) count += nr * offset;
+ const Scalar* b0 = &rhs[(j2+0)*rhsStride];
+ const Scalar* b1 = &rhs[(j2+1)*rhsStride];
+ const Scalar* b2 = &rhs[(j2+2)*rhsStride];
+ const Scalar* b3 = &rhs[(j2+3)*rhsStride];
+ for(Index k=0; k<depth; k++)
{
- // skip what we have before
- if(PanelMode) count += nr * offset;
- const Scalar* b0 = &rhs[(j2+0)*rhsStride];
- const Scalar* b1 = &rhs[(j2+1)*rhsStride];
- const Scalar* b2 = &rhs[(j2+2)*rhsStride];
- const Scalar* b3 = &rhs[(j2+3)*rhsStride];
- for(Index k=0; k<depth; k++)
- {
- blockB[count+0] = cj(b0[k]);
- blockB[count+1] = cj(b1[k]);
- if(nr==4) blockB[count+2] = cj(b2[k]);
- if(nr==4) blockB[count+3] = cj(b3[k]);
- count += nr;
- }
- // skip what we have after
- if(PanelMode) count += nr * (stride-offset-depth);
+ blockB[count+0] = cj(b0[k]);
+ blockB[count+1] = cj(b1[k]);
+ if(nr==4) blockB[count+2] = cj(b2[k]);
+ if(nr==4) blockB[count+3] = cj(b3[k]);
+ count += nr;
}
+ // skip what we have after
+ if(PanelMode) count += nr * (stride-offset-depth);
+ }
- // copy the remaining columns one at a time (nr==1)
- for(Index j2=packet_cols; j2<cols; ++j2)
+ // copy the remaining columns one at a time (nr==1)
+ for(Index j2=packet_cols; j2<cols; ++j2)
+ {
+ if(PanelMode) count += offset;
+ const Scalar* b0 = &rhs[(j2+0)*rhsStride];
+ for(Index k=0; k<depth; k++)
{
- if(PanelMode) count += offset;
- const Scalar* b0 = &rhs[(j2+0)*rhsStride];
- for(Index k=0; k<depth; k++)
- {
- blockB[count] = cj(b0[k]);
- count += 1;
- }
- if(PanelMode) count += (stride-offset-depth);
+ blockB[count] = cj(b0[k]);
+ count += 1;
}
+ if(PanelMode) count += (stride-offset-depth);
}
-};
+}
// this version is optimized for row major matrices
template<typename Scalar, typename Index, int nr, bool Conjugate, bool PanelMode>
struct gemm_pack_rhs<Scalar, Index, nr, RowMajor, Conjugate, PanelMode>
{
enum { PacketSize = packet_traits<Scalar>::size };
- EIGEN_DONT_INLINE void operator()(Scalar* blockB, const Scalar* rhs, Index rhsStride, Index depth, Index cols,
- Index stride=0, Index offset=0)
+ EIGEN_DONT_INLINE void operator()(Scalar* blockB, const Scalar* rhs, Index rhsStride, Index depth, Index cols, Index stride=0, Index offset=0);
+};
+
+template<typename Scalar, typename Index, int nr, bool Conjugate, bool PanelMode>
+EIGEN_DONT_INLINE void gemm_pack_rhs<Scalar, Index, nr, RowMajor, Conjugate, PanelMode>
+ ::operator()(Scalar* blockB, const Scalar* rhs, Index rhsStride, Index depth, Index cols, Index stride, Index offset)
+{
+ EIGEN_ASM_COMMENT("EIGEN PRODUCT PACK RHS ROWMAJOR");
+ EIGEN_UNUSED_VARIABLE(stride)
+ EIGEN_UNUSED_VARIABLE(offset)
+ eigen_assert(((!PanelMode) && stride==0 && offset==0) || (PanelMode && stride>=depth && offset<=stride));
+ conj_if<NumTraits<Scalar>::IsComplex && Conjugate> cj;
+ Index packet_cols = (cols/nr) * nr;
+ Index count = 0;
+ for(Index j2=0; j2<packet_cols; j2+=nr)
{
- EIGEN_ASM_COMMENT("EIGEN PRODUCT PACK RHS ROWMAJOR");
- eigen_assert(((!PanelMode) && stride==0 && offset==0) || (PanelMode && stride>=depth && offset<=stride));
- conj_if<NumTraits<Scalar>::IsComplex && Conjugate> cj;
- Index packet_cols = (cols/nr) * nr;
- Index count = 0;
- for(Index j2=0; j2<packet_cols; j2+=nr)
+ // skip what we have before
+ if(PanelMode) count += nr * offset;
+ for(Index k=0; k<depth; k++)
{
- // skip what we have before
- if(PanelMode) count += nr * offset;
- for(Index k=0; k<depth; k++)
- {
- const Scalar* b0 = &rhs[k*rhsStride + j2];
- blockB[count+0] = cj(b0[0]);
- blockB[count+1] = cj(b0[1]);
- if(nr==4) blockB[count+2] = cj(b0[2]);
- if(nr==4) blockB[count+3] = cj(b0[3]);
- count += nr;
- }
- // skip what we have after
- if(PanelMode) count += nr * (stride-offset-depth);
+ const Scalar* b0 = &rhs[k*rhsStride + j2];
+ blockB[count+0] = cj(b0[0]);
+ blockB[count+1] = cj(b0[1]);
+ if(nr==4) blockB[count+2] = cj(b0[2]);
+ if(nr==4) blockB[count+3] = cj(b0[3]);
+ count += nr;
}
- // copy the remaining columns one at a time (nr==1)
- for(Index j2=packet_cols; j2<cols; ++j2)
+ // skip what we have after
+ if(PanelMode) count += nr * (stride-offset-depth);
+ }
+ // copy the remaining columns one at a time (nr==1)
+ for(Index j2=packet_cols; j2<cols; ++j2)
+ {
+ if(PanelMode) count += offset;
+ const Scalar* b0 = &rhs[j2];
+ for(Index k=0; k<depth; k++)
{
- if(PanelMode) count += offset;
- const Scalar* b0 = &rhs[j2];
- for(Index k=0; k<depth; k++)
- {
- blockB[count] = cj(b0[k*rhsStride]);
- count += 1;
- }
- if(PanelMode) count += stride-offset-depth;
+ blockB[count] = cj(b0[k*rhsStride]);
+ count += 1;
}
+ if(PanelMode) count += stride-offset-depth;
}
-};
+}
} // end namespace internal
diff --git a/Eigen/src/Core/products/GeneralMatrixMatrix.h b/Eigen/src/Core/products/GeneralMatrixMatrix.h
index 73a465ec5..3f5ffcf51 100644
--- a/Eigen/src/Core/products/GeneralMatrixMatrix.h
+++ b/Eigen/src/Core/products/GeneralMatrixMatrix.h
@@ -50,6 +50,7 @@ template<
typename RhsScalar, int RhsStorageOrder, bool ConjugateRhs>
struct general_matrix_matrix_product<Index,LhsScalar,LhsStorageOrder,ConjugateLhs,RhsScalar,RhsStorageOrder,ConjugateRhs,ColMajor>
{
+
typedef typename scalar_product_traits<LhsScalar, RhsScalar>::ReturnType ResScalar;
static void run(Index rows, Index cols, Index depth,
const LhsScalar* _lhs, Index lhsStride,
@@ -169,7 +170,6 @@ static void run(Index rows, Index cols, Index depth,
// vertical panel which is, in practice, a very low number.
pack_rhs(blockB, &rhs(k2,0), rhsStride, actual_kc, cols);
-
// For each mc x kc block of the lhs's vertical panel...
// (==GEPP_VAR1)
for(Index i2=0; i2<rows; i2+=mc)
@@ -183,7 +183,6 @@ static void run(Index rows, Index cols, Index depth,
// Everything is packed, we can now call the block * panel kernel:
gebp(res+i2, resStride, blockA, blockB, actual_mc, actual_kc, cols, alpha, -1, -1, 0, 0, blockW);
-
}
}
}
@@ -204,7 +203,7 @@ struct traits<GeneralProduct<Lhs,Rhs,GemmProduct> >
template<typename Scalar, typename Index, typename Gemm, typename Lhs, typename Rhs, typename Dest, typename BlockingType>
struct gemm_functor
{
- gemm_functor(const Lhs& lhs, const Rhs& rhs, Dest& dest, Scalar actualAlpha,
+ gemm_functor(const Lhs& lhs, const Rhs& rhs, Dest& dest, const Scalar& actualAlpha,
BlockingType& blocking)
: m_lhs(lhs), m_rhs(rhs), m_dest(dest), m_actualAlpha(actualAlpha), m_blocking(blocking)
{}
@@ -395,7 +394,7 @@ class GeneralProduct<Lhs, Rhs, GemmProduct>
EIGEN_CHECK_BINARY_COMPATIBILIY(BinOp,LhsScalar,RhsScalar);
}
- template<typename Dest> void scaleAndAddTo(Dest& dst, Scalar alpha) const
+ template<typename Dest> void scaleAndAddTo(Dest& dst, const Scalar& alpha) const
{
eigen_assert(dst.rows()==m_lhs.rows() && dst.cols()==m_rhs.cols());
diff --git a/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h b/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h
index 432d3a9dc..5c3763909 100644
--- a/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h
+++ b/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h
@@ -12,6 +12,9 @@
namespace Eigen {
+template<typename Scalar, typename Index, int StorageOrder, int UpLo, bool ConjLhs, bool ConjRhs>
+struct selfadjoint_rank1_update;
+
namespace internal {
/**********************************************************************
@@ -39,7 +42,7 @@ struct general_matrix_matrix_triangular_product<Index,LhsScalar,LhsStorageOrder,
{
typedef typename scalar_product_traits<LhsScalar, RhsScalar>::ReturnType ResScalar;
static EIGEN_STRONG_INLINE void run(Index size, Index depth,const LhsScalar* lhs, Index lhsStride,
- const RhsScalar* rhs, Index rhsStride, ResScalar* res, Index resStride, ResScalar alpha)
+ const RhsScalar* rhs, Index rhsStride, ResScalar* res, Index resStride, const ResScalar& alpha)
{
general_matrix_matrix_triangular_product<Index,
RhsScalar, RhsStorageOrder==RowMajor ? ColMajor : RowMajor, ConjugateRhs,
@@ -55,7 +58,7 @@ struct general_matrix_matrix_triangular_product<Index,LhsScalar,LhsStorageOrder,
{
typedef typename scalar_product_traits<LhsScalar, RhsScalar>::ReturnType ResScalar;
static EIGEN_STRONG_INLINE void run(Index size, Index depth,const LhsScalar* _lhs, Index lhsStride,
- const RhsScalar* _rhs, Index rhsStride, ResScalar* res, Index resStride, ResScalar alpha)
+ const RhsScalar* _rhs, Index rhsStride, ResScalar* res, Index resStride, const ResScalar& alpha)
{
const_blas_data_mapper<LhsScalar, Index, LhsStorageOrder> lhs(_lhs,lhsStride);
const_blas_data_mapper<RhsScalar, Index, RhsStorageOrder> rhs(_rhs,rhsStride);
@@ -133,7 +136,7 @@ struct tribb_kernel
enum {
BlockSize = EIGEN_PLAIN_ENUM_MAX(mr,nr)
};
- void operator()(ResScalar* res, Index resStride, const LhsScalar* blockA, const RhsScalar* blockB, Index size, Index depth, ResScalar alpha, RhsScalar* workspace)
+ void operator()(ResScalar* res, Index resStride, const LhsScalar* blockA, const RhsScalar* blockB, Index size, Index depth, const ResScalar& alpha, RhsScalar* workspace)
{
gebp_kernel<LhsScalar, RhsScalar, Index, mr, nr, ConjLhs, ConjRhs> gebp_kernel;
Matrix<ResScalar,BlockSize,BlockSize,ColMajor> buffer;
@@ -180,31 +183,92 @@ struct tribb_kernel
// high level API
+template<typename MatrixType, typename ProductType, int UpLo, bool IsOuterProduct>
+struct general_product_to_triangular_selector;
+
+
+template<typename MatrixType, typename ProductType, int UpLo>
+struct general_product_to_triangular_selector<MatrixType,ProductType,UpLo,true>
+{
+ static void run(MatrixType& mat, const ProductType& prod, const typename MatrixType::Scalar& alpha)
+ {
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::Index Index;
+
+ typedef typename internal::remove_all<typename ProductType::LhsNested>::type Lhs;
+ typedef internal::blas_traits<Lhs> LhsBlasTraits;
+ typedef typename LhsBlasTraits::DirectLinearAccessType ActualLhs;
+ typedef typename internal::remove_all<ActualLhs>::type _ActualLhs;
+ typename internal::add_const_on_value_type<ActualLhs>::type actualLhs = LhsBlasTraits::extract(prod.lhs());
+
+ typedef typename internal::remove_all<typename ProductType::RhsNested>::type Rhs;
+ typedef internal::blas_traits<Rhs> RhsBlasTraits;
+ typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhs;
+ typedef typename internal::remove_all<ActualRhs>::type _ActualRhs;
+ typename internal::add_const_on_value_type<ActualRhs>::type actualRhs = RhsBlasTraits::extract(prod.rhs());
+
+ Scalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs().derived()) * RhsBlasTraits::extractScalarFactor(prod.rhs().derived());
+
+ enum {
+ StorageOrder = (internal::traits<MatrixType>::Flags&RowMajorBit) ? RowMajor : ColMajor,
+ UseLhsDirectly = _ActualLhs::InnerStrideAtCompileTime==1,
+ UseRhsDirectly = _ActualRhs::InnerStrideAtCompileTime==1
+ };
+
+ internal::gemv_static_vector_if<Scalar,Lhs::SizeAtCompileTime,Lhs::MaxSizeAtCompileTime,!UseLhsDirectly> static_lhs;
+ ei_declare_aligned_stack_constructed_variable(Scalar, actualLhsPtr, actualLhs.size(),
+ (UseLhsDirectly ? const_cast<Scalar*>(actualLhs.data()) : static_lhs.data()));
+ if(!UseLhsDirectly) Map<typename _ActualLhs::PlainObject>(actualLhsPtr, actualLhs.size()) = actualLhs;
+
+ internal::gemv_static_vector_if<Scalar,Rhs::SizeAtCompileTime,Rhs::MaxSizeAtCompileTime,!UseRhsDirectly> static_rhs;
+ ei_declare_aligned_stack_constructed_variable(Scalar, actualRhsPtr, actualRhs.size(),
+ (UseRhsDirectly ? const_cast<Scalar*>(actualRhs.data()) : static_rhs.data()));
+ if(!UseRhsDirectly) Map<typename _ActualRhs::PlainObject>(actualRhsPtr, actualRhs.size()) = actualRhs;
+
+
+ selfadjoint_rank1_update<Scalar,Index,StorageOrder,UpLo,
+ LhsBlasTraits::NeedToConjugate && NumTraits<Scalar>::IsComplex,
+ RhsBlasTraits::NeedToConjugate && NumTraits<Scalar>::IsComplex>
+ ::run(actualLhs.size(), mat.data(), mat.outerStride(), actualLhsPtr, actualRhsPtr, actualAlpha);
+ }
+};
+
+template<typename MatrixType, typename ProductType, int UpLo>
+struct general_product_to_triangular_selector<MatrixType,ProductType,UpLo,false>
+{
+ static void run(MatrixType& mat, const ProductType& prod, const typename MatrixType::Scalar& alpha)
+ {
+ typedef typename MatrixType::Index Index;
+
+ typedef typename internal::remove_all<typename ProductType::LhsNested>::type Lhs;
+ typedef internal::blas_traits<Lhs> LhsBlasTraits;
+ typedef typename LhsBlasTraits::DirectLinearAccessType ActualLhs;
+ typedef typename internal::remove_all<ActualLhs>::type _ActualLhs;
+ typename internal::add_const_on_value_type<ActualLhs>::type actualLhs = LhsBlasTraits::extract(prod.lhs());
+
+ typedef typename internal::remove_all<typename ProductType::RhsNested>::type Rhs;
+ typedef internal::blas_traits<Rhs> RhsBlasTraits;
+ typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhs;
+ typedef typename internal::remove_all<ActualRhs>::type _ActualRhs;
+ typename internal::add_const_on_value_type<ActualRhs>::type actualRhs = RhsBlasTraits::extract(prod.rhs());
+
+ typename ProductType::Scalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs().derived()) * RhsBlasTraits::extractScalarFactor(prod.rhs().derived());
+
+ internal::general_matrix_matrix_triangular_product<Index,
+ typename Lhs::Scalar, _ActualLhs::Flags&RowMajorBit ? RowMajor : ColMajor, LhsBlasTraits::NeedToConjugate,
+ typename Rhs::Scalar, _ActualRhs::Flags&RowMajorBit ? RowMajor : ColMajor, RhsBlasTraits::NeedToConjugate,
+ MatrixType::Flags&RowMajorBit ? RowMajor : ColMajor, UpLo>
+ ::run(mat.cols(), actualLhs.cols(),
+ &actualLhs.coeffRef(0,0), actualLhs.outerStride(), &actualRhs.coeffRef(0,0), actualRhs.outerStride(),
+ mat.data(), mat.outerStride(), actualAlpha);
+ }
+};
+
template<typename MatrixType, unsigned int UpLo>
template<typename ProductDerived, typename _Lhs, typename _Rhs>
TriangularView<MatrixType,UpLo>& TriangularView<MatrixType,UpLo>::assignProduct(const ProductBase<ProductDerived, _Lhs,_Rhs>& prod, const Scalar& alpha)
{
- typedef typename internal::remove_all<typename ProductDerived::LhsNested>::type Lhs;
- typedef internal::blas_traits<Lhs> LhsBlasTraits;
- typedef typename LhsBlasTraits::DirectLinearAccessType ActualLhs;
- typedef typename internal::remove_all<ActualLhs>::type _ActualLhs;
- typename internal::add_const_on_value_type<ActualLhs>::type actualLhs = LhsBlasTraits::extract(prod.lhs());
-
- typedef typename internal::remove_all<typename ProductDerived::RhsNested>::type Rhs;
- typedef internal::blas_traits<Rhs> RhsBlasTraits;
- typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhs;
- typedef typename internal::remove_all<ActualRhs>::type _ActualRhs;
- typename internal::add_const_on_value_type<ActualRhs>::type actualRhs = RhsBlasTraits::extract(prod.rhs());
-
- typename ProductDerived::Scalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs().derived()) * RhsBlasTraits::extractScalarFactor(prod.rhs().derived());
-
- internal::general_matrix_matrix_triangular_product<Index,
- typename Lhs::Scalar, _ActualLhs::Flags&RowMajorBit ? RowMajor : ColMajor, LhsBlasTraits::NeedToConjugate,
- typename Rhs::Scalar, _ActualRhs::Flags&RowMajorBit ? RowMajor : ColMajor, RhsBlasTraits::NeedToConjugate,
- MatrixType::Flags&RowMajorBit ? RowMajor : ColMajor, UpLo>
- ::run(m_matrix.cols(), actualLhs.cols(),
- &actualLhs.coeffRef(0,0), actualLhs.outerStride(), &actualRhs.coeffRef(0,0), actualRhs.outerStride(),
- const_cast<Scalar*>(m_matrix.data()), m_matrix.outerStride(), actualAlpha);
+ general_product_to_triangular_selector<MatrixType, ProductDerived, UpLo, (_Lhs::ColsAtCompileTime==1) || (_Rhs::RowsAtCompileTime==1)>::run(m_matrix.const_cast_derived(), prod.derived(), alpha);
return *this;
}
diff --git a/Eigen/src/Core/products/GeneralMatrixVector.h b/Eigen/src/Core/products/GeneralMatrixVector.h
index ba1f73957..09387703e 100644
--- a/Eigen/src/Core/products/GeneralMatrixVector.h
+++ b/Eigen/src/Core/products/GeneralMatrixVector.h
@@ -52,12 +52,17 @@ EIGEN_DONT_INLINE static void run(
Index rows, Index cols,
const LhsScalar* lhs, Index lhsStride,
const RhsScalar* rhs, Index rhsIncr,
- ResScalar* res, Index
- #ifdef EIGEN_INTERNAL_DEBUGGING
- resIncr
- #endif
- , RhsScalar alpha)
+ ResScalar* res, Index resIncr, RhsScalar alpha);
+};
+
+template<typename Index, typename LhsScalar, bool ConjugateLhs, typename RhsScalar, bool ConjugateRhs, int Version>
+EIGEN_DONT_INLINE void general_matrix_vector_product<Index,LhsScalar,ColMajor,ConjugateLhs,RhsScalar,ConjugateRhs,Version>::run(
+ Index rows, Index cols,
+ const LhsScalar* lhs, Index lhsStride,
+ const RhsScalar* rhs, Index rhsIncr,
+ ResScalar* res, Index resIncr, RhsScalar alpha)
{
+ EIGEN_UNUSED_VARIABLE(resIncr)
eigen_internal_assert(resIncr==1);
#ifdef _EIGEN_ACCUMULATE_PACKETS
#error _EIGEN_ACCUMULATE_PACKETS has already been defined
@@ -74,21 +79,21 @@ EIGEN_DONT_INLINE static void run(
conj_helper<LhsScalar,RhsScalar,ConjugateLhs,ConjugateRhs> cj;
conj_helper<LhsPacket,RhsPacket,ConjugateLhs,ConjugateRhs> pcj;
if(ConjugateRhs)
- alpha = conj(alpha);
+ alpha = numext::conj(alpha);
enum { AllAligned = 0, EvenAligned, FirstAligned, NoneAligned };
const Index columnsAtOnce = 4;
const Index peels = 2;
const Index LhsPacketAlignedMask = LhsPacketSize-1;
const Index ResPacketAlignedMask = ResPacketSize-1;
- const Index PeelAlignedMask = ResPacketSize*peels-1;
+// const Index PeelAlignedMask = ResPacketSize*peels-1;
const Index size = rows;
// How many coeffs of the result do we have to skip to be aligned.
// Here we assume data are at least aligned on the base scalar type.
Index alignedStart = internal::first_aligned(res,size);
Index alignedSize = ResPacketSize>1 ? alignedStart + ((size-alignedStart) & ~ResPacketAlignedMask) : 0;
- const Index peeledSize = peels>1 ? alignedStart + ((alignedSize-alignedStart) & ~PeelAlignedMask) : alignedStart;
+ const Index peeledSize = alignedSize - RhsPacketSize*peels - RhsPacketSize + 1;
const Index alignmentStep = LhsPacketSize>1 ? (LhsPacketSize - lhsStride % LhsPacketSize) & LhsPacketAlignedMask : 0;
Index alignmentPattern = alignmentStep==0 ? AllAligned
@@ -177,6 +182,8 @@ EIGEN_DONT_INLINE static void run(
_EIGEN_ACCUMULATE_PACKETS(d,du,d);
break;
case FirstAligned:
+ {
+ Index j = alignedStart;
if(peels>1)
{
LhsPacket A00, A01, A02, A03, A10, A11, A12, A13;
@@ -186,7 +193,7 @@ EIGEN_DONT_INLINE static void run(
A02 = pload<LhsPacket>(&lhs2[alignedStart-2]);
A03 = pload<LhsPacket>(&lhs3[alignedStart-3]);
- for (Index j = alignedStart; j<peeledSize; j+=peels*ResPacketSize)
+ for (; j<peeledSize; j+=peels*ResPacketSize)
{
A11 = pload<LhsPacket>(&lhs1[j-1+LhsPacketSize]); palign<1>(A01,A11);
A12 = pload<LhsPacket>(&lhs2[j-2+LhsPacketSize]); palign<2>(A02,A12);
@@ -210,9 +217,10 @@ EIGEN_DONT_INLINE static void run(
pstore(&res[j+ResPacketSize],T1);
}
}
- for (Index j = peeledSize; j<alignedSize; j+=ResPacketSize)
+ for (; j<alignedSize; j+=ResPacketSize)
_EIGEN_ACCUMULATE_PACKETS(d,du,du);
break;
+ }
default:
for (Index j = alignedStart; j<alignedSize; j+=ResPacketSize)
_EIGEN_ACCUMULATE_PACKETS(du,du,du);
@@ -250,7 +258,7 @@ EIGEN_DONT_INLINE static void run(
// process aligned result's coeffs
if ((size_t(lhs0+alignedStart)%sizeof(LhsPacket))==0)
for (Index i = alignedStart;i<alignedSize;i+=ResPacketSize)
- pstore(&res[i], pcj.pmadd(ploadu<LhsPacket>(&lhs0[i]), ptmp0, pload<ResPacket>(&res[i])));
+ pstore(&res[i], pcj.pmadd(pload<LhsPacket>(&lhs0[i]), ptmp0, pload<ResPacket>(&res[i])));
else
for (Index i = alignedStart;i<alignedSize;i+=ResPacketSize)
pstore(&res[i], pcj.pmadd(ploadu<LhsPacket>(&lhs0[i]), ptmp0, pload<ResPacket>(&res[i])));
@@ -271,7 +279,6 @@ EIGEN_DONT_INLINE static void run(
} while(Vectorizable);
#undef _EIGEN_ACCUMULATE_PACKETS
}
-};
/* Optimized row-major matrix * vector product:
* This algorithm processes 4 rows at onces that allows to both reduce
@@ -309,6 +316,15 @@ EIGEN_DONT_INLINE static void run(
const LhsScalar* lhs, Index lhsStride,
const RhsScalar* rhs, Index rhsIncr,
ResScalar* res, Index resIncr,
+ ResScalar alpha);
+};
+
+template<typename Index, typename LhsScalar, bool ConjugateLhs, typename RhsScalar, bool ConjugateRhs, int Version>
+EIGEN_DONT_INLINE void general_matrix_vector_product<Index,LhsScalar,RowMajor,ConjugateLhs,RhsScalar,ConjugateRhs,Version>::run(
+ Index rows, Index cols,
+ const LhsScalar* lhs, Index lhsStride,
+ const RhsScalar* rhs, Index rhsIncr,
+ ResScalar* res, Index resIncr,
ResScalar alpha)
{
EIGEN_UNUSED_VARIABLE(rhsIncr);
@@ -332,7 +348,7 @@ EIGEN_DONT_INLINE static void run(
const Index peels = 2;
const Index RhsPacketAlignedMask = RhsPacketSize-1;
const Index LhsPacketAlignedMask = LhsPacketSize-1;
- const Index PeelAlignedMask = RhsPacketSize*peels-1;
+// const Index PeelAlignedMask = RhsPacketSize*peels-1;
const Index depth = cols;
// How many coeffs of the result do we have to skip to be aligned.
@@ -340,7 +356,7 @@ EIGEN_DONT_INLINE static void run(
// if that's not the case then vectorization is discarded, see below.
Index alignedStart = internal::first_aligned(rhs, depth);
Index alignedSize = RhsPacketSize>1 ? alignedStart + ((depth-alignedStart) & ~RhsPacketAlignedMask) : 0;
- const Index peeledSize = peels>1 ? alignedStart + ((alignedSize-alignedStart) & ~PeelAlignedMask) : alignedStart;
+ const Index peeledSize = alignedSize - RhsPacketSize*peels - RhsPacketSize + 1;
const Index alignmentStep = LhsPacketSize>1 ? (LhsPacketSize - lhsStride % LhsPacketSize) & LhsPacketAlignedMask : 0;
Index alignmentPattern = alignmentStep==0 ? AllAligned
@@ -430,10 +446,12 @@ EIGEN_DONT_INLINE static void run(
_EIGEN_ACCUMULATE_PACKETS(d,du,d);
break;
case FirstAligned:
+ {
+ Index j = alignedStart;
if (peels>1)
{
/* Here we proccess 4 rows with with two peeled iterations to hide
- * tghe overhead of unaligned loads. Moreover unaligned loads are handled
+ * the overhead of unaligned loads. Moreover unaligned loads are handled
* using special shift/move operations between the two aligned packets
* overlaping the desired unaligned packet. This is *much* more efficient
* than basic unaligned loads.
@@ -443,7 +461,7 @@ EIGEN_DONT_INLINE static void run(
A02 = pload<LhsPacket>(&lhs2[alignedStart-2]);
A03 = pload<LhsPacket>(&lhs3[alignedStart-3]);
- for (Index j = alignedStart; j<peeledSize; j+=peels*RhsPacketSize)
+ for (; j<peeledSize; j+=peels*RhsPacketSize)
{
RhsPacket b = pload<RhsPacket>(&rhs[j]);
A11 = pload<LhsPacket>(&lhs1[j-1+LhsPacketSize]); palign<1>(A01,A11);
@@ -465,9 +483,10 @@ EIGEN_DONT_INLINE static void run(
ptmp3 = pcj.pmadd(A13, b, ptmp3);
}
}
- for (Index j = peeledSize; j<alignedSize; j+=RhsPacketSize)
+ for (; j<alignedSize; j+=RhsPacketSize)
_EIGEN_ACCUMULATE_PACKETS(d,du,du);
break;
+ }
default:
for (Index j = alignedStart; j<alignedSize; j+=RhsPacketSize)
_EIGEN_ACCUMULATE_PACKETS(du,du,du);
@@ -539,7 +558,6 @@ EIGEN_DONT_INLINE static void run(
#undef _EIGEN_ACCUMULATE_PACKETS
}
-};
} // end namespace internal
diff --git a/Eigen/src/Core/products/GeneralMatrixVector_MKL.h b/Eigen/src/Core/products/GeneralMatrixVector_MKL.h
index e9de6af3e..1cb9fe6b5 100644
--- a/Eigen/src/Core/products/GeneralMatrixVector_MKL.h
+++ b/Eigen/src/Core/products/GeneralMatrixVector_MKL.h
@@ -53,7 +53,7 @@ struct general_matrix_vector_product_gemv :
#define EIGEN_MKL_GEMV_SPECIALIZE(Scalar) \
template<typename Index, bool ConjugateLhs, bool ConjugateRhs> \
struct general_matrix_vector_product<Index,Scalar,ColMajor,ConjugateLhs,Scalar,ConjugateRhs,Specialized> { \
-static EIGEN_DONT_INLINE void run( \
+static void run( \
Index rows, Index cols, \
const Scalar* lhs, Index lhsStride, \
const Scalar* rhs, Index rhsIncr, \
@@ -70,7 +70,7 @@ static EIGEN_DONT_INLINE void run( \
}; \
template<typename Index, bool ConjugateLhs, bool ConjugateRhs> \
struct general_matrix_vector_product<Index,Scalar,RowMajor,ConjugateLhs,Scalar,ConjugateRhs,Specialized> { \
-static EIGEN_DONT_INLINE void run( \
+static void run( \
Index rows, Index cols, \
const Scalar* lhs, Index lhsStride, \
const Scalar* rhs, Index rhsIncr, \
@@ -92,7 +92,7 @@ struct general_matrix_vector_product_gemv<Index,EIGTYPE,LhsStorageOrder,Conjugat
{ \
typedef Matrix<EIGTYPE,Dynamic,1,ColMajor> GEMVVector;\
\
-static EIGEN_DONT_INLINE void run( \
+static void run( \
Index rows, Index cols, \
const EIGTYPE* lhs, Index lhsStride, \
const EIGTYPE* rhs, Index rhsIncr, \
diff --git a/Eigen/src/Core/products/SelfadjointMatrixMatrix.h b/Eigen/src/Core/products/SelfadjointMatrixMatrix.h
index 48209636e..99cf9e0ae 100644
--- a/Eigen/src/Core/products/SelfadjointMatrixMatrix.h
+++ b/Eigen/src/Core/products/SelfadjointMatrixMatrix.h
@@ -30,9 +30,9 @@ struct symm_pack_lhs
for(Index k=i; k<i+BlockRows; k++)
{
for(Index w=0; w<h; w++)
- blockA[count++] = conj(lhs(k, i+w)); // transposed
+ blockA[count++] = numext::conj(lhs(k, i+w)); // transposed
- blockA[count++] = real(lhs(k,k)); // real (diagonal)
+ blockA[count++] = numext::real(lhs(k,k)); // real (diagonal)
for(Index w=h+1; w<BlockRows; w++)
blockA[count++] = lhs(i+w, k); // normal
@@ -41,7 +41,7 @@ struct symm_pack_lhs
// transposed copy
for(Index k=i+BlockRows; k<cols; k++)
for(Index w=0; w<BlockRows; w++)
- blockA[count++] = conj(lhs(k, i+w)); // transposed
+ blockA[count++] = numext::conj(lhs(k, i+w)); // transposed
}
void operator()(Scalar* blockA, const Scalar* _lhs, Index lhsStride, Index cols, Index rows)
{
@@ -65,10 +65,10 @@ struct symm_pack_lhs
for(Index k=0; k<i; k++)
blockA[count++] = lhs(i, k); // normal
- blockA[count++] = real(lhs(i, i)); // real (diagonal)
+ blockA[count++] = numext::real(lhs(i, i)); // real (diagonal)
for(Index k=i+1; k<cols; k++)
- blockA[count++] = conj(lhs(k, i)); // transposed
+ blockA[count++] = numext::conj(lhs(k, i)); // transposed
}
}
};
@@ -107,12 +107,12 @@ struct symm_pack_rhs
// transpose
for(Index k=k2; k<j2; k++)
{
- blockB[count+0] = conj(rhs(j2+0,k));
- blockB[count+1] = conj(rhs(j2+1,k));
+ blockB[count+0] = numext::conj(rhs(j2+0,k));
+ blockB[count+1] = numext::conj(rhs(j2+1,k));
if (nr==4)
{
- blockB[count+2] = conj(rhs(j2+2,k));
- blockB[count+3] = conj(rhs(j2+3,k));
+ blockB[count+2] = numext::conj(rhs(j2+2,k));
+ blockB[count+3] = numext::conj(rhs(j2+3,k));
}
count += nr;
}
@@ -124,11 +124,11 @@ struct symm_pack_rhs
for (Index w=0 ; w<h; ++w)
blockB[count+w] = rhs(k,j2+w);
- blockB[count+h] = real(rhs(k,k));
+ blockB[count+h] = numext::real(rhs(k,k));
// transpose
for (Index w=h+1 ; w<nr; ++w)
- blockB[count+w] = conj(rhs(j2+w,k));
+ blockB[count+w] = numext::conj(rhs(j2+w,k));
count += nr;
++h;
}
@@ -151,12 +151,12 @@ struct symm_pack_rhs
{
for(Index k=k2; k<end_k; k++)
{
- blockB[count+0] = conj(rhs(j2+0,k));
- blockB[count+1] = conj(rhs(j2+1,k));
+ blockB[count+0] = numext::conj(rhs(j2+0,k));
+ blockB[count+1] = numext::conj(rhs(j2+1,k));
if (nr==4)
{
- blockB[count+2] = conj(rhs(j2+2,k));
- blockB[count+3] = conj(rhs(j2+3,k));
+ blockB[count+2] = numext::conj(rhs(j2+2,k));
+ blockB[count+3] = numext::conj(rhs(j2+3,k));
}
count += nr;
}
@@ -169,13 +169,13 @@ struct symm_pack_rhs
Index half = (std::min)(end_k,j2);
for(Index k=k2; k<half; k++)
{
- blockB[count] = conj(rhs(j2,k));
+ blockB[count] = numext::conj(rhs(j2,k));
count += 1;
}
if(half==j2 && half<k2+rows)
{
- blockB[count] = real(rhs(j2,j2));
+ blockB[count] = numext::real(rhs(j2,j2));
count += 1;
}
else
@@ -211,7 +211,7 @@ struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,LhsSelfAdjoint,Co
const Scalar* lhs, Index lhsStride,
const Scalar* rhs, Index rhsStride,
Scalar* res, Index resStride,
- Scalar alpha)
+ const Scalar& alpha)
{
product_selfadjoint_matrix<Scalar, Index,
EIGEN_LOGICAL_XOR(RhsSelfAdjoint,RhsStorageOrder==RowMajor) ? ColMajor : RowMajor,
@@ -234,7 +234,18 @@ struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,true,ConjugateLhs
const Scalar* _lhs, Index lhsStride,
const Scalar* _rhs, Index rhsStride,
Scalar* res, Index resStride,
- Scalar alpha)
+ const Scalar& alpha);
+};
+
+template <typename Scalar, typename Index,
+ int LhsStorageOrder, bool ConjugateLhs,
+ int RhsStorageOrder, bool ConjugateRhs>
+EIGEN_DONT_INLINE void product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,true,ConjugateLhs, RhsStorageOrder,false,ConjugateRhs,ColMajor>::run(
+ Index rows, Index cols,
+ const Scalar* _lhs, Index lhsStride,
+ const Scalar* _rhs, Index rhsStride,
+ Scalar* res, Index resStride,
+ const Scalar& alpha)
{
Index size = rows;
@@ -301,7 +312,6 @@ struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,true,ConjugateLhs
}
}
}
-};
// matrix * selfadjoint product
template <typename Scalar, typename Index,
@@ -315,7 +325,18 @@ struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,false,ConjugateLh
const Scalar* _lhs, Index lhsStride,
const Scalar* _rhs, Index rhsStride,
Scalar* res, Index resStride,
- Scalar alpha)
+ const Scalar& alpha);
+};
+
+template <typename Scalar, typename Index,
+ int LhsStorageOrder, bool ConjugateLhs,
+ int RhsStorageOrder, bool ConjugateRhs>
+EIGEN_DONT_INLINE void product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,false,ConjugateLhs, RhsStorageOrder,true,ConjugateRhs,ColMajor>::run(
+ Index rows, Index cols,
+ const Scalar* _lhs, Index lhsStride,
+ const Scalar* _rhs, Index rhsStride,
+ Scalar* res, Index resStride,
+ const Scalar& alpha)
{
Index size = cols;
@@ -353,7 +374,6 @@ struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,false,ConjugateLh
}
}
}
-};
} // end namespace internal
@@ -383,7 +403,7 @@ struct SelfadjointProductMatrix<Lhs,LhsMode,false,Rhs,RhsMode,false>
RhsIsSelfAdjoint = (RhsMode&SelfAdjoint)==SelfAdjoint
};
- template<typename Dest> void scaleAndAddTo(Dest& dst, Scalar alpha) const
+ template<typename Dest> void scaleAndAddTo(Dest& dst, const Scalar& alpha) const
{
eigen_assert(dst.rows()==m_lhs.rows() && dst.cols()==m_rhs.cols());
diff --git a/Eigen/src/Core/products/SelfadjointMatrixMatrix_MKL.h b/Eigen/src/Core/products/SelfadjointMatrixMatrix_MKL.h
index 4e5c4125c..dfa687fef 100644
--- a/Eigen/src/Core/products/SelfadjointMatrixMatrix_MKL.h
+++ b/Eigen/src/Core/products/SelfadjointMatrixMatrix_MKL.h
@@ -23,7 +23,7 @@
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
+//
********************************************************************************
* Content : Eigen bindings to Intel(R) MKL
* Self adjoint matrix * matrix product functionality based on ?SYMM/?HEMM.
@@ -47,7 +47,7 @@ template <typename Index, \
struct product_selfadjoint_matrix<EIGTYPE,Index,LhsStorageOrder,true,ConjugateLhs,RhsStorageOrder,false,ConjugateRhs,ColMajor> \
{\
\
- static EIGEN_DONT_INLINE void run( \
+ static void run( \
Index rows, Index cols, \
const EIGTYPE* _lhs, Index lhsStride, \
const EIGTYPE* _rhs, Index rhsStride, \
@@ -98,7 +98,7 @@ template <typename Index, \
int RhsStorageOrder, bool ConjugateRhs> \
struct product_selfadjoint_matrix<EIGTYPE,Index,LhsStorageOrder,true,ConjugateLhs,RhsStorageOrder,false,ConjugateRhs,ColMajor> \
{\
- static EIGEN_DONT_INLINE void run( \
+ static void run( \
Index rows, Index cols, \
const EIGTYPE* _lhs, Index lhsStride, \
const EIGTYPE* _rhs, Index rhsStride, \
@@ -174,7 +174,7 @@ template <typename Index, \
struct product_selfadjoint_matrix<EIGTYPE,Index,LhsStorageOrder,false,ConjugateLhs,RhsStorageOrder,true,ConjugateRhs,ColMajor> \
{\
\
- static EIGEN_DONT_INLINE void run( \
+ static void run( \
Index rows, Index cols, \
const EIGTYPE* _lhs, Index lhsStride, \
const EIGTYPE* _rhs, Index rhsStride, \
@@ -224,7 +224,7 @@ template <typename Index, \
int RhsStorageOrder, bool ConjugateRhs> \
struct product_selfadjoint_matrix<EIGTYPE,Index,LhsStorageOrder,false,ConjugateLhs,RhsStorageOrder,true,ConjugateRhs,ColMajor> \
{\
- static EIGEN_DONT_INLINE void run( \
+ static void run( \
Index rows, Index cols, \
const EIGTYPE* _lhs, Index lhsStride, \
const EIGTYPE* _rhs, Index rhsStride, \
diff --git a/Eigen/src/Core/products/SelfadjointMatrixVector.h b/Eigen/src/Core/products/SelfadjointMatrixVector.h
index c3145c69a..f698f67f9 100644
--- a/Eigen/src/Core/products/SelfadjointMatrixVector.h
+++ b/Eigen/src/Core/products/SelfadjointMatrixVector.h
@@ -32,10 +32,18 @@ static EIGEN_DONT_INLINE void run(
const Scalar* lhs, Index lhsStride,
const Scalar* _rhs, Index rhsIncr,
Scalar* res,
+ Scalar alpha);
+};
+
+template<typename Scalar, typename Index, int StorageOrder, int UpLo, bool ConjugateLhs, bool ConjugateRhs, int Version>
+EIGEN_DONT_INLINE void selfadjoint_matrix_vector_product<Scalar,Index,StorageOrder,UpLo,ConjugateLhs,ConjugateRhs,Version>::run(
+ Index size,
+ const Scalar* lhs, Index lhsStride,
+ const Scalar* _rhs, Index rhsIncr,
+ Scalar* res,
Scalar alpha)
{
typedef typename packet_traits<Scalar>::type Packet;
- typedef typename NumTraits<Scalar>::Real RealScalar;
const Index PacketSize = sizeof(Packet)/sizeof(Scalar);
enum {
@@ -51,7 +59,7 @@ static EIGEN_DONT_INLINE void run(
conj_helper<Packet,Packet,NumTraits<Scalar>::IsComplex && EIGEN_LOGICAL_XOR(ConjugateLhs, IsRowMajor), ConjugateRhs> pcj0;
conj_helper<Packet,Packet,NumTraits<Scalar>::IsComplex && EIGEN_LOGICAL_XOR(ConjugateLhs, !IsRowMajor), ConjugateRhs> pcj1;
- Scalar cjAlpha = ConjugateRhs ? conj(alpha) : alpha;
+ Scalar cjAlpha = ConjugateRhs ? numext::conj(alpha) : alpha;
// FIXME this copy is now handled outside product_selfadjoint_vector, so it could probably be removed.
// if the rhs is not sequentially stored in memory we copy it to a temporary buffer,
@@ -71,8 +79,8 @@ static EIGEN_DONT_INLINE void run(
for (Index j=FirstTriangular ? bound : 0;
j<(FirstTriangular ? size : bound);j+=2)
{
- register const Scalar* EIGEN_RESTRICT A0 = lhs + j*lhsStride;
- register const Scalar* EIGEN_RESTRICT A1 = lhs + (j+1)*lhsStride;
+ const Scalar* EIGEN_RESTRICT A0 = lhs + j*lhsStride;
+ const Scalar* EIGEN_RESTRICT A1 = lhs + (j+1)*lhsStride;
Scalar t0 = cjAlpha * rhs[j];
Packet ptmp0 = pset1<Packet>(t0);
@@ -90,8 +98,8 @@ static EIGEN_DONT_INLINE void run(
size_t alignedEnd = alignedStart + ((endi-alignedStart)/(PacketSize))*(PacketSize);
// TODO make sure this product is a real * complex and that the rhs is properly conjugated if needed
- res[j] += cjd.pmul(internal::real(A0[j]), t0);
- res[j+1] += cjd.pmul(internal::real(A1[j+1]), t1);
+ res[j] += cjd.pmul(numext::real(A0[j]), t0);
+ res[j+1] += cjd.pmul(numext::real(A1[j+1]), t1);
if(FirstTriangular)
{
res[j] += cj0.pmul(A1[j], t1);
@@ -106,8 +114,8 @@ static EIGEN_DONT_INLINE void run(
for (size_t i=starti; i<alignedStart; ++i)
{
res[i] += t0 * A0[i] + t1 * A1[i];
- t2 += conj(A0[i]) * rhs[i];
- t3 += conj(A1[i]) * rhs[i];
+ t2 += numext::conj(A0[i]) * rhs[i];
+ t3 += numext::conj(A1[i]) * rhs[i];
}
// Yes this an optimization for gcc 4.3 and 4.4 (=> huge speed up)
// gcc 4.2 does this optimization automatically.
@@ -139,12 +147,12 @@ static EIGEN_DONT_INLINE void run(
}
for (Index j=FirstTriangular ? 0 : bound;j<(FirstTriangular ? bound : size);j++)
{
- register const Scalar* EIGEN_RESTRICT A0 = lhs + j*lhsStride;
+ const Scalar* EIGEN_RESTRICT A0 = lhs + j*lhsStride;
Scalar t1 = cjAlpha * rhs[j];
Scalar t2(0);
// TODO make sure this product is a real * complex and that the rhs is properly conjugated if needed
- res[j] += cjd.pmul(internal::real(A0[j]), t1);
+ res[j] += cjd.pmul(numext::real(A0[j]), t1);
for (Index i=FirstTriangular ? 0 : j+1; i<(FirstTriangular ? j : size); i++)
{
res[i] += cj0.pmul(A0[i], t1);
@@ -153,7 +161,6 @@ static EIGEN_DONT_INLINE void run(
res[j] += alpha * t2;
}
}
-};
} // end namespace internal
@@ -180,7 +187,7 @@ struct SelfadjointProductMatrix<Lhs,LhsMode,false,Rhs,0,true>
SelfadjointProductMatrix(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) {}
- template<typename Dest> void scaleAndAddTo(Dest& dest, Scalar alpha) const
+ template<typename Dest> void scaleAndAddTo(Dest& dest, const Scalar& alpha) const
{
typedef typename Dest::Scalar ResScalar;
typedef typename Base::RhsScalar RhsScalar;
@@ -260,7 +267,7 @@ struct SelfadjointProductMatrix<Lhs,0,true,Rhs,RhsMode,false>
SelfadjointProductMatrix(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) {}
- template<typename Dest> void scaleAndAddTo(Dest& dest, Scalar alpha) const
+ template<typename Dest> void scaleAndAddTo(Dest& dest, const Scalar& alpha) const
{
// let's simply transpose the product
Transpose<Dest> destT(dest);
diff --git a/Eigen/src/Core/products/SelfadjointMatrixVector_MKL.h b/Eigen/src/Core/products/SelfadjointMatrixVector_MKL.h
index f88d483b6..86684b66d 100644
--- a/Eigen/src/Core/products/SelfadjointMatrixVector_MKL.h
+++ b/Eigen/src/Core/products/SelfadjointMatrixVector_MKL.h
@@ -50,7 +50,7 @@ struct selfadjoint_matrix_vector_product_symv :
#define EIGEN_MKL_SYMV_SPECIALIZE(Scalar) \
template<typename Index, int StorageOrder, int UpLo, bool ConjugateLhs, bool ConjugateRhs> \
struct selfadjoint_matrix_vector_product<Scalar,Index,StorageOrder,UpLo,ConjugateLhs,ConjugateRhs,Specialized> { \
-static EIGEN_DONT_INLINE void run( \
+static void run( \
Index size, const Scalar* lhs, Index lhsStride, \
const Scalar* _rhs, Index rhsIncr, Scalar* res, Scalar alpha) { \
enum {\
@@ -77,7 +77,7 @@ struct selfadjoint_matrix_vector_product_symv<EIGTYPE,Index,StorageOrder,UpLo,Co
{ \
typedef Matrix<EIGTYPE,Dynamic,1,ColMajor> SYMVVector;\
\
-static EIGEN_DONT_INLINE void run( \
+static void run( \
Index size, const EIGTYPE* lhs, Index lhsStride, \
const EIGTYPE* _rhs, Index rhsIncr, EIGTYPE* res, EIGTYPE alpha) \
{ \
diff --git a/Eigen/src/Core/products/SelfadjointProduct.h b/Eigen/src/Core/products/SelfadjointProduct.h
index 6a55f3d77..6ca4ae6c0 100644
--- a/Eigen/src/Core/products/SelfadjointProduct.h
+++ b/Eigen/src/Core/products/SelfadjointProduct.h
@@ -18,21 +18,19 @@
namespace Eigen {
-template<typename Scalar, typename Index, int StorageOrder, int UpLo, bool ConjLhs, bool ConjRhs>
-struct selfadjoint_rank1_update;
template<typename Scalar, typename Index, int UpLo, bool ConjLhs, bool ConjRhs>
struct selfadjoint_rank1_update<Scalar,Index,ColMajor,UpLo,ConjLhs,ConjRhs>
{
- static void run(Index size, Scalar* mat, Index stride, const Scalar* vec, Scalar alpha)
+ static void run(Index size, Scalar* mat, Index stride, const Scalar* vecX, const Scalar* vecY, const Scalar& alpha)
{
internal::conj_if<ConjRhs> cj;
typedef Map<const Matrix<Scalar,Dynamic,1> > OtherMap;
- typedef typename internal::conditional<ConjLhs,typename OtherMap::ConjugateReturnType,const OtherMap&>::type ConjRhsType;
+ typedef typename internal::conditional<ConjLhs,typename OtherMap::ConjugateReturnType,const OtherMap&>::type ConjLhsType;
for (Index i=0; i<size; ++i)
{
Map<Matrix<Scalar,Dynamic,1> >(mat+stride*i+(UpLo==Lower ? i : 0), (UpLo==Lower ? size-i : (i+1)))
- += (alpha * cj(vec[i])) * ConjRhsType(OtherMap(vec+(UpLo==Lower ? i : 0),UpLo==Lower ? size-i : (i+1)));
+ += (alpha * cj(vecY[i])) * ConjLhsType(OtherMap(vecX+(UpLo==Lower ? i : 0),UpLo==Lower ? size-i : (i+1)));
}
}
};
@@ -40,9 +38,9 @@ struct selfadjoint_rank1_update<Scalar,Index,ColMajor,UpLo,ConjLhs,ConjRhs>
template<typename Scalar, typename Index, int UpLo, bool ConjLhs, bool ConjRhs>
struct selfadjoint_rank1_update<Scalar,Index,RowMajor,UpLo,ConjLhs,ConjRhs>
{
- static void run(Index size, Scalar* mat, Index stride, const Scalar* vec, Scalar alpha)
+ static void run(Index size, Scalar* mat, Index stride, const Scalar* vecX, const Scalar* vecY, const Scalar& alpha)
{
- selfadjoint_rank1_update<Scalar,Index,ColMajor,UpLo==Lower?Upper:Lower,ConjRhs,ConjLhs>::run(size,mat,stride,vec,alpha);
+ selfadjoint_rank1_update<Scalar,Index,ColMajor,UpLo==Lower?Upper:Lower,ConjRhs,ConjLhs>::run(size,mat,stride,vecY,vecX,alpha);
}
};
@@ -52,7 +50,7 @@ struct selfadjoint_product_selector;
template<typename MatrixType, typename OtherType, int UpLo>
struct selfadjoint_product_selector<MatrixType,OtherType,UpLo,true>
{
- static void run(MatrixType& mat, const OtherType& other, typename MatrixType::Scalar alpha)
+ static void run(MatrixType& mat, const OtherType& other, const typename MatrixType::Scalar& alpha)
{
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::Index Index;
@@ -78,14 +76,14 @@ struct selfadjoint_product_selector<MatrixType,OtherType,UpLo,true>
selfadjoint_rank1_update<Scalar,Index,StorageOrder,UpLo,
OtherBlasTraits::NeedToConjugate && NumTraits<Scalar>::IsComplex,
(!OtherBlasTraits::NeedToConjugate) && NumTraits<Scalar>::IsComplex>
- ::run(other.size(), mat.data(), mat.outerStride(), actualOtherPtr, actualAlpha);
+ ::run(other.size(), mat.data(), mat.outerStride(), actualOtherPtr, actualOtherPtr, actualAlpha);
}
};
template<typename MatrixType, typename OtherType, int UpLo>
struct selfadjoint_product_selector<MatrixType,OtherType,UpLo,false>
{
- static void run(MatrixType& mat, const OtherType& other, typename MatrixType::Scalar alpha)
+ static void run(MatrixType& mat, const OtherType& other, const typename MatrixType::Scalar& alpha)
{
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::Index Index;
@@ -113,7 +111,7 @@ struct selfadjoint_product_selector<MatrixType,OtherType,UpLo,false>
template<typename MatrixType, unsigned int UpLo>
template<typename DerivedU>
SelfAdjointView<MatrixType,UpLo>& SelfAdjointView<MatrixType,UpLo>
-::rankUpdate(const MatrixBase<DerivedU>& u, Scalar alpha)
+::rankUpdate(const MatrixBase<DerivedU>& u, const Scalar& alpha)
{
selfadjoint_product_selector<MatrixType,DerivedU,UpLo>::run(_expression().const_cast_derived(), u.derived(), alpha);
diff --git a/Eigen/src/Core/products/SelfadjointRank2Update.h b/Eigen/src/Core/products/SelfadjointRank2Update.h
index 57a98cc2d..8594a97ce 100644
--- a/Eigen/src/Core/products/SelfadjointRank2Update.h
+++ b/Eigen/src/Core/products/SelfadjointRank2Update.h
@@ -24,14 +24,14 @@ struct selfadjoint_rank2_update_selector;
template<typename Scalar, typename Index, typename UType, typename VType>
struct selfadjoint_rank2_update_selector<Scalar,Index,UType,VType,Lower>
{
- static void run(Scalar* mat, Index stride, const UType& u, const VType& v, Scalar alpha)
+ static void run(Scalar* mat, Index stride, const UType& u, const VType& v, const Scalar& alpha)
{
const Index size = u.size();
for (Index i=0; i<size; ++i)
{
Map<Matrix<Scalar,Dynamic,1> >(mat+stride*i+i, size-i) +=
- (conj(alpha) * conj(u.coeff(i))) * v.tail(size-i)
- + (alpha * conj(v.coeff(i))) * u.tail(size-i);
+ (numext::conj(alpha) * numext::conj(u.coeff(i))) * v.tail(size-i)
+ + (alpha * numext::conj(v.coeff(i))) * u.tail(size-i);
}
}
};
@@ -39,13 +39,13 @@ struct selfadjoint_rank2_update_selector<Scalar,Index,UType,VType,Lower>
template<typename Scalar, typename Index, typename UType, typename VType>
struct selfadjoint_rank2_update_selector<Scalar,Index,UType,VType,Upper>
{
- static void run(Scalar* mat, Index stride, const UType& u, const VType& v, Scalar alpha)
+ static void run(Scalar* mat, Index stride, const UType& u, const VType& v, const Scalar& alpha)
{
const Index size = u.size();
for (Index i=0; i<size; ++i)
Map<Matrix<Scalar,Dynamic,1> >(mat+stride*i, i+1) +=
- (conj(alpha) * conj(u.coeff(i))) * v.head(i+1)
- + (alpha * conj(v.coeff(i))) * u.head(i+1);
+ (numext::conj(alpha) * numext::conj(u.coeff(i))) * v.head(i+1)
+ + (alpha * numext::conj(v.coeff(i))) * u.head(i+1);
}
};
@@ -58,7 +58,7 @@ template<bool Cond, typename T> struct conj_expr_if
template<typename MatrixType, unsigned int UpLo>
template<typename DerivedU, typename DerivedV>
SelfAdjointView<MatrixType,UpLo>& SelfAdjointView<MatrixType,UpLo>
-::rankUpdate(const MatrixBase<DerivedU>& u, const MatrixBase<DerivedV>& v, Scalar alpha)
+::rankUpdate(const MatrixBase<DerivedU>& u, const MatrixBase<DerivedV>& v, const Scalar& alpha)
{
typedef internal::blas_traits<DerivedU> UBlasTraits;
typedef typename UBlasTraits::DirectLinearAccessType ActualUType;
@@ -75,9 +75,9 @@ SelfAdjointView<MatrixType,UpLo>& SelfAdjointView<MatrixType,UpLo>
enum { IsRowMajor = (internal::traits<MatrixType>::Flags&RowMajorBit) ? 1 : 0 };
Scalar actualAlpha = alpha * UBlasTraits::extractScalarFactor(u.derived())
- * internal::conj(VBlasTraits::extractScalarFactor(v.derived()));
+ * numext::conj(VBlasTraits::extractScalarFactor(v.derived()));
if (IsRowMajor)
- actualAlpha = internal::conj(actualAlpha);
+ actualAlpha = numext::conj(actualAlpha);
internal::selfadjoint_rank2_update_selector<Scalar, Index,
typename internal::remove_all<typename internal::conj_expr_if<IsRowMajor ^ UBlasTraits::NeedToConjugate,_ActualUType>::type>::type,
diff --git a/Eigen/src/Core/products/TriangularMatrixMatrix.h b/Eigen/src/Core/products/TriangularMatrixMatrix.h
index 92cba66f6..8110507b5 100644
--- a/Eigen/src/Core/products/TriangularMatrixMatrix.h
+++ b/Eigen/src/Core/products/TriangularMatrixMatrix.h
@@ -61,7 +61,7 @@ struct product_triangular_matrix_matrix<Scalar,Index,Mode,LhsIsTriangular,
const Scalar* lhs, Index lhsStride,
const Scalar* rhs, Index rhsStride,
Scalar* res, Index resStride,
- Scalar alpha, level3_blocking<Scalar,Scalar>& blocking)
+ const Scalar& alpha, level3_blocking<Scalar,Scalar>& blocking)
{
product_triangular_matrix_matrix<Scalar, Index,
(Mode&(UnitDiag|ZeroDiag)) | ((Mode&Upper) ? Lower : Upper),
@@ -96,7 +96,20 @@ struct product_triangular_matrix_matrix<Scalar,Index,Mode,true,
const Scalar* _lhs, Index lhsStride,
const Scalar* _rhs, Index rhsStride,
Scalar* res, Index resStride,
- Scalar alpha, level3_blocking<Scalar,Scalar>& blocking)
+ const Scalar& alpha, level3_blocking<Scalar,Scalar>& blocking);
+};
+
+template <typename Scalar, typename Index, int Mode,
+ int LhsStorageOrder, bool ConjugateLhs,
+ int RhsStorageOrder, bool ConjugateRhs, int Version>
+EIGEN_DONT_INLINE void product_triangular_matrix_matrix<Scalar,Index,Mode,true,
+ LhsStorageOrder,ConjugateLhs,
+ RhsStorageOrder,ConjugateRhs,ColMajor,Version>::run(
+ Index _rows, Index _cols, Index _depth,
+ const Scalar* _lhs, Index lhsStride,
+ const Scalar* _rhs, Index rhsStride,
+ Scalar* res, Index resStride,
+ const Scalar& alpha, level3_blocking<Scalar,Scalar>& blocking)
{
// strip zeros
Index diagSize = (std::min)(_rows,_depth);
@@ -203,15 +216,14 @@ struct product_triangular_matrix_matrix<Scalar,Index,Mode,true,
}
}
}
-};
// implements col-major += alpha * op(general) * op(triangular)
template <typename Scalar, typename Index, int Mode,
int LhsStorageOrder, bool ConjugateLhs,
int RhsStorageOrder, bool ConjugateRhs, int Version>
struct product_triangular_matrix_matrix<Scalar,Index,Mode,false,
- LhsStorageOrder,ConjugateLhs,
- RhsStorageOrder,ConjugateRhs,ColMajor,Version>
+ LhsStorageOrder,ConjugateLhs,
+ RhsStorageOrder,ConjugateRhs,ColMajor,Version>
{
typedef gebp_traits<Scalar,Scalar> Traits;
enum {
@@ -225,7 +237,20 @@ struct product_triangular_matrix_matrix<Scalar,Index,Mode,false,
const Scalar* _lhs, Index lhsStride,
const Scalar* _rhs, Index rhsStride,
Scalar* res, Index resStride,
- Scalar alpha, level3_blocking<Scalar,Scalar>& blocking)
+ const Scalar& alpha, level3_blocking<Scalar,Scalar>& blocking);
+};
+
+template <typename Scalar, typename Index, int Mode,
+ int LhsStorageOrder, bool ConjugateLhs,
+ int RhsStorageOrder, bool ConjugateRhs, int Version>
+EIGEN_DONT_INLINE void product_triangular_matrix_matrix<Scalar,Index,Mode,false,
+ LhsStorageOrder,ConjugateLhs,
+ RhsStorageOrder,ConjugateRhs,ColMajor,Version>::run(
+ Index _rows, Index _cols, Index _depth,
+ const Scalar* _lhs, Index lhsStride,
+ const Scalar* _rhs, Index rhsStride,
+ Scalar* res, Index resStride,
+ const Scalar& alpha, level3_blocking<Scalar,Scalar>& blocking)
{
// strip zeros
Index diagSize = (std::min)(_cols,_depth);
@@ -343,7 +368,6 @@ struct product_triangular_matrix_matrix<Scalar,Index,Mode,false,
}
}
}
-};
/***************************************************************************
* Wrapper to product_triangular_matrix_matrix
@@ -364,7 +388,7 @@ struct TriangularProduct<Mode,LhsIsTriangular,Lhs,false,Rhs,false>
TriangularProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) {}
- template<typename Dest> void scaleAndAddTo(Dest& dst, Scalar alpha) const
+ template<typename Dest> void scaleAndAddTo(Dest& dst, const Scalar& alpha) const
{
typename internal::add_const_on_value_type<ActualLhsType>::type lhs = LhsBlasTraits::extract(m_lhs);
typename internal::add_const_on_value_type<ActualRhsType>::type rhs = RhsBlasTraits::extract(m_rhs);
diff --git a/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h b/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h
index 8173da5bb..ba41a1c99 100644
--- a/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h
+++ b/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h
@@ -57,11 +57,11 @@ template <typename Index, int Mode, \
struct product_triangular_matrix_matrix<Scalar,Index, Mode, LhsIsTriangular, \
LhsStorageOrder,ConjugateLhs, RhsStorageOrder,ConjugateRhs,ColMajor,Specialized> { \
static inline void run(Index _rows, Index _cols, Index _depth, const Scalar* _lhs, Index lhsStride,\
- const Scalar* _rhs, Index rhsStride, Scalar* res, Index resStride, Scalar alpha) { \
+ const Scalar* _rhs, Index rhsStride, Scalar* res, Index resStride, Scalar alpha, level3_blocking<Scalar,Scalar>& blocking) { \
product_triangular_matrix_matrix_trmm<Scalar,Index,Mode, \
LhsIsTriangular,LhsStorageOrder,ConjugateLhs, \
RhsStorageOrder, ConjugateRhs, ColMajor>::run( \
- _rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, resStride, alpha); \
+ _rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, resStride, alpha, blocking); \
} \
};
@@ -91,12 +91,12 @@ struct product_triangular_matrix_matrix_trmm<EIGTYPE,Index,Mode,true, \
conjA = ((LhsStorageOrder==ColMajor) && ConjugateLhs) ? 1 : 0 \
}; \
\
- static EIGEN_DONT_INLINE void run( \
+ static void run( \
Index _rows, Index _cols, Index _depth, \
const EIGTYPE* _lhs, Index lhsStride, \
const EIGTYPE* _rhs, Index rhsStride, \
EIGTYPE* res, Index resStride, \
- EIGTYPE alpha) \
+ EIGTYPE alpha, level3_blocking<EIGTYPE,EIGTYPE>& blocking) \
{ \
Index diagSize = (std::min)(_rows,_depth); \
Index rows = IsLower ? _rows : diagSize; \
@@ -115,16 +115,16 @@ struct product_triangular_matrix_matrix_trmm<EIGTYPE,Index,Mode,true, \
/* Most likely no benefit to call TRMM or GEMM from MKL*/ \
product_triangular_matrix_matrix<EIGTYPE,Index,Mode,true, \
LhsStorageOrder,ConjugateLhs, RhsStorageOrder, ConjugateRhs, ColMajor, BuiltIn>::run( \
- _rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, resStride, alpha); \
+ _rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, resStride, alpha, blocking); \
/*std::cout << "TRMM_L: A is not square! Go to Eigen TRMM implementation!\n";*/ \
} else { \
/* Make sense to call GEMM */ \
Map<const MatrixLhs, 0, OuterStride<> > lhsMap(_lhs,rows,depth,OuterStride<>(lhsStride)); \
MatrixLhs aa_tmp=lhsMap.template triangularView<Mode>(); \
MKL_INT aStride = aa_tmp.outerStride(); \
- gemm_blocking_space<ColMajor,EIGTYPE,EIGTYPE,Dynamic,Dynamic,Dynamic> blocking(_rows,_cols,_depth); \
+ gemm_blocking_space<ColMajor,EIGTYPE,EIGTYPE,Dynamic,Dynamic,Dynamic> gemm_blocking(_rows,_cols,_depth); \
general_matrix_matrix_product<Index,EIGTYPE,LhsStorageOrder,ConjugateLhs,EIGTYPE,RhsStorageOrder,ConjugateRhs,ColMajor>::run( \
- rows, cols, depth, aa_tmp.data(), aStride, _rhs, rhsStride, res, resStride, alpha, blocking, 0); \
+ rows, cols, depth, aa_tmp.data(), aStride, _rhs, rhsStride, res, resStride, alpha, gemm_blocking, 0); \
\
/*std::cout << "TRMM_L: A is not square! Go to MKL GEMM implementation! " << nthr<<" \n";*/ \
} \
@@ -205,12 +205,12 @@ struct product_triangular_matrix_matrix_trmm<EIGTYPE,Index,Mode,false, \
conjA = ((RhsStorageOrder==ColMajor) && ConjugateRhs) ? 1 : 0 \
}; \
\
- static EIGEN_DONT_INLINE void run( \
+ static void run( \
Index _rows, Index _cols, Index _depth, \
const EIGTYPE* _lhs, Index lhsStride, \
const EIGTYPE* _rhs, Index rhsStride, \
EIGTYPE* res, Index resStride, \
- EIGTYPE alpha) \
+ EIGTYPE alpha, level3_blocking<EIGTYPE,EIGTYPE>& blocking) \
{ \
Index diagSize = (std::min)(_cols,_depth); \
Index rows = _rows; \
@@ -229,16 +229,16 @@ struct product_triangular_matrix_matrix_trmm<EIGTYPE,Index,Mode,false, \
/* Most likely no benefit to call TRMM or GEMM from MKL*/ \
product_triangular_matrix_matrix<EIGTYPE,Index,Mode,false, \
LhsStorageOrder,ConjugateLhs, RhsStorageOrder, ConjugateRhs, ColMajor, BuiltIn>::run( \
- _rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, resStride, alpha); \
+ _rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, resStride, alpha, blocking); \
/*std::cout << "TRMM_R: A is not square! Go to Eigen TRMM implementation!\n";*/ \
} else { \
/* Make sense to call GEMM */ \
Map<const MatrixRhs, 0, OuterStride<> > rhsMap(_rhs,depth,cols, OuterStride<>(rhsStride)); \
MatrixRhs aa_tmp=rhsMap.template triangularView<Mode>(); \
MKL_INT aStride = aa_tmp.outerStride(); \
- gemm_blocking_space<ColMajor,EIGTYPE,EIGTYPE,Dynamic,Dynamic,Dynamic> blocking(_rows,_cols,_depth); \
+ gemm_blocking_space<ColMajor,EIGTYPE,EIGTYPE,Dynamic,Dynamic,Dynamic> gemm_blocking(_rows,_cols,_depth); \
general_matrix_matrix_product<Index,EIGTYPE,LhsStorageOrder,ConjugateLhs,EIGTYPE,RhsStorageOrder,ConjugateRhs,ColMajor>::run( \
- rows, cols, depth, _lhs, lhsStride, aa_tmp.data(), aStride, res, resStride, alpha, blocking, 0); \
+ rows, cols, depth, _lhs, lhsStride, aa_tmp.data(), aStride, res, resStride, alpha, gemm_blocking, 0); \
\
/*std::cout << "TRMM_R: A is not square! Go to MKL GEMM implementation! " << nthr<<" \n";*/ \
} \
diff --git a/Eigen/src/Core/products/TriangularMatrixVector.h b/Eigen/src/Core/products/TriangularMatrixVector.h
index b1c10c201..6117d5a82 100644
--- a/Eigen/src/Core/products/TriangularMatrixVector.h
+++ b/Eigen/src/Core/products/TriangularMatrixVector.h
@@ -27,7 +27,13 @@ struct triangular_matrix_vector_product<Index,Mode,LhsScalar,ConjLhs,RhsScalar,C
HasZeroDiag = (Mode & ZeroDiag)==ZeroDiag
};
static EIGEN_DONT_INLINE void run(Index _rows, Index _cols, const LhsScalar* _lhs, Index lhsStride,
- const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, ResScalar alpha)
+ const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, const ResScalar& alpha);
+};
+
+template<typename Index, int Mode, typename LhsScalar, bool ConjLhs, typename RhsScalar, bool ConjRhs, int Version>
+EIGEN_DONT_INLINE void triangular_matrix_vector_product<Index,Mode,LhsScalar,ConjLhs,RhsScalar,ConjRhs,ColMajor,Version>
+ ::run(Index _rows, Index _cols, const LhsScalar* _lhs, Index lhsStride,
+ const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, const ResScalar& alpha)
{
static const Index PanelWidth = EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH;
Index size = (std::min)(_rows,_cols);
@@ -78,7 +84,6 @@ struct triangular_matrix_vector_product<Index,Mode,LhsScalar,ConjLhs,RhsScalar,C
_res, resIncr, alpha);
}
}
-};
template<typename Index, int Mode, typename LhsScalar, bool ConjLhs, typename RhsScalar, bool ConjRhs,int Version>
struct triangular_matrix_vector_product<Index,Mode,LhsScalar,ConjLhs,RhsScalar,ConjRhs,RowMajor,Version>
@@ -89,8 +94,14 @@ struct triangular_matrix_vector_product<Index,Mode,LhsScalar,ConjLhs,RhsScalar,C
HasUnitDiag = (Mode & UnitDiag)==UnitDiag,
HasZeroDiag = (Mode & ZeroDiag)==ZeroDiag
};
- static void run(Index _rows, Index _cols, const LhsScalar* _lhs, Index lhsStride,
- const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, ResScalar alpha)
+ static EIGEN_DONT_INLINE void run(Index _rows, Index _cols, const LhsScalar* _lhs, Index lhsStride,
+ const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, const ResScalar& alpha);
+};
+
+template<typename Index, int Mode, typename LhsScalar, bool ConjLhs, typename RhsScalar, bool ConjRhs,int Version>
+EIGEN_DONT_INLINE void triangular_matrix_vector_product<Index,Mode,LhsScalar,ConjLhs,RhsScalar,ConjRhs,RowMajor,Version>
+ ::run(Index _rows, Index _cols, const LhsScalar* _lhs, Index lhsStride,
+ const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, const ResScalar& alpha)
{
static const Index PanelWidth = EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH;
Index diagSize = (std::min)(_rows,_cols);
@@ -141,7 +152,6 @@ struct triangular_matrix_vector_product<Index,Mode,LhsScalar,ConjLhs,RhsScalar,C
&res.coeffRef(diagSize), resIncr, alpha);
}
}
-};
/***************************************************************************
* Wrapper to product_triangular_vector
@@ -171,7 +181,7 @@ struct TriangularProduct<Mode,true,Lhs,false,Rhs,true>
TriangularProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) {}
- template<typename Dest> void scaleAndAddTo(Dest& dst, Scalar alpha) const
+ template<typename Dest> void scaleAndAddTo(Dest& dst, const Scalar& alpha) const
{
eigen_assert(dst.rows()==m_lhs.rows() && dst.cols()==m_rhs.cols());
@@ -187,7 +197,7 @@ struct TriangularProduct<Mode,false,Lhs,true,Rhs,false>
TriangularProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) {}
- template<typename Dest> void scaleAndAddTo(Dest& dst, Scalar alpha) const
+ template<typename Dest> void scaleAndAddTo(Dest& dst, const Scalar& alpha) const
{
eigen_assert(dst.rows()==m_lhs.rows() && dst.cols()==m_rhs.cols());
@@ -205,7 +215,7 @@ namespace internal {
template<> struct trmv_selector<ColMajor>
{
template<int Mode, typename Lhs, typename Rhs, typename Dest>
- static void run(const TriangularProduct<Mode,true,Lhs,false,Rhs,true>& prod, Dest& dest, typename TriangularProduct<Mode,true,Lhs,false,Rhs,true>::Scalar alpha)
+ static void run(const TriangularProduct<Mode,true,Lhs,false,Rhs,true>& prod, Dest& dest, const typename TriangularProduct<Mode,true,Lhs,false,Rhs,true>::Scalar& alpha)
{
typedef TriangularProduct<Mode,true,Lhs,false,Rhs,true> ProductType;
typedef typename ProductType::Index Index;
@@ -235,7 +245,7 @@ template<> struct trmv_selector<ColMajor>
gemv_static_vector_if<ResScalar,Dest::SizeAtCompileTime,Dest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;
- bool alphaIsCompatible = (!ComplexByReal) || (imag(actualAlpha)==RealScalar(0));
+ bool alphaIsCompatible = (!ComplexByReal) || (numext::imag(actualAlpha)==RealScalar(0));
bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;
RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha);
@@ -246,7 +256,7 @@ template<> struct trmv_selector<ColMajor>
if(!evalToDest)
{
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
- int size = dest.size();
+ Index size = dest.size();
EIGEN_DENSE_STORAGE_CTOR_PLUGIN
#endif
if(!alphaIsCompatible)
@@ -281,7 +291,7 @@ template<> struct trmv_selector<ColMajor>
template<> struct trmv_selector<RowMajor>
{
template<int Mode, typename Lhs, typename Rhs, typename Dest>
- static void run(const TriangularProduct<Mode,true,Lhs,false,Rhs,true>& prod, Dest& dest, typename TriangularProduct<Mode,true,Lhs,false,Rhs,true>::Scalar alpha)
+ static void run(const TriangularProduct<Mode,true,Lhs,false,Rhs,true>& prod, Dest& dest, const typename TriangularProduct<Mode,true,Lhs,false,Rhs,true>::Scalar& alpha)
{
typedef TriangularProduct<Mode,true,Lhs,false,Rhs,true> ProductType;
typedef typename ProductType::LhsScalar LhsScalar;
diff --git a/Eigen/src/Core/products/TriangularMatrixVector_MKL.h b/Eigen/src/Core/products/TriangularMatrixVector_MKL.h
index 3589b8c5e..09f110da7 100644
--- a/Eigen/src/Core/products/TriangularMatrixVector_MKL.h
+++ b/Eigen/src/Core/products/TriangularMatrixVector_MKL.h
@@ -50,7 +50,7 @@ struct triangular_matrix_vector_product_trmv :
#define EIGEN_MKL_TRMV_SPECIALIZE(Scalar) \
template<typename Index, int Mode, bool ConjLhs, bool ConjRhs> \
struct triangular_matrix_vector_product<Index,Mode,Scalar,ConjLhs,Scalar,ConjRhs,ColMajor,Specialized> { \
- static EIGEN_DONT_INLINE void run(Index _rows, Index _cols, const Scalar* _lhs, Index lhsStride, \
+ static void run(Index _rows, Index _cols, const Scalar* _lhs, Index lhsStride, \
const Scalar* _rhs, Index rhsIncr, Scalar* _res, Index resIncr, Scalar alpha) { \
triangular_matrix_vector_product_trmv<Index,Mode,Scalar,ConjLhs,Scalar,ConjRhs,ColMajor>::run( \
_rows, _cols, _lhs, lhsStride, _rhs, rhsIncr, _res, resIncr, alpha); \
@@ -58,7 +58,7 @@ struct triangular_matrix_vector_product<Index,Mode,Scalar,ConjLhs,Scalar,ConjRhs
}; \
template<typename Index, int Mode, bool ConjLhs, bool ConjRhs> \
struct triangular_matrix_vector_product<Index,Mode,Scalar,ConjLhs,Scalar,ConjRhs,RowMajor,Specialized> { \
- static EIGEN_DONT_INLINE void run(Index _rows, Index _cols, const Scalar* _lhs, Index lhsStride, \
+ static void run(Index _rows, Index _cols, const Scalar* _lhs, Index lhsStride, \
const Scalar* _rhs, Index rhsIncr, Scalar* _res, Index resIncr, Scalar alpha) { \
triangular_matrix_vector_product_trmv<Index,Mode,Scalar,ConjLhs,Scalar,ConjRhs,RowMajor>::run( \
_rows, _cols, _lhs, lhsStride, _rhs, rhsIncr, _res, resIncr, alpha); \
@@ -81,12 +81,12 @@ struct triangular_matrix_vector_product_trmv<Index,Mode,EIGTYPE,ConjLhs,EIGTYPE,
IsZeroDiag = (Mode&ZeroDiag) ? 1 : 0, \
LowUp = IsLower ? Lower : Upper \
}; \
- static EIGEN_DONT_INLINE void run(Index _rows, Index _cols, const EIGTYPE* _lhs, Index lhsStride, \
- const EIGTYPE* _rhs, Index rhsIncr, EIGTYPE* _res, Index resIncr, EIGTYPE alpha, level3_blocking<EIGTYPE,EIGTYPE>& blocking) \
+ static void run(Index _rows, Index _cols, const EIGTYPE* _lhs, Index lhsStride, \
+ const EIGTYPE* _rhs, Index rhsIncr, EIGTYPE* _res, Index resIncr, EIGTYPE alpha) \
{ \
if (ConjLhs || IsZeroDiag) { \
triangular_matrix_vector_product<Index,Mode,EIGTYPE,ConjLhs,EIGTYPE,ConjRhs,ColMajor,BuiltIn>::run( \
- _rows, _cols, _lhs, lhsStride, _rhs, rhsIncr, _res, resIncr, alpha, blocking); \
+ _rows, _cols, _lhs, lhsStride, _rhs, rhsIncr, _res, resIncr, alpha); \
return; \
}\
Index size = (std::min)(_rows,_cols); \
@@ -166,12 +166,12 @@ struct triangular_matrix_vector_product_trmv<Index,Mode,EIGTYPE,ConjLhs,EIGTYPE,
IsZeroDiag = (Mode&ZeroDiag) ? 1 : 0, \
LowUp = IsLower ? Lower : Upper \
}; \
- static EIGEN_DONT_INLINE void run(Index _rows, Index _cols, const EIGTYPE* _lhs, Index lhsStride, \
- const EIGTYPE* _rhs, Index rhsIncr, EIGTYPE* _res, Index resIncr, EIGTYPE alpha, level3_blocking<EIGTYPE,EIGTYPE>& blocking) \
+ static void run(Index _rows, Index _cols, const EIGTYPE* _lhs, Index lhsStride, \
+ const EIGTYPE* _rhs, Index rhsIncr, EIGTYPE* _res, Index resIncr, EIGTYPE alpha) \
{ \
if (IsZeroDiag) { \
triangular_matrix_vector_product<Index,Mode,EIGTYPE,ConjLhs,EIGTYPE,ConjRhs,RowMajor,BuiltIn>::run( \
- _rows, _cols, _lhs, lhsStride, _rhs, rhsIncr, _res, resIncr, alpha, blocking); \
+ _rows, _cols, _lhs, lhsStride, _rhs, rhsIncr, _res, resIncr, alpha); \
return; \
}\
Index size = (std::min)(_rows,_cols); \
diff --git a/Eigen/src/Core/products/TriangularSolverMatrix.h b/Eigen/src/Core/products/TriangularSolverMatrix.h
index a49ea3183..f103eae72 100644
--- a/Eigen/src/Core/products/TriangularSolverMatrix.h
+++ b/Eigen/src/Core/products/TriangularSolverMatrix.h
@@ -18,7 +18,7 @@ namespace internal {
template <typename Scalar, typename Index, int Side, int Mode, bool Conjugate, int TriStorageOrder>
struct triangular_solve_matrix<Scalar,Index,Side,Mode,Conjugate,TriStorageOrder,RowMajor>
{
- static EIGEN_DONT_INLINE void run(
+ static void run(
Index size, Index cols,
const Scalar* tri, Index triStride,
Scalar* _other, Index otherStride,
@@ -42,6 +42,13 @@ struct triangular_solve_matrix<Scalar,Index,OnTheLeft,Mode,Conjugate,TriStorageO
Index size, Index otherSize,
const Scalar* _tri, Index triStride,
Scalar* _other, Index otherStride,
+ level3_blocking<Scalar,Scalar>& blocking);
+};
+template <typename Scalar, typename Index, int Mode, bool Conjugate, int TriStorageOrder>
+EIGEN_DONT_INLINE void triangular_solve_matrix<Scalar,Index,OnTheLeft,Mode,Conjugate,TriStorageOrder,ColMajor>::run(
+ Index size, Index otherSize,
+ const Scalar* _tri, Index triStride,
+ Scalar* _other, Index otherStride,
level3_blocking<Scalar,Scalar>& blocking)
{
Index cols = otherSize;
@@ -173,7 +180,6 @@ struct triangular_solve_matrix<Scalar,Index,OnTheLeft,Mode,Conjugate,TriStorageO
}
}
}
-};
/* Optimized triangular solver with multiple left hand sides and the trinagular matrix on the right
*/
@@ -184,6 +190,13 @@ struct triangular_solve_matrix<Scalar,Index,OnTheRight,Mode,Conjugate,TriStorage
Index size, Index otherSize,
const Scalar* _tri, Index triStride,
Scalar* _other, Index otherStride,
+ level3_blocking<Scalar,Scalar>& blocking);
+};
+template <typename Scalar, typename Index, int Mode, bool Conjugate, int TriStorageOrder>
+EIGEN_DONT_INLINE void triangular_solve_matrix<Scalar,Index,OnTheRight,Mode,Conjugate,TriStorageOrder,ColMajor>::run(
+ Index size, Index otherSize,
+ const Scalar* _tri, Index triStride,
+ Scalar* _other, Index otherStride,
level3_blocking<Scalar,Scalar>& blocking)
{
Index rows = otherSize;
@@ -308,7 +321,6 @@ struct triangular_solve_matrix<Scalar,Index,OnTheRight,Mode,Conjugate,TriStorage
}
}
}
-};
} // end namespace internal
diff --git a/Eigen/src/Core/products/TriangularSolverMatrix_MKL.h b/Eigen/src/Core/products/TriangularSolverMatrix_MKL.h
index a4f508b2e..6a0bb8339 100644
--- a/Eigen/src/Core/products/TriangularSolverMatrix_MKL.h
+++ b/Eigen/src/Core/products/TriangularSolverMatrix_MKL.h
@@ -48,7 +48,7 @@ struct triangular_solve_matrix<EIGTYPE,Index,OnTheLeft,Mode,Conjugate,TriStorage
IsZeroDiag = (Mode&ZeroDiag) ? 1 : 0, \
conjA = ((TriStorageOrder==ColMajor) && Conjugate) ? 1 : 0 \
}; \
- static EIGEN_DONT_INLINE void run( \
+ static void run( \
Index size, Index otherSize, \
const EIGTYPE* _tri, Index triStride, \
EIGTYPE* _other, Index otherStride, level3_blocking<EIGTYPE,EIGTYPE>& /*blocking*/) \
@@ -103,7 +103,7 @@ struct triangular_solve_matrix<EIGTYPE,Index,OnTheRight,Mode,Conjugate,TriStorag
IsZeroDiag = (Mode&ZeroDiag) ? 1 : 0, \
conjA = ((TriStorageOrder==ColMajor) && Conjugate) ? 1 : 0 \
}; \
- static EIGEN_DONT_INLINE void run( \
+ static void run( \
Index size, Index otherSize, \
const EIGTYPE* _tri, Index triStride, \
EIGTYPE* _other, Index otherStride, level3_blocking<EIGTYPE,EIGTYPE>& /*blocking*/) \
diff --git a/Eigen/src/Core/util/BlasUtil.h b/Eigen/src/Core/util/BlasUtil.h
index 91496651c..a28f16fa0 100644
--- a/Eigen/src/Core/util/BlasUtil.h
+++ b/Eigen/src/Core/util/BlasUtil.h
@@ -42,7 +42,7 @@ template<bool Conjugate> struct conj_if;
template<> struct conj_if<true> {
template<typename T>
- inline T operator()(const T& x) { return conj(x); }
+ inline T operator()(const T& x) { return numext::conj(x); }
template<typename T>
inline T pconj(const T& x) { return internal::pconj(x); }
};
@@ -67,7 +67,7 @@ template<typename RealScalar> struct conj_helper<std::complex<RealScalar>, std::
{ return c + pmul(x,y); }
EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const
- { return Scalar(real(x)*real(y) + imag(x)*imag(y), imag(x)*real(y) - real(x)*imag(y)); }
+ { return Scalar(numext::real(x)*numext::real(y) + numext::imag(x)*numext::imag(y), numext::imag(x)*numext::real(y) - numext::real(x)*numext::imag(y)); }
};
template<typename RealScalar> struct conj_helper<std::complex<RealScalar>, std::complex<RealScalar>, true,false>
@@ -77,7 +77,7 @@ template<typename RealScalar> struct conj_helper<std::complex<RealScalar>, std::
{ return c + pmul(x,y); }
EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const
- { return Scalar(real(x)*real(y) + imag(x)*imag(y), real(x)*imag(y) - imag(x)*real(y)); }
+ { return Scalar(numext::real(x)*numext::real(y) + numext::imag(x)*numext::imag(y), numext::real(x)*numext::imag(y) - numext::imag(x)*numext::real(y)); }
};
template<typename RealScalar> struct conj_helper<std::complex<RealScalar>, std::complex<RealScalar>, true,true>
@@ -87,7 +87,7 @@ template<typename RealScalar> struct conj_helper<std::complex<RealScalar>, std::
{ return c + pmul(x,y); }
EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const
- { return Scalar(real(x)*real(y) - imag(x)*imag(y), - real(x)*imag(y) - imag(x)*real(y)); }
+ { return Scalar(numext::real(x)*numext::real(y) - numext::imag(x)*numext::imag(y), - numext::real(x)*numext::imag(y) - numext::imag(x)*numext::real(y)); }
};
template<typename RealScalar,bool Conj> struct conj_helper<std::complex<RealScalar>, RealScalar, Conj,false>
@@ -113,7 +113,7 @@ template<typename From,typename To> struct get_factor {
};
template<typename Scalar> struct get_factor<Scalar,typename NumTraits<Scalar>::Real> {
- static EIGEN_STRONG_INLINE typename NumTraits<Scalar>::Real run(const Scalar& x) { return real(x); }
+ static EIGEN_STRONG_INLINE typename NumTraits<Scalar>::Real run(const Scalar& x) { return numext::real(x); }
};
// Lightweight helper class to access matrix coefficients.
diff --git a/Eigen/src/Core/util/Constants.h b/Eigen/src/Core/util/Constants.h
index 3fd45e84f..14b9624e1 100644
--- a/Eigen/src/Core/util/Constants.h
+++ b/Eigen/src/Core/util/Constants.h
@@ -13,13 +13,18 @@
namespace Eigen {
-/** This value means that a quantity is not known at compile-time, and that instead the value is
+/** This value means that a positive quantity (e.g., a size) is not known at compile-time, and that instead the value is
* stored in some runtime variable.
*
* Changing the value of Dynamic breaks the ABI, as Dynamic is often used as a template parameter for Matrix.
*/
const int Dynamic = -1;
+/** This value means that a signed quantity (e.g., a signed index) is not known at compile-time, and that instead its value
+ * has to be specified at runtime.
+ */
+const int DynamicIndex = 0xffffff;
+
/** This value means +Infinity; it is currently used only as the p parameter to MatrixBase::lpNorm<int>().
* The value Infinity there means the L-infinity norm.
*/
@@ -227,7 +232,9 @@ enum {
* scalar loops to handle the unaligned boundaries */
SliceVectorizedTraversal,
/** \internal Special case to properly handle incompatible scalar types or other defecting cases*/
- InvalidTraversal
+ InvalidTraversal,
+ /** \internal Evaluate all entries at once */
+ AllAtOnceTraversal
};
/** \internal \ingroup enums
@@ -257,9 +264,9 @@ enum {
ColMajor = 0,
/** Storage order is row major (see \ref TopicStorageOrders). */
RowMajor = 0x1, // it is only a coincidence that this is equal to RowMajorBit -- don't rely on that
- /** \internal Align the matrix itself if it is vectorizable fixed-size */
+ /** Align the matrix itself if it is vectorizable fixed-size */
AutoAlign = 0,
- /** \internal Don't require alignment for the matrix itself (the array of coefficients, if dynamically allocated, may still be requested to be aligned) */ // FIXME --- clarify the situation
+ /** Don't require alignment for the matrix itself (the array of coefficients, if dynamically allocated, may still be requested to be aligned) */ // FIXME --- clarify the situation
DontAlign = 0x2
};
diff --git a/Eigen/src/Core/util/ForwardDeclarations.h b/Eigen/src/Core/util/ForwardDeclarations.h
index bcdfe3914..d6a814586 100644
--- a/Eigen/src/Core/util/ForwardDeclarations.h
+++ b/Eigen/src/Core/util/ForwardDeclarations.h
@@ -78,8 +78,7 @@ template<typename ExpressionType> class NestByValue;
template<typename ExpressionType> class ForceAlignedAccess;
template<typename ExpressionType> class SwapWrapper;
-template<typename XprType, int BlockRows=Dynamic, int BlockCols=Dynamic, bool InnerPanel = false,
- bool HasDirectAccess = internal::has_direct_access<XprType>::ret> class Block;
+template<typename XprType, int BlockRows=Dynamic, int BlockCols=Dynamic, bool InnerPanel = false> class Block;
template<typename MatrixType, int Size=Dynamic> class VectorBlock;
template<typename MatrixType> class Transpose;
@@ -154,7 +153,6 @@ template<typename LhsScalar, typename RhsScalar, bool ConjLhs=false, bool ConjRh
template<typename Scalar> struct scalar_sum_op;
template<typename Scalar> struct scalar_difference_op;
template<typename LhsScalar,typename RhsScalar> struct scalar_conj_product_op;
-template<typename Scalar> struct scalar_quotient_op;
template<typename Scalar> struct scalar_opposite_op;
template<typename Scalar> struct scalar_conjugate_op;
template<typename Scalar> struct scalar_real_op;
@@ -185,6 +183,7 @@ template<typename Scalar> struct scalar_identity_op;
template<typename LhsScalar,typename RhsScalar=LhsScalar> struct scalar_product_op;
template<typename LhsScalar,typename RhsScalar> struct scalar_multiple2_op;
+template<typename LhsScalar,typename RhsScalar=LhsScalar> struct scalar_quotient_op;
} // end namespace internal
@@ -271,6 +270,8 @@ template<typename Derived> struct MatrixExponentialReturnValue;
template<typename Derived> class MatrixFunctionReturnValue;
template<typename Derived> class MatrixSquareRootReturnValue;
template<typename Derived> class MatrixLogarithmReturnValue;
+template<typename Derived> class MatrixPowerReturnValue;
+template<typename Derived, typename Lhs, typename Rhs> class MatrixPowerProduct;
namespace internal {
template <typename Scalar>
diff --git a/Eigen/src/Core/util/MKL_support.h b/Eigen/src/Core/util/MKL_support.h
index 1e6e355d6..8acca9c8c 100644
--- a/Eigen/src/Core/util/MKL_support.h
+++ b/Eigen/src/Core/util/MKL_support.h
@@ -54,8 +54,25 @@
#endif
#if defined EIGEN_USE_MKL
+# include <mkl.h>
+/*Check IMKL version for compatibility: < 10.3 is not usable with Eigen*/
+# ifndef INTEL_MKL_VERSION
+# undef EIGEN_USE_MKL /* INTEL_MKL_VERSION is not even defined on older versions */
+# elif INTEL_MKL_VERSION < 100305 /* the intel-mkl-103-release-notes say this was when the lapacke.h interface was added*/
+# undef EIGEN_USE_MKL
+# endif
+# ifndef EIGEN_USE_MKL
+ /*If the MKL version is too old, undef everything*/
+# undef EIGEN_USE_MKL_ALL
+# undef EIGEN_USE_BLAS
+# undef EIGEN_USE_LAPACKE
+# undef EIGEN_USE_MKL_VML
+# undef EIGEN_USE_LAPACKE_STRICT
+# undef EIGEN_USE_LAPACKE
+# endif
+#endif
-#include <mkl.h>
+#if defined EIGEN_USE_MKL
#include <mkl_lapacke.h>
#define EIGEN_MKL_VML_THRESHOLD 128
diff --git a/Eigen/src/Core/util/Macros.h b/Eigen/src/Core/util/Macros.h
index d973a6837..3a010ec6a 100644
--- a/Eigen/src/Core/util/Macros.h
+++ b/Eigen/src/Core/util/Macros.h
@@ -12,8 +12,8 @@
#define EIGEN_MACROS_H
#define EIGEN_WORLD_VERSION 3
-#define EIGEN_MAJOR_VERSION 1
-#define EIGEN_MINOR_VERSION 1
+#define EIGEN_MAJOR_VERSION 2
+#define EIGEN_MINOR_VERSION 2
#define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \
(EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \
@@ -115,12 +115,6 @@
#define EIGEN_MAKESTRING2(a) #a
#define EIGEN_MAKESTRING(a) EIGEN_MAKESTRING2(a)
-#if EIGEN_GNUC_AT_LEAST(4,1) && !defined(__clang__) && !defined(__INTEL_COMPILER)
-#define EIGEN_FLATTEN_ATTRIB __attribute__((flatten))
-#else
-#define EIGEN_FLATTEN_ATTRIB
-#endif
-
// EIGEN_STRONG_INLINE is a stronger version of the inline, using __forceinline on MSVC,
// but it still doesn't use GCC's always_inline. This is useful in (common) situations where MSVC needs forceinline
// but GCC is still doing fine with just inline.
@@ -151,6 +145,12 @@
#define EIGEN_DONT_INLINE
#endif
+#if (defined __GNUC__)
+#define EIGEN_PERMISSIVE_EXPR __extension__
+#else
+#define EIGEN_PERMISSIVE_EXPR
+#endif
+
// this macro allows to get rid of linking errors about multiply defined functions.
// - static is not very good because it prevents definitions from different object files to be merged.
// So static causes the resulting linked executable to be bloated with multiple copies of the same function.
@@ -238,12 +238,19 @@
#endif
// Suppresses 'unused variable' warnings.
-#define EIGEN_UNUSED_VARIABLE(var) (void)var;
+namespace Eigen {
+ namespace internal {
+ template<typename T> void ignore_unused_variable(const T&) {}
+ }
+}
+#define EIGEN_UNUSED_VARIABLE(var) Eigen::internal::ignore_unused_variable(var);
-#if !defined(EIGEN_ASM_COMMENT) && (defined __GNUC__)
-#define EIGEN_ASM_COMMENT(X) asm("#" X)
-#else
-#define EIGEN_ASM_COMMENT(X)
+#if !defined(EIGEN_ASM_COMMENT)
+ #if (defined __GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
+ #define EIGEN_ASM_COMMENT(X) asm("#" X)
+ #else
+ #define EIGEN_ASM_COMMENT(X)
+ #endif
#endif
/* EIGEN_ALIGN_TO_BOUNDARY(n) forces data to be n-byte aligned. This is used to satisfy SIMD requirements.
@@ -282,7 +289,8 @@
#endif
#ifndef EIGEN_STACK_ALLOCATION_LIMIT
-#define EIGEN_STACK_ALLOCATION_LIMIT 20000
+// 131072 == 128 KB
+#define EIGEN_STACK_ALLOCATION_LIMIT 131072
#endif
#ifndef EIGEN_DEFAULT_IO_FORMAT
@@ -301,6 +309,12 @@
#if defined(_MSC_VER) && (!defined(__INTEL_COMPILER))
#define EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) \
using Base::operator =;
+#elif defined(__clang__) // workaround clang bug (see http://forum.kde.org/viewtopic.php?f=74&t=102653)
+#define EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) \
+ using Base::operator =; \
+ EIGEN_STRONG_INLINE Derived& operator=(const Derived& other) { Base::operator=(other); return *this; } \
+ template <typename OtherDerived> \
+ EIGEN_STRONG_INLINE Derived& operator=(const DenseBase<OtherDerived>& other) { Base::operator=(other.derived()); return *this; }
#else
#define EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) \
using Base::operator =; \
diff --git a/Eigen/src/Core/util/Memory.h b/Eigen/src/Core/util/Memory.h
index 758913712..c4011245a 100644
--- a/Eigen/src/Core/util/Memory.h
+++ b/Eigen/src/Core/util/Memory.h
@@ -19,6 +19,10 @@
#ifndef EIGEN_MEMORY_H
#define EIGEN_MEMORY_H
+#ifndef EIGEN_MALLOC_ALREADY_ALIGNED
+
+// Try to determine automatically if malloc is already aligned.
+
// On 64-bit systems, glibc's malloc returns 16-byte-aligned pointers, see:
// http://www.gnu.org/s/libc/manual/html_node/Aligned-Memory-Blocks.html
// This is true at least since glibc 2.8.
@@ -27,7 +31,7 @@
// page 114, "[The] LP64 model [...] is used by all 64-bit UNIX ports" so it's indeed
// quite safe, at least within the context of glibc, to equate 64-bit with LP64.
#if defined(__GLIBC__) && ((__GLIBC__>=2 && __GLIBC_MINOR__ >= 8) || __GLIBC__>2) \
- && defined(__LP64__)
+ && defined(__LP64__) && ! defined( __SANITIZE_ADDRESS__ )
#define EIGEN_GLIBC_MALLOC_ALREADY_ALIGNED 1
#else
#define EIGEN_GLIBC_MALLOC_ALREADY_ALIGNED 0
@@ -52,10 +56,19 @@
#define EIGEN_MALLOC_ALREADY_ALIGNED 0
#endif
-#if ((defined __QNXNTO__) || (defined _GNU_SOURCE) || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))) \
- && (defined _POSIX_ADVISORY_INFO) && (_POSIX_ADVISORY_INFO > 0)
- #define EIGEN_HAS_POSIX_MEMALIGN 1
-#else
+#endif
+
+// See bug 554 (http://eigen.tuxfamily.org/bz/show_bug.cgi?id=554)
+// It seems to be unsafe to check _POSIX_ADVISORY_INFO without including unistd.h first.
+// Currently, let's include it only on unix systems:
+#if defined(__unix__) || defined(__unix)
+ #include <unistd.h>
+ #if ((defined __QNXNTO__) || (defined _GNU_SOURCE) || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))) && (defined _POSIX_ADVISORY_INFO) && (_POSIX_ADVISORY_INFO > 0)
+ #define EIGEN_HAS_POSIX_MEMALIGN 1
+ #endif
+#endif
+
+#ifndef EIGEN_HAS_POSIX_MEMALIGN
#define EIGEN_HAS_POSIX_MEMALIGN 0
#endif
@@ -88,11 +101,11 @@ inline void throw_std_bad_alloc()
/** \internal Like malloc, but the returned pointer is guaranteed to be 16-byte aligned.
* Fast, but wastes 16 additional bytes of memory. Does not throw any exception.
*/
-inline void* handmade_aligned_malloc(size_t size)
+inline void* handmade_aligned_malloc(std::size_t size)
{
void *original = std::malloc(size+16);
if (original == 0) return 0;
- void *aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(original) & ~(size_t(15))) + 16);
+ void *aligned = reinterpret_cast<void*>((reinterpret_cast<std::size_t>(original) & ~(std::size_t(15))) + 16);
*(reinterpret_cast<void**>(aligned) - 1) = original;
return aligned;
}
@@ -108,13 +121,18 @@ inline void handmade_aligned_free(void *ptr)
* Since we know that our handmade version is based on std::realloc
* we can use std::realloc to implement efficient reallocation.
*/
-inline void* handmade_aligned_realloc(void* ptr, size_t size, size_t = 0)
+inline void* handmade_aligned_realloc(void* ptr, std::size_t size, std::size_t = 0)
{
if (ptr == 0) return handmade_aligned_malloc(size);
void *original = *(reinterpret_cast<void**>(ptr) - 1);
+ std::ptrdiff_t previous_offset = static_cast<char *>(ptr)-static_cast<char *>(original);
original = std::realloc(original,size+16);
if (original == 0) return 0;
- void *aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(original) & ~(size_t(15))) + 16);
+ void *aligned = reinterpret_cast<void*>((reinterpret_cast<std::size_t>(original) & ~(std::size_t(15))) + 16);
+ void *previous_aligned = static_cast<char *>(original)+previous_offset;
+ if(aligned!=previous_aligned)
+ std::memmove(aligned, previous_aligned, size);
+
*(reinterpret_cast<void**>(aligned) - 1) = original;
return aligned;
}
@@ -123,7 +141,7 @@ inline void* handmade_aligned_realloc(void* ptr, size_t size, size_t = 0)
*** Implementation of generic aligned realloc (when no realloc can be used)***
*****************************************************************************/
-void* aligned_malloc(size_t size);
+void* aligned_malloc(std::size_t size);
void aligned_free(void *ptr);
/** \internal
@@ -183,7 +201,7 @@ inline void check_that_malloc_is_allowed()
{
eigen_assert(is_malloc_allowed() && "heap allocation is forbidden (EIGEN_RUNTIME_NO_MALLOC is defined and g_is_malloc_allowed is false)");
}
-#else
+#else
inline void check_that_malloc_is_allowed()
{}
#endif
@@ -204,7 +222,7 @@ inline void* aligned_malloc(size_t size)
if(posix_memalign(&result, 16, size)) result = 0;
#elif EIGEN_HAS_MM_MALLOC
result = _mm_malloc(size, 16);
- #elif (defined _MSC_VER)
+ #elif defined(_MSC_VER) && (!defined(_WIN32_WCE))
result = _aligned_malloc(size, 16);
#else
result = handmade_aligned_malloc(size);
@@ -227,7 +245,7 @@ inline void aligned_free(void *ptr)
std::free(ptr);
#elif EIGEN_HAS_MM_MALLOC
_mm_free(ptr);
- #elif defined(_MSC_VER)
+ #elif defined(_MSC_VER) && (!defined(_WIN32_WCE))
_aligned_free(ptr);
#else
handmade_aligned_free(ptr);
@@ -254,12 +272,12 @@ inline void* aligned_realloc(void *ptr, size_t new_size, size_t old_size)
// The defined(_mm_free) is just here to verify that this MSVC version
// implements _mm_malloc/_mm_free based on the corresponding _aligned_
// functions. This may not always be the case and we just try to be safe.
- #if defined(_MSC_VER) && defined(_mm_free)
+ #if defined(_MSC_VER) && (!defined(_WIN32_WCE)) && defined(_mm_free)
result = _aligned_realloc(ptr,new_size,16);
#else
result = generic_aligned_realloc(ptr,new_size,old_size);
#endif
-#elif defined(_MSC_VER)
+#elif defined(_MSC_VER) && (!defined(_WIN32_WCE))
result = _aligned_realloc(ptr,new_size,16);
#else
result = handmade_aligned_realloc(ptr,new_size,old_size);
@@ -446,7 +464,6 @@ template<typename T, bool Align> inline void conditional_aligned_delete_auto(T *
template<typename Scalar, typename Index>
static inline Index first_aligned(const Scalar* array, Index size)
{
- typedef typename packet_traits<Scalar>::type Packet;
enum { PacketSize = packet_traits<Scalar>::size,
PacketAlignedMask = PacketSize-1
};
@@ -470,6 +487,13 @@ static inline Index first_aligned(const Scalar* array, Index size)
}
}
+/** \internal Returns the smallest integer multiple of \a base and greater or equal to \a size
+ */
+template<typename Index>
+inline static Index first_multiple(Index size, Index base)
+{
+ return ((size+base-1)/base)*base;
+}
// std::copy is much slower than memcpy, so let's introduce a smart_copy which
// use memcpy on trivial types, i.e., on types that does not require an initialization ctor.
@@ -554,7 +578,7 @@ template<typename T> class aligned_stack_memory_handler
*/
#ifdef EIGEN_ALLOCA
- #ifdef __arm__
+ #if defined(__arm__) || defined(_WIN32)
#define EIGEN_ALIGNED_ALLOCA(SIZE) reinterpret_cast<void*>((reinterpret_cast<size_t>(EIGEN_ALLOCA(SIZE+16)) & ~(size_t(15))) + 16)
#else
#define EIGEN_ALIGNED_ALLOCA EIGEN_ALLOCA
@@ -574,7 +598,7 @@ template<typename T> class aligned_stack_memory_handler
Eigen::internal::check_size_for_overflow<TYPE>(SIZE); \
TYPE* NAME = (BUFFER)!=0 ? BUFFER : reinterpret_cast<TYPE*>(Eigen::internal::aligned_malloc(sizeof(TYPE)*SIZE)); \
Eigen::internal::aligned_stack_memory_handler<TYPE> EIGEN_CAT(NAME,_stack_memory_destructor)((BUFFER)==0 ? NAME : 0,SIZE,true)
-
+
#endif
@@ -610,7 +634,9 @@ template<typename T> class aligned_stack_memory_handler
/* memory allocated we can safely let the default implementation handle */ \
/* this particular case. */ \
static void *operator new(size_t size, void *ptr) { return ::operator new(size,ptr); } \
+ static void *operator new[](size_t size, void* ptr) { return ::operator new[](size,ptr); } \
void operator delete(void * memory, void *ptr) throw() { return ::operator delete(memory,ptr); } \
+ void operator delete[](void * memory, void *ptr) throw() { return ::operator delete[](memory,ptr); } \
/* nothrow-new (returns zero instead of std::bad_alloc) */ \
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
void operator delete(void *ptr, const std::nothrow_t&) throw() { \
@@ -635,7 +661,7 @@ template<typename T> class aligned_stack_memory_handler
* Example:
* \code
* // Matrix4f requires 16 bytes alignment:
-* std::map< int, Matrix4f, std::less<int>,
+* std::map< int, Matrix4f, std::less<int>,
* aligned_allocator<std::pair<const int, Matrix4f> > > my_map_mat4;
* // Vector3f does not require 16 bytes alignment, no need to use Eigen's allocator:
* std::map< int, Vector3f > my_map_vec3;
@@ -705,16 +731,6 @@ public:
::new( p ) T( value );
}
- // Support for c++11
- // Not yet supported in google3
-#if 0 //(__cplusplus >= 201103L)
- template<typename... Args>
- void construct(pointer p, Args&&... args)
- {
- ::new(p) T(std::forward<Args>(args)...);
- }
-#endif
-
void destroy( pointer p )
{
p->~T();
@@ -739,14 +755,19 @@ public:
# if defined(__PIC__) && defined(__i386__)
// Case for x86 with PIC
# define EIGEN_CPUID(abcd,func,id) \
- __asm__ __volatile__ ("xchgl %%ebx, %%esi;cpuid; xchgl %%ebx,%%esi": "=a" (abcd[0]), "=S" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "a" (func), "c" (id));
+ __asm__ __volatile__ ("xchgl %%ebx, %k1;cpuid; xchgl %%ebx,%k1": "=a" (abcd[0]), "=&r" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "a" (func), "c" (id));
+# elif defined(__PIC__) && defined(__x86_64__)
+ // Case for x64 with PIC. In theory this is only a problem with recent gcc and with medium or large code model, not with the default small code model.
+ // However, we cannot detect which code model is used, and the xchg overhead is negligible anyway.
+# define EIGEN_CPUID(abcd,func,id) \
+ __asm__ __volatile__ ("xchg{q}\t{%%}rbx, %q1; cpuid; xchg{q}\t{%%}rbx, %q1": "=a" (abcd[0]), "=&r" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "0" (func), "2" (id));
# else
// Case for x86_64 or x86 w/o PIC
# define EIGEN_CPUID(abcd,func,id) \
- __asm__ __volatile__ ("cpuid": "=a" (abcd[0]), "=b" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "a" (func), "c" (id) );
+ __asm__ __volatile__ ("cpuid": "=a" (abcd[0]), "=b" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "0" (func), "2" (id) );
# endif
# elif defined(_MSC_VER)
-# if (_MSC_VER > 1500)
+# if (_MSC_VER > 1500) && ( defined(_M_IX86) || defined(_M_X64) )
# define EIGEN_CPUID(abcd,func,id) __cpuidex((int*)abcd,func,id)
# endif
# endif
@@ -756,9 +777,9 @@ namespace internal {
#ifdef EIGEN_CPUID
-inline bool cpuid_is_vendor(int abcd[4], const char* vendor)
+inline bool cpuid_is_vendor(int abcd[4], const int vendor[3])
{
- return abcd[1]==(reinterpret_cast<const int*>(vendor))[0] && abcd[3]==(reinterpret_cast<const int*>(vendor))[1] && abcd[2]==(reinterpret_cast<const int*>(vendor))[2];
+ return abcd[1]==vendor[0] && abcd[3]==vendor[1] && abcd[2]==vendor[2];
}
inline void queryCacheSizes_intel_direct(int& l1, int& l2, int& l3)
@@ -900,13 +921,16 @@ inline void queryCacheSizes(int& l1, int& l2, int& l3)
{
#ifdef EIGEN_CPUID
int abcd[4];
+ const int GenuineIntel[] = {0x756e6547, 0x49656e69, 0x6c65746e};
+ const int AuthenticAMD[] = {0x68747541, 0x69746e65, 0x444d4163};
+ const int AMDisbetter_[] = {0x69444d41, 0x74656273, 0x21726574}; // "AMDisbetter!"
// identify the CPU vendor
EIGEN_CPUID(abcd,0x0,0);
int max_std_funcs = abcd[1];
- if(cpuid_is_vendor(abcd,"GenuineIntel"))
+ if(cpuid_is_vendor(abcd,GenuineIntel))
queryCacheSizes_intel(l1,l2,l3,max_std_funcs);
- else if(cpuid_is_vendor(abcd,"AuthenticAMD") || cpuid_is_vendor(abcd,"AMDisbetter!"))
+ else if(cpuid_is_vendor(abcd,AuthenticAMD) || cpuid_is_vendor(abcd,AMDisbetter_))
queryCacheSizes_amd(l1,l2,l3);
else
// by default let's use Intel's API
diff --git a/Eigen/src/Core/util/Meta.h b/Eigen/src/Core/util/Meta.h
index a5f31164d..71d587108 100644
--- a/Eigen/src/Core/util/Meta.h
+++ b/Eigen/src/Core/util/Meta.h
@@ -186,23 +186,35 @@ template<int Y, int InfX, int SupX>
class meta_sqrt<Y, InfX, SupX, true> { public: enum { ret = (SupX*SupX <= Y) ? SupX : InfX }; };
/** \internal determines whether the product of two numeric types is allowed and what the return type is */
-template<typename T, typename U> struct scalar_product_traits;
+template<typename T, typename U> struct scalar_product_traits
+{
+ enum { Defined = 0 };
+};
template<typename T> struct scalar_product_traits<T,T>
{
- //enum { Cost = NumTraits<T>::MulCost };
+ enum {
+ // Cost = NumTraits<T>::MulCost,
+ Defined = 1
+ };
typedef T ReturnType;
};
template<typename T> struct scalar_product_traits<T,std::complex<T> >
{
- //enum { Cost = 2*NumTraits<T>::MulCost };
+ enum {
+ // Cost = 2*NumTraits<T>::MulCost,
+ Defined = 1
+ };
typedef std::complex<T> ReturnType;
};
template<typename T> struct scalar_product_traits<std::complex<T>, T>
{
- //enum { Cost = 2*NumTraits<T>::MulCost };
+ enum {
+ // Cost = 2*NumTraits<T>::MulCost,
+ Defined = 1
+ };
typedef std::complex<T> ReturnType;
};
diff --git a/Eigen/src/Core/util/StaticAssert.h b/Eigen/src/Core/util/StaticAssert.h
index b46a75b37..8872c5b64 100644
--- a/Eigen/src/Core/util/StaticAssert.h
+++ b/Eigen/src/Core/util/StaticAssert.h
@@ -89,7 +89,8 @@
YOU_PASSED_A_ROW_VECTOR_BUT_A_COLUMN_VECTOR_WAS_EXPECTED,
YOU_PASSED_A_COLUMN_VECTOR_BUT_A_ROW_VECTOR_WAS_EXPECTED,
THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE,
- THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH
+ THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH,
+ OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG
};
};
diff --git a/Eigen/src/Core/util/XprHelper.h b/Eigen/src/Core/util/XprHelper.h
index 2a65c7cbf..3c4773054 100644
--- a/Eigen/src/Core/util/XprHelper.h
+++ b/Eigen/src/Core/util/XprHelper.h
@@ -65,12 +65,34 @@ template<typename T> class variable_if_dynamic<T, Dynamic>
void setValue(T value) { m_value = value; }
};
+/** \internal like variable_if_dynamic but for DynamicIndex
+ */
+template<typename T, int Value> class variable_if_dynamicindex
+{
+ public:
+ EIGEN_EMPTY_STRUCT_CTOR(variable_if_dynamicindex)
+ explicit variable_if_dynamicindex(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); assert(v == T(Value)); }
+ static T value() { return T(Value); }
+ void setValue(T) {}
+};
+
+template<typename T> class variable_if_dynamicindex<T, DynamicIndex>
+{
+ T m_value;
+ variable_if_dynamicindex() { assert(false); }
+ public:
+ explicit variable_if_dynamicindex(T value) : m_value(value) {}
+ T value() const { return m_value; }
+ void setValue(T value) { m_value = value; }
+};
+
template<typename T> struct functor_traits
{
enum
{
Cost = 10,
- PacketAccess = false
+ PacketAccess = false,
+ IsRepeatable = false
};
};
@@ -301,9 +323,9 @@ template<typename T, int n=1, typename PlainObject = typename eval<T>::type> str
// it's important that this value can still be squared without integer overflowing.
DynamicAsInteger = 10000,
ScalarReadCost = NumTraits<typename traits<T>::Scalar>::ReadCost,
- ScalarReadCostAsInteger = ScalarReadCost == Dynamic ? DynamicAsInteger : ScalarReadCost,
+ ScalarReadCostAsInteger = ScalarReadCost == Dynamic ? int(DynamicAsInteger) : int(ScalarReadCost),
CoeffReadCost = traits<T>::CoeffReadCost,
- CoeffReadCostAsInteger = CoeffReadCost == Dynamic ? DynamicAsInteger : CoeffReadCost,
+ CoeffReadCostAsInteger = CoeffReadCost == Dynamic ? int(DynamicAsInteger) : int(CoeffReadCost),
NAsInteger = n == Dynamic ? int(DynamicAsInteger) : n,
CostEvalAsInteger = (NAsInteger+1) * ScalarReadCostAsInteger + CoeffReadCostAsInteger,
CostNoEvalAsInteger = NAsInteger * CoeffReadCostAsInteger
diff --git a/Eigen/src/Eigen2Support/Geometry/AlignedBox.h b/Eigen/src/Eigen2Support/Geometry/AlignedBox.h
index 5c928e8fc..2e4309dd9 100644
--- a/Eigen/src/Eigen2Support/Geometry/AlignedBox.h
+++ b/Eigen/src/Eigen2Support/Geometry/AlignedBox.h
@@ -1,5 +1,5 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
+// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
@@ -34,7 +34,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim==
typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;
/** Default constructor initializing a null box. */
- inline explicit AlignedBox()
+ inline AlignedBox()
{ if (AmbientDimAtCompileTime!=Dynamic) setNull(); }
/** Constructs a null box with \a _dim the dimension of the ambient space. */
diff --git a/Eigen/src/Eigen2Support/Geometry/AngleAxis.h b/Eigen/src/Eigen2Support/Geometry/AngleAxis.h
index 20f1fceeb..af598a403 100644
--- a/Eigen/src/Eigen2Support/Geometry/AngleAxis.h
+++ b/Eigen/src/Eigen2Support/Geometry/AngleAxis.h
@@ -1,5 +1,5 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
+// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
diff --git a/Eigen/src/Eigen2Support/Geometry/Hyperplane.h b/Eigen/src/Eigen2Support/Geometry/Hyperplane.h
index 19cc1bfd8..b95bf00ec 100644
--- a/Eigen/src/Eigen2Support/Geometry/Hyperplane.h
+++ b/Eigen/src/Eigen2Support/Geometry/Hyperplane.h
@@ -1,5 +1,5 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
+// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
@@ -44,7 +44,7 @@ public:
typedef Block<Coefficients,AmbientDimAtCompileTime,1> NormalReturnType;
/** Default constructor without initialization */
- inline explicit Hyperplane() {}
+ inline Hyperplane() {}
/** Constructs a dynamic-size hyperplane with \a _dim the dimension
* of the ambient space */
diff --git a/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h b/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h
index 6e4a168a8..9b57b7e0b 100644
--- a/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h
+++ b/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h
@@ -1,5 +1,5 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
+// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
@@ -36,7 +36,7 @@ public:
typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;
/** Default constructor without initialization */
- inline explicit ParametrizedLine() {}
+ inline ParametrizedLine() {}
/** Constructs a dynamic-size line with \a _dim the dimension
* of the ambient space */
diff --git a/Eigen/src/Eigen2Support/Geometry/Quaternion.h b/Eigen/src/Eigen2Support/Geometry/Quaternion.h
index ec87da054..4b6390cf1 100644
--- a/Eigen/src/Eigen2Support/Geometry/Quaternion.h
+++ b/Eigen/src/Eigen2Support/Geometry/Quaternion.h
@@ -1,5 +1,5 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
+// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
diff --git a/Eigen/src/Eigen2Support/Geometry/Rotation2D.h b/Eigen/src/Eigen2Support/Geometry/Rotation2D.h
index 3e02b7a4f..19b8582a1 100644
--- a/Eigen/src/Eigen2Support/Geometry/Rotation2D.h
+++ b/Eigen/src/Eigen2Support/Geometry/Rotation2D.h
@@ -1,5 +1,5 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
+// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
diff --git a/Eigen/src/Eigen2Support/Geometry/RotationBase.h b/Eigen/src/Eigen2Support/Geometry/RotationBase.h
index 78ad73b60..b1c8f38da 100644
--- a/Eigen/src/Eigen2Support/Geometry/RotationBase.h
+++ b/Eigen/src/Eigen2Support/Geometry/RotationBase.h
@@ -1,5 +1,5 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
+// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
diff --git a/Eigen/src/Eigen2Support/Geometry/Scaling.h b/Eigen/src/Eigen2Support/Geometry/Scaling.h
index a07c1c7c7..b8fa6cd3f 100644
--- a/Eigen/src/Eigen2Support/Geometry/Scaling.h
+++ b/Eigen/src/Eigen2Support/Geometry/Scaling.h
@@ -1,5 +1,5 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
+// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
diff --git a/Eigen/src/Eigen2Support/Geometry/Transform.h b/Eigen/src/Eigen2Support/Geometry/Transform.h
index dceb80203..fab60b251 100644
--- a/Eigen/src/Eigen2Support/Geometry/Transform.h
+++ b/Eigen/src/Eigen2Support/Geometry/Transform.h
@@ -1,5 +1,5 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
+// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
diff --git a/Eigen/src/Eigen2Support/Geometry/Translation.h b/Eigen/src/Eigen2Support/Geometry/Translation.h
index 0fb9a9f9a..2b9859f6f 100644
--- a/Eigen/src/Eigen2Support/Geometry/Translation.h
+++ b/Eigen/src/Eigen2Support/Geometry/Translation.h
@@ -1,5 +1,5 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
+// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
diff --git a/Eigen/src/Eigen2Support/LeastSquares.h b/Eigen/src/Eigen2Support/LeastSquares.h
index 7aff428dc..0e6fdb488 100644
--- a/Eigen/src/Eigen2Support/LeastSquares.h
+++ b/Eigen/src/Eigen2Support/LeastSquares.h
@@ -1,5 +1,5 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
+// for linear algebra.
//
// Copyright (C) 2006-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
//
diff --git a/Eigen/src/Eigen2Support/MathFunctions.h b/Eigen/src/Eigen2Support/MathFunctions.h
index 3a8a9ca81..3544af253 100644
--- a/Eigen/src/Eigen2Support/MathFunctions.h
+++ b/Eigen/src/Eigen2Support/MathFunctions.h
@@ -12,18 +12,18 @@
namespace Eigen {
-template<typename T> inline typename NumTraits<T>::Real ei_real(const T& x) { return internal::real(x); }
-template<typename T> inline typename NumTraits<T>::Real ei_imag(const T& x) { return internal::imag(x); }
-template<typename T> inline T ei_conj(const T& x) { return internal::conj(x); }
-template<typename T> inline typename NumTraits<T>::Real ei_abs (const T& x) { return internal::abs(x); }
-template<typename T> inline typename NumTraits<T>::Real ei_abs2(const T& x) { return internal::abs2(x); }
-template<typename T> inline T ei_sqrt(const T& x) { return internal::sqrt(x); }
-template<typename T> inline T ei_exp (const T& x) { return internal::exp(x); }
-template<typename T> inline T ei_log (const T& x) { return internal::log(x); }
-template<typename T> inline T ei_sin (const T& x) { return internal::sin(x); }
-template<typename T> inline T ei_cos (const T& x) { return internal::cos(x); }
-template<typename T> inline T ei_atan2(const T& x,const T& y) { return internal::atan2(x,y); }
-template<typename T> inline T ei_pow (const T& x,const T& y) { return internal::pow(x,y); }
+template<typename T> inline typename NumTraits<T>::Real ei_real(const T& x) { return numext::real(x); }
+template<typename T> inline typename NumTraits<T>::Real ei_imag(const T& x) { return numext::imag(x); }
+template<typename T> inline T ei_conj(const T& x) { return numext::conj(x); }
+template<typename T> inline typename NumTraits<T>::Real ei_abs (const T& x) { using std::abs; return abs(x); }
+template<typename T> inline typename NumTraits<T>::Real ei_abs2(const T& x) { return numext::abs2(x); }
+template<typename T> inline T ei_sqrt(const T& x) { using std::sqrt; return sqrt(x); }
+template<typename T> inline T ei_exp (const T& x) { using std::exp; return exp(x); }
+template<typename T> inline T ei_log (const T& x) { using std::log; return log(x); }
+template<typename T> inline T ei_sin (const T& x) { using std::sin; return sin(x); }
+template<typename T> inline T ei_cos (const T& x) { using std::cos; return cos(x); }
+template<typename T> inline T ei_atan2(const T& x,const T& y) { using std::atan2; return atan2(x,y); }
+template<typename T> inline T ei_pow (const T& x,const T& y) { return numext::pow(x,y); }
template<typename T> inline T ei_random () { return internal::random<T>(); }
template<typename T> inline T ei_random (const T& x, const T& y) { return internal::random(x, y); }
diff --git a/Eigen/src/Eigen2Support/SVD.h b/Eigen/src/Eigen2Support/SVD.h
index 3d2eeb445..3d03d2288 100644
--- a/Eigen/src/Eigen2Support/SVD.h
+++ b/Eigen/src/Eigen2Support/SVD.h
@@ -1,5 +1,5 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
+// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
@@ -315,7 +315,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
e[p-2] = 0.0;
for (j = p-2; j >= k; --j)
{
- Scalar t(internal::hypot(m_sigma[j],f));
+ Scalar t(numext::hypot(m_sigma[j],f));
Scalar cs(m_sigma[j]/t);
Scalar sn(f/t);
m_sigma[j] = t;
@@ -344,7 +344,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
e[k-1] = 0.0;
for (j = k; j < p; ++j)
{
- Scalar t(internal::hypot(m_sigma[j],f));
+ Scalar t(numext::hypot(m_sigma[j],f));
Scalar cs( m_sigma[j]/t);
Scalar sn(f/t);
m_sigma[j] = t;
@@ -392,7 +392,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
for (j = k; j < p-1; ++j)
{
- Scalar t = internal::hypot(f,g);
+ Scalar t = numext::hypot(f,g);
Scalar cs = f/t;
Scalar sn = g/t;
if (j != k)
@@ -410,7 +410,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
m_matV(i,j) = t;
}
}
- t = internal::hypot(f,g);
+ t = numext::hypot(f,g);
cs = f/t;
sn = g/t;
m_sigma[j] = t;
@@ -512,8 +512,7 @@ template<typename MatrixType>
template<typename OtherDerived, typename ResultType>
bool SVD<MatrixType>::solve(const MatrixBase<OtherDerived> &b, ResultType* result) const
{
- const int rows = m_matU.rows();
- ei_assert(b.rows() == rows);
+ ei_assert(b.rows() == m_matU.rows());
Scalar maxVal = m_sigma.cwise().abs().maxCoeff();
for (int j=0; j<b.cols(); ++j)
diff --git a/Eigen/src/Eigenvalues/ComplexEigenSolver.h b/Eigen/src/Eigenvalues/ComplexEigenSolver.h
index c4b8a308c..af434bc9b 100644
--- a/Eigen/src/Eigenvalues/ComplexEigenSolver.h
+++ b/Eigen/src/Eigenvalues/ComplexEigenSolver.h
@@ -3,7 +3,7 @@
//
// Copyright (C) 2009 Claire Maurice
// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
+// Copyright (C) 2010,2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
//
// 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
@@ -220,6 +220,19 @@ template<typename _MatrixType> class ComplexEigenSolver
return m_schur.info();
}
+ /** \brief Sets the maximum number of iterations allowed. */
+ ComplexEigenSolver& setMaxIterations(Index maxIters)
+ {
+ m_schur.setMaxIterations(maxIters);
+ return *this;
+ }
+
+ /** \brief Returns the maximum number of iterations. */
+ Index getMaxIterations()
+ {
+ return m_schur.getMaxIterations();
+ }
+
protected:
EigenvectorType m_eivec;
EigenvalueType m_eivalues;
@@ -229,16 +242,17 @@ template<typename _MatrixType> class ComplexEigenSolver
EigenvectorType m_matX;
private:
- void doComputeEigenvectors(RealScalar matrixnorm);
+ void doComputeEigenvectors(const RealScalar& matrixnorm);
void sortEigenvalues(bool computeEigenvectors);
};
template<typename MatrixType>
-ComplexEigenSolver<MatrixType>& ComplexEigenSolver<MatrixType>::compute(const MatrixType& matrix, bool computeEigenvectors)
+ComplexEigenSolver<MatrixType>&
+ComplexEigenSolver<MatrixType>::compute(const MatrixType& matrix, bool computeEigenvectors)
{
// this code is inspired from Jampack
- assert(matrix.cols() == matrix.rows());
+ eigen_assert(matrix.cols() == matrix.rows());
// Do a complex Schur decomposition, A = U T U^*
// The eigenvalues are on the diagonal of T.
@@ -259,7 +273,7 @@ ComplexEigenSolver<MatrixType>& ComplexEigenSolver<MatrixType>::compute(const Ma
template<typename MatrixType>
-void ComplexEigenSolver<MatrixType>::doComputeEigenvectors(RealScalar matrixnorm)
+void ComplexEigenSolver<MatrixType>::doComputeEigenvectors(const RealScalar& matrixnorm)
{
const Index n = m_eivalues.size();
@@ -280,7 +294,7 @@ void ComplexEigenSolver<MatrixType>::doComputeEigenvectors(RealScalar matrixnorm
{
// If the i-th and k-th eigenvalue are equal, then z equals 0.
// Use a small value instead, to prevent division by zero.
- internal::real_ref(z) = NumTraits<RealScalar>::epsilon() * matrixnorm;
+ numext::real_ref(z) = NumTraits<RealScalar>::epsilon() * matrixnorm;
}
m_matX.coeffRef(i,k) = m_matX.coeff(i,k) / z;
}
diff --git a/Eigen/src/Eigenvalues/ComplexSchur.h b/Eigen/src/Eigenvalues/ComplexSchur.h
index 16a9a03d2..89e6cade3 100644
--- a/Eigen/src/Eigenvalues/ComplexSchur.h
+++ b/Eigen/src/Eigenvalues/ComplexSchur.h
@@ -3,7 +3,7 @@
//
// Copyright (C) 2009 Claire Maurice
// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
+// Copyright (C) 2010,2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
//
// 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
@@ -96,7 +96,8 @@ template<typename _MatrixType> class ComplexSchur
m_matU(size,size),
m_hess(size),
m_isInitialized(false),
- m_matUisUptodate(false)
+ m_matUisUptodate(false),
+ m_maxIters(-1)
{}
/** \brief Constructor; computes Schur decomposition of given matrix.
@@ -109,11 +110,12 @@ template<typename _MatrixType> class ComplexSchur
* \sa matrixT() and matrixU() for examples.
*/
ComplexSchur(const MatrixType& matrix, bool computeU = true)
- : m_matT(matrix.rows(),matrix.cols()),
- m_matU(matrix.rows(),matrix.cols()),
- m_hess(matrix.rows()),
- m_isInitialized(false),
- m_matUisUptodate(false)
+ : m_matT(matrix.rows(),matrix.cols()),
+ m_matU(matrix.rows(),matrix.cols()),
+ m_hess(matrix.rows()),
+ m_isInitialized(false),
+ m_matUisUptodate(false),
+ m_maxIters(-1)
{
compute(matrix, computeU);
}
@@ -166,6 +168,7 @@ template<typename _MatrixType> class ComplexSchur
*
* \param[in] matrix Square matrix whose Schur decomposition is to be computed.
* \param[in] computeU If true, both T and U are computed; if false, only T is computed.
+
* \returns Reference to \c *this
*
* The Schur decomposition is computed by first reducing the
@@ -180,8 +183,30 @@ template<typename _MatrixType> class ComplexSchur
*
* Example: \include ComplexSchur_compute.cpp
* Output: \verbinclude ComplexSchur_compute.out
+ *
+ * \sa compute(const MatrixType&, bool, Index)
*/
ComplexSchur& compute(const MatrixType& matrix, bool computeU = true);
+
+ /** \brief Compute Schur decomposition from a given Hessenberg matrix
+ * \param[in] matrixH Matrix in Hessenberg form H
+ * \param[in] matrixQ orthogonal matrix Q that transform a matrix A to H : A = Q H Q^T
+ * \param computeU Computes the matriX U of the Schur vectors
+ * \return Reference to \c *this
+ *
+ * This routine assumes that the matrix is already reduced in Hessenberg form matrixH
+ * using either the class HessenbergDecomposition or another mean.
+ * It computes the upper quasi-triangular matrix T of the Schur decomposition of H
+ * When computeU is true, this routine computes the matrix U such that
+ * A = U T U^T = (QZ) T (QZ)^T = Q H Q^T where A is the initial matrix
+ *
+ * NOTE Q is referenced if computeU is true; so, if the initial orthogonal matrix
+ * is not available, the user should give an identity matrix (Q.setIdentity())
+ *
+ * \sa compute(const MatrixType&, bool)
+ */
+ template<typename HessMatrixType, typename OrthMatrixType>
+ ComplexSchur& computeFromHessenberg(const HessMatrixType& matrixH, const OrthMatrixType& matrixQ, bool computeU=true);
/** \brief Reports whether previous computation was successful.
*
@@ -189,15 +214,33 @@ template<typename _MatrixType> class ComplexSchur
*/
ComputationInfo info() const
{
- eigen_assert(m_isInitialized && "RealSchur is not initialized.");
+ eigen_assert(m_isInitialized && "ComplexSchur is not initialized.");
return m_info;
}
- /** \brief Maximum number of iterations.
+ /** \brief Sets the maximum number of iterations allowed.
*
- * Maximum number of iterations allowed for an eigenvalue to converge.
+ * If not specified by the user, the maximum number of iterations is m_maxIterationsPerRow times the size
+ * of the matrix.
*/
- static const int m_maxIterations = 30;
+ ComplexSchur& setMaxIterations(Index maxIters)
+ {
+ m_maxIters = maxIters;
+ return *this;
+ }
+
+ /** \brief Returns the maximum number of iterations. */
+ Index getMaxIterations()
+ {
+ return m_maxIters;
+ }
+
+ /** \brief Maximum number of iterations per row.
+ *
+ * If not otherwise specified, the maximum number of iterations is this number times the size of the
+ * matrix. It is currently set to 30.
+ */
+ static const int m_maxIterationsPerRow = 30;
protected:
ComplexMatrixType m_matT, m_matU;
@@ -205,6 +248,7 @@ template<typename _MatrixType> class ComplexSchur
ComputationInfo m_info;
bool m_isInitialized;
bool m_matUisUptodate;
+ Index m_maxIters;
private:
bool subdiagonalEntryIsNeglegible(Index i);
@@ -219,8 +263,8 @@ template<typename _MatrixType> class ComplexSchur
template<typename MatrixType>
inline bool ComplexSchur<MatrixType>::subdiagonalEntryIsNeglegible(Index i)
{
- RealScalar d = internal::norm1(m_matT.coeff(i,i)) + internal::norm1(m_matT.coeff(i+1,i+1));
- RealScalar sd = internal::norm1(m_matT.coeff(i+1,i));
+ RealScalar d = numext::norm1(m_matT.coeff(i,i)) + numext::norm1(m_matT.coeff(i+1,i+1));
+ RealScalar sd = numext::norm1(m_matT.coeff(i+1,i));
if (internal::isMuchSmallerThan(sd, d, NumTraits<RealScalar>::epsilon()))
{
m_matT.coeffRef(i+1,i) = ComplexScalar(0);
@@ -234,10 +278,11 @@ inline bool ComplexSchur<MatrixType>::subdiagonalEntryIsNeglegible(Index i)
template<typename MatrixType>
typename ComplexSchur<MatrixType>::ComplexScalar ComplexSchur<MatrixType>::computeShift(Index iu, Index iter)
{
+ using std::abs;
if (iter == 10 || iter == 20)
{
// exceptional shift, taken from http://www.netlib.org/eispack/comqr.f
- return internal::abs(internal::real(m_matT.coeff(iu,iu-1))) + internal::abs(internal::real(m_matT.coeff(iu-1,iu-2)));
+ return abs(numext::real(m_matT.coeff(iu,iu-1))) + abs(numext::real(m_matT.coeff(iu-1,iu-2)));
}
// compute the shift as one of the eigenvalues of t, the 2x2
@@ -254,13 +299,13 @@ typename ComplexSchur<MatrixType>::ComplexScalar ComplexSchur<MatrixType>::compu
ComplexScalar eival1 = (trace + disc) / RealScalar(2);
ComplexScalar eival2 = (trace - disc) / RealScalar(2);
- if(internal::norm1(eival1) > internal::norm1(eival2))
+ if(numext::norm1(eival1) > numext::norm1(eival2))
eival2 = det / eival1;
else
eival1 = det / eival2;
// choose the eigenvalue closest to the bottom entry of the diagonal
- if(internal::norm1(eival1-t.coeff(1,1)) < internal::norm1(eival2-t.coeff(1,1)))
+ if(numext::norm1(eival1-t.coeff(1,1)) < numext::norm1(eival2-t.coeff(1,1)))
return normt * eival1;
else
return normt * eival2;
@@ -284,10 +329,20 @@ ComplexSchur<MatrixType>& ComplexSchur<MatrixType>::compute(const MatrixType& ma
}
internal::complex_schur_reduce_to_hessenberg<MatrixType, NumTraits<Scalar>::IsComplex>::run(*this, matrix, computeU);
- reduceToTriangularForm(computeU);
+ computeFromHessenberg(m_matT, m_matU, computeU);
return *this;
}
+template<typename MatrixType>
+template<typename HessMatrixType, typename OrthMatrixType>
+ComplexSchur<MatrixType>& ComplexSchur<MatrixType>::computeFromHessenberg(const HessMatrixType& matrixH, const OrthMatrixType& matrixQ, bool computeU)
+{
+ m_matT = matrixH;
+ if(computeU)
+ m_matU = matrixQ;
+ reduceToTriangularForm(computeU);
+ return *this;
+}
namespace internal {
/* Reduce given matrix to Hessenberg form */
@@ -309,7 +364,6 @@ struct complex_schur_reduce_to_hessenberg<MatrixType, false>
static void run(ComplexSchur<MatrixType>& _this, const MatrixType& matrix, bool computeU)
{
typedef typename ComplexSchur<MatrixType>::ComplexScalar ComplexScalar;
- typedef typename ComplexSchur<MatrixType>::ComplexMatrixType ComplexMatrixType;
// Note: m_hess is over RealScalar; m_matT and m_matU is over ComplexScalar
_this.m_hess.compute(matrix);
@@ -329,6 +383,10 @@ struct complex_schur_reduce_to_hessenberg<MatrixType, false>
template<typename MatrixType>
void ComplexSchur<MatrixType>::reduceToTriangularForm(bool computeU)
{
+ Index maxIters = m_maxIters;
+ if (maxIters == -1)
+ maxIters = m_maxIterationsPerRow * m_matT.rows();
+
// The matrix m_matT is divided in three parts.
// Rows 0,...,il-1 are decoupled from the rest because m_matT(il,il-1) is zero.
// Rows il,...,iu is the part we are working on (the active submatrix).
@@ -336,6 +394,7 @@ void ComplexSchur<MatrixType>::reduceToTriangularForm(bool computeU)
Index iu = m_matT.cols() - 1;
Index il;
Index iter = 0; // number of iterations we are working on the (iu,iu) element
+ Index totalIter = 0; // number of iterations for whole matrix
while(true)
{
@@ -350,9 +409,10 @@ void ComplexSchur<MatrixType>::reduceToTriangularForm(bool computeU)
// if iu is zero then we are done; the whole matrix is triangularized
if(iu==0) break;
- // if we spent too many iterations on the current element, we give up
+ // if we spent too many iterations, we give up
iter++;
- if(iter > m_maxIterations * m_matT.cols()) break;
+ totalIter++;
+ if(totalIter > maxIters) break;
// find il, the top row of the active submatrix
il = iu-1;
@@ -382,7 +442,7 @@ void ComplexSchur<MatrixType>::reduceToTriangularForm(bool computeU)
}
}
- if(iter <= m_maxIterations * m_matT.cols())
+ if(totalIter <= maxIters)
m_info = Success;
else
m_info = NoConvergence;
diff --git a/Eigen/src/Eigenvalues/ComplexSchur_MKL.h b/Eigen/src/Eigenvalues/ComplexSchur_MKL.h
index aa18e6963..91496ae5b 100644
--- a/Eigen/src/Eigenvalues/ComplexSchur_MKL.h
+++ b/Eigen/src/Eigenvalues/ComplexSchur_MKL.h
@@ -40,7 +40,7 @@ namespace Eigen {
/** \internal Specialization for the data types supported by MKL */
#define EIGEN_MKL_SCHUR_COMPLEX(EIGTYPE, MKLTYPE, MKLPREFIX, MKLPREFIX_U, EIGCOLROW, MKLCOLROW) \
-template<> inline\
+template<> inline \
ComplexSchur<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> >& \
ComplexSchur<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> >::compute(const Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW>& matrix, bool computeU) \
{ \
@@ -49,7 +49,7 @@ ComplexSchur<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> >::compute(const Matri
typedef MatrixType::RealScalar RealScalar; \
typedef std::complex<RealScalar> ComplexScalar; \
\
- assert(matrix.cols() == matrix.rows()); \
+ eigen_assert(matrix.cols() == matrix.rows()); \
\
m_matUisUptodate = false; \
if(matrix.cols() == 1) \
diff --git a/Eigen/src/Eigenvalues/EigenSolver.h b/Eigen/src/Eigenvalues/EigenSolver.h
index c16ff2b74..6e7150685 100644
--- a/Eigen/src/Eigenvalues/EigenSolver.h
+++ b/Eigen/src/Eigenvalues/EigenSolver.h
@@ -2,7 +2,7 @@
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
+// Copyright (C) 2010,2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
//
// 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
@@ -281,6 +281,19 @@ template<typename _MatrixType> class EigenSolver
return m_realSchur.info();
}
+ /** \brief Sets the maximum number of iterations allowed. */
+ EigenSolver& setMaxIterations(Index maxIters)
+ {
+ m_realSchur.setMaxIterations(maxIters);
+ return *this;
+ }
+
+ /** \brief Returns the maximum number of iterations. */
+ Index getMaxIterations()
+ {
+ return m_realSchur.getMaxIterations();
+ }
+
private:
void doComputeEigenvectors();
@@ -304,12 +317,12 @@ MatrixType EigenSolver<MatrixType>::pseudoEigenvalueMatrix() const
MatrixType matD = MatrixType::Zero(n,n);
for (Index i=0; i<n; ++i)
{
- if (internal::isMuchSmallerThan(internal::imag(m_eivalues.coeff(i)), internal::real(m_eivalues.coeff(i))))
- matD.coeffRef(i,i) = internal::real(m_eivalues.coeff(i));
+ if (internal::isMuchSmallerThan(numext::imag(m_eivalues.coeff(i)), numext::real(m_eivalues.coeff(i))))
+ matD.coeffRef(i,i) = numext::real(m_eivalues.coeff(i));
else
{
- matD.template block<2,2>(i,i) << internal::real(m_eivalues.coeff(i)), internal::imag(m_eivalues.coeff(i)),
- -internal::imag(m_eivalues.coeff(i)), internal::real(m_eivalues.coeff(i));
+ matD.template block<2,2>(i,i) << numext::real(m_eivalues.coeff(i)), numext::imag(m_eivalues.coeff(i)),
+ -numext::imag(m_eivalues.coeff(i)), numext::real(m_eivalues.coeff(i));
++i;
}
}
@@ -325,7 +338,7 @@ typename EigenSolver<MatrixType>::EigenvectorsType EigenSolver<MatrixType>::eige
EigenvectorsType matV(n,n);
for (Index j=0; j<n; ++j)
{
- if (internal::isMuchSmallerThan(internal::imag(m_eivalues.coeff(j)), internal::real(m_eivalues.coeff(j))) || j+1==n)
+ if (internal::isMuchSmallerThan(numext::imag(m_eivalues.coeff(j)), numext::real(m_eivalues.coeff(j))) || j+1==n)
{
// we have a real eigen value
matV.col(j) = m_eivec.col(j).template cast<ComplexScalar>();
@@ -348,12 +361,16 @@ typename EigenSolver<MatrixType>::EigenvectorsType EigenSolver<MatrixType>::eige
}
template<typename MatrixType>
-EigenSolver<MatrixType>& EigenSolver<MatrixType>::compute(const MatrixType& matrix, bool computeEigenvectors)
+EigenSolver<MatrixType>&
+EigenSolver<MatrixType>::compute(const MatrixType& matrix, bool computeEigenvectors)
{
- assert(matrix.cols() == matrix.rows());
+ using std::sqrt;
+ using std::abs;
+ eigen_assert(matrix.cols() == matrix.rows());
// Reduce to real Schur form.
m_realSchur.compute(matrix, computeEigenvectors);
+
if (m_realSchur.info() == Success)
{
m_matT = m_realSchur.matrixT();
@@ -373,7 +390,7 @@ EigenSolver<MatrixType>& EigenSolver<MatrixType>::compute(const MatrixType& matr
else
{
Scalar p = Scalar(0.5) * (m_matT.coeff(i, i) - m_matT.coeff(i+1, i+1));
- Scalar z = internal::sqrt(internal::abs(p * p + m_matT.coeff(i+1, i) * m_matT.coeff(i, i+1)));
+ Scalar z = sqrt(abs(p * p + m_matT.coeff(i+1, i) * m_matT.coeff(i, i+1)));
m_eivalues.coeffRef(i) = ComplexScalar(m_matT.coeff(i+1, i+1) + p, z);
m_eivalues.coeffRef(i+1) = ComplexScalar(m_matT.coeff(i+1, i+1) + p, -z);
i += 2;
@@ -393,10 +410,11 @@ EigenSolver<MatrixType>& EigenSolver<MatrixType>::compute(const MatrixType& matr
// Complex scalar division.
template<typename Scalar>
-std::complex<Scalar> cdiv(Scalar xr, Scalar xi, Scalar yr, Scalar yi)
+std::complex<Scalar> cdiv(const Scalar& xr, const Scalar& xi, const Scalar& yr, const Scalar& yi)
{
+ using std::abs;
Scalar r,d;
- if (internal::abs(yr) > internal::abs(yi))
+ if (abs(yr) > abs(yi))
{
r = yi/yr;
d = yr + r*yi;
@@ -414,6 +432,7 @@ std::complex<Scalar> cdiv(Scalar xr, Scalar xi, Scalar yr, Scalar yi)
template<typename MatrixType>
void EigenSolver<MatrixType>::doComputeEigenvectors()
{
+ using std::abs;
const Index size = m_eivec.cols();
const Scalar eps = NumTraits<Scalar>::epsilon();
@@ -469,14 +488,14 @@ void EigenSolver<MatrixType>::doComputeEigenvectors()
Scalar denom = (m_eivalues.coeff(i).real() - p) * (m_eivalues.coeff(i).real() - p) + m_eivalues.coeff(i).imag() * m_eivalues.coeff(i).imag();
Scalar t = (x * lastr - lastw * r) / denom;
m_matT.coeffRef(i,n) = t;
- if (internal::abs(x) > internal::abs(lastw))
+ if (abs(x) > abs(lastw))
m_matT.coeffRef(i+1,n) = (-r - w * t) / x;
else
m_matT.coeffRef(i+1,n) = (-lastr - y * t) / lastw;
}
// Overflow control
- Scalar t = internal::abs(m_matT.coeff(i,n));
+ Scalar t = abs(m_matT.coeff(i,n));
if ((eps * t) * t > Scalar(1))
m_matT.col(n).tail(size-i) /= t;
}
@@ -488,7 +507,7 @@ void EigenSolver<MatrixType>::doComputeEigenvectors()
Index l = n-1;
// Last vector component imaginary so matrix is triangular
- if (internal::abs(m_matT.coeff(n,n-1)) > internal::abs(m_matT.coeff(n-1,n)))
+ if (abs(m_matT.coeff(n,n-1)) > abs(m_matT.coeff(n-1,n)))
{
m_matT.coeffRef(n-1,n-1) = q / m_matT.coeff(n,n-1);
m_matT.coeffRef(n-1,n) = -(m_matT.coeff(n,n) - p) / m_matT.coeff(n,n-1);
@@ -496,8 +515,8 @@ void EigenSolver<MatrixType>::doComputeEigenvectors()
else
{
std::complex<Scalar> cc = cdiv<Scalar>(0.0,-m_matT.coeff(n-1,n),m_matT.coeff(n-1,n-1)-p,q);
- m_matT.coeffRef(n-1,n-1) = internal::real(cc);
- m_matT.coeffRef(n-1,n) = internal::imag(cc);
+ m_matT.coeffRef(n-1,n-1) = numext::real(cc);
+ m_matT.coeffRef(n-1,n) = numext::imag(cc);
}
m_matT.coeffRef(n,n-1) = 0.0;
m_matT.coeffRef(n,n) = 1.0;
@@ -519,8 +538,8 @@ void EigenSolver<MatrixType>::doComputeEigenvectors()
if (m_eivalues.coeff(i).imag() == RealScalar(0))
{
std::complex<Scalar> cc = cdiv(-ra,-sa,w,q);
- m_matT.coeffRef(i,n-1) = internal::real(cc);
- m_matT.coeffRef(i,n) = internal::imag(cc);
+ m_matT.coeffRef(i,n-1) = numext::real(cc);
+ m_matT.coeffRef(i,n) = numext::imag(cc);
}
else
{
@@ -530,12 +549,12 @@ void EigenSolver<MatrixType>::doComputeEigenvectors()
Scalar vr = (m_eivalues.coeff(i).real() - p) * (m_eivalues.coeff(i).real() - p) + m_eivalues.coeff(i).imag() * m_eivalues.coeff(i).imag() - q * q;
Scalar vi = (m_eivalues.coeff(i).real() - p) * Scalar(2) * q;
if ((vr == 0.0) && (vi == 0.0))
- vr = eps * norm * (internal::abs(w) + internal::abs(q) + internal::abs(x) + internal::abs(y) + internal::abs(lastw));
+ vr = eps * norm * (abs(w) + abs(q) + abs(x) + abs(y) + abs(lastw));
- std::complex<Scalar> cc = cdiv(x*lastra-lastw*ra+q*sa,x*lastsa-lastw*sa-q*ra,vr,vi);
- m_matT.coeffRef(i,n-1) = internal::real(cc);
- m_matT.coeffRef(i,n) = internal::imag(cc);
- if (internal::abs(x) > (internal::abs(lastw) + internal::abs(q)))
+ std::complex<Scalar> cc = cdiv(x*lastra-lastw*ra+q*sa,x*lastsa-lastw*sa-q*ra,vr,vi);
+ m_matT.coeffRef(i,n-1) = numext::real(cc);
+ m_matT.coeffRef(i,n) = numext::imag(cc);
+ if (abs(x) > (abs(lastw) + abs(q)))
{
m_matT.coeffRef(i+1,n-1) = (-ra - w * m_matT.coeff(i,n-1) + q * m_matT.coeff(i,n)) / x;
m_matT.coeffRef(i+1,n) = (-sa - w * m_matT.coeff(i,n) - q * m_matT.coeff(i,n-1)) / x;
@@ -543,14 +562,14 @@ void EigenSolver<MatrixType>::doComputeEigenvectors()
else
{
cc = cdiv(-lastra-y*m_matT.coeff(i,n-1),-lastsa-y*m_matT.coeff(i,n),lastw,q);
- m_matT.coeffRef(i+1,n-1) = internal::real(cc);
- m_matT.coeffRef(i+1,n) = internal::imag(cc);
+ m_matT.coeffRef(i+1,n-1) = numext::real(cc);
+ m_matT.coeffRef(i+1,n) = numext::imag(cc);
}
}
// Overflow control
using std::max;
- Scalar t = (max)(internal::abs(m_matT.coeff(i,n-1)),internal::abs(m_matT.coeff(i,n)));
+ Scalar t = (max)(abs(m_matT.coeff(i,n-1)),abs(m_matT.coeff(i,n)));
if ((eps * t) * t > Scalar(1))
m_matT.block(i, n-1, size-i, 2) /= t;
diff --git a/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h b/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h
new file mode 100644
index 000000000..dc240e13e
--- /dev/null
+++ b/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h
@@ -0,0 +1,341 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2010,2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
+//
+// 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_GENERALIZEDEIGENSOLVER_H
+#define EIGEN_GENERALIZEDEIGENSOLVER_H
+
+#include "./RealQZ.h"
+
+namespace Eigen {
+
+/** \eigenvalues_module \ingroup Eigenvalues_Module
+ *
+ *
+ * \class GeneralizedEigenSolver
+ *
+ * \brief Computes the generalized eigenvalues and eigenvectors of a pair of general matrices
+ *
+ * \tparam _MatrixType the type of the matrices of which we are computing the
+ * eigen-decomposition; this is expected to be an instantiation of the Matrix
+ * class template. Currently, only real matrices are supported.
+ *
+ * The generalized eigenvalues and eigenvectors of a matrix pair \f$ A \f$ and \f$ B \f$ are scalars
+ * \f$ \lambda \f$ and vectors \f$ v \f$ such that \f$ Av = \lambda Bv \f$. If
+ * \f$ D \f$ is a diagonal matrix with the eigenvalues on the diagonal, and
+ * \f$ V \f$ is a matrix with the eigenvectors as its columns, then \f$ A V =
+ * B V D \f$. The matrix \f$ V \f$ is almost always invertible, in which case we
+ * have \f$ A = B V D V^{-1} \f$. This is called the generalized eigen-decomposition.
+ *
+ * The generalized eigenvalues and eigenvectors of a matrix pair may be complex, even when the
+ * matrices are real. Moreover, the generalized eigenvalue might be infinite if the matrix B is
+ * singular. To workaround this difficulty, the eigenvalues are provided as a pair of complex \f$ \alpha \f$
+ * and real \f$ \beta \f$ such that: \f$ \lambda_i = \alpha_i / \beta_i \f$. If \f$ \beta_i \f$ is (nearly) zero,
+ * then one can consider the well defined left eigenvalue \f$ \mu = \beta_i / \alpha_i\f$ such that:
+ * \f$ \mu_i A v_i = B v_i \f$, or even \f$ \mu_i u_i^T A = u_i^T B \f$ where \f$ u_i \f$ is
+ * called the left eigenvector.
+ *
+ * Call the function compute() to compute the generalized eigenvalues and eigenvectors of
+ * a given matrix pair. Alternatively, you can use the
+ * GeneralizedEigenSolver(const MatrixType&, const MatrixType&, bool) constructor which computes the
+ * eigenvalues and eigenvectors at construction time. Once the eigenvalue and
+ * eigenvectors are computed, they can be retrieved with the eigenvalues() and
+ * eigenvectors() functions.
+ *
+ * Here is an usage example of this class:
+ * Example: \include GeneralizedEigenSolver.cpp
+ * Output: \verbinclude GeneralizedEigenSolver.out
+ *
+ * \sa MatrixBase::eigenvalues(), class ComplexEigenSolver, class SelfAdjointEigenSolver
+ */
+template<typename _MatrixType> class GeneralizedEigenSolver
+{
+ public:
+
+ /** \brief Synonym for the template parameter \p _MatrixType. */
+ typedef _MatrixType MatrixType;
+
+ enum {
+ RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+ ColsAtCompileTime = MatrixType::ColsAtCompileTime,
+ Options = MatrixType::Options,
+ MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
+ MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
+ };
+
+ /** \brief Scalar type for matrices of type #MatrixType. */
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename NumTraits<Scalar>::Real RealScalar;
+ typedef typename MatrixType::Index Index;
+
+ /** \brief Complex scalar type for #MatrixType.
+ *
+ * This is \c std::complex<Scalar> if #Scalar is real (e.g.,
+ * \c float or \c double) and just \c Scalar if #Scalar is
+ * complex.
+ */
+ typedef std::complex<RealScalar> ComplexScalar;
+
+ /** \brief Type for vector of real scalar values eigenvalues as returned by betas().
+ *
+ * This is a column vector with entries of type #Scalar.
+ * The length of the vector is the size of #MatrixType.
+ */
+ typedef Matrix<Scalar, ColsAtCompileTime, 1, Options & ~RowMajor, MaxColsAtCompileTime, 1> VectorType;
+
+ /** \brief Type for vector of complex scalar values eigenvalues as returned by betas().
+ *
+ * This is a column vector with entries of type #ComplexScalar.
+ * The length of the vector is the size of #MatrixType.
+ */
+ typedef Matrix<ComplexScalar, ColsAtCompileTime, 1, Options & ~RowMajor, MaxColsAtCompileTime, 1> ComplexVectorType;
+
+ /** \brief Expression type for the eigenvalues as returned by eigenvalues().
+ */
+ typedef CwiseBinaryOp<internal::scalar_quotient_op<ComplexScalar,Scalar>,ComplexVectorType,VectorType> EigenvalueType;
+
+ /** \brief Type for matrix of eigenvectors as returned by eigenvectors().
+ *
+ * This is a square matrix with entries of type #ComplexScalar.
+ * The size is the same as the size of #MatrixType.
+ */
+ typedef Matrix<ComplexScalar, RowsAtCompileTime, ColsAtCompileTime, Options, MaxRowsAtCompileTime, MaxColsAtCompileTime> EigenvectorsType;
+
+ /** \brief Default constructor.
+ *
+ * The default constructor is useful in cases in which the user intends to
+ * perform decompositions via EigenSolver::compute(const MatrixType&, bool).
+ *
+ * \sa compute() for an example.
+ */
+ GeneralizedEigenSolver() : m_eivec(), m_alphas(), m_betas(), m_isInitialized(false), m_realQZ(), m_matS(), m_tmp() {}
+
+ /** \brief Default constructor with memory preallocation
+ *
+ * Like the default constructor but with preallocation of the internal data
+ * according to the specified problem \a size.
+ * \sa GeneralizedEigenSolver()
+ */
+ GeneralizedEigenSolver(Index size)
+ : m_eivec(size, size),
+ m_alphas(size),
+ m_betas(size),
+ m_isInitialized(false),
+ m_eigenvectorsOk(false),
+ m_realQZ(size),
+ m_matS(size, size),
+ m_tmp(size)
+ {}
+
+ /** \brief Constructor; computes the generalized eigendecomposition of given matrix pair.
+ *
+ * \param[in] A Square matrix whose eigendecomposition is to be computed.
+ * \param[in] B Square matrix whose eigendecomposition is to be computed.
+ * \param[in] computeEigenvectors If true, both the eigenvectors and the
+ * eigenvalues are computed; if false, only the eigenvalues are computed.
+ *
+ * This constructor calls compute() to compute the generalized eigenvalues
+ * and eigenvectors.
+ *
+ * \sa compute()
+ */
+ GeneralizedEigenSolver(const MatrixType& A, const MatrixType& B, bool computeEigenvectors = true)
+ : m_eivec(A.rows(), A.cols()),
+ m_alphas(A.cols()),
+ m_betas(A.cols()),
+ m_isInitialized(false),
+ m_eigenvectorsOk(false),
+ m_realQZ(A.cols()),
+ m_matS(A.rows(), A.cols()),
+ m_tmp(A.cols())
+ {
+ compute(A, B, computeEigenvectors);
+ }
+
+ /* \brief Returns the computed generalized eigenvectors.
+ *
+ * \returns %Matrix whose columns are the (possibly complex) eigenvectors.
+ *
+ * \pre Either the constructor
+ * GeneralizedEigenSolver(const MatrixType&,const MatrixType&, bool) or the member function
+ * compute(const MatrixType&, const MatrixType& bool) has been called before, and
+ * \p computeEigenvectors was set to true (the default).
+ *
+ * Column \f$ k \f$ of the returned matrix is an eigenvector corresponding
+ * to eigenvalue number \f$ k \f$ as returned by eigenvalues(). The
+ * eigenvectors are normalized to have (Euclidean) norm equal to one. The
+ * matrix returned by this function is the matrix \f$ V \f$ in the
+ * generalized eigendecomposition \f$ A = B V D V^{-1} \f$, if it exists.
+ *
+ * \sa eigenvalues()
+ */
+// EigenvectorsType eigenvectors() const;
+
+ /** \brief Returns an expression of the computed generalized eigenvalues.
+ *
+ * \returns An expression of the column vector containing the eigenvalues.
+ *
+ * It is a shortcut for \code this->alphas().cwiseQuotient(this->betas()); \endcode
+ * Not that betas might contain zeros. It is therefore not recommended to use this function,
+ * but rather directly deal with the alphas and betas vectors.
+ *
+ * \pre Either the constructor
+ * GeneralizedEigenSolver(const MatrixType&,const MatrixType&,bool) or the member function
+ * compute(const MatrixType&,const MatrixType&,bool) has been called before.
+ *
+ * The eigenvalues are repeated according to their algebraic multiplicity,
+ * so there are as many eigenvalues as rows in the matrix. The eigenvalues
+ * are not sorted in any particular order.
+ *
+ * \sa alphas(), betas(), eigenvectors()
+ */
+ EigenvalueType eigenvalues() const
+ {
+ eigen_assert(m_isInitialized && "GeneralizedEigenSolver is not initialized.");
+ return EigenvalueType(m_alphas,m_betas);
+ }
+
+ /** \returns A const reference to the vectors containing the alpha values
+ *
+ * This vector permits to reconstruct the j-th eigenvalues as alphas(i)/betas(j).
+ *
+ * \sa betas(), eigenvalues() */
+ ComplexVectorType alphas() const
+ {
+ eigen_assert(m_isInitialized && "GeneralizedEigenSolver is not initialized.");
+ return m_alphas;
+ }
+
+ /** \returns A const reference to the vectors containing the beta values
+ *
+ * This vector permits to reconstruct the j-th eigenvalues as alphas(i)/betas(j).
+ *
+ * \sa alphas(), eigenvalues() */
+ VectorType betas() const
+ {
+ eigen_assert(m_isInitialized && "GeneralizedEigenSolver is not initialized.");
+ return m_betas;
+ }
+
+ /** \brief Computes generalized eigendecomposition of given matrix.
+ *
+ * \param[in] A Square matrix whose eigendecomposition is to be computed.
+ * \param[in] B Square matrix whose eigendecomposition is to be computed.
+ * \param[in] computeEigenvectors If true, both the eigenvectors and the
+ * eigenvalues are computed; if false, only the eigenvalues are
+ * computed.
+ * \returns Reference to \c *this
+ *
+ * This function computes the eigenvalues of the real matrix \p matrix.
+ * The eigenvalues() function can be used to retrieve them. If
+ * \p computeEigenvectors is true, then the eigenvectors are also computed
+ * and can be retrieved by calling eigenvectors().
+ *
+ * The matrix is first reduced to real generalized Schur form using the RealQZ
+ * class. The generalized Schur decomposition is then used to compute the eigenvalues
+ * and eigenvectors.
+ *
+ * The cost of the computation is dominated by the cost of the
+ * generalized Schur decomposition.
+ *
+ * This method reuses of the allocated data in the GeneralizedEigenSolver object.
+ */
+ GeneralizedEigenSolver& compute(const MatrixType& A, const MatrixType& B, bool computeEigenvectors = true);
+
+ ComputationInfo info() const
+ {
+ eigen_assert(m_isInitialized && "EigenSolver is not initialized.");
+ return m_realQZ.info();
+ }
+
+ /** Sets the maximal number of iterations allowed.
+ */
+ GeneralizedEigenSolver& setMaxIterations(Index maxIters)
+ {
+ m_realQZ.setMaxIterations(maxIters);
+ return *this;
+ }
+
+ protected:
+ MatrixType m_eivec;
+ ComplexVectorType m_alphas;
+ VectorType m_betas;
+ bool m_isInitialized;
+ bool m_eigenvectorsOk;
+ RealQZ<MatrixType> m_realQZ;
+ MatrixType m_matS;
+
+ typedef Matrix<Scalar, ColsAtCompileTime, 1, Options & ~RowMajor, MaxColsAtCompileTime, 1> ColumnVectorType;
+ ColumnVectorType m_tmp;
+};
+
+//template<typename MatrixType>
+//typename GeneralizedEigenSolver<MatrixType>::EigenvectorsType GeneralizedEigenSolver<MatrixType>::eigenvectors() const
+//{
+// eigen_assert(m_isInitialized && "EigenSolver is not initialized.");
+// eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
+// Index n = m_eivec.cols();
+// EigenvectorsType matV(n,n);
+// // TODO
+// return matV;
+//}
+
+template<typename MatrixType>
+GeneralizedEigenSolver<MatrixType>&
+GeneralizedEigenSolver<MatrixType>::compute(const MatrixType& A, const MatrixType& B, bool computeEigenvectors)
+{
+ using std::sqrt;
+ using std::abs;
+ eigen_assert(A.cols() == A.rows() && B.cols() == A.rows() && B.cols() == B.rows());
+
+ // Reduce to generalized real Schur form:
+ // A = Q S Z and B = Q T Z
+ m_realQZ.compute(A, B, computeEigenvectors);
+
+ if (m_realQZ.info() == Success)
+ {
+ m_matS = m_realQZ.matrixS();
+ if (computeEigenvectors)
+ m_eivec = m_realQZ.matrixZ().transpose();
+
+ // Compute eigenvalues from matS
+ m_alphas.resize(A.cols());
+ m_betas.resize(A.cols());
+ Index i = 0;
+ while (i < A.cols())
+ {
+ if (i == A.cols() - 1 || m_matS.coeff(i+1, i) == Scalar(0))
+ {
+ m_alphas.coeffRef(i) = m_matS.coeff(i, i);
+ m_betas.coeffRef(i) = m_realQZ.matrixT().coeff(i,i);
+ ++i;
+ }
+ else
+ {
+ Scalar p = Scalar(0.5) * (m_matS.coeff(i, i) - m_matS.coeff(i+1, i+1));
+ Scalar z = sqrt(abs(p * p + m_matS.coeff(i+1, i) * m_matS.coeff(i, i+1)));
+ m_alphas.coeffRef(i) = ComplexScalar(m_matS.coeff(i+1, i+1) + p, z);
+ m_alphas.coeffRef(i+1) = ComplexScalar(m_matS.coeff(i+1, i+1) + p, -z);
+
+ m_betas.coeffRef(i) = m_realQZ.matrixT().coeff(i,i);
+ m_betas.coeffRef(i+1) = m_realQZ.matrixT().coeff(i,i);
+ i += 2;
+ }
+ }
+ }
+
+ m_isInitialized = true;
+ m_eigenvectorsOk = false;//computeEigenvectors;
+
+ return *this;
+}
+
+} // end namespace Eigen
+
+#endif // EIGEN_GENERALIZEDEIGENSOLVER_H
diff --git a/Eigen/src/Eigenvalues/HessenbergDecomposition.h b/Eigen/src/Eigenvalues/HessenbergDecomposition.h
index b8378b08a..3db0c0106 100644
--- a/Eigen/src/Eigenvalues/HessenbergDecomposition.h
+++ b/Eigen/src/Eigenvalues/HessenbergDecomposition.h
@@ -82,7 +82,7 @@ template<typename _MatrixType> class HessenbergDecomposition
typedef Matrix<Scalar, SizeMinusOne, 1, Options & ~RowMajor, MaxSizeMinusOne, 1> CoeffVectorType;
/** \brief Return type of matrixQ() */
- typedef typename HouseholderSequence<MatrixType,CoeffVectorType>::ConjugateReturnType HouseholderSequenceType;
+ typedef HouseholderSequence<MatrixType,typename internal::remove_all<typename CoeffVectorType::ConjugateReturnType>::type> HouseholderSequenceType;
typedef internal::HessenbergDecompositionMatrixHReturnType<MatrixType> MatrixHReturnType;
@@ -291,7 +291,7 @@ template<typename _MatrixType> class HessenbergDecomposition
template<typename MatrixType>
void HessenbergDecomposition<MatrixType>::_compute(MatrixType& matA, CoeffVectorType& hCoeffs, VectorType& temp)
{
- assert(matA.rows()==matA.cols());
+ eigen_assert(matA.rows()==matA.cols());
Index n = matA.rows();
temp.resize(n);
for (Index i = 0; i<n-1; ++i)
@@ -313,7 +313,7 @@ void HessenbergDecomposition<MatrixType>::_compute(MatrixType& matA, CoeffVector
// A = A H'
matA.rightCols(remainingSize)
- .applyHouseholderOnTheRight(matA.col(i).tail(remainingSize-1).conjugate(), internal::conj(h), &temp.coeffRef(0));
+ .applyHouseholderOnTheRight(matA.col(i).tail(remainingSize-1).conjugate(), numext::conj(h), &temp.coeffRef(0));
}
}
diff --git a/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h b/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h
index 6af481c75..4fec8af0a 100644
--- a/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h
+++ b/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h
@@ -121,10 +121,11 @@ template<typename Derived>
inline typename MatrixBase<Derived>::RealScalar
MatrixBase<Derived>::operatorNorm() const
{
+ using std::sqrt;
typename Derived::PlainObject m_eval(derived());
// FIXME if it is really guaranteed that the eigenvalues are already sorted,
// then we don't need to compute a maxCoeff() here, comparing the 1st and last ones is enough.
- return internal::sqrt((m_eval*m_eval.adjoint())
+ return sqrt((m_eval*m_eval.adjoint())
.eval()
.template selfadjointView<Lower>()
.eigenvalues()
diff --git a/Eigen/src/Eigenvalues/RealQZ.h b/Eigen/src/Eigenvalues/RealQZ.h
new file mode 100644
index 000000000..5706eeebe
--- /dev/null
+++ b/Eigen/src/Eigenvalues/RealQZ.h
@@ -0,0 +1,624 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Alexey Korepanov <kaikaikai@yandex.ru>
+//
+// 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_REAL_QZ_H
+#define EIGEN_REAL_QZ_H
+
+namespace Eigen {
+
+ /** \eigenvalues_module \ingroup Eigenvalues_Module
+ *
+ *
+ * \class RealQZ
+ *
+ * \brief Performs a real QZ decomposition of a pair of square matrices
+ *
+ * \tparam _MatrixType the type of the matrix of which we are computing the
+ * real QZ decomposition; this is expected to be an instantiation of the
+ * Matrix class template.
+ *
+ * Given a real square matrices A and B, this class computes the real QZ
+ * decomposition: \f$ A = Q S Z \f$, \f$ B = Q T Z \f$ where Q and Z are
+ * real orthogonal matrixes, T is upper-triangular matrix, and S is upper
+ * quasi-triangular matrix. An orthogonal matrix is a matrix whose
+ * inverse is equal to its transpose, \f$ U^{-1} = U^T \f$. A quasi-triangular
+ * matrix is a block-triangular matrix whose diagonal consists of 1-by-1
+ * blocks and 2-by-2 blocks where further reduction is impossible due to
+ * complex eigenvalues.
+ *
+ * The eigenvalues of the pencil \f$ A - z B \f$ can be obtained from
+ * 1x1 and 2x2 blocks on the diagonals of S and T.
+ *
+ * Call the function compute() to compute the real QZ decomposition of a
+ * given pair of matrices. Alternatively, you can use the
+ * RealQZ(const MatrixType& B, const MatrixType& B, bool computeQZ)
+ * constructor which computes the real QZ decomposition at construction
+ * time. Once the decomposition is computed, you can use the matrixS(),
+ * matrixT(), matrixQ() and matrixZ() functions to retrieve the matrices
+ * S, T, Q and Z in the decomposition. If computeQZ==false, some time
+ * is saved by not computing matrices Q and Z.
+ *
+ * Example: \include RealQZ_compute.cpp
+ * Output: \include RealQZ_compute.out
+ *
+ * \note The implementation is based on the algorithm in "Matrix Computations"
+ * by Gene H. Golub and Charles F. Van Loan, and a paper "An algorithm for
+ * generalized eigenvalue problems" by C.B.Moler and G.W.Stewart.
+ *
+ * \sa class RealSchur, class ComplexSchur, class EigenSolver, class ComplexEigenSolver
+ */
+
+ template<typename _MatrixType> class RealQZ
+ {
+ public:
+ typedef _MatrixType MatrixType;
+ enum {
+ RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+ ColsAtCompileTime = MatrixType::ColsAtCompileTime,
+ Options = MatrixType::Options,
+ MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
+ MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
+ };
+ typedef typename MatrixType::Scalar Scalar;
+ typedef std::complex<typename NumTraits<Scalar>::Real> ComplexScalar;
+ typedef typename MatrixType::Index Index;
+
+ typedef Matrix<ComplexScalar, ColsAtCompileTime, 1, Options & ~RowMajor, MaxColsAtCompileTime, 1> EigenvalueType;
+ typedef Matrix<Scalar, ColsAtCompileTime, 1, Options & ~RowMajor, MaxColsAtCompileTime, 1> ColumnVectorType;
+
+ /** \brief Default constructor.
+ *
+ * \param [in] size Positive integer, size of the matrix whose QZ decomposition will be computed.
+ *
+ * The default constructor is useful in cases in which the user intends to
+ * perform decompositions via compute(). The \p size parameter is only
+ * used as a hint. It is not an error to give a wrong \p size, but it may
+ * impair performance.
+ *
+ * \sa compute() for an example.
+ */
+ RealQZ(Index size = RowsAtCompileTime==Dynamic ? 1 : RowsAtCompileTime) :
+ m_S(size, size),
+ m_T(size, size),
+ m_Q(size, size),
+ m_Z(size, size),
+ m_workspace(size*2),
+ m_maxIters(400),
+ m_isInitialized(false)
+ { }
+
+ /** \brief Constructor; computes real QZ decomposition of given matrices
+ *
+ * \param[in] A Matrix A.
+ * \param[in] B Matrix B.
+ * \param[in] computeQZ If false, A and Z are not computed.
+ *
+ * This constructor calls compute() to compute the QZ decomposition.
+ */
+ RealQZ(const MatrixType& A, const MatrixType& B, bool computeQZ = true) :
+ m_S(A.rows(),A.cols()),
+ m_T(A.rows(),A.cols()),
+ m_Q(A.rows(),A.cols()),
+ m_Z(A.rows(),A.cols()),
+ m_workspace(A.rows()*2),
+ m_maxIters(400),
+ m_isInitialized(false) {
+ compute(A, B, computeQZ);
+ }
+
+ /** \brief Returns matrix Q in the QZ decomposition.
+ *
+ * \returns A const reference to the matrix Q.
+ */
+ const MatrixType& matrixQ() const {
+ eigen_assert(m_isInitialized && "RealQZ 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 && "RealQZ 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 && "RealQZ 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 && "RealQZ is not initialized.");
+ return m_T;
+ }
+
+ /** \brief Computes QZ decomposition of given matrix.
+ *
+ * \param[in] A Matrix A.
+ * \param[in] B Matrix B.
+ * \param[in] computeQZ If false, A and Z are not computed.
+ * \returns Reference to \c *this
+ */
+ RealQZ& compute(const MatrixType& A, const MatrixType& B, bool computeQZ = true);
+
+ /** \brief Reports whether previous computation was successful.
+ *
+ * \returns \c Success if computation was succesful, \c NoConvergence otherwise.
+ */
+ ComputationInfo info() const
+ {
+ eigen_assert(m_isInitialized && "RealQZ is not initialized.");
+ return m_info;
+ }
+
+ /** \brief Returns number of performed QR-like iterations.
+ */
+ Index iterations() const
+ {
+ eigen_assert(m_isInitialized && "RealQZ is not initialized.");
+ return m_global_iter;
+ }
+
+ /** Sets the maximal number of iterations allowed to converge to one eigenvalue
+ * or decouple the problem.
+ */
+ RealQZ& setMaxIterations(Index maxIters)
+ {
+ m_maxIters = maxIters;
+ return *this;
+ }
+
+ private:
+
+ MatrixType m_S, m_T, m_Q, m_Z;
+ Matrix<Scalar,Dynamic,1> m_workspace;
+ ComputationInfo m_info;
+ Index m_maxIters;
+ bool m_isInitialized;
+ bool m_computeQZ;
+ Scalar m_normOfT, m_normOfS;
+ Index m_global_iter;
+
+ typedef Matrix<Scalar,3,1> Vector3s;
+ typedef Matrix<Scalar,2,1> Vector2s;
+ typedef Matrix<Scalar,2,2> Matrix2s;
+ typedef JacobiRotation<Scalar> JRs;
+
+ void hessenbergTriangular();
+ void computeNorms();
+ Index findSmallSubdiagEntry(Index iu);
+ Index findSmallDiagEntry(Index f, Index l);
+ void splitOffTwoRows(Index i);
+ void pushDownZero(Index z, Index f, Index l);
+ void step(Index f, Index l, Index iter);
+
+ }; // RealQZ
+
+ /** \internal Reduces S and T to upper Hessenberg - triangular form */
+ template<typename MatrixType>
+ void RealQZ<MatrixType>::hessenbergTriangular()
+ {
+
+ const Index dim = m_S.cols();
+
+ // perform QR decomposition of T, overwrite T with R, save Q
+ HouseholderQR<MatrixType> qrT(m_T);
+ m_T = qrT.matrixQR();
+ m_T.template triangularView<StrictlyLower>().setZero();
+ m_Q = qrT.householderQ();
+ // overwrite S with Q* S
+ m_S.applyOnTheLeft(m_Q.adjoint());
+ // init Z as Identity
+ if (m_computeQZ)
+ m_Z = MatrixType::Identity(dim,dim);
+ // reduce S to upper Hessenberg with Givens rotations
+ for (Index j=0; j<=dim-3; j++) {
+ for (Index i=dim-1; i>=j+2; i--) {
+ JRs G;
+ // kill S(i,j)
+ if(m_S.coeff(i,j) != 0)
+ {
+ 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.0);
+ m_S.rightCols(dim-j-1).applyOnTheLeft(i-1,i,G.adjoint());
+ m_T.rightCols(dim-i+1).applyOnTheLeft(i-1,i,G.adjoint());
+ }
+ // update Q
+ if (m_computeQZ)
+ m_Q.applyOnTheRight(i-1,i,G);
+ // kill T(i,i-1)
+ if(m_T.coeff(i,i-1)!=Scalar(0))
+ {
+ G.makeGivens(m_T.coeff(i,i), m_T.coeff(i,i-1), &m_T.coeffRef(i,i));
+ m_T.coeffRef(i,i-1) = Scalar(0.0);
+ m_S.applyOnTheRight(i,i-1,G);
+ m_T.topRows(i).applyOnTheRight(i,i-1,G);
+ }
+ // update Z
+ if (m_computeQZ)
+ m_Z.applyOnTheLeft(i,i-1,G.adjoint());
+ }
+ }
+ }
+
+ /** \internal Computes vector L1 norms of S and T when in Hessenberg-Triangular form already */
+ template<typename MatrixType>
+ inline void RealQZ<MatrixType>::computeNorms()
+ {
+ const Index size = m_S.cols();
+ m_normOfS = Scalar(0.0);
+ m_normOfT = Scalar(0.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) */
+ template<typename MatrixType>
+ inline typename MatrixType::Index RealQZ<MatrixType>::findSmallSubdiagEntry(Index iu)
+ {
+ using std::abs;
+ Index res = iu;
+ while (res > 0)
+ {
+ Scalar s = abs(m_S.coeff(res-1,res-1)) + abs(m_S.coeff(res,res));
+ if (s == Scalar(0.0))
+ s = m_normOfS;
+ if (abs(m_S.coeff(res,res-1)) < NumTraits<Scalar>::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) */
+ template<typename MatrixType>
+ inline typename MatrixType::Index RealQZ<MatrixType>::findSmallDiagEntry(Index f, Index l)
+ {
+ using std::abs;
+ Index res = l;
+ while (res >= f) {
+ if (abs(m_T.coeff(res,res)) <= NumTraits<Scalar>::epsilon() * m_normOfT)
+ break;
+ res--;
+ }
+ return res;
+ }
+
+ /** \internal decouple 2x2 diagonal block in rows i, i+1 if eigenvalues are real */
+ template<typename MatrixType>
+ inline void RealQZ<MatrixType>::splitOffTwoRows(Index i)
+ {
+ using std::abs;
+ using std::sqrt;
+ const Index dim=m_S.cols();
+ if (abs(m_S.coeff(i+1,i)==Scalar(0)))
+ return;
+ Index z = findSmallDiagEntry(i,i+1);
+ if (z==i-1)
+ {
+ // block of (S T^{-1})
+ Matrix2s STi = m_T.template block<2,2>(i,i).template triangularView<Upper>().
+ template solve<OnTheRight>(m_S.template block<2,2>(i,i));
+ Scalar p = Scalar(0.5)*(STi(0,0)-STi(1,1));
+ Scalar q = p*p + STi(1,0)*STi(0,1);
+ if (q>=0) {
+ Scalar z = sqrt(q);
+ // one QR-like iteration for ABi - lambda I
+ // is enough - when we know exact eigenvalue in advance,
+ // convergence is immediate
+ JRs G;
+ if (p>=0)
+ G.makeGivens(p + z, STi(1,0));
+ else
+ G.makeGivens(p - z, STi(1,0));
+ m_S.rightCols(dim-i).applyOnTheLeft(i,i+1,G.adjoint());
+ m_T.rightCols(dim-i).applyOnTheLeft(i,i+1,G.adjoint());
+ // update Q
+ if (m_computeQZ)
+ m_Q.applyOnTheRight(i,i+1,G);
+
+ G.makeGivens(m_T.coeff(i+1,i+1), m_T.coeff(i+1,i));
+ m_S.topRows(i+2).applyOnTheRight(i+1,i,G);
+ m_T.topRows(i+2).applyOnTheRight(i+1,i,G);
+ // update Z
+ if (m_computeQZ)
+ m_Z.applyOnTheLeft(i+1,i,G.adjoint());
+
+ m_S.coeffRef(i+1,i) = Scalar(0.0);
+ m_T.coeffRef(i+1,i) = Scalar(0.0);
+ }
+ }
+ else
+ {
+ pushDownZero(z,i,i+1);
+ }
+ }
+
+ /** \internal use zero in T(z,z) to zero S(l,l-1), working in block f..l */
+ template<typename MatrixType>
+ inline void RealQZ<MatrixType>::pushDownZero(Index z, Index f, Index l)
+ {
+ JRs G;
+ const Index dim = m_S.cols();
+ for (Index zz=z; zz<l; zz++)
+ {
+ // push 0 down
+ Index firstColS = zz>f ? (zz-1) : zz;
+ G.makeGivens(m_T.coeff(zz, zz+1), m_T.coeff(zz+1, zz+1));
+ m_S.rightCols(dim-firstColS).applyOnTheLeft(zz,zz+1,G.adjoint());
+ m_T.rightCols(dim-zz).applyOnTheLeft(zz,zz+1,G.adjoint());
+ m_T.coeffRef(zz+1,zz+1) = Scalar(0.0);
+ // update Q
+ if (m_computeQZ)
+ m_Q.applyOnTheRight(zz,zz+1,G);
+ // kill S(zz+1, zz-1)
+ if (zz>f)
+ {
+ G.makeGivens(m_S.coeff(zz+1, zz), m_S.coeff(zz+1,zz-1));
+ m_S.topRows(zz+2).applyOnTheRight(zz, zz-1,G);
+ m_T.topRows(zz+1).applyOnTheRight(zz, zz-1,G);
+ m_S.coeffRef(zz+1,zz-1) = Scalar(0.0);
+ // update Z
+ if (m_computeQZ)
+ m_Z.applyOnTheLeft(zz,zz-1,G.adjoint());
+ }
+ }
+ // finally kill S(l,l-1)
+ G.makeGivens(m_S.coeff(l,l), m_S.coeff(l,l-1));
+ m_S.applyOnTheRight(l,l-1,G);
+ m_T.applyOnTheRight(l,l-1,G);
+ m_S.coeffRef(l,l-1)=Scalar(0.0);
+ // update Z
+ if (m_computeQZ)
+ m_Z.applyOnTheLeft(l,l-1,G.adjoint());
+ }
+
+ /** \internal QR-like iterative step for block f..l */
+ template<typename MatrixType>
+ inline void RealQZ<MatrixType>::step(Index f, Index l, Index iter)
+ {
+ using std::abs;
+ const Index dim = m_S.cols();
+
+ // x, y, z
+ Scalar x, y, z;
+ if (iter==10)
+ {
+ // Wilkinson ad hoc shift
+ const Scalar
+ a11=m_S.coeff(f+0,f+0), a12=m_S.coeff(f+0,f+1),
+ a21=m_S.coeff(f+1,f+0), a22=m_S.coeff(f+1,f+1), a32=m_S.coeff(f+2,f+1),
+ b12=m_T.coeff(f+0,f+1),
+ b11i=Scalar(1.0)/m_T.coeff(f+0,f+0),
+ b22i=Scalar(1.0)/m_T.coeff(f+1,f+1),
+ a87=m_S.coeff(l-1,l-2),
+ a98=m_S.coeff(l-0,l-1),
+ b77i=Scalar(1.0)/m_T.coeff(l-2,l-2),
+ b88i=Scalar(1.0)/m_T.coeff(l-1,l-1);
+ Scalar ss = abs(a87*b77i) + abs(a98*b88i),
+ lpl = Scalar(1.5)*ss,
+ ll = ss*ss;
+ x = ll + a11*a11*b11i*b11i - lpl*a11*b11i + a12*a21*b11i*b22i
+ - a11*a21*b12*b11i*b11i*b22i;
+ y = a11*a21*b11i*b11i - lpl*a21*b11i + a21*a22*b11i*b22i
+ - a21*a21*b12*b11i*b11i*b22i;
+ z = a21*a32*b11i*b22i;
+ }
+ else if (iter==16)
+ {
+ // another exceptional shift
+ x = m_S.coeff(f,f)/m_T.coeff(f,f)-m_S.coeff(l,l)/m_T.coeff(l,l) + m_S.coeff(l,l-1)*m_T.coeff(l-1,l) /
+ (m_T.coeff(l-1,l-1)*m_T.coeff(l,l));
+ y = m_S.coeff(f+1,f)/m_T.coeff(f,f);
+ z = 0;
+ }
+ else if (iter>23 && !(iter%8))
+ {
+ // extremely exceptional shift
+ x = internal::random<Scalar>(-1.0,1.0);
+ y = internal::random<Scalar>(-1.0,1.0);
+ z = internal::random<Scalar>(-1.0,1.0);
+ }
+ else
+ {
+ // Compute the shifts: (x,y,z,0...) = (AB^-1 - l1 I) (AB^-1 - l2 I) e1
+ // where l1 and l2 are the eigenvalues of the 2x2 matrix C = U V^-1 where
+ // U and V are 2x2 bottom right sub matrices of A and B. Thus:
+ // = AB^-1AB^-1 + l1 l2 I - (l1+l2)(AB^-1)
+ // = AB^-1AB^-1 + det(M) - tr(M)(AB^-1)
+ // Since we are only interested in having x, y, z with a correct ratio, we have:
+ const Scalar
+ a11 = m_S.coeff(f,f), a12 = m_S.coeff(f,f+1),
+ a21 = m_S.coeff(f+1,f), a22 = m_S.coeff(f+1,f+1),
+ a32 = m_S.coeff(f+2,f+1),
+
+ a88 = m_S.coeff(l-1,l-1), a89 = m_S.coeff(l-1,l),
+ a98 = m_S.coeff(l,l-1), a99 = m_S.coeff(l,l),
+
+ b11 = m_T.coeff(f,f), b12 = m_T.coeff(f,f+1),
+ b22 = m_T.coeff(f+1,f+1),
+
+ b88 = m_T.coeff(l-1,l-1), b89 = m_T.coeff(l-1,l),
+ b99 = m_T.coeff(l,l);
+
+ x = ( (a88/b88 - a11/b11)*(a99/b99 - a11/b11) - (a89/b99)*(a98/b88) + (a98/b88)*(b89/b99)*(a11/b11) ) * (b11/a21)
+ + a12/b22 - (a11/b11)*(b12/b22);
+ y = (a22/b22-a11/b11) - (a21/b11)*(b12/b22) - (a88/b88-a11/b11) - (a99/b99-a11/b11) + (a98/b88)*(b89/b99);
+ z = a32/b22;
+ }
+
+ JRs G;
+
+ for (Index k=f; k<=l-2; k++)
+ {
+ // variables for Householder reflections
+ Vector2s essential2;
+ Scalar tau, beta;
+
+ Vector3s hr(x,y,z);
+
+ // Q_k to annihilate S(k+1,k-1) and S(k+2,k-1)
+ hr.makeHouseholderInPlace(tau, beta);
+ essential2 = hr.template bottomRows<2>();
+ Index fc=(std::max)(k-1,Index(0)); // first col to update
+ m_S.template middleRows<3>(k).rightCols(dim-fc).applyHouseholderOnTheLeft(essential2, tau, m_workspace.data());
+ m_T.template middleRows<3>(k).rightCols(dim-fc).applyHouseholderOnTheLeft(essential2, tau, m_workspace.data());
+ if (m_computeQZ)
+ m_Q.template middleCols<3>(k).applyHouseholderOnTheRight(essential2, tau, m_workspace.data());
+ if (k>f)
+ m_S.coeffRef(k+2,k-1) = m_S.coeffRef(k+1,k-1) = Scalar(0.0);
+
+ // Z_{k1} to annihilate T(k+2,k+1) and T(k+2,k)
+ hr << m_T.coeff(k+2,k+2),m_T.coeff(k+2,k),m_T.coeff(k+2,k+1);
+ hr.makeHouseholderInPlace(tau, beta);
+ essential2 = hr.template bottomRows<2>();
+ {
+ Index lr = (std::min)(k+4,dim); // last row to update
+ Map<Matrix<Scalar,Dynamic,1> > tmp(m_workspace.data(),lr);
+ // S
+ tmp = m_S.template middleCols<2>(k).topRows(lr) * essential2;
+ tmp += m_S.col(k+2).head(lr);
+ m_S.col(k+2).head(lr) -= tau*tmp;
+ m_S.template middleCols<2>(k).topRows(lr) -= (tau*tmp) * essential2.adjoint();
+ // T
+ tmp = m_T.template middleCols<2>(k).topRows(lr) * essential2;
+ tmp += m_T.col(k+2).head(lr);
+ m_T.col(k+2).head(lr) -= tau*tmp;
+ m_T.template middleCols<2>(k).topRows(lr) -= (tau*tmp) * essential2.adjoint();
+ }
+ if (m_computeQZ)
+ {
+ // Z
+ Map<Matrix<Scalar,1,Dynamic> > tmp(m_workspace.data(),dim);
+ tmp = essential2.adjoint()*(m_Z.template middleRows<2>(k));
+ tmp += m_Z.row(k+2);
+ m_Z.row(k+2) -= tau*tmp;
+ m_Z.template middleRows<2>(k) -= essential2 * (tau*tmp);
+ }
+ m_T.coeffRef(k+2,k) = m_T.coeffRef(k+2,k+1) = Scalar(0.0);
+
+ // Z_{k2} to annihilate T(k+1,k)
+ G.makeGivens(m_T.coeff(k+1,k+1), m_T.coeff(k+1,k));
+ m_S.applyOnTheRight(k+1,k,G);
+ m_T.applyOnTheRight(k+1,k,G);
+ // update Z
+ if (m_computeQZ)
+ m_Z.applyOnTheLeft(k+1,k,G.adjoint());
+ m_T.coeffRef(k+1,k) = Scalar(0.0);
+
+ // update x,y,z
+ x = m_S.coeff(k+1,k);
+ y = m_S.coeff(k+2,k);
+ if (k < l-2)
+ z = m_S.coeff(k+3,k);
+ } // loop over k
+
+ // Q_{n-1} to annihilate y = S(l,l-2)
+ G.makeGivens(x,y);
+ m_S.applyOnTheLeft(l-1,l,G.adjoint());
+ m_T.applyOnTheLeft(l-1,l,G.adjoint());
+ if (m_computeQZ)
+ m_Q.applyOnTheRight(l-1,l,G);
+ m_S.coeffRef(l,l-2) = Scalar(0.0);
+
+ // Z_{n-1} to annihilate T(l,l-1)
+ G.makeGivens(m_T.coeff(l,l),m_T.coeff(l,l-1));
+ m_S.applyOnTheRight(l,l-1,G);
+ m_T.applyOnTheRight(l,l-1,G);
+ if (m_computeQZ)
+ m_Z.applyOnTheLeft(l,l-1,G.adjoint());
+ m_T.coeffRef(l,l-1) = Scalar(0.0);
+ }
+
+
+ template<typename MatrixType>
+ RealQZ<MatrixType>& RealQZ<MatrixType>::compute(const MatrixType& A_in, const MatrixType& B_in, bool computeQZ)
+ {
+
+ const Index dim = A_in.cols();
+
+ eigen_assert (A_in.rows()==dim && A_in.cols()==dim
+ && B_in.rows()==dim && B_in.cols()==dim
+ && "Need square matrices of the same dimension");
+
+ m_isInitialized = true;
+ m_computeQZ = computeQZ;
+ m_S = A_in; m_T = B_in;
+ m_workspace.resize(dim*2);
+ m_global_iter = 0;
+
+ // entrance point: hessenberg triangular decomposition
+ hessenbergTriangular();
+ // compute L1 vector norms of T, S into m_normOfS, m_normOfT
+ computeNorms();
+
+ Index l = dim-1,
+ f,
+ local_iter = 0;
+
+ while (l>0 && local_iter<m_maxIters)
+ {
+ f = findSmallSubdiagEntry(l);
+ // now rows and columns f..l (including) decouple from the rest of the problem
+ if (f>0) m_S.coeffRef(f,f-1) = Scalar(0.0);
+ if (f == l) // One root found
+ {
+ l--;
+ local_iter = 0;
+ }
+ else if (f == l-1) // Two roots found
+ {
+ splitOffTwoRows(f);
+ l -= 2;
+ local_iter = 0;
+ }
+ else // No convergence yet
+ {
+ // if there's zero on diagonal of T, we can isolate an eigenvalue with Givens rotations
+ Index z = findSmallDiagEntry(f,l);
+ if (z>=f)
+ {
+ // zero found
+ pushDownZero(z,f,l);
+ }
+ else
+ {
+ // We are sure now that S.block(f,f, l-f+1,l-f+1) is underuced upper-Hessenberg
+ // and T.block(f,f, l-f+1,l-f+1) is invertible uper-triangular, which allows to
+ // apply a QR-like iteration to rows and columns f..l.
+ step(f,l, local_iter);
+ local_iter++;
+ m_global_iter++;
+ }
+ }
+ }
+ // check if we converged before reaching iterations limit
+ m_info = (local_iter<m_maxIters) ? Success : NoConvergence;
+ return *this;
+ } // end compute
+
+} // end namespace Eigen
+
+#endif //EIGEN_REAL_QZ
diff --git a/Eigen/src/Eigenvalues/RealSchur.h b/Eigen/src/Eigenvalues/RealSchur.h
index 781692ecc..64d136341 100644
--- a/Eigen/src/Eigenvalues/RealSchur.h
+++ b/Eigen/src/Eigenvalues/RealSchur.h
@@ -2,7 +2,7 @@
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
+// Copyright (C) 2010,2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
//
// 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
@@ -86,7 +86,8 @@ template<typename _MatrixType> class RealSchur
m_workspaceVector(size),
m_hess(size),
m_isInitialized(false),
- m_matUisUptodate(false)
+ m_matUisUptodate(false),
+ m_maxIters(-1)
{ }
/** \brief Constructor; computes real Schur decomposition of given matrix.
@@ -105,7 +106,8 @@ template<typename _MatrixType> class RealSchur
m_workspaceVector(matrix.rows()),
m_hess(matrix.rows()),
m_isInitialized(false),
- m_matUisUptodate(false)
+ m_matUisUptodate(false),
+ m_maxIters(-1)
{
compute(matrix, computeU);
}
@@ -160,9 +162,30 @@ template<typename _MatrixType> class RealSchur
*
* Example: \include RealSchur_compute.cpp
* Output: \verbinclude RealSchur_compute.out
+ *
+ * \sa compute(const MatrixType&, bool, Index)
*/
RealSchur& compute(const MatrixType& matrix, bool computeU = true);
+ /** \brief Computes Schur decomposition of a Hessenberg matrix H = Z T Z^T
+ * \param[in] matrixH Matrix in Hessenberg form H
+ * \param[in] matrixQ orthogonal matrix Q that transform a matrix A to H : A = Q H Q^T
+ * \param computeU Computes the matriX U of the Schur vectors
+ * \return Reference to \c *this
+ *
+ * This routine assumes that the matrix is already reduced in Hessenberg form matrixH
+ * using either the class HessenbergDecomposition or another mean.
+ * It computes the upper quasi-triangular matrix T of the Schur decomposition of H
+ * When computeU is true, this routine computes the matrix U such that
+ * A = U T U^T = (QZ) T (QZ)^T = Q H Q^T where A is the initial matrix
+ *
+ * NOTE Q is referenced if computeU is true; so, if the initial orthogonal matrix
+ * is not available, the user should give an identity matrix (Q.setIdentity())
+ *
+ * \sa compute(const MatrixType&, bool)
+ */
+ template<typename HessMatrixType, typename OrthMatrixType>
+ RealSchur& computeFromHessenberg(const HessMatrixType& matrixH, const OrthMatrixType& matrixQ, bool computeU);
/** \brief Reports whether previous computation was successful.
*
* \returns \c Success if computation was succesful, \c NoConvergence otherwise.
@@ -173,11 +196,29 @@ template<typename _MatrixType> class RealSchur
return m_info;
}
- /** \brief Maximum number of iterations.
+ /** \brief Sets the maximum number of iterations allowed.
+ *
+ * If not specified by the user, the maximum number of iterations is m_maxIterationsPerRow times the size
+ * of the matrix.
+ */
+ RealSchur& setMaxIterations(Index maxIters)
+ {
+ m_maxIters = maxIters;
+ return *this;
+ }
+
+ /** \brief Returns the maximum number of iterations. */
+ Index getMaxIterations()
+ {
+ return m_maxIters;
+ }
+
+ /** \brief Maximum number of iterations per row.
*
- * Maximum number of iterations allowed for an eigenvalue to converge.
+ * If not otherwise specified, the maximum number of iterations is this number times the size of the
+ * matrix. It is currently set to 40.
*/
- static const int m_maxIterations = 40;
+ static const int m_maxIterationsPerRow = 40;
private:
@@ -188,12 +229,13 @@ template<typename _MatrixType> class RealSchur
ComputationInfo m_info;
bool m_isInitialized;
bool m_matUisUptodate;
+ Index m_maxIters;
typedef Matrix<Scalar,3,1> Vector3s;
Scalar computeNormOfT();
- Index findSmallSubdiagEntry(Index iu, Scalar norm);
- void splitOffTwoRows(Index iu, bool computeU, Scalar exshift);
+ Index findSmallSubdiagEntry(Index iu, const Scalar& norm);
+ void splitOffTwoRows(Index iu, bool computeU, const Scalar& exshift);
void computeShift(Index iu, Index iter, Scalar& exshift, Vector3s& shiftInfo);
void initFrancisQRStep(Index il, Index iu, const Vector3s& shiftInfo, Index& im, Vector3s& firstHouseholderVector);
void performFrancisQRStep(Index il, Index im, Index iu, bool computeU, const Vector3s& firstHouseholderVector, Scalar* workspace);
@@ -203,15 +245,30 @@ template<typename _MatrixType> class RealSchur
template<typename MatrixType>
RealSchur<MatrixType>& RealSchur<MatrixType>::compute(const MatrixType& matrix, bool computeU)
{
- assert(matrix.cols() == matrix.rows());
+ eigen_assert(matrix.cols() == matrix.rows());
+ Index maxIters = m_maxIters;
+ if (maxIters == -1)
+ maxIters = m_maxIterationsPerRow * matrix.rows();
// Step 1. Reduce to Hessenberg form
m_hess.compute(matrix);
- m_matT = m_hess.matrixH();
- if (computeU)
- m_matU = m_hess.matrixQ();
// Step 2. Reduce to real Schur form
+ computeFromHessenberg(m_hess.matrixH(), m_hess.matrixQ(), computeU);
+
+ return *this;
+}
+template<typename MatrixType>
+template<typename HessMatrixType, typename OrthMatrixType>
+RealSchur<MatrixType>& RealSchur<MatrixType>::computeFromHessenberg(const HessMatrixType& matrixH, const OrthMatrixType& matrixQ, bool computeU)
+{
+ m_matT = matrixH;
+ if(computeU)
+ m_matU = matrixQ;
+
+ Index maxIters = m_maxIters;
+ if (maxIters == -1)
+ maxIters = m_maxIterationsPerRow * matrixH.rows();
m_workspaceVector.resize(m_matT.cols());
Scalar* workspace = &m_workspaceVector.coeffRef(0);
@@ -220,8 +277,9 @@ RealSchur<MatrixType>& RealSchur<MatrixType>::compute(const MatrixType& matrix,
// Rows il,...,iu is the part we are working on (the active window).
// Rows iu+1,...,end are already brought in triangular form.
Index iu = m_matT.cols() - 1;
- Index iter = 0; // iteration count
- Scalar exshift(0); // sum of exceptional shifts
+ Index iter = 0; // iteration count for current eigenvalue
+ Index totalIter = 0; // iteration count for whole matrix
+ Scalar exshift(0); // sum of exceptional shifts
Scalar norm = computeNormOfT();
if(norm!=0)
@@ -251,14 +309,15 @@ RealSchur<MatrixType>& RealSchur<MatrixType>::compute(const MatrixType& matrix,
Vector3s firstHouseholderVector(0,0,0), shiftInfo;
computeShift(iu, iter, exshift, shiftInfo);
iter = iter + 1;
- if (iter > m_maxIterations * m_matT.cols()) break;
+ totalIter = totalIter + 1;
+ if (totalIter > maxIters) break;
Index im;
initFrancisQRStep(il, iu, shiftInfo, im, firstHouseholderVector);
performFrancisQRStep(il, im, iu, computeU, firstHouseholderVector, workspace);
}
}
}
- if(iter <= m_maxIterations * m_matT.cols())
+ if(totalIter <= maxIters)
m_info = Success;
else
m_info = NoConvergence;
@@ -278,21 +337,22 @@ inline typename MatrixType::Scalar RealSchur<MatrixType>::computeNormOfT()
// + m_matT.bottomLeftCorner(size-1,size-1).diagonal().cwiseAbs().sum();
Scalar norm(0);
for (Index j = 0; j < size; ++j)
- norm += m_matT.row(j).segment((std::max)(j-1,Index(0)), size-(std::max)(j-1,Index(0))).cwiseAbs().sum();
+ norm += m_matT.col(j).segment(0, (std::min)(size,j+2)).cwiseAbs().sum();
return norm;
}
/** \internal Look for single small sub-diagonal element and returns its index */
template<typename MatrixType>
-inline typename MatrixType::Index RealSchur<MatrixType>::findSmallSubdiagEntry(Index iu, Scalar norm)
+inline typename MatrixType::Index RealSchur<MatrixType>::findSmallSubdiagEntry(Index iu, const Scalar& norm)
{
+ using std::abs;
Index res = iu;
while (res > 0)
{
- Scalar s = internal::abs(m_matT.coeff(res-1,res-1)) + internal::abs(m_matT.coeff(res,res));
+ Scalar s = abs(m_matT.coeff(res-1,res-1)) + abs(m_matT.coeff(res,res));
if (s == 0.0)
s = norm;
- if (internal::abs(m_matT.coeff(res,res-1)) < NumTraits<Scalar>::epsilon() * s)
+ if (abs(m_matT.coeff(res,res-1)) < NumTraits<Scalar>::epsilon() * s)
break;
res--;
}
@@ -301,8 +361,10 @@ inline typename MatrixType::Index RealSchur<MatrixType>::findSmallSubdiagEntry(I
/** \internal Update T given that rows iu-1 and iu decouple from the rest. */
template<typename MatrixType>
-inline void RealSchur<MatrixType>::splitOffTwoRows(Index iu, bool computeU, Scalar exshift)
+inline void RealSchur<MatrixType>::splitOffTwoRows(Index iu, bool computeU, const Scalar& exshift)
{
+ using std::sqrt;
+ using std::abs;
const Index size = m_matT.cols();
// The eigenvalues of the 2x2 matrix [a b; c d] are
@@ -314,7 +376,7 @@ inline void RealSchur<MatrixType>::splitOffTwoRows(Index iu, bool computeU, Scal
if (q >= Scalar(0)) // Two real eigenvalues
{
- Scalar z = internal::sqrt(internal::abs(q));
+ Scalar z = sqrt(abs(q));
JacobiRotation<Scalar> rot;
if (p >= Scalar(0))
rot.makeGivens(p + z, m_matT.coeff(iu, iu-1));
@@ -336,6 +398,8 @@ inline void RealSchur<MatrixType>::splitOffTwoRows(Index iu, bool computeU, Scal
template<typename MatrixType>
inline void RealSchur<MatrixType>::computeShift(Index iu, Index iter, Scalar& exshift, Vector3s& shiftInfo)
{
+ using std::sqrt;
+ using std::abs;
shiftInfo.coeffRef(0) = m_matT.coeff(iu,iu);
shiftInfo.coeffRef(1) = m_matT.coeff(iu-1,iu-1);
shiftInfo.coeffRef(2) = m_matT.coeff(iu,iu-1) * m_matT.coeff(iu-1,iu);
@@ -346,7 +410,7 @@ inline void RealSchur<MatrixType>::computeShift(Index iu, Index iter, Scalar& ex
exshift += shiftInfo.coeff(0);
for (Index i = 0; i <= iu; ++i)
m_matT.coeffRef(i,i) -= shiftInfo.coeff(0);
- Scalar s = internal::abs(m_matT.coeff(iu,iu-1)) + internal::abs(m_matT.coeff(iu-1,iu-2));
+ Scalar s = abs(m_matT.coeff(iu,iu-1)) + abs(m_matT.coeff(iu-1,iu-2));
shiftInfo.coeffRef(0) = Scalar(0.75) * s;
shiftInfo.coeffRef(1) = Scalar(0.75) * s;
shiftInfo.coeffRef(2) = Scalar(-0.4375) * s * s;
@@ -359,7 +423,7 @@ inline void RealSchur<MatrixType>::computeShift(Index iu, Index iter, Scalar& ex
s = s * s + shiftInfo.coeff(2);
if (s > Scalar(0))
{
- s = internal::sqrt(s);
+ s = sqrt(s);
if (shiftInfo.coeff(1) < shiftInfo.coeff(0))
s = -s;
s = s + (shiftInfo.coeff(1) - shiftInfo.coeff(0)) / Scalar(2.0);
@@ -376,6 +440,7 @@ inline void RealSchur<MatrixType>::computeShift(Index iu, Index iter, Scalar& ex
template<typename MatrixType>
inline void RealSchur<MatrixType>::initFrancisQRStep(Index il, Index iu, const Vector3s& shiftInfo, Index& im, Vector3s& firstHouseholderVector)
{
+ using std::abs;
Vector3s& v = firstHouseholderVector; // alias to save typing
for (im = iu-2; im >= il; --im)
@@ -389,9 +454,9 @@ inline void RealSchur<MatrixType>::initFrancisQRStep(Index il, Index iu, const V
if (im == il) {
break;
}
- const Scalar lhs = m_matT.coeff(im,im-1) * (internal::abs(v.coeff(1)) + internal::abs(v.coeff(2)));
- const Scalar rhs = v.coeff(0) * (internal::abs(m_matT.coeff(im-1,im-1)) + internal::abs(Tmm) + internal::abs(m_matT.coeff(im+1,im+1)));
- if (internal::abs(lhs) < NumTraits<Scalar>::epsilon() * rhs)
+ const Scalar lhs = m_matT.coeff(im,im-1) * (abs(v.coeff(1)) + abs(v.coeff(2)));
+ const Scalar rhs = v.coeff(0) * (abs(m_matT.coeff(im-1,im-1)) + abs(Tmm) + abs(m_matT.coeff(im+1,im+1)));
+ if (abs(lhs) < NumTraits<Scalar>::epsilon() * rhs)
{
break;
}
@@ -402,8 +467,8 @@ inline void RealSchur<MatrixType>::initFrancisQRStep(Index il, Index iu, const V
template<typename MatrixType>
inline void RealSchur<MatrixType>::performFrancisQRStep(Index il, Index im, Index iu, bool computeU, const Vector3s& firstHouseholderVector, Scalar* workspace)
{
- assert(im >= il);
- assert(im <= iu-2);
+ eigen_assert(im >= il);
+ eigen_assert(im <= iu-2);
const Index size = m_matT.cols();
diff --git a/Eigen/src/Eigenvalues/RealSchur_MKL.h b/Eigen/src/Eigenvalues/RealSchur_MKL.h
index 960ec3c76..ad9736460 100644
--- a/Eigen/src/Eigenvalues/RealSchur_MKL.h
+++ b/Eigen/src/Eigenvalues/RealSchur_MKL.h
@@ -48,7 +48,7 @@ RealSchur<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> >::compute(const Matrix<E
typedef MatrixType::Scalar Scalar; \
typedef MatrixType::RealScalar RealScalar; \
\
- assert(matrix.cols() == matrix.rows()); \
+ eigen_assert(matrix.cols() == matrix.rows()); \
\
lapack_int n = matrix.cols(), sdim, info; \
lapack_int lda = matrix.outerStride(); \
diff --git a/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h b/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h
index acc5576fe..3993046a8 100644
--- a/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h
+++ b/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h
@@ -384,6 +384,7 @@ template<typename MatrixType>
SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
::compute(const MatrixType& matrix, int options)
{
+ using std::abs;
eigen_assert(matrix.cols() == matrix.rows());
eigen_assert((options&~(EigVecMask|GenEigMask))==0
&& (options&EigVecMask)!=EigVecMask
@@ -394,7 +395,7 @@ SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
if(n==1)
{
- m_eivalues.coeffRef(0,0) = internal::real(matrix.coeff(0,0));
+ m_eivalues.coeffRef(0,0) = numext::real(matrix.coeff(0,0));
if(computeEigenvectors)
m_eivec.setOnes(n,n);
m_info = Success;
@@ -408,9 +409,10 @@ SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
MatrixType& mat = m_eivec;
// map the matrix coefficients to [-1:1] to avoid over- and underflow.
- RealScalar scale = matrix.cwiseAbs().maxCoeff();
+ mat = matrix.template triangularView<Lower>();
+ RealScalar scale = mat.cwiseAbs().maxCoeff();
if(scale==RealScalar(0)) scale = RealScalar(1);
- mat = matrix / scale;
+ mat.template triangularView<Lower>() /= scale;
m_subdiag.resize(n-1);
internal::tridiagonalization_inplace(mat, diag, m_subdiag, computeEigenvectors);
@@ -421,7 +423,7 @@ SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
while (end>0)
{
for (Index i = start; i<end; ++i)
- if (internal::isMuchSmallerThan(internal::abs(m_subdiag[i]),(internal::abs(diag[i])+internal::abs(diag[i+1]))))
+ if (internal::isMuchSmallerThan(abs(m_subdiag[i]),(abs(diag[i])+abs(diag[i+1]))))
m_subdiag[i] = 0;
// find the largest unreduced block
@@ -667,7 +669,7 @@ template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,2
static inline void computeRoots(const MatrixType& m, VectorType& roots)
{
using std::sqrt;
- const Scalar t0 = Scalar(0.5) * sqrt( abs2(m(0,0)-m(1,1)) + Scalar(4)*m(1,0)*m(1,0));
+ const Scalar t0 = Scalar(0.5) * sqrt( numext::abs2(m(0,0)-m(1,1)) + Scalar(4)*m(1,0)*m(1,0));
const Scalar t1 = Scalar(0.5) * (m(0,0) + m(1,1));
roots(0) = t1 - t0;
roots(1) = t1 + t0;
@@ -675,6 +677,7 @@ template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,2
static inline void run(SolverType& solver, const MatrixType& mat, int options)
{
+ using std::sqrt;
eigen_assert(mat.cols() == 2 && mat.cols() == mat.rows());
eigen_assert((options&~(EigVecMask|GenEigMask))==0
&& (options&EigVecMask)!=EigVecMask
@@ -696,9 +699,9 @@ template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,2
if(computeEigenvectors)
{
scaledMat.diagonal().array () -= eivals(1);
- Scalar a2 = abs2(scaledMat(0,0));
- Scalar c2 = abs2(scaledMat(1,1));
- Scalar b2 = abs2(scaledMat(1,0));
+ Scalar a2 = numext::abs2(scaledMat(0,0));
+ Scalar c2 = numext::abs2(scaledMat(1,1));
+ Scalar b2 = numext::abs2(scaledMat(1,0));
if(a2>c2)
{
eivecs.col(1) << -scaledMat(1,0), scaledMat(0,0);
@@ -736,14 +739,24 @@ namespace internal {
template<int StorageOrder,typename RealScalar, typename Scalar, typename Index>
static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index start, Index end, Scalar* matrixQ, Index n)
{
+ using std::abs;
RealScalar td = (diag[end-1] - diag[end])*RealScalar(0.5);
RealScalar e = subdiag[end-1];
// Note that thanks to scaling, e^2 or td^2 cannot overflow, however they can still
// underflow thus leading to inf/NaN values when using the following commented code:
-// RealScalar e2 = abs2(subdiag[end-1]);
+// RealScalar e2 = numext::abs2(subdiag[end-1]);
// RealScalar mu = diag[end] - e2 / (td + (td>0 ? 1 : -1) * sqrt(td*td + e2));
// This explain the following, somewhat more complicated, version:
- RealScalar mu = diag[end] - (e / (td + (td>0 ? 1 : -1))) * (e / hypot(td,e));
+ RealScalar mu = diag[end];
+ if(td==0)
+ mu -= abs(e);
+ else
+ {
+ RealScalar e2 = numext::abs2(subdiag[end-1]);
+ RealScalar h = numext::hypot(td,e);
+ if(e2==0) mu -= (e / (td + (td>0 ? 1 : -1))) * (e / h);
+ else mu -= e2 / (td + (td>0 ? h : -h));
+ }
RealScalar x = diag[start] - mu;
RealScalar z = subdiag[start];
diff --git a/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_MKL.h b/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_MKL.h
index 9380956b5..17c0dadd2 100644
--- a/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_MKL.h
+++ b/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_MKL.h
@@ -40,7 +40,7 @@ namespace Eigen {
/** \internal Specialization for the data types supported by MKL */
#define EIGEN_MKL_EIG_SELFADJ(EIGTYPE, MKLTYPE, MKLRTYPE, MKLNAME, EIGCOLROW, MKLCOLROW ) \
-template<> inline\
+template<> inline \
SelfAdjointEigenSolver<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> >& \
SelfAdjointEigenSolver<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> >::compute(const Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW>& matrix, int options) \
{ \
@@ -56,7 +56,7 @@ SelfAdjointEigenSolver<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> >::compute(c
\
if(n==1) \
{ \
- m_eivalues.coeffRef(0,0) = internal::real(matrix.coeff(0,0)); \
+ m_eivalues.coeffRef(0,0) = numext::real(matrix.coeff(0,0)); \
if(computeEigenvectors) m_eivec.setOnes(n,n); \
m_info = Success; \
m_isInitialized = true; \
diff --git a/Eigen/src/Eigenvalues/Tridiagonalization.h b/Eigen/src/Eigenvalues/Tridiagonalization.h
index c34b7b3b8..192278d68 100644
--- a/Eigen/src/Eigenvalues/Tridiagonalization.h
+++ b/Eigen/src/Eigenvalues/Tridiagonalization.h
@@ -96,7 +96,7 @@ template<typename _MatrixType> class Tridiagonalization
>::type SubDiagonalReturnType;
/** \brief Return type of matrixQ() */
- typedef typename HouseholderSequence<MatrixType,CoeffVectorType>::ConjugateReturnType HouseholderSequenceType;
+ typedef HouseholderSequence<MatrixType,typename internal::remove_all<typename CoeffVectorType::ConjugateReturnType>::type> HouseholderSequenceType;
/** \brief Default constructor.
*
@@ -345,6 +345,7 @@ namespace internal {
template<typename MatrixType, typename CoeffVectorType>
void tridiagonalization_inplace(MatrixType& matA, CoeffVectorType& hCoeffs)
{
+ using numext::conj;
typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
@@ -425,8 +426,6 @@ struct tridiagonalization_inplace_selector;
template<typename MatrixType, typename DiagonalType, typename SubDiagonalType>
void tridiagonalization_inplace(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, bool extractQ)
{
- typedef typename MatrixType::Index Index;
- //Index n = mat.rows();
eigen_assert(mat.cols()==mat.rows() && diag.size()==mat.rows() && subdiag.size()==mat.rows()-1);
tridiagonalization_inplace_selector<MatrixType>::run(mat, diag, subdiag, extractQ);
}
@@ -467,8 +466,9 @@ struct tridiagonalization_inplace_selector<MatrixType,3,false>
template<typename DiagonalType, typename SubDiagonalType>
static void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, bool extractQ)
{
+ using std::sqrt;
diag[0] = mat(0,0);
- RealScalar v1norm2 = abs2(mat(2,0));
+ RealScalar v1norm2 = numext::abs2(mat(2,0));
if(v1norm2 == RealScalar(0))
{
diag[1] = mat(1,1);
@@ -480,7 +480,7 @@ struct tridiagonalization_inplace_selector<MatrixType,3,false>
}
else
{
- RealScalar beta = sqrt(abs2(mat(1,0)) + v1norm2);
+ RealScalar beta = sqrt(numext::abs2(mat(1,0)) + v1norm2);
RealScalar invBeta = RealScalar(1)/beta;
Scalar m01 = mat(1,0) * invBeta;
Scalar m02 = mat(2,0) * invBeta;
@@ -510,7 +510,7 @@ struct tridiagonalization_inplace_selector<MatrixType,1,IsComplex>
template<typename DiagonalType, typename SubDiagonalType>
static void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType&, bool extractQ)
{
- diag(0,0) = real(mat(0,0));
+ diag(0,0) = numext::real(mat(0,0));
if(extractQ)
mat(0,0) = Scalar(1);
}
diff --git a/Eigen/src/Geometry/AlignedBox.h b/Eigen/src/Geometry/AlignedBox.h
index 5830fcd35..8e186d57a 100644
--- a/Eigen/src/Geometry/AlignedBox.h
+++ b/Eigen/src/Geometry/AlignedBox.h
@@ -56,7 +56,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
/** Default constructor initializing a null box. */
- inline explicit AlignedBox()
+ inline AlignedBox()
{ if (AmbientDimAtCompileTime!=Dynamic) setEmpty(); }
/** Constructs a null box with \a _dim the dimension of the ambient space. */
@@ -71,7 +71,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
template<typename Derived>
inline explicit AlignedBox(const MatrixBase<Derived>& a_p)
{
- const typename internal::nested<Derived,2>::type p(a_p.derived());
+ typename internal::nested<Derived,2>::type p(a_p.derived());
m_min = p;
m_max = p;
}
@@ -79,7 +79,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
~AlignedBox() {}
/** \returns the dimension in which the box holds */
- inline Index dim() const { return AmbientDimAtCompileTime==Dynamic ? m_min.size()-1 : Index(AmbientDimAtCompileTime); }
+ inline Index dim() const { return AmbientDimAtCompileTime==Dynamic ? m_min.size() : Index(AmbientDimAtCompileTime); }
/** \deprecated use isEmpty */
inline bool isNull() const { return isEmpty(); }
@@ -248,14 +248,14 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
*/
template<typename Derived>
inline NonInteger exteriorDistance(const MatrixBase<Derived>& p) const
- { return internal::sqrt(NonInteger(squaredExteriorDistance(p))); }
+ { using std::sqrt; return sqrt(NonInteger(squaredExteriorDistance(p))); }
/** \returns the distance between the boxes \a b and \c *this,
* and zero if the boxes intersect.
* \sa squaredExteriorDistance()
*/
inline NonInteger exteriorDistance(const AlignedBox& b) const
- { return internal::sqrt(NonInteger(squaredExteriorDistance(b))); }
+ { using std::sqrt; return sqrt(NonInteger(squaredExteriorDistance(b))); }
/** \returns \c *this with scalar type casted to \a NewScalarType
*
@@ -282,7 +282,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
* determined by \a prec.
*
* \sa MatrixBase::isApprox() */
- bool isApprox(const AlignedBox& other, RealScalar prec = ScalarTraits::dummy_precision()) const
+ bool isApprox(const AlignedBox& other, const RealScalar& prec = ScalarTraits::dummy_precision()) const
{ return m_min.isApprox(other.m_min, prec) && m_max.isApprox(other.m_max, prec); }
protected:
@@ -296,7 +296,7 @@ template<typename Scalar,int AmbientDim>
template<typename Derived>
inline Scalar AlignedBox<Scalar,AmbientDim>::squaredExteriorDistance(const MatrixBase<Derived>& a_p) const
{
- const typename internal::nested<Derived,2*AmbientDim>::type p(a_p.derived());
+ typename internal::nested<Derived,2*AmbientDim>::type p(a_p.derived());
Scalar dist2(0);
Scalar aux;
for (Index k=0; k<dim(); ++k)
diff --git a/Eigen/src/Geometry/AngleAxis.h b/Eigen/src/Geometry/AngleAxis.h
index 67197ac78..553d38c74 100644
--- a/Eigen/src/Geometry/AngleAxis.h
+++ b/Eigen/src/Geometry/AngleAxis.h
@@ -76,7 +76,7 @@ public:
* \warning If the \a axis vector is not normalized, then the angle-axis object
* represents an invalid rotation. */
template<typename Derived>
- inline AngleAxis(Scalar angle, const MatrixBase<Derived>& axis) : m_axis(axis), m_angle(angle) {}
+ inline AngleAxis(const Scalar& angle, const MatrixBase<Derived>& axis) : m_axis(axis), m_angle(angle) {}
/** Constructs and initialize the angle-axis rotation from a quaternion \a q. */
template<typename QuatDerived> inline explicit AngleAxis(const QuaternionBase<QuatDerived>& q) { *this = q; }
/** Constructs and initialize the angle-axis rotation from a 3x3 rotation matrix. */
@@ -137,7 +137,7 @@ public:
* determined by \a prec.
*
* \sa MatrixBase::isApprox() */
- bool isApprox(const AngleAxis& other, typename NumTraits<Scalar>::Real prec = NumTraits<Scalar>::dummy_precision()) const
+ bool isApprox(const AngleAxis& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
{ return m_axis.isApprox(other.m_axis, prec) && internal::isApprox(m_angle,other.m_angle, prec); }
};
@@ -161,6 +161,7 @@ AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const QuaternionBase<QuatDerived
using std::acos;
using std::min;
using std::max;
+ using std::sqrt;
Scalar n2 = q.vec().squaredNorm();
if (n2 < NumTraits<Scalar>::dummy_precision()*NumTraits<Scalar>::dummy_precision())
{
@@ -170,7 +171,7 @@ AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const QuaternionBase<QuatDerived
else
{
m_angle = Scalar(2)*acos((min)((max)(Scalar(-1),q.w()),Scalar(1)));
- m_axis = q.vec() / internal::sqrt(n2);
+ m_axis = q.vec() / sqrt(n2);
}
return *this;
}
@@ -202,9 +203,11 @@ template<typename Scalar>
typename AngleAxis<Scalar>::Matrix3
AngleAxis<Scalar>::toRotationMatrix(void) const
{
+ using std::sin;
+ using std::cos;
Matrix3 res;
- Vector3 sin_axis = internal::sin(m_angle) * m_axis;
- Scalar c = internal::cos(m_angle);
+ Vector3 sin_axis = sin(m_angle) * m_axis;
+ Scalar c = cos(m_angle);
Vector3 cos1_axis = (Scalar(1)-c) * m_axis;
Scalar tmp;
diff --git a/Eigen/src/Geometry/EulerAngles.h b/Eigen/src/Geometry/EulerAngles.h
index e424d2406..82802fb43 100644
--- a/Eigen/src/Geometry/EulerAngles.h
+++ b/Eigen/src/Geometry/EulerAngles.h
@@ -27,55 +27,75 @@ namespace Eigen {
* * AngleAxisf(ea[1], Vector3f::UnitX())
* * AngleAxisf(ea[2], Vector3f::UnitZ()); \endcode
* This corresponds to the right-multiply conventions (with right hand side frames).
+ *
+ * The returned angles are in the ranges [0:pi]x[-pi:pi]x[-pi:pi].
+ *
+ * \sa class AngleAxis
*/
template<typename Derived>
inline Matrix<typename MatrixBase<Derived>::Scalar,3,1>
MatrixBase<Derived>::eulerAngles(Index a0, Index a1, Index a2) const
{
+ using std::atan2;
+ using std::sin;
+ using std::cos;
/* Implemented from Graphics Gems IV */
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Derived,3,3)
Matrix<Scalar,3,1> res;
typedef Matrix<typename Derived::Scalar,2,1> Vector2;
- const Scalar epsilon = NumTraits<Scalar>::dummy_precision();
const Index odd = ((a0+1)%3 == a1) ? 0 : 1;
const Index i = a0;
const Index j = (a0 + 1 + odd)%3;
const Index k = (a0 + 2 - odd)%3;
-
+
if (a0==a2)
{
- Scalar s = Vector2(coeff(j,i) , coeff(k,i)).norm();
- res[1] = internal::atan2(s, coeff(i,i));
- if (s > epsilon)
+ res[0] = atan2(coeff(j,i), coeff(k,i));
+ if((odd && res[0]<Scalar(0)) || ((!odd) && res[0]>Scalar(0)))
{
- res[0] = internal::atan2(coeff(j,i), coeff(k,i));
- res[2] = internal::atan2(coeff(i,j),-coeff(i,k));
+ res[0] = (res[0] > Scalar(0)) ? res[0] - Scalar(M_PI) : res[0] + Scalar(M_PI);
+ Scalar s2 = Vector2(coeff(j,i), coeff(k,i)).norm();
+ res[1] = -atan2(s2, coeff(i,i));
}
else
{
- res[0] = Scalar(0);
- res[2] = (coeff(i,i)>0?1:-1)*internal::atan2(-coeff(k,j), coeff(j,j));
+ Scalar s2 = Vector2(coeff(j,i), coeff(k,i)).norm();
+ res[1] = atan2(s2, coeff(i,i));
}
- }
+
+ // With a=(0,1,0), we have i=0; j=1; k=2, and after computing the first two angles,
+ // we can compute their respective rotation, and apply its inverse to M. Since the result must
+ // be a rotation around x, we have:
+ //
+ // c2 s1.s2 c1.s2 1 0 0
+ // 0 c1 -s1 * M = 0 c3 s3
+ // -s2 s1.c2 c1.c2 0 -s3 c3
+ //
+ // Thus: m11.c1 - m21.s1 = c3 & m12.c1 - m22.s1 = s3
+
+ Scalar s1 = sin(res[0]);
+ Scalar c1 = cos(res[0]);
+ res[2] = atan2(c1*coeff(j,k)-s1*coeff(k,k), c1*coeff(j,j) - s1 * coeff(k,j));
+ }
else
{
- Scalar c = Vector2(coeff(i,i) , coeff(i,j)).norm();
- res[1] = internal::atan2(-coeff(i,k), c);
- if (c > epsilon)
- {
- res[0] = internal::atan2(coeff(j,k), coeff(k,k));
- res[2] = internal::atan2(coeff(i,j), coeff(i,i));
+ res[0] = atan2(coeff(j,k), coeff(k,k));
+ Scalar c2 = Vector2(coeff(i,i), coeff(i,j)).norm();
+ if((odd && res[0]<Scalar(0)) || ((!odd) && res[0]>Scalar(0))) {
+ res[0] = (res[0] > Scalar(0)) ? res[0] - Scalar(M_PI) : res[0] + Scalar(M_PI);
+ res[1] = atan2(-coeff(i,k), -c2);
}
else
- {
- res[0] = Scalar(0);
- res[2] = (coeff(i,k)>0?1:-1)*internal::atan2(-coeff(k,j), coeff(j,j));
- }
+ res[1] = atan2(-coeff(i,k), c2);
+ Scalar s1 = sin(res[0]);
+ Scalar c1 = cos(res[0]);
+ res[2] = atan2(s1*coeff(k,i)-c1*coeff(j,i), c1*coeff(j,j) - s1 * coeff(k,j));
}
if (!odd)
res = -res;
+
return res;
}
diff --git a/Eigen/src/Geometry/Homogeneous.h b/Eigen/src/Geometry/Homogeneous.h
index df03feb55..00e71d190 100644
--- a/Eigen/src/Geometry/Homogeneous.h
+++ b/Eigen/src/Geometry/Homogeneous.h
@@ -59,7 +59,7 @@ template<typename MatrixType,typename Rhs> struct homogeneous_right_product_impl
} // end namespace internal
template<typename MatrixType,int _Direction> class Homogeneous
- : public MatrixBase<Homogeneous<MatrixType,_Direction> >
+ : internal::no_assignment_operator, public MatrixBase<Homogeneous<MatrixType,_Direction> >
{
public:
diff --git a/Eigen/src/Geometry/Hyperplane.h b/Eigen/src/Geometry/Hyperplane.h
index 1b7c7c78c..aeff43fef 100644
--- a/Eigen/src/Geometry/Hyperplane.h
+++ b/Eigen/src/Geometry/Hyperplane.h
@@ -50,7 +50,7 @@ public:
typedef const Block<const Coefficients,AmbientDimAtCompileTime,1> ConstNormalReturnType;
/** Default constructor without initialization */
- inline explicit Hyperplane() {}
+ inline Hyperplane() {}
template<int OtherOptions>
Hyperplane(const Hyperplane<Scalar,AmbientDimAtCompileTime,OtherOptions>& other)
@@ -75,7 +75,7 @@ public:
* such that the algebraic equation of the plane is \f$ n \cdot x + d = 0 \f$.
* \warning the vector normal is assumed to be normalized.
*/
- inline Hyperplane(const VectorType& n, Scalar d)
+ inline Hyperplane(const VectorType& n, const Scalar& d)
: m_coeffs(n.size()+1)
{
normal() = n;
@@ -135,7 +135,7 @@ public:
/** \returns the absolute distance between the plane \c *this and a point \a p.
* \sa signedDistance()
*/
- inline Scalar absDistance(const VectorType& p) const { return internal::abs(signedDistance(p)); }
+ inline Scalar absDistance(const VectorType& p) const { using std::abs; return abs(signedDistance(p)); }
/** \returns the projection of a point \a p onto the plane \c *this.
*/
@@ -178,13 +178,14 @@ public:
*/
VectorType intersection(const Hyperplane& other) const
{
+ using std::abs;
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 2)
Scalar det = coeffs().coeff(0) * other.coeffs().coeff(1) - coeffs().coeff(1) * other.coeffs().coeff(0);
// since the line equations ax+by=c are normalized with a^2+b^2=1, the following tests
// whether the two lines are approximately parallel.
if(internal::isMuchSmallerThan(det, Scalar(1)))
{ // special case where the two lines are approximately parallel. Pick any point on the first line.
- if(internal::abs(coeffs().coeff(1))>internal::abs(coeffs().coeff(0)))
+ if(abs(coeffs().coeff(1))>abs(coeffs().coeff(0)))
return VectorType(coeffs().coeff(1), -coeffs().coeff(2)/coeffs().coeff(1)-coeffs().coeff(0));
else
return VectorType(-coeffs().coeff(2)/coeffs().coeff(0)-coeffs().coeff(1), coeffs().coeff(0));
@@ -256,7 +257,7 @@ public:
*
* \sa MatrixBase::isApprox() */
template<int OtherOptions>
- bool isApprox(const Hyperplane<Scalar,AmbientDimAtCompileTime,OtherOptions>& other, typename NumTraits<Scalar>::Real prec = NumTraits<Scalar>::dummy_precision()) const
+ bool isApprox(const Hyperplane<Scalar,AmbientDimAtCompileTime,OtherOptions>& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
protected:
diff --git a/Eigen/src/Geometry/OrthoMethods.h b/Eigen/src/Geometry/OrthoMethods.h
index 11ad5829c..556bc8160 100644
--- a/Eigen/src/Geometry/OrthoMethods.h
+++ b/Eigen/src/Geometry/OrthoMethods.h
@@ -33,9 +33,9 @@ MatrixBase<Derived>::cross(const MatrixBase<OtherDerived>& other) const
typename internal::nested<Derived,2>::type lhs(derived());
typename internal::nested<OtherDerived,2>::type rhs(other.derived());
return typename cross_product_return_type<OtherDerived>::type(
- internal::conj(lhs.coeff(1) * rhs.coeff(2) - lhs.coeff(2) * rhs.coeff(1)),
- internal::conj(lhs.coeff(2) * rhs.coeff(0) - lhs.coeff(0) * rhs.coeff(2)),
- internal::conj(lhs.coeff(0) * rhs.coeff(1) - lhs.coeff(1) * rhs.coeff(0))
+ numext::conj(lhs.coeff(1) * rhs.coeff(2) - lhs.coeff(2) * rhs.coeff(1)),
+ numext::conj(lhs.coeff(2) * rhs.coeff(0) - lhs.coeff(0) * rhs.coeff(2)),
+ numext::conj(lhs.coeff(0) * rhs.coeff(1) - lhs.coeff(1) * rhs.coeff(0))
);
}
@@ -49,9 +49,9 @@ struct cross3_impl {
run(const VectorLhs& lhs, const VectorRhs& rhs)
{
return typename internal::plain_matrix_type<VectorLhs>::type(
- internal::conj(lhs.coeff(1) * rhs.coeff(2) - lhs.coeff(2) * rhs.coeff(1)),
- internal::conj(lhs.coeff(2) * rhs.coeff(0) - lhs.coeff(0) * rhs.coeff(2)),
- internal::conj(lhs.coeff(0) * rhs.coeff(1) - lhs.coeff(1) * rhs.coeff(0)),
+ numext::conj(lhs.coeff(1) * rhs.coeff(2) - lhs.coeff(2) * rhs.coeff(1)),
+ numext::conj(lhs.coeff(2) * rhs.coeff(0) - lhs.coeff(0) * rhs.coeff(2)),
+ numext::conj(lhs.coeff(0) * rhs.coeff(1) - lhs.coeff(1) * rhs.coeff(0)),
0
);
}
@@ -78,8 +78,8 @@ MatrixBase<Derived>::cross3(const MatrixBase<OtherDerived>& other) const
typedef typename internal::nested<Derived,2>::type DerivedNested;
typedef typename internal::nested<OtherDerived,2>::type OtherDerivedNested;
- const DerivedNested lhs(derived());
- const OtherDerivedNested rhs(other.derived());
+ DerivedNested lhs(derived());
+ OtherDerivedNested rhs(other.derived());
return internal::cross3_impl<Architecture::Target,
typename internal::remove_all<DerivedNested>::type,
@@ -141,8 +141,8 @@ struct unitOrthogonal_selector
if (maxi==0)
sndi = 1;
RealScalar invnm = RealScalar(1)/(Vector2() << src.coeff(sndi),src.coeff(maxi)).finished().norm();
- perp.coeffRef(maxi) = -conj(src.coeff(sndi)) * invnm;
- perp.coeffRef(sndi) = conj(src.coeff(maxi)) * invnm;
+ perp.coeffRef(maxi) = -numext::conj(src.coeff(sndi)) * invnm;
+ perp.coeffRef(sndi) = numext::conj(src.coeff(maxi)) * invnm;
return perp;
}
@@ -168,8 +168,8 @@ struct unitOrthogonal_selector<Derived,3>
|| (!isMuchSmallerThan(src.y(), src.z())))
{
RealScalar invnm = RealScalar(1)/src.template head<2>().norm();
- perp.coeffRef(0) = -conj(src.y())*invnm;
- perp.coeffRef(1) = conj(src.x())*invnm;
+ perp.coeffRef(0) = -numext::conj(src.y())*invnm;
+ perp.coeffRef(1) = numext::conj(src.x())*invnm;
perp.coeffRef(2) = 0;
}
/* if both x and y are close to zero, then the vector is close
@@ -180,8 +180,8 @@ struct unitOrthogonal_selector<Derived,3>
{
RealScalar invnm = RealScalar(1)/src.template tail<2>().norm();
perp.coeffRef(0) = 0;
- perp.coeffRef(1) = -conj(src.z())*invnm;
- perp.coeffRef(2) = conj(src.y())*invnm;
+ perp.coeffRef(1) = -numext::conj(src.z())*invnm;
+ perp.coeffRef(2) = numext::conj(src.y())*invnm;
}
return perp;
@@ -193,7 +193,7 @@ struct unitOrthogonal_selector<Derived,2>
{
typedef typename plain_matrix_type<Derived>::type VectorType;
static inline VectorType run(const Derived& src)
- { return VectorType(-conj(src.y()), conj(src.x())).normalized(); }
+ { return VectorType(-numext::conj(src.y()), numext::conj(src.x())).normalized(); }
};
} // end namespace internal
diff --git a/Eigen/src/Geometry/ParametrizedLine.h b/Eigen/src/Geometry/ParametrizedLine.h
index 719a90441..77fa228e6 100644
--- a/Eigen/src/Geometry/ParametrizedLine.h
+++ b/Eigen/src/Geometry/ParametrizedLine.h
@@ -41,7 +41,7 @@ public:
typedef Matrix<Scalar,AmbientDimAtCompileTime,1,Options> VectorType;
/** Default constructor without initialization */
- inline explicit ParametrizedLine() {}
+ inline ParametrizedLine() {}
template<int OtherOptions>
ParametrizedLine(const ParametrizedLine<Scalar,AmbientDimAtCompileTime,OtherOptions>& other)
@@ -87,13 +87,13 @@ public:
/** \returns the distance of a point \a p to its projection onto the line \c *this.
* \sa squaredDistance()
*/
- RealScalar distance(const VectorType& p) const { return internal::sqrt(squaredDistance(p)); }
+ RealScalar distance(const VectorType& p) const { using std::sqrt; return sqrt(squaredDistance(p)); }
/** \returns the projection of a point \a p onto the line \c *this. */
VectorType projection(const VectorType& p) const
{ return origin() + direction().dot(p-origin()) * direction(); }
- VectorType pointAt( Scalar t ) const;
+ VectorType pointAt(const Scalar& t) const;
template <int OtherOptions>
Scalar intersectionParameter(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const;
@@ -154,7 +154,7 @@ inline ParametrizedLine<_Scalar, _AmbientDim,_Options>::ParametrizedLine(const H
*/
template <typename _Scalar, int _AmbientDim, int _Options>
inline typename ParametrizedLine<_Scalar, _AmbientDim,_Options>::VectorType
-ParametrizedLine<_Scalar, _AmbientDim,_Options>::pointAt( _Scalar t ) const
+ParametrizedLine<_Scalar, _AmbientDim,_Options>::pointAt(const _Scalar& t) const
{
return origin() + (direction()*t);
}
diff --git a/Eigen/src/Geometry/Quaternion.h b/Eigen/src/Geometry/Quaternion.h
index 8792e2da2..f06653f1c 100644
--- a/Eigen/src/Geometry/Quaternion.h
+++ b/Eigen/src/Geometry/Quaternion.h
@@ -150,18 +150,14 @@ public:
/** \returns the conjugated quaternion */
Quaternion<Scalar> conjugate() const;
- /** \returns an interpolation for a constant motion between \a other and \c *this
- * \a t in [0;1]
- * see http://en.wikipedia.org/wiki/Slerp
- */
- template<class OtherDerived> Quaternion<Scalar> slerp(Scalar t, const QuaternionBase<OtherDerived>& other) const;
+ template<class OtherDerived> Quaternion<Scalar> slerp(const Scalar& t, const QuaternionBase<OtherDerived>& other) const;
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
* determined by \a prec.
*
* \sa MatrixBase::isApprox() */
template<class OtherDerived>
- bool isApprox(const QuaternionBase<OtherDerived>& other, RealScalar prec = NumTraits<Scalar>::dummy_precision()) const
+ bool isApprox(const QuaternionBase<OtherDerived>& other, const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const
{ return coeffs().isApprox(other.coeffs(), prec); }
/** return the result vector of \a v through the rotation*/
@@ -193,11 +189,12 @@ public:
*
* \brief The quaternion class used to represent 3D orientations and rotations
*
- * \param _Scalar the scalar type, i.e., the type of the coefficients
+ * \tparam _Scalar the scalar type, i.e., the type of the coefficients
+ * \tparam _Options controls the memory alignment of the coefficients. Can be \# AutoAlign or \# DontAlign. Default is AutoAlign.
*
* This class represents a quaternion \f$ w+xi+yj+zk \f$ that is a convenient representation of
* orientations and rotations of objects in three dimensions. Compared to other representations
- * like Euler angles or 3x3 matrices, quatertions offer the following advantages:
+ * like Euler angles or 3x3 matrices, quaternions offer the following advantages:
* \li \b compact storage (4 scalars)
* \li \b efficient to compose (28 flops),
* \li \b stable spherical interpolation
@@ -206,6 +203,8 @@ public:
* \li \c Quaternionf for \c float
* \li \c Quaterniond for \c double
*
+ * \warning Operations interpreting the quaternion as rotation have undefined behavior if the quaternion is not normalized.
+ *
* \sa class AngleAxis, class Transform
*/
@@ -248,7 +247,7 @@ public:
* while internally the coefficients are stored in the following order:
* [\c x, \c y, \c z, \c w]
*/
- inline Quaternion(Scalar w, Scalar x, Scalar y, Scalar z) : m_coeffs(x, y, z, w){}
+ inline Quaternion(const Scalar& w, const Scalar& x, const Scalar& y, const Scalar& z) : m_coeffs(x, y, z, w){}
/** Constructs and initialize a quaternion from the array data */
inline Quaternion(const Scalar* data) : m_coeffs(data) {}
@@ -304,41 +303,29 @@ typedef Quaternion<double> Quaterniond;
namespace internal {
template<typename _Scalar, int _Options>
- struct traits<Map<Quaternion<_Scalar>, _Options> >:
- traits<Quaternion<_Scalar, _Options> >
+ struct traits<Map<Quaternion<_Scalar>, _Options> > : traits<Quaternion<_Scalar, (int(_Options)&Aligned)==Aligned ? AutoAlign : DontAlign> >
{
- typedef _Scalar Scalar;
typedef Map<Matrix<_Scalar,4,1>, _Options> Coefficients;
-
- typedef traits<Quaternion<_Scalar, _Options> > TraitsBase;
- enum {
- IsAligned = TraitsBase::IsAligned,
-
- Flags = TraitsBase::Flags
- };
};
}
namespace internal {
template<typename _Scalar, int _Options>
- struct traits<Map<const Quaternion<_Scalar>, _Options> >:
- traits<Quaternion<_Scalar> >
+ struct traits<Map<const Quaternion<_Scalar>, _Options> > : traits<Quaternion<_Scalar, (int(_Options)&Aligned)==Aligned ? AutoAlign : DontAlign> >
{
- typedef _Scalar Scalar;
typedef Map<const Matrix<_Scalar,4,1>, _Options> Coefficients;
-
- typedef traits<Quaternion<_Scalar, _Options> > TraitsBase;
+ typedef traits<Quaternion<_Scalar, (int(_Options)&Aligned)==Aligned ? AutoAlign : DontAlign> > TraitsBase;
enum {
- IsAligned = TraitsBase::IsAligned,
Flags = TraitsBase::Flags & ~LvalueBit
};
};
}
-/** \brief Quaternion expression mapping a constant memory buffer
+/** \ingroup Geometry_Module
+ * \brief Quaternion expression mapping a constant memory buffer
*
- * \param _Scalar the type of the Quaternion coefficients
- * \param _Options see class Map
+ * \tparam _Scalar the type of the Quaternion coefficients
+ * \tparam _Options see class Map
*
* This is a specialization of class Map for Quaternion. This class allows to view
* a 4 scalar memory buffer as an Eigen's Quaternion object.
@@ -359,7 +346,7 @@ class Map<const Quaternion<_Scalar>, _Options >
/** Constructs a Mapped Quaternion object from the pointer \a coeffs
*
- * The pointer \a coeffs must reference the four coeffecients of Quaternion in the following order:
+ * The pointer \a coeffs must reference the four coefficients of Quaternion in the following order:
* \code *coeffs == {x, y, z, w} \endcode
*
* If the template parameter _Options is set to #Aligned, then the pointer coeffs must be aligned. */
@@ -371,10 +358,11 @@ class Map<const Quaternion<_Scalar>, _Options >
const Coefficients m_coeffs;
};
-/** \brief Expression of a quaternion from a memory buffer
+/** \ingroup Geometry_Module
+ * \brief Expression of a quaternion from a memory buffer
*
- * \param _Scalar the type of the Quaternion coefficients
- * \param _Options see class Map
+ * \tparam _Scalar the type of the Quaternion coefficients
+ * \tparam _Options see class Map
*
* This is a specialization of class Map for Quaternion. This class allows to view
* a 4 scalar memory buffer as an Eigen's Quaternion object.
@@ -395,7 +383,7 @@ class Map<Quaternion<_Scalar>, _Options >
/** Constructs a Mapped Quaternion object from the pointer \a coeffs
*
- * The pointer \a coeffs must reference the four coeffecients of Quaternion in the following order:
+ * The pointer \a coeffs must reference the four coefficients of Quaternion in the following order:
* \code *coeffs == {x, y, z, w} \endcode
*
* If the template parameter _Options is set to #Aligned, then the pointer coeffs must be aligned. */
@@ -409,16 +397,16 @@ class Map<Quaternion<_Scalar>, _Options >
};
/** \ingroup Geometry_Module
- * Map an unaligned array of single precision scalar as a quaternion */
+ * Map an unaligned array of single precision scalars as a quaternion */
typedef Map<Quaternion<float>, 0> QuaternionMapf;
/** \ingroup Geometry_Module
- * Map an unaligned array of double precision scalar as a quaternion */
+ * Map an unaligned array of double precision scalars as a quaternion */
typedef Map<Quaternion<double>, 0> QuaternionMapd;
/** \ingroup Geometry_Module
- * Map a 16-bits aligned array of double precision scalars as a quaternion */
+ * Map a 16-byte aligned array of single precision scalars as a quaternion */
typedef Map<Quaternion<float>, Aligned> QuaternionMapAlignedf;
/** \ingroup Geometry_Module
- * Map a 16-bits aligned array of double precision scalars as a quaternion */
+ * Map a 16-byte aligned array of double precision scalars as a quaternion */
typedef Map<Quaternion<double>, Aligned> QuaternionMapAlignedd;
/***************************************************************************
@@ -478,7 +466,7 @@ QuaternionBase<Derived>::_transformVector(Vector3 v) const
// Note that this algorithm comes from the optimization by hand
// of the conversion to a Matrix followed by a Matrix/Vector product.
// It appears to be much faster than the common algorithm found
- // in the litterature (30 versus 39 flops). It also requires two
+ // in the literature (30 versus 39 flops). It also requires two
// Vector3 as temporaries.
Vector3 uv = this->vec().cross(v);
uv += uv;
@@ -505,9 +493,11 @@ EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator=(const Quaternion
template<class Derived>
EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator=(const AngleAxisType& aa)
{
+ using std::cos;
+ using std::sin;
Scalar ha = Scalar(0.5)*aa.angle(); // Scalar(0.5) to suppress precision loss warnings
- this->w() = internal::cos(ha);
- this->vec() = internal::sin(ha) * aa.axis();
+ this->w() = cos(ha);
+ this->vec() = sin(ha) * aa.axis();
return derived();
}
@@ -581,12 +571,13 @@ template<typename Derived1, typename Derived2>
inline Derived& QuaternionBase<Derived>::setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b)
{
using std::max;
+ using std::sqrt;
Vector3 v0 = a.normalized();
Vector3 v1 = b.normalized();
Scalar c = v1.dot(v0);
// if dot == -1, vectors are nearly opposites
- // => accuraletly compute the rotation axis by computing the
+ // => accurately compute the rotation axis by computing the
// intersection of the two planes. This is done by solving:
// x^T v0 = 0
// x^T v1 = 0
@@ -595,18 +586,18 @@ inline Derived& QuaternionBase<Derived>::setFromTwoVectors(const MatrixBase<Deri
// which yields a singular value problem
if (c < Scalar(-1)+NumTraits<Scalar>::dummy_precision())
{
- c = max<Scalar>(c,-1);
+ c = (max)(c,Scalar(-1));
Matrix<Scalar,2,3> m; m << v0.transpose(), v1.transpose();
JacobiSVD<Matrix<Scalar,2,3> > svd(m, ComputeFullV);
Vector3 axis = svd.matrixV().col(2);
Scalar w2 = (Scalar(1)+c)*Scalar(0.5);
- this->w() = internal::sqrt(w2);
- this->vec() = axis * internal::sqrt(Scalar(1) - w2);
+ this->w() = sqrt(w2);
+ this->vec() = axis * sqrt(Scalar(1) - w2);
return derived();
}
Vector3 axis = v0.cross(v1);
- Scalar s = internal::sqrt((Scalar(1)+c)*Scalar(2));
+ Scalar s = sqrt((Scalar(1)+c)*Scalar(2));
Scalar invs = Scalar(1)/s;
this->vec() = axis * invs;
this->w() = s * Scalar(0.5);
@@ -677,24 +668,32 @@ inline typename internal::traits<Derived>::Scalar
QuaternionBase<Derived>::angularDistance(const QuaternionBase<OtherDerived>& other) const
{
using std::acos;
- double d = internal::abs(this->dot(other));
- if (d>=1.0)
+ using std::abs;
+ Scalar d = abs(this->dot(other));
+ if (d>=Scalar(1))
return Scalar(0);
- return static_cast<Scalar>(2 * acos(d));
+ return Scalar(2) * acos(d);
}
+
+
/** \returns the spherical linear interpolation between the two quaternions
- * \c *this and \a other at the parameter \a t
+ * \c *this and \a other at the parameter \a t in [0;1].
+ *
+ * This represents an interpolation for a constant motion between \c *this and \a other,
+ * see also http://en.wikipedia.org/wiki/Slerp.
*/
template <class Derived>
template <class OtherDerived>
Quaternion<typename internal::traits<Derived>::Scalar>
-QuaternionBase<Derived>::slerp(Scalar t, const QuaternionBase<OtherDerived>& other) const
+QuaternionBase<Derived>::slerp(const Scalar& t, const QuaternionBase<OtherDerived>& other) const
{
using std::acos;
+ using std::sin;
+ using std::abs;
static const Scalar one = Scalar(1) - NumTraits<Scalar>::epsilon();
Scalar d = this->dot(other);
- Scalar absD = internal::abs(d);
+ Scalar absD = abs(d);
Scalar scale0;
Scalar scale1;
@@ -708,10 +707,10 @@ QuaternionBase<Derived>::slerp(Scalar t, const QuaternionBase<OtherDerived>& oth
{
// theta is the angle between the 2 quaternions
Scalar theta = acos(absD);
- Scalar sinTheta = internal::sin(theta);
+ Scalar sinTheta = sin(theta);
- scale0 = internal::sin( ( Scalar(1) - t ) * theta) / sinTheta;
- scale1 = internal::sin( ( t * theta) ) / sinTheta;
+ scale0 = sin( ( Scalar(1) - t ) * theta) / sinTheta;
+ scale1 = sin( ( t * theta) ) / sinTheta;
}
if(d<0) scale1 = -scale1;
@@ -728,6 +727,7 @@ struct quaternionbase_assign_impl<Other,3,3>
typedef DenseIndex Index;
template<class Derived> static inline void run(QuaternionBase<Derived>& q, const Other& mat)
{
+ using std::sqrt;
// This algorithm comes from "Quaternion Calculus and Fast Animation",
// Ken Shoemake, 1987 SIGGRAPH course notes
Scalar t = mat.trace();
diff --git a/Eigen/src/Geometry/Rotation2D.h b/Eigen/src/Geometry/Rotation2D.h
index 868e2ef31..1cac343a5 100644
--- a/Eigen/src/Geometry/Rotation2D.h
+++ b/Eigen/src/Geometry/Rotation2D.h
@@ -59,7 +59,7 @@ protected:
public:
/** Construct a 2D counter clock wise rotation from the angle \a a in radian. */
- inline Rotation2D(Scalar a) : m_angle(a) {}
+ inline Rotation2D(const Scalar& a) : m_angle(a) {}
/** \returns the rotation angle */
inline Scalar angle() const { return m_angle; }
@@ -89,7 +89,7 @@ public:
/** \returns the spherical interpolation between \c *this and \a other using
* parameter \a t. It is in fact equivalent to a linear interpolation.
*/
- inline Rotation2D slerp(Scalar t, const Rotation2D& other) const
+ inline Rotation2D slerp(const Scalar& t, const Rotation2D& other) const
{ return m_angle * (1-t) + other.angle() * t; }
/** \returns \c *this with scalar type casted to \a NewScalarType
@@ -114,7 +114,7 @@ public:
* determined by \a prec.
*
* \sa MatrixBase::isApprox() */
- bool isApprox(const Rotation2D& other, typename NumTraits<Scalar>::Real prec = NumTraits<Scalar>::dummy_precision()) const
+ bool isApprox(const Rotation2D& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
{ return internal::isApprox(m_angle,other.m_angle, prec); }
};
@@ -133,8 +133,9 @@ template<typename Scalar>
template<typename Derived>
Rotation2D<Scalar>& Rotation2D<Scalar>::fromRotationMatrix(const MatrixBase<Derived>& mat)
{
+ using std::atan2;
EIGEN_STATIC_ASSERT(Derived::RowsAtCompileTime==2 && Derived::ColsAtCompileTime==2,YOU_MADE_A_PROGRAMMING_MISTAKE)
- m_angle = internal::atan2(mat.coeff(1,0), mat.coeff(0,0));
+ m_angle = atan2(mat.coeff(1,0), mat.coeff(0,0));
return *this;
}
@@ -144,8 +145,10 @@ template<typename Scalar>
typename Rotation2D<Scalar>::Matrix2
Rotation2D<Scalar>::toRotationMatrix(void) const
{
- Scalar sinA = internal::sin(m_angle);
- Scalar cosA = internal::cos(m_angle);
+ using std::sin;
+ using std::cos;
+ Scalar sinA = sin(m_angle);
+ Scalar cosA = cos(m_angle);
return (Matrix2() << cosA, -sinA, sinA, cosA).finished();
}
diff --git a/Eigen/src/Geometry/Scaling.h b/Eigen/src/Geometry/Scaling.h
index 8edcac31c..1c25f36fe 100644
--- a/Eigen/src/Geometry/Scaling.h
+++ b/Eigen/src/Geometry/Scaling.h
@@ -99,7 +99,7 @@ public:
* determined by \a prec.
*
* \sa MatrixBase::isApprox() */
- bool isApprox(const UniformScaling& other, typename NumTraits<Scalar>::Real prec = NumTraits<Scalar>::dummy_precision()) const
+ bool isApprox(const UniformScaling& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
{ return internal::isApprox(m_factor, other.factor(), prec); }
};
@@ -122,11 +122,11 @@ static inline UniformScaling<std::complex<RealScalar> > Scaling(const std::compl
/** Constructs a 2D axis aligned scaling */
template<typename Scalar>
-static inline DiagonalMatrix<Scalar,2> Scaling(Scalar sx, Scalar sy)
+static inline DiagonalMatrix<Scalar,2> Scaling(const Scalar& sx, const Scalar& sy)
{ return DiagonalMatrix<Scalar,2>(sx, sy); }
/** Constructs a 3D axis aligned scaling */
template<typename Scalar>
-static inline DiagonalMatrix<Scalar,3> Scaling(Scalar sx, Scalar sy, Scalar sz)
+static inline DiagonalMatrix<Scalar,3> Scaling(const Scalar& sx, const Scalar& sy, const Scalar& sz)
{ return DiagonalMatrix<Scalar,3>(sx, sy, sz); }
/** Constructs an axis aligned scaling expression from vector expression \a coeffs
diff --git a/Eigen/src/Geometry/Transform.h b/Eigen/src/Geometry/Transform.h
index 4c1ef8eaa..56f361566 100644
--- a/Eigen/src/Geometry/Transform.h
+++ b/Eigen/src/Geometry/Transform.h
@@ -194,9 +194,9 @@ public:
/** type of the matrix used to represent the linear part of the transformation */
typedef Matrix<Scalar,Dim,Dim,Options> LinearMatrixType;
/** type of read/write reference to the linear part of the transformation */
- typedef Block<MatrixType,Dim,Dim,int(Mode)==(AffineCompact)> LinearPart;
+ typedef Block<MatrixType,Dim,Dim,int(Mode)==(AffineCompact) && (Options&RowMajor)==0> LinearPart;
/** type of read reference to the linear part of the transformation */
- typedef const Block<ConstMatrixType,Dim,Dim,int(Mode)==(AffineCompact)> ConstLinearPart;
+ typedef const Block<ConstMatrixType,Dim,Dim,int(Mode)==(AffineCompact) && (Options&RowMajor)==0> ConstLinearPart;
/** type of read/write reference to the affine part of the transformation */
typedef typename internal::conditional<int(Mode)==int(AffineCompact),
MatrixType&,
@@ -506,8 +506,8 @@ public:
template<typename OtherDerived>
inline Transform& prescale(const MatrixBase<OtherDerived> &other);
- inline Transform& scale(Scalar s);
- inline Transform& prescale(Scalar s);
+ inline Transform& scale(const Scalar& s);
+ inline Transform& prescale(const Scalar& s);
template<typename OtherDerived>
inline Transform& translate(const MatrixBase<OtherDerived> &other);
@@ -521,8 +521,8 @@ public:
template<typename RotationType>
inline Transform& prerotate(const RotationType& rotation);
- Transform& shear(Scalar sx, Scalar sy);
- Transform& preshear(Scalar sx, Scalar sy);
+ Transform& shear(const Scalar& sx, const Scalar& sy);
+ Transform& preshear(const Scalar& sx, const Scalar& sy);
inline Transform& operator=(const TranslationType& t);
inline Transform& operator*=(const TranslationType& t) { return translate(t.vector()); }
@@ -530,9 +530,9 @@ public:
inline Transform& operator=(const UniformScaling<Scalar>& t);
inline Transform& operator*=(const UniformScaling<Scalar>& s) { return scale(s.factor()); }
- inline Transform<Scalar,Dim,(int(Mode)==int(Isometry)?Affine:Isometry)> operator*(const UniformScaling<Scalar>& s) const
+ inline Transform<Scalar,Dim,(int(Mode)==int(Isometry)?int(Affine):int(Mode))> operator*(const UniformScaling<Scalar>& s) const
{
- Transform<Scalar,Dim,(int(Mode)==int(Isometry)?Affine:Isometry),Options> res = *this;
+ Transform<Scalar,Dim,(int(Mode)==int(Isometry)?int(Affine):int(Mode)),Options> res = *this;
res.scale(s.factor());
return res;
}
@@ -584,7 +584,7 @@ public:
* determined by \a prec.
*
* \sa MatrixBase::isApprox() */
- bool isApprox(const Transform& other, typename NumTraits<Scalar>::Real prec = NumTraits<Scalar>::dummy_precision()) const
+ bool isApprox(const Transform& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
{ return m_matrix.isApprox(other.m_matrix, prec); }
/** Sets the last row to [0 ... 0 1]
@@ -794,7 +794,7 @@ Transform<Scalar,Dim,Mode,Options>::scale(const MatrixBase<OtherDerived> &other)
* \sa prescale(Scalar)
*/
template<typename Scalar, int Dim, int Mode, int Options>
-inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::scale(Scalar s)
+inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::scale(const Scalar& s)
{
EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
linearExt() *= s;
@@ -821,7 +821,7 @@ Transform<Scalar,Dim,Mode,Options>::prescale(const MatrixBase<OtherDerived> &oth
* \sa scale(Scalar)
*/
template<typename Scalar, int Dim, int Mode, int Options>
-inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::prescale(Scalar s)
+inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::prescale(const Scalar& s)
{
EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
m_matrix.template topRows<Dim>() *= s;
@@ -909,7 +909,7 @@ Transform<Scalar,Dim,Mode,Options>::prerotate(const RotationType& rotation)
*/
template<typename Scalar, int Dim, int Mode, int Options>
Transform<Scalar,Dim,Mode,Options>&
-Transform<Scalar,Dim,Mode,Options>::shear(Scalar sx, Scalar sy)
+Transform<Scalar,Dim,Mode,Options>::shear(const Scalar& sx, const Scalar& sy)
{
EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
@@ -925,7 +925,7 @@ Transform<Scalar,Dim,Mode,Options>::shear(Scalar sx, Scalar sy)
*/
template<typename Scalar, int Dim, int Mode, int Options>
Transform<Scalar,Dim,Mode,Options>&
-Transform<Scalar,Dim,Mode,Options>::preshear(Scalar sx, Scalar sy)
+Transform<Scalar,Dim,Mode,Options>::preshear(const Scalar& sx, const Scalar& sy)
{
EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
diff --git a/Eigen/src/Geometry/Umeyama.h b/Eigen/src/Geometry/Umeyama.h
index ac0939cde..5e20662f8 100644
--- a/Eigen/src/Geometry/Umeyama.h
+++ b/Eigen/src/Geometry/Umeyama.h
@@ -113,7 +113,7 @@ umeyama(const MatrixBase<Derived>& src, const MatrixBase<OtherDerived>& dst, boo
const Index n = src.cols(); // number of measurements
// required for demeaning ...
- const RealScalar one_over_n = 1 / static_cast<RealScalar>(n);
+ const RealScalar one_over_n = RealScalar(1) / static_cast<RealScalar>(n);
// computation of mean
const VectorType src_mean = src.rowwise().sum() * one_over_n;
@@ -136,16 +136,16 @@ umeyama(const MatrixBase<Derived>& src, const MatrixBase<OtherDerived>& dst, boo
// Eq. (39)
VectorType S = VectorType::Ones(m);
- if (sigma.determinant()<0) S(m-1) = -1;
+ if (sigma.determinant()<Scalar(0)) S(m-1) = Scalar(-1);
// Eq. (40) and (43)
const VectorType& d = svd.singularValues();
Index rank = 0; for (Index i=0; i<m; ++i) if (!internal::isMuchSmallerThan(d.coeff(i),d.coeff(0))) ++rank;
if (rank == m-1) {
- if ( svd.matrixU().determinant() * svd.matrixV().determinant() > 0 ) {
+ if ( svd.matrixU().determinant() * svd.matrixV().determinant() > Scalar(0) ) {
Rt.block(0,0,m,m).noalias() = svd.matrixU()*svd.matrixV().transpose();
} else {
- const Scalar s = S(m-1); S(m-1) = -1;
+ const Scalar s = S(m-1); S(m-1) = Scalar(-1);
Rt.block(0,0,m,m).noalias() = svd.matrixU() * S.asDiagonal() * svd.matrixV().transpose();
S(m-1) = s;
}
@@ -153,16 +153,21 @@ umeyama(const MatrixBase<Derived>& src, const MatrixBase<OtherDerived>& dst, boo
Rt.block(0,0,m,m).noalias() = svd.matrixU() * S.asDiagonal() * svd.matrixV().transpose();
}
- // Eq. (42)
- const Scalar c = 1/src_var * svd.singularValues().dot(S);
+ if (with_scaling)
+ {
+ // Eq. (42)
+ const Scalar c = Scalar(1)/src_var * svd.singularValues().dot(S);
- // Eq. (41)
- // Note that we first assign dst_mean to the destination so that there no need
- // for a temporary.
- Rt.col(m).head(m) = dst_mean;
- Rt.col(m).head(m).noalias() -= c*Rt.topLeftCorner(m,m)*src_mean;
-
- if (with_scaling) Rt.block(0,0,m,m) *= c;
+ // Eq. (41)
+ Rt.col(m).head(m) = dst_mean;
+ Rt.col(m).head(m).noalias() -= c*Rt.topLeftCorner(m,m)*src_mean;
+ Rt.block(0,0,m,m) *= c;
+ }
+ else
+ {
+ Rt.col(m).head(m) = dst_mean;
+ Rt.col(m).head(m).noalias() -= Rt.topLeftCorner(m,m)*src_mean;
+ }
return Rt;
}
diff --git a/Eigen/src/Householder/BlockHouseholder.h b/Eigen/src/Householder/BlockHouseholder.h
index 1991c6527..60dbea5f5 100644
--- a/Eigen/src/Householder/BlockHouseholder.h
+++ b/Eigen/src/Householder/BlockHouseholder.h
@@ -48,7 +48,7 @@ void apply_block_householder_on_the_left(MatrixType& mat, const VectorsType& vec
typedef typename MatrixType::Index Index;
enum { TFactorSize = MatrixType::ColsAtCompileTime };
Index nbVecs = vectors.cols();
- Matrix<typename MatrixType::Scalar, TFactorSize, TFactorSize> T(nbVecs,nbVecs);
+ Matrix<typename MatrixType::Scalar, TFactorSize, TFactorSize, ColMajor> T(nbVecs,nbVecs);
make_block_householder_triangular_factor(T, vectors, hCoeffs);
const TriangularView<const VectorsType, UnitLower>& V(vectors);
diff --git a/Eigen/src/Householder/Householder.h b/Eigen/src/Householder/Householder.h
index 3f64b7dde..32112af9b 100644
--- a/Eigen/src/Householder/Householder.h
+++ b/Eigen/src/Householder/Householder.h
@@ -67,25 +67,28 @@ void MatrixBase<Derived>::makeHouseholder(
Scalar& tau,
RealScalar& beta) const
{
+ using std::sqrt;
+ using numext::conj;
+
EIGEN_STATIC_ASSERT_VECTOR_ONLY(EssentialPart)
VectorBlock<const Derived, EssentialPart::SizeAtCompileTime> tail(derived(), 1, size()-1);
RealScalar tailSqNorm = size()==1 ? RealScalar(0) : tail.squaredNorm();
Scalar c0 = coeff(0);
- if(tailSqNorm == RealScalar(0) && internal::imag(c0)==RealScalar(0))
+ if(tailSqNorm == RealScalar(0) && numext::imag(c0)==RealScalar(0))
{
tau = RealScalar(0);
- beta = internal::real(c0);
+ beta = numext::real(c0);
essential.setZero();
}
else
{
- beta = internal::sqrt(internal::abs2(c0) + tailSqNorm);
- if (internal::real(c0)>=RealScalar(0))
+ beta = sqrt(numext::abs2(c0) + tailSqNorm);
+ if (numext::real(c0)>=RealScalar(0))
beta = -beta;
essential = tail / (c0 - beta);
- tau = internal::conj((beta - c0) / beta);
+ tau = conj((beta - c0) / beta);
}
}
diff --git a/Eigen/src/Householder/HouseholderSequence.h b/Eigen/src/Householder/HouseholderSequence.h
index 1e71e16a7..d800ca1fa 100644
--- a/Eigen/src/Householder/HouseholderSequence.h
+++ b/Eigen/src/Householder/HouseholderSequence.h
@@ -112,6 +112,9 @@ template<typename OtherScalarType, typename MatrixType> struct matrix_type_times
template<typename VectorsType, typename CoeffsType, int Side> class HouseholderSequence
: public EigenBase<HouseholderSequence<VectorsType,CoeffsType,Side> >
{
+ typedef typename internal::hseq_side_dependent_impl<VectorsType,CoeffsType,Side>::EssentialVectorType EssentialVectorType;
+
+ public:
enum {
RowsAtCompileTime = internal::traits<HouseholderSequence>::RowsAtCompileTime,
ColsAtCompileTime = internal::traits<HouseholderSequence>::ColsAtCompileTime,
@@ -121,13 +124,10 @@ template<typename VectorsType, typename CoeffsType, int Side> class HouseholderS
typedef typename internal::traits<HouseholderSequence>::Scalar Scalar;
typedef typename VectorsType::Index Index;
- typedef typename internal::hseq_side_dependent_impl<VectorsType,CoeffsType,Side>::EssentialVectorType
- EssentialVectorType;
-
- public:
-
typedef HouseholderSequence<
- VectorsType,
+ typename internal::conditional<NumTraits<Scalar>::IsComplex,
+ typename internal::remove_all<typename VectorsType::ConjugateReturnType>::type,
+ VectorsType>::type,
typename internal::conditional<NumTraits<Scalar>::IsComplex,
typename internal::remove_all<typename CoeffsType::ConjugateReturnType>::type,
CoeffsType>::type,
@@ -208,7 +208,7 @@ template<typename VectorsType, typename CoeffsType, int Side> class HouseholderS
/** \brief Complex conjugate of the Householder sequence. */
ConjugateReturnType conjugate() const
{
- return ConjugateReturnType(m_vectors, m_coeffs.conjugate())
+ return ConjugateReturnType(m_vectors.conjugate(), m_coeffs.conjugate())
.setTrans(m_trans)
.setLength(m_length)
.setShift(m_shift);
diff --git a/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h b/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h
index 126341be8..2b9fb7f88 100644
--- a/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h
+++ b/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h
@@ -39,10 +39,17 @@ bool bicgstab(const MatrixType& mat, const Rhs& rhs, Dest& x,
int maxIters = iters;
int n = mat.cols();
+ x = precond.solve(x);
VectorType r = rhs - mat * x;
VectorType r0 = r;
RealScalar r0_sqnorm = r0.squaredNorm();
+ RealScalar rhs_sqnorm = rhs.squaredNorm();
+ if(rhs_sqnorm == 0)
+ {
+ x.setZero();
+ return true;
+ }
Scalar rho = 1;
Scalar alpha = 1;
Scalar w = 1;
@@ -54,14 +61,24 @@ bool bicgstab(const MatrixType& mat, const Rhs& rhs, Dest& x,
VectorType s(n), t(n);
RealScalar tol2 = tol*tol;
+ RealScalar eps2 = NumTraits<Scalar>::epsilon()*NumTraits<Scalar>::epsilon();
int i = 0;
+ int restarts = 0;
- while ( r.squaredNorm()/r0_sqnorm > tol2 && i<maxIters )
+ while ( r.squaredNorm()/rhs_sqnorm > tol2 && i<maxIters )
{
Scalar rho_old = rho;
rho = r0.dot(r);
- if (rho == Scalar(0)) return false; /* New search directions cannot be found */
+ if (abs(rho) < eps2*r0_sqnorm)
+ {
+ // The new residual vector became too orthogonal to the arbitrarily choosen direction r0
+ // Let's restart with a new r0:
+ r0 = r;
+ rho = r0_sqnorm = r.squaredNorm();
+ if(restarts++ == 0)
+ i = 0;
+ }
Scalar beta = (rho/rho_old) * (alpha / w);
p = r + beta * (p - w * v);
@@ -75,12 +92,16 @@ bool bicgstab(const MatrixType& mat, const Rhs& rhs, Dest& x,
z = precond.solve(s);
t.noalias() = mat * z;
- w = t.dot(s) / t.squaredNorm();
+ RealScalar tmp = t.squaredNorm();
+ if(tmp>RealScalar(0))
+ w = t.dot(s) / tmp;
+ else
+ w = Scalar(0);
x += alpha * y + w * z;
r = s - w * t;
++i;
}
- tol_error = sqrt(r.squaredNorm()/r0_sqnorm);
+ tol_error = sqrt(r.squaredNorm()/rhs_sqnorm);
iters = i;
return true;
}
@@ -223,7 +244,8 @@ public:
template<typename Rhs,typename Dest>
void _solve(const Rhs& b, Dest& x) const
{
- x.setZero();
+// x.setZero();
+ x = b;
_solveWithGuess(b,x);
}
diff --git a/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h b/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h
index f64f2534d..a74a8155e 100644
--- a/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h
+++ b/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h
@@ -41,15 +41,29 @@ void conjugate_gradient(const MatrixType& mat, const Rhs& rhs, Dest& x,
int n = mat.cols();
VectorType residual = rhs - mat * x; //initial residual
- VectorType p(n);
+ RealScalar rhsNorm2 = rhs.squaredNorm();
+ if(rhsNorm2 == 0)
+ {
+ x.setZero();
+ iters = 0;
+ tol_error = 0;
+ return;
+ }
+ RealScalar threshold = tol*tol*rhsNorm2;
+ RealScalar residualNorm2 = residual.squaredNorm();
+ if (residualNorm2 < threshold)
+ {
+ iters = 0;
+ tol_error = sqrt(residualNorm2 / rhsNorm2);
+ return;
+ }
+
+ VectorType p(n);
p = precond.solve(residual); //initial search direction
VectorType z(n), tmp(n);
- RealScalar absNew = internal::real(residual.dot(p)); // the square of the absolute value of r scaled by invM
- RealScalar rhsNorm2 = rhs.squaredNorm();
- RealScalar residualNorm2 = 0;
- RealScalar threshold = tol*tol*rhsNorm2;
+ RealScalar absNew = numext::real(residual.dot(p)); // the square of the absolute value of r scaled by invM
int i = 0;
while(i < maxIters)
{
@@ -66,7 +80,7 @@ void conjugate_gradient(const MatrixType& mat, const Rhs& rhs, Dest& x,
z = precond.solve(residual); // approximately solve for "A z = residual"
RealScalar absOld = absNew;
- absNew = internal::real(residual.dot(z)); // update the absolute value of r
+ absNew = numext::real(residual.dot(z)); // update the absolute value of r
RealScalar beta = absNew / absOld; // calculate the Gram-Schmidt value used to create the new search direction
p = z + beta * p; // update search direction
i++;
diff --git a/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h b/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h
index 224304f0e..b55afc136 100644
--- a/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h
+++ b/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h
@@ -10,36 +10,88 @@
#ifndef EIGEN_INCOMPLETE_LUT_H
#define EIGEN_INCOMPLETE_LUT_H
+
namespace Eigen {
-/**
- * \brief Incomplete LU factorization with dual-threshold strategy
- * During the numerical factorization, two dropping rules are used :
- * 1) any element whose magnitude is less than some tolerance is dropped.
- * This tolerance is obtained by multiplying the input tolerance @p droptol
- * by the average magnitude of all the original elements in the current row.
- * 2) After the elimination of the row, only the @p fill largest elements in
- * the L part and the @p fill largest elements in the U part are kept
- * (in addition to the diagonal element ). Note that @p fill is computed from
- * the input parameter @p fillfactor which is used the ratio to control the fill_in
- * relatively to the initial number of nonzero elements.
- *
- * The two extreme cases are when @p droptol=0 (to keep all the @p fill*2 largest elements)
- * and when @p fill=n/2 with @p droptol being different to zero.
- *
- * References : Yousef Saad, ILUT: A dual threshold incomplete LU factorization,
- * Numerical Linear Algebra with Applications, 1(4), pp 387-402, 1994.
- *
- * NOTE : The following implementation is derived from the ILUT implementation
- * in the SPARSKIT package, Copyright (C) 2005, the Regents of the University of Minnesota
- * released under the terms of the GNU LGPL:
- * http://www-users.cs.umn.edu/~saad/software/SPARSKIT/README
- * However, Yousef Saad gave us permission to relicense his ILUT code to MPL2.
- * See the Eigen mailing list archive, thread: ILUT, date: July 8, 2012:
- * http://listengine.tuxfamily.org/lists.tuxfamily.org/eigen/2012/07/msg00064.html
- * alternatively, on GMANE:
- * http://comments.gmane.org/gmane.comp.lib.eigen/3302
- */
+namespace internal {
+
+/** \internal
+ * Compute a quick-sort split of a vector
+ * On output, the vector row is permuted such that its elements satisfy
+ * abs(row(i)) >= abs(row(ncut)) if i<ncut
+ * abs(row(i)) <= abs(row(ncut)) if i>ncut
+ * \param row The vector of values
+ * \param ind The array of index for the elements in @p row
+ * \param ncut The number of largest elements to keep
+ **/
+template <typename VectorV, typename VectorI, typename Index>
+Index QuickSplit(VectorV &row, VectorI &ind, Index ncut)
+{
+ typedef typename VectorV::RealScalar RealScalar;
+ using std::swap;
+ using std::abs;
+ Index mid;
+ Index n = row.size(); /* length of the vector */
+ Index first, last ;
+
+ ncut--; /* to fit the zero-based indices */
+ first = 0;
+ last = n-1;
+ if (ncut < first || ncut > last ) return 0;
+
+ do {
+ mid = first;
+ RealScalar abskey = abs(row(mid));
+ for (Index j = first + 1; j <= last; j++) {
+ if ( abs(row(j)) > abskey) {
+ ++mid;
+ swap(row(mid), row(j));
+ swap(ind(mid), ind(j));
+ }
+ }
+ /* Interchange for the pivot element */
+ swap(row(mid), row(first));
+ swap(ind(mid), ind(first));
+
+ if (mid > ncut) last = mid - 1;
+ else if (mid < ncut ) first = mid + 1;
+ } while (mid != ncut );
+
+ return 0; /* mid is equal to ncut */
+}
+
+}// end namespace internal
+
+/** \ingroup IterativeLinearSolvers_Module
+ * \class IncompleteLUT
+ * \brief Incomplete LU factorization with dual-threshold strategy
+ *
+ * During the numerical factorization, two dropping rules are used :
+ * 1) any element whose magnitude is less than some tolerance is dropped.
+ * This tolerance is obtained by multiplying the input tolerance @p droptol
+ * by the average magnitude of all the original elements in the current row.
+ * 2) After the elimination of the row, only the @p fill largest elements in
+ * the L part and the @p fill largest elements in the U part are kept
+ * (in addition to the diagonal element ). Note that @p fill is computed from
+ * the input parameter @p fillfactor which is used the ratio to control the fill_in
+ * relatively to the initial number of nonzero elements.
+ *
+ * The two extreme cases are when @p droptol=0 (to keep all the @p fill*2 largest elements)
+ * and when @p fill=n/2 with @p droptol being different to zero.
+ *
+ * References : Yousef Saad, ILUT: A dual threshold incomplete LU factorization,
+ * Numerical Linear Algebra with Applications, 1(4), pp 387-402, 1994.
+ *
+ * NOTE : The following implementation is derived from the ILUT implementation
+ * in the SPARSKIT package, Copyright (C) 2005, the Regents of the University of Minnesota
+ * released under the terms of the GNU LGPL:
+ * http://www-users.cs.umn.edu/~saad/software/SPARSKIT/README
+ * However, Yousef Saad gave us permission to relicense his ILUT code to MPL2.
+ * See the Eigen mailing list archive, thread: ILUT, date: July 8, 2012:
+ * http://listengine.tuxfamily.org/lists.tuxfamily.org/eigen/2012/07/msg00064.html
+ * alternatively, on GMANE:
+ * http://comments.gmane.org/gmane.comp.lib.eigen/3302
+ */
template <typename _Scalar>
class IncompleteLUT : internal::noncopyable
{
@@ -59,7 +111,7 @@ class IncompleteLUT : internal::noncopyable
{}
template<typename MatrixType>
- IncompleteLUT(const MatrixType& mat, RealScalar droptol=NumTraits<Scalar>::dummy_precision(), int fillfactor = 10)
+ IncompleteLUT(const MatrixType& mat, const RealScalar& droptol=NumTraits<Scalar>::dummy_precision(), int fillfactor = 10)
: m_droptol(droptol),m_fillfactor(fillfactor),
m_analysisIsOk(false),m_factorizationIsOk(false),m_isInitialized(false)
{
@@ -98,12 +150,11 @@ class IncompleteLUT : internal::noncopyable
{
analyzePattern(amat);
factorize(amat);
- eigen_assert(m_factorizationIsOk == true);
- m_isInitialized = true;
+ m_isInitialized = m_factorizationIsOk;
return *this;
}
- void setDroptol(RealScalar droptol);
+ void setDroptol(const RealScalar& droptol);
void setFillfactor(int fillfactor);
template<typename Rhs, typename Dest>
@@ -126,10 +177,6 @@ class IncompleteLUT : internal::noncopyable
protected:
- template <typename VectorV, typename VectorI>
- int QuickSplit(VectorV &row, VectorI &ind, int ncut);
-
-
/** keeps off-diagonal entries; drops diagonal entries */
struct keep_diag {
inline bool operator() (const Index& row, const Index& col, const Scalar&) const
@@ -156,7 +203,7 @@ protected:
* \param droptol Drop any element whose magnitude is less than this tolerance
**/
template<typename Scalar>
-void IncompleteLUT<Scalar>::setDroptol(RealScalar droptol)
+void IncompleteLUT<Scalar>::setDroptol(const RealScalar& droptol)
{
this->m_droptol = droptol;
}
@@ -171,51 +218,6 @@ void IncompleteLUT<Scalar>::setFillfactor(int fillfactor)
this->m_fillfactor = fillfactor;
}
-
-/**
- * Compute a quick-sort split of a vector
- * On output, the vector row is permuted such that its elements satisfy
- * abs(row(i)) >= abs(row(ncut)) if i<ncut
- * abs(row(i)) <= abs(row(ncut)) if i>ncut
- * \param row The vector of values
- * \param ind The array of index for the elements in @p row
- * \param ncut The number of largest elements to keep
- **/
-template <typename Scalar>
-template <typename VectorV, typename VectorI>
-int IncompleteLUT<Scalar>::QuickSplit(VectorV &row, VectorI &ind, int ncut)
-{
- using std::swap;
- int mid;
- int n = row.size(); /* length of the vector */
- int first, last ;
-
- ncut--; /* to fit the zero-based indices */
- first = 0;
- last = n-1;
- if (ncut < first || ncut > last ) return 0;
-
- do {
- mid = first;
- RealScalar abskey = std::abs(row(mid));
- for (int j = first + 1; j <= last; j++) {
- if ( std::abs(row(j)) > abskey) {
- ++mid;
- swap(row(mid), row(j));
- swap(ind(mid), ind(j));
- }
- }
- /* Interchange for the pivot element */
- swap(row(mid), row(first));
- swap(ind(mid), ind(first));
-
- if (mid > ncut) last = mid - 1;
- else if (mid < ncut ) first = mid + 1;
- } while (mid != ncut );
-
- return 0; /* mid is equal to ncut */
-}
-
template <typename Scalar>
template<typename _MatrixType>
void IncompleteLUT<Scalar>::analyzePattern(const _MatrixType& amat)
@@ -244,7 +246,7 @@ void IncompleteLUT<Scalar>::factorize(const _MatrixType& amat)
using std::abs;
eigen_assert((amat.rows() == amat.cols()) && "The factorization should be done on a square matrix");
- int n = amat.cols(); // Size of the matrix
+ Index n = amat.cols(); // Size of the matrix
m_lu.resize(n,n);
// Declare Working vectors and variables
Vector u(n) ; // real values of the row -- maximum size is n --
@@ -262,21 +264,21 @@ void IncompleteLUT<Scalar>::factorize(const _MatrixType& amat)
u.fill(0);
// number of largest elements to keep in each row:
- int fill_in = static_cast<int> (amat.nonZeros()*m_fillfactor)/n+1;
+ Index fill_in = static_cast<Index> (amat.nonZeros()*m_fillfactor)/n+1;
if (fill_in > n) fill_in = n;
// number of largest nonzero elements to keep in the L and the U part of the current row:
- int nnzL = fill_in/2;
- int nnzU = nnzL;
+ Index nnzL = fill_in/2;
+ Index nnzU = nnzL;
m_lu.reserve(n * (nnzL + nnzU + 1));
// global loop over the rows of the sparse matrix
- for (int ii = 0; ii < n; ii++)
+ for (Index ii = 0; ii < n; ii++)
{
// 1 - copy the lower and the upper part of the row i of mat in the working vector u
- int sizeu = 1; // number of nonzero elements in the upper part of the current row
- int sizel = 0; // number of nonzero elements in the lower part of the current row
+ Index sizeu = 1; // number of nonzero elements in the upper part of the current row
+ Index sizel = 0; // number of nonzero elements in the lower part of the current row
ju(ii) = ii;
u(ii) = 0;
jr(ii) = ii;
@@ -285,7 +287,7 @@ void IncompleteLUT<Scalar>::factorize(const _MatrixType& amat)
typename FactorType::InnerIterator j_it(mat, ii); // Iterate through the current row ii
for (; j_it; ++j_it)
{
- int k = j_it.index();
+ Index k = j_it.index();
if (k < ii)
{
// copy the lower part
@@ -301,13 +303,13 @@ void IncompleteLUT<Scalar>::factorize(const _MatrixType& amat)
else
{
// copy the upper part
- int jpos = ii + sizeu;
+ Index jpos = ii + sizeu;
ju(jpos) = k;
u(jpos) = j_it.value();
jr(k) = jpos;
++sizeu;
}
- rownorm += internal::abs2(j_it.value());
+ rownorm += numext::abs2(j_it.value());
}
// 2 - detect possible zero row
@@ -320,19 +322,19 @@ void IncompleteLUT<Scalar>::factorize(const _MatrixType& amat)
rownorm = sqrt(rownorm);
// 3 - eliminate the previous nonzero rows
- int jj = 0;
- int len = 0;
+ Index jj = 0;
+ Index len = 0;
while (jj < sizel)
{
// In order to eliminate in the correct order,
// we must select first the smallest column index among ju(jj:sizel)
- int k;
- int minrow = ju.segment(jj,sizel-jj).minCoeff(&k); // k is relative to the segment
+ Index k;
+ Index minrow = ju.segment(jj,sizel-jj).minCoeff(&k); // k is relative to the segment
k += jj;
if (minrow != ju(jj))
{
// swap the two locations
- int j = ju(jj);
+ Index j = ju(jj);
swap(ju(jj), ju(k));
jr(minrow) = jj; jr(j) = k;
swap(u(jj), u(k));
@@ -358,11 +360,11 @@ void IncompleteLUT<Scalar>::factorize(const _MatrixType& amat)
for (; ki_it; ++ki_it)
{
Scalar prod = fact * ki_it.value();
- int j = ki_it.index();
- int jpos = jr(j);
+ Index j = ki_it.index();
+ Index jpos = jr(j);
if (jpos == -1) // fill-in element
{
- int newpos;
+ Index newpos;
if (j >= ii) // dealing with the upper part
{
newpos = ii + sizeu;
@@ -391,7 +393,7 @@ void IncompleteLUT<Scalar>::factorize(const _MatrixType& amat)
} // end of the elimination on the row ii
// reset the upper part of the pointer jr to zero
- for(int k = 0; k <sizeu; k++) jr(ju(ii+k)) = -1;
+ for(Index k = 0; k <sizeu; k++) jr(ju(ii+k)) = -1;
// 4 - partially sort and insert the elements in the m_lu matrix
@@ -400,11 +402,11 @@ void IncompleteLUT<Scalar>::factorize(const _MatrixType& amat)
len = (std::min)(sizel, nnzL);
typename Vector::SegmentReturnType ul(u.segment(0, sizel));
typename VectorXi::SegmentReturnType jul(ju.segment(0, sizel));
- QuickSplit(ul, jul, len);
+ internal::QuickSplit(ul, jul, len);
// store the largest m_fill elements of the L part
m_lu.startVec(ii);
- for(int k = 0; k < len; k++)
+ for(Index k = 0; k < len; k++)
m_lu.insertBackByOuterInnerUnordered(ii,ju(k)) = u(k);
// store the diagonal element
@@ -416,7 +418,7 @@ void IncompleteLUT<Scalar>::factorize(const _MatrixType& amat)
// sort the U-part of the row
// apply the dropping rule first
len = 0;
- for(int k = 1; k < sizeu; k++)
+ for(Index k = 1; k < sizeu; k++)
{
if(abs(u(ii+k)) > m_droptol * rownorm )
{
@@ -429,10 +431,10 @@ void IncompleteLUT<Scalar>::factorize(const _MatrixType& amat)
len = (std::min)(sizeu, nnzU);
typename Vector::SegmentReturnType uu(u.segment(ii+1, sizeu-1));
typename VectorXi::SegmentReturnType juu(ju.segment(ii+1, sizeu-1));
- QuickSplit(uu, juu, len);
+ internal::QuickSplit(uu, juu, len);
// store the largest elements of the U part
- for(int k = ii + 1; k < ii + len; k++)
+ for(Index k = ii + 1; k < ii + len; k++)
m_lu.insertBackByOuterInnerUnordered(ii,ju(k)) = u(k);
}
@@ -463,4 +465,3 @@ struct solve_retval<IncompleteLUT<_MatrixType>, Rhs>
} // end namespace Eigen
#endif // EIGEN_INCOMPLETE_LUT_H
-
diff --git a/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h b/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h
index 11706ceba..2036922d6 100644
--- a/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h
+++ b/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h
@@ -120,7 +120,7 @@ public:
RealScalar tolerance() const { return m_tolerance; }
/** Sets the tolerance threshold used by the stopping criteria */
- Derived& setTolerance(RealScalar tolerance)
+ Derived& setTolerance(const RealScalar& tolerance)
{
m_tolerance = tolerance;
return derived();
diff --git a/Eigen/src/Jacobi/Jacobi.h b/Eigen/src/Jacobi/Jacobi.h
index a9c17dcdf..956f72d57 100644
--- a/Eigen/src/Jacobi/Jacobi.h
+++ b/Eigen/src/Jacobi/Jacobi.h
@@ -50,19 +50,20 @@ template<typename Scalar> class JacobiRotation
/** Concatenates two planar rotation */
JacobiRotation operator*(const JacobiRotation& other)
{
- return JacobiRotation(m_c * other.m_c - internal::conj(m_s) * other.m_s,
- internal::conj(m_c * internal::conj(other.m_s) + internal::conj(m_s) * internal::conj(other.m_c)));
+ using numext::conj;
+ return JacobiRotation(m_c * other.m_c - conj(m_s) * other.m_s,
+ conj(m_c * conj(other.m_s) + conj(m_s) * conj(other.m_c)));
}
/** Returns the transposed transformation */
- JacobiRotation transpose() const { return JacobiRotation(m_c, -internal::conj(m_s)); }
+ JacobiRotation transpose() const { using numext::conj; return JacobiRotation(m_c, -conj(m_s)); }
/** Returns the adjoint transformation */
- JacobiRotation adjoint() const { return JacobiRotation(internal::conj(m_c), -m_s); }
+ JacobiRotation adjoint() const { using numext::conj; return JacobiRotation(conj(m_c), -m_s); }
template<typename Derived>
bool makeJacobi(const MatrixBase<Derived>&, typename Derived::Index p, typename Derived::Index q);
- bool makeJacobi(RealScalar x, Scalar y, RealScalar z);
+ bool makeJacobi(const RealScalar& x, const Scalar& y, const RealScalar& z);
void makeGivens(const Scalar& p, const Scalar& q, Scalar* z=0);
@@ -79,8 +80,10 @@ template<typename Scalar> class JacobiRotation
* \sa MatrixBase::makeJacobi(const MatrixBase<Derived>&, Index, Index), MatrixBase::applyOnTheLeft(), MatrixBase::applyOnTheRight()
*/
template<typename Scalar>
-bool JacobiRotation<Scalar>::makeJacobi(RealScalar x, Scalar y, RealScalar z)
+bool JacobiRotation<Scalar>::makeJacobi(const RealScalar& x, const Scalar& y, const RealScalar& z)
{
+ using std::sqrt;
+ using std::abs;
typedef typename NumTraits<Scalar>::Real RealScalar;
if(y == Scalar(0))
{
@@ -90,8 +93,8 @@ bool JacobiRotation<Scalar>::makeJacobi(RealScalar x, Scalar y, RealScalar z)
}
else
{
- RealScalar tau = (x-z)/(RealScalar(2)*internal::abs(y));
- RealScalar w = internal::sqrt(internal::abs2(tau) + RealScalar(1));
+ RealScalar tau = (x-z)/(RealScalar(2)*abs(y));
+ RealScalar w = sqrt(numext::abs2(tau) + RealScalar(1));
RealScalar t;
if(tau>RealScalar(0))
{
@@ -102,8 +105,8 @@ bool JacobiRotation<Scalar>::makeJacobi(RealScalar x, Scalar y, RealScalar z)
t = RealScalar(1) / (tau - w);
}
RealScalar sign_t = t > RealScalar(0) ? RealScalar(1) : RealScalar(-1);
- RealScalar n = RealScalar(1) / internal::sqrt(internal::abs2(t)+RealScalar(1));
- m_s = - sign_t * (internal::conj(y) / internal::abs(y)) * internal::abs(t) * n;
+ RealScalar n = RealScalar(1) / sqrt(numext::abs2(t)+RealScalar(1));
+ m_s = - sign_t * (numext::conj(y) / abs(y)) * abs(t) * n;
m_c = n;
return true;
}
@@ -122,7 +125,7 @@ template<typename Scalar>
template<typename Derived>
inline bool JacobiRotation<Scalar>::makeJacobi(const MatrixBase<Derived>& m, typename Derived::Index p, typename Derived::Index q)
{
- return makeJacobi(internal::real(m.coeff(p,p)), m.coeff(p,q), internal::real(m.coeff(q,q)));
+ return makeJacobi(numext::real(m.coeff(p,p)), m.coeff(p,q), numext::real(m.coeff(q,q)));
}
/** Makes \c *this as a Givens rotation \c G such that applying \f$ G^* \f$ to the left of the vector
@@ -152,52 +155,56 @@ void JacobiRotation<Scalar>::makeGivens(const Scalar& p, const Scalar& q, Scalar
template<typename Scalar>
void JacobiRotation<Scalar>::makeGivens(const Scalar& p, const Scalar& q, Scalar* r, internal::true_type)
{
+ using std::sqrt;
+ using std::abs;
+ using numext::conj;
+
if(q==Scalar(0))
{
- m_c = internal::real(p)<0 ? Scalar(-1) : Scalar(1);
+ m_c = numext::real(p)<0 ? Scalar(-1) : Scalar(1);
m_s = 0;
if(r) *r = m_c * p;
}
else if(p==Scalar(0))
{
m_c = 0;
- m_s = -q/internal::abs(q);
- if(r) *r = internal::abs(q);
+ m_s = -q/abs(q);
+ if(r) *r = abs(q);
}
else
{
- RealScalar p1 = internal::norm1(p);
- RealScalar q1 = internal::norm1(q);
+ RealScalar p1 = numext::norm1(p);
+ RealScalar q1 = numext::norm1(q);
if(p1>=q1)
{
Scalar ps = p / p1;
- RealScalar p2 = internal::abs2(ps);
+ RealScalar p2 = numext::abs2(ps);
Scalar qs = q / p1;
- RealScalar q2 = internal::abs2(qs);
+ RealScalar q2 = numext::abs2(qs);
- RealScalar u = internal::sqrt(RealScalar(1) + q2/p2);
- if(internal::real(p)<RealScalar(0))
+ RealScalar u = sqrt(RealScalar(1) + q2/p2);
+ if(numext::real(p)<RealScalar(0))
u = -u;
m_c = Scalar(1)/u;
- m_s = -qs*internal::conj(ps)*(m_c/p2);
+ m_s = -qs*conj(ps)*(m_c/p2);
if(r) *r = p * u;
}
else
{
Scalar ps = p / q1;
- RealScalar p2 = internal::abs2(ps);
+ RealScalar p2 = numext::abs2(ps);
Scalar qs = q / q1;
- RealScalar q2 = internal::abs2(qs);
+ RealScalar q2 = numext::abs2(qs);
- RealScalar u = q1 * internal::sqrt(p2 + q2);
- if(internal::real(p)<RealScalar(0))
+ RealScalar u = q1 * sqrt(p2 + q2);
+ if(numext::real(p)<RealScalar(0))
u = -u;
- p1 = internal::abs(p);
+ p1 = abs(p);
ps = p/p1;
m_c = p1/u;
- m_s = -internal::conj(ps) * (q/u);
+ m_s = -conj(ps) * (q/u);
if(r) *r = ps * u;
}
}
@@ -207,23 +214,24 @@ void JacobiRotation<Scalar>::makeGivens(const Scalar& p, const Scalar& q, Scalar
template<typename Scalar>
void JacobiRotation<Scalar>::makeGivens(const Scalar& p, const Scalar& q, Scalar* r, internal::false_type)
{
-
+ using std::sqrt;
+ using std::abs;
if(q==Scalar(0))
{
m_c = p<Scalar(0) ? Scalar(-1) : Scalar(1);
m_s = Scalar(0);
- if(r) *r = internal::abs(p);
+ if(r) *r = abs(p);
}
else if(p==Scalar(0))
{
m_c = Scalar(0);
m_s = q<Scalar(0) ? Scalar(1) : Scalar(-1);
- if(r) *r = internal::abs(q);
+ if(r) *r = abs(q);
}
- else if(internal::abs(p) > internal::abs(q))
+ else if(abs(p) > abs(q))
{
Scalar t = q/p;
- Scalar u = internal::sqrt(Scalar(1) + internal::abs2(t));
+ Scalar u = sqrt(Scalar(1) + numext::abs2(t));
if(p<Scalar(0))
u = -u;
m_c = Scalar(1)/u;
@@ -233,7 +241,7 @@ void JacobiRotation<Scalar>::makeGivens(const Scalar& p, const Scalar& q, Scalar
else
{
Scalar t = p/q;
- Scalar u = internal::sqrt(Scalar(1) + internal::abs2(t));
+ Scalar u = sqrt(Scalar(1) + numext::abs2(t));
if(q<Scalar(0))
u = -u;
m_s = -Scalar(1)/u;
@@ -303,6 +311,11 @@ void /*EIGEN_DONT_INLINE*/ apply_rotation_in_the_plane(VectorX& _x, VectorY& _y,
Scalar* EIGEN_RESTRICT x = &_x.coeffRef(0);
Scalar* EIGEN_RESTRICT y = &_y.coeffRef(0);
+
+ OtherScalar c = j.c();
+ OtherScalar s = j.s();
+ if (c==OtherScalar(1) && s==OtherScalar(0))
+ return;
/*** dynamic-size vectorized paths ***/
@@ -316,16 +329,16 @@ void /*EIGEN_DONT_INLINE*/ apply_rotation_in_the_plane(VectorX& _x, VectorY& _y,
Index alignedStart = internal::first_aligned(y, size);
Index alignedEnd = alignedStart + ((size-alignedStart)/PacketSize)*PacketSize;
- const Packet pc = pset1<Packet>(j.c());
- const Packet ps = pset1<Packet>(j.s());
+ const Packet pc = pset1<Packet>(c);
+ const Packet ps = pset1<Packet>(s);
conj_helper<Packet,Packet,NumTraits<Scalar>::IsComplex,false> pcj;
for(Index i=0; i<alignedStart; ++i)
{
Scalar xi = x[i];
Scalar yi = y[i];
- x[i] = j.c() * xi + conj(j.s()) * yi;
- y[i] = -j.s() * xi + conj(j.c()) * yi;
+ x[i] = c * xi + numext::conj(s) * yi;
+ y[i] = -s * xi + numext::conj(c) * yi;
}
Scalar* EIGEN_RESTRICT px = x + alignedStart;
@@ -372,8 +385,8 @@ void /*EIGEN_DONT_INLINE*/ apply_rotation_in_the_plane(VectorX& _x, VectorY& _y,
{
Scalar xi = x[i];
Scalar yi = y[i];
- x[i] = j.c() * xi + conj(j.s()) * yi;
- y[i] = -j.s() * xi + conj(j.c()) * yi;
+ x[i] = c * xi + numext::conj(s) * yi;
+ y[i] = -s * xi + numext::conj(c) * yi;
}
}
@@ -382,8 +395,8 @@ void /*EIGEN_DONT_INLINE*/ apply_rotation_in_the_plane(VectorX& _x, VectorY& _y,
(VectorX::Flags & VectorY::Flags & PacketAccessBit) &&
(VectorX::Flags & VectorY::Flags & AlignedBit))
{
- const Packet pc = pset1<Packet>(j.c());
- const Packet ps = pset1<Packet>(j.s());
+ const Packet pc = pset1<Packet>(c);
+ const Packet ps = pset1<Packet>(s);
conj_helper<Packet,Packet,NumTraits<Scalar>::IsComplex,false> pcj;
Scalar* EIGEN_RESTRICT px = x;
Scalar* EIGEN_RESTRICT py = y;
@@ -405,8 +418,8 @@ void /*EIGEN_DONT_INLINE*/ apply_rotation_in_the_plane(VectorX& _x, VectorY& _y,
{
Scalar xi = *x;
Scalar yi = *y;
- *x = j.c() * xi + conj(j.s()) * yi;
- *y = -j.s() * xi + conj(j.c()) * yi;
+ *x = c * xi + numext::conj(s) * yi;
+ *y = -s * xi + numext::conj(c) * yi;
x += incrx;
y += incry;
}
diff --git a/Eigen/src/LU/Determinant.h b/Eigen/src/LU/Determinant.h
index d862c5d77..bb8e78a8a 100644
--- a/Eigen/src/LU/Determinant.h
+++ b/Eigen/src/LU/Determinant.h
@@ -91,7 +91,7 @@ template<typename Derived> struct determinant_impl<Derived, 4>
template<typename Derived>
inline typename internal::traits<Derived>::Scalar MatrixBase<Derived>::determinant() const
{
- assert(rows() == cols());
+ eigen_assert(rows() == cols());
typedef typename internal::nested<Derived,Base::RowsAtCompileTime>::type Nested;
return internal::determinant_impl<typename internal::remove_all<Nested>::type>::run(derived());
}
diff --git a/Eigen/src/LU/FullPivLU.h b/Eigen/src/LU/FullPivLU.h
index e23f96cdc..79ab6a8c8 100644
--- a/Eigen/src/LU/FullPivLU.h
+++ b/Eigen/src/LU/FullPivLU.h
@@ -20,10 +20,11 @@ namespace Eigen {
*
* \param MatrixType the type of the matrix of which we are computing the LU decomposition
*
- * This class represents a LU decomposition of any matrix, with complete pivoting: the matrix A
- * is decomposed as A = PLUQ where L is unit-lower-triangular, U is upper-triangular, and P and Q
- * are permutation matrices. This is a rank-revealing LU decomposition. The eigenvalues (diagonal
- * coefficients) of U are sorted in such a way that any zeros are at the end.
+ * This class represents a LU decomposition of any matrix, with complete pivoting: the matrix A is
+ * decomposed as \f$ A = P^{-1} L U Q^{-1} \f$ where L is unit-lower-triangular, U is
+ * upper-triangular, and P and Q are permutation matrices. This is a rank-revealing LU
+ * decomposition. The eigenvalues (diagonal coefficients) of U are sorted in such a way that any
+ * zeros are at the end.
*
* This decomposition provides the generic approach to solving systems of linear equations, computing
* the rank, invertibility, inverse, kernel, and determinant.
@@ -293,11 +294,12 @@ template<typename _MatrixType> class FullPivLU
*/
inline Index rank() const
{
+ using std::abs;
eigen_assert(m_isInitialized && "LU is not initialized.");
- RealScalar premultiplied_threshold = internal::abs(m_maxpivot) * threshold();
+ RealScalar premultiplied_threshold = abs(m_maxpivot) * threshold();
Index result = 0;
for(Index i = 0; i < m_nonzero_pivots; ++i)
- result += (internal::abs(m_lu.coeff(i,i)) > premultiplied_threshold);
+ result += (abs(m_lu.coeff(i,i)) > premultiplied_threshold);
return result;
}
@@ -416,6 +418,9 @@ FullPivLU<MatrixType>::FullPivLU(const MatrixType& matrix)
template<typename MatrixType>
FullPivLU<MatrixType>& FullPivLU<MatrixType>::compute(const MatrixType& matrix)
{
+ // the permutations are stored as int indices, so just to be sure:
+ eigen_assert(matrix.rows()<=NumTraits<int>::highest() && matrix.cols()<=NumTraits<int>::highest());
+
m_isInitialized = true;
m_lu = matrix;
@@ -507,8 +512,8 @@ typename internal::traits<MatrixType>::Scalar FullPivLU<MatrixType>::determinant
}
/** \returns the matrix represented by the decomposition,
- * i.e., it returns the product: P^{-1} L U Q^{-1}.
- * This function is provided for debug purpose. */
+ * i.e., it returns the product: \f$ P^{-1} L U Q^{-1} \f$.
+ * This function is provided for debug purposes. */
template<typename MatrixType>
MatrixType FullPivLU<MatrixType>::reconstructedMatrix() const
{
@@ -547,6 +552,7 @@ struct kernel_retval<FullPivLU<_MatrixType> >
template<typename Dest> void evalTo(Dest& dst) const
{
+ using std::abs;
const Index cols = dec().matrixLU().cols(), dimker = cols - rank();
if(dimker == 0)
{
@@ -632,6 +638,7 @@ struct image_retval<FullPivLU<_MatrixType> >
template<typename Dest> void evalTo(Dest& dst) const
{
+ using std::abs;
if(rank() == 0)
{
// The Image is just {0}, so it doesn't have a basis properly speaking, but let's
diff --git a/Eigen/src/LU/Inverse.h b/Eigen/src/LU/Inverse.h
index 39b8cdbc8..3cf887193 100644
--- a/Eigen/src/LU/Inverse.h
+++ b/Eigen/src/LU/Inverse.h
@@ -55,6 +55,7 @@ struct compute_inverse_and_det_with_check<MatrixType, ResultType, 1>
bool& invertible
)
{
+ using std::abs;
determinant = matrix.coeff(0,0);
invertible = abs(determinant) > absDeterminantThreshold;
if(invertible) result.coeffRef(0,0) = typename ResultType::Scalar(1) / determinant;
@@ -98,6 +99,7 @@ struct compute_inverse_and_det_with_check<MatrixType, ResultType, 2>
bool& invertible
)
{
+ using std::abs;
typedef typename ResultType::Scalar Scalar;
determinant = matrix.determinant();
invertible = abs(determinant) > absDeterminantThreshold;
@@ -167,6 +169,7 @@ struct compute_inverse_and_det_with_check<MatrixType, ResultType, 3>
bool& invertible
)
{
+ using std::abs;
typedef typename ResultType::Scalar Scalar;
Matrix<Scalar,3,1> cofactors_col0;
cofactors_col0.coeffRef(0) = cofactor_3x3<MatrixType,0,0>(matrix);
@@ -251,6 +254,7 @@ struct compute_inverse_and_det_with_check<MatrixType, ResultType, 4>
bool& invertible
)
{
+ using std::abs;
determinant = matrix.determinant();
invertible = abs(determinant) > absDeterminantThreshold;
if(invertible) compute_inverse<MatrixType, ResultType>::run(matrix, inverse);
@@ -327,7 +331,7 @@ inline const internal::inverse_impl<Derived> MatrixBase<Derived>::inverse() cons
* This is only for fixed-size square matrices of size up to 4x4.
*
* \param inverse Reference to the matrix in which to store the inverse.
- * \param determinant Reference to the variable in which to store the inverse.
+ * \param determinant Reference to the variable in which to store the determinant.
* \param invertible Reference to the bool variable in which to store whether the matrix is invertible.
* \param absDeterminantThreshold Optional parameter controlling the invertibility check.
* The matrix will be declared invertible if the absolute value of its
diff --git a/Eigen/src/LU/PartialPivLU.h b/Eigen/src/LU/PartialPivLU.h
index c9ff9dd5a..740ee694c 100644
--- a/Eigen/src/LU/PartialPivLU.h
+++ b/Eigen/src/LU/PartialPivLU.h
@@ -242,7 +242,7 @@ struct partial_lu_impl
const Index cols = lu.cols();
const Index size = (std::min)(rows,cols);
nb_transpositions = 0;
- int first_zero_pivot = -1;
+ Index first_zero_pivot = -1;
for(Index k = 0; k < size; ++k)
{
Index rrows = rows-k-1;
@@ -253,7 +253,7 @@ struct partial_lu_impl
= lu.col(k).tail(rows-k).cwiseAbs().maxCoeff(&row_of_biggest_in_col);
row_of_biggest_in_col += k;
- row_transpositions[k] = row_of_biggest_in_col;
+ row_transpositions[k] = PivIndex(row_of_biggest_in_col);
if(biggest_in_corner != RealScalar(0))
{
@@ -318,7 +318,7 @@ struct partial_lu_impl
}
nb_transpositions = 0;
- int first_zero_pivot = -1;
+ Index first_zero_pivot = -1;
for(Index k = 0; k < size; k+=blockSize)
{
Index bs = (std::min)(size-k,blockSize); // actual size of the block
@@ -386,6 +386,9 @@ void partial_lu_inplace(MatrixType& lu, TranspositionType& row_transpositions, t
template<typename MatrixType>
PartialPivLU<MatrixType>& PartialPivLU<MatrixType>::compute(const MatrixType& matrix)
{
+ // the row permutation is stored as int indices, so just to be sure:
+ eigen_assert(matrix.rows()<NumTraits<int>::highest());
+
m_lu = matrix;
eigen_assert(matrix.rows() == matrix.cols() && "PartialPivLU is only for square (and moreover invertible) matrices");
diff --git a/Eigen/src/MetisSupport/CMakeLists.txt b/Eigen/src/MetisSupport/CMakeLists.txt
new file mode 100644
index 000000000..2bad31416
--- /dev/null
+++ b/Eigen/src/MetisSupport/CMakeLists.txt
@@ -0,0 +1,6 @@
+FILE(GLOB Eigen_MetisSupport_SRCS "*.h")
+
+INSTALL(FILES
+ ${Eigen_MetisSupport_SRCS}
+ DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/MetisSupport COMPONENT Devel
+ )
diff --git a/Eigen/src/MetisSupport/MetisSupport.h b/Eigen/src/MetisSupport/MetisSupport.h
new file mode 100644
index 000000000..f2bbef20c
--- /dev/null
+++ b/Eigen/src/MetisSupport/MetisSupport.h
@@ -0,0 +1,137 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef METIS_SUPPORT_H
+#define METIS_SUPPORT_H
+
+namespace Eigen {
+/**
+ * Get the fill-reducing ordering from the METIS package
+ *
+ * If A is the original matrix and Ap is the permuted matrix,
+ * the fill-reducing permutation is defined as follows :
+ * Row (column) i of A is the matperm(i) row (column) of Ap.
+ * WARNING: As computed by METIS, this corresponds to the vector iperm (instead of perm)
+ */
+template <typename Index>
+class MetisOrdering
+{
+public:
+ typedef PermutationMatrix<Dynamic,Dynamic,Index> PermutationType;
+ typedef Matrix<Index,Dynamic,1> IndexVector;
+
+ template <typename MatrixType>
+ void get_symmetrized_graph(const MatrixType& A)
+ {
+ Index m = A.cols();
+ eigen_assert((A.rows() == A.cols()) && "ONLY FOR SQUARED MATRICES");
+ // Get the transpose of the input matrix
+ MatrixType At = A.transpose();
+ // Get the number of nonzeros elements in each row/col of At+A
+ Index TotNz = 0;
+ IndexVector visited(m);
+ visited.setConstant(-1);
+ for (int j = 0; j < m; j++)
+ {
+ // Compute the union structure of of A(j,:) and At(j,:)
+ visited(j) = j; // Do not include the diagonal element
+ // Get the nonzeros in row/column j of A
+ for (typename MatrixType::InnerIterator it(A, j); it; ++it)
+ {
+ Index idx = it.index(); // Get the row index (for column major) or column index (for row major)
+ if (visited(idx) != j )
+ {
+ visited(idx) = j;
+ ++TotNz;
+ }
+ }
+ //Get the nonzeros in row/column j of At
+ for (typename MatrixType::InnerIterator it(At, j); it; ++it)
+ {
+ Index idx = it.index();
+ if(visited(idx) != j)
+ {
+ visited(idx) = j;
+ ++TotNz;
+ }
+ }
+ }
+ // Reserve place for A + At
+ m_indexPtr.resize(m+1);
+ m_innerIndices.resize(TotNz);
+
+ // Now compute the real adjacency list of each column/row
+ visited.setConstant(-1);
+ Index CurNz = 0;
+ for (int j = 0; j < m; j++)
+ {
+ m_indexPtr(j) = CurNz;
+
+ visited(j) = j; // Do not include the diagonal element
+ // Add the pattern of row/column j of A to A+At
+ for (typename MatrixType::InnerIterator it(A,j); it; ++it)
+ {
+ Index idx = it.index(); // Get the row index (for column major) or column index (for row major)
+ if (visited(idx) != j )
+ {
+ visited(idx) = j;
+ m_innerIndices(CurNz) = idx;
+ CurNz++;
+ }
+ }
+ //Add the pattern of row/column j of At to A+At
+ for (typename MatrixType::InnerIterator it(At, j); it; ++it)
+ {
+ Index idx = it.index();
+ if(visited(idx) != j)
+ {
+ visited(idx) = j;
+ m_innerIndices(CurNz) = idx;
+ ++CurNz;
+ }
+ }
+ }
+ m_indexPtr(m) = CurNz;
+ }
+
+ template <typename MatrixType>
+ void operator() (const MatrixType& A, PermutationType& matperm)
+ {
+ Index m = A.cols();
+ IndexVector perm(m),iperm(m);
+ // First, symmetrize the matrix graph.
+ get_symmetrized_graph(A);
+ int output_error;
+
+ // Call the fill-reducing routine from METIS
+ output_error = METIS_NodeND(&m, m_indexPtr.data(), m_innerIndices.data(), NULL, NULL, perm.data(), iperm.data());
+
+ if(output_error != METIS_OK)
+ {
+ //FIXME The ordering interface should define a class of possible errors
+ std::cerr << "ERROR WHILE CALLING THE METIS PACKAGE \n";
+ return;
+ }
+
+ // Get the fill-reducing permutation
+ //NOTE: If Ap is the permuted matrix then perm and iperm vectors are defined as follows
+ // Row (column) i of Ap is the perm(i) row(column) of A, and row (column) i of A is the iperm(i) row(column) of Ap
+
+ matperm.resize(m);
+ for (int j = 0; j < m; j++)
+ matperm.indices()(iperm(j)) = j;
+
+ }
+
+ protected:
+ IndexVector m_indexPtr; // Pointer to the adjacenccy list of each row/column
+ IndexVector m_innerIndices; // Adjacency list
+};
+
+}// end namespace eigen
+#endif
diff --git a/Eigen/src/OrderingMethods/Amd.h b/Eigen/src/OrderingMethods/Amd.h
index ce04852b8..41b4fd7e3 100644
--- a/Eigen/src/OrderingMethods/Amd.h
+++ b/Eigen/src/OrderingMethods/Amd.h
@@ -2,10 +2,6 @@
// for linear algebra.
//
// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// This Source Code Form is subject to the terms of the Mozilla
-// Public License v. 2.0. If a copy of the MPL was not distributed
-// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
/*
@@ -86,6 +82,7 @@ Index cs_tdfs(Index j, Index k, Index *head, const Index *next, Index *post, Ind
/** \internal
+ * \ingroup OrderingMethods_Module
* Approximate minimum degree ordering algorithm.
* \returns the permutation P reducing the fill-in of the input matrix \a C
* The input matrix \a C must be a selfadjoint compressed column major SparseMatrix object. Both the upper and lower parts have to be stored, but the diagonal entries are optional.
@@ -94,7 +91,6 @@ template<typename Scalar, typename Index>
void minimum_degree_ordering(SparseMatrix<Scalar,ColMajor,Index>& C, PermutationMatrix<Dynamic,Dynamic,Index>& perm)
{
using std::sqrt;
- typedef SparseMatrix<Scalar,ColMajor,Index> CCS;
int d, dk, dext, lemax = 0, e, elenk, eln, i, j, k, k1,
k2, k3, jlast, ln, dense, nzmax, mindeg = 0, nvi, nvj, nvk, mark, wnvi,
diff --git a/Eigen/src/OrderingMethods/Eigen_Colamd.h b/Eigen/src/OrderingMethods/Eigen_Colamd.h
new file mode 100644
index 000000000..44548f660
--- /dev/null
+++ b/Eigen/src/OrderingMethods/Eigen_Colamd.h
@@ -0,0 +1,1850 @@
+// // This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Desire Nuentsa Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+// This file is modified from the colamd/symamd library. The copyright is below
+
+// The authors of the code itself are Stefan I. Larimore and Timothy A.
+// Davis (davis@cise.ufl.edu), University of Florida. The algorithm was
+// developed in collaboration with John Gilbert, Xerox PARC, and Esmond
+// Ng, Oak Ridge National Laboratory.
+//
+// Date:
+//
+// September 8, 2003. Version 2.3.
+//
+// Acknowledgements:
+//
+// This work was supported by the National Science Foundation, under
+// grants DMS-9504974 and DMS-9803599.
+//
+// Notice:
+//
+// Copyright (c) 1998-2003 by the University of Florida.
+// All Rights Reserved.
+//
+// THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
+// EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+//
+// Permission is hereby granted to use, copy, modify, and/or distribute
+// this program, provided that the Copyright, this License, and the
+// Availability of the original version is retained on all copies and made
+// accessible to the end-user of any code or package that includes COLAMD
+// or any modified version of COLAMD.
+//
+// Availability:
+//
+// The colamd/symamd library is available at
+//
+// http://www.cise.ufl.edu/research/sparse/colamd/
+
+// This is the http://www.cise.ufl.edu/research/sparse/colamd/colamd.h
+// file. It is required by the colamd.c, colamdmex.c, and symamdmex.c
+// files, and by any C code that calls the routines whose prototypes are
+// listed below, or that uses the colamd/symamd definitions listed below.
+
+#ifndef EIGEN_COLAMD_H
+#define EIGEN_COLAMD_H
+
+namespace internal {
+/* Ensure that debugging is turned off: */
+#ifndef COLAMD_NDEBUG
+#define COLAMD_NDEBUG
+#endif /* NDEBUG */
+/* ========================================================================== */
+/* === Knob and statistics definitions ====================================== */
+/* ========================================================================== */
+
+/* size of the knobs [ ] array. Only knobs [0..1] are currently used. */
+#define COLAMD_KNOBS 20
+
+/* number of output statistics. Only stats [0..6] are currently used. */
+#define COLAMD_STATS 20
+
+/* knobs [0] and stats [0]: dense row knob and output statistic. */
+#define COLAMD_DENSE_ROW 0
+
+/* knobs [1] and stats [1]: dense column knob and output statistic. */
+#define COLAMD_DENSE_COL 1
+
+/* stats [2]: memory defragmentation count output statistic */
+#define COLAMD_DEFRAG_COUNT 2
+
+/* stats [3]: colamd status: zero OK, > 0 warning or notice, < 0 error */
+#define COLAMD_STATUS 3
+
+/* stats [4..6]: error info, or info on jumbled columns */
+#define COLAMD_INFO1 4
+#define COLAMD_INFO2 5
+#define COLAMD_INFO3 6
+
+/* error codes returned in stats [3]: */
+#define COLAMD_OK (0)
+#define COLAMD_OK_BUT_JUMBLED (1)
+#define COLAMD_ERROR_A_not_present (-1)
+#define COLAMD_ERROR_p_not_present (-2)
+#define COLAMD_ERROR_nrow_negative (-3)
+#define COLAMD_ERROR_ncol_negative (-4)
+#define COLAMD_ERROR_nnz_negative (-5)
+#define COLAMD_ERROR_p0_nonzero (-6)
+#define COLAMD_ERROR_A_too_small (-7)
+#define COLAMD_ERROR_col_length_negative (-8)
+#define COLAMD_ERROR_row_index_out_of_bounds (-9)
+#define COLAMD_ERROR_out_of_memory (-10)
+#define COLAMD_ERROR_internal_error (-999)
+
+/* ========================================================================== */
+/* === Definitions ========================================================== */
+/* ========================================================================== */
+
+#define COLAMD_MAX(a,b) (((a) > (b)) ? (a) : (b))
+#define COLAMD_MIN(a,b) (((a) < (b)) ? (a) : (b))
+
+#define ONES_COMPLEMENT(r) (-(r)-1)
+
+/* -------------------------------------------------------------------------- */
+
+#define COLAMD_EMPTY (-1)
+
+/* Row and column status */
+#define ALIVE (0)
+#define DEAD (-1)
+
+/* Column status */
+#define DEAD_PRINCIPAL (-1)
+#define DEAD_NON_PRINCIPAL (-2)
+
+/* Macros for row and column status update and checking. */
+#define ROW_IS_DEAD(r) ROW_IS_MARKED_DEAD (Row[r].shared2.mark)
+#define ROW_IS_MARKED_DEAD(row_mark) (row_mark < ALIVE)
+#define ROW_IS_ALIVE(r) (Row [r].shared2.mark >= ALIVE)
+#define COL_IS_DEAD(c) (Col [c].start < ALIVE)
+#define COL_IS_ALIVE(c) (Col [c].start >= ALIVE)
+#define COL_IS_DEAD_PRINCIPAL(c) (Col [c].start == DEAD_PRINCIPAL)
+#define KILL_ROW(r) { Row [r].shared2.mark = DEAD ; }
+#define KILL_PRINCIPAL_COL(c) { Col [c].start = DEAD_PRINCIPAL ; }
+#define KILL_NON_PRINCIPAL_COL(c) { Col [c].start = DEAD_NON_PRINCIPAL ; }
+
+/* ========================================================================== */
+/* === Colamd reporting mechanism =========================================== */
+/* ========================================================================== */
+
+// == Row and Column structures ==
+template <typename Index>
+struct colamd_col
+{
+ Index start ; /* index for A of first row in this column, or DEAD */
+ /* if column is dead */
+ Index length ; /* number of rows in this column */
+ union
+ {
+ Index thickness ; /* number of original columns represented by this */
+ /* col, if the column is alive */
+ Index parent ; /* parent in parent tree super-column structure, if */
+ /* the column is dead */
+ } shared1 ;
+ union
+ {
+ Index score ; /* the score used to maintain heap, if col is alive */
+ Index order ; /* pivot ordering of this column, if col is dead */
+ } shared2 ;
+ union
+ {
+ Index headhash ; /* head of a hash bucket, if col is at the head of */
+ /* a degree list */
+ Index hash ; /* hash value, if col is not in a degree list */
+ Index prev ; /* previous column in degree list, if col is in a */
+ /* degree list (but not at the head of a degree list) */
+ } shared3 ;
+ union
+ {
+ Index degree_next ; /* next column, if col is in a degree list */
+ Index hash_next ; /* next column, if col is in a hash list */
+ } shared4 ;
+
+};
+
+template <typename Index>
+struct Colamd_Row
+{
+ Index start ; /* index for A of first col in this row */
+ Index length ; /* number of principal columns in this row */
+ union
+ {
+ Index degree ; /* number of principal & non-principal columns in row */
+ Index p ; /* used as a row pointer in init_rows_cols () */
+ } shared1 ;
+ union
+ {
+ Index mark ; /* for computing set differences and marking dead rows*/
+ Index first_column ;/* first column in row (used in garbage collection) */
+ } shared2 ;
+
+};
+
+/* ========================================================================== */
+/* === Colamd recommended memory size ======================================= */
+/* ========================================================================== */
+
+/*
+ The recommended length Alen of the array A passed to colamd is given by
+ the COLAMD_RECOMMENDED (nnz, n_row, n_col) macro. It returns -1 if any
+ argument is negative. 2*nnz space is required for the row and column
+ indices of the matrix. colamd_c (n_col) + colamd_r (n_row) space is
+ required for the Col and Row arrays, respectively, which are internal to
+ colamd. An additional n_col space is the minimal amount of "elbow room",
+ and nnz/5 more space is recommended for run time efficiency.
+
+ This macro is not needed when using symamd.
+
+ Explicit typecast to Index added Sept. 23, 2002, COLAMD version 2.2, to avoid
+ gcc -pedantic warning messages.
+*/
+template <typename Index>
+inline Index colamd_c(Index n_col)
+{ return Index( ((n_col) + 1) * sizeof (colamd_col<Index>) / sizeof (Index) ) ; }
+
+template <typename Index>
+inline Index colamd_r(Index n_row)
+{ return Index(((n_row) + 1) * sizeof (Colamd_Row<Index>) / sizeof (Index)); }
+
+// Prototypes of non-user callable routines
+template <typename Index>
+static Index init_rows_cols (Index n_row, Index n_col, Colamd_Row<Index> Row [], colamd_col<Index> col [], Index A [], Index p [], Index stats[COLAMD_STATS] );
+
+template <typename Index>
+static void init_scoring (Index n_row, Index n_col, Colamd_Row<Index> Row [], colamd_col<Index> Col [], Index A [], Index head [], double knobs[COLAMD_KNOBS], Index *p_n_row2, Index *p_n_col2, Index *p_max_deg);
+
+template <typename Index>
+static Index find_ordering (Index n_row, Index n_col, Index Alen, Colamd_Row<Index> Row [], colamd_col<Index> Col [], Index A [], Index head [], Index n_col2, Index max_deg, Index pfree);
+
+template <typename Index>
+static void order_children (Index n_col, colamd_col<Index> Col [], Index p []);
+
+template <typename Index>
+static void detect_super_cols (colamd_col<Index> Col [], Index A [], Index head [], Index row_start, Index row_length ) ;
+
+template <typename Index>
+static Index garbage_collection (Index n_row, Index n_col, Colamd_Row<Index> Row [], colamd_col<Index> Col [], Index A [], Index *pfree) ;
+
+template <typename Index>
+static inline Index clear_mark (Index n_row, Colamd_Row<Index> Row [] ) ;
+
+/* === No debugging ========================================================= */
+
+#define COLAMD_DEBUG0(params) ;
+#define COLAMD_DEBUG1(params) ;
+#define COLAMD_DEBUG2(params) ;
+#define COLAMD_DEBUG3(params) ;
+#define COLAMD_DEBUG4(params) ;
+
+#define COLAMD_ASSERT(expression) ((void) 0)
+
+
+/**
+ * \brief Returns the recommended value of Alen
+ *
+ * Returns recommended value of Alen for use by colamd.
+ * Returns -1 if any input argument is negative.
+ * The use of this routine or macro is optional.
+ * Note that the macro uses its arguments more than once,
+ * so be careful for side effects, if you pass expressions as arguments to COLAMD_RECOMMENDED.
+ *
+ * \param nnz nonzeros in A
+ * \param n_row number of rows in A
+ * \param n_col number of columns in A
+ * \return recommended value of Alen for use by colamd
+ */
+template <typename Index>
+inline Index colamd_recommended ( Index nnz, Index n_row, Index n_col)
+{
+ if ((nnz) < 0 || (n_row) < 0 || (n_col) < 0)
+ return (-1);
+ else
+ return (2 * (nnz) + colamd_c (n_col) + colamd_r (n_row) + (n_col) + ((nnz) / 5));
+}
+
+/**
+ * \brief set default parameters The use of this routine is optional.
+ *
+ * Colamd: rows with more than (knobs [COLAMD_DENSE_ROW] * n_col)
+ * entries are removed prior to ordering. Columns with more than
+ * (knobs [COLAMD_DENSE_COL] * n_row) entries are removed prior to
+ * ordering, and placed last in the output column ordering.
+ *
+ * COLAMD_DENSE_ROW and COLAMD_DENSE_COL are defined as 0 and 1,
+ * respectively, in colamd.h. Default values of these two knobs
+ * are both 0.5. Currently, only knobs [0] and knobs [1] are
+ * used, but future versions may use more knobs. If so, they will
+ * be properly set to their defaults by the future version of
+ * colamd_set_defaults, so that the code that calls colamd will
+ * not need to change, assuming that you either use
+ * colamd_set_defaults, or pass a (double *) NULL pointer as the
+ * knobs array to colamd or symamd.
+ *
+ * \param knobs parameter settings for colamd
+ */
+
+static inline void colamd_set_defaults(double knobs[COLAMD_KNOBS])
+{
+ /* === Local variables ================================================== */
+
+ int i ;
+
+ if (!knobs)
+ {
+ return ; /* no knobs to initialize */
+ }
+ for (i = 0 ; i < COLAMD_KNOBS ; i++)
+ {
+ knobs [i] = 0 ;
+ }
+ knobs [COLAMD_DENSE_ROW] = 0.5 ; /* ignore rows over 50% dense */
+ knobs [COLAMD_DENSE_COL] = 0.5 ; /* ignore columns over 50% dense */
+}
+
+/**
+ * \brief Computes a column ordering using the column approximate minimum degree ordering
+ *
+ * Computes a column ordering (Q) of A such that P(AQ)=LU or
+ * (AQ)'AQ=LL' have less fill-in and require fewer floating point
+ * operations than factorizing the unpermuted matrix A or A'A,
+ * respectively.
+ *
+ *
+ * \param n_row number of rows in A
+ * \param n_col number of columns in A
+ * \param Alen, size of the array A
+ * \param A row indices of the matrix, of size ALen
+ * \param p column pointers of A, of size n_col+1
+ * \param knobs parameter settings for colamd
+ * \param stats colamd output statistics and error codes
+ */
+template <typename Index>
+static bool colamd(Index n_row, Index n_col, Index Alen, Index *A, Index *p, double knobs[COLAMD_KNOBS], Index stats[COLAMD_STATS])
+{
+ /* === Local variables ================================================== */
+
+ Index i ; /* loop index */
+ Index nnz ; /* nonzeros in A */
+ Index Row_size ; /* size of Row [], in integers */
+ Index Col_size ; /* size of Col [], in integers */
+ Index need ; /* minimum required length of A */
+ Colamd_Row<Index> *Row ; /* pointer into A of Row [0..n_row] array */
+ colamd_col<Index> *Col ; /* pointer into A of Col [0..n_col] array */
+ Index n_col2 ; /* number of non-dense, non-empty columns */
+ Index n_row2 ; /* number of non-dense, non-empty rows */
+ Index ngarbage ; /* number of garbage collections performed */
+ Index max_deg ; /* maximum row degree */
+ double default_knobs [COLAMD_KNOBS] ; /* default knobs array */
+
+
+ /* === Check the input arguments ======================================== */
+
+ if (!stats)
+ {
+ COLAMD_DEBUG0 (("colamd: stats not present\n")) ;
+ return (false) ;
+ }
+ for (i = 0 ; i < COLAMD_STATS ; i++)
+ {
+ stats [i] = 0 ;
+ }
+ stats [COLAMD_STATUS] = COLAMD_OK ;
+ stats [COLAMD_INFO1] = -1 ;
+ stats [COLAMD_INFO2] = -1 ;
+
+ if (!A) /* A is not present */
+ {
+ stats [COLAMD_STATUS] = COLAMD_ERROR_A_not_present ;
+ COLAMD_DEBUG0 (("colamd: A not present\n")) ;
+ return (false) ;
+ }
+
+ if (!p) /* p is not present */
+ {
+ stats [COLAMD_STATUS] = COLAMD_ERROR_p_not_present ;
+ COLAMD_DEBUG0 (("colamd: p not present\n")) ;
+ return (false) ;
+ }
+
+ if (n_row < 0) /* n_row must be >= 0 */
+ {
+ stats [COLAMD_STATUS] = COLAMD_ERROR_nrow_negative ;
+ stats [COLAMD_INFO1] = n_row ;
+ COLAMD_DEBUG0 (("colamd: nrow negative %d\n", n_row)) ;
+ return (false) ;
+ }
+
+ if (n_col < 0) /* n_col must be >= 0 */
+ {
+ stats [COLAMD_STATUS] = COLAMD_ERROR_ncol_negative ;
+ stats [COLAMD_INFO1] = n_col ;
+ COLAMD_DEBUG0 (("colamd: ncol negative %d\n", n_col)) ;
+ return (false) ;
+ }
+
+ nnz = p [n_col] ;
+ if (nnz < 0) /* nnz must be >= 0 */
+ {
+ stats [COLAMD_STATUS] = COLAMD_ERROR_nnz_negative ;
+ stats [COLAMD_INFO1] = nnz ;
+ COLAMD_DEBUG0 (("colamd: number of entries negative %d\n", nnz)) ;
+ return (false) ;
+ }
+
+ if (p [0] != 0)
+ {
+ stats [COLAMD_STATUS] = COLAMD_ERROR_p0_nonzero ;
+ stats [COLAMD_INFO1] = p [0] ;
+ COLAMD_DEBUG0 (("colamd: p[0] not zero %d\n", p [0])) ;
+ return (false) ;
+ }
+
+ /* === If no knobs, set default knobs =================================== */
+
+ if (!knobs)
+ {
+ colamd_set_defaults (default_knobs) ;
+ knobs = default_knobs ;
+ }
+
+ /* === Allocate the Row and Col arrays from array A ===================== */
+
+ Col_size = colamd_c (n_col) ;
+ Row_size = colamd_r (n_row) ;
+ need = 2*nnz + n_col + Col_size + Row_size ;
+
+ if (need > Alen)
+ {
+ /* not enough space in array A to perform the ordering */
+ stats [COLAMD_STATUS] = COLAMD_ERROR_A_too_small ;
+ stats [COLAMD_INFO1] = need ;
+ stats [COLAMD_INFO2] = Alen ;
+ COLAMD_DEBUG0 (("colamd: Need Alen >= %d, given only Alen = %d\n", need,Alen));
+ return (false) ;
+ }
+
+ Alen -= Col_size + Row_size ;
+ Col = (colamd_col<Index> *) &A [Alen] ;
+ Row = (Colamd_Row<Index> *) &A [Alen + Col_size] ;
+
+ /* === Construct the row and column data structures ===================== */
+
+ if (!Eigen::internal::init_rows_cols (n_row, n_col, Row, Col, A, p, stats))
+ {
+ /* input matrix is invalid */
+ COLAMD_DEBUG0 (("colamd: Matrix invalid\n")) ;
+ return (false) ;
+ }
+
+ /* === Initialize scores, kill dense rows/columns ======================= */
+
+ Eigen::internal::init_scoring (n_row, n_col, Row, Col, A, p, knobs,
+ &n_row2, &n_col2, &max_deg) ;
+
+ /* === Order the supercolumns =========================================== */
+
+ ngarbage = Eigen::internal::find_ordering (n_row, n_col, Alen, Row, Col, A, p,
+ n_col2, max_deg, 2*nnz) ;
+
+ /* === Order the non-principal columns ================================== */
+
+ Eigen::internal::order_children (n_col, Col, p) ;
+
+ /* === Return statistics in stats ======================================= */
+
+ stats [COLAMD_DENSE_ROW] = n_row - n_row2 ;
+ stats [COLAMD_DENSE_COL] = n_col - n_col2 ;
+ stats [COLAMD_DEFRAG_COUNT] = ngarbage ;
+ COLAMD_DEBUG0 (("colamd: done.\n")) ;
+ return (true) ;
+}
+
+/* ========================================================================== */
+/* === NON-USER-CALLABLE ROUTINES: ========================================== */
+/* ========================================================================== */
+
+/* There are no user-callable routines beyond this point in the file */
+
+
+/* ========================================================================== */
+/* === init_rows_cols ======================================================= */
+/* ========================================================================== */
+
+/*
+ Takes the column form of the matrix in A and creates the row form of the
+ matrix. Also, row and column attributes are stored in the Col and Row
+ structs. If the columns are un-sorted or contain duplicate row indices,
+ this routine will also sort and remove duplicate row indices from the
+ column form of the matrix. Returns false if the matrix is invalid,
+ true otherwise. Not user-callable.
+*/
+template <typename Index>
+static Index init_rows_cols /* returns true if OK, or false otherwise */
+ (
+ /* === Parameters ======================================================= */
+
+ Index n_row, /* number of rows of A */
+ Index n_col, /* number of columns of A */
+ Colamd_Row<Index> Row [], /* of size n_row+1 */
+ colamd_col<Index> Col [], /* of size n_col+1 */
+ Index A [], /* row indices of A, of size Alen */
+ Index p [], /* pointers to columns in A, of size n_col+1 */
+ Index stats [COLAMD_STATS] /* colamd statistics */
+ )
+{
+ /* === Local variables ================================================== */
+
+ Index col ; /* a column index */
+ Index row ; /* a row index */
+ Index *cp ; /* a column pointer */
+ Index *cp_end ; /* a pointer to the end of a column */
+ Index *rp ; /* a row pointer */
+ Index *rp_end ; /* a pointer to the end of a row */
+ Index last_row ; /* previous row */
+
+ /* === Initialize columns, and check column pointers ==================== */
+
+ for (col = 0 ; col < n_col ; col++)
+ {
+ Col [col].start = p [col] ;
+ Col [col].length = p [col+1] - p [col] ;
+
+ if (Col [col].length < 0)
+ {
+ /* column pointers must be non-decreasing */
+ stats [COLAMD_STATUS] = COLAMD_ERROR_col_length_negative ;
+ stats [COLAMD_INFO1] = col ;
+ stats [COLAMD_INFO2] = Col [col].length ;
+ COLAMD_DEBUG0 (("colamd: col %d length %d < 0\n", col, Col [col].length)) ;
+ return (false) ;
+ }
+
+ Col [col].shared1.thickness = 1 ;
+ Col [col].shared2.score = 0 ;
+ Col [col].shared3.prev = COLAMD_EMPTY ;
+ Col [col].shared4.degree_next = COLAMD_EMPTY ;
+ }
+
+ /* p [0..n_col] no longer needed, used as "head" in subsequent routines */
+
+ /* === Scan columns, compute row degrees, and check row indices ========= */
+
+ stats [COLAMD_INFO3] = 0 ; /* number of duplicate or unsorted row indices*/
+
+ for (row = 0 ; row < n_row ; row++)
+ {
+ Row [row].length = 0 ;
+ Row [row].shared2.mark = -1 ;
+ }
+
+ for (col = 0 ; col < n_col ; col++)
+ {
+ last_row = -1 ;
+
+ cp = &A [p [col]] ;
+ cp_end = &A [p [col+1]] ;
+
+ while (cp < cp_end)
+ {
+ row = *cp++ ;
+
+ /* make sure row indices within range */
+ if (row < 0 || row >= n_row)
+ {
+ stats [COLAMD_STATUS] = COLAMD_ERROR_row_index_out_of_bounds ;
+ stats [COLAMD_INFO1] = col ;
+ stats [COLAMD_INFO2] = row ;
+ stats [COLAMD_INFO3] = n_row ;
+ COLAMD_DEBUG0 (("colamd: row %d col %d out of bounds\n", row, col)) ;
+ return (false) ;
+ }
+
+ if (row <= last_row || Row [row].shared2.mark == col)
+ {
+ /* row index are unsorted or repeated (or both), thus col */
+ /* is jumbled. This is a notice, not an error condition. */
+ stats [COLAMD_STATUS] = COLAMD_OK_BUT_JUMBLED ;
+ stats [COLAMD_INFO1] = col ;
+ stats [COLAMD_INFO2] = row ;
+ (stats [COLAMD_INFO3]) ++ ;
+ COLAMD_DEBUG1 (("colamd: row %d col %d unsorted/duplicate\n",row,col));
+ }
+
+ if (Row [row].shared2.mark != col)
+ {
+ Row [row].length++ ;
+ }
+ else
+ {
+ /* this is a repeated entry in the column, */
+ /* it will be removed */
+ Col [col].length-- ;
+ }
+
+ /* mark the row as having been seen in this column */
+ Row [row].shared2.mark = col ;
+
+ last_row = row ;
+ }
+ }
+
+ /* === Compute row pointers ============================================= */
+
+ /* row form of the matrix starts directly after the column */
+ /* form of matrix in A */
+ Row [0].start = p [n_col] ;
+ Row [0].shared1.p = Row [0].start ;
+ Row [0].shared2.mark = -1 ;
+ for (row = 1 ; row < n_row ; row++)
+ {
+ Row [row].start = Row [row-1].start + Row [row-1].length ;
+ Row [row].shared1.p = Row [row].start ;
+ Row [row].shared2.mark = -1 ;
+ }
+
+ /* === Create row form ================================================== */
+
+ if (stats [COLAMD_STATUS] == COLAMD_OK_BUT_JUMBLED)
+ {
+ /* if cols jumbled, watch for repeated row indices */
+ for (col = 0 ; col < n_col ; col++)
+ {
+ cp = &A [p [col]] ;
+ cp_end = &A [p [col+1]] ;
+ while (cp < cp_end)
+ {
+ row = *cp++ ;
+ if (Row [row].shared2.mark != col)
+ {
+ A [(Row [row].shared1.p)++] = col ;
+ Row [row].shared2.mark = col ;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* if cols not jumbled, we don't need the mark (this is faster) */
+ for (col = 0 ; col < n_col ; col++)
+ {
+ cp = &A [p [col]] ;
+ cp_end = &A [p [col+1]] ;
+ while (cp < cp_end)
+ {
+ A [(Row [*cp++].shared1.p)++] = col ;
+ }
+ }
+ }
+
+ /* === Clear the row marks and set row degrees ========================== */
+
+ for (row = 0 ; row < n_row ; row++)
+ {
+ Row [row].shared2.mark = 0 ;
+ Row [row].shared1.degree = Row [row].length ;
+ }
+
+ /* === See if we need to re-create columns ============================== */
+
+ if (stats [COLAMD_STATUS] == COLAMD_OK_BUT_JUMBLED)
+ {
+ COLAMD_DEBUG0 (("colamd: reconstructing column form, matrix jumbled\n")) ;
+
+
+ /* === Compute col pointers ========================================= */
+
+ /* col form of the matrix starts at A [0]. */
+ /* Note, we may have a gap between the col form and the row */
+ /* form if there were duplicate entries, if so, it will be */
+ /* removed upon the first garbage collection */
+ Col [0].start = 0 ;
+ p [0] = Col [0].start ;
+ for (col = 1 ; col < n_col ; col++)
+ {
+ /* note that the lengths here are for pruned columns, i.e. */
+ /* no duplicate row indices will exist for these columns */
+ Col [col].start = Col [col-1].start + Col [col-1].length ;
+ p [col] = Col [col].start ;
+ }
+
+ /* === Re-create col form =========================================== */
+
+ for (row = 0 ; row < n_row ; row++)
+ {
+ rp = &A [Row [row].start] ;
+ rp_end = rp + Row [row].length ;
+ while (rp < rp_end)
+ {
+ A [(p [*rp++])++] = row ;
+ }
+ }
+ }
+
+ /* === Done. Matrix is not (or no longer) jumbled ====================== */
+
+ return (true) ;
+}
+
+
+/* ========================================================================== */
+/* === init_scoring ========================================================= */
+/* ========================================================================== */
+
+/*
+ Kills dense or empty columns and rows, calculates an initial score for
+ each column, and places all columns in the degree lists. Not user-callable.
+*/
+template <typename Index>
+static void init_scoring
+ (
+ /* === Parameters ======================================================= */
+
+ Index n_row, /* number of rows of A */
+ Index n_col, /* number of columns of A */
+ Colamd_Row<Index> Row [], /* of size n_row+1 */
+ colamd_col<Index> Col [], /* of size n_col+1 */
+ Index A [], /* column form and row form of A */
+ Index head [], /* of size n_col+1 */
+ double knobs [COLAMD_KNOBS],/* parameters */
+ Index *p_n_row2, /* number of non-dense, non-empty rows */
+ Index *p_n_col2, /* number of non-dense, non-empty columns */
+ Index *p_max_deg /* maximum row degree */
+ )
+{
+ /* === Local variables ================================================== */
+
+ Index c ; /* a column index */
+ Index r, row ; /* a row index */
+ Index *cp ; /* a column pointer */
+ Index deg ; /* degree of a row or column */
+ Index *cp_end ; /* a pointer to the end of a column */
+ Index *new_cp ; /* new column pointer */
+ Index col_length ; /* length of pruned column */
+ Index score ; /* current column score */
+ Index n_col2 ; /* number of non-dense, non-empty columns */
+ Index n_row2 ; /* number of non-dense, non-empty rows */
+ Index dense_row_count ; /* remove rows with more entries than this */
+ Index dense_col_count ; /* remove cols with more entries than this */
+ Index min_score ; /* smallest column score */
+ Index max_deg ; /* maximum row degree */
+ Index next_col ; /* Used to add to degree list.*/
+
+
+ /* === Extract knobs ==================================================== */
+
+ dense_row_count = COLAMD_MAX (0, COLAMD_MIN (knobs [COLAMD_DENSE_ROW] * n_col, n_col)) ;
+ dense_col_count = COLAMD_MAX (0, COLAMD_MIN (knobs [COLAMD_DENSE_COL] * n_row, n_row)) ;
+ COLAMD_DEBUG1 (("colamd: densecount: %d %d\n", dense_row_count, dense_col_count)) ;
+ max_deg = 0 ;
+ n_col2 = n_col ;
+ n_row2 = n_row ;
+
+ /* === Kill empty columns =============================================== */
+
+ /* Put the empty columns at the end in their natural order, so that LU */
+ /* factorization can proceed as far as possible. */
+ for (c = n_col-1 ; c >= 0 ; c--)
+ {
+ deg = Col [c].length ;
+ if (deg == 0)
+ {
+ /* this is a empty column, kill and order it last */
+ Col [c].shared2.order = --n_col2 ;
+ KILL_PRINCIPAL_COL (c) ;
+ }
+ }
+ COLAMD_DEBUG1 (("colamd: null columns killed: %d\n", n_col - n_col2)) ;
+
+ /* === Kill dense columns =============================================== */
+
+ /* Put the dense columns at the end, in their natural order */
+ for (c = n_col-1 ; c >= 0 ; c--)
+ {
+ /* skip any dead columns */
+ if (COL_IS_DEAD (c))
+ {
+ continue ;
+ }
+ deg = Col [c].length ;
+ if (deg > dense_col_count)
+ {
+ /* this is a dense column, kill and order it last */
+ Col [c].shared2.order = --n_col2 ;
+ /* decrement the row degrees */
+ cp = &A [Col [c].start] ;
+ cp_end = cp + Col [c].length ;
+ while (cp < cp_end)
+ {
+ Row [*cp++].shared1.degree-- ;
+ }
+ KILL_PRINCIPAL_COL (c) ;
+ }
+ }
+ COLAMD_DEBUG1 (("colamd: Dense and null columns killed: %d\n", n_col - n_col2)) ;
+
+ /* === Kill dense and empty rows ======================================== */
+
+ for (r = 0 ; r < n_row ; r++)
+ {
+ deg = Row [r].shared1.degree ;
+ COLAMD_ASSERT (deg >= 0 && deg <= n_col) ;
+ if (deg > dense_row_count || deg == 0)
+ {
+ /* kill a dense or empty row */
+ KILL_ROW (r) ;
+ --n_row2 ;
+ }
+ else
+ {
+ /* keep track of max degree of remaining rows */
+ max_deg = COLAMD_MAX (max_deg, deg) ;
+ }
+ }
+ COLAMD_DEBUG1 (("colamd: Dense and null rows killed: %d\n", n_row - n_row2)) ;
+
+ /* === Compute initial column scores ==================================== */
+
+ /* At this point the row degrees are accurate. They reflect the number */
+ /* of "live" (non-dense) columns in each row. No empty rows exist. */
+ /* Some "live" columns may contain only dead rows, however. These are */
+ /* pruned in the code below. */
+
+ /* now find the initial matlab score for each column */
+ for (c = n_col-1 ; c >= 0 ; c--)
+ {
+ /* skip dead column */
+ if (COL_IS_DEAD (c))
+ {
+ continue ;
+ }
+ score = 0 ;
+ cp = &A [Col [c].start] ;
+ new_cp = cp ;
+ cp_end = cp + Col [c].length ;
+ while (cp < cp_end)
+ {
+ /* get a row */
+ row = *cp++ ;
+ /* skip if dead */
+ if (ROW_IS_DEAD (row))
+ {
+ continue ;
+ }
+ /* compact the column */
+ *new_cp++ = row ;
+ /* add row's external degree */
+ score += Row [row].shared1.degree - 1 ;
+ /* guard against integer overflow */
+ score = COLAMD_MIN (score, n_col) ;
+ }
+ /* determine pruned column length */
+ col_length = (Index) (new_cp - &A [Col [c].start]) ;
+ if (col_length == 0)
+ {
+ /* a newly-made null column (all rows in this col are "dense" */
+ /* and have already been killed) */
+ COLAMD_DEBUG2 (("Newly null killed: %d\n", c)) ;
+ Col [c].shared2.order = --n_col2 ;
+ KILL_PRINCIPAL_COL (c) ;
+ }
+ else
+ {
+ /* set column length and set score */
+ COLAMD_ASSERT (score >= 0) ;
+ COLAMD_ASSERT (score <= n_col) ;
+ Col [c].length = col_length ;
+ Col [c].shared2.score = score ;
+ }
+ }
+ COLAMD_DEBUG1 (("colamd: Dense, null, and newly-null columns killed: %d\n",
+ n_col-n_col2)) ;
+
+ /* At this point, all empty rows and columns are dead. All live columns */
+ /* are "clean" (containing no dead rows) and simplicial (no supercolumns */
+ /* yet). Rows may contain dead columns, but all live rows contain at */
+ /* least one live column. */
+
+ /* === Initialize degree lists ========================================== */
+
+
+ /* clear the hash buckets */
+ for (c = 0 ; c <= n_col ; c++)
+ {
+ head [c] = COLAMD_EMPTY ;
+ }
+ min_score = n_col ;
+ /* place in reverse order, so low column indices are at the front */
+ /* of the lists. This is to encourage natural tie-breaking */
+ for (c = n_col-1 ; c >= 0 ; c--)
+ {
+ /* only add principal columns to degree lists */
+ if (COL_IS_ALIVE (c))
+ {
+ COLAMD_DEBUG4 (("place %d score %d minscore %d ncol %d\n",
+ c, Col [c].shared2.score, min_score, n_col)) ;
+
+ /* === Add columns score to DList =============================== */
+
+ score = Col [c].shared2.score ;
+
+ COLAMD_ASSERT (min_score >= 0) ;
+ COLAMD_ASSERT (min_score <= n_col) ;
+ COLAMD_ASSERT (score >= 0) ;
+ COLAMD_ASSERT (score <= n_col) ;
+ COLAMD_ASSERT (head [score] >= COLAMD_EMPTY) ;
+
+ /* now add this column to dList at proper score location */
+ next_col = head [score] ;
+ Col [c].shared3.prev = COLAMD_EMPTY ;
+ Col [c].shared4.degree_next = next_col ;
+
+ /* if there already was a column with the same score, set its */
+ /* previous pointer to this new column */
+ if (next_col != COLAMD_EMPTY)
+ {
+ Col [next_col].shared3.prev = c ;
+ }
+ head [score] = c ;
+
+ /* see if this score is less than current min */
+ min_score = COLAMD_MIN (min_score, score) ;
+
+
+ }
+ }
+
+
+ /* === Return number of remaining columns, and max row degree =========== */
+
+ *p_n_col2 = n_col2 ;
+ *p_n_row2 = n_row2 ;
+ *p_max_deg = max_deg ;
+}
+
+
+/* ========================================================================== */
+/* === find_ordering ======================================================== */
+/* ========================================================================== */
+
+/*
+ Order the principal columns of the supercolumn form of the matrix
+ (no supercolumns on input). Uses a minimum approximate column minimum
+ degree ordering method. Not user-callable.
+*/
+template <typename Index>
+static Index find_ordering /* return the number of garbage collections */
+ (
+ /* === Parameters ======================================================= */
+
+ Index n_row, /* number of rows of A */
+ Index n_col, /* number of columns of A */
+ Index Alen, /* size of A, 2*nnz + n_col or larger */
+ Colamd_Row<Index> Row [], /* of size n_row+1 */
+ colamd_col<Index> Col [], /* of size n_col+1 */
+ Index A [], /* column form and row form of A */
+ Index head [], /* of size n_col+1 */
+ Index n_col2, /* Remaining columns to order */
+ Index max_deg, /* Maximum row degree */
+ Index pfree /* index of first free slot (2*nnz on entry) */
+ )
+{
+ /* === Local variables ================================================== */
+
+ Index k ; /* current pivot ordering step */
+ Index pivot_col ; /* current pivot column */
+ Index *cp ; /* a column pointer */
+ Index *rp ; /* a row pointer */
+ Index pivot_row ; /* current pivot row */
+ Index *new_cp ; /* modified column pointer */
+ Index *new_rp ; /* modified row pointer */
+ Index pivot_row_start ; /* pointer to start of pivot row */
+ Index pivot_row_degree ; /* number of columns in pivot row */
+ Index pivot_row_length ; /* number of supercolumns in pivot row */
+ Index pivot_col_score ; /* score of pivot column */
+ Index needed_memory ; /* free space needed for pivot row */
+ Index *cp_end ; /* pointer to the end of a column */
+ Index *rp_end ; /* pointer to the end of a row */
+ Index row ; /* a row index */
+ Index col ; /* a column index */
+ Index max_score ; /* maximum possible score */
+ Index cur_score ; /* score of current column */
+ unsigned int hash ; /* hash value for supernode detection */
+ Index head_column ; /* head of hash bucket */
+ Index first_col ; /* first column in hash bucket */
+ Index tag_mark ; /* marker value for mark array */
+ Index row_mark ; /* Row [row].shared2.mark */
+ Index set_difference ; /* set difference size of row with pivot row */
+ Index min_score ; /* smallest column score */
+ Index col_thickness ; /* "thickness" (no. of columns in a supercol) */
+ Index max_mark ; /* maximum value of tag_mark */
+ Index pivot_col_thickness ; /* number of columns represented by pivot col */
+ Index prev_col ; /* Used by Dlist operations. */
+ Index next_col ; /* Used by Dlist operations. */
+ Index ngarbage ; /* number of garbage collections performed */
+
+
+ /* === Initialization and clear mark ==================================== */
+
+ max_mark = INT_MAX - n_col ; /* INT_MAX defined in <limits.h> */
+ tag_mark = Eigen::internal::clear_mark (n_row, Row) ;
+ min_score = 0 ;
+ ngarbage = 0 ;
+ COLAMD_DEBUG1 (("colamd: Ordering, n_col2=%d\n", n_col2)) ;
+
+ /* === Order the columns ================================================ */
+
+ for (k = 0 ; k < n_col2 ; /* 'k' is incremented below */)
+ {
+
+ /* === Select pivot column, and order it ============================ */
+
+ /* make sure degree list isn't empty */
+ COLAMD_ASSERT (min_score >= 0) ;
+ COLAMD_ASSERT (min_score <= n_col) ;
+ COLAMD_ASSERT (head [min_score] >= COLAMD_EMPTY) ;
+
+ /* get pivot column from head of minimum degree list */
+ while (head [min_score] == COLAMD_EMPTY && min_score < n_col)
+ {
+ min_score++ ;
+ }
+ pivot_col = head [min_score] ;
+ COLAMD_ASSERT (pivot_col >= 0 && pivot_col <= n_col) ;
+ next_col = Col [pivot_col].shared4.degree_next ;
+ head [min_score] = next_col ;
+ if (next_col != COLAMD_EMPTY)
+ {
+ Col [next_col].shared3.prev = COLAMD_EMPTY ;
+ }
+
+ COLAMD_ASSERT (COL_IS_ALIVE (pivot_col)) ;
+ COLAMD_DEBUG3 (("Pivot col: %d\n", pivot_col)) ;
+
+ /* remember score for defrag check */
+ pivot_col_score = Col [pivot_col].shared2.score ;
+
+ /* the pivot column is the kth column in the pivot order */
+ Col [pivot_col].shared2.order = k ;
+
+ /* increment order count by column thickness */
+ pivot_col_thickness = Col [pivot_col].shared1.thickness ;
+ k += pivot_col_thickness ;
+ COLAMD_ASSERT (pivot_col_thickness > 0) ;
+
+ /* === Garbage_collection, if necessary ============================= */
+
+ needed_memory = COLAMD_MIN (pivot_col_score, n_col - k) ;
+ if (pfree + needed_memory >= Alen)
+ {
+ pfree = Eigen::internal::garbage_collection (n_row, n_col, Row, Col, A, &A [pfree]) ;
+ ngarbage++ ;
+ /* after garbage collection we will have enough */
+ COLAMD_ASSERT (pfree + needed_memory < Alen) ;
+ /* garbage collection has wiped out the Row[].shared2.mark array */
+ tag_mark = Eigen::internal::clear_mark (n_row, Row) ;
+
+ }
+
+ /* === Compute pivot row pattern ==================================== */
+
+ /* get starting location for this new merged row */
+ pivot_row_start = pfree ;
+
+ /* initialize new row counts to zero */
+ pivot_row_degree = 0 ;
+
+ /* tag pivot column as having been visited so it isn't included */
+ /* in merged pivot row */
+ Col [pivot_col].shared1.thickness = -pivot_col_thickness ;
+
+ /* pivot row is the union of all rows in the pivot column pattern */
+ cp = &A [Col [pivot_col].start] ;
+ cp_end = cp + Col [pivot_col].length ;
+ while (cp < cp_end)
+ {
+ /* get a row */
+ row = *cp++ ;
+ COLAMD_DEBUG4 (("Pivot col pattern %d %d\n", ROW_IS_ALIVE (row), row)) ;
+ /* skip if row is dead */
+ if (ROW_IS_DEAD (row))
+ {
+ continue ;
+ }
+ rp = &A [Row [row].start] ;
+ rp_end = rp + Row [row].length ;
+ while (rp < rp_end)
+ {
+ /* get a column */
+ col = *rp++ ;
+ /* add the column, if alive and untagged */
+ col_thickness = Col [col].shared1.thickness ;
+ if (col_thickness > 0 && COL_IS_ALIVE (col))
+ {
+ /* tag column in pivot row */
+ Col [col].shared1.thickness = -col_thickness ;
+ COLAMD_ASSERT (pfree < Alen) ;
+ /* place column in pivot row */
+ A [pfree++] = col ;
+ pivot_row_degree += col_thickness ;
+ }
+ }
+ }
+
+ /* clear tag on pivot column */
+ Col [pivot_col].shared1.thickness = pivot_col_thickness ;
+ max_deg = COLAMD_MAX (max_deg, pivot_row_degree) ;
+
+
+ /* === Kill all rows used to construct pivot row ==================== */
+
+ /* also kill pivot row, temporarily */
+ cp = &A [Col [pivot_col].start] ;
+ cp_end = cp + Col [pivot_col].length ;
+ while (cp < cp_end)
+ {
+ /* may be killing an already dead row */
+ row = *cp++ ;
+ COLAMD_DEBUG3 (("Kill row in pivot col: %d\n", row)) ;
+ KILL_ROW (row) ;
+ }
+
+ /* === Select a row index to use as the new pivot row =============== */
+
+ pivot_row_length = pfree - pivot_row_start ;
+ if (pivot_row_length > 0)
+ {
+ /* pick the "pivot" row arbitrarily (first row in col) */
+ pivot_row = A [Col [pivot_col].start] ;
+ COLAMD_DEBUG3 (("Pivotal row is %d\n", pivot_row)) ;
+ }
+ else
+ {
+ /* there is no pivot row, since it is of zero length */
+ pivot_row = COLAMD_EMPTY ;
+ COLAMD_ASSERT (pivot_row_length == 0) ;
+ }
+ COLAMD_ASSERT (Col [pivot_col].length > 0 || pivot_row_length == 0) ;
+
+ /* === Approximate degree computation =============================== */
+
+ /* Here begins the computation of the approximate degree. The column */
+ /* score is the sum of the pivot row "length", plus the size of the */
+ /* set differences of each row in the column minus the pattern of the */
+ /* pivot row itself. The column ("thickness") itself is also */
+ /* excluded from the column score (we thus use an approximate */
+ /* external degree). */
+
+ /* The time taken by the following code (compute set differences, and */
+ /* add them up) is proportional to the size of the data structure */
+ /* being scanned - that is, the sum of the sizes of each column in */
+ /* the pivot row. Thus, the amortized time to compute a column score */
+ /* is proportional to the size of that column (where size, in this */
+ /* context, is the column "length", or the number of row indices */
+ /* in that column). The number of row indices in a column is */
+ /* monotonically non-decreasing, from the length of the original */
+ /* column on input to colamd. */
+
+ /* === Compute set differences ====================================== */
+
+ COLAMD_DEBUG3 (("** Computing set differences phase. **\n")) ;
+
+ /* pivot row is currently dead - it will be revived later. */
+
+ COLAMD_DEBUG3 (("Pivot row: ")) ;
+ /* for each column in pivot row */
+ rp = &A [pivot_row_start] ;
+ rp_end = rp + pivot_row_length ;
+ while (rp < rp_end)
+ {
+ col = *rp++ ;
+ COLAMD_ASSERT (COL_IS_ALIVE (col) && col != pivot_col) ;
+ COLAMD_DEBUG3 (("Col: %d\n", col)) ;
+
+ /* clear tags used to construct pivot row pattern */
+ col_thickness = -Col [col].shared1.thickness ;
+ COLAMD_ASSERT (col_thickness > 0) ;
+ Col [col].shared1.thickness = col_thickness ;
+
+ /* === Remove column from degree list =========================== */
+
+ cur_score = Col [col].shared2.score ;
+ prev_col = Col [col].shared3.prev ;
+ next_col = Col [col].shared4.degree_next ;
+ COLAMD_ASSERT (cur_score >= 0) ;
+ COLAMD_ASSERT (cur_score <= n_col) ;
+ COLAMD_ASSERT (cur_score >= COLAMD_EMPTY) ;
+ if (prev_col == COLAMD_EMPTY)
+ {
+ head [cur_score] = next_col ;
+ }
+ else
+ {
+ Col [prev_col].shared4.degree_next = next_col ;
+ }
+ if (next_col != COLAMD_EMPTY)
+ {
+ Col [next_col].shared3.prev = prev_col ;
+ }
+
+ /* === Scan the column ========================================== */
+
+ cp = &A [Col [col].start] ;
+ cp_end = cp + Col [col].length ;
+ while (cp < cp_end)
+ {
+ /* get a row */
+ row = *cp++ ;
+ row_mark = Row [row].shared2.mark ;
+ /* skip if dead */
+ if (ROW_IS_MARKED_DEAD (row_mark))
+ {
+ continue ;
+ }
+ COLAMD_ASSERT (row != pivot_row) ;
+ set_difference = row_mark - tag_mark ;
+ /* check if the row has been seen yet */
+ if (set_difference < 0)
+ {
+ COLAMD_ASSERT (Row [row].shared1.degree <= max_deg) ;
+ set_difference = Row [row].shared1.degree ;
+ }
+ /* subtract column thickness from this row's set difference */
+ set_difference -= col_thickness ;
+ COLAMD_ASSERT (set_difference >= 0) ;
+ /* absorb this row if the set difference becomes zero */
+ if (set_difference == 0)
+ {
+ COLAMD_DEBUG3 (("aggressive absorption. Row: %d\n", row)) ;
+ KILL_ROW (row) ;
+ }
+ else
+ {
+ /* save the new mark */
+ Row [row].shared2.mark = set_difference + tag_mark ;
+ }
+ }
+ }
+
+
+ /* === Add up set differences for each column ======================= */
+
+ COLAMD_DEBUG3 (("** Adding set differences phase. **\n")) ;
+
+ /* for each column in pivot row */
+ rp = &A [pivot_row_start] ;
+ rp_end = rp + pivot_row_length ;
+ while (rp < rp_end)
+ {
+ /* get a column */
+ col = *rp++ ;
+ COLAMD_ASSERT (COL_IS_ALIVE (col) && col != pivot_col) ;
+ hash = 0 ;
+ cur_score = 0 ;
+ cp = &A [Col [col].start] ;
+ /* compact the column */
+ new_cp = cp ;
+ cp_end = cp + Col [col].length ;
+
+ COLAMD_DEBUG4 (("Adding set diffs for Col: %d.\n", col)) ;
+
+ while (cp < cp_end)
+ {
+ /* get a row */
+ row = *cp++ ;
+ COLAMD_ASSERT(row >= 0 && row < n_row) ;
+ row_mark = Row [row].shared2.mark ;
+ /* skip if dead */
+ if (ROW_IS_MARKED_DEAD (row_mark))
+ {
+ continue ;
+ }
+ COLAMD_ASSERT (row_mark > tag_mark) ;
+ /* compact the column */
+ *new_cp++ = row ;
+ /* compute hash function */
+ hash += row ;
+ /* add set difference */
+ cur_score += row_mark - tag_mark ;
+ /* integer overflow... */
+ cur_score = COLAMD_MIN (cur_score, n_col) ;
+ }
+
+ /* recompute the column's length */
+ Col [col].length = (Index) (new_cp - &A [Col [col].start]) ;
+
+ /* === Further mass elimination ================================= */
+
+ if (Col [col].length == 0)
+ {
+ COLAMD_DEBUG4 (("further mass elimination. Col: %d\n", col)) ;
+ /* nothing left but the pivot row in this column */
+ KILL_PRINCIPAL_COL (col) ;
+ pivot_row_degree -= Col [col].shared1.thickness ;
+ COLAMD_ASSERT (pivot_row_degree >= 0) ;
+ /* order it */
+ Col [col].shared2.order = k ;
+ /* increment order count by column thickness */
+ k += Col [col].shared1.thickness ;
+ }
+ else
+ {
+ /* === Prepare for supercolumn detection ==================== */
+
+ COLAMD_DEBUG4 (("Preparing supercol detection for Col: %d.\n", col)) ;
+
+ /* save score so far */
+ Col [col].shared2.score = cur_score ;
+
+ /* add column to hash table, for supercolumn detection */
+ hash %= n_col + 1 ;
+
+ COLAMD_DEBUG4 ((" Hash = %d, n_col = %d.\n", hash, n_col)) ;
+ COLAMD_ASSERT (hash <= n_col) ;
+
+ head_column = head [hash] ;
+ if (head_column > COLAMD_EMPTY)
+ {
+ /* degree list "hash" is non-empty, use prev (shared3) of */
+ /* first column in degree list as head of hash bucket */
+ first_col = Col [head_column].shared3.headhash ;
+ Col [head_column].shared3.headhash = col ;
+ }
+ else
+ {
+ /* degree list "hash" is empty, use head as hash bucket */
+ first_col = - (head_column + 2) ;
+ head [hash] = - (col + 2) ;
+ }
+ Col [col].shared4.hash_next = first_col ;
+
+ /* save hash function in Col [col].shared3.hash */
+ Col [col].shared3.hash = (Index) hash ;
+ COLAMD_ASSERT (COL_IS_ALIVE (col)) ;
+ }
+ }
+
+ /* The approximate external column degree is now computed. */
+
+ /* === Supercolumn detection ======================================== */
+
+ COLAMD_DEBUG3 (("** Supercolumn detection phase. **\n")) ;
+
+ Eigen::internal::detect_super_cols (Col, A, head, pivot_row_start, pivot_row_length) ;
+
+ /* === Kill the pivotal column ====================================== */
+
+ KILL_PRINCIPAL_COL (pivot_col) ;
+
+ /* === Clear mark =================================================== */
+
+ tag_mark += (max_deg + 1) ;
+ if (tag_mark >= max_mark)
+ {
+ COLAMD_DEBUG2 (("clearing tag_mark\n")) ;
+ tag_mark = Eigen::internal::clear_mark (n_row, Row) ;
+ }
+
+ /* === Finalize the new pivot row, and column scores ================ */
+
+ COLAMD_DEBUG3 (("** Finalize scores phase. **\n")) ;
+
+ /* for each column in pivot row */
+ rp = &A [pivot_row_start] ;
+ /* compact the pivot row */
+ new_rp = rp ;
+ rp_end = rp + pivot_row_length ;
+ while (rp < rp_end)
+ {
+ col = *rp++ ;
+ /* skip dead columns */
+ if (COL_IS_DEAD (col))
+ {
+ continue ;
+ }
+ *new_rp++ = col ;
+ /* add new pivot row to column */
+ A [Col [col].start + (Col [col].length++)] = pivot_row ;
+
+ /* retrieve score so far and add on pivot row's degree. */
+ /* (we wait until here for this in case the pivot */
+ /* row's degree was reduced due to mass elimination). */
+ cur_score = Col [col].shared2.score + pivot_row_degree ;
+
+ /* calculate the max possible score as the number of */
+ /* external columns minus the 'k' value minus the */
+ /* columns thickness */
+ max_score = n_col - k - Col [col].shared1.thickness ;
+
+ /* make the score the external degree of the union-of-rows */
+ cur_score -= Col [col].shared1.thickness ;
+
+ /* make sure score is less or equal than the max score */
+ cur_score = COLAMD_MIN (cur_score, max_score) ;
+ COLAMD_ASSERT (cur_score >= 0) ;
+
+ /* store updated score */
+ Col [col].shared2.score = cur_score ;
+
+ /* === Place column back in degree list ========================= */
+
+ COLAMD_ASSERT (min_score >= 0) ;
+ COLAMD_ASSERT (min_score <= n_col) ;
+ COLAMD_ASSERT (cur_score >= 0) ;
+ COLAMD_ASSERT (cur_score <= n_col) ;
+ COLAMD_ASSERT (head [cur_score] >= COLAMD_EMPTY) ;
+ next_col = head [cur_score] ;
+ Col [col].shared4.degree_next = next_col ;
+ Col [col].shared3.prev = COLAMD_EMPTY ;
+ if (next_col != COLAMD_EMPTY)
+ {
+ Col [next_col].shared3.prev = col ;
+ }
+ head [cur_score] = col ;
+
+ /* see if this score is less than current min */
+ min_score = COLAMD_MIN (min_score, cur_score) ;
+
+ }
+
+ /* === Resurrect the new pivot row ================================== */
+
+ if (pivot_row_degree > 0)
+ {
+ /* update pivot row length to reflect any cols that were killed */
+ /* during super-col detection and mass elimination */
+ Row [pivot_row].start = pivot_row_start ;
+ Row [pivot_row].length = (Index) (new_rp - &A[pivot_row_start]) ;
+ Row [pivot_row].shared1.degree = pivot_row_degree ;
+ Row [pivot_row].shared2.mark = 0 ;
+ /* pivot row is no longer dead */
+ }
+ }
+
+ /* === All principal columns have now been ordered ====================== */
+
+ return (ngarbage) ;
+}
+
+
+/* ========================================================================== */
+/* === order_children ======================================================= */
+/* ========================================================================== */
+
+/*
+ The find_ordering routine has ordered all of the principal columns (the
+ representatives of the supercolumns). The non-principal columns have not
+ yet been ordered. This routine orders those columns by walking up the
+ parent tree (a column is a child of the column which absorbed it). The
+ final permutation vector is then placed in p [0 ... n_col-1], with p [0]
+ being the first column, and p [n_col-1] being the last. It doesn't look
+ like it at first glance, but be assured that this routine takes time linear
+ in the number of columns. Although not immediately obvious, the time
+ taken by this routine is O (n_col), that is, linear in the number of
+ columns. Not user-callable.
+*/
+template <typename Index>
+static inline void order_children
+(
+ /* === Parameters ======================================================= */
+
+ Index n_col, /* number of columns of A */
+ colamd_col<Index> Col [], /* of size n_col+1 */
+ Index p [] /* p [0 ... n_col-1] is the column permutation*/
+ )
+{
+ /* === Local variables ================================================== */
+
+ Index i ; /* loop counter for all columns */
+ Index c ; /* column index */
+ Index parent ; /* index of column's parent */
+ Index order ; /* column's order */
+
+ /* === Order each non-principal column ================================== */
+
+ for (i = 0 ; i < n_col ; i++)
+ {
+ /* find an un-ordered non-principal column */
+ COLAMD_ASSERT (COL_IS_DEAD (i)) ;
+ if (!COL_IS_DEAD_PRINCIPAL (i) && Col [i].shared2.order == COLAMD_EMPTY)
+ {
+ parent = i ;
+ /* once found, find its principal parent */
+ do
+ {
+ parent = Col [parent].shared1.parent ;
+ } while (!COL_IS_DEAD_PRINCIPAL (parent)) ;
+
+ /* now, order all un-ordered non-principal columns along path */
+ /* to this parent. collapse tree at the same time */
+ c = i ;
+ /* get order of parent */
+ order = Col [parent].shared2.order ;
+
+ do
+ {
+ COLAMD_ASSERT (Col [c].shared2.order == COLAMD_EMPTY) ;
+
+ /* order this column */
+ Col [c].shared2.order = order++ ;
+ /* collaps tree */
+ Col [c].shared1.parent = parent ;
+
+ /* get immediate parent of this column */
+ c = Col [c].shared1.parent ;
+
+ /* continue until we hit an ordered column. There are */
+ /* guarranteed not to be anymore unordered columns */
+ /* above an ordered column */
+ } while (Col [c].shared2.order == COLAMD_EMPTY) ;
+
+ /* re-order the super_col parent to largest order for this group */
+ Col [parent].shared2.order = order ;
+ }
+ }
+
+ /* === Generate the permutation ========================================= */
+
+ for (c = 0 ; c < n_col ; c++)
+ {
+ p [Col [c].shared2.order] = c ;
+ }
+}
+
+
+/* ========================================================================== */
+/* === detect_super_cols ==================================================== */
+/* ========================================================================== */
+
+/*
+ Detects supercolumns by finding matches between columns in the hash buckets.
+ Check amongst columns in the set A [row_start ... row_start + row_length-1].
+ The columns under consideration are currently *not* in the degree lists,
+ and have already been placed in the hash buckets.
+
+ The hash bucket for columns whose hash function is equal to h is stored
+ as follows:
+
+ if head [h] is >= 0, then head [h] contains a degree list, so:
+
+ head [h] is the first column in degree bucket h.
+ Col [head [h]].headhash gives the first column in hash bucket h.
+
+ otherwise, the degree list is empty, and:
+
+ -(head [h] + 2) is the first column in hash bucket h.
+
+ For a column c in a hash bucket, Col [c].shared3.prev is NOT a "previous
+ column" pointer. Col [c].shared3.hash is used instead as the hash number
+ for that column. The value of Col [c].shared4.hash_next is the next column
+ in the same hash bucket.
+
+ Assuming no, or "few" hash collisions, the time taken by this routine is
+ linear in the sum of the sizes (lengths) of each column whose score has
+ just been computed in the approximate degree computation.
+ Not user-callable.
+*/
+template <typename Index>
+static void detect_super_cols
+(
+ /* === Parameters ======================================================= */
+
+ colamd_col<Index> Col [], /* of size n_col+1 */
+ Index A [], /* row indices of A */
+ Index head [], /* head of degree lists and hash buckets */
+ Index row_start, /* pointer to set of columns to check */
+ Index row_length /* number of columns to check */
+)
+{
+ /* === Local variables ================================================== */
+
+ Index hash ; /* hash value for a column */
+ Index *rp ; /* pointer to a row */
+ Index c ; /* a column index */
+ Index super_c ; /* column index of the column to absorb into */
+ Index *cp1 ; /* column pointer for column super_c */
+ Index *cp2 ; /* column pointer for column c */
+ Index length ; /* length of column super_c */
+ Index prev_c ; /* column preceding c in hash bucket */
+ Index i ; /* loop counter */
+ Index *rp_end ; /* pointer to the end of the row */
+ Index col ; /* a column index in the row to check */
+ Index head_column ; /* first column in hash bucket or degree list */
+ Index first_col ; /* first column in hash bucket */
+
+ /* === Consider each column in the row ================================== */
+
+ rp = &A [row_start] ;
+ rp_end = rp + row_length ;
+ while (rp < rp_end)
+ {
+ col = *rp++ ;
+ if (COL_IS_DEAD (col))
+ {
+ continue ;
+ }
+
+ /* get hash number for this column */
+ hash = Col [col].shared3.hash ;
+ COLAMD_ASSERT (hash <= n_col) ;
+
+ /* === Get the first column in this hash bucket ===================== */
+
+ head_column = head [hash] ;
+ if (head_column > COLAMD_EMPTY)
+ {
+ first_col = Col [head_column].shared3.headhash ;
+ }
+ else
+ {
+ first_col = - (head_column + 2) ;
+ }
+
+ /* === Consider each column in the hash bucket ====================== */
+
+ for (super_c = first_col ; super_c != COLAMD_EMPTY ;
+ super_c = Col [super_c].shared4.hash_next)
+ {
+ COLAMD_ASSERT (COL_IS_ALIVE (super_c)) ;
+ COLAMD_ASSERT (Col [super_c].shared3.hash == hash) ;
+ length = Col [super_c].length ;
+
+ /* prev_c is the column preceding column c in the hash bucket */
+ prev_c = super_c ;
+
+ /* === Compare super_c with all columns after it ================ */
+
+ for (c = Col [super_c].shared4.hash_next ;
+ c != COLAMD_EMPTY ; c = Col [c].shared4.hash_next)
+ {
+ COLAMD_ASSERT (c != super_c) ;
+ COLAMD_ASSERT (COL_IS_ALIVE (c)) ;
+ COLAMD_ASSERT (Col [c].shared3.hash == hash) ;
+
+ /* not identical if lengths or scores are different */
+ if (Col [c].length != length ||
+ Col [c].shared2.score != Col [super_c].shared2.score)
+ {
+ prev_c = c ;
+ continue ;
+ }
+
+ /* compare the two columns */
+ cp1 = &A [Col [super_c].start] ;
+ cp2 = &A [Col [c].start] ;
+
+ for (i = 0 ; i < length ; i++)
+ {
+ /* the columns are "clean" (no dead rows) */
+ COLAMD_ASSERT (ROW_IS_ALIVE (*cp1)) ;
+ COLAMD_ASSERT (ROW_IS_ALIVE (*cp2)) ;
+ /* row indices will same order for both supercols, */
+ /* no gather scatter nessasary */
+ if (*cp1++ != *cp2++)
+ {
+ break ;
+ }
+ }
+
+ /* the two columns are different if the for-loop "broke" */
+ if (i != length)
+ {
+ prev_c = c ;
+ continue ;
+ }
+
+ /* === Got it! two columns are identical =================== */
+
+ COLAMD_ASSERT (Col [c].shared2.score == Col [super_c].shared2.score) ;
+
+ Col [super_c].shared1.thickness += Col [c].shared1.thickness ;
+ Col [c].shared1.parent = super_c ;
+ KILL_NON_PRINCIPAL_COL (c) ;
+ /* order c later, in order_children() */
+ Col [c].shared2.order = COLAMD_EMPTY ;
+ /* remove c from hash bucket */
+ Col [prev_c].shared4.hash_next = Col [c].shared4.hash_next ;
+ }
+ }
+
+ /* === Empty this hash bucket ======================================= */
+
+ if (head_column > COLAMD_EMPTY)
+ {
+ /* corresponding degree list "hash" is not empty */
+ Col [head_column].shared3.headhash = COLAMD_EMPTY ;
+ }
+ else
+ {
+ /* corresponding degree list "hash" is empty */
+ head [hash] = COLAMD_EMPTY ;
+ }
+ }
+}
+
+
+/* ========================================================================== */
+/* === garbage_collection =================================================== */
+/* ========================================================================== */
+
+/*
+ Defragments and compacts columns and rows in the workspace A. Used when
+ all avaliable memory has been used while performing row merging. Returns
+ the index of the first free position in A, after garbage collection. The
+ time taken by this routine is linear is the size of the array A, which is
+ itself linear in the number of nonzeros in the input matrix.
+ Not user-callable.
+*/
+template <typename Index>
+static Index garbage_collection /* returns the new value of pfree */
+ (
+ /* === Parameters ======================================================= */
+
+ Index n_row, /* number of rows */
+ Index n_col, /* number of columns */
+ Colamd_Row<Index> Row [], /* row info */
+ colamd_col<Index> Col [], /* column info */
+ Index A [], /* A [0 ... Alen-1] holds the matrix */
+ Index *pfree /* &A [0] ... pfree is in use */
+ )
+{
+ /* === Local variables ================================================== */
+
+ Index *psrc ; /* source pointer */
+ Index *pdest ; /* destination pointer */
+ Index j ; /* counter */
+ Index r ; /* a row index */
+ Index c ; /* a column index */
+ Index length ; /* length of a row or column */
+
+ /* === Defragment the columns =========================================== */
+
+ pdest = &A[0] ;
+ for (c = 0 ; c < n_col ; c++)
+ {
+ if (COL_IS_ALIVE (c))
+ {
+ psrc = &A [Col [c].start] ;
+
+ /* move and compact the column */
+ COLAMD_ASSERT (pdest <= psrc) ;
+ Col [c].start = (Index) (pdest - &A [0]) ;
+ length = Col [c].length ;
+ for (j = 0 ; j < length ; j++)
+ {
+ r = *psrc++ ;
+ if (ROW_IS_ALIVE (r))
+ {
+ *pdest++ = r ;
+ }
+ }
+ Col [c].length = (Index) (pdest - &A [Col [c].start]) ;
+ }
+ }
+
+ /* === Prepare to defragment the rows =================================== */
+
+ for (r = 0 ; r < n_row ; r++)
+ {
+ if (ROW_IS_ALIVE (r))
+ {
+ if (Row [r].length == 0)
+ {
+ /* this row is of zero length. cannot compact it, so kill it */
+ COLAMD_DEBUG3 (("Defrag row kill\n")) ;
+ KILL_ROW (r) ;
+ }
+ else
+ {
+ /* save first column index in Row [r].shared2.first_column */
+ psrc = &A [Row [r].start] ;
+ Row [r].shared2.first_column = *psrc ;
+ COLAMD_ASSERT (ROW_IS_ALIVE (r)) ;
+ /* flag the start of the row with the one's complement of row */
+ *psrc = ONES_COMPLEMENT (r) ;
+
+ }
+ }
+ }
+
+ /* === Defragment the rows ============================================== */
+
+ psrc = pdest ;
+ while (psrc < pfree)
+ {
+ /* find a negative number ... the start of a row */
+ if (*psrc++ < 0)
+ {
+ psrc-- ;
+ /* get the row index */
+ r = ONES_COMPLEMENT (*psrc) ;
+ COLAMD_ASSERT (r >= 0 && r < n_row) ;
+ /* restore first column index */
+ *psrc = Row [r].shared2.first_column ;
+ COLAMD_ASSERT (ROW_IS_ALIVE (r)) ;
+
+ /* move and compact the row */
+ COLAMD_ASSERT (pdest <= psrc) ;
+ Row [r].start = (Index) (pdest - &A [0]) ;
+ length = Row [r].length ;
+ for (j = 0 ; j < length ; j++)
+ {
+ c = *psrc++ ;
+ if (COL_IS_ALIVE (c))
+ {
+ *pdest++ = c ;
+ }
+ }
+ Row [r].length = (Index) (pdest - &A [Row [r].start]) ;
+
+ }
+ }
+ /* ensure we found all the rows */
+ COLAMD_ASSERT (debug_rows == 0) ;
+
+ /* === Return the new value of pfree ==================================== */
+
+ return ((Index) (pdest - &A [0])) ;
+}
+
+
+/* ========================================================================== */
+/* === clear_mark =========================================================== */
+/* ========================================================================== */
+
+/*
+ Clears the Row [].shared2.mark array, and returns the new tag_mark.
+ Return value is the new tag_mark. Not user-callable.
+*/
+template <typename Index>
+static inline Index clear_mark /* return the new value for tag_mark */
+ (
+ /* === Parameters ======================================================= */
+
+ Index n_row, /* number of rows in A */
+ Colamd_Row<Index> Row [] /* Row [0 ... n_row-1].shared2.mark is set to zero */
+ )
+{
+ /* === Local variables ================================================== */
+
+ Index r ;
+
+ for (r = 0 ; r < n_row ; r++)
+ {
+ if (ROW_IS_ALIVE (r))
+ {
+ Row [r].shared2.mark = 0 ;
+ }
+ }
+ return (1) ;
+}
+
+
+} // namespace internal
+#endif
diff --git a/Eigen/src/OrderingMethods/Ordering.h b/Eigen/src/OrderingMethods/Ordering.h
new file mode 100644
index 000000000..f3c31f9cb
--- /dev/null
+++ b/Eigen/src/OrderingMethods/Ordering.h
@@ -0,0 +1,154 @@
+
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef EIGEN_ORDERING_H
+#define EIGEN_ORDERING_H
+
+namespace Eigen {
+
+#include "Eigen_Colamd.h"
+
+namespace internal {
+
+/** \internal
+ * \ingroup OrderingMethods_Module
+ * \returns the symmetric pattern A^T+A from the input matrix A.
+ * FIXME: The values should not be considered here
+ */
+template<typename MatrixType>
+void ordering_helper_at_plus_a(const MatrixType& mat, MatrixType& symmat)
+{
+ MatrixType C;
+ C = mat.transpose(); // NOTE: Could be costly
+ for (int i = 0; i < C.rows(); i++)
+ {
+ for (typename MatrixType::InnerIterator it(C, i); it; ++it)
+ it.valueRef() = 0.0;
+ }
+ symmat = C + mat;
+}
+
+}
+
+#ifndef EIGEN_MPL2_ONLY
+
+/** \ingroup OrderingMethods_Module
+ * \class AMDOrdering
+ *
+ * Functor computing the \em approximate \em minimum \em degree ordering
+ * If the matrix is not structurally symmetric, an ordering of A^T+A is computed
+ * \tparam Index The type of indices of the matrix
+ * \sa COLAMDOrdering
+ */
+template <typename Index>
+class AMDOrdering
+{
+ public:
+ typedef PermutationMatrix<Dynamic, Dynamic, Index> PermutationType;
+
+ /** Compute the permutation vector from a sparse matrix
+ * This routine is much faster if the input matrix is column-major
+ */
+ template <typename MatrixType>
+ void operator()(const MatrixType& mat, PermutationType& perm)
+ {
+ // Compute the symmetric pattern
+ SparseMatrix<typename MatrixType::Scalar, ColMajor, Index> symm;
+ internal::ordering_helper_at_plus_a(mat,symm);
+
+ // Call the AMD routine
+ //m_mat.prune(keep_diag());
+ internal::minimum_degree_ordering(symm, perm);
+ }
+
+ /** Compute the permutation with a selfadjoint matrix */
+ template <typename SrcType, unsigned int SrcUpLo>
+ void operator()(const SparseSelfAdjointView<SrcType, SrcUpLo>& mat, PermutationType& perm)
+ {
+ SparseMatrix<typename SrcType::Scalar, ColMajor, Index> C; C = mat;
+
+ // Call the AMD routine
+ // m_mat.prune(keep_diag()); //Remove the diagonal elements
+ internal::minimum_degree_ordering(C, perm);
+ }
+};
+
+#endif // EIGEN_MPL2_ONLY
+
+/** \ingroup OrderingMethods_Module
+ * \class NaturalOrdering
+ *
+ * Functor computing the natural ordering (identity)
+ *
+ * \note Returns an empty permutation matrix
+ * \tparam Index The type of indices of the matrix
+ */
+template <typename Index>
+class NaturalOrdering
+{
+ public:
+ typedef PermutationMatrix<Dynamic, Dynamic, Index> PermutationType;
+
+ /** Compute the permutation vector from a column-major sparse matrix */
+ template <typename MatrixType>
+ void operator()(const MatrixType& /*mat*/, PermutationType& perm)
+ {
+ perm.resize(0);
+ }
+
+};
+
+/** \ingroup OrderingMethods_Module
+ * \class COLAMDOrdering
+ *
+ * Functor computing the \em column \em approximate \em minimum \em degree ordering
+ * The matrix should be in column-major and \b compressed format (see SparseMatrix::makeCompressed()).
+ */
+template<typename Index>
+class COLAMDOrdering
+{
+ public:
+ typedef PermutationMatrix<Dynamic, Dynamic, Index> PermutationType;
+ typedef Matrix<Index, Dynamic, 1> IndexVector;
+
+ /** Compute the permutation vector \a perm form the sparse matrix \a mat
+ * \warning The input sparse matrix \a mat must be in compressed mode (see SparseMatrix::makeCompressed()).
+ */
+ template <typename MatrixType>
+ void operator() (const MatrixType& mat, PermutationType& perm)
+ {
+ eigen_assert(mat.isCompressed() && "COLAMDOrdering requires a sparse matrix in compressed mode. Call .makeCompressed() before passing it to COLAMDOrdering");
+
+ Index m = mat.rows();
+ Index n = mat.cols();
+ Index nnz = mat.nonZeros();
+ // Get the recommended value of Alen to be used by colamd
+ Index Alen = internal::colamd_recommended(nnz, m, n);
+ // Set the default parameters
+ double knobs [COLAMD_KNOBS];
+ Index stats [COLAMD_STATS];
+ internal::colamd_set_defaults(knobs);
+
+ IndexVector p(n+1), A(Alen);
+ for(Index i=0; i <= n; i++) p(i) = mat.outerIndexPtr()[i];
+ for(Index i=0; i < nnz; i++) A(i) = mat.innerIndexPtr()[i];
+ // Call Colamd routine to compute the ordering
+ Index info = internal::colamd(m, n, Alen, A.data(), p.data(), knobs, stats);
+ EIGEN_UNUSED_VARIABLE(info);
+ eigen_assert( info && "COLAMD failed " );
+
+ perm.resize(n);
+ for (Index i = 0; i < n; i++) perm.indices()(p(i)) = i;
+ }
+};
+
+} // end namespace Eigen
+
+#endif
diff --git a/Eigen/src/PaStiXSupport/PaStiXSupport.h b/Eigen/src/PaStiXSupport/PaStiXSupport.h
index 82e137c64..a955287d1 100644
--- a/Eigen/src/PaStiXSupport/PaStiXSupport.h
+++ b/Eigen/src/PaStiXSupport/PaStiXSupport.h
@@ -157,27 +157,6 @@ class PastixBase : internal::noncopyable
template<typename Rhs,typename Dest>
bool _solve (const MatrixBase<Rhs> &b, MatrixBase<Dest> &x) const;
- /** \internal */
- template<typename Rhs, typename DestScalar, int DestOptions, typename DestIndex>
- void _solve_sparse(const Rhs& b, SparseMatrix<DestScalar,DestOptions,DestIndex> &dest) const
- {
- eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
- eigen_assert(rows()==b.rows());
-
- // we process the sparse rhs per block of NbColsAtOnce columns temporarily stored into a dense matrix.
- static const int NbColsAtOnce = 1;
- int rhsCols = b.cols();
- int size = b.rows();
- Eigen::Matrix<DestScalar,Dynamic,Dynamic> tmp(size,rhsCols);
- for(int k=0; k<rhsCols; k+=NbColsAtOnce)
- {
- int actualCols = std::min<int>(rhsCols-k, NbColsAtOnce);
- tmp.leftCols(actualCols) = b.middleCols(k,actualCols);
- tmp.leftCols(actualCols) = derived().solve(tmp.leftCols(actualCols));
- dest.middleCols(k,actualCols) = tmp.leftCols(actualCols).sparseView();
- }
- }
-
Derived& derived()
{
return *static_cast<Derived*>(this);
@@ -731,7 +710,7 @@ struct sparse_solve_retval<PastixBase<_MatrixType>, Rhs>
template<typename Dest> void evalTo(Dest& dst) const
{
- dec()._solve_sparse(rhs(),dst);
+ this->defaultEvalTo(dst);
}
};
diff --git a/Eigen/src/PardisoSupport/PardisoSupport.h b/Eigen/src/PardisoSupport/PardisoSupport.h
index e6defc8c3..1c48f0df7 100644
--- a/Eigen/src/PardisoSupport/PardisoSupport.h
+++ b/Eigen/src/PardisoSupport/PardisoSupport.h
@@ -108,6 +108,7 @@ class PardisoImpl
typedef Matrix<Scalar,Dynamic,1> VectorType;
typedef Matrix<Index, 1, MatrixType::ColsAtCompileTime> IntRowVectorType;
typedef Matrix<Index, MatrixType::RowsAtCompileTime, 1> IntColVectorType;
+ typedef Array<Index,64,1,DontAlign> ParameterType;
enum {
ScalarIsComplex = NumTraits<Scalar>::IsComplex
};
@@ -142,7 +143,7 @@ class PardisoImpl
/** \warning for advanced usage only.
* \returns a reference to the parameter array controlling PARDISO.
* See the PARDISO manual to know how to use it. */
- Array<Index,64,1>& pardisoParameterArray()
+ ParameterType& pardisoParameterArray()
{
return m_iparm;
}
@@ -205,29 +206,6 @@ class PardisoImpl
template<typename BDerived, typename XDerived>
bool _solve(const MatrixBase<BDerived> &b, MatrixBase<XDerived>& x) const;
- /** \internal */
- template<typename Rhs, typename DestScalar, int DestOptions, typename DestIndex>
- void _solve_sparse(const Rhs& b, SparseMatrix<DestScalar,DestOptions,DestIndex> &dest) const
- {
- eigen_assert(m_size==b.rows());
-
- // we process the sparse rhs per block of NbColsAtOnce columns temporarily stored into a dense matrix.
- static const int NbColsAtOnce = 4;
- int rhsCols = b.cols();
- int size = b.rows();
- // Pardiso cannot solve in-place,
- // so we need two temporaries
- Eigen::Matrix<DestScalar,Dynamic,Dynamic,ColMajor> tmp_rhs(size,rhsCols);
- Eigen::Matrix<DestScalar,Dynamic,Dynamic,ColMajor> tmp_res(size,rhsCols);
- for(int k=0; k<rhsCols; k+=NbColsAtOnce)
- {
- int actualCols = std::min<int>(rhsCols-k, NbColsAtOnce);
- tmp_rhs.leftCols(actualCols) = b.middleCols(k,actualCols);
- tmp_res.leftCols(actualCols) = derived().solve(tmp_rhs.leftCols(actualCols));
- dest.middleCols(k,actualCols) = tmp_res.leftCols(actualCols).sparseView();
- }
- }
-
protected:
void pardisoRelease()
{
@@ -295,7 +273,7 @@ class PardisoImpl
bool m_initialized, m_analysisIsOk, m_factorizationIsOk;
Index m_type, m_msglvl;
mutable void *m_pt[64];
- mutable Array<Index,64,1> m_iparm;
+ mutable ParameterType m_iparm;
mutable IntColVectorType m_perm;
Index m_size;
@@ -603,7 +581,7 @@ struct sparse_solve_retval<PardisoImpl<Derived>, Rhs>
template<typename Dest> void evalTo(Dest& dst) const
{
- dec().derived()._solve_sparse(rhs(),dst);
+ this->defaultEvalTo(dst);
}
};
diff --git a/Eigen/src/QR/ColPivHouseholderQR.h b/Eigen/src/QR/ColPivHouseholderQR.h
index 2daa23cc3..773d1df8f 100644
--- a/Eigen/src/QR/ColPivHouseholderQR.h
+++ b/Eigen/src/QR/ColPivHouseholderQR.h
@@ -55,7 +55,13 @@ template<typename _MatrixType> class ColPivHouseholderQR
typedef typename internal::plain_row_type<MatrixType, Index>::type IntRowVectorType;
typedef typename internal::plain_row_type<MatrixType>::type RowVectorType;
typedef typename internal::plain_row_type<MatrixType, RealScalar>::type RealRowVectorType;
- typedef typename HouseholderSequence<MatrixType,HCoeffsType>::ConjugateReturnType HouseholderSequenceType;
+ typedef HouseholderSequence<MatrixType,typename internal::remove_all<typename HCoeffsType::ConjugateReturnType>::type> HouseholderSequenceType;
+
+ private:
+
+ typedef typename PermutationType::Index PermIndexType;
+
+ public:
/**
* \brief Default Constructor.
@@ -70,7 +76,8 @@ template<typename _MatrixType> class ColPivHouseholderQR
m_colsTranspositions(),
m_temp(),
m_colSqNorms(),
- m_isInitialized(false) {}
+ m_isInitialized(false),
+ m_usePrescribedThreshold(false) {}
/** \brief Default Constructor with memory preallocation
*
@@ -81,17 +88,29 @@ template<typename _MatrixType> class ColPivHouseholderQR
ColPivHouseholderQR(Index rows, Index cols)
: m_qr(rows, cols),
m_hCoeffs((std::min)(rows,cols)),
- m_colsPermutation(cols),
+ m_colsPermutation(PermIndexType(cols)),
m_colsTranspositions(cols),
m_temp(cols),
m_colSqNorms(cols),
m_isInitialized(false),
m_usePrescribedThreshold(false) {}
+ /** \brief Constructs a QR factorization from a given matrix
+ *
+ * This constructor computes the QR factorization of the matrix \a matrix by calling
+ * the method compute(). It is a short cut for:
+ *
+ * \code
+ * ColPivHouseholderQR<MatrixType> qr(matrix.rows(), matrix.cols());
+ * qr.compute(matrix);
+ * \endcode
+ *
+ * \sa compute()
+ */
ColPivHouseholderQR(const MatrixType& matrix)
: m_qr(matrix.rows(), matrix.cols()),
m_hCoeffs((std::min)(matrix.rows(),matrix.cols())),
- m_colsPermutation(matrix.cols()),
+ m_colsPermutation(PermIndexType(matrix.cols())),
m_colsTranspositions(matrix.cols()),
m_temp(matrix.cols()),
m_colSqNorms(matrix.cols()),
@@ -127,6 +146,10 @@ template<typename _MatrixType> class ColPivHouseholderQR
}
HouseholderSequenceType householderQ(void) const;
+ HouseholderSequenceType matrixQ(void) const
+ {
+ return householderQ();
+ }
/** \returns a reference to the matrix where the Householder QR decomposition is stored
*/
@@ -135,9 +158,25 @@ template<typename _MatrixType> class ColPivHouseholderQR
eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
return m_qr;
}
-
+
+ /** \returns a reference to the matrix where the result Householder QR is stored
+ * \warning The strict lower part of this matrix contains internal values.
+ * Only the upper triangular part should be referenced. To get it, use
+ * \code matrixR().template triangularView<Upper>() \endcode
+ * For rank-deficient matrices, use
+ * \code
+ * matrixR().topLeftCorner(rank(), rank()).template triangularView<Upper>()
+ * \endcode
+ */
+ const MatrixType& matrixR() const
+ {
+ eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
+ return m_qr;
+ }
+
ColPivHouseholderQR& compute(const MatrixType& matrix);
+ /** \returns a const reference to the column permutation matrix */
const PermutationType& colsPermutation() const
{
eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
@@ -181,11 +220,12 @@ template<typename _MatrixType> class ColPivHouseholderQR
*/
inline Index rank() const
{
+ using std::abs;
eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
- RealScalar premultiplied_threshold = internal::abs(m_maxpivot) * threshold();
+ RealScalar premultiplied_threshold = abs(m_maxpivot) * threshold();
Index result = 0;
for(Index i = 0; i < m_nonzero_pivots; ++i)
- result += (internal::abs(m_qr.coeff(i,i)) > premultiplied_threshold);
+ result += (abs(m_qr.coeff(i,i)) > premultiplied_threshold);
return result;
}
@@ -255,6 +295,11 @@ template<typename _MatrixType> class ColPivHouseholderQR
inline Index rows() const { return m_qr.rows(); }
inline Index cols() const { return m_qr.cols(); }
+
+ /** \returns a const reference to the vector of Householder coefficients used to represent the factor \c Q.
+ *
+ * For advanced uses only.
+ */
const HCoeffsType& hCoeffs() const { return m_hCoeffs; }
/** Allows to prescribe a threshold to be used by certain methods, such as rank(),
@@ -305,7 +350,7 @@ template<typename _MatrixType> class ColPivHouseholderQR
return m_usePrescribedThreshold ? m_prescribedThreshold
// this formula comes from experimenting (see "LU precision tuning" thread on the list)
// and turns out to be identical to Higham's formula used already in LDLt.
- : NumTraits<Scalar>::epsilon() * m_qr.diagonalSize();
+ : NumTraits<Scalar>::epsilon() * RealScalar(m_qr.diagonalSize());
}
/** \returns the number of nonzero pivots in the QR decomposition.
@@ -325,6 +370,18 @@ template<typename _MatrixType> class ColPivHouseholderQR
* diagonal coefficient of R.
*/
RealScalar maxPivot() const { return m_maxpivot; }
+
+ /** \brief Reports whether the QR factorization was succesful.
+ *
+ * \note This function always returns \c Success. It is provided for compatibility
+ * with other factorization routines.
+ * \returns \c Success
+ */
+ ComputationInfo info() const
+ {
+ eigen_assert(m_isInitialized && "Decomposition is not initialized.");
+ return Success;
+ }
protected:
MatrixType m_qr;
@@ -342,9 +399,10 @@ template<typename _MatrixType> class ColPivHouseholderQR
template<typename MatrixType>
typename MatrixType::RealScalar ColPivHouseholderQR<MatrixType>::absDeterminant() const
{
+ using std::abs;
eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
- return internal::abs(m_qr.diagonal().prod());
+ return abs(m_qr.diagonal().prod());
}
template<typename MatrixType>
@@ -355,12 +413,22 @@ typename MatrixType::RealScalar ColPivHouseholderQR<MatrixType>::logAbsDetermina
return m_qr.diagonal().cwiseAbs().array().log().sum();
}
+/** Performs the QR factorization of the given matrix \a matrix. The result of
+ * the factorization is stored into \c *this, and a reference to \c *this
+ * is returned.
+ *
+ * \sa class ColPivHouseholderQR, ColPivHouseholderQR(const MatrixType&)
+ */
template<typename MatrixType>
ColPivHouseholderQR<MatrixType>& ColPivHouseholderQR<MatrixType>::compute(const MatrixType& matrix)
{
+ using std::abs;
Index rows = matrix.rows();
Index cols = matrix.cols();
Index size = matrix.diagonalSize();
+
+ // the column permutation is stored as int indices, so just to be sure:
+ eigen_assert(cols<=NumTraits<int>::highest());
m_qr = matrix;
m_hCoeffs.resize(size);
@@ -374,7 +442,7 @@ ColPivHouseholderQR<MatrixType>& ColPivHouseholderQR<MatrixType>::compute(const
for(Index k = 0; k < cols; ++k)
m_colSqNorms.coeffRef(k) = m_qr.col(k).squaredNorm();
- RealScalar threshold_helper = m_colSqNorms.maxCoeff() * internal::abs2(NumTraits<Scalar>::epsilon()) / RealScalar(rows);
+ RealScalar threshold_helper = m_colSqNorms.maxCoeff() * numext::abs2(NumTraits<Scalar>::epsilon()) / RealScalar(rows);
m_nonzero_pivots = size; // the generic case is that in which all pivots are nonzero (invertible case)
m_maxpivot = RealScalar(0);
@@ -426,7 +494,7 @@ ColPivHouseholderQR<MatrixType>& ColPivHouseholderQR<MatrixType>::compute(const
m_qr.coeffRef(k,k) = beta;
// remember the maximum absolute value of diagonal coefficients
- if(internal::abs(beta) > m_maxpivot) m_maxpivot = internal::abs(beta);
+ if(abs(beta) > m_maxpivot) m_maxpivot = abs(beta);
// apply the householder transformation
m_qr.bottomRightCorner(rows-k, cols-k-1)
@@ -436,9 +504,9 @@ ColPivHouseholderQR<MatrixType>& ColPivHouseholderQR<MatrixType>::compute(const
m_colSqNorms.tail(cols-k-1) -= m_qr.row(k).tail(cols-k-1).cwiseAbs2();
}
- m_colsPermutation.setIdentity(cols);
- for(Index k = 0; k < m_nonzero_pivots; ++k)
- m_colsPermutation.applyTranspositionOnTheRight(k, m_colsTranspositions.coeff(k));
+ m_colsPermutation.setIdentity(PermIndexType(cols));
+ for(PermIndexType k = 0; k < m_nonzero_pivots; ++k)
+ m_colsPermutation.applyTranspositionOnTheRight(k, PermIndexType(m_colsTranspositions.coeff(k)));
m_det_pq = (number_of_transpositions%2) ? -1 : 1;
m_isInitialized = true;
@@ -458,8 +526,8 @@ struct solve_retval<ColPivHouseholderQR<_MatrixType>, Rhs>
{
eigen_assert(rhs().rows() == dec().rows());
- const int cols = dec().cols(),
- nonzero_pivots = dec().nonzeroPivots();
+ const Index cols = dec().cols(),
+ nonzero_pivots = dec().nonzeroPivots();
if(nonzero_pivots == 0)
{
@@ -475,19 +543,11 @@ struct solve_retval<ColPivHouseholderQR<_MatrixType>, Rhs>
.transpose()
);
- dec().matrixQR()
+ dec().matrixR()
.topLeftCorner(nonzero_pivots, nonzero_pivots)
.template triangularView<Upper>()
.solveInPlace(c.topRows(nonzero_pivots));
-
- typename Rhs::PlainObject d(c);
- d.topRows(nonzero_pivots)
- = dec().matrixQR()
- .topLeftCorner(nonzero_pivots, nonzero_pivots)
- .template triangularView<Upper>()
- * c.topRows(nonzero_pivots);
-
for(Index i = 0; i < nonzero_pivots; ++i) dst.row(dec().colsPermutation().indices().coeff(i)) = c.row(i);
for(Index i = nonzero_pivots; i < cols; ++i) dst.row(dec().colsPermutation().indices().coeff(i)).setZero();
}
diff --git a/Eigen/src/QR/ColPivHouseholderQR_MKL.h b/Eigen/src/QR/ColPivHouseholderQR_MKL.h
index 745ecf8be..b5b198326 100644
--- a/Eigen/src/QR/ColPivHouseholderQR_MKL.h
+++ b/Eigen/src/QR/ColPivHouseholderQR_MKL.h
@@ -41,12 +41,13 @@ namespace Eigen {
/** \internal Specialization for the data types supported by MKL */
#define EIGEN_MKL_QR_COLPIV(EIGTYPE, MKLTYPE, MKLPREFIX, EIGCOLROW, MKLCOLROW) \
-template<> inline\
+template<> inline \
ColPivHouseholderQR<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic> >& \
ColPivHouseholderQR<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic> >::compute( \
const Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic>& matrix) \
\
{ \
+ using std::abs; \
typedef Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic> MatrixType; \
typedef MatrixType::Scalar Scalar; \
typedef MatrixType::RealScalar RealScalar; \
@@ -71,10 +72,10 @@ ColPivHouseholderQR<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynami
m_isInitialized = true; \
m_maxpivot=m_qr.diagonal().cwiseAbs().maxCoeff(); \
m_hCoeffs.adjointInPlace(); \
- RealScalar premultiplied_threshold = internal::abs(m_maxpivot) * threshold(); \
+ RealScalar premultiplied_threshold = abs(m_maxpivot) * threshold(); \
lapack_int *perm = m_colsPermutation.indices().data(); \
for(i=0;i<size;i++) { \
- m_nonzero_pivots += (internal::abs(m_qr.coeff(i,i)) > premultiplied_threshold);\
+ m_nonzero_pivots += (abs(m_qr.coeff(i,i)) > premultiplied_threshold);\
} \
for(i=0;i<cols;i++) perm[i]--;\
\
diff --git a/Eigen/src/QR/FullPivHouseholderQR.h b/Eigen/src/QR/FullPivHouseholderQR.h
index 37898e77c..6168e7abf 100644
--- a/Eigen/src/QR/FullPivHouseholderQR.h
+++ b/Eigen/src/QR/FullPivHouseholderQR.h
@@ -63,9 +63,10 @@ template<typename _MatrixType> class FullPivHouseholderQR
typedef typename MatrixType::Index Index;
typedef internal::FullPivHouseholderQRMatrixQReturnType<MatrixType> MatrixQReturnType;
typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
- typedef Matrix<Index, 1, ColsAtCompileTime, RowMajor, 1, MaxColsAtCompileTime> IntRowVectorType;
+ typedef Matrix<Index, 1,
+ EIGEN_SIZE_MIN_PREFER_DYNAMIC(ColsAtCompileTime,RowsAtCompileTime), RowMajor, 1,
+ EIGEN_SIZE_MIN_PREFER_FIXED(MaxColsAtCompileTime,MaxRowsAtCompileTime)> IntDiagSizeVectorType;
typedef PermutationMatrix<ColsAtCompileTime, MaxColsAtCompileTime> PermutationType;
- typedef typename internal::plain_col_type<MatrixType, Index>::type IntColVectorType;
typedef typename internal::plain_row_type<MatrixType>::type RowVectorType;
typedef typename internal::plain_col_type<MatrixType>::type ColVectorType;
@@ -93,20 +94,32 @@ template<typename _MatrixType> class FullPivHouseholderQR
FullPivHouseholderQR(Index rows, Index cols)
: m_qr(rows, cols),
m_hCoeffs((std::min)(rows,cols)),
- m_rows_transpositions(rows),
- m_cols_transpositions(cols),
+ m_rows_transpositions((std::min)(rows,cols)),
+ m_cols_transpositions((std::min)(rows,cols)),
m_cols_permutation(cols),
- m_temp((std::min)(rows,cols)),
+ m_temp(cols),
m_isInitialized(false),
m_usePrescribedThreshold(false) {}
+ /** \brief Constructs a QR factorization from a given matrix
+ *
+ * This constructor computes the QR factorization of the matrix \a matrix by calling
+ * the method compute(). It is a short cut for:
+ *
+ * \code
+ * FullPivHouseholderQR<MatrixType> qr(matrix.rows(), matrix.cols());
+ * qr.compute(matrix);
+ * \endcode
+ *
+ * \sa compute()
+ */
FullPivHouseholderQR(const MatrixType& matrix)
: m_qr(matrix.rows(), matrix.cols()),
m_hCoeffs((std::min)(matrix.rows(), matrix.cols())),
- m_rows_transpositions(matrix.rows()),
- m_cols_transpositions(matrix.cols()),
+ m_rows_transpositions((std::min)(matrix.rows(), matrix.cols())),
+ m_cols_transpositions((std::min)(matrix.rows(), matrix.cols())),
m_cols_permutation(matrix.cols()),
- m_temp((std::min)(matrix.rows(), matrix.cols())),
+ m_temp(matrix.cols()),
m_isInitialized(false),
m_usePrescribedThreshold(false)
{
@@ -114,11 +127,12 @@ template<typename _MatrixType> class FullPivHouseholderQR
}
/** This method finds a solution x to the equation Ax=b, where A is the matrix of which
- * *this is the QR decomposition, if any exists.
+ * \c *this is the QR decomposition.
*
* \param b the right-hand-side of the equation to solve.
*
- * \returns a solution.
+ * \returns the exact or least-square solution if the rank is greater or equal to the number of columns of A,
+ * and an arbitrary solution otherwise.
*
* \note The case where b is a matrix is not yet implemented. Also, this
* code is space inefficient.
@@ -152,13 +166,15 @@ template<typename _MatrixType> class FullPivHouseholderQR
FullPivHouseholderQR& compute(const MatrixType& matrix);
+ /** \returns a const reference to the column permutation matrix */
const PermutationType& colsPermutation() const
{
eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized.");
return m_cols_permutation;
}
- const IntColVectorType& rowsTranspositions() const
+ /** \returns a const reference to the vector of indices representing the rows transpositions */
+ const IntDiagSizeVectorType& rowsTranspositions() const
{
eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized.");
return m_rows_transpositions;
@@ -201,11 +217,12 @@ template<typename _MatrixType> class FullPivHouseholderQR
*/
inline Index rank() const
{
+ using std::abs;
eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized.");
- RealScalar premultiplied_threshold = internal::abs(m_maxpivot) * threshold();
+ RealScalar premultiplied_threshold = abs(m_maxpivot) * threshold();
Index result = 0;
for(Index i = 0; i < m_nonzero_pivots; ++i)
- result += (internal::abs(m_qr.coeff(i,i)) > premultiplied_threshold);
+ result += (abs(m_qr.coeff(i,i)) > premultiplied_threshold);
return result;
}
@@ -274,6 +291,11 @@ template<typename _MatrixType> class FullPivHouseholderQR
inline Index rows() const { return m_qr.rows(); }
inline Index cols() const { return m_qr.cols(); }
+
+ /** \returns a const reference to the vector of Householder coefficients used to represent the factor \c Q.
+ *
+ * For advanced uses only.
+ */
const HCoeffsType& hCoeffs() const { return m_hCoeffs; }
/** Allows to prescribe a threshold to be used by certain methods, such as rank(),
@@ -324,7 +346,7 @@ template<typename _MatrixType> class FullPivHouseholderQR
return m_usePrescribedThreshold ? m_prescribedThreshold
// this formula comes from experimenting (see "LU precision tuning" thread on the list)
// and turns out to be identical to Higham's formula used already in LDLt.
- : NumTraits<Scalar>::epsilon() * m_qr.diagonalSize();
+ : NumTraits<Scalar>::epsilon() * RealScalar(m_qr.diagonalSize());
}
/** \returns the number of nonzero pivots in the QR decomposition.
@@ -348,8 +370,8 @@ template<typename _MatrixType> class FullPivHouseholderQR
protected:
MatrixType m_qr;
HCoeffsType m_hCoeffs;
- IntColVectorType m_rows_transpositions;
- IntRowVectorType m_cols_transpositions;
+ IntDiagSizeVectorType m_rows_transpositions;
+ IntDiagSizeVectorType m_cols_transpositions;
PermutationType m_cols_permutation;
RowVectorType m_temp;
bool m_isInitialized, m_usePrescribedThreshold;
@@ -362,9 +384,10 @@ template<typename _MatrixType> class FullPivHouseholderQR
template<typename MatrixType>
typename MatrixType::RealScalar FullPivHouseholderQR<MatrixType>::absDeterminant() const
{
+ using std::abs;
eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized.");
eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
- return internal::abs(m_qr.diagonal().prod());
+ return abs(m_qr.diagonal().prod());
}
template<typename MatrixType>
@@ -375,9 +398,16 @@ typename MatrixType::RealScalar FullPivHouseholderQR<MatrixType>::logAbsDetermin
return m_qr.diagonal().cwiseAbs().array().log().sum();
}
+/** Performs the QR factorization of the given matrix \a matrix. The result of
+ * the factorization is stored into \c *this, and a reference to \c *this
+ * is returned.
+ *
+ * \sa class FullPivHouseholderQR, FullPivHouseholderQR(const MatrixType&)
+ */
template<typename MatrixType>
FullPivHouseholderQR<MatrixType>& FullPivHouseholderQR<MatrixType>::compute(const MatrixType& matrix)
{
+ using std::abs;
Index rows = matrix.rows();
Index cols = matrix.cols();
Index size = (std::min)(rows,cols);
@@ -387,10 +417,10 @@ FullPivHouseholderQR<MatrixType>& FullPivHouseholderQR<MatrixType>::compute(cons
m_temp.resize(cols);
- m_precision = NumTraits<Scalar>::epsilon() * size;
+ m_precision = NumTraits<Scalar>::epsilon() * RealScalar(size);
- m_rows_transpositions.resize(matrix.rows());
- m_cols_transpositions.resize(matrix.cols());
+ m_rows_transpositions.resize(size);
+ m_cols_transpositions.resize(size);
Index number_of_transpositions = 0;
RealScalar biggest(0);
@@ -439,7 +469,7 @@ FullPivHouseholderQR<MatrixType>& FullPivHouseholderQR<MatrixType>::compute(cons
m_qr.coeffRef(k,k) = beta;
// remember the maximum absolute value of diagonal coefficients
- if(internal::abs(beta) > m_maxpivot) m_maxpivot = internal::abs(beta);
+ if(abs(beta) > m_maxpivot) m_maxpivot = abs(beta);
m_qr.bottomRightCorner(rows-k, cols-k-1)
.applyHouseholderOnTheLeft(m_qr.col(k).tail(rows-k-1), m_hCoeffs.coeffRef(k), &m_temp.coeffRef(k+1));
@@ -488,17 +518,6 @@ struct solve_retval<FullPivHouseholderQR<_MatrixType>, Rhs>
dec().hCoeffs().coeff(k), &temp.coeffRef(0));
}
- if(!dec().isSurjective())
- {
- // is c is in the image of R ?
- RealScalar biggest_in_upper_part_of_c = c.topRows( dec().rank() ).cwiseAbs().maxCoeff();
- RealScalar biggest_in_lower_part_of_c = c.bottomRows(rows-dec().rank()).cwiseAbs().maxCoeff();
- // FIXME brain dead
- const RealScalar m_precision = NumTraits<Scalar>::epsilon() * (std::min)(rows,cols);
- // this internal:: prefix is needed by at least gcc 3.4 and ICC
- if(!internal::isMuchSmallerThan(biggest_in_lower_part_of_c, biggest_in_upper_part_of_c, m_precision))
- return;
- }
dec().matrixQR()
.topLeftCorner(dec().rank(), dec().rank())
.template triangularView<Upper>()
@@ -520,14 +539,14 @@ template<typename MatrixType> struct FullPivHouseholderQRMatrixQReturnType
{
public:
typedef typename MatrixType::Index Index;
- typedef typename internal::plain_col_type<MatrixType, Index>::type IntColVectorType;
+ typedef typename FullPivHouseholderQR<MatrixType>::IntDiagSizeVectorType IntDiagSizeVectorType;
typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
typedef Matrix<typename MatrixType::Scalar, 1, MatrixType::RowsAtCompileTime, RowMajor, 1,
MatrixType::MaxRowsAtCompileTime> WorkVectorType;
FullPivHouseholderQRMatrixQReturnType(const MatrixType& qr,
const HCoeffsType& hCoeffs,
- const IntColVectorType& rowsTranspositions)
+ const IntDiagSizeVectorType& rowsTranspositions)
: m_qr(qr),
m_hCoeffs(hCoeffs),
m_rowsTranspositions(rowsTranspositions)
@@ -544,6 +563,7 @@ public:
template <typename ResultType>
void evalTo(ResultType& result, WorkVectorType& workspace) const
{
+ using numext::conj;
// compute the product H'_0 H'_1 ... H'_n-1,
// where H_k is the k-th Householder transformation I - h_k v_k v_k'
// and v_k is the k-th Householder vector [1,m_qr(k+1,k), m_qr(k+2,k), ...]
@@ -555,7 +575,7 @@ public:
for (Index k = size-1; k >= 0; k--)
{
result.block(k, k, rows-k, rows-k)
- .applyHouseholderOnTheLeft(m_qr.col(k).tail(rows-k-1), internal::conj(m_hCoeffs.coeff(k)), &workspace.coeffRef(k));
+ .applyHouseholderOnTheLeft(m_qr.col(k).tail(rows-k-1), conj(m_hCoeffs.coeff(k)), &workspace.coeffRef(k));
result.row(k).swap(result.row(m_rowsTranspositions.coeff(k)));
}
}
@@ -566,7 +586,7 @@ public:
protected:
typename MatrixType::Nested m_qr;
typename HCoeffsType::Nested m_hCoeffs;
- typename IntColVectorType::Nested m_rowsTranspositions;
+ typename IntDiagSizeVectorType::Nested m_rowsTranspositions;
};
} // end namespace internal
diff --git a/Eigen/src/QR/HouseholderQR.h b/Eigen/src/QR/HouseholderQR.h
index 5bcb32c1e..abc61bcbb 100644
--- a/Eigen/src/QR/HouseholderQR.h
+++ b/Eigen/src/QR/HouseholderQR.h
@@ -57,14 +57,14 @@ template<typename _MatrixType> class HouseholderQR
typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime, (MatrixType::Flags&RowMajorBit) ? RowMajor : ColMajor, MaxRowsAtCompileTime, MaxRowsAtCompileTime> MatrixQType;
typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
typedef typename internal::plain_row_type<MatrixType>::type RowVectorType;
- typedef typename HouseholderSequence<MatrixType,HCoeffsType>::ConjugateReturnType HouseholderSequenceType;
+ typedef HouseholderSequence<MatrixType,typename internal::remove_all<typename HCoeffsType::ConjugateReturnType>::type> HouseholderSequenceType;
/**
- * \brief Default Constructor.
- *
- * The default constructor is useful in cases in which the user intends to
- * perform decompositions via HouseholderQR::compute(const MatrixType&).
- */
+ * \brief Default Constructor.
+ *
+ * The default constructor is useful in cases in which the user intends to
+ * perform decompositions via HouseholderQR::compute(const MatrixType&).
+ */
HouseholderQR() : m_qr(), m_hCoeffs(), m_temp(), m_isInitialized(false) {}
/** \brief Default Constructor with memory preallocation
@@ -79,6 +79,18 @@ template<typename _MatrixType> class HouseholderQR
m_temp(cols),
m_isInitialized(false) {}
+ /** \brief Constructs a QR factorization from a given matrix
+ *
+ * This constructor computes the QR factorization of the matrix \a matrix by calling
+ * the method compute(). It is a short cut for:
+ *
+ * \code
+ * HouseholderQR<MatrixType> qr(matrix.rows(), matrix.cols());
+ * qr.compute(matrix);
+ * \endcode
+ *
+ * \sa compute()
+ */
HouseholderQR(const MatrixType& matrix)
: m_qr(matrix.rows(), matrix.cols()),
m_hCoeffs((std::min)(matrix.rows(),matrix.cols())),
@@ -113,6 +125,14 @@ template<typename _MatrixType> class HouseholderQR
return internal::solve_retval<HouseholderQR, Rhs>(*this, b.derived());
}
+ /** This method returns an expression of the unitary matrix Q as a sequence of Householder transformations.
+ *
+ * The returned expression can directly be used to perform matrix products. It can also be assigned to a dense Matrix object.
+ * Here is an example showing how to recover the full or thin matrix Q, as well as how to perform matrix products using operator*:
+ *
+ * Example: \include HouseholderQR_householderQ.cpp
+ * Output: \verbinclude HouseholderQR_householderQ.out
+ */
HouseholderSequenceType householderQ() const
{
eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
@@ -161,6 +181,11 @@ template<typename _MatrixType> class HouseholderQR
inline Index rows() const { return m_qr.rows(); }
inline Index cols() const { return m_qr.cols(); }
+
+ /** \returns a const reference to the vector of Householder coefficients used to represent the factor \c Q.
+ *
+ * For advanced uses only.
+ */
const HCoeffsType& hCoeffs() const { return m_hCoeffs; }
protected:
@@ -173,9 +198,10 @@ template<typename _MatrixType> class HouseholderQR
template<typename MatrixType>
typename MatrixType::RealScalar HouseholderQR<MatrixType>::absDeterminant() const
{
+ using std::abs;
eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
- return internal::abs(m_qr.diagonal().prod());
+ return abs(m_qr.diagonal().prod());
}
template<typename MatrixType>
@@ -232,7 +258,6 @@ void householder_qr_inplace_blocked(MatrixQR& mat, HCoeffs& hCoeffs,
{
typedef typename MatrixQR::Index Index;
typedef typename MatrixQR::Scalar Scalar;
- typedef typename MatrixQR::RealScalar RealScalar;
typedef Block<MatrixQR,Dynamic,Dynamic> BlockType;
Index rows = mat.rows();
@@ -309,6 +334,12 @@ struct solve_retval<HouseholderQR<_MatrixType>, Rhs>
} // end namespace internal
+/** Performs the QR factorization of the given matrix \a matrix. The result of
+ * the factorization is stored into \c *this, and a reference to \c *this
+ * is returned.
+ *
+ * \sa class HouseholderQR, HouseholderQR(const MatrixType&)
+ */
template<typename MatrixType>
HouseholderQR<MatrixType>& HouseholderQR<MatrixType>::compute(const MatrixType& matrix)
{
diff --git a/Eigen/src/SPQRSupport/CMakeLists.txt b/Eigen/src/SPQRSupport/CMakeLists.txt
new file mode 100644
index 000000000..4968beaf2
--- /dev/null
+++ b/Eigen/src/SPQRSupport/CMakeLists.txt
@@ -0,0 +1,6 @@
+FILE(GLOB Eigen_SPQRSupport_SRCS "*.h")
+
+INSTALL(FILES
+ ${Eigen_SPQRSupport_SRCS}
+ DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/SPQRSupport/ COMPONENT Devel
+ )
diff --git a/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h b/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h
new file mode 100644
index 000000000..a2cc2a9e2
--- /dev/null
+++ b/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h
@@ -0,0 +1,314 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Desire Nuentsa <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef EIGEN_SUITESPARSEQRSUPPORT_H
+#define EIGEN_SUITESPARSEQRSUPPORT_H
+
+namespace Eigen {
+
+ template<typename MatrixType> class SPQR;
+ template<typename SPQRType> struct SPQRMatrixQReturnType;
+ template<typename SPQRType> struct SPQRMatrixQTransposeReturnType;
+ template <typename SPQRType, typename Derived> struct SPQR_QProduct;
+ namespace internal {
+ template <typename SPQRType> struct traits<SPQRMatrixQReturnType<SPQRType> >
+ {
+ typedef typename SPQRType::MatrixType ReturnType;
+ };
+ template <typename SPQRType> struct traits<SPQRMatrixQTransposeReturnType<SPQRType> >
+ {
+ typedef typename SPQRType::MatrixType ReturnType;
+ };
+ template <typename SPQRType, typename Derived> struct traits<SPQR_QProduct<SPQRType, Derived> >
+ {
+ typedef typename Derived::PlainObject ReturnType;
+ };
+ } // End namespace internal
+
+/**
+ * \ingroup SPQRSupport_Module
+ * \class SPQR
+ * \brief Sparse QR factorization based on SuiteSparseQR library
+ *
+ * This class is used to perform a multithreaded and multifrontal rank-revealing QR decomposition
+ * of sparse matrices. The result is then used to solve linear leasts_square systems.
+ * Clearly, a QR factorization is returned such that A*P = Q*R where :
+ *
+ * P is the column permutation. Use colsPermutation() to get it.
+ *
+ * Q is the orthogonal matrix represented as Householder reflectors.
+ * Use matrixQ() to get an expression and matrixQ().transpose() to get the transpose.
+ * You can then apply it to a vector.
+ *
+ * R is the sparse triangular factor. Use matrixQR() to get it as SparseMatrix.
+ * NOTE : The Index type of R is always UF_long. You can get it with SPQR::Index
+ *
+ * \tparam _MatrixType The type of the sparse matrix A, must be a column-major SparseMatrix<>
+ * NOTE
+ *
+ */
+template<typename _MatrixType>
+class SPQR
+{
+ public:
+ typedef typename _MatrixType::Scalar Scalar;
+ typedef typename _MatrixType::RealScalar RealScalar;
+ typedef UF_long Index ;
+ typedef SparseMatrix<Scalar, ColMajor, Index> MatrixType;
+ typedef PermutationMatrix<Dynamic, Dynamic> PermutationType;
+ public:
+ SPQR()
+ : m_isInitialized(false),
+ m_ordering(SPQR_ORDERING_DEFAULT),
+ m_allow_tol(SPQR_DEFAULT_TOL),
+ m_tolerance (NumTraits<Scalar>::epsilon())
+ {
+ cholmod_l_start(&m_cc);
+ }
+
+ SPQR(const _MatrixType& matrix)
+ : m_isInitialized(false),
+ m_ordering(SPQR_ORDERING_DEFAULT),
+ m_allow_tol(SPQR_DEFAULT_TOL),
+ m_tolerance (NumTraits<Scalar>::epsilon())
+ {
+ cholmod_l_start(&m_cc);
+ compute(matrix);
+ }
+
+ ~SPQR()
+ {
+ SPQR_free();
+ cholmod_l_finish(&m_cc);
+ }
+ void SPQR_free()
+ {
+ cholmod_l_free_sparse(&m_H, &m_cc);
+ cholmod_l_free_sparse(&m_cR, &m_cc);
+ cholmod_l_free_dense(&m_HTau, &m_cc);
+ std::free(m_E);
+ std::free(m_HPinv);
+ }
+
+ void compute(const _MatrixType& matrix)
+ {
+ if(m_isInitialized) SPQR_free();
+
+ MatrixType mat(matrix);
+ cholmod_sparse A;
+ A = viewAsCholmod(mat);
+ Index col = matrix.cols();
+ m_rank = SuiteSparseQR<Scalar>(m_ordering, m_tolerance, col, &A,
+ &m_cR, &m_E, &m_H, &m_HPinv, &m_HTau, &m_cc);
+
+ if (!m_cR)
+ {
+ m_info = NumericalIssue;
+ m_isInitialized = false;
+ return;
+ }
+ m_info = Success;
+ m_isInitialized = true;
+ m_isRUpToDate = false;
+ }
+ /**
+ * Get the number of rows of the input matrix and the Q matrix
+ */
+ inline Index rows() const {return m_H->nrow; }
+
+ /**
+ * Get the number of columns of the input matrix.
+ */
+ inline Index cols() const { return m_cR->ncol; }
+
+ /** \returns the solution X of \f$ A X = B \f$ using the current decomposition of A.
+ *
+ * \sa compute()
+ */
+ template<typename Rhs>
+ inline const internal::solve_retval<SPQR, Rhs> solve(const MatrixBase<Rhs>& B) const
+ {
+ eigen_assert(m_isInitialized && " The QR factorization should be computed first, call compute()");
+ eigen_assert(this->rows()==B.rows()
+ && "SPQR::solve(): invalid number of rows of the right hand side matrix B");
+ return internal::solve_retval<SPQR, Rhs>(*this, B.derived());
+ }
+
+ template<typename Rhs, typename Dest>
+ void _solve(const MatrixBase<Rhs> &b, MatrixBase<Dest> &dest) const
+ {
+ eigen_assert(m_isInitialized && " The QR factorization should be computed first, call compute()");
+ eigen_assert(b.cols()==1 && "This method is for vectors only");
+
+ //Compute Q^T * b
+ typename Dest::PlainObject y;
+ y = matrixQ().transpose() * b;
+ // Solves with the triangular matrix R
+ Index rk = this->rank();
+ y.topRows(rk) = this->matrixR().topLeftCorner(rk, rk).template triangularView<Upper>().solve(y.topRows(rk));
+ y.bottomRows(cols()-rk).setZero();
+ // Apply the column permutation
+ dest.topRows(cols()) = colsPermutation() * y.topRows(cols());
+
+ m_info = Success;
+ }
+
+ /** \returns the sparse triangular factor R. It is a sparse matrix
+ */
+ const MatrixType matrixR() const
+ {
+ eigen_assert(m_isInitialized && " The QR factorization should be computed first, call compute()");
+ if(!m_isRUpToDate) {
+ m_R = viewAsEigen<Scalar,ColMajor, typename MatrixType::Index>(*m_cR);
+ m_isRUpToDate = true;
+ }
+ return m_R;
+ }
+ /// Get an expression of the matrix Q
+ SPQRMatrixQReturnType<SPQR> matrixQ() const
+ {
+ return SPQRMatrixQReturnType<SPQR>(*this);
+ }
+ /// Get the permutation that was applied to columns of A
+ PermutationType colsPermutation() const
+ {
+ eigen_assert(m_isInitialized && "Decomposition is not initialized.");
+ Index n = m_cR->ncol;
+ PermutationType colsPerm(n);
+ for(Index j = 0; j <n; j++) colsPerm.indices()(j) = m_E[j];
+ return colsPerm;
+
+ }
+ /**
+ * Gets the rank of the matrix.
+ * It should be equal to matrixQR().cols if the matrix is full-rank
+ */
+ Index rank() const
+ {
+ eigen_assert(m_isInitialized && "Decomposition is not initialized.");
+ return m_cc.SPQR_istat[4];
+ }
+ /// Set the fill-reducing ordering method to be used
+ void setSPQROrdering(int ord) { m_ordering = ord;}
+ /// Set the tolerance tol to treat columns with 2-norm < =tol as zero
+ void setPivotThreshold(const RealScalar& tol) { m_tolerance = tol; }
+
+ /** \returns a pointer to the SPQR workspace */
+ cholmod_common *cholmodCommon() const { return &m_cc; }
+
+
+ /** \brief Reports whether previous computation was successful.
+ *
+ * \returns \c Success if computation was succesful,
+ * \c NumericalIssue if the sparse QR can not be computed
+ */
+ ComputationInfo info() const
+ {
+ eigen_assert(m_isInitialized && "Decomposition is not initialized.");
+ return m_info;
+ }
+ protected:
+ bool m_isInitialized;
+ bool m_analysisIsOk;
+ bool m_factorizationIsOk;
+ mutable bool m_isRUpToDate;
+ mutable ComputationInfo m_info;
+ int m_ordering; // Ordering method to use, see SPQR's manual
+ int m_allow_tol; // Allow to use some tolerance during numerical factorization.
+ RealScalar m_tolerance; // treat columns with 2-norm below this tolerance as zero
+ mutable cholmod_sparse *m_cR; // The sparse R factor in cholmod format
+ mutable MatrixType m_R; // The sparse matrix R in Eigen format
+ mutable Index *m_E; // The permutation applied to columns
+ mutable cholmod_sparse *m_H; //The householder vectors
+ mutable Index *m_HPinv; // The row permutation of H
+ mutable cholmod_dense *m_HTau; // The Householder coefficients
+ mutable Index m_rank; // The rank of the matrix
+ mutable cholmod_common m_cc; // Workspace and parameters
+ template<typename ,typename > friend struct SPQR_QProduct;
+};
+
+template <typename SPQRType, typename Derived>
+struct SPQR_QProduct : ReturnByValue<SPQR_QProduct<SPQRType,Derived> >
+{
+ typedef typename SPQRType::Scalar Scalar;
+ typedef typename SPQRType::Index Index;
+ //Define the constructor to get reference to argument types
+ SPQR_QProduct(const SPQRType& spqr, const Derived& other, bool transpose) : m_spqr(spqr),m_other(other),m_transpose(transpose) {}
+
+ inline Index rows() const { return m_transpose ? m_spqr.rows() : m_spqr.cols(); }
+ inline Index cols() const { return m_other.cols(); }
+ // Assign to a vector
+ template<typename ResType>
+ void evalTo(ResType& res) const
+ {
+ cholmod_dense y_cd;
+ cholmod_dense *x_cd;
+ int method = m_transpose ? SPQR_QTX : SPQR_QX;
+ cholmod_common *cc = m_spqr.cholmodCommon();
+ y_cd = viewAsCholmod(m_other.const_cast_derived());
+ x_cd = SuiteSparseQR_qmult<Scalar>(method, m_spqr.m_H, m_spqr.m_HTau, m_spqr.m_HPinv, &y_cd, cc);
+ res = Matrix<Scalar,ResType::RowsAtCompileTime,ResType::ColsAtCompileTime>::Map(reinterpret_cast<Scalar*>(x_cd->x), x_cd->nrow, x_cd->ncol);
+ cholmod_l_free_dense(&x_cd, cc);
+ }
+ const SPQRType& m_spqr;
+ const Derived& m_other;
+ bool m_transpose;
+
+};
+template<typename SPQRType>
+struct SPQRMatrixQReturnType{
+
+ SPQRMatrixQReturnType(const SPQRType& spqr) : m_spqr(spqr) {}
+ template<typename Derived>
+ SPQR_QProduct<SPQRType, Derived> operator*(const MatrixBase<Derived>& other)
+ {
+ return SPQR_QProduct<SPQRType,Derived>(m_spqr,other.derived(),false);
+ }
+ SPQRMatrixQTransposeReturnType<SPQRType> adjoint() const
+ {
+ return SPQRMatrixQTransposeReturnType<SPQRType>(m_spqr);
+ }
+ // To use for operations with the transpose of Q
+ SPQRMatrixQTransposeReturnType<SPQRType> transpose() const
+ {
+ return SPQRMatrixQTransposeReturnType<SPQRType>(m_spqr);
+ }
+ const SPQRType& m_spqr;
+};
+
+template<typename SPQRType>
+struct SPQRMatrixQTransposeReturnType{
+ SPQRMatrixQTransposeReturnType(const SPQRType& spqr) : m_spqr(spqr) {}
+ template<typename Derived>
+ SPQR_QProduct<SPQRType,Derived> operator*(const MatrixBase<Derived>& other)
+ {
+ return SPQR_QProduct<SPQRType,Derived>(m_spqr,other.derived(), true);
+ }
+ const SPQRType& m_spqr;
+};
+
+namespace internal {
+
+template<typename _MatrixType, typename Rhs>
+struct solve_retval<SPQR<_MatrixType>, Rhs>
+ : solve_retval_base<SPQR<_MatrixType>, Rhs>
+{
+ typedef SPQR<_MatrixType> Dec;
+ EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs)
+
+ template<typename Dest> void evalTo(Dest& dst) const
+ {
+ dec()._solve(rhs(),dst);
+ }
+};
+
+} // end namespace internal
+
+}// End namespace Eigen
+#endif
diff --git a/Eigen/src/SVD/JacobiSVD.h b/Eigen/src/SVD/JacobiSVD.h
index a7dbf0737..dff9e44eb 100644
--- a/Eigen/src/SVD/JacobiSVD.h
+++ b/Eigen/src/SVD/JacobiSVD.h
@@ -78,7 +78,8 @@ public:
{
if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols())
{
- m_qr = FullPivHouseholderQR<MatrixType>(svd.rows(), svd.cols());
+ m_qr.~QRType();
+ ::new (&m_qr) QRType(svd.rows(), svd.cols());
}
if (svd.m_computeFullU) m_workspace.resize(svd.rows());
}
@@ -96,7 +97,8 @@ public:
return false;
}
private:
- FullPivHouseholderQR<MatrixType> m_qr;
+ typedef FullPivHouseholderQR<MatrixType> QRType;
+ QRType m_qr;
WorkspaceType m_workspace;
};
@@ -121,7 +123,8 @@ public:
{
if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols())
{
- m_qr = FullPivHouseholderQR<TransposeTypeWithSameStorageOrder>(svd.cols(), svd.rows());
+ m_qr.~QRType();
+ ::new (&m_qr) QRType(svd.cols(), svd.rows());
}
m_adjoint.resize(svd.cols(), svd.rows());
if (svd.m_computeFullV) m_workspace.resize(svd.cols());
@@ -141,7 +144,8 @@ public:
else return false;
}
private:
- FullPivHouseholderQR<TransposeTypeWithSameStorageOrder> m_qr;
+ typedef FullPivHouseholderQR<TransposeTypeWithSameStorageOrder> QRType;
+ QRType m_qr;
TransposeTypeWithSameStorageOrder m_adjoint;
typename internal::plain_row_type<MatrixType>::type m_workspace;
};
@@ -158,7 +162,8 @@ public:
{
if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols())
{
- m_qr = ColPivHouseholderQR<MatrixType>(svd.rows(), svd.cols());
+ m_qr.~QRType();
+ ::new (&m_qr) QRType(svd.rows(), svd.cols());
}
if (svd.m_computeFullU) m_workspace.resize(svd.rows());
else if (svd.m_computeThinU) m_workspace.resize(svd.cols());
@@ -183,7 +188,8 @@ public:
}
private:
- ColPivHouseholderQR<MatrixType> m_qr;
+ typedef ColPivHouseholderQR<MatrixType> QRType;
+ QRType m_qr;
typename internal::plain_col_type<MatrixType>::type m_workspace;
};
@@ -209,7 +215,8 @@ public:
{
if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols())
{
- m_qr = ColPivHouseholderQR<TransposeTypeWithSameStorageOrder>(svd.cols(), svd.rows());
+ m_qr.~QRType();
+ ::new (&m_qr) QRType(svd.cols(), svd.rows());
}
if (svd.m_computeFullV) m_workspace.resize(svd.cols());
else if (svd.m_computeThinV) m_workspace.resize(svd.rows());
@@ -237,7 +244,8 @@ public:
}
private:
- ColPivHouseholderQR<TransposeTypeWithSameStorageOrder> m_qr;
+ typedef ColPivHouseholderQR<TransposeTypeWithSameStorageOrder> QRType;
+ QRType m_qr;
TransposeTypeWithSameStorageOrder m_adjoint;
typename internal::plain_row_type<MatrixType>::type m_workspace;
};
@@ -254,7 +262,8 @@ public:
{
if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols())
{
- m_qr = HouseholderQR<MatrixType>(svd.rows(), svd.cols());
+ m_qr.~QRType();
+ ::new (&m_qr) QRType(svd.rows(), svd.cols());
}
if (svd.m_computeFullU) m_workspace.resize(svd.rows());
else if (svd.m_computeThinU) m_workspace.resize(svd.cols());
@@ -278,7 +287,8 @@ public:
return false;
}
private:
- HouseholderQR<MatrixType> m_qr;
+ typedef HouseholderQR<MatrixType> QRType;
+ QRType m_qr;
typename internal::plain_col_type<MatrixType>::type m_workspace;
};
@@ -304,7 +314,8 @@ public:
{
if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols())
{
- m_qr = HouseholderQR<TransposeTypeWithSameStorageOrder>(svd.cols(), svd.rows());
+ m_qr.~QRType();
+ ::new (&m_qr) QRType(svd.cols(), svd.rows());
}
if (svd.m_computeFullV) m_workspace.resize(svd.cols());
else if (svd.m_computeThinV) m_workspace.resize(svd.rows());
@@ -332,7 +343,8 @@ public:
}
private:
- HouseholderQR<TransposeTypeWithSameStorageOrder> m_qr;
+ typedef HouseholderQR<TransposeTypeWithSameStorageOrder> QRType;
+ QRType m_qr;
TransposeTypeWithSameStorageOrder m_adjoint;
typename internal::plain_row_type<MatrixType>::type m_workspace;
};
@@ -359,17 +371,23 @@ struct svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner, true>
typedef typename SVD::Index Index;
static void run(typename SVD::WorkMatrixType& work_matrix, SVD& svd, Index p, Index q)
{
+ using std::sqrt;
Scalar z;
JacobiRotation<Scalar> rot;
- RealScalar n = sqrt(abs2(work_matrix.coeff(p,p)) + abs2(work_matrix.coeff(q,p)));
+ RealScalar n = sqrt(numext::abs2(work_matrix.coeff(p,p)) + numext::abs2(work_matrix.coeff(q,p)));
+
if(n==0)
{
z = abs(work_matrix.coeff(p,q)) / work_matrix.coeff(p,q);
work_matrix.row(p) *= z;
if(svd.computeU()) svd.m_matrixU.col(p) *= conj(z);
- z = abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
- work_matrix.row(q) *= z;
- if(svd.computeU()) svd.m_matrixU.col(q) *= conj(z);
+ if(work_matrix.coeff(q,q)!=Scalar(0))
+ {
+ z = abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
+ work_matrix.row(q) *= z;
+ if(svd.computeU()) svd.m_matrixU.col(q) *= conj(z);
+ }
+ // otherwise the second row is already zero, so we have nothing to do.
}
else
{
@@ -398,9 +416,11 @@ void real_2x2_jacobi_svd(const MatrixType& matrix, Index p, Index q,
JacobiRotation<RealScalar> *j_left,
JacobiRotation<RealScalar> *j_right)
{
+ using std::sqrt;
+ using std::abs;
Matrix<RealScalar,2,2> m;
- m << real(matrix.coeff(p,p)), real(matrix.coeff(p,q)),
- real(matrix.coeff(q,p)), real(matrix.coeff(q,q));
+ 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<RealScalar> rot1;
RealScalar t = m.coeff(0,0) + m.coeff(1,1);
RealScalar d = m.coeff(1,0) - m.coeff(0,1);
@@ -411,9 +431,11 @@ void real_2x2_jacobi_svd(const MatrixType& matrix, Index p, Index q,
}
else
{
- RealScalar u = d / t;
- rot1.c() = RealScalar(1) / sqrt(RealScalar(1) + abs2(u));
- rot1.s() = rot1.c() * u;
+ RealScalar t2d2 = numext::hypot(t,d);
+ rot1.c() = abs(t)/t2d2;
+ rot1.s() = d/t2d2;
+ if(t<RealScalar(0))
+ rot1.s() = -rot1.s();
}
m.applyOnTheLeft(0,1,rot1);
j_right->makeJacobi(m,0,1);
@@ -514,8 +536,9 @@ template<typename _MatrixType, int QRPreconditioner> class JacobiSVD
JacobiSVD()
: m_isInitialized(false),
m_isAllocated(false),
+ m_usePrescribedThreshold(false),
m_computationOptions(0),
- m_rows(-1), m_cols(-1)
+ m_rows(-1), m_cols(-1), m_diagSize(0)
{}
@@ -528,6 +551,7 @@ template<typename _MatrixType, int QRPreconditioner> class JacobiSVD
JacobiSVD(Index rows, Index cols, unsigned int computationOptions = 0)
: m_isInitialized(false),
m_isAllocated(false),
+ m_usePrescribedThreshold(false),
m_computationOptions(0),
m_rows(-1), m_cols(-1)
{
@@ -547,6 +571,7 @@ template<typename _MatrixType, int QRPreconditioner> class JacobiSVD
JacobiSVD(const MatrixType& matrix, unsigned int computationOptions = 0)
: m_isInitialized(false),
m_isAllocated(false),
+ m_usePrescribedThreshold(false),
m_computationOptions(0),
m_rows(-1), m_cols(-1)
{
@@ -648,6 +673,69 @@ template<typename _MatrixType, int QRPreconditioner> class JacobiSVD
eigen_assert(m_isInitialized && "JacobiSVD is not initialized.");
return m_nonzeroSingularValues;
}
+
+ /** \returns the rank of the matrix of which \c *this is the SVD.
+ *
+ * \note This method has to determine which singular values should be considered nonzero.
+ * For that, it uses the threshold value that you can control by calling
+ * setThreshold(const RealScalar&).
+ */
+ inline Index rank() const
+ {
+ using std::abs;
+ eigen_assert(m_isInitialized && "JacobiSVD is not initialized.");
+ if(m_singularValues.size()==0) return 0;
+ RealScalar premultiplied_threshold = m_singularValues.coeff(0) * threshold();
+ Index i = m_nonzeroSingularValues-1;
+ while(i>=0 && m_singularValues.coeff(i) < premultiplied_threshold) --i;
+ return i+1;
+ }
+
+ /** Allows to prescribe a threshold to be used by certain methods, such as rank() and solve(),
+ * which need to determine when singular values are to be considered nonzero.
+ * This is not used for the SVD decomposition itself.
+ *
+ * When it needs to get the threshold value, Eigen calls threshold().
+ * The default is \c NumTraits<Scalar>::epsilon()
+ *
+ * \param threshold The new value to use as the threshold.
+ *
+ * A singular value will be considered nonzero if its value is strictly greater than
+ * \f$ \vert singular value \vert \leqslant threshold \times \vert max singular value \vert \f$.
+ *
+ * If you want to come back to the default behavior, call setThreshold(Default_t)
+ */
+ JacobiSVD& setThreshold(const RealScalar& threshold)
+ {
+ m_usePrescribedThreshold = true;
+ m_prescribedThreshold = threshold;
+ return *this;
+ }
+
+ /** Allows to come back to the default behavior, letting Eigen use its default formula for
+ * determining the threshold.
+ *
+ * You should pass the special object Eigen::Default as parameter here.
+ * \code svd.setThreshold(Eigen::Default); \endcode
+ *
+ * See the documentation of setThreshold(const RealScalar&).
+ */
+ JacobiSVD& setThreshold(Default_t)
+ {
+ m_usePrescribedThreshold = false;
+ return *this;
+ }
+
+ /** Returns the threshold that will be used by certain methods such as rank().
+ *
+ * See the documentation of setThreshold(const RealScalar&).
+ */
+ RealScalar threshold() const
+ {
+ eigen_assert(m_isInitialized || m_usePrescribedThreshold);
+ return m_usePrescribedThreshold ? m_prescribedThreshold
+ : (std::max<Index>)(1,m_diagSize)*NumTraits<Scalar>::epsilon();
+ }
inline Index rows() const { return m_rows; }
inline Index cols() const { return m_cols; }
@@ -660,11 +748,12 @@ template<typename _MatrixType, int QRPreconditioner> class JacobiSVD
MatrixVType m_matrixV;
SingularValuesType m_singularValues;
WorkMatrixType m_workMatrix;
- bool m_isInitialized, m_isAllocated;
+ bool m_isInitialized, m_isAllocated, m_usePrescribedThreshold;
bool m_computeFullU, m_computeThinU;
bool m_computeFullV, m_computeThinV;
unsigned int m_computationOptions;
Index m_nonzeroSingularValues, m_rows, m_cols, m_diagSize;
+ RealScalar m_prescribedThreshold;
template<typename __MatrixType, int _QRPreconditioner, bool _IsComplex>
friend struct internal::svd_precondition_2x2_block_to_be_real;
@@ -709,12 +798,14 @@ void JacobiSVD<MatrixType, QRPreconditioner>::allocate(Index rows, Index cols, u
}
m_diagSize = (std::min)(m_rows, m_cols);
m_singularValues.resize(m_diagSize);
- m_matrixU.resize(m_rows, m_computeFullU ? m_rows
- : m_computeThinU ? m_diagSize
- : 0);
- m_matrixV.resize(m_cols, m_computeFullV ? m_cols
- : m_computeThinV ? m_diagSize
- : 0);
+ if(RowsAtCompileTime==Dynamic)
+ m_matrixU.resize(m_rows, m_computeFullU ? m_rows
+ : m_computeThinU ? m_diagSize
+ : 0);
+ if(ColsAtCompileTime==Dynamic)
+ m_matrixV.resize(m_cols, m_computeFullV ? m_cols
+ : m_computeThinV ? m_diagSize
+ : 0);
m_workMatrix.resize(m_diagSize, m_diagSize);
if(m_cols>m_rows) m_qr_precond_morecols.allocate(*this);
@@ -725,6 +816,7 @@ template<typename MatrixType, int QRPreconditioner>
JacobiSVD<MatrixType, QRPreconditioner>&
JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType& matrix, unsigned int computationOptions)
{
+ using std::abs;
allocate(matrix.rows(), matrix.cols(), computationOptions);
// currently we stop when we reach precision 2*epsilon as the last bit of precision can require an unreasonable number of iterations,
@@ -744,6 +836,11 @@ JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType& matrix, unsig
if(m_computeFullV) m_matrixV.setIdentity(m_cols,m_cols);
if(m_computeThinV) m_matrixV.setIdentity(m_cols, m_diagSize);
}
+
+ // Scaling factor to reduce over/under-flows
+ RealScalar scale = m_workMatrix.cwiseAbs().maxCoeff();
+ if(scale==RealScalar(0)) scale = RealScalar(1);
+ m_workMatrix /= scale;
/*** step 2. The main Jacobi SVD iteration. ***/
@@ -762,9 +859,9 @@ JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType& matrix, unsig
// notice that this comparison will evaluate to false if any NaN is involved, ensuring that NaN's don't
// keep us iterating forever. Similarly, small denormal numbers are considered zero.
using std::max;
- RealScalar threshold = (max)(considerAsZero, precision * (max)(internal::abs(m_workMatrix.coeff(p,p)),
- internal::abs(m_workMatrix.coeff(q,q))));
- if((max)(internal::abs(m_workMatrix.coeff(p,q)),internal::abs(m_workMatrix.coeff(q,p))) > threshold)
+ RealScalar threshold = (max)(considerAsZero, precision * (max)(abs(m_workMatrix.coeff(p,p)),
+ abs(m_workMatrix.coeff(q,q))));
+ if((max)(abs(m_workMatrix.coeff(p,q)),abs(m_workMatrix.coeff(q,p))) > threshold)
{
finished = false;
@@ -788,7 +885,7 @@ JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType& matrix, unsig
for(Index i = 0; i < m_diagSize; ++i)
{
- RealScalar a = internal::abs(m_workMatrix.coeff(i,i));
+ RealScalar a = abs(m_workMatrix.coeff(i,i));
m_singularValues.coeffRef(i) = a;
if(computeU() && (a!=RealScalar(0))) m_matrixU.col(i) *= m_workMatrix.coeff(i,i)/a;
}
@@ -813,6 +910,8 @@ JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType& matrix, unsig
if(computeV()) m_matrixV.col(pos).swap(m_matrixV.col(i));
}
}
+
+ m_singularValues *= scale;
m_isInitialized = true;
return *this;
@@ -833,17 +932,12 @@ struct solve_retval<JacobiSVD<_MatrixType, QRPreconditioner>, Rhs>
// A = U S V^*
// So A^{-1} = V S^{-1} U^*
- Index diagSize = (std::min)(dec().rows(), dec().cols());
- typename JacobiSVDType::SingularValuesType invertedSingVals(diagSize);
-
- Index nonzeroSingVals = dec().nonzeroSingularValues();
- invertedSingVals.head(nonzeroSingVals) = dec().singularValues().head(nonzeroSingVals).array().inverse();
- invertedSingVals.tail(diagSize - nonzeroSingVals).setZero();
-
- dst = dec().matrixV().leftCols(diagSize)
- * invertedSingVals.asDiagonal()
- * dec().matrixU().leftCols(diagSize).adjoint()
- * rhs();
+ Matrix<Scalar, Dynamic, Rhs::ColsAtCompileTime, 0, _MatrixType::MaxRowsAtCompileTime, Rhs::MaxColsAtCompileTime> tmp;
+ Index rank = dec().rank();
+
+ tmp.noalias() = dec().matrixU().leftCols(rank).adjoint() * rhs();
+ tmp = dec().singularValues().head(rank).asDiagonal().inverse() * tmp;
+ dst = dec().matrixV().leftCols(rank) * tmp;
}
};
} // end namespace internal
diff --git a/Eigen/src/SVD/JacobiSVD_MKL.h b/Eigen/src/SVD/JacobiSVD_MKL.h
index 4d479f6b2..decda7540 100644
--- a/Eigen/src/SVD/JacobiSVD_MKL.h
+++ b/Eigen/src/SVD/JacobiSVD_MKL.h
@@ -40,7 +40,7 @@ namespace Eigen {
/** \internal Specialization for the data types supported by MKL */
#define EIGEN_MKL_SVD(EIGTYPE, MKLTYPE, MKLRTYPE, MKLPREFIX, EIGCOLROW, MKLCOLROW) \
-template<> inline\
+template<> inline \
JacobiSVD<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic>, ColPivHouseholderQRPreconditioner>& \
JacobiSVD<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic>, ColPivHouseholderQRPreconditioner>::compute(const Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic>& matrix, unsigned int computationOptions) \
{ \
diff --git a/Eigen/src/SVD/UpperBidiagonalization.h b/Eigen/src/SVD/UpperBidiagonalization.h
index 213b3100d..587de37a5 100644
--- a/Eigen/src/SVD/UpperBidiagonalization.h
+++ b/Eigen/src/SVD/UpperBidiagonalization.h
@@ -39,7 +39,7 @@ template<typename _MatrixType> class UpperBidiagonalization
CwiseUnaryOp<internal::scalar_conjugate_op<Scalar>, const Diagonal<const MatrixType,0> >
> HouseholderUSequenceType;
typedef HouseholderSequence<
- const MatrixType,
+ const typename internal::remove_all<typename MatrixType::ConjugateReturnType>::type,
Diagonal<const MatrixType,1>,
OnTheRight
> HouseholderVSequenceType;
@@ -74,7 +74,7 @@ template<typename _MatrixType> class UpperBidiagonalization
const HouseholderVSequenceType householderV() // const here gives nasty errors and i'm lazy
{
eigen_assert(m_isInitialized && "UpperBidiagonalization is not initialized.");
- return HouseholderVSequenceType(m_householder, m_householder.const_derived().template diagonal<1>())
+ return HouseholderVSequenceType(m_householder.conjugate(), m_householder.const_derived().template diagonal<1>())
.setLength(m_householder.cols()-1)
.setShift(1);
}
diff --git a/Eigen/src/SparseCholesky/SimplicialCholesky.h b/Eigen/src/SparseCholesky/SimplicialCholesky.h
index 9bf38ab2d..e1f96ba5a 100644
--- a/Eigen/src/SparseCholesky/SimplicialCholesky.h
+++ b/Eigen/src/SparseCholesky/SimplicialCholesky.h
@@ -1,52 +1,12 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008-2012 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
-/*
-
-NOTE: the _symbolic, and _numeric functions has been adapted from
- the LDL library:
-
-LDL Copyright (c) 2005 by Timothy A. Davis. All Rights Reserved.
-
-LDL License:
-
- Your use or distribution of LDL or any modified version of
- LDL implies that you agree to this License.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
- USA
-
- Permission is hereby granted to use or copy this program under the
- terms of the GNU LGPL, provided that the Copyright, this License,
- and the Availability of the original version is retained on all copies.
- User documentation of any code that uses this code or any modified
- version of this code must cite the Copyright, this License, the
- Availability note, and "Used by permission." Permission to modify
- the code and to distribute modified code is granted, provided the
- Copyright, this License, and the Availability note are retained,
- and a notice that the code was modified is included.
- */
-
-#include "../Core/util/NonMPL2.h"
-
#ifndef EIGEN_SIMPLICIAL_CHOLESKY_H
#define EIGEN_SIMPLICIAL_CHOLESKY_H
@@ -77,6 +37,7 @@ class SimplicialCholeskyBase : internal::noncopyable
{
public:
typedef typename internal::traits<Derived>::MatrixType MatrixType;
+ typedef typename internal::traits<Derived>::OrderingType OrderingType;
enum { UpLo = internal::traits<Derived>::UpLo };
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
@@ -215,27 +176,6 @@ class SimplicialCholeskyBase : internal::noncopyable
dest = m_Pinv * dest;
}
- /** \internal */
- template<typename Rhs, typename DestScalar, int DestOptions, typename DestIndex>
- void _solve_sparse(const Rhs& b, SparseMatrix<DestScalar,DestOptions,DestIndex> &dest) const
- {
- eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
- eigen_assert(m_matrix.rows()==b.rows());
-
- // we process the sparse rhs per block of NbColsAtOnce columns temporarily stored into a dense matrix.
- static const int NbColsAtOnce = 4;
- int rhsCols = b.cols();
- int size = b.rows();
- Eigen::Matrix<DestScalar,Dynamic,Dynamic> tmp(size,rhsCols);
- for(int k=0; k<rhsCols; k+=NbColsAtOnce)
- {
- int actualCols = std::min<int>(rhsCols-k, NbColsAtOnce);
- tmp.leftCols(actualCols) = b.middleCols(k,actualCols);
- tmp.leftCols(actualCols) = derived().solve(tmp.leftCols(actualCols));
- dest.middleCols(k,actualCols) = tmp.leftCols(actualCols).sparseView();
- }
- }
-
#endif // EIGEN_PARSED_BY_DOXYGEN
protected:
@@ -301,15 +241,16 @@ class SimplicialCholeskyBase : internal::noncopyable
RealScalar m_shiftScale;
};
-template<typename _MatrixType, int _UpLo = Lower> class SimplicialLLT;
-template<typename _MatrixType, int _UpLo = Lower> class SimplicialLDLT;
-template<typename _MatrixType, int _UpLo = Lower> class SimplicialCholesky;
+template<typename _MatrixType, int _UpLo = Lower, typename _Ordering = AMDOrdering<typename _MatrixType::Index> > class SimplicialLLT;
+template<typename _MatrixType, int _UpLo = Lower, typename _Ordering = AMDOrdering<typename _MatrixType::Index> > class SimplicialLDLT;
+template<typename _MatrixType, int _UpLo = Lower, typename _Ordering = AMDOrdering<typename _MatrixType::Index> > class SimplicialCholesky;
namespace internal {
-template<typename _MatrixType, int _UpLo> struct traits<SimplicialLLT<_MatrixType,_UpLo> >
+template<typename _MatrixType, int _UpLo, typename _Ordering> struct traits<SimplicialLLT<_MatrixType,_UpLo,_Ordering> >
{
typedef _MatrixType MatrixType;
+ typedef _Ordering OrderingType;
enum { UpLo = _UpLo };
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::Index Index;
@@ -320,9 +261,10 @@ template<typename _MatrixType, int _UpLo> struct traits<SimplicialLLT<_MatrixTyp
static inline MatrixU getU(const MatrixType& m) { return m.adjoint(); }
};
-template<typename _MatrixType,int _UpLo> struct traits<SimplicialLDLT<_MatrixType,_UpLo> >
+template<typename _MatrixType,int _UpLo, typename _Ordering> struct traits<SimplicialLDLT<_MatrixType,_UpLo,_Ordering> >
{
typedef _MatrixType MatrixType;
+ typedef _Ordering OrderingType;
enum { UpLo = _UpLo };
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::Index Index;
@@ -333,9 +275,10 @@ template<typename _MatrixType,int _UpLo> struct traits<SimplicialLDLT<_MatrixTyp
static inline MatrixU getU(const MatrixType& m) { return m.adjoint(); }
};
-template<typename _MatrixType, int _UpLo> struct traits<SimplicialCholesky<_MatrixType,_UpLo> >
+template<typename _MatrixType, int _UpLo, typename _Ordering> struct traits<SimplicialCholesky<_MatrixType,_UpLo,_Ordering> >
{
typedef _MatrixType MatrixType;
+ typedef _Ordering OrderingType;
enum { UpLo = _UpLo };
};
@@ -355,11 +298,12 @@ template<typename _MatrixType, int _UpLo> struct traits<SimplicialCholesky<_Matr
* \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
* \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
* or Upper. Default is Lower.
+ * \tparam _Ordering The ordering method to use, either AMDOrdering<> or NaturalOrdering<>. Default is AMDOrdering<>
*
- * \sa class SimplicialLDLT
+ * \sa class SimplicialLDLT, class AMDOrdering, class NaturalOrdering
*/
-template<typename _MatrixType, int _UpLo>
- class SimplicialLLT : public SimplicialCholeskyBase<SimplicialLLT<_MatrixType,_UpLo> >
+template<typename _MatrixType, int _UpLo, typename _Ordering>
+ class SimplicialLLT : public SimplicialCholeskyBase<SimplicialLLT<_MatrixType,_UpLo,_Ordering> >
{
public:
typedef _MatrixType MatrixType;
@@ -425,7 +369,7 @@ public:
Scalar determinant() const
{
Scalar detL = Base::m_matrix.diagonal().prod();
- return internal::abs2(detL);
+ return numext::abs2(detL);
}
};
@@ -443,11 +387,12 @@ public:
* \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
* \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
* or Upper. Default is Lower.
+ * \tparam _Ordering The ordering method to use, either AMDOrdering<> or NaturalOrdering<>. Default is AMDOrdering<>
*
- * \sa class SimplicialLLT
+ * \sa class SimplicialLLT, class AMDOrdering, class NaturalOrdering
*/
-template<typename _MatrixType, int _UpLo>
- class SimplicialLDLT : public SimplicialCholeskyBase<SimplicialLDLT<_MatrixType,_UpLo> >
+template<typename _MatrixType, int _UpLo, typename _Ordering>
+ class SimplicialLDLT : public SimplicialCholeskyBase<SimplicialLDLT<_MatrixType,_UpLo,_Ordering> >
{
public:
typedef _MatrixType MatrixType;
@@ -528,8 +473,8 @@ public:
*
* \sa class SimplicialLDLT, class SimplicialLLT
*/
-template<typename _MatrixType, int _UpLo>
- class SimplicialCholesky : public SimplicialCholeskyBase<SimplicialCholesky<_MatrixType,_UpLo> >
+template<typename _MatrixType, int _UpLo, typename _Ordering>
+ class SimplicialCholesky : public SimplicialCholeskyBase<SimplicialCholesky<_MatrixType,_UpLo,_Ordering> >
{
public:
typedef _MatrixType MatrixType;
@@ -660,7 +605,7 @@ public:
else
{
Scalar detL = Diagonal<const CholMatrixType>(Base::m_matrix).prod();
- return internal::abs2(detL);
+ return numext::abs2(detL);
}
}
@@ -673,15 +618,13 @@ void SimplicialCholeskyBase<Derived>::ordering(const MatrixType& a, CholMatrixTy
{
eigen_assert(a.rows()==a.cols());
const Index size = a.rows();
- // TODO allows to configure the permutation
// Note that amd compute the inverse permutation
{
CholMatrixType C;
C = a.template selfadjointView<UpLo>();
- // remove diagonal entries:
- // seems not to be needed
- // C.prune(keep_diag());
- internal::minimum_degree_ordering(C, m_Pinv);
+
+ OrderingType ordering;
+ ordering(C,m_Pinv);
}
if(m_Pinv.size()>0)
@@ -693,151 +636,6 @@ void SimplicialCholeskyBase<Derived>::ordering(const MatrixType& a, CholMatrixTy
ap.template selfadjointView<Upper>() = a.template selfadjointView<UpLo>().twistedBy(m_P);
}
-template<typename Derived>
-void SimplicialCholeskyBase<Derived>::analyzePattern_preordered(const CholMatrixType& ap, bool doLDLT)
-{
- const Index size = ap.rows();
- m_matrix.resize(size, size);
- m_parent.resize(size);
- m_nonZerosPerCol.resize(size);
-
- ei_declare_aligned_stack_constructed_variable(Index, tags, size, 0);
-
- for(Index k = 0; k < size; ++k)
- {
- /* L(k,:) pattern: all nodes reachable in etree from nz in A(0:k-1,k) */
- m_parent[k] = -1; /* parent of k is not yet known */
- tags[k] = k; /* mark node k as visited */
- m_nonZerosPerCol[k] = 0; /* count of nonzeros in column k of L */
- for(typename CholMatrixType::InnerIterator it(ap,k); it; ++it)
- {
- Index i = it.index();
- if(i < k)
- {
- /* follow path from i to root of etree, stop at flagged node */
- for(; tags[i] != k; i = m_parent[i])
- {
- /* find parent of i if not yet determined */
- if (m_parent[i] == -1)
- m_parent[i] = k;
- m_nonZerosPerCol[i]++; /* L (k,i) is nonzero */
- tags[i] = k; /* mark i as visited */
- }
- }
- }
- }
-
- /* construct Lp index array from m_nonZerosPerCol column counts */
- Index* Lp = m_matrix.outerIndexPtr();
- Lp[0] = 0;
- for(Index k = 0; k < size; ++k)
- Lp[k+1] = Lp[k] + m_nonZerosPerCol[k] + (doLDLT ? 0 : 1);
-
- m_matrix.resizeNonZeros(Lp[size]);
-
- m_isInitialized = true;
- m_info = Success;
- m_analysisIsOk = true;
- m_factorizationIsOk = false;
-}
-
-
-template<typename Derived>
-template<bool DoLDLT>
-void SimplicialCholeskyBase<Derived>::factorize_preordered(const CholMatrixType& ap)
-{
- eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
- eigen_assert(ap.rows()==ap.cols());
- const Index size = ap.rows();
- eigen_assert(m_parent.size()==size);
- eigen_assert(m_nonZerosPerCol.size()==size);
-
- const Index* Lp = m_matrix.outerIndexPtr();
- Index* Li = m_matrix.innerIndexPtr();
- Scalar* Lx = m_matrix.valuePtr();
-
- ei_declare_aligned_stack_constructed_variable(Scalar, y, size, 0);
- ei_declare_aligned_stack_constructed_variable(Index, pattern, size, 0);
- ei_declare_aligned_stack_constructed_variable(Index, tags, size, 0);
-
- bool ok = true;
- m_diag.resize(DoLDLT ? size : 0);
-
- for(Index k = 0; k < size; ++k)
- {
- // compute nonzero pattern of kth row of L, in topological order
- y[k] = 0.0; // Y(0:k) is now all zero
- Index top = size; // stack for pattern is empty
- tags[k] = k; // mark node k as visited
- m_nonZerosPerCol[k] = 0; // count of nonzeros in column k of L
- for(typename MatrixType::InnerIterator it(ap,k); it; ++it)
- {
- Index i = it.index();
- if(i <= k)
- {
- y[i] += internal::conj(it.value()); /* scatter A(i,k) into Y (sum duplicates) */
- Index len;
- for(len = 0; tags[i] != k; i = m_parent[i])
- {
- pattern[len++] = i; /* L(k,i) is nonzero */
- tags[i] = k; /* mark i as visited */
- }
- while(len > 0)
- pattern[--top] = pattern[--len];
- }
- }
-
- /* compute numerical values kth row of L (a sparse triangular solve) */
-
- RealScalar d = internal::real(y[k]) * m_shiftScale + m_shiftOffset; // get D(k,k), apply the shift function, and clear Y(k)
- y[k] = 0.0;
- for(; top < size; ++top)
- {
- Index i = pattern[top]; /* pattern[top:n-1] is pattern of L(:,k) */
- Scalar yi = y[i]; /* get and clear Y(i) */
- y[i] = 0.0;
-
- /* the nonzero entry L(k,i) */
- Scalar l_ki;
- if(DoLDLT)
- l_ki = yi / m_diag[i];
- else
- yi = l_ki = yi / Lx[Lp[i]];
-
- Index p2 = Lp[i] + m_nonZerosPerCol[i];
- Index p;
- for(p = Lp[i] + (DoLDLT ? 0 : 1); p < p2; ++p)
- y[Li[p]] -= internal::conj(Lx[p]) * yi;
- d -= internal::real(l_ki * internal::conj(yi));
- Li[p] = k; /* store L(k,i) in column form of L */
- Lx[p] = l_ki;
- ++m_nonZerosPerCol[i]; /* increment count of nonzeros in col i */
- }
- if(DoLDLT)
- {
- m_diag[k] = d;
- if(d == RealScalar(0))
- {
- ok = false; /* failure, D(k,k) is zero */
- break;
- }
- }
- else
- {
- Index p = Lp[k] + m_nonZerosPerCol[k]++;
- Li[p] = k ; /* store L(k,k) = sqrt (d) in column k */
- if(d <= RealScalar(0)) {
- ok = false; /* failure, matrix is not positive definite */
- break;
- }
- Lx[p] = internal::sqrt(d) ;
- }
- }
-
- m_info = ok ? Success : NumericalIssue;
- m_factorizationIsOk = true;
-}
-
namespace internal {
template<typename Derived, typename Rhs>
@@ -862,7 +660,7 @@ struct sparse_solve_retval<SimplicialCholeskyBase<Derived>, Rhs>
template<typename Dest> void evalTo(Dest& dst) const
{
- dec().derived()._solve_sparse(rhs(),dst);
+ this->defaultEvalTo(dst);
}
};
diff --git a/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h b/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h
new file mode 100644
index 000000000..7aaf702be
--- /dev/null
+++ b/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h
@@ -0,0 +1,199 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2012 Gael Guennebaud <gael.guennebaud@inria.fr>
+
+/*
+
+NOTE: thes functions vave been adapted from the LDL library:
+
+LDL Copyright (c) 2005 by Timothy A. Davis. All Rights Reserved.
+
+LDL License:
+
+ Your use or distribution of LDL or any modified version of
+ LDL implies that you agree to this License.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ USA
+
+ Permission is hereby granted to use or copy this program under the
+ terms of the GNU LGPL, provided that the Copyright, this License,
+ and the Availability of the original version is retained on all copies.
+ User documentation of any code that uses this code or any modified
+ version of this code must cite the Copyright, this License, the
+ Availability note, and "Used by permission." Permission to modify
+ the code and to distribute modified code is granted, provided the
+ Copyright, this License, and the Availability note are retained,
+ and a notice that the code was modified is included.
+ */
+
+#include "../Core/util/NonMPL2.h"
+
+#ifndef EIGEN_SIMPLICIAL_CHOLESKY_IMPL_H
+#define EIGEN_SIMPLICIAL_CHOLESKY_IMPL_H
+
+namespace Eigen {
+
+template<typename Derived>
+void SimplicialCholeskyBase<Derived>::analyzePattern_preordered(const CholMatrixType& ap, bool doLDLT)
+{
+ const Index size = ap.rows();
+ m_matrix.resize(size, size);
+ m_parent.resize(size);
+ m_nonZerosPerCol.resize(size);
+
+ ei_declare_aligned_stack_constructed_variable(Index, tags, size, 0);
+
+ for(Index k = 0; k < size; ++k)
+ {
+ /* L(k,:) pattern: all nodes reachable in etree from nz in A(0:k-1,k) */
+ m_parent[k] = -1; /* parent of k is not yet known */
+ tags[k] = k; /* mark node k as visited */
+ m_nonZerosPerCol[k] = 0; /* count of nonzeros in column k of L */
+ for(typename CholMatrixType::InnerIterator it(ap,k); it; ++it)
+ {
+ Index i = it.index();
+ if(i < k)
+ {
+ /* follow path from i to root of etree, stop at flagged node */
+ for(; tags[i] != k; i = m_parent[i])
+ {
+ /* find parent of i if not yet determined */
+ if (m_parent[i] == -1)
+ m_parent[i] = k;
+ m_nonZerosPerCol[i]++; /* L (k,i) is nonzero */
+ tags[i] = k; /* mark i as visited */
+ }
+ }
+ }
+ }
+
+ /* construct Lp index array from m_nonZerosPerCol column counts */
+ Index* Lp = m_matrix.outerIndexPtr();
+ Lp[0] = 0;
+ for(Index k = 0; k < size; ++k)
+ Lp[k+1] = Lp[k] + m_nonZerosPerCol[k] + (doLDLT ? 0 : 1);
+
+ m_matrix.resizeNonZeros(Lp[size]);
+
+ m_isInitialized = true;
+ m_info = Success;
+ m_analysisIsOk = true;
+ m_factorizationIsOk = false;
+}
+
+
+template<typename Derived>
+template<bool DoLDLT>
+void SimplicialCholeskyBase<Derived>::factorize_preordered(const CholMatrixType& ap)
+{
+ using std::sqrt;
+
+ eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
+ eigen_assert(ap.rows()==ap.cols());
+ const Index size = ap.rows();
+ eigen_assert(m_parent.size()==size);
+ eigen_assert(m_nonZerosPerCol.size()==size);
+
+ const Index* Lp = m_matrix.outerIndexPtr();
+ Index* Li = m_matrix.innerIndexPtr();
+ Scalar* Lx = m_matrix.valuePtr();
+
+ ei_declare_aligned_stack_constructed_variable(Scalar, y, size, 0);
+ ei_declare_aligned_stack_constructed_variable(Index, pattern, size, 0);
+ ei_declare_aligned_stack_constructed_variable(Index, tags, size, 0);
+
+ bool ok = true;
+ m_diag.resize(DoLDLT ? size : 0);
+
+ for(Index k = 0; k < size; ++k)
+ {
+ // compute nonzero pattern of kth row of L, in topological order
+ y[k] = 0.0; // Y(0:k) is now all zero
+ Index top = size; // stack for pattern is empty
+ tags[k] = k; // mark node k as visited
+ m_nonZerosPerCol[k] = 0; // count of nonzeros in column k of L
+ for(typename MatrixType::InnerIterator it(ap,k); it; ++it)
+ {
+ Index i = it.index();
+ if(i <= k)
+ {
+ y[i] += numext::conj(it.value()); /* scatter A(i,k) into Y (sum duplicates) */
+ Index len;
+ for(len = 0; tags[i] != k; i = m_parent[i])
+ {
+ pattern[len++] = i; /* L(k,i) is nonzero */
+ tags[i] = k; /* mark i as visited */
+ }
+ while(len > 0)
+ pattern[--top] = pattern[--len];
+ }
+ }
+
+ /* compute numerical values kth row of L (a sparse triangular solve) */
+
+ RealScalar d = numext::real(y[k]) * m_shiftScale + m_shiftOffset; // get D(k,k), apply the shift function, and clear Y(k)
+ y[k] = 0.0;
+ for(; top < size; ++top)
+ {
+ Index i = pattern[top]; /* pattern[top:n-1] is pattern of L(:,k) */
+ Scalar yi = y[i]; /* get and clear Y(i) */
+ y[i] = 0.0;
+
+ /* the nonzero entry L(k,i) */
+ Scalar l_ki;
+ if(DoLDLT)
+ l_ki = yi / m_diag[i];
+ else
+ yi = l_ki = yi / Lx[Lp[i]];
+
+ Index p2 = Lp[i] + m_nonZerosPerCol[i];
+ Index p;
+ for(p = Lp[i] + (DoLDLT ? 0 : 1); p < p2; ++p)
+ y[Li[p]] -= numext::conj(Lx[p]) * yi;
+ d -= numext::real(l_ki * numext::conj(yi));
+ Li[p] = k; /* store L(k,i) in column form of L */
+ Lx[p] = l_ki;
+ ++m_nonZerosPerCol[i]; /* increment count of nonzeros in col i */
+ }
+ if(DoLDLT)
+ {
+ m_diag[k] = d;
+ if(d == RealScalar(0))
+ {
+ ok = false; /* failure, D(k,k) is zero */
+ break;
+ }
+ }
+ else
+ {
+ Index p = Lp[k] + m_nonZerosPerCol[k]++;
+ Li[p] = k ; /* store L(k,k) = sqrt (d) in column k */
+ if(d <= RealScalar(0)) {
+ ok = false; /* failure, matrix is not positive definite */
+ break;
+ }
+ Lx[p] = sqrt(d) ;
+ }
+ }
+
+ m_info = ok ? Success : NumericalIssue;
+ m_factorizationIsOk = true;
+}
+
+} // end namespace Eigen
+
+#endif // EIGEN_SIMPLICIAL_CHOLESKY_IMPL_H
diff --git a/Eigen/src/SparseCore/AmbiVector.h b/Eigen/src/SparseCore/AmbiVector.h
index 6cfaadbaa..17fff96a7 100644
--- a/Eigen/src/SparseCore/AmbiVector.h
+++ b/Eigen/src/SparseCore/AmbiVector.h
@@ -288,9 +288,10 @@ class AmbiVector<_Scalar,_Index>::Iterator
* In practice, all coefficients having a magnitude smaller than \a epsilon
* are skipped.
*/
- Iterator(const AmbiVector& vec, RealScalar epsilon = 0)
+ Iterator(const AmbiVector& vec, const RealScalar& epsilon = 0)
: m_vector(vec)
{
+ using std::abs;
m_epsilon = epsilon;
m_isDense = m_vector.m_mode==IsDense;
if (m_isDense)
@@ -304,7 +305,7 @@ class AmbiVector<_Scalar,_Index>::Iterator
{
ListEl* EIGEN_RESTRICT llElements = reinterpret_cast<ListEl*>(m_vector.m_buffer);
m_currentEl = m_vector.m_llStart;
- while (m_currentEl>=0 && internal::abs(llElements[m_currentEl].value)<=m_epsilon)
+ while (m_currentEl>=0 && abs(llElements[m_currentEl].value)<=m_epsilon)
m_currentEl = llElements[m_currentEl].next;
if (m_currentEl<0)
{
@@ -326,11 +327,12 @@ class AmbiVector<_Scalar,_Index>::Iterator
Iterator& operator++()
{
+ using std::abs;
if (m_isDense)
{
do {
++m_cachedIndex;
- } while (m_cachedIndex<m_vector.m_end && internal::abs(m_vector.m_buffer[m_cachedIndex])<m_epsilon);
+ } while (m_cachedIndex<m_vector.m_end && abs(m_vector.m_buffer[m_cachedIndex])<m_epsilon);
if (m_cachedIndex<m_vector.m_end)
m_cachedValue = m_vector.m_buffer[m_cachedIndex];
else
@@ -341,7 +343,7 @@ class AmbiVector<_Scalar,_Index>::Iterator
ListEl* EIGEN_RESTRICT llElements = reinterpret_cast<ListEl*>(m_vector.m_buffer);
do {
m_currentEl = llElements[m_currentEl].next;
- } while (m_currentEl>=0 && internal::abs(llElements[m_currentEl].value)<m_epsilon);
+ } while (m_currentEl>=0 && abs(llElements[m_currentEl].value)<m_epsilon);
if (m_currentEl<0)
{
m_cachedIndex = -1;
diff --git a/Eigen/src/SparseCore/CompressedStorage.h b/Eigen/src/SparseCore/CompressedStorage.h
index 85a998aff..a667cb56e 100644
--- a/Eigen/src/SparseCore/CompressedStorage.h
+++ b/Eigen/src/SparseCore/CompressedStorage.h
@@ -51,8 +51,8 @@ class CompressedStorage
CompressedStorage& operator=(const CompressedStorage& other)
{
resize(other.size());
- memcpy(m_values, other.m_values, m_size * sizeof(Scalar));
- memcpy(m_indices, other.m_indices, m_size * sizeof(Index));
+ internal::smart_copy(other.m_values, other.m_values + m_size, m_values);
+ internal::smart_copy(other.m_indices, other.m_indices + m_size, m_indices);
return *this;
}
@@ -83,10 +83,10 @@ class CompressedStorage
reallocate(m_size);
}
- void resize(size_t size, float reserveSizeFactor = 0)
+ void resize(size_t size, double reserveSizeFactor = 0)
{
if (m_allocatedSize<size)
- reallocate(size + size_t(reserveSizeFactor*size));
+ reallocate(size + size_t(reserveSizeFactor*double(size)));
m_size = size;
}
@@ -139,7 +139,7 @@ class CompressedStorage
/** \returns the stored value at index \a key
* If the value does not exist, then the value \a defaultValue is returned without any insertion. */
- inline Scalar at(Index key, Scalar defaultValue = Scalar(0)) const
+ inline Scalar at(Index key, const Scalar& defaultValue = Scalar(0)) const
{
if (m_size==0)
return defaultValue;
@@ -152,7 +152,7 @@ class CompressedStorage
}
/** Like at(), but the search is performed in the range [start,end) */
- inline Scalar atInRange(size_t start, size_t end, Index key, Scalar defaultValue = Scalar(0)) const
+ inline Scalar atInRange(size_t start, size_t end, Index key, const Scalar& defaultValue = Scalar(0)) const
{
if (start>=end)
return Scalar(0);
@@ -167,7 +167,7 @@ class CompressedStorage
/** \returns a reference to the value at index \a key
* If the value does not exist, then the value \a defaultValue is inserted
* such that the keys are sorted. */
- inline Scalar& atWithInsertion(Index key, Scalar defaultValue = Scalar(0))
+ inline Scalar& atWithInsertion(Index key, const Scalar& defaultValue = Scalar(0))
{
size_t id = searchLowerIndex(0,m_size,key);
if (id>=m_size || m_indices[id]!=key)
@@ -184,7 +184,7 @@ class CompressedStorage
return m_values[id];
}
- void prune(Scalar reference, RealScalar epsilon = NumTraits<RealScalar>::dummy_precision())
+ void prune(const Scalar& reference, const RealScalar& epsilon = NumTraits<RealScalar>::dummy_precision())
{
size_t k = 0;
size_t n = size();
diff --git a/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h b/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h
index 16b5e1dba..5c320e2d2 100644
--- a/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h
+++ b/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h
@@ -66,9 +66,9 @@ static void conservative_sparse_sparse_product_impl(const Lhs& lhs, const Rhs& r
}
// unordered insertion
- for(int k=0; k<nnz; ++k)
+ for(Index k=0; k<nnz; ++k)
{
- int i = indices[k];
+ Index i = indices[k];
res.insertBackByOuterInnerUnordered(j,i) = values[i];
mask[i] = false;
}
@@ -76,8 +76,8 @@ static void conservative_sparse_sparse_product_impl(const Lhs& lhs, const Rhs& r
#if 0
// alternative ordered insertion code:
- int t200 = rows/(log2(200)*1.39);
- int t = (rows*100)/139;
+ Index t200 = rows/(log2(200)*1.39);
+ Index t = (rows*100)/139;
// FIXME reserve nnz non zeros
// FIXME implement fast sort algorithms for very small nnz
@@ -90,9 +90,9 @@ static void conservative_sparse_sparse_product_impl(const Lhs& lhs, const Rhs& r
if(true)
{
if(nnz>1) std::sort(indices.data(),indices.data()+nnz);
- for(int k=0; k<nnz; ++k)
+ for(Index k=0; k<nnz; ++k)
{
- int i = indices[k];
+ Index i = indices[k];
res.insertBackByOuterInner(j,i) = values[i];
mask[i] = false;
}
@@ -100,7 +100,7 @@ static void conservative_sparse_sparse_product_impl(const Lhs& lhs, const Rhs& r
else
{
// dense path
- for(int i=0; i<rows; ++i)
+ for(Index i=0; i<rows; ++i)
{
if(mask[i])
{
@@ -121,9 +121,9 @@ static void conservative_sparse_sparse_product_impl(const Lhs& lhs, const Rhs& r
namespace internal {
template<typename Lhs, typename Rhs, typename ResultType,
- int LhsStorageOrder = traits<Lhs>::Flags&RowMajorBit,
- int RhsStorageOrder = traits<Rhs>::Flags&RowMajorBit,
- int ResStorageOrder = traits<ResultType>::Flags&RowMajorBit>
+ int LhsStorageOrder = (traits<Lhs>::Flags&RowMajorBit) ? RowMajor : ColMajor,
+ int RhsStorageOrder = (traits<Rhs>::Flags&RowMajorBit) ? RowMajor : ColMajor,
+ int ResStorageOrder = (traits<ResultType>::Flags&RowMajorBit) ? RowMajor : ColMajor>
struct conservative_sparse_sparse_product_selector;
template<typename Lhs, typename Rhs, typename ResultType>
@@ -134,8 +134,8 @@ struct conservative_sparse_sparse_product_selector<Lhs,Rhs,ResultType,ColMajor,C
static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
{
- typedef SparseMatrix<typename ResultType::Scalar,RowMajor> RowMajorMatrix;
- typedef SparseMatrix<typename ResultType::Scalar,ColMajor> ColMajorMatrix;
+ typedef SparseMatrix<typename ResultType::Scalar,RowMajor,typename ResultType::Index> RowMajorMatrix;
+ typedef SparseMatrix<typename ResultType::Scalar,ColMajor,typename ResultType::Index> ColMajorMatrix;
ColMajorMatrix resCol(lhs.rows(),rhs.cols());
internal::conservative_sparse_sparse_product_impl<Lhs,Rhs,ColMajorMatrix>(lhs, rhs, resCol);
// sort the non zeros:
@@ -149,7 +149,7 @@ struct conservative_sparse_sparse_product_selector<Lhs,Rhs,ResultType,RowMajor,C
{
static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
{
- typedef SparseMatrix<typename ResultType::Scalar,RowMajor> RowMajorMatrix;
+ typedef SparseMatrix<typename ResultType::Scalar,RowMajor,typename ResultType::Index> RowMajorMatrix;
RowMajorMatrix rhsRow = rhs;
RowMajorMatrix resRow(lhs.rows(), rhs.cols());
internal::conservative_sparse_sparse_product_impl<RowMajorMatrix,Lhs,RowMajorMatrix>(rhsRow, lhs, resRow);
@@ -162,7 +162,7 @@ struct conservative_sparse_sparse_product_selector<Lhs,Rhs,ResultType,ColMajor,R
{
static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
{
- typedef SparseMatrix<typename ResultType::Scalar,RowMajor> RowMajorMatrix;
+ typedef SparseMatrix<typename ResultType::Scalar,RowMajor,typename ResultType::Index> RowMajorMatrix;
RowMajorMatrix lhsRow = lhs;
RowMajorMatrix resRow(lhs.rows(), rhs.cols());
internal::conservative_sparse_sparse_product_impl<Rhs,RowMajorMatrix,RowMajorMatrix>(rhs, lhsRow, resRow);
@@ -175,7 +175,7 @@ struct conservative_sparse_sparse_product_selector<Lhs,Rhs,ResultType,RowMajor,R
{
static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
{
- typedef SparseMatrix<typename ResultType::Scalar,RowMajor> RowMajorMatrix;
+ typedef SparseMatrix<typename ResultType::Scalar,RowMajor,typename ResultType::Index> RowMajorMatrix;
RowMajorMatrix resRow(lhs.rows(), rhs.cols());
internal::conservative_sparse_sparse_product_impl<Rhs,Lhs,RowMajorMatrix>(rhs, lhs, resRow);
res = resRow;
@@ -190,7 +190,7 @@ struct conservative_sparse_sparse_product_selector<Lhs,Rhs,ResultType,ColMajor,C
static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
{
- typedef SparseMatrix<typename ResultType::Scalar,ColMajor> ColMajorMatrix;
+ typedef SparseMatrix<typename ResultType::Scalar,ColMajor,typename ResultType::Index> ColMajorMatrix;
ColMajorMatrix resCol(lhs.rows(), rhs.cols());
internal::conservative_sparse_sparse_product_impl<Lhs,Rhs,ColMajorMatrix>(lhs, rhs, resCol);
res = resCol;
@@ -202,7 +202,7 @@ struct conservative_sparse_sparse_product_selector<Lhs,Rhs,ResultType,RowMajor,C
{
static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
{
- typedef SparseMatrix<typename ResultType::Scalar,ColMajor> ColMajorMatrix;
+ typedef SparseMatrix<typename ResultType::Scalar,ColMajor,typename ResultType::Index> ColMajorMatrix;
ColMajorMatrix lhsCol = lhs;
ColMajorMatrix resCol(lhs.rows(), rhs.cols());
internal::conservative_sparse_sparse_product_impl<ColMajorMatrix,Rhs,ColMajorMatrix>(lhsCol, rhs, resCol);
@@ -215,7 +215,7 @@ struct conservative_sparse_sparse_product_selector<Lhs,Rhs,ResultType,ColMajor,R
{
static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
{
- typedef SparseMatrix<typename ResultType::Scalar,ColMajor> ColMajorMatrix;
+ typedef SparseMatrix<typename ResultType::Scalar,ColMajor,typename ResultType::Index> ColMajorMatrix;
ColMajorMatrix rhsCol = rhs;
ColMajorMatrix resCol(lhs.rows(), rhs.cols());
internal::conservative_sparse_sparse_product_impl<Lhs,ColMajorMatrix,ColMajorMatrix>(lhs, rhsCol, resCol);
@@ -228,8 +228,8 @@ struct conservative_sparse_sparse_product_selector<Lhs,Rhs,ResultType,RowMajor,R
{
static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
{
- typedef SparseMatrix<typename ResultType::Scalar,RowMajor> RowMajorMatrix;
- typedef SparseMatrix<typename ResultType::Scalar,ColMajor> ColMajorMatrix;
+ typedef SparseMatrix<typename ResultType::Scalar,RowMajor,typename ResultType::Index> RowMajorMatrix;
+ typedef SparseMatrix<typename ResultType::Scalar,ColMajor,typename ResultType::Index> ColMajorMatrix;
RowMajorMatrix resRow(lhs.rows(),rhs.cols());
internal::conservative_sparse_sparse_product_impl<Rhs,Lhs,RowMajorMatrix>(rhs, lhs, resRow);
// sort the non zeros:
diff --git a/Eigen/src/SparseCore/MappedSparseMatrix.h b/Eigen/src/SparseCore/MappedSparseMatrix.h
index 93cd4832d..ab1a266a9 100644
--- a/Eigen/src/SparseCore/MappedSparseMatrix.h
+++ b/Eigen/src/SparseCore/MappedSparseMatrix.h
@@ -50,6 +50,8 @@ class MappedSparseMatrix
inline Index cols() const { return IsRowMajor ? m_innerSize : m_outerSize; }
inline Index innerSize() const { return m_innerSize; }
inline Index outerSize() const { return m_outerSize; }
+
+ bool isCompressed() const { return true; }
//----------------------------------------
// direct access interface
diff --git a/Eigen/src/SparseCore/SparseAssign.h b/Eigen/src/SparseCore/SparseAssign.h
deleted file mode 100644
index e69de29bb..000000000
--- a/Eigen/src/SparseCore/SparseAssign.h
+++ /dev/null
diff --git a/Eigen/src/SparseCore/SparseBlock.h b/Eigen/src/SparseCore/SparseBlock.h
index eefd80702..16a20a574 100644
--- a/Eigen/src/SparseCore/SparseBlock.h
+++ b/Eigen/src/SparseCore/SparseBlock.h
@@ -12,51 +12,37 @@
namespace Eigen {
-namespace internal {
-template<typename MatrixType, int Size>
-struct traits<SparseInnerVectorSet<MatrixType, Size> >
+template<typename XprType, int BlockRows, int BlockCols>
+class BlockImpl<XprType,BlockRows,BlockCols,true,Sparse>
+ : public SparseMatrixBase<Block<XprType,BlockRows,BlockCols,true> >
{
- typedef typename traits<MatrixType>::Scalar Scalar;
- typedef typename traits<MatrixType>::Index Index;
- typedef typename traits<MatrixType>::StorageKind StorageKind;
- typedef MatrixXpr XprKind;
- enum {
- IsRowMajor = (int(MatrixType::Flags)&RowMajorBit)==RowMajorBit,
- Flags = MatrixType::Flags,
- RowsAtCompileTime = IsRowMajor ? Size : MatrixType::RowsAtCompileTime,
- ColsAtCompileTime = IsRowMajor ? MatrixType::ColsAtCompileTime : Size,
- MaxRowsAtCompileTime = RowsAtCompileTime,
- MaxColsAtCompileTime = ColsAtCompileTime,
- CoeffReadCost = MatrixType::CoeffReadCost
- };
-};
-} // end namespace internal
-
-template<typename MatrixType, int Size>
-class SparseInnerVectorSet : internal::no_assignment_operator,
- public SparseMatrixBase<SparseInnerVectorSet<MatrixType, Size> >
-{
- public:
-
- enum { IsRowMajor = internal::traits<SparseInnerVectorSet>::IsRowMajor };
-
- EIGEN_SPARSE_PUBLIC_INTERFACE(SparseInnerVectorSet)
- class InnerIterator: public MatrixType::InnerIterator
+ typedef typename internal::remove_all<typename XprType::Nested>::type _MatrixTypeNested;
+ typedef Block<XprType, BlockRows, BlockCols, true> BlockType;
+public:
+ enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor };
+protected:
+ enum { OuterSize = IsRowMajor ? BlockRows : BlockCols };
+public:
+ EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType)
+
+ class InnerIterator: public XprType::InnerIterator
{
+ typedef typename BlockImpl::Index Index;
public:
- inline InnerIterator(const SparseInnerVectorSet& xpr, Index outer)
- : MatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer)
+ inline InnerIterator(const BlockType& xpr, Index outer)
+ : XprType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer)
{}
inline Index row() const { return IsRowMajor ? m_outer : this->index(); }
inline Index col() const { return IsRowMajor ? this->index() : m_outer; }
protected:
Index m_outer;
};
- class ReverseInnerIterator: public MatrixType::ReverseInnerIterator
+ class ReverseInnerIterator: public XprType::ReverseInnerIterator
{
+ typedef typename BlockImpl::Index Index;
public:
- inline ReverseInnerIterator(const SparseInnerVectorSet& xpr, Index outer)
- : MatrixType::ReverseInnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer)
+ inline ReverseInnerIterator(const BlockType& xpr, Index outer)
+ : XprType::ReverseInnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer)
{}
inline Index row() const { return IsRowMajor ? m_outer : this->index(); }
inline Index col() const { return IsRowMajor ? this->index() : m_outer; }
@@ -64,39 +50,24 @@ class SparseInnerVectorSet : internal::no_assignment_operator,
Index m_outer;
};
- inline SparseInnerVectorSet(const MatrixType& matrix, Index outerStart, Index outerSize)
- : m_matrix(matrix), m_outerStart(outerStart), m_outerSize(outerSize)
- {
- eigen_assert( (outerStart>=0) && ((outerStart+outerSize)<=matrix.outerSize()) );
- }
-
- inline SparseInnerVectorSet(const MatrixType& matrix, Index outer)
- : m_matrix(matrix), m_outerStart(outer), m_outerSize(Size)
- {
- eigen_assert(Size!=Dynamic);
- eigen_assert( (outer>=0) && (outer<matrix.outerSize()) );
- }
-
-// template<typename OtherDerived>
-// inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other)
-// {
-// return *this;
-// }
+ inline BlockImpl(const XprType& xpr, int i)
+ : m_matrix(xpr), m_outerStart(i), m_outerSize(OuterSize)
+ {}
-// template<typename Sparse>
-// inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other)
-// {
-// return *this;
-// }
+ inline BlockImpl(const XprType& xpr, int startRow, int startCol, int blockRows, int blockCols)
+ : m_matrix(xpr), m_outerStart(IsRowMajor ? startRow : startCol), m_outerSize(IsRowMajor ? blockRows : blockCols)
+ {}
EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
protected:
- const typename MatrixType::Nested m_matrix;
+ typename XprType::Nested m_matrix;
Index m_outerStart;
- const internal::variable_if_dynamic<Index, Size> m_outerSize;
+ const internal::variable_if_dynamic<Index, OuterSize> m_outerSize;
+
+ EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl)
};
@@ -104,32 +75,36 @@ class SparseInnerVectorSet : internal::no_assignment_operator,
* specialisation for SparseMatrix
***************************************************************************/
-template<typename _Scalar, int _Options, typename _Index, int Size>
-class SparseInnerVectorSet<SparseMatrix<_Scalar, _Options, _Index>, Size>
- : public SparseMatrixBase<SparseInnerVectorSet<SparseMatrix<_Scalar, _Options, _Index>, Size> >
+template<typename _Scalar, int _Options, typename _Index, int BlockRows, int BlockCols>
+class BlockImpl<SparseMatrix<_Scalar, _Options, _Index>,BlockRows,BlockCols,true,Sparse>
+ : public SparseMatrixBase<Block<SparseMatrix<_Scalar, _Options, _Index>,BlockRows,BlockCols,true> >
{
- typedef SparseMatrix<_Scalar, _Options, _Index> MatrixType;
- public:
-
- enum { IsRowMajor = internal::traits<SparseInnerVectorSet>::IsRowMajor };
-
- EIGEN_SPARSE_PUBLIC_INTERFACE(SparseInnerVectorSet)
- class InnerIterator: public MatrixType::InnerIterator
+ typedef SparseMatrix<_Scalar, _Options, _Index> SparseMatrixType;
+ typedef typename internal::remove_all<typename SparseMatrixType::Nested>::type _MatrixTypeNested;
+ typedef Block<SparseMatrixType, BlockRows, BlockCols, true> BlockType;
+public:
+ enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor };
+ EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType)
+protected:
+ enum { OuterSize = IsRowMajor ? BlockRows : BlockCols };
+public:
+
+ class InnerIterator: public SparseMatrixType::InnerIterator
{
public:
- inline InnerIterator(const SparseInnerVectorSet& xpr, Index outer)
- : MatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer)
+ inline InnerIterator(const BlockType& xpr, Index outer)
+ : SparseMatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer)
{}
inline Index row() const { return IsRowMajor ? m_outer : this->index(); }
inline Index col() const { return IsRowMajor ? this->index() : m_outer; }
protected:
Index m_outer;
};
- class ReverseInnerIterator: public MatrixType::ReverseInnerIterator
+ class ReverseInnerIterator: public SparseMatrixType::ReverseInnerIterator
{
public:
- inline ReverseInnerIterator(const SparseInnerVectorSet& xpr, Index outer)
- : MatrixType::ReverseInnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer)
+ inline ReverseInnerIterator(const BlockType& xpr, Index outer)
+ : SparseMatrixType::ReverseInnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer)
{}
inline Index row() const { return IsRowMajor ? m_outer : this->index(); }
inline Index col() const { return IsRowMajor ? this->index() : m_outer; }
@@ -137,23 +112,18 @@ class SparseInnerVectorSet<SparseMatrix<_Scalar, _Options, _Index>, Size>
Index m_outer;
};
- inline SparseInnerVectorSet(const MatrixType& matrix, Index outerStart, Index outerSize)
- : m_matrix(matrix), m_outerStart(outerStart), m_outerSize(outerSize)
- {
- eigen_assert( (outerStart>=0) && ((outerStart+outerSize)<=matrix.outerSize()) );
- }
+ inline BlockImpl(const SparseMatrixType& xpr, int i)
+ : m_matrix(xpr), m_outerStart(i), m_outerSize(OuterSize)
+ {}
- inline SparseInnerVectorSet(const MatrixType& matrix, Index outer)
- : m_matrix(matrix), m_outerStart(outer), m_outerSize(Size)
- {
- eigen_assert(Size==1);
- eigen_assert( (outer>=0) && (outer<matrix.outerSize()) );
- }
+ inline BlockImpl(const SparseMatrixType& xpr, int startRow, int startCol, int blockRows, int blockCols)
+ : m_matrix(xpr), m_outerStart(IsRowMajor ? startRow : startCol), m_outerSize(IsRowMajor ? blockRows : blockCols)
+ {}
template<typename OtherDerived>
- inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other)
+ inline BlockType& operator=(const SparseMatrixBase<OtherDerived>& other)
{
- typedef typename internal::remove_all<typename MatrixType::Nested>::type _NestedMatrixType;
+ typedef typename internal::remove_all<typename SparseMatrixType::Nested>::type _NestedMatrixType;
_NestedMatrixType& matrix = const_cast<_NestedMatrixType&>(m_matrix);;
// This assignement is slow if this vector set is not empty
// and/or it is not at the end of the nonzeros of the underlying matrix.
@@ -163,70 +133,69 @@ class SparseInnerVectorSet<SparseMatrix<_Scalar, _Options, _Index>, Size>
// 2 - let's check whether there is enough allocated memory
Index nnz = tmp.nonZeros();
- Index nnz_previous = nonZeros();
- Index free_size = Index(matrix.data().allocatedSize()) + nnz_previous;
- Index nnz_head = m_outerStart==0 ? 0 : matrix.outerIndexPtr()[m_outerStart];
- Index tail = m_matrix.outerIndexPtr()[m_outerStart+m_outerSize.value()];
- Index nnz_tail = matrix.nonZeros() - tail;
-
- if(nnz>free_size)
+ Index start = m_outerStart==0 ? 0 : matrix.outerIndexPtr()[m_outerStart]; // starting position of the current block
+ Index end = m_matrix.outerIndexPtr()[m_outerStart+m_outerSize.value()]; // ending posiiton of the current block
+ Index block_size = end - start; // available room in the current block
+ Index tail_size = m_matrix.outerIndexPtr()[m_matrix.outerSize()] - end;
+
+ Index free_size = m_matrix.isCompressed()
+ ? Index(matrix.data().allocatedSize()) + block_size
+ : block_size;
+
+ if(nnz>free_size)
{
// realloc manually to reduce copies
- typename MatrixType::Storage newdata(m_matrix.nonZeros() - nnz_previous + nnz);
+ typename SparseMatrixType::Storage newdata(m_matrix.data().allocatedSize() - block_size + nnz);
- std::memcpy(&newdata.value(0), &m_matrix.data().value(0), nnz_head*sizeof(Scalar));
- std::memcpy(&newdata.index(0), &m_matrix.data().index(0), nnz_head*sizeof(Index));
+ std::memcpy(&newdata.value(0), &m_matrix.data().value(0), start*sizeof(Scalar));
+ std::memcpy(&newdata.index(0), &m_matrix.data().index(0), start*sizeof(Index));
- std::memcpy(&newdata.value(nnz_head), &tmp.data().value(0), nnz*sizeof(Scalar));
- std::memcpy(&newdata.index(nnz_head), &tmp.data().index(0), nnz*sizeof(Index));
+ std::memcpy(&newdata.value(start), &tmp.data().value(0), nnz*sizeof(Scalar));
+ std::memcpy(&newdata.index(start), &tmp.data().index(0), nnz*sizeof(Index));
- std::memcpy(&newdata.value(nnz_head+nnz), &matrix.data().value(tail), nnz_tail*sizeof(Scalar));
- std::memcpy(&newdata.index(nnz_head+nnz), &matrix.data().index(tail), nnz_tail*sizeof(Index));
+ std::memcpy(&newdata.value(start+nnz), &matrix.data().value(end), tail_size*sizeof(Scalar));
+ std::memcpy(&newdata.index(start+nnz), &matrix.data().index(end), tail_size*sizeof(Index));
+
+ newdata.resize(m_matrix.outerIndexPtr()[m_matrix.outerSize()] - block_size + nnz);
matrix.data().swap(newdata);
}
else
{
// no need to realloc, simply copy the tail at its respective position and insert tmp
- matrix.data().resize(nnz_head + nnz + nnz_tail);
-
- if(nnz<nnz_previous)
- {
- std::memcpy(&matrix.data().value(nnz_head+nnz), &matrix.data().value(tail), nnz_tail*sizeof(Scalar));
- std::memcpy(&matrix.data().index(nnz_head+nnz), &matrix.data().index(tail), nnz_tail*sizeof(Index));
- }
- else
- {
- for(Index i=nnz_tail-1; i>=0; --i)
- {
- matrix.data().value(nnz_head+nnz+i) = matrix.data().value(tail+i);
- matrix.data().index(nnz_head+nnz+i) = matrix.data().index(tail+i);
- }
- }
-
- std::memcpy(&matrix.data().value(nnz_head), &tmp.data().value(0), nnz*sizeof(Scalar));
- std::memcpy(&matrix.data().index(nnz_head), &tmp.data().index(0), nnz*sizeof(Index));
+ matrix.data().resize(start + nnz + tail_size);
+
+ std::memmove(&matrix.data().value(start+nnz), &matrix.data().value(end), tail_size*sizeof(Scalar));
+ std::memmove(&matrix.data().index(start+nnz), &matrix.data().index(end), tail_size*sizeof(Index));
+
+ std::memcpy(&matrix.data().value(start), &tmp.data().value(0), nnz*sizeof(Scalar));
+ std::memcpy(&matrix.data().index(start), &tmp.data().index(0), nnz*sizeof(Index));
}
+
+ // update innerNonZeros
+ if(!m_matrix.isCompressed())
+ for(Index j=0; j<m_outerSize.value(); ++j)
+ matrix.innerNonZeroPtr()[m_outerStart+j] = tmp.innerVector(j).nonZeros();
// update outer index pointers
- Index p = nnz_head;
+ Index p = start;
for(Index k=0; k<m_outerSize.value(); ++k)
{
matrix.outerIndexPtr()[m_outerStart+k] = p;
p += tmp.innerVector(k).nonZeros();
}
- std::ptrdiff_t offset = nnz - nnz_previous;
+ std::ptrdiff_t offset = nnz - block_size;
for(Index k = m_outerStart + m_outerSize.value(); k<=matrix.outerSize(); ++k)
{
matrix.outerIndexPtr()[k] += offset;
}
- return *this;
+ return derived();
}
- inline SparseInnerVectorSet& operator=(const SparseInnerVectorSet& other)
+ inline BlockType& operator=(const BlockType& other)
{
- return operator=<SparseInnerVectorSet>(other);
+ return operator=<BlockType>(other);
}
inline const Scalar* valuePtr() const
@@ -252,12 +221,12 @@ class SparseInnerVectorSet<SparseMatrix<_Scalar, _Options, _Index>, Size>
else if(m_outerSize.value()==0)
return 0;
else
- return Map<const Matrix<Index,Size,1> >(m_matrix.innerNonZeroPtr()+m_outerStart, m_outerSize.value()).sum();
+ return Map<const Matrix<Index,OuterSize,1> >(m_matrix.innerNonZeroPtr()+m_outerStart, m_outerSize.value()).sum();
}
const Scalar& lastCoeff() const
{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(SparseInnerVectorSet);
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(BlockImpl);
eigen_assert(nonZeros()>0);
if(m_matrix.isCompressed())
return m_matrix.valuePtr()[m_matrix.outerIndexPtr()[m_outerStart+1]-1];
@@ -265,122 +234,175 @@ class SparseInnerVectorSet<SparseMatrix<_Scalar, _Options, _Index>, Size>
return m_matrix.valuePtr()[m_matrix.outerIndexPtr()[m_outerStart]+m_matrix.innerNonZeroPtr()[m_outerStart]-1];
}
-// template<typename Sparse>
-// inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other)
-// {
-// return *this;
-// }
-
EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
protected:
- typename MatrixType::Nested m_matrix;
+ typename SparseMatrixType::Nested m_matrix;
Index m_outerStart;
- const internal::variable_if_dynamic<Index, Size> m_outerSize;
+ const internal::variable_if_dynamic<Index, OuterSize> m_outerSize;
};
//----------
-/** \returns the i-th row of the matrix \c *this. For row-major matrix only. */
-template<typename Derived>
-SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::row(Index i)
-{
- EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES);
- return innerVector(i);
-}
-
-/** \returns the i-th row of the matrix \c *this. For row-major matrix only.
- * (read-only version) */
-template<typename Derived>
-const SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::row(Index i) const
-{
- EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES);
- return innerVector(i);
-}
-
-/** \returns the i-th column of the matrix \c *this. For column-major matrix only. */
-template<typename Derived>
-SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::col(Index i)
-{
- EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
- return innerVector(i);
-}
-
-/** \returns the i-th column of the matrix \c *this. For column-major matrix only.
- * (read-only version) */
-template<typename Derived>
-const SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::col(Index i) const
-{
- EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
- return innerVector(i);
-}
-
/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this
* is col-major (resp. row-major).
*/
template<typename Derived>
-SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::innerVector(Index outer)
-{ return SparseInnerVectorSet<Derived,1>(derived(), outer); }
+typename SparseMatrixBase<Derived>::InnerVectorReturnType SparseMatrixBase<Derived>::innerVector(Index outer)
+{ return InnerVectorReturnType(derived(), outer); }
/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this
* is col-major (resp. row-major). Read-only.
*/
template<typename Derived>
-const SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::innerVector(Index outer) const
-{ return SparseInnerVectorSet<Derived,1>(derived(), outer); }
+const typename SparseMatrixBase<Derived>::ConstInnerVectorReturnType SparseMatrixBase<Derived>::innerVector(Index outer) const
+{ return ConstInnerVectorReturnType(derived(), outer); }
-/** \returns the i-th row of the matrix \c *this. For row-major matrix only. */
+/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this
+ * is col-major (resp. row-major).
+ */
template<typename Derived>
-SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::middleRows(Index start, Index size)
+Block<Derived,Dynamic,Dynamic,true> SparseMatrixBase<Derived>::innerVectors(Index outerStart, Index outerSize)
{
- EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES);
- return innerVectors(start, size);
+ return Block<Derived,Dynamic,Dynamic,true>(derived(),
+ IsRowMajor ? outerStart : 0, IsRowMajor ? 0 : outerStart,
+ IsRowMajor ? outerSize : rows(), IsRowMajor ? cols() : outerSize);
+
}
-/** \returns the i-th row of the matrix \c *this. For row-major matrix only.
- * (read-only version) */
+/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this
+ * is col-major (resp. row-major). Read-only.
+ */
template<typename Derived>
-const SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::middleRows(Index start, Index size) const
+const Block<const Derived,Dynamic,Dynamic,true> SparseMatrixBase<Derived>::innerVectors(Index outerStart, Index outerSize) const
{
- EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES);
- return innerVectors(start, size);
+ return Block<const Derived,Dynamic,Dynamic,true>(derived(),
+ IsRowMajor ? outerStart : 0, IsRowMajor ? 0 : outerStart,
+ IsRowMajor ? outerSize : rows(), IsRowMajor ? cols() : outerSize);
+
}
-/** \returns the i-th column of the matrix \c *this. For column-major matrix only. */
-template<typename Derived>
-SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::middleCols(Index start, Index size)
+/** Generic implementation of sparse Block expression.
+ * Real-only.
+ */
+template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
+class BlockImpl<XprType,BlockRows,BlockCols,InnerPanel,Sparse>
+ : public SparseMatrixBase<Block<XprType,BlockRows,BlockCols,InnerPanel> >, internal::no_assignment_operator
{
- EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
- return innerVectors(start, size);
-}
+ typedef typename internal::remove_all<typename XprType::Nested>::type _MatrixTypeNested;
+ typedef Block<XprType, BlockRows, BlockCols, InnerPanel> BlockType;
+public:
+ enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor };
+ EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType)
+
+ /** Column or Row constructor
+ */
+ inline BlockImpl(const XprType& xpr, int i)
+ : m_matrix(xpr),
+ m_startRow( (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0),
+ m_startCol( (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0),
+ m_blockRows(xpr.rows()),
+ m_blockCols(xpr.cols())
+ {}
+
+ /** Dynamic-size constructor
+ */
+ inline BlockImpl(const XprType& xpr, int startRow, int startCol, int blockRows, int blockCols)
+ : m_matrix(xpr), m_startRow(startRow), m_startCol(startCol), m_blockRows(blockRows), m_blockCols(blockCols)
+ {}
+
+ inline int rows() const { return m_blockRows.value(); }
+ inline int cols() const { return m_blockCols.value(); }
+
+ inline Scalar& coeffRef(int row, int col)
+ {
+ return m_matrix.const_cast_derived()
+ .coeffRef(row + m_startRow.value(), col + m_startCol.value());
+ }
-/** \returns the i-th column of the matrix \c *this. For column-major matrix only.
- * (read-only version) */
-template<typename Derived>
-const SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::middleCols(Index start, Index size) const
-{
- EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
- return innerVectors(start, size);
-}
+ inline const Scalar coeff(int row, int col) const
+ {
+ return m_matrix.coeff(row + m_startRow.value(), col + m_startCol.value());
+ }
+ inline Scalar& coeffRef(int index)
+ {
+ return m_matrix.const_cast_derived()
+ .coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
+ m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
+ }
+ inline const Scalar coeff(int index) const
+ {
+ return m_matrix
+ .coeff(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
+ m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
+ }
+
+ inline const _MatrixTypeNested& nestedExpression() const { return m_matrix; }
+
+ class InnerIterator : public _MatrixTypeNested::InnerIterator
+ {
+ typedef typename _MatrixTypeNested::InnerIterator Base;
+ const BlockType& m_block;
+ Index m_end;
+ public:
+
+ EIGEN_STRONG_INLINE InnerIterator(const BlockType& block, Index outer)
+ : Base(block.derived().nestedExpression(), outer + (IsRowMajor ? block.m_startRow.value() : block.m_startCol.value())),
+ m_block(block),
+ m_end(IsRowMajor ? block.m_startCol.value()+block.m_blockCols.value() : block.m_startRow.value()+block.m_blockRows.value())
+ {
+ while( (Base::operator bool()) && (Base::index() < (IsRowMajor ? m_block.m_startCol.value() : m_block.m_startRow.value())) )
+ Base::operator++();
+ }
-/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this
- * is col-major (resp. row-major).
- */
-template<typename Derived>
-SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::innerVectors(Index outerStart, Index outerSize)
-{ return SparseInnerVectorSet<Derived,Dynamic>(derived(), outerStart, outerSize); }
+ inline Index index() const { return Base::index() - (IsRowMajor ? m_block.m_startCol.value() : m_block.m_startRow.value()); }
+ inline Index outer() const { return Base::outer() - (IsRowMajor ? m_block.m_startRow.value() : m_block.m_startCol.value()); }
+ inline Index row() const { return Base::row() - m_block.m_startRow.value(); }
+ inline Index col() const { return Base::col() - m_block.m_startCol.value(); }
+
+ inline operator bool() const { return Base::operator bool() && Base::index() < m_end; }
+ };
+ class ReverseInnerIterator : public _MatrixTypeNested::ReverseInnerIterator
+ {
+ typedef typename _MatrixTypeNested::ReverseInnerIterator Base;
+ const BlockType& m_block;
+ Index m_begin;
+ public:
+
+ EIGEN_STRONG_INLINE ReverseInnerIterator(const BlockType& block, Index outer)
+ : Base(block.derived().nestedExpression(), outer + (IsRowMajor ? block.m_startRow.value() : block.m_startCol.value())),
+ m_block(block),
+ m_begin(IsRowMajor ? block.m_startCol.value() : block.m_startRow.value())
+ {
+ while( (Base::operator bool()) && (Base::index() >= (IsRowMajor ? m_block.m_startCol.value()+block.m_blockCols.value() : m_block.m_startRow.value()+block.m_blockRows.value())) )
+ Base::operator--();
+ }
-/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this
- * is col-major (resp. row-major). Read-only.
- */
-template<typename Derived>
-const SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::innerVectors(Index outerStart, Index outerSize) const
-{ return SparseInnerVectorSet<Derived,Dynamic>(derived(), outerStart, outerSize); }
+ inline Index index() const { return Base::index() - (IsRowMajor ? m_block.m_startCol.value() : m_block.m_startRow.value()); }
+ inline Index outer() const { return Base::outer() - (IsRowMajor ? m_block.m_startRow.value() : m_block.m_startCol.value()); }
+ inline Index row() const { return Base::row() - m_block.m_startRow.value(); }
+ inline Index col() const { return Base::col() - m_block.m_startCol.value(); }
+
+ inline operator bool() const { return Base::operator bool() && Base::index() >= m_begin; }
+ };
+ protected:
+ friend class InnerIterator;
+ friend class ReverseInnerIterator;
+
+ EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl)
+
+ typename XprType::Nested m_matrix;
+ const internal::variable_if_dynamic<Index, XprType::RowsAtCompileTime == 1 ? 0 : Dynamic> m_startRow;
+ const internal::variable_if_dynamic<Index, XprType::ColsAtCompileTime == 1 ? 0 : Dynamic> m_startCol;
+ const internal::variable_if_dynamic<Index, RowsAtCompileTime> m_blockRows;
+ const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_blockCols;
+
+};
} // end namespace Eigen
diff --git a/Eigen/src/SparseCore/SparseColEtree.h b/Eigen/src/SparseCore/SparseColEtree.h
new file mode 100644
index 000000000..f8745f461
--- /dev/null
+++ b/Eigen/src/SparseCore/SparseColEtree.h
@@ -0,0 +1,206 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+
+/*
+
+ * NOTE: This file is the modified version of sp_coletree.c file in SuperLU
+
+ * -- SuperLU routine (version 3.1) --
+ * Univ. of California Berkeley, Xerox Palo Alto Research Center,
+ * and Lawrence Berkeley National Lab.
+ * August 1, 2008
+ *
+ * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
+ * EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program for any
+ * purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is
+ * granted, provided the above notices are retained, and a notice that
+ * the code was modified is included with the above copyright notice.
+ */
+#ifndef SPARSE_COLETREE_H
+#define SPARSE_COLETREE_H
+
+namespace Eigen {
+
+namespace internal {
+
+/** Find the root of the tree/set containing the vertex i : Use Path halving */
+template<typename Index, typename IndexVector>
+Index etree_find (Index i, IndexVector& pp)
+{
+ Index p = pp(i); // Parent
+ Index gp = pp(p); // Grand parent
+ while (gp != p)
+ {
+ pp(i) = gp; // Parent pointer on find path is changed to former grand parent
+ i = gp;
+ p = pp(i);
+ gp = pp(p);
+ }
+ return p;
+}
+
+/** Compute the column elimination tree of a sparse matrix
+ * \param mat The matrix in column-major format.
+ * \param parent The elimination tree
+ * \param firstRowElt The column index of the first element in each row
+ * \param perm The permutation to apply to the column of \b mat
+ */
+template <typename MatrixType, typename IndexVector>
+int coletree(const MatrixType& mat, IndexVector& parent, IndexVector& firstRowElt, typename MatrixType::Index *perm=0)
+{
+ typedef typename MatrixType::Index Index;
+ Index nc = mat.cols(); // Number of columns
+ Index m = mat.rows();
+ Index diagSize = (std::min)(nc,m);
+ IndexVector root(nc); // root of subtree of etree
+ root.setZero();
+ IndexVector pp(nc); // disjoint sets
+ pp.setZero(); // Initialize disjoint sets
+ parent.resize(mat.cols());
+ //Compute first nonzero column in each row
+ Index row,col;
+ firstRowElt.resize(m);
+ firstRowElt.setConstant(nc);
+ firstRowElt.segment(0, diagSize).setLinSpaced(diagSize, 0, diagSize-1);
+ bool found_diag;
+ for (col = 0; col < nc; col++)
+ {
+ Index pcol = col;
+ if(perm) pcol = perm[col];
+ for (typename MatrixType::InnerIterator it(mat, pcol); it; ++it)
+ {
+ row = it.row();
+ firstRowElt(row) = (std::min)(firstRowElt(row), col);
+ }
+ }
+ /* Compute etree by Liu's algorithm for symmetric matrices,
+ except use (firstRowElt[r],c) in place of an edge (r,c) of A.
+ Thus each row clique in A'*A is replaced by a star
+ centered at its first vertex, which has the same fill. */
+ Index rset, cset, rroot;
+ for (col = 0; col < nc; col++)
+ {
+ found_diag = col>=m;
+ pp(col) = col;
+ cset = col;
+ root(cset) = col;
+ parent(col) = nc;
+ /* The diagonal element is treated here even if it does not exist in the matrix
+ * hence the loop is executed once more */
+ Index pcol = col;
+ if(perm) pcol = perm[col];
+ for (typename MatrixType::InnerIterator it(mat, pcol); it||!found_diag; ++it)
+ { // A sequence of interleaved find and union is performed
+ Index i = col;
+ if(it) i = it.index();
+ if (i == col) found_diag = true;
+
+ row = firstRowElt(i);
+ if (row >= col) continue;
+ rset = internal::etree_find(row, pp); // Find the name of the set containing row
+ rroot = root(rset);
+ if (rroot != col)
+ {
+ parent(rroot) = col;
+ pp(cset) = rset;
+ cset = rset;
+ root(cset) = col;
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * Depth-first search from vertex n. No recursion.
+ * This routine was contributed by Cédric Doucet, CEDRAT Group, Meylan, France.
+*/
+template <typename Index, typename IndexVector>
+void nr_etdfs (Index n, IndexVector& parent, IndexVector& first_kid, IndexVector& next_kid, IndexVector& post, Index postnum)
+{
+ Index current = n, first, next;
+ while (postnum != n)
+ {
+ // No kid for the current node
+ first = first_kid(current);
+
+ // no kid for the current node
+ if (first == -1)
+ {
+ // Numbering this node because it has no kid
+ post(current) = postnum++;
+
+ // looking for the next kid
+ next = next_kid(current);
+ while (next == -1)
+ {
+ // No more kids : back to the parent node
+ current = parent(current);
+ // numbering the parent node
+ post(current) = postnum++;
+
+ // Get the next kid
+ next = next_kid(current);
+ }
+ // stopping criterion
+ if (postnum == n+1) return;
+
+ // Updating current node
+ current = next;
+ }
+ else
+ {
+ current = first;
+ }
+ }
+}
+
+
+/**
+ * \brief Post order a tree
+ * \param n the number of nodes
+ * \param parent Input tree
+ * \param post postordered tree
+ */
+template <typename Index, typename IndexVector>
+void treePostorder(Index n, IndexVector& parent, IndexVector& post)
+{
+ IndexVector first_kid, next_kid; // Linked list of children
+ Index postnum;
+ // Allocate storage for working arrays and results
+ first_kid.resize(n+1);
+ next_kid.setZero(n+1);
+ post.setZero(n+1);
+
+ // Set up structure describing children
+ Index v, dad;
+ first_kid.setConstant(-1);
+ for (v = n-1; v >= 0; v--)
+ {
+ dad = parent(v);
+ next_kid(v) = first_kid(dad);
+ first_kid(dad) = v;
+ }
+
+ // Depth-first search from dummy root vertex #n
+ postnum = 0;
+ internal::nr_etdfs(n, parent, first_kid, next_kid, post, postnum);
+}
+
+} // end namespace internal
+
+} // end namespace Eigen
+
+#endif // SPARSE_COLETREE_H
diff --git a/Eigen/src/SparseCore/SparseCwiseBinaryOp.h b/Eigen/src/SparseCore/SparseCwiseBinaryOp.h
index d5f97f78f..60ca7690c 100644
--- a/Eigen/src/SparseCore/SparseCwiseBinaryOp.h
+++ b/Eigen/src/SparseCore/SparseCwiseBinaryOp.h
@@ -73,7 +73,8 @@ class CwiseBinaryOpImpl<BinaryOp,Lhs,Rhs,Sparse>::InnerIterator
typedef internal::sparse_cwise_binary_op_inner_iterator_selector<
BinaryOp,Lhs,Rhs, InnerIterator> Base;
- EIGEN_STRONG_INLINE InnerIterator(const CwiseBinaryOpImpl& binOp, typename CwiseBinaryOpImpl::Index outer)
+ // NOTE: we have to prefix Index by "typename Lhs::" to avoid an ICE with VC11
+ EIGEN_STRONG_INLINE InnerIterator(const CwiseBinaryOpImpl& binOp, typename Lhs::Index outer)
: Base(binOp.derived(),outer)
{}
};
@@ -300,7 +301,7 @@ template<typename OtherDerived>
EIGEN_STRONG_INLINE Derived &
SparseMatrixBase<Derived>::operator-=(const SparseMatrixBase<OtherDerived> &other)
{
- return *this = derived() - other.derived();
+ return derived() = derived() - other.derived();
}
template<typename Derived>
@@ -308,7 +309,7 @@ template<typename OtherDerived>
EIGEN_STRONG_INLINE Derived &
SparseMatrixBase<Derived>::operator+=(const SparseMatrixBase<OtherDerived>& other)
{
- return *this = derived() + other.derived();
+ return derived() = derived() + other.derived();
}
template<typename Derived>
diff --git a/Eigen/src/SparseCore/SparseDenseProduct.h b/Eigen/src/SparseCore/SparseDenseProduct.h
index 6f32940d6..78411db98 100644
--- a/Eigen/src/SparseCore/SparseDenseProduct.h
+++ b/Eigen/src/SparseCore/SparseDenseProduct.h
@@ -19,7 +19,10 @@ template<typename Lhs, typename Rhs, int InnerSize> struct SparseDenseProductRet
template<typename Lhs, typename Rhs> struct SparseDenseProductReturnType<Lhs,Rhs,1>
{
- typedef SparseDenseOuterProduct<Lhs,Rhs,false> Type;
+ typedef typename internal::conditional<
+ Lhs::IsRowMajor,
+ SparseDenseOuterProduct<Rhs,Lhs,true>,
+ SparseDenseOuterProduct<Lhs,Rhs,false> >::type Type;
};
template<typename Lhs, typename Rhs, int InnerSize> struct DenseSparseProductReturnType
@@ -29,7 +32,10 @@ template<typename Lhs, typename Rhs, int InnerSize> struct DenseSparseProductRet
template<typename Lhs, typename Rhs> struct DenseSparseProductReturnType<Lhs,Rhs,1>
{
- typedef SparseDenseOuterProduct<Rhs,Lhs,true> Type;
+ typedef typename internal::conditional<
+ Rhs::IsRowMajor,
+ SparseDenseOuterProduct<Rhs,Lhs,true>,
+ SparseDenseOuterProduct<Lhs,Rhs,false> >::type Type;
};
namespace internal {
@@ -39,7 +45,7 @@ struct traits<SparseDenseOuterProduct<Lhs,Rhs,Tr> >
{
typedef Sparse StorageKind;
typedef typename scalar_product_traits<typename traits<Lhs>::Scalar,
- typename traits<Rhs>::Scalar>::ReturnType Scalar;
+ typename traits<Rhs>::Scalar>::ReturnType Scalar;
typedef typename Lhs::Index Index;
typedef typename Lhs::Nested LhsNested;
typedef typename Rhs::Nested RhsNested;
@@ -111,20 +117,34 @@ template<typename Lhs, typename Rhs, bool Transpose>
class SparseDenseOuterProduct<Lhs,Rhs,Transpose>::InnerIterator : public _LhsNested::InnerIterator
{
typedef typename _LhsNested::InnerIterator Base;
+ typedef typename SparseDenseOuterProduct::Index Index;
public:
EIGEN_STRONG_INLINE InnerIterator(const SparseDenseOuterProduct& prod, Index outer)
- : Base(prod.lhs(), 0), m_outer(outer), m_factor(prod.rhs().coeff(outer))
- {
- }
+ : Base(prod.lhs(), 0), m_outer(outer), m_factor(get(prod.rhs(), outer, typename internal::traits<Rhs>::StorageKind() ))
+ { }
inline Index outer() const { return m_outer; }
- inline Index row() const { return Transpose ? Base::row() : m_outer; }
- inline Index col() const { return Transpose ? m_outer : Base::row(); }
+ inline Index row() const { return Transpose ? m_outer : Base::index(); }
+ inline Index col() const { return Transpose ? Base::index() : m_outer; }
inline Scalar value() const { return Base::value() * m_factor; }
protected:
- int m_outer;
+ static Scalar get(const _RhsNested &rhs, Index outer, Dense = Dense())
+ {
+ return rhs.coeff(outer);
+ }
+
+ static Scalar get(const _RhsNested &rhs, Index outer, Sparse = Sparse())
+ {
+ typename Traits::_RhsNested::InnerIterator it(rhs, outer);
+ if (it && it.index()==0)
+ return it.value();
+
+ return Scalar(0);
+ }
+
+ Index m_outer;
Scalar m_factor;
};
@@ -150,11 +170,11 @@ struct sparse_time_dense_product_impl<SparseLhsType,DenseRhsType,DenseResType, R
typedef typename internal::remove_all<DenseResType>::type Res;
typedef typename Lhs::Index Index;
typedef typename Lhs::InnerIterator LhsInnerIterator;
- static void run(const SparseLhsType& lhs, const DenseRhsType& rhs, DenseResType& res, typename Res::Scalar alpha)
+ static void run(const SparseLhsType& lhs, const DenseRhsType& rhs, DenseResType& res, const typename Res::Scalar& alpha)
{
for(Index c=0; c<rhs.cols(); ++c)
{
- int n = lhs.outerSize();
+ Index n = lhs.outerSize();
for(Index j=0; j<n; ++j)
{
typename Res::Scalar tmp(0);
@@ -174,7 +194,7 @@ struct sparse_time_dense_product_impl<SparseLhsType,DenseRhsType,DenseResType, C
typedef typename internal::remove_all<DenseResType>::type Res;
typedef typename Lhs::InnerIterator LhsInnerIterator;
typedef typename Lhs::Index Index;
- static void run(const SparseLhsType& lhs, const DenseRhsType& rhs, DenseResType& res, typename Res::Scalar alpha)
+ static void run(const SparseLhsType& lhs, const DenseRhsType& rhs, DenseResType& res, const typename Res::Scalar& alpha)
{
for(Index c=0; c<rhs.cols(); ++c)
{
@@ -196,7 +216,7 @@ struct sparse_time_dense_product_impl<SparseLhsType,DenseRhsType,DenseResType, R
typedef typename internal::remove_all<DenseResType>::type Res;
typedef typename Lhs::InnerIterator LhsInnerIterator;
typedef typename Lhs::Index Index;
- static void run(const SparseLhsType& lhs, const DenseRhsType& rhs, DenseResType& res, typename Res::Scalar alpha)
+ static void run(const SparseLhsType& lhs, const DenseRhsType& rhs, DenseResType& res, const typename Res::Scalar& alpha)
{
for(Index j=0; j<lhs.outerSize(); ++j)
{
@@ -215,7 +235,7 @@ struct sparse_time_dense_product_impl<SparseLhsType,DenseRhsType,DenseResType, C
typedef typename internal::remove_all<DenseResType>::type Res;
typedef typename Lhs::InnerIterator LhsInnerIterator;
typedef typename Lhs::Index Index;
- static void run(const SparseLhsType& lhs, const DenseRhsType& rhs, DenseResType& res, typename Res::Scalar alpha)
+ static void run(const SparseLhsType& lhs, const DenseRhsType& rhs, DenseResType& res, const typename Res::Scalar& alpha)
{
for(Index j=0; j<lhs.outerSize(); ++j)
{
@@ -244,7 +264,7 @@ class SparseTimeDenseProduct
SparseTimeDenseProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
{}
- template<typename Dest> void scaleAndAddTo(Dest& dest, Scalar alpha) const
+ template<typename Dest> void scaleAndAddTo(Dest& dest, const Scalar& alpha) const
{
internal::sparse_time_dense_product(m_lhs, m_rhs, dest, alpha);
}
@@ -274,7 +294,7 @@ class DenseTimeSparseProduct
DenseTimeSparseProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
{}
- template<typename Dest> void scaleAndAddTo(Dest& dest, Scalar alpha) const
+ template<typename Dest> void scaleAndAddTo(Dest& dest, const Scalar& alpha) const
{
Transpose<const _LhsNested> lhs_t(m_lhs);
Transpose<const _RhsNested> rhs_t(m_rhs);
diff --git a/Eigen/src/SparseCore/SparseDiagonalProduct.h b/Eigen/src/SparseCore/SparseDiagonalProduct.h
index 095bf6863..1bb590e64 100644
--- a/Eigen/src/SparseCore/SparseDiagonalProduct.h
+++ b/Eigen/src/SparseCore/SparseDiagonalProduct.h
@@ -78,7 +78,11 @@ class SparseDiagonalProduct
EIGEN_SPARSE_PUBLIC_INTERFACE(SparseDiagonalProduct)
typedef internal::sparse_diagonal_product_inner_iterator_selector
- <_LhsNested,_RhsNested,SparseDiagonalProduct,LhsMode,RhsMode> InnerIterator;
+ <_LhsNested,_RhsNested,SparseDiagonalProduct,LhsMode,RhsMode> InnerIterator;
+
+ // We do not want ReverseInnerIterator for diagonal-sparse products,
+ // but this dummy declaration is needed to make diag * sparse * diag compile.
+ class ReverseInnerIterator;
EIGEN_STRONG_INLINE SparseDiagonalProduct(const Lhs& lhs, const Rhs& rhs)
: m_lhs(lhs), m_rhs(rhs)
@@ -118,19 +122,23 @@ class sparse_diagonal_product_inner_iterator_selector
<Lhs,Rhs,SparseDiagonalProductType,SDP_IsDiagonal,SDP_IsSparseColMajor>
: public CwiseBinaryOp<
scalar_product_op<typename Lhs::Scalar>,
- SparseInnerVectorSet<Rhs,1>,
- typename Lhs::DiagonalVectorType>::InnerIterator
+ const typename Rhs::ConstInnerVectorReturnType,
+ const typename Lhs::DiagonalVectorType>::InnerIterator
{
typedef typename CwiseBinaryOp<
scalar_product_op<typename Lhs::Scalar>,
- SparseInnerVectorSet<Rhs,1>,
- typename Lhs::DiagonalVectorType>::InnerIterator Base;
+ const typename Rhs::ConstInnerVectorReturnType,
+ const typename Lhs::DiagonalVectorType>::InnerIterator Base;
typedef typename Lhs::Index Index;
+ Index m_outer;
public:
inline sparse_diagonal_product_inner_iterator_selector(
const SparseDiagonalProductType& expr, Index outer)
- : Base(expr.rhs().innerVector(outer) .cwiseProduct(expr.lhs().diagonal()), 0)
+ : Base(expr.rhs().innerVector(outer) .cwiseProduct(expr.lhs().diagonal()), 0), m_outer(outer)
{}
+
+ inline Index outer() const { return m_outer; }
+ inline Index col() const { return m_outer; }
};
template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
@@ -152,19 +160,23 @@ class sparse_diagonal_product_inner_iterator_selector
<Lhs,Rhs,SparseDiagonalProductType,SDP_IsSparseRowMajor,SDP_IsDiagonal>
: public CwiseBinaryOp<
scalar_product_op<typename Rhs::Scalar>,
- SparseInnerVectorSet<Lhs,1>,
- Transpose<const typename Rhs::DiagonalVectorType> >::InnerIterator
+ const typename Lhs::ConstInnerVectorReturnType,
+ const Transpose<const typename Rhs::DiagonalVectorType> >::InnerIterator
{
typedef typename CwiseBinaryOp<
scalar_product_op<typename Rhs::Scalar>,
- SparseInnerVectorSet<Lhs,1>,
- Transpose<const typename Rhs::DiagonalVectorType> >::InnerIterator Base;
+ const typename Lhs::ConstInnerVectorReturnType,
+ const Transpose<const typename Rhs::DiagonalVectorType> >::InnerIterator Base;
typedef typename Lhs::Index Index;
+ Index m_outer;
public:
inline sparse_diagonal_product_inner_iterator_selector(
const SparseDiagonalProductType& expr, Index outer)
- : Base(expr.lhs().innerVector(outer) .cwiseProduct(expr.rhs().diagonal().transpose()), 0)
+ : Base(expr.lhs().innerVector(outer) .cwiseProduct(expr.rhs().diagonal().transpose()), 0), m_outer(outer)
{}
+
+ inline Index outer() const { return m_outer; }
+ inline Index row() const { return m_outer; }
};
} // end namespace internal
diff --git a/Eigen/src/SparseCore/SparseDot.h b/Eigen/src/SparseCore/SparseDot.h
index 5c4a593dc..db39c9aec 100644
--- a/Eigen/src/SparseCore/SparseDot.h
+++ b/Eigen/src/SparseCore/SparseDot.h
@@ -30,7 +30,7 @@ SparseMatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
Scalar res(0);
while (i)
{
- res += internal::conj(i.value()) * other.coeff(i.index());
+ res += numext::conj(i.value()) * other.coeff(i.index());
++i;
}
return res;
@@ -54,8 +54,8 @@ SparseMatrixBase<Derived>::dot(const SparseMatrixBase<OtherDerived>& other) cons
typedef typename internal::remove_all<Nested>::type NestedCleaned;
typedef typename internal::remove_all<OtherNested>::type OtherNestedCleaned;
- const Nested nthis(derived());
- const OtherNested nother(other.derived());
+ Nested nthis(derived());
+ OtherNested nother(other.derived());
typename NestedCleaned::InnerIterator i(nthis,0);
typename OtherNestedCleaned::InnerIterator j(nother,0);
@@ -64,7 +64,7 @@ SparseMatrixBase<Derived>::dot(const SparseMatrixBase<OtherDerived>& other) cons
{
if (i.index()==j.index())
{
- res += internal::conj(i.value()) * j.value();
+ res += numext::conj(i.value()) * j.value();
++i; ++j;
}
else if (i.index()<j.index())
@@ -79,16 +79,23 @@ template<typename Derived>
inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
SparseMatrixBase<Derived>::squaredNorm() const
{
- return internal::real((*this).cwiseAbs2().sum());
+ return numext::real((*this).cwiseAbs2().sum());
}
template<typename Derived>
inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
SparseMatrixBase<Derived>::norm() const
{
- return internal::sqrt(squaredNorm());
+ using std::sqrt;
+ return sqrt(squaredNorm());
}
+template<typename Derived>
+inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
+SparseMatrixBase<Derived>::blueNorm() const
+{
+ return internal::blueNorm_impl(*this);
+}
} // end namespace Eigen
#endif // EIGEN_SPARSE_DOT_H
diff --git a/Eigen/src/SparseCore/SparseMatrix.h b/Eigen/src/SparseCore/SparseMatrix.h
index efb774f03..ba5e3a9b6 100644
--- a/Eigen/src/SparseCore/SparseMatrix.h
+++ b/Eigen/src/SparseCore/SparseMatrix.h
@@ -31,7 +31,7 @@ namespace Eigen {
*
* \tparam _Scalar the scalar type, i.e. the type of the coefficients
* \tparam _Options Union of bit flags controlling the storage scheme. Currently the only possibility
- * is RowMajor. The default is 0 which means column-major.
+ * is ColMajor or RowMajor. The default is 0 which means column-major.
* \tparam _Index the type of the indices. It has to be a \b signed type (e.g., short, int, std::ptrdiff_t). Default is \c int.
*
* This class can be extended with the help of the plugin mechanism described on the page
@@ -170,6 +170,8 @@ class SparseMatrix
* This function returns Scalar(0) if the element is an explicit \em zero */
inline Scalar coeff(Index row, Index col) const
{
+ eigen_assert(row>=0 && row<rows() && col>=0 && col<cols());
+
const Index outer = IsRowMajor ? row : col;
const Index inner = IsRowMajor ? col : row;
Index end = m_innerNonZeros ? m_outerIndex[outer] + m_innerNonZeros[outer] : m_outerIndex[outer+1];
@@ -186,6 +188,8 @@ class SparseMatrix
*/
inline Scalar& coeffRef(Index row, Index col)
{
+ eigen_assert(row>=0 && row<rows() && col>=0 && col<cols());
+
const Index outer = IsRowMajor ? row : col;
const Index inner = IsRowMajor ? col : row;
@@ -213,11 +217,13 @@ class SparseMatrix
* inserted in increasing inner index order, and in O(nnz_j) for a random insertion.
*
*/
- EIGEN_DONT_INLINE Scalar& insert(Index row, Index col)
+ Scalar& insert(Index row, Index col)
{
+ eigen_assert(row>=0 && row<rows() && col>=0 && col<cols());
+
if(isCompressed())
{
- reserve(VectorXi::Constant(outerSize(), 2));
+ reserve(Matrix<Index,Dynamic,1>::Constant(outerSize(), 2));
}
return insertUncompressed(row,col);
}
@@ -281,12 +287,12 @@ class SparseMatrix
template<class SizesType>
inline void reserveInnerVectors(const SizesType& reserveSizes)
{
-
if(isCompressed())
{
std::size_t totalReserveSize = 0;
// turn the matrix into non-compressed mode
- m_innerNonZeros = new Index[m_outerSize];
+ m_innerNonZeros = static_cast<Index*>(std::malloc(m_outerSize * sizeof(Index)));
+ if (!m_innerNonZeros) internal::throw_std_bad_alloc();
// temporarily use m_innerSizes to hold the new starting points.
Index* newOuterIndex = m_innerNonZeros;
@@ -299,11 +305,11 @@ class SparseMatrix
totalReserveSize += reserveSizes[j];
}
m_data.reserve(totalReserveSize);
- std::ptrdiff_t previousOuterIndex = m_outerIndex[m_outerSize];
- for(std::ptrdiff_t j=m_outerSize-1; j>=0; --j)
+ Index previousOuterIndex = m_outerIndex[m_outerSize];
+ for(Index j=m_outerSize-1; j>=0; --j)
{
- ptrdiff_t innerNNZ = previousOuterIndex - m_outerIndex[j];
- for(std::ptrdiff_t i=innerNNZ-1; i>=0; --i)
+ Index innerNNZ = previousOuterIndex - m_outerIndex[j];
+ for(Index i=innerNNZ-1; i>=0; --i)
{
m_data.index(newOuterIndex[j]+i) = m_data.index(m_outerIndex[j]+i);
m_data.value(newOuterIndex[j]+i) = m_data.value(m_outerIndex[j]+i);
@@ -318,25 +324,27 @@ class SparseMatrix
}
else
{
- Index* newOuterIndex = new Index[m_outerSize+1];
+ Index* newOuterIndex = static_cast<Index*>(std::malloc((m_outerSize+1)*sizeof(Index)));
+ if (!newOuterIndex) internal::throw_std_bad_alloc();
+
Index count = 0;
for(Index j=0; j<m_outerSize; ++j)
{
newOuterIndex[j] = count;
Index alreadyReserved = (m_outerIndex[j+1]-m_outerIndex[j]) - m_innerNonZeros[j];
- Index toReserve = std::max<std::ptrdiff_t>(reserveSizes[j], alreadyReserved);
+ Index toReserve = std::max<Index>(reserveSizes[j], alreadyReserved);
count += toReserve + m_innerNonZeros[j];
}
newOuterIndex[m_outerSize] = count;
m_data.resize(count);
- for(ptrdiff_t j=m_outerSize-1; j>=0; --j)
+ for(Index j=m_outerSize-1; j>=0; --j)
{
- std::ptrdiff_t offset = newOuterIndex[j] - m_outerIndex[j];
+ Index offset = newOuterIndex[j] - m_outerIndex[j];
if(offset>0)
{
- std::ptrdiff_t innerNNZ = m_innerNonZeros[j];
- for(std::ptrdiff_t i=innerNNZ-1; i>=0; --i)
+ Index innerNNZ = m_innerNonZeros[j];
+ for(Index i=innerNNZ-1; i>=0; --i)
{
m_data.index(newOuterIndex[j]+i) = m_data.index(m_outerIndex[j]+i);
m_data.value(newOuterIndex[j]+i) = m_data.value(m_outerIndex[j]+i);
@@ -345,7 +353,7 @@ class SparseMatrix
}
std::swap(m_outerIndex, newOuterIndex);
- delete[] newOuterIndex;
+ std::free(newOuterIndex);
}
}
@@ -394,7 +402,7 @@ class SparseMatrix
* \sa insertBack, insertBackByOuterInner */
inline void startVec(Index outer)
{
- eigen_assert(m_outerIndex[outer]==int(m_data.size()) && "You must call startVec for each inner vector sequentially");
+ eigen_assert(m_outerIndex[outer]==Index(m_data.size()) && "You must call startVec for each inner vector sequentially");
eigen_assert(m_outerIndex[outer+1]==0 && "You must call startVec for each inner vector sequentially");
m_outerIndex[outer+1] = m_outerIndex[outer];
}
@@ -431,7 +439,7 @@ class SparseMatrix
/** \internal
* same as insert(Index,Index) except that the indices are given relative to the storage order */
- EIGEN_DONT_INLINE Scalar& insertByOuterInner(Index j, Index i)
+ Scalar& insertByOuterInner(Index j, Index i)
{
return insert(IsRowMajor ? j : i, IsRowMajor ? i : j);
}
@@ -448,7 +456,7 @@ class SparseMatrix
for(Index j=1; j<m_outerSize; ++j)
{
Index nextOldStart = m_outerIndex[j+1];
- std::ptrdiff_t offset = oldStart - m_outerIndex[j];
+ Index offset = oldStart - m_outerIndex[j];
if(offset>0)
{
for(Index k=0; k<m_innerNonZeros[j]; ++k)
@@ -460,14 +468,26 @@ class SparseMatrix
m_outerIndex[j+1] = m_outerIndex[j] + m_innerNonZeros[j];
oldStart = nextOldStart;
}
- delete[] m_innerNonZeros;
+ std::free(m_innerNonZeros);
m_innerNonZeros = 0;
m_data.resize(m_outerIndex[m_outerSize]);
m_data.squeeze();
}
+ /** Turns the matrix into the uncompressed mode */
+ void uncompress()
+ {
+ if(m_innerNonZeros != 0)
+ return;
+ m_innerNonZeros = static_cast<Index*>(std::malloc(m_outerSize * sizeof(Index)));
+ for (Index i = 0; i < m_outerSize; i++)
+ {
+ m_innerNonZeros[i] = m_outerIndex[i+1] - m_outerIndex[i];
+ }
+ }
+
/** Suppresses all nonzeros which are \b much \b smaller \b than \a reference under the tolerence \a epsilon */
- void prune(Scalar reference, RealScalar epsilon = NumTraits<RealScalar>::dummy_precision())
+ void prune(const Scalar& reference, const RealScalar& epsilon = NumTraits<RealScalar>::dummy_precision())
{
prune(default_prunning_func(reference,epsilon));
}
@@ -506,6 +526,70 @@ class SparseMatrix
m_data.resize(k,0);
}
+ /** Resizes the matrix to a \a rows x \a cols matrix leaving old values untouched.
+ * \sa resizeNonZeros(Index), reserve(), setZero()
+ */
+ void conservativeResize(Index rows, Index cols)
+ {
+ // No change
+ if (this->rows() == rows && this->cols() == cols) return;
+
+ // If one dimension is null, then there is nothing to be preserved
+ if(rows==0 || cols==0) return resize(rows,cols);
+
+ Index innerChange = IsRowMajor ? cols - this->cols() : rows - this->rows();
+ Index outerChange = IsRowMajor ? rows - this->rows() : cols - this->cols();
+ Index newInnerSize = IsRowMajor ? cols : rows;
+
+ // Deals with inner non zeros
+ if (m_innerNonZeros)
+ {
+ // Resize m_innerNonZeros
+ Index *newInnerNonZeros = static_cast<Index*>(std::realloc(m_innerNonZeros, (m_outerSize + outerChange) * sizeof(Index)));
+ if (!newInnerNonZeros) internal::throw_std_bad_alloc();
+ m_innerNonZeros = newInnerNonZeros;
+
+ for(Index i=m_outerSize; i<m_outerSize+outerChange; i++)
+ m_innerNonZeros[i] = 0;
+ }
+ else if (innerChange < 0)
+ {
+ // Inner size decreased: allocate a new m_innerNonZeros
+ m_innerNonZeros = static_cast<Index*>(std::malloc((m_outerSize+outerChange+1) * sizeof(Index)));
+ if (!m_innerNonZeros) internal::throw_std_bad_alloc();
+ for(Index i = 0; i < m_outerSize; i++)
+ m_innerNonZeros[i] = m_outerIndex[i+1] - m_outerIndex[i];
+ }
+
+ // Change the m_innerNonZeros in case of a decrease of inner size
+ if (m_innerNonZeros && innerChange < 0)
+ {
+ for(Index i = 0; i < m_outerSize + (std::min)(outerChange, Index(0)); i++)
+ {
+ Index &n = m_innerNonZeros[i];
+ Index start = m_outerIndex[i];
+ while (n > 0 && m_data.index(start+n-1) >= newInnerSize) --n;
+ }
+ }
+
+ m_innerSize = newInnerSize;
+
+ // Re-allocate outer index structure if necessary
+ if (outerChange == 0)
+ return;
+
+ Index *newOuterIndex = static_cast<Index*>(std::realloc(m_outerIndex, (m_outerSize + outerChange + 1) * sizeof(Index)));
+ if (!newOuterIndex) internal::throw_std_bad_alloc();
+ m_outerIndex = newOuterIndex;
+ if (outerChange > 0)
+ {
+ Index last = m_outerSize == 0 ? 0 : m_outerIndex[m_outerSize];
+ for(Index i=m_outerSize; i<m_outerSize+outerChange+1; i++)
+ m_outerIndex[i] = last;
+ }
+ m_outerSize += outerChange;
+ }
+
/** Resizes the matrix to a \a rows x \a cols matrix and initializes it to zero.
* \sa resizeNonZeros(Index), reserve(), setZero()
*/
@@ -516,13 +600,15 @@ class SparseMatrix
m_data.clear();
if (m_outerSize != outerSize || m_outerSize==0)
{
- delete[] m_outerIndex;
- m_outerIndex = new Index [outerSize+1];
+ std::free(m_outerIndex);
+ m_outerIndex = static_cast<Index*>(std::malloc((outerSize + 1) * sizeof(Index)));
+ if (!m_outerIndex) internal::throw_std_bad_alloc();
+
m_outerSize = outerSize;
}
if(m_innerNonZeros)
{
- delete[] m_innerNonZeros;
+ std::free(m_innerNonZeros);
m_innerNonZeros = 0;
}
memset(m_outerIndex, 0, (m_outerSize+1)*sizeof(Index));
@@ -560,9 +646,20 @@ class SparseMatrix
inline SparseMatrix(const SparseMatrixBase<OtherDerived>& other)
: m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0)
{
+ EIGEN_STATIC_ASSERT((internal::is_same<Scalar, typename OtherDerived::Scalar>::value),
+ YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
check_template_parameters();
*this = other.derived();
}
+
+ /** Constructs a sparse matrix from the sparse selfadjoint view \a other */
+ template<typename OtherDerived, unsigned int UpLo>
+ inline SparseMatrix(const SparseSelfAdjointView<OtherDerived, UpLo>& other)
+ : m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0)
+ {
+ check_template_parameters();
+ *this = other;
+ }
/** Copy constructor (it performs a deep copy) */
inline SparseMatrix(const SparseMatrix& other)
@@ -572,6 +669,16 @@ class SparseMatrix
*this = other.derived();
}
+ /** \brief Copy constructor with in-place evaluation */
+ template<typename OtherDerived>
+ SparseMatrix(const ReturnByValue<OtherDerived>& other)
+ : Base(), m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0)
+ {
+ check_template_parameters();
+ initAssignment(other);
+ other.evalTo(*this);
+ }
+
/** Swaps the content of two sparse matrices of the same type.
* This is a fast operation that simply swaps the underlying pointers and parameters. */
inline void swap(SparseMatrix& other)
@@ -584,13 +691,22 @@ class SparseMatrix
m_data.swap(other.m_data);
}
+ /** Sets *this to the identity matrix */
+ inline void setIdentity()
+ {
+ eigen_assert(rows() == cols() && "ONLY FOR SQUARED MATRICES");
+ this->m_data.resize(rows());
+ Eigen::Map<Matrix<Index, Dynamic, 1> >(&this->m_data.index(0), rows()).setLinSpaced(0, rows()-1);
+ Eigen::Map<Matrix<Scalar, Dynamic, 1> >(&this->m_data.value(0), rows()).setOnes();
+ Eigen::Map<Matrix<Index, Dynamic, 1> >(this->m_outerIndex, rows()+1).setLinSpaced(0, rows());
+ }
inline SparseMatrix& operator=(const SparseMatrix& other)
{
if (other.isRValue())
{
swap(other.const_cast_derived());
}
- else
+ else if(this!=&other)
{
initAssignment(other);
if(other.isCompressed())
@@ -613,7 +729,10 @@ class SparseMatrix
template<typename OtherDerived>
inline SparseMatrix& operator=(const ReturnByValue<OtherDerived>& other)
- { return Base::operator=(other.derived()); }
+ {
+ initAssignment(other);
+ return Base::operator=(other.derived());
+ }
template<typename OtherDerived>
inline SparseMatrix& operator=(const EigenBase<OtherDerived>& other)
@@ -621,58 +740,7 @@ class SparseMatrix
#endif
template<typename OtherDerived>
- EIGEN_DONT_INLINE SparseMatrix& operator=(const SparseMatrixBase<OtherDerived>& other)
- {
- initAssignment(other.derived());
- const bool needToTranspose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit);
- if (needToTranspose)
- {
- // two passes algorithm:
- // 1 - compute the number of coeffs per dest inner vector
- // 2 - do the actual copy/eval
- // Since each coeff of the rhs has to be evaluated twice, let's evaluate it if needed
- typedef typename internal::nested<OtherDerived,2>::type OtherCopy;
- typedef typename internal::remove_all<OtherCopy>::type _OtherCopy;
- OtherCopy otherCopy(other.derived());
-
- Eigen::Map<Matrix<Index, Dynamic, 1> > (m_outerIndex,outerSize()).setZero();
- // pass 1
- // FIXME the above copy could be merged with that pass
- for (Index j=0; j<otherCopy.outerSize(); ++j)
- for (typename _OtherCopy::InnerIterator it(otherCopy, j); it; ++it)
- ++m_outerIndex[it.index()];
-
- // prefix sum
- Index count = 0;
- VectorXi positions(outerSize());
- for (Index j=0; j<outerSize(); ++j)
- {
- Index tmp = m_outerIndex[j];
- m_outerIndex[j] = count;
- positions[j] = count;
- count += tmp;
- }
- m_outerIndex[outerSize()] = count;
- // alloc
- m_data.resize(count);
- // pass 2
- for (Index j=0; j<otherCopy.outerSize(); ++j)
- {
- for (typename _OtherCopy::InnerIterator it(otherCopy, j); it; ++it)
- {
- Index pos = positions[it.index()]++;
- m_data.index(pos) = j;
- m_data.value(pos) = it.value();
- }
- }
- return *this;
- }
- else
- {
- // there is no special optimization
- return Base::operator=(other.derived());
- }
- }
+ EIGEN_DONT_INLINE SparseMatrix& operator=(const SparseMatrixBase<OtherDerived>& other);
friend std::ostream & operator << (std::ostream & s, const SparseMatrix& m)
{
@@ -684,8 +752,8 @@ class SparseMatrix
else
for (Index i=0; i<m.outerSize(); ++i)
{
- int p = m.m_outerIndex[i];
- int pe = m.m_outerIndex[i]+m.m_innerNonZeros[i];
+ Index p = m.m_outerIndex[i];
+ Index pe = m.m_outerIndex[i]+m.m_innerNonZeros[i];
Index k=p;
for (; k<pe; ++k)
s << "(" << m.m_data.value(k) << "," << m.m_data.index(k) << ") ";
@@ -714,8 +782,8 @@ class SparseMatrix
/** Destructor */
inline ~SparseMatrix()
{
- delete[] m_outerIndex;
- delete[] m_innerNonZeros;
+ std::free(m_outerIndex);
+ std::free(m_innerNonZeros);
}
#ifndef EIGEN_PARSED_BY_DOXYGEN
@@ -735,118 +803,14 @@ protected:
resize(other.rows(), other.cols());
if(m_innerNonZeros)
{
- delete[] m_innerNonZeros;
+ std::free(m_innerNonZeros);
m_innerNonZeros = 0;
}
}
/** \internal
* \sa insert(Index,Index) */
- EIGEN_DONT_INLINE Scalar& insertCompressed(Index row, Index col)
- {
- eigen_assert(isCompressed());
-
- const Index outer = IsRowMajor ? row : col;
- const Index inner = IsRowMajor ? col : row;
-
- Index previousOuter = outer;
- if (m_outerIndex[outer+1]==0)
- {
- // we start a new inner vector
- while (previousOuter>=0 && m_outerIndex[previousOuter]==0)
- {
- m_outerIndex[previousOuter] = static_cast<Index>(m_data.size());
- --previousOuter;
- }
- m_outerIndex[outer+1] = m_outerIndex[outer];
- }
-
- // here we have to handle the tricky case where the outerIndex array
- // starts with: [ 0 0 0 0 0 1 ...] and we are inserted in, e.g.,
- // the 2nd inner vector...
- bool isLastVec = (!(previousOuter==-1 && m_data.size()!=0))
- && (size_t(m_outerIndex[outer+1]) == m_data.size());
-
- size_t startId = m_outerIndex[outer];
- // FIXME let's make sure sizeof(long int) == sizeof(size_t)
- size_t p = m_outerIndex[outer+1];
- ++m_outerIndex[outer+1];
-
- float reallocRatio = 1;
- if (m_data.allocatedSize()<=m_data.size())
- {
- // if there is no preallocated memory, let's reserve a minimum of 32 elements
- if (m_data.size()==0)
- {
- m_data.reserve(32);
- }
- else
- {
- // we need to reallocate the data, to reduce multiple reallocations
- // we use a smart resize algorithm based on the current filling ratio
- // in addition, we use float to avoid integers overflows
- float nnzEstimate = float(m_outerIndex[outer])*float(m_outerSize)/float(outer+1);
- reallocRatio = (nnzEstimate-float(m_data.size()))/float(m_data.size());
- // furthermore we bound the realloc ratio to:
- // 1) reduce multiple minor realloc when the matrix is almost filled
- // 2) avoid to allocate too much memory when the matrix is almost empty
- reallocRatio = (std::min)((std::max)(reallocRatio,1.5f),8.f);
- }
- }
- m_data.resize(m_data.size()+1,reallocRatio);
-
- if (!isLastVec)
- {
- if (previousOuter==-1)
- {
- // oops wrong guess.
- // let's correct the outer offsets
- for (Index k=0; k<=(outer+1); ++k)
- m_outerIndex[k] = 0;
- Index k=outer+1;
- while(m_outerIndex[k]==0)
- m_outerIndex[k++] = 1;
- while (k<=m_outerSize && m_outerIndex[k]!=0)
- m_outerIndex[k++]++;
- p = 0;
- --k;
- k = m_outerIndex[k]-1;
- while (k>0)
- {
- m_data.index(k) = m_data.index(k-1);
- m_data.value(k) = m_data.value(k-1);
- k--;
- }
- }
- else
- {
- // we are not inserting into the last inner vec
- // update outer indices:
- Index j = outer+2;
- while (j<=m_outerSize && m_outerIndex[j]!=0)
- m_outerIndex[j++]++;
- --j;
- // shift data of last vecs:
- Index k = m_outerIndex[j]-1;
- while (k>=Index(p))
- {
- m_data.index(k) = m_data.index(k-1);
- m_data.value(k) = m_data.value(k-1);
- k--;
- }
- }
- }
-
- while ( (p > startId) && (m_data.index(p-1) > inner) )
- {
- m_data.index(p) = m_data.index(p-1);
- m_data.value(p) = m_data.value(p-1);
- --p;
- }
-
- m_data.index(p) = inner;
- return (m_data.value(p) = 0);
- }
+ EIGEN_DONT_INLINE Scalar& insertCompressed(Index row, Index col);
/** \internal
* A vector object that is equal to 0 everywhere but v at the position i */
@@ -865,40 +829,12 @@ protected:
/** \internal
* \sa insert(Index,Index) */
- EIGEN_DONT_INLINE Scalar& insertUncompressed(Index row, Index col)
- {
- eigen_assert(!isCompressed());
-
- const Index outer = IsRowMajor ? row : col;
- const Index inner = IsRowMajor ? col : row;
-
- std::ptrdiff_t room = m_outerIndex[outer+1] - m_outerIndex[outer];
- std::ptrdiff_t innerNNZ = m_innerNonZeros[outer];
- if(innerNNZ>=room)
- {
- // this inner vector is full, we need to reallocate the whole buffer :(
- reserve(SingletonVector(outer,std::max<std::ptrdiff_t>(2,innerNNZ)));
- }
-
- Index startId = m_outerIndex[outer];
- Index p = startId + m_innerNonZeros[outer];
- while ( (p > startId) && (m_data.index(p-1) > inner) )
- {
- m_data.index(p) = m_data.index(p-1);
- m_data.value(p) = m_data.value(p-1);
- --p;
- }
-
- m_innerNonZeros[outer]++;
-
- m_data.index(p) = inner;
- return (m_data.value(p) = 0);
- }
+ EIGEN_DONT_INLINE Scalar& insertUncompressed(Index row, Index col);
public:
/** \internal
* \sa insert(Index,Index) */
- inline Scalar& insertBackUncompressed(Index row, Index col)
+ EIGEN_STRONG_INLINE Scalar& insertBackUncompressed(Index row, Index col)
{
const Index outer = IsRowMajor ? row : col;
const Index inner = IsRowMajor ? col : row;
@@ -906,8 +842,7 @@ public:
eigen_assert(!isCompressed());
eigen_assert(m_innerNonZeros[outer]<=(m_outerIndex[outer+1] - m_outerIndex[outer]));
- Index p = m_outerIndex[outer] + m_innerNonZeros[outer];
- m_innerNonZeros[outer]++;
+ Index p = m_outerIndex[outer] + m_innerNonZeros[outer]++;
m_data.index(p) = inner;
return (m_data.value(p) = 0);
}
@@ -916,10 +851,11 @@ private:
static void check_template_parameters()
{
EIGEN_STATIC_ASSERT(NumTraits<Index>::IsSigned,THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE);
+ EIGEN_STATIC_ASSERT((Options&(ColMajor|RowMajor))==Options,INVALID_MATRIX_TEMPLATE_PARAMETERS);
}
struct default_prunning_func {
- default_prunning_func(Scalar ref, RealScalar eps) : reference(ref), epsilon(eps) {}
+ default_prunning_func(const Scalar& ref, const RealScalar& eps) : reference(ref), epsilon(eps) {}
inline bool operator() (const Index&, const Index&, const Scalar& value) const
{
return !internal::isMuchSmallerThan(value, reference, epsilon);
@@ -1004,21 +940,27 @@ void set_from_triplets(const InputIterator& begin, const InputIterator& end, Spa
enum { IsRowMajor = SparseMatrixType::IsRowMajor };
typedef typename SparseMatrixType::Scalar Scalar;
typedef typename SparseMatrixType::Index Index;
- SparseMatrix<Scalar,IsRowMajor?ColMajor:RowMajor> trMat(mat.rows(),mat.cols());
+ SparseMatrix<Scalar,IsRowMajor?ColMajor:RowMajor,Index> trMat(mat.rows(),mat.cols());
- // pass 1: count the nnz per inner-vector
- VectorXi wi(trMat.outerSize());
- wi.setZero();
- for(InputIterator it(begin); it!=end; ++it)
- wi(IsRowMajor ? it->col() : it->row())++;
+ if(begin!=end)
+ {
+ // pass 1: count the nnz per inner-vector
+ Matrix<Index,Dynamic,1> wi(trMat.outerSize());
+ wi.setZero();
+ for(InputIterator it(begin); it!=end; ++it)
+ {
+ eigen_assert(it->row()>=0 && it->row()<mat.rows() && it->col()>=0 && it->col()<mat.cols());
+ wi(IsRowMajor ? it->col() : it->row())++;
+ }
- // pass 2: insert all the elements into trMat
- trMat.reserve(wi);
- for(InputIterator it(begin); it!=end; ++it)
- trMat.insertBackUncompressed(it->row(),it->col()) = it->value();
+ // pass 2: insert all the elements into trMat
+ trMat.reserve(wi);
+ for(InputIterator it(begin); it!=end; ++it)
+ trMat.insertBackUncompressed(it->row(),it->col()) = it->value();
- // pass 3:
- trMat.sumupDuplicates();
+ // pass 3:
+ trMat.sumupDuplicates();
+ }
// pass 4: transposed copy -> implicit sorting
mat = trMat;
@@ -1027,7 +969,7 @@ void set_from_triplets(const InputIterator& begin, const InputIterator& end, Spa
}
-/** Fill the matrix \c *this with the list of \em triplets defined by the iterator range \a begin - \b.
+/** Fill the matrix \c *this with the list of \em triplets defined by the iterator range \a begin - \a end.
*
* A \em triplet is a tuple (i,j,value) defining a non-zero element.
* The input list of triplets does not have to be sorted, and can contains duplicated elements.
@@ -1077,11 +1019,11 @@ void SparseMatrix<Scalar,_Options,_Index>::sumupDuplicates()
{
eigen_assert(!isCompressed());
// TODO, in practice we should be able to use m_innerNonZeros for that task
- VectorXi wi(innerSize());
+ Matrix<Index,Dynamic,1> wi(innerSize());
wi.fill(-1);
Index count = 0;
// for each inner-vector, wi[inner_index] will hold the position of first element into the index/value buffers
- for(int j=0; j<outerSize(); ++j)
+ for(Index j=0; j<outerSize(); ++j)
{
Index start = count;
Index oldEnd = m_outerIndex[j]+m_innerNonZeros[j];
@@ -1106,11 +1048,212 @@ void SparseMatrix<Scalar,_Options,_Index>::sumupDuplicates()
m_outerIndex[m_outerSize] = count;
// turn the matrix into compressed form
- delete[] m_innerNonZeros;
+ std::free(m_innerNonZeros);
m_innerNonZeros = 0;
m_data.resize(m_outerIndex[m_outerSize]);
}
+template<typename Scalar, int _Options, typename _Index>
+template<typename OtherDerived>
+EIGEN_DONT_INLINE SparseMatrix<Scalar,_Options,_Index>& SparseMatrix<Scalar,_Options,_Index>::operator=(const SparseMatrixBase<OtherDerived>& other)
+{
+ EIGEN_STATIC_ASSERT((internal::is_same<Scalar, typename OtherDerived::Scalar>::value),
+ YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
+
+ const bool needToTranspose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit);
+ if (needToTranspose)
+ {
+ // two passes algorithm:
+ // 1 - compute the number of coeffs per dest inner vector
+ // 2 - do the actual copy/eval
+ // Since each coeff of the rhs has to be evaluated twice, let's evaluate it if needed
+ typedef typename internal::nested<OtherDerived,2>::type OtherCopy;
+ typedef typename internal::remove_all<OtherCopy>::type _OtherCopy;
+ OtherCopy otherCopy(other.derived());
+
+ SparseMatrix dest(other.rows(),other.cols());
+ Eigen::Map<Matrix<Index, Dynamic, 1> > (dest.m_outerIndex,dest.outerSize()).setZero();
+
+ // pass 1
+ // FIXME the above copy could be merged with that pass
+ for (Index j=0; j<otherCopy.outerSize(); ++j)
+ for (typename _OtherCopy::InnerIterator it(otherCopy, j); it; ++it)
+ ++dest.m_outerIndex[it.index()];
+
+ // prefix sum
+ Index count = 0;
+ Matrix<Index,Dynamic,1> positions(dest.outerSize());
+ for (Index j=0; j<dest.outerSize(); ++j)
+ {
+ Index tmp = dest.m_outerIndex[j];
+ dest.m_outerIndex[j] = count;
+ positions[j] = count;
+ count += tmp;
+ }
+ dest.m_outerIndex[dest.outerSize()] = count;
+ // alloc
+ dest.m_data.resize(count);
+ // pass 2
+ for (Index j=0; j<otherCopy.outerSize(); ++j)
+ {
+ for (typename _OtherCopy::InnerIterator it(otherCopy, j); it; ++it)
+ {
+ Index pos = positions[it.index()]++;
+ dest.m_data.index(pos) = j;
+ dest.m_data.value(pos) = it.value();
+ }
+ }
+ this->swap(dest);
+ return *this;
+ }
+ else
+ {
+ if(other.isRValue())
+ initAssignment(other.derived());
+ // there is no special optimization
+ return Base::operator=(other.derived());
+ }
+}
+
+template<typename _Scalar, int _Options, typename _Index>
+EIGEN_DONT_INLINE typename SparseMatrix<_Scalar,_Options,_Index>::Scalar& SparseMatrix<_Scalar,_Options,_Index>::insertUncompressed(Index row, Index col)
+{
+ eigen_assert(!isCompressed());
+
+ const Index outer = IsRowMajor ? row : col;
+ const Index inner = IsRowMajor ? col : row;
+
+ Index room = m_outerIndex[outer+1] - m_outerIndex[outer];
+ Index innerNNZ = m_innerNonZeros[outer];
+ if(innerNNZ>=room)
+ {
+ // this inner vector is full, we need to reallocate the whole buffer :(
+ reserve(SingletonVector(outer,std::max<Index>(2,innerNNZ)));
+ }
+
+ Index startId = m_outerIndex[outer];
+ Index p = startId + m_innerNonZeros[outer];
+ while ( (p > startId) && (m_data.index(p-1) > inner) )
+ {
+ m_data.index(p) = m_data.index(p-1);
+ m_data.value(p) = m_data.value(p-1);
+ --p;
+ }
+ eigen_assert((p<=startId || m_data.index(p-1)!=inner) && "you cannot insert an element that already exist, you must call coeffRef to this end");
+
+ m_innerNonZeros[outer]++;
+
+ m_data.index(p) = inner;
+ return (m_data.value(p) = 0);
+}
+
+template<typename _Scalar, int _Options, typename _Index>
+EIGEN_DONT_INLINE typename SparseMatrix<_Scalar,_Options,_Index>::Scalar& SparseMatrix<_Scalar,_Options,_Index>::insertCompressed(Index row, Index col)
+{
+ eigen_assert(isCompressed());
+
+ const Index outer = IsRowMajor ? row : col;
+ const Index inner = IsRowMajor ? col : row;
+
+ Index previousOuter = outer;
+ if (m_outerIndex[outer+1]==0)
+ {
+ // we start a new inner vector
+ while (previousOuter>=0 && m_outerIndex[previousOuter]==0)
+ {
+ m_outerIndex[previousOuter] = static_cast<Index>(m_data.size());
+ --previousOuter;
+ }
+ m_outerIndex[outer+1] = m_outerIndex[outer];
+ }
+
+ // here we have to handle the tricky case where the outerIndex array
+ // starts with: [ 0 0 0 0 0 1 ...] and we are inserted in, e.g.,
+ // the 2nd inner vector...
+ bool isLastVec = (!(previousOuter==-1 && m_data.size()!=0))
+ && (size_t(m_outerIndex[outer+1]) == m_data.size());
+
+ size_t startId = m_outerIndex[outer];
+ // FIXME let's make sure sizeof(long int) == sizeof(size_t)
+ size_t p = m_outerIndex[outer+1];
+ ++m_outerIndex[outer+1];
+
+ double reallocRatio = 1;
+ if (m_data.allocatedSize()<=m_data.size())
+ {
+ // if there is no preallocated memory, let's reserve a minimum of 32 elements
+ if (m_data.size()==0)
+ {
+ m_data.reserve(32);
+ }
+ else
+ {
+ // we need to reallocate the data, to reduce multiple reallocations
+ // we use a smart resize algorithm based on the current filling ratio
+ // in addition, we use double to avoid integers overflows
+ double nnzEstimate = double(m_outerIndex[outer])*double(m_outerSize)/double(outer+1);
+ reallocRatio = (nnzEstimate-double(m_data.size()))/double(m_data.size());
+ // furthermore we bound the realloc ratio to:
+ // 1) reduce multiple minor realloc when the matrix is almost filled
+ // 2) avoid to allocate too much memory when the matrix is almost empty
+ reallocRatio = (std::min)((std::max)(reallocRatio,1.5),8.);
+ }
+ }
+ m_data.resize(m_data.size()+1,reallocRatio);
+
+ if (!isLastVec)
+ {
+ if (previousOuter==-1)
+ {
+ // oops wrong guess.
+ // let's correct the outer offsets
+ for (Index k=0; k<=(outer+1); ++k)
+ m_outerIndex[k] = 0;
+ Index k=outer+1;
+ while(m_outerIndex[k]==0)
+ m_outerIndex[k++] = 1;
+ while (k<=m_outerSize && m_outerIndex[k]!=0)
+ m_outerIndex[k++]++;
+ p = 0;
+ --k;
+ k = m_outerIndex[k]-1;
+ while (k>0)
+ {
+ m_data.index(k) = m_data.index(k-1);
+ m_data.value(k) = m_data.value(k-1);
+ k--;
+ }
+ }
+ else
+ {
+ // we are not inserting into the last inner vec
+ // update outer indices:
+ Index j = outer+2;
+ while (j<=m_outerSize && m_outerIndex[j]!=0)
+ m_outerIndex[j++]++;
+ --j;
+ // shift data of last vecs:
+ Index k = m_outerIndex[j]-1;
+ while (k>=Index(p))
+ {
+ m_data.index(k) = m_data.index(k-1);
+ m_data.value(k) = m_data.value(k-1);
+ k--;
+ }
+ }
+ }
+
+ while ( (p > startId) && (m_data.index(p-1) > inner) )
+ {
+ m_data.index(p) = m_data.index(p-1);
+ m_data.value(p) = m_data.value(p-1);
+ --p;
+ }
+
+ m_data.index(p) = inner;
+ return (m_data.value(p) = 0);
+}
+
} // end namespace Eigen
#endif // EIGEN_SPARSEMATRIX_H
diff --git a/Eigen/src/SparseCore/SparseMatrixBase.h b/Eigen/src/SparseCore/SparseMatrixBase.h
index 9a1258097..bbcf7fb1c 100644
--- a/Eigen/src/SparseCore/SparseMatrixBase.h
+++ b/Eigen/src/SparseCore/SparseMatrixBase.h
@@ -89,6 +89,9 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
*/
IsRowMajor = Flags&RowMajorBit ? 1 : 0,
+
+ InnerSizeAtCompileTime = int(IsVectorAtCompileTime) ? int(SizeAtCompileTime)
+ : int(IsRowMajor) ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
#ifndef EIGEN_PARSED_BY_DOXYGEN
_HasDirectAccess = (int(Flags)&DirectAccessBit) ? 1 : 0 // workaround sunCC
@@ -102,7 +105,7 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
>::type AdjointReturnType;
- typedef SparseMatrix<Scalar, Flags&RowMajorBit ? RowMajor : ColMajor> PlainObject;
+ typedef SparseMatrix<Scalar, Flags&RowMajorBit ? RowMajor : ColMajor, Index> PlainObject;
#ifndef EIGEN_PARSED_BY_DOXYGEN
@@ -136,13 +139,13 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
# include "../plugins/CommonCwiseBinaryOps.h"
# include "../plugins/MatrixCwiseUnaryOps.h"
# include "../plugins/MatrixCwiseBinaryOps.h"
+# include "../plugins/BlockMethods.h"
# ifdef EIGEN_SPARSEMATRIXBASE_PLUGIN
# include EIGEN_SPARSEMATRIXBASE_PLUGIN
# endif
# undef EIGEN_CURRENT_STORAGE_BASE_CLASS
#undef EIGEN_CURRENT_STORAGE_BASE_CLASS
-
/** \returns the number of rows. \sa cols() */
inline Index rows() const { return derived().rows(); }
/** \returns the number of columns. \sa rows() */
@@ -299,8 +302,8 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
}
else
{
- SparseMatrix<Scalar, RowMajorBit> trans = m;
- s << static_cast<const SparseMatrixBase<SparseMatrix<Scalar, RowMajorBit> >&>(trans);
+ SparseMatrix<Scalar, RowMajorBit, Index> trans = m;
+ s << static_cast<const SparseMatrixBase<SparseMatrix<Scalar, RowMajorBit, Index> >&>(trans);
}
}
return s;
@@ -322,8 +325,8 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
typename internal::traits<OtherDerived>::Scalar \
>::ReturnType \
>, \
- Derived, \
- OtherDerived \
+ const Derived, \
+ const OtherDerived \
>
template<typename OtherDerived>
@@ -387,55 +390,45 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
template<typename OtherDerived> Scalar dot(const SparseMatrixBase<OtherDerived>& other) const;
RealScalar squaredNorm() const;
RealScalar norm() const;
+ RealScalar blueNorm() const;
Transpose<Derived> transpose() { return derived(); }
const Transpose<const Derived> transpose() const { return derived(); }
const AdjointReturnType adjoint() const { return transpose(); }
- // sub-vector
- SparseInnerVectorSet<Derived,1> row(Index i);
- const SparseInnerVectorSet<Derived,1> row(Index i) const;
- SparseInnerVectorSet<Derived,1> col(Index j);
- const SparseInnerVectorSet<Derived,1> col(Index j) const;
- SparseInnerVectorSet<Derived,1> innerVector(Index outer);
- const SparseInnerVectorSet<Derived,1> innerVector(Index outer) const;
-
- // set of sub-vectors
- SparseInnerVectorSet<Derived,Dynamic> subrows(Index start, Index size);
- const SparseInnerVectorSet<Derived,Dynamic> subrows(Index start, Index size) const;
- SparseInnerVectorSet<Derived,Dynamic> subcols(Index start, Index size);
- const SparseInnerVectorSet<Derived,Dynamic> subcols(Index start, Index size) const;
-
- SparseInnerVectorSet<Derived,Dynamic> middleRows(Index start, Index size);
- const SparseInnerVectorSet<Derived,Dynamic> middleRows(Index start, Index size) const;
- SparseInnerVectorSet<Derived,Dynamic> middleCols(Index start, Index size);
- const SparseInnerVectorSet<Derived,Dynamic> middleCols(Index start, Index size) const;
- SparseInnerVectorSet<Derived,Dynamic> innerVectors(Index outerStart, Index outerSize);
- const SparseInnerVectorSet<Derived,Dynamic> innerVectors(Index outerStart, Index outerSize) const;
-
- /** \internal use operator= */
- template<typename DenseDerived>
- void evalTo(MatrixBase<DenseDerived>& dst) const
- {
- dst.setZero();
- for (Index j=0; j<outerSize(); ++j)
- for (typename Derived::InnerIterator i(derived(),j); i; ++i)
- dst.coeffRef(i.row(),i.col()) = i.value();
- }
+ // inner-vector
+ typedef Block<Derived,IsRowMajor?1:Dynamic,IsRowMajor?Dynamic:1,true> InnerVectorReturnType;
+ typedef Block<const Derived,IsRowMajor?1:Dynamic,IsRowMajor?Dynamic:1,true> ConstInnerVectorReturnType;
+ InnerVectorReturnType innerVector(Index outer);
+ const ConstInnerVectorReturnType innerVector(Index outer) const;
- Matrix<Scalar,RowsAtCompileTime,ColsAtCompileTime> toDense() const
- {
- return derived();
- }
+ // set of inner-vectors
+ Block<Derived,Dynamic,Dynamic,true> innerVectors(Index outerStart, Index outerSize);
+ const Block<const Derived,Dynamic,Dynamic,true> innerVectors(Index outerStart, Index outerSize) const;
+
+ /** \internal use operator= */
+ template<typename DenseDerived>
+ void evalTo(MatrixBase<DenseDerived>& dst) const
+ {
+ dst.setZero();
+ for (Index j=0; j<outerSize(); ++j)
+ for (typename Derived::InnerIterator i(derived(),j); i; ++i)
+ dst.coeffRef(i.row(),i.col()) = i.value();
+ }
+
+ Matrix<Scalar,RowsAtCompileTime,ColsAtCompileTime> toDense() const
+ {
+ return derived();
+ }
template<typename OtherDerived>
bool isApprox(const SparseMatrixBase<OtherDerived>& other,
- RealScalar prec = NumTraits<Scalar>::dummy_precision()) const
+ const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const
{ return toDense().isApprox(other.toDense(),prec); }
template<typename OtherDerived>
bool isApprox(const MatrixBase<OtherDerived>& other,
- RealScalar prec = NumTraits<Scalar>::dummy_precision()) const
+ const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const
{ return toDense().isApprox(other,prec); }
/** \returns the matrix or vector obtained by evaluating this expression.
diff --git a/Eigen/src/SparseCore/SparsePermutation.h b/Eigen/src/SparseCore/SparsePermutation.h
index b897b7595..b85be93f6 100644
--- a/Eigen/src/SparseCore/SparsePermutation.h
+++ b/Eigen/src/SparseCore/SparsePermutation.h
@@ -57,7 +57,7 @@ struct permut_sparsematrix_product_retval
if(MoveOuter)
{
SparseMatrix<Scalar,SrcStorageOrder,Index> tmp(m_matrix.rows(), m_matrix.cols());
- VectorXi sizes(m_matrix.outerSize());
+ Matrix<Index,Dynamic,1> sizes(m_matrix.outerSize());
for(Index j=0; j<m_matrix.outerSize(); ++j)
{
Index jp = m_permutation.indices().coeff(j);
@@ -77,7 +77,7 @@ struct permut_sparsematrix_product_retval
else
{
SparseMatrix<Scalar,int(SrcStorageOrder)==RowMajor?ColMajor:RowMajor,Index> tmp(m_matrix.rows(), m_matrix.cols());
- VectorXi sizes(tmp.outerSize());
+ Matrix<Index,Dynamic,1> sizes(tmp.outerSize());
sizes.setZero();
PermutationMatrix<Dynamic,Dynamic,Index> perm;
if((Side==OnTheLeft) ^ Transposed)
diff --git a/Eigen/src/SparseCore/SparseProduct.h b/Eigen/src/SparseCore/SparseProduct.h
index 6a555b834..cf7663070 100644
--- a/Eigen/src/SparseCore/SparseProduct.h
+++ b/Eigen/src/SparseCore/SparseProduct.h
@@ -16,6 +16,7 @@ template<typename Lhs, typename Rhs>
struct SparseSparseProductReturnType
{
typedef typename internal::traits<Lhs>::Scalar Scalar;
+ typedef typename internal::traits<Lhs>::Index Index;
enum {
LhsRowMajor = internal::traits<Lhs>::Flags & RowMajorBit,
RhsRowMajor = internal::traits<Rhs>::Flags & RowMajorBit,
@@ -24,11 +25,11 @@ struct SparseSparseProductReturnType
};
typedef typename internal::conditional<TransposeLhs,
- SparseMatrix<Scalar,0>,
+ SparseMatrix<Scalar,0,Index>,
typename internal::nested<Lhs,Rhs::RowsAtCompileTime>::type>::type LhsNested;
typedef typename internal::conditional<TransposeRhs,
- SparseMatrix<Scalar,0>,
+ SparseMatrix<Scalar,0,Index>,
typename internal::nested<Rhs,Lhs::RowsAtCompileTime>::type>::type RhsNested;
typedef SparseSparseProduct<LhsNested, RhsNested> Type;
@@ -99,15 +100,16 @@ class SparseSparseProduct : internal::no_assignment_operator,
}
template<typename Lhs, typename Rhs>
- EIGEN_STRONG_INLINE SparseSparseProduct(const Lhs& lhs, const Rhs& rhs, RealScalar tolerance)
+ EIGEN_STRONG_INLINE SparseSparseProduct(const Lhs& lhs, const Rhs& rhs, const RealScalar& tolerance)
: m_lhs(lhs), m_rhs(rhs), m_tolerance(tolerance), m_conservative(false)
{
init();
}
- SparseSparseProduct pruned(Scalar reference = 0, RealScalar epsilon = NumTraits<RealScalar>::dummy_precision()) const
+ SparseSparseProduct pruned(const Scalar& reference = 0, const RealScalar& epsilon = NumTraits<RealScalar>::dummy_precision()) const
{
- return SparseSparseProduct(m_lhs,m_rhs,internal::abs(reference)*epsilon);
+ using std::abs;
+ return SparseSparseProduct(m_lhs,m_rhs,abs(reference)*epsilon);
}
template<typename Dest>
diff --git a/Eigen/src/SparseCore/SparseSelfAdjointView.h b/Eigen/src/SparseCore/SparseSelfAdjointView.h
index 86ec0a6c5..0eda96bc4 100644
--- a/Eigen/src/SparseCore/SparseSelfAdjointView.h
+++ b/Eigen/src/SparseCore/SparseSelfAdjointView.h
@@ -69,6 +69,30 @@ template<typename MatrixType, unsigned int UpLo> class SparseSelfAdjointView
const _MatrixTypeNested& matrix() const { return m_matrix; }
_MatrixTypeNested& matrix() { return m_matrix.const_cast_derived(); }
+ /** \returns an expression of the matrix product between a sparse self-adjoint matrix \c *this and a sparse matrix \a rhs.
+ *
+ * Note that there is no algorithmic advantage of performing such a product compared to a general sparse-sparse matrix product.
+ * Indeed, the SparseSelfadjointView operand is first copied into a temporary SparseMatrix before computing the product.
+ */
+ template<typename OtherDerived>
+ SparseSparseProduct<typename OtherDerived::PlainObject, OtherDerived>
+ operator*(const SparseMatrixBase<OtherDerived>& rhs) const
+ {
+ return SparseSparseProduct<typename OtherDerived::PlainObject, OtherDerived>(*this, rhs.derived());
+ }
+
+ /** \returns an expression of the matrix product between a sparse matrix \a lhs and a sparse self-adjoint matrix \a rhs.
+ *
+ * Note that there is no algorithmic advantage of performing such a product compared to a general sparse-sparse matrix product.
+ * Indeed, the SparseSelfadjointView operand is first copied into a temporary SparseMatrix before computing the product.
+ */
+ template<typename OtherDerived> friend
+ SparseSparseProduct<OtherDerived, typename OtherDerived::PlainObject >
+ operator*(const SparseMatrixBase<OtherDerived>& lhs, const SparseSelfAdjointView& rhs)
+ {
+ return SparseSparseProduct<OtherDerived, typename OtherDerived::PlainObject>(lhs.derived(), rhs);
+ }
+
/** Efficient sparse self-adjoint matrix times dense vector/matrix product */
template<typename OtherDerived>
SparseSelfAdjointTimeDenseProduct<MatrixType,OtherDerived,UpLo>
@@ -94,7 +118,7 @@ template<typename MatrixType, unsigned int UpLo> class SparseSelfAdjointView
* call this function with u.adjoint().
*/
template<typename DerivedU>
- SparseSelfAdjointView& rankUpdate(const SparseMatrixBase<DerivedU>& u, Scalar alpha = Scalar(1));
+ SparseSelfAdjointView& rankUpdate(const SparseMatrixBase<DerivedU>& u, const Scalar& alpha = Scalar(1));
/** \internal triggered by sparse_matrix = SparseSelfadjointView; */
template<typename DestScalar,int StorageOrder> void evalTo(SparseMatrix<DestScalar,StorageOrder,Index>& _dest) const
@@ -173,7 +197,7 @@ SparseSelfAdjointView<Derived, UpLo> SparseMatrixBase<Derived>::selfadjointView(
template<typename MatrixType, unsigned int UpLo>
template<typename DerivedU>
SparseSelfAdjointView<MatrixType,UpLo>&
-SparseSelfAdjointView<MatrixType,UpLo>::rankUpdate(const SparseMatrixBase<DerivedU>& u, Scalar alpha)
+SparseSelfAdjointView<MatrixType,UpLo>::rankUpdate(const SparseMatrixBase<DerivedU>& u, const Scalar& alpha)
{
SparseMatrix<Scalar,MatrixType::Flags&RowMajorBit?RowMajor:ColMajor> tmp = u * u.adjoint();
if(alpha==Scalar(0))
@@ -207,12 +231,12 @@ class SparseSelfAdjointTimeDenseProduct
SparseSelfAdjointTimeDenseProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
{}
- template<typename Dest> void scaleAndAddTo(Dest& dest, Scalar alpha) const
+ template<typename Dest> void scaleAndAddTo(Dest& dest, const Scalar& alpha) const
{
+ EIGEN_ONLY_USED_FOR_DEBUG(alpha);
// TODO use alpha
eigen_assert(alpha==Scalar(1) && "alpha != 1 is not implemented yet, sorry");
typedef typename internal::remove_all<Lhs>::type _Lhs;
- typedef typename internal::remove_all<Rhs>::type _Rhs;
typedef typename _Lhs::InnerIterator LhsInnerIterator;
enum {
LhsIsRowMajor = (_Lhs::Flags&RowMajorBit)==RowMajorBit,
@@ -240,7 +264,7 @@ class SparseSelfAdjointTimeDenseProduct
Index b = LhsIsRowMajor ? i.index() : j;
typename Lhs::Scalar v = i.value();
dest.row(a) += (v) * m_rhs.row(b);
- dest.row(b) += internal::conj(v) * m_rhs.row(a);
+ dest.row(b) += numext::conj(v) * m_rhs.row(a);
}
if (ProcessFirstHalf && i && (i.index()==j))
dest.row(j) += i.value() * m_rhs.row(j);
@@ -268,7 +292,7 @@ class DenseTimeSparseSelfAdjointProduct
DenseTimeSparseSelfAdjointProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
{}
- template<typename Dest> void scaleAndAddTo(Dest& /*dest*/, Scalar /*alpha*/) const
+ template<typename Dest> void scaleAndAddTo(Dest& /*dest*/, const Scalar& /*alpha*/) const
{
// TODO
}
@@ -367,7 +391,7 @@ void permute_symm_to_fullsymm(const MatrixType& mat, SparseMatrix<typename Matri
dest.valuePtr()[k] = it.value();
k = count[ip]++;
dest.innerIndexPtr()[k] = jp;
- dest.valuePtr()[k] = internal::conj(it.value());
+ dest.valuePtr()[k] = numext::conj(it.value());
}
}
}
@@ -428,7 +452,7 @@ void permute_symm_to_symm(const MatrixType& mat, SparseMatrix<typename MatrixTyp
if(!StorageOrderMatch) std::swap(ip,jp);
if( ((int(DstUpLo)==int(Lower) && ip<jp) || (int(DstUpLo)==int(Upper) && ip>jp)))
- dest.valuePtr()[k] = conj(it.value());
+ dest.valuePtr()[k] = numext::conj(it.value());
else
dest.valuePtr()[k] = it.value();
}
@@ -461,7 +485,10 @@ class SparseSymmetricPermutationProduct
template<typename DestScalar, int Options, typename DstIndex>
void evalTo(SparseMatrix<DestScalar,Options,DstIndex>& _dest) const
{
- internal::permute_symm_to_fullsymm<UpLo>(m_matrix,_dest,m_perm.indices().data());
+// internal::permute_symm_to_fullsymm<UpLo>(m_matrix,_dest,m_perm.indices().data());
+ SparseMatrix<DestScalar,(Options&RowMajor)==RowMajor ? ColMajor : RowMajor, DstIndex> tmp;
+ internal::permute_symm_to_fullsymm<UpLo>(m_matrix,tmp,m_perm.indices().data());
+ _dest = tmp;
}
template<typename DestType,unsigned int DestUpLo> void evalTo(SparseSelfAdjointView<DestType,DestUpLo>& dest) const
diff --git a/Eigen/src/SparseCore/SparseSparseProductWithPruning.h b/Eigen/src/SparseCore/SparseSparseProductWithPruning.h
index 2438ac573..fcc18f5c9 100644
--- a/Eigen/src/SparseCore/SparseSparseProductWithPruning.h
+++ b/Eigen/src/SparseCore/SparseSparseProductWithPruning.h
@@ -17,7 +17,7 @@ namespace internal {
// perform a pseudo in-place sparse * sparse product assuming all matrices are col major
template<typename Lhs, typename Rhs, typename ResultType>
-static void sparse_sparse_product_with_pruning_impl(const Lhs& lhs, const Rhs& rhs, ResultType& res, typename ResultType::RealScalar tolerance)
+static void sparse_sparse_product_with_pruning_impl(const Lhs& lhs, const Rhs& rhs, ResultType& res, const typename ResultType::RealScalar& tolerance)
{
// return sparse_sparse_product_with_pruning_impl2(lhs,rhs,res);
@@ -27,7 +27,7 @@ static void sparse_sparse_product_with_pruning_impl(const Lhs& lhs, const Rhs& r
// make sure to call innerSize/outerSize since we fake the storage order.
Index rows = lhs.innerSize();
Index cols = rhs.outerSize();
- //int size = lhs.outerSize();
+ //Index size = lhs.outerSize();
eigen_assert(lhs.outerSize() == rhs.innerSize());
// allocate a temporary buffer
@@ -85,7 +85,7 @@ struct sparse_sparse_product_with_pruning_selector<Lhs,Rhs,ResultType,ColMajor,C
typedef typename traits<typename remove_all<Lhs>::type>::Scalar Scalar;
typedef typename ResultType::RealScalar RealScalar;
- static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, RealScalar tolerance)
+ static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, const RealScalar& tolerance)
{
typename remove_all<ResultType>::type _res(res.rows(), res.cols());
internal::sparse_sparse_product_with_pruning_impl<Lhs,Rhs,ResultType>(lhs, rhs, _res, tolerance);
@@ -97,10 +97,10 @@ template<typename Lhs, typename Rhs, typename ResultType>
struct sparse_sparse_product_with_pruning_selector<Lhs,Rhs,ResultType,ColMajor,ColMajor,RowMajor>
{
typedef typename ResultType::RealScalar RealScalar;
- static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, RealScalar tolerance)
+ static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, const RealScalar& tolerance)
{
// we need a col-major matrix to hold the result
- typedef SparseMatrix<typename ResultType::Scalar> SparseTemporaryType;
+ typedef SparseMatrix<typename ResultType::Scalar,ColMajor,typename ResultType::Index> SparseTemporaryType;
SparseTemporaryType _res(res.rows(), res.cols());
internal::sparse_sparse_product_with_pruning_impl<Lhs,Rhs,SparseTemporaryType>(lhs, rhs, _res, tolerance);
res = _res;
@@ -111,7 +111,7 @@ template<typename Lhs, typename Rhs, typename ResultType>
struct sparse_sparse_product_with_pruning_selector<Lhs,Rhs,ResultType,RowMajor,RowMajor,RowMajor>
{
typedef typename ResultType::RealScalar RealScalar;
- static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, RealScalar tolerance)
+ static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, const RealScalar& tolerance)
{
// let's transpose the product to get a column x column product
typename remove_all<ResultType>::type _res(res.rows(), res.cols());
@@ -124,12 +124,13 @@ template<typename Lhs, typename Rhs, typename ResultType>
struct sparse_sparse_product_with_pruning_selector<Lhs,Rhs,ResultType,RowMajor,RowMajor,ColMajor>
{
typedef typename ResultType::RealScalar RealScalar;
- static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, RealScalar tolerance)
+ static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, const RealScalar& tolerance)
{
- typedef SparseMatrix<typename ResultType::Scalar,ColMajor> ColMajorMatrix;
- ColMajorMatrix colLhs(lhs);
- ColMajorMatrix colRhs(rhs);
- internal::sparse_sparse_product_with_pruning_impl<ColMajorMatrix,ColMajorMatrix,ResultType>(colLhs, colRhs, res, tolerance);
+ typedef SparseMatrix<typename ResultType::Scalar,ColMajor,typename Lhs::Index> ColMajorMatrixLhs;
+ typedef SparseMatrix<typename ResultType::Scalar,ColMajor,typename Lhs::Index> ColMajorMatrixRhs;
+ ColMajorMatrixLhs colLhs(lhs);
+ ColMajorMatrixRhs colRhs(rhs);
+ internal::sparse_sparse_product_with_pruning_impl<ColMajorMatrixLhs,ColMajorMatrixRhs,ResultType>(colLhs, colRhs, res, tolerance);
// let's transpose the product to get a column x column product
// typedef SparseMatrix<typename ResultType::Scalar> SparseTemporaryType;
diff --git a/Eigen/src/SparseCore/SparseTranspose.h b/Eigen/src/SparseCore/SparseTranspose.h
index 273f9de68..76d031d52 100644
--- a/Eigen/src/SparseCore/SparseTranspose.h
+++ b/Eigen/src/SparseCore/SparseTranspose.h
@@ -18,7 +18,7 @@ template<typename MatrixType> class TransposeImpl<MatrixType,Sparse>
typedef typename internal::remove_all<typename MatrixType::Nested>::type _MatrixTypeNested;
public:
- EIGEN_SPARSE_PUBLIC_INTERFACE(Transpose<MatrixType>)
+ EIGEN_SPARSE_PUBLIC_INTERFACE(Transpose<MatrixType> )
class InnerIterator;
class ReverseInnerIterator;
@@ -26,7 +26,7 @@ template<typename MatrixType> class TransposeImpl<MatrixType,Sparse>
inline Index nonZeros() const { return derived().nestedExpression().nonZeros(); }
};
-// NOTE: VC10 trigger an ICE if don't put typename TransposeImpl<MatrixType,Sparse>:: in front of Index,
+// NOTE: VC10 and VC11 trigger an ICE if don't put typename TransposeImpl<MatrixType,Sparse>:: in front of Index,
// a typedef typename TransposeImpl<MatrixType,Sparse>::Index Index;
// does not fix the issue.
// An alternative is to define the nested class in the parent class itself.
@@ -34,26 +34,28 @@ template<typename MatrixType> class TransposeImpl<MatrixType,Sparse>::InnerItera
: public _MatrixTypeNested::InnerIterator
{
typedef typename _MatrixTypeNested::InnerIterator Base;
+ typedef typename TransposeImpl::Index Index;
public:
EIGEN_STRONG_INLINE InnerIterator(const TransposeImpl& trans, typename TransposeImpl<MatrixType,Sparse>::Index outer)
: Base(trans.derived().nestedExpression(), outer)
{}
- inline typename TransposeImpl<MatrixType,Sparse>::Index row() const { return Base::col(); }
- inline typename TransposeImpl<MatrixType,Sparse>::Index col() const { return Base::row(); }
+ typename TransposeImpl<MatrixType,Sparse>::Index row() const { return Base::col(); }
+ typename TransposeImpl<MatrixType,Sparse>::Index col() const { return Base::row(); }
};
template<typename MatrixType> class TransposeImpl<MatrixType,Sparse>::ReverseInnerIterator
: public _MatrixTypeNested::ReverseInnerIterator
{
typedef typename _MatrixTypeNested::ReverseInnerIterator Base;
+ typedef typename TransposeImpl::Index Index;
public:
EIGEN_STRONG_INLINE ReverseInnerIterator(const TransposeImpl& xpr, typename TransposeImpl<MatrixType,Sparse>::Index outer)
: Base(xpr.derived().nestedExpression(), outer)
{}
- inline typename TransposeImpl<MatrixType,Sparse>::Index row() const { return Base::col(); }
- inline typename TransposeImpl<MatrixType,Sparse>::Index col() const { return Base::row(); }
+ typename TransposeImpl<MatrixType,Sparse>::Index row() const { return Base::col(); }
+ typename TransposeImpl<MatrixType,Sparse>::Index col() const { return Base::row(); }
};
} // end namespace Eigen
diff --git a/Eigen/src/SparseCore/SparseTriangularView.h b/Eigen/src/SparseCore/SparseTriangularView.h
index 477e4bd94..333127b78 100644
--- a/Eigen/src/SparseCore/SparseTriangularView.h
+++ b/Eigen/src/SparseCore/SparseTriangularView.h
@@ -2,6 +2,7 @@
// for linear algebra.
//
// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
@@ -27,6 +28,7 @@ template<typename MatrixType, int Mode> class SparseTriangularView
enum { SkipFirst = ((Mode&Lower) && !(MatrixType::Flags&RowMajorBit))
|| ((Mode&Upper) && (MatrixType::Flags&RowMajorBit)),
SkipLast = !SkipFirst,
+ SkipDiag = (Mode&ZeroDiag) ? 1 : 0,
HasUnitDiag = (Mode&UnitDiag) ? 1 : 0
};
@@ -64,6 +66,7 @@ template<typename MatrixType, int Mode>
class SparseTriangularView<MatrixType,Mode>::InnerIterator : public MatrixTypeNestedCleaned::InnerIterator
{
typedef typename MatrixTypeNestedCleaned::InnerIterator Base;
+ typedef typename SparseTriangularView::Index Index;
public:
EIGEN_STRONG_INLINE InnerIterator(const SparseTriangularView& view, Index outer)
@@ -71,7 +74,7 @@ class SparseTriangularView<MatrixType,Mode>::InnerIterator : public MatrixTypeNe
{
if(SkipFirst)
{
- while((*this) && (HasUnitDiag ? this->index()<=outer : this->index()<outer))
+ while((*this) && ((HasUnitDiag||SkipDiag) ? this->index()<=outer : this->index()<outer))
Base::operator++();
if(HasUnitDiag)
m_returnOne = true;
@@ -101,8 +104,8 @@ class SparseTriangularView<MatrixType,Mode>::InnerIterator : public MatrixTypeNe
return *this;
}
- inline Index row() const { return Base::row(); }
- inline Index col() const { return Base::col(); }
+ inline Index row() const { return (MatrixType::Flags&RowMajorBit ? Base::outer() : this->index()); }
+ inline Index col() const { return (MatrixType::Flags&RowMajorBit ? this->index() : Base::outer()); }
inline Index index() const
{
if(HasUnitDiag && m_returnOne) return Base::outer();
@@ -118,7 +121,12 @@ class SparseTriangularView<MatrixType,Mode>::InnerIterator : public MatrixTypeNe
{
if(HasUnitDiag && m_returnOne)
return true;
- return (SkipFirst ? Base::operator bool() : (Base::operator bool() && this->index() <= this->outer()));
+ if(SkipFirst) return Base::operator bool();
+ else
+ {
+ if (SkipDiag) return (Base::operator bool() && this->index() < this->outer());
+ else return (Base::operator bool() && this->index() <= this->outer());
+ }
}
protected:
bool m_returnOne;
@@ -128,18 +136,20 @@ template<typename MatrixType, int Mode>
class SparseTriangularView<MatrixType,Mode>::ReverseInnerIterator : public MatrixTypeNestedCleaned::ReverseInnerIterator
{
typedef typename MatrixTypeNestedCleaned::ReverseInnerIterator Base;
+ typedef typename SparseTriangularView::Index Index;
public:
EIGEN_STRONG_INLINE ReverseInnerIterator(const SparseTriangularView& view, Index outer)
: Base(view.nestedExpression(), outer)
{
eigen_assert((!HasUnitDiag) && "ReverseInnerIterator does not support yet triangular views with a unit diagonal");
- if(SkipLast)
- while((*this) && this->index()>outer)
+ if(SkipLast) {
+ while((*this) && (SkipDiag ? this->index()>=outer : this->index()>outer))
--(*this);
+ }
}
- EIGEN_STRONG_INLINE InnerIterator& operator--()
+ EIGEN_STRONG_INLINE ReverseInnerIterator& operator--()
{ Base::operator--(); return *this; }
inline Index row() const { return Base::row(); }
@@ -147,7 +157,12 @@ class SparseTriangularView<MatrixType,Mode>::ReverseInnerIterator : public Matri
EIGEN_STRONG_INLINE operator bool() const
{
- return SkipLast ? Base::operator bool() : (Base::operator bool() && this->index() >= this->outer());
+ if (SkipLast) return Base::operator bool() ;
+ else
+ {
+ if(SkipDiag) return (Base::operator bool() && this->index() > this->outer());
+ else return (Base::operator bool() && this->index() >= this->outer());
+ }
}
};
diff --git a/Eigen/src/SparseCore/SparseUtil.h b/Eigen/src/SparseCore/SparseUtil.h
index 6062a086f..0ba471320 100644
--- a/Eigen/src/SparseCore/SparseUtil.h
+++ b/Eigen/src/SparseCore/SparseUtil.h
@@ -73,7 +73,6 @@ template<typename _Scalar, int _Flags = 0, typename _Index = int> class Dynamic
template<typename _Scalar, int _Flags = 0, typename _Index = int> class SparseVector;
template<typename _Scalar, int _Flags = 0, typename _Index = int> class MappedSparseMatrix;
-template<typename MatrixType, int Size> class SparseInnerVectorSet;
template<typename MatrixType, int Mode> class SparseTriangularView;
template<typename MatrixType, unsigned int UpLo> class SparseSelfAdjointView;
template<typename Lhs, typename Rhs> class SparseDiagonalProduct;
@@ -85,8 +84,10 @@ template<typename Lhs, typename Rhs> class DenseTimeSparseProduct;
template<typename Lhs, typename Rhs, bool Transpose> class SparseDenseOuterProduct;
template<typename Lhs, typename Rhs> struct SparseSparseProductReturnType;
-template<typename Lhs, typename Rhs, int InnerSize = internal::traits<Lhs>::ColsAtCompileTime> struct DenseSparseProductReturnType;
-template<typename Lhs, typename Rhs, int InnerSize = internal::traits<Lhs>::ColsAtCompileTime> struct SparseDenseProductReturnType;
+template<typename Lhs, typename Rhs,
+ int InnerSize = EIGEN_SIZE_MIN_PREFER_FIXED(internal::traits<Lhs>::ColsAtCompileTime,internal::traits<Rhs>::RowsAtCompileTime)> struct DenseSparseProductReturnType;
+template<typename Lhs, typename Rhs,
+ int InnerSize = EIGEN_SIZE_MIN_PREFER_FIXED(internal::traits<Lhs>::ColsAtCompileTime,internal::traits<Rhs>::RowsAtCompileTime)> struct SparseDenseProductReturnType;
template<typename MatrixType,int UpLo> class SparseSymmetricPermutationProduct;
namespace internal {
@@ -99,23 +100,24 @@ template<typename T> struct eval<T,Sparse>
template<typename T,int Cols> struct sparse_eval<T,1,Cols> {
typedef typename traits<T>::Scalar _Scalar;
- enum { _Flags = traits<T>::Flags| RowMajorBit };
+ typedef typename traits<T>::Index _Index;
public:
- typedef SparseVector<_Scalar, _Flags> type;
+ typedef SparseVector<_Scalar, RowMajor, _Index> type;
};
template<typename T,int Rows> struct sparse_eval<T,Rows,1> {
typedef typename traits<T>::Scalar _Scalar;
- enum { _Flags = traits<T>::Flags & (~RowMajorBit) };
+ typedef typename traits<T>::Index _Index;
public:
- typedef SparseVector<_Scalar, _Flags> type;
+ typedef SparseVector<_Scalar, ColMajor, _Index> type;
};
template<typename T,int Rows,int Cols> struct sparse_eval {
typedef typename traits<T>::Scalar _Scalar;
- enum { _Flags = traits<T>::Flags };
+ typedef typename traits<T>::Index _Index;
+ enum { _Options = ((traits<T>::Flags&RowMajorBit)==RowMajorBit) ? RowMajor : ColMajor };
public:
- typedef SparseMatrix<_Scalar, _Flags> type;
+ typedef SparseMatrix<_Scalar, _Options, _Index> type;
};
template<typename T> struct sparse_eval<T,1,1> {
@@ -127,12 +129,10 @@ template<typename T> struct sparse_eval<T,1,1> {
template<typename T> struct plain_matrix_type<T,Sparse>
{
typedef typename traits<T>::Scalar _Scalar;
- enum {
- _Flags = traits<T>::Flags
- };
-
+ typedef typename traits<T>::Index _Index;
+ enum { _Options = ((traits<T>::Flags&RowMajorBit)==RowMajorBit) ? RowMajor : ColMajor };
public:
- typedef SparseMatrix<_Scalar, _Flags> type;
+ typedef SparseMatrix<_Scalar, _Options, _Index> type;
};
} // end namespace internal
@@ -145,7 +145,7 @@ template<typename T> struct plain_matrix_type<T,Sparse>
*
* \sa SparseMatrix::setFromTriplets()
*/
-template<typename Scalar, typename Index=unsigned int>
+template<typename Scalar, typename Index=typename SparseMatrix<Scalar>::Index >
class Triplet
{
public:
diff --git a/Eigen/src/SparseCore/SparseVector.h b/Eigen/src/SparseCore/SparseVector.h
index c952f6540..7e15c814b 100644
--- a/Eigen/src/SparseCore/SparseVector.h
+++ b/Eigen/src/SparseCore/SparseVector.h
@@ -45,35 +45,40 @@ struct traits<SparseVector<_Scalar, _Options, _Index> >
SupportedAccessPatterns = InnerRandomAccessPattern
};
};
+
+// Sparse-Vector-Assignment kinds:
+enum {
+ SVA_RuntimeSwitch,
+ SVA_Inner,
+ SVA_Outer
+};
+
+template< typename Dest, typename Src,
+ int AssignmentKind = !bool(Src::IsVectorAtCompileTime) ? SVA_RuntimeSwitch
+ : Src::InnerSizeAtCompileTime==1 ? SVA_Outer
+ : SVA_Inner>
+struct sparse_vector_assign_selector;
+
}
template<typename _Scalar, int _Options, typename _Index>
class SparseVector
: public SparseMatrixBase<SparseVector<_Scalar, _Options, _Index> >
{
+ typedef SparseMatrixBase<SparseVector> SparseBase;
+
public:
EIGEN_SPARSE_PUBLIC_INTERFACE(SparseVector)
EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, +=)
EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, -=)
-
- protected:
- public:
-
- typedef SparseMatrixBase<SparseVector> SparseBase;
+
+ typedef internal::CompressedStorage<Scalar,Index> Storage;
enum { IsColVector = internal::traits<SparseVector>::IsColVector };
enum {
Options = _Options
};
-
- internal::CompressedStorage<Scalar,Index> m_data;
- Index m_size;
-
- internal::CompressedStorage<Scalar,Index>& _data() { return m_data; }
- internal::CompressedStorage<Scalar,Index>& _data() const { return m_data; }
-
- public:
-
+
EIGEN_STRONG_INLINE Index rows() const { return IsColVector ? m_size : 1; }
EIGEN_STRONG_INLINE Index cols() const { return IsColVector ? 1 : m_size; }
EIGEN_STRONG_INLINE Index innerSize() const { return m_size; }
@@ -84,17 +89,26 @@ class SparseVector
EIGEN_STRONG_INLINE const Index* innerIndexPtr() const { return &m_data.index(0); }
EIGEN_STRONG_INLINE Index* innerIndexPtr() { return &m_data.index(0); }
+
+ /** \internal */
+ inline Storage& data() { return m_data; }
+ /** \internal */
+ inline const Storage& data() const { return m_data; }
inline Scalar coeff(Index row, Index col) const
{
- eigen_assert((IsColVector ? col : row)==0);
+ eigen_assert(IsColVector ? (col==0 && row>=0 && row<m_size) : (row==0 && col>=0 && col<m_size));
return coeff(IsColVector ? row : col);
}
- inline Scalar coeff(Index i) const { return m_data.at(i); }
+ inline Scalar coeff(Index i) const
+ {
+ eigen_assert(i>=0 && i<m_size);
+ return m_data.at(i);
+ }
inline Scalar& coeffRef(Index row, Index col)
{
- eigen_assert((IsColVector ? col : row)==0);
+ eigen_assert(IsColVector ? (col==0 && row>=0 && row<m_size) : (row==0 && col>=0 && col<m_size));
return coeff(IsColVector ? row : col);
}
@@ -106,6 +120,7 @@ class SparseVector
*/
inline Scalar& coeffRef(Index i)
{
+ eigen_assert(i>=0 && i<m_size);
return m_data.atWithInsertion(i);
}
@@ -139,6 +154,8 @@ class SparseVector
inline Scalar& insert(Index row, Index col)
{
+ eigen_assert(IsColVector ? (col==0 && row>=0 && row<m_size) : (row==0 && col>=0 && col<m_size));
+
Index inner = IsColVector ? row : col;
Index outer = IsColVector ? col : row;
eigen_assert(outer==0);
@@ -146,6 +163,8 @@ class SparseVector
}
Scalar& insert(Index i)
{
+ eigen_assert(i>=0 && i<m_size);
+
Index startId = 0;
Index p = Index(m_data.size()) - 1;
// TODO smart realloc
@@ -169,7 +188,7 @@ class SparseVector
inline void finalize() {}
- void prune(Scalar reference, RealScalar epsilon = NumTraits<RealScalar>::dummy_precision())
+ void prune(const Scalar& reference, const RealScalar& epsilon = NumTraits<RealScalar>::dummy_precision())
{
m_data.prune(reference,epsilon);
}
@@ -188,25 +207,31 @@ class SparseVector
void resizeNonZeros(Index size) { m_data.resize(size); }
- inline SparseVector() : m_size(0) { resize(0); }
+ inline SparseVector() : m_size(0) { check_template_parameters(); resize(0); }
- inline SparseVector(Index size) : m_size(0) { resize(size); }
+ inline SparseVector(Index size) : m_size(0) { check_template_parameters(); resize(size); }
- inline SparseVector(Index rows, Index cols) : m_size(0) { resize(rows,cols); }
+ inline SparseVector(Index rows, Index cols) : m_size(0) { check_template_parameters(); resize(rows,cols); }
template<typename OtherDerived>
inline SparseVector(const SparseMatrixBase<OtherDerived>& other)
: m_size(0)
{
+ check_template_parameters();
*this = other.derived();
}
inline SparseVector(const SparseVector& other)
- : m_size(0)
+ : SparseBase(other), m_size(0)
{
+ check_template_parameters();
*this = other.derived();
}
+ /** Swaps the values of \c *this and \a other.
+ * Overloaded for performance: this version performs a \em shallow swap by swaping pointers and attributes only.
+ * \sa SparseMatrixBase::swap()
+ */
inline void swap(SparseVector& other)
{
std::swap(m_size, other.m_size);
@@ -230,10 +255,10 @@ class SparseVector
template<typename OtherDerived>
inline SparseVector& operator=(const SparseMatrixBase<OtherDerived>& other)
{
- if (int(RowsAtCompileTime)!=int(OtherDerived::RowsAtCompileTime))
- return assign(other.transpose());
- else
- return assign(other);
+ SparseVector tmp(other.size());
+ internal::sparse_vector_assign_selector<SparseVector,OtherDerived>::run(tmp,other.derived());
+ this->swap(tmp);
+ return *this;
}
#ifndef EIGEN_PARSED_BY_DOXYGEN
@@ -260,73 +285,63 @@ class SparseVector
public:
- /** \deprecated use setZero() and reserve() */
+ /** \internal \deprecated use setZero() and reserve() */
EIGEN_DEPRECATED void startFill(Index reserve)
{
setZero();
m_data.reserve(reserve);
}
- /** \deprecated use insertBack(Index,Index) */
+ /** \internal \deprecated use insertBack(Index,Index) */
EIGEN_DEPRECATED Scalar& fill(Index r, Index c)
{
eigen_assert(r==0 || c==0);
return fill(IsColVector ? r : c);
}
- /** \deprecated use insertBack(Index) */
+ /** \internal \deprecated use insertBack(Index) */
EIGEN_DEPRECATED Scalar& fill(Index i)
{
m_data.append(0, i);
return m_data.value(m_data.size()-1);
}
- /** \deprecated use insert(Index,Index) */
+ /** \internal \deprecated use insert(Index,Index) */
EIGEN_DEPRECATED Scalar& fillrand(Index r, Index c)
{
eigen_assert(r==0 || c==0);
return fillrand(IsColVector ? r : c);
}
- /** \deprecated use insert(Index) */
+ /** \internal \deprecated use insert(Index) */
EIGEN_DEPRECATED Scalar& fillrand(Index i)
{
return insert(i);
}
- /** \deprecated use finalize() */
+ /** \internal \deprecated use finalize() */
EIGEN_DEPRECATED void endFill() {}
+ // These two functions were here in the 3.1 release, so let's keep them in case some code rely on them.
+ /** \internal \deprecated use data() */
+ EIGEN_DEPRECATED Storage& _data() { return m_data; }
+ /** \internal \deprecated use data() */
+ EIGEN_DEPRECATED const Storage& _data() const { return m_data; }
+
# ifdef EIGEN_SPARSEVECTOR_PLUGIN
# include EIGEN_SPARSEVECTOR_PLUGIN
# endif
protected:
- template<typename OtherDerived>
- EIGEN_DONT_INLINE SparseVector& assign(const SparseMatrixBase<OtherDerived>& _other)
+
+ static void check_template_parameters()
{
- const OtherDerived& other(_other.derived());
- const bool needToTranspose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit);
- if(needToTranspose)
- {
- Index size = other.size();
- Index nnz = other.nonZeros();
- resize(size);
- reserve(nnz);
- for(Index i=0; i<size; ++i)
- {
- typename OtherDerived::InnerIterator it(other, i);
- if(it)
- insert(i) = it.value();
- }
- return *this;
- }
- else
- {
- // there is no special optimization
- return Base::operator=(other);
- }
+ EIGEN_STATIC_ASSERT(NumTraits<Index>::IsSigned,THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE);
+ EIGEN_STATIC_ASSERT((_Options&(ColMajor|RowMajor))==Options,INVALID_MATRIX_TEMPLATE_PARAMETERS);
}
+
+ Storage m_data;
+ Index m_size;
};
template<typename Scalar, int _Options, typename _Index>
@@ -393,6 +408,40 @@ class SparseVector<Scalar,_Options,_Index>::ReverseInnerIterator
const Index m_start;
};
+namespace internal {
+
+template< typename Dest, typename Src>
+struct sparse_vector_assign_selector<Dest,Src,SVA_Inner> {
+ static void run(Dest& dst, const Src& src) {
+ eigen_internal_assert(src.innerSize()==src.size());
+ for(typename Src::InnerIterator it(src, 0); it; ++it)
+ dst.insert(it.index()) = it.value();
+ }
+};
+
+template< typename Dest, typename Src>
+struct sparse_vector_assign_selector<Dest,Src,SVA_Outer> {
+ static void run(Dest& dst, const Src& src) {
+ eigen_internal_assert(src.outerSize()==src.size());
+ for(typename Dest::Index i=0; i<src.size(); ++i)
+ {
+ typename Src::InnerIterator it(src, i);
+ if(it)
+ dst.insert(i) = it.value();
+ }
+ }
+};
+
+template< typename Dest, typename Src>
+struct sparse_vector_assign_selector<Dest,Src,SVA_RuntimeSwitch> {
+ static void run(Dest& dst, const Src& src) {
+ if(src.outerSize()==1) sparse_vector_assign_selector<Dest,Src,SVA_Inner>::run(dst, src);
+ else sparse_vector_assign_selector<Dest,Src,SVA_Outer>::run(dst, src);
+ }
+};
+
+}
+
} // end namespace Eigen
#endif // EIGEN_SPARSEVECTOR_H
diff --git a/Eigen/src/SparseCore/SparseView.h b/Eigen/src/SparseCore/SparseView.h
index 8b0b9ea03..fd8450463 100644
--- a/Eigen/src/SparseCore/SparseView.h
+++ b/Eigen/src/SparseCore/SparseView.h
@@ -18,7 +18,7 @@ namespace internal {
template<typename MatrixType>
struct traits<SparseView<MatrixType> > : traits<MatrixType>
{
- typedef int Index;
+ typedef typename MatrixType::Index Index;
typedef Sparse StorageKind;
enum {
Flags = int(traits<MatrixType>::Flags) & (RowMajorBit)
@@ -56,6 +56,7 @@ protected:
template<typename MatrixType>
class SparseView<MatrixType>::InnerIterator : public _MatrixTypeNested::InnerIterator
{
+ typedef typename SparseView::Index Index;
public:
typedef typename _MatrixTypeNested::InnerIterator IterBase;
InnerIterator(const SparseView& view, Index outer) :
@@ -88,7 +89,7 @@ private:
template<typename Derived>
const SparseView<Derived> MatrixBase<Derived>::sparseView(const Scalar& m_reference,
- typename NumTraits<Scalar>::Real m_epsilon) const
+ const typename NumTraits<Scalar>::Real& m_epsilon) const
{
return SparseView<Derived>(derived(), m_reference, m_epsilon);
}
diff --git a/Eigen/src/SparseLU/CMakeLists.txt b/Eigen/src/SparseLU/CMakeLists.txt
new file mode 100644
index 000000000..69729ee89
--- /dev/null
+++ b/Eigen/src/SparseLU/CMakeLists.txt
@@ -0,0 +1,6 @@
+FILE(GLOB Eigen_SparseLU_SRCS "*.h")
+
+INSTALL(FILES
+ ${Eigen_SparseLU_SRCS}
+ DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/SparseLU COMPONENT Devel
+ )
diff --git a/Eigen/src/SparseLU/SparseLU.h b/Eigen/src/SparseLU/SparseLU.h
new file mode 100644
index 000000000..1d592f2c8
--- /dev/null
+++ b/Eigen/src/SparseLU/SparseLU.h
@@ -0,0 +1,758 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+// Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+
+#ifndef EIGEN_SPARSE_LU_H
+#define EIGEN_SPARSE_LU_H
+
+namespace Eigen {
+
+template <typename _MatrixType, typename _OrderingType = COLAMDOrdering<typename _MatrixType::Index> > class SparseLU;
+template <typename MappedSparseMatrixType> struct SparseLUMatrixLReturnType;
+template <typename MatrixLType, typename MatrixUType> struct SparseLUMatrixUReturnType;
+
+/** \ingroup SparseLU_Module
+ * \class SparseLU
+ *
+ * \brief Sparse supernodal LU factorization for general matrices
+ *
+ * This class implements the supernodal LU factorization for general matrices.
+ * It uses the main techniques from the sequential SuperLU package
+ * (http://crd-legacy.lbl.gov/~xiaoye/SuperLU/). It handles transparently real
+ * and complex arithmetics with single and double precision, depending on the
+ * scalar type of your input matrix.
+ * The code has been optimized to provide BLAS-3 operations during supernode-panel updates.
+ * It benefits directly from the built-in high-performant Eigen BLAS routines.
+ * Moreover, when the size of a supernode is very small, the BLAS calls are avoided to
+ * enable a better optimization from the compiler. For best performance,
+ * you should compile it with NDEBUG flag to avoid the numerous bounds checking on vectors.
+ *
+ * An important parameter of this class is the ordering method. It is used to reorder the columns
+ * (and eventually the rows) of the matrix to reduce the number of new elements that are created during
+ * numerical factorization. The cheapest method available is COLAMD.
+ * See \link OrderingMethods_Module the OrderingMethods module \endlink for the list of
+ * built-in and external ordering methods.
+ *
+ * Simple example with key steps
+ * \code
+ * VectorXd x(n), b(n);
+ * SparseMatrix<double, ColMajor> A;
+ * SparseLU<SparseMatrix<scalar, ColMajor>, COLAMDOrdering<Index> > solver;
+ * // fill A and b;
+ * // Compute the ordering permutation vector from the structural pattern of A
+ * solver.analyzePattern(A);
+ * // Compute the numerical factorization
+ * solver.factorize(A);
+ * //Use the factors to solve the linear system
+ * x = solver.solve(b);
+ * \endcode
+ *
+ * \warning The input matrix A should be in a \b compressed and \b column-major form.
+ * Otherwise an expensive copy will be made. You can call the inexpensive makeCompressed() to get a compressed matrix.
+ *
+ * \note Unlike the initial SuperLU implementation, there is no step to equilibrate the matrix.
+ * For badly scaled matrices, this step can be useful to reduce the pivoting during factorization.
+ * If this is the case for your matrices, you can try the basic scaling method at
+ * "unsupported/Eigen/src/IterativeSolvers/Scaling.h"
+ *
+ * \tparam _MatrixType The type of the sparse matrix. It must be a column-major SparseMatrix<>
+ * \tparam _OrderingType The ordering method to use, either AMD, COLAMD or METIS. Default is COLMAD
+ *
+ *
+ * \sa \ref TutorialSparseDirectSolvers
+ * \sa \ref OrderingMethods_Module
+ */
+template <typename _MatrixType, typename _OrderingType>
+class SparseLU : public internal::SparseLUImpl<typename _MatrixType::Scalar, typename _MatrixType::Index>
+{
+ public:
+ typedef _MatrixType MatrixType;
+ typedef _OrderingType OrderingType;
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::RealScalar RealScalar;
+ typedef typename MatrixType::Index Index;
+ typedef SparseMatrix<Scalar,ColMajor,Index> NCMatrix;
+ typedef internal::MappedSuperNodalMatrix<Scalar, Index> SCMatrix;
+ typedef Matrix<Scalar,Dynamic,1> ScalarVector;
+ typedef Matrix<Index,Dynamic,1> IndexVector;
+ typedef PermutationMatrix<Dynamic, Dynamic, Index> PermutationType;
+ typedef internal::SparseLUImpl<Scalar, Index> Base;
+
+ public:
+ SparseLU():m_isInitialized(true),m_lastError(""),m_Ustore(0,0,0,0,0,0),m_symmetricmode(false),m_diagpivotthresh(1.0),m_detPermR(1)
+ {
+ initperfvalues();
+ }
+ SparseLU(const MatrixType& matrix):m_isInitialized(true),m_lastError(""),m_Ustore(0,0,0,0,0,0),m_symmetricmode(false),m_diagpivotthresh(1.0),m_detPermR(1)
+ {
+ initperfvalues();
+ compute(matrix);
+ }
+
+ ~SparseLU()
+ {
+ // Free all explicit dynamic pointers
+ }
+
+ void analyzePattern (const MatrixType& matrix);
+ void factorize (const MatrixType& matrix);
+ void simplicialfactorize(const MatrixType& matrix);
+
+ /**
+ * Compute the symbolic and numeric factorization of the input sparse matrix.
+ * The input matrix should be in column-major storage.
+ */
+ void compute (const MatrixType& matrix)
+ {
+ // Analyze
+ analyzePattern(matrix);
+ //Factorize
+ factorize(matrix);
+ }
+
+ inline Index rows() const { return m_mat.rows(); }
+ inline Index cols() const { return m_mat.cols(); }
+ /** Indicate that the pattern of the input matrix is symmetric */
+ void isSymmetric(bool sym)
+ {
+ m_symmetricmode = sym;
+ }
+
+ /** \returns an expression of the matrix L, internally stored as supernodes
+ * The only operation available with this expression is the triangular solve
+ * \code
+ * y = b; matrixL().solveInPlace(y);
+ * \endcode
+ */
+ SparseLUMatrixLReturnType<SCMatrix> matrixL() const
+ {
+ return SparseLUMatrixLReturnType<SCMatrix>(m_Lstore);
+ }
+ /** \returns an expression of the matrix U,
+ * The only operation available with this expression is the triangular solve
+ * \code
+ * y = b; matrixU().solveInPlace(y);
+ * \endcode
+ */
+ SparseLUMatrixUReturnType<SCMatrix,MappedSparseMatrix<Scalar,ColMajor,Index> > matrixU() const
+ {
+ return SparseLUMatrixUReturnType<SCMatrix, MappedSparseMatrix<Scalar,ColMajor,Index> >(m_Lstore, m_Ustore);
+ }
+
+ /**
+ * \returns a reference to the row matrix permutation \f$ P_r \f$ such that \f$P_r A P_c^T = L U\f$
+ * \sa colsPermutation()
+ */
+ inline const PermutationType& rowsPermutation() const
+ {
+ return m_perm_r;
+ }
+ /**
+ * \returns a reference to the column matrix permutation\f$ P_c^T \f$ such that \f$P_r A P_c^T = L U\f$
+ * \sa rowsPermutation()
+ */
+ inline const PermutationType& colsPermutation() const
+ {
+ return m_perm_c;
+ }
+ /** Set the threshold used for a diagonal entry to be an acceptable pivot. */
+ void setPivotThreshold(const RealScalar& thresh)
+ {
+ m_diagpivotthresh = thresh;
+ }
+
+ /** \returns the solution X of \f$ A X = B \f$ using the current decomposition of A.
+ *
+ * \warning the destination matrix X in X = this->solve(B) must be colmun-major.
+ *
+ * \sa compute()
+ */
+ template<typename Rhs>
+ inline const internal::solve_retval<SparseLU, Rhs> solve(const MatrixBase<Rhs>& B) const
+ {
+ eigen_assert(m_factorizationIsOk && "SparseLU is not initialized.");
+ eigen_assert(rows()==B.rows()
+ && "SparseLU::solve(): invalid number of rows of the right hand side matrix B");
+ return internal::solve_retval<SparseLU, Rhs>(*this, B.derived());
+ }
+
+ /** \returns the solution X of \f$ A X = B \f$ using the current decomposition of A.
+ *
+ * \sa compute()
+ */
+ template<typename Rhs>
+ inline const internal::sparse_solve_retval<SparseLU, Rhs> solve(const SparseMatrixBase<Rhs>& B) const
+ {
+ eigen_assert(m_factorizationIsOk && "SparseLU is not initialized.");
+ eigen_assert(rows()==B.rows()
+ && "SparseLU::solve(): invalid number of rows of the right hand side matrix B");
+ return internal::sparse_solve_retval<SparseLU, Rhs>(*this, B.derived());
+ }
+
+ /** \brief Reports whether previous computation was successful.
+ *
+ * \returns \c Success if computation was succesful,
+ * \c NumericalIssue if the LU factorization reports a problem, zero diagonal for instance
+ * \c InvalidInput if the input matrix is invalid
+ *
+ * \sa iparm()
+ */
+ ComputationInfo info() const
+ {
+ eigen_assert(m_isInitialized && "Decomposition is not initialized.");
+ return m_info;
+ }
+
+ /**
+ * \returns A string describing the type of error
+ */
+ std::string lastErrorMessage() const
+ {
+ return m_lastError;
+ }
+
+ template<typename Rhs, typename Dest>
+ bool _solve(const MatrixBase<Rhs> &B, MatrixBase<Dest> &X_base) const
+ {
+ Dest& X(X_base.derived());
+ eigen_assert(m_factorizationIsOk && "The matrix should be factorized first");
+ EIGEN_STATIC_ASSERT((Dest::Flags&RowMajorBit)==0,
+ THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
+
+ // Permute the right hand side to form X = Pr*B
+ // on return, X is overwritten by the computed solution
+ X.resize(B.rows(),B.cols());
+
+ // this ugly const_cast_derived() helps to detect aliasing when applying the permutations
+ for(Index j = 0; j < B.cols(); ++j)
+ X.col(j) = rowsPermutation() * B.const_cast_derived().col(j);
+
+ //Forward substitution with L
+ this->matrixL().solveInPlace(X);
+ this->matrixU().solveInPlace(X);
+
+ // Permute back the solution
+ for (Index j = 0; j < B.cols(); ++j)
+ X.col(j) = colsPermutation().inverse() * X.col(j);
+
+ return true;
+ }
+
+ /**
+ * \returns the absolute value of the determinant of the matrix of which
+ * *this is the QR decomposition.
+ *
+ * \warning a determinant can be very big or small, so for matrices
+ * of large enough dimension, there is a risk of overflow/underflow.
+ * One way to work around that is to use logAbsDeterminant() instead.
+ *
+ * \sa logAbsDeterminant(), signDeterminant()
+ */
+ Scalar absDeterminant()
+ {
+ eigen_assert(m_factorizationIsOk && "The matrix should be factorized first.");
+ // Initialize with the determinant of the row matrix
+ Scalar det = Scalar(1.);
+ //Note that the diagonal blocks of U are stored in supernodes,
+ // which are available in the L part :)
+ for (Index j = 0; j < this->cols(); ++j)
+ {
+ for (typename SCMatrix::InnerIterator it(m_Lstore, j); it; ++it)
+ {
+ if(it.row() < j) continue;
+ if(it.row() == j)
+ {
+ det *= (std::abs)(it.value());
+ break;
+ }
+ }
+ }
+ return det;
+ }
+
+ /** \returns the natural log of the absolute value of the determinant of the matrix
+ * of which **this is the QR decomposition
+ *
+ * \note This method is useful to work around the risk of overflow/underflow that's
+ * inherent to the determinant computation.
+ *
+ * \sa absDeterminant(), signDeterminant()
+ */
+ Scalar logAbsDeterminant() const
+ {
+ eigen_assert(m_factorizationIsOk && "The matrix should be factorized first.");
+ Scalar det = Scalar(0.);
+ for (Index j = 0; j < this->cols(); ++j)
+ {
+ for (typename SCMatrix::InnerIterator it(m_Lstore, j); it; ++it)
+ {
+ if(it.row() < j) continue;
+ if(it.row() == j)
+ {
+ det += (std::log)((std::abs)(it.value()));
+ break;
+ }
+ }
+ }
+ return det;
+ }
+
+ /** \returns A number representing the sign of the determinant
+ *
+ * \sa absDeterminant(), logAbsDeterminant()
+ */
+ Scalar signDeterminant()
+ {
+ eigen_assert(m_factorizationIsOk && "The matrix should be factorized first.");
+ return Scalar(m_detPermR);
+ }
+
+ protected:
+ // Functions
+ void initperfvalues()
+ {
+ m_perfv.panel_size = 1;
+ m_perfv.relax = 1;
+ m_perfv.maxsuper = 128;
+ m_perfv.rowblk = 16;
+ m_perfv.colblk = 8;
+ m_perfv.fillfactor = 20;
+ }
+
+ // Variables
+ mutable ComputationInfo m_info;
+ bool m_isInitialized;
+ bool m_factorizationIsOk;
+ bool m_analysisIsOk;
+ std::string m_lastError;
+ NCMatrix m_mat; // The input (permuted ) matrix
+ SCMatrix m_Lstore; // The lower triangular matrix (supernodal)
+ MappedSparseMatrix<Scalar,ColMajor,Index> m_Ustore; // The upper triangular matrix
+ PermutationType m_perm_c; // Column permutation
+ PermutationType m_perm_r ; // Row permutation
+ IndexVector m_etree; // Column elimination tree
+
+ typename Base::GlobalLU_t m_glu;
+
+ // SparseLU options
+ bool m_symmetricmode;
+ // values for performance
+ internal::perfvalues<Index> m_perfv;
+ RealScalar m_diagpivotthresh; // Specifies the threshold used for a diagonal entry to be an acceptable pivot
+ Index m_nnzL, m_nnzU; // Nonzeros in L and U factors
+ Index m_detPermR; // Determinant of the coefficient matrix
+ private:
+ // Disable copy constructor
+ SparseLU (const SparseLU& );
+
+}; // End class SparseLU
+
+
+
+// Functions needed by the anaysis phase
+/**
+ * Compute the column permutation to minimize the fill-in
+ *
+ * - Apply this permutation to the input matrix -
+ *
+ * - Compute the column elimination tree on the permuted matrix
+ *
+ * - Postorder the elimination tree and the column permutation
+ *
+ */
+template <typename MatrixType, typename OrderingType>
+void SparseLU<MatrixType, OrderingType>::analyzePattern(const MatrixType& mat)
+{
+
+ //TODO It is possible as in SuperLU to compute row and columns scaling vectors to equilibrate the matrix mat.
+
+ OrderingType ord;
+ ord(mat,m_perm_c);
+
+ // Apply the permutation to the column of the input matrix
+ //First copy the whole input matrix.
+ m_mat = mat;
+ if (m_perm_c.size()) {
+ m_mat.uncompress(); //NOTE: The effect of this command is only to create the InnerNonzeros pointers. FIXME : This vector is filled but not subsequently used.
+ //Then, permute only the column pointers
+ const Index * outerIndexPtr;
+ if (mat.isCompressed()) outerIndexPtr = mat.outerIndexPtr();
+ else
+ {
+ Index *outerIndexPtr_t = new Index[mat.cols()+1];
+ for(Index i = 0; i <= mat.cols(); i++) outerIndexPtr_t[i] = m_mat.outerIndexPtr()[i];
+ outerIndexPtr = outerIndexPtr_t;
+ }
+ for (Index i = 0; i < mat.cols(); i++)
+ {
+ m_mat.outerIndexPtr()[m_perm_c.indices()(i)] = outerIndexPtr[i];
+ m_mat.innerNonZeroPtr()[m_perm_c.indices()(i)] = outerIndexPtr[i+1] - outerIndexPtr[i];
+ }
+ if(!mat.isCompressed()) delete[] outerIndexPtr;
+ }
+ // Compute the column elimination tree of the permuted matrix
+ IndexVector firstRowElt;
+ internal::coletree(m_mat, m_etree,firstRowElt);
+
+ // In symmetric mode, do not do postorder here
+ if (!m_symmetricmode) {
+ IndexVector post, iwork;
+ // Post order etree
+ internal::treePostorder(m_mat.cols(), m_etree, post);
+
+
+ // Renumber etree in postorder
+ Index m = m_mat.cols();
+ iwork.resize(m+1);
+ for (Index i = 0; i < m; ++i) iwork(post(i)) = post(m_etree(i));
+ m_etree = iwork;
+
+ // Postmultiply A*Pc by post, i.e reorder the matrix according to the postorder of the etree
+ PermutationType post_perm(m);
+ for (Index i = 0; i < m; i++)
+ post_perm.indices()(i) = post(i);
+
+ // Combine the two permutations : postorder the permutation for future use
+ if(m_perm_c.size()) {
+ m_perm_c = post_perm * m_perm_c;
+ }
+
+ } // end postordering
+
+ m_analysisIsOk = true;
+}
+
+// Functions needed by the numerical factorization phase
+
+
+/**
+ * - Numerical factorization
+ * - Interleaved with the symbolic factorization
+ * On exit, info is
+ *
+ * = 0: successful factorization
+ *
+ * > 0: if info = i, and i is
+ *
+ * <= A->ncol: U(i,i) is exactly zero. The factorization has
+ * been completed, but the factor U is exactly singular,
+ * and division by zero will occur if it is used to solve a
+ * system of equations.
+ *
+ * > A->ncol: number of bytes allocated when memory allocation
+ * failure occurred, plus A->ncol. If lwork = -1, it is
+ * the estimated amount of space needed, plus A->ncol.
+ */
+template <typename MatrixType, typename OrderingType>
+void SparseLU<MatrixType, OrderingType>::factorize(const MatrixType& matrix)
+{
+ using internal::emptyIdxLU;
+ eigen_assert(m_analysisIsOk && "analyzePattern() should be called first");
+ eigen_assert((matrix.rows() == matrix.cols()) && "Only for squared matrices");
+
+ typedef typename IndexVector::Scalar Index;
+
+
+ // Apply the column permutation computed in analyzepattern()
+ // m_mat = matrix * m_perm_c.inverse();
+ m_mat = matrix;
+ if (m_perm_c.size())
+ {
+ m_mat.uncompress(); //NOTE: The effect of this command is only to create the InnerNonzeros pointers.
+ //Then, permute only the column pointers
+ const Index * outerIndexPtr;
+ if (matrix.isCompressed()) outerIndexPtr = matrix.outerIndexPtr();
+ else
+ {
+ Index* outerIndexPtr_t = new Index[matrix.cols()+1];
+ for(Index i = 0; i <= matrix.cols(); i++) outerIndexPtr_t[i] = m_mat.outerIndexPtr()[i];
+ outerIndexPtr = outerIndexPtr_t;
+ }
+ for (Index i = 0; i < matrix.cols(); i++)
+ {
+ m_mat.outerIndexPtr()[m_perm_c.indices()(i)] = outerIndexPtr[i];
+ m_mat.innerNonZeroPtr()[m_perm_c.indices()(i)] = outerIndexPtr[i+1] - outerIndexPtr[i];
+ }
+ if(!matrix.isCompressed()) delete[] outerIndexPtr;
+ }
+ else
+ { //FIXME This should not be needed if the empty permutation is handled transparently
+ m_perm_c.resize(matrix.cols());
+ for(Index i = 0; i < matrix.cols(); ++i) m_perm_c.indices()(i) = i;
+ }
+
+ Index m = m_mat.rows();
+ Index n = m_mat.cols();
+ Index nnz = m_mat.nonZeros();
+ Index maxpanel = m_perfv.panel_size * m;
+ // Allocate working storage common to the factor routines
+ Index lwork = 0;
+ Index info = Base::memInit(m, n, nnz, lwork, m_perfv.fillfactor, m_perfv.panel_size, m_glu);
+ if (info)
+ {
+ m_lastError = "UNABLE TO ALLOCATE WORKING MEMORY\n\n" ;
+ m_factorizationIsOk = false;
+ return ;
+ }
+
+ // Set up pointers for integer working arrays
+ IndexVector segrep(m); segrep.setZero();
+ IndexVector parent(m); parent.setZero();
+ IndexVector xplore(m); xplore.setZero();
+ IndexVector repfnz(maxpanel);
+ IndexVector panel_lsub(maxpanel);
+ IndexVector xprune(n); xprune.setZero();
+ IndexVector marker(m*internal::LUNoMarker); marker.setZero();
+
+ repfnz.setConstant(-1);
+ panel_lsub.setConstant(-1);
+
+ // Set up pointers for scalar working arrays
+ ScalarVector dense;
+ dense.setZero(maxpanel);
+ ScalarVector tempv;
+ tempv.setZero(internal::LUnumTempV(m, m_perfv.panel_size, m_perfv.maxsuper, /*m_perfv.rowblk*/m) );
+
+ // Compute the inverse of perm_c
+ PermutationType iperm_c(m_perm_c.inverse());
+
+ // Identify initial relaxed snodes
+ IndexVector relax_end(n);
+ if ( m_symmetricmode == true )
+ Base::heap_relax_snode(n, m_etree, m_perfv.relax, marker, relax_end);
+ else
+ Base::relax_snode(n, m_etree, m_perfv.relax, marker, relax_end);
+
+
+ m_perm_r.resize(m);
+ m_perm_r.indices().setConstant(-1);
+ marker.setConstant(-1);
+ m_detPermR = 1; // Record the determinant of the row permutation
+
+ m_glu.supno(0) = emptyIdxLU; m_glu.xsup.setConstant(0);
+ m_glu.xsup(0) = m_glu.xlsub(0) = m_glu.xusub(0) = m_glu.xlusup(0) = Index(0);
+
+ // Work on one 'panel' at a time. A panel is one of the following :
+ // (a) a relaxed supernode at the bottom of the etree, or
+ // (b) panel_size contiguous columns, <panel_size> defined by the user
+ Index jcol;
+ IndexVector panel_histo(n);
+ Index pivrow; // Pivotal row number in the original row matrix
+ Index nseg1; // Number of segments in U-column above panel row jcol
+ Index nseg; // Number of segments in each U-column
+ Index irep;
+ Index i, k, jj;
+ for (jcol = 0; jcol < n; )
+ {
+ // Adjust panel size so that a panel won't overlap with the next relaxed snode.
+ Index panel_size = m_perfv.panel_size; // upper bound on panel width
+ for (k = jcol + 1; k < (std::min)(jcol+panel_size, n); k++)
+ {
+ if (relax_end(k) != emptyIdxLU)
+ {
+ panel_size = k - jcol;
+ break;
+ }
+ }
+ if (k == n)
+ panel_size = n - jcol;
+
+ // Symbolic outer factorization on a panel of columns
+ Base::panel_dfs(m, panel_size, jcol, m_mat, m_perm_r.indices(), nseg1, dense, panel_lsub, segrep, repfnz, xprune, marker, parent, xplore, m_glu);
+
+ // Numeric sup-panel updates in topological order
+ Base::panel_bmod(m, panel_size, jcol, nseg1, dense, tempv, segrep, repfnz, m_glu);
+
+ // Sparse LU within the panel, and below the panel diagonal
+ for ( jj = jcol; jj< jcol + panel_size; jj++)
+ {
+ k = (jj - jcol) * m; // Column index for w-wide arrays
+
+ nseg = nseg1; // begin after all the panel segments
+ //Depth-first-search for the current column
+ VectorBlock<IndexVector> panel_lsubk(panel_lsub, k, m);
+ VectorBlock<IndexVector> repfnz_k(repfnz, k, m);
+ info = Base::column_dfs(m, jj, m_perm_r.indices(), m_perfv.maxsuper, nseg, panel_lsubk, segrep, repfnz_k, xprune, marker, parent, xplore, m_glu);
+ if ( info )
+ {
+ m_lastError = "UNABLE TO EXPAND MEMORY IN COLUMN_DFS() ";
+ m_info = NumericalIssue;
+ m_factorizationIsOk = false;
+ return;
+ }
+ // Numeric updates to this column
+ VectorBlock<ScalarVector> dense_k(dense, k, m);
+ VectorBlock<IndexVector> segrep_k(segrep, nseg1, m-nseg1);
+ info = Base::column_bmod(jj, (nseg - nseg1), dense_k, tempv, segrep_k, repfnz_k, jcol, m_glu);
+ if ( info )
+ {
+ m_lastError = "UNABLE TO EXPAND MEMORY IN COLUMN_BMOD() ";
+ m_info = NumericalIssue;
+ m_factorizationIsOk = false;
+ return;
+ }
+
+ // Copy the U-segments to ucol(*)
+ info = Base::copy_to_ucol(jj, nseg, segrep, repfnz_k ,m_perm_r.indices(), dense_k, m_glu);
+ if ( info )
+ {
+ m_lastError = "UNABLE TO EXPAND MEMORY IN COPY_TO_UCOL() ";
+ m_info = NumericalIssue;
+ m_factorizationIsOk = false;
+ return;
+ }
+
+ // Form the L-segment
+ info = Base::pivotL(jj, m_diagpivotthresh, m_perm_r.indices(), iperm_c.indices(), pivrow, m_glu);
+ if ( info )
+ {
+ m_lastError = "THE MATRIX IS STRUCTURALLY SINGULAR ... ZERO COLUMN AT ";
+ std::ostringstream returnInfo;
+ returnInfo << info;
+ m_lastError += returnInfo.str();
+ m_info = NumericalIssue;
+ m_factorizationIsOk = false;
+ return;
+ }
+
+ // Update the determinant of the row permutation matrix
+ if (pivrow != jj) m_detPermR *= -1;
+
+ // Prune columns (0:jj-1) using column jj
+ Base::pruneL(jj, m_perm_r.indices(), pivrow, nseg, segrep, repfnz_k, xprune, m_glu);
+
+ // Reset repfnz for this column
+ for (i = 0; i < nseg; i++)
+ {
+ irep = segrep(i);
+ repfnz_k(irep) = emptyIdxLU;
+ }
+ } // end SparseLU within the panel
+ jcol += panel_size; // Move to the next panel
+ } // end for -- end elimination
+
+ // Count the number of nonzeros in factors
+ Base::countnz(n, m_nnzL, m_nnzU, m_glu);
+ // Apply permutation to the L subscripts
+ Base::fixupL(n, m_perm_r.indices(), m_glu);
+
+ // Create supernode matrix L
+ m_Lstore.setInfos(m, n, m_glu.lusup, m_glu.xlusup, m_glu.lsub, m_glu.xlsub, m_glu.supno, m_glu.xsup);
+ // Create the column major upper sparse matrix U;
+ new (&m_Ustore) MappedSparseMatrix<Scalar, ColMajor, Index> ( m, n, m_nnzU, m_glu.xusub.data(), m_glu.usub.data(), m_glu.ucol.data() );
+
+ m_info = Success;
+ m_factorizationIsOk = true;
+}
+
+template<typename MappedSupernodalType>
+struct SparseLUMatrixLReturnType : internal::no_assignment_operator
+{
+ typedef typename MappedSupernodalType::Index Index;
+ typedef typename MappedSupernodalType::Scalar Scalar;
+ SparseLUMatrixLReturnType(const MappedSupernodalType& mapL) : m_mapL(mapL)
+ { }
+ Index rows() { return m_mapL.rows(); }
+ Index cols() { return m_mapL.cols(); }
+ template<typename Dest>
+ void solveInPlace( MatrixBase<Dest> &X) const
+ {
+ m_mapL.solveInPlace(X);
+ }
+ const MappedSupernodalType& m_mapL;
+};
+
+template<typename MatrixLType, typename MatrixUType>
+struct SparseLUMatrixUReturnType : internal::no_assignment_operator
+{
+ typedef typename MatrixLType::Index Index;
+ typedef typename MatrixLType::Scalar Scalar;
+ SparseLUMatrixUReturnType(const MatrixLType& mapL, const MatrixUType& mapU)
+ : m_mapL(mapL),m_mapU(mapU)
+ { }
+ Index rows() { return m_mapL.rows(); }
+ Index cols() { return m_mapL.cols(); }
+
+ template<typename Dest> void solveInPlace(MatrixBase<Dest> &X) const
+ {
+ Index nrhs = X.cols();
+ Index n = X.rows();
+ // Backward solve with U
+ for (Index k = m_mapL.nsuper(); k >= 0; k--)
+ {
+ Index fsupc = m_mapL.supToCol()[k];
+ Index lda = m_mapL.colIndexPtr()[fsupc+1] - m_mapL.colIndexPtr()[fsupc]; // leading dimension
+ Index nsupc = m_mapL.supToCol()[k+1] - fsupc;
+ Index luptr = m_mapL.colIndexPtr()[fsupc];
+
+ if (nsupc == 1)
+ {
+ for (Index j = 0; j < nrhs; j++)
+ {
+ X(fsupc, j) /= m_mapL.valuePtr()[luptr];
+ }
+ }
+ else
+ {
+ Map<const Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > A( &(m_mapL.valuePtr()[luptr]), nsupc, nsupc, OuterStride<>(lda) );
+ Map< Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > U (&(X(fsupc,0)), nsupc, nrhs, OuterStride<>(n) );
+ U = A.template triangularView<Upper>().solve(U);
+ }
+
+ for (Index j = 0; j < nrhs; ++j)
+ {
+ for (Index jcol = fsupc; jcol < fsupc + nsupc; jcol++)
+ {
+ typename MatrixUType::InnerIterator it(m_mapU, jcol);
+ for ( ; it; ++it)
+ {
+ Index irow = it.index();
+ X(irow, j) -= X(jcol, j) * it.value();
+ }
+ }
+ }
+ } // End For U-solve
+ }
+ const MatrixLType& m_mapL;
+ const MatrixUType& m_mapU;
+};
+
+namespace internal {
+
+template<typename _MatrixType, typename Derived, typename Rhs>
+struct solve_retval<SparseLU<_MatrixType,Derived>, Rhs>
+ : solve_retval_base<SparseLU<_MatrixType,Derived>, Rhs>
+{
+ typedef SparseLU<_MatrixType,Derived> Dec;
+ EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs)
+
+ template<typename Dest> void evalTo(Dest& dst) const
+ {
+ dec()._solve(rhs(),dst);
+ }
+};
+
+template<typename _MatrixType, typename Derived, typename Rhs>
+struct sparse_solve_retval<SparseLU<_MatrixType,Derived>, Rhs>
+ : sparse_solve_retval_base<SparseLU<_MatrixType,Derived>, Rhs>
+{
+ typedef SparseLU<_MatrixType,Derived> Dec;
+ EIGEN_MAKE_SPARSE_SOLVE_HELPERS(Dec,Rhs)
+
+ template<typename Dest> void evalTo(Dest& dst) const
+ {
+ this->defaultEvalTo(dst);
+ }
+};
+} // end namespace internal
+
+} // End namespace Eigen
+
+#endif
diff --git a/Eigen/src/SparseLU/SparseLUImpl.h b/Eigen/src/SparseLU/SparseLUImpl.h
new file mode 100644
index 000000000..14d70897d
--- /dev/null
+++ b/Eigen/src/SparseLU/SparseLUImpl.h
@@ -0,0 +1,64 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef SPARSELU_IMPL_H
+#define SPARSELU_IMPL_H
+
+namespace Eigen {
+namespace internal {
+
+/** \ingroup SparseLU_Module
+ * \class SparseLUImpl
+ * Base class for sparseLU
+ */
+template <typename Scalar, typename Index>
+class SparseLUImpl
+{
+ public:
+ typedef Matrix<Scalar,Dynamic,1> ScalarVector;
+ typedef Matrix<Index,Dynamic,1> IndexVector;
+ typedef typename ScalarVector::RealScalar RealScalar;
+ typedef Ref<Matrix<Scalar,Dynamic,1> > BlockScalarVector;
+ typedef Ref<Matrix<Index,Dynamic,1> > BlockIndexVector;
+ typedef LU_GlobalLU_t<IndexVector, ScalarVector> GlobalLU_t;
+ typedef SparseMatrix<Scalar,ColMajor,Index> MatrixType;
+
+ protected:
+ template <typename VectorType>
+ Index expand(VectorType& vec, Index& length, Index nbElts, Index keep_prev, Index& num_expansions);
+ Index memInit(Index m, Index n, Index annz, Index lwork, Index fillratio, Index panel_size, GlobalLU_t& glu);
+ template <typename VectorType>
+ Index memXpand(VectorType& vec, Index& maxlen, Index nbElts, MemType memtype, Index& num_expansions);
+ void heap_relax_snode (const Index n, IndexVector& et, const Index relax_columns, IndexVector& descendants, IndexVector& relax_end);
+ void relax_snode (const Index n, IndexVector& et, const Index relax_columns, IndexVector& descendants, IndexVector& relax_end);
+ Index snode_dfs(const Index jcol, const Index kcol,const MatrixType& mat, IndexVector& xprune, IndexVector& marker, GlobalLU_t& glu);
+ Index snode_bmod (const Index jcol, const Index fsupc, ScalarVector& dense, GlobalLU_t& glu);
+ Index pivotL(const Index jcol, const RealScalar& diagpivotthresh, IndexVector& perm_r, IndexVector& iperm_c, Index& pivrow, GlobalLU_t& glu);
+ template <typename Traits>
+ void dfs_kernel(const Index jj, IndexVector& perm_r,
+ Index& nseg, IndexVector& panel_lsub, IndexVector& segrep,
+ Ref<IndexVector> repfnz_col, IndexVector& xprune, Ref<IndexVector> marker, IndexVector& parent,
+ IndexVector& xplore, GlobalLU_t& glu, Index& nextl_col, Index krow, Traits& traits);
+ void panel_dfs(const Index m, const Index w, const Index jcol, MatrixType& A, IndexVector& perm_r, Index& nseg, ScalarVector& dense, IndexVector& panel_lsub, IndexVector& segrep, IndexVector& repfnz, IndexVector& xprune, IndexVector& marker, IndexVector& parent, IndexVector& xplore, GlobalLU_t& glu);
+
+ void panel_bmod(const Index m, const Index w, const Index jcol, const Index nseg, ScalarVector& dense, ScalarVector& tempv, IndexVector& segrep, IndexVector& repfnz, GlobalLU_t& glu);
+ Index column_dfs(const Index m, const Index jcol, IndexVector& perm_r, Index maxsuper, Index& nseg, BlockIndexVector lsub_col, IndexVector& segrep, BlockIndexVector repfnz, IndexVector& xprune, IndexVector& marker, IndexVector& parent, IndexVector& xplore, GlobalLU_t& glu);
+ Index column_bmod(const Index jcol, const Index nseg, BlockScalarVector dense, ScalarVector& tempv, BlockIndexVector segrep, BlockIndexVector repfnz, Index fpanelc, GlobalLU_t& glu);
+ Index copy_to_ucol(const Index jcol, const Index nseg, IndexVector& segrep, BlockIndexVector repfnz ,IndexVector& perm_r, BlockScalarVector dense, GlobalLU_t& glu);
+ void pruneL(const Index jcol, const IndexVector& perm_r, const Index pivrow, const Index nseg, const IndexVector& segrep, BlockIndexVector repfnz, IndexVector& xprune, GlobalLU_t& glu);
+ void countnz(const Index n, Index& nnzL, Index& nnzU, GlobalLU_t& glu);
+ void fixupL(const Index n, const IndexVector& perm_r, GlobalLU_t& glu);
+
+ template<typename , typename >
+ friend struct column_dfs_traits;
+};
+
+} // end namespace internal
+} // namespace Eigen
+
+#endif
diff --git a/Eigen/src/SparseLU/SparseLU_Memory.h b/Eigen/src/SparseLU/SparseLU_Memory.h
new file mode 100644
index 000000000..1ffa7d54e
--- /dev/null
+++ b/Eigen/src/SparseLU/SparseLU_Memory.h
@@ -0,0 +1,227 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/*
+
+ * NOTE: This file is the modified version of [s,d,c,z]memory.c files in SuperLU
+
+ * -- SuperLU routine (version 3.1) --
+ * Univ. of California Berkeley, Xerox Palo Alto Research Center,
+ * and Lawrence Berkeley National Lab.
+ * August 1, 2008
+ *
+ * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
+ * EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program for any
+ * purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is
+ * granted, provided the above notices are retained, and a notice that
+ * the code was modified is included with the above copyright notice.
+ */
+
+#ifndef EIGEN_SPARSELU_MEMORY
+#define EIGEN_SPARSELU_MEMORY
+
+namespace Eigen {
+namespace internal {
+
+enum { LUNoMarker = 3 };
+enum {emptyIdxLU = -1};
+template<typename Index>
+inline Index LUnumTempV(Index& m, Index& w, Index& t, Index& b)
+{
+ return (std::max)(m, (t+b)*w);
+}
+
+template< typename Scalar, typename Index>
+inline Index LUTempSpace(Index&m, Index& w)
+{
+ return (2*w + 4 + LUNoMarker) * m * sizeof(Index) + (w + 1) * m * sizeof(Scalar);
+}
+
+
+
+
+/**
+ * Expand the existing storage to accomodate more fill-ins
+ * \param vec Valid pointer to the vector to allocate or expand
+ * \param[in,out] length At input, contain the current length of the vector that is to be increased. At output, length of the newly allocated vector
+ * \param[in] nbElts Current number of elements in the factors
+ * \param keep_prev 1: use length and do not expand the vector; 0: compute new_len and expand
+ * \param[in,out] num_expansions Number of times the memory has been expanded
+ */
+template <typename Scalar, typename Index>
+template <typename VectorType>
+Index SparseLUImpl<Scalar,Index>::expand(VectorType& vec, Index& length, Index nbElts, Index keep_prev, Index& num_expansions)
+{
+
+ float alpha = 1.5; // Ratio of the memory increase
+ Index new_len; // New size of the allocated memory
+
+ if(num_expansions == 0 || keep_prev)
+ new_len = length ; // First time allocate requested
+ else
+ new_len = (std::max)(length+1,Index(alpha * length));
+
+ VectorType old_vec; // Temporary vector to hold the previous values
+ if (nbElts > 0 )
+ old_vec = vec.segment(0,nbElts);
+
+ //Allocate or expand the current vector
+#ifdef EIGEN_EXCEPTIONS
+ try
+#endif
+ {
+ vec.resize(new_len);
+ }
+#ifdef EIGEN_EXCEPTIONS
+ catch(std::bad_alloc& )
+#else
+ if(!vec.size())
+#endif
+ {
+ if (!num_expansions)
+ {
+ // First time to allocate from LUMemInit()
+ // Let LUMemInit() deals with it.
+ return -1;
+ }
+ if (keep_prev)
+ {
+ // In this case, the memory length should not not be reduced
+ return new_len;
+ }
+ else
+ {
+ // Reduce the size and increase again
+ Index tries = 0; // Number of attempts
+ do
+ {
+ alpha = (alpha + 1)/2;
+ new_len = (std::max)(length+1,Index(alpha * length));
+#ifdef EIGEN_EXCEPTIONS
+ try
+#endif
+ {
+ vec.resize(new_len);
+ }
+#ifdef EIGEN_EXCEPTIONS
+ catch(std::bad_alloc& )
+#else
+ if (!vec.size())
+#endif
+ {
+ tries += 1;
+ if ( tries > 10) return new_len;
+ }
+ } while (!vec.size());
+ }
+ }
+ //Copy the previous values to the newly allocated space
+ if (nbElts > 0)
+ vec.segment(0, nbElts) = old_vec;
+
+
+ length = new_len;
+ if(num_expansions) ++num_expansions;
+ return 0;
+}
+
+/**
+ * \brief Allocate various working space for the numerical factorization phase.
+ * \param m number of rows of the input matrix
+ * \param n number of columns
+ * \param annz number of initial nonzeros in the matrix
+ * \param lwork if lwork=-1, this routine returns an estimated size of the required memory
+ * \param glu persistent data to facilitate multiple factors : will be deleted later ??
+ * \param fillratio estimated ratio of fill in the factors
+ * \param panel_size Size of a panel
+ * \return an estimated size of the required memory if lwork = -1; otherwise, return the size of actually allocated memory when allocation failed, and 0 on success
+ * \note Unlike SuperLU, this routine does not support successive factorization with the same pattern and the same row permutation
+ */
+template <typename Scalar, typename Index>
+Index SparseLUImpl<Scalar,Index>::memInit(Index m, Index n, Index annz, Index lwork, Index fillratio, Index panel_size, GlobalLU_t& glu)
+{
+ Index& num_expansions = glu.num_expansions; //No memory expansions so far
+ num_expansions = 0;
+ glu.nzumax = glu.nzlumax = (std::min)(fillratio * annz / n, m) * n; // estimated number of nonzeros in U
+ glu.nzlmax = (std::max)(Index(4), fillratio) * annz / 4; // estimated nnz in L factor
+ // Return the estimated size to the user if necessary
+ Index tempSpace;
+ tempSpace = (2*panel_size + 4 + LUNoMarker) * m * sizeof(Index) + (panel_size + 1) * m * sizeof(Scalar);
+ if (lwork == emptyIdxLU)
+ {
+ Index estimated_size;
+ estimated_size = (5 * n + 5) * sizeof(Index) + tempSpace
+ + (glu.nzlmax + glu.nzumax) * sizeof(Index) + (glu.nzlumax+glu.nzumax) * sizeof(Scalar) + n;
+ return estimated_size;
+ }
+
+ // Setup the required space
+
+ // First allocate Integer pointers for L\U factors
+ glu.xsup.resize(n+1);
+ glu.supno.resize(n+1);
+ glu.xlsub.resize(n+1);
+ glu.xlusup.resize(n+1);
+ glu.xusub.resize(n+1);
+
+ // Reserve memory for L/U factors
+ do
+ {
+ if( (expand<ScalarVector>(glu.lusup, glu.nzlumax, 0, 0, num_expansions)<0)
+ || (expand<ScalarVector>(glu.ucol, glu.nzumax, 0, 0, num_expansions)<0)
+ || (expand<IndexVector> (glu.lsub, glu.nzlmax, 0, 0, num_expansions)<0)
+ || (expand<IndexVector> (glu.usub, glu.nzumax, 0, 1, num_expansions)<0) )
+ {
+ //Reduce the estimated size and retry
+ glu.nzlumax /= 2;
+ glu.nzumax /= 2;
+ glu.nzlmax /= 2;
+ if (glu.nzlumax < annz ) return glu.nzlumax;
+ }
+ } while (!glu.lusup.size() || !glu.ucol.size() || !glu.lsub.size() || !glu.usub.size());
+
+ ++num_expansions;
+ return 0;
+
+} // end LuMemInit
+
+/**
+ * \brief Expand the existing storage
+ * \param vec vector to expand
+ * \param[in,out] maxlen On input, previous size of vec (Number of elements to copy ). on output, new size
+ * \param nbElts current number of elements in the vector.
+ * \param memtype Type of the element to expand
+ * \param num_expansions Number of expansions
+ * \return 0 on success, > 0 size of the memory allocated so far
+ */
+template <typename Scalar, typename Index>
+template <typename VectorType>
+Index SparseLUImpl<Scalar,Index>::memXpand(VectorType& vec, Index& maxlen, Index nbElts, MemType memtype, Index& num_expansions)
+{
+ Index failed_size;
+ if (memtype == USUB)
+ failed_size = this->expand<VectorType>(vec, maxlen, nbElts, 1, num_expansions);
+ else
+ failed_size = this->expand<VectorType>(vec, maxlen, nbElts, 0, num_expansions);
+
+ if (failed_size)
+ return failed_size;
+
+ return 0 ;
+}
+
+} // end namespace internal
+
+} // end namespace Eigen
+#endif // EIGEN_SPARSELU_MEMORY
diff --git a/Eigen/src/SparseLU/SparseLU_Structs.h b/Eigen/src/SparseLU/SparseLU_Structs.h
new file mode 100644
index 000000000..24d6bf179
--- /dev/null
+++ b/Eigen/src/SparseLU/SparseLU_Structs.h
@@ -0,0 +1,111 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/*
+ * NOTE: This file comes from a partly modified version of files slu_[s,d,c,z]defs.h
+ * -- SuperLU routine (version 4.1) --
+ * Univ. of California Berkeley, Xerox Palo Alto Research Center,
+ * and Lawrence Berkeley National Lab.
+ * November, 2010
+ *
+ * Global data structures used in LU factorization -
+ *
+ * nsuper: #supernodes = nsuper + 1, numbered [0, nsuper].
+ * (xsup,supno): supno[i] is the supernode no to which i belongs;
+ * xsup(s) points to the beginning of the s-th supernode.
+ * e.g. supno 0 1 2 2 3 3 3 4 4 4 4 4 (n=12)
+ * xsup 0 1 2 4 7 12
+ * Note: dfs will be performed on supernode rep. relative to the new
+ * row pivoting ordering
+ *
+ * (xlsub,lsub): lsub[*] contains the compressed subscript of
+ * rectangular supernodes; xlsub[j] points to the starting
+ * location of the j-th column in lsub[*]. Note that xlsub
+ * is indexed by column.
+ * Storage: original row subscripts
+ *
+ * During the course of sparse LU factorization, we also use
+ * (xlsub,lsub) for the purpose of symmetric pruning. For each
+ * supernode {s,s+1,...,t=s+r} with first column s and last
+ * column t, the subscript set
+ * lsub[j], j=xlsub[s], .., xlsub[s+1]-1
+ * is the structure of column s (i.e. structure of this supernode).
+ * It is used for the storage of numerical values.
+ * Furthermore,
+ * lsub[j], j=xlsub[t], .., xlsub[t+1]-1
+ * is the structure of the last column t of this supernode.
+ * It is for the purpose of symmetric pruning. Therefore, the
+ * structural subscripts can be rearranged without making physical
+ * interchanges among the numerical values.
+ *
+ * However, if the supernode has only one column, then we
+ * only keep one set of subscripts. For any subscript interchange
+ * performed, similar interchange must be done on the numerical
+ * values.
+ *
+ * The last column structures (for pruning) will be removed
+ * after the numercial LU factorization phase.
+ *
+ * (xlusup,lusup): lusup[*] contains the numerical values of the
+ * rectangular supernodes; xlusup[j] points to the starting
+ * location of the j-th column in storage vector lusup[*]
+ * Note: xlusup is indexed by column.
+ * Each rectangular supernode is stored by column-major
+ * scheme, consistent with Fortran 2-dim array storage.
+ *
+ * (xusub,ucol,usub): ucol[*] stores the numerical values of
+ * U-columns outside the rectangular supernodes. The row
+ * subscript of nonzero ucol[k] is stored in usub[k].
+ * xusub[i] points to the starting location of column i in ucol.
+ * Storage: new row subscripts; that is subscripts of PA.
+ */
+
+#ifndef EIGEN_LU_STRUCTS
+#define EIGEN_LU_STRUCTS
+namespace Eigen {
+namespace internal {
+
+typedef enum {LUSUP, UCOL, LSUB, USUB, LLVL, ULVL} MemType;
+
+template <typename IndexVector, typename ScalarVector>
+struct LU_GlobalLU_t {
+ typedef typename IndexVector::Scalar Index;
+ IndexVector xsup; //First supernode column ... xsup(s) points to the beginning of the s-th supernode
+ IndexVector supno; // Supernode number corresponding to this column (column to supernode mapping)
+ ScalarVector lusup; // nonzero values of L ordered by columns
+ IndexVector lsub; // Compressed row indices of L rectangular supernodes.
+ IndexVector xlusup; // pointers to the beginning of each column in lusup
+ IndexVector xlsub; // pointers to the beginning of each column in lsub
+ Index nzlmax; // Current max size of lsub
+ Index nzlumax; // Current max size of lusup
+ ScalarVector ucol; // nonzero values of U ordered by columns
+ IndexVector usub; // row indices of U columns in ucol
+ IndexVector xusub; // Pointers to the beginning of each column of U in ucol
+ Index nzumax; // Current max size of ucol
+ Index n; // Number of columns in the matrix
+ Index num_expansions;
+};
+
+// Values to set for performance
+template <typename Index>
+struct perfvalues {
+ Index panel_size; // a panel consists of at most <panel_size> consecutive columns
+ Index relax; // To control degree of relaxing supernodes. If the number of nodes (columns)
+ // in a subtree of the elimination tree is less than relax, this subtree is considered
+ // as one supernode regardless of the row structures of those columns
+ Index maxsuper; // The maximum size for a supernode in complete LU
+ Index rowblk; // The minimum row dimension for 2-D blocking to be used;
+ Index colblk; // The minimum column dimension for 2-D blocking to be used;
+ Index fillfactor; // The estimated fills factors for L and U, compared with A
+};
+
+} // end namespace internal
+
+} // end namespace Eigen
+#endif // EIGEN_LU_STRUCTS
diff --git a/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h b/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h
new file mode 100644
index 000000000..ad6f2183f
--- /dev/null
+++ b/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h
@@ -0,0 +1,298 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+// Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef EIGEN_SPARSELU_SUPERNODAL_MATRIX_H
+#define EIGEN_SPARSELU_SUPERNODAL_MATRIX_H
+
+namespace Eigen {
+namespace internal {
+
+/** \ingroup SparseLU_Module
+ * \brief a class to manipulate the L supernodal factor from the SparseLU factorization
+ *
+ * This class contain the data to easily store
+ * and manipulate the supernodes during the factorization and solution phase of Sparse LU.
+ * Only the lower triangular matrix has supernodes.
+ *
+ * NOTE : This class corresponds to the SCformat structure in SuperLU
+ *
+ */
+/* TODO
+ * InnerIterator as for sparsematrix
+ * SuperInnerIterator to iterate through all supernodes
+ * Function for triangular solve
+ */
+template <typename _Scalar, typename _Index>
+class MappedSuperNodalMatrix
+{
+ public:
+ typedef _Scalar Scalar;
+ typedef _Index Index;
+ typedef Matrix<Index,Dynamic,1> IndexVector;
+ typedef Matrix<Scalar,Dynamic,1> ScalarVector;
+ public:
+ MappedSuperNodalMatrix()
+ {
+
+ }
+ MappedSuperNodalMatrix(Index m, Index n, ScalarVector& nzval, IndexVector& nzval_colptr, IndexVector& rowind,
+ IndexVector& rowind_colptr, IndexVector& col_to_sup, IndexVector& sup_to_col )
+ {
+ setInfos(m, n, nzval, nzval_colptr, rowind, rowind_colptr, col_to_sup, sup_to_col);
+ }
+
+ ~MappedSuperNodalMatrix()
+ {
+
+ }
+ /**
+ * Set appropriate pointers for the lower triangular supernodal matrix
+ * These infos are available at the end of the numerical factorization
+ * FIXME This class will be modified such that it can be use in the course
+ * of the factorization.
+ */
+ void setInfos(Index m, Index n, ScalarVector& nzval, IndexVector& nzval_colptr, IndexVector& rowind,
+ IndexVector& rowind_colptr, IndexVector& col_to_sup, IndexVector& sup_to_col )
+ {
+ m_row = m;
+ m_col = n;
+ m_nzval = nzval.data();
+ m_nzval_colptr = nzval_colptr.data();
+ m_rowind = rowind.data();
+ m_rowind_colptr = rowind_colptr.data();
+ m_nsuper = col_to_sup(n);
+ m_col_to_sup = col_to_sup.data();
+ m_sup_to_col = sup_to_col.data();
+ }
+
+ /**
+ * Number of rows
+ */
+ Index rows() { return m_row; }
+
+ /**
+ * Number of columns
+ */
+ Index cols() { return m_col; }
+
+ /**
+ * Return the array of nonzero values packed by column
+ *
+ * The size is nnz
+ */
+ Scalar* valuePtr() { return m_nzval; }
+
+ const Scalar* valuePtr() const
+ {
+ return m_nzval;
+ }
+ /**
+ * Return the pointers to the beginning of each column in \ref valuePtr()
+ */
+ Index* colIndexPtr()
+ {
+ return m_nzval_colptr;
+ }
+
+ const Index* colIndexPtr() const
+ {
+ return m_nzval_colptr;
+ }
+
+ /**
+ * Return the array of compressed row indices of all supernodes
+ */
+ Index* rowIndex() { return m_rowind; }
+
+ const Index* rowIndex() const
+ {
+ return m_rowind;
+ }
+
+ /**
+ * Return the location in \em rowvaluePtr() which starts each column
+ */
+ Index* rowIndexPtr() { return m_rowind_colptr; }
+
+ const Index* rowIndexPtr() const
+ {
+ return m_rowind_colptr;
+ }
+
+ /**
+ * Return the array of column-to-supernode mapping
+ */
+ Index* colToSup() { return m_col_to_sup; }
+
+ const Index* colToSup() const
+ {
+ return m_col_to_sup;
+ }
+ /**
+ * Return the array of supernode-to-column mapping
+ */
+ Index* supToCol() { return m_sup_to_col; }
+
+ const Index* supToCol() const
+ {
+ return m_sup_to_col;
+ }
+
+ /**
+ * Return the number of supernodes
+ */
+ Index nsuper() const
+ {
+ return m_nsuper;
+ }
+
+ class InnerIterator;
+ template<typename Dest>
+ void solveInPlace( MatrixBase<Dest>&X) const;
+
+
+
+
+ protected:
+ Index m_row; // Number of rows
+ Index m_col; // Number of columns
+ Index m_nsuper; // Number of supernodes
+ Scalar* m_nzval; //array of nonzero values packed by column
+ Index* m_nzval_colptr; //nzval_colptr[j] Stores the location in nzval[] which starts column j
+ Index* m_rowind; // Array of compressed row indices of rectangular supernodes
+ Index* m_rowind_colptr; //rowind_colptr[j] stores the location in rowind[] which starts column j
+ Index* m_col_to_sup; // col_to_sup[j] is the supernode number to which column j belongs
+ Index* m_sup_to_col; //sup_to_col[s] points to the starting column of the s-th supernode
+
+ private :
+};
+
+/**
+ * \brief InnerIterator class to iterate over nonzero values of the current column in the supernodal matrix L
+ *
+ */
+template<typename Scalar, typename Index>
+class MappedSuperNodalMatrix<Scalar,Index>::InnerIterator
+{
+ public:
+ InnerIterator(const MappedSuperNodalMatrix& mat, Index outer)
+ : m_matrix(mat),
+ m_outer(outer),
+ m_supno(mat.colToSup()[outer]),
+ m_idval(mat.colIndexPtr()[outer]),
+ m_startidval(m_idval),
+ m_endidval(mat.colIndexPtr()[outer+1]),
+ m_idrow(mat.rowIndexPtr()[outer]),
+ m_endidrow(mat.rowIndexPtr()[outer+1])
+ {}
+ inline InnerIterator& operator++()
+ {
+ m_idval++;
+ m_idrow++;
+ return *this;
+ }
+ inline Scalar value() const { return m_matrix.valuePtr()[m_idval]; }
+
+ inline Scalar& valueRef() { return const_cast<Scalar&>(m_matrix.valuePtr()[m_idval]); }
+
+ inline Index index() const { return m_matrix.rowIndex()[m_idrow]; }
+ inline Index row() const { return index(); }
+ inline Index col() const { return m_outer; }
+
+ inline Index supIndex() const { return m_supno; }
+
+ inline operator bool() const
+ {
+ return ( (m_idval < m_endidval) && (m_idval >= m_startidval)
+ && (m_idrow < m_endidrow) );
+ }
+
+ protected:
+ const MappedSuperNodalMatrix& m_matrix; // Supernodal lower triangular matrix
+ const Index m_outer; // Current column
+ const Index m_supno; // Current SuperNode number
+ Index m_idval; // Index to browse the values in the current column
+ const Index m_startidval; // Start of the column value
+ const Index m_endidval; // End of the column value
+ Index m_idrow; // Index to browse the row indices
+ Index m_endidrow; // End index of row indices of the current column
+};
+
+/**
+ * \brief Solve with the supernode triangular matrix
+ *
+ */
+template<typename Scalar, typename Index>
+template<typename Dest>
+void MappedSuperNodalMatrix<Scalar,Index>::solveInPlace( MatrixBase<Dest>&X) const
+{
+ Index n = X.rows();
+ Index nrhs = X.cols();
+ const Scalar * Lval = valuePtr(); // Nonzero values
+ Matrix<Scalar,Dynamic,Dynamic> work(n, nrhs); // working vector
+ work.setZero();
+ for (Index k = 0; k <= nsuper(); k ++)
+ {
+ Index fsupc = supToCol()[k]; // First column of the current supernode
+ Index istart = rowIndexPtr()[fsupc]; // Pointer index to the subscript of the current column
+ Index nsupr = rowIndexPtr()[fsupc+1] - istart; // Number of rows in the current supernode
+ Index nsupc = supToCol()[k+1] - fsupc; // Number of columns in the current supernode
+ Index nrow = nsupr - nsupc; // Number of rows in the non-diagonal part of the supernode
+ Index irow; //Current index row
+
+ if (nsupc == 1 )
+ {
+ for (Index j = 0; j < nrhs; j++)
+ {
+ InnerIterator it(*this, fsupc);
+ ++it; // Skip the diagonal element
+ for (; it; ++it)
+ {
+ irow = it.row();
+ X(irow, j) -= X(fsupc, j) * it.value();
+ }
+ }
+ }
+ else
+ {
+ // The supernode has more than one column
+ Index luptr = colIndexPtr()[fsupc];
+ Index lda = colIndexPtr()[fsupc+1] - luptr;
+
+ // Triangular solve
+ Map<const Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > A( &(Lval[luptr]), nsupc, nsupc, OuterStride<>(lda) );
+ Map< Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > U (&(X(fsupc,0)), nsupc, nrhs, OuterStride<>(n) );
+ U = A.template triangularView<UnitLower>().solve(U);
+
+ // Matrix-vector product
+ new (&A) Map<const Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > ( &(Lval[luptr+nsupc]), nrow, nsupc, OuterStride<>(lda) );
+ work.block(0, 0, nrow, nrhs) = A * U;
+
+ //Begin Scatter
+ for (Index j = 0; j < nrhs; j++)
+ {
+ Index iptr = istart + nsupc;
+ for (Index i = 0; i < nrow; i++)
+ {
+ irow = rowIndex()[iptr];
+ X(irow, j) -= work(i, j); // Scatter operation
+ work(i, j) = Scalar(0);
+ iptr++;
+ }
+ }
+ }
+ }
+}
+
+} // end namespace internal
+
+} // end namespace Eigen
+
+#endif // EIGEN_SPARSELU_MATRIX_H
diff --git a/Eigen/src/SparseLU/SparseLU_Utils.h b/Eigen/src/SparseLU/SparseLU_Utils.h
new file mode 100644
index 000000000..15352ac33
--- /dev/null
+++ b/Eigen/src/SparseLU/SparseLU_Utils.h
@@ -0,0 +1,80 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+
+#ifndef EIGEN_SPARSELU_UTILS_H
+#define EIGEN_SPARSELU_UTILS_H
+
+namespace Eigen {
+namespace internal {
+
+/**
+ * \brief Count Nonzero elements in the factors
+ */
+template <typename Scalar, typename Index>
+void SparseLUImpl<Scalar,Index>::countnz(const Index n, Index& nnzL, Index& nnzU, GlobalLU_t& glu)
+{
+ nnzL = 0;
+ nnzU = (glu.xusub)(n);
+ Index nsuper = (glu.supno)(n);
+ Index jlen;
+ Index i, j, fsupc;
+ if (n <= 0 ) return;
+ // For each supernode
+ for (i = 0; i <= nsuper; i++)
+ {
+ fsupc = glu.xsup(i);
+ jlen = glu.xlsub(fsupc+1) - glu.xlsub(fsupc);
+
+ for (j = fsupc; j < glu.xsup(i+1); j++)
+ {
+ nnzL += jlen;
+ nnzU += j - fsupc + 1;
+ jlen--;
+ }
+ }
+}
+
+/**
+ * \brief Fix up the data storage lsub for L-subscripts.
+ *
+ * It removes the subscripts sets for structural pruning,
+ * and applies permutation to the remaining subscripts
+ *
+ */
+template <typename Scalar, typename Index>
+void SparseLUImpl<Scalar,Index>::fixupL(const Index n, const IndexVector& perm_r, GlobalLU_t& glu)
+{
+ Index fsupc, i, j, k, jstart;
+
+ Index nextl = 0;
+ Index nsuper = (glu.supno)(n);
+
+ // For each supernode
+ for (i = 0; i <= nsuper; i++)
+ {
+ fsupc = glu.xsup(i);
+ jstart = glu.xlsub(fsupc);
+ glu.xlsub(fsupc) = nextl;
+ for (j = jstart; j < glu.xlsub(fsupc + 1); j++)
+ {
+ glu.lsub(nextl) = perm_r(glu.lsub(j)); // Now indexed into P*A
+ nextl++;
+ }
+ for (k = fsupc+1; k < glu.xsup(i+1); k++)
+ glu.xlsub(k) = nextl; // other columns in supernode i
+ }
+
+ glu.xlsub(n) = nextl;
+}
+
+} // end namespace internal
+
+} // end namespace Eigen
+#endif // EIGEN_SPARSELU_UTILS_H
diff --git a/Eigen/src/SparseLU/SparseLU_column_bmod.h b/Eigen/src/SparseLU/SparseLU_column_bmod.h
new file mode 100644
index 000000000..f24bd87d3
--- /dev/null
+++ b/Eigen/src/SparseLU/SparseLU_column_bmod.h
@@ -0,0 +1,180 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+// Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/*
+
+ * NOTE: This file is the modified version of xcolumn_bmod.c file in SuperLU
+
+ * -- SuperLU routine (version 3.0) --
+ * Univ. of California Berkeley, Xerox Palo Alto Research Center,
+ * and Lawrence Berkeley National Lab.
+ * October 15, 2003
+ *
+ * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
+ * EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program for any
+ * purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is
+ * granted, provided the above notices are retained, and a notice that
+ * the code was modified is included with the above copyright notice.
+ */
+#ifndef SPARSELU_COLUMN_BMOD_H
+#define SPARSELU_COLUMN_BMOD_H
+
+namespace Eigen {
+
+namespace internal {
+/**
+ * \brief Performs numeric block updates (sup-col) in topological order
+ *
+ * \param jcol current column to update
+ * \param nseg Number of segments in the U part
+ * \param dense Store the full representation of the column
+ * \param tempv working array
+ * \param segrep segment representative ...
+ * \param repfnz ??? First nonzero column in each row ??? ...
+ * \param fpanelc First column in the current panel
+ * \param glu Global LU data.
+ * \return 0 - successful return
+ * > 0 - number of bytes allocated when run out of space
+ *
+ */
+template <typename Scalar, typename Index>
+Index SparseLUImpl<Scalar,Index>::column_bmod(const Index jcol, const Index nseg, BlockScalarVector dense, ScalarVector& tempv, BlockIndexVector segrep, BlockIndexVector repfnz, Index fpanelc, GlobalLU_t& glu)
+{
+ Index jsupno, k, ksub, krep, ksupno;
+ Index lptr, nrow, isub, irow, nextlu, new_next, ufirst;
+ Index fsupc, nsupc, nsupr, luptr, kfnz, no_zeros;
+ /* krep = representative of current k-th supernode
+ * fsupc = first supernodal column
+ * nsupc = number of columns in a supernode
+ * nsupr = number of rows in a supernode
+ * luptr = location of supernodal LU-block in storage
+ * kfnz = first nonz in the k-th supernodal segment
+ * no_zeros = no lf leading zeros in a supernodal U-segment
+ */
+
+ jsupno = glu.supno(jcol);
+ // For each nonzero supernode segment of U[*,j] in topological order
+ k = nseg - 1;
+ Index d_fsupc; // distance between the first column of the current panel and the
+ // first column of the current snode
+ Index fst_col; // First column within small LU update
+ Index segsize;
+ for (ksub = 0; ksub < nseg; ksub++)
+ {
+ krep = segrep(k); k--;
+ ksupno = glu.supno(krep);
+ if (jsupno != ksupno )
+ {
+ // outside the rectangular supernode
+ fsupc = glu.xsup(ksupno);
+ fst_col = (std::max)(fsupc, fpanelc);
+
+ // Distance from the current supernode to the current panel;
+ // d_fsupc = 0 if fsupc > fpanelc
+ d_fsupc = fst_col - fsupc;
+
+ luptr = glu.xlusup(fst_col) + d_fsupc;
+ lptr = glu.xlsub(fsupc) + d_fsupc;
+
+ kfnz = repfnz(krep);
+ kfnz = (std::max)(kfnz, fpanelc);
+
+ segsize = krep - kfnz + 1;
+ nsupc = krep - fst_col + 1;
+ nsupr = glu.xlsub(fsupc+1) - glu.xlsub(fsupc);
+ nrow = nsupr - d_fsupc - nsupc;
+ Index lda = glu.xlusup(fst_col+1) - glu.xlusup(fst_col);
+
+
+ // Perform a triangular solver and block update,
+ // then scatter the result of sup-col update to dense
+ no_zeros = kfnz - fst_col;
+ if(segsize==1)
+ LU_kernel_bmod<1>::run(segsize, dense, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
+ else
+ LU_kernel_bmod<Dynamic>::run(segsize, dense, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
+ } // end if jsupno
+ } // end for each segment
+
+ // Process the supernodal portion of L\U[*,j]
+ nextlu = glu.xlusup(jcol);
+ fsupc = glu.xsup(jsupno);
+
+ // copy the SPA dense into L\U[*,j]
+ Index mem;
+ new_next = nextlu + glu.xlsub(fsupc + 1) - glu.xlsub(fsupc);
+ Index offset = internal::first_multiple<Index>(new_next, internal::packet_traits<Scalar>::size) - new_next;
+ if(offset)
+ new_next += offset;
+ while (new_next > glu.nzlumax )
+ {
+ mem = memXpand<ScalarVector>(glu.lusup, glu.nzlumax, nextlu, LUSUP, glu.num_expansions);
+ if (mem) return mem;
+ }
+
+ for (isub = glu.xlsub(fsupc); isub < glu.xlsub(fsupc+1); isub++)
+ {
+ irow = glu.lsub(isub);
+ glu.lusup(nextlu) = dense(irow);
+ dense(irow) = Scalar(0.0);
+ ++nextlu;
+ }
+
+ if(offset)
+ {
+ glu.lusup.segment(nextlu,offset).setZero();
+ nextlu += offset;
+ }
+ glu.xlusup(jcol + 1) = nextlu; // close L\U(*,jcol);
+
+ /* For more updates within the panel (also within the current supernode),
+ * should start from the first column of the panel, or the first column
+ * of the supernode, whichever is bigger. There are two cases:
+ * 1) fsupc < fpanelc, then fst_col <-- fpanelc
+ * 2) fsupc >= fpanelc, then fst_col <-- fsupc
+ */
+ fst_col = (std::max)(fsupc, fpanelc);
+
+ if (fst_col < jcol)
+ {
+ // Distance between the current supernode and the current panel
+ // d_fsupc = 0 if fsupc >= fpanelc
+ d_fsupc = fst_col - fsupc;
+
+ lptr = glu.xlsub(fsupc) + d_fsupc;
+ luptr = glu.xlusup(fst_col) + d_fsupc;
+ nsupr = glu.xlsub(fsupc+1) - glu.xlsub(fsupc); // leading dimension
+ nsupc = jcol - fst_col; // excluding jcol
+ nrow = nsupr - d_fsupc - nsupc;
+
+ // points to the beginning of jcol in snode L\U(jsupno)
+ ufirst = glu.xlusup(jcol) + d_fsupc;
+ Index lda = glu.xlusup(jcol+1) - glu.xlusup(jcol);
+ Map<Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > A( &(glu.lusup.data()[luptr]), nsupc, nsupc, OuterStride<>(lda) );
+ VectorBlock<ScalarVector> u(glu.lusup, ufirst, nsupc);
+ u = A.template triangularView<UnitLower>().solve(u);
+
+ new (&A) Map<Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > ( &(glu.lusup.data()[luptr+nsupc]), nrow, nsupc, OuterStride<>(lda) );
+ VectorBlock<ScalarVector> l(glu.lusup, ufirst+nsupc, nrow);
+ l.noalias() -= A * u;
+
+ } // End if fst_col
+ return 0;
+}
+
+} // end namespace internal
+} // end namespace Eigen
+
+#endif // SPARSELU_COLUMN_BMOD_H
diff --git a/Eigen/src/SparseLU/SparseLU_column_dfs.h b/Eigen/src/SparseLU/SparseLU_column_dfs.h
new file mode 100644
index 000000000..4c04b0e44
--- /dev/null
+++ b/Eigen/src/SparseLU/SparseLU_column_dfs.h
@@ -0,0 +1,177 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/*
+
+ * NOTE: This file is the modified version of [s,d,c,z]column_dfs.c file in SuperLU
+
+ * -- SuperLU routine (version 2.0) --
+ * Univ. of California Berkeley, Xerox Palo Alto Research Center,
+ * and Lawrence Berkeley National Lab.
+ * November 15, 1997
+ *
+ * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
+ * EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program for any
+ * purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is
+ * granted, provided the above notices are retained, and a notice that
+ * the code was modified is included with the above copyright notice.
+ */
+#ifndef SPARSELU_COLUMN_DFS_H
+#define SPARSELU_COLUMN_DFS_H
+
+template <typename Scalar, typename Index> class SparseLUImpl;
+namespace Eigen {
+
+namespace internal {
+
+template<typename IndexVector, typename ScalarVector>
+struct column_dfs_traits : no_assignment_operator
+{
+ typedef typename ScalarVector::Scalar Scalar;
+ typedef typename IndexVector::Scalar Index;
+ column_dfs_traits(Index jcol, Index& jsuper, typename SparseLUImpl<Scalar, Index>::GlobalLU_t& glu, SparseLUImpl<Scalar, Index>& luImpl)
+ : m_jcol(jcol), m_jsuper_ref(jsuper), m_glu(glu), m_luImpl(luImpl)
+ {}
+ bool update_segrep(Index /*krep*/, Index /*jj*/)
+ {
+ return true;
+ }
+ void mem_expand(IndexVector& lsub, Index& nextl, Index chmark)
+ {
+ if (nextl >= m_glu.nzlmax)
+ m_luImpl.memXpand(lsub, m_glu.nzlmax, nextl, LSUB, m_glu.num_expansions);
+ if (chmark != (m_jcol-1)) m_jsuper_ref = emptyIdxLU;
+ }
+ enum { ExpandMem = true };
+
+ Index m_jcol;
+ Index& m_jsuper_ref;
+ typename SparseLUImpl<Scalar, Index>::GlobalLU_t& m_glu;
+ SparseLUImpl<Scalar, Index>& m_luImpl;
+};
+
+
+/**
+ * \brief Performs a symbolic factorization on column jcol and decide the supernode boundary
+ *
+ * A supernode representative is the last column of a supernode.
+ * The nonzeros in U[*,j] are segments that end at supernodes representatives.
+ * The routine returns a list of the supernodal representatives
+ * in topological order of the dfs that generates them.
+ * The location of the first nonzero in each supernodal segment
+ * (supernodal entry location) is also returned.
+ *
+ * \param m number of rows in the matrix
+ * \param jcol Current column
+ * \param perm_r Row permutation
+ * \param maxsuper Maximum number of column allowed in a supernode
+ * \param [in,out] nseg Number of segments in current U[*,j] - new segments appended
+ * \param lsub_col defines the rhs vector to start the dfs
+ * \param [in,out] segrep Segment representatives - new segments appended
+ * \param repfnz First nonzero location in each row
+ * \param xprune
+ * \param marker marker[i] == jj, if i was visited during dfs of current column jj;
+ * \param parent
+ * \param xplore working array
+ * \param glu global LU data
+ * \return 0 success
+ * > 0 number of bytes allocated when run out of space
+ *
+ */
+template <typename Scalar, typename Index>
+Index SparseLUImpl<Scalar,Index>::column_dfs(const Index m, const Index jcol, IndexVector& perm_r, Index maxsuper, Index& nseg, BlockIndexVector lsub_col, IndexVector& segrep, BlockIndexVector repfnz, IndexVector& xprune, IndexVector& marker, IndexVector& parent, IndexVector& xplore, GlobalLU_t& glu)
+{
+
+ Index jsuper = glu.supno(jcol);
+ Index nextl = glu.xlsub(jcol);
+ VectorBlock<IndexVector> marker2(marker, 2*m, m);
+
+
+ column_dfs_traits<IndexVector, ScalarVector> traits(jcol, jsuper, glu, *this);
+
+ // For each nonzero in A(*,jcol) do dfs
+ for (Index k = 0; ((k < m) ? lsub_col[k] != emptyIdxLU : false) ; k++)
+ {
+ Index krow = lsub_col(k);
+ lsub_col(k) = emptyIdxLU;
+ Index kmark = marker2(krow);
+
+ // krow was visited before, go to the next nonz;
+ if (kmark == jcol) continue;
+
+ dfs_kernel(jcol, perm_r, nseg, glu.lsub, segrep, repfnz, xprune, marker2, parent,
+ xplore, glu, nextl, krow, traits);
+ } // for each nonzero ...
+
+ Index fsupc, jptr, jm1ptr, ito, ifrom, istop;
+ Index nsuper = glu.supno(jcol);
+ Index jcolp1 = jcol + 1;
+ Index jcolm1 = jcol - 1;
+
+ // check to see if j belongs in the same supernode as j-1
+ if ( jcol == 0 )
+ { // Do nothing for column 0
+ nsuper = glu.supno(0) = 0 ;
+ }
+ else
+ {
+ fsupc = glu.xsup(nsuper);
+ jptr = glu.xlsub(jcol); // Not yet compressed
+ jm1ptr = glu.xlsub(jcolm1);
+
+ // Use supernodes of type T2 : see SuperLU paper
+ if ( (nextl-jptr != jptr-jm1ptr-1) ) jsuper = emptyIdxLU;
+
+ // Make sure the number of columns in a supernode doesn't
+ // exceed threshold
+ if ( (jcol - fsupc) >= maxsuper) jsuper = emptyIdxLU;
+
+ /* If jcol starts a new supernode, reclaim storage space in
+ * glu.lsub from previous supernode. Note we only store
+ * the subscript set of the first and last columns of
+ * a supernode. (first for num values, last for pruning)
+ */
+ if (jsuper == emptyIdxLU)
+ { // starts a new supernode
+ if ( (fsupc < jcolm1-1) )
+ { // >= 3 columns in nsuper
+ ito = glu.xlsub(fsupc+1);
+ glu.xlsub(jcolm1) = ito;
+ istop = ito + jptr - jm1ptr;
+ xprune(jcolm1) = istop; // intialize xprune(jcol-1)
+ glu.xlsub(jcol) = istop;
+
+ for (ifrom = jm1ptr; ifrom < nextl; ++ifrom, ++ito)
+ glu.lsub(ito) = glu.lsub(ifrom);
+ nextl = ito; // = istop + length(jcol)
+ }
+ nsuper++;
+ glu.supno(jcol) = nsuper;
+ } // if a new supernode
+ } // end else: jcol > 0
+
+ // Tidy up the pointers before exit
+ glu.xsup(nsuper+1) = jcolp1;
+ glu.supno(jcolp1) = nsuper;
+ xprune(jcol) = nextl; // Intialize upper bound for pruning
+ glu.xlsub(jcolp1) = nextl;
+
+ return 0;
+}
+
+} // end namespace internal
+
+} // end namespace Eigen
+
+#endif
diff --git a/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h b/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h
new file mode 100644
index 000000000..170610d9f
--- /dev/null
+++ b/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h
@@ -0,0 +1,106 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+/*
+
+ * NOTE: This file is the modified version of [s,d,c,z]copy_to_ucol.c file in SuperLU
+
+ * -- SuperLU routine (version 2.0) --
+ * Univ. of California Berkeley, Xerox Palo Alto Research Center,
+ * and Lawrence Berkeley National Lab.
+ * November 15, 1997
+ *
+ * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
+ * EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program for any
+ * purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is
+ * granted, provided the above notices are retained, and a notice that
+ * the code was modified is included with the above copyright notice.
+ */
+#ifndef SPARSELU_COPY_TO_UCOL_H
+#define SPARSELU_COPY_TO_UCOL_H
+
+namespace Eigen {
+namespace internal {
+
+/**
+ * \brief Performs numeric block updates (sup-col) in topological order
+ *
+ * \param jcol current column to update
+ * \param nseg Number of segments in the U part
+ * \param segrep segment representative ...
+ * \param repfnz First nonzero column in each row ...
+ * \param perm_r Row permutation
+ * \param dense Store the full representation of the column
+ * \param glu Global LU data.
+ * \return 0 - successful return
+ * > 0 - number of bytes allocated when run out of space
+ *
+ */
+template <typename Scalar, typename Index>
+Index SparseLUImpl<Scalar,Index>::copy_to_ucol(const Index jcol, const Index nseg, IndexVector& segrep, BlockIndexVector repfnz ,IndexVector& perm_r, BlockScalarVector dense, GlobalLU_t& glu)
+{
+ Index ksub, krep, ksupno;
+
+ Index jsupno = glu.supno(jcol);
+
+ // For each nonzero supernode segment of U[*,j] in topological order
+ Index k = nseg - 1, i;
+ Index nextu = glu.xusub(jcol);
+ Index kfnz, isub, segsize;
+ Index new_next,irow;
+ Index fsupc, mem;
+ for (ksub = 0; ksub < nseg; ksub++)
+ {
+ krep = segrep(k); k--;
+ ksupno = glu.supno(krep);
+ if (jsupno != ksupno ) // should go into ucol();
+ {
+ kfnz = repfnz(krep);
+ if (kfnz != emptyIdxLU)
+ { // Nonzero U-segment
+ fsupc = glu.xsup(ksupno);
+ isub = glu.xlsub(fsupc) + kfnz - fsupc;
+ segsize = krep - kfnz + 1;
+ new_next = nextu + segsize;
+ while (new_next > glu.nzumax)
+ {
+ mem = memXpand<ScalarVector>(glu.ucol, glu.nzumax, nextu, UCOL, glu.num_expansions);
+ if (mem) return mem;
+ mem = memXpand<IndexVector>(glu.usub, glu.nzumax, nextu, USUB, glu.num_expansions);
+ if (mem) return mem;
+
+ }
+
+ for (i = 0; i < segsize; i++)
+ {
+ irow = glu.lsub(isub);
+ glu.usub(nextu) = perm_r(irow); // Unlike the L part, the U part is stored in its final order
+ glu.ucol(nextu) = dense(irow);
+ dense(irow) = Scalar(0.0);
+ nextu++;
+ isub++;
+ }
+
+ } // end nonzero U-segment
+
+ } // end if jsupno
+
+ } // end for each segment
+ glu.xusub(jcol + 1) = nextu; // close U(*,jcol)
+ return 0;
+}
+
+} // namespace internal
+} // end namespace Eigen
+
+#endif // SPARSELU_COPY_TO_UCOL_H
diff --git a/Eigen/src/SparseLU/SparseLU_gemm_kernel.h b/Eigen/src/SparseLU/SparseLU_gemm_kernel.h
new file mode 100644
index 000000000..9e4e3e72b
--- /dev/null
+++ b/Eigen/src/SparseLU/SparseLU_gemm_kernel.h
@@ -0,0 +1,279 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef EIGEN_SPARSELU_GEMM_KERNEL_H
+#define EIGEN_SPARSELU_GEMM_KERNEL_H
+
+namespace Eigen {
+
+namespace internal {
+
+
+/** \internal
+ * A general matrix-matrix product kernel optimized for the SparseLU factorization.
+ * - A, B, and C must be column major
+ * - lda and ldc must be multiples of the respective packet size
+ * - C must have the same alignment as A
+ */
+template<typename Scalar,typename Index>
+EIGEN_DONT_INLINE
+void sparselu_gemm(Index m, Index n, Index d, const Scalar* A, Index lda, const Scalar* B, Index ldb, Scalar* C, Index ldc)
+{
+ using namespace Eigen::internal;
+
+ typedef typename packet_traits<Scalar>::type Packet;
+ enum {
+ NumberOfRegisters = EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS,
+ PacketSize = packet_traits<Scalar>::size,
+ PM = 8, // peeling in M
+ RN = 2, // register blocking
+ RK = NumberOfRegisters>=16 ? 4 : 2, // register blocking
+ BM = 4096/sizeof(Scalar), // number of rows of A-C per chunk
+ SM = PM*PacketSize // step along M
+ };
+ Index d_end = (d/RK)*RK; // number of columns of A (rows of B) suitable for full register blocking
+ Index n_end = (n/RN)*RN; // number of columns of B-C suitable for processing RN columns at once
+ Index i0 = internal::first_aligned(A,m);
+
+ eigen_internal_assert(((lda%PacketSize)==0) && ((ldc%PacketSize)==0) && (i0==internal::first_aligned(C,m)));
+
+ // handle the non aligned rows of A and C without any optimization:
+ for(Index i=0; i<i0; ++i)
+ {
+ for(Index j=0; j<n; ++j)
+ {
+ Scalar c = C[i+j*ldc];
+ for(Index k=0; k<d; ++k)
+ c += B[k+j*ldb] * A[i+k*lda];
+ C[i+j*ldc] = c;
+ }
+ }
+ // process the remaining rows per chunk of BM rows
+ for(Index ib=i0; ib<m; ib+=BM)
+ {
+ Index actual_b = std::min<Index>(BM, m-ib); // actual number of rows
+ Index actual_b_end1 = (actual_b/SM)*SM; // actual number of rows suitable for peeling
+ Index actual_b_end2 = (actual_b/PacketSize)*PacketSize; // actual number of rows suitable for vectorization
+
+ // Let's process two columns of B-C at once
+ for(Index j=0; j<n_end; j+=RN)
+ {
+ const Scalar* Bc0 = B+(j+0)*ldb;
+ const Scalar* Bc1 = B+(j+1)*ldb;
+
+ for(Index k=0; k<d_end; k+=RK)
+ {
+
+ // load and expand a RN x RK block of B
+ Packet b00, b10, b20, b30, b01, b11, b21, b31;
+ b00 = pset1<Packet>(Bc0[0]);
+ b10 = pset1<Packet>(Bc0[1]);
+ if(RK==4) b20 = pset1<Packet>(Bc0[2]);
+ if(RK==4) b30 = pset1<Packet>(Bc0[3]);
+ b01 = pset1<Packet>(Bc1[0]);
+ b11 = pset1<Packet>(Bc1[1]);
+ if(RK==4) b21 = pset1<Packet>(Bc1[2]);
+ if(RK==4) b31 = pset1<Packet>(Bc1[3]);
+
+ Packet a0, a1, a2, a3, c0, c1, t0, t1;
+
+ const Scalar* A0 = A+ib+(k+0)*lda;
+ const Scalar* A1 = A+ib+(k+1)*lda;
+ const Scalar* A2 = A+ib+(k+2)*lda;
+ const Scalar* A3 = A+ib+(k+3)*lda;
+
+ Scalar* C0 = C+ib+(j+0)*ldc;
+ Scalar* C1 = C+ib+(j+1)*ldc;
+
+ a0 = pload<Packet>(A0);
+ a1 = pload<Packet>(A1);
+ if(RK==4)
+ {
+ a2 = pload<Packet>(A2);
+ a3 = pload<Packet>(A3);
+ }
+ else
+ {
+ // workaround "may be used uninitialized in this function" warning
+ a2 = a3 = a0;
+ }
+
+#define KMADD(c, a, b, tmp) {tmp = b; tmp = pmul(a,tmp); c = padd(c,tmp);}
+#define WORK(I) \
+ c0 = pload<Packet>(C0+i+(I)*PacketSize); \
+ c1 = pload<Packet>(C1+i+(I)*PacketSize); \
+ KMADD(c0, a0, b00, t0) \
+ KMADD(c1, a0, b01, t1) \
+ a0 = pload<Packet>(A0+i+(I+1)*PacketSize); \
+ KMADD(c0, a1, b10, t0) \
+ KMADD(c1, a1, b11, t1) \
+ a1 = pload<Packet>(A1+i+(I+1)*PacketSize); \
+ if(RK==4) KMADD(c0, a2, b20, t0) \
+ if(RK==4) KMADD(c1, a2, b21, t1) \
+ if(RK==4) a2 = pload<Packet>(A2+i+(I+1)*PacketSize); \
+ if(RK==4) KMADD(c0, a3, b30, t0) \
+ if(RK==4) KMADD(c1, a3, b31, t1) \
+ if(RK==4) a3 = pload<Packet>(A3+i+(I+1)*PacketSize); \
+ pstore(C0+i+(I)*PacketSize, c0); \
+ pstore(C1+i+(I)*PacketSize, c1)
+
+ // process rows of A' - C' with aggressive vectorization and peeling
+ for(Index i=0; i<actual_b_end1; i+=PacketSize*8)
+ {
+ EIGEN_ASM_COMMENT("SPARSELU_GEMML_KERNEL1");
+ prefetch((A0+i+(5)*PacketSize));
+ prefetch((A1+i+(5)*PacketSize));
+ if(RK==4) prefetch((A2+i+(5)*PacketSize));
+ if(RK==4) prefetch((A3+i+(5)*PacketSize));
+ WORK(0);
+ WORK(1);
+ WORK(2);
+ WORK(3);
+ WORK(4);
+ WORK(5);
+ WORK(6);
+ WORK(7);
+ }
+ // process the remaining rows with vectorization only
+ for(Index i=actual_b_end1; i<actual_b_end2; i+=PacketSize)
+ {
+ WORK(0);
+ }
+#undef WORK
+ // process the remaining rows without vectorization
+ for(Index i=actual_b_end2; i<actual_b; ++i)
+ {
+ if(RK==4)
+ {
+ C0[i] += A0[i]*Bc0[0]+A1[i]*Bc0[1]+A2[i]*Bc0[2]+A3[i]*Bc0[3];
+ C1[i] += A0[i]*Bc1[0]+A1[i]*Bc1[1]+A2[i]*Bc1[2]+A3[i]*Bc1[3];
+ }
+ else
+ {
+ C0[i] += A0[i]*Bc0[0]+A1[i]*Bc0[1];
+ C1[i] += A0[i]*Bc1[0]+A1[i]*Bc1[1];
+ }
+ }
+
+ Bc0 += RK;
+ Bc1 += RK;
+ } // peeled loop on k
+ } // peeled loop on the columns j
+ // process the last column (we now perform a matrux-vector product)
+ if((n-n_end)>0)
+ {
+ const Scalar* Bc0 = B+(n-1)*ldb;
+
+ for(Index k=0; k<d_end; k+=RK)
+ {
+
+ // load and expand a 1 x RK block of B
+ Packet b00, b10, b20, b30;
+ b00 = pset1<Packet>(Bc0[0]);
+ b10 = pset1<Packet>(Bc0[1]);
+ if(RK==4) b20 = pset1<Packet>(Bc0[2]);
+ if(RK==4) b30 = pset1<Packet>(Bc0[3]);
+
+ Packet a0, a1, a2, a3, c0, t0/*, t1*/;
+
+ const Scalar* A0 = A+ib+(k+0)*lda;
+ const Scalar* A1 = A+ib+(k+1)*lda;
+ const Scalar* A2 = A+ib+(k+2)*lda;
+ const Scalar* A3 = A+ib+(k+3)*lda;
+
+ Scalar* C0 = C+ib+(n_end)*ldc;
+
+ a0 = pload<Packet>(A0);
+ a1 = pload<Packet>(A1);
+ if(RK==4)
+ {
+ a2 = pload<Packet>(A2);
+ a3 = pload<Packet>(A3);
+ }
+ else
+ {
+ // workaround "may be used uninitialized in this function" warning
+ a2 = a3 = a0;
+ }
+
+#define WORK(I) \
+ c0 = pload<Packet>(C0+i+(I)*PacketSize); \
+ KMADD(c0, a0, b00, t0) \
+ a0 = pload<Packet>(A0+i+(I+1)*PacketSize); \
+ KMADD(c0, a1, b10, t0) \
+ a1 = pload<Packet>(A1+i+(I+1)*PacketSize); \
+ if(RK==4) KMADD(c0, a2, b20, t0) \
+ if(RK==4) a2 = pload<Packet>(A2+i+(I+1)*PacketSize); \
+ if(RK==4) KMADD(c0, a3, b30, t0) \
+ if(RK==4) a3 = pload<Packet>(A3+i+(I+1)*PacketSize); \
+ pstore(C0+i+(I)*PacketSize, c0);
+
+ // agressive vectorization and peeling
+ for(Index i=0; i<actual_b_end1; i+=PacketSize*8)
+ {
+ EIGEN_ASM_COMMENT("SPARSELU_GEMML_KERNEL2");
+ WORK(0);
+ WORK(1);
+ WORK(2);
+ WORK(3);
+ WORK(4);
+ WORK(5);
+ WORK(6);
+ WORK(7);
+ }
+ // vectorization only
+ for(Index i=actual_b_end1; i<actual_b_end2; i+=PacketSize)
+ {
+ WORK(0);
+ }
+ // remaining scalars
+ for(Index i=actual_b_end2; i<actual_b; ++i)
+ {
+ if(RK==4)
+ C0[i] += A0[i]*Bc0[0]+A1[i]*Bc0[1]+A2[i]*Bc0[2]+A3[i]*Bc0[3];
+ else
+ C0[i] += A0[i]*Bc0[0]+A1[i]*Bc0[1];
+ }
+
+ Bc0 += RK;
+#undef WORK
+ }
+ }
+
+ // process the last columns of A, corresponding to the last rows of B
+ Index rd = d-d_end;
+ if(rd>0)
+ {
+ for(Index j=0; j<n; ++j)
+ {
+ enum {
+ Alignment = PacketSize>1 ? Aligned : 0
+ };
+ typedef Map<Matrix<Scalar,Dynamic,1>, Alignment > MapVector;
+ typedef Map<const Matrix<Scalar,Dynamic,1>, Alignment > ConstMapVector;
+ if(rd==1) MapVector(C+j*ldc+ib,actual_b) += B[0+d_end+j*ldb] * ConstMapVector(A+(d_end+0)*lda+ib, actual_b);
+
+ else if(rd==2) MapVector(C+j*ldc+ib,actual_b) += B[0+d_end+j*ldb] * ConstMapVector(A+(d_end+0)*lda+ib, actual_b)
+ + B[1+d_end+j*ldb] * ConstMapVector(A+(d_end+1)*lda+ib, actual_b);
+
+ else MapVector(C+j*ldc+ib,actual_b) += B[0+d_end+j*ldb] * ConstMapVector(A+(d_end+0)*lda+ib, actual_b)
+ + B[1+d_end+j*ldb] * ConstMapVector(A+(d_end+1)*lda+ib, actual_b)
+ + B[2+d_end+j*ldb] * ConstMapVector(A+(d_end+2)*lda+ib, actual_b);
+ }
+ }
+
+ } // blocking on the rows of A and C
+}
+#undef KMADD
+
+} // namespace internal
+
+} // namespace Eigen
+
+#endif // EIGEN_SPARSELU_GEMM_KERNEL_H
diff --git a/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h b/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h
new file mode 100644
index 000000000..7a4e4305a
--- /dev/null
+++ b/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h
@@ -0,0 +1,127 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/* This file is a modified version of heap_relax_snode.c file in SuperLU
+ * -- SuperLU routine (version 3.0) --
+ * Univ. of California Berkeley, Xerox Palo Alto Research Center,
+ * and Lawrence Berkeley National Lab.
+ * October 15, 2003
+ *
+ * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
+ * EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program for any
+ * purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is
+ * granted, provided the above notices are retained, and a notice that
+ * the code was modified is included with the above copyright notice.
+ */
+
+#ifndef SPARSELU_HEAP_RELAX_SNODE_H
+#define SPARSELU_HEAP_RELAX_SNODE_H
+
+namespace Eigen {
+namespace internal {
+
+/**
+ * \brief Identify the initial relaxed supernodes
+ *
+ * This routine applied to a symmetric elimination tree.
+ * It assumes that the matrix has been reordered according to the postorder of the etree
+ * \param n The number of columns
+ * \param et elimination tree
+ * \param relax_columns Maximum number of columns allowed in a relaxed snode
+ * \param descendants Number of descendants of each node in the etree
+ * \param relax_end last column in a supernode
+ */
+template <typename Scalar, typename Index>
+void SparseLUImpl<Scalar,Index>::heap_relax_snode (const Index n, IndexVector& et, const Index relax_columns, IndexVector& descendants, IndexVector& relax_end)
+{
+
+ // The etree may not be postordered, but its heap ordered
+ IndexVector post;
+ internal::treePostorder(n, et, post); // Post order etree
+ IndexVector inv_post(n+1);
+ Index i;
+ for (i = 0; i < n+1; ++i) inv_post(post(i)) = i; // inv_post = post.inverse()???
+
+ // Renumber etree in postorder
+ IndexVector iwork(n);
+ IndexVector et_save(n+1);
+ for (i = 0; i < n; ++i)
+ {
+ iwork(post(i)) = post(et(i));
+ }
+ et_save = et; // Save the original etree
+ et = iwork;
+
+ // compute the number of descendants of each node in the etree
+ relax_end.setConstant(emptyIdxLU);
+ Index j, parent;
+ descendants.setZero();
+ for (j = 0; j < n; j++)
+ {
+ parent = et(j);
+ if (parent != n) // not the dummy root
+ descendants(parent) += descendants(j) + 1;
+ }
+ // Identify the relaxed supernodes by postorder traversal of the etree
+ Index snode_start; // beginning of a snode
+ Index k;
+ Index nsuper_et_post = 0; // Number of relaxed snodes in postordered etree
+ Index nsuper_et = 0; // Number of relaxed snodes in the original etree
+ Index l;
+ for (j = 0; j < n; )
+ {
+ parent = et(j);
+ snode_start = j;
+ while ( parent != n && descendants(parent) < relax_columns )
+ {
+ j = parent;
+ parent = et(j);
+ }
+ // Found a supernode in postordered etree, j is the last column
+ ++nsuper_et_post;
+ k = n;
+ for (i = snode_start; i <= j; ++i)
+ k = (std::min)(k, inv_post(i));
+ l = inv_post(j);
+ if ( (l - k) == (j - snode_start) ) // Same number of columns in the snode
+ {
+ // This is also a supernode in the original etree
+ relax_end(k) = l; // Record last column
+ ++nsuper_et;
+ }
+ else
+ {
+ for (i = snode_start; i <= j; ++i)
+ {
+ l = inv_post(i);
+ if (descendants(i) == 0)
+ {
+ relax_end(l) = l;
+ ++nsuper_et;
+ }
+ }
+ }
+ j++;
+ // Search for a new leaf
+ while (descendants(j) != 0 && j < n) j++;
+ } // End postorder traversal of the etree
+
+ // Recover the original etree
+ et = et_save;
+}
+
+} // end namespace internal
+
+} // end namespace Eigen
+#endif // SPARSELU_HEAP_RELAX_SNODE_H
diff --git a/Eigen/src/SparseLU/SparseLU_kernel_bmod.h b/Eigen/src/SparseLU/SparseLU_kernel_bmod.h
new file mode 100644
index 000000000..0d0283b13
--- /dev/null
+++ b/Eigen/src/SparseLU/SparseLU_kernel_bmod.h
@@ -0,0 +1,130 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+// Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef SPARSELU_KERNEL_BMOD_H
+#define SPARSELU_KERNEL_BMOD_H
+
+namespace Eigen {
+namespace internal {
+
+/**
+ * \brief Performs numeric block updates from a given supernode to a single column
+ *
+ * \param segsize Size of the segment (and blocks ) to use for updates
+ * \param[in,out] dense Packed values of the original matrix
+ * \param tempv temporary vector to use for updates
+ * \param lusup array containing the supernodes
+ * \param lda Leading dimension in the supernode
+ * \param nrow Number of rows in the rectangular part of the supernode
+ * \param lsub compressed row subscripts of supernodes
+ * \param lptr pointer to the first column of the current supernode in lsub
+ * \param no_zeros Number of nonzeros elements before the diagonal part of the supernode
+ * \return 0 on success
+ */
+template <int SegSizeAtCompileTime> struct LU_kernel_bmod
+{
+ template <typename BlockScalarVector, typename ScalarVector, typename IndexVector, typename Index>
+ static EIGEN_DONT_INLINE void run(const int segsize, BlockScalarVector& dense, ScalarVector& tempv, ScalarVector& lusup, Index& luptr, const Index lda,
+ const Index nrow, IndexVector& lsub, const Index lptr, const Index no_zeros);
+};
+
+template <int SegSizeAtCompileTime>
+template <typename BlockScalarVector, typename ScalarVector, typename IndexVector, typename Index>
+EIGEN_DONT_INLINE void LU_kernel_bmod<SegSizeAtCompileTime>::run(const int segsize, BlockScalarVector& dense, ScalarVector& tempv, ScalarVector& lusup, Index& luptr, const Index lda,
+ const Index nrow, IndexVector& lsub, const Index lptr, const Index no_zeros)
+{
+ typedef typename ScalarVector::Scalar Scalar;
+ // First, copy U[*,j] segment from dense(*) to tempv(*)
+ // The result of triangular solve is in tempv[*];
+ // The result of matric-vector update is in dense[*]
+ Index isub = lptr + no_zeros;
+ int i;
+ Index irow;
+ for (i = 0; i < ((SegSizeAtCompileTime==Dynamic)?segsize:SegSizeAtCompileTime); i++)
+ {
+ irow = lsub(isub);
+ tempv(i) = dense(irow);
+ ++isub;
+ }
+ // Dense triangular solve -- start effective triangle
+ luptr += lda * no_zeros + no_zeros;
+ // Form Eigen matrix and vector
+ Map<Matrix<Scalar,SegSizeAtCompileTime,SegSizeAtCompileTime>, 0, OuterStride<> > A( &(lusup.data()[luptr]), segsize, segsize, OuterStride<>(lda) );
+ Map<Matrix<Scalar,SegSizeAtCompileTime,1> > u(tempv.data(), segsize);
+
+ u = A.template triangularView<UnitLower>().solve(u);
+
+ // Dense matrix-vector product y <-- B*x
+ luptr += segsize;
+ const Index PacketSize = internal::packet_traits<Scalar>::size;
+ Index ldl = internal::first_multiple(nrow, PacketSize);
+ Map<Matrix<Scalar,Dynamic,SegSizeAtCompileTime>, 0, OuterStride<> > B( &(lusup.data()[luptr]), nrow, segsize, OuterStride<>(lda) );
+ Index aligned_offset = internal::first_aligned(tempv.data()+segsize, PacketSize);
+ Index aligned_with_B_offset = (PacketSize-internal::first_aligned(B.data(), PacketSize))%PacketSize;
+ Map<Matrix<Scalar,Dynamic,1>, 0, OuterStride<> > l(tempv.data()+segsize+aligned_offset+aligned_with_B_offset, nrow, OuterStride<>(ldl) );
+
+ l.setZero();
+ internal::sparselu_gemm<Scalar>(l.rows(), l.cols(), B.cols(), B.data(), B.outerStride(), u.data(), u.outerStride(), l.data(), l.outerStride());
+
+ // Scatter tempv[] into SPA dense[] as a temporary storage
+ isub = lptr + no_zeros;
+ for (i = 0; i < ((SegSizeAtCompileTime==Dynamic)?segsize:SegSizeAtCompileTime); i++)
+ {
+ irow = lsub(isub++);
+ dense(irow) = tempv(i);
+ }
+
+ // Scatter l into SPA dense[]
+ for (i = 0; i < nrow; i++)
+ {
+ irow = lsub(isub++);
+ dense(irow) -= l(i);
+ }
+}
+
+template <> struct LU_kernel_bmod<1>
+{
+ template <typename BlockScalarVector, typename ScalarVector, typename IndexVector, typename Index>
+ static EIGEN_DONT_INLINE void run(const int /*segsize*/, BlockScalarVector& dense, ScalarVector& /*tempv*/, ScalarVector& lusup, Index& luptr,
+ const Index lda, const Index nrow, IndexVector& lsub, const Index lptr, const Index no_zeros);
+};
+
+
+template <typename BlockScalarVector, typename ScalarVector, typename IndexVector, typename Index>
+EIGEN_DONT_INLINE void LU_kernel_bmod<1>::run(const int /*segsize*/, BlockScalarVector& dense, ScalarVector& /*tempv*/, ScalarVector& lusup, Index& luptr,
+ const Index lda, const Index nrow, IndexVector& lsub, const Index lptr, const Index no_zeros)
+{
+ typedef typename ScalarVector::Scalar Scalar;
+ Scalar f = dense(lsub(lptr + no_zeros));
+ luptr += lda * no_zeros + no_zeros + 1;
+ const Scalar* a(lusup.data() + luptr);
+ const /*typename IndexVector::Scalar*/Index* irow(lsub.data()+lptr + no_zeros + 1);
+ Index i = 0;
+ for (; i+1 < nrow; i+=2)
+ {
+ Index i0 = *(irow++);
+ Index i1 = *(irow++);
+ Scalar a0 = *(a++);
+ Scalar a1 = *(a++);
+ Scalar d0 = dense.coeff(i0);
+ Scalar d1 = dense.coeff(i1);
+ d0 -= f*a0;
+ d1 -= f*a1;
+ dense.coeffRef(i0) = d0;
+ dense.coeffRef(i1) = d1;
+ }
+ if(i<nrow)
+ dense.coeffRef(*(irow++)) -= f * *(a++);
+}
+
+} // end namespace internal
+
+} // end namespace Eigen
+#endif // SPARSELU_KERNEL_BMOD_H
diff --git a/Eigen/src/SparseLU/SparseLU_panel_bmod.h b/Eigen/src/SparseLU/SparseLU_panel_bmod.h
new file mode 100644
index 000000000..da0e0fc3c
--- /dev/null
+++ b/Eigen/src/SparseLU/SparseLU_panel_bmod.h
@@ -0,0 +1,223 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+// Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/*
+
+ * NOTE: This file is the modified version of [s,d,c,z]panel_bmod.c file in SuperLU
+
+ * -- SuperLU routine (version 3.0) --
+ * Univ. of California Berkeley, Xerox Palo Alto Research Center,
+ * and Lawrence Berkeley National Lab.
+ * October 15, 2003
+ *
+ * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
+ * EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program for any
+ * purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is
+ * granted, provided the above notices are retained, and a notice that
+ * the code was modified is included with the above copyright notice.
+ */
+#ifndef SPARSELU_PANEL_BMOD_H
+#define SPARSELU_PANEL_BMOD_H
+
+namespace Eigen {
+namespace internal {
+
+/**
+ * \brief Performs numeric block updates (sup-panel) in topological order.
+ *
+ * Before entering this routine, the original nonzeros in the panel
+ * were already copied i nto the spa[m,w]
+ *
+ * \param m number of rows in the matrix
+ * \param w Panel size
+ * \param jcol Starting column of the panel
+ * \param nseg Number of segments in the U part
+ * \param dense Store the full representation of the panel
+ * \param tempv working array
+ * \param segrep segment representative... first row in the segment
+ * \param repfnz First nonzero rows
+ * \param glu Global LU data.
+ *
+ *
+ */
+template <typename Scalar, typename Index>
+void SparseLUImpl<Scalar,Index>::panel_bmod(const Index m, const Index w, const Index jcol,
+ const Index nseg, ScalarVector& dense, ScalarVector& tempv,
+ IndexVector& segrep, IndexVector& repfnz, GlobalLU_t& glu)
+{
+
+ Index ksub,jj,nextl_col;
+ Index fsupc, nsupc, nsupr, nrow;
+ Index krep, kfnz;
+ Index lptr; // points to the row subscripts of a supernode
+ Index luptr; // ...
+ Index segsize,no_zeros ;
+ // For each nonz supernode segment of U[*,j] in topological order
+ Index k = nseg - 1;
+ const Index PacketSize = internal::packet_traits<Scalar>::size;
+
+ for (ksub = 0; ksub < nseg; ksub++)
+ { // For each updating supernode
+ /* krep = representative of current k-th supernode
+ * fsupc = first supernodal column
+ * nsupc = number of columns in a supernode
+ * nsupr = number of rows in a supernode
+ */
+ krep = segrep(k); k--;
+ fsupc = glu.xsup(glu.supno(krep));
+ nsupc = krep - fsupc + 1;
+ nsupr = glu.xlsub(fsupc+1) - glu.xlsub(fsupc);
+ nrow = nsupr - nsupc;
+ lptr = glu.xlsub(fsupc);
+
+ // loop over the panel columns to detect the actual number of columns and rows
+ Index u_rows = 0;
+ Index u_cols = 0;
+ for (jj = jcol; jj < jcol + w; jj++)
+ {
+ nextl_col = (jj-jcol) * m;
+ VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
+
+ kfnz = repfnz_col(krep);
+ if ( kfnz == emptyIdxLU )
+ continue; // skip any zero segment
+
+ segsize = krep - kfnz + 1;
+ u_cols++;
+ u_rows = (std::max)(segsize,u_rows);
+ }
+
+ if(nsupc >= 2)
+ {
+ Index ldu = internal::first_multiple<Index>(u_rows, PacketSize);
+ Map<Matrix<Scalar,Dynamic,Dynamic>, Aligned, OuterStride<> > U(tempv.data(), u_rows, u_cols, OuterStride<>(ldu));
+
+ // gather U
+ Index u_col = 0;
+ for (jj = jcol; jj < jcol + w; jj++)
+ {
+ nextl_col = (jj-jcol) * m;
+ VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
+ VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here
+
+ kfnz = repfnz_col(krep);
+ if ( kfnz == emptyIdxLU )
+ continue; // skip any zero segment
+
+ segsize = krep - kfnz + 1;
+ luptr = glu.xlusup(fsupc);
+ no_zeros = kfnz - fsupc;
+
+ Index isub = lptr + no_zeros;
+ Index off = u_rows-segsize;
+ for (Index i = 0; i < off; i++) U(i,u_col) = 0;
+ for (Index i = 0; i < segsize; i++)
+ {
+ Index irow = glu.lsub(isub);
+ U(i+off,u_col) = dense_col(irow);
+ ++isub;
+ }
+ u_col++;
+ }
+ // solve U = A^-1 U
+ luptr = glu.xlusup(fsupc);
+ Index lda = glu.xlusup(fsupc+1) - glu.xlusup(fsupc);
+ no_zeros = (krep - u_rows + 1) - fsupc;
+ luptr += lda * no_zeros + no_zeros;
+ Map<Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > A(glu.lusup.data()+luptr, u_rows, u_rows, OuterStride<>(lda) );
+ U = A.template triangularView<UnitLower>().solve(U);
+
+ // update
+ luptr += u_rows;
+ Map<Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > B(glu.lusup.data()+luptr, nrow, u_rows, OuterStride<>(lda) );
+ eigen_assert(tempv.size()>w*ldu + nrow*w + 1);
+
+ Index ldl = internal::first_multiple<Index>(nrow, PacketSize);
+ Index offset = (PacketSize-internal::first_aligned(B.data(), PacketSize)) % PacketSize;
+ Map<Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > L(tempv.data()+w*ldu+offset, nrow, u_cols, OuterStride<>(ldl));
+
+ L.setZero();
+ internal::sparselu_gemm<Scalar>(L.rows(), L.cols(), B.cols(), B.data(), B.outerStride(), U.data(), U.outerStride(), L.data(), L.outerStride());
+
+ // scatter U and L
+ u_col = 0;
+ for (jj = jcol; jj < jcol + w; jj++)
+ {
+ nextl_col = (jj-jcol) * m;
+ VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
+ VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here
+
+ kfnz = repfnz_col(krep);
+ if ( kfnz == emptyIdxLU )
+ continue; // skip any zero segment
+
+ segsize = krep - kfnz + 1;
+ no_zeros = kfnz - fsupc;
+ Index isub = lptr + no_zeros;
+
+ Index off = u_rows-segsize;
+ for (Index i = 0; i < segsize; i++)
+ {
+ Index irow = glu.lsub(isub++);
+ dense_col(irow) = U.coeff(i+off,u_col);
+ U.coeffRef(i+off,u_col) = 0;
+ }
+
+ // Scatter l into SPA dense[]
+ for (Index i = 0; i < nrow; i++)
+ {
+ Index irow = glu.lsub(isub++);
+ dense_col(irow) -= L.coeff(i,u_col);
+ L.coeffRef(i,u_col) = 0;
+ }
+ u_col++;
+ }
+ }
+ else // level 2 only
+ {
+ // Sequence through each column in the panel
+ for (jj = jcol; jj < jcol + w; jj++)
+ {
+ nextl_col = (jj-jcol) * m;
+ VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
+ VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here
+
+ kfnz = repfnz_col(krep);
+ if ( kfnz == emptyIdxLU )
+ continue; // skip any zero segment
+
+ segsize = krep - kfnz + 1;
+ luptr = glu.xlusup(fsupc);
+
+ Index lda = glu.xlusup(fsupc+1)-glu.xlusup(fsupc);// nsupr
+
+ // Perform a trianglar solve and block update,
+ // then scatter the result of sup-col update to dense[]
+ no_zeros = kfnz - fsupc;
+ if(segsize==1) LU_kernel_bmod<1>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
+ else if(segsize==2) LU_kernel_bmod<2>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
+ else if(segsize==3) LU_kernel_bmod<3>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
+ else LU_kernel_bmod<Dynamic>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
+ } // End for each column in the panel
+ }
+
+ } // End for each updating supernode
+} // end panel bmod
+
+} // end namespace internal
+
+} // end namespace Eigen
+
+#endif // SPARSELU_PANEL_BMOD_H
diff --git a/Eigen/src/SparseLU/SparseLU_panel_dfs.h b/Eigen/src/SparseLU/SparseLU_panel_dfs.h
new file mode 100644
index 000000000..dc0054efd
--- /dev/null
+++ b/Eigen/src/SparseLU/SparseLU_panel_dfs.h
@@ -0,0 +1,258 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/*
+
+ * NOTE: This file is the modified version of [s,d,c,z]panel_dfs.c file in SuperLU
+
+ * -- SuperLU routine (version 2.0) --
+ * Univ. of California Berkeley, Xerox Palo Alto Research Center,
+ * and Lawrence Berkeley National Lab.
+ * November 15, 1997
+ *
+ * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
+ * EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program for any
+ * purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is
+ * granted, provided the above notices are retained, and a notice that
+ * the code was modified is included with the above copyright notice.
+ */
+#ifndef SPARSELU_PANEL_DFS_H
+#define SPARSELU_PANEL_DFS_H
+
+namespace Eigen {
+
+namespace internal {
+
+template<typename IndexVector>
+struct panel_dfs_traits
+{
+ typedef typename IndexVector::Scalar Index;
+ panel_dfs_traits(Index jcol, Index* marker)
+ : m_jcol(jcol), m_marker(marker)
+ {}
+ bool update_segrep(Index krep, Index jj)
+ {
+ if(m_marker[krep]<m_jcol)
+ {
+ m_marker[krep] = jj;
+ return true;
+ }
+ return false;
+ }
+ void mem_expand(IndexVector& /*glu.lsub*/, Index /*nextl*/, Index /*chmark*/) {}
+ enum { ExpandMem = false };
+ Index m_jcol;
+ Index* m_marker;
+};
+
+
+template <typename Scalar, typename Index>
+template <typename Traits>
+void SparseLUImpl<Scalar,Index>::dfs_kernel(const Index jj, IndexVector& perm_r,
+ Index& nseg, IndexVector& panel_lsub, IndexVector& segrep,
+ Ref<IndexVector> repfnz_col, IndexVector& xprune, Ref<IndexVector> marker, IndexVector& parent,
+ IndexVector& xplore, GlobalLU_t& glu,
+ Index& nextl_col, Index krow, Traits& traits
+ )
+{
+
+ Index kmark = marker(krow);
+
+ // For each unmarked krow of jj
+ marker(krow) = jj;
+ Index kperm = perm_r(krow);
+ if (kperm == emptyIdxLU ) {
+ // krow is in L : place it in structure of L(*, jj)
+ panel_lsub(nextl_col++) = krow; // krow is indexed into A
+
+ traits.mem_expand(panel_lsub, nextl_col, kmark);
+ }
+ else
+ {
+ // krow is in U : if its supernode-representative krep
+ // has been explored, update repfnz(*)
+ // krep = supernode representative of the current row
+ Index krep = glu.xsup(glu.supno(kperm)+1) - 1;
+ // First nonzero element in the current column:
+ Index myfnz = repfnz_col(krep);
+
+ if (myfnz != emptyIdxLU )
+ {
+ // Representative visited before
+ if (myfnz > kperm ) repfnz_col(krep) = kperm;
+
+ }
+ else
+ {
+ // Otherwise, perform dfs starting at krep
+ Index oldrep = emptyIdxLU;
+ parent(krep) = oldrep;
+ repfnz_col(krep) = kperm;
+ Index xdfs = glu.xlsub(krep);
+ Index maxdfs = xprune(krep);
+
+ Index kpar;
+ do
+ {
+ // For each unmarked kchild of krep
+ while (xdfs < maxdfs)
+ {
+ Index kchild = glu.lsub(xdfs);
+ xdfs++;
+ Index chmark = marker(kchild);
+
+ if (chmark != jj )
+ {
+ marker(kchild) = jj;
+ Index chperm = perm_r(kchild);
+
+ if (chperm == emptyIdxLU)
+ {
+ // case kchild is in L: place it in L(*, j)
+ panel_lsub(nextl_col++) = kchild;
+ traits.mem_expand(panel_lsub, nextl_col, chmark);
+ }
+ else
+ {
+ // case kchild is in U :
+ // chrep = its supernode-rep. If its rep has been explored,
+ // update its repfnz(*)
+ Index chrep = glu.xsup(glu.supno(chperm)+1) - 1;
+ myfnz = repfnz_col(chrep);
+
+ if (myfnz != emptyIdxLU)
+ { // Visited before
+ if (myfnz > chperm)
+ repfnz_col(chrep) = chperm;
+ }
+ else
+ { // Cont. dfs at snode-rep of kchild
+ xplore(krep) = xdfs;
+ oldrep = krep;
+ krep = chrep; // Go deeper down G(L)
+ parent(krep) = oldrep;
+ repfnz_col(krep) = chperm;
+ xdfs = glu.xlsub(krep);
+ maxdfs = xprune(krep);
+
+ } // end if myfnz != -1
+ } // end if chperm == -1
+
+ } // end if chmark !=jj
+ } // end while xdfs < maxdfs
+
+ // krow has no more unexplored nbrs :
+ // Place snode-rep krep in postorder DFS, if this
+ // segment is seen for the first time. (Note that
+ // "repfnz(krep)" may change later.)
+ // Baktrack dfs to its parent
+ if(traits.update_segrep(krep,jj))
+ //if (marker1(krep) < jcol )
+ {
+ segrep(nseg) = krep;
+ ++nseg;
+ //marker1(krep) = jj;
+ }
+
+ kpar = parent(krep); // Pop recursion, mimic recursion
+ if (kpar == emptyIdxLU)
+ break; // dfs done
+ krep = kpar;
+ xdfs = xplore(krep);
+ maxdfs = xprune(krep);
+
+ } while (kpar != emptyIdxLU); // Do until empty stack
+
+ } // end if (myfnz = -1)
+
+ } // end if (kperm == -1)
+}
+
+/**
+ * \brief Performs a symbolic factorization on a panel of columns [jcol, jcol+w)
+ *
+ * A supernode representative is the last column of a supernode.
+ * The nonzeros in U[*,j] are segments that end at supernodes representatives
+ *
+ * The routine returns a list of the supernodal representatives
+ * in topological order of the dfs that generates them. This list is
+ * a superset of the topological order of each individual column within
+ * the panel.
+ * The location of the first nonzero in each supernodal segment
+ * (supernodal entry location) is also returned. Each column has
+ * a separate list for this purpose.
+ *
+ * Two markers arrays are used for dfs :
+ * marker[i] == jj, if i was visited during dfs of current column jj;
+ * marker1[i] >= jcol, if i was visited by earlier columns in this panel;
+ *
+ * \param[in] m number of rows in the matrix
+ * \param[in] w Panel size
+ * \param[in] jcol Starting column of the panel
+ * \param[in] A Input matrix in column-major storage
+ * \param[in] perm_r Row permutation
+ * \param[out] nseg Number of U segments
+ * \param[out] dense Accumulate the column vectors of the panel
+ * \param[out] panel_lsub Subscripts of the row in the panel
+ * \param[out] segrep Segment representative i.e first nonzero row of each segment
+ * \param[out] repfnz First nonzero location in each row
+ * \param[out] xprune The pruned elimination tree
+ * \param[out] marker work vector
+ * \param parent The elimination tree
+ * \param xplore work vector
+ * \param glu The global data structure
+ *
+ */
+
+template <typename Scalar, typename Index>
+void SparseLUImpl<Scalar,Index>::panel_dfs(const Index m, const Index w, const Index jcol, MatrixType& A, IndexVector& perm_r, Index& nseg, ScalarVector& dense, IndexVector& panel_lsub, IndexVector& segrep, IndexVector& repfnz, IndexVector& xprune, IndexVector& marker, IndexVector& parent, IndexVector& xplore, GlobalLU_t& glu)
+{
+ Index nextl_col; // Next available position in panel_lsub[*,jj]
+
+ // Initialize pointers
+ VectorBlock<IndexVector> marker1(marker, m, m);
+ nseg = 0;
+
+ panel_dfs_traits<IndexVector> traits(jcol, marker1.data());
+
+ // For each column in the panel
+ for (Index jj = jcol; jj < jcol + w; jj++)
+ {
+ nextl_col = (jj - jcol) * m;
+
+ VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero location in each row
+ VectorBlock<ScalarVector> dense_col(dense,nextl_col, m); // Accumulate a column vector here
+
+
+ // For each nnz in A[*, jj] do depth first search
+ for (typename MatrixType::InnerIterator it(A, jj); it; ++it)
+ {
+ Index krow = it.row();
+ dense_col(krow) = it.value();
+
+ Index kmark = marker(krow);
+ if (kmark == jj)
+ continue; // krow visited before, go to the next nonzero
+
+ dfs_kernel(jj, perm_r, nseg, panel_lsub, segrep, repfnz_col, xprune, marker, parent,
+ xplore, glu, nextl_col, krow, traits);
+ }// end for nonzeros in column jj
+
+ } // end for column jj
+}
+
+} // end namespace internal
+} // end namespace Eigen
+
+#endif // SPARSELU_PANEL_DFS_H
diff --git a/Eigen/src/SparseLU/SparseLU_pivotL.h b/Eigen/src/SparseLU/SparseLU_pivotL.h
new file mode 100644
index 000000000..ddcd4ec98
--- /dev/null
+++ b/Eigen/src/SparseLU/SparseLU_pivotL.h
@@ -0,0 +1,134 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/*
+
+ * NOTE: This file is the modified version of xpivotL.c file in SuperLU
+
+ * -- SuperLU routine (version 3.0) --
+ * Univ. of California Berkeley, Xerox Palo Alto Research Center,
+ * and Lawrence Berkeley National Lab.
+ * October 15, 2003
+ *
+ * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
+ * EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program for any
+ * purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is
+ * granted, provided the above notices are retained, and a notice that
+ * the code was modified is included with the above copyright notice.
+ */
+#ifndef SPARSELU_PIVOTL_H
+#define SPARSELU_PIVOTL_H
+
+namespace Eigen {
+namespace internal {
+
+/**
+ * \brief Performs the numerical pivotin on the current column of L, and the CDIV operation.
+ *
+ * Pivot policy :
+ * (1) Compute thresh = u * max_(i>=j) abs(A_ij);
+ * (2) IF user specifies pivot row k and abs(A_kj) >= thresh THEN
+ * pivot row = k;
+ * ELSE IF abs(A_jj) >= thresh THEN
+ * pivot row = j;
+ * ELSE
+ * pivot row = m;
+ *
+ * Note: If you absolutely want to use a given pivot order, then set u=0.0.
+ *
+ * \param jcol The current column of L
+ * \param diagpivotthresh diagonal pivoting threshold
+ * \param[in,out] perm_r Row permutation (threshold pivoting)
+ * \param[in] iperm_c column permutation - used to finf diagonal of Pc*A*Pc'
+ * \param[out] pivrow The pivot row
+ * \param glu Global LU data
+ * \return 0 if success, i > 0 if U(i,i) is exactly zero
+ *
+ */
+template <typename Scalar, typename Index>
+Index SparseLUImpl<Scalar,Index>::pivotL(const Index jcol, const RealScalar& diagpivotthresh, IndexVector& perm_r, IndexVector& iperm_c, Index& pivrow, GlobalLU_t& glu)
+{
+
+ Index fsupc = (glu.xsup)((glu.supno)(jcol)); // First column in the supernode containing the column jcol
+ Index nsupc = jcol - fsupc; // Number of columns in the supernode portion, excluding jcol; nsupc >=0
+ Index lptr = glu.xlsub(fsupc); // pointer to the starting location of the row subscripts for this supernode portion
+ Index nsupr = glu.xlsub(fsupc+1) - lptr; // Number of rows in the supernode
+ Index lda = glu.xlusup(fsupc+1) - glu.xlusup(fsupc); // leading dimension
+ Scalar* lu_sup_ptr = &(glu.lusup.data()[glu.xlusup(fsupc)]); // Start of the current supernode
+ Scalar* lu_col_ptr = &(glu.lusup.data()[glu.xlusup(jcol)]); // Start of jcol in the supernode
+ Index* lsub_ptr = &(glu.lsub.data()[lptr]); // Start of row indices of the supernode
+
+ // Determine the largest abs numerical value for partial pivoting
+ Index diagind = iperm_c(jcol); // diagonal index
+ RealScalar pivmax = 0.0;
+ Index pivptr = nsupc;
+ Index diag = emptyIdxLU;
+ RealScalar rtemp;
+ Index isub, icol, itemp, k;
+ for (isub = nsupc; isub < nsupr; ++isub) {
+ rtemp = std::abs(lu_col_ptr[isub]);
+ if (rtemp > pivmax) {
+ pivmax = rtemp;
+ pivptr = isub;
+ }
+ if (lsub_ptr[isub] == diagind) diag = isub;
+ }
+
+ // Test for singularity
+ if ( pivmax == 0.0 ) {
+ pivrow = lsub_ptr[pivptr];
+ perm_r(pivrow) = jcol;
+ return (jcol+1);
+ }
+
+ RealScalar thresh = diagpivotthresh * pivmax;
+
+ // Choose appropriate pivotal element
+
+ {
+ // Test if the diagonal element can be used as a pivot (given the threshold value)
+ if (diag >= 0 )
+ {
+ // Diagonal element exists
+ rtemp = std::abs(lu_col_ptr[diag]);
+ if (rtemp != 0.0 && rtemp >= thresh) pivptr = diag;
+ }
+ pivrow = lsub_ptr[pivptr];
+ }
+
+ // Record pivot row
+ perm_r(pivrow) = jcol;
+ // Interchange row subscripts
+ if (pivptr != nsupc )
+ {
+ std::swap( lsub_ptr[pivptr], lsub_ptr[nsupc] );
+ // Interchange numerical values as well, for the two rows in the whole snode
+ // such that L is indexed the same way as A
+ for (icol = 0; icol <= nsupc; icol++)
+ {
+ itemp = pivptr + icol * lda;
+ std::swap(lu_sup_ptr[itemp], lu_sup_ptr[nsupc + icol * lda]);
+ }
+ }
+ // cdiv operations
+ Scalar temp = Scalar(1.0) / lu_col_ptr[nsupc];
+ for (k = nsupc+1; k < nsupr; k++)
+ lu_col_ptr[k] *= temp;
+ return 0;
+}
+
+} // end namespace internal
+} // end namespace Eigen
+
+#endif // SPARSELU_PIVOTL_H
diff --git a/Eigen/src/SparseLU/SparseLU_pruneL.h b/Eigen/src/SparseLU/SparseLU_pruneL.h
new file mode 100644
index 000000000..66460d168
--- /dev/null
+++ b/Eigen/src/SparseLU/SparseLU_pruneL.h
@@ -0,0 +1,135 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/*
+
+ * NOTE: This file is the modified version of [s,d,c,z]pruneL.c file in SuperLU
+
+ * -- SuperLU routine (version 2.0) --
+ * Univ. of California Berkeley, Xerox Palo Alto Research Center,
+ * and Lawrence Berkeley National Lab.
+ * November 15, 1997
+ *
+ * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
+ * EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program for any
+ * purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is
+ * granted, provided the above notices are retained, and a notice that
+ * the code was modified is included with the above copyright notice.
+ */
+#ifndef SPARSELU_PRUNEL_H
+#define SPARSELU_PRUNEL_H
+
+namespace Eigen {
+namespace internal {
+
+/**
+ * \brief Prunes the L-structure.
+ *
+ * It prunes the L-structure of supernodes whose L-structure contains the current pivot row "pivrow"
+ *
+ *
+ * \param jcol The current column of L
+ * \param[in] perm_r Row permutation
+ * \param[out] pivrow The pivot row
+ * \param nseg Number of segments
+ * \param segrep
+ * \param repfnz
+ * \param[out] xprune
+ * \param glu Global LU data
+ *
+ */
+template <typename Scalar, typename Index>
+void SparseLUImpl<Scalar,Index>::pruneL(const Index jcol, const IndexVector& perm_r, const Index pivrow, const Index nseg, const IndexVector& segrep, BlockIndexVector repfnz, IndexVector& xprune, GlobalLU_t& glu)
+{
+ // For each supernode-rep irep in U(*,j]
+ Index jsupno = glu.supno(jcol);
+ Index i,irep,irep1;
+ bool movnum, do_prune = false;
+ Index kmin = 0, kmax = 0, minloc, maxloc,krow;
+ for (i = 0; i < nseg; i++)
+ {
+ irep = segrep(i);
+ irep1 = irep + 1;
+ do_prune = false;
+
+ // Don't prune with a zero U-segment
+ if (repfnz(irep) == emptyIdxLU) continue;
+
+ // If a snode overlaps with the next panel, then the U-segment
+ // is fragmented into two parts -- irep and irep1. We should let
+ // pruning occur at the rep-column in irep1s snode.
+ if (glu.supno(irep) == glu.supno(irep1) ) continue; // don't prune
+
+ // If it has not been pruned & it has a nonz in row L(pivrow,i)
+ if (glu.supno(irep) != jsupno )
+ {
+ if ( xprune (irep) >= glu.xlsub(irep1) )
+ {
+ kmin = glu.xlsub(irep);
+ kmax = glu.xlsub(irep1) - 1;
+ for (krow = kmin; krow <= kmax; krow++)
+ {
+ if (glu.lsub(krow) == pivrow)
+ {
+ do_prune = true;
+ break;
+ }
+ }
+ }
+
+ if (do_prune)
+ {
+ // do a quicksort-type partition
+ // movnum=true means that the num values have to be exchanged
+ movnum = false;
+ if (irep == glu.xsup(glu.supno(irep)) ) // Snode of size 1
+ movnum = true;
+
+ while (kmin <= kmax)
+ {
+ if (perm_r(glu.lsub(kmax)) == emptyIdxLU)
+ kmax--;
+ else if ( perm_r(glu.lsub(kmin)) != emptyIdxLU)
+ kmin++;
+ else
+ {
+ // kmin below pivrow (not yet pivoted), and kmax
+ // above pivrow: interchange the two suscripts
+ std::swap(glu.lsub(kmin), glu.lsub(kmax));
+
+ // If the supernode has only one column, then we
+ // only keep one set of subscripts. For any subscript
+ // intercnahge performed, similar interchange must be
+ // done on the numerical values.
+ if (movnum)
+ {
+ minloc = glu.xlusup(irep) + ( kmin - glu.xlsub(irep) );
+ maxloc = glu.xlusup(irep) + ( kmax - glu.xlsub(irep) );
+ std::swap(glu.lusup(minloc), glu.lusup(maxloc));
+ }
+ kmin++;
+ kmax--;
+ }
+ } // end while
+
+ xprune(irep) = kmin; //Pruning
+ } // end if do_prune
+ } // end pruning
+ } // End for each U-segment
+}
+
+} // end namespace internal
+} // end namespace Eigen
+
+#endif // SPARSELU_PRUNEL_H
diff --git a/Eigen/src/SparseLU/SparseLU_relax_snode.h b/Eigen/src/SparseLU/SparseLU_relax_snode.h
new file mode 100644
index 000000000..58ec32e27
--- /dev/null
+++ b/Eigen/src/SparseLU/SparseLU_relax_snode.h
@@ -0,0 +1,83 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/* This file is a modified version of heap_relax_snode.c file in SuperLU
+ * -- SuperLU routine (version 3.0) --
+ * Univ. of California Berkeley, Xerox Palo Alto Research Center,
+ * and Lawrence Berkeley National Lab.
+ * October 15, 2003
+ *
+ * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
+ * EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program for any
+ * purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is
+ * granted, provided the above notices are retained, and a notice that
+ * the code was modified is included with the above copyright notice.
+ */
+
+#ifndef SPARSELU_RELAX_SNODE_H
+#define SPARSELU_RELAX_SNODE_H
+
+namespace Eigen {
+
+namespace internal {
+
+/**
+ * \brief Identify the initial relaxed supernodes
+ *
+ * This routine is applied to a column elimination tree.
+ * It assumes that the matrix has been reordered according to the postorder of the etree
+ * \param n the number of columns
+ * \param et elimination tree
+ * \param relax_columns Maximum number of columns allowed in a relaxed snode
+ * \param descendants Number of descendants of each node in the etree
+ * \param relax_end last column in a supernode
+ */
+template <typename Scalar, typename Index>
+void SparseLUImpl<Scalar,Index>::relax_snode (const Index n, IndexVector& et, const Index relax_columns, IndexVector& descendants, IndexVector& relax_end)
+{
+
+ // compute the number of descendants of each node in the etree
+ Index j, parent;
+ relax_end.setConstant(emptyIdxLU);
+ descendants.setZero();
+ for (j = 0; j < n; j++)
+ {
+ parent = et(j);
+ if (parent != n) // not the dummy root
+ descendants(parent) += descendants(j) + 1;
+ }
+ // Identify the relaxed supernodes by postorder traversal of the etree
+ Index snode_start; // beginning of a snode
+ for (j = 0; j < n; )
+ {
+ parent = et(j);
+ snode_start = j;
+ while ( parent != n && descendants(parent) < relax_columns )
+ {
+ j = parent;
+ parent = et(j);
+ }
+ // Found a supernode in postordered etree, j is the last column
+ relax_end(snode_start) = j; // Record last column
+ j++;
+ // Search for a new leaf
+ while (descendants(j) != 0 && j < n) j++;
+ } // End postorder traversal of the etree
+
+}
+
+} // end namespace internal
+
+} // end namespace Eigen
+#endif
diff --git a/Eigen/src/SparseQR/CMakeLists.txt b/Eigen/src/SparseQR/CMakeLists.txt
new file mode 100644
index 000000000..f9ddf2bdb
--- /dev/null
+++ b/Eigen/src/SparseQR/CMakeLists.txt
@@ -0,0 +1,6 @@
+FILE(GLOB Eigen_SparseQR_SRCS "*.h")
+
+INSTALL(FILES
+ ${Eigen_SparseQR_SRCS}
+ DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/SparseQR/ COMPONENT Devel
+ )
diff --git a/Eigen/src/SparseQR/SparseQR.h b/Eigen/src/SparseQR/SparseQR.h
new file mode 100644
index 000000000..4c6553bf2
--- /dev/null
+++ b/Eigen/src/SparseQR/SparseQR.h
@@ -0,0 +1,685 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012-2013 Desire Nuentsa <desire.nuentsa_wakam@inria.fr>
+// Copyright (C) 2012-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef EIGEN_SPARSE_QR_H
+#define EIGEN_SPARSE_QR_H
+
+namespace Eigen {
+
+template<typename MatrixType, typename OrderingType> class SparseQR;
+template<typename SparseQRType> struct SparseQRMatrixQReturnType;
+template<typename SparseQRType> struct SparseQRMatrixQTransposeReturnType;
+template<typename SparseQRType, typename Derived> struct SparseQR_QProduct;
+namespace internal {
+ template <typename SparseQRType> struct traits<SparseQRMatrixQReturnType<SparseQRType> >
+ {
+ typedef typename SparseQRType::MatrixType ReturnType;
+ typedef typename ReturnType::Index Index;
+ typedef typename ReturnType::StorageKind StorageKind;
+ };
+ template <typename SparseQRType> struct traits<SparseQRMatrixQTransposeReturnType<SparseQRType> >
+ {
+ typedef typename SparseQRType::MatrixType ReturnType;
+ };
+ template <typename SparseQRType, typename Derived> struct traits<SparseQR_QProduct<SparseQRType, Derived> >
+ {
+ typedef typename Derived::PlainObject ReturnType;
+ };
+} // End namespace internal
+
+/**
+ * \ingroup SparseQR_Module
+ * \class SparseQR
+ * \brief Sparse left-looking rank-revealing QR factorization
+ *
+ * This class implements a left-looking rank-revealing QR decomposition
+ * of sparse matrices. When a column has a norm less than a given tolerance
+ * it is implicitly permuted to the end. The QR factorization thus obtained is
+ * given by A*P = Q*R where R is upper triangular or trapezoidal.
+ *
+ * P is the column permutation which is the product of the fill-reducing and the
+ * rank-revealing permutations. Use colsPermutation() to get it.
+ *
+ * Q is the orthogonal matrix represented as products of Householder reflectors.
+ * Use matrixQ() to get an expression and matrixQ().transpose() to get the transpose.
+ * You can then apply it to a vector.
+ *
+ * R is the sparse triangular or trapezoidal matrix. The later occurs when A is rank-deficient.
+ * matrixR().topLeftCorner(rank(), rank()) always returns a triangular factor of full rank.
+ *
+ * \tparam _MatrixType The type of the sparse matrix A, must be a column-major SparseMatrix<>
+ * \tparam _OrderingType The fill-reducing ordering method. See the \link OrderingMethods_Module
+ * OrderingMethods \endlink module for the list of built-in and external ordering methods.
+ *
+ * \warning The input sparse matrix A must be in compressed mode (see SparseMatrix::makeCompressed()).
+ *
+ */
+template<typename _MatrixType, typename _OrderingType>
+class SparseQR
+{
+ public:
+ typedef _MatrixType MatrixType;
+ typedef _OrderingType OrderingType;
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::RealScalar RealScalar;
+ typedef typename MatrixType::Index Index;
+ typedef SparseMatrix<Scalar,ColMajor,Index> QRMatrixType;
+ typedef Matrix<Index, Dynamic, 1> IndexVector;
+ typedef Matrix<Scalar, Dynamic, 1> ScalarVector;
+ typedef PermutationMatrix<Dynamic, Dynamic, Index> PermutationType;
+ public:
+ SparseQR () : m_isInitialized(false), m_analysisIsok(false), m_lastError(""), m_useDefaultThreshold(true),m_isQSorted(false)
+ { }
+
+ /** Construct a QR factorization of the matrix \a mat.
+ *
+ * \warning The matrix \a mat must be in compressed mode (see SparseMatrix::makeCompressed()).
+ *
+ * \sa compute()
+ */
+ SparseQR(const MatrixType& mat) : m_isInitialized(false), m_analysisIsok(false), m_lastError(""), m_useDefaultThreshold(true),m_isQSorted(false)
+ {
+ compute(mat);
+ }
+
+ /** Computes the QR factorization of the sparse matrix \a mat.
+ *
+ * \warning The matrix \a mat must be in compressed mode (see SparseMatrix::makeCompressed()).
+ *
+ * \sa analyzePattern(), factorize()
+ */
+ void compute(const MatrixType& mat)
+ {
+ analyzePattern(mat);
+ factorize(mat);
+ }
+ void analyzePattern(const MatrixType& mat);
+ void factorize(const MatrixType& mat);
+
+ /** \returns the number of rows of the represented matrix.
+ */
+ inline Index rows() const { return m_pmat.rows(); }
+
+ /** \returns the number of columns of the represented matrix.
+ */
+ inline Index cols() const { return m_pmat.cols();}
+
+ /** \returns a const reference to the \b sparse upper triangular matrix R of the QR factorization.
+ */
+ const QRMatrixType& matrixR() const { return m_R; }
+
+ /** \returns the number of non linearly dependent columns as determined by the pivoting threshold.
+ *
+ * \sa setPivotThreshold()
+ */
+ Index rank() const
+ {
+ eigen_assert(m_isInitialized && "The factorization should be called first, use compute()");
+ return m_nonzeropivots;
+ }
+
+ /** \returns an expression of the matrix Q as products of sparse Householder reflectors.
+ * The common usage of this function is to apply it to a dense matrix or vector
+ * \code
+ * VectorXd B1, B2;
+ * // Initialize B1
+ * B2 = matrixQ() * B1;
+ * \endcode
+ *
+ * To get a plain SparseMatrix representation of Q:
+ * \code
+ * SparseMatrix<double> Q;
+ * Q = SparseQR<SparseMatrix<double> >(A).matrixQ();
+ * \endcode
+ * Internally, this call simply performs a sparse product between the matrix Q
+ * and a sparse identity matrix. However, due to the fact that the sparse
+ * reflectors are stored unsorted, two transpositions are needed to sort
+ * them before performing the product.
+ */
+ SparseQRMatrixQReturnType<SparseQR> matrixQ() const
+ { return SparseQRMatrixQReturnType<SparseQR>(*this); }
+
+ /** \returns a const reference to the column permutation P that was applied to A such that A*P = Q*R
+ * It is the combination of the fill-in reducing permutation and numerical column pivoting.
+ */
+ const PermutationType& colsPermutation() const
+ {
+ eigen_assert(m_isInitialized && "Decomposition is not initialized.");
+ return m_outputPerm_c;
+ }
+
+ /** \returns A string describing the type of error.
+ * This method is provided to ease debugging, not to handle errors.
+ */
+ std::string lastErrorMessage() const { return m_lastError; }
+
+ /** \internal */
+ template<typename Rhs, typename Dest>
+ bool _solve(const MatrixBase<Rhs> &B, MatrixBase<Dest> &dest) const
+ {
+ eigen_assert(m_isInitialized && "The factorization should be called first, use compute()");
+ eigen_assert(this->rows() == B.rows() && "SparseQR::solve() : invalid number of rows in the right hand side matrix");
+
+ Index rank = this->rank();
+
+ // Compute Q^T * b;
+ typename Dest::PlainObject y, b;
+ y = this->matrixQ().transpose() * B;
+ b = y;
+
+ // Solve with the triangular matrix R
+ y.resize((std::max)(cols(),Index(y.rows())),y.cols());
+ y.topRows(rank) = this->matrixR().topLeftCorner(rank, rank).template triangularView<Upper>().solve(b.topRows(rank));
+ y.bottomRows(y.rows()-rank).setZero();
+
+ // Apply the column permutation
+ if (m_perm_c.size()) dest = colsPermutation() * y.topRows(cols());
+ else dest = y.topRows(cols());
+
+ m_info = Success;
+ return true;
+ }
+
+
+ /** Sets the threshold that is used to determine linearly dependent columns during the factorization.
+ *
+ * In practice, if during the factorization the norm of the column that has to be eliminated is below
+ * this threshold, then the entire column is treated as zero, and it is moved at the end.
+ */
+ void setPivotThreshold(const RealScalar& threshold)
+ {
+ m_useDefaultThreshold = false;
+ m_threshold = threshold;
+ }
+
+ /** \returns the solution X of \f$ A X = B \f$ using the current decomposition of A.
+ *
+ * \sa compute()
+ */
+ template<typename Rhs>
+ inline const internal::solve_retval<SparseQR, Rhs> solve(const MatrixBase<Rhs>& B) const
+ {
+ eigen_assert(m_isInitialized && "The factorization should be called first, use compute()");
+ eigen_assert(this->rows() == B.rows() && "SparseQR::solve() : invalid number of rows in the right hand side matrix");
+ return internal::solve_retval<SparseQR, Rhs>(*this, B.derived());
+ }
+ template<typename Rhs>
+ inline const internal::sparse_solve_retval<SparseQR, Rhs> solve(const SparseMatrixBase<Rhs>& B) const
+ {
+ eigen_assert(m_isInitialized && "The factorization should be called first, use compute()");
+ eigen_assert(this->rows() == B.rows() && "SparseQR::solve() : invalid number of rows in the right hand side matrix");
+ return internal::sparse_solve_retval<SparseQR, Rhs>(*this, B.derived());
+ }
+
+ /** \brief Reports whether previous computation was successful.
+ *
+ * \returns \c Success if computation was successful,
+ * \c NumericalIssue if the QR factorization reports a numerical problem
+ * \c InvalidInput if the input matrix is invalid
+ *
+ * \sa iparm()
+ */
+ ComputationInfo info() const
+ {
+ eigen_assert(m_isInitialized && "Decomposition is not initialized.");
+ return m_info;
+ }
+
+ protected:
+ inline void sort_matrix_Q()
+ {
+ if(this->m_isQSorted) return;
+ // The matrix Q is sorted during the transposition
+ SparseMatrix<Scalar, RowMajor, Index> mQrm(this->m_Q);
+ this->m_Q = mQrm;
+ this->m_isQSorted = true;
+ }
+
+
+ protected:
+ bool m_isInitialized;
+ bool m_analysisIsok;
+ bool m_factorizationIsok;
+ mutable ComputationInfo m_info;
+ std::string m_lastError;
+ QRMatrixType m_pmat; // Temporary matrix
+ QRMatrixType m_R; // The triangular factor matrix
+ QRMatrixType m_Q; // The orthogonal reflectors
+ ScalarVector m_hcoeffs; // The Householder coefficients
+ PermutationType m_perm_c; // Fill-reducing Column permutation
+ PermutationType m_pivotperm; // The permutation for rank revealing
+ PermutationType m_outputPerm_c; // The final column permutation
+ RealScalar m_threshold; // Threshold to determine null Householder reflections
+ bool m_useDefaultThreshold; // Use default threshold
+ Index m_nonzeropivots; // Number of non zero pivots found
+ IndexVector m_etree; // Column elimination tree
+ IndexVector m_firstRowElt; // First element in each row
+ bool m_isQSorted; // whether Q is sorted or not
+
+ template <typename, typename > friend struct SparseQR_QProduct;
+ template <typename > friend struct SparseQRMatrixQReturnType;
+
+};
+
+/** \brief Preprocessing step of a QR factorization
+ *
+ * \warning The matrix \a mat must be in compressed mode (see SparseMatrix::makeCompressed()).
+ *
+ * In this step, the fill-reducing permutation is computed and applied to the columns of A
+ * and the column elimination tree is computed as well. Only the sparsity pattern of \a mat is exploited.
+ *
+ * \note In this step it is assumed that there is no empty row in the matrix \a mat.
+ */
+template <typename MatrixType, typename OrderingType>
+void SparseQR<MatrixType,OrderingType>::analyzePattern(const MatrixType& mat)
+{
+ eigen_assert(mat.isCompressed() && "SparseQR requires a sparse matrix in compressed mode. Call .makeCompressed() before passing it to SparseQR");
+ // Compute the column fill reducing ordering
+ OrderingType ord;
+ ord(mat, m_perm_c);
+ Index n = mat.cols();
+ Index m = mat.rows();
+ Index diagSize = (std::min)(m,n);
+
+ if (!m_perm_c.size())
+ {
+ m_perm_c.resize(n);
+ m_perm_c.indices().setLinSpaced(n, 0,n-1);
+ }
+
+ // Compute the column elimination tree of the permuted matrix
+ m_outputPerm_c = m_perm_c.inverse();
+ internal::coletree(mat, m_etree, m_firstRowElt, m_outputPerm_c.indices().data());
+
+ m_R.resize(m, n);
+ m_Q.resize(m, diagSize);
+
+ // Allocate space for nonzero elements : rough estimation
+ m_R.reserve(2*mat.nonZeros()); //FIXME Get a more accurate estimation through symbolic factorization with the etree
+ m_Q.reserve(2*mat.nonZeros());
+ m_hcoeffs.resize(diagSize);
+ m_analysisIsok = true;
+}
+
+/** \brief Performs the numerical QR factorization of the input matrix
+ *
+ * The function SparseQR::analyzePattern(const MatrixType&) must have been called beforehand with
+ * a matrix having the same sparsity pattern than \a mat.
+ *
+ * \param mat The sparse column-major matrix
+ */
+template <typename MatrixType, typename OrderingType>
+void SparseQR<MatrixType,OrderingType>::factorize(const MatrixType& mat)
+{
+ using std::abs;
+ using std::max;
+
+ eigen_assert(m_analysisIsok && "analyzePattern() should be called before this step");
+ Index m = mat.rows();
+ Index n = mat.cols();
+ Index diagSize = (std::min)(m,n);
+ IndexVector mark((std::max)(m,n)); mark.setConstant(-1); // Record the visited nodes
+ IndexVector Ridx(n), Qidx(m); // Store temporarily the row indexes for the current column of R and Q
+ Index nzcolR, nzcolQ; // Number of nonzero for the current column of R and Q
+ ScalarVector tval(m); // The dense vector used to compute the current column
+ RealScalar pivotThreshold = m_threshold;
+
+ m_pmat = mat;
+ m_pmat.uncompress(); // To have the innerNonZeroPtr allocated
+ // Apply the fill-in reducing permutation lazily:
+ for (int i = 0; i < n; i++)
+ {
+ Index p = m_perm_c.size() ? m_perm_c.indices()(i) : i;
+ m_pmat.outerIndexPtr()[p] = mat.outerIndexPtr()[i];
+ m_pmat.innerNonZeroPtr()[p] = mat.outerIndexPtr()[i+1] - mat.outerIndexPtr()[i];
+ }
+
+ /* Compute the default threshold as in MatLab, see:
+ * Tim Davis, "Algorithm 915, SuiteSparseQR: Multifrontal Multithreaded Rank-Revealing
+ * Sparse QR Factorization, ACM Trans. on Math. Soft. 38(1), 2011, Page 8:3
+ */
+ if(m_useDefaultThreshold)
+ {
+ RealScalar max2Norm = 0.0;
+ for (int j = 0; j < n; j++) max2Norm = (max)(max2Norm, m_pmat.col(j).norm());
+ pivotThreshold = 20 * (m + n) * max2Norm * NumTraits<RealScalar>::epsilon();
+ }
+
+ // Initialize the numerical permutation
+ m_pivotperm.setIdentity(n);
+
+ Index nonzeroCol = 0; // Record the number of valid pivots
+ m_Q.startVec(0);
+
+ // Left looking rank-revealing QR factorization: compute a column of R and Q at a time
+ for (Index col = 0; col < n; ++col)
+ {
+ mark.setConstant(-1);
+ m_R.startVec(col);
+ mark(nonzeroCol) = col;
+ Qidx(0) = nonzeroCol;
+ nzcolR = 0; nzcolQ = 1;
+ bool found_diag = nonzeroCol>=m;
+ tval.setZero();
+
+ // Symbolic factorization: find the nonzero locations of the column k of the factors R and Q, i.e.,
+ // all the nodes (with indexes lower than rank) reachable through the column elimination tree (etree) rooted at node k.
+ // Note: if the diagonal entry does not exist, then its contribution must be explicitly added,
+ // thus the trick with found_diag that permits to do one more iteration on the diagonal element if this one has not been found.
+ for (typename MatrixType::InnerIterator itp(m_pmat, col); itp || !found_diag; ++itp)
+ {
+ Index curIdx = nonzeroCol;
+ if(itp) curIdx = itp.row();
+ if(curIdx == nonzeroCol) found_diag = true;
+
+ // Get the nonzeros indexes of the current column of R
+ Index st = m_firstRowElt(curIdx); // The traversal of the etree starts here
+ if (st < 0 )
+ {
+ m_lastError = "Empty row found during numerical factorization";
+ m_info = InvalidInput;
+ return;
+ }
+
+ // Traverse the etree
+ Index bi = nzcolR;
+ for (; mark(st) != col; st = m_etree(st))
+ {
+ Ridx(nzcolR) = st; // Add this row to the list,
+ mark(st) = col; // and mark this row as visited
+ nzcolR++;
+ }
+
+ // Reverse the list to get the topological ordering
+ Index nt = nzcolR-bi;
+ for(Index i = 0; i < nt/2; i++) std::swap(Ridx(bi+i), Ridx(nzcolR-i-1));
+
+ // Copy the current (curIdx,pcol) value of the input matrix
+ if(itp) tval(curIdx) = itp.value();
+ else tval(curIdx) = Scalar(0);
+
+ // Compute the pattern of Q(:,k)
+ if(curIdx > nonzeroCol && mark(curIdx) != col )
+ {
+ Qidx(nzcolQ) = curIdx; // Add this row to the pattern of Q,
+ mark(curIdx) = col; // and mark it as visited
+ nzcolQ++;
+ }
+ }
+
+ // Browse all the indexes of R(:,col) in reverse order
+ for (Index i = nzcolR-1; i >= 0; i--)
+ {
+ Index curIdx = Ridx(i);
+
+ // Apply the curIdx-th householder vector to the current column (temporarily stored into tval)
+ Scalar tdot(0);
+
+ // First compute q' * tval
+ tdot = m_Q.col(curIdx).dot(tval);
+
+ tdot *= m_hcoeffs(curIdx);
+
+ // Then update tval = tval - q * tau
+ // FIXME: tval -= tdot * m_Q.col(curIdx) should amount to the same (need to check/add support for efficient "dense ?= sparse")
+ for (typename QRMatrixType::InnerIterator itq(m_Q, curIdx); itq; ++itq)
+ tval(itq.row()) -= itq.value() * tdot;
+
+ // Detect fill-in for the current column of Q
+ if(m_etree(Ridx(i)) == nonzeroCol)
+ {
+ for (typename QRMatrixType::InnerIterator itq(m_Q, curIdx); itq; ++itq)
+ {
+ Index iQ = itq.row();
+ if (mark(iQ) != col)
+ {
+ Qidx(nzcolQ++) = iQ; // Add this row to the pattern of Q,
+ mark(iQ) = col; // and mark it as visited
+ }
+ }
+ }
+ } // End update current column
+
+ Scalar tau;
+ RealScalar beta = 0;
+
+ if(nonzeroCol < diagSize)
+ {
+ // Compute the Householder reflection that eliminate the current column
+ // FIXME this step should call the Householder module.
+ Scalar c0 = nzcolQ ? tval(Qidx(0)) : Scalar(0);
+
+ // First, the squared norm of Q((col+1):m, col)
+ RealScalar sqrNorm = 0.;
+ for (Index itq = 1; itq < nzcolQ; ++itq) sqrNorm += numext::abs2(tval(Qidx(itq)));
+ if(sqrNorm == RealScalar(0) && numext::imag(c0) == RealScalar(0))
+ {
+ tau = RealScalar(0);
+ beta = numext::real(c0);
+ tval(Qidx(0)) = 1;
+ }
+ else
+ {
+ using std::sqrt;
+ beta = sqrt(numext::abs2(c0) + sqrNorm);
+ if(numext::real(c0) >= RealScalar(0))
+ beta = -beta;
+ tval(Qidx(0)) = 1;
+ for (Index itq = 1; itq < nzcolQ; ++itq)
+ tval(Qidx(itq)) /= (c0 - beta);
+ tau = numext::conj((beta-c0) / beta);
+
+ }
+ }
+
+ // Insert values in R
+ for (Index i = nzcolR-1; i >= 0; i--)
+ {
+ Index curIdx = Ridx(i);
+ if(curIdx < nonzeroCol)
+ {
+ m_R.insertBackByOuterInnerUnordered(col, curIdx) = tval(curIdx);
+ tval(curIdx) = Scalar(0.);
+ }
+ }
+
+ if(nonzeroCol < diagSize && abs(beta) >= pivotThreshold)
+ {
+ m_R.insertBackByOuterInner(col, nonzeroCol) = beta;
+ // The householder coefficient
+ m_hcoeffs(nonzeroCol) = tau;
+ // Record the householder reflections
+ for (Index itq = 0; itq < nzcolQ; ++itq)
+ {
+ Index iQ = Qidx(itq);
+ m_Q.insertBackByOuterInnerUnordered(nonzeroCol,iQ) = tval(iQ);
+ tval(iQ) = Scalar(0.);
+ }
+ nonzeroCol++;
+ if(nonzeroCol<diagSize)
+ m_Q.startVec(nonzeroCol);
+ }
+ else
+ {
+ // Zero pivot found: move implicitly this column to the end
+ for (Index j = nonzeroCol; j < n-1; j++)
+ std::swap(m_pivotperm.indices()(j), m_pivotperm.indices()[j+1]);
+
+ // Recompute the column elimination tree
+ internal::coletree(m_pmat, m_etree, m_firstRowElt, m_pivotperm.indices().data());
+ }
+ }
+
+ m_hcoeffs.tail(diagSize-nonzeroCol).setZero();
+
+ // Finalize the column pointers of the sparse matrices R and Q
+ m_Q.finalize();
+ m_Q.makeCompressed();
+ m_R.finalize();
+ m_R.makeCompressed();
+ m_isQSorted = false;
+
+ m_nonzeropivots = nonzeroCol;
+
+ if(nonzeroCol<n)
+ {
+ // Permute the triangular factor to put the 'dead' columns to the end
+ MatrixType tempR(m_R);
+ m_R = tempR * m_pivotperm;
+
+ // Update the column permutation
+ m_outputPerm_c = m_outputPerm_c * m_pivotperm;
+ }
+
+ m_isInitialized = true;
+ m_factorizationIsok = true;
+ m_info = Success;
+}
+
+namespace internal {
+
+template<typename _MatrixType, typename OrderingType, typename Rhs>
+struct solve_retval<SparseQR<_MatrixType,OrderingType>, Rhs>
+ : solve_retval_base<SparseQR<_MatrixType,OrderingType>, Rhs>
+{
+ typedef SparseQR<_MatrixType,OrderingType> Dec;
+ EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs)
+
+ template<typename Dest> void evalTo(Dest& dst) const
+ {
+ dec()._solve(rhs(),dst);
+ }
+};
+template<typename _MatrixType, typename OrderingType, typename Rhs>
+struct sparse_solve_retval<SparseQR<_MatrixType, OrderingType>, Rhs>
+ : sparse_solve_retval_base<SparseQR<_MatrixType, OrderingType>, Rhs>
+{
+ typedef SparseQR<_MatrixType, OrderingType> Dec;
+ EIGEN_MAKE_SPARSE_SOLVE_HELPERS(Dec, Rhs)
+
+ template<typename Dest> void evalTo(Dest& dst) const
+ {
+ this->defaultEvalTo(dst);
+ }
+};
+} // end namespace internal
+
+template <typename SparseQRType, typename Derived>
+struct SparseQR_QProduct : ReturnByValue<SparseQR_QProduct<SparseQRType, Derived> >
+{
+ typedef typename SparseQRType::QRMatrixType MatrixType;
+ typedef typename SparseQRType::Scalar Scalar;
+ typedef typename SparseQRType::Index Index;
+ // Get the references
+ SparseQR_QProduct(const SparseQRType& qr, const Derived& other, bool transpose) :
+ m_qr(qr),m_other(other),m_transpose(transpose) {}
+ inline Index rows() const { return m_transpose ? m_qr.rows() : m_qr.cols(); }
+ inline Index cols() const { return m_other.cols(); }
+
+ // Assign to a vector
+ template<typename DesType>
+ void evalTo(DesType& res) const
+ {
+ Index m = m_qr.rows();
+ Index n = m_qr.cols();
+ Index diagSize = (std::min)(m,n);
+ res = m_other;
+ if (m_transpose)
+ {
+ eigen_assert(m_qr.m_Q.rows() == m_other.rows() && "Non conforming object sizes");
+ //Compute res = Q' * other column by column
+ for(Index j = 0; j < res.cols(); j++){
+ for (Index k = 0; k < diagSize; k++)
+ {
+ Scalar tau = Scalar(0);
+ tau = m_qr.m_Q.col(k).dot(res.col(j));
+ if(tau==Scalar(0)) continue;
+ tau = tau * m_qr.m_hcoeffs(k);
+ res.col(j) -= tau * m_qr.m_Q.col(k);
+ }
+ }
+ }
+ else
+ {
+ eigen_assert(m_qr.m_Q.rows() == m_other.rows() && "Non conforming object sizes");
+ // Compute res = Q * other column by column
+ for(Index j = 0; j < res.cols(); j++)
+ {
+ for (Index k = diagSize-1; k >=0; k--)
+ {
+ Scalar tau = Scalar(0);
+ tau = m_qr.m_Q.col(k).dot(res.col(j));
+ if(tau==Scalar(0)) continue;
+ tau = tau * m_qr.m_hcoeffs(k);
+ res.col(j) -= tau * m_qr.m_Q.col(k);
+ }
+ }
+ }
+ }
+
+ const SparseQRType& m_qr;
+ const Derived& m_other;
+ bool m_transpose;
+};
+
+template<typename SparseQRType>
+struct SparseQRMatrixQReturnType : public EigenBase<SparseQRMatrixQReturnType<SparseQRType> >
+{
+ typedef typename SparseQRType::Index Index;
+ typedef typename SparseQRType::Scalar Scalar;
+ typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
+ SparseQRMatrixQReturnType(const SparseQRType& qr) : m_qr(qr) {}
+ template<typename Derived>
+ SparseQR_QProduct<SparseQRType, Derived> operator*(const MatrixBase<Derived>& other)
+ {
+ return SparseQR_QProduct<SparseQRType,Derived>(m_qr,other.derived(),false);
+ }
+ SparseQRMatrixQTransposeReturnType<SparseQRType> adjoint() const
+ {
+ return SparseQRMatrixQTransposeReturnType<SparseQRType>(m_qr);
+ }
+ inline Index rows() const { return m_qr.rows(); }
+ inline Index cols() const { return (std::min)(m_qr.rows(),m_qr.cols()); }
+ // To use for operations with the transpose of Q
+ SparseQRMatrixQTransposeReturnType<SparseQRType> transpose() const
+ {
+ return SparseQRMatrixQTransposeReturnType<SparseQRType>(m_qr);
+ }
+ template<typename Dest> void evalTo(MatrixBase<Dest>& dest) const
+ {
+ dest.derived() = m_qr.matrixQ() * Dest::Identity(m_qr.rows(), m_qr.rows());
+ }
+ template<typename Dest> void evalTo(SparseMatrixBase<Dest>& dest) const
+ {
+ Dest idMat(m_qr.rows(), m_qr.rows());
+ idMat.setIdentity();
+ // Sort the sparse householder reflectors if needed
+ const_cast<SparseQRType *>(&m_qr)->sort_matrix_Q();
+ dest.derived() = SparseQR_QProduct<SparseQRType, Dest>(m_qr, idMat, false);
+ }
+
+ const SparseQRType& m_qr;
+};
+
+template<typename SparseQRType>
+struct SparseQRMatrixQTransposeReturnType
+{
+ SparseQRMatrixQTransposeReturnType(const SparseQRType& qr) : m_qr(qr) {}
+ template<typename Derived>
+ SparseQR_QProduct<SparseQRType,Derived> operator*(const MatrixBase<Derived>& other)
+ {
+ return SparseQR_QProduct<SparseQRType,Derived>(m_qr,other.derived(), true);
+ }
+ const SparseQRType& m_qr;
+};
+
+} // end namespace Eigen
+
+#endif
diff --git a/Eigen/src/StlSupport/StdDeque.h b/Eigen/src/StlSupport/StdDeque.h
index 4ee8e5c10..aaf66330b 100644
--- a/Eigen/src/StlSupport/StdDeque.h
+++ b/Eigen/src/StlSupport/StdDeque.h
@@ -11,7 +11,7 @@
#ifndef EIGEN_STDDEQUE_H
#define EIGEN_STDDEQUE_H
-#include "Eigen/src/StlSupport/details.h"
+#include "details.h"
// Define the explicit instantiation (e.g. necessary for the Intel compiler)
#if defined(__INTEL_COMPILER) || defined(__GNUC__)
diff --git a/Eigen/src/StlSupport/StdList.h b/Eigen/src/StlSupport/StdList.h
index 627381ece..3c742430c 100644
--- a/Eigen/src/StlSupport/StdList.h
+++ b/Eigen/src/StlSupport/StdList.h
@@ -10,7 +10,7 @@
#ifndef EIGEN_STDLIST_H
#define EIGEN_STDLIST_H
-#include "Eigen/src/StlSupport/details.h"
+#include "details.h"
// Define the explicit instantiation (e.g. necessary for the Intel compiler)
#if defined(__INTEL_COMPILER) || defined(__GNUC__)
diff --git a/Eigen/src/StlSupport/StdVector.h b/Eigen/src/StlSupport/StdVector.h
index 40a9abefa..611664a2e 100644
--- a/Eigen/src/StlSupport/StdVector.h
+++ b/Eigen/src/StlSupport/StdVector.h
@@ -11,7 +11,7 @@
#ifndef EIGEN_STDVECTOR_H
#define EIGEN_STDVECTOR_H
-#include "Eigen/src/StlSupport/details.h"
+#include "details.h"
/**
* This section contains a convenience MACRO which allows an easy specialization of
diff --git a/Eigen/src/SuperLUSupport/SuperLUSupport.h b/Eigen/src/SuperLUSupport/SuperLUSupport.h
index 11fb014dd..bcb355760 100644
--- a/Eigen/src/SuperLUSupport/SuperLUSupport.h
+++ b/Eigen/src/SuperLUSupport/SuperLUSupport.h
@@ -160,7 +160,7 @@ struct SluMatrix : SuperMatrix
res.ncol = mat.cols();
res.storage.lda = MatrixType::IsVectorAtCompileTime ? mat.size() : mat.outerStride();
- res.storage.values = mat.data();
+ res.storage.values = (void*)(mat.data());
return res;
}
@@ -353,14 +353,14 @@ class SuperLUBase : internal::noncopyable
*
* \sa compute()
*/
-// template<typename Rhs>
-// inline const internal::sparse_solve_retval<SuperLU, Rhs> solve(const SparseMatrixBase<Rhs>& b) const
-// {
-// eigen_assert(m_isInitialized && "SuperLU is not initialized.");
-// eigen_assert(rows()==b.rows()
-// && "SuperLU::solve(): invalid number of rows of the right hand side matrix b");
-// return internal::sparse_solve_retval<SuperLU, Rhs>(*this, b.derived());
-// }
+ template<typename Rhs>
+ inline const internal::sparse_solve_retval<SuperLUBase, Rhs> solve(const SparseMatrixBase<Rhs>& b) const
+ {
+ eigen_assert(m_isInitialized && "SuperLU is not initialized.");
+ eigen_assert(rows()==b.rows()
+ && "SuperLU::solve(): invalid number of rows of the right hand side matrix b");
+ return internal::sparse_solve_retval<SuperLUBase, Rhs>(*this, b.derived());
+ }
/** Performs a symbolic decomposition on the sparcity of \a matrix.
*
@@ -377,7 +377,7 @@ class SuperLUBase : internal::noncopyable
}
template<typename Stream>
- void dumpMemory(Stream& s)
+ void dumpMemory(Stream& /*s*/)
{}
protected:
@@ -496,8 +496,8 @@ class SuperLU : public SuperLUBase<_MatrixType,SuperLU<_MatrixType> >
SuperLU(const MatrixType& matrix) : Base()
{
- Base::init();
- compute(matrix);
+ init();
+ Base::compute(matrix);
}
~SuperLU()
@@ -612,6 +612,7 @@ void SuperLU<MatrixType>::factorize(const MatrixType& a)
this->initFactorization(a);
+ m_sluOptions.ColPerm = COLAMD;
int info = 0;
RealScalar recip_pivot_growth, rcond;
RealScalar ferr, berr;
@@ -833,7 +834,7 @@ class SuperILU : public SuperLUBase<_MatrixType,SuperILU<_MatrixType> >
SuperILU(const MatrixType& matrix) : Base()
{
init();
- compute(matrix);
+ Base::compute(matrix);
}
~SuperILU()
@@ -1014,7 +1015,7 @@ struct sparse_solve_retval<SuperLUBase<_MatrixType,Derived>, Rhs>
template<typename Dest> void evalTo(Dest& dst) const
{
- dec().derived()._solve(rhs(),dst);
+ this->defaultEvalTo(dst);
}
};
diff --git a/Eigen/src/UmfPackSupport/UmfPackSupport.h b/Eigen/src/UmfPackSupport/UmfPackSupport.h
index f01720362..3a48cecf7 100644
--- a/Eigen/src/UmfPackSupport/UmfPackSupport.h
+++ b/Eigen/src/UmfPackSupport/UmfPackSupport.h
@@ -39,7 +39,7 @@ inline int umfpack_symbolic(int n_row,int n_col,
const int Ap[], const int Ai[], const std::complex<double> Ax[], void **Symbolic,
const double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO])
{
- return umfpack_zi_symbolic(n_row,n_col,Ap,Ai,&internal::real_ref(Ax[0]),0,Symbolic,Control,Info);
+ return umfpack_zi_symbolic(n_row,n_col,Ap,Ai,&numext::real_ref(Ax[0]),0,Symbolic,Control,Info);
}
inline int umfpack_numeric( const int Ap[], const int Ai[], const double Ax[],
@@ -53,7 +53,7 @@ inline int umfpack_numeric( const int Ap[], const int Ai[], const std::complex<d
void *Symbolic, void **Numeric,
const double Control[UMFPACK_CONTROL],double Info [UMFPACK_INFO])
{
- return umfpack_zi_numeric(Ap,Ai,&internal::real_ref(Ax[0]),0,Symbolic,Numeric,Control,Info);
+ return umfpack_zi_numeric(Ap,Ai,&numext::real_ref(Ax[0]),0,Symbolic,Numeric,Control,Info);
}
inline int umfpack_solve( int sys, const int Ap[], const int Ai[], const double Ax[],
@@ -67,7 +67,7 @@ inline int umfpack_solve( int sys, const int Ap[], const int Ai[], const std::co
std::complex<double> X[], const std::complex<double> B[], void *Numeric,
const double Control[UMFPACK_CONTROL], double Info[UMFPACK_INFO])
{
- return umfpack_zi_solve(sys,Ap,Ai,&internal::real_ref(Ax[0]),0,&internal::real_ref(X[0]),0,&internal::real_ref(B[0]),0,Numeric,Control,Info);
+ return umfpack_zi_solve(sys,Ap,Ai,&numext::real_ref(Ax[0]),0,&numext::real_ref(X[0]),0,&numext::real_ref(B[0]),0,Numeric,Control,Info);
}
inline int umfpack_get_lunz(int *lnz, int *unz, int *n_row, int *n_col, int *nz_udiag, void *Numeric, double)
@@ -89,9 +89,9 @@ inline int umfpack_get_numeric(int Lp[], int Lj[], double Lx[], int Up[], int Ui
inline int umfpack_get_numeric(int Lp[], int Lj[], std::complex<double> Lx[], int Up[], int Ui[], std::complex<double> Ux[],
int P[], int Q[], std::complex<double> Dx[], int *do_recip, double Rs[], void *Numeric)
{
- double& lx0_real = internal::real_ref(Lx[0]);
- double& ux0_real = internal::real_ref(Ux[0]);
- double& dx0_real = internal::real_ref(Dx[0]);
+ double& lx0_real = numext::real_ref(Lx[0]);
+ double& ux0_real = numext::real_ref(Ux[0]);
+ double& dx0_real = numext::real_ref(Dx[0]);
return umfpack_zi_get_numeric(Lp,Lj,Lx?&lx0_real:0,0,Up,Ui,Ux?&ux0_real:0,0,P,Q,
Dx?&dx0_real:0,0,do_recip,Rs,Numeric);
}
@@ -103,7 +103,7 @@ inline int umfpack_get_determinant(double *Mx, double *Ex, void *NumericHandle,
inline int umfpack_get_determinant(std::complex<double> *Mx, double *Ex, void *NumericHandle, double User_Info [UMFPACK_INFO])
{
- double& mx_real = internal::real_ref(*Mx);
+ double& mx_real = numext::real_ref(*Mx);
return umfpack_zi_get_determinant(&mx_real,0,Ex,NumericHandle,User_Info);
}
@@ -114,7 +114,7 @@ inline int umfpack_get_determinant(std::complex<double> *Mx, double *Ex, void *N
* using the UmfPack library. The sparse matrix A must be squared and full rank.
* The vectors or matrices X and B can be either dense or sparse.
*
- * \WARNING The input matrix A should be in a \b compressed and \b column-major form.
+ * \warning The input matrix A should be in a \b compressed and \b column-major form.
* Otherwise an expensive copy will be made. You can call the inexpensive makeCompressed() to get a compressed matrix.
* \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
*
@@ -215,14 +215,14 @@ class UmfPackLU : internal::noncopyable
*
* \sa compute()
*/
-// template<typename Rhs>
-// inline const internal::sparse_solve_retval<UmfPAckLU, Rhs> solve(const SparseMatrixBase<Rhs>& b) const
-// {
-// eigen_assert(m_isInitialized && "UmfPAckLU is not initialized.");
-// eigen_assert(rows()==b.rows()
-// && "UmfPAckLU::solve(): invalid number of rows of the right hand side matrix b");
-// return internal::sparse_solve_retval<UmfPAckLU, Rhs>(*this, b.derived());
-// }
+ template<typename Rhs>
+ inline const internal::sparse_solve_retval<UmfPackLU, Rhs> solve(const SparseMatrixBase<Rhs>& b) const
+ {
+ eigen_assert(m_isInitialized && "UmfPackLU is not initialized.");
+ eigen_assert(rows()==b.rows()
+ && "UmfPackLU::solve(): invalid number of rows of the right hand side matrix b");
+ return internal::sparse_solve_retval<UmfPackLU, Rhs>(*this, b.derived());
+ }
/** Performs a symbolic decomposition on the sparcity of \a matrix.
*
@@ -381,7 +381,8 @@ bool UmfPackLU<MatrixType>::_solve(const MatrixBase<BDerived> &b, MatrixBase<XDe
const int rhsCols = b.cols();
eigen_assert((BDerived::Flags&RowMajorBit)==0 && "UmfPackLU backend does not support non col-major rhs yet");
eigen_assert((XDerived::Flags&RowMajorBit)==0 && "UmfPackLU backend does not support non col-major result yet");
-
+ eigen_assert(b.derived().data() != x.derived().data() && " Umfpack does not support inplace solve");
+
int errorCode;
for (int j=0; j<rhsCols; ++j)
{
@@ -420,7 +421,7 @@ struct sparse_solve_retval<UmfPackLU<_MatrixType>, Rhs>
template<typename Dest> void evalTo(Dest& dst) const
{
- dec()._solve(rhs(),dst);
+ this->defaultEvalTo(dst);
}
};
diff --git a/Eigen/src/misc/SparseSolve.h b/Eigen/src/misc/SparseSolve.h
index 272c4a479..244bb8ec7 100644
--- a/Eigen/src/misc/SparseSolve.h
+++ b/Eigen/src/misc/SparseSolve.h
@@ -47,6 +47,23 @@ template<typename _DecompositionType, typename Rhs> struct sparse_solve_retval_b
}
protected:
+ template<typename DestScalar, int DestOptions, typename DestIndex>
+ inline void defaultEvalTo(SparseMatrix<DestScalar,DestOptions,DestIndex>& dst) const
+ {
+ // we process the sparse rhs per block of NbColsAtOnce columns temporarily stored into a dense matrix.
+ static const int NbColsAtOnce = 4;
+ int rhsCols = m_rhs.cols();
+ int size = m_rhs.rows();
+ Eigen::Matrix<DestScalar,Dynamic,Dynamic> tmp(size,rhsCols);
+ Eigen::Matrix<DestScalar,Dynamic,Dynamic> tmpX(size,rhsCols);
+ for(int k=0; k<rhsCols; k+=NbColsAtOnce)
+ {
+ int actualCols = std::min<int>(rhsCols-k, NbColsAtOnce);
+ tmp.leftCols(actualCols) = m_rhs.middleCols(k,actualCols);
+ tmpX.leftCols(actualCols) = m_dec.solve(tmp.leftCols(actualCols));
+ dst.middleCols(k,actualCols) = tmpX.leftCols(actualCols).sparseView();
+ }
+ }
const DecompositionType& m_dec;
typename Rhs::Nested m_rhs;
};
diff --git a/Eigen/src/plugins/ArrayCwiseBinaryOps.h b/Eigen/src/plugins/ArrayCwiseBinaryOps.h
index 5b979ebf8..5c8c476ee 100644
--- a/Eigen/src/plugins/ArrayCwiseBinaryOps.h
+++ b/Eigen/src/plugins/ArrayCwiseBinaryOps.h
@@ -33,8 +33,14 @@ EIGEN_MAKE_CWISE_BINARY_OP(min,internal::scalar_min_op)
*
* \sa max()
*/
-EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_min_op<Scalar>, const Derived, const ConstantReturnType>
-(min)(const Scalar &other) const
+EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_min_op<Scalar>, const Derived,
+ const CwiseNullaryOp<internal::scalar_constant_op<Scalar>, PlainObject> >
+#ifdef EIGEN_PARSED_BY_DOXYGEN
+min
+#else
+(min)
+#endif
+(const Scalar &other) const
{
return (min)(Derived::PlainObject::Constant(rows(), cols(), other));
}
@@ -52,8 +58,14 @@ EIGEN_MAKE_CWISE_BINARY_OP(max,internal::scalar_max_op)
*
* \sa min()
*/
-EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_max_op<Scalar>, const Derived, const ConstantReturnType>
-(max)(const Scalar &other) const
+EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_max_op<Scalar>, const Derived,
+ const CwiseNullaryOp<internal::scalar_constant_op<Scalar>, PlainObject> >
+#ifdef EIGEN_PARSED_BY_DOXYGEN
+max
+#else
+(max)
+#endif
+(const Scalar &other) const
{
return (max)(Derived::PlainObject::Constant(rows(), cols(), other));
}
diff --git a/Eigen/src/plugins/ArrayCwiseUnaryOps.h b/Eigen/src/plugins/ArrayCwiseUnaryOps.h
index 0dffaf413..a59636790 100644
--- a/Eigen/src/plugins/ArrayCwiseUnaryOps.h
+++ b/Eigen/src/plugins/ArrayCwiseUnaryOps.h
@@ -200,3 +200,4 @@ EIGEN_MAKE_SCALAR_CWISE_UNARY_OP(operator<=, std::less_equal)
EIGEN_MAKE_SCALAR_CWISE_UNARY_OP(operator>, std::greater)
EIGEN_MAKE_SCALAR_CWISE_UNARY_OP(operator>=, std::greater_equal)
+
diff --git a/Eigen/src/plugins/BlockMethods.h b/Eigen/src/plugins/BlockMethods.h
index ef224001a..2788251e0 100644
--- a/Eigen/src/plugins/BlockMethods.h
+++ b/Eigen/src/plugins/BlockMethods.h
@@ -8,8 +8,6 @@
// 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_BLOCKMETHODS_H
-#define EIGEN_BLOCKMETHODS_H
#ifndef EIGEN_PARSED_BY_DOXYGEN
@@ -32,6 +30,10 @@ template<int N> struct ConstNColsBlockXpr { typedef const Block<const Derived, i
template<int N> struct NRowsBlockXpr { typedef Block<Derived, N, internal::traits<Derived>::ColsAtCompileTime, IsRowMajor> Type; };
template<int N> struct ConstNRowsBlockXpr { typedef const Block<const Derived, N, internal::traits<Derived>::ColsAtCompileTime, IsRowMajor> Type; };
+typedef VectorBlock<Derived> SegmentReturnType;
+typedef const VectorBlock<const Derived> ConstSegmentReturnType;
+template<int Size> struct FixedSegmentReturnType { typedef VectorBlock<Derived, Size> Type; };
+template<int Size> struct ConstFixedSegmentReturnType { typedef const VectorBlock<const Derived, Size> Type; };
#endif // not EIGEN_PARSED_BY_DOXYGEN
@@ -88,12 +90,13 @@ inline const Block<const Derived> topRightCorner(Index cRows, Index cCols) const
/** \returns an expression of a fixed-size top-right corner of *this.
*
- * The template parameters CRows and CCols are the number of rows and columns in the corner.
+ * \tparam CRows the number of rows in the corner
+ * \tparam CCols the number of columns in the corner
*
* Example: \include MatrixBase_template_int_int_topRightCorner.cpp
* Output: \verbinclude MatrixBase_template_int_int_topRightCorner.out
*
- * \sa class Block, block(Index,Index,Index,Index)
+ * \sa class Block, block<int,int>(Index,Index)
*/
template<int CRows, int CCols>
inline Block<Derived, CRows, CCols> topRightCorner()
@@ -108,6 +111,35 @@ inline const Block<const Derived, CRows, CCols> topRightCorner() const
return Block<const Derived, CRows, CCols>(derived(), 0, cols() - CCols);
}
+/** \returns an expression of a top-right corner of *this.
+ *
+ * \tparam CRows number of rows in corner as specified at compile-time
+ * \tparam CCols number of columns in corner as specified at compile-time
+ * \param cRows number of rows in corner as specified at run-time
+ * \param cCols number of columns in corner as specified at run-time
+ *
+ * This function is mainly useful for corners where the number of rows is specified at compile-time
+ * and the number of columns is specified at run-time, or vice versa. The compile-time and run-time
+ * information should not contradict. In other words, \a cRows should equal \a CRows unless
+ * \a CRows is \a Dynamic, and the same for the number of columns.
+ *
+ * Example: \include MatrixBase_template_int_int_topRightCorner_int_int.cpp
+ * Output: \verbinclude MatrixBase_template_int_int_topRightCorner_int_int.out
+ *
+ * \sa class Block
+ */
+template<int CRows, int CCols>
+inline Block<Derived, CRows, CCols> topRightCorner(Index cRows, Index cCols)
+{
+ return Block<Derived, CRows, CCols>(derived(), 0, cols() - cCols, cRows, cCols);
+}
+
+/** This is the const version of topRightCorner<int, int>(Index, Index).*/
+template<int CRows, int CCols>
+inline const Block<const Derived, CRows, CCols> topRightCorner(Index cRows, Index cCols) const
+{
+ return Block<const Derived, CRows, CCols>(derived(), 0, cols() - cCols, cRows, cCols);
+}
@@ -154,6 +186,36 @@ inline const Block<const Derived, CRows, CCols> topLeftCorner() const
return Block<const Derived, CRows, CCols>(derived(), 0, 0);
}
+/** \returns an expression of a top-left corner of *this.
+ *
+ * \tparam CRows number of rows in corner as specified at compile-time
+ * \tparam CCols number of columns in corner as specified at compile-time
+ * \param cRows number of rows in corner as specified at run-time
+ * \param cCols number of columns in corner as specified at run-time
+ *
+ * This function is mainly useful for corners where the number of rows is specified at compile-time
+ * and the number of columns is specified at run-time, or vice versa. The compile-time and run-time
+ * information should not contradict. In other words, \a cRows should equal \a CRows unless
+ * \a CRows is \a Dynamic, and the same for the number of columns.
+ *
+ * Example: \include MatrixBase_template_int_int_topLeftCorner_int_int.cpp
+ * Output: \verbinclude MatrixBase_template_int_int_topLeftCorner_int_int.out
+ *
+ * \sa class Block
+ */
+template<int CRows, int CCols>
+inline Block<Derived, CRows, CCols> topLeftCorner(Index cRows, Index cCols)
+{
+ return Block<Derived, CRows, CCols>(derived(), 0, 0, cRows, cCols);
+}
+
+/** This is the const version of topLeftCorner<int, int>(Index, Index).*/
+template<int CRows, int CCols>
+inline const Block<const Derived, CRows, CCols> topLeftCorner(Index cRows, Index cCols) const
+{
+ return Block<const Derived, CRows, CCols>(derived(), 0, 0, cRows, cCols);
+}
+
/** \returns a dynamic-size expression of a bottom-right corner of *this.
@@ -199,6 +261,36 @@ inline const Block<const Derived, CRows, CCols> bottomRightCorner() const
return Block<const Derived, CRows, CCols>(derived(), rows() - CRows, cols() - CCols);
}
+/** \returns an expression of a bottom-right corner of *this.
+ *
+ * \tparam CRows number of rows in corner as specified at compile-time
+ * \tparam CCols number of columns in corner as specified at compile-time
+ * \param cRows number of rows in corner as specified at run-time
+ * \param cCols number of columns in corner as specified at run-time
+ *
+ * This function is mainly useful for corners where the number of rows is specified at compile-time
+ * and the number of columns is specified at run-time, or vice versa. The compile-time and run-time
+ * information should not contradict. In other words, \a cRows should equal \a CRows unless
+ * \a CRows is \a Dynamic, and the same for the number of columns.
+ *
+ * Example: \include MatrixBase_template_int_int_bottomRightCorner_int_int.cpp
+ * Output: \verbinclude MatrixBase_template_int_int_bottomRightCorner_int_int.out
+ *
+ * \sa class Block
+ */
+template<int CRows, int CCols>
+inline Block<Derived, CRows, CCols> bottomRightCorner(Index cRows, Index cCols)
+{
+ return Block<Derived, CRows, CCols>(derived(), rows() - cRows, cols() - cCols, cRows, cCols);
+}
+
+/** This is the const version of bottomRightCorner<int, int>(Index, Index).*/
+template<int CRows, int CCols>
+inline const Block<const Derived, CRows, CCols> bottomRightCorner(Index cRows, Index cCols) const
+{
+ return Block<const Derived, CRows, CCols>(derived(), rows() - cRows, cols() - cCols, cRows, cCols);
+}
+
/** \returns a dynamic-size expression of a bottom-left corner of *this.
@@ -244,6 +336,36 @@ inline const Block<const Derived, CRows, CCols> bottomLeftCorner() const
return Block<const Derived, CRows, CCols>(derived(), rows() - CRows, 0);
}
+/** \returns an expression of a bottom-left corner of *this.
+ *
+ * \tparam CRows number of rows in corner as specified at compile-time
+ * \tparam CCols number of columns in corner as specified at compile-time
+ * \param cRows number of rows in corner as specified at run-time
+ * \param cCols number of columns in corner as specified at run-time
+ *
+ * This function is mainly useful for corners where the number of rows is specified at compile-time
+ * and the number of columns is specified at run-time, or vice versa. The compile-time and run-time
+ * information should not contradict. In other words, \a cRows should equal \a CRows unless
+ * \a CRows is \a Dynamic, and the same for the number of columns.
+ *
+ * Example: \include MatrixBase_template_int_int_bottomLeftCorner_int_int.cpp
+ * Output: \verbinclude MatrixBase_template_int_int_bottomLeftCorner_int_int.out
+ *
+ * \sa class Block
+ */
+template<int CRows, int CCols>
+inline Block<Derived, CRows, CCols> bottomLeftCorner(Index cRows, Index cCols)
+{
+ return Block<Derived, CRows, CCols>(derived(), rows() - cRows, 0, cRows, cCols);
+}
+
+/** This is the const version of bottomLeftCorner<int, int>(Index, Index).*/
+template<int CRows, int CCols>
+inline const Block<const Derived, CRows, CCols> bottomLeftCorner(Index cRows, Index cCols) const
+{
+ return Block<const Derived, CRows, CCols>(derived(), rows() - cRows, 0, cRows, cCols);
+}
+
/** \returns a block consisting of the top rows of *this.
@@ -268,7 +390,11 @@ inline ConstRowsBlockXpr topRows(Index n) const
/** \returns a block consisting of the top rows of *this.
*
- * \tparam N the number of rows in the block
+ * \tparam N the number of rows in the block as specified at compile-time
+ * \param n the number of rows in the block as specified at run-time
+ *
+ * The compile-time and run-time information should not contradict. In other words,
+ * \a n should equal \a N unless \a N is \a Dynamic.
*
* Example: \include MatrixBase_template_int_topRows.cpp
* Output: \verbinclude MatrixBase_template_int_topRows.out
@@ -276,16 +402,16 @@ inline ConstRowsBlockXpr topRows(Index n) const
* \sa class Block, block(Index,Index,Index,Index)
*/
template<int N>
-inline typename NRowsBlockXpr<N>::Type topRows()
+inline typename NRowsBlockXpr<N>::Type topRows(Index n = N)
{
- return typename NRowsBlockXpr<N>::Type(derived(), 0, 0, N, cols());
+ return typename NRowsBlockXpr<N>::Type(derived(), 0, 0, n, cols());
}
/** This is the const version of topRows<int>().*/
template<int N>
-inline typename ConstNRowsBlockXpr<N>::Type topRows() const
+inline typename ConstNRowsBlockXpr<N>::Type topRows(Index n = N) const
{
- return typename ConstNRowsBlockXpr<N>::Type(derived(), 0, 0, N, cols());
+ return typename ConstNRowsBlockXpr<N>::Type(derived(), 0, 0, n, cols());
}
@@ -312,7 +438,11 @@ inline ConstRowsBlockXpr bottomRows(Index n) const
/** \returns a block consisting of the bottom rows of *this.
*
- * \tparam N the number of rows in the block
+ * \tparam N the number of rows in the block as specified at compile-time
+ * \param n the number of rows in the block as specified at run-time
+ *
+ * The compile-time and run-time information should not contradict. In other words,
+ * \a n should equal \a N unless \a N is \a Dynamic.
*
* Example: \include MatrixBase_template_int_bottomRows.cpp
* Output: \verbinclude MatrixBase_template_int_bottomRows.out
@@ -320,16 +450,16 @@ inline ConstRowsBlockXpr bottomRows(Index n) const
* \sa class Block, block(Index,Index,Index,Index)
*/
template<int N>
-inline typename NRowsBlockXpr<N>::Type bottomRows()
+inline typename NRowsBlockXpr<N>::Type bottomRows(Index n = N)
{
- return typename NRowsBlockXpr<N>::Type(derived(), rows() - N, 0, N, cols());
+ return typename NRowsBlockXpr<N>::Type(derived(), rows() - n, 0, n, cols());
}
/** This is the const version of bottomRows<int>().*/
template<int N>
-inline typename ConstNRowsBlockXpr<N>::Type bottomRows() const
+inline typename ConstNRowsBlockXpr<N>::Type bottomRows(Index n = N) const
{
- return typename ConstNRowsBlockXpr<N>::Type(derived(), rows() - N, 0, N, cols());
+ return typename ConstNRowsBlockXpr<N>::Type(derived(), rows() - n, 0, n, cols());
}
@@ -337,28 +467,32 @@ inline typename ConstNRowsBlockXpr<N>::Type bottomRows() const
/** \returns a block consisting of a range of rows of *this.
*
* \param startRow the index of the first row in the block
- * \param numRows the number of rows in the block
+ * \param n the number of rows in the block
*
* Example: \include DenseBase_middleRows_int.cpp
* Output: \verbinclude DenseBase_middleRows_int.out
*
* \sa class Block, block(Index,Index,Index,Index)
*/
-inline RowsBlockXpr middleRows(Index startRow, Index numRows)
+inline RowsBlockXpr middleRows(Index startRow, Index n)
{
- return RowsBlockXpr(derived(), startRow, 0, numRows, cols());
+ return RowsBlockXpr(derived(), startRow, 0, n, cols());
}
/** This is the const version of middleRows(Index,Index).*/
-inline ConstRowsBlockXpr middleRows(Index startRow, Index numRows) const
+inline ConstRowsBlockXpr middleRows(Index startRow, Index n) const
{
- return ConstRowsBlockXpr(derived(), startRow, 0, numRows, cols());
+ return ConstRowsBlockXpr(derived(), startRow, 0, n, cols());
}
/** \returns a block consisting of a range of rows of *this.
*
- * \tparam N the number of rows in the block
+ * \tparam N the number of rows in the block as specified at compile-time
* \param startRow the index of the first row in the block
+ * \param n the number of rows in the block as specified at run-time
+ *
+ * The compile-time and run-time information should not contradict. In other words,
+ * \a n should equal \a N unless \a N is \a Dynamic.
*
* Example: \include DenseBase_template_int_middleRows.cpp
* Output: \verbinclude DenseBase_template_int_middleRows.out
@@ -366,16 +500,16 @@ inline ConstRowsBlockXpr middleRows(Index startRow, Index numRows) const
* \sa class Block, block(Index,Index,Index,Index)
*/
template<int N>
-inline typename NRowsBlockXpr<N>::Type middleRows(Index startRow)
+inline typename NRowsBlockXpr<N>::Type middleRows(Index startRow, Index n = N)
{
- return typename NRowsBlockXpr<N>::Type(derived(), startRow, 0, N, cols());
+ return typename NRowsBlockXpr<N>::Type(derived(), startRow, 0, n, cols());
}
/** This is the const version of middleRows<int>().*/
template<int N>
-inline typename ConstNRowsBlockXpr<N>::Type middleRows(Index startRow) const
+inline typename ConstNRowsBlockXpr<N>::Type middleRows(Index startRow, Index n = N) const
{
- return typename ConstNRowsBlockXpr<N>::Type(derived(), startRow, 0, N, cols());
+ return typename ConstNRowsBlockXpr<N>::Type(derived(), startRow, 0, n, cols());
}
@@ -402,7 +536,11 @@ inline ConstColsBlockXpr leftCols(Index n) const
/** \returns a block consisting of the left columns of *this.
*
- * \tparam N the number of columns in the block
+ * \tparam N the number of columns in the block as specified at compile-time
+ * \param n the number of columns in the block as specified at run-time
+ *
+ * The compile-time and run-time information should not contradict. In other words,
+ * \a n should equal \a N unless \a N is \a Dynamic.
*
* Example: \include MatrixBase_template_int_leftCols.cpp
* Output: \verbinclude MatrixBase_template_int_leftCols.out
@@ -410,16 +548,16 @@ inline ConstColsBlockXpr leftCols(Index n) const
* \sa class Block, block(Index,Index,Index,Index)
*/
template<int N>
-inline typename NColsBlockXpr<N>::Type leftCols()
+inline typename NColsBlockXpr<N>::Type leftCols(Index n = N)
{
- return typename NColsBlockXpr<N>::Type(derived(), 0, 0, rows(), N);
+ return typename NColsBlockXpr<N>::Type(derived(), 0, 0, rows(), n);
}
/** This is the const version of leftCols<int>().*/
template<int N>
-inline typename ConstNColsBlockXpr<N>::Type leftCols() const
+inline typename ConstNColsBlockXpr<N>::Type leftCols(Index n = N) const
{
- return typename ConstNColsBlockXpr<N>::Type(derived(), 0, 0, rows(), N);
+ return typename ConstNColsBlockXpr<N>::Type(derived(), 0, 0, rows(), n);
}
@@ -446,7 +584,11 @@ inline ConstColsBlockXpr rightCols(Index n) const
/** \returns a block consisting of the right columns of *this.
*
- * \tparam N the number of columns in the block
+ * \tparam N the number of columns in the block as specified at compile-time
+ * \param n the number of columns in the block as specified at run-time
+ *
+ * The compile-time and run-time information should not contradict. In other words,
+ * \a n should equal \a N unless \a N is \a Dynamic.
*
* Example: \include MatrixBase_template_int_rightCols.cpp
* Output: \verbinclude MatrixBase_template_int_rightCols.out
@@ -454,16 +596,16 @@ inline ConstColsBlockXpr rightCols(Index n) const
* \sa class Block, block(Index,Index,Index,Index)
*/
template<int N>
-inline typename NColsBlockXpr<N>::Type rightCols()
+inline typename NColsBlockXpr<N>::Type rightCols(Index n = N)
{
- return typename NColsBlockXpr<N>::Type(derived(), 0, cols() - N, rows(), N);
+ return typename NColsBlockXpr<N>::Type(derived(), 0, cols() - n, rows(), n);
}
/** This is the const version of rightCols<int>().*/
template<int N>
-inline typename ConstNColsBlockXpr<N>::Type rightCols() const
+inline typename ConstNColsBlockXpr<N>::Type rightCols(Index n = N) const
{
- return typename ConstNColsBlockXpr<N>::Type(derived(), 0, cols() - N, rows(), N);
+ return typename ConstNColsBlockXpr<N>::Type(derived(), 0, cols() - n, rows(), n);
}
@@ -491,8 +633,12 @@ inline ConstColsBlockXpr middleCols(Index startCol, Index numCols) const
/** \returns a block consisting of a range of columns of *this.
*
- * \tparam N the number of columns in the block
+ * \tparam N the number of columns in the block as specified at compile-time
* \param startCol the index of the first column in the block
+ * \param n the number of columns in the block as specified at run-time
+ *
+ * The compile-time and run-time information should not contradict. In other words,
+ * \a n should equal \a N unless \a N is \a Dynamic.
*
* Example: \include DenseBase_template_int_middleCols.cpp
* Output: \verbinclude DenseBase_template_int_middleCols.out
@@ -500,16 +646,16 @@ inline ConstColsBlockXpr middleCols(Index startCol, Index numCols) const
* \sa class Block, block(Index,Index,Index,Index)
*/
template<int N>
-inline typename NColsBlockXpr<N>::Type middleCols(Index startCol)
+inline typename NColsBlockXpr<N>::Type middleCols(Index startCol, Index n = N)
{
- return typename NColsBlockXpr<N>::Type(derived(), 0, startCol, rows(), N);
+ return typename NColsBlockXpr<N>::Type(derived(), 0, startCol, rows(), n);
}
/** This is the const version of middleCols<int>().*/
template<int N>
-inline typename ConstNColsBlockXpr<N>::Type middleCols(Index startCol) const
+inline typename ConstNColsBlockXpr<N>::Type middleCols(Index startCol, Index n = N) const
{
- return typename ConstNColsBlockXpr<N>::Type(derived(), 0, startCol, rows(), N);
+ return typename ConstNColsBlockXpr<N>::Type(derived(), 0, startCol, rows(), n);
}
@@ -543,6 +689,40 @@ inline const Block<const Derived, BlockRows, BlockCols> block(Index startRow, In
return Block<const Derived, BlockRows, BlockCols>(derived(), startRow, startCol);
}
+/** \returns an expression of a block in *this.
+ *
+ * \tparam BlockRows number of rows in block as specified at compile-time
+ * \tparam BlockCols number of columns in block as specified at compile-time
+ * \param startRow the first row in the block
+ * \param startCol the first column in the block
+ * \param blockRows number of rows in block as specified at run-time
+ * \param blockCols number of columns in block as specified at run-time
+ *
+ * This function is mainly useful for blocks where the number of rows is specified at compile-time
+ * and the number of columns is specified at run-time, or vice versa. The compile-time and run-time
+ * information should not contradict. In other words, \a blockRows should equal \a BlockRows unless
+ * \a BlockRows is \a Dynamic, and the same for the number of columns.
+ *
+ * Example: \include MatrixBase_template_int_int_block_int_int_int_int.cpp
+ * Output: \verbinclude MatrixBase_template_int_int_block_int_int_int_int.cpp
+ *
+ * \sa class Block, block(Index,Index,Index,Index)
+ */
+template<int BlockRows, int BlockCols>
+inline Block<Derived, BlockRows, BlockCols> block(Index startRow, Index startCol,
+ Index blockRows, Index blockCols)
+{
+ return Block<Derived, BlockRows, BlockCols>(derived(), startRow, startCol, blockRows, blockCols);
+}
+
+/** This is the const version of block<>(Index, Index, Index, Index). */
+template<int BlockRows, int BlockCols>
+inline const Block<const Derived, BlockRows, BlockCols> block(Index startRow, Index startCol,
+ Index blockRows, Index blockCols) const
+{
+ return Block<const Derived, BlockRows, BlockCols>(derived(), startRow, startCol, blockRows, blockCols);
+}
+
/** \returns an expression of the \a i-th column of *this. Note that the numbering starts at 0.
*
* Example: \include MatrixBase_col.cpp
@@ -577,4 +757,179 @@ inline ConstRowXpr row(Index i) const
return ConstRowXpr(derived(), i);
}
-#endif // EIGEN_BLOCKMETHODS_H
+/** \returns a dynamic-size expression of a segment (i.e. a vector block) in *this.
+ *
+ * \only_for_vectors
+ *
+ * \param start the first coefficient in the segment
+ * \param n the number of coefficients in the segment
+ *
+ * Example: \include MatrixBase_segment_int_int.cpp
+ * Output: \verbinclude MatrixBase_segment_int_int.out
+ *
+ * \note Even though the returned expression has dynamic size, in the case
+ * when it is applied to a fixed-size vector, it inherits a fixed maximal size,
+ * which means that evaluating it does not cause a dynamic memory allocation.
+ *
+ * \sa class Block, segment(Index)
+ */
+inline SegmentReturnType segment(Index start, Index n)
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return SegmentReturnType(derived(), start, n);
+}
+
+
+/** This is the const version of segment(Index,Index).*/
+inline ConstSegmentReturnType segment(Index start, Index n) const
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return ConstSegmentReturnType(derived(), start, n);
+}
+
+/** \returns a dynamic-size expression of the first coefficients of *this.
+ *
+ * \only_for_vectors
+ *
+ * \param n the number of coefficients in the segment
+ *
+ * Example: \include MatrixBase_start_int.cpp
+ * Output: \verbinclude MatrixBase_start_int.out
+ *
+ * \note Even though the returned expression has dynamic size, in the case
+ * when it is applied to a fixed-size vector, it inherits a fixed maximal size,
+ * which means that evaluating it does not cause a dynamic memory allocation.
+ *
+ * \sa class Block, block(Index,Index)
+ */
+inline SegmentReturnType head(Index n)
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return SegmentReturnType(derived(), 0, n);
+}
+
+/** This is the const version of head(Index).*/
+inline ConstSegmentReturnType head(Index n) const
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return ConstSegmentReturnType(derived(), 0, n);
+}
+
+/** \returns a dynamic-size expression of the last coefficients of *this.
+ *
+ * \only_for_vectors
+ *
+ * \param n the number of coefficients in the segment
+ *
+ * Example: \include MatrixBase_end_int.cpp
+ * Output: \verbinclude MatrixBase_end_int.out
+ *
+ * \note Even though the returned expression has dynamic size, in the case
+ * when it is applied to a fixed-size vector, it inherits a fixed maximal size,
+ * which means that evaluating it does not cause a dynamic memory allocation.
+ *
+ * \sa class Block, block(Index,Index)
+ */
+inline SegmentReturnType tail(Index n)
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return SegmentReturnType(derived(), this->size() - n, n);
+}
+
+/** This is the const version of tail(Index).*/
+inline ConstSegmentReturnType tail(Index n) const
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return ConstSegmentReturnType(derived(), this->size() - n, n);
+}
+
+/** \returns a fixed-size expression of a segment (i.e. a vector block) in \c *this
+ *
+ * \only_for_vectors
+ *
+ * \tparam N the number of coefficients in the segment as specified at compile-time
+ * \param start the index of the first element in the segment
+ * \param n the number of coefficients in the segment as specified at compile-time
+ *
+ * The compile-time and run-time information should not contradict. In other words,
+ * \a n should equal \a N unless \a N is \a Dynamic.
+ *
+ * Example: \include MatrixBase_template_int_segment.cpp
+ * Output: \verbinclude MatrixBase_template_int_segment.out
+ *
+ * \sa class Block
+ */
+template<int N>
+inline typename FixedSegmentReturnType<N>::Type segment(Index start, Index n = N)
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return typename FixedSegmentReturnType<N>::Type(derived(), start, n);
+}
+
+/** This is the const version of segment<int>(Index).*/
+template<int N>
+inline typename ConstFixedSegmentReturnType<N>::Type segment(Index start, Index n = N) const
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return typename ConstFixedSegmentReturnType<N>::Type(derived(), start, n);
+}
+
+/** \returns a fixed-size expression of the first coefficients of *this.
+ *
+ * \only_for_vectors
+ *
+ * \tparam N the number of coefficients in the segment as specified at compile-time
+ * \param n the number of coefficients in the segment as specified at run-time
+ *
+ * The compile-time and run-time information should not contradict. In other words,
+ * \a n should equal \a N unless \a N is \a Dynamic.
+ *
+ * Example: \include MatrixBase_template_int_start.cpp
+ * Output: \verbinclude MatrixBase_template_int_start.out
+ *
+ * \sa class Block
+ */
+template<int N>
+inline typename FixedSegmentReturnType<N>::Type head(Index n = N)
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return typename FixedSegmentReturnType<N>::Type(derived(), 0, n);
+}
+
+/** This is the const version of head<int>().*/
+template<int N>
+inline typename ConstFixedSegmentReturnType<N>::Type head(Index n = N) const
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return typename ConstFixedSegmentReturnType<N>::Type(derived(), 0, n);
+}
+
+/** \returns a fixed-size expression of the last coefficients of *this.
+ *
+ * \only_for_vectors
+ *
+ * \tparam N the number of coefficients in the segment as specified at compile-time
+ * \param n the number of coefficients in the segment as specified at run-time
+ *
+ * The compile-time and run-time information should not contradict. In other words,
+ * \a n should equal \a N unless \a N is \a Dynamic.
+ *
+ * Example: \include MatrixBase_template_int_end.cpp
+ * Output: \verbinclude MatrixBase_template_int_end.out
+ *
+ * \sa class Block
+ */
+template<int N>
+inline typename FixedSegmentReturnType<N>::Type tail(Index n = N)
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return typename FixedSegmentReturnType<N>::Type(derived(), size() - n);
+}
+
+/** This is the const version of tail<int>.*/
+template<int N>
+inline typename ConstFixedSegmentReturnType<N>::Type tail(Index n = N) const
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return typename ConstFixedSegmentReturnType<N>::Type(derived(), size() - n);
+}
diff --git a/Eigen/src/plugins/MatrixCwiseBinaryOps.h b/Eigen/src/plugins/MatrixCwiseBinaryOps.h
index 3a737df7b..7f62149e0 100644
--- a/Eigen/src/plugins/MatrixCwiseBinaryOps.h
+++ b/Eigen/src/plugins/MatrixCwiseBinaryOps.h
@@ -83,7 +83,7 @@ cwiseMin(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other) const
EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_min_op<Scalar>, const Derived, const ConstantReturnType>
cwiseMin(const Scalar &other) const
{
- return cwiseMin(Derived::PlainObject::Constant(rows(), cols(), other));
+ return cwiseMin(Derived::Constant(rows(), cols(), other));
}
/** \returns an expression of the coefficient-wise max of *this and \a other
@@ -107,7 +107,7 @@ cwiseMax(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other) const
EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_max_op<Scalar>, const Derived, const ConstantReturnType>
cwiseMax(const Scalar &other) const
{
- return cwiseMax(Derived::PlainObject::Constant(rows(), cols(), other));
+ return cwiseMax(Derived::Constant(rows(), cols(), other));
}
diff --git a/README.android b/README.android
index 6610a1a6e..b08a68565 100644
--- a/README.android
+++ b/README.android
@@ -1,4 +1,4 @@
-Eigen 3.1.1
+Eigen 3.2.2
-----------
Eigen is a C++ template library for linear algebra: matrices, vectors,
@@ -6,8 +6,8 @@ numerical solvers, and related algorithms.
Website: http://eigen.tuxfamily.org/
-v3.1.1. Released on July 22, 2012. This is a copy of the source
-distribution from http://bitbucket.org/eigen/eigen/get/3.1.1.tar.gz.
+v3.2.2. Released on August 4, 2014. This is a copy of the source
+distribution from http://bitbucket.org/eigen/eigen/get/3.2.2.tar.bz2.
Non MPL2 license code is disabled. Trying to include such files will
lead to an error. See ./Eigen/src/Core/util/NonMPL2.h for details.
diff --git a/bench/benchGeometry.cpp b/bench/benchGeometry.cpp
new file mode 100644
index 000000000..6e16c0331
--- /dev/null
+++ b/bench/benchGeometry.cpp
@@ -0,0 +1,134 @@
+#include <iostream>
+#include <iomanip>
+#include <Eigen/Core>
+#include <Eigen/Geometry>
+#include <bench/BenchTimer.h>
+
+using namespace Eigen;
+using namespace std;
+
+#ifndef REPEAT
+#define REPEAT 1000000
+#endif
+
+enum func_opt
+{
+ TV,
+ TMATV,
+ TMATVMAT,
+};
+
+
+template <class res, class arg1, class arg2, int opt>
+struct func;
+
+template <class res, class arg1, class arg2>
+struct func<res, arg1, arg2, TV>
+{
+ static EIGEN_DONT_INLINE res run( arg1& a1, arg2& a2 )
+ {
+ asm ("");
+ return a1 * a2;
+ }
+};
+
+template <class res, class arg1, class arg2>
+struct func<res, arg1, arg2, TMATV>
+{
+ static EIGEN_DONT_INLINE res run( arg1& a1, arg2& a2 )
+ {
+ asm ("");
+ return a1.matrix() * a2;
+ }
+};
+
+template <class res, class arg1, class arg2>
+struct func<res, arg1, arg2, TMATVMAT>
+{
+ static EIGEN_DONT_INLINE res run( arg1& a1, arg2& a2 )
+ {
+ asm ("");
+ return res(a1.matrix() * a2.matrix());
+ }
+};
+
+template <class func, class arg1, class arg2>
+struct test_transform
+{
+ static void run()
+ {
+ arg1 a1;
+ a1.setIdentity();
+ arg2 a2;
+ a2.setIdentity();
+
+ BenchTimer timer;
+ timer.reset();
+ for (int k=0; k<10; ++k)
+ {
+ timer.start();
+ for (int k=0; k<REPEAT; ++k)
+ a2 = func::run( a1, a2 );
+ timer.stop();
+ }
+ cout << setprecision(4) << fixed << timer.value() << "s " << endl;;
+ }
+};
+
+
+#define run_vec( op, scalar, mode, option, vsize ) \
+ std::cout << #scalar << "\t " << #mode << "\t " << #option << " " << #vsize " "; \
+ {\
+ typedef Transform<scalar, 3, mode, option> Trans;\
+ typedef Matrix<scalar, vsize, 1, option> Vec;\
+ typedef func<Vec,Trans,Vec,op> Func;\
+ test_transform< Func, Trans, Vec >::run();\
+ }
+
+#define run_trans( op, scalar, mode, option ) \
+ std::cout << #scalar << "\t " << #mode << "\t " << #option << " "; \
+ {\
+ typedef Transform<scalar, 3, mode, option> Trans;\
+ typedef func<Trans,Trans,Trans,op> Func;\
+ test_transform< Func, Trans, Trans >::run();\
+ }
+
+int main(int argc, char* argv[])
+{
+ cout << "vec = trans * vec" << endl;
+ run_vec(TV, float, Isometry, AutoAlign, 3);
+ run_vec(TV, float, Isometry, DontAlign, 3);
+ run_vec(TV, float, Isometry, AutoAlign, 4);
+ run_vec(TV, float, Isometry, DontAlign, 4);
+ run_vec(TV, float, Projective, AutoAlign, 4);
+ run_vec(TV, float, Projective, DontAlign, 4);
+ run_vec(TV, double, Isometry, AutoAlign, 3);
+ run_vec(TV, double, Isometry, DontAlign, 3);
+ run_vec(TV, double, Isometry, AutoAlign, 4);
+ run_vec(TV, double, Isometry, DontAlign, 4);
+ run_vec(TV, double, Projective, AutoAlign, 4);
+ run_vec(TV, double, Projective, DontAlign, 4);
+
+ cout << "vec = trans.matrix() * vec" << endl;
+ run_vec(TMATV, float, Isometry, AutoAlign, 4);
+ run_vec(TMATV, float, Isometry, DontAlign, 4);
+ run_vec(TMATV, double, Isometry, AutoAlign, 4);
+ run_vec(TMATV, double, Isometry, DontAlign, 4);
+
+ cout << "trans = trans1 * trans" << endl;
+ run_trans(TV, float, Isometry, AutoAlign);
+ run_trans(TV, float, Isometry, DontAlign);
+ run_trans(TV, double, Isometry, AutoAlign);
+ run_trans(TV, double, Isometry, DontAlign);
+ run_trans(TV, float, Projective, AutoAlign);
+ run_trans(TV, float, Projective, DontAlign);
+ run_trans(TV, double, Projective, AutoAlign);
+ run_trans(TV, double, Projective, DontAlign);
+
+ cout << "trans = trans1.matrix() * trans.matrix()" << endl;
+ run_trans(TMATVMAT, float, Isometry, AutoAlign);
+ run_trans(TMATVMAT, float, Isometry, DontAlign);
+ run_trans(TMATVMAT, double, Isometry, AutoAlign);
+ run_trans(TMATVMAT, double, Isometry, DontAlign);
+}
+
diff --git a/bench/bench_gemm.cpp b/bench/bench_gemm.cpp
index 98ac34e20..41ca8b3b6 100644
--- a/bench/bench_gemm.cpp
+++ b/bench/bench_gemm.cpp
@@ -24,7 +24,7 @@ typedef Matrix<RealScalar,Dynamic,Dynamic> M;
#ifdef HAVE_BLAS
extern "C" {
- #include <bench/btl/libs/C_BLAS/blas.h>
+ #include <Eigen/src/misc/blas.h>
}
static float fone = 1;
diff --git a/bench/spbench/CMakeLists.txt b/bench/spbench/CMakeLists.txt
index 079912266..6e0e1b103 100644
--- a/bench/spbench/CMakeLists.txt
+++ b/bench/spbench/CMakeLists.txt
@@ -55,6 +55,12 @@ if(PASTIX_FOUND AND BLAS_FOUND)
set(PASTIX_ALL_LIBS ${PASTIX_LIBRARIES} ${BLAS_LIBRARIES})
endif(PASTIX_FOUND AND BLAS_FOUND)
+if(METIS_FOUND)
+ include_directories(${METIS_INCLUDES})
+ set (SPARSE_LIBS ${SPARSE_LIBS} ${METIS_LIBRARIES})
+ add_definitions("-DEIGEN_METIS_SUPPORT")
+endif(METIS_FOUND)
+
find_library(RT_LIBRARY rt)
if(RT_LIBRARY)
set(SPARSE_LIBS ${SPARSE_LIBS} ${RT_LIBRARY})
@@ -63,3 +69,10 @@ endif(RT_LIBRARY)
add_executable(spbenchsolver spbenchsolver.cpp)
target_link_libraries (spbenchsolver ${SPARSE_LIBS})
+add_executable(spsolver sp_solver.cpp)
+target_link_libraries (spsolver ${SPARSE_LIBS})
+
+
+add_executable(test_sparseLU test_sparseLU.cpp)
+target_link_libraries (test_sparseLU ${SPARSE_LIBS})
+
diff --git a/bench/spbench/sp_solver.cpp b/bench/spbench/sp_solver.cpp
new file mode 100644
index 000000000..a1f4bac8a
--- /dev/null
+++ b/bench/spbench/sp_solver.cpp
@@ -0,0 +1,125 @@
+// Small bench routine for Eigen available in Eigen
+// (C) Desire NUENTSA WAKAM, INRIA
+
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+#include <Eigen/Jacobi>
+#include <Eigen/Householder>
+#include <Eigen/IterativeLinearSolvers>
+#include <Eigen/LU>
+#include <unsupported/Eigen/SparseExtra>
+//#include <Eigen/SparseLU>
+#include <Eigen/SuperLUSupport>
+// #include <unsupported/Eigen/src/IterativeSolvers/Scaling.h>
+#include <bench/BenchTimer.h>
+#include <unsupported/Eigen/IterativeSolvers>
+using namespace std;
+using namespace Eigen;
+
+int main(int argc, char **args)
+{
+ SparseMatrix<double, ColMajor> A;
+ typedef SparseMatrix<double, ColMajor>::Index Index;
+ typedef Matrix<double, Dynamic, Dynamic> DenseMatrix;
+ typedef Matrix<double, Dynamic, 1> DenseRhs;
+ VectorXd b, x, tmp;
+ BenchTimer timer,totaltime;
+ //SparseLU<SparseMatrix<double, ColMajor> > solver;
+// SuperLU<SparseMatrix<double, ColMajor> > solver;
+ ConjugateGradient<SparseMatrix<double, ColMajor>, Lower,IncompleteCholesky<double,Lower> > solver;
+ ifstream matrix_file;
+ string line;
+ int n;
+ // Set parameters
+// solver.iparm(IPARM_THREAD_NBR) = 4;
+ /* Fill the matrix with sparse matrix stored in Matrix-Market coordinate column-oriented format */
+ if (argc < 2) assert(false && "please, give the matrix market file ");
+
+ timer.start();
+ totaltime.start();
+ loadMarket(A, args[1]);
+ cout << "End charging matrix " << endl;
+ bool iscomplex=false, isvector=false;
+ int sym;
+ getMarketHeader(args[1], sym, iscomplex, isvector);
+ if (iscomplex) { cout<< " Not for complex matrices \n"; return -1; }
+ if (isvector) { cout << "The provided file is not a matrix file\n"; return -1;}
+ if (sym != 0) { // symmetric matrices, only the lower part is stored
+ SparseMatrix<double, ColMajor> temp;
+ temp = A;
+ A = temp.selfadjointView<Lower>();
+ }
+ timer.stop();
+
+ n = A.cols();
+ // ====== TESTS FOR SPARSE TUTORIAL ======
+// cout<< "OuterSize " << A.outerSize() << " inner " << A.innerSize() << endl;
+// SparseMatrix<double, RowMajor> mat1(A);
+// SparseMatrix<double, RowMajor> mat2;
+// cout << " norm of A " << mat1.norm() << endl; ;
+// PermutationMatrix<Dynamic, Dynamic, int> perm(n);
+// perm.resize(n,1);
+// perm.indices().setLinSpaced(n, 0, n-1);
+// mat2 = perm * mat1;
+// mat.subrows();
+// mat2.resize(n,n);
+// mat2.reserve(10);
+// mat2.setConstant();
+// std::cout<< "NORM " << mat1.squaredNorm()<< endl;
+
+ cout<< "Time to load the matrix " << timer.value() <<endl;
+ /* Fill the right hand side */
+
+// solver.set_restart(374);
+ if (argc > 2)
+ loadMarketVector(b, args[2]);
+ else
+ {
+ b.resize(n);
+ tmp.resize(n);
+// tmp.setRandom();
+ for (int i = 0; i < n; i++) tmp(i) = i;
+ b = A * tmp ;
+ }
+// Scaling<SparseMatrix<double> > scal;
+// scal.computeRef(A);
+// b = scal.LeftScaling().cwiseProduct(b);
+
+ /* Compute the factorization */
+ cout<< "Starting the factorization "<< endl;
+ timer.reset();
+ timer.start();
+ cout<< "Size of Input Matrix "<< b.size()<<"\n\n";
+ cout<< "Rows and columns "<< A.rows() <<" " <<A.cols() <<"\n";
+ solver.compute(A);
+// solver.analyzePattern(A);
+// solver.factorize(A);
+ if (solver.info() != Success) {
+ std::cout<< "The solver failed \n";
+ return -1;
+ }
+ timer.stop();
+ float time_comp = timer.value();
+ cout <<" Compute Time " << time_comp<< endl;
+
+ timer.reset();
+ timer.start();
+ x = solver.solve(b);
+// x = scal.RightScaling().cwiseProduct(x);
+ timer.stop();
+ float time_solve = timer.value();
+ cout<< " Time to solve " << time_solve << endl;
+
+ /* Check the accuracy */
+ VectorXd tmp2 = b - A*x;
+ double tempNorm = tmp2.norm()/b.norm();
+ cout << "Relative norm of the computed solution : " << tempNorm <<"\n";
+// cout << "Iterations : " << solver.iterations() << "\n";
+
+ totaltime.stop();
+ cout << "Total time " << totaltime.value() << "\n";
+// std::cout<<x.transpose()<<"\n";
+
+ return 0;
+} \ No newline at end of file
diff --git a/bench/spbench/spbench.dtd b/bench/spbench/spbench.dtd
new file mode 100644
index 000000000..0fb51b89a
--- /dev/null
+++ b/bench/spbench/spbench.dtd
@@ -0,0 +1,31 @@
+<!ELEMENT BENCH (AVAILSOLVER+,LINEARSYSTEM+)>
+ <!ELEMENT AVAILSOLVER (SOLVER+)>
+ <!ELEMENT SOLVER (TYPE,PACKAGE)>
+ <!ELEMENT TYPE (#PCDATA)> <!-- One of LU, LLT, LDLT, ITER -->
+ <!ELEMENT PACKAGE (#PCDATA)> <!-- Derived from a library -->
+ <!ELEMENT LINEARSYSTEM (MATRIX,SOLVER_STAT+,BEST_SOLVER,GLOBAL_PARAMS*)>
+ <!ELEMENT MATRIX (NAME,SIZE,ENTRIES,PATTERN?,SYMMETRY,POSDEF?,ARITHMETIC,RHS*)>
+ <!ELEMENT NAME (#PCDATA)>
+ <!ELEMENT SIZE (#PCDATA)>
+ <!ELEMENT ENTRIES (#PCDATA)> <!-- The number of nonzeros elements -->
+ <!ELEMENT PATTERN (#PCDATA)> <!-- Is structural pattern symmetric or not -->
+ <!ELEMENT SYMMETRY (#PCDATA)> <!-- symmmetry with numerical values -->
+ <!ELEMENT POSDEF (#PCDATA)> <!-- Is the matrix positive definite or not -->
+ <!ELEMENT ARITHMETIC (#PCDATA)>
+ <!ELEMENT RHS (SOURCE)> <!-- A matrix can have one or more right hand side associated. -->
+ <!ELEMENT SOURCE (#PCDATA)> <!-- Source of the right hand side, either generated or provided -->
+ <!ELEMENT SOLVER_STAT (PARAMS*,TIME,ERROR,ITER?)>
+ <!ELEMENT PARAMS (#PCDATA)>
+ <!ELEMENT TIME (COMPUTE,SOLVE,TOTAL)>
+ <!ELEMENT COMPUTE (#PCDATA)> <!-- Time to analyze,to factorize, or to setup the preconditioner-->
+ <!ELEMENT SOLVE (#PCDATA)> <!-- Time to solve with all the available rhs -->
+ <!ELEMENT TOTAL (#PCDATA)>
+ <!ELEMENT ERROR (#PCDATA)> <!-- Either the relative error or the relative residual norm -->
+ <!ELEMENT ITER (#PCDATA)> <!-- Number of iterations -->
+ <!ELEMENT BEST_SOLVER CDATA> <!-- Id of the best solver -->
+ <!ELEMENT GLOBAL_PARAMS (#PCDATA)> <!-- Parameters shared by all solvers -->
+
+<!ATTLIST SOLVER ID CDATA #REQUIRED>
+<!ATTLIST SOLVER_STAT ID CDATA #REQUIRED>
+<!ATTLIST BEST_SOLVER ID CDATA #REQUIRED>
+<!ATTLIST RHS ID CDATA #IMPLIED> \ No newline at end of file
diff --git a/bench/spbench/spbenchsolver.cpp b/bench/spbench/spbenchsolver.cpp
index 830542ff1..4acd0039c 100644
--- a/bench/spbench/spbenchsolver.cpp
+++ b/bench/spbench/spbenchsolver.cpp
@@ -5,7 +5,6 @@ void bench_printhelp()
cout<< " \nbenchsolver : performs a benchmark of all the solvers available in Eigen \n\n";
cout<< " MATRIX FOLDER : \n";
cout<< " The matrices for the benchmark should be collected in a folder specified with an environment variable EIGEN_MATRIXDIR \n";
- cout<< " This folder should contain the subfolders real/ and complex/ : \n";
cout<< " The matrices are stored using the matrix market coordinate format \n";
cout<< " The matrix and associated right-hand side (rhs) files are named respectively \n";
cout<< " as MatrixName.mtx and MatrixName_b.mtx. If the rhs does not exist, a random one is generated. \n";
@@ -15,7 +14,7 @@ void bench_printhelp()
cout<< " OPTIONS : \n";
cout<< " -h or --help \n print this help and return\n\n";
cout<< " -d matrixdir \n Use matrixdir as the matrix folder instead of the one specified in the environment variable EIGEN_MATRIXDIR\n\n";
- cout<< " -o outputfile.html \n Output the statistics to a html file \n\n";
+ cout<< " -o outputfile.xml \n Output the statistics to a xml file \n\n";
cout<< " --eps <RelErr> Sets the relative tolerance for iterative solvers (default 1e-08) \n\n";
cout<< " --maxits <MaxIts> Sets the maximum number of iterations (default 1000) \n\n";
@@ -68,18 +67,16 @@ int main(int argc, char ** args)
maxiters = atoi(inval.c_str());
string current_dir;
- // Test the matrices in %EIGEN_MATRIXDIR/real
- current_dir = matrix_dir + "/real";
- Browse_Matrices<double>(current_dir, statFileExists, statFile,maxiters, tol);
+ // Test the real-arithmetics matrices
+ Browse_Matrices<double>(matrix_dir, statFileExists, statFile,maxiters, tol);
- // Test the matrices in %EIGEN_MATRIXDIR/complex
- current_dir = matrix_dir + "/complex";
- Browse_Matrices<std::complex<double> >(current_dir, statFileExists, statFile, maxiters, tol);
+ // Test the complex-arithmetics matrices
+ Browse_Matrices<std::complex<double> >(matrix_dir, statFileExists, statFile, maxiters, tol);
if(statFileExists)
{
statbuf.open(statFile.c_str(), std::ios::app);
- statbuf << "</TABLE> \n";
+ statbuf << "</BENCH> \n";
cout << "\n Output written in " << statFile << " ...\n";
statbuf.close();
}
diff --git a/bench/spbench/spbenchsolver.h b/bench/spbench/spbenchsolver.h
index 609c7c39d..19c719c04 100644
--- a/bench/spbench/spbenchsolver.h
+++ b/bench/spbench/spbenchsolver.h
@@ -10,7 +10,7 @@
#include <iostream>
#include <fstream>
-#include "Eigen/SparseCore"
+#include <Eigen/SparseCore>
#include <bench/BenchTimer.h>
#include <cstdlib>
#include <string>
@@ -21,6 +21,13 @@
#include <unsupported/Eigen/IterativeSolvers>
#include <Eigen/LU>
#include <unsupported/Eigen/SparseExtra>
+#include <Eigen/SparseLU>
+
+#include "spbenchstyle.h"
+
+#ifdef EIGEN_METIS_SUPPORT
+#include <Eigen/MetisSupport>
+#endif
#ifdef EIGEN_CHOLMOD_SUPPORT
#include <Eigen/CholmodSupport>
@@ -43,45 +50,37 @@
#endif
// CONSTANTS
-#define EIGEN_UMFPACK 0
-#define EIGEN_SUPERLU 1
-#define EIGEN_PASTIX 2
-#define EIGEN_PARDISO 3
-#define EIGEN_BICGSTAB 4
-#define EIGEN_BICGSTAB_ILUT 5
-#define EIGEN_GMRES 6
-#define EIGEN_GMRES_ILUT 7
-#define EIGEN_SIMPLICIAL_LDLT 8
-#define EIGEN_CHOLMOD_LDLT 9
-#define EIGEN_PASTIX_LDLT 10
-#define EIGEN_PARDISO_LDLT 11
-#define EIGEN_SIMPLICIAL_LLT 12
-#define EIGEN_CHOLMOD_SUPERNODAL_LLT 13
-#define EIGEN_CHOLMOD_SIMPLICIAL_LLT 14
-#define EIGEN_PASTIX_LLT 15
-#define EIGEN_PARDISO_LLT 16
-#define EIGEN_CG 17
-#define EIGEN_CG_PRECOND 18
-#define EIGEN_ALL_SOLVERS 19
+#define EIGEN_UMFPACK 10
+#define EIGEN_SUPERLU 20
+#define EIGEN_PASTIX 30
+#define EIGEN_PARDISO 40
+#define EIGEN_SPARSELU_COLAMD 50
+#define EIGEN_SPARSELU_METIS 51
+#define EIGEN_BICGSTAB 60
+#define EIGEN_BICGSTAB_ILUT 61
+#define EIGEN_GMRES 70
+#define EIGEN_GMRES_ILUT 71
+#define EIGEN_SIMPLICIAL_LDLT 80
+#define EIGEN_CHOLMOD_LDLT 90
+#define EIGEN_PASTIX_LDLT 100
+#define EIGEN_PARDISO_LDLT 110
+#define EIGEN_SIMPLICIAL_LLT 120
+#define EIGEN_CHOLMOD_SUPERNODAL_LLT 130
+#define EIGEN_CHOLMOD_SIMPLICIAL_LLT 140
+#define EIGEN_PASTIX_LLT 150
+#define EIGEN_PARDISO_LLT 160
+#define EIGEN_CG 170
+#define EIGEN_CG_PRECOND 180
using namespace Eigen;
using namespace std;
-struct Stats{
- ComputationInfo info;
- double total_time;
- double compute_time;
- double solve_time;
- double rel_error;
- int memory_used;
- int iterations;
- int isavail;
- int isIterative;
-};
// Global variables for input parameters
int MaximumIters; // Maximum number of iterations
double RelErr; // Relative error of the computed solution
+double best_time_val; // Current best time overall solvers
+int best_time_id; // id of the best solver for the current system
template<typename T> inline typename NumTraits<T>::Real test_precision() { return NumTraits<T>::dummy_precision(); }
template<> inline float test_precision<float>() { return 1e-3f; }
@@ -91,41 +90,134 @@ template<> inline double test_precision<std::complex<double> >() { return test_p
void printStatheader(std::ofstream& out)
{
- int LUcnt = 0;
- string LUlist =" ", LLTlist = "<TH > LLT", LDLTlist = "<TH > LDLT ";
+ // Print XML header
+ // NOTE It would have been much easier to write these XML documents using external libraries like tinyXML or Xerces-C++.
+
+ out << "<?xml version='1.0' encoding='UTF-8'?> \n";
+ out << "<?xml-stylesheet type='text/xsl' href='#stylesheet' ?> \n";
+ out << "<!DOCTYPE BENCH [\n<!ATTLIST xsl:stylesheet\n id\t ID #REQUIRED>\n]>";
+ out << "\n\n<!-- Generated by the Eigen library -->\n";
+ out << "\n<BENCH> \n" ; //root XML element
+ // Print the xsl style section
+ printBenchStyle(out);
+ // List all available solvers
+ out << " <AVAILSOLVER> \n";
#ifdef EIGEN_UMFPACK_SUPPORT
- LUlist += "<TH > UMFPACK "; LUcnt++;
+ out <<" <SOLVER ID='" << EIGEN_UMFPACK << "'>\n";
+ out << " <TYPE> LU </TYPE> \n";
+ out << " <PACKAGE> UMFPACK </PACKAGE> \n";
+ out << " </SOLVER> \n";
#endif
#ifdef EIGEN_SUPERLU_SUPPORT
- LUlist += "<TH > SUPERLU "; LUcnt++;
+ out <<" <SOLVER ID='" << EIGEN_SUPERLU << "'>\n";
+ out << " <TYPE> LU </TYPE> \n";
+ out << " <PACKAGE> SUPERLU </PACKAGE> \n";
+ out << " </SOLVER> \n";
#endif
#ifdef EIGEN_CHOLMOD_SUPPORT
- LLTlist += "<TH > CHOLMOD SP LLT<TH > CHOLMOD LLT";
- LDLTlist += "<TH>CHOLMOD LDLT";
+ out <<" <SOLVER ID='" << EIGEN_CHOLMOD_SIMPLICIAL_LLT << "'>\n";
+ out << " <TYPE> LLT SP</TYPE> \n";
+ out << " <PACKAGE> CHOLMOD </PACKAGE> \n";
+ out << " </SOLVER> \n";
+
+ out <<" <SOLVER ID='" << EIGEN_CHOLMOD_SUPERNODAL_LLT << "'>\n";
+ out << " <TYPE> LLT</TYPE> \n";
+ out << " <PACKAGE> CHOLMOD </PACKAGE> \n";
+ out << " </SOLVER> \n";
+
+ out <<" <SOLVER ID='" << EIGEN_CHOLMOD_LDLT << "'>\n";
+ out << " <TYPE> LDLT </TYPE> \n";
+ out << " <PACKAGE> CHOLMOD </PACKAGE> \n";
+ out << " </SOLVER> \n";
#endif
#ifdef EIGEN_PARDISO_SUPPORT
- LUlist += "<TH > PARDISO LU"; LUcnt++;
- LLTlist += "<TH > PARDISO LLT";
- LDLTlist += "<TH > PARDISO LDLT";
+ out <<" <SOLVER ID='" << EIGEN_PARDISO << "'>\n";
+ out << " <TYPE> LU </TYPE> \n";
+ out << " <PACKAGE> PARDISO </PACKAGE> \n";
+ out << " </SOLVER> \n";
+
+ out <<" <SOLVER ID='" << EIGEN_PARDISO_LLT << "'>\n";
+ out << " <TYPE> LLT </TYPE> \n";
+ out << " <PACKAGE> PARDISO </PACKAGE> \n";
+ out << " </SOLVER> \n";
+
+ out <<" <SOLVER ID='" << EIGEN_PARDISO_LDLT << "'>\n";
+ out << " <TYPE> LDLT </TYPE> \n";
+ out << " <PACKAGE> PARDISO </PACKAGE> \n";
+ out << " </SOLVER> \n";
#endif
#ifdef EIGEN_PASTIX_SUPPORT
- LUlist += "<TH > PASTIX LU"; LUcnt++;
- LLTlist += "<TH > PASTIX LLT";
- LDLTlist += "<TH > PASTIX LDLT";
+ out <<" <SOLVER ID='" << EIGEN_PASTIX << "'>\n";
+ out << " <TYPE> LU </TYPE> \n";
+ out << " <PACKAGE> PASTIX </PACKAGE> \n";
+ out << " </SOLVER> \n";
+
+ out <<" <SOLVER ID='" << EIGEN_PASTIX_LLT << "'>\n";
+ out << " <TYPE> LLT </TYPE> \n";
+ out << " <PACKAGE> PASTIX </PACKAGE> \n";
+ out << " </SOLVER> \n";
+
+ out <<" <SOLVER ID='" << EIGEN_PASTIX_LDLT << "'>\n";
+ out << " <TYPE> LDLT </TYPE> \n";
+ out << " <PACKAGE> PASTIX </PACKAGE> \n";
+ out << " </SOLVER> \n";
+#endif
+
+ out <<" <SOLVER ID='" << EIGEN_BICGSTAB << "'>\n";
+ out << " <TYPE> BICGSTAB </TYPE> \n";
+ out << " <PACKAGE> EIGEN </PACKAGE> \n";
+ out << " </SOLVER> \n";
+
+ out <<" <SOLVER ID='" << EIGEN_BICGSTAB_ILUT << "'>\n";
+ out << " <TYPE> BICGSTAB_ILUT </TYPE> \n";
+ out << " <PACKAGE> EIGEN </PACKAGE> \n";
+ out << " </SOLVER> \n";
+
+ out <<" <SOLVER ID='" << EIGEN_GMRES_ILUT << "'>\n";
+ out << " <TYPE> GMRES_ILUT </TYPE> \n";
+ out << " <PACKAGE> EIGEN </PACKAGE> \n";
+ out << " </SOLVER> \n";
+
+ out <<" <SOLVER ID='" << EIGEN_SIMPLICIAL_LDLT << "'>\n";
+ out << " <TYPE> LDLT </TYPE> \n";
+ out << " <PACKAGE> EIGEN </PACKAGE> \n";
+ out << " </SOLVER> \n";
+
+ out <<" <SOLVER ID='" << EIGEN_SIMPLICIAL_LLT << "'>\n";
+ out << " <TYPE> LLT </TYPE> \n";
+ out << " <PACKAGE> EIGEN </PACKAGE> \n";
+ out << " </SOLVER> \n";
+
+ out <<" <SOLVER ID='" << EIGEN_CG << "'>\n";
+ out << " <TYPE> CG </TYPE> \n";
+ out << " <PACKAGE> EIGEN </PACKAGE> \n";
+ out << " </SOLVER> \n";
+
+ out <<" <SOLVER ID='" << EIGEN_SPARSELU_COLAMD << "'>\n";
+ out << " <TYPE> LU_COLAMD </TYPE> \n";
+ out << " <PACKAGE> EIGEN </PACKAGE> \n";
+ out << " </SOLVER> \n";
+
+#ifdef EIGEN_METIS_SUPPORT
+ out <<" <SOLVER ID='" << EIGEN_SPARSELU_METIS << "'>\n";
+ out << " <TYPE> LU_METIS </TYPE> \n";
+ out << " <PACKAGE> EIGEN </PACKAGE> \n";
+ out << " </SOLVER> \n";
#endif
+ out << " </AVAILSOLVER> \n";
- out << "<TABLE border=\"1\" >\n ";
- out << "<TR><TH>Matrix <TH> N <TH> NNZ <TH> ";
- if (LUcnt) out << LUlist;
- out << " <TH >BiCGSTAB <TH >BiCGSTAB+ILUT"<< "<TH >GMRES+ILUT" <<LDLTlist << LLTlist << "<TH> CG "<< std::endl;
}
template<typename Solver, typename Scalar>
-Stats call_solver(Solver &solver, const typename Solver::MatrixType& A, const Matrix<Scalar, Dynamic, 1>& b, const Matrix<Scalar, Dynamic, 1>& refX)
+void call_solver(Solver &solver, const int solver_id, const typename Solver::MatrixType& A, const Matrix<Scalar, Dynamic, 1>& b, const Matrix<Scalar, Dynamic, 1>& refX,std::ofstream& statbuf)
{
- Stats stat;
+
+ double total_time;
+ double compute_time;
+ double solve_time;
+ double rel_error;
Matrix<Scalar, Dynamic, 1> x;
BenchTimer timer;
timer.reset();
@@ -133,170 +225,95 @@ Stats call_solver(Solver &solver, const typename Solver::MatrixType& A, const Ma
solver.compute(A);
if (solver.info() != Success)
{
- stat.info = NumericalIssue;
std::cerr << "Solver failed ... \n";
- return stat;
+ return;
}
- timer.stop();
- stat.compute_time = timer.value();
-
+ timer.stop();
+ compute_time = timer.value();
+ statbuf << " <TIME>\n";
+ statbuf << " <COMPUTE> " << timer.value() << "</COMPUTE>\n";
+ std::cout<< "COMPUTE TIME : " << timer.value() <<std::endl;
+
timer.reset();
timer.start();
x = solver.solve(b);
if (solver.info() == NumericalIssue)
{
- stat.info = NumericalIssue;
std::cerr << "Solver failed ... \n";
- return stat;
+ return;
}
-
timer.stop();
- stat.solve_time = timer.value();
- stat.total_time = stat.solve_time + stat.compute_time;
- stat.memory_used = 0;
+ solve_time = timer.value();
+ statbuf << " <SOLVE> " << timer.value() << "</SOLVE>\n";
+ std::cout<< "SOLVE TIME : " << timer.value() <<std::endl;
+
+ total_time = solve_time + compute_time;
+ statbuf << " <TOTAL> " << total_time << "</TOTAL>\n";
+ std::cout<< "TOTAL TIME : " << total_time <<std::endl;
+ statbuf << " </TIME>\n";
+
// Verify the relative error
if(refX.size() != 0)
- stat.rel_error = (refX - x).norm()/refX.norm();
+ rel_error = (refX - x).norm()/refX.norm();
else
{
// Compute the relative residual norm
Matrix<Scalar, Dynamic, 1> temp;
temp = A * x;
- stat.rel_error = (b-temp).norm()/b.norm();
- }
- if ( stat.rel_error > RelErr )
- {
- stat.info = NoConvergence;
- return stat;
+ rel_error = (b-temp).norm()/b.norm();
}
- else
+ statbuf << " <ERROR> " << rel_error << "</ERROR>\n";
+ std::cout<< "REL. ERROR : " << rel_error << "\n\n" ;
+ if ( rel_error <= RelErr )
{
- stat.info = Success;
- return stat;
+ // check the best time if convergence
+ if(!best_time_val || (best_time_val > total_time))
+ {
+ best_time_val = total_time;
+ best_time_id = solver_id;
+ }
}
}
template<typename Solver, typename Scalar>
-Stats call_directsolver(Solver& solver, const typename Solver::MatrixType& A, const Matrix<Scalar, Dynamic, 1>& b, const Matrix<Scalar, Dynamic, 1>& refX)
+void call_directsolver(Solver& solver, const int solver_id, const typename Solver::MatrixType& A, const Matrix<Scalar, Dynamic, 1>& b, const Matrix<Scalar, Dynamic, 1>& refX, std::string& statFile)
{
- Stats stat;
- stat = call_solver(solver, A, b, refX);
- return stat;
+ std::ofstream statbuf(statFile.c_str(), std::ios::app);
+ statbuf << " <SOLVER_STAT ID='" << solver_id <<"'>\n";
+ call_solver(solver, solver_id, A, b, refX,statbuf);
+ statbuf << " </SOLVER_STAT>\n";
+ statbuf.close();
}
template<typename Solver, typename Scalar>
-Stats call_itersolver(Solver &solver, const typename Solver::MatrixType& A, const Matrix<Scalar, Dynamic, 1>& b, const Matrix<Scalar, Dynamic, 1>& refX)
+void call_itersolver(Solver &solver, const int solver_id, const typename Solver::MatrixType& A, const Matrix<Scalar, Dynamic, 1>& b, const Matrix<Scalar, Dynamic, 1>& refX, std::string& statFile)
{
- Stats stat;
solver.setTolerance(RelErr);
solver.setMaxIterations(MaximumIters);
- stat = call_solver(solver, A, b, refX);
- stat.iterations = solver.iterations();
- return stat;
-}
-
-inline void printStatItem(Stats *stat, int solver_id, int& best_time_id, double& best_time_val)
-{
- stat[solver_id].isavail = 1;
-
- if (stat[solver_id].info == NumericalIssue)
- {
- cout << " SOLVER FAILED ... Probably a numerical issue \n";
- return;
- }
- if (stat[solver_id].info == NoConvergence){
- cout << "REL. ERROR " << stat[solver_id].rel_error;
- if(stat[solver_id].isIterative == 1)
- cout << " (" << stat[solver_id].iterations << ") \n";
- return;
- }
+ std::ofstream statbuf(statFile.c_str(), std::ios::app);
+ statbuf << " <SOLVER_STAT ID='" << solver_id <<"'>\n";
+ call_solver(solver, solver_id, A, b, refX,statbuf);
+ statbuf << " <ITER> "<< solver.iterations() << "</ITER>\n";
+ statbuf << " </SOLVER_STAT>\n";
+ std::cout << "ITERATIONS : " << solver.iterations() <<"\n\n\n";
- // Record the best CPU time
- if (!best_time_val)
- {
- best_time_val = stat[solver_id].total_time;
- best_time_id = solver_id;
- }
- else if (stat[solver_id].total_time < best_time_val)
- {
- best_time_val = stat[solver_id].total_time;
- best_time_id = solver_id;
- }
- // Print statistics to standard output
- if (stat[solver_id].info == Success){
- cout<< "COMPUTE TIME : " << stat[solver_id].compute_time<< " \n";
- cout<< "SOLVE TIME : " << stat[solver_id].solve_time<< " \n";
- cout<< "TOTAL TIME : " << stat[solver_id].total_time<< " \n";
- cout << "REL. ERROR : " << stat[solver_id].rel_error ;
- if(stat[solver_id].isIterative == 1) {
- cout << " (" << stat[solver_id].iterations << ") ";
- }
- cout << std::endl;
- }
-
}
-/* Print the results from all solvers corresponding to a particular matrix
- * The best CPU time is printed in bold
- */
-inline void printHtmlStatLine(Stats *stat, int best_time_id, string& statline)
-{
-
- string markup;
- ostringstream compute,solve,total,error;
- for (int i = 0; i < EIGEN_ALL_SOLVERS; i++)
- {
- if (stat[i].isavail == 0) continue;
- if(i == best_time_id)
- markup = "<TD style=\"background-color:red\">";
- else
- markup = "<TD>";
-
- if (stat[i].info == Success){
- compute << markup << stat[i].compute_time;
- solve << markup << stat[i].solve_time;
- total << markup << stat[i].total_time;
- error << " <TD> " << stat[i].rel_error;
- if(stat[i].isIterative == 1) {
- error << " (" << stat[i].iterations << ") ";
- }
- }
- else {
- compute << " <TD> -" ;
- solve << " <TD> -" ;
- total << " <TD> -" ;
- if(stat[i].info == NoConvergence){
- error << " <TD> "<< stat[i].rel_error ;
- if(stat[i].isIterative == 1)
- error << " (" << stat[i].iterations << ") ";
- }
- else error << " <TD> - ";
- }
- }
-
- statline = "<TH>Compute Time " + compute.str() + "\n"
- + "<TR><TH>Solve Time " + solve.str() + "\n"
- + "<TR><TH>Total Time " + total.str() + "\n"
- +"<TR><TH>Error(Iter)" + error.str() + "\n";
-
-}
-
template <typename Scalar>
-int SelectSolvers(const SparseMatrix<Scalar>&A, unsigned int sym, Matrix<Scalar, Dynamic, 1>& b, const Matrix<Scalar, Dynamic, 1>& refX, Stats *stat)
+void SelectSolvers(const SparseMatrix<Scalar>&A, unsigned int sym, Matrix<Scalar, Dynamic, 1>& b, const Matrix<Scalar, Dynamic, 1>& refX, std::string& statFile)
{
typedef SparseMatrix<Scalar, ColMajor> SpMat;
// First, deal with Nonsymmetric and symmetric matrices
- int best_time_id = 0;
- double best_time_val = 0.0;
+ best_time_id = 0;
+ best_time_val = 0.0;
//UMFPACK
#ifdef EIGEN_UMFPACK_SUPPORT
{
cout << "Solving with UMFPACK LU ... \n";
UmfPackLU<SpMat> solver;
- stat[EIGEN_UMFPACK] = call_directsolver(solver, A, b, refX);
- printStatItem(stat, EIGEN_UMFPACK, best_time_id, best_time_val);
+ call_directsolver(solver, EIGEN_UMFPACK, A, b, refX,statFile);
}
#endif
//SuperLU
@@ -304,8 +321,7 @@ int SelectSolvers(const SparseMatrix<Scalar>&A, unsigned int sym, Matrix<Scalar,
{
cout << "\nSolving with SUPERLU ... \n";
SuperLU<SpMat> solver;
- stat[EIGEN_SUPERLU] = call_directsolver(solver, A, b, refX);
- printStatItem(stat, EIGEN_SUPERLU, best_time_id, best_time_val);
+ call_directsolver(solver, EIGEN_SUPERLU, A, b, refX,statFile);
}
#endif
@@ -314,8 +330,7 @@ int SelectSolvers(const SparseMatrix<Scalar>&A, unsigned int sym, Matrix<Scalar,
{
cout << "\nSolving with PASTIX LU ... \n";
PastixLU<SpMat> solver;
- stat[EIGEN_PASTIX] = call_directsolver(solver, A, b, refX) ;
- printStatItem(stat, EIGEN_PASTIX, best_time_id, best_time_val);
+ call_directsolver(solver, EIGEN_PASTIX, A, b, refX,statFile) ;
}
#endif
@@ -324,28 +339,34 @@ int SelectSolvers(const SparseMatrix<Scalar>&A, unsigned int sym, Matrix<Scalar,
{
cout << "\nSolving with PARDISO LU ... \n";
PardisoLU<SpMat> solver;
- stat[EIGEN_PARDISO] = call_directsolver(solver, A, b, refX);
- printStatItem(stat, EIGEN_PARDISO, best_time_id, best_time_val);
+ call_directsolver(solver, EIGEN_PARDISO, A, b, refX,statFile);
+ }
+ #endif
+
+ // Eigen SparseLU METIS
+ cout << "\n Solving with Sparse LU AND COLAMD ... \n";
+ SparseLU<SpMat, COLAMDOrdering<int> > solver;
+ call_directsolver(solver, EIGEN_SPARSELU_COLAMD, A, b, refX, statFile);
+ // Eigen SparseLU METIS
+ #ifdef EIGEN_METIS_SUPPORT
+ {
+ cout << "\n Solving with Sparse LU AND METIS ... \n";
+ SparseLU<SpMat, MetisOrdering<int> > solver;
+ call_directsolver(solver, EIGEN_SPARSELU_METIS, A, b, refX, statFile);
}
#endif
-
-
//BiCGSTAB
{
cout << "\nSolving with BiCGSTAB ... \n";
BiCGSTAB<SpMat> solver;
- stat[EIGEN_BICGSTAB] = call_itersolver(solver, A, b, refX);
- stat[EIGEN_BICGSTAB].isIterative = 1;
- printStatItem(stat, EIGEN_BICGSTAB, best_time_id, best_time_val);
+ call_itersolver(solver, EIGEN_BICGSTAB, A, b, refX,statFile);
}
//BiCGSTAB+ILUT
{
cout << "\nSolving with BiCGSTAB and ILUT ... \n";
BiCGSTAB<SpMat, IncompleteLUT<Scalar> > solver;
- stat[EIGEN_BICGSTAB_ILUT] = call_itersolver(solver, A, b, refX);
- stat[EIGEN_BICGSTAB_ILUT].isIterative = 1;
- printStatItem(stat, EIGEN_BICGSTAB_ILUT, best_time_id, best_time_val);
+ call_itersolver(solver, EIGEN_BICGSTAB_ILUT, A, b, refX,statFile);
}
@@ -353,17 +374,13 @@ int SelectSolvers(const SparseMatrix<Scalar>&A, unsigned int sym, Matrix<Scalar,
// {
// cout << "\nSolving with GMRES ... \n";
// GMRES<SpMat> solver;
-// stat[EIGEN_GMRES] = call_itersolver(solver, A, b, refX);
-// stat[EIGEN_GMRES].isIterative = 1;
-// printStatItem(stat, EIGEN_GMRES, best_time_id, best_time_val);
+// call_itersolver(solver, EIGEN_GMRES, A, b, refX,statFile);
// }
//GMRES+ILUT
{
cout << "\nSolving with GMRES and ILUT ... \n";
GMRES<SpMat, IncompleteLUT<Scalar> > solver;
- stat[EIGEN_GMRES_ILUT] = call_itersolver(solver, A, b, refX);
- stat[EIGEN_GMRES_ILUT].isIterative = 1;
- printStatItem(stat, EIGEN_GMRES_ILUT, best_time_id, best_time_val);
+ call_itersolver(solver, EIGEN_GMRES_ILUT, A, b, refX,statFile);
}
// Hermitian and not necessarily positive-definites
@@ -373,8 +390,7 @@ int SelectSolvers(const SparseMatrix<Scalar>&A, unsigned int sym, Matrix<Scalar,
{
cout << "\nSolving with Simplicial LDLT ... \n";
SimplicialLDLT<SpMat, Lower> solver;
- stat[EIGEN_SIMPLICIAL_LDLT] = call_directsolver(solver, A, b, refX);
- printStatItem(stat, EIGEN_SIMPLICIAL_LDLT, best_time_id, best_time_val);
+ call_directsolver(solver, EIGEN_SIMPLICIAL_LDLT, A, b, refX,statFile);
}
// CHOLMOD
@@ -383,8 +399,7 @@ int SelectSolvers(const SparseMatrix<Scalar>&A, unsigned int sym, Matrix<Scalar,
cout << "\nSolving with CHOLMOD LDLT ... \n";
CholmodDecomposition<SpMat, Lower> solver;
solver.setMode(CholmodLDLt);
- stat[EIGEN_CHOLMOD_LDLT] = call_directsolver(solver, A, b, refX);
- printStatItem(stat,EIGEN_CHOLMOD_LDLT, best_time_id, best_time_val);
+ call_directsolver(solver,EIGEN_CHOLMOD_LDLT, A, b, refX,statFile);
}
#endif
@@ -393,8 +408,7 @@ int SelectSolvers(const SparseMatrix<Scalar>&A, unsigned int sym, Matrix<Scalar,
{
cout << "\nSolving with PASTIX LDLT ... \n";
PastixLDLT<SpMat, Lower> solver;
- stat[EIGEN_PASTIX_LDLT] = call_directsolver(solver, A, b, refX);
- printStatItem(stat,EIGEN_PASTIX_LDLT, best_time_id, best_time_val);
+ call_directsolver(solver,EIGEN_PASTIX_LDLT, A, b, refX,statFile);
}
#endif
@@ -403,8 +417,7 @@ int SelectSolvers(const SparseMatrix<Scalar>&A, unsigned int sym, Matrix<Scalar,
{
cout << "\nSolving with PARDISO LDLT ... \n";
PardisoLDLT<SpMat, Lower> solver;
- stat[EIGEN_PARDISO_LDLT] = call_directsolver(solver, A, b, refX);
- printStatItem(stat,EIGEN_PARDISO_LDLT, best_time_id, best_time_val);
+ call_directsolver(solver,EIGEN_PARDISO_LDLT, A, b, refX,statFile);
}
#endif
}
@@ -417,8 +430,7 @@ int SelectSolvers(const SparseMatrix<Scalar>&A, unsigned int sym, Matrix<Scalar,
{
cout << "\nSolving with SIMPLICIAL LLT ... \n";
SimplicialLLT<SpMat, Lower> solver;
- stat[EIGEN_SIMPLICIAL_LLT] = call_directsolver(solver, A, b, refX);
- printStatItem(stat,EIGEN_SIMPLICIAL_LLT, best_time_id, best_time_val);
+ call_directsolver(solver,EIGEN_SIMPLICIAL_LLT, A, b, refX,statFile);
}
// CHOLMOD
@@ -428,13 +440,11 @@ int SelectSolvers(const SparseMatrix<Scalar>&A, unsigned int sym, Matrix<Scalar,
cout << "\nSolving with CHOLMOD LLT (Supernodal)... \n";
CholmodDecomposition<SpMat, Lower> solver;
solver.setMode(CholmodSupernodalLLt);
- stat[EIGEN_CHOLMOD_SUPERNODAL_LLT] = call_directsolver(solver, A, b, refX);
- printStatItem(stat,EIGEN_CHOLMOD_SUPERNODAL_LLT, best_time_id, best_time_val);
+ call_directsolver(solver,EIGEN_CHOLMOD_SUPERNODAL_LLT, A, b, refX,statFile);
// CholMod Simplicial LLT
cout << "\nSolving with CHOLMOD LLT (Simplicial) ... \n";
solver.setMode(CholmodSimplicialLLt);
- stat[EIGEN_CHOLMOD_SIMPLICIAL_LLT] = call_directsolver(solver, A, b, refX);
- printStatItem(stat,EIGEN_CHOLMOD_SIMPLICIAL_LLT, best_time_id, best_time_val);
+ call_directsolver(solver,EIGEN_CHOLMOD_SIMPLICIAL_LLT, A, b, refX,statFile);
}
#endif
@@ -443,8 +453,7 @@ int SelectSolvers(const SparseMatrix<Scalar>&A, unsigned int sym, Matrix<Scalar,
{
cout << "\nSolving with PASTIX LLT ... \n";
PastixLLT<SpMat, Lower> solver;
- stat[EIGEN_PASTIX_LLT] = call_directsolver(solver, A, b, refX);
- printStatItem(stat,EIGEN_PASTIX_LLT, best_time_id, best_time_val);
+ call_directsolver(solver,EIGEN_PASTIX_LLT, A, b, refX,statFile);
}
#endif
@@ -453,8 +462,7 @@ int SelectSolvers(const SparseMatrix<Scalar>&A, unsigned int sym, Matrix<Scalar,
{
cout << "\nSolving with PARDISO LLT ... \n";
PardisoLLT<SpMat, Lower> solver;
- stat[EIGEN_PARDISO_LLT] = call_directsolver(solver, A, b, refX);
- printStatItem(stat,EIGEN_PARDISO_LLT, best_time_id, best_time_val);
+ call_directsolver(solver,EIGEN_PARDISO_LLT, A, b, refX,statFile);
}
#endif
@@ -462,21 +470,15 @@ int SelectSolvers(const SparseMatrix<Scalar>&A, unsigned int sym, Matrix<Scalar,
{
cout << "\nSolving with CG ... \n";
ConjugateGradient<SpMat, Lower> solver;
- stat[EIGEN_CG] = call_itersolver(solver, A, b, refX);
- stat[EIGEN_CG].isIterative = 1;
- printStatItem(stat,EIGEN_CG, best_time_id, best_time_val);
+ call_itersolver(solver,EIGEN_CG, A, b, refX,statFile);
}
//CG+IdentityPreconditioner
// {
// cout << "\nSolving with CG and IdentityPreconditioner ... \n";
// ConjugateGradient<SpMat, Lower, IdentityPreconditioner> solver;
-// stat[EIGEN_CG_PRECOND] = call_itersolver(solver, A, b, refX);
-// stat[EIGEN_CG_PRECOND].isIterative = 1;
-// printStatItem(stat,EIGEN_CG_PRECOND, best_time_id, best_time_val);
+// call_itersolver(solver,EIGEN_CG_PRECOND, A, b, refX,statFile);
// }
} // End SPD matrices
-
- return best_time_id;
}
/* Browse all the matrices available in the specified folder
@@ -490,30 +492,49 @@ void Browse_Matrices(const string folder, bool statFileExists, std::string& stat
MaximumIters = maxiters; // Maximum number of iterations, global variable
RelErr = tol; //Relative residual error as stopping criterion for iterative solvers
MatrixMarketIterator<Scalar> it(folder);
- Stats stat[EIGEN_ALL_SOLVERS];
for ( ; it; ++it)
- {
- for (int i = 0; i < EIGEN_ALL_SOLVERS; i++)
+ {
+ //print the infos for this linear system
+ if(statFileExists)
{
- stat[i].isavail = 0;
- stat[i].isIterative = 0;
+ std::ofstream statbuf(statFile.c_str(), std::ios::app);
+ statbuf << "<LINEARSYSTEM> \n";
+ statbuf << " <MATRIX> \n";
+ statbuf << " <NAME> " << it.matname() << " </NAME>\n";
+ statbuf << " <SIZE> " << it.matrix().rows() << " </SIZE>\n";
+ statbuf << " <ENTRIES> " << it.matrix().nonZeros() << "</ENTRIES>\n";
+ if (it.sym()!=NonSymmetric)
+ {
+ statbuf << " <SYMMETRY> Symmetric </SYMMETRY>\n" ;
+ if (it.sym() == SPD)
+ statbuf << " <POSDEF> YES </POSDEF>\n";
+ else
+ statbuf << " <POSDEF> NO </POSDEF>\n";
+
+ }
+ else
+ {
+ statbuf << " <SYMMETRY> NonSymmetric </SYMMETRY>\n" ;
+ statbuf << " <POSDEF> NO </POSDEF>\n";
+ }
+ statbuf << " </MATRIX> \n";
+ statbuf.close();
}
- int best_time_id;
cout<< "\n\n===================================================== \n";
cout<< " ====== SOLVING WITH MATRIX " << it.matname() << " ====\n";
cout<< " =================================================== \n\n";
Matrix<Scalar, Dynamic, 1> refX;
if(it.hasrefX()) refX = it.refX();
- best_time_id = SelectSolvers<Scalar>(it.matrix(), it.sym(), it.rhs(), refX, &stat[0]);
+ // Call all suitable solvers for this linear system
+ SelectSolvers<Scalar>(it.matrix(), it.sym(), it.rhs(), refX, statFile);
if(statFileExists)
{
- string statline;
- printHtmlStatLine(&stat[0], best_time_id, statline);
std::ofstream statbuf(statFile.c_str(), std::ios::app);
- statbuf << "<TR><TH rowspan=\"4\">" << it.matname() << " <TD rowspan=\"4\"> "
- << it.matrix().rows() << " <TD rowspan=\"4\"> " << it.matrix().nonZeros()<< " "<< statline ;
+ statbuf << " <BEST_SOLVER ID='"<< best_time_id
+ << "'></BEST_SOLVER>\n";
+ statbuf << " </LINEARSYSTEM> \n";
statbuf.close();
}
}
diff --git a/bench/spbench/spbenchstyle.h b/bench/spbench/spbenchstyle.h
new file mode 100644
index 000000000..17a05ce71
--- /dev/null
+++ b/bench/spbench/spbenchstyle.h
@@ -0,0 +1,94 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef SPBENCHSTYLE_H
+#define SPBENCHSTYLE_H
+
+void printBenchStyle(std::ofstream& out)
+{
+ out << "<xsl:stylesheet id='stylesheet' version='1.0' \
+ xmlns:xsl='http://www.w3.org/1999/XSL/Transform' >\n \
+ <xsl:template match='xsl:stylesheet' />\n \
+ <xsl:template match='/'> <!-- Root of the document -->\n \
+ <html>\n \
+ <head> \n \
+ <style type='text/css'> \n \
+ td { white-space: nowrap;}\n \
+ </style>\n \
+ </head>\n \
+ <body>";
+ out<<"<table border='1' width='100%' height='100%'>\n \
+ <TR> <!-- Write the table header -->\n \
+ <TH>Matrix</TH> <TH>N</TH> <TH> NNZ</TH> <TH> Sym</TH> <TH> SPD</TH> <TH> </TH>\n \
+ <xsl:for-each select='BENCH/AVAILSOLVER/SOLVER'>\n \
+ <xsl:sort select='@ID' data-type='number'/>\n \
+ <TH>\n \
+ <xsl:value-of select='TYPE' />\n \
+ <xsl:text></xsl:text>\n \
+ <xsl:value-of select='PACKAGE' />\n \
+ <xsl:text></xsl:text>\n \
+ </TH>\n \
+ </xsl:for-each>\n \
+ </TR>";
+
+ out<<" <xsl:for-each select='BENCH/LINEARSYSTEM'>\n \
+ <TR> <!-- print statistics for one linear system-->\n \
+ <TH rowspan='4'> <xsl:value-of select='MATRIX/NAME' /> </TH>\n \
+ <TD rowspan='4'> <xsl:value-of select='MATRIX/SIZE' /> </TD>\n \
+ <TD rowspan='4'> <xsl:value-of select='MATRIX/ENTRIES' /> </TD>\n \
+ <TD rowspan='4'> <xsl:value-of select='MATRIX/SYMMETRY' /> </TD>\n \
+ <TD rowspan='4'> <xsl:value-of select='MATRIX/POSDEF' /> </TD>\n \
+ <TH> Compute Time </TH>\n \
+ <xsl:for-each select='SOLVER_STAT'>\n \
+ <xsl:sort select='@ID' data-type='number'/>\n \
+ <TD> <xsl:value-of select='TIME/COMPUTE' /> </TD>\n \
+ </xsl:for-each>\n \
+ </TR>";
+ out<<" <TR>\n \
+ <TH> Solve Time </TH>\n \
+ <xsl:for-each select='SOLVER_STAT'>\n \
+ <xsl:sort select='@ID' data-type='number'/>\n \
+ <TD> <xsl:value-of select='TIME/SOLVE' /> </TD>\n \
+ </xsl:for-each>\n \
+ </TR>\n \
+ <TR>\n \
+ <TH> Total Time </TH>\n \
+ <xsl:for-each select='SOLVER_STAT'>\n \
+ <xsl:sort select='@ID' data-type='number'/>\n \
+ <xsl:choose>\n \
+ <xsl:when test='@ID=../BEST_SOLVER/@ID'>\n \
+ <TD style='background-color:red'> <xsl:value-of select='TIME/TOTAL' /> </TD>\n \
+ </xsl:when>\n \
+ <xsl:otherwise>\n \
+ <TD> <xsl:value-of select='TIME/TOTAL' /></TD>\n \
+ </xsl:otherwise>\n \
+ </xsl:choose>\n \
+ </xsl:for-each>\n \
+ </TR>";
+ out<<" <TR>\n \
+ <TH> Error </TH>\n \
+ <xsl:for-each select='SOLVER_STAT'>\n \
+ <xsl:sort select='@ID' data-type='number'/>\n \
+ <TD> <xsl:value-of select='ERROR' />\n \
+ <xsl:if test='ITER'>\n \
+ <xsl:text>(</xsl:text>\n \
+ <xsl:value-of select='ITER' />\n \
+ <xsl:text>)</xsl:text>\n \
+ </xsl:if> </TD>\n \
+ </xsl:for-each>\n \
+ </TR>\n \
+ </xsl:for-each>\n \
+ </table>\n \
+ </body>\n \
+ </html>\n \
+ </xsl:template>\n \
+ </xsl:stylesheet>\n\n";
+
+}
+#endif \ No newline at end of file
diff --git a/bench/spbench/test_sparseLU.cpp b/bench/spbench/test_sparseLU.cpp
new file mode 100644
index 000000000..f8ecbe69b
--- /dev/null
+++ b/bench/spbench/test_sparseLU.cpp
@@ -0,0 +1,93 @@
+// Small bench routine for Eigen available in Eigen
+// (C) Desire NUENTSA WAKAM, INRIA
+
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+#include <unsupported/Eigen/SparseExtra>
+#include <Eigen/SparseLU>
+#include <bench/BenchTimer.h>
+#ifdef EIGEN_METIS_SUPPORT
+#include <Eigen/MetisSupport>
+#endif
+
+using namespace std;
+using namespace Eigen;
+
+int main(int argc, char **args)
+{
+// typedef complex<double> scalar;
+ typedef double scalar;
+ SparseMatrix<scalar, ColMajor> A;
+ typedef SparseMatrix<scalar, ColMajor>::Index Index;
+ typedef Matrix<scalar, Dynamic, Dynamic> DenseMatrix;
+ typedef Matrix<scalar, Dynamic, 1> DenseRhs;
+ Matrix<scalar, Dynamic, 1> b, x, tmp;
+// SparseLU<SparseMatrix<scalar, ColMajor>, AMDOrdering<int> > solver;
+// #ifdef EIGEN_METIS_SUPPORT
+// SparseLU<SparseMatrix<scalar, ColMajor>, MetisOrdering<int> > solver;
+// std::cout<< "ORDERING : METIS\n";
+// #else
+ SparseLU<SparseMatrix<scalar, ColMajor>, COLAMDOrdering<int> > solver;
+ std::cout<< "ORDERING : COLAMD\n";
+// #endif
+
+ ifstream matrix_file;
+ string line;
+ int n;
+ BenchTimer timer;
+
+ // Set parameters
+ /* Fill the matrix with sparse matrix stored in Matrix-Market coordinate column-oriented format */
+ if (argc < 2) assert(false && "please, give the matrix market file ");
+ loadMarket(A, args[1]);
+ cout << "End charging matrix " << endl;
+ bool iscomplex=false, isvector=false;
+ int sym;
+ getMarketHeader(args[1], sym, iscomplex, isvector);
+// if (iscomplex) { cout<< " Not for complex matrices \n"; return -1; }
+ if (isvector) { cout << "The provided file is not a matrix file\n"; return -1;}
+ if (sym != 0) { // symmetric matrices, only the lower part is stored
+ SparseMatrix<scalar, ColMajor> temp;
+ temp = A;
+ A = temp.selfadjointView<Lower>();
+ }
+ n = A.cols();
+ /* Fill the right hand side */
+
+ if (argc > 2)
+ loadMarketVector(b, args[2]);
+ else
+ {
+ b.resize(n);
+ tmp.resize(n);
+// tmp.setRandom();
+ for (int i = 0; i < n; i++) tmp(i) = i;
+ b = A * tmp ;
+ }
+
+ /* Compute the factorization */
+// solver.isSymmetric(true);
+ timer.start();
+// solver.compute(A);
+ solver.analyzePattern(A);
+ timer.stop();
+ cout << "Time to analyze " << timer.value() << std::endl;
+ timer.reset();
+ timer.start();
+ solver.factorize(A);
+ timer.stop();
+ cout << "Factorize Time " << timer.value() << std::endl;
+ timer.reset();
+ timer.start();
+ x = solver.solve(b);
+ timer.stop();
+ cout << "solve time " << timer.value() << std::endl;
+ /* Check the accuracy */
+ Matrix<scalar, Dynamic, 1> tmp2 = b - A*x;
+ scalar tempNorm = tmp2.norm()/b.norm();
+ cout << "Relative norm of the computed solution : " << tempNorm <<"\n";
+ cout << "Number of nonzeros in the factor : " << solver.nnzL() + solver.nnzU() << std::endl;
+
+ return 0;
+} \ No newline at end of file
diff --git a/bench/spmv.cpp b/bench/spmv.cpp
index f6326dbb1..959bab09b 100644
--- a/bench/spmv.cpp
+++ b/bench/spmv.cpp
@@ -99,7 +99,7 @@ int main(int argc, char *argv[])
SPMV_BENCH(res = dm * sm);
std::cout << "Dense " << t.value()/repeats << "\t";
- SPMV_BENCHres = dm.transpose() * sm);
+ SPMV_BENCH(res = dm.transpose() * sm);
std::cout << t.value()/repeats << endl;
}
#endif
diff --git a/blas/CMakeLists.txt b/blas/CMakeLists.txt
index 453d5874c..a9bc05137 100644
--- a/blas/CMakeLists.txt
+++ b/blas/CMakeLists.txt
@@ -7,6 +7,9 @@ workaround_9220(Fortran EIGEN_Fortran_COMPILER_WORKS)
if(EIGEN_Fortran_COMPILER_WORKS)
enable_language(Fortran OPTIONAL)
+ if(NOT CMAKE_Fortran_COMPILER)
+ set(EIGEN_Fortran_COMPILER_WORKS OFF)
+ endif()
endif()
add_custom_target(blas)
@@ -18,10 +21,10 @@ if(EIGEN_Fortran_COMPILER_WORKS)
set(EigenBlas_SRCS ${EigenBlas_SRCS}
complexdots.f
srotm.f srotmg.f drotm.f drotmg.f
- lsame.f chpr2.f dspmv.f dtpsv.f ssbmv.f sspr.f stpmv.f
- zhpr2.f chbmv.f chpr.f ctpmv.f dspr2.f sspmv.f stpsv.f
- zhbmv.f zhpr.f ztpmv.f chpmv.f ctpsv.f dsbmv.f dspr.f dtpmv.f sspr2.f
- zhpmv.f ztpsv.f
+ lsame.f dspmv.f ssbmv.f
+ chbmv.f sspmv.f
+ zhbmv.f chpmv.f dsbmv.f
+ zhpmv.f
dtbmv.f stbmv.f ctbmv.f ztbmv.f
)
else()
diff --git a/blas/GeneralRank1Update.h b/blas/GeneralRank1Update.h
new file mode 100644
index 000000000..07d388c88
--- /dev/null
+++ b/blas/GeneralRank1Update.h
@@ -0,0 +1,44 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Chen-Pang He <jdh8@ms63.hinet.net>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef EIGEN_GENERAL_RANK1UPDATE_H
+#define EIGEN_GENERAL_RANK1UPDATE_H
+
+namespace internal {
+
+/* Optimized matrix += alpha * uv' */
+template<typename Scalar, typename Index, int StorageOrder, bool ConjLhs, bool ConjRhs>
+struct general_rank1_update;
+
+template<typename Scalar, typename Index, bool ConjLhs, bool ConjRhs>
+struct general_rank1_update<Scalar,Index,ColMajor,ConjLhs,ConjRhs>
+{
+ static void run(Index rows, Index cols, Scalar* mat, Index stride, const Scalar* u, const Scalar* v, Scalar alpha)
+ {
+ typedef Map<const Matrix<Scalar,Dynamic,1> > OtherMap;
+ typedef typename conj_expr_if<ConjLhs,OtherMap>::type ConjRhsType;
+ conj_if<ConjRhs> cj;
+
+ for (Index i=0; i<cols; ++i)
+ Map<Matrix<Scalar,Dynamic,1> >(mat+stride*i,rows) += alpha * cj(v[i]) * ConjRhsType(OtherMap(u,rows));
+ }
+};
+
+template<typename Scalar, typename Index, bool ConjLhs, bool ConjRhs>
+struct general_rank1_update<Scalar,Index,RowMajor,ConjLhs,ConjRhs>
+{
+ static void run(Index rows, Index cols, Scalar* mat, Index stride, const Scalar* u, const Scalar* v, Scalar alpha)
+ {
+ general_rank1_update<Scalar,Index,ColMajor,ConjRhs,ConjRhs>::run(rows,cols,mat,stride,u,v,alpha);
+ }
+};
+
+} // end namespace internal
+
+#endif // EIGEN_GENERAL_RANK1UPDATE_H
diff --git a/blas/PackedSelfadjointProduct.h b/blas/PackedSelfadjointProduct.h
new file mode 100644
index 000000000..07327a246
--- /dev/null
+++ b/blas/PackedSelfadjointProduct.h
@@ -0,0 +1,53 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Chen-Pang He <jdh8@ms63.hinet.net>
+//
+// 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_SELFADJOINT_PACKED_PRODUCT_H
+#define EIGEN_SELFADJOINT_PACKED_PRODUCT_H
+
+namespace internal {
+
+/* Optimized matrix += alpha * uv'
+ * The matrix is in packed form.
+ */
+template<typename Scalar, typename Index, int StorageOrder, int UpLo, bool ConjLhs, bool ConjRhs>
+struct selfadjoint_packed_rank1_update;
+
+template<typename Scalar, typename Index, int UpLo, bool ConjLhs, bool ConjRhs>
+struct selfadjoint_packed_rank1_update<Scalar,Index,ColMajor,UpLo,ConjLhs,ConjRhs>
+{
+ typedef typename NumTraits<Scalar>::Real RealScalar;
+ static void run(Index size, Scalar* mat, const Scalar* vec, RealScalar alpha)
+ {
+ typedef Map<const Matrix<Scalar,Dynamic,1> > OtherMap;
+ typedef typename conj_expr_if<ConjLhs,OtherMap>::type ConjRhsType;
+ conj_if<ConjRhs> cj;
+
+ for (Index i=0; i<size; ++i)
+ {
+ Map<Matrix<Scalar,Dynamic,1> >(mat, UpLo==Lower ? size-i : (i+1)) += alpha * cj(vec[i]) * ConjRhsType(OtherMap(vec+(UpLo==Lower ? i : 0), UpLo==Lower ? size-i : (i+1)));
+ //FIXME This should be handled outside.
+ mat[UpLo==Lower ? 0 : i] = numext::real(mat[UpLo==Lower ? 0 : i]);
+ mat += UpLo==Lower ? size-i : (i+1);
+ }
+ }
+};
+
+template<typename Scalar, typename Index, int UpLo, bool ConjLhs, bool ConjRhs>
+struct selfadjoint_packed_rank1_update<Scalar,Index,RowMajor,UpLo,ConjLhs,ConjRhs>
+{
+ typedef typename NumTraits<Scalar>::Real RealScalar;
+ static void run(Index size, Scalar* mat, const Scalar* vec, RealScalar alpha)
+ {
+ selfadjoint_packed_rank1_update<Scalar,Index,ColMajor,UpLo==Lower?Upper:Lower,ConjRhs,ConjLhs>::run(size,mat,vec,alpha);
+ }
+};
+
+} // end namespace internal
+
+#endif // EIGEN_SELFADJOINT_PACKED_PRODUCT_H
diff --git a/blas/PackedTriangularMatrixVector.h b/blas/PackedTriangularMatrixVector.h
new file mode 100644
index 000000000..e9886d56f
--- /dev/null
+++ b/blas/PackedTriangularMatrixVector.h
@@ -0,0 +1,79 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Chen-Pang He <jdh8@ms63.hinet.net>
+//
+// 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_PACKED_TRIANGULAR_MATRIX_VECTOR_H
+#define EIGEN_PACKED_TRIANGULAR_MATRIX_VECTOR_H
+
+namespace internal {
+
+template<typename Index, int Mode, typename LhsScalar, bool ConjLhs, typename RhsScalar, bool ConjRhs, int StorageOrder>
+struct packed_triangular_matrix_vector_product;
+
+template<typename Index, int Mode, typename LhsScalar, bool ConjLhs, typename RhsScalar, bool ConjRhs>
+struct packed_triangular_matrix_vector_product<Index,Mode,LhsScalar,ConjLhs,RhsScalar,ConjRhs,ColMajor>
+{
+ typedef typename scalar_product_traits<LhsScalar, RhsScalar>::ReturnType ResScalar;
+ enum {
+ IsLower = (Mode & Lower) ==Lower,
+ HasUnitDiag = (Mode & UnitDiag)==UnitDiag,
+ HasZeroDiag = (Mode & ZeroDiag)==ZeroDiag
+ };
+ static void run(Index size, const LhsScalar* lhs, const RhsScalar* rhs, ResScalar* res, ResScalar alpha)
+ {
+ internal::conj_if<ConjRhs> cj;
+ typedef Map<const Matrix<LhsScalar,Dynamic,1> > LhsMap;
+ typedef typename conj_expr_if<ConjLhs,LhsMap>::type ConjLhsType;
+ typedef Map<Matrix<ResScalar,Dynamic,1> > ResMap;
+
+ for (Index i=0; i<size; ++i)
+ {
+ Index s = IsLower&&(HasUnitDiag||HasZeroDiag) ? 1 : 0;
+ Index r = IsLower ? size-i: i+1;
+ if (EIGEN_IMPLIES(HasUnitDiag||HasZeroDiag, (--r)>0))
+ ResMap(res+(IsLower ? s+i : 0),r) += alpha * cj(rhs[i]) * ConjLhsType(LhsMap(lhs+s,r));
+ if (HasUnitDiag)
+ res[i] += alpha * cj(rhs[i]);
+ lhs += IsLower ? size-i: i+1;
+ }
+ };
+};
+
+template<typename Index, int Mode, typename LhsScalar, bool ConjLhs, typename RhsScalar, bool ConjRhs>
+struct packed_triangular_matrix_vector_product<Index,Mode,LhsScalar,ConjLhs,RhsScalar,ConjRhs,RowMajor>
+{
+ typedef typename scalar_product_traits<LhsScalar, RhsScalar>::ReturnType ResScalar;
+ enum {
+ IsLower = (Mode & Lower) ==Lower,
+ HasUnitDiag = (Mode & UnitDiag)==UnitDiag,
+ HasZeroDiag = (Mode & ZeroDiag)==ZeroDiag
+ };
+ static void run(Index size, const LhsScalar* lhs, const RhsScalar* rhs, ResScalar* res, ResScalar alpha)
+ {
+ internal::conj_if<ConjRhs> cj;
+ typedef Map<const Matrix<LhsScalar,Dynamic,1> > LhsMap;
+ typedef typename conj_expr_if<ConjLhs,LhsMap>::type ConjLhsType;
+ typedef Map<const Matrix<RhsScalar,Dynamic,1> > RhsMap;
+ typedef typename conj_expr_if<ConjRhs,RhsMap>::type ConjRhsType;
+
+ for (Index i=0; i<size; ++i)
+ {
+ Index s = !IsLower&&(HasUnitDiag||HasZeroDiag) ? 1 : 0;
+ Index r = IsLower ? i+1 : size-i;
+ if (EIGEN_IMPLIES(HasUnitDiag||HasZeroDiag, (--r)>0))
+ res[i] += alpha * (ConjLhsType(LhsMap(lhs+s,r)).cwiseProduct(ConjRhsType(RhsMap(rhs+(IsLower ? 0 : s+i),r)))).sum();
+ if (HasUnitDiag)
+ res[i] += alpha * cj(rhs[i]);
+ lhs += IsLower ? i+1 : size-i;
+ }
+ };
+};
+
+} // end namespace internal
+
+#endif // EIGEN_PACKED_TRIANGULAR_MATRIX_VECTOR_H
diff --git a/blas/PackedTriangularSolverVector.h b/blas/PackedTriangularSolverVector.h
new file mode 100644
index 000000000..5c0bb4bd6
--- /dev/null
+++ b/blas/PackedTriangularSolverVector.h
@@ -0,0 +1,88 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Chen-Pang He <jdh8@ms63.hinet.net>
+//
+// 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_PACKED_TRIANGULAR_SOLVER_VECTOR_H
+#define EIGEN_PACKED_TRIANGULAR_SOLVER_VECTOR_H
+
+namespace internal {
+
+template<typename LhsScalar, typename RhsScalar, typename Index, int Side, int Mode, bool Conjugate, int StorageOrder>
+struct packed_triangular_solve_vector;
+
+// forward and backward substitution, row-major, rhs is a vector
+template<typename LhsScalar, typename RhsScalar, typename Index, int Mode, bool Conjugate>
+struct packed_triangular_solve_vector<LhsScalar, RhsScalar, Index, OnTheLeft, Mode, Conjugate, RowMajor>
+{
+ enum {
+ IsLower = (Mode&Lower)==Lower
+ };
+ static void run(Index size, const LhsScalar* lhs, RhsScalar* rhs)
+ {
+ internal::conj_if<Conjugate> cj;
+ typedef Map<const Matrix<LhsScalar,Dynamic,1> > LhsMap;
+ typedef typename conj_expr_if<Conjugate,LhsMap>::type ConjLhsType;
+
+ lhs += IsLower ? 0 : (size*(size+1)>>1)-1;
+ for(Index pi=0; pi<size; ++pi)
+ {
+ Index i = IsLower ? pi : size-pi-1;
+ Index s = IsLower ? 0 : 1;
+ if (pi>0)
+ rhs[i] -= (ConjLhsType(LhsMap(lhs+s,pi))
+ .cwiseProduct(Map<const Matrix<RhsScalar,Dynamic,1> >(rhs+(IsLower ? 0 : i+1),pi))).sum();
+ if (!(Mode & UnitDiag))
+ rhs[i] /= cj(lhs[IsLower ? i : 0]);
+ IsLower ? lhs += pi+1 : lhs -= pi+2;
+ }
+ }
+};
+
+// forward and backward substitution, column-major, rhs is a vector
+template<typename LhsScalar, typename RhsScalar, typename Index, int Mode, bool Conjugate>
+struct packed_triangular_solve_vector<LhsScalar, RhsScalar, Index, OnTheLeft, Mode, Conjugate, ColMajor>
+{
+ enum {
+ IsLower = (Mode&Lower)==Lower
+ };
+ static void run(Index size, const LhsScalar* lhs, RhsScalar* rhs)
+ {
+ internal::conj_if<Conjugate> cj;
+ typedef Map<const Matrix<LhsScalar,Dynamic,1> > LhsMap;
+ typedef typename conj_expr_if<Conjugate,LhsMap>::type ConjLhsType;
+
+ lhs += IsLower ? 0 : size*(size-1)>>1;
+ for(Index pi=0; pi<size; ++pi)
+ {
+ Index i = IsLower ? pi : size-pi-1;
+ Index r = size - pi - 1;
+ if (!(Mode & UnitDiag))
+ rhs[i] /= cj(lhs[IsLower ? 0 : i]);
+ if (r>0)
+ Map<Matrix<RhsScalar,Dynamic,1> >(rhs+(IsLower? i+1 : 0),r) -=
+ rhs[i] * ConjLhsType(LhsMap(lhs+(IsLower? 1 : 0),r));
+ IsLower ? lhs += size-pi : lhs -= r;
+ }
+ }
+};
+
+template<typename LhsScalar, typename RhsScalar, typename Index, int Mode, bool Conjugate, int StorageOrder>
+struct packed_triangular_solve_vector<LhsScalar, RhsScalar, Index, OnTheRight, Mode, Conjugate, StorageOrder>
+{
+ static void run(Index size, const LhsScalar* lhs, RhsScalar* rhs)
+ {
+ packed_triangular_solve_vector<LhsScalar,RhsScalar,Index,OnTheLeft,
+ ((Mode&Upper)==Upper ? Lower : Upper) | (Mode&UnitDiag),
+ Conjugate,StorageOrder==RowMajor?ColMajor:RowMajor
+ >::run(size, lhs, rhs);
+ }
+};
+
+} // end namespace internal
+
+#endif // EIGEN_PACKED_TRIANGULAR_SOLVER_VECTOR_H
diff --git a/blas/README.txt b/blas/README.txt
index 07a8bd92a..63a5203b9 100644
--- a/blas/README.txt
+++ b/blas/README.txt
@@ -1,9 +1,6 @@
This directory contains a BLAS library built on top of Eigen.
-This is currently a work in progress which is far to be ready for use,
-but feel free to contribute to it if you wish.
-
This module is not built by default. In order to compile it, you need to
type 'make blas' from within your build dir.
diff --git a/blas/Rank2Update.h b/blas/Rank2Update.h
new file mode 100644
index 000000000..138d70fd6
--- /dev/null
+++ b/blas/Rank2Update.h
@@ -0,0 +1,57 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Chen-Pang He <jdh8@ms63.hinet.net>
+//
+// 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_RANK2UPDATE_H
+#define EIGEN_RANK2UPDATE_H
+
+namespace internal {
+
+/* Optimized selfadjoint matrix += alpha * uv' + conj(alpha)*vu'
+ * This is the low-level version of SelfadjointRank2Update.h
+ */
+template<typename Scalar, typename Index, int UpLo>
+struct rank2_update_selector
+{
+ static void run(Index size, Scalar* mat, Index stride, const Scalar* u, const Scalar* v, Scalar alpha)
+ {
+ typedef Map<const Matrix<Scalar,Dynamic,1> > OtherMap;
+ for (Index i=0; i<size; ++i)
+ {
+ Map<Matrix<Scalar,Dynamic,1> >(mat+stride*i+(UpLo==Lower ? i : 0), UpLo==Lower ? size-i : (i+1)) +=
+ numext::conj(alpha) * numext::conj(u[i]) * OtherMap(v+(UpLo==Lower ? i : 0), UpLo==Lower ? size-i : (i+1))
+ + alpha * numext::conj(v[i]) * OtherMap(u+(UpLo==Lower ? i : 0), UpLo==Lower ? size-i : (i+1));
+ }
+ }
+};
+
+/* Optimized selfadjoint matrix += alpha * uv' + conj(alpha)*vu'
+ * The matrix is in packed form.
+ */
+template<typename Scalar, typename Index, int UpLo>
+struct packed_rank2_update_selector
+{
+ static void run(Index size, Scalar* mat, const Scalar* u, const Scalar* v, Scalar alpha)
+ {
+ typedef Map<const Matrix<Scalar,Dynamic,1> > OtherMap;
+ Index offset = 0;
+ for (Index i=0; i<size; ++i)
+ {
+ Map<Matrix<Scalar,Dynamic,1> >(mat+offset, UpLo==Lower ? size-i : (i+1)) +=
+ numext::conj(alpha) * numext::conj(u[i]) * OtherMap(v+(UpLo==Lower ? i : 0), UpLo==Lower ? size-i : (i+1))
+ + alpha * numext::conj(v[i]) * OtherMap(u+(UpLo==Lower ? i : 0), UpLo==Lower ? size-i : (i+1));
+ //FIXME This should be handled outside.
+ mat[offset+(UpLo==Lower ? 0 : i)] = numext::real(mat[offset+(UpLo==Lower ? 0 : i)]);
+ offset += UpLo==Lower ? size-i : (i+1);
+ }
+ }
+};
+
+} // end namespace internal
+
+#endif // EIGEN_RANK2UPDATE_H
diff --git a/blas/chpr.f b/blas/chpr.f
deleted file mode 100644
index 11bd5c6ee..000000000
--- a/blas/chpr.f
+++ /dev/null
@@ -1,220 +0,0 @@
- SUBROUTINE CHPR(UPLO,N,ALPHA,X,INCX,AP)
-* .. Scalar Arguments ..
- REAL ALPHA
- INTEGER INCX,N
- CHARACTER UPLO
-* ..
-* .. Array Arguments ..
- COMPLEX AP(*),X(*)
-* ..
-*
-* Purpose
-* =======
-*
-* CHPR performs the hermitian rank 1 operation
-*
-* A := alpha*x*conjg( x' ) + A,
-*
-* where alpha is a real scalar, x is an n element vector and A is an
-* n by n hermitian matrix, supplied in packed form.
-*
-* Arguments
-* ==========
-*
-* UPLO - CHARACTER*1.
-* On entry, UPLO specifies whether the upper or lower
-* triangular part of the matrix A is supplied in the packed
-* array AP as follows:
-*
-* UPLO = 'U' or 'u' The upper triangular part of A is
-* supplied in AP.
-*
-* UPLO = 'L' or 'l' The lower triangular part of A is
-* supplied in AP.
-*
-* Unchanged on exit.
-*
-* N - INTEGER.
-* On entry, N specifies the order of the matrix A.
-* N must be at least zero.
-* Unchanged on exit.
-*
-* ALPHA - REAL .
-* On entry, ALPHA specifies the scalar alpha.
-* Unchanged on exit.
-*
-* X - COMPLEX array of dimension at least
-* ( 1 + ( n - 1 )*abs( INCX ) ).
-* Before entry, the incremented array X must contain the n
-* element vector x.
-* Unchanged on exit.
-*
-* INCX - INTEGER.
-* On entry, INCX specifies the increment for the elements of
-* X. INCX must not be zero.
-* Unchanged on exit.
-*
-* AP - COMPLEX array of DIMENSION at least
-* ( ( n*( n + 1 ) )/2 ).
-* Before entry with UPLO = 'U' or 'u', the array AP must
-* contain the upper triangular part of the hermitian matrix
-* packed sequentially, column by column, so that AP( 1 )
-* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 1, 2 )
-* and a( 2, 2 ) respectively, and so on. On exit, the array
-* AP is overwritten by the upper triangular part of the
-* updated matrix.
-* Before entry with UPLO = 'L' or 'l', the array AP must
-* contain the lower triangular part of the hermitian matrix
-* packed sequentially, column by column, so that AP( 1 )
-* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 2, 1 )
-* and a( 3, 1 ) respectively, and so on. On exit, the array
-* AP is overwritten by the lower triangular part of the
-* updated matrix.
-* Note that the imaginary parts of the diagonal elements need
-* not be set, they are assumed to be zero, and on exit they
-* are set to zero.
-*
-* Further Details
-* ===============
-*
-* Level 2 Blas routine.
-*
-* -- Written on 22-October-1986.
-* Jack Dongarra, Argonne National Lab.
-* Jeremy Du Croz, Nag Central Office.
-* Sven Hammarling, Nag Central Office.
-* Richard Hanson, Sandia National Labs.
-*
-* =====================================================================
-*
-* .. Parameters ..
- COMPLEX ZERO
- PARAMETER (ZERO= (0.0E+0,0.0E+0))
-* ..
-* .. Local Scalars ..
- COMPLEX TEMP
- INTEGER I,INFO,IX,J,JX,K,KK,KX
-* ..
-* .. External Functions ..
- LOGICAL LSAME
- EXTERNAL LSAME
-* ..
-* .. External Subroutines ..
- EXTERNAL XERBLA
-* ..
-* .. Intrinsic Functions ..
- INTRINSIC CONJG,REAL
-* ..
-*
-* Test the input parameters.
-*
- INFO = 0
- IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN
- INFO = 1
- ELSE IF (N.LT.0) THEN
- INFO = 2
- ELSE IF (INCX.EQ.0) THEN
- INFO = 5
- END IF
- IF (INFO.NE.0) THEN
- CALL XERBLA('CHPR ',INFO)
- RETURN
- END IF
-*
-* Quick return if possible.
-*
- IF ((N.EQ.0) .OR. (ALPHA.EQ.REAL(ZERO))) RETURN
-*
-* Set the start point in X if the increment is not unity.
-*
- IF (INCX.LE.0) THEN
- KX = 1 - (N-1)*INCX
- ELSE IF (INCX.NE.1) THEN
- KX = 1
- END IF
-*
-* Start the operations. In this version the elements of the array AP
-* are accessed sequentially with one pass through AP.
-*
- KK = 1
- IF (LSAME(UPLO,'U')) THEN
-*
-* Form A when upper triangle is stored in AP.
-*
- IF (INCX.EQ.1) THEN
- DO 20 J = 1,N
- IF (X(J).NE.ZERO) THEN
- TEMP = ALPHA*CONJG(X(J))
- K = KK
- DO 10 I = 1,J - 1
- AP(K) = AP(K) + X(I)*TEMP
- K = K + 1
- 10 CONTINUE
- AP(KK+J-1) = REAL(AP(KK+J-1)) + REAL(X(J)*TEMP)
- ELSE
- AP(KK+J-1) = REAL(AP(KK+J-1))
- END IF
- KK = KK + J
- 20 CONTINUE
- ELSE
- JX = KX
- DO 40 J = 1,N
- IF (X(JX).NE.ZERO) THEN
- TEMP = ALPHA*CONJG(X(JX))
- IX = KX
- DO 30 K = KK,KK + J - 2
- AP(K) = AP(K) + X(IX)*TEMP
- IX = IX + INCX
- 30 CONTINUE
- AP(KK+J-1) = REAL(AP(KK+J-1)) + REAL(X(JX)*TEMP)
- ELSE
- AP(KK+J-1) = REAL(AP(KK+J-1))
- END IF
- JX = JX + INCX
- KK = KK + J
- 40 CONTINUE
- END IF
- ELSE
-*
-* Form A when lower triangle is stored in AP.
-*
- IF (INCX.EQ.1) THEN
- DO 60 J = 1,N
- IF (X(J).NE.ZERO) THEN
- TEMP = ALPHA*CONJG(X(J))
- AP(KK) = REAL(AP(KK)) + REAL(TEMP*X(J))
- K = KK + 1
- DO 50 I = J + 1,N
- AP(K) = AP(K) + X(I)*TEMP
- K = K + 1
- 50 CONTINUE
- ELSE
- AP(KK) = REAL(AP(KK))
- END IF
- KK = KK + N - J + 1
- 60 CONTINUE
- ELSE
- JX = KX
- DO 80 J = 1,N
- IF (X(JX).NE.ZERO) THEN
- TEMP = ALPHA*CONJG(X(JX))
- AP(KK) = REAL(AP(KK)) + REAL(TEMP*X(JX))
- IX = JX
- DO 70 K = KK + 1,KK + N - J
- IX = IX + INCX
- AP(K) = AP(K) + X(IX)*TEMP
- 70 CONTINUE
- ELSE
- AP(KK) = REAL(AP(KK))
- END IF
- JX = JX + INCX
- KK = KK + N - J + 1
- 80 CONTINUE
- END IF
- END IF
-*
- RETURN
-*
-* End of CHPR .
-*
- END
diff --git a/blas/chpr2.f b/blas/chpr2.f
deleted file mode 100644
index a0020ef3e..000000000
--- a/blas/chpr2.f
+++ /dev/null
@@ -1,255 +0,0 @@
- SUBROUTINE CHPR2(UPLO,N,ALPHA,X,INCX,Y,INCY,AP)
-* .. Scalar Arguments ..
- COMPLEX ALPHA
- INTEGER INCX,INCY,N
- CHARACTER UPLO
-* ..
-* .. Array Arguments ..
- COMPLEX AP(*),X(*),Y(*)
-* ..
-*
-* Purpose
-* =======
-*
-* CHPR2 performs the hermitian rank 2 operation
-*
-* A := alpha*x*conjg( y' ) + conjg( alpha )*y*conjg( x' ) + A,
-*
-* where alpha is a scalar, x and y are n element vectors and A is an
-* n by n hermitian matrix, supplied in packed form.
-*
-* Arguments
-* ==========
-*
-* UPLO - CHARACTER*1.
-* On entry, UPLO specifies whether the upper or lower
-* triangular part of the matrix A is supplied in the packed
-* array AP as follows:
-*
-* UPLO = 'U' or 'u' The upper triangular part of A is
-* supplied in AP.
-*
-* UPLO = 'L' or 'l' The lower triangular part of A is
-* supplied in AP.
-*
-* Unchanged on exit.
-*
-* N - INTEGER.
-* On entry, N specifies the order of the matrix A.
-* N must be at least zero.
-* Unchanged on exit.
-*
-* ALPHA - COMPLEX .
-* On entry, ALPHA specifies the scalar alpha.
-* Unchanged on exit.
-*
-* X - COMPLEX array of dimension at least
-* ( 1 + ( n - 1 )*abs( INCX ) ).
-* Before entry, the incremented array X must contain the n
-* element vector x.
-* Unchanged on exit.
-*
-* INCX - INTEGER.
-* On entry, INCX specifies the increment for the elements of
-* X. INCX must not be zero.
-* Unchanged on exit.
-*
-* Y - COMPLEX array of dimension at least
-* ( 1 + ( n - 1 )*abs( INCY ) ).
-* Before entry, the incremented array Y must contain the n
-* element vector y.
-* Unchanged on exit.
-*
-* INCY - INTEGER.
-* On entry, INCY specifies the increment for the elements of
-* Y. INCY must not be zero.
-* Unchanged on exit.
-*
-* AP - COMPLEX array of DIMENSION at least
-* ( ( n*( n + 1 ) )/2 ).
-* Before entry with UPLO = 'U' or 'u', the array AP must
-* contain the upper triangular part of the hermitian matrix
-* packed sequentially, column by column, so that AP( 1 )
-* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 1, 2 )
-* and a( 2, 2 ) respectively, and so on. On exit, the array
-* AP is overwritten by the upper triangular part of the
-* updated matrix.
-* Before entry with UPLO = 'L' or 'l', the array AP must
-* contain the lower triangular part of the hermitian matrix
-* packed sequentially, column by column, so that AP( 1 )
-* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 2, 1 )
-* and a( 3, 1 ) respectively, and so on. On exit, the array
-* AP is overwritten by the lower triangular part of the
-* updated matrix.
-* Note that the imaginary parts of the diagonal elements need
-* not be set, they are assumed to be zero, and on exit they
-* are set to zero.
-*
-* Further Details
-* ===============
-*
-* Level 2 Blas routine.
-*
-* -- Written on 22-October-1986.
-* Jack Dongarra, Argonne National Lab.
-* Jeremy Du Croz, Nag Central Office.
-* Sven Hammarling, Nag Central Office.
-* Richard Hanson, Sandia National Labs.
-*
-* =====================================================================
-*
-* .. Parameters ..
- COMPLEX ZERO
- PARAMETER (ZERO= (0.0E+0,0.0E+0))
-* ..
-* .. Local Scalars ..
- COMPLEX TEMP1,TEMP2
- INTEGER I,INFO,IX,IY,J,JX,JY,K,KK,KX,KY
-* ..
-* .. External Functions ..
- LOGICAL LSAME
- EXTERNAL LSAME
-* ..
-* .. External Subroutines ..
- EXTERNAL XERBLA
-* ..
-* .. Intrinsic Functions ..
- INTRINSIC CONJG,REAL
-* ..
-*
-* Test the input parameters.
-*
- INFO = 0
- IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN
- INFO = 1
- ELSE IF (N.LT.0) THEN
- INFO = 2
- ELSE IF (INCX.EQ.0) THEN
- INFO = 5
- ELSE IF (INCY.EQ.0) THEN
- INFO = 7
- END IF
- IF (INFO.NE.0) THEN
- CALL XERBLA('CHPR2 ',INFO)
- RETURN
- END IF
-*
-* Quick return if possible.
-*
- IF ((N.EQ.0) .OR. (ALPHA.EQ.ZERO)) RETURN
-*
-* Set up the start points in X and Y if the increments are not both
-* unity.
-*
- IF ((INCX.NE.1) .OR. (INCY.NE.1)) THEN
- IF (INCX.GT.0) THEN
- KX = 1
- ELSE
- KX = 1 - (N-1)*INCX
- END IF
- IF (INCY.GT.0) THEN
- KY = 1
- ELSE
- KY = 1 - (N-1)*INCY
- END IF
- JX = KX
- JY = KY
- END IF
-*
-* Start the operations. In this version the elements of the array AP
-* are accessed sequentially with one pass through AP.
-*
- KK = 1
- IF (LSAME(UPLO,'U')) THEN
-*
-* Form A when upper triangle is stored in AP.
-*
- IF ((INCX.EQ.1) .AND. (INCY.EQ.1)) THEN
- DO 20 J = 1,N
- IF ((X(J).NE.ZERO) .OR. (Y(J).NE.ZERO)) THEN
- TEMP1 = ALPHA*CONJG(Y(J))
- TEMP2 = CONJG(ALPHA*X(J))
- K = KK
- DO 10 I = 1,J - 1
- AP(K) = AP(K) + X(I)*TEMP1 + Y(I)*TEMP2
- K = K + 1
- 10 CONTINUE
- AP(KK+J-1) = REAL(AP(KK+J-1)) +
- + REAL(X(J)*TEMP1+Y(J)*TEMP2)
- ELSE
- AP(KK+J-1) = REAL(AP(KK+J-1))
- END IF
- KK = KK + J
- 20 CONTINUE
- ELSE
- DO 40 J = 1,N
- IF ((X(JX).NE.ZERO) .OR. (Y(JY).NE.ZERO)) THEN
- TEMP1 = ALPHA*CONJG(Y(JY))
- TEMP2 = CONJG(ALPHA*X(JX))
- IX = KX
- IY = KY
- DO 30 K = KK,KK + J - 2
- AP(K) = AP(K) + X(IX)*TEMP1 + Y(IY)*TEMP2
- IX = IX + INCX
- IY = IY + INCY
- 30 CONTINUE
- AP(KK+J-1) = REAL(AP(KK+J-1)) +
- + REAL(X(JX)*TEMP1+Y(JY)*TEMP2)
- ELSE
- AP(KK+J-1) = REAL(AP(KK+J-1))
- END IF
- JX = JX + INCX
- JY = JY + INCY
- KK = KK + J
- 40 CONTINUE
- END IF
- ELSE
-*
-* Form A when lower triangle is stored in AP.
-*
- IF ((INCX.EQ.1) .AND. (INCY.EQ.1)) THEN
- DO 60 J = 1,N
- IF ((X(J).NE.ZERO) .OR. (Y(J).NE.ZERO)) THEN
- TEMP1 = ALPHA*CONJG(Y(J))
- TEMP2 = CONJG(ALPHA*X(J))
- AP(KK) = REAL(AP(KK)) +
- + REAL(X(J)*TEMP1+Y(J)*TEMP2)
- K = KK + 1
- DO 50 I = J + 1,N
- AP(K) = AP(K) + X(I)*TEMP1 + Y(I)*TEMP2
- K = K + 1
- 50 CONTINUE
- ELSE
- AP(KK) = REAL(AP(KK))
- END IF
- KK = KK + N - J + 1
- 60 CONTINUE
- ELSE
- DO 80 J = 1,N
- IF ((X(JX).NE.ZERO) .OR. (Y(JY).NE.ZERO)) THEN
- TEMP1 = ALPHA*CONJG(Y(JY))
- TEMP2 = CONJG(ALPHA*X(JX))
- AP(KK) = REAL(AP(KK)) +
- + REAL(X(JX)*TEMP1+Y(JY)*TEMP2)
- IX = JX
- IY = JY
- DO 70 K = KK + 1,KK + N - J
- IX = IX + INCX
- IY = IY + INCY
- AP(K) = AP(K) + X(IX)*TEMP1 + Y(IY)*TEMP2
- 70 CONTINUE
- ELSE
- AP(KK) = REAL(AP(KK))
- END IF
- JX = JX + INCX
- JY = JY + INCY
- KK = KK + N - J + 1
- 80 CONTINUE
- END IF
- END IF
-*
- RETURN
-*
-* End of CHPR2 .
-*
- END
diff --git a/blas/common.h b/blas/common.h
index b598c4e45..2bf642c6b 100644
--- a/blas/common.h
+++ b/blas/common.h
@@ -10,6 +10,9 @@
#ifndef EIGEN_BLAS_COMMON_H
#define EIGEN_BLAS_COMMON_H
+#include <Eigen/Core>
+#include <Eigen/Jacobi>
+
#include <iostream>
#include <complex>
@@ -48,7 +51,7 @@
: ((X)=='L' || (X)=='l') ? LO \
: INVALID)
-#define DIAG(X) ( ((X)=='N' || (X)=='N') ? NUNIT \
+#define DIAG(X) ( ((X)=='N' || (X)=='n') ? NUNIT \
: ((X)=='U' || (X)=='u') ? UNIT \
: INVALID)
@@ -68,12 +71,14 @@ inline bool check_uplo(const char* uplo)
return UPLO(*uplo)!=0xff;
}
-#include <Eigen/Core>
-#include <Eigen/Jacobi>
-
namespace Eigen {
#include "BandTriangularSolver.h"
+#include "GeneralRank1Update.h"
+#include "PackedSelfadjointProduct.h"
+#include "PackedTriangularMatrixVector.h"
+#include "PackedTriangularSolverVector.h"
+#include "Rank2Update.h"
}
using namespace Eigen;
diff --git a/blas/ctpmv.f b/blas/ctpmv.f
deleted file mode 100644
index b63742ccb..000000000
--- a/blas/ctpmv.f
+++ /dev/null
@@ -1,329 +0,0 @@
- SUBROUTINE CTPMV(UPLO,TRANS,DIAG,N,AP,X,INCX)
-* .. Scalar Arguments ..
- INTEGER INCX,N
- CHARACTER DIAG,TRANS,UPLO
-* ..
-* .. Array Arguments ..
- COMPLEX AP(*),X(*)
-* ..
-*
-* Purpose
-* =======
-*
-* CTPMV performs one of the matrix-vector operations
-*
-* x := A*x, or x := A'*x, or x := conjg( A' )*x,
-*
-* where x is an n element vector and A is an n by n unit, or non-unit,
-* upper or lower triangular matrix, supplied in packed form.
-*
-* Arguments
-* ==========
-*
-* UPLO - CHARACTER*1.
-* On entry, UPLO specifies whether the matrix is an upper or
-* lower triangular matrix as follows:
-*
-* UPLO = 'U' or 'u' A is an upper triangular matrix.
-*
-* UPLO = 'L' or 'l' A is a lower triangular matrix.
-*
-* Unchanged on exit.
-*
-* TRANS - CHARACTER*1.
-* On entry, TRANS specifies the operation to be performed as
-* follows:
-*
-* TRANS = 'N' or 'n' x := A*x.
-*
-* TRANS = 'T' or 't' x := A'*x.
-*
-* TRANS = 'C' or 'c' x := conjg( A' )*x.
-*
-* Unchanged on exit.
-*
-* DIAG - CHARACTER*1.
-* On entry, DIAG specifies whether or not A is unit
-* triangular as follows:
-*
-* DIAG = 'U' or 'u' A is assumed to be unit triangular.
-*
-* DIAG = 'N' or 'n' A is not assumed to be unit
-* triangular.
-*
-* Unchanged on exit.
-*
-* N - INTEGER.
-* On entry, N specifies the order of the matrix A.
-* N must be at least zero.
-* Unchanged on exit.
-*
-* AP - COMPLEX array of DIMENSION at least
-* ( ( n*( n + 1 ) )/2 ).
-* Before entry with UPLO = 'U' or 'u', the array AP must
-* contain the upper triangular matrix packed sequentially,
-* column by column, so that AP( 1 ) contains a( 1, 1 ),
-* AP( 2 ) and AP( 3 ) contain a( 1, 2 ) and a( 2, 2 )
-* respectively, and so on.
-* Before entry with UPLO = 'L' or 'l', the array AP must
-* contain the lower triangular matrix packed sequentially,
-* column by column, so that AP( 1 ) contains a( 1, 1 ),
-* AP( 2 ) and AP( 3 ) contain a( 2, 1 ) and a( 3, 1 )
-* respectively, and so on.
-* Note that when DIAG = 'U' or 'u', the diagonal elements of
-* A are not referenced, but are assumed to be unity.
-* Unchanged on exit.
-*
-* X - COMPLEX array of dimension at least
-* ( 1 + ( n - 1 )*abs( INCX ) ).
-* Before entry, the incremented array X must contain the n
-* element vector x. On exit, X is overwritten with the
-* tranformed vector x.
-*
-* INCX - INTEGER.
-* On entry, INCX specifies the increment for the elements of
-* X. INCX must not be zero.
-* Unchanged on exit.
-*
-* Further Details
-* ===============
-*
-* Level 2 Blas routine.
-*
-* -- Written on 22-October-1986.
-* Jack Dongarra, Argonne National Lab.
-* Jeremy Du Croz, Nag Central Office.
-* Sven Hammarling, Nag Central Office.
-* Richard Hanson, Sandia National Labs.
-*
-* =====================================================================
-*
-* .. Parameters ..
- COMPLEX ZERO
- PARAMETER (ZERO= (0.0E+0,0.0E+0))
-* ..
-* .. Local Scalars ..
- COMPLEX TEMP
- INTEGER I,INFO,IX,J,JX,K,KK,KX
- LOGICAL NOCONJ,NOUNIT
-* ..
-* .. External Functions ..
- LOGICAL LSAME
- EXTERNAL LSAME
-* ..
-* .. External Subroutines ..
- EXTERNAL XERBLA
-* ..
-* .. Intrinsic Functions ..
- INTRINSIC CONJG
-* ..
-*
-* Test the input parameters.
-*
- INFO = 0
- IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN
- INFO = 1
- ELSE IF (.NOT.LSAME(TRANS,'N') .AND. .NOT.LSAME(TRANS,'T') .AND.
- + .NOT.LSAME(TRANS,'C')) THEN
- INFO = 2
- ELSE IF (.NOT.LSAME(DIAG,'U') .AND. .NOT.LSAME(DIAG,'N')) THEN
- INFO = 3
- ELSE IF (N.LT.0) THEN
- INFO = 4
- ELSE IF (INCX.EQ.0) THEN
- INFO = 7
- END IF
- IF (INFO.NE.0) THEN
- CALL XERBLA('CTPMV ',INFO)
- RETURN
- END IF
-*
-* Quick return if possible.
-*
- IF (N.EQ.0) RETURN
-*
- NOCONJ = LSAME(TRANS,'T')
- NOUNIT = LSAME(DIAG,'N')
-*
-* Set up the start point in X if the increment is not unity. This
-* will be ( N - 1 )*INCX too small for descending loops.
-*
- IF (INCX.LE.0) THEN
- KX = 1 - (N-1)*INCX
- ELSE IF (INCX.NE.1) THEN
- KX = 1
- END IF
-*
-* Start the operations. In this version the elements of AP are
-* accessed sequentially with one pass through AP.
-*
- IF (LSAME(TRANS,'N')) THEN
-*
-* Form x:= A*x.
-*
- IF (LSAME(UPLO,'U')) THEN
- KK = 1
- IF (INCX.EQ.1) THEN
- DO 20 J = 1,N
- IF (X(J).NE.ZERO) THEN
- TEMP = X(J)
- K = KK
- DO 10 I = 1,J - 1
- X(I) = X(I) + TEMP*AP(K)
- K = K + 1
- 10 CONTINUE
- IF (NOUNIT) X(J) = X(J)*AP(KK+J-1)
- END IF
- KK = KK + J
- 20 CONTINUE
- ELSE
- JX = KX
- DO 40 J = 1,N
- IF (X(JX).NE.ZERO) THEN
- TEMP = X(JX)
- IX = KX
- DO 30 K = KK,KK + J - 2
- X(IX) = X(IX) + TEMP*AP(K)
- IX = IX + INCX
- 30 CONTINUE
- IF (NOUNIT) X(JX) = X(JX)*AP(KK+J-1)
- END IF
- JX = JX + INCX
- KK = KK + J
- 40 CONTINUE
- END IF
- ELSE
- KK = (N* (N+1))/2
- IF (INCX.EQ.1) THEN
- DO 60 J = N,1,-1
- IF (X(J).NE.ZERO) THEN
- TEMP = X(J)
- K = KK
- DO 50 I = N,J + 1,-1
- X(I) = X(I) + TEMP*AP(K)
- K = K - 1
- 50 CONTINUE
- IF (NOUNIT) X(J) = X(J)*AP(KK-N+J)
- END IF
- KK = KK - (N-J+1)
- 60 CONTINUE
- ELSE
- KX = KX + (N-1)*INCX
- JX = KX
- DO 80 J = N,1,-1
- IF (X(JX).NE.ZERO) THEN
- TEMP = X(JX)
- IX = KX
- DO 70 K = KK,KK - (N- (J+1)),-1
- X(IX) = X(IX) + TEMP*AP(K)
- IX = IX - INCX
- 70 CONTINUE
- IF (NOUNIT) X(JX) = X(JX)*AP(KK-N+J)
- END IF
- JX = JX - INCX
- KK = KK - (N-J+1)
- 80 CONTINUE
- END IF
- END IF
- ELSE
-*
-* Form x := A'*x or x := conjg( A' )*x.
-*
- IF (LSAME(UPLO,'U')) THEN
- KK = (N* (N+1))/2
- IF (INCX.EQ.1) THEN
- DO 110 J = N,1,-1
- TEMP = X(J)
- K = KK - 1
- IF (NOCONJ) THEN
- IF (NOUNIT) TEMP = TEMP*AP(KK)
- DO 90 I = J - 1,1,-1
- TEMP = TEMP + AP(K)*X(I)
- K = K - 1
- 90 CONTINUE
- ELSE
- IF (NOUNIT) TEMP = TEMP*CONJG(AP(KK))
- DO 100 I = J - 1,1,-1
- TEMP = TEMP + CONJG(AP(K))*X(I)
- K = K - 1
- 100 CONTINUE
- END IF
- X(J) = TEMP
- KK = KK - J
- 110 CONTINUE
- ELSE
- JX = KX + (N-1)*INCX
- DO 140 J = N,1,-1
- TEMP = X(JX)
- IX = JX
- IF (NOCONJ) THEN
- IF (NOUNIT) TEMP = TEMP*AP(KK)
- DO 120 K = KK - 1,KK - J + 1,-1
- IX = IX - INCX
- TEMP = TEMP + AP(K)*X(IX)
- 120 CONTINUE
- ELSE
- IF (NOUNIT) TEMP = TEMP*CONJG(AP(KK))
- DO 130 K = KK - 1,KK - J + 1,-1
- IX = IX - INCX
- TEMP = TEMP + CONJG(AP(K))*X(IX)
- 130 CONTINUE
- END IF
- X(JX) = TEMP
- JX = JX - INCX
- KK = KK - J
- 140 CONTINUE
- END IF
- ELSE
- KK = 1
- IF (INCX.EQ.1) THEN
- DO 170 J = 1,N
- TEMP = X(J)
- K = KK + 1
- IF (NOCONJ) THEN
- IF (NOUNIT) TEMP = TEMP*AP(KK)
- DO 150 I = J + 1,N
- TEMP = TEMP + AP(K)*X(I)
- K = K + 1
- 150 CONTINUE
- ELSE
- IF (NOUNIT) TEMP = TEMP*CONJG(AP(KK))
- DO 160 I = J + 1,N
- TEMP = TEMP + CONJG(AP(K))*X(I)
- K = K + 1
- 160 CONTINUE
- END IF
- X(J) = TEMP
- KK = KK + (N-J+1)
- 170 CONTINUE
- ELSE
- JX = KX
- DO 200 J = 1,N
- TEMP = X(JX)
- IX = JX
- IF (NOCONJ) THEN
- IF (NOUNIT) TEMP = TEMP*AP(KK)
- DO 180 K = KK + 1,KK + N - J
- IX = IX + INCX
- TEMP = TEMP + AP(K)*X(IX)
- 180 CONTINUE
- ELSE
- IF (NOUNIT) TEMP = TEMP*CONJG(AP(KK))
- DO 190 K = KK + 1,KK + N - J
- IX = IX + INCX
- TEMP = TEMP + CONJG(AP(K))*X(IX)
- 190 CONTINUE
- END IF
- X(JX) = TEMP
- JX = JX + INCX
- KK = KK + (N-J+1)
- 200 CONTINUE
- END IF
- END IF
- END IF
-*
- RETURN
-*
-* End of CTPMV .
-*
- END
diff --git a/blas/ctpsv.f b/blas/ctpsv.f
deleted file mode 100644
index 1804797ea..000000000
--- a/blas/ctpsv.f
+++ /dev/null
@@ -1,332 +0,0 @@
- SUBROUTINE CTPSV(UPLO,TRANS,DIAG,N,AP,X,INCX)
-* .. Scalar Arguments ..
- INTEGER INCX,N
- CHARACTER DIAG,TRANS,UPLO
-* ..
-* .. Array Arguments ..
- COMPLEX AP(*),X(*)
-* ..
-*
-* Purpose
-* =======
-*
-* CTPSV solves one of the systems of equations
-*
-* A*x = b, or A'*x = b, or conjg( A' )*x = b,
-*
-* where b and x are n element vectors and A is an n by n unit, or
-* non-unit, upper or lower triangular matrix, supplied in packed form.
-*
-* No test for singularity or near-singularity is included in this
-* routine. Such tests must be performed before calling this routine.
-*
-* Arguments
-* ==========
-*
-* UPLO - CHARACTER*1.
-* On entry, UPLO specifies whether the matrix is an upper or
-* lower triangular matrix as follows:
-*
-* UPLO = 'U' or 'u' A is an upper triangular matrix.
-*
-* UPLO = 'L' or 'l' A is a lower triangular matrix.
-*
-* Unchanged on exit.
-*
-* TRANS - CHARACTER*1.
-* On entry, TRANS specifies the equations to be solved as
-* follows:
-*
-* TRANS = 'N' or 'n' A*x = b.
-*
-* TRANS = 'T' or 't' A'*x = b.
-*
-* TRANS = 'C' or 'c' conjg( A' )*x = b.
-*
-* Unchanged on exit.
-*
-* DIAG - CHARACTER*1.
-* On entry, DIAG specifies whether or not A is unit
-* triangular as follows:
-*
-* DIAG = 'U' or 'u' A is assumed to be unit triangular.
-*
-* DIAG = 'N' or 'n' A is not assumed to be unit
-* triangular.
-*
-* Unchanged on exit.
-*
-* N - INTEGER.
-* On entry, N specifies the order of the matrix A.
-* N must be at least zero.
-* Unchanged on exit.
-*
-* AP - COMPLEX array of DIMENSION at least
-* ( ( n*( n + 1 ) )/2 ).
-* Before entry with UPLO = 'U' or 'u', the array AP must
-* contain the upper triangular matrix packed sequentially,
-* column by column, so that AP( 1 ) contains a( 1, 1 ),
-* AP( 2 ) and AP( 3 ) contain a( 1, 2 ) and a( 2, 2 )
-* respectively, and so on.
-* Before entry with UPLO = 'L' or 'l', the array AP must
-* contain the lower triangular matrix packed sequentially,
-* column by column, so that AP( 1 ) contains a( 1, 1 ),
-* AP( 2 ) and AP( 3 ) contain a( 2, 1 ) and a( 3, 1 )
-* respectively, and so on.
-* Note that when DIAG = 'U' or 'u', the diagonal elements of
-* A are not referenced, but are assumed to be unity.
-* Unchanged on exit.
-*
-* X - COMPLEX array of dimension at least
-* ( 1 + ( n - 1 )*abs( INCX ) ).
-* Before entry, the incremented array X must contain the n
-* element right-hand side vector b. On exit, X is overwritten
-* with the solution vector x.
-*
-* INCX - INTEGER.
-* On entry, INCX specifies the increment for the elements of
-* X. INCX must not be zero.
-* Unchanged on exit.
-*
-* Further Details
-* ===============
-*
-* Level 2 Blas routine.
-*
-* -- Written on 22-October-1986.
-* Jack Dongarra, Argonne National Lab.
-* Jeremy Du Croz, Nag Central Office.
-* Sven Hammarling, Nag Central Office.
-* Richard Hanson, Sandia National Labs.
-*
-* =====================================================================
-*
-* .. Parameters ..
- COMPLEX ZERO
- PARAMETER (ZERO= (0.0E+0,0.0E+0))
-* ..
-* .. Local Scalars ..
- COMPLEX TEMP
- INTEGER I,INFO,IX,J,JX,K,KK,KX
- LOGICAL NOCONJ,NOUNIT
-* ..
-* .. External Functions ..
- LOGICAL LSAME
- EXTERNAL LSAME
-* ..
-* .. External Subroutines ..
- EXTERNAL XERBLA
-* ..
-* .. Intrinsic Functions ..
- INTRINSIC CONJG
-* ..
-*
-* Test the input parameters.
-*
- INFO = 0
- IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN
- INFO = 1
- ELSE IF (.NOT.LSAME(TRANS,'N') .AND. .NOT.LSAME(TRANS,'T') .AND.
- + .NOT.LSAME(TRANS,'C')) THEN
- INFO = 2
- ELSE IF (.NOT.LSAME(DIAG,'U') .AND. .NOT.LSAME(DIAG,'N')) THEN
- INFO = 3
- ELSE IF (N.LT.0) THEN
- INFO = 4
- ELSE IF (INCX.EQ.0) THEN
- INFO = 7
- END IF
- IF (INFO.NE.0) THEN
- CALL XERBLA('CTPSV ',INFO)
- RETURN
- END IF
-*
-* Quick return if possible.
-*
- IF (N.EQ.0) RETURN
-*
- NOCONJ = LSAME(TRANS,'T')
- NOUNIT = LSAME(DIAG,'N')
-*
-* Set up the start point in X if the increment is not unity. This
-* will be ( N - 1 )*INCX too small for descending loops.
-*
- IF (INCX.LE.0) THEN
- KX = 1 - (N-1)*INCX
- ELSE IF (INCX.NE.1) THEN
- KX = 1
- END IF
-*
-* Start the operations. In this version the elements of AP are
-* accessed sequentially with one pass through AP.
-*
- IF (LSAME(TRANS,'N')) THEN
-*
-* Form x := inv( A )*x.
-*
- IF (LSAME(UPLO,'U')) THEN
- KK = (N* (N+1))/2
- IF (INCX.EQ.1) THEN
- DO 20 J = N,1,-1
- IF (X(J).NE.ZERO) THEN
- IF (NOUNIT) X(J) = X(J)/AP(KK)
- TEMP = X(J)
- K = KK - 1
- DO 10 I = J - 1,1,-1
- X(I) = X(I) - TEMP*AP(K)
- K = K - 1
- 10 CONTINUE
- END IF
- KK = KK - J
- 20 CONTINUE
- ELSE
- JX = KX + (N-1)*INCX
- DO 40 J = N,1,-1
- IF (X(JX).NE.ZERO) THEN
- IF (NOUNIT) X(JX) = X(JX)/AP(KK)
- TEMP = X(JX)
- IX = JX
- DO 30 K = KK - 1,KK - J + 1,-1
- IX = IX - INCX
- X(IX) = X(IX) - TEMP*AP(K)
- 30 CONTINUE
- END IF
- JX = JX - INCX
- KK = KK - J
- 40 CONTINUE
- END IF
- ELSE
- KK = 1
- IF (INCX.EQ.1) THEN
- DO 60 J = 1,N
- IF (X(J).NE.ZERO) THEN
- IF (NOUNIT) X(J) = X(J)/AP(KK)
- TEMP = X(J)
- K = KK + 1
- DO 50 I = J + 1,N
- X(I) = X(I) - TEMP*AP(K)
- K = K + 1
- 50 CONTINUE
- END IF
- KK = KK + (N-J+1)
- 60 CONTINUE
- ELSE
- JX = KX
- DO 80 J = 1,N
- IF (X(JX).NE.ZERO) THEN
- IF (NOUNIT) X(JX) = X(JX)/AP(KK)
- TEMP = X(JX)
- IX = JX
- DO 70 K = KK + 1,KK + N - J
- IX = IX + INCX
- X(IX) = X(IX) - TEMP*AP(K)
- 70 CONTINUE
- END IF
- JX = JX + INCX
- KK = KK + (N-J+1)
- 80 CONTINUE
- END IF
- END IF
- ELSE
-*
-* Form x := inv( A' )*x or x := inv( conjg( A' ) )*x.
-*
- IF (LSAME(UPLO,'U')) THEN
- KK = 1
- IF (INCX.EQ.1) THEN
- DO 110 J = 1,N
- TEMP = X(J)
- K = KK
- IF (NOCONJ) THEN
- DO 90 I = 1,J - 1
- TEMP = TEMP - AP(K)*X(I)
- K = K + 1
- 90 CONTINUE
- IF (NOUNIT) TEMP = TEMP/AP(KK+J-1)
- ELSE
- DO 100 I = 1,J - 1
- TEMP = TEMP - CONJG(AP(K))*X(I)
- K = K + 1
- 100 CONTINUE
- IF (NOUNIT) TEMP = TEMP/CONJG(AP(KK+J-1))
- END IF
- X(J) = TEMP
- KK = KK + J
- 110 CONTINUE
- ELSE
- JX = KX
- DO 140 J = 1,N
- TEMP = X(JX)
- IX = KX
- IF (NOCONJ) THEN
- DO 120 K = KK,KK + J - 2
- TEMP = TEMP - AP(K)*X(IX)
- IX = IX + INCX
- 120 CONTINUE
- IF (NOUNIT) TEMP = TEMP/AP(KK+J-1)
- ELSE
- DO 130 K = KK,KK + J - 2
- TEMP = TEMP - CONJG(AP(K))*X(IX)
- IX = IX + INCX
- 130 CONTINUE
- IF (NOUNIT) TEMP = TEMP/CONJG(AP(KK+J-1))
- END IF
- X(JX) = TEMP
- JX = JX + INCX
- KK = KK + J
- 140 CONTINUE
- END IF
- ELSE
- KK = (N* (N+1))/2
- IF (INCX.EQ.1) THEN
- DO 170 J = N,1,-1
- TEMP = X(J)
- K = KK
- IF (NOCONJ) THEN
- DO 150 I = N,J + 1,-1
- TEMP = TEMP - AP(K)*X(I)
- K = K - 1
- 150 CONTINUE
- IF (NOUNIT) TEMP = TEMP/AP(KK-N+J)
- ELSE
- DO 160 I = N,J + 1,-1
- TEMP = TEMP - CONJG(AP(K))*X(I)
- K = K - 1
- 160 CONTINUE
- IF (NOUNIT) TEMP = TEMP/CONJG(AP(KK-N+J))
- END IF
- X(J) = TEMP
- KK = KK - (N-J+1)
- 170 CONTINUE
- ELSE
- KX = KX + (N-1)*INCX
- JX = KX
- DO 200 J = N,1,-1
- TEMP = X(JX)
- IX = KX
- IF (NOCONJ) THEN
- DO 180 K = KK,KK - (N- (J+1)),-1
- TEMP = TEMP - AP(K)*X(IX)
- IX = IX - INCX
- 180 CONTINUE
- IF (NOUNIT) TEMP = TEMP/AP(KK-N+J)
- ELSE
- DO 190 K = KK,KK - (N- (J+1)),-1
- TEMP = TEMP - CONJG(AP(K))*X(IX)
- IX = IX - INCX
- 190 CONTINUE
- IF (NOUNIT) TEMP = TEMP/CONJG(AP(KK-N+J))
- END IF
- X(JX) = TEMP
- JX = JX - INCX
- KK = KK - (N-J+1)
- 200 CONTINUE
- END IF
- END IF
- END IF
-*
- RETURN
-*
-* End of CTPSV .
-*
- END
diff --git a/blas/double.cpp b/blas/double.cpp
index cad2f63ec..8fd0709ba 100644
--- a/blas/double.cpp
+++ b/blas/double.cpp
@@ -2,6 +2,7 @@
// for linear algebra.
//
// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2012 Chen-Pang He <jdh8@ms63.hinet.net>
//
// 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
@@ -17,3 +18,16 @@
#include "level2_impl.h"
#include "level2_real_impl.h"
#include "level3_impl.h"
+
+double BLASFUNC(dsdot)(int* n, float* x, int* incx, float* y, int* incy)
+{
+ if(*n<=0) return 0;
+
+ if(*incx==1 && *incy==1) return (vector(x,*n).cast<double>().cwiseProduct(vector(y,*n).cast<double>())).sum();
+ else if(*incx>0 && *incy>0) return (vector(x,*n,*incx).cast<double>().cwiseProduct(vector(y,*n,*incy).cast<double>())).sum();
+ else if(*incx<0 && *incy>0) return (vector(x,*n,-*incx).reverse().cast<double>().cwiseProduct(vector(y,*n,*incy).cast<double>())).sum();
+ else if(*incx>0 && *incy<0) return (vector(x,*n,*incx).cast<double>().cwiseProduct(vector(y,*n,-*incy).reverse().cast<double>())).sum();
+ else if(*incx<0 && *incy<0) return (vector(x,*n,-*incx).reverse().cast<double>().cwiseProduct(vector(y,*n,-*incy).reverse().cast<double>())).sum();
+ else return 0;
+}
+
diff --git a/blas/dspr.f b/blas/dspr.f
deleted file mode 100644
index 538e4f76b..000000000
--- a/blas/dspr.f
+++ /dev/null
@@ -1,202 +0,0 @@
- SUBROUTINE DSPR(UPLO,N,ALPHA,X,INCX,AP)
-* .. Scalar Arguments ..
- DOUBLE PRECISION ALPHA
- INTEGER INCX,N
- CHARACTER UPLO
-* ..
-* .. Array Arguments ..
- DOUBLE PRECISION AP(*),X(*)
-* ..
-*
-* Purpose
-* =======
-*
-* DSPR performs the symmetric rank 1 operation
-*
-* A := alpha*x*x' + A,
-*
-* where alpha is a real scalar, x is an n element vector and A is an
-* n by n symmetric matrix, supplied in packed form.
-*
-* Arguments
-* ==========
-*
-* UPLO - CHARACTER*1.
-* On entry, UPLO specifies whether the upper or lower
-* triangular part of the matrix A is supplied in the packed
-* array AP as follows:
-*
-* UPLO = 'U' or 'u' The upper triangular part of A is
-* supplied in AP.
-*
-* UPLO = 'L' or 'l' The lower triangular part of A is
-* supplied in AP.
-*
-* Unchanged on exit.
-*
-* N - INTEGER.
-* On entry, N specifies the order of the matrix A.
-* N must be at least zero.
-* Unchanged on exit.
-*
-* ALPHA - DOUBLE PRECISION.
-* On entry, ALPHA specifies the scalar alpha.
-* Unchanged on exit.
-*
-* X - DOUBLE PRECISION array of dimension at least
-* ( 1 + ( n - 1 )*abs( INCX ) ).
-* Before entry, the incremented array X must contain the n
-* element vector x.
-* Unchanged on exit.
-*
-* INCX - INTEGER.
-* On entry, INCX specifies the increment for the elements of
-* X. INCX must not be zero.
-* Unchanged on exit.
-*
-* AP - DOUBLE PRECISION array of DIMENSION at least
-* ( ( n*( n + 1 ) )/2 ).
-* Before entry with UPLO = 'U' or 'u', the array AP must
-* contain the upper triangular part of the symmetric matrix
-* packed sequentially, column by column, so that AP( 1 )
-* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 1, 2 )
-* and a( 2, 2 ) respectively, and so on. On exit, the array
-* AP is overwritten by the upper triangular part of the
-* updated matrix.
-* Before entry with UPLO = 'L' or 'l', the array AP must
-* contain the lower triangular part of the symmetric matrix
-* packed sequentially, column by column, so that AP( 1 )
-* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 2, 1 )
-* and a( 3, 1 ) respectively, and so on. On exit, the array
-* AP is overwritten by the lower triangular part of the
-* updated matrix.
-*
-* Further Details
-* ===============
-*
-* Level 2 Blas routine.
-*
-* -- Written on 22-October-1986.
-* Jack Dongarra, Argonne National Lab.
-* Jeremy Du Croz, Nag Central Office.
-* Sven Hammarling, Nag Central Office.
-* Richard Hanson, Sandia National Labs.
-*
-* =====================================================================
-*
-* .. Parameters ..
- DOUBLE PRECISION ZERO
- PARAMETER (ZERO=0.0D+0)
-* ..
-* .. Local Scalars ..
- DOUBLE PRECISION TEMP
- INTEGER I,INFO,IX,J,JX,K,KK,KX
-* ..
-* .. External Functions ..
- LOGICAL LSAME
- EXTERNAL LSAME
-* ..
-* .. External Subroutines ..
- EXTERNAL XERBLA
-* ..
-*
-* Test the input parameters.
-*
- INFO = 0
- IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN
- INFO = 1
- ELSE IF (N.LT.0) THEN
- INFO = 2
- ELSE IF (INCX.EQ.0) THEN
- INFO = 5
- END IF
- IF (INFO.NE.0) THEN
- CALL XERBLA('DSPR ',INFO)
- RETURN
- END IF
-*
-* Quick return if possible.
-*
- IF ((N.EQ.0) .OR. (ALPHA.EQ.ZERO)) RETURN
-*
-* Set the start point in X if the increment is not unity.
-*
- IF (INCX.LE.0) THEN
- KX = 1 - (N-1)*INCX
- ELSE IF (INCX.NE.1) THEN
- KX = 1
- END IF
-*
-* Start the operations. In this version the elements of the array AP
-* are accessed sequentially with one pass through AP.
-*
- KK = 1
- IF (LSAME(UPLO,'U')) THEN
-*
-* Form A when upper triangle is stored in AP.
-*
- IF (INCX.EQ.1) THEN
- DO 20 J = 1,N
- IF (X(J).NE.ZERO) THEN
- TEMP = ALPHA*X(J)
- K = KK
- DO 10 I = 1,J
- AP(K) = AP(K) + X(I)*TEMP
- K = K + 1
- 10 CONTINUE
- END IF
- KK = KK + J
- 20 CONTINUE
- ELSE
- JX = KX
- DO 40 J = 1,N
- IF (X(JX).NE.ZERO) THEN
- TEMP = ALPHA*X(JX)
- IX = KX
- DO 30 K = KK,KK + J - 1
- AP(K) = AP(K) + X(IX)*TEMP
- IX = IX + INCX
- 30 CONTINUE
- END IF
- JX = JX + INCX
- KK = KK + J
- 40 CONTINUE
- END IF
- ELSE
-*
-* Form A when lower triangle is stored in AP.
-*
- IF (INCX.EQ.1) THEN
- DO 60 J = 1,N
- IF (X(J).NE.ZERO) THEN
- TEMP = ALPHA*X(J)
- K = KK
- DO 50 I = J,N
- AP(K) = AP(K) + X(I)*TEMP
- K = K + 1
- 50 CONTINUE
- END IF
- KK = KK + N - J + 1
- 60 CONTINUE
- ELSE
- JX = KX
- DO 80 J = 1,N
- IF (X(JX).NE.ZERO) THEN
- TEMP = ALPHA*X(JX)
- IX = JX
- DO 70 K = KK,KK + N - J
- AP(K) = AP(K) + X(IX)*TEMP
- IX = IX + INCX
- 70 CONTINUE
- END IF
- JX = JX + INCX
- KK = KK + N - J + 1
- 80 CONTINUE
- END IF
- END IF
-*
- RETURN
-*
-* End of DSPR .
-*
- END
diff --git a/blas/dspr2.f b/blas/dspr2.f
deleted file mode 100644
index 6f6b54a8c..000000000
--- a/blas/dspr2.f
+++ /dev/null
@@ -1,233 +0,0 @@
- SUBROUTINE DSPR2(UPLO,N,ALPHA,X,INCX,Y,INCY,AP)
-* .. Scalar Arguments ..
- DOUBLE PRECISION ALPHA
- INTEGER INCX,INCY,N
- CHARACTER UPLO
-* ..
-* .. Array Arguments ..
- DOUBLE PRECISION AP(*),X(*),Y(*)
-* ..
-*
-* Purpose
-* =======
-*
-* DSPR2 performs the symmetric rank 2 operation
-*
-* A := alpha*x*y' + alpha*y*x' + A,
-*
-* where alpha is a scalar, x and y are n element vectors and A is an
-* n by n symmetric matrix, supplied in packed form.
-*
-* Arguments
-* ==========
-*
-* UPLO - CHARACTER*1.
-* On entry, UPLO specifies whether the upper or lower
-* triangular part of the matrix A is supplied in the packed
-* array AP as follows:
-*
-* UPLO = 'U' or 'u' The upper triangular part of A is
-* supplied in AP.
-*
-* UPLO = 'L' or 'l' The lower triangular part of A is
-* supplied in AP.
-*
-* Unchanged on exit.
-*
-* N - INTEGER.
-* On entry, N specifies the order of the matrix A.
-* N must be at least zero.
-* Unchanged on exit.
-*
-* ALPHA - DOUBLE PRECISION.
-* On entry, ALPHA specifies the scalar alpha.
-* Unchanged on exit.
-*
-* X - DOUBLE PRECISION array of dimension at least
-* ( 1 + ( n - 1 )*abs( INCX ) ).
-* Before entry, the incremented array X must contain the n
-* element vector x.
-* Unchanged on exit.
-*
-* INCX - INTEGER.
-* On entry, INCX specifies the increment for the elements of
-* X. INCX must not be zero.
-* Unchanged on exit.
-*
-* Y - DOUBLE PRECISION array of dimension at least
-* ( 1 + ( n - 1 )*abs( INCY ) ).
-* Before entry, the incremented array Y must contain the n
-* element vector y.
-* Unchanged on exit.
-*
-* INCY - INTEGER.
-* On entry, INCY specifies the increment for the elements of
-* Y. INCY must not be zero.
-* Unchanged on exit.
-*
-* AP - DOUBLE PRECISION array of DIMENSION at least
-* ( ( n*( n + 1 ) )/2 ).
-* Before entry with UPLO = 'U' or 'u', the array AP must
-* contain the upper triangular part of the symmetric matrix
-* packed sequentially, column by column, so that AP( 1 )
-* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 1, 2 )
-* and a( 2, 2 ) respectively, and so on. On exit, the array
-* AP is overwritten by the upper triangular part of the
-* updated matrix.
-* Before entry with UPLO = 'L' or 'l', the array AP must
-* contain the lower triangular part of the symmetric matrix
-* packed sequentially, column by column, so that AP( 1 )
-* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 2, 1 )
-* and a( 3, 1 ) respectively, and so on. On exit, the array
-* AP is overwritten by the lower triangular part of the
-* updated matrix.
-*
-* Further Details
-* ===============
-*
-* Level 2 Blas routine.
-*
-* -- Written on 22-October-1986.
-* Jack Dongarra, Argonne National Lab.
-* Jeremy Du Croz, Nag Central Office.
-* Sven Hammarling, Nag Central Office.
-* Richard Hanson, Sandia National Labs.
-*
-* =====================================================================
-*
-* .. Parameters ..
- DOUBLE PRECISION ZERO
- PARAMETER (ZERO=0.0D+0)
-* ..
-* .. Local Scalars ..
- DOUBLE PRECISION TEMP1,TEMP2
- INTEGER I,INFO,IX,IY,J,JX,JY,K,KK,KX,KY
-* ..
-* .. External Functions ..
- LOGICAL LSAME
- EXTERNAL LSAME
-* ..
-* .. External Subroutines ..
- EXTERNAL XERBLA
-* ..
-*
-* Test the input parameters.
-*
- INFO = 0
- IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN
- INFO = 1
- ELSE IF (N.LT.0) THEN
- INFO = 2
- ELSE IF (INCX.EQ.0) THEN
- INFO = 5
- ELSE IF (INCY.EQ.0) THEN
- INFO = 7
- END IF
- IF (INFO.NE.0) THEN
- CALL XERBLA('DSPR2 ',INFO)
- RETURN
- END IF
-*
-* Quick return if possible.
-*
- IF ((N.EQ.0) .OR. (ALPHA.EQ.ZERO)) RETURN
-*
-* Set up the start points in X and Y if the increments are not both
-* unity.
-*
- IF ((INCX.NE.1) .OR. (INCY.NE.1)) THEN
- IF (INCX.GT.0) THEN
- KX = 1
- ELSE
- KX = 1 - (N-1)*INCX
- END IF
- IF (INCY.GT.0) THEN
- KY = 1
- ELSE
- KY = 1 - (N-1)*INCY
- END IF
- JX = KX
- JY = KY
- END IF
-*
-* Start the operations. In this version the elements of the array AP
-* are accessed sequentially with one pass through AP.
-*
- KK = 1
- IF (LSAME(UPLO,'U')) THEN
-*
-* Form A when upper triangle is stored in AP.
-*
- IF ((INCX.EQ.1) .AND. (INCY.EQ.1)) THEN
- DO 20 J = 1,N
- IF ((X(J).NE.ZERO) .OR. (Y(J).NE.ZERO)) THEN
- TEMP1 = ALPHA*Y(J)
- TEMP2 = ALPHA*X(J)
- K = KK
- DO 10 I = 1,J
- AP(K) = AP(K) + X(I)*TEMP1 + Y(I)*TEMP2
- K = K + 1
- 10 CONTINUE
- END IF
- KK = KK + J
- 20 CONTINUE
- ELSE
- DO 40 J = 1,N
- IF ((X(JX).NE.ZERO) .OR. (Y(JY).NE.ZERO)) THEN
- TEMP1 = ALPHA*Y(JY)
- TEMP2 = ALPHA*X(JX)
- IX = KX
- IY = KY
- DO 30 K = KK,KK + J - 1
- AP(K) = AP(K) + X(IX)*TEMP1 + Y(IY)*TEMP2
- IX = IX + INCX
- IY = IY + INCY
- 30 CONTINUE
- END IF
- JX = JX + INCX
- JY = JY + INCY
- KK = KK + J
- 40 CONTINUE
- END IF
- ELSE
-*
-* Form A when lower triangle is stored in AP.
-*
- IF ((INCX.EQ.1) .AND. (INCY.EQ.1)) THEN
- DO 60 J = 1,N
- IF ((X(J).NE.ZERO) .OR. (Y(J).NE.ZERO)) THEN
- TEMP1 = ALPHA*Y(J)
- TEMP2 = ALPHA*X(J)
- K = KK
- DO 50 I = J,N
- AP(K) = AP(K) + X(I)*TEMP1 + Y(I)*TEMP2
- K = K + 1
- 50 CONTINUE
- END IF
- KK = KK + N - J + 1
- 60 CONTINUE
- ELSE
- DO 80 J = 1,N
- IF ((X(JX).NE.ZERO) .OR. (Y(JY).NE.ZERO)) THEN
- TEMP1 = ALPHA*Y(JY)
- TEMP2 = ALPHA*X(JX)
- IX = JX
- IY = JY
- DO 70 K = KK,KK + N - J
- AP(K) = AP(K) + X(IX)*TEMP1 + Y(IY)*TEMP2
- IX = IX + INCX
- IY = IY + INCY
- 70 CONTINUE
- END IF
- JX = JX + INCX
- JY = JY + INCY
- KK = KK + N - J + 1
- 80 CONTINUE
- END IF
- END IF
-*
- RETURN
-*
-* End of DSPR2 .
-*
- END
diff --git a/blas/dtpmv.f b/blas/dtpmv.f
deleted file mode 100644
index c5bc112dc..000000000
--- a/blas/dtpmv.f
+++ /dev/null
@@ -1,293 +0,0 @@
- SUBROUTINE DTPMV(UPLO,TRANS,DIAG,N,AP,X,INCX)
-* .. Scalar Arguments ..
- INTEGER INCX,N
- CHARACTER DIAG,TRANS,UPLO
-* ..
-* .. Array Arguments ..
- DOUBLE PRECISION AP(*),X(*)
-* ..
-*
-* Purpose
-* =======
-*
-* DTPMV performs one of the matrix-vector operations
-*
-* x := A*x, or x := A'*x,
-*
-* where x is an n element vector and A is an n by n unit, or non-unit,
-* upper or lower triangular matrix, supplied in packed form.
-*
-* Arguments
-* ==========
-*
-* UPLO - CHARACTER*1.
-* On entry, UPLO specifies whether the matrix is an upper or
-* lower triangular matrix as follows:
-*
-* UPLO = 'U' or 'u' A is an upper triangular matrix.
-*
-* UPLO = 'L' or 'l' A is a lower triangular matrix.
-*
-* Unchanged on exit.
-*
-* TRANS - CHARACTER*1.
-* On entry, TRANS specifies the operation to be performed as
-* follows:
-*
-* TRANS = 'N' or 'n' x := A*x.
-*
-* TRANS = 'T' or 't' x := A'*x.
-*
-* TRANS = 'C' or 'c' x := A'*x.
-*
-* Unchanged on exit.
-*
-* DIAG - CHARACTER*1.
-* On entry, DIAG specifies whether or not A is unit
-* triangular as follows:
-*
-* DIAG = 'U' or 'u' A is assumed to be unit triangular.
-*
-* DIAG = 'N' or 'n' A is not assumed to be unit
-* triangular.
-*
-* Unchanged on exit.
-*
-* N - INTEGER.
-* On entry, N specifies the order of the matrix A.
-* N must be at least zero.
-* Unchanged on exit.
-*
-* AP - DOUBLE PRECISION array of DIMENSION at least
-* ( ( n*( n + 1 ) )/2 ).
-* Before entry with UPLO = 'U' or 'u', the array AP must
-* contain the upper triangular matrix packed sequentially,
-* column by column, so that AP( 1 ) contains a( 1, 1 ),
-* AP( 2 ) and AP( 3 ) contain a( 1, 2 ) and a( 2, 2 )
-* respectively, and so on.
-* Before entry with UPLO = 'L' or 'l', the array AP must
-* contain the lower triangular matrix packed sequentially,
-* column by column, so that AP( 1 ) contains a( 1, 1 ),
-* AP( 2 ) and AP( 3 ) contain a( 2, 1 ) and a( 3, 1 )
-* respectively, and so on.
-* Note that when DIAG = 'U' or 'u', the diagonal elements of
-* A are not referenced, but are assumed to be unity.
-* Unchanged on exit.
-*
-* X - DOUBLE PRECISION array of dimension at least
-* ( 1 + ( n - 1 )*abs( INCX ) ).
-* Before entry, the incremented array X must contain the n
-* element vector x. On exit, X is overwritten with the
-* tranformed vector x.
-*
-* INCX - INTEGER.
-* On entry, INCX specifies the increment for the elements of
-* X. INCX must not be zero.
-* Unchanged on exit.
-*
-* Further Details
-* ===============
-*
-* Level 2 Blas routine.
-*
-* -- Written on 22-October-1986.
-* Jack Dongarra, Argonne National Lab.
-* Jeremy Du Croz, Nag Central Office.
-* Sven Hammarling, Nag Central Office.
-* Richard Hanson, Sandia National Labs.
-*
-* =====================================================================
-*
-* .. Parameters ..
- DOUBLE PRECISION ZERO
- PARAMETER (ZERO=0.0D+0)
-* ..
-* .. Local Scalars ..
- DOUBLE PRECISION TEMP
- INTEGER I,INFO,IX,J,JX,K,KK,KX
- LOGICAL NOUNIT
-* ..
-* .. External Functions ..
- LOGICAL LSAME
- EXTERNAL LSAME
-* ..
-* .. External Subroutines ..
- EXTERNAL XERBLA
-* ..
-*
-* Test the input parameters.
-*
- INFO = 0
- IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN
- INFO = 1
- ELSE IF (.NOT.LSAME(TRANS,'N') .AND. .NOT.LSAME(TRANS,'T') .AND.
- + .NOT.LSAME(TRANS,'C')) THEN
- INFO = 2
- ELSE IF (.NOT.LSAME(DIAG,'U') .AND. .NOT.LSAME(DIAG,'N')) THEN
- INFO = 3
- ELSE IF (N.LT.0) THEN
- INFO = 4
- ELSE IF (INCX.EQ.0) THEN
- INFO = 7
- END IF
- IF (INFO.NE.0) THEN
- CALL XERBLA('DTPMV ',INFO)
- RETURN
- END IF
-*
-* Quick return if possible.
-*
- IF (N.EQ.0) RETURN
-*
- NOUNIT = LSAME(DIAG,'N')
-*
-* Set up the start point in X if the increment is not unity. This
-* will be ( N - 1 )*INCX too small for descending loops.
-*
- IF (INCX.LE.0) THEN
- KX = 1 - (N-1)*INCX
- ELSE IF (INCX.NE.1) THEN
- KX = 1
- END IF
-*
-* Start the operations. In this version the elements of AP are
-* accessed sequentially with one pass through AP.
-*
- IF (LSAME(TRANS,'N')) THEN
-*
-* Form x:= A*x.
-*
- IF (LSAME(UPLO,'U')) THEN
- KK = 1
- IF (INCX.EQ.1) THEN
- DO 20 J = 1,N
- IF (X(J).NE.ZERO) THEN
- TEMP = X(J)
- K = KK
- DO 10 I = 1,J - 1
- X(I) = X(I) + TEMP*AP(K)
- K = K + 1
- 10 CONTINUE
- IF (NOUNIT) X(J) = X(J)*AP(KK+J-1)
- END IF
- KK = KK + J
- 20 CONTINUE
- ELSE
- JX = KX
- DO 40 J = 1,N
- IF (X(JX).NE.ZERO) THEN
- TEMP = X(JX)
- IX = KX
- DO 30 K = KK,KK + J - 2
- X(IX) = X(IX) + TEMP*AP(K)
- IX = IX + INCX
- 30 CONTINUE
- IF (NOUNIT) X(JX) = X(JX)*AP(KK+J-1)
- END IF
- JX = JX + INCX
- KK = KK + J
- 40 CONTINUE
- END IF
- ELSE
- KK = (N* (N+1))/2
- IF (INCX.EQ.1) THEN
- DO 60 J = N,1,-1
- IF (X(J).NE.ZERO) THEN
- TEMP = X(J)
- K = KK
- DO 50 I = N,J + 1,-1
- X(I) = X(I) + TEMP*AP(K)
- K = K - 1
- 50 CONTINUE
- IF (NOUNIT) X(J) = X(J)*AP(KK-N+J)
- END IF
- KK = KK - (N-J+1)
- 60 CONTINUE
- ELSE
- KX = KX + (N-1)*INCX
- JX = KX
- DO 80 J = N,1,-1
- IF (X(JX).NE.ZERO) THEN
- TEMP = X(JX)
- IX = KX
- DO 70 K = KK,KK - (N- (J+1)),-1
- X(IX) = X(IX) + TEMP*AP(K)
- IX = IX - INCX
- 70 CONTINUE
- IF (NOUNIT) X(JX) = X(JX)*AP(KK-N+J)
- END IF
- JX = JX - INCX
- KK = KK - (N-J+1)
- 80 CONTINUE
- END IF
- END IF
- ELSE
-*
-* Form x := A'*x.
-*
- IF (LSAME(UPLO,'U')) THEN
- KK = (N* (N+1))/2
- IF (INCX.EQ.1) THEN
- DO 100 J = N,1,-1
- TEMP = X(J)
- IF (NOUNIT) TEMP = TEMP*AP(KK)
- K = KK - 1
- DO 90 I = J - 1,1,-1
- TEMP = TEMP + AP(K)*X(I)
- K = K - 1
- 90 CONTINUE
- X(J) = TEMP
- KK = KK - J
- 100 CONTINUE
- ELSE
- JX = KX + (N-1)*INCX
- DO 120 J = N,1,-1
- TEMP = X(JX)
- IX = JX
- IF (NOUNIT) TEMP = TEMP*AP(KK)
- DO 110 K = KK - 1,KK - J + 1,-1
- IX = IX - INCX
- TEMP = TEMP + AP(K)*X(IX)
- 110 CONTINUE
- X(JX) = TEMP
- JX = JX - INCX
- KK = KK - J
- 120 CONTINUE
- END IF
- ELSE
- KK = 1
- IF (INCX.EQ.1) THEN
- DO 140 J = 1,N
- TEMP = X(J)
- IF (NOUNIT) TEMP = TEMP*AP(KK)
- K = KK + 1
- DO 130 I = J + 1,N
- TEMP = TEMP + AP(K)*X(I)
- K = K + 1
- 130 CONTINUE
- X(J) = TEMP
- KK = KK + (N-J+1)
- 140 CONTINUE
- ELSE
- JX = KX
- DO 160 J = 1,N
- TEMP = X(JX)
- IX = JX
- IF (NOUNIT) TEMP = TEMP*AP(KK)
- DO 150 K = KK + 1,KK + N - J
- IX = IX + INCX
- TEMP = TEMP + AP(K)*X(IX)
- 150 CONTINUE
- X(JX) = TEMP
- JX = JX + INCX
- KK = KK + (N-J+1)
- 160 CONTINUE
- END IF
- END IF
- END IF
-*
- RETURN
-*
-* End of DTPMV .
-*
- END
diff --git a/blas/dtpsv.f b/blas/dtpsv.f
deleted file mode 100644
index c7e58d32f..000000000
--- a/blas/dtpsv.f
+++ /dev/null
@@ -1,296 +0,0 @@
- SUBROUTINE DTPSV(UPLO,TRANS,DIAG,N,AP,X,INCX)
-* .. Scalar Arguments ..
- INTEGER INCX,N
- CHARACTER DIAG,TRANS,UPLO
-* ..
-* .. Array Arguments ..
- DOUBLE PRECISION AP(*),X(*)
-* ..
-*
-* Purpose
-* =======
-*
-* DTPSV solves one of the systems of equations
-*
-* A*x = b, or A'*x = b,
-*
-* where b and x are n element vectors and A is an n by n unit, or
-* non-unit, upper or lower triangular matrix, supplied in packed form.
-*
-* No test for singularity or near-singularity is included in this
-* routine. Such tests must be performed before calling this routine.
-*
-* Arguments
-* ==========
-*
-* UPLO - CHARACTER*1.
-* On entry, UPLO specifies whether the matrix is an upper or
-* lower triangular matrix as follows:
-*
-* UPLO = 'U' or 'u' A is an upper triangular matrix.
-*
-* UPLO = 'L' or 'l' A is a lower triangular matrix.
-*
-* Unchanged on exit.
-*
-* TRANS - CHARACTER*1.
-* On entry, TRANS specifies the equations to be solved as
-* follows:
-*
-* TRANS = 'N' or 'n' A*x = b.
-*
-* TRANS = 'T' or 't' A'*x = b.
-*
-* TRANS = 'C' or 'c' A'*x = b.
-*
-* Unchanged on exit.
-*
-* DIAG - CHARACTER*1.
-* On entry, DIAG specifies whether or not A is unit
-* triangular as follows:
-*
-* DIAG = 'U' or 'u' A is assumed to be unit triangular.
-*
-* DIAG = 'N' or 'n' A is not assumed to be unit
-* triangular.
-*
-* Unchanged on exit.
-*
-* N - INTEGER.
-* On entry, N specifies the order of the matrix A.
-* N must be at least zero.
-* Unchanged on exit.
-*
-* AP - DOUBLE PRECISION array of DIMENSION at least
-* ( ( n*( n + 1 ) )/2 ).
-* Before entry with UPLO = 'U' or 'u', the array AP must
-* contain the upper triangular matrix packed sequentially,
-* column by column, so that AP( 1 ) contains a( 1, 1 ),
-* AP( 2 ) and AP( 3 ) contain a( 1, 2 ) and a( 2, 2 )
-* respectively, and so on.
-* Before entry with UPLO = 'L' or 'l', the array AP must
-* contain the lower triangular matrix packed sequentially,
-* column by column, so that AP( 1 ) contains a( 1, 1 ),
-* AP( 2 ) and AP( 3 ) contain a( 2, 1 ) and a( 3, 1 )
-* respectively, and so on.
-* Note that when DIAG = 'U' or 'u', the diagonal elements of
-* A are not referenced, but are assumed to be unity.
-* Unchanged on exit.
-*
-* X - DOUBLE PRECISION array of dimension at least
-* ( 1 + ( n - 1 )*abs( INCX ) ).
-* Before entry, the incremented array X must contain the n
-* element right-hand side vector b. On exit, X is overwritten
-* with the solution vector x.
-*
-* INCX - INTEGER.
-* On entry, INCX specifies the increment for the elements of
-* X. INCX must not be zero.
-* Unchanged on exit.
-*
-* Further Details
-* ===============
-*
-* Level 2 Blas routine.
-*
-* -- Written on 22-October-1986.
-* Jack Dongarra, Argonne National Lab.
-* Jeremy Du Croz, Nag Central Office.
-* Sven Hammarling, Nag Central Office.
-* Richard Hanson, Sandia National Labs.
-*
-* =====================================================================
-*
-* .. Parameters ..
- DOUBLE PRECISION ZERO
- PARAMETER (ZERO=0.0D+0)
-* ..
-* .. Local Scalars ..
- DOUBLE PRECISION TEMP
- INTEGER I,INFO,IX,J,JX,K,KK,KX
- LOGICAL NOUNIT
-* ..
-* .. External Functions ..
- LOGICAL LSAME
- EXTERNAL LSAME
-* ..
-* .. External Subroutines ..
- EXTERNAL XERBLA
-* ..
-*
-* Test the input parameters.
-*
- INFO = 0
- IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN
- INFO = 1
- ELSE IF (.NOT.LSAME(TRANS,'N') .AND. .NOT.LSAME(TRANS,'T') .AND.
- + .NOT.LSAME(TRANS,'C')) THEN
- INFO = 2
- ELSE IF (.NOT.LSAME(DIAG,'U') .AND. .NOT.LSAME(DIAG,'N')) THEN
- INFO = 3
- ELSE IF (N.LT.0) THEN
- INFO = 4
- ELSE IF (INCX.EQ.0) THEN
- INFO = 7
- END IF
- IF (INFO.NE.0) THEN
- CALL XERBLA('DTPSV ',INFO)
- RETURN
- END IF
-*
-* Quick return if possible.
-*
- IF (N.EQ.0) RETURN
-*
- NOUNIT = LSAME(DIAG,'N')
-*
-* Set up the start point in X if the increment is not unity. This
-* will be ( N - 1 )*INCX too small for descending loops.
-*
- IF (INCX.LE.0) THEN
- KX = 1 - (N-1)*INCX
- ELSE IF (INCX.NE.1) THEN
- KX = 1
- END IF
-*
-* Start the operations. In this version the elements of AP are
-* accessed sequentially with one pass through AP.
-*
- IF (LSAME(TRANS,'N')) THEN
-*
-* Form x := inv( A )*x.
-*
- IF (LSAME(UPLO,'U')) THEN
- KK = (N* (N+1))/2
- IF (INCX.EQ.1) THEN
- DO 20 J = N,1,-1
- IF (X(J).NE.ZERO) THEN
- IF (NOUNIT) X(J) = X(J)/AP(KK)
- TEMP = X(J)
- K = KK - 1
- DO 10 I = J - 1,1,-1
- X(I) = X(I) - TEMP*AP(K)
- K = K - 1
- 10 CONTINUE
- END IF
- KK = KK - J
- 20 CONTINUE
- ELSE
- JX = KX + (N-1)*INCX
- DO 40 J = N,1,-1
- IF (X(JX).NE.ZERO) THEN
- IF (NOUNIT) X(JX) = X(JX)/AP(KK)
- TEMP = X(JX)
- IX = JX
- DO 30 K = KK - 1,KK - J + 1,-1
- IX = IX - INCX
- X(IX) = X(IX) - TEMP*AP(K)
- 30 CONTINUE
- END IF
- JX = JX - INCX
- KK = KK - J
- 40 CONTINUE
- END IF
- ELSE
- KK = 1
- IF (INCX.EQ.1) THEN
- DO 60 J = 1,N
- IF (X(J).NE.ZERO) THEN
- IF (NOUNIT) X(J) = X(J)/AP(KK)
- TEMP = X(J)
- K = KK + 1
- DO 50 I = J + 1,N
- X(I) = X(I) - TEMP*AP(K)
- K = K + 1
- 50 CONTINUE
- END IF
- KK = KK + (N-J+1)
- 60 CONTINUE
- ELSE
- JX = KX
- DO 80 J = 1,N
- IF (X(JX).NE.ZERO) THEN
- IF (NOUNIT) X(JX) = X(JX)/AP(KK)
- TEMP = X(JX)
- IX = JX
- DO 70 K = KK + 1,KK + N - J
- IX = IX + INCX
- X(IX) = X(IX) - TEMP*AP(K)
- 70 CONTINUE
- END IF
- JX = JX + INCX
- KK = KK + (N-J+1)
- 80 CONTINUE
- END IF
- END IF
- ELSE
-*
-* Form x := inv( A' )*x.
-*
- IF (LSAME(UPLO,'U')) THEN
- KK = 1
- IF (INCX.EQ.1) THEN
- DO 100 J = 1,N
- TEMP = X(J)
- K = KK
- DO 90 I = 1,J - 1
- TEMP = TEMP - AP(K)*X(I)
- K = K + 1
- 90 CONTINUE
- IF (NOUNIT) TEMP = TEMP/AP(KK+J-1)
- X(J) = TEMP
- KK = KK + J
- 100 CONTINUE
- ELSE
- JX = KX
- DO 120 J = 1,N
- TEMP = X(JX)
- IX = KX
- DO 110 K = KK,KK + J - 2
- TEMP = TEMP - AP(K)*X(IX)
- IX = IX + INCX
- 110 CONTINUE
- IF (NOUNIT) TEMP = TEMP/AP(KK+J-1)
- X(JX) = TEMP
- JX = JX + INCX
- KK = KK + J
- 120 CONTINUE
- END IF
- ELSE
- KK = (N* (N+1))/2
- IF (INCX.EQ.1) THEN
- DO 140 J = N,1,-1
- TEMP = X(J)
- K = KK
- DO 130 I = N,J + 1,-1
- TEMP = TEMP - AP(K)*X(I)
- K = K - 1
- 130 CONTINUE
- IF (NOUNIT) TEMP = TEMP/AP(KK-N+J)
- X(J) = TEMP
- KK = KK - (N-J+1)
- 140 CONTINUE
- ELSE
- KX = KX + (N-1)*INCX
- JX = KX
- DO 160 J = N,1,-1
- TEMP = X(JX)
- IX = KX
- DO 150 K = KK,KK - (N- (J+1)),-1
- TEMP = TEMP - AP(K)*X(IX)
- IX = IX - INCX
- 150 CONTINUE
- IF (NOUNIT) TEMP = TEMP/AP(KK-N+J)
- X(JX) = TEMP
- JX = JX - INCX
- KK = KK - (N-J+1)
- 160 CONTINUE
- END IF
- END IF
- END IF
-*
- RETURN
-*
-* End of DTPSV .
-*
- END
diff --git a/blas/level1_cplx_impl.h b/blas/level1_cplx_impl.h
index 8d6b92829..283b9f827 100644
--- a/blas/level1_cplx_impl.h
+++ b/blas/level1_cplx_impl.h
@@ -12,7 +12,7 @@
struct scalar_norm1_op {
typedef RealScalar result_type;
EIGEN_EMPTY_STRUCT_CTOR(scalar_norm1_op)
- inline RealScalar operator() (const Scalar& a) const { return internal::norm1(a); }
+ inline RealScalar operator() (const Scalar& a) const { return numext::norm1(a); }
};
namespace Eigen {
namespace internal {
diff --git a/blas/level1_impl.h b/blas/level1_impl.h
index 95ea220af..b08c2f6be 100644
--- a/blas/level1_impl.h
+++ b/blas/level1_impl.h
@@ -75,6 +75,9 @@ int EIGEN_CAT(EIGEN_CAT(i,SCALAR_SUFFIX),amin_)(int *n, RealScalar *px, int *inc
int EIGEN_BLAS_FUNC(rotg)(RealScalar *pa, RealScalar *pb, RealScalar *pc, RealScalar *ps)
{
+ using std::sqrt;
+ using std::abs;
+
Scalar& a = *reinterpret_cast<Scalar*>(pa);
Scalar& b = *reinterpret_cast<Scalar*>(pb);
RealScalar* c = pc;
@@ -82,8 +85,8 @@ int EIGEN_BLAS_FUNC(rotg)(RealScalar *pa, RealScalar *pb, RealScalar *pc, RealSc
#if !ISCOMPLEX
Scalar r,z;
- Scalar aa = internal::abs(a);
- Scalar ab = internal::abs(b);
+ Scalar aa = abs(a);
+ Scalar ab = abs(b);
if((aa+ab)==Scalar(0))
{
*c = 1;
@@ -93,7 +96,7 @@ int EIGEN_BLAS_FUNC(rotg)(RealScalar *pa, RealScalar *pb, RealScalar *pc, RealSc
}
else
{
- r = internal::sqrt(a*a + b*b);
+ r = sqrt(a*a + b*b);
Scalar amax = aa>ab ? a : b;
r = amax>0 ? r : -r;
*c = a/r;
@@ -108,7 +111,7 @@ int EIGEN_BLAS_FUNC(rotg)(RealScalar *pa, RealScalar *pb, RealScalar *pc, RealSc
#else
Scalar alpha;
RealScalar norm,scale;
- if(internal::abs(a)==RealScalar(0))
+ if(abs(a)==RealScalar(0))
{
*c = RealScalar(0);
*s = Scalar(1);
@@ -116,11 +119,11 @@ int EIGEN_BLAS_FUNC(rotg)(RealScalar *pa, RealScalar *pb, RealScalar *pc, RealSc
}
else
{
- scale = internal::abs(a) + internal::abs(b);
- norm = scale*internal::sqrt((internal::abs2(a/scale))+ (internal::abs2(b/scale)));
- alpha = a/internal::abs(a);
- *c = internal::abs(a)/norm;
- *s = alpha*internal::conj(b)/norm;
+ scale = abs(a) + abs(b);
+ norm = scale*sqrt((numext::abs2(a/scale)) + (numext::abs2(b/scale)));
+ alpha = a/abs(a);
+ *c = abs(a)/norm;
+ *s = alpha*numext::conj(b)/norm;
a = alpha*norm;
}
#endif
diff --git a/blas/level2_cplx_impl.h b/blas/level2_cplx_impl.h
index 7878f2a16..b850b6cd1 100644
--- a/blas/level2_cplx_impl.h
+++ b/blas/level2_cplx_impl.h
@@ -18,6 +18,21 @@
*/
int EIGEN_BLAS_FUNC(hemv)(char *uplo, int *n, RealScalar *palpha, RealScalar *pa, int *lda, RealScalar *px, int *incx, RealScalar *pbeta, RealScalar *py, int *incy)
{
+ typedef void (*functype)(int, const Scalar*, int, const Scalar*, int, Scalar*, Scalar);
+ static functype func[2];
+
+ static bool init = false;
+ if(!init)
+ {
+ for(int k=0; k<2; ++k)
+ func[k] = 0;
+
+ func[UP] = (internal::selfadjoint_matrix_vector_product<Scalar,int,ColMajor,Upper,false,false>::run);
+ func[LO] = (internal::selfadjoint_matrix_vector_product<Scalar,int,ColMajor,Lower,false,false>::run);
+
+ init = true;
+ }
+
Scalar* a = reinterpret_cast<Scalar*>(pa);
Scalar* x = reinterpret_cast<Scalar*>(px);
Scalar* y = reinterpret_cast<Scalar*>(py);
@@ -48,9 +63,11 @@ int EIGEN_BLAS_FUNC(hemv)(char *uplo, int *n, RealScalar *palpha, RealScalar *pa
if(alpha!=Scalar(0))
{
- // TODO performs a direct call to the underlying implementation function
- if(UPLO(*uplo)==UP) vector(actual_y,*n).noalias() += matrix(a,*n,*n,*lda).selfadjointView<Upper>() * (alpha * vector(actual_x,*n));
- else if(UPLO(*uplo)==LO) vector(actual_y,*n).noalias() += matrix(a,*n,*n,*lda).selfadjointView<Lower>() * (alpha * vector(actual_x,*n));
+ int code = UPLO(*uplo);
+ if(code>=2 || func[code]==0)
+ return 0;
+
+ func[code](*n, a, *lda, actual_x, 1, actual_y, alpha);
}
if(actual_x!=x) delete[] actual_x;
@@ -91,10 +108,49 @@ int EIGEN_BLAS_FUNC(hemv)(char *uplo, int *n, RealScalar *palpha, RealScalar *pa
* where alpha is a real scalar, x is an n element vector and A is an
* n by n hermitian matrix, supplied in packed form.
*/
-// int EIGEN_BLAS_FUNC(hpr)(char *uplo, int *n, RealScalar *alpha, RealScalar *x, int *incx, RealScalar *ap)
-// {
-// return 1;
-// }
+int EIGEN_BLAS_FUNC(hpr)(char *uplo, int *n, RealScalar *palpha, RealScalar *px, int *incx, RealScalar *pap)
+{
+ typedef void (*functype)(int, Scalar*, const Scalar*, RealScalar);
+ static functype func[2];
+
+ static bool init = false;
+ if(!init)
+ {
+ for(int k=0; k<2; ++k)
+ func[k] = 0;
+
+ func[UP] = (internal::selfadjoint_packed_rank1_update<Scalar,int,ColMajor,Upper,false,Conj>::run);
+ func[LO] = (internal::selfadjoint_packed_rank1_update<Scalar,int,ColMajor,Lower,false,Conj>::run);
+
+ init = true;
+ }
+
+ Scalar* x = reinterpret_cast<Scalar*>(px);
+ Scalar* ap = reinterpret_cast<Scalar*>(pap);
+ RealScalar alpha = *palpha;
+
+ int info = 0;
+ if(UPLO(*uplo)==INVALID) info = 1;
+ else if(*n<0) info = 2;
+ else if(*incx==0) info = 5;
+ if(info)
+ return xerbla_(SCALAR_SUFFIX_UP"HPR ",&info,6);
+
+ if(alpha==Scalar(0))
+ return 1;
+
+ Scalar* x_cpy = get_compact_vector(x, *n, *incx);
+
+ int code = UPLO(*uplo);
+ if(code>=2 || func[code]==0)
+ return 0;
+
+ func[code](*n, ap, x_cpy, alpha);
+
+ if(x_cpy!=x) delete[] x_cpy;
+
+ return 1;
+}
/** ZHPR2 performs the hermitian rank 2 operation
*
@@ -103,10 +159,53 @@ int EIGEN_BLAS_FUNC(hemv)(char *uplo, int *n, RealScalar *palpha, RealScalar *pa
* where alpha is a scalar, x and y are n element vectors and A is an
* n by n hermitian matrix, supplied in packed form.
*/
-// int EIGEN_BLAS_FUNC(hpr2)(char *uplo, int *n, RealScalar *palpha, RealScalar *x, int *incx, RealScalar *y, int *incy, RealScalar *ap)
-// {
-// return 1;
-// }
+int EIGEN_BLAS_FUNC(hpr2)(char *uplo, int *n, RealScalar *palpha, RealScalar *px, int *incx, RealScalar *py, int *incy, RealScalar *pap)
+{
+ typedef void (*functype)(int, Scalar*, const Scalar*, const Scalar*, Scalar);
+ static functype func[2];
+
+ static bool init = false;
+ if(!init)
+ {
+ for(int k=0; k<2; ++k)
+ func[k] = 0;
+
+ func[UP] = (internal::packed_rank2_update_selector<Scalar,int,Upper>::run);
+ func[LO] = (internal::packed_rank2_update_selector<Scalar,int,Lower>::run);
+
+ init = true;
+ }
+
+ Scalar* x = reinterpret_cast<Scalar*>(px);
+ Scalar* y = reinterpret_cast<Scalar*>(py);
+ Scalar* ap = reinterpret_cast<Scalar*>(pap);
+ Scalar alpha = *reinterpret_cast<Scalar*>(palpha);
+
+ int info = 0;
+ if(UPLO(*uplo)==INVALID) info = 1;
+ else if(*n<0) info = 2;
+ else if(*incx==0) info = 5;
+ else if(*incy==0) info = 7;
+ if(info)
+ return xerbla_(SCALAR_SUFFIX_UP"HPR2 ",&info,6);
+
+ if(alpha==Scalar(0))
+ return 1;
+
+ Scalar* x_cpy = get_compact_vector(x, *n, *incx);
+ Scalar* y_cpy = get_compact_vector(y, *n, *incy);
+
+ int code = UPLO(*uplo);
+ if(code>=2 || func[code]==0)
+ return 0;
+
+ func[code](*n, ap, x_cpy, y_cpy, alpha);
+
+ if(x_cpy!=x) delete[] x_cpy;
+ if(y_cpy!=y) delete[] y_cpy;
+
+ return 1;
+}
/** ZHER performs the hermitian rank 1 operation
*
@@ -117,6 +216,21 @@ int EIGEN_BLAS_FUNC(hemv)(char *uplo, int *n, RealScalar *palpha, RealScalar *pa
*/
int EIGEN_BLAS_FUNC(her)(char *uplo, int *n, RealScalar *palpha, RealScalar *px, int *incx, RealScalar *pa, int *lda)
{
+ typedef void (*functype)(int, Scalar*, int, const Scalar*, const Scalar*, const Scalar&);
+ static functype func[2];
+
+ static bool init = false;
+ if(!init)
+ {
+ for(int k=0; k<2; ++k)
+ func[k] = 0;
+
+ func[UP] = (selfadjoint_rank1_update<Scalar,int,ColMajor,Upper,false,Conj>::run);
+ func[LO] = (selfadjoint_rank1_update<Scalar,int,ColMajor,Lower,false,Conj>::run);
+
+ init = true;
+ }
+
Scalar* x = reinterpret_cast<Scalar*>(px);
Scalar* a = reinterpret_cast<Scalar*>(pa);
RealScalar alpha = *reinterpret_cast<RealScalar*>(palpha);
@@ -134,16 +248,11 @@ int EIGEN_BLAS_FUNC(her)(char *uplo, int *n, RealScalar *palpha, RealScalar *px,
Scalar* x_cpy = get_compact_vector(x, *n, *incx);
- // TODO perform direct calls to underlying implementation
-// if(UPLO(*uplo)==LO) matrix(a,*n,*n,*lda).selfadjointView<Lower>().rankUpdate(vector(x_cpy,*n), alpha);
-// else if(UPLO(*uplo)==UP) matrix(a,*n,*n,*lda).selfadjointView<Upper>().rankUpdate(vector(x_cpy,*n), alpha);
+ int code = UPLO(*uplo);
+ if(code>=2 || func[code]==0)
+ return 0;
- if(UPLO(*uplo)==LO)
- for(int j=0;j<*n;++j)
- matrix(a,*n,*n,*lda).col(j).tail(*n-j) += alpha * internal::conj(x_cpy[j]) * vector(x_cpy+j,*n-j);
- else
- for(int j=0;j<*n;++j)
- matrix(a,*n,*n,*lda).col(j).head(j+1) += alpha * internal::conj(x_cpy[j]) * vector(x_cpy,j+1);
+ func[code](*n, a, *lda, x_cpy, x_cpy, alpha);
matrix(a,*n,*n,*lda).diagonal().imag().setZero();
@@ -161,6 +270,21 @@ int EIGEN_BLAS_FUNC(her)(char *uplo, int *n, RealScalar *palpha, RealScalar *px,
*/
int EIGEN_BLAS_FUNC(her2)(char *uplo, int *n, RealScalar *palpha, RealScalar *px, int *incx, RealScalar *py, int *incy, RealScalar *pa, int *lda)
{
+ typedef void (*functype)(int, Scalar*, int, const Scalar*, const Scalar*, Scalar);
+ static functype func[2];
+
+ static bool init = false;
+ if(!init)
+ {
+ for(int k=0; k<2; ++k)
+ func[k] = 0;
+
+ func[UP] = (internal::rank2_update_selector<Scalar,int,Upper>::run);
+ func[LO] = (internal::rank2_update_selector<Scalar,int,Lower>::run);
+
+ init = true;
+ }
+
Scalar* x = reinterpret_cast<Scalar*>(px);
Scalar* y = reinterpret_cast<Scalar*>(py);
Scalar* a = reinterpret_cast<Scalar*>(pa);
@@ -181,9 +305,11 @@ int EIGEN_BLAS_FUNC(her2)(char *uplo, int *n, RealScalar *palpha, RealScalar *px
Scalar* x_cpy = get_compact_vector(x, *n, *incx);
Scalar* y_cpy = get_compact_vector(y, *n, *incy);
- // TODO perform direct calls to underlying implementation
- if(UPLO(*uplo)==LO) matrix(a,*n,*n,*lda).selfadjointView<Lower>().rankUpdate(vector(x_cpy,*n),vector(y_cpy,*n),alpha);
- else if(UPLO(*uplo)==UP) matrix(a,*n,*n,*lda).selfadjointView<Upper>().rankUpdate(vector(x_cpy,*n),vector(y_cpy,*n),alpha);
+ int code = UPLO(*uplo);
+ if(code>=2 || func[code]==0)
+ return 0;
+
+ func[code](*n, a, *lda, x_cpy, y_cpy, alpha);
matrix(a,*n,*n,*lda).diagonal().imag().setZero();
@@ -222,8 +348,7 @@ int EIGEN_BLAS_FUNC(geru)(int *m, int *n, RealScalar *palpha, RealScalar *px, in
Scalar* x_cpy = get_compact_vector(x,*m,*incx);
Scalar* y_cpy = get_compact_vector(y,*n,*incy);
- // TODO perform direct calls to underlying implementation
- matrix(a,*m,*n,*lda) += alpha * vector(x_cpy,*m) * vector(y_cpy,*n).transpose();
+ internal::general_rank1_update<Scalar,int,ColMajor,false,false>::run(*m, *n, a, *lda, x_cpy, y_cpy, alpha);
if(x_cpy!=x) delete[] x_cpy;
if(y_cpy!=y) delete[] y_cpy;
@@ -260,8 +385,7 @@ int EIGEN_BLAS_FUNC(gerc)(int *m, int *n, RealScalar *palpha, RealScalar *px, in
Scalar* x_cpy = get_compact_vector(x,*m,*incx);
Scalar* y_cpy = get_compact_vector(y,*n,*incy);
- // TODO perform direct calls to underlying implementation
- matrix(a,*m,*n,*lda) += alpha * vector(x_cpy,*m) * vector(y_cpy,*n).adjoint();
+ internal::general_rank1_update<Scalar,int,ColMajor,false,Conj>::run(*m, *n, a, *lda, x_cpy, y_cpy, alpha);
if(x_cpy!=x) delete[] x_cpy;
if(y_cpy!=y) delete[] y_cpy;
diff --git a/blas/level2_impl.h b/blas/level2_impl.h
index 7099cf96d..5f3941975 100644
--- a/blas/level2_impl.h
+++ b/blas/level2_impl.h
@@ -49,7 +49,8 @@ int EIGEN_BLAS_FUNC(gemv)(char *opa, int *m, int *n, RealScalar *palpha, RealSca
int actual_m = *m;
int actual_n = *n;
- if(OP(*opa)!=NOTR)
+ int code = OP(*opa);
+ if(code!=NOTR)
std::swap(actual_m,actual_n);
Scalar* actual_b = get_compact_vector(b,actual_n,*incb);
@@ -61,7 +62,9 @@ int EIGEN_BLAS_FUNC(gemv)(char *opa, int *m, int *n, RealScalar *palpha, RealSca
else vector(actual_c, actual_m) *= beta;
}
- int code = OP(*opa);
+ if(code>=4 || func[code]==0)
+ return 0;
+
func[code](actual_m, actual_n, a, *lda, actual_b, 1, actual_c, 1, alpha);
if(actual_b!=b) delete[] actual_b;
@@ -127,7 +130,7 @@ int EIGEN_BLAS_FUNC(trsv)(char *uplo, char *opa, char *diag, int *n, RealScalar
int EIGEN_BLAS_FUNC(trmv)(char *uplo, char *opa, char *diag, int *n, RealScalar *pa, int *lda, RealScalar *pb, int *incb)
{
- typedef void (*functype)(int, int, const Scalar *, int, const Scalar *, int, Scalar *, int, Scalar);
+ typedef void (*functype)(int, int, const Scalar *, int, const Scalar *, int, Scalar *, int, const Scalar&);
static functype func[16];
static bool init = false;
@@ -184,7 +187,7 @@ int EIGEN_BLAS_FUNC(trmv)(char *uplo, char *opa, char *diag, int *n, RealScalar
copy_back(res.data(),b,*n,*incb);
if(actual_b!=b) delete[] actual_b;
- return 0;
+ return 1;
}
/** GBMV performs one of the matrix-vector operations
@@ -396,10 +399,66 @@ int EIGEN_BLAS_FUNC(tbsv)(char *uplo, char *op, char *diag, int *n, int *k, Real
* where x is an n element vector and A is an n by n unit, or non-unit,
* upper or lower triangular matrix, supplied in packed form.
*/
-// int EIGEN_BLAS_FUNC(tpmv)(char *uplo, char *trans, char *diag, int *n, RealScalar *ap, RealScalar *x, int *incx)
-// {
-// return 1;
-// }
+int EIGEN_BLAS_FUNC(tpmv)(char *uplo, char *opa, char *diag, int *n, RealScalar *pap, RealScalar *px, int *incx)
+{
+ typedef void (*functype)(int, const Scalar*, const Scalar*, Scalar*, Scalar);
+ static functype func[16];
+
+ static bool init = false;
+ if(!init)
+ {
+ for(int k=0; k<16; ++k)
+ func[k] = 0;
+
+ func[NOTR | (UP << 2) | (NUNIT << 3)] = (internal::packed_triangular_matrix_vector_product<int,Upper|0, Scalar,false,Scalar,false,ColMajor>::run);
+ func[TR | (UP << 2) | (NUNIT << 3)] = (internal::packed_triangular_matrix_vector_product<int,Lower|0, Scalar,false,Scalar,false,RowMajor>::run);
+ func[ADJ | (UP << 2) | (NUNIT << 3)] = (internal::packed_triangular_matrix_vector_product<int,Lower|0, Scalar,Conj, Scalar,false,RowMajor>::run);
+
+ func[NOTR | (LO << 2) | (NUNIT << 3)] = (internal::packed_triangular_matrix_vector_product<int,Lower|0, Scalar,false,Scalar,false,ColMajor>::run);
+ func[TR | (LO << 2) | (NUNIT << 3)] = (internal::packed_triangular_matrix_vector_product<int,Upper|0, Scalar,false,Scalar,false,RowMajor>::run);
+ func[ADJ | (LO << 2) | (NUNIT << 3)] = (internal::packed_triangular_matrix_vector_product<int,Upper|0, Scalar,Conj, Scalar,false,RowMajor>::run);
+
+ func[NOTR | (UP << 2) | (UNIT << 3)] = (internal::packed_triangular_matrix_vector_product<int,Upper|UnitDiag,Scalar,false,Scalar,false,ColMajor>::run);
+ func[TR | (UP << 2) | (UNIT << 3)] = (internal::packed_triangular_matrix_vector_product<int,Lower|UnitDiag,Scalar,false,Scalar,false,RowMajor>::run);
+ func[ADJ | (UP << 2) | (UNIT << 3)] = (internal::packed_triangular_matrix_vector_product<int,Lower|UnitDiag,Scalar,Conj, Scalar,false,RowMajor>::run);
+
+ func[NOTR | (LO << 2) | (UNIT << 3)] = (internal::packed_triangular_matrix_vector_product<int,Lower|UnitDiag,Scalar,false,Scalar,false,ColMajor>::run);
+ func[TR | (LO << 2) | (UNIT << 3)] = (internal::packed_triangular_matrix_vector_product<int,Upper|UnitDiag,Scalar,false,Scalar,false,RowMajor>::run);
+ func[ADJ | (LO << 2) | (UNIT << 3)] = (internal::packed_triangular_matrix_vector_product<int,Upper|UnitDiag,Scalar,Conj, Scalar,false,RowMajor>::run);
+
+ init = true;
+ }
+
+ Scalar* ap = reinterpret_cast<Scalar*>(pap);
+ Scalar* x = reinterpret_cast<Scalar*>(px);
+
+ int info = 0;
+ if(UPLO(*uplo)==INVALID) info = 1;
+ else if(OP(*opa)==INVALID) info = 2;
+ else if(DIAG(*diag)==INVALID) info = 3;
+ else if(*n<0) info = 4;
+ else if(*incx==0) info = 7;
+ if(info)
+ return xerbla_(SCALAR_SUFFIX_UP"TPMV ",&info,6);
+
+ if(*n==0)
+ return 1;
+
+ Scalar* actual_x = get_compact_vector(x,*n,*incx);
+ Matrix<Scalar,Dynamic,1> res(*n);
+ res.setZero();
+
+ int code = OP(*opa) | (UPLO(*uplo) << 2) | (DIAG(*diag) << 3);
+ if(code>=16 || func[code]==0)
+ return 0;
+
+ func[code](*n, ap, actual_x, res.data(), Scalar(1));
+
+ copy_back(res.data(),x,*n,*incx);
+ if(actual_x!=x) delete[] actual_x;
+
+ return 1;
+}
/** DTPSV solves one of the systems of equations
*
@@ -411,47 +470,55 @@ int EIGEN_BLAS_FUNC(tbsv)(char *uplo, char *op, char *diag, int *n, int *k, Real
* No test for singularity or near-singularity is included in this
* routine. Such tests must be performed before calling this routine.
*/
-// int EIGEN_BLAS_FUNC(tpsv)(char *uplo, char *trans, char *diag, int *n, RealScalar *ap, RealScalar *x, int *incx)
-// {
-// return 1;
-// }
-
-/** DGER performs the rank 1 operation
- *
- * A := alpha*x*y' + A,
- *
- * where alpha is a scalar, x is an m element vector, y is an n element
- * vector and A is an m by n matrix.
- */
-int EIGEN_BLAS_FUNC(ger)(int *m, int *n, Scalar *palpha, Scalar *px, int *incx, Scalar *py, int *incy, Scalar *pa, int *lda)
+int EIGEN_BLAS_FUNC(tpsv)(char *uplo, char *opa, char *diag, int *n, RealScalar *pap, RealScalar *px, int *incx)
{
+ typedef void (*functype)(int, const Scalar*, Scalar*);
+ static functype func[16];
+
+ static bool init = false;
+ if(!init)
+ {
+ for(int k=0; k<16; ++k)
+ func[k] = 0;
+
+ func[NOTR | (UP << 2) | (NUNIT << 3)] = (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|0, false,ColMajor>::run);
+ func[TR | (UP << 2) | (NUNIT << 3)] = (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|0, false,RowMajor>::run);
+ func[ADJ | (UP << 2) | (NUNIT << 3)] = (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|0, Conj, RowMajor>::run);
+
+ func[NOTR | (LO << 2) | (NUNIT << 3)] = (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|0, false,ColMajor>::run);
+ func[TR | (LO << 2) | (NUNIT << 3)] = (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|0, false,RowMajor>::run);
+ func[ADJ | (LO << 2) | (NUNIT << 3)] = (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|0, Conj, RowMajor>::run);
+
+ func[NOTR | (UP << 2) | (UNIT << 3)] = (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|UnitDiag,false,ColMajor>::run);
+ func[TR | (UP << 2) | (UNIT << 3)] = (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|UnitDiag,false,RowMajor>::run);
+ func[ADJ | (UP << 2) | (UNIT << 3)] = (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|UnitDiag,Conj, RowMajor>::run);
+
+ func[NOTR | (LO << 2) | (UNIT << 3)] = (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|UnitDiag,false,ColMajor>::run);
+ func[TR | (LO << 2) | (UNIT << 3)] = (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|UnitDiag,false,RowMajor>::run);
+ func[ADJ | (LO << 2) | (UNIT << 3)] = (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|UnitDiag,Conj, RowMajor>::run);
+
+ init = true;
+ }
+
+ Scalar* ap = reinterpret_cast<Scalar*>(pap);
Scalar* x = reinterpret_cast<Scalar*>(px);
- Scalar* y = reinterpret_cast<Scalar*>(py);
- Scalar* a = reinterpret_cast<Scalar*>(pa);
- Scalar alpha = *reinterpret_cast<Scalar*>(palpha);
int info = 0;
- if(*m<0) info = 1;
- else if(*n<0) info = 2;
- else if(*incx==0) info = 5;
- else if(*incy==0) info = 7;
- else if(*lda<std::max(1,*m)) info = 9;
+ if(UPLO(*uplo)==INVALID) info = 1;
+ else if(OP(*opa)==INVALID) info = 2;
+ else if(DIAG(*diag)==INVALID) info = 3;
+ else if(*n<0) info = 4;
+ else if(*incx==0) info = 7;
if(info)
- return xerbla_(SCALAR_SUFFIX_UP"GER ",&info,6);
+ return xerbla_(SCALAR_SUFFIX_UP"TPSV ",&info,6);
- if(alpha==Scalar(0))
- return 1;
-
- Scalar* x_cpy = get_compact_vector(x,*m,*incx);
- Scalar* y_cpy = get_compact_vector(y,*n,*incy);
+ Scalar* actual_x = get_compact_vector(x,*n,*incx);
- // TODO perform direct calls to underlying implementation
- matrix(a,*m,*n,*lda) += alpha * vector(x_cpy,*m) * vector(y_cpy,*n).adjoint();
+ int code = OP(*opa) | (UPLO(*uplo) << 2) | (DIAG(*diag) << 3);
+ func[code](*n, ap, actual_x);
- if(x_cpy!=x) delete[] x_cpy;
- if(y_cpy!=y) delete[] y_cpy;
+ if(actual_x!=x) delete[] copy_back(actual_x,x,*n,*incx);
return 1;
}
-
diff --git a/blas/level2_real_impl.h b/blas/level2_real_impl.h
index cd8332973..8d56eaaa1 100644
--- a/blas/level2_real_impl.h
+++ b/blas/level2_real_impl.h
@@ -12,6 +12,21 @@
// y = alpha*A*x + beta*y
int EIGEN_BLAS_FUNC(symv) (char *uplo, int *n, RealScalar *palpha, RealScalar *pa, int *lda, RealScalar *px, int *incx, RealScalar *pbeta, RealScalar *py, int *incy)
{
+ typedef void (*functype)(int, const Scalar*, int, const Scalar*, int, Scalar*, Scalar);
+ static functype func[2];
+
+ static bool init = false;
+ if(!init)
+ {
+ for(int k=0; k<2; ++k)
+ func[k] = 0;
+
+ func[UP] = (internal::selfadjoint_matrix_vector_product<Scalar,int,ColMajor,Upper,false,false>::run);
+ func[LO] = (internal::selfadjoint_matrix_vector_product<Scalar,int,ColMajor,Lower,false,false>::run);
+
+ init = true;
+ }
+
Scalar* a = reinterpret_cast<Scalar*>(pa);
Scalar* x = reinterpret_cast<Scalar*>(px);
Scalar* y = reinterpret_cast<Scalar*>(py);
@@ -40,9 +55,11 @@ int EIGEN_BLAS_FUNC(symv) (char *uplo, int *n, RealScalar *palpha, RealScalar *p
else vector(actual_y, *n) *= beta;
}
- // TODO performs a direct call to the underlying implementation function
- if(UPLO(*uplo)==UP) vector(actual_y,*n).noalias() += matrix(a,*n,*n,*lda).selfadjointView<Upper>() * (alpha * vector(actual_x,*n));
- else if(UPLO(*uplo)==LO) vector(actual_y,*n).noalias() += matrix(a,*n,*n,*lda).selfadjointView<Lower>() * (alpha * vector(actual_x,*n));
+ int code = UPLO(*uplo);
+ if(code>=2 || func[code]==0)
+ return 0;
+
+ func[code](*n, a, *lda, actual_x, 1, actual_y, alpha);
if(actual_x!=x) delete[] actual_x;
if(actual_y!=y) delete[] copy_back(actual_y,y,*n,*incy);
@@ -68,6 +85,20 @@ int EIGEN_BLAS_FUNC(syr)(char *uplo, int *n, RealScalar *palpha, RealScalar *px,
// init = true;
// }
+ typedef void (*functype)(int, Scalar*, int, const Scalar*, const Scalar*, const Scalar&);
+ static functype func[2];
+
+ static bool init = false;
+ if(!init)
+ {
+ for(int k=0; k<2; ++k)
+ func[k] = 0;
+
+ func[UP] = (selfadjoint_rank1_update<Scalar,int,ColMajor,Upper,false,Conj>::run);
+ func[LO] = (selfadjoint_rank1_update<Scalar,int,ColMajor,Lower,false,Conj>::run);
+
+ init = true;
+ }
Scalar* x = reinterpret_cast<Scalar*>(px);
Scalar* c = reinterpret_cast<Scalar*>(pc);
@@ -86,18 +117,11 @@ int EIGEN_BLAS_FUNC(syr)(char *uplo, int *n, RealScalar *palpha, RealScalar *px,
// if the increment is not 1, let's copy it to a temporary vector to enable vectorization
Scalar* x_cpy = get_compact_vector(x,*n,*incx);
- Matrix<Scalar,Dynamic,Dynamic> m2(matrix(c,*n,*n,*ldc));
-
- // TODO check why this is not accurate enough for lapack tests
-// if(UPLO(*uplo)==LO) matrix(c,*n,*n,*ldc).selfadjointView<Lower>().rankUpdate(vector(x_cpy,*n), alpha);
-// else if(UPLO(*uplo)==UP) matrix(c,*n,*n,*ldc).selfadjointView<Upper>().rankUpdate(vector(x_cpy,*n), alpha);
+ int code = UPLO(*uplo);
+ if(code>=2 || func[code]==0)
+ return 0;
- if(UPLO(*uplo)==LO)
- for(int j=0;j<*n;++j)
- matrix(c,*n,*n,*ldc).col(j).tail(*n-j) += alpha * x_cpy[j] * vector(x_cpy+j,*n-j);
- else
- for(int j=0;j<*n;++j)
- matrix(c,*n,*n,*ldc).col(j).head(j+1) += alpha * x_cpy[j] * vector(x_cpy,j+1);
+ func[code](*n, c, *ldc, x_cpy, x_cpy, alpha);
if(x_cpy!=x) delete[] x_cpy;
@@ -121,6 +145,20 @@ int EIGEN_BLAS_FUNC(syr2)(char *uplo, int *n, RealScalar *palpha, RealScalar *px
//
// init = true;
// }
+ typedef void (*functype)(int, Scalar*, int, const Scalar*, const Scalar*, Scalar);
+ static functype func[2];
+
+ static bool init = false;
+ if(!init)
+ {
+ for(int k=0; k<2; ++k)
+ func[k] = 0;
+
+ func[UP] = (internal::rank2_update_selector<Scalar,int,Upper>::run);
+ func[LO] = (internal::rank2_update_selector<Scalar,int,Lower>::run);
+
+ init = true;
+ }
Scalar* x = reinterpret_cast<Scalar*>(px);
Scalar* y = reinterpret_cast<Scalar*>(py);
@@ -141,10 +179,12 @@ int EIGEN_BLAS_FUNC(syr2)(char *uplo, int *n, RealScalar *palpha, RealScalar *px
Scalar* x_cpy = get_compact_vector(x,*n,*incx);
Scalar* y_cpy = get_compact_vector(y,*n,*incy);
+
+ int code = UPLO(*uplo);
+ if(code>=2 || func[code]==0)
+ return 0;
- // TODO perform direct calls to underlying implementation
- if(UPLO(*uplo)==LO) matrix(c,*n,*n,*ldc).selfadjointView<Lower>().rankUpdate(vector(x_cpy,*n), vector(y_cpy,*n), alpha);
- else if(UPLO(*uplo)==UP) matrix(c,*n,*n,*ldc).selfadjointView<Upper>().rankUpdate(vector(x_cpy,*n), vector(y_cpy,*n), alpha);
+ func[code](*n, c, *ldc, x_cpy, y_cpy, alpha);
if(x_cpy!=x) delete[] x_cpy;
if(y_cpy!=y) delete[] y_cpy;
@@ -191,10 +231,49 @@ int EIGEN_BLAS_FUNC(syr2)(char *uplo, int *n, RealScalar *palpha, RealScalar *px
* where alpha is a real scalar, x is an n element vector and A is an
* n by n symmetric matrix, supplied in packed form.
*/
-// int EIGEN_BLAS_FUNC(spr)(char *uplo, int *n, Scalar *alpha, Scalar *x, int *incx, Scalar *ap)
-// {
-// return 1;
-// }
+int EIGEN_BLAS_FUNC(spr)(char *uplo, int *n, Scalar *palpha, Scalar *px, int *incx, Scalar *pap)
+{
+ typedef void (*functype)(int, Scalar*, const Scalar*, Scalar);
+ static functype func[2];
+
+ static bool init = false;
+ if(!init)
+ {
+ for(int k=0; k<2; ++k)
+ func[k] = 0;
+
+ func[UP] = (internal::selfadjoint_packed_rank1_update<Scalar,int,ColMajor,Upper,false,false>::run);
+ func[LO] = (internal::selfadjoint_packed_rank1_update<Scalar,int,ColMajor,Lower,false,false>::run);
+
+ init = true;
+ }
+
+ Scalar* x = reinterpret_cast<Scalar*>(px);
+ Scalar* ap = reinterpret_cast<Scalar*>(pap);
+ Scalar alpha = *reinterpret_cast<Scalar*>(palpha);
+
+ int info = 0;
+ if(UPLO(*uplo)==INVALID) info = 1;
+ else if(*n<0) info = 2;
+ else if(*incx==0) info = 5;
+ if(info)
+ return xerbla_(SCALAR_SUFFIX_UP"SPR ",&info,6);
+
+ if(alpha==Scalar(0))
+ return 1;
+
+ Scalar* x_cpy = get_compact_vector(x, *n, *incx);
+
+ int code = UPLO(*uplo);
+ if(code>=2 || func[code]==0)
+ return 0;
+
+ func[code](*n, ap, x_cpy, alpha);
+
+ if(x_cpy!=x) delete[] x_cpy;
+
+ return 1;
+}
/** DSPR2 performs the symmetric rank 2 operation
*
@@ -203,8 +282,89 @@ int EIGEN_BLAS_FUNC(syr2)(char *uplo, int *n, RealScalar *palpha, RealScalar *px
* where alpha is a scalar, x and y are n element vectors and A is an
* n by n symmetric matrix, supplied in packed form.
*/
-// int EIGEN_BLAS_FUNC(spr2)(char *uplo, int *n, RealScalar *alpha, RealScalar *x, int *incx, RealScalar *y, int *incy, RealScalar *ap)
-// {
-// return 1;
-// }
+int EIGEN_BLAS_FUNC(spr2)(char *uplo, int *n, RealScalar *palpha, RealScalar *px, int *incx, RealScalar *py, int *incy, RealScalar *pap)
+{
+ typedef void (*functype)(int, Scalar*, const Scalar*, const Scalar*, Scalar);
+ static functype func[2];
+
+ static bool init = false;
+ if(!init)
+ {
+ for(int k=0; k<2; ++k)
+ func[k] = 0;
+
+ func[UP] = (internal::packed_rank2_update_selector<Scalar,int,Upper>::run);
+ func[LO] = (internal::packed_rank2_update_selector<Scalar,int,Lower>::run);
+
+ init = true;
+ }
+
+ Scalar* x = reinterpret_cast<Scalar*>(px);
+ Scalar* y = reinterpret_cast<Scalar*>(py);
+ Scalar* ap = reinterpret_cast<Scalar*>(pap);
+ Scalar alpha = *reinterpret_cast<Scalar*>(palpha);
+
+ int info = 0;
+ if(UPLO(*uplo)==INVALID) info = 1;
+ else if(*n<0) info = 2;
+ else if(*incx==0) info = 5;
+ else if(*incy==0) info = 7;
+ if(info)
+ return xerbla_(SCALAR_SUFFIX_UP"SPR2 ",&info,6);
+
+ if(alpha==Scalar(0))
+ return 1;
+
+ Scalar* x_cpy = get_compact_vector(x, *n, *incx);
+ Scalar* y_cpy = get_compact_vector(y, *n, *incy);
+
+ int code = UPLO(*uplo);
+ if(code>=2 || func[code]==0)
+ return 0;
+
+ func[code](*n, ap, x_cpy, y_cpy, alpha);
+
+ if(x_cpy!=x) delete[] x_cpy;
+ if(y_cpy!=y) delete[] y_cpy;
+
+ return 1;
+}
+
+/** DGER performs the rank 1 operation
+ *
+ * A := alpha*x*y' + A,
+ *
+ * where alpha is a scalar, x is an m element vector, y is an n element
+ * vector and A is an m by n matrix.
+ */
+int EIGEN_BLAS_FUNC(ger)(int *m, int *n, Scalar *palpha, Scalar *px, int *incx, Scalar *py, int *incy, Scalar *pa, int *lda)
+{
+ Scalar* x = reinterpret_cast<Scalar*>(px);
+ Scalar* y = reinterpret_cast<Scalar*>(py);
+ Scalar* a = reinterpret_cast<Scalar*>(pa);
+ Scalar alpha = *reinterpret_cast<Scalar*>(palpha);
+
+ int info = 0;
+ if(*m<0) info = 1;
+ else if(*n<0) info = 2;
+ else if(*incx==0) info = 5;
+ else if(*incy==0) info = 7;
+ else if(*lda<std::max(1,*m)) info = 9;
+ if(info)
+ return xerbla_(SCALAR_SUFFIX_UP"GER ",&info,6);
+
+ if(alpha==Scalar(0))
+ return 1;
+
+ Scalar* x_cpy = get_compact_vector(x,*m,*incx);
+ Scalar* y_cpy = get_compact_vector(y,*n,*incy);
+
+ internal::general_rank1_update<Scalar,int,ColMajor,false,false>::run(*m, *n, a, *lda, x_cpy, y_cpy, alpha);
+
+ if(x_cpy!=x) delete[] x_cpy;
+ if(y_cpy!=y) delete[] y_cpy;
+
+ return 1;
+}
+
diff --git a/blas/level3_impl.h b/blas/level3_impl.h
index 2371f25c3..07dbc22ff 100644
--- a/blas/level3_impl.h
+++ b/blas/level3_impl.h
@@ -152,7 +152,7 @@ int EIGEN_BLAS_FUNC(trsm)(char *side, char *uplo, char *opa, char *diag, int *m,
int EIGEN_BLAS_FUNC(trmm)(char *side, char *uplo, char *opa, char *diag, int *m, int *n, RealScalar *palpha, RealScalar *pa, int *lda, RealScalar *pb, int *ldb)
{
// std::cerr << "in trmm " << *side << " " << *uplo << " " << *opa << " " << *diag << " " << *m << " " << *n << " " << *lda << " " << *ldb << " " << *palpha << "\n";
- typedef void (*functype)(DenseIndex, DenseIndex, DenseIndex, const Scalar *, DenseIndex, const Scalar *, DenseIndex, Scalar *, DenseIndex, Scalar, internal::level3_blocking<Scalar,Scalar>&);
+ typedef void (*functype)(DenseIndex, DenseIndex, DenseIndex, const Scalar *, DenseIndex, const Scalar *, DenseIndex, Scalar *, DenseIndex, const Scalar&, internal::level3_blocking<Scalar,Scalar>&);
static functype func[32];
static bool init = false;
if(!init)
@@ -305,7 +305,8 @@ int EIGEN_BLAS_FUNC(symm)(char *side, char *uplo, int *m, int *n, RealScalar *pa
int EIGEN_BLAS_FUNC(syrk)(char *uplo, char *op, int *n, int *k, RealScalar *palpha, RealScalar *pa, int *lda, RealScalar *pbeta, RealScalar *pc, int *ldc)
{
// std::cerr << "in syrk " << *uplo << " " << *op << " " << *n << " " << *k << " " << *palpha << " " << *lda << " " << *pbeta << " " << *ldc << "\n";
- typedef void (*functype)(DenseIndex, DenseIndex, const Scalar *, DenseIndex, const Scalar *, DenseIndex, Scalar *, DenseIndex, Scalar);
+ #if !ISCOMPLEX
+ typedef void (*functype)(DenseIndex, DenseIndex, const Scalar *, DenseIndex, const Scalar *, DenseIndex, Scalar *, DenseIndex, const Scalar&);
static functype func[8];
static bool init = false;
@@ -324,6 +325,7 @@ int EIGEN_BLAS_FUNC(syrk)(char *uplo, char *op, int *n, int *k, RealScalar *palp
init = true;
}
+ #endif
Scalar* a = reinterpret_cast<Scalar*>(pa);
Scalar* c = reinterpret_cast<Scalar*>(pc);
@@ -498,7 +500,7 @@ int EIGEN_BLAS_FUNC(hemm)(char *side, char *uplo, int *m, int *n, RealScalar *pa
// c = alpha*conj(a')*a + beta*c for op = 'C'or'c'
int EIGEN_BLAS_FUNC(herk)(char *uplo, char *op, int *n, int *k, RealScalar *palpha, RealScalar *pa, int *lda, RealScalar *pbeta, RealScalar *pc, int *ldc)
{
- typedef void (*functype)(DenseIndex, DenseIndex, const Scalar *, DenseIndex, const Scalar *, DenseIndex, Scalar *, DenseIndex, Scalar);
+ typedef void (*functype)(DenseIndex, DenseIndex, const Scalar *, DenseIndex, const Scalar *, DenseIndex, Scalar *, DenseIndex, const Scalar&);
static functype func[8];
static bool init = false;
@@ -606,24 +608,24 @@ int EIGEN_BLAS_FUNC(her2k)(char *uplo, char *op, int *n, int *k, RealScalar *pal
if(UPLO(*uplo)==UP)
{
matrix(c, *n, *n, *ldc).triangularView<Upper>()
- += alpha *matrix(a, *n, *k, *lda)*matrix(b, *n, *k, *ldb).adjoint()
- + internal::conj(alpha)*matrix(b, *n, *k, *ldb)*matrix(a, *n, *k, *lda).adjoint();
+ += alpha *matrix(a, *n, *k, *lda)*matrix(b, *n, *k, *ldb).adjoint()
+ + numext::conj(alpha)*matrix(b, *n, *k, *ldb)*matrix(a, *n, *k, *lda).adjoint();
}
else if(UPLO(*uplo)==LO)
matrix(c, *n, *n, *ldc).triangularView<Lower>()
+= alpha*matrix(a, *n, *k, *lda)*matrix(b, *n, *k, *ldb).adjoint()
- + internal::conj(alpha)*matrix(b, *n, *k, *ldb)*matrix(a, *n, *k, *lda).adjoint();
+ + numext::conj(alpha)*matrix(b, *n, *k, *ldb)*matrix(a, *n, *k, *lda).adjoint();
}
else if(OP(*op)==ADJ)
{
if(UPLO(*uplo)==UP)
matrix(c, *n, *n, *ldc).triangularView<Upper>()
- += alpha*matrix(a, *k, *n, *lda).adjoint()*matrix(b, *k, *n, *ldb)
- + internal::conj(alpha)*matrix(b, *k, *n, *ldb).adjoint()*matrix(a, *k, *n, *lda);
+ += alpha*matrix(a, *k, *n, *lda).adjoint()*matrix(b, *k, *n, *ldb)
+ + numext::conj(alpha)*matrix(b, *k, *n, *ldb).adjoint()*matrix(a, *k, *n, *lda);
else if(UPLO(*uplo)==LO)
matrix(c, *n, *n, *ldc).triangularView<Lower>()
- += alpha*matrix(a, *k, *n, *lda).adjoint()*matrix(b, *k, *n, *ldb)
- + internal::conj(alpha)*matrix(b, *k, *n, *ldb).adjoint()*matrix(a, *k, *n, *lda);
+ += alpha*matrix(a, *k, *n, *lda).adjoint()*matrix(b, *k, *n, *ldb)
+ + numext::conj(alpha)*matrix(b, *k, *n, *ldb).adjoint()*matrix(a, *k, *n, *lda);
}
return 1;
diff --git a/blas/single.cpp b/blas/single.cpp
index 1b7775aed..836e3eee2 100644
--- a/blas/single.cpp
+++ b/blas/single.cpp
@@ -17,3 +17,6 @@
#include "level2_impl.h"
#include "level2_real_impl.h"
#include "level3_impl.h"
+
+float BLASFUNC(sdsdot)(int* n, float* alpha, float* x, int* incx, float* y, int* incy)
+{ return *alpha + BLASFUNC(dsdot)(n, x, incx, y, incy); }
diff --git a/blas/sspr.f b/blas/sspr.f
deleted file mode 100644
index bae92612e..000000000
--- a/blas/sspr.f
+++ /dev/null
@@ -1,202 +0,0 @@
- SUBROUTINE SSPR(UPLO,N,ALPHA,X,INCX,AP)
-* .. Scalar Arguments ..
- REAL ALPHA
- INTEGER INCX,N
- CHARACTER UPLO
-* ..
-* .. Array Arguments ..
- REAL AP(*),X(*)
-* ..
-*
-* Purpose
-* =======
-*
-* SSPR performs the symmetric rank 1 operation
-*
-* A := alpha*x*x' + A,
-*
-* where alpha is a real scalar, x is an n element vector and A is an
-* n by n symmetric matrix, supplied in packed form.
-*
-* Arguments
-* ==========
-*
-* UPLO - CHARACTER*1.
-* On entry, UPLO specifies whether the upper or lower
-* triangular part of the matrix A is supplied in the packed
-* array AP as follows:
-*
-* UPLO = 'U' or 'u' The upper triangular part of A is
-* supplied in AP.
-*
-* UPLO = 'L' or 'l' The lower triangular part of A is
-* supplied in AP.
-*
-* Unchanged on exit.
-*
-* N - INTEGER.
-* On entry, N specifies the order of the matrix A.
-* N must be at least zero.
-* Unchanged on exit.
-*
-* ALPHA - REAL .
-* On entry, ALPHA specifies the scalar alpha.
-* Unchanged on exit.
-*
-* X - REAL array of dimension at least
-* ( 1 + ( n - 1 )*abs( INCX ) ).
-* Before entry, the incremented array X must contain the n
-* element vector x.
-* Unchanged on exit.
-*
-* INCX - INTEGER.
-* On entry, INCX specifies the increment for the elements of
-* X. INCX must not be zero.
-* Unchanged on exit.
-*
-* AP - REAL array of DIMENSION at least
-* ( ( n*( n + 1 ) )/2 ).
-* Before entry with UPLO = 'U' or 'u', the array AP must
-* contain the upper triangular part of the symmetric matrix
-* packed sequentially, column by column, so that AP( 1 )
-* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 1, 2 )
-* and a( 2, 2 ) respectively, and so on. On exit, the array
-* AP is overwritten by the upper triangular part of the
-* updated matrix.
-* Before entry with UPLO = 'L' or 'l', the array AP must
-* contain the lower triangular part of the symmetric matrix
-* packed sequentially, column by column, so that AP( 1 )
-* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 2, 1 )
-* and a( 3, 1 ) respectively, and so on. On exit, the array
-* AP is overwritten by the lower triangular part of the
-* updated matrix.
-*
-* Further Details
-* ===============
-*
-* Level 2 Blas routine.
-*
-* -- Written on 22-October-1986.
-* Jack Dongarra, Argonne National Lab.
-* Jeremy Du Croz, Nag Central Office.
-* Sven Hammarling, Nag Central Office.
-* Richard Hanson, Sandia National Labs.
-*
-* =====================================================================
-*
-* .. Parameters ..
- REAL ZERO
- PARAMETER (ZERO=0.0E+0)
-* ..
-* .. Local Scalars ..
- REAL TEMP
- INTEGER I,INFO,IX,J,JX,K,KK,KX
-* ..
-* .. External Functions ..
- LOGICAL LSAME
- EXTERNAL LSAME
-* ..
-* .. External Subroutines ..
- EXTERNAL XERBLA
-* ..
-*
-* Test the input parameters.
-*
- INFO = 0
- IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN
- INFO = 1
- ELSE IF (N.LT.0) THEN
- INFO = 2
- ELSE IF (INCX.EQ.0) THEN
- INFO = 5
- END IF
- IF (INFO.NE.0) THEN
- CALL XERBLA('SSPR ',INFO)
- RETURN
- END IF
-*
-* Quick return if possible.
-*
- IF ((N.EQ.0) .OR. (ALPHA.EQ.ZERO)) RETURN
-*
-* Set the start point in X if the increment is not unity.
-*
- IF (INCX.LE.0) THEN
- KX = 1 - (N-1)*INCX
- ELSE IF (INCX.NE.1) THEN
- KX = 1
- END IF
-*
-* Start the operations. In this version the elements of the array AP
-* are accessed sequentially with one pass through AP.
-*
- KK = 1
- IF (LSAME(UPLO,'U')) THEN
-*
-* Form A when upper triangle is stored in AP.
-*
- IF (INCX.EQ.1) THEN
- DO 20 J = 1,N
- IF (X(J).NE.ZERO) THEN
- TEMP = ALPHA*X(J)
- K = KK
- DO 10 I = 1,J
- AP(K) = AP(K) + X(I)*TEMP
- K = K + 1
- 10 CONTINUE
- END IF
- KK = KK + J
- 20 CONTINUE
- ELSE
- JX = KX
- DO 40 J = 1,N
- IF (X(JX).NE.ZERO) THEN
- TEMP = ALPHA*X(JX)
- IX = KX
- DO 30 K = KK,KK + J - 1
- AP(K) = AP(K) + X(IX)*TEMP
- IX = IX + INCX
- 30 CONTINUE
- END IF
- JX = JX + INCX
- KK = KK + J
- 40 CONTINUE
- END IF
- ELSE
-*
-* Form A when lower triangle is stored in AP.
-*
- IF (INCX.EQ.1) THEN
- DO 60 J = 1,N
- IF (X(J).NE.ZERO) THEN
- TEMP = ALPHA*X(J)
- K = KK
- DO 50 I = J,N
- AP(K) = AP(K) + X(I)*TEMP
- K = K + 1
- 50 CONTINUE
- END IF
- KK = KK + N - J + 1
- 60 CONTINUE
- ELSE
- JX = KX
- DO 80 J = 1,N
- IF (X(JX).NE.ZERO) THEN
- TEMP = ALPHA*X(JX)
- IX = JX
- DO 70 K = KK,KK + N - J
- AP(K) = AP(K) + X(IX)*TEMP
- IX = IX + INCX
- 70 CONTINUE
- END IF
- JX = JX + INCX
- KK = KK + N - J + 1
- 80 CONTINUE
- END IF
- END IF
-*
- RETURN
-*
-* End of SSPR .
-*
- END
diff --git a/blas/sspr2.f b/blas/sspr2.f
deleted file mode 100644
index cd27c734b..000000000
--- a/blas/sspr2.f
+++ /dev/null
@@ -1,233 +0,0 @@
- SUBROUTINE SSPR2(UPLO,N,ALPHA,X,INCX,Y,INCY,AP)
-* .. Scalar Arguments ..
- REAL ALPHA
- INTEGER INCX,INCY,N
- CHARACTER UPLO
-* ..
-* .. Array Arguments ..
- REAL AP(*),X(*),Y(*)
-* ..
-*
-* Purpose
-* =======
-*
-* SSPR2 performs the symmetric rank 2 operation
-*
-* A := alpha*x*y' + alpha*y*x' + A,
-*
-* where alpha is a scalar, x and y are n element vectors and A is an
-* n by n symmetric matrix, supplied in packed form.
-*
-* Arguments
-* ==========
-*
-* UPLO - CHARACTER*1.
-* On entry, UPLO specifies whether the upper or lower
-* triangular part of the matrix A is supplied in the packed
-* array AP as follows:
-*
-* UPLO = 'U' or 'u' The upper triangular part of A is
-* supplied in AP.
-*
-* UPLO = 'L' or 'l' The lower triangular part of A is
-* supplied in AP.
-*
-* Unchanged on exit.
-*
-* N - INTEGER.
-* On entry, N specifies the order of the matrix A.
-* N must be at least zero.
-* Unchanged on exit.
-*
-* ALPHA - REAL .
-* On entry, ALPHA specifies the scalar alpha.
-* Unchanged on exit.
-*
-* X - REAL array of dimension at least
-* ( 1 + ( n - 1 )*abs( INCX ) ).
-* Before entry, the incremented array X must contain the n
-* element vector x.
-* Unchanged on exit.
-*
-* INCX - INTEGER.
-* On entry, INCX specifies the increment for the elements of
-* X. INCX must not be zero.
-* Unchanged on exit.
-*
-* Y - REAL array of dimension at least
-* ( 1 + ( n - 1 )*abs( INCY ) ).
-* Before entry, the incremented array Y must contain the n
-* element vector y.
-* Unchanged on exit.
-*
-* INCY - INTEGER.
-* On entry, INCY specifies the increment for the elements of
-* Y. INCY must not be zero.
-* Unchanged on exit.
-*
-* AP - REAL array of DIMENSION at least
-* ( ( n*( n + 1 ) )/2 ).
-* Before entry with UPLO = 'U' or 'u', the array AP must
-* contain the upper triangular part of the symmetric matrix
-* packed sequentially, column by column, so that AP( 1 )
-* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 1, 2 )
-* and a( 2, 2 ) respectively, and so on. On exit, the array
-* AP is overwritten by the upper triangular part of the
-* updated matrix.
-* Before entry with UPLO = 'L' or 'l', the array AP must
-* contain the lower triangular part of the symmetric matrix
-* packed sequentially, column by column, so that AP( 1 )
-* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 2, 1 )
-* and a( 3, 1 ) respectively, and so on. On exit, the array
-* AP is overwritten by the lower triangular part of the
-* updated matrix.
-*
-* Further Details
-* ===============
-*
-* Level 2 Blas routine.
-*
-* -- Written on 22-October-1986.
-* Jack Dongarra, Argonne National Lab.
-* Jeremy Du Croz, Nag Central Office.
-* Sven Hammarling, Nag Central Office.
-* Richard Hanson, Sandia National Labs.
-*
-* =====================================================================
-*
-* .. Parameters ..
- REAL ZERO
- PARAMETER (ZERO=0.0E+0)
-* ..
-* .. Local Scalars ..
- REAL TEMP1,TEMP2
- INTEGER I,INFO,IX,IY,J,JX,JY,K,KK,KX,KY
-* ..
-* .. External Functions ..
- LOGICAL LSAME
- EXTERNAL LSAME
-* ..
-* .. External Subroutines ..
- EXTERNAL XERBLA
-* ..
-*
-* Test the input parameters.
-*
- INFO = 0
- IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN
- INFO = 1
- ELSE IF (N.LT.0) THEN
- INFO = 2
- ELSE IF (INCX.EQ.0) THEN
- INFO = 5
- ELSE IF (INCY.EQ.0) THEN
- INFO = 7
- END IF
- IF (INFO.NE.0) THEN
- CALL XERBLA('SSPR2 ',INFO)
- RETURN
- END IF
-*
-* Quick return if possible.
-*
- IF ((N.EQ.0) .OR. (ALPHA.EQ.ZERO)) RETURN
-*
-* Set up the start points in X and Y if the increments are not both
-* unity.
-*
- IF ((INCX.NE.1) .OR. (INCY.NE.1)) THEN
- IF (INCX.GT.0) THEN
- KX = 1
- ELSE
- KX = 1 - (N-1)*INCX
- END IF
- IF (INCY.GT.0) THEN
- KY = 1
- ELSE
- KY = 1 - (N-1)*INCY
- END IF
- JX = KX
- JY = KY
- END IF
-*
-* Start the operations. In this version the elements of the array AP
-* are accessed sequentially with one pass through AP.
-*
- KK = 1
- IF (LSAME(UPLO,'U')) THEN
-*
-* Form A when upper triangle is stored in AP.
-*
- IF ((INCX.EQ.1) .AND. (INCY.EQ.1)) THEN
- DO 20 J = 1,N
- IF ((X(J).NE.ZERO) .OR. (Y(J).NE.ZERO)) THEN
- TEMP1 = ALPHA*Y(J)
- TEMP2 = ALPHA*X(J)
- K = KK
- DO 10 I = 1,J
- AP(K) = AP(K) + X(I)*TEMP1 + Y(I)*TEMP2
- K = K + 1
- 10 CONTINUE
- END IF
- KK = KK + J
- 20 CONTINUE
- ELSE
- DO 40 J = 1,N
- IF ((X(JX).NE.ZERO) .OR. (Y(JY).NE.ZERO)) THEN
- TEMP1 = ALPHA*Y(JY)
- TEMP2 = ALPHA*X(JX)
- IX = KX
- IY = KY
- DO 30 K = KK,KK + J - 1
- AP(K) = AP(K) + X(IX)*TEMP1 + Y(IY)*TEMP2
- IX = IX + INCX
- IY = IY + INCY
- 30 CONTINUE
- END IF
- JX = JX + INCX
- JY = JY + INCY
- KK = KK + J
- 40 CONTINUE
- END IF
- ELSE
-*
-* Form A when lower triangle is stored in AP.
-*
- IF ((INCX.EQ.1) .AND. (INCY.EQ.1)) THEN
- DO 60 J = 1,N
- IF ((X(J).NE.ZERO) .OR. (Y(J).NE.ZERO)) THEN
- TEMP1 = ALPHA*Y(J)
- TEMP2 = ALPHA*X(J)
- K = KK
- DO 50 I = J,N
- AP(K) = AP(K) + X(I)*TEMP1 + Y(I)*TEMP2
- K = K + 1
- 50 CONTINUE
- END IF
- KK = KK + N - J + 1
- 60 CONTINUE
- ELSE
- DO 80 J = 1,N
- IF ((X(JX).NE.ZERO) .OR. (Y(JY).NE.ZERO)) THEN
- TEMP1 = ALPHA*Y(JY)
- TEMP2 = ALPHA*X(JX)
- IX = JX
- IY = JY
- DO 70 K = KK,KK + N - J
- AP(K) = AP(K) + X(IX)*TEMP1 + Y(IY)*TEMP2
- IX = IX + INCX
- IY = IY + INCY
- 70 CONTINUE
- END IF
- JX = JX + INCX
- JY = JY + INCY
- KK = KK + N - J + 1
- 80 CONTINUE
- END IF
- END IF
-*
- RETURN
-*
-* End of SSPR2 .
-*
- END
diff --git a/blas/stpmv.f b/blas/stpmv.f
deleted file mode 100644
index 71ea49a36..000000000
--- a/blas/stpmv.f
+++ /dev/null
@@ -1,293 +0,0 @@
- SUBROUTINE STPMV(UPLO,TRANS,DIAG,N,AP,X,INCX)
-* .. Scalar Arguments ..
- INTEGER INCX,N
- CHARACTER DIAG,TRANS,UPLO
-* ..
-* .. Array Arguments ..
- REAL AP(*),X(*)
-* ..
-*
-* Purpose
-* =======
-*
-* STPMV performs one of the matrix-vector operations
-*
-* x := A*x, or x := A'*x,
-*
-* where x is an n element vector and A is an n by n unit, or non-unit,
-* upper or lower triangular matrix, supplied in packed form.
-*
-* Arguments
-* ==========
-*
-* UPLO - CHARACTER*1.
-* On entry, UPLO specifies whether the matrix is an upper or
-* lower triangular matrix as follows:
-*
-* UPLO = 'U' or 'u' A is an upper triangular matrix.
-*
-* UPLO = 'L' or 'l' A is a lower triangular matrix.
-*
-* Unchanged on exit.
-*
-* TRANS - CHARACTER*1.
-* On entry, TRANS specifies the operation to be performed as
-* follows:
-*
-* TRANS = 'N' or 'n' x := A*x.
-*
-* TRANS = 'T' or 't' x := A'*x.
-*
-* TRANS = 'C' or 'c' x := A'*x.
-*
-* Unchanged on exit.
-*
-* DIAG - CHARACTER*1.
-* On entry, DIAG specifies whether or not A is unit
-* triangular as follows:
-*
-* DIAG = 'U' or 'u' A is assumed to be unit triangular.
-*
-* DIAG = 'N' or 'n' A is not assumed to be unit
-* triangular.
-*
-* Unchanged on exit.
-*
-* N - INTEGER.
-* On entry, N specifies the order of the matrix A.
-* N must be at least zero.
-* Unchanged on exit.
-*
-* AP - REAL array of DIMENSION at least
-* ( ( n*( n + 1 ) )/2 ).
-* Before entry with UPLO = 'U' or 'u', the array AP must
-* contain the upper triangular matrix packed sequentially,
-* column by column, so that AP( 1 ) contains a( 1, 1 ),
-* AP( 2 ) and AP( 3 ) contain a( 1, 2 ) and a( 2, 2 )
-* respectively, and so on.
-* Before entry with UPLO = 'L' or 'l', the array AP must
-* contain the lower triangular matrix packed sequentially,
-* column by column, so that AP( 1 ) contains a( 1, 1 ),
-* AP( 2 ) and AP( 3 ) contain a( 2, 1 ) and a( 3, 1 )
-* respectively, and so on.
-* Note that when DIAG = 'U' or 'u', the diagonal elements of
-* A are not referenced, but are assumed to be unity.
-* Unchanged on exit.
-*
-* X - REAL array of dimension at least
-* ( 1 + ( n - 1 )*abs( INCX ) ).
-* Before entry, the incremented array X must contain the n
-* element vector x. On exit, X is overwritten with the
-* tranformed vector x.
-*
-* INCX - INTEGER.
-* On entry, INCX specifies the increment for the elements of
-* X. INCX must not be zero.
-* Unchanged on exit.
-*
-* Further Details
-* ===============
-*
-* Level 2 Blas routine.
-*
-* -- Written on 22-October-1986.
-* Jack Dongarra, Argonne National Lab.
-* Jeremy Du Croz, Nag Central Office.
-* Sven Hammarling, Nag Central Office.
-* Richard Hanson, Sandia National Labs.
-*
-* =====================================================================
-*
-* .. Parameters ..
- REAL ZERO
- PARAMETER (ZERO=0.0E+0)
-* ..
-* .. Local Scalars ..
- REAL TEMP
- INTEGER I,INFO,IX,J,JX,K,KK,KX
- LOGICAL NOUNIT
-* ..
-* .. External Functions ..
- LOGICAL LSAME
- EXTERNAL LSAME
-* ..
-* .. External Subroutines ..
- EXTERNAL XERBLA
-* ..
-*
-* Test the input parameters.
-*
- INFO = 0
- IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN
- INFO = 1
- ELSE IF (.NOT.LSAME(TRANS,'N') .AND. .NOT.LSAME(TRANS,'T') .AND.
- + .NOT.LSAME(TRANS,'C')) THEN
- INFO = 2
- ELSE IF (.NOT.LSAME(DIAG,'U') .AND. .NOT.LSAME(DIAG,'N')) THEN
- INFO = 3
- ELSE IF (N.LT.0) THEN
- INFO = 4
- ELSE IF (INCX.EQ.0) THEN
- INFO = 7
- END IF
- IF (INFO.NE.0) THEN
- CALL XERBLA('STPMV ',INFO)
- RETURN
- END IF
-*
-* Quick return if possible.
-*
- IF (N.EQ.0) RETURN
-*
- NOUNIT = LSAME(DIAG,'N')
-*
-* Set up the start point in X if the increment is not unity. This
-* will be ( N - 1 )*INCX too small for descending loops.
-*
- IF (INCX.LE.0) THEN
- KX = 1 - (N-1)*INCX
- ELSE IF (INCX.NE.1) THEN
- KX = 1
- END IF
-*
-* Start the operations. In this version the elements of AP are
-* accessed sequentially with one pass through AP.
-*
- IF (LSAME(TRANS,'N')) THEN
-*
-* Form x:= A*x.
-*
- IF (LSAME(UPLO,'U')) THEN
- KK = 1
- IF (INCX.EQ.1) THEN
- DO 20 J = 1,N
- IF (X(J).NE.ZERO) THEN
- TEMP = X(J)
- K = KK
- DO 10 I = 1,J - 1
- X(I) = X(I) + TEMP*AP(K)
- K = K + 1
- 10 CONTINUE
- IF (NOUNIT) X(J) = X(J)*AP(KK+J-1)
- END IF
- KK = KK + J
- 20 CONTINUE
- ELSE
- JX = KX
- DO 40 J = 1,N
- IF (X(JX).NE.ZERO) THEN
- TEMP = X(JX)
- IX = KX
- DO 30 K = KK,KK + J - 2
- X(IX) = X(IX) + TEMP*AP(K)
- IX = IX + INCX
- 30 CONTINUE
- IF (NOUNIT) X(JX) = X(JX)*AP(KK+J-1)
- END IF
- JX = JX + INCX
- KK = KK + J
- 40 CONTINUE
- END IF
- ELSE
- KK = (N* (N+1))/2
- IF (INCX.EQ.1) THEN
- DO 60 J = N,1,-1
- IF (X(J).NE.ZERO) THEN
- TEMP = X(J)
- K = KK
- DO 50 I = N,J + 1,-1
- X(I) = X(I) + TEMP*AP(K)
- K = K - 1
- 50 CONTINUE
- IF (NOUNIT) X(J) = X(J)*AP(KK-N+J)
- END IF
- KK = KK - (N-J+1)
- 60 CONTINUE
- ELSE
- KX = KX + (N-1)*INCX
- JX = KX
- DO 80 J = N,1,-1
- IF (X(JX).NE.ZERO) THEN
- TEMP = X(JX)
- IX = KX
- DO 70 K = KK,KK - (N- (J+1)),-1
- X(IX) = X(IX) + TEMP*AP(K)
- IX = IX - INCX
- 70 CONTINUE
- IF (NOUNIT) X(JX) = X(JX)*AP(KK-N+J)
- END IF
- JX = JX - INCX
- KK = KK - (N-J+1)
- 80 CONTINUE
- END IF
- END IF
- ELSE
-*
-* Form x := A'*x.
-*
- IF (LSAME(UPLO,'U')) THEN
- KK = (N* (N+1))/2
- IF (INCX.EQ.1) THEN
- DO 100 J = N,1,-1
- TEMP = X(J)
- IF (NOUNIT) TEMP = TEMP*AP(KK)
- K = KK - 1
- DO 90 I = J - 1,1,-1
- TEMP = TEMP + AP(K)*X(I)
- K = K - 1
- 90 CONTINUE
- X(J) = TEMP
- KK = KK - J
- 100 CONTINUE
- ELSE
- JX = KX + (N-1)*INCX
- DO 120 J = N,1,-1
- TEMP = X(JX)
- IX = JX
- IF (NOUNIT) TEMP = TEMP*AP(KK)
- DO 110 K = KK - 1,KK - J + 1,-1
- IX = IX - INCX
- TEMP = TEMP + AP(K)*X(IX)
- 110 CONTINUE
- X(JX) = TEMP
- JX = JX - INCX
- KK = KK - J
- 120 CONTINUE
- END IF
- ELSE
- KK = 1
- IF (INCX.EQ.1) THEN
- DO 140 J = 1,N
- TEMP = X(J)
- IF (NOUNIT) TEMP = TEMP*AP(KK)
- K = KK + 1
- DO 130 I = J + 1,N
- TEMP = TEMP + AP(K)*X(I)
- K = K + 1
- 130 CONTINUE
- X(J) = TEMP
- KK = KK + (N-J+1)
- 140 CONTINUE
- ELSE
- JX = KX
- DO 160 J = 1,N
- TEMP = X(JX)
- IX = JX
- IF (NOUNIT) TEMP = TEMP*AP(KK)
- DO 150 K = KK + 1,KK + N - J
- IX = IX + INCX
- TEMP = TEMP + AP(K)*X(IX)
- 150 CONTINUE
- X(JX) = TEMP
- JX = JX + INCX
- KK = KK + (N-J+1)
- 160 CONTINUE
- END IF
- END IF
- END IF
-*
- RETURN
-*
-* End of STPMV .
-*
- END
diff --git a/blas/stpsv.f b/blas/stpsv.f
deleted file mode 100644
index 7d95efbde..000000000
--- a/blas/stpsv.f
+++ /dev/null
@@ -1,296 +0,0 @@
- SUBROUTINE STPSV(UPLO,TRANS,DIAG,N,AP,X,INCX)
-* .. Scalar Arguments ..
- INTEGER INCX,N
- CHARACTER DIAG,TRANS,UPLO
-* ..
-* .. Array Arguments ..
- REAL AP(*),X(*)
-* ..
-*
-* Purpose
-* =======
-*
-* STPSV solves one of the systems of equations
-*
-* A*x = b, or A'*x = b,
-*
-* where b and x are n element vectors and A is an n by n unit, or
-* non-unit, upper or lower triangular matrix, supplied in packed form.
-*
-* No test for singularity or near-singularity is included in this
-* routine. Such tests must be performed before calling this routine.
-*
-* Arguments
-* ==========
-*
-* UPLO - CHARACTER*1.
-* On entry, UPLO specifies whether the matrix is an upper or
-* lower triangular matrix as follows:
-*
-* UPLO = 'U' or 'u' A is an upper triangular matrix.
-*
-* UPLO = 'L' or 'l' A is a lower triangular matrix.
-*
-* Unchanged on exit.
-*
-* TRANS - CHARACTER*1.
-* On entry, TRANS specifies the equations to be solved as
-* follows:
-*
-* TRANS = 'N' or 'n' A*x = b.
-*
-* TRANS = 'T' or 't' A'*x = b.
-*
-* TRANS = 'C' or 'c' A'*x = b.
-*
-* Unchanged on exit.
-*
-* DIAG - CHARACTER*1.
-* On entry, DIAG specifies whether or not A is unit
-* triangular as follows:
-*
-* DIAG = 'U' or 'u' A is assumed to be unit triangular.
-*
-* DIAG = 'N' or 'n' A is not assumed to be unit
-* triangular.
-*
-* Unchanged on exit.
-*
-* N - INTEGER.
-* On entry, N specifies the order of the matrix A.
-* N must be at least zero.
-* Unchanged on exit.
-*
-* AP - REAL array of DIMENSION at least
-* ( ( n*( n + 1 ) )/2 ).
-* Before entry with UPLO = 'U' or 'u', the array AP must
-* contain the upper triangular matrix packed sequentially,
-* column by column, so that AP( 1 ) contains a( 1, 1 ),
-* AP( 2 ) and AP( 3 ) contain a( 1, 2 ) and a( 2, 2 )
-* respectively, and so on.
-* Before entry with UPLO = 'L' or 'l', the array AP must
-* contain the lower triangular matrix packed sequentially,
-* column by column, so that AP( 1 ) contains a( 1, 1 ),
-* AP( 2 ) and AP( 3 ) contain a( 2, 1 ) and a( 3, 1 )
-* respectively, and so on.
-* Note that when DIAG = 'U' or 'u', the diagonal elements of
-* A are not referenced, but are assumed to be unity.
-* Unchanged on exit.
-*
-* X - REAL array of dimension at least
-* ( 1 + ( n - 1 )*abs( INCX ) ).
-* Before entry, the incremented array X must contain the n
-* element right-hand side vector b. On exit, X is overwritten
-* with the solution vector x.
-*
-* INCX - INTEGER.
-* On entry, INCX specifies the increment for the elements of
-* X. INCX must not be zero.
-* Unchanged on exit.
-*
-* Further Details
-* ===============
-*
-* Level 2 Blas routine.
-*
-* -- Written on 22-October-1986.
-* Jack Dongarra, Argonne National Lab.
-* Jeremy Du Croz, Nag Central Office.
-* Sven Hammarling, Nag Central Office.
-* Richard Hanson, Sandia National Labs.
-*
-* =====================================================================
-*
-* .. Parameters ..
- REAL ZERO
- PARAMETER (ZERO=0.0E+0)
-* ..
-* .. Local Scalars ..
- REAL TEMP
- INTEGER I,INFO,IX,J,JX,K,KK,KX
- LOGICAL NOUNIT
-* ..
-* .. External Functions ..
- LOGICAL LSAME
- EXTERNAL LSAME
-* ..
-* .. External Subroutines ..
- EXTERNAL XERBLA
-* ..
-*
-* Test the input parameters.
-*
- INFO = 0
- IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN
- INFO = 1
- ELSE IF (.NOT.LSAME(TRANS,'N') .AND. .NOT.LSAME(TRANS,'T') .AND.
- + .NOT.LSAME(TRANS,'C')) THEN
- INFO = 2
- ELSE IF (.NOT.LSAME(DIAG,'U') .AND. .NOT.LSAME(DIAG,'N')) THEN
- INFO = 3
- ELSE IF (N.LT.0) THEN
- INFO = 4
- ELSE IF (INCX.EQ.0) THEN
- INFO = 7
- END IF
- IF (INFO.NE.0) THEN
- CALL XERBLA('STPSV ',INFO)
- RETURN
- END IF
-*
-* Quick return if possible.
-*
- IF (N.EQ.0) RETURN
-*
- NOUNIT = LSAME(DIAG,'N')
-*
-* Set up the start point in X if the increment is not unity. This
-* will be ( N - 1 )*INCX too small for descending loops.
-*
- IF (INCX.LE.0) THEN
- KX = 1 - (N-1)*INCX
- ELSE IF (INCX.NE.1) THEN
- KX = 1
- END IF
-*
-* Start the operations. In this version the elements of AP are
-* accessed sequentially with one pass through AP.
-*
- IF (LSAME(TRANS,'N')) THEN
-*
-* Form x := inv( A )*x.
-*
- IF (LSAME(UPLO,'U')) THEN
- KK = (N* (N+1))/2
- IF (INCX.EQ.1) THEN
- DO 20 J = N,1,-1
- IF (X(J).NE.ZERO) THEN
- IF (NOUNIT) X(J) = X(J)/AP(KK)
- TEMP = X(J)
- K = KK - 1
- DO 10 I = J - 1,1,-1
- X(I) = X(I) - TEMP*AP(K)
- K = K - 1
- 10 CONTINUE
- END IF
- KK = KK - J
- 20 CONTINUE
- ELSE
- JX = KX + (N-1)*INCX
- DO 40 J = N,1,-1
- IF (X(JX).NE.ZERO) THEN
- IF (NOUNIT) X(JX) = X(JX)/AP(KK)
- TEMP = X(JX)
- IX = JX
- DO 30 K = KK - 1,KK - J + 1,-1
- IX = IX - INCX
- X(IX) = X(IX) - TEMP*AP(K)
- 30 CONTINUE
- END IF
- JX = JX - INCX
- KK = KK - J
- 40 CONTINUE
- END IF
- ELSE
- KK = 1
- IF (INCX.EQ.1) THEN
- DO 60 J = 1,N
- IF (X(J).NE.ZERO) THEN
- IF (NOUNIT) X(J) = X(J)/AP(KK)
- TEMP = X(J)
- K = KK + 1
- DO 50 I = J + 1,N
- X(I) = X(I) - TEMP*AP(K)
- K = K + 1
- 50 CONTINUE
- END IF
- KK = KK + (N-J+1)
- 60 CONTINUE
- ELSE
- JX = KX
- DO 80 J = 1,N
- IF (X(JX).NE.ZERO) THEN
- IF (NOUNIT) X(JX) = X(JX)/AP(KK)
- TEMP = X(JX)
- IX = JX
- DO 70 K = KK + 1,KK + N - J
- IX = IX + INCX
- X(IX) = X(IX) - TEMP*AP(K)
- 70 CONTINUE
- END IF
- JX = JX + INCX
- KK = KK + (N-J+1)
- 80 CONTINUE
- END IF
- END IF
- ELSE
-*
-* Form x := inv( A' )*x.
-*
- IF (LSAME(UPLO,'U')) THEN
- KK = 1
- IF (INCX.EQ.1) THEN
- DO 100 J = 1,N
- TEMP = X(J)
- K = KK
- DO 90 I = 1,J - 1
- TEMP = TEMP - AP(K)*X(I)
- K = K + 1
- 90 CONTINUE
- IF (NOUNIT) TEMP = TEMP/AP(KK+J-1)
- X(J) = TEMP
- KK = KK + J
- 100 CONTINUE
- ELSE
- JX = KX
- DO 120 J = 1,N
- TEMP = X(JX)
- IX = KX
- DO 110 K = KK,KK + J - 2
- TEMP = TEMP - AP(K)*X(IX)
- IX = IX + INCX
- 110 CONTINUE
- IF (NOUNIT) TEMP = TEMP/AP(KK+J-1)
- X(JX) = TEMP
- JX = JX + INCX
- KK = KK + J
- 120 CONTINUE
- END IF
- ELSE
- KK = (N* (N+1))/2
- IF (INCX.EQ.1) THEN
- DO 140 J = N,1,-1
- TEMP = X(J)
- K = KK
- DO 130 I = N,J + 1,-1
- TEMP = TEMP - AP(K)*X(I)
- K = K - 1
- 130 CONTINUE
- IF (NOUNIT) TEMP = TEMP/AP(KK-N+J)
- X(J) = TEMP
- KK = KK - (N-J+1)
- 140 CONTINUE
- ELSE
- KX = KX + (N-1)*INCX
- JX = KX
- DO 160 J = N,1,-1
- TEMP = X(JX)
- IX = KX
- DO 150 K = KK,KK - (N- (J+1)),-1
- TEMP = TEMP - AP(K)*X(IX)
- IX = IX - INCX
- 150 CONTINUE
- IF (NOUNIT) TEMP = TEMP/AP(KK-N+J)
- X(JX) = TEMP
- JX = JX - INCX
- KK = KK - (N-J+1)
- 160 CONTINUE
- END IF
- END IF
- END IF
-*
- RETURN
-*
-* End of STPSV .
-*
- END
diff --git a/blas/testing/dblat1.f b/blas/testing/dblat1.f
index 5a45d69f4..30691f9bf 100644
--- a/blas/testing/dblat1.f
+++ b/blas/testing/dblat1.f
@@ -1,12 +1,54 @@
+*> \brief \b DBLAT1
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+* Definition:
+* ===========
+*
+* PROGRAM DBLAT1
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> Test program for the DOUBLE PRECISION Level 1 BLAS.
+*>
+*> Based upon the original BLAS test routine together with:
+*> F06EAF Example Program Text
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date April 2012
+*
+*> \ingroup double_blas_testing
+*
+* =====================================================================
PROGRAM DBLAT1
-* Test program for the DOUBLE PRECISION Level 1 BLAS.
-* Based upon the original BLAS test routine together with:
-* F06EAF Example Program Text
+*
+* -- Reference BLAS test routine (version 3.4.1) --
+* -- Reference BLAS is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* April 2012
+*
+* =====================================================================
+*
* .. Parameters ..
INTEGER NOUT
PARAMETER (NOUT=6)
* .. Scalars in Common ..
- INTEGER ICASE, INCX, INCY, MODE, N
+ INTEGER ICASE, INCX, INCY, N
LOGICAL PASS
* .. Local Scalars ..
DOUBLE PRECISION SFAC
@@ -14,31 +56,30 @@
* .. External Subroutines ..
EXTERNAL CHECK0, CHECK1, CHECK2, CHECK3, HEADER
* .. Common blocks ..
- COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS
+ COMMON /COMBLA/ICASE, N, INCX, INCY, PASS
* .. Data statements ..
DATA SFAC/9.765625D-4/
* .. Executable Statements ..
WRITE (NOUT,99999)
- DO 20 IC = 1, 10
+ DO 20 IC = 1, 13
ICASE = IC
CALL HEADER
*
-* .. Initialize PASS, INCX, INCY, and MODE for a new case. ..
-* .. the value 9999 for INCX, INCY or MODE will appear in the ..
+* .. Initialize PASS, INCX, and INCY for a new case. ..
+* .. the value 9999 for INCX or INCY will appear in the ..
* .. detailed output, if any, for cases that do not involve ..
* .. these parameters ..
*
PASS = .TRUE.
INCX = 9999
INCY = 9999
- MODE = 9999
- IF (ICASE.EQ.3) THEN
+ IF (ICASE.EQ.3 .OR. ICASE.EQ.11) THEN
CALL CHECK0(SFAC)
ELSE IF (ICASE.EQ.7 .OR. ICASE.EQ.8 .OR. ICASE.EQ.9 .OR.
+ ICASE.EQ.10) THEN
CALL CHECK1(SFAC)
ELSE IF (ICASE.EQ.1 .OR. ICASE.EQ.2 .OR. ICASE.EQ.5 .OR.
- + ICASE.EQ.6) THEN
+ + ICASE.EQ.6 .OR. ICASE.EQ.12 .OR. ICASE.EQ.13) THEN
CALL CHECK2(SFAC)
ELSE IF (ICASE.EQ.4) THEN
CALL CHECK3(SFAC)
@@ -56,12 +97,12 @@
INTEGER NOUT
PARAMETER (NOUT=6)
* .. Scalars in Common ..
- INTEGER ICASE, INCX, INCY, MODE, N
+ INTEGER ICASE, INCX, INCY, N
LOGICAL PASS
* .. Local Arrays ..
- CHARACTER*6 L(10)
+ CHARACTER*6 L(13)
* .. Common blocks ..
- COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS
+ COMMON /COMBLA/ICASE, N, INCX, INCY, PASS
* .. Data statements ..
DATA L(1)/' DDOT '/
DATA L(2)/'DAXPY '/
@@ -73,6 +114,9 @@
DATA L(8)/'DASUM '/
DATA L(9)/'DSCAL '/
DATA L(10)/'IDAMAX'/
+ DATA L(11)/'DROTMG'/
+ DATA L(12)/'DROTM '/
+ DATA L(13)/'DSDOT '/
* .. Executable Statements ..
WRITE (NOUT,99999) ICASE, L(ICASE)
RETURN
@@ -86,18 +130,18 @@
* .. Scalar Arguments ..
DOUBLE PRECISION SFAC
* .. Scalars in Common ..
- INTEGER ICASE, INCX, INCY, MODE, N
+ INTEGER ICASE, INCX, INCY, N
LOGICAL PASS
* .. Local Scalars ..
- DOUBLE PRECISION D12, SA, SB, SC, SS
- INTEGER K
+ DOUBLE PRECISION SA, SB, SC, SS, D12
+ INTEGER I, K
* .. Local Arrays ..
DOUBLE PRECISION DA1(8), DATRUE(8), DB1(8), DBTRUE(8), DC1(8),
- + DS1(8)
+ $ DS1(8), DAB(4,9), DTEMP(9), DTRUE(9,9)
* .. External Subroutines ..
- EXTERNAL DROTG, STEST1
+ EXTERNAL DROTG, DROTMG, STEST1
* .. Common blocks ..
- COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS
+ COMMON /COMBLA/ICASE, N, INCX, INCY, PASS
* .. Data statements ..
DATA DA1/0.3D0, 0.4D0, -0.3D0, -0.4D0, -0.3D0, 0.0D0,
+ 0.0D0, 1.0D0/
@@ -111,7 +155,52 @@
+ 0.0D0, 1.0D0, 1.0D0/
DATA DBTRUE/0.0D0, 0.6D0, 0.0D0, -0.6D0, 0.0D0,
+ 0.0D0, 1.0D0, 0.0D0/
- DATA D12/4096.0D0/
+* INPUT FOR MODIFIED GIVENS
+ DATA DAB/ .1D0,.3D0,1.2D0,.2D0,
+ A .7D0, .2D0, .6D0, 4.2D0,
+ B 0.D0,0.D0,0.D0,0.D0,
+ C 4.D0, -1.D0, 2.D0, 4.D0,
+ D 6.D-10, 2.D-2, 1.D5, 10.D0,
+ E 4.D10, 2.D-2, 1.D-5, 10.D0,
+ F 2.D-10, 4.D-2, 1.D5, 10.D0,
+ G 2.D10, 4.D-2, 1.D-5, 10.D0,
+ H 4.D0, -2.D0, 8.D0, 4.D0 /
+* TRUE RESULTS FOR MODIFIED GIVENS
+ DATA DTRUE/0.D0,0.D0, 1.3D0, .2D0, 0.D0,0.D0,0.D0, .5D0, 0.D0,
+ A 0.D0,0.D0, 4.5D0, 4.2D0, 1.D0, .5D0, 0.D0,0.D0,0.D0,
+ B 0.D0,0.D0,0.D0,0.D0, -2.D0, 0.D0,0.D0,0.D0,0.D0,
+ C 0.D0,0.D0,0.D0, 4.D0, -1.D0, 0.D0,0.D0,0.D0,0.D0,
+ D 0.D0, 15.D-3, 0.D0, 10.D0, -1.D0, 0.D0, -1.D-4,
+ E 0.D0, 1.D0,
+ F 0.D0,0.D0, 6144.D-5, 10.D0, -1.D0, 4096.D0, -1.D6,
+ G 0.D0, 1.D0,
+ H 0.D0,0.D0,15.D0,10.D0,-1.D0, 5.D-5, 0.D0,1.D0,0.D0,
+ I 0.D0,0.D0, 15.D0, 10.D0, -1. D0, 5.D5, -4096.D0,
+ J 1.D0, 4096.D-6,
+ K 0.D0,0.D0, 7.D0, 4.D0, 0.D0,0.D0, -.5D0, -.25D0, 0.D0/
+* 4096 = 2 ** 12
+ DATA D12 /4096.D0/
+ DTRUE(1,1) = 12.D0 / 130.D0
+ DTRUE(2,1) = 36.D0 / 130.D0
+ DTRUE(7,1) = -1.D0 / 6.D0
+ DTRUE(1,2) = 14.D0 / 75.D0
+ DTRUE(2,2) = 49.D0 / 75.D0
+ DTRUE(9,2) = 1.D0 / 7.D0
+ DTRUE(1,5) = 45.D-11 * (D12 * D12)
+ DTRUE(3,5) = 4.D5 / (3.D0 * D12)
+ DTRUE(6,5) = 1.D0 / D12
+ DTRUE(8,5) = 1.D4 / (3.D0 * D12)
+ DTRUE(1,6) = 4.D10 / (1.5D0 * D12 * D12)
+ DTRUE(2,6) = 2.D-2 / 1.5D0
+ DTRUE(8,6) = 5.D-7 * D12
+ DTRUE(1,7) = 4.D0 / 150.D0
+ DTRUE(2,7) = (2.D-10 / 1.5D0) * (D12 * D12)
+ DTRUE(7,7) = -DTRUE(6,5)
+ DTRUE(9,7) = 1.D4 / D12
+ DTRUE(1,8) = DTRUE(1,7)
+ DTRUE(2,8) = 2.D10 / (1.5D0 * D12 * D12)
+ DTRUE(1,9) = 32.D0 / 7.D0
+ DTRUE(2,9) = -16.D0 / 7.D0
* .. Executable Statements ..
*
* Compute true values which cannot be prestored
@@ -134,6 +223,15 @@
CALL STEST1(SB,DBTRUE(K),DBTRUE(K),SFAC)
CALL STEST1(SC,DC1(K),DC1(K),SFAC)
CALL STEST1(SS,DS1(K),DS1(K),SFAC)
+ ELSEIF (ICASE.EQ.11) THEN
+* .. DROTMG ..
+ DO I=1,4
+ DTEMP(I)= DAB(I,K)
+ DTEMP(I+4) = 0.0
+ END DO
+ DTEMP(9) = 0.0
+ CALL DROTMG(DTEMP(1),DTEMP(2),DTEMP(3),DTEMP(4),DTEMP(5))
+ CALL STEST(9,DTEMP,DTRUE(1,K),DTRUE(1,K),SFAC)
ELSE
WRITE (NOUT,*) ' Shouldn''t be here in CHECK0'
STOP
@@ -148,7 +246,7 @@
* .. Scalar Arguments ..
DOUBLE PRECISION SFAC
* .. Scalars in Common ..
- INTEGER ICASE, INCX, INCY, MODE, N
+ INTEGER ICASE, INCX, INCY, N
LOGICAL PASS
* .. Local Scalars ..
INTEGER I, LEN, NP1
@@ -165,7 +263,7 @@
* .. Intrinsic Functions ..
INTRINSIC MAX
* .. Common blocks ..
- COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS
+ COMMON /COMBLA/ICASE, N, INCX, INCY, PASS
* .. Data statements ..
DATA SA/0.3D0, -1.0D0, 0.0D0, 1.0D0, 0.3D0, 0.3D0,
+ 0.3D0, 0.3D0, 0.3D0, 0.3D0/
@@ -212,11 +310,11 @@
IF (ICASE.EQ.7) THEN
* .. DNRM2 ..
STEMP(1) = DTRUE1(NP1)
- CALL STEST1(DNRM2(N,SX,INCX),STEMP,STEMP,SFAC)
+ CALL STEST1(DNRM2(N,SX,INCX),STEMP(1),STEMP,SFAC)
ELSE IF (ICASE.EQ.8) THEN
* .. DASUM ..
STEMP(1) = DTRUE3(NP1)
- CALL STEST1(DASUM(N,SX,INCX),STEMP,STEMP,SFAC)
+ CALL STEST1(DASUM(N,SX,INCX),STEMP(1),STEMP,SFAC)
ELSE IF (ICASE.EQ.9) THEN
* .. DSCAL ..
CALL DSCAL(N,SA((INCX-1)*5+NP1),SX,INCX)
@@ -242,27 +340,39 @@
* .. Scalar Arguments ..
DOUBLE PRECISION SFAC
* .. Scalars in Common ..
- INTEGER ICASE, INCX, INCY, MODE, N
+ INTEGER ICASE, INCX, INCY, N
LOGICAL PASS
* .. Local Scalars ..
- DOUBLE PRECISION SA, SC, SS
- INTEGER I, J, KI, KN, KSIZE, LENX, LENY, MX, MY
+ DOUBLE PRECISION SA
+ INTEGER I, J, KI, KN, KNI, KPAR, KSIZE, LENX, LENY,
+ $ MX, MY
* .. Local Arrays ..
DOUBLE PRECISION DT10X(7,4,4), DT10Y(7,4,4), DT7(4,4),
- + DT8(7,4,4), DT9X(7,4,4), DT9Y(7,4,4), DX1(7),
- + DY1(7), SSIZE1(4), SSIZE2(14,2), STX(7), STY(7),
- + SX(7), SY(7)
+ $ DT8(7,4,4), DX1(7),
+ $ DY1(7), SSIZE1(4), SSIZE2(14,2), SSIZE(7),
+ $ STX(7), STY(7), SX(7), SY(7),
+ $ DPAR(5,4), DT19X(7,4,16),DT19XA(7,4,4),
+ $ DT19XB(7,4,4), DT19XC(7,4,4),DT19XD(7,4,4),
+ $ DT19Y(7,4,16), DT19YA(7,4,4),DT19YB(7,4,4),
+ $ DT19YC(7,4,4), DT19YD(7,4,4), DTEMP(5)
INTEGER INCXS(4), INCYS(4), LENS(4,2), NS(4)
* .. External Functions ..
- DOUBLE PRECISION DDOT
- EXTERNAL DDOT
+ DOUBLE PRECISION DDOT, DSDOT
+ EXTERNAL DDOT, DSDOT
* .. External Subroutines ..
- EXTERNAL DAXPY, DCOPY, DSWAP, STEST, STEST1
+ EXTERNAL DAXPY, DCOPY, DROTM, DSWAP, STEST, STEST1
* .. Intrinsic Functions ..
INTRINSIC ABS, MIN
* .. Common blocks ..
- COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS
+ COMMON /COMBLA/ICASE, N, INCX, INCY, PASS
* .. Data statements ..
+ EQUIVALENCE (DT19X(1,1,1),DT19XA(1,1,1)),(DT19X(1,1,5),
+ A DT19XB(1,1,1)),(DT19X(1,1,9),DT19XC(1,1,1)),
+ B (DT19X(1,1,13),DT19XD(1,1,1))
+ EQUIVALENCE (DT19Y(1,1,1),DT19YA(1,1,1)),(DT19Y(1,1,5),
+ A DT19YB(1,1,1)),(DT19Y(1,1,9),DT19YC(1,1,1)),
+ B (DT19Y(1,1,13),DT19YD(1,1,1))
+
DATA SA/0.3D0/
DATA INCXS/1, 2, -2, -1/
DATA INCYS/1, -2, 1, -2/
@@ -272,7 +382,6 @@
+ -0.4D0/
DATA DY1/0.5D0, -0.9D0, 0.3D0, 0.7D0, -0.6D0, 0.2D0,
+ 0.8D0/
- DATA SC, SS/0.8D0, 0.6D0/
DATA DT7/0.0D0, 0.30D0, 0.21D0, 0.62D0, 0.0D0,
+ 0.30D0, -0.07D0, 0.85D0, 0.0D0, 0.30D0, -0.79D0,
+ -0.74D0, 0.0D0, 0.30D0, 0.33D0, 1.27D0/
@@ -295,44 +404,6 @@
+ 0.0D0, 0.68D0, -0.9D0, 0.33D0, 0.0D0, 0.0D0,
+ 0.0D0, 0.0D0, 0.68D0, -0.9D0, 0.33D0, 0.7D0,
+ -0.75D0, 0.2D0, 1.04D0/
- DATA DT9X/0.6D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0,
- + 0.0D0, 0.78D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0,
- + 0.0D0, 0.0D0, 0.78D0, -0.46D0, 0.0D0, 0.0D0,
- + 0.0D0, 0.0D0, 0.0D0, 0.78D0, -0.46D0, -0.22D0,
- + 1.06D0, 0.0D0, 0.0D0, 0.0D0, 0.6D0, 0.0D0,
- + 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.78D0,
- + 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0,
- + 0.66D0, 0.1D0, -0.1D0, 0.0D0, 0.0D0, 0.0D0,
- + 0.0D0, 0.96D0, 0.1D0, -0.76D0, 0.8D0, 0.90D0,
- + -0.3D0, -0.02D0, 0.6D0, 0.0D0, 0.0D0, 0.0D0,
- + 0.0D0, 0.0D0, 0.0D0, 0.78D0, 0.0D0, 0.0D0,
- + 0.0D0, 0.0D0, 0.0D0, 0.0D0, -0.06D0, 0.1D0,
- + -0.1D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.90D0,
- + 0.1D0, -0.22D0, 0.8D0, 0.18D0, -0.3D0, -0.02D0,
- + 0.6D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0,
- + 0.78D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0,
- + 0.0D0, 0.78D0, 0.26D0, 0.0D0, 0.0D0, 0.0D0,
- + 0.0D0, 0.0D0, 0.78D0, 0.26D0, -0.76D0, 1.12D0,
- + 0.0D0, 0.0D0, 0.0D0/
- DATA DT9Y/0.5D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0,
- + 0.0D0, 0.04D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0,
- + 0.0D0, 0.0D0, 0.04D0, -0.78D0, 0.0D0, 0.0D0,
- + 0.0D0, 0.0D0, 0.0D0, 0.04D0, -0.78D0, 0.54D0,
- + 0.08D0, 0.0D0, 0.0D0, 0.0D0, 0.5D0, 0.0D0,
- + 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.04D0,
- + 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.7D0,
- + -0.9D0, -0.12D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0,
- + 0.64D0, -0.9D0, -0.30D0, 0.7D0, -0.18D0, 0.2D0,
- + 0.28D0, 0.5D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0,
- + 0.0D0, 0.0D0, 0.04D0, 0.0D0, 0.0D0, 0.0D0,
- + 0.0D0, 0.0D0, 0.0D0, 0.7D0, -1.08D0, 0.0D0,
- + 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.64D0, -1.26D0,
- + 0.54D0, 0.20D0, 0.0D0, 0.0D0, 0.0D0, 0.5D0,
- + 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0,
- + 0.04D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0,
- + 0.0D0, 0.04D0, -0.9D0, 0.18D0, 0.0D0, 0.0D0,
- + 0.0D0, 0.0D0, 0.04D0, -0.9D0, 0.18D0, 0.7D0,
- + -0.18D0, 0.2D0, 0.16D0/
DATA DT10X/0.6D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0,
+ 0.0D0, 0.5D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0,
+ 0.0D0, 0.5D0, -0.9D0, 0.0D0, 0.0D0, 0.0D0,
@@ -375,6 +446,150 @@
+ 0.0D0, 1.17D0, 1.17D0, 1.17D0, 1.17D0, 1.17D0,
+ 1.17D0, 1.17D0, 1.17D0, 1.17D0, 1.17D0, 1.17D0,
+ 1.17D0, 1.17D0, 1.17D0/
+*
+* FOR DROTM
+*
+ DATA DPAR/-2.D0, 0.D0,0.D0,0.D0,0.D0,
+ A -1.D0, 2.D0, -3.D0, -4.D0, 5.D0,
+ B 0.D0, 0.D0, 2.D0, -3.D0, 0.D0,
+ C 1.D0, 5.D0, 2.D0, 0.D0, -4.D0/
+* TRUE X RESULTS F0R ROTATIONS DROTM
+ DATA DT19XA/.6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ A .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ B .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ C .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ D .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ E -.8D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ F -.9D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ G 3.5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ H .6D0, .1D0, 0.D0,0.D0,0.D0,0.D0,0.D0,
+ I -.8D0, 3.8D0, 0.D0,0.D0,0.D0,0.D0,0.D0,
+ J -.9D0, 2.8D0, 0.D0,0.D0,0.D0,0.D0,0.D0,
+ K 3.5D0, -.4D0, 0.D0,0.D0,0.D0,0.D0,0.D0,
+ L .6D0, .1D0, -.5D0, .8D0, 0.D0,0.D0,0.D0,
+ M -.8D0, 3.8D0, -2.2D0, -1.2D0, 0.D0,0.D0,0.D0,
+ N -.9D0, 2.8D0, -1.4D0, -1.3D0, 0.D0,0.D0,0.D0,
+ O 3.5D0, -.4D0, -2.2D0, 4.7D0, 0.D0,0.D0,0.D0/
+*
+ DATA DT19XB/.6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ A .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ B .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ C .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ D .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ E -.8D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ F -.9D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ G 3.5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ H .6D0, .1D0, -.5D0, 0.D0,0.D0,0.D0,0.D0,
+ I 0.D0, .1D0, -3.0D0, 0.D0,0.D0,0.D0,0.D0,
+ J -.3D0, .1D0, -2.0D0, 0.D0,0.D0,0.D0,0.D0,
+ K 3.3D0, .1D0, -2.0D0, 0.D0,0.D0,0.D0,0.D0,
+ L .6D0, .1D0, -.5D0, .8D0, .9D0, -.3D0, -.4D0,
+ M -2.0D0, .1D0, 1.4D0, .8D0, .6D0, -.3D0, -2.8D0,
+ N -1.8D0, .1D0, 1.3D0, .8D0, 0.D0, -.3D0, -1.9D0,
+ O 3.8D0, .1D0, -3.1D0, .8D0, 4.8D0, -.3D0, -1.5D0 /
+*
+ DATA DT19XC/.6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ A .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ B .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ C .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ D .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ E -.8D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ F -.9D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ G 3.5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ H .6D0, .1D0, -.5D0, 0.D0,0.D0,0.D0,0.D0,
+ I 4.8D0, .1D0, -3.0D0, 0.D0,0.D0,0.D0,0.D0,
+ J 3.3D0, .1D0, -2.0D0, 0.D0,0.D0,0.D0,0.D0,
+ K 2.1D0, .1D0, -2.0D0, 0.D0,0.D0,0.D0,0.D0,
+ L .6D0, .1D0, -.5D0, .8D0, .9D0, -.3D0, -.4D0,
+ M -1.6D0, .1D0, -2.2D0, .8D0, 5.4D0, -.3D0, -2.8D0,
+ N -1.5D0, .1D0, -1.4D0, .8D0, 3.6D0, -.3D0, -1.9D0,
+ O 3.7D0, .1D0, -2.2D0, .8D0, 3.6D0, -.3D0, -1.5D0 /
+*
+ DATA DT19XD/.6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ A .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ B .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ C .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ D .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ E -.8D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ F -.9D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ G 3.5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ H .6D0, .1D0, 0.D0,0.D0,0.D0,0.D0,0.D0,
+ I -.8D0, -1.0D0, 0.D0,0.D0,0.D0,0.D0,0.D0,
+ J -.9D0, -.8D0, 0.D0,0.D0,0.D0,0.D0,0.D0,
+ K 3.5D0, .8D0, 0.D0,0.D0,0.D0,0.D0,0.D0,
+ L .6D0, .1D0, -.5D0, .8D0, 0.D0,0.D0,0.D0,
+ M -.8D0, -1.0D0, 1.4D0, -1.6D0, 0.D0,0.D0,0.D0,
+ N -.9D0, -.8D0, 1.3D0, -1.6D0, 0.D0,0.D0,0.D0,
+ O 3.5D0, .8D0, -3.1D0, 4.8D0, 0.D0,0.D0,0.D0/
+* TRUE Y RESULTS FOR ROTATIONS DROTM
+ DATA DT19YA/.5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ A .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ B .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ C .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ D .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ E .7D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ F 1.7D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ G -2.6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ H .5D0, -.9D0, 0.D0,0.D0,0.D0,0.D0,0.D0,
+ I .7D0, -4.8D0, 0.D0,0.D0,0.D0,0.D0,0.D0,
+ J 1.7D0, -.7D0, 0.D0,0.D0,0.D0,0.D0,0.D0,
+ K -2.6D0, 3.5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,
+ L .5D0, -.9D0, .3D0, .7D0, 0.D0,0.D0,0.D0,
+ M .7D0, -4.8D0, 3.0D0, 1.1D0, 0.D0,0.D0,0.D0,
+ N 1.7D0, -.7D0, -.7D0, 2.3D0, 0.D0,0.D0,0.D0,
+ O -2.6D0, 3.5D0, -.7D0, -3.6D0, 0.D0,0.D0,0.D0/
+*
+ DATA DT19YB/.5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ A .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ B .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ C .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ D .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ E .7D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ F 1.7D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ G -2.6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ H .5D0, -.9D0, .3D0, 0.D0,0.D0,0.D0,0.D0,
+ I 4.0D0, -.9D0, -.3D0, 0.D0,0.D0,0.D0,0.D0,
+ J -.5D0, -.9D0, 1.5D0, 0.D0,0.D0,0.D0,0.D0,
+ K -1.5D0, -.9D0, -1.8D0, 0.D0,0.D0,0.D0,0.D0,
+ L .5D0, -.9D0, .3D0, .7D0, -.6D0, .2D0, .8D0,
+ M 3.7D0, -.9D0, -1.2D0, .7D0, -1.5D0, .2D0, 2.2D0,
+ N -.3D0, -.9D0, 2.1D0, .7D0, -1.6D0, .2D0, 2.0D0,
+ O -1.6D0, -.9D0, -2.1D0, .7D0, 2.9D0, .2D0, -3.8D0 /
+*
+ DATA DT19YC/.5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ A .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ B .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ C .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ D .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ E .7D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ F 1.7D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ G -2.6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ H .5D0, -.9D0, 0.D0,0.D0,0.D0,0.D0,0.D0,
+ I 4.0D0, -6.3D0, 0.D0,0.D0,0.D0,0.D0,0.D0,
+ J -.5D0, .3D0, 0.D0,0.D0,0.D0,0.D0,0.D0,
+ K -1.5D0, 3.0D0, 0.D0,0.D0,0.D0,0.D0,0.D0,
+ L .5D0, -.9D0, .3D0, .7D0, 0.D0,0.D0,0.D0,
+ M 3.7D0, -7.2D0, 3.0D0, 1.7D0, 0.D0,0.D0,0.D0,
+ N -.3D0, .9D0, -.7D0, 1.9D0, 0.D0,0.D0,0.D0,
+ O -1.6D0, 2.7D0, -.7D0, -3.4D0, 0.D0,0.D0,0.D0/
+*
+ DATA DT19YD/.5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ A .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ B .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ C .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ D .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ E .7D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ F 1.7D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ G -2.6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
+ H .5D0, -.9D0, .3D0, 0.D0,0.D0,0.D0,0.D0,
+ I .7D0, -.9D0, 1.2D0, 0.D0,0.D0,0.D0,0.D0,
+ J 1.7D0, -.9D0, .5D0, 0.D0,0.D0,0.D0,0.D0,
+ K -2.6D0, -.9D0, -1.3D0, 0.D0,0.D0,0.D0,0.D0,
+ L .5D0, -.9D0, .3D0, .7D0, -.6D0, .2D0, .8D0,
+ M .7D0, -.9D0, 1.2D0, .7D0, -1.5D0, .2D0, 1.6D0,
+ N 1.7D0, -.9D0, .5D0, .7D0, -1.6D0, .2D0, 2.4D0,
+ O -2.6D0, -.9D0, -1.3D0, .7D0, 2.9D0, .2D0, -4.0D0 /
+*
* .. Executable Statements ..
*
DO 120 KI = 1, 4
@@ -421,6 +636,39 @@
80 CONTINUE
CALL STEST(LENX,SX,STX,SSIZE2(1,1),1.0D0)
CALL STEST(LENY,SY,STY,SSIZE2(1,1),1.0D0)
+ ELSE IF (ICASE.EQ.12) THEN
+* .. DROTM ..
+ KNI=KN+4*(KI-1)
+ DO KPAR=1,4
+ DO I=1,7
+ SX(I) = DX1(I)
+ SY(I) = DY1(I)
+ STX(I)= DT19X(I,KPAR,KNI)
+ STY(I)= DT19Y(I,KPAR,KNI)
+ END DO
+*
+ DO I=1,5
+ DTEMP(I) = DPAR(I,KPAR)
+ END DO
+*
+ DO I=1,LENX
+ SSIZE(I)=STX(I)
+ END DO
+* SEE REMARK ABOVE ABOUT DT11X(1,2,7)
+* AND DT11X(5,3,8).
+ IF ((KPAR .EQ. 2) .AND. (KNI .EQ. 7))
+ $ SSIZE(1) = 2.4D0
+ IF ((KPAR .EQ. 3) .AND. (KNI .EQ. 8))
+ $ SSIZE(5) = 1.8D0
+*
+ CALL DROTM(N,SX,INCX,SY,INCY,DTEMP)
+ CALL STEST(LENX,SX,STX,SSIZE,SFAC)
+ CALL STEST(LENY,SY,STY,STY,SFAC)
+ END DO
+ ELSE IF (ICASE.EQ.13) THEN
+* .. DSDOT ..
+ CALL TESTDSDOT(REAL(DSDOT(N,REAL(SX),INCX,REAL(SY),INCY)),
+ $ REAL(DT7(KN,KI)),REAL(SSIZE1(KN)), .3125E-1)
ELSE
WRITE (NOUT,*) ' Shouldn''t be here in CHECK2'
STOP
@@ -436,10 +684,10 @@
* .. Scalar Arguments ..
DOUBLE PRECISION SFAC
* .. Scalars in Common ..
- INTEGER ICASE, INCX, INCY, MODE, N
+ INTEGER ICASE, INCX, INCY, N
LOGICAL PASS
* .. Local Scalars ..
- DOUBLE PRECISION SA, SC, SS
+ DOUBLE PRECISION SC, SS
INTEGER I, K, KI, KN, KSIZE, LENX, LENY, MX, MY
* .. Local Arrays ..
DOUBLE PRECISION COPYX(5), COPYY(5), DT9X(7,4,4), DT9Y(7,4,4),
@@ -454,9 +702,8 @@
* .. Intrinsic Functions ..
INTRINSIC ABS, MIN
* .. Common blocks ..
- COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS
+ COMMON /COMBLA/ICASE, N, INCX, INCY, PASS
* .. Data statements ..
- DATA SA/0.3D0/
DATA INCXS/1, 2, -2, -1/
DATA INCYS/1, -2, 1, -2/
DATA LENS/1, 1, 2, 4, 1, 1, 3, 7/
@@ -647,14 +894,15 @@
*
* .. Parameters ..
INTEGER NOUT
- PARAMETER (NOUT=6)
+ DOUBLE PRECISION ZERO
+ PARAMETER (NOUT=6, ZERO=0.0D0)
* .. Scalar Arguments ..
DOUBLE PRECISION SFAC
INTEGER LEN
* .. Array Arguments ..
DOUBLE PRECISION SCOMP(LEN), SSIZE(LEN), STRUE(LEN)
* .. Scalars in Common ..
- INTEGER ICASE, INCX, INCY, MODE, N
+ INTEGER ICASE, INCX, INCY, N
LOGICAL PASS
* .. Local Scalars ..
DOUBLE PRECISION SD
@@ -665,12 +913,12 @@
* .. Intrinsic Functions ..
INTRINSIC ABS
* .. Common blocks ..
- COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS
+ COMMON /COMBLA/ICASE, N, INCX, INCY, PASS
* .. Executable Statements ..
*
DO 40 I = 1, LEN
SD = SCOMP(I) - STRUE(I)
- IF (SDIFF(ABS(SSIZE(I))+ABS(SFAC*SD),ABS(SSIZE(I))).EQ.0.0D0)
+ IF (ABS(SFAC*SD) .LE. ABS(SSIZE(I))*EPSILON(ZERO))
+ GO TO 40
*
* HERE SCOMP(I) IS NOT CLOSE TO STRUE(I).
@@ -680,16 +928,64 @@
PASS = .FALSE.
WRITE (NOUT,99999)
WRITE (NOUT,99998)
- 20 WRITE (NOUT,99997) ICASE, N, INCX, INCY, MODE, I, SCOMP(I),
+ 20 WRITE (NOUT,99997) ICASE, N, INCX, INCY, I, SCOMP(I),
+ STRUE(I), SD, SSIZE(I)
40 CONTINUE
RETURN
*
99999 FORMAT (' FAIL')
-99998 FORMAT (/' CASE N INCX INCY MODE I ',
+99998 FORMAT (/' CASE N INCX INCY I ',
+ + ' COMP(I) TRUE(I) DIFFERENCE',
+ + ' SIZE(I)',/1X)
+99997 FORMAT (1X,I4,I3,2I5,I3,2D36.8,2D12.4)
+ END
+ SUBROUTINE TESTDSDOT(SCOMP,STRUE,SSIZE,SFAC)
+* ********************************* STEST **************************
+*
+* THIS SUBR COMPARES ARRAYS SCOMP() AND STRUE() OF LENGTH LEN TO
+* SEE IF THE TERM BY TERM DIFFERENCES, MULTIPLIED BY SFAC, ARE
+* NEGLIGIBLE.
+*
+* C. L. LAWSON, JPL, 1974 DEC 10
+*
+* .. Parameters ..
+ INTEGER NOUT
+ REAL ZERO
+ PARAMETER (NOUT=6, ZERO=0.0E0)
+* .. Scalar Arguments ..
+ REAL SFAC, SCOMP, SSIZE, STRUE
+* .. Scalars in Common ..
+ INTEGER ICASE, INCX, INCY, N
+ LOGICAL PASS
+* .. Local Scalars ..
+ REAL SD
+* .. Intrinsic Functions ..
+ INTRINSIC ABS
+* .. Common blocks ..
+ COMMON /COMBLA/ICASE, N, INCX, INCY, PASS
+* .. Executable Statements ..
+*
+ SD = SCOMP - STRUE
+ IF (ABS(SFAC*SD) .LE. ABS(SSIZE) * EPSILON(ZERO))
+ + GO TO 40
+*
+* HERE SCOMP(I) IS NOT CLOSE TO STRUE(I).
+*
+ IF ( .NOT. PASS) GO TO 20
+* PRINT FAIL MESSAGE AND HEADER.
+ PASS = .FALSE.
+ WRITE (NOUT,99999)
+ WRITE (NOUT,99998)
+ 20 WRITE (NOUT,99997) ICASE, N, INCX, INCY, SCOMP,
+ + STRUE, SD, SSIZE
+ 40 CONTINUE
+ RETURN
+*
+99999 FORMAT (' FAIL')
+99998 FORMAT (/' CASE N INCX INCY ',
+ ' COMP(I) TRUE(I) DIFFERENCE',
+ ' SIZE(I)',/1X)
-99997 FORMAT (1X,I4,I3,3I5,I3,2D36.8,2D12.4)
+99997 FORMAT (1X,I4,I3,1I5,I3,2E36.8,2E12.4)
END
SUBROUTINE STEST1(SCOMP1,STRUE1,SSIZE,SFAC)
* ************************* STEST1 *****************************
@@ -739,12 +1035,12 @@
* .. Scalar Arguments ..
INTEGER ICOMP, ITRUE
* .. Scalars in Common ..
- INTEGER ICASE, INCX, INCY, MODE, N
+ INTEGER ICASE, INCX, INCY, N
LOGICAL PASS
* .. Local Scalars ..
INTEGER ID
* .. Common blocks ..
- COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS
+ COMMON /COMBLA/ICASE, N, INCX, INCY, PASS
* .. Executable Statements ..
*
IF (ICOMP.EQ.ITRUE) GO TO 40
@@ -757,13 +1053,13 @@
WRITE (NOUT,99999)
WRITE (NOUT,99998)
20 ID = ICOMP - ITRUE
- WRITE (NOUT,99997) ICASE, N, INCX, INCY, MODE, ICOMP, ITRUE, ID
+ WRITE (NOUT,99997) ICASE, N, INCX, INCY, ICOMP, ITRUE, ID
40 CONTINUE
RETURN
*
99999 FORMAT (' FAIL')
-99998 FORMAT (/' CASE N INCX INCY MODE ',
+99998 FORMAT (/' CASE N INCX INCY ',
+ ' COMP TRUE DIFFERENCE',
+ /1X)
-99997 FORMAT (1X,I4,I3,3I5,2I36,I12)
+99997 FORMAT (1X,I4,I3,2I5,2I36,I12)
END
diff --git a/blas/testing/sblat1.f b/blas/testing/sblat1.f
index a982d1852..6657c2693 100644
--- a/blas/testing/sblat1.f
+++ b/blas/testing/sblat1.f
@@ -1,12 +1,54 @@
+*> \brief \b SBLAT1
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+* Definition:
+* ===========
+*
+* PROGRAM SBLAT1
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> Test program for the REAL Level 1 BLAS.
+*>
+*> Based upon the original BLAS test routine together with:
+*> F06EAF Example Program Text
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date April 2012
+*
+*> \ingroup single_blas_testing
+*
+* =====================================================================
PROGRAM SBLAT1
-* Test program for the REAL Level 1 BLAS.
-* Based upon the original BLAS test routine together with:
-* F06EAF Example Program Text
+*
+* -- Reference BLAS test routine (version 3.4.1) --
+* -- Reference BLAS is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* April 2012
+*
+* =====================================================================
+*
* .. Parameters ..
INTEGER NOUT
PARAMETER (NOUT=6)
* .. Scalars in Common ..
- INTEGER ICASE, INCX, INCY, MODE, N
+ INTEGER ICASE, INCX, INCY, N
LOGICAL PASS
* .. Local Scalars ..
REAL SFAC
@@ -14,31 +56,30 @@
* .. External Subroutines ..
EXTERNAL CHECK0, CHECK1, CHECK2, CHECK3, HEADER
* .. Common blocks ..
- COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS
+ COMMON /COMBLA/ICASE, N, INCX, INCY, PASS
* .. Data statements ..
DATA SFAC/9.765625E-4/
* .. Executable Statements ..
WRITE (NOUT,99999)
- DO 20 IC = 1, 10
+ DO 20 IC = 1, 13
ICASE = IC
CALL HEADER
*
-* .. Initialize PASS, INCX, INCY, and MODE for a new case. ..
-* .. the value 9999 for INCX, INCY or MODE will appear in the ..
+* .. Initialize PASS, INCX, and INCY for a new case. ..
+* .. the value 9999 for INCX or INCY will appear in the ..
* .. detailed output, if any, for cases that do not involve ..
* .. these parameters ..
*
PASS = .TRUE.
INCX = 9999
INCY = 9999
- MODE = 9999
- IF (ICASE.EQ.3) THEN
+ IF (ICASE.EQ.3 .OR. ICASE.EQ.11) THEN
CALL CHECK0(SFAC)
ELSE IF (ICASE.EQ.7 .OR. ICASE.EQ.8 .OR. ICASE.EQ.9 .OR.
+ ICASE.EQ.10) THEN
CALL CHECK1(SFAC)
ELSE IF (ICASE.EQ.1 .OR. ICASE.EQ.2 .OR. ICASE.EQ.5 .OR.
- + ICASE.EQ.6) THEN
+ + ICASE.EQ.6 .OR. ICASE.EQ.12 .OR. ICASE.EQ.13) THEN
CALL CHECK2(SFAC)
ELSE IF (ICASE.EQ.4) THEN
CALL CHECK3(SFAC)
@@ -56,12 +97,12 @@
INTEGER NOUT
PARAMETER (NOUT=6)
* .. Scalars in Common ..
- INTEGER ICASE, INCX, INCY, MODE, N
+ INTEGER ICASE, INCX, INCY, N
LOGICAL PASS
* .. Local Arrays ..
- CHARACTER*6 L(10)
+ CHARACTER*6 L(13)
* .. Common blocks ..
- COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS
+ COMMON /COMBLA/ICASE, N, INCX, INCY, PASS
* .. Data statements ..
DATA L(1)/' SDOT '/
DATA L(2)/'SAXPY '/
@@ -73,6 +114,9 @@
DATA L(8)/'SASUM '/
DATA L(9)/'SSCAL '/
DATA L(10)/'ISAMAX'/
+ DATA L(11)/'SROTMG'/
+ DATA L(12)/'SROTM '/
+ DATA L(13)/'SDSDOT'/
* .. Executable Statements ..
WRITE (NOUT,99999) ICASE, L(ICASE)
RETURN
@@ -86,18 +130,18 @@
* .. Scalar Arguments ..
REAL SFAC
* .. Scalars in Common ..
- INTEGER ICASE, INCX, INCY, MODE, N
+ INTEGER ICASE, INCX, INCY, N
LOGICAL PASS
* .. Local Scalars ..
REAL D12, SA, SB, SC, SS
- INTEGER K
+ INTEGER I, K
* .. Local Arrays ..
REAL DA1(8), DATRUE(8), DB1(8), DBTRUE(8), DC1(8),
- + DS1(8)
+ + DS1(8), DAB(4,9), DTEMP(9), DTRUE(9,9)
* .. External Subroutines ..
- EXTERNAL SROTG, STEST1
+ EXTERNAL SROTG, SROTMG, STEST1
* .. Common blocks ..
- COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS
+ COMMON /COMBLA/ICASE, N, INCX, INCY, PASS
* .. Data statements ..
DATA DA1/0.3E0, 0.4E0, -0.3E0, -0.4E0, -0.3E0, 0.0E0,
+ 0.0E0, 1.0E0/
@@ -111,7 +155,52 @@
+ 0.0E0, 1.0E0, 1.0E0/
DATA DBTRUE/0.0E0, 0.6E0, 0.0E0, -0.6E0, 0.0E0,
+ 0.0E0, 1.0E0, 0.0E0/
- DATA D12/4096.0E0/
+* INPUT FOR MODIFIED GIVENS
+ DATA DAB/ .1E0,.3E0,1.2E0,.2E0,
+ A .7E0, .2E0, .6E0, 4.2E0,
+ B 0.E0,0.E0,0.E0,0.E0,
+ C 4.E0, -1.E0, 2.E0, 4.E0,
+ D 6.E-10, 2.E-2, 1.E5, 10.E0,
+ E 4.E10, 2.E-2, 1.E-5, 10.E0,
+ F 2.E-10, 4.E-2, 1.E5, 10.E0,
+ G 2.E10, 4.E-2, 1.E-5, 10.E0,
+ H 4.E0, -2.E0, 8.E0, 4.E0 /
+* TRUE RESULTS FOR MODIFIED GIVENS
+ DATA DTRUE/0.E0,0.E0, 1.3E0, .2E0, 0.E0,0.E0,0.E0, .5E0, 0.E0,
+ A 0.E0,0.E0, 4.5E0, 4.2E0, 1.E0, .5E0, 0.E0,0.E0,0.E0,
+ B 0.E0,0.E0,0.E0,0.E0, -2.E0, 0.E0,0.E0,0.E0,0.E0,
+ C 0.E0,0.E0,0.E0, 4.E0, -1.E0, 0.E0,0.E0,0.E0,0.E0,
+ D 0.E0, 15.E-3, 0.E0, 10.E0, -1.E0, 0.E0, -1.E-4,
+ E 0.E0, 1.E0,
+ F 0.E0,0.E0, 6144.E-5, 10.E0, -1.E0, 4096.E0, -1.E6,
+ G 0.E0, 1.E0,
+ H 0.E0,0.E0,15.E0,10.E0,-1.E0, 5.E-5, 0.E0,1.E0,0.E0,
+ I 0.E0,0.E0, 15.E0, 10.E0, -1. E0, 5.E5, -4096.E0,
+ J 1.E0, 4096.E-6,
+ K 0.E0,0.E0, 7.E0, 4.E0, 0.E0,0.E0, -.5E0, -.25E0, 0.E0/
+* 4096 = 2 ** 12
+ DATA D12 /4096.E0/
+ DTRUE(1,1) = 12.E0 / 130.E0
+ DTRUE(2,1) = 36.E0 / 130.E0
+ DTRUE(7,1) = -1.E0 / 6.E0
+ DTRUE(1,2) = 14.E0 / 75.E0
+ DTRUE(2,2) = 49.E0 / 75.E0
+ DTRUE(9,2) = 1.E0 / 7.E0
+ DTRUE(1,5) = 45.E-11 * (D12 * D12)
+ DTRUE(3,5) = 4.E5 / (3.E0 * D12)
+ DTRUE(6,5) = 1.E0 / D12
+ DTRUE(8,5) = 1.E4 / (3.E0 * D12)
+ DTRUE(1,6) = 4.E10 / (1.5E0 * D12 * D12)
+ DTRUE(2,6) = 2.E-2 / 1.5E0
+ DTRUE(8,6) = 5.E-7 * D12
+ DTRUE(1,7) = 4.E0 / 150.E0
+ DTRUE(2,7) = (2.E-10 / 1.5E0) * (D12 * D12)
+ DTRUE(7,7) = -DTRUE(6,5)
+ DTRUE(9,7) = 1.E4 / D12
+ DTRUE(1,8) = DTRUE(1,7)
+ DTRUE(2,8) = 2.E10 / (1.5E0 * D12 * D12)
+ DTRUE(1,9) = 32.E0 / 7.E0
+ DTRUE(2,9) = -16.E0 / 7.E0
* .. Executable Statements ..
*
* Compute true values which cannot be prestored
@@ -134,6 +223,15 @@
CALL STEST1(SB,DBTRUE(K),DBTRUE(K),SFAC)
CALL STEST1(SC,DC1(K),DC1(K),SFAC)
CALL STEST1(SS,DS1(K),DS1(K),SFAC)
+ ELSEIF (ICASE.EQ.11) THEN
+* .. SROTMG ..
+ DO I=1,4
+ DTEMP(I)= DAB(I,K)
+ DTEMP(I+4) = 0.0
+ END DO
+ DTEMP(9) = 0.0
+ CALL SROTMG(DTEMP(1),DTEMP(2),DTEMP(3),DTEMP(4),DTEMP(5))
+ CALL STEST(9,DTEMP,DTRUE(1,K),DTRUE(1,K),SFAC)
ELSE
WRITE (NOUT,*) ' Shouldn''t be here in CHECK0'
STOP
@@ -148,7 +246,7 @@
* .. Scalar Arguments ..
REAL SFAC
* .. Scalars in Common ..
- INTEGER ICASE, INCX, INCY, MODE, N
+ INTEGER ICASE, INCX, INCY, N
LOGICAL PASS
* .. Local Scalars ..
INTEGER I, LEN, NP1
@@ -165,7 +263,7 @@
* .. Intrinsic Functions ..
INTRINSIC MAX
* .. Common blocks ..
- COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS
+ COMMON /COMBLA/ICASE, N, INCX, INCY, PASS
* .. Data statements ..
DATA SA/0.3E0, -1.0E0, 0.0E0, 1.0E0, 0.3E0, 0.3E0,
+ 0.3E0, 0.3E0, 0.3E0, 0.3E0/
@@ -212,11 +310,11 @@
IF (ICASE.EQ.7) THEN
* .. SNRM2 ..
STEMP(1) = DTRUE1(NP1)
- CALL STEST1(SNRM2(N,SX,INCX),STEMP,STEMP,SFAC)
+ CALL STEST1(SNRM2(N,SX,INCX),STEMP(1),STEMP,SFAC)
ELSE IF (ICASE.EQ.8) THEN
* .. SASUM ..
STEMP(1) = DTRUE3(NP1)
- CALL STEST1(SASUM(N,SX,INCX),STEMP,STEMP,SFAC)
+ CALL STEST1(SASUM(N,SX,INCX),STEMP(1),STEMP,SFAC)
ELSE IF (ICASE.EQ.9) THEN
* .. SSCAL ..
CALL SSCAL(N,SA((INCX-1)*5+NP1),SX,INCX)
@@ -242,27 +340,40 @@
* .. Scalar Arguments ..
REAL SFAC
* .. Scalars in Common ..
- INTEGER ICASE, INCX, INCY, MODE, N
+ INTEGER ICASE, INCX, INCY, N
LOGICAL PASS
* .. Local Scalars ..
- REAL SA, SC, SS
- INTEGER I, J, KI, KN, KSIZE, LENX, LENY, MX, MY
+ REAL SA
+ INTEGER I, J, KI, KN, KNI, KPAR, KSIZE, LENX, LENY,
+ $ MX, MY
* .. Local Arrays ..
REAL DT10X(7,4,4), DT10Y(7,4,4), DT7(4,4),
- + DT8(7,4,4), DT9X(7,4,4), DT9Y(7,4,4), DX1(7),
- + DY1(7), SSIZE1(4), SSIZE2(14,2), STX(7), STY(7),
- + SX(7), SY(7)
+ $ DT8(7,4,4), DX1(7),
+ $ DY1(7), SSIZE1(4), SSIZE2(14,2), SSIZE3(4),
+ $ SSIZE(7), STX(7), STY(7), SX(7), SY(7),
+ $ DPAR(5,4), DT19X(7,4,16),DT19XA(7,4,4),
+ $ DT19XB(7,4,4), DT19XC(7,4,4),DT19XD(7,4,4),
+ $ DT19Y(7,4,16), DT19YA(7,4,4),DT19YB(7,4,4),
+ $ DT19YC(7,4,4), DT19YD(7,4,4), DTEMP(5),
+ $ ST7B(4,4)
INTEGER INCXS(4), INCYS(4), LENS(4,2), NS(4)
* .. External Functions ..
- REAL SDOT
- EXTERNAL SDOT
+ REAL SDOT, SDSDOT
+ EXTERNAL SDOT, SDSDOT
* .. External Subroutines ..
- EXTERNAL SAXPY, SCOPY, SSWAP, STEST, STEST1
+ EXTERNAL SAXPY, SCOPY, SROTM, SSWAP, STEST, STEST1
* .. Intrinsic Functions ..
INTRINSIC ABS, MIN
* .. Common blocks ..
- COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS
+ COMMON /COMBLA/ICASE, N, INCX, INCY, PASS
* .. Data statements ..
+ EQUIVALENCE (DT19X(1,1,1),DT19XA(1,1,1)),(DT19X(1,1,5),
+ A DT19XB(1,1,1)),(DT19X(1,1,9),DT19XC(1,1,1)),
+ B (DT19X(1,1,13),DT19XD(1,1,1))
+ EQUIVALENCE (DT19Y(1,1,1),DT19YA(1,1,1)),(DT19Y(1,1,5),
+ A DT19YB(1,1,1)),(DT19Y(1,1,9),DT19YC(1,1,1)),
+ B (DT19Y(1,1,13),DT19YD(1,1,1))
+
DATA SA/0.3E0/
DATA INCXS/1, 2, -2, -1/
DATA INCYS/1, -2, 1, -2/
@@ -272,10 +383,11 @@
+ -0.4E0/
DATA DY1/0.5E0, -0.9E0, 0.3E0, 0.7E0, -0.6E0, 0.2E0,
+ 0.8E0/
- DATA SC, SS/0.8E0, 0.6E0/
DATA DT7/0.0E0, 0.30E0, 0.21E0, 0.62E0, 0.0E0,
+ 0.30E0, -0.07E0, 0.85E0, 0.0E0, 0.30E0, -0.79E0,
+ -0.74E0, 0.0E0, 0.30E0, 0.33E0, 1.27E0/
+ DATA ST7B/ .1, .4, .31, .72, .1, .4, .03, .95,
+ + .1, .4, -.69, -.64, .1, .4, .43, 1.37/
DATA DT8/0.5E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0,
+ 0.0E0, 0.68E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0,
+ 0.0E0, 0.0E0, 0.68E0, -0.87E0, 0.0E0, 0.0E0,
@@ -295,44 +407,6 @@
+ 0.0E0, 0.68E0, -0.9E0, 0.33E0, 0.0E0, 0.0E0,
+ 0.0E0, 0.0E0, 0.68E0, -0.9E0, 0.33E0, 0.7E0,
+ -0.75E0, 0.2E0, 1.04E0/
- DATA DT9X/0.6E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0,
- + 0.0E0, 0.78E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0,
- + 0.0E0, 0.0E0, 0.78E0, -0.46E0, 0.0E0, 0.0E0,
- + 0.0E0, 0.0E0, 0.0E0, 0.78E0, -0.46E0, -0.22E0,
- + 1.06E0, 0.0E0, 0.0E0, 0.0E0, 0.6E0, 0.0E0,
- + 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.78E0,
- + 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0,
- + 0.66E0, 0.1E0, -0.1E0, 0.0E0, 0.0E0, 0.0E0,
- + 0.0E0, 0.96E0, 0.1E0, -0.76E0, 0.8E0, 0.90E0,
- + -0.3E0, -0.02E0, 0.6E0, 0.0E0, 0.0E0, 0.0E0,
- + 0.0E0, 0.0E0, 0.0E0, 0.78E0, 0.0E0, 0.0E0,
- + 0.0E0, 0.0E0, 0.0E0, 0.0E0, -0.06E0, 0.1E0,
- + -0.1E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.90E0,
- + 0.1E0, -0.22E0, 0.8E0, 0.18E0, -0.3E0, -0.02E0,
- + 0.6E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0,
- + 0.78E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0,
- + 0.0E0, 0.78E0, 0.26E0, 0.0E0, 0.0E0, 0.0E0,
- + 0.0E0, 0.0E0, 0.78E0, 0.26E0, -0.76E0, 1.12E0,
- + 0.0E0, 0.0E0, 0.0E0/
- DATA DT9Y/0.5E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0,
- + 0.0E0, 0.04E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0,
- + 0.0E0, 0.0E0, 0.04E0, -0.78E0, 0.0E0, 0.0E0,
- + 0.0E0, 0.0E0, 0.0E0, 0.04E0, -0.78E0, 0.54E0,
- + 0.08E0, 0.0E0, 0.0E0, 0.0E0, 0.5E0, 0.0E0,
- + 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.04E0,
- + 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.7E0,
- + -0.9E0, -0.12E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0,
- + 0.64E0, -0.9E0, -0.30E0, 0.7E0, -0.18E0, 0.2E0,
- + 0.28E0, 0.5E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0,
- + 0.0E0, 0.0E0, 0.04E0, 0.0E0, 0.0E0, 0.0E0,
- + 0.0E0, 0.0E0, 0.0E0, 0.7E0, -1.08E0, 0.0E0,
- + 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.64E0, -1.26E0,
- + 0.54E0, 0.20E0, 0.0E0, 0.0E0, 0.0E0, 0.5E0,
- + 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0,
- + 0.04E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0,
- + 0.0E0, 0.04E0, -0.9E0, 0.18E0, 0.0E0, 0.0E0,
- + 0.0E0, 0.0E0, 0.04E0, -0.9E0, 0.18E0, 0.7E0,
- + -0.18E0, 0.2E0, 0.16E0/
DATA DT10X/0.6E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0,
+ 0.0E0, 0.5E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0,
+ 0.0E0, 0.5E0, -0.9E0, 0.0E0, 0.0E0, 0.0E0,
@@ -375,6 +449,151 @@
+ 0.0E0, 1.17E0, 1.17E0, 1.17E0, 1.17E0, 1.17E0,
+ 1.17E0, 1.17E0, 1.17E0, 1.17E0, 1.17E0, 1.17E0,
+ 1.17E0, 1.17E0, 1.17E0/
+ DATA SSIZE3/ .1, .4, 1.7, 3.3 /
+*
+* FOR DROTM
+*
+ DATA DPAR/-2.E0, 0.E0,0.E0,0.E0,0.E0,
+ A -1.E0, 2.E0, -3.E0, -4.E0, 5.E0,
+ B 0.E0, 0.E0, 2.E0, -3.E0, 0.E0,
+ C 1.E0, 5.E0, 2.E0, 0.E0, -4.E0/
+* TRUE X RESULTS F0R ROTATIONS DROTM
+ DATA DT19XA/.6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ A .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ B .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ C .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ D .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ E -.8E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ F -.9E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ G 3.5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ H .6E0, .1E0, 0.E0,0.E0,0.E0,0.E0,0.E0,
+ I -.8E0, 3.8E0, 0.E0,0.E0,0.E0,0.E0,0.E0,
+ J -.9E0, 2.8E0, 0.E0,0.E0,0.E0,0.E0,0.E0,
+ K 3.5E0, -.4E0, 0.E0,0.E0,0.E0,0.E0,0.E0,
+ L .6E0, .1E0, -.5E0, .8E0, 0.E0,0.E0,0.E0,
+ M -.8E0, 3.8E0, -2.2E0, -1.2E0, 0.E0,0.E0,0.E0,
+ N -.9E0, 2.8E0, -1.4E0, -1.3E0, 0.E0,0.E0,0.E0,
+ O 3.5E0, -.4E0, -2.2E0, 4.7E0, 0.E0,0.E0,0.E0/
+*
+ DATA DT19XB/.6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ A .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ B .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ C .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ D .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ E -.8E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ F -.9E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ G 3.5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ H .6E0, .1E0, -.5E0, 0.E0,0.E0,0.E0,0.E0,
+ I 0.E0, .1E0, -3.0E0, 0.E0,0.E0,0.E0,0.E0,
+ J -.3E0, .1E0, -2.0E0, 0.E0,0.E0,0.E0,0.E0,
+ K 3.3E0, .1E0, -2.0E0, 0.E0,0.E0,0.E0,0.E0,
+ L .6E0, .1E0, -.5E0, .8E0, .9E0, -.3E0, -.4E0,
+ M -2.0E0, .1E0, 1.4E0, .8E0, .6E0, -.3E0, -2.8E0,
+ N -1.8E0, .1E0, 1.3E0, .8E0, 0.E0, -.3E0, -1.9E0,
+ O 3.8E0, .1E0, -3.1E0, .8E0, 4.8E0, -.3E0, -1.5E0 /
+*
+ DATA DT19XC/.6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ A .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ B .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ C .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ D .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ E -.8E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ F -.9E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ G 3.5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ H .6E0, .1E0, -.5E0, 0.E0,0.E0,0.E0,0.E0,
+ I 4.8E0, .1E0, -3.0E0, 0.E0,0.E0,0.E0,0.E0,
+ J 3.3E0, .1E0, -2.0E0, 0.E0,0.E0,0.E0,0.E0,
+ K 2.1E0, .1E0, -2.0E0, 0.E0,0.E0,0.E0,0.E0,
+ L .6E0, .1E0, -.5E0, .8E0, .9E0, -.3E0, -.4E0,
+ M -1.6E0, .1E0, -2.2E0, .8E0, 5.4E0, -.3E0, -2.8E0,
+ N -1.5E0, .1E0, -1.4E0, .8E0, 3.6E0, -.3E0, -1.9E0,
+ O 3.7E0, .1E0, -2.2E0, .8E0, 3.6E0, -.3E0, -1.5E0 /
+*
+ DATA DT19XD/.6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ A .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ B .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ C .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ D .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ E -.8E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ F -.9E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ G 3.5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ H .6E0, .1E0, 0.E0,0.E0,0.E0,0.E0,0.E0,
+ I -.8E0, -1.0E0, 0.E0,0.E0,0.E0,0.E0,0.E0,
+ J -.9E0, -.8E0, 0.E0,0.E0,0.E0,0.E0,0.E0,
+ K 3.5E0, .8E0, 0.E0,0.E0,0.E0,0.E0,0.E0,
+ L .6E0, .1E0, -.5E0, .8E0, 0.E0,0.E0,0.E0,
+ M -.8E0, -1.0E0, 1.4E0, -1.6E0, 0.E0,0.E0,0.E0,
+ N -.9E0, -.8E0, 1.3E0, -1.6E0, 0.E0,0.E0,0.E0,
+ O 3.5E0, .8E0, -3.1E0, 4.8E0, 0.E0,0.E0,0.E0/
+* TRUE Y RESULTS FOR ROTATIONS DROTM
+ DATA DT19YA/.5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ A .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ B .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ C .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ D .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ E .7E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ F 1.7E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ G -2.6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ H .5E0, -.9E0, 0.E0,0.E0,0.E0,0.E0,0.E0,
+ I .7E0, -4.8E0, 0.E0,0.E0,0.E0,0.E0,0.E0,
+ J 1.7E0, -.7E0, 0.E0,0.E0,0.E0,0.E0,0.E0,
+ K -2.6E0, 3.5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,
+ L .5E0, -.9E0, .3E0, .7E0, 0.E0,0.E0,0.E0,
+ M .7E0, -4.8E0, 3.0E0, 1.1E0, 0.E0,0.E0,0.E0,
+ N 1.7E0, -.7E0, -.7E0, 2.3E0, 0.E0,0.E0,0.E0,
+ O -2.6E0, 3.5E0, -.7E0, -3.6E0, 0.E0,0.E0,0.E0/
+*
+ DATA DT19YB/.5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ A .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ B .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ C .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ D .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ E .7E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ F 1.7E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ G -2.6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ H .5E0, -.9E0, .3E0, 0.E0,0.E0,0.E0,0.E0,
+ I 4.0E0, -.9E0, -.3E0, 0.E0,0.E0,0.E0,0.E0,
+ J -.5E0, -.9E0, 1.5E0, 0.E0,0.E0,0.E0,0.E0,
+ K -1.5E0, -.9E0, -1.8E0, 0.E0,0.E0,0.E0,0.E0,
+ L .5E0, -.9E0, .3E0, .7E0, -.6E0, .2E0, .8E0,
+ M 3.7E0, -.9E0, -1.2E0, .7E0, -1.5E0, .2E0, 2.2E0,
+ N -.3E0, -.9E0, 2.1E0, .7E0, -1.6E0, .2E0, 2.0E0,
+ O -1.6E0, -.9E0, -2.1E0, .7E0, 2.9E0, .2E0, -3.8E0 /
+*
+ DATA DT19YC/.5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ A .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ B .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ C .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ D .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ E .7E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ F 1.7E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ G -2.6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ H .5E0, -.9E0, 0.E0,0.E0,0.E0,0.E0,0.E0,
+ I 4.0E0, -6.3E0, 0.E0,0.E0,0.E0,0.E0,0.E0,
+ J -.5E0, .3E0, 0.E0,0.E0,0.E0,0.E0,0.E0,
+ K -1.5E0, 3.0E0, 0.E0,0.E0,0.E0,0.E0,0.E0,
+ L .5E0, -.9E0, .3E0, .7E0, 0.E0,0.E0,0.E0,
+ M 3.7E0, -7.2E0, 3.0E0, 1.7E0, 0.E0,0.E0,0.E0,
+ N -.3E0, .9E0, -.7E0, 1.9E0, 0.E0,0.E0,0.E0,
+ O -1.6E0, 2.7E0, -.7E0, -3.4E0, 0.E0,0.E0,0.E0/
+*
+ DATA DT19YD/.5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ A .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ B .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ C .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ D .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ E .7E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ F 1.7E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ G -2.6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,
+ H .5E0, -.9E0, .3E0, 0.E0,0.E0,0.E0,0.E0,
+ I .7E0, -.9E0, 1.2E0, 0.E0,0.E0,0.E0,0.E0,
+ J 1.7E0, -.9E0, .5E0, 0.E0,0.E0,0.E0,0.E0,
+ K -2.6E0, -.9E0, -1.3E0, 0.E0,0.E0,0.E0,0.E0,
+ L .5E0, -.9E0, .3E0, .7E0, -.6E0, .2E0, .8E0,
+ M .7E0, -.9E0, 1.2E0, .7E0, -1.5E0, .2E0, 1.6E0,
+ N 1.7E0, -.9E0, .5E0, .7E0, -1.6E0, .2E0, 2.4E0,
+ O -2.6E0, -.9E0, -1.3E0, .7E0, 2.9E0, .2E0, -4.0E0 /
+*
* .. Executable Statements ..
*
DO 120 KI = 1, 4
@@ -421,6 +640,39 @@
80 CONTINUE
CALL STEST(LENX,SX,STX,SSIZE2(1,1),1.0E0)
CALL STEST(LENY,SY,STY,SSIZE2(1,1),1.0E0)
+ ELSEIF (ICASE.EQ.12) THEN
+* .. SROTM ..
+ KNI=KN+4*(KI-1)
+ DO KPAR=1,4
+ DO I=1,7
+ SX(I) = DX1(I)
+ SY(I) = DY1(I)
+ STX(I)= DT19X(I,KPAR,KNI)
+ STY(I)= DT19Y(I,KPAR,KNI)
+ END DO
+*
+ DO I=1,5
+ DTEMP(I) = DPAR(I,KPAR)
+ END DO
+*
+ DO I=1,LENX
+ SSIZE(I)=STX(I)
+ END DO
+* SEE REMARK ABOVE ABOUT DT11X(1,2,7)
+* AND DT11X(5,3,8).
+ IF ((KPAR .EQ. 2) .AND. (KNI .EQ. 7))
+ $ SSIZE(1) = 2.4E0
+ IF ((KPAR .EQ. 3) .AND. (KNI .EQ. 8))
+ $ SSIZE(5) = 1.8E0
+*
+ CALL SROTM(N,SX,INCX,SY,INCY,DTEMP)
+ CALL STEST(LENX,SX,STX,SSIZE,SFAC)
+ CALL STEST(LENY,SY,STY,STY,SFAC)
+ END DO
+ ELSEIF (ICASE.EQ.13) THEN
+* .. SDSROT ..
+ CALL STEST1 (SDSDOT(N,.1,SX,INCX,SY,INCY),
+ $ ST7B(KN,KI),SSIZE3(KN),SFAC)
ELSE
WRITE (NOUT,*) ' Shouldn''t be here in CHECK2'
STOP
@@ -436,10 +688,10 @@
* .. Scalar Arguments ..
REAL SFAC
* .. Scalars in Common ..
- INTEGER ICASE, INCX, INCY, MODE, N
+ INTEGER ICASE, INCX, INCY, N
LOGICAL PASS
* .. Local Scalars ..
- REAL SA, SC, SS
+ REAL SC, SS
INTEGER I, K, KI, KN, KSIZE, LENX, LENY, MX, MY
* .. Local Arrays ..
REAL COPYX(5), COPYY(5), DT9X(7,4,4), DT9Y(7,4,4),
@@ -454,9 +706,8 @@
* .. Intrinsic Functions ..
INTRINSIC ABS, MIN
* .. Common blocks ..
- COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS
+ COMMON /COMBLA/ICASE, N, INCX, INCY, PASS
* .. Data statements ..
- DATA SA/0.3E0/
DATA INCXS/1, 2, -2, -1/
DATA INCYS/1, -2, 1, -2/
DATA LENS/1, 1, 2, 4, 1, 1, 3, 7/
@@ -647,14 +898,15 @@
*
* .. Parameters ..
INTEGER NOUT
- PARAMETER (NOUT=6)
+ REAL ZERO
+ PARAMETER (NOUT=6, ZERO=0.0E0)
* .. Scalar Arguments ..
REAL SFAC
INTEGER LEN
* .. Array Arguments ..
REAL SCOMP(LEN), SSIZE(LEN), STRUE(LEN)
* .. Scalars in Common ..
- INTEGER ICASE, INCX, INCY, MODE, N
+ INTEGER ICASE, INCX, INCY, N
LOGICAL PASS
* .. Local Scalars ..
REAL SD
@@ -665,12 +917,12 @@
* .. Intrinsic Functions ..
INTRINSIC ABS
* .. Common blocks ..
- COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS
+ COMMON /COMBLA/ICASE, N, INCX, INCY, PASS
* .. Executable Statements ..
*
DO 40 I = 1, LEN
SD = SCOMP(I) - STRUE(I)
- IF (SDIFF(ABS(SSIZE(I))+ABS(SFAC*SD),ABS(SSIZE(I))).EQ.0.0E0)
+ IF (ABS(SFAC*SD) .LE. ABS(SSIZE(I))*EPSILON(ZERO))
+ GO TO 40
*
* HERE SCOMP(I) IS NOT CLOSE TO STRUE(I).
@@ -680,16 +932,16 @@
PASS = .FALSE.
WRITE (NOUT,99999)
WRITE (NOUT,99998)
- 20 WRITE (NOUT,99997) ICASE, N, INCX, INCY, MODE, I, SCOMP(I),
+ 20 WRITE (NOUT,99997) ICASE, N, INCX, INCY, I, SCOMP(I),
+ STRUE(I), SD, SSIZE(I)
40 CONTINUE
RETURN
*
99999 FORMAT (' FAIL')
-99998 FORMAT (/' CASE N INCX INCY MODE I ',
+99998 FORMAT (/' CASE N INCX INCY I ',
+ ' COMP(I) TRUE(I) DIFFERENCE',
+ ' SIZE(I)',/1X)
-99997 FORMAT (1X,I4,I3,3I5,I3,2E36.8,2E12.4)
+99997 FORMAT (1X,I4,I3,2I5,I3,2E36.8,2E12.4)
END
SUBROUTINE STEST1(SCOMP1,STRUE1,SSIZE,SFAC)
* ************************* STEST1 *****************************
@@ -739,12 +991,12 @@
* .. Scalar Arguments ..
INTEGER ICOMP, ITRUE
* .. Scalars in Common ..
- INTEGER ICASE, INCX, INCY, MODE, N
+ INTEGER ICASE, INCX, INCY, N
LOGICAL PASS
* .. Local Scalars ..
INTEGER ID
* .. Common blocks ..
- COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS
+ COMMON /COMBLA/ICASE, N, INCX, INCY, PASS
* .. Executable Statements ..
*
IF (ICOMP.EQ.ITRUE) GO TO 40
@@ -757,13 +1009,13 @@
WRITE (NOUT,99999)
WRITE (NOUT,99998)
20 ID = ICOMP - ITRUE
- WRITE (NOUT,99997) ICASE, N, INCX, INCY, MODE, ICOMP, ITRUE, ID
+ WRITE (NOUT,99997) ICASE, N, INCX, INCY, ICOMP, ITRUE, ID
40 CONTINUE
RETURN
*
99999 FORMAT (' FAIL')
-99998 FORMAT (/' CASE N INCX INCY MODE ',
+99998 FORMAT (/' CASE N INCX INCY ',
+ ' COMP TRUE DIFFERENCE',
+ /1X)
-99997 FORMAT (1X,I4,I3,3I5,2I36,I12)
+99997 FORMAT (1X,I4,I3,2I5,2I36,I12)
END
diff --git a/blas/zhpr.f b/blas/zhpr.f
deleted file mode 100644
index 40efbc7d5..000000000
--- a/blas/zhpr.f
+++ /dev/null
@@ -1,220 +0,0 @@
- SUBROUTINE ZHPR(UPLO,N,ALPHA,X,INCX,AP)
-* .. Scalar Arguments ..
- DOUBLE PRECISION ALPHA
- INTEGER INCX,N
- CHARACTER UPLO
-* ..
-* .. Array Arguments ..
- DOUBLE COMPLEX AP(*),X(*)
-* ..
-*
-* Purpose
-* =======
-*
-* ZHPR performs the hermitian rank 1 operation
-*
-* A := alpha*x*conjg( x' ) + A,
-*
-* where alpha is a real scalar, x is an n element vector and A is an
-* n by n hermitian matrix, supplied in packed form.
-*
-* Arguments
-* ==========
-*
-* UPLO - CHARACTER*1.
-* On entry, UPLO specifies whether the upper or lower
-* triangular part of the matrix A is supplied in the packed
-* array AP as follows:
-*
-* UPLO = 'U' or 'u' The upper triangular part of A is
-* supplied in AP.
-*
-* UPLO = 'L' or 'l' The lower triangular part of A is
-* supplied in AP.
-*
-* Unchanged on exit.
-*
-* N - INTEGER.
-* On entry, N specifies the order of the matrix A.
-* N must be at least zero.
-* Unchanged on exit.
-*
-* ALPHA - DOUBLE PRECISION.
-* On entry, ALPHA specifies the scalar alpha.
-* Unchanged on exit.
-*
-* X - COMPLEX*16 array of dimension at least
-* ( 1 + ( n - 1 )*abs( INCX ) ).
-* Before entry, the incremented array X must contain the n
-* element vector x.
-* Unchanged on exit.
-*
-* INCX - INTEGER.
-* On entry, INCX specifies the increment for the elements of
-* X. INCX must not be zero.
-* Unchanged on exit.
-*
-* AP - COMPLEX*16 array of DIMENSION at least
-* ( ( n*( n + 1 ) )/2 ).
-* Before entry with UPLO = 'U' or 'u', the array AP must
-* contain the upper triangular part of the hermitian matrix
-* packed sequentially, column by column, so that AP( 1 )
-* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 1, 2 )
-* and a( 2, 2 ) respectively, and so on. On exit, the array
-* AP is overwritten by the upper triangular part of the
-* updated matrix.
-* Before entry with UPLO = 'L' or 'l', the array AP must
-* contain the lower triangular part of the hermitian matrix
-* packed sequentially, column by column, so that AP( 1 )
-* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 2, 1 )
-* and a( 3, 1 ) respectively, and so on. On exit, the array
-* AP is overwritten by the lower triangular part of the
-* updated matrix.
-* Note that the imaginary parts of the diagonal elements need
-* not be set, they are assumed to be zero, and on exit they
-* are set to zero.
-*
-* Further Details
-* ===============
-*
-* Level 2 Blas routine.
-*
-* -- Written on 22-October-1986.
-* Jack Dongarra, Argonne National Lab.
-* Jeremy Du Croz, Nag Central Office.
-* Sven Hammarling, Nag Central Office.
-* Richard Hanson, Sandia National Labs.
-*
-* =====================================================================
-*
-* .. Parameters ..
- DOUBLE COMPLEX ZERO
- PARAMETER (ZERO= (0.0D+0,0.0D+0))
-* ..
-* .. Local Scalars ..
- DOUBLE COMPLEX TEMP
- INTEGER I,INFO,IX,J,JX,K,KK,KX
-* ..
-* .. External Functions ..
- LOGICAL LSAME
- EXTERNAL LSAME
-* ..
-* .. External Subroutines ..
- EXTERNAL XERBLA
-* ..
-* .. Intrinsic Functions ..
- INTRINSIC DBLE,DCONJG
-* ..
-*
-* Test the input parameters.
-*
- INFO = 0
- IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN
- INFO = 1
- ELSE IF (N.LT.0) THEN
- INFO = 2
- ELSE IF (INCX.EQ.0) THEN
- INFO = 5
- END IF
- IF (INFO.NE.0) THEN
- CALL XERBLA('ZHPR ',INFO)
- RETURN
- END IF
-*
-* Quick return if possible.
-*
- IF ((N.EQ.0) .OR. (ALPHA.EQ.DBLE(ZERO))) RETURN
-*
-* Set the start point in X if the increment is not unity.
-*
- IF (INCX.LE.0) THEN
- KX = 1 - (N-1)*INCX
- ELSE IF (INCX.NE.1) THEN
- KX = 1
- END IF
-*
-* Start the operations. In this version the elements of the array AP
-* are accessed sequentially with one pass through AP.
-*
- KK = 1
- IF (LSAME(UPLO,'U')) THEN
-*
-* Form A when upper triangle is stored in AP.
-*
- IF (INCX.EQ.1) THEN
- DO 20 J = 1,N
- IF (X(J).NE.ZERO) THEN
- TEMP = ALPHA*DCONJG(X(J))
- K = KK
- DO 10 I = 1,J - 1
- AP(K) = AP(K) + X(I)*TEMP
- K = K + 1
- 10 CONTINUE
- AP(KK+J-1) = DBLE(AP(KK+J-1)) + DBLE(X(J)*TEMP)
- ELSE
- AP(KK+J-1) = DBLE(AP(KK+J-1))
- END IF
- KK = KK + J
- 20 CONTINUE
- ELSE
- JX = KX
- DO 40 J = 1,N
- IF (X(JX).NE.ZERO) THEN
- TEMP = ALPHA*DCONJG(X(JX))
- IX = KX
- DO 30 K = KK,KK + J - 2
- AP(K) = AP(K) + X(IX)*TEMP
- IX = IX + INCX
- 30 CONTINUE
- AP(KK+J-1) = DBLE(AP(KK+J-1)) + DBLE(X(JX)*TEMP)
- ELSE
- AP(KK+J-1) = DBLE(AP(KK+J-1))
- END IF
- JX = JX + INCX
- KK = KK + J
- 40 CONTINUE
- END IF
- ELSE
-*
-* Form A when lower triangle is stored in AP.
-*
- IF (INCX.EQ.1) THEN
- DO 60 J = 1,N
- IF (X(J).NE.ZERO) THEN
- TEMP = ALPHA*DCONJG(X(J))
- AP(KK) = DBLE(AP(KK)) + DBLE(TEMP*X(J))
- K = KK + 1
- DO 50 I = J + 1,N
- AP(K) = AP(K) + X(I)*TEMP
- K = K + 1
- 50 CONTINUE
- ELSE
- AP(KK) = DBLE(AP(KK))
- END IF
- KK = KK + N - J + 1
- 60 CONTINUE
- ELSE
- JX = KX
- DO 80 J = 1,N
- IF (X(JX).NE.ZERO) THEN
- TEMP = ALPHA*DCONJG(X(JX))
- AP(KK) = DBLE(AP(KK)) + DBLE(TEMP*X(JX))
- IX = JX
- DO 70 K = KK + 1,KK + N - J
- IX = IX + INCX
- AP(K) = AP(K) + X(IX)*TEMP
- 70 CONTINUE
- ELSE
- AP(KK) = DBLE(AP(KK))
- END IF
- JX = JX + INCX
- KK = KK + N - J + 1
- 80 CONTINUE
- END IF
- END IF
-*
- RETURN
-*
-* End of ZHPR .
-*
- END
diff --git a/blas/zhpr2.f b/blas/zhpr2.f
deleted file mode 100644
index 99977462e..000000000
--- a/blas/zhpr2.f
+++ /dev/null
@@ -1,255 +0,0 @@
- SUBROUTINE ZHPR2(UPLO,N,ALPHA,X,INCX,Y,INCY,AP)
-* .. Scalar Arguments ..
- DOUBLE COMPLEX ALPHA
- INTEGER INCX,INCY,N
- CHARACTER UPLO
-* ..
-* .. Array Arguments ..
- DOUBLE COMPLEX AP(*),X(*),Y(*)
-* ..
-*
-* Purpose
-* =======
-*
-* ZHPR2 performs the hermitian rank 2 operation
-*
-* A := alpha*x*conjg( y' ) + conjg( alpha )*y*conjg( x' ) + A,
-*
-* where alpha is a scalar, x and y are n element vectors and A is an
-* n by n hermitian matrix, supplied in packed form.
-*
-* Arguments
-* ==========
-*
-* UPLO - CHARACTER*1.
-* On entry, UPLO specifies whether the upper or lower
-* triangular part of the matrix A is supplied in the packed
-* array AP as follows:
-*
-* UPLO = 'U' or 'u' The upper triangular part of A is
-* supplied in AP.
-*
-* UPLO = 'L' or 'l' The lower triangular part of A is
-* supplied in AP.
-*
-* Unchanged on exit.
-*
-* N - INTEGER.
-* On entry, N specifies the order of the matrix A.
-* N must be at least zero.
-* Unchanged on exit.
-*
-* ALPHA - COMPLEX*16 .
-* On entry, ALPHA specifies the scalar alpha.
-* Unchanged on exit.
-*
-* X - COMPLEX*16 array of dimension at least
-* ( 1 + ( n - 1 )*abs( INCX ) ).
-* Before entry, the incremented array X must contain the n
-* element vector x.
-* Unchanged on exit.
-*
-* INCX - INTEGER.
-* On entry, INCX specifies the increment for the elements of
-* X. INCX must not be zero.
-* Unchanged on exit.
-*
-* Y - COMPLEX*16 array of dimension at least
-* ( 1 + ( n - 1 )*abs( INCY ) ).
-* Before entry, the incremented array Y must contain the n
-* element vector y.
-* Unchanged on exit.
-*
-* INCY - INTEGER.
-* On entry, INCY specifies the increment for the elements of
-* Y. INCY must not be zero.
-* Unchanged on exit.
-*
-* AP - COMPLEX*16 array of DIMENSION at least
-* ( ( n*( n + 1 ) )/2 ).
-* Before entry with UPLO = 'U' or 'u', the array AP must
-* contain the upper triangular part of the hermitian matrix
-* packed sequentially, column by column, so that AP( 1 )
-* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 1, 2 )
-* and a( 2, 2 ) respectively, and so on. On exit, the array
-* AP is overwritten by the upper triangular part of the
-* updated matrix.
-* Before entry with UPLO = 'L' or 'l', the array AP must
-* contain the lower triangular part of the hermitian matrix
-* packed sequentially, column by column, so that AP( 1 )
-* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 2, 1 )
-* and a( 3, 1 ) respectively, and so on. On exit, the array
-* AP is overwritten by the lower triangular part of the
-* updated matrix.
-* Note that the imaginary parts of the diagonal elements need
-* not be set, they are assumed to be zero, and on exit they
-* are set to zero.
-*
-* Further Details
-* ===============
-*
-* Level 2 Blas routine.
-*
-* -- Written on 22-October-1986.
-* Jack Dongarra, Argonne National Lab.
-* Jeremy Du Croz, Nag Central Office.
-* Sven Hammarling, Nag Central Office.
-* Richard Hanson, Sandia National Labs.
-*
-* =====================================================================
-*
-* .. Parameters ..
- DOUBLE COMPLEX ZERO
- PARAMETER (ZERO= (0.0D+0,0.0D+0))
-* ..
-* .. Local Scalars ..
- DOUBLE COMPLEX TEMP1,TEMP2
- INTEGER I,INFO,IX,IY,J,JX,JY,K,KK,KX,KY
-* ..
-* .. External Functions ..
- LOGICAL LSAME
- EXTERNAL LSAME
-* ..
-* .. External Subroutines ..
- EXTERNAL XERBLA
-* ..
-* .. Intrinsic Functions ..
- INTRINSIC DBLE,DCONJG
-* ..
-*
-* Test the input parameters.
-*
- INFO = 0
- IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN
- INFO = 1
- ELSE IF (N.LT.0) THEN
- INFO = 2
- ELSE IF (INCX.EQ.0) THEN
- INFO = 5
- ELSE IF (INCY.EQ.0) THEN
- INFO = 7
- END IF
- IF (INFO.NE.0) THEN
- CALL XERBLA('ZHPR2 ',INFO)
- RETURN
- END IF
-*
-* Quick return if possible.
-*
- IF ((N.EQ.0) .OR. (ALPHA.EQ.ZERO)) RETURN
-*
-* Set up the start points in X and Y if the increments are not both
-* unity.
-*
- IF ((INCX.NE.1) .OR. (INCY.NE.1)) THEN
- IF (INCX.GT.0) THEN
- KX = 1
- ELSE
- KX = 1 - (N-1)*INCX
- END IF
- IF (INCY.GT.0) THEN
- KY = 1
- ELSE
- KY = 1 - (N-1)*INCY
- END IF
- JX = KX
- JY = KY
- END IF
-*
-* Start the operations. In this version the elements of the array AP
-* are accessed sequentially with one pass through AP.
-*
- KK = 1
- IF (LSAME(UPLO,'U')) THEN
-*
-* Form A when upper triangle is stored in AP.
-*
- IF ((INCX.EQ.1) .AND. (INCY.EQ.1)) THEN
- DO 20 J = 1,N
- IF ((X(J).NE.ZERO) .OR. (Y(J).NE.ZERO)) THEN
- TEMP1 = ALPHA*DCONJG(Y(J))
- TEMP2 = DCONJG(ALPHA*X(J))
- K = KK
- DO 10 I = 1,J - 1
- AP(K) = AP(K) + X(I)*TEMP1 + Y(I)*TEMP2
- K = K + 1
- 10 CONTINUE
- AP(KK+J-1) = DBLE(AP(KK+J-1)) +
- + DBLE(X(J)*TEMP1+Y(J)*TEMP2)
- ELSE
- AP(KK+J-1) = DBLE(AP(KK+J-1))
- END IF
- KK = KK + J
- 20 CONTINUE
- ELSE
- DO 40 J = 1,N
- IF ((X(JX).NE.ZERO) .OR. (Y(JY).NE.ZERO)) THEN
- TEMP1 = ALPHA*DCONJG(Y(JY))
- TEMP2 = DCONJG(ALPHA*X(JX))
- IX = KX
- IY = KY
- DO 30 K = KK,KK + J - 2
- AP(K) = AP(K) + X(IX)*TEMP1 + Y(IY)*TEMP2
- IX = IX + INCX
- IY = IY + INCY
- 30 CONTINUE
- AP(KK+J-1) = DBLE(AP(KK+J-1)) +
- + DBLE(X(JX)*TEMP1+Y(JY)*TEMP2)
- ELSE
- AP(KK+J-1) = DBLE(AP(KK+J-1))
- END IF
- JX = JX + INCX
- JY = JY + INCY
- KK = KK + J
- 40 CONTINUE
- END IF
- ELSE
-*
-* Form A when lower triangle is stored in AP.
-*
- IF ((INCX.EQ.1) .AND. (INCY.EQ.1)) THEN
- DO 60 J = 1,N
- IF ((X(J).NE.ZERO) .OR. (Y(J).NE.ZERO)) THEN
- TEMP1 = ALPHA*DCONJG(Y(J))
- TEMP2 = DCONJG(ALPHA*X(J))
- AP(KK) = DBLE(AP(KK)) +
- + DBLE(X(J)*TEMP1+Y(J)*TEMP2)
- K = KK + 1
- DO 50 I = J + 1,N
- AP(K) = AP(K) + X(I)*TEMP1 + Y(I)*TEMP2
- K = K + 1
- 50 CONTINUE
- ELSE
- AP(KK) = DBLE(AP(KK))
- END IF
- KK = KK + N - J + 1
- 60 CONTINUE
- ELSE
- DO 80 J = 1,N
- IF ((X(JX).NE.ZERO) .OR. (Y(JY).NE.ZERO)) THEN
- TEMP1 = ALPHA*DCONJG(Y(JY))
- TEMP2 = DCONJG(ALPHA*X(JX))
- AP(KK) = DBLE(AP(KK)) +
- + DBLE(X(JX)*TEMP1+Y(JY)*TEMP2)
- IX = JX
- IY = JY
- DO 70 K = KK + 1,KK + N - J
- IX = IX + INCX
- IY = IY + INCY
- AP(K) = AP(K) + X(IX)*TEMP1 + Y(IY)*TEMP2
- 70 CONTINUE
- ELSE
- AP(KK) = DBLE(AP(KK))
- END IF
- JX = JX + INCX
- JY = JY + INCY
- KK = KK + N - J + 1
- 80 CONTINUE
- END IF
- END IF
-*
- RETURN
-*
-* End of ZHPR2 .
-*
- END
diff --git a/blas/ztpmv.f b/blas/ztpmv.f
deleted file mode 100644
index 5a7b3b8b7..000000000
--- a/blas/ztpmv.f
+++ /dev/null
@@ -1,329 +0,0 @@
- SUBROUTINE ZTPMV(UPLO,TRANS,DIAG,N,AP,X,INCX)
-* .. Scalar Arguments ..
- INTEGER INCX,N
- CHARACTER DIAG,TRANS,UPLO
-* ..
-* .. Array Arguments ..
- DOUBLE COMPLEX AP(*),X(*)
-* ..
-*
-* Purpose
-* =======
-*
-* ZTPMV performs one of the matrix-vector operations
-*
-* x := A*x, or x := A'*x, or x := conjg( A' )*x,
-*
-* where x is an n element vector and A is an n by n unit, or non-unit,
-* upper or lower triangular matrix, supplied in packed form.
-*
-* Arguments
-* ==========
-*
-* UPLO - CHARACTER*1.
-* On entry, UPLO specifies whether the matrix is an upper or
-* lower triangular matrix as follows:
-*
-* UPLO = 'U' or 'u' A is an upper triangular matrix.
-*
-* UPLO = 'L' or 'l' A is a lower triangular matrix.
-*
-* Unchanged on exit.
-*
-* TRANS - CHARACTER*1.
-* On entry, TRANS specifies the operation to be performed as
-* follows:
-*
-* TRANS = 'N' or 'n' x := A*x.
-*
-* TRANS = 'T' or 't' x := A'*x.
-*
-* TRANS = 'C' or 'c' x := conjg( A' )*x.
-*
-* Unchanged on exit.
-*
-* DIAG - CHARACTER*1.
-* On entry, DIAG specifies whether or not A is unit
-* triangular as follows:
-*
-* DIAG = 'U' or 'u' A is assumed to be unit triangular.
-*
-* DIAG = 'N' or 'n' A is not assumed to be unit
-* triangular.
-*
-* Unchanged on exit.
-*
-* N - INTEGER.
-* On entry, N specifies the order of the matrix A.
-* N must be at least zero.
-* Unchanged on exit.
-*
-* AP - COMPLEX*16 array of DIMENSION at least
-* ( ( n*( n + 1 ) )/2 ).
-* Before entry with UPLO = 'U' or 'u', the array AP must
-* contain the upper triangular matrix packed sequentially,
-* column by column, so that AP( 1 ) contains a( 1, 1 ),
-* AP( 2 ) and AP( 3 ) contain a( 1, 2 ) and a( 2, 2 )
-* respectively, and so on.
-* Before entry with UPLO = 'L' or 'l', the array AP must
-* contain the lower triangular matrix packed sequentially,
-* column by column, so that AP( 1 ) contains a( 1, 1 ),
-* AP( 2 ) and AP( 3 ) contain a( 2, 1 ) and a( 3, 1 )
-* respectively, and so on.
-* Note that when DIAG = 'U' or 'u', the diagonal elements of
-* A are not referenced, but are assumed to be unity.
-* Unchanged on exit.
-*
-* X - COMPLEX*16 array of dimension at least
-* ( 1 + ( n - 1 )*abs( INCX ) ).
-* Before entry, the incremented array X must contain the n
-* element vector x. On exit, X is overwritten with the
-* tranformed vector x.
-*
-* INCX - INTEGER.
-* On entry, INCX specifies the increment for the elements of
-* X. INCX must not be zero.
-* Unchanged on exit.
-*
-* Further Details
-* ===============
-*
-* Level 2 Blas routine.
-*
-* -- Written on 22-October-1986.
-* Jack Dongarra, Argonne National Lab.
-* Jeremy Du Croz, Nag Central Office.
-* Sven Hammarling, Nag Central Office.
-* Richard Hanson, Sandia National Labs.
-*
-* =====================================================================
-*
-* .. Parameters ..
- DOUBLE COMPLEX ZERO
- PARAMETER (ZERO= (0.0D+0,0.0D+0))
-* ..
-* .. Local Scalars ..
- DOUBLE COMPLEX TEMP
- INTEGER I,INFO,IX,J,JX,K,KK,KX
- LOGICAL NOCONJ,NOUNIT
-* ..
-* .. External Functions ..
- LOGICAL LSAME
- EXTERNAL LSAME
-* ..
-* .. External Subroutines ..
- EXTERNAL XERBLA
-* ..
-* .. Intrinsic Functions ..
- INTRINSIC DCONJG
-* ..
-*
-* Test the input parameters.
-*
- INFO = 0
- IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN
- INFO = 1
- ELSE IF (.NOT.LSAME(TRANS,'N') .AND. .NOT.LSAME(TRANS,'T') .AND.
- + .NOT.LSAME(TRANS,'C')) THEN
- INFO = 2
- ELSE IF (.NOT.LSAME(DIAG,'U') .AND. .NOT.LSAME(DIAG,'N')) THEN
- INFO = 3
- ELSE IF (N.LT.0) THEN
- INFO = 4
- ELSE IF (INCX.EQ.0) THEN
- INFO = 7
- END IF
- IF (INFO.NE.0) THEN
- CALL XERBLA('ZTPMV ',INFO)
- RETURN
- END IF
-*
-* Quick return if possible.
-*
- IF (N.EQ.0) RETURN
-*
- NOCONJ = LSAME(TRANS,'T')
- NOUNIT = LSAME(DIAG,'N')
-*
-* Set up the start point in X if the increment is not unity. This
-* will be ( N - 1 )*INCX too small for descending loops.
-*
- IF (INCX.LE.0) THEN
- KX = 1 - (N-1)*INCX
- ELSE IF (INCX.NE.1) THEN
- KX = 1
- END IF
-*
-* Start the operations. In this version the elements of AP are
-* accessed sequentially with one pass through AP.
-*
- IF (LSAME(TRANS,'N')) THEN
-*
-* Form x:= A*x.
-*
- IF (LSAME(UPLO,'U')) THEN
- KK = 1
- IF (INCX.EQ.1) THEN
- DO 20 J = 1,N
- IF (X(J).NE.ZERO) THEN
- TEMP = X(J)
- K = KK
- DO 10 I = 1,J - 1
- X(I) = X(I) + TEMP*AP(K)
- K = K + 1
- 10 CONTINUE
- IF (NOUNIT) X(J) = X(J)*AP(KK+J-1)
- END IF
- KK = KK + J
- 20 CONTINUE
- ELSE
- JX = KX
- DO 40 J = 1,N
- IF (X(JX).NE.ZERO) THEN
- TEMP = X(JX)
- IX = KX
- DO 30 K = KK,KK + J - 2
- X(IX) = X(IX) + TEMP*AP(K)
- IX = IX + INCX
- 30 CONTINUE
- IF (NOUNIT) X(JX) = X(JX)*AP(KK+J-1)
- END IF
- JX = JX + INCX
- KK = KK + J
- 40 CONTINUE
- END IF
- ELSE
- KK = (N* (N+1))/2
- IF (INCX.EQ.1) THEN
- DO 60 J = N,1,-1
- IF (X(J).NE.ZERO) THEN
- TEMP = X(J)
- K = KK
- DO 50 I = N,J + 1,-1
- X(I) = X(I) + TEMP*AP(K)
- K = K - 1
- 50 CONTINUE
- IF (NOUNIT) X(J) = X(J)*AP(KK-N+J)
- END IF
- KK = KK - (N-J+1)
- 60 CONTINUE
- ELSE
- KX = KX + (N-1)*INCX
- JX = KX
- DO 80 J = N,1,-1
- IF (X(JX).NE.ZERO) THEN
- TEMP = X(JX)
- IX = KX
- DO 70 K = KK,KK - (N- (J+1)),-1
- X(IX) = X(IX) + TEMP*AP(K)
- IX = IX - INCX
- 70 CONTINUE
- IF (NOUNIT) X(JX) = X(JX)*AP(KK-N+J)
- END IF
- JX = JX - INCX
- KK = KK - (N-J+1)
- 80 CONTINUE
- END IF
- END IF
- ELSE
-*
-* Form x := A'*x or x := conjg( A' )*x.
-*
- IF (LSAME(UPLO,'U')) THEN
- KK = (N* (N+1))/2
- IF (INCX.EQ.1) THEN
- DO 110 J = N,1,-1
- TEMP = X(J)
- K = KK - 1
- IF (NOCONJ) THEN
- IF (NOUNIT) TEMP = TEMP*AP(KK)
- DO 90 I = J - 1,1,-1
- TEMP = TEMP + AP(K)*X(I)
- K = K - 1
- 90 CONTINUE
- ELSE
- IF (NOUNIT) TEMP = TEMP*DCONJG(AP(KK))
- DO 100 I = J - 1,1,-1
- TEMP = TEMP + DCONJG(AP(K))*X(I)
- K = K - 1
- 100 CONTINUE
- END IF
- X(J) = TEMP
- KK = KK - J
- 110 CONTINUE
- ELSE
- JX = KX + (N-1)*INCX
- DO 140 J = N,1,-1
- TEMP = X(JX)
- IX = JX
- IF (NOCONJ) THEN
- IF (NOUNIT) TEMP = TEMP*AP(KK)
- DO 120 K = KK - 1,KK - J + 1,-1
- IX = IX - INCX
- TEMP = TEMP + AP(K)*X(IX)
- 120 CONTINUE
- ELSE
- IF (NOUNIT) TEMP = TEMP*DCONJG(AP(KK))
- DO 130 K = KK - 1,KK - J + 1,-1
- IX = IX - INCX
- TEMP = TEMP + DCONJG(AP(K))*X(IX)
- 130 CONTINUE
- END IF
- X(JX) = TEMP
- JX = JX - INCX
- KK = KK - J
- 140 CONTINUE
- END IF
- ELSE
- KK = 1
- IF (INCX.EQ.1) THEN
- DO 170 J = 1,N
- TEMP = X(J)
- K = KK + 1
- IF (NOCONJ) THEN
- IF (NOUNIT) TEMP = TEMP*AP(KK)
- DO 150 I = J + 1,N
- TEMP = TEMP + AP(K)*X(I)
- K = K + 1
- 150 CONTINUE
- ELSE
- IF (NOUNIT) TEMP = TEMP*DCONJG(AP(KK))
- DO 160 I = J + 1,N
- TEMP = TEMP + DCONJG(AP(K))*X(I)
- K = K + 1
- 160 CONTINUE
- END IF
- X(J) = TEMP
- KK = KK + (N-J+1)
- 170 CONTINUE
- ELSE
- JX = KX
- DO 200 J = 1,N
- TEMP = X(JX)
- IX = JX
- IF (NOCONJ) THEN
- IF (NOUNIT) TEMP = TEMP*AP(KK)
- DO 180 K = KK + 1,KK + N - J
- IX = IX + INCX
- TEMP = TEMP + AP(K)*X(IX)
- 180 CONTINUE
- ELSE
- IF (NOUNIT) TEMP = TEMP*DCONJG(AP(KK))
- DO 190 K = KK + 1,KK + N - J
- IX = IX + INCX
- TEMP = TEMP + DCONJG(AP(K))*X(IX)
- 190 CONTINUE
- END IF
- X(JX) = TEMP
- JX = JX + INCX
- KK = KK + (N-J+1)
- 200 CONTINUE
- END IF
- END IF
- END IF
-*
- RETURN
-*
-* End of ZTPMV .
-*
- END
diff --git a/blas/ztpsv.f b/blas/ztpsv.f
deleted file mode 100644
index b56e1d8c4..000000000
--- a/blas/ztpsv.f
+++ /dev/null
@@ -1,332 +0,0 @@
- SUBROUTINE ZTPSV(UPLO,TRANS,DIAG,N,AP,X,INCX)
-* .. Scalar Arguments ..
- INTEGER INCX,N
- CHARACTER DIAG,TRANS,UPLO
-* ..
-* .. Array Arguments ..
- DOUBLE COMPLEX AP(*),X(*)
-* ..
-*
-* Purpose
-* =======
-*
-* ZTPSV solves one of the systems of equations
-*
-* A*x = b, or A'*x = b, or conjg( A' )*x = b,
-*
-* where b and x are n element vectors and A is an n by n unit, or
-* non-unit, upper or lower triangular matrix, supplied in packed form.
-*
-* No test for singularity or near-singularity is included in this
-* routine. Such tests must be performed before calling this routine.
-*
-* Arguments
-* ==========
-*
-* UPLO - CHARACTER*1.
-* On entry, UPLO specifies whether the matrix is an upper or
-* lower triangular matrix as follows:
-*
-* UPLO = 'U' or 'u' A is an upper triangular matrix.
-*
-* UPLO = 'L' or 'l' A is a lower triangular matrix.
-*
-* Unchanged on exit.
-*
-* TRANS - CHARACTER*1.
-* On entry, TRANS specifies the equations to be solved as
-* follows:
-*
-* TRANS = 'N' or 'n' A*x = b.
-*
-* TRANS = 'T' or 't' A'*x = b.
-*
-* TRANS = 'C' or 'c' conjg( A' )*x = b.
-*
-* Unchanged on exit.
-*
-* DIAG - CHARACTER*1.
-* On entry, DIAG specifies whether or not A is unit
-* triangular as follows:
-*
-* DIAG = 'U' or 'u' A is assumed to be unit triangular.
-*
-* DIAG = 'N' or 'n' A is not assumed to be unit
-* triangular.
-*
-* Unchanged on exit.
-*
-* N - INTEGER.
-* On entry, N specifies the order of the matrix A.
-* N must be at least zero.
-* Unchanged on exit.
-*
-* AP - COMPLEX*16 array of DIMENSION at least
-* ( ( n*( n + 1 ) )/2 ).
-* Before entry with UPLO = 'U' or 'u', the array AP must
-* contain the upper triangular matrix packed sequentially,
-* column by column, so that AP( 1 ) contains a( 1, 1 ),
-* AP( 2 ) and AP( 3 ) contain a( 1, 2 ) and a( 2, 2 )
-* respectively, and so on.
-* Before entry with UPLO = 'L' or 'l', the array AP must
-* contain the lower triangular matrix packed sequentially,
-* column by column, so that AP( 1 ) contains a( 1, 1 ),
-* AP( 2 ) and AP( 3 ) contain a( 2, 1 ) and a( 3, 1 )
-* respectively, and so on.
-* Note that when DIAG = 'U' or 'u', the diagonal elements of
-* A are not referenced, but are assumed to be unity.
-* Unchanged on exit.
-*
-* X - COMPLEX*16 array of dimension at least
-* ( 1 + ( n - 1 )*abs( INCX ) ).
-* Before entry, the incremented array X must contain the n
-* element right-hand side vector b. On exit, X is overwritten
-* with the solution vector x.
-*
-* INCX - INTEGER.
-* On entry, INCX specifies the increment for the elements of
-* X. INCX must not be zero.
-* Unchanged on exit.
-*
-* Further Details
-* ===============
-*
-* Level 2 Blas routine.
-*
-* -- Written on 22-October-1986.
-* Jack Dongarra, Argonne National Lab.
-* Jeremy Du Croz, Nag Central Office.
-* Sven Hammarling, Nag Central Office.
-* Richard Hanson, Sandia National Labs.
-*
-* =====================================================================
-*
-* .. Parameters ..
- DOUBLE COMPLEX ZERO
- PARAMETER (ZERO= (0.0D+0,0.0D+0))
-* ..
-* .. Local Scalars ..
- DOUBLE COMPLEX TEMP
- INTEGER I,INFO,IX,J,JX,K,KK,KX
- LOGICAL NOCONJ,NOUNIT
-* ..
-* .. External Functions ..
- LOGICAL LSAME
- EXTERNAL LSAME
-* ..
-* .. External Subroutines ..
- EXTERNAL XERBLA
-* ..
-* .. Intrinsic Functions ..
- INTRINSIC DCONJG
-* ..
-*
-* Test the input parameters.
-*
- INFO = 0
- IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN
- INFO = 1
- ELSE IF (.NOT.LSAME(TRANS,'N') .AND. .NOT.LSAME(TRANS,'T') .AND.
- + .NOT.LSAME(TRANS,'C')) THEN
- INFO = 2
- ELSE IF (.NOT.LSAME(DIAG,'U') .AND. .NOT.LSAME(DIAG,'N')) THEN
- INFO = 3
- ELSE IF (N.LT.0) THEN
- INFO = 4
- ELSE IF (INCX.EQ.0) THEN
- INFO = 7
- END IF
- IF (INFO.NE.0) THEN
- CALL XERBLA('ZTPSV ',INFO)
- RETURN
- END IF
-*
-* Quick return if possible.
-*
- IF (N.EQ.0) RETURN
-*
- NOCONJ = LSAME(TRANS,'T')
- NOUNIT = LSAME(DIAG,'N')
-*
-* Set up the start point in X if the increment is not unity. This
-* will be ( N - 1 )*INCX too small for descending loops.
-*
- IF (INCX.LE.0) THEN
- KX = 1 - (N-1)*INCX
- ELSE IF (INCX.NE.1) THEN
- KX = 1
- END IF
-*
-* Start the operations. In this version the elements of AP are
-* accessed sequentially with one pass through AP.
-*
- IF (LSAME(TRANS,'N')) THEN
-*
-* Form x := inv( A )*x.
-*
- IF (LSAME(UPLO,'U')) THEN
- KK = (N* (N+1))/2
- IF (INCX.EQ.1) THEN
- DO 20 J = N,1,-1
- IF (X(J).NE.ZERO) THEN
- IF (NOUNIT) X(J) = X(J)/AP(KK)
- TEMP = X(J)
- K = KK - 1
- DO 10 I = J - 1,1,-1
- X(I) = X(I) - TEMP*AP(K)
- K = K - 1
- 10 CONTINUE
- END IF
- KK = KK - J
- 20 CONTINUE
- ELSE
- JX = KX + (N-1)*INCX
- DO 40 J = N,1,-1
- IF (X(JX).NE.ZERO) THEN
- IF (NOUNIT) X(JX) = X(JX)/AP(KK)
- TEMP = X(JX)
- IX = JX
- DO 30 K = KK - 1,KK - J + 1,-1
- IX = IX - INCX
- X(IX) = X(IX) - TEMP*AP(K)
- 30 CONTINUE
- END IF
- JX = JX - INCX
- KK = KK - J
- 40 CONTINUE
- END IF
- ELSE
- KK = 1
- IF (INCX.EQ.1) THEN
- DO 60 J = 1,N
- IF (X(J).NE.ZERO) THEN
- IF (NOUNIT) X(J) = X(J)/AP(KK)
- TEMP = X(J)
- K = KK + 1
- DO 50 I = J + 1,N
- X(I) = X(I) - TEMP*AP(K)
- K = K + 1
- 50 CONTINUE
- END IF
- KK = KK + (N-J+1)
- 60 CONTINUE
- ELSE
- JX = KX
- DO 80 J = 1,N
- IF (X(JX).NE.ZERO) THEN
- IF (NOUNIT) X(JX) = X(JX)/AP(KK)
- TEMP = X(JX)
- IX = JX
- DO 70 K = KK + 1,KK + N - J
- IX = IX + INCX
- X(IX) = X(IX) - TEMP*AP(K)
- 70 CONTINUE
- END IF
- JX = JX + INCX
- KK = KK + (N-J+1)
- 80 CONTINUE
- END IF
- END IF
- ELSE
-*
-* Form x := inv( A' )*x or x := inv( conjg( A' ) )*x.
-*
- IF (LSAME(UPLO,'U')) THEN
- KK = 1
- IF (INCX.EQ.1) THEN
- DO 110 J = 1,N
- TEMP = X(J)
- K = KK
- IF (NOCONJ) THEN
- DO 90 I = 1,J - 1
- TEMP = TEMP - AP(K)*X(I)
- K = K + 1
- 90 CONTINUE
- IF (NOUNIT) TEMP = TEMP/AP(KK+J-1)
- ELSE
- DO 100 I = 1,J - 1
- TEMP = TEMP - DCONJG(AP(K))*X(I)
- K = K + 1
- 100 CONTINUE
- IF (NOUNIT) TEMP = TEMP/DCONJG(AP(KK+J-1))
- END IF
- X(J) = TEMP
- KK = KK + J
- 110 CONTINUE
- ELSE
- JX = KX
- DO 140 J = 1,N
- TEMP = X(JX)
- IX = KX
- IF (NOCONJ) THEN
- DO 120 K = KK,KK + J - 2
- TEMP = TEMP - AP(K)*X(IX)
- IX = IX + INCX
- 120 CONTINUE
- IF (NOUNIT) TEMP = TEMP/AP(KK+J-1)
- ELSE
- DO 130 K = KK,KK + J - 2
- TEMP = TEMP - DCONJG(AP(K))*X(IX)
- IX = IX + INCX
- 130 CONTINUE
- IF (NOUNIT) TEMP = TEMP/DCONJG(AP(KK+J-1))
- END IF
- X(JX) = TEMP
- JX = JX + INCX
- KK = KK + J
- 140 CONTINUE
- END IF
- ELSE
- KK = (N* (N+1))/2
- IF (INCX.EQ.1) THEN
- DO 170 J = N,1,-1
- TEMP = X(J)
- K = KK
- IF (NOCONJ) THEN
- DO 150 I = N,J + 1,-1
- TEMP = TEMP - AP(K)*X(I)
- K = K - 1
- 150 CONTINUE
- IF (NOUNIT) TEMP = TEMP/AP(KK-N+J)
- ELSE
- DO 160 I = N,J + 1,-1
- TEMP = TEMP - DCONJG(AP(K))*X(I)
- K = K - 1
- 160 CONTINUE
- IF (NOUNIT) TEMP = TEMP/DCONJG(AP(KK-N+J))
- END IF
- X(J) = TEMP
- KK = KK - (N-J+1)
- 170 CONTINUE
- ELSE
- KX = KX + (N-1)*INCX
- JX = KX
- DO 200 J = N,1,-1
- TEMP = X(JX)
- IX = KX
- IF (NOCONJ) THEN
- DO 180 K = KK,KK - (N- (J+1)),-1
- TEMP = TEMP - AP(K)*X(IX)
- IX = IX - INCX
- 180 CONTINUE
- IF (NOUNIT) TEMP = TEMP/AP(KK-N+J)
- ELSE
- DO 190 K = KK,KK - (N- (J+1)),-1
- TEMP = TEMP - DCONJG(AP(K))*X(IX)
- IX = IX - INCX
- 190 CONTINUE
- IF (NOUNIT) TEMP = TEMP/DCONJG(AP(KK-N+J))
- END IF
- X(JX) = TEMP
- JX = JX - INCX
- KK = KK - (N-J+1)
- 200 CONTINUE
- END IF
- END IF
- END IF
-*
- RETURN
-*
-* End of ZTPSV .
-*
- END
diff --git a/cmake/CMakeDetermineVSServicePack.cmake b/cmake/CMakeDetermineVSServicePack.cmake
deleted file mode 100644
index b89462308..000000000
--- a/cmake/CMakeDetermineVSServicePack.cmake
+++ /dev/null
@@ -1,103 +0,0 @@
-# - Includes a public function for assisting users in trying to determine the
-# Visual Studio service pack in use.
-#
-# Sets the passed in variable to one of the following values or an empty
-# string if unknown.
-# vc80
-# vc80sp1
-# vc90
-# vc90sp1
-#
-# Usage:
-# ===========================
-#
-# if(MSVC)
-# include(CMakeDetermineVSServicePack)
-# DetermineVSServicePack( my_service_pack )
-#
-# if( my_service_pack )
-# message(STATUS "Detected: ${my_service_pack}")
-# endif()
-# endif()
-#
-# ===========================
-
-#=============================================================================
-# Copyright 2009-2010 Kitware, Inc.
-# Copyright 2009-2010 Philip Lowman <philip@yhbt.com>
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
-# (To distribute this file outside of CMake, substitute the full
-# License text for the above reference.)
-
-# [INTERNAL]
-# Please do not call this function directly
-function(_DetermineVSServicePackFromCompiler _OUT_VAR _cl_version)
- if (${_cl_version} VERSION_EQUAL "14.00.50727.42")
- set(_version "vc80")
- elseif(${_cl_version} VERSION_EQUAL "14.00.50727.762")
- set(_version "vc80sp1")
- elseif(${_cl_version} VERSION_EQUAL "15.00.21022.08")
- set(_version "vc90")
- elseif(${_cl_version} VERSION_EQUAL "15.00.30729.01")
- set(_version "vc90sp1")
- elseif(${_cl_version} VERSION_EQUAL "16.00.30319.01")
- set(_version "vc100")
- else()
- set(_version "")
- endif()
- set(${_OUT_VAR} ${_version} PARENT_SCOPE)
-endfunction()
-
-#
-# A function to call to determine the Visual Studio service pack
-# in use. See documentation above.
-function(DetermineVSServicePack _pack)
- if(NOT DETERMINED_VS_SERVICE_PACK OR NOT ${_pack})
- if(${CMAKE_BUILD_TOOL} STREQUAL "nmake")
- EXECUTE_PROCESS(COMMAND ${CMAKE_CXX_COMPILER} "/?"
- ERROR_VARIABLE _output)
- set(DETERMINED_VS_SERVICE_PACK ${_output})
- else()
- file(WRITE "${CMAKE_BINARY_DIR}/return0.cc"
- "int main() { return 0; }\n")
-
- try_compile(DETERMINED_VS_SERVICE_PACK
- "${CMAKE_BINARY_DIR}"
- "${CMAKE_BINARY_DIR}/return0.cc"
- OUTPUT_VARIABLE _output
- COPY_FILE "${CMAKE_BINARY_DIR}/return0.cc")
-
- file(REMOVE "${CMAKE_BINARY_DIR}/return0.cc")
- endif()
-
- if(DETERMINED_VS_SERVICE_PACK AND _output)
- string(REGEX MATCH "Compiler Version [0-9]+.[0-9]+.[0-9]+.[0-9]+"
- _cl_version "${_output}")
- if(_cl_version)
- string(REGEX MATCHALL "[0-9]+"
- _cl_version_list "${_cl_version}")
- list(GET _cl_version_list 0 _major)
- list(GET _cl_version_list 1 _minor)
- list(GET _cl_version_list 2 _patch)
- list(GET _cl_version_list 3 _tweak)
-
- set(_cl_version_string ${_major}.${_minor}.${_patch}.${_tweak})
-
- # Call helper function to determine VS version
- _DetermineVSServicePackFromCompiler(_sp "${_cl_version_string}")
- if(_sp)
- #set(${_pack} "${_sp}(${_cl_version_string})" CACHE INTERNAL
- set(${_pack} "${_sp}" CACHE INTERNAL
- "The Visual Studio Release with Service Pack")
- endif()
- endif()
- endif()
- endif()
-endfunction()
diff --git a/cmake/EigenConfigureTesting.cmake b/cmake/EigenConfigureTesting.cmake
index cf8f32c01..11ecc9585 100644
--- a/cmake/EigenConfigureTesting.cmake
+++ b/cmake/EigenConfigureTesting.cmake
@@ -24,22 +24,24 @@ set(CMAKE_MAKE_PROGRAM "@EIGEN_MAKECOMMAND_PLACEHOLDER@")
# This call activates testing and generates the DartConfiguration.tcl
include(CTest)
+set(EIGEN_TEST_BUILD_FLAGS " " CACHE STRING "Options passed to the build command of unit tests")
+
# overwrite default DartConfiguration.tcl
# The worarounds are different for each version of the MSVC IDE
if(MSVC_IDE)
- if(MSVC_VERSION EQUAL 1600) # MSVC 2010
- set(EIGEN_MAKECOMMAND_PLACEHOLDER "${CMAKE_MAKE_PROGRAM_SAVE} buildtests.vcxproj /p:Configuration=\${CTEST_CONFIGURATION_TYPE} \n# ")
- else() # MSVC 2008 (TODO check MSVC 2005)
- set(EIGEN_MAKECOMMAND_PLACEHOLDER "${CMAKE_MAKE_PROGRAM_SAVE} Eigen.sln /build \"Release\" /project buildtests \n# ")
+ if(CMAKE_MAKE_PROGRAM_SAVE MATCHES "devenv") # devenv
+ set(EIGEN_MAKECOMMAND_PLACEHOLDER "${CMAKE_MAKE_PROGRAM_SAVE} Eigen.sln /build \"Release\" /project buildtests ${EIGEN_TEST_BUILD_FLAGS} \n# ")
+ else() # msbuild
+ set(EIGEN_MAKECOMMAND_PLACEHOLDER "${CMAKE_MAKE_PROGRAM_SAVE} buildtests.vcxproj /p:Configuration=\${CTEST_CONFIGURATION_TYPE} ${EIGEN_TEST_BUILD_FLAGS}\n# ")
endif()
else()
# for make and nmake
- set(EIGEN_MAKECOMMAND_PLACEHOLDER "${CMAKE_MAKE_PROGRAM_SAVE} buildtests")
+ set(EIGEN_MAKECOMMAND_PLACEHOLDER "${CMAKE_MAKE_PROGRAM_SAVE} buildtests ${EIGEN_TEST_BUILD_FLAGS}")
endif()
# copy ctest properties, which currently
# o raise the warning levels
-configure_file(${CMAKE_BINARY_DIR}/DartConfiguration.tcl ${CMAKE_BINARY_DIR}/DartConfiguration.tcl)
+configure_file(${CMAKE_CURRENT_BINARY_DIR}/DartConfiguration.tcl ${CMAKE_BINARY_DIR}/DartConfiguration.tcl)
# restore default CMAKE_MAKE_PROGRAM
set(CMAKE_MAKE_PROGRAM ${CMAKE_MAKE_PROGRAM_SAVE})
@@ -48,7 +50,7 @@ set(CMAKE_MAKE_PROGRAM ${CMAKE_MAKE_PROGRAM_SAVE})
set(CMAKE_MAKE_PROGRAM_SAVE)
set(EIGEN_MAKECOMMAND_PLACEHOLDER)
-configure_file(${CMAKE_SOURCE_DIR}/CTestCustom.cmake.in ${CMAKE_BINARY_DIR}/CTestCustom.cmake)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CTestCustom.cmake.in ${CMAKE_BINARY_DIR}/CTestCustom.cmake)
# some documentation of this function would be nice
ei_init_testing()
diff --git a/cmake/EigenDetermineVSServicePack.cmake b/cmake/EigenDetermineVSServicePack.cmake
new file mode 100644
index 000000000..8e5546a85
--- /dev/null
+++ b/cmake/EigenDetermineVSServicePack.cmake
@@ -0,0 +1,27 @@
+include(CMakeDetermineVSServicePack)
+
+# The code is almost identical to the CMake version. The only difference is that we remove
+# _DetermineVSServicePack_FastCheckVersionWithCompiler which lead to errors on some systems.
+function(EigenDetermineVSServicePack _pack)
+ if(NOT DETERMINED_VS_SERVICE_PACK OR NOT ${_pack})
+
+ if(NOT DETERMINED_VS_SERVICE_PACK)
+ _DetermineVSServicePack_CheckVersionWithTryCompile(DETERMINED_VS_SERVICE_PACK _cl_version)
+ if(NOT DETERMINED_VS_SERVICE_PACK)
+ _DetermineVSServicePack_CheckVersionWithTryRun(DETERMINED_VS_SERVICE_PACK _cl_version)
+ endif()
+ endif()
+
+ if(DETERMINED_VS_SERVICE_PACK)
+
+ if(_cl_version)
+ # Call helper function to determine VS version
+ _DetermineVSServicePackFromCompiler(_sp "${_cl_version}")
+ if(_sp)
+ set(${_pack} ${_sp} CACHE INTERNAL
+ "The Visual Studio Release with Service Pack")
+ endif()
+ endif()
+ endif()
+ endif()
+endfunction()
diff --git a/cmake/EigenTesting.cmake b/cmake/EigenTesting.cmake
index 266043974..d9e22ab1a 100644
--- a/cmake/EigenTesting.cmake
+++ b/cmake/EigenTesting.cmake
@@ -73,6 +73,14 @@ macro(ei_add_test_internal testname testname_with_suffix)
else()
add_test(${testname_with_suffix} "${targetname}")
endif()
+
+ # Specify target and test labels accoirding to EIGEN_CURRENT_SUBPROJECT
+ get_property(current_subproject GLOBAL PROPERTY EIGEN_CURRENT_SUBPROJECT)
+ if ((current_subproject) AND (NOT (current_subproject STREQUAL "")))
+ set_property(TARGET ${targetname} PROPERTY LABELS "Build${current_subproject}")
+ add_dependencies("Build${current_subproject}" ${targetname})
+ set_property(TEST ${testname_with_suffix} PROPERTY LABELS "${current_subproject}")
+ endif()
endmacro(ei_add_test_internal)
@@ -263,6 +271,7 @@ macro(ei_testing_print_summary)
endmacro(ei_testing_print_summary)
macro(ei_init_testing)
+ define_property(GLOBAL PROPERTY EIGEN_CURRENT_SUBPROJECT BRIEF_DOCS " " FULL_DOCS " ")
define_property(GLOBAL PROPERTY EIGEN_TESTED_BACKENDS BRIEF_DOCS " " FULL_DOCS " ")
define_property(GLOBAL PROPERTY EIGEN_MISSING_BACKENDS BRIEF_DOCS " " FULL_DOCS " ")
define_property(GLOBAL PROPERTY EIGEN_TESTING_SUMMARY BRIEF_DOCS " " FULL_DOCS " ")
@@ -303,8 +312,8 @@ endmacro(ei_set_sitename)
macro(ei_get_compilerver VAR)
if(MSVC)
# on windows system, we use a modified CMake script
- include(CMakeDetermineVSServicePack)
- DetermineVSServicePack( my_service_pack )
+ include(EigenDetermineVSServicePack)
+ EigenDetermineVSServicePack( my_service_pack )
if( my_service_pack )
set(${VAR} ${my_service_pack})
@@ -313,13 +322,21 @@ macro(ei_get_compilerver VAR)
endif()
else()
# on all other system we rely on ${CMAKE_CXX_COMPILER}
- # supporting a "--version" flag
- execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version
- COMMAND head -n 1
- OUTPUT_VARIABLE eigen_cxx_compiler_version_string OUTPUT_STRIP_TRAILING_WHITESPACE)
+ # supporting a "--version" flag
- ei_get_compilerver_from_cxx_version_string(${eigen_cxx_compiler_version_string} CNAME CVER)
+ # check whether the head command exists
+ find_program(HEAD_EXE head NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH)
+ if(HEAD_EXE)
+ execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version
+ COMMAND head -n 1
+ OUTPUT_VARIABLE eigen_cxx_compiler_version_string OUTPUT_STRIP_TRAILING_WHITESPACE)
+ else()
+ execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version
+ OUTPUT_VARIABLE eigen_cxx_compiler_version_string OUTPUT_STRIP_TRAILING_WHITESPACE)
+ string(REGEX REPLACE "[\n\r].*" "" eigen_cxx_compiler_version_string ${eigen_cxx_compiler_version_string})
+ endif()
+ ei_get_compilerver_from_cxx_version_string("${eigen_cxx_compiler_version_string}" CNAME CVER)
set(${VAR} "${CNAME}-${CVER}")
endif()
endmacro(ei_get_compilerver)
@@ -426,6 +443,10 @@ macro(ei_set_build_string)
else()
set(TMP_BUILD_STRING ${TMP_BUILD_STRING}-64bit)
endif()
+
+ if(EIGEN_BUILD_STRING_SUFFIX)
+ set(TMP_BUILD_STRING ${TMP_BUILD_STRING}-${EIGEN_BUILD_STRING_SUFFIX})
+ endif()
string(TOLOWER ${TMP_BUILD_STRING} BUILDNAME)
endmacro(ei_set_build_string)
diff --git a/cmake/FindCholmod.cmake b/cmake/FindCholmod.cmake
index 9095bea31..7b3046d45 100644
--- a/cmake/FindCholmod.cmake
+++ b/cmake/FindCholmod.cmake
@@ -73,8 +73,17 @@ if(CHOLMOD_LIBRARIES)
endif(CHOLMOD_LIBRARIES)
+if(CHOLMOD_LIBRARIES)
+
+ find_library(SUITESPARSE_LIBRARY SuiteSparse PATHS ${CHOLMOD_LIBDIR} $ENV{CHOLMODDIR} ${LIB_INSTALL_DIR})
+ if (SUITESPARSE_LIBRARY)
+ set(CHOLMOD_LIBRARIES ${CHOLMOD_LIBRARIES} ${SUITESPARSE_LIBRARY})
+ endif (SUITESPARSE_LIBRARY)
+
+endif(CHOLMOD_LIBRARIES)
+
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(CHOLMOD DEFAULT_MSG
CHOLMOD_INCLUDES CHOLMOD_LIBRARIES)
-mark_as_advanced(CHOLMOD_INCLUDES CHOLMOD_LIBRARIES AMD_LIBRARY COLAMD_LIBRARY)
+mark_as_advanced(CHOLMOD_INCLUDES CHOLMOD_LIBRARIES AMD_LIBRARY COLAMD_LIBRARY SUITESPARSE_LIBRARY)
diff --git a/cmake/FindMetis.cmake b/cmake/FindMetis.cmake
index e4d6ef258..627c3e9ae 100644
--- a/cmake/FindMetis.cmake
+++ b/cmake/FindMetis.cmake
@@ -12,10 +12,11 @@ find_path(METIS_INCLUDES
${INCLUDE_INSTALL_DIR}
PATH_SUFFIXES
metis
+ include
)
-find_library(METIS_LIBRARIES metis PATHS $ENV{METISDIR} ${LIB_INSTALL_DIR})
+find_library(METIS_LIBRARIES metis PATHS $ENV{METISDIR} ${LIB_INSTALL_DIR} PATH_SUFFIXES lib)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(METIS DEFAULT_MSG
diff --git a/cmake/FindSPQR.cmake b/cmake/FindSPQR.cmake
new file mode 100644
index 000000000..794c212af
--- /dev/null
+++ b/cmake/FindSPQR.cmake
@@ -0,0 +1,36 @@
+# SPQR lib usually requires linking to a blas and lapack library.
+# It is up to the user of this module to find a BLAS and link to it.
+
+# SPQR lib requires Cholmod, colamd and amd as well.
+# FindCholmod.cmake can be used to find those packages before finding spqr
+
+if (SPQR_INCLUDES AND SPQR_LIBRARIES)
+ set(SPQR_FIND_QUIETLY TRUE)
+endif (SPQR_INCLUDES AND SPQR_LIBRARIES)
+
+find_path(SPQR_INCLUDES
+ NAMES
+ SuiteSparseQR.hpp
+ PATHS
+ $ENV{SPQRDIR}
+ ${INCLUDE_INSTALL_DIR}
+ PATH_SUFFIXES
+ suitesparse
+ ufsparse
+)
+
+find_library(SPQR_LIBRARIES spqr $ENV{SPQRDIR} ${LIB_INSTALL_DIR})
+
+if(SPQR_LIBRARIES)
+
+ find_library(SUITESPARSE_LIBRARY SuiteSparse PATHS $ENV{SPQRDIR} ${LIB_INSTALL_DIR})
+ if (SUITESPARSE_LIBRARY)
+ set(SPQR_LIBRARIES ${SPQR_LIBRARIES} ${SUITESPARSE_LIBRARY})
+ endif (SUITESPARSE_LIBRARY)
+
+endif(SPQR_LIBRARIES)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(SPQR DEFAULT_MSG SPQR_INCLUDES SPQR_LIBRARIES)
+
+mark_as_advanced(SPQR_INCLUDES SPQR_LIBRARIES) \ No newline at end of file
diff --git a/cmake/FindSuperLU.cmake b/cmake/FindSuperLU.cmake
index ca72b4498..8a3df3666 100644
--- a/cmake/FindSuperLU.cmake
+++ b/cmake/FindSuperLU.cmake
@@ -14,9 +14,10 @@ find_path(SUPERLU_INCLUDES
${INCLUDE_INSTALL_DIR}
PATH_SUFFIXES
superlu
+ SRC
)
-find_library(SUPERLU_LIBRARIES superlu PATHS $ENV{SUPERLUDIR} ${LIB_INSTALL_DIR})
+find_library(SUPERLU_LIBRARIES superlu PATHS $ENV{SUPERLUDIR} ${LIB_INSTALL_DIR} PATH_SUFFIXES lib)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(SUPERLU DEFAULT_MSG
diff --git a/cmake/FindUmfpack.cmake b/cmake/FindUmfpack.cmake
index d42c3c4a2..16b046cd6 100644
--- a/cmake/FindUmfpack.cmake
+++ b/cmake/FindUmfpack.cmake
@@ -20,31 +20,29 @@ find_library(UMFPACK_LIBRARIES umfpack PATHS $ENV{UMFPACKDIR} ${LIB_INSTALL_DIR}
if(UMFPACK_LIBRARIES)
- get_filename_component(UMFPACK_LIBDIR ${UMFPACK_LIBRARIES} PATH)
+ if (NOT UMFPACK_LIBDIR)
+ get_filename_component(UMFPACK_LIBDIR ${UMFPACK_LIBRARIES} PATH)
+ endif(NOT UMFPACK_LIBDIR)
+ find_library(COLAMD_LIBRARY colamd PATHS ${UMFPACK_LIBDIR} $ENV{UMFPACKDIR} ${LIB_INSTALL_DIR})
+ if (COLAMD_LIBRARY)
+ set(UMFPACK_LIBRARIES ${UMFPACK_LIBRARIES} ${COLAMD_LIBRARY})
+ endif (COLAMD_LIBRARY)
+
find_library(AMD_LIBRARY amd PATHS ${UMFPACK_LIBDIR} $ENV{UMFPACKDIR} ${LIB_INSTALL_DIR})
if (AMD_LIBRARY)
set(UMFPACK_LIBRARIES ${UMFPACK_LIBRARIES} ${AMD_LIBRARY})
- #else (AMD_LIBRARY)
- # set(UMFPACK_LIBRARIES FALSE)
endif (AMD_LIBRARY)
-endif(UMFPACK_LIBRARIES)
-
-if(UMFPACK_LIBRARIES)
-
- find_library(COLAMD_LIBRARY colamd PATHS ${UMFPACK_LIBDIR} $ENV{UMFPACKDIR} ${LIB_INSTALL_DIR})
- if (COLAMD_LIBRARY)
- set(UMFPACK_LIBRARIES ${UMFPACK_LIBRARIES} ${COLAMD_LIBRARY})
- #else (COLAMD_LIBRARY)
- # set(UMFPACK_LIBRARIES FALSE)
- endif (COLAMD_LIBRARY)
+ find_library(SUITESPARSE_LIBRARY SuiteSparse PATHS ${UMFPACK_LIBDIR} $ENV{UMFPACKDIR} ${LIB_INSTALL_DIR})
+ if (SUITESPARSE_LIBRARY)
+ set(UMFPACK_LIBRARIES ${UMFPACK_LIBRARIES} ${SUITESPARSE_LIBRARY})
+ endif (SUITESPARSE_LIBRARY)
endif(UMFPACK_LIBRARIES)
-
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(UMFPACK DEFAULT_MSG
UMFPACK_INCLUDES UMFPACK_LIBRARIES)
-mark_as_advanced(UMFPACK_INCLUDES UMFPACK_LIBRARIES AMD_LIBRARY COLAMD_LIBRARY)
+mark_as_advanced(UMFPACK_INCLUDES UMFPACK_LIBRARIES AMD_LIBRARY COLAMD_LIBRARY SUITESPARSE_LIBRARY)
diff --git a/cmake/language_support.cmake b/cmake/language_support.cmake
index 3414e6ea6..d687b71f6 100644
--- a/cmake/language_support.cmake
+++ b/cmake/language_support.cmake
@@ -23,7 +23,9 @@ function(workaround_9220 language language_works)
#message("DEBUG: language = ${language}")
set(text
"project(test NONE)
- cmake_minimum_required(VERSION 2.6.0)
+ cmake_minimum_required(VERSION 2.8.0)
+ set (CMAKE_Fortran_FLAGS \"${CMAKE_Fortran_FLAGS}\")
+ set (CMAKE_EXE_LINKER_FLAGS \"${CMAKE_EXE_LINKER_FLAGS}\")
enable_language(${language} OPTIONAL)
")
file(REMOVE_RECURSE ${CMAKE_BINARY_DIR}/language_tests/${language})
diff --git a/debug/gdb/printers.py b/debug/gdb/printers.py
index 9187acb33..86996a4f9 100644
--- a/debug/gdb/printers.py
+++ b/debug/gdb/printers.py
@@ -51,12 +51,12 @@ class EigenMatrixPrinter:
template_params = m.split(',')
template_params = map(lambda x:x.replace(" ", ""), template_params)
- if template_params[1] == '-0x00000000000000001' or template_params[1] == '-0x000000001':
+ if template_params[1] == '-0x00000000000000001' or template_params[1] == '-0x000000001' or template_params[1] == '-1':
self.rows = val['m_storage']['m_rows']
else:
self.rows = int(template_params[1])
- if template_params[2] == '-0x00000000000000001' or template_params[2] == '-0x000000001':
+ if template_params[2] == '-0x00000000000000001' or template_params[2] == '-0x000000001' or template_params[2] == '-1':
self.cols = val['m_storage']['m_cols']
else:
self.cols = int(template_params[2])
diff --git a/debug/msvc/eigen.natvis b/debug/msvc/eigen.natvis
new file mode 100644
index 000000000..da8985717
--- /dev/null
+++ b/debug/msvc/eigen.natvis
@@ -0,0 +1,235 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
+
+ <!-- Fixed x Fixed Matrix -->
+ <Type Name="Eigen::Matrix&lt;*,*,*,*,*,*&gt;">
+ <AlternativeType Name="Eigen::Array&lt;*,-1,-1,*,*,*&gt;"/>
+ <DisplayString>[{$T2}, {$T3}] (fixed matrix)</DisplayString>
+ <Expand>
+ <ArrayItems Condition="Flags%2"> <!-- row major layout -->
+ <Rank>2</Rank>
+ <Size>$i==0 ? $T2 : $T3</Size>
+ <ValuePointer>m_storage.m_data.array</ValuePointer>
+ </ArrayItems>
+ <ArrayItems Condition="!(Flags%2)"> <!-- column major layout -->
+ <Direction>Backward</Direction>
+ <Rank>2</Rank>
+ <Size>$i==0 ? $T2 : $T3</Size>
+ <ValuePointer>m_storage.m_data.array</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+
+ <!-- 2 x 2 Matrix -->
+ <Type Name="Eigen::Matrix&lt;*,2,2,*,*,*&gt;">
+ <AlternativeType Name="Eigen::Array&lt;*,2,2,*,*,*&gt;"/>
+ <DisplayString>[2, 2] (fixed matrix)</DisplayString>
+ <Expand>
+ <Synthetic Name="[row 0]" Condition="Flags%2">
+ <DisplayString>({m_storage.m_data.array[0]}, {m_storage.m_data.array[1]})</DisplayString>
+ </Synthetic>
+ <Synthetic Name="[row 0]" Condition="!(Flags%2)">
+ <DisplayString>({m_storage.m_data.array[0]}, {m_storage.m_data.array[2]})</DisplayString>
+ </Synthetic>
+ <Synthetic Name="[row 1]" Condition="Flags%2">
+ <DisplayString>({m_storage.m_data.array[2]}, {m_storage.m_data.array[3]})</DisplayString>
+ </Synthetic>
+ <Synthetic Name="[row 1]" Condition="!(Flags%2)">
+ <DisplayString>({m_storage.m_data.array[1]}, {m_storage.m_data.array[3]})</DisplayString>
+ </Synthetic>
+ </Expand>
+ </Type>
+
+ <!-- 3 x 3 Matrix -->
+ <Type Name="Eigen::Matrix&lt;*,3,3,*,*,*&gt;">
+ <AlternativeType Name="Eigen::Array&lt;*,3,3,*,*,*&gt;"/>
+ <DisplayString>[3, 3] (fixed matrix)</DisplayString>
+ <Expand>
+ <Synthetic Name="[row 0]" Condition="Flags%2">
+ <DisplayString>({m_storage.m_data.array[0]}, {m_storage.m_data.array[1]}, {m_storage.m_data.array[2]})</DisplayString>
+ </Synthetic>
+ <Synthetic Name="[row 0]" Condition="!(Flags%2)">
+ <DisplayString>({m_storage.m_data.array[0]}, {m_storage.m_data.array[3]}, {m_storage.m_data.array[6]})</DisplayString>
+ </Synthetic>
+ <Synthetic Name="[row 1]" Condition="Flags%2">
+ <DisplayString>({m_storage.m_data.array[3]}, {m_storage.m_data.array[4]}, {m_storage.m_data.array[5]})</DisplayString>
+ </Synthetic>
+ <Synthetic Name="[row 1]" Condition="!(Flags%2)">
+ <DisplayString>({m_storage.m_data.array[1]}, {m_storage.m_data.array[4]}, {m_storage.m_data.array[7]})</DisplayString>
+ </Synthetic>
+ <Synthetic Name="[row 2]" Condition="Flags%2">
+ <DisplayString>({m_storage.m_data.array[6]}, {m_storage.m_data.array[7]}, {m_storage.m_data.array[8]})</DisplayString>
+ </Synthetic>
+ <Synthetic Name="[row 2]" Condition="!(Flags%2)">
+ <DisplayString>({m_storage.m_data.array[2]}, {m_storage.m_data.array[5]}, {m_storage.m_data.array[8]})</DisplayString>
+ </Synthetic>
+ </Expand>
+ </Type>
+
+ <!-- 4 x 4 Matrix -->
+ <Type Name="Eigen::Matrix&lt;*,4,4,*,*,*&gt;">
+ <AlternativeType Name="Eigen::Array&lt;*,4,4,*,*,*&gt;"/>
+ <DisplayString>[4, 4] (fixed matrix)</DisplayString>
+ <Expand>
+ <Synthetic Name="[row 0]" Condition="Flags%2">
+ <DisplayString>({m_storage.m_data.array[0]}, {m_storage.m_data.array[1]}, {m_storage.m_data.array[2]}, {m_storage.m_data.array[3]})</DisplayString>
+ </Synthetic>
+ <Synthetic Name="[row 0]" Condition="!(Flags%2)">
+ <DisplayString>({m_storage.m_data.array[0]}, {m_storage.m_data.array[4]}, {m_storage.m_data.array[8]}, {m_storage.m_data.array[12]})</DisplayString>
+ </Synthetic>
+ <Synthetic Name="[row 1]" Condition="Flags%2">
+ <DisplayString>({m_storage.m_data.array[4]}, {m_storage.m_data.array[5]}, {m_storage.m_data.array[6]}, {m_storage.m_data.array[7]})</DisplayString>
+ </Synthetic>
+ <Synthetic Name="[row 1]" Condition="!(Flags%2)">
+ <DisplayString>({m_storage.m_data.array[1]}, {m_storage.m_data.array[5]}, {m_storage.m_data.array[9]}, {m_storage.m_data.array[13]})</DisplayString>
+ </Synthetic>
+ <Synthetic Name="[row 2]" Condition="Flags%2">
+ <DisplayString>({m_storage.m_data.array[8]}, {m_storage.m_data.array[9]}, {m_storage.m_data.array[10]}, {m_storage.m_data.array[11]})</DisplayString>
+ </Synthetic>
+ <Synthetic Name="[row 2]" Condition="!(Flags%2)">
+ <DisplayString>({m_storage.m_data.array[2]}, {m_storage.m_data.array[6]}, {m_storage.m_data.array[10]}, {m_storage.m_data.array[14]})</DisplayString>
+ </Synthetic>
+ <Synthetic Name="[row 3]" Condition="Flags%2">
+ <DisplayString>({m_storage.m_data.array[12]}, {m_storage.m_data.array[13]}, {m_storage.m_data.array[14]}, {m_storage.m_data.array[15]})</DisplayString>
+ </Synthetic>
+ <Synthetic Name="[row 3]" Condition="!(Flags%2)">
+ <DisplayString>({m_storage.m_data.array[3]}, {m_storage.m_data.array[7]}, {m_storage.m_data.array[11]}, {m_storage.m_data.array[15]})</DisplayString>
+ </Synthetic>
+ </Expand>
+ </Type>
+
+ <!-- Dynamic x Dynamic Matrix -->
+ <Type Name="Eigen::Matrix&lt;*,-1,-1,*,*,*&gt;">
+ <AlternativeType Name="Eigen::Array&lt;*,-1,-1,*,*,*&gt;"/>
+ <DisplayString Condition="m_storage.m_data == 0">empty</DisplayString>
+ <DisplayString Condition="m_storage.m_data != 0">[{m_storage.m_rows}, {m_storage.m_cols}] (dynamic matrix)</DisplayString>
+ <Expand>
+ <ArrayItems Condition="Flags%2"> <!-- row major layout -->
+ <Rank>2</Rank>
+ <Size>$i==0 ? m_storage.m_rows : m_storage.m_cols</Size>
+ <ValuePointer>m_storage.m_data</ValuePointer>
+ </ArrayItems>
+ <ArrayItems Condition="!(Flags%2)"> <!-- column major layout -->
+ <Direction>Backward</Direction>
+ <Rank>2</Rank>
+ <Size>$i==0 ? m_storage.m_rows : m_storage.m_cols</Size>
+ <ValuePointer>m_storage.m_data</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+
+ <!-- Fixed x Dynamic Matrix -->
+ <Type Name="Eigen::Matrix&lt;*,*,-1,*,*,*&gt;">
+ <AlternativeType Name="Eigen::Array&lt;*,*,-1,*,*,*&gt;"/>
+ <DisplayString Condition="m_storage.m_data == 0">empty</DisplayString>
+ <DisplayString Condition="m_storage.m_data != 0">[{$T2}, {m_storage.m_cols}] (dynamic column matrix)</DisplayString>
+ <Expand>
+ <ArrayItems Condition="Flags%2"> <!-- row major layout -->
+ <Rank>2</Rank>
+ <Size>$i==0 ? $T2 : m_storage.m_cols</Size>
+ <ValuePointer>m_storage.m_data</ValuePointer>
+ </ArrayItems>
+ <ArrayItems Condition="!(Flags%2)"> <!-- column major layout -->
+ <Direction>Backward</Direction>
+ <Rank>2</Rank>
+ <Size>$i==0 ? $T2 : m_storage.m_cols</Size>
+ <ValuePointer>m_storage.m_data</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+
+ <!-- Dynamic x Fixed Matrix -->
+ <Type Name="Eigen::Matrix&lt;*,-1,*,*,*,*&gt;">
+ <AlternativeType Name="Eigen::Array&lt;*,-1,*,*,*,*&gt;"/>
+ <DisplayString Condition="m_storage.m_data == 0">empty</DisplayString>
+ <DisplayString Condition="m_storage.m_data != 0">[{m_storage.m_rows}, {$T2}] (dynamic row matrix)</DisplayString>
+ <Expand>
+ <ArrayItems Condition="Flags%2"> <!-- row major layout -->
+ <Rank>2</Rank>
+ <Size>$i==0 ? m_storage.m_rows : $T2</Size>
+ <ValuePointer>m_storage.m_data</ValuePointer>
+ </ArrayItems>
+ <ArrayItems Condition="!(Flags%2)"> <!-- column major layout -->
+ <Direction>Backward</Direction>
+ <Rank>2</Rank>
+ <Size>$i==0 ? m_storage.m_rows : $T2</Size>
+ <ValuePointer>m_storage.m_data</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+
+ <!-- Dynamic Column Vector -->
+ <Type Name="Eigen::Matrix&lt;*,1,-1,*,*,*&gt;">
+ <AlternativeType Name="Eigen::Array&lt;*,1,-1,*,*,*&gt;"/>
+ <DisplayString Condition="m_storage.m_data == 0">empty</DisplayString>
+ <DisplayString Condition="m_storage.m_data != 0">[{m_storage.m_cols}] (dynamic column vector)</DisplayString>
+ <Expand>
+ <Item Name="[size]">m_storage.m_cols</Item>
+ <ArrayItems>
+ <Size>m_storage.m_cols</Size>
+ <ValuePointer>m_storage.m_data</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+
+ <!-- Dynamic Row Vector -->
+ <Type Name="Eigen::Matrix&lt;*,-1,1,*,*,*&gt;">
+ <AlternativeType Name="Eigen::Array&lt;*,-1,1,*,*,*&gt;"/>
+ <DisplayString Condition="m_storage.m_data == 0">empty</DisplayString>
+ <DisplayString Condition="m_storage.m_data != 0">[{m_storage.m_rows}] (dynamic row vector)</DisplayString>
+ <Expand>
+ <Item Name="[size]">m_storage.m_rows</Item>
+ <ArrayItems>
+ <Size>m_storage.m_rows</Size>
+ <ValuePointer>m_storage.m_data</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+
+ <!-- Fixed Vector -->
+ <Type Name="Eigen::Matrix&lt;*,1,1,*,*,*&gt;">
+ <AlternativeType Name="Eigen::Array&lt;*,1,1,*,*,*&gt;"/>
+ <DisplayString>[1] ({m_storage.m_data.array[0]})</DisplayString>
+ <Expand>
+ <Item Name="[x]">m_storage.m_data.array[0]</Item>
+ </Expand>
+ </Type>
+
+ <Type Name="Eigen::Matrix&lt;*,2,1,*,*,*&gt;">
+ <AlternativeType Name="Eigen::Matrix&lt;*,1,2,*,*,*&gt;"/>
+ <AlternativeType Name="Eigen::Array&lt;*,2,1,*,*,*&gt;"/>
+ <AlternativeType Name="Eigen::Array&lt;*,1,2,*,*,*&gt;"/>
+ <DisplayString>[2] ({m_storage.m_data.array[0]}, {m_storage.m_data.array[1]})</DisplayString>
+ <Expand>
+ <Item Name="[x]">m_storage.m_data.array[0]</Item>
+ <Item Name="[y]">m_storage.m_data.array[1]</Item>
+ </Expand>
+ </Type>
+
+ <Type Name="Eigen::Matrix&lt;*,3,1,*,*,*&gt;">
+ <AlternativeType Name="Eigen::Matrix&lt;*,1,3,*,*,*&gt;"/>
+ <AlternativeType Name="Eigen::Array&lt;*,3,1,*,*,*&gt;"/>
+ <AlternativeType Name="Eigen::Array&lt;*,1,3,*,*,*&gt;"/>
+ <DisplayString>[3] ({m_storage.m_data.array[0]}, {m_storage.m_data.array[1]}, {m_storage.m_data.array[2]})</DisplayString>
+ <Expand>
+ <Item Name="[x]">m_storage.m_data.array[0]</Item>
+ <Item Name="[y]">m_storage.m_data.array[1]</Item>
+ <Item Name="[z]">m_storage.m_data.array[2]</Item>
+ </Expand>
+ </Type>
+
+ <Type Name="Eigen::Matrix&lt;*,4,1,*,*,*&gt;">
+ <AlternativeType Name="Eigen::Matrix&lt;*,1,4,*,*,*&gt;"/>
+ <AlternativeType Name="Eigen::Array&lt;*,4,1,*,*,*&gt;"/>
+ <AlternativeType Name="Eigen::Array&lt;*,1,4,*,*,*&gt;"/>
+ <DisplayString>[4] ({m_storage.m_data.array[0]}, {m_storage.m_data.array[1]}, {m_storage.m_data.array[2]}, {m_storage.m_data.array[3]})</DisplayString>
+ <Expand>
+ <Item Name="[x]">m_storage.m_data.array[0]</Item>
+ <Item Name="[y]">m_storage.m_data.array[1]</Item>
+ <Item Name="[z]">m_storage.m_data.array[2]</Item>
+ <Item Name="[w]">m_storage.m_data.array[3]</Item>
+ </Expand>
+ </Type>
+
+</AutoVisualizer>
diff --git a/demos/opengl/CMakeLists.txt b/demos/opengl/CMakeLists.txt
index b98a30c01..299aa441d 100644
--- a/demos/opengl/CMakeLists.txt
+++ b/demos/opengl/CMakeLists.txt
@@ -1,20 +1,28 @@
-find_package(Qt4 REQUIRED)
-find_package(OpenGL REQUIRED)
+find_package(Qt4)
+find_package(OpenGL)
-set(QT_USE_QTOPENGL TRUE)
-include(${QT_USE_FILE})
+if(QT4_FOUND AND OPENGL_FOUND)
-set(CMAKE_INCLUDE_CURRENT_DIR ON)
+ set(QT_USE_QTOPENGL TRUE)
+ include(${QT_USE_FILE})
-include_directories( ${QT_INCLUDE_DIR} )
+ set(CMAKE_INCLUDE_CURRENT_DIR ON)
-set(quaternion_demo_SRCS gpuhelper.cpp icosphere.cpp camera.cpp trackball.cpp quaternion_demo.cpp)
+ include_directories( ${QT_INCLUDE_DIR} )
-qt4_automoc(${quaternion_demo_SRCS})
+ set(quaternion_demo_SRCS gpuhelper.cpp icosphere.cpp camera.cpp trackball.cpp quaternion_demo.cpp)
-add_executable(quaternion_demo ${quaternion_demo_SRCS})
-add_dependencies(demos quaternion_demo)
+ qt4_automoc(${quaternion_demo_SRCS})
-target_link_libraries(quaternion_demo
- ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY}
- ${QT_QTOPENGL_LIBRARY} ${OPENGL_LIBRARIES} )
+ add_executable(quaternion_demo ${quaternion_demo_SRCS})
+ add_dependencies(demos quaternion_demo)
+
+ target_link_libraries(quaternion_demo
+ ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY}
+ ${QT_QTOPENGL_LIBRARY} ${OPENGL_LIBRARIES} )
+
+else()
+
+ message(STATUS "OpenGL demo disabled because Qt4 and/or OpenGL have not been found.")
+
+endif() \ No newline at end of file
diff --git a/doc/A05_PortingFrom2To3.dox b/doc/A05_PortingFrom2To3.dox
index 10ce96870..4d5f3ae1f 100644
--- a/doc/A05_PortingFrom2To3.dox
+++ b/doc/A05_PortingFrom2To3.dox
@@ -2,31 +2,16 @@ namespace Eigen {
/** \page Eigen2ToEigen3 Porting from Eigen2 to Eigen3
+<div class="bigwarning">Eigen2 support is deprecated in Eigen 3.2.x and it will be removed in Eigen 3.3.</div>
+
This page lists the most important API changes between Eigen2 and Eigen3,
and gives tips to help porting your application from Eigen2 to Eigen3.
-\b Table \b of \b contents
- - \ref CompatibilitySupport
- - \ref Using
- - \ref ComplexDot
- - \ref VectorBlocks
- - \ref Corners
- - \ref CoefficientWiseOperations
- - \ref PartAndExtract
- - \ref TriangularSolveInPlace
- - \ref Decompositions
- - \ref LinearSolvers
- - \ref GeometryModule
- - \ref Transform
- - \ref LazyVsNoalias
- - \ref AlignMacros
- - \ref AlignedMap
- - \ref StdContainers
- - \ref eiPrefix
+\eigenAutoToc
\section CompatibilitySupport Eigen2 compatibility support
-In order to ease the switch from Eigen2 to Eigen3, Eigen3 features \ref Eigen2SupportModes "Eigen2 support modes".
+In order to ease the switch from Eigen2 to Eigen3, Eigen3 features \subpage Eigen2SupportModes "Eigen2 support modes".
The quick way to enable this is to define the \c EIGEN2_SUPPORT preprocessor token \b before including any Eigen header (typically it should be set in your project options).
@@ -298,7 +283,7 @@ result = Vector4f::MapAligned(some_aligned_array);
\section StdContainers STL Containers
-In Eigen2, #include<Eigen/StdVector> tweaked std::vector to automatically align elements. The problem was that that was quite invasive. In Eigen3, we only override standard behavior if you use Eigen::aligned_allocator<T> as your allocator type. So for example, if you use std::vector<Matrix4f>, you need to do the following change (note that aligned_allocator is under namespace Eigen):
+In Eigen2, <tt>#include<Eigen/StdVector></tt> tweaked std::vector to automatically align elements. The problem was that that was quite invasive. In Eigen3, we only override standard behavior if you use Eigen::aligned_allocator<T> as your allocator type. So for example, if you use std::vector<Matrix4f>, you need to do the following change (note that aligned_allocator is under namespace Eigen):
<table class="manual">
<tr><th>Eigen 2</th><th>Eigen 3</th></tr>
diff --git a/doc/A10_Eigen2SupportModes.dox b/doc/A10_Eigen2SupportModes.dox
index c20b64eed..f3df91515 100644
--- a/doc/A10_Eigen2SupportModes.dox
+++ b/doc/A10_Eigen2SupportModes.dox
@@ -2,18 +2,12 @@ namespace Eigen {
/** \page Eigen2SupportModes Eigen 2 support modes
+<div class="bigwarning">Eigen2 support is deprecated in Eigen 3.2.x and it will be removed in Eigen 3.3.</div>
+
This page documents the Eigen2 support modes, a powerful tool to help migrating your project from Eigen 2 to Eigen 3.
Don't miss our page on \ref Eigen2ToEigen3 "API changes" between Eigen 2 and Eigen 3.
-\b Table \b of \b contents
- - \ref EIGEN2_SUPPORT_Macro
- - \ref StagedMigrationPathOverview
- - \ref Stage10
- - \ref Stage20
- - \ref Stage30
- - \ref Stage40
- - \ref FinallyDropAllEigen2Support
- - \ref ABICompatibility
+\eigenAutoToc
\section EIGEN2_SUPPORT_Macro The quick way: define EIGEN2_SUPPORT
diff --git a/doc/AsciiQuickReference.txt b/doc/AsciiQuickReference.txt
index d2e973f5d..1e74e0528 100644
--- a/doc/AsciiQuickReference.txt
+++ b/doc/AsciiQuickReference.txt
@@ -1,8 +1,7 @@
// A simple quickref for Eigen. Add anything that's missing.
// Main author: Keir Mierle
-#include <Eigen/Core>
-#include <Eigen/Array>
+#include <Eigen/Dense>
Matrix<double, 3, 3> A; // Fixed rows and cols. Same as Matrix3d.
Matrix<double, 3, Dynamic> B; // Fixed rows, dynamic cols.
@@ -11,13 +10,14 @@ Matrix<double, 3, 3, RowMajor> E; // Row major; default is column-major.
Matrix3f P, Q, R; // 3x3 float matrix.
Vector3f x, y, z; // 3x1 float matrix.
RowVector3f a, b, c; // 1x3 float matrix.
+VectorXd v; // Dynamic column vector of doubles
double s;
// Basic usage
// Eigen // Matlab // comments
x.size() // length(x) // vector size
-C.rows() // size(C)(1) // number of rows
-C.cols() // size(C)(2) // number of columns
+C.rows() // size(C,1) // number of rows
+C.cols() // size(C,2) // number of columns
x(i) // x(i+1) // Matlab is 1-based
C(i,j) // C(i+1,j+1) //
@@ -31,9 +31,19 @@ A << 1, 2, 3, // Initialize A. The elements can also be
7, 8, 9; // and then the rows are stacked.
B << A, A, A; // B is three horizontally stacked A's.
A.fill(10); // Fill A with all 10's.
-A.setRandom(); // Fill A with uniform random numbers in (-1, 1).
- // Requires #include <Eigen/Array>.
-A.setIdentity(); // Fill A with the identity.
+
+// Eigen // Matlab
+MatrixXd::Identity(rows,cols) // eye(rows,cols)
+C.setIdentity(rows,cols) // C = eye(rows,cols)
+MatrixXd::Zero(rows,cols) // zeros(rows,cols)
+C.setZero(rows,cols) // C = ones(rows,cols)
+MatrixXd::Ones(rows,cols) // ones(rows,cols)
+C.setOnes(rows,cols) // C = ones(rows,cols)
+MatrixXd::Random(rows,cols) // rand(rows,cols)*2-1 // MatrixXd::Random returns uniform random numbers in (-1, 1).
+C.setRandom(rows,cols) // C = rand(rows,cols)*2-1
+VectorXd::LinSpaced(size,low,high) // linspace(low,high,size)'
+v.setLinSpaced(size,low,high) // v = linspace(low,high,size)'
+
// Matrix slicing and blocks. All expressions listed here are read/write.
// Templated size versions are faster. Note that Matlab is 1-based (a size N
@@ -41,20 +51,34 @@ A.setIdentity(); // Fill A with the identity.
// Eigen // Matlab
x.head(n) // x(1:n)
x.head<n>() // x(1:n)
-x.tail(n) // N = rows(x); x(N - n: N)
-x.tail<n>() // N = rows(x); x(N - n: N)
+x.tail(n) // x(end - n + 1: end)
+x.tail<n>() // x(end - n + 1: end)
x.segment(i, n) // x(i+1 : i+n)
x.segment<n>(i) // x(i+1 : i+n)
P.block(i, j, rows, cols) // P(i+1 : i+rows, j+1 : j+cols)
P.block<rows, cols>(i, j) // P(i+1 : i+rows, j+1 : j+cols)
+P.row(i) // P(i+1, :)
+P.col(j) // P(:, j+1)
+P.leftCols<cols>() // P(:, 1:cols)
+P.leftCols(cols) // P(:, 1:cols)
+P.middleCols<cols>(j) // P(:, j+1:j+cols)
+P.middleCols(j, cols) // P(:, j+1:j+cols)
+P.rightCols<cols>() // P(:, end-cols+1:end)
+P.rightCols(cols) // P(:, end-cols+1:end)
+P.topRows<rows>() // P(1:rows, :)
+P.topRows(rows) // P(1:rows, :)
+P.middleRows<rows>(i) // P(:, i+1:i+rows)
+P.middleRows(i, rows) // P(:, i+1:i+rows)
+P.bottomRows<rows>() // P(:, end-rows+1:end)
+P.bottomRows(rows) // P(:, end-rows+1:end)
P.topLeftCorner(rows, cols) // P(1:rows, 1:cols)
-P.topRightCorner(rows, cols) // [m n]=size(P); P(1:rows, n-cols+1:n)
-P.bottomLeftCorner(rows, cols) // [m n]=size(P); P(m-rows+1:m, 1:cols)
-P.bottomRightCorner(rows, cols) // [m n]=size(P); P(m-rows+1:m, n-cols+1:n)
+P.topRightCorner(rows, cols) // P(1:rows, end-cols+1:end)
+P.bottomLeftCorner(rows, cols) // P(end-rows+1:end, 1:cols)
+P.bottomRightCorner(rows, cols) // P(end-rows+1:end, end-cols+1:end)
P.topLeftCorner<rows,cols>() // P(1:rows, 1:cols)
-P.topRightCorner<rows,cols>() // [m n]=size(P); P(1:rows, n-cols+1:n)
-P.bottomLeftCorner<rows,cols>() // [m n]=size(P); P(m-rows+1:m, 1:cols)
-P.bottomRightCorner<rows,cols>() // [m n]=size(P); P(m-rows+1:m, n-cols+1:n)
+P.topRightCorner<rows,cols>() // P(1:rows, end-cols+1:end)
+P.bottomLeftCorner<rows,cols>() // P(end-rows+1:end, 1:cols)
+P.bottomRightCorner<rows,cols>() // P(end-rows+1:end, end-cols+1:end)
// Of particular note is Eigen's swap function which is highly optimized.
// Eigen // Matlab
@@ -67,6 +91,8 @@ R.adjoint() // R'
R.transpose() // R.' or conj(R')
R.diagonal() // diag(R)
x.asDiagonal() // diag(x)
+R.transpose().colwise().reverse(); // rot90(R)
+R.conjugate() // conj(R)
// All the same as Matlab, but matlab doesn't have *= style operators.
// Matrix-vector. Matrix-matrix. Matrix-scalar.
@@ -77,8 +103,7 @@ a *= M; R = P + Q; R = P/s;
R += Q; R *= s;
R -= Q; R /= s;
- // Vectorized operations on each element independently
- // (most require #include <Eigen/Array>)
+// Vectorized operations on each element independently
// Eigen // Matlab
R = P.cwiseProduct(Q); // R = P .* Q
R = P.array() * s.array();// R = P .* s
@@ -116,16 +141,14 @@ int r, c;
// Eigen // Matlab
R.minCoeff() // min(R(:))
R.maxCoeff() // max(R(:))
-s = R.minCoeff(&r, &c) // [aa, bb] = min(R); [cc, dd] = min(aa);
- // r = bb(dd); c = dd; s = cc
-s = R.maxCoeff(&r, &c) // [aa, bb] = max(R); [cc, dd] = max(aa);
- // row = bb(dd); col = dd; s = cc
+s = R.minCoeff(&r, &c) // [s, i] = min(R(:)); [r, c] = ind2sub(size(R), i);
+s = R.maxCoeff(&r, &c) // [s, i] = max(R(:)); [r, c] = ind2sub(size(R), i);
R.sum() // sum(R(:))
-R.colwise.sum() // sum(R)
-R.rowwise.sum() // sum(R, 2) or sum(R')'
+R.colwise().sum() // sum(R)
+R.rowwise().sum() // sum(R, 2) or sum(R')'
R.prod() // prod(R(:))
-R.colwise.prod() // prod(R)
-R.rowwise.prod() // prod(R, 2) or prod(R')'
+R.colwise().prod() // prod(R)
+R.rowwise().prod() // prod(R, 2) or prod(R')'
R.trace() // trace(R)
R.all() // all(R(:))
R.colwise().all() // all(R)
@@ -141,21 +164,34 @@ x.squaredNorm() // dot(x, x) Note the equivalence is not true for co
x.dot(y) // dot(x, y)
x.cross(y) // cross(x, y) Requires #include <Eigen/Geometry>
+//// Type conversion
+// Eigen // Matlab
+A.cast<double>(); // double(A)
+A.cast<float>(); // single(A)
+A.cast<int>(); // int32(A)
+A.real(); // real(A)
+A.imag(); // imag(A)
+// if the original type equals destination type, no work is done
+
+// Note that for most operations Eigen requires all operands to have the same type:
+MatrixXf F = MatrixXf::Zero(3,3);
+A += F; // illegal in Eigen. In Matlab A = A+F is allowed
+A += F.cast<double>(); // F converted to double and then added (generally, conversion happens on-the-fly)
+
// Eigen can map existing memory into Eigen matrices.
float array[3];
-Map<Vector3f>(array, 3).fill(10);
-int data[4] = 1, 2, 3, 4;
-Matrix2i mat2x2(data);
-MatrixXi mat2x2 = Map<Matrix2i>(data);
-MatrixXi mat2x2 = Map<MatrixXi>(data, 2, 2);
+Vector3f::Map(array).fill(10); // create a temporary Map over array and sets entries to 10
+int data[4] = {1, 2, 3, 4};
+Matrix2i mat2x2(data); // copies data into mat2x2
+Matrix2i::Map(data) = 2*mat2x2; // overwrite elements of data with 2*mat2x2
+MatrixXi::Map(data, 2, 2) += mat2x2; // adds mat2x2 to elements of data (alternative syntax if size is not know at compile time)
// Solve Ax = b. Result stored in x. Matlab: x = A \ b.
-bool solved;
-solved = A.ldlt().solve(b, &x)); // A sym. p.s.d. #include <Eigen/Cholesky>
-solved = A.llt() .solve(b, &x)); // A sym. p.d. #include <Eigen/Cholesky>
-solved = A.lu() .solve(b, &x)); // Stable and fast. #include <Eigen/LU>
-solved = A.qr() .solve(b, &x)); // No pivoting. #include <Eigen/QR>
-solved = A.svd() .solve(b, &x)); // Stable, slowest. #include <Eigen/SVD>
+x = A.ldlt().solve(b)); // A sym. p.s.d. #include <Eigen/Cholesky>
+x = A.llt() .solve(b)); // A sym. p.d. #include <Eigen/Cholesky>
+x = A.lu() .solve(b)); // Stable and fast. #include <Eigen/LU>
+x = A.qr() .solve(b)); // No pivoting. #include <Eigen/QR>
+x = A.svd() .solve(b)); // Stable, slowest. #include <Eigen/SVD>
// .ldlt() -> .matrixL() and .matrixD()
// .llt() -> .matrixL()
// .lu() -> .matrixL() and .matrixU()
@@ -168,3 +204,4 @@ A.eigenvalues(); // eig(A);
EigenSolver<Matrix3d> eig(A); // [vec val] = eig(A)
eig.eigenvalues(); // diag(val)
eig.eigenvectors(); // vec
+// For self-adjoint matrices use SelfAdjointEigenSolver<>
diff --git a/doc/B01_Experimental.dox b/doc/B01_Experimental.dox
index 6d8b90d5a..5fc0ccd60 100644
--- a/doc/B01_Experimental.dox
+++ b/doc/B01_Experimental.dox
@@ -2,10 +2,7 @@ namespace Eigen {
/** \page Experimental Experimental parts of Eigen
-\b Table \b of \b contents
- - \ref summary
- - \ref modules
- - \ref core
+\eigenAutoToc
\section summary Summary
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
index 96bff41bf..8a493031c 100644
--- a/doc/CMakeLists.txt
+++ b/doc/CMakeLists.txt
@@ -10,14 +10,28 @@ if(CMAKE_COMPILER_IS_GNUCXX)
endif(CMAKE_SYSTEM_NAME MATCHES Linux)
endif(CMAKE_COMPILER_IS_GNUCXX)
+# Set some Doxygen flags
+set(EIGEN_DOXY_PROJECT_NAME "Eigen")
+set(EIGEN_DOXY_OUTPUT_DIRECTORY_SUFFIX "")
+set(EIGEN_DOXY_INPUT "\"${Eigen_SOURCE_DIR}/Eigen\" \"${Eigen_SOURCE_DIR}/doc\"")
+set(EIGEN_DOXY_HTML_COLORSTYLE_HUE "220")
+set(EIGEN_DOXY_TAGFILES "")
+
configure_file(
- ${Eigen_SOURCE_DIR}/unsupported/doc/Doxyfile.in
- ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile-unsupported
+ ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
+ ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
)
+set(EIGEN_DOXY_PROJECT_NAME "Eigen-unsupported")
+set(EIGEN_DOXY_OUTPUT_DIRECTORY_SUFFIX "/unsupported")
+set(EIGEN_DOXY_INPUT "\"${Eigen_SOURCE_DIR}/unsupported/Eigen\" \"${Eigen_SOURCE_DIR}/unsupported/doc\"")
+set(EIGEN_DOXY_HTML_COLORSTYLE_HUE "0")
+# set(EIGEN_DOXY_TAGFILES "\"${Eigen_BINARY_DIR}/doc/eigen.doxytags =../\"")
+set(EIGEN_DOXY_TAGFILES "")
+
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
- ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
+ ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile-unsupported
)
configure_file(
@@ -30,10 +44,21 @@ configure_file(
${CMAKE_CURRENT_BINARY_DIR}/eigendoxy_footer.html
)
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/eigendoxy_layout.xml.in
+ ${CMAKE_CURRENT_BINARY_DIR}/eigendoxy_layout.xml
+)
+
+configure_file(
+ ${Eigen_SOURCE_DIR}/unsupported/doc/eigendoxy_layout.xml.in
+ ${Eigen_BINARY_DIR}/doc/unsupported/eigendoxy_layout.xml
+)
+
set(examples_targets "")
set(snippets_targets "")
add_definitions("-DEIGEN_MAKING_DOCS")
+add_custom_target(all_examples)
add_subdirectory(examples)
add_subdirectory(special_examples)
@@ -43,12 +68,9 @@ add_custom_target(
doc-eigen-prerequisites
ALL
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/html/
- COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/eigendoxy_tabs.css
- ${CMAKE_CURRENT_BINARY_DIR}/html/
- COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/Eigen_Silly_Professor_64x64.png
- ${CMAKE_CURRENT_BINARY_DIR}/html/
- COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/AsciiQuickReference.txt
- ${CMAKE_CURRENT_BINARY_DIR}/html/
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/eigen_navtree_hacks.js ${CMAKE_CURRENT_BINARY_DIR}/html/
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/Eigen_Silly_Professor_64x64.png ${CMAKE_CURRENT_BINARY_DIR}/html/
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/AsciiQuickReference.txt ${CMAKE_CURRENT_BINARY_DIR}/html/
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
@@ -56,10 +78,8 @@ add_custom_target(
doc-unsupported-prerequisites
ALL
COMMAND ${CMAKE_COMMAND} -E make_directory ${Eigen_BINARY_DIR}/doc/html/unsupported
- COMMAND ${CMAKE_COMMAND} -E copy ${Eigen_SOURCE_DIR}/doc/eigendoxy_tabs.css
- ${Eigen_BINARY_DIR}/doc/html/unsupported/
- COMMAND ${CMAKE_COMMAND} -E copy ${Eigen_SOURCE_DIR}/doc/Eigen_Silly_Professor_64x64.png
- ${Eigen_BINARY_DIR}/doc/html/unsupported/
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/eigen_navtree_hacks.js ${CMAKE_CURRENT_BINARY_DIR}/html/unsupported/
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/Eigen_Silly_Professor_64x64.png ${CMAKE_CURRENT_BINARY_DIR}/html/unsupported/
WORKING_DIRECTORY ${Eigen_BINARY_DIR}/doc
)
@@ -67,11 +87,11 @@ add_dependencies(doc-eigen-prerequisites all_snippets all_examples)
add_dependencies(doc-unsupported-prerequisites unsupported_snippets unsupported_examples)
add_custom_target(doc ALL
- COMMAND doxygen Doxyfile-unsupported
COMMAND doxygen
- COMMAND doxygen Doxyfile-unsupported # run doxygen twice to get proper eigen <=> unsupported cross references
+ COMMAND doxygen Doxyfile-unsupported
COMMAND ${CMAKE_COMMAND} -E rename html eigen-doc
- COMMAND ${CMAKE_COMMAND} -E tar cvfz eigen-doc/eigen-doc.tgz eigen-doc/*.html eigen-doc/*.map eigen-doc/*.png eigen-doc/*.css eigen-doc/*.js eigen-doc/*.txt eigen-doc/unsupported
+ COMMAND ${CMAKE_COMMAND} -E remove eigen-doc/eigen-doc.tgz
+ COMMAND ${CMAKE_COMMAND} -E tar cfz eigen-doc/eigen-doc.tgz eigen-doc
COMMAND ${CMAKE_COMMAND} -E rename eigen-doc html
WORKING_DIRECTORY ${Eigen_BINARY_DIR}/doc)
diff --git a/doc/I12_ClassHierarchy.dox b/doc/ClassHierarchy.dox
index 700d01802..468e60a76 100644
--- a/doc/I12_ClassHierarchy.dox
+++ b/doc/ClassHierarchy.dox
@@ -6,11 +6,7 @@ This page explains the design of the core classes in Eigen's class hierarchy and
users probably need not concern themselves with these details, but it may be useful for both advanced users
and Eigen developers.
-<b>Table of contents</b>
- - \ref TopicClassHierarchyPrinciples
- - \ref TopicClassHierarchyCoreClasses
- - \ref TopicClassHierarchyBaseClasses
- - \ref TopicClassHierarchyInheritanceDiagrams
+\eigenAutoToc
\section TopicClassHierarchyPrinciples Principles
diff --git a/doc/I00_CustomizingEigen.dox b/doc/CustomizingEigen.dox
index aa4514d68..5a0890ea9 100644
--- a/doc/I00_CustomizingEigen.dox
+++ b/doc/CustomizingEigen.dox
@@ -4,10 +4,7 @@ namespace Eigen {
Eigen can be extended in several ways, for instance, by defining global methods, \ref ExtendingMatrixBase "by adding custom methods to MatrixBase", adding support to \ref CustomScalarType "custom types" etc.
-\b Table \b of \b contents
- - \ref ExtendingMatrixBase
- - \ref InheritingFromMatrix
- - \ref CustomScalarType
+\eigenAutoToc
\section ExtendingMatrixBase Extending MatrixBase (and other classes)
@@ -127,7 +124,7 @@ Eigen::MatrixBase<Eigen::Matrix<std::complex<float>, 10000, 1, 2, 10000, 1>
\anchor user_defined_scalars \section CustomScalarType Using custom scalar types
-By default, Eigen currently supports standard floating-point types (\c float, \c double, \c std::complex<float>, \c std::complex<double>, \c long \c double), as well as all integrale types (e.g., \c int, \c unsigned \c int, \c short, etc.), and \c bool.
+By default, Eigen currently supports standard floating-point types (\c float, \c double, \c std::complex<float>, \c std::complex<double>, \c long \c double), as well as all native integer types (e.g., \c int, \c unsigned \c int, \c short, etc.), and \c bool.
On x86-64 systems, \c long \c double permits to locally enforces the use of x87 registers with extended accuracy (in comparison to SSE).
In order to add support for a custom type \c T you need:
@@ -136,7 +133,7 @@ In order to add support for a custom type \c T you need:
-# define the math functions that makes sense for your type. This includes standard ones like sqrt, pow, sin, tan, conj, real, imag, etc, as well as abs2 which is Eigen specific.
(see the file Eigen/src/Core/MathFunctions.h)
-The math function should be defined in the same namespace than \c T, or in the \c std namespace though that second appraoch is not recommended.
+The math function should be defined in the same namespace than \c T, or in the \c std namespace though that second approach is not recommended.
Here is a concrete example adding support for the Adolc's \c adouble type. <a href="https://projects.coin-or.org/ADOL-C">Adolc</a> is an automatic differentiation library. The type \c adouble is basically a real value tracking the values of any number of partial derivatives.
diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in
index e9e89d486..1a2603b04 100644
--- a/doc/Doxyfile.in
+++ b/doc/Doxyfile.in
@@ -1,12 +1,14 @@
+# Doxyfile 1.8.1.1
+
# This file describes the settings to be used by the documentation system
-# doxygen (www.doxygen.org) for a project
+# doxygen (www.doxygen.org) for a project.
#
-# All text after a hash (#) is considered a comment and will be ignored
+# All text after a hash (#) is considered a comment and will be ignored.
# The format is:
# TAG = value [value, ...]
# For lists items can also be appended using:
# TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (" ")
+# Values that contain spaces should be placed between quotes (" ").
#---------------------------------------------------------------------------
# Project related configuration options
@@ -20,24 +22,39 @@
DOXYFILE_ENCODING = UTF-8
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
-# by quotes) that should identify the project.
+# The PROJECT_NAME tag is a single word (or sequence of words) that should
+# identify the project. Note that if you do not use Doxywizard you need
+# to put quotes around the project name if it contains spaces.
-PROJECT_NAME = Eigen
+PROJECT_NAME = ${EIGEN_DOXY_PROJECT_NAME}
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
# This could be handy for archiving the generated documentation or
# if some version control system is used.
-#EIGEN_VERSION is set in the root CMakeLists.txt
+# EIGEN_VERSION is set in the root CMakeLists.txt
+
PROJECT_NUMBER = "${EIGEN_VERSION}"
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO = "${Eigen_SOURCE_DIR}/doc/Eigen_Silly_Professor_64x64.png"
+
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
-OUTPUT_DIRECTORY = "${Eigen_BINARY_DIR}/doc"
+OUTPUT_DIRECTORY = "${Eigen_BINARY_DIR}/doc${EIGEN_DOXY_OUTPUT_DIRECTORY_SUFFIX}"
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
# 4096 sub-directories (in 2 levels) under the output directory of each output
@@ -53,11 +70,11 @@ CREATE_SUBDIRS = NO
# information to generate all constant output in the proper language.
# The default language is English, other supported languages are:
# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
-# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
-# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
-# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
-# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish,
-# and Ukrainian.
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
OUTPUT_LANGUAGE = English
@@ -135,7 +152,7 @@ STRIP_FROM_PATH =
STRIP_FROM_INC_PATH =
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
-# (but less readable) file names. This can be useful is your file systems
+# (but less readable) file names. This can be useful if your file system
# doesn't support long names like on DOS, Mac, or CD-ROM.
SHORT_NAMES = NO
@@ -164,13 +181,6 @@ QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
-# If the DETAILS_AT_TOP tag is set to YES then Doxygen
-# will output the detailed description near the top, like JavaDoc.
-# If set to NO, the detailed description appears after the member
-# documentation.
-
-DETAILS_AT_TOP = YES
-
# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
# member inherits the documentation from any documented member that it
# re-implements.
@@ -211,7 +221,18 @@ ALIASES = "only_for_vectors=This is only for vectors (either row-
"note_about_arbitrary_choice_of_solution=If there exists more than one solution, this method will arbitrarily choose one." \
"note_about_using_kernel_to_study_multiple_solutions=If you need a complete analysis of the space of solutions, take the one solution obtained by this method and add to it elements of the kernel, as determined by kernel()." \
"note_about_checking_solutions=This method just tries to find as good a solution as possible. If you want to check whether a solution exists or if it is accurate, just call this function to get a result and then compute the error of this result, or use MatrixBase::isApprox() directly, for instance like this: \code bool a_solution_exists = (A*result).isApprox(b, precision); \endcode This method avoids dividing by zero, so that the non-existence of a solution doesn't by itself mean that you'll get \c inf or \c nan values." \
- "note_try_to_help_rvo=This function returns the result by value. In order to make that efficient, it is implemented as just a return statement using a special constructor, hopefully allowing the compiler to perform a RVO (return value optimization)."
+ "note_try_to_help_rvo=This function returns the result by value. In order to make that efficient, it is implemented as just a return statement using a special constructor, hopefully allowing the compiler to perform a RVO (return value optimization)." \
+ "nonstableyet=\warning This is not considered to be part of the stable public API yet. Changes may happen in future releases. See \ref Experimental \"Experimental parts of Eigen\"
+
+ALIASES += "eigenAutoToc= "
+ALIASES += "eigenManualPage=\defgroup"
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding
+# "class=itcl::class" will allow you to use the command class in the
+# itcl::class meaning.
+
+TCL_SUBST =
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
# sources only. Doxygen will then generate output that is more tailored for C.
@@ -239,11 +260,32 @@ OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this
+# tag. The format is ext=language, where ext is a file extension, and language
+# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
+# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
+# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
+# comments according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you
+# can mix doxygen, HTML, and XML commands with Markdown formatting.
+# Disable only in case of backward compatibilities issues.
+
+MARKDOWN_SUPPORT = YES
+
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
# to include (a tag file for) the STL sources as input, then you should
# set this tag to YES in order to let doxygen match functions declarations and
# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
-# func(std::string) {}). This also make the inheritance and collaboration
+# func(std::string) {}). This also makes the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
BUILTIN_STL_SUPPORT = NO
@@ -261,7 +303,7 @@ SIP_SUPPORT = NO
# For Microsoft's IDL there are propget and propput attributes to indicate getter
# and setter methods for a property. Setting this option to YES (the default)
-# will make doxygen to replace the get and set methods by a property in the
+# will make doxygen replace the get and set methods by a property in the
# documentation. This will only work if the methods are indeed getting or
# setting a simple type. If this is not the case, or you want to show the
# methods anyway, you should set this option to NO.
@@ -283,6 +325,22 @@ DISTRIBUTE_GROUP_DOC = NO
SUBGROUPING = YES
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
+# unions with only public data fields will be shown inline in the documentation
+# of the scope in which they are defined (i.e. file, namespace, or group
+# documentation), provided this scope is documented. If set to NO (the default),
+# structs, classes, and unions are shown on a separate page (for HTML and Man
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS = NO
+
# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
# is documented as struct, union, or enum with the name of the typedef. So
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
@@ -293,6 +351,33 @@ SUBGROUPING = YES
TYPEDEF_HIDES_STRUCT = NO
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+SYMBOL_CACHE_SIZE = 0
+
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
+# their name and scope. Since this can be an expensive process and often the
+# same symbol appear multiple times in the code, doxygen keeps a cache of
+# pre-resolved symbols. If the cache is too small doxygen will become slower.
+# If the cache is too large, memory is wasted. The cache size is given by this
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE = 0
+
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
@@ -302,13 +387,17 @@ TYPEDEF_HIDES_STRUCT = NO
# Private class members and static file members will be hidden unless
# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
-EXTRACT_ALL = YES
+EXTRACT_ALL = NO
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
# will be included in the documentation.
EXTRACT_PRIVATE = NO
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation.
+
+EXTRACT_PACKAGE = NO
+
# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
@@ -331,7 +420,7 @@ EXTRACT_LOCAL_METHODS = NO
# extracted and appear in the documentation as a namespace called
# 'anonymous_namespace{file}', where file will be replaced with the base
# name of the file that contains the anonymous namespace. By default
-# anonymous namespace are hidden.
+# anonymous namespaces are hidden.
EXTRACT_ANON_NSPACES = NO
@@ -389,7 +478,13 @@ HIDE_SCOPE_NAMES = YES
# will put a list of the files that are included by a file in the documentation
# of that file.
-SHOW_INCLUDE_FILES = YES
+SHOW_INCLUDE_FILES = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES = NO
# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
# is inserted in the documentation for inline members.
@@ -410,6 +505,16 @@ SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = YES
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
# hierarchy of group names into alphabetical order. If set to NO (the default)
# the group names will appear in their defined order.
@@ -426,6 +531,15 @@ SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING = NO
+
# The GENERATE_TODOLIST tag can be used to enable (YES) or
# disable (NO) the todo list. This list is created by putting \todo
# commands in the documentation.
@@ -456,10 +570,10 @@ GENERATE_DEPRECATEDLIST= NO
ENABLED_SECTIONS =
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
-# the initial value of a variable or define consists of for it to appear in
+# the initial value of a variable or macro consists of for it to appear in
# the documentation. If the initializer consists of more lines than specified
# here it will be hidden. Use a value of 0 to hide initializers completely.
-# The appearance of the initializer of individual variables and defines in the
+# The appearance of the initializer of individual variables and macros in the
# documentation can be controlled using \showinitializer or \hideinitializer
# command in the documentation regardless of this setting.
@@ -471,12 +585,6 @@ MAX_INITIALIZER_LINES = 0
SHOW_USED_FILES = YES
-# If the sources in your project are distributed over multiple directories
-# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
-# in the documentation. The default is NO.
-
-SHOW_DIRECTORIES = NO
-
# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
# This will remove the Files entry from the Quick Index and from the
# Folder Tree View (if specified). The default is YES.
@@ -484,10 +592,11 @@ SHOW_DIRECTORIES = NO
SHOW_FILES = YES
# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
-# Namespaces page. This will remove the Namespaces entry from the Quick Index
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
# and from the Folder Tree View (if specified). The default is YES.
-SHOW_NAMESPACES = YES
+SHOW_NAMESPACES = NO
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
# doxygen should invoke to get the current version for each file (typically from
@@ -499,6 +608,25 @@ SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE = "${Eigen_BINARY_DIR}/doc${EIGEN_DOXY_OUTPUT_DIRECTORY_SUFFIX}/eigendoxy_layout.xml"
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files
+# containing the references data. This must be a list of .bib files. The
+# .bib extension is automatically appended if omitted. Using this command
+# requires the bibtex tool to be installed. See also
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
+# feature you need bibtex and perl available in the search path.
+
+CITE_BIB_FILES =
+
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
@@ -527,7 +655,7 @@ WARN_IF_UNDOCUMENTED = NO
WARN_IF_DOC_ERROR = YES
-# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
# functions that are documented, but have no documentation for their parameters
# or return value. If set to NO (the default) doxygen will only warn about
# wrong or incomplete parameter documentation, but not about the absence of
@@ -559,8 +687,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
-INPUT = "${Eigen_SOURCE_DIR}/Eigen" \
- "${Eigen_SOURCE_DIR}/doc"
+INPUT = ${EIGEN_DOXY_INPUT}
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
@@ -574,8 +701,9 @@ INPUT_ENCODING = UTF-8
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank the following patterns are tested:
-# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
-# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
FILE_PATTERNS = *
@@ -585,18 +713,22 @@ FILE_PATTERNS = *
RECURSIVE = YES
-# The EXCLUDE tag can be used to specify files and/or directories that should
+# The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
EXCLUDE = "${Eigen_SOURCE_DIR}/Eigen/Eigen2Support" \
"${Eigen_SOURCE_DIR}/Eigen/src/Eigen2Support" \
"${Eigen_SOURCE_DIR}/doc/examples" \
"${Eigen_SOURCE_DIR}/doc/special_examples" \
- "${Eigen_SOURCE_DIR}/doc/snippets"
+ "${Eigen_SOURCE_DIR}/doc/snippets" \
+ "${Eigen_SOURCE_DIR}/unsupported/doc/examples" \
+ "${Eigen_SOURCE_DIR}/unsupported/doc/snippets"
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
-# directories that are symbolic links (a Unix filesystem feature) are excluded
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
# from the input.
EXCLUDE_SYMLINKS = NO
@@ -607,21 +739,21 @@ EXCLUDE_SYMLINKS = NO
# against the file with absolute path, so to exclude all test directories
# for example use the pattern */test/*
-EXCLUDE_PATTERNS = CMake* \
- *.txt \
- *.sh \
- *.orig \
- *.diff \
- diff \
- *~ \
- *. \
- *.sln \
- *.sdf \
- *.tmp \
- *.vcxproj \
- *.filters \
- *.user \
- *.suo
+EXCLUDE_PATTERNS = CMake* \
+ *.txt \
+ *.sh \
+ *.orig \
+ *.diff \
+ diff \
+ *~ \
+ *. \
+ *.sln \
+ *.sdf \
+ *.tmp \
+ *.vcxproj \
+ *.filters \
+ *.user \
+ *.suo
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
@@ -629,8 +761,11 @@ EXCLUDE_PATTERNS = CMake* \
# wildcard * is used, a substring. Examples: ANamespace, AClass,
# AClass::ANamespace, ANamespace::*Test
-# This could used to clean up the "class hierarchy" page
-EXCLUDE_SYMBOLS = internal::* Flagged* *InnerIterator* DenseStorage<*
+EXCLUDE_SYMBOLS = internal::* \
+ Flagged* \
+ *InnerIterator* \
+ DenseStorage<* \
+
# The EXAMPLE_PATH tag can be used to specify one or more files or
# directories that contain example code fragments that are included (see
@@ -641,7 +776,11 @@ EXAMPLE_PATH = "${Eigen_SOURCE_DIR}/doc/snippets" \
"${Eigen_SOURCE_DIR}/doc/examples" \
"${Eigen_BINARY_DIR}/doc/examples" \
"${Eigen_SOURCE_DIR}/doc/special_examples" \
- "${Eigen_BINARY_DIR}/doc/special_examples"
+ "${Eigen_BINARY_DIR}/doc/special_examples" \
+ "${Eigen_SOURCE_DIR}/unsupported/doc/snippets" \
+ "${Eigen_BINARY_DIR}/unsupported/doc/snippets" \
+ "${Eigen_SOURCE_DIR}/unsupported/doc/examples" \
+ "${Eigen_BINARY_DIR}/unsupported/doc/examples"
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
@@ -668,17 +807,20 @@ IMAGE_PATH =
# by executing (via popen()) the command <filter> <input-file>, where <filter>
# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
# input file. Doxygen will then use the output that the filter program writes
-# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
# ignored.
INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
-# basis. Doxygen will compare the file name with each pattern and apply the
-# filter if there is a match. The filters are a list of the form:
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
-# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
-# is applied to all files.
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
FILTER_PATTERNS =
@@ -688,6 +830,14 @@ FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
@@ -706,7 +856,7 @@ INLINE_SOURCES = NO
# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
# doxygen to hide any special comment blocks from generated source code
-# fragments. Normal C and C++ comments will always remain visible.
+# fragments. Normal C, C++ and Fortran comments will always remain visible.
STRIP_CODE_COMMENTS = YES
@@ -725,7 +875,8 @@ REFERENCES_RELATION = YES
# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
-# link to the source code. Otherwise they will link to the documentstion.
+# link to the source code.
+# Otherwise they will link to the documentation.
REFERENCES_LINK_SOURCE = YES
@@ -779,7 +930,7 @@ GENERATE_HTML = YES
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `html' will be used as the default path.
-HTML_OUTPUT = html
+HTML_OUTPUT = "${Eigen_BINARY_DIR}/doc/html${EIGEN_DOXY_OUTPUT_DIRECTORY_SUFFIX}"
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
@@ -789,39 +940,89 @@ HTML_FILE_EXTENSION = .html
# The HTML_HEADER tag can be used to specify a personal HTML header for
# each generated HTML page. If it is left blank doxygen will generate a
-# standard header.
+# standard header. Note that when using a custom header you are responsible
+# for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is advised to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
-HTML_HEADER = "${Eigen_BINARY_DIR}/doc/eigendoxy_header.html"
+HTML_HEADER = "${Eigen_BINARY_DIR}/doc/eigendoxy_header.html"
# The HTML_FOOTER tag can be used to specify a personal HTML footer for
# each generated HTML page. If it is left blank doxygen will generate a
# standard footer.
-# the footer has not been customized yet, so let's use the default one
-# ${Eigen_BINARY_DIR}/doc/eigendoxy_footer.html
-HTML_FOOTER =
+HTML_FOOTER = "${Eigen_BINARY_DIR}/doc/eigendoxy_footer.html"
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
# style sheet that is used by each HTML page. It can be used to
# fine-tune the look of the HTML output. If the tag is left blank doxygen
# will generate a default style sheet. Note that doxygen will try to copy
# the style sheet file to the HTML output directory, so don't put your own
-# stylesheet in the HTML output directory as well, or it will be erased!
+# style sheet in the HTML output directory as well, or it will be erased!
-HTML_STYLESHEET = "${Eigen_SOURCE_DIR}/doc/eigendoxy.css"
+HTML_STYLESHEET =
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
-# files or namespaces will be aligned in HTML using tables. If set to
-# NO a bullet list will be used.
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
-HTML_ALIGN_MEMBERS = YES
+HTML_EXTRA_FILES = "${Eigen_SOURCE_DIR}/doc/eigendoxy.css"
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files
-# will be generated that can be used as input for tools like the
-# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
-# of the generated HTML documentation.
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the style sheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+# The default is 220.
-GENERATE_HTMLHELP = NO
+HTML_COLORSTYLE_HUE = ${EIGEN_DOXY_HTML_COLORSTYLE_HUE}
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+
+HTML_DYNAMIC_SECTIONS = YES
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
+# entries shown in the various tree structured indices initially; the user
+# can expand and collapse entries dynamically later on. Doxygen will expand
+# the tree to such a level that at most the specified number of entries are
+# visible (unless a fully collapsed tree already exceeds this amount).
+# So setting the number of entries 1 will produce a full collapsed tree by
+# default. 0 is a special value representing an infinite number of entries
+# and will result in a full expanded tree by default.
+
+HTML_INDEX_NUM_ENTRIES = 100
# If the GENERATE_DOCSET tag is set to YES, additional index files
# will be generated that can be used as input for Apple's Xcode 3
@@ -831,6 +1032,8 @@ GENERATE_HTMLHELP = NO
# directory and running "make install" will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
GENERATE_DOCSET = NO
@@ -848,13 +1051,22 @@ DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
-# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
-# documentation will contain sections that can be hidden and shown after the
-# page has loaded. For this to work a browser that supports
-# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
-# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
-HTML_DYNAMIC_SECTIONS = YES
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
# be used to specify the file name of the resulting .chm file. You
@@ -893,33 +1105,102 @@ BINARY_TOC = NO
TOC_EXPAND = NO
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
-# top of each HTML page. The value NO (the default) enables the index and
-# the value YES disables it.
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
-DISABLE_INDEX = NO
+GENERATE_QHP = NO
-# This tag can be used to set the number of enum values (range [1..20])
-# that doxygen will group on one line in the generated HTML documentation.
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
-ENUM_VALUES_PER_LINE = 1
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
+# at top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it. Since the tabs have the same information as the
+# navigation tree you can set this option to NO if you already set
+# GENERATE_TREEVIEW to YES.
+
+DISABLE_INDEX = YES
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information.
-# If the tag value is set to FRAME, a side panel will be generated
+# If the tag value is set to YES, a side panel will be generated
# containing a tree-like index structure (just like the one that
# is generated for HTML Help). For this to work a browser that supports
-# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
-# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
-# probably better off using the HTML help feature. Other possible values
-# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
-# and Class Hiererachy pages using a tree view instead of an ordered list;
-# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
-# disables this behavior completely. For backwards compatibility with previous
-# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
-# respectively.
-
-GENERATE_TREEVIEW = NO
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+# Since the tree basically has the same information as the tab index you
+# could consider to set DISABLE_INDEX to NO when enabling this option.
+
+GENERATE_TREEVIEW = YES
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE = 1
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
# used to set the initial width (in pixels) of the frame in which the tree
@@ -927,6 +1208,11 @@ GENERATE_TREEVIEW = NO
TREEVIEW_WIDTH = 250
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW = NO
+
# Use this tag to change the font size of Latex formulas included
# as images in the HTML documentation. The default is 10. Note that
# when you change the font size after a successful doxygen run you need
@@ -935,6 +1221,60 @@ TREEVIEW_WIDTH = 250
FORMULA_FONTSIZE = 12
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you may also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to
+# the MathJax Content Delivery Network so you can quickly see the result without
+# installing MathJax.
+# However, it is strongly recommended to install a local
+# copy of MathJax from http://www.mathjax.org before deployment.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvantages are that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH = NO
+
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
@@ -952,6 +1292,9 @@ LATEX_OUTPUT = latex
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
LATEX_CMD_NAME = latex
@@ -968,7 +1311,7 @@ MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
# The PAPER_TYPE tag can be used to set the paper type that is used
-# by the printer. Possible values are: a4, a4wide, letter, legal and
+# by the printer. Possible values are: a4, letter, legal and
# executive. If left blank a4wide will be used.
PAPER_TYPE = a4wide
@@ -986,6 +1329,13 @@ EXTRA_PACKAGES = amssymb \
LATEX_HEADER =
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER =
+
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
# is prepared for conversion to pdf (using ps2pdf). The pdf file will
# contain links (just like the HTML output) instead of page references
@@ -1012,6 +1362,19 @@ LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE = plain
+
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
@@ -1043,7 +1406,7 @@ COMPACT_RTF = NO
RTF_HYPERLINKS = NO
-# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# Load style sheet definitions from file. Syntax is similar to doxygen's
# config file, i.e. a series of assignments. You only have to provide
# replacements, missing definitions are set to their default value.
@@ -1148,8 +1511,10 @@ GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
-# nicely formatted so it can be parsed by a human reader. This is useful
-# if you want to understand what is going on. On the other hand, if this
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
# tag is set to NO the size of the Perl module output will be much smaller
# and Perl will parse it just the same.
@@ -1186,7 +1551,7 @@ MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
-# in the INCLUDE_PATH (see below) will be search if a #include is found.
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
SEARCH_INCLUDES = YES
@@ -1194,7 +1559,7 @@ SEARCH_INCLUDES = YES
# contain include files that are not input files but should be processed by
# the preprocessor.
-INCLUDE_PATH = "${Eigen_SOURCE_DIR}/Eigen/src/plugins"
+INCLUDE_PATH = "${Eigen_SOURCE_DIR}/Eigen/src/plugins"
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
@@ -1216,29 +1581,30 @@ PREDEFINED = EIGEN_EMPTY_STRUCT \
EIGEN_VECTORIZE \
EIGEN_QT_SUPPORT \
EIGEN_STRONG_INLINE=inline \
- EIGEN2_SUPPORT_STAGE=99
+ "EIGEN2_SUPPORT_STAGE=99" \
+ "EIGEN_MAKE_CWISE_BINARY_OP(METHOD,FUNCTOR)=template<typename OtherDerived> const CwiseBinaryOp<FUNCTOR<Scalar>, const Derived, const OtherDerived> METHOD(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other) const;" \
+ "EIGEN_CWISE_PRODUCT_RETURN_TYPE(LHS,RHS)=CwiseBinaryOp<internal::scalar_product_op<typename LHS::Scalar, typename RHS::Scalar >, const LHS, const RHS>"
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
# The macro definition that is found in the sources will be used.
-# Use the PREDEFINED tag if you want to use a different macro definition.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
EXPAND_AS_DEFINED = EIGEN_MAKE_TYPEDEFS \
EIGEN_MAKE_FIXED_TYPEDEFS \
EIGEN_MAKE_TYPEDEFS_ALL_SIZES \
- EIGEN_MAKE_CWISE_BINARY_OP \
EIGEN_CWISE_UNOP_RETURN_TYPE \
EIGEN_CWISE_BINOP_RETURN_TYPE \
- EIGEN_CWISE_PRODUCT_RETURN_TYPE \
EIGEN_CURRENT_STORAGE_BASE_CLASS \
+ EIGEN_MATHFUNC_IMPL \
_EIGEN_GENERIC_PUBLIC_INTERFACE \
EIGEN2_SUPPORT
# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
-# doxygen's preprocessor will remove all function-like macros that are alone
-# on a line, have an all uppercase name, and do not end with a semicolon. Such
-# function macros are typically used for boiler-plate code, and will confuse
-# the parser if not removed.
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
SKIP_FUNCTION_MACROS = YES
@@ -1246,27 +1612,26 @@ SKIP_FUNCTION_MACROS = YES
# Configuration::additions related to external references
#---------------------------------------------------------------------------
-# The TAGFILES option can be used to specify one or more tagfiles.
-# Optionally an initial location of the external documentation
-# can be added for each tagfile. The format of a tag file without
-# this location is as follows:
-# TAGFILES = file1 file2 ...
+# The TAGFILES option can be used to specify one or more tagfiles. For each
+# tag file the location of the external documentation should be added. The
+# format of a tag file without this location is as follows:
+#
+# TAGFILES = file1 file2 ...
# Adding location for the tag files is done as follows:
-# TAGFILES = file1=loc1 "file2 = loc2" ...
-# where "loc1" and "loc2" can be relative or absolute paths or
-# URLs. If a location is present for each tag, the installdox tool
-# does not have to be run to correct the links.
-# Note that each tag file must have a unique name
-# (where the name does NOT include the path)
-# If a tag file is not located in the directory in which doxygen
-# is run, you must also specify the path to the tagfile here.
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths
+# or URLs. Note that each tag file must have a unique name (where the name does
+# NOT include the path). If a tag file is not located in the directory in which
+# doxygen is run, you must also specify the path to the tagfile here.
-TAGFILES = "${Eigen_BINARY_DIR}/doc/eigen-unsupported.doxytags"=unsupported
+TAGFILES = ${EIGEN_DOXY_TAGFILES}
+# "${Eigen_BINARY_DIR}/doc/eigen-unsupported.doxytags =unsupported"
# When a file name is specified after GENERATE_TAGFILE, doxygen will create
# a tag file that is based on the input files it reads.
-GENERATE_TAGFILE = "${Eigen_BINARY_DIR}/doc/eigen.doxytags"
+GENERATE_TAGFILE = "${Eigen_BINARY_DIR}/doc/${EIGEN_DOXY_PROJECT_NAME}.doxytags"
# If the ALLEXTERNALS tag is set to YES all external classes will be listed
# in the class index. If set to NO only the inherited external classes
@@ -1292,9 +1657,8 @@ PERL_PATH = /usr/bin/perl
# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
# or super classes. Setting the tag to NO turns the diagrams off. Note that
-# this option is superseded by the HAVE_DOT option below. This is only a
-# fallback. It is recommended to install and use dot, since it yields more
-# powerful graphs.
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
CLASS_DIAGRAMS = YES
@@ -1320,28 +1684,38 @@ HIDE_UNDOC_RELATIONS = NO
HAVE_DOT = YES
-# By default doxygen will write a font called FreeSans.ttf to the output
-# directory and reference it in all dot files that doxygen generates. This
-# font does not include all possible unicode characters however, so when you need
-# these (or just want a differently looking font) you can specify the font name
-# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
-# which can be done by putting it in a standard location or by setting the
-# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
-# containing the font.
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS = 0
+
+# By default doxygen will use the Helvetica font for all dot files that
+# doxygen generates. When you want a differently looking font you can specify
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find
+# the font, which can be done by putting it in a standard location or by setting
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font.
DOT_FONTNAME = FreeSans
-# By default doxygen will tell dot to use the output directory to look for the
-# FreeSans.ttf font (which doxygen will put there itself). If you specify a
-# different font using DOT_FONTNAME you can set the path where dot
-# can find it using this tag.
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the Helvetica font.
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
+# set the path where dot can find it.
DOT_FONTPATH =
# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect inheritance relations. Setting this tag to YES will force the
-# the CLASS_DIAGRAMS tag to NO.
+# CLASS_DIAGRAMS tag to NO.
CLASS_GRAPH = YES
@@ -1363,6 +1737,15 @@ GROUP_GRAPHS = NO
UML_LOOK = YES
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside
+# the class node. If there are many fields or methods and many nodes the
+# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
+# threshold limits the number of items for each type to make the size more
+# managable. Set this to 0 for no limit. Note that the threshold may be
+# exceeded by 50% before the limit is enforced.
+
+UML_LIMIT_NUM_FIELDS = 10
+
# If set to YES, the inheritance and collaboration graphs will show the
# relations between templates and their instances.
@@ -1399,11 +1782,11 @@ CALL_GRAPH = NO
CALLER_GRAPH = NO
# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
-# will graphical hierarchy of all classes instead of a textual one.
+# will generate a graphical hierarchy of all classes instead of a textual one.
GRAPHICAL_HIERARCHY = NO
-# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
# then doxygen will show the dependencies a directory has on other directories
# in a graphical way. The dependency relations are determined by the #include
# relations between the files in the directories.
@@ -1411,11 +1794,22 @@ GRAPHICAL_HIERARCHY = NO
DIRECTORY_GRAPH = NO
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot. Possible values are png, jpg, or gif
-# If left blank png will be used.
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used. If you choose svg you need to set
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible in IE 9+ (other browsers do not have this requirement).
DOT_IMAGE_FORMAT = png
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# Note that this requires a modern browser other than Internet Explorer.
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG = NO
+
# The tag DOT_PATH can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
@@ -1427,6 +1821,12 @@ DOT_PATH =
DOTFILE_DIRS =
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS =
+
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
# nodes that will be shown in the graph. If the number of nodes in a graph
# becomes larger than this value, doxygen will truncate the graph, which is
@@ -1448,10 +1848,10 @@ DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is enabled by default, which results in a transparent
-# background. Warning: Depending on the platform used, enabling this option
-# may lead to badly anti-aliased labels on the edges of a graph (i.e. they
-# become hard to read).
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
DOT_TRANSPARENT = NO
@@ -1473,12 +1873,3 @@ GENERATE_LEGEND = YES
# the various graphs.
DOT_CLEANUP = YES
-
-#---------------------------------------------------------------------------
-# Configuration::additions related to the search engine
-#---------------------------------------------------------------------------
-
-# The SEARCHENGINE tag specifies whether or not a search engine should be
-# used. If set to NO the values of all tags below this one will be ignored.
-
-SEARCHENGINE = NO
diff --git a/doc/I05_FixedSizeVectorizable.dox b/doc/FixedSizeVectorizable.dox
index 192ea7406..8ae135173 100644
--- a/doc/I05_FixedSizeVectorizable.dox
+++ b/doc/FixedSizeVectorizable.dox
@@ -1,6 +1,6 @@
namespace Eigen {
-/** \page TopicFixedSizeVectorizable Fixed-size vectorizable Eigen objects
+/** \eigenManualPage TopicFixedSizeVectorizable Fixed-size vectorizable Eigen objects
The goal of this page is to explain what we mean by "fixed-size vectorizable".
diff --git a/doc/I13_FunctionsTakingEigenTypes.dox b/doc/FunctionsTakingEigenTypes.dox
index f9e6fafed..152dda47d 100644
--- a/doc/I13_FunctionsTakingEigenTypes.dox
+++ b/doc/FunctionsTakingEigenTypes.dox
@@ -1,23 +1,18 @@
namespace Eigen {
-/** \page TopicFunctionTakingEigenTypes Writing Functions Taking Eigen Types as Parameters
+/** \page TopicFunctionTakingEigenTypes Writing Functions Taking %Eigen Types as Parameters
-Eigen's use of expression templates results in potentially every expression being of a different type. If you pass such an expression to a function taking a parameter of type Matrix, your expression will implicitly be evaluated into a temporary Matrix, which will then be passed to the function. This means that you lose the benefit of expression templates. Concretely, this has two drawbacks:
+%Eigen's use of expression templates results in potentially every expression being of a different type. If you pass such an expression to a function taking a parameter of type Matrix, your expression will implicitly be evaluated into a temporary Matrix, which will then be passed to the function. This means that you lose the benefit of expression templates. Concretely, this has two drawbacks:
\li The evaluation into a temporary may be useless and inefficient;
\li This only allows the function to read from the expression, not to write to it.
-Fortunately, all this myriad of expression types have in common that they all inherit a few common, templated base classes. By letting your function take templated parameters of these base types, you can let them play nicely with Eigen's expression templates.
+Fortunately, all this myriad of expression types have in common that they all inherit a few common, templated base classes. By letting your function take templated parameters of these base types, you can let them play nicely with %Eigen's expression templates.
-<b>Table of contents</b>
- - \ref TopicFirstExamples
- - \ref TopicPlainFunctionsWorking
- - \ref TopicPlainFunctionsFailing
- - \ref TopicResizingInGenericImplementations
- - \ref TopicSummary
+\eigenAutoToc
\section TopicFirstExamples Some First Examples
-This section will provide simple examples for different types of objects Eigen is offering. Before starting with the actual examples, we need to recapitulate which base objects we can work with (see also \ref TopicClassHierarchy).
+This section will provide simple examples for different types of objects %Eigen is offering. Before starting with the actual examples, we need to recapitulate which base objects we can work with (see also \ref TopicClassHierarchy).
\li MatrixBase: The common base class for all dense matrix expressions (as opposed to array expressions, as opposed to sparse and special matrix classes). Use it in functions that are meant to work only on dense matrices.
\li ArrayBase: The common base class for all dense array expressions (as opposed to matrix expressions, etc). Use it in functions that are meant to work only on arrays.
@@ -25,7 +20,7 @@ This section will provide simple examples for different types of objects Eigen i
\li EigenBase: The base class unifying all types of objects that can be evaluated into dense matrices or arrays, for example special matrix classes such as diagonal matrices, permutation matrices, etc. It can be used in functions that are meant to work on any such general type.
<b> %EigenBase Example </b><br/><br/>
-Prints the dimensions of the most generic object present in Eigen. It coulde be any matrix expressions, any dense or sparse matrix and any array.
+Prints the dimensions of the most generic object present in %Eigen. It could be any matrix expressions, any dense or sparse matrix and any array.
<table class="example">
<tr><th>Example:</th><th>Output:</th></tr>
<tr><td>
@@ -81,9 +76,42 @@ where the first argument \c v1 is a vector and the second argument \c 2*v2 is an
These examples are just intended to give the reader a first impression of how functions can be written which take a plain and constant Matrix or Array argument. They are also intended to give the reader an idea about the most common base classes being the optimal candidates for functions. In the next section we will look in more detail at an example and the different ways it can be implemented, while discussing each implementation's problems and advantages. For the discussion below, Matrix and Array as well as MatrixBase and ArrayBase can be exchanged and all arguments still hold.
+
+\section TopicUsingRefClass How to write generic, but non-templated function?
+
+In all the previous examples, the functions had to be template functions. This approach allows to write very generic code, but it is often desirable to write non templated function and still keep some level of genericity to avoid stupid copies of the arguments. The typical example is to write functions accepting both a MatrixXf or a block of a MatrixXf. This exactly the purpose of the Ref class. Here is a simple example:
+
+<table class="example">
+<tr><th>Example:</th><th>Output:</th></tr>
+<tr><td>
+\include function_taking_ref.cpp
+</td>
+<td>
+\verbinclude function_taking_ref.out
+</td></tr></table>
+In the first two calls to inv_cond, no copy occur because the memory layout of the arguments matches the memory layout accepted by Ref<MatrixXf>. However, in the last call, we have a generic expression that will be automatically evaluated into a temporary MatrixXf by the Ref<> object.
+
+A Ref object can also be writable. Here is an example of a function computing the covariance matrix of two input matrices where each row is an observation:
+\code
+void cov(const Ref<const MatrixXf> x, const Ref<const MatrixXf> y, Ref<MatrixXf> C)
+{
+ const float num_observations = static_cast<float>(x.rows());
+ const RowVectorXf x_mean = x.colwise().sum() / num_observations;
+ const RowVectorXf y_mean = y.colwise().sum() / num_observations;
+ C = (x.rowwise() - x_mean).transpose() * (y.rowwise() - y_mean) / num_observations;
+}
+\endcode
+and here are two examples calling cov without any copy:
+\code
+MatrixXf m1, m2, m3
+cov(m1, m2, m3);
+cov(m1.leftCols<3>(), m2.leftCols<3>(), m3.topLeftCorner<3,3>());
+\endcode
+The Ref<> class has two other optional template arguments allowing to control the kind of memory layout that can be accepted without any copy. See the class Ref documentation for the details.
+
\section TopicPlainFunctionsWorking In which cases do functions taking plain Matrix or Array arguments work?
-Let's assume one wants to write a function computing the covariance matrix of two input matrices where each row is an observation. The implementation of this function might look like this
+Without using template functions, and without the Ref class, a naive implementation of the previous cov function might look like this
\code
MatrixXf cov(const MatrixXf& x, const MatrixXf& y)
{
@@ -93,7 +121,7 @@ MatrixXf cov(const MatrixXf& x, const MatrixXf& y)
return (x.rowwise() - x_mean).transpose() * (y.rowwise() - y_mean) / num_observations;
}
\endcode
-and contrary to what one might think at first, this implementation is fine unless you require a genric implementation that works with double matrices too and unless you do not care about temporary objects. Why is that the case? Where are temporaries involved? How can code as given below compile?
+and contrary to what one might think at first, this implementation is fine unless you require a generic implementation that works with double matrices too and unless you do not care about temporary objects. Why is that the case? Where are temporaries involved? How can code as given below compile?
\code
MatrixXf x,y,z;
MatrixXf C = cov(x,y+z);
@@ -102,6 +130,7 @@ In this special case, the example is fine and will be working because both param
\b Note: Functions taking \e const references to Matrix (or Array) can process expressions at the cost of temporaries.
+
\section TopicPlainFunctionsFailing In which cases do functions taking a plain Matrix or Array argument fail?
Here, we consider a slightly modified version of the function given above. This time, we do not want to return the result but pass an additional non-const paramter which allows us to store the result. A first naive implementation might look as follows.
@@ -154,7 +183,7 @@ MatrixXf y = MatrixXf::Random(100,3);
MatrixXf C;
cov(x, y, C);
\endcode
-This is not the case anymore, when we are using an implementation taking MatrixBase as a parameter. In general, Eigen supports automatic resizing but it is not possible to do so on expressions. Why should resizing of a matrix Block be allowed? It is a reference to a sub-matrix and we definitely don't want to resize that. So how can we incorporate resizing if we cannot resize on MatrixBase? The solution is to resize the derived object as in this implementation.
+This is not the case anymore, when we are using an implementation taking MatrixBase as a parameter. In general, %Eigen supports automatic resizing but it is not possible to do so on expressions. Why should resizing of a matrix Block be allowed? It is a reference to a sub-matrix and we definitely don't want to resize that. So how can we incorporate resizing if we cannot resize on MatrixBase? The solution is to resize the derived object as in this implementation.
\code
template <typename Derived, typename OtherDerived>
void cov(const MatrixBase<Derived>& x, const MatrixBase<Derived>& y, MatrixBase<OtherDerived> const & C_)
diff --git a/doc/I02_HiPerformance.dox b/doc/HiPerformance.dox
index ac1c2ca2b..ab6cdfd44 100644
--- a/doc/I02_HiPerformance.dox
+++ b/doc/HiPerformance.dox
@@ -79,7 +79,7 @@ temp = m2 * m3;
m1 += temp.adjoint(); \endcode</td>
<td>\code
m1.noalias() += m3.adjoint()
- * m2.adjoint(); \endcode</td>
+* * m2.adjoint(); \endcode</td>
<td>This is because the product expression has the EvalBeforeNesting bit which
enforces the evaluation of the product by the Tranpose expression.</td>
</tr>
diff --git a/doc/I10_Assertions.dox b/doc/I10_Assertions.dox
deleted file mode 100644
index d5697fcee..000000000
--- a/doc/I10_Assertions.dox
+++ /dev/null
@@ -1,13 +0,0 @@
-namespace Eigen {
-
-/** \page TopicAssertions Assertions
-
-
-TODO: write this dox page!
-
-Is linked from the tutorial on matrix arithmetic.
-
-\sa Section \ref TopicPreprocessorDirectivesAssertions on page \ref TopicPreprocessorDirectives.
-
-*/
-}
diff --git a/doc/I03_InsideEigenExample.dox b/doc/InsideEigenExample.dox
index 3245a01c0..ed053c69d 100644
--- a/doc/I03_InsideEigenExample.dox
+++ b/doc/InsideEigenExample.dox
@@ -2,12 +2,7 @@ namespace Eigen {
/** \page TopicInsideEigenExample What happens inside Eigen, on a simple example
-\b Table \b of \b contents
- - \ref WhyInteresting
- - \ref ConstructingVectors
- - \ref ConstructionOfSumXpr
- - \ref Assignment
-\n
+\eigenAutoToc
<hr>
diff --git a/doc/Manual.dox b/doc/Manual.dox
new file mode 100644
index 000000000..3367982ca
--- /dev/null
+++ b/doc/Manual.dox
@@ -0,0 +1,159 @@
+
+// This file strutures pages and modules into a convenient hierarchical structure.
+
+namespace Eigen {
+
+/** \page UserManual_Generalities General topics
+ - \subpage Eigen2ToEigen3
+ - \subpage TopicFunctionTakingEigenTypes
+ - \subpage TopicPreprocessorDirectives
+ - \subpage TopicAssertions
+ - \subpage TopicCustomizingEigen
+ - \subpage TopicMultiThreading
+ - \subpage TopicUsingIntelMKL
+ - \subpage TopicTemplateKeyword
+ - \subpage UserManual_UnderstandingEigen
+*/
+
+/** \page UserManual_UnderstandingEigen Understanding Eigen
+ - \subpage TopicInsideEigenExample
+ - \subpage TopicClassHierarchy
+ - \subpage TopicLazyEvaluation
+*/
+
+/** \page UnclassifiedPages Unclassified pages
+ - \subpage TopicResizing
+ - \subpage TopicVectorization
+ - \subpage TopicEigenExpressionTemplates
+ - \subpage TopicScalarTypes
+ - \subpage GettingStarted
+ - \subpage TutorialSparse_example_details
+ - \subpage TopicWritingEfficientProductExpression
+ - \subpage Experimental
+*/
+
+
+/** \defgroup Support_modules Support modules
+ * Category of modules which add support for external libraries.
+ */
+
+
+/** \defgroup DenseMatrixManipulation_chapter Dense matrix and array manipulation */
+/** \defgroup DenseMatrixManipulation_Alignement Alignment issues */
+/** \defgroup DenseMatrixManipulation_Reference Reference */
+
+/** \addtogroup TutorialMatrixClass
+ \ingroup DenseMatrixManipulation_chapter */
+/** \addtogroup TutorialMatrixArithmetic
+ \ingroup DenseMatrixManipulation_chapter */
+/** \addtogroup TutorialArrayClass
+ \ingroup DenseMatrixManipulation_chapter */
+/** \addtogroup TutorialBlockOperations
+ \ingroup DenseMatrixManipulation_chapter */
+/** \addtogroup TutorialAdvancedInitialization
+ \ingroup DenseMatrixManipulation_chapter */
+/** \addtogroup TutorialReductionsVisitorsBroadcasting
+ \ingroup DenseMatrixManipulation_chapter */
+/** \addtogroup TutorialMapClass
+ \ingroup DenseMatrixManipulation_chapter */
+/** \addtogroup TopicAliasing
+ \ingroup DenseMatrixManipulation_chapter */
+/** \addtogroup TopicStorageOrders
+ \ingroup DenseMatrixManipulation_chapter */
+
+/** \addtogroup DenseMatrixManipulation_Alignement
+ \ingroup DenseMatrixManipulation_chapter */
+/** \addtogroup TopicUnalignedArrayAssert
+ \ingroup DenseMatrixManipulation_Alignement */
+/** \addtogroup TopicFixedSizeVectorizable
+ \ingroup DenseMatrixManipulation_Alignement */
+/** \addtogroup TopicStructHavingEigenMembers
+ \ingroup DenseMatrixManipulation_Alignement */
+/** \addtogroup TopicStlContainers
+ \ingroup DenseMatrixManipulation_Alignement */
+/** \addtogroup TopicPassingByValue
+ \ingroup DenseMatrixManipulation_Alignement */
+/** \addtogroup TopicWrongStackAlignment
+ \ingroup DenseMatrixManipulation_Alignement */
+
+/** \addtogroup DenseMatrixManipulation_Reference
+ \ingroup DenseMatrixManipulation_chapter */
+/** \addtogroup Core_Module
+ \ingroup DenseMatrixManipulation_Reference */
+/** \addtogroup Jacobi_Module
+ \ingroup DenseMatrixManipulation_Reference */
+/** \addtogroup Householder_Module
+ \ingroup DenseMatrixManipulation_Reference */
+
+/** \addtogroup QuickRefPage
+ \ingroup DenseMatrixManipulation_chapter */
+
+
+/** \defgroup DenseLinearSolvers_chapter Dense linear problems and decompositions */
+/** \defgroup DenseLinearSolvers_Reference Reference */
+
+/** \addtogroup TutorialLinearAlgebra
+ \ingroup DenseLinearSolvers_chapter */
+/** \addtogroup TopicLinearAlgebraDecompositions
+ \ingroup DenseLinearSolvers_chapter */
+
+/** \addtogroup DenseLinearSolvers_Reference
+ \ingroup DenseLinearSolvers_chapter */
+/** \addtogroup Cholesky_Module
+ \ingroup DenseLinearSolvers_Reference */
+/** \addtogroup LU_Module
+ \ingroup DenseLinearSolvers_Reference */
+/** \addtogroup QR_Module
+ \ingroup DenseLinearSolvers_Reference */
+/** \addtogroup SVD_Module
+ \ingroup DenseLinearSolvers_Reference*/
+/** \addtogroup Eigenvalues_Module
+ \ingroup DenseLinearSolvers_Reference */
+
+
+
+
+/** \defgroup Sparse_chapter Sparse linear algebra */
+/** \defgroup Sparse_Reference Reference */
+
+/** \addtogroup TutorialSparse
+ \ingroup Sparse_chapter */
+/** \addtogroup TopicSparseSystems
+ \ingroup Sparse_chapter */
+
+/** \addtogroup Sparse_Reference
+ \ingroup Sparse_chapter */
+/** \addtogroup SparseCore_Module
+ \ingroup Sparse_Reference */
+/** \addtogroup OrderingMethods_Module
+ \ingroup Sparse_Reference */
+/** \addtogroup SparseCholesky_Module
+ \ingroup Sparse_Reference */
+/** \addtogroup SparseLU_Module
+ \ingroup Sparse_Reference */
+/** \addtogroup SparseQR_Module
+ \ingroup Sparse_Reference */
+/** \addtogroup IterativeLinearSolvers_Module
+ \ingroup Sparse_Reference */
+/** \addtogroup Sparse_Module
+ \ingroup Sparse_Reference */
+/** \addtogroup Support_modules
+ \ingroup Sparse_Reference */
+
+/** \addtogroup SparseQuickRefPage
+ \ingroup Sparse_chapter */
+
+
+/** \defgroup Geometry_chapter Geometry */
+/** \defgroup Geometry_Reference Reference */
+
+/** \addtogroup TutorialGeometry
+ \ingroup Geometry_chapter */
+
+/** \addtogroup Geometry_Reference
+ \ingroup Geometry_chapter */
+/** \addtogroup Geometry_Module
+ \ingroup Geometry_Reference */
+/** \addtogroup Splines_Module
+ \ingroup Geometry_Reference */
+}
diff --git a/doc/Overview.dox b/doc/Overview.dox
index 2657c85bc..9ab96233a 100644
--- a/doc/Overview.dox
+++ b/doc/Overview.dox
@@ -1,59 +1,27 @@
namespace Eigen {
-o /** \mainpage Eigen
-
-<div class="eimainmenu">
- \ref GettingStarted "Getting started"
- | \ref TutorialMatrixClass "Tutorial"
- | \ref QuickRefPage "Short reference"
-</div>
+/** \mainpage notitle
This is the API documentation for Eigen3. You can <a href="eigen-doc.tgz">download</a> it as a tgz archive for offline reading.
-Eigen2 users: here is a \ref Eigen2ToEigen3 guide to help porting your application.
-
-For a first contact with Eigen, the best place is to have a look at the \ref GettingStarted "tutorial". The \ref QuickRefPage "short reference" page gives you a quite complete description of the API in a very condensed format that is specially useful to recall the syntax of a particular feature, or to have a quick look at the API. For Matlab users, there is also a <a href="AsciiQuickReference.txt">ASCII quick reference</a> with Matlab translations. The \e Modules and \e Classes tabs at the top of this page give you access to the API documentation of individual classes and functions.
-
-\b Table \b of \b contents
- - \ref Eigen2ToEigen3
- - \ref GettingStarted
- - \b Tutorial
- - \ref TutorialMatrixClass
- - \ref TutorialMatrixArithmetic
- - \ref TutorialArrayClass
- - \ref TutorialBlockOperations
- - \ref TutorialAdvancedInitialization
- - \ref TutorialLinearAlgebra
- - \ref TutorialReductionsVisitorsBroadcasting
- - \ref TutorialGeometry
- - \ref TutorialSparse
- - \ref TutorialMapClass
- - \ref QuickRefPage
- - <b>Advanced topics</b>
- - \ref TopicAliasing
- - \ref TopicLazyEvaluation
- - \ref TopicLinearAlgebraDecompositions
- - \ref TopicCustomizingEigen
- - \ref TopicMultiThreading
- - \ref TopicPreprocessorDirectives
- - \ref TopicStorageOrders
- - \ref TopicInsideEigenExample
- - \ref TopicWritingEfficientProductExpression
- - \ref TopicClassHierarchy
- - \ref TopicFunctionTakingEigenTypes
- - \ref TopicTemplateKeyword
- - \ref TopicUsingIntelMKL
- - <b>Topics related to alignment issues</b>
- - \ref TopicUnalignedArrayAssert
- - \ref TopicFixedSizeVectorizable
- - \ref TopicStlContainers
- - \ref TopicStructHavingEigenMembers
- - \ref TopicPassingByValue
- - \ref TopicWrongStackAlignment
+You're already an Eigen2 user? Here is a \link Eigen2ToEigen3 Eigen2 to Eigen3 guide \endlink to help porting your application.
+
+For a first contact with Eigen, the best place is to have a look at the \link GettingStarted getting started \endlink page that show you how to write and compile your first program with Eigen.
+
+Then, the \b quick \b reference \b pages give you a quite complete description of the API in a very condensed format that is specially useful to recall the syntax of a particular feature, or to have a quick look at the API. They currently cover the two following feature sets, and more will come in the future:
+ - \link QuickRefPage [QuickRef] Dense matrix and array manipulations \endlink
+ - \link SparseQuickRefPage [QuickRef] Sparse linear algebra \endlink
+
+You're a MatLab user? There is also a <a href="AsciiQuickReference.txt">short ASCII reference</a> with Matlab translations.
-
+The \b main \b documentation is organized into \em chapters covering different domains of features.
+They are themselves composed of \em user \em manual pages describing the different features in a comprehensive way, and \em reference pages that gives you access to the API documentation through the related Eigen's \em modules and \em classes.
+
+Under the \subpage UserManual_Generalities section, you will find documentation on more general topics such as preprocessor directives, controlling assertions, multi-threading, MKL support, some Eigen's internal insights, and much more...
+
+Finally, do not miss the search engine, useful to quickly get to the documentation of a given class or function.
-Want more? Checkout the \ref Unsupported_modules "unsupported modules" <a href="unsupported/index.html">documentation</a>.
+Want more? Checkout the <a href="unsupported/index.html">\em unsupported \em modules </a> documentation.
*/
diff --git a/doc/D07_PassingByValue.dox b/doc/PassingByValue.dox
index b1e5e683b..bf4d0ef4b 100644
--- a/doc/D07_PassingByValue.dox
+++ b/doc/PassingByValue.dox
@@ -1,6 +1,6 @@
namespace Eigen {
-/** \page TopicPassingByValue Passing Eigen objects by value to functions
+/** \eigenManualPage TopicPassingByValue Passing Eigen objects by value to functions
Passing objects by value is almost always a very bad idea in C++, as this means useless copies, and one should pass them by reference instead.
diff --git a/doc/I14_PreprocessorDirectives.dox b/doc/PreprocessorDirectives.dox
index f29f0720c..8a2968ebb 100644
--- a/doc/I14_PreprocessorDirectives.dox
+++ b/doc/PreprocessorDirectives.dox
@@ -7,12 +7,7 @@ should be defined before any %Eigen headers are included. Often they are best se
This page lists the preprocesor tokens recognised by %Eigen.
-<b>Table of contents</b>
- - \ref TopicPreprocessorDirectivesMajor
- - \ref TopicPreprocessorDirectivesAssertions
- - \ref TopicPreprocessorDirectivesPerformance
- - \ref TopicPreprocessorDirectivesPlugins
- - \ref TopicPreprocessorDirectivesDevelopers
+\eigenAutoToc
\section TopicPreprocessorDirectivesMajor Macros with major effects
@@ -29,10 +24,14 @@ are doing.
Eigen3; see \ref Eigen2SupportModes.
- \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.
- Defaults to the #IOFormat constructed by the default constructor IOFormat().
+ - \b EIGEN_DEFAULT_IO_FORMAT - the IOFormat to use when printing a matrix if no %IOFormat is specified.
+ Defaults to the %IOFormat constructed by the default constructor IOFormat::IOFormat().
- \b EIGEN_INITIALIZE_MATRICES_BY_ZERO - if defined, all entries of newly constructed matrices and arrays are
- initializes to zero, as are new entries in matrices and arrays after resizing. Not defined by default.
+ initialized to zero, as are new entries in matrices and arrays after resizing. Not defined by default.
+ - \b EIGEN_INITIALIZE_MATRICES_BY_NAN - if defined, all entries of newly constructed matrices and arrays are
+ initialized to NaN, as are new entries in matrices and arrays after resizing. This option is especially
+ useful for debugging purpose, though a memory tool like <a href="http://valgrind.org/">valgrind</a> is
+ preferable. Not defined by default.
- \b EIGEN_NO_AUTOMATIC_RESIZING - if defined, the matrices (or arrays) on both sides of an assignment
<tt>a = b</tt> 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.
@@ -56,18 +55,26 @@ run time. However, these assertions do cost time and can thus be turned off.
\section TopicPreprocessorDirectivesPerformance Alignment, vectorization and performance tweaking
+ - \b EIGEN_MALLOC_ALREADY_ALIGNED - Can be set to 0 or 1 to tell whether default system malloc already
+ returns aligned buffers. In not defined, then this information is automatically deduced from the compiler
+ and system preprocessor tokens.
- \b EIGEN_DONT_ALIGN - disables alignment completely. %Eigen will not try to align its objects and does not
expect that any objects passed to it are aligned. This will turn off vectorization. Not defined by default.
- \b EIGEN_DONT_ALIGN_STATICALLY - disables alignment of arrays on the stack. Not defined by default, unless
\c EIGEN_DONT_ALIGN is defined.
+ - \b EIGEN_DONT_PARALLELIZE - if defined, this disables multi-threading. This is only relevant if you enabled OpenMP.
+ See \ref TopicMultiThreading for details.
- \b 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 EIGEN_FAST_MATH - enables some optimizations which might affect the accuracy of the result. The only
- optimization this currently includes is single precision sin() and cos() in the present of SSE
- vectorization. Defined by default.
+ - \b EIGEN_FAST_MATH - enables some optimizations which might affect the accuracy of the result. This currently
+ enables the SSE vectorization of sin() and cos(), and speedups sqrt() for single precision. Defined to 1 by default.
+ Define it to 0 to disable.
- \b EIGEN_UNROLLING_LIMIT - defines the size of a loop to enable meta unrolling. Set it to zero to disable
unrolling. The size of a loop here is expressed in %Eigen's own notion of "number of FLOPS", it does not
- correspond to the number of iterations or the number of instructions. The default is value 100.
+ correspond to the number of iterations or the number of instructions. The default is value 100.
+ - \b EIGEN_STACK_ALLOCATION_LIMIT - defines the maximum bytes for a buffer to be allocated on the stack. For internal
+ temporary buffers, dynamic memory allocation is employed as a fall back. For fixed-size matrices or arrays, exceeding
+ this threshold raises a compile time assertion. Use 0 to set no limit. Default is 128 KB.
\section TopicPreprocessorDirectivesPlugins Plugins
diff --git a/doc/QuickReference.dox b/doc/QuickReference.dox
index 3310d390a..a4be0f68a 100644
--- a/doc/QuickReference.dox
+++ b/doc/QuickReference.dox
@@ -1,18 +1,8 @@
namespace Eigen {
-/** \page QuickRefPage Quick reference guide
-
-\b Table \b of \b contents
- - \ref QuickRef_Headers
- - \ref QuickRef_Types
- - \ref QuickRef_Map
- - \ref QuickRef_ArithmeticOperators
- - \ref QuickRef_Coeffwise
- - \ref QuickRef_Reductions
- - \ref QuickRef_Blocks
- - \ref QuickRef_Misc
- - \ref QuickRef_DiagTriSymm
-\n
+/** \eigenManualPage QuickRefPage Quick reference guide
+
+\eigenAutoToc
<hr>
@@ -31,7 +21,7 @@ The Eigen library is divided in a Core module and several additional modules. Ea
<tr><td>\link SVD_Module SVD \endlink</td><td>\code#include <Eigen/SVD>\endcode</td><td>SVD decomposition with least-squares solver (JacobiSVD)</td></tr>
<tr class="alt"><td>\link QR_Module QR \endlink</td><td>\code#include <Eigen/QR>\endcode</td><td>QR decomposition with solver (HouseholderQR, ColPivHouseholderQR, FullPivHouseholderQR)</td></tr>
<tr><td>\link Eigenvalues_Module Eigenvalues \endlink</td><td>\code#include <Eigen/Eigenvalues>\endcode</td><td>Eigenvalue, eigenvector decompositions (EigenSolver, SelfAdjointEigenSolver, ComplexEigenSolver)</td></tr>
-<tr class="alt"><td>\link Sparse_Module Sparse \endlink</td><td>\code#include <Eigen/Sparse>\endcode</td><td>%Sparse matrix storage and related basic linear algebra (SparseMatrix, DynamicSparseMatrix, SparseVector)</td></tr>
+<tr class="alt"><td>\link Sparse_modules Sparse \endlink</td><td>\code#include <Eigen/Sparse>\endcode</td><td>%Sparse matrix storage and related basic linear algebra (SparseMatrix, DynamicSparseMatrix, SparseVector)</td></tr>
<tr><td></td><td>\code#include <Eigen/Dense>\endcode</td><td>Includes Core, Geometry, LU, Cholesky, SVD, QR, and Eigenvalues header files</td></tr>
<tr class="alt"><td></td><td>\code#include <Eigen/Eigen>\endcode</td><td>Includes %Dense and %Sparse header files (the whole Eigen library)</td></tr>
</table>
@@ -55,7 +45,7 @@ All combinations are allowed: you can have a matrix with a fixed number of rows
Matrix<double, 6, Dynamic> // Dynamic number of columns (heap allocation)
Matrix<double, Dynamic, 2> // Dynamic number of rows (heap allocation)
Matrix<double, Dynamic, Dynamic, RowMajor> // Fully dynamic, row major (heap allocation)
-Matrix<double, 13, 3> // Fully fixed (static allocation)
+Matrix<double, 13, 3> // Fully fixed (usually allocated on stack)
\endcode
In most cases, you can simply use one of the convenience typedefs for \ref matrixtypedefs "matrices" and \ref arraytypedefs "arrays". Some examples:
@@ -89,8 +79,8 @@ MatrixWrapper<Array44f> a1m(a1);
\endcode
In the rest of this document we will use the following symbols to emphasize the features which are specifics to a given kind of object:
-\li <a name="matrixonly"><a/>\matrixworld linear algebra matrix and vector only
-\li <a name="arrayonly"><a/>\arrayworld array objects only
+\li <a name="matrixonly"></a>\matrixworld linear algebra matrix and vector only
+\li <a name="arrayonly"></a>\arrayworld array objects only
\subsection QuickRef_Basics Basic matrix manipulation
@@ -415,19 +405,19 @@ array1 == array2 array1 != array2 array1 == scalar array1 != scalar
array1.min(array2)
array1.max(array2)
array1.abs2()
-array1.abs() std::abs(array1)
-array1.sqrt() std::sqrt(array1)
-array1.log() std::log(array1)
-array1.exp() std::exp(array1)
-array1.pow(exponent) std::pow(array1,exponent)
+array1.abs() abs(array1)
+array1.sqrt() sqrt(array1)
+array1.log() log(array1)
+array1.exp() exp(array1)
+array1.pow(exponent) pow(array1,exponent)
array1.square()
array1.cube()
array1.inverse()
-array1.sin() std::sin(array1)
-array1.cos() std::cos(array1)
-array1.tan() std::tan(array1)
-array1.asin() std::asin(array1)
-array1.acos() std::acos(array1)
+array1.sin() sin(array1)
+array1.cos() cos(array1)
+array1.tan() tan(array1)
+array1.asin() asin(array1)
+array1.acos() acos(array1)
\endcode
</td></tr>
</table>
@@ -458,7 +448,7 @@ mat = 2 7 8
\endcode</td></tr>
</table>
-Special versions of \link DenseBase::minCoeff(Index*,Index*) minCoeff \endlink and \link DenseBase::maxCoeff(Index*,Index*) maxCoeff \endlink:
+Special versions of \link DenseBase::minCoeff(IndexType*,IndexType*) const minCoeff \endlink and \link DenseBase::maxCoeff(IndexType*,IndexType*) const maxCoeff \endlink:
\code
int i, j;
s = vector.minCoeff(&i); // s == vector[i]
@@ -490,7 +480,7 @@ Read-write access to sub-vectors:
<tr><td>\code vec1.head(n)\endcode</td><td>\code vec1.head<n>()\endcode</td><td>the first \c n coeffs </td></tr>
<tr><td>\code vec1.tail(n)\endcode</td><td>\code vec1.tail<n>()\endcode</td><td>the last \c n coeffs </td></tr>
<tr><td>\code vec1.segment(pos,n)\endcode</td><td>\code vec1.segment<n>(pos)\endcode</td>
- <td>the \c n coeffs in \n the range [\c pos : \c pos + \c n [</td></tr>
+ <td>the \c n coeffs in the \n range [\c pos : \c pos + \c n - 1]</td></tr>
<tr class="alt"><td colspan="3">
Read-write access to sub-matrices:</td></tr>
diff --git a/doc/C00_QuickStartGuide.dox b/doc/QuickStartGuide.dox
index 8534cb0c3..ea32c3b3d 100644
--- a/doc/C00_QuickStartGuide.dox
+++ b/doc/QuickStartGuide.dox
@@ -1,7 +1,8 @@
namespace Eigen {
/** \page GettingStarted Getting started
- \ingroup Tutorial
+
+\eigenAutoToc
This is a very short guide on how to get started with Eigen. It has a dual purpose. It serves as a minimal introduction to the Eigen library for people who want to start coding as soon as possible. You can also read this page as the first part of the Tutorial, which explains the library in more detail; in this case you will continue with \ref TutorialMatrixClass.
diff --git a/doc/SparseLinearSystems.dox b/doc/SparseLinearSystems.dox
new file mode 100644
index 000000000..c00be10d3
--- /dev/null
+++ b/doc/SparseLinearSystems.dox
@@ -0,0 +1,183 @@
+namespace Eigen {
+/** \eigenManualPage TopicSparseSystems Solving Sparse Linear Systems
+In Eigen, there are several methods available to solve linear systems when the coefficient matrix is sparse. Because of the special representation of this class of matrices, special care should be taken in order to get a good performance. See \ref TutorialSparse for a detailed introduction about sparse matrices in Eigen. This page lists the sparse solvers available in Eigen. The main steps that are common to all these linear solvers are introduced as well. Depending on the properties of the matrix, the desired accuracy, the end-user is able to tune those steps in order to improve the performance of its code. Note that it is not required to know deeply what's hiding behind these steps: the last section presents a benchmark routine that can be easily used to get an insight on the performance of all the available solvers.
+
+\eigenAutoToc
+
+\section TutorialSparseDirectSolvers Sparse solvers
+
+%Eigen currently provides a limited set of built-in solvers, as well as wrappers to external solver libraries.
+They are summarized in the following table:
+
+<table class="manual">
+<tr><th>Class</th><th>Module</th><th>Solver kind</th><th>Matrix kind</th><th>Features related to performance</th>
+ <th>Dependencies,License</th><th class="width20em"><p>Notes</p></th></tr>
+<tr><td>SimplicialLLT </td><td>\link SparseCholesky_Module SparseCholesky \endlink</td><td>Direct LLt factorization</td><td>SPD</td><td>Fill-in reducing</td>
+ <td>built-in, LGPL</td>
+ <td>SimplicialLDLT is often preferable</td></tr>
+<tr><td>SimplicialLDLT </td><td>\link SparseCholesky_Module SparseCholesky \endlink</td><td>Direct LDLt factorization</td><td>SPD</td><td>Fill-in reducing</td>
+ <td>built-in, LGPL</td>
+ <td>Recommended for very sparse and not too large problems (e.g., 2D Poisson eq.)</td></tr>
+<tr><td>ConjugateGradient</td><td>\link IterativeLinearSolvers_Module IterativeLinearSolvers \endlink</td><td>Classic iterative CG</td><td>SPD</td><td>Preconditionning</td>
+ <td>built-in, MPL2</td>
+ <td>Recommended for large symmetric problems (e.g., 3D Poisson eq.)</td></tr>
+<tr><td>BiCGSTAB</td><td>\link IterativeLinearSolvers_Module IterativeLinearSolvers \endlink</td><td>Iterative stabilized bi-conjugate gradient</td><td>Square</td><td>Preconditionning</td>
+ <td>built-in, MPL2</td>
+ <td>To speedup the convergence, try it with the \ref IncompleteLUT preconditioner.</td></tr>
+<tr><td>SparseLU</td> <td>\link SparseLU_Module SparseLU \endlink </td> <td>LU factorization </td>
+ <td>Square </td><td>Fill-in reducing, Leverage fast dense algebra</td>
+ <td> built-in, MPL2</td> <td>optimized for small and large problems with irregular patterns </td></tr>
+<tr><td>SparseQR</td> <td>\link SparseQR_Module SparseQR \endlink</td> <td> QR factorization</td>
+ <td>Any, rectangular</td><td> Fill-in reducing</td>
+ <td>built-in, MPL2</td><td>recommended for least-square problems, has a basic rank-revealing feature</td></tr>
+<tr> <th colspan="7"> Wrappers to external solvers </th></tr>
+<tr><td>PastixLLT \n PastixLDLT \n PastixLU</td><td>\link PaStiXSupport_Module PaStiXSupport \endlink</td><td>Direct LLt, LDLt, LU factorizations</td><td>SPD \n SPD \n Square</td><td>Fill-in reducing, Leverage fast dense algebra, Multithreading</td>
+ <td>Requires the <a href="http://pastix.gforge.inria.fr">PaStiX</a> package, \b CeCILL-C </td>
+ <td>optimized for tough problems and symmetric patterns</td></tr>
+<tr><td>CholmodSupernodalLLT</td><td>\link CholmodSupport_Module CholmodSupport \endlink</td><td>Direct LLt factorization</td><td>SPD</td><td>Fill-in reducing, Leverage fast dense algebra</td>
+ <td>Requires the <a href="http://www.cise.ufl.edu/research/sparse/SuiteSparse/">SuiteSparse</a> package, \b GPL </td>
+ <td></td></tr>
+<tr><td>UmfPackLU</td><td>\link UmfPackSupport_Module UmfPackSupport \endlink</td><td>Direct LU factorization</td><td>Square</td><td>Fill-in reducing, Leverage fast dense algebra</td>
+ <td>Requires the <a href="http://www.cise.ufl.edu/research/sparse/SuiteSparse/">SuiteSparse</a> package, \b GPL </td>
+ <td></td></tr>
+<tr><td>SuperLU</td><td>\link SuperLUSupport_Module SuperLUSupport \endlink</td><td>Direct LU factorization</td><td>Square</td><td>Fill-in reducing, Leverage fast dense algebra</td>
+ <td>Requires the <a href="http://crd-legacy.lbl.gov/~xiaoye/SuperLU/">SuperLU</a> library, (BSD-like)</td>
+ <td></td></tr>
+<tr><td>SPQR</td><td>\link SPQRSupport_Module SPQRSupport \endlink </td> <td> QR factorization </td>
+ <td> Any, rectangular</td><td>fill-in reducing, multithreaded, fast dense algebra</td>
+ <td> requires the <a href="http://www.cise.ufl.edu/research/sparse/SuiteSparse/">SuiteSparse</a> package, \b GPL </td><td>recommended for linear least-squares problems, has a rank-revealing feature</tr>
+</table>
+
+Here \c SPD means symmetric positive definite.
+
+All these solvers follow the same general concept.
+Here is a typical and general example:
+\code
+#include <Eigen/RequiredModuleName>
+// ...
+SparseMatrix<double> A;
+// fill A
+VectorXd b, x;
+// fill b
+// solve Ax = b
+SolverClassName<SparseMatrix<double> > solver;
+solver.compute(A);
+if(solver.info()!=Success) {
+ // decomposition failed
+ return;
+}
+x = solver.solve(b);
+if(solver.info()!=Success) {
+ // solving failed
+ return;
+}
+// solve for another right hand side:
+x1 = solver.solve(b1);
+\endcode
+
+For \c SPD solvers, a second optional template argument allows to specify which triangular part have to be used, e.g.:
+
+\code
+#include <Eigen/IterativeLinearSolvers>
+
+ConjugateGradient<SparseMatrix<double>, Eigen::Upper> solver;
+x = solver.compute(A).solve(b);
+\endcode
+In the above example, only the upper triangular part of the input matrix A is considered for solving. The opposite triangle might either be empty or contain arbitrary values.
+
+In the case where multiple problems with the same sparsity pattern have to be solved, then the "compute" step can be decomposed as follow:
+\code
+SolverClassName<SparseMatrix<double> > solver;
+solver.analyzePattern(A); // for this step the numerical values of A are not used
+solver.factorize(A);
+x1 = solver.solve(b1);
+x2 = solver.solve(b2);
+...
+A = ...; // modify the values of the nonzeros of A, the nonzeros pattern must stay unchanged
+solver.factorize(A);
+x1 = solver.solve(b1);
+x2 = solver.solve(b2);
+...
+\endcode
+The compute() method is equivalent to calling both analyzePattern() and factorize().
+
+Finally, each solver provides some specific features, such as determinant, access to the factors, controls of the iterations, and so on.
+More details are availble in the documentations of the respective classes.
+
+\section TheSparseCompute The Compute Step
+In the compute() function, the matrix is generally factorized: LLT for self-adjoint matrices, LDLT for general hermitian matrices, LU for non hermitian matrices and QR for rectangular matrices. These are the results of using direct solvers. For this class of solvers precisely, the compute step is further subdivided into analyzePattern() and factorize().
+
+The goal of analyzePattern() is to reorder the nonzero elements of the matrix, such that the factorization step creates less fill-in. This step exploits only the structure of the matrix. Hence, the results of this step can be used for other linear systems where the matrix has the same structure. Note however that sometimes, some external solvers (like SuperLU) require that the values of the matrix are set in this step, for instance to equilibrate the rows and columns of the matrix. In this situation, the results of this step should not be used with other matrices.
+
+Eigen provides a limited set of methods to reorder the matrix in this step, either built-in (COLAMD, AMD) or external (METIS). These methods are set in template parameter list of the solver :
+\code
+DirectSolverClassName<SparseMatrix<double>, OrderingMethod<IndexType> > solver;
+\endcode
+
+See the \link OrderingMethods_Module OrderingMethods module \endlink for the list of available methods and the associated options.
+
+In factorize(), the factors of the coefficient matrix are computed. This step should be called each time the values of the matrix change. However, the structural pattern of the matrix should not change between multiple calls.
+
+For iterative solvers, the compute step is used to eventually setup a preconditioner. For instance, with the ILUT preconditioner, the incomplete factors L and U are computed in this step. Remember that, basically, the goal of the preconditioner is to speedup the convergence of an iterative method by solving a modified linear system where the coefficient matrix has more clustered eigenvalues. For real problems, an iterative solver should always be used with a preconditioner. In Eigen, a preconditioner is selected by simply adding it as a template parameter to the iterative solver object.
+\code
+IterativeSolverClassName<SparseMatrix<double>, PreconditionerName<SparseMatrix<double> > solver;
+\endcode
+The member function preconditioner() returns a read-write reference to the preconditioner
+ to directly interact with it. See the \link IterativeLinearSolvers_Module Iterative solvers module \endlink and the documentation of each class for the list of available methods.
+
+\section TheSparseSolve The Solve step
+The solve() function computes the solution of the linear systems with one or many right hand sides.
+\code
+X = solver.solve(B);
+\endcode
+Here, B can be a vector or a matrix where the columns form the different right hand sides. The solve() function can be called several times as well, for instance when all the right hand sides are not available at once.
+\code
+x1 = solver.solve(b1);
+// Get the second right hand side b2
+x2 = solver.solve(b2);
+// ...
+\endcode
+For direct methods, the solution are computed at the machine precision. Sometimes, the solution need not be too accurate. In this case, the iterative methods are more suitable and the desired accuracy can be set before the solve step using \b setTolerance(). For all the available functions, please, refer to the documentation of the \link IterativeLinearSolvers_Module Iterative solvers module \endlink.
+
+\section BenchmarkRoutine
+Most of the time, all you need is to know how much time it will take to qolve your system, and hopefully, what is the most suitable solver. In Eigen, we provide a benchmark routine that can be used for this purpose. It is very easy to use. In the build directory, navigate to bench/spbench and compile the routine by typing \b make \e spbenchsolver. Run it with --help option to get the list of all available options. Basically, the matrices to test should be in <a href="http://math.nist.gov/MatrixMarket/formats.html">MatrixMarket Coordinate format</a>, and the routine returns the statistics from all available solvers in Eigen.
+
+The following table gives an example of XML statistics from several Eigen built-in and external solvers.
+<TABLE border="1">
+ <TR><TH>Matrix <TH> N <TH> NNZ <TH> <TH > UMFPACK <TH > SUPERLU <TH > PASTIX LU <TH >BiCGSTAB <TH > BiCGSTAB+ILUT <TH >GMRES+ILUT<TH > LDLT <TH> CHOLMOD LDLT <TH > PASTIX LDLT <TH > LLT <TH > CHOLMOD SP LLT <TH > CHOLMOD LLT <TH > PASTIX LLT <TH> CG</TR>
+<TR><TH rowspan="4">vector_graphics <TD rowspan="4"> 12855 <TD rowspan="4"> 72069 <TH>Compute Time <TD>0.0254549<TD>0.0215677<TD>0.0701827<TD>0.000153388<TD>0.0140107<TD>0.0153709<TD>0.0101601<TD style="background-color:red">0.00930502<TD>0.0649689
+<TR><TH>Solve Time <TD>0.00337835<TD>0.000951826<TD>0.00484373<TD>0.0374886<TD>0.0046445<TD>0.00847754<TD>0.000541813<TD style="background-color:red">0.000293696<TD>0.00485376
+<TR><TH>Total Time <TD>0.0288333<TD>0.0225195<TD>0.0750265<TD>0.037642<TD>0.0186552<TD>0.0238484<TD>0.0107019<TD style="background-color:red">0.00959871<TD>0.0698227
+<TR><TH>Error(Iter) <TD> 1.299e-16 <TD> 2.04207e-16 <TD> 4.83393e-15 <TD> 3.94856e-11 (80) <TD> 1.03861e-12 (3) <TD> 5.81088e-14 (6) <TD> 1.97578e-16 <TD> 1.83927e-16 <TD> 4.24115e-15
+<TR><TH rowspan="4">poisson_SPD <TD rowspan="4"> 19788 <TD rowspan="4"> 308232 <TH>Compute Time <TD>0.425026<TD>1.82378<TD>0.617367<TD>0.000478921<TD>1.34001<TD>1.33471<TD>0.796419<TD>0.857573<TD>0.473007<TD>0.814826<TD style="background-color:red">0.184719<TD>0.861555<TD>0.470559<TD>0.000458188
+<TR><TH>Solve Time <TD>0.0280053<TD>0.0194402<TD>0.0268747<TD>0.249437<TD>0.0548444<TD>0.0926991<TD>0.00850204<TD>0.0053171<TD>0.0258932<TD>0.00874603<TD style="background-color:red">0.00578155<TD>0.00530361<TD>0.0248942<TD>0.239093
+<TR><TH>Total Time <TD>0.453031<TD>1.84322<TD>0.644241<TD>0.249916<TD>1.39486<TD>1.42741<TD>0.804921<TD>0.862891<TD>0.4989<TD>0.823572<TD style="background-color:red">0.190501<TD>0.866859<TD>0.495453<TD>0.239551
+<TR><TH>Error(Iter) <TD> 4.67146e-16 <TD> 1.068e-15 <TD> 1.3397e-15 <TD> 6.29233e-11 (201) <TD> 3.68527e-11 (6) <TD> 3.3168e-15 (16) <TD> 1.86376e-15 <TD> 1.31518e-16 <TD> 1.42593e-15 <TD> 3.45361e-15 <TD> 3.14575e-16 <TD> 2.21723e-15 <TD> 7.21058e-16 <TD> 9.06435e-12 (261)
+<TR><TH rowspan="4">sherman2 <TD rowspan="4"> 1080 <TD rowspan="4"> 23094 <TH>Compute Time <TD style="background-color:red">0.00631754<TD>0.015052<TD>0.0247514 <TD> -<TD>0.0214425<TD>0.0217988
+<TR><TH>Solve Time <TD style="background-color:red">0.000478424<TD>0.000337998<TD>0.0010291 <TD> -<TD>0.00243152<TD>0.00246152
+<TR><TH>Total Time <TD style="background-color:red">0.00679597<TD>0.01539<TD>0.0257805 <TD> -<TD>0.023874<TD>0.0242603
+<TR><TH>Error(Iter) <TD> 1.83099e-15 <TD> 8.19351e-15 <TD> 2.625e-14 <TD> 1.3678e+69 (1080) <TD> 4.1911e-12 (7) <TD> 5.0299e-13 (12)
+<TR><TH rowspan="4">bcsstk01_SPD <TD rowspan="4"> 48 <TD rowspan="4"> 400 <TH>Compute Time <TD>0.000169079<TD>0.00010789<TD>0.000572538<TD>1.425e-06<TD>9.1612e-05<TD>8.3985e-05<TD style="background-color:red">5.6489e-05<TD>7.0913e-05<TD>0.000468251<TD>5.7389e-05<TD>8.0212e-05<TD>5.8394e-05<TD>0.000463017<TD>1.333e-06
+<TR><TH>Solve Time <TD>1.2288e-05<TD>1.1124e-05<TD>0.000286387<TD>8.5896e-05<TD>1.6381e-05<TD>1.6984e-05<TD style="background-color:red">3.095e-06<TD>4.115e-06<TD>0.000325438<TD>3.504e-06<TD>7.369e-06<TD>3.454e-06<TD>0.000294095<TD>6.0516e-05
+<TR><TH>Total Time <TD>0.000181367<TD>0.000119014<TD>0.000858925<TD>8.7321e-05<TD>0.000107993<TD>0.000100969<TD style="background-color:red">5.9584e-05<TD>7.5028e-05<TD>0.000793689<TD>6.0893e-05<TD>8.7581e-05<TD>6.1848e-05<TD>0.000757112<TD>6.1849e-05
+<TR><TH>Error(Iter) <TD> 1.03474e-16 <TD> 2.23046e-16 <TD> 2.01273e-16 <TD> 4.87455e-07 (48) <TD> 1.03553e-16 (2) <TD> 3.55965e-16 (2) <TD> 2.48189e-16 <TD> 1.88808e-16 <TD> 1.97976e-16 <TD> 2.37248e-16 <TD> 1.82701e-16 <TD> 2.71474e-16 <TD> 2.11322e-16 <TD> 3.547e-09 (48)
+<TR><TH rowspan="4">sherman1 <TD rowspan="4"> 1000 <TD rowspan="4"> 3750 <TH>Compute Time <TD>0.00228805<TD>0.00209231<TD>0.00528268<TD>9.846e-06<TD>0.00163522<TD>0.00162155<TD>0.000789259<TD style="background-color:red">0.000804495<TD>0.00438269
+<TR><TH>Solve Time <TD>0.000213788<TD>9.7983e-05<TD>0.000938831<TD>0.00629835<TD>0.000361764<TD>0.00078794<TD>4.3989e-05<TD style="background-color:red">2.5331e-05<TD>0.000917166
+<TR><TH>Total Time <TD>0.00250184<TD>0.00219029<TD>0.00622151<TD>0.0063082<TD>0.00199698<TD>0.00240949<TD>0.000833248<TD style="background-color:red">0.000829826<TD>0.00529986
+<TR><TH>Error(Iter) <TD> 1.16839e-16 <TD> 2.25968e-16 <TD> 2.59116e-16 <TD> 3.76779e-11 (248) <TD> 4.13343e-11 (4) <TD> 2.22347e-14 (10) <TD> 2.05861e-16 <TD> 1.83555e-16 <TD> 1.02917e-15
+<TR><TH rowspan="4">young1c <TD rowspan="4"> 841 <TD rowspan="4"> 4089 <TH>Compute Time <TD>0.00235843<TD style="background-color:red">0.00217228<TD>0.00568075<TD>1.2735e-05<TD>0.00264866<TD>0.00258236
+<TR><TH>Solve Time <TD>0.000329599<TD style="background-color:red">0.000168634<TD>0.00080118<TD>0.0534738<TD>0.00187193<TD>0.00450211
+<TR><TH>Total Time <TD>0.00268803<TD style="background-color:red">0.00234091<TD>0.00648193<TD>0.0534865<TD>0.00452059<TD>0.00708447
+<TR><TH>Error(Iter) <TD> 1.27029e-16 <TD> 2.81321e-16 <TD> 5.0492e-15 <TD> 8.0507e-11 (706) <TD> 3.00447e-12 (8) <TD> 1.46532e-12 (16)
+<TR><TH rowspan="4">mhd1280b <TD rowspan="4"> 1280 <TD rowspan="4"> 22778 <TH>Compute Time <TD>0.00234898<TD>0.00207079<TD>0.00570918<TD>2.5976e-05<TD>0.00302563<TD>0.00298036<TD>0.00144525<TD style="background-color:red">0.000919922<TD>0.00426444
+<TR><TH>Solve Time <TD>0.00103392<TD>0.000211911<TD>0.00105<TD>0.0110432<TD>0.000628287<TD>0.00392089<TD>0.000138303<TD style="background-color:red">6.2446e-05<TD>0.00097564
+<TR><TH>Total Time <TD>0.0033829<TD>0.0022827<TD>0.00675918<TD>0.0110692<TD>0.00365392<TD>0.00690124<TD>0.00158355<TD style="background-color:red">0.000982368<TD>0.00524008
+<TR><TH>Error(Iter) <TD> 1.32953e-16 <TD> 3.08646e-16 <TD> 6.734e-16 <TD> 8.83132e-11 (40) <TD> 1.51153e-16 (1) <TD> 6.08556e-16 (8) <TD> 1.89264e-16 <TD> 1.97477e-16 <TD> 6.68126e-09
+<TR><TH rowspan="4">crashbasis <TD rowspan="4"> 160000 <TD rowspan="4"> 1750416 <TH>Compute Time <TD>3.2019<TD>5.7892<TD>15.7573<TD style="background-color:red">0.00383515<TD>3.1006<TD>3.09921
+<TR><TH>Solve Time <TD>0.261915<TD>0.106225<TD>0.402141<TD style="background-color:red">1.49089<TD>0.24888<TD>0.443673
+<TR><TH>Total Time <TD>3.46381<TD>5.89542<TD>16.1594<TD style="background-color:red">1.49473<TD>3.34948<TD>3.54288
+<TR><TH>Error(Iter) <TD> 1.76348e-16 <TD> 4.58395e-16 <TD> 1.67982e-14 <TD> 8.64144e-11 (61) <TD> 8.5996e-12 (2) <TD> 6.04042e-14 (5)
+
+</TABLE>
+*/
+}
diff --git a/doc/SparseQuickReference.dox b/doc/SparseQuickReference.dox
index 7d6eb0fa9..4a33d0cc9 100644
--- a/doc/SparseQuickReference.dox
+++ b/doc/SparseQuickReference.dox
@@ -1,74 +1,87 @@
namespace Eigen {
-/** \page SparseQuickRefPage Quick reference guide for sparse matrices
-
-\b Table \b of \b contents
- - \ref Constructors
- - \ref SparseMatrixInsertion
- - \ref SparseBasicInfos
- - \ref SparseBasicOps
- - \ref SparseInterops
- - \ref sparsepermutation
- - \ref sparsesubmatrices
- - \ref sparseselfadjointview
-\n
+/** \eigenManualPage SparseQuickRefPage Quick reference guide for sparse matrices
+\eigenAutoToc
<hr>
-In this page, we give a quick summary of the main operations available for sparse matrices in the class SparseMatrix. First, it is recommended to read first the introductory tutorial at \ref TutorialSparse. The important point to have in mind when working on sparse matrices is how they are stored :
-i.e either row major or column major. The default is column major. Most arithmetic operations on sparse matrices will assert that they have the same storage order. Moreover, when interacting with external libraries that are not yet supported by Eigen, it is important to know how to send the required matrix pointers.
-
-\section Constructors Constructors and assignments
-SparseMatrix is the core class to build and manipulate sparse matrices in Eigen. It takes as template parameters the Scalar type and the storage order, either RowMajor or ColumnMajor. The default is ColumnMajor.
+In this page, we give a quick summary of the main operations available for sparse matrices in the class SparseMatrix. First, it is recommended to read the introductory tutorial at \ref TutorialSparse. The important point to have in mind when working on sparse matrices is how they are stored :
+i.e either row major or column major. The default is column major. Most arithmetic operations on sparse matrices will assert that they have the same storage order.
+\section SparseMatrixInit Sparse Matrix Initialization
+<table class="manual">
+<tr><th> Category </th> <th> Operations</th> <th>Notes</th></tr>
+<tr><td>Constructor</td>
+<td>
\code
- SparseMatrix<double> sm1(1000,1000); // 1000x1000 compressed sparse matrix of double.
- SparseMatrix<std::complex<double>,RowMajor> sm2; // Compressed row major matrix of complex double.
+ SparseMatrix<double> sm1(1000,1000);
+ SparseMatrix<std::complex<double>,RowMajor> sm2;
\endcode
-The copy constructor and assignment can be used to convert matrices from a storage order to another
+</td> <td> Default is ColMajor</td> </tr>
+<tr class="alt">
+<td> Resize/Reserve</td>
+<td>
+ \code
+ sm1.resize(m,n); //Change sm1 to a m x n matrix.
+ sm1.reserve(nnz); // Allocate room for nnz nonzeros elements.
+ \endcode
+</td>
+<td> Note that when calling reserve(), it is not required that nnz is the exact number of nonzero elements in the final matrix. However, an exact estimation will avoid multiple reallocations during the insertion phase. </td>
+</tr>
+<tr>
+<td> Assignment </td>
+<td>
\code
SparseMatrix<double,Colmajor> sm1;
- // Eventually fill the matrix sm1 ...
- SparseMatrix<double,Rowmajor> sm2(sm1), sm3; // Initialize sm2 with sm1.
- sm3 = sm1; // Assignment and evaluations modify the storage order.
+ // Initialize sm2 with sm1.
+ SparseMatrix<double,Rowmajor> sm2(sm1), sm3;
+ // Assignment and evaluations modify the storage order.
+ sm3 = sm1;
\endcode
-
-\section SparseMatrixInsertion Allocating and inserting values
-resize() and reserve() are used to set the size and allocate space for nonzero elements
- \code
- sm1.resize(m,n); //Change sm to a mxn matrix.
- sm1.reserve(nnz); // Allocate room for nnz nonzeros elements.
- \endcode
-Note that when calling reserve(), it is not required that nnz is the exact number of nonzero elements in the final matrix. However, an exact estimation will avoid multiple reallocations during the insertion phase.
-
-Insertions of values in the sparse matrix can be done directly by looping over nonzero elements and use the insert() function
+</td>
+<td> The copy constructor can be used to convert from a storage order to another</td>
+</tr>
+<tr class="alt">
+<td> Element-wise Insertion</td>
+<td>
\code
-// Direct insertion of the value v_ij;
- sm1.insert(i, j) = v_ij; // It is assumed that v_ij does not already exist in the matrix.
-\endcode
+// Insert a new element;
+ sm1.insert(i, j) = v_ij;
-After insertion, a value at (i,j) can be modified using coeffRef()
-\code
- // Update the value v_ij
- sm1.coeffRef(i,j) = v_ij;
- sm1.coeffRef(i,j) += v_ij;
- sm1.coeffRef(i,j) -= v_ij;
- ...
+// Update the value v_ij
+ sm1.coeffRef(i,j) = v_ij;
+ sm1.coeffRef(i,j) += v_ij;
+ sm1.coeffRef(i,j) -= v_ij;
\endcode
-
-The recommended way to insert values is to build a list of triplets (row, col, val) and then call setFromTriplets().
+</td>
+<td> insert() assumes that the element does not already exist; otherwise, use coeffRef()</td>
+</tr>
+<tr>
+<td> Batch insertion</td>
+<td>
\code
+ std::vector< Eigen::Triplet<double> > tripletList;
+ tripletList.reserve(estimation_of_entries);
+ // -- Fill tripletList with nonzero elements...
sm1.setFromTriplets(TripletList.begin(), TripletList.end());
\endcode
-A complete example is available at \ref TutorialSparseFilling.
-
-The following functions can be used to set constant or random values in the matrix.
+</td>
+<td>A complete example is available at \link TutorialSparseFilling Triplet Insertion \endlink.</td>
+</tr>
+<tr class="alt">
+<td> Constant or Random Insertion</td>
+<td>
\code
- sm1.setZero(); // Reset the matrix with zero elements
- ...
+sm1.setZero(); // Set the matrix with zero elements
+sm1.setConstant(val); //Replace all the nonzero values with val
\endcode
+</td>
+<td> The matrix sm1 should have been created before ???</td>
+</tr>
+</table>
+
\section SparseBasicInfos Matrix properties
-Beyond the functions rows() and cols() that are used to get the number of rows and columns, there are some useful functions that are available to easily get some informations from the matrix.
+Beyond the basic functions rows() and cols(), there are some useful functions that are available to easily get some informations from the matrix.
<table class="manual">
<tr>
<td> \code
@@ -77,16 +90,18 @@ Beyond the functions rows() and cols() that are used to get the number of rows a
sm1.nonZeros(); // Number of non zero values
sm1.outerSize(); // Number of columns (resp. rows) for a column major (resp. row major )
sm1.innerSize(); // Number of rows (resp. columns) for a row major (resp. column major)
- sm1.norm(); // (Euclidian ??) norm of the matrix
- sm1.squaredNorm(); //
+ sm1.norm(); // Euclidian norm of the matrix
+ sm1.squaredNorm(); // Squared norm of the matrix
+ sm1.blueNorm();
sm1.isVector(); // Check if sm1 is a sparse vector or a sparse matrix
+ sm1.isCompressed(); // Check if sm1 is in compressed form
...
\endcode </td>
</tr>
</table>
\section SparseBasicOps Arithmetic operations
-It is easy to perform arithmetic operations on sparse matrices provided that the dimensions are adequate and that the matrices have the same storage order. Note that the evaluation can always be done in a matrix with a different storage order.
+It is easy to perform arithmetic operations on sparse matrices provided that the dimensions are adequate and that the matrices have the same storage order. Note that the evaluation can always be done in a matrix with a different storage order. In the following, \b sm denotes a sparse matrix, \b dm a dense matrix and \b dv a dense vector.
<table class="manual">
<tr><th> Operations </th> <th> Code </th> <th> Notes </th></tr>
@@ -113,7 +128,7 @@ It is easy to perform arithmetic operations on sparse matrices provided that the
</tr>
<tr>
- <td> Product </td>
+ <td> %Sparse %Product </td>
<td> \code
sm3 = sm1 * sm2;
dm2 = sm1 * dm1;
@@ -133,7 +148,20 @@ It is easy to perform arithmetic operations on sparse matrices provided that the
Note that the transposition change the storage order. There is no support for transposeInPlace().
</td>
</tr>
-
+<tr>
+<td> Permutation </td>
+<td>
+\code
+perm.indices(); // Reference to the vector of indices
+sm1.twistedBy(perm); // Permute rows and columns
+sm2 = sm1 * perm; //Permute the columns
+sm2 = perm * sm1; // Permute the columns
+\endcode
+</td>
+<td>
+
+</td>
+</tr>
<tr>
<td>
Component-wise ops
@@ -152,47 +180,70 @@ It is easy to perform arithmetic operations on sparse matrices provided that the
</tr>
</table>
-
-\section SparseInterops Low-level storage
-There are a set of low-levels functions to get the standard compressed storage pointers. The matrix should be in compressed mode which can be checked by calling isCompressed(); makeCompressed() should do the job otherwise.
+\section sparseotherops Other supported operations
+<table class="manual">
+<tr><th>Operations</th> <th> Code </th> <th> Notes</th> </tr>
+<tr>
+<td>Sub-matrices</td>
+<td>
+\code
+ sm1.block(startRow, startCol, rows, cols);
+ sm1.block(startRow, startCol);
+ sm1.topLeftCorner(rows, cols);
+ sm1.topRightCorner(rows, cols);
+ sm1.bottomLeftCorner( rows, cols);
+ sm1.bottomRightCorner( rows, cols);
+ \endcode
+</td> <td> </td>
+</tr>
+<tr>
+<td> Range </td>
+<td>
+\code
+ sm1.innerVector(outer);
+ sm1.innerVectors(start, size);
+ sm1.leftCols(size);
+ sm2.rightCols(size);
+ sm1.middleRows(start, numRows);
+ sm1.middleCols(start, numCols);
+ sm1.col(j);
+\endcode
+</td>
+<td>A inner vector is either a row (for row-major) or a column (for column-major). As stated earlier, the evaluation can be done in a matrix with different storage order </td>
+</tr>
+<tr>
+<td> Triangular and selfadjoint views</td>
+<td>
\code
- // Scalar pointer to the values of the matrix, size nnz
- sm1.valuePtr();
- // Index pointer to get the row indices (resp. column indices) for column major (resp. row major) matrix, size nnz
- sm1.innerIndexPtr();
- // Index pointer to the beginning of each row (resp. column) in valuePtr() and innerIndexPtr() for column major (row major). The size is outersize()+1;
- sm1.outerIndexPtr();
+ sm2 = sm1.triangularview<Lower>();
+ sm2 = sm1.selfadjointview<Lower>();
\endcode
-These pointers can therefore be easily used to send the matrix to some external libraries/solvers that are not yet supported by Eigen.
-
-\section sparsepermutation Permutations, submatrices and Selfadjoint Views
-In many cases, it is necessary to reorder the rows and/or the columns of the sparse matrix for several purposes : fill-in reducing during matrix decomposition, better data locality for sparse matrix-vector products... The class PermutationMatrix is available to this end.
- \code
- PermutationMatrix<Dynamic, Dynamic, int> perm;
- // Reserve and fill the values of perm;
- perm.inverse(n); // Compute eventually the inverse permutation
- sm1.twistedBy(perm) //Apply the permutation on rows and columns
- sm2 = sm1 * perm; // ??? Apply the permutation on columns ???;
- sm2 = perm * sm1; // ??? Apply the permutation on rows ???;
- \endcode
-
-\section sparsesubmatrices Sub-matrices
-The following functions are useful to extract a block of rows (resp. columns) from a row-major (resp. column major) sparse matrix. Note that because of the particular storage, it is not ?? efficient ?? to extract a submatrix comprising a certain number of subrows and subcolumns.
- \code
- sm1.innerVector(outer); // Returns the outer -th column (resp. row) of the matrix if sm is col-major (resp. row-major)
- sm1.innerVectors(outer); // Returns the outer -th column (resp. row) of the matrix if mat is col-major (resp. row-major)
- sm1.middleRows(start, numRows); // For row major matrices, get a range of numRows rows
- sm1.middleCols(start, numCols); // For column major matrices, get a range of numCols cols
- \endcode
- Examples :
-
-\section sparseselfadjointview Sparse triangular and selfadjoint Views
- \code
- sm2 = sm1.triangularview<Lower>(); // Get the lower triangular part of the matrix.
- dv2 = sm1.triangularView<Upper>().solve(dv1); // Solve the linear system with the uppper triangular part.
- sm2 = sm1.selfadjointview<Lower>(); // Build a selfadjoint matrix from the lower part of sm1.
- \endcode
-
-
+</td>
+<td> Several combination between triangular views and blocks views are possible
+\code
+ \endcode </td>
+</tr>
+<tr>
+<td>Triangular solve </td>
+<td>
+\code
+ dv2 = sm1.triangularView<Upper>().solve(dv1);
+ dv2 = sm1.topLeftCorner(size, size).triangularView<Lower>().solve(dv1);
+\endcode
+</td>
+<td> For general sparse solve, Use any suitable module described at \ref TopicSparseSystems </td>
+</tr>
+<tr>
+<td> Low-level API</td>
+<td>
+\code
+sm1.valuePtr(); // Pointer to the values
+sm1.innerIndextr(); // Pointer to the indices.
+sm1.outerIndexPtr(); //Pointer to the beginning of each inner vector
+\endcode
+</td>
+<td> If the matrix is not in compressed form, makeCompressed() should be called before. Note that these functions are mostly provided for interoperability purposes with external libraries. A better access to the values of the matrix is done by using the InnerIterator class as described in \link TutorialSparse the Tutorial Sparse \endlink section</td>
+</tr>
+</table>
*/
}
diff --git a/doc/D01_StlContainers.dox b/doc/StlContainers.dox
index b5dbf0698..d8d0d529c 100644
--- a/doc/D01_StlContainers.dox
+++ b/doc/StlContainers.dox
@@ -1,11 +1,8 @@
namespace Eigen {
-/** \page TopicStlContainers Using STL Containers with Eigen
+/** \eigenManualPage TopicStlContainers Using STL Containers with Eigen
-\b Table \b of \b contents
- - \ref summary
- - \ref allocator
- - \ref vector
+\eigenAutoToc
\section summary Executive summary
@@ -38,7 +35,7 @@ The situation with std::vector was even worse (explanation below) so we had to s
Here is an example:
\code
#include<Eigen/StdVector>
-\/* ... *\/
+/* ... */
std::vector<Eigen::Vector4f,Eigen::aligned_allocator<Eigen::Vector4f> >
\endcode
@@ -52,7 +49,7 @@ the compiler will compile that particular instance with the default std::allocat
Here is an example:
\code
#include<Eigen/StdVector>
-\/* ... *\/
+/* ... */
EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Matrix2d)
std::vector<Eigen::Vector2d>
\endcode
diff --git a/doc/I15_StorageOrders.dox b/doc/StorageOrders.dox
index 7418912a6..61645313e 100644
--- a/doc/I15_StorageOrders.dox
+++ b/doc/StorageOrders.dox
@@ -1,14 +1,11 @@
namespace Eigen {
-/** \page TopicStorageOrders Storage orders
+/** \eigenManualPage TopicStorageOrders Storage orders
There are two different storage orders for matrices and two-dimensional arrays: column-major and row-major.
This page explains these storage orders and how to specify which one should be used.
-<b>Table of contents</b>
- - \ref TopicStorageOrdersIntro
- - \ref TopicStorageOrdersInEigen
- - \ref TopicStorageOrdersWhich
+\eigenAutoToc
\section TopicStorageOrdersIntro Column-major and row-major storage
diff --git a/doc/D09_StructHavingEigenMembers.dox b/doc/StructHavingEigenMembers.dox
index 51789ca9c..74a8d5217 100644
--- a/doc/D09_StructHavingEigenMembers.dox
+++ b/doc/StructHavingEigenMembers.dox
@@ -1,16 +1,8 @@
namespace Eigen {
-/** \page TopicStructHavingEigenMembers Structures Having Eigen Members
-
-\b Table \b of \b contents
- - \ref summary
- - \ref what
- - \ref how
- - \ref why
- - \ref movetotop
- - \ref bugineigen
- - \ref conditional
- - \ref othersolutions
+/** \eigenManualPage TopicStructHavingEigenMembers Structures Having Eigen Members
+
+\eigenAutoToc
\section summary Executive Summary
diff --git a/doc/I16_TemplateKeyword.dox b/doc/TemplateKeyword.dox
index 324532310..f4e4f237e 100644
--- a/doc/I16_TemplateKeyword.dox
+++ b/doc/TemplateKeyword.dox
@@ -7,11 +7,7 @@ amongst programmers: to define templates. The other use is more obscure: to spec
to a template function or a type. This regularly trips up programmers that use the %Eigen library, often
leading to error messages from the compiler that are difficult to understand.
-<b>Table of contents</b>
- - \ref TopicTemplateKeywordToDefineTemplates
- - \ref TopicTemplateKeywordExample
- - \ref TopicTemplateKeywordExplanation
- - \ref TopicTemplateKeywordResources
+\eigenAutoToc
\section TopicTemplateKeywordToDefineTemplates Using the template and typename keywords to define templates
diff --git a/doc/I11_Aliasing.dox b/doc/TopicAliasing.dox
index 7c111991c..c2654aed2 100644
--- a/doc/I11_Aliasing.dox
+++ b/doc/TopicAliasing.dox
@@ -1,19 +1,14 @@
namespace Eigen {
-/** \page TopicAliasing Aliasing
+/** \eigenManualPage TopicAliasing Aliasing
-In Eigen, aliasing refers to assignment statement in which the same matrix (or array or vector) appears on the
+In %Eigen, aliasing refers to assignment statement in which the same matrix (or array or vector) appears on the
left and on the right of the assignment operators. Statements like <tt>mat = 2 * mat;</tt> or <tt>mat =
mat.transpose();</tt> exhibit aliasing. The aliasing in the first example is harmless, but the aliasing in the
second example leads to unexpected results. This page explains what aliasing is, when it is harmful, and what
to do about it.
-<b>Table of contents</b>
- - \ref TopicAliasingExamples
- - \ref TopicAliasingSolution
- - \ref TopicAliasingCwise
- - \ref TopicAliasingMatrixMult
- - \ref TopicAliasingSummary
+\eigenAutoToc
\section TopicAliasingExamples Examples
@@ -37,7 +32,7 @@ This assignment exhibits aliasing: the coefficient \c mat(1,1) appears both in t
<tt>mat.bottomRightCorner(2,2)</tt> on the left-hand side of the assignment and the block
<tt>mat.topLeftCorner(2,2)</tt> on the right-hand side. After the assignment, the (2,2) entry in the bottom
right corner should have the value of \c mat(1,1) before the assignment, which is 5. However, the output shows
-that \c mat(2,2) is actually 1. The problem is that Eigen uses lazy evaluation (see
+that \c mat(2,2) is actually 1. The problem is that %Eigen uses lazy evaluation (see
\ref TopicEigenExpressionTemplates) for <tt>mat.topLeftCorner(2,2)</tt>. The result is similar to
\code
mat(1,1) = mat(0,0);
@@ -48,10 +43,13 @@ mat(2,2) = mat(1,1);
Thus, \c mat(2,2) is assigned the \e new value of \c mat(1,1) instead of the old value. The next section
explains how to solve this problem by calling \link DenseBase::eval() eval()\endlink.
-Note that if \c mat were a bigger, then the blocks would not overlap, and there would be no aliasing
-problem. This means that in general aliasing cannot be detected at compile time. However, Eigen does detect
-some instances of aliasing, albeit at run time. The following example exhibiting aliasing was mentioned in
-\ref TutorialMatrixArithmetic :
+Aliasing occurs more naturally when trying to shrink a matrix. For example, the expressions <tt>vec =
+vec.head(n)</tt> and <tt>mat = mat.block(i,j,r,c)</tt> exhibit aliasing.
+
+In general, aliasing cannot be detected at compile time: if \c mat in the first example were a bit bigger,
+then the blocks would not overlap, and there would be no aliasing problem. However, %Eigen does detect some
+instances of aliasing, albeit at run time. The following example exhibiting aliasing was mentioned in \ref
+TutorialMatrixArithmetic :
<table class="example">
<tr><th>Example</th><th>Output</th></tr>
@@ -62,24 +60,24 @@ some instances of aliasing, albeit at run time. The following example exhibitin
\verbinclude tut_arithmetic_transpose_aliasing.out
</td></tr></table>
-Again, the output shows the aliasing issue. However, by default Eigen uses a run-time assertion to detect this
+Again, the output shows the aliasing issue. However, by default %Eigen uses a run-time assertion to detect this
and exits with a message like
\verbatim
void Eigen::DenseBase<Derived>::checkTransposeAliasing(const OtherDerived&) const
[with OtherDerived = Eigen::Transpose<Eigen::Matrix<int, 2, 2, 0, 2, 2> >, Derived = Eigen::Matrix<int, 2, 2, 0, 2, 2>]:
Assertion `(!internal::check_transpose_aliasing_selector<Scalar,internal::blas_traits<Derived>::IsTransposed,OtherDerived>::run(internal::extract_data(derived()), other))
-&& "aliasing detected during tranposition, use transposeInPlace() or evaluate the rhs into a temporary using .eval()"' failed.
+&& "aliasing detected during transposition, use transposeInPlace() or evaluate the rhs into a temporary using .eval()"' failed.
\endverbatim
-The user can turn Eigen's run-time assertions like the one to detect this aliasing problem off by defining the
+The user can turn %Eigen's run-time assertions like the one to detect this aliasing problem off by defining the
EIGEN_NO_DEBUG macro, and the above program was compiled with this macro turned off in order to illustrate the
-aliasing problem. See \ref TopicAssertions for more information about Eigen's run-time assertions.
+aliasing problem. See \ref TopicAssertions for more information about %Eigen's run-time assertions.
\section TopicAliasingSolution Resolving aliasing issues
-If you understand the cause of the aliasing issue, then it is obvious what must happen to solve it: Eigen has
+If you understand the cause of the aliasing issue, then it is obvious what must happen to solve it: %Eigen has
to evaluate the right-hand side fully into a temporary matrix/array and then assign it to the left-hand
side. The function \link DenseBase::eval() eval() \endlink does precisely that.
@@ -98,7 +96,7 @@ Now, \c mat(2,2) equals 5 after the assignment, as it should be.
The same solution also works for the second example, with the transpose: simply replace the line
<tt>a = a.transpose();</tt> with <tt>a = a.transpose().eval();</tt>. However, in this common case there is a
-better solution. Eigen provides the special-purpose function
+better solution. %Eigen provides the special-purpose function
\link DenseBase::transposeInPlace() transposeInPlace() \endlink which replaces a matrix by its transpose.
This is shown below:
@@ -112,7 +110,7 @@ This is shown below:
</td></tr></table>
If an xxxInPlace() function is available, then it is best to use it, because it indicates more clearly what you
-are doing. This may also allow Eigen to optimize more aggressively. These are some of the xxxInPlace()
+are doing. This may also allow %Eigen to optimize more aggressively. These are some of the xxxInPlace()
functions provided:
<table class="manual">
@@ -125,6 +123,9 @@ functions provided:
<tr class="alt"> <td> DenseBase::transpose() </td> <td> DenseBase::transposeInPlace() </td> </tr>
</table>
+In the special case where a matrix or vector is shrunk using an expression like <tt>vec = vec.head(n)</tt>,
+you can use \link PlainObjectBase::conservativeResize() conservativeResize() \endlink.
+
\section TopicAliasingCwise Aliasing and component-wise operations
@@ -133,8 +134,8 @@ right-hand side of an assignment operator, and it is then often necessary to eva
explicitly. However, applying component-wise operations (such as matrix addition, scalar multiplication and
array multiplication) is safe.
-The following example has only component-wise operations. Thus, there is no need for .eval() even though
-the same matrix appears on both sides of the assignments.
+The following example has only component-wise operations. Thus, there is no need for \link DenseBase::eval()
+eval() \endlink even though the same matrix appears on both sides of the assignments.
<table class="example">
<tr><th>Example</th><th>Output</th></tr>
@@ -152,8 +153,8 @@ not necessary to evaluate the right-hand side explicitly.
\section TopicAliasingMatrixMult Aliasing and matrix multiplication
-Matrix multiplication is the only operation in Eigen that assumes aliasing by default. Thus, if \c matA is a
-matrix, then the statement <tt>matA = matA * matA;</tt> is safe. All other operations in Eigen assume that
+Matrix multiplication is the only operation in %Eigen that assumes aliasing by default. Thus, if \c matA is a
+matrix, then the statement <tt>matA = matA * matA;</tt> is safe. All other operations in %Eigen assume that
there are no aliasing problems, either because the result is assigned to a different matrix or because it is a
component-wise operation.
@@ -166,14 +167,14 @@ component-wise operation.
\verbinclude TopicAliasing_mult1.out
</td></tr></table>
-However, this comes at a price. When executing the expression <tt>matA = matA * matA</tt>, Eigen evaluates the
-product in a temporary matrix which is assigned to \c matA after the computation. This is fine. But Eigen does
+However, this comes at a price. When executing the expression <tt>matA = matA * matA</tt>, %Eigen evaluates the
+product in a temporary matrix which is assigned to \c matA after the computation. This is fine. But %Eigen does
the same when the product is assigned to a different matrix (e.g., <tt>matB = matA * matA</tt>). In that case,
it is more efficient to evaluate the product directly into \c matB instead of evaluating it first into a
temporary matrix and copying that matrix to \c matB.
The user can indicate with the \link MatrixBase::noalias() noalias()\endlink function that there is no
-aliasing, as follows: <tt>matB.noalias() = matA * matA</tt>. This allows Eigen to evaluate the matrix product
+aliasing, as follows: <tt>matB.noalias() = matA * matA</tt>. This allows %Eigen to evaluate the matrix product
<tt>matA * matA</tt> directly into \c matB.
<table class="example">
@@ -204,9 +205,9 @@ Aliasing occurs when the same matrix or array coefficients appear both on the le
an assignment operator.
- Aliasing is harmless with coefficient-wise computations; this includes scalar multiplication and matrix or
array addition.
- - When you multiply two matrices, Eigen assumes that aliasing occurs. If you know that there is no aliasing,
+ - When you multiply two matrices, %Eigen assumes that aliasing occurs. If you know that there is no aliasing,
then you can use \link MatrixBase::noalias() noalias()\endlink.
- - In all other situations, Eigen assumes that there is no aliasing issue and thus gives the wrong result if
+ - In all other situations, %Eigen assumes that there is no aliasing issue and thus gives the wrong result if
aliasing does in fact occur. To prevent this, you have to use \link DenseBase::eval() eval() \endlink or
one of the xxxInPlace() functions.
diff --git a/doc/TopicAssertions.dox b/doc/TopicAssertions.dox
new file mode 100644
index 000000000..4ead40174
--- /dev/null
+++ b/doc/TopicAssertions.dox
@@ -0,0 +1,108 @@
+namespace Eigen {
+
+/** \page TopicAssertions Assertions
+
+\eigenAutoToc
+
+\section PlainAssert Assertions
+
+The macro eigen_assert is defined to be \c eigen_plain_assert by default. We use eigen_plain_assert instead of \c assert to work around a known bug for GCC <= 4.3. Basically, eigen_plain_assert \a is \c assert.
+
+\subsection RedefineAssert Redefining assertions
+
+Both eigen_assert and eigen_plain_assert are defined in Macros.h. Defining eigen_assert indirectly gives you a chance to change its behavior. You can redefine this macro if you want to do something else such as throwing an exception, and fall back to its default behavior with eigen_plain_assert. The code below tells Eigen to throw an std::runtime_error:
+
+\code
+#include <stdexcept>
+#undef eigen_assert
+#define eigen_assert(x) \
+ if (!x) { throw (std::runtime_error("Put your message here")); }
+\endcode
+
+\subsection DisableAssert Disabling assertions
+
+Assertions cost run time and can be turned off. You can suppress eigen_assert by defining \c EIGEN_NO_DEBUG \b before including Eigen headers. \c EIGEN_NO_DEBUG is undefined by default unless \c NDEBUG is defined.
+
+\section StaticAssert Static assertions
+
+Static assertions are not standardized until C++11. However, in the Eigen library, there are many conditions can and should be detectedat compile time. For instance, we use static assertions to prevent the code below from compiling.
+
+\code
+Matrix3d() + Matrix4d(); // adding matrices of different sizes
+Matrix4cd() * Vector3cd(); // invalid product known at compile time
+\endcode
+
+Static assertions are defined in StaticAssert.h. If there is native static_assert, we use it. Otherwise, we have implemented an assertion macro that can show a limited range of messages.
+
+One can easily come up with static assertions without messages, such as:
+
+\code
+#define STATIC_ASSERT(x) \
+ switch(0) { case 0: case x:; }
+\endcode
+
+However, the example above obviously cannot tell why the assertion failed. Therefore, we define a \c struct in namespace Eigen::internal to handle available messages.
+
+\code
+template<bool condition>
+struct static_assertion {};
+
+template<>
+struct static_assertion<true>
+{
+ enum {
+ YOU_TRIED_CALLING_A_VECTOR_METHOD_ON_A_MATRIX,
+ YOU_MIXED_VECTORS_OF_DIFFERENT_SIZES,
+ // see StaticAssert.h for all enums.
+ };
+};
+\endcode
+
+And then, we define EIGEN_STATIC_ASSERT(CONDITION,MSG) to access Eigen::internal::static_assertion<bool(CONDITION)>::MSG. If the condition evaluates into \c false, your compiler displays a lot of messages explaining there is no MSG in static_assert<false>. Nevertheless, this is \a not in what we are interested. As you can see, all members of static_assert<true> are ALL_CAPS_AND_THEY_ARE_SHOUTING.
+
+\warning
+When using this macro, MSG should be a member of static_assertion<true>, or the static assertion \b always fails.
+Currently, it can only be used in function scope.
+
+\subsection DerivedStaticAssert Derived static assertions
+
+There are other macros derived from EIGEN_STATIC_ASSERT to enhance readability. Their names are self-explanatory.
+
+- \b EIGEN_STATIC_ASSERT_FIXED_SIZE(TYPE) - passes if \a TYPE is fixed size.
+- \b EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(TYPE) - passes if \a TYPE is dynamic size.
+- \b EIGEN_STATIC_ASSERT_LVALUE(Derived) - failes if \a Derived is read-only.
+- \b EIGEN_STATIC_ASSERT_ARRAYXPR(Derived) - passes if \a Derived is an array expression.
+- <b>EIGEN_STATIC_ASSERT_SAME_XPR_KIND(Derived1, Derived2)</b> - failes if the two expressions are an array one and a matrix one.
+
+Because Eigen handles both fixed-size and dynamic-size expressions, some conditions cannot be clearly determined at compile time. We classify them into strict assertions and permissive assertions.
+
+\subsubsection StrictAssertions Strict assertions
+
+These assertions fail if the condition <b>may not</b> be met. For example, MatrixXd may not be a vector, so it fails EIGEN_STATIC_ASSERT_VECTOR_ONLY.
+
+- \b EIGEN_STATIC_ASSERT_VECTOR_ONLY(TYPE) - passes if \a TYPE must be a vector type.
+- <b>EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(TYPE, SIZE)</b> - passes if \a TYPE must be a vector of the given size.
+- <b>EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(TYPE, ROWS, COLS)</b> - passes if \a TYPE must be a matrix with given rows and columns.
+
+\subsubsection PermissiveAssertions Permissive assertions
+
+These assertions fail if the condition \b cannot be met. For example, MatrixXd and Matrix4d may have the same size, so they pass EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE.
+
+- \b EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(TYPE0,TYPE1) - fails if the two vector expression types must have different sizes.
+- \b EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(TYPE0,TYPE1) - fails if the two matrix expression types must have different sizes.
+- \b EIGEN_STATIC_ASSERT_SIZE_1x1(TYPE) - fails if \a TYPE cannot be an 1x1 expression.
+
+See StaticAssert.h for details such as what messages they throw.
+
+\subsection DisableStaticAssert Disabling static assertions
+
+If \c EIGEN_NO_STATIC_ASSERT is defined, static assertions turn into <tt>eigen_assert</tt>'s, working like:
+
+\code
+#define EIGEN_STATIC_ASSERT(CONDITION,MSG) eigen_assert((CONDITION) && #MSG);
+\endcode
+
+This saves compile time but consumes more run time. \c EIGEN_NO_STATIC_ASSERT is undefined by default.
+
+*/
+}
diff --git a/doc/I06_TopicEigenExpressionTemplates.dox b/doc/TopicEigenExpressionTemplates.dox
index b31fd47f9..b31fd47f9 100644
--- a/doc/I06_TopicEigenExpressionTemplates.dox
+++ b/doc/TopicEigenExpressionTemplates.dox
diff --git a/doc/I01_TopicLazyEvaluation.dox b/doc/TopicLazyEvaluation.dox
index 393bc41d8..393bc41d8 100644
--- a/doc/I01_TopicLazyEvaluation.dox
+++ b/doc/TopicLazyEvaluation.dox
diff --git a/doc/TopicLinearAlgebraDecompositions.dox b/doc/TopicLinearAlgebraDecompositions.dox
index faa564b93..8649cc27b 100644
--- a/doc/TopicLinearAlgebraDecompositions.dox
+++ b/doc/TopicLinearAlgebraDecompositions.dox
@@ -1,12 +1,13 @@
namespace Eigen {
-/** \page TopicLinearAlgebraDecompositions Linear algebra and decompositions
+/** \eigenManualPage TopicLinearAlgebraDecompositions Catalogue of dense decompositions
+This page presents a catalogue of the dense matrix decompositions offered by Eigen.
+For an introduction on linear solvers and decompositions, check this \link TutorialLinearAlgebra page \endlink.
\section TopicLinAlgBigTable Catalogue of decompositions offered by Eigen
<table class="manual-vl">
-
<tr>
<th class="meta"></th>
<th class="meta" colspan="5">Generic information, not Eigen-specific</th>
diff --git a/doc/I08_Resizing.dox b/doc/TopicResizing.dox
index c323e17ad..c323e17ad 100644
--- a/doc/I08_Resizing.dox
+++ b/doc/TopicResizing.dox
diff --git a/doc/I07_TopicScalarTypes.dox b/doc/TopicScalarTypes.dox
index 2ff03c198..2ff03c198 100644
--- a/doc/I07_TopicScalarTypes.dox
+++ b/doc/TopicScalarTypes.dox
diff --git a/doc/I09_Vectorization.dox b/doc/TopicVectorization.dox
index 274d0451b..274d0451b 100644
--- a/doc/I09_Vectorization.dox
+++ b/doc/TopicVectorization.dox
diff --git a/doc/C05_TutorialAdvancedInitialization.dox b/doc/TutorialAdvancedInitialization.dox
index 4f27f1e4d..50374d0d0 100644
--- a/doc/C05_TutorialAdvancedInitialization.dox
+++ b/doc/TutorialAdvancedInitialization.dox
@@ -1,20 +1,12 @@
namespace Eigen {
-/** \page TutorialAdvancedInitialization Tutorial page 5 - Advanced initialization
- \ingroup Tutorial
-
-\li \b Previous: \ref TutorialBlockOperations
-\li \b Next: \ref TutorialLinearAlgebra
+/** \eigenManualPage TutorialAdvancedInitialization Advanced initialization
This page discusses several advanced methods for initializing matrices. It gives more details on the
comma-initializer, which was introduced before. It also explains how to get special matrices such as the
identity matrix and the zero matrix.
-\b Table \b of \b contents
- - \ref TutorialAdvancedInitializationCommaInitializer
- - \ref TutorialAdvancedInitializationSpecialMatrices
- - \ref TutorialAdvancedInitializationTemporaryObjects
-
+\eigenAutoToc
\section TutorialAdvancedInitializationCommaInitializer The comma initializer
@@ -165,8 +157,6 @@ The \link CommaInitializer::finished() finished() \endlink method is necessary h
object once the comma initialization of our temporary submatrix is done.
-\li \b Next: \ref TutorialLinearAlgebra
-
*/
}
diff --git a/doc/C03_TutorialArrayClass.dox b/doc/TutorialArrayClass.dox
index a1d8d6985..6432684aa 100644
--- a/doc/C03_TutorialArrayClass.dox
+++ b/doc/TutorialArrayClass.dox
@@ -1,23 +1,12 @@
namespace Eigen {
-/** \page TutorialArrayClass Tutorial page 3 - The %Array class and coefficient-wise operations
- \ingroup Tutorial
+/** \eigenManualPage TutorialArrayClass The Array class and coefficient-wise operations
-\li \b Previous: \ref TutorialMatrixArithmetic
-\li \b Next: \ref TutorialBlockOperations
-
-This tutorial aims to provide an overview and explanations on how to use
+This page aims to provide an overview and explanations on how to use
Eigen's Array class.
-\b Table \b of \b contents
- - \ref TutorialArrayClassIntro
- - \ref TutorialArrayClassTypes
- - \ref TutorialArrayClassAccess
- - \ref TutorialArrayClassAddSub
- - \ref TutorialArrayClassMult
- - \ref TutorialArrayClassCwiseOther
- - \ref TutorialArrayClassConvert
-
+\eigenAutoToc
+
\section TutorialArrayClassIntro What is the Array class?
The Array class provides general-purpose arrays, as opposed to the Matrix class which
@@ -122,7 +111,7 @@ arrays can be multiplied if and only if they have the same dimensions.
The Array class defines other coefficient-wise operations besides the addition, subtraction and multiplication
operators described above. For example, the \link ArrayBase::abs() .abs() \endlink method takes the absolute
value of each coefficient, while \link ArrayBase::sqrt() .sqrt() \endlink computes the square root of the
-coefficients. If you have two arrays of the same size, you can call \link ArrayBase::min() .min() \endlink to
+coefficients. If you have two arrays of the same size, you can call \link ArrayBase::min(const Eigen::ArrayBase<OtherDerived>&) const .min(.) \endlink to
construct the array whose coefficients are the minimum of the corresponding coefficients of the two given
arrays. These operations are illustrated in the following example.
@@ -168,8 +157,8 @@ The following example shows how to use array operations on a Matrix object by em
* to multiply them coefficient-wise and assigns the result to the matrix variable \c result (this is legal
because Eigen allows assigning array expressions to matrix variables).
-As a matter of fact, this usage case is so common that Eigen provides a \link MatrixBase::cwiseProduct()
-.cwiseProduct() \endlink method for matrices to compute the coefficient-wise product. This is also shown in
+As a matter of fact, this usage case is so common that Eigen provides a \link MatrixBase::cwiseProduct() const
+.cwiseProduct(.) \endlink method for matrices to compute the coefficient-wise product. This is also shown in
the example program.
<table class="example">
@@ -198,8 +187,6 @@ expression <tt>(m.array() * n.array()).matrix() * m</tt> computes the coefficien
\verbinclude Tutorial_ArrayClass_interop.out
</td></tr></table>
-\li \b Next: \ref TutorialBlockOperations
-
*/
}
diff --git a/doc/C04_TutorialBlockOperations.dox b/doc/TutorialBlockOperations.dox
index eac0eaa59..a2d8c97cc 100644
--- a/doc/C04_TutorialBlockOperations.dox
+++ b/doc/TutorialBlockOperations.dox
@@ -1,22 +1,13 @@
namespace Eigen {
-/** \page TutorialBlockOperations Tutorial page 4 - %Block operations
- \ingroup Tutorial
+/** \eigenManualPage TutorialBlockOperations Block operations
-\li \b Previous: \ref TutorialArrayClass
-\li \b Next: \ref TutorialAdvancedInitialization
-
-This tutorial page explains the essentials of block operations.
+This page explains the essentials of block operations.
A block is a rectangular part of a matrix or array. Blocks expressions can be used both
as rvalues and as lvalues. As usual with Eigen expressions, this abstraction has zero runtime cost
provided that you let your compiler optimize.
-\b Table \b of \b contents
- - \ref TutorialBlockOperationsUsing
- - \ref TutorialBlockOperationsSyntaxColumnRows
- - \ref TutorialBlockOperationsSyntaxCorners
- - \ref TutorialBlockOperationsSyntaxVectors
-
+\eigenAutoToc
\section TutorialBlockOperationsUsing Using block operations
@@ -232,8 +223,6 @@ An example is presented below:
\verbinclude Tutorial_BlockOperations_vector.out
</td></tr></table>
-\li \b Next: \ref TutorialAdvancedInitialization
-
*/
}
diff --git a/doc/C08_TutorialGeometry.dox b/doc/TutorialGeometry.dox
index b9e9eba12..372a275de 100644
--- a/doc/C08_TutorialGeometry.dox
+++ b/doc/TutorialGeometry.dox
@@ -1,18 +1,10 @@
namespace Eigen {
-/** \page TutorialGeometry Tutorial page 8 - Geometry
- \ingroup Tutorial
+/** \eigenManualPage TutorialGeometry Space transformations
-\li \b Previous: \ref TutorialReductionsVisitorsBroadcasting
-\li \b Next: \ref TutorialSparse
+In this page, we will introduce the many possibilities offered by the \ref Geometry_Module "geometry module" to deal with 2D and 3D rotations and projective or affine transformations.
-In this tutorial, we will briefly introduce the many possibilities offered by the \ref Geometry_Module "geometry module", namely 2D and 3D rotations and projective or affine transformations.
-
-\b Table \b of \b contents
- - \ref TutorialGeoElementaryTransformations
- - \ref TutorialGeoCommontransformationAPI
- - \ref TutorialGeoTransform
- - \ref TutorialGeoEulerAngles
+\eigenAutoToc
Eigen's Geometry module provides two different kinds of geometric transformations:
- Abstract transformations, such as rotations (represented by \ref AngleAxis "angle and axis" or by a \ref Quaternion "quaternion"), \ref Translation "translations", \ref Scaling "scalings". These transformations are NOT represented as matrices, but you can nevertheless mix them with matrices and vectors in expressions, and convert them to matrices if you wish.
@@ -135,7 +127,7 @@ VectorNf vec1, vec2;
vec2 = t.linear() * vec1;\endcode</td></tr>
<tr><td>
Apply a \em general transformation \n to a \b normal \b vector
-(<a href="http://www.cgafaq.info/wiki/Transforming_normals">explanations</a>)</td><td>\code
+(<a href="http://femto.cs.uiuc.edu/faqs/cga-faq.html#S5.27">explanations</a>)</td><td>\code
VectorNf n1, n2;
MatrixNf normalMatrix = t.linear().inverse().transpose();
n2 = (normalMatrix * n1).normalized();\endcode</td></tr>
@@ -178,7 +170,7 @@ matNxN = t.linear();
\endcode</td></tr>
<tr><td>
extract the rotation matrix</td><td>\code
-matNxN = t.extractRotation();
+matNxN = t.rotation();
\endcode</td></tr>
</table>
@@ -244,8 +236,6 @@ m = AngleAxisf(angle1, Vector3f::UnitZ())
\endcode</td></tr>
</table>
-\li \b Next: \ref TutorialSparse
-
*/
}
diff --git a/doc/C06_TutorialLinearAlgebra.dox b/doc/TutorialLinearAlgebra.dox
index e8b3b7953..b09f3543e 100644
--- a/doc/C06_TutorialLinearAlgebra.dox
+++ b/doc/TutorialLinearAlgebra.dox
@@ -1,24 +1,12 @@
namespace Eigen {
-/** \page TutorialLinearAlgebra Tutorial page 6 - Linear algebra and decompositions
- \ingroup Tutorial
+/** \eigenManualPage TutorialLinearAlgebra Linear algebra and decompositions
-\li \b Previous: \ref TutorialAdvancedInitialization
-\li \b Next: \ref TutorialReductionsVisitorsBroadcasting
-
-This tutorial explains how to solve linear systems, compute various decompositions such as LU,
-QR, %SVD, eigendecompositions... for more advanced topics, don't miss our special page on
-\ref TopicLinearAlgebraDecompositions "this topic".
-
-\b Table \b of \b contents
- - \ref TutorialLinAlgBasicSolve
- - \ref TutorialLinAlgSolutionExists
- - \ref TutorialLinAlgEigensolving
- - \ref TutorialLinAlgInverse
- - \ref TutorialLinAlgLeastsquares
- - \ref TutorialLinAlgSeparateComputation
- - \ref TutorialLinAlgRankRevealing
+This page explains how to solve linear systems, compute various decompositions such as LU,
+QR, %SVD, eigendecompositions... After reading this page, don't miss our
+\link TopicLinearAlgebraDecompositions catalogue \endlink of dense matrix decompositions.
+\eigenAutoToc
\section TutorialLinAlgBasicSolve Basic linear solving
@@ -262,8 +250,6 @@ decomposition after you've changed the threshold.
</tr>
</table>
-\li \b Next: \ref TutorialReductionsVisitorsBroadcasting
-
*/
}
diff --git a/doc/C10_TutorialMapClass.dox b/doc/TutorialMapClass.dox
index 09e792792..f8fb0fd2f 100644
--- a/doc/C10_TutorialMapClass.dox
+++ b/doc/TutorialMapClass.dox
@@ -1,27 +1,19 @@
namespace Eigen {
-/** \page TutorialMapClass Tutorial page 10 - Interfacing with C/C++ arrays and external libraries: the %Map class
+/** \eigenManualPage TutorialMapClass Interfacing with raw buffers: the Map class
-\ingroup Tutorial
+This page explains how to work with "raw" C/C++ arrays.
+This can be useful in a variety of contexts, particularly when "importing" vectors and matrices from other libraries into %Eigen.
-\li \b Previous: \ref TutorialSparse
-\li \b Next: \ref TODO
-
-This tutorial page explains how to work with "raw" C++ arrays. This can be useful in a variety of contexts, particularly when "importing" vectors and matrices from other libraries into Eigen.
-
-\b Table \b of \b contents
- - \ref TutorialMapIntroduction
- - \ref TutorialMapTypes
- - \ref TutorialMapUsing
- - \ref TutorialMapPlacementNew
+\eigenAutoToc
\section TutorialMapIntroduction Introduction
-Occasionally you may have a pre-defined array of numbers that you want to use within Eigen as a vector or matrix. While one option is to make a copy of the data, most commonly you probably want to re-use this memory as an Eigen type. Fortunately, this is very easy with the Map class.
+Occasionally you may have a pre-defined array of numbers that you want to use within %Eigen as a vector or matrix. While one option is to make a copy of the data, most commonly you probably want to re-use this memory as an %Eigen type. Fortunately, this is very easy with the Map class.
\section TutorialMapTypes Map types and declaring Map variables
-A Map object has a type defined by its Eigen equivalent:
+A Map object has a type defined by its %Eigen equivalent:
\code
Map<Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime> >
\endcode
@@ -57,7 +49,7 @@ However, Stride is even more flexible than this; for details, see the documentat
\section TutorialMapUsing Using Map variables
-You can use a Map object just like any other Eigen type:
+You can use a Map object just like any other %Eigen type:
<table class="example">
<tr><th>Example:</th><th>Output:</th></tr>
<tr>
@@ -65,7 +57,7 @@ You can use a Map object just like any other Eigen type:
<td>\verbinclude Tutorial_Map_using.out </td>
</table>
-However, when writing functions taking Eigen types, it is important to realize that a Map type is \em not identical to its Dense equivalent. See \ref TopicFunctionTakingEigenTypesMultiarguments for details.
+All %Eigen functions are written to accept Map objects just like other %Eigen types. However, when writing your own functions taking %Eigen types, this does \em not happen automatically: a Map type is not identical to its Dense equivalent. See \ref TopicFunctionTakingEigenTypes for details.
\section TutorialMapPlacementNew Changing the mapped array
@@ -89,8 +81,6 @@ for (int i = 0; i < n_matrices; i++)
}
\endcode
-\li \b Next: \ref TODO
-
*/
}
diff --git a/doc/C02_TutorialMatrixArithmetic.dox b/doc/TutorialMatrixArithmetic.dox
index b04821a87..5fc569a30 100644
--- a/doc/C02_TutorialMatrixArithmetic.dox
+++ b/doc/TutorialMatrixArithmetic.dox
@@ -1,24 +1,11 @@
namespace Eigen {
-/** \page TutorialMatrixArithmetic Tutorial page 2 - %Matrix and vector arithmetic
- \ingroup Tutorial
+/** \eigenManualPage TutorialMatrixArithmetic Matrix and vector arithmetic
-\li \b Previous: \ref TutorialMatrixClass
-\li \b Next: \ref TutorialArrayClass
-
-This tutorial aims to provide an overview and some details on how to perform arithmetic
+This page aims to provide an overview and some details on how to perform arithmetic
between matrices, vectors and scalars with Eigen.
-\b Table \b of \b contents
- - \ref TutorialArithmeticIntroduction
- - \ref TutorialArithmeticAddSub
- - \ref TutorialArithmeticScalarMulDiv
- - \ref TutorialArithmeticMentionXprTemplates
- - \ref TutorialArithmeticTranspose
- - \ref TutorialArithmeticMatrixMul
- - \ref TutorialArithmeticDotAndCross
- - \ref TutorialArithmeticRedux
- - \ref TutorialArithmeticValidity
+\eigenAutoToc
\section TutorialArithmeticIntroduction Introduction
@@ -222,8 +209,6 @@ Eigen then uses runtime assertions. This means that the program will abort with
For more details on this topic, see \ref TopicAssertions "this page".
-\li \b Next: \ref TutorialArrayClass
-
*/
}
diff --git a/doc/C01_TutorialMatrixClass.dox b/doc/TutorialMatrixClass.dox
index 4860616e5..7ea0cd789 100644
--- a/doc/C01_TutorialMatrixClass.dox
+++ b/doc/TutorialMatrixClass.dox
@@ -1,27 +1,8 @@
namespace Eigen {
-/** \page TutorialMatrixClass Tutorial page 1 - The %Matrix class
+/** \eigenManualPage TutorialMatrixClass The Matrix class
-\ingroup Tutorial
-
-\li \b Previous: \ref GettingStarted
-\li \b Next: \ref TutorialMatrixArithmetic
-
-We assume that you have already read the quick \link GettingStarted "getting started" \endlink tutorial.
-This page is the first one in a much longer multi-page tutorial.
-
-\b Table \b of \b contents
- - \ref TutorialMatrixFirst3Params
- - \ref TutorialMatrixVectors
- - \ref TutorialMatrixDynamic
- - \ref TutorialMatrixConstructors
- - \ref TutorialMatrixCoeffAccessors
- - \ref TutorialMatrixCommaInitializer
- - \ref TutorialMatrixSizesResizing
- - \ref TutorialMatrixAssignment
- - \ref TutorialMatrixFixedVsDynamic
- - \ref TutorialMatrixOptTemplParams
- - \ref TutorialMatrixTypedefs
+\eigenAutoToc
In Eigen, all matrices and vectors are objects of the Matrix template class.
Vectors are just a special case of matrices, with either 1 row or 1 column.
@@ -98,8 +79,8 @@ Matrix3f a;
MatrixXf b;
\endcode
Here,
-\li \c a is a 3x3 matrix, with a static float[9] array of uninitialized coefficients,
-\li \c b is a dynamic-size matrix whose size is currently 0x0, and whose array of
+\li \c a is a 3-by-3 matrix, with a plain float[9] array of uninitialized coefficients,
+\li \c b is a dynamic-size matrix whose size is currently 0-by-0, and whose array of
coefficients hasn't yet been allocated at all.
Constructors taking sizes are also available. For matrices, the number of rows is always passed first.
@@ -216,7 +197,7 @@ The simple answer is: use fixed
sizes for very small sizes where you can, and use dynamic sizes for larger sizes or where you have to. For small sizes,
especially for sizes smaller than (roughly) 16, using fixed sizes is hugely beneficial
to performance, as it allows Eigen to avoid dynamic memory allocation and to unroll
-loops. Internally, a fixed-size Eigen matrix is just a plain static array, i.e. doing
+loops. Internally, a fixed-size Eigen matrix is just a plain array, i.e. doing
\code Matrix4f mymatrix; \endcode
really amounts to just doing
\code float mymatrix[16]; \endcode
@@ -231,8 +212,9 @@ member variables.
The limitation of using fixed sizes, of course, is that this is only possible
when you know the sizes at compile time. Also, for large enough sizes, say for sizes
greater than (roughly) 32, the performance benefit of using fixed sizes becomes negligible.
-Worse, trying to create a very large matrix using fixed sizes could result in a stack overflow,
-since Eigen will try to allocate the array as a static array, which by default goes on the stack.
+Worse, trying to create a very large matrix using fixed sizes inside a function could result in a
+stack overflow, since Eigen will try to allocate the array automatically as a local variable, and
+this is normally done on the stack.
Finally, depending on circumstances, Eigen can also be more aggressive trying to vectorize
(use SIMD instructions) when dynamic sizes are used, see \ref TopicVectorization "Vectorization".
@@ -258,7 +240,7 @@ Matrix<typename Scalar,
\li \c MaxRowsAtCompileTime and \c MaxColsAtCompileTime are useful when you want to specify that, even though
the exact sizes of your matrices are not known at compile time, a fixed upper bound is known at
compile time. The biggest reason why you might want to do that is to avoid dynamic memory allocation.
- For example the following matrix type uses a static array of 12 floats, without dynamic memory allocation:
+ For example the following matrix type uses a plain array of 12 floats, without dynamic memory allocation:
\code
Matrix<float, Dynamic, Dynamic, 0, 3, 4>
\endcode
@@ -277,7 +259,6 @@ Where:
defined for these five types doesn't mean that they are the only supported scalar types. For example,
all standard integer types are supported, see \ref TopicScalarTypes "Scalar types".
-\li \b Next: \ref TutorialMatrixArithmetic
*/
diff --git a/doc/C07_TutorialReductionsVisitorsBroadcasting.dox b/doc/TutorialReductionsVisitorsBroadcasting.dox
index f3879b8b9..992cf6f34 100644
--- a/doc/C07_TutorialReductionsVisitorsBroadcasting.dox
+++ b/doc/TutorialReductionsVisitorsBroadcasting.dox
@@ -1,25 +1,11 @@
namespace Eigen {
-/** \page TutorialReductionsVisitorsBroadcasting Tutorial page 7 - Reductions, visitors and broadcasting
- \ingroup Tutorial
+/** \eigenManualPage TutorialReductionsVisitorsBroadcasting Reductions, visitors and broadcasting
-\li \b Previous: \ref TutorialLinearAlgebra
-\li \b Next: \ref TutorialGeometry
-
-This tutorial explains Eigen's reductions, visitors and broadcasting and how they are used with
+This page explains Eigen's reductions, visitors and broadcasting and how they are used with
\link MatrixBase matrices \endlink and \link ArrayBase arrays \endlink.
-\b Table \b of \b contents
- - \ref TutorialReductionsVisitorsBroadcastingReductions
- - \ref TutorialReductionsVisitorsBroadcastingReductionsNorm
- - \ref TutorialReductionsVisitorsBroadcastingReductionsBool
- - \ref TutorialReductionsVisitorsBroadcastingReductionsUserdefined
- - \ref TutorialReductionsVisitorsBroadcastingVisitors
- - \ref TutorialReductionsVisitorsBroadcastingPartialReductions
- - \ref TutorialReductionsVisitorsBroadcastingPartialReductionsCombined
- - \ref TutorialReductionsVisitorsBroadcastingBroadcasting
- - \ref TutorialReductionsVisitorsBroadcastingBroadcastingCombined
-
+\eigenAutoToc
\section TutorialReductionsVisitorsBroadcastingReductions Reductions
In Eigen, a reduction is a function taking a matrix or array, and returning a single
@@ -266,8 +252,6 @@ this operation is a row-vector where each coefficient is the squared Euclidean d
- Finally, <tt>minCoeff(&index)</tt> is used to obtain the index of the column in <tt>m</tt> that is closest to <tt>v</tt> in terms of Euclidean
distance.
-\li \b Next: \ref TutorialGeometry
-
*/
}
diff --git a/doc/C09_TutorialSparse.dox b/doc/TutorialSparse.dox
index 34154bd0d..fa2a3ad8b 100644
--- a/doc/C09_TutorialSparse.dox
+++ b/doc/TutorialSparse.dox
@@ -1,37 +1,23 @@
namespace Eigen {
-/** \page TutorialSparse Tutorial page 9 - Sparse Matrix
- \ingroup Tutorial
+/** \eigenManualPage TutorialSparse Sparse matrix manipulations
-\li \b Previous: \ref TutorialGeometry
-\li \b Next: \ref TutorialMapClass
-
-\b Table \b of \b contents \n
- - \ref TutorialSparseIntro
- - \ref TutorialSparseExample "Example"
- - \ref TutorialSparseSparseMatrix
- - \ref TutorialSparseFilling
- - \ref TutorialSparseDirectSolvers
- - \ref TutorialSparseFeatureSet
- - \ref TutorialSparse_BasicOps
- - \ref TutorialSparse_Products
- - \ref TutorialSparse_TriangularSelfadjoint
- - \ref TutorialSparse_Submat
-
-
-<hr>
+\eigenAutoToc
Manipulating and solving sparse problems involves various modules which are summarized below:
<table class="manual">
<tr><th>Module</th><th>Header file</th><th>Contents</th></tr>
-<tr><td>\link Sparse_Module SparseCore \endlink</td><td>\code#include <Eigen/SparseCore>\endcode</td><td>SparseMatrix and SparseVector classes, matrix assembly, basic sparse linear algebra (including sparse triangular solvers)</td></tr>
+<tr><td>\link SparseCore_Module SparseCore \endlink</td><td>\code#include <Eigen/SparseCore>\endcode</td><td>SparseMatrix and SparseVector classes, matrix assembly, basic sparse linear algebra (including sparse triangular solvers)</td></tr>
<tr><td>\link SparseCholesky_Module SparseCholesky \endlink</td><td>\code#include <Eigen/SparseCholesky>\endcode</td><td>Direct sparse LLT and LDLT Cholesky factorization to solve sparse self-adjoint positive definite problems</td></tr>
+<tr><td>\link SparseLU_Module SparseLU \endlink</td><td>\code #include<Eigen/SparseLU> \endcode</td>
+<td>%Sparse LU factorization to solve general square sparse systems</td></tr>
+<tr><td>\link SparseQR_Module SparseQR \endlink</td><td>\code #include<Eigen/SparseQR>\endcode </td><td>%Sparse QR factorization for solving sparse linear least-squares problems</td></tr>
<tr><td>\link IterativeLinearSolvers_Module IterativeLinearSolvers \endlink</td><td>\code#include <Eigen/IterativeLinearSolvers>\endcode</td><td>Iterative solvers to solve large general linear square problems (including self-adjoint positive definite problems)</td></tr>
-<tr><td></td><td>\code#include <Eigen/Sparse>\endcode</td><td>Includes all the above modules</td></tr>
+<tr><td>\link Sparse_Module Sparse \endlink</td><td>\code#include <Eigen/Sparse>\endcode</td><td>Includes all the above modules</td></tr>
</table>
-\section TutorialSparseIntro Sparse matrix representation
+\section TutorialSparseIntro Sparse matrix format
In many applications (e.g., finite element methods) it is common to deal with very large matrices where only a few coefficients are different from zero. In such cases, memory consumption can be reduced and performance increased by using a specialized representation storing only the nonzero coefficients. Such a matrix is called a sparse matrix.
@@ -97,7 +83,7 @@ There is no notion of compressed/uncompressed mode for a SparseVector.
\section TutorialSparseExample First example
-Before describing each individual class, let's start with the following typical example: solving the Lapace equation \f$ \nabla u = 0 \f$ on a regular 2D grid using a finite difference scheme and Dirichlet boundary conditions.
+Before describing each individual class, let's start with the following typical example: solving the Laplace equation \f$ \nabla u = 0 \f$ on a regular 2D grid using a finite difference scheme and Dirichlet boundary conditions.
Such problem can be mathematically expressed as a linear problem of the form \f$ Ax=b \f$ where \f$ x \f$ is the vector of \c m unknowns (in our case, the values of the pixels), \f$ b \f$ is the right hand side vector resulting from the boundary conditions, and \f$ A \f$ is an \f$ m \times m \f$ matrix containing only a few non-zero elements resulting from the discretization of the Laplacian operator.
<table class="manual">
@@ -130,7 +116,7 @@ Describing the \a buildProblem and \a save functions is out of the scope of this
The SparseMatrix and SparseVector classes take three template arguments:
* the scalar type (e.g., double)
- * the storage order (ColMajor or RowMajor, the default is RowMajor)
+ * the storage order (ColMajor or RowMajor, the default is ColMajor)
* the inner index type (default is \c int).
As for dense Matrix objects, constructors takes the size of the object.
@@ -211,7 +197,7 @@ Here is a typical usage example:
\code
typedef Eigen::Triplet<double> T;
std::vector<T> tripletList;
-triplets.reserve(estimation_of_entries);
+tripletList.reserve(estimation_of_entries);
for(...)
{
// ...
@@ -241,102 +227,10 @@ A typical scenario of this approach is illustrated bellow:
- The line 5 suppresses the remaining empty space and transforms the matrix into a compressed column storage.
-\section TutorialSparseDirectSolvers Solving linear problems
-
-%Eigen currently provides a limited set of built-in solvers, as well as wrappers to external solver libraries.
-They are summarized in the following table:
-
-<table class="manual">
-<tr><th>Class</th><th>Module</th><th>Solver kind</th><th>Matrix kind</th><th>Features related to performance</th>
- <th>Dependencies,License</th><th class="width20em"><p>Notes</p></th></tr>
-<tr><td>SimplicialLLT </td><td>\link SparseCholesky_Module SparseCholesky \endlink</td><td>Direct LLt factorization</td><td>SPD</td><td>Fill-in reducing</td>
- <td>built-in, LGPL</td>
- <td>SimplicialLDLT is often preferable</td></tr>
-<tr><td>SimplicialLDLT </td><td>\link SparseCholesky_Module SparseCholesky \endlink</td><td>Direct LDLt factorization</td><td>SPD</td><td>Fill-in reducing</td>
- <td>built-in, LGPL</td>
- <td>Recommended for very sparse and not too large problems (e.g., 2D Poisson eq.)</td></tr>
-<tr><td>ConjugateGradient</td><td>\link IterativeLinearSolvers_Module IterativeLinearSolvers \endlink</td><td>Classic iterative CG</td><td>SPD</td><td>Preconditionning</td>
- <td>built-in, LGPL</td>
- <td>Recommended for large symmetric problems (e.g., 3D Poisson eq.)</td></tr>
-<tr><td>BiCGSTAB</td><td>\link IterativeLinearSolvers_Module IterativeLinearSolvers \endlink</td><td>Iterative stabilized bi-conjugate gradient</td><td>Square</td><td>Preconditionning</td>
- <td>built-in, LGPL</td>
- <td>Might not always converge</td></tr>
-
-
-<tr><td>PastixLLT \n PastixLDLT \n PastixLU</td><td>\link PaStiXSupport_Module PaStiXSupport \endlink</td><td>Direct LLt, LDLt, LU factorizations</td><td>SPD \n SPD \n Square</td><td>Fill-in reducing, Leverage fast dense algebra, Multithreading</td>
- <td>Requires the <a href="http://pastix.gforge.inria.fr">PaStiX</a> package, \b CeCILL-C </td>
- <td>optimized for tough problems and symmetric patterns</td></tr>
-<tr><td>CholmodSupernodalLLT</td><td>\link CholmodSupport_Module CholmodSupport \endlink</td><td>Direct LLt factorization</td><td>SPD</td><td>Fill-in reducing, Leverage fast dense algebra</td>
- <td>Requires the <a href="http://www.cise.ufl.edu/research/sparse/SuiteSparse/">SuiteSparse</a> package, \b GPL </td>
- <td></td></tr>
-<tr><td>UmfPackLU</td><td>\link UmfPackSupport_Module UmfPackSupport \endlink</td><td>Direct LU factorization</td><td>Square</td><td>Fill-in reducing, Leverage fast dense algebra</td>
- <td>Requires the <a href="http://www.cise.ufl.edu/research/sparse/SuiteSparse/">SuiteSparse</a> package, \b GPL </td>
- <td></td></tr>
-<tr><td>SuperLU</td><td>\link SuperLUSupport_Module SuperLUSupport \endlink</td><td>Direct LU factorization</td><td>Square</td><td>Fill-in reducing, Leverage fast dense algebra</td>
- <td>Requires the <a href="http://crd-legacy.lbl.gov/~xiaoye/SuperLU/">SuperLU</a> library, (BSD-like)</td>
- <td></td></tr>
-</table>
-
-Here \c SPD means symmetric positive definite.
-
-All these solvers follow the same general concept.
-Here is a typical and general example:
-\code
-#include <Eigen/RequiredModuleName>
-// ...
-SparseMatrix<double> A;
-// fill A
-VectorXd b, x;
-// fill b
-// solve Ax = b
-SolverClassName<SparseMatrix<double> > solver;
-solver.compute(A);
-if(solver.info()!=Succeeded) {
- // decomposition failed
- return;
-}
-x = solver.solve(b);
-if(solver.info()!=Succeeded) {
- // solving failed
- return;
-}
-// solve for another right hand side:
-x1 = solver.solve(b1);
-\endcode
-
-For \c SPD solvers, a second optional template argument allows to specify which triangular part have to be used, e.g.:
-
-\code
-#include <Eigen/IterativeLinearSolvers>
-
-ConjugateGradient<SparseMatrix<double>, Eigen::Upper> solver;
-x = solver.compute(A).solve(b);
-\endcode
-In the above example, only the upper triangular part of the input matrix A is considered for solving. The opposite triangle might either be empty or contain arbitrary values.
-
-In the case where multiple problems with the same sparcity pattern have to be solved, then the "compute" step can be decomposed as follow:
-\code
-SolverClassName<SparseMatrix<double> > solver;
-solver.analyzePattern(A); // for this step the numerical values of A are not used
-solver.factorize(A);
-x1 = solver.solve(b1);
-x2 = solver.solve(b2);
-...
-A = ...; // modify the values of the nonzeros of A, the nonzeros pattern must stay unchanged
-solver.factorize(A);
-x1 = solver.solve(b1);
-x2 = solver.solve(b2);
-...
-\endcode
-The compute() method is equivalent to calling both analyzePattern() and factorize().
-
-Finally, each solver provides some specific features, such as determinant, access to the factors, controls of the iterations, and so on.
-More details are availble in the documentations of the respective classes.
-
\section TutorialSparseFeatureSet Supported operators and functions
-Because of their special storage format, sparse matrices cannot offer the same level of flexbility than dense matrices.
+Because of their special storage format, sparse matrices cannot offer the same level of flexibility than dense matrices.
In Eigen's sparse module we chose to expose only the subset of the dense matrix API which can be efficiently implemented.
In the following \em sm denotes a sparse matrix, \em sv a sparse vector, \em dm a dense matrix, and \em dv a dense vector.
@@ -359,12 +253,15 @@ SparseMatrix<double> A, B;
B = SparseMatrix<double>(A.transpose()) + A;
\endcode
-Binary coefficient wise operators can also mix sparse and dense expressions:
+Some binary coefficient-wise operators can also mix sparse and dense expressions:
\code
sm2 = sm1.cwiseProduct(dm1);
-dm2 = sm1 + dm1;
+dm1 += sm1;
\endcode
+However, it is not yet possible to add a sparse and a dense matrix as in <tt>dm2 = sm1 + dm1</tt>.
+Please write this as the equivalent <tt>dm2 = dm1; dm2 += sm1</tt> (we plan to lift this restriction
+in the next release of %Eigen).
%Sparse expressions also support transposition:
\code
@@ -396,9 +293,9 @@ sm3 = 4 * sm1.adjoint() * sm2;
\endcode
The second algorithm prunes on the fly the explicit zeros, or the values smaller than a given threshold. It is enabled and controlled through the prune() functions:
\code
-sm3 = (sm1 * sm2).prune(); // removes numerical zeros
-sm3 = (sm1 * sm2).prune(ref); // removes elements much smaller than ref
-sm3 = (sm1 * sm2).prune(ref,epsilon); // removes elements smaller than ref*epsilon
+sm3 = (sm1 * sm2).pruned(); // removes numerical zeros
+sm3 = (sm1 * sm2).pruned(ref); // removes elements much smaller than ref
+sm3 = (sm1 * sm2).pruned(ref,epsilon); // removes elements smaller than ref*epsilon
\endcode
- \b permutations. Finally, permutations can be applied to sparse matrices too:
@@ -437,18 +334,7 @@ sm2 = A.selfadjointView<Upper>().twistedBy(P); //
sm2.selfadjointView<Lower>() = A.selfadjointView<Lower>().twistedBy(P); // compute P S P' from the lower triangular part of A, and then only compute the lower part
\endcode
-\subsection TutorialSparse_Submat Sub-matrices
-
-%Sparse matrices does not support yet the addressing of arbitrary sub matrices. Currently, one can only reference a set of contiguous \em inner vectors, i.e., a set of contiguous rows for a row-major matrix, or a set of contiguous columns for a column major matrix:
-\code
- sm1.innerVector(j); // returns an expression of the j-th column (resp. row) of the matrix if sm1 is col-major (resp. row-major)
- sm1.innerVectors(j, nb); // returns an expression of the nb columns (resp. row) starting from the j-th column (resp. row)
- // of the matrix if sm1 is col-major (resp. row-major)
- sm1.middleRows(j, nb); // for row major matrices only, get a range of nb rows
- sm1.middleCols(j, nb); // for column major matrices only, get a range of nb columns
-\endcode
-
-\li \b Next: \ref TutorialMapClass
+Please, refer to the \link SparseQuickRefPage Quick Reference \endlink guide for the list of supported operations. The list of linear solvers available is \link TopicSparseSystems here. \endlink
*/
diff --git a/doc/D11_UnalignedArrayAssert.dox b/doc/UnalignedArrayAssert.dox
index d173ee5f4..8c97d7874 100644
--- a/doc/D11_UnalignedArrayAssert.dox
+++ b/doc/UnalignedArrayAssert.dox
@@ -1,6 +1,6 @@
namespace Eigen {
-/** \page TopicUnalignedArrayAssert Explanation of the assertion on unaligned arrays
+/** \eigenManualPage TopicUnalignedArrayAssert Explanation of the assertion on unaligned arrays
Hello! You are seeing this webpage because your program terminated on an assertion failure like this one:
<pre>
@@ -14,14 +14,7 @@ is explained here: http://eigen.tuxfamily.org/dox/UnalignedArrayAssert.html
There are 4 known causes for this issue. Please read on to understand them and learn how to fix them.
-\b Table \b of \b contents
- - \ref where
- - \ref c1
- - \ref c2
- - \ref c3
- - \ref c4
- - \ref explanation
- - \ref getrid
+\eigenAutoToc
\section where Where in my own code is the cause of the problem?
diff --git a/doc/UsingIntelMKL.dox b/doc/UsingIntelMKL.dox
index 379ee3ffd..4b624a156 100644
--- a/doc/UsingIntelMKL.dox
+++ b/doc/UsingIntelMKL.dox
@@ -40,7 +40,7 @@ Since Eigen version 3.1 and later, users can benefit from built-in Intel MKL opt
<a href="http://eigen.tuxfamily.org/Counter/redirect_to_mkl.php"> Intel MKL </a> provides highly optimized multi-threaded mathematical routines for x86-compatible architectures.
Intel MKL is available on Linux, Mac and Windows for both Intel64 and IA32 architectures.
-\warning Be aware that Intel® MKL is a proprietary software. It is the responsibility of the users to buy MKL licenses for their products. Moreover, the license of the user product has to allow linking to proprietary software that excludes any unmodified versions of the GPL. As a consequence, this also means that Eigen has to be used through the LGPL3+ license.
+\warning Be aware that Intel® MKL is a proprietary software. It is the responsibility of the users to buy MKL licenses for their products. Moreover, the license of the user product has to allow linking to proprietary software that excludes any unmodified versions of the GPL.
Using Intel MKL through Eigen is easy:
-# define the \c EIGEN_USE_MKL_ALL macro before including any Eigen's header
@@ -61,7 +61,7 @@ In addition you can coarsely select choose which parts will be substituted by de
<tr><td>\c EIGEN_USE_MKL_ALL </td><td>Defines \c EIGEN_USE_BLAS, \c EIGEN_USE_LAPACKE, and \c EIGEN_USE_MKL_VML </td></tr>
</table>
-Finally, the PARDISO sparse solver shipped with Intel MKL can be used through the \ref PardisoLU, \ref PardisoLLT and \ref PardisoLDLT classes of the \ref PARDISOSupport_Module.
+Finally, the PARDISO sparse solver shipped with Intel MKL can be used through the \ref PardisoLU, \ref PardisoLLT and \ref PardisoLDLT classes of the \ref PardisoSupport_Module.
\section TopicUsingIntelMKL_SupportedFeatures List of supported features
@@ -165,4 +165,4 @@ In the examples, m1 and m2 are dense matrices and v1 and v2 are dense vectors.
*/
-} \ No newline at end of file
+}
diff --git a/doc/D03_WrongStackAlignment.dox b/doc/WrongStackAlignment.dox
index b0e42edce..17d5513a7 100644
--- a/doc/D03_WrongStackAlignment.dox
+++ b/doc/WrongStackAlignment.dox
@@ -1,6 +1,6 @@
namespace Eigen {
-/** \page TopicWrongStackAlignment Compiler making a wrong assumption on stack alignment
+/** \eigenManualPage TopicWrongStackAlignment Compiler making a wrong assumption on stack alignment
<h4>It appears that this was a GCC bug that has been fixed in GCC 4.5.
If you hit this issue, please upgrade to GCC 4.5 and report to us, so we can update this page.</h4>
diff --git a/doc/eigen_navtree_hacks.js b/doc/eigen_navtree_hacks.js
new file mode 100644
index 000000000..bd7e02b38
--- /dev/null
+++ b/doc/eigen_navtree_hacks.js
@@ -0,0 +1,240 @@
+
+// generate a table of contents in the side-nav based on the h1/h2 tags of the current page.
+function generate_autotoc() {
+ var headers = $("h1, h2");
+ if(headers.length > 1) {
+ var toc = $("#side-nav").append('<div id="nav-toc" class="toc"><h3>Table of contents</h3></div>');
+ toc = $("#nav-toc");
+ var footerHeight = footer.height();
+ toc = toc.append('<ul></ul>');
+ toc = toc.find('ul');
+ var indices = new Array();
+ indices[0] = 0;
+ indices[1] = 0;
+
+ var h1counts = $("h1").length;
+ headers.each(function(i) {
+ var current = $(this);
+ var levelTag = current[0].tagName.charAt(1);
+ if(h1counts==0)
+ levelTag--;
+ var cur_id = current.attr("id");
+
+ indices[levelTag-1]+=1;
+ var prefix = indices[0];
+ if (levelTag >1) {
+ prefix+="."+indices[1];
+ }
+
+ // Uncomment to add number prefixes
+ // current.html(prefix + " " + current.html());
+ for(var l = levelTag; l < 2; ++l){
+ indices[l] = 0;
+ }
+
+ if(cur_id == undefined) {
+ current.attr('id', 'title' + i);
+ current.addClass('anchor');
+ toc.append("<li class='level" + levelTag + "'><a id='link" + i + "' href='#title" +
+ i + "' title='" + current.prop("tagName") + "'>" + current.text() + "</a></li>");
+ } else {
+ toc.append("<li class='level" + levelTag + "'><a id='" + cur_id + "' href='#title" +
+ i + "' title='" + current.prop("tagName") + "'>" + current.text() + "</a></li>");
+ }
+ });
+ resizeHeight();
+ }
+}
+
+
+var global_navtree_object;
+
+// Overloaded to remove links to sections/subsections
+function getNode(o, po)
+{
+ po.childrenVisited = true;
+ var l = po.childrenData.length-1;
+ for (var i in po.childrenData) {
+ var nodeData = po.childrenData[i];
+ if((!nodeData[1]) || (nodeData[1].indexOf('#')==-1)) // <- we added this line
+ po.children[i] = newNode(o, po, nodeData[0], nodeData[1], nodeData[2], i==l);
+ }
+}
+
+// Overloaded to adjust the size of the navtree wrt the toc
+function resizeHeight()
+{
+ var toc = $("#nav-toc");
+ var tocHeight = toc.height(); // <- we added this line
+ var headerHeight = header.height();
+ var footerHeight = footer.height();
+ var windowHeight = $(window).height() - headerHeight - footerHeight;
+ content.css({height:windowHeight + "px"});
+ navtree.css({height:(windowHeight-tocHeight) + "px"}); // <- we modified this line
+ sidenav.css({height:(windowHeight) + "px",top: headerHeight+"px"});
+}
+
+// Overloaded to save the root node into global_navtree_object
+function initNavTree(toroot,relpath)
+{
+ var o = new Object();
+ global_navtree_object = o; // <- we added this line
+ o.toroot = toroot;
+ o.node = new Object();
+ o.node.li = document.getElementById("nav-tree-contents");
+ o.node.childrenData = NAVTREE;
+ o.node.children = new Array();
+ o.node.childrenUL = document.createElement("ul");
+ o.node.getChildrenUL = function() { return o.node.childrenUL; };
+ o.node.li.appendChild(o.node.childrenUL);
+ o.node.depth = 0;
+ o.node.relpath = relpath;
+ o.node.expanded = false;
+ o.node.isLast = true;
+ o.node.plus_img = document.createElement("img");
+ o.node.plus_img.src = relpath+"ftv2pnode.png";
+ o.node.plus_img.width = 16;
+ o.node.plus_img.height = 22;
+
+ if (localStorageSupported()) {
+ var navSync = $('#nav-sync');
+ if (cachedLink()) {
+ showSyncOff(navSync,relpath);
+ navSync.removeClass('sync');
+ } else {
+ showSyncOn(navSync,relpath);
+ }
+ navSync.click(function(){ toggleSyncButton(relpath); });
+ }
+
+ navTo(o,toroot,window.location.hash,relpath);
+
+ $(window).bind('hashchange', function(){
+ if (window.location.hash && window.location.hash.length>1){
+ var a;
+ if ($(location).attr('hash')){
+ var clslink=stripPath($(location).attr('pathname'))+':'+
+ $(location).attr('hash').substring(1);
+ a=$('.item a[class$="'+clslink+'"]');
+ }
+ if (a==null || !$(a).parent().parent().hasClass('selected')){
+ $('.item').removeClass('selected');
+ $('.item').removeAttr('id');
+ }
+ var link=stripPath2($(location).attr('pathname'));
+ navTo(o,link,$(location).attr('hash'),relpath);
+ } else if (!animationInProgress) {
+ $('#doc-content').scrollTop(0);
+ $('.item').removeClass('selected');
+ $('.item').removeAttr('id');
+ navTo(o,toroot,window.location.hash,relpath);
+ }
+ })
+
+ $(window).load(showRoot);
+}
+
+// return false if the the node has no children at all, or has only section/subsection children
+function checkChildrenData(node) {
+ if (!(typeof(node.childrenData)==='string')) {
+ for (var i in node.childrenData) {
+ var url = node.childrenData[i][1];
+ if(url.indexOf("#")==-1)
+ return true;
+ }
+ return false;
+ }
+ return (node.childrenData);
+}
+
+// Modified to:
+// 1 - remove the root node
+// 2 - remove the section/subsection children
+function createIndent(o,domNode,node,level)
+{
+ var level=-2; // <- we replaced level=-1 by level=-2
+ var n = node;
+ while (n.parentNode) { level++; n=n.parentNode; }
+ var imgNode = document.createElement("img");
+ imgNode.style.paddingLeft=(16*(level)).toString()+'px';
+ imgNode.width = 16;
+ imgNode.height = 22;
+ imgNode.border = 0;
+ if (checkChildrenData(node)) { // <- we modified this line to use checkChildrenData(node) instead of node.childrenData
+ node.plus_img = imgNode;
+ node.expandToggle = document.createElement("a");
+ node.expandToggle.href = "javascript:void(0)";
+ node.expandToggle.onclick = function() {
+ if (node.expanded) {
+ $(node.getChildrenUL()).slideUp("fast");
+ node.plus_img.src = node.relpath+"ftv2pnode.png";
+ node.expanded = false;
+ } else {
+ expandNode(o, node, false, false);
+ }
+ }
+ node.expandToggle.appendChild(imgNode);
+ domNode.appendChild(node.expandToggle);
+ imgNode.src = node.relpath+"ftv2pnode.png";
+ } else {
+ imgNode.src = node.relpath+"ftv2node.png";
+ domNode.appendChild(imgNode);
+ }
+}
+
+// Overloaded to automatically expand the selected node
+function selectAndHighlight(hash,n)
+{
+ var a;
+ if (hash) {
+ var link=stripPath($(location).attr('pathname'))+':'+hash.substring(1);
+ a=$('.item a[class$="'+link+'"]');
+ }
+ if (a && a.length) {
+ a.parent().parent().addClass('selected');
+ a.parent().parent().attr('id','selected');
+ highlightAnchor();
+ } else if (n) {
+ $(n.itemDiv).addClass('selected');
+ $(n.itemDiv).attr('id','selected');
+ }
+ if ($('#nav-tree-contents .item:first').hasClass('selected')) {
+ $('#nav-sync').css('top','30px');
+ } else {
+ $('#nav-sync').css('top','5px');
+ }
+ expandNode(global_navtree_object, n, true, true); // <- we added this line
+ showRoot();
+}
+
+
+$(document).ready(function() {
+
+ generate_autotoc();
+
+ (function (){ // wait until the first "selected" element has been created
+ try {
+
+ // this line will triger an exception if there is no #selected element, i.e., before the tree structure is complete.
+ document.getElementById("selected").className = "item selected";
+
+ // ok, the default tree has been created, we can keep going...
+
+ // expand the "Chapters" node
+ if(window.location.href.indexOf('unsupported')==-1)
+ expandNode(global_navtree_object, global_navtree_object.node.children[0].children[2], true, true);
+ else
+ expandNode(global_navtree_object, global_navtree_object.node.children[0].children[1], true, true);
+
+ // Hide the root node "Eigen"
+ $(document.getElementsByClassName('index.html')[0]).parent().parent().css({display:"none"});
+
+ } catch (err) {
+ setTimeout(arguments.callee, 10);
+ }
+ })();
+});
+
+$(window).load(function() {
+ resizeHeight();
+});
diff --git a/doc/eigendoxy.css b/doc/eigendoxy.css
index c6c16286d..efaeb46dc 100644
--- a/doc/eigendoxy.css
+++ b/doc/eigendoxy.css
@@ -1,708 +1,33 @@
-/* The standard CSS for doxygen */
-body, table, div, p, dl {
- font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif;
- font-size: 12px;
-}
-
-/* @group Heading Levels */
-
-h1 {
- font-size: 150%;
-}
-
-h2 {
- font-size: 120%;
-}
-
-h3 {
- font-size: 100%;
-}
-
-dt {
- font-weight: bold;
-}
-
-div.multicol {
- -moz-column-gap: 1em;
- -webkit-column-gap: 1em;
- -moz-column-count: 3;
- -webkit-column-count: 3;
-}
-
-p.startli, p.startdd, p.starttd {
- margin-top: 2px;
-}
-
-p.endli {
- margin-bottom: 0px;
-}
-
-p.enddd {
- margin-bottom: 4px;
-}
-
-p.endtd {
- margin-bottom: 2px;
-}
-
-/* @end */
-
-caption {
- font-weight: bold;
-}
-
-span.legend {
- font-size: 70%;
- text-align: center;
-}
-
-h3.version {
- font-size: 90%;
- text-align: center;
-}
-
-div.qindex, div.navtab{
- background-color: #EBEFF6;
- border: 1px solid #A3B4D7;
- text-align: center;
- margin: 2px;
- padding: 2px;
-}
-
-div.qindex, div.navpath {
- width: 100%;
- line-height: 140%;
-}
-
-div.navtab {
- margin-right: 15px;
-}
-
-/* @group Link Styling */
-
-a {
- color: #3D578C;
- font-weight: normal;
- text-decoration: none;
-}
-
-.contents a:visited {
- color: #4665A2;
-}
-
-a:hover {
- text-decoration: underline;
-}
-
-a.qindex {
- font-weight: bold;
-}
-
-a.qindexHL {
- font-weight: bold;
- background-color: #9CAFD4;
- color: #ffffff;
- border: 1px double #869DCA;
-}
-
-.contents a.qindexHL:visited {
- color: #ffffff;
-}
-
-a.el {
- font-weight: bold;
-}
-
-a.elRef {
-}
-
-a.code {
- color: #4665A2;
-}
-
-a.codeRef {
- color: #4665A2;
-}
-
-/* @end */
-
-dl.el {
- margin-left: -1cm;
-}
-
-.fragment {
- font-family: monospace, fixed;
- font-size: 105%;
-}
-
-pre.fragment {
- border: 1px solid #C4CFE5;
- background-color: #FBFCFD;
- padding: 4px 6px;
- margin: 4px 8px 4px 2px;
- overflow: auto;
- /*word-wrap: break-word;*/
- font-size: 9pt;
- line-height: 125%;
-}
-
-div.ah {
- background-color: black;
- font-weight: bold;
- color: #ffffff;
- margin-bottom: 3px;
- margin-top: 3px;
- padding: 0.2em;
- border: solid thin #333;
- border-radius: 0.5em;
- -webkit-border-radius: .5em;
- -moz-border-radius: .5em;
- box-shadow: 2px 2px 3px #999;
- -webkit-box-shadow: 2px 2px 3px #999;
- -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;
- background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444));
- background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000);
-}
-
-div.groupHeader {
- margin-left: 16px;
- margin-top: 12px;
- font-weight: bold;
-}
-
-div.groupText {
- margin-left: 16px;
- font-style: italic;
-}
-
-body {
- background: white;
- color: black;
- margin: 0;
-}
-
-div.contents {
- margin-top: 10px;
- margin-left: 10px;
- margin-right: 10px;
-}
-
-td.indexkey {
- background-color: #EBEFF6;
- font-weight: bold;
- border: 1px solid #C4CFE5;
- margin: 2px 0px 2px 0;
- padding: 2px 10px;
-}
-
-td.indexvalue {
- background-color: #EBEFF6;
- border: 1px solid #C4CFE5;
- padding: 2px 10px;
- margin: 2px 0px;
-}
-
-tr.memlist {
- background-color: #EEF1F7;
-}
-
-p.formulaDsp {
- text-align: center;
-}
-
-img.formulaDsp {
-
-}
-
-img.formulaInl {
- vertical-align: middle;
-}
-
-div.center {
- text-align: center;
- margin-top: 0px;
- margin-bottom: 0px;
- padding: 0px;
-}
-
-div.center img {
- border: 0px;
-}
-
-address.footer {
- text-align: right;
- padding-right: 12px;
-}
-
-img.footer {
- border: 0px;
- vertical-align: middle;
-}
-
-/* @group Code Colorization */
-
-span.keyword {
- color: #008000
-}
-
-span.keywordtype {
- color: #604020
-}
-
-span.keywordflow {
- color: #e08000
-}
-
-span.comment {
- color: #800000
-}
-
-span.preprocessor {
- color: #806020
-}
-
-span.stringliteral {
- color: #002080
-}
-
-span.charliteral {
- color: #008080
-}
-
-span.vhdldigit {
- color: #ff00ff
-}
-
-span.vhdlchar {
- color: #000000
-}
-
-span.vhdlkeyword {
- color: #700070
-}
-
-span.vhdllogic {
- color: #ff0000
-}
-
-/* @end */
-
-/*
-.search {
- color: #003399;
- font-weight: bold;
-}
-
-form.search {
- margin-bottom: 0px;
- margin-top: 0px;
-}
-
-input.search {
- font-size: 75%;
- color: #000080;
- font-weight: normal;
- background-color: #e8eef2;
-}
-*/
-
-td.tiny {
- font-size: 75%;
-}
-
-.dirtab {
- padding: 4px;
- border-collapse: collapse;
- border: 1px solid #A3B4D7;
-}
-
-th.dirtab {
- background: #EBEFF6;
- font-weight: bold;
-}
-
-hr {
- height: 0px;
- border: none;
- border-top: 1px solid #4A6AAA;
-}
-
-hr.footer {
- height: 1px;
-}
-
-/* @group Member Descriptions */
-
-table.memberdecls {
- border-spacing: 0px;
- padding: 0px;
-}
-
-.mdescLeft, .mdescRight,
-.memItemLeft, .memItemRight,
-.memTemplItemLeft, .memTemplItemRight, .memTemplParams {
- background-color: #F9FAFC;
- border: none;
- margin: 4px;
- padding: 1px 0 0 8px;
-}
-
-.mdescLeft, .mdescRight {
- padding: 0px 8px 4px 8px;
- color: #555;
-}
-
-.memItemLeft, .memItemRight, .memTemplParams {
- border-top: 1px solid #C4CFE5;
-}
-
-.memItemLeft, .memTemplItemLeft {
- white-space: nowrap;
-}
-
-.memTemplParams {
- color: #4665A2;
- white-space: nowrap;
-}
-
-/* @end */
-
-/* @group Member Details */
-
-/* Styles for detailed member documentation */
-
-.memtemplate {
- font-size: 80%;
- color: #4665A2;
- font-weight: normal;
- margin-left: 9px;
-}
-
-.memnav {
- background-color: #EBEFF6;
- border: 1px solid #A3B4D7;
- text-align: center;
- margin: 2px;
- margin-right: 15px;
- padding: 2px;
-}
-
-.memitem {
- padding: 0;
- margin-bottom: 10px;
-}
-
-.memname {
- white-space: nowrap;
- font-weight: bold;
- margin-left: 6px;
-}
-
-.memproto {
- border-top: 1px solid #A8B8D9;
- border-left: 1px solid #A8B8D9;
- border-right: 1px solid #A8B8D9;
- padding: 6px 0px 6px 0px;
- color: #253555;
- font-weight: bold;
- text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
- /* opera specific markup */
- box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
- border-top-right-radius: 8px;
- border-top-left-radius: 8px;
- /* firefox specific markup */
- -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
- -moz-border-radius-topright: 8px;
- -moz-border-radius-topleft: 8px;
- /* webkit specific markup */
- -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
- -webkit-border-top-right-radius: 8px;
- -webkit-border-top-left-radius: 8px;
- background-image:url('nav_f.png');
- background-repeat:repeat-x;
- background-color: #E2E8F2;
-
-}
-
-.memdoc {
- border-bottom: 1px solid #A8B8D9;
- border-left: 1px solid #A8B8D9;
- border-right: 1px solid #A8B8D9;
- padding: 2px 5px;
- background-color: #FBFCFD;
- border-top-width: 0;
- /* opera specific markup */
- border-bottom-left-radius: 8px;
- border-bottom-right-radius: 8px;
- box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
- /* firefox specific markup */
- -moz-border-radius-bottomleft: 8px;
- -moz-border-radius-bottomright: 8px;
- -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
- background-image: -moz-linear-gradient(center top, #FFFFFF 0%, #FFFFFF 60%, #F7F8FB 95%, #EEF1F7);
- /* webkit specific markup */
- -webkit-border-bottom-left-radius: 8px;
- -webkit-border-bottom-right-radius: 8px;
- -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
- background-image: -webkit-gradient(linear,center top,center bottom,from(#FFFFFF), color-stop(0.6,#FFFFFF), color-stop(0.60,#FFFFFF), color-stop(0.95,#F7F8FB), to(#EEF1F7));
-}
-
-.paramkey {
- text-align: right;
-}
-
-.paramtype {
- white-space: nowrap;
-}
-
-.paramname {
- color: #602020;
- white-space: nowrap;
-}
-.paramname em {
- font-style: normal;
-}
-
-.params, .retval, .exception, .tparams {
- border-spacing: 6px 2px;
-}
-
-.params .paramname, .retval .paramname {
- font-weight: bold;
- vertical-align: top;
-}
-
-.params .paramtype {
- font-style: italic;
- vertical-align: top;
-}
-
-.params .paramdir {
- font-family: "courier new",courier,monospace;
- vertical-align: top;
-}
-
-
-
-
-/* @end */
-
-/* @group Directory (tree) */
-
-/* for the tree view */
-
-.ftvtree {
- font-family: sans-serif;
- margin: 0px;
-}
-
-/* these are for tree view when used as main index */
-
-.directory {
- font-size: 9pt;
- font-weight: bold;
- margin: 5px;
-}
-
-.directory h3 {
- margin: 0px;
- margin-top: 1em;
- font-size: 11pt;
-}
-
-/*
-The following two styles can be used to replace the root node title
-with an image of your choice. Simply uncomment the next two styles,
-specify the name of your image and be sure to set 'height' to the
-proper pixel height of your image.
-*/
-
-/*
-.directory h3.swap {
- height: 61px;
- background-repeat: no-repeat;
- background-image: url("yourimage.gif");
-}
-.directory h3.swap span {
- display: none;
-}
-*/
-
-.directory > h3 {
- margin-top: 0;
-}
-
-.directory p {
- margin: 0px;
- white-space: nowrap;
-}
-
-.directory div {
- display: none;
- margin: 0px;
-}
-
-.directory img {
- vertical-align: -30%;
-}
-
-/* these are for tree view when not used as main index */
-
-.directory-alt {
- font-size: 100%;
- font-weight: bold;
-}
-
-.directory-alt h3 {
- margin: 0px;
- margin-top: 1em;
- font-size: 11pt;
-}
-
-.directory-alt > h3 {
- margin-top: 0;
-}
-
-.directory-alt p {
- margin: 0px;
- white-space: nowrap;
-}
-
-.directory-alt div {
- display: none;
- margin: 0px;
-}
-
-.directory-alt img {
- vertical-align: -30%;
-}
-
-/* @end */
-
-div.dynheader {
- margin-top: 8px;
-}
-
-address {
- font-style: normal;
- color: #2A3D61;
-}
-
-table.doxtable {
- border-collapse:collapse;
-}
-
-table.doxtable td, table.doxtable th {
- border: 1px solid #2D4068;
- padding: 3px 7px 2px;
-}
-
-table.doxtable th {
- background-color: #374F7F;
- color: #FFFFFF;
- font-size: 110%;
- padding-bottom: 4px;
- padding-top: 5px;
- text-align:left;
-}
-
-.tabsearch {
- top: 0px;
- left: 10px;
- height: 36px;
- background-image: url('tab_b.png');
- z-index: 101;
- overflow: hidden;
- font-size: 13px;
-}
-
-.navpath ul
-{
- font-size: 11px;
- background-image:url('tab_b.png');
- background-repeat:repeat-x;
- height:30px;
- line-height:30px;
- color:#8AA0CC;
- border:solid 1px #C2CDE4;
- overflow:hidden;
- margin:0px;
- padding:0px;
-}
-
-.navpath li
-{
- list-style-type:none;
- float:left;
- padding-left:10px;
- padding-right: 15px;
- background-image:url('bc_s.png');
- background-repeat:no-repeat;
- background-position:right;
- color:#364D7C;
-}
+/******** Eigen specific CSS code ************/
-.navpath a
-{
- height:32px;
- display:block;
- text-decoration: none;
- outline: none;
-}
+/**** Styles removing elements ****/
-.navpath a:hover
-{
- color:#6884BD;
+/* remove the "modules|classes" link for module pages (they are already in the TOC) */
+div.summary {
+ display:none;
}
-div.summary
-{
- float: right;
- font-size: 8pt;
- padding-right: 5px;
- width: 50%;
- text-align: right;
-}
-
-div.summary a
-{
- white-space: nowrap;
+/* remove */
+div.contents hr {
+ display:none;
}
-div.header
-{
- background-image:url('nav_h.png');
- background-repeat:repeat-x;
- background-color: #F9FAFC;
- margin: 0px;
- border-bottom: 1px solid #C4CFE5;
-}
+/**** ****/
-div.headertitle
+p, dl.warning, dl.attention, dl.note
{
- padding: 5px 5px 5px 10px;
-}
-
-
-
-/******** Eigen specific CSS code ************/
-
-
-body {
max-width:60em;
- margin-left:5%;
- margin-top:2%;
- font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif;
+ text-align:justify;
}
-img {
- border: 0;
+li {
+ max-width:55em;
+ text-align:justify;
}
-a.logo {
- float:right;
- margin:10px;
+img {
+ border: 0;
}
div.fragment {
@@ -712,10 +37,12 @@ div.fragment {
pre.fragment {
border: 1px solid #cccccc;
- margin: 2px 0px 2px 0px ;
+ margin: 2px 0px 2px 0px;
padding: 3px 5px 3px 5px;
}
+
+
/* Common style for all Eigen's tables */
table.example, table.manual, table.manual-vl {
@@ -816,51 +143,31 @@ h2 {
border-color: #cccccc;
}
+/**** Table of content in the side-nav ****/
-/**** old Eigen's styles ****/
-th {
- /*text-align: left;
- padding-right: 1em;*/
- /* border: #cccccc dashed; */
- /* border-style: dashed; */
- /* border-width: 0 0 3px 0; */
-}
-/*
-table.noborder {
- border-collapse: separate;
- border-bottom-style : none;
- border-left-style : none;
- border-right-style : none;
- border-top-style : none ;
- border-spacing : 0px 0px;
- margin: 4pt 0 0 0;
- padding: 0 0 0 0;
-
- -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
- -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
+div.toc {
+ margin:0;
+ padding: 0.3em 0 0 0;
+ width:100%;
+ float:none;
+ position:absolute;
+ bottom:0;
+ border-radius:0px;
+ border-style: solid none none none;
}
-table.noborder td {
- border-bottom-style : none;
- border-left-style : none;
- border-right-style : none;
- border-top-style : none;
- border-spacing : 0px 0px;
- margin: 0 0 0 0;
- vertical-align: top;
+div.toc h3 {
+ margin-left: 0.5em;
+ margin-bottom: 0.2em;
}
-table.tutorial_code {
- width: 90%;
- -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
- -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
+div.toc ul {
+ margin: 0.2em 0 0.4em 0.5em;
}
-table.tutorial_code tr {
- border: 1px dashed #888888;
-}
-*/
+/**** old Eigen's styles ****/
+
table.tutorial_code td {
border-color: transparent; /* required for Firefox */
@@ -878,23 +185,6 @@ table.tutorial_code td.note p.starttd {
border: none;
padding: 0px;
}
-/*
-div.fragment {
- font-family: monospace, fixed;
- font-size: 95%;
-
- border: none;
- padding: 0pt;
-}
-
-pre.fragment {
- margin: 0pt;
- border: 1px solid #cccccc;
- padding: 2px 5px 2px 5px;
-
- background-color: #f5f5f5;
-}
-*/
div.eimainmenu {
text-align: center;
@@ -909,3 +199,13 @@ h3.version {
td.width20em p.endtd {
width: 20em;
}
+
+.bigwarning {
+ font-size:2em;
+ font-weight:bold;
+ margin:1em;
+ padding:1em;
+ color:red;
+ border:solid;
+}
+
diff --git a/doc/eigendoxy_footer.html.in b/doc/eigendoxy_footer.html.in
index e70829fb0..878244a19 100644
--- a/doc/eigendoxy_footer.html.in
+++ b/doc/eigendoxy_footer.html.in
@@ -1,5 +1,36 @@
-
+<!-- start footer part -->
+<!--BEGIN GENERATE_TREEVIEW-->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+ <ul>
+ $navpath
+ <li class="footer">$generatedby
+ <a href="http://www.doxygen.org/index.html">
+ <img class="footer" src="$relpath$doxygen.png" alt="doxygen"/></a> $doxygenversion </li>
+ </ul>
+</div>
+<!--END GENERATE_TREEVIEW-->
+<!--BEGIN !GENERATE_TREEVIEW-->
<hr class="footer"/><address class="footer"><small>
-<a href="http://www.doxygen.org/index.html"><img class="footer" src="$relpath$doxygen.png" alt="doxygen"/></a></small></address>
+$generatedby &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="$relpath$doxygen.png" alt="doxygen"/>
+</a> $doxygenversion
+</small></address>
+<!--END !GENERATE_TREEVIEW-->
+
+<!-- Piwik -->
+<script type="text/javascript">
+var pkBaseURL = (("https:" == document.location.protocol) ? "https://stats.sylphide-consulting.com/piwik/" : "http://stats.sylphide-consulting.com/piwik/");
+document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E"));
+</script><script type="text/javascript">
+try {
+var piwikTracker = Piwik.getTracker(pkBaseURL + "piwik.php", 20);
+piwikTracker.trackPageView();
+piwikTracker.enableLinkTracking();
+} catch( err ) {}
+</script><noscript><p><img src="http://stats.sylphide-consulting.com/piwik/piwik.php?idsite=20" style="border:0" alt="" /></p></noscript>
+<!-- End Piwik Tracking Code -->
+
</body>
-</html> \ No newline at end of file
+</html>
+
+
diff --git a/doc/eigendoxy_header.html.in b/doc/eigendoxy_header.html.in
index a4fe47f27..0f3859f40 100644
--- a/doc/eigendoxy_header.html.in
+++ b/doc/eigendoxy_header.html.in
@@ -2,13 +2,60 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
-<title>$title</title>
-<link href="$relpath$eigendoxy_tabs.css" rel="stylesheet" type="text/css">
-<link href="$relpath$search/search.css" rel="stylesheet" type="text/css"/>
-<script type="text/javaScript" src="$relpath$search/search.js"></script>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen $doxygenversion"/>
+<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
+<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
+<link href="$relpath$tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="$relpath$jquery.js"></script>
+<script type="text/javascript" src="$relpath$dynsections.js"></script>
+$treeview
+$search
+$mathjax
+<link href="$relpath$$stylesheet" rel="stylesheet" type="text/css" />
<link href="$relpath$eigendoxy.css" rel="stylesheet" type="text/css">
+<!-- $extrastylesheet -->
+<script type="text/javascript" src="$relpath$eigen_navtree_hacks.js"></script>
+<!-- <script type="text/javascript"> -->
+<!-- </script> -->
+
</head>
-<body onload='searchBox.OnSelectItem(0);'>
-<a name="top"></a>
-<a class="logo" href="http://eigen.tuxfamily.org/">
-<img class="logo" src="Eigen_Silly_Professor_64x64.png" width=64 height=64 alt="Eigen's silly professor"/></a>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<!-- <a name="top"></a> -->
+
+<!--BEGIN TITLEAREA-->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <!--BEGIN PROJECT_LOGO-->
+ <td id="projectlogo"><img alt="Logo" src="$relpath$$projectlogo"/></td>
+ <!--END PROJECT_LOGO-->
+ <!--BEGIN PROJECT_NAME-->
+ <td style="padding-left: 0.5em;">
+ <div id="projectname"><a href="http://eigen.tuxfamily.org">$projectname</a>
+ <!--BEGIN PROJECT_NUMBER-->&#160;<span id="projectnumber">$projectnumber</span><!--END PROJECT_NUMBER-->
+ </div>
+ <!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
+ </td>
+ <!--END PROJECT_NAME-->
+ <!--BEGIN !PROJECT_NAME-->
+ <!--BEGIN PROJECT_BRIEF-->
+ <td style="padding-left: 0.5em;">
+ <div id="projectbrief">$projectbrief</div>
+ </td>
+ <!--END PROJECT_BRIEF-->
+ <!--END !PROJECT_NAME-->
+ <!--BEGIN DISABLE_INDEX-->
+ <!--BEGIN SEARCHENGINE-->
+ <td>$searchbox</td>
+ <!--END SEARCHENGINE-->
+ <!--END DISABLE_INDEX-->
+ </tr>
+ </tbody>
+</table>
+</div>
+<!--END TITLEAREA-->
+<!-- end header part -->
+
diff --git a/doc/eigendoxy_layout.xml.in b/doc/eigendoxy_layout.xml.in
new file mode 100644
index 000000000..c14b621e5
--- /dev/null
+++ b/doc/eigendoxy_layout.xml.in
@@ -0,0 +1,178 @@
+<?xml version="1.0"?>
+<doxygenlayout version="1.0">
+ <!-- Navigation index tabs for HTML output -->
+ <navindex>
+ <tab type="user" url="index.html" title="Overview" />
+ <tab type="user" url="@ref GettingStarted" title="Getting started" />
+ <tab type="modules" visible="yes" title="Chapters" intro=""/>
+ <tab type="mainpage" visible="yes" title=""/>
+ <tab type="classlist" visible="yes" title="" intro=""/>
+<!-- <tab type="classmembers" visible="yes" title="" intro=""/> -->
+ </navindex>
+
+ <!-- Layout definition for a class page -->
+ <class>
+ <briefdescription visible="no"/>
+ <includes visible="$SHOW_INCLUDE_FILES"/>
+ <detaileddescription title=""/>
+ <inheritancegraph visible="$CLASS_GRAPH"/>
+ <collaborationgraph visible="$COLLABORATION_GRAPH"/>
+ <allmemberslink visible="yes"/>
+ <memberdecl>
+ <nestedclasses visible="yes" title=""/>
+ <publictypes title=""/>
+ <publicslots title=""/>
+ <signals title=""/>
+ <publicmethods title=""/>
+ <publicstaticmethods title=""/>
+ <publicattributes title=""/>
+ <publicstaticattributes title=""/>
+ <protectedtypes title=""/>
+ <protectedslots title=""/>
+ <protectedmethods title=""/>
+ <protectedstaticmethods title=""/>
+ <protectedattributes title=""/>
+ <protectedstaticattributes title=""/>
+ <packagetypes title=""/>
+ <packagemethods title=""/>
+ <packagestaticmethods title=""/>
+ <packageattributes title=""/>
+ <packagestaticattributes title=""/>
+ <properties title=""/>
+ <events title=""/>
+ <privatetypes title=""/>
+ <privateslots title=""/>
+ <privatemethods title=""/>
+ <privatestaticmethods title=""/>
+ <privateattributes title=""/>
+ <privatestaticattributes title=""/>
+ <friends title=""/>
+ <related title="" subtitle=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+
+ <memberdef>
+ <inlineclasses title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <constructors title=""/>
+ <functions title=""/>
+ <related title=""/>
+ <variables title=""/>
+ <properties title=""/>
+ <events title=""/>
+ </memberdef>
+ <usedfiles visible="$SHOW_USED_FILES"/>
+ <authorsection visible="yes"/>
+ </class>
+
+ <!-- Layout definition for a namespace page -->
+ <namespace>
+ <briefdescription visible="yes"/>
+ <memberdecl>
+ <nestednamespaces visible="yes" title=""/>
+ <classes visible="yes" title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <inlineclasses title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ </memberdef>
+ <authorsection visible="yes"/>
+ </namespace>
+
+ <!-- Layout definition for a file page -->
+ <file>
+ <briefdescription visible="yes"/>
+ <includes visible="$SHOW_INCLUDE_FILES"/>
+ <includegraph visible="$INCLUDE_GRAPH"/>
+ <includedbygraph visible="$INCLUDED_BY_GRAPH"/>
+ <sourcelink visible="yes"/>
+ <memberdecl>
+ <classes visible="yes" title=""/>
+ <namespaces visible="yes" title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <inlineclasses title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ </memberdef>
+ <authorsection/>
+ </file>
+
+ <!-- Layout definition for a group page -->
+ <group>
+ <briefdescription visible="no"/>
+ <detaileddescription title=""/>
+ <groupgraph visible="$GROUP_GRAPHS"/>
+ <memberdecl>
+ <nestedgroups visible="yes" title=""/>
+ <dirs visible="yes" title=""/>
+ <files visible="yes" title=""/>
+ <namespaces visible="yes" title=""/>
+ <classes visible="yes" title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <enumvalues title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <signals title=""/>
+ <publicslots title=""/>
+ <protectedslots title=""/>
+ <privateslots title=""/>
+ <events title=""/>
+ <properties title=""/>
+ <friends title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+
+ <memberdef>
+ <pagedocs/>
+ <inlineclasses title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <enumvalues title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <signals title=""/>
+ <publicslots title=""/>
+ <protectedslots title=""/>
+ <privateslots title=""/>
+ <events title=""/>
+ <properties title=""/>
+ <friends title=""/>
+ </memberdef>
+ <authorsection visible="yes"/>
+ </group>
+
+ <!-- Layout definition for a directory page -->
+ <directory>
+ <briefdescription visible="yes"/>
+ <directorygraph visible="yes"/>
+ <memberdecl>
+ <dirs visible="yes"/>
+ <files visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ </directory>
+</doxygenlayout>
diff --git a/doc/examples/CMakeLists.txt b/doc/examples/CMakeLists.txt
index 13ec0c123..71b272a15 100644
--- a/doc/examples/CMakeLists.txt
+++ b/doc/examples/CMakeLists.txt
@@ -1,7 +1,5 @@
file(GLOB examples_SRCS "*.cpp")
-add_custom_target(all_examples)
-
foreach(example_src ${examples_SRCS})
get_filename_component(example ${example_src} NAME_WE)
add_executable(${example} ${example_src})
diff --git a/doc/examples/QuickStart_example2_dynamic.cpp b/doc/examples/QuickStart_example2_dynamic.cpp
index 672ac82e9..ff6746e21 100644
--- a/doc/examples/QuickStart_example2_dynamic.cpp
+++ b/doc/examples/QuickStart_example2_dynamic.cpp
@@ -6,10 +6,10 @@ using namespace std;
int main()
{
- MatrixXf m = MatrixXf::Random(3,3);
- m = (m + MatrixXf::Constant(3,3,1.2)) * 50;
+ MatrixXd m = MatrixXd::Random(3,3);
+ m = (m + MatrixXd::Constant(3,3,1.2)) * 50;
cout << "m =" << endl << m << endl;
- VectorXf v(3);
+ VectorXd v(3);
v << 1, 2, 3;
cout << "m * v =" << endl << m * v << endl;
}
diff --git a/doc/examples/QuickStart_example2_fixed.cpp b/doc/examples/QuickStart_example2_fixed.cpp
index edf3268cd..d91175273 100644
--- a/doc/examples/QuickStart_example2_fixed.cpp
+++ b/doc/examples/QuickStart_example2_fixed.cpp
@@ -6,10 +6,10 @@ using namespace std;
int main()
{
- Matrix3f m = Matrix3f::Random();
- m = (m + Matrix3f::Constant(1.2)) * 50;
+ Matrix3d m = Matrix3d::Random();
+ m = (m + Matrix3d::Constant(1.2)) * 50;
cout << "m =" << endl << m << endl;
- Vector3f v(1,2,3);
+ Vector3d v(1,2,3);
cout << "m * v =" << endl << m * v << endl;
}
diff --git a/doc/examples/function_taking_ref.cpp b/doc/examples/function_taking_ref.cpp
new file mode 100644
index 000000000..162a202e4
--- /dev/null
+++ b/doc/examples/function_taking_ref.cpp
@@ -0,0 +1,19 @@
+#include <iostream>
+#include <Eigen/SVD>
+using namespace Eigen;
+using namespace std;
+
+float inv_cond(const Ref<const MatrixXf>& a)
+{
+ const VectorXf sing_vals = a.jacobiSvd().singularValues();
+ return sing_vals(sing_vals.size()-1) / sing_vals(0);
+}
+
+int main()
+{
+ Matrix4f m = Matrix4f::Random();
+ cout << "matrix m:" << endl << m << endl << endl;
+ cout << "inv_cond(m): " << inv_cond(m) << endl;
+ cout << "inv_cond(m(1:3,1:3)): " << inv_cond(m.topLeftCorner(3,3)) << endl;
+ cout << "inv_cond(m+I): " << inv_cond(m+Matrix4f::Identity()) << endl;
+}
diff --git a/doc/snippets/Cwise_asin.cpp b/doc/snippets/Cwise_asin.cpp
new file mode 100644
index 000000000..8dad838fd
--- /dev/null
+++ b/doc/snippets/Cwise_asin.cpp
@@ -0,0 +1,2 @@
+Array3d v(0, sqrt(2.)/2, 1);
+cout << v.asin() << endl;
diff --git a/doc/snippets/DenseBase_setLinSpaced.cpp b/doc/snippets/DenseBase_setLinSpaced.cpp
index 50871dfcc..46054f234 100644
--- a/doc/snippets/DenseBase_setLinSpaced.cpp
+++ b/doc/snippets/DenseBase_setLinSpaced.cpp
@@ -1,3 +1,3 @@
VectorXf v;
-v.setLinSpaced(5,0.5f,1.5f).transpose();
+v.setLinSpaced(5,0.5f,1.5f);
cout << v << endl;
diff --git a/doc/snippets/GeneralizedEigenSolver.cpp b/doc/snippets/GeneralizedEigenSolver.cpp
new file mode 100644
index 000000000..2acda45fa
--- /dev/null
+++ b/doc/snippets/GeneralizedEigenSolver.cpp
@@ -0,0 +1,7 @@
+GeneralizedEigenSolver<MatrixXf> ges;
+MatrixXf A = MatrixXf::Random(4,4);
+MatrixXf B = MatrixXf::Random(4,4);
+ges.compute(A, B);
+cout << "The (complex) numerators of the generalzied eigenvalues are: " << ges.alphas().transpose() << endl;
+cout << "The (real) denominatore of the generalzied eigenvalues are: " << ges.betas().transpose() << endl;
+cout << "The (complex) generalzied eigenvalues are (alphas./beta): " << ges.eigenvalues().transpose() << endl;
diff --git a/doc/snippets/HouseholderQR_householderQ.cpp b/doc/snippets/HouseholderQR_householderQ.cpp
new file mode 100644
index 000000000..e859ce55b
--- /dev/null
+++ b/doc/snippets/HouseholderQR_householderQ.cpp
@@ -0,0 +1,7 @@
+MatrixXf A(MatrixXf::Random(5,3)), thinQ(MatrixXf::Identity(5,3)), Q;
+A.setRandom();
+HouseholderQR<MatrixXf> qr(A);
+Q = qr.householderQ();
+thinQ = qr.householderQ() * thinQ;
+std::cout << "The complete unitary matrix Q is:\n" << Q << "\n\n";
+std::cout << "The thin matrix Q is:\n" << thinQ << "\n\n";
diff --git a/doc/snippets/MatrixBase_applyOnTheLeft.cpp b/doc/snippets/MatrixBase_applyOnTheLeft.cpp
new file mode 100644
index 000000000..6398c873a
--- /dev/null
+++ b/doc/snippets/MatrixBase_applyOnTheLeft.cpp
@@ -0,0 +1,7 @@
+Matrix3f A = Matrix3f::Random(3,3), B;
+B << 0,1,0,
+ 0,0,1,
+ 1,0,0;
+cout << "At start, A = " << endl << A << endl;
+A.applyOnTheLeft(B);
+cout << "After applyOnTheLeft, A = " << endl << A << endl;
diff --git a/doc/snippets/MatrixBase_applyOnTheRight.cpp b/doc/snippets/MatrixBase_applyOnTheRight.cpp
new file mode 100644
index 000000000..e4b71b2d8
--- /dev/null
+++ b/doc/snippets/MatrixBase_applyOnTheRight.cpp
@@ -0,0 +1,9 @@
+Matrix3f A = Matrix3f::Random(3,3), B;
+B << 0,1,0,
+ 0,0,1,
+ 1,0,0;
+cout << "At start, A = " << endl << A << endl;
+A *= B;
+cout << "After A *= B, A = " << endl << A << endl;
+A.applyOnTheRight(B); // equivalent to A *= B
+cout << "After applyOnTheRight, A = " << endl << A << endl;
diff --git a/doc/snippets/MatrixBase_template_int_int_block_int_int_int_int.cpp b/doc/snippets/MatrixBase_template_int_int_block_int_int_int_int.cpp
new file mode 100644
index 000000000..4dced03ba
--- /dev/null
+++ b/doc/snippets/MatrixBase_template_int_int_block_int_int_int_int.cpp
@@ -0,0 +1,5 @@
+Matrix4i m = Matrix4i::Random();
+cout << "Here is the matrix m:" << endl << m << endl;
+cout << "Here is the block:" << endl << m.block<2, Dynamic>(1, 1, 2, 3) << endl;
+m.block<2, Dynamic>(1, 1, 2, 3).setZero();
+cout << "Now the matrix m is:" << endl << m << endl;
diff --git a/doc/snippets/MatrixBase_template_int_int_bottomLeftCorner_int_int.cpp b/doc/snippets/MatrixBase_template_int_int_bottomLeftCorner_int_int.cpp
new file mode 100644
index 000000000..a1edcc808
--- /dev/null
+++ b/doc/snippets/MatrixBase_template_int_int_bottomLeftCorner_int_int.cpp
@@ -0,0 +1,6 @@
+Matrix4i m = Matrix4i::Random();
+cout << "Here is the matrix m:" << endl << m << endl;
+cout << "Here is m.bottomLeftCorner<2,Dynamic>(2,2):" << endl;
+cout << m.bottomLeftCorner<2,Dynamic>(2,2) << endl;
+m.bottomLeftCorner<2,Dynamic>(2,2).setZero();
+cout << "Now the matrix m is:" << endl << m << endl;
diff --git a/doc/snippets/MatrixBase_template_int_int_bottomRightCorner_int_int.cpp b/doc/snippets/MatrixBase_template_int_int_bottomRightCorner_int_int.cpp
new file mode 100644
index 000000000..a65508fd8
--- /dev/null
+++ b/doc/snippets/MatrixBase_template_int_int_bottomRightCorner_int_int.cpp
@@ -0,0 +1,6 @@
+Matrix4i m = Matrix4i::Random();
+cout << "Here is the matrix m:" << endl << m << endl;
+cout << "Here is m.bottomRightCorner<2,Dynamic>(2,2):" << endl;
+cout << m.bottomRightCorner<2,Dynamic>(2,2) << endl;
+m.bottomRightCorner<2,Dynamic>(2,2).setZero();
+cout << "Now the matrix m is:" << endl << m << endl;
diff --git a/doc/snippets/MatrixBase_template_int_int_topLeftCorner_int_int.cpp b/doc/snippets/MatrixBase_template_int_int_topLeftCorner_int_int.cpp
new file mode 100644
index 000000000..fac761f63
--- /dev/null
+++ b/doc/snippets/MatrixBase_template_int_int_topLeftCorner_int_int.cpp
@@ -0,0 +1,6 @@
+Matrix4i m = Matrix4i::Random();
+cout << "Here is the matrix m:" << endl << m << endl;
+cout << "Here is m.topLeftCorner<2,Dynamic>(2,2):" << endl;
+cout << m.topLeftCorner<2,Dynamic>(2,2) << endl;
+m.topLeftCorner<2,Dynamic>(2,2).setZero();
+cout << "Now the matrix m is:" << endl << m << endl;
diff --git a/doc/snippets/MatrixBase_template_int_int_topRightCorner_int_int.cpp b/doc/snippets/MatrixBase_template_int_int_topRightCorner_int_int.cpp
new file mode 100644
index 000000000..a17acc004
--- /dev/null
+++ b/doc/snippets/MatrixBase_template_int_int_topRightCorner_int_int.cpp
@@ -0,0 +1,6 @@
+Matrix4i m = Matrix4i::Random();
+cout << "Here is the matrix m:" << endl << m << endl;
+cout << "Here is m.topRightCorner<2,Dynamic>(2,2):" << endl;
+cout << m.topRightCorner<2,Dynamic>(2,2) << endl;
+m.topRightCorner<2,Dynamic>(2,2).setZero();
+cout << "Now the matrix m is:" << endl << m << endl;
diff --git a/doc/snippets/RealQZ_compute.cpp b/doc/snippets/RealQZ_compute.cpp
new file mode 100644
index 000000000..a18da42e8
--- /dev/null
+++ b/doc/snippets/RealQZ_compute.cpp
@@ -0,0 +1,17 @@
+MatrixXf A = MatrixXf::Random(4,4);
+MatrixXf B = MatrixXf::Random(4,4);
+RealQZ<MatrixXf> qz(4); // preallocate space for 4x4 matrices
+qz.compute(A,B); // A = Q S Z, B = Q T Z
+
+// print original matrices and result of decomposition
+cout << "A:\n" << A << "\n" << "B:\n" << B << "\n";
+cout << "S:\n" << qz.matrixS() << "\n" << "T:\n" << qz.matrixT() << "\n";
+cout << "Q:\n" << qz.matrixQ() << "\n" << "Z:\n" << qz.matrixZ() << "\n";
+
+// verify precision
+cout << "\nErrors:"
+ << "\n|A-QSZ|: " << (A-qz.matrixQ()*qz.matrixS()*qz.matrixZ()).norm()
+ << ", |B-QTZ|: " << (B-qz.matrixQ()*qz.matrixT()*qz.matrixZ()).norm()
+ << "\n|QQ* - I|: " << (qz.matrixQ()*qz.matrixQ().adjoint() - MatrixXf::Identity(4,4)).norm()
+ << ", |ZZ* - I|: " << (qz.matrixZ()*qz.matrixZ().adjoint() - MatrixXf::Identity(4,4)).norm()
+ << "\n";
diff --git a/doc/special_examples/CMakeLists.txt b/doc/special_examples/CMakeLists.txt
index eeeae1d2a..0c9b3c3ba 100644
--- a/doc/special_examples/CMakeLists.txt
+++ b/doc/special_examples/CMakeLists.txt
@@ -10,11 +10,12 @@ endif(NOT EIGEN_TEST_NOQT)
if(QT4_FOUND)
add_executable(Tutorial_sparse_example Tutorial_sparse_example.cpp Tutorial_sparse_example_details.cpp)
target_link_libraries(Tutorial_sparse_example ${EIGEN_STANDARD_LIBRARIES_TO_LINK_TO} ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY})
-
+
add_custom_command(
TARGET Tutorial_sparse_example
POST_BUILD
- COMMAND Tutorial_sparse_example
- ARGS ${CMAKE_CURRENT_BINARY_DIR}/../html/Tutorial_sparse_example.jpeg
+ COMMAND Tutorial_sparse_example ARGS ${CMAKE_CURRENT_BINARY_DIR}/../html/Tutorial_sparse_example.jpeg
)
+
+ add_dependencies(all_examples Tutorial_sparse_example)
endif(QT4_FOUND)
diff --git a/doc/special_examples/Tutorial_sparse_example_details.cpp b/doc/special_examples/Tutorial_sparse_example_details.cpp
index 8c3020b63..7d820b44a 100644
--- a/doc/special_examples/Tutorial_sparse_example_details.cpp
+++ b/doc/special_examples/Tutorial_sparse_example_details.cpp
@@ -11,8 +11,8 @@ void insertCoefficient(int id, int i, int j, double w, std::vector<T>& coeffs,
int n = boundary.size();
int id1 = i+j*n;
- if(i==-1 || i==n) b(id) -= w * boundary(j); // constrained coeffcieint
- else if(j==-1 || j==n) b(id) -= w * boundary(i); // constrained coeffcieint
+ if(i==-1 || i==n) b(id) -= w * boundary(j); // constrained coefficient
+ else if(j==-1 || j==n) b(id) -= w * boundary(i); // constrained coefficient
else coeffs.push_back(T(id,id1,w)); // unknown coefficient
}
diff --git a/lapack/CMakeLists.txt b/lapack/CMakeLists.txt
index 062845a3f..9883d4c72 100644
--- a/lapack/CMakeLists.txt
+++ b/lapack/CMakeLists.txt
@@ -7,6 +7,9 @@ workaround_9220(Fortran EIGEN_Fortran_COMPILER_WORKS)
if(EIGEN_Fortran_COMPILER_WORKS)
enable_language(Fortran OPTIONAL)
+ if(NOT CMAKE_Fortran_COMPILER)
+ set(EIGEN_Fortran_COMPILER_WORKS OFF)
+ endif()
endif()
add_custom_target(lapack)
@@ -18,346 +21,80 @@ single.cpp double.cpp complex_single.cpp complex_double.cpp ../blas/xerbla.cpp
if(EIGEN_Fortran_COMPILER_WORKS)
-get_filename_component(eigen_full_path_to_reference_to_reference_lapack "./reference/" ABSOLUTE)
-if(EXISTS ${eigen_full_path_to_reference_to_reference_lapack})
-set(EigenLapack_SRCS ${EigenLapack_SRCS}
-# reference/dpotrf.f reference/zpotrf.f reference/cpotrf.f reference/spotrf.f
-# reference/dpotrs.f reference/spotrs.f reference/zpotrs.f reference/cpotrs.f
-# reference/dgetrf.f reference/cgetrf.f reference/sgetrf.f reference/zgetrf.f
-# reference/cgetrs.f reference/dgetrs.f reference/sgetrs.f reference/zgetrs.f
-# reference/dsyev.f reference/ssyev.f
-
-reference/dlamch.f reference/ilaver.f reference/lsame.f reference/slamch.f reference/second_NONE.f reference/dsecnd_NONE.f
-reference/cbdsqr.f reference/ctbrfs.f reference/dorml2.f reference/sla_porfsx_extended.f reference/zggglm.f
-reference/cgbbrd.f reference/ctbtrs.f reference/dormlq.f reference/sla_porpvgrw.f reference/zgghrd.f
-reference/cgbcon.f reference/ctfsm.f reference/dormql.f reference/slapy2.f reference/zgglse.f
-reference/cgbequb.f reference/ctftri.f reference/dormqr.f reference/slapy3.f reference/zggqrf.f
-reference/cgbequ.f reference/ctfttp.f reference/dormr2.f reference/slaqgb.f reference/zggrqf.f
-reference/cgbrfs.f reference/ctfttr.f reference/dormr3.f reference/slaqge.f reference/zggsvd.f
-reference/cgbrfsx.f reference/ctgevc.f reference/dormrq.f reference/slaqp2.f reference/zggsvp.f
-reference/cgbsv.f reference/ctgex2.f reference/dormrz.f reference/slaqps.f reference/zgtcon.f
-reference/cgbsvx.f reference/ctgexc.f reference/dormtr.f reference/slaqr0.f reference/zgtrfs.f
-reference/cgbsvxx.f reference/ctgsen.f reference/dpbcon.f reference/slaqr1.f reference/zgtsv.f
-reference/cgbtf2.f reference/ctgsja.f reference/dpbequ.f reference/slaqr2.f reference/zgtsvx.f
-reference/cgbtrf.f reference/ctgsna.f reference/dpbrfs.f reference/slaqr3.f reference/zgttrf.f
-reference/cgbtrs.f reference/ctgsy2.f reference/dpbstf.f reference/slaqr4.f reference/zgttrs.f
-reference/cgebak.f reference/ctgsyl.f reference/dpbsv.f reference/slaqr5.f reference/zgtts2.f
-reference/cgebal.f reference/ctpcon.f reference/dpbsvx.f reference/slaqsb.f reference/zhbevd.f
-reference/cgebd2.f reference/ctprfs.f reference/dpbtf2.f reference/slaqsp.f reference/zhbev.f
-reference/cgebrd.f reference/ctptri.f reference/dpbtrf.f reference/slaqsy.f reference/zhbevx.f
-reference/cgecon.f reference/ctptrs.f reference/dpbtrs.f reference/slaqtr.f reference/zhbgst.f
-reference/cgeequb.f reference/ctpttf.f reference/dpftrf.f reference/slar1v.f reference/zhbgvd.f
-reference/cgeequ.f reference/ctpttr.f reference/dpftri.f reference/slar2v.f reference/zhbgv.f
-reference/cgees.f reference/ctrcon.f reference/dpftrs.f reference/slarfb.f reference/zhbgvx.f
-reference/cgeesx.f reference/ctrevc.f reference/dpocon.f reference/slarf.f reference/zhbtrd.f
-reference/cgeev.f reference/ctrexc.f reference/dpoequb.f reference/slarfg.f reference/zhecon.f
-reference/cgeevx.f reference/ctrrfs.f reference/dpoequ.f reference/slarfp.f reference/zheequb.f
-reference/cgegs.f reference/ctrsen.f reference/dporfs.f reference/slarft.f reference/zheevd.f
-reference/cgegv.f reference/ctrsna.f reference/dporfsx.f reference/slarfx.f reference/zheev.f
-reference/cgehd2.f reference/ctrsyl.f reference/dposv.f reference/slargv.f reference/zheevr.f
-reference/cgehrd.f reference/ctrti2.f reference/dposvx.f reference/slarnv.f reference/zheevx.f
-reference/cgelq2.f reference/ctrtri.f reference/dposvxx.f reference/sla_rpvgrw.f reference/zhegs2.f
-reference/cgelqf.f reference/ctrtrs.f reference/dpotf2.f reference/slarra.f reference/zhegst.f
-reference/cgelsd.f reference/ctrttf.f
-reference/slarrb.f reference/zhegvd.f
-reference/cgels.f reference/ctrttp.f reference/dpotri.f reference/slarrc.f reference/zhegv.f
-reference/cgelss.f reference/ctzrqf.f reference/slarrd.f reference/zhegvx.f
-reference/cgelsx.f reference/ctzrzf.f reference/dppcon.f reference/slarre.f reference/zherfs.f
-reference/cgelsy.f reference/cung2l.f reference/dppequ.f reference/slarrf.f reference/zherfsx.f
-reference/cgeql2.f reference/cung2r.f reference/dpprfs.f reference/slarrj.f reference/zhesv.f
-reference/cgeqlf.f reference/cungbr.f reference/dppsv.f reference/slarrk.f reference/zhesvx.f
-reference/cgeqp3.f reference/cunghr.f reference/dppsvx.f reference/slarrr.f reference/zhesvxx.f
-reference/cgeqpf.f reference/cungl2.f reference/dpptrf.f reference/slarrv.f reference/zhetd2.f
-reference/cgeqr2.f reference/cunglq.f reference/dpptri.f reference/slarscl2.f reference/zhetf2.f
-reference/cgeqrf.f reference/cungql.f reference/dpptrs.f reference/slartg.f reference/zhetrd.f
-reference/cgerfs.f reference/cungqr.f reference/dpstf2.f reference/slartv.f reference/zhetrf.f
-reference/cgerfsx.f reference/cungr2.f reference/dpstrf.f reference/slaruv.f reference/zhetri.f
-reference/cgerq2.f reference/cungrq.f reference/dptcon.f reference/slarzb.f reference/zhetrs.f
-reference/cgerqf.f reference/cungtr.f reference/dpteqr.f reference/slarz.f reference/zhfrk.f
-reference/cgesc2.f reference/cunm2l.f reference/dptrfs.f reference/slarzt.f reference/zhgeqz.f
-reference/cgesdd.f reference/cunm2r.f reference/dptsv.f reference/slas2.f reference/zhpcon.f
-reference/cgesvd.f reference/cunmbr.f reference/dptsvx.f reference/slascl2.f reference/zhpevd.f
-reference/cgesv.f reference/cunmhr.f reference/dpttrf.f reference/slascl.f reference/zhpev.f
-reference/cgesvx.f reference/cunml2.f reference/dpttrs.f reference/slasd0.f reference/zhpevx.f
-reference/cgesvxx.f reference/cunmlq.f reference/dptts2.f reference/slasd1.f reference/zhpgst.f
-reference/cgetc2.f reference/cunmql.f reference/drscl.f reference/slasd2.f reference/zhpgvd.f
-reference/cgetf2.f reference/cunmqr.f reference/dsbevd.f reference/slasd3.f reference/zhpgv.f
-reference/cunmr2.f reference/dsbev.f reference/slasd4.f reference/zhpgvx.f
-reference/cgetri.f reference/cunmr3.f reference/dsbevx.f reference/slasd5.f reference/zhprfs.f
- reference/cunmrq.f reference/dsbgst.f reference/slasd6.f reference/zhpsv.f
-reference/cggbak.f reference/cunmrz.f reference/dsbgvd.f reference/slasd7.f reference/zhpsvx.f
-reference/cggbal.f reference/cunmtr.f reference/dsbgv.f reference/slasd8.f reference/zhptrd.f
-reference/cgges.f reference/cupgtr.f reference/dsbgvx.f reference/slasda.f reference/zhptrf.f
-reference/cggesx.f reference/cupmtr.f reference/dsbtrd.f reference/slasdq.f reference/zhptri.f
-reference/cggev.f reference/dbdsdc.f reference/dsfrk.f reference/slasdt.f reference/zhptrs.f
-reference/cggevx.f reference/dbdsqr.f reference/dsgesv.f reference/slaset.f reference/zhsein.f
-reference/cggglm.f reference/ddisna.f reference/dspcon.f reference/slasq1.f reference/zhseqr.f
-reference/cgghrd.f reference/dgbbrd.f reference/dspevd.f reference/slasq2.f reference/zlabrd.f
-reference/cgglse.f reference/dgbcon.f reference/dspev.f reference/slasq3.f reference/zlacgv.f
-reference/cggqrf.f reference/dgbequb.f reference/dspevx.f reference/slasq4.f reference/zlacn2.f
-reference/cggrqf.f reference/dgbequ.f reference/dspgst.f reference/slasq5.f reference/zlacon.f
-reference/cggsvd.f reference/dgbrfs.f reference/dspgvd.f reference/slasq6.f reference/zlacp2.f
-reference/cggsvp.f reference/dgbrfsx.f reference/dspgv.f reference/slasr.f reference/zlacpy.f
-reference/cgtcon.f reference/dgbsv.f reference/dspgvx.f reference/slasrt.f reference/zlacrm.f
-reference/cgtrfs.f reference/dgbsvx.f reference/dsposv.f reference/slassq.f reference/zlacrt.f
-reference/cgtsv.f reference/dgbsvxx.f reference/dsprfs.f reference/slasv2.f reference/zladiv.f
-reference/cgtsvx.f reference/dgbtf2.f reference/dspsv.f reference/slaswp.f reference/zlaed0.f
-reference/cgttrf.f reference/dgbtrf.f reference/dspsvx.f reference/slasy2.f reference/zlaed7.f
-reference/cgttrs.f reference/dgbtrs.f reference/dsptrd.f reference/sla_syamv.f reference/zlaed8.f
-reference/cgtts2.f reference/dgebak.f reference/dsptrf.f reference/slasyf.f reference/zlaein.f
-reference/chbevd.f reference/dgebal.f reference/dsptri.f reference/sla_syrcond.f reference/zlaesy.f
-reference/chbev.f reference/dgebd2.f reference/dsptrs.f reference/sla_syrfsx_extended.f reference/zlaev2.f
-reference/chbevx.f reference/dgebrd.f reference/dstebz.f reference/sla_syrpvgrw.f reference/zlag2c.f
-reference/chbgst.f reference/dgecon.f reference/dstedc.f reference/slatbs.f reference/zla_gbamv.f
-reference/chbgvd.f reference/dgeequb.f reference/dstegr.f reference/slatdf.f reference/zla_gbrcond_c.f
-reference/chbgv.f reference/dgeequ.f reference/dstein.f reference/slatps.f reference/zla_gbrcond_x.f
-reference/chbgvx.f reference/dgees.f reference/dstemr.f reference/slatrd.f reference/zla_gbrfsx_extended.f
-reference/chbtrd.f reference/dgeesx.f reference/dsteqr.f reference/slatrs.f reference/zla_gbrpvgrw.f
-reference/checon.f reference/dgeev.f reference/dsterf.f reference/slatrz.f reference/zla_geamv.f
-reference/cheequb.f reference/dgeevx.f reference/dstevd.f reference/slatzm.f reference/zla_gercond_c.f
-reference/cheevd.f reference/dgegs.f reference/dstev.f reference/slauu2.f reference/zla_gercond_x.f
-reference/cheev.f reference/dgegv.f reference/dstevr.f reference/slauum.f reference/zla_gerfsx_extended.f
-reference/cheevr.f reference/dgehd2.f reference/dstevx.f reference/sla_wwaddw.f reference/zlags2.f
-reference/cheevx.f reference/dgehrd.f reference/dsycon.f reference/sopgtr.f reference/zlagtm.f
-reference/chegs2.f reference/dgejsv.f reference/dsyequb.f reference/sopmtr.f reference/zla_heamv.f
-reference/chegst.f reference/dgelq2.f reference/dsyevd.f reference/sorg2l.f reference/zlahef.f
-reference/chegvd.f reference/dgelqf.f reference/sorg2r.f reference/zla_hercond_c.f
-reference/chegv.f reference/dgelsd.f reference/dsyevr.f reference/sorgbr.f reference/zla_hercond_x.f
-reference/chegvx.f reference/dgels.f reference/dsyevx.f reference/sorghr.f reference/zla_herfsx_extended.f
-reference/cherfs.f reference/dgelss.f reference/dsygs2.f reference/sorgl2.f reference/zla_herpvgrw.f
-reference/cherfsx.f reference/dgelsx.f reference/dsygst.f reference/sorglq.f reference/zlahqr.f
-reference/chesv.f reference/dgelsy.f reference/dsygvd.f reference/sorgql.f reference/zlahr2.f
-reference/chesvx.f reference/dgeql2.f reference/dsygv.f reference/sorgqr.f reference/zlahrd.f
-reference/chesvxx.f reference/dgeqlf.f reference/dsygvx.f reference/sorgr2.f reference/zlaic1.f
-reference/chetd2.f reference/dgeqp3.f reference/dsyrfs.f reference/sorgrq.f reference/zla_lin_berr.f
-reference/chetf2.f reference/dgeqpf.f reference/dsyrfsx.f reference/sorgtr.f reference/zlals0.f
-reference/chetrd.f reference/dgeqr2.f reference/dsysv.f reference/sorm2l.f reference/zlalsa.f
-reference/chetrf.f reference/dgeqrf.f reference/dsysvx.f reference/sorm2r.f reference/zlalsd.f
-reference/chetri.f reference/dgerfs.f reference/dsysvxx.f reference/sormbr.f reference/zlangb.f
-reference/chetrs.f reference/dgerfsx.f reference/dsytd2.f reference/sormhr.f reference/zlange.f
-reference/chfrk.f reference/dgerq2.f reference/dsytf2.f reference/sorml2.f reference/zlangt.f
-reference/chgeqz.f reference/dgerqf.f reference/dsytrd.f reference/sormlq.f reference/zlanhb.f
-reference/chla_transtype.f reference/dgesc2.f reference/dsytrf.f reference/sormql.f reference/zlanhe.f
-reference/chpcon.f reference/dgesdd.f reference/dsytri.f reference/sormqr.f reference/zlanhf.f
-reference/chpevd.f reference/dgesvd.f reference/dsytrs.f reference/sormr2.f reference/zlanhp.f
-reference/chpev.f reference/dgesv.f reference/dtbcon.f reference/sormr3.f reference/zlanhs.f
-reference/chpevx.f reference/dgesvj.f reference/dtbrfs.f reference/sormrq.f reference/zlanht.f
-reference/chpgst.f reference/dgesvx.f reference/dtbtrs.f reference/sormrz.f reference/zlansb.f
-reference/chpgvd.f reference/dgesvxx.f reference/dtfsm.f reference/sormtr.f reference/zlansp.f
-reference/chpgv.f reference/dgetc2.f reference/dtftri.f reference/spbcon.f reference/zlansy.f
-reference/chpgvx.f reference/dgetf2.f reference/dtfttp.f reference/spbequ.f reference/zlantb.f
-reference/chprfs.f
-reference/dtfttr.f reference/spbrfs.f reference/zlantp.f
-reference/chpsv.f reference/dgetri.f reference/dtgevc.f reference/spbstf.f reference/zlantr.f
-reference/chpsvx.f reference/dtgex2.f reference/spbsv.f reference/zlapll.f
-reference/chptrd.f reference/dggbak.f reference/dtgexc.f reference/spbsvx.f reference/zlapmt.f
-reference/chptrf.f reference/dggbal.f reference/dtgsen.f reference/spbtf2.f reference/zla_porcond_c.f
-reference/chptri.f reference/dgges.f reference/dtgsja.f reference/spbtrf.f reference/zla_porcond_x.f
-reference/chptrs.f reference/dggesx.f reference/dtgsna.f reference/spbtrs.f reference/zla_porfsx_extended.f
-reference/chsein.f reference/dggev.f reference/dtgsy2.f reference/spftrf.f reference/zla_porpvgrw.f
-reference/chseqr.f reference/dggevx.f reference/dtgsyl.f reference/spftri.f reference/zlaqgb.f
-reference/clabrd.f reference/dggglm.f reference/dtpcon.f reference/spftrs.f reference/zlaqge.f
-reference/clacgv.f reference/dgghrd.f reference/dtprfs.f reference/spocon.f reference/zlaqhb.f
-reference/clacn2.f reference/dgglse.f reference/dtptri.f reference/spoequb.f reference/zlaqhe.f
-reference/clacon.f reference/dggqrf.f reference/dtptrs.f reference/spoequ.f reference/zlaqhp.f
-reference/clacp2.f reference/dggrqf.f reference/dtpttf.f reference/sporfs.f reference/zlaqp2.f
-reference/clacpy.f reference/dggsvd.f reference/dtpttr.f reference/sporfsx.f reference/zlaqps.f
-reference/clacrm.f reference/dggsvp.f reference/dtrcon.f reference/sposv.f reference/zlaqr0.f
-reference/clacrt.f reference/dgsvj0.f reference/dtrevc.f reference/sposvx.f reference/zlaqr1.f
-reference/cladiv.f reference/dgsvj1.f reference/dtrexc.f reference/sposvxx.f reference/zlaqr2.f
-reference/claed0.f reference/dgtcon.f reference/dtrrfs.f reference/spotf2.f reference/zlaqr3.f
-reference/claed7.f reference/dgtrfs.f reference/dtrsen.f
-reference/zlaqr4.f
-reference/claed8.f reference/dgtsv.f reference/dtrsna.f reference/spotri.f reference/zlaqr5.f
-reference/claein.f reference/dgtsvx.f reference/dtrsyl.f reference/zlaqsb.f
-reference/claesy.f reference/dgttrf.f reference/dtrti2.f reference/sppcon.f reference/zlaqsp.f
-reference/claev2.f reference/dgttrs.f reference/dtrtri.f reference/sppequ.f reference/zlaqsy.f
-reference/clag2z.f reference/dgtts2.f reference/dtrtrs.f reference/spprfs.f reference/zlar1v.f
-reference/cla_gbamv.f reference/dhgeqz.f reference/dtrttf.f reference/sppsv.f reference/zlar2v.f
-reference/cla_gbrcond_c.f reference/dhsein.f reference/dtrttp.f reference/sppsvx.f reference/zlarcm.f
-reference/cla_gbrcond_x.f reference/dhseqr.f reference/dtzrqf.f reference/spptrf.f reference/zlarfb.f
-reference/cla_gbrfsx_extended.f reference/disnan.f reference/dtzrzf.f reference/spptri.f reference/zlarf.f
-reference/cla_gbrpvgrw.f reference/dlabad.f reference/dzsum1.f reference/spptrs.f reference/zlarfg.f
-reference/cla_geamv.f reference/dlabrd.f reference/icmax1.f reference/spstf2.f reference/zlarfp.f
-reference/cla_gercond_c.f reference/dlacn2.f reference/ieeeck.f reference/spstrf.f reference/zlarft.f
-reference/cla_gercond_x.f reference/dlacon.f reference/ilaclc.f reference/sptcon.f reference/zlarfx.f
-reference/cla_gerfsx_extended.f reference/dlacpy.f reference/ilaclr.f reference/spteqr.f reference/zlargv.f
-reference/clags2.f reference/dladiv.f reference/iladiag.f reference/sptrfs.f reference/zlarnv.f
-reference/clagtm.f reference/dlae2.f reference/iladlc.f reference/sptsv.f reference/zla_rpvgrw.f
-reference/cla_heamv.f reference/dlaebz.f reference/iladlr.f reference/sptsvx.f reference/zlarrv.f
-reference/clahef.f reference/dlaed0.f reference/ilaenv.f reference/spttrf.f reference/zlarscl2.f
-reference/cla_hercond_c.f reference/dlaed1.f reference/ilaprec.f reference/spttrs.f reference/zlartg.f
-reference/cla_hercond_x.f reference/dlaed2.f reference/ilaslc.f reference/sptts2.f reference/zlartv.f
-reference/cla_herfsx_extended.f reference/dlaed3.f reference/ilaslr.f reference/srscl.f reference/zlarzb.f
-reference/cla_herpvgrw.f reference/dlaed4.f reference/ilatrans.f reference/ssbevd.f reference/zlarz.f
-reference/clahqr.f reference/dlaed5.f reference/ilauplo.f reference/ssbev.f reference/zlarzt.f
-reference/clahr2.f reference/dlaed6.f reference/ilaver.f reference/ssbevx.f reference/zlascl2.f
-reference/clahrd.f reference/dlaed7.f reference/ilazlc.f reference/ssbgst.f reference/zlascl.f
-reference/claic1.f reference/dlaed8.f reference/ilazlr.f reference/ssbgvd.f reference/zlaset.f
-reference/cla_lin_berr.f reference/dlaed9.f reference/iparmq.f reference/ssbgv.f reference/zlasr.f
-reference/clals0.f reference/dlaeda.f reference/izmax1.f reference/ssbgvx.f reference/zlassq.f
-reference/clalsa.f reference/dlaein.f reference/lsamen.f reference/ssbtrd.f reference/zlaswp.f
-reference/clalsd.f reference/dlaev2.f reference/sbdsdc.f reference/ssfrk.f reference/zla_syamv.f
-reference/clangb.f reference/dlaexc.f reference/sbdsqr.f reference/sspcon.f reference/zlasyf.f
-reference/clange.f reference/dlag2.f reference/scsum1.f reference/sspevd.f reference/zla_syrcond_c.f
-reference/clangt.f reference/dlag2s.f reference/sdisna.f reference/sspev.f reference/zla_syrcond_x.f
-reference/clanhb.f reference/dla_gbamv.f reference/sgbbrd.f reference/sspevx.f reference/zla_syrfsx_extended.f
-reference/clanhe.f reference/dla_gbrcond.f reference/sgbcon.f reference/sspgst.f reference/zla_syrpvgrw.f
-reference/clanhf.f reference/dla_gbrfsx_extended.f reference/sgbequb.f reference/sspgvd.f reference/zlat2c.f
-reference/clanhp.f reference/dla_gbrpvgrw.f reference/sgbequ.f reference/sspgv.f reference/zlatbs.f
-reference/clanhs.f reference/dla_geamv.f reference/sgbrfs.f reference/sspgvx.f reference/zlatdf.f
-reference/clanht.f reference/dla_gercond.f reference/sgbrfsx.f reference/ssprfs.f reference/zlatps.f
-reference/clansb.f reference/dla_gerfsx_extended.f reference/sgbsv.f reference/sspsv.f reference/zlatrd.f
-reference/clansp.f reference/dlags2.f reference/sgbsvx.f reference/sspsvx.f reference/zlatrs.f
-reference/clansy.f reference/dlagtf.f reference/sgbsvxx.f reference/ssptrd.f reference/zlatrz.f
-reference/clantb.f reference/dlagtm.f reference/sgbtf2.f reference/ssptrf.f reference/zlatzm.f
-reference/clantp.f reference/dlagts.f reference/sgbtrf.f reference/ssptri.f reference/zlauu2.f
-reference/clantr.f reference/dlagv2.f reference/sgbtrs.f reference/ssptrs.f reference/zlauum.f
-reference/clapll.f reference/dlahqr.f reference/sgebak.f reference/sstebz.f reference/zla_wwaddw.f
-reference/clapmt.f reference/dlahr2.f reference/sgebal.f reference/sstedc.f reference/zpbcon.f
-reference/cla_porcond_c.f reference/dlahrd.f reference/sgebd2.f reference/sstegr.f reference/zpbequ.f
-reference/cla_porcond_x.f reference/dlaic1.f reference/sgebrd.f reference/sstein.f reference/zpbrfs.f
-reference/cla_porfsx_extended.f reference/dlaisnan.f reference/sgecon.f reference/sstemr.f reference/zpbstf.f
-reference/cla_porpvgrw.f reference/dla_lin_berr.f reference/sgeequb.f reference/ssteqr.f reference/zpbsv.f
-reference/claqgb.f reference/dlaln2.f reference/sgeequ.f reference/ssterf.f reference/zpbsvx.f
-reference/claqge.f reference/dlals0.f reference/sgees.f reference/sstevd.f reference/zpbtf2.f
-reference/claqhb.f reference/dlalsa.f reference/sgeesx.f reference/sstev.f reference/zpbtrf.f
-reference/claqhe.f reference/dlalsd.f reference/sgeev.f reference/sstevr.f reference/zpbtrs.f
-reference/claqhp.f reference/dlamrg.f reference/sgeevx.f reference/sstevx.f reference/zpftrf.f
-reference/claqp2.f reference/dlaneg.f reference/sgegs.f reference/ssycon.f reference/zpftri.f
-reference/claqps.f reference/dlangb.f reference/sgegv.f reference/ssyequb.f reference/zpftrs.f
-reference/claqr0.f reference/dlange.f reference/sgehd2.f reference/ssyevd.f reference/zpocon.f
-reference/claqr1.f reference/dlangt.f reference/sgehrd.f reference/zpoequb.f
-reference/claqr2.f reference/dlanhs.f reference/sgejsv.f reference/ssyevr.f reference/zpoequ.f
-reference/claqr3.f reference/dlansb.f reference/sgelq2.f reference/ssyevx.f reference/zporfs.f
-reference/claqr4.f reference/dlansf.f reference/sgelqf.f reference/ssygs2.f reference/zporfsx.f
-reference/claqr5.f reference/dlansp.f reference/sgelsd.f reference/ssygst.f reference/zposv.f
-reference/claqsb.f reference/dlanst.f reference/sgels.f reference/ssygvd.f reference/zposvx.f
-reference/claqsp.f reference/dlansy.f reference/sgelss.f reference/ssygv.f reference/zposvxx.f
-reference/claqsy.f reference/dlantb.f reference/sgelsx.f reference/ssygvx.f reference/zpotf2.f
-reference/clar1v.f reference/dlantp.f reference/sgelsy.f reference/ssyrfs.f
-reference/clar2v.f reference/dlantr.f reference/sgeql2.f reference/ssyrfsx.f reference/zpotri.f
-reference/clarcm.f reference/dlanv2.f reference/sgeqlf.f reference/ssysv.f
-reference/clarfb.f reference/dlapll.f reference/sgeqp3.f reference/ssysvx.f reference/zppcon.f
-reference/clarf.f reference/dlapmt.f reference/sgeqpf.f reference/ssysvxx.f reference/zppequ.f
-reference/clarfg.f reference/dla_porcond.f reference/sgeqr2.f reference/ssytd2.f reference/zpprfs.f
-reference/clarfp.f reference/dla_porfsx_extended.f reference/sgeqrf.f reference/ssytf2.f reference/zppsv.f
-reference/clarft.f reference/dla_porpvgrw.f reference/sgerfs.f reference/ssytrd.f reference/zppsvx.f
-reference/clarfx.f reference/dlapy2.f reference/sgerfsx.f reference/ssytrf.f reference/zpptrf.f
-reference/clargv.f reference/dlapy3.f reference/sgerq2.f reference/ssytri.f reference/zpptri.f
-reference/clarnv.f reference/dlaqgb.f reference/sgerqf.f reference/ssytrs.f reference/zpptrs.f
-reference/cla_rpvgrw.f reference/dlaqge.f reference/sgesc2.f reference/stbcon.f reference/zpstf2.f
-reference/clarrv.f reference/dlaqp2.f reference/sgesdd.f reference/stbrfs.f reference/zpstrf.f
-reference/clarscl2.f reference/dlaqps.f reference/sgesvd.f reference/stbtrs.f reference/zptcon.f
-reference/clartg.f reference/dlaqr0.f reference/sgesv.f reference/stfsm.f reference/zpteqr.f
-reference/clartv.f reference/dlaqr1.f reference/sgesvj.f reference/stftri.f reference/zptrfs.f
-reference/clarzb.f reference/dlaqr2.f reference/sgesvx.f reference/stfttp.f reference/zptsv.f
-reference/clarz.f reference/dlaqr3.f reference/sgesvxx.f reference/stfttr.f reference/zptsvx.f
-reference/clarzt.f reference/dlaqr4.f reference/sgetc2.f reference/stgevc.f reference/zpttrf.f
-reference/clascl2.f reference/dlaqr5.f reference/sgetf2.f reference/stgex2.f reference/zpttrs.f
-reference/clascl.f reference/dlaqsb.f
-reference/stgexc.f reference/zptts2.f
-reference/claset.f reference/dlaqsp.f reference/sgetri.f reference/stgsen.f reference/zrot.f
-reference/clasr.f reference/dlaqsy.f reference/stgsja.f reference/zspcon.f
-reference/classq.f reference/dlaqtr.f reference/sggbak.f reference/stgsna.f reference/zspmv.f
-reference/claswp.f reference/dlar1v.f reference/sggbal.f reference/stgsy2.f reference/zspr.f
-reference/cla_syamv.f reference/dlar2v.f reference/sgges.f reference/stgsyl.f reference/zsprfs.f
-reference/clasyf.f reference/dlarfb.f reference/sggesx.f reference/stpcon.f reference/zspsv.f
-reference/cla_syrcond_c.f reference/dlarf.f reference/sggev.f reference/stprfs.f reference/zspsvx.f
-reference/cla_syrcond_x.f reference/dlarfg.f reference/sggevx.f reference/stptri.f reference/zsptrf.f
-reference/cla_syrfsx_extended.f reference/dlarfp.f reference/sggglm.f reference/stptrs.f reference/zsptri.f
-reference/cla_syrpvgrw.f reference/dlarft.f reference/sgghrd.f reference/stpttf.f reference/zsptrs.f
-reference/clatbs.f reference/dlarfx.f reference/sgglse.f reference/stpttr.f reference/zstedc.f
-reference/clatdf.f reference/dlargv.f reference/sggqrf.f reference/strcon.f reference/zstegr.f
-reference/clatps.f reference/dlarnv.f reference/sggrqf.f reference/strevc.f reference/zstein.f
-reference/clatrd.f reference/dla_rpvgrw.f reference/sggsvd.f reference/strexc.f reference/zstemr.f
-reference/clatrs.f reference/dlarra.f reference/sggsvp.f reference/strrfs.f reference/zsteqr.f
-reference/clatrz.f reference/dlarrb.f reference/sgsvj0.f reference/strsen.f reference/zsycon.f
-reference/clatzm.f reference/dlarrc.f reference/sgsvj1.f reference/strsna.f reference/zsyequb.f
-reference/clauu2.f reference/dlarrd.f reference/sgtcon.f reference/strsyl.f reference/zsymv.f
-reference/clauum.f reference/dlarre.f reference/sgtrfs.f reference/strti2.f reference/zsyr.f
-reference/cla_wwaddw.f reference/dlarrf.f reference/sgtsv.f reference/strtri.f reference/zsyrfs.f
-reference/cpbcon.f reference/dlarrj.f reference/sgtsvx.f reference/strtrs.f reference/zsyrfsx.f
-reference/cpbequ.f reference/dlarrk.f reference/sgttrf.f reference/strttf.f reference/zsysv.f
-reference/cpbrfs.f reference/dlarrr.f reference/sgttrs.f reference/strttp.f reference/zsysvx.f
-reference/cpbstf.f reference/dlarrv.f reference/sgtts2.f reference/stzrqf.f reference/zsysvxx.f
-reference/cpbsv.f reference/dlarscl2.f reference/shgeqz.f reference/stzrzf.f reference/zsytf2.f
-reference/cpbsvx.f reference/dlartg.f reference/shsein.f reference/xerbla_array.f reference/zsytrf.f
-reference/cpbtf2.f reference/dlartv.f reference/shseqr.f reference/xerbla.f reference/zsytri.f
-reference/cpbtrf.f reference/dlaruv.f reference/sisnan.f reference/zbdsqr.f reference/zsytrs.f
-reference/cpbtrs.f reference/dlarzb.f reference/slabad.f reference/zcgesv.f reference/ztbcon.f
-reference/cpftrf.f reference/dlarz.f reference/slabrd.f reference/zcposv.f reference/ztbrfs.f
-reference/cpftri.f reference/dlarzt.f reference/slacn2.f reference/zdrscl.f reference/ztbtrs.f
-reference/cpftrs.f reference/dlas2.f reference/slacon.f reference/zgbbrd.f reference/ztfsm.f
-reference/cpocon.f reference/dlascl2.f reference/slacpy.f reference/zgbcon.f reference/ztftri.f
-reference/cpoequb.f reference/dlascl.f reference/sladiv.f reference/zgbequb.f reference/ztfttp.f
-reference/cpoequ.f reference/dlasd0.f reference/slae2.f reference/zgbequ.f reference/ztfttr.f
-reference/cporfs.f reference/dlasd1.f reference/slaebz.f reference/zgbrfs.f reference/ztgevc.f
-reference/cporfsx.f reference/dlasd2.f reference/slaed0.f reference/zgbrfsx.f reference/ztgex2.f
-reference/cposv.f reference/dlasd3.f reference/slaed1.f reference/zgbsv.f reference/ztgexc.f
-reference/cposvx.f reference/dlasd4.f reference/slaed2.f reference/zgbsvx.f reference/ztgsen.f
-reference/cposvxx.f reference/dlasd5.f reference/slaed3.f reference/zgbsvxx.f reference/ztgsja.f
-reference/cpotf2.f reference/dlasd6.f reference/slaed4.f reference/zgbtf2.f reference/ztgsna.f
-reference/dlasd7.f reference/slaed5.f reference/zgbtrf.f reference/ztgsy2.f
-reference/cpotri.f reference/dlasd8.f reference/slaed6.f reference/zgbtrs.f reference/ztgsyl.f
- reference/dlasda.f reference/slaed7.f reference/zgebak.f reference/ztpcon.f
-reference/cppcon.f reference/dlasdq.f reference/slaed8.f reference/zgebal.f reference/ztprfs.f
-reference/cppequ.f reference/dlasdt.f reference/slaed9.f reference/zgebd2.f reference/ztptri.f
-reference/cpprfs.f reference/dlaset.f reference/slaeda.f reference/zgebrd.f reference/ztptrs.f
-reference/cppsv.f reference/dlasq1.f reference/slaein.f reference/zgecon.f reference/ztpttf.f
-reference/cppsvx.f reference/dlasq2.f reference/slaev2.f reference/zgeequb.f reference/ztpttr.f
-reference/cpptrf.f reference/dlasq3.f reference/slaexc.f reference/zgeequ.f reference/ztrcon.f
-reference/cpptri.f reference/dlasq4.f reference/slag2d.f reference/zgees.f reference/ztrevc.f
-reference/cpptrs.f reference/dlasq5.f reference/slag2.f reference/zgeesx.f reference/ztrexc.f
-reference/cpstf2.f reference/dlasq6.f reference/sla_gbamv.f reference/zgeev.f reference/ztrrfs.f
-reference/cpstrf.f reference/dlasr.f reference/sla_gbrcond.f reference/zgeevx.f reference/ztrsen.f
-reference/cptcon.f reference/dlasrt.f reference/sla_gbrfsx_extended.f reference/zgegs.f reference/ztrsna.f
-reference/cpteqr.f reference/dlassq.f reference/sla_gbrpvgrw.f reference/zgegv.f reference/ztrsyl.f
-reference/cptrfs.f reference/dlasv2.f reference/sla_geamv.f reference/zgehd2.f reference/ztrti2.f
-reference/cptsv.f reference/dlaswp.f reference/sla_gercond.f reference/zgehrd.f reference/ztrtri.f
-reference/cptsvx.f reference/dlasy2.f reference/sla_gerfsx_extended.f reference/zgelq2.f reference/ztrtrs.f
-reference/cpttrf.f reference/dla_syamv.f reference/slags2.f reference/zgelqf.f reference/ztrttf.f
-reference/cpttrs.f reference/dlasyf.f reference/slagtf.f reference/zgelsd.f reference/ztrttp.f
-reference/cptts2.f reference/dla_syrcond.f reference/slagtm.f reference/zgels.f reference/ztzrqf.f
-reference/crot.f reference/dla_syrfsx_extended.f reference/slagts.f reference/zgelss.f reference/ztzrzf.f
-reference/cspcon.f reference/dla_syrpvgrw.f reference/slagv2.f reference/zgelsx.f reference/zung2l.f
-reference/cspmv.f reference/dlat2s.f reference/slahqr.f reference/zgelsy.f reference/zung2r.f
-reference/cspr.f reference/dlatbs.f reference/slahr2.f reference/zgeql2.f reference/zungbr.f
-reference/csprfs.f reference/dlatdf.f reference/slahrd.f reference/zgeqlf.f reference/zunghr.f
-reference/cspsv.f reference/dlatps.f reference/slaic1.f reference/zgeqp3.f reference/zungl2.f
-reference/cspsvx.f reference/dlatrd.f reference/slaisnan.f reference/zgeqpf.f reference/zunglq.f
-reference/csptrf.f reference/dlatrs.f reference/sla_lin_berr.f reference/zgeqr2.f reference/zungql.f
-reference/csptri.f reference/dlatrz.f reference/slaln2.f reference/zgeqrf.f reference/zungqr.f
-reference/csptrs.f reference/dlatzm.f reference/slals0.f reference/zgerfs.f reference/zungr2.f
-reference/csrscl.f reference/dlauu2.f reference/slalsa.f reference/zgerfsx.f reference/zungrq.f
-reference/cstedc.f reference/dlauum.f reference/slalsd.f reference/zgerq2.f reference/zungtr.f
-reference/cstegr.f reference/dla_wwaddw.f reference/slamrg.f reference/zgerqf.f reference/zunm2l.f
-reference/cstein.f reference/dopgtr.f reference/slaneg.f reference/zgesc2.f reference/zunm2r.f
-reference/cstemr.f reference/dopmtr.f reference/slangb.f reference/zgesdd.f reference/zunmbr.f
-reference/csteqr.f reference/dorg2l.f reference/slange.f reference/zgesvd.f reference/zunmhr.f
-reference/csycon.f reference/dorg2r.f reference/slangt.f reference/zgesv.f reference/zunml2.f
-reference/csyequb.f reference/dorgbr.f reference/slanhs.f reference/zgesvx.f reference/zunmlq.f
-reference/csymv.f reference/dorghr.f reference/slansb.f reference/zgesvxx.f reference/zunmql.f
-reference/csyr.f reference/dorgl2.f reference/slansf.f reference/zgetc2.f reference/zunmqr.f
-reference/csyrfs.f reference/dorglq.f reference/slansp.f reference/zgetf2.f reference/zunmr2.f
-reference/csyrfsx.f reference/dorgql.f reference/slanst.f
-reference/zunmr3.f
-reference/csysv.f reference/dorgqr.f reference/slansy.f reference/zgetri.f reference/zunmrq.f
-reference/csysvx.f reference/dorgr2.f reference/slantb.f reference/zunmrz.f
-reference/csysvxx.f reference/dorgrq.f reference/slantp.f reference/zggbak.f reference/zunmtr.f
-reference/csytf2.f reference/dorgtr.f reference/slantr.f reference/zggbal.f reference/zupgtr.f
-reference/csytrf.f reference/dorm2l.f reference/slanv2.f reference/zgges.f reference/zupmtr.f
-reference/csytri.f reference/dorm2r.f reference/slapll.f reference/zggesx.f
-reference/csytrs.f reference/dormbr.f reference/slapmt.f reference/zggev.f
-reference/ctbcon.f reference/dormhr.f reference/sla_porcond.f reference/zggevx.f
+set(EigenLapack_SRCS ${EigenLapack_SRCS}
+ slarft.f dlarft.f clarft.f zlarft.f
+ slarfb.f dlarfb.f clarfb.f zlarfb.f
+ slarfg.f dlarfg.f clarfg.f zlarfg.f
+ slarf.f dlarf.f clarf.f zlarf.f
+ sladiv.f dladiv.f cladiv.f zladiv.f
+ ilaslr.f iladlr.f ilaclr.f ilazlr.f
+ ilaslc.f iladlc.f ilaclc.f ilazlc.f
+ dlapy2.f dlapy3.f slapy2.f slapy3.f
+ clacgv.f zlacgv.f
+ slamch.f dlamch.f
+ second_NONE.f dsecnd_NONE.f
)
-endif()
+
+option(EIGEN_ENABLE_LAPACK_TESTS OFF "Enbale the Lapack unit tests")
+
+if(EIGEN_ENABLE_LAPACK_TESTS)
+
+ get_filename_component(eigen_full_path_to_reference_lapack "./reference/" ABSOLUTE)
+ if(NOT EXISTS ${eigen_full_path_to_reference_lapack})
+ # Download lapack and install sources and testing at the right place
+ message(STATUS "Download lapack_addons_3.4.1.tgz...")
+
+ file(DOWNLOAD "http://downloads.tuxfamily.org/eigen/lapack_addons_3.4.1.tgz"
+ "${CMAKE_CURRENT_SOURCE_DIR}/lapack_addons_3.4.1.tgz"
+ INACTIVITY_TIMEOUT 15
+ TIMEOUT 240
+ STATUS download_status
+ EXPECTED_MD5 5758ce55afcf79da98de8b9de1615ad5
+ SHOW_PROGRESS)
+
+ message(STATUS ${download_status})
+ list(GET download_status 0 download_status_num)
+ set(download_status_num 0)
+ if(download_status_num EQUAL 0)
+ message(STATUS "Setup lapack reference and lapack unit tests")
+ execute_process(COMMAND tar xzf "lapack_addons_3.4.1.tgz" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+ else()
+ message(STATUS "Download of lapack_addons_3.4.1.tgz failed, LAPACK unit tests wont be enabled")
+ set(EIGEN_ENABLE_LAPACK_TESTS false)
+ endif()
+
+ endif()
+
+ get_filename_component(eigen_full_path_to_reference_lapack "./reference/" ABSOLUTE)
+ if(EXISTS ${eigen_full_path_to_reference_lapack})
+ set(EigenLapack_funcfilenames
+ ssyev.f dsyev.f csyev.f zsyev.f
+ spotrf.f dpotrf.f cpotrf.f zpotrf.f
+ spotrs.f dpotrs.f cpotrs.f zpotrs.f
+ sgetrf.f dgetrf.f cgetrf.f zgetrf.f
+ sgetrs.f dgetrs.f cgetrs.f zgetrs.f)
+
+ FILE(GLOB ReferenceLapack_SRCS0 RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "reference/*.f")
+ foreach(filename1 IN LISTS ReferenceLapack_SRCS0)
+ string(REPLACE "reference/" "" filename ${filename1})
+ list(FIND EigenLapack_SRCS ${filename} id1)
+ list(FIND EigenLapack_funcfilenames ${filename} id2)
+ if((id1 EQUAL -1) AND (id2 EQUAL -1))
+ set(ReferenceLapack_SRCS ${ReferenceLapack_SRCS} reference/${filename})
+ endif()
+ endforeach()
+ endif()
+
+
+endif(EIGEN_ENABLE_LAPACK_TESTS)
endif(EIGEN_Fortran_COMPILER_WORKS)
-add_library(eigen_lapack_static ${EigenLapack_SRCS})
+add_library(eigen_lapack_static ${EigenLapack_SRCS} ${ReferenceLapack_SRCS})
add_library(eigen_lapack SHARED ${EigenLapack_SRCS})
+target_link_libraries(eigen_lapack eigen_blas)
+
if(EIGEN_STANDARD_LIBRARIES_TO_LINK_TO)
target_link_libraries(eigen_lapack_static ${EIGEN_STANDARD_LIBRARIES_TO_LINK_TO})
target_link_libraries(eigen_lapack ${EIGEN_STANDARD_LIBRARIES_TO_LINK_TO})
@@ -370,5 +107,343 @@ install(TARGETS eigen_lapack eigen_lapack_static
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)
-# add_subdirectory(testing)
+
+
+get_filename_component(eigen_full_path_to_testing_lapack "./testing/" ABSOLUTE)
+if(EXISTS ${eigen_full_path_to_testing_lapack})
+
+ # The following comes from lapack/TESTING/CMakeLists.txt
+ # Get Python
+ find_package(PythonInterp)
+ message(STATUS "Looking for Python found - ${PYTHONINTERP_FOUND}")
+ if (PYTHONINTERP_FOUND)
+ message(STATUS "Using Python version ${PYTHON_VERSION_STRING}")
+ endif()
+
+ set(LAPACK_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+ set(LAPACK_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
+ set(BUILD_SINGLE true)
+ set(BUILD_DOUBLE true)
+ set(BUILD_COMPLEX true)
+ set(BUILD_COMPLEX16E true)
+
+ if(MSVC_VERSION)
+# string(REPLACE "/STACK:10000000" "/STACK:900000000000000000"
+# CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
+ string(REGEX REPLACE "(.*)/STACK:(.*) (.*)" "\\1/STACK:900000000000000000 \\3"
+ CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
+ endif()
+ add_subdirectory(testing/MATGEN)
+ add_subdirectory(testing/LIN)
+ add_subdirectory(testing/EIG)
+ macro(add_lapack_test output input target)
+ set(TEST_INPUT "${LAPACK_SOURCE_DIR}/testing/${input}")
+ set(TEST_OUTPUT "${LAPACK_BINARY_DIR}/testing/${output}")
+ get_target_property(TEST_LOC ${target} LOCATION)
+ string(REPLACE "." "_" input_name ${input})
+ set(testName "${target}_${input_name}")
+ if(EXISTS "${TEST_INPUT}")
+ add_test(LAPACK-${testName} "${CMAKE_COMMAND}"
+ -DTEST=${TEST_LOC}
+ -DINPUT=${TEST_INPUT}
+ -DOUTPUT=${TEST_OUTPUT}
+ -DINTDIR=${CMAKE_CFG_INTDIR}
+ -P "${LAPACK_SOURCE_DIR}/testing/runtest.cmake")
+ endif()
+ endmacro(add_lapack_test)
+
+ if (BUILD_SINGLE)
+ add_lapack_test(stest.out stest.in xlintsts)
+ #
+ # ======== SINGLE RFP LIN TESTS ========================
+ add_lapack_test(stest_rfp.out stest_rfp.in xlintstrfs)
+ #
+ #
+ # ======== SINGLE EIG TESTS ===========================
+ #
+
+ add_lapack_test(snep.out nep.in xeigtsts)
+
+
+ add_lapack_test(ssep.out sep.in xeigtsts)
+
+
+ add_lapack_test(ssvd.out svd.in xeigtsts)
+
+
+ add_lapack_test(sec.out sec.in xeigtsts)
+
+
+ add_lapack_test(sed.out sed.in xeigtsts)
+
+
+ add_lapack_test(sgg.out sgg.in xeigtsts)
+
+
+ add_lapack_test(sgd.out sgd.in xeigtsts)
+
+
+ add_lapack_test(ssb.out ssb.in xeigtsts)
+
+
+ add_lapack_test(ssg.out ssg.in xeigtsts)
+
+
+ add_lapack_test(sbal.out sbal.in xeigtsts)
+
+
+ add_lapack_test(sbak.out sbak.in xeigtsts)
+
+
+ add_lapack_test(sgbal.out sgbal.in xeigtsts)
+
+
+ add_lapack_test(sgbak.out sgbak.in xeigtsts)
+
+
+ add_lapack_test(sbb.out sbb.in xeigtsts)
+
+
+ add_lapack_test(sglm.out glm.in xeigtsts)
+
+
+ add_lapack_test(sgqr.out gqr.in xeigtsts)
+
+
+ add_lapack_test(sgsv.out gsv.in xeigtsts)
+
+
+ add_lapack_test(scsd.out csd.in xeigtsts)
+
+
+ add_lapack_test(slse.out lse.in xeigtsts)
+ endif()
+
+ if (BUILD_DOUBLE)
+ #
+ # ======== DOUBLE LIN TESTS ===========================
+ add_lapack_test(dtest.out dtest.in xlintstd)
+ #
+ # ======== DOUBLE RFP LIN TESTS ========================
+ add_lapack_test(dtest_rfp.out dtest_rfp.in xlintstrfd)
+ #
+ # ======== DOUBLE EIG TESTS ===========================
+
+ add_lapack_test(dnep.out nep.in xeigtstd)
+
+
+ add_lapack_test(dsep.out sep.in xeigtstd)
+
+
+ add_lapack_test(dsvd.out svd.in xeigtstd)
+
+
+ add_lapack_test(dec.out dec.in xeigtstd)
+
+
+ add_lapack_test(ded.out ded.in xeigtstd)
+
+
+ add_lapack_test(dgg.out dgg.in xeigtstd)
+
+
+ add_lapack_test(dgd.out dgd.in xeigtstd)
+
+
+ add_lapack_test(dsb.out dsb.in xeigtstd)
+
+
+ add_lapack_test(dsg.out dsg.in xeigtstd)
+
+
+ add_lapack_test(dbal.out dbal.in xeigtstd)
+
+
+ add_lapack_test(dbak.out dbak.in xeigtstd)
+
+
+ add_lapack_test(dgbal.out dgbal.in xeigtstd)
+
+
+ add_lapack_test(dgbak.out dgbak.in xeigtstd)
+
+
+ add_lapack_test(dbb.out dbb.in xeigtstd)
+
+
+ add_lapack_test(dglm.out glm.in xeigtstd)
+
+
+ add_lapack_test(dgqr.out gqr.in xeigtstd)
+
+
+ add_lapack_test(dgsv.out gsv.in xeigtstd)
+
+
+ add_lapack_test(dcsd.out csd.in xeigtstd)
+
+
+ add_lapack_test(dlse.out lse.in xeigtstd)
+ endif()
+
+ if (BUILD_COMPLEX)
+ add_lapack_test(ctest.out ctest.in xlintstc)
+ #
+ # ======== COMPLEX RFP LIN TESTS ========================
+ add_lapack_test(ctest_rfp.out ctest_rfp.in xlintstrfc)
+ #
+ # ======== COMPLEX EIG TESTS ===========================
+
+ add_lapack_test(cnep.out nep.in xeigtstc)
+
+
+ add_lapack_test(csep.out sep.in xeigtstc)
+
+
+ add_lapack_test(csvd.out svd.in xeigtstc)
+
+
+ add_lapack_test(cec.out cec.in xeigtstc)
+
+
+ add_lapack_test(ced.out ced.in xeigtstc)
+
+
+ add_lapack_test(cgg.out cgg.in xeigtstc)
+
+
+ add_lapack_test(cgd.out cgd.in xeigtstc)
+
+
+ add_lapack_test(csb.out csb.in xeigtstc)
+
+
+ add_lapack_test(csg.out csg.in xeigtstc)
+
+
+ add_lapack_test(cbal.out cbal.in xeigtstc)
+
+
+ add_lapack_test(cbak.out cbak.in xeigtstc)
+
+
+ add_lapack_test(cgbal.out cgbal.in xeigtstc)
+
+
+ add_lapack_test(cgbak.out cgbak.in xeigtstc)
+
+
+ add_lapack_test(cbb.out cbb.in xeigtstc)
+
+
+ add_lapack_test(cglm.out glm.in xeigtstc)
+
+
+ add_lapack_test(cgqr.out gqr.in xeigtstc)
+
+
+ add_lapack_test(cgsv.out gsv.in xeigtstc)
+
+
+ add_lapack_test(ccsd.out csd.in xeigtstc)
+
+
+ add_lapack_test(clse.out lse.in xeigtstc)
+ endif()
+
+ if (BUILD_COMPLEX16)
+ #
+ # ======== COMPLEX16 LIN TESTS ========================
+ add_lapack_test(ztest.out ztest.in xlintstz)
+ #
+ # ======== COMPLEX16 RFP LIN TESTS ========================
+ add_lapack_test(ztest_rfp.out ztest_rfp.in xlintstrfz)
+ #
+ # ======== COMPLEX16 EIG TESTS ===========================
+
+ add_lapack_test(znep.out nep.in xeigtstz)
+
+
+ add_lapack_test(zsep.out sep.in xeigtstz)
+
+
+ add_lapack_test(zsvd.out svd.in xeigtstz)
+
+
+ add_lapack_test(zec.out zec.in xeigtstz)
+
+
+ add_lapack_test(zed.out zed.in xeigtstz)
+
+
+ add_lapack_test(zgg.out zgg.in xeigtstz)
+
+
+ add_lapack_test(zgd.out zgd.in xeigtstz)
+
+
+ add_lapack_test(zsb.out zsb.in xeigtstz)
+
+
+ add_lapack_test(zsg.out zsg.in xeigtstz)
+
+
+ add_lapack_test(zbal.out zbal.in xeigtstz)
+
+
+ add_lapack_test(zbak.out zbak.in xeigtstz)
+
+
+ add_lapack_test(zgbal.out zgbal.in xeigtstz)
+
+
+ add_lapack_test(zgbak.out zgbak.in xeigtstz)
+
+
+ add_lapack_test(zbb.out zbb.in xeigtstz)
+
+
+ add_lapack_test(zglm.out glm.in xeigtstz)
+
+
+ add_lapack_test(zgqr.out gqr.in xeigtstz)
+
+
+ add_lapack_test(zgsv.out gsv.in xeigtstz)
+
+
+ add_lapack_test(zcsd.out csd.in xeigtstz)
+
+
+ add_lapack_test(zlse.out lse.in xeigtstz)
+ endif()
+
+
+ if (BUILD_SIMPLE)
+ if (BUILD_DOUBLE)
+ #
+ # ======== SINGLE-DOUBLE PROTO LIN TESTS ==============
+ add_lapack_test(dstest.out dstest.in xlintstds)
+ endif()
+ endif()
+
+
+ if (BUILD_COMPLEX)
+ if (BUILD_COMPLEX16)
+ #
+ # ======== COMPLEX-COMPLEX16 LIN TESTS ========================
+ add_lapack_test(zctest.out zctest.in xlintstzc)
+ endif()
+ endif()
+
+ # ==============================================================================
+
+ execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${LAPACK_SOURCE_DIR}/testing/lapack_testing.py ${LAPACK_BINARY_DIR})
+ add_test(
+ NAME LAPACK_Test_Summary
+ WORKING_DIRECTORY ${LAPACK_BINARY_DIR}
+ COMMAND ${PYTHON_EXECUTABLE} "lapack_testing.py"
+ )
+
+endif()
diff --git a/lapack/cholesky.cpp b/lapack/cholesky.cpp
index 604fa437a..ea3bc123b 100644
--- a/lapack/cholesky.cpp
+++ b/lapack/cholesky.cpp
@@ -26,8 +26,8 @@ EIGEN_LAPACK_FUNC(potrf,(char* uplo, int *n, RealScalar *pa, int *lda, int *info
Scalar* a = reinterpret_cast<Scalar*>(pa);
MatrixType A(a,*n,*n,*lda);
int ret;
- if(UPLO(*uplo)==UP) ret = internal::llt_inplace<Scalar, Upper>::blocked(A);
- else ret = internal::llt_inplace<Scalar, Lower>::blocked(A);
+ if(UPLO(*uplo)==UP) ret = int(internal::llt_inplace<Scalar, Upper>::blocked(A));
+ else ret = int(internal::llt_inplace<Scalar, Lower>::blocked(A));
if(ret>=0)
*info = ret+1;
diff --git a/lapack/clacgv.f b/lapack/clacgv.f
new file mode 100644
index 000000000..359eb07f3
--- /dev/null
+++ b/lapack/clacgv.f
@@ -0,0 +1,116 @@
+*> \brief \b CLACGV
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download CLACGV + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/clacgv.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/clacgv.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clacgv.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE CLACGV( N, X, INCX )
+*
+* .. Scalar Arguments ..
+* INTEGER INCX, N
+* ..
+* .. Array Arguments ..
+* COMPLEX X( * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> CLACGV conjugates a complex vector of length N.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The length of the vector X. N >= 0.
+*> \endverbatim
+*>
+*> \param[in,out] X
+*> \verbatim
+*> X is COMPLEX array, dimension
+*> (1+(N-1)*abs(INCX))
+*> On entry, the vector of length N to be conjugated.
+*> On exit, X is overwritten with conjg(X).
+*> \endverbatim
+*>
+*> \param[in] INCX
+*> \verbatim
+*> INCX is INTEGER
+*> The spacing between successive elements of X.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup complexOTHERauxiliary
+*
+* =====================================================================
+ SUBROUTINE CLACGV( N, X, INCX )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ INTEGER INCX, N
+* ..
+* .. Array Arguments ..
+ COMPLEX X( * )
+* ..
+*
+* =====================================================================
+*
+* .. Local Scalars ..
+ INTEGER I, IOFF
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC CONJG
+* ..
+* .. Executable Statements ..
+*
+ IF( INCX.EQ.1 ) THEN
+ DO 10 I = 1, N
+ X( I ) = CONJG( X( I ) )
+ 10 CONTINUE
+ ELSE
+ IOFF = 1
+ IF( INCX.LT.0 )
+ $ IOFF = 1 - ( N-1 )*INCX
+ DO 20 I = 1, N
+ X( IOFF ) = CONJG( X( IOFF ) )
+ IOFF = IOFF + INCX
+ 20 CONTINUE
+ END IF
+ RETURN
+*
+* End of CLACGV
+*
+ END
diff --git a/lapack/cladiv.f b/lapack/cladiv.f
new file mode 100644
index 000000000..2807ac5fc
--- /dev/null
+++ b/lapack/cladiv.f
@@ -0,0 +1,97 @@
+*> \brief \b CLADIV
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download CLADIV + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/cladiv.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/cladiv.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cladiv.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* COMPLEX FUNCTION CLADIV( X, Y )
+*
+* .. Scalar Arguments ..
+* COMPLEX X, Y
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> CLADIV := X / Y, where X and Y are complex. The computation of X / Y
+*> will not overflow on an intermediary step unless the results
+*> overflows.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] X
+*> \verbatim
+*> X is COMPLEX
+*> \endverbatim
+*>
+*> \param[in] Y
+*> \verbatim
+*> Y is COMPLEX
+*> The complex scalars X and Y.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup complexOTHERauxiliary
+*
+* =====================================================================
+ COMPLEX FUNCTION CLADIV( X, Y )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ COMPLEX X, Y
+* ..
+*
+* =====================================================================
+*
+* .. Local Scalars ..
+ REAL ZI, ZR
+* ..
+* .. External Subroutines ..
+ EXTERNAL SLADIV
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC AIMAG, CMPLX, REAL
+* ..
+* .. Executable Statements ..
+*
+ CALL SLADIV( REAL( X ), AIMAG( X ), REAL( Y ), AIMAG( Y ), ZR,
+ $ ZI )
+ CLADIV = CMPLX( ZR, ZI )
+*
+ RETURN
+*
+* End of CLADIV
+*
+ END
diff --git a/lapack/clarf.f b/lapack/clarf.f
new file mode 100644
index 000000000..ca0328fb5
--- /dev/null
+++ b/lapack/clarf.f
@@ -0,0 +1,232 @@
+*> \brief \b CLARF
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download CLARF + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/clarf.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/clarf.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clarf.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE CLARF( SIDE, M, N, V, INCV, TAU, C, LDC, WORK )
+*
+* .. Scalar Arguments ..
+* CHARACTER SIDE
+* INTEGER INCV, LDC, M, N
+* COMPLEX TAU
+* ..
+* .. Array Arguments ..
+* COMPLEX C( LDC, * ), V( * ), WORK( * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> CLARF applies a complex elementary reflector H to a complex M-by-N
+*> matrix C, from either the left or the right. H is represented in the
+*> form
+*>
+*> H = I - tau * v * v**H
+*>
+*> where tau is a complex scalar and v is a complex vector.
+*>
+*> If tau = 0, then H is taken to be the unit matrix.
+*>
+*> To apply H**H (the conjugate transpose of H), supply conjg(tau) instead
+*> tau.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] SIDE
+*> \verbatim
+*> SIDE is CHARACTER*1
+*> = 'L': form H * C
+*> = 'R': form C * H
+*> \endverbatim
+*>
+*> \param[in] M
+*> \verbatim
+*> M is INTEGER
+*> The number of rows of the matrix C.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The number of columns of the matrix C.
+*> \endverbatim
+*>
+*> \param[in] V
+*> \verbatim
+*> V is COMPLEX array, dimension
+*> (1 + (M-1)*abs(INCV)) if SIDE = 'L'
+*> or (1 + (N-1)*abs(INCV)) if SIDE = 'R'
+*> The vector v in the representation of H. V is not used if
+*> TAU = 0.
+*> \endverbatim
+*>
+*> \param[in] INCV
+*> \verbatim
+*> INCV is INTEGER
+*> The increment between elements of v. INCV <> 0.
+*> \endverbatim
+*>
+*> \param[in] TAU
+*> \verbatim
+*> TAU is COMPLEX
+*> The value tau in the representation of H.
+*> \endverbatim
+*>
+*> \param[in,out] C
+*> \verbatim
+*> C is COMPLEX array, dimension (LDC,N)
+*> On entry, the M-by-N matrix C.
+*> On exit, C is overwritten by the matrix H * C if SIDE = 'L',
+*> or C * H if SIDE = 'R'.
+*> \endverbatim
+*>
+*> \param[in] LDC
+*> \verbatim
+*> LDC is INTEGER
+*> The leading dimension of the array C. LDC >= max(1,M).
+*> \endverbatim
+*>
+*> \param[out] WORK
+*> \verbatim
+*> WORK is COMPLEX array, dimension
+*> (N) if SIDE = 'L'
+*> or (M) if SIDE = 'R'
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup complexOTHERauxiliary
+*
+* =====================================================================
+ SUBROUTINE CLARF( SIDE, M, N, V, INCV, TAU, C, LDC, WORK )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ CHARACTER SIDE
+ INTEGER INCV, LDC, M, N
+ COMPLEX TAU
+* ..
+* .. Array Arguments ..
+ COMPLEX C( LDC, * ), V( * ), WORK( * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ COMPLEX ONE, ZERO
+ PARAMETER ( ONE = ( 1.0E+0, 0.0E+0 ),
+ $ ZERO = ( 0.0E+0, 0.0E+0 ) )
+* ..
+* .. Local Scalars ..
+ LOGICAL APPLYLEFT
+ INTEGER I, LASTV, LASTC
+* ..
+* .. External Subroutines ..
+ EXTERNAL CGEMV, CGERC
+* ..
+* .. External Functions ..
+ LOGICAL LSAME
+ INTEGER ILACLR, ILACLC
+ EXTERNAL LSAME, ILACLR, ILACLC
+* ..
+* .. Executable Statements ..
+*
+ APPLYLEFT = LSAME( SIDE, 'L' )
+ LASTV = 0
+ LASTC = 0
+ IF( TAU.NE.ZERO ) THEN
+! Set up variables for scanning V. LASTV begins pointing to the end
+! of V.
+ IF( APPLYLEFT ) THEN
+ LASTV = M
+ ELSE
+ LASTV = N
+ END IF
+ IF( INCV.GT.0 ) THEN
+ I = 1 + (LASTV-1) * INCV
+ ELSE
+ I = 1
+ END IF
+! Look for the last non-zero row in V.
+ DO WHILE( LASTV.GT.0 .AND. V( I ).EQ.ZERO )
+ LASTV = LASTV - 1
+ I = I - INCV
+ END DO
+ IF( APPLYLEFT ) THEN
+! Scan for the last non-zero column in C(1:lastv,:).
+ LASTC = ILACLC(LASTV, N, C, LDC)
+ ELSE
+! Scan for the last non-zero row in C(:,1:lastv).
+ LASTC = ILACLR(M, LASTV, C, LDC)
+ END IF
+ END IF
+! Note that lastc.eq.0 renders the BLAS operations null; no special
+! case is needed at this level.
+ IF( APPLYLEFT ) THEN
+*
+* Form H * C
+*
+ IF( LASTV.GT.0 ) THEN
+*
+* w(1:lastc,1) := C(1:lastv,1:lastc)**H * v(1:lastv,1)
+*
+ CALL CGEMV( 'Conjugate transpose', LASTV, LASTC, ONE,
+ $ C, LDC, V, INCV, ZERO, WORK, 1 )
+*
+* C(1:lastv,1:lastc) := C(...) - v(1:lastv,1) * w(1:lastc,1)**H
+*
+ CALL CGERC( LASTV, LASTC, -TAU, V, INCV, WORK, 1, C, LDC )
+ END IF
+ ELSE
+*
+* Form C * H
+*
+ IF( LASTV.GT.0 ) THEN
+*
+* w(1:lastc,1) := C(1:lastc,1:lastv) * v(1:lastv,1)
+*
+ CALL CGEMV( 'No transpose', LASTC, LASTV, ONE, C, LDC,
+ $ V, INCV, ZERO, WORK, 1 )
+*
+* C(1:lastc,1:lastv) := C(...) - w(1:lastc,1) * v(1:lastv,1)**H
+*
+ CALL CGERC( LASTC, LASTV, -TAU, WORK, 1, V, INCV, C, LDC )
+ END IF
+ END IF
+ RETURN
+*
+* End of CLARF
+*
+ END
diff --git a/lapack/clarfb.f b/lapack/clarfb.f
new file mode 100644
index 000000000..40bbdf487
--- /dev/null
+++ b/lapack/clarfb.f
@@ -0,0 +1,771 @@
+*> \brief \b CLARFB
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download CLARFB + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/clarfb.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/clarfb.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clarfb.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE CLARFB( SIDE, TRANS, DIRECT, STOREV, M, N, K, V, LDV,
+* T, LDT, C, LDC, WORK, LDWORK )
+*
+* .. Scalar Arguments ..
+* CHARACTER DIRECT, SIDE, STOREV, TRANS
+* INTEGER K, LDC, LDT, LDV, LDWORK, M, N
+* ..
+* .. Array Arguments ..
+* COMPLEX C( LDC, * ), T( LDT, * ), V( LDV, * ),
+* $ WORK( LDWORK, * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> CLARFB applies a complex block reflector H or its transpose H**H to a
+*> complex M-by-N matrix C, from either the left or the right.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] SIDE
+*> \verbatim
+*> SIDE is CHARACTER*1
+*> = 'L': apply H or H**H from the Left
+*> = 'R': apply H or H**H from the Right
+*> \endverbatim
+*>
+*> \param[in] TRANS
+*> \verbatim
+*> TRANS is CHARACTER*1
+*> = 'N': apply H (No transpose)
+*> = 'C': apply H**H (Conjugate transpose)
+*> \endverbatim
+*>
+*> \param[in] DIRECT
+*> \verbatim
+*> DIRECT is CHARACTER*1
+*> Indicates how H is formed from a product of elementary
+*> reflectors
+*> = 'F': H = H(1) H(2) . . . H(k) (Forward)
+*> = 'B': H = H(k) . . . H(2) H(1) (Backward)
+*> \endverbatim
+*>
+*> \param[in] STOREV
+*> \verbatim
+*> STOREV is CHARACTER*1
+*> Indicates how the vectors which define the elementary
+*> reflectors are stored:
+*> = 'C': Columnwise
+*> = 'R': Rowwise
+*> \endverbatim
+*>
+*> \param[in] M
+*> \verbatim
+*> M is INTEGER
+*> The number of rows of the matrix C.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The number of columns of the matrix C.
+*> \endverbatim
+*>
+*> \param[in] K
+*> \verbatim
+*> K is INTEGER
+*> The order of the matrix T (= the number of elementary
+*> reflectors whose product defines the block reflector).
+*> \endverbatim
+*>
+*> \param[in] V
+*> \verbatim
+*> V is COMPLEX array, dimension
+*> (LDV,K) if STOREV = 'C'
+*> (LDV,M) if STOREV = 'R' and SIDE = 'L'
+*> (LDV,N) if STOREV = 'R' and SIDE = 'R'
+*> The matrix V. See Further Details.
+*> \endverbatim
+*>
+*> \param[in] LDV
+*> \verbatim
+*> LDV is INTEGER
+*> The leading dimension of the array V.
+*> If STOREV = 'C' and SIDE = 'L', LDV >= max(1,M);
+*> if STOREV = 'C' and SIDE = 'R', LDV >= max(1,N);
+*> if STOREV = 'R', LDV >= K.
+*> \endverbatim
+*>
+*> \param[in] T
+*> \verbatim
+*> T is COMPLEX array, dimension (LDT,K)
+*> The triangular K-by-K matrix T in the representation of the
+*> block reflector.
+*> \endverbatim
+*>
+*> \param[in] LDT
+*> \verbatim
+*> LDT is INTEGER
+*> The leading dimension of the array T. LDT >= K.
+*> \endverbatim
+*>
+*> \param[in,out] C
+*> \verbatim
+*> C is COMPLEX array, dimension (LDC,N)
+*> On entry, the M-by-N matrix C.
+*> On exit, C is overwritten by H*C or H**H*C or C*H or C*H**H.
+*> \endverbatim
+*>
+*> \param[in] LDC
+*> \verbatim
+*> LDC is INTEGER
+*> The leading dimension of the array C. LDC >= max(1,M).
+*> \endverbatim
+*>
+*> \param[out] WORK
+*> \verbatim
+*> WORK is COMPLEX array, dimension (LDWORK,K)
+*> \endverbatim
+*>
+*> \param[in] LDWORK
+*> \verbatim
+*> LDWORK is INTEGER
+*> The leading dimension of the array WORK.
+*> If SIDE = 'L', LDWORK >= max(1,N);
+*> if SIDE = 'R', LDWORK >= max(1,M).
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup complexOTHERauxiliary
+*
+*> \par Further Details:
+* =====================
+*>
+*> \verbatim
+*>
+*> The shape of the matrix V and the storage of the vectors which define
+*> the H(i) is best illustrated by the following example with n = 5 and
+*> k = 3. The elements equal to 1 are not stored; the corresponding
+*> array elements are modified but restored on exit. The rest of the
+*> array is not used.
+*>
+*> DIRECT = 'F' and STOREV = 'C': DIRECT = 'F' and STOREV = 'R':
+*>
+*> V = ( 1 ) V = ( 1 v1 v1 v1 v1 )
+*> ( v1 1 ) ( 1 v2 v2 v2 )
+*> ( v1 v2 1 ) ( 1 v3 v3 )
+*> ( v1 v2 v3 )
+*> ( v1 v2 v3 )
+*>
+*> DIRECT = 'B' and STOREV = 'C': DIRECT = 'B' and STOREV = 'R':
+*>
+*> V = ( v1 v2 v3 ) V = ( v1 v1 1 )
+*> ( v1 v2 v3 ) ( v2 v2 v2 1 )
+*> ( 1 v2 v3 ) ( v3 v3 v3 v3 1 )
+*> ( 1 v3 )
+*> ( 1 )
+*> \endverbatim
+*>
+* =====================================================================
+ SUBROUTINE CLARFB( SIDE, TRANS, DIRECT, STOREV, M, N, K, V, LDV,
+ $ T, LDT, C, LDC, WORK, LDWORK )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ CHARACTER DIRECT, SIDE, STOREV, TRANS
+ INTEGER K, LDC, LDT, LDV, LDWORK, M, N
+* ..
+* .. Array Arguments ..
+ COMPLEX C( LDC, * ), T( LDT, * ), V( LDV, * ),
+ $ WORK( LDWORK, * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ COMPLEX ONE
+ PARAMETER ( ONE = ( 1.0E+0, 0.0E+0 ) )
+* ..
+* .. Local Scalars ..
+ CHARACTER TRANST
+ INTEGER I, J, LASTV, LASTC
+* ..
+* .. External Functions ..
+ LOGICAL LSAME
+ INTEGER ILACLR, ILACLC
+ EXTERNAL LSAME, ILACLR, ILACLC
+* ..
+* .. External Subroutines ..
+ EXTERNAL CCOPY, CGEMM, CLACGV, CTRMM
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC CONJG
+* ..
+* .. Executable Statements ..
+*
+* Quick return if possible
+*
+ IF( M.LE.0 .OR. N.LE.0 )
+ $ RETURN
+*
+ IF( LSAME( TRANS, 'N' ) ) THEN
+ TRANST = 'C'
+ ELSE
+ TRANST = 'N'
+ END IF
+*
+ IF( LSAME( STOREV, 'C' ) ) THEN
+*
+ IF( LSAME( DIRECT, 'F' ) ) THEN
+*
+* Let V = ( V1 ) (first K rows)
+* ( V2 )
+* where V1 is unit lower triangular.
+*
+ IF( LSAME( SIDE, 'L' ) ) THEN
+*
+* Form H * C or H**H * C where C = ( C1 )
+* ( C2 )
+*
+ LASTV = MAX( K, ILACLR( M, K, V, LDV ) )
+ LASTC = ILACLC( LASTV, N, C, LDC )
+*
+* W := C**H * V = (C1**H * V1 + C2**H * V2) (stored in WORK)
+*
+* W := C1**H
+*
+ DO 10 J = 1, K
+ CALL CCOPY( LASTC, C( J, 1 ), LDC, WORK( 1, J ), 1 )
+ CALL CLACGV( LASTC, WORK( 1, J ), 1 )
+ 10 CONTINUE
+*
+* W := W * V1
+*
+ CALL CTRMM( 'Right', 'Lower', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C2**H *V2
+*
+ CALL CGEMM( 'Conjugate transpose', 'No transpose',
+ $ LASTC, K, LASTV-K, ONE, C( K+1, 1 ), LDC,
+ $ V( K+1, 1 ), LDV, ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T**H or W * T
+*
+ CALL CTRMM( 'Right', 'Upper', TRANST, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - V * W**H
+*
+ IF( M.GT.K ) THEN
+*
+* C2 := C2 - V2 * W**H
+*
+ CALL CGEMM( 'No transpose', 'Conjugate transpose',
+ $ LASTV-K, LASTC, K, -ONE, V( K+1, 1 ), LDV,
+ $ WORK, LDWORK, ONE, C( K+1, 1 ), LDC )
+ END IF
+*
+* W := W * V1**H
+*
+ CALL CTRMM( 'Right', 'Lower', 'Conjugate transpose',
+ $ 'Unit', LASTC, K, ONE, V, LDV, WORK, LDWORK )
+*
+* C1 := C1 - W**H
+*
+ DO 30 J = 1, K
+ DO 20 I = 1, LASTC
+ C( J, I ) = C( J, I ) - CONJG( WORK( I, J ) )
+ 20 CONTINUE
+ 30 CONTINUE
+*
+ ELSE IF( LSAME( SIDE, 'R' ) ) THEN
+*
+* Form C * H or C * H**H where C = ( C1 C2 )
+*
+ LASTV = MAX( K, ILACLR( N, K, V, LDV ) )
+ LASTC = ILACLR( M, LASTV, C, LDC )
+*
+* W := C * V = (C1*V1 + C2*V2) (stored in WORK)
+*
+* W := C1
+*
+ DO 40 J = 1, K
+ CALL CCOPY( LASTC, C( 1, J ), 1, WORK( 1, J ), 1 )
+ 40 CONTINUE
+*
+* W := W * V1
+*
+ CALL CTRMM( 'Right', 'Lower', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C2 * V2
+*
+ CALL CGEMM( 'No transpose', 'No transpose',
+ $ LASTC, K, LASTV-K,
+ $ ONE, C( 1, K+1 ), LDC, V( K+1, 1 ), LDV,
+ $ ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T or W * T**H
+*
+ CALL CTRMM( 'Right', 'Upper', TRANS, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - W * V**H
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C2 := C2 - W * V2**H
+*
+ CALL CGEMM( 'No transpose', 'Conjugate transpose',
+ $ LASTC, LASTV-K, K,
+ $ -ONE, WORK, LDWORK, V( K+1, 1 ), LDV,
+ $ ONE, C( 1, K+1 ), LDC )
+ END IF
+*
+* W := W * V1**H
+*
+ CALL CTRMM( 'Right', 'Lower', 'Conjugate transpose',
+ $ 'Unit', LASTC, K, ONE, V, LDV, WORK, LDWORK )
+*
+* C1 := C1 - W
+*
+ DO 60 J = 1, K
+ DO 50 I = 1, LASTC
+ C( I, J ) = C( I, J ) - WORK( I, J )
+ 50 CONTINUE
+ 60 CONTINUE
+ END IF
+*
+ ELSE
+*
+* Let V = ( V1 )
+* ( V2 ) (last K rows)
+* where V2 is unit upper triangular.
+*
+ IF( LSAME( SIDE, 'L' ) ) THEN
+*
+* Form H * C or H**H * C where C = ( C1 )
+* ( C2 )
+*
+ LASTV = MAX( K, ILACLR( M, K, V, LDV ) )
+ LASTC = ILACLC( LASTV, N, C, LDC )
+*
+* W := C**H * V = (C1**H * V1 + C2**H * V2) (stored in WORK)
+*
+* W := C2**H
+*
+ DO 70 J = 1, K
+ CALL CCOPY( LASTC, C( LASTV-K+J, 1 ), LDC,
+ $ WORK( 1, J ), 1 )
+ CALL CLACGV( LASTC, WORK( 1, J ), 1 )
+ 70 CONTINUE
+*
+* W := W * V2
+*
+ CALL CTRMM( 'Right', 'Upper', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV,
+ $ WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C1**H*V1
+*
+ CALL CGEMM( 'Conjugate transpose', 'No transpose',
+ $ LASTC, K, LASTV-K, ONE, C, LDC, V, LDV,
+ $ ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T**H or W * T
+*
+ CALL CTRMM( 'Right', 'Lower', TRANST, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - V * W**H
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C1 := C1 - V1 * W**H
+*
+ CALL CGEMM( 'No transpose', 'Conjugate transpose',
+ $ LASTV-K, LASTC, K, -ONE, V, LDV, WORK, LDWORK,
+ $ ONE, C, LDC )
+ END IF
+*
+* W := W * V2**H
+*
+ CALL CTRMM( 'Right', 'Upper', 'Conjugate transpose',
+ $ 'Unit', LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV,
+ $ WORK, LDWORK )
+*
+* C2 := C2 - W**H
+*
+ DO 90 J = 1, K
+ DO 80 I = 1, LASTC
+ C( LASTV-K+J, I ) = C( LASTV-K+J, I ) -
+ $ CONJG( WORK( I, J ) )
+ 80 CONTINUE
+ 90 CONTINUE
+*
+ ELSE IF( LSAME( SIDE, 'R' ) ) THEN
+*
+* Form C * H or C * H**H where C = ( C1 C2 )
+*
+ LASTV = MAX( K, ILACLR( N, K, V, LDV ) )
+ LASTC = ILACLR( M, LASTV, C, LDC )
+*
+* W := C * V = (C1*V1 + C2*V2) (stored in WORK)
+*
+* W := C2
+*
+ DO 100 J = 1, K
+ CALL CCOPY( LASTC, C( 1, LASTV-K+J ), 1,
+ $ WORK( 1, J ), 1 )
+ 100 CONTINUE
+*
+* W := W * V2
+*
+ CALL CTRMM( 'Right', 'Upper', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV,
+ $ WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C1 * V1
+*
+ CALL CGEMM( 'No transpose', 'No transpose',
+ $ LASTC, K, LASTV-K,
+ $ ONE, C, LDC, V, LDV, ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T or W * T**H
+*
+ CALL CTRMM( 'Right', 'Lower', TRANS, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - W * V**H
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C1 := C1 - W * V1**H
+*
+ CALL CGEMM( 'No transpose', 'Conjugate transpose',
+ $ LASTC, LASTV-K, K, -ONE, WORK, LDWORK, V, LDV,
+ $ ONE, C, LDC )
+ END IF
+*
+* W := W * V2**H
+*
+ CALL CTRMM( 'Right', 'Upper', 'Conjugate transpose',
+ $ 'Unit', LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV,
+ $ WORK, LDWORK )
+*
+* C2 := C2 - W
+*
+ DO 120 J = 1, K
+ DO 110 I = 1, LASTC
+ C( I, LASTV-K+J ) = C( I, LASTV-K+J )
+ $ - WORK( I, J )
+ 110 CONTINUE
+ 120 CONTINUE
+ END IF
+ END IF
+*
+ ELSE IF( LSAME( STOREV, 'R' ) ) THEN
+*
+ IF( LSAME( DIRECT, 'F' ) ) THEN
+*
+* Let V = ( V1 V2 ) (V1: first K columns)
+* where V1 is unit upper triangular.
+*
+ IF( LSAME( SIDE, 'L' ) ) THEN
+*
+* Form H * C or H**H * C where C = ( C1 )
+* ( C2 )
+*
+ LASTV = MAX( K, ILACLC( K, M, V, LDV ) )
+ LASTC = ILACLC( LASTV, N, C, LDC )
+*
+* W := C**H * V**H = (C1**H * V1**H + C2**H * V2**H) (stored in WORK)
+*
+* W := C1**H
+*
+ DO 130 J = 1, K
+ CALL CCOPY( LASTC, C( J, 1 ), LDC, WORK( 1, J ), 1 )
+ CALL CLACGV( LASTC, WORK( 1, J ), 1 )
+ 130 CONTINUE
+*
+* W := W * V1**H
+*
+ CALL CTRMM( 'Right', 'Upper', 'Conjugate transpose',
+ $ 'Unit', LASTC, K, ONE, V, LDV, WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C2**H*V2**H
+*
+ CALL CGEMM( 'Conjugate transpose',
+ $ 'Conjugate transpose', LASTC, K, LASTV-K,
+ $ ONE, C( K+1, 1 ), LDC, V( 1, K+1 ), LDV,
+ $ ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T**H or W * T
+*
+ CALL CTRMM( 'Right', 'Upper', TRANST, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - V**H * W**H
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C2 := C2 - V2**H * W**H
+*
+ CALL CGEMM( 'Conjugate transpose',
+ $ 'Conjugate transpose', LASTV-K, LASTC, K,
+ $ -ONE, V( 1, K+1 ), LDV, WORK, LDWORK,
+ $ ONE, C( K+1, 1 ), LDC )
+ END IF
+*
+* W := W * V1
+*
+ CALL CTRMM( 'Right', 'Upper', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+*
+* C1 := C1 - W**H
+*
+ DO 150 J = 1, K
+ DO 140 I = 1, LASTC
+ C( J, I ) = C( J, I ) - CONJG( WORK( I, J ) )
+ 140 CONTINUE
+ 150 CONTINUE
+*
+ ELSE IF( LSAME( SIDE, 'R' ) ) THEN
+*
+* Form C * H or C * H**H where C = ( C1 C2 )
+*
+ LASTV = MAX( K, ILACLC( K, N, V, LDV ) )
+ LASTC = ILACLR( M, LASTV, C, LDC )
+*
+* W := C * V**H = (C1*V1**H + C2*V2**H) (stored in WORK)
+*
+* W := C1
+*
+ DO 160 J = 1, K
+ CALL CCOPY( LASTC, C( 1, J ), 1, WORK( 1, J ), 1 )
+ 160 CONTINUE
+*
+* W := W * V1**H
+*
+ CALL CTRMM( 'Right', 'Upper', 'Conjugate transpose',
+ $ 'Unit', LASTC, K, ONE, V, LDV, WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C2 * V2**H
+*
+ CALL CGEMM( 'No transpose', 'Conjugate transpose',
+ $ LASTC, K, LASTV-K, ONE, C( 1, K+1 ), LDC,
+ $ V( 1, K+1 ), LDV, ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T or W * T**H
+*
+ CALL CTRMM( 'Right', 'Upper', TRANS, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - W * V
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C2 := C2 - W * V2
+*
+ CALL CGEMM( 'No transpose', 'No transpose',
+ $ LASTC, LASTV-K, K,
+ $ -ONE, WORK, LDWORK, V( 1, K+1 ), LDV,
+ $ ONE, C( 1, K+1 ), LDC )
+ END IF
+*
+* W := W * V1
+*
+ CALL CTRMM( 'Right', 'Upper', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+*
+* C1 := C1 - W
+*
+ DO 180 J = 1, K
+ DO 170 I = 1, LASTC
+ C( I, J ) = C( I, J ) - WORK( I, J )
+ 170 CONTINUE
+ 180 CONTINUE
+*
+ END IF
+*
+ ELSE
+*
+* Let V = ( V1 V2 ) (V2: last K columns)
+* where V2 is unit lower triangular.
+*
+ IF( LSAME( SIDE, 'L' ) ) THEN
+*
+* Form H * C or H**H * C where C = ( C1 )
+* ( C2 )
+*
+ LASTV = MAX( K, ILACLC( K, M, V, LDV ) )
+ LASTC = ILACLC( LASTV, N, C, LDC )
+*
+* W := C**H * V**H = (C1**H * V1**H + C2**H * V2**H) (stored in WORK)
+*
+* W := C2**H
+*
+ DO 190 J = 1, K
+ CALL CCOPY( LASTC, C( LASTV-K+J, 1 ), LDC,
+ $ WORK( 1, J ), 1 )
+ CALL CLACGV( LASTC, WORK( 1, J ), 1 )
+ 190 CONTINUE
+*
+* W := W * V2**H
+*
+ CALL CTRMM( 'Right', 'Lower', 'Conjugate transpose',
+ $ 'Unit', LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV,
+ $ WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C1**H * V1**H
+*
+ CALL CGEMM( 'Conjugate transpose',
+ $ 'Conjugate transpose', LASTC, K, LASTV-K,
+ $ ONE, C, LDC, V, LDV, ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T**H or W * T
+*
+ CALL CTRMM( 'Right', 'Lower', TRANST, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - V**H * W**H
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C1 := C1 - V1**H * W**H
+*
+ CALL CGEMM( 'Conjugate transpose',
+ $ 'Conjugate transpose', LASTV-K, LASTC, K,
+ $ -ONE, V, LDV, WORK, LDWORK, ONE, C, LDC )
+ END IF
+*
+* W := W * V2
+*
+ CALL CTRMM( 'Right', 'Lower', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV,
+ $ WORK, LDWORK )
+*
+* C2 := C2 - W**H
+*
+ DO 210 J = 1, K
+ DO 200 I = 1, LASTC
+ C( LASTV-K+J, I ) = C( LASTV-K+J, I ) -
+ $ CONJG( WORK( I, J ) )
+ 200 CONTINUE
+ 210 CONTINUE
+*
+ ELSE IF( LSAME( SIDE, 'R' ) ) THEN
+*
+* Form C * H or C * H**H where C = ( C1 C2 )
+*
+ LASTV = MAX( K, ILACLC( K, N, V, LDV ) )
+ LASTC = ILACLR( M, LASTV, C, LDC )
+*
+* W := C * V**H = (C1*V1**H + C2*V2**H) (stored in WORK)
+*
+* W := C2
+*
+ DO 220 J = 1, K
+ CALL CCOPY( LASTC, C( 1, LASTV-K+J ), 1,
+ $ WORK( 1, J ), 1 )
+ 220 CONTINUE
+*
+* W := W * V2**H
+*
+ CALL CTRMM( 'Right', 'Lower', 'Conjugate transpose',
+ $ 'Unit', LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV,
+ $ WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C1 * V1**H
+*
+ CALL CGEMM( 'No transpose', 'Conjugate transpose',
+ $ LASTC, K, LASTV-K, ONE, C, LDC, V, LDV, ONE,
+ $ WORK, LDWORK )
+ END IF
+*
+* W := W * T or W * T**H
+*
+ CALL CTRMM( 'Right', 'Lower', TRANS, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - W * V
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C1 := C1 - W * V1
+*
+ CALL CGEMM( 'No transpose', 'No transpose',
+ $ LASTC, LASTV-K, K, -ONE, WORK, LDWORK, V, LDV,
+ $ ONE, C, LDC )
+ END IF
+*
+* W := W * V2
+*
+ CALL CTRMM( 'Right', 'Lower', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV,
+ $ WORK, LDWORK )
+*
+* C1 := C1 - W
+*
+ DO 240 J = 1, K
+ DO 230 I = 1, LASTC
+ C( I, LASTV-K+J ) = C( I, LASTV-K+J )
+ $ - WORK( I, J )
+ 230 CONTINUE
+ 240 CONTINUE
+*
+ END IF
+*
+ END IF
+ END IF
+*
+ RETURN
+*
+* End of CLARFB
+*
+ END
diff --git a/lapack/clarfg.f b/lapack/clarfg.f
new file mode 100644
index 000000000..d64f396c3
--- /dev/null
+++ b/lapack/clarfg.f
@@ -0,0 +1,203 @@
+*> \brief \b CLARFG
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download CLARFG + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/clarfg.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/clarfg.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clarfg.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE CLARFG( N, ALPHA, X, INCX, TAU )
+*
+* .. Scalar Arguments ..
+* INTEGER INCX, N
+* COMPLEX ALPHA, TAU
+* ..
+* .. Array Arguments ..
+* COMPLEX X( * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> CLARFG generates a complex elementary reflector H of order n, such
+*> that
+*>
+*> H**H * ( alpha ) = ( beta ), H**H * H = I.
+*> ( x ) ( 0 )
+*>
+*> where alpha and beta are scalars, with beta real, and x is an
+*> (n-1)-element complex vector. H is represented in the form
+*>
+*> H = I - tau * ( 1 ) * ( 1 v**H ) ,
+*> ( v )
+*>
+*> where tau is a complex scalar and v is a complex (n-1)-element
+*> vector. Note that H is not hermitian.
+*>
+*> If the elements of x are all zero and alpha is real, then tau = 0
+*> and H is taken to be the unit matrix.
+*>
+*> Otherwise 1 <= real(tau) <= 2 and abs(tau-1) <= 1 .
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The order of the elementary reflector.
+*> \endverbatim
+*>
+*> \param[in,out] ALPHA
+*> \verbatim
+*> ALPHA is COMPLEX
+*> On entry, the value alpha.
+*> On exit, it is overwritten with the value beta.
+*> \endverbatim
+*>
+*> \param[in,out] X
+*> \verbatim
+*> X is COMPLEX array, dimension
+*> (1+(N-2)*abs(INCX))
+*> On entry, the vector x.
+*> On exit, it is overwritten with the vector v.
+*> \endverbatim
+*>
+*> \param[in] INCX
+*> \verbatim
+*> INCX is INTEGER
+*> The increment between elements of X. INCX > 0.
+*> \endverbatim
+*>
+*> \param[out] TAU
+*> \verbatim
+*> TAU is COMPLEX
+*> The value tau.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup complexOTHERauxiliary
+*
+* =====================================================================
+ SUBROUTINE CLARFG( N, ALPHA, X, INCX, TAU )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ INTEGER INCX, N
+ COMPLEX ALPHA, TAU
+* ..
+* .. Array Arguments ..
+ COMPLEX X( * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ REAL ONE, ZERO
+ PARAMETER ( ONE = 1.0E+0, ZERO = 0.0E+0 )
+* ..
+* .. Local Scalars ..
+ INTEGER J, KNT
+ REAL ALPHI, ALPHR, BETA, RSAFMN, SAFMIN, XNORM
+* ..
+* .. External Functions ..
+ REAL SCNRM2, SLAMCH, SLAPY3
+ COMPLEX CLADIV
+ EXTERNAL SCNRM2, SLAMCH, SLAPY3, CLADIV
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC ABS, AIMAG, CMPLX, REAL, SIGN
+* ..
+* .. External Subroutines ..
+ EXTERNAL CSCAL, CSSCAL
+* ..
+* .. Executable Statements ..
+*
+ IF( N.LE.0 ) THEN
+ TAU = ZERO
+ RETURN
+ END IF
+*
+ XNORM = SCNRM2( N-1, X, INCX )
+ ALPHR = REAL( ALPHA )
+ ALPHI = AIMAG( ALPHA )
+*
+ IF( XNORM.EQ.ZERO .AND. ALPHI.EQ.ZERO ) THEN
+*
+* H = I
+*
+ TAU = ZERO
+ ELSE
+*
+* general case
+*
+ BETA = -SIGN( SLAPY3( ALPHR, ALPHI, XNORM ), ALPHR )
+ SAFMIN = SLAMCH( 'S' ) / SLAMCH( 'E' )
+ RSAFMN = ONE / SAFMIN
+*
+ KNT = 0
+ IF( ABS( BETA ).LT.SAFMIN ) THEN
+*
+* XNORM, BETA may be inaccurate; scale X and recompute them
+*
+ 10 CONTINUE
+ KNT = KNT + 1
+ CALL CSSCAL( N-1, RSAFMN, X, INCX )
+ BETA = BETA*RSAFMN
+ ALPHI = ALPHI*RSAFMN
+ ALPHR = ALPHR*RSAFMN
+ IF( ABS( BETA ).LT.SAFMIN )
+ $ GO TO 10
+*
+* New BETA is at most 1, at least SAFMIN
+*
+ XNORM = SCNRM2( N-1, X, INCX )
+ ALPHA = CMPLX( ALPHR, ALPHI )
+ BETA = -SIGN( SLAPY3( ALPHR, ALPHI, XNORM ), ALPHR )
+ END IF
+ TAU = CMPLX( ( BETA-ALPHR ) / BETA, -ALPHI / BETA )
+ ALPHA = CLADIV( CMPLX( ONE ), ALPHA-BETA )
+ CALL CSCAL( N-1, ALPHA, X, INCX )
+*
+* If ALPHA is subnormal, it may lose relative accuracy
+*
+ DO 20 J = 1, KNT
+ BETA = BETA*SAFMIN
+ 20 CONTINUE
+ ALPHA = BETA
+ END IF
+*
+ RETURN
+*
+* End of CLARFG
+*
+ END
diff --git a/lapack/clarft.f b/lapack/clarft.f
new file mode 100644
index 000000000..981447f77
--- /dev/null
+++ b/lapack/clarft.f
@@ -0,0 +1,328 @@
+*> \brief \b CLARFT
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download CLARFT + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/clarft.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/clarft.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clarft.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE CLARFT( DIRECT, STOREV, N, K, V, LDV, TAU, T, LDT )
+*
+* .. Scalar Arguments ..
+* CHARACTER DIRECT, STOREV
+* INTEGER K, LDT, LDV, N
+* ..
+* .. Array Arguments ..
+* COMPLEX T( LDT, * ), TAU( * ), V( LDV, * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> CLARFT forms the triangular factor T of a complex block reflector H
+*> of order n, which is defined as a product of k elementary reflectors.
+*>
+*> If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular;
+*>
+*> If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular.
+*>
+*> If STOREV = 'C', the vector which defines the elementary reflector
+*> H(i) is stored in the i-th column of the array V, and
+*>
+*> H = I - V * T * V**H
+*>
+*> If STOREV = 'R', the vector which defines the elementary reflector
+*> H(i) is stored in the i-th row of the array V, and
+*>
+*> H = I - V**H * T * V
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] DIRECT
+*> \verbatim
+*> DIRECT is CHARACTER*1
+*> Specifies the order in which the elementary reflectors are
+*> multiplied to form the block reflector:
+*> = 'F': H = H(1) H(2) . . . H(k) (Forward)
+*> = 'B': H = H(k) . . . H(2) H(1) (Backward)
+*> \endverbatim
+*>
+*> \param[in] STOREV
+*> \verbatim
+*> STOREV is CHARACTER*1
+*> Specifies how the vectors which define the elementary
+*> reflectors are stored (see also Further Details):
+*> = 'C': columnwise
+*> = 'R': rowwise
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The order of the block reflector H. N >= 0.
+*> \endverbatim
+*>
+*> \param[in] K
+*> \verbatim
+*> K is INTEGER
+*> The order of the triangular factor T (= the number of
+*> elementary reflectors). K >= 1.
+*> \endverbatim
+*>
+*> \param[in] V
+*> \verbatim
+*> V is COMPLEX array, dimension
+*> (LDV,K) if STOREV = 'C'
+*> (LDV,N) if STOREV = 'R'
+*> The matrix V. See further details.
+*> \endverbatim
+*>
+*> \param[in] LDV
+*> \verbatim
+*> LDV is INTEGER
+*> The leading dimension of the array V.
+*> If STOREV = 'C', LDV >= max(1,N); if STOREV = 'R', LDV >= K.
+*> \endverbatim
+*>
+*> \param[in] TAU
+*> \verbatim
+*> TAU is COMPLEX array, dimension (K)
+*> TAU(i) must contain the scalar factor of the elementary
+*> reflector H(i).
+*> \endverbatim
+*>
+*> \param[out] T
+*> \verbatim
+*> T is COMPLEX array, dimension (LDT,K)
+*> The k by k triangular factor T of the block reflector.
+*> If DIRECT = 'F', T is upper triangular; if DIRECT = 'B', T is
+*> lower triangular. The rest of the array is not used.
+*> \endverbatim
+*>
+*> \param[in] LDT
+*> \verbatim
+*> LDT is INTEGER
+*> The leading dimension of the array T. LDT >= K.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date April 2012
+*
+*> \ingroup complexOTHERauxiliary
+*
+*> \par Further Details:
+* =====================
+*>
+*> \verbatim
+*>
+*> The shape of the matrix V and the storage of the vectors which define
+*> the H(i) is best illustrated by the following example with n = 5 and
+*> k = 3. The elements equal to 1 are not stored.
+*>
+*> DIRECT = 'F' and STOREV = 'C': DIRECT = 'F' and STOREV = 'R':
+*>
+*> V = ( 1 ) V = ( 1 v1 v1 v1 v1 )
+*> ( v1 1 ) ( 1 v2 v2 v2 )
+*> ( v1 v2 1 ) ( 1 v3 v3 )
+*> ( v1 v2 v3 )
+*> ( v1 v2 v3 )
+*>
+*> DIRECT = 'B' and STOREV = 'C': DIRECT = 'B' and STOREV = 'R':
+*>
+*> V = ( v1 v2 v3 ) V = ( v1 v1 1 )
+*> ( v1 v2 v3 ) ( v2 v2 v2 1 )
+*> ( 1 v2 v3 ) ( v3 v3 v3 v3 1 )
+*> ( 1 v3 )
+*> ( 1 )
+*> \endverbatim
+*>
+* =====================================================================
+ SUBROUTINE CLARFT( DIRECT, STOREV, N, K, V, LDV, TAU, T, LDT )
+*
+* -- LAPACK auxiliary routine (version 3.4.1) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* April 2012
+*
+* .. Scalar Arguments ..
+ CHARACTER DIRECT, STOREV
+ INTEGER K, LDT, LDV, N
+* ..
+* .. Array Arguments ..
+ COMPLEX T( LDT, * ), TAU( * ), V( LDV, * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ COMPLEX ONE, ZERO
+ PARAMETER ( ONE = ( 1.0E+0, 0.0E+0 ),
+ $ ZERO = ( 0.0E+0, 0.0E+0 ) )
+* ..
+* .. Local Scalars ..
+ INTEGER I, J, PREVLASTV, LASTV
+* ..
+* .. External Subroutines ..
+ EXTERNAL CGEMV, CLACGV, CTRMV
+* ..
+* .. External Functions ..
+ LOGICAL LSAME
+ EXTERNAL LSAME
+* ..
+* .. Executable Statements ..
+*
+* Quick return if possible
+*
+ IF( N.EQ.0 )
+ $ RETURN
+*
+ IF( LSAME( DIRECT, 'F' ) ) THEN
+ PREVLASTV = N
+ DO I = 1, K
+ PREVLASTV = MAX( PREVLASTV, I )
+ IF( TAU( I ).EQ.ZERO ) THEN
+*
+* H(i) = I
+*
+ DO J = 1, I
+ T( J, I ) = ZERO
+ END DO
+ ELSE
+*
+* general case
+*
+ IF( LSAME( STOREV, 'C' ) ) THEN
+* Skip any trailing zeros.
+ DO LASTV = N, I+1, -1
+ IF( V( LASTV, I ).NE.ZERO ) EXIT
+ END DO
+ DO J = 1, I-1
+ T( J, I ) = -TAU( I ) * CONJG( V( I , J ) )
+ END DO
+ J = MIN( LASTV, PREVLASTV )
+*
+* T(1:i-1,i) := - tau(i) * V(i:j,1:i-1)**H * V(i:j,i)
+*
+ CALL CGEMV( 'Conjugate transpose', J-I, I-1,
+ $ -TAU( I ), V( I+1, 1 ), LDV,
+ $ V( I+1, I ), 1,
+ $ ONE, T( 1, I ), 1 )
+ ELSE
+* Skip any trailing zeros.
+ DO LASTV = N, I+1, -1
+ IF( V( I, LASTV ).NE.ZERO ) EXIT
+ END DO
+ DO J = 1, I-1
+ T( J, I ) = -TAU( I ) * V( J , I )
+ END DO
+ J = MIN( LASTV, PREVLASTV )
+*
+* T(1:i-1,i) := - tau(i) * V(1:i-1,i:j) * V(i,i:j)**H
+*
+ CALL CGEMM( 'N', 'C', I-1, 1, J-I, -TAU( I ),
+ $ V( 1, I+1 ), LDV, V( I, I+1 ), LDV,
+ $ ONE, T( 1, I ), LDT )
+ END IF
+*
+* T(1:i-1,i) := T(1:i-1,1:i-1) * T(1:i-1,i)
+*
+ CALL CTRMV( 'Upper', 'No transpose', 'Non-unit', I-1, T,
+ $ LDT, T( 1, I ), 1 )
+ T( I, I ) = TAU( I )
+ IF( I.GT.1 ) THEN
+ PREVLASTV = MAX( PREVLASTV, LASTV )
+ ELSE
+ PREVLASTV = LASTV
+ END IF
+ END IF
+ END DO
+ ELSE
+ PREVLASTV = 1
+ DO I = K, 1, -1
+ IF( TAU( I ).EQ.ZERO ) THEN
+*
+* H(i) = I
+*
+ DO J = I, K
+ T( J, I ) = ZERO
+ END DO
+ ELSE
+*
+* general case
+*
+ IF( I.LT.K ) THEN
+ IF( LSAME( STOREV, 'C' ) ) THEN
+* Skip any leading zeros.
+ DO LASTV = 1, I-1
+ IF( V( LASTV, I ).NE.ZERO ) EXIT
+ END DO
+ DO J = I+1, K
+ T( J, I ) = -TAU( I ) * CONJG( V( N-K+I , J ) )
+ END DO
+ J = MAX( LASTV, PREVLASTV )
+*
+* T(i+1:k,i) = -tau(i) * V(j:n-k+i,i+1:k)**H * V(j:n-k+i,i)
+*
+ CALL CGEMV( 'Conjugate transpose', N-K+I-J, K-I,
+ $ -TAU( I ), V( J, I+1 ), LDV, V( J, I ),
+ $ 1, ONE, T( I+1, I ), 1 )
+ ELSE
+* Skip any leading zeros.
+ DO LASTV = 1, I-1
+ IF( V( I, LASTV ).NE.ZERO ) EXIT
+ END DO
+ DO J = I+1, K
+ T( J, I ) = -TAU( I ) * V( J, N-K+I )
+ END DO
+ J = MAX( LASTV, PREVLASTV )
+*
+* T(i+1:k,i) = -tau(i) * V(i+1:k,j:n-k+i) * V(i,j:n-k+i)**H
+*
+ CALL CGEMM( 'N', 'C', K-I, 1, N-K+I-J, -TAU( I ),
+ $ V( I+1, J ), LDV, V( I, J ), LDV,
+ $ ONE, T( I+1, I ), LDT )
+ END IF
+*
+* T(i+1:k,i) := T(i+1:k,i+1:k) * T(i+1:k,i)
+*
+ CALL CTRMV( 'Lower', 'No transpose', 'Non-unit', K-I,
+ $ T( I+1, I+1 ), LDT, T( I+1, I ), 1 )
+ IF( I.GT.1 ) THEN
+ PREVLASTV = MIN( PREVLASTV, LASTV )
+ ELSE
+ PREVLASTV = LASTV
+ END IF
+ END IF
+ T( I, I ) = TAU( I )
+ END IF
+ END DO
+ END IF
+ RETURN
+*
+* End of CLARFT
+*
+ END
diff --git a/lapack/dladiv.f b/lapack/dladiv.f
new file mode 100644
index 000000000..090a90654
--- /dev/null
+++ b/lapack/dladiv.f
@@ -0,0 +1,128 @@
+*> \brief \b DLADIV
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download DLADIV + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dladiv.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dladiv.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dladiv.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE DLADIV( A, B, C, D, P, Q )
+*
+* .. Scalar Arguments ..
+* DOUBLE PRECISION A, B, C, D, P, Q
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> DLADIV performs complex division in real arithmetic
+*>
+*> a + i*b
+*> p + i*q = ---------
+*> c + i*d
+*>
+*> The algorithm is due to Robert L. Smith and can be found
+*> in D. Knuth, The art of Computer Programming, Vol.2, p.195
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] A
+*> \verbatim
+*> A is DOUBLE PRECISION
+*> \endverbatim
+*>
+*> \param[in] B
+*> \verbatim
+*> B is DOUBLE PRECISION
+*> \endverbatim
+*>
+*> \param[in] C
+*> \verbatim
+*> C is DOUBLE PRECISION
+*> \endverbatim
+*>
+*> \param[in] D
+*> \verbatim
+*> D is DOUBLE PRECISION
+*> The scalars a, b, c, and d in the above expression.
+*> \endverbatim
+*>
+*> \param[out] P
+*> \verbatim
+*> P is DOUBLE PRECISION
+*> \endverbatim
+*>
+*> \param[out] Q
+*> \verbatim
+*> Q is DOUBLE PRECISION
+*> The scalars p and q in the above expression.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup auxOTHERauxiliary
+*
+* =====================================================================
+ SUBROUTINE DLADIV( A, B, C, D, P, Q )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ DOUBLE PRECISION A, B, C, D, P, Q
+* ..
+*
+* =====================================================================
+*
+* .. Local Scalars ..
+ DOUBLE PRECISION E, F
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC ABS
+* ..
+* .. Executable Statements ..
+*
+ IF( ABS( D ).LT.ABS( C ) ) THEN
+ E = D / C
+ F = C + D*E
+ P = ( A+B*E ) / F
+ Q = ( B-A*E ) / F
+ ELSE
+ E = C / D
+ F = D + C*E
+ P = ( B+A*E ) / F
+ Q = ( -A+B*E ) / F
+ END IF
+*
+ RETURN
+*
+* End of DLADIV
+*
+ END
diff --git a/lapack/dlamch.f b/lapack/dlamch.f
new file mode 100644
index 000000000..eb307e5e1
--- /dev/null
+++ b/lapack/dlamch.f
@@ -0,0 +1,189 @@
+*> \brief \b DLAMCH
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+* Definition:
+* ===========
+*
+* DOUBLE PRECISION FUNCTION DLAMCH( CMACH )
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> DLAMCH determines double precision machine parameters.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] CMACH
+*> \verbatim
+*> Specifies the value to be returned by DLAMCH:
+*> = 'E' or 'e', DLAMCH := eps
+*> = 'S' or 's , DLAMCH := sfmin
+*> = 'B' or 'b', DLAMCH := base
+*> = 'P' or 'p', DLAMCH := eps*base
+*> = 'N' or 'n', DLAMCH := t
+*> = 'R' or 'r', DLAMCH := rnd
+*> = 'M' or 'm', DLAMCH := emin
+*> = 'U' or 'u', DLAMCH := rmin
+*> = 'L' or 'l', DLAMCH := emax
+*> = 'O' or 'o', DLAMCH := rmax
+*> where
+*> eps = relative machine precision
+*> sfmin = safe minimum, such that 1/sfmin does not overflow
+*> base = base of the machine
+*> prec = eps*base
+*> t = number of (base) digits in the mantissa
+*> rnd = 1.0 when rounding occurs in addition, 0.0 otherwise
+*> emin = minimum exponent before (gradual) underflow
+*> rmin = underflow threshold - base**(emin-1)
+*> emax = largest exponent before overflow
+*> rmax = overflow threshold - (base**emax)*(1-eps)
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup auxOTHERauxiliary
+*
+* =====================================================================
+ DOUBLE PRECISION FUNCTION DLAMCH( CMACH )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ CHARACTER CMACH
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ DOUBLE PRECISION ONE, ZERO
+ PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
+* ..
+* .. Local Scalars ..
+ DOUBLE PRECISION RND, EPS, SFMIN, SMALL, RMACH
+* ..
+* .. External Functions ..
+ LOGICAL LSAME
+ EXTERNAL LSAME
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC DIGITS, EPSILON, HUGE, MAXEXPONENT,
+ $ MINEXPONENT, RADIX, TINY
+* ..
+* .. Executable Statements ..
+*
+*
+* Assume rounding, not chopping. Always.
+*
+ RND = ONE
+*
+ IF( ONE.EQ.RND ) THEN
+ EPS = EPSILON(ZERO) * 0.5
+ ELSE
+ EPS = EPSILON(ZERO)
+ END IF
+*
+ IF( LSAME( CMACH, 'E' ) ) THEN
+ RMACH = EPS
+ ELSE IF( LSAME( CMACH, 'S' ) ) THEN
+ SFMIN = TINY(ZERO)
+ SMALL = ONE / HUGE(ZERO)
+ IF( SMALL.GE.SFMIN ) THEN
+*
+* Use SMALL plus a bit, to avoid the possibility of rounding
+* causing overflow when computing 1/sfmin.
+*
+ SFMIN = SMALL*( ONE+EPS )
+ END IF
+ RMACH = SFMIN
+ ELSE IF( LSAME( CMACH, 'B' ) ) THEN
+ RMACH = RADIX(ZERO)
+ ELSE IF( LSAME( CMACH, 'P' ) ) THEN
+ RMACH = EPS * RADIX(ZERO)
+ ELSE IF( LSAME( CMACH, 'N' ) ) THEN
+ RMACH = DIGITS(ZERO)
+ ELSE IF( LSAME( CMACH, 'R' ) ) THEN
+ RMACH = RND
+ ELSE IF( LSAME( CMACH, 'M' ) ) THEN
+ RMACH = MINEXPONENT(ZERO)
+ ELSE IF( LSAME( CMACH, 'U' ) ) THEN
+ RMACH = tiny(zero)
+ ELSE IF( LSAME( CMACH, 'L' ) ) THEN
+ RMACH = MAXEXPONENT(ZERO)
+ ELSE IF( LSAME( CMACH, 'O' ) ) THEN
+ RMACH = HUGE(ZERO)
+ ELSE
+ RMACH = ZERO
+ END IF
+*
+ DLAMCH = RMACH
+ RETURN
+*
+* End of DLAMCH
+*
+ END
+************************************************************************
+*> \brief \b DLAMC3
+*> \details
+*> \b Purpose:
+*> \verbatim
+*> DLAMC3 is intended to force A and B to be stored prior to doing
+*> the addition of A and B , for use in situations where optimizers
+*> might hold one of these in a register.
+*> \endverbatim
+*> \author LAPACK is a software package provided by Univ. of Tennessee, Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..
+*> \date November 2011
+*> \ingroup auxOTHERauxiliary
+*>
+*> \param[in] A
+*> \verbatim
+*> A is a DOUBLE PRECISION
+*> \endverbatim
+*>
+*> \param[in] B
+*> \verbatim
+*> B is a DOUBLE PRECISION
+*> The values A and B.
+*> \endverbatim
+*>
+ DOUBLE PRECISION FUNCTION DLAMC3( A, B )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
+* November 2010
+*
+* .. Scalar Arguments ..
+ DOUBLE PRECISION A, B
+* ..
+* =====================================================================
+*
+* .. Executable Statements ..
+*
+ DLAMC3 = A + B
+*
+ RETURN
+*
+* End of DLAMC3
+*
+ END
+*
+************************************************************************
diff --git a/lapack/dlapy2.f b/lapack/dlapy2.f
new file mode 100644
index 000000000..e6a62bf4a
--- /dev/null
+++ b/lapack/dlapy2.f
@@ -0,0 +1,104 @@
+*> \brief \b DLAPY2
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download DLAPY2 + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlapy2.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlapy2.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlapy2.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* DOUBLE PRECISION FUNCTION DLAPY2( X, Y )
+*
+* .. Scalar Arguments ..
+* DOUBLE PRECISION X, Y
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> DLAPY2 returns sqrt(x**2+y**2), taking care not to cause unnecessary
+*> overflow.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] X
+*> \verbatim
+*> X is DOUBLE PRECISION
+*> \endverbatim
+*>
+*> \param[in] Y
+*> \verbatim
+*> Y is DOUBLE PRECISION
+*> X and Y specify the values x and y.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup auxOTHERauxiliary
+*
+* =====================================================================
+ DOUBLE PRECISION FUNCTION DLAPY2( X, Y )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ DOUBLE PRECISION X, Y
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ DOUBLE PRECISION ZERO
+ PARAMETER ( ZERO = 0.0D0 )
+ DOUBLE PRECISION ONE
+ PARAMETER ( ONE = 1.0D0 )
+* ..
+* .. Local Scalars ..
+ DOUBLE PRECISION W, XABS, YABS, Z
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC ABS, MAX, MIN, SQRT
+* ..
+* .. Executable Statements ..
+*
+ XABS = ABS( X )
+ YABS = ABS( Y )
+ W = MAX( XABS, YABS )
+ Z = MIN( XABS, YABS )
+ IF( Z.EQ.ZERO ) THEN
+ DLAPY2 = W
+ ELSE
+ DLAPY2 = W*SQRT( ONE+( Z / W )**2 )
+ END IF
+ RETURN
+*
+* End of DLAPY2
+*
+ END
diff --git a/lapack/dlapy3.f b/lapack/dlapy3.f
new file mode 100644
index 000000000..ae9844f80
--- /dev/null
+++ b/lapack/dlapy3.f
@@ -0,0 +1,111 @@
+*> \brief \b DLAPY3
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download DLAPY3 + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlapy3.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlapy3.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlapy3.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* DOUBLE PRECISION FUNCTION DLAPY3( X, Y, Z )
+*
+* .. Scalar Arguments ..
+* DOUBLE PRECISION X, Y, Z
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> DLAPY3 returns sqrt(x**2+y**2+z**2), taking care not to cause
+*> unnecessary overflow.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] X
+*> \verbatim
+*> X is DOUBLE PRECISION
+*> \endverbatim
+*>
+*> \param[in] Y
+*> \verbatim
+*> Y is DOUBLE PRECISION
+*> \endverbatim
+*>
+*> \param[in] Z
+*> \verbatim
+*> Z is DOUBLE PRECISION
+*> X, Y and Z specify the values x, y and z.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup auxOTHERauxiliary
+*
+* =====================================================================
+ DOUBLE PRECISION FUNCTION DLAPY3( X, Y, Z )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ DOUBLE PRECISION X, Y, Z
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ DOUBLE PRECISION ZERO
+ PARAMETER ( ZERO = 0.0D0 )
+* ..
+* .. Local Scalars ..
+ DOUBLE PRECISION W, XABS, YABS, ZABS
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC ABS, MAX, SQRT
+* ..
+* .. Executable Statements ..
+*
+ XABS = ABS( X )
+ YABS = ABS( Y )
+ ZABS = ABS( Z )
+ W = MAX( XABS, YABS, ZABS )
+ IF( W.EQ.ZERO ) THEN
+* W can be zero for max(0,nan,0)
+* adding all three entries together will make sure
+* NaN will not disappear.
+ DLAPY3 = XABS + YABS + ZABS
+ ELSE
+ DLAPY3 = W*SQRT( ( XABS / W )**2+( YABS / W )**2+
+ $ ( ZABS / W )**2 )
+ END IF
+ RETURN
+*
+* End of DLAPY3
+*
+ END
diff --git a/lapack/dlarf.f b/lapack/dlarf.f
new file mode 100644
index 000000000..2a82ff439
--- /dev/null
+++ b/lapack/dlarf.f
@@ -0,0 +1,227 @@
+*> \brief \b DLARF
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download DLARF + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlarf.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlarf.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlarf.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE DLARF( SIDE, M, N, V, INCV, TAU, C, LDC, WORK )
+*
+* .. Scalar Arguments ..
+* CHARACTER SIDE
+* INTEGER INCV, LDC, M, N
+* DOUBLE PRECISION TAU
+* ..
+* .. Array Arguments ..
+* DOUBLE PRECISION C( LDC, * ), V( * ), WORK( * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> DLARF applies a real elementary reflector H to a real m by n matrix
+*> C, from either the left or the right. H is represented in the form
+*>
+*> H = I - tau * v * v**T
+*>
+*> where tau is a real scalar and v is a real vector.
+*>
+*> If tau = 0, then H is taken to be the unit matrix.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] SIDE
+*> \verbatim
+*> SIDE is CHARACTER*1
+*> = 'L': form H * C
+*> = 'R': form C * H
+*> \endverbatim
+*>
+*> \param[in] M
+*> \verbatim
+*> M is INTEGER
+*> The number of rows of the matrix C.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The number of columns of the matrix C.
+*> \endverbatim
+*>
+*> \param[in] V
+*> \verbatim
+*> V is DOUBLE PRECISION array, dimension
+*> (1 + (M-1)*abs(INCV)) if SIDE = 'L'
+*> or (1 + (N-1)*abs(INCV)) if SIDE = 'R'
+*> The vector v in the representation of H. V is not used if
+*> TAU = 0.
+*> \endverbatim
+*>
+*> \param[in] INCV
+*> \verbatim
+*> INCV is INTEGER
+*> The increment between elements of v. INCV <> 0.
+*> \endverbatim
+*>
+*> \param[in] TAU
+*> \verbatim
+*> TAU is DOUBLE PRECISION
+*> The value tau in the representation of H.
+*> \endverbatim
+*>
+*> \param[in,out] C
+*> \verbatim
+*> C is DOUBLE PRECISION array, dimension (LDC,N)
+*> On entry, the m by n matrix C.
+*> On exit, C is overwritten by the matrix H * C if SIDE = 'L',
+*> or C * H if SIDE = 'R'.
+*> \endverbatim
+*>
+*> \param[in] LDC
+*> \verbatim
+*> LDC is INTEGER
+*> The leading dimension of the array C. LDC >= max(1,M).
+*> \endverbatim
+*>
+*> \param[out] WORK
+*> \verbatim
+*> WORK is DOUBLE PRECISION array, dimension
+*> (N) if SIDE = 'L'
+*> or (M) if SIDE = 'R'
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup doubleOTHERauxiliary
+*
+* =====================================================================
+ SUBROUTINE DLARF( SIDE, M, N, V, INCV, TAU, C, LDC, WORK )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ CHARACTER SIDE
+ INTEGER INCV, LDC, M, N
+ DOUBLE PRECISION TAU
+* ..
+* .. Array Arguments ..
+ DOUBLE PRECISION C( LDC, * ), V( * ), WORK( * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ DOUBLE PRECISION ONE, ZERO
+ PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
+* ..
+* .. Local Scalars ..
+ LOGICAL APPLYLEFT
+ INTEGER I, LASTV, LASTC
+* ..
+* .. External Subroutines ..
+ EXTERNAL DGEMV, DGER
+* ..
+* .. External Functions ..
+ LOGICAL LSAME
+ INTEGER ILADLR, ILADLC
+ EXTERNAL LSAME, ILADLR, ILADLC
+* ..
+* .. Executable Statements ..
+*
+ APPLYLEFT = LSAME( SIDE, 'L' )
+ LASTV = 0
+ LASTC = 0
+ IF( TAU.NE.ZERO ) THEN
+! Set up variables for scanning V. LASTV begins pointing to the end
+! of V.
+ IF( APPLYLEFT ) THEN
+ LASTV = M
+ ELSE
+ LASTV = N
+ END IF
+ IF( INCV.GT.0 ) THEN
+ I = 1 + (LASTV-1) * INCV
+ ELSE
+ I = 1
+ END IF
+! Look for the last non-zero row in V.
+ DO WHILE( LASTV.GT.0 .AND. V( I ).EQ.ZERO )
+ LASTV = LASTV - 1
+ I = I - INCV
+ END DO
+ IF( APPLYLEFT ) THEN
+! Scan for the last non-zero column in C(1:lastv,:).
+ LASTC = ILADLC(LASTV, N, C, LDC)
+ ELSE
+! Scan for the last non-zero row in C(:,1:lastv).
+ LASTC = ILADLR(M, LASTV, C, LDC)
+ END IF
+ END IF
+! Note that lastc.eq.0 renders the BLAS operations null; no special
+! case is needed at this level.
+ IF( APPLYLEFT ) THEN
+*
+* Form H * C
+*
+ IF( LASTV.GT.0 ) THEN
+*
+* w(1:lastc,1) := C(1:lastv,1:lastc)**T * v(1:lastv,1)
+*
+ CALL DGEMV( 'Transpose', LASTV, LASTC, ONE, C, LDC, V, INCV,
+ $ ZERO, WORK, 1 )
+*
+* C(1:lastv,1:lastc) := C(...) - v(1:lastv,1) * w(1:lastc,1)**T
+*
+ CALL DGER( LASTV, LASTC, -TAU, V, INCV, WORK, 1, C, LDC )
+ END IF
+ ELSE
+*
+* Form C * H
+*
+ IF( LASTV.GT.0 ) THEN
+*
+* w(1:lastc,1) := C(1:lastc,1:lastv) * v(1:lastv,1)
+*
+ CALL DGEMV( 'No transpose', LASTC, LASTV, ONE, C, LDC,
+ $ V, INCV, ZERO, WORK, 1 )
+*
+* C(1:lastc,1:lastv) := C(...) - w(1:lastc,1) * v(1:lastv,1)**T
+*
+ CALL DGER( LASTC, LASTV, -TAU, WORK, 1, V, INCV, C, LDC )
+ END IF
+ END IF
+ RETURN
+*
+* End of DLARF
+*
+ END
diff --git a/lapack/dlarfb.f b/lapack/dlarfb.f
new file mode 100644
index 000000000..206d3b268
--- /dev/null
+++ b/lapack/dlarfb.f
@@ -0,0 +1,762 @@
+*> \brief \b DLARFB
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download DLARFB + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlarfb.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlarfb.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlarfb.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE DLARFB( SIDE, TRANS, DIRECT, STOREV, M, N, K, V, LDV,
+* T, LDT, C, LDC, WORK, LDWORK )
+*
+* .. Scalar Arguments ..
+* CHARACTER DIRECT, SIDE, STOREV, TRANS
+* INTEGER K, LDC, LDT, LDV, LDWORK, M, N
+* ..
+* .. Array Arguments ..
+* DOUBLE PRECISION C( LDC, * ), T( LDT, * ), V( LDV, * ),
+* $ WORK( LDWORK, * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> DLARFB applies a real block reflector H or its transpose H**T to a
+*> real m by n matrix C, from either the left or the right.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] SIDE
+*> \verbatim
+*> SIDE is CHARACTER*1
+*> = 'L': apply H or H**T from the Left
+*> = 'R': apply H or H**T from the Right
+*> \endverbatim
+*>
+*> \param[in] TRANS
+*> \verbatim
+*> TRANS is CHARACTER*1
+*> = 'N': apply H (No transpose)
+*> = 'T': apply H**T (Transpose)
+*> \endverbatim
+*>
+*> \param[in] DIRECT
+*> \verbatim
+*> DIRECT is CHARACTER*1
+*> Indicates how H is formed from a product of elementary
+*> reflectors
+*> = 'F': H = H(1) H(2) . . . H(k) (Forward)
+*> = 'B': H = H(k) . . . H(2) H(1) (Backward)
+*> \endverbatim
+*>
+*> \param[in] STOREV
+*> \verbatim
+*> STOREV is CHARACTER*1
+*> Indicates how the vectors which define the elementary
+*> reflectors are stored:
+*> = 'C': Columnwise
+*> = 'R': Rowwise
+*> \endverbatim
+*>
+*> \param[in] M
+*> \verbatim
+*> M is INTEGER
+*> The number of rows of the matrix C.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The number of columns of the matrix C.
+*> \endverbatim
+*>
+*> \param[in] K
+*> \verbatim
+*> K is INTEGER
+*> The order of the matrix T (= the number of elementary
+*> reflectors whose product defines the block reflector).
+*> \endverbatim
+*>
+*> \param[in] V
+*> \verbatim
+*> V is DOUBLE PRECISION array, dimension
+*> (LDV,K) if STOREV = 'C'
+*> (LDV,M) if STOREV = 'R' and SIDE = 'L'
+*> (LDV,N) if STOREV = 'R' and SIDE = 'R'
+*> The matrix V. See Further Details.
+*> \endverbatim
+*>
+*> \param[in] LDV
+*> \verbatim
+*> LDV is INTEGER
+*> The leading dimension of the array V.
+*> If STOREV = 'C' and SIDE = 'L', LDV >= max(1,M);
+*> if STOREV = 'C' and SIDE = 'R', LDV >= max(1,N);
+*> if STOREV = 'R', LDV >= K.
+*> \endverbatim
+*>
+*> \param[in] T
+*> \verbatim
+*> T is DOUBLE PRECISION array, dimension (LDT,K)
+*> The triangular k by k matrix T in the representation of the
+*> block reflector.
+*> \endverbatim
+*>
+*> \param[in] LDT
+*> \verbatim
+*> LDT is INTEGER
+*> The leading dimension of the array T. LDT >= K.
+*> \endverbatim
+*>
+*> \param[in,out] C
+*> \verbatim
+*> C is DOUBLE PRECISION array, dimension (LDC,N)
+*> On entry, the m by n matrix C.
+*> On exit, C is overwritten by H*C or H**T*C or C*H or C*H**T.
+*> \endverbatim
+*>
+*> \param[in] LDC
+*> \verbatim
+*> LDC is INTEGER
+*> The leading dimension of the array C. LDC >= max(1,M).
+*> \endverbatim
+*>
+*> \param[out] WORK
+*> \verbatim
+*> WORK is DOUBLE PRECISION array, dimension (LDWORK,K)
+*> \endverbatim
+*>
+*> \param[in] LDWORK
+*> \verbatim
+*> LDWORK is INTEGER
+*> The leading dimension of the array WORK.
+*> If SIDE = 'L', LDWORK >= max(1,N);
+*> if SIDE = 'R', LDWORK >= max(1,M).
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup doubleOTHERauxiliary
+*
+*> \par Further Details:
+* =====================
+*>
+*> \verbatim
+*>
+*> The shape of the matrix V and the storage of the vectors which define
+*> the H(i) is best illustrated by the following example with n = 5 and
+*> k = 3. The elements equal to 1 are not stored; the corresponding
+*> array elements are modified but restored on exit. The rest of the
+*> array is not used.
+*>
+*> DIRECT = 'F' and STOREV = 'C': DIRECT = 'F' and STOREV = 'R':
+*>
+*> V = ( 1 ) V = ( 1 v1 v1 v1 v1 )
+*> ( v1 1 ) ( 1 v2 v2 v2 )
+*> ( v1 v2 1 ) ( 1 v3 v3 )
+*> ( v1 v2 v3 )
+*> ( v1 v2 v3 )
+*>
+*> DIRECT = 'B' and STOREV = 'C': DIRECT = 'B' and STOREV = 'R':
+*>
+*> V = ( v1 v2 v3 ) V = ( v1 v1 1 )
+*> ( v1 v2 v3 ) ( v2 v2 v2 1 )
+*> ( 1 v2 v3 ) ( v3 v3 v3 v3 1 )
+*> ( 1 v3 )
+*> ( 1 )
+*> \endverbatim
+*>
+* =====================================================================
+ SUBROUTINE DLARFB( SIDE, TRANS, DIRECT, STOREV, M, N, K, V, LDV,
+ $ T, LDT, C, LDC, WORK, LDWORK )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ CHARACTER DIRECT, SIDE, STOREV, TRANS
+ INTEGER K, LDC, LDT, LDV, LDWORK, M, N
+* ..
+* .. Array Arguments ..
+ DOUBLE PRECISION C( LDC, * ), T( LDT, * ), V( LDV, * ),
+ $ WORK( LDWORK, * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ DOUBLE PRECISION ONE
+ PARAMETER ( ONE = 1.0D+0 )
+* ..
+* .. Local Scalars ..
+ CHARACTER TRANST
+ INTEGER I, J, LASTV, LASTC
+* ..
+* .. External Functions ..
+ LOGICAL LSAME
+ INTEGER ILADLR, ILADLC
+ EXTERNAL LSAME, ILADLR, ILADLC
+* ..
+* .. External Subroutines ..
+ EXTERNAL DCOPY, DGEMM, DTRMM
+* ..
+* .. Executable Statements ..
+*
+* Quick return if possible
+*
+ IF( M.LE.0 .OR. N.LE.0 )
+ $ RETURN
+*
+ IF( LSAME( TRANS, 'N' ) ) THEN
+ TRANST = 'T'
+ ELSE
+ TRANST = 'N'
+ END IF
+*
+ IF( LSAME( STOREV, 'C' ) ) THEN
+*
+ IF( LSAME( DIRECT, 'F' ) ) THEN
+*
+* Let V = ( V1 ) (first K rows)
+* ( V2 )
+* where V1 is unit lower triangular.
+*
+ IF( LSAME( SIDE, 'L' ) ) THEN
+*
+* Form H * C or H**T * C where C = ( C1 )
+* ( C2 )
+*
+ LASTV = MAX( K, ILADLR( M, K, V, LDV ) )
+ LASTC = ILADLC( LASTV, N, C, LDC )
+*
+* W := C**T * V = (C1**T * V1 + C2**T * V2) (stored in WORK)
+*
+* W := C1**T
+*
+ DO 10 J = 1, K
+ CALL DCOPY( LASTC, C( J, 1 ), LDC, WORK( 1, J ), 1 )
+ 10 CONTINUE
+*
+* W := W * V1
+*
+ CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C2**T *V2
+*
+ CALL DGEMM( 'Transpose', 'No transpose',
+ $ LASTC, K, LASTV-K,
+ $ ONE, C( K+1, 1 ), LDC, V( K+1, 1 ), LDV,
+ $ ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T**T or W * T
+*
+ CALL DTRMM( 'Right', 'Upper', TRANST, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - V * W**T
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C2 := C2 - V2 * W**T
+*
+ CALL DGEMM( 'No transpose', 'Transpose',
+ $ LASTV-K, LASTC, K,
+ $ -ONE, V( K+1, 1 ), LDV, WORK, LDWORK, ONE,
+ $ C( K+1, 1 ), LDC )
+ END IF
+*
+* W := W * V1**T
+*
+ CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+*
+* C1 := C1 - W**T
+*
+ DO 30 J = 1, K
+ DO 20 I = 1, LASTC
+ C( J, I ) = C( J, I ) - WORK( I, J )
+ 20 CONTINUE
+ 30 CONTINUE
+*
+ ELSE IF( LSAME( SIDE, 'R' ) ) THEN
+*
+* Form C * H or C * H**T where C = ( C1 C2 )
+*
+ LASTV = MAX( K, ILADLR( N, K, V, LDV ) )
+ LASTC = ILADLR( M, LASTV, C, LDC )
+*
+* W := C * V = (C1*V1 + C2*V2) (stored in WORK)
+*
+* W := C1
+*
+ DO 40 J = 1, K
+ CALL DCOPY( LASTC, C( 1, J ), 1, WORK( 1, J ), 1 )
+ 40 CONTINUE
+*
+* W := W * V1
+*
+ CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C2 * V2
+*
+ CALL DGEMM( 'No transpose', 'No transpose',
+ $ LASTC, K, LASTV-K,
+ $ ONE, C( 1, K+1 ), LDC, V( K+1, 1 ), LDV,
+ $ ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T or W * T**T
+*
+ CALL DTRMM( 'Right', 'Upper', TRANS, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - W * V**T
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C2 := C2 - W * V2**T
+*
+ CALL DGEMM( 'No transpose', 'Transpose',
+ $ LASTC, LASTV-K, K,
+ $ -ONE, WORK, LDWORK, V( K+1, 1 ), LDV, ONE,
+ $ C( 1, K+1 ), LDC )
+ END IF
+*
+* W := W * V1**T
+*
+ CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+*
+* C1 := C1 - W
+*
+ DO 60 J = 1, K
+ DO 50 I = 1, LASTC
+ C( I, J ) = C( I, J ) - WORK( I, J )
+ 50 CONTINUE
+ 60 CONTINUE
+ END IF
+*
+ ELSE
+*
+* Let V = ( V1 )
+* ( V2 ) (last K rows)
+* where V2 is unit upper triangular.
+*
+ IF( LSAME( SIDE, 'L' ) ) THEN
+*
+* Form H * C or H**T * C where C = ( C1 )
+* ( C2 )
+*
+ LASTV = MAX( K, ILADLR( M, K, V, LDV ) )
+ LASTC = ILADLC( LASTV, N, C, LDC )
+*
+* W := C**T * V = (C1**T * V1 + C2**T * V2) (stored in WORK)
+*
+* W := C2**T
+*
+ DO 70 J = 1, K
+ CALL DCOPY( LASTC, C( LASTV-K+J, 1 ), LDC,
+ $ WORK( 1, J ), 1 )
+ 70 CONTINUE
+*
+* W := W * V2
+*
+ CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV,
+ $ WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C1**T*V1
+*
+ CALL DGEMM( 'Transpose', 'No transpose',
+ $ LASTC, K, LASTV-K, ONE, C, LDC, V, LDV,
+ $ ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T**T or W * T
+*
+ CALL DTRMM( 'Right', 'Lower', TRANST, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - V * W**T
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C1 := C1 - V1 * W**T
+*
+ CALL DGEMM( 'No transpose', 'Transpose',
+ $ LASTV-K, LASTC, K, -ONE, V, LDV, WORK, LDWORK,
+ $ ONE, C, LDC )
+ END IF
+*
+* W := W * V2**T
+*
+ CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit',
+ $ LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV,
+ $ WORK, LDWORK )
+*
+* C2 := C2 - W**T
+*
+ DO 90 J = 1, K
+ DO 80 I = 1, LASTC
+ C( LASTV-K+J, I ) = C( LASTV-K+J, I ) - WORK(I, J)
+ 80 CONTINUE
+ 90 CONTINUE
+*
+ ELSE IF( LSAME( SIDE, 'R' ) ) THEN
+*
+* Form C * H or C * H**T where C = ( C1 C2 )
+*
+ LASTV = MAX( K, ILADLR( N, K, V, LDV ) )
+ LASTC = ILADLR( M, LASTV, C, LDC )
+*
+* W := C * V = (C1*V1 + C2*V2) (stored in WORK)
+*
+* W := C2
+*
+ DO 100 J = 1, K
+ CALL DCOPY( LASTC, C( 1, N-K+J ), 1, WORK( 1, J ), 1 )
+ 100 CONTINUE
+*
+* W := W * V2
+*
+ CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV,
+ $ WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C1 * V1
+*
+ CALL DGEMM( 'No transpose', 'No transpose',
+ $ LASTC, K, LASTV-K, ONE, C, LDC, V, LDV,
+ $ ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T or W * T**T
+*
+ CALL DTRMM( 'Right', 'Lower', TRANS, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - W * V**T
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C1 := C1 - W * V1**T
+*
+ CALL DGEMM( 'No transpose', 'Transpose',
+ $ LASTC, LASTV-K, K, -ONE, WORK, LDWORK, V, LDV,
+ $ ONE, C, LDC )
+ END IF
+*
+* W := W * V2**T
+*
+ CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit',
+ $ LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV,
+ $ WORK, LDWORK )
+*
+* C2 := C2 - W
+*
+ DO 120 J = 1, K
+ DO 110 I = 1, LASTC
+ C( I, LASTV-K+J ) = C( I, LASTV-K+J ) - WORK(I, J)
+ 110 CONTINUE
+ 120 CONTINUE
+ END IF
+ END IF
+*
+ ELSE IF( LSAME( STOREV, 'R' ) ) THEN
+*
+ IF( LSAME( DIRECT, 'F' ) ) THEN
+*
+* Let V = ( V1 V2 ) (V1: first K columns)
+* where V1 is unit upper triangular.
+*
+ IF( LSAME( SIDE, 'L' ) ) THEN
+*
+* Form H * C or H**T * C where C = ( C1 )
+* ( C2 )
+*
+ LASTV = MAX( K, ILADLC( K, M, V, LDV ) )
+ LASTC = ILADLC( LASTV, N, C, LDC )
+*
+* W := C**T * V**T = (C1**T * V1**T + C2**T * V2**T) (stored in WORK)
+*
+* W := C1**T
+*
+ DO 130 J = 1, K
+ CALL DCOPY( LASTC, C( J, 1 ), LDC, WORK( 1, J ), 1 )
+ 130 CONTINUE
+*
+* W := W * V1**T
+*
+ CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C2**T*V2**T
+*
+ CALL DGEMM( 'Transpose', 'Transpose',
+ $ LASTC, K, LASTV-K,
+ $ ONE, C( K+1, 1 ), LDC, V( 1, K+1 ), LDV,
+ $ ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T**T or W * T
+*
+ CALL DTRMM( 'Right', 'Upper', TRANST, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - V**T * W**T
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C2 := C2 - V2**T * W**T
+*
+ CALL DGEMM( 'Transpose', 'Transpose',
+ $ LASTV-K, LASTC, K,
+ $ -ONE, V( 1, K+1 ), LDV, WORK, LDWORK,
+ $ ONE, C( K+1, 1 ), LDC )
+ END IF
+*
+* W := W * V1
+*
+ CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+*
+* C1 := C1 - W**T
+*
+ DO 150 J = 1, K
+ DO 140 I = 1, LASTC
+ C( J, I ) = C( J, I ) - WORK( I, J )
+ 140 CONTINUE
+ 150 CONTINUE
+*
+ ELSE IF( LSAME( SIDE, 'R' ) ) THEN
+*
+* Form C * H or C * H**T where C = ( C1 C2 )
+*
+ LASTV = MAX( K, ILADLC( K, N, V, LDV ) )
+ LASTC = ILADLR( M, LASTV, C, LDC )
+*
+* W := C * V**T = (C1*V1**T + C2*V2**T) (stored in WORK)
+*
+* W := C1
+*
+ DO 160 J = 1, K
+ CALL DCOPY( LASTC, C( 1, J ), 1, WORK( 1, J ), 1 )
+ 160 CONTINUE
+*
+* W := W * V1**T
+*
+ CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C2 * V2**T
+*
+ CALL DGEMM( 'No transpose', 'Transpose',
+ $ LASTC, K, LASTV-K,
+ $ ONE, C( 1, K+1 ), LDC, V( 1, K+1 ), LDV,
+ $ ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T or W * T**T
+*
+ CALL DTRMM( 'Right', 'Upper', TRANS, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - W * V
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C2 := C2 - W * V2
+*
+ CALL DGEMM( 'No transpose', 'No transpose',
+ $ LASTC, LASTV-K, K,
+ $ -ONE, WORK, LDWORK, V( 1, K+1 ), LDV,
+ $ ONE, C( 1, K+1 ), LDC )
+ END IF
+*
+* W := W * V1
+*
+ CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+*
+* C1 := C1 - W
+*
+ DO 180 J = 1, K
+ DO 170 I = 1, LASTC
+ C( I, J ) = C( I, J ) - WORK( I, J )
+ 170 CONTINUE
+ 180 CONTINUE
+*
+ END IF
+*
+ ELSE
+*
+* Let V = ( V1 V2 ) (V2: last K columns)
+* where V2 is unit lower triangular.
+*
+ IF( LSAME( SIDE, 'L' ) ) THEN
+*
+* Form H * C or H**T * C where C = ( C1 )
+* ( C2 )
+*
+ LASTV = MAX( K, ILADLC( K, M, V, LDV ) )
+ LASTC = ILADLC( LASTV, N, C, LDC )
+*
+* W := C**T * V**T = (C1**T * V1**T + C2**T * V2**T) (stored in WORK)
+*
+* W := C2**T
+*
+ DO 190 J = 1, K
+ CALL DCOPY( LASTC, C( LASTV-K+J, 1 ), LDC,
+ $ WORK( 1, J ), 1 )
+ 190 CONTINUE
+*
+* W := W * V2**T
+*
+ CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit',
+ $ LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV,
+ $ WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C1**T * V1**T
+*
+ CALL DGEMM( 'Transpose', 'Transpose',
+ $ LASTC, K, LASTV-K, ONE, C, LDC, V, LDV,
+ $ ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T**T or W * T
+*
+ CALL DTRMM( 'Right', 'Lower', TRANST, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - V**T * W**T
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C1 := C1 - V1**T * W**T
+*
+ CALL DGEMM( 'Transpose', 'Transpose',
+ $ LASTV-K, LASTC, K, -ONE, V, LDV, WORK, LDWORK,
+ $ ONE, C, LDC )
+ END IF
+*
+* W := W * V2
+*
+ CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV,
+ $ WORK, LDWORK )
+*
+* C2 := C2 - W**T
+*
+ DO 210 J = 1, K
+ DO 200 I = 1, LASTC
+ C( LASTV-K+J, I ) = C( LASTV-K+J, I ) - WORK(I, J)
+ 200 CONTINUE
+ 210 CONTINUE
+*
+ ELSE IF( LSAME( SIDE, 'R' ) ) THEN
+*
+* Form C * H or C * H**T where C = ( C1 C2 )
+*
+ LASTV = MAX( K, ILADLC( K, N, V, LDV ) )
+ LASTC = ILADLR( M, LASTV, C, LDC )
+*
+* W := C * V**T = (C1*V1**T + C2*V2**T) (stored in WORK)
+*
+* W := C2
+*
+ DO 220 J = 1, K
+ CALL DCOPY( LASTC, C( 1, LASTV-K+J ), 1,
+ $ WORK( 1, J ), 1 )
+ 220 CONTINUE
+*
+* W := W * V2**T
+*
+ CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit',
+ $ LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV,
+ $ WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C1 * V1**T
+*
+ CALL DGEMM( 'No transpose', 'Transpose',
+ $ LASTC, K, LASTV-K, ONE, C, LDC, V, LDV,
+ $ ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T or W * T**T
+*
+ CALL DTRMM( 'Right', 'Lower', TRANS, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - W * V
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C1 := C1 - W * V1
+*
+ CALL DGEMM( 'No transpose', 'No transpose',
+ $ LASTC, LASTV-K, K, -ONE, WORK, LDWORK, V, LDV,
+ $ ONE, C, LDC )
+ END IF
+*
+* W := W * V2
+*
+ CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV,
+ $ WORK, LDWORK )
+*
+* C1 := C1 - W
+*
+ DO 240 J = 1, K
+ DO 230 I = 1, LASTC
+ C( I, LASTV-K+J ) = C( I, LASTV-K+J ) - WORK(I, J)
+ 230 CONTINUE
+ 240 CONTINUE
+*
+ END IF
+*
+ END IF
+ END IF
+*
+ RETURN
+*
+* End of DLARFB
+*
+ END
diff --git a/lapack/dlarfg.f b/lapack/dlarfg.f
new file mode 100644
index 000000000..458ad2e05
--- /dev/null
+++ b/lapack/dlarfg.f
@@ -0,0 +1,196 @@
+*> \brief \b DLARFG
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download DLARFG + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlarfg.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlarfg.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlarfg.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE DLARFG( N, ALPHA, X, INCX, TAU )
+*
+* .. Scalar Arguments ..
+* INTEGER INCX, N
+* DOUBLE PRECISION ALPHA, TAU
+* ..
+* .. Array Arguments ..
+* DOUBLE PRECISION X( * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> DLARFG generates a real elementary reflector H of order n, such
+*> that
+*>
+*> H * ( alpha ) = ( beta ), H**T * H = I.
+*> ( x ) ( 0 )
+*>
+*> where alpha and beta are scalars, and x is an (n-1)-element real
+*> vector. H is represented in the form
+*>
+*> H = I - tau * ( 1 ) * ( 1 v**T ) ,
+*> ( v )
+*>
+*> where tau is a real scalar and v is a real (n-1)-element
+*> vector.
+*>
+*> If the elements of x are all zero, then tau = 0 and H is taken to be
+*> the unit matrix.
+*>
+*> Otherwise 1 <= tau <= 2.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The order of the elementary reflector.
+*> \endverbatim
+*>
+*> \param[in,out] ALPHA
+*> \verbatim
+*> ALPHA is DOUBLE PRECISION
+*> On entry, the value alpha.
+*> On exit, it is overwritten with the value beta.
+*> \endverbatim
+*>
+*> \param[in,out] X
+*> \verbatim
+*> X is DOUBLE PRECISION array, dimension
+*> (1+(N-2)*abs(INCX))
+*> On entry, the vector x.
+*> On exit, it is overwritten with the vector v.
+*> \endverbatim
+*>
+*> \param[in] INCX
+*> \verbatim
+*> INCX is INTEGER
+*> The increment between elements of X. INCX > 0.
+*> \endverbatim
+*>
+*> \param[out] TAU
+*> \verbatim
+*> TAU is DOUBLE PRECISION
+*> The value tau.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup doubleOTHERauxiliary
+*
+* =====================================================================
+ SUBROUTINE DLARFG( N, ALPHA, X, INCX, TAU )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ INTEGER INCX, N
+ DOUBLE PRECISION ALPHA, TAU
+* ..
+* .. Array Arguments ..
+ DOUBLE PRECISION X( * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ DOUBLE PRECISION ONE, ZERO
+ PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
+* ..
+* .. Local Scalars ..
+ INTEGER J, KNT
+ DOUBLE PRECISION BETA, RSAFMN, SAFMIN, XNORM
+* ..
+* .. External Functions ..
+ DOUBLE PRECISION DLAMCH, DLAPY2, DNRM2
+ EXTERNAL DLAMCH, DLAPY2, DNRM2
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC ABS, SIGN
+* ..
+* .. External Subroutines ..
+ EXTERNAL DSCAL
+* ..
+* .. Executable Statements ..
+*
+ IF( N.LE.1 ) THEN
+ TAU = ZERO
+ RETURN
+ END IF
+*
+ XNORM = DNRM2( N-1, X, INCX )
+*
+ IF( XNORM.EQ.ZERO ) THEN
+*
+* H = I
+*
+ TAU = ZERO
+ ELSE
+*
+* general case
+*
+ BETA = -SIGN( DLAPY2( ALPHA, XNORM ), ALPHA )
+ SAFMIN = DLAMCH( 'S' ) / DLAMCH( 'E' )
+ KNT = 0
+ IF( ABS( BETA ).LT.SAFMIN ) THEN
+*
+* XNORM, BETA may be inaccurate; scale X and recompute them
+*
+ RSAFMN = ONE / SAFMIN
+ 10 CONTINUE
+ KNT = KNT + 1
+ CALL DSCAL( N-1, RSAFMN, X, INCX )
+ BETA = BETA*RSAFMN
+ ALPHA = ALPHA*RSAFMN
+ IF( ABS( BETA ).LT.SAFMIN )
+ $ GO TO 10
+*
+* New BETA is at most 1, at least SAFMIN
+*
+ XNORM = DNRM2( N-1, X, INCX )
+ BETA = -SIGN( DLAPY2( ALPHA, XNORM ), ALPHA )
+ END IF
+ TAU = ( BETA-ALPHA ) / BETA
+ CALL DSCAL( N-1, ONE / ( ALPHA-BETA ), X, INCX )
+*
+* If ALPHA is subnormal, it may lose relative accuracy
+*
+ DO 20 J = 1, KNT
+ BETA = BETA*SAFMIN
+ 20 CONTINUE
+ ALPHA = BETA
+ END IF
+*
+ RETURN
+*
+* End of DLARFG
+*
+ END
diff --git a/lapack/dlarft.f b/lapack/dlarft.f
new file mode 100644
index 000000000..4b7550403
--- /dev/null
+++ b/lapack/dlarft.f
@@ -0,0 +1,326 @@
+*> \brief \b DLARFT
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download DLARFT + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlarft.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlarft.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlarft.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE DLARFT( DIRECT, STOREV, N, K, V, LDV, TAU, T, LDT )
+*
+* .. Scalar Arguments ..
+* CHARACTER DIRECT, STOREV
+* INTEGER K, LDT, LDV, N
+* ..
+* .. Array Arguments ..
+* DOUBLE PRECISION T( LDT, * ), TAU( * ), V( LDV, * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> DLARFT forms the triangular factor T of a real block reflector H
+*> of order n, which is defined as a product of k elementary reflectors.
+*>
+*> If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular;
+*>
+*> If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular.
+*>
+*> If STOREV = 'C', the vector which defines the elementary reflector
+*> H(i) is stored in the i-th column of the array V, and
+*>
+*> H = I - V * T * V**T
+*>
+*> If STOREV = 'R', the vector which defines the elementary reflector
+*> H(i) is stored in the i-th row of the array V, and
+*>
+*> H = I - V**T * T * V
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] DIRECT
+*> \verbatim
+*> DIRECT is CHARACTER*1
+*> Specifies the order in which the elementary reflectors are
+*> multiplied to form the block reflector:
+*> = 'F': H = H(1) H(2) . . . H(k) (Forward)
+*> = 'B': H = H(k) . . . H(2) H(1) (Backward)
+*> \endverbatim
+*>
+*> \param[in] STOREV
+*> \verbatim
+*> STOREV is CHARACTER*1
+*> Specifies how the vectors which define the elementary
+*> reflectors are stored (see also Further Details):
+*> = 'C': columnwise
+*> = 'R': rowwise
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The order of the block reflector H. N >= 0.
+*> \endverbatim
+*>
+*> \param[in] K
+*> \verbatim
+*> K is INTEGER
+*> The order of the triangular factor T (= the number of
+*> elementary reflectors). K >= 1.
+*> \endverbatim
+*>
+*> \param[in] V
+*> \verbatim
+*> V is DOUBLE PRECISION array, dimension
+*> (LDV,K) if STOREV = 'C'
+*> (LDV,N) if STOREV = 'R'
+*> The matrix V. See further details.
+*> \endverbatim
+*>
+*> \param[in] LDV
+*> \verbatim
+*> LDV is INTEGER
+*> The leading dimension of the array V.
+*> If STOREV = 'C', LDV >= max(1,N); if STOREV = 'R', LDV >= K.
+*> \endverbatim
+*>
+*> \param[in] TAU
+*> \verbatim
+*> TAU is DOUBLE PRECISION array, dimension (K)
+*> TAU(i) must contain the scalar factor of the elementary
+*> reflector H(i).
+*> \endverbatim
+*>
+*> \param[out] T
+*> \verbatim
+*> T is DOUBLE PRECISION array, dimension (LDT,K)
+*> The k by k triangular factor T of the block reflector.
+*> If DIRECT = 'F', T is upper triangular; if DIRECT = 'B', T is
+*> lower triangular. The rest of the array is not used.
+*> \endverbatim
+*>
+*> \param[in] LDT
+*> \verbatim
+*> LDT is INTEGER
+*> The leading dimension of the array T. LDT >= K.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date April 2012
+*
+*> \ingroup doubleOTHERauxiliary
+*
+*> \par Further Details:
+* =====================
+*>
+*> \verbatim
+*>
+*> The shape of the matrix V and the storage of the vectors which define
+*> the H(i) is best illustrated by the following example with n = 5 and
+*> k = 3. The elements equal to 1 are not stored.
+*>
+*> DIRECT = 'F' and STOREV = 'C': DIRECT = 'F' and STOREV = 'R':
+*>
+*> V = ( 1 ) V = ( 1 v1 v1 v1 v1 )
+*> ( v1 1 ) ( 1 v2 v2 v2 )
+*> ( v1 v2 1 ) ( 1 v3 v3 )
+*> ( v1 v2 v3 )
+*> ( v1 v2 v3 )
+*>
+*> DIRECT = 'B' and STOREV = 'C': DIRECT = 'B' and STOREV = 'R':
+*>
+*> V = ( v1 v2 v3 ) V = ( v1 v1 1 )
+*> ( v1 v2 v3 ) ( v2 v2 v2 1 )
+*> ( 1 v2 v3 ) ( v3 v3 v3 v3 1 )
+*> ( 1 v3 )
+*> ( 1 )
+*> \endverbatim
+*>
+* =====================================================================
+ SUBROUTINE DLARFT( DIRECT, STOREV, N, K, V, LDV, TAU, T, LDT )
+*
+* -- LAPACK auxiliary routine (version 3.4.1) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* April 2012
+*
+* .. Scalar Arguments ..
+ CHARACTER DIRECT, STOREV
+ INTEGER K, LDT, LDV, N
+* ..
+* .. Array Arguments ..
+ DOUBLE PRECISION T( LDT, * ), TAU( * ), V( LDV, * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ DOUBLE PRECISION ONE, ZERO
+ PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
+* ..
+* .. Local Scalars ..
+ INTEGER I, J, PREVLASTV, LASTV
+* ..
+* .. External Subroutines ..
+ EXTERNAL DGEMV, DTRMV
+* ..
+* .. External Functions ..
+ LOGICAL LSAME
+ EXTERNAL LSAME
+* ..
+* .. Executable Statements ..
+*
+* Quick return if possible
+*
+ IF( N.EQ.0 )
+ $ RETURN
+*
+ IF( LSAME( DIRECT, 'F' ) ) THEN
+ PREVLASTV = N
+ DO I = 1, K
+ PREVLASTV = MAX( I, PREVLASTV )
+ IF( TAU( I ).EQ.ZERO ) THEN
+*
+* H(i) = I
+*
+ DO J = 1, I
+ T( J, I ) = ZERO
+ END DO
+ ELSE
+*
+* general case
+*
+ IF( LSAME( STOREV, 'C' ) ) THEN
+* Skip any trailing zeros.
+ DO LASTV = N, I+1, -1
+ IF( V( LASTV, I ).NE.ZERO ) EXIT
+ END DO
+ DO J = 1, I-1
+ T( J, I ) = -TAU( I ) * V( I , J )
+ END DO
+ J = MIN( LASTV, PREVLASTV )
+*
+* T(1:i-1,i) := - tau(i) * V(i:j,1:i-1)**T * V(i:j,i)
+*
+ CALL DGEMV( 'Transpose', J-I, I-1, -TAU( I ),
+ $ V( I+1, 1 ), LDV, V( I+1, I ), 1, ONE,
+ $ T( 1, I ), 1 )
+ ELSE
+* Skip any trailing zeros.
+ DO LASTV = N, I+1, -1
+ IF( V( I, LASTV ).NE.ZERO ) EXIT
+ END DO
+ DO J = 1, I-1
+ T( J, I ) = -TAU( I ) * V( J , I )
+ END DO
+ J = MIN( LASTV, PREVLASTV )
+*
+* T(1:i-1,i) := - tau(i) * V(1:i-1,i:j) * V(i,i:j)**T
+*
+ CALL DGEMV( 'No transpose', I-1, J-I, -TAU( I ),
+ $ V( 1, I+1 ), LDV, V( I, I+1 ), LDV, ONE,
+ $ T( 1, I ), 1 )
+ END IF
+*
+* T(1:i-1,i) := T(1:i-1,1:i-1) * T(1:i-1,i)
+*
+ CALL DTRMV( 'Upper', 'No transpose', 'Non-unit', I-1, T,
+ $ LDT, T( 1, I ), 1 )
+ T( I, I ) = TAU( I )
+ IF( I.GT.1 ) THEN
+ PREVLASTV = MAX( PREVLASTV, LASTV )
+ ELSE
+ PREVLASTV = LASTV
+ END IF
+ END IF
+ END DO
+ ELSE
+ PREVLASTV = 1
+ DO I = K, 1, -1
+ IF( TAU( I ).EQ.ZERO ) THEN
+*
+* H(i) = I
+*
+ DO J = I, K
+ T( J, I ) = ZERO
+ END DO
+ ELSE
+*
+* general case
+*
+ IF( I.LT.K ) THEN
+ IF( LSAME( STOREV, 'C' ) ) THEN
+* Skip any leading zeros.
+ DO LASTV = 1, I-1
+ IF( V( LASTV, I ).NE.ZERO ) EXIT
+ END DO
+ DO J = I+1, K
+ T( J, I ) = -TAU( I ) * V( N-K+I , J )
+ END DO
+ J = MAX( LASTV, PREVLASTV )
+*
+* T(i+1:k,i) = -tau(i) * V(j:n-k+i,i+1:k)**T * V(j:n-k+i,i)
+*
+ CALL DGEMV( 'Transpose', N-K+I-J, K-I, -TAU( I ),
+ $ V( J, I+1 ), LDV, V( J, I ), 1, ONE,
+ $ T( I+1, I ), 1 )
+ ELSE
+* Skip any leading zeros.
+ DO LASTV = 1, I-1
+ IF( V( I, LASTV ).NE.ZERO ) EXIT
+ END DO
+ DO J = I+1, K
+ T( J, I ) = -TAU( I ) * V( J, N-K+I )
+ END DO
+ J = MAX( LASTV, PREVLASTV )
+*
+* T(i+1:k,i) = -tau(i) * V(i+1:k,j:n-k+i) * V(i,j:n-k+i)**T
+*
+ CALL DGEMV( 'No transpose', K-I, N-K+I-J,
+ $ -TAU( I ), V( I+1, J ), LDV, V( I, J ), LDV,
+ $ ONE, T( I+1, I ), 1 )
+ END IF
+*
+* T(i+1:k,i) := T(i+1:k,i+1:k) * T(i+1:k,i)
+*
+ CALL DTRMV( 'Lower', 'No transpose', 'Non-unit', K-I,
+ $ T( I+1, I+1 ), LDT, T( I+1, I ), 1 )
+ IF( I.GT.1 ) THEN
+ PREVLASTV = MIN( PREVLASTV, LASTV )
+ ELSE
+ PREVLASTV = LASTV
+ END IF
+ END IF
+ T( I, I ) = TAU( I )
+ END IF
+ END DO
+ END IF
+ RETURN
+*
+* End of DLARFT
+*
+ END
diff --git a/lapack/dsecnd_NONE.f b/lapack/dsecnd_NONE.f
new file mode 100644
index 000000000..61a8dff13
--- /dev/null
+++ b/lapack/dsecnd_NONE.f
@@ -0,0 +1,52 @@
+*> \brief \b DSECND returns nothing
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+* Definition:
+* ===========
+*
+* DOUBLE PRECISION FUNCTION DSECND( )
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> DSECND returns nothing instead of returning the user time for a process in seconds.
+*> If you are using that routine, it means that neither EXTERNAL ETIME,
+*> EXTERNAL ETIME_, INTERNAL ETIME, INTERNAL CPU_TIME is available on
+*> your machine.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup auxOTHERauxiliary
+*
+* =====================================================================
+ DOUBLE PRECISION FUNCTION DSECND( )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* =====================================================================
+*
+ DSECND = 0.0D+0
+ RETURN
+*
+* End of DSECND
+*
+ END
diff --git a/lapack/ilaclc.f b/lapack/ilaclc.f
new file mode 100644
index 000000000..4ceb61c52
--- /dev/null
+++ b/lapack/ilaclc.f
@@ -0,0 +1,118 @@
+*> \brief \b ILACLC
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download ILACLC + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/ilaclc.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/ilaclc.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ilaclc.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* INTEGER FUNCTION ILACLC( M, N, A, LDA )
+*
+* .. Scalar Arguments ..
+* INTEGER M, N, LDA
+* ..
+* .. Array Arguments ..
+* COMPLEX A( LDA, * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> ILACLC scans A for its last non-zero column.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] M
+*> \verbatim
+*> M is INTEGER
+*> The number of rows of the matrix A.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The number of columns of the matrix A.
+*> \endverbatim
+*>
+*> \param[in] A
+*> \verbatim
+*> A is COMPLEX array, dimension (LDA,N)
+*> The m by n matrix A.
+*> \endverbatim
+*>
+*> \param[in] LDA
+*> \verbatim
+*> LDA is INTEGER
+*> The leading dimension of the array A. LDA >= max(1,M).
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup complexOTHERauxiliary
+*
+* =====================================================================
+ INTEGER FUNCTION ILACLC( M, N, A, LDA )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ INTEGER M, N, LDA
+* ..
+* .. Array Arguments ..
+ COMPLEX A( LDA, * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ COMPLEX ZERO
+ PARAMETER ( ZERO = (0.0E+0, 0.0E+0) )
+* ..
+* .. Local Scalars ..
+ INTEGER I
+* ..
+* .. Executable Statements ..
+*
+* Quick test for the common case where one corner is non-zero.
+ IF( N.EQ.0 ) THEN
+ ILACLC = N
+ ELSE IF( A(1, N).NE.ZERO .OR. A(M, N).NE.ZERO ) THEN
+ ILACLC = N
+ ELSE
+* Now scan each column from the end, returning with the first non-zero.
+ DO ILACLC = N, 1, -1
+ DO I = 1, M
+ IF( A(I, ILACLC).NE.ZERO ) RETURN
+ END DO
+ END DO
+ END IF
+ RETURN
+ END
diff --git a/lapack/ilaclr.f b/lapack/ilaclr.f
new file mode 100644
index 000000000..d8ab09c55
--- /dev/null
+++ b/lapack/ilaclr.f
@@ -0,0 +1,121 @@
+*> \brief \b ILACLR
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download ILACLR + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/ilaclr.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/ilaclr.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ilaclr.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* INTEGER FUNCTION ILACLR( M, N, A, LDA )
+*
+* .. Scalar Arguments ..
+* INTEGER M, N, LDA
+* ..
+* .. Array Arguments ..
+* COMPLEX A( LDA, * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> ILACLR scans A for its last non-zero row.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] M
+*> \verbatim
+*> M is INTEGER
+*> The number of rows of the matrix A.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The number of columns of the matrix A.
+*> \endverbatim
+*>
+*> \param[in] A
+*> \verbatim
+*> A is array, dimension (LDA,N)
+*> The m by n matrix A.
+*> \endverbatim
+*>
+*> \param[in] LDA
+*> \verbatim
+*> LDA is INTEGER
+*> The leading dimension of the array A. LDA >= max(1,M).
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date April 2012
+*
+*> \ingroup complexOTHERauxiliary
+*
+* =====================================================================
+ INTEGER FUNCTION ILACLR( M, N, A, LDA )
+*
+* -- LAPACK auxiliary routine (version 3.4.1) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* April 2012
+*
+* .. Scalar Arguments ..
+ INTEGER M, N, LDA
+* ..
+* .. Array Arguments ..
+ COMPLEX A( LDA, * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ COMPLEX ZERO
+ PARAMETER ( ZERO = (0.0E+0, 0.0E+0) )
+* ..
+* .. Local Scalars ..
+ INTEGER I, J
+* ..
+* .. Executable Statements ..
+*
+* Quick test for the common case where one corner is non-zero.
+ IF( M.EQ.0 ) THEN
+ ILACLR = M
+ ELSE IF( A(M, 1).NE.ZERO .OR. A(M, N).NE.ZERO ) THEN
+ ILACLR = M
+ ELSE
+* Scan up each column tracking the last zero row seen.
+ ILACLR = 0
+ DO J = 1, N
+ I=M
+ DO WHILE((A(MAX(I,1),J).EQ.ZERO).AND.(I.GE.1))
+ I=I-1
+ ENDDO
+ ILACLR = MAX( ILACLR, I )
+ END DO
+ END IF
+ RETURN
+ END
diff --git a/lapack/iladlc.f b/lapack/iladlc.f
new file mode 100644
index 000000000..f84bd833a
--- /dev/null
+++ b/lapack/iladlc.f
@@ -0,0 +1,118 @@
+*> \brief \b ILADLC
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download ILADLC + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/iladlc.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/iladlc.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/iladlc.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* INTEGER FUNCTION ILADLC( M, N, A, LDA )
+*
+* .. Scalar Arguments ..
+* INTEGER M, N, LDA
+* ..
+* .. Array Arguments ..
+* DOUBLE PRECISION A( LDA, * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> ILADLC scans A for its last non-zero column.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] M
+*> \verbatim
+*> M is INTEGER
+*> The number of rows of the matrix A.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The number of columns of the matrix A.
+*> \endverbatim
+*>
+*> \param[in] A
+*> \verbatim
+*> A is DOUBLE PRECISION array, dimension (LDA,N)
+*> The m by n matrix A.
+*> \endverbatim
+*>
+*> \param[in] LDA
+*> \verbatim
+*> LDA is INTEGER
+*> The leading dimension of the array A. LDA >= max(1,M).
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup auxOTHERauxiliary
+*
+* =====================================================================
+ INTEGER FUNCTION ILADLC( M, N, A, LDA )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ INTEGER M, N, LDA
+* ..
+* .. Array Arguments ..
+ DOUBLE PRECISION A( LDA, * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ DOUBLE PRECISION ZERO
+ PARAMETER ( ZERO = 0.0D+0 )
+* ..
+* .. Local Scalars ..
+ INTEGER I
+* ..
+* .. Executable Statements ..
+*
+* Quick test for the common case where one corner is non-zero.
+ IF( N.EQ.0 ) THEN
+ ILADLC = N
+ ELSE IF( A(1, N).NE.ZERO .OR. A(M, N).NE.ZERO ) THEN
+ ILADLC = N
+ ELSE
+* Now scan each column from the end, returning with the first non-zero.
+ DO ILADLC = N, 1, -1
+ DO I = 1, M
+ IF( A(I, ILADLC).NE.ZERO ) RETURN
+ END DO
+ END DO
+ END IF
+ RETURN
+ END
diff --git a/lapack/iladlr.f b/lapack/iladlr.f
new file mode 100644
index 000000000..2114c6164
--- /dev/null
+++ b/lapack/iladlr.f
@@ -0,0 +1,121 @@
+*> \brief \b ILADLR
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download ILADLR + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/iladlr.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/iladlr.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/iladlr.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* INTEGER FUNCTION ILADLR( M, N, A, LDA )
+*
+* .. Scalar Arguments ..
+* INTEGER M, N, LDA
+* ..
+* .. Array Arguments ..
+* DOUBLE PRECISION A( LDA, * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> ILADLR scans A for its last non-zero row.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] M
+*> \verbatim
+*> M is INTEGER
+*> The number of rows of the matrix A.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The number of columns of the matrix A.
+*> \endverbatim
+*>
+*> \param[in] A
+*> \verbatim
+*> A is DOUBLE PRECISION array, dimension (LDA,N)
+*> The m by n matrix A.
+*> \endverbatim
+*>
+*> \param[in] LDA
+*> \verbatim
+*> LDA is INTEGER
+*> The leading dimension of the array A. LDA >= max(1,M).
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date April 2012
+*
+*> \ingroup auxOTHERauxiliary
+*
+* =====================================================================
+ INTEGER FUNCTION ILADLR( M, N, A, LDA )
+*
+* -- LAPACK auxiliary routine (version 3.4.1) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* April 2012
+*
+* .. Scalar Arguments ..
+ INTEGER M, N, LDA
+* ..
+* .. Array Arguments ..
+ DOUBLE PRECISION A( LDA, * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ DOUBLE PRECISION ZERO
+ PARAMETER ( ZERO = 0.0D+0 )
+* ..
+* .. Local Scalars ..
+ INTEGER I, J
+* ..
+* .. Executable Statements ..
+*
+* Quick test for the common case where one corner is non-zero.
+ IF( M.EQ.0 ) THEN
+ ILADLR = M
+ ELSE IF( A(M, 1).NE.ZERO .OR. A(M, N).NE.ZERO ) THEN
+ ILADLR = M
+ ELSE
+* Scan up each column tracking the last zero row seen.
+ ILADLR = 0
+ DO J = 1, N
+ I=M
+ DO WHILE((A(MAX(I,1),J).EQ.ZERO).AND.(I.GE.1))
+ I=I-1
+ ENDDO
+ ILADLR = MAX( ILADLR, I )
+ END DO
+ END IF
+ RETURN
+ END
diff --git a/lapack/ilaslc.f b/lapack/ilaslc.f
new file mode 100644
index 000000000..e3db0f4ae
--- /dev/null
+++ b/lapack/ilaslc.f
@@ -0,0 +1,118 @@
+*> \brief \b ILASLC
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download ILASLC + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/ilaslc.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/ilaslc.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ilaslc.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* INTEGER FUNCTION ILASLC( M, N, A, LDA )
+*
+* .. Scalar Arguments ..
+* INTEGER M, N, LDA
+* ..
+* .. Array Arguments ..
+* REAL A( LDA, * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> ILASLC scans A for its last non-zero column.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] M
+*> \verbatim
+*> M is INTEGER
+*> The number of rows of the matrix A.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The number of columns of the matrix A.
+*> \endverbatim
+*>
+*> \param[in] A
+*> \verbatim
+*> A is REAL array, dimension (LDA,N)
+*> The m by n matrix A.
+*> \endverbatim
+*>
+*> \param[in] LDA
+*> \verbatim
+*> LDA is INTEGER
+*> The leading dimension of the array A. LDA >= max(1,M).
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup realOTHERauxiliary
+*
+* =====================================================================
+ INTEGER FUNCTION ILASLC( M, N, A, LDA )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ INTEGER M, N, LDA
+* ..
+* .. Array Arguments ..
+ REAL A( LDA, * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ REAL ZERO
+ PARAMETER ( ZERO = 0.0D+0 )
+* ..
+* .. Local Scalars ..
+ INTEGER I
+* ..
+* .. Executable Statements ..
+*
+* Quick test for the common case where one corner is non-zero.
+ IF( N.EQ.0 ) THEN
+ ILASLC = N
+ ELSE IF( A(1, N).NE.ZERO .OR. A(M, N).NE.ZERO ) THEN
+ ILASLC = N
+ ELSE
+* Now scan each column from the end, returning with the first non-zero.
+ DO ILASLC = N, 1, -1
+ DO I = 1, M
+ IF( A(I, ILASLC).NE.ZERO ) RETURN
+ END DO
+ END DO
+ END IF
+ RETURN
+ END
diff --git a/lapack/ilaslr.f b/lapack/ilaslr.f
new file mode 100644
index 000000000..48b73f44d
--- /dev/null
+++ b/lapack/ilaslr.f
@@ -0,0 +1,121 @@
+*> \brief \b ILASLR
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download ILASLR + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/ilaslr.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/ilaslr.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ilaslr.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* INTEGER FUNCTION ILASLR( M, N, A, LDA )
+*
+* .. Scalar Arguments ..
+* INTEGER M, N, LDA
+* ..
+* .. Array Arguments ..
+* REAL A( LDA, * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> ILASLR scans A for its last non-zero row.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] M
+*> \verbatim
+*> M is INTEGER
+*> The number of rows of the matrix A.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The number of columns of the matrix A.
+*> \endverbatim
+*>
+*> \param[in] A
+*> \verbatim
+*> A is REAL array, dimension (LDA,N)
+*> The m by n matrix A.
+*> \endverbatim
+*>
+*> \param[in] LDA
+*> \verbatim
+*> LDA is INTEGER
+*> The leading dimension of the array A. LDA >= max(1,M).
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date April 2012
+*
+*> \ingroup realOTHERauxiliary
+*
+* =====================================================================
+ INTEGER FUNCTION ILASLR( M, N, A, LDA )
+*
+* -- LAPACK auxiliary routine (version 3.4.1) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* April 2012
+*
+* .. Scalar Arguments ..
+ INTEGER M, N, LDA
+* ..
+* .. Array Arguments ..
+ REAL A( LDA, * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ REAL ZERO
+ PARAMETER ( ZERO = 0.0E+0 )
+* ..
+* .. Local Scalars ..
+ INTEGER I, J
+* ..
+* .. Executable Statements ..
+*
+* Quick test for the common case where one corner is non-zero.
+ IF( M.EQ.0 ) THEN
+ ILASLR = M
+ ELSEIF( A(M, 1).NE.ZERO .OR. A(M, N).NE.ZERO ) THEN
+ ILASLR = M
+ ELSE
+* Scan up each column tracking the last zero row seen.
+ ILASLR = 0
+ DO J = 1, N
+ I=M
+ DO WHILE((A(MAX(I,1),J).EQ.ZERO).AND.(I.GE.1))
+ I=I-1
+ ENDDO
+ ILASLR = MAX( ILASLR, I )
+ END DO
+ END IF
+ RETURN
+ END
diff --git a/lapack/ilazlc.f b/lapack/ilazlc.f
new file mode 100644
index 000000000..15b149022
--- /dev/null
+++ b/lapack/ilazlc.f
@@ -0,0 +1,118 @@
+*> \brief \b ILAZLC
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download ILAZLC + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/ilazlc.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/ilazlc.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ilazlc.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* INTEGER FUNCTION ILAZLC( M, N, A, LDA )
+*
+* .. Scalar Arguments ..
+* INTEGER M, N, LDA
+* ..
+* .. Array Arguments ..
+* COMPLEX*16 A( LDA, * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> ILAZLC scans A for its last non-zero column.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] M
+*> \verbatim
+*> M is INTEGER
+*> The number of rows of the matrix A.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The number of columns of the matrix A.
+*> \endverbatim
+*>
+*> \param[in] A
+*> \verbatim
+*> A is COMPLEX*16 array, dimension (LDA,N)
+*> The m by n matrix A.
+*> \endverbatim
+*>
+*> \param[in] LDA
+*> \verbatim
+*> LDA is INTEGER
+*> The leading dimension of the array A. LDA >= max(1,M).
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup complex16OTHERauxiliary
+*
+* =====================================================================
+ INTEGER FUNCTION ILAZLC( M, N, A, LDA )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ INTEGER M, N, LDA
+* ..
+* .. Array Arguments ..
+ COMPLEX*16 A( LDA, * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ COMPLEX*16 ZERO
+ PARAMETER ( ZERO = (0.0D+0, 0.0D+0) )
+* ..
+* .. Local Scalars ..
+ INTEGER I
+* ..
+* .. Executable Statements ..
+*
+* Quick test for the common case where one corner is non-zero.
+ IF( N.EQ.0 ) THEN
+ ILAZLC = N
+ ELSE IF( A(1, N).NE.ZERO .OR. A(M, N).NE.ZERO ) THEN
+ ILAZLC = N
+ ELSE
+* Now scan each column from the end, returning with the first non-zero.
+ DO ILAZLC = N, 1, -1
+ DO I = 1, M
+ IF( A(I, ILAZLC).NE.ZERO ) RETURN
+ END DO
+ END DO
+ END IF
+ RETURN
+ END
diff --git a/lapack/ilazlr.f b/lapack/ilazlr.f
new file mode 100644
index 000000000..b2ab943ca
--- /dev/null
+++ b/lapack/ilazlr.f
@@ -0,0 +1,121 @@
+*> \brief \b ILAZLR
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download ILAZLR + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/ilazlr.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/ilazlr.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ilazlr.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* INTEGER FUNCTION ILAZLR( M, N, A, LDA )
+*
+* .. Scalar Arguments ..
+* INTEGER M, N, LDA
+* ..
+* .. Array Arguments ..
+* COMPLEX*16 A( LDA, * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> ILAZLR scans A for its last non-zero row.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] M
+*> \verbatim
+*> M is INTEGER
+*> The number of rows of the matrix A.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The number of columns of the matrix A.
+*> \endverbatim
+*>
+*> \param[in] A
+*> \verbatim
+*> A is COMPLEX*16 array, dimension (LDA,N)
+*> The m by n matrix A.
+*> \endverbatim
+*>
+*> \param[in] LDA
+*> \verbatim
+*> LDA is INTEGER
+*> The leading dimension of the array A. LDA >= max(1,M).
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date April 2012
+*
+*> \ingroup complex16OTHERauxiliary
+*
+* =====================================================================
+ INTEGER FUNCTION ILAZLR( M, N, A, LDA )
+*
+* -- LAPACK auxiliary routine (version 3.4.1) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* April 2012
+*
+* .. Scalar Arguments ..
+ INTEGER M, N, LDA
+* ..
+* .. Array Arguments ..
+ COMPLEX*16 A( LDA, * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ COMPLEX*16 ZERO
+ PARAMETER ( ZERO = (0.0D+0, 0.0D+0) )
+* ..
+* .. Local Scalars ..
+ INTEGER I, J
+* ..
+* .. Executable Statements ..
+*
+* Quick test for the common case where one corner is non-zero.
+ IF( M.EQ.0 ) THEN
+ ILAZLR = M
+ ELSE IF( A(M, 1).NE.ZERO .OR. A(M, N).NE.ZERO ) THEN
+ ILAZLR = M
+ ELSE
+* Scan up each column tracking the last zero row seen.
+ ILAZLR = 0
+ DO J = 1, N
+ I=M
+ DO WHILE((A(MAX(I,1),J).EQ.ZERO).AND.(I.GE.1))
+ I=I-1
+ ENDDO
+ ILAZLR = MAX( ILAZLR, I )
+ END DO
+ END IF
+ RETURN
+ END
diff --git a/lapack/lu.cpp b/lapack/lu.cpp
index 311511674..90cebe0f4 100644
--- a/lapack/lu.cpp
+++ b/lapack/lu.cpp
@@ -28,8 +28,8 @@ EIGEN_LAPACK_FUNC(getrf,(int *m, int *n, RealScalar *pa, int *lda, int *ipiv, in
Scalar* a = reinterpret_cast<Scalar*>(pa);
int nb_transpositions;
- int ret = Eigen::internal::partial_lu_impl<Scalar,ColMajor,int>
- ::blocked_lu(*m, *n, a, *lda, ipiv, nb_transpositions);
+ int ret = int(Eigen::internal::partial_lu_impl<Scalar,ColMajor,int>
+ ::blocked_lu(*m, *n, a, *lda, ipiv, nb_transpositions));
for(int i=0; i<std::min(*m,*n); ++i)
ipiv[i]++;
diff --git a/lapack/second_NONE.f b/lapack/second_NONE.f
new file mode 100644
index 000000000..d3e6d3319
--- /dev/null
+++ b/lapack/second_NONE.f
@@ -0,0 +1,52 @@
+*> \brief \b SECOND returns nothing
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+* Definition:
+* ===========
+*
+* REAL FUNCTION SECOND( )
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> SECOND returns nothing instead of returning the user time for a process in seconds.
+*> If you are using that routine, it means that neither EXTERNAL ETIME,
+*> EXTERNAL ETIME_, INTERNAL ETIME, INTERNAL CPU_TIME is available on
+*> your machine.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup auxOTHERauxiliary
+*
+* =====================================================================
+ REAL FUNCTION SECOND( )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* =====================================================================
+*
+ SECOND = 0.0E+0
+ RETURN
+*
+* End of SECOND
+*
+ END
diff --git a/lapack/sladiv.f b/lapack/sladiv.f
new file mode 100644
index 000000000..da3afa36b
--- /dev/null
+++ b/lapack/sladiv.f
@@ -0,0 +1,128 @@
+*> \brief \b SLADIV
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download SLADIV + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/sladiv.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/sladiv.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sladiv.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE SLADIV( A, B, C, D, P, Q )
+*
+* .. Scalar Arguments ..
+* REAL A, B, C, D, P, Q
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> SLADIV performs complex division in real arithmetic
+*>
+*> a + i*b
+*> p + i*q = ---------
+*> c + i*d
+*>
+*> The algorithm is due to Robert L. Smith and can be found
+*> in D. Knuth, The art of Computer Programming, Vol.2, p.195
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] A
+*> \verbatim
+*> A is REAL
+*> \endverbatim
+*>
+*> \param[in] B
+*> \verbatim
+*> B is REAL
+*> \endverbatim
+*>
+*> \param[in] C
+*> \verbatim
+*> C is REAL
+*> \endverbatim
+*>
+*> \param[in] D
+*> \verbatim
+*> D is REAL
+*> The scalars a, b, c, and d in the above expression.
+*> \endverbatim
+*>
+*> \param[out] P
+*> \verbatim
+*> P is REAL
+*> \endverbatim
+*>
+*> \param[out] Q
+*> \verbatim
+*> Q is REAL
+*> The scalars p and q in the above expression.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup auxOTHERauxiliary
+*
+* =====================================================================
+ SUBROUTINE SLADIV( A, B, C, D, P, Q )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ REAL A, B, C, D, P, Q
+* ..
+*
+* =====================================================================
+*
+* .. Local Scalars ..
+ REAL E, F
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC ABS
+* ..
+* .. Executable Statements ..
+*
+ IF( ABS( D ).LT.ABS( C ) ) THEN
+ E = D / C
+ F = C + D*E
+ P = ( A+B*E ) / F
+ Q = ( B-A*E ) / F
+ ELSE
+ E = C / D
+ F = D + C*E
+ P = ( B+A*E ) / F
+ Q = ( -A+B*E ) / F
+ END IF
+*
+ RETURN
+*
+* End of SLADIV
+*
+ END
diff --git a/lapack/slamch.f b/lapack/slamch.f
new file mode 100644
index 000000000..4bffad0eb
--- /dev/null
+++ b/lapack/slamch.f
@@ -0,0 +1,192 @@
+*> \brief \b SLAMCH
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+* Definition:
+* ===========
+*
+* REAL FUNCTION SLAMCH( CMACH )
+*
+* .. Scalar Arguments ..
+* CHARACTER CMACH
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> SLAMCH determines single precision machine parameters.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] CMACH
+*> \verbatim
+*> Specifies the value to be returned by SLAMCH:
+*> = 'E' or 'e', SLAMCH := eps
+*> = 'S' or 's , SLAMCH := sfmin
+*> = 'B' or 'b', SLAMCH := base
+*> = 'P' or 'p', SLAMCH := eps*base
+*> = 'N' or 'n', SLAMCH := t
+*> = 'R' or 'r', SLAMCH := rnd
+*> = 'M' or 'm', SLAMCH := emin
+*> = 'U' or 'u', SLAMCH := rmin
+*> = 'L' or 'l', SLAMCH := emax
+*> = 'O' or 'o', SLAMCH := rmax
+*> where
+*> eps = relative machine precision
+*> sfmin = safe minimum, such that 1/sfmin does not overflow
+*> base = base of the machine
+*> prec = eps*base
+*> t = number of (base) digits in the mantissa
+*> rnd = 1.0 when rounding occurs in addition, 0.0 otherwise
+*> emin = minimum exponent before (gradual) underflow
+*> rmin = underflow threshold - base**(emin-1)
+*> emax = largest exponent before overflow
+*> rmax = overflow threshold - (base**emax)*(1-eps)
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup auxOTHERauxiliary
+*
+* =====================================================================
+ REAL FUNCTION SLAMCH( CMACH )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ CHARACTER CMACH
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ REAL ONE, ZERO
+ PARAMETER ( ONE = 1.0E+0, ZERO = 0.0E+0 )
+* ..
+* .. Local Scalars ..
+ REAL RND, EPS, SFMIN, SMALL, RMACH
+* ..
+* .. External Functions ..
+ LOGICAL LSAME
+ EXTERNAL LSAME
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC DIGITS, EPSILON, HUGE, MAXEXPONENT,
+ $ MINEXPONENT, RADIX, TINY
+* ..
+* .. Executable Statements ..
+*
+*
+* Assume rounding, not chopping. Always.
+*
+ RND = ONE
+*
+ IF( ONE.EQ.RND ) THEN
+ EPS = EPSILON(ZERO) * 0.5
+ ELSE
+ EPS = EPSILON(ZERO)
+ END IF
+*
+ IF( LSAME( CMACH, 'E' ) ) THEN
+ RMACH = EPS
+ ELSE IF( LSAME( CMACH, 'S' ) ) THEN
+ SFMIN = TINY(ZERO)
+ SMALL = ONE / HUGE(ZERO)
+ IF( SMALL.GE.SFMIN ) THEN
+*
+* Use SMALL plus a bit, to avoid the possibility of rounding
+* causing overflow when computing 1/sfmin.
+*
+ SFMIN = SMALL*( ONE+EPS )
+ END IF
+ RMACH = SFMIN
+ ELSE IF( LSAME( CMACH, 'B' ) ) THEN
+ RMACH = RADIX(ZERO)
+ ELSE IF( LSAME( CMACH, 'P' ) ) THEN
+ RMACH = EPS * RADIX(ZERO)
+ ELSE IF( LSAME( CMACH, 'N' ) ) THEN
+ RMACH = DIGITS(ZERO)
+ ELSE IF( LSAME( CMACH, 'R' ) ) THEN
+ RMACH = RND
+ ELSE IF( LSAME( CMACH, 'M' ) ) THEN
+ RMACH = MINEXPONENT(ZERO)
+ ELSE IF( LSAME( CMACH, 'U' ) ) THEN
+ RMACH = tiny(zero)
+ ELSE IF( LSAME( CMACH, 'L' ) ) THEN
+ RMACH = MAXEXPONENT(ZERO)
+ ELSE IF( LSAME( CMACH, 'O' ) ) THEN
+ RMACH = HUGE(ZERO)
+ ELSE
+ RMACH = ZERO
+ END IF
+*
+ SLAMCH = RMACH
+ RETURN
+*
+* End of SLAMCH
+*
+ END
+************************************************************************
+*> \brief \b SLAMC3
+*> \details
+*> \b Purpose:
+*> \verbatim
+*> SLAMC3 is intended to force A and B to be stored prior to doing
+*> the addition of A and B , for use in situations where optimizers
+*> might hold one of these in a register.
+*> \endverbatim
+*> \author LAPACK is a software package provided by Univ. of Tennessee, Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..
+*> \date November 2011
+*> \ingroup auxOTHERauxiliary
+*>
+*> \param[in] A
+*> \verbatim
+*> \endverbatim
+*>
+*> \param[in] B
+*> \verbatim
+*> The values A and B.
+*> \endverbatim
+*>
+*
+ REAL FUNCTION SLAMC3( A, B )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
+* November 2010
+*
+* .. Scalar Arguments ..
+ REAL A, B
+* ..
+* =====================================================================
+*
+* .. Executable Statements ..
+*
+ SLAMC3 = A + B
+*
+ RETURN
+*
+* End of SLAMC3
+*
+ END
+*
+************************************************************************
diff --git a/lapack/slapy2.f b/lapack/slapy2.f
new file mode 100644
index 000000000..1f6b1ca4f
--- /dev/null
+++ b/lapack/slapy2.f
@@ -0,0 +1,104 @@
+*> \brief \b SLAPY2
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download SLAPY2 + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/slapy2.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/slapy2.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slapy2.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* REAL FUNCTION SLAPY2( X, Y )
+*
+* .. Scalar Arguments ..
+* REAL X, Y
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> SLAPY2 returns sqrt(x**2+y**2), taking care not to cause unnecessary
+*> overflow.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] X
+*> \verbatim
+*> X is REAL
+*> \endverbatim
+*>
+*> \param[in] Y
+*> \verbatim
+*> Y is REAL
+*> X and Y specify the values x and y.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup auxOTHERauxiliary
+*
+* =====================================================================
+ REAL FUNCTION SLAPY2( X, Y )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ REAL X, Y
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ REAL ZERO
+ PARAMETER ( ZERO = 0.0E0 )
+ REAL ONE
+ PARAMETER ( ONE = 1.0E0 )
+* ..
+* .. Local Scalars ..
+ REAL W, XABS, YABS, Z
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC ABS, MAX, MIN, SQRT
+* ..
+* .. Executable Statements ..
+*
+ XABS = ABS( X )
+ YABS = ABS( Y )
+ W = MAX( XABS, YABS )
+ Z = MIN( XABS, YABS )
+ IF( Z.EQ.ZERO ) THEN
+ SLAPY2 = W
+ ELSE
+ SLAPY2 = W*SQRT( ONE+( Z / W )**2 )
+ END IF
+ RETURN
+*
+* End of SLAPY2
+*
+ END
diff --git a/lapack/slapy3.f b/lapack/slapy3.f
new file mode 100644
index 000000000..aa2f5bfc4
--- /dev/null
+++ b/lapack/slapy3.f
@@ -0,0 +1,111 @@
+*> \brief \b SLAPY3
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download SLAPY3 + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/slapy3.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/slapy3.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slapy3.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* REAL FUNCTION SLAPY3( X, Y, Z )
+*
+* .. Scalar Arguments ..
+* REAL X, Y, Z
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> SLAPY3 returns sqrt(x**2+y**2+z**2), taking care not to cause
+*> unnecessary overflow.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] X
+*> \verbatim
+*> X is REAL
+*> \endverbatim
+*>
+*> \param[in] Y
+*> \verbatim
+*> Y is REAL
+*> \endverbatim
+*>
+*> \param[in] Z
+*> \verbatim
+*> Z is REAL
+*> X, Y and Z specify the values x, y and z.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup auxOTHERauxiliary
+*
+* =====================================================================
+ REAL FUNCTION SLAPY3( X, Y, Z )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ REAL X, Y, Z
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ REAL ZERO
+ PARAMETER ( ZERO = 0.0E0 )
+* ..
+* .. Local Scalars ..
+ REAL W, XABS, YABS, ZABS
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC ABS, MAX, SQRT
+* ..
+* .. Executable Statements ..
+*
+ XABS = ABS( X )
+ YABS = ABS( Y )
+ ZABS = ABS( Z )
+ W = MAX( XABS, YABS, ZABS )
+ IF( W.EQ.ZERO ) THEN
+* W can be zero for max(0,nan,0)
+* adding all three entries together will make sure
+* NaN will not disappear.
+ SLAPY3 = XABS + YABS + ZABS
+ ELSE
+ SLAPY3 = W*SQRT( ( XABS / W )**2+( YABS / W )**2+
+ $ ( ZABS / W )**2 )
+ END IF
+ RETURN
+*
+* End of SLAPY3
+*
+ END
diff --git a/lapack/slarf.f b/lapack/slarf.f
new file mode 100644
index 000000000..8a8ff308e
--- /dev/null
+++ b/lapack/slarf.f
@@ -0,0 +1,227 @@
+*> \brief \b SLARF
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download SLARF + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/slarf.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/slarf.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slarf.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE SLARF( SIDE, M, N, V, INCV, TAU, C, LDC, WORK )
+*
+* .. Scalar Arguments ..
+* CHARACTER SIDE
+* INTEGER INCV, LDC, M, N
+* REAL TAU
+* ..
+* .. Array Arguments ..
+* REAL C( LDC, * ), V( * ), WORK( * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> SLARF applies a real elementary reflector H to a real m by n matrix
+*> C, from either the left or the right. H is represented in the form
+*>
+*> H = I - tau * v * v**T
+*>
+*> where tau is a real scalar and v is a real vector.
+*>
+*> If tau = 0, then H is taken to be the unit matrix.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] SIDE
+*> \verbatim
+*> SIDE is CHARACTER*1
+*> = 'L': form H * C
+*> = 'R': form C * H
+*> \endverbatim
+*>
+*> \param[in] M
+*> \verbatim
+*> M is INTEGER
+*> The number of rows of the matrix C.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The number of columns of the matrix C.
+*> \endverbatim
+*>
+*> \param[in] V
+*> \verbatim
+*> V is REAL array, dimension
+*> (1 + (M-1)*abs(INCV)) if SIDE = 'L'
+*> or (1 + (N-1)*abs(INCV)) if SIDE = 'R'
+*> The vector v in the representation of H. V is not used if
+*> TAU = 0.
+*> \endverbatim
+*>
+*> \param[in] INCV
+*> \verbatim
+*> INCV is INTEGER
+*> The increment between elements of v. INCV <> 0.
+*> \endverbatim
+*>
+*> \param[in] TAU
+*> \verbatim
+*> TAU is REAL
+*> The value tau in the representation of H.
+*> \endverbatim
+*>
+*> \param[in,out] C
+*> \verbatim
+*> C is REAL array, dimension (LDC,N)
+*> On entry, the m by n matrix C.
+*> On exit, C is overwritten by the matrix H * C if SIDE = 'L',
+*> or C * H if SIDE = 'R'.
+*> \endverbatim
+*>
+*> \param[in] LDC
+*> \verbatim
+*> LDC is INTEGER
+*> The leading dimension of the array C. LDC >= max(1,M).
+*> \endverbatim
+*>
+*> \param[out] WORK
+*> \verbatim
+*> WORK is REAL array, dimension
+*> (N) if SIDE = 'L'
+*> or (M) if SIDE = 'R'
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup realOTHERauxiliary
+*
+* =====================================================================
+ SUBROUTINE SLARF( SIDE, M, N, V, INCV, TAU, C, LDC, WORK )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ CHARACTER SIDE
+ INTEGER INCV, LDC, M, N
+ REAL TAU
+* ..
+* .. Array Arguments ..
+ REAL C( LDC, * ), V( * ), WORK( * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ REAL ONE, ZERO
+ PARAMETER ( ONE = 1.0E+0, ZERO = 0.0E+0 )
+* ..
+* .. Local Scalars ..
+ LOGICAL APPLYLEFT
+ INTEGER I, LASTV, LASTC
+* ..
+* .. External Subroutines ..
+ EXTERNAL SGEMV, SGER
+* ..
+* .. External Functions ..
+ LOGICAL LSAME
+ INTEGER ILASLR, ILASLC
+ EXTERNAL LSAME, ILASLR, ILASLC
+* ..
+* .. Executable Statements ..
+*
+ APPLYLEFT = LSAME( SIDE, 'L' )
+ LASTV = 0
+ LASTC = 0
+ IF( TAU.NE.ZERO ) THEN
+! Set up variables for scanning V. LASTV begins pointing to the end
+! of V.
+ IF( APPLYLEFT ) THEN
+ LASTV = M
+ ELSE
+ LASTV = N
+ END IF
+ IF( INCV.GT.0 ) THEN
+ I = 1 + (LASTV-1) * INCV
+ ELSE
+ I = 1
+ END IF
+! Look for the last non-zero row in V.
+ DO WHILE( LASTV.GT.0 .AND. V( I ).EQ.ZERO )
+ LASTV = LASTV - 1
+ I = I - INCV
+ END DO
+ IF( APPLYLEFT ) THEN
+! Scan for the last non-zero column in C(1:lastv,:).
+ LASTC = ILASLC(LASTV, N, C, LDC)
+ ELSE
+! Scan for the last non-zero row in C(:,1:lastv).
+ LASTC = ILASLR(M, LASTV, C, LDC)
+ END IF
+ END IF
+! Note that lastc.eq.0 renders the BLAS operations null; no special
+! case is needed at this level.
+ IF( APPLYLEFT ) THEN
+*
+* Form H * C
+*
+ IF( LASTV.GT.0 ) THEN
+*
+* w(1:lastc,1) := C(1:lastv,1:lastc)**T * v(1:lastv,1)
+*
+ CALL SGEMV( 'Transpose', LASTV, LASTC, ONE, C, LDC, V, INCV,
+ $ ZERO, WORK, 1 )
+*
+* C(1:lastv,1:lastc) := C(...) - v(1:lastv,1) * w(1:lastc,1)**T
+*
+ CALL SGER( LASTV, LASTC, -TAU, V, INCV, WORK, 1, C, LDC )
+ END IF
+ ELSE
+*
+* Form C * H
+*
+ IF( LASTV.GT.0 ) THEN
+*
+* w(1:lastc,1) := C(1:lastc,1:lastv) * v(1:lastv,1)
+*
+ CALL SGEMV( 'No transpose', LASTC, LASTV, ONE, C, LDC,
+ $ V, INCV, ZERO, WORK, 1 )
+*
+* C(1:lastc,1:lastv) := C(...) - w(1:lastc,1) * v(1:lastv,1)**T
+*
+ CALL SGER( LASTC, LASTV, -TAU, WORK, 1, V, INCV, C, LDC )
+ END IF
+ END IF
+ RETURN
+*
+* End of SLARF
+*
+ END
diff --git a/lapack/slarfb.f b/lapack/slarfb.f
new file mode 100644
index 000000000..eb95990b3
--- /dev/null
+++ b/lapack/slarfb.f
@@ -0,0 +1,763 @@
+*> \brief \b SLARFB
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download SLARFB + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/slarfb.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/slarfb.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slarfb.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE SLARFB( SIDE, TRANS, DIRECT, STOREV, M, N, K, V, LDV,
+* T, LDT, C, LDC, WORK, LDWORK )
+*
+* .. Scalar Arguments ..
+* CHARACTER DIRECT, SIDE, STOREV, TRANS
+* INTEGER K, LDC, LDT, LDV, LDWORK, M, N
+* ..
+* .. Array Arguments ..
+* REAL C( LDC, * ), T( LDT, * ), V( LDV, * ),
+* $ WORK( LDWORK, * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> SLARFB applies a real block reflector H or its transpose H**T to a
+*> real m by n matrix C, from either the left or the right.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] SIDE
+*> \verbatim
+*> SIDE is CHARACTER*1
+*> = 'L': apply H or H**T from the Left
+*> = 'R': apply H or H**T from the Right
+*> \endverbatim
+*>
+*> \param[in] TRANS
+*> \verbatim
+*> TRANS is CHARACTER*1
+*> = 'N': apply H (No transpose)
+*> = 'T': apply H**T (Transpose)
+*> \endverbatim
+*>
+*> \param[in] DIRECT
+*> \verbatim
+*> DIRECT is CHARACTER*1
+*> Indicates how H is formed from a product of elementary
+*> reflectors
+*> = 'F': H = H(1) H(2) . . . H(k) (Forward)
+*> = 'B': H = H(k) . . . H(2) H(1) (Backward)
+*> \endverbatim
+*>
+*> \param[in] STOREV
+*> \verbatim
+*> STOREV is CHARACTER*1
+*> Indicates how the vectors which define the elementary
+*> reflectors are stored:
+*> = 'C': Columnwise
+*> = 'R': Rowwise
+*> \endverbatim
+*>
+*> \param[in] M
+*> \verbatim
+*> M is INTEGER
+*> The number of rows of the matrix C.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The number of columns of the matrix C.
+*> \endverbatim
+*>
+*> \param[in] K
+*> \verbatim
+*> K is INTEGER
+*> The order of the matrix T (= the number of elementary
+*> reflectors whose product defines the block reflector).
+*> \endverbatim
+*>
+*> \param[in] V
+*> \verbatim
+*> V is REAL array, dimension
+*> (LDV,K) if STOREV = 'C'
+*> (LDV,M) if STOREV = 'R' and SIDE = 'L'
+*> (LDV,N) if STOREV = 'R' and SIDE = 'R'
+*> The matrix V. See Further Details.
+*> \endverbatim
+*>
+*> \param[in] LDV
+*> \verbatim
+*> LDV is INTEGER
+*> The leading dimension of the array V.
+*> If STOREV = 'C' and SIDE = 'L', LDV >= max(1,M);
+*> if STOREV = 'C' and SIDE = 'R', LDV >= max(1,N);
+*> if STOREV = 'R', LDV >= K.
+*> \endverbatim
+*>
+*> \param[in] T
+*> \verbatim
+*> T is REAL array, dimension (LDT,K)
+*> The triangular k by k matrix T in the representation of the
+*> block reflector.
+*> \endverbatim
+*>
+*> \param[in] LDT
+*> \verbatim
+*> LDT is INTEGER
+*> The leading dimension of the array T. LDT >= K.
+*> \endverbatim
+*>
+*> \param[in,out] C
+*> \verbatim
+*> C is REAL array, dimension (LDC,N)
+*> On entry, the m by n matrix C.
+*> On exit, C is overwritten by H*C or H**T*C or C*H or C*H**T.
+*> \endverbatim
+*>
+*> \param[in] LDC
+*> \verbatim
+*> LDC is INTEGER
+*> The leading dimension of the array C. LDC >= max(1,M).
+*> \endverbatim
+*>
+*> \param[out] WORK
+*> \verbatim
+*> WORK is REAL array, dimension (LDWORK,K)
+*> \endverbatim
+*>
+*> \param[in] LDWORK
+*> \verbatim
+*> LDWORK is INTEGER
+*> The leading dimension of the array WORK.
+*> If SIDE = 'L', LDWORK >= max(1,N);
+*> if SIDE = 'R', LDWORK >= max(1,M).
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup realOTHERauxiliary
+*
+*> \par Further Details:
+* =====================
+*>
+*> \verbatim
+*>
+*> The shape of the matrix V and the storage of the vectors which define
+*> the H(i) is best illustrated by the following example with n = 5 and
+*> k = 3. The elements equal to 1 are not stored; the corresponding
+*> array elements are modified but restored on exit. The rest of the
+*> array is not used.
+*>
+*> DIRECT = 'F' and STOREV = 'C': DIRECT = 'F' and STOREV = 'R':
+*>
+*> V = ( 1 ) V = ( 1 v1 v1 v1 v1 )
+*> ( v1 1 ) ( 1 v2 v2 v2 )
+*> ( v1 v2 1 ) ( 1 v3 v3 )
+*> ( v1 v2 v3 )
+*> ( v1 v2 v3 )
+*>
+*> DIRECT = 'B' and STOREV = 'C': DIRECT = 'B' and STOREV = 'R':
+*>
+*> V = ( v1 v2 v3 ) V = ( v1 v1 1 )
+*> ( v1 v2 v3 ) ( v2 v2 v2 1 )
+*> ( 1 v2 v3 ) ( v3 v3 v3 v3 1 )
+*> ( 1 v3 )
+*> ( 1 )
+*> \endverbatim
+*>
+* =====================================================================
+ SUBROUTINE SLARFB( SIDE, TRANS, DIRECT, STOREV, M, N, K, V, LDV,
+ $ T, LDT, C, LDC, WORK, LDWORK )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ CHARACTER DIRECT, SIDE, STOREV, TRANS
+ INTEGER K, LDC, LDT, LDV, LDWORK, M, N
+* ..
+* .. Array Arguments ..
+ REAL C( LDC, * ), T( LDT, * ), V( LDV, * ),
+ $ WORK( LDWORK, * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ REAL ONE
+ PARAMETER ( ONE = 1.0E+0 )
+* ..
+* .. Local Scalars ..
+ CHARACTER TRANST
+ INTEGER I, J, LASTV, LASTC
+* ..
+* .. External Functions ..
+ LOGICAL LSAME
+ INTEGER ILASLR, ILASLC
+ EXTERNAL LSAME, ILASLR, ILASLC
+* ..
+* .. External Subroutines ..
+ EXTERNAL SCOPY, SGEMM, STRMM
+* ..
+* .. Executable Statements ..
+*
+* Quick return if possible
+*
+ IF( M.LE.0 .OR. N.LE.0 )
+ $ RETURN
+*
+ IF( LSAME( TRANS, 'N' ) ) THEN
+ TRANST = 'T'
+ ELSE
+ TRANST = 'N'
+ END IF
+*
+ IF( LSAME( STOREV, 'C' ) ) THEN
+*
+ IF( LSAME( DIRECT, 'F' ) ) THEN
+*
+* Let V = ( V1 ) (first K rows)
+* ( V2 )
+* where V1 is unit lower triangular.
+*
+ IF( LSAME( SIDE, 'L' ) ) THEN
+*
+* Form H * C or H**T * C where C = ( C1 )
+* ( C2 )
+*
+ LASTV = MAX( K, ILASLR( M, K, V, LDV ) )
+ LASTC = ILASLC( LASTV, N, C, LDC )
+*
+* W := C**T * V = (C1**T * V1 + C2**T * V2) (stored in WORK)
+*
+* W := C1**T
+*
+ DO 10 J = 1, K
+ CALL SCOPY( LASTC, C( J, 1 ), LDC, WORK( 1, J ), 1 )
+ 10 CONTINUE
+*
+* W := W * V1
+*
+ CALL STRMM( 'Right', 'Lower', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C2**T *V2
+*
+ CALL SGEMM( 'Transpose', 'No transpose',
+ $ LASTC, K, LASTV-K,
+ $ ONE, C( K+1, 1 ), LDC, V( K+1, 1 ), LDV,
+ $ ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T**T or W * T
+*
+ CALL STRMM( 'Right', 'Upper', TRANST, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - V * W**T
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C2 := C2 - V2 * W**T
+*
+ CALL SGEMM( 'No transpose', 'Transpose',
+ $ LASTV-K, LASTC, K,
+ $ -ONE, V( K+1, 1 ), LDV, WORK, LDWORK, ONE,
+ $ C( K+1, 1 ), LDC )
+ END IF
+*
+* W := W * V1**T
+*
+ CALL STRMM( 'Right', 'Lower', 'Transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+*
+* C1 := C1 - W**T
+*
+ DO 30 J = 1, K
+ DO 20 I = 1, LASTC
+ C( J, I ) = C( J, I ) - WORK( I, J )
+ 20 CONTINUE
+ 30 CONTINUE
+*
+ ELSE IF( LSAME( SIDE, 'R' ) ) THEN
+*
+* Form C * H or C * H**T where C = ( C1 C2 )
+*
+ LASTV = MAX( K, ILASLR( N, K, V, LDV ) )
+ LASTC = ILASLR( M, LASTV, C, LDC )
+*
+* W := C * V = (C1*V1 + C2*V2) (stored in WORK)
+*
+* W := C1
+*
+ DO 40 J = 1, K
+ CALL SCOPY( LASTC, C( 1, J ), 1, WORK( 1, J ), 1 )
+ 40 CONTINUE
+*
+* W := W * V1
+*
+ CALL STRMM( 'Right', 'Lower', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C2 * V2
+*
+ CALL SGEMM( 'No transpose', 'No transpose',
+ $ LASTC, K, LASTV-K,
+ $ ONE, C( 1, K+1 ), LDC, V( K+1, 1 ), LDV,
+ $ ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T or W * T**T
+*
+ CALL STRMM( 'Right', 'Upper', TRANS, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - W * V**T
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C2 := C2 - W * V2**T
+*
+ CALL SGEMM( 'No transpose', 'Transpose',
+ $ LASTC, LASTV-K, K,
+ $ -ONE, WORK, LDWORK, V( K+1, 1 ), LDV, ONE,
+ $ C( 1, K+1 ), LDC )
+ END IF
+*
+* W := W * V1**T
+*
+ CALL STRMM( 'Right', 'Lower', 'Transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+*
+* C1 := C1 - W
+*
+ DO 60 J = 1, K
+ DO 50 I = 1, LASTC
+ C( I, J ) = C( I, J ) - WORK( I, J )
+ 50 CONTINUE
+ 60 CONTINUE
+ END IF
+*
+ ELSE
+*
+* Let V = ( V1 )
+* ( V2 ) (last K rows)
+* where V2 is unit upper triangular.
+*
+ IF( LSAME( SIDE, 'L' ) ) THEN
+*
+* Form H * C or H**T * C where C = ( C1 )
+* ( C2 )
+*
+ LASTV = MAX( K, ILASLR( M, K, V, LDV ) )
+ LASTC = ILASLC( LASTV, N, C, LDC )
+*
+* W := C**T * V = (C1**T * V1 + C2**T * V2) (stored in WORK)
+*
+* W := C2**T
+*
+ DO 70 J = 1, K
+ CALL SCOPY( LASTC, C( LASTV-K+J, 1 ), LDC,
+ $ WORK( 1, J ), 1 )
+ 70 CONTINUE
+*
+* W := W * V2
+*
+ CALL STRMM( 'Right', 'Upper', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV,
+ $ WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C1**T*V1
+*
+ CALL SGEMM( 'Transpose', 'No transpose',
+ $ LASTC, K, LASTV-K, ONE, C, LDC, V, LDV,
+ $ ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T**T or W * T
+*
+ CALL STRMM( 'Right', 'Lower', TRANST, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - V * W**T
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C1 := C1 - V1 * W**T
+*
+ CALL SGEMM( 'No transpose', 'Transpose',
+ $ LASTV-K, LASTC, K, -ONE, V, LDV, WORK, LDWORK,
+ $ ONE, C, LDC )
+ END IF
+*
+* W := W * V2**T
+*
+ CALL STRMM( 'Right', 'Upper', 'Transpose', 'Unit',
+ $ LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV,
+ $ WORK, LDWORK )
+*
+* C2 := C2 - W**T
+*
+ DO 90 J = 1, K
+ DO 80 I = 1, LASTC
+ C( LASTV-K+J, I ) = C( LASTV-K+J, I ) - WORK(I, J)
+ 80 CONTINUE
+ 90 CONTINUE
+*
+ ELSE IF( LSAME( SIDE, 'R' ) ) THEN
+*
+* Form C * H or C * H**T where C = ( C1 C2 )
+*
+ LASTV = MAX( K, ILASLR( N, K, V, LDV ) )
+ LASTC = ILASLR( M, LASTV, C, LDC )
+*
+* W := C * V = (C1*V1 + C2*V2) (stored in WORK)
+*
+* W := C2
+*
+ DO 100 J = 1, K
+ CALL SCOPY( LASTC, C( 1, N-K+J ), 1, WORK( 1, J ), 1 )
+ 100 CONTINUE
+*
+* W := W * V2
+*
+ CALL STRMM( 'Right', 'Upper', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV,
+ $ WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C1 * V1
+*
+ CALL SGEMM( 'No transpose', 'No transpose',
+ $ LASTC, K, LASTV-K, ONE, C, LDC, V, LDV,
+ $ ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T or W * T**T
+*
+ CALL STRMM( 'Right', 'Lower', TRANS, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - W * V**T
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C1 := C1 - W * V1**T
+*
+ CALL SGEMM( 'No transpose', 'Transpose',
+ $ LASTC, LASTV-K, K, -ONE, WORK, LDWORK, V, LDV,
+ $ ONE, C, LDC )
+ END IF
+*
+* W := W * V2**T
+*
+ CALL STRMM( 'Right', 'Upper', 'Transpose', 'Unit',
+ $ LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV,
+ $ WORK, LDWORK )
+*
+* C2 := C2 - W
+*
+ DO 120 J = 1, K
+ DO 110 I = 1, LASTC
+ C( I, LASTV-K+J ) = C( I, LASTV-K+J ) - WORK(I, J)
+ 110 CONTINUE
+ 120 CONTINUE
+ END IF
+ END IF
+*
+ ELSE IF( LSAME( STOREV, 'R' ) ) THEN
+*
+ IF( LSAME( DIRECT, 'F' ) ) THEN
+*
+* Let V = ( V1 V2 ) (V1: first K columns)
+* where V1 is unit upper triangular.
+*
+ IF( LSAME( SIDE, 'L' ) ) THEN
+*
+* Form H * C or H**T * C where C = ( C1 )
+* ( C2 )
+*
+ LASTV = MAX( K, ILASLC( K, M, V, LDV ) )
+ LASTC = ILASLC( LASTV, N, C, LDC )
+*
+* W := C**T * V**T = (C1**T * V1**T + C2**T * V2**T) (stored in WORK)
+*
+* W := C1**T
+*
+ DO 130 J = 1, K
+ CALL SCOPY( LASTC, C( J, 1 ), LDC, WORK( 1, J ), 1 )
+ 130 CONTINUE
+*
+* W := W * V1**T
+*
+ CALL STRMM( 'Right', 'Upper', 'Transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C2**T*V2**T
+*
+ CALL SGEMM( 'Transpose', 'Transpose',
+ $ LASTC, K, LASTV-K,
+ $ ONE, C( K+1, 1 ), LDC, V( 1, K+1 ), LDV,
+ $ ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T**T or W * T
+*
+ CALL STRMM( 'Right', 'Upper', TRANST, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - V**T * W**T
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C2 := C2 - V2**T * W**T
+*
+ CALL SGEMM( 'Transpose', 'Transpose',
+ $ LASTV-K, LASTC, K,
+ $ -ONE, V( 1, K+1 ), LDV, WORK, LDWORK,
+ $ ONE, C( K+1, 1 ), LDC )
+ END IF
+*
+* W := W * V1
+*
+ CALL STRMM( 'Right', 'Upper', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+*
+* C1 := C1 - W**T
+*
+ DO 150 J = 1, K
+ DO 140 I = 1, LASTC
+ C( J, I ) = C( J, I ) - WORK( I, J )
+ 140 CONTINUE
+ 150 CONTINUE
+*
+ ELSE IF( LSAME( SIDE, 'R' ) ) THEN
+*
+* Form C * H or C * H**T where C = ( C1 C2 )
+*
+ LASTV = MAX( K, ILASLC( K, N, V, LDV ) )
+ LASTC = ILASLR( M, LASTV, C, LDC )
+*
+* W := C * V**T = (C1*V1**T + C2*V2**T) (stored in WORK)
+*
+* W := C1
+*
+ DO 160 J = 1, K
+ CALL SCOPY( LASTC, C( 1, J ), 1, WORK( 1, J ), 1 )
+ 160 CONTINUE
+*
+* W := W * V1**T
+*
+ CALL STRMM( 'Right', 'Upper', 'Transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C2 * V2**T
+*
+ CALL SGEMM( 'No transpose', 'Transpose',
+ $ LASTC, K, LASTV-K,
+ $ ONE, C( 1, K+1 ), LDC, V( 1, K+1 ), LDV,
+ $ ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T or W * T**T
+*
+ CALL STRMM( 'Right', 'Upper', TRANS, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - W * V
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C2 := C2 - W * V2
+*
+ CALL SGEMM( 'No transpose', 'No transpose',
+ $ LASTC, LASTV-K, K,
+ $ -ONE, WORK, LDWORK, V( 1, K+1 ), LDV,
+ $ ONE, C( 1, K+1 ), LDC )
+ END IF
+*
+* W := W * V1
+*
+ CALL STRMM( 'Right', 'Upper', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+*
+* C1 := C1 - W
+*
+ DO 180 J = 1, K
+ DO 170 I = 1, LASTC
+ C( I, J ) = C( I, J ) - WORK( I, J )
+ 170 CONTINUE
+ 180 CONTINUE
+*
+ END IF
+*
+ ELSE
+*
+* Let V = ( V1 V2 ) (V2: last K columns)
+* where V2 is unit lower triangular.
+*
+ IF( LSAME( SIDE, 'L' ) ) THEN
+*
+* Form H * C or H**T * C where C = ( C1 )
+* ( C2 )
+*
+ LASTV = MAX( K, ILASLC( K, M, V, LDV ) )
+ LASTC = ILASLC( LASTV, N, C, LDC )
+*
+* W := C**T * V**T = (C1**T * V1**T + C2**T * V2**T) (stored in WORK)
+*
+* W := C2**T
+*
+ DO 190 J = 1, K
+ CALL SCOPY( LASTC, C( LASTV-K+J, 1 ), LDC,
+ $ WORK( 1, J ), 1 )
+ 190 CONTINUE
+*
+* W := W * V2**T
+*
+ CALL STRMM( 'Right', 'Lower', 'Transpose', 'Unit',
+ $ LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV,
+ $ WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C1**T * V1**T
+*
+ CALL SGEMM( 'Transpose', 'Transpose',
+ $ LASTC, K, LASTV-K, ONE, C, LDC, V, LDV,
+ $ ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T**T or W * T
+*
+ CALL STRMM( 'Right', 'Lower', TRANST, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - V**T * W**T
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C1 := C1 - V1**T * W**T
+*
+ CALL SGEMM( 'Transpose', 'Transpose',
+ $ LASTV-K, LASTC, K, -ONE, V, LDV, WORK, LDWORK,
+ $ ONE, C, LDC )
+ END IF
+*
+* W := W * V2
+*
+ CALL STRMM( 'Right', 'Lower', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV,
+ $ WORK, LDWORK )
+*
+* C2 := C2 - W**T
+*
+ DO 210 J = 1, K
+ DO 200 I = 1, LASTC
+ C( LASTV-K+J, I ) = C( LASTV-K+J, I ) - WORK(I, J)
+ 200 CONTINUE
+ 210 CONTINUE
+*
+ ELSE IF( LSAME( SIDE, 'R' ) ) THEN
+*
+* Form C * H or C * H**T where C = ( C1 C2 )
+*
+ LASTV = MAX( K, ILASLC( K, N, V, LDV ) )
+ LASTC = ILASLR( M, LASTV, C, LDC )
+*
+* W := C * V**T = (C1*V1**T + C2*V2**T) (stored in WORK)
+*
+* W := C2
+*
+ DO 220 J = 1, K
+ CALL SCOPY( LASTC, C( 1, LASTV-K+J ), 1,
+ $ WORK( 1, J ), 1 )
+ 220 CONTINUE
+*
+* W := W * V2**T
+*
+ CALL STRMM( 'Right', 'Lower', 'Transpose', 'Unit',
+ $ LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV,
+ $ WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C1 * V1**T
+*
+ CALL SGEMM( 'No transpose', 'Transpose',
+ $ LASTC, K, LASTV-K, ONE, C, LDC, V, LDV,
+ $ ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T or W * T**T
+*
+ CALL STRMM( 'Right', 'Lower', TRANS, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - W * V
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C1 := C1 - W * V1
+*
+ CALL SGEMM( 'No transpose', 'No transpose',
+ $ LASTC, LASTV-K, K, -ONE, WORK, LDWORK, V, LDV,
+ $ ONE, C, LDC )
+ END IF
+*
+* W := W * V2
+*
+ CALL STRMM( 'Right', 'Lower', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV,
+ $ WORK, LDWORK )
+*
+* C1 := C1 - W
+*
+ DO 240 J = 1, K
+ DO 230 I = 1, LASTC
+ C( I, LASTV-K+J ) = C( I, LASTV-K+J )
+ $ - WORK( I, J )
+ 230 CONTINUE
+ 240 CONTINUE
+*
+ END IF
+*
+ END IF
+ END IF
+*
+ RETURN
+*
+* End of SLARFB
+*
+ END
diff --git a/lapack/slarfg.f b/lapack/slarfg.f
new file mode 100644
index 000000000..4f10ffcaf
--- /dev/null
+++ b/lapack/slarfg.f
@@ -0,0 +1,196 @@
+*> \brief \b SLARFG
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download SLARFG + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/slarfg.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/slarfg.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slarfg.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE SLARFG( N, ALPHA, X, INCX, TAU )
+*
+* .. Scalar Arguments ..
+* INTEGER INCX, N
+* REAL ALPHA, TAU
+* ..
+* .. Array Arguments ..
+* REAL X( * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> SLARFG generates a real elementary reflector H of order n, such
+*> that
+*>
+*> H * ( alpha ) = ( beta ), H**T * H = I.
+*> ( x ) ( 0 )
+*>
+*> where alpha and beta are scalars, and x is an (n-1)-element real
+*> vector. H is represented in the form
+*>
+*> H = I - tau * ( 1 ) * ( 1 v**T ) ,
+*> ( v )
+*>
+*> where tau is a real scalar and v is a real (n-1)-element
+*> vector.
+*>
+*> If the elements of x are all zero, then tau = 0 and H is taken to be
+*> the unit matrix.
+*>
+*> Otherwise 1 <= tau <= 2.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The order of the elementary reflector.
+*> \endverbatim
+*>
+*> \param[in,out] ALPHA
+*> \verbatim
+*> ALPHA is REAL
+*> On entry, the value alpha.
+*> On exit, it is overwritten with the value beta.
+*> \endverbatim
+*>
+*> \param[in,out] X
+*> \verbatim
+*> X is REAL array, dimension
+*> (1+(N-2)*abs(INCX))
+*> On entry, the vector x.
+*> On exit, it is overwritten with the vector v.
+*> \endverbatim
+*>
+*> \param[in] INCX
+*> \verbatim
+*> INCX is INTEGER
+*> The increment between elements of X. INCX > 0.
+*> \endverbatim
+*>
+*> \param[out] TAU
+*> \verbatim
+*> TAU is REAL
+*> The value tau.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup realOTHERauxiliary
+*
+* =====================================================================
+ SUBROUTINE SLARFG( N, ALPHA, X, INCX, TAU )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ INTEGER INCX, N
+ REAL ALPHA, TAU
+* ..
+* .. Array Arguments ..
+ REAL X( * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ REAL ONE, ZERO
+ PARAMETER ( ONE = 1.0E+0, ZERO = 0.0E+0 )
+* ..
+* .. Local Scalars ..
+ INTEGER J, KNT
+ REAL BETA, RSAFMN, SAFMIN, XNORM
+* ..
+* .. External Functions ..
+ REAL SLAMCH, SLAPY2, SNRM2
+ EXTERNAL SLAMCH, SLAPY2, SNRM2
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC ABS, SIGN
+* ..
+* .. External Subroutines ..
+ EXTERNAL SSCAL
+* ..
+* .. Executable Statements ..
+*
+ IF( N.LE.1 ) THEN
+ TAU = ZERO
+ RETURN
+ END IF
+*
+ XNORM = SNRM2( N-1, X, INCX )
+*
+ IF( XNORM.EQ.ZERO ) THEN
+*
+* H = I
+*
+ TAU = ZERO
+ ELSE
+*
+* general case
+*
+ BETA = -SIGN( SLAPY2( ALPHA, XNORM ), ALPHA )
+ SAFMIN = SLAMCH( 'S' ) / SLAMCH( 'E' )
+ KNT = 0
+ IF( ABS( BETA ).LT.SAFMIN ) THEN
+*
+* XNORM, BETA may be inaccurate; scale X and recompute them
+*
+ RSAFMN = ONE / SAFMIN
+ 10 CONTINUE
+ KNT = KNT + 1
+ CALL SSCAL( N-1, RSAFMN, X, INCX )
+ BETA = BETA*RSAFMN
+ ALPHA = ALPHA*RSAFMN
+ IF( ABS( BETA ).LT.SAFMIN )
+ $ GO TO 10
+*
+* New BETA is at most 1, at least SAFMIN
+*
+ XNORM = SNRM2( N-1, X, INCX )
+ BETA = -SIGN( SLAPY2( ALPHA, XNORM ), ALPHA )
+ END IF
+ TAU = ( BETA-ALPHA ) / BETA
+ CALL SSCAL( N-1, ONE / ( ALPHA-BETA ), X, INCX )
+*
+* If ALPHA is subnormal, it may lose relative accuracy
+*
+ DO 20 J = 1, KNT
+ BETA = BETA*SAFMIN
+ 20 CONTINUE
+ ALPHA = BETA
+ END IF
+*
+ RETURN
+*
+* End of SLARFG
+*
+ END
diff --git a/lapack/slarft.f b/lapack/slarft.f
new file mode 100644
index 000000000..30b0668e4
--- /dev/null
+++ b/lapack/slarft.f
@@ -0,0 +1,326 @@
+*> \brief \b SLARFT
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download SLARFT + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/slarft.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/slarft.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slarft.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE SLARFT( DIRECT, STOREV, N, K, V, LDV, TAU, T, LDT )
+*
+* .. Scalar Arguments ..
+* CHARACTER DIRECT, STOREV
+* INTEGER K, LDT, LDV, N
+* ..
+* .. Array Arguments ..
+* REAL T( LDT, * ), TAU( * ), V( LDV, * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> SLARFT forms the triangular factor T of a real block reflector H
+*> of order n, which is defined as a product of k elementary reflectors.
+*>
+*> If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular;
+*>
+*> If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular.
+*>
+*> If STOREV = 'C', the vector which defines the elementary reflector
+*> H(i) is stored in the i-th column of the array V, and
+*>
+*> H = I - V * T * V**T
+*>
+*> If STOREV = 'R', the vector which defines the elementary reflector
+*> H(i) is stored in the i-th row of the array V, and
+*>
+*> H = I - V**T * T * V
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] DIRECT
+*> \verbatim
+*> DIRECT is CHARACTER*1
+*> Specifies the order in which the elementary reflectors are
+*> multiplied to form the block reflector:
+*> = 'F': H = H(1) H(2) . . . H(k) (Forward)
+*> = 'B': H = H(k) . . . H(2) H(1) (Backward)
+*> \endverbatim
+*>
+*> \param[in] STOREV
+*> \verbatim
+*> STOREV is CHARACTER*1
+*> Specifies how the vectors which define the elementary
+*> reflectors are stored (see also Further Details):
+*> = 'C': columnwise
+*> = 'R': rowwise
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The order of the block reflector H. N >= 0.
+*> \endverbatim
+*>
+*> \param[in] K
+*> \verbatim
+*> K is INTEGER
+*> The order of the triangular factor T (= the number of
+*> elementary reflectors). K >= 1.
+*> \endverbatim
+*>
+*> \param[in] V
+*> \verbatim
+*> V is REAL array, dimension
+*> (LDV,K) if STOREV = 'C'
+*> (LDV,N) if STOREV = 'R'
+*> The matrix V. See further details.
+*> \endverbatim
+*>
+*> \param[in] LDV
+*> \verbatim
+*> LDV is INTEGER
+*> The leading dimension of the array V.
+*> If STOREV = 'C', LDV >= max(1,N); if STOREV = 'R', LDV >= K.
+*> \endverbatim
+*>
+*> \param[in] TAU
+*> \verbatim
+*> TAU is REAL array, dimension (K)
+*> TAU(i) must contain the scalar factor of the elementary
+*> reflector H(i).
+*> \endverbatim
+*>
+*> \param[out] T
+*> \verbatim
+*> T is REAL array, dimension (LDT,K)
+*> The k by k triangular factor T of the block reflector.
+*> If DIRECT = 'F', T is upper triangular; if DIRECT = 'B', T is
+*> lower triangular. The rest of the array is not used.
+*> \endverbatim
+*>
+*> \param[in] LDT
+*> \verbatim
+*> LDT is INTEGER
+*> The leading dimension of the array T. LDT >= K.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date April 2012
+*
+*> \ingroup realOTHERauxiliary
+*
+*> \par Further Details:
+* =====================
+*>
+*> \verbatim
+*>
+*> The shape of the matrix V and the storage of the vectors which define
+*> the H(i) is best illustrated by the following example with n = 5 and
+*> k = 3. The elements equal to 1 are not stored.
+*>
+*> DIRECT = 'F' and STOREV = 'C': DIRECT = 'F' and STOREV = 'R':
+*>
+*> V = ( 1 ) V = ( 1 v1 v1 v1 v1 )
+*> ( v1 1 ) ( 1 v2 v2 v2 )
+*> ( v1 v2 1 ) ( 1 v3 v3 )
+*> ( v1 v2 v3 )
+*> ( v1 v2 v3 )
+*>
+*> DIRECT = 'B' and STOREV = 'C': DIRECT = 'B' and STOREV = 'R':
+*>
+*> V = ( v1 v2 v3 ) V = ( v1 v1 1 )
+*> ( v1 v2 v3 ) ( v2 v2 v2 1 )
+*> ( 1 v2 v3 ) ( v3 v3 v3 v3 1 )
+*> ( 1 v3 )
+*> ( 1 )
+*> \endverbatim
+*>
+* =====================================================================
+ SUBROUTINE SLARFT( DIRECT, STOREV, N, K, V, LDV, TAU, T, LDT )
+*
+* -- LAPACK auxiliary routine (version 3.4.1) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* April 2012
+*
+* .. Scalar Arguments ..
+ CHARACTER DIRECT, STOREV
+ INTEGER K, LDT, LDV, N
+* ..
+* .. Array Arguments ..
+ REAL T( LDT, * ), TAU( * ), V( LDV, * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ REAL ONE, ZERO
+ PARAMETER ( ONE = 1.0E+0, ZERO = 0.0E+0 )
+* ..
+* .. Local Scalars ..
+ INTEGER I, J, PREVLASTV, LASTV
+* ..
+* .. External Subroutines ..
+ EXTERNAL SGEMV, STRMV
+* ..
+* .. External Functions ..
+ LOGICAL LSAME
+ EXTERNAL LSAME
+* ..
+* .. Executable Statements ..
+*
+* Quick return if possible
+*
+ IF( N.EQ.0 )
+ $ RETURN
+*
+ IF( LSAME( DIRECT, 'F' ) ) THEN
+ PREVLASTV = N
+ DO I = 1, K
+ PREVLASTV = MAX( I, PREVLASTV )
+ IF( TAU( I ).EQ.ZERO ) THEN
+*
+* H(i) = I
+*
+ DO J = 1, I
+ T( J, I ) = ZERO
+ END DO
+ ELSE
+*
+* general case
+*
+ IF( LSAME( STOREV, 'C' ) ) THEN
+* Skip any trailing zeros.
+ DO LASTV = N, I+1, -1
+ IF( V( LASTV, I ).NE.ZERO ) EXIT
+ END DO
+ DO J = 1, I-1
+ T( J, I ) = -TAU( I ) * V( I , J )
+ END DO
+ J = MIN( LASTV, PREVLASTV )
+*
+* T(1:i-1,i) := - tau(i) * V(i:j,1:i-1)**T * V(i:j,i)
+*
+ CALL SGEMV( 'Transpose', J-I, I-1, -TAU( I ),
+ $ V( I+1, 1 ), LDV, V( I+1, I ), 1, ONE,
+ $ T( 1, I ), 1 )
+ ELSE
+* Skip any trailing zeros.
+ DO LASTV = N, I+1, -1
+ IF( V( I, LASTV ).NE.ZERO ) EXIT
+ END DO
+ DO J = 1, I-1
+ T( J, I ) = -TAU( I ) * V( J , I )
+ END DO
+ J = MIN( LASTV, PREVLASTV )
+*
+* T(1:i-1,i) := - tau(i) * V(1:i-1,i:j) * V(i,i:j)**T
+*
+ CALL SGEMV( 'No transpose', I-1, J-I, -TAU( I ),
+ $ V( 1, I+1 ), LDV, V( I, I+1 ), LDV,
+ $ ONE, T( 1, I ), 1 )
+ END IF
+*
+* T(1:i-1,i) := T(1:i-1,1:i-1) * T(1:i-1,i)
+*
+ CALL STRMV( 'Upper', 'No transpose', 'Non-unit', I-1, T,
+ $ LDT, T( 1, I ), 1 )
+ T( I, I ) = TAU( I )
+ IF( I.GT.1 ) THEN
+ PREVLASTV = MAX( PREVLASTV, LASTV )
+ ELSE
+ PREVLASTV = LASTV
+ END IF
+ END IF
+ END DO
+ ELSE
+ PREVLASTV = 1
+ DO I = K, 1, -1
+ IF( TAU( I ).EQ.ZERO ) THEN
+*
+* H(i) = I
+*
+ DO J = I, K
+ T( J, I ) = ZERO
+ END DO
+ ELSE
+*
+* general case
+*
+ IF( I.LT.K ) THEN
+ IF( LSAME( STOREV, 'C' ) ) THEN
+* Skip any leading zeros.
+ DO LASTV = 1, I-1
+ IF( V( LASTV, I ).NE.ZERO ) EXIT
+ END DO
+ DO J = I+1, K
+ T( J, I ) = -TAU( I ) * V( N-K+I , J )
+ END DO
+ J = MAX( LASTV, PREVLASTV )
+*
+* T(i+1:k,i) = -tau(i) * V(j:n-k+i,i+1:k)**T * V(j:n-k+i,i)
+*
+ CALL SGEMV( 'Transpose', N-K+I-J, K-I, -TAU( I ),
+ $ V( J, I+1 ), LDV, V( J, I ), 1, ONE,
+ $ T( I+1, I ), 1 )
+ ELSE
+* Skip any leading zeros.
+ DO LASTV = 1, I-1
+ IF( V( I, LASTV ).NE.ZERO ) EXIT
+ END DO
+ DO J = I+1, K
+ T( J, I ) = -TAU( I ) * V( J, N-K+I )
+ END DO
+ J = MAX( LASTV, PREVLASTV )
+*
+* T(i+1:k,i) = -tau(i) * V(i+1:k,j:n-k+i) * V(i,j:n-k+i)**T
+*
+ CALL SGEMV( 'No transpose', K-I, N-K+I-J,
+ $ -TAU( I ), V( I+1, J ), LDV, V( I, J ), LDV,
+ $ ONE, T( I+1, I ), 1 )
+ END IF
+*
+* T(i+1:k,i) := T(i+1:k,i+1:k) * T(i+1:k,i)
+*
+ CALL STRMV( 'Lower', 'No transpose', 'Non-unit', K-I,
+ $ T( I+1, I+1 ), LDT, T( I+1, I ), 1 )
+ IF( I.GT.1 ) THEN
+ PREVLASTV = MIN( PREVLASTV, LASTV )
+ ELSE
+ PREVLASTV = LASTV
+ END IF
+ END IF
+ T( I, I ) = TAU( I )
+ END IF
+ END DO
+ END IF
+ RETURN
+*
+* End of SLARFT
+*
+ END
diff --git a/lapack/zlacgv.f b/lapack/zlacgv.f
new file mode 100644
index 000000000..16c2e2ed9
--- /dev/null
+++ b/lapack/zlacgv.f
@@ -0,0 +1,116 @@
+*> \brief \b ZLACGV
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download ZLACGV + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zlacgv.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zlacgv.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlacgv.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE ZLACGV( N, X, INCX )
+*
+* .. Scalar Arguments ..
+* INTEGER INCX, N
+* ..
+* .. Array Arguments ..
+* COMPLEX*16 X( * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> ZLACGV conjugates a complex vector of length N.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The length of the vector X. N >= 0.
+*> \endverbatim
+*>
+*> \param[in,out] X
+*> \verbatim
+*> X is COMPLEX*16 array, dimension
+*> (1+(N-1)*abs(INCX))
+*> On entry, the vector of length N to be conjugated.
+*> On exit, X is overwritten with conjg(X).
+*> \endverbatim
+*>
+*> \param[in] INCX
+*> \verbatim
+*> INCX is INTEGER
+*> The spacing between successive elements of X.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup complex16OTHERauxiliary
+*
+* =====================================================================
+ SUBROUTINE ZLACGV( N, X, INCX )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ INTEGER INCX, N
+* ..
+* .. Array Arguments ..
+ COMPLEX*16 X( * )
+* ..
+*
+* =====================================================================
+*
+* .. Local Scalars ..
+ INTEGER I, IOFF
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC DCONJG
+* ..
+* .. Executable Statements ..
+*
+ IF( INCX.EQ.1 ) THEN
+ DO 10 I = 1, N
+ X( I ) = DCONJG( X( I ) )
+ 10 CONTINUE
+ ELSE
+ IOFF = 1
+ IF( INCX.LT.0 )
+ $ IOFF = 1 - ( N-1 )*INCX
+ DO 20 I = 1, N
+ X( IOFF ) = DCONJG( X( IOFF ) )
+ IOFF = IOFF + INCX
+ 20 CONTINUE
+ END IF
+ RETURN
+*
+* End of ZLACGV
+*
+ END
diff --git a/lapack/zladiv.f b/lapack/zladiv.f
new file mode 100644
index 000000000..aa71db14a
--- /dev/null
+++ b/lapack/zladiv.f
@@ -0,0 +1,97 @@
+*> \brief \b ZLADIV
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download ZLADIV + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zladiv.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zladiv.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zladiv.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* COMPLEX*16 FUNCTION ZLADIV( X, Y )
+*
+* .. Scalar Arguments ..
+* COMPLEX*16 X, Y
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> ZLADIV := X / Y, where X and Y are complex. The computation of X / Y
+*> will not overflow on an intermediary step unless the results
+*> overflows.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] X
+*> \verbatim
+*> X is COMPLEX*16
+*> \endverbatim
+*>
+*> \param[in] Y
+*> \verbatim
+*> Y is COMPLEX*16
+*> The complex scalars X and Y.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup complex16OTHERauxiliary
+*
+* =====================================================================
+ COMPLEX*16 FUNCTION ZLADIV( X, Y )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ COMPLEX*16 X, Y
+* ..
+*
+* =====================================================================
+*
+* .. Local Scalars ..
+ DOUBLE PRECISION ZI, ZR
+* ..
+* .. External Subroutines ..
+ EXTERNAL DLADIV
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC DBLE, DCMPLX, DIMAG
+* ..
+* .. Executable Statements ..
+*
+ CALL DLADIV( DBLE( X ), DIMAG( X ), DBLE( Y ), DIMAG( Y ), ZR,
+ $ ZI )
+ ZLADIV = DCMPLX( ZR, ZI )
+*
+ RETURN
+*
+* End of ZLADIV
+*
+ END
diff --git a/lapack/zlarf.f b/lapack/zlarf.f
new file mode 100644
index 000000000..53f314d64
--- /dev/null
+++ b/lapack/zlarf.f
@@ -0,0 +1,232 @@
+*> \brief \b ZLARF
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download ZLARF + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zlarf.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zlarf.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlarf.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE ZLARF( SIDE, M, N, V, INCV, TAU, C, LDC, WORK )
+*
+* .. Scalar Arguments ..
+* CHARACTER SIDE
+* INTEGER INCV, LDC, M, N
+* COMPLEX*16 TAU
+* ..
+* .. Array Arguments ..
+* COMPLEX*16 C( LDC, * ), V( * ), WORK( * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> ZLARF applies a complex elementary reflector H to a complex M-by-N
+*> matrix C, from either the left or the right. H is represented in the
+*> form
+*>
+*> H = I - tau * v * v**H
+*>
+*> where tau is a complex scalar and v is a complex vector.
+*>
+*> If tau = 0, then H is taken to be the unit matrix.
+*>
+*> To apply H**H, supply conjg(tau) instead
+*> tau.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] SIDE
+*> \verbatim
+*> SIDE is CHARACTER*1
+*> = 'L': form H * C
+*> = 'R': form C * H
+*> \endverbatim
+*>
+*> \param[in] M
+*> \verbatim
+*> M is INTEGER
+*> The number of rows of the matrix C.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The number of columns of the matrix C.
+*> \endverbatim
+*>
+*> \param[in] V
+*> \verbatim
+*> V is COMPLEX*16 array, dimension
+*> (1 + (M-1)*abs(INCV)) if SIDE = 'L'
+*> or (1 + (N-1)*abs(INCV)) if SIDE = 'R'
+*> The vector v in the representation of H. V is not used if
+*> TAU = 0.
+*> \endverbatim
+*>
+*> \param[in] INCV
+*> \verbatim
+*> INCV is INTEGER
+*> The increment between elements of v. INCV <> 0.
+*> \endverbatim
+*>
+*> \param[in] TAU
+*> \verbatim
+*> TAU is COMPLEX*16
+*> The value tau in the representation of H.
+*> \endverbatim
+*>
+*> \param[in,out] C
+*> \verbatim
+*> C is COMPLEX*16 array, dimension (LDC,N)
+*> On entry, the M-by-N matrix C.
+*> On exit, C is overwritten by the matrix H * C if SIDE = 'L',
+*> or C * H if SIDE = 'R'.
+*> \endverbatim
+*>
+*> \param[in] LDC
+*> \verbatim
+*> LDC is INTEGER
+*> The leading dimension of the array C. LDC >= max(1,M).
+*> \endverbatim
+*>
+*> \param[out] WORK
+*> \verbatim
+*> WORK is COMPLEX*16 array, dimension
+*> (N) if SIDE = 'L'
+*> or (M) if SIDE = 'R'
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup complex16OTHERauxiliary
+*
+* =====================================================================
+ SUBROUTINE ZLARF( SIDE, M, N, V, INCV, TAU, C, LDC, WORK )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ CHARACTER SIDE
+ INTEGER INCV, LDC, M, N
+ COMPLEX*16 TAU
+* ..
+* .. Array Arguments ..
+ COMPLEX*16 C( LDC, * ), V( * ), WORK( * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ COMPLEX*16 ONE, ZERO
+ PARAMETER ( ONE = ( 1.0D+0, 0.0D+0 ),
+ $ ZERO = ( 0.0D+0, 0.0D+0 ) )
+* ..
+* .. Local Scalars ..
+ LOGICAL APPLYLEFT
+ INTEGER I, LASTV, LASTC
+* ..
+* .. External Subroutines ..
+ EXTERNAL ZGEMV, ZGERC
+* ..
+* .. External Functions ..
+ LOGICAL LSAME
+ INTEGER ILAZLR, ILAZLC
+ EXTERNAL LSAME, ILAZLR, ILAZLC
+* ..
+* .. Executable Statements ..
+*
+ APPLYLEFT = LSAME( SIDE, 'L' )
+ LASTV = 0
+ LASTC = 0
+ IF( TAU.NE.ZERO ) THEN
+* Set up variables for scanning V. LASTV begins pointing to the end
+* of V.
+ IF( APPLYLEFT ) THEN
+ LASTV = M
+ ELSE
+ LASTV = N
+ END IF
+ IF( INCV.GT.0 ) THEN
+ I = 1 + (LASTV-1) * INCV
+ ELSE
+ I = 1
+ END IF
+* Look for the last non-zero row in V.
+ DO WHILE( LASTV.GT.0 .AND. V( I ).EQ.ZERO )
+ LASTV = LASTV - 1
+ I = I - INCV
+ END DO
+ IF( APPLYLEFT ) THEN
+* Scan for the last non-zero column in C(1:lastv,:).
+ LASTC = ILAZLC(LASTV, N, C, LDC)
+ ELSE
+* Scan for the last non-zero row in C(:,1:lastv).
+ LASTC = ILAZLR(M, LASTV, C, LDC)
+ END IF
+ END IF
+* Note that lastc.eq.0 renders the BLAS operations null; no special
+* case is needed at this level.
+ IF( APPLYLEFT ) THEN
+*
+* Form H * C
+*
+ IF( LASTV.GT.0 ) THEN
+*
+* w(1:lastc,1) := C(1:lastv,1:lastc)**H * v(1:lastv,1)
+*
+ CALL ZGEMV( 'Conjugate transpose', LASTV, LASTC, ONE,
+ $ C, LDC, V, INCV, ZERO, WORK, 1 )
+*
+* C(1:lastv,1:lastc) := C(...) - v(1:lastv,1) * w(1:lastc,1)**H
+*
+ CALL ZGERC( LASTV, LASTC, -TAU, V, INCV, WORK, 1, C, LDC )
+ END IF
+ ELSE
+*
+* Form C * H
+*
+ IF( LASTV.GT.0 ) THEN
+*
+* w(1:lastc,1) := C(1:lastc,1:lastv) * v(1:lastv,1)
+*
+ CALL ZGEMV( 'No transpose', LASTC, LASTV, ONE, C, LDC,
+ $ V, INCV, ZERO, WORK, 1 )
+*
+* C(1:lastc,1:lastv) := C(...) - w(1:lastc,1) * v(1:lastv,1)**H
+*
+ CALL ZGERC( LASTC, LASTV, -TAU, WORK, 1, V, INCV, C, LDC )
+ END IF
+ END IF
+ RETURN
+*
+* End of ZLARF
+*
+ END
diff --git a/lapack/zlarfb.f b/lapack/zlarfb.f
new file mode 100644
index 000000000..30fc4b940
--- /dev/null
+++ b/lapack/zlarfb.f
@@ -0,0 +1,774 @@
+*> \brief \b ZLARFB
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download ZLARFB + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zlarfb.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zlarfb.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlarfb.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE ZLARFB( SIDE, TRANS, DIRECT, STOREV, M, N, K, V, LDV,
+* T, LDT, C, LDC, WORK, LDWORK )
+*
+* .. Scalar Arguments ..
+* CHARACTER DIRECT, SIDE, STOREV, TRANS
+* INTEGER K, LDC, LDT, LDV, LDWORK, M, N
+* ..
+* .. Array Arguments ..
+* COMPLEX*16 C( LDC, * ), T( LDT, * ), V( LDV, * ),
+* $ WORK( LDWORK, * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> ZLARFB applies a complex block reflector H or its transpose H**H to a
+*> complex M-by-N matrix C, from either the left or the right.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] SIDE
+*> \verbatim
+*> SIDE is CHARACTER*1
+*> = 'L': apply H or H**H from the Left
+*> = 'R': apply H or H**H from the Right
+*> \endverbatim
+*>
+*> \param[in] TRANS
+*> \verbatim
+*> TRANS is CHARACTER*1
+*> = 'N': apply H (No transpose)
+*> = 'C': apply H**H (Conjugate transpose)
+*> \endverbatim
+*>
+*> \param[in] DIRECT
+*> \verbatim
+*> DIRECT is CHARACTER*1
+*> Indicates how H is formed from a product of elementary
+*> reflectors
+*> = 'F': H = H(1) H(2) . . . H(k) (Forward)
+*> = 'B': H = H(k) . . . H(2) H(1) (Backward)
+*> \endverbatim
+*>
+*> \param[in] STOREV
+*> \verbatim
+*> STOREV is CHARACTER*1
+*> Indicates how the vectors which define the elementary
+*> reflectors are stored:
+*> = 'C': Columnwise
+*> = 'R': Rowwise
+*> \endverbatim
+*>
+*> \param[in] M
+*> \verbatim
+*> M is INTEGER
+*> The number of rows of the matrix C.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The number of columns of the matrix C.
+*> \endverbatim
+*>
+*> \param[in] K
+*> \verbatim
+*> K is INTEGER
+*> The order of the matrix T (= the number of elementary
+*> reflectors whose product defines the block reflector).
+*> \endverbatim
+*>
+*> \param[in] V
+*> \verbatim
+*> V is COMPLEX*16 array, dimension
+*> (LDV,K) if STOREV = 'C'
+*> (LDV,M) if STOREV = 'R' and SIDE = 'L'
+*> (LDV,N) if STOREV = 'R' and SIDE = 'R'
+*> See Further Details.
+*> \endverbatim
+*>
+*> \param[in] LDV
+*> \verbatim
+*> LDV is INTEGER
+*> The leading dimension of the array V.
+*> If STOREV = 'C' and SIDE = 'L', LDV >= max(1,M);
+*> if STOREV = 'C' and SIDE = 'R', LDV >= max(1,N);
+*> if STOREV = 'R', LDV >= K.
+*> \endverbatim
+*>
+*> \param[in] T
+*> \verbatim
+*> T is COMPLEX*16 array, dimension (LDT,K)
+*> The triangular K-by-K matrix T in the representation of the
+*> block reflector.
+*> \endverbatim
+*>
+*> \param[in] LDT
+*> \verbatim
+*> LDT is INTEGER
+*> The leading dimension of the array T. LDT >= K.
+*> \endverbatim
+*>
+*> \param[in,out] C
+*> \verbatim
+*> C is COMPLEX*16 array, dimension (LDC,N)
+*> On entry, the M-by-N matrix C.
+*> On exit, C is overwritten by H*C or H**H*C or C*H or C*H**H.
+*> \endverbatim
+*>
+*> \param[in] LDC
+*> \verbatim
+*> LDC is INTEGER
+*> The leading dimension of the array C. LDC >= max(1,M).
+*> \endverbatim
+*>
+*> \param[out] WORK
+*> \verbatim
+*> WORK is COMPLEX*16 array, dimension (LDWORK,K)
+*> \endverbatim
+*>
+*> \param[in] LDWORK
+*> \verbatim
+*> LDWORK is INTEGER
+*> The leading dimension of the array WORK.
+*> If SIDE = 'L', LDWORK >= max(1,N);
+*> if SIDE = 'R', LDWORK >= max(1,M).
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup complex16OTHERauxiliary
+*
+*> \par Further Details:
+* =====================
+*>
+*> \verbatim
+*>
+*> The shape of the matrix V and the storage of the vectors which define
+*> the H(i) is best illustrated by the following example with n = 5 and
+*> k = 3. The elements equal to 1 are not stored; the corresponding
+*> array elements are modified but restored on exit. The rest of the
+*> array is not used.
+*>
+*> DIRECT = 'F' and STOREV = 'C': DIRECT = 'F' and STOREV = 'R':
+*>
+*> V = ( 1 ) V = ( 1 v1 v1 v1 v1 )
+*> ( v1 1 ) ( 1 v2 v2 v2 )
+*> ( v1 v2 1 ) ( 1 v3 v3 )
+*> ( v1 v2 v3 )
+*> ( v1 v2 v3 )
+*>
+*> DIRECT = 'B' and STOREV = 'C': DIRECT = 'B' and STOREV = 'R':
+*>
+*> V = ( v1 v2 v3 ) V = ( v1 v1 1 )
+*> ( v1 v2 v3 ) ( v2 v2 v2 1 )
+*> ( 1 v2 v3 ) ( v3 v3 v3 v3 1 )
+*> ( 1 v3 )
+*> ( 1 )
+*> \endverbatim
+*>
+* =====================================================================
+ SUBROUTINE ZLARFB( SIDE, TRANS, DIRECT, STOREV, M, N, K, V, LDV,
+ $ T, LDT, C, LDC, WORK, LDWORK )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ CHARACTER DIRECT, SIDE, STOREV, TRANS
+ INTEGER K, LDC, LDT, LDV, LDWORK, M, N
+* ..
+* .. Array Arguments ..
+ COMPLEX*16 C( LDC, * ), T( LDT, * ), V( LDV, * ),
+ $ WORK( LDWORK, * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ COMPLEX*16 ONE
+ PARAMETER ( ONE = ( 1.0D+0, 0.0D+0 ) )
+* ..
+* .. Local Scalars ..
+ CHARACTER TRANST
+ INTEGER I, J, LASTV, LASTC
+* ..
+* .. External Functions ..
+ LOGICAL LSAME
+ INTEGER ILAZLR, ILAZLC
+ EXTERNAL LSAME, ILAZLR, ILAZLC
+* ..
+* .. External Subroutines ..
+ EXTERNAL ZCOPY, ZGEMM, ZLACGV, ZTRMM
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC DCONJG
+* ..
+* .. Executable Statements ..
+*
+* Quick return if possible
+*
+ IF( M.LE.0 .OR. N.LE.0 )
+ $ RETURN
+*
+ IF( LSAME( TRANS, 'N' ) ) THEN
+ TRANST = 'C'
+ ELSE
+ TRANST = 'N'
+ END IF
+*
+ IF( LSAME( STOREV, 'C' ) ) THEN
+*
+ IF( LSAME( DIRECT, 'F' ) ) THEN
+*
+* Let V = ( V1 ) (first K rows)
+* ( V2 )
+* where V1 is unit lower triangular.
+*
+ IF( LSAME( SIDE, 'L' ) ) THEN
+*
+* Form H * C or H**H * C where C = ( C1 )
+* ( C2 )
+*
+ LASTV = MAX( K, ILAZLR( M, K, V, LDV ) )
+ LASTC = ILAZLC( LASTV, N, C, LDC )
+*
+* W := C**H * V = (C1**H * V1 + C2**H * V2) (stored in WORK)
+*
+* W := C1**H
+*
+ DO 10 J = 1, K
+ CALL ZCOPY( LASTC, C( J, 1 ), LDC, WORK( 1, J ), 1 )
+ CALL ZLACGV( LASTC, WORK( 1, J ), 1 )
+ 10 CONTINUE
+*
+* W := W * V1
+*
+ CALL ZTRMM( 'Right', 'Lower', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C2**H *V2
+*
+ CALL ZGEMM( 'Conjugate transpose', 'No transpose',
+ $ LASTC, K, LASTV-K, ONE, C( K+1, 1 ), LDC,
+ $ V( K+1, 1 ), LDV, ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T**H or W * T
+*
+ CALL ZTRMM( 'Right', 'Upper', TRANST, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - V * W**H
+*
+ IF( M.GT.K ) THEN
+*
+* C2 := C2 - V2 * W**H
+*
+ CALL ZGEMM( 'No transpose', 'Conjugate transpose',
+ $ LASTV-K, LASTC, K,
+ $ -ONE, V( K+1, 1 ), LDV, WORK, LDWORK,
+ $ ONE, C( K+1, 1 ), LDC )
+ END IF
+*
+* W := W * V1**H
+*
+ CALL ZTRMM( 'Right', 'Lower', 'Conjugate transpose',
+ $ 'Unit', LASTC, K, ONE, V, LDV, WORK, LDWORK )
+*
+* C1 := C1 - W**H
+*
+ DO 30 J = 1, K
+ DO 20 I = 1, LASTC
+ C( J, I ) = C( J, I ) - DCONJG( WORK( I, J ) )
+ 20 CONTINUE
+ 30 CONTINUE
+*
+ ELSE IF( LSAME( SIDE, 'R' ) ) THEN
+*
+* Form C * H or C * H**H where C = ( C1 C2 )
+*
+ LASTV = MAX( K, ILAZLR( N, K, V, LDV ) )
+ LASTC = ILAZLR( M, LASTV, C, LDC )
+*
+* W := C * V = (C1*V1 + C2*V2) (stored in WORK)
+*
+* W := C1
+*
+ DO 40 J = 1, K
+ CALL ZCOPY( LASTC, C( 1, J ), 1, WORK( 1, J ), 1 )
+ 40 CONTINUE
+*
+* W := W * V1
+*
+ CALL ZTRMM( 'Right', 'Lower', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C2 * V2
+*
+ CALL ZGEMM( 'No transpose', 'No transpose',
+ $ LASTC, K, LASTV-K,
+ $ ONE, C( 1, K+1 ), LDC, V( K+1, 1 ), LDV,
+ $ ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T or W * T**H
+*
+ CALL ZTRMM( 'Right', 'Upper', TRANS, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - W * V**H
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C2 := C2 - W * V2**H
+*
+ CALL ZGEMM( 'No transpose', 'Conjugate transpose',
+ $ LASTC, LASTV-K, K,
+ $ -ONE, WORK, LDWORK, V( K+1, 1 ), LDV,
+ $ ONE, C( 1, K+1 ), LDC )
+ END IF
+*
+* W := W * V1**H
+*
+ CALL ZTRMM( 'Right', 'Lower', 'Conjugate transpose',
+ $ 'Unit', LASTC, K, ONE, V, LDV, WORK, LDWORK )
+*
+* C1 := C1 - W
+*
+ DO 60 J = 1, K
+ DO 50 I = 1, LASTC
+ C( I, J ) = C( I, J ) - WORK( I, J )
+ 50 CONTINUE
+ 60 CONTINUE
+ END IF
+*
+ ELSE
+*
+* Let V = ( V1 )
+* ( V2 ) (last K rows)
+* where V2 is unit upper triangular.
+*
+ IF( LSAME( SIDE, 'L' ) ) THEN
+*
+* Form H * C or H**H * C where C = ( C1 )
+* ( C2 )
+*
+ LASTV = MAX( K, ILAZLR( M, K, V, LDV ) )
+ LASTC = ILAZLC( LASTV, N, C, LDC )
+*
+* W := C**H * V = (C1**H * V1 + C2**H * V2) (stored in WORK)
+*
+* W := C2**H
+*
+ DO 70 J = 1, K
+ CALL ZCOPY( LASTC, C( LASTV-K+J, 1 ), LDC,
+ $ WORK( 1, J ), 1 )
+ CALL ZLACGV( LASTC, WORK( 1, J ), 1 )
+ 70 CONTINUE
+*
+* W := W * V2
+*
+ CALL ZTRMM( 'Right', 'Upper', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV,
+ $ WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C1**H*V1
+*
+ CALL ZGEMM( 'Conjugate transpose', 'No transpose',
+ $ LASTC, K, LASTV-K,
+ $ ONE, C, LDC, V, LDV,
+ $ ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T**H or W * T
+*
+ CALL ZTRMM( 'Right', 'Lower', TRANST, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - V * W**H
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C1 := C1 - V1 * W**H
+*
+ CALL ZGEMM( 'No transpose', 'Conjugate transpose',
+ $ LASTV-K, LASTC, K,
+ $ -ONE, V, LDV, WORK, LDWORK,
+ $ ONE, C, LDC )
+ END IF
+*
+* W := W * V2**H
+*
+ CALL ZTRMM( 'Right', 'Upper', 'Conjugate transpose',
+ $ 'Unit', LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV,
+ $ WORK, LDWORK )
+*
+* C2 := C2 - W**H
+*
+ DO 90 J = 1, K
+ DO 80 I = 1, LASTC
+ C( LASTV-K+J, I ) = C( LASTV-K+J, I ) -
+ $ DCONJG( WORK( I, J ) )
+ 80 CONTINUE
+ 90 CONTINUE
+*
+ ELSE IF( LSAME( SIDE, 'R' ) ) THEN
+*
+* Form C * H or C * H**H where C = ( C1 C2 )
+*
+ LASTV = MAX( K, ILAZLR( N, K, V, LDV ) )
+ LASTC = ILAZLR( M, LASTV, C, LDC )
+*
+* W := C * V = (C1*V1 + C2*V2) (stored in WORK)
+*
+* W := C2
+*
+ DO 100 J = 1, K
+ CALL ZCOPY( LASTC, C( 1, LASTV-K+J ), 1,
+ $ WORK( 1, J ), 1 )
+ 100 CONTINUE
+*
+* W := W * V2
+*
+ CALL ZTRMM( 'Right', 'Upper', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV,
+ $ WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C1 * V1
+*
+ CALL ZGEMM( 'No transpose', 'No transpose',
+ $ LASTC, K, LASTV-K,
+ $ ONE, C, LDC, V, LDV, ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T or W * T**H
+*
+ CALL ZTRMM( 'Right', 'Lower', TRANS, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - W * V**H
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C1 := C1 - W * V1**H
+*
+ CALL ZGEMM( 'No transpose', 'Conjugate transpose',
+ $ LASTC, LASTV-K, K, -ONE, WORK, LDWORK, V, LDV,
+ $ ONE, C, LDC )
+ END IF
+*
+* W := W * V2**H
+*
+ CALL ZTRMM( 'Right', 'Upper', 'Conjugate transpose',
+ $ 'Unit', LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV,
+ $ WORK, LDWORK )
+*
+* C2 := C2 - W
+*
+ DO 120 J = 1, K
+ DO 110 I = 1, LASTC
+ C( I, LASTV-K+J ) = C( I, LASTV-K+J )
+ $ - WORK( I, J )
+ 110 CONTINUE
+ 120 CONTINUE
+ END IF
+ END IF
+*
+ ELSE IF( LSAME( STOREV, 'R' ) ) THEN
+*
+ IF( LSAME( DIRECT, 'F' ) ) THEN
+*
+* Let V = ( V1 V2 ) (V1: first K columns)
+* where V1 is unit upper triangular.
+*
+ IF( LSAME( SIDE, 'L' ) ) THEN
+*
+* Form H * C or H**H * C where C = ( C1 )
+* ( C2 )
+*
+ LASTV = MAX( K, ILAZLC( K, M, V, LDV ) )
+ LASTC = ILAZLC( LASTV, N, C, LDC )
+*
+* W := C**H * V**H = (C1**H * V1**H + C2**H * V2**H) (stored in WORK)
+*
+* W := C1**H
+*
+ DO 130 J = 1, K
+ CALL ZCOPY( LASTC, C( J, 1 ), LDC, WORK( 1, J ), 1 )
+ CALL ZLACGV( LASTC, WORK( 1, J ), 1 )
+ 130 CONTINUE
+*
+* W := W * V1**H
+*
+ CALL ZTRMM( 'Right', 'Upper', 'Conjugate transpose',
+ $ 'Unit', LASTC, K, ONE, V, LDV, WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C2**H*V2**H
+*
+ CALL ZGEMM( 'Conjugate transpose',
+ $ 'Conjugate transpose', LASTC, K, LASTV-K,
+ $ ONE, C( K+1, 1 ), LDC, V( 1, K+1 ), LDV,
+ $ ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T**H or W * T
+*
+ CALL ZTRMM( 'Right', 'Upper', TRANST, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - V**H * W**H
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C2 := C2 - V2**H * W**H
+*
+ CALL ZGEMM( 'Conjugate transpose',
+ $ 'Conjugate transpose', LASTV-K, LASTC, K,
+ $ -ONE, V( 1, K+1 ), LDV, WORK, LDWORK,
+ $ ONE, C( K+1, 1 ), LDC )
+ END IF
+*
+* W := W * V1
+*
+ CALL ZTRMM( 'Right', 'Upper', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+*
+* C1 := C1 - W**H
+*
+ DO 150 J = 1, K
+ DO 140 I = 1, LASTC
+ C( J, I ) = C( J, I ) - DCONJG( WORK( I, J ) )
+ 140 CONTINUE
+ 150 CONTINUE
+*
+ ELSE IF( LSAME( SIDE, 'R' ) ) THEN
+*
+* Form C * H or C * H**H where C = ( C1 C2 )
+*
+ LASTV = MAX( K, ILAZLC( K, N, V, LDV ) )
+ LASTC = ILAZLR( M, LASTV, C, LDC )
+*
+* W := C * V**H = (C1*V1**H + C2*V2**H) (stored in WORK)
+*
+* W := C1
+*
+ DO 160 J = 1, K
+ CALL ZCOPY( LASTC, C( 1, J ), 1, WORK( 1, J ), 1 )
+ 160 CONTINUE
+*
+* W := W * V1**H
+*
+ CALL ZTRMM( 'Right', 'Upper', 'Conjugate transpose',
+ $ 'Unit', LASTC, K, ONE, V, LDV, WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C2 * V2**H
+*
+ CALL ZGEMM( 'No transpose', 'Conjugate transpose',
+ $ LASTC, K, LASTV-K, ONE, C( 1, K+1 ), LDC,
+ $ V( 1, K+1 ), LDV, ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T or W * T**H
+*
+ CALL ZTRMM( 'Right', 'Upper', TRANS, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - W * V
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C2 := C2 - W * V2
+*
+ CALL ZGEMM( 'No transpose', 'No transpose',
+ $ LASTC, LASTV-K, K,
+ $ -ONE, WORK, LDWORK, V( 1, K+1 ), LDV,
+ $ ONE, C( 1, K+1 ), LDC )
+ END IF
+*
+* W := W * V1
+*
+ CALL ZTRMM( 'Right', 'Upper', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V, LDV, WORK, LDWORK )
+*
+* C1 := C1 - W
+*
+ DO 180 J = 1, K
+ DO 170 I = 1, LASTC
+ C( I, J ) = C( I, J ) - WORK( I, J )
+ 170 CONTINUE
+ 180 CONTINUE
+*
+ END IF
+*
+ ELSE
+*
+* Let V = ( V1 V2 ) (V2: last K columns)
+* where V2 is unit lower triangular.
+*
+ IF( LSAME( SIDE, 'L' ) ) THEN
+*
+* Form H * C or H**H * C where C = ( C1 )
+* ( C2 )
+*
+ LASTV = MAX( K, ILAZLC( K, M, V, LDV ) )
+ LASTC = ILAZLC( LASTV, N, C, LDC )
+*
+* W := C**H * V**H = (C1**H * V1**H + C2**H * V2**H) (stored in WORK)
+*
+* W := C2**H
+*
+ DO 190 J = 1, K
+ CALL ZCOPY( LASTC, C( LASTV-K+J, 1 ), LDC,
+ $ WORK( 1, J ), 1 )
+ CALL ZLACGV( LASTC, WORK( 1, J ), 1 )
+ 190 CONTINUE
+*
+* W := W * V2**H
+*
+ CALL ZTRMM( 'Right', 'Lower', 'Conjugate transpose',
+ $ 'Unit', LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV,
+ $ WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C1**H * V1**H
+*
+ CALL ZGEMM( 'Conjugate transpose',
+ $ 'Conjugate transpose', LASTC, K, LASTV-K,
+ $ ONE, C, LDC, V, LDV, ONE, WORK, LDWORK )
+ END IF
+*
+* W := W * T**H or W * T
+*
+ CALL ZTRMM( 'Right', 'Lower', TRANST, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - V**H * W**H
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C1 := C1 - V1**H * W**H
+*
+ CALL ZGEMM( 'Conjugate transpose',
+ $ 'Conjugate transpose', LASTV-K, LASTC, K,
+ $ -ONE, V, LDV, WORK, LDWORK, ONE, C, LDC )
+ END IF
+*
+* W := W * V2
+*
+ CALL ZTRMM( 'Right', 'Lower', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV,
+ $ WORK, LDWORK )
+*
+* C2 := C2 - W**H
+*
+ DO 210 J = 1, K
+ DO 200 I = 1, LASTC
+ C( LASTV-K+J, I ) = C( LASTV-K+J, I ) -
+ $ DCONJG( WORK( I, J ) )
+ 200 CONTINUE
+ 210 CONTINUE
+*
+ ELSE IF( LSAME( SIDE, 'R' ) ) THEN
+*
+* Form C * H or C * H**H where C = ( C1 C2 )
+*
+ LASTV = MAX( K, ILAZLC( K, N, V, LDV ) )
+ LASTC = ILAZLR( M, LASTV, C, LDC )
+*
+* W := C * V**H = (C1*V1**H + C2*V2**H) (stored in WORK)
+*
+* W := C2
+*
+ DO 220 J = 1, K
+ CALL ZCOPY( LASTC, C( 1, LASTV-K+J ), 1,
+ $ WORK( 1, J ), 1 )
+ 220 CONTINUE
+*
+* W := W * V2**H
+*
+ CALL ZTRMM( 'Right', 'Lower', 'Conjugate transpose',
+ $ 'Unit', LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV,
+ $ WORK, LDWORK )
+ IF( LASTV.GT.K ) THEN
+*
+* W := W + C1 * V1**H
+*
+ CALL ZGEMM( 'No transpose', 'Conjugate transpose',
+ $ LASTC, K, LASTV-K, ONE, C, LDC, V, LDV, ONE,
+ $ WORK, LDWORK )
+ END IF
+*
+* W := W * T or W * T**H
+*
+ CALL ZTRMM( 'Right', 'Lower', TRANS, 'Non-unit',
+ $ LASTC, K, ONE, T, LDT, WORK, LDWORK )
+*
+* C := C - W * V
+*
+ IF( LASTV.GT.K ) THEN
+*
+* C1 := C1 - W * V1
+*
+ CALL ZGEMM( 'No transpose', 'No transpose',
+ $ LASTC, LASTV-K, K, -ONE, WORK, LDWORK, V, LDV,
+ $ ONE, C, LDC )
+ END IF
+*
+* W := W * V2
+*
+ CALL ZTRMM( 'Right', 'Lower', 'No transpose', 'Unit',
+ $ LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV,
+ $ WORK, LDWORK )
+*
+* C1 := C1 - W
+*
+ DO 240 J = 1, K
+ DO 230 I = 1, LASTC
+ C( I, LASTV-K+J ) = C( I, LASTV-K+J )
+ $ - WORK( I, J )
+ 230 CONTINUE
+ 240 CONTINUE
+*
+ END IF
+*
+ END IF
+ END IF
+*
+ RETURN
+*
+* End of ZLARFB
+*
+ END
diff --git a/lapack/zlarfg.f b/lapack/zlarfg.f
new file mode 100644
index 000000000..a90ae9f74
--- /dev/null
+++ b/lapack/zlarfg.f
@@ -0,0 +1,203 @@
+*> \brief \b ZLARFG
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download ZLARFG + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zlarfg.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zlarfg.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlarfg.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE ZLARFG( N, ALPHA, X, INCX, TAU )
+*
+* .. Scalar Arguments ..
+* INTEGER INCX, N
+* COMPLEX*16 ALPHA, TAU
+* ..
+* .. Array Arguments ..
+* COMPLEX*16 X( * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> ZLARFG generates a complex elementary reflector H of order n, such
+*> that
+*>
+*> H**H * ( alpha ) = ( beta ), H**H * H = I.
+*> ( x ) ( 0 )
+*>
+*> where alpha and beta are scalars, with beta real, and x is an
+*> (n-1)-element complex vector. H is represented in the form
+*>
+*> H = I - tau * ( 1 ) * ( 1 v**H ) ,
+*> ( v )
+*>
+*> where tau is a complex scalar and v is a complex (n-1)-element
+*> vector. Note that H is not hermitian.
+*>
+*> If the elements of x are all zero and alpha is real, then tau = 0
+*> and H is taken to be the unit matrix.
+*>
+*> Otherwise 1 <= real(tau) <= 2 and abs(tau-1) <= 1 .
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The order of the elementary reflector.
+*> \endverbatim
+*>
+*> \param[in,out] ALPHA
+*> \verbatim
+*> ALPHA is COMPLEX*16
+*> On entry, the value alpha.
+*> On exit, it is overwritten with the value beta.
+*> \endverbatim
+*>
+*> \param[in,out] X
+*> \verbatim
+*> X is COMPLEX*16 array, dimension
+*> (1+(N-2)*abs(INCX))
+*> On entry, the vector x.
+*> On exit, it is overwritten with the vector v.
+*> \endverbatim
+*>
+*> \param[in] INCX
+*> \verbatim
+*> INCX is INTEGER
+*> The increment between elements of X. INCX > 0.
+*> \endverbatim
+*>
+*> \param[out] TAU
+*> \verbatim
+*> TAU is COMPLEX*16
+*> The value tau.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup complex16OTHERauxiliary
+*
+* =====================================================================
+ SUBROUTINE ZLARFG( N, ALPHA, X, INCX, TAU )
+*
+* -- LAPACK auxiliary routine (version 3.4.0) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* November 2011
+*
+* .. Scalar Arguments ..
+ INTEGER INCX, N
+ COMPLEX*16 ALPHA, TAU
+* ..
+* .. Array Arguments ..
+ COMPLEX*16 X( * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ DOUBLE PRECISION ONE, ZERO
+ PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
+* ..
+* .. Local Scalars ..
+ INTEGER J, KNT
+ DOUBLE PRECISION ALPHI, ALPHR, BETA, RSAFMN, SAFMIN, XNORM
+* ..
+* .. External Functions ..
+ DOUBLE PRECISION DLAMCH, DLAPY3, DZNRM2
+ COMPLEX*16 ZLADIV
+ EXTERNAL DLAMCH, DLAPY3, DZNRM2, ZLADIV
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC ABS, DBLE, DCMPLX, DIMAG, SIGN
+* ..
+* .. External Subroutines ..
+ EXTERNAL ZDSCAL, ZSCAL
+* ..
+* .. Executable Statements ..
+*
+ IF( N.LE.0 ) THEN
+ TAU = ZERO
+ RETURN
+ END IF
+*
+ XNORM = DZNRM2( N-1, X, INCX )
+ ALPHR = DBLE( ALPHA )
+ ALPHI = DIMAG( ALPHA )
+*
+ IF( XNORM.EQ.ZERO .AND. ALPHI.EQ.ZERO ) THEN
+*
+* H = I
+*
+ TAU = ZERO
+ ELSE
+*
+* general case
+*
+ BETA = -SIGN( DLAPY3( ALPHR, ALPHI, XNORM ), ALPHR )
+ SAFMIN = DLAMCH( 'S' ) / DLAMCH( 'E' )
+ RSAFMN = ONE / SAFMIN
+*
+ KNT = 0
+ IF( ABS( BETA ).LT.SAFMIN ) THEN
+*
+* XNORM, BETA may be inaccurate; scale X and recompute them
+*
+ 10 CONTINUE
+ KNT = KNT + 1
+ CALL ZDSCAL( N-1, RSAFMN, X, INCX )
+ BETA = BETA*RSAFMN
+ ALPHI = ALPHI*RSAFMN
+ ALPHR = ALPHR*RSAFMN
+ IF( ABS( BETA ).LT.SAFMIN )
+ $ GO TO 10
+*
+* New BETA is at most 1, at least SAFMIN
+*
+ XNORM = DZNRM2( N-1, X, INCX )
+ ALPHA = DCMPLX( ALPHR, ALPHI )
+ BETA = -SIGN( DLAPY3( ALPHR, ALPHI, XNORM ), ALPHR )
+ END IF
+ TAU = DCMPLX( ( BETA-ALPHR ) / BETA, -ALPHI / BETA )
+ ALPHA = ZLADIV( DCMPLX( ONE ), ALPHA-BETA )
+ CALL ZSCAL( N-1, ALPHA, X, INCX )
+*
+* If ALPHA is subnormal, it may lose relative accuracy
+*
+ DO 20 J = 1, KNT
+ BETA = BETA*SAFMIN
+ 20 CONTINUE
+ ALPHA = BETA
+ END IF
+*
+ RETURN
+*
+* End of ZLARFG
+*
+ END
diff --git a/lapack/zlarft.f b/lapack/zlarft.f
new file mode 100644
index 000000000..6a6151fd0
--- /dev/null
+++ b/lapack/zlarft.f
@@ -0,0 +1,327 @@
+*> \brief \b ZLARFT
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download ZLARFT + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zlarft.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zlarft.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlarft.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE ZLARFT( DIRECT, STOREV, N, K, V, LDV, TAU, T, LDT )
+*
+* .. Scalar Arguments ..
+* CHARACTER DIRECT, STOREV
+* INTEGER K, LDT, LDV, N
+* ..
+* .. Array Arguments ..
+* COMPLEX*16 T( LDT, * ), TAU( * ), V( LDV, * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> ZLARFT forms the triangular factor T of a complex block reflector H
+*> of order n, which is defined as a product of k elementary reflectors.
+*>
+*> If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular;
+*>
+*> If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular.
+*>
+*> If STOREV = 'C', the vector which defines the elementary reflector
+*> H(i) is stored in the i-th column of the array V, and
+*>
+*> H = I - V * T * V**H
+*>
+*> If STOREV = 'R', the vector which defines the elementary reflector
+*> H(i) is stored in the i-th row of the array V, and
+*>
+*> H = I - V**H * T * V
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] DIRECT
+*> \verbatim
+*> DIRECT is CHARACTER*1
+*> Specifies the order in which the elementary reflectors are
+*> multiplied to form the block reflector:
+*> = 'F': H = H(1) H(2) . . . H(k) (Forward)
+*> = 'B': H = H(k) . . . H(2) H(1) (Backward)
+*> \endverbatim
+*>
+*> \param[in] STOREV
+*> \verbatim
+*> STOREV is CHARACTER*1
+*> Specifies how the vectors which define the elementary
+*> reflectors are stored (see also Further Details):
+*> = 'C': columnwise
+*> = 'R': rowwise
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The order of the block reflector H. N >= 0.
+*> \endverbatim
+*>
+*> \param[in] K
+*> \verbatim
+*> K is INTEGER
+*> The order of the triangular factor T (= the number of
+*> elementary reflectors). K >= 1.
+*> \endverbatim
+*>
+*> \param[in] V
+*> \verbatim
+*> V is COMPLEX*16 array, dimension
+*> (LDV,K) if STOREV = 'C'
+*> (LDV,N) if STOREV = 'R'
+*> The matrix V. See further details.
+*> \endverbatim
+*>
+*> \param[in] LDV
+*> \verbatim
+*> LDV is INTEGER
+*> The leading dimension of the array V.
+*> If STOREV = 'C', LDV >= max(1,N); if STOREV = 'R', LDV >= K.
+*> \endverbatim
+*>
+*> \param[in] TAU
+*> \verbatim
+*> TAU is COMPLEX*16 array, dimension (K)
+*> TAU(i) must contain the scalar factor of the elementary
+*> reflector H(i).
+*> \endverbatim
+*>
+*> \param[out] T
+*> \verbatim
+*> T is COMPLEX*16 array, dimension (LDT,K)
+*> The k by k triangular factor T of the block reflector.
+*> If DIRECT = 'F', T is upper triangular; if DIRECT = 'B', T is
+*> lower triangular. The rest of the array is not used.
+*> \endverbatim
+*>
+*> \param[in] LDT
+*> \verbatim
+*> LDT is INTEGER
+*> The leading dimension of the array T. LDT >= K.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date April 2012
+*
+*> \ingroup complex16OTHERauxiliary
+*
+*> \par Further Details:
+* =====================
+*>
+*> \verbatim
+*>
+*> The shape of the matrix V and the storage of the vectors which define
+*> the H(i) is best illustrated by the following example with n = 5 and
+*> k = 3. The elements equal to 1 are not stored.
+*>
+*> DIRECT = 'F' and STOREV = 'C': DIRECT = 'F' and STOREV = 'R':
+*>
+*> V = ( 1 ) V = ( 1 v1 v1 v1 v1 )
+*> ( v1 1 ) ( 1 v2 v2 v2 )
+*> ( v1 v2 1 ) ( 1 v3 v3 )
+*> ( v1 v2 v3 )
+*> ( v1 v2 v3 )
+*>
+*> DIRECT = 'B' and STOREV = 'C': DIRECT = 'B' and STOREV = 'R':
+*>
+*> V = ( v1 v2 v3 ) V = ( v1 v1 1 )
+*> ( v1 v2 v3 ) ( v2 v2 v2 1 )
+*> ( 1 v2 v3 ) ( v3 v3 v3 v3 1 )
+*> ( 1 v3 )
+*> ( 1 )
+*> \endverbatim
+*>
+* =====================================================================
+ SUBROUTINE ZLARFT( DIRECT, STOREV, N, K, V, LDV, TAU, T, LDT )
+*
+* -- LAPACK auxiliary routine (version 3.4.1) --
+* -- LAPACK is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* April 2012
+*
+* .. Scalar Arguments ..
+ CHARACTER DIRECT, STOREV
+ INTEGER K, LDT, LDV, N
+* ..
+* .. Array Arguments ..
+ COMPLEX*16 T( LDT, * ), TAU( * ), V( LDV, * )
+* ..
+*
+* =====================================================================
+*
+* .. Parameters ..
+ COMPLEX*16 ONE, ZERO
+ PARAMETER ( ONE = ( 1.0D+0, 0.0D+0 ),
+ $ ZERO = ( 0.0D+0, 0.0D+0 ) )
+* ..
+* .. Local Scalars ..
+ INTEGER I, J, PREVLASTV, LASTV
+* ..
+* .. External Subroutines ..
+ EXTERNAL ZGEMV, ZLACGV, ZTRMV
+* ..
+* .. External Functions ..
+ LOGICAL LSAME
+ EXTERNAL LSAME
+* ..
+* .. Executable Statements ..
+*
+* Quick return if possible
+*
+ IF( N.EQ.0 )
+ $ RETURN
+*
+ IF( LSAME( DIRECT, 'F' ) ) THEN
+ PREVLASTV = N
+ DO I = 1, K
+ PREVLASTV = MAX( PREVLASTV, I )
+ IF( TAU( I ).EQ.ZERO ) THEN
+*
+* H(i) = I
+*
+ DO J = 1, I
+ T( J, I ) = ZERO
+ END DO
+ ELSE
+*
+* general case
+*
+ IF( LSAME( STOREV, 'C' ) ) THEN
+* Skip any trailing zeros.
+ DO LASTV = N, I+1, -1
+ IF( V( LASTV, I ).NE.ZERO ) EXIT
+ END DO
+ DO J = 1, I-1
+ T( J, I ) = -TAU( I ) * CONJG( V( I , J ) )
+ END DO
+ J = MIN( LASTV, PREVLASTV )
+*
+* T(1:i-1,i) := - tau(i) * V(i:j,1:i-1)**H * V(i:j,i)
+*
+ CALL ZGEMV( 'Conjugate transpose', J-I, I-1,
+ $ -TAU( I ), V( I+1, 1 ), LDV,
+ $ V( I+1, I ), 1, ONE, T( 1, I ), 1 )
+ ELSE
+* Skip any trailing zeros.
+ DO LASTV = N, I+1, -1
+ IF( V( I, LASTV ).NE.ZERO ) EXIT
+ END DO
+ DO J = 1, I-1
+ T( J, I ) = -TAU( I ) * V( J , I )
+ END DO
+ J = MIN( LASTV, PREVLASTV )
+*
+* T(1:i-1,i) := - tau(i) * V(1:i-1,i:j) * V(i,i:j)**H
+*
+ CALL ZGEMM( 'N', 'C', I-1, 1, J-I, -TAU( I ),
+ $ V( 1, I+1 ), LDV, V( I, I+1 ), LDV,
+ $ ONE, T( 1, I ), LDT )
+ END IF
+*
+* T(1:i-1,i) := T(1:i-1,1:i-1) * T(1:i-1,i)
+*
+ CALL ZTRMV( 'Upper', 'No transpose', 'Non-unit', I-1, T,
+ $ LDT, T( 1, I ), 1 )
+ T( I, I ) = TAU( I )
+ IF( I.GT.1 ) THEN
+ PREVLASTV = MAX( PREVLASTV, LASTV )
+ ELSE
+ PREVLASTV = LASTV
+ END IF
+ END IF
+ END DO
+ ELSE
+ PREVLASTV = 1
+ DO I = K, 1, -1
+ IF( TAU( I ).EQ.ZERO ) THEN
+*
+* H(i) = I
+*
+ DO J = I, K
+ T( J, I ) = ZERO
+ END DO
+ ELSE
+*
+* general case
+*
+ IF( I.LT.K ) THEN
+ IF( LSAME( STOREV, 'C' ) ) THEN
+* Skip any leading zeros.
+ DO LASTV = 1, I-1
+ IF( V( LASTV, I ).NE.ZERO ) EXIT
+ END DO
+ DO J = I+1, K
+ T( J, I ) = -TAU( I ) * CONJG( V( N-K+I , J ) )
+ END DO
+ J = MAX( LASTV, PREVLASTV )
+*
+* T(i+1:k,i) = -tau(i) * V(j:n-k+i,i+1:k)**H * V(j:n-k+i,i)
+*
+ CALL ZGEMV( 'Conjugate transpose', N-K+I-J, K-I,
+ $ -TAU( I ), V( J, I+1 ), LDV, V( J, I ),
+ $ 1, ONE, T( I+1, I ), 1 )
+ ELSE
+* Skip any leading zeros.
+ DO LASTV = 1, I-1
+ IF( V( I, LASTV ).NE.ZERO ) EXIT
+ END DO
+ DO J = I+1, K
+ T( J, I ) = -TAU( I ) * V( J, N-K+I )
+ END DO
+ J = MAX( LASTV, PREVLASTV )
+*
+* T(i+1:k,i) = -tau(i) * V(i+1:k,j:n-k+i) * V(i,j:n-k+i)**H
+*
+ CALL ZGEMM( 'N', 'C', K-I, 1, N-K+I-J, -TAU( I ),
+ $ V( I+1, J ), LDV, V( I, J ), LDV,
+ $ ONE, T( I+1, I ), LDT )
+ END IF
+*
+* T(i+1:k,i) := T(i+1:k,i+1:k) * T(i+1:k,i)
+*
+ CALL ZTRMV( 'Lower', 'No transpose', 'Non-unit', K-I,
+ $ T( I+1, I+1 ), LDT, T( I+1, I ), 1 )
+ IF( I.GT.1 ) THEN
+ PREVLASTV = MIN( PREVLASTV, LASTV )
+ ELSE
+ PREVLASTV = LASTV
+ END IF
+ END IF
+ T( I, I ) = TAU( I )
+ END IF
+ END DO
+ END IF
+ RETURN
+*
+* End of ZLARFT
+*
+ END
diff --git a/scripts/cdashtesting.cmake.in b/scripts/cdashtesting.cmake.in
new file mode 100644
index 000000000..59cf53328
--- /dev/null
+++ b/scripts/cdashtesting.cmake.in
@@ -0,0 +1,49 @@
+
+set(CTEST_SOURCE_DIRECTORY "@CMAKE_SOURCE_DIR@")
+set(CTEST_BINARY_DIRECTORY "@CMAKE_BINARY_DIR@")
+set(CTEST_CMAKE_GENERATOR "@CMAKE_GENERATOR@")
+set(CTEST_BUILD_NAME "@BUILDNAME@")
+set(CTEST_SITE "@SITE@")
+
+set(MODEL Experimental)
+if(${CTEST_SCRIPT_ARG} MATCHES Nightly)
+ set(MODEL Nightly)
+elseif(${CTEST_SCRIPT_ARG} MATCHES Continuous)
+ set(MODEL Continuous)
+endif()
+
+find_program(CTEST_HG_COMMAND NAMES hg)
+set(CTEST_UPDATE_COMMAND "${CTEST_HG_COMMAND}")
+
+ctest_start(${MODEL} ${CTEST_SOURCE_DIRECTORY} ${CTEST_BINARY_DIRECTORY})
+
+ctest_update(SOURCE "${CTEST_SOURCE_DIRECTORY}")
+ctest_submit(PARTS Update Notes)
+
+# to get CTEST_PROJECT_SUBPROJECTS definition:
+include("${CTEST_SOURCE_DIRECTORY}/CTestConfig.cmake")
+
+foreach(subproject ${CTEST_PROJECT_SUBPROJECTS})
+ message("")
+ message("Process ${subproject}")
+
+ set_property(GLOBAL PROPERTY SubProject ${subproject})
+ set_property(GLOBAL PROPERTY Label ${subproject})
+
+ ctest_configure(BUILD ${CTEST_BINARY_DIRECTORY} SOURCE ${CTEST_SOURCE_DIRECTORY} )
+ ctest_submit(PARTS Configure)
+
+ set(CTEST_BUILD_TARGET "Build${subproject}")
+ message("Build ${CTEST_BUILD_TARGET}")
+ ctest_build(BUILD "${CTEST_BINARY_DIRECTORY}" APPEND)
+ # builds target ${CTEST_BUILD_TARGET}
+ ctest_submit(PARTS Build)
+
+ ctest_test(BUILD "${CTEST_BINARY_DIRECTORY}" INCLUDE_LABEL "${subproject}" )
+ # runs only tests that have a LABELS property matching "${subproject}"
+
+ ctest_coverage(BUILD "${CTEST_BINARY_DIRECTORY}" LABELS "${subproject}" )
+
+ ctest_submit(PARTS Test)
+
+endforeach()
diff --git a/scripts/eigen_gen_docs b/scripts/eigen_gen_docs
index 921d600ed..0e6f9ada2 100644
--- a/scripts/eigen_gen_docs
+++ b/scripts/eigen_gen_docs
@@ -4,19 +4,21 @@
# You should call this script with USER set as you want, else some default
# will be used
USER=${USER:-'orzel'}
+UPLOAD_DIR=dox
#ulimit -v 1024000
# step 1 : build
+rm build/doc/html -Rf
mkdir build -p
(cd build && cmake .. && make doc) || { echo "make failed"; exit 1; }
#step 2 : upload
# (the '/' at the end of path is very important, see rsync documentation)
-rsync -az --no-p --delete build/doc/html/ $USER@ssh.tuxfamily.org:eigen/eigen.tuxfamily.org-web/htdocs/dox-devel/ || { echo "upload failed"; exit 1; }
+rsync -az --no-p --delete build/doc/html/ $USER@ssh.tuxfamily.org:eigen/eigen.tuxfamily.org-web/htdocs/$UPLOAD_DIR/ || { echo "upload failed"; exit 1; }
#step 3 : fix the perm
-ssh $USER@ssh.tuxfamily.org 'chmod -R g+w /home/eigen/eigen.tuxfamily.org-web/htdocs/dox-devel' || { echo "perm failed"; exit 1; }
+ssh $USER@ssh.tuxfamily.org "chmod -R g+w /home/eigen/eigen.tuxfamily.org-web/htdocs/$UPLOAD_DIR" || { echo "perm failed"; exit 1; }
echo "Uploaded successfully"
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 6f8fc4ae3..ccb0fc798 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -86,6 +86,27 @@ else()
ei_add_property(EIGEN_MISSING_BACKENDS "PaStiX, ")
endif()
+if(METIS_FOUND)
+ add_definitions("-DEIGEN_METIS_SUPPORT")
+ include_directories(${METIS_INCLUDES})
+ ei_add_property(EIGEN_TESTED_BACKENDS "METIS, ")
+else()
+ ei_add_property(EIGEN_MISSING_BACKENDS "METIS, ")
+endif()
+
+find_package(SPQR)
+if(SPQR_FOUND AND BLAS_FOUND AND LAPACK_FOUND)
+ if(CHOLMOD_FOUND)
+ add_definitions("-DEIGEN_SPQR_SUPPORT")
+ include_directories(${SPQR_INCLUDES})
+ set(SPQR_ALL_LIBS ${SPQR_LIBRARIES} ${CHOLMOD_LIBRARIES} ${LAPACK_LIBRARIES} ${BLAS_LIBRARIES})
+ set(SPARSE_LIBS ${SPARSE_LIBS} ${SPQR_ALL_LIBS})
+ ei_add_property(EIGEN_TESTED_BACKENDS "SPQR, ")
+ else(CHOLMOD_FOUND)
+ ei_add_property(EIGEN_MISSING_BACKENDS "SPQR, ")
+ endif(CHOLMOD_FOUND)
+endif()
+
option(EIGEN_TEST_NOQT "Disable Qt support in unit tests" OFF)
if(NOT EIGEN_TEST_NOQT)
find_package(Qt4)
@@ -101,6 +122,9 @@ if(TEST_LIB)
add_definitions("-DEIGEN_EXTERN_INSTANTIATIONS=1")
endif(TEST_LIB)
+set_property(GLOBAL PROPERTY EIGEN_CURRENT_SUBPROJECT "Official")
+add_custom_target(BuildOfficial)
+
ei_add_test(meta)
ei_add_test(sizeof)
ei_add_test(dynalloc)
@@ -129,13 +153,14 @@ ei_add_test(diagonal)
ei_add_test(miscmatrices)
ei_add_test(commainitializer)
ei_add_test(smallvectors)
-ei_add_test(map)
+ei_add_test(mapped_matrix)
ei_add_test(mapstride)
ei_add_test(mapstaticmethods)
ei_add_test(array)
ei_add_test(array_for_matrix)
ei_add_test(array_replicate)
ei_add_test(array_reverse)
+ei_add_test(ref)
ei_add_test(triangular)
ei_add_test(selfadjoint)
ei_add_test(product_selfadjoint)
@@ -162,6 +187,8 @@ ei_add_test(schur_complex)
ei_add_test(eigensolver_selfadjoint)
ei_add_test(eigensolver_generic)
ei_add_test(eigensolver_complex)
+ei_add_test(real_qz)
+ei_add_test(eigensolver_generalized_real)
ei_add_test(jacobi)
ei_add_test(jacobisvd)
ei_add_test(geo_orthomethods)
@@ -177,9 +204,6 @@ ei_add_test(stdvector_overload)
ei_add_test(stdlist)
ei_add_test(stddeque)
ei_add_test(resize)
-if(QT4_FOUND)
- ei_add_test(qtvector "" "${QT_QTCORE_LIBRARY}")
-endif(QT4_FOUND)
ei_add_test(sparse_vector)
ei_add_test(sparse_basic)
ei_add_test(sparse_product)
@@ -190,7 +214,6 @@ ei_add_test(swap)
ei_add_test(conservative_resize)
ei_add_test(permutationmatrices)
ei_add_test(sparse_permutations)
-ei_add_test(eigen2support)
ei_add_test(nullary)
ei_add_test(nesting_ops "${CMAKE_CXX_FLAGS_DEBUG}")
ei_add_test(zerosized)
@@ -198,11 +221,21 @@ ei_add_test(dontalign)
ei_add_test(sizeoverflow)
ei_add_test(prec_inverse_4x4)
ei_add_test(vectorwiseop)
+ei_add_test(special_numbers)
ei_add_test(simplicial_cholesky)
ei_add_test(conjugate_gradient)
ei_add_test(bicgstab)
+ei_add_test(sparselu)
+ei_add_test(sparseqr)
+# ei_add_test(denseLM)
+
+if(QT4_FOUND)
+ ei_add_test(qtvector "" "${QT_QTCORE_LIBRARY}")
+endif(QT4_FOUND)
+
+ei_add_test(eigen2support)
if(UMFPACK_FOUND)
ei_add_test(umfpack_support "" "${UMFPACK_ALL_LIBS}")
@@ -224,6 +257,14 @@ if(PASTIX_FOUND AND (SCOTCH_FOUND OR METIS_FOUND))
ei_add_test(pastix_support "" "${PASTIX_ALL_LIBS}")
endif()
+if(SPQR_FOUND AND CHOLMOD_FOUND)
+ ei_add_test(spqr_support "" "${SPQR_ALL_LIBS}")
+endif()
+
+if(METIS_FOUND)
+ei_add_test(metis_support "" "${METIS_LIBRARIES}")
+endif()
+
string(TOLOWER "${CMAKE_CXX_COMPILER}" cmake_cxx_compiler_tolower)
if(cmake_cxx_compiler_tolower MATCHES "qcc")
set(CXX_IS_QCC "ON")
diff --git a/test/adjoint.cpp b/test/adjoint.cpp
index b6cf0a68b..ea36f7841 100644
--- a/test/adjoint.cpp
+++ b/test/adjoint.cpp
@@ -11,11 +11,54 @@
#include "main.h"
+template<bool IsInteger> struct adjoint_specific;
+
+template<> struct adjoint_specific<true> {
+ template<typename Vec, typename Mat, typename Scalar>
+ static void run(const Vec& v1, const Vec& v2, Vec& v3, const Mat& square, Scalar s1, Scalar s2) {
+ VERIFY(test_isApproxWithRef((s1 * v1 + s2 * v2).dot(v3), numext::conj(s1) * v1.dot(v3) + numext::conj(s2) * v2.dot(v3), 0));
+ VERIFY(test_isApproxWithRef(v3.dot(s1 * v1 + s2 * v2), s1*v3.dot(v1)+s2*v3.dot(v2), 0));
+
+ // check compatibility of dot and adjoint
+ VERIFY(test_isApproxWithRef(v1.dot(square * v2), (square.adjoint() * v1).dot(v2), 0));
+ }
+};
+
+template<> struct adjoint_specific<false> {
+ template<typename Vec, typename Mat, typename Scalar>
+ static void run(const Vec& v1, const Vec& v2, Vec& v3, const Mat& square, Scalar s1, Scalar s2) {
+ typedef typename NumTraits<Scalar>::Real RealScalar;
+ using std::abs;
+
+ RealScalar ref = NumTraits<Scalar>::IsInteger ? RealScalar(0) : (std::max)((s1 * v1 + s2 * v2).norm(),v3.norm());
+ VERIFY(test_isApproxWithRef((s1 * v1 + s2 * v2).dot(v3), numext::conj(s1) * v1.dot(v3) + numext::conj(s2) * v2.dot(v3), ref));
+ VERIFY(test_isApproxWithRef(v3.dot(s1 * v1 + s2 * v2), s1*v3.dot(v1)+s2*v3.dot(v2), ref));
+
+ VERIFY_IS_APPROX(v1.squaredNorm(), v1.norm() * v1.norm());
+ // check normalized() and normalize()
+ VERIFY_IS_APPROX(v1, v1.norm() * v1.normalized());
+ v3 = v1;
+ v3.normalize();
+ VERIFY_IS_APPROX(v1, v1.norm() * v3);
+ VERIFY_IS_APPROX(v3, v1.normalized());
+ VERIFY_IS_APPROX(v3.norm(), RealScalar(1));
+
+ // check compatibility of dot and adjoint
+ ref = NumTraits<Scalar>::IsInteger ? 0 : (std::max)((std::max)(v1.norm(),v2.norm()),(std::max)((square * v2).norm(),(square.adjoint() * v1).norm()));
+ VERIFY(internal::isMuchSmallerThan(abs(v1.dot(square * v2) - (square.adjoint() * v1).dot(v2)), ref, test_precision<Scalar>()));
+
+ // check that Random().normalized() works: tricky as the random xpr must be evaluated by
+ // normalized() in order to produce a consistent result.
+ VERIFY_IS_APPROX(Vec::Random(v1.size()).normalized().norm(), RealScalar(1));
+ }
+};
+
template<typename MatrixType> void adjoint(const MatrixType& m)
{
/* this test covers the following files:
Transpose.h Conjugate.h Dot.h
*/
+ using std::abs;
typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
@@ -43,45 +86,21 @@ template<typename MatrixType> void adjoint(const MatrixType& m)
// check multiplicative behavior
VERIFY_IS_APPROX((m1.adjoint() * m2).adjoint(), m2.adjoint() * m1);
- VERIFY_IS_APPROX((s1 * m1).adjoint(), internal::conj(s1) * m1.adjoint());
+ VERIFY_IS_APPROX((s1 * m1).adjoint(), numext::conj(s1) * m1.adjoint());
- // check basic properties of dot, norm, norm2
- typedef typename NumTraits<Scalar>::Real RealScalar;
+ // check basic properties of dot, squaredNorm
+ VERIFY_IS_APPROX(numext::conj(v1.dot(v2)), v2.dot(v1));
+ VERIFY_IS_APPROX(numext::real(v1.dot(v1)), v1.squaredNorm());
- RealScalar ref = NumTraits<Scalar>::IsInteger ? RealScalar(0) : (std::max)((s1 * v1 + s2 * v2).norm(),v3.norm());
- VERIFY(test_isApproxWithRef((s1 * v1 + s2 * v2).dot(v3), internal::conj(s1) * v1.dot(v3) + internal::conj(s2) * v2.dot(v3), ref));
- VERIFY(test_isApproxWithRef(v3.dot(s1 * v1 + s2 * v2), s1*v3.dot(v1)+s2*v3.dot(v2), ref));
- VERIFY_IS_APPROX(internal::conj(v1.dot(v2)), v2.dot(v1));
- VERIFY_IS_APPROX(internal::real(v1.dot(v1)), v1.squaredNorm());
- if(!NumTraits<Scalar>::IsInteger) {
- VERIFY_IS_APPROX(v1.squaredNorm(), v1.norm() * v1.norm());
- // check normalized() and normalize()
- VERIFY_IS_APPROX(v1, v1.norm() * v1.normalized());
- v3 = v1;
- v3.normalize();
- VERIFY_IS_APPROX(v1, v1.norm() * v3);
- VERIFY_IS_APPROX(v3, v1.normalized());
- VERIFY_IS_APPROX(v3.norm(), RealScalar(1));
- }
- VERIFY_IS_MUCH_SMALLER_THAN(internal::abs(vzero.dot(v1)), static_cast<RealScalar>(1));
+ adjoint_specific<NumTraits<Scalar>::IsInteger>::run(v1, v2, v3, square, s1, s2);
- // check compatibility of dot and adjoint
+ VERIFY_IS_MUCH_SMALLER_THAN(abs(vzero.dot(v1)), static_cast<RealScalar>(1));
- ref = NumTraits<Scalar>::IsInteger ? 0 : (std::max)((std::max)(v1.norm(),v2.norm()),(std::max)((square * v2).norm(),(square.adjoint() * v1).norm()));
- VERIFY(test_isApproxWithRef(v1.dot(square * v2), (square.adjoint() * v1).dot(v2), ref));
-
// like in testBasicStuff, test operator() to check const-qualification
Index r = internal::random<Index>(0, rows-1),
c = internal::random<Index>(0, cols-1);
- VERIFY_IS_APPROX(m1.conjugate()(r,c), internal::conj(m1(r,c)));
- VERIFY_IS_APPROX(m1.adjoint()(c,r), internal::conj(m1(r,c)));
-
- if(!NumTraits<Scalar>::IsInteger)
- {
- // check that Random().normalized() works: tricky as the random xpr must be evaluated by
- // normalized() in order to produce a consistent result.
- VERIFY_IS_APPROX(VectorType::Random(rows).normalized().norm(), RealScalar(1));
- }
+ VERIFY_IS_APPROX(m1.conjugate()(r,c), numext::conj(m1(r,c)));
+ VERIFY_IS_APPROX(m1.adjoint()(c,r), numext::conj(m1(r,c)));
// check inplace transpose
m3 = m1;
diff --git a/test/array.cpp b/test/array.cpp
index 3548fa641..c607da631 100644
--- a/test/array.cpp
+++ b/test/array.cpp
@@ -13,7 +13,6 @@ template<typename ArrayType> void array(const ArrayType& m)
{
typedef typename ArrayType::Index Index;
typedef typename ArrayType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
typedef Array<Scalar, ArrayType::RowsAtCompileTime, 1> ColVectorType;
typedef Array<Scalar, 1, ArrayType::ColsAtCompileTime> RowVectorType;
@@ -64,9 +63,12 @@ template<typename ArrayType> void array(const ArrayType& m)
VERIFY_IS_APPROX(m1, m3 / m2);
// reductions
- VERIFY_IS_APPROX(m1.colwise().sum().sum(), m1.sum());
- VERIFY_IS_APPROX(m1.rowwise().sum().sum(), m1.sum());
- if (!internal::isApprox(m1.sum(), (m1+m2).sum(), test_precision<Scalar>()))
+ VERIFY_IS_APPROX(m1.abs().colwise().sum().sum(), m1.abs().sum());
+ VERIFY_IS_APPROX(m1.abs().rowwise().sum().sum(), m1.abs().sum());
+ using std::abs;
+ VERIFY_IS_MUCH_SMALLER_THAN(abs(m1.colwise().sum().sum() - m1.sum()), m1.abs().sum());
+ VERIFY_IS_MUCH_SMALLER_THAN(abs(m1.rowwise().sum().sum() - m1.sum()), m1.abs().sum());
+ if (!internal::isMuchSmallerThan(abs(m1.sum() - (m1+m2).sum()), m1.abs().sum(), test_precision<Scalar>()))
VERIFY_IS_NOT_APPROX(((m1+m2).rowwise().sum()).sum(), m1.sum());
VERIFY_IS_APPROX(m1.colwise().sum(), m1.colwise().redux(internal::scalar_sum_op<Scalar>()));
@@ -83,10 +85,10 @@ template<typename ArrayType> void array(const ArrayType& m)
template<typename ArrayType> void comparisons(const ArrayType& m)
{
+ using std::abs;
typedef typename ArrayType::Index Index;
typedef typename ArrayType::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef Array<Scalar, ArrayType::RowsAtCompileTime, 1> VectorType;
Index rows = m.rows();
Index cols = m.cols();
@@ -120,7 +122,7 @@ template<typename ArrayType> void comparisons(const ArrayType& m)
Scalar mid = (m1.cwiseAbs().minCoeff() + m1.cwiseAbs().maxCoeff())/Scalar(2);
for (int j=0; j<cols; ++j)
for (int i=0; i<rows; ++i)
- m3(i,j) = internal::abs(m1(i,j))<mid ? 0 : m1(i,j);
+ m3(i,j) = abs(m1(i,j))<mid ? 0 : m1(i,j);
VERIFY_IS_APPROX( (m1.abs()<ArrayType::Constant(rows,cols,mid))
.select(ArrayType::Zero(rows,cols),m1), m3);
// shorter versions:
@@ -149,6 +151,8 @@ template<typename ArrayType> void comparisons(const ArrayType& m)
template<typename ArrayType> void array_real(const ArrayType& m)
{
+ using std::abs;
+ using std::sqrt;
typedef typename ArrayType::Index Index;
typedef typename ArrayType::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
@@ -157,58 +161,58 @@ template<typename ArrayType> void array_real(const ArrayType& m)
Index cols = m.cols();
ArrayType m1 = ArrayType::Random(rows, cols),
- m2 = ArrayType::Random(rows, cols),
- m3(rows, cols);
+ m2 = ArrayType::Random(rows, cols),
+ m3(rows, cols);
Scalar s1 = internal::random<Scalar>();
// these tests are mostly to check possible compilation issues.
- VERIFY_IS_APPROX(m1.sin(), std::sin(m1));
- VERIFY_IS_APPROX(m1.sin(), internal::sin(m1));
- VERIFY_IS_APPROX(m1.cos(), std::cos(m1));
- VERIFY_IS_APPROX(m1.cos(), internal::cos(m1));
- VERIFY_IS_APPROX(m1.asin(), std::asin(m1));
- VERIFY_IS_APPROX(m1.asin(), internal::asin(m1));
- VERIFY_IS_APPROX(m1.acos(), std::acos(m1));
- VERIFY_IS_APPROX(m1.acos(), internal::acos(m1));
- VERIFY_IS_APPROX(m1.tan(), std::tan(m1));
- VERIFY_IS_APPROX(m1.tan(), internal::tan(m1));
+ VERIFY_IS_APPROX(m1.sin(), sin(m1));
+ VERIFY_IS_APPROX(m1.cos(), cos(m1));
+ VERIFY_IS_APPROX(m1.asin(), asin(m1));
+ VERIFY_IS_APPROX(m1.acos(), acos(m1));
+ VERIFY_IS_APPROX(m1.tan(), tan(m1));
- VERIFY_IS_APPROX(internal::cos(m1+RealScalar(3)*m2), internal::cos((m1+RealScalar(3)*m2).eval()));
- VERIFY_IS_APPROX(std::cos(m1+RealScalar(3)*m2), std::cos((m1+RealScalar(3)*m2).eval()));
+ VERIFY_IS_APPROX(cos(m1+RealScalar(3)*m2), cos((m1+RealScalar(3)*m2).eval()));
- VERIFY_IS_APPROX(m1.abs().sqrt(), std::sqrt(std::abs(m1)));
- VERIFY_IS_APPROX(m1.abs().sqrt(), internal::sqrt(internal::abs(m1)));
- VERIFY_IS_APPROX(m1.abs(), internal::sqrt(internal::abs2(m1)));
+ VERIFY_IS_APPROX(m1.abs().sqrt(), sqrt(abs(m1)));
+ VERIFY_IS_APPROX(m1.abs(), sqrt(numext::abs2(m1)));
- VERIFY_IS_APPROX(internal::abs2(internal::real(m1)) + internal::abs2(internal::imag(m1)), internal::abs2(m1));
- VERIFY_IS_APPROX(internal::abs2(std::real(m1)) + internal::abs2(std::imag(m1)), internal::abs2(m1));
+ VERIFY_IS_APPROX(numext::abs2(numext::real(m1)) + numext::abs2(numext::imag(m1)), numext::abs2(m1));
+ VERIFY_IS_APPROX(numext::abs2(real(m1)) + numext::abs2(imag(m1)), numext::abs2(m1));
if(!NumTraits<Scalar>::IsComplex)
- VERIFY_IS_APPROX(internal::real(m1), m1);
+ VERIFY_IS_APPROX(numext::real(m1), m1);
- VERIFY_IS_APPROX(m1.abs().log(), std::log(std::abs(m1)));
- VERIFY_IS_APPROX(m1.abs().log(), internal::log(internal::abs(m1)));
+ // shift argument of logarithm so that it is not zero
+ Scalar smallNumber = NumTraits<Scalar>::dummy_precision();
+ VERIFY_IS_APPROX((m1.abs() + smallNumber).log() , log(abs(m1) + smallNumber));
- VERIFY_IS_APPROX(m1.exp(), std::exp(m1));
- VERIFY_IS_APPROX(m1.exp() * m2.exp(), std::exp(m1+m2));
- VERIFY_IS_APPROX(m1.exp(), internal::exp(m1));
- VERIFY_IS_APPROX(m1.exp() / m2.exp(), std::exp(m1-m2));
+ VERIFY_IS_APPROX(m1.exp() * m2.exp(), exp(m1+m2));
+ VERIFY_IS_APPROX(m1.exp(), exp(m1));
+ VERIFY_IS_APPROX(m1.exp() / m2.exp(),(m1-m2).exp());
VERIFY_IS_APPROX(m1.pow(2), m1.square());
- VERIFY_IS_APPROX(std::pow(m1,2), m1.square());
+ VERIFY_IS_APPROX(pow(m1,2), m1.square());
ArrayType exponents = ArrayType::Constant(rows, cols, RealScalar(2));
- VERIFY_IS_APPROX(std::pow(m1,exponents), m1.square());
+ VERIFY_IS_APPROX(Eigen::pow(m1,exponents), m1.square());
m3 = m1.abs();
VERIFY_IS_APPROX(m3.pow(RealScalar(0.5)), m3.sqrt());
- VERIFY_IS_APPROX(std::pow(m3,RealScalar(0.5)), m3.sqrt());
+ VERIFY_IS_APPROX(pow(m3,RealScalar(0.5)), m3.sqrt());
// scalar by array division
- const RealScalar tiny = std::sqrt(std::numeric_limits<RealScalar>::epsilon());
+ const RealScalar tiny = sqrt(std::numeric_limits<RealScalar>::epsilon());
s1 += Scalar(tiny);
m1 += ArrayType::Constant(rows,cols,Scalar(tiny));
VERIFY_IS_APPROX(s1/m1, s1 * m1.inverse());
+
+ // check inplace transpose
+ m3 = m1;
+ m3.transposeInPlace();
+ VERIFY_IS_APPROX(m3,m1.transpose());
+ m3.transposeInPlace();
+ VERIFY_IS_APPROX(m3,m1);
}
template<typename ArrayType> void array_complex(const ArrayType& m)
@@ -223,11 +227,10 @@ template<typename ArrayType> void array_complex(const ArrayType& m)
for (Index i = 0; i < m.rows(); ++i)
for (Index j = 0; j < m.cols(); ++j)
- m2(i,j) = std::sqrt(m1(i,j));
+ m2(i,j) = sqrt(m1(i,j));
VERIFY_IS_APPROX(m1.sqrt(), m2);
- VERIFY_IS_APPROX(m1.sqrt(), std::sqrt(m1));
- VERIFY_IS_APPROX(m1.sqrt(), internal::sqrt(m1));
+ VERIFY_IS_APPROX(m1.sqrt(), Eigen::sqrt(m1));
}
template<typename ArrayType> void min_max(const ArrayType& m)
diff --git a/test/array_for_matrix.cpp b/test/array_for_matrix.cpp
index 4b637c3a6..9a50f99ab 100644
--- a/test/array_for_matrix.cpp
+++ b/test/array_for_matrix.cpp
@@ -13,7 +13,6 @@ template<typename MatrixType> void array_for_matrix(const MatrixType& m)
{
typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> ColVectorType;
typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType;
@@ -26,10 +25,10 @@ template<typename MatrixType> void array_for_matrix(const MatrixType& m)
ColVectorType cv1 = ColVectorType::Random(rows);
RowVectorType rv1 = RowVectorType::Random(cols);
-
+
Scalar s1 = internal::random<Scalar>(),
s2 = internal::random<Scalar>();
-
+
// scalar addition
VERIFY_IS_APPROX(m1.array() + s1, s1 + m1.array());
VERIFY_IS_APPROX((m1.array() + s1).matrix(), MatrixType::Constant(rows,cols,s1) + m1);
@@ -42,10 +41,10 @@ template<typename MatrixType> void array_for_matrix(const MatrixType& m)
VERIFY_IS_APPROX(m3, (m1.array() - s1).matrix());
// reductions
- VERIFY_IS_MUCH_SMALLER_THAN(m1.colwise().sum().sum() - m1.sum(), m1.cwiseAbs().maxCoeff());
- VERIFY_IS_MUCH_SMALLER_THAN(m1.rowwise().sum().sum() - m1.sum(), m1.cwiseAbs().maxCoeff());
- VERIFY_IS_MUCH_SMALLER_THAN(m1.colwise().sum() + m2.colwise().sum() - (m1+m2).colwise().sum(), (m1+m2).cwiseAbs().maxCoeff());
- VERIFY_IS_MUCH_SMALLER_THAN(m1.rowwise().sum() - m2.rowwise().sum() - (m1-m2).rowwise().sum(), (m1-m2).cwiseAbs().maxCoeff());
+ VERIFY_IS_MUCH_SMALLER_THAN(m1.colwise().sum().sum() - m1.sum(), m1.squaredNorm());
+ VERIFY_IS_MUCH_SMALLER_THAN(m1.rowwise().sum().sum() - m1.sum(), m1.squaredNorm());
+ VERIFY_IS_MUCH_SMALLER_THAN(m1.colwise().sum() + m2.colwise().sum() - (m1+m2).colwise().sum(), (m1+m2).squaredNorm());
+ VERIFY_IS_MUCH_SMALLER_THAN(m1.rowwise().sum() - m2.rowwise().sum() - (m1-m2).rowwise().sum(), (m1-m2).squaredNorm());
VERIFY_IS_APPROX(m1.colwise().sum(), m1.colwise().redux(internal::scalar_sum_op<Scalar>()));
// vector-wise ops
@@ -73,10 +72,10 @@ template<typename MatrixType> void array_for_matrix(const MatrixType& m)
template<typename MatrixType> void comparisons(const MatrixType& m)
{
+ using std::abs;
typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
Index rows = m.rows();
Index cols = m.cols();
@@ -110,7 +109,7 @@ template<typename MatrixType> void comparisons(const MatrixType& m)
Scalar mid = (m1.cwiseAbs().minCoeff() + m1.cwiseAbs().maxCoeff())/Scalar(2);
for (int j=0; j<cols; ++j)
for (int i=0; i<rows; ++i)
- m3(i,j) = internal::abs(m1(i,j))<mid ? 0 : m1(i,j);
+ m3(i,j) = abs(m1(i,j))<mid ? 0 : m1(i,j);
VERIFY_IS_APPROX( (m1.array().abs()<MatrixType::Constant(rows,cols,mid).array())
.select(MatrixType::Zero(rows,cols),m1), m3);
// shorter versions:
@@ -133,12 +132,13 @@ template<typename MatrixType> void comparisons(const MatrixType& m)
template<typename VectorType> void lpNorm(const VectorType& v)
{
+ using std::sqrt;
VectorType u = VectorType::Random(v.size());
VERIFY_IS_APPROX(u.template lpNorm<Infinity>(), u.cwiseAbs().maxCoeff());
VERIFY_IS_APPROX(u.template lpNorm<1>(), u.cwiseAbs().sum());
- VERIFY_IS_APPROX(u.template lpNorm<2>(), internal::sqrt(u.array().abs().square().sum()));
- VERIFY_IS_APPROX(internal::pow(u.template lpNorm<5>(), typename VectorType::RealScalar(5)), u.array().abs().pow(5).sum());
+ VERIFY_IS_APPROX(u.template lpNorm<2>(), sqrt(u.array().abs().square().sum()));
+ VERIFY_IS_APPROX(numext::pow(u.template lpNorm<5>(), typename VectorType::RealScalar(5)), u.array().abs().pow(5).sum());
}
template<typename MatrixType> void cwise_min_max(const MatrixType& m)
@@ -163,11 +163,53 @@ template<typename MatrixType> void cwise_min_max(const MatrixType& m)
// min/max with scalar input
VERIFY_IS_APPROX(MatrixType::Constant(rows,cols, minM1), m1.cwiseMin( minM1));
- VERIFY_IS_APPROX(m1, m1.cwiseMin( maxM1));
+ VERIFY_IS_APPROX(m1, m1.cwiseMin(maxM1));
+ VERIFY_IS_APPROX(-m1, (-m1).cwiseMin(-minM1));
+ VERIFY_IS_APPROX(-m1.array(), ((-m1).array().min)( -minM1));
VERIFY_IS_APPROX(MatrixType::Constant(rows,cols, maxM1), m1.cwiseMax( maxM1));
- VERIFY_IS_APPROX(m1, m1.cwiseMax( minM1));
+ VERIFY_IS_APPROX(m1, m1.cwiseMax(minM1));
+ VERIFY_IS_APPROX(-m1, (-m1).cwiseMax(-maxM1));
+ VERIFY_IS_APPROX(-m1.array(), ((-m1).array().max)(-maxM1));
+
+ VERIFY_IS_APPROX(MatrixType::Constant(rows,cols, minM1).array(), (m1.array().min)( minM1));
+ VERIFY_IS_APPROX(m1.array(), (m1.array().min)( maxM1));
+
+ VERIFY_IS_APPROX(MatrixType::Constant(rows,cols, maxM1).array(), (m1.array().max)( maxM1));
+ VERIFY_IS_APPROX(m1.array(), (m1.array().max)( minM1));
+
+}
+template<typename MatrixTraits> void resize(const MatrixTraits& t)
+{
+ typedef typename MatrixTraits::Index Index;
+ typedef typename MatrixTraits::Scalar Scalar;
+ typedef Matrix<Scalar,Dynamic,Dynamic> MatrixType;
+ typedef Array<Scalar,Dynamic,Dynamic> Array2DType;
+ typedef Matrix<Scalar,Dynamic,1> VectorType;
+ typedef Array<Scalar,Dynamic,1> Array1DType;
+
+ Index rows = t.rows(), cols = t.cols();
+
+ MatrixType m(rows,cols);
+ VectorType v(rows);
+ Array2DType a2(rows,cols);
+ Array1DType a1(rows);
+
+ m.array().resize(rows+1,cols+1);
+ VERIFY(m.rows()==rows+1 && m.cols()==cols+1);
+ a2.matrix().resize(rows+1,cols+1);
+ VERIFY(a2.rows()==rows+1 && a2.cols()==cols+1);
+ v.array().resize(cols);
+ VERIFY(v.size()==cols);
+ a1.matrix().resize(cols);
+ VERIFY(a1.size()==cols);
+}
+
+void regression_bug_654()
+{
+ ArrayXf a = RowVectorXf(3);
+ VectorXf v = Array<float,1,Dynamic>(3);
}
void test_array_for_matrix()
@@ -202,4 +244,10 @@ void test_array_for_matrix()
CALL_SUBTEST_5( lpNorm(VectorXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
CALL_SUBTEST_4( lpNorm(VectorXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
}
+ for(int i = 0; i < g_repeat; i++) {
+ CALL_SUBTEST_4( resize(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+ CALL_SUBTEST_5( resize(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+ CALL_SUBTEST_6( resize(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+ }
+ CALL_SUBTEST_6( regression_bug_654() );
}
diff --git a/test/array_replicate.cpp b/test/array_replicate.cpp
index 94da7425b..f412d1aed 100644
--- a/test/array_replicate.cpp
+++ b/test/array_replicate.cpp
@@ -16,7 +16,6 @@ template<typename MatrixType> void replicate(const MatrixType& m)
*/
typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
typedef Matrix<Scalar, Dynamic, Dynamic> MatrixX;
typedef Matrix<Scalar, Dynamic, 1> VectorX;
diff --git a/test/basicstuff.cpp b/test/basicstuff.cpp
index 48db531c1..8c0621ecd 100644
--- a/test/basicstuff.cpp
+++ b/test/basicstuff.cpp
@@ -52,8 +52,7 @@ template<typename MatrixType> void basicStuff(const MatrixType& m)
VERIFY_IS_APPROX( v1, v1);
VERIFY_IS_NOT_APPROX( v1, 2*v1);
VERIFY_IS_MUCH_SMALLER_THAN( vzero, v1);
- if(!NumTraits<Scalar>::IsInteger)
- VERIFY_IS_MUCH_SMALLER_THAN( vzero, v1.norm());
+ VERIFY_IS_MUCH_SMALLER_THAN( vzero, v1.squaredNorm());
VERIFY_IS_NOT_MUCH_SMALLER_THAN(v1, v1);
VERIFY_IS_APPROX( vzero, v1-v1);
VERIFY_IS_APPROX( m1, m1);
@@ -142,10 +141,10 @@ template<typename MatrixType> void basicStuffComplex(const MatrixType& m)
Scalar s1 = internal::random<Scalar>(),
s2 = internal::random<Scalar>();
- VERIFY(internal::real(s1)==internal::real_ref(s1));
- VERIFY(internal::imag(s1)==internal::imag_ref(s1));
- internal::real_ref(s1) = internal::real(s2);
- internal::imag_ref(s1) = internal::imag(s2);
+ VERIFY(numext::real(s1)==numext::real_ref(s1));
+ VERIFY(numext::imag(s1)==numext::imag_ref(s1));
+ numext::real_ref(s1) = numext::real(s2);
+ numext::imag_ref(s1) = numext::imag(s2);
VERIFY(internal::isApprox(s1, s2, NumTraits<RealScalar>::epsilon()));
// extended precision in Intel FPUs means that s1 == s2 in the line above is not guaranteed.
diff --git a/test/block.cpp b/test/block.cpp
index 0969262ca..9ed5d7bc5 100644
--- a/test/block.cpp
+++ b/test/block.cpp
@@ -10,6 +10,26 @@
#define EIGEN_NO_STATIC_ASSERT // otherwise we fail at compile time on unused paths
#include "main.h"
+template<typename MatrixType, typename Index, typename Scalar>
+typename Eigen::internal::enable_if<!NumTraits<typename MatrixType::Scalar>::IsComplex,typename MatrixType::Scalar>::type
+block_real_only(const MatrixType &m1, Index r1, Index r2, Index c1, Index c2, const Scalar& s1) {
+ // check cwise-Functions:
+ VERIFY_IS_APPROX(m1.row(r1).cwiseMax(s1), m1.cwiseMax(s1).row(r1));
+ VERIFY_IS_APPROX(m1.col(c1).cwiseMin(s1), m1.cwiseMin(s1).col(c1));
+
+ VERIFY_IS_APPROX(m1.block(r1,c1,r2-r1+1,c2-c1+1).cwiseMin(s1), m1.cwiseMin(s1).block(r1,c1,r2-r1+1,c2-c1+1));
+ VERIFY_IS_APPROX(m1.block(r1,c1,r2-r1+1,c2-c1+1).cwiseMax(s1), m1.cwiseMax(s1).block(r1,c1,r2-r1+1,c2-c1+1));
+
+ return Scalar(0);
+}
+
+template<typename MatrixType, typename Index, typename Scalar>
+typename Eigen::internal::enable_if<NumTraits<typename MatrixType::Scalar>::IsComplex,typename MatrixType::Scalar>::type
+block_real_only(const MatrixType &, Index, Index, Index, Index, const Scalar&) {
+ return Scalar(0);
+}
+
+
template<typename MatrixType> void block(const MatrixType& m)
{
typedef typename MatrixType::Index Index;
@@ -37,6 +57,8 @@ template<typename MatrixType> void block(const MatrixType& m)
Index c1 = internal::random<Index>(0,cols-1);
Index c2 = internal::random<Index>(c1,cols-1);
+ block_real_only(m1, r1, r2, c1, c1, s1);
+
//check row() and col()
VERIFY_IS_EQUAL(m1.col(c1).transpose(), m1.transpose().row(c1));
//check operator(), both constant and non-constant, on row() and col()
@@ -51,7 +73,8 @@ template<typename MatrixType> void block(const MatrixType& m)
VERIFY_IS_APPROX(m1.col(c1), m1_copy.col(c1) + s1 * m1_copy.col(c2));
m1.col(c1).col(0) += s1 * m1_copy.col(c2);
VERIFY_IS_APPROX(m1.col(c1), m1_copy.col(c1) + Scalar(2) * s1 * m1_copy.col(c2));
-
+
+
//check block()
Matrix<Scalar,Dynamic,Dynamic> b1(1,1); b1(0,0) = m1(r1,c1);
@@ -77,6 +100,12 @@ template<typename MatrixType> void block(const MatrixType& m)
// check that fixed block() and block() agree
Matrix<Scalar,Dynamic,Dynamic> b = m1.template block<BlockRows,BlockCols>(3,3);
VERIFY_IS_EQUAL(b, m1.block(3,3,BlockRows,BlockCols));
+
+ // same tests with mixed fixed/dynamic size
+ m1.template block<BlockRows,Dynamic>(1,1,BlockRows,BlockCols) *= s1;
+ m1.template block<BlockRows,Dynamic>(1,1,BlockRows,BlockCols)(0,3) = m1.template block<2,5>(1,1)(1,2);
+ Matrix<Scalar,Dynamic,Dynamic> b2 = m1.template block<Dynamic,BlockCols>(3,3,2,5);
+ VERIFY_IS_EQUAL(b2, m1.block(3,3,BlockRows,BlockCols));
}
if (rows>2)
@@ -96,11 +125,11 @@ template<typename MatrixType> void block(const MatrixType& m)
}
// stress some basic stuffs with block matrices
- VERIFY(internal::real(ones.col(c1).sum()) == RealScalar(rows));
- VERIFY(internal::real(ones.row(r1).sum()) == RealScalar(cols));
+ VERIFY(numext::real(ones.col(c1).sum()) == RealScalar(rows));
+ VERIFY(numext::real(ones.row(r1).sum()) == RealScalar(cols));
- VERIFY(internal::real(ones.col(c1).dot(ones.col(c2))) == RealScalar(rows));
- VERIFY(internal::real(ones.row(r1).dot(ones.row(r2))) == RealScalar(cols));
+ VERIFY(numext::real(ones.col(c1).dot(ones.col(c2))) == RealScalar(rows));
+ VERIFY(numext::real(ones.row(r1).dot(ones.row(r2))) == RealScalar(cols));
// now test some block-inside-of-block.
diff --git a/test/cholesky.cpp b/test/cholesky.cpp
index 14e01c006..64bcbccc4 100644
--- a/test/cholesky.cpp
+++ b/test/cholesky.cpp
@@ -83,14 +83,14 @@ template<typename MatrixType> void cholesky(const MatrixType& m)
symm += a1 * a1.adjoint();
}
- SquareMatrixType symmUp = symm.template triangularView<Upper>();
- SquareMatrixType symmLo = symm.template triangularView<Lower>();
-
// to test if really Cholesky only uses the upper triangular part, uncomment the following
// FIXME: currently that fails !!
//symm.template part<StrictlyLower>().setZero();
{
+ SquareMatrixType symmUp = symm.template triangularView<Upper>();
+ SquareMatrixType symmLo = symm.template triangularView<Lower>();
+
LLT<SquareMatrixType,Lower> chollo(symmLo);
VERIFY_IS_APPROX(symm, chollo.reconstructedMatrix());
vecX = chollo.solve(vecB);
@@ -114,6 +114,21 @@ template<typename MatrixType> void cholesky(const MatrixType& m)
VERIFY_IS_APPROX(MatrixType(chollo.matrixU().transpose().conjugate()), MatrixType(chollo.matrixL()));
VERIFY_IS_APPROX(MatrixType(cholup.matrixL().transpose().conjugate()), MatrixType(cholup.matrixU()));
VERIFY_IS_APPROX(MatrixType(cholup.matrixU().transpose().conjugate()), MatrixType(cholup.matrixL()));
+
+ // test some special use cases of SelfCwiseBinaryOp:
+ MatrixType m1 = MatrixType::Random(rows,cols), m2(rows,cols);
+ m2 = m1;
+ m2 += symmLo.template selfadjointView<Lower>().llt().solve(matB);
+ VERIFY_IS_APPROX(m2, m1 + symmLo.template selfadjointView<Lower>().llt().solve(matB));
+ m2 = m1;
+ m2 -= symmLo.template selfadjointView<Lower>().llt().solve(matB);
+ VERIFY_IS_APPROX(m2, m1 - symmLo.template selfadjointView<Lower>().llt().solve(matB));
+ m2 = m1;
+ m2.noalias() += symmLo.template selfadjointView<Lower>().llt().solve(matB);
+ VERIFY_IS_APPROX(m2, m1 + symmLo.template selfadjointView<Lower>().llt().solve(matB));
+ m2 = m1;
+ m2.noalias() -= symmLo.template selfadjointView<Lower>().llt().solve(matB);
+ VERIFY_IS_APPROX(m2, m1 - symmLo.template selfadjointView<Lower>().llt().solve(matB));
}
// LDLT
@@ -165,22 +180,58 @@ template<typename MatrixType> void cholesky(const MatrixType& m)
// restore
if(sign == -1)
symm = -symm;
- }
- // test some special use cases of SelfCwiseBinaryOp:
- MatrixType m1 = MatrixType::Random(rows,cols), m2(rows,cols);
- m2 = m1;
- m2 += symmLo.template selfadjointView<Lower>().llt().solve(matB);
- VERIFY_IS_APPROX(m2, m1 + symmLo.template selfadjointView<Lower>().llt().solve(matB));
- m2 = m1;
- m2 -= symmLo.template selfadjointView<Lower>().llt().solve(matB);
- VERIFY_IS_APPROX(m2, m1 - symmLo.template selfadjointView<Lower>().llt().solve(matB));
- m2 = m1;
- m2.noalias() += symmLo.template selfadjointView<Lower>().llt().solve(matB);
- VERIFY_IS_APPROX(m2, m1 + symmLo.template selfadjointView<Lower>().llt().solve(matB));
- m2 = m1;
- m2.noalias() -= symmLo.template selfadjointView<Lower>().llt().solve(matB);
- VERIFY_IS_APPROX(m2, m1 - symmLo.template selfadjointView<Lower>().llt().solve(matB));
+ // check matrices coming from linear constraints with Lagrange multipliers
+ if(rows>=3)
+ {
+ SquareMatrixType A = symm;
+ int c = internal::random<int>(0,rows-2);
+ A.bottomRightCorner(c,c).setZero();
+ // Make sure a solution exists:
+ vecX.setRandom();
+ vecB = A * vecX;
+ vecX.setZero();
+ ldltlo.compute(A);
+ VERIFY_IS_APPROX(A, ldltlo.reconstructedMatrix());
+ vecX = ldltlo.solve(vecB);
+ VERIFY_IS_APPROX(A * vecX, vecB);
+ }
+
+ // check non-full rank matrices
+ if(rows>=3)
+ {
+ int r = internal::random<int>(1,rows-1);
+ Matrix<Scalar,Dynamic,Dynamic> a = Matrix<Scalar,Dynamic,Dynamic>::Random(rows,r);
+ SquareMatrixType A = a * a.adjoint();
+ // Make sure a solution exists:
+ vecX.setRandom();
+ vecB = A * vecX;
+ vecX.setZero();
+ ldltlo.compute(A);
+ VERIFY_IS_APPROX(A, ldltlo.reconstructedMatrix());
+ vecX = ldltlo.solve(vecB);
+ VERIFY_IS_APPROX(A * vecX, vecB);
+ }
+
+ // check matrices with a wide spectrum
+ if(rows>=3)
+ {
+ RealScalar s = (std::min)(16,std::numeric_limits<RealScalar>::max_exponent10/8);
+ Matrix<Scalar,Dynamic,Dynamic> a = Matrix<Scalar,Dynamic,Dynamic>::Random(rows,rows);
+ Matrix<RealScalar,Dynamic,1> d = Matrix<RealScalar,Dynamic,1>::Random(rows);
+ for(int k=0; k<rows; ++k)
+ d(k) = d(k)*std::pow(RealScalar(10),internal::random<RealScalar>(-s,s));
+ SquareMatrixType A = a * d.asDiagonal() * a.adjoint();
+ // Make sure a solution exists:
+ vecX.setRandom();
+ vecB = A * vecX;
+ vecX.setZero();
+ ldltlo.compute(A);
+ VERIFY_IS_APPROX(A, ldltlo.reconstructedMatrix());
+ vecX = ldltlo.solve(vecB);
+ VERIFY_IS_APPROX(A * vecX, vecB);
+ }
+ }
// update/downdate
CALL_SUBTEST(( test_chol_update<SquareMatrixType,LLT>(symm) ));
@@ -262,6 +313,45 @@ template<typename MatrixType> void cholesky_bug241(const MatrixType& m)
VERIFY_IS_APPROX(matA * vecX, vecB);
}
+// LDLT is not guaranteed to work for indefinite matrices, but happens to work fine if matrix is diagonal.
+// This test checks that LDLT reports correctly that matrix is indefinite.
+// See http://forum.kde.org/viewtopic.php?f=74&t=106942 and bug 736
+template<typename MatrixType> void cholesky_definiteness(const MatrixType& m)
+{
+ eigen_assert(m.rows() == 2 && m.cols() == 2);
+ MatrixType mat;
+ {
+ mat << 1, 0, 0, -1;
+ LDLT<MatrixType> ldlt(mat);
+ VERIFY(!ldlt.isNegative());
+ VERIFY(!ldlt.isPositive());
+ }
+ {
+ mat << 1, 2, 2, 1;
+ LDLT<MatrixType> ldlt(mat);
+ VERIFY(!ldlt.isNegative());
+ VERIFY(!ldlt.isPositive());
+ }
+ {
+ mat << 0, 0, 0, 0;
+ LDLT<MatrixType> ldlt(mat);
+ VERIFY(ldlt.isNegative());
+ VERIFY(ldlt.isPositive());
+ }
+ {
+ mat << 0, 0, 0, 1;
+ LDLT<MatrixType> ldlt(mat);
+ VERIFY(!ldlt.isNegative());
+ VERIFY(ldlt.isPositive());
+ }
+ {
+ mat << -1, 0, 0, 0;
+ LDLT<MatrixType> ldlt(mat);
+ VERIFY(ldlt.isNegative());
+ VERIFY(!ldlt.isPositive());
+ }
+}
+
template<typename MatrixType> void cholesky_verify_assert()
{
MatrixType tmp;
@@ -284,11 +374,12 @@ template<typename MatrixType> void cholesky_verify_assert()
void test_cholesky()
{
- int s;
+ int s = 0;
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST_1( cholesky(Matrix<double,1,1>()) );
CALL_SUBTEST_3( cholesky(Matrix2d()) );
CALL_SUBTEST_3( cholesky_bug241(Matrix2d()) );
+ CALL_SUBTEST_3( cholesky_definiteness(Matrix2d()) );
CALL_SUBTEST_4( cholesky(Matrix3f()) );
CALL_SUBTEST_5( cholesky(Matrix4d()) );
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
@@ -306,5 +397,6 @@ void test_cholesky()
CALL_SUBTEST_9( LLT<MatrixXf>(10) );
CALL_SUBTEST_9( LDLT<MatrixXf>(10) );
- EIGEN_UNUSED_VARIABLE(s)
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
+ TEST_SET_BUT_UNUSED_VARIABLE(nb_temporaries)
}
diff --git a/test/conservative_resize.cpp b/test/conservative_resize.cpp
index 4d11e4075..498421b4c 100644
--- a/test/conservative_resize.cpp
+++ b/test/conservative_resize.cpp
@@ -60,34 +60,51 @@ void run_matrix_tests()
template <typename Scalar>
void run_vector_tests()
{
- typedef Matrix<Scalar, 1, Eigen::Dynamic> MatrixType;
+ typedef Matrix<Scalar, 1, Eigen::Dynamic> VectorType;
- MatrixType m, n;
+ VectorType m, n;
// boundary cases ...
- m = n = MatrixType::Random(50);
+ m = n = VectorType::Random(50);
m.conservativeResize(1);
VERIFY_IS_APPROX(m, n.segment(0,1));
- m = n = MatrixType::Random(50);
+ m = n = VectorType::Random(50);
m.conservativeResize(50);
VERIFY_IS_APPROX(m, n.segment(0,50));
+
+ m = n = VectorType::Random(50);
+ m.conservativeResize(m.rows(),1);
+ VERIFY_IS_APPROX(m, n.segment(0,1));
+
+ m = n = VectorType::Random(50);
+ m.conservativeResize(m.rows(),50);
+ VERIFY_IS_APPROX(m, n.segment(0,50));
// random shrinking ...
for (int i=0; i<50; ++i)
{
const int size = internal::random<int>(1,50);
- m = n = MatrixType::Random(50);
+ m = n = VectorType::Random(50);
m.conservativeResize(size);
VERIFY_IS_APPROX(m, n.segment(0,size));
+
+ m = n = VectorType::Random(50);
+ m.conservativeResize(m.rows(), size);
+ VERIFY_IS_APPROX(m, n.segment(0,size));
}
// random growing with zeroing ...
for (int i=0; i<50; ++i)
{
const int size = internal::random<int>(50,100);
- m = n = MatrixType::Random(50);
- m.conservativeResizeLike(MatrixType::Zero(size));
+ m = n = VectorType::Random(50);
+ m.conservativeResizeLike(VectorType::Zero(size));
+ VERIFY_IS_APPROX(m.segment(0,50), n);
+ VERIFY( size<=50 || m.segment(50,size-50).sum() == Scalar(0) );
+
+ m = n = VectorType::Random(50);
+ m.conservativeResizeLike(Matrix<Scalar,Dynamic,Dynamic>::Zero(1,size));
VERIFY_IS_APPROX(m.segment(0,50), n);
VERIFY( size<=50 || m.segment(50,size-50).sum() == Scalar(0) );
}
@@ -95,20 +112,23 @@ void run_vector_tests()
void test_conservative_resize()
{
- CALL_SUBTEST_1((run_matrix_tests<int, Eigen::RowMajor>()));
- CALL_SUBTEST_1((run_matrix_tests<int, Eigen::ColMajor>()));
- CALL_SUBTEST_2((run_matrix_tests<float, Eigen::RowMajor>()));
- CALL_SUBTEST_2((run_matrix_tests<float, Eigen::ColMajor>()));
- CALL_SUBTEST_3((run_matrix_tests<double, Eigen::RowMajor>()));
- CALL_SUBTEST_3((run_matrix_tests<double, Eigen::ColMajor>()));
- CALL_SUBTEST_4((run_matrix_tests<std::complex<float>, Eigen::RowMajor>()));
- CALL_SUBTEST_4((run_matrix_tests<std::complex<float>, Eigen::ColMajor>()));
- CALL_SUBTEST_5((run_matrix_tests<std::complex<double>, Eigen::RowMajor>()));
- CALL_SUBTEST_6((run_matrix_tests<std::complex<double>, Eigen::ColMajor>()));
-
- CALL_SUBTEST_1((run_vector_tests<int>()));
- CALL_SUBTEST_2((run_vector_tests<float>()));
- CALL_SUBTEST_3((run_vector_tests<double>()));
- CALL_SUBTEST_4((run_vector_tests<std::complex<float> >()));
- CALL_SUBTEST_5((run_vector_tests<std::complex<double> >()));
+ for(int i=0; i<g_repeat; ++i)
+ {
+ CALL_SUBTEST_1((run_matrix_tests<int, Eigen::RowMajor>()));
+ CALL_SUBTEST_1((run_matrix_tests<int, Eigen::ColMajor>()));
+ CALL_SUBTEST_2((run_matrix_tests<float, Eigen::RowMajor>()));
+ CALL_SUBTEST_2((run_matrix_tests<float, Eigen::ColMajor>()));
+ CALL_SUBTEST_3((run_matrix_tests<double, Eigen::RowMajor>()));
+ CALL_SUBTEST_3((run_matrix_tests<double, Eigen::ColMajor>()));
+ CALL_SUBTEST_4((run_matrix_tests<std::complex<float>, Eigen::RowMajor>()));
+ CALL_SUBTEST_4((run_matrix_tests<std::complex<float>, Eigen::ColMajor>()));
+ CALL_SUBTEST_5((run_matrix_tests<std::complex<double>, Eigen::RowMajor>()));
+ CALL_SUBTEST_6((run_matrix_tests<std::complex<double>, Eigen::ColMajor>()));
+
+ CALL_SUBTEST_1((run_vector_tests<int>()));
+ CALL_SUBTEST_2((run_vector_tests<float>()));
+ CALL_SUBTEST_3((run_vector_tests<double>()));
+ CALL_SUBTEST_4((run_vector_tests<std::complex<float> >()));
+ CALL_SUBTEST_5((run_vector_tests<std::complex<double> >()));
+ }
}
diff --git a/test/corners.cpp b/test/corners.cpp
index 4705c5f05..3c64c32a1 100644
--- a/test/corners.cpp
+++ b/test/corners.cpp
@@ -62,6 +62,16 @@ template<typename MatrixType, int CRows, int CCols, int SRows, int SCols> void c
VERIFY_IS_EQUAL((matrix.template bottomLeftCorner<r,c>()), (matrix.template block<r,c>(rows-r,0)));
VERIFY_IS_EQUAL((matrix.template bottomRightCorner<r,c>()), (matrix.template block<r,c>(rows-r,cols-c)));
+ VERIFY_IS_EQUAL((matrix.template topLeftCorner<r,c>()), (matrix.template topLeftCorner<r,Dynamic>(r,c)));
+ VERIFY_IS_EQUAL((matrix.template topRightCorner<r,c>()), (matrix.template topRightCorner<r,Dynamic>(r,c)));
+ VERIFY_IS_EQUAL((matrix.template bottomLeftCorner<r,c>()), (matrix.template bottomLeftCorner<r,Dynamic>(r,c)));
+ VERIFY_IS_EQUAL((matrix.template bottomRightCorner<r,c>()), (matrix.template bottomRightCorner<r,Dynamic>(r,c)));
+
+ VERIFY_IS_EQUAL((matrix.template topLeftCorner<r,c>()), (matrix.template topLeftCorner<Dynamic,c>(r,c)));
+ VERIFY_IS_EQUAL((matrix.template topRightCorner<r,c>()), (matrix.template topRightCorner<Dynamic,c>(r,c)));
+ VERIFY_IS_EQUAL((matrix.template bottomLeftCorner<r,c>()), (matrix.template bottomLeftCorner<Dynamic,c>(r,c)));
+ VERIFY_IS_EQUAL((matrix.template bottomRightCorner<r,c>()), (matrix.template bottomRightCorner<Dynamic,c>(r,c)));
+
VERIFY_IS_EQUAL((matrix.template topRows<r>()), (matrix.template block<r,cols>(0,0)));
VERIFY_IS_EQUAL((matrix.template middleRows<r>(sr)), (matrix.template block<r,cols>(sr,0)));
VERIFY_IS_EQUAL((matrix.template bottomRows<r>()), (matrix.template block<r,cols>(rows-r,0)));
@@ -74,6 +84,16 @@ template<typename MatrixType, int CRows, int CCols, int SRows, int SCols> void c
VERIFY_IS_EQUAL((const_matrix.template bottomLeftCorner<r,c>()), (const_matrix.template block<r,c>(rows-r,0)));
VERIFY_IS_EQUAL((const_matrix.template bottomRightCorner<r,c>()), (const_matrix.template block<r,c>(rows-r,cols-c)));
+ VERIFY_IS_EQUAL((const_matrix.template topLeftCorner<r,c>()), (const_matrix.template topLeftCorner<r,Dynamic>(r,c)));
+ VERIFY_IS_EQUAL((const_matrix.template topRightCorner<r,c>()), (const_matrix.template topRightCorner<r,Dynamic>(r,c)));
+ VERIFY_IS_EQUAL((const_matrix.template bottomLeftCorner<r,c>()), (const_matrix.template bottomLeftCorner<r,Dynamic>(r,c)));
+ VERIFY_IS_EQUAL((const_matrix.template bottomRightCorner<r,c>()), (const_matrix.template bottomRightCorner<r,Dynamic>(r,c)));
+
+ VERIFY_IS_EQUAL((const_matrix.template topLeftCorner<r,c>()), (const_matrix.template topLeftCorner<Dynamic,c>(r,c)));
+ VERIFY_IS_EQUAL((const_matrix.template topRightCorner<r,c>()), (const_matrix.template topRightCorner<Dynamic,c>(r,c)));
+ VERIFY_IS_EQUAL((const_matrix.template bottomLeftCorner<r,c>()), (const_matrix.template bottomLeftCorner<Dynamic,c>(r,c)));
+ VERIFY_IS_EQUAL((const_matrix.template bottomRightCorner<r,c>()), (const_matrix.template bottomRightCorner<Dynamic,c>(r,c)));
+
VERIFY_IS_EQUAL((const_matrix.template topRows<r>()), (const_matrix.template block<r,cols>(0,0)));
VERIFY_IS_EQUAL((const_matrix.template middleRows<r>(sr)), (const_matrix.template block<r,cols>(sr,0)));
VERIFY_IS_EQUAL((const_matrix.template bottomRows<r>()), (const_matrix.template block<r,cols>(rows-r,0)));
diff --git a/test/cwiseop.cpp b/test/cwiseop.cpp
index ca6e4211c..247fa2a09 100644
--- a/test/cwiseop.cpp
+++ b/test/cwiseop.cpp
@@ -28,17 +28,52 @@ template<typename Scalar> struct AddIfNull {
enum { Cost = NumTraits<Scalar>::AddCost };
};
+template<typename MatrixType>
+typename Eigen::internal::enable_if<!NumTraits<typename MatrixType::Scalar>::IsInteger,typename MatrixType::Scalar>::type
+cwiseops_real_only(MatrixType& m1, MatrixType& m2, MatrixType& m3, MatrixType& mones)
+{
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename NumTraits<Scalar>::Real RealScalar;
+
+ VERIFY_IS_APPROX(m1.cwise() / m2, m1.cwise() * (m2.cwise().inverse()));
+ m3 = m1.cwise().abs().cwise().sqrt();
+ VERIFY_IS_APPROX(m3.cwise().square(), m1.cwise().abs());
+ VERIFY_IS_APPROX(m1.cwise().square().cwise().sqrt(), m1.cwise().abs());
+ VERIFY_IS_APPROX(m1.cwise().abs().cwise().log().cwise().exp() , m1.cwise().abs());
+
+ VERIFY_IS_APPROX(m1.cwise().pow(2), m1.cwise().square());
+ m3 = (m1.cwise().abs().cwise()<=RealScalar(0.01)).select(mones,m1);
+ VERIFY_IS_APPROX(m3.cwise().pow(-1), m3.cwise().inverse());
+ m3 = m1.cwise().abs();
+ VERIFY_IS_APPROX(m3.cwise().pow(RealScalar(0.5)), m3.cwise().sqrt());
+
+// VERIFY_IS_APPROX(m1.cwise().tan(), m1.cwise().sin().cwise() / m1.cwise().cos());
+ VERIFY_IS_APPROX(mones, m1.cwise().sin().cwise().square() + m1.cwise().cos().cwise().square());
+ m3 = m1;
+ m3.cwise() /= m2;
+ VERIFY_IS_APPROX(m3, m1.cwise() / m2);
+
+ return Scalar(0);
+}
+
+template<typename MatrixType>
+typename Eigen::internal::enable_if<NumTraits<typename MatrixType::Scalar>::IsInteger,typename MatrixType::Scalar>::type
+cwiseops_real_only(MatrixType& , MatrixType& , MatrixType& , MatrixType& )
+{
+ return 0;
+}
+
template<typename MatrixType> void cwiseops(const MatrixType& m)
{
typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
Index rows = m.rows();
Index cols = m.cols();
MatrixType m1 = MatrixType::Random(rows, cols),
+ m1bis = m1,
m2 = MatrixType::Random(rows, cols),
m3(rows, cols),
m4(rows, cols),
@@ -101,26 +136,6 @@ template<typename MatrixType> void cwiseops(const MatrixType& m)
VERIFY_IS_APPROX(m3, m1.cwise() * m2);
VERIFY_IS_APPROX(mones, m2.cwise()/m2);
- if(!NumTraits<Scalar>::IsInteger)
- {
- VERIFY_IS_APPROX(m1.cwise() / m2, m1.cwise() * (m2.cwise().inverse()));
- m3 = m1.cwise().abs().cwise().sqrt();
- VERIFY_IS_APPROX(m3.cwise().square(), m1.cwise().abs());
- VERIFY_IS_APPROX(m1.cwise().square().cwise().sqrt(), m1.cwise().abs());
- VERIFY_IS_APPROX(m1.cwise().abs().cwise().log().cwise().exp() , m1.cwise().abs());
-
- VERIFY_IS_APPROX(m1.cwise().pow(2), m1.cwise().square());
- m3 = (m1.cwise().abs().cwise()<=RealScalar(0.01)).select(mones,m1);
- VERIFY_IS_APPROX(m3.cwise().pow(-1), m3.cwise().inverse());
- m3 = m1.cwise().abs();
- VERIFY_IS_APPROX(m3.cwise().pow(RealScalar(0.5)), m3.cwise().sqrt());
-
-// VERIFY_IS_APPROX(m1.cwise().tan(), m1.cwise().sin().cwise() / m1.cwise().cos());
- VERIFY_IS_APPROX(mones, m1.cwise().sin().cwise().square() + m1.cwise().cos().cwise().square());
- m3 = m1;
- m3.cwise() /= m2;
- VERIFY_IS_APPROX(m3, m1.cwise() / m2);
- }
// check min
VERIFY_IS_APPROX( m1.cwise().min(m2), m2.cwise().min(m1) );
@@ -148,8 +163,10 @@ template<typename MatrixType> void cwiseops(const MatrixType& m)
VERIFY( (m1.cwise().max(m2).cwise() > (m1-mones)).all() );
VERIFY( (m1.cwise()<m1.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).all() );
- VERIFY( !(m1.cwise()<m1.unaryExpr(bind2nd(minus<Scalar>(), Scalar(1)))).all() );
- VERIFY( !(m1.cwise()>m1.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).any() );
+ VERIFY( !(m1.cwise()<m1bis.unaryExpr(bind2nd(minus<Scalar>(), Scalar(1)))).all() );
+ VERIFY( !(m1.cwise()>m1bis.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).any() );
+
+ cwiseops_real_only(m1, m2, m3, mones);
}
void test_cwiseop()
diff --git a/test/denseLM.cpp b/test/denseLM.cpp
new file mode 100644
index 000000000..0aa736ea3
--- /dev/null
+++ b/test/denseLM.cpp
@@ -0,0 +1,190 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Desire Nuentsa <desire.nuentsa_wakam@inria.fr>
+// Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+
+#include "main.h"
+#include <Eigen/LevenbergMarquardt>
+using namespace std;
+using namespace Eigen;
+
+template<typename Scalar>
+struct DenseLM : DenseFunctor<Scalar>
+{
+ typedef DenseFunctor<Scalar> Base;
+ typedef typename Base::JacobianType JacobianType;
+ typedef Matrix<Scalar,Dynamic,1> VectorType;
+
+ DenseLM(int n, int m) : DenseFunctor<Scalar>(n,m)
+ { }
+
+ VectorType model(const VectorType& uv, VectorType& x)
+ {
+ VectorType y; // Should change to use expression template
+ int m = Base::values();
+ int n = Base::inputs();
+ eigen_assert(uv.size()%2 == 0);
+ eigen_assert(uv.size() == n);
+ eigen_assert(x.size() == m);
+ y.setZero(m);
+ int half = n/2;
+ VectorBlock<const VectorType> u(uv, 0, half);
+ VectorBlock<const VectorType> v(uv, half, half);
+ for (int j = 0; j < m; j++)
+ {
+ for (int i = 0; i < half; i++)
+ y(j) += u(i)*std::exp(-(x(j)-i)*(x(j)-i)/(v(i)*v(i)));
+ }
+ return y;
+
+ }
+ void initPoints(VectorType& uv_ref, VectorType& x)
+ {
+ m_x = x;
+ m_y = this->model(uv_ref, x);
+ }
+
+ int operator()(const VectorType& uv, VectorType& fvec)
+ {
+
+ int m = Base::values();
+ int n = Base::inputs();
+ eigen_assert(uv.size()%2 == 0);
+ eigen_assert(uv.size() == n);
+ eigen_assert(fvec.size() == m);
+ int half = n/2;
+ VectorBlock<const VectorType> u(uv, 0, half);
+ VectorBlock<const VectorType> v(uv, half, half);
+ for (int j = 0; j < m; j++)
+ {
+ fvec(j) = m_y(j);
+ for (int i = 0; i < half; i++)
+ {
+ fvec(j) -= u(i) *std::exp(-(m_x(j)-i)*(m_x(j)-i)/(v(i)*v(i)));
+ }
+ }
+
+ return 0;
+ }
+ int df(const VectorType& uv, JacobianType& fjac)
+ {
+ int m = Base::values();
+ int n = Base::inputs();
+ eigen_assert(n == uv.size());
+ eigen_assert(fjac.rows() == m);
+ eigen_assert(fjac.cols() == n);
+ int half = n/2;
+ VectorBlock<const VectorType> u(uv, 0, half);
+ VectorBlock<const VectorType> v(uv, half, half);
+ for (int j = 0; j < m; j++)
+ {
+ for (int i = 0; i < half; i++)
+ {
+ fjac.coeffRef(j,i) = -std::exp(-(m_x(j)-i)*(m_x(j)-i)/(v(i)*v(i)));
+ fjac.coeffRef(j,i+half) = -2.*u(i)*(m_x(j)-i)*(m_x(j)-i)/(std::pow(v(i),3)) * std::exp(-(m_x(j)-i)*(m_x(j)-i)/(v(i)*v(i)));
+ }
+ }
+ return 0;
+ }
+ VectorType m_x, m_y; //Data Points
+};
+
+template<typename FunctorType, typename VectorType>
+int test_minimizeLM(FunctorType& functor, VectorType& uv)
+{
+ LevenbergMarquardt<FunctorType> lm(functor);
+ LevenbergMarquardtSpace::Status info;
+
+ info = lm.minimize(uv);
+
+ VERIFY_IS_EQUAL(info, 1);
+ //FIXME Check other parameters
+ return info;
+}
+
+template<typename FunctorType, typename VectorType>
+int test_lmder(FunctorType& functor, VectorType& uv)
+{
+ typedef typename VectorType::Scalar Scalar;
+ LevenbergMarquardtSpace::Status info;
+ LevenbergMarquardt<FunctorType> lm(functor);
+ info = lm.lmder1(uv);
+
+ VERIFY_IS_EQUAL(info, 1);
+ //FIXME Check other parameters
+ return info;
+}
+
+template<typename FunctorType, typename VectorType>
+int test_minimizeSteps(FunctorType& functor, VectorType& uv)
+{
+ LevenbergMarquardtSpace::Status info;
+ LevenbergMarquardt<FunctorType> lm(functor);
+ info = lm.minimizeInit(uv);
+ if (info==LevenbergMarquardtSpace::ImproperInputParameters)
+ return info;
+ do
+ {
+ info = lm.minimizeOneStep(uv);
+ } while (info==LevenbergMarquardtSpace::Running);
+
+ VERIFY_IS_EQUAL(info, 1);
+ //FIXME Check other parameters
+ return info;
+}
+
+template<typename T>
+void test_denseLM_T()
+{
+ typedef Matrix<T,Dynamic,1> VectorType;
+
+ int inputs = 10;
+ int values = 1000;
+ DenseLM<T> dense_gaussian(inputs, values);
+ VectorType uv(inputs),uv_ref(inputs);
+ VectorType x(values);
+
+ // Generate the reference solution
+ uv_ref << -2, 1, 4 ,8, 6, 1.8, 1.2, 1.1, 1.9 , 3;
+
+ //Generate the reference data points
+ x.setRandom();
+ x = 10*x;
+ x.array() += 10;
+ dense_gaussian.initPoints(uv_ref, x);
+
+ // Generate the initial parameters
+ VectorBlock<VectorType> u(uv, 0, inputs/2);
+ VectorBlock<VectorType> v(uv, inputs/2, inputs/2);
+
+ // Solve the optimization problem
+
+ //Solve in one go
+ u.setOnes(); v.setOnes();
+ test_minimizeLM(dense_gaussian, uv);
+
+ //Solve until the machine precision
+ u.setOnes(); v.setOnes();
+ test_lmder(dense_gaussian, uv);
+
+ // Solve step by step
+ v.setOnes(); u.setOnes();
+ test_minimizeSteps(dense_gaussian, uv);
+
+}
+
+void test_denseLM()
+{
+ CALL_SUBTEST_2(test_denseLM_T<double>());
+
+ // CALL_SUBTEST_2(test_sparseLM_T<std::complex<double>());
+}
diff --git a/test/determinant.cpp b/test/determinant.cpp
index e93f2f297..758f3afbb 100644
--- a/test/determinant.cpp
+++ b/test/determinant.cpp
@@ -39,7 +39,7 @@ template<typename MatrixType> void determinant(const MatrixType& m)
m2.col(i).swap(m2.col(j));
VERIFY_IS_APPROX(m2.determinant(), -m1.determinant());
VERIFY_IS_APPROX(m2.determinant(), m2.transpose().determinant());
- VERIFY_IS_APPROX(internal::conj(m2.determinant()), m2.adjoint().determinant());
+ VERIFY_IS_APPROX(numext::conj(m2.determinant()), m2.adjoint().determinant());
m2 = m1;
m2.row(i) += x*m2.row(j);
VERIFY_IS_APPROX(m2.determinant(), m1.determinant());
@@ -53,8 +53,8 @@ template<typename MatrixType> void determinant(const MatrixType& m)
void test_determinant()
{
- int s;
for(int i = 0; i < g_repeat; i++) {
+ int s = 0;
CALL_SUBTEST_1( determinant(Matrix<float, 1, 1>()) );
CALL_SUBTEST_2( determinant(Matrix<double, 2, 2>()) );
CALL_SUBTEST_3( determinant(Matrix<double, 3, 3>()) );
@@ -62,6 +62,6 @@ void test_determinant()
CALL_SUBTEST_5( determinant(Matrix<std::complex<double>, 10, 10>()) );
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
CALL_SUBTEST_6( determinant(MatrixXd(s, s)) );
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
}
- EIGEN_UNUSED_VARIABLE(s)
}
diff --git a/test/diagonal.cpp b/test/diagonal.cpp
index 95cd10372..53814a588 100644
--- a/test/diagonal.cpp
+++ b/test/diagonal.cpp
@@ -13,9 +13,6 @@ template<typename MatrixType> void diagonal(const MatrixType& m)
{
typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::RealScalar RealScalar;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
- typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType;
Index rows = m.rows();
Index cols = m.cols();
@@ -31,17 +28,14 @@ template<typename MatrixType> void diagonal(const MatrixType& m)
if (rows>2)
{
enum {
- N1 = MatrixType::RowsAtCompileTime>1 ? 1 : 0,
- N2 = MatrixType::RowsAtCompileTime>2 ? -2 : 0
+ N1 = MatrixType::RowsAtCompileTime>2 ? 2 : 0,
+ N2 = MatrixType::RowsAtCompileTime>1 ? -1 : 0
};
// check sub/super diagonal
- if(m1.template diagonal<N1>().RowsAtCompileTime!=Dynamic)
+ if(MatrixType::SizeAtCompileTime!=Dynamic)
{
VERIFY(m1.template diagonal<N1>().RowsAtCompileTime == m1.diagonal(N1).size());
- }
- if(m1.template diagonal<N2>().RowsAtCompileTime!=Dynamic)
- {
VERIFY(m1.template diagonal<N2>().RowsAtCompileTime == m1.diagonal(N2).size());
}
@@ -56,12 +50,12 @@ template<typename MatrixType> void diagonal(const MatrixType& m)
VERIFY_IS_APPROX(m2.template diagonal<N2>()[0], static_cast<Scalar>(6) * m1.template diagonal<N2>()[0]);
m2.diagonal(N1) = 2 * m1.diagonal(N1);
- VERIFY_IS_APPROX(m2.diagonal<N1>(), static_cast<Scalar>(2) * m1.diagonal(N1));
+ VERIFY_IS_APPROX(m2.template diagonal<N1>(), static_cast<Scalar>(2) * m1.diagonal(N1));
m2.diagonal(N1)[0] *= 3;
VERIFY_IS_APPROX(m2.diagonal(N1)[0], static_cast<Scalar>(6) * m1.diagonal(N1)[0]);
m2.diagonal(N2) = 2 * m1.diagonal(N2);
- VERIFY_IS_APPROX(m2.diagonal<N2>(), static_cast<Scalar>(2) * m1.diagonal(N2));
+ VERIFY_IS_APPROX(m2.template diagonal<N2>(), static_cast<Scalar>(2) * m1.diagonal(N2));
m2.diagonal(N2)[0] *= 3;
VERIFY_IS_APPROX(m2.diagonal(N2)[0], static_cast<Scalar>(6) * m1.diagonal(N2)[0]);
}
diff --git a/test/diagonalmatrices.cpp b/test/diagonalmatrices.cpp
index 3f5776dfc..149f1db2f 100644
--- a/test/diagonalmatrices.cpp
+++ b/test/diagonalmatrices.cpp
@@ -13,7 +13,6 @@ template<typename MatrixType> void diagonalmatrices(const MatrixType& m)
{
typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::RealScalar RealScalar;
enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime };
typedef Matrix<Scalar, Rows, 1> VectorType;
typedef Matrix<Scalar, 1, Cols> RowVectorType;
@@ -32,6 +31,8 @@ template<typename MatrixType> void diagonalmatrices(const MatrixType& m)
rv2 = RowVectorType::Random(cols);
LeftDiagonalMatrix ldm1(v1), ldm2(v2);
RightDiagonalMatrix rdm1(rv1), rdm2(rv2);
+
+ Scalar s1 = internal::random<Scalar>();
SquareMatrixType sq_m1 (v1.asDiagonal());
VERIFY_IS_APPROX(sq_m1, v1.asDiagonal().toDenseMatrix());
@@ -76,6 +77,13 @@ template<typename MatrixType> void diagonalmatrices(const MatrixType& m)
big.block(i,j,rows,cols) = big.block(i,j,rows,cols) * rv1.asDiagonal();
VERIFY_IS_APPROX((big.block(i,j,rows,cols)) , m1 * rv1.asDiagonal() );
+
+ // scalar multiple
+ VERIFY_IS_APPROX(LeftDiagonalMatrix(ldm1*s1).diagonal(), ldm1.diagonal() * s1);
+ VERIFY_IS_APPROX(LeftDiagonalMatrix(s1*ldm1).diagonal(), s1 * ldm1.diagonal());
+
+ VERIFY_IS_APPROX(m1 * (rdm1 * s1), (m1 * rdm1) * s1);
+ VERIFY_IS_APPROX(m1 * (s1 * rdm1), (m1 * rdm1) * s1);
}
void test_diagonalmatrices()
diff --git a/test/dynalloc.cpp b/test/dynalloc.cpp
index c7ccbffef..7e41bfa97 100644
--- a/test/dynalloc.cpp
+++ b/test/dynalloc.cpp
@@ -53,7 +53,7 @@ void check_aligned_new()
void check_aligned_stack_alloc()
{
- for(int i = 1; i < 1000; i++)
+ for(int i = 1; i < 400; i++)
{
ei_declare_aligned_stack_constructed_variable(float,p,i,0);
VERIFY(size_t(p)%ALIGNMENT==0);
@@ -82,6 +82,7 @@ class MyClassA
template<typename T> void check_dynaligned()
{
T* obj = new T;
+ VERIFY(T::NeedsToAlign==1);
VERIFY(size_t(obj)%ALIGNMENT==0);
delete obj;
}
diff --git a/test/eigen2support.cpp b/test/eigen2support.cpp
index 7e02bdf5b..ad1d98091 100644
--- a/test/eigen2support.cpp
+++ b/test/eigen2support.cpp
@@ -43,7 +43,9 @@ template<typename MatrixType> void eigen2support(const MatrixType& m)
VERIFY_IS_EQUAL((m1.col(0).end(1)), (m1.col(0).segment(rows-1,1)));
VERIFY_IS_EQUAL((m1.col(0).template end<1>()), (m1.col(0).segment(rows-1,1)));
- using namespace internal;
+ using std::cos;
+ using numext::real;
+ using numext::abs2;
VERIFY_IS_EQUAL(ei_cos(s1), cos(s1));
VERIFY_IS_EQUAL(ei_real(s1), real(s1));
VERIFY_IS_EQUAL(ei_abs2(s1), abs2(s1));
diff --git a/test/eigensolver_complex.cpp b/test/eigensolver_complex.cpp
index 0c2059512..c9d8c0877 100644
--- a/test/eigensolver_complex.cpp
+++ b/test/eigensolver_complex.cpp
@@ -41,9 +41,6 @@ template<typename MatrixType> void eigensolver(const MatrixType& m)
typedef typename MatrixType::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
- typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
- typedef typename std::complex<typename NumTraits<typename MatrixType::Scalar>::Real> Complex;
MatrixType a = MatrixType::Random(rows,cols);
MatrixType symmA = a.adjoint() * a;
@@ -59,6 +56,17 @@ template<typename MatrixType> void eigensolver(const MatrixType& m)
// another algorithm so results may differ slightly
verify_is_approx_upto_permutation(a.eigenvalues(), ei1.eigenvalues());
+ ComplexEigenSolver<MatrixType> ei2;
+ ei2.setMaxIterations(ComplexSchur<MatrixType>::m_maxIterationsPerRow * rows).compute(a);
+ VERIFY_IS_EQUAL(ei2.info(), Success);
+ VERIFY_IS_EQUAL(ei2.eigenvectors(), ei1.eigenvectors());
+ VERIFY_IS_EQUAL(ei2.eigenvalues(), ei1.eigenvalues());
+ if (rows > 2) {
+ ei2.setMaxIterations(1).compute(a);
+ VERIFY_IS_EQUAL(ei2.info(), NoConvergence);
+ VERIFY_IS_EQUAL(ei2.getMaxIterations(), 1);
+ }
+
ComplexEigenSolver<MatrixType> eiNoEivecs(a, false);
VERIFY_IS_EQUAL(eiNoEivecs.info(), Success);
VERIFY_IS_APPROX(ei1.eigenvalues(), eiNoEivecs.eigenvalues());
@@ -93,7 +101,7 @@ template<typename MatrixType> void eigensolver_verify_assert(const MatrixType& m
void test_eigensolver_complex()
{
- int s;
+ int s = 0;
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST_1( eigensolver(Matrix4cf()) );
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
@@ -101,7 +109,6 @@ void test_eigensolver_complex()
CALL_SUBTEST_3( eigensolver(Matrix<std::complex<float>, 1, 1>()) );
CALL_SUBTEST_4( eigensolver(Matrix3f()) );
}
-
CALL_SUBTEST_1( eigensolver_verify_assert(Matrix4cf()) );
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
CALL_SUBTEST_2( eigensolver_verify_assert(MatrixXcd(s,s)) );
@@ -109,7 +116,7 @@ void test_eigensolver_complex()
CALL_SUBTEST_4( eigensolver_verify_assert(Matrix3f()) );
// Test problem size constructors
- CALL_SUBTEST_5(ComplexEigenSolver<MatrixXf>(s));
+ CALL_SUBTEST_5(ComplexEigenSolver<MatrixXf> tmp(s));
- EIGEN_UNUSED_VARIABLE(s)
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
}
diff --git a/test/eigensolver_generalized_real.cpp b/test/eigensolver_generalized_real.cpp
new file mode 100644
index 000000000..566a4bdc6
--- /dev/null
+++ b/test/eigensolver_generalized_real.cpp
@@ -0,0 +1,59 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <limits>
+#include <Eigen/Eigenvalues>
+
+template<typename MatrixType> void generalized_eigensolver_real(const MatrixType& m)
+{
+ typedef typename MatrixType::Index Index;
+ /* this test covers the following files:
+ GeneralizedEigenSolver.h
+ */
+ Index rows = m.rows();
+ Index cols = m.cols();
+
+ typedef typename MatrixType::Scalar Scalar;
+ typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+
+ MatrixType a = MatrixType::Random(rows,cols);
+ MatrixType b = MatrixType::Random(rows,cols);
+ MatrixType a1 = MatrixType::Random(rows,cols);
+ MatrixType b1 = MatrixType::Random(rows,cols);
+ MatrixType spdA = a.adjoint() * a + a1.adjoint() * a1;
+ MatrixType spdB = b.adjoint() * b + b1.adjoint() * b1;
+
+ // lets compare to GeneralizedSelfAdjointEigenSolver
+ GeneralizedSelfAdjointEigenSolver<MatrixType> symmEig(spdA, spdB);
+ GeneralizedEigenSolver<MatrixType> eig(spdA, spdB);
+
+ VERIFY_IS_EQUAL(eig.eigenvalues().imag().cwiseAbs().maxCoeff(), 0);
+
+ VectorType realEigenvalues = eig.eigenvalues().real();
+ std::sort(realEigenvalues.data(), realEigenvalues.data()+realEigenvalues.size());
+ VERIFY_IS_APPROX(realEigenvalues, symmEig.eigenvalues());
+}
+
+void test_eigensolver_generalized_real()
+{
+ for(int i = 0; i < g_repeat; i++) {
+ int s = 0;
+ CALL_SUBTEST_1( generalized_eigensolver_real(Matrix4f()) );
+ s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
+ CALL_SUBTEST_2( generalized_eigensolver_real(MatrixXd(s,s)) );
+
+ // some trivial but implementation-wise tricky cases
+ CALL_SUBTEST_2( generalized_eigensolver_real(MatrixXd(1,1)) );
+ CALL_SUBTEST_2( generalized_eigensolver_real(MatrixXd(2,2)) );
+ CALL_SUBTEST_3( generalized_eigensolver_real(Matrix<double,1,1>()) );
+ CALL_SUBTEST_4( generalized_eigensolver_real(Matrix2d()) );
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
+ }
+}
diff --git a/test/eigensolver_generic.cpp b/test/eigensolver_generic.cpp
index 0b55ccd93..005af81eb 100644
--- a/test/eigensolver_generic.cpp
+++ b/test/eigensolver_generic.cpp
@@ -2,7 +2,7 @@
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
+// Copyright (C) 2010,2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
//
// 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
@@ -23,7 +23,6 @@ template<typename MatrixType> void eigensolver(const MatrixType& m)
typedef typename MatrixType::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
typedef typename std::complex<typename NumTraits<typename MatrixType::Scalar>::Real> Complex;
@@ -45,6 +44,17 @@ template<typename MatrixType> void eigensolver(const MatrixType& m)
VERIFY_IS_APPROX(ei1.eigenvectors().colwise().norm(), RealVectorType::Ones(rows).transpose());
VERIFY_IS_APPROX(a.eigenvalues(), ei1.eigenvalues());
+ EigenSolver<MatrixType> ei2;
+ ei2.setMaxIterations(RealSchur<MatrixType>::m_maxIterationsPerRow * rows).compute(a);
+ VERIFY_IS_EQUAL(ei2.info(), Success);
+ VERIFY_IS_EQUAL(ei2.eigenvectors(), ei1.eigenvectors());
+ VERIFY_IS_EQUAL(ei2.eigenvalues(), ei1.eigenvalues());
+ if (rows > 2) {
+ ei2.setMaxIterations(1).compute(a);
+ VERIFY_IS_EQUAL(ei2.info(), NoConvergence);
+ VERIFY_IS_EQUAL(ei2.getMaxIterations(), 1);
+ }
+
EigenSolver<MatrixType> eiNoEivecs(a, false);
VERIFY_IS_EQUAL(eiNoEivecs.info(), Success);
VERIFY_IS_APPROX(ei1.eigenvalues(), eiNoEivecs.eigenvalues());
@@ -78,7 +88,7 @@ template<typename MatrixType> void eigensolver_verify_assert(const MatrixType& m
void test_eigensolver_generic()
{
- int s;
+ int s = 0;
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST_1( eigensolver(Matrix4f()) );
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
@@ -98,7 +108,7 @@ void test_eigensolver_generic()
CALL_SUBTEST_4( eigensolver_verify_assert(Matrix2d()) );
// Test problem size constructors
- CALL_SUBTEST_5(EigenSolver<MatrixXf>(s));
+ CALL_SUBTEST_5(EigenSolver<MatrixXf> tmp(s));
// regression test for bug 410
CALL_SUBTEST_2(
@@ -111,5 +121,5 @@ void test_eigensolver_generic()
}
);
- EIGEN_UNUSED_VARIABLE(s)
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
}
diff --git a/test/eigensolver_selfadjoint.cpp b/test/eigensolver_selfadjoint.cpp
index 02dbdb429..5c6ecd875 100644
--- a/test/eigensolver_selfadjoint.cpp
+++ b/test/eigensolver_selfadjoint.cpp
@@ -23,9 +23,6 @@ template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m)
typedef typename MatrixType::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
- typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
- typedef typename std::complex<typename NumTraits<typename MatrixType::Scalar>::Real> Complex;
RealScalar largerEps = 10*test_precision<RealScalar>();
@@ -113,7 +110,7 @@ template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m)
void test_eigensolver_selfadjoint()
{
- int s;
+ int s = 0;
for(int i = 0; i < g_repeat; i++) {
// very important to test 3x3 and 2x2 matrices since we provide special paths for them
CALL_SUBTEST_1( selfadjointeigensolver(Matrix2d()) );
@@ -138,9 +135,9 @@ void test_eigensolver_selfadjoint()
// Test problem size constructors
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
- CALL_SUBTEST_8(SelfAdjointEigenSolver<MatrixXf>(s));
- CALL_SUBTEST_8(Tridiagonalization<MatrixXf>(s));
+ CALL_SUBTEST_8(SelfAdjointEigenSolver<MatrixXf> tmp1(s));
+ CALL_SUBTEST_8(Tridiagonalization<MatrixXf> tmp2(s));
- EIGEN_UNUSED_VARIABLE(s)
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
}
diff --git a/test/exceptions.cpp b/test/exceptions.cpp
index 8c48b2f7b..b83fb82ba 100644
--- a/test/exceptions.cpp
+++ b/test/exceptions.cpp
@@ -69,6 +69,10 @@ class ScalarWithExceptions
static int countdown;
};
+ScalarWithExceptions real(const ScalarWithExceptions &x) { return x; }
+ScalarWithExceptions imag(const ScalarWithExceptions & ) { return 0; }
+ScalarWithExceptions conj(const ScalarWithExceptions &x) { return x; }
+
int ScalarWithExceptions::instances = 0;
int ScalarWithExceptions::countdown = 0;
diff --git a/test/geo_alignedbox.cpp b/test/geo_alignedbox.cpp
index 5886f9181..8e36adbe3 100644
--- a/test/geo_alignedbox.cpp
+++ b/test/geo_alignedbox.cpp
@@ -15,6 +15,10 @@
#include<iostream>
using namespace std;
+template<typename T> EIGEN_DONT_INLINE
+void kill_extra_precision(T& x) { eigen_assert(&x != 0); }
+
+
template<typename BoxType> void alignedbox(const BoxType& _box)
{
/* this test covers the following files:
@@ -36,6 +40,10 @@ template<typename BoxType> void alignedbox(const BoxType& _box)
BoxType b0(dim);
BoxType b1(VectorType::Random(dim),VectorType::Random(dim));
BoxType b2;
+
+ kill_extra_precision(b1);
+ kill_extra_precision(p0);
+ kill_extra_precision(p1);
b0.extend(p0);
b0.extend(p1);
@@ -71,7 +79,6 @@ void alignedboxCastTests(const BoxType& _box)
// casting
typedef typename BoxType::Index Index;
typedef typename BoxType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
typedef Matrix<Scalar, BoxType::AmbientDimAtCompileTime, 1> VectorType;
const Index dim = _box.dim();
@@ -109,7 +116,7 @@ void specificTest1()
VERIFY_IS_APPROX( 14.0f, box.volume() );
VERIFY_IS_APPROX( 53.0f, box.diagonal().squaredNorm() );
- VERIFY_IS_APPROX( internal::sqrt( 53.0f ), box.diagonal().norm() );
+ VERIFY_IS_APPROX( std::sqrt( 53.0f ), box.diagonal().norm() );
VERIFY_IS_APPROX( m, box.corner( BoxType::BottomLeft ) );
VERIFY_IS_APPROX( M, box.corner( BoxType::TopRight ) );
diff --git a/test/geo_eulerangles.cpp b/test/geo_eulerangles.cpp
index 9bf149d2a..b4830bd41 100644
--- a/test/geo_eulerangles.cpp
+++ b/test/geo_eulerangles.cpp
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008-2012 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
@@ -12,10 +12,55 @@
#include <Eigen/LU>
#include <Eigen/SVD>
-template<typename Scalar> void eulerangles(void)
+
+template<typename Scalar>
+void verify_euler(const Matrix<Scalar,3,1>& ea, int i, int j, int k)
{
typedef Matrix<Scalar,3,3> Matrix3;
typedef Matrix<Scalar,3,1> Vector3;
+ typedef AngleAxis<Scalar> AngleAxisx;
+ using std::abs;
+ Matrix3 m(AngleAxisx(ea[0], Vector3::Unit(i)) * AngleAxisx(ea[1], Vector3::Unit(j)) * AngleAxisx(ea[2], Vector3::Unit(k)));
+ Vector3 eabis = m.eulerAngles(i, j, k);
+ Matrix3 mbis(AngleAxisx(eabis[0], Vector3::Unit(i)) * AngleAxisx(eabis[1], Vector3::Unit(j)) * AngleAxisx(eabis[2], Vector3::Unit(k)));
+ VERIFY_IS_APPROX(m, mbis);
+ /* If I==K, and ea[1]==0, then there no unique solution. */
+ /* The remark apply in the case where I!=K, and |ea[1]| is close to pi/2. */
+ if( (i!=k || ea[1]!=0) && (i==k || !internal::isApprox(abs(ea[1]),Scalar(M_PI/2),test_precision<Scalar>())) )
+ VERIFY((ea-eabis).norm() <= test_precision<Scalar>());
+
+ // approx_or_less_than does not work for 0
+ VERIFY(0 < eabis[0] || test_isMuchSmallerThan(eabis[0], Scalar(1)));
+ VERIFY_IS_APPROX_OR_LESS_THAN(eabis[0], Scalar(M_PI));
+ VERIFY_IS_APPROX_OR_LESS_THAN(-Scalar(M_PI), eabis[1]);
+ VERIFY_IS_APPROX_OR_LESS_THAN(eabis[1], Scalar(M_PI));
+ VERIFY_IS_APPROX_OR_LESS_THAN(-Scalar(M_PI), eabis[2]);
+ VERIFY_IS_APPROX_OR_LESS_THAN(eabis[2], Scalar(M_PI));
+}
+
+template<typename Scalar> void check_all_var(const Matrix<Scalar,3,1>& ea)
+{
+ verify_euler(ea, 0,1,2);
+ verify_euler(ea, 0,1,0);
+ verify_euler(ea, 0,2,1);
+ verify_euler(ea, 0,2,0);
+
+ verify_euler(ea, 1,2,0);
+ verify_euler(ea, 1,2,1);
+ verify_euler(ea, 1,0,2);
+ verify_euler(ea, 1,0,1);
+
+ verify_euler(ea, 2,0,1);
+ verify_euler(ea, 2,0,2);
+ verify_euler(ea, 2,1,0);
+ verify_euler(ea, 2,1,2);
+}
+
+template<typename Scalar> void eulerangles()
+{
+ typedef Matrix<Scalar,3,3> Matrix3;
+ typedef Matrix<Scalar,3,1> Vector3;
+ typedef Array<Scalar,3,1> Array3;
typedef Quaternion<Scalar> Quaternionx;
typedef AngleAxis<Scalar> AngleAxisx;
@@ -24,25 +69,38 @@ template<typename Scalar> void eulerangles(void)
q1 = AngleAxisx(a, Vector3::Random().normalized());
Matrix3 m;
m = q1;
-
- #define VERIFY_EULER(I,J,K, X,Y,Z) { \
- Vector3 ea = m.eulerAngles(I,J,K); \
- VERIFY_IS_APPROX(m, Matrix3(AngleAxisx(ea[0], Vector3::Unit##X()) * AngleAxisx(ea[1], Vector3::Unit##Y()) * AngleAxisx(ea[2], Vector3::Unit##Z()))); \
- }
- VERIFY_EULER(0,1,2, X,Y,Z);
- VERIFY_EULER(0,1,0, X,Y,X);
- VERIFY_EULER(0,2,1, X,Z,Y);
- VERIFY_EULER(0,2,0, X,Z,X);
-
- VERIFY_EULER(1,2,0, Y,Z,X);
- VERIFY_EULER(1,2,1, Y,Z,Y);
- VERIFY_EULER(1,0,2, Y,X,Z);
- VERIFY_EULER(1,0,1, Y,X,Y);
-
- VERIFY_EULER(2,0,1, Z,X,Y);
- VERIFY_EULER(2,0,2, Z,X,Z);
- VERIFY_EULER(2,1,0, Z,Y,X);
- VERIFY_EULER(2,1,2, Z,Y,Z);
+
+ Vector3 ea = m.eulerAngles(0,1,2);
+ check_all_var(ea);
+ ea = m.eulerAngles(0,1,0);
+ check_all_var(ea);
+
+ // Check with purely random Quaternion:
+ q1.coeffs() = Quaternionx::Coefficients::Random().normalized();
+ m = q1;
+ ea = m.eulerAngles(0,1,2);
+ check_all_var(ea);
+ ea = m.eulerAngles(0,1,0);
+ check_all_var(ea);
+
+ // Check with random angles in range [0:pi]x[-pi:pi]x[-pi:pi].
+ ea = (Array3::Random() + Array3(1,0,0))*Scalar(M_PI)*Array3(0.5,1,1);
+ check_all_var(ea);
+
+ ea[2] = ea[0] = internal::random<Scalar>(0,Scalar(M_PI));
+ check_all_var(ea);
+
+ ea[0] = ea[1] = internal::random<Scalar>(0,Scalar(M_PI));
+ check_all_var(ea);
+
+ ea[1] = 0;
+ check_all_var(ea);
+
+ ea.head(2).setZero();
+ check_all_var(ea);
+
+ ea.setZero();
+ check_all_var(ea);
}
void test_geo_eulerangles()
diff --git a/test/geo_hyperplane.cpp b/test/geo_hyperplane.cpp
index 3fc80c4c7..f26fc1329 100644
--- a/test/geo_hyperplane.cpp
+++ b/test/geo_hyperplane.cpp
@@ -22,7 +22,6 @@ template<typename HyperplaneType> void hyperplane(const HyperplaneType& _plane)
const Index dim = _plane.dim();
enum { Options = HyperplaneType::Options };
typedef typename HyperplaneType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
typedef Matrix<Scalar, HyperplaneType::AmbientDimAtCompileTime, 1> VectorType;
typedef Matrix<Scalar, HyperplaneType::AmbientDimAtCompileTime,
HyperplaneType::AmbientDimAtCompileTime> MatrixType;
@@ -79,6 +78,7 @@ template<typename HyperplaneType> void hyperplane(const HyperplaneType& _plane)
template<typename Scalar> void lines()
{
+ using std::abs;
typedef Hyperplane<Scalar, 2> HLine;
typedef ParametrizedLine<Scalar, 2> PLine;
typedef Matrix<Scalar,2,1> Vector;
@@ -90,7 +90,7 @@ template<typename Scalar> void lines()
Vector u = Vector::Random();
Vector v = Vector::Random();
Scalar a = internal::random<Scalar>();
- while (internal::abs(a-1) < 1e-4) a = internal::random<Scalar>();
+ while (abs(a-1) < 1e-4) a = internal::random<Scalar>();
while (u.norm() < 1e-4) u = Vector::Random();
while (v.norm() < 1e-4) v = Vector::Random();
diff --git a/test/geo_parametrizedline.cpp b/test/geo_parametrizedline.cpp
index 4e1f845dd..f0462d40a 100644
--- a/test/geo_parametrizedline.cpp
+++ b/test/geo_parametrizedline.cpp
@@ -18,13 +18,12 @@ template<typename LineType> void parametrizedline(const LineType& _line)
/* this test covers the following files:
ParametrizedLine.h
*/
+ using std::abs;
typedef typename LineType::Index Index;
const Index dim = _line.dim();
typedef typename LineType::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
typedef Matrix<Scalar, LineType::AmbientDimAtCompileTime, 1> VectorType;
- typedef Matrix<Scalar, LineType::AmbientDimAtCompileTime,
- LineType::AmbientDimAtCompileTime> MatrixType;
typedef Hyperplane<Scalar,LineType::AmbientDimAtCompileTime> HyperplaneType;
VectorType p0 = VectorType::Random(dim);
@@ -35,7 +34,7 @@ template<typename LineType> void parametrizedline(const LineType& _line)
LineType l0(p0, d0);
Scalar s0 = internal::random<Scalar>();
- Scalar s1 = internal::abs(internal::random<Scalar>());
+ Scalar s1 = abs(internal::random<Scalar>());
VERIFY_IS_MUCH_SMALLER_THAN( l0.distance(p0), RealScalar(1) );
VERIFY_IS_MUCH_SMALLER_THAN( l0.distance(p0+s0*d0), RealScalar(1) );
diff --git a/test/geo_quaternion.cpp b/test/geo_quaternion.cpp
index 6e6922864..1694b32c7 100644
--- a/test/geo_quaternion.cpp
+++ b/test/geo_quaternion.cpp
@@ -23,22 +23,22 @@ template<typename T> T bounded_acos(T v)
template<typename QuatType> void check_slerp(const QuatType& q0, const QuatType& q1)
{
+ using std::abs;
typedef typename QuatType::Scalar Scalar;
- typedef Matrix<Scalar,3,1> VectorType;
typedef AngleAxis<Scalar> AA;
Scalar largeEps = test_precision<Scalar>();
Scalar theta_tot = AA(q1*q0.inverse()).angle();
if(theta_tot>M_PI)
- theta_tot = 2.*M_PI-theta_tot;
- for(Scalar t=0; t<=1.001; t+=0.1)
+ theta_tot = Scalar(2.*M_PI)-theta_tot;
+ for(Scalar t=0; t<=Scalar(1.001); t+=Scalar(0.1))
{
QuatType q = q0.slerp(t,q1);
Scalar theta = AA(q*q0.inverse()).angle();
- VERIFY(internal::abs(q.norm() - 1) < largeEps);
+ VERIFY(abs(q.norm() - 1) < largeEps);
if(theta_tot==0) VERIFY(theta_tot==0);
- else VERIFY(internal::abs(theta/theta_tot - t) < largeEps);
+ else VERIFY(abs(theta - t * theta_tot) < largeEps);
}
}
@@ -47,8 +47,7 @@ template<typename Scalar, int Options> void quaternion(void)
/* this test covers the following files:
Quaternion.h
*/
-
- typedef Matrix<Scalar,3,3> Matrix3;
+ using std::abs;
typedef Matrix<Scalar,3,1> Vector3;
typedef Matrix<Scalar,4,1> Vector4;
typedef Quaternion<Scalar,Options> Quaternionx;
@@ -82,13 +81,13 @@ template<typename Scalar, int Options> void quaternion(void)
q2 = AngleAxisx(a, v1.normalized());
// angular distance
- Scalar refangle = internal::abs(AngleAxisx(q1.inverse()*q2).angle());
+ Scalar refangle = abs(AngleAxisx(q1.inverse()*q2).angle());
if (refangle>Scalar(M_PI))
refangle = Scalar(2)*Scalar(M_PI) - refangle;
if((q1.coeffs()-q2.coeffs()).norm() > 10*largeEps)
{
- VERIFY_IS_MUCH_SMALLER_THAN(internal::abs(q1.angularDistance(q2) - refangle), Scalar(1));
+ VERIFY_IS_MUCH_SMALLER_THAN(abs(q1.angularDistance(q2) - refangle), Scalar(1));
}
// rotation matrix conversion
@@ -109,7 +108,7 @@ template<typename Scalar, int Options> void quaternion(void)
// Do not execute the test if the rotation angle is almost zero, or
// the rotation axis and v1 are almost parallel.
- if (internal::abs(aa.angle()) > 5*test_precision<Scalar>()
+ if (abs(aa.angle()) > 5*test_precision<Scalar>()
&& (aa.axis() - v1.normalized()).norm() < 1.99
&& (aa.axis() + v1.normalized()).norm() < 1.99)
{
@@ -157,7 +156,7 @@ template<typename Scalar, int Options> void quaternion(void)
check_slerp(q1,q2);
q1 = AngleAxisx(b, v1.normalized());
- q2 = AngleAxisx(b+M_PI, v1.normalized());
+ q2 = AngleAxisx(b+Scalar(M_PI), v1.normalized());
check_slerp(q1,q2);
q1 = AngleAxisx(b, v1.normalized());
@@ -171,23 +170,36 @@ template<typename Scalar, int Options> void quaternion(void)
template<typename Scalar> void mapQuaternion(void){
typedef Map<Quaternion<Scalar>, Aligned> MQuaternionA;
+ typedef Map<const Quaternion<Scalar>, Aligned> MCQuaternionA;
typedef Map<Quaternion<Scalar> > MQuaternionUA;
typedef Map<const Quaternion<Scalar> > MCQuaternionUA;
typedef Quaternion<Scalar> Quaternionx;
+ typedef Matrix<Scalar,3,1> Vector3;
+ typedef AngleAxis<Scalar> AngleAxisx;
+
+ Vector3 v0 = Vector3::Random(),
+ v1 = Vector3::Random();
+ Scalar a = internal::random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
EIGEN_ALIGN16 Scalar array1[4];
EIGEN_ALIGN16 Scalar array2[4];
EIGEN_ALIGN16 Scalar array3[4+1];
Scalar* array3unaligned = array3+1;
+
+ MQuaternionA mq1(array1);
+ MCQuaternionA mcq1(array1);
+ MQuaternionA mq2(array2);
+ MQuaternionUA mq3(array3unaligned);
+ MCQuaternionUA mcq3(array3unaligned);
// std::cerr << array1 << " " << array2 << " " << array3 << "\n";
- MQuaternionA(array1).coeffs().setRandom();
- (MQuaternionA(array2)) = MQuaternionA(array1);
- (MQuaternionUA(array3unaligned)) = MQuaternionA(array1);
+ mq1 = AngleAxisx(a, v0.normalized());
+ mq2 = mq1;
+ mq3 = mq1;
- Quaternionx q1 = MQuaternionA(array1);
- Quaternionx q2 = MQuaternionA(array2);
- Quaternionx q3 = MQuaternionUA(array3unaligned);
+ Quaternionx q1 = mq1;
+ Quaternionx q2 = mq2;
+ Quaternionx q3 = mq3;
Quaternionx q4 = MCQuaternionUA(array3unaligned);
VERIFY_IS_APPROX(q1.coeffs(), q2.coeffs());
@@ -197,6 +209,23 @@ template<typename Scalar> void mapQuaternion(void){
if(internal::packet_traits<Scalar>::Vectorizable)
VERIFY_RAISES_ASSERT((MQuaternionA(array3unaligned)));
#endif
+
+ VERIFY_IS_APPROX(mq1 * (mq1.inverse() * v1), v1);
+ VERIFY_IS_APPROX(mq1 * (mq1.conjugate() * v1), v1);
+
+ VERIFY_IS_APPROX(mcq1 * (mcq1.inverse() * v1), v1);
+ VERIFY_IS_APPROX(mcq1 * (mcq1.conjugate() * v1), v1);
+
+ VERIFY_IS_APPROX(mq3 * (mq3.inverse() * v1), v1);
+ VERIFY_IS_APPROX(mq3 * (mq3.conjugate() * v1), v1);
+
+ VERIFY_IS_APPROX(mcq3 * (mcq3.inverse() * v1), v1);
+ VERIFY_IS_APPROX(mcq3 * (mcq3.conjugate() * v1), v1);
+
+ VERIFY_IS_APPROX(mq1*mq2, q1*q2);
+ VERIFY_IS_APPROX(mq3*mq2, q3*q2);
+ VERIFY_IS_APPROX(mcq1*mq2, q1*q2);
+ VERIFY_IS_APPROX(mcq3*mq2, q3*q2);
}
template<typename Scalar> void quaternionAlignment(void){
diff --git a/test/geo_transformations.cpp b/test/geo_transformations.cpp
index f4d65aabc..ee3030b5d 100644
--- a/test/geo_transformations.cpp
+++ b/test/geo_transformations.cpp
@@ -17,22 +17,11 @@ template<typename Scalar, int Mode, int Options> void non_projective_only()
/* this test covers the following files:
Cross.h Quaternion.h, Transform.cpp
*/
- typedef Matrix<Scalar,2,2> Matrix2;
- typedef Matrix<Scalar,3,3> Matrix3;
- typedef Matrix<Scalar,4,4> Matrix4;
- typedef Matrix<Scalar,2,1> Vector2;
typedef Matrix<Scalar,3,1> Vector3;
- typedef Matrix<Scalar,4,1> Vector4;
typedef Quaternion<Scalar> Quaternionx;
typedef AngleAxis<Scalar> AngleAxisx;
- typedef Transform<Scalar,2,Mode,Options> Transform2;
typedef Transform<Scalar,3,Mode,Options> Transform3;
- typedef Transform<Scalar,2,Isometry,Options> Isometry2;
- typedef Transform<Scalar,3,Isometry,Options> Isometry3;
- typedef typename Transform3::MatrixType MatrixType;
- typedef DiagonalMatrix<Scalar,2> AlignedScaling2;
typedef DiagonalMatrix<Scalar,3> AlignedScaling3;
- typedef Translation<Scalar,2> Translation2;
typedef Translation<Scalar,3> Translation3;
Vector3 v0 = Vector3::Random(),
@@ -88,7 +77,8 @@ template<typename Scalar, int Mode, int Options> void transformations()
/* this test covers the following files:
Cross.h Quaternion.h, Transform.cpp
*/
- typedef Matrix<Scalar,2,2> Matrix2;
+ using std::cos;
+ using std::abs;
typedef Matrix<Scalar,3,3> Matrix3;
typedef Matrix<Scalar,4,4> Matrix4;
typedef Matrix<Scalar,2,1> Vector2;
@@ -98,10 +88,7 @@ template<typename Scalar, int Mode, int Options> void transformations()
typedef AngleAxis<Scalar> AngleAxisx;
typedef Transform<Scalar,2,Mode,Options> Transform2;
typedef Transform<Scalar,3,Mode,Options> Transform3;
- typedef Transform<Scalar,2,Isometry,Options> Isometry2;
- typedef Transform<Scalar,3,Isometry,Options> Isometry3;
typedef typename Transform3::MatrixType MatrixType;
- typedef DiagonalMatrix<Scalar,2> AlignedScaling2;
typedef DiagonalMatrix<Scalar,3> AlignedScaling3;
typedef Translation<Scalar,2> Translation2;
typedef Translation<Scalar,3> Translation3;
@@ -115,7 +102,7 @@ template<typename Scalar, int Mode, int Options> void transformations()
VERIFY_IS_APPROX(v0, AngleAxisx(a, v0.normalized()) * v0);
VERIFY_IS_APPROX(-v0, AngleAxisx(Scalar(M_PI), v0.unitOrthogonal()) * v0);
- VERIFY_IS_APPROX(internal::cos(a)*v0.squaredNorm(), v0.dot(AngleAxisx(a, v0.unitOrthogonal()) * v0));
+ VERIFY_IS_APPROX(cos(a)*v0.squaredNorm(), v0.dot(AngleAxisx(a, v0.unitOrthogonal()) * v0));
m = AngleAxisx(a, v0.normalized()).toRotationMatrix().adjoint();
VERIFY_IS_APPROX(Matrix3::Identity(), m * AngleAxisx(a, v0.normalized()));
VERIFY_IS_APPROX(Matrix3::Identity(), AngleAxisx(a, v0.normalized()) * m);
@@ -155,7 +142,7 @@ template<typename Scalar, int Mode, int Options> void transformations()
// Transform
// TODO complete the tests !
a = 0;
- while (internal::abs(a)<Scalar(0.1))
+ while (abs(a)<Scalar(0.1))
a = internal::random<Scalar>(-Scalar(0.4)*Scalar(M_PI), Scalar(0.4)*Scalar(M_PI));
q1 = AngleAxisx(a, v0.normalized());
Transform3 t0, t1, t2;
@@ -249,7 +236,7 @@ template<typename Scalar, int Mode, int Options> void transformations()
Vector2 v20 = Vector2::Random();
Vector2 v21 = Vector2::Random();
for (int k=0; k<2; ++k)
- if (internal::abs(v21[k])<Scalar(1e-3)) v21[k] = Scalar(1e-3);
+ if (abs(v21[k])<Scalar(1e-3)) v21[k] = Scalar(1e-3);
t21.setIdentity();
t21.linear() = Rotation2D<Scalar>(a).toRotationMatrix();
VERIFY_IS_APPROX(t20.fromPositionOrientationScale(v20,a,v21).matrix(),
@@ -292,6 +279,13 @@ template<typename Scalar, int Mode, int Options> void transformations()
t1 = Eigen::Scaling(s0,s0,s0) * t1;
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+ t0 = t3;
+ t0.scale(s0);
+ t1 = t3 * Eigen::Scaling(s0);
+ VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+ t0.prescale(s0);
+ t1 = Eigen::Scaling(s0) * t1;
+ VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
t0.setIdentity();
t0.prerotate(q1).prescale(v0).pretranslate(v0);
@@ -400,8 +394,8 @@ template<typename Scalar, int Mode, int Options> void transformations()
Rotation2D<double> r2d1d = r2d1.template cast<double>();
VERIFY_IS_APPROX(r2d1d.template cast<Scalar>(),r2d1);
- t20 = Translation2(v20) * (Rotation2D<Scalar>(s0) * Scaling(s0));
- t21 = Translation2(v20) * Rotation2D<Scalar>(s0) * Scaling(s0);
+ t20 = Translation2(v20) * (Rotation2D<Scalar>(s0) * Eigen::Scaling(s0));
+ t21 = Translation2(v20) * Rotation2D<Scalar>(s0) * Eigen::Scaling(s0);
VERIFY_IS_APPROX(t20,t21);
}
diff --git a/test/householder.cpp b/test/householder.cpp
index 203dce46c..c5f6b5e4f 100644
--- a/test/householder.cpp
+++ b/test/householder.cpp
@@ -29,8 +29,6 @@ template<typename MatrixType> void householder(const MatrixType& m)
typedef Matrix<Scalar, Dynamic, MatrixType::ColsAtCompileTime> HBlockMatrixType;
typedef Matrix<Scalar, Dynamic, 1> HCoeffsVectorType;
- typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, MatrixType::ColsAtCompileTime> RightSquareMatrixType;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, Dynamic> VBlockMatrixType;
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, MatrixType::RowsAtCompileTime> TMatrixType;
Matrix<Scalar, EIGEN_SIZE_MAX(MatrixType::RowsAtCompileTime,MatrixType::ColsAtCompileTime), 1> _tmp((std::max)(rows,cols));
@@ -62,8 +60,8 @@ template<typename MatrixType> void householder(const MatrixType& m)
m1.applyHouseholderOnTheLeft(essential,beta,tmp);
VERIFY_IS_APPROX(m1.norm(), m2.norm());
if(rows>=2) VERIFY_IS_MUCH_SMALLER_THAN(m1.block(1,0,rows-1,cols).norm(), m1.norm());
- VERIFY_IS_MUCH_SMALLER_THAN(internal::imag(m1(0,0)), internal::real(m1(0,0)));
- VERIFY_IS_APPROX(internal::real(m1(0,0)), alpha);
+ VERIFY_IS_MUCH_SMALLER_THAN(numext::imag(m1(0,0)), numext::real(m1(0,0)));
+ VERIFY_IS_APPROX(numext::real(m1(0,0)), alpha);
v1 = VectorType::Random(rows);
if(even) v1.tail(rows-1).setZero();
@@ -74,8 +72,8 @@ template<typename MatrixType> void householder(const MatrixType& m)
m3.applyHouseholderOnTheRight(essential,beta,tmp);
VERIFY_IS_APPROX(m3.norm(), m4.norm());
if(rows>=2) VERIFY_IS_MUCH_SMALLER_THAN(m3.block(0,1,rows,rows-1).norm(), m3.norm());
- VERIFY_IS_MUCH_SMALLER_THAN(internal::imag(m3(0,0)), internal::real(m3(0,0)));
- VERIFY_IS_APPROX(internal::real(m3(0,0)), alpha);
+ VERIFY_IS_MUCH_SMALLER_THAN(numext::imag(m3(0,0)), numext::real(m3(0,0)));
+ VERIFY_IS_APPROX(numext::real(m3(0,0)), alpha);
// test householder sequence on the left with a shift
@@ -91,12 +89,29 @@ template<typename MatrixType> void householder(const MatrixType& m)
hseq.setLength(hc.size()).setShift(shift);
VERIFY(hseq.length() == hc.size());
VERIFY(hseq.shift() == shift);
-
+
MatrixType m5 = m2;
m5.block(shift,0,brows,cols).template triangularView<StrictlyLower>().setZero();
VERIFY_IS_APPROX(hseq * m5, m1); // test applying hseq directly
m3 = hseq;
VERIFY_IS_APPROX(m3 * m5, m1); // test evaluating hseq to a dense matrix, then applying
+
+ SquareMatrixType hseq_mat = hseq;
+ SquareMatrixType hseq_mat_conj = hseq.conjugate();
+ SquareMatrixType hseq_mat_adj = hseq.adjoint();
+ SquareMatrixType hseq_mat_trans = hseq.transpose();
+ SquareMatrixType m6 = SquareMatrixType::Random(rows, rows);
+ VERIFY_IS_APPROX(hseq_mat.adjoint(), hseq_mat_adj);
+ VERIFY_IS_APPROX(hseq_mat.conjugate(), hseq_mat_conj);
+ VERIFY_IS_APPROX(hseq_mat.transpose(), hseq_mat_trans);
+ VERIFY_IS_APPROX(hseq_mat * m6, hseq_mat * m6);
+ VERIFY_IS_APPROX(hseq_mat.adjoint() * m6, hseq_mat_adj * m6);
+ VERIFY_IS_APPROX(hseq_mat.conjugate() * m6, hseq_mat_conj * m6);
+ VERIFY_IS_APPROX(hseq_mat.transpose() * m6, hseq_mat_trans * m6);
+ VERIFY_IS_APPROX(m6 * hseq_mat, m6 * hseq_mat);
+ VERIFY_IS_APPROX(m6 * hseq_mat.adjoint(), m6 * hseq_mat_adj);
+ VERIFY_IS_APPROX(m6 * hseq_mat.conjugate(), m6 * hseq_mat_conj);
+ VERIFY_IS_APPROX(m6 * hseq_mat.transpose(), m6 * hseq_mat_trans);
// test householder sequence on the right with a shift
diff --git a/test/inverse.cpp b/test/inverse.cpp
index cff42dd8d..8187b088d 100644
--- a/test/inverse.cpp
+++ b/test/inverse.cpp
@@ -13,6 +13,7 @@
template<typename MatrixType> void inverse(const MatrixType& m)
{
+ using std::abs;
typedef typename MatrixType::Index Index;
/* this test covers the following files:
Inverse.h
@@ -21,8 +22,6 @@ template<typename MatrixType> void inverse(const MatrixType& m)
Index cols = m.cols();
typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
MatrixType m1(rows, cols),
m2(rows, cols),
@@ -42,6 +41,9 @@ template<typename MatrixType> void inverse(const MatrixType& m)
VERIFY_IS_APPROX(MatrixType(m1.transpose().inverse()), MatrixType(m1.inverse().transpose()));
#if !defined(EIGEN_TEST_PART_5) && !defined(EIGEN_TEST_PART_6)
+ typedef typename NumTraits<Scalar>::Real RealScalar;
+ typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
+
//computeInverseAndDetWithCheck tests
//First: an invertible matrix
bool invertible;
@@ -63,7 +65,7 @@ template<typename MatrixType> void inverse(const MatrixType& m)
MatrixType m3 = v3*v3.transpose(), m4(rows,cols);
m3.computeInverseAndDetWithCheck(m4, det, invertible);
VERIFY( rows==1 ? invertible : !invertible );
- VERIFY_IS_MUCH_SMALLER_THAN(internal::abs(det-m3.determinant()), RealScalar(1));
+ VERIFY_IS_MUCH_SMALLER_THAN(abs(det-m3.determinant()), RealScalar(1));
m3.computeInverseWithCheck(m4, invertible);
VERIFY( rows==1 ? invertible : !invertible );
#endif
@@ -84,19 +86,19 @@ template<typename MatrixType> void inverse(const MatrixType& m)
void test_inverse()
{
- int s;
+ int s = 0;
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST_1( inverse(Matrix<double,1,1>()) );
CALL_SUBTEST_2( inverse(Matrix2d()) );
CALL_SUBTEST_3( inverse(Matrix3f()) );
CALL_SUBTEST_4( inverse(Matrix4f()) );
CALL_SUBTEST_4( inverse(Matrix<float,4,4,DontAlign>()) );
- s = internal::random<int>(50,320);
+ s = internal::random<int>(50,320);
CALL_SUBTEST_5( inverse(MatrixXf(s,s)) );
s = internal::random<int>(25,100);
CALL_SUBTEST_6( inverse(MatrixXcd(s,s)) );
CALL_SUBTEST_7( inverse(Matrix4d()) );
CALL_SUBTEST_7( inverse(Matrix<double,4,4,DontAlign>()) );
}
- EIGEN_UNUSED_VARIABLE(s)
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
}
diff --git a/test/jacobi.cpp b/test/jacobi.cpp
index f64f5d08f..7ccd4124b 100644
--- a/test/jacobi.cpp
+++ b/test/jacobi.cpp
@@ -14,7 +14,6 @@
template<typename MatrixType, typename JacobiScalar>
void jacobi(const MatrixType& m = MatrixType())
{
- typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::Index Index;
Index rows = m.rows();
Index cols = m.cols();
@@ -41,8 +40,8 @@ void jacobi(const MatrixType& m = MatrixType())
MatrixType b = a;
b.applyOnTheLeft(p, q, rot);
- VERIFY_IS_APPROX(b.row(p), c * a.row(p) + internal::conj(s) * a.row(q));
- VERIFY_IS_APPROX(b.row(q), -s * a.row(p) + internal::conj(c) * a.row(q));
+ VERIFY_IS_APPROX(b.row(p), c * a.row(p) + numext::conj(s) * a.row(q));
+ VERIFY_IS_APPROX(b.row(q), -s * a.row(p) + numext::conj(c) * a.row(q));
}
{
@@ -55,7 +54,7 @@ void jacobi(const MatrixType& m = MatrixType())
MatrixType b = a;
b.applyOnTheRight(p, q, rot);
VERIFY_IS_APPROX(b.col(p), c * a.col(p) - s * a.col(q));
- VERIFY_IS_APPROX(b.col(q), internal::conj(s) * a.col(p) + internal::conj(c) * a.col(q));
+ VERIFY_IS_APPROX(b.col(q), numext::conj(s) * a.col(p) + numext::conj(c) * a.col(q));
}
}
@@ -75,7 +74,8 @@ void test_jacobi()
// complex<float> is really important to test as it is the only way to cover conjugation issues in certain unaligned paths
CALL_SUBTEST_6(( jacobi<MatrixXcf, float>(MatrixXcf(r,c)) ));
CALL_SUBTEST_6(( jacobi<MatrixXcf, std::complex<float> >(MatrixXcf(r,c)) ));
- (void) r;
- (void) c;
+
+ TEST_SET_BUT_UNUSED_VARIABLE(r);
+ TEST_SET_BUT_UNUSED_VARIABLE(c);
}
}
diff --git a/test/jacobisvd.cpp b/test/jacobisvd.cpp
index f6c567829..7c21f0ab3 100644
--- a/test/jacobisvd.cpp
+++ b/test/jacobisvd.cpp
@@ -27,11 +27,8 @@ void jacobisvd_check_full(const MatrixType& m, const JacobiSVD<MatrixType, QRPre
};
typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime> MatrixUType;
typedef Matrix<Scalar, ColsAtCompileTime, ColsAtCompileTime> MatrixVType;
- typedef Matrix<Scalar, RowsAtCompileTime, 1> ColVectorType;
- typedef Matrix<Scalar, ColsAtCompileTime, 1> InputVectorType;
MatrixType sigma = MatrixType::Zero(rows,cols);
sigma.diagonal() = svd.singularValues().template cast<Scalar>();
@@ -70,6 +67,7 @@ template<typename MatrixType, int QRPreconditioner>
void jacobisvd_solve(const MatrixType& m, unsigned int computationOptions)
{
typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::RealScalar RealScalar;
typedef typename MatrixType::Index Index;
Index rows = m.rows();
Index cols = m.cols();
@@ -84,9 +82,90 @@ void jacobisvd_solve(const MatrixType& m, unsigned int computationOptions)
RhsType rhs = RhsType::Random(rows, internal::random<Index>(1, cols));
JacobiSVD<MatrixType, QRPreconditioner> svd(m, computationOptions);
+
+ if(internal::is_same<RealScalar,double>::value) svd.setThreshold(1e-8);
+ else if(internal::is_same<RealScalar,float>::value) svd.setThreshold(1e-4);
+
SolutionType x = svd.solve(rhs);
+
+ RealScalar residual = (m*x-rhs).norm();
+ // Check that there is no significantly better solution in the neighborhood of x
+ if(!test_isMuchSmallerThan(residual,rhs.norm()))
+ {
+ // If the residual is very small, then we have an exact solution, so we are already good.
+ for(int k=0;k<x.rows();++k)
+ {
+ SolutionType y(x);
+ y.row(k).array() += 2*NumTraits<RealScalar>::epsilon();
+ RealScalar residual_y = (m*y-rhs).norm();
+ VERIFY( test_isApprox(residual_y,residual) || residual < residual_y );
+
+ y.row(k) = x.row(k).array() - 2*NumTraits<RealScalar>::epsilon();
+ residual_y = (m*y-rhs).norm();
+ VERIFY( test_isApprox(residual_y,residual) || residual < residual_y );
+ }
+ }
+
// evaluate normal equation which works also for least-squares solutions
- VERIFY_IS_APPROX(m.adjoint()*m*x,m.adjoint()*rhs);
+ if(internal::is_same<RealScalar,double>::value)
+ {
+ // This test is not stable with single precision.
+ // This is probably because squaring m signicantly affects the precision.
+ VERIFY_IS_APPROX(m.adjoint()*m*x,m.adjoint()*rhs);
+ }
+
+ // check minimal norm solutions
+ {
+ // generate a full-rank m x n problem with m<n
+ enum {
+ RankAtCompileTime2 = ColsAtCompileTime==Dynamic ? Dynamic : (ColsAtCompileTime)/2+1,
+ RowsAtCompileTime3 = ColsAtCompileTime==Dynamic ? Dynamic : ColsAtCompileTime+1
+ };
+ typedef Matrix<Scalar, RankAtCompileTime2, ColsAtCompileTime> MatrixType2;
+ typedef Matrix<Scalar, RankAtCompileTime2, 1> RhsType2;
+ typedef Matrix<Scalar, ColsAtCompileTime, RankAtCompileTime2> MatrixType2T;
+ Index rank = RankAtCompileTime2==Dynamic ? internal::random<Index>(1,cols) : Index(RankAtCompileTime2);
+ MatrixType2 m2(rank,cols);
+ int guard = 0;
+ do {
+ m2.setRandom();
+ } while(m2.jacobiSvd().setThreshold(test_precision<Scalar>()).rank()!=rank && (++guard)<10);
+ VERIFY(guard<10);
+ RhsType2 rhs2 = RhsType2::Random(rank);
+ // use QR to find a reference minimal norm solution
+ HouseholderQR<MatrixType2T> qr(m2.adjoint());
+ Matrix<Scalar,Dynamic,1> tmp = qr.matrixQR().topLeftCorner(rank,rank).template triangularView<Upper>().adjoint().solve(rhs2);
+ tmp.conservativeResize(cols);
+ tmp.tail(cols-rank).setZero();
+ SolutionType x21 = qr.householderQ() * tmp;
+ // now check with SVD
+ JacobiSVD<MatrixType2, ColPivHouseholderQRPreconditioner> svd2(m2, computationOptions);
+ SolutionType x22 = svd2.solve(rhs2);
+ VERIFY_IS_APPROX(m2*x21, rhs2);
+ VERIFY_IS_APPROX(m2*x22, rhs2);
+ VERIFY_IS_APPROX(x21, x22);
+
+ // Now check with a rank deficient matrix
+ typedef Matrix<Scalar, RowsAtCompileTime3, ColsAtCompileTime> MatrixType3;
+ typedef Matrix<Scalar, RowsAtCompileTime3, 1> RhsType3;
+ Index rows3 = RowsAtCompileTime3==Dynamic ? internal::random<Index>(rank+1,2*cols) : Index(RowsAtCompileTime3);
+ Matrix<Scalar,RowsAtCompileTime3,Dynamic> C = Matrix<Scalar,RowsAtCompileTime3,Dynamic>::Random(rows3,rank);
+ MatrixType3 m3 = C * m2;
+ RhsType3 rhs3 = C * rhs2;
+ JacobiSVD<MatrixType3, ColPivHouseholderQRPreconditioner> svd3(m3, computationOptions);
+ SolutionType x3 = svd3.solve(rhs3);
+ if(svd3.rank()!=rank) {
+ std::cout << m3 << "\n\n";
+ std::cout << svd3.singularValues().transpose() << "\n";
+ std::cout << svd3.rank() << " == " << rank << "\n";
+ std::cout << x21.norm() << " == " << x3.norm() << "\n";
+ }
+// VERIFY_IS_APPROX(m3*x3, rhs3);
+ VERIFY_IS_APPROX(m3*x21, rhs3);
+ VERIFY_IS_APPROX(m2*x3, rhs2);
+
+ VERIFY_IS_APPROX(x21, x3);
+ }
}
template<typename MatrixType, int QRPreconditioner>
@@ -95,27 +174,30 @@ void jacobisvd_test_all_computation_options(const MatrixType& m)
if (QRPreconditioner == NoQRPreconditioner && m.rows() != m.cols())
return;
JacobiSVD<MatrixType, QRPreconditioner> fullSvd(m, ComputeFullU|ComputeFullV);
-
- jacobisvd_check_full(m, fullSvd);
- jacobisvd_solve<MatrixType, QRPreconditioner>(m, ComputeFullU | ComputeFullV);
-
+ CALL_SUBTEST(( jacobisvd_check_full(m, fullSvd) ));
+ CALL_SUBTEST(( jacobisvd_solve<MatrixType, QRPreconditioner>(m, ComputeFullU | ComputeFullV) ));
+
+ #if defined __INTEL_COMPILER
+ // remark #111: statement is unreachable
+ #pragma warning disable 111
+ #endif
if(QRPreconditioner == FullPivHouseholderQRPreconditioner)
return;
- jacobisvd_compare_to_full(m, ComputeFullU, fullSvd);
- jacobisvd_compare_to_full(m, ComputeFullV, fullSvd);
- jacobisvd_compare_to_full(m, 0, fullSvd);
+ CALL_SUBTEST(( jacobisvd_compare_to_full(m, ComputeFullU, fullSvd) ));
+ CALL_SUBTEST(( jacobisvd_compare_to_full(m, ComputeFullV, fullSvd) ));
+ CALL_SUBTEST(( jacobisvd_compare_to_full(m, 0, fullSvd) ));
if (MatrixType::ColsAtCompileTime == Dynamic) {
// thin U/V are only available with dynamic number of columns
- jacobisvd_compare_to_full(m, ComputeFullU|ComputeThinV, fullSvd);
- jacobisvd_compare_to_full(m, ComputeThinV, fullSvd);
- jacobisvd_compare_to_full(m, ComputeThinU|ComputeFullV, fullSvd);
- jacobisvd_compare_to_full(m, ComputeThinU , fullSvd);
- jacobisvd_compare_to_full(m, ComputeThinU|ComputeThinV, fullSvd);
- jacobisvd_solve<MatrixType, QRPreconditioner>(m, ComputeFullU | ComputeThinV);
- jacobisvd_solve<MatrixType, QRPreconditioner>(m, ComputeThinU | ComputeFullV);
- jacobisvd_solve<MatrixType, QRPreconditioner>(m, ComputeThinU | ComputeThinV);
+ CALL_SUBTEST(( jacobisvd_compare_to_full(m, ComputeFullU|ComputeThinV, fullSvd) ));
+ CALL_SUBTEST(( jacobisvd_compare_to_full(m, ComputeThinV, fullSvd) ));
+ CALL_SUBTEST(( jacobisvd_compare_to_full(m, ComputeThinU|ComputeFullV, fullSvd) ));
+ CALL_SUBTEST(( jacobisvd_compare_to_full(m, ComputeThinU , fullSvd) ));
+ CALL_SUBTEST(( jacobisvd_compare_to_full(m, ComputeThinU|ComputeThinV, fullSvd) ));
+ CALL_SUBTEST(( jacobisvd_solve<MatrixType, QRPreconditioner>(m, ComputeFullU | ComputeThinV) ));
+ CALL_SUBTEST(( jacobisvd_solve<MatrixType, QRPreconditioner>(m, ComputeThinU | ComputeFullV) ));
+ CALL_SUBTEST(( jacobisvd_solve<MatrixType, QRPreconditioner>(m, ComputeThinU | ComputeThinV) ));
// test reconstruction
typedef typename MatrixType::Index Index;
@@ -128,12 +210,29 @@ void jacobisvd_test_all_computation_options(const MatrixType& m)
template<typename MatrixType>
void jacobisvd(const MatrixType& a = MatrixType(), bool pickrandom = true)
{
- MatrixType m = pickrandom ? MatrixType::Random(a.rows(), a.cols()) : a;
+ MatrixType m = a;
+ if(pickrandom)
+ {
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::RealScalar RealScalar;
+ typedef typename MatrixType::Index Index;
+ Index diagSize = (std::min)(a.rows(), a.cols());
+ RealScalar s = std::numeric_limits<RealScalar>::max_exponent10/4;
+ s = internal::random<RealScalar>(1,s);
+ Matrix<RealScalar,Dynamic,1> d = Matrix<RealScalar,Dynamic,1>::Random(diagSize);
+ for(Index k=0; k<diagSize; ++k)
+ d(k) = d(k)*std::pow(RealScalar(10),internal::random<RealScalar>(-s,s));
+ m = Matrix<Scalar,Dynamic,Dynamic>::Random(a.rows(),diagSize) * d.asDiagonal() * Matrix<Scalar,Dynamic,Dynamic>::Random(diagSize,a.cols());
+ // cancel some coeffs
+ Index n = internal::random<Index>(0,m.size()-1);
+ for(Index i=0; i<n; ++i)
+ m(internal::random<Index>(0,m.rows()-1), internal::random<Index>(0,m.cols()-1)) = Scalar(0);
+ }
- jacobisvd_test_all_computation_options<MatrixType, FullPivHouseholderQRPreconditioner>(m);
- jacobisvd_test_all_computation_options<MatrixType, ColPivHouseholderQRPreconditioner>(m);
- jacobisvd_test_all_computation_options<MatrixType, HouseholderQRPreconditioner>(m);
- jacobisvd_test_all_computation_options<MatrixType, NoQRPreconditioner>(m);
+ CALL_SUBTEST(( jacobisvd_test_all_computation_options<MatrixType, FullPivHouseholderQRPreconditioner>(m) ));
+ CALL_SUBTEST(( jacobisvd_test_all_computation_options<MatrixType, ColPivHouseholderQRPreconditioner>(m) ));
+ CALL_SUBTEST(( jacobisvd_test_all_computation_options<MatrixType, HouseholderQRPreconditioner>(m) ));
+ CALL_SUBTEST(( jacobisvd_test_all_computation_options<MatrixType, NoQRPreconditioner>(m) ));
}
template<typename MatrixType> void jacobisvd_verify_assert(const MatrixType& m)
@@ -260,7 +359,7 @@ void jacobisvd_preallocate()
MatrixXf m = v.asDiagonal();
internal::set_is_malloc_allowed(false);
- VERIFY_RAISES_ASSERT(VectorXf v(10);)
+ VERIFY_RAISES_ASSERT(VectorXf tmp(10);)
JacobiSVD<MatrixXf> svd;
internal::set_is_malloc_allowed(true);
svd.compute(m);
@@ -323,6 +422,11 @@ void test_jacobisvd()
int r = internal::random<int>(1, 30),
c = internal::random<int>(1, 30);
+
+ TEST_SET_BUT_UNUSED_VARIABLE(r)
+ TEST_SET_BUT_UNUSED_VARIABLE(c)
+
+ CALL_SUBTEST_10(( jacobisvd<MatrixXd>(MatrixXd(r,c)) ));
CALL_SUBTEST_7(( jacobisvd<MatrixXf>(MatrixXf(r,c)) ));
CALL_SUBTEST_8(( jacobisvd<MatrixXcd>(MatrixXcd(r,c)) ));
(void) r;
diff --git a/test/linearstructure.cpp b/test/linearstructure.cpp
index fd071c995..618984d5c 100644
--- a/test/linearstructure.cpp
+++ b/test/linearstructure.cpp
@@ -11,6 +11,7 @@
template<typename MatrixType> void linearStructure(const MatrixType& m)
{
+ using std::abs;
/* this test covers the following files:
CwiseUnaryOp.h, CwiseBinaryOp.h, SelfCwiseBinaryOp.h
*/
@@ -27,7 +28,7 @@ template<typename MatrixType> void linearStructure(const MatrixType& m)
m3(rows, cols);
Scalar s1 = internal::random<Scalar>();
- while (internal::abs(s1)<1e-3) s1 = internal::random<Scalar>();
+ while (abs(s1)<1e-3) s1 = internal::random<Scalar>();
Index r = internal::random<Index>(0, rows-1),
c = internal::random<Index>(0, cols-1);
diff --git a/test/lu.cpp b/test/lu.cpp
index 6cbcb0a95..25f86755a 100644
--- a/test/lu.cpp
+++ b/test/lu.cpp
@@ -14,7 +14,6 @@ using namespace std;
template<typename MatrixType> void lu_non_invertible()
{
typedef typename MatrixType::Index Index;
- typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
/* this test covers the following files:
LU.h
@@ -100,7 +99,6 @@ template<typename MatrixType> void lu_invertible()
/* this test covers the following files:
LU.h
*/
- typedef typename MatrixType::Scalar Scalar;
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
int size = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
@@ -132,8 +130,6 @@ template<typename MatrixType> void lu_partial_piv()
PartialPivLU.h
*/
typedef typename MatrixType::Index Index;
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
Index rows = internal::random<Index>(1,4);
Index cols = rows;
diff --git a/test/main.h b/test/main.h
index 2da327c17..14f0d2f78 100644
--- a/test/main.h
+++ b/test/main.h
@@ -14,6 +14,7 @@
#include <iostream>
#include <fstream>
#include <string>
+#include <sstream>
#include <vector>
#include <typeinfo>
#include <limits>
@@ -30,6 +31,10 @@
// B0 is defined in POSIX header termios.h
#define B0 FORBIDDEN_IDENTIFIER
+
+// shuts down ICC's remark #593: variable "XXX" was set but never used
+#define TEST_SET_BUT_UNUSED_VARIABLE(X) X = X + 0;
+
// the following file is automatically generated by cmake
#include "split_test_helper.h"
@@ -37,6 +42,11 @@
#undef NDEBUG
#endif
+// On windows CE, NDEBUG is automatically defined <assert.h> if NDEBUG is not defined.
+#ifndef DEBUG
+#define DEBUG
+#endif
+
// bounds integer values for AltiVec
#ifdef __ALTIVEC__
#define EIGEN_MAKING_DOCS
@@ -48,11 +58,6 @@
#define DEFAULT_REPEAT 10
-#ifdef __ICC
-// disable warning #279: controlling expression is constant
-#pragma warning disable 279
-#endif
-
namespace Eigen
{
static std::vector<std::string> g_test_stack;
@@ -169,12 +174,17 @@ namespace Eigen
#define EIGEN_INTERNAL_DEBUGGING
#include <Eigen/QR> // required for createRandomPIMatrixOfRank
-static void verify_impl(bool condition, const char *testname, const char *file, int line, const char *condition_as_string)
+inline void verify_impl(bool condition, const char *testname, const char *file, int line, const char *condition_as_string)
{
if (!condition)
{
- std::cerr << "Test " << testname << " failed in " << file << " (" << line << ")" \
- << std::endl << " " << condition_as_string << std::endl << std::endl; \
+ std::cerr << "Test " << testname << " failed in " << file << " (" << line << ")"
+ << std::endl << " " << condition_as_string << std::endl;
+ std::cerr << "Stack:\n";
+ const int test_stack_size = static_cast<int>(Eigen::g_test_stack.size());
+ for(int i=test_stack_size-1; i>=0; --i)
+ std::cerr << " - " << Eigen::g_test_stack[i] << "\n";
+ std::cerr << "\n";
abort();
}
}
@@ -260,6 +270,7 @@ inline bool test_isApprox(const Type1& a, const Type2& b)
// The idea behind this function is to compare the two scalars a and b where
// the scalar ref is a hint about the expected order of magnitude of a and b.
+// WARNING: the scalar a and b must be positive
// Therefore, if for some reason a and b are very small compared to ref,
// we won't issue a false negative.
// This test could be: abs(a-b) <= eps * ref
@@ -290,6 +301,10 @@ inline bool test_isUnitary(const MatrixBase<Derived>& m)
return m.isUnitary(test_precision<typename internal::traits<Derived>::Scalar>());
}
+// Forward declaration to avoid ICC warning
+template<typename T, typename U>
+bool test_is_equal(const T& actual, const U& expected);
+
template<typename T, typename U>
bool test_is_equal(const T& actual, const U& expected)
{
@@ -307,6 +322,9 @@ bool test_is_equal(const T& actual, const U& expected)
* A partial isometry is a matrix all of whose singular values are either 0 or 1.
* This is very useful to test rank-revealing algorithms.
*/
+// Forward declaration to avoid ICC warning
+template<typename MatrixType>
+void createRandomPIMatrixOfRank(typename MatrixType::Index desired_rank, typename MatrixType::Index rows, typename MatrixType::Index cols, MatrixType& m);
template<typename MatrixType>
void createRandomPIMatrixOfRank(typename MatrixType::Index desired_rank, typename MatrixType::Index rows, typename MatrixType::Index cols, MatrixType& m)
{
@@ -345,6 +363,9 @@ void createRandomPIMatrixOfRank(typename MatrixType::Index desired_rank, typenam
m = qra.householderQ() * d * qrb.householderQ();
}
+// Forward declaration to avoid ICC warning
+template<typename PermutationVectorType>
+void randomPermutationVector(PermutationVectorType& v, typename PermutationVectorType::Index size);
template<typename PermutationVectorType>
void randomPermutationVector(PermutationVectorType& v, typename PermutationVectorType::Index size)
{
@@ -371,20 +392,22 @@ template<> struct GetDifferentType<double> { typedef float type; };
template<typename T> struct GetDifferentType<std::complex<T> >
{ typedef std::complex<typename GetDifferentType<T>::type> type; };
-template<typename T> std::string type_name() { return "other"; }
-template<> std::string type_name<float>() { return "float"; }
-template<> std::string type_name<double>() { return "double"; }
-template<> std::string type_name<int>() { return "int"; }
-template<> std::string type_name<std::complex<float> >() { return "complex<float>"; }
+// Forward declaration to avoid ICC warning
+template<typename T> std::string type_name();
+template<typename T> std::string type_name() { return "other"; }
+template<> std::string type_name<float>() { return "float"; }
+template<> std::string type_name<double>() { return "double"; }
+template<> std::string type_name<int>() { return "int"; }
+template<> std::string type_name<std::complex<float> >() { return "complex<float>"; }
template<> std::string type_name<std::complex<double> >() { return "complex<double>"; }
-template<> std::string type_name<std::complex<int> >() { return "complex<int>"; }
+template<> std::string type_name<std::complex<int> >() { return "complex<int>"; }
// forward declaration of the main test function
void EIGEN_CAT(test_,EIGEN_TEST_FUNC)();
using namespace Eigen;
-void set_repeat_from_string(const char *str)
+inline void set_repeat_from_string(const char *str)
{
errno = 0;
g_repeat = int(strtoul(str, 0, 10));
@@ -396,10 +419,10 @@ void set_repeat_from_string(const char *str)
g_has_set_repeat = true;
}
-void set_seed_from_string(const char *str)
+inline void set_seed_from_string(const char *str)
{
errno = 0;
- g_seed = strtoul(str, 0, 10);
+ g_seed = int(strtoul(str, 0, 10));
if(errno || g_seed == 0)
{
std::cout << "Invalid seed value " << str << std::endl;
@@ -462,11 +485,25 @@ int main(int argc, char *argv[])
if(!g_has_set_repeat) g_repeat = DEFAULT_REPEAT;
std::cout << "Initializing random number generator with seed " << g_seed << std::endl;
+ std::stringstream ss;
+ ss << "Seed: " << g_seed;
+ g_test_stack.push_back(ss.str());
srand(g_seed);
std::cout << "Repeating each test " << g_repeat << " times" << std::endl;
- Eigen::g_test_stack.push_back(EI_PP_MAKE_STRING(EIGEN_TEST_FUNC));
+ Eigen::g_test_stack.push_back(std::string(EI_PP_MAKE_STRING(EIGEN_TEST_FUNC)));
EIGEN_CAT(test_,EIGEN_TEST_FUNC)();
return 0;
}
+
+// These warning are disabled here such that they are still ON when parsing Eigen's header files.
+#if defined __INTEL_COMPILER
+ // remark #383: value copied to temporary, reference to temporary used
+ // -> this warning is raised even for legal usage as: g_test_stack.push_back("foo"); where g_test_stack is a std::vector<std::string>
+ // remark #1418: external function definition with no prior declaration
+ // -> this warning is raised for all our test functions. Declaring them static would fix the issue.
+ // warning #279: controlling expression is constant
+ // remark #1572: floating-point equality and inequality comparisons are unreliable
+ #pragma warning disable 279 383 1418 1572
+#endif
diff --git a/test/map.cpp b/test/mapped_matrix.cpp
index fe983e802..de9dbbde3 100644
--- a/test/map.cpp
+++ b/test/mapped_matrix.cpp
@@ -102,9 +102,6 @@ template<typename VectorType> void map_static_methods(const VectorType& m)
template<typename PlainObjectType> void check_const_correctness(const PlainObjectType&)
{
- typedef typename PlainObjectType::Index Index;
- typedef typename PlainObjectType::Scalar Scalar;
-
// there's a lot that we can't test here while still having this test compile!
// the only possible approach would be to run a script trying to compile stuff and checking that it fails.
// CMake can help with that.
@@ -117,7 +114,7 @@ template<typename PlainObjectType> void check_const_correctness(const PlainObjec
VERIFY( !(Map<ConstPlainObjectType, Aligned>::Flags & LvalueBit) );
}
-void test_map()
+void test_mapped_matrix()
{
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST_1( map_class_vector(Matrix<float, 1, 1>()) );
diff --git a/test/mapstride.cpp b/test/mapstride.cpp
index fe35b9d23..b1dc9de2a 100644
--- a/test/mapstride.cpp
+++ b/test/mapstride.cpp
@@ -116,7 +116,7 @@ template<int Alignment,typename MatrixType> void map_class_matrix(const MatrixTy
void test_mapstride()
{
for(int i = 0; i < g_repeat; i++) {
- EIGEN_UNUSED int maxn = 30;
+ int maxn = 30;
CALL_SUBTEST_1( map_class_vector<Aligned>(Matrix<float, 1, 1>()) );
CALL_SUBTEST_1( map_class_vector<Unaligned>(Matrix<float, 1, 1>()) );
CALL_SUBTEST_2( map_class_vector<Aligned>(Vector4d()) );
@@ -142,5 +142,7 @@ void test_mapstride()
CALL_SUBTEST_5( map_class_matrix<Unaligned>(MatrixXi(internal::random<int>(1,maxn),internal::random<int>(1,maxn))) );
CALL_SUBTEST_6( map_class_matrix<Aligned>(MatrixXcd(internal::random<int>(1,maxn),internal::random<int>(1,maxn))) );
CALL_SUBTEST_6( map_class_matrix<Unaligned>(MatrixXcd(internal::random<int>(1,maxn),internal::random<int>(1,maxn))) );
+
+ TEST_SET_BUT_UNUSED_VARIABLE(maxn);
}
}
diff --git a/test/meta.cpp b/test/meta.cpp
index dc1d128d5..3302c5887 100644
--- a/test/meta.cpp
+++ b/test/meta.cpp
@@ -11,9 +11,6 @@
void test_meta()
{
- typedef float & FloatRef;
- typedef const float & ConstFloatRef;
-
VERIFY((internal::conditional<(3<4),internal::true_type, internal::false_type>::type::value));
VERIFY(( internal::is_same<float,float>::value));
VERIFY((!internal::is_same<float,double>::value));
@@ -56,7 +53,7 @@ void test_meta()
VERIFY(( internal::is_same<float,internal::remove_pointer<float* const >::type >::value));
VERIFY(internal::meta_sqrt<1>::ret == 1);
- #define VERIFY_META_SQRT(X) VERIFY(internal::meta_sqrt<X>::ret == int(internal::sqrt(double(X))))
+ #define VERIFY_META_SQRT(X) VERIFY(internal::meta_sqrt<X>::ret == int(std::sqrt(double(X))))
VERIFY_META_SQRT(2);
VERIFY_META_SQRT(3);
VERIFY_META_SQRT(4);
diff --git a/test/metis_support.cpp b/test/metis_support.cpp
new file mode 100644
index 000000000..932b04074
--- /dev/null
+++ b/test/metis_support.cpp
@@ -0,0 +1,39 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// Eigen is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 3 of the License, or (at your option) any later version.
+//
+// Alternatively, you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+#include "sparse_solver.h"
+#include <Eigen/SparseLU>
+#include <Eigen/MetisSupport>
+#include <unsupported/Eigen/SparseExtra>
+
+template<typename T> void test_metis_T()
+{
+ SparseLU<SparseMatrix<T, ColMajor>, MetisOrdering<int> > sparselu_metis;
+
+ check_sparse_square_solving(sparselu_metis);
+}
+
+void test_metis_support()
+{
+ CALL_SUBTEST_1(test_metis_T<double>());
+}
diff --git a/test/miscmatrices.cpp b/test/miscmatrices.cpp
index af0481cfe..ef20dc749 100644
--- a/test/miscmatrices.cpp
+++ b/test/miscmatrices.cpp
@@ -17,7 +17,6 @@ template<typename MatrixType> void miscMatrices(const MatrixType& m)
typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
- typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType;
Index rows = m.rows();
Index cols = m.cols();
diff --git a/test/nesting_ops.cpp b/test/nesting_ops.cpp
index 938ebcb7a..1e8523283 100644
--- a/test/nesting_ops.cpp
+++ b/test/nesting_ops.cpp
@@ -12,17 +12,9 @@
template <typename MatrixType> void run_nesting_ops(const MatrixType& _m)
{
typename MatrixType::Nested m(_m);
- typedef typename MatrixType::Scalar Scalar;
-#ifdef NDEBUG
- const bool is_debug = false;
-#else
- const bool is_debug = true;
-#endif
-
- // Make really sure that we are in debug mode! We don't want any type of
- // inlining for these tests to pass.
- VERIFY(is_debug);
+ // Make really sure that we are in debug mode!
+ VERIFY_RAISES_ASSERT(eigen_assert(false));
// The only intention of these tests is to ensure that this code does
// not trigger any asserts or segmentation faults... more to come.
diff --git a/test/nomalloc.cpp b/test/nomalloc.cpp
index d4ffcefcb..cbd02dd21 100644
--- a/test/nomalloc.cpp
+++ b/test/nomalloc.cpp
@@ -12,6 +12,12 @@
#ifdef __GNUC__
#define throw(X)
#endif
+
+#ifdef __INTEL_COMPILER
+ // disable "warning #76: argument to macro is empty" produced by the above hack
+ #pragma warning disable 76
+#endif
+
// discard stack allocation as that too bypasses malloc
#define EIGEN_STACK_ALLOCATION_LIMIT 0
// any heap allocation will raise an assert
@@ -30,7 +36,6 @@ template<typename MatrixType> void nomalloc(const MatrixType& m)
*/
typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
Index rows = m.rows();
Index cols = m.cols();
diff --git a/test/nullary.cpp b/test/nullary.cpp
index 1220e3f97..5408d88b2 100644
--- a/test/nullary.cpp
+++ b/test/nullary.cpp
@@ -91,6 +91,12 @@ void testVectorType(const VectorType& base)
scalar.setLinSpaced(1,low,high);
VERIFY_IS_APPROX( scalar, ScalarMatrix::Constant(high) );
VERIFY_IS_APPROX( ScalarMatrix::LinSpaced(1,low,high), ScalarMatrix::Constant(high) );
+
+ // regression test for bug 526 (linear vectorized transversal)
+ if (size > 1) {
+ m.tail(size-1).setLinSpaced(low, high);
+ VERIFY_IS_APPROX(m(size-1), high);
+ }
}
template<typename MatrixType>
diff --git a/test/packetmath.cpp b/test/packetmath.cpp
index c1464e994..2c0519c41 100644
--- a/test/packetmath.cpp
+++ b/test/packetmath.cpp
@@ -40,7 +40,7 @@ template<typename Scalar> bool areApprox(const Scalar* a, const Scalar* b, int s
{
for (int i=0; i<size; ++i)
{
- if (!internal::isApprox(a[i],b[i]))
+ if (a[i]!=b[i] && !internal::isApprox(a[i],b[i]))
{
std::cout << "[" << Map<const Matrix<Scalar,1,Dynamic> >(a,size) << "]" << " != " << Map<const Matrix<Scalar,1,Dynamic> >(b,size) << "\n";
return false;
@@ -99,6 +99,7 @@ struct packet_helper<false,Packet>
template<typename Scalar> void packetmath()
{
+ using std::abs;
typedef typename internal::packet_traits<Scalar>::type Packet;
const int PacketSize = internal::packet_traits<Scalar>::size;
typedef typename NumTraits<Scalar>::Real RealScalar;
@@ -113,7 +114,7 @@ template<typename Scalar> void packetmath()
{
data1[i] = internal::random<Scalar>()/RealScalar(PacketSize);
data2[i] = internal::random<Scalar>()/RealScalar(PacketSize);
- refvalue = (std::max)(refvalue,internal::abs(data1[i]));
+ refvalue = (std::max)(refvalue,abs(data1[i]));
}
internal::pstore(data2, internal::pload<Packet>(data1));
@@ -144,7 +145,6 @@ template<typename Scalar> void packetmath()
for (int i=0; i<PacketSize; ++i)
ref[i] = data1[i+offset];
- typedef Matrix<Scalar, PacketSize, 1> Vector;
VERIFY(areApprox(ref, data2, PacketSize) && "internal::palign");
}
@@ -156,7 +156,7 @@ template<typename Scalar> void packetmath()
CHECK_CWISE2(REF_DIV, internal::pdiv);
#endif
CHECK_CWISE1(internal::negate, internal::pnegate);
- CHECK_CWISE1(internal::conj, internal::pconj);
+ CHECK_CWISE1(numext::conj, internal::pconj);
for(int offset=0;offset<3;++offset)
{
@@ -207,6 +207,7 @@ template<typename Scalar> void packetmath()
template<typename Scalar> void packetmath_real()
{
+ using std::abs;
typedef typename internal::packet_traits<Scalar>::type Packet;
const int PacketSize = internal::packet_traits<Scalar>::size;
@@ -217,35 +218,50 @@ template<typename Scalar> void packetmath_real()
for (int i=0; i<size; ++i)
{
- data1[i] = internal::random<Scalar>(-1e3,1e3);
- data2[i] = internal::random<Scalar>(-1e3,1e3);
+ data1[i] = internal::random<Scalar>(-1,1) * std::pow(Scalar(10), internal::random<Scalar>(-3,3));
+ data2[i] = internal::random<Scalar>(-1,1) * std::pow(Scalar(10), internal::random<Scalar>(-3,3));
}
- CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasSin, internal::sin, internal::psin);
- CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasCos, internal::cos, internal::pcos);
- CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasTan, internal::tan, internal::ptan);
+ CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasSin, std::sin, internal::psin);
+ CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasCos, std::cos, internal::pcos);
+ CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasTan, std::tan, internal::ptan);
for (int i=0; i<size; ++i)
{
data1[i] = internal::random<Scalar>(-1,1);
data2[i] = internal::random<Scalar>(-1,1);
}
- CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasASin, internal::asin, internal::pasin);
- CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasACos, internal::acos, internal::pacos);
+ CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasASin, std::asin, internal::pasin);
+ CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasACos, std::acos, internal::pacos);
for (int i=0; i<size; ++i)
{
data1[i] = internal::random<Scalar>(-87,88);
data2[i] = internal::random<Scalar>(-87,88);
}
- CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasExp, internal::exp, internal::pexp);
+ CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasExp, std::exp, internal::pexp);
for (int i=0; i<size; ++i)
{
- data1[i] = internal::random<Scalar>(0,1e6);
- data2[i] = internal::random<Scalar>(0,1e6);
+ data1[i] = internal::random<Scalar>(0,1) * std::pow(Scalar(10), internal::random<Scalar>(-6,6));
+ data2[i] = internal::random<Scalar>(0,1) * std::pow(Scalar(10), internal::random<Scalar>(-6,6));
}
- CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasLog, internal::log, internal::plog);
- CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasSqrt, internal::sqrt, internal::psqrt);
+ if(internal::random<float>(0,1)<0.1)
+ data1[internal::random<int>(0, PacketSize)] = 0;
+ CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasLog, std::log, internal::plog);
+ CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasSqrt, std::sqrt, internal::psqrt);
+}
+
+template<typename Scalar> void packetmath_notcomplex()
+{
+ using std::abs;
+ typedef typename internal::packet_traits<Scalar>::type Packet;
+ const int PacketSize = internal::packet_traits<Scalar>::size;
+
+ EIGEN_ALIGN16 Scalar data1[internal::packet_traits<Scalar>::size*4];
+ EIGEN_ALIGN16 Scalar data2[internal::packet_traits<Scalar>::size*4];
+ EIGEN_ALIGN16 Scalar ref[internal::packet_traits<Scalar>::size*4];
+
+ Array<Scalar,Dynamic,1>::Map(data1, internal::packet_traits<Scalar>::size*4).setRandom();
ref[0] = data1[0];
for (int i=0; i<PacketSize; ++i)
@@ -254,7 +270,7 @@ template<typename Scalar> void packetmath_real()
CHECK_CWISE2((std::min), internal::pmin);
CHECK_CWISE2((std::max), internal::pmax);
- CHECK_CWISE1(internal::abs, internal::pabs);
+ CHECK_CWISE1(abs, internal::pabs);
ref[0] = data1[0];
for (int i=0; i<PacketSize; ++i)
@@ -336,6 +352,10 @@ void test_packetmath()
CALL_SUBTEST_1( packetmath<std::complex<float> >() );
CALL_SUBTEST_2( packetmath<std::complex<double> >() );
+ CALL_SUBTEST_1( packetmath_notcomplex<float>() );
+ CALL_SUBTEST_2( packetmath_notcomplex<double>() );
+ CALL_SUBTEST_3( packetmath_notcomplex<int>() );
+
CALL_SUBTEST_1( packetmath_real<float>() );
CALL_SUBTEST_2( packetmath_real<double>() );
diff --git a/test/pastix_support.cpp b/test/pastix_support.cpp
index 0e57227f9..14da0944b 100644
--- a/test/pastix_support.cpp
+++ b/test/pastix_support.cpp
@@ -41,4 +41,4 @@ void test_pastix_support()
CALL_SUBTEST_2(test_pastix_T<double>());
CALL_SUBTEST_3( (test_pastix_T_LU<std::complex<float> >()) );
CALL_SUBTEST_4(test_pastix_T_LU<std::complex<double> >());
-} \ No newline at end of file
+}
diff --git a/test/permutationmatrices.cpp b/test/permutationmatrices.cpp
index 00f666ccd..7b0dbc763 100644
--- a/test/permutationmatrices.cpp
+++ b/test/permutationmatrices.cpp
@@ -14,7 +14,6 @@ template<typename MatrixType> void permutationmatrices(const MatrixType& m)
{
typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::RealScalar RealScalar;
enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime,
Options = MatrixType::Options };
typedef PermutationMatrix<Rows> LeftPermutationType;
diff --git a/test/prec_inverse_4x4.cpp b/test/prec_inverse_4x4.cpp
index f7d0aff70..c4ef2d4bd 100644
--- a/test/prec_inverse_4x4.cpp
+++ b/test/prec_inverse_4x4.cpp
@@ -14,7 +14,6 @@
template<typename MatrixType> void inverse_permutation_4x4()
{
typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::RealScalar RealScalar;
Vector4i indices(0,1,2,3);
for(int i = 0; i < 24; ++i)
{
@@ -29,6 +28,7 @@ template<typename MatrixType> void inverse_permutation_4x4()
template<typename MatrixType> void inverse_general_4x4(int repeat)
{
+ using std::abs;
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
double error_sum = 0., error_max = 0.;
@@ -38,7 +38,7 @@ template<typename MatrixType> void inverse_general_4x4(int repeat)
RealScalar absdet;
do {
m = MatrixType::Random();
- absdet = internal::abs(m.determinant());
+ absdet = abs(m.determinant());
} while(absdet < NumTraits<Scalar>::epsilon());
MatrixType inv = m.inverse();
double error = double( (m*inv-MatrixType::Identity()).norm() * absdet / NumTraits<Scalar>::epsilon() );
diff --git a/test/product.h b/test/product.h
index 4aa9fd56d..856b234ac 100644
--- a/test/product.h
+++ b/test/product.h
@@ -24,7 +24,6 @@ template<typename MatrixType> void product(const MatrixType& m)
*/
typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::NonInteger NonInteger;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> RowVectorType;
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> ColVectorType;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> RowSquareMatrixType;
diff --git a/test/product_extra.cpp b/test/product_extra.cpp
index 9a6bf0792..744a1ef7f 100644
--- a/test/product_extra.cpp
+++ b/test/product_extra.cpp
@@ -13,7 +13,6 @@ template<typename MatrixType> void product_extra(const MatrixType& m)
{
typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::NonInteger NonInteger;
typedef Matrix<Scalar, 1, Dynamic> RowVectorType;
typedef Matrix<Scalar, Dynamic, 1> ColVectorType;
typedef Matrix<Scalar, Dynamic, Dynamic,
@@ -43,7 +42,7 @@ template<typename MatrixType> void product_extra(const MatrixType& m)
VERIFY_IS_APPROX(m3.noalias() = m1.adjoint() * square.adjoint(), m1.adjoint().eval() * square.adjoint().eval());
VERIFY_IS_APPROX(m3.noalias() = m1.adjoint() * m2, m1.adjoint().eval() * m2);
VERIFY_IS_APPROX(m3.noalias() = (s1 * m1.adjoint()) * m2, (s1 * m1.adjoint()).eval() * m2);
- VERIFY_IS_APPROX(m3.noalias() = ((s1 * m1).adjoint()) * m2, (internal::conj(s1) * m1.adjoint()).eval() * m2);
+ VERIFY_IS_APPROX(m3.noalias() = ((s1 * m1).adjoint()) * m2, (numext::conj(s1) * m1.adjoint()).eval() * m2);
VERIFY_IS_APPROX(m3.noalias() = (- m1.adjoint() * s1) * (s3 * m2), (- m1.adjoint() * s1).eval() * (s3 * m2).eval());
VERIFY_IS_APPROX(m3.noalias() = (s2 * m1.adjoint() * s1) * m2, (s2 * m1.adjoint() * s1).eval() * m2);
VERIFY_IS_APPROX(m3.noalias() = (-m1*s2) * s1*m2.adjoint(), (-m1*s2).eval() * (s1*m2.adjoint()).eval());
@@ -135,6 +134,35 @@ void zero_sized_objects()
a*b;
}
+void unaligned_objects()
+{
+ // Regression test for the bug reported here:
+ // http://forum.kde.org/viewtopic.php?f=74&t=107541
+ // Recall the matrix*vector kernel avoid unaligned loads by loading two packets and then reassemble then.
+ // There was a mistake in the computation of the valid range for fully unaligned objects: in some rare cases,
+ // memory was read outside the allocated matrix memory. Though the values were not used, this might raise segfault.
+ for(int m=450;m<460;++m)
+ {
+ for(int n=8;n<12;++n)
+ {
+ MatrixXf M(m, n);
+ VectorXf v1(n), r1(500);
+ RowVectorXf v2(m), r2(16);
+
+ M.setRandom();
+ v1.setRandom();
+ v2.setRandom();
+ for(int o=0; o<4; ++o)
+ {
+ r1.segment(o,m).noalias() = M * v1;
+ VERIFY_IS_APPROX(r1.segment(o,m), M * MatrixXf(v1));
+ r2.segment(o,n).noalias() = v2 * M;
+ VERIFY_IS_APPROX(r2.segment(o,n), MatrixXf(v2) * M);
+ }
+ }
+ }
+}
+
void test_product_extra()
{
for(int i = 0; i < g_repeat; i++) {
@@ -143,6 +171,7 @@ void test_product_extra()
CALL_SUBTEST_2( mat_mat_scalar_scalar_product() );
CALL_SUBTEST_3( product_extra(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2), internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
CALL_SUBTEST_4( product_extra(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2), internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
- CALL_SUBTEST_5( zero_sized_objects() );
}
+ CALL_SUBTEST_5( zero_sized_objects() );
+ CALL_SUBTEST_6( unaligned_objects() );
}
diff --git a/test/product_mmtr.cpp b/test/product_mmtr.cpp
index 879cfe16a..7d6746800 100644
--- a/test/product_mmtr.cpp
+++ b/test/product_mmtr.cpp
@@ -19,8 +19,6 @@
template<typename Scalar> void mmtr(int size)
{
- typedef typename NumTraits<Scalar>::Real RealScalar;
-
typedef Matrix<Scalar,Dynamic,Dynamic,ColMajor> MatrixColMaj;
typedef Matrix<Scalar,Dynamic,Dynamic,RowMajor> MatrixRowMaj;
diff --git a/test/product_notemporary.cpp b/test/product_notemporary.cpp
index cf9dbdd03..258d238e2 100644
--- a/test/product_notemporary.cpp
+++ b/test/product_notemporary.cpp
@@ -9,7 +9,7 @@
static int nb_temporaries;
-void on_temporary_creation(int size) {
+inline void on_temporary_creation(int size) {
// here's a great place to set a breakpoint when debugging failures in this test!
if(size!=0) nb_temporaries++;
}
@@ -77,6 +77,9 @@ template<typename MatrixType> void product_notemporary(const MatrixType& m)
VERIFY_EVALUATION_COUNT( m3.noalias() -= (s1 * m1).template triangularView<Lower>() * m2, 0);
VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template triangularView<Upper>() * (m2+m2), 1);
VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template triangularView<UnitUpper>() * m2.adjoint(), 0);
+
+ VERIFY_EVALUATION_COUNT( m3.template triangularView<Upper>() = (m1 * m2.adjoint()), 0);
+ VERIFY_EVALUATION_COUNT( m3.template triangularView<Upper>() -= (m1 * m2.adjoint()), 0);
// NOTE this is because the blas_traits require innerstride==1 to avoid a temporary, but that doesn't seem to be actually needed for the triangular products
VERIFY_EVALUATION_COUNT( rm3.col(c0).noalias() = (s1 * m1.adjoint()).template triangularView<UnitUpper>() * (s2*m2.row(c0)).adjoint(), 1);
diff --git a/test/product_selfadjoint.cpp b/test/product_selfadjoint.cpp
index 95693b155..374e2393b 100644
--- a/test/product_selfadjoint.cpp
+++ b/test/product_selfadjoint.cpp
@@ -13,7 +13,6 @@ template<typename MatrixType> void product_selfadjoint(const MatrixType& m)
{
typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
typedef Matrix<Scalar, 1, MatrixType::RowsAtCompileTime> RowVectorType;
@@ -45,11 +44,11 @@ template<typename MatrixType> void product_selfadjoint(const MatrixType& m)
m2 = m1.template triangularView<Upper>();
m2.template selfadjointView<Upper>().rankUpdate(-v1,s2*v2,s3);
- VERIFY_IS_APPROX(m2, (m1 + (s3*(-v1)*(s2*v2).adjoint()+internal::conj(s3)*(s2*v2)*(-v1).adjoint())).template triangularView<Upper>().toDenseMatrix());
+ VERIFY_IS_APPROX(m2, (m1 + (s3*(-v1)*(s2*v2).adjoint()+numext::conj(s3)*(s2*v2)*(-v1).adjoint())).template triangularView<Upper>().toDenseMatrix());
m2 = m1.template triangularView<Upper>();
m2.template selfadjointView<Upper>().rankUpdate(-s2*r1.adjoint(),r2.adjoint()*s3,s1);
- VERIFY_IS_APPROX(m2, (m1 + s1*(-s2*r1.adjoint())*(r2.adjoint()*s3).adjoint() + internal::conj(s1)*(r2.adjoint()*s3) * (-s2*r1.adjoint()).adjoint()).template triangularView<Upper>().toDenseMatrix());
+ VERIFY_IS_APPROX(m2, (m1 + s1*(-s2*r1.adjoint())*(r2.adjoint()*s3).adjoint() + numext::conj(s1)*(r2.adjoint()*s3) * (-s2*r1.adjoint()).adjoint()).template triangularView<Upper>().toDenseMatrix());
if (rows>1)
{
@@ -63,7 +62,7 @@ template<typename MatrixType> void product_selfadjoint(const MatrixType& m)
void test_product_selfadjoint()
{
- int s;
+ int s = 0;
for(int i = 0; i < g_repeat ; i++) {
CALL_SUBTEST_1( product_selfadjoint(Matrix<float, 1, 1>()) );
CALL_SUBTEST_2( product_selfadjoint(Matrix<float, 2, 2>()) );
@@ -77,5 +76,5 @@ void test_product_selfadjoint()
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
CALL_SUBTEST_7( product_selfadjoint(Matrix<float,Dynamic,Dynamic,RowMajor>(s,s)) );
}
- EIGEN_UNUSED_VARIABLE(s)
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
}
diff --git a/test/product_symm.cpp b/test/product_symm.cpp
index 2f7a0d231..74d7329b1 100644
--- a/test/product_symm.cpp
+++ b/test/product_symm.cpp
@@ -11,8 +11,6 @@
template<typename Scalar, int Size, int OtherSize> void symm(int size = Size, int othersize = OtherSize)
{
- typedef typename NumTraits<Scalar>::Real RealScalar;
-
typedef Matrix<Scalar, Size, Size> MatrixType;
typedef Matrix<Scalar, Size, OtherSize> Rhs1;
typedef Matrix<Scalar, OtherSize, Size> Rhs2;
diff --git a/test/product_syrk.cpp b/test/product_syrk.cpp
index 5855c2181..73c95000c 100644
--- a/test/product_syrk.cpp
+++ b/test/product_syrk.cpp
@@ -13,7 +13,7 @@ template<typename MatrixType> void syrk(const MatrixType& m)
{
typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
+ typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime, RowMajor> RMatrixType;
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, Dynamic> Rhs1;
typedef Matrix<Scalar, Dynamic, MatrixType::RowsAtCompileTime> Rhs2;
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, Dynamic,RowMajor> Rhs3;
@@ -22,10 +22,12 @@ template<typename MatrixType> void syrk(const MatrixType& m)
Index cols = m.cols();
MatrixType m1 = MatrixType::Random(rows, cols),
- m2 = MatrixType::Random(rows, cols);
+ m2 = MatrixType::Random(rows, cols),
+ m3 = MatrixType::Random(rows, cols);
+ RMatrixType rm2 = MatrixType::Random(rows, cols);
- Rhs1 rhs1 = Rhs1::Random(internal::random<int>(1,320), cols);
- Rhs2 rhs2 = Rhs2::Random(rows, internal::random<int>(1,320));
+ Rhs1 rhs1 = Rhs1::Random(internal::random<int>(1,320), cols); Rhs1 rhs11 = Rhs1::Random(rhs1.rows(), cols);
+ Rhs2 rhs2 = Rhs2::Random(rows, internal::random<int>(1,320)); Rhs2 rhs22 = Rhs2::Random(rows, rhs2.cols());
Rhs3 rhs3 = Rhs3::Random(internal::random<int>(1,320), rows);
Scalar s1 = internal::random<Scalar>();
@@ -35,19 +37,34 @@ template<typename MatrixType> void syrk(const MatrixType& m)
m2.setZero();
VERIFY_IS_APPROX((m2.template selfadjointView<Lower>().rankUpdate(rhs2,s1)._expression()),
((s1 * rhs2 * rhs2.adjoint()).eval().template triangularView<Lower>().toDenseMatrix()));
+ m2.setZero();
+ VERIFY_IS_APPROX(((m2.template triangularView<Lower>() += s1 * rhs2 * rhs22.adjoint()).nestedExpression()),
+ ((s1 * rhs2 * rhs22.adjoint()).eval().template triangularView<Lower>().toDenseMatrix()));
+
m2.setZero();
VERIFY_IS_APPROX(m2.template selfadjointView<Upper>().rankUpdate(rhs2,s1)._expression(),
(s1 * rhs2 * rhs2.adjoint()).eval().template triangularView<Upper>().toDenseMatrix());
+ m2.setZero();
+ VERIFY_IS_APPROX((m2.template triangularView<Upper>() += s1 * rhs22 * rhs2.adjoint()).nestedExpression(),
+ (s1 * rhs22 * rhs2.adjoint()).eval().template triangularView<Upper>().toDenseMatrix());
+
m2.setZero();
VERIFY_IS_APPROX(m2.template selfadjointView<Lower>().rankUpdate(rhs1.adjoint(),s1)._expression(),
(s1 * rhs1.adjoint() * rhs1).eval().template triangularView<Lower>().toDenseMatrix());
-
+ m2.setZero();
+ VERIFY_IS_APPROX((m2.template triangularView<Lower>() += s1 * rhs11.adjoint() * rhs1).nestedExpression(),
+ (s1 * rhs11.adjoint() * rhs1).eval().template triangularView<Lower>().toDenseMatrix());
+
+
m2.setZero();
VERIFY_IS_APPROX(m2.template selfadjointView<Upper>().rankUpdate(rhs1.adjoint(),s1)._expression(),
(s1 * rhs1.adjoint() * rhs1).eval().template triangularView<Upper>().toDenseMatrix());
+ VERIFY_IS_APPROX((m2.template triangularView<Upper>() = s1 * rhs1.adjoint() * rhs11).nestedExpression(),
+ (s1 * rhs1.adjoint() * rhs11).eval().template triangularView<Upper>().toDenseMatrix());
+
m2.setZero();
VERIFY_IS_APPROX(m2.template selfadjointView<Lower>().rankUpdate(rhs3.adjoint(),s1)._expression(),
(s1 * rhs3.adjoint() * rhs3).eval().template triangularView<Lower>().toDenseMatrix());
@@ -63,6 +80,15 @@ template<typename MatrixType> void syrk(const MatrixType& m)
m2.setZero();
VERIFY_IS_APPROX((m2.template selfadjointView<Upper>().rankUpdate(m1.col(c),s1)._expression()),
((s1 * m1.col(c) * m1.col(c).adjoint()).eval().template triangularView<Upper>().toDenseMatrix()));
+ rm2.setZero();
+ VERIFY_IS_APPROX((rm2.template selfadjointView<Upper>().rankUpdate(m1.col(c),s1)._expression()),
+ ((s1 * m1.col(c) * m1.col(c).adjoint()).eval().template triangularView<Upper>().toDenseMatrix()));
+ m2.setZero();
+ VERIFY_IS_APPROX((m2.template triangularView<Upper>() += s1 * m3.col(c) * m1.col(c).adjoint()).nestedExpression(),
+ ((s1 * m3.col(c) * m1.col(c).adjoint()).eval().template triangularView<Upper>().toDenseMatrix()));
+ rm2.setZero();
+ VERIFY_IS_APPROX((rm2.template triangularView<Upper>() += s1 * m1.col(c) * m3.col(c).adjoint()).nestedExpression(),
+ ((s1 * m1.col(c) * m3.col(c).adjoint()).eval().template triangularView<Upper>().toDenseMatrix()));
m2.setZero();
VERIFY_IS_APPROX((m2.template selfadjointView<Lower>().rankUpdate(m1.col(c).conjugate(),s1)._expression()),
@@ -72,9 +98,20 @@ template<typename MatrixType> void syrk(const MatrixType& m)
VERIFY_IS_APPROX((m2.template selfadjointView<Upper>().rankUpdate(m1.col(c).conjugate(),s1)._expression()),
((s1 * m1.col(c).conjugate() * m1.col(c).conjugate().adjoint()).eval().template triangularView<Upper>().toDenseMatrix()));
+
m2.setZero();
VERIFY_IS_APPROX((m2.template selfadjointView<Lower>().rankUpdate(m1.row(c),s1)._expression()),
((s1 * m1.row(c).transpose() * m1.row(c).transpose().adjoint()).eval().template triangularView<Lower>().toDenseMatrix()));
+ rm2.setZero();
+ VERIFY_IS_APPROX((rm2.template selfadjointView<Lower>().rankUpdate(m1.row(c),s1)._expression()),
+ ((s1 * m1.row(c).transpose() * m1.row(c).transpose().adjoint()).eval().template triangularView<Lower>().toDenseMatrix()));
+ m2.setZero();
+ VERIFY_IS_APPROX((m2.template triangularView<Lower>() += s1 * m3.row(c).transpose() * m1.row(c).transpose().adjoint()).nestedExpression(),
+ ((s1 * m3.row(c).transpose() * m1.row(c).transpose().adjoint()).eval().template triangularView<Lower>().toDenseMatrix()));
+ rm2.setZero();
+ VERIFY_IS_APPROX((rm2.template triangularView<Lower>() += s1 * m3.row(c).transpose() * m1.row(c).transpose().adjoint()).nestedExpression(),
+ ((s1 * m3.row(c).transpose() * m1.row(c).transpose().adjoint()).eval().template triangularView<Lower>().toDenseMatrix()));
+
m2.setZero();
VERIFY_IS_APPROX((m2.template selfadjointView<Upper>().rankUpdate(m1.row(c).adjoint(),s1)._expression()),
diff --git a/test/product_trmm.cpp b/test/product_trmm.cpp
index 64244c18f..d715b9a36 100644
--- a/test/product_trmm.cpp
+++ b/test/product_trmm.cpp
@@ -14,8 +14,6 @@ void trmm(int rows=internal::random<int>(1,EIGEN_TEST_MAX_SIZE),
int cols=internal::random<int>(1,EIGEN_TEST_MAX_SIZE),
int otherCols = OtherCols==Dynamic?internal::random<int>(1,EIGEN_TEST_MAX_SIZE):OtherCols)
{
- typedef typename NumTraits<Scalar>::Real RealScalar;
-
typedef Matrix<Scalar,Dynamic,Dynamic,TriOrder> TriMatrix;
typedef Matrix<Scalar,Dynamic,OtherCols,OtherCols==1?ColMajor:OtherOrder> OnTheRight;
typedef Matrix<Scalar,OtherCols,Dynamic,OtherCols==1?RowMajor:OtherOrder> OnTheLeft;
@@ -53,10 +51,11 @@ void trmm(int rows=internal::random<int>(1,EIGEN_TEST_MAX_SIZE),
ge_xs_save = ge_xs;
VERIFY_IS_APPROX( (ge_xs_save + s1*triTr.conjugate() * (s2*ge_left.adjoint())).eval(), ge_xs.noalias() += (s1*mat.adjoint()).template triangularView<Mode>() * (s2*ge_left.adjoint()) );
+ ge_sx.setRandom();
ge_sx_save = ge_sx;
VERIFY_IS_APPROX( ge_sx_save - (ge_right.adjoint() * (-s1 * triTr).conjugate()).eval(), ge_sx.noalias() -= (ge_right.adjoint() * (-s1 * mat).adjoint().template triangularView<Mode>()).eval());
- VERIFY_IS_APPROX( ge_xs = (s1*mat).adjoint().template triangularView<Mode>() * ge_left.adjoint(), internal::conj(s1) * triTr.conjugate() * ge_left.adjoint());
+ VERIFY_IS_APPROX( ge_xs = (s1*mat).adjoint().template triangularView<Mode>() * ge_left.adjoint(), numext::conj(s1) * triTr.conjugate() * ge_left.adjoint());
// TODO check with sub-matrix expressions ?
}
diff --git a/test/product_trmv.cpp b/test/product_trmv.cpp
index 435018e8e..4c3c435c2 100644
--- a/test/product_trmv.cpp
+++ b/test/product_trmv.cpp
@@ -73,7 +73,7 @@ template<typename MatrixType> void trmv(const MatrixType& m)
void test_product_trmv()
{
- int s;
+ int s = 0;
for(int i = 0; i < g_repeat ; i++) {
CALL_SUBTEST_1( trmv(Matrix<float, 1, 1>()) );
CALL_SUBTEST_2( trmv(Matrix<float, 2, 2>()) );
@@ -85,5 +85,5 @@ void test_product_trmv()
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
CALL_SUBTEST_6( trmv(Matrix<float,Dynamic,Dynamic,RowMajor>(s, s)) );
}
- EIGEN_UNUSED_VARIABLE(s);
+ TEST_SET_BUT_UNUSED_VARIABLE(s);
}
diff --git a/test/qr.cpp b/test/qr.cpp
index 37fb7aa4d..a79e0dd34 100644
--- a/test/qr.cpp
+++ b/test/qr.cpp
@@ -19,7 +19,6 @@ template<typename MatrixType> void qr(const MatrixType& m)
typedef typename MatrixType::Scalar Scalar;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> MatrixQType;
- typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
MatrixType a = MatrixType::Random(rows,cols);
HouseholderQR<MatrixType> qrOfA(a);
@@ -53,6 +52,8 @@ template<typename MatrixType, int Cols2> void qr_fixedsize()
template<typename MatrixType> void qr_invertible()
{
+ using std::log;
+ using std::abs;
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
typedef typename MatrixType::Scalar Scalar;
@@ -76,12 +77,12 @@ template<typename MatrixType> void qr_invertible()
// now construct a matrix with prescribed determinant
m1.setZero();
for(int i = 0; i < size; i++) m1(i,i) = internal::random<Scalar>();
- RealScalar absdet = internal::abs(m1.diagonal().prod());
+ RealScalar absdet = abs(m1.diagonal().prod());
m3 = qr.householderQ(); // get a unitary
m1 = m3 * m1 * m3;
qr.compute(m1);
VERIFY_IS_APPROX(absdet, qr.absDeterminant());
- VERIFY_IS_APPROX(internal::log(absdet), qr.logAbsDeterminant());
+ VERIFY_IS_APPROX(log(absdet), qr.logAbsDeterminant());
}
template<typename MatrixType> void qr_verify_assert()
diff --git a/test/qr_colpivoting.cpp b/test/qr_colpivoting.cpp
index dd0812819..eb3feac01 100644
--- a/test/qr_colpivoting.cpp
+++ b/test/qr_colpivoting.cpp
@@ -19,9 +19,7 @@ template<typename MatrixType> void qr()
Index rank = internal::random<Index>(1, (std::min)(rows, cols)-1);
typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::RealScalar RealScalar;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> MatrixQType;
- typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
MatrixType m1;
createRandomPIMatrixOfRank(rank,rows,cols,m1);
ColPivHouseholderQR<MatrixType> qr(m1);
@@ -72,6 +70,8 @@ template<typename MatrixType, int Cols2> void qr_fixedsize()
template<typename MatrixType> void qr_invertible()
{
+ using std::log;
+ using std::abs;
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
typedef typename MatrixType::Scalar Scalar;
@@ -95,12 +95,12 @@ template<typename MatrixType> void qr_invertible()
// now construct a matrix with prescribed determinant
m1.setZero();
for(int i = 0; i < size; i++) m1(i,i) = internal::random<Scalar>();
- RealScalar absdet = internal::abs(m1.diagonal().prod());
+ RealScalar absdet = abs(m1.diagonal().prod());
m3 = qr.householderQ(); // get a unitary
m1 = m3 * m1 * m3;
qr.compute(m1);
VERIFY_IS_APPROX(absdet, qr.absDeterminant());
- VERIFY_IS_APPROX(internal::log(absdet), qr.logAbsDeterminant());
+ VERIFY_IS_APPROX(log(absdet), qr.logAbsDeterminant());
}
template<typename MatrixType> void qr_verify_assert()
diff --git a/test/qr_fullpivoting.cpp b/test/qr_fullpivoting.cpp
index e5c9790c8..511f2473f 100644
--- a/test/qr_fullpivoting.cpp
+++ b/test/qr_fullpivoting.cpp
@@ -20,7 +20,6 @@ template<typename MatrixType> void qr()
typedef typename MatrixType::Scalar Scalar;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> MatrixQType;
- typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
MatrixType m1;
createRandomPIMatrixOfRank(rank,rows,cols,m1);
FullPivHouseholderQR<MatrixType> qr(m1);
@@ -51,6 +50,8 @@ template<typename MatrixType> void qr()
template<typename MatrixType> void qr_invertible()
{
+ using std::log;
+ using std::abs;
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
typedef typename MatrixType::Scalar Scalar;
@@ -78,12 +79,12 @@ template<typename MatrixType> void qr_invertible()
// now construct a matrix with prescribed determinant
m1.setZero();
for(int i = 0; i < size; i++) m1(i,i) = internal::random<Scalar>();
- RealScalar absdet = internal::abs(m1.diagonal().prod());
+ RealScalar absdet = abs(m1.diagonal().prod());
m3 = qr.matrixQ(); // get a unitary
m1 = m3 * m1 * m3;
qr.compute(m1);
VERIFY_IS_APPROX(absdet, qr.absDeterminant());
- VERIFY_IS_APPROX(internal::log(absdet), qr.logAbsDeterminant());
+ VERIFY_IS_APPROX(log(absdet), qr.logAbsDeterminant());
}
template<typename MatrixType> void qr_verify_assert()
@@ -129,4 +130,8 @@ void test_qr_fullpivoting()
// Test problem size constructors
CALL_SUBTEST_7(FullPivHouseholderQR<MatrixXf>(10, 20));
+ CALL_SUBTEST_7((FullPivHouseholderQR<Matrix<float,10,20> >(10,20)));
+ CALL_SUBTEST_7((FullPivHouseholderQR<Matrix<float,10,20> >(Matrix<float,10,20>::Random())));
+ CALL_SUBTEST_7((FullPivHouseholderQR<Matrix<float,20,10> >(20,10)));
+ CALL_SUBTEST_7((FullPivHouseholderQR<Matrix<float,20,10> >(Matrix<float,20,10>::Random())));
}
diff --git a/test/real_qz.cpp b/test/real_qz.cpp
new file mode 100644
index 000000000..7d743a734
--- /dev/null
+++ b/test/real_qz.cpp
@@ -0,0 +1,65 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Alexey Korepanov <kaikaikai@yandex.ru>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <limits>
+#include <Eigen/Eigenvalues>
+
+template<typename MatrixType> void real_qz(const MatrixType& m)
+{
+ /* this test covers the following files:
+ RealQZ.h
+ */
+ using std::abs;
+ typedef typename MatrixType::Index Index;
+ typedef typename MatrixType::Scalar Scalar;
+
+ Index dim = m.cols();
+
+ MatrixType A = MatrixType::Random(dim,dim),
+ B = MatrixType::Random(dim,dim);
+
+ RealQZ<MatrixType> qz(A,B);
+
+ VERIFY_IS_EQUAL(qz.info(), Success);
+ // check for zeros
+ bool all_zeros = true;
+ for (Index i=0; i<A.cols(); i++)
+ for (Index j=0; j<i; j++) {
+ if (abs(qz.matrixT()(i,j))!=Scalar(0.0))
+ all_zeros = false;
+ if (j<i-1 && abs(qz.matrixS()(i,j))!=Scalar(0.0))
+ all_zeros = false;
+ if (j==i-1 && j>0 && abs(qz.matrixS()(i,j))!=Scalar(0.0) && abs(qz.matrixS()(i-1,j-1))!=Scalar(0.0))
+ all_zeros = false;
+ }
+ VERIFY_IS_EQUAL(all_zeros, 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));
+}
+
+void test_real_qz()
+{
+ int s = 0;
+ for(int i = 0; i < g_repeat; i++) {
+ CALL_SUBTEST_1( real_qz(Matrix4f()) );
+ s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
+ CALL_SUBTEST_2( real_qz(MatrixXd(s,s)) );
+
+ // some trivial but implementation-wise tricky cases
+ CALL_SUBTEST_2( real_qz(MatrixXd(1,1)) );
+ CALL_SUBTEST_2( real_qz(MatrixXd(2,2)) );
+ CALL_SUBTEST_3( real_qz(Matrix<double,1,1>()) );
+ CALL_SUBTEST_4( real_qz(Matrix2d()) );
+ }
+
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
+}
diff --git a/test/redux.cpp b/test/redux.cpp
index e07d4b1e4..0d176e500 100644
--- a/test/redux.cpp
+++ b/test/redux.cpp
@@ -22,26 +22,26 @@ template<typename MatrixType> void matrixRedux(const MatrixType& m)
// The entries of m1 are uniformly distributed in [0,1], so m1.prod() is very small. This may lead to test
// failures if we underflow into denormals. Thus, we scale so that entires are close to 1.
- MatrixType m1_for_prod = MatrixType::Ones(rows, cols) + Scalar(0.2) * m1;
+ MatrixType m1_for_prod = MatrixType::Ones(rows, cols) + RealScalar(0.2) * m1;
VERIFY_IS_MUCH_SMALLER_THAN(MatrixType::Zero(rows, cols).sum(), Scalar(1));
VERIFY_IS_APPROX(MatrixType::Ones(rows, cols).sum(), Scalar(float(rows*cols))); // the float() here to shut up excessive MSVC warning about int->complex conversion being lossy
- Scalar s(0), p(1), minc(internal::real(m1.coeff(0))), maxc(internal::real(m1.coeff(0)));
+ Scalar s(0), p(1), minc(numext::real(m1.coeff(0))), maxc(numext::real(m1.coeff(0)));
for(int j = 0; j < cols; j++)
for(int i = 0; i < rows; i++)
{
s += m1(i,j);
p *= m1_for_prod(i,j);
- minc = (std::min)(internal::real(minc), internal::real(m1(i,j)));
- maxc = (std::max)(internal::real(maxc), internal::real(m1(i,j)));
+ minc = (std::min)(numext::real(minc), numext::real(m1(i,j)));
+ maxc = (std::max)(numext::real(maxc), numext::real(m1(i,j)));
}
const Scalar mean = s/Scalar(RealScalar(rows*cols));
VERIFY_IS_APPROX(m1.sum(), s);
VERIFY_IS_APPROX(m1.mean(), mean);
VERIFY_IS_APPROX(m1_for_prod.prod(), p);
- VERIFY_IS_APPROX(m1.real().minCoeff(), internal::real(minc));
- VERIFY_IS_APPROX(m1.real().maxCoeff(), internal::real(maxc));
+ VERIFY_IS_APPROX(m1.real().minCoeff(), numext::real(minc));
+ VERIFY_IS_APPROX(m1.real().maxCoeff(), numext::real(maxc));
// test slice vectorization assuming assign is ok
Index r0 = internal::random<Index>(0,rows-1);
@@ -61,6 +61,7 @@ template<typename MatrixType> void matrixRedux(const MatrixType& m)
template<typename VectorType> void vectorRedux(const VectorType& w)
{
+ using std::abs;
typedef typename VectorType::Index Index;
typedef typename VectorType::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
@@ -72,15 +73,15 @@ template<typename VectorType> void vectorRedux(const VectorType& w)
for(int i = 1; i < size; i++)
{
Scalar s(0), p(1);
- RealScalar minc(internal::real(v.coeff(0))), maxc(internal::real(v.coeff(0)));
+ RealScalar minc(numext::real(v.coeff(0))), maxc(numext::real(v.coeff(0)));
for(int j = 0; j < i; j++)
{
s += v[j];
p *= v_for_prod[j];
- minc = (std::min)(minc, internal::real(v[j]));
- maxc = (std::max)(maxc, internal::real(v[j]));
+ minc = (std::min)(minc, numext::real(v[j]));
+ maxc = (std::max)(maxc, numext::real(v[j]));
}
- VERIFY_IS_MUCH_SMALLER_THAN(internal::abs(s - v.head(i).sum()), Scalar(1));
+ VERIFY_IS_MUCH_SMALLER_THAN(abs(s - v.head(i).sum()), Scalar(1));
VERIFY_IS_APPROX(p, v_for_prod.head(i).prod());
VERIFY_IS_APPROX(minc, v.real().head(i).minCoeff());
VERIFY_IS_APPROX(maxc, v.real().head(i).maxCoeff());
@@ -89,15 +90,15 @@ template<typename VectorType> void vectorRedux(const VectorType& w)
for(int i = 0; i < size-1; i++)
{
Scalar s(0), p(1);
- RealScalar minc(internal::real(v.coeff(i))), maxc(internal::real(v.coeff(i)));
+ RealScalar minc(numext::real(v.coeff(i))), maxc(numext::real(v.coeff(i)));
for(int j = i; j < size; j++)
{
s += v[j];
p *= v_for_prod[j];
- minc = (std::min)(minc, internal::real(v[j]));
- maxc = (std::max)(maxc, internal::real(v[j]));
+ minc = (std::min)(minc, numext::real(v[j]));
+ maxc = (std::max)(maxc, numext::real(v[j]));
}
- VERIFY_IS_MUCH_SMALLER_THAN(internal::abs(s - v.tail(size-i).sum()), Scalar(1));
+ VERIFY_IS_MUCH_SMALLER_THAN(abs(s - v.tail(size-i).sum()), Scalar(1));
VERIFY_IS_APPROX(p, v_for_prod.tail(size-i).prod());
VERIFY_IS_APPROX(minc, v.real().tail(size-i).minCoeff());
VERIFY_IS_APPROX(maxc, v.real().tail(size-i).maxCoeff());
@@ -106,15 +107,15 @@ template<typename VectorType> void vectorRedux(const VectorType& w)
for(int i = 0; i < size/2; i++)
{
Scalar s(0), p(1);
- RealScalar minc(internal::real(v.coeff(i))), maxc(internal::real(v.coeff(i)));
+ RealScalar minc(numext::real(v.coeff(i))), maxc(numext::real(v.coeff(i)));
for(int j = i; j < size-i; j++)
{
s += v[j];
p *= v_for_prod[j];
- minc = (std::min)(minc, internal::real(v[j]));
- maxc = (std::max)(maxc, internal::real(v[j]));
+ minc = (std::min)(minc, numext::real(v[j]));
+ maxc = (std::max)(maxc, numext::real(v[j]));
}
- VERIFY_IS_MUCH_SMALLER_THAN(internal::abs(s - v.segment(i, size-2*i).sum()), Scalar(1));
+ VERIFY_IS_MUCH_SMALLER_THAN(abs(s - v.segment(i, size-2*i).sum()), Scalar(1));
VERIFY_IS_APPROX(p, v_for_prod.segment(i, size-2*i).prod());
VERIFY_IS_APPROX(minc, v.real().segment(i, size-2*i).minCoeff());
VERIFY_IS_APPROX(maxc, v.real().segment(i, size-2*i).maxCoeff());
@@ -132,7 +133,7 @@ void test_redux()
{
// the max size cannot be too large, otherwise reduxion operations obviously generate large errors.
int maxsize = (std::min)(100,EIGEN_TEST_MAX_SIZE);
- EIGEN_UNUSED_VARIABLE(maxsize);
+ TEST_SET_BUT_UNUSED_VARIABLE(maxsize);
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST_1( matrixRedux(Matrix<float, 1, 1>()) );
CALL_SUBTEST_1( matrixRedux(Array<float, 1, 1>()) );
diff --git a/test/ref.cpp b/test/ref.cpp
new file mode 100644
index 000000000..19e81549c
--- /dev/null
+++ b/test/ref.cpp
@@ -0,0 +1,252 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 20013 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+// This unit test cannot be easily written to work with EIGEN_DEFAULT_TO_ROW_MAJOR
+#ifdef EIGEN_DEFAULT_TO_ROW_MAJOR
+#undef EIGEN_DEFAULT_TO_ROW_MAJOR
+#endif
+
+static int nb_temporaries;
+
+inline void on_temporary_creation(int) {
+ // here's a great place to set a breakpoint when debugging failures in this test!
+ nb_temporaries++;
+}
+
+
+#define EIGEN_DENSE_STORAGE_CTOR_PLUGIN { on_temporary_creation(size); }
+
+#include "main.h"
+
+#define VERIFY_EVALUATION_COUNT(XPR,N) {\
+ nb_temporaries = 0; \
+ XPR; \
+ if(nb_temporaries!=N) std::cerr << "nb_temporaries == " << nb_temporaries << "\n"; \
+ VERIFY( (#XPR) && nb_temporaries==N ); \
+ }
+
+
+// test Ref.h
+
+template<typename MatrixType> void ref_matrix(const MatrixType& m)
+{
+ typedef typename MatrixType::Index Index;
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::RealScalar RealScalar;
+ typedef Matrix<Scalar,Dynamic,Dynamic,MatrixType::Options> DynMatrixType;
+ typedef Matrix<RealScalar,Dynamic,Dynamic,MatrixType::Options> RealDynMatrixType;
+
+ typedef Ref<MatrixType> RefMat;
+ typedef Ref<DynMatrixType> RefDynMat;
+ typedef Ref<const DynMatrixType> ConstRefDynMat;
+ typedef Ref<RealDynMatrixType , 0, Stride<Dynamic,Dynamic> > RefRealMatWithStride;
+
+ Index rows = m.rows(), cols = m.cols();
+
+ MatrixType m1 = MatrixType::Random(rows, cols),
+ m2 = m1;
+
+ Index i = internal::random<Index>(0,rows-1);
+ Index j = internal::random<Index>(0,cols-1);
+ Index brows = internal::random<Index>(1,rows-i);
+ Index bcols = internal::random<Index>(1,cols-j);
+
+ RefMat rm0 = m1;
+ VERIFY_IS_EQUAL(rm0, m1);
+ RefDynMat rm1 = m1;
+ VERIFY_IS_EQUAL(rm1, m1);
+ RefDynMat rm2 = m1.block(i,j,brows,bcols);
+ VERIFY_IS_EQUAL(rm2, m1.block(i,j,brows,bcols));
+ rm2.setOnes();
+ m2.block(i,j,brows,bcols).setOnes();
+ VERIFY_IS_EQUAL(m1, m2);
+
+ m2.block(i,j,brows,bcols).setRandom();
+ rm2 = m2.block(i,j,brows,bcols);
+ VERIFY_IS_EQUAL(m1, m2);
+
+
+ ConstRefDynMat rm3 = m1.block(i,j,brows,bcols);
+ m1.block(i,j,brows,bcols) *= 2;
+ m2.block(i,j,brows,bcols) *= 2;
+ VERIFY_IS_EQUAL(rm3, m2.block(i,j,brows,bcols));
+ RefRealMatWithStride rm4 = m1.real();
+ VERIFY_IS_EQUAL(rm4, m2.real());
+ rm4.array() += 1;
+ m2.real().array() += 1;
+ VERIFY_IS_EQUAL(m1, m2);
+}
+
+template<typename VectorType> void ref_vector(const VectorType& m)
+{
+ typedef typename VectorType::Index Index;
+ typedef typename VectorType::Scalar Scalar;
+ typedef typename VectorType::RealScalar RealScalar;
+ typedef Matrix<Scalar,Dynamic,1,VectorType::Options> DynMatrixType;
+ typedef Matrix<Scalar,Dynamic,Dynamic,ColMajor> MatrixType;
+ typedef Matrix<RealScalar,Dynamic,1,VectorType::Options> RealDynMatrixType;
+
+ typedef Ref<VectorType> RefMat;
+ typedef Ref<DynMatrixType> RefDynMat;
+ typedef Ref<const DynMatrixType> ConstRefDynMat;
+ typedef Ref<RealDynMatrixType , 0, InnerStride<> > RefRealMatWithStride;
+ typedef Ref<DynMatrixType , 0, InnerStride<> > RefMatWithStride;
+
+ Index size = m.size();
+
+ VectorType v1 = VectorType::Random(size),
+ v2 = v1;
+ MatrixType mat1 = MatrixType::Random(size,size),
+ mat2 = mat1,
+ mat3 = MatrixType::Random(size,size);
+
+ Index i = internal::random<Index>(0,size-1);
+ Index bsize = internal::random<Index>(1,size-i);
+
+ RefMat rm0 = v1;
+ VERIFY_IS_EQUAL(rm0, v1);
+ RefDynMat rv1 = v1;
+ VERIFY_IS_EQUAL(rv1, v1);
+ RefDynMat rv2 = v1.segment(i,bsize);
+ VERIFY_IS_EQUAL(rv2, v1.segment(i,bsize));
+ rv2.setOnes();
+ v2.segment(i,bsize).setOnes();
+ VERIFY_IS_EQUAL(v1, v2);
+
+ v2.segment(i,bsize).setRandom();
+ rv2 = v2.segment(i,bsize);
+ VERIFY_IS_EQUAL(v1, v2);
+
+ ConstRefDynMat rm3 = v1.segment(i,bsize);
+ v1.segment(i,bsize) *= 2;
+ v2.segment(i,bsize) *= 2;
+ VERIFY_IS_EQUAL(rm3, v2.segment(i,bsize));
+
+ RefRealMatWithStride rm4 = v1.real();
+ VERIFY_IS_EQUAL(rm4, v2.real());
+ rm4.array() += 1;
+ v2.real().array() += 1;
+ VERIFY_IS_EQUAL(v1, v2);
+
+ RefMatWithStride rm5 = mat1.row(i).transpose();
+ VERIFY_IS_EQUAL(rm5, mat1.row(i).transpose());
+ rm5.array() += 1;
+ mat2.row(i).array() += 1;
+ VERIFY_IS_EQUAL(mat1, mat2);
+ rm5.noalias() = rm4.transpose() * mat3;
+ mat2.row(i) = v2.real().transpose() * mat3;
+ VERIFY_IS_APPROX(mat1, mat2);
+}
+
+template<typename PlainObjectType> void check_const_correctness(const PlainObjectType&)
+{
+ // verify that ref-to-const don't have LvalueBit
+ typedef typename internal::add_const<PlainObjectType>::type ConstPlainObjectType;
+ VERIFY( !(internal::traits<Ref<ConstPlainObjectType> >::Flags & LvalueBit) );
+ VERIFY( !(internal::traits<Ref<ConstPlainObjectType, Aligned> >::Flags & LvalueBit) );
+ VERIFY( !(Ref<ConstPlainObjectType>::Flags & LvalueBit) );
+ VERIFY( !(Ref<ConstPlainObjectType, Aligned>::Flags & LvalueBit) );
+}
+
+template<typename B>
+EIGEN_DONT_INLINE void call_ref_1(Ref<VectorXf> a, const B &b) { VERIFY_IS_EQUAL(a,b); }
+template<typename B>
+EIGEN_DONT_INLINE void call_ref_2(const Ref<const VectorXf>& a, const B &b) { VERIFY_IS_EQUAL(a,b); }
+template<typename B>
+EIGEN_DONT_INLINE void call_ref_3(Ref<VectorXf,0,InnerStride<> > a, const B &b) { VERIFY_IS_EQUAL(a,b); }
+template<typename B>
+EIGEN_DONT_INLINE void call_ref_4(const Ref<const VectorXf,0,InnerStride<> >& a, const B &b) { VERIFY_IS_EQUAL(a,b); }
+template<typename B>
+EIGEN_DONT_INLINE void call_ref_5(Ref<MatrixXf,0,OuterStride<> > a, const B &b) { VERIFY_IS_EQUAL(a,b); }
+template<typename B>
+EIGEN_DONT_INLINE void call_ref_6(const Ref<const MatrixXf,0,OuterStride<> >& a, const B &b) { VERIFY_IS_EQUAL(a,b); }
+template<typename B>
+EIGEN_DONT_INLINE void call_ref_7(Ref<Matrix<float,Dynamic,3> > a, const B &b) { VERIFY_IS_EQUAL(a,b); }
+
+void call_ref()
+{
+ VectorXcf ca = VectorXcf::Random(10);
+ VectorXf a = VectorXf::Random(10);
+ RowVectorXf b = RowVectorXf::Random(10);
+ MatrixXf A = MatrixXf::Random(10,10);
+ RowVector3f c = RowVector3f::Random();
+ const VectorXf& ac(a);
+ VectorBlock<VectorXf> ab(a,0,3);
+ const VectorBlock<VectorXf> abc(a,0,3);
+
+
+ VERIFY_EVALUATION_COUNT( call_ref_1(a,a), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_1(b,b.transpose()), 0);
+// call_ref_1(ac); // does not compile because ac is const
+ VERIFY_EVALUATION_COUNT( call_ref_1(ab,ab), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_1(a.head(4),a.head(4)), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_1(abc,abc), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_1(A.col(3),A.col(3)), 0);
+// call_ref_1(A.row(3)); // does not compile because innerstride!=1
+ VERIFY_EVALUATION_COUNT( call_ref_3(A.row(3),A.row(3).transpose()), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_4(A.row(3),A.row(3).transpose()), 0);
+// call_ref_1(a+a); // does not compile for obvious reason
+
+ MatrixXf tmp = A*A.col(1);
+ VERIFY_EVALUATION_COUNT( call_ref_2(A*A.col(1), tmp), 1); // evaluated into a temp
+ VERIFY_EVALUATION_COUNT( call_ref_2(ac.head(5),ac.head(5)), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_2(ac,ac), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_2(a,a), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_2(ab,ab), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_2(a.head(4),a.head(4)), 0);
+ tmp = a+a;
+ VERIFY_EVALUATION_COUNT( call_ref_2(a+a,tmp), 1); // evaluated into a temp
+ VERIFY_EVALUATION_COUNT( call_ref_2(ca.imag(),ca.imag()), 1); // evaluated into a temp
+
+ VERIFY_EVALUATION_COUNT( call_ref_4(ac.head(5),ac.head(5)), 0);
+ tmp = a+a;
+ VERIFY_EVALUATION_COUNT( call_ref_4(a+a,tmp), 1); // evaluated into a temp
+ VERIFY_EVALUATION_COUNT( call_ref_4(ca.imag(),ca.imag()), 0);
+
+ VERIFY_EVALUATION_COUNT( call_ref_5(a,a), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_5(a.head(3),a.head(3)), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_5(A,A), 0);
+// call_ref_5(A.transpose()); // does not compile
+ VERIFY_EVALUATION_COUNT( call_ref_5(A.block(1,1,2,2),A.block(1,1,2,2)), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_5(b,b), 0); // storage order do not match, but this is a degenerate case that should work
+ VERIFY_EVALUATION_COUNT( call_ref_5(a.row(3),a.row(3)), 0);
+
+ VERIFY_EVALUATION_COUNT( call_ref_6(a,a), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_6(a.head(3),a.head(3)), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_6(A.row(3),A.row(3)), 1); // evaluated into a temp thouth it could be avoided by viewing it as a 1xn matrix
+ tmp = A+A;
+ VERIFY_EVALUATION_COUNT( call_ref_6(A+A,tmp), 1); // evaluated into a temp
+ VERIFY_EVALUATION_COUNT( call_ref_6(A,A), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_6(A.transpose(),A.transpose()), 1); // evaluated into a temp because the storage orders do not match
+ VERIFY_EVALUATION_COUNT( call_ref_6(A.block(1,1,2,2),A.block(1,1,2,2)), 0);
+
+ VERIFY_EVALUATION_COUNT( call_ref_7(c,c), 0);
+}
+
+void test_ref()
+{
+ for(int i = 0; i < g_repeat; i++) {
+ CALL_SUBTEST_1( ref_vector(Matrix<float, 1, 1>()) );
+ CALL_SUBTEST_1( check_const_correctness(Matrix<float, 1, 1>()) );
+ CALL_SUBTEST_2( ref_vector(Vector4d()) );
+ CALL_SUBTEST_2( check_const_correctness(Matrix4d()) );
+ CALL_SUBTEST_3( ref_vector(Vector4cf()) );
+ CALL_SUBTEST_4( ref_vector(VectorXcf(8)) );
+ CALL_SUBTEST_5( ref_vector(VectorXi(12)) );
+ CALL_SUBTEST_5( check_const_correctness(VectorXi(12)) );
+
+ CALL_SUBTEST_1( ref_matrix(Matrix<float, 1, 1>()) );
+ CALL_SUBTEST_2( ref_matrix(Matrix4d()) );
+ CALL_SUBTEST_1( ref_matrix(Matrix<float,3,5>()) );
+ CALL_SUBTEST_4( ref_matrix(MatrixXcf(internal::random<int>(1,10),internal::random<int>(1,10))) );
+ CALL_SUBTEST_4( ref_matrix(Matrix<std::complex<double>,10,15>()) );
+ CALL_SUBTEST_5( ref_matrix(MatrixXi(internal::random<int>(1,10),internal::random<int>(1,10))) );
+ CALL_SUBTEST_6( call_ref() );
+ }
+}
diff --git a/test/schur_complex.cpp b/test/schur_complex.cpp
index a6f66ab02..5e869790f 100644
--- a/test/schur_complex.cpp
+++ b/test/schur_complex.cpp
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
-// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
+// Copyright (C) 2010,2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
//
// 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
@@ -47,6 +47,23 @@ template<typename MatrixType> void schur(int size = MatrixType::ColsAtCompileTim
VERIFY_IS_EQUAL(cs1.matrixT(), cs2.matrixT());
VERIFY_IS_EQUAL(cs1.matrixU(), cs2.matrixU());
+ // Test maximum number of iterations
+ ComplexSchur<MatrixType> cs3;
+ cs3.setMaxIterations(ComplexSchur<MatrixType>::m_maxIterationsPerRow * size).compute(A);
+ VERIFY_IS_EQUAL(cs3.info(), Success);
+ VERIFY_IS_EQUAL(cs3.matrixT(), cs1.matrixT());
+ VERIFY_IS_EQUAL(cs3.matrixU(), cs1.matrixU());
+ cs3.setMaxIterations(1).compute(A);
+ VERIFY_IS_EQUAL(cs3.info(), size > 1 ? NoConvergence : Success);
+ VERIFY_IS_EQUAL(cs3.getMaxIterations(), 1);
+
+ MatrixType Atriangular = A;
+ Atriangular.template triangularView<StrictlyLower>().setZero();
+ cs3.setMaxIterations(1).compute(Atriangular); // triangular matrices do not need any iterations
+ VERIFY_IS_EQUAL(cs3.info(), Success);
+ VERIFY_IS_EQUAL(cs3.matrixT(), Atriangular.template cast<ComplexScalar>());
+ VERIFY_IS_EQUAL(cs3.matrixU(), ComplexMatrixType::Identity(size, size));
+
// Test computation of only T, not U
ComplexSchur<MatrixType> csOnlyT(A, false);
VERIFY_IS_EQUAL(csOnlyT.info(), Success);
diff --git a/test/schur_real.cpp b/test/schur_real.cpp
index e6351d94a..36b9c24d1 100644
--- a/test/schur_real.cpp
+++ b/test/schur_real.cpp
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
-// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
+// Copyright (C) 2010,2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
//
// 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
@@ -66,6 +66,25 @@ template<typename MatrixType> void schur(int size = MatrixType::ColsAtCompileTim
VERIFY_IS_EQUAL(rs1.matrixT(), rs2.matrixT());
VERIFY_IS_EQUAL(rs1.matrixU(), rs2.matrixU());
+ // Test maximum number of iterations
+ RealSchur<MatrixType> rs3;
+ rs3.setMaxIterations(RealSchur<MatrixType>::m_maxIterationsPerRow * size).compute(A);
+ VERIFY_IS_EQUAL(rs3.info(), Success);
+ VERIFY_IS_EQUAL(rs3.matrixT(), rs1.matrixT());
+ VERIFY_IS_EQUAL(rs3.matrixU(), rs1.matrixU());
+ if (size > 2) {
+ rs3.setMaxIterations(1).compute(A);
+ VERIFY_IS_EQUAL(rs3.info(), NoConvergence);
+ VERIFY_IS_EQUAL(rs3.getMaxIterations(), 1);
+ }
+
+ MatrixType Atriangular = A;
+ Atriangular.template triangularView<StrictlyLower>().setZero();
+ rs3.setMaxIterations(1).compute(Atriangular); // triangular matrices do not need any iterations
+ VERIFY_IS_EQUAL(rs3.info(), Success);
+ VERIFY_IS_EQUAL(rs3.matrixT(), Atriangular);
+ VERIFY_IS_EQUAL(rs3.matrixU(), MatrixType::Identity(size, size));
+
// Test computation of only T, not U
RealSchur<MatrixType> rsOnlyT(A, false);
VERIFY_IS_EQUAL(rsOnlyT.info(), Success);
diff --git a/test/selfadjoint.cpp b/test/selfadjoint.cpp
index 6d3ec6536..76dab6d64 100644
--- a/test/selfadjoint.cpp
+++ b/test/selfadjoint.cpp
@@ -16,7 +16,6 @@ template<typename MatrixType> void selfadjoint(const MatrixType& m)
{
typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
Index rows = m.rows();
Index cols = m.cols();
@@ -47,7 +46,7 @@ void test_selfadjoint()
{
for(int i = 0; i < g_repeat ; i++)
{
- int s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE); EIGEN_UNUSED_VARIABLE(s);
+ int s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
CALL_SUBTEST_1( selfadjoint(Matrix<float, 1, 1>()) );
CALL_SUBTEST_2( selfadjoint(Matrix<float, 2, 2>()) );
@@ -55,7 +54,7 @@ void test_selfadjoint()
CALL_SUBTEST_4( selfadjoint(MatrixXcd(s,s)) );
CALL_SUBTEST_5( selfadjoint(Matrix<float,Dynamic,Dynamic,RowMajor>(s, s)) );
- EIGEN_UNUSED_VARIABLE(s)
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
}
CALL_SUBTEST_1( bug_159() );
diff --git a/test/simplicial_cholesky.cpp b/test/simplicial_cholesky.cpp
index e93a52e9c..786468421 100644
--- a/test/simplicial_cholesky.cpp
+++ b/test/simplicial_cholesky.cpp
@@ -11,26 +11,31 @@
template<typename T> void test_simplicial_cholesky_T()
{
- SimplicialCholesky<SparseMatrix<T>, Lower> chol_colmajor_lower;
- SimplicialCholesky<SparseMatrix<T>, Upper> chol_colmajor_upper;
- SimplicialLLT<SparseMatrix<T>, Lower> llt_colmajor_lower;
- SimplicialLDLT<SparseMatrix<T>, Upper> llt_colmajor_upper;
- SimplicialLDLT<SparseMatrix<T>, Lower> ldlt_colmajor_lower;
- SimplicialLDLT<SparseMatrix<T>, Upper> ldlt_colmajor_upper;
+ SimplicialCholesky<SparseMatrix<T>, Lower> chol_colmajor_lower_amd;
+ SimplicialCholesky<SparseMatrix<T>, Upper> chol_colmajor_upper_amd;
+ SimplicialLLT<SparseMatrix<T>, Lower> llt_colmajor_lower_amd;
+ SimplicialLLT<SparseMatrix<T>, Upper> llt_colmajor_upper_amd;
+ SimplicialLDLT<SparseMatrix<T>, Lower> ldlt_colmajor_lower_amd;
+ SimplicialLDLT<SparseMatrix<T>, Upper> ldlt_colmajor_upper_amd;
+ SimplicialLDLT<SparseMatrix<T>, Lower, NaturalOrdering<int> > ldlt_colmajor_lower_nat;
+ SimplicialLDLT<SparseMatrix<T>, Upper, NaturalOrdering<int> > ldlt_colmajor_upper_nat;
- check_sparse_spd_solving(chol_colmajor_lower);
- check_sparse_spd_solving(chol_colmajor_upper);
- check_sparse_spd_solving(llt_colmajor_lower);
- check_sparse_spd_solving(llt_colmajor_upper);
- check_sparse_spd_solving(ldlt_colmajor_lower);
- check_sparse_spd_solving(ldlt_colmajor_upper);
+ check_sparse_spd_solving(chol_colmajor_lower_amd);
+ check_sparse_spd_solving(chol_colmajor_upper_amd);
+ check_sparse_spd_solving(llt_colmajor_lower_amd);
+ check_sparse_spd_solving(llt_colmajor_upper_amd);
+ check_sparse_spd_solving(ldlt_colmajor_lower_amd);
+ check_sparse_spd_solving(ldlt_colmajor_upper_amd);
- check_sparse_spd_determinant(chol_colmajor_lower);
- check_sparse_spd_determinant(chol_colmajor_upper);
- check_sparse_spd_determinant(llt_colmajor_lower);
- check_sparse_spd_determinant(llt_colmajor_upper);
- check_sparse_spd_determinant(ldlt_colmajor_lower);
- check_sparse_spd_determinant(ldlt_colmajor_upper);
+ check_sparse_spd_determinant(chol_colmajor_lower_amd);
+ check_sparse_spd_determinant(chol_colmajor_upper_amd);
+ check_sparse_spd_determinant(llt_colmajor_lower_amd);
+ check_sparse_spd_determinant(llt_colmajor_upper_amd);
+ check_sparse_spd_determinant(ldlt_colmajor_lower_amd);
+ check_sparse_spd_determinant(ldlt_colmajor_upper_amd);
+
+ check_sparse_spd_solving(ldlt_colmajor_lower_nat);
+ check_sparse_spd_solving(ldlt_colmajor_upper_nat);
}
void test_simplicial_cholesky()
diff --git a/test/sizeof.cpp b/test/sizeof.cpp
index 68463c9b6..d9ad35620 100644
--- a/test/sizeof.cpp
+++ b/test/sizeof.cpp
@@ -13,7 +13,7 @@ template<typename MatrixType> void verifySizeOf(const MatrixType&)
{
typedef typename MatrixType::Scalar Scalar;
if (MatrixType::RowsAtCompileTime!=Dynamic && MatrixType::ColsAtCompileTime!=Dynamic)
- VERIFY(sizeof(MatrixType)==sizeof(Scalar)*size_t(MatrixType::SizeAtCompileTime));
+ VERIFY(std::ptrdiff_t(sizeof(MatrixType))==std::ptrdiff_t(sizeof(Scalar))*std::ptrdiff_t(MatrixType::SizeAtCompileTime));
else
VERIFY(sizeof(MatrixType)==sizeof(Scalar*) + 2 * sizeof(typename MatrixType::Index));
}
diff --git a/test/sparse.h b/test/sparse.h
index 4db0004aa..e19a76316 100644
--- a/test/sparse.h
+++ b/test/sparse.h
@@ -58,18 +58,18 @@ initSparse(double density,
Matrix<Scalar,Dynamic,Dynamic,Opt1>& refMat,
SparseMatrix<Scalar,Opt2,Index>& sparseMat,
int flags = 0,
- std::vector<Vector2i>* zeroCoords = 0,
- std::vector<Vector2i>* nonzeroCoords = 0)
+ std::vector<Matrix<Index,2,1> >* zeroCoords = 0,
+ std::vector<Matrix<Index,2,1> >* nonzeroCoords = 0)
{
enum { IsRowMajor = SparseMatrix<Scalar,Opt2,Index>::IsRowMajor };
sparseMat.setZero();
//sparseMat.reserve(int(refMat.rows()*refMat.cols()*density));
sparseMat.reserve(VectorXi::Constant(IsRowMajor ? refMat.rows() : refMat.cols(), int((1.5*density)*(IsRowMajor?refMat.cols():refMat.rows()))));
- for(int j=0; j<sparseMat.outerSize(); j++)
+ for(Index j=0; j<sparseMat.outerSize(); j++)
{
//sparseMat.startVec(j);
- for(int i=0; i<sparseMat.innerSize(); i++)
+ for(Index i=0; i<sparseMat.innerSize(); i++)
{
int ai(i), aj(j);
if(IsRowMajor)
@@ -86,18 +86,18 @@ initSparse(double density,
v = Scalar(0);
if ((flags&ForceRealDiag) && (i==j))
- v = internal::real(v);
+ v = numext::real(v);
if (v!=Scalar(0))
{
//sparseMat.insertBackByOuterInner(j,i) = v;
sparseMat.insertByOuterInner(j,i) = v;
if (nonzeroCoords)
- nonzeroCoords->push_back(Vector2i(ai,aj));
+ nonzeroCoords->push_back(Matrix<Index,2,1> (ai,aj));
}
else if (zeroCoords)
{
- zeroCoords->push_back(Vector2i(ai,aj));
+ zeroCoords->push_back(Matrix<Index,2,1> (ai,aj));
}
refMat(ai,aj) = v;
}
@@ -110,8 +110,8 @@ initSparse(double density,
Matrix<Scalar,Dynamic,Dynamic, Opt1>& refMat,
DynamicSparseMatrix<Scalar, Opt2, Index>& sparseMat,
int flags = 0,
- std::vector<Vector2i>* zeroCoords = 0,
- std::vector<Vector2i>* nonzeroCoords = 0)
+ std::vector<Matrix<Index,2,1> >* zeroCoords = 0,
+ std::vector<Matrix<Index,2,1> >* nonzeroCoords = 0)
{
enum { IsRowMajor = DynamicSparseMatrix<Scalar,Opt2,Index>::IsRowMajor };
sparseMat.setZero();
@@ -136,17 +136,17 @@ initSparse(double density,
v = Scalar(0);
if ((flags&ForceRealDiag) && (i==j))
- v = internal::real(v);
+ v = numext::real(v);
if (v!=Scalar(0))
{
sparseMat.insertBackByOuterInner(j,i) = v;
if (nonzeroCoords)
- nonzeroCoords->push_back(Vector2i(ai,aj));
+ nonzeroCoords->push_back(Matrix<Index,2,1> (ai,aj));
}
else if (zeroCoords)
{
- zeroCoords->push_back(Vector2i(ai,aj));
+ zeroCoords->push_back(Matrix<Index,2,1> (ai,aj));
}
refMat(ai,aj) = v;
}
@@ -154,10 +154,34 @@ initSparse(double density,
sparseMat.finalize();
}
-template<typename Scalar> void
+template<typename Scalar,int Options,typename Index> void
initSparse(double density,
Matrix<Scalar,Dynamic,1>& refVec,
- SparseVector<Scalar>& sparseVec,
+ SparseVector<Scalar,Options,Index>& sparseVec,
+ std::vector<int>* zeroCoords = 0,
+ std::vector<int>* nonzeroCoords = 0)
+{
+ sparseVec.reserve(int(refVec.size()*density));
+ sparseVec.setZero();
+ for(Index i=0; i<refVec.size(); i++)
+ {
+ Scalar v = (internal::random<double>(0,1) < density) ? internal::random<Scalar>() : Scalar(0);
+ if (v!=Scalar(0))
+ {
+ sparseVec.insertBack(i) = v;
+ if (nonzeroCoords)
+ nonzeroCoords->push_back(i);
+ }
+ else if (zeroCoords)
+ zeroCoords->push_back(i);
+ refVec[i] = v;
+ }
+}
+
+template<typename Scalar,int Options,typename Index> void
+initSparse(double density,
+ Matrix<Scalar,1,Dynamic>& refVec,
+ SparseVector<Scalar,Options,Index>& sparseVec,
std::vector<int>* zeroCoords = 0,
std::vector<int>* nonzeroCoords = 0)
{
@@ -178,5 +202,6 @@ initSparse(double density,
}
}
+
#include <unsupported/Eigen/SparseExtra>
#endif // EIGEN_TESTSPARSE_H
diff --git a/test/sparseLM.cpp b/test/sparseLM.cpp
new file mode 100644
index 000000000..8e148f9bc
--- /dev/null
+++ b/test/sparseLM.cpp
@@ -0,0 +1,176 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Desire Nuentsa <desire.nuentsa_wakam@inria.fr>
+// Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+
+#include "main.h"
+#include <Eigen/LevenbergMarquardt>
+
+using namespace std;
+using namespace Eigen;
+
+template <typename Scalar>
+struct sparseGaussianTest : SparseFunctor<Scalar, int>
+{
+ typedef Matrix<Scalar,Dynamic,1> VectorType;
+ typedef SparseFunctor<Scalar,int> Base;
+ typedef typename Base::JacobianType JacobianType;
+ sparseGaussianTest(int inputs, int values) : SparseFunctor<Scalar,int>(inputs,values)
+ { }
+
+ VectorType model(const VectorType& uv, VectorType& x)
+ {
+ VectorType y; //Change this to use expression template
+ int m = Base::values();
+ int n = Base::inputs();
+ eigen_assert(uv.size()%2 == 0);
+ eigen_assert(uv.size() == n);
+ eigen_assert(x.size() == m);
+ y.setZero(m);
+ int half = n/2;
+ VectorBlock<const VectorType> u(uv, 0, half);
+ VectorBlock<const VectorType> v(uv, half, half);
+ Scalar coeff;
+ for (int j = 0; j < m; j++)
+ {
+ for (int i = 0; i < half; i++)
+ {
+ coeff = (x(j)-i)/v(i);
+ coeff *= coeff;
+ if (coeff < 1. && coeff > 0.)
+ y(j) += u(i)*std::pow((1-coeff), 2);
+ }
+ }
+ return y;
+ }
+ void initPoints(VectorType& uv_ref, VectorType& x)
+ {
+ m_x = x;
+ m_y = this->model(uv_ref,x);
+ }
+ int operator()(const VectorType& uv, VectorType& fvec)
+ {
+ int m = Base::values();
+ int n = Base::inputs();
+ eigen_assert(uv.size()%2 == 0);
+ eigen_assert(uv.size() == n);
+ int half = n/2;
+ VectorBlock<const VectorType> u(uv, 0, half);
+ VectorBlock<const VectorType> v(uv, half, half);
+ fvec = m_y;
+ Scalar coeff;
+ for (int j = 0; j < m; j++)
+ {
+ for (int i = 0; i < half; i++)
+ {
+ coeff = (m_x(j)-i)/v(i);
+ coeff *= coeff;
+ if (coeff < 1. && coeff > 0.)
+ fvec(j) -= u(i)*std::pow((1-coeff), 2);
+ }
+ }
+ return 0;
+ }
+
+ int df(const VectorType& uv, JacobianType& fjac)
+ {
+ int m = Base::values();
+ int n = Base::inputs();
+ eigen_assert(n == uv.size());
+ eigen_assert(fjac.rows() == m);
+ eigen_assert(fjac.cols() == n);
+ int half = n/2;
+ VectorBlock<const VectorType> u(uv, 0, half);
+ VectorBlock<const VectorType> v(uv, half, half);
+ Scalar coeff;
+
+ //Derivatives with respect to u
+ for (int col = 0; col < half; col++)
+ {
+ for (int row = 0; row < m; row++)
+ {
+ coeff = (m_x(row)-col)/v(col);
+ coeff = coeff*coeff;
+ if(coeff < 1. && coeff > 0.)
+ {
+ fjac.coeffRef(row,col) = -(1-coeff)*(1-coeff);
+ }
+ }
+ }
+ //Derivatives with respect to v
+ for (int col = 0; col < half; col++)
+ {
+ for (int row = 0; row < m; row++)
+ {
+ coeff = (m_x(row)-col)/v(col);
+ coeff = coeff*coeff;
+ if(coeff < 1. && coeff > 0.)
+ {
+ fjac.coeffRef(row,col+half) = -4 * (u(col)/v(col))*coeff*(1-coeff);
+ }
+ }
+ }
+ return 0;
+ }
+
+ VectorType m_x, m_y; //Data points
+};
+
+
+template<typename T>
+void test_sparseLM_T()
+{
+ typedef Matrix<T,Dynamic,1> VectorType;
+
+ int inputs = 10;
+ int values = 2000;
+ sparseGaussianTest<T> sparse_gaussian(inputs, values);
+ VectorType uv(inputs),uv_ref(inputs);
+ VectorType x(values);
+ // Generate the reference solution
+ uv_ref << -2, 1, 4 ,8, 6, 1.8, 1.2, 1.1, 1.9 , 3;
+ //Generate the reference data points
+ x.setRandom();
+ x = 10*x;
+ x.array() += 10;
+ sparse_gaussian.initPoints(uv_ref, x);
+
+
+ // Generate the initial parameters
+ VectorBlock<VectorType> u(uv, 0, inputs/2);
+ VectorBlock<VectorType> v(uv, inputs/2, inputs/2);
+ v.setOnes();
+ //Generate u or Solve for u from v
+ u.setOnes();
+
+ // Solve the optimization problem
+ LevenbergMarquardt<sparseGaussianTest<T> > lm(sparse_gaussian);
+ int info;
+// info = lm.minimize(uv);
+
+ VERIFY_IS_EQUAL(info,1);
+ // Do a step by step solution and save the residual
+ int maxiter = 200;
+ int iter = 0;
+ MatrixXd Err(values, maxiter);
+ MatrixXd Mod(values, maxiter);
+ LevenbergMarquardtSpace::Status status;
+ status = lm.minimizeInit(uv);
+ if (status==LevenbergMarquardtSpace::ImproperInputParameters)
+ return ;
+
+}
+void test_sparseLM()
+{
+ CALL_SUBTEST_1(test_sparseLM_T<double>());
+
+ // CALL_SUBTEST_2(test_sparseLM_T<std::complex<double>());
+}
diff --git a/test/sparse_basic.cpp b/test/sparse_basic.cpp
index 8897a9dca..498ecfe29 100644
--- a/test/sparse_basic.cpp
+++ b/test/sparse_basic.cpp
@@ -3,6 +3,7 @@
//
// Copyright (C) 2008-2011 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2008 Daniel Gomez Ferro <dgomezferro@gmail.com>
+// Copyright (C) 2013 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
@@ -13,7 +14,8 @@
template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& ref)
{
typedef typename SparseMatrixType::Index Index;
-
+ typedef Matrix<Index,2,1> Vector2;
+
const Index rows = ref.rows();
const Index cols = ref.cols();
typedef typename SparseMatrixType::Scalar Scalar;
@@ -24,71 +26,77 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
typedef Matrix<Scalar,Dynamic,1> DenseVector;
Scalar eps = 1e-6;
- SparseMatrixType m(rows, cols);
- DenseMatrix refMat = DenseMatrix::Zero(rows, cols);
- DenseVector vec1 = DenseVector::Random(rows);
Scalar s1 = internal::random<Scalar>();
-
- std::vector<Vector2i> zeroCoords;
- std::vector<Vector2i> nonzeroCoords;
- initSparse<Scalar>(density, refMat, m, 0, &zeroCoords, &nonzeroCoords);
-
- if (zeroCoords.size()==0 || nonzeroCoords.size()==0)
- return;
-
- // test coeff and coeffRef
- for (int i=0; i<(int)zeroCoords.size(); ++i)
{
- VERIFY_IS_MUCH_SMALLER_THAN( m.coeff(zeroCoords[i].x(),zeroCoords[i].y()), eps );
- if(internal::is_same<SparseMatrixType,SparseMatrix<Scalar,Flags> >::value)
- VERIFY_RAISES_ASSERT( m.coeffRef(zeroCoords[0].x(),zeroCoords[0].y()) = 5 );
- }
- VERIFY_IS_APPROX(m, refMat);
+ SparseMatrixType m(rows, cols);
+ DenseMatrix refMat = DenseMatrix::Zero(rows, cols);
+ DenseVector vec1 = DenseVector::Random(rows);
- m.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5);
- refMat.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5);
+ std::vector<Vector2> zeroCoords;
+ std::vector<Vector2> nonzeroCoords;
+ initSparse<Scalar>(density, refMat, m, 0, &zeroCoords, &nonzeroCoords);
- VERIFY_IS_APPROX(m, refMat);
- /*
- // test InnerIterators and Block expressions
- for (int t=0; t<10; ++t)
- {
- int j = internal::random<int>(0,cols-1);
- int i = internal::random<int>(0,rows-1);
- int w = internal::random<int>(1,cols-j-1);
- int h = internal::random<int>(1,rows-i-1);
+ if (zeroCoords.size()==0 || nonzeroCoords.size()==0)
+ return;
-// VERIFY_IS_APPROX(m.block(i,j,h,w), refMat.block(i,j,h,w));
- for(int c=0; c<w; c++)
+ // test coeff and coeffRef
+ for (int i=0; i<(int)zeroCoords.size(); ++i)
{
- VERIFY_IS_APPROX(m.block(i,j,h,w).col(c), refMat.block(i,j,h,w).col(c));
- for(int r=0; r<h; r++)
+ VERIFY_IS_MUCH_SMALLER_THAN( m.coeff(zeroCoords[i].x(),zeroCoords[i].y()), eps );
+ if(internal::is_same<SparseMatrixType,SparseMatrix<Scalar,Flags> >::value)
+ VERIFY_RAISES_ASSERT( m.coeffRef(zeroCoords[0].x(),zeroCoords[0].y()) = 5 );
+ }
+ VERIFY_IS_APPROX(m, refMat);
+
+ m.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5);
+ refMat.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5);
+
+ VERIFY_IS_APPROX(m, refMat);
+ /*
+ // test InnerIterators and Block expressions
+ for (int t=0; t<10; ++t)
{
-// VERIFY_IS_APPROX(m.block(i,j,h,w).col(c).coeff(r), refMat.block(i,j,h,w).col(c).coeff(r));
+ int j = internal::random<int>(0,cols-1);
+ int i = internal::random<int>(0,rows-1);
+ int w = internal::random<int>(1,cols-j-1);
+ int h = internal::random<int>(1,rows-i-1);
+
+ // VERIFY_IS_APPROX(m.block(i,j,h,w), refMat.block(i,j,h,w));
+ for(int c=0; c<w; c++)
+ {
+ VERIFY_IS_APPROX(m.block(i,j,h,w).col(c), refMat.block(i,j,h,w).col(c));
+ for(int r=0; r<h; r++)
+ {
+ // VERIFY_IS_APPROX(m.block(i,j,h,w).col(c).coeff(r), refMat.block(i,j,h,w).col(c).coeff(r));
+ }
+ }
+ // for(int r=0; r<h; r++)
+ // {
+ // VERIFY_IS_APPROX(m.block(i,j,h,w).row(r), refMat.block(i,j,h,w).row(r));
+ // for(int c=0; c<w; c++)
+ // {
+ // VERIFY_IS_APPROX(m.block(i,j,h,w).row(r).coeff(c), refMat.block(i,j,h,w).row(r).coeff(c));
+ // }
+ // }
}
- }
-// for(int r=0; r<h; r++)
-// {
-// VERIFY_IS_APPROX(m.block(i,j,h,w).row(r), refMat.block(i,j,h,w).row(r));
-// for(int c=0; c<w; c++)
-// {
-// VERIFY_IS_APPROX(m.block(i,j,h,w).row(r).coeff(c), refMat.block(i,j,h,w).row(r).coeff(c));
-// }
-// }
- }
- for(int c=0; c<cols; c++)
- {
- VERIFY_IS_APPROX(m.col(c) + m.col(c), (m + m).col(c));
- VERIFY_IS_APPROX(m.col(c) + m.col(c), refMat.col(c) + refMat.col(c));
- }
+ for(int c=0; c<cols; c++)
+ {
+ VERIFY_IS_APPROX(m.col(c) + m.col(c), (m + m).col(c));
+ VERIFY_IS_APPROX(m.col(c) + m.col(c), refMat.col(c) + refMat.col(c));
+ }
- for(int r=0; r<rows; r++)
- {
- VERIFY_IS_APPROX(m.row(r) + m.row(r), (m + m).row(r));
- VERIFY_IS_APPROX(m.row(r) + m.row(r), refMat.row(r) + refMat.row(r));
- }
- */
+ for(int r=0; r<rows; r++)
+ {
+ VERIFY_IS_APPROX(m.row(r) + m.row(r), (m + m).row(r));
+ VERIFY_IS_APPROX(m.row(r) + m.row(r), refMat.row(r) + refMat.row(r));
+ }
+ */
+
+ // test assertion
+ VERIFY_RAISES_ASSERT( m.coeffRef(-1,1) = 0 );
+ VERIFY_RAISES_ASSERT( m.coeffRef(0,m.cols()) = 0 );
+ }
// test insert (inner random)
{
@@ -97,11 +105,11 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
SparseMatrixType m2(rows,cols);
if(internal::random<int>()%2)
m2.reserve(VectorXi::Constant(m2.outerSize(), 2));
- for (int j=0; j<cols; ++j)
+ for (Index j=0; j<cols; ++j)
{
- for (int k=0; k<rows/2; ++k)
+ for (Index k=0; k<rows/2; ++k)
{
- int i = internal::random<int>(0,rows-1);
+ Index i = internal::random<Index>(0,rows-1);
if (m1.coeff(i,j)==Scalar(0))
m2.insert(i,j) = m1(i,j) = internal::random<Scalar>();
}
@@ -119,8 +127,8 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
m2.reserve(VectorXi::Constant(m2.outerSize(), 2));
for (int k=0; k<rows*cols; ++k)
{
- int i = internal::random<int>(0,rows-1);
- int j = internal::random<int>(0,cols-1);
+ Index i = internal::random<Index>(0,rows-1);
+ Index j = internal::random<Index>(0,cols-1);
if ((m1.coeff(i,j)==Scalar(0)) && (internal::random<int>()%2))
m2.insert(i,j) = m1(i,j) = internal::random<Scalar>();
else
@@ -143,8 +151,8 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
m2.reserve(r);
for (int k=0; k<rows*cols; ++k)
{
- int i = internal::random<int>(0,rows-1);
- int j = internal::random<int>(0,cols-1);
+ Index i = internal::random<Index>(0,rows-1);
+ Index j = internal::random<Index>(0,cols-1);
if (m1.coeff(i,j)==Scalar(0))
m2.insert(i,j) = m1(i,j) = internal::random<Scalar>();
if(mode==3)
@@ -155,6 +163,80 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
VERIFY_IS_APPROX(m2,m1);
}
+ // test innerVector()
+ {
+ DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
+ SparseMatrixType m2(rows, rows);
+ initSparse<Scalar>(density, refMat2, m2);
+ Index j0 = internal::random<Index>(0,rows-1);
+ Index j1 = internal::random<Index>(0,rows-1);
+ if(SparseMatrixType::IsRowMajor)
+ VERIFY_IS_APPROX(m2.innerVector(j0), refMat2.row(j0));
+ else
+ VERIFY_IS_APPROX(m2.innerVector(j0), refMat2.col(j0));
+
+ if(SparseMatrixType::IsRowMajor)
+ VERIFY_IS_APPROX(m2.innerVector(j0)+m2.innerVector(j1), refMat2.row(j0)+refMat2.row(j1));
+ else
+ VERIFY_IS_APPROX(m2.innerVector(j0)+m2.innerVector(j1), refMat2.col(j0)+refMat2.col(j1));
+
+ SparseMatrixType m3(rows,rows);
+ m3.reserve(VectorXi::Constant(rows,rows/2));
+ for(Index j=0; j<rows; ++j)
+ for(Index k=0; k<j; ++k)
+ m3.insertByOuterInner(j,k) = k+1;
+ for(Index j=0; j<rows; ++j)
+ {
+ VERIFY(j==numext::real(m3.innerVector(j).nonZeros()));
+ if(j>0)
+ VERIFY(j==numext::real(m3.innerVector(j).lastCoeff()));
+ }
+ m3.makeCompressed();
+ for(Index j=0; j<rows; ++j)
+ {
+ VERIFY(j==numext::real(m3.innerVector(j).nonZeros()));
+ if(j>0)
+ VERIFY(j==numext::real(m3.innerVector(j).lastCoeff()));
+ }
+
+ //m2.innerVector(j0) = 2*m2.innerVector(j1);
+ //refMat2.col(j0) = 2*refMat2.col(j1);
+ //VERIFY_IS_APPROX(m2, refMat2);
+ }
+
+ // test innerVectors()
+ {
+ DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
+ SparseMatrixType m2(rows, rows);
+ initSparse<Scalar>(density, refMat2, m2);
+ if(internal::random<float>(0,1)>0.5) m2.makeCompressed();
+
+ Index j0 = internal::random<Index>(0,rows-2);
+ Index j1 = internal::random<Index>(0,rows-2);
+ Index n0 = internal::random<Index>(1,rows-(std::max)(j0,j1));
+ if(SparseMatrixType::IsRowMajor)
+ VERIFY_IS_APPROX(m2.innerVectors(j0,n0), refMat2.block(j0,0,n0,cols));
+ else
+ VERIFY_IS_APPROX(m2.innerVectors(j0,n0), refMat2.block(0,j0,rows,n0));
+ if(SparseMatrixType::IsRowMajor)
+ VERIFY_IS_APPROX(m2.innerVectors(j0,n0)+m2.innerVectors(j1,n0),
+ refMat2.middleRows(j0,n0)+refMat2.middleRows(j1,n0));
+ else
+ VERIFY_IS_APPROX(m2.innerVectors(j0,n0)+m2.innerVectors(j1,n0),
+ refMat2.block(0,j0,rows,n0)+refMat2.block(0,j1,rows,n0));
+
+ VERIFY_IS_APPROX(m2, refMat2);
+
+ m2.innerVectors(j0,n0) = m2.innerVectors(j0,n0) + m2.innerVectors(j1,n0);
+ if(SparseMatrixType::IsRowMajor)
+ refMat2.middleRows(j0,n0) = (refMat2.middleRows(j0,n0) + refMat2.middleRows(j1,n0)).eval();
+ else
+ refMat2.middleCols(j0,n0) = (refMat2.middleCols(j0,n0) + refMat2.middleCols(j1,n0)).eval();
+
+ VERIFY_IS_APPROX(m2, refMat2);
+
+ }
+
// test basic computations
{
DenseMatrix refM1 = DenseMatrix::Zero(rows, rows);
@@ -193,6 +275,12 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
// sparse cwise* dense
VERIFY_IS_APPROX(m3.cwiseProduct(refM4), refM3.cwiseProduct(refM4));
// VERIFY_IS_APPROX(m3.cwise()/refM4, refM3.cwise()/refM4);
+
+ // test aliasing
+ VERIFY_IS_APPROX((m1 = -m1), (refM1 = -refM1));
+ VERIFY_IS_APPROX((m1 = m1.transpose()), (refM1 = refM1.transpose().eval()));
+ VERIFY_IS_APPROX((m1 = -m1.transpose()), (refM1 = -refM1.transpose().eval()));
+ VERIFY_IS_APPROX((m1 += -m1), (refM1 += -refM1));
}
// test transpose
@@ -206,67 +294,38 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
VERIFY_IS_APPROX(SparseMatrixType(m2.adjoint()), refMat2.adjoint());
}
- // test innerVector()
- {
- DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
- SparseMatrixType m2(rows, rows);
- initSparse<Scalar>(density, refMat2, m2);
- int j0 = internal::random<int>(0,rows-1);
- int j1 = internal::random<int>(0,rows-1);
- if(SparseMatrixType::IsRowMajor)
- VERIFY_IS_APPROX(m2.innerVector(j0), refMat2.row(j0));
- else
- VERIFY_IS_APPROX(m2.innerVector(j0), refMat2.col(j0));
-
- if(SparseMatrixType::IsRowMajor)
- VERIFY_IS_APPROX(m2.innerVector(j0)+m2.innerVector(j1), refMat2.row(j0)+refMat2.row(j1));
- else
- VERIFY_IS_APPROX(m2.innerVector(j0)+m2.innerVector(j1), refMat2.col(j0)+refMat2.col(j1));
-
- SparseMatrixType m3(rows,rows);
- m3.reserve(VectorXi::Constant(rows,rows/2));
- for(int j=0; j<rows; ++j)
- for(int k=0; k<j; ++k)
- m3.insertByOuterInner(j,k) = k+1;
- for(int j=0; j<rows; ++j)
- {
- VERIFY(j==internal::real(m3.innerVector(j).nonZeros()));
- if(j>0)
- VERIFY(j==internal::real(m3.innerVector(j).lastCoeff()));
- }
- m3.makeCompressed();
- for(int j=0; j<rows; ++j)
- {
- VERIFY(j==internal::real(m3.innerVector(j).nonZeros()));
- if(j>0)
- VERIFY(j==internal::real(m3.innerVector(j).lastCoeff()));
- }
-
- //m2.innerVector(j0) = 2*m2.innerVector(j1);
- //refMat2.col(j0) = 2*refMat2.col(j1);
- //VERIFY_IS_APPROX(m2, refMat2);
- }
-
- // test innerVectors()
+
+
+ // test generic blocks
{
DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
SparseMatrixType m2(rows, rows);
initSparse<Scalar>(density, refMat2, m2);
- int j0 = internal::random<int>(0,rows-2);
- int j1 = internal::random<int>(0,rows-2);
- int n0 = internal::random<int>(1,rows-(std::max)(j0,j1));
+ Index j0 = internal::random<Index>(0,rows-2);
+ Index j1 = internal::random<Index>(0,rows-2);
+ Index n0 = internal::random<Index>(1,rows-(std::max)(j0,j1));
if(SparseMatrixType::IsRowMajor)
- VERIFY_IS_APPROX(m2.innerVectors(j0,n0), refMat2.block(j0,0,n0,cols));
+ VERIFY_IS_APPROX(m2.block(j0,0,n0,cols), refMat2.block(j0,0,n0,cols));
else
- VERIFY_IS_APPROX(m2.innerVectors(j0,n0), refMat2.block(0,j0,rows,n0));
+ VERIFY_IS_APPROX(m2.block(0,j0,rows,n0), refMat2.block(0,j0,rows,n0));
+
if(SparseMatrixType::IsRowMajor)
- VERIFY_IS_APPROX(m2.innerVectors(j0,n0)+m2.innerVectors(j1,n0),
+ VERIFY_IS_APPROX(m2.block(j0,0,n0,cols)+m2.block(j1,0,n0,cols),
refMat2.block(j0,0,n0,cols)+refMat2.block(j1,0,n0,cols));
else
- VERIFY_IS_APPROX(m2.innerVectors(j0,n0)+m2.innerVectors(j1,n0),
+ VERIFY_IS_APPROX(m2.block(0,j0,rows,n0)+m2.block(0,j1,rows,n0),
refMat2.block(0,j0,rows,n0)+refMat2.block(0,j1,rows,n0));
- //m2.innerVectors(j0,n0) = m2.innerVectors(j0,n0) + m2.innerVectors(j1,n0);
- //refMat2.block(0,j0,rows,n0) = refMat2.block(0,j0,rows,n0) + refMat2.block(0,j1,rows,n0);
+
+ Index i = internal::random<Index>(0,m2.outerSize()-1);
+ if(SparseMatrixType::IsRowMajor) {
+ m2.innerVector(i) = m2.innerVector(i) * s1;
+ refMat2.row(i) = refMat2.row(i) * s1;
+ VERIFY_IS_APPROX(m2,refMat2);
+ } else {
+ m2.innerVector(i) = m2.innerVector(i) * s1;
+ refMat2.col(i) = refMat2.col(i) * s1;
+ VERIFY_IS_APPROX(m2,refMat2);
+ }
}
// test prune
@@ -276,10 +335,10 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
refM2.setZero();
int countFalseNonZero = 0;
int countTrueNonZero = 0;
- for (int j=0; j<m2.outerSize(); ++j)
+ for (Index j=0; j<m2.outerSize(); ++j)
{
m2.startVec(j);
- for (int i=0; i<m2.innerSize(); ++i)
+ for (Index i=0; i<m2.innerSize(); ++i)
{
float x = internal::random<float>(0,1);
if (x<0.1)
@@ -320,8 +379,8 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
refMat.setZero();
for(int i=0;i<ntriplets;++i)
{
- int r = internal::random<int>(0,rows-1);
- int c = internal::random<int>(0,cols-1);
+ Index r = internal::random<Index>(0,rows-1);
+ Index c = internal::random<Index>(0,cols-1);
Scalar v = internal::random<Scalar>();
triplets.push_back(TripletType(r,c,v));
refMat(r,c) += v;
@@ -351,6 +410,14 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
refMat3 = refMat2.template triangularView<UnitLower>();
m3 = m2.template triangularView<UnitLower>();
VERIFY_IS_APPROX(m3, refMat3);
+
+ refMat3 = refMat2.template triangularView<StrictlyUpper>();
+ m3 = m2.template triangularView<StrictlyUpper>();
+ VERIFY_IS_APPROX(m3, refMat3);
+
+ refMat3 = refMat2.template triangularView<StrictlyLower>();
+ m3 = m2.template triangularView<StrictlyLower>();
+ VERIFY_IS_APPROX(m3, refMat3);
}
// test selfadjointView
@@ -379,17 +446,64 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
initSparse<Scalar>(density, refMat2, m2);
VERIFY_IS_APPROX(m2.diagonal(), refMat2.diagonal().eval());
}
+
+ // test conservative resize
+ {
+ std::vector< std::pair<Index,Index> > inc;
+ inc.push_back(std::pair<Index,Index>(-3,-2));
+ inc.push_back(std::pair<Index,Index>(0,0));
+ inc.push_back(std::pair<Index,Index>(3,2));
+ inc.push_back(std::pair<Index,Index>(3,0));
+ inc.push_back(std::pair<Index,Index>(0,3));
+
+ for(size_t i = 0; i< inc.size(); i++) {
+ Index incRows = inc[i].first;
+ Index incCols = inc[i].second;
+ SparseMatrixType m1(rows, cols);
+ DenseMatrix refMat1 = DenseMatrix::Zero(rows, cols);
+ initSparse<Scalar>(density, refMat1, m1);
+
+ m1.conservativeResize(rows+incRows, cols+incCols);
+ refMat1.conservativeResize(rows+incRows, cols+incCols);
+ if (incRows > 0) refMat1.bottomRows(incRows).setZero();
+ if (incCols > 0) refMat1.rightCols(incCols).setZero();
+
+ VERIFY_IS_APPROX(m1, refMat1);
+
+ // Insert new values
+ if (incRows > 0)
+ m1.insert(m1.rows()-1, 0) = refMat1(refMat1.rows()-1, 0) = 1;
+ if (incCols > 0)
+ m1.insert(0, m1.cols()-1) = refMat1(0, refMat1.cols()-1) = 1;
+
+ VERIFY_IS_APPROX(m1, refMat1);
+
+
+ }
+ }
+
+ // test Identity matrix
+ {
+ DenseMatrix refMat1 = DenseMatrix::Identity(rows, rows);
+ SparseMatrixType m1(rows, rows);
+ m1.setIdentity();
+ VERIFY_IS_APPROX(m1, refMat1);
+ }
}
void test_sparse_basic()
{
for(int i = 0; i < g_repeat; i++) {
int s = Eigen::internal::random<int>(1,50);
+ EIGEN_UNUSED_VARIABLE(s);
CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double>(8, 8)) ));
CALL_SUBTEST_2(( sparse_basic(SparseMatrix<std::complex<double>, ColMajor>(s, s)) ));
CALL_SUBTEST_2(( sparse_basic(SparseMatrix<std::complex<double>, RowMajor>(s, s)) ));
CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double>(s, s)) ));
CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double,ColMajor,long int>(s, s)) ));
CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double,RowMajor,long int>(s, s)) ));
+
+ CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double,ColMajor,short int>(short(s), short(s))) ));
+ CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double,RowMajor,short int>(short(s), short(s))) ));
}
}
diff --git a/test/sparse_product.cpp b/test/sparse_product.cpp
index 17a955c9d..a2ea9d5b7 100644
--- a/test/sparse_product.cpp
+++ b/test/sparse_product.cpp
@@ -13,8 +13,9 @@ template<typename SparseMatrixType, typename DenseMatrix, bool IsRowMajor=Sparse
template<typename SparseMatrixType, typename DenseMatrix> struct test_outer<SparseMatrixType,DenseMatrix,false> {
static void run(SparseMatrixType& m2, SparseMatrixType& m4, DenseMatrix& refMat2, DenseMatrix& refMat4) {
- int c = internal::random(0,m2.cols()-1);
- int c1 = internal::random(0,m2.cols()-1);
+ typedef typename SparseMatrixType::Index Index;
+ Index c = internal::random<Index>(0,m2.cols()-1);
+ Index c1 = internal::random<Index>(0,m2.cols()-1);
VERIFY_IS_APPROX(m4=m2.col(c)*refMat2.col(c1).transpose(), refMat4=refMat2.col(c)*refMat2.col(c1).transpose());
VERIFY_IS_APPROX(m4=refMat2.col(c1)*m2.col(c).transpose(), refMat4=refMat2.col(c1)*refMat2.col(c).transpose());
}
@@ -22,8 +23,9 @@ template<typename SparseMatrixType, typename DenseMatrix> struct test_outer<Spar
template<typename SparseMatrixType, typename DenseMatrix> struct test_outer<SparseMatrixType,DenseMatrix,true> {
static void run(SparseMatrixType& m2, SparseMatrixType& m4, DenseMatrix& refMat2, DenseMatrix& refMat4) {
- int r = internal::random(0,m2.rows()-1);
- int c1 = internal::random(0,m2.cols()-1);
+ typedef typename SparseMatrixType::Index Index;
+ Index r = internal::random<Index>(0,m2.rows()-1);
+ Index c1 = internal::random<Index>(0,m2.cols()-1);
VERIFY_IS_APPROX(m4=m2.row(r).transpose()*refMat2.col(c1).transpose(), refMat4=refMat2.row(r).transpose()*refMat2.col(c1).transpose());
VERIFY_IS_APPROX(m4=refMat2.col(c1)*m2.row(r), refMat4=refMat2.col(c1)*refMat2.row(r));
}
@@ -37,15 +39,18 @@ template<typename SparseMatrixType> void sparse_product()
{
typedef typename SparseMatrixType::Index Index;
Index n = 100;
- const Index rows = internal::random<int>(1,n);
- const Index cols = internal::random<int>(1,n);
- const Index depth = internal::random<int>(1,n);
+ const Index rows = internal::random<Index>(1,n);
+ const Index cols = internal::random<Index>(1,n);
+ const Index depth = internal::random<Index>(1,n);
typedef typename SparseMatrixType::Scalar Scalar;
enum { Flags = SparseMatrixType::Flags };
- double density = (std::max)(8./(rows*cols), 0.01);
+ double density = (std::max)(8./(rows*cols), 0.1);
typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
typedef Matrix<Scalar,Dynamic,1> DenseVector;
+ typedef Matrix<Scalar,1,Dynamic> RowDenseVector;
+ typedef SparseVector<Scalar,0,Index> ColSpVector;
+ typedef SparseVector<Scalar,RowMajor,Index> RowSpVector;
Scalar s1 = internal::random<Scalar>();
Scalar s2 = internal::random<Scalar>();
@@ -117,21 +122,54 @@ template<typename SparseMatrixType> void sparse_product()
test_outer<SparseMatrixType,DenseMatrix>::run(m2,m4,refMat2,refMat4);
VERIFY_IS_APPROX(m6=m6*m6, refMat6=refMat6*refMat6);
+
+ // sparse matrix * sparse vector
+ ColSpVector cv0(cols), cv1;
+ DenseVector dcv0(cols), dcv1;
+ initSparse(2*density,dcv0, cv0);
+
+ RowSpVector rv0(depth), rv1;
+ RowDenseVector drv0(depth), drv1(rv1);
+ initSparse(2*density,drv0, rv0);
+
+ VERIFY_IS_APPROX(cv1=rv0*m3, dcv1=drv0*refMat3);
+ VERIFY_IS_APPROX(rv1=rv0*m3, drv1=drv0*refMat3);
+ VERIFY_IS_APPROX(cv1=m3*cv0, dcv1=refMat3*dcv0);
+ VERIFY_IS_APPROX(cv1=m3t.adjoint()*cv0, dcv1=refMat3t.adjoint()*dcv0);
+ VERIFY_IS_APPROX(rv1=m3*cv0, drv1=refMat3*dcv0);
}
-
+
// test matrix - diagonal product
{
- DenseMatrix refM2 = DenseMatrix::Zero(rows, rows);
- DenseMatrix refM3 = DenseMatrix::Zero(rows, rows);
- DiagonalMatrix<Scalar,Dynamic> d1(DenseVector::Random(rows));
- SparseMatrixType m2(rows, rows);
- SparseMatrixType m3(rows, rows);
+ DenseMatrix refM2 = DenseMatrix::Zero(rows, cols);
+ DenseMatrix refM3 = DenseMatrix::Zero(rows, cols);
+ DenseMatrix d3 = DenseMatrix::Zero(rows, cols);
+ DiagonalMatrix<Scalar,Dynamic> d1(DenseVector::Random(cols));
+ DiagonalMatrix<Scalar,Dynamic> d2(DenseVector::Random(rows));
+ SparseMatrixType m2(rows, cols);
+ SparseMatrixType m3(rows, cols);
initSparse<Scalar>(density, refM2, m2);
initSparse<Scalar>(density, refM3, m3);
VERIFY_IS_APPROX(m3=m2*d1, refM3=refM2*d1);
- VERIFY_IS_APPROX(m3=m2.transpose()*d1, refM3=refM2.transpose()*d1);
- VERIFY_IS_APPROX(m3=d1*m2, refM3=d1*refM2);
- VERIFY_IS_APPROX(m3=d1*m2.transpose(), refM3=d1 * refM2.transpose());
+ VERIFY_IS_APPROX(m3=m2.transpose()*d2, refM3=refM2.transpose()*d2);
+ VERIFY_IS_APPROX(m3=d2*m2, refM3=d2*refM2);
+ VERIFY_IS_APPROX(m3=d1*m2.transpose(), refM3=d1*refM2.transpose());
+
+ // also check with a SparseWrapper:
+ DenseVector v1 = DenseVector::Random(cols);
+ DenseVector v2 = DenseVector::Random(rows);
+ VERIFY_IS_APPROX(m3=m2*v1.asDiagonal(), refM3=refM2*v1.asDiagonal());
+ VERIFY_IS_APPROX(m3=m2.transpose()*v2.asDiagonal(), refM3=refM2.transpose()*v2.asDiagonal());
+ VERIFY_IS_APPROX(m3=v2.asDiagonal()*m2, refM3=v2.asDiagonal()*refM2);
+ VERIFY_IS_APPROX(m3=v1.asDiagonal()*m2.transpose(), refM3=v1.asDiagonal()*refM2.transpose());
+
+ VERIFY_IS_APPROX(m3=v2.asDiagonal()*m2*v1.asDiagonal(), refM3=v2.asDiagonal()*refM2*v1.asDiagonal());
+
+ // evaluate to a dense matrix to check the .row() and .col() iterator functions
+ VERIFY_IS_APPROX(d3=m2*d1, refM3=refM2*d1);
+ VERIFY_IS_APPROX(d3=m2.transpose()*d2, refM3=refM2.transpose()*d2);
+ VERIFY_IS_APPROX(d3=d2*m2, refM3=d2*refM2);
+ VERIFY_IS_APPROX(d3=d1*m2.transpose(), refM3=d1*refM2.transpose());
}
// test self adjoint products
@@ -167,7 +205,16 @@ template<typename SparseMatrixType> void sparse_product()
VERIFY_IS_APPROX(x=mUp.template selfadjointView<Upper>()*b, refX=refS*b);
VERIFY_IS_APPROX(x=mLo.template selfadjointView<Lower>()*b, refX=refS*b);
VERIFY_IS_APPROX(x=mS.template selfadjointView<Upper|Lower>()*b, refX=refS*b);
+
+ // sparse selfadjointView * sparse
+ SparseMatrixType mSres(rows,rows);
+ VERIFY_IS_APPROX(mSres = mLo.template selfadjointView<Lower>()*mS,
+ refX = refLo.template selfadjointView<Lower>()*refS);
+ // sparse * sparse selfadjointview
+ VERIFY_IS_APPROX(mSres = mS * mLo.template selfadjointView<Lower>(),
+ refX = refS * refLo.template selfadjointView<Lower>());
}
+
}
// New test for Bug in SparseTimeDenseProduct
@@ -199,6 +246,7 @@ void test_sparse_product()
CALL_SUBTEST_1( (sparse_product<SparseMatrix<double,RowMajor> >()) );
CALL_SUBTEST_2( (sparse_product<SparseMatrix<std::complex<double>, ColMajor > >()) );
CALL_SUBTEST_2( (sparse_product<SparseMatrix<std::complex<double>, RowMajor > >()) );
+ CALL_SUBTEST_3( (sparse_product<SparseMatrix<float,ColMajor,long int> >()) );
CALL_SUBTEST_4( (sparse_product_regression_test<SparseMatrix<double,RowMajor>, Matrix<double, Dynamic, Dynamic, RowMajor> >()) );
}
}
diff --git a/test/sparse_solver.h b/test/sparse_solver.h
index 75fa85082..d84aff070 100644
--- a/test/sparse_solver.h
+++ b/test/sparse_solver.h
@@ -17,54 +17,54 @@ void check_sparse_solving(Solver& solver, const typename Solver::MatrixType& A,
typedef typename Mat::Scalar Scalar;
DenseRhs refX = dA.lu().solve(db);
-
- Rhs x(b.rows(), b.cols());
- Rhs oldb = b;
-
- solver.compute(A);
- if (solver.info() != Success)
{
- std::cerr << "sparse solver testing: factorization failed (check_sparse_solving)\n";
- exit(0);
- return;
- }
- x = solver.solve(b);
- if (solver.info() != Success)
- {
- std::cerr << "sparse solver testing: solving failed\n";
- return;
- }
- VERIFY(oldb.isApprox(b) && "sparse solver testing: the rhs should not be modified!");
+ Rhs x(b.rows(), b.cols());
+ Rhs oldb = b;
+
+ solver.compute(A);
+ if (solver.info() != Success)
+ {
+ std::cerr << "sparse solver testing: factorization failed (check_sparse_solving)\n";
+ exit(0);
+ return;
+ }
+ x = solver.solve(b);
+ if (solver.info() != Success)
+ {
+ std::cerr << "sparse solver testing: solving failed\n";
+ return;
+ }
+ VERIFY(oldb.isApprox(b) && "sparse solver testing: the rhs should not be modified!");
- VERIFY(x.isApprox(refX,test_precision<Scalar>()));
-
- x.setZero();
- // test the analyze/factorize API
- solver.analyzePattern(A);
- solver.factorize(A);
- if (solver.info() != Success)
- {
- std::cerr << "sparse solver testing: factorization failed (check_sparse_solving)\n";
- exit(0);
- return;
- }
- x = solver.solve(b);
- if (solver.info() != Success)
- {
- std::cerr << "sparse solver testing: solving failed\n";
- return;
- }
- VERIFY(oldb.isApprox(b) && "sparse solver testing: the rhs should not be modified!");
+ VERIFY(x.isApprox(refX,test_precision<Scalar>()));
+ x.setZero();
+ // test the analyze/factorize API
+ solver.analyzePattern(A);
+ solver.factorize(A);
+ if (solver.info() != Success)
+ {
+ std::cerr << "sparse solver testing: factorization failed (check_sparse_solving)\n";
+ exit(0);
+ return;
+ }
+ x = solver.solve(b);
+ if (solver.info() != Success)
+ {
+ std::cerr << "sparse solver testing: solving failed\n";
+ return;
+ }
+ VERIFY(oldb.isApprox(b) && "sparse solver testing: the rhs should not be modified!");
- VERIFY(x.isApprox(refX,test_precision<Scalar>()));
+ VERIFY(x.isApprox(refX,test_precision<Scalar>()));
+ }
- // test Block as the result and rhs:
+ // test dense Block as the result and rhs:
{
DenseRhs x(db.rows(), db.cols());
- DenseRhs b(db), oldb(db);
+ DenseRhs oldb(db);
x.setZero();
- x.block(0,0,x.rows(),x.cols()) = solver.solve(b.block(0,0,b.rows(),b.cols()));
- VERIFY(oldb.isApprox(b) && "sparse solver testing: the rhs should not be modified!");
+ x.block(0,0,x.rows(),x.cols()) = solver.solve(db.block(0,0,db.rows(),db.cols()));
+ VERIFY(oldb.isApprox(db) && "sparse solver testing: the rhs should not be modified!");
VERIFY(x.isApprox(refX,test_precision<Scalar>()));
}
}
@@ -113,7 +113,6 @@ void check_sparse_determinant(Solver& solver, const typename Solver::MatrixType&
{
typedef typename Solver::MatrixType Mat;
typedef typename Mat::Scalar Scalar;
- typedef typename Mat::RealScalar RealScalar;
solver.compute(A);
if (solver.info() != Success)
@@ -158,9 +157,9 @@ inline std::string get_matrixfolder()
{
std::string mat_folder = TEST_REAL_CASES;
if( internal::is_same<Scalar, std::complex<float> >::value || internal::is_same<Scalar, std::complex<double> >::value )
- mat_folder = mat_folder + static_cast<string>("/complex/");
+ mat_folder = mat_folder + static_cast<std::string>("/complex/");
else
- mat_folder = mat_folder + static_cast<string>("/real/");
+ mat_folder = mat_folder + static_cast<std::string>("/real/");
return mat_folder;
}
#endif
@@ -169,7 +168,6 @@ template<typename Solver> void check_sparse_spd_solving(Solver& solver)
{
typedef typename Solver::MatrixType Mat;
typedef typename Mat::Scalar Scalar;
- typedef typename Mat::Index Index;
typedef SparseMatrix<Scalar,ColMajor> SpMat;
typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
typedef Matrix<Scalar,Dynamic,1> DenseVector;
@@ -177,25 +175,32 @@ template<typename Solver> void check_sparse_spd_solving(Solver& solver)
// generate the problem
Mat A, halfA;
DenseMatrix dA;
- int size = generate_sparse_spd_problem(solver, A, halfA, dA);
-
- // generate the right hand sides
- int rhsCols = internal::random<int>(1,16);
- double density = (std::max)(8./(size*rhsCols), 0.1);
- SpMat B(size,rhsCols);
- DenseVector b = DenseVector::Random(size);
- DenseMatrix dB(size,rhsCols);
- initSparse<Scalar>(density, dB, B, ForceNonZeroDiag);
-
for (int i = 0; i < g_repeat; i++) {
+ int size = generate_sparse_spd_problem(solver, A, halfA, dA);
+
+ // generate the right hand sides
+ int rhsCols = internal::random<int>(1,16);
+ double density = (std::max)(8./(size*rhsCols), 0.1);
+ SpMat B(size,rhsCols);
+ DenseVector b = DenseVector::Random(size);
+ DenseMatrix dB(size,rhsCols);
+ initSparse<Scalar>(density, dB, B, ForceNonZeroDiag);
+
check_sparse_solving(solver, A, b, dA, b);
check_sparse_solving(solver, halfA, b, dA, b);
check_sparse_solving(solver, A, dB, dA, dB);
check_sparse_solving(solver, halfA, dB, dA, dB);
check_sparse_solving(solver, A, B, dA, dB);
check_sparse_solving(solver, halfA, B, dA, dB);
+
+ // check only once
+ if(i==0)
+ {
+ b = DenseVector::Zero(size);
+ check_sparse_solving(solver, A, b, dA, b);
+ }
}
-
+
// First, get the folder
#ifdef TEST_REAL_CASES
if (internal::is_same<Scalar, float>::value
@@ -241,7 +246,6 @@ int generate_sparse_square_problem(Solver&, typename Solver::MatrixType& A, Dens
{
typedef typename Solver::MatrixType Mat;
typedef typename Mat::Scalar Scalar;
- typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
int size = internal::random<int>(1,maxSize);
double density = (std::max)(8./(size*size), 0.01);
@@ -258,6 +262,7 @@ template<typename Solver> void check_sparse_square_solving(Solver& solver)
{
typedef typename Solver::MatrixType Mat;
typedef typename Mat::Scalar Scalar;
+ typedef SparseMatrix<Scalar,ColMajor> SpMat;
typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
typedef Matrix<Scalar,Dynamic,1> DenseVector;
@@ -265,16 +270,28 @@ template<typename Solver> void check_sparse_square_solving(Solver& solver)
Mat A;
DenseMatrix dA;
- int size = generate_sparse_square_problem(solver, A, dA);
-
- DenseVector b = DenseVector::Random(size);
- DenseMatrix dB = DenseMatrix::Random(size,rhsCols);
- A.makeCompressed();
for (int i = 0; i < g_repeat; i++) {
+ int size = generate_sparse_square_problem(solver, A, dA);
+
+ A.makeCompressed();
+ DenseVector b = DenseVector::Random(size);
+ DenseMatrix dB(size,rhsCols);
+ SpMat B(size,rhsCols);
+ double density = (std::max)(8./(size*rhsCols), 0.1);
+ initSparse<Scalar>(density, dB, B, ForceNonZeroDiag);
+ B.makeCompressed();
check_sparse_solving(solver, A, b, dA, b);
check_sparse_solving(solver, A, dB, dA, dB);
+ check_sparse_solving(solver, A, B, dA, dB);
+
+ // check only once
+ if(i==0)
+ {
+ b = DenseVector::Zero(size);
+ check_sparse_solving(solver, A, b, dA, b);
+ }
}
-
+
// First, get the folder
#ifdef TEST_REAL_CASES
if (internal::is_same<Scalar, float>::value
diff --git a/test/sparse_vector.cpp b/test/sparse_vector.cpp
index 7201afe5b..0c9476803 100644
--- a/test/sparse_vector.cpp
+++ b/test/sparse_vector.cpp
@@ -9,14 +9,14 @@
#include "sparse.h"
-template<typename Scalar> void sparse_vector(int rows, int cols)
+template<typename Scalar,typename Index> void sparse_vector(int rows, int cols)
{
double densityMat = (std::max)(8./(rows*cols), 0.01);
double densityVec = (std::max)(8./float(rows), 0.1);
typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
typedef Matrix<Scalar,Dynamic,1> DenseVector;
- typedef SparseVector<Scalar> SparseVectorType;
- typedef SparseMatrix<Scalar> SparseMatrixType;
+ typedef SparseVector<Scalar,0,Index> SparseVectorType;
+ typedef SparseMatrix<Scalar,0,Index> SparseMatrixType;
Scalar eps = 1e-6;
SparseMatrixType m1(rows,rows);
@@ -77,15 +77,34 @@ template<typename Scalar> void sparse_vector(int rows, int cols)
VERIFY_IS_APPROX(v1.squaredNorm(), refV1.squaredNorm());
+
+ VERIFY_IS_APPROX(v1.blueNorm(), refV1.blueNorm());
+
+ // test aliasing
+ VERIFY_IS_APPROX((v1 = -v1), (refV1 = -refV1));
+ VERIFY_IS_APPROX((v1 = v1.transpose()), (refV1 = refV1.transpose().eval()));
+ VERIFY_IS_APPROX((v1 += -v1), (refV1 += -refV1));
+
+ // sparse matrix to sparse vector
+ SparseMatrixType mv1;
+ VERIFY_IS_APPROX((mv1=v1),v1);
+ VERIFY_IS_APPROX(mv1,(v1=mv1));
+ VERIFY_IS_APPROX(mv1,(v1=mv1.transpose()));
+
+ // check copy to dense vector with transpose
+ refV3.resize(0);
+ VERIFY_IS_APPROX(refV3 = v1.transpose(),v1.toDense());
+ VERIFY_IS_APPROX(DenseVector(v1),v1.toDense());
}
void test_sparse_vector()
{
for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( sparse_vector<double>(8, 8) );
- CALL_SUBTEST_2( sparse_vector<std::complex<double> >(16, 16) );
- CALL_SUBTEST_1( sparse_vector<double>(299, 535) );
+ CALL_SUBTEST_1(( sparse_vector<double,int>(8, 8) ));
+ CALL_SUBTEST_2(( sparse_vector<std::complex<double>, int>(16, 16) ));
+ CALL_SUBTEST_1(( sparse_vector<double,long int>(299, 535) ));
+ CALL_SUBTEST_1(( sparse_vector<double,short>(299, 535) ));
}
}
diff --git a/test/sparselu.cpp b/test/sparselu.cpp
new file mode 100644
index 000000000..37980defc
--- /dev/null
+++ b/test/sparselu.cpp
@@ -0,0 +1,55 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// Eigen is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 3 of the License, or (at your option) any later version.
+//
+// Alternatively, you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+
+// SparseLU solve does not accept column major matrices for the destination.
+// However, as expected, the generic check_sparse_square_solving routines produces row-major
+// rhs and destination matrices when compiled with EIGEN_DEFAULT_TO_ROW_MAJOR
+
+#ifdef EIGEN_DEFAULT_TO_ROW_MAJOR
+#undef EIGEN_DEFAULT_TO_ROW_MAJOR
+#endif
+
+#include "sparse_solver.h"
+#include <Eigen/SparseLU>
+#include <unsupported/Eigen/SparseExtra>
+
+template<typename T> void test_sparselu_T()
+{
+ SparseLU<SparseMatrix<T, ColMajor> /*, COLAMDOrdering<int>*/ > sparselu_colamd; // COLAMDOrdering is the default
+ SparseLU<SparseMatrix<T, ColMajor>, AMDOrdering<int> > sparselu_amd;
+ SparseLU<SparseMatrix<T, ColMajor, long int>, NaturalOrdering<long int> > sparselu_natural;
+
+ check_sparse_square_solving(sparselu_colamd);
+ check_sparse_square_solving(sparselu_amd);
+ check_sparse_square_solving(sparselu_natural);
+}
+
+void test_sparselu()
+{
+ CALL_SUBTEST_1(test_sparselu_T<float>());
+ CALL_SUBTEST_2(test_sparselu_T<double>());
+ CALL_SUBTEST_3(test_sparselu_T<std::complex<float> >());
+ CALL_SUBTEST_4(test_sparselu_T<std::complex<double> >());
+}
diff --git a/test/sparseqr.cpp b/test/sparseqr.cpp
new file mode 100644
index 000000000..1fe4a98ee
--- /dev/null
+++ b/test/sparseqr.cpp
@@ -0,0 +1,99 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Desire Nuentsa Wakam <desire.nuentsa_wakam@inria.fr>
+// Copyright (C) 2014 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+#include "sparse.h"
+#include <Eigen/SparseQR>
+
+template<typename MatrixType,typename DenseMat>
+int generate_sparse_rectangular_problem(MatrixType& A, DenseMat& dA, int maxRows = 300, int maxCols = 150)
+{
+ eigen_assert(maxRows >= maxCols);
+ typedef typename MatrixType::Scalar Scalar;
+ int rows = internal::random<int>(1,maxRows);
+ int cols = internal::random<int>(1,maxCols);
+ double density = (std::max)(8./(rows*cols), 0.01);
+
+ A.resize(rows,cols);
+ dA.resize(rows,cols);
+ initSparse<Scalar>(density, dA, A,ForceNonZeroDiag);
+ A.makeCompressed();
+ int nop = internal::random<int>(0, internal::random<double>(0,1) > 0.5 ? cols/2 : 0);
+ for(int k=0; k<nop; ++k)
+ {
+ int j0 = internal::random<int>(0,cols-1);
+ int j1 = internal::random<int>(0,cols-1);
+ Scalar s = internal::random<Scalar>();
+ A.col(j0) = s * A.col(j1);
+ dA.col(j0) = s * dA.col(j1);
+ }
+
+// if(rows<cols) {
+// A.conservativeResize(cols,cols);
+// dA.conservativeResize(cols,cols);
+// dA.bottomRows(cols-rows).setZero();
+// }
+
+ return rows;
+}
+
+template<typename Scalar> void test_sparseqr_scalar()
+{
+ typedef SparseMatrix<Scalar,ColMajor> MatrixType;
+ typedef Matrix<Scalar,Dynamic,Dynamic> DenseMat;
+ typedef Matrix<Scalar,Dynamic,1> DenseVector;
+ MatrixType A;
+ DenseMat dA;
+ DenseVector refX,x,b;
+ SparseQR<MatrixType, COLAMDOrdering<int> > solver;
+ generate_sparse_rectangular_problem(A,dA);
+
+ b = dA * DenseVector::Random(A.cols());
+ solver.compute(A);
+ if (solver.info() != Success)
+ {
+ std::cerr << "sparse QR factorization failed\n";
+ exit(0);
+ return;
+ }
+ x = solver.solve(b);
+ if (solver.info() != Success)
+ {
+ std::cerr << "sparse QR factorization failed\n";
+ exit(0);
+ return;
+ }
+
+ VERIFY_IS_APPROX(A * x, b);
+
+ //Compare with a dense QR solver
+ ColPivHouseholderQR<DenseMat> dqr(dA);
+ refX = dqr.solve(b);
+
+ VERIFY_IS_EQUAL(dqr.rank(), solver.rank());
+ if(solver.rank()==A.cols()) // full rank
+ VERIFY_IS_APPROX(x, refX);
+// else
+// VERIFY((dA * refX - b).norm() * 2 > (A * x - b).norm() );
+
+ // Compute explicitly the matrix Q
+ MatrixType Q, QtQ, idM;
+ Q = solver.matrixQ();
+ //Check ||Q' * Q - I ||
+ QtQ = Q * Q.adjoint();
+ idM.resize(Q.rows(), Q.rows()); idM.setIdentity();
+ VERIFY(idM.isApprox(QtQ));
+}
+void test_sparseqr()
+{
+ for(int i=0; i<g_repeat; ++i)
+ {
+ CALL_SUBTEST_1(test_sparseqr_scalar<double>());
+ CALL_SUBTEST_2(test_sparseqr_scalar<std::complex<double> >());
+ }
+}
+
diff --git a/test/special_numbers.cpp b/test/special_numbers.cpp
new file mode 100644
index 000000000..2f1b704be
--- /dev/null
+++ b/test/special_numbers.cpp
@@ -0,0 +1,58 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2013 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename Scalar> void special_numbers()
+{
+ typedef Matrix<Scalar, Dynamic,Dynamic> MatType;
+ int rows = internal::random<int>(1,300);
+ int cols = internal::random<int>(1,300);
+
+ Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
+ Scalar inf = std::numeric_limits<Scalar>::infinity();
+ Scalar s1 = internal::random<Scalar>();
+
+ MatType m1 = MatType::Random(rows,cols),
+ mnan = MatType::Random(rows,cols),
+ minf = MatType::Random(rows,cols),
+ mboth = MatType::Random(rows,cols);
+
+ int n = internal::random<int>(1,10);
+ for(int k=0; k<n; ++k)
+ {
+ mnan(internal::random<int>(0,rows-1), internal::random<int>(0,cols-1)) = nan;
+ minf(internal::random<int>(0,rows-1), internal::random<int>(0,cols-1)) = inf;
+ }
+ mboth = mnan + minf;
+
+ VERIFY(!m1.hasNaN());
+ VERIFY(m1.allFinite());
+
+ VERIFY(mnan.hasNaN());
+ VERIFY((s1*mnan).hasNaN());
+ VERIFY(!minf.hasNaN());
+ VERIFY(!(2*minf).hasNaN());
+ VERIFY(mboth.hasNaN());
+ VERIFY(mboth.array().hasNaN());
+
+ VERIFY(!mnan.allFinite());
+ VERIFY(!minf.allFinite());
+ VERIFY(!(minf-mboth).allFinite());
+ VERIFY(!mboth.allFinite());
+ VERIFY(!mboth.array().allFinite());
+}
+
+void test_special_numbers()
+{
+ for(int i = 0; i < 10*g_repeat; i++) {
+ CALL_SUBTEST_1( special_numbers<float>() );
+ CALL_SUBTEST_1( special_numbers<double>() );
+ }
+}
diff --git a/test/spqr_support.cpp b/test/spqr_support.cpp
new file mode 100644
index 000000000..b8980e081
--- /dev/null
+++ b/test/spqr_support.cpp
@@ -0,0 +1,62 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Desire Nuentsa Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+#include "sparse.h"
+#include <Eigen/SPQRSupport>
+
+
+template<typename MatrixType,typename DenseMat>
+int generate_sparse_rectangular_problem(MatrixType& A, DenseMat& dA, int maxRows = 300, int maxCols = 300)
+{
+ eigen_assert(maxRows >= maxCols);
+ typedef typename MatrixType::Scalar Scalar;
+ int rows = internal::random<int>(1,maxRows);
+ int cols = internal::random<int>(1,rows);
+ double density = (std::max)(8./(rows*cols), 0.01);
+
+ A.resize(rows,rows);
+ dA.resize(rows,rows);
+ initSparse<Scalar>(density, dA, A,ForceNonZeroDiag);
+ A.makeCompressed();
+ return rows;
+}
+
+template<typename Scalar> void test_spqr_scalar()
+{
+ typedef SparseMatrix<Scalar,ColMajor> MatrixType;
+ MatrixType A;
+ Matrix<Scalar,Dynamic,Dynamic> dA;
+ typedef Matrix<Scalar,Dynamic,1> DenseVector;
+ DenseVector refX,x,b;
+ SPQR<MatrixType> solver;
+ generate_sparse_rectangular_problem(A,dA);
+
+ int m = A.rows();
+ b = DenseVector::Random(m);
+ solver.compute(A);
+ if (solver.info() != Success)
+ {
+ std::cerr << "sparse QR factorization failed\n";
+ exit(0);
+ return;
+ }
+ x = solver.solve(b);
+ if (solver.info() != Success)
+ {
+ std::cerr << "sparse QR factorization failed\n";
+ exit(0);
+ return;
+ }
+ //Compare with a dense solver
+ refX = dA.colPivHouseholderQr().solve(b);
+ VERIFY(x.isApprox(refX,test_precision<Scalar>()));
+}
+void test_spqr_support()
+{
+ CALL_SUBTEST_1(test_spqr_scalar<double>());
+ CALL_SUBTEST_2(test_spqr_scalar<std::complex<double> >());
+}
diff --git a/test/stable_norm.cpp b/test/stable_norm.cpp
index a25dbf51c..549f91fbf 100644
--- a/test/stable_norm.cpp
+++ b/test/stable_norm.cpp
@@ -32,6 +32,8 @@ template<typename MatrixType> void stable_norm(const MatrixType& m)
/* this test covers the following files:
StableNorm.h
*/
+ using std::sqrt;
+ using std::abs;
typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
@@ -53,8 +55,16 @@ template<typename MatrixType> void stable_norm(const MatrixType& m)
Index rows = m.rows();
Index cols = m.cols();
- Scalar big = internal::random<Scalar>() * ((std::numeric_limits<RealScalar>::max)() * RealScalar(1e-4));
- Scalar small = internal::random<Scalar>() * ((std::numeric_limits<RealScalar>::min)() * RealScalar(1e4));
+ // get a non-zero random factor
+ Scalar factor = internal::random<Scalar>();
+ while(numext::abs2(factor)<RealScalar(1e-4))
+ factor = internal::random<Scalar>();
+ Scalar big = factor * ((std::numeric_limits<RealScalar>::max)() * RealScalar(1e-4));
+
+ factor = internal::random<Scalar>();
+ while(numext::abs2(factor)<RealScalar(1e-4))
+ factor = internal::random<Scalar>();
+ Scalar small = factor * ((std::numeric_limits<RealScalar>::min)() * RealScalar(1e4));
MatrixType vzero = MatrixType::Zero(rows, cols),
vrand = MatrixType::Random(rows, cols),
@@ -73,23 +83,23 @@ template<typename MatrixType> void stable_norm(const MatrixType& m)
// test isFinite
VERIFY(!isFinite( std::numeric_limits<RealScalar>::infinity()));
- VERIFY(!isFinite(internal::sqrt(-internal::abs(big))));
+ VERIFY(!isFinite(sqrt(-abs(big))));
// test overflow
- VERIFY(isFinite(internal::sqrt(size)*internal::abs(big)));
- VERIFY_IS_NOT_APPROX(internal::sqrt(copy(vbig.squaredNorm())), internal::abs(internal::sqrt(size)*big)); // here the default norm must fail
- VERIFY_IS_APPROX(vbig.stableNorm(), internal::sqrt(size)*internal::abs(big));
- VERIFY_IS_APPROX(vbig.blueNorm(), internal::sqrt(size)*internal::abs(big));
- VERIFY_IS_APPROX(vbig.hypotNorm(), internal::sqrt(size)*internal::abs(big));
+ VERIFY(isFinite(sqrt(size)*abs(big)));
+ VERIFY_IS_NOT_APPROX(sqrt(copy(vbig.squaredNorm())), abs(sqrt(size)*big)); // here the default norm must fail
+ VERIFY_IS_APPROX(vbig.stableNorm(), sqrt(size)*abs(big));
+ VERIFY_IS_APPROX(vbig.blueNorm(), sqrt(size)*abs(big));
+ VERIFY_IS_APPROX(vbig.hypotNorm(), sqrt(size)*abs(big));
// test underflow
- VERIFY(isFinite(internal::sqrt(size)*internal::abs(small)));
- VERIFY_IS_NOT_APPROX(internal::sqrt(copy(vsmall.squaredNorm())), internal::abs(internal::sqrt(size)*small)); // here the default norm must fail
- VERIFY_IS_APPROX(vsmall.stableNorm(), internal::sqrt(size)*internal::abs(small));
- VERIFY_IS_APPROX(vsmall.blueNorm(), internal::sqrt(size)*internal::abs(small));
- VERIFY_IS_APPROX(vsmall.hypotNorm(), internal::sqrt(size)*internal::abs(small));
+ VERIFY(isFinite(sqrt(size)*abs(small)));
+ VERIFY_IS_NOT_APPROX(sqrt(copy(vsmall.squaredNorm())), abs(sqrt(size)*small)); // here the default norm must fail
+ VERIFY_IS_APPROX(vsmall.stableNorm(), sqrt(size)*abs(small));
+ VERIFY_IS_APPROX(vsmall.blueNorm(), sqrt(size)*abs(small));
+ VERIFY_IS_APPROX(vsmall.hypotNorm(), sqrt(size)*abs(small));
-// Test compilation of cwise() version
+ // Test compilation of cwise() version
VERIFY_IS_APPROX(vrand.colwise().stableNorm(), vrand.colwise().norm());
VERIFY_IS_APPROX(vrand.colwise().blueNorm(), vrand.colwise().norm());
VERIFY_IS_APPROX(vrand.colwise().hypotNorm(), vrand.colwise().norm());
diff --git a/test/triangular.cpp b/test/triangular.cpp
index 0e8ee5487..54320390b 100644
--- a/test/triangular.cpp
+++ b/test/triangular.cpp
@@ -65,7 +65,7 @@ template<typename MatrixType> void triangular_square(const MatrixType& m)
m1 = MatrixType::Random(rows, cols);
for (int i=0; i<rows; ++i)
- while (internal::abs2(m1(i,i))<1e-1) m1(i,i) = internal::random<Scalar>();
+ while (numext::abs2(m1(i,i))<1e-1) m1(i,i) = internal::random<Scalar>();
Transpose<MatrixType> trm4(m4);
// test back and forward subsitution with a vector as the rhs
@@ -123,9 +123,6 @@ template<typename MatrixType> void triangular_rect(const MatrixType& m)
typedef typename MatrixType::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime };
- typedef Matrix<Scalar, Rows, 1> VectorType;
- typedef Matrix<Scalar, Rows, Rows> RMatrixType;
-
Index rows = m.rows();
Index cols = m.cols();
@@ -214,8 +211,8 @@ void test_triangular()
int maxsize = (std::min)(EIGEN_TEST_MAX_SIZE,20);
for(int i = 0; i < g_repeat ; i++)
{
- int r = internal::random<int>(2,maxsize); EIGEN_UNUSED_VARIABLE(r);
- int c = internal::random<int>(2,maxsize); EIGEN_UNUSED_VARIABLE(c);
+ int r = internal::random<int>(2,maxsize); TEST_SET_BUT_UNUSED_VARIABLE(r)
+ int c = internal::random<int>(2,maxsize); TEST_SET_BUT_UNUSED_VARIABLE(c)
CALL_SUBTEST_1( triangular_square(Matrix<float, 1, 1>()) );
CALL_SUBTEST_2( triangular_square(Matrix<float, 2, 2>()) );
diff --git a/test/umeyama.cpp b/test/umeyama.cpp
index b6c9be3a5..2e8092434 100644
--- a/test/umeyama.cpp
+++ b/test/umeyama.cpp
@@ -22,8 +22,6 @@ template <typename T>
Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> randMatrixUnitary(int size)
{
typedef T Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
-
typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> MatrixType;
MatrixType Q;
@@ -77,7 +75,6 @@ template <typename T>
Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> randMatrixSpecialUnitary(int size)
{
typedef T Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> MatrixType;
@@ -85,7 +82,7 @@ Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> randMatrixSpecialUnitary(int si
MatrixType Q = randMatrixUnitary<Scalar>(size);
// tweak the first column to make the determinant be 1
- Q.col(0) *= internal::conj(Q.determinant());
+ Q.col(0) *= numext::conj(Q.determinant());
return Q;
}
@@ -93,13 +90,14 @@ Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> randMatrixSpecialUnitary(int si
template <typename MatrixType>
void run_test(int dim, int num_elements)
{
+ using std::abs;
typedef typename internal::traits<MatrixType>::Scalar Scalar;
typedef Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> MatrixX;
typedef Matrix<Scalar, Eigen::Dynamic, 1> VectorX;
// MUST be positive because in any other case det(cR_t) may become negative for
// odd dimensions!
- const Scalar c = internal::abs(internal::random<Scalar>());
+ const Scalar c = abs(internal::random<Scalar>());
MatrixX R = randMatrixSpecialUnitary<Scalar>(dim);
VectorX t = Scalar(50)*VectorX::Random(dim,1);
@@ -122,6 +120,7 @@ void run_test(int dim, int num_elements)
template<typename Scalar, int Dimension>
void run_fixed_size_test(int num_elements)
{
+ using std::abs;
typedef Matrix<Scalar, Dimension+1, Dynamic> MatrixX;
typedef Matrix<Scalar, Dimension+1, Dimension+1> HomMatrix;
typedef Matrix<Scalar, Dimension, Dimension> FixedMatrix;
@@ -131,10 +130,11 @@ void run_fixed_size_test(int num_elements)
// MUST be positive because in any other case det(cR_t) may become negative for
// odd dimensions!
- const Scalar c = internal::abs(internal::random<Scalar>());
+ // Also if c is to small compared to t.norm(), problem is ill-posed (cf. Bug 744)
+ const Scalar c = internal::random<Scalar>(0.5, 2.0);
FixedMatrix R = randMatrixSpecialUnitary<Scalar>(dim);
- FixedVector t = Scalar(50)*FixedVector::Random(dim,1);
+ FixedVector t = Scalar(32)*FixedVector::Random(dim,1);
HomMatrix cR_t = HomMatrix::Identity(dim+1,dim+1);
cR_t.block(0,0,dim,dim) = c*R;
@@ -150,9 +150,9 @@ void run_fixed_size_test(int num_elements)
HomMatrix cR_t_umeyama = umeyama(src_block, dst_block);
- const Scalar error = ( cR_t_umeyama*src - dst ).array().square().sum();
+ const Scalar error = ( cR_t_umeyama*src - dst ).squaredNorm();
- VERIFY(error < Scalar(10)*std::numeric_limits<Scalar>::epsilon());
+ VERIFY(error < Scalar(16)*std::numeric_limits<Scalar>::epsilon());
}
void test_umeyama()
diff --git a/test/unalignedcount.cpp b/test/unalignedcount.cpp
index 5451159e6..ca7e159f3 100644
--- a/test/unalignedcount.cpp
+++ b/test/unalignedcount.cpp
@@ -40,5 +40,7 @@ void test_unalignedcount()
#else
// The following line is to eliminate "variable not used" warnings
nb_load = nb_loadu = nb_store = nb_storeu = 0;
+ int a(0), b(0);
+ VERIFY(a==b);
#endif
}
diff --git a/test/upperbidiagonalization.cpp b/test/upperbidiagonalization.cpp
index db6ce383e..d15bf588b 100644
--- a/test/upperbidiagonalization.cpp
+++ b/test/upperbidiagonalization.cpp
@@ -15,8 +15,8 @@ template<typename MatrixType> void upperbidiag(const MatrixType& m)
const typename MatrixType::Index rows = m.rows();
const typename MatrixType::Index cols = m.cols();
- typedef typename MatrixType::Scalar Scalar;
typedef Matrix<typename MatrixType::RealScalar, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime> RealMatrixType;
+ typedef Matrix<typename MatrixType::Scalar, MatrixType::ColsAtCompileTime, MatrixType::RowsAtCompileTime> TransposeMatrixType;
MatrixType a = MatrixType::Random(rows,cols);
internal::UpperBidiagonalization<MatrixType> ubd(a);
@@ -25,6 +25,8 @@ template<typename MatrixType> void upperbidiag(const MatrixType& m)
b.block(0,0,cols,cols) = ubd.bidiagonal();
MatrixType c = ubd.householderU() * b * ubd.householderV().adjoint();
VERIFY_IS_APPROX(a,c);
+ TransposeMatrixType d = ubd.householderV() * b.adjoint() * ubd.householderU().adjoint();
+ VERIFY_IS_APPROX(a.adjoint(),d);
}
void test_upperbidiagonalization()
diff --git a/test/vectorwiseop.cpp b/test/vectorwiseop.cpp
index b938e3957..6cd1acdda 100644
--- a/test/vectorwiseop.cpp
+++ b/test/vectorwiseop.cpp
@@ -15,7 +15,6 @@ template<typename ArrayType> void vectorwiseop_array(const ArrayType& m)
{
typedef typename ArrayType::Index Index;
typedef typename ArrayType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
typedef Array<Scalar, ArrayType::RowsAtCompileTime, 1> ColVectorType;
typedef Array<Scalar, 1, ArrayType::ColsAtCompileTime> RowVectorType;
@@ -102,6 +101,16 @@ template<typename ArrayType> void vectorwiseop_array(const ArrayType& m)
VERIFY_RAISES_ASSERT(m2.rowwise() /= rowvec.transpose());
VERIFY_RAISES_ASSERT(m1.rowwise() / rowvec.transpose());
+
+ m2 = m1;
+ // yes, there might be an aliasing issue there but ".rowwise() /="
+ // is suppposed to evaluate " m2.colwise().sum()" into to temporary to avoid
+ // evaluating the reducions multiple times
+ if(ArrayType::RowsAtCompileTime>2 || ArrayType::RowsAtCompileTime==Dynamic)
+ {
+ m2.rowwise() /= m2.colwise().sum();
+ VERIFY_IS_APPROX(m2, m1.rowwise() / m1.colwise().sum());
+ }
}
template<typename MatrixType> void vectorwiseop_matrix(const MatrixType& m)
@@ -111,6 +120,8 @@ template<typename MatrixType> void vectorwiseop_matrix(const MatrixType& m)
typedef typename NumTraits<Scalar>::Real RealScalar;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> ColVectorType;
typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType;
+ typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealColVectorType;
+ typedef Matrix<RealScalar, 1, MatrixType::ColsAtCompileTime> RealRowVectorType;
Index rows = m.rows();
Index cols = m.cols();
@@ -123,6 +134,8 @@ template<typename MatrixType> void vectorwiseop_matrix(const MatrixType& m)
ColVectorType colvec = ColVectorType::Random(rows);
RowVectorType rowvec = RowVectorType::Random(cols);
+ RealColVectorType rcres;
+ RealRowVectorType rrres;
// test addition
@@ -159,6 +172,26 @@ template<typename MatrixType> void vectorwiseop_matrix(const MatrixType& m)
VERIFY_RAISES_ASSERT(m2.rowwise() -= rowvec.transpose());
VERIFY_RAISES_ASSERT(m1.rowwise() - rowvec.transpose());
+
+ // test norm
+ rrres = m1.colwise().norm();
+ VERIFY_IS_APPROX(rrres(c), m1.col(c).norm());
+ rcres = m1.rowwise().norm();
+ VERIFY_IS_APPROX(rcres(r), m1.row(r).norm());
+
+ // test normalized
+ m2 = m1.colwise().normalized();
+ VERIFY_IS_APPROX(m2.col(c), m1.col(c).normalized());
+ m2 = m1.rowwise().normalized();
+ VERIFY_IS_APPROX(m2.row(r), m1.row(r).normalized());
+
+ // test normalize
+ m2 = m1;
+ m2.colwise().normalize();
+ VERIFY_IS_APPROX(m2.col(c), m1.col(c).normalized());
+ m2 = m1;
+ m2.rowwise().normalize();
+ VERIFY_IS_APPROX(m2.row(r), m1.row(r).normalized());
}
void test_vectorwiseop()
diff --git a/test/visitor.cpp b/test/visitor.cpp
index 087306258..39a5d6b5f 100644
--- a/test/visitor.cpp
+++ b/test/visitor.cpp
@@ -72,8 +72,8 @@ template<typename VectorType> void vectorVisitor(const VectorType& w)
while(v(i) == v(i2)) // yes, ==
v(i) = internal::random<Scalar>();
- Scalar minc = Scalar(1000), maxc = Scalar(-1000);
- Index minidx=0,maxidx=0;
+ Scalar minc = v(0), maxc = v(0);
+ Index minidx=0, maxidx=0;
for(Index i = 0; i < size; i++)
{
if(v(i) < minc)
@@ -97,6 +97,17 @@ template<typename VectorType> void vectorVisitor(const VectorType& w)
VERIFY_IS_APPROX(maxc, eigen_maxc);
VERIFY_IS_APPROX(minc, v.minCoeff());
VERIFY_IS_APPROX(maxc, v.maxCoeff());
+
+ Index idx0 = internal::random<Index>(0,size-1);
+ Index idx1 = eigen_minidx;
+ Index idx2 = eigen_maxidx;
+ VectorType v1(v), v2(v);
+ v1(idx0) = v1(idx1);
+ v2(idx0) = v2(idx2);
+ v1.minCoeff(&eigen_minidx);
+ v2.maxCoeff(&eigen_maxidx);
+ VERIFY(eigen_minidx == (std::min)(idx0,idx1));
+ VERIFY(eigen_maxidx == (std::min)(idx0,idx2));
}
void test_visitor()
@@ -111,6 +122,7 @@ void test_visitor()
}
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST_7( vectorVisitor(Vector4f()) );
+ CALL_SUBTEST_7( vectorVisitor(Matrix<int,12,1>()) );
CALL_SUBTEST_8( vectorVisitor(VectorXd(10)) );
CALL_SUBTEST_9( vectorVisitor(RowVectorXd(10)) );
CALL_SUBTEST_10( vectorVisitor(VectorXf(33)) );
diff --git a/test/zerosized.cpp b/test/zerosized.cpp
index 6905e584e..da7dd0481 100644
--- a/test/zerosized.cpp
+++ b/test/zerosized.cpp
@@ -9,12 +9,26 @@
#include "main.h"
+
+template<typename MatrixType> void zeroReduction(const MatrixType& m) {
+ // Reductions that must hold for zero sized objects
+ VERIFY(m.all());
+ VERIFY(!m.any());
+ VERIFY(m.prod()==1);
+ VERIFY(m.sum()==0);
+ VERIFY(m.count()==0);
+ VERIFY(m.allFinite());
+ VERIFY(!m.hasNaN());
+}
+
+
template<typename MatrixType> void zeroSizedMatrix()
{
MatrixType t1;
- if (MatrixType::SizeAtCompileTime == Dynamic)
+ if (MatrixType::SizeAtCompileTime == Dynamic || MatrixType::SizeAtCompileTime == 0)
{
+ zeroReduction(t1);
if (MatrixType::RowsAtCompileTime == Dynamic)
VERIFY(t1.rows() == 0);
if (MatrixType::ColsAtCompileTime == Dynamic)
@@ -22,9 +36,13 @@ template<typename MatrixType> void zeroSizedMatrix()
if (MatrixType::RowsAtCompileTime == Dynamic && MatrixType::ColsAtCompileTime == Dynamic)
{
+
MatrixType t2(0, 0);
VERIFY(t2.rows() == 0);
VERIFY(t2.cols() == 0);
+
+ zeroReduction(t2);
+ VERIFY(t1==t2);
}
}
}
@@ -33,11 +51,15 @@ template<typename VectorType> void zeroSizedVector()
{
VectorType t1;
- if (VectorType::SizeAtCompileTime == Dynamic)
+ if (VectorType::SizeAtCompileTime == Dynamic || VectorType::SizeAtCompileTime==0)
{
+ zeroReduction(t1);
VERIFY(t1.size() == 0);
VectorType t2(DenseIndex(0)); // DenseIndex disambiguates with 0-the-null-pointer (error with gcc 4.4 and MSVC8)
VERIFY(t2.size() == 0);
+ zeroReduction(t2);
+
+ VERIFY(t1==t2);
}
}
@@ -51,9 +73,12 @@ void test_zerosized()
zeroSizedMatrix<Matrix<float, Dynamic, 0, 0, 0, 0> >();
zeroSizedMatrix<Matrix<float, 0, Dynamic, 0, 0, 0> >();
zeroSizedMatrix<Matrix<float, Dynamic, Dynamic, 0, 0, 0> >();
-
+ zeroSizedMatrix<Matrix<float, 0, 4> >();
+ zeroSizedMatrix<Matrix<float, 4, 0> >();
+
zeroSizedVector<Vector2d>();
zeroSizedVector<Vector3i>();
zeroSizedVector<VectorXf>();
zeroSizedVector<Matrix<float, 0, 1> >();
+ zeroSizedVector<Matrix<float, 1, 0> >();
}
diff --git a/unsupported/Eigen/AdolcForward b/unsupported/Eigen/AdolcForward
index b96f9450e..2627decd0 100644
--- a/unsupported/Eigen/AdolcForward
+++ b/unsupported/Eigen/AdolcForward
@@ -44,7 +44,7 @@
namespace Eigen {
-/** \ingroup Unsupported_modules
+/**
* \defgroup AdolcForward_Module Adolc forward module
* This module provides support for adolc's adouble type in forward mode.
* ADOL-C is a C++ automatic differentiation library,
diff --git a/unsupported/Eigen/AlignedVector3 b/unsupported/Eigen/AlignedVector3
index 8ad0eb477..7b45e6cce 100644
--- a/unsupported/Eigen/AlignedVector3
+++ b/unsupported/Eigen/AlignedVector3
@@ -14,7 +14,7 @@
namespace Eigen {
-/** \ingroup Unsupported_modules
+/**
* \defgroup AlignedVector3_Module Aligned vector3 module
*
* \code
@@ -167,7 +167,8 @@ template<typename _Scalar> class AlignedVector3
inline Scalar norm() const
{
- return internal::sqrt(squaredNorm());
+ using std::sqrt;
+ return sqrt(squaredNorm());
}
inline AlignedVector3 cross(const AlignedVector3& other) const
diff --git a/unsupported/Eigen/ArpackSupport b/unsupported/Eigen/ArpackSupport
new file mode 100644
index 000000000..37a2799ef
--- /dev/null
+++ b/unsupported/Eigen/ArpackSupport
@@ -0,0 +1,31 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+//
+// 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_ARPACKSUPPORT_MODULE_H
+#define EIGEN_ARPACKSUPPORT_MODULE_H
+
+#include <Eigen/Core>
+
+#include <Eigen/src/Core/util/DisableStupidWarnings.h>
+
+/** \defgroup ArpackSupport_Module Arpack support module
+ *
+ * This module provides a wrapper to Arpack, a library for sparse eigenvalue decomposition.
+ *
+ * \code
+ * #include <Eigen/ArpackSupport>
+ * \endcode
+ */
+
+#include <Eigen/SparseCholesky>
+#include "src/Eigenvalues/ArpackSelfAdjointEigenSolver.h"
+
+#include <Eigen/src/Core/util/ReenableStupidWarnings.h>
+
+#endif // EIGEN_ARPACKSUPPORT_MODULE_H
+/* vim: set filetype=cpp et sw=2 ts=2 ai: */
diff --git a/unsupported/Eigen/AutoDiff b/unsupported/Eigen/AutoDiff
index 3c73b424e..abf5b7d67 100644
--- a/unsupported/Eigen/AutoDiff
+++ b/unsupported/Eigen/AutoDiff
@@ -12,7 +12,7 @@
namespace Eigen {
-/** \ingroup Unsupported_modules
+/**
* \defgroup AutoDiff_Module Auto Diff module
*
* This module features forward automatic differentation via a simple
diff --git a/unsupported/Eigen/BVH b/unsupported/Eigen/BVH
index 860a7dd89..0161a5402 100644
--- a/unsupported/Eigen/BVH
+++ b/unsupported/Eigen/BVH
@@ -18,7 +18,7 @@
namespace Eigen {
-/** \ingroup Unsupported_modules
+/**
* \defgroup BVH_Module BVH module
* \brief This module provides generic bounding volume hierarchy algorithms
* and reference tree implementations.
diff --git a/unsupported/Eigen/CMakeLists.txt b/unsupported/Eigen/CMakeLists.txt
index e961e72c5..e06f1238b 100644
--- a/unsupported/Eigen/CMakeLists.txt
+++ b/unsupported/Eigen/CMakeLists.txt
@@ -1,6 +1,6 @@
set(Eigen_HEADERS AdolcForward BVH IterativeSolvers MatrixFunctions MoreVectorization AutoDiff AlignedVector3 Polynomials
FFT NonLinearOptimization SparseExtra IterativeSolvers
- NumericalDiff Skyline MPRealSupport OpenGLSupport KroneckerProduct Splines
+ NumericalDiff Skyline MPRealSupport OpenGLSupport KroneckerProduct Splines LevenbergMarquardt
)
install(FILES
diff --git a/unsupported/Eigen/FFT b/unsupported/Eigen/FFT
index d233c6d5f..2c45b3999 100644
--- a/unsupported/Eigen/FFT
+++ b/unsupported/Eigen/FFT
@@ -16,7 +16,7 @@
#include <Eigen/Core>
-/** \ingroup Unsupported_modules
+/**
* \defgroup FFT_Module Fast Fourier Transform module
*
* \code
diff --git a/unsupported/Eigen/IterativeSolvers b/unsupported/Eigen/IterativeSolvers
index 6c6946d91..aa15403db 100644
--- a/unsupported/Eigen/IterativeSolvers
+++ b/unsupported/Eigen/IterativeSolvers
@@ -12,7 +12,7 @@
#include <Eigen/Sparse>
-/** \ingroup Unsupported_modules
+/**
* \defgroup IterativeSolvers_Module Iterative solvers module
* This module aims to provide various iterative linear and non linear solver algorithms.
* It currently provides:
@@ -27,13 +27,18 @@
#include "../../Eigen/src/misc/Solve.h"
#include "../../Eigen/src/misc/SparseSolve.h"
+#ifndef EIGEN_MPL2_ONLY
#include "src/IterativeSolvers/IterationController.h"
#include "src/IterativeSolvers/ConstrainedConjGrad.h"
+#endif
+
#include "src/IterativeSolvers/IncompleteLU.h"
#include "../../Eigen/Jacobi"
#include "../../Eigen/Householder"
#include "src/IterativeSolvers/GMRES.h"
+#include "src/IterativeSolvers/IncompleteCholesky.h"
//#include "src/IterativeSolvers/SSORPreconditioner.h"
+#include "src/IterativeSolvers/MINRES.h"
//@}
diff --git a/unsupported/Eigen/KroneckerProduct b/unsupported/Eigen/KroneckerProduct
index 796e386ad..c932c06a6 100644
--- a/unsupported/Eigen/KroneckerProduct
+++ b/unsupported/Eigen/KroneckerProduct
@@ -1,3 +1,11 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+//
+// 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_KRONECKER_PRODUCT_MODULE_H
#define EIGEN_KRONECKER_PRODUCT_MODULE_H
@@ -7,7 +15,7 @@
namespace Eigen {
-/** \ingroup Unsupported_modules
+/**
* \defgroup KroneckerProduct_Module KroneckerProduct module
*
* This module contains an experimental Kronecker product implementation.
diff --git a/unsupported/Eigen/LevenbergMarquardt b/unsupported/Eigen/LevenbergMarquardt
new file mode 100644
index 000000000..0fe2680ba
--- /dev/null
+++ b/unsupported/Eigen/LevenbergMarquardt
@@ -0,0 +1,45 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org>
+//
+// 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_LEVENBERGMARQUARDT_MODULE
+#define EIGEN_LEVENBERGMARQUARDT_MODULE
+
+// #include <vector>
+
+#include <Eigen/Core>
+#include <Eigen/Jacobi>
+#include <Eigen/QR>
+#include <unsupported/Eigen/NumericalDiff>
+
+#include <Eigen/SparseQR>
+
+/**
+ * \defgroup LevenbergMarquardt_Module Levenberg-Marquardt module
+ *
+ * \code
+ * #include </Eigen/LevenbergMarquardt>
+ * \endcode
+ *
+ *
+ */
+
+#include "Eigen/SparseCore"
+#ifndef EIGEN_PARSED_BY_DOXYGEN
+
+#include "src/LevenbergMarquardt/LMqrsolv.h"
+#include "src/LevenbergMarquardt/LMcovar.h"
+#include "src/LevenbergMarquardt/LMpar.h"
+
+#endif
+
+#include "src/LevenbergMarquardt/LevenbergMarquardt.h"
+#include "src/LevenbergMarquardt/LMonestep.h"
+
+
+#endif // EIGEN_LEVENBERGMARQUARDT_MODULE
diff --git a/unsupported/Eigen/MPRealSupport b/unsupported/Eigen/MPRealSupport
index 3895623fe..d4b03647d 100644
--- a/unsupported/Eigen/MPRealSupport
+++ b/unsupported/Eigen/MPRealSupport
@@ -1,41 +1,36 @@
// This file is part of a joint effort between Eigen, a lightweight C++ template library
// for linear algebra, and MPFR C++, a C++ interface to MPFR library (http://www.holoborodko.com/pavel/)
//
-// Copyright (C) 2010 Pavel Holoborodko <pavel@holoborodko.com>
+// Copyright (C) 2010-2012 Pavel Holoborodko <pavel@holoborodko.com>
// Copyright (C) 2010 Konstantin Holoborodko <konstantin@holoborodko.com>
// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
-//
-// Contributors:
-// Brian Gladman, Helmut Jarausch, Fokko Beekhof, Ulrich Mutze, Heinz van Saanen, Pere Constans
#ifndef EIGEN_MPREALSUPPORT_MODULE_H
#define EIGEN_MPREALSUPPORT_MODULE_H
-#include <ctime>
-#include <mpreal.h>
#include <Eigen/Core>
+#include <mpreal.h>
namespace Eigen {
- /** \ingroup Unsupported_modules
- * \defgroup MPRealSupport_Module MPFRC++ Support module
- *
- * \code
- * #include <Eigen/MPRealSupport>
- * \endcode
- *
- * This module provides support for multi precision floating point numbers
- * via the <a href="http://www.holoborodko.com/pavel/mpfr">MPFR C++</a>
- * library which itself is built upon <a href="http://www.mpfr.org/">MPFR</a>/<a href="http://gmplib.org/">GMP</a>.
- *
- * You can find a copy of MPFR C++ that is known to be compatible in the unsupported/test/mpreal folder.
- *
- * Here is an example:
- *
+/**
+ * \defgroup MPRealSupport_Module MPFRC++ Support module
+ * \code
+ * #include <Eigen/MPRealSupport>
+ * \endcode
+ *
+ * This module provides support for multi precision floating point numbers
+ * via the <a href="http://www.holoborodko.com/pavel/mpfr">MPFR C++</a>
+ * library which itself is built upon <a href="http://www.mpfr.org/">MPFR</a>/<a href="http://gmplib.org/">GMP</a>.
+ *
+ * You can find a copy of MPFR C++ that is known to be compatible in the unsupported/test/mpreal folder.
+ *
+ * Here is an example:
+ *
\code
#include <iostream>
#include <Eigen/MPRealSupport>
@@ -59,9 +54,9 @@ int main()
return 0;
}
\endcode
- *
- */
-
+ *
+ */
+
template<> struct NumTraits<mpfr::mpreal>
: GenericNumTraits<mpfr::mpreal>
{
@@ -77,72 +72,132 @@ int main()
typedef mpfr::mpreal Real;
typedef mpfr::mpreal NonInteger;
-
- inline static mpfr::mpreal highest() { return mpfr::mpreal_max(mpfr::mpreal::get_default_prec()); }
- inline static mpfr::mpreal lowest() { return -mpfr::mpreal_max(mpfr::mpreal::get_default_prec()); }
-
- inline static Real epsilon()
- {
- return mpfr::machine_epsilon(mpfr::mpreal::get_default_prec());
- }
- inline static Real dummy_precision()
- {
- unsigned int weak_prec = ((mpfr::mpreal::get_default_prec()-1)*90)/100;
- return mpfr::machine_epsilon(weak_prec);
+
+ inline static Real highest (long Precision = mpfr::mpreal::get_default_prec()) { return mpfr::maxval(Precision); }
+ inline static Real lowest (long Precision = mpfr::mpreal::get_default_prec()) { return -mpfr::maxval(Precision); }
+
+ // Constants
+ inline static Real Pi (long Precision = mpfr::mpreal::get_default_prec()) { return mpfr::const_pi(Precision); }
+ inline static Real Euler (long Precision = mpfr::mpreal::get_default_prec()) { return mpfr::const_euler(Precision); }
+ inline static Real Log2 (long Precision = mpfr::mpreal::get_default_prec()) { return mpfr::const_log2(Precision); }
+ inline static Real Catalan (long Precision = mpfr::mpreal::get_default_prec()) { return mpfr::const_catalan(Precision); }
+
+ inline static Real epsilon (long Precision = mpfr::mpreal::get_default_prec()) { return mpfr::machine_epsilon(Precision); }
+ inline static Real epsilon (const Real& x) { return mpfr::machine_epsilon(x); }
+
+ inline static Real dummy_precision()
+ {
+ unsigned int weak_prec = ((mpfr::mpreal::get_default_prec()-1) * 90) / 100;
+ return mpfr::machine_epsilon(weak_prec);
}
};
-namespace internal {
+ namespace internal {
- template<> mpfr::mpreal random<mpfr::mpreal>()
+ template<> inline mpfr::mpreal random<mpfr::mpreal>()
{
-#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))
- static gmp_randstate_t state;
- static bool isFirstTime = true;
-
- if(isFirstTime)
- {
- gmp_randinit_default(state);
- gmp_randseed_ui(state,(unsigned)time(NULL));
- isFirstTime = false;
- }
-
- return mpfr::urandom(state)*2-1;
-#else
- return mpfr::mpreal(random<double>());
-#endif
+ return mpfr::random();
}
- template<> mpfr::mpreal random<mpfr::mpreal>(const mpfr::mpreal& a, const mpfr::mpreal& b)
+ template<> inline mpfr::mpreal random<mpfr::mpreal>(const mpfr::mpreal& a, const mpfr::mpreal& b)
{
return a + (b-a) * random<mpfr::mpreal>();
}
- bool isMuchSmallerThan(const mpfr::mpreal& a, const mpfr::mpreal& b, const mpfr::mpreal& prec)
+ inline bool isMuchSmallerThan(const mpfr::mpreal& a, const mpfr::mpreal& b, const mpfr::mpreal& eps)
{
- return mpfr::abs(a) <= mpfr::abs(b) * prec;
+ return mpfr::abs(a) <= mpfr::abs(b) * eps;
}
- inline bool isApprox(const mpfr::mpreal& a, const mpfr::mpreal& b, const mpfr::mpreal& prec)
+ inline bool isApprox(const mpfr::mpreal& a, const mpfr::mpreal& b, const mpfr::mpreal& eps)
{
- return mpfr::abs(a - b) <= (mpfr::min)(mpfr::abs(a), mpfr::abs(b)) * prec;
+ return mpfr::isEqualFuzzy(a,b,eps);
}
- inline bool isApproxOrLessThan(const mpfr::mpreal& a, const mpfr::mpreal& b, const mpfr::mpreal& prec)
+ inline bool isApproxOrLessThan(const mpfr::mpreal& a, const mpfr::mpreal& b, const mpfr::mpreal& eps)
{
- return a <= b || isApprox(a, b, prec);
+ return a <= b || mpfr::isEqualFuzzy(a,b,eps);
}
-
+
template<> inline long double cast<mpfr::mpreal,long double>(const mpfr::mpreal& x)
{ return x.toLDouble(); }
+
template<> inline double cast<mpfr::mpreal,double>(const mpfr::mpreal& x)
{ return x.toDouble(); }
+
template<> inline long cast<mpfr::mpreal,long>(const mpfr::mpreal& x)
{ return x.toLong(); }
+
template<> inline int cast<mpfr::mpreal,int>(const mpfr::mpreal& x)
{ return int(x.toLong()); }
-} // end namespace internal
+ // Specialize GEBP kernel and traits for mpreal (no need for peeling, nor complicated stuff)
+ // This also permits to directly call mpfr's routines and avoid many temporaries produced by mpreal
+ template<>
+ class gebp_traits<mpfr::mpreal, mpfr::mpreal, false, false>
+ {
+ public:
+ typedef mpfr::mpreal ResScalar;
+ enum {
+ nr = 2, // must be 2 for proper packing...
+ mr = 1,
+ WorkSpaceFactor = nr,
+ LhsProgress = 1,
+ RhsProgress = 1
+ };
+ };
+
+ template<typename Index, int mr, int nr, bool ConjugateLhs, bool ConjugateRhs>
+ struct gebp_kernel<mpfr::mpreal,mpfr::mpreal,Index,mr,nr,ConjugateLhs,ConjugateRhs>
+ {
+ typedef mpfr::mpreal mpreal;
+
+ EIGEN_DONT_INLINE
+ void operator()(mpreal* res, Index resStride, const mpreal* blockA, const mpreal* blockB, Index rows, Index depth, Index cols, mpreal alpha,
+ Index strideA=-1, Index strideB=-1, Index offsetA=0, Index offsetB=0, mpreal* /*unpackedB*/ = 0)
+ {
+ mpreal acc1, acc2, tmp;
+
+ if(strideA==-1) strideA = depth;
+ if(strideB==-1) strideB = depth;
+
+ for(Index j=0; j<cols; j+=nr)
+ {
+ Index actual_nr = (std::min<Index>)(nr,cols-j);
+ mpreal *C1 = res + j*resStride;
+ mpreal *C2 = res + (j+1)*resStride;
+ for(Index i=0; i<rows; i++)
+ {
+ mpreal *B = const_cast<mpreal*>(blockB) + j*strideB + offsetB*actual_nr;
+ mpreal *A = const_cast<mpreal*>(blockA) + i*strideA + offsetA;
+ acc1 = 0;
+ acc2 = 0;
+ for(Index k=0; k<depth; k++)
+ {
+ mpfr_mul(tmp.mpfr_ptr(), A[k].mpfr_ptr(), B[0].mpfr_ptr(), mpreal::get_default_rnd());
+ mpfr_add(acc1.mpfr_ptr(), acc1.mpfr_ptr(), tmp.mpfr_ptr(), mpreal::get_default_rnd());
+
+ if(actual_nr==2) {
+ mpfr_mul(tmp.mpfr_ptr(), A[k].mpfr_ptr(), B[1].mpfr_ptr(), mpreal::get_default_rnd());
+ mpfr_add(acc2.mpfr_ptr(), acc2.mpfr_ptr(), tmp.mpfr_ptr(), mpreal::get_default_rnd());
+ }
+
+ B+=actual_nr;
+ }
+
+ mpfr_mul(acc1.mpfr_ptr(), acc1.mpfr_ptr(), alpha.mpfr_ptr(), mpreal::get_default_rnd());
+ mpfr_add(C1[i].mpfr_ptr(), C1[i].mpfr_ptr(), acc1.mpfr_ptr(), mpreal::get_default_rnd());
+
+ if(actual_nr==2) {
+ mpfr_mul(acc2.mpfr_ptr(), acc2.mpfr_ptr(), alpha.mpfr_ptr(), mpreal::get_default_rnd());
+ mpfr_add(C2[i].mpfr_ptr(), C2[i].mpfr_ptr(), acc2.mpfr_ptr(), mpreal::get_default_rnd());
+ }
+ }
+ }
+ }
+ };
+
+ } // end namespace internal
}
#endif // EIGEN_MPREALSUPPORT_MODULE_H
diff --git a/unsupported/Eigen/MatrixFunctions b/unsupported/Eigen/MatrixFunctions
index 56ab71cd3..0991817d5 100644
--- a/unsupported/Eigen/MatrixFunctions
+++ b/unsupported/Eigen/MatrixFunctions
@@ -2,6 +2,7 @@
// for linear algebra.
//
// Copyright (C) 2009 Jitse Niesen <jitse@maths.leeds.ac.uk>
+// Copyright (C) 2012 Chen-Pang He <jdh8@ms63.hinet.net>
//
// 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
@@ -19,7 +20,7 @@
#include <Eigen/LU>
#include <Eigen/Eigenvalues>
-/** \ingroup Unsupported_modules
+/**
* \defgroup MatrixFunctions_Module Matrix functions module
* \brief This module aims to provide various methods for the computation of
* matrix functions.
@@ -35,6 +36,7 @@
* - \ref matrixbase_cosh "MatrixBase::cosh()", for computing the matrix hyperbolic cosine
* - \ref matrixbase_exp "MatrixBase::exp()", for computing the matrix exponential
* - \ref matrixbase_log "MatrixBase::log()", for computing the matrix logarithm
+ * - \ref matrixbase_pow "MatrixBase::pow()", for computing the matrix power
* - \ref matrixbase_matrixfunction "MatrixBase::matrixFunction()", for computing general matrix functions
* - \ref matrixbase_sin "MatrixBase::sin()", for computing the matrix sine
* - \ref matrixbase_sinh "MatrixBase::sinh()", for computing the matrix hyperbolic sine
@@ -57,19 +59,21 @@
#include "src/MatrixFunctions/MatrixFunction.h"
#include "src/MatrixFunctions/MatrixSquareRoot.h"
#include "src/MatrixFunctions/MatrixLogarithm.h"
-
+#include "src/MatrixFunctions/MatrixPower.h"
/**
-\page matrixbaseextra MatrixBase methods defined in the MatrixFunctions module
+\page matrixbaseextra_page
\ingroup MatrixFunctions_Module
+\section matrixbaseextra MatrixBase methods defined in the MatrixFunctions module
+
The remainder of the page documents the following MatrixBase methods
which are defined in the MatrixFunctions module.
-\section matrixbase_cos MatrixBase::cos()
+\subsection matrixbase_cos MatrixBase::cos()
Compute the matrix cosine.
@@ -86,7 +90,7 @@ This function calls \ref matrixbase_matrixfunction "matrixFunction()" with StdSt
-\section matrixbase_cosh MatrixBase::cosh()
+\subsection matrixbase_cosh MatrixBase::cosh()
Compute the matrix hyberbolic cosine.
@@ -103,7 +107,7 @@ This function calls \ref matrixbase_matrixfunction "matrixFunction()" with StdSt
-\section matrixbase_exp MatrixBase::exp()
+\subsection matrixbase_exp MatrixBase::exp()
Compute the matrix exponential.
@@ -158,7 +162,7 @@ Output: \verbinclude MatrixExponential.out
\c complex<float>, \c complex<double>, or \c complex<long double> .
-\section matrixbase_log MatrixBase::log()
+\subsection matrixbase_log MatrixBase::log()
Compute the matrix logarithm.
@@ -209,14 +213,77 @@ documentation of \ref matrixbase_exp "exp()".
\include MatrixLogarithm.cpp
Output: \verbinclude MatrixLogarithm.out
-\note \p M has to be a matrix of \c float, \c double, \c long double
-\c complex<float>, \c complex<double>, or \c complex<long double> .
+\note \p M has to be a matrix of \c float, \c double, <tt>long
+double</tt>, \c complex<float>, \c complex<double>, or \c complex<long
+double> .
\sa MatrixBase::exp(), MatrixBase::matrixFunction(),
class MatrixLogarithmAtomic, MatrixBase::sqrt().
-\section matrixbase_matrixfunction MatrixBase::matrixFunction()
+\subsection matrixbase_pow MatrixBase::pow()
+
+Compute the matrix raised to arbitrary real power.
+
+\code
+const MatrixPowerReturnValue<Derived> MatrixBase<Derived>::pow(RealScalar p) const
+\endcode
+
+\param[in] M base of the matrix power, should be a square matrix.
+\param[in] p exponent of the matrix power, should be real.
+
+The matrix power \f$ M^p \f$ is defined as \f$ \exp(p \log(M)) \f$,
+where exp denotes the matrix exponential, and log denotes the matrix
+logarithm.
+
+The matrix \f$ M \f$ should meet the conditions to be an argument of
+matrix logarithm. If \p p is not of the real scalar type of \p M, it
+is casted into the real scalar type of \p M.
+
+This function computes the matrix power using the Schur-Pad&eacute;
+algorithm as implemented by class MatrixPower. The exponent is split
+into integral part and fractional part, where the fractional part is
+in the interval \f$ (-1, 1) \f$. The main diagonal and the first
+super-diagonal is directly computed.
+
+Details of the algorithm can be found in: Nicholas J. Higham and
+Lijing Lin, "A Schur-Pad&eacute; algorithm for fractional powers of a
+matrix," <em>SIAM J. %Matrix Anal. Applic.</em>,
+<b>32(3)</b>:1056&ndash;1078, 2011.
+
+Example: The following program checks that
+\f[ \left[ \begin{array}{ccc}
+ \cos1 & -\sin1 & 0 \\
+ \sin1 & \cos1 & 0 \\
+ 0 & 0 & 1
+ \end{array} \right]^{\frac14\pi} = \left[ \begin{array}{ccc}
+ \frac12\sqrt2 & -\frac12\sqrt2 & 0 \\
+ \frac12\sqrt2 & \frac12\sqrt2 & 0 \\
+ 0 & 0 & 1
+ \end{array} \right]. \f]
+This corresponds to \f$ \frac14\pi \f$ rotations of 1 radian around
+the z-axis.
+
+\include MatrixPower.cpp
+Output: \verbinclude MatrixPower.out
+
+MatrixBase::pow() is user-friendly. However, there are some
+circumstances under which you should use class MatrixPower directly.
+MatrixPower can save the result of Schur decomposition, so it's
+better for computing various powers for the same matrix.
+
+Example:
+\include MatrixPower_optimal.cpp
+Output: \verbinclude MatrixPower_optimal.out
+
+\note \p M has to be a matrix of \c float, \c double, <tt>long
+double</tt>, \c complex<float>, \c complex<double>, or \c complex<long
+double> .
+
+\sa MatrixBase::exp(), MatrixBase::log(), class MatrixPower.
+
+
+\subsection matrixbase_matrixfunction MatrixBase::matrixFunction()
Compute a matrix function.
@@ -272,7 +339,7 @@ A.matrixFunction(StdStemFunctions<std::complex<double> >::exp, &B);
-\section matrixbase_sin MatrixBase::sin()
+\subsection matrixbase_sin MatrixBase::sin()
Compute the matrix sine.
@@ -290,7 +357,7 @@ Output: \verbinclude MatrixSine.out
-\section matrixbase_sinh MatrixBase::sinh()
+\subsection matrixbase_sinh MatrixBase::sinh()
Compute the matrix hyperbolic sine.
@@ -307,7 +374,7 @@ Example: \include MatrixSinh.cpp
Output: \verbinclude MatrixSinh.out
-\section matrixbase_sqrt MatrixBase::sqrt()
+\subsection matrixbase_sqrt MatrixBase::sqrt()
Compute the matrix square root.
diff --git a/unsupported/Eigen/MoreVectorization b/unsupported/Eigen/MoreVectorization
index 9f0a39f75..470e72430 100644
--- a/unsupported/Eigen/MoreVectorization
+++ b/unsupported/Eigen/MoreVectorization
@@ -1,3 +1,11 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+//
+// 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_MOREVECTORIZATION_MODULE_H
#define EIGEN_MOREVECTORIZATION_MODULE_H
@@ -5,7 +13,7 @@
namespace Eigen {
-/** \ingroup Unsupported_modules
+/**
* \defgroup MoreVectorization More vectorization module
*/
diff --git a/unsupported/Eigen/NonLinearOptimization b/unsupported/Eigen/NonLinearOptimization
index cf6ca58f8..600ab4c12 100644
--- a/unsupported/Eigen/NonLinearOptimization
+++ b/unsupported/Eigen/NonLinearOptimization
@@ -1,4 +1,4 @@
-// This file is part of Eugenio, a lightweight C++ template library
+// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org>
@@ -17,7 +17,7 @@
#include <Eigen/QR>
#include <unsupported/Eigen/NumericalDiff>
-/** \ingroup Unsupported_modules
+/**
* \defgroup NonLinearOptimization_Module Non linear optimization module
*
* \code
diff --git a/unsupported/Eigen/NumericalDiff b/unsupported/Eigen/NumericalDiff
index b3480312d..433334ca8 100644
--- a/unsupported/Eigen/NumericalDiff
+++ b/unsupported/Eigen/NumericalDiff
@@ -14,7 +14,7 @@
namespace Eigen {
-/** \ingroup Unsupported_modules
+/**
* \defgroup NumericalDiff_Module Numerical differentiation module
*
* \code
diff --git a/unsupported/Eigen/OpenGLSupport b/unsupported/Eigen/OpenGLSupport
index e66a425f8..c4090ab11 100644
--- a/unsupported/Eigen/OpenGLSupport
+++ b/unsupported/Eigen/OpenGLSupport
@@ -11,11 +11,16 @@
#define EIGEN_OPENGL_MODULE
#include <Eigen/Geometry>
-#include <GL/gl.h>
+
+#if defined(__APPLE_CC__)
+ #include <OpenGL/gl.h>
+#else
+ #include <GL/gl.h>
+#endif
namespace Eigen {
-/** \ingroup Unsupported_modules
+/**
* \defgroup OpenGLSUpport_Module OpenGL Support module
*
* This module provides wrapper functions for a couple of OpenGL functions
diff --git a/unsupported/Eigen/Polynomials b/unsupported/Eigen/Polynomials
index fa58b006d..cece56337 100644
--- a/unsupported/Eigen/Polynomials
+++ b/unsupported/Eigen/Polynomials
@@ -1,3 +1,11 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+//
+// 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_POLYNOMIALS_MODULE_H
#define EIGEN_POLYNOMIALS_MODULE_H
@@ -16,11 +24,8 @@
#undef EIGEN_HIDE_HEAVY_CODE
#endif
-/** \ingroup Unsupported_modules
+/**
* \defgroup Polynomials_Module Polynomials module
- *
- *
- *
* \brief This module provides a QR based polynomial solver.
*
* To use this module, add
diff --git a/unsupported/Eigen/SVD b/unsupported/Eigen/SVD
new file mode 100644
index 000000000..7cc059280
--- /dev/null
+++ b/unsupported/Eigen/SVD
@@ -0,0 +1,39 @@
+#ifndef EIGEN_SVD_MODULE_H
+#define EIGEN_SVD_MODULE_H
+
+#include <Eigen/QR>
+#include <Eigen/Householder>
+#include <Eigen/Jacobi>
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+/** \defgroup SVD_Module SVD module
+ *
+ *
+ *
+ * This module provides SVD decomposition for matrices (both real and complex).
+ * This decomposition is accessible via the following MatrixBase method:
+ * - MatrixBase::jacobiSvd()
+ *
+ * \code
+ * #include <Eigen/SVD>
+ * \endcode
+ */
+
+#include "../../Eigen/src/misc/Solve.h"
+#include "../../Eigen/src/SVD/UpperBidiagonalization.h"
+#include "src/SVD/SVDBase.h"
+#include "src/SVD/JacobiSVD.h"
+#include "src/SVD/BDCSVD.h"
+#if defined(EIGEN_USE_LAPACKE) && !defined(EIGEN_USE_LAPACKE_STRICT)
+#include "../../Eigen/src/SVD/JacobiSVD_MKL.h"
+#endif
+
+#ifdef EIGEN2_SUPPORT
+#include "../../Eigen/src/Eigen2Support/SVD.h"
+#endif
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+#endif // EIGEN_SVD_MODULE_H
+/* vim: set filetype=cpp et sw=2 ts=2 ai: */
diff --git a/unsupported/Eigen/Skyline b/unsupported/Eigen/Skyline
index c9823f358..71a68cb42 100644
--- a/unsupported/Eigen/Skyline
+++ b/unsupported/Eigen/Skyline
@@ -1,3 +1,11 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+//
+// 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_SKYLINE_MODULE_H
#define EIGEN_SKYLINE_MODULE_H
@@ -11,7 +19,7 @@
#include <cstring>
#include <algorithm>
-/** \ingroup Unsupported_modules
+/**
* \defgroup Skyline_Module Skyline module
*
*
diff --git a/unsupported/Eigen/SparseExtra b/unsupported/Eigen/SparseExtra
index 340c34736..b5597902a 100644
--- a/unsupported/Eigen/SparseExtra
+++ b/unsupported/Eigen/SparseExtra
@@ -1,3 +1,12 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
#ifndef EIGEN_SPARSE_EXTRA_MODULE_H
#define EIGEN_SPARSE_EXTRA_MODULE_H
@@ -17,7 +26,7 @@
#include <google/dense_hash_map>
#endif
-/** \ingroup Unsupported_modules
+/**
* \defgroup SparseExtra_Module SparseExtra module
*
* This module contains some experimental features extending the sparse module.
diff --git a/unsupported/Eigen/Splines b/unsupported/Eigen/Splines
index 801cec1a1..322e6b9f5 100644
--- a/unsupported/Eigen/Splines
+++ b/unsupported/Eigen/Splines
@@ -12,7 +12,7 @@
namespace Eigen
{
-/** \ingroup Unsupported_modules
+/**
* \defgroup Splines_Module Spline and spline fitting module
*
* This module provides a simple multi-dimensional spline class while
diff --git a/unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h b/unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h
index b833df3c0..8d42e69b9 100644
--- a/unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h
+++ b/unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h
@@ -47,8 +47,8 @@ template<typename _DerType, bool Enable> struct auto_diff_special_op;
*
* It supports the following list of global math function:
* - std::abs, std::sqrt, std::pow, std::exp, std::log, std::sin, std::cos,
- * - internal::abs, internal::sqrt, internal::pow, internal::exp, internal::log, internal::sin, internal::cos,
- * - internal::conj, internal::real, internal::imag, internal::abs2.
+ * - internal::abs, internal::sqrt, numext::pow, internal::exp, internal::log, internal::sin, internal::cos,
+ * - internal::conj, internal::real, internal::imag, numext::abs2.
*
* AutoDiffScalar can be used as the scalar type of an Eigen::Matrix object. However,
* in that case, the expression template mechanism only occurs at the top Matrix level,
@@ -489,20 +489,32 @@ struct make_coherent_impl<Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows,
}
};
-template<typename A_Scalar, int A_Rows, int A_Cols, int A_Options, int A_MaxRows, int A_MaxCols> struct scalar_product_traits<Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows, A_MaxCols>,A_Scalar>
+template<typename A_Scalar, int A_Rows, int A_Cols, int A_Options, int A_MaxRows, int A_MaxCols>
+struct scalar_product_traits<Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows, A_MaxCols>,A_Scalar>
{
- typedef Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows, A_MaxCols> ReturnType;
+ enum { Defined = 1 };
+ typedef Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows, A_MaxCols> ReturnType;
};
-template<typename A_Scalar, int A_Rows, int A_Cols, int A_Options, int A_MaxRows, int A_MaxCols> struct scalar_product_traits<A_Scalar, Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows, A_MaxCols> >
+template<typename A_Scalar, int A_Rows, int A_Cols, int A_Options, int A_MaxRows, int A_MaxCols>
+struct scalar_product_traits<A_Scalar, Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows, A_MaxCols> >
{
- typedef Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows, A_MaxCols> ReturnType;
+ enum { Defined = 1 };
+ typedef Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows, A_MaxCols> ReturnType;
};
template<typename DerType>
struct scalar_product_traits<AutoDiffScalar<DerType>,typename DerType::Scalar>
{
- typedef AutoDiffScalar<DerType> ReturnType;
+ enum { Defined = 1 };
+ typedef AutoDiffScalar<DerType> ReturnType;
+};
+
+template<typename DerType>
+struct scalar_product_traits<typename DerType::Scalar,AutoDiffScalar<DerType> >
+{
+ enum { Defined = 1 };
+ typedef AutoDiffScalar<DerType> ReturnType;
};
} // end namespace internal
@@ -532,14 +544,12 @@ inline AutoDiffScalar<DerType> (min)(const T& x, const AutoDiffScalar<DerType>&
template<typename DerType, typename T>
inline AutoDiffScalar<DerType> (max)(const T& x, const AutoDiffScalar<DerType>& y) { return (x > y ? x : y); }
-#define sign(x) x >= 0 ? 1 : -1 // required for abs function below
-
EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(abs,
using std::abs;
- return ReturnType(abs(x.value()), x.derivatives() * (sign(x.value())));)
+ return ReturnType(abs(x.value()), x.derivatives() * (x.value()<0 ? -1 : 1) );)
EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(abs2,
- using internal::abs2;
+ using numext::abs2;
return ReturnType(abs2(x.value()), x.derivatives() * (Scalar(2)*x.value()));)
EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(sqrt,
@@ -602,17 +612,17 @@ atan2(const AutoDiffScalar<DerTypeA>& a, const AutoDiffScalar<DerTypeB>& b)
EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(tan,
using std::tan;
using std::cos;
- return ReturnType(tan(x.value()),x.derivatives() * (Scalar(1)/internal::abs2(cos(x.value()))));)
+ return ReturnType(tan(x.value()),x.derivatives() * (Scalar(1)/numext::abs2(cos(x.value()))));)
EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(asin,
using std::sqrt;
using std::asin;
- return ReturnType(asin(x.value()),x.derivatives() * (Scalar(1)/sqrt(1-internal::abs2(x.value()))));)
+ return ReturnType(asin(x.value()),x.derivatives() * (Scalar(1)/sqrt(1-numext::abs2(x.value()))));)
EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(acos,
using std::sqrt;
using std::acos;
- return ReturnType(acos(x.value()),x.derivatives() * (Scalar(-1)/sqrt(1-internal::abs2(x.value()))));)
+ return ReturnType(acos(x.value()),x.derivatives() * (Scalar(-1)/sqrt(1-numext::abs2(x.value()))));)
#undef EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY
diff --git a/unsupported/Eigen/src/AutoDiff/AutoDiffVector.h b/unsupported/Eigen/src/AutoDiff/AutoDiffVector.h
index 0540add0a..8c2d04830 100644
--- a/unsupported/Eigen/src/AutoDiff/AutoDiffVector.h
+++ b/unsupported/Eigen/src/AutoDiff/AutoDiffVector.h
@@ -21,8 +21,8 @@ namespace Eigen {
*
* It supports the following list of global math function:
* - std::abs, std::sqrt, std::pow, std::exp, std::log, std::sin, std::cos,
- * - internal::abs, internal::sqrt, internal::pow, internal::exp, internal::log, internal::sin, internal::cos,
- * - internal::conj, internal::real, internal::imag, internal::abs2.
+ * - internal::abs, internal::sqrt, numext::pow, internal::exp, internal::log, internal::sin, internal::cos,
+ * - internal::conj, internal::real, internal::imag, numext::abs2.
*
* AutoDiffScalar can be used as the scalar type of an Eigen::Matrix object. However,
* in that case, the expression template mechanism only occurs at the top Matrix level,
diff --git a/unsupported/Eigen/src/BVH/BVAlgorithms.h b/unsupported/Eigen/src/BVH/BVAlgorithms.h
index e5b51decb..994c8af54 100644
--- a/unsupported/Eigen/src/BVH/BVAlgorithms.h
+++ b/unsupported/Eigen/src/BVH/BVAlgorithms.h
@@ -189,7 +189,7 @@ struct minimizer_helper1
Object2 stored;
Minimizer &minimizer;
private:
- minimizer_helper1& operator=(const minimizer_helper1&) {}
+ minimizer_helper1& operator=(const minimizer_helper1&);
};
template<typename Volume2, typename Object2, typename Object1, typename Minimizer>
diff --git a/unsupported/Eigen/src/Eigenvalues/ArpackSelfAdjointEigenSolver.h b/unsupported/Eigen/src/Eigenvalues/ArpackSelfAdjointEigenSolver.h
new file mode 100644
index 000000000..3b6a69aff
--- /dev/null
+++ b/unsupported/Eigen/src/Eigenvalues/ArpackSelfAdjointEigenSolver.h
@@ -0,0 +1,805 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 David Harmon <dharmon@gmail.com>
+//
+// Eigen is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 3 of the License, or (at your option) any later version.
+//
+// Alternatively, you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_ARPACKGENERALIZEDSELFADJOINTEIGENSOLVER_H
+#define EIGEN_ARPACKGENERALIZEDSELFADJOINTEIGENSOLVER_H
+
+#include <Eigen/Dense>
+
+namespace Eigen {
+
+namespace internal {
+ template<typename Scalar, typename RealScalar> struct arpack_wrapper;
+ template<typename MatrixSolver, typename MatrixType, typename Scalar, bool BisSPD> struct OP;
+}
+
+
+
+template<typename MatrixType, typename MatrixSolver=SimplicialLLT<MatrixType>, bool BisSPD=false>
+class ArpackGeneralizedSelfAdjointEigenSolver
+{
+public:
+ //typedef typename MatrixSolver::MatrixType MatrixType;
+
+ /** \brief Scalar type for matrices of type \p MatrixType. */
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::Index Index;
+
+ /** \brief Real scalar type for \p MatrixType.
+ *
+ * This is just \c Scalar if #Scalar is real (e.g., \c float or
+ * \c Scalar), and the type of the real part of \c Scalar if #Scalar is
+ * complex.
+ */
+ typedef typename NumTraits<Scalar>::Real RealScalar;
+
+ /** \brief Type for vector of eigenvalues as returned by eigenvalues().
+ *
+ * This is a column vector with entries of type #RealScalar.
+ * The length of the vector is the size of \p nbrEigenvalues.
+ */
+ typedef typename internal::plain_col_type<MatrixType, RealScalar>::type RealVectorType;
+
+ /** \brief Default constructor.
+ *
+ * The default constructor is for cases in which the user intends to
+ * perform decompositions via compute().
+ *
+ */
+ ArpackGeneralizedSelfAdjointEigenSolver()
+ : m_eivec(),
+ m_eivalues(),
+ m_isInitialized(false),
+ m_eigenvectorsOk(false),
+ m_nbrConverged(0),
+ m_nbrIterations(0)
+ { }
+
+ /** \brief Constructor; computes generalized eigenvalues of given matrix with respect to another matrix.
+ *
+ * \param[in] A Self-adjoint matrix whose eigenvalues / eigenvectors will
+ * computed. By default, the upper triangular part is used, but can be changed
+ * through the template parameter.
+ * \param[in] B Self-adjoint matrix for the generalized eigenvalue problem.
+ * \param[in] nbrEigenvalues The number of eigenvalues / eigenvectors to compute.
+ * Must be less than the size of the input matrix, or an error is returned.
+ * \param[in] eigs_sigma String containing either "LM", "SM", "LA", or "SA", with
+ * respective meanings to find the largest magnitude , smallest magnitude,
+ * largest algebraic, or smallest algebraic eigenvalues. Alternatively, this
+ * value can contain floating point value in string form, in which case the
+ * eigenvalues closest to this value will be found.
+ * \param[in] options Can be #ComputeEigenvectors (default) or #EigenvaluesOnly.
+ * \param[in] tol What tolerance to find the eigenvalues to. Default is 0, which
+ * means machine precision.
+ *
+ * This constructor calls compute(const MatrixType&, const MatrixType&, Index, string, int, RealScalar)
+ * to compute the eigenvalues of the matrix \p A with respect to \p B. The eigenvectors are computed if
+ * \p options equals #ComputeEigenvectors.
+ *
+ */
+ ArpackGeneralizedSelfAdjointEigenSolver(const MatrixType& A, const MatrixType& B,
+ Index nbrEigenvalues, std::string eigs_sigma="LM",
+ int options=ComputeEigenvectors, RealScalar tol=0.0)
+ : m_eivec(),
+ m_eivalues(),
+ m_isInitialized(false),
+ m_eigenvectorsOk(false),
+ m_nbrConverged(0),
+ m_nbrIterations(0)
+ {
+ compute(A, B, nbrEigenvalues, eigs_sigma, options, tol);
+ }
+
+ /** \brief Constructor; computes eigenvalues of given matrix.
+ *
+ * \param[in] A Self-adjoint matrix whose eigenvalues / eigenvectors will
+ * computed. By default, the upper triangular part is used, but can be changed
+ * through the template parameter.
+ * \param[in] nbrEigenvalues The number of eigenvalues / eigenvectors to compute.
+ * Must be less than the size of the input matrix, or an error is returned.
+ * \param[in] eigs_sigma String containing either "LM", "SM", "LA", or "SA", with
+ * respective meanings to find the largest magnitude , smallest magnitude,
+ * largest algebraic, or smallest algebraic eigenvalues. Alternatively, this
+ * value can contain floating point value in string form, in which case the
+ * eigenvalues closest to this value will be found.
+ * \param[in] options Can be #ComputeEigenvectors (default) or #EigenvaluesOnly.
+ * \param[in] tol What tolerance to find the eigenvalues to. Default is 0, which
+ * means machine precision.
+ *
+ * This constructor calls compute(const MatrixType&, Index, string, int, RealScalar)
+ * to compute the eigenvalues of the matrix \p A. The eigenvectors are computed if
+ * \p options equals #ComputeEigenvectors.
+ *
+ */
+
+ ArpackGeneralizedSelfAdjointEigenSolver(const MatrixType& A,
+ Index nbrEigenvalues, std::string eigs_sigma="LM",
+ int options=ComputeEigenvectors, RealScalar tol=0.0)
+ : m_eivec(),
+ m_eivalues(),
+ m_isInitialized(false),
+ m_eigenvectorsOk(false),
+ m_nbrConverged(0),
+ m_nbrIterations(0)
+ {
+ compute(A, nbrEigenvalues, eigs_sigma, options, tol);
+ }
+
+
+ /** \brief Computes generalized eigenvalues / eigenvectors of given matrix using the external ARPACK library.
+ *
+ * \param[in] A Selfadjoint matrix whose eigendecomposition is to be computed.
+ * \param[in] B Selfadjoint matrix for generalized eigenvalues.
+ * \param[in] nbrEigenvalues The number of eigenvalues / eigenvectors to compute.
+ * Must be less than the size of the input matrix, or an error is returned.
+ * \param[in] eigs_sigma String containing either "LM", "SM", "LA", or "SA", with
+ * respective meanings to find the largest magnitude , smallest magnitude,
+ * largest algebraic, or smallest algebraic eigenvalues. Alternatively, this
+ * value can contain floating point value in string form, in which case the
+ * eigenvalues closest to this value will be found.
+ * \param[in] options Can be #ComputeEigenvectors (default) or #EigenvaluesOnly.
+ * \param[in] tol What tolerance to find the eigenvalues to. Default is 0, which
+ * means machine precision.
+ *
+ * \returns Reference to \c *this
+ *
+ * This function computes the generalized eigenvalues of \p A with respect to \p B using ARPACK. The eigenvalues()
+ * function can be used to retrieve them. If \p options equals #ComputeEigenvectors,
+ * then the eigenvectors are also computed and can be retrieved by
+ * calling eigenvectors().
+ *
+ */
+ ArpackGeneralizedSelfAdjointEigenSolver& compute(const MatrixType& A, const MatrixType& B,
+ Index nbrEigenvalues, std::string eigs_sigma="LM",
+ int options=ComputeEigenvectors, RealScalar tol=0.0);
+
+ /** \brief Computes eigenvalues / eigenvectors of given matrix using the external ARPACK library.
+ *
+ * \param[in] A Selfadjoint matrix whose eigendecomposition is to be computed.
+ * \param[in] nbrEigenvalues The number of eigenvalues / eigenvectors to compute.
+ * Must be less than the size of the input matrix, or an error is returned.
+ * \param[in] eigs_sigma String containing either "LM", "SM", "LA", or "SA", with
+ * respective meanings to find the largest magnitude , smallest magnitude,
+ * largest algebraic, or smallest algebraic eigenvalues. Alternatively, this
+ * value can contain floating point value in string form, in which case the
+ * eigenvalues closest to this value will be found.
+ * \param[in] options Can be #ComputeEigenvectors (default) or #EigenvaluesOnly.
+ * \param[in] tol What tolerance to find the eigenvalues to. Default is 0, which
+ * means machine precision.
+ *
+ * \returns Reference to \c *this
+ *
+ * This function computes the eigenvalues of \p A using ARPACK. The eigenvalues()
+ * function can be used to retrieve them. If \p options equals #ComputeEigenvectors,
+ * then the eigenvectors are also computed and can be retrieved by
+ * calling eigenvectors().
+ *
+ */
+ ArpackGeneralizedSelfAdjointEigenSolver& compute(const MatrixType& A,
+ Index nbrEigenvalues, std::string eigs_sigma="LM",
+ int options=ComputeEigenvectors, RealScalar tol=0.0);
+
+
+ /** \brief Returns the eigenvectors of given matrix.
+ *
+ * \returns A const reference to the matrix whose columns are the eigenvectors.
+ *
+ * \pre The eigenvectors have been computed before.
+ *
+ * Column \f$ k \f$ of the returned matrix is an eigenvector corresponding
+ * to eigenvalue number \f$ k \f$ as returned by eigenvalues(). The
+ * eigenvectors are normalized to have (Euclidean) norm equal to one. If
+ * this object was used to solve the eigenproblem for the selfadjoint
+ * matrix \f$ A \f$, then the matrix returned by this function is the
+ * matrix \f$ V \f$ in the eigendecomposition \f$ A V = D V \f$.
+ * For the generalized eigenproblem, the matrix returned is the solution \f$ A V = D B V \f$
+ *
+ * Example: \include SelfAdjointEigenSolver_eigenvectors.cpp
+ * Output: \verbinclude SelfAdjointEigenSolver_eigenvectors.out
+ *
+ * \sa eigenvalues()
+ */
+ const Matrix<Scalar, Dynamic, Dynamic>& eigenvectors() const
+ {
+ eigen_assert(m_isInitialized && "ArpackGeneralizedSelfAdjointEigenSolver is not initialized.");
+ eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
+ return m_eivec;
+ }
+
+ /** \brief Returns the eigenvalues of given matrix.
+ *
+ * \returns A const reference to the column vector containing the eigenvalues.
+ *
+ * \pre The eigenvalues have been computed before.
+ *
+ * The eigenvalues are repeated according to their algebraic multiplicity,
+ * so there are as many eigenvalues as rows in the matrix. The eigenvalues
+ * are sorted in increasing order.
+ *
+ * Example: \include SelfAdjointEigenSolver_eigenvalues.cpp
+ * Output: \verbinclude SelfAdjointEigenSolver_eigenvalues.out
+ *
+ * \sa eigenvectors(), MatrixBase::eigenvalues()
+ */
+ const Matrix<Scalar, Dynamic, 1>& eigenvalues() const
+ {
+ eigen_assert(m_isInitialized && "ArpackGeneralizedSelfAdjointEigenSolver is not initialized.");
+ return m_eivalues;
+ }
+
+ /** \brief Computes the positive-definite square root of the matrix.
+ *
+ * \returns the positive-definite square root of the matrix
+ *
+ * \pre The eigenvalues and eigenvectors of a positive-definite matrix
+ * have been computed before.
+ *
+ * The square root of a positive-definite matrix \f$ A \f$ is the
+ * positive-definite matrix whose square equals \f$ A \f$. This function
+ * uses the eigendecomposition \f$ A = V D V^{-1} \f$ to compute the
+ * square root as \f$ A^{1/2} = V D^{1/2} V^{-1} \f$.
+ *
+ * Example: \include SelfAdjointEigenSolver_operatorSqrt.cpp
+ * Output: \verbinclude SelfAdjointEigenSolver_operatorSqrt.out
+ *
+ * \sa operatorInverseSqrt(),
+ * \ref MatrixFunctions_Module "MatrixFunctions Module"
+ */
+ Matrix<Scalar, Dynamic, Dynamic> operatorSqrt() const
+ {
+ eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized.");
+ eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
+ return m_eivec * m_eivalues.cwiseSqrt().asDiagonal() * m_eivec.adjoint();
+ }
+
+ /** \brief Computes the inverse square root of the matrix.
+ *
+ * \returns the inverse positive-definite square root of the matrix
+ *
+ * \pre The eigenvalues and eigenvectors of a positive-definite matrix
+ * have been computed before.
+ *
+ * This function uses the eigendecomposition \f$ A = V D V^{-1} \f$ to
+ * compute the inverse square root as \f$ V D^{-1/2} V^{-1} \f$. This is
+ * cheaper than first computing the square root with operatorSqrt() and
+ * then its inverse with MatrixBase::inverse().
+ *
+ * Example: \include SelfAdjointEigenSolver_operatorInverseSqrt.cpp
+ * Output: \verbinclude SelfAdjointEigenSolver_operatorInverseSqrt.out
+ *
+ * \sa operatorSqrt(), MatrixBase::inverse(),
+ * \ref MatrixFunctions_Module "MatrixFunctions Module"
+ */
+ Matrix<Scalar, Dynamic, Dynamic> operatorInverseSqrt() const
+ {
+ eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized.");
+ eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
+ return m_eivec * m_eivalues.cwiseInverse().cwiseSqrt().asDiagonal() * m_eivec.adjoint();
+ }
+
+ /** \brief Reports whether previous computation was successful.
+ *
+ * \returns \c Success if computation was succesful, \c NoConvergence otherwise.
+ */
+ ComputationInfo info() const
+ {
+ eigen_assert(m_isInitialized && "ArpackGeneralizedSelfAdjointEigenSolver is not initialized.");
+ return m_info;
+ }
+
+ size_t getNbrConvergedEigenValues() const
+ { return m_nbrConverged; }
+
+ size_t getNbrIterations() const
+ { return m_nbrIterations; }
+
+protected:
+ Matrix<Scalar, Dynamic, Dynamic> m_eivec;
+ Matrix<Scalar, Dynamic, 1> m_eivalues;
+ ComputationInfo m_info;
+ bool m_isInitialized;
+ bool m_eigenvectorsOk;
+
+ size_t m_nbrConverged;
+ size_t m_nbrIterations;
+};
+
+
+
+
+
+template<typename MatrixType, typename MatrixSolver, bool BisSPD>
+ArpackGeneralizedSelfAdjointEigenSolver<MatrixType, MatrixSolver, BisSPD>&
+ ArpackGeneralizedSelfAdjointEigenSolver<MatrixType, MatrixSolver, BisSPD>
+::compute(const MatrixType& A, Index nbrEigenvalues,
+ std::string eigs_sigma, int options, RealScalar tol)
+{
+ MatrixType B(0,0);
+ compute(A, B, nbrEigenvalues, eigs_sigma, options, tol);
+
+ return *this;
+}
+
+
+template<typename MatrixType, typename MatrixSolver, bool BisSPD>
+ArpackGeneralizedSelfAdjointEigenSolver<MatrixType, MatrixSolver, BisSPD>&
+ ArpackGeneralizedSelfAdjointEigenSolver<MatrixType, MatrixSolver, BisSPD>
+::compute(const MatrixType& A, const MatrixType& B, Index nbrEigenvalues,
+ std::string eigs_sigma, int options, RealScalar tol)
+{
+ eigen_assert(A.cols() == A.rows());
+ eigen_assert(B.cols() == B.rows());
+ eigen_assert(B.rows() == 0 || A.cols() == B.rows());
+ eigen_assert((options &~ (EigVecMask | GenEigMask)) == 0
+ && (options & EigVecMask) != EigVecMask
+ && "invalid option parameter");
+
+ bool isBempty = (B.rows() == 0) || (B.cols() == 0);
+
+ // For clarity, all parameters match their ARPACK name
+ //
+ // Always 0 on the first call
+ //
+ int ido = 0;
+
+ int n = (int)A.cols();
+
+ // User options: "LA", "SA", "SM", "LM", "BE"
+ //
+ char whch[3] = "LM";
+
+ // Specifies the shift if iparam[6] = { 3, 4, 5 }, not used if iparam[6] = { 1, 2 }
+ //
+ RealScalar sigma = 0.0;
+
+ if (eigs_sigma.length() >= 2 && isalpha(eigs_sigma[0]) && isalpha(eigs_sigma[1]))
+ {
+ eigs_sigma[0] = toupper(eigs_sigma[0]);
+ eigs_sigma[1] = toupper(eigs_sigma[1]);
+
+ // In the following special case we're going to invert the problem, since solving
+ // for larger magnitude is much much faster
+ // i.e., if 'SM' is specified, we're going to really use 'LM', the default
+ //
+ if (eigs_sigma.substr(0,2) != "SM")
+ {
+ whch[0] = eigs_sigma[0];
+ whch[1] = eigs_sigma[1];
+ }
+ }
+ else
+ {
+ eigen_assert(false && "Specifying clustered eigenvalues is not yet supported!");
+
+ // If it's not scalar values, then the user may be explicitly
+ // specifying the sigma value to cluster the evs around
+ //
+ sigma = atof(eigs_sigma.c_str());
+
+ // If atof fails, it returns 0.0, which is a fine default
+ //
+ }
+
+ // "I" means normal eigenvalue problem, "G" means generalized
+ //
+ char bmat[2] = "I";
+ if (eigs_sigma.substr(0,2) == "SM" || !(isalpha(eigs_sigma[0]) && isalpha(eigs_sigma[1])) || (!isBempty && !BisSPD))
+ bmat[0] = 'G';
+
+ // Now we determine the mode to use
+ //
+ int mode = (bmat[0] == 'G') + 1;
+ if (eigs_sigma.substr(0,2) == "SM" || !(isalpha(eigs_sigma[0]) && isalpha(eigs_sigma[1])))
+ {
+ // We're going to use shift-and-invert mode, and basically find
+ // the largest eigenvalues of the inverse operator
+ //
+ mode = 3;
+ }
+
+ // The user-specified number of eigenvalues/vectors to compute
+ //
+ int nev = (int)nbrEigenvalues;
+
+ // Allocate space for ARPACK to store the residual
+ //
+ Scalar *resid = new Scalar[n];
+
+ // Number of Lanczos vectors, must satisfy nev < ncv <= n
+ // Note that this indicates that nev != n, and we cannot compute
+ // all eigenvalues of a mtrix
+ //
+ int ncv = std::min(std::max(2*nev, 20), n);
+
+ // The working n x ncv matrix, also store the final eigenvectors (if computed)
+ //
+ Scalar *v = new Scalar[n*ncv];
+ int ldv = n;
+
+ // Working space
+ //
+ Scalar *workd = new Scalar[3*n];
+ int lworkl = ncv*ncv+8*ncv; // Must be at least this length
+ Scalar *workl = new Scalar[lworkl];
+
+ int *iparam= new int[11];
+ iparam[0] = 1; // 1 means we let ARPACK perform the shifts, 0 means we'd have to do it
+ iparam[2] = std::max(300, (int)std::ceil(2*n/std::max(ncv,1)));
+ iparam[6] = mode; // The mode, 1 is standard ev problem, 2 for generalized ev, 3 for shift-and-invert
+
+ // Used during reverse communicate to notify where arrays start
+ //
+ int *ipntr = new int[11];
+
+ // Error codes are returned in here, initial value of 0 indicates a random initial
+ // residual vector is used, any other values means resid contains the initial residual
+ // vector, possibly from a previous run
+ //
+ int info = 0;
+
+ Scalar scale = 1.0;
+ //if (!isBempty)
+ //{
+ //Scalar scale = B.norm() / std::sqrt(n);
+ //scale = std::pow(2, std::floor(std::log(scale+1)));
+ ////M /= scale;
+ //for (size_t i=0; i<(size_t)B.outerSize(); i++)
+ // for (typename MatrixType::InnerIterator it(B, i); it; ++it)
+ // it.valueRef() /= scale;
+ //}
+
+ MatrixSolver OP;
+ if (mode == 1 || mode == 2)
+ {
+ if (!isBempty)
+ OP.compute(B);
+ }
+ else if (mode == 3)
+ {
+ if (sigma == 0.0)
+ {
+ OP.compute(A);
+ }
+ else
+ {
+ // Note: We will never enter here because sigma must be 0.0
+ //
+ if (isBempty)
+ {
+ MatrixType AminusSigmaB(A);
+ for (Index i=0; i<A.rows(); ++i)
+ AminusSigmaB.coeffRef(i,i) -= sigma;
+
+ OP.compute(AminusSigmaB);
+ }
+ else
+ {
+ MatrixType AminusSigmaB = A - sigma * B;
+ OP.compute(AminusSigmaB);
+ }
+ }
+ }
+
+ if (!(mode == 1 && isBempty) && !(mode == 2 && isBempty) && OP.info() != Success)
+ std::cout << "Error factoring matrix" << std::endl;
+
+ do
+ {
+ internal::arpack_wrapper<Scalar, RealScalar>::saupd(&ido, bmat, &n, whch, &nev, &tol, resid,
+ &ncv, v, &ldv, iparam, ipntr, workd, workl,
+ &lworkl, &info);
+
+ if (ido == -1 || ido == 1)
+ {
+ Scalar *in = workd + ipntr[0] - 1;
+ Scalar *out = workd + ipntr[1] - 1;
+
+ if (ido == 1 && mode != 2)
+ {
+ Scalar *out2 = workd + ipntr[2] - 1;
+ if (isBempty || mode == 1)
+ Matrix<Scalar, Dynamic, 1>::Map(out2, n) = Matrix<Scalar, Dynamic, 1>::Map(in, n);
+ else
+ Matrix<Scalar, Dynamic, 1>::Map(out2, n) = B * Matrix<Scalar, Dynamic, 1>::Map(in, n);
+
+ in = workd + ipntr[2] - 1;
+ }
+
+ if (mode == 1)
+ {
+ if (isBempty)
+ {
+ // OP = A
+ //
+ Matrix<Scalar, Dynamic, 1>::Map(out, n) = A * Matrix<Scalar, Dynamic, 1>::Map(in, n);
+ }
+ else
+ {
+ // OP = L^{-1}AL^{-T}
+ //
+ internal::OP<MatrixSolver, MatrixType, Scalar, BisSPD>::applyOP(OP, A, n, in, out);
+ }
+ }
+ else if (mode == 2)
+ {
+ if (ido == 1)
+ Matrix<Scalar, Dynamic, 1>::Map(in, n) = A * Matrix<Scalar, Dynamic, 1>::Map(in, n);
+
+ // OP = B^{-1} A
+ //
+ Matrix<Scalar, Dynamic, 1>::Map(out, n) = OP.solve(Matrix<Scalar, Dynamic, 1>::Map(in, n));
+ }
+ else if (mode == 3)
+ {
+ // OP = (A-\sigmaB)B (\sigma could be 0, and B could be I)
+ // The B * in is already computed and stored at in if ido == 1
+ //
+ if (ido == 1 || isBempty)
+ Matrix<Scalar, Dynamic, 1>::Map(out, n) = OP.solve(Matrix<Scalar, Dynamic, 1>::Map(in, n));
+ else
+ Matrix<Scalar, Dynamic, 1>::Map(out, n) = OP.solve(B * Matrix<Scalar, Dynamic, 1>::Map(in, n));
+ }
+ }
+ else if (ido == 2)
+ {
+ Scalar *in = workd + ipntr[0] - 1;
+ Scalar *out = workd + ipntr[1] - 1;
+
+ if (isBempty || mode == 1)
+ Matrix<Scalar, Dynamic, 1>::Map(out, n) = Matrix<Scalar, Dynamic, 1>::Map(in, n);
+ else
+ Matrix<Scalar, Dynamic, 1>::Map(out, n) = B * Matrix<Scalar, Dynamic, 1>::Map(in, n);
+ }
+ } while (ido != 99);
+
+ if (info == 1)
+ m_info = NoConvergence;
+ else if (info == 3)
+ m_info = NumericalIssue;
+ else if (info < 0)
+ m_info = InvalidInput;
+ else if (info != 0)
+ eigen_assert(false && "Unknown ARPACK return value!");
+ else
+ {
+ // Do we compute eigenvectors or not?
+ //
+ int rvec = (options & ComputeEigenvectors) == ComputeEigenvectors;
+
+ // "A" means "All", use "S" to choose specific eigenvalues (not yet supported in ARPACK))
+ //
+ char howmny[2] = "A";
+
+ // if howmny == "S", specifies the eigenvalues to compute (not implemented in ARPACK)
+ //
+ int *select = new int[ncv];
+
+ // Final eigenvalues
+ //
+ m_eivalues.resize(nev, 1);
+
+ internal::arpack_wrapper<Scalar, RealScalar>::seupd(&rvec, howmny, select, m_eivalues.data(), v, &ldv,
+ &sigma, bmat, &n, whch, &nev, &tol, resid, &ncv,
+ v, &ldv, iparam, ipntr, workd, workl, &lworkl, &info);
+
+ if (info == -14)
+ m_info = NoConvergence;
+ else if (info != 0)
+ m_info = InvalidInput;
+ else
+ {
+ if (rvec)
+ {
+ m_eivec.resize(A.rows(), nev);
+ for (int i=0; i<nev; i++)
+ for (int j=0; j<n; j++)
+ m_eivec(j,i) = v[i*n+j] / scale;
+
+ if (mode == 1 && !isBempty && BisSPD)
+ internal::OP<MatrixSolver, MatrixType, Scalar, BisSPD>::project(OP, n, nev, m_eivec.data());
+
+ m_eigenvectorsOk = true;
+ }
+
+ m_nbrIterations = iparam[2];
+ m_nbrConverged = iparam[4];
+
+ m_info = Success;
+ }
+
+ delete select;
+ }
+
+ delete v;
+ delete iparam;
+ delete ipntr;
+ delete workd;
+ delete workl;
+ delete resid;
+
+ m_isInitialized = true;
+
+ return *this;
+}
+
+
+// Single precision
+//
+extern "C" void ssaupd_(int *ido, char *bmat, int *n, char *which,
+ int *nev, float *tol, float *resid, int *ncv,
+ float *v, int *ldv, int *iparam, int *ipntr,
+ float *workd, float *workl, int *lworkl,
+ int *info);
+
+extern "C" void sseupd_(int *rvec, char *All, int *select, float *d,
+ float *z, int *ldz, float *sigma,
+ char *bmat, int *n, char *which, int *nev,
+ float *tol, float *resid, int *ncv, float *v,
+ int *ldv, int *iparam, int *ipntr, float *workd,
+ float *workl, int *lworkl, int *ierr);
+
+// Double precision
+//
+extern "C" void dsaupd_(int *ido, char *bmat, int *n, char *which,
+ int *nev, double *tol, double *resid, int *ncv,
+ double *v, int *ldv, int *iparam, int *ipntr,
+ double *workd, double *workl, int *lworkl,
+ int *info);
+
+extern "C" void dseupd_(int *rvec, char *All, int *select, double *d,
+ double *z, int *ldz, double *sigma,
+ char *bmat, int *n, char *which, int *nev,
+ double *tol, double *resid, int *ncv, double *v,
+ int *ldv, int *iparam, int *ipntr, double *workd,
+ double *workl, int *lworkl, int *ierr);
+
+
+namespace internal {
+
+template<typename Scalar, typename RealScalar> struct arpack_wrapper
+{
+ static inline void saupd(int *ido, char *bmat, int *n, char *which,
+ int *nev, RealScalar *tol, Scalar *resid, int *ncv,
+ Scalar *v, int *ldv, int *iparam, int *ipntr,
+ Scalar *workd, Scalar *workl, int *lworkl, int *info)
+ {
+ EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsComplex, NUMERIC_TYPE_MUST_BE_REAL)
+ }
+
+ static inline void seupd(int *rvec, char *All, int *select, Scalar *d,
+ Scalar *z, int *ldz, RealScalar *sigma,
+ char *bmat, int *n, char *which, int *nev,
+ RealScalar *tol, Scalar *resid, int *ncv, Scalar *v,
+ int *ldv, int *iparam, int *ipntr, Scalar *workd,
+ Scalar *workl, int *lworkl, int *ierr)
+ {
+ EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsComplex, NUMERIC_TYPE_MUST_BE_REAL)
+ }
+};
+
+template <> struct arpack_wrapper<float, float>
+{
+ static inline void saupd(int *ido, char *bmat, int *n, char *which,
+ int *nev, float *tol, float *resid, int *ncv,
+ float *v, int *ldv, int *iparam, int *ipntr,
+ float *workd, float *workl, int *lworkl, int *info)
+ {
+ ssaupd_(ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, info);
+ }
+
+ static inline void seupd(int *rvec, char *All, int *select, float *d,
+ float *z, int *ldz, float *sigma,
+ char *bmat, int *n, char *which, int *nev,
+ float *tol, float *resid, int *ncv, float *v,
+ int *ldv, int *iparam, int *ipntr, float *workd,
+ float *workl, int *lworkl, int *ierr)
+ {
+ sseupd_(rvec, All, select, d, z, ldz, sigma, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam, ipntr,
+ workd, workl, lworkl, ierr);
+ }
+};
+
+template <> struct arpack_wrapper<double, double>
+{
+ static inline void saupd(int *ido, char *bmat, int *n, char *which,
+ int *nev, double *tol, double *resid, int *ncv,
+ double *v, int *ldv, int *iparam, int *ipntr,
+ double *workd, double *workl, int *lworkl, int *info)
+ {
+ dsaupd_(ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, info);
+ }
+
+ static inline void seupd(int *rvec, char *All, int *select, double *d,
+ double *z, int *ldz, double *sigma,
+ char *bmat, int *n, char *which, int *nev,
+ double *tol, double *resid, int *ncv, double *v,
+ int *ldv, int *iparam, int *ipntr, double *workd,
+ double *workl, int *lworkl, int *ierr)
+ {
+ dseupd_(rvec, All, select, d, v, ldv, sigma, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam, ipntr,
+ workd, workl, lworkl, ierr);
+ }
+};
+
+
+template<typename MatrixSolver, typename MatrixType, typename Scalar, bool BisSPD>
+struct OP
+{
+ static inline void applyOP(MatrixSolver &OP, const MatrixType &A, int n, Scalar *in, Scalar *out);
+ static inline void project(MatrixSolver &OP, int n, int k, Scalar *vecs);
+};
+
+template<typename MatrixSolver, typename MatrixType, typename Scalar>
+struct OP<MatrixSolver, MatrixType, Scalar, true>
+{
+ static inline void applyOP(MatrixSolver &OP, const MatrixType &A, int n, Scalar *in, Scalar *out)
+{
+ // OP = L^{-1} A L^{-T} (B = LL^T)
+ //
+ // First solve L^T out = in
+ //
+ Matrix<Scalar, Dynamic, 1>::Map(out, n) = OP.matrixU().solve(Matrix<Scalar, Dynamic, 1>::Map(in, n));
+ Matrix<Scalar, Dynamic, 1>::Map(out, n) = OP.permutationPinv() * Matrix<Scalar, Dynamic, 1>::Map(out, n);
+
+ // Then compute out = A out
+ //
+ Matrix<Scalar, Dynamic, 1>::Map(out, n) = A * Matrix<Scalar, Dynamic, 1>::Map(out, n);
+
+ // Then solve L out = out
+ //
+ Matrix<Scalar, Dynamic, 1>::Map(out, n) = OP.permutationP() * Matrix<Scalar, Dynamic, 1>::Map(out, n);
+ Matrix<Scalar, Dynamic, 1>::Map(out, n) = OP.matrixL().solve(Matrix<Scalar, Dynamic, 1>::Map(out, n));
+}
+
+ static inline void project(MatrixSolver &OP, int n, int k, Scalar *vecs)
+{
+ // Solve L^T out = in
+ //
+ Matrix<Scalar, Dynamic, Dynamic>::Map(vecs, n, k) = OP.matrixU().solve(Matrix<Scalar, Dynamic, Dynamic>::Map(vecs, n, k));
+ Matrix<Scalar, Dynamic, Dynamic>::Map(vecs, n, k) = OP.permutationPinv() * Matrix<Scalar, Dynamic, Dynamic>::Map(vecs, n, k);
+}
+
+};
+
+template<typename MatrixSolver, typename MatrixType, typename Scalar>
+struct OP<MatrixSolver, MatrixType, Scalar, false>
+{
+ static inline void applyOP(MatrixSolver &OP, const MatrixType &A, int n, Scalar *in, Scalar *out)
+{
+ eigen_assert(false && "Should never be in here...");
+}
+
+ static inline void project(MatrixSolver &OP, int n, int k, Scalar *vecs)
+{
+ eigen_assert(false && "Should never be in here...");
+}
+
+};
+
+} // end namespace internal
+
+} // end namespace Eigen
+
+#endif // EIGEN_ARPACKSELFADJOINTEIGENSOLVER_H
+
diff --git a/unsupported/Eigen/src/FFT/ei_kissfft_impl.h b/unsupported/Eigen/src/FFT/ei_kissfft_impl.h
index 37f5af4c1..be51b4e6f 100644
--- a/unsupported/Eigen/src/FFT/ei_kissfft_impl.h
+++ b/unsupported/Eigen/src/FFT/ei_kissfft_impl.h
@@ -28,6 +28,7 @@ struct kiss_cpx_fft
inline
void make_twiddles(int nfft,bool inverse)
{
+ using std::acos;
m_inverse = inverse;
m_twiddles.resize(nfft);
Scalar phinc = (inverse?2:-2)* acos( (Scalar) -1) / nfft;
@@ -399,6 +400,7 @@ struct kissfft_impl
inline
Complex * real_twiddles(int ncfft2)
{
+ using std::acos;
std::vector<Complex> & twidref = m_realTwiddles[ncfft2];// creates new if not there
if ( (int)twidref.size() != ncfft2 ) {
twidref.resize(ncfft2);
diff --git a/unsupported/Eigen/src/IterativeSolvers/ConstrainedConjGrad.h b/unsupported/Eigen/src/IterativeSolvers/ConstrainedConjGrad.h
index b83bf7aef..dc0093eb9 100644
--- a/unsupported/Eigen/src/IterativeSolvers/ConstrainedConjGrad.h
+++ b/unsupported/Eigen/src/IterativeSolvers/ConstrainedConjGrad.h
@@ -2,10 +2,6 @@
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// This Source Code Form is subject to the terms of the Mozilla
-// Public License v. 2.0. If a copy of the MPL was not distributed
-// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
/* NOTE The functions of this file have been adapted from the GMM++ library */
@@ -62,7 +58,9 @@ void pseudo_inverse(const CMatrix &C, CINVMatrix &CINV)
Scalar rho, rho_1, alpha;
d.setZero();
- CINV.startFill(); // FIXME estimate the number of non-zeros
+ typedef Triplet<double> T;
+ std::vector<T> tripletList;
+
for (Index i = 0; i < rows; ++i)
{
d[i] = 1.0;
@@ -88,11 +86,12 @@ void pseudo_inverse(const CMatrix &C, CINVMatrix &CINV)
// FIXME add a generic "prune/filter" expression for both dense and sparse object to sparse
for (Index j=0; j<l.size(); ++j)
if (l[j]<1e-15)
- CINV.fill(i,j) = l[j];
+ tripletList.push_back(T(i,j,l(j)));
+
d[i] = 0.0;
}
- CINV.endFill();
+ CINV.setFromTriplets(tripletList.begin(), tripletList.end());
}
@@ -107,6 +106,7 @@ template<typename TMatrix, typename CMatrix,
void constrained_cg(const TMatrix& A, const CMatrix& C, VectorX& x,
const VectorB& b, const VectorF& f, IterationController &iter)
{
+ using std::sqrt;
typedef typename TMatrix::Scalar Scalar;
typedef typename TMatrix::Index Index;
typedef Matrix<Scalar,Dynamic,1> TmpVec;
diff --git a/unsupported/Eigen/src/IterativeSolvers/DGMRES.h b/unsupported/Eigen/src/IterativeSolvers/DGMRES.h
new file mode 100644
index 000000000..9fcc8a8d9
--- /dev/null
+++ b/unsupported/Eigen/src/IterativeSolvers/DGMRES.h
@@ -0,0 +1,542 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef EIGEN_DGMRES_H
+#define EIGEN_DGMRES_H
+
+#include <Eigen/Eigenvalues>
+
+namespace Eigen {
+
+template< typename _MatrixType,
+ typename _Preconditioner = DiagonalPreconditioner<typename _MatrixType::Scalar> >
+class DGMRES;
+
+namespace internal {
+
+template< typename _MatrixType, typename _Preconditioner>
+struct traits<DGMRES<_MatrixType,_Preconditioner> >
+{
+ typedef _MatrixType MatrixType;
+ typedef _Preconditioner Preconditioner;
+};
+
+/** \brief Computes a permutation vector to have a sorted sequence
+ * \param vec The vector to reorder.
+ * \param perm gives the sorted sequence on output. Must be initialized with 0..n-1
+ * \param ncut Put the ncut smallest elements at the end of the vector
+ * WARNING This is an expensive sort, so should be used only
+ * for small size vectors
+ * TODO Use modified QuickSplit or std::nth_element to get the smallest values
+ */
+template <typename VectorType, typename IndexType>
+void sortWithPermutation (VectorType& vec, IndexType& perm, typename IndexType::Scalar& ncut)
+{
+ eigen_assert(vec.size() == perm.size());
+ typedef typename IndexType::Scalar Index;
+ typedef typename VectorType::Scalar Scalar;
+ bool flag;
+ for (Index k = 0; k < ncut; k++)
+ {
+ flag = false;
+ for (Index j = 0; j < vec.size()-1; j++)
+ {
+ if ( vec(perm(j)) < vec(perm(j+1)) )
+ {
+ std::swap(perm(j),perm(j+1));
+ flag = true;
+ }
+ if (!flag) break; // The vector is in sorted order
+ }
+ }
+}
+
+}
+/**
+ * \ingroup IterativeLInearSolvers_Module
+ * \brief A Restarted GMRES with deflation.
+ * This class implements a modification of the GMRES solver for
+ * sparse linear systems. The basis is built with modified
+ * Gram-Schmidt. At each restart, a few approximated eigenvectors
+ * corresponding to the smallest eigenvalues are used to build a
+ * preconditioner for the next cycle. This preconditioner
+ * for deflation can be combined with any other preconditioner,
+ * the IncompleteLUT for instance. The preconditioner is applied
+ * at right of the matrix and the combination is multiplicative.
+ *
+ * \tparam _MatrixType the type of the sparse matrix A, can be a dense or a sparse matrix.
+ * \tparam _Preconditioner the type of the preconditioner. Default is DiagonalPreconditioner
+ * Typical usage :
+ * \code
+ * SparseMatrix<double> A;
+ * VectorXd x, b;
+ * //Fill A and b ...
+ * DGMRES<SparseMatrix<double> > solver;
+ * solver.set_restart(30); // Set restarting value
+ * solver.setEigenv(1); // Set the number of eigenvalues to deflate
+ * solver.compute(A);
+ * x = solver.solve(b);
+ * \endcode
+ *
+ * References :
+ * [1] D. NUENTSA WAKAM and F. PACULL, Memory Efficient Hybrid
+ * Algebraic Solvers for Linear Systems Arising from Compressible
+ * Flows, Computers and Fluids, In Press,
+ * http://dx.doi.org/10.1016/j.compfluid.2012.03.023
+ * [2] K. Burrage and J. Erhel, On the performance of various
+ * adaptive preconditioned GMRES strategies, 5(1998), 101-121.
+ * [3] J. Erhel, K. Burrage and B. Pohl, Restarted GMRES
+ * preconditioned by deflation,J. Computational and Applied
+ * Mathematics, 69(1996), 303-318.
+
+ *
+ */
+template< typename _MatrixType, typename _Preconditioner>
+class DGMRES : public IterativeSolverBase<DGMRES<_MatrixType,_Preconditioner> >
+{
+ typedef IterativeSolverBase<DGMRES> Base;
+ using Base::mp_matrix;
+ using Base::m_error;
+ using Base::m_iterations;
+ using Base::m_info;
+ using Base::m_isInitialized;
+ using Base::m_tolerance;
+ public:
+ typedef _MatrixType MatrixType;
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::Index Index;
+ typedef typename MatrixType::RealScalar RealScalar;
+ typedef _Preconditioner Preconditioner;
+ typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
+ typedef Matrix<RealScalar,Dynamic,Dynamic> DenseRealMatrix;
+ typedef Matrix<Scalar,Dynamic,1> DenseVector;
+ typedef Matrix<RealScalar,Dynamic,1> DenseRealVector;
+ typedef Matrix<std::complex<RealScalar>, Dynamic, 1> ComplexVector;
+
+
+ /** Default constructor. */
+ DGMRES() : Base(),m_restart(30),m_neig(0),m_r(0),m_maxNeig(5),m_isDeflAllocated(false),m_isDeflInitialized(false) {}
+
+ /** Initialize the solver with matrix \a A for further \c Ax=b solving.
+ *
+ * This constructor is a shortcut for the default constructor followed
+ * by a call to compute().
+ *
+ * \warning this class stores a reference to the matrix A as well as some
+ * precomputed values that depend on it. Therefore, if \a A is changed
+ * this class becomes invalid. Call compute() to update it with the new
+ * matrix A, or modify a copy of A.
+ */
+ DGMRES(const MatrixType& A) : Base(A),m_restart(30),m_neig(0),m_r(0),m_maxNeig(5),m_isDeflAllocated(false),m_isDeflInitialized(false)
+ {}
+
+ ~DGMRES() {}
+
+ /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A
+ * \a x0 as an initial solution.
+ *
+ * \sa compute()
+ */
+ template<typename Rhs,typename Guess>
+ inline const internal::solve_retval_with_guess<DGMRES, Rhs, Guess>
+ solveWithGuess(const MatrixBase<Rhs>& b, const Guess& x0) const
+ {
+ eigen_assert(m_isInitialized && "DGMRES is not initialized.");
+ eigen_assert(Base::rows()==b.rows()
+ && "DGMRES::solve(): invalid number of rows of the right hand side matrix b");
+ return internal::solve_retval_with_guess
+ <DGMRES, Rhs, Guess>(*this, b.derived(), x0);
+ }
+
+ /** \internal */
+ template<typename Rhs,typename Dest>
+ void _solveWithGuess(const Rhs& b, Dest& x) const
+ {
+ bool failed = false;
+ for(int j=0; j<b.cols(); ++j)
+ {
+ m_iterations = Base::maxIterations();
+ m_error = Base::m_tolerance;
+
+ typename Dest::ColXpr xj(x,j);
+ dgmres(*mp_matrix, b.col(j), xj, Base::m_preconditioner);
+ }
+ m_info = failed ? NumericalIssue
+ : m_error <= Base::m_tolerance ? Success
+ : NoConvergence;
+ m_isInitialized = true;
+ }
+
+ /** \internal */
+ template<typename Rhs,typename Dest>
+ void _solve(const Rhs& b, Dest& x) const
+ {
+ x = b;
+ _solveWithGuess(b,x);
+ }
+ /**
+ * Get the restart value
+ */
+ int restart() { return m_restart; }
+
+ /**
+ * Set the restart value (default is 30)
+ */
+ void set_restart(const int restart) { m_restart=restart; }
+
+ /**
+ * Set the number of eigenvalues to deflate at each restart
+ */
+ void setEigenv(const int neig)
+ {
+ m_neig = neig;
+ if (neig+1 > m_maxNeig) m_maxNeig = neig+1; // To allow for complex conjugates
+ }
+
+ /**
+ * Get the size of the deflation subspace size
+ */
+ int deflSize() {return m_r; }
+
+ /**
+ * Set the maximum size of the deflation subspace
+ */
+ void setMaxEigenv(const int maxNeig) { m_maxNeig = maxNeig; }
+
+ protected:
+ // DGMRES algorithm
+ template<typename Rhs, typename Dest>
+ void dgmres(const MatrixType& mat,const Rhs& rhs, Dest& x, const Preconditioner& precond) const;
+ // Perform one cycle of GMRES
+ template<typename Dest>
+ int dgmresCycle(const MatrixType& mat, const Preconditioner& precond, Dest& x, DenseVector& r0, RealScalar& beta, const RealScalar& normRhs, int& nbIts) const;
+ // Compute data to use for deflation
+ int dgmresComputeDeflationData(const MatrixType& mat, const Preconditioner& precond, const Index& it, Index& neig) const;
+ // Apply deflation to a vector
+ template<typename RhsType, typename DestType>
+ int dgmresApplyDeflation(const RhsType& In, DestType& Out) const;
+ ComplexVector schurValues(const ComplexSchur<DenseMatrix>& schurofH) const;
+ ComplexVector schurValues(const RealSchur<DenseMatrix>& schurofH) const;
+ // Init data for deflation
+ void dgmresInitDeflation(Index& rows) const;
+ mutable DenseMatrix m_V; // Krylov basis vectors
+ mutable DenseMatrix m_H; // Hessenberg matrix
+ mutable DenseMatrix m_Hes; // Initial hessenberg matrix wihout Givens rotations applied
+ mutable Index m_restart; // Maximum size of the Krylov subspace
+ mutable DenseMatrix m_U; // Vectors that form the basis of the invariant subspace
+ mutable DenseMatrix m_MU; // matrix operator applied to m_U (for next cycles)
+ mutable DenseMatrix m_T; /* T=U^T*M^{-1}*A*U */
+ mutable PartialPivLU<DenseMatrix> m_luT; // LU factorization of m_T
+ mutable int m_neig; //Number of eigenvalues to extract at each restart
+ mutable int m_r; // Current number of deflated eigenvalues, size of m_U
+ mutable int m_maxNeig; // Maximum number of eigenvalues to deflate
+ mutable RealScalar m_lambdaN; //Modulus of the largest eigenvalue of A
+ mutable bool m_isDeflAllocated;
+ mutable bool m_isDeflInitialized;
+
+ //Adaptive strategy
+ mutable RealScalar m_smv; // Smaller multiple of the remaining number of steps allowed
+ mutable bool m_force; // Force the use of deflation at each restart
+
+};
+/**
+ * \brief Perform several cycles of restarted GMRES with modified Gram Schmidt,
+ *
+ * A right preconditioner is used combined with deflation.
+ *
+ */
+template< typename _MatrixType, typename _Preconditioner>
+template<typename Rhs, typename Dest>
+void DGMRES<_MatrixType, _Preconditioner>::dgmres(const MatrixType& mat,const Rhs& rhs, Dest& x,
+ const Preconditioner& precond) const
+{
+ //Initialization
+ int n = mat.rows();
+ DenseVector r0(n);
+ int nbIts = 0;
+ m_H.resize(m_restart+1, m_restart);
+ m_Hes.resize(m_restart, m_restart);
+ m_V.resize(n,m_restart+1);
+ //Initial residual vector and intial norm
+ x = precond.solve(x);
+ r0 = rhs - mat * x;
+ RealScalar beta = r0.norm();
+ RealScalar normRhs = rhs.norm();
+ m_error = beta/normRhs;
+ if(m_error < m_tolerance)
+ m_info = Success;
+ else
+ m_info = NoConvergence;
+
+ // Iterative process
+ while (nbIts < m_iterations && m_info == NoConvergence)
+ {
+ dgmresCycle(mat, precond, x, r0, beta, normRhs, nbIts);
+
+ // Compute the new residual vector for the restart
+ if (nbIts < m_iterations && m_info == NoConvergence)
+ r0 = rhs - mat * x;
+ }
+}
+
+/**
+ * \brief Perform one restart cycle of DGMRES
+ * \param mat The coefficient matrix
+ * \param precond The preconditioner
+ * \param x the new approximated solution
+ * \param r0 The initial residual vector
+ * \param beta The norm of the residual computed so far
+ * \param normRhs The norm of the right hand side vector
+ * \param nbIts The number of iterations
+ */
+template< typename _MatrixType, typename _Preconditioner>
+template<typename Dest>
+int DGMRES<_MatrixType, _Preconditioner>::dgmresCycle(const MatrixType& mat, const Preconditioner& precond, Dest& x, DenseVector& r0, RealScalar& beta, const RealScalar& normRhs, int& nbIts) const
+{
+ //Initialization
+ DenseVector g(m_restart+1); // Right hand side of the least square problem
+ g.setZero();
+ g(0) = Scalar(beta);
+ m_V.col(0) = r0/beta;
+ m_info = NoConvergence;
+ std::vector<JacobiRotation<Scalar> >gr(m_restart); // Givens rotations
+ int it = 0; // Number of inner iterations
+ int n = mat.rows();
+ DenseVector tv1(n), tv2(n); //Temporary vectors
+ while (m_info == NoConvergence && it < m_restart && nbIts < m_iterations)
+ {
+ // Apply preconditioner(s) at right
+ if (m_isDeflInitialized )
+ {
+ dgmresApplyDeflation(m_V.col(it), tv1); // Deflation
+ tv2 = precond.solve(tv1);
+ }
+ else
+ {
+ tv2 = precond.solve(m_V.col(it)); // User's selected preconditioner
+ }
+ tv1 = mat * tv2;
+
+ // Orthogonalize it with the previous basis in the basis using modified Gram-Schmidt
+ Scalar coef;
+ for (int i = 0; i <= it; ++i)
+ {
+ coef = tv1.dot(m_V.col(i));
+ tv1 = tv1 - coef * m_V.col(i);
+ m_H(i,it) = coef;
+ m_Hes(i,it) = coef;
+ }
+ // Normalize the vector
+ coef = tv1.norm();
+ m_V.col(it+1) = tv1/coef;
+ m_H(it+1, it) = coef;
+// m_Hes(it+1,it) = coef;
+
+ // FIXME Check for happy breakdown
+
+ // Update Hessenberg matrix with Givens rotations
+ for (int i = 1; i <= it; ++i)
+ {
+ m_H.col(it).applyOnTheLeft(i-1,i,gr[i-1].adjoint());
+ }
+ // Compute the new plane rotation
+ gr[it].makeGivens(m_H(it, it), m_H(it+1,it));
+ // Apply the new rotation
+ m_H.col(it).applyOnTheLeft(it,it+1,gr[it].adjoint());
+ g.applyOnTheLeft(it,it+1, gr[it].adjoint());
+
+ beta = std::abs(g(it+1));
+ m_error = beta/normRhs;
+ std::cerr << nbIts << " Relative Residual Norm " << m_error << std::endl;
+ it++; nbIts++;
+
+ if (m_error < m_tolerance)
+ {
+ // The method has converged
+ m_info = Success;
+ break;
+ }
+ }
+
+ // Compute the new coefficients by solving the least square problem
+// it++;
+ //FIXME Check first if the matrix is singular ... zero diagonal
+ DenseVector nrs(m_restart);
+ nrs = m_H.topLeftCorner(it,it).template triangularView<Upper>().solve(g.head(it));
+
+ // Form the new solution
+ if (m_isDeflInitialized)
+ {
+ tv1 = m_V.leftCols(it) * nrs;
+ dgmresApplyDeflation(tv1, tv2);
+ x = x + precond.solve(tv2);
+ }
+ else
+ x = x + precond.solve(m_V.leftCols(it) * nrs);
+
+ // Go for a new cycle and compute data for deflation
+ if(nbIts < m_iterations && m_info == NoConvergence && m_neig > 0 && (m_r+m_neig) < m_maxNeig)
+ dgmresComputeDeflationData(mat, precond, it, m_neig);
+ return 0;
+
+}
+
+
+template< typename _MatrixType, typename _Preconditioner>
+void DGMRES<_MatrixType, _Preconditioner>::dgmresInitDeflation(Index& rows) const
+{
+ m_U.resize(rows, m_maxNeig);
+ m_MU.resize(rows, m_maxNeig);
+ m_T.resize(m_maxNeig, m_maxNeig);
+ m_lambdaN = 0.0;
+ m_isDeflAllocated = true;
+}
+
+template< typename _MatrixType, typename _Preconditioner>
+inline typename DGMRES<_MatrixType, _Preconditioner>::ComplexVector DGMRES<_MatrixType, _Preconditioner>::schurValues(const ComplexSchur<DenseMatrix>& schurofH) const
+{
+ return schurofH.matrixT().diagonal();
+}
+
+template< typename _MatrixType, typename _Preconditioner>
+inline typename DGMRES<_MatrixType, _Preconditioner>::ComplexVector DGMRES<_MatrixType, _Preconditioner>::schurValues(const RealSchur<DenseMatrix>& schurofH) const
+{
+ typedef typename MatrixType::Index Index;
+ const DenseMatrix& T = schurofH.matrixT();
+ Index it = T.rows();
+ ComplexVector eig(it);
+ Index j = 0;
+ while (j < it-1)
+ {
+ if (T(j+1,j) ==Scalar(0))
+ {
+ eig(j) = std::complex<RealScalar>(T(j,j),RealScalar(0));
+ j++;
+ }
+ else
+ {
+ eig(j) = std::complex<RealScalar>(T(j,j),T(j+1,j));
+ eig(j+1) = std::complex<RealScalar>(T(j,j+1),T(j+1,j+1));
+ j++;
+ }
+ }
+ if (j < it-1) eig(j) = std::complex<RealScalar>(T(j,j),RealScalar(0));
+ return eig;
+}
+
+template< typename _MatrixType, typename _Preconditioner>
+int DGMRES<_MatrixType, _Preconditioner>::dgmresComputeDeflationData(const MatrixType& mat, const Preconditioner& precond, const Index& it, Index& neig) const
+{
+ // First, find the Schur form of the Hessenberg matrix H
+ typename internal::conditional<NumTraits<Scalar>::IsComplex, ComplexSchur<DenseMatrix>, RealSchur<DenseMatrix> >::type schurofH;
+ bool computeU = true;
+ DenseMatrix matrixQ(it,it);
+ matrixQ.setIdentity();
+ schurofH.computeFromHessenberg(m_Hes.topLeftCorner(it,it), matrixQ, computeU);
+
+ ComplexVector eig(it);
+ Matrix<Index,Dynamic,1>perm(it);
+ eig = this->schurValues(schurofH);
+
+ // Reorder the absolute values of Schur values
+ DenseRealVector modulEig(it);
+ for (int j=0; j<it; ++j) modulEig(j) = std::abs(eig(j));
+ perm.setLinSpaced(it,0,it-1);
+ internal::sortWithPermutation(modulEig, perm, neig);
+
+ if (!m_lambdaN)
+ {
+ m_lambdaN = (std::max)(modulEig.maxCoeff(), m_lambdaN);
+ }
+ //Count the real number of extracted eigenvalues (with complex conjugates)
+ int nbrEig = 0;
+ while (nbrEig < neig)
+ {
+ if(eig(perm(it-nbrEig-1)).imag() == RealScalar(0)) nbrEig++;
+ else nbrEig += 2;
+ }
+ // Extract the Schur vectors corresponding to the smallest Ritz values
+ DenseMatrix Sr(it, nbrEig);
+ Sr.setZero();
+ for (int j = 0; j < nbrEig; j++)
+ {
+ Sr.col(j) = schurofH.matrixU().col(perm(it-j-1));
+ }
+
+ // Form the Schur vectors of the initial matrix using the Krylov basis
+ DenseMatrix X;
+ X = m_V.leftCols(it) * Sr;
+ if (m_r)
+ {
+ // Orthogonalize X against m_U using modified Gram-Schmidt
+ for (int j = 0; j < nbrEig; j++)
+ for (int k =0; k < m_r; k++)
+ X.col(j) = X.col(j) - (m_U.col(k).dot(X.col(j)))*m_U.col(k);
+ }
+
+ // Compute m_MX = A * M^-1 * X
+ Index m = m_V.rows();
+ if (!m_isDeflAllocated)
+ dgmresInitDeflation(m);
+ DenseMatrix MX(m, nbrEig);
+ DenseVector tv1(m);
+ for (int j = 0; j < nbrEig; j++)
+ {
+ tv1 = mat * X.col(j);
+ MX.col(j) = precond.solve(tv1);
+ }
+
+ //Update m_T = [U'MU U'MX; X'MU X'MX]
+ m_T.block(m_r, m_r, nbrEig, nbrEig) = X.transpose() * MX;
+ if(m_r)
+ {
+ m_T.block(0, m_r, m_r, nbrEig) = m_U.leftCols(m_r).transpose() * MX;
+ m_T.block(m_r, 0, nbrEig, m_r) = X.transpose() * m_MU.leftCols(m_r);
+ }
+
+ // Save X into m_U and m_MX in m_MU
+ for (int j = 0; j < nbrEig; j++) m_U.col(m_r+j) = X.col(j);
+ for (int j = 0; j < nbrEig; j++) m_MU.col(m_r+j) = MX.col(j);
+ // Increase the size of the invariant subspace
+ m_r += nbrEig;
+
+ // Factorize m_T into m_luT
+ m_luT.compute(m_T.topLeftCorner(m_r, m_r));
+
+ //FIXME CHeck if the factorization was correctly done (nonsingular matrix)
+ m_isDeflInitialized = true;
+ return 0;
+}
+template<typename _MatrixType, typename _Preconditioner>
+template<typename RhsType, typename DestType>
+int DGMRES<_MatrixType, _Preconditioner>::dgmresApplyDeflation(const RhsType &x, DestType &y) const
+{
+ DenseVector x1 = m_U.leftCols(m_r).transpose() * x;
+ y = x + m_U.leftCols(m_r) * ( m_lambdaN * m_luT.solve(x1) - x1);
+ return 0;
+}
+
+namespace internal {
+
+ template<typename _MatrixType, typename _Preconditioner, typename Rhs>
+struct solve_retval<DGMRES<_MatrixType, _Preconditioner>, Rhs>
+ : solve_retval_base<DGMRES<_MatrixType, _Preconditioner>, Rhs>
+{
+ typedef DGMRES<_MatrixType, _Preconditioner> Dec;
+ EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs)
+
+ template<typename Dest> void evalTo(Dest& dst) const
+ {
+ dec()._solve(rhs(),dst);
+ }
+};
+} // end namespace internal
+
+} // end namespace Eigen
+#endif
diff --git a/unsupported/Eigen/src/IterativeSolvers/GMRES.h b/unsupported/Eigen/src/IterativeSolvers/GMRES.h
index 34e67db82..c8c84069e 100644
--- a/unsupported/Eigen/src/IterativeSolvers/GMRES.h
+++ b/unsupported/Eigen/src/IterativeSolvers/GMRES.h
@@ -2,7 +2,7 @@
// for linear algebra.
//
// Copyright (C) 2011 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2012 Kolja Brix <brix@igpm.rwth-aaachen.de>
+// Copyright (C) 2012, 2014 Kolja Brix <brix@igpm.rwth-aaachen.de>
//
// 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
@@ -61,7 +61,6 @@ bool gmres(const MatrixType & mat, const Rhs & rhs, Dest & x, const Precondition
typedef typename Dest::RealScalar RealScalar;
typedef typename Dest::Scalar Scalar;
- typedef Matrix < RealScalar, Dynamic, 1 > RealVectorType;
typedef Matrix < Scalar, Dynamic, 1 > VectorType;
typedef Matrix < Scalar, Dynamic, Dynamic > FMatrixType;
@@ -73,16 +72,20 @@ bool gmres(const MatrixType & mat, const Rhs & rhs, Dest & x, const Precondition
VectorType p0 = rhs - mat*x;
VectorType r0 = precond.solve(p0);
-// RealScalar r0_sqnorm = r0.squaredNorm();
+
+ // is initial guess already good enough?
+ if(abs(r0.norm()) < tol) {
+ return true;
+ }
VectorType w = VectorType::Zero(restart + 1);
- FMatrixType H = FMatrixType::Zero(m, restart + 1);
+ FMatrixType H = FMatrixType::Zero(m, restart + 1); // Hessenberg matrix
VectorType tau = VectorType::Zero(restart + 1);
std::vector < JacobiRotation < Scalar > > G(restart);
// generate first Householder vector
- VectorType e;
+ VectorType e(m-1);
RealScalar beta;
r0.makeHouseholder(e, tau.coeffRef(0), beta);
w(0)=(Scalar) beta;
@@ -348,7 +351,8 @@ public:
template<typename Rhs,typename Dest>
void _solve(const Rhs& b, Dest& x) const
{
- x.setZero();
+ x = b;
+ if(x.squaredNorm() == 0) return; // Check Zero right hand side
_solveWithGuess(b,x);
}
diff --git a/unsupported/Eigen/src/IterativeSolvers/IncompleteCholesky.h b/unsupported/Eigen/src/IterativeSolvers/IncompleteCholesky.h
new file mode 100644
index 000000000..661c1f2e0
--- /dev/null
+++ b/unsupported/Eigen/src/IterativeSolvers/IncompleteCholesky.h
@@ -0,0 +1,278 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef EIGEN_INCOMPLETE_CHOlESKY_H
+#define EIGEN_INCOMPLETE_CHOlESKY_H
+#include "Eigen/src/IterativeLinearSolvers/IncompleteLUT.h"
+#include <Eigen/OrderingMethods>
+#include <list>
+
+namespace Eigen {
+/**
+ * \brief Modified Incomplete Cholesky with dual threshold
+ *
+ * References : C-J. Lin and J. J. Moré, Incomplete Cholesky Factorizations with
+ * Limited memory, SIAM J. Sci. Comput. 21(1), pp. 24-45, 1999
+ *
+ * \tparam _MatrixType The type of the sparse matrix. It should be a symmetric
+ * matrix. It is advised to give a row-oriented sparse matrix
+ * \tparam _UpLo The triangular part of the matrix to reference.
+ * \tparam _OrderingType
+ */
+
+template <typename Scalar, int _UpLo = Lower, typename _OrderingType = NaturalOrdering<int> >
+class IncompleteCholesky : internal::noncopyable
+{
+ public:
+ typedef SparseMatrix<Scalar,ColMajor> MatrixType;
+ typedef _OrderingType OrderingType;
+ typedef typename MatrixType::RealScalar RealScalar;
+ typedef typename MatrixType::Index Index;
+ typedef PermutationMatrix<Dynamic, Dynamic, Index> PermutationType;
+ typedef Matrix<Scalar,Dynamic,1> ScalarType;
+ typedef Matrix<Index,Dynamic, 1> IndexType;
+ typedef std::vector<std::list<Index> > VectorList;
+ enum { UpLo = _UpLo };
+ public:
+ IncompleteCholesky() : m_shift(1),m_factorizationIsOk(false) {}
+ IncompleteCholesky(const MatrixType& matrix) : m_shift(1),m_factorizationIsOk(false)
+ {
+ compute(matrix);
+ }
+
+ Index rows() const { return m_L.rows(); }
+
+ Index cols() const { return m_L.cols(); }
+
+
+ /** \brief Reports whether previous computation was successful.
+ *
+ * \returns \c Success if computation was succesful,
+ * \c NumericalIssue if the matrix appears to be negative.
+ */
+ ComputationInfo info() const
+ {
+ eigen_assert(m_isInitialized && "IncompleteLLT is not initialized.");
+ return m_info;
+ }
+
+ /**
+ * \brief Set the initial shift parameter
+ */
+ void setShift( Scalar shift) { m_shift = shift; }
+
+ /**
+ * \brief Computes the fill reducing permutation vector.
+ */
+ template<typename MatrixType>
+ void analyzePattern(const MatrixType& mat)
+ {
+ OrderingType ord;
+ ord(mat.template selfadjointView<UpLo>(), m_perm);
+ m_analysisIsOk = true;
+ }
+
+ template<typename MatrixType>
+ void factorize(const MatrixType& amat);
+
+ template<typename MatrixType>
+ void compute (const MatrixType& matrix)
+ {
+ analyzePattern(matrix);
+ factorize(matrix);
+ }
+
+ template<typename Rhs, typename Dest>
+ void _solve(const Rhs& b, Dest& x) const
+ {
+ eigen_assert(m_factorizationIsOk && "factorize() should be called first");
+ if (m_perm.rows() == b.rows())
+ x = m_perm.inverse() * b;
+ else
+ x = b;
+ x = m_scal.asDiagonal() * x;
+ x = m_L.template triangularView<UnitLower>().solve(x);
+ x = m_L.adjoint().template triangularView<Upper>().solve(x);
+ if (m_perm.rows() == b.rows())
+ x = m_perm * x;
+ x = m_scal.asDiagonal() * x;
+ }
+ template<typename Rhs> inline const internal::solve_retval<IncompleteCholesky, Rhs>
+ solve(const MatrixBase<Rhs>& b) const
+ {
+ eigen_assert(m_factorizationIsOk && "IncompleteLLT did not succeed");
+ eigen_assert(m_isInitialized && "IncompleteLLT is not initialized.");
+ eigen_assert(cols()==b.rows()
+ && "IncompleteLLT::solve(): invalid number of rows of the right hand side matrix b");
+ return internal::solve_retval<IncompleteCholesky, Rhs>(*this, b.derived());
+ }
+ protected:
+ SparseMatrix<Scalar,ColMajor> m_L; // The lower part stored in CSC
+ ScalarType m_scal; // The vector for scaling the matrix
+ Scalar m_shift; //The initial shift parameter
+ bool m_analysisIsOk;
+ bool m_factorizationIsOk;
+ bool m_isInitialized;
+ ComputationInfo m_info;
+ PermutationType m_perm;
+
+ private:
+ template <typename IdxType, typename SclType>
+ inline void updateList(const IdxType& colPtr, IdxType& rowIdx, SclType& vals, const Index& col, const Index& jk, IndexType& firstElt, VectorList& listCol);
+};
+
+template<typename Scalar, int _UpLo, typename OrderingType>
+template<typename _MatrixType>
+void IncompleteCholesky<Scalar,_UpLo, OrderingType>::factorize(const _MatrixType& mat)
+{
+ using std::sqrt;
+ using std::min;
+ eigen_assert(m_analysisIsOk && "analyzePattern() should be called first");
+
+ // Dropping strategies : Keep only the p largest elements per column, where p is the number of elements in the column of the original matrix. Other strategies will be added
+
+ // Apply the fill-reducing permutation computed in analyzePattern()
+ if (m_perm.rows() == mat.rows() ) // To detect the null permutation
+ m_L.template selfadjointView<Lower>() = mat.template selfadjointView<_UpLo>().twistedBy(m_perm);
+ else
+ m_L.template selfadjointView<Lower>() = mat.template selfadjointView<_UpLo>();
+
+ Index n = m_L.cols();
+ Index nnz = m_L.nonZeros();
+ Map<ScalarType> vals(m_L.valuePtr(), nnz); //values
+ Map<IndexType> rowIdx(m_L.innerIndexPtr(), nnz); //Row indices
+ Map<IndexType> colPtr( m_L.outerIndexPtr(), n+1); // Pointer to the beginning of each row
+ IndexType firstElt(n-1); // for each j, points to the next entry in vals that will be used in the factorization
+ VectorList listCol(n); // listCol(j) is a linked list of columns to update column j
+ ScalarType curCol(n); // Store a nonzero values in each column
+ IndexType irow(n); // Row indices of nonzero elements in each column
+
+
+ // Computes the scaling factors
+ m_scal.resize(n);
+ for (int j = 0; j < n; j++)
+ {
+ m_scal(j) = m_L.col(j).norm();
+ m_scal(j) = sqrt(m_scal(j));
+ }
+ // Scale and compute the shift for the matrix
+ Scalar mindiag = vals[0];
+ for (int j = 0; j < n; j++){
+ for (int k = colPtr[j]; k < colPtr[j+1]; k++)
+ vals[k] /= (m_scal(j) * m_scal(rowIdx[k]));
+ mindiag = (min)(vals[colPtr[j]], mindiag);
+ }
+
+ if(mindiag < Scalar(0.)) m_shift = m_shift - mindiag;
+ // Apply the shift to the diagonal elements of the matrix
+ for (int j = 0; j < n; j++)
+ vals[colPtr[j]] += m_shift;
+ // jki version of the Cholesky factorization
+ for (int j=0; j < n; ++j)
+ {
+ //Left-looking factorize the column j
+ // First, load the jth column into curCol
+ Scalar diag = vals[colPtr[j]]; // It is assumed that only the lower part is stored
+ curCol.setZero();
+ irow.setLinSpaced(n,0,n-1);
+ for (int i = colPtr[j] + 1; i < colPtr[j+1]; i++)
+ {
+ curCol(rowIdx[i]) = vals[i];
+ irow(rowIdx[i]) = rowIdx[i];
+ }
+ std::list<int>::iterator k;
+ // Browse all previous columns that will update column j
+ for(k = listCol[j].begin(); k != listCol[j].end(); k++)
+ {
+ int jk = firstElt(*k); // First element to use in the column
+ jk += 1;
+ for (int i = jk; i < colPtr[*k+1]; i++)
+ {
+ curCol(rowIdx[i]) -= vals[i] * vals[jk] ;
+ }
+ updateList(colPtr,rowIdx,vals, *k, jk, firstElt, listCol);
+ }
+
+ // Scale the current column
+ if(RealScalar(diag) <= 0)
+ {
+ std::cerr << "\nNegative diagonal during Incomplete factorization... "<< j << "\n";
+ m_info = NumericalIssue;
+ return;
+ }
+ RealScalar rdiag = sqrt(RealScalar(diag));
+ vals[colPtr[j]] = rdiag;
+ for (int i = j+1; i < n; i++)
+ {
+ //Scale
+ curCol(i) /= rdiag;
+ //Update the remaining diagonals with curCol
+ vals[colPtr[i]] -= curCol(i) * curCol(i);
+ }
+ // Select the largest p elements
+ // p is the original number of elements in the column (without the diagonal)
+ int p = colPtr[j+1] - colPtr[j] - 1 ;
+ internal::QuickSplit(curCol, irow, p);
+ // Insert the largest p elements in the matrix
+ int cpt = 0;
+ for (int i = colPtr[j]+1; i < colPtr[j+1]; i++)
+ {
+ vals[i] = curCol(cpt);
+ rowIdx[i] = irow(cpt);
+ cpt ++;
+ }
+ // Get the first smallest row index and put it after the diagonal element
+ Index jk = colPtr(j)+1;
+ updateList(colPtr,rowIdx,vals,j,jk,firstElt,listCol);
+ }
+ m_factorizationIsOk = true;
+ m_isInitialized = true;
+ m_info = Success;
+}
+
+template<typename Scalar, int _UpLo, typename OrderingType>
+template <typename IdxType, typename SclType>
+inline void IncompleteCholesky<Scalar,_UpLo, OrderingType>::updateList(const IdxType& colPtr, IdxType& rowIdx, SclType& vals, const Index& col, const Index& jk, IndexType& firstElt, VectorList& listCol)
+{
+ if (jk < colPtr(col+1) )
+ {
+ Index p = colPtr(col+1) - jk;
+ Index minpos;
+ rowIdx.segment(jk,p).minCoeff(&minpos);
+ minpos += jk;
+ if (rowIdx(minpos) != rowIdx(jk))
+ {
+ //Swap
+ std::swap(rowIdx(jk),rowIdx(minpos));
+ std::swap(vals(jk),vals(minpos));
+ }
+ firstElt(col) = jk;
+ listCol[rowIdx(jk)].push_back(col);
+ }
+}
+namespace internal {
+
+template<typename _Scalar, int _UpLo, typename OrderingType, typename Rhs>
+struct solve_retval<IncompleteCholesky<_Scalar, _UpLo, OrderingType>, Rhs>
+ : solve_retval_base<IncompleteCholesky<_Scalar, _UpLo, OrderingType>, Rhs>
+{
+ typedef IncompleteCholesky<_Scalar, _UpLo, OrderingType> Dec;
+ EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs)
+
+ template<typename Dest> void evalTo(Dest& dst) const
+ {
+ dec()._solve(rhs(),dst);
+ }
+};
+
+} // end namespace internal
+
+} // end namespace Eigen
+
+#endif
diff --git a/unsupported/Eigen/src/IterativeSolvers/IterationController.h b/unsupported/Eigen/src/IterativeSolvers/IterationController.h
index aaf46d544..c9c1a4be2 100644
--- a/unsupported/Eigen/src/IterativeSolvers/IterationController.h
+++ b/unsupported/Eigen/src/IterativeSolvers/IterationController.h
@@ -2,10 +2,6 @@
// for linear algebra.
//
// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// This Source Code Form is subject to the terms of the Mozilla
-// Public License v. 2.0. If a copy of the MPL was not distributed
-// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
/* NOTE The class IterationController has been adapted from the iteration
* class of the GMM++ and ITL libraries.
@@ -129,7 +125,8 @@ class IterationController
bool converged() const { return m_res <= m_rhsn * m_resmax; }
bool converged(double nr)
{
- m_res = internal::abs(nr);
+ using std::abs;
+ m_res = abs(nr);
m_resminreach = (std::min)(m_resminreach, m_res);
return converged();
}
diff --git a/unsupported/Eigen/src/IterativeSolvers/MINRES.h b/unsupported/Eigen/src/IterativeSolvers/MINRES.h
new file mode 100644
index 000000000..0e56342a8
--- /dev/null
+++ b/unsupported/Eigen/src/IterativeSolvers/MINRES.h
@@ -0,0 +1,302 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Giacomo Po <gpo@ucla.edu>
+// Copyright (C) 2011 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+
+#ifndef EIGEN_MINRES_H_
+#define EIGEN_MINRES_H_
+
+
+namespace Eigen {
+
+ namespace internal {
+
+ /** \internal Low-level MINRES algorithm
+ * \param mat The matrix A
+ * \param rhs The right hand side vector b
+ * \param x On input and initial solution, on output the computed solution.
+ * \param precond A right preconditioner being able to efficiently solve for an
+ * approximation of Ax=b (regardless of b)
+ * \param iters On input the max number of iteration, on output the number of performed iterations.
+ * \param tol_error On input the tolerance error, on output an estimation of the relative error.
+ */
+ template<typename MatrixType, typename Rhs, typename Dest, typename Preconditioner>
+ EIGEN_DONT_INLINE
+ void minres(const MatrixType& mat, const Rhs& rhs, Dest& x,
+ const Preconditioner& precond, int& iters,
+ typename Dest::RealScalar& tol_error)
+ {
+ using std::sqrt;
+ typedef typename Dest::RealScalar RealScalar;
+ typedef typename Dest::Scalar Scalar;
+ typedef Matrix<Scalar,Dynamic,1> VectorType;
+
+ // initialize
+ const int maxIters(iters); // initialize maxIters to iters
+ const int N(mat.cols()); // the size of the matrix
+ const RealScalar rhsNorm2(rhs.squaredNorm());
+ const RealScalar threshold2(tol_error*tol_error*rhsNorm2); // convergence threshold (compared to residualNorm2)
+
+ // Initialize preconditioned Lanczos
+// VectorType v_old(N); // will be initialized inside loop
+ VectorType v( VectorType::Zero(N) ); //initialize v
+ VectorType v_new(rhs-mat*x); //initialize v_new
+ RealScalar residualNorm2(v_new.squaredNorm());
+// VectorType w(N); // will be initialized inside loop
+ VectorType w_new(precond.solve(v_new)); // initialize w_new
+// RealScalar beta; // will be initialized inside loop
+ RealScalar beta_new2(v_new.dot(w_new));
+ eigen_assert(beta_new2 >= 0 && "PRECONDITIONER IS NOT POSITIVE DEFINITE");
+ RealScalar beta_new(sqrt(beta_new2));
+ const RealScalar beta_one(beta_new);
+ v_new /= beta_new;
+ w_new /= beta_new;
+ // Initialize other variables
+ RealScalar c(1.0); // the cosine of the Givens rotation
+ RealScalar c_old(1.0);
+ RealScalar s(0.0); // the sine of the Givens rotation
+ RealScalar s_old(0.0); // the sine of the Givens rotation
+// VectorType p_oold(N); // will be initialized in loop
+ VectorType p_old(VectorType::Zero(N)); // initialize p_old=0
+ VectorType p(p_old); // initialize p=0
+ RealScalar eta(1.0);
+
+ iters = 0; // reset iters
+ while ( iters < maxIters ){
+
+ // Preconditioned Lanczos
+ /* Note that there are 4 variants on the Lanczos algorithm. These are
+ * described in Paige, C. C. (1972). Computational variants of
+ * the Lanczos method for the eigenproblem. IMA Journal of Applied
+ * Mathematics, 10(3), 373–381. The current implementation corresponds
+ * to the case A(2,7) in the paper. It also corresponds to
+ * algorithm 6.14 in Y. Saad, Iterative Methods for Sparse Linear
+ * Systems, 2003 p.173. For the preconditioned version see
+ * A. Greenbaum, Iterative Methods for Solving Linear Systems, SIAM (1987).
+ */
+ const RealScalar beta(beta_new);
+// v_old = v; // update: at first time step, this makes v_old = 0 so value of beta doesn't matter
+ const VectorType v_old(v); // NOT SURE IF CREATING v_old EVERY ITERATION IS EFFICIENT
+ v = v_new; // update
+// w = w_new; // update
+ const VectorType w(w_new); // NOT SURE IF CREATING w EVERY ITERATION IS EFFICIENT
+ v_new.noalias() = mat*w - beta*v_old; // compute v_new
+ const RealScalar alpha = v_new.dot(w);
+ v_new -= alpha*v; // overwrite v_new
+ w_new = precond.solve(v_new); // overwrite w_new
+ beta_new2 = v_new.dot(w_new); // compute beta_new
+ eigen_assert(beta_new2 >= 0 && "PRECONDITIONER IS NOT POSITIVE DEFINITE");
+ beta_new = sqrt(beta_new2); // compute beta_new
+ v_new /= beta_new; // overwrite v_new for next iteration
+ w_new /= beta_new; // overwrite w_new for next iteration
+
+ // Givens rotation
+ const RealScalar r2 =s*alpha+c*c_old*beta; // s, s_old, c and c_old are still from previous iteration
+ const RealScalar r3 =s_old*beta; // s, s_old, c and c_old are still from previous iteration
+ const RealScalar r1_hat=c*alpha-c_old*s*beta;
+ const RealScalar r1 =sqrt( std::pow(r1_hat,2) + std::pow(beta_new,2) );
+ c_old = c; // store for next iteration
+ s_old = s; // store for next iteration
+ c=r1_hat/r1; // new cosine
+ s=beta_new/r1; // new sine
+
+ // Update solution
+// p_oold = p_old;
+ const VectorType p_oold(p_old); // NOT SURE IF CREATING p_oold EVERY ITERATION IS EFFICIENT
+ p_old = p;
+ p.noalias()=(w-r2*p_old-r3*p_oold) /r1; // IS NOALIAS REQUIRED?
+ x += beta_one*c*eta*p;
+ residualNorm2 *= s*s;
+
+ if ( residualNorm2 < threshold2){
+ break;
+ }
+
+ eta=-s*eta; // update eta
+ iters++; // increment iteration number (for output purposes)
+ }
+ tol_error = std::sqrt(residualNorm2 / rhsNorm2); // return error. Note that this is the estimated error. The real error |Ax-b|/|b| may be slightly larger
+ }
+
+ }
+
+ template< typename _MatrixType, int _UpLo=Lower,
+ typename _Preconditioner = IdentityPreconditioner>
+// typename _Preconditioner = IdentityPreconditioner<typename _MatrixType::Scalar> > // preconditioner must be positive definite
+ class MINRES;
+
+ namespace internal {
+
+ template< typename _MatrixType, int _UpLo, typename _Preconditioner>
+ struct traits<MINRES<_MatrixType,_UpLo,_Preconditioner> >
+ {
+ typedef _MatrixType MatrixType;
+ typedef _Preconditioner Preconditioner;
+ };
+
+ }
+
+ /** \ingroup IterativeLinearSolvers_Module
+ * \brief A minimal residual solver for sparse symmetric problems
+ *
+ * This class allows to solve for A.x = b sparse linear problems using the MINRES algorithm
+ * of Paige and Saunders (1975). The sparse matrix A must be symmetric (possibly indefinite).
+ * The vectors x and b can be either dense or sparse.
+ *
+ * \tparam _MatrixType the type of the sparse matrix A, can be a dense or a sparse matrix.
+ * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
+ * or Upper. Default is Lower.
+ * \tparam _Preconditioner the type of the preconditioner. Default is DiagonalPreconditioner
+ *
+ * The maximal number of iterations and tolerance value can be controlled via the setMaxIterations()
+ * and setTolerance() methods. The defaults are the size of the problem for the maximal number of iterations
+ * and NumTraits<Scalar>::epsilon() for the tolerance.
+ *
+ * This class can be used as the direct solver classes. Here is a typical usage example:
+ * \code
+ * int n = 10000;
+ * VectorXd x(n), b(n);
+ * SparseMatrix<double> A(n,n);
+ * // fill A and b
+ * MINRES<SparseMatrix<double> > mr;
+ * mr.compute(A);
+ * x = mr.solve(b);
+ * std::cout << "#iterations: " << mr.iterations() << std::endl;
+ * std::cout << "estimated error: " << mr.error() << std::endl;
+ * // update b, and solve again
+ * x = mr.solve(b);
+ * \endcode
+ *
+ * By default the iterations start with x=0 as an initial guess of the solution.
+ * One can control the start using the solveWithGuess() method. Here is a step by
+ * step execution example starting with a random guess and printing the evolution
+ * of the estimated error:
+ * * \code
+ * x = VectorXd::Random(n);
+ * mr.setMaxIterations(1);
+ * int i = 0;
+ * do {
+ * x = mr.solveWithGuess(b,x);
+ * std::cout << i << " : " << mr.error() << std::endl;
+ * ++i;
+ * } while (mr.info()!=Success && i<100);
+ * \endcode
+ * Note that such a step by step excution is slightly slower.
+ *
+ * \sa class ConjugateGradient, BiCGSTAB, SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner
+ */
+ template< typename _MatrixType, int _UpLo, typename _Preconditioner>
+ class MINRES : public IterativeSolverBase<MINRES<_MatrixType,_UpLo,_Preconditioner> >
+ {
+
+ typedef IterativeSolverBase<MINRES> Base;
+ using Base::mp_matrix;
+ using Base::m_error;
+ using Base::m_iterations;
+ using Base::m_info;
+ using Base::m_isInitialized;
+ public:
+ typedef _MatrixType MatrixType;
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::Index Index;
+ typedef typename MatrixType::RealScalar RealScalar;
+ typedef _Preconditioner Preconditioner;
+
+ enum {UpLo = _UpLo};
+
+ public:
+
+ /** Default constructor. */
+ MINRES() : Base() {}
+
+ /** Initialize the solver with matrix \a A for further \c Ax=b solving.
+ *
+ * This constructor is a shortcut for the default constructor followed
+ * by a call to compute().
+ *
+ * \warning this class stores a reference to the matrix A as well as some
+ * precomputed values that depend on it. Therefore, if \a A is changed
+ * this class becomes invalid. Call compute() to update it with the new
+ * matrix A, or modify a copy of A.
+ */
+ MINRES(const MatrixType& A) : Base(A) {}
+
+ /** Destructor. */
+ ~MINRES(){}
+
+ /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A
+ * \a x0 as an initial solution.
+ *
+ * \sa compute()
+ */
+ template<typename Rhs,typename Guess>
+ inline const internal::solve_retval_with_guess<MINRES, Rhs, Guess>
+ solveWithGuess(const MatrixBase<Rhs>& b, const Guess& x0) const
+ {
+ eigen_assert(m_isInitialized && "MINRES is not initialized.");
+ eigen_assert(Base::rows()==b.rows()
+ && "MINRES::solve(): invalid number of rows of the right hand side matrix b");
+ return internal::solve_retval_with_guess
+ <MINRES, Rhs, Guess>(*this, b.derived(), x0);
+ }
+
+ /** \internal */
+ template<typename Rhs,typename Dest>
+ void _solveWithGuess(const Rhs& b, Dest& x) const
+ {
+ m_iterations = Base::maxIterations();
+ m_error = Base::m_tolerance;
+
+ for(int j=0; j<b.cols(); ++j)
+ {
+ m_iterations = Base::maxIterations();
+ m_error = Base::m_tolerance;
+
+ typename Dest::ColXpr xj(x,j);
+ internal::minres(mp_matrix->template selfadjointView<UpLo>(), b.col(j), xj,
+ Base::m_preconditioner, m_iterations, m_error);
+ }
+
+ m_isInitialized = true;
+ m_info = m_error <= Base::m_tolerance ? Success : NoConvergence;
+ }
+
+ /** \internal */
+ template<typename Rhs,typename Dest>
+ void _solve(const Rhs& b, Dest& x) const
+ {
+ x.setZero();
+ _solveWithGuess(b,x);
+ }
+
+ protected:
+
+ };
+
+ namespace internal {
+
+ template<typename _MatrixType, int _UpLo, typename _Preconditioner, typename Rhs>
+ struct solve_retval<MINRES<_MatrixType,_UpLo,_Preconditioner>, Rhs>
+ : solve_retval_base<MINRES<_MatrixType,_UpLo,_Preconditioner>, Rhs>
+ {
+ typedef MINRES<_MatrixType,_UpLo,_Preconditioner> Dec;
+ EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs)
+
+ template<typename Dest> void evalTo(Dest& dst) const
+ {
+ dec()._solve(rhs(),dst);
+ }
+ };
+
+ } // end namespace internal
+
+} // end namespace Eigen
+
+#endif // EIGEN_MINRES_H
+
diff --git a/unsupported/Eigen/src/IterativeSolvers/Scaling.h b/unsupported/Eigen/src/IterativeSolvers/Scaling.h
index fdef0aca3..4fd439202 100644
--- a/unsupported/Eigen/src/IterativeSolvers/Scaling.h
+++ b/unsupported/Eigen/src/IterativeSolvers/Scaling.h
@@ -7,8 +7,8 @@
// 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_SCALING_H
-#define EIGEN_SCALING_H
+#ifndef EIGEN_ITERSCALING_H
+#define EIGEN_ITERSCALING_H
/**
* \ingroup IterativeSolvers_Module
* \brief iterative scaling algorithm to equilibrate rows and column norms in matrices
@@ -24,7 +24,7 @@
* VectorXd x(n), b(n);
* SparseMatrix<double> A;
* // fill A and b;
- * Scaling<SparseMatrix<double> > scal;
+ * IterScaling<SparseMatrix<double> > scal;
* // Compute the left and right scaling vectors. The matrix is equilibrated at output
* scal.computeRef(A);
* // Scale the right hand side
@@ -41,10 +41,10 @@
*
* \sa \ref IncompleteLUT
*/
+namespace Eigen {
using std::abs;
-using namespace Eigen;
template<typename _MatrixType>
-class Scaling
+class IterScaling
{
public:
typedef _MatrixType MatrixType;
@@ -52,15 +52,15 @@ class Scaling
typedef typename MatrixType::Index Index;
public:
- Scaling() { init(); }
+ IterScaling() { init(); }
- Scaling(const MatrixType& matrix)
+ IterScaling(const MatrixType& matrix)
{
init();
compute(matrix);
}
- ~Scaling() { }
+ ~IterScaling() { }
/**
* Compute the left and right diagonal matrices to scale the input matrix @p mat
@@ -73,7 +73,7 @@ class Scaling
{
int m = mat.rows();
int n = mat.cols();
- assert((m>0 && m == n) && "Please give a non - empty matrix");
+ eigen_assert((m>0 && m == n) && "Please give a non - empty matrix");
m_left.resize(m);
m_right.resize(n);
m_left.setOnes();
@@ -181,5 +181,5 @@ class Scaling
double m_tol;
int m_maxits; // Maximum number of iterations allowed
};
-
-#endif \ No newline at end of file
+}
+#endif
diff --git a/unsupported/Eigen/src/KroneckerProduct/KroneckerTensorProduct.h b/unsupported/Eigen/src/KroneckerProduct/KroneckerTensorProduct.h
index 84fd72fc6..532896c3b 100644
--- a/unsupported/Eigen/src/KroneckerProduct/KroneckerTensorProduct.h
+++ b/unsupported/Eigen/src/KroneckerProduct/KroneckerTensorProduct.h
@@ -3,153 +3,240 @@
//
// Copyright (C) 2011 Kolja Brix <brix@igpm.rwth-aachen.de>
// Copyright (C) 2011 Andreas Platen <andiplaten@gmx.de>
+// Copyright (C) 2012 Chen-Pang He <jdh8@ms63.hinet.net>
//
// 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 KRONECKER_TENSOR_PRODUCT_H
#define KRONECKER_TENSOR_PRODUCT_H
-
namespace Eigen {
-namespace internal {
+template<typename Scalar, int Options, typename Index> class SparseMatrix;
/*!
- * Kronecker tensor product helper function for dense matrices
+ * \brief Kronecker tensor product helper class for dense matrices
*
- * \param A Dense matrix A
- * \param B Dense matrix B
- * \param AB_ Kronecker tensor product of A and B
+ * This class is the return value of kroneckerProduct(MatrixBase,
+ * MatrixBase). Use the function rather than construct this class
+ * directly to avoid specifying template prarameters.
+ *
+ * \tparam Lhs Type of the left-hand side, a matrix expression.
+ * \tparam Rhs Type of the rignt-hand side, a matrix expression.
*/
-template<typename Derived_A, typename Derived_B, typename Derived_AB>
-void kroneckerProduct_full(const Derived_A& A, const Derived_B& B, Derived_AB & AB)
+template<typename Lhs, typename Rhs>
+class KroneckerProduct : public ReturnByValue<KroneckerProduct<Lhs,Rhs> >
{
- const unsigned int Ar = A.rows(),
- Ac = A.cols(),
- Br = B.rows(),
- Bc = B.cols();
- for (unsigned int i=0; i<Ar; ++i)
- for (unsigned int j=0; j<Ac; ++j)
- AB.block(i*Br,j*Bc,Br,Bc) = A(i,j)*B;
-}
+ private:
+ typedef ReturnByValue<KroneckerProduct> Base;
+ typedef typename Base::Scalar Scalar;
+ typedef typename Base::Index Index;
+
+ public:
+ /*! \brief Constructor. */
+ KroneckerProduct(const Lhs& A, const Rhs& B)
+ : m_A(A), m_B(B)
+ {}
+
+ /*! \brief Evaluate the Kronecker tensor product. */
+ template<typename Dest> void evalTo(Dest& dst) const;
+
+ inline Index rows() const { return m_A.rows() * m_B.rows(); }
+ inline Index cols() const { return m_A.cols() * m_B.cols(); }
+
+ Scalar coeff(Index row, Index col) const
+ {
+ return m_A.coeff(row / m_B.rows(), col / m_B.cols()) *
+ m_B.coeff(row % m_B.rows(), col % m_B.cols());
+ }
+
+ Scalar coeff(Index i) const
+ {
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(KroneckerProduct);
+ return m_A.coeff(i / m_A.size()) * m_B.coeff(i % m_A.size());
+ }
+ private:
+ typename Lhs::Nested m_A;
+ typename Rhs::Nested m_B;
+};
/*!
- * Kronecker tensor product helper function for matrices, where at least one is sparse
+ * \brief Kronecker tensor product helper class for sparse matrices
+ *
+ * If at least one of the operands is a sparse matrix expression,
+ * then this class is returned and evaluates into a sparse matrix.
+ *
+ * This class is the return value of kroneckerProduct(EigenBase,
+ * EigenBase). Use the function rather than construct this class
+ * directly to avoid specifying template prarameters.
*
- * \param A Matrix A
- * \param B Matrix B
- * \param AB_ Kronecker tensor product of A and B
+ * \tparam Lhs Type of the left-hand side, a matrix expression.
+ * \tparam Rhs Type of the rignt-hand side, a matrix expression.
*/
-template<typename Derived_A, typename Derived_B, typename Derived_AB>
-void kroneckerProduct_sparse(const Derived_A &A, const Derived_B &B, Derived_AB &AB)
+template<typename Lhs, typename Rhs>
+class KroneckerProductSparse : public EigenBase<KroneckerProductSparse<Lhs,Rhs> >
{
- const unsigned int Ar = A.rows(),
- Ac = A.cols(),
- Br = B.rows(),
- Bc = B.cols();
- AB.resize(Ar*Br,Ac*Bc);
- AB.resizeNonZeros(0);
- AB.reserve(A.nonZeros()*B.nonZeros());
-
- for (int kA=0; kA<A.outerSize(); ++kA)
+ private:
+ typedef typename internal::traits<KroneckerProductSparse>::Index Index;
+
+ public:
+ /*! \brief Constructor. */
+ KroneckerProductSparse(const Lhs& A, const Rhs& B)
+ : m_A(A), m_B(B)
+ {}
+
+ /*! \brief Evaluate the Kronecker tensor product. */
+ template<typename Dest> void evalTo(Dest& dst) const;
+
+ inline Index rows() const { return m_A.rows() * m_B.rows(); }
+ inline Index cols() const { return m_A.cols() * m_B.cols(); }
+
+ template<typename Scalar, int Options, typename Index>
+ operator SparseMatrix<Scalar, Options, Index>()
+ {
+ SparseMatrix<Scalar, Options, Index> result;
+ evalTo(result.derived());
+ return result;
+ }
+
+ private:
+ typename Lhs::Nested m_A;
+ typename Rhs::Nested m_B;
+};
+
+template<typename Lhs, typename Rhs>
+template<typename Dest>
+void KroneckerProduct<Lhs,Rhs>::evalTo(Dest& dst) const
+{
+ const int BlockRows = Rhs::RowsAtCompileTime,
+ BlockCols = Rhs::ColsAtCompileTime;
+ const Index Br = m_B.rows(),
+ Bc = m_B.cols();
+ for (Index i=0; i < m_A.rows(); ++i)
+ for (Index j=0; j < m_A.cols(); ++j)
+ Block<Dest,BlockRows,BlockCols>(dst,i*Br,j*Bc,Br,Bc) = m_A.coeff(i,j) * m_B;
+}
+
+template<typename Lhs, typename Rhs>
+template<typename Dest>
+void KroneckerProductSparse<Lhs,Rhs>::evalTo(Dest& dst) const
+{
+ const Index Br = m_B.rows(),
+ Bc = m_B.cols();
+ dst.resize(rows(),cols());
+ dst.resizeNonZeros(0);
+ dst.reserve(m_A.nonZeros() * m_B.nonZeros());
+
+ for (Index kA=0; kA < m_A.outerSize(); ++kA)
{
- for (int kB=0; kB<B.outerSize(); ++kB)
+ for (Index kB=0; kB < m_B.outerSize(); ++kB)
{
- for (typename Derived_A::InnerIterator itA(A,kA); itA; ++itA)
+ for (typename Lhs::InnerIterator itA(m_A,kA); itA; ++itA)
{
- for (typename Derived_B::InnerIterator itB(B,kB); itB; ++itB)
+ for (typename Rhs::InnerIterator itB(m_B,kB); itB; ++itB)
{
- const unsigned int iA = itA.row(),
- jA = itA.col(),
- iB = itB.row(),
- jB = itB.col(),
- i = iA*Br + iB,
- j = jA*Bc + jB;
- AB.insert(i,j) = itA.value() * itB.value();
+ const Index i = itA.row() * Br + itB.row(),
+ j = itA.col() * Bc + itB.col();
+ dst.insert(i,j) = itA.value() * itB.value();
}
}
}
}
}
-} // end namespace internal
+namespace internal {
+template<typename _Lhs, typename _Rhs>
+struct traits<KroneckerProduct<_Lhs,_Rhs> >
+{
+ typedef typename remove_all<_Lhs>::type Lhs;
+ typedef typename remove_all<_Rhs>::type Rhs;
+ typedef typename scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType Scalar;
+
+ enum {
+ Rows = size_at_compile_time<traits<Lhs>::RowsAtCompileTime, traits<Rhs>::RowsAtCompileTime>::ret,
+ Cols = size_at_compile_time<traits<Lhs>::ColsAtCompileTime, traits<Rhs>::ColsAtCompileTime>::ret,
+ MaxRows = size_at_compile_time<traits<Lhs>::MaxRowsAtCompileTime, traits<Rhs>::MaxRowsAtCompileTime>::ret,
+ MaxCols = size_at_compile_time<traits<Lhs>::MaxColsAtCompileTime, traits<Rhs>::MaxColsAtCompileTime>::ret,
+ CoeffReadCost = Lhs::CoeffReadCost + Rhs::CoeffReadCost + NumTraits<Scalar>::MulCost
+ };
+
+ typedef Matrix<Scalar,Rows,Cols> ReturnType;
+};
+
+template<typename _Lhs, typename _Rhs>
+struct traits<KroneckerProductSparse<_Lhs,_Rhs> >
+{
+ typedef MatrixXpr XprKind;
+ typedef typename remove_all<_Lhs>::type Lhs;
+ typedef typename remove_all<_Rhs>::type Rhs;
+ typedef typename scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType Scalar;
+ typedef typename promote_storage_type<typename traits<Lhs>::StorageKind, typename traits<Rhs>::StorageKind>::ret StorageKind;
+ typedef typename promote_index_type<typename Lhs::Index, typename Rhs::Index>::type Index;
+
+ enum {
+ LhsFlags = Lhs::Flags,
+ RhsFlags = Rhs::Flags,
+
+ RowsAtCompileTime = size_at_compile_time<traits<Lhs>::RowsAtCompileTime, traits<Rhs>::RowsAtCompileTime>::ret,
+ ColsAtCompileTime = size_at_compile_time<traits<Lhs>::ColsAtCompileTime, traits<Rhs>::ColsAtCompileTime>::ret,
+ MaxRowsAtCompileTime = size_at_compile_time<traits<Lhs>::MaxRowsAtCompileTime, traits<Rhs>::MaxRowsAtCompileTime>::ret,
+ MaxColsAtCompileTime = size_at_compile_time<traits<Lhs>::MaxColsAtCompileTime, traits<Rhs>::MaxColsAtCompileTime>::ret,
+
+ EvalToRowMajor = (LhsFlags & RhsFlags & RowMajorBit),
+ RemovedBits = ~(EvalToRowMajor ? 0 : RowMajorBit),
+
+ Flags = ((LhsFlags | RhsFlags) & HereditaryBits & RemovedBits)
+ | EvalBeforeNestingBit | EvalBeforeAssigningBit,
+ CoeffReadCost = Dynamic
+ };
+};
+} // end namespace internal
/*!
- * Computes Kronecker tensor product of two dense matrices
+ * \ingroup KroneckerProduct_Module
*
- * \param a Dense matrix a
- * \param b Dense matrix b
- * \param c Kronecker tensor product of a and b
- */
-template<typename A,typename B,typename CScalar,int CRows,int CCols, int COptions, int CMaxRows, int CMaxCols>
-void kroneckerProduct(const MatrixBase<A>& a, const MatrixBase<B>& b, Matrix<CScalar,CRows,CCols,COptions,CMaxRows,CMaxCols>& c)
-{
- c.resize(a.rows()*b.rows(),a.cols()*b.cols());
- internal::kroneckerProduct_full(a.derived(), b.derived(), c);
-}
-
-/*!
* Computes Kronecker tensor product of two dense matrices
*
- * Remark: this function uses the const cast hack and has been
- * implemented to make the function call possible, where the
- * output matrix is a submatrix, e.g.
- * kroneckerProduct(A,B,AB.block(2,5,6,6));
+ * \warning If you want to replace a matrix by its Kronecker product
+ * with some matrix, do \b NOT do this:
+ * \code
+ * A = kroneckerProduct(A,B); // bug!!! caused by aliasing effect
+ * \endcode
+ * instead, use eval() to work around this:
+ * \code
+ * A = kroneckerProduct(A,B).eval();
+ * \endcode
*
* \param a Dense matrix a
* \param b Dense matrix b
- * \param c Kronecker tensor product of a and b
+ * \return Kronecker tensor product of a and b
*/
-template<typename A,typename B,typename C>
-void kroneckerProduct(const MatrixBase<A>& a, const MatrixBase<B>& b, MatrixBase<C> const & c_)
+template<typename A, typename B>
+KroneckerProduct<A,B> kroneckerProduct(const MatrixBase<A>& a, const MatrixBase<B>& b)
{
- MatrixBase<C>& c = const_cast<MatrixBase<C>& >(c_);
- internal::kroneckerProduct_full(a.derived(), b.derived(), c.derived());
+ return KroneckerProduct<A, B>(a.derived(), b.derived());
}
/*!
- * Computes Kronecker tensor product of a dense and a sparse matrix
+ * \ingroup KroneckerProduct_Module
*
- * \param a Dense matrix a
- * \param b Sparse matrix b
- * \param c Kronecker tensor product of a and b
- */
-template<typename A,typename B,typename C>
-void kroneckerProduct(const MatrixBase<A>& a, const SparseMatrixBase<B>& b, SparseMatrixBase<C>& c)
-{
- internal::kroneckerProduct_sparse(a.derived(), b.derived(), c.derived());
-}
-
-/*!
- * Computes Kronecker tensor product of a sparse and a dense matrix
- *
- * \param a Sparse matrix a
- * \param b Dense matrix b
- * \param c Kronecker tensor product of a and b
- */
-template<typename A,typename B,typename C>
-void kroneckerProduct(const SparseMatrixBase<A>& a, const MatrixBase<B>& b, SparseMatrixBase<C>& c)
-{
- internal::kroneckerProduct_sparse(a.derived(), b.derived(), c.derived());
-}
-
-/*!
- * Computes Kronecker tensor product of two sparse matrices
+ * Computes Kronecker tensor product of two matrices, at least one of
+ * which is sparse
*
- * \param a Sparse matrix a
- * \param b Sparse matrix b
- * \param c Kronecker tensor product of a and b
+ * \param a Dense/sparse matrix a
+ * \param b Dense/sparse matrix b
+ * \return Kronecker tensor product of a and b, stored in a sparse
+ * matrix
*/
-template<typename A,typename B,typename C>
-void kroneckerProduct(const SparseMatrixBase<A>& a, const SparseMatrixBase<B>& b, SparseMatrixBase<C>& c)
+template<typename A, typename B>
+KroneckerProductSparse<A,B> kroneckerProduct(const EigenBase<A>& a, const EigenBase<B>& b)
{
- internal::kroneckerProduct_sparse(a.derived(), b.derived(), c.derived());
+ return KroneckerProductSparse<A,B>(a.derived(), b.derived());
}
} // end namespace Eigen
diff --git a/unsupported/Eigen/src/LevenbergMarquardt/CMakeLists.txt b/unsupported/Eigen/src/LevenbergMarquardt/CMakeLists.txt
new file mode 100644
index 000000000..8513803ce
--- /dev/null
+++ b/unsupported/Eigen/src/LevenbergMarquardt/CMakeLists.txt
@@ -0,0 +1,6 @@
+FILE(GLOB Eigen_LevenbergMarquardt_SRCS "*.h")
+
+INSTALL(FILES
+ ${Eigen_LevenbergMarquardt_SRCS}
+ DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/LevenbergMarquardt COMPONENT Devel
+ )
diff --git a/unsupported/Eigen/src/LevenbergMarquardt/CopyrightMINPACK.txt b/unsupported/Eigen/src/LevenbergMarquardt/CopyrightMINPACK.txt
new file mode 100644
index 000000000..ae7984dae
--- /dev/null
+++ b/unsupported/Eigen/src/LevenbergMarquardt/CopyrightMINPACK.txt
@@ -0,0 +1,52 @@
+Minpack Copyright Notice (1999) University of Chicago. All rights reserved
+
+Redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the
+following conditions are met:
+
+1. Redistributions of source code must retain the above
+copyright notice, this list of conditions and the following
+disclaimer.
+
+2. Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials
+provided with the distribution.
+
+3. The end-user documentation included with the
+redistribution, if any, must include the following
+acknowledgment:
+
+ "This product includes software developed by the
+ University of Chicago, as Operator of Argonne National
+ Laboratory.
+
+Alternately, this acknowledgment may appear in the software
+itself, if and wherever such third-party acknowledgments
+normally appear.
+
+4. WARRANTY DISCLAIMER. THE SOFTWARE IS SUPPLIED "AS IS"
+WITHOUT WARRANTY OF ANY KIND. THE COPYRIGHT HOLDER, THE
+UNITED STATES, THE UNITED STATES DEPARTMENT OF ENERGY, AND
+THEIR EMPLOYEES: (1) DISCLAIM ANY WARRANTIES, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE
+OR NON-INFRINGEMENT, (2) DO NOT ASSUME ANY LEGAL LIABILITY
+OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR
+USEFULNESS OF THE SOFTWARE, (3) DO NOT REPRESENT THAT USE OF
+THE SOFTWARE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS, (4)
+DO NOT WARRANT THAT THE SOFTWARE WILL FUNCTION
+UNINTERRUPTED, THAT IT IS ERROR-FREE OR THAT ANY ERRORS WILL
+BE CORRECTED.
+
+5. LIMITATION OF LIABILITY. IN NO EVENT WILL THE COPYRIGHT
+HOLDER, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF
+ENERGY, OR THEIR EMPLOYEES: BE LIABLE FOR ANY INDIRECT,
+INCIDENTAL, CONSEQUENTIAL, SPECIAL OR PUNITIVE DAMAGES OF
+ANY KIND OR NATURE, INCLUDING BUT NOT LIMITED TO LOSS OF
+PROFITS OR LOSS OF DATA, FOR ANY REASON WHATSOEVER, WHETHER
+SUCH LIABILITY IS ASSERTED ON THE BASIS OF CONTRACT, TORT
+(INCLUDING NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE,
+EVEN IF ANY OF SAID PARTIES HAS BEEN WARNED OF THE
+POSSIBILITY OF SUCH LOSS OR DAMAGES.
+
diff --git a/unsupported/Eigen/src/LevenbergMarquardt/LMcovar.h b/unsupported/Eigen/src/LevenbergMarquardt/LMcovar.h
new file mode 100644
index 000000000..32d3ad518
--- /dev/null
+++ b/unsupported/Eigen/src/LevenbergMarquardt/LMcovar.h
@@ -0,0 +1,85 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// This code initially comes from MINPACK whose original authors are:
+// Copyright Jorge More - Argonne National Laboratory
+// Copyright Burt Garbow - Argonne National Laboratory
+// Copyright Ken Hillstrom - Argonne National Laboratory
+//
+// This Source Code Form is subject to the terms of the Minpack license
+// (a BSD-like license) described in the campaigned CopyrightMINPACK.txt file.
+
+#ifndef EIGEN_LMCOVAR_H
+#define EIGEN_LMCOVAR_H
+
+namespace Eigen {
+
+namespace internal {
+
+template <typename Scalar>
+void covar(
+ Matrix< Scalar, Dynamic, Dynamic > &r,
+ const VectorXi& ipvt,
+ Scalar tol = std::sqrt(NumTraits<Scalar>::epsilon()) )
+{
+ using std::abs;
+ typedef DenseIndex Index;
+ /* Local variables */
+ Index i, j, k, l, ii, jj;
+ bool sing;
+ Scalar temp;
+
+ /* Function Body */
+ const Index n = r.cols();
+ const Scalar tolr = tol * abs(r(0,0));
+ Matrix< Scalar, Dynamic, 1 > wa(n);
+ eigen_assert(ipvt.size()==n);
+
+ /* form the inverse of r in the full upper triangle of r. */
+ l = -1;
+ for (k = 0; k < n; ++k)
+ if (abs(r(k,k)) > tolr) {
+ r(k,k) = 1. / r(k,k);
+ for (j = 0; j <= k-1; ++j) {
+ temp = r(k,k) * r(j,k);
+ r(j,k) = 0.;
+ r.col(k).head(j+1) -= r.col(j).head(j+1) * temp;
+ }
+ l = k;
+ }
+
+ /* form the full upper triangle of the inverse of (r transpose)*r */
+ /* in the full upper triangle of r. */
+ for (k = 0; k <= l; ++k) {
+ for (j = 0; j <= k-1; ++j)
+ r.col(j).head(j+1) += r.col(k).head(j+1) * r(j,k);
+ r.col(k).head(k+1) *= r(k,k);
+ }
+
+ /* form the full lower triangle of the covariance matrix */
+ /* in the strict lower triangle of r and in wa. */
+ for (j = 0; j < n; ++j) {
+ jj = ipvt[j];
+ sing = j > l;
+ for (i = 0; i <= j; ++i) {
+ if (sing)
+ r(i,j) = 0.;
+ ii = ipvt[i];
+ if (ii > jj)
+ r(ii,jj) = r(i,j);
+ if (ii < jj)
+ r(jj,ii) = r(i,j);
+ }
+ wa[jj] = r(j,j);
+ }
+
+ /* symmetrize the covariance matrix in r. */
+ r.topLeftCorner(n,n).template triangularView<StrictlyUpper>() = r.topLeftCorner(n,n).transpose();
+ r.diagonal() = wa;
+}
+
+} // end namespace internal
+
+} // end namespace Eigen
+
+#endif // EIGEN_LMCOVAR_H
diff --git a/unsupported/Eigen/src/LevenbergMarquardt/LMonestep.h b/unsupported/Eigen/src/LevenbergMarquardt/LMonestep.h
new file mode 100644
index 000000000..25b32ec5b
--- /dev/null
+++ b/unsupported/Eigen/src/LevenbergMarquardt/LMonestep.h
@@ -0,0 +1,202 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org>
+//
+// This code initially comes from MINPACK whose original authors are:
+// Copyright Jorge More - Argonne National Laboratory
+// Copyright Burt Garbow - Argonne National Laboratory
+// Copyright Ken Hillstrom - Argonne National Laboratory
+//
+// This Source Code Form is subject to the terms of the Minpack license
+// (a BSD-like license) described in the campaigned CopyrightMINPACK.txt file.
+
+#ifndef EIGEN_LMONESTEP_H
+#define EIGEN_LMONESTEP_H
+
+namespace Eigen {
+
+template<typename FunctorType>
+LevenbergMarquardtSpace::Status
+LevenbergMarquardt<FunctorType>::minimizeOneStep(FVectorType &x)
+{
+ using std::abs;
+ using std::sqrt;
+ RealScalar temp, temp1,temp2;
+ RealScalar ratio;
+ RealScalar pnorm, xnorm, fnorm1, actred, dirder, prered;
+ eigen_assert(x.size()==n); // check the caller is not cheating us
+
+ temp = 0.0; xnorm = 0.0;
+ /* calculate the jacobian matrix. */
+ Index df_ret = m_functor.df(x, m_fjac);
+ if (df_ret<0)
+ return LevenbergMarquardtSpace::UserAsked;
+ if (df_ret>0)
+ // numerical diff, we evaluated the function df_ret times
+ m_nfev += df_ret;
+ else m_njev++;
+
+ /* compute the qr factorization of the jacobian. */
+ for (int j = 0; j < x.size(); ++j)
+ m_wa2(j) = m_fjac.col(j).blueNorm();
+ QRSolver qrfac(m_fjac);
+ if(qrfac.info() != Success) {
+ m_info = NumericalIssue;
+ return LevenbergMarquardtSpace::ImproperInputParameters;
+ }
+ // Make a copy of the first factor with the associated permutation
+ m_rfactor = qrfac.matrixR();
+ m_permutation = (qrfac.colsPermutation());
+
+ /* on the first iteration and if external scaling is not used, scale according */
+ /* to the norms of the columns of the initial jacobian. */
+ if (m_iter == 1) {
+ if (!m_useExternalScaling)
+ for (Index j = 0; j < n; ++j)
+ m_diag[j] = (m_wa2[j]==0.)? 1. : m_wa2[j];
+
+ /* on the first iteration, calculate the norm of the scaled x */
+ /* and initialize the step bound m_delta. */
+ xnorm = m_diag.cwiseProduct(x).stableNorm();
+ m_delta = m_factor * xnorm;
+ if (m_delta == 0.)
+ m_delta = m_factor;
+ }
+
+ /* form (q transpose)*m_fvec and store the first n components in */
+ /* m_qtf. */
+ m_wa4 = m_fvec;
+ m_wa4 = qrfac.matrixQ().adjoint() * m_fvec;
+ m_qtf = m_wa4.head(n);
+
+ /* compute the norm of the scaled gradient. */
+ m_gnorm = 0.;
+ if (m_fnorm != 0.)
+ for (Index j = 0; j < n; ++j)
+ if (m_wa2[m_permutation.indices()[j]] != 0.)
+ m_gnorm = (std::max)(m_gnorm, abs( m_rfactor.col(j).head(j+1).dot(m_qtf.head(j+1)/m_fnorm) / m_wa2[m_permutation.indices()[j]]));
+
+ /* test for convergence of the gradient norm. */
+ if (m_gnorm <= m_gtol) {
+ m_info = Success;
+ return LevenbergMarquardtSpace::CosinusTooSmall;
+ }
+
+ /* rescale if necessary. */
+ if (!m_useExternalScaling)
+ m_diag = m_diag.cwiseMax(m_wa2);
+
+ do {
+ /* determine the levenberg-marquardt parameter. */
+ internal::lmpar2(qrfac, m_diag, m_qtf, m_delta, m_par, m_wa1);
+
+ /* store the direction p and x + p. calculate the norm of p. */
+ m_wa1 = -m_wa1;
+ m_wa2 = x + m_wa1;
+ pnorm = m_diag.cwiseProduct(m_wa1).stableNorm();
+
+ /* on the first iteration, adjust the initial step bound. */
+ if (m_iter == 1)
+ m_delta = (std::min)(m_delta,pnorm);
+
+ /* evaluate the function at x + p and calculate its norm. */
+ if ( m_functor(m_wa2, m_wa4) < 0)
+ return LevenbergMarquardtSpace::UserAsked;
+ ++m_nfev;
+ fnorm1 = m_wa4.stableNorm();
+
+ /* compute the scaled actual reduction. */
+ actred = -1.;
+ if (Scalar(.1) * fnorm1 < m_fnorm)
+ actred = 1. - numext::abs2(fnorm1 / m_fnorm);
+
+ /* compute the scaled predicted reduction and */
+ /* the scaled directional derivative. */
+ m_wa3 = m_rfactor.template triangularView<Upper>() * (m_permutation.inverse() *m_wa1);
+ temp1 = numext::abs2(m_wa3.stableNorm() / m_fnorm);
+ temp2 = numext::abs2(sqrt(m_par) * pnorm / m_fnorm);
+ prered = temp1 + temp2 / Scalar(.5);
+ dirder = -(temp1 + temp2);
+
+ /* compute the ratio of the actual to the predicted */
+ /* reduction. */
+ ratio = 0.;
+ if (prered != 0.)
+ ratio = actred / prered;
+
+ /* update the step bound. */
+ if (ratio <= Scalar(.25)) {
+ if (actred >= 0.)
+ temp = RealScalar(.5);
+ if (actred < 0.)
+ temp = RealScalar(.5) * dirder / (dirder + RealScalar(.5) * actred);
+ if (RealScalar(.1) * fnorm1 >= m_fnorm || temp < RealScalar(.1))
+ temp = Scalar(.1);
+ /* Computing MIN */
+ m_delta = temp * (std::min)(m_delta, pnorm / RealScalar(.1));
+ m_par /= temp;
+ } else if (!(m_par != 0. && ratio < RealScalar(.75))) {
+ m_delta = pnorm / RealScalar(.5);
+ m_par = RealScalar(.5) * m_par;
+ }
+
+ /* test for successful iteration. */
+ if (ratio >= RealScalar(1e-4)) {
+ /* successful iteration. update x, m_fvec, and their norms. */
+ x = m_wa2;
+ m_wa2 = m_diag.cwiseProduct(x);
+ m_fvec = m_wa4;
+ xnorm = m_wa2.stableNorm();
+ m_fnorm = fnorm1;
+ ++m_iter;
+ }
+
+ /* tests for convergence. */
+ if (abs(actred) <= m_ftol && prered <= m_ftol && Scalar(.5) * ratio <= 1. && m_delta <= m_xtol * xnorm)
+ {
+ m_info = Success;
+ return LevenbergMarquardtSpace::RelativeErrorAndReductionTooSmall;
+ }
+ if (abs(actred) <= m_ftol && prered <= m_ftol && Scalar(.5) * ratio <= 1.)
+ {
+ m_info = Success;
+ return LevenbergMarquardtSpace::RelativeReductionTooSmall;
+ }
+ if (m_delta <= m_xtol * xnorm)
+ {
+ m_info = Success;
+ return LevenbergMarquardtSpace::RelativeErrorTooSmall;
+ }
+
+ /* tests for termination and stringent tolerances. */
+ if (m_nfev >= m_maxfev)
+ {
+ m_info = NoConvergence;
+ return LevenbergMarquardtSpace::TooManyFunctionEvaluation;
+ }
+ if (abs(actred) <= NumTraits<Scalar>::epsilon() && prered <= NumTraits<Scalar>::epsilon() && Scalar(.5) * ratio <= 1.)
+ {
+ m_info = Success;
+ return LevenbergMarquardtSpace::FtolTooSmall;
+ }
+ if (m_delta <= NumTraits<Scalar>::epsilon() * xnorm)
+ {
+ m_info = Success;
+ return LevenbergMarquardtSpace::XtolTooSmall;
+ }
+ if (m_gnorm <= NumTraits<Scalar>::epsilon())
+ {
+ m_info = Success;
+ return LevenbergMarquardtSpace::GtolTooSmall;
+ }
+
+ } while (ratio < Scalar(1e-4));
+
+ return LevenbergMarquardtSpace::Running;
+}
+
+
+} // end namespace Eigen
+
+#endif // EIGEN_LMONESTEP_H
diff --git a/unsupported/Eigen/src/LevenbergMarquardt/LMpar.h b/unsupported/Eigen/src/LevenbergMarquardt/LMpar.h
new file mode 100644
index 000000000..9532042d9
--- /dev/null
+++ b/unsupported/Eigen/src/LevenbergMarquardt/LMpar.h
@@ -0,0 +1,160 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// This code initially comes from MINPACK whose original authors are:
+// Copyright Jorge More - Argonne National Laboratory
+// Copyright Burt Garbow - Argonne National Laboratory
+// Copyright Ken Hillstrom - Argonne National Laboratory
+//
+// This Source Code Form is subject to the terms of the Minpack license
+// (a BSD-like license) described in the campaigned CopyrightMINPACK.txt file.
+
+#ifndef EIGEN_LMPAR_H
+#define EIGEN_LMPAR_H
+
+namespace Eigen {
+
+namespace internal {
+
+ template <typename QRSolver, typename VectorType>
+ void lmpar2(
+ const QRSolver &qr,
+ const VectorType &diag,
+ const VectorType &qtb,
+ typename VectorType::Scalar m_delta,
+ typename VectorType::Scalar &par,
+ VectorType &x)
+
+ {
+ using std::sqrt;
+ using std::abs;
+ typedef typename QRSolver::MatrixType MatrixType;
+ typedef typename QRSolver::Scalar Scalar;
+ typedef typename QRSolver::Index Index;
+
+ /* Local variables */
+ Index j;
+ Scalar fp;
+ Scalar parc, parl;
+ Index iter;
+ Scalar temp, paru;
+ Scalar gnorm;
+ Scalar dxnorm;
+
+ // Make a copy of the triangular factor.
+ // This copy is modified during call the qrsolv
+ MatrixType s;
+ s = qr.matrixR();
+
+ /* Function Body */
+ const Scalar dwarf = (std::numeric_limits<Scalar>::min)();
+ const Index n = qr.matrixR().cols();
+ eigen_assert(n==diag.size());
+ eigen_assert(n==qtb.size());
+
+ VectorType wa1, wa2;
+
+ /* compute and store in x the gauss-newton direction. if the */
+ /* jacobian is rank-deficient, obtain a least squares solution. */
+
+ // const Index rank = qr.nonzeroPivots(); // exactly double(0.)
+ const Index rank = qr.rank(); // use a threshold
+ wa1 = qtb;
+ wa1.tail(n-rank).setZero();
+ //FIXME There is no solve in place for sparse triangularView
+ wa1.head(rank) = s.topLeftCorner(rank,rank).template triangularView<Upper>().solve(qtb.head(rank));
+
+ x = qr.colsPermutation()*wa1;
+
+ /* initialize the iteration counter. */
+ /* evaluate the function at the origin, and test */
+ /* for acceptance of the gauss-newton direction. */
+ iter = 0;
+ wa2 = diag.cwiseProduct(x);
+ dxnorm = wa2.blueNorm();
+ fp = dxnorm - m_delta;
+ if (fp <= Scalar(0.1) * m_delta) {
+ par = 0;
+ return;
+ }
+
+ /* if the jacobian is not rank deficient, the newton */
+ /* step provides a lower bound, parl, for the zero of */
+ /* the function. otherwise set this bound to zero. */
+ parl = 0.;
+ if (rank==n) {
+ wa1 = qr.colsPermutation().inverse() * diag.cwiseProduct(wa2)/dxnorm;
+ s.topLeftCorner(n,n).transpose().template triangularView<Lower>().solveInPlace(wa1);
+ temp = wa1.blueNorm();
+ parl = fp / m_delta / temp / temp;
+ }
+
+ /* calculate an upper bound, paru, for the zero of the function. */
+ for (j = 0; j < n; ++j)
+ wa1[j] = s.col(j).head(j+1).dot(qtb.head(j+1)) / diag[qr.colsPermutation().indices()(j)];
+
+ gnorm = wa1.stableNorm();
+ paru = gnorm / m_delta;
+ if (paru == 0.)
+ paru = dwarf / (std::min)(m_delta,Scalar(0.1));
+
+ /* if the input par lies outside of the interval (parl,paru), */
+ /* set par to the closer endpoint. */
+ par = (std::max)(par,parl);
+ par = (std::min)(par,paru);
+ if (par == 0.)
+ par = gnorm / dxnorm;
+
+ /* beginning of an iteration. */
+ while (true) {
+ ++iter;
+
+ /* evaluate the function at the current value of par. */
+ if (par == 0.)
+ par = (std::max)(dwarf,Scalar(.001) * paru); /* Computing MAX */
+ wa1 = sqrt(par)* diag;
+
+ VectorType sdiag(n);
+ lmqrsolv(s, qr.colsPermutation(), wa1, qtb, x, sdiag);
+
+ wa2 = diag.cwiseProduct(x);
+ dxnorm = wa2.blueNorm();
+ temp = fp;
+ fp = dxnorm - m_delta;
+
+ /* if the function is small enough, accept the current value */
+ /* of par. also test for the exceptional cases where parl */
+ /* is zero or the number of iterations has reached 10. */
+ if (abs(fp) <= Scalar(0.1) * m_delta || (parl == 0. && fp <= temp && temp < 0.) || iter == 10)
+ break;
+
+ /* compute the newton correction. */
+ wa1 = qr.colsPermutation().inverse() * diag.cwiseProduct(wa2/dxnorm);
+ // we could almost use this here, but the diagonal is outside qr, in sdiag[]
+ for (j = 0; j < n; ++j) {
+ wa1[j] /= sdiag[j];
+ temp = wa1[j];
+ for (Index i = j+1; i < n; ++i)
+ wa1[i] -= s.coeff(i,j) * temp;
+ }
+ temp = wa1.blueNorm();
+ parc = fp / m_delta / temp / temp;
+
+ /* depending on the sign of the function, update parl or paru. */
+ if (fp > 0.)
+ parl = (std::max)(parl,par);
+ if (fp < 0.)
+ paru = (std::min)(paru,par);
+
+ /* compute an improved estimate for par. */
+ par = (std::max)(parl,par+parc);
+ }
+ if (iter == 0)
+ par = 0.;
+ return;
+ }
+} // end namespace internal
+
+} // end namespace Eigen
+
+#endif // EIGEN_LMPAR_H
diff --git a/unsupported/Eigen/src/LevenbergMarquardt/LMqrsolv.h b/unsupported/Eigen/src/LevenbergMarquardt/LMqrsolv.h
new file mode 100644
index 000000000..f5290dee4
--- /dev/null
+++ b/unsupported/Eigen/src/LevenbergMarquardt/LMqrsolv.h
@@ -0,0 +1,189 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org>
+// Copyright (C) 2012 Desire Nuentsa <desire.nuentsa_wakam@inria.fr>
+//
+// This code initially comes from MINPACK whose original authors are:
+// Copyright Jorge More - Argonne National Laboratory
+// Copyright Burt Garbow - Argonne National Laboratory
+// Copyright Ken Hillstrom - Argonne National Laboratory
+//
+// This Source Code Form is subject to the terms of the Minpack license
+// (a BSD-like license) described in the campaigned CopyrightMINPACK.txt file.
+
+#ifndef EIGEN_LMQRSOLV_H
+#define EIGEN_LMQRSOLV_H
+
+namespace Eigen {
+
+namespace internal {
+
+template <typename Scalar,int Rows, int Cols, typename Index>
+void lmqrsolv(
+ Matrix<Scalar,Rows,Cols> &s,
+ const PermutationMatrix<Dynamic,Dynamic,Index> &iPerm,
+ const Matrix<Scalar,Dynamic,1> &diag,
+ const Matrix<Scalar,Dynamic,1> &qtb,
+ Matrix<Scalar,Dynamic,1> &x,
+ Matrix<Scalar,Dynamic,1> &sdiag)
+{
+
+ /* Local variables */
+ Index i, j, k, l;
+ Scalar temp;
+ Index n = s.cols();
+ Matrix<Scalar,Dynamic,1> wa(n);
+ JacobiRotation<Scalar> givens;
+
+ /* Function Body */
+ // the following will only change the lower triangular part of s, including
+ // the diagonal, though the diagonal is restored afterward
+
+ /* copy r and (q transpose)*b to preserve input and initialize s. */
+ /* in particular, save the diagonal elements of r in x. */
+ x = s.diagonal();
+ wa = qtb;
+
+
+ s.topLeftCorner(n,n).template triangularView<StrictlyLower>() = s.topLeftCorner(n,n).transpose();
+ /* eliminate the diagonal matrix d using a givens rotation. */
+ for (j = 0; j < n; ++j) {
+
+ /* prepare the row of d to be eliminated, locating the */
+ /* diagonal element using p from the qr factorization. */
+ l = iPerm.indices()(j);
+ if (diag[l] == 0.)
+ break;
+ sdiag.tail(n-j).setZero();
+ sdiag[j] = diag[l];
+
+ /* the transformations to eliminate the row of d */
+ /* modify only a single element of (q transpose)*b */
+ /* beyond the first n, which is initially zero. */
+ Scalar qtbpj = 0.;
+ for (k = j; k < n; ++k) {
+ /* determine a givens rotation which eliminates the */
+ /* appropriate element in the current row of d. */
+ givens.makeGivens(-s(k,k), sdiag[k]);
+
+ /* compute the modified diagonal element of r and */
+ /* the modified element of ((q transpose)*b,0). */
+ s(k,k) = givens.c() * s(k,k) + givens.s() * sdiag[k];
+ temp = givens.c() * wa[k] + givens.s() * qtbpj;
+ qtbpj = -givens.s() * wa[k] + givens.c() * qtbpj;
+ wa[k] = temp;
+
+ /* accumulate the tranformation in the row of s. */
+ for (i = k+1; i<n; ++i) {
+ temp = givens.c() * s(i,k) + givens.s() * sdiag[i];
+ sdiag[i] = -givens.s() * s(i,k) + givens.c() * sdiag[i];
+ s(i,k) = temp;
+ }
+ }
+ }
+
+ /* solve the triangular system for z. if the system is */
+ /* singular, then obtain a least squares solution. */
+ Index nsing;
+ for(nsing=0; nsing<n && sdiag[nsing]!=0; nsing++) {}
+
+ wa.tail(n-nsing).setZero();
+ s.topLeftCorner(nsing, nsing).transpose().template triangularView<Upper>().solveInPlace(wa.head(nsing));
+
+ // restore
+ sdiag = s.diagonal();
+ s.diagonal() = x;
+
+ /* permute the components of z back to components of x. */
+ x = iPerm * wa;
+}
+
+template <typename Scalar, int _Options, typename Index>
+void lmqrsolv(
+ SparseMatrix<Scalar,_Options,Index> &s,
+ const PermutationMatrix<Dynamic,Dynamic> &iPerm,
+ const Matrix<Scalar,Dynamic,1> &diag,
+ const Matrix<Scalar,Dynamic,1> &qtb,
+ Matrix<Scalar,Dynamic,1> &x,
+ Matrix<Scalar,Dynamic,1> &sdiag)
+{
+ /* Local variables */
+ typedef SparseMatrix<Scalar,RowMajor,Index> FactorType;
+ Index i, j, k, l;
+ Scalar temp;
+ Index n = s.cols();
+ Matrix<Scalar,Dynamic,1> wa(n);
+ JacobiRotation<Scalar> givens;
+
+ /* Function Body */
+ // the following will only change the lower triangular part of s, including
+ // the diagonal, though the diagonal is restored afterward
+
+ /* copy r and (q transpose)*b to preserve input and initialize R. */
+ wa = qtb;
+ FactorType R(s);
+ // Eliminate the diagonal matrix d using a givens rotation
+ for (j = 0; j < n; ++j)
+ {
+ // Prepare the row of d to be eliminated, locating the
+ // diagonal element using p from the qr factorization
+ l = iPerm.indices()(j);
+ if (diag(l) == Scalar(0))
+ break;
+ sdiag.tail(n-j).setZero();
+ sdiag[j] = diag[l];
+ // the transformations to eliminate the row of d
+ // modify only a single element of (q transpose)*b
+ // beyond the first n, which is initially zero.
+
+ Scalar qtbpj = 0;
+ // Browse the nonzero elements of row j of the upper triangular s
+ for (k = j; k < n; ++k)
+ {
+ typename FactorType::InnerIterator itk(R,k);
+ for (; itk; ++itk){
+ if (itk.index() < k) continue;
+ else break;
+ }
+ //At this point, we have the diagonal element R(k,k)
+ // Determine a givens rotation which eliminates
+ // the appropriate element in the current row of d
+ givens.makeGivens(-itk.value(), sdiag(k));
+
+ // Compute the modified diagonal element of r and
+ // the modified element of ((q transpose)*b,0).
+ itk.valueRef() = givens.c() * itk.value() + givens.s() * sdiag(k);
+ temp = givens.c() * wa(k) + givens.s() * qtbpj;
+ qtbpj = -givens.s() * wa(k) + givens.c() * qtbpj;
+ wa(k) = temp;
+
+ // Accumulate the transformation in the remaining k row/column of R
+ for (++itk; itk; ++itk)
+ {
+ i = itk.index();
+ temp = givens.c() * itk.value() + givens.s() * sdiag(i);
+ sdiag(i) = -givens.s() * itk.value() + givens.c() * sdiag(i);
+ itk.valueRef() = temp;
+ }
+ }
+ }
+
+ // Solve the triangular system for z. If the system is
+ // singular, then obtain a least squares solution
+ Index nsing;
+ for(nsing = 0; nsing<n && sdiag(nsing) !=0; nsing++) {}
+
+ wa.tail(n-nsing).setZero();
+// x = wa;
+ wa.head(nsing) = R.topLeftCorner(nsing,nsing).template triangularView<Upper>().solve/*InPlace*/(wa.head(nsing));
+
+ sdiag = R.diagonal();
+ // Permute the components of z back to components of x
+ x = iPerm * wa;
+}
+} // end namespace internal
+
+} // end namespace Eigen
+
+#endif // EIGEN_LMQRSOLV_H
diff --git a/unsupported/Eigen/src/LevenbergMarquardt/LevenbergMarquardt.h b/unsupported/Eigen/src/LevenbergMarquardt/LevenbergMarquardt.h
new file mode 100644
index 000000000..51dd1d3c4
--- /dev/null
+++ b/unsupported/Eigen/src/LevenbergMarquardt/LevenbergMarquardt.h
@@ -0,0 +1,377 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org>
+// Copyright (C) 2012 Desire Nuentsa <desire.nuentsa_wakam@inria.fr>
+//
+// The algorithm of this class initially comes from MINPACK whose original authors are:
+// Copyright Jorge More - Argonne National Laboratory
+// Copyright Burt Garbow - Argonne National Laboratory
+// Copyright Ken Hillstrom - Argonne National Laboratory
+//
+// This Source Code Form is subject to the terms of the Minpack license
+// (a BSD-like license) described in the campaigned CopyrightMINPACK.txt file.
+//
+// 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_LEVENBERGMARQUARDT_H
+#define EIGEN_LEVENBERGMARQUARDT_H
+
+
+namespace Eigen {
+namespace LevenbergMarquardtSpace {
+ enum Status {
+ NotStarted = -2,
+ Running = -1,
+ ImproperInputParameters = 0,
+ RelativeReductionTooSmall = 1,
+ RelativeErrorTooSmall = 2,
+ RelativeErrorAndReductionTooSmall = 3,
+ CosinusTooSmall = 4,
+ TooManyFunctionEvaluation = 5,
+ FtolTooSmall = 6,
+ XtolTooSmall = 7,
+ GtolTooSmall = 8,
+ UserAsked = 9
+ };
+}
+
+template <typename _Scalar, int NX=Dynamic, int NY=Dynamic>
+struct DenseFunctor
+{
+ typedef _Scalar Scalar;
+ enum {
+ InputsAtCompileTime = NX,
+ ValuesAtCompileTime = NY
+ };
+ typedef Matrix<Scalar,InputsAtCompileTime,1> InputType;
+ typedef Matrix<Scalar,ValuesAtCompileTime,1> ValueType;
+ typedef Matrix<Scalar,ValuesAtCompileTime,InputsAtCompileTime> JacobianType;
+ typedef ColPivHouseholderQR<JacobianType> QRSolver;
+ const int m_inputs, m_values;
+
+ DenseFunctor() : m_inputs(InputsAtCompileTime), m_values(ValuesAtCompileTime) {}
+ DenseFunctor(int inputs, int values) : m_inputs(inputs), m_values(values) {}
+
+ int inputs() const { return m_inputs; }
+ int values() const { return m_values; }
+
+ //int operator()(const InputType &x, ValueType& fvec) { }
+ // should be defined in derived classes
+
+ //int df(const InputType &x, JacobianType& fjac) { }
+ // should be defined in derived classes
+};
+
+template <typename _Scalar, typename _Index>
+struct SparseFunctor
+{
+ typedef _Scalar Scalar;
+ typedef _Index Index;
+ typedef Matrix<Scalar,Dynamic,1> InputType;
+ typedef Matrix<Scalar,Dynamic,1> ValueType;
+ typedef SparseMatrix<Scalar, ColMajor, Index> JacobianType;
+ typedef SparseQR<JacobianType, COLAMDOrdering<int> > QRSolver;
+ enum {
+ InputsAtCompileTime = Dynamic,
+ ValuesAtCompileTime = Dynamic
+ };
+
+ SparseFunctor(int inputs, int values) : m_inputs(inputs), m_values(values) {}
+
+ int inputs() const { return m_inputs; }
+ int values() const { return m_values; }
+
+ const int m_inputs, m_values;
+ //int operator()(const InputType &x, ValueType& fvec) { }
+ // to be defined in the functor
+
+ //int df(const InputType &x, JacobianType& fjac) { }
+ // to be defined in the functor if no automatic differentiation
+
+};
+namespace internal {
+template <typename QRSolver, typename VectorType>
+void lmpar2(const QRSolver &qr, const VectorType &diag, const VectorType &qtb,
+ typename VectorType::Scalar m_delta, typename VectorType::Scalar &par,
+ VectorType &x);
+ }
+/**
+ * \ingroup NonLinearOptimization_Module
+ * \brief Performs non linear optimization over a non-linear function,
+ * using a variant of the Levenberg Marquardt algorithm.
+ *
+ * Check wikipedia for more information.
+ * http://en.wikipedia.org/wiki/Levenberg%E2%80%93Marquardt_algorithm
+ */
+template<typename _FunctorType>
+class LevenbergMarquardt : internal::no_assignment_operator
+{
+ public:
+ typedef _FunctorType FunctorType;
+ typedef typename FunctorType::QRSolver QRSolver;
+ typedef typename FunctorType::JacobianType JacobianType;
+ typedef typename JacobianType::Scalar Scalar;
+ typedef typename JacobianType::RealScalar RealScalar;
+ typedef typename JacobianType::Index Index;
+ typedef typename QRSolver::Index PermIndex;
+ typedef Matrix<Scalar,Dynamic,1> FVectorType;
+ typedef PermutationMatrix<Dynamic,Dynamic> PermutationType;
+ public:
+ LevenbergMarquardt(FunctorType& functor)
+ : m_functor(functor),m_nfev(0),m_njev(0),m_fnorm(0.0),m_gnorm(0),
+ m_isInitialized(false),m_info(InvalidInput)
+ {
+ resetParameters();
+ m_useExternalScaling=false;
+ }
+
+ LevenbergMarquardtSpace::Status minimize(FVectorType &x);
+ LevenbergMarquardtSpace::Status minimizeInit(FVectorType &x);
+ LevenbergMarquardtSpace::Status minimizeOneStep(FVectorType &x);
+ LevenbergMarquardtSpace::Status lmder1(
+ FVectorType &x,
+ const Scalar tol = std::sqrt(NumTraits<Scalar>::epsilon())
+ );
+ static LevenbergMarquardtSpace::Status lmdif1(
+ FunctorType &functor,
+ FVectorType &x,
+ Index *nfev,
+ const Scalar tol = std::sqrt(NumTraits<Scalar>::epsilon())
+ );
+
+ /** Sets the default parameters */
+ void resetParameters()
+ {
+ m_factor = 100.;
+ m_maxfev = 400;
+ m_ftol = std::sqrt(NumTraits<RealScalar>::epsilon());
+ m_xtol = std::sqrt(NumTraits<RealScalar>::epsilon());
+ m_gtol = 0. ;
+ m_epsfcn = 0. ;
+ }
+
+ /** Sets the tolerance for the norm of the solution vector*/
+ void setXtol(RealScalar xtol) { m_xtol = xtol; }
+
+ /** Sets the tolerance for the norm of the vector function*/
+ void setFtol(RealScalar ftol) { m_ftol = ftol; }
+
+ /** Sets the tolerance for the norm of the gradient of the error vector*/
+ void setGtol(RealScalar gtol) { m_gtol = gtol; }
+
+ /** Sets the step bound for the diagonal shift */
+ void setFactor(RealScalar factor) { m_factor = factor; }
+
+ /** Sets the error precision */
+ void setEpsilon (RealScalar epsfcn) { m_epsfcn = epsfcn; }
+
+ /** Sets the maximum number of function evaluation */
+ void setMaxfev(Index maxfev) {m_maxfev = maxfev; }
+
+ /** Use an external Scaling. If set to true, pass a nonzero diagonal to diag() */
+ void setExternalScaling(bool value) {m_useExternalScaling = value; }
+
+ /** \returns a reference to the diagonal of the jacobian */
+ FVectorType& diag() {return m_diag; }
+
+ /** \returns the number of iterations performed */
+ Index iterations() { return m_iter; }
+
+ /** \returns the number of functions evaluation */
+ Index nfev() { return m_nfev; }
+
+ /** \returns the number of jacobian evaluation */
+ Index njev() { return m_njev; }
+
+ /** \returns the norm of current vector function */
+ RealScalar fnorm() {return m_fnorm; }
+
+ /** \returns the norm of the gradient of the error */
+ RealScalar gnorm() {return m_gnorm; }
+
+ /** \returns the LevenbergMarquardt parameter */
+ RealScalar lm_param(void) { return m_par; }
+
+ /** \returns a reference to the current vector function
+ */
+ FVectorType& fvec() {return m_fvec; }
+
+ /** \returns a reference to the matrix where the current Jacobian matrix is stored
+ */
+ JacobianType& jacobian() {return m_fjac; }
+
+ /** \returns a reference to the triangular matrix R from the QR of the jacobian matrix.
+ * \sa jacobian()
+ */
+ JacobianType& matrixR() {return m_rfactor; }
+
+ /** the permutation used in the QR factorization
+ */
+ PermutationType permutation() {return m_permutation; }
+
+ /**
+ * \brief Reports whether the minimization was successful
+ * \returns \c Success if the minimization was succesful,
+ * \c NumericalIssue if a numerical problem arises during the
+ * minimization process, for exemple during the QR factorization
+ * \c NoConvergence if the minimization did not converge after
+ * the maximum number of function evaluation allowed
+ * \c InvalidInput if the input matrix is invalid
+ */
+ ComputationInfo info() const
+ {
+
+ return m_info;
+ }
+ private:
+ JacobianType m_fjac;
+ JacobianType m_rfactor; // The triangular matrix R from the QR of the jacobian matrix m_fjac
+ FunctorType &m_functor;
+ FVectorType m_fvec, m_qtf, m_diag;
+ Index n;
+ Index m;
+ Index m_nfev;
+ Index m_njev;
+ RealScalar m_fnorm; // Norm of the current vector function
+ RealScalar m_gnorm; //Norm of the gradient of the error
+ RealScalar m_factor; //
+ Index m_maxfev; // Maximum number of function evaluation
+ RealScalar m_ftol; //Tolerance in the norm of the vector function
+ RealScalar m_xtol; //
+ RealScalar m_gtol; //tolerance of the norm of the error gradient
+ RealScalar m_epsfcn; //
+ Index m_iter; // Number of iterations performed
+ RealScalar m_delta;
+ bool m_useExternalScaling;
+ PermutationType m_permutation;
+ FVectorType m_wa1, m_wa2, m_wa3, m_wa4; //Temporary vectors
+ RealScalar m_par;
+ bool m_isInitialized; // Check whether the minimization step has been called
+ ComputationInfo m_info;
+};
+
+template<typename FunctorType>
+LevenbergMarquardtSpace::Status
+LevenbergMarquardt<FunctorType>::minimize(FVectorType &x)
+{
+ LevenbergMarquardtSpace::Status status = minimizeInit(x);
+ if (status==LevenbergMarquardtSpace::ImproperInputParameters) {
+ m_isInitialized = true;
+ return status;
+ }
+ do {
+// std::cout << " uv " << x.transpose() << "\n";
+ status = minimizeOneStep(x);
+ } while (status==LevenbergMarquardtSpace::Running);
+ m_isInitialized = true;
+ return status;
+}
+
+template<typename FunctorType>
+LevenbergMarquardtSpace::Status
+LevenbergMarquardt<FunctorType>::minimizeInit(FVectorType &x)
+{
+ n = x.size();
+ m = m_functor.values();
+
+ m_wa1.resize(n); m_wa2.resize(n); m_wa3.resize(n);
+ m_wa4.resize(m);
+ m_fvec.resize(m);
+ //FIXME Sparse Case : Allocate space for the jacobian
+ m_fjac.resize(m, n);
+// m_fjac.reserve(VectorXi::Constant(n,5)); // FIXME Find a better alternative
+ if (!m_useExternalScaling)
+ m_diag.resize(n);
+ eigen_assert( (!m_useExternalScaling || m_diag.size()==n) || "When m_useExternalScaling is set, the caller must provide a valid 'm_diag'");
+ m_qtf.resize(n);
+
+ /* Function Body */
+ m_nfev = 0;
+ m_njev = 0;
+
+ /* check the input parameters for errors. */
+ if (n <= 0 || m < n || m_ftol < 0. || m_xtol < 0. || m_gtol < 0. || m_maxfev <= 0 || m_factor <= 0.){
+ m_info = InvalidInput;
+ return LevenbergMarquardtSpace::ImproperInputParameters;
+ }
+
+ if (m_useExternalScaling)
+ for (Index j = 0; j < n; ++j)
+ if (m_diag[j] <= 0.)
+ {
+ m_info = InvalidInput;
+ return LevenbergMarquardtSpace::ImproperInputParameters;
+ }
+
+ /* evaluate the function at the starting point */
+ /* and calculate its norm. */
+ m_nfev = 1;
+ if ( m_functor(x, m_fvec) < 0)
+ return LevenbergMarquardtSpace::UserAsked;
+ m_fnorm = m_fvec.stableNorm();
+
+ /* initialize levenberg-marquardt parameter and iteration counter. */
+ m_par = 0.;
+ m_iter = 1;
+
+ return LevenbergMarquardtSpace::NotStarted;
+}
+
+template<typename FunctorType>
+LevenbergMarquardtSpace::Status
+LevenbergMarquardt<FunctorType>::lmder1(
+ FVectorType &x,
+ const Scalar tol
+ )
+{
+ n = x.size();
+ m = m_functor.values();
+
+ /* check the input parameters for errors. */
+ if (n <= 0 || m < n || tol < 0.)
+ return LevenbergMarquardtSpace::ImproperInputParameters;
+
+ resetParameters();
+ m_ftol = tol;
+ m_xtol = tol;
+ m_maxfev = 100*(n+1);
+
+ return minimize(x);
+}
+
+
+template<typename FunctorType>
+LevenbergMarquardtSpace::Status
+LevenbergMarquardt<FunctorType>::lmdif1(
+ FunctorType &functor,
+ FVectorType &x,
+ Index *nfev,
+ const Scalar tol
+ )
+{
+ Index n = x.size();
+ Index m = functor.values();
+
+ /* check the input parameters for errors. */
+ if (n <= 0 || m < n || tol < 0.)
+ return LevenbergMarquardtSpace::ImproperInputParameters;
+
+ NumericalDiff<FunctorType> numDiff(functor);
+ // embedded LevenbergMarquardt
+ LevenbergMarquardt<NumericalDiff<FunctorType> > lm(numDiff);
+ lm.setFtol(tol);
+ lm.setXtol(tol);
+ lm.setMaxfev(200*(n+1));
+
+ LevenbergMarquardtSpace::Status info = LevenbergMarquardtSpace::Status(lm.minimize(x));
+ if (nfev)
+ * nfev = lm.nfev();
+ return info;
+}
+
+} // end namespace Eigen
+
+#endif // EIGEN_LEVENBERGMARQUARDT_H
diff --git a/unsupported/Eigen/src/MatrixFunctions/MatrixExponential.h b/unsupported/Eigen/src/MatrixFunctions/MatrixExponential.h
index 642916764..6825a7882 100644
--- a/unsupported/Eigen/src/MatrixFunctions/MatrixExponential.h
+++ b/unsupported/Eigen/src/MatrixFunctions/MatrixExponential.h
@@ -13,12 +13,7 @@
#include "StemFunction.h"
-namespace Eigen {
-
-#if defined(_MSC_VER) || defined(__FreeBSD__)
- template <typename Scalar> Scalar log2(Scalar v) { using std::log; return log(v)/log(Scalar(2)); }
-#endif
-
+namespace Eigen {
/** \ingroup MatrixFunctions_Module
* \brief Class for computing the matrix exponential.
@@ -233,7 +228,7 @@ template <typename MatrixType>
EIGEN_STRONG_INLINE void MatrixExponential<MatrixType>::pade9(const MatrixType &A)
{
const RealScalar b[] = {17643225600., 8821612800., 2075673600., 302702400., 30270240.,
- 2162160., 110880., 3960., 90., 1.};
+ 2162160., 110880., 3960., 90., 1.};
MatrixType A2 = A * A;
MatrixType A4 = A2 * A2;
MatrixType A6 = A4 * A2;
@@ -247,8 +242,8 @@ template <typename MatrixType>
EIGEN_STRONG_INLINE void MatrixExponential<MatrixType>::pade13(const MatrixType &A)
{
const RealScalar b[] = {64764752532480000., 32382376266240000., 7771770303897600.,
- 1187353796428800., 129060195264000., 10559470521600., 670442572800.,
- 33522128640., 1323241920., 40840800., 960960., 16380., 182., 1.};
+ 1187353796428800., 129060195264000., 10559470521600., 670442572800.,
+ 33522128640., 1323241920., 40840800., 960960., 16380., 182., 1.};
MatrixType A2 = A * A;
MatrixType A4 = A2 * A2;
m_tmp1.noalias() = A4 * A2;
@@ -266,11 +261,11 @@ template <typename MatrixType>
EIGEN_STRONG_INLINE void MatrixExponential<MatrixType>::pade17(const MatrixType &A)
{
const RealScalar b[] = {830034394580628357120000.L, 415017197290314178560000.L,
- 100610229646136770560000.L, 15720348382208870400000.L,
- 1774878043152614400000.L, 153822763739893248000.L, 10608466464820224000.L,
- 595373117923584000.L, 27563570274240000.L, 1060137318240000.L,
- 33924394183680.L, 899510451840.L, 19554575040.L, 341863200.L, 4651200.L,
- 46512.L, 306.L, 1.L};
+ 100610229646136770560000.L, 15720348382208870400000.L,
+ 1774878043152614400000.L, 153822763739893248000.L, 10608466464820224000.L,
+ 595373117923584000.L, 27563570274240000.L, 1060137318240000.L,
+ 33924394183680.L, 899510451840.L, 19554575040.L, 341863200.L, 4651200.L,
+ 46512.L, 306.L, 1.L};
MatrixType A2 = A * A;
MatrixType A4 = A2 * A2;
MatrixType A6 = A4 * A2;
@@ -288,16 +283,16 @@ EIGEN_STRONG_INLINE void MatrixExponential<MatrixType>::pade17(const MatrixType
template <typename MatrixType>
void MatrixExponential<MatrixType>::computeUV(float)
{
- using std::max;
+ using std::frexp;
using std::pow;
- using std::ceil;
if (m_l1norm < 4.258730016922831e-001) {
pade3(m_M);
} else if (m_l1norm < 1.880152677804762e+000) {
pade5(m_M);
} else {
const float maxnorm = 3.925724783138660f;
- m_squarings = (max)(0, (int)ceil(log2(m_l1norm / maxnorm)));
+ frexp(m_l1norm / maxnorm, &m_squarings);
+ if (m_squarings < 0) m_squarings = 0;
MatrixType A = m_M / pow(Scalar(2), m_squarings);
pade7(A);
}
@@ -306,9 +301,8 @@ void MatrixExponential<MatrixType>::computeUV(float)
template <typename MatrixType>
void MatrixExponential<MatrixType>::computeUV(double)
{
- using std::max;
+ using std::frexp;
using std::pow;
- using std::ceil;
if (m_l1norm < 1.495585217958292e-002) {
pade3(m_M);
} else if (m_l1norm < 2.539398330063230e-001) {
@@ -319,7 +313,8 @@ void MatrixExponential<MatrixType>::computeUV(double)
pade9(m_M);
} else {
const double maxnorm = 5.371920351148152;
- m_squarings = (max)(0, (int)ceil(log2(m_l1norm / maxnorm)));
+ frexp(m_l1norm / maxnorm, &m_squarings);
+ if (m_squarings < 0) m_squarings = 0;
MatrixType A = m_M / pow(Scalar(2), m_squarings);
pade13(A);
}
@@ -328,9 +323,8 @@ void MatrixExponential<MatrixType>::computeUV(double)
template <typename MatrixType>
void MatrixExponential<MatrixType>::computeUV(long double)
{
- using std::max;
+ using std::frexp;
using std::pow;
- using std::ceil;
#if LDBL_MANT_DIG == 53 // double precision
computeUV(double());
#elif LDBL_MANT_DIG <= 64 // extended precision
@@ -344,7 +338,8 @@ void MatrixExponential<MatrixType>::computeUV(long double)
pade9(m_M);
} else {
const long double maxnorm = 4.0246098906697353063L;
- m_squarings = (max)(0, (int)ceil(log2(m_l1norm / maxnorm)));
+ frexp(m_l1norm / maxnorm, &m_squarings);
+ if (m_squarings < 0) m_squarings = 0;
MatrixType A = m_M / pow(Scalar(2), m_squarings);
pade13(A);
}
@@ -361,7 +356,8 @@ void MatrixExponential<MatrixType>::computeUV(long double)
pade13(m_M);
} else {
const long double maxnorm = 3.2579440895405400856599663723517L;
- m_squarings = (max)(0, (int)ceil(log2(m_l1norm / maxnorm)));
+ frexp(m_l1norm / maxnorm, &m_squarings);
+ if (m_squarings < 0) m_squarings = 0;
MatrixType A = m_M / pow(Scalar(2), m_squarings);
pade17(A);
}
@@ -378,7 +374,8 @@ void MatrixExponential<MatrixType>::computeUV(long double)
pade13(m_M);
} else {
const long double maxnorm = 2.884233277829519311757165057717815L;
- m_squarings = (max)(0, (int)ceil(log2(m_l1norm / maxnorm)));
+ frexp(m_l1norm / maxnorm, &m_squarings);
+ if (m_squarings < 0) m_squarings = 0;
MatrixType A = m_M / pow(Scalar(2), m_squarings);
pade17(A);
}
diff --git a/unsupported/Eigen/src/MatrixFunctions/MatrixFunction.h b/unsupported/Eigen/src/MatrixFunctions/MatrixFunction.h
index c57ca87ed..7d426640c 100644
--- a/unsupported/Eigen/src/MatrixFunctions/MatrixFunction.h
+++ b/unsupported/Eigen/src/MatrixFunctions/MatrixFunction.h
@@ -209,7 +209,7 @@ void MatrixFunction<MatrixType,AtomicType,1>::compute(ResultType& result)
permuteSchur();
computeBlockAtomic();
computeOffDiagonal();
- result = m_U * m_fT * m_U.adjoint();
+ result = m_U * (m_fT.template triangularView<Upper>() * m_U.adjoint());
}
/** \brief Store the Schur decomposition of #m_A in #m_T and #m_U */
@@ -235,6 +235,7 @@ void MatrixFunction<MatrixType,AtomicType,1>::computeSchurDecomposition()
template <typename MatrixType, typename AtomicType>
void MatrixFunction<MatrixType,AtomicType,1>::partitionEigenvalues()
{
+ using std::abs;
const Index rows = m_T.rows();
VectorType diag = m_T.diagonal(); // contains eigenvalues of A
@@ -251,14 +252,14 @@ void MatrixFunction<MatrixType,AtomicType,1>::partitionEigenvalues()
// Look for other element to add to the set
for (Index j=i+1; j<rows; ++j) {
- if (internal::abs(diag(j) - diag(i)) <= separation() && std::find(qi->begin(), qi->end(), diag(j)) == qi->end()) {
- typename ListOfClusters::iterator qj = findCluster(diag(j));
- if (qj == m_clusters.end()) {
- qi->push_back(diag(j));
- } else {
- qi->insert(qi->end(), qj->begin(), qj->end());
- m_clusters.erase(qj);
- }
+ if (abs(diag(j) - diag(i)) <= separation() && std::find(qi->begin(), qi->end(), diag(j)) == qi->end()) {
+ typename ListOfClusters::iterator qj = findCluster(diag(j));
+ if (qj == m_clusters.end()) {
+ qi->push_back(diag(j));
+ } else {
+ qi->insert(qi->end(), qj->begin(), qj->end());
+ m_clusters.erase(qj);
+ }
}
}
}
diff --git a/unsupported/Eigen/src/MatrixFunctions/MatrixLogarithm.h b/unsupported/Eigen/src/MatrixFunctions/MatrixLogarithm.h
index 3a50514b9..c744fc05f 100644
--- a/unsupported/Eigen/src/MatrixFunctions/MatrixLogarithm.h
+++ b/unsupported/Eigen/src/MatrixFunctions/MatrixLogarithm.h
@@ -51,7 +51,6 @@ private:
void compute2x2(const MatrixType& A, MatrixType& result);
void computeBig(const MatrixType& A, MatrixType& result);
- static Scalar atanh(Scalar x);
int getPadeDegree(float normTminusI);
int getPadeDegree(double normTminusI);
int getPadeDegree(long double normTminusI);
@@ -67,10 +66,11 @@ private:
void computePade11(MatrixType& result, const MatrixType& T);
static const int minPadeDegree = 3;
- static const int maxPadeDegree = std::numeric_limits<RealScalar>::digits<= 24? 5: // single precision
- std::numeric_limits<RealScalar>::digits<= 53? 7: // double precision
- std::numeric_limits<RealScalar>::digits<= 64? 8: // extended precision
- std::numeric_limits<RealScalar>::digits<=106? 10: 11; // double-double or quadruple precision
+ static const int maxPadeDegree = std::numeric_limits<RealScalar>::digits<= 24? 5: // single precision
+ std::numeric_limits<RealScalar>::digits<= 53? 7: // double precision
+ std::numeric_limits<RealScalar>::digits<= 64? 8: // extended precision
+ std::numeric_limits<RealScalar>::digits<=106? 10: // double-double
+ 11; // quadruple precision
// Prevent copying
MatrixLogarithmAtomic(const MatrixLogarithmAtomic&);
@@ -92,18 +92,6 @@ MatrixType MatrixLogarithmAtomic<MatrixType>::compute(const MatrixType& A)
return result;
}
-/** \brief Compute atanh (inverse hyperbolic tangent). */
-template <typename MatrixType>
-typename MatrixType::Scalar MatrixLogarithmAtomic<MatrixType>::atanh(typename MatrixType::Scalar x)
-{
- using std::abs;
- using std::sqrt;
- if (abs(x) > sqrt(NumTraits<Scalar>::epsilon()))
- return Scalar(0.5) * log((Scalar(1) + x) / (Scalar(1) - x));
- else
- return x + x*x*x / Scalar(3);
-}
-
/** \brief Compute logarithm of 2x2 triangular matrix. */
template <typename MatrixType>
void MatrixLogarithmAtomic<MatrixType>::compute2x2(const MatrixType& A, MatrixType& result)
@@ -127,8 +115,8 @@ void MatrixLogarithmAtomic<MatrixType>::compute2x2(const MatrixType& A, MatrixTy
} else {
// computation in previous branch is inaccurate if A(1,1) \approx A(0,0)
int unwindingNumber = static_cast<int>(ceil((imag(logA11 - logA00) - M_PI) / (2*M_PI)));
- Scalar z = (A(1,1) - A(0,0)) / (A(1,1) + A(0,0));
- result(0,1) = A(0,1) * (Scalar(2) * atanh(z) + Scalar(0,2*M_PI*unwindingNumber)) / (A(1,1) - A(0,0));
+ Scalar y = A(1,1) - A(0,0), x = A(1,1) + A(0,0);
+ result(0,1) = A(0,1) * (Scalar(2) * numext::atanh2(y,x) + Scalar(0,2*M_PI*unwindingNumber)) / y;
}
}
@@ -137,10 +125,11 @@ void MatrixLogarithmAtomic<MatrixType>::compute2x2(const MatrixType& A, MatrixTy
template <typename MatrixType>
void MatrixLogarithmAtomic<MatrixType>::computeBig(const MatrixType& A, MatrixType& result)
{
+ using std::pow;
int numberOfSquareRoots = 0;
int numberOfExtraSquareRoots = 0;
int degree;
- MatrixType T = A;
+ MatrixType T = A, sqrtT;
const RealScalar maxNormForPade = maxPadeDegree<= 5? 5.3149729967117310e-1: // single precision
maxPadeDegree<= 7? 2.6429608311114350e-1: // double precision
maxPadeDegree<= 8? 2.32777776523703892094e-1L: // extended precision
@@ -153,12 +142,11 @@ void MatrixLogarithmAtomic<MatrixType>::computeBig(const MatrixType& A, MatrixTy
degree = getPadeDegree(normTminusI);
int degree2 = getPadeDegree(normTminusI / RealScalar(2));
if ((degree - degree2 <= 1) || (numberOfExtraSquareRoots == 1))
- break;
+ break;
++numberOfExtraSquareRoots;
}
- MatrixType sqrtT;
MatrixSquareRootTriangular<MatrixType>(T).compute(sqrtT);
- T = sqrtT;
+ T = sqrtT.template triangularView<Upper>();
++numberOfSquareRoots;
}
@@ -172,10 +160,11 @@ int MatrixLogarithmAtomic<MatrixType>::getPadeDegree(float normTminusI)
{
const float maxNormForPade[] = { 2.5111573934555054e-1 /* degree = 3 */ , 4.0535837411880493e-1,
5.3149729967117310e-1 };
- for (int degree = 3; degree <= maxPadeDegree; ++degree)
+ int degree = 3;
+ for (; degree <= maxPadeDegree; ++degree)
if (normTminusI <= maxNormForPade[degree - minPadeDegree])
- return degree;
- assert(false); // this line should never be reached
+ break;
+ return degree;
}
/* \brief Get suitable degree for Pade approximation. (specialized for RealScalar = double) */
@@ -184,10 +173,11 @@ int MatrixLogarithmAtomic<MatrixType>::getPadeDegree(double normTminusI)
{
const double maxNormForPade[] = { 1.6206284795015624e-2 /* degree = 3 */ , 5.3873532631381171e-2,
1.1352802267628681e-1, 1.8662860613541288e-1, 2.642960831111435e-1 };
- for (int degree = 3; degree <= maxPadeDegree; ++degree)
+ int degree = 3;
+ for (; degree <= maxPadeDegree; ++degree)
if (normTminusI <= maxNormForPade[degree - minPadeDegree])
- return degree;
- assert(false); // this line should never be reached
+ break;
+ return degree;
}
/* \brief Get suitable degree for Pade approximation. (specialized for RealScalar = long double) */
@@ -195,29 +185,30 @@ template <typename MatrixType>
int MatrixLogarithmAtomic<MatrixType>::getPadeDegree(long double normTminusI)
{
#if LDBL_MANT_DIG == 53 // double precision
- const double maxNormForPade[] = { 1.6206284795015624e-2 /* degree = 3 */ , 5.3873532631381171e-2,
- 1.1352802267628681e-1, 1.8662860613541288e-1, 2.642960831111435e-1 };
+ const long double maxNormForPade[] = { 1.6206284795015624e-2L /* degree = 3 */ , 5.3873532631381171e-2L,
+ 1.1352802267628681e-1L, 1.8662860613541288e-1L, 2.642960831111435e-1L };
#elif LDBL_MANT_DIG <= 64 // extended precision
- const double maxNormForPade[] = { 5.48256690357782863103e-3 /* degree = 3 */, 2.34559162387971167321e-2,
- 5.84603923897347449857e-2, 1.08486423756725170223e-1, 1.68385767881294446649e-1,
- 2.32777776523703892094e-1 };
+ const long double maxNormForPade[] = { 5.48256690357782863103e-3L /* degree = 3 */, 2.34559162387971167321e-2L,
+ 5.84603923897347449857e-2L, 1.08486423756725170223e-1L, 1.68385767881294446649e-1L,
+ 2.32777776523703892094e-1L };
#elif LDBL_MANT_DIG <= 106 // double-double
- const double maxNormForPade[] = { 8.58970550342939562202529664318890e-5 /* degree = 3 */,
- 9.34074328446359654039446552677759e-4, 4.26117194647672175773064114582860e-3,
- 1.21546224740281848743149666560464e-2, 2.61100544998339436713088248557444e-2,
- 4.66170074627052749243018566390567e-2, 7.32585144444135027565872014932387e-2,
- 1.05026503471351080481093652651105e-1 };
+ const long double maxNormForPade[] = { 8.58970550342939562202529664318890e-5L /* degree = 3 */,
+ 9.34074328446359654039446552677759e-4L, 4.26117194647672175773064114582860e-3L,
+ 1.21546224740281848743149666560464e-2L, 2.61100544998339436713088248557444e-2L,
+ 4.66170074627052749243018566390567e-2L, 7.32585144444135027565872014932387e-2L,
+ 1.05026503471351080481093652651105e-1L };
#else // quadruple precision
- const double maxNormForPade[] = { 4.7419931187193005048501568167858103e-5 /* degree = 3 */,
- 5.8853168473544560470387769480192666e-4, 2.9216120366601315391789493628113520e-3,
- 8.8415758124319434347116734705174308e-3, 1.9850836029449446668518049562565291e-2,
- 3.6688019729653446926585242192447447e-2, 5.9290962294020186998954055264528393e-2,
- 8.6998436081634343903250580992127677e-2, 1.1880960220216759245467951592883642e-1 };
+ const long double maxNormForPade[] = { 4.7419931187193005048501568167858103e-5L /* degree = 3 */,
+ 5.8853168473544560470387769480192666e-4L, 2.9216120366601315391789493628113520e-3L,
+ 8.8415758124319434347116734705174308e-3L, 1.9850836029449446668518049562565291e-2L,
+ 3.6688019729653446926585242192447447e-2L, 5.9290962294020186998954055264528393e-2L,
+ 8.6998436081634343903250580992127677e-2L, 1.1880960220216759245467951592883642e-1L };
#endif
- for (int degree = 3; degree <= maxPadeDegree; ++degree)
+ int degree = 3;
+ for (; degree <= maxPadeDegree; ++degree)
if (normTminusI <= maxNormForPade[degree - minPadeDegree])
- return degree;
- assert(false); // this line should never be reached
+ break;
+ return degree;
}
/* \brief Compute Pade approximation to matrix logarithm */
@@ -246,7 +237,7 @@ void MatrixLogarithmAtomic<MatrixType>::computePade3(MatrixType& result, const M
0.8872983346207416885179265399782400L };
const RealScalar weights[] = { 0.2777777777777777777777777777777778L, 0.4444444444444444444444444444444444L,
0.2777777777777777777777777777777778L };
- assert(degree <= maxPadeDegree);
+ eigen_assert(degree <= maxPadeDegree);
MatrixType TminusI = T - MatrixType::Identity(T.rows(), T.rows());
result.setZero(T.rows(), T.rows());
for (int k = 0; k < degree; ++k)
@@ -262,7 +253,7 @@ void MatrixLogarithmAtomic<MatrixType>::computePade4(MatrixType& result, const M
0.6699905217924281324013328795516223L, 0.9305681557970262876119732444464048L };
const RealScalar weights[] = { 0.1739274225687269286865319746109997L, 0.3260725774312730713134680253890003L,
0.3260725774312730713134680253890003L, 0.1739274225687269286865319746109997L };
- assert(degree <= maxPadeDegree);
+ eigen_assert(degree <= maxPadeDegree);
MatrixType TminusI = T - MatrixType::Identity(T.rows(), T.rows());
result.setZero(T.rows(), T.rows());
for (int k = 0; k < degree; ++k)
@@ -280,7 +271,7 @@ void MatrixLogarithmAtomic<MatrixType>::computePade5(MatrixType& result, const M
const RealScalar weights[] = { 0.1184634425280945437571320203599587L, 0.2393143352496832340206457574178191L,
0.2844444444444444444444444444444444L, 0.2393143352496832340206457574178191L,
0.1184634425280945437571320203599587L };
- assert(degree <= maxPadeDegree);
+ eigen_assert(degree <= maxPadeDegree);
MatrixType TminusI = T - MatrixType::Identity(T.rows(), T.rows());
result.setZero(T.rows(), T.rows());
for (int k = 0; k < degree; ++k)
@@ -294,11 +285,11 @@ void MatrixLogarithmAtomic<MatrixType>::computePade6(MatrixType& result, const M
const int degree = 6;
const RealScalar nodes[] = { 0.0337652428984239860938492227530027L, 0.1693953067668677431693002024900473L,
0.3806904069584015456847491391596440L, 0.6193095930415984543152508608403560L,
- 0.8306046932331322568306997975099527L, 0.9662347571015760139061507772469973L };
+ 0.8306046932331322568306997975099527L, 0.9662347571015760139061507772469973L };
const RealScalar weights[] = { 0.0856622461895851725201480710863665L, 0.1803807865240693037849167569188581L,
0.2339569672863455236949351719947755L, 0.2339569672863455236949351719947755L,
- 0.1803807865240693037849167569188581L, 0.0856622461895851725201480710863665L };
- assert(degree <= maxPadeDegree);
+ 0.1803807865240693037849167569188581L, 0.0856622461895851725201480710863665L };
+ eigen_assert(degree <= maxPadeDegree);
MatrixType TminusI = T - MatrixType::Identity(T.rows(), T.rows());
result.setZero(T.rows(), T.rows());
for (int k = 0; k < degree; ++k)
@@ -318,7 +309,7 @@ void MatrixLogarithmAtomic<MatrixType>::computePade7(MatrixType& result, const M
0.1909150252525594724751848877444876L, 0.2089795918367346938775510204081633L,
0.1909150252525594724751848877444876L, 0.1398526957446383339507338857118898L,
0.0647424830844348466353057163395410L };
- assert(degree <= maxPadeDegree);
+ eigen_assert(degree <= maxPadeDegree);
MatrixType TminusI = T - MatrixType::Identity(T.rows(), T.rows());
result.setZero(T.rows(), T.rows());
for (int k = 0; k < degree; ++k)
@@ -338,7 +329,7 @@ void MatrixLogarithmAtomic<MatrixType>::computePade8(MatrixType& result, const M
0.1568533229389436436689811009933007L, 0.1813418916891809914825752246385978L,
0.1813418916891809914825752246385978L, 0.1568533229389436436689811009933007L,
0.1111905172266872352721779972131204L, 0.0506142681451881295762656771549811L };
- assert(degree <= maxPadeDegree);
+ eigen_assert(degree <= maxPadeDegree);
MatrixType TminusI = T - MatrixType::Identity(T.rows(), T.rows());
result.setZero(T.rows(), T.rows());
for (int k = 0; k < degree; ++k)
@@ -360,7 +351,7 @@ void MatrixLogarithmAtomic<MatrixType>::computePade9(MatrixType& result, const M
0.1651196775006298815822625346434870L, 0.1561735385200014200343152032922218L,
0.1303053482014677311593714347093164L, 0.0903240803474287020292360156214564L,
0.0406371941807872059859460790552618L };
- assert(degree <= maxPadeDegree);
+ eigen_assert(degree <= maxPadeDegree);
MatrixType TminusI = T - MatrixType::Identity(T.rows(), T.rows());
result.setZero(T.rows(), T.rows());
for (int k = 0; k < degree; ++k)
@@ -382,7 +373,7 @@ void MatrixLogarithmAtomic<MatrixType>::computePade10(MatrixType& result, const
0.1477621123573764350869464973256692L, 0.1477621123573764350869464973256692L,
0.1346333596549981775456134607847347L, 0.1095431812579910219977674671140816L,
0.0747256745752902965728881698288487L, 0.0333356721543440687967844049466659L };
- assert(degree <= maxPadeDegree);
+ eigen_assert(degree <= maxPadeDegree);
MatrixType TminusI = T - MatrixType::Identity(T.rows(), T.rows());
result.setZero(T.rows(), T.rows());
for (int k = 0; k < degree; ++k)
@@ -406,7 +397,7 @@ void MatrixLogarithmAtomic<MatrixType>::computePade11(MatrixType& result, const
0.1314022722551233310903444349452546L, 0.1165968822959952399592618524215876L,
0.0931451054638671257130488207158280L, 0.0627901847324523123173471496119701L,
0.0278342835580868332413768602212743L };
- assert(degree <= maxPadeDegree);
+ eigen_assert(degree <= maxPadeDegree);
MatrixType TminusI = T - MatrixType::Identity(T.rows(), T.rows());
result.setZero(T.rows(), T.rows());
for (int k = 0; k < degree; ++k)
@@ -423,8 +414,8 @@ void MatrixLogarithmAtomic<MatrixType>::computePade11(MatrixType& result, const
* This class holds the argument to the matrix function until it is
* assigned or evaluated for some other reason (so the argument
* should not be changed in the meantime). It is the return type of
- * matrixBase::matrixLogarithm() and most of the time this is the
- * only way it is used.
+ * MatrixBase::log() and most of the time this is the only way it
+ * is used.
*/
template<typename Derived> class MatrixLogarithmReturnValue
: public ReturnByValue<MatrixLogarithmReturnValue<Derived> >
diff --git a/unsupported/Eigen/src/MatrixFunctions/MatrixPower.h b/unsupported/Eigen/src/MatrixFunctions/MatrixPower.h
new file mode 100644
index 000000000..c32437281
--- /dev/null
+++ b/unsupported/Eigen/src/MatrixFunctions/MatrixPower.h
@@ -0,0 +1,509 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012, 2013 Chen-Pang He <jdh8@ms63.hinet.net>
+//
+// 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_MATRIX_POWER
+#define EIGEN_MATRIX_POWER
+
+namespace Eigen {
+
+template<typename MatrixType> class MatrixPower;
+
+template<typename MatrixType>
+class MatrixPowerRetval : public ReturnByValue< MatrixPowerRetval<MatrixType> >
+{
+ public:
+ typedef typename MatrixType::RealScalar RealScalar;
+ typedef typename MatrixType::Index Index;
+
+ MatrixPowerRetval(MatrixPower<MatrixType>& pow, RealScalar p) : m_pow(pow), m_p(p)
+ { }
+
+ template<typename ResultType>
+ inline void evalTo(ResultType& res) const
+ { m_pow.compute(res, m_p); }
+
+ Index rows() const { return m_pow.rows(); }
+ Index cols() const { return m_pow.cols(); }
+
+ private:
+ MatrixPower<MatrixType>& m_pow;
+ const RealScalar m_p;
+ MatrixPowerRetval& operator=(const MatrixPowerRetval&);
+};
+
+template<typename MatrixType>
+class MatrixPowerAtomic
+{
+ private:
+ enum {
+ RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+ MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime
+ };
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::RealScalar RealScalar;
+ typedef std::complex<RealScalar> ComplexScalar;
+ typedef typename MatrixType::Index Index;
+ typedef Array<Scalar, RowsAtCompileTime, 1, ColMajor, MaxRowsAtCompileTime> ArrayType;
+
+ const MatrixType& m_A;
+ RealScalar m_p;
+
+ void computePade(int degree, const MatrixType& IminusT, MatrixType& res) const;
+ void compute2x2(MatrixType& res, RealScalar p) const;
+ void computeBig(MatrixType& res) const;
+ static int getPadeDegree(float normIminusT);
+ static int getPadeDegree(double normIminusT);
+ static int getPadeDegree(long double normIminusT);
+ static ComplexScalar computeSuperDiag(const ComplexScalar&, const ComplexScalar&, RealScalar p);
+ static RealScalar computeSuperDiag(RealScalar, RealScalar, RealScalar p);
+
+ public:
+ MatrixPowerAtomic(const MatrixType& T, RealScalar p);
+ void compute(MatrixType& res) const;
+};
+
+template<typename MatrixType>
+MatrixPowerAtomic<MatrixType>::MatrixPowerAtomic(const MatrixType& T, RealScalar p) :
+ m_A(T), m_p(p)
+{ eigen_assert(T.rows() == T.cols()); }
+
+template<typename MatrixType>
+void MatrixPowerAtomic<MatrixType>::compute(MatrixType& res) const
+{
+ res.resizeLike(m_A);
+ switch (m_A.rows()) {
+ case 0:
+ break;
+ case 1:
+ res(0,0) = std::pow(m_A(0,0), m_p);
+ break;
+ case 2:
+ compute2x2(res, m_p);
+ break;
+ default:
+ computeBig(res);
+ }
+}
+
+template<typename MatrixType>
+void MatrixPowerAtomic<MatrixType>::computePade(int degree, const MatrixType& IminusT, MatrixType& res) const
+{
+ int i = degree<<1;
+ res = (m_p-degree) / ((i-1)<<1) * IminusT;
+ for (--i; i; --i) {
+ res = (MatrixType::Identity(IminusT.rows(), IminusT.cols()) + res).template triangularView<Upper>()
+ .solve((i==1 ? -m_p : i&1 ? (-m_p-(i>>1))/(i<<1) : (m_p-(i>>1))/((i-1)<<1)) * IminusT).eval();
+ }
+ res += MatrixType::Identity(IminusT.rows(), IminusT.cols());
+}
+
+// This function assumes that res has the correct size (see bug 614)
+template<typename MatrixType>
+void MatrixPowerAtomic<MatrixType>::compute2x2(MatrixType& res, RealScalar p) const
+{
+ using std::abs;
+ using std::pow;
+
+ ArrayType logTdiag = m_A.diagonal().array().log();
+ res.coeffRef(0,0) = pow(m_A.coeff(0,0), p);
+
+ for (Index i=1; i < m_A.cols(); ++i) {
+ res.coeffRef(i,i) = pow(m_A.coeff(i,i), p);
+ if (m_A.coeff(i-1,i-1) == m_A.coeff(i,i))
+ res.coeffRef(i-1,i) = p * pow(m_A.coeff(i,i), p-1);
+ else if (2*abs(m_A.coeff(i-1,i-1)) < abs(m_A.coeff(i,i)) || 2*abs(m_A.coeff(i,i)) < abs(m_A.coeff(i-1,i-1)))
+ res.coeffRef(i-1,i) = (res.coeff(i,i)-res.coeff(i-1,i-1)) / (m_A.coeff(i,i)-m_A.coeff(i-1,i-1));
+ else
+ res.coeffRef(i-1,i) = computeSuperDiag(m_A.coeff(i,i), m_A.coeff(i-1,i-1), p);
+ res.coeffRef(i-1,i) *= m_A.coeff(i-1,i);
+ }
+}
+
+template<typename MatrixType>
+void MatrixPowerAtomic<MatrixType>::computeBig(MatrixType& res) const
+{
+ const int digits = std::numeric_limits<RealScalar>::digits;
+ const RealScalar maxNormForPade = digits <= 24? 4.3386528e-1f: // sigle precision
+ digits <= 53? 2.789358995219730e-1: // double precision
+ digits <= 64? 2.4471944416607995472e-1L: // extended precision
+ digits <= 106? 1.1016843812851143391275867258512e-1L: // double-double
+ 9.134603732914548552537150753385375e-2L; // quadruple precision
+ MatrixType IminusT, sqrtT, T = m_A.template triangularView<Upper>();
+ RealScalar normIminusT;
+ int degree, degree2, numberOfSquareRoots = 0;
+ bool hasExtraSquareRoot = false;
+
+ /* FIXME
+ * For singular T, norm(I - T) >= 1 but maxNormForPade < 1, leads to infinite
+ * loop. We should move 0 eigenvalues to bottom right corner. We need not
+ * worry about tiny values (e.g. 1e-300) because they will reach 1 if
+ * repetitively sqrt'ed.
+ *
+ * If the 0 eigenvalues are semisimple, they can form a 0 matrix at the
+ * bottom right corner.
+ *
+ * [ T A ]^p [ T^p (T^-1 T^p A) ]
+ * [ ] = [ ]
+ * [ 0 0 ] [ 0 0 ]
+ */
+ for (Index i=0; i < m_A.cols(); ++i)
+ eigen_assert(m_A(i,i) != RealScalar(0));
+
+ while (true) {
+ IminusT = MatrixType::Identity(m_A.rows(), m_A.cols()) - T;
+ normIminusT = IminusT.cwiseAbs().colwise().sum().maxCoeff();
+ if (normIminusT < maxNormForPade) {
+ degree = getPadeDegree(normIminusT);
+ degree2 = getPadeDegree(normIminusT/2);
+ if (degree - degree2 <= 1 || hasExtraSquareRoot)
+ break;
+ hasExtraSquareRoot = true;
+ }
+ MatrixSquareRootTriangular<MatrixType>(T).compute(sqrtT);
+ T = sqrtT.template triangularView<Upper>();
+ ++numberOfSquareRoots;
+ }
+ computePade(degree, IminusT, res);
+
+ for (; numberOfSquareRoots; --numberOfSquareRoots) {
+ compute2x2(res, std::ldexp(m_p, -numberOfSquareRoots));
+ res = res.template triangularView<Upper>() * res;
+ }
+ compute2x2(res, m_p);
+}
+
+template<typename MatrixType>
+inline int MatrixPowerAtomic<MatrixType>::getPadeDegree(float normIminusT)
+{
+ const float maxNormForPade[] = { 2.8064004e-1f /* degree = 3 */ , 4.3386528e-1f };
+ int degree = 3;
+ for (; degree <= 4; ++degree)
+ if (normIminusT <= maxNormForPade[degree - 3])
+ break;
+ return degree;
+}
+
+template<typename MatrixType>
+inline int MatrixPowerAtomic<MatrixType>::getPadeDegree(double normIminusT)
+{
+ const double maxNormForPade[] = { 1.884160592658218e-2 /* degree = 3 */ , 6.038881904059573e-2, 1.239917516308172e-1,
+ 1.999045567181744e-1, 2.789358995219730e-1 };
+ int degree = 3;
+ for (; degree <= 7; ++degree)
+ if (normIminusT <= maxNormForPade[degree - 3])
+ break;
+ return degree;
+}
+
+template<typename MatrixType>
+inline int MatrixPowerAtomic<MatrixType>::getPadeDegree(long double normIminusT)
+{
+#if LDBL_MANT_DIG == 53
+ const int maxPadeDegree = 7;
+ const double maxNormForPade[] = { 1.884160592658218e-2L /* degree = 3 */ , 6.038881904059573e-2L, 1.239917516308172e-1L,
+ 1.999045567181744e-1L, 2.789358995219730e-1L };
+#elif LDBL_MANT_DIG <= 64
+ const int maxPadeDegree = 8;
+ const double maxNormForPade[] = { 6.3854693117491799460e-3L /* degree = 3 */ , 2.6394893435456973676e-2L,
+ 6.4216043030404063729e-2L, 1.1701165502926694307e-1L, 1.7904284231268670284e-1L, 2.4471944416607995472e-1L };
+#elif LDBL_MANT_DIG <= 106
+ const int maxPadeDegree = 10;
+ const double maxNormForPade[] = { 1.0007161601787493236741409687186e-4L /* degree = 3 */ ,
+ 1.0007161601787493236741409687186e-3L, 4.7069769360887572939882574746264e-3L, 1.3220386624169159689406653101695e-2L,
+ 2.8063482381631737920612944054906e-2L, 4.9625993951953473052385361085058e-2L, 7.7367040706027886224557538328171e-2L,
+ 1.1016843812851143391275867258512e-1L };
+#else
+ const int maxPadeDegree = 10;
+ const double maxNormForPade[] = { 5.524506147036624377378713555116378e-5L /* degree = 3 */ ,
+ 6.640600568157479679823602193345995e-4L, 3.227716520106894279249709728084626e-3L,
+ 9.619593944683432960546978734646284e-3L, 2.134595382433742403911124458161147e-2L,
+ 3.908166513900489428442993794761185e-2L, 6.266780814639442865832535460550138e-2L,
+ 9.134603732914548552537150753385375e-2L };
+#endif
+ int degree = 3;
+ for (; degree <= maxPadeDegree; ++degree)
+ if (normIminusT <= maxNormForPade[degree - 3])
+ break;
+ return degree;
+}
+
+template<typename MatrixType>
+inline typename MatrixPowerAtomic<MatrixType>::ComplexScalar
+MatrixPowerAtomic<MatrixType>::computeSuperDiag(const ComplexScalar& curr, const ComplexScalar& prev, RealScalar p)
+{
+ ComplexScalar logCurr = std::log(curr);
+ ComplexScalar logPrev = std::log(prev);
+ int unwindingNumber = std::ceil((numext::imag(logCurr - logPrev) - M_PI) / (2*M_PI));
+ ComplexScalar w = numext::atanh2(curr - prev, curr + prev) + ComplexScalar(0, M_PI*unwindingNumber);
+ return RealScalar(2) * std::exp(RealScalar(0.5) * p * (logCurr + logPrev)) * std::sinh(p * w) / (curr - prev);
+}
+
+template<typename MatrixType>
+inline typename MatrixPowerAtomic<MatrixType>::RealScalar
+MatrixPowerAtomic<MatrixType>::computeSuperDiag(RealScalar curr, RealScalar prev, RealScalar p)
+{
+ RealScalar w = numext::atanh2(curr - prev, curr + prev);
+ return 2 * std::exp(p * (std::log(curr) + std::log(prev)) / 2) * std::sinh(p * w) / (curr - prev);
+}
+
+/**
+ * \ingroup MatrixFunctions_Module
+ *
+ * \brief Class for computing matrix powers.
+ *
+ * \tparam MatrixType type of the base, expected to be an instantiation
+ * of the Matrix class template.
+ *
+ * This class is capable of computing real/complex matrices raised to
+ * an arbitrary real power. Meanwhile, it saves the result of Schur
+ * decomposition if an non-integral power has even been calculated.
+ * Therefore, if you want to compute multiple (>= 2) matrix powers
+ * for the same matrix, using the class directly is more efficient than
+ * calling MatrixBase::pow().
+ *
+ * Example:
+ * \include MatrixPower_optimal.cpp
+ * Output: \verbinclude MatrixPower_optimal.out
+ */
+template<typename MatrixType>
+class MatrixPower
+{
+ private:
+ enum {
+ RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+ ColsAtCompileTime = MatrixType::ColsAtCompileTime,
+ MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
+ MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
+ };
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::RealScalar RealScalar;
+ typedef typename MatrixType::Index Index;
+
+ public:
+ /**
+ * \brief Constructor.
+ *
+ * \param[in] A the base of the matrix power.
+ *
+ * The class stores a reference to A, so it should not be changed
+ * (or destroyed) before evaluation.
+ */
+ explicit MatrixPower(const MatrixType& A) : m_A(A), m_conditionNumber(0)
+ { eigen_assert(A.rows() == A.cols()); }
+
+ /**
+ * \brief Returns the matrix power.
+ *
+ * \param[in] p exponent, a real scalar.
+ * \return The expression \f$ A^p \f$, where A is specified in the
+ * constructor.
+ */
+ const MatrixPowerRetval<MatrixType> operator()(RealScalar p)
+ { return MatrixPowerRetval<MatrixType>(*this, p); }
+
+ /**
+ * \brief Compute the matrix power.
+ *
+ * \param[in] p exponent, a real scalar.
+ * \param[out] res \f$ A^p \f$ where A is specified in the
+ * constructor.
+ */
+ template<typename ResultType>
+ void compute(ResultType& res, RealScalar p);
+
+ Index rows() const { return m_A.rows(); }
+ Index cols() const { return m_A.cols(); }
+
+ private:
+ typedef std::complex<RealScalar> ComplexScalar;
+ typedef Matrix<ComplexScalar, RowsAtCompileTime, ColsAtCompileTime, MatrixType::Options,
+ MaxRowsAtCompileTime, MaxColsAtCompileTime> ComplexMatrix;
+
+ typename MatrixType::Nested m_A;
+ MatrixType m_tmp;
+ ComplexMatrix m_T, m_U, m_fT;
+ RealScalar m_conditionNumber;
+
+ RealScalar modfAndInit(RealScalar, RealScalar*);
+
+ template<typename ResultType>
+ void computeIntPower(ResultType&, RealScalar);
+
+ template<typename ResultType>
+ void computeFracPower(ResultType&, RealScalar);
+
+ template<int Rows, int Cols, int Options, int MaxRows, int MaxCols>
+ static void revertSchur(
+ Matrix<ComplexScalar, Rows, Cols, Options, MaxRows, MaxCols>& res,
+ const ComplexMatrix& T,
+ const ComplexMatrix& U);
+
+ template<int Rows, int Cols, int Options, int MaxRows, int MaxCols>
+ static void revertSchur(
+ Matrix<RealScalar, Rows, Cols, Options, MaxRows, MaxCols>& res,
+ const ComplexMatrix& T,
+ const ComplexMatrix& U);
+};
+
+template<typename MatrixType>
+template<typename ResultType>
+void MatrixPower<MatrixType>::compute(ResultType& res, RealScalar p)
+{
+ switch (cols()) {
+ case 0:
+ break;
+ case 1:
+ res(0,0) = std::pow(m_A.coeff(0,0), p);
+ break;
+ default:
+ RealScalar intpart, x = modfAndInit(p, &intpart);
+ computeIntPower(res, intpart);
+ computeFracPower(res, x);
+ }
+}
+
+template<typename MatrixType>
+typename MatrixPower<MatrixType>::RealScalar
+MatrixPower<MatrixType>::modfAndInit(RealScalar x, RealScalar* intpart)
+{
+ typedef Array<RealScalar, RowsAtCompileTime, 1, ColMajor, MaxRowsAtCompileTime> RealArray;
+
+ *intpart = std::floor(x);
+ RealScalar res = x - *intpart;
+
+ if (!m_conditionNumber && res) {
+ const ComplexSchur<MatrixType> schurOfA(m_A);
+ m_T = schurOfA.matrixT();
+ m_U = schurOfA.matrixU();
+
+ const RealArray absTdiag = m_T.diagonal().array().abs();
+ m_conditionNumber = absTdiag.maxCoeff() / absTdiag.minCoeff();
+ }
+
+ if (res>RealScalar(0.5) && res>(1-res)*std::pow(m_conditionNumber, res)) {
+ --res;
+ ++*intpart;
+ }
+ return res;
+}
+
+template<typename MatrixType>
+template<typename ResultType>
+void MatrixPower<MatrixType>::computeIntPower(ResultType& res, RealScalar p)
+{
+ RealScalar pp = std::abs(p);
+
+ if (p<0) m_tmp = m_A.inverse();
+ else m_tmp = m_A;
+
+ res = MatrixType::Identity(rows(), cols());
+ while (pp >= 1) {
+ if (std::fmod(pp, 2) >= 1)
+ res = m_tmp * res;
+ m_tmp *= m_tmp;
+ pp /= 2;
+ }
+}
+
+template<typename MatrixType>
+template<typename ResultType>
+void MatrixPower<MatrixType>::computeFracPower(ResultType& res, RealScalar p)
+{
+ if (p) {
+ eigen_assert(m_conditionNumber);
+ MatrixPowerAtomic<ComplexMatrix>(m_T, p).compute(m_fT);
+ revertSchur(m_tmp, m_fT, m_U);
+ res = m_tmp * res;
+ }
+}
+
+template<typename MatrixType>
+template<int Rows, int Cols, int Options, int MaxRows, int MaxCols>
+inline void MatrixPower<MatrixType>::revertSchur(
+ Matrix<ComplexScalar, Rows, Cols, Options, MaxRows, MaxCols>& res,
+ const ComplexMatrix& T,
+ const ComplexMatrix& U)
+{ res.noalias() = U * (T.template triangularView<Upper>() * U.adjoint()); }
+
+template<typename MatrixType>
+template<int Rows, int Cols, int Options, int MaxRows, int MaxCols>
+inline void MatrixPower<MatrixType>::revertSchur(
+ Matrix<RealScalar, Rows, Cols, Options, MaxRows, MaxCols>& res,
+ const ComplexMatrix& T,
+ const ComplexMatrix& U)
+{ res.noalias() = (U * (T.template triangularView<Upper>() * U.adjoint())).real(); }
+
+/**
+ * \ingroup MatrixFunctions_Module
+ *
+ * \brief Proxy for the matrix power of some matrix (expression).
+ *
+ * \tparam Derived type of the base, a matrix (expression).
+ *
+ * This class holds the arguments to the matrix power until it is
+ * assigned or evaluated for some other reason (so the argument
+ * should not be changed in the meantime). It is the return type of
+ * MatrixBase::pow() and related functions and most of the
+ * time this is the only way it is used.
+ */
+template<typename Derived>
+class MatrixPowerReturnValue : public ReturnByValue< MatrixPowerReturnValue<Derived> >
+{
+ public:
+ typedef typename Derived::PlainObject PlainObject;
+ typedef typename Derived::RealScalar RealScalar;
+ typedef typename Derived::Index Index;
+
+ /**
+ * \brief Constructor.
+ *
+ * \param[in] A %Matrix (expression), the base of the matrix power.
+ * \param[in] p scalar, the exponent of the matrix power.
+ */
+ MatrixPowerReturnValue(const Derived& A, RealScalar p) : m_A(A), m_p(p)
+ { }
+
+ /**
+ * \brief Compute the matrix power.
+ *
+ * \param[out] result \f$ A^p \f$ where \p A and \p p are as in the
+ * constructor.
+ */
+ template<typename ResultType>
+ inline void evalTo(ResultType& res) const
+ { MatrixPower<PlainObject>(m_A.eval()).compute(res, m_p); }
+
+ Index rows() const { return m_A.rows(); }
+ Index cols() const { return m_A.cols(); }
+
+ private:
+ const Derived& m_A;
+ const RealScalar m_p;
+ MatrixPowerReturnValue& operator=(const MatrixPowerReturnValue&);
+};
+
+namespace internal {
+
+template<typename MatrixPowerType>
+struct traits< MatrixPowerRetval<MatrixPowerType> >
+{ typedef typename MatrixPowerType::PlainObject ReturnType; };
+
+template<typename Derived>
+struct traits< MatrixPowerReturnValue<Derived> >
+{ typedef typename Derived::PlainObject ReturnType; };
+
+}
+
+template<typename Derived>
+const MatrixPowerReturnValue<Derived> MatrixBase<Derived>::pow(const RealScalar& p) const
+{ return MatrixPowerReturnValue<Derived>(derived(), p); }
+
+} // namespace Eigen
+
+#endif // EIGEN_MATRIX_POWER
diff --git a/unsupported/Eigen/src/MatrixFunctions/MatrixSquareRoot.h b/unsupported/Eigen/src/MatrixFunctions/MatrixSquareRoot.h
index 10319fa17..b48ea9d46 100644
--- a/unsupported/Eigen/src/MatrixFunctions/MatrixSquareRoot.h
+++ b/unsupported/Eigen/src/MatrixFunctions/MatrixSquareRoot.h
@@ -60,17 +60,17 @@ class MatrixSquareRootQuasiTriangular
void computeOffDiagonalPartOfSqrt(MatrixType& sqrtT, const MatrixType& T);
void compute2x2diagonalBlock(MatrixType& sqrtT, const MatrixType& T, typename MatrixType::Index i);
void compute1x1offDiagonalBlock(MatrixType& sqrtT, const MatrixType& T,
- typename MatrixType::Index i, typename MatrixType::Index j);
+ typename MatrixType::Index i, typename MatrixType::Index j);
void compute1x2offDiagonalBlock(MatrixType& sqrtT, const MatrixType& T,
- typename MatrixType::Index i, typename MatrixType::Index j);
+ typename MatrixType::Index i, typename MatrixType::Index j);
void compute2x1offDiagonalBlock(MatrixType& sqrtT, const MatrixType& T,
- typename MatrixType::Index i, typename MatrixType::Index j);
+ typename MatrixType::Index i, typename MatrixType::Index j);
void compute2x2offDiagonalBlock(MatrixType& sqrtT, const MatrixType& T,
- typename MatrixType::Index i, typename MatrixType::Index j);
+ typename MatrixType::Index i, typename MatrixType::Index j);
template <typename SmallMatrixType>
static void solveAuxiliaryEquation(SmallMatrixType& X, const SmallMatrixType& A,
- const SmallMatrixType& B, const SmallMatrixType& C);
+ const SmallMatrixType& B, const SmallMatrixType& C);
const MatrixType& m_A;
};
@@ -79,18 +79,9 @@ template <typename MatrixType>
template <typename ResultType>
void MatrixSquareRootQuasiTriangular<MatrixType>::compute(ResultType &result)
{
- // Compute Schur decomposition of m_A
- const RealSchur<MatrixType> schurOfA(m_A);
- const MatrixType& T = schurOfA.matrixT();
- const MatrixType& U = schurOfA.matrixU();
-
- // Compute square root of T
- MatrixType sqrtT = MatrixType::Zero(m_A.rows(), m_A.rows());
- computeDiagonalPartOfSqrt(sqrtT, T);
- computeOffDiagonalPartOfSqrt(sqrtT, T);
-
- // Compute square root of m_A
- result = U * sqrtT * U.adjoint();
+ result.resize(m_A.rows(), m_A.cols());
+ computeDiagonalPartOfSqrt(result, m_A);
+ computeOffDiagonalPartOfSqrt(result, m_A);
}
// pre: T is quasi-upper-triangular and sqrtT is a zero matrix of the same size
@@ -99,11 +90,12 @@ template <typename MatrixType>
void MatrixSquareRootQuasiTriangular<MatrixType>::computeDiagonalPartOfSqrt(MatrixType& sqrtT,
const MatrixType& T)
{
+ using std::sqrt;
const Index size = m_A.rows();
for (Index i = 0; i < size; i++) {
if (i == size - 1 || T.coeff(i+1, i) == 0) {
- eigen_assert(T(i,i) > 0);
- sqrtT.coeffRef(i,i) = internal::sqrt(T.coeff(i,i));
+ eigen_assert(T(i,i) >= 0);
+ sqrtT.coeffRef(i,i) = sqrt(T.coeff(i,i));
}
else {
compute2x2diagonalBlock(sqrtT, T, i);
@@ -289,17 +281,14 @@ template <typename MatrixType>
template <typename ResultType>
void MatrixSquareRootTriangular<MatrixType>::compute(ResultType &result)
{
- // Compute Schur decomposition of m_A
- const ComplexSchur<MatrixType> schurOfA(m_A);
- const MatrixType& T = schurOfA.matrixT();
- const MatrixType& U = schurOfA.matrixU();
+ using std::sqrt;
- // Compute square root of T and store it in upper triangular part of result
+ // Compute square root of m_A and store it in upper triangular part of result
// This uses that the square root of triangular matrices can be computed directly.
result.resize(m_A.rows(), m_A.cols());
typedef typename MatrixType::Index Index;
for (Index i = 0; i < m_A.rows(); i++) {
- result.coeffRef(i,i) = internal::sqrt(T.coeff(i,i));
+ result.coeffRef(i,i) = sqrt(m_A.coeff(i,i));
}
for (Index j = 1; j < m_A.cols(); j++) {
for (Index i = j-1; i >= 0; i--) {
@@ -307,14 +296,9 @@ void MatrixSquareRootTriangular<MatrixType>::compute(ResultType &result)
// if i = j-1, then segment has length 0 so tmp = 0
Scalar tmp = (result.row(i).segment(i+1,j-i-1) * result.col(j).segment(i+1,j-i-1)).value();
// denominator may be zero if original matrix is singular
- result.coeffRef(i,j) = (T.coeff(i,j) - tmp) / (result.coeff(i,i) + result.coeff(j,j));
+ result.coeffRef(i,j) = (m_A.coeff(i,j) - tmp) / (result.coeff(i,i) + result.coeff(j,j));
}
}
-
- // Compute square root of m_A as U * result * U.adjoint()
- MatrixType tmp;
- tmp.noalias() = U * result.template triangularView<Upper>();
- result.noalias() = tmp * U.adjoint();
}
@@ -371,9 +355,8 @@ class MatrixSquareRoot<MatrixType, 0>
const MatrixType& U = schurOfA.matrixU();
// Compute square root of T
- MatrixSquareRootQuasiTriangular<MatrixType> tmp(T);
- MatrixType sqrtT = MatrixType::Zero(m_A.rows(), m_A.rows());
- tmp.compute(sqrtT);
+ MatrixType sqrtT = MatrixType::Zero(m_A.rows(), m_A.cols());
+ MatrixSquareRootQuasiTriangular<MatrixType>(T).compute(sqrtT);
// Compute square root of m_A
result = U * sqrtT * U.adjoint();
@@ -405,12 +388,11 @@ class MatrixSquareRoot<MatrixType, 1>
const MatrixType& U = schurOfA.matrixU();
// Compute square root of T
- MatrixSquareRootTriangular<MatrixType> tmp(T);
- MatrixType sqrtT = MatrixType::Zero(m_A.rows(), m_A.rows());
- tmp.compute(sqrtT);
+ MatrixType sqrtT;
+ MatrixSquareRootTriangular<MatrixType>(T).compute(sqrtT);
// Compute square root of m_A
- result = U * sqrtT * U.adjoint();
+ result = U * (sqrtT.template triangularView<Upper>() * U.adjoint());
}
private:
diff --git a/unsupported/Eigen/src/NonLinearOptimization/HybridNonLinearSolver.h b/unsupported/Eigen/src/NonLinearOptimization/HybridNonLinearSolver.h
index d9ce4eab6..b8ba6ddcb 100644
--- a/unsupported/Eigen/src/NonLinearOptimization/HybridNonLinearSolver.h
+++ b/unsupported/Eigen/src/NonLinearOptimization/HybridNonLinearSolver.h
@@ -52,7 +52,7 @@ public:
Parameters()
: factor(Scalar(100.))
, maxfev(1000)
- , xtol(internal::sqrt(NumTraits<Scalar>::epsilon()))
+ , xtol(std::sqrt(NumTraits<Scalar>::epsilon()))
, nb_of_subdiagonals(-1)
, nb_of_superdiagonals(-1)
, epsfcn(Scalar(0.)) {}
@@ -70,7 +70,7 @@ public:
HybridNonLinearSolverSpace::Status hybrj1(
FVectorType &x,
- const Scalar tol = internal::sqrt(NumTraits<Scalar>::epsilon())
+ const Scalar tol = std::sqrt(NumTraits<Scalar>::epsilon())
);
HybridNonLinearSolverSpace::Status solveInit(FVectorType &x);
@@ -79,7 +79,7 @@ public:
HybridNonLinearSolverSpace::Status hybrd1(
FVectorType &x,
- const Scalar tol = internal::sqrt(NumTraits<Scalar>::epsilon())
+ const Scalar tol = std::sqrt(NumTraits<Scalar>::epsilon())
);
HybridNonLinearSolverSpace::Status solveNumericalDiffInit(FVectorType &x);
@@ -150,7 +150,7 @@ HybridNonLinearSolver<FunctorType,Scalar>::solveInit(FVectorType &x)
fjac.resize(n, n);
if (!useExternalScaling)
diag.resize(n);
- assert( (!useExternalScaling || diag.size()==n) || "When useExternalScaling is set, the caller must provide a valid 'diag'");
+ eigen_assert( (!useExternalScaling || diag.size()==n) || "When useExternalScaling is set, the caller must provide a valid 'diag'");
/* Function Body */
nfev = 0;
@@ -185,7 +185,9 @@ template<typename FunctorType, typename Scalar>
HybridNonLinearSolverSpace::Status
HybridNonLinearSolver<FunctorType,Scalar>::solveOneStep(FVectorType &x)
{
- assert(x.size()==n); // check the caller is not cheating us
+ using std::abs;
+
+ eigen_assert(x.size()==n); // check the caller is not cheating us
Index j;
std::vector<JacobiRotation<Scalar> > v_givens(n), w_givens(n);
@@ -252,14 +254,14 @@ HybridNonLinearSolver<FunctorType,Scalar>::solveOneStep(FVectorType &x)
/* compute the scaled actual reduction. */
actred = -1.;
if (fnorm1 < fnorm) /* Computing 2nd power */
- actred = 1. - internal::abs2(fnorm1 / fnorm);
+ actred = 1. - numext::abs2(fnorm1 / fnorm);
/* compute the scaled predicted reduction. */
wa3 = R.template triangularView<Upper>()*wa1 + qtf;
temp = wa3.stableNorm();
prered = 0.;
if (temp < fnorm) /* Computing 2nd power */
- prered = 1. - internal::abs2(temp / fnorm);
+ prered = 1. - numext::abs2(temp / fnorm);
/* compute the ratio of the actual to the predicted reduction. */
ratio = 0.;
@@ -276,7 +278,7 @@ HybridNonLinearSolver<FunctorType,Scalar>::solveOneStep(FVectorType &x)
++ncsuc;
if (ratio >= Scalar(.5) || ncsuc > 1)
delta = (std::max)(delta, pnorm / Scalar(.5));
- if (internal::abs(ratio - 1.) <= Scalar(.1)) {
+ if (abs(ratio - 1.) <= Scalar(.1)) {
delta = pnorm / Scalar(.5);
}
}
@@ -388,7 +390,7 @@ HybridNonLinearSolver<FunctorType,Scalar>::solveNumericalDiffInit(FVectorType &
fvec.resize(n);
if (!useExternalScaling)
diag.resize(n);
- assert( (!useExternalScaling || diag.size()==n) || "When useExternalScaling is set, the caller must provide a valid 'diag'");
+ eigen_assert( (!useExternalScaling || diag.size()==n) || "When useExternalScaling is set, the caller must provide a valid 'diag'");
/* Function Body */
nfev = 0;
@@ -423,6 +425,9 @@ template<typename FunctorType, typename Scalar>
HybridNonLinearSolverSpace::Status
HybridNonLinearSolver<FunctorType,Scalar>::solveNumericalDiffOneStep(FVectorType &x)
{
+ using std::sqrt;
+ using std::abs;
+
assert(x.size()==n); // check the caller is not cheating us
Index j;
@@ -492,14 +497,14 @@ HybridNonLinearSolver<FunctorType,Scalar>::solveNumericalDiffOneStep(FVectorType
/* compute the scaled actual reduction. */
actred = -1.;
if (fnorm1 < fnorm) /* Computing 2nd power */
- actred = 1. - internal::abs2(fnorm1 / fnorm);
+ actred = 1. - numext::abs2(fnorm1 / fnorm);
/* compute the scaled predicted reduction. */
wa3 = R.template triangularView<Upper>()*wa1 + qtf;
temp = wa3.stableNorm();
prered = 0.;
if (temp < fnorm) /* Computing 2nd power */
- prered = 1. - internal::abs2(temp / fnorm);
+ prered = 1. - numext::abs2(temp / fnorm);
/* compute the ratio of the actual to the predicted reduction. */
ratio = 0.;
@@ -516,7 +521,7 @@ HybridNonLinearSolver<FunctorType,Scalar>::solveNumericalDiffOneStep(FVectorType
++ncsuc;
if (ratio >= Scalar(.5) || ncsuc > 1)
delta = (std::max)(delta, pnorm / Scalar(.5));
- if (internal::abs(ratio - 1.) <= Scalar(.1)) {
+ if (abs(ratio - 1.) <= Scalar(.1)) {
delta = pnorm / Scalar(.5);
}
}
diff --git a/unsupported/Eigen/src/NonLinearOptimization/LevenbergMarquardt.h b/unsupported/Eigen/src/NonLinearOptimization/LevenbergMarquardt.h
index 075faeeb0..bfeb26fc9 100644
--- a/unsupported/Eigen/src/NonLinearOptimization/LevenbergMarquardt.h
+++ b/unsupported/Eigen/src/NonLinearOptimization/LevenbergMarquardt.h
@@ -55,8 +55,8 @@ public:
Parameters()
: factor(Scalar(100.))
, maxfev(400)
- , ftol(internal::sqrt(NumTraits<Scalar>::epsilon()))
- , xtol(internal::sqrt(NumTraits<Scalar>::epsilon()))
+ , ftol(std::sqrt(NumTraits<Scalar>::epsilon()))
+ , xtol(std::sqrt(NumTraits<Scalar>::epsilon()))
, gtol(Scalar(0.))
, epsfcn(Scalar(0.)) {}
Scalar factor;
@@ -72,7 +72,7 @@ public:
LevenbergMarquardtSpace::Status lmder1(
FVectorType &x,
- const Scalar tol = internal::sqrt(NumTraits<Scalar>::epsilon())
+ const Scalar tol = std::sqrt(NumTraits<Scalar>::epsilon())
);
LevenbergMarquardtSpace::Status minimize(FVectorType &x);
@@ -83,12 +83,12 @@ public:
FunctorType &functor,
FVectorType &x,
Index *nfev,
- const Scalar tol = internal::sqrt(NumTraits<Scalar>::epsilon())
+ const Scalar tol = std::sqrt(NumTraits<Scalar>::epsilon())
);
LevenbergMarquardtSpace::Status lmstr1(
FVectorType &x,
- const Scalar tol = internal::sqrt(NumTraits<Scalar>::epsilon())
+ const Scalar tol = std::sqrt(NumTraits<Scalar>::epsilon())
);
LevenbergMarquardtSpace::Status minimizeOptimumStorage(FVectorType &x);
@@ -172,7 +172,7 @@ LevenbergMarquardt<FunctorType,Scalar>::minimizeInit(FVectorType &x)
fjac.resize(m, n);
if (!useExternalScaling)
diag.resize(n);
- assert( (!useExternalScaling || diag.size()==n) || "When useExternalScaling is set, the caller must provide a valid 'diag'");
+ eigen_assert( (!useExternalScaling || diag.size()==n) || "When useExternalScaling is set, the caller must provide a valid 'diag'");
qtf.resize(n);
/* Function Body */
@@ -206,7 +206,10 @@ template<typename FunctorType, typename Scalar>
LevenbergMarquardtSpace::Status
LevenbergMarquardt<FunctorType,Scalar>::minimizeOneStep(FVectorType &x)
{
- assert(x.size()==n); // check the caller is not cheating us
+ using std::abs;
+ using std::sqrt;
+
+ eigen_assert(x.size()==n); // check the caller is not cheating us
/* calculate the jacobian matrix. */
Index df_ret = functor.df(x, fjac);
@@ -249,7 +252,7 @@ LevenbergMarquardt<FunctorType,Scalar>::minimizeOneStep(FVectorType &x)
if (fnorm != 0.)
for (Index j = 0; j < n; ++j)
if (wa2[permutation.indices()[j]] != 0.)
- gnorm = (std::max)(gnorm, internal::abs( fjac.col(j).head(j+1).dot(qtf.head(j+1)/fnorm) / wa2[permutation.indices()[j]]));
+ gnorm = (std::max)(gnorm, abs( fjac.col(j).head(j+1).dot(qtf.head(j+1)/fnorm) / wa2[permutation.indices()[j]]));
/* test for convergence of the gradient norm. */
if (gnorm <= parameters.gtol)
@@ -282,13 +285,13 @@ LevenbergMarquardt<FunctorType,Scalar>::minimizeOneStep(FVectorType &x)
/* compute the scaled actual reduction. */
actred = -1.;
if (Scalar(.1) * fnorm1 < fnorm)
- actred = 1. - internal::abs2(fnorm1 / fnorm);
+ actred = 1. - numext::abs2(fnorm1 / fnorm);
/* compute the scaled predicted reduction and */
/* the scaled directional derivative. */
wa3 = fjac.template triangularView<Upper>() * (qrfac.colsPermutation().inverse() *wa1);
- temp1 = internal::abs2(wa3.stableNorm() / fnorm);
- temp2 = internal::abs2(internal::sqrt(par) * pnorm / fnorm);
+ temp1 = numext::abs2(wa3.stableNorm() / fnorm);
+ temp2 = numext::abs2(sqrt(par) * pnorm / fnorm);
prered = temp1 + temp2 / Scalar(.5);
dirder = -(temp1 + temp2);
@@ -326,9 +329,9 @@ LevenbergMarquardt<FunctorType,Scalar>::minimizeOneStep(FVectorType &x)
}
/* tests for convergence. */
- if (internal::abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1. && delta <= parameters.xtol * xnorm)
+ if (abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1. && delta <= parameters.xtol * xnorm)
return LevenbergMarquardtSpace::RelativeErrorAndReductionTooSmall;
- if (internal::abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1.)
+ if (abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1.)
return LevenbergMarquardtSpace::RelativeReductionTooSmall;
if (delta <= parameters.xtol * xnorm)
return LevenbergMarquardtSpace::RelativeErrorTooSmall;
@@ -336,7 +339,7 @@ LevenbergMarquardt<FunctorType,Scalar>::minimizeOneStep(FVectorType &x)
/* tests for termination and stringent tolerances. */
if (nfev >= parameters.maxfev)
return LevenbergMarquardtSpace::TooManyFunctionEvaluation;
- if (internal::abs(actred) <= NumTraits<Scalar>::epsilon() && prered <= NumTraits<Scalar>::epsilon() && Scalar(.5) * ratio <= 1.)
+ if (abs(actred) <= NumTraits<Scalar>::epsilon() && prered <= NumTraits<Scalar>::epsilon() && Scalar(.5) * ratio <= 1.)
return LevenbergMarquardtSpace::FtolTooSmall;
if (delta <= NumTraits<Scalar>::epsilon() * xnorm)
return LevenbergMarquardtSpace::XtolTooSmall;
@@ -388,7 +391,7 @@ LevenbergMarquardt<FunctorType,Scalar>::minimizeOptimumStorageInit(FVectorType
fjac.resize(n, n);
if (!useExternalScaling)
diag.resize(n);
- assert( (!useExternalScaling || diag.size()==n) || "When useExternalScaling is set, the caller must provide a valid 'diag'");
+ eigen_assert( (!useExternalScaling || diag.size()==n) || "When useExternalScaling is set, the caller must provide a valid 'diag'");
qtf.resize(n);
/* Function Body */
@@ -423,7 +426,10 @@ template<typename FunctorType, typename Scalar>
LevenbergMarquardtSpace::Status
LevenbergMarquardt<FunctorType,Scalar>::minimizeOptimumStorageOneStep(FVectorType &x)
{
- assert(x.size()==n); // check the caller is not cheating us
+ using std::abs;
+ using std::sqrt;
+
+ eigen_assert(x.size()==n); // check the caller is not cheating us
Index i, j;
bool sing;
@@ -496,7 +502,7 @@ LevenbergMarquardt<FunctorType,Scalar>::minimizeOptimumStorageOneStep(FVectorTyp
if (fnorm != 0.)
for (j = 0; j < n; ++j)
if (wa2[permutation.indices()[j]] != 0.)
- gnorm = (std::max)(gnorm, internal::abs( fjac.col(j).head(j+1).dot(qtf.head(j+1)/fnorm) / wa2[permutation.indices()[j]]));
+ gnorm = (std::max)(gnorm, abs( fjac.col(j).head(j+1).dot(qtf.head(j+1)/fnorm) / wa2[permutation.indices()[j]]));
/* test for convergence of the gradient norm. */
if (gnorm <= parameters.gtol)
@@ -529,13 +535,13 @@ LevenbergMarquardt<FunctorType,Scalar>::minimizeOptimumStorageOneStep(FVectorTyp
/* compute the scaled actual reduction. */
actred = -1.;
if (Scalar(.1) * fnorm1 < fnorm)
- actred = 1. - internal::abs2(fnorm1 / fnorm);
+ actred = 1. - numext::abs2(fnorm1 / fnorm);
/* compute the scaled predicted reduction and */
/* the scaled directional derivative. */
wa3 = fjac.topLeftCorner(n,n).template triangularView<Upper>() * (permutation.inverse() * wa1);
- temp1 = internal::abs2(wa3.stableNorm() / fnorm);
- temp2 = internal::abs2(internal::sqrt(par) * pnorm / fnorm);
+ temp1 = numext::abs2(wa3.stableNorm() / fnorm);
+ temp2 = numext::abs2(sqrt(par) * pnorm / fnorm);
prered = temp1 + temp2 / Scalar(.5);
dirder = -(temp1 + temp2);
@@ -573,9 +579,9 @@ LevenbergMarquardt<FunctorType,Scalar>::minimizeOptimumStorageOneStep(FVectorTyp
}
/* tests for convergence. */
- if (internal::abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1. && delta <= parameters.xtol * xnorm)
+ if (abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1. && delta <= parameters.xtol * xnorm)
return LevenbergMarquardtSpace::RelativeErrorAndReductionTooSmall;
- if (internal::abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1.)
+ if (abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1.)
return LevenbergMarquardtSpace::RelativeReductionTooSmall;
if (delta <= parameters.xtol * xnorm)
return LevenbergMarquardtSpace::RelativeErrorTooSmall;
@@ -583,7 +589,7 @@ LevenbergMarquardt<FunctorType,Scalar>::minimizeOptimumStorageOneStep(FVectorTyp
/* tests for termination and stringent tolerances. */
if (nfev >= parameters.maxfev)
return LevenbergMarquardtSpace::TooManyFunctionEvaluation;
- if (internal::abs(actred) <= NumTraits<Scalar>::epsilon() && prered <= NumTraits<Scalar>::epsilon() && Scalar(.5) * ratio <= 1.)
+ if (abs(actred) <= NumTraits<Scalar>::epsilon() && prered <= NumTraits<Scalar>::epsilon() && Scalar(.5) * ratio <= 1.)
return LevenbergMarquardtSpace::FtolTooSmall;
if (delta <= NumTraits<Scalar>::epsilon() * xnorm)
return LevenbergMarquardtSpace::XtolTooSmall;
diff --git a/unsupported/Eigen/src/NonLinearOptimization/chkder.h b/unsupported/Eigen/src/NonLinearOptimization/chkder.h
index ad37c5029..db8ff7d6e 100644
--- a/unsupported/Eigen/src/NonLinearOptimization/chkder.h
+++ b/unsupported/Eigen/src/NonLinearOptimization/chkder.h
@@ -16,6 +16,10 @@ void chkder(
Matrix< Scalar, Dynamic, 1 > &err
)
{
+ using std::sqrt;
+ using std::abs;
+ using std::log;
+
typedef DenseIndex Index;
const Scalar eps = sqrt(NumTraits<Scalar>::epsilon());
diff --git a/unsupported/Eigen/src/NonLinearOptimization/covar.h b/unsupported/Eigen/src/NonLinearOptimization/covar.h
index c73a09645..68260d191 100644
--- a/unsupported/Eigen/src/NonLinearOptimization/covar.h
+++ b/unsupported/Eigen/src/NonLinearOptimization/covar.h
@@ -6,8 +6,9 @@ template <typename Scalar>
void covar(
Matrix< Scalar, Dynamic, Dynamic > &r,
const VectorXi &ipvt,
- Scalar tol = sqrt(NumTraits<Scalar>::epsilon()) )
+ Scalar tol = std::sqrt(NumTraits<Scalar>::epsilon()) )
{
+ using std::abs;
typedef DenseIndex Index;
/* Local variables */
@@ -19,7 +20,7 @@ void covar(
const Index n = r.cols();
const Scalar tolr = tol * abs(r(0,0));
Matrix< Scalar, Dynamic, 1 > wa(n);
- assert(ipvt.size()==n);
+ eigen_assert(ipvt.size()==n);
/* form the inverse of r in the full upper triangle of r. */
l = -1;
diff --git a/unsupported/Eigen/src/NonLinearOptimization/dogleg.h b/unsupported/Eigen/src/NonLinearOptimization/dogleg.h
index 4fbc98bfc..80c5d277b 100644
--- a/unsupported/Eigen/src/NonLinearOptimization/dogleg.h
+++ b/unsupported/Eigen/src/NonLinearOptimization/dogleg.h
@@ -10,6 +10,9 @@ void dogleg(
Scalar delta,
Matrix< Scalar, Dynamic, 1 > &x)
{
+ using std::abs;
+ using std::sqrt;
+
typedef DenseIndex Index;
/* Local variables */
@@ -21,9 +24,9 @@ void dogleg(
/* Function Body */
const Scalar epsmch = NumTraits<Scalar>::epsilon();
const Index n = qrfac.cols();
- assert(n==qtb.size());
- assert(n==x.size());
- assert(n==diag.size());
+ eigen_assert(n==qtb.size());
+ eigen_assert(n==x.size());
+ eigen_assert(n==diag.size());
Matrix< Scalar, Dynamic, 1 > wa1(n), wa2(n);
/* first, calculate the gauss-newton direction. */
@@ -89,8 +92,8 @@ void dogleg(
/* at which the quadratic is minimized. */
bnorm = qtb.stableNorm();
temp = bnorm / gnorm * (bnorm / qnorm) * (sgnorm / delta);
- temp = temp - delta / qnorm * abs2(sgnorm / delta) + sqrt(abs2(temp - delta / qnorm) + (1.-abs2(delta / qnorm)) * (1.-abs2(sgnorm / delta)));
- alpha = delta / qnorm * (1. - abs2(sgnorm / delta)) / temp;
+ temp = temp - delta / qnorm * numext::abs2(sgnorm / delta) + sqrt(numext::abs2(temp - delta / qnorm) + (1.-numext::abs2(delta / qnorm)) * (1.-numext::abs2(sgnorm / delta)));
+ alpha = delta / qnorm * (1. - numext::abs2(sgnorm / delta)) / temp;
algo_end:
/* form appropriate convex combination of the gauss-newton */
diff --git a/unsupported/Eigen/src/NonLinearOptimization/fdjac1.h b/unsupported/Eigen/src/NonLinearOptimization/fdjac1.h
index 1cabe69ae..bb7cf267b 100644
--- a/unsupported/Eigen/src/NonLinearOptimization/fdjac1.h
+++ b/unsupported/Eigen/src/NonLinearOptimization/fdjac1.h
@@ -11,6 +11,9 @@ DenseIndex fdjac1(
DenseIndex ml, DenseIndex mu,
Scalar epsfcn)
{
+ using std::sqrt;
+ using std::abs;
+
typedef DenseIndex Index;
/* Local variables */
@@ -24,7 +27,7 @@ DenseIndex fdjac1(
/* Function Body */
const Scalar epsmch = NumTraits<Scalar>::epsilon();
const Index n = x.size();
- assert(fvec.size()==n);
+ eigen_assert(fvec.size()==n);
Matrix< Scalar, Dynamic, 1 > wa1(n);
Matrix< Scalar, Dynamic, 1 > wa2(n);
diff --git a/unsupported/Eigen/src/NonLinearOptimization/lmpar.h b/unsupported/Eigen/src/NonLinearOptimization/lmpar.h
index cc1ca530f..4c17d4cdf 100644
--- a/unsupported/Eigen/src/NonLinearOptimization/lmpar.h
+++ b/unsupported/Eigen/src/NonLinearOptimization/lmpar.h
@@ -12,6 +12,8 @@ void lmpar(
Scalar &par,
Matrix< Scalar, Dynamic, 1 > &x)
{
+ using std::abs;
+ using std::sqrt;
typedef DenseIndex Index;
/* Local variables */
@@ -25,11 +27,11 @@ void lmpar(
/* Function Body */
- const Scalar dwarf = std::numeric_limits<Scalar>::min();
+ const Scalar dwarf = (std::numeric_limits<Scalar>::min)();
const Index n = r.cols();
- assert(n==diag.size());
- assert(n==qtb.size());
- assert(n==x.size());
+ eigen_assert(n==diag.size());
+ eigen_assert(n==qtb.size());
+ eigen_assert(n==x.size());
Matrix< Scalar, Dynamic, 1 > wa1, wa2;
@@ -168,6 +170,8 @@ void lmpar2(
Matrix< Scalar, Dynamic, 1 > &x)
{
+ using std::sqrt;
+ using std::abs;
typedef DenseIndex Index;
/* Local variables */
@@ -181,10 +185,10 @@ void lmpar2(
/* Function Body */
- const Scalar dwarf = std::numeric_limits<Scalar>::min();
+ const Scalar dwarf = (std::numeric_limits<Scalar>::min)();
const Index n = qr.matrixQR().cols();
- assert(n==diag.size());
- assert(n==qtb.size());
+ eigen_assert(n==diag.size());
+ eigen_assert(n==qtb.size());
Matrix< Scalar, Dynamic, 1 > wa1, wa2;
diff --git a/unsupported/Eigen/src/NonLinearOptimization/r1updt.h b/unsupported/Eigen/src/NonLinearOptimization/r1updt.h
index 55fae5ae8..f28766061 100644
--- a/unsupported/Eigen/src/NonLinearOptimization/r1updt.h
+++ b/unsupported/Eigen/src/NonLinearOptimization/r1updt.h
@@ -24,10 +24,10 @@ void r1updt(
// r1updt had a broader usecase, but we dont use it here. And, more
// importantly, we can not test it.
- assert(m==n);
- assert(u.size()==m);
- assert(v.size()==n);
- assert(w.size()==n);
+ eigen_assert(m==n);
+ eigen_assert(u.size()==m);
+ eigen_assert(v.size()==n);
+ eigen_assert(w.size()==n);
/* move the nontrivial part of the last column of s into w. */
w[n-1] = s(n-1,n-1);
diff --git a/unsupported/Eigen/src/NonLinearOptimization/rwupdt.h b/unsupported/Eigen/src/NonLinearOptimization/rwupdt.h
index 9ce079e22..6ebf8563f 100644
--- a/unsupported/Eigen/src/NonLinearOptimization/rwupdt.h
+++ b/unsupported/Eigen/src/NonLinearOptimization/rwupdt.h
@@ -12,7 +12,7 @@ void rwupdt(
typedef DenseIndex Index;
const Index n = r.cols();
- assert(r.rows()>=n);
+ eigen_assert(r.rows()>=n);
std::vector<JacobiRotation<Scalar> > givens(n);
/* Local variables */
diff --git a/unsupported/Eigen/src/NumericalDiff/NumericalDiff.h b/unsupported/Eigen/src/NumericalDiff/NumericalDiff.h
index d848cb407..ea5d8bc27 100644
--- a/unsupported/Eigen/src/NumericalDiff/NumericalDiff.h
+++ b/unsupported/Eigen/src/NumericalDiff/NumericalDiff.h
@@ -63,11 +63,13 @@ public:
*/
int df(const InputType& _x, JacobianType &jac) const
{
+ using std::sqrt;
+ using std::abs;
/* Local variables */
Scalar h;
int nfev=0;
const typename InputType::Index n = _x.size();
- const Scalar eps = internal::sqrt(((std::max)(epsfcn,NumTraits<Scalar>::epsilon() )));
+ const Scalar eps = sqrt(((std::max)(epsfcn,NumTraits<Scalar>::epsilon() )));
ValueType val1, val2;
InputType x = _x;
// TODO : we should do this only if the size is not already known
@@ -84,12 +86,12 @@ public:
// do nothing
break;
default:
- assert(false);
+ eigen_assert(false);
};
// Function Body
for (int j = 0; j < n; ++j) {
- h = eps * internal::abs(x[j]);
+ h = eps * abs(x[j]);
if (h == 0.) {
h = eps;
}
@@ -110,7 +112,7 @@ public:
jac.col(j) = (val2-val1)/(2*h);
break;
default:
- assert(false);
+ eigen_assert(false);
};
}
return nfev;
diff --git a/unsupported/Eigen/src/Polynomials/Companion.h b/unsupported/Eigen/src/Polynomials/Companion.h
index 4badd9d58..b515c2920 100644
--- a/unsupported/Eigen/src/Polynomials/Companion.h
+++ b/unsupported/Eigen/src/Polynomials/Companion.h
@@ -210,6 +210,7 @@ bool companion<_Scalar,_Deg>::balancedR( Scalar colNorm, Scalar rowNorm,
template< typename _Scalar, int _Deg >
void companion<_Scalar,_Deg>::balance()
{
+ using std::abs;
EIGEN_STATIC_ASSERT( Deg == Dynamic || 1 < Deg, YOU_MADE_A_PROGRAMMING_MISTAKE );
const Index deg = m_monic.size();
const Index deg_1 = deg-1;
diff --git a/unsupported/Eigen/src/Polynomials/PolynomialSolver.h b/unsupported/Eigen/src/Polynomials/PolynomialSolver.h
index 70b873dbc..cd5c04bbf 100644
--- a/unsupported/Eigen/src/Polynomials/PolynomialSolver.h
+++ b/unsupported/Eigen/src/Polynomials/PolynomialSolver.h
@@ -69,10 +69,11 @@ class PolynomialSolverBase
inline void realRoots( Stl_back_insertion_sequence& bi_seq,
const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision() ) const
{
+ using std::abs;
bi_seq.clear();
for(Index i=0; i<m_roots.size(); ++i )
{
- if( internal::abs( m_roots[i].imag() ) < absImaginaryThreshold ){
+ if( abs( m_roots[i].imag() ) < absImaginaryThreshold ){
bi_seq.push_back( m_roots[i].real() ); }
}
}
@@ -82,10 +83,10 @@ class PolynomialSolverBase
inline const RootType& selectComplexRoot_withRespectToNorm( squaredNormBinaryPredicate& pred ) const
{
Index res=0;
- RealScalar norm2 = internal::abs2( m_roots[0] );
+ RealScalar norm2 = numext::abs2( m_roots[0] );
for( Index i=1; i<m_roots.size(); ++i )
{
- const RealScalar currNorm2 = internal::abs2( m_roots[i] );
+ const RealScalar currNorm2 = numext::abs2( m_roots[i] );
if( pred( currNorm2, norm2 ) ){
res=i; norm2=currNorm2; }
}
@@ -118,13 +119,14 @@ class PolynomialSolverBase
bool& hasArealRoot,
const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision() ) const
{
+ using std::abs;
hasArealRoot = false;
Index res=0;
RealScalar abs2(0);
for( Index i=0; i<m_roots.size(); ++i )
{
- if( internal::abs( m_roots[i].imag() ) < absImaginaryThreshold )
+ if( abs( m_roots[i].imag() ) < absImaginaryThreshold )
{
if( !hasArealRoot )
{
@@ -144,11 +146,11 @@ class PolynomialSolverBase
}
else
{
- if( internal::abs( m_roots[i].imag() ) < internal::abs( m_roots[res].imag() ) ){
+ if( abs( m_roots[i].imag() ) < abs( m_roots[res].imag() ) ){
res = i; }
}
}
- return internal::real_ref(m_roots[res]);
+ return numext::real_ref(m_roots[res]);
}
@@ -158,13 +160,14 @@ class PolynomialSolverBase
bool& hasArealRoot,
const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision() ) const
{
+ using std::abs;
hasArealRoot = false;
Index res=0;
RealScalar val(0);
for( Index i=0; i<m_roots.size(); ++i )
{
- if( internal::abs( m_roots[i].imag() ) < absImaginaryThreshold )
+ if( abs( m_roots[i].imag() ) < absImaginaryThreshold )
{
if( !hasArealRoot )
{
@@ -184,11 +187,11 @@ class PolynomialSolverBase
}
else
{
- if( internal::abs( m_roots[i].imag() ) < internal::abs( m_roots[res].imag() ) ){
+ if( abs( m_roots[i].imag() ) < abs( m_roots[res].imag() ) ){
res = i; }
}
}
- return internal::real_ref(m_roots[res]);
+ return numext::real_ref(m_roots[res]);
}
public:
@@ -341,7 +344,7 @@ class PolynomialSolver : public PolynomialSolverBase<_Scalar,_Deg>
template< typename OtherPolynomial >
void compute( const OtherPolynomial& poly )
{
- assert( Scalar(0) != poly[poly.size()-1] );
+ eigen_assert( Scalar(0) != poly[poly.size()-1] );
internal::companion<Scalar,_Deg> companion( poly );
companion.balance();
m_eigenSolver.compute( companion.denseMatrix() );
@@ -373,7 +376,7 @@ class PolynomialSolver<_Scalar,1> : public PolynomialSolverBase<_Scalar,1>
template< typename OtherPolynomial >
void compute( const OtherPolynomial& poly )
{
- assert( Scalar(0) != poly[poly.size()-1] );
+ eigen_assert( Scalar(0) != poly[poly.size()-1] );
m_roots[0] = -poly[0]/poly[poly.size()-1];
}
diff --git a/unsupported/Eigen/src/Polynomials/PolynomialUtils.h b/unsupported/Eigen/src/Polynomials/PolynomialUtils.h
index c23204c65..2bb8bc84a 100644
--- a/unsupported/Eigen/src/Polynomials/PolynomialUtils.h
+++ b/unsupported/Eigen/src/Polynomials/PolynomialUtils.h
@@ -47,7 +47,7 @@ T poly_eval( const Polynomials& poly, const T& x )
{
typedef typename NumTraits<T>::Real Real;
- if( internal::abs2( x ) <= Real(1) ){
+ if( numext::abs2( x ) <= Real(1) ){
return poly_eval_horner( poly, x ); }
else
{
@@ -74,15 +74,16 @@ template <typename Polynomial>
inline
typename NumTraits<typename Polynomial::Scalar>::Real cauchy_max_bound( const Polynomial& poly )
{
+ using std::abs;
typedef typename Polynomial::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real Real;
- assert( Scalar(0) != poly[poly.size()-1] );
+ eigen_assert( Scalar(0) != poly[poly.size()-1] );
const Scalar inv_leading_coeff = Scalar(1)/poly[poly.size()-1];
Real cb(0);
for( DenseIndex i=0; i<poly.size()-1; ++i ){
- cb += internal::abs(poly[i]*inv_leading_coeff); }
+ cb += abs(poly[i]*inv_leading_coeff); }
return cb + Real(1);
}
@@ -96,6 +97,7 @@ template <typename Polynomial>
inline
typename NumTraits<typename Polynomial::Scalar>::Real cauchy_min_bound( const Polynomial& poly )
{
+ using std::abs;
typedef typename Polynomial::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real Real;
@@ -107,7 +109,7 @@ typename NumTraits<typename Polynomial::Scalar>::Real cauchy_min_bound( const Po
const Scalar inv_min_coeff = Scalar(1)/poly[i];
Real cb(1);
for( DenseIndex j=i+1; j<poly.size(); ++j ){
- cb += internal::abs(poly[j]*inv_min_coeff); }
+ cb += abs(poly[j]*inv_min_coeff); }
return Real(1)/cb;
}
diff --git a/unsupported/Eigen/src/SVD/BDCSVD.h b/unsupported/Eigen/src/SVD/BDCSVD.h
new file mode 100644
index 000000000..11d4882e4
--- /dev/null
+++ b/unsupported/Eigen/src/SVD/BDCSVD.h
@@ -0,0 +1,748 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// We used the "A Divide-And-Conquer Algorithm for the Bidiagonal SVD"
+// research report written by Ming Gu and Stanley C.Eisenstat
+// The code variable names correspond to the names they used in their
+// report
+//
+// Copyright (C) 2013 Gauthier Brun <brun.gauthier@gmail.com>
+// Copyright (C) 2013 Nicolas Carre <nicolas.carre@ensimag.fr>
+// Copyright (C) 2013 Jean Ceccato <jean.ceccato@ensimag.fr>
+// Copyright (C) 2013 Pierre Zoppitelli <pierre.zoppitelli@ensimag.fr>
+//
+// 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_BDCSVD_H
+#define EIGEN_BDCSVD_H
+
+#define EPSILON 0.0000000000000001
+
+#define ALGOSWAP 32
+
+namespace Eigen {
+/** \ingroup SVD_Module
+ *
+ *
+ * \class BDCSVD
+ *
+ * \brief class Bidiagonal Divide and Conquer SVD
+ *
+ * \param MatrixType the type of the matrix of which we are computing the SVD decomposition
+ * We plan to have a very similar interface to JacobiSVD on this class.
+ * It should be used to speed up the calcul of SVD for big matrices.
+ */
+template<typename _MatrixType>
+class BDCSVD : public SVDBase<_MatrixType>
+{
+ typedef SVDBase<_MatrixType> Base;
+
+public:
+ using Base::rows;
+ using Base::cols;
+
+ typedef _MatrixType MatrixType;
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
+ typedef typename MatrixType::Index Index;
+ enum {
+ RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+ ColsAtCompileTime = MatrixType::ColsAtCompileTime,
+ DiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_DYNAMIC(RowsAtCompileTime, ColsAtCompileTime),
+ MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
+ MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
+ MaxDiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(MaxRowsAtCompileTime, MaxColsAtCompileTime),
+ MatrixOptions = MatrixType::Options
+ };
+
+ typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime,
+ MatrixOptions, MaxRowsAtCompileTime, MaxRowsAtCompileTime>
+ MatrixUType;
+ typedef Matrix<Scalar, ColsAtCompileTime, ColsAtCompileTime,
+ MatrixOptions, MaxColsAtCompileTime, MaxColsAtCompileTime>
+ MatrixVType;
+ typedef typename internal::plain_diag_type<MatrixType, RealScalar>::type SingularValuesType;
+ typedef typename internal::plain_row_type<MatrixType>::type RowType;
+ typedef typename internal::plain_col_type<MatrixType>::type ColType;
+ typedef Matrix<Scalar, Dynamic, Dynamic> MatrixX;
+ typedef Matrix<RealScalar, Dynamic, Dynamic> MatrixXr;
+ typedef Matrix<RealScalar, Dynamic, 1> VectorType;
+
+ /** \brief Default Constructor.
+ *
+ * The default constructor is useful in cases in which the user intends to
+ * perform decompositions via BDCSVD::compute(const MatrixType&).
+ */
+ BDCSVD()
+ : SVDBase<_MatrixType>::SVDBase(),
+ algoswap(ALGOSWAP)
+ {}
+
+
+ /** \brief Default Constructor with memory preallocation
+ *
+ * Like the default constructor but with preallocation of the internal data
+ * according to the specified problem size.
+ * \sa BDCSVD()
+ */
+ BDCSVD(Index rows, Index cols, unsigned int computationOptions = 0)
+ : SVDBase<_MatrixType>::SVDBase(),
+ algoswap(ALGOSWAP)
+ {
+ allocate(rows, cols, computationOptions);
+ }
+
+ /** \brief Constructor performing the decomposition of given matrix.
+ *
+ * \param matrix the matrix to decompose
+ * \param computationOptions optional parameter allowing to specify if you want full or thin U or V unitaries to be computed.
+ * By default, none is computed. This is a bit - field, the possible bits are #ComputeFullU, #ComputeThinU,
+ * #ComputeFullV, #ComputeThinV.
+ *
+ * Thin unitaries are only available if your matrix type has a Dynamic number of columns (for example MatrixXf). They also are not
+ * available with the (non - default) FullPivHouseholderQR preconditioner.
+ */
+ BDCSVD(const MatrixType& matrix, unsigned int computationOptions = 0)
+ : SVDBase<_MatrixType>::SVDBase(),
+ algoswap(ALGOSWAP)
+ {
+ compute(matrix, computationOptions);
+ }
+
+ ~BDCSVD()
+ {
+ }
+ /** \brief Method performing the decomposition of given matrix using custom options.
+ *
+ * \param matrix the matrix to decompose
+ * \param computationOptions optional parameter allowing to specify if you want full or thin U or V unitaries to be computed.
+ * By default, none is computed. This is a bit - field, the possible bits are #ComputeFullU, #ComputeThinU,
+ * #ComputeFullV, #ComputeThinV.
+ *
+ * Thin unitaries are only available if your matrix type has a Dynamic number of columns (for example MatrixXf). They also are not
+ * available with the (non - default) FullPivHouseholderQR preconditioner.
+ */
+ SVDBase<MatrixType>& compute(const MatrixType& matrix, unsigned int computationOptions);
+
+ /** \brief Method performing the decomposition of given matrix using current options.
+ *
+ * \param matrix the matrix to decompose
+ *
+ * This method uses the current \a computationOptions, as already passed to the constructor or to compute(const MatrixType&, unsigned int).
+ */
+ SVDBase<MatrixType>& compute(const MatrixType& matrix)
+ {
+ return compute(matrix, this->m_computationOptions);
+ }
+
+ void setSwitchSize(int s)
+ {
+ eigen_assert(s>3 && "BDCSVD the size of the algo switch has to be greater than 4");
+ algoswap = s;
+ }
+
+
+ /** \returns a (least squares) solution of \f$ A x = b \f$ using the current SVD decomposition of A.
+ *
+ * \param b the right - hand - side of the equation to solve.
+ *
+ * \note Solving requires both U and V to be computed. Thin U and V are enough, there is no need for full U or V.
+ *
+ * \note SVD solving is implicitly least - squares. Thus, this method serves both purposes of exact solving and least - squares solving.
+ * In other words, the returned solution is guaranteed to minimize the Euclidean norm \f$ \Vert A x - b \Vert \f$.
+ */
+ template<typename Rhs>
+ inline const internal::solve_retval<BDCSVD, Rhs>
+ solve(const MatrixBase<Rhs>& b) const
+ {
+ eigen_assert(this->m_isInitialized && "BDCSVD is not initialized.");
+ eigen_assert(SVDBase<_MatrixType>::computeU() && SVDBase<_MatrixType>::computeV() &&
+ "BDCSVD::solve() requires both unitaries U and V to be computed (thin unitaries suffice).");
+ return internal::solve_retval<BDCSVD, Rhs>(*this, b.derived());
+ }
+
+
+ const MatrixUType& matrixU() const
+ {
+ eigen_assert(this->m_isInitialized && "SVD is not initialized.");
+ if (isTranspose){
+ eigen_assert(this->computeV() && "This SVD decomposition didn't compute U. Did you ask for it?");
+ return this->m_matrixV;
+ }
+ else
+ {
+ eigen_assert(this->computeU() && "This SVD decomposition didn't compute U. Did you ask for it?");
+ return this->m_matrixU;
+ }
+
+ }
+
+
+ const MatrixVType& matrixV() const
+ {
+ eigen_assert(this->m_isInitialized && "SVD is not initialized.");
+ if (isTranspose){
+ eigen_assert(this->computeU() && "This SVD decomposition didn't compute V. Did you ask for it?");
+ return this->m_matrixU;
+ }
+ else
+ {
+ eigen_assert(this->computeV() && "This SVD decomposition didn't compute V. Did you ask for it?");
+ return this->m_matrixV;
+ }
+ }
+
+private:
+ void allocate(Index rows, Index cols, unsigned int computationOptions);
+ void divide (Index firstCol, Index lastCol, Index firstRowW,
+ Index firstColW, Index shift);
+ void deflation43(Index firstCol, Index shift, Index i, Index size);
+ void deflation44(Index firstColu , Index firstColm, Index firstRowW, Index firstColW, Index i, Index j, Index size);
+ void deflation(Index firstCol, Index lastCol, Index k, Index firstRowW, Index firstColW, Index shift);
+ void copyUV(MatrixXr naiveU, MatrixXr naiveV, MatrixX householderU, MatrixX houseHolderV);
+
+protected:
+ MatrixXr m_naiveU, m_naiveV;
+ MatrixXr m_computed;
+ Index nRec;
+ int algoswap;
+ bool isTranspose, compU, compV;
+
+}; //end class BDCSVD
+
+
+// Methode to allocate ans initialize matrix and attributs
+template<typename MatrixType>
+void BDCSVD<MatrixType>::allocate(Index rows, Index cols, unsigned int computationOptions)
+{
+ isTranspose = (cols > rows);
+ if (SVDBase<MatrixType>::allocate(rows, cols, computationOptions)) return;
+ m_computed = MatrixXr::Zero(this->m_diagSize + 1, this->m_diagSize );
+ if (isTranspose){
+ compU = this->computeU();
+ compV = this->computeV();
+ }
+ else
+ {
+ compV = this->computeU();
+ compU = this->computeV();
+ }
+ if (compU) m_naiveU = MatrixXr::Zero(this->m_diagSize + 1, this->m_diagSize + 1 );
+ else m_naiveU = MatrixXr::Zero(2, this->m_diagSize + 1 );
+
+ if (compV) m_naiveV = MatrixXr::Zero(this->m_diagSize, this->m_diagSize);
+
+
+ //should be changed for a cleaner implementation
+ if (isTranspose){
+ bool aux;
+ if (this->computeU()||this->computeV()){
+ aux = this->m_computeFullU;
+ this->m_computeFullU = this->m_computeFullV;
+ this->m_computeFullV = aux;
+ aux = this->m_computeThinU;
+ this->m_computeThinU = this->m_computeThinV;
+ this->m_computeThinV = aux;
+ }
+ }
+}// end allocate
+
+// Methode which compute the BDCSVD for the int
+template<>
+SVDBase<Matrix<int, Dynamic, Dynamic> >&
+BDCSVD<Matrix<int, Dynamic, Dynamic> >::compute(const MatrixType& matrix, unsigned int computationOptions) {
+ allocate(matrix.rows(), matrix.cols(), computationOptions);
+ this->m_nonzeroSingularValues = 0;
+ m_computed = Matrix<int, Dynamic, Dynamic>::Zero(rows(), cols());
+ for (int i=0; i<this->m_diagSize; i++) {
+ this->m_singularValues.coeffRef(i) = 0;
+ }
+ if (this->m_computeFullU) this->m_matrixU = Matrix<int, Dynamic, Dynamic>::Zero(rows(), rows());
+ if (this->m_computeFullV) this->m_matrixV = Matrix<int, Dynamic, Dynamic>::Zero(cols(), cols());
+ this->m_isInitialized = true;
+ return *this;
+}
+
+
+// Methode which compute the BDCSVD
+template<typename MatrixType>
+SVDBase<MatrixType>&
+BDCSVD<MatrixType>::compute(const MatrixType& matrix, unsigned int computationOptions)
+{
+ allocate(matrix.rows(), matrix.cols(), computationOptions);
+ using std::abs;
+
+ //**** step 1 Bidiagonalization isTranspose = (matrix.cols()>matrix.rows()) ;
+ MatrixType copy;
+ if (isTranspose) copy = matrix.adjoint();
+ else copy = matrix;
+
+ internal::UpperBidiagonalization<MatrixX > bid(copy);
+
+ //**** step 2 Divide
+ // this is ugly and has to be redone (care of complex cast)
+ MatrixXr temp;
+ temp = bid.bidiagonal().toDenseMatrix().transpose();
+ m_computed.setZero();
+ for (int i=0; i<this->m_diagSize - 1; i++) {
+ m_computed(i, i) = temp(i, i);
+ m_computed(i + 1, i) = temp(i + 1, i);
+ }
+ m_computed(this->m_diagSize - 1, this->m_diagSize - 1) = temp(this->m_diagSize - 1, this->m_diagSize - 1);
+ divide(0, this->m_diagSize - 1, 0, 0, 0);
+
+ //**** step 3 copy
+ for (int i=0; i<this->m_diagSize; i++) {
+ RealScalar a = abs(m_computed.coeff(i, i));
+ this->m_singularValues.coeffRef(i) = a;
+ if (a == 0){
+ this->m_nonzeroSingularValues = i;
+ break;
+ }
+ else if (i == this->m_diagSize - 1)
+ {
+ this->m_nonzeroSingularValues = i + 1;
+ break;
+ }
+ }
+ copyUV(m_naiveV, m_naiveU, bid.householderU(), bid.householderV());
+ this->m_isInitialized = true;
+ return *this;
+}// end compute
+
+
+template<typename MatrixType>
+void BDCSVD<MatrixType>::copyUV(MatrixXr naiveU, MatrixXr naiveV, MatrixX householderU, MatrixX householderV){
+ if (this->computeU()){
+ MatrixX temp = MatrixX::Zero(naiveU.rows(), naiveU.cols());
+ temp.real() = naiveU;
+ if (this->m_computeThinU){
+ this->m_matrixU = MatrixX::Identity(householderU.cols(), this->m_nonzeroSingularValues );
+ this->m_matrixU.block(0, 0, this->m_diagSize, this->m_nonzeroSingularValues) =
+ temp.block(0, 0, this->m_diagSize, this->m_nonzeroSingularValues);
+ this->m_matrixU = householderU * this->m_matrixU ;
+ }
+ else
+ {
+ this->m_matrixU = MatrixX::Identity(householderU.cols(), householderU.cols());
+ this->m_matrixU.block(0, 0, this->m_diagSize, this->m_diagSize) = temp.block(0, 0, this->m_diagSize, this->m_diagSize);
+ this->m_matrixU = householderU * this->m_matrixU ;
+ }
+ }
+ if (this->computeV()){
+ MatrixX temp = MatrixX::Zero(naiveV.rows(), naiveV.cols());
+ temp.real() = naiveV;
+ if (this->m_computeThinV){
+ this->m_matrixV = MatrixX::Identity(householderV.cols(),this->m_nonzeroSingularValues );
+ this->m_matrixV.block(0, 0, this->m_nonzeroSingularValues, this->m_nonzeroSingularValues) =
+ temp.block(0, 0, this->m_nonzeroSingularValues, this->m_nonzeroSingularValues);
+ this->m_matrixV = householderV * this->m_matrixV ;
+ }
+ else
+ {
+ this->m_matrixV = MatrixX::Identity(householderV.cols(), householderV.cols());
+ this->m_matrixV.block(0, 0, this->m_diagSize, this->m_diagSize) = temp.block(0, 0, this->m_diagSize, this->m_diagSize);
+ this->m_matrixV = householderV * this->m_matrixV;
+ }
+ }
+}
+
+// The divide algorithm is done "in place", we are always working on subsets of the same matrix. The divide methods takes as argument the
+// place of the submatrix we are currently working on.
+
+//@param firstCol : The Index of the first column of the submatrix of m_computed and for m_naiveU;
+//@param lastCol : The Index of the last column of the submatrix of m_computed and for m_naiveU;
+// lastCol + 1 - firstCol is the size of the submatrix.
+//@param firstRowW : The Index of the first row of the matrix W that we are to change. (see the reference paper section 1 for more information on W)
+//@param firstRowW : Same as firstRowW with the column.
+//@param shift : Each time one takes the left submatrix, one must add 1 to the shift. Why? Because! We actually want the last column of the U submatrix
+// to become the first column (*coeff) and to shift all the other columns to the right. There are more details on the reference paper.
+template<typename MatrixType>
+void BDCSVD<MatrixType>::divide (Index firstCol, Index lastCol, Index firstRowW,
+ Index firstColW, Index shift)
+{
+ // requires nbRows = nbCols + 1;
+ using std::pow;
+ using std::sqrt;
+ using std::abs;
+ const Index n = lastCol - firstCol + 1;
+ const Index k = n/2;
+ RealScalar alphaK;
+ RealScalar betaK;
+ RealScalar r0;
+ RealScalar lambda, phi, c0, s0;
+ MatrixXr l, f;
+ // We use the other algorithm which is more efficient for small
+ // matrices.
+ if (n < algoswap){
+ JacobiSVD<MatrixXr> b(m_computed.block(firstCol, firstCol, n + 1, n),
+ ComputeFullU | (ComputeFullV * compV)) ;
+ if (compU) m_naiveU.block(firstCol, firstCol, n + 1, n + 1).real() << b.matrixU();
+ else
+ {
+ m_naiveU.row(0).segment(firstCol, n + 1).real() << b.matrixU().row(0);
+ m_naiveU.row(1).segment(firstCol, n + 1).real() << b.matrixU().row(n);
+ }
+ if (compV) m_naiveV.block(firstRowW, firstColW, n, n).real() << b.matrixV();
+ m_computed.block(firstCol + shift, firstCol + shift, n + 1, n).setZero();
+ for (int i=0; i<n; i++)
+ {
+ m_computed(firstCol + shift + i, firstCol + shift +i) = b.singularValues().coeffRef(i);
+ }
+ return;
+ }
+ // We use the divide and conquer algorithm
+ alphaK = m_computed(firstCol + k, firstCol + k);
+ betaK = m_computed(firstCol + k + 1, firstCol + k);
+ // The divide must be done in that order in order to have good results. Divide change the data inside the submatrices
+ // and the divide of the right submatrice reads one column of the left submatrice. That's why we need to treat the
+ // right submatrix before the left one.
+ divide(k + 1 + firstCol, lastCol, k + 1 + firstRowW, k + 1 + firstColW, shift);
+ divide(firstCol, k - 1 + firstCol, firstRowW, firstColW + 1, shift + 1);
+ if (compU)
+ {
+ lambda = m_naiveU(firstCol + k, firstCol + k);
+ phi = m_naiveU(firstCol + k + 1, lastCol + 1);
+ }
+ else
+ {
+ lambda = m_naiveU(1, firstCol + k);
+ phi = m_naiveU(0, lastCol + 1);
+ }
+ r0 = sqrt((abs(alphaK * lambda) * abs(alphaK * lambda))
+ + abs(betaK * phi) * abs(betaK * phi));
+ if (compU)
+ {
+ l = m_naiveU.row(firstCol + k).segment(firstCol, k);
+ f = m_naiveU.row(firstCol + k + 1).segment(firstCol + k + 1, n - k - 1);
+ }
+ else
+ {
+ l = m_naiveU.row(1).segment(firstCol, k);
+ f = m_naiveU.row(0).segment(firstCol + k + 1, n - k - 1);
+ }
+ if (compV) m_naiveV(firstRowW+k, firstColW) = 1;
+ if (r0 == 0)
+ {
+ c0 = 1;
+ s0 = 0;
+ }
+ else
+ {
+ c0 = alphaK * lambda / r0;
+ s0 = betaK * phi / r0;
+ }
+ if (compU)
+ {
+ MatrixXr q1 (m_naiveU.col(firstCol + k).segment(firstCol, k + 1));
+ // we shiftW Q1 to the right
+ for (Index i = firstCol + k - 1; i >= firstCol; i--)
+ {
+ m_naiveU.col(i + 1).segment(firstCol, k + 1) << m_naiveU.col(i).segment(firstCol, k + 1);
+ }
+ // we shift q1 at the left with a factor c0
+ m_naiveU.col(firstCol).segment( firstCol, k + 1) << (q1 * c0);
+ // last column = q1 * - s0
+ m_naiveU.col(lastCol + 1).segment(firstCol, k + 1) << (q1 * ( - s0));
+ // first column = q2 * s0
+ m_naiveU.col(firstCol).segment(firstCol + k + 1, n - k) <<
+ m_naiveU.col(lastCol + 1).segment(firstCol + k + 1, n - k) *s0;
+ // q2 *= c0
+ m_naiveU.col(lastCol + 1).segment(firstCol + k + 1, n - k) *= c0;
+ }
+ else
+ {
+ RealScalar q1 = (m_naiveU(0, firstCol + k));
+ // we shift Q1 to the right
+ for (Index i = firstCol + k - 1; i >= firstCol; i--)
+ {
+ m_naiveU(0, i + 1) = m_naiveU(0, i);
+ }
+ // we shift q1 at the left with a factor c0
+ m_naiveU(0, firstCol) = (q1 * c0);
+ // last column = q1 * - s0
+ m_naiveU(0, lastCol + 1) = (q1 * ( - s0));
+ // first column = q2 * s0
+ m_naiveU(1, firstCol) = m_naiveU(1, lastCol + 1) *s0;
+ // q2 *= c0
+ m_naiveU(1, lastCol + 1) *= c0;
+ m_naiveU.row(1).segment(firstCol + 1, k).setZero();
+ m_naiveU.row(0).segment(firstCol + k + 1, n - k - 1).setZero();
+ }
+ m_computed(firstCol + shift, firstCol + shift) = r0;
+ m_computed.col(firstCol + shift).segment(firstCol + shift + 1, k) << alphaK * l.transpose().real();
+ m_computed.col(firstCol + shift).segment(firstCol + shift + k + 1, n - k - 1) << betaK * f.transpose().real();
+
+
+ // the line below do the deflation of the matrix for the third part of the algorithm
+ // Here the deflation is commented because the third part of the algorithm is not implemented
+ // the third part of the algorithm is a fast SVD on the matrix m_computed which works thanks to the deflation
+
+ deflation(firstCol, lastCol, k, firstRowW, firstColW, shift);
+
+ // Third part of the algorithm, since the real third part of the algorithm is not implemeted we use a JacobiSVD
+ JacobiSVD<MatrixXr> res= JacobiSVD<MatrixXr>(m_computed.block(firstCol + shift, firstCol +shift, n + 1, n),
+ ComputeFullU | (ComputeFullV * compV)) ;
+ if (compU) m_naiveU.block(firstCol, firstCol, n + 1, n + 1) *= res.matrixU();
+ else m_naiveU.block(0, firstCol, 2, n + 1) *= res.matrixU();
+
+ if (compV) m_naiveV.block(firstRowW, firstColW, n, n) *= res.matrixV();
+ m_computed.block(firstCol + shift, firstCol + shift, n, n) << MatrixXr::Zero(n, n);
+ for (int i=0; i<n; i++)
+ m_computed(firstCol + shift + i, firstCol + shift +i) = res.singularValues().coeffRef(i);
+ // end of the third part
+
+
+}// end divide
+
+
+// page 12_13
+// i >= 1, di almost null and zi non null.
+// We use a rotation to zero out zi applied to the left of M
+template <typename MatrixType>
+void BDCSVD<MatrixType>::deflation43(Index firstCol, Index shift, Index i, Index size){
+ using std::abs;
+ using std::sqrt;
+ using std::pow;
+ RealScalar c = m_computed(firstCol + shift, firstCol + shift);
+ RealScalar s = m_computed(i, firstCol + shift);
+ RealScalar r = sqrt(pow(abs(c), 2) + pow(abs(s), 2));
+ if (r == 0){
+ m_computed(i, i)=0;
+ return;
+ }
+ c/=r;
+ s/=r;
+ m_computed(firstCol + shift, firstCol + shift) = r;
+ m_computed(i, firstCol + shift) = 0;
+ m_computed(i, i) = 0;
+ if (compU){
+ m_naiveU.col(firstCol).segment(firstCol,size) =
+ c * m_naiveU.col(firstCol).segment(firstCol, size) -
+ s * m_naiveU.col(i).segment(firstCol, size) ;
+
+ m_naiveU.col(i).segment(firstCol, size) =
+ (c + s*s/c) * m_naiveU.col(i).segment(firstCol, size) +
+ (s/c) * m_naiveU.col(firstCol).segment(firstCol,size);
+ }
+}// end deflation 43
+
+
+// page 13
+// i,j >= 1, i != j and |di - dj| < epsilon * norm2(M)
+// We apply two rotations to have zj = 0;
+template <typename MatrixType>
+void BDCSVD<MatrixType>::deflation44(Index firstColu , Index firstColm, Index firstRowW, Index firstColW, Index i, Index j, Index size){
+ using std::abs;
+ using std::sqrt;
+ using std::conj;
+ using std::pow;
+ RealScalar c = m_computed(firstColm, firstColm + j - 1);
+ RealScalar s = m_computed(firstColm, firstColm + i - 1);
+ RealScalar r = sqrt(pow(abs(c), 2) + pow(abs(s), 2));
+ if (r==0){
+ m_computed(firstColm + i, firstColm + i) = m_computed(firstColm + j, firstColm + j);
+ return;
+ }
+ c/=r;
+ s/=r;
+ m_computed(firstColm + i, firstColm) = r;
+ m_computed(firstColm + i, firstColm + i) = m_computed(firstColm + j, firstColm + j);
+ m_computed(firstColm + j, firstColm) = 0;
+ if (compU){
+ m_naiveU.col(firstColu + i).segment(firstColu, size) =
+ c * m_naiveU.col(firstColu + i).segment(firstColu, size) -
+ s * m_naiveU.col(firstColu + j).segment(firstColu, size) ;
+
+ m_naiveU.col(firstColu + j).segment(firstColu, size) =
+ (c + s*s/c) * m_naiveU.col(firstColu + j).segment(firstColu, size) +
+ (s/c) * m_naiveU.col(firstColu + i).segment(firstColu, size);
+ }
+ if (compV){
+ m_naiveV.col(firstColW + i).segment(firstRowW, size - 1) =
+ c * m_naiveV.col(firstColW + i).segment(firstRowW, size - 1) +
+ s * m_naiveV.col(firstColW + j).segment(firstRowW, size - 1) ;
+
+ m_naiveV.col(firstColW + j).segment(firstRowW, size - 1) =
+ (c + s*s/c) * m_naiveV.col(firstColW + j).segment(firstRowW, size - 1) -
+ (s/c) * m_naiveV.col(firstColW + i).segment(firstRowW, size - 1);
+ }
+}// end deflation 44
+
+
+
+template <typename MatrixType>
+void BDCSVD<MatrixType>::deflation(Index firstCol, Index lastCol, Index k, Index firstRowW, Index firstColW, Index shift){
+ //condition 4.1
+ RealScalar EPS = EPSILON * (std::max<RealScalar>(m_computed(firstCol + shift + 1, firstCol + shift + 1), m_computed(firstCol + k, firstCol + k)));
+ const Index length = lastCol + 1 - firstCol;
+ if (m_computed(firstCol + shift, firstCol + shift) < EPS){
+ m_computed(firstCol + shift, firstCol + shift) = EPS;
+ }
+ //condition 4.2
+ for (Index i=firstCol + shift + 1;i<=lastCol + shift;i++){
+ if (std::abs(m_computed(i, firstCol + shift)) < EPS){
+ m_computed(i, firstCol + shift) = 0;
+ }
+ }
+
+ //condition 4.3
+ for (Index i=firstCol + shift + 1;i<=lastCol + shift; i++){
+ if (m_computed(i, i) < EPS){
+ deflation43(firstCol, shift, i, length);
+ }
+ }
+
+ //condition 4.4
+
+ Index i=firstCol + shift + 1, j=firstCol + shift + k + 1;
+ //we stock the final place of each line
+ Index *permutation = new Index[length];
+
+ for (Index p =1; p < length; p++) {
+ if (i> firstCol + shift + k){
+ permutation[p] = j;
+ j++;
+ } else if (j> lastCol + shift)
+ {
+ permutation[p] = i;
+ i++;
+ }
+ else
+ {
+ if (m_computed(i, i) < m_computed(j, j)){
+ permutation[p] = j;
+ j++;
+ }
+ else
+ {
+ permutation[p] = i;
+ i++;
+ }
+ }
+ }
+ //we do the permutation
+ RealScalar aux;
+ //we stock the current index of each col
+ //and the column of each index
+ Index *realInd = new Index[length];
+ Index *realCol = new Index[length];
+ for (int pos = 0; pos< length; pos++){
+ realCol[pos] = pos + firstCol + shift;
+ realInd[pos] = pos;
+ }
+ const Index Zero = firstCol + shift;
+ VectorType temp;
+ for (int i = 1; i < length - 1; i++){
+ const Index I = i + Zero;
+ const Index realI = realInd[i];
+ const Index j = permutation[length - i] - Zero;
+ const Index J = realCol[j];
+
+ //diag displace
+ aux = m_computed(I, I);
+ m_computed(I, I) = m_computed(J, J);
+ m_computed(J, J) = aux;
+
+ //firstrow displace
+ aux = m_computed(I, Zero);
+ m_computed(I, Zero) = m_computed(J, Zero);
+ m_computed(J, Zero) = aux;
+
+ // change columns
+ if (compU) {
+ temp = m_naiveU.col(I - shift).segment(firstCol, length + 1);
+ m_naiveU.col(I - shift).segment(firstCol, length + 1) <<
+ m_naiveU.col(J - shift).segment(firstCol, length + 1);
+ m_naiveU.col(J - shift).segment(firstCol, length + 1) << temp;
+ }
+ else
+ {
+ temp = m_naiveU.col(I - shift).segment(0, 2);
+ m_naiveU.col(I - shift).segment(0, 2) <<
+ m_naiveU.col(J - shift).segment(0, 2);
+ m_naiveU.col(J - shift).segment(0, 2) << temp;
+ }
+ if (compV) {
+ const Index CWI = I + firstColW - Zero;
+ const Index CWJ = J + firstColW - Zero;
+ temp = m_naiveV.col(CWI).segment(firstRowW, length);
+ m_naiveV.col(CWI).segment(firstRowW, length) << m_naiveV.col(CWJ).segment(firstRowW, length);
+ m_naiveV.col(CWJ).segment(firstRowW, length) << temp;
+ }
+
+ //update real pos
+ realCol[realI] = J;
+ realCol[j] = I;
+ realInd[J - Zero] = realI;
+ realInd[I - Zero] = j;
+ }
+ for (Index i = firstCol + shift + 1; i<lastCol + shift;i++){
+ if ((m_computed(i + 1, i + 1) - m_computed(i, i)) < EPS){
+ deflation44(firstCol ,
+ firstCol + shift,
+ firstRowW,
+ firstColW,
+ i - Zero,
+ i + 1 - Zero,
+ length);
+ }
+ }
+ delete [] permutation;
+ delete [] realInd;
+ delete [] realCol;
+
+}//end deflation
+
+
+namespace internal{
+
+template<typename _MatrixType, typename Rhs>
+struct solve_retval<BDCSVD<_MatrixType>, Rhs>
+ : solve_retval_base<BDCSVD<_MatrixType>, Rhs>
+{
+ typedef BDCSVD<_MatrixType> BDCSVDType;
+ EIGEN_MAKE_SOLVE_HELPERS(BDCSVDType, Rhs)
+
+ template<typename Dest> void evalTo(Dest& dst) const
+ {
+ eigen_assert(rhs().rows() == dec().rows());
+ // A = U S V^*
+ // So A^{ - 1} = V S^{ - 1} U^*
+ Index diagSize = (std::min)(dec().rows(), dec().cols());
+ typename BDCSVDType::SingularValuesType invertedSingVals(diagSize);
+ Index nonzeroSingVals = dec().nonzeroSingularValues();
+ invertedSingVals.head(nonzeroSingVals) = dec().singularValues().head(nonzeroSingVals).array().inverse();
+ invertedSingVals.tail(diagSize - nonzeroSingVals).setZero();
+
+ dst = dec().matrixV().leftCols(diagSize)
+ * invertedSingVals.asDiagonal()
+ * dec().matrixU().leftCols(diagSize).adjoint()
+ * rhs();
+ return;
+ }
+};
+
+} //end namespace internal
+
+ /** \svd_module
+ *
+ * \return the singular value decomposition of \c *this computed by
+ * BDC Algorithm
+ *
+ * \sa class BDCSVD
+ */
+/*
+template<typename Derived>
+BDCSVD<typename MatrixBase<Derived>::PlainObject>
+MatrixBase<Derived>::bdcSvd(unsigned int computationOptions) const
+{
+ return BDCSVD<PlainObject>(*this, computationOptions);
+}
+*/
+
+} // end namespace Eigen
+
+#endif
diff --git a/unsupported/Eigen/src/SVD/CMakeLists.txt b/unsupported/Eigen/src/SVD/CMakeLists.txt
new file mode 100644
index 000000000..b40baf092
--- /dev/null
+++ b/unsupported/Eigen/src/SVD/CMakeLists.txt
@@ -0,0 +1,6 @@
+FILE(GLOB Eigen_SVD_SRCS "*.h")
+
+INSTALL(FILES
+ ${Eigen_SVD_SRCS}
+ DESTINATION ${INCLUDE_INSTALL_DIR}unsupported/Eigen/src/SVD COMPONENT Devel
+ )
diff --git a/unsupported/Eigen/src/SVD/JacobiSVD.h b/unsupported/Eigen/src/SVD/JacobiSVD.h
new file mode 100644
index 000000000..02fac409e
--- /dev/null
+++ b/unsupported/Eigen/src/SVD/JacobiSVD.h
@@ -0,0 +1,782 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef EIGEN_JACOBISVD_H
+#define EIGEN_JACOBISVD_H
+
+namespace Eigen {
+
+namespace internal {
+// forward declaration (needed by ICC)
+// the empty body is required by MSVC
+template<typename MatrixType, int QRPreconditioner,
+ bool IsComplex = NumTraits<typename MatrixType::Scalar>::IsComplex>
+struct svd_precondition_2x2_block_to_be_real {};
+
+/*** QR preconditioners (R-SVD)
+ ***
+ *** Their role is to reduce the problem of computing the SVD to the case of a square matrix.
+ *** This approach, known as R-SVD, is an optimization for rectangular-enough matrices, and is a requirement for
+ *** JacobiSVD which by itself is only able to work on square matrices.
+ ***/
+
+enum { PreconditionIfMoreColsThanRows, PreconditionIfMoreRowsThanCols };
+
+template<typename MatrixType, int QRPreconditioner, int Case>
+struct qr_preconditioner_should_do_anything
+{
+ enum { a = MatrixType::RowsAtCompileTime != Dynamic &&
+ MatrixType::ColsAtCompileTime != Dynamic &&
+ MatrixType::ColsAtCompileTime <= MatrixType::RowsAtCompileTime,
+ b = MatrixType::RowsAtCompileTime != Dynamic &&
+ MatrixType::ColsAtCompileTime != Dynamic &&
+ MatrixType::RowsAtCompileTime <= MatrixType::ColsAtCompileTime,
+ ret = !( (QRPreconditioner == NoQRPreconditioner) ||
+ (Case == PreconditionIfMoreColsThanRows && bool(a)) ||
+ (Case == PreconditionIfMoreRowsThanCols && bool(b)) )
+ };
+};
+
+template<typename MatrixType, int QRPreconditioner, int Case,
+ bool DoAnything = qr_preconditioner_should_do_anything<MatrixType, QRPreconditioner, Case>::ret
+> struct qr_preconditioner_impl {};
+
+template<typename MatrixType, int QRPreconditioner, int Case>
+class qr_preconditioner_impl<MatrixType, QRPreconditioner, Case, false>
+{
+public:
+ typedef typename MatrixType::Index Index;
+ void allocate(const JacobiSVD<MatrixType, QRPreconditioner>&) {}
+ bool run(JacobiSVD<MatrixType, QRPreconditioner>&, const MatrixType&)
+ {
+ return false;
+ }
+};
+
+/*** preconditioner using FullPivHouseholderQR ***/
+
+template<typename MatrixType>
+class qr_preconditioner_impl<MatrixType, FullPivHouseholderQRPreconditioner, PreconditionIfMoreRowsThanCols, true>
+{
+public:
+ typedef typename MatrixType::Index Index;
+ typedef typename MatrixType::Scalar Scalar;
+ enum
+ {
+ RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+ MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime
+ };
+ typedef Matrix<Scalar, 1, RowsAtCompileTime, RowMajor, 1, MaxRowsAtCompileTime> WorkspaceType;
+
+ void allocate(const JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner>& svd)
+ {
+ if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols())
+ {
+ m_qr.~QRType();
+ ::new (&m_qr) QRType(svd.rows(), svd.cols());
+ }
+ if (svd.m_computeFullU) m_workspace.resize(svd.rows());
+ }
+
+ bool run(JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
+ {
+ if(matrix.rows() > matrix.cols())
+ {
+ m_qr.compute(matrix);
+ svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView<Upper>();
+ if(svd.m_computeFullU) m_qr.matrixQ().evalTo(svd.m_matrixU, m_workspace);
+ if(svd.computeV()) svd.m_matrixV = m_qr.colsPermutation();
+ return true;
+ }
+ return false;
+ }
+private:
+ typedef FullPivHouseholderQR<MatrixType> QRType;
+ QRType m_qr;
+ WorkspaceType m_workspace;
+};
+
+template<typename MatrixType>
+class qr_preconditioner_impl<MatrixType, FullPivHouseholderQRPreconditioner, PreconditionIfMoreColsThanRows, true>
+{
+public:
+ typedef typename MatrixType::Index Index;
+ typedef typename MatrixType::Scalar Scalar;
+ enum
+ {
+ RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+ ColsAtCompileTime = MatrixType::ColsAtCompileTime,
+ MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
+ MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
+ Options = MatrixType::Options
+ };
+ typedef Matrix<Scalar, ColsAtCompileTime, RowsAtCompileTime, Options, MaxColsAtCompileTime, MaxRowsAtCompileTime>
+ TransposeTypeWithSameStorageOrder;
+
+ void allocate(const JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner>& svd)
+ {
+ if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols())
+ {
+ m_qr.~QRType();
+ ::new (&m_qr) QRType(svd.cols(), svd.rows());
+ }
+ m_adjoint.resize(svd.cols(), svd.rows());
+ if (svd.m_computeFullV) m_workspace.resize(svd.cols());
+ }
+
+ bool run(JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
+ {
+ if(matrix.cols() > matrix.rows())
+ {
+ m_adjoint = matrix.adjoint();
+ m_qr.compute(m_adjoint);
+ svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView<Upper>().adjoint();
+ if(svd.m_computeFullV) m_qr.matrixQ().evalTo(svd.m_matrixV, m_workspace);
+ if(svd.computeU()) svd.m_matrixU = m_qr.colsPermutation();
+ return true;
+ }
+ else return false;
+ }
+private:
+ typedef FullPivHouseholderQR<TransposeTypeWithSameStorageOrder> QRType;
+ QRType m_qr;
+ TransposeTypeWithSameStorageOrder m_adjoint;
+ typename internal::plain_row_type<MatrixType>::type m_workspace;
+};
+
+/*** preconditioner using ColPivHouseholderQR ***/
+
+template<typename MatrixType>
+class qr_preconditioner_impl<MatrixType, ColPivHouseholderQRPreconditioner, PreconditionIfMoreRowsThanCols, true>
+{
+public:
+ typedef typename MatrixType::Index Index;
+
+ void allocate(const JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner>& svd)
+ {
+ if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols())
+ {
+ m_qr.~QRType();
+ ::new (&m_qr) QRType(svd.rows(), svd.cols());
+ }
+ if (svd.m_computeFullU) m_workspace.resize(svd.rows());
+ else if (svd.m_computeThinU) m_workspace.resize(svd.cols());
+ }
+
+ bool run(JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
+ {
+ if(matrix.rows() > matrix.cols())
+ {
+ m_qr.compute(matrix);
+ svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView<Upper>();
+ if(svd.m_computeFullU) m_qr.householderQ().evalTo(svd.m_matrixU, m_workspace);
+ else if(svd.m_computeThinU)
+ {
+ svd.m_matrixU.setIdentity(matrix.rows(), matrix.cols());
+ m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixU, m_workspace);
+ }
+ if(svd.computeV()) svd.m_matrixV = m_qr.colsPermutation();
+ return true;
+ }
+ return false;
+ }
+
+private:
+ typedef ColPivHouseholderQR<MatrixType> QRType;
+ QRType m_qr;
+ typename internal::plain_col_type<MatrixType>::type m_workspace;
+};
+
+template<typename MatrixType>
+class qr_preconditioner_impl<MatrixType, ColPivHouseholderQRPreconditioner, PreconditionIfMoreColsThanRows, true>
+{
+public:
+ typedef typename MatrixType::Index Index;
+ typedef typename MatrixType::Scalar Scalar;
+ enum
+ {
+ RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+ ColsAtCompileTime = MatrixType::ColsAtCompileTime,
+ MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
+ MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
+ Options = MatrixType::Options
+ };
+
+ typedef Matrix<Scalar, ColsAtCompileTime, RowsAtCompileTime, Options, MaxColsAtCompileTime, MaxRowsAtCompileTime>
+ TransposeTypeWithSameStorageOrder;
+
+ void allocate(const JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner>& svd)
+ {
+ if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols())
+ {
+ m_qr.~QRType();
+ ::new (&m_qr) QRType(svd.cols(), svd.rows());
+ }
+ if (svd.m_computeFullV) m_workspace.resize(svd.cols());
+ else if (svd.m_computeThinV) m_workspace.resize(svd.rows());
+ m_adjoint.resize(svd.cols(), svd.rows());
+ }
+
+ bool run(JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
+ {
+ if(matrix.cols() > matrix.rows())
+ {
+ m_adjoint = matrix.adjoint();
+ m_qr.compute(m_adjoint);
+
+ svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView<Upper>().adjoint();
+ if(svd.m_computeFullV) m_qr.householderQ().evalTo(svd.m_matrixV, m_workspace);
+ else if(svd.m_computeThinV)
+ {
+ svd.m_matrixV.setIdentity(matrix.cols(), matrix.rows());
+ m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixV, m_workspace);
+ }
+ if(svd.computeU()) svd.m_matrixU = m_qr.colsPermutation();
+ return true;
+ }
+ else return false;
+ }
+
+private:
+ typedef ColPivHouseholderQR<TransposeTypeWithSameStorageOrder> QRType;
+ QRType m_qr;
+ TransposeTypeWithSameStorageOrder m_adjoint;
+ typename internal::plain_row_type<MatrixType>::type m_workspace;
+};
+
+/*** preconditioner using HouseholderQR ***/
+
+template<typename MatrixType>
+class qr_preconditioner_impl<MatrixType, HouseholderQRPreconditioner, PreconditionIfMoreRowsThanCols, true>
+{
+public:
+ typedef typename MatrixType::Index Index;
+
+ void allocate(const JacobiSVD<MatrixType, HouseholderQRPreconditioner>& svd)
+ {
+ if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols())
+ {
+ m_qr.~QRType();
+ ::new (&m_qr) QRType(svd.rows(), svd.cols());
+ }
+ if (svd.m_computeFullU) m_workspace.resize(svd.rows());
+ else if (svd.m_computeThinU) m_workspace.resize(svd.cols());
+ }
+
+ bool run(JacobiSVD<MatrixType, HouseholderQRPreconditioner>& svd, const MatrixType& matrix)
+ {
+ if(matrix.rows() > matrix.cols())
+ {
+ m_qr.compute(matrix);
+ svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView<Upper>();
+ if(svd.m_computeFullU) m_qr.householderQ().evalTo(svd.m_matrixU, m_workspace);
+ else if(svd.m_computeThinU)
+ {
+ svd.m_matrixU.setIdentity(matrix.rows(), matrix.cols());
+ m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixU, m_workspace);
+ }
+ if(svd.computeV()) svd.m_matrixV.setIdentity(matrix.cols(), matrix.cols());
+ return true;
+ }
+ return false;
+ }
+private:
+ typedef HouseholderQR<MatrixType> QRType;
+ QRType m_qr;
+ typename internal::plain_col_type<MatrixType>::type m_workspace;
+};
+
+template<typename MatrixType>
+class qr_preconditioner_impl<MatrixType, HouseholderQRPreconditioner, PreconditionIfMoreColsThanRows, true>
+{
+public:
+ typedef typename MatrixType::Index Index;
+ typedef typename MatrixType::Scalar Scalar;
+ enum
+ {
+ RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+ ColsAtCompileTime = MatrixType::ColsAtCompileTime,
+ MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
+ MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
+ Options = MatrixType::Options
+ };
+
+ typedef Matrix<Scalar, ColsAtCompileTime, RowsAtCompileTime, Options, MaxColsAtCompileTime, MaxRowsAtCompileTime>
+ TransposeTypeWithSameStorageOrder;
+
+ void allocate(const JacobiSVD<MatrixType, HouseholderQRPreconditioner>& svd)
+ {
+ if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols())
+ {
+ m_qr.~QRType();
+ ::new (&m_qr) QRType(svd.cols(), svd.rows());
+ }
+ if (svd.m_computeFullV) m_workspace.resize(svd.cols());
+ else if (svd.m_computeThinV) m_workspace.resize(svd.rows());
+ m_adjoint.resize(svd.cols(), svd.rows());
+ }
+
+ bool run(JacobiSVD<MatrixType, HouseholderQRPreconditioner>& svd, const MatrixType& matrix)
+ {
+ if(matrix.cols() > matrix.rows())
+ {
+ m_adjoint = matrix.adjoint();
+ m_qr.compute(m_adjoint);
+
+ svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView<Upper>().adjoint();
+ if(svd.m_computeFullV) m_qr.householderQ().evalTo(svd.m_matrixV, m_workspace);
+ else if(svd.m_computeThinV)
+ {
+ svd.m_matrixV.setIdentity(matrix.cols(), matrix.rows());
+ m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixV, m_workspace);
+ }
+ if(svd.computeU()) svd.m_matrixU.setIdentity(matrix.rows(), matrix.rows());
+ return true;
+ }
+ else return false;
+ }
+
+private:
+ typedef HouseholderQR<TransposeTypeWithSameStorageOrder> QRType;
+ QRType m_qr;
+ TransposeTypeWithSameStorageOrder m_adjoint;
+ typename internal::plain_row_type<MatrixType>::type m_workspace;
+};
+
+/*** 2x2 SVD implementation
+ ***
+ *** JacobiSVD consists in performing a series of 2x2 SVD subproblems
+ ***/
+
+template<typename MatrixType, int QRPreconditioner>
+struct svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner, false>
+{
+ typedef JacobiSVD<MatrixType, QRPreconditioner> SVD;
+ typedef typename SVD::Index Index;
+ static void run(typename SVD::WorkMatrixType&, SVD&, Index, Index) {}
+};
+
+template<typename MatrixType, int QRPreconditioner>
+struct svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner, true>
+{
+ typedef JacobiSVD<MatrixType, QRPreconditioner> SVD;
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::RealScalar RealScalar;
+ typedef typename SVD::Index Index;
+ static void run(typename SVD::WorkMatrixType& work_matrix, SVD& svd, Index p, Index q)
+ {
+ using std::sqrt;
+ Scalar z;
+ JacobiRotation<Scalar> rot;
+ RealScalar n = sqrt(numext::abs2(work_matrix.coeff(p,p)) + numext::abs2(work_matrix.coeff(q,p)));
+ if(n==0)
+ {
+ z = abs(work_matrix.coeff(p,q)) / work_matrix.coeff(p,q);
+ work_matrix.row(p) *= z;
+ if(svd.computeU()) svd.m_matrixU.col(p) *= conj(z);
+ z = abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
+ work_matrix.row(q) *= z;
+ if(svd.computeU()) svd.m_matrixU.col(q) *= conj(z);
+ }
+ else
+ {
+ rot.c() = conj(work_matrix.coeff(p,p)) / n;
+ rot.s() = work_matrix.coeff(q,p) / n;
+ work_matrix.applyOnTheLeft(p,q,rot);
+ if(svd.computeU()) svd.m_matrixU.applyOnTheRight(p,q,rot.adjoint());
+ if(work_matrix.coeff(p,q) != Scalar(0))
+ {
+ Scalar z = abs(work_matrix.coeff(p,q)) / work_matrix.coeff(p,q);
+ work_matrix.col(q) *= z;
+ if(svd.computeV()) svd.m_matrixV.col(q) *= z;
+ }
+ if(work_matrix.coeff(q,q) != Scalar(0))
+ {
+ z = abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
+ work_matrix.row(q) *= z;
+ if(svd.computeU()) svd.m_matrixU.col(q) *= conj(z);
+ }
+ }
+ }
+};
+
+template<typename MatrixType, typename RealScalar, typename Index>
+void real_2x2_jacobi_svd(const MatrixType& matrix, Index p, Index q,
+ JacobiRotation<RealScalar> *j_left,
+ JacobiRotation<RealScalar> *j_right)
+{
+ using std::sqrt;
+ Matrix<RealScalar,2,2> 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<RealScalar> rot1;
+ RealScalar t = m.coeff(0,0) + m.coeff(1,1);
+ RealScalar d = m.coeff(1,0) - m.coeff(0,1);
+ if(t == RealScalar(0))
+ {
+ rot1.c() = RealScalar(0);
+ rot1.s() = d > RealScalar(0) ? RealScalar(1) : RealScalar(-1);
+ }
+ else
+ {
+ RealScalar u = d / t;
+ rot1.c() = RealScalar(1) / sqrt(RealScalar(1) + numext::abs2(u));
+ rot1.s() = rot1.c() * u;
+ }
+ m.applyOnTheLeft(0,1,rot1);
+ j_right->makeJacobi(m,0,1);
+ *j_left = rot1 * j_right->transpose();
+}
+
+} // end namespace internal
+
+/** \ingroup SVD_Module
+ *
+ *
+ * \class JacobiSVD
+ *
+ * \brief Two-sided Jacobi SVD decomposition of a rectangular matrix
+ *
+ * \param MatrixType the type of the matrix of which we are computing the SVD decomposition
+ * \param QRPreconditioner this optional parameter allows to specify the type of QR decomposition that will be used internally
+ * for the R-SVD step for non-square matrices. See discussion of possible values below.
+ *
+ * SVD decomposition consists in decomposing any n-by-p matrix \a A as a product
+ * \f[ A = U S V^* \f]
+ * where \a U is a n-by-n unitary, \a V is a p-by-p unitary, and \a S is a n-by-p real positive matrix which is zero outside of its main diagonal;
+ * the diagonal entries of S are known as the \em singular \em values of \a A and the columns of \a U and \a V are known as the left
+ * and right \em singular \em vectors of \a A respectively.
+ *
+ * Singular values are always sorted in decreasing order.
+ *
+ * This JacobiSVD decomposition computes only the singular values by default. If you want \a U or \a V, you need to ask for them explicitly.
+ *
+ * You can ask for only \em thin \a U or \a V to be computed, meaning the following. In case of a rectangular n-by-p matrix, letting \a m be the
+ * smaller value among \a n and \a p, there are only \a m singular vectors; the remaining columns of \a U and \a V do not correspond to actual
+ * singular vectors. Asking for \em thin \a U or \a V means asking for only their \a m first columns to be formed. So \a U is then a n-by-m matrix,
+ * and \a V is then a p-by-m matrix. Notice that thin \a U and \a V are all you need for (least squares) solving.
+ *
+ * Here's an example demonstrating basic usage:
+ * \include JacobiSVD_basic.cpp
+ * Output: \verbinclude JacobiSVD_basic.out
+ *
+ * This JacobiSVD class is a two-sided Jacobi R-SVD decomposition, ensuring optimal reliability and accuracy. The downside is that it's slower than
+ * bidiagonalizing SVD algorithms for large square matrices; however its complexity is still \f$ O(n^2p) \f$ where \a n is the smaller dimension and
+ * \a p is the greater dimension, meaning that it is still of the same order of complexity as the faster bidiagonalizing R-SVD algorithms.
+ * In particular, like any R-SVD, it takes advantage of non-squareness in that its complexity is only linear in the greater dimension.
+ *
+ * If the input matrix has inf or nan coefficients, the result of the computation is undefined, but the computation is guaranteed to
+ * terminate in finite (and reasonable) time.
+ *
+ * The possible values for QRPreconditioner are:
+ * \li ColPivHouseholderQRPreconditioner is the default. In practice it's very safe. It uses column-pivoting QR.
+ * \li FullPivHouseholderQRPreconditioner, is the safest and slowest. It uses full-pivoting QR.
+ * Contrary to other QRs, it doesn't allow computing thin unitaries.
+ * \li HouseholderQRPreconditioner is the fastest, and less safe and accurate than the pivoting variants. It uses non-pivoting QR.
+ * This is very similar in safety and accuracy to the bidiagonalization process used by bidiagonalizing SVD algorithms (since bidiagonalization
+ * is inherently non-pivoting). However the resulting SVD is still more reliable than bidiagonalizing SVDs because the Jacobi-based iterarive
+ * process is more reliable than the optimized bidiagonal SVD iterations.
+ * \li NoQRPreconditioner allows not to use a QR preconditioner at all. This is useful if you know that you will only be computing
+ * JacobiSVD decompositions of square matrices. Non-square matrices require a QR preconditioner. Using this option will result in
+ * faster compilation and smaller executable code. It won't significantly speed up computation, since JacobiSVD is always checking
+ * if QR preconditioning is needed before applying it anyway.
+ *
+ * \sa MatrixBase::jacobiSvd()
+ */
+template<typename _MatrixType, int QRPreconditioner>
+class JacobiSVD : public SVDBase<_MatrixType>
+{
+ public:
+
+ typedef _MatrixType MatrixType;
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
+ typedef typename MatrixType::Index Index;
+ enum {
+ RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+ ColsAtCompileTime = MatrixType::ColsAtCompileTime,
+ DiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_DYNAMIC(RowsAtCompileTime,ColsAtCompileTime),
+ MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
+ MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
+ MaxDiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(MaxRowsAtCompileTime,MaxColsAtCompileTime),
+ MatrixOptions = MatrixType::Options
+ };
+
+ typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime,
+ MatrixOptions, MaxRowsAtCompileTime, MaxRowsAtCompileTime>
+ MatrixUType;
+ typedef Matrix<Scalar, ColsAtCompileTime, ColsAtCompileTime,
+ MatrixOptions, MaxColsAtCompileTime, MaxColsAtCompileTime>
+ MatrixVType;
+ typedef typename internal::plain_diag_type<MatrixType, RealScalar>::type SingularValuesType;
+ typedef typename internal::plain_row_type<MatrixType>::type RowType;
+ typedef typename internal::plain_col_type<MatrixType>::type ColType;
+ typedef Matrix<Scalar, DiagSizeAtCompileTime, DiagSizeAtCompileTime,
+ MatrixOptions, MaxDiagSizeAtCompileTime, MaxDiagSizeAtCompileTime>
+ WorkMatrixType;
+
+ /** \brief Default Constructor.
+ *
+ * The default constructor is useful in cases in which the user intends to
+ * perform decompositions via JacobiSVD::compute(const MatrixType&).
+ */
+ JacobiSVD()
+ : SVDBase<_MatrixType>::SVDBase()
+ {}
+
+
+ /** \brief Default Constructor with memory preallocation
+ *
+ * Like the default constructor but with preallocation of the internal data
+ * according to the specified problem size.
+ * \sa JacobiSVD()
+ */
+ JacobiSVD(Index rows, Index cols, unsigned int computationOptions = 0)
+ : SVDBase<_MatrixType>::SVDBase()
+ {
+ allocate(rows, cols, computationOptions);
+ }
+
+ /** \brief Constructor performing the decomposition of given matrix.
+ *
+ * \param matrix the matrix to decompose
+ * \param computationOptions optional parameter allowing to specify if you want full or thin U or V unitaries to be computed.
+ * By default, none is computed. This is a bit-field, the possible bits are #ComputeFullU, #ComputeThinU,
+ * #ComputeFullV, #ComputeThinV.
+ *
+ * Thin unitaries are only available if your matrix type has a Dynamic number of columns (for example MatrixXf). They also are not
+ * available with the (non-default) FullPivHouseholderQR preconditioner.
+ */
+ JacobiSVD(const MatrixType& matrix, unsigned int computationOptions = 0)
+ : SVDBase<_MatrixType>::SVDBase()
+ {
+ compute(matrix, computationOptions);
+ }
+
+ /** \brief Method performing the decomposition of given matrix using custom options.
+ *
+ * \param matrix the matrix to decompose
+ * \param computationOptions optional parameter allowing to specify if you want full or thin U or V unitaries to be computed.
+ * By default, none is computed. This is a bit-field, the possible bits are #ComputeFullU, #ComputeThinU,
+ * #ComputeFullV, #ComputeThinV.
+ *
+ * Thin unitaries are only available if your matrix type has a Dynamic number of columns (for example MatrixXf). They also are not
+ * available with the (non-default) FullPivHouseholderQR preconditioner.
+ */
+ SVDBase<MatrixType>& compute(const MatrixType& matrix, unsigned int computationOptions);
+
+ /** \brief Method performing the decomposition of given matrix using current options.
+ *
+ * \param matrix the matrix to decompose
+ *
+ * This method uses the current \a computationOptions, as already passed to the constructor or to compute(const MatrixType&, unsigned int).
+ */
+ SVDBase<MatrixType>& compute(const MatrixType& matrix)
+ {
+ return compute(matrix, this->m_computationOptions);
+ }
+
+ /** \returns a (least squares) solution of \f$ A x = b \f$ using the current SVD decomposition of A.
+ *
+ * \param b the right-hand-side of the equation to solve.
+ *
+ * \note Solving requires both U and V to be computed. Thin U and V are enough, there is no need for full U or V.
+ *
+ * \note SVD solving is implicitly least-squares. Thus, this method serves both purposes of exact solving and least-squares solving.
+ * In other words, the returned solution is guaranteed to minimize the Euclidean norm \f$ \Vert A x - b \Vert \f$.
+ */
+ template<typename Rhs>
+ inline const internal::solve_retval<JacobiSVD, Rhs>
+ solve(const MatrixBase<Rhs>& b) const
+ {
+ eigen_assert(this->m_isInitialized && "JacobiSVD is not initialized.");
+ eigen_assert(SVDBase<MatrixType>::computeU() && SVDBase<MatrixType>::computeV() && "JacobiSVD::solve() requires both unitaries U and V to be computed (thin unitaries suffice).");
+ return internal::solve_retval<JacobiSVD, Rhs>(*this, b.derived());
+ }
+
+
+
+ private:
+ void allocate(Index rows, Index cols, unsigned int computationOptions);
+
+ protected:
+ WorkMatrixType m_workMatrix;
+
+ template<typename __MatrixType, int _QRPreconditioner, bool _IsComplex>
+ friend struct internal::svd_precondition_2x2_block_to_be_real;
+ template<typename __MatrixType, int _QRPreconditioner, int _Case, bool _DoAnything>
+ friend struct internal::qr_preconditioner_impl;
+
+ internal::qr_preconditioner_impl<MatrixType, QRPreconditioner, internal::PreconditionIfMoreColsThanRows> m_qr_precond_morecols;
+ internal::qr_preconditioner_impl<MatrixType, QRPreconditioner, internal::PreconditionIfMoreRowsThanCols> m_qr_precond_morerows;
+};
+
+template<typename MatrixType, int QRPreconditioner>
+void JacobiSVD<MatrixType, QRPreconditioner>::allocate(Index rows, Index cols, unsigned int computationOptions)
+{
+ if (SVDBase<MatrixType>::allocate(rows, cols, computationOptions)) return;
+
+ if (QRPreconditioner == FullPivHouseholderQRPreconditioner)
+ {
+ eigen_assert(!(this->m_computeThinU || this->m_computeThinV) &&
+ "JacobiSVD: can't compute thin U or thin V with the FullPivHouseholderQR preconditioner. "
+ "Use the ColPivHouseholderQR preconditioner instead.");
+ }
+
+ m_workMatrix.resize(this->m_diagSize, this->m_diagSize);
+
+ if(this->m_cols>this->m_rows) m_qr_precond_morecols.allocate(*this);
+ if(this->m_rows>this->m_cols) m_qr_precond_morerows.allocate(*this);
+}
+
+template<typename MatrixType, int QRPreconditioner>
+SVDBase<MatrixType>&
+JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType& matrix, unsigned int computationOptions)
+{
+ using std::abs;
+ allocate(matrix.rows(), matrix.cols(), computationOptions);
+
+ // currently we stop when we reach precision 2*epsilon as the last bit of precision can require an unreasonable number of iterations,
+ // only worsening the precision of U and V as we accumulate more rotations
+ const RealScalar precision = RealScalar(2) * NumTraits<Scalar>::epsilon();
+
+ // limit for very small denormal numbers to be considered zero in order to avoid infinite loops (see bug 286)
+ const RealScalar considerAsZero = RealScalar(2) * std::numeric_limits<RealScalar>::denorm_min();
+
+ /*** step 1. The R-SVD step: we use a QR decomposition to reduce to the case of a square matrix */
+
+ if(!m_qr_precond_morecols.run(*this, matrix) && !m_qr_precond_morerows.run(*this, matrix))
+ {
+ m_workMatrix = matrix.block(0,0,this->m_diagSize,this->m_diagSize);
+ if(this->m_computeFullU) this->m_matrixU.setIdentity(this->m_rows,this->m_rows);
+ if(this->m_computeThinU) this->m_matrixU.setIdentity(this->m_rows,this->m_diagSize);
+ if(this->m_computeFullV) this->m_matrixV.setIdentity(this->m_cols,this->m_cols);
+ if(this->m_computeThinV) this->m_matrixV.setIdentity(this->m_cols, this->m_diagSize);
+ }
+
+ /*** step 2. The main Jacobi SVD iteration. ***/
+
+ bool finished = false;
+ while(!finished)
+ {
+ finished = true;
+
+ // do a sweep: for all index pairs (p,q), perform SVD of the corresponding 2x2 sub-matrix
+
+ for(Index p = 1; p < this->m_diagSize; ++p)
+ {
+ for(Index q = 0; q < p; ++q)
+ {
+ // if this 2x2 sub-matrix is not diagonal already...
+ // notice that this comparison will evaluate to false if any NaN is involved, ensuring that NaN's don't
+ // keep us iterating forever. Similarly, small denormal numbers are considered zero.
+ using std::max;
+ RealScalar threshold = (max)(considerAsZero, precision * (max)(abs(m_workMatrix.coeff(p,p)),
+ abs(m_workMatrix.coeff(q,q))));
+ if((max)(abs(m_workMatrix.coeff(p,q)),abs(m_workMatrix.coeff(q,p))) > threshold)
+ {
+ finished = false;
+
+ // perform SVD decomposition of 2x2 sub-matrix corresponding to indices p,q to make it diagonal
+ internal::svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner>::run(m_workMatrix, *this, p, q);
+ JacobiRotation<RealScalar> j_left, j_right;
+ internal::real_2x2_jacobi_svd(m_workMatrix, p, q, &j_left, &j_right);
+
+ // accumulate resulting Jacobi rotations
+ m_workMatrix.applyOnTheLeft(p,q,j_left);
+ if(SVDBase<MatrixType>::computeU()) this->m_matrixU.applyOnTheRight(p,q,j_left.transpose());
+
+ m_workMatrix.applyOnTheRight(p,q,j_right);
+ if(SVDBase<MatrixType>::computeV()) this->m_matrixV.applyOnTheRight(p,q,j_right);
+ }
+ }
+ }
+ }
+
+ /*** step 3. The work matrix is now diagonal, so ensure it's positive so its diagonal entries are the singular values ***/
+
+ for(Index i = 0; i < this->m_diagSize; ++i)
+ {
+ RealScalar a = abs(m_workMatrix.coeff(i,i));
+ this->m_singularValues.coeffRef(i) = a;
+ if(SVDBase<MatrixType>::computeU() && (a!=RealScalar(0))) this->m_matrixU.col(i) *= this->m_workMatrix.coeff(i,i)/a;
+ }
+
+ /*** step 4. Sort singular values in descending order and compute the number of nonzero singular values ***/
+
+ this->m_nonzeroSingularValues = this->m_diagSize;
+ for(Index i = 0; i < this->m_diagSize; i++)
+ {
+ Index pos;
+ RealScalar maxRemainingSingularValue = this->m_singularValues.tail(this->m_diagSize-i).maxCoeff(&pos);
+ if(maxRemainingSingularValue == RealScalar(0))
+ {
+ this->m_nonzeroSingularValues = i;
+ break;
+ }
+ if(pos)
+ {
+ pos += i;
+ std::swap(this->m_singularValues.coeffRef(i), this->m_singularValues.coeffRef(pos));
+ if(SVDBase<MatrixType>::computeU()) this->m_matrixU.col(pos).swap(this->m_matrixU.col(i));
+ if(SVDBase<MatrixType>::computeV()) this->m_matrixV.col(pos).swap(this->m_matrixV.col(i));
+ }
+ }
+
+ this->m_isInitialized = true;
+ return *this;
+}
+
+namespace internal {
+template<typename _MatrixType, int QRPreconditioner, typename Rhs>
+struct solve_retval<JacobiSVD<_MatrixType, QRPreconditioner>, Rhs>
+ : solve_retval_base<JacobiSVD<_MatrixType, QRPreconditioner>, Rhs>
+{
+ typedef JacobiSVD<_MatrixType, QRPreconditioner> JacobiSVDType;
+ EIGEN_MAKE_SOLVE_HELPERS(JacobiSVDType,Rhs)
+
+ template<typename Dest> void evalTo(Dest& dst) const
+ {
+ eigen_assert(rhs().rows() == dec().rows());
+
+ // A = U S V^*
+ // So A^{-1} = V S^{-1} U^*
+
+ Index diagSize = (std::min)(dec().rows(), dec().cols());
+ typename JacobiSVDType::SingularValuesType invertedSingVals(diagSize);
+
+ Index nonzeroSingVals = dec().nonzeroSingularValues();
+ invertedSingVals.head(nonzeroSingVals) = dec().singularValues().head(nonzeroSingVals).array().inverse();
+ invertedSingVals.tail(diagSize - nonzeroSingVals).setZero();
+
+ dst = dec().matrixV().leftCols(diagSize)
+ * invertedSingVals.asDiagonal()
+ * dec().matrixU().leftCols(diagSize).adjoint()
+ * rhs();
+ }
+};
+} // end namespace internal
+
+/** \svd_module
+ *
+ * \return the singular value decomposition of \c *this computed by two-sided
+ * Jacobi transformations.
+ *
+ * \sa class JacobiSVD
+ */
+template<typename Derived>
+JacobiSVD<typename MatrixBase<Derived>::PlainObject>
+MatrixBase<Derived>::jacobiSvd(unsigned int computationOptions) const
+{
+ return JacobiSVD<PlainObject>(*this, computationOptions);
+}
+
+} // end namespace Eigen
+
+#endif // EIGEN_JACOBISVD_H
diff --git a/unsupported/Eigen/src/SVD/SVDBase.h b/unsupported/Eigen/src/SVD/SVDBase.h
new file mode 100644
index 000000000..fd8af3b8c
--- /dev/null
+++ b/unsupported/Eigen/src/SVD/SVDBase.h
@@ -0,0 +1,236 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Copyright (C) 2013 Gauthier Brun <brun.gauthier@gmail.com>
+// Copyright (C) 2013 Nicolas Carre <nicolas.carre@ensimag.fr>
+// Copyright (C) 2013 Jean Ceccato <jean.ceccato@ensimag.fr>
+// Copyright (C) 2013 Pierre Zoppitelli <pierre.zoppitelli@ensimag.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef EIGEN_SVD_H
+#define EIGEN_SVD_H
+
+namespace Eigen {
+/** \ingroup SVD_Module
+ *
+ *
+ * \class SVDBase
+ *
+ * \brief Mother class of SVD classes algorithms
+ *
+ * \param MatrixType the type of the matrix of which we are computing the SVD decomposition
+ * SVD decomposition consists in decomposing any n-by-p matrix \a A as a product
+ * \f[ A = U S V^* \f]
+ * where \a U is a n-by-n unitary, \a V is a p-by-p unitary, and \a S is a n-by-p real positive matrix which is zero outside of its main diagonal;
+ * the diagonal entries of S are known as the \em singular \em values of \a A and the columns of \a U and \a V are known as the left
+ * and right \em singular \em vectors of \a A respectively.
+ *
+ * Singular values are always sorted in decreasing order.
+ *
+ *
+ * You can ask for only \em thin \a U or \a V to be computed, meaning the following. In case of a rectangular n-by-p matrix, letting \a m be the
+ * smaller value among \a n and \a p, there are only \a m singular vectors; the remaining columns of \a U and \a V do not correspond to actual
+ * singular vectors. Asking for \em thin \a U or \a V means asking for only their \a m first columns to be formed. So \a U is then a n-by-m matrix,
+ * and \a V is then a p-by-m matrix. Notice that thin \a U and \a V are all you need for (least squares) solving.
+ *
+ * If the input matrix has inf or nan coefficients, the result of the computation is undefined, but the computation is guaranteed to
+ * terminate in finite (and reasonable) time.
+ * \sa MatrixBase::genericSvd()
+ */
+template<typename _MatrixType>
+class SVDBase
+{
+
+public:
+ typedef _MatrixType MatrixType;
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
+ typedef typename MatrixType::Index Index;
+ enum {
+ RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+ ColsAtCompileTime = MatrixType::ColsAtCompileTime,
+ DiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_DYNAMIC(RowsAtCompileTime,ColsAtCompileTime),
+ MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
+ MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
+ MaxDiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(MaxRowsAtCompileTime,MaxColsAtCompileTime),
+ MatrixOptions = MatrixType::Options
+ };
+
+ typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime,
+ MatrixOptions, MaxRowsAtCompileTime, MaxRowsAtCompileTime>
+ MatrixUType;
+ typedef Matrix<Scalar, ColsAtCompileTime, ColsAtCompileTime,
+ MatrixOptions, MaxColsAtCompileTime, MaxColsAtCompileTime>
+ MatrixVType;
+ typedef typename internal::plain_diag_type<MatrixType, RealScalar>::type SingularValuesType;
+ typedef typename internal::plain_row_type<MatrixType>::type RowType;
+ typedef typename internal::plain_col_type<MatrixType>::type ColType;
+ typedef Matrix<Scalar, DiagSizeAtCompileTime, DiagSizeAtCompileTime,
+ MatrixOptions, MaxDiagSizeAtCompileTime, MaxDiagSizeAtCompileTime>
+ WorkMatrixType;
+
+
+
+
+ /** \brief Method performing the decomposition of given matrix using custom options.
+ *
+ * \param matrix the matrix to decompose
+ * \param computationOptions optional parameter allowing to specify if you want full or thin U or V unitaries to be computed.
+ * By default, none is computed. This is a bit-field, the possible bits are #ComputeFullU, #ComputeThinU,
+ * #ComputeFullV, #ComputeThinV.
+ *
+ * Thin unitaries are only available if your matrix type has a Dynamic number of columns (for example MatrixXf). They also are not
+ * available with the (non-default) FullPivHouseholderQR preconditioner.
+ */
+ SVDBase& compute(const MatrixType& matrix, unsigned int computationOptions);
+
+ /** \brief Method performing the decomposition of given matrix using current options.
+ *
+ * \param matrix the matrix to decompose
+ *
+ * This method uses the current \a computationOptions, as already passed to the constructor or to compute(const MatrixType&, unsigned int).
+ */
+ //virtual SVDBase& compute(const MatrixType& matrix) = 0;
+ SVDBase& compute(const MatrixType& matrix);
+
+ /** \returns the \a U matrix.
+ *
+ * For the SVDBase decomposition of a n-by-p matrix, letting \a m be the minimum of \a n and \a p,
+ * the U matrix is n-by-n if you asked for #ComputeFullU, and is n-by-m if you asked for #ComputeThinU.
+ *
+ * The \a m first columns of \a U are the left singular vectors of the matrix being decomposed.
+ *
+ * This method asserts that you asked for \a U to be computed.
+ */
+ const MatrixUType& matrixU() const
+ {
+ eigen_assert(m_isInitialized && "SVD is not initialized.");
+ eigen_assert(computeU() && "This SVD decomposition didn't compute U. Did you ask for it?");
+ return m_matrixU;
+ }
+
+ /** \returns the \a V matrix.
+ *
+ * For the SVD decomposition of a n-by-p matrix, letting \a m be the minimum of \a n and \a p,
+ * the V matrix is p-by-p if you asked for #ComputeFullV, and is p-by-m if you asked for ComputeThinV.
+ *
+ * The \a m first columns of \a V are the right singular vectors of the matrix being decomposed.
+ *
+ * This method asserts that you asked for \a V to be computed.
+ */
+ const MatrixVType& matrixV() const
+ {
+ eigen_assert(m_isInitialized && "SVD is not initialized.");
+ eigen_assert(computeV() && "This SVD decomposition didn't compute V. Did you ask for it?");
+ return m_matrixV;
+ }
+
+ /** \returns the vector of singular values.
+ *
+ * For the SVD decomposition of a n-by-p matrix, letting \a m be the minimum of \a n and \a p, the
+ * returned vector has size \a m. Singular values are always sorted in decreasing order.
+ */
+ const SingularValuesType& singularValues() const
+ {
+ eigen_assert(m_isInitialized && "SVD is not initialized.");
+ return m_singularValues;
+ }
+
+
+
+ /** \returns the number of singular values that are not exactly 0 */
+ Index nonzeroSingularValues() const
+ {
+ eigen_assert(m_isInitialized && "SVD is not initialized.");
+ return m_nonzeroSingularValues;
+ }
+
+
+ /** \returns true if \a U (full or thin) is asked for in this SVD decomposition */
+ inline bool computeU() const { return m_computeFullU || m_computeThinU; }
+ /** \returns true if \a V (full or thin) is asked for in this SVD decomposition */
+ inline bool computeV() const { return m_computeFullV || m_computeThinV; }
+
+
+ inline Index rows() const { return m_rows; }
+ inline Index cols() const { return m_cols; }
+
+
+protected:
+ // return true if already allocated
+ bool allocate(Index rows, Index cols, unsigned int computationOptions) ;
+
+ MatrixUType m_matrixU;
+ MatrixVType m_matrixV;
+ SingularValuesType m_singularValues;
+ bool m_isInitialized, m_isAllocated;
+ bool m_computeFullU, m_computeThinU;
+ bool m_computeFullV, m_computeThinV;
+ unsigned int m_computationOptions;
+ Index m_nonzeroSingularValues, m_rows, m_cols, m_diagSize;
+
+
+ /** \brief Default Constructor.
+ *
+ * Default constructor of SVDBase
+ */
+ SVDBase()
+ : m_isInitialized(false),
+ m_isAllocated(false),
+ m_computationOptions(0),
+ m_rows(-1), m_cols(-1)
+ {}
+
+
+};
+
+
+template<typename MatrixType>
+bool SVDBase<MatrixType>::allocate(Index rows, Index cols, unsigned int computationOptions)
+{
+ eigen_assert(rows >= 0 && cols >= 0);
+
+ if (m_isAllocated &&
+ rows == m_rows &&
+ cols == m_cols &&
+ computationOptions == m_computationOptions)
+ {
+ return true;
+ }
+
+ m_rows = rows;
+ m_cols = cols;
+ m_isInitialized = false;
+ m_isAllocated = true;
+ m_computationOptions = computationOptions;
+ m_computeFullU = (computationOptions & ComputeFullU) != 0;
+ m_computeThinU = (computationOptions & ComputeThinU) != 0;
+ m_computeFullV = (computationOptions & ComputeFullV) != 0;
+ m_computeThinV = (computationOptions & ComputeThinV) != 0;
+ eigen_assert(!(m_computeFullU && m_computeThinU) && "SVDBase: you can't ask for both full and thin U");
+ eigen_assert(!(m_computeFullV && m_computeThinV) && "SVDBase: you can't ask for both full and thin V");
+ eigen_assert(EIGEN_IMPLIES(m_computeThinU || m_computeThinV, MatrixType::ColsAtCompileTime==Dynamic) &&
+ "SVDBase: thin U and V are only available when your matrix has a dynamic number of columns.");
+
+ m_diagSize = (std::min)(m_rows, m_cols);
+ m_singularValues.resize(m_diagSize);
+ if(RowsAtCompileTime==Dynamic)
+ m_matrixU.resize(m_rows, m_computeFullU ? m_rows
+ : m_computeThinU ? m_diagSize
+ : 0);
+ if(ColsAtCompileTime==Dynamic)
+ m_matrixV.resize(m_cols, m_computeFullV ? m_cols
+ : m_computeThinV ? m_diagSize
+ : 0);
+
+ return false;
+}
+
+}// end namespace
+
+#endif // EIGEN_SVD_H
diff --git a/unsupported/Eigen/src/SVD/TODOBdcsvd.txt b/unsupported/Eigen/src/SVD/TODOBdcsvd.txt
new file mode 100644
index 000000000..0bc9a46e6
--- /dev/null
+++ b/unsupported/Eigen/src/SVD/TODOBdcsvd.txt
@@ -0,0 +1,29 @@
+TO DO LIST
+
+
+
+(optional optimization) - do all the allocations in the allocate part
+ - support static matrices
+ - return a error at compilation time when using integer matrices (int, long, std::complex<int>, ...)
+
+to finish the algorithm :
+ -implement the last part of the algorithm as described on the reference paper.
+ You may find more information on that part on this paper
+
+ -to replace the call to JacobiSVD at the end of the divide algorithm, just after the call to
+ deflation.
+
+(suggested step by step resolution)
+ 0) comment the call to Jacobi in the last part of the divide method and everything right after
+ until the end of the method. What is commented can be a guideline to steps 3) 4) and 6)
+ 1) solve the secular equation (Characteristic equation) on the values that are not null (zi!=0 and di!=0), after the deflation
+ wich should be uncommented in the divide method
+ 2) remember the values of the singular values that are already computed (zi=0)
+ 3) assign the singular values found in m_computed at the right places (with the ones found in step 2) )
+ in decreasing order
+ 4) set the firstcol to zero (except the first element) in m_computed
+ 5) compute all the singular vectors when CompV is set to true and only the left vectors when
+ CompV is set to false
+ 6) multiply naiveU and naiveV to the right by the matrices found, only naiveU when CompV is set to
+ false, /!\ if CompU is false NaiveU has only 2 rows
+ 7) delete everything commented in step 0)
diff --git a/unsupported/Eigen/src/SVD/doneInBDCSVD.txt b/unsupported/Eigen/src/SVD/doneInBDCSVD.txt
new file mode 100644
index 000000000..8563ddab8
--- /dev/null
+++ b/unsupported/Eigen/src/SVD/doneInBDCSVD.txt
@@ -0,0 +1,21 @@
+This unsupported package is about a divide and conquer algorithm to compute SVD.
+
+The implementation follows as closely as possible the following reference paper :
+http://www.cs.yale.edu/publications/techreports/tr933.pdf
+
+The code documentation uses the same names for variables as the reference paper. The code, deflation included, is
+working but there are a few things that could be optimised as explained in the TODOBdsvd.
+
+In the code comments were put at the line where would be the third step of the algorithm so one could simply add the call
+of a function doing the last part of the algorithm and that would not require any knowledge of the part we implemented.
+
+In the TODOBdcsvd we explain what is the main difficulty of the last part and suggest a reference paper to help solve it.
+
+The implemented has trouble with fixed size matrices.
+
+In the actual implementation, it returns matrices of zero when ask to do a svd on an int matrix.
+
+
+Paper for the third part:
+http://www.stat.uchicago.edu/~lekheng/courses/302/classics/greengard-rokhlin.pdf
+
diff --git a/unsupported/Eigen/src/SparseExtra/BlockOfDynamicSparseMatrix.h b/unsupported/Eigen/src/SparseExtra/BlockOfDynamicSparseMatrix.h
index fd24a732d..e9ec746e3 100644
--- a/unsupported/Eigen/src/SparseExtra/BlockOfDynamicSparseMatrix.h
+++ b/unsupported/Eigen/src/SparseExtra/BlockOfDynamicSparseMatrix.h
@@ -12,6 +12,12 @@
namespace Eigen {
+#if 0
+
+// NOTE Have to be reimplemented as a specialization of BlockImpl< DynamicSparseMatrix<_Scalar, _Options, _Index>, ... >
+// See SparseBlock.h for an example
+
+
/***************************************************************************
* specialisation for DynamicSparseMatrix
***************************************************************************/
@@ -109,6 +115,8 @@ class SparseInnerVectorSet<DynamicSparseMatrix<_Scalar, _Options, _Index>, Size>
};
+#endif
+
} // end namespace Eigen
#endif // EIGEN_SPARSE_BLOCKFORDYNAMICMATRIX_H
diff --git a/unsupported/Eigen/src/SparseExtra/MarketIO.h b/unsupported/Eigen/src/SparseExtra/MarketIO.h
index de958de9f..7aafce928 100644
--- a/unsupported/Eigen/src/SparseExtra/MarketIO.h
+++ b/unsupported/Eigen/src/SparseExtra/MarketIO.h
@@ -116,7 +116,7 @@ inline bool getMarketHeader(const std::string& filename, int& sym, bool& iscompl
std::string line;
// The matrix header is always the first line in the file
- std::getline(in, line); assert(in.good());
+ std::getline(in, line); eigen_assert(in.good());
std::stringstream fmtline(line);
std::string substr[5];
@@ -200,11 +200,11 @@ bool loadMarketVector(VectorType& vec, const std::string& filename)
int n(0), col(0);
do
{ // Skip comments
- std::getline(in, line); assert(in.good());
+ std::getline(in, line); eigen_assert(in.good());
} while (line[0] == '%');
std::istringstream newline(line);
newline >> n >> col;
- assert(n>0 && col>0);
+ eigen_assert(n>0 && col>0);
vec.resize(n);
int i = 0;
Scalar value;
diff --git a/unsupported/Eigen/src/SparseExtra/MatrixMarketIterator.h b/unsupported/Eigen/src/SparseExtra/MatrixMarketIterator.h
index 4716b68e7..bf13cf21f 100644
--- a/unsupported/Eigen/src/SparseExtra/MatrixMarketIterator.h
+++ b/unsupported/Eigen/src/SparseExtra/MatrixMarketIterator.h
@@ -184,9 +184,20 @@ class MatrixMarketIterator
// if (S_ISDIR(st_buf.st_mode)) continue;
// Determine from the header if it is a matrix or a right hand side
- bool isvector,iscomplex;
+ bool isvector,iscomplex=false;
if(!getMarketHeader(curfile,m_sym,iscomplex,isvector)) continue;
if(isvector) continue;
+ if (!iscomplex)
+ {
+ if(internal::is_same<Scalar, std::complex<float> >::value || internal::is_same<Scalar, std::complex<double> >::value)
+ continue;
+ }
+ if (iscomplex)
+ {
+ if(internal::is_same<Scalar, float>::value || internal::is_same<Scalar, double>::value)
+ continue;
+ }
+
// Get the matrix name
std::string filename = m_curs_id->d_name;
diff --git a/unsupported/Eigen/src/Splines/Spline.h b/unsupported/Eigen/src/Splines/Spline.h
index 3680f013a..771f10432 100644
--- a/unsupported/Eigen/src/Splines/Spline.h
+++ b/unsupported/Eigen/src/Splines/Spline.h
@@ -16,7 +16,7 @@ namespace Eigen
{
/**
* \ingroup Splines_Module
- * \class Spline class
+ * \class Spline
* \brief A class representing multi-dimensional spline curves.
*
* The class represents B-splines with non-uniform knot vectors. Each control
@@ -50,6 +50,21 @@ namespace Eigen
/** \brief The data type representing the spline's control points. */
typedef typename SplineTraits<Spline>::ControlPointVectorType ControlPointVectorType;
+
+ /**
+ * \brief Creates a (constant) zero spline.
+ * For Splines with dynamic degree, the resulting degree will be 0.
+ **/
+ Spline()
+ : m_knots(1, (Degree==Dynamic ? 2 : 2*Degree+2))
+ , m_ctrls(ControlPointVectorType::Zero(2,(Degree==Dynamic ? 1 : Degree+1)))
+ {
+ // in theory this code can go to the initializer list but it will get pretty
+ // much unreadable ...
+ enum { MinDegree = (Degree==Dynamic ? 0 : Degree) };
+ m_knots.template segment<MinDegree+1>(0) = Array<Scalar,1,MinDegree+1>::Zero();
+ m_knots.template segment<MinDegree+1>(MinDegree+1) = Array<Scalar,1,MinDegree+1>::Ones();
+ }
/**
* \brief Creates a spline from a knot vector and control points.
@@ -280,11 +295,7 @@ namespace Eigen
enum { Order = SplineTraits<SplineType>::OrderAtCompileTime };
enum { DerivativeOrder = DerivativeType::ColsAtCompileTime };
- typedef typename SplineTraits<SplineType>::Scalar Scalar;
-
- typedef typename SplineTraits<SplineType>::BasisVectorType BasisVectorType;
typedef typename SplineTraits<SplineType>::ControlPointVectorType ControlPointVectorType;
-
typedef typename SplineTraits<SplineType,DerivativeOrder>::BasisDerivativeType BasisDerivativeType;
typedef typename BasisDerivativeType::ConstRowXpr BasisDerivativeRowXpr;
@@ -343,7 +354,6 @@ namespace Eigen
typedef typename SplineTraits<SplineType>::Scalar Scalar;
typedef typename SplineTraits<SplineType>::BasisVectorType BasisVectorType;
typedef typename SplineTraits<SplineType>::KnotVectorType KnotVectorType;
- typedef typename SplineTraits<SplineType>::ControlPointVectorType ControlPointVectorType;
const KnotVectorType& U = spline.knots();
diff --git a/unsupported/Eigen/src/Splines/SplineFitting.h b/unsupported/Eigen/src/Splines/SplineFitting.h
index 1b566332f..0265d532c 100644
--- a/unsupported/Eigen/src/Splines/SplineFitting.h
+++ b/unsupported/Eigen/src/Splines/SplineFitting.h
@@ -40,8 +40,6 @@ namespace Eigen
template <typename KnotVectorType>
void KnotAveraging(const KnotVectorType& parameters, DenseIndex degree, KnotVectorType& knots)
{
- typedef typename KnotVectorType::Scalar Scalar;
-
knots.resize(parameters.size()+degree+1);
for (DenseIndex j=1; j<parameters.size()-degree; ++j)
@@ -118,7 +116,6 @@ namespace Eigen
SplineType SplineFitting<SplineType>::Interpolate(const PointArrayType& pts, DenseIndex degree, const KnotVectorType& knot_parameters)
{
typedef typename SplineType::KnotVectorType::Scalar Scalar;
- typedef typename SplineType::BasisVectorType BasisVectorType;
typedef typename SplineType::ControlPointVectorType ControlPointVectorType;
typedef Matrix<Scalar,Dynamic,Dynamic> MatrixType;
diff --git a/unsupported/bench/bench_svd.cpp b/unsupported/bench/bench_svd.cpp
new file mode 100644
index 000000000..01d8231ae
--- /dev/null
+++ b/unsupported/bench/bench_svd.cpp
@@ -0,0 +1,123 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2013 Gauthier Brun <brun.gauthier@gmail.com>
+// Copyright (C) 2013 Nicolas Carre <nicolas.carre@ensimag.fr>
+// Copyright (C) 2013 Jean Ceccato <jean.ceccato@ensimag.fr>
+// Copyright (C) 2013 Pierre Zoppitelli <pierre.zoppitelli@ensimag.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/
+
+// Bench to compare the efficiency of SVD algorithms
+
+#include <iostream>
+#include <bench/BenchTimer.h>
+#include <unsupported/Eigen/SVD>
+
+
+using namespace Eigen;
+using namespace std;
+
+// number of computations of each algorithm before the print of the time
+#ifndef REPEAT
+#define REPEAT 10
+#endif
+
+// number of tests of the same type
+#ifndef NUMBER_SAMPLE
+#define NUMBER_SAMPLE 2
+#endif
+
+template<typename MatrixType>
+void bench_svd(const MatrixType& a = MatrixType())
+{
+ MatrixType m = MatrixType::Random(a.rows(), a.cols());
+ BenchTimer timerJacobi;
+ BenchTimer timerBDC;
+ timerJacobi.reset();
+ timerBDC.reset();
+
+ cout << " Only compute Singular Values" <<endl;
+ for (int k=1; k<=NUMBER_SAMPLE; ++k)
+ {
+ timerBDC.start();
+ for (int i=0; i<REPEAT; ++i)
+ {
+ BDCSVD<MatrixType> bdc_matrix(m);
+ }
+ timerBDC.stop();
+
+ timerJacobi.start();
+ for (int i=0; i<REPEAT; ++i)
+ {
+ JacobiSVD<MatrixType> jacobi_matrix(m);
+ }
+ timerJacobi.stop();
+
+
+ cout << "Sample " << k << " : " << REPEAT << " computations : Jacobi : " << fixed << timerJacobi.value() << "s ";
+ cout << " || " << " BDC : " << timerBDC.value() << "s " <<endl <<endl;
+
+ if (timerBDC.value() >= timerJacobi.value())
+ cout << "KO : BDC is " << timerJacobi.value() / timerBDC.value() << " times faster than Jacobi" <<endl;
+ else
+ cout << "OK : BDC is " << timerJacobi.value() / timerBDC.value() << " times faster than Jacobi" <<endl;
+
+ }
+ cout << " =================" <<endl;
+ std::cout<< std::endl;
+ timerJacobi.reset();
+ timerBDC.reset();
+ cout << " Computes rotaion matrix" <<endl;
+ for (int k=1; k<=NUMBER_SAMPLE; ++k)
+ {
+ timerBDC.start();
+ for (int i=0; i<REPEAT; ++i)
+ {
+ BDCSVD<MatrixType> bdc_matrix(m, ComputeFullU|ComputeFullV);
+ }
+ timerBDC.stop();
+
+ timerJacobi.start();
+ for (int i=0; i<REPEAT; ++i)
+ {
+ JacobiSVD<MatrixType> jacobi_matrix(m, ComputeFullU|ComputeFullV);
+ }
+ timerJacobi.stop();
+
+
+ cout << "Sample " << k << " : " << REPEAT << " computations : Jacobi : " << fixed << timerJacobi.value() << "s ";
+ cout << " || " << " BDC : " << timerBDC.value() << "s " <<endl <<endl;
+
+ if (timerBDC.value() >= timerJacobi.value())
+ cout << "KO : BDC is " << timerJacobi.value() / timerBDC.value() << " times faster than Jacobi" <<endl;
+ else
+ cout << "OK : BDC is " << timerJacobi.value() / timerBDC.value() << " times faster than Jacobi" <<endl;
+
+ }
+ std::cout<< std::endl;
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ std::cout<< std::endl;
+
+ std::cout<<"On a (Dynamic, Dynamic) (6, 6) Matrix" <<std::endl;
+ bench_svd<Matrix<double,Dynamic,Dynamic> >(Matrix<double,Dynamic,Dynamic>(6, 6));
+
+ std::cout<<"On a (Dynamic, Dynamic) (32, 32) Matrix" <<std::endl;
+ bench_svd<Matrix<double,Dynamic,Dynamic> >(Matrix<double,Dynamic,Dynamic>(32, 32));
+
+ //std::cout<<"On a (Dynamic, Dynamic) (128, 128) Matrix" <<std::endl;
+ //bench_svd<Matrix<double,Dynamic,Dynamic> >(Matrix<double,Dynamic,Dynamic>(128, 128));
+
+ std::cout<<"On a (Dynamic, Dynamic) (160, 160) Matrix" <<std::endl;
+ bench_svd<Matrix<double,Dynamic,Dynamic> >(Matrix<double,Dynamic,Dynamic>(160, 160));
+
+ std::cout<< "--------------------------------------------------------------------"<< std::endl;
+
+}
diff --git a/unsupported/doc/Doxyfile.in b/unsupported/doc/Doxyfile.in
deleted file mode 100644
index 1facf2985..000000000
--- a/unsupported/doc/Doxyfile.in
+++ /dev/null
@@ -1,1460 +0,0 @@
-# This file describes the settings to be used by the documentation system
-# doxygen (www.doxygen.org) for a project
-#
-# All text after a hash (#) is considered a comment and will be ignored
-# The format is:
-# TAG = value [value, ...]
-# For lists items can also be appended using:
-# TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (" ")
-
-#---------------------------------------------------------------------------
-# Project related configuration options
-#---------------------------------------------------------------------------
-
-# This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all
-# text before the first occurrence of this tag. Doxygen uses libiconv (or the
-# iconv built into libc) for the transcoding. See
-# http://www.gnu.org/software/libiconv for the list of possible encodings.
-
-DOXYFILE_ENCODING = UTF-8
-
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
-# by quotes) that should identify the project.
-
-PROJECT_NAME = Eigen - unsupported modules
-
-# The PROJECT_NUMBER tag can be used to enter a project or revision number.
-# This could be handy for archiving the generated documentation or
-# if some version control system is used.
-
-#EIGEN_VERSION is set in the root CMakeLists.txt
-PROJECT_NUMBER = "${EIGEN_VERSION}"
-
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
-# base path where the generated documentation will be put.
-# If a relative path is entered, it will be relative to the location
-# where doxygen was started. If left blank the current directory will be used.
-
-OUTPUT_DIRECTORY = "${Eigen_BINARY_DIR}/doc/unsupported"
-
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
-# 4096 sub-directories (in 2 levels) under the output directory of each output
-# format and will distribute the generated files over these directories.
-# Enabling this option can be useful when feeding doxygen a huge amount of
-# source files, where putting all generated files in the same directory would
-# otherwise cause performance problems for the file system.
-
-CREATE_SUBDIRS = NO
-
-# The OUTPUT_LANGUAGE tag is used to specify the language in which all
-# documentation generated by doxygen is written. Doxygen will use this
-# information to generate all constant output in the proper language.
-# The default language is English, other supported languages are:
-# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
-# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
-# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
-# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
-# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish,
-# and Ukrainian.
-
-OUTPUT_LANGUAGE = English
-
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
-# include brief member descriptions after the members that are listed in
-# the file and class documentation (similar to JavaDoc).
-# Set to NO to disable this.
-
-BRIEF_MEMBER_DESC = YES
-
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
-# the brief description of a member or function before the detailed description.
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
-# brief descriptions will be completely suppressed.
-
-REPEAT_BRIEF = YES
-
-# This tag implements a quasi-intelligent brief description abbreviator
-# that is used to form the text in various listings. Each string
-# in this list, if found as the leading text of the brief description, will be
-# stripped from the text and the result after processing the whole list, is
-# used as the annotated text. Otherwise, the brief description is used as-is.
-# If left blank, the following values are used ("$name" is automatically
-# replaced with the name of the entity): "The $name class" "The $name widget"
-# "The $name file" "is" "provides" "specifies" "contains"
-# "represents" "a" "an" "the"
-
-ABBREVIATE_BRIEF = "The $name class" \
- "The $name widget" \
- "The $name file" \
- is \
- provides \
- specifies \
- contains \
- represents \
- a \
- an \
- the
-
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
-# Doxygen will generate a detailed section even if there is only a brief
-# description.
-
-ALWAYS_DETAILED_SEC = NO
-
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
-# inherited members of a class in the documentation of that class as if those
-# members were ordinary class members. Constructors, destructors and assignment
-# operators of the base classes will not be shown.
-
-INLINE_INHERITED_MEMB = NO
-
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
-# path before files name in the file list and in the header files. If set
-# to NO the shortest path that makes the file name unique will be used.
-
-FULL_PATH_NAMES = NO
-
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
-# can be used to strip a user-defined part of the path. Stripping is
-# only done if one of the specified strings matches the left-hand part of
-# the path. The tag can be used to show relative paths in the file list.
-# If left blank the directory from which doxygen is run is used as the
-# path to strip.
-
-STRIP_FROM_PATH =
-
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
-# the path mentioned in the documentation of a class, which tells
-# the reader which header file to include in order to use a class.
-# If left blank only the name of the header file containing the class
-# definition is used. Otherwise one should specify the include paths that
-# are normally passed to the compiler using the -I flag.
-
-STRIP_FROM_INC_PATH =
-
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
-# (but less readable) file names. This can be useful is your file systems
-# doesn't support long names like on DOS, Mac, or CD-ROM.
-
-SHORT_NAMES = NO
-
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
-# will interpret the first line (until the first dot) of a JavaDoc-style
-# comment as the brief description. If set to NO, the JavaDoc
-# comments will behave just like regular Qt-style comments
-# (thus requiring an explicit @brief command for a brief description.)
-
-JAVADOC_AUTOBRIEF = NO
-
-# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
-# interpret the first line (until the first dot) of a Qt-style
-# comment as the brief description. If set to NO, the comments
-# will behave just like regular Qt-style comments (thus requiring
-# an explicit \brief command for a brief description.)
-
-QT_AUTOBRIEF = NO
-
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
-# treat a multi-line C++ special comment block (i.e. a block of //! or ///
-# comments) as a brief description. This used to be the default behaviour.
-# The new default is to treat a multi-line C++ comment block as a detailed
-# description. Set this tag to YES if you prefer the old behaviour instead.
-
-MULTILINE_CPP_IS_BRIEF = NO
-
-# If the DETAILS_AT_TOP tag is set to YES then Doxygen
-# will output the detailed description near the top, like JavaDoc.
-# If set to NO, the detailed description appears after the member
-# documentation.
-
-DETAILS_AT_TOP = YES
-
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
-# member inherits the documentation from any documented member that it
-# re-implements.
-
-INHERIT_DOCS = YES
-
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
-# a new page for each member. If set to NO, the documentation of a member will
-# be part of the file/class/namespace that contains it.
-
-SEPARATE_MEMBER_PAGES = NO
-
-# The TAB_SIZE tag can be used to set the number of spaces in a tab.
-# Doxygen uses this value to replace tabs by spaces in code fragments.
-
-TAB_SIZE = 8
-
-# This tag can be used to specify a number of aliases that acts
-# as commands in the documentation. An alias has the form "name=value".
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to
-# put the command \sideeffect (or @sideeffect) in the documentation, which
-# will result in a user-defined paragraph with heading "Side Effects:".
-# You can put \n's in the value part of an alias to insert newlines.
-
-ALIASES = "only_for_vectors=This is only for vectors (either row-vectors or column-vectors), i.e. matrices which are known at compile-time to have either one row or one column." \
- "array_module=This is defined in the %Array module. \code #include <Eigen/Array> \endcode" \
- "lu_module=This is defined in the %LU module. \code #include <Eigen/LU> \endcode" \
- "cholesky_module=This is defined in the %Cholesky module. \code #include <Eigen/Cholesky> \endcode" \
- "qr_module=This is defined in the %QR module. \code #include <Eigen/QR> \endcode" \
- "svd_module=This is defined in the %SVD module. \code #include <Eigen/SVD> \endcode" \
- "geometry_module=This is defined in the %Geometry module. \code #include <Eigen/Geometry> \endcode" \
- "label=\bug" \
- "nonstableyet=\warning This is not considered to be part of the stable public API yet. Changes may happen in future releases. See \ref Experimental \"Experimental parts of Eigen\""
-
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
-# sources only. Doxygen will then generate output that is more tailored for C.
-# For instance, some of the names that are used will be different. The list
-# of all members will be omitted, etc.
-
-OPTIMIZE_OUTPUT_FOR_C = NO
-
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
-# sources only. Doxygen will then generate output that is more tailored for
-# Java. For instance, namespaces will be presented as packages, qualified
-# scopes will look different, etc.
-
-OPTIMIZE_OUTPUT_JAVA = NO
-
-# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
-# sources only. Doxygen will then generate output that is more tailored for
-# Fortran.
-
-OPTIMIZE_FOR_FORTRAN = NO
-
-# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
-# sources. Doxygen will then generate output that is tailored for
-# VHDL.
-
-OPTIMIZE_OUTPUT_VHDL = NO
-
-# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
-# to include (a tag file for) the STL sources as input, then you should
-# set this tag to YES in order to let doxygen match functions declarations and
-# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
-# func(std::string) {}). This also make the inheritance and collaboration
-# diagrams that involve STL classes more complete and accurate.
-
-BUILTIN_STL_SUPPORT = NO
-
-# If you use Microsoft's C++/CLI language, you should set this option to YES to
-# enable parsing support.
-
-CPP_CLI_SUPPORT = NO
-
-# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
-# Doxygen will parse them like normal C++ but will assume all classes use public
-# instead of private inheritance when no explicit protection keyword is present.
-
-SIP_SUPPORT = NO
-
-# For Microsoft's IDL there are propget and propput attributes to indicate getter
-# and setter methods for a property. Setting this option to YES (the default)
-# will make doxygen to replace the get and set methods by a property in the
-# documentation. This will only work if the methods are indeed getting or
-# setting a simple type. If this is not the case, or you want to show the
-# methods anyway, you should set this option to NO.
-
-IDL_PROPERTY_SUPPORT = YES
-
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
-# member in the group (if any) for the other members of the group. By default
-# all members of a group must be documented explicitly.
-
-DISTRIBUTE_GROUP_DOC = NO
-
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
-# the same type (for instance a group of public functions) to be put as a
-# subgroup of that type (e.g. under the Public Functions section). Set it to
-# NO to prevent subgrouping. Alternatively, this can be done per class using
-# the \nosubgrouping command.
-
-SUBGROUPING = YES
-
-# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
-# is documented as struct, union, or enum with the name of the typedef. So
-# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
-# with name TypeT. When disabled the typedef will appear as a member of a file,
-# namespace, or class. And the struct will be named TypeS. This can typically
-# be useful for C code in case the coding convention dictates that all compound
-# types are typedef'ed and only the typedef is referenced, never the tag name.
-
-TYPEDEF_HIDES_STRUCT = NO
-
-#---------------------------------------------------------------------------
-# Build related configuration options
-#---------------------------------------------------------------------------
-
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
-# documentation are documented, even if no documentation was available.
-# Private class members and static file members will be hidden unless
-# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
-
-EXTRACT_ALL = NO
-
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
-# will be included in the documentation.
-
-EXTRACT_PRIVATE = NO
-
-# If the EXTRACT_STATIC tag is set to YES all static members of a file
-# will be included in the documentation.
-
-EXTRACT_STATIC = NO
-
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
-# defined locally in source files will be included in the documentation.
-# If set to NO only classes defined in header files are included.
-
-EXTRACT_LOCAL_CLASSES = NO
-
-# This flag is only useful for Objective-C code. When set to YES local
-# methods, which are defined in the implementation section but not in
-# the interface are included in the documentation.
-# If set to NO (the default) only methods in the interface are included.
-
-EXTRACT_LOCAL_METHODS = NO
-
-# If this flag is set to YES, the members of anonymous namespaces will be
-# extracted and appear in the documentation as a namespace called
-# 'anonymous_namespace{file}', where file will be replaced with the base
-# name of the file that contains the anonymous namespace. By default
-# anonymous namespace are hidden.
-
-EXTRACT_ANON_NSPACES = NO
-
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
-# undocumented members of documented classes, files or namespaces.
-# If set to NO (the default) these members will be included in the
-# various overviews, but no documentation section is generated.
-# This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_MEMBERS = NO
-
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
-# undocumented classes that are normally visible in the class hierarchy.
-# If set to NO (the default) these classes will be included in the various
-# overviews. This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_CLASSES = YES
-
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
-# friend (class|struct|union) declarations.
-# If set to NO (the default) these declarations will be included in the
-# documentation.
-
-HIDE_FRIEND_COMPOUNDS = YES
-
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
-# documentation blocks found inside the body of a function.
-# If set to NO (the default) these blocks will be appended to the
-# function's detailed documentation block.
-
-HIDE_IN_BODY_DOCS = NO
-
-# The INTERNAL_DOCS tag determines if documentation
-# that is typed after a \internal command is included. If the tag is set
-# to NO (the default) then the documentation will be excluded.
-# Set it to YES to include the internal documentation.
-
-INTERNAL_DOCS = NO
-
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
-# file names in lower-case letters. If set to YES upper-case letters are also
-# allowed. This is useful if you have classes or files whose names only differ
-# in case and if your file system supports case sensitive file names. Windows
-# and Mac users are advised to set this option to NO.
-
-CASE_SENSE_NAMES = YES
-
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
-# will show members with their full class and namespace scopes in the
-# documentation. If set to YES the scope will be hidden.
-
-HIDE_SCOPE_NAMES = YES
-
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
-# will put a list of the files that are included by a file in the documentation
-# of that file.
-
-SHOW_INCLUDE_FILES = YES
-
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
-# is inserted in the documentation for inline members.
-
-INLINE_INFO = YES
-
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
-# will sort the (detailed) documentation of file and class members
-# alphabetically by member name. If set to NO the members will appear in
-# declaration order.
-
-SORT_MEMBER_DOCS = YES
-
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
-# brief documentation of file, namespace and class members alphabetically
-# by member name. If set to NO (the default) the members will appear in
-# declaration order.
-
-SORT_BRIEF_DOCS = YES
-
-# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
-# hierarchy of group names into alphabetical order. If set to NO (the default)
-# the group names will appear in their defined order.
-
-SORT_GROUP_NAMES = NO
-
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
-# sorted by fully-qualified names, including namespaces. If set to
-# NO (the default), the class list will be sorted only by class name,
-# not including the namespace part.
-# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the
-# alphabetical list.
-
-SORT_BY_SCOPE_NAME = NO
-
-# The GENERATE_TODOLIST tag can be used to enable (YES) or
-# disable (NO) the todo list. This list is created by putting \todo
-# commands in the documentation.
-
-GENERATE_TODOLIST = NO
-
-# The GENERATE_TESTLIST tag can be used to enable (YES) or
-# disable (NO) the test list. This list is created by putting \test
-# commands in the documentation.
-
-GENERATE_TESTLIST = NO
-
-# The GENERATE_BUGLIST tag can be used to enable (YES) or
-# disable (NO) the bug list. This list is created by putting \bug
-# commands in the documentation.
-
-GENERATE_BUGLIST = NO
-
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
-# disable (NO) the deprecated list. This list is created by putting
-# \deprecated commands in the documentation.
-
-GENERATE_DEPRECATEDLIST= NO
-
-# The ENABLED_SECTIONS tag can be used to enable conditional
-# documentation sections, marked by \if sectionname ... \endif.
-
-ENABLED_SECTIONS =
-
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
-# the initial value of a variable or define consists of for it to appear in
-# the documentation. If the initializer consists of more lines than specified
-# here it will be hidden. Use a value of 0 to hide initializers completely.
-# The appearance of the initializer of individual variables and defines in the
-# documentation can be controlled using \showinitializer or \hideinitializer
-# command in the documentation regardless of this setting.
-
-MAX_INITIALIZER_LINES = 0
-
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
-# at the bottom of the documentation of classes and structs. If set to YES the
-# list will mention the files that were used to generate the documentation.
-
-SHOW_USED_FILES = YES
-
-# If the sources in your project are distributed over multiple directories
-# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
-# in the documentation. The default is NO.
-
-SHOW_DIRECTORIES = NO
-
-# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
-# This will remove the Files entry from the Quick Index and from the
-# Folder Tree View (if specified). The default is YES.
-
-SHOW_FILES = YES
-
-# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
-# Namespaces page. This will remove the Namespaces entry from the Quick Index
-# and from the Folder Tree View (if specified). The default is YES.
-
-SHOW_NAMESPACES = NO
-
-# The FILE_VERSION_FILTER tag can be used to specify a program or script that
-# doxygen should invoke to get the current version for each file (typically from
-# the version control system). Doxygen will invoke the program by executing (via
-# popen()) the command <command> <input-file>, where <command> is the value of
-# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
-# provided by doxygen. Whatever the program writes to standard output
-# is used as the file version. See the manual for examples.
-
-FILE_VERSION_FILTER =
-
-#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
-#---------------------------------------------------------------------------
-
-# The QUIET tag can be used to turn on/off the messages that are generated
-# by doxygen. Possible values are YES and NO. If left blank NO is used.
-
-QUIET = NO
-
-# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated by doxygen. Possible values are YES and NO. If left blank
-# NO is used.
-
-WARNINGS = YES
-
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
-# automatically be disabled.
-
-WARN_IF_UNDOCUMENTED = NO
-
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some
-# parameters in a documented function, or documenting parameters that
-# don't exist or using markup commands wrongly.
-
-WARN_IF_DOC_ERROR = YES
-
-# This WARN_NO_PARAMDOC option can be abled to get warnings for
-# functions that are documented, but have no documentation for their parameters
-# or return value. If set to NO (the default) doxygen will only warn about
-# wrong or incomplete parameter documentation, but not about the absence of
-# documentation.
-
-WARN_NO_PARAMDOC = NO
-
-# The WARN_FORMAT tag determines the format of the warning messages that
-# doxygen can produce. The string should contain the $file, $line, and $text
-# tags, which will be replaced by the file and line number from which the
-# warning originated and the warning text. Optionally the format may contain
-# $version, which will be replaced by the version of the file (if it could
-# be obtained via FILE_VERSION_FILTER)
-
-WARN_FORMAT = "$file:$line: $text"
-
-# The WARN_LOGFILE tag can be used to specify a file to which warning
-# and error messages should be written. If left blank the output is written
-# to stderr.
-
-WARN_LOGFILE =
-
-#---------------------------------------------------------------------------
-# configuration options related to the input files
-#---------------------------------------------------------------------------
-
-# The INPUT tag can be used to specify the files and/or directories that contain
-# documented source files. You may enter file names like "myfile.cpp" or
-# directories like "/usr/src/myproject". Separate the files or directories
-# with spaces.
-
-INPUT = "${Eigen_SOURCE_DIR}/unsupported/Eigen" \
- "${Eigen_SOURCE_DIR}/unsupported/doc"
-
-# This tag can be used to specify the character encoding of the source files
-# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
-# also the default input encoding. Doxygen uses libiconv (or the iconv built
-# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
-# the list of possible encodings.
-
-INPUT_ENCODING = UTF-8
-
-# If the value of the INPUT tag contains directories, you can use the
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank the following patterns are tested:
-# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
-# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
-
-FILE_PATTERNS = *
-
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories
-# should be searched for input files as well. Possible values are YES and NO.
-# If left blank NO is used.
-
-RECURSIVE = YES
-
-# The EXCLUDE tag can be used to specify files and/or directories that should
-# excluded from the INPUT source files. This way you can easily exclude a
-# subdirectory from a directory tree whose root is specified with the INPUT tag.
-
-EXCLUDE = "${Eigen_SOURCE_DIR}/unsupported/doc/examples" \
- "${Eigen_SOURCE_DIR}/unsupported/doc/snippets"
-
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
-# directories that are symbolic links (a Unix filesystem feature) are excluded
-# from the input.
-
-EXCLUDE_SYMLINKS = NO
-
-# If the value of the INPUT tag contains directories, you can use the
-# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
-# certain files from those directories. Note that the wildcards are matched
-# against the file with absolute path, so to exclude all test directories
-# for example use the pattern */test/*
-
-EXCLUDE_PATTERNS = CMake* \
- *.txt \
- *.sh \
- *.diff \
- *.orig \
- diff \
- *~
-
-# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
-# (namespaces, classes, functions, etc.) that should be excluded from the
-# output. The symbol name can be a fully qualified name, a word, or if the
-# wildcard * is used, a substring. Examples: ANamespace, AClass,
-# AClass::ANamespace, ANamespace::*Test
-
-EXCLUDE_SYMBOLS = MatrixBase<* MapBase<* RotationBase<* Matrix<*
-
-# The EXAMPLE_PATH tag can be used to specify one or more files or
-# directories that contain example code fragments that are included (see
-# the \include command).
-
-EXAMPLE_PATH = "${Eigen_SOURCE_DIR}/doc/snippets" \
- "${Eigen_BINARY_DIR}/doc/snippets" \
- "${Eigen_SOURCE_DIR}/doc/examples" \
- "${Eigen_BINARY_DIR}/doc/examples" \
- "${Eigen_SOURCE_DIR}/unsupported/doc/snippets" \
- "${Eigen_BINARY_DIR}/unsupported/doc/snippets" \
- "${Eigen_SOURCE_DIR}/unsupported/doc/examples" \
- "${Eigen_BINARY_DIR}/unsupported/doc/examples"
-
-# If the value of the EXAMPLE_PATH tag contains directories, you can use the
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank all files are included.
-
-EXAMPLE_PATTERNS = *
-
-# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
-# searched for input files to be used with the \include or \dontinclude
-# commands irrespective of the value of the RECURSIVE tag.
-# Possible values are YES and NO. If left blank NO is used.
-
-EXAMPLE_RECURSIVE = NO
-
-# The IMAGE_PATH tag can be used to specify one or more files or
-# directories that contain image that are included in the documentation (see
-# the \image command).
-
-IMAGE_PATH =
-
-# The INPUT_FILTER tag can be used to specify a program that doxygen should
-# invoke to filter for each input file. Doxygen will invoke the filter program
-# by executing (via popen()) the command <filter> <input-file>, where <filter>
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
-# input file. Doxygen will then use the output that the filter program writes
-# to standard output. If FILTER_PATTERNS is specified, this tag will be
-# ignored.
-
-INPUT_FILTER =
-
-# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
-# basis. Doxygen will compare the file name with each pattern and apply the
-# filter if there is a match. The filters are a list of the form:
-# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
-# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
-# is applied to all files.
-
-FILTER_PATTERNS =
-
-# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER) will be used to filter the input files when producing source
-# files to browse (i.e. when SOURCE_BROWSER is set to YES).
-
-FILTER_SOURCE_FILES = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to source browsing
-#---------------------------------------------------------------------------
-
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will
-# be generated. Documented entities will be cross-referenced with these sources.
-# Note: To get rid of all source code in the generated output, make sure also
-# VERBATIM_HEADERS is set to NO.
-
-SOURCE_BROWSER = NO
-
-# Setting the INLINE_SOURCES tag to YES will include the body
-# of functions and classes directly in the documentation.
-
-INLINE_SOURCES = NO
-
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
-# doxygen to hide any special comment blocks from generated source code
-# fragments. Normal C and C++ comments will always remain visible.
-
-STRIP_CODE_COMMENTS = YES
-
-# If the REFERENCED_BY_RELATION tag is set to YES
-# then for each documented function all documented
-# functions referencing it will be listed.
-
-REFERENCED_BY_RELATION = YES
-
-# If the REFERENCES_RELATION tag is set to YES
-# then for each documented function all documented entities
-# called/used by that function will be listed.
-
-REFERENCES_RELATION = YES
-
-# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
-# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
-# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
-# link to the source code. Otherwise they will link to the documentstion.
-
-REFERENCES_LINK_SOURCE = YES
-
-# If the USE_HTAGS tag is set to YES then the references to source code
-# will point to the HTML generated by the htags(1) tool instead of doxygen
-# built-in source browser. The htags tool is part of GNU's global source
-# tagging system (see http://www.gnu.org/software/global/global.html). You
-# will need version 4.8.6 or higher.
-
-USE_HTAGS = NO
-
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
-# will generate a verbatim copy of the header file for each class for
-# which an include is specified. Set to NO to disable this.
-
-VERBATIM_HEADERS = YES
-
-#---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
-#---------------------------------------------------------------------------
-
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
-# of all compounds will be generated. Enable this if the project
-# contains a lot of classes, structs, unions or interfaces.
-
-ALPHABETICAL_INDEX = NO
-
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
-# in which this list will be split (can be a number in the range [1..20])
-
-COLS_IN_ALPHA_INDEX = 5
-
-# In case all classes in a project start with a common prefix, all
-# classes will be put under the same header in the alphabetical index.
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
-# should be ignored while generating the index headers.
-
-IGNORE_PREFIX =
-
-#---------------------------------------------------------------------------
-# configuration options related to the HTML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
-# generate HTML output.
-
-GENERATE_HTML = YES
-
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `html' will be used as the default path.
-
-HTML_OUTPUT = "${Eigen_BINARY_DIR}/doc/html/unsupported"
-
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
-# doxygen will generate files with .html extension.
-
-HTML_FILE_EXTENSION = .html
-
-# The HTML_HEADER tag can be used to specify a personal HTML header for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard header.
-
-HTML_HEADER = "${Eigen_BINARY_DIR}/doc/eigendoxy_header.html"
-
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard footer.
-
-# the footer has not been customized yet, so let's use the default one
-# ${Eigen_BINARY_DIR}/doc/eigendoxy_footer.html
-HTML_FOOTER =
-
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
-# style sheet that is used by each HTML page. It can be used to
-# fine-tune the look of the HTML output. If the tag is left blank doxygen
-# will generate a default style sheet. Note that doxygen will try to copy
-# the style sheet file to the HTML output directory, so don't put your own
-# stylesheet in the HTML output directory as well, or it will be erased!
-
-HTML_STYLESHEET = "${Eigen_SOURCE_DIR}/doc/eigendoxy.css"
-
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
-# files or namespaces will be aligned in HTML using tables. If set to
-# NO a bullet list will be used.
-
-HTML_ALIGN_MEMBERS = YES
-
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files
-# will be generated that can be used as input for tools like the
-# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
-# of the generated HTML documentation.
-
-GENERATE_HTMLHELP = NO
-
-# If the GENERATE_DOCSET tag is set to YES, additional index files
-# will be generated that can be used as input for Apple's Xcode 3
-# integrated development environment, introduced with OSX 10.5 (Leopard).
-# To create a documentation set, doxygen will generate a Makefile in the
-# HTML output directory. Running make will produce the docset in that
-# directory and running "make install" will install the docset in
-# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
-# it at startup.
-
-GENERATE_DOCSET = NO
-
-# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
-# feed. A documentation feed provides an umbrella under which multiple
-# documentation sets from a single provider (such as a company or product suite)
-# can be grouped.
-
-DOCSET_FEEDNAME = "Doxygen generated docs"
-
-# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
-# should uniquely identify the documentation set bundle. This should be a
-# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
-# will append .docset to the name.
-
-DOCSET_BUNDLE_ID = org.doxygen.Project
-
-# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
-# documentation will contain sections that can be hidden and shown after the
-# page has loaded. For this to work a browser that supports
-# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
-# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
-
-HTML_DYNAMIC_SECTIONS = NO
-
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
-# be used to specify the file name of the resulting .chm file. You
-# can add a path in front of the file if the result should not be
-# written to the html output directory.
-
-CHM_FILE =
-
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
-# be used to specify the location (absolute path including file name) of
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
-# the HTML help compiler on the generated index.hhp.
-
-HHC_LOCATION =
-
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
-# controls if a separate .chi index file is generated (YES) or that
-# it should be included in the master .chm file (NO).
-
-GENERATE_CHI = NO
-
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
-# is used to encode HtmlHelp index (hhk), content (hhc) and project file
-# content.
-
-CHM_INDEX_ENCODING =
-
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
-# controls whether a binary table of contents is generated (YES) or a
-# normal table of contents (NO) in the .chm file.
-
-BINARY_TOC = NO
-
-# The TOC_EXPAND flag can be set to YES to add extra items for group members
-# to the contents of the HTML help documentation and to the tree view.
-
-TOC_EXPAND = NO
-
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
-# top of each HTML page. The value NO (the default) enables the index and
-# the value YES disables it.
-
-DISABLE_INDEX = NO
-
-# This tag can be used to set the number of enum values (range [1..20])
-# that doxygen will group on one line in the generated HTML documentation.
-
-ENUM_VALUES_PER_LINE = 1
-
-# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
-# structure should be generated to display hierarchical information.
-# If the tag value is set to FRAME, a side panel will be generated
-# containing a tree-like index structure (just like the one that
-# is generated for HTML Help). For this to work a browser that supports
-# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
-# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
-# probably better off using the HTML help feature. Other possible values
-# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
-# and Class Hiererachy pages using a tree view instead of an ordered list;
-# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
-# disables this behavior completely. For backwards compatibility with previous
-# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
-# respectively.
-
-GENERATE_TREEVIEW = NO
-
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
-# used to set the initial width (in pixels) of the frame in which the tree
-# is shown.
-
-TREEVIEW_WIDTH = 250
-
-# Use this tag to change the font size of Latex formulas included
-# as images in the HTML documentation. The default is 10. Note that
-# when you change the font size after a successful doxygen run you need
-# to manually remove any form_*.png images from the HTML output directory
-# to force them to be regenerated.
-
-FORMULA_FONTSIZE = 12
-
-#---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
-# generate Latex output.
-
-GENERATE_LATEX = NO
-
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `latex' will be used as the default path.
-
-LATEX_OUTPUT = latex
-
-# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
-# invoked. If left blank `latex' will be used as the default command name.
-
-LATEX_CMD_NAME = latex
-
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
-# generate index for LaTeX. If left blank `makeindex' will be used as the
-# default command name.
-
-MAKEINDEX_CMD_NAME = makeindex
-
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
-# LaTeX documents. This may be useful for small projects and may help to
-# save some trees in general.
-
-COMPACT_LATEX = NO
-
-# The PAPER_TYPE tag can be used to set the paper type that is used
-# by the printer. Possible values are: a4, a4wide, letter, legal and
-# executive. If left blank a4wide will be used.
-
-PAPER_TYPE = a4wide
-
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
-# packages that should be included in the LaTeX output.
-
-EXTRA_PACKAGES = amssymb \
- amsmath
-
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
-# the generated latex document. The header should contain everything until
-# the first chapter. If it is left blank doxygen will generate a
-# standard header. Notice: only use this tag if you know what you are doing!
-
-LATEX_HEADER =
-
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will
-# contain links (just like the HTML output) instead of page references
-# This makes the output suitable for online browsing using a pdf viewer.
-
-PDF_HYPERLINKS = NO
-
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
-# plain latex in the generated Makefile. Set this option to YES to get a
-# higher quality PDF documentation.
-
-USE_PDFLATEX = NO
-
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
-# command to the generated LaTeX files. This will instruct LaTeX to keep
-# running if errors occur, instead of asking the user for help.
-# This option is also used when generating formulas in HTML.
-
-LATEX_BATCHMODE = NO
-
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not
-# include the index chapters (such as File Index, Compound Index, etc.)
-# in the output.
-
-LATEX_HIDE_INDICES = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the RTF output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
-# The RTF output is optimized for Word 97 and may not look very pretty with
-# other RTF readers or editors.
-
-GENERATE_RTF = NO
-
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `rtf' will be used as the default path.
-
-RTF_OUTPUT = rtf
-
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
-# RTF documents. This may be useful for small projects and may help to
-# save some trees in general.
-
-COMPACT_RTF = NO
-
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
-# will contain hyperlink fields. The RTF file will
-# contain links (just like the HTML output) instead of page references.
-# This makes the output suitable for online browsing using WORD or other
-# programs which support those fields.
-# Note: wordpad (write) and others do not support links.
-
-RTF_HYPERLINKS = NO
-
-# Load stylesheet definitions from file. Syntax is similar to doxygen's
-# config file, i.e. a series of assignments. You only have to provide
-# replacements, missing definitions are set to their default value.
-
-RTF_STYLESHEET_FILE =
-
-# Set optional variables used in the generation of an rtf document.
-# Syntax is similar to doxygen's config file.
-
-RTF_EXTENSIONS_FILE =
-
-#---------------------------------------------------------------------------
-# configuration options related to the man page output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
-# generate man pages
-
-GENERATE_MAN = NO
-
-# The MAN_OUTPUT tag is used to specify where the man pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `man' will be used as the default path.
-
-MAN_OUTPUT = man
-
-# The MAN_EXTENSION tag determines the extension that is added to
-# the generated man pages (default is the subroutine's section .3)
-
-MAN_EXTENSION = .3
-
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
-# then it will generate one additional man file for each entity
-# documented in the real man page(s). These additional files
-# only source the real man page, but without them the man command
-# would be unable to find the correct page. The default is NO.
-
-MAN_LINKS = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the XML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_XML tag is set to YES Doxygen will
-# generate an XML file that captures the structure of
-# the code including all documentation.
-
-GENERATE_XML = NO
-
-# The XML_OUTPUT tag is used to specify where the XML pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `xml' will be used as the default path.
-
-XML_OUTPUT = xml
-
-# The XML_SCHEMA tag can be used to specify an XML schema,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
-
-XML_SCHEMA =
-
-# The XML_DTD tag can be used to specify an XML DTD,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
-
-XML_DTD =
-
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
-# dump the program listings (including syntax highlighting
-# and cross-referencing information) to the XML output. Note that
-# enabling this will significantly increase the size of the XML output.
-
-XML_PROGRAMLISTING = YES
-
-#---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
-# generate an AutoGen Definitions (see autogen.sf.net) file
-# that captures the structure of the code including all
-# documentation. Note that this feature is still experimental
-# and incomplete at the moment.
-
-GENERATE_AUTOGEN_DEF = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the Perl module output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will
-# generate a Perl module file that captures the structure of
-# the code including all documentation. Note that this
-# feature is still experimental and incomplete at the
-# moment.
-
-GENERATE_PERLMOD = NO
-
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able
-# to generate PDF and DVI output from the Perl module output.
-
-PERLMOD_LATEX = NO
-
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
-# nicely formatted so it can be parsed by a human reader. This is useful
-# if you want to understand what is going on. On the other hand, if this
-# tag is set to NO the size of the Perl module output will be much smaller
-# and Perl will parse it just the same.
-
-PERLMOD_PRETTY = YES
-
-# The names of the make variables in the generated doxyrules.make file
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
-# This is useful so different doxyrules.make files included by the same
-# Makefile don't overwrite each other's variables.
-
-PERLMOD_MAKEVAR_PREFIX =
-
-#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor
-#---------------------------------------------------------------------------
-
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
-# evaluate all C-preprocessor directives found in the sources and include
-# files.
-
-ENABLE_PREPROCESSING = YES
-
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
-# names in the source code. If set to NO (the default) only conditional
-# compilation will be performed. Macro expansion can be done in a controlled
-# way by setting EXPAND_ONLY_PREDEF to YES.
-
-MACRO_EXPANSION = YES
-
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
-# then the macro expansion is limited to the macros specified with the
-# PREDEFINED and EXPAND_AS_DEFINED tags.
-
-EXPAND_ONLY_PREDEF = YES
-
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
-# in the INCLUDE_PATH (see below) will be search if a #include is found.
-
-SEARCH_INCLUDES = YES
-
-# The INCLUDE_PATH tag can be used to specify one or more directories that
-# contain include files that are not input files but should be processed by
-# the preprocessor.
-
-INCLUDE_PATH =
-
-# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
-# patterns (like *.h and *.hpp) to filter out the header-files in the
-# directories. If left blank, the patterns specified with FILE_PATTERNS will
-# be used.
-
-INCLUDE_FILE_PATTERNS =
-
-# The PREDEFINED tag can be used to specify one or more macro names that
-# are defined before the preprocessor is started (similar to the -D option of
-# gcc). The argument of the tag is a list of macros of the form: name
-# or name=definition (no spaces). If the definition and the = are
-# omitted =1 is assumed. To prevent a macro definition from being
-# undefined via #undef or recursively expanded use the := operator
-# instead of the = operator.
-
-PREDEFINED = EIGEN_EMPTY_STRUCT \
- EIGEN_PARSED_BY_DOXYGEN \
- EIGEN_VECTORIZE \
- EIGEN_QT_SUPPORT \
- EIGEN_STRONG_INLINE=inline
-
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
-# this tag can be used to specify a list of macro names that should be expanded.
-# The macro definition that is found in the sources will be used.
-# Use the PREDEFINED tag if you want to use a different macro definition.
-
-EXPAND_AS_DEFINED = EIGEN_MAKE_SCALAR_OPS \
- EIGEN_MAKE_TYPEDEFS \
- EIGEN_MAKE_TYPEDEFS_ALL_SIZES \
- EIGEN_CWISE_UNOP_RETURN_TYPE \
- EIGEN_CWISE_BINOP_RETURN_TYPE
-
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
-# doxygen's preprocessor will remove all function-like macros that are alone
-# on a line, have an all uppercase name, and do not end with a semicolon. Such
-# function macros are typically used for boiler-plate code, and will confuse
-# the parser if not removed.
-
-SKIP_FUNCTION_MACROS = YES
-
-#---------------------------------------------------------------------------
-# Configuration::additions related to external references
-#---------------------------------------------------------------------------
-
-# The TAGFILES option can be used to specify one or more tagfiles.
-# Optionally an initial location of the external documentation
-# can be added for each tagfile. The format of a tag file without
-# this location is as follows:
-# TAGFILES = file1 file2 ...
-# Adding location for the tag files is done as follows:
-# TAGFILES = file1=loc1 "file2 = loc2" ...
-# where "loc1" and "loc2" can be relative or absolute paths or
-# URLs. If a location is present for each tag, the installdox tool
-# does not have to be run to correct the links.
-# Note that each tag file must have a unique name
-# (where the name does NOT include the path)
-# If a tag file is not located in the directory in which doxygen
-# is run, you must also specify the path to the tagfile here.
-
-TAGFILES = "${Eigen_BINARY_DIR}/doc/eigen.doxytags"=../
-
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create
-# a tag file that is based on the input files it reads.
-
-GENERATE_TAGFILE = "${Eigen_BINARY_DIR}/doc/eigen-unsupported.doxytags"
-
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed
-# in the class index. If set to NO only the inherited external classes
-# will be listed.
-
-ALLEXTERNALS = NO
-
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
-# in the modules index. If set to NO, only the current project's groups will
-# be listed.
-
-EXTERNAL_GROUPS = YES
-
-# The PERL_PATH should be the absolute path and name of the perl script
-# interpreter (i.e. the result of `which perl').
-
-PERL_PATH = /usr/bin/perl
-
-#---------------------------------------------------------------------------
-# Configuration options related to the dot tool
-#---------------------------------------------------------------------------
-
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
-# or super classes. Setting the tag to NO turns the diagrams off. Note that
-# this option is superseded by the HAVE_DOT option below. This is only a
-# fallback. It is recommended to install and use dot, since it yields more
-# powerful graphs.
-
-CLASS_DIAGRAMS = NO
-
-# You can define message sequence charts within doxygen comments using the \msc
-# command. Doxygen will then run the mscgen tool (see
-# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
-# documentation. The MSCGEN_PATH tag allows you to specify the directory where
-# the mscgen tool resides. If left empty the tool is assumed to be found in the
-# default search path.
-
-MSCGEN_PATH = NO
-
-# If set to YES, the inheritance and collaboration graphs will hide
-# inheritance and usage relations if the target is undocumented
-# or is not a class.
-
-HIDE_UNDOC_RELATIONS = NO
-
-# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
-# available from the path. This tool is part of Graphviz, a graph visualization
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section
-# have no effect if this option is set to NO (the default)
-
-HAVE_DOT = NO
-
-# By default doxygen will write a font called FreeSans.ttf to the output
-# directory and reference it in all dot files that doxygen generates. This
-# font does not include all possible unicode characters however, so when you need
-# these (or just want a differently looking font) you can specify the font name
-# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
-# which can be done by putting it in a standard location or by setting the
-# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
-# containing the font.
-
-DOT_FONTNAME = FreeSans
-
-# By default doxygen will tell dot to use the output directory to look for the
-# FreeSans.ttf font (which doxygen will put there itself). If you specify a
-# different font using DOT_FONTNAME you can set the path where dot
-# can find it using this tag.
-
-DOT_FONTPATH =
-
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect inheritance relations. Setting this tag to YES will force the
-# the CLASS_DIAGRAMS tag to NO.
-
-CLASS_GRAPH = NO
-
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect implementation dependencies (inheritance, containment, and
-# class references variables) of the class with other documented classes.
-
-COLLABORATION_GRAPH = NO
-
-# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for groups, showing the direct groups dependencies
-
-GROUP_GRAPHS = NO
-
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
-# collaboration diagrams in a style similar to the OMG's Unified Modeling
-# Language.
-
-UML_LOOK = NO
-
-# If set to YES, the inheritance and collaboration graphs will show the
-# relations between templates and their instances.
-
-TEMPLATE_RELATIONS = NO
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
-# tags are set to YES then doxygen will generate a graph for each documented
-# file showing the direct and indirect include dependencies of the file with
-# other documented files.
-
-INCLUDE_GRAPH = NO
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
-# documented header file showing the documented files that directly or
-# indirectly include this file.
-
-INCLUDED_BY_GRAPH = NO
-
-# If the CALL_GRAPH and HAVE_DOT options are set to YES then
-# doxygen will generate a call dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable call graphs
-# for selected functions only using the \callgraph command.
-
-CALL_GRAPH = NO
-
-# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
-# doxygen will generate a caller dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable caller
-# graphs for selected functions only using the \callergraph command.
-
-CALLER_GRAPH = NO
-
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
-# will graphical hierarchy of all classes instead of a textual one.
-
-GRAPHICAL_HIERARCHY = NO
-
-# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
-# then doxygen will show the dependencies a directory has on other directories
-# in a graphical way. The dependency relations are determined by the #include
-# relations between the files in the directories.
-
-DIRECTORY_GRAPH = NO
-
-# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot. Possible values are png, jpg, or gif
-# If left blank png will be used.
-
-DOT_IMAGE_FORMAT = png
-
-# The tag DOT_PATH can be used to specify the path where the dot tool can be
-# found. If left blank, it is assumed the dot tool can be found in the path.
-
-DOT_PATH =
-
-# The DOTFILE_DIRS tag can be used to specify one or more directories that
-# contain dot files that are included in the documentation (see the
-# \dotfile command).
-
-DOTFILE_DIRS =
-
-# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
-# nodes that will be shown in the graph. If the number of nodes in a graph
-# becomes larger than this value, doxygen will truncate the graph, which is
-# visualized by representing a node as a red box. Note that doxygen if the
-# number of direct children of the root node in a graph is already larger than
-# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
-# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
-
-DOT_GRAPH_MAX_NODES = 50
-
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
-# graphs generated by dot. A depth value of 3 means that only nodes reachable
-# from the root by following a path via at most 3 edges will be shown. Nodes
-# that lay further from the root node will be omitted. Note that setting this
-# option to 1 or 2 may greatly reduce the computation time needed for large
-# code bases. Also note that the size of a graph can be further restricted by
-# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
-
-MAX_DOT_GRAPH_DEPTH = 1000
-
-# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is enabled by default, which results in a transparent
-# background. Warning: Depending on the platform used, enabling this option
-# may lead to badly anti-aliased labels on the edges of a graph (i.e. they
-# become hard to read).
-
-DOT_TRANSPARENT = NO
-
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
-# files in one run (i.e. multiple -o and -T options on the command line). This
-# makes dot run faster, but since only newer versions of dot (>1.8.10)
-# support this, this feature is disabled by default.
-
-DOT_MULTI_TARGETS = NO
-
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
-# generate a legend page explaining the meaning of the various boxes and
-# arrows in the dot generated graphs.
-
-GENERATE_LEGEND = NO
-
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
-# remove the intermediate dot files that are used to generate
-# the various graphs.
-
-DOT_CLEANUP = NO
-
-#---------------------------------------------------------------------------
-# Configuration::additions related to the search engine
-#---------------------------------------------------------------------------
-
-# The SEARCHENGINE tag specifies whether or not a search engine should be
-# used. If set to NO the values of all tags below this one will be ignored.
-
-SEARCHENGINE = NO
diff --git a/unsupported/doc/Overview.dox b/unsupported/doc/Overview.dox
index 458b507b5..d048377df 100644
--- a/unsupported/doc/Overview.dox
+++ b/unsupported/doc/Overview.dox
@@ -10,6 +10,9 @@ Click on the \e Modules tab at the top of this page to get a list of all unsuppo
Don't miss the <a href="..//index.html">official Eigen documentation</a>.
+*/
+
+/*
\defgroup Unsupported_modules Unsupported modules
diff --git a/unsupported/doc/eigendoxy_layout.xml.in b/unsupported/doc/eigendoxy_layout.xml.in
new file mode 100644
index 000000000..c93621ed3
--- /dev/null
+++ b/unsupported/doc/eigendoxy_layout.xml.in
@@ -0,0 +1,177 @@
+<?xml version="1.0"?>
+<doxygenlayout version="1.0">
+ <!-- Navigation index tabs for HTML output -->
+ <navindex>
+ <tab type="user" url="index.html" title="Overview" />
+ <tab type="modules" visible="yes" title="Unsupported Modules" intro=""/>
+<!-- <tab type="mainpage" visible="yes" title=""/> -->
+ <tab type="classlist" visible="yes" title="" intro=""/>
+<!-- <tab type="classmembers" visible="yes" title="" intro=""/> -->
+ </navindex>
+
+ <!-- Layout definition for a class page -->
+ <class>
+ <briefdescription visible="no"/>
+ <includes visible="$SHOW_INCLUDE_FILES"/>
+ <detaileddescription title=""/>
+ <inheritancegraph visible="$CLASS_GRAPH"/>
+ <collaborationgraph visible="$COLLABORATION_GRAPH"/>
+ <allmemberslink visible="yes"/>
+ <memberdecl>
+ <nestedclasses visible="yes" title=""/>
+ <publictypes title=""/>
+ <publicslots title=""/>
+ <signals title=""/>
+ <publicmethods title=""/>
+ <publicstaticmethods title=""/>
+ <publicattributes title=""/>
+ <publicstaticattributes title=""/>
+ <protectedtypes title=""/>
+ <protectedslots title=""/>
+ <protectedmethods title=""/>
+ <protectedstaticmethods title=""/>
+ <protectedattributes title=""/>
+ <protectedstaticattributes title=""/>
+ <packagetypes title=""/>
+ <packagemethods title=""/>
+ <packagestaticmethods title=""/>
+ <packageattributes title=""/>
+ <packagestaticattributes title=""/>
+ <properties title=""/>
+ <events title=""/>
+ <privatetypes title=""/>
+ <privateslots title=""/>
+ <privatemethods title=""/>
+ <privatestaticmethods title=""/>
+ <privateattributes title=""/>
+ <privatestaticattributes title=""/>
+ <friends title=""/>
+ <related title="" subtitle=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+
+ <memberdef>
+ <inlineclasses title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <constructors title=""/>
+ <functions title=""/>
+ <related title=""/>
+ <variables title=""/>
+ <properties title=""/>
+ <events title=""/>
+ </memberdef>
+ <usedfiles visible="$SHOW_USED_FILES"/>
+ <authorsection visible="yes"/>
+ </class>
+
+ <!-- Layout definition for a namespace page -->
+ <namespace>
+ <briefdescription visible="yes"/>
+ <memberdecl>
+ <nestednamespaces visible="yes" title=""/>
+ <classes visible="yes" title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <inlineclasses title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ </memberdef>
+ <authorsection visible="yes"/>
+ </namespace>
+
+ <!-- Layout definition for a file page -->
+ <file>
+ <briefdescription visible="yes"/>
+ <includes visible="$SHOW_INCLUDE_FILES"/>
+ <includegraph visible="$INCLUDE_GRAPH"/>
+ <includedbygraph visible="$INCLUDED_BY_GRAPH"/>
+ <sourcelink visible="yes"/>
+ <memberdecl>
+ <classes visible="yes" title=""/>
+ <namespaces visible="yes" title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <inlineclasses title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ </memberdef>
+ <authorsection/>
+ </file>
+
+ <!-- Layout definition for a group page -->
+ <group>
+ <briefdescription visible="no"/>
+ <detaileddescription title=""/>
+ <groupgraph visible="$GROUP_GRAPHS"/>
+ <memberdecl>
+ <nestedgroups visible="yes" title=""/>
+ <dirs visible="yes" title=""/>
+ <files visible="yes" title=""/>
+ <namespaces visible="yes" title=""/>
+ <classes visible="yes" title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <enumvalues title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <signals title=""/>
+ <publicslots title=""/>
+ <protectedslots title=""/>
+ <privateslots title=""/>
+ <events title=""/>
+ <properties title=""/>
+ <friends title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+
+ <memberdef>
+ <pagedocs/>
+ <inlineclasses title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <enumvalues title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <signals title=""/>
+ <publicslots title=""/>
+ <protectedslots title=""/>
+ <privateslots title=""/>
+ <events title=""/>
+ <properties title=""/>
+ <friends title=""/>
+ </memberdef>
+ <authorsection visible="yes"/>
+ </group>
+
+ <!-- Layout definition for a directory page -->
+ <directory>
+ <briefdescription visible="yes"/>
+ <directorygraph visible="yes"/>
+ <memberdecl>
+ <dirs visible="yes"/>
+ <files visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ </directory>
+</doxygenlayout>
diff --git a/unsupported/doc/examples/MatrixPower.cpp b/unsupported/doc/examples/MatrixPower.cpp
new file mode 100644
index 000000000..222452476
--- /dev/null
+++ b/unsupported/doc/examples/MatrixPower.cpp
@@ -0,0 +1,16 @@
+#include <unsupported/Eigen/MatrixFunctions>
+#include <iostream>
+
+using namespace Eigen;
+
+int main()
+{
+ const double pi = std::acos(-1.0);
+ Matrix3d A;
+ A << cos(1), -sin(1), 0,
+ sin(1), cos(1), 0,
+ 0 , 0 , 1;
+ std::cout << "The matrix A is:\n" << A << "\n\n"
+ "The matrix power A^(pi/4) is:\n" << A.pow(pi/4) << std::endl;
+ return 0;
+}
diff --git a/unsupported/doc/examples/MatrixPower_optimal.cpp b/unsupported/doc/examples/MatrixPower_optimal.cpp
new file mode 100644
index 000000000..86470ba0a
--- /dev/null
+++ b/unsupported/doc/examples/MatrixPower_optimal.cpp
@@ -0,0 +1,17 @@
+#include <unsupported/Eigen/MatrixFunctions>
+#include <iostream>
+
+using namespace Eigen;
+
+int main()
+{
+ Matrix4cd A = Matrix4cd::Random();
+ MatrixPower<Matrix4cd> Apow(A);
+
+ std::cout << "The matrix A is:\n" << A << "\n\n"
+ "A^3.1 is:\n" << Apow(3.1) << "\n\n"
+ "A^3.3 is:\n" << Apow(3.3) << "\n\n"
+ "A^3.7 is:\n" << Apow(3.7) << "\n\n"
+ "A^3.9 is:\n" << Apow(3.9) << std::endl;
+ return 0;
+}
diff --git a/unsupported/doc/examples/PolynomialSolver1.cpp b/unsupported/doc/examples/PolynomialSolver1.cpp
index 71e6b825f..cd777a4e2 100644
--- a/unsupported/doc/examples/PolynomialSolver1.cpp
+++ b/unsupported/doc/examples/PolynomialSolver1.cpp
@@ -49,5 +49,5 @@ int main()
cout.precision(10);
cout << "The last root in float then in double: " << psolvef.roots()[5] << "\t" << psolve6d.roots()[5] << endl;
std::complex<float> castedRoot( psolve6d.roots()[5].real(), psolve6d.roots()[5].imag() );
- cout << "Norm of the difference: " << internal::abs( psolvef.roots()[5] - castedRoot ) << endl;
+ cout << "Norm of the difference: " << std::abs( psolvef.roots()[5] - castedRoot ) << endl;
}
diff --git a/unsupported/test/CMakeLists.txt b/unsupported/test/CMakeLists.txt
index b34b151b1..a94a3b5e5 100644
--- a/unsupported/test/CMakeLists.txt
+++ b/unsupported/test/CMakeLists.txt
@@ -1,4 +1,7 @@
+set_property(GLOBAL PROPERTY EIGEN_CURRENT_SUBPROJECT "Unsupported")
+add_custom_target(BuildUnsupported)
+
include_directories(../../test ../../unsupported ../../Eigen
${CMAKE_CURRENT_BINARY_DIR}/../../test)
@@ -22,7 +25,7 @@ endif(ADOLC_FOUND)
# this test seems to never have been successful on x87, so is considered to contain a FP-related bug.
# see thread: "non-linear optimization test summary"
-#ei_add_test(NonLinearOptimization)
+ei_add_test(NonLinearOptimization)
ei_add_test(NumericalDiff)
ei_add_test(autodiff)
@@ -33,6 +36,7 @@ endif()
ei_add_test(matrix_exponential)
ei_add_test(matrix_function)
+ei_add_test(matrix_power)
ei_add_test(matrix_square_root)
ei_add_test(alignedvector3)
ei_add_test(FFT)
@@ -84,4 +88,6 @@ ei_add_test(polynomialutils)
ei_add_test(kronecker_product)
ei_add_test(splines)
ei_add_test(gmres)
-
+ei_add_test(minres)
+ei_add_test(levenberg_marquardt)
+ei_add_test(bdcsvd)
diff --git a/unsupported/test/FFTW.cpp b/unsupported/test/FFTW.cpp
index a07bf274b..d3718e2d2 100644
--- a/unsupported/test/FFTW.cpp
+++ b/unsupported/test/FFTW.cpp
@@ -16,9 +16,6 @@ std::complex<T> RandomCpx() { return std::complex<T>( (T)(rand()/(T)RAND_MAX - .
using namespace std;
using namespace Eigen;
-float norm(float x) {return x*x;}
-double norm(double x) {return x*x;}
-long double norm(long double x) {return x*x;}
template < typename T>
complex<long double> promote(complex<T> x) { return complex<long double>(x.real(),x.imag()); }
@@ -40,11 +37,11 @@ complex<long double> promote(long double x) { return complex<long double>( x);
for (size_t k1=0;k1<(size_t)timebuf.size();++k1) {
acc += promote( timebuf[k1] ) * exp( complex<long double>(0,k1*phinc) );
}
- totalpower += norm(acc);
+ totalpower += numext::abs2(acc);
complex<long double> x = promote(fftbuf[k0]);
complex<long double> dif = acc - x;
- difpower += norm(dif);
- //cerr << k0 << "\t" << acc << "\t" << x << "\t" << sqrt(norm(dif)) << endl;
+ difpower += numext::abs2(dif);
+ //cerr << k0 << "\t" << acc << "\t" << x << "\t" << sqrt(numext::abs2(dif)) << endl;
}
cerr << "rmse:" << sqrt(difpower/totalpower) << endl;
return sqrt(difpower/totalpower);
@@ -57,8 +54,8 @@ complex<long double> promote(long double x) { return complex<long double>( x);
long double difpower=0;
size_t n = (min)( buf1.size(),buf2.size() );
for (size_t k=0;k<n;++k) {
- totalpower += (norm( buf1[k] ) + norm(buf2[k]) )/2.;
- difpower += norm(buf1[k] - buf2[k]);
+ totalpower += (numext::abs2( buf1[k] ) + numext::abs2(buf2[k]) )/2.;
+ difpower += numext::abs2(buf1[k] - buf2[k]);
}
return sqrt(difpower/totalpower);
}
diff --git a/unsupported/test/NonLinearOptimization.cpp b/unsupported/test/NonLinearOptimization.cpp
index 81b066897..d7376b0f5 100644
--- a/unsupported/test/NonLinearOptimization.cpp
+++ b/unsupported/test/NonLinearOptimization.cpp
@@ -12,6 +12,8 @@
// It is intended to be done for this test only.
#include <Eigen/src/Core/util/DisableStupidWarnings.h>
+using std::sqrt;
+
int fcn_chkder(const VectorXd &x, VectorXd &fvec, MatrixXd &fjac, int iflag)
{
/* subroutine fcn for chkder example. */
@@ -795,7 +797,9 @@ struct hahn1_functor : Functor<double>
static const double m_x[236];
int operator()(const VectorXd &b, VectorXd &fvec)
{
- static const double m_y[236] = { .591E0 , 1.547E0 , 2.902E0 , 2.894E0 , 4.703E0 , 6.307E0 , 7.03E0 , 7.898E0 , 9.470E0 , 9.484E0 , 10.072E0 , 10.163E0 , 11.615E0 , 12.005E0 , 12.478E0 , 12.982E0 , 12.970E0 , 13.926E0 , 14.452E0 , 14.404E0 , 15.190E0 , 15.550E0 , 15.528E0 , 15.499E0 , 16.131E0 , 16.438E0 , 16.387E0 , 16.549E0 , 16.872E0 , 16.830E0 , 16.926E0 , 16.907E0 , 16.966E0 , 17.060E0 , 17.122E0 , 17.311E0 , 17.355E0 , 17.668E0 , 17.767E0 , 17.803E0 , 17.765E0 , 17.768E0 , 17.736E0 , 17.858E0 , 17.877E0 , 17.912E0 , 18.046E0 , 18.085E0 , 18.291E0 , 18.357E0 , 18.426E0 , 18.584E0 , 18.610E0 , 18.870E0 , 18.795E0 , 19.111E0 , .367E0 , .796E0 , 0.892E0 , 1.903E0 , 2.150E0 , 3.697E0 , 5.870E0 , 6.421E0 , 7.422E0 , 9.944E0 , 11.023E0 , 11.87E0 , 12.786E0 , 14.067E0 , 13.974E0 , 14.462E0 , 14.464E0 , 15.381E0 , 15.483E0 , 15.59E0 , 16.075E0 , 16.347E0 , 16.181E0 , 16.915E0 , 17.003E0 , 16.978E0 , 17.756E0 , 17.808E0 , 17.868E0 , 18.481E0 , 18.486E0 , 19.090E0 , 16.062E0 , 16.337E0 , 16.345E0 , 16.388E0 , 17.159E0 , 17.116E0 , 17.164E0 , 17.123E0 , 17.979E0 , 17.974E0 , 18.007E0 , 17.993E0 , 18.523E0 , 18.669E0 , 18.617E0 , 19.371E0 , 19.330E0 , 0.080E0 , 0.248E0 , 1.089E0 , 1.418E0 , 2.278E0 , 3.624E0 , 4.574E0 , 5.556E0 , 7.267E0 , 7.695E0 , 9.136E0 , 9.959E0 , 9.957E0 , 11.600E0 , 13.138E0 , 13.564E0 , 13.871E0 , 13.994E0 , 14.947E0 , 15.473E0 , 15.379E0 , 15.455E0 , 15.908E0 , 16.114E0 , 17.071E0 , 17.135E0 , 17.282E0 , 17.368E0 , 17.483E0 , 17.764E0 , 18.185E0 , 18.271E0 , 18.236E0 , 18.237E0 , 18.523E0 , 18.627E0 , 18.665E0 , 19.086E0 , 0.214E0 , 0.943E0 , 1.429E0 , 2.241E0 , 2.951E0 , 3.782E0 , 4.757E0 , 5.602E0 , 7.169E0 , 8.920E0 , 10.055E0 , 12.035E0 , 12.861E0 , 13.436E0 , 14.167E0 , 14.755E0 , 15.168E0 , 15.651E0 , 15.746E0 , 16.216E0 , 16.445E0 , 16.965E0 , 17.121E0 , 17.206E0 , 17.250E0 , 17.339E0 , 17.793E0 , 18.123E0 , 18.49E0 , 18.566E0 , 18.645E0 , 18.706E0 , 18.924E0 , 19.1E0 , 0.375E0 , 0.471E0 , 1.504E0 , 2.204E0 , 2.813E0 , 4.765E0 , 9.835E0 , 10.040E0 , 11.946E0 , 12.596E0 , 13.303E0 , 13.922E0 , 14.440E0 , 14.951E0 , 15.627E0 , 15.639E0 , 15.814E0 , 16.315E0 , 16.334E0 , 16.430E0 , 16.423E0 , 17.024E0 , 17.009E0 , 17.165E0 , 17.134E0 , 17.349E0 , 17.576E0 , 17.848E0 , 18.090E0 , 18.276E0 , 18.404E0 , 18.519E0 , 19.133E0 , 19.074E0 , 19.239E0 , 19.280E0 , 19.101E0 , 19.398E0 , 19.252E0 , 19.89E0 , 20.007E0 , 19.929E0 , 19.268E0 , 19.324E0 , 20.049E0 , 20.107E0 , 20.062E0 , 20.065E0 , 19.286E0 , 19.972E0 , 20.088E0 , 20.743E0 , 20.83E0 , 20.935E0 , 21.035E0 , 20.93E0 , 21.074E0 , 21.085E0 , 20.935E0 };
+ static const double m_y[236] = { .591E0 , 1.547E0 , 2.902E0 , 2.894E0 , 4.703E0 , 6.307E0 , 7.03E0 , 7.898E0 , 9.470E0 , 9.484E0 , 10.072E0 , 10.163E0 , 11.615E0 , 12.005E0 , 12.478E0 , 12.982E0 , 12.970E0 , 13.926E0 , 14.452E0 , 14.404E0 , 15.190E0 , 15.550E0 , 15.528E0 , 15.499E0 , 16.131E0 , 16.438E0 , 16.387E0 , 16.549E0 , 16.872E0 , 16.830E0 , 16.926E0 , 16.907E0 , 16.966E0 , 17.060E0 , 17.122E0 , 17.311E0 , 17.355E0 , 17.668E0 , 17.767E0 , 17.803E0 , 17.765E0 , 17.768E0 , 17.736E0 , 17.858E0 , 17.877E0 , 17.912E0 , 18.046E0 , 18.085E0 , 18.291E0 , 18.357E0 , 18.426E0 , 18.584E0 , 18.610E0 , 18.870E0 , 18.795E0 , 19.111E0 , .367E0 , .796E0 , 0.892E0 , 1.903E0 , 2.150E0 , 3.697E0 , 5.870E0 , 6.421E0 , 7.422E0 , 9.944E0 , 11.023E0 , 11.87E0 , 12.786E0 , 14.067E0 , 13.974E0 , 14.462E0 , 14.464E0 , 15.381E0 , 15.483E0 , 15.59E0 , 16.075E0 , 16.347E0 , 16.181E0 , 16.915E0 , 17.003E0 , 16.978E0 , 17.756E0 , 17.808E0 , 17.868E0 , 18.481E0 , 18.486E0 , 19.090E0 , 16.062E0 , 16.337E0 , 16.345E0 ,
+ 16.388E0 , 17.159E0 , 17.116E0 , 17.164E0 , 17.123E0 , 17.979E0 , 17.974E0 , 18.007E0 , 17.993E0 , 18.523E0 , 18.669E0 , 18.617E0 , 19.371E0 , 19.330E0 , 0.080E0 , 0.248E0 , 1.089E0 , 1.418E0 , 2.278E0 , 3.624E0 , 4.574E0 , 5.556E0 , 7.267E0 , 7.695E0 , 9.136E0 , 9.959E0 , 9.957E0 , 11.600E0 , 13.138E0 , 13.564E0 , 13.871E0 , 13.994E0 , 14.947E0 , 15.473E0 , 15.379E0 , 15.455E0 , 15.908E0 , 16.114E0 , 17.071E0 , 17.135E0 , 17.282E0 , 17.368E0 , 17.483E0 , 17.764E0 , 18.185E0 , 18.271E0 , 18.236E0 , 18.237E0 , 18.523E0 , 18.627E0 , 18.665E0 , 19.086E0 , 0.214E0 , 0.943E0 , 1.429E0 , 2.241E0 , 2.951E0 , 3.782E0 , 4.757E0 , 5.602E0 , 7.169E0 , 8.920E0 , 10.055E0 , 12.035E0 , 12.861E0 , 13.436E0 , 14.167E0 , 14.755E0 , 15.168E0 , 15.651E0 , 15.746E0 , 16.216E0 , 16.445E0 , 16.965E0 , 17.121E0 , 17.206E0 , 17.250E0 , 17.339E0 , 17.793E0 , 18.123E0 , 18.49E0 , 18.566E0 , 18.645E0 , 18.706E0 , 18.924E0 , 19.1E0 , 0.375E0 , 0.471E0 , 1.504E0 , 2.204E0 , 2.813E0 , 4.765E0 , 9.835E0 , 10.040E0 , 11.946E0 , 12.596E0 ,
+13.303E0 , 13.922E0 , 14.440E0 , 14.951E0 , 15.627E0 , 15.639E0 , 15.814E0 , 16.315E0 , 16.334E0 , 16.430E0 , 16.423E0 , 17.024E0 , 17.009E0 , 17.165E0 , 17.134E0 , 17.349E0 , 17.576E0 , 17.848E0 , 18.090E0 , 18.276E0 , 18.404E0 , 18.519E0 , 19.133E0 , 19.074E0 , 19.239E0 , 19.280E0 , 19.101E0 , 19.398E0 , 19.252E0 , 19.89E0 , 20.007E0 , 19.929E0 , 19.268E0 , 19.324E0 , 20.049E0 , 20.107E0 , 20.062E0 , 20.065E0 , 19.286E0 , 19.972E0 , 20.088E0 , 20.743E0 , 20.83E0 , 20.935E0 , 21.035E0 , 20.93E0 , 21.074E0 , 21.085E0 , 20.935E0 };
// int called=0; printf("call hahn1_functor with iflag=%d, called=%d\n", iflag, called); if (iflag==1) called++;
@@ -828,7 +832,9 @@ struct hahn1_functor : Functor<double>
return 0;
}
};
-const double hahn1_functor::m_x[236] = { 24.41E0 , 34.82E0 , 44.09E0 , 45.07E0 , 54.98E0 , 65.51E0 , 70.53E0 , 75.70E0 , 89.57E0 , 91.14E0 , 96.40E0 , 97.19E0 , 114.26E0 , 120.25E0 , 127.08E0 , 133.55E0 , 133.61E0 , 158.67E0 , 172.74E0 , 171.31E0 , 202.14E0 , 220.55E0 , 221.05E0 , 221.39E0 , 250.99E0 , 268.99E0 , 271.80E0 , 271.97E0 , 321.31E0 , 321.69E0 , 330.14E0 , 333.03E0 , 333.47E0 , 340.77E0 , 345.65E0 , 373.11E0 , 373.79E0 , 411.82E0 , 419.51E0 , 421.59E0 , 422.02E0 , 422.47E0 , 422.61E0 , 441.75E0 , 447.41E0 , 448.7E0 , 472.89E0 , 476.69E0 , 522.47E0 , 522.62E0 , 524.43E0 , 546.75E0 , 549.53E0 , 575.29E0 , 576.00E0 , 625.55E0 , 20.15E0 , 28.78E0 , 29.57E0 , 37.41E0 , 39.12E0 , 50.24E0 , 61.38E0 , 66.25E0 , 73.42E0 , 95.52E0 , 107.32E0 , 122.04E0 , 134.03E0 , 163.19E0 , 163.48E0 , 175.70E0 , 179.86E0 , 211.27E0 , 217.78E0 , 219.14E0 , 262.52E0 , 268.01E0 , 268.62E0 , 336.25E0 , 337.23E0 , 339.33E0 , 427.38E0 , 428.58E0 , 432.68E0 , 528.99E0 , 531.08E0 , 628.34E0 , 253.24E0 , 273.13E0 , 273.66E0 , 282.10E0 , 346.62E0 , 347.19E0 , 348.78E0 , 351.18E0 , 450.10E0 , 450.35E0 , 451.92E0 , 455.56E0 , 552.22E0 , 553.56E0 , 555.74E0 , 652.59E0 , 656.20E0 , 14.13E0 , 20.41E0 , 31.30E0 , 33.84E0 , 39.70E0 , 48.83E0 , 54.50E0 , 60.41E0 , 72.77E0 , 75.25E0 , 86.84E0 , 94.88E0 , 96.40E0 , 117.37E0 , 139.08E0 , 147.73E0 , 158.63E0 , 161.84E0 , 192.11E0 , 206.76E0 , 209.07E0 , 213.32E0 , 226.44E0 , 237.12E0 , 330.90E0 , 358.72E0 , 370.77E0 , 372.72E0 , 396.24E0 , 416.59E0 , 484.02E0 , 495.47E0 , 514.78E0 , 515.65E0 , 519.47E0 , 544.47E0 , 560.11E0 , 620.77E0 , 18.97E0 , 28.93E0 , 33.91E0 , 40.03E0 , 44.66E0 , 49.87E0 , 55.16E0 , 60.90E0 , 72.08E0 , 85.15E0 , 97.06E0 , 119.63E0 , 133.27E0 , 143.84E0 , 161.91E0 , 180.67E0 , 198.44E0 , 226.86E0 , 229.65E0 , 258.27E0 , 273.77E0 , 339.15E0 , 350.13E0 , 362.75E0 , 371.03E0 , 393.32E0 , 448.53E0 , 473.78E0 , 511.12E0 , 524.70E0 , 548.75E0 , 551.64E0 , 574.02E0 , 623.86E0 , 21.46E0 , 24.33E0 , 33.43E0 , 39.22E0 , 44.18E0 , 55.02E0 , 94.33E0 , 96.44E0 , 118.82E0 , 128.48E0 , 141.94E0 , 156.92E0 , 171.65E0 , 190.00E0 , 223.26E0 , 223.88E0 , 231.50E0 , 265.05E0 , 269.44E0 , 271.78E0 , 273.46E0 , 334.61E0 , 339.79E0 , 349.52E0 , 358.18E0 , 377.98E0 , 394.77E0 , 429.66E0 , 468.22E0 , 487.27E0 , 519.54E0 , 523.03E0 , 612.99E0 , 638.59E0 , 641.36E0 , 622.05E0 , 631.50E0 , 663.97E0 , 646.9E0 , 748.29E0 , 749.21E0 , 750.14E0 , 647.04E0 , 646.89E0 , 746.9E0 , 748.43E0 , 747.35E0 , 749.27E0 , 647.61E0 , 747.78E0 , 750.51E0 , 851.37E0 , 845.97E0 , 847.54E0 , 849.93E0 , 851.61E0 , 849.75E0 , 850.98E0 , 848.23E0};
+const double hahn1_functor::m_x[236] = { 24.41E0 , 34.82E0 , 44.09E0 , 45.07E0 , 54.98E0 , 65.51E0 , 70.53E0 , 75.70E0 , 89.57E0 , 91.14E0 , 96.40E0 , 97.19E0 , 114.26E0 , 120.25E0 , 127.08E0 , 133.55E0 , 133.61E0 , 158.67E0 , 172.74E0 , 171.31E0 , 202.14E0 , 220.55E0 , 221.05E0 , 221.39E0 , 250.99E0 , 268.99E0 , 271.80E0 , 271.97E0 , 321.31E0 , 321.69E0 , 330.14E0 , 333.03E0 , 333.47E0 , 340.77E0 , 345.65E0 , 373.11E0 , 373.79E0 , 411.82E0 , 419.51E0 , 421.59E0 , 422.02E0 , 422.47E0 , 422.61E0 , 441.75E0 , 447.41E0 , 448.7E0 , 472.89E0 , 476.69E0 , 522.47E0 , 522.62E0 , 524.43E0 , 546.75E0 , 549.53E0 , 575.29E0 , 576.00E0 , 625.55E0 , 20.15E0 , 28.78E0 , 29.57E0 , 37.41E0 , 39.12E0 , 50.24E0 , 61.38E0 , 66.25E0 , 73.42E0 , 95.52E0 , 107.32E0 , 122.04E0 , 134.03E0 , 163.19E0 , 163.48E0 , 175.70E0 , 179.86E0 , 211.27E0 , 217.78E0 , 219.14E0 , 262.52E0 , 268.01E0 , 268.62E0 , 336.25E0 , 337.23E0 , 339.33E0 , 427.38E0 , 428.58E0 , 432.68E0 , 528.99E0 , 531.08E0 , 628.34E0 , 253.24E0 , 273.13E0 , 273.66E0 ,
+282.10E0 , 346.62E0 , 347.19E0 , 348.78E0 , 351.18E0 , 450.10E0 , 450.35E0 , 451.92E0 , 455.56E0 , 552.22E0 , 553.56E0 , 555.74E0 , 652.59E0 , 656.20E0 , 14.13E0 , 20.41E0 , 31.30E0 , 33.84E0 , 39.70E0 , 48.83E0 , 54.50E0 , 60.41E0 , 72.77E0 , 75.25E0 , 86.84E0 , 94.88E0 , 96.40E0 , 117.37E0 , 139.08E0 , 147.73E0 , 158.63E0 , 161.84E0 , 192.11E0 , 206.76E0 , 209.07E0 , 213.32E0 , 226.44E0 , 237.12E0 , 330.90E0 , 358.72E0 , 370.77E0 , 372.72E0 , 396.24E0 , 416.59E0 , 484.02E0 , 495.47E0 , 514.78E0 , 515.65E0 , 519.47E0 , 544.47E0 , 560.11E0 , 620.77E0 , 18.97E0 , 28.93E0 , 33.91E0 , 40.03E0 , 44.66E0 , 49.87E0 , 55.16E0 , 60.90E0 , 72.08E0 , 85.15E0 , 97.06E0 , 119.63E0 , 133.27E0 , 143.84E0 , 161.91E0 , 180.67E0 , 198.44E0 , 226.86E0 , 229.65E0 , 258.27E0 , 273.77E0 , 339.15E0 , 350.13E0 , 362.75E0 , 371.03E0 , 393.32E0 , 448.53E0 , 473.78E0 , 511.12E0 , 524.70E0 , 548.75E0 , 551.64E0 , 574.02E0 , 623.86E0 , 21.46E0 , 24.33E0 , 33.43E0 , 39.22E0 , 44.18E0 , 55.02E0 , 94.33E0 , 96.44E0 , 118.82E0 , 128.48E0 ,
+141.94E0 , 156.92E0 , 171.65E0 , 190.00E0 , 223.26E0 , 223.88E0 , 231.50E0 , 265.05E0 , 269.44E0 , 271.78E0 , 273.46E0 , 334.61E0 , 339.79E0 , 349.52E0 , 358.18E0 , 377.98E0 , 394.77E0 , 429.66E0 , 468.22E0 , 487.27E0 , 519.54E0 , 523.03E0 , 612.99E0 , 638.59E0 , 641.36E0 , 622.05E0 , 631.50E0 , 663.97E0 , 646.9E0 , 748.29E0 , 749.21E0 , 750.14E0 , 647.04E0 , 646.89E0 , 746.9E0 , 748.43E0 , 747.35E0 , 749.27E0 , 647.61E0 , 747.78E0 , 750.51E0 , 851.37E0 , 845.97E0 , 847.54E0 , 849.93E0 , 851.61E0 , 849.75E0 , 850.98E0 , 848.23E0};
// http://www.itl.nist.gov/div898/strd/nls/data/hahn1.shtml
void testNistHahn1(void)
@@ -1485,8 +1491,11 @@ struct Bennett5_functor : Functor<double>
return 0;
}
};
-const double Bennett5_functor::x[154] = { 7.447168E0, 8.102586E0, 8.452547E0, 8.711278E0, 8.916774E0, 9.087155E0, 9.232590E0, 9.359535E0, 9.472166E0, 9.573384E0, 9.665293E0, 9.749461E0, 9.827092E0, 9.899128E0, 9.966321E0, 10.029280E0, 10.088510E0, 10.144430E0, 10.197380E0, 10.247670E0, 10.295560E0, 10.341250E0, 10.384950E0, 10.426820E0, 10.467000E0, 10.505640E0, 10.542830E0, 10.578690E0, 10.613310E0, 10.646780E0, 10.679150E0, 10.710520E0, 10.740920E0, 10.770440E0, 10.799100E0, 10.826970E0, 10.854080E0, 10.880470E0, 10.906190E0, 10.931260E0, 10.955720E0, 10.979590E0, 11.002910E0, 11.025700E0, 11.047980E0, 11.069770E0, 11.091100E0, 11.111980E0, 11.132440E0, 11.152480E0, 11.172130E0, 11.191410E0, 11.210310E0, 11.228870E0, 11.247090E0, 11.264980E0, 11.282560E0, 11.299840E0, 11.316820E0, 11.333520E0, 11.349940E0, 11.366100E0, 11.382000E0, 11.397660E0, 11.413070E0, 11.428240E0, 11.443200E0, 11.457930E0, 11.472440E0, 11.486750E0, 11.500860E0, 11.514770E0, 11.528490E0, 11.542020E0, 11.555380E0, 11.568550E0, 11.581560E0, 11.594420E0, 11.607121E0, 11.619640E0, 11.632000E0, 11.644210E0, 11.656280E0, 11.668200E0, 11.679980E0, 11.691620E0, 11.703130E0, 11.714510E0, 11.725760E0, 11.736880E0, 11.747890E0, 11.758780E0, 11.769550E0, 11.780200E0, 11.790730E0, 11.801160E0, 11.811480E0, 11.821700E0, 11.831810E0, 11.841820E0, 11.851730E0, 11.861550E0, 11.871270E0, 11.880890E0, 11.890420E0, 11.899870E0, 11.909220E0, 11.918490E0, 11.927680E0, 11.936780E0, 11.945790E0, 11.954730E0, 11.963590E0, 11.972370E0, 11.981070E0, 11.989700E0, 11.998260E0, 12.006740E0, 12.015150E0, 12.023490E0, 12.031760E0, 12.039970E0, 12.048100E0, 12.056170E0, 12.064180E0, 12.072120E0, 12.080010E0, 12.087820E0, 12.095580E0, 12.103280E0, 12.110920E0, 12.118500E0, 12.126030E0, 12.133500E0, 12.140910E0, 12.148270E0, 12.155570E0, 12.162830E0, 12.170030E0, 12.177170E0, 12.184270E0, 12.191320E0, 12.198320E0, 12.205270E0, 12.212170E0, 12.219030E0, 12.225840E0, 12.232600E0, 12.239320E0, 12.245990E0, 12.252620E0, 12.259200E0, 12.265750E0, 12.272240E0 };
-const double Bennett5_functor::y[154] = { -34.834702E0 ,-34.393200E0 ,-34.152901E0 ,-33.979099E0 ,-33.845901E0 ,-33.732899E0 ,-33.640301E0 ,-33.559200E0 ,-33.486801E0 ,-33.423100E0 ,-33.365101E0 ,-33.313000E0 ,-33.260899E0 ,-33.217400E0 ,-33.176899E0 ,-33.139198E0 ,-33.101601E0 ,-33.066799E0 ,-33.035000E0 ,-33.003101E0 ,-32.971298E0 ,-32.942299E0 ,-32.916302E0 ,-32.890202E0 ,-32.864101E0 ,-32.841000E0 ,-32.817799E0 ,-32.797501E0 ,-32.774300E0 ,-32.757000E0 ,-32.733799E0 ,-32.716400E0 ,-32.699100E0 ,-32.678799E0 ,-32.661400E0 ,-32.644001E0 ,-32.626701E0 ,-32.612202E0 ,-32.597698E0 ,-32.583199E0 ,-32.568699E0 ,-32.554298E0 ,-32.539799E0 ,-32.525299E0 ,-32.510799E0 ,-32.499199E0 ,-32.487598E0 ,-32.473202E0 ,-32.461601E0 ,-32.435501E0 ,-32.435501E0 ,-32.426800E0 ,-32.412300E0 ,-32.400799E0 ,-32.392101E0 ,-32.380501E0 ,-32.366001E0 ,-32.357300E0 ,-32.348598E0 ,-32.339901E0 ,-32.328400E0 ,-32.319698E0 ,-32.311001E0 ,-32.299400E0 ,-32.290699E0 ,-32.282001E0 ,-32.273300E0 ,-32.264599E0 ,-32.256001E0 ,-32.247299E0 ,-32.238602E0 ,-32.229900E0 ,-32.224098E0 ,-32.215401E0 ,-32.203800E0 ,-32.198002E0 ,-32.189400E0 ,-32.183601E0 ,-32.174900E0 ,-32.169102E0 ,-32.163300E0 ,-32.154598E0 ,-32.145901E0 ,-32.140099E0 ,-32.131401E0 ,-32.125599E0 ,-32.119801E0 ,-32.111198E0 ,-32.105400E0 ,-32.096699E0 ,-32.090900E0 ,-32.088001E0 ,-32.079300E0 ,-32.073502E0 ,-32.067699E0 ,-32.061901E0 ,-32.056099E0 ,-32.050301E0 ,-32.044498E0 ,-32.038799E0 ,-32.033001E0 ,-32.027199E0 ,-32.024300E0 ,-32.018501E0 ,-32.012699E0 ,-32.004002E0 ,-32.001099E0 ,-31.995300E0 ,-31.989500E0 ,-31.983700E0 ,-31.977900E0 ,-31.972099E0 ,-31.969299E0 ,-31.963501E0 ,-31.957701E0 ,-31.951900E0 ,-31.946100E0 ,-31.940300E0 ,-31.937401E0 ,-31.931601E0 ,-31.925800E0 ,-31.922899E0 ,-31.917101E0 ,-31.911301E0 ,-31.908400E0 ,-31.902599E0 ,-31.896900E0 ,-31.893999E0 ,-31.888201E0 ,-31.885300E0 ,-31.882401E0 ,-31.876600E0 ,-31.873699E0 ,-31.867901E0 ,-31.862101E0 ,-31.859200E0 ,-31.856300E0 ,-31.850500E0 ,-31.844700E0 ,-31.841801E0 ,-31.838900E0 ,-31.833099E0 ,-31.830200E0 ,-31.827299E0 ,-31.821600E0 ,-31.818701E0 ,-31.812901E0 ,-31.809999E0 ,-31.807100E0 ,-31.801300E0 ,-31.798401E0 ,-31.795500E0 ,-31.789700E0 ,-31.786800E0 };
+const double Bennett5_functor::x[154] = { 7.447168E0, 8.102586E0, 8.452547E0, 8.711278E0, 8.916774E0, 9.087155E0, 9.232590E0, 9.359535E0, 9.472166E0, 9.573384E0, 9.665293E0, 9.749461E0, 9.827092E0, 9.899128E0, 9.966321E0, 10.029280E0, 10.088510E0, 10.144430E0, 10.197380E0, 10.247670E0, 10.295560E0, 10.341250E0, 10.384950E0, 10.426820E0, 10.467000E0, 10.505640E0, 10.542830E0, 10.578690E0, 10.613310E0, 10.646780E0, 10.679150E0, 10.710520E0, 10.740920E0, 10.770440E0, 10.799100E0, 10.826970E0, 10.854080E0, 10.880470E0, 10.906190E0, 10.931260E0, 10.955720E0, 10.979590E0, 11.002910E0, 11.025700E0, 11.047980E0, 11.069770E0, 11.091100E0, 11.111980E0, 11.132440E0, 11.152480E0, 11.172130E0, 11.191410E0, 11.210310E0, 11.228870E0, 11.247090E0, 11.264980E0, 11.282560E0, 11.299840E0, 11.316820E0, 11.333520E0, 11.349940E0, 11.366100E0, 11.382000E0, 11.397660E0, 11.413070E0, 11.428240E0, 11.443200E0, 11.457930E0, 11.472440E0, 11.486750E0, 11.500860E0, 11.514770E0, 11.528490E0, 11.542020E0, 11.555380E0, 11.568550E0,
+11.581560E0, 11.594420E0, 11.607121E0, 11.619640E0, 11.632000E0, 11.644210E0, 11.656280E0, 11.668200E0, 11.679980E0, 11.691620E0, 11.703130E0, 11.714510E0, 11.725760E0, 11.736880E0, 11.747890E0, 11.758780E0, 11.769550E0, 11.780200E0, 11.790730E0, 11.801160E0, 11.811480E0, 11.821700E0, 11.831810E0, 11.841820E0, 11.851730E0, 11.861550E0, 11.871270E0, 11.880890E0, 11.890420E0, 11.899870E0, 11.909220E0, 11.918490E0, 11.927680E0, 11.936780E0, 11.945790E0, 11.954730E0, 11.963590E0, 11.972370E0, 11.981070E0, 11.989700E0, 11.998260E0, 12.006740E0, 12.015150E0, 12.023490E0, 12.031760E0, 12.039970E0, 12.048100E0, 12.056170E0, 12.064180E0, 12.072120E0, 12.080010E0, 12.087820E0, 12.095580E0, 12.103280E0, 12.110920E0, 12.118500E0, 12.126030E0, 12.133500E0, 12.140910E0, 12.148270E0, 12.155570E0, 12.162830E0, 12.170030E0, 12.177170E0, 12.184270E0, 12.191320E0, 12.198320E0, 12.205270E0, 12.212170E0, 12.219030E0, 12.225840E0, 12.232600E0, 12.239320E0, 12.245990E0, 12.252620E0, 12.259200E0, 12.265750E0, 12.272240E0 };
+const double Bennett5_functor::y[154] = { -34.834702E0 ,-34.393200E0 ,-34.152901E0 ,-33.979099E0 ,-33.845901E0 ,-33.732899E0 ,-33.640301E0 ,-33.559200E0 ,-33.486801E0 ,-33.423100E0 ,-33.365101E0 ,-33.313000E0 ,-33.260899E0 ,-33.217400E0 ,-33.176899E0 ,-33.139198E0 ,-33.101601E0 ,-33.066799E0 ,-33.035000E0 ,-33.003101E0 ,-32.971298E0 ,-32.942299E0 ,-32.916302E0 ,-32.890202E0 ,-32.864101E0 ,-32.841000E0 ,-32.817799E0 ,-32.797501E0 ,-32.774300E0 ,-32.757000E0 ,-32.733799E0 ,-32.716400E0 ,-32.699100E0 ,-32.678799E0 ,-32.661400E0 ,-32.644001E0 ,-32.626701E0 ,-32.612202E0 ,-32.597698E0 ,-32.583199E0 ,-32.568699E0 ,-32.554298E0 ,-32.539799E0 ,-32.525299E0 ,-32.510799E0 ,-32.499199E0 ,-32.487598E0 ,-32.473202E0 ,-32.461601E0 ,-32.435501E0 ,-32.435501E0 ,-32.426800E0 ,-32.412300E0 ,-32.400799E0 ,-32.392101E0 ,-32.380501E0 ,-32.366001E0 ,-32.357300E0 ,-32.348598E0 ,-32.339901E0 ,-32.328400E0 ,-32.319698E0 ,-32.311001E0 ,-32.299400E0 ,-32.290699E0 ,-32.282001E0 ,-32.273300E0 ,-32.264599E0 ,-32.256001E0 ,-32.247299E0
+,-32.238602E0 ,-32.229900E0 ,-32.224098E0 ,-32.215401E0 ,-32.203800E0 ,-32.198002E0 ,-32.189400E0 ,-32.183601E0 ,-32.174900E0 ,-32.169102E0 ,-32.163300E0 ,-32.154598E0 ,-32.145901E0 ,-32.140099E0 ,-32.131401E0 ,-32.125599E0 ,-32.119801E0 ,-32.111198E0 ,-32.105400E0 ,-32.096699E0 ,-32.090900E0 ,-32.088001E0 ,-32.079300E0 ,-32.073502E0 ,-32.067699E0 ,-32.061901E0 ,-32.056099E0 ,-32.050301E0 ,-32.044498E0 ,-32.038799E0 ,-32.033001E0 ,-32.027199E0 ,-32.024300E0 ,-32.018501E0 ,-32.012699E0 ,-32.004002E0 ,-32.001099E0 ,-31.995300E0 ,-31.989500E0 ,-31.983700E0 ,-31.977900E0 ,-31.972099E0 ,-31.969299E0 ,-31.963501E0 ,-31.957701E0 ,-31.951900E0 ,-31.946100E0 ,-31.940300E0 ,-31.937401E0 ,-31.931601E0 ,-31.925800E0 ,-31.922899E0 ,-31.917101E0 ,-31.911301E0 ,-31.908400E0 ,-31.902599E0 ,-31.896900E0 ,-31.893999E0 ,-31.888201E0 ,-31.885300E0 ,-31.882401E0 ,-31.876600E0 ,-31.873699E0 ,-31.867901E0 ,-31.862101E0 ,-31.859200E0 ,-31.856300E0 ,-31.850500E0 ,-31.844700E0 ,-31.841801E0 ,-31.838900E0 ,-31.833099E0 ,-31.830200E0 ,
+-31.827299E0 ,-31.821600E0 ,-31.818701E0 ,-31.812901E0 ,-31.809999E0 ,-31.807100E0 ,-31.801300E0 ,-31.798401E0 ,-31.795500E0 ,-31.789700E0 ,-31.786800E0 };
// http://www.itl.nist.gov/div898/strd/nls/data/bennett5.shtml
void testNistBennett5(void)
@@ -1823,14 +1832,14 @@ void test_NonLinearOptimization()
// NIST tests, level of difficulty = "Average"
CALL_SUBTEST/*_5*/(testNistHahn1());
CALL_SUBTEST/*_6*/(testNistMisra1d());
- CALL_SUBTEST/*_7*/(testNistMGH17());
- CALL_SUBTEST/*_8*/(testNistLanczos1());
+// CALL_SUBTEST/*_7*/(testNistMGH17());
+// CALL_SUBTEST/*_8*/(testNistLanczos1());
- // NIST tests, level of difficulty = "Higher"
+// // NIST tests, level of difficulty = "Higher"
CALL_SUBTEST/*_9*/(testNistRat42());
- CALL_SUBTEST/*_10*/(testNistMGH10());
+// CALL_SUBTEST/*_10*/(testNistMGH10());
CALL_SUBTEST/*_11*/(testNistBoxBOD());
- CALL_SUBTEST/*_12*/(testNistMGH09());
+// CALL_SUBTEST/*_12*/(testNistMGH09());
CALL_SUBTEST/*_13*/(testNistBennett5());
CALL_SUBTEST/*_14*/(testNistThurber());
CALL_SUBTEST/*_15*/(testNistRat43());
diff --git a/unsupported/test/autodiff.cpp b/unsupported/test/autodiff.cpp
index 6eb417e8d..087e7c542 100644
--- a/unsupported/test/autodiff.cpp
+++ b/unsupported/test/autodiff.cpp
@@ -127,46 +127,47 @@ template<typename Func> void forward_jacobian(const Func& f)
VERIFY_IS_APPROX(j, jref);
}
+
+// TODO also check actual derivatives!
void test_autodiff_scalar()
{
- std::cerr << foo<float>(1,2) << "\n";
+ Vector2f p = Vector2f::Random();
typedef AutoDiffScalar<Vector2f> AD;
- AD ax(1,Vector2f::UnitX());
- AD ay(2,Vector2f::UnitY());
+ AD ax(p.x(),Vector2f::UnitX());
+ AD ay(p.y(),Vector2f::UnitY());
AD res = foo<AD>(ax,ay);
- std::cerr << res.value() << " <> "
- << res.derivatives().transpose() << "\n\n";
+ VERIFY_IS_APPROX(res.value(), foo(p.x(),p.y()));
}
+// TODO also check actual derivatives!
void test_autodiff_vector()
{
- std::cerr << foo<Vector2f>(Vector2f(1,2)) << "\n";
+ Vector2f p = Vector2f::Random();
typedef AutoDiffScalar<Vector2f> AD;
typedef Matrix<AD,2,1> VectorAD;
- VectorAD p(AD(1),AD(-1));
- p.x().derivatives() = Vector2f::UnitX();
- p.y().derivatives() = Vector2f::UnitY();
+ VectorAD ap = p.cast<AD>();
+ ap.x().derivatives() = Vector2f::UnitX();
+ ap.y().derivatives() = Vector2f::UnitY();
- AD res = foo<VectorAD>(p);
- std::cerr << res.value() << " <> "
- << res.derivatives().transpose() << "\n\n";
+ AD res = foo<VectorAD>(ap);
+ VERIFY_IS_APPROX(res.value(), foo(p));
}
void test_autodiff_jacobian()
{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST(( forward_jacobian(TestFunc1<double,2,2>()) ));
- CALL_SUBTEST(( forward_jacobian(TestFunc1<double,2,3>()) ));
- CALL_SUBTEST(( forward_jacobian(TestFunc1<double,3,2>()) ));
- CALL_SUBTEST(( forward_jacobian(TestFunc1<double,3,3>()) ));
- CALL_SUBTEST(( forward_jacobian(TestFunc1<double>(3,3)) ));
- }
+ CALL_SUBTEST(( forward_jacobian(TestFunc1<double,2,2>()) ));
+ CALL_SUBTEST(( forward_jacobian(TestFunc1<double,2,3>()) ));
+ CALL_SUBTEST(( forward_jacobian(TestFunc1<double,3,2>()) ));
+ CALL_SUBTEST(( forward_jacobian(TestFunc1<double,3,3>()) ));
+ CALL_SUBTEST(( forward_jacobian(TestFunc1<double>(3,3)) ));
}
void test_autodiff()
{
- test_autodiff_scalar();
- test_autodiff_vector();
-// test_autodiff_jacobian();
+ for(int i = 0; i < g_repeat; i++) {
+ CALL_SUBTEST_1( test_autodiff_scalar() );
+ CALL_SUBTEST_2( test_autodiff_vector() );
+ CALL_SUBTEST_3( test_autodiff_jacobian() );
+ }
}
diff --git a/unsupported/test/bdcsvd.cpp b/unsupported/test/bdcsvd.cpp
new file mode 100644
index 000000000..115a649b0
--- /dev/null
+++ b/unsupported/test/bdcsvd.cpp
@@ -0,0 +1,213 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2013 Gauthier Brun <brun.gauthier@gmail.com>
+// Copyright (C) 2013 Nicolas Carre <nicolas.carre@ensimag.fr>
+// Copyright (C) 2013 Jean Ceccato <jean.ceccato@ensimag.fr>
+// Copyright (C) 2013 Pierre Zoppitelli <pierre.zoppitelli@ensimag.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/
+
+#include "svd_common.h"
+#include <iostream>
+#include <Eigen/LU>
+
+// check if "svd" is the good image of "m"
+template<typename MatrixType>
+void bdcsvd_check_full(const MatrixType& m, const BDCSVD<MatrixType>& svd)
+{
+ svd_check_full< MatrixType, BDCSVD< MatrixType > >(m, svd);
+}
+
+// Compare to a reference value
+template<typename MatrixType>
+void bdcsvd_compare_to_full(const MatrixType& m,
+ unsigned int computationOptions,
+ const BDCSVD<MatrixType>& referenceSvd)
+{
+ svd_compare_to_full< MatrixType, BDCSVD< MatrixType > >(m, computationOptions, referenceSvd);
+} // end bdcsvd_compare_to_full
+
+
+template<typename MatrixType>
+void bdcsvd_solve(const MatrixType& m, unsigned int computationOptions)
+{
+ svd_solve< MatrixType, BDCSVD< MatrixType > >(m, computationOptions);
+} // end template bdcsvd_solve
+
+
+// test the computations options
+template<typename MatrixType>
+void bdcsvd_test_all_computation_options(const MatrixType& m)
+{
+ BDCSVD<MatrixType> fullSvd(m, ComputeFullU|ComputeFullV);
+ svd_test_computation_options_1< MatrixType, BDCSVD< MatrixType > >(m, fullSvd);
+ svd_test_computation_options_2< MatrixType, BDCSVD< MatrixType > >(m, fullSvd);
+} // end bdcsvd_test_all_computation_options
+
+
+// Call a test with all the computations options
+template<typename MatrixType>
+void bdcsvd(const MatrixType& a = MatrixType(), bool pickrandom = true)
+{
+ MatrixType m = pickrandom ? MatrixType::Random(a.rows(), a.cols()) : a;
+ bdcsvd_test_all_computation_options<MatrixType>(m);
+} // end template bdcsvd
+
+
+// verify assert
+template<typename MatrixType>
+void bdcsvd_verify_assert(const MatrixType& m)
+{
+ svd_verify_assert< MatrixType, BDCSVD< MatrixType > >(m);
+}// end template bdcsvd_verify_assert
+
+
+// test weird values
+template<typename MatrixType>
+void bdcsvd_inf_nan()
+{
+ svd_inf_nan< MatrixType, BDCSVD< MatrixType > >();
+}// end template bdcsvd_inf_nan
+
+
+
+void bdcsvd_preallocate()
+{
+ svd_preallocate< BDCSVD< MatrixXf > >();
+} // end bdcsvd_preallocate
+
+
+// compare the Singular values returned with Jacobi and Bdc
+template<typename MatrixType>
+void compare_bdc_jacobi(const MatrixType& a = MatrixType(), unsigned int computationOptions = 0)
+{
+ std::cout << "debut compare" << std::endl;
+ MatrixType m = MatrixType::Random(a.rows(), a.cols());
+ BDCSVD<MatrixType> bdc_svd(m);
+ JacobiSVD<MatrixType> jacobi_svd(m);
+ VERIFY_IS_APPROX(bdc_svd.singularValues(), jacobi_svd.singularValues());
+ if(computationOptions & ComputeFullU)
+ VERIFY_IS_APPROX(bdc_svd.matrixU(), jacobi_svd.matrixU());
+ if(computationOptions & ComputeThinU)
+ VERIFY_IS_APPROX(bdc_svd.matrixU(), jacobi_svd.matrixU());
+ if(computationOptions & ComputeFullV)
+ VERIFY_IS_APPROX(bdc_svd.matrixV(), jacobi_svd.matrixV());
+ if(computationOptions & ComputeThinV)
+ VERIFY_IS_APPROX(bdc_svd.matrixV(), jacobi_svd.matrixV());
+ std::cout << "fin compare" << std::endl;
+} // end template compare_bdc_jacobi
+
+
+// call the tests
+void test_bdcsvd()
+{
+ // test of Dynamic defined Matrix (42, 42) of float
+ CALL_SUBTEST_11(( bdcsvd_verify_assert<Matrix<float,Dynamic,Dynamic> >
+ (Matrix<float,Dynamic,Dynamic>(42,42)) ));
+ CALL_SUBTEST_11(( compare_bdc_jacobi<Matrix<float,Dynamic,Dynamic> >
+ (Matrix<float,Dynamic,Dynamic>(42,42), 0) ));
+ CALL_SUBTEST_11(( bdcsvd<Matrix<float,Dynamic,Dynamic> >
+ (Matrix<float,Dynamic,Dynamic>(42,42)) ));
+
+ // test of Dynamic defined Matrix (50, 50) of double
+ CALL_SUBTEST_13(( bdcsvd_verify_assert<Matrix<double,Dynamic,Dynamic> >
+ (Matrix<double,Dynamic,Dynamic>(50,50)) ));
+ CALL_SUBTEST_13(( compare_bdc_jacobi<Matrix<double,Dynamic,Dynamic> >
+ (Matrix<double,Dynamic,Dynamic>(50,50), 0) ));
+ CALL_SUBTEST_13(( bdcsvd<Matrix<double,Dynamic,Dynamic> >
+ (Matrix<double,Dynamic,Dynamic>(50, 50)) ));
+
+ // test of Dynamic defined Matrix (22, 22) of complex double
+ CALL_SUBTEST_14(( bdcsvd_verify_assert<Matrix<std::complex<double>,Dynamic,Dynamic> >
+ (Matrix<std::complex<double>,Dynamic,Dynamic>(22,22)) ));
+ CALL_SUBTEST_14(( compare_bdc_jacobi<Matrix<std::complex<double>,Dynamic,Dynamic> >
+ (Matrix<std::complex<double>, Dynamic, Dynamic> (22,22), 0) ));
+ CALL_SUBTEST_14(( bdcsvd<Matrix<std::complex<double>,Dynamic,Dynamic> >
+ (Matrix<std::complex<double>,Dynamic,Dynamic>(22, 22)) ));
+
+ // test of Dynamic defined Matrix (10, 10) of int
+ //CALL_SUBTEST_15(( bdcsvd_verify_assert<Matrix<int,Dynamic,Dynamic> >
+ // (Matrix<int,Dynamic,Dynamic>(10,10)) ));
+ //CALL_SUBTEST_15(( compare_bdc_jacobi<Matrix<int,Dynamic,Dynamic> >
+ // (Matrix<int,Dynamic,Dynamic>(10,10), 0) ));
+ //CALL_SUBTEST_15(( bdcsvd<Matrix<int,Dynamic,Dynamic> >
+ // (Matrix<int,Dynamic,Dynamic>(10, 10)) ));
+
+
+ // test of Dynamic defined Matrix (8, 6) of double
+
+ CALL_SUBTEST_16(( bdcsvd_verify_assert<Matrix<double,Dynamic,Dynamic> >
+ (Matrix<double,Dynamic,Dynamic>(8,6)) ));
+ CALL_SUBTEST_16(( compare_bdc_jacobi<Matrix<double,Dynamic,Dynamic> >
+ (Matrix<double,Dynamic,Dynamic>(8, 6), 0) ));
+ CALL_SUBTEST_16(( bdcsvd<Matrix<double,Dynamic,Dynamic> >
+ (Matrix<double,Dynamic,Dynamic>(8, 6)) ));
+
+
+
+ // test of Dynamic defined Matrix (36, 12) of float
+ CALL_SUBTEST_17(( compare_bdc_jacobi<Matrix<float,Dynamic,Dynamic> >
+ (Matrix<float,Dynamic,Dynamic>(36, 12), 0) ));
+ CALL_SUBTEST_17(( bdcsvd<Matrix<float,Dynamic,Dynamic> >
+ (Matrix<float,Dynamic,Dynamic>(36, 12)) ));
+
+ // test of Dynamic defined Matrix (5, 8) of double
+ CALL_SUBTEST_18(( compare_bdc_jacobi<Matrix<double,Dynamic,Dynamic> >
+ (Matrix<double,Dynamic,Dynamic>(5, 8), 0) ));
+ CALL_SUBTEST_18(( bdcsvd<Matrix<double,Dynamic,Dynamic> >
+ (Matrix<double,Dynamic,Dynamic>(5, 8)) ));
+
+
+ // non regression tests
+ CALL_SUBTEST_3(( bdcsvd_verify_assert(Matrix3f()) ));
+ CALL_SUBTEST_4(( bdcsvd_verify_assert(Matrix4d()) ));
+ CALL_SUBTEST_7(( bdcsvd_verify_assert(MatrixXf(10,12)) ));
+ CALL_SUBTEST_8(( bdcsvd_verify_assert(MatrixXcd(7,5)) ));
+
+ // SUBTESTS 1 and 2 on specifics matrix
+ for(int i = 0; i < g_repeat; i++) {
+ Matrix2cd m;
+ m << 0, 1,
+ 0, 1;
+ CALL_SUBTEST_1(( bdcsvd(m, false) ));
+ m << 1, 0,
+ 1, 0;
+ CALL_SUBTEST_1(( bdcsvd(m, false) ));
+
+ Matrix2d n;
+ n << 0, 0,
+ 0, 0;
+ CALL_SUBTEST_2(( bdcsvd(n, false) ));
+ n << 0, 0,
+ 0, 1;
+ CALL_SUBTEST_2(( bdcsvd(n, false) ));
+
+ // Statics matrix don't work with BDSVD yet
+ // bdc algo on a random 3x3 float matrix
+ // CALL_SUBTEST_3(( bdcsvd<Matrix3f>() ));
+ // bdc algo on a random 4x4 double matrix
+ // CALL_SUBTEST_4(( bdcsvd<Matrix4d>() ));
+ // bdc algo on a random 3x5 float matrix
+ // CALL_SUBTEST_5(( bdcsvd<Matrix<float,3,5> >() ));
+
+ int r = internal::random<int>(1, 30),
+ c = internal::random<int>(1, 30);
+ CALL_SUBTEST_7(( bdcsvd<MatrixXf>(MatrixXf(r,c)) ));
+ CALL_SUBTEST_8(( bdcsvd<MatrixXcd>(MatrixXcd(r,c)) ));
+ (void) r;
+ (void) c;
+
+ // Test on inf/nan matrix
+ CALL_SUBTEST_7( bdcsvd_inf_nan<MatrixXf>() );
+ }
+
+ CALL_SUBTEST_7(( bdcsvd<MatrixXf>(MatrixXf(internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE/2), internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE/2))) ));
+ CALL_SUBTEST_8(( bdcsvd<MatrixXcd>(MatrixXcd(internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE/3), internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE/3))) ));
+
+ // Test problem size constructors
+ CALL_SUBTEST_7( BDCSVD<MatrixXf>(10,10) );
+
+} // end test_bdcsvd
diff --git a/unsupported/test/dgmres.cpp b/unsupported/test/dgmres.cpp
new file mode 100644
index 000000000..2b11807c8
--- /dev/null
+++ b/unsupported/test/dgmres.cpp
@@ -0,0 +1,31 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2011 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2012 desire Nuentsa <desire.nuentsa_wakam@inria.fr
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../../test/sparse_solver.h"
+#include <Eigen/src/IterativeSolvers/DGMRES.h>
+
+template<typename T> void test_dgmres_T()
+{
+ DGMRES<SparseMatrix<T>, DiagonalPreconditioner<T> > dgmres_colmajor_diag;
+ DGMRES<SparseMatrix<T>, IdentityPreconditioner > dgmres_colmajor_I;
+ DGMRES<SparseMatrix<T>, IncompleteLUT<T> > dgmres_colmajor_ilut;
+ //GMRES<SparseMatrix<T>, SSORPreconditioner<T> > dgmres_colmajor_ssor;
+
+ CALL_SUBTEST( check_sparse_square_solving(dgmres_colmajor_diag) );
+// CALL_SUBTEST( check_sparse_square_solving(dgmres_colmajor_I) );
+ CALL_SUBTEST( check_sparse_square_solving(dgmres_colmajor_ilut) );
+ //CALL_SUBTEST( check_sparse_square_solving(dgmres_colmajor_ssor) );
+}
+
+void test_dgmres()
+{
+ CALL_SUBTEST_1(test_dgmres_T<double>());
+ CALL_SUBTEST_2(test_dgmres_T<std::complex<double> >());
+}
diff --git a/unsupported/test/gmres.cpp b/unsupported/test/gmres.cpp
index 647c16927..f2969116b 100644
--- a/unsupported/test/gmres.cpp
+++ b/unsupported/test/gmres.cpp
@@ -26,8 +26,6 @@ template<typename T> void test_gmres_T()
void test_gmres()
{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1(test_gmres_T<double>());
- CALL_SUBTEST_2(test_gmres_T<std::complex<double> >());
- }
+ CALL_SUBTEST_1(test_gmres_T<double>());
+ CALL_SUBTEST_2(test_gmres_T<std::complex<double> >());
}
diff --git a/unsupported/test/jacobisvd.cpp b/unsupported/test/jacobisvd.cpp
new file mode 100644
index 000000000..b4e884eee
--- /dev/null
+++ b/unsupported/test/jacobisvd.cpp
@@ -0,0 +1,198 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "svd_common.h"
+
+template<typename MatrixType, int QRPreconditioner>
+void jacobisvd_check_full(const MatrixType& m, const JacobiSVD<MatrixType, QRPreconditioner>& svd)
+{
+ svd_check_full<MatrixType, JacobiSVD<MatrixType, QRPreconditioner > >(m, svd);
+}
+
+template<typename MatrixType, int QRPreconditioner>
+void jacobisvd_compare_to_full(const MatrixType& m,
+ unsigned int computationOptions,
+ const JacobiSVD<MatrixType, QRPreconditioner>& referenceSvd)
+{
+ svd_compare_to_full<MatrixType, JacobiSVD<MatrixType, QRPreconditioner> >(m, computationOptions, referenceSvd);
+}
+
+
+template<typename MatrixType, int QRPreconditioner>
+void jacobisvd_solve(const MatrixType& m, unsigned int computationOptions)
+{
+ svd_solve< MatrixType, JacobiSVD< MatrixType, QRPreconditioner > >(m, computationOptions);
+}
+
+
+
+template<typename MatrixType, int QRPreconditioner>
+void jacobisvd_test_all_computation_options(const MatrixType& m)
+{
+
+ if (QRPreconditioner == NoQRPreconditioner && m.rows() != m.cols())
+ return;
+
+ JacobiSVD< MatrixType, QRPreconditioner > fullSvd(m, ComputeFullU|ComputeFullV);
+ svd_test_computation_options_1< MatrixType, JacobiSVD< MatrixType, QRPreconditioner > >(m, fullSvd);
+
+ if(QRPreconditioner == FullPivHouseholderQRPreconditioner)
+ return;
+ svd_test_computation_options_2< MatrixType, JacobiSVD< MatrixType, QRPreconditioner > >(m, fullSvd);
+
+}
+
+template<typename MatrixType>
+void jacobisvd(const MatrixType& a = MatrixType(), bool pickrandom = true)
+{
+ MatrixType m = pickrandom ? MatrixType::Random(a.rows(), a.cols()) : a;
+
+ jacobisvd_test_all_computation_options<MatrixType, FullPivHouseholderQRPreconditioner>(m);
+ jacobisvd_test_all_computation_options<MatrixType, ColPivHouseholderQRPreconditioner>(m);
+ jacobisvd_test_all_computation_options<MatrixType, HouseholderQRPreconditioner>(m);
+ jacobisvd_test_all_computation_options<MatrixType, NoQRPreconditioner>(m);
+}
+
+
+template<typename MatrixType>
+void jacobisvd_verify_assert(const MatrixType& m)
+{
+
+ svd_verify_assert<MatrixType, JacobiSVD< MatrixType > >(m);
+
+ typedef typename MatrixType::Index Index;
+ Index rows = m.rows();
+ Index cols = m.cols();
+
+ enum {
+ RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+ ColsAtCompileTime = MatrixType::ColsAtCompileTime
+ };
+
+ MatrixType a = MatrixType::Zero(rows, cols);
+ a.setZero();
+
+ if (ColsAtCompileTime == Dynamic)
+ {
+ JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner> svd_fullqr;
+ VERIFY_RAISES_ASSERT(svd_fullqr.compute(a, ComputeFullU|ComputeThinV))
+ VERIFY_RAISES_ASSERT(svd_fullqr.compute(a, ComputeThinU|ComputeThinV))
+ VERIFY_RAISES_ASSERT(svd_fullqr.compute(a, ComputeThinU|ComputeFullV))
+ }
+}
+
+template<typename MatrixType>
+void jacobisvd_method()
+{
+ enum { Size = MatrixType::RowsAtCompileTime };
+ typedef typename MatrixType::RealScalar RealScalar;
+ typedef Matrix<RealScalar, Size, 1> RealVecType;
+ MatrixType m = MatrixType::Identity();
+ VERIFY_IS_APPROX(m.jacobiSvd().singularValues(), RealVecType::Ones());
+ VERIFY_RAISES_ASSERT(m.jacobiSvd().matrixU());
+ VERIFY_RAISES_ASSERT(m.jacobiSvd().matrixV());
+ VERIFY_IS_APPROX(m.jacobiSvd(ComputeFullU|ComputeFullV).solve(m), m);
+}
+
+
+
+template<typename MatrixType>
+void jacobisvd_inf_nan()
+{
+ svd_inf_nan<MatrixType, JacobiSVD< MatrixType > >();
+}
+
+
+// Regression test for bug 286: JacobiSVD loops indefinitely with some
+// matrices containing denormal numbers.
+void jacobisvd_bug286()
+{
+#if defined __INTEL_COMPILER
+// shut up warning #239: floating point underflow
+#pragma warning push
+#pragma warning disable 239
+#endif
+ Matrix2d M;
+ M << -7.90884e-313, -4.94e-324,
+ 0, 5.60844e-313;
+#if defined __INTEL_COMPILER
+#pragma warning pop
+#endif
+ JacobiSVD<Matrix2d> svd;
+ svd.compute(M); // just check we don't loop indefinitely
+}
+
+
+void jacobisvd_preallocate()
+{
+ svd_preallocate< JacobiSVD <MatrixXf> >();
+}
+
+void test_jacobisvd()
+{
+ CALL_SUBTEST_11(( jacobisvd<Matrix<double,Dynamic,Dynamic> >
+ (Matrix<double,Dynamic,Dynamic>(16, 6)) ));
+
+ CALL_SUBTEST_3(( jacobisvd_verify_assert(Matrix3f()) ));
+ CALL_SUBTEST_4(( jacobisvd_verify_assert(Matrix4d()) ));
+ CALL_SUBTEST_7(( jacobisvd_verify_assert(MatrixXf(10,12)) ));
+ CALL_SUBTEST_8(( jacobisvd_verify_assert(MatrixXcd(7,5)) ));
+
+ for(int i = 0; i < g_repeat; i++) {
+ Matrix2cd m;
+ m << 0, 1,
+ 0, 1;
+ CALL_SUBTEST_1(( jacobisvd(m, false) ));
+ m << 1, 0,
+ 1, 0;
+ CALL_SUBTEST_1(( jacobisvd(m, false) ));
+
+ Matrix2d n;
+ n << 0, 0,
+ 0, 0;
+ CALL_SUBTEST_2(( jacobisvd(n, false) ));
+ n << 0, 0,
+ 0, 1;
+ CALL_SUBTEST_2(( jacobisvd(n, false) ));
+
+ CALL_SUBTEST_3(( jacobisvd<Matrix3f>() ));
+ CALL_SUBTEST_4(( jacobisvd<Matrix4d>() ));
+ CALL_SUBTEST_5(( jacobisvd<Matrix<float,3,5> >() ));
+ CALL_SUBTEST_6(( jacobisvd<Matrix<double,Dynamic,2> >(Matrix<double,Dynamic,2>(10,2)) ));
+
+ int r = internal::random<int>(1, 30),
+ c = internal::random<int>(1, 30);
+ CALL_SUBTEST_7(( jacobisvd<MatrixXf>(MatrixXf(r,c)) ));
+ CALL_SUBTEST_8(( jacobisvd<MatrixXcd>(MatrixXcd(r,c)) ));
+ (void) r;
+ (void) c;
+
+ // Test on inf/nan matrix
+ CALL_SUBTEST_7( jacobisvd_inf_nan<MatrixXf>() );
+ }
+
+ CALL_SUBTEST_7(( jacobisvd<MatrixXf>(MatrixXf(internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE/2), internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE/2))) ));
+ CALL_SUBTEST_8(( jacobisvd<MatrixXcd>(MatrixXcd(internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE/3), internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE/3))) ));
+
+
+ // test matrixbase method
+ CALL_SUBTEST_1(( jacobisvd_method<Matrix2cd>() ));
+ CALL_SUBTEST_3(( jacobisvd_method<Matrix3f>() ));
+
+
+ // Test problem size constructors
+ CALL_SUBTEST_7( JacobiSVD<MatrixXf>(10,10) );
+
+ // Check that preallocation avoids subsequent mallocs
+ CALL_SUBTEST_9( jacobisvd_preallocate() );
+
+ // Regression check for bug 286
+ CALL_SUBTEST_2( jacobisvd_bug286() );
+}
diff --git a/unsupported/test/kronecker_product.cpp b/unsupported/test/kronecker_product.cpp
index a60bd3022..8ddc6ec28 100644
--- a/unsupported/test/kronecker_product.cpp
+++ b/unsupported/test/kronecker_product.cpp
@@ -3,6 +3,7 @@
//
// Copyright (C) 2011 Kolja Brix <brix@igpm.rwth-aachen.de>
// Copyright (C) 2011 Andreas Platen <andiplaten@gmx.de>
+// Copyright (C) 2012 Chen-Pang He <jdh8@ms63.hinet.net>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
@@ -15,7 +16,7 @@
template<typename MatrixType>
-void check_dimension(const MatrixType& ab, const unsigned int rows, const unsigned int cols)
+void check_dimension(const MatrixType& ab, const int rows, const int cols)
{
VERIFY_IS_EQUAL(ab.rows(), rows);
VERIFY_IS_EQUAL(ab.cols(), cols);
@@ -85,68 +86,69 @@ void check_sparse_kronecker_product(const MatrixType& ab)
void test_kronecker_product()
{
// DM = dense matrix; SM = sparse matrix
+
Matrix<double, 2, 3> DM_a;
- MatrixXd DM_b(3,2);
SparseMatrix<double> SM_a(2,3);
+ SM_a.insert(0,0) = DM_a.coeffRef(0,0) = -0.4461540300782201;
+ SM_a.insert(0,1) = DM_a.coeffRef(0,1) = -0.8057364375283049;
+ SM_a.insert(0,2) = DM_a.coeffRef(0,2) = 0.3896572459516341;
+ SM_a.insert(1,0) = DM_a.coeffRef(1,0) = -0.9076572187376921;
+ SM_a.insert(1,1) = DM_a.coeffRef(1,1) = 0.6469156566545853;
+ SM_a.insert(1,2) = DM_a.coeffRef(1,2) = -0.3658010398782789;
+
+ MatrixXd DM_b(3,2);
SparseMatrix<double> SM_b(3,2);
- SM_a.insert(0,0) = DM_a(0,0) = -0.4461540300782201;
- SM_a.insert(0,1) = DM_a(0,1) = -0.8057364375283049;
- SM_a.insert(0,2) = DM_a(0,2) = 0.3896572459516341;
- SM_a.insert(1,0) = DM_a(1,0) = -0.9076572187376921;
- SM_a.insert(1,1) = DM_a(1,1) = 0.6469156566545853;
- SM_a.insert(1,2) = DM_a(1,2) = -0.3658010398782789;
- SM_b.insert(0,0) = DM_b(0,0) = 0.9004440976767099;
- SM_b.insert(0,1) = DM_b(0,1) = -0.2368830858139832;
- SM_b.insert(1,0) = DM_b(1,0) = -0.9311078389941825;
- SM_b.insert(1,1) = DM_b(1,1) = 0.5310335762980047;
- SM_b.insert(2,0) = DM_b(2,0) = -0.1225112806872035;
- SM_b.insert(2,1) = DM_b(2,1) = 0.5903998022741264;
+ SM_b.insert(0,0) = DM_b.coeffRef(0,0) = 0.9004440976767099;
+ SM_b.insert(0,1) = DM_b.coeffRef(0,1) = -0.2368830858139832;
+ SM_b.insert(1,0) = DM_b.coeffRef(1,0) = -0.9311078389941825;
+ SM_b.insert(1,1) = DM_b.coeffRef(1,1) = 0.5310335762980047;
+ SM_b.insert(2,0) = DM_b.coeffRef(2,0) = -0.1225112806872035;
+ SM_b.insert(2,1) = DM_b.coeffRef(2,1) = 0.5903998022741264;
+
SparseMatrix<double,RowMajor> SM_row_a(SM_a), SM_row_b(SM_b);
// test kroneckerProduct(DM_block,DM,DM_fixedSize)
- Matrix<double, 6, 6> DM_fix_ab;
- DM_fix_ab(0,0)=37.0;
- kroneckerProduct(DM_a.block(0,0,2,3),DM_b,DM_fix_ab);
+ Matrix<double, 6, 6> DM_fix_ab = kroneckerProduct(DM_a.topLeftCorner<2,3>(),DM_b);
+
CALL_SUBTEST(check_kronecker_product(DM_fix_ab));
+ for(int i=0;i<DM_fix_ab.rows();++i)
+ for(int j=0;j<DM_fix_ab.cols();++j)
+ VERIFY_IS_APPROX(kroneckerProduct(DM_a,DM_b).coeff(i,j), DM_fix_ab(i,j));
+
// test kroneckerProduct(DM,DM,DM_block)
MatrixXd DM_block_ab(10,15);
- DM_block_ab(0,0)=37.0;
- kroneckerProduct(DM_a,DM_b,DM_block_ab.block(2,5,6,6));
- CALL_SUBTEST(check_kronecker_product(DM_block_ab.block(2,5,6,6)));
+ DM_block_ab.block<6,6>(2,5) = kroneckerProduct(DM_a,DM_b);
+ CALL_SUBTEST(check_kronecker_product(DM_block_ab.block<6,6>(2,5)));
// test kroneckerProduct(DM,DM,DM)
- MatrixXd DM_ab(1,5);
- DM_ab(0,0)=37.0;
- kroneckerProduct(DM_a,DM_b,DM_ab);
+ MatrixXd DM_ab = kroneckerProduct(DM_a,DM_b);
CALL_SUBTEST(check_kronecker_product(DM_ab));
// test kroneckerProduct(SM,DM,SM)
- SparseMatrix<double> SM_ab(1,20);
- SM_ab.insert(0,0)=37.0;
- kroneckerProduct(SM_a,DM_b,SM_ab);
+ SparseMatrix<double> SM_ab = kroneckerProduct(SM_a,DM_b);
CALL_SUBTEST(check_kronecker_product(SM_ab));
- SparseMatrix<double,RowMajor> SM_ab2(10,3);
- SM_ab2.insert(0,0)=37.0;
- kroneckerProduct(SM_a,DM_b,SM_ab2);
+ SparseMatrix<double,RowMajor> SM_ab2 = kroneckerProduct(SM_a,DM_b);
CALL_SUBTEST(check_kronecker_product(SM_ab2));
// test kroneckerProduct(DM,SM,SM)
+ SM_ab.setZero();
SM_ab.insert(0,0)=37.0;
- kroneckerProduct(DM_a,SM_b,SM_ab);
+ SM_ab = kroneckerProduct(DM_a,SM_b);
CALL_SUBTEST(check_kronecker_product(SM_ab));
+ SM_ab2.setZero();
SM_ab2.insert(0,0)=37.0;
- kroneckerProduct(DM_a,SM_b,SM_ab2);
+ SM_ab2 = kroneckerProduct(DM_a,SM_b);
CALL_SUBTEST(check_kronecker_product(SM_ab2));
// test kroneckerProduct(SM,SM,SM)
SM_ab.resize(2,33);
SM_ab.insert(0,0)=37.0;
- kroneckerProduct(SM_a,SM_b,SM_ab);
+ SM_ab = kroneckerProduct(SM_a,SM_b);
CALL_SUBTEST(check_kronecker_product(SM_ab));
SM_ab2.resize(5,11);
SM_ab2.insert(0,0)=37.0;
- kroneckerProduct(SM_a,SM_b,SM_ab2);
+ SM_ab2 = kroneckerProduct(SM_a,SM_b);
CALL_SUBTEST(check_kronecker_product(SM_ab2));
// test kroneckerProduct(SM,SM,SM) with sparse pattern
@@ -158,22 +160,22 @@ void test_kronecker_product()
SM_a.insert(0,3) = -0.2;
SM_a.insert(2,4) = 0.3;
SM_a.finalize();
+
SM_b.insert(0,0) = 0.4;
SM_b.insert(2,1) = -0.5;
SM_b.finalize();
SM_ab.resize(1,1);
SM_ab.insert(0,0)=37.0;
- kroneckerProduct(SM_a,SM_b,SM_ab);
+ SM_ab = kroneckerProduct(SM_a,SM_b);
CALL_SUBTEST(check_sparse_kronecker_product(SM_ab));
// test dimension of result of kroneckerProduct(DM,DM,DM)
MatrixXd DM_a2(2,1);
MatrixXd DM_b2(5,4);
- MatrixXd DM_ab2;
- kroneckerProduct(DM_a2,DM_b2,DM_ab2);
+ MatrixXd DM_ab2 = kroneckerProduct(DM_a2,DM_b2);
CALL_SUBTEST(check_dimension(DM_ab2,2*5,1*4));
DM_a2.resize(10,9);
DM_b2.resize(4,8);
- kroneckerProduct(DM_a2,DM_b2,DM_ab2);
+ DM_ab2 = kroneckerProduct(DM_a2,DM_b2);
CALL_SUBTEST(check_dimension(DM_ab2,10*4,9*8));
}
diff --git a/unsupported/test/levenberg_marquardt.cpp b/unsupported/test/levenberg_marquardt.cpp
new file mode 100644
index 000000000..04464727d
--- /dev/null
+++ b/unsupported/test/levenberg_marquardt.cpp
@@ -0,0 +1,1448 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org>
+// Copyright (C) 2012 desire Nuentsa <desire.nuentsa_wakam@inria.fr
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+
+#include <stdio.h>
+
+#include "main.h"
+#include <unsupported/Eigen/LevenbergMarquardt>
+
+// This disables some useless Warnings on MSVC.
+// It is intended to be done for this test only.
+#include <Eigen/src/Core/util/DisableStupidWarnings.h>
+
+using std::sqrt;
+
+struct lmder_functor : DenseFunctor<double>
+{
+ lmder_functor(void): DenseFunctor<double>(3,15) {}
+ int operator()(const VectorXd &x, VectorXd &fvec) const
+ {
+ double tmp1, tmp2, tmp3;
+ static const double y[15] = {1.4e-1, 1.8e-1, 2.2e-1, 2.5e-1, 2.9e-1, 3.2e-1, 3.5e-1,
+ 3.9e-1, 3.7e-1, 5.8e-1, 7.3e-1, 9.6e-1, 1.34, 2.1, 4.39};
+
+ for (int i = 0; i < values(); i++)
+ {
+ tmp1 = i+1;
+ tmp2 = 16 - i - 1;
+ tmp3 = (i>=8)? tmp2 : tmp1;
+ fvec[i] = y[i] - (x[0] + tmp1/(x[1]*tmp2 + x[2]*tmp3));
+ }
+ return 0;
+ }
+
+ int df(const VectorXd &x, MatrixXd &fjac) const
+ {
+ double tmp1, tmp2, tmp3, tmp4;
+ for (int i = 0; i < values(); i++)
+ {
+ tmp1 = i+1;
+ tmp2 = 16 - i - 1;
+ tmp3 = (i>=8)? tmp2 : tmp1;
+ tmp4 = (x[1]*tmp2 + x[2]*tmp3); tmp4 = tmp4*tmp4;
+ fjac(i,0) = -1;
+ fjac(i,1) = tmp1*tmp2/tmp4;
+ fjac(i,2) = tmp1*tmp3/tmp4;
+ }
+ return 0;
+ }
+};
+
+void testLmder1()
+{
+ int n=3, info;
+
+ VectorXd x;
+
+ /* the following starting values provide a rough fit. */
+ x.setConstant(n, 1.);
+
+ // do the computation
+ lmder_functor functor;
+ LevenbergMarquardt<lmder_functor> lm(functor);
+ info = lm.lmder1(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 6);
+ VERIFY_IS_EQUAL(lm.njev(), 5);
+
+ // check norm
+ VERIFY_IS_APPROX(lm.fvec().blueNorm(), 0.09063596);
+
+ // check x
+ VectorXd x_ref(n);
+ x_ref << 0.08241058, 1.133037, 2.343695;
+ VERIFY_IS_APPROX(x, x_ref);
+}
+
+void testLmder()
+{
+ const int m=15, n=3;
+ int info;
+ double fnorm, covfac;
+ VectorXd x;
+
+ /* the following starting values provide a rough fit. */
+ x.setConstant(n, 1.);
+
+ // do the computation
+ lmder_functor functor;
+ LevenbergMarquardt<lmder_functor> lm(functor);
+ info = lm.minimize(x);
+
+ // check return values
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 6);
+ VERIFY_IS_EQUAL(lm.njev(), 5);
+
+ // check norm
+ fnorm = lm.fvec().blueNorm();
+ VERIFY_IS_APPROX(fnorm, 0.09063596);
+
+ // check x
+ VectorXd x_ref(n);
+ x_ref << 0.08241058, 1.133037, 2.343695;
+ VERIFY_IS_APPROX(x, x_ref);
+
+ // check covariance
+ covfac = fnorm*fnorm/(m-n);
+ internal::covar(lm.matrixR(), lm.permutation().indices()); // TODO : move this as a function of lm
+
+ MatrixXd cov_ref(n,n);
+ cov_ref <<
+ 0.0001531202, 0.002869941, -0.002656662,
+ 0.002869941, 0.09480935, -0.09098995,
+ -0.002656662, -0.09098995, 0.08778727;
+
+// std::cout << fjac*covfac << std::endl;
+
+ MatrixXd cov;
+ cov = covfac*lm.matrixR().topLeftCorner<n,n>();
+ VERIFY_IS_APPROX( cov, cov_ref);
+ // TODO: why isn't this allowed ? :
+ // VERIFY_IS_APPROX( covfac*fjac.topLeftCorner<n,n>() , cov_ref);
+}
+
+struct lmdif_functor : DenseFunctor<double>
+{
+ lmdif_functor(void) : DenseFunctor<double>(3,15) {}
+ int operator()(const VectorXd &x, VectorXd &fvec) const
+ {
+ int i;
+ double tmp1,tmp2,tmp3;
+ static const double y[15]={1.4e-1,1.8e-1,2.2e-1,2.5e-1,2.9e-1,3.2e-1,3.5e-1,3.9e-1,
+ 3.7e-1,5.8e-1,7.3e-1,9.6e-1,1.34e0,2.1e0,4.39e0};
+
+ assert(x.size()==3);
+ assert(fvec.size()==15);
+ for (i=0; i<15; i++)
+ {
+ tmp1 = i+1;
+ tmp2 = 15 - i;
+ tmp3 = tmp1;
+
+ if (i >= 8) tmp3 = tmp2;
+ fvec[i] = y[i] - (x[0] + tmp1/(x[1]*tmp2 + x[2]*tmp3));
+ }
+ return 0;
+ }
+};
+
+void testLmdif1()
+{
+ const int n=3;
+ int info;
+
+ VectorXd x(n), fvec(15);
+
+ /* the following starting values provide a rough fit. */
+ x.setConstant(n, 1.);
+
+ // do the computation
+ lmdif_functor functor;
+ DenseIndex nfev;
+ info = LevenbergMarquardt<lmdif_functor>::lmdif1(functor, x, &nfev);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+// VERIFY_IS_EQUAL(nfev, 26);
+
+ // check norm
+ functor(x, fvec);
+ VERIFY_IS_APPROX(fvec.blueNorm(), 0.09063596);
+
+ // check x
+ VectorXd x_ref(n);
+ x_ref << 0.0824106, 1.1330366, 2.3436947;
+ VERIFY_IS_APPROX(x, x_ref);
+
+}
+
+void testLmdif()
+{
+ const int m=15, n=3;
+ int info;
+ double fnorm, covfac;
+ VectorXd x(n);
+
+ /* the following starting values provide a rough fit. */
+ x.setConstant(n, 1.);
+
+ // do the computation
+ lmdif_functor functor;
+ NumericalDiff<lmdif_functor> numDiff(functor);
+ LevenbergMarquardt<NumericalDiff<lmdif_functor> > lm(numDiff);
+ info = lm.minimize(x);
+
+ // check return values
+ VERIFY_IS_EQUAL(info, 1);
+// VERIFY_IS_EQUAL(lm.nfev(), 26);
+
+ // check norm
+ fnorm = lm.fvec().blueNorm();
+ VERIFY_IS_APPROX(fnorm, 0.09063596);
+
+ // check x
+ VectorXd x_ref(n);
+ x_ref << 0.08241058, 1.133037, 2.343695;
+ VERIFY_IS_APPROX(x, x_ref);
+
+ // check covariance
+ covfac = fnorm*fnorm/(m-n);
+ internal::covar(lm.matrixR(), lm.permutation().indices()); // TODO : move this as a function of lm
+
+ MatrixXd cov_ref(n,n);
+ cov_ref <<
+ 0.0001531202, 0.002869942, -0.002656662,
+ 0.002869942, 0.09480937, -0.09098997,
+ -0.002656662, -0.09098997, 0.08778729;
+
+// std::cout << fjac*covfac << std::endl;
+
+ MatrixXd cov;
+ cov = covfac*lm.matrixR().topLeftCorner<n,n>();
+ VERIFY_IS_APPROX( cov, cov_ref);
+ // TODO: why isn't this allowed ? :
+ // VERIFY_IS_APPROX( covfac*fjac.topLeftCorner<n,n>() , cov_ref);
+}
+
+struct chwirut2_functor : DenseFunctor<double>
+{
+ chwirut2_functor(void) : DenseFunctor<double>(3,54) {}
+ static const double m_x[54];
+ static const double m_y[54];
+ int operator()(const VectorXd &b, VectorXd &fvec)
+ {
+ int i;
+
+ assert(b.size()==3);
+ assert(fvec.size()==54);
+ for(i=0; i<54; i++) {
+ double x = m_x[i];
+ fvec[i] = exp(-b[0]*x)/(b[1]+b[2]*x) - m_y[i];
+ }
+ return 0;
+ }
+ int df(const VectorXd &b, MatrixXd &fjac)
+ {
+ assert(b.size()==3);
+ assert(fjac.rows()==54);
+ assert(fjac.cols()==3);
+ for(int i=0; i<54; i++) {
+ double x = m_x[i];
+ double factor = 1./(b[1]+b[2]*x);
+ double e = exp(-b[0]*x);
+ fjac(i,0) = -x*e*factor;
+ fjac(i,1) = -e*factor*factor;
+ fjac(i,2) = -x*e*factor*factor;
+ }
+ return 0;
+ }
+};
+const double chwirut2_functor::m_x[54] = { 0.500E0, 1.000E0, 1.750E0, 3.750E0, 5.750E0, 0.875E0, 2.250E0, 3.250E0, 5.250E0, 0.750E0, 1.750E0, 2.750E0, 4.750E0, 0.625E0, 1.250E0, 2.250E0, 4.250E0, .500E0, 3.000E0, .750E0, 3.000E0, 1.500E0, 6.000E0, 3.000E0, 6.000E0, 1.500E0, 3.000E0, .500E0, 2.000E0, 4.000E0, .750E0, 2.000E0, 5.000E0, .750E0, 2.250E0, 3.750E0, 5.750E0, 3.000E0, .750E0, 2.500E0, 4.000E0, .750E0, 2.500E0, 4.000E0, .750E0, 2.500E0, 4.000E0, .500E0, 6.000E0, 3.000E0, .500E0, 2.750E0, .500E0, 1.750E0};
+const double chwirut2_functor::m_y[54] = { 92.9000E0 ,57.1000E0 ,31.0500E0 ,11.5875E0 ,8.0250E0 ,63.6000E0 ,21.4000E0 ,14.2500E0 ,8.4750E0 ,63.8000E0 ,26.8000E0 ,16.4625E0 ,7.1250E0 ,67.3000E0 ,41.0000E0 ,21.1500E0 ,8.1750E0 ,81.5000E0 ,13.1200E0 ,59.9000E0 ,14.6200E0 ,32.9000E0 ,5.4400E0 ,12.5600E0 ,5.4400E0 ,32.0000E0 ,13.9500E0 ,75.8000E0 ,20.0000E0 ,10.4200E0 ,59.5000E0 ,21.6700E0 ,8.5500E0 ,62.0000E0 ,20.2000E0 ,7.7600E0 ,3.7500E0 ,11.8100E0 ,54.7000E0 ,23.7000E0 ,11.5500E0 ,61.3000E0 ,17.7000E0 ,8.7400E0 ,59.2000E0 ,16.3000E0 ,8.6200E0 ,81.0000E0 ,4.8700E0 ,14.6200E0 ,81.7000E0 ,17.1700E0 ,81.3000E0 ,28.9000E0 };
+
+// http://www.itl.nist.gov/div898/strd/nls/data/chwirut2.shtml
+void testNistChwirut2(void)
+{
+ const int n=3;
+ int info;
+
+ VectorXd x(n);
+
+ /*
+ * First try
+ */
+ x<< 0.1, 0.01, 0.02;
+ // do the computation
+ chwirut2_functor functor;
+ LevenbergMarquardt<chwirut2_functor> lm(functor);
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+// VERIFY_IS_EQUAL(lm.nfev(), 10);
+ VERIFY_IS_EQUAL(lm.njev(), 8);
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 5.1304802941E+02);
+ // check x
+ VERIFY_IS_APPROX(x[0], 1.6657666537E-01);
+ VERIFY_IS_APPROX(x[1], 5.1653291286E-03);
+ VERIFY_IS_APPROX(x[2], 1.2150007096E-02);
+
+ /*
+ * Second try
+ */
+ x<< 0.15, 0.008, 0.010;
+ // do the computation
+ lm.resetParameters();
+ lm.setFtol(1.E6*NumTraits<double>::epsilon());
+ lm.setXtol(1.E6*NumTraits<double>::epsilon());
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+// VERIFY_IS_EQUAL(lm.nfev(), 7);
+ VERIFY_IS_EQUAL(lm.njev(), 6);
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 5.1304802941E+02);
+ // check x
+ VERIFY_IS_APPROX(x[0], 1.6657666537E-01);
+ VERIFY_IS_APPROX(x[1], 5.1653291286E-03);
+ VERIFY_IS_APPROX(x[2], 1.2150007096E-02);
+}
+
+
+struct misra1a_functor : DenseFunctor<double>
+{
+ misra1a_functor(void) : DenseFunctor<double>(2,14) {}
+ static const double m_x[14];
+ static const double m_y[14];
+ int operator()(const VectorXd &b, VectorXd &fvec)
+ {
+ assert(b.size()==2);
+ assert(fvec.size()==14);
+ for(int i=0; i<14; i++) {
+ fvec[i] = b[0]*(1.-exp(-b[1]*m_x[i])) - m_y[i] ;
+ }
+ return 0;
+ }
+ int df(const VectorXd &b, MatrixXd &fjac)
+ {
+ assert(b.size()==2);
+ assert(fjac.rows()==14);
+ assert(fjac.cols()==2);
+ for(int i=0; i<14; i++) {
+ fjac(i,0) = (1.-exp(-b[1]*m_x[i]));
+ fjac(i,1) = (b[0]*m_x[i]*exp(-b[1]*m_x[i]));
+ }
+ return 0;
+ }
+};
+const double misra1a_functor::m_x[14] = { 77.6E0, 114.9E0, 141.1E0, 190.8E0, 239.9E0, 289.0E0, 332.8E0, 378.4E0, 434.8E0, 477.3E0, 536.8E0, 593.1E0, 689.1E0, 760.0E0};
+const double misra1a_functor::m_y[14] = { 10.07E0, 14.73E0, 17.94E0, 23.93E0, 29.61E0, 35.18E0, 40.02E0, 44.82E0, 50.76E0, 55.05E0, 61.01E0, 66.40E0, 75.47E0, 81.78E0};
+
+// http://www.itl.nist.gov/div898/strd/nls/data/misra1a.shtml
+void testNistMisra1a(void)
+{
+ const int n=2;
+ int info;
+
+ VectorXd x(n);
+
+ /*
+ * First try
+ */
+ x<< 500., 0.0001;
+ // do the computation
+ misra1a_functor functor;
+ LevenbergMarquardt<misra1a_functor> lm(functor);
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 19);
+ VERIFY_IS_EQUAL(lm.njev(), 15);
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 1.2455138894E-01);
+ // check x
+ VERIFY_IS_APPROX(x[0], 2.3894212918E+02);
+ VERIFY_IS_APPROX(x[1], 5.5015643181E-04);
+
+ /*
+ * Second try
+ */
+ x<< 250., 0.0005;
+ // do the computation
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 5);
+ VERIFY_IS_EQUAL(lm.njev(), 4);
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 1.2455138894E-01);
+ // check x
+ VERIFY_IS_APPROX(x[0], 2.3894212918E+02);
+ VERIFY_IS_APPROX(x[1], 5.5015643181E-04);
+}
+
+struct hahn1_functor : DenseFunctor<double>
+{
+ hahn1_functor(void) : DenseFunctor<double>(7,236) {}
+ static const double m_x[236];
+ int operator()(const VectorXd &b, VectorXd &fvec)
+ {
+ static const double m_y[236] = { .591E0 , 1.547E0 , 2.902E0 , 2.894E0 , 4.703E0 , 6.307E0 , 7.03E0 , 7.898E0 , 9.470E0 , 9.484E0 , 10.072E0 , 10.163E0 , 11.615E0 , 12.005E0 , 12.478E0 , 12.982E0 , 12.970E0 , 13.926E0 , 14.452E0 , 14.404E0 , 15.190E0 , 15.550E0 , 15.528E0 , 15.499E0 , 16.131E0 , 16.438E0 , 16.387E0 , 16.549E0 , 16.872E0 , 16.830E0 , 16.926E0 , 16.907E0 , 16.966E0 , 17.060E0 , 17.122E0 , 17.311E0 , 17.355E0 , 17.668E0 , 17.767E0 , 17.803E0 , 17.765E0 , 17.768E0 , 17.736E0 , 17.858E0 , 17.877E0 , 17.912E0 , 18.046E0 , 18.085E0 , 18.291E0 , 18.357E0 , 18.426E0 , 18.584E0 , 18.610E0 , 18.870E0 , 18.795E0 , 19.111E0 , .367E0 , .796E0 , 0.892E0 , 1.903E0 , 2.150E0 , 3.697E0 , 5.870E0 , 6.421E0 , 7.422E0 , 9.944E0 , 11.023E0 , 11.87E0 , 12.786E0 , 14.067E0 , 13.974E0 , 14.462E0 , 14.464E0 , 15.381E0 , 15.483E0 , 15.59E0 , 16.075E0 , 16.347E0 , 16.181E0 , 16.915E0 , 17.003E0 , 16.978E0 , 17.756E0 , 17.808E0 , 17.868E0 , 18.481E0 , 18.486E0 , 19.090E0 , 16.062E0 , 16.337E0 , 16.345E0 ,
+ 16.388E0 , 17.159E0 , 17.116E0 , 17.164E0 , 17.123E0 , 17.979E0 , 17.974E0 , 18.007E0 , 17.993E0 , 18.523E0 , 18.669E0 , 18.617E0 , 19.371E0 , 19.330E0 , 0.080E0 , 0.248E0 , 1.089E0 , 1.418E0 , 2.278E0 , 3.624E0 , 4.574E0 , 5.556E0 , 7.267E0 , 7.695E0 , 9.136E0 , 9.959E0 , 9.957E0 , 11.600E0 , 13.138E0 , 13.564E0 , 13.871E0 , 13.994E0 , 14.947E0 , 15.473E0 , 15.379E0 , 15.455E0 , 15.908E0 , 16.114E0 , 17.071E0 , 17.135E0 , 17.282E0 , 17.368E0 , 17.483E0 , 17.764E0 , 18.185E0 , 18.271E0 , 18.236E0 , 18.237E0 , 18.523E0 , 18.627E0 , 18.665E0 , 19.086E0 , 0.214E0 , 0.943E0 , 1.429E0 , 2.241E0 , 2.951E0 , 3.782E0 , 4.757E0 , 5.602E0 , 7.169E0 , 8.920E0 , 10.055E0 , 12.035E0 , 12.861E0 , 13.436E0 , 14.167E0 , 14.755E0 , 15.168E0 , 15.651E0 , 15.746E0 , 16.216E0 , 16.445E0 , 16.965E0 , 17.121E0 , 17.206E0 , 17.250E0 , 17.339E0 , 17.793E0 , 18.123E0 , 18.49E0 , 18.566E0 , 18.645E0 , 18.706E0 , 18.924E0 , 19.1E0 , 0.375E0 , 0.471E0 , 1.504E0 , 2.204E0 , 2.813E0 , 4.765E0 , 9.835E0 , 10.040E0 , 11.946E0 ,
+12.596E0 ,
+13.303E0 , 13.922E0 , 14.440E0 , 14.951E0 , 15.627E0 , 15.639E0 , 15.814E0 , 16.315E0 , 16.334E0 , 16.430E0 , 16.423E0 , 17.024E0 , 17.009E0 , 17.165E0 , 17.134E0 , 17.349E0 , 17.576E0 , 17.848E0 , 18.090E0 , 18.276E0 , 18.404E0 , 18.519E0 , 19.133E0 , 19.074E0 , 19.239E0 , 19.280E0 , 19.101E0 , 19.398E0 , 19.252E0 , 19.89E0 , 20.007E0 , 19.929E0 , 19.268E0 , 19.324E0 , 20.049E0 , 20.107E0 , 20.062E0 , 20.065E0 , 19.286E0 , 19.972E0 , 20.088E0 , 20.743E0 , 20.83E0 , 20.935E0 , 21.035E0 , 20.93E0 , 21.074E0 , 21.085E0 , 20.935E0 };
+
+ // int called=0; printf("call hahn1_functor with iflag=%d, called=%d\n", iflag, called); if (iflag==1) called++;
+
+ assert(b.size()==7);
+ assert(fvec.size()==236);
+ for(int i=0; i<236; i++) {
+ double x=m_x[i], xx=x*x, xxx=xx*x;
+ fvec[i] = (b[0]+b[1]*x+b[2]*xx+b[3]*xxx) / (1.+b[4]*x+b[5]*xx+b[6]*xxx) - m_y[i];
+ }
+ return 0;
+ }
+
+ int df(const VectorXd &b, MatrixXd &fjac)
+ {
+ assert(b.size()==7);
+ assert(fjac.rows()==236);
+ assert(fjac.cols()==7);
+ for(int i=0; i<236; i++) {
+ double x=m_x[i], xx=x*x, xxx=xx*x;
+ double fact = 1./(1.+b[4]*x+b[5]*xx+b[6]*xxx);
+ fjac(i,0) = 1.*fact;
+ fjac(i,1) = x*fact;
+ fjac(i,2) = xx*fact;
+ fjac(i,3) = xxx*fact;
+ fact = - (b[0]+b[1]*x+b[2]*xx+b[3]*xxx) * fact * fact;
+ fjac(i,4) = x*fact;
+ fjac(i,5) = xx*fact;
+ fjac(i,6) = xxx*fact;
+ }
+ return 0;
+ }
+};
+const double hahn1_functor::m_x[236] = { 24.41E0 , 34.82E0 , 44.09E0 , 45.07E0 , 54.98E0 , 65.51E0 , 70.53E0 , 75.70E0 , 89.57E0 , 91.14E0 , 96.40E0 , 97.19E0 , 114.26E0 , 120.25E0 , 127.08E0 , 133.55E0 , 133.61E0 , 158.67E0 , 172.74E0 , 171.31E0 , 202.14E0 , 220.55E0 , 221.05E0 , 221.39E0 , 250.99E0 , 268.99E0 , 271.80E0 , 271.97E0 , 321.31E0 , 321.69E0 , 330.14E0 , 333.03E0 , 333.47E0 , 340.77E0 , 345.65E0 , 373.11E0 , 373.79E0 , 411.82E0 , 419.51E0 , 421.59E0 , 422.02E0 , 422.47E0 , 422.61E0 , 441.75E0 , 447.41E0 , 448.7E0 , 472.89E0 , 476.69E0 , 522.47E0 , 522.62E0 , 524.43E0 , 546.75E0 , 549.53E0 , 575.29E0 , 576.00E0 , 625.55E0 , 20.15E0 , 28.78E0 , 29.57E0 , 37.41E0 , 39.12E0 , 50.24E0 , 61.38E0 , 66.25E0 , 73.42E0 , 95.52E0 , 107.32E0 , 122.04E0 , 134.03E0 , 163.19E0 , 163.48E0 , 175.70E0 , 179.86E0 , 211.27E0 , 217.78E0 , 219.14E0 , 262.52E0 , 268.01E0 , 268.62E0 , 336.25E0 , 337.23E0 , 339.33E0 , 427.38E0 , 428.58E0 , 432.68E0 , 528.99E0 , 531.08E0 , 628.34E0 , 253.24E0 , 273.13E0 , 273.66E0 ,
+282.10E0 , 346.62E0 , 347.19E0 , 348.78E0 , 351.18E0 , 450.10E0 , 450.35E0 , 451.92E0 , 455.56E0 , 552.22E0 , 553.56E0 , 555.74E0 , 652.59E0 , 656.20E0 , 14.13E0 , 20.41E0 , 31.30E0 , 33.84E0 , 39.70E0 , 48.83E0 , 54.50E0 , 60.41E0 , 72.77E0 , 75.25E0 , 86.84E0 , 94.88E0 , 96.40E0 , 117.37E0 , 139.08E0 , 147.73E0 , 158.63E0 , 161.84E0 , 192.11E0 , 206.76E0 , 209.07E0 , 213.32E0 , 226.44E0 , 237.12E0 , 330.90E0 , 358.72E0 , 370.77E0 , 372.72E0 , 396.24E0 , 416.59E0 , 484.02E0 , 495.47E0 , 514.78E0 , 515.65E0 , 519.47E0 , 544.47E0 , 560.11E0 , 620.77E0 , 18.97E0 , 28.93E0 , 33.91E0 , 40.03E0 , 44.66E0 , 49.87E0 , 55.16E0 , 60.90E0 , 72.08E0 , 85.15E0 , 97.06E0 , 119.63E0 , 133.27E0 , 143.84E0 , 161.91E0 , 180.67E0 , 198.44E0 , 226.86E0 , 229.65E0 , 258.27E0 , 273.77E0 , 339.15E0 , 350.13E0 , 362.75E0 , 371.03E0 , 393.32E0 , 448.53E0 , 473.78E0 , 511.12E0 , 524.70E0 , 548.75E0 , 551.64E0 , 574.02E0 , 623.86E0 , 21.46E0 , 24.33E0 , 33.43E0 , 39.22E0 , 44.18E0 , 55.02E0 , 94.33E0 , 96.44E0 , 118.82E0 , 128.48E0 ,
+141.94E0 , 156.92E0 , 171.65E0 , 190.00E0 , 223.26E0 , 223.88E0 , 231.50E0 , 265.05E0 , 269.44E0 , 271.78E0 , 273.46E0 , 334.61E0 , 339.79E0 , 349.52E0 , 358.18E0 , 377.98E0 , 394.77E0 , 429.66E0 , 468.22E0 , 487.27E0 , 519.54E0 , 523.03E0 , 612.99E0 , 638.59E0 , 641.36E0 , 622.05E0 , 631.50E0 , 663.97E0 , 646.9E0 , 748.29E0 , 749.21E0 , 750.14E0 , 647.04E0 , 646.89E0 , 746.9E0 , 748.43E0 , 747.35E0 , 749.27E0 , 647.61E0 , 747.78E0 , 750.51E0 , 851.37E0 , 845.97E0 , 847.54E0 , 849.93E0 , 851.61E0 , 849.75E0 , 850.98E0 , 848.23E0};
+
+// http://www.itl.nist.gov/div898/strd/nls/data/hahn1.shtml
+void testNistHahn1(void)
+{
+ const int n=7;
+ int info;
+
+ VectorXd x(n);
+
+ /*
+ * First try
+ */
+ x<< 10., -1., .05, -.00001, -.05, .001, -.000001;
+ // do the computation
+ hahn1_functor functor;
+ LevenbergMarquardt<hahn1_functor> lm(functor);
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 11);
+ VERIFY_IS_EQUAL(lm.njev(), 10);
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 1.5324382854E+00);
+ // check x
+ VERIFY_IS_APPROX(x[0], 1.0776351733E+00);
+ VERIFY_IS_APPROX(x[1],-1.2269296921E-01);
+ VERIFY_IS_APPROX(x[2], 4.0863750610E-03);
+ VERIFY_IS_APPROX(x[3],-1.426264e-06); // shoulde be : -1.4262662514E-06
+ VERIFY_IS_APPROX(x[4],-5.7609940901E-03);
+ VERIFY_IS_APPROX(x[5], 2.4053735503E-04);
+ VERIFY_IS_APPROX(x[6],-1.2314450199E-07);
+
+ /*
+ * Second try
+ */
+ x<< .1, -.1, .005, -.000001, -.005, .0001, -.0000001;
+ // do the computation
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+// VERIFY_IS_EQUAL(lm.nfev(), 11);
+ VERIFY_IS_EQUAL(lm.njev(), 10);
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 1.5324382854E+00);
+ // check x
+ VERIFY_IS_APPROX(x[0], 1.077640); // should be : 1.0776351733E+00
+ VERIFY_IS_APPROX(x[1], -0.1226933); // should be : -1.2269296921E-01
+ VERIFY_IS_APPROX(x[2], 0.004086383); // should be : 4.0863750610E-03
+ VERIFY_IS_APPROX(x[3], -1.426277e-06); // shoulde be : -1.4262662514E-06
+ VERIFY_IS_APPROX(x[4],-5.7609940901E-03);
+ VERIFY_IS_APPROX(x[5], 0.00024053772); // should be : 2.4053735503E-04
+ VERIFY_IS_APPROX(x[6], -1.231450e-07); // should be : -1.2314450199E-07
+
+}
+
+struct misra1d_functor : DenseFunctor<double>
+{
+ misra1d_functor(void) : DenseFunctor<double>(2,14) {}
+ static const double x[14];
+ static const double y[14];
+ int operator()(const VectorXd &b, VectorXd &fvec)
+ {
+ assert(b.size()==2);
+ assert(fvec.size()==14);
+ for(int i=0; i<14; i++) {
+ fvec[i] = b[0]*b[1]*x[i]/(1.+b[1]*x[i]) - y[i];
+ }
+ return 0;
+ }
+ int df(const VectorXd &b, MatrixXd &fjac)
+ {
+ assert(b.size()==2);
+ assert(fjac.rows()==14);
+ assert(fjac.cols()==2);
+ for(int i=0; i<14; i++) {
+ double den = 1.+b[1]*x[i];
+ fjac(i,0) = b[1]*x[i] / den;
+ fjac(i,1) = b[0]*x[i]*(den-b[1]*x[i])/den/den;
+ }
+ return 0;
+ }
+};
+const double misra1d_functor::x[14] = { 77.6E0, 114.9E0, 141.1E0, 190.8E0, 239.9E0, 289.0E0, 332.8E0, 378.4E0, 434.8E0, 477.3E0, 536.8E0, 593.1E0, 689.1E0, 760.0E0};
+const double misra1d_functor::y[14] = { 10.07E0, 14.73E0, 17.94E0, 23.93E0, 29.61E0, 35.18E0, 40.02E0, 44.82E0, 50.76E0, 55.05E0, 61.01E0, 66.40E0, 75.47E0, 81.78E0};
+
+// http://www.itl.nist.gov/div898/strd/nls/data/misra1d.shtml
+void testNistMisra1d(void)
+{
+ const int n=2;
+ int info;
+
+ VectorXd x(n);
+
+ /*
+ * First try
+ */
+ x<< 500., 0.0001;
+ // do the computation
+ misra1d_functor functor;
+ LevenbergMarquardt<misra1d_functor> lm(functor);
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 9);
+ VERIFY_IS_EQUAL(lm.njev(), 7);
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 5.6419295283E-02);
+ // check x
+ VERIFY_IS_APPROX(x[0], 4.3736970754E+02);
+ VERIFY_IS_APPROX(x[1], 3.0227324449E-04);
+
+ /*
+ * Second try
+ */
+ x<< 450., 0.0003;
+ // do the computation
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 4);
+ VERIFY_IS_EQUAL(lm.njev(), 3);
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 5.6419295283E-02);
+ // check x
+ VERIFY_IS_APPROX(x[0], 4.3736970754E+02);
+ VERIFY_IS_APPROX(x[1], 3.0227324449E-04);
+}
+
+
+struct lanczos1_functor : DenseFunctor<double>
+{
+ lanczos1_functor(void) : DenseFunctor<double>(6,24) {}
+ static const double x[24];
+ static const double y[24];
+ int operator()(const VectorXd &b, VectorXd &fvec)
+ {
+ assert(b.size()==6);
+ assert(fvec.size()==24);
+ for(int i=0; i<24; i++)
+ fvec[i] = b[0]*exp(-b[1]*x[i]) + b[2]*exp(-b[3]*x[i]) + b[4]*exp(-b[5]*x[i]) - y[i];
+ return 0;
+ }
+ int df(const VectorXd &b, MatrixXd &fjac)
+ {
+ assert(b.size()==6);
+ assert(fjac.rows()==24);
+ assert(fjac.cols()==6);
+ for(int i=0; i<24; i++) {
+ fjac(i,0) = exp(-b[1]*x[i]);
+ fjac(i,1) = -b[0]*x[i]*exp(-b[1]*x[i]);
+ fjac(i,2) = exp(-b[3]*x[i]);
+ fjac(i,3) = -b[2]*x[i]*exp(-b[3]*x[i]);
+ fjac(i,4) = exp(-b[5]*x[i]);
+ fjac(i,5) = -b[4]*x[i]*exp(-b[5]*x[i]);
+ }
+ return 0;
+ }
+};
+const double lanczos1_functor::x[24] = { 0.000000000000E+00, 5.000000000000E-02, 1.000000000000E-01, 1.500000000000E-01, 2.000000000000E-01, 2.500000000000E-01, 3.000000000000E-01, 3.500000000000E-01, 4.000000000000E-01, 4.500000000000E-01, 5.000000000000E-01, 5.500000000000E-01, 6.000000000000E-01, 6.500000000000E-01, 7.000000000000E-01, 7.500000000000E-01, 8.000000000000E-01, 8.500000000000E-01, 9.000000000000E-01, 9.500000000000E-01, 1.000000000000E+00, 1.050000000000E+00, 1.100000000000E+00, 1.150000000000E+00 };
+const double lanczos1_functor::y[24] = { 2.513400000000E+00 ,2.044333373291E+00 ,1.668404436564E+00 ,1.366418021208E+00 ,1.123232487372E+00 ,9.268897180037E-01 ,7.679338563728E-01 ,6.388775523106E-01 ,5.337835317402E-01 ,4.479363617347E-01 ,3.775847884350E-01 ,3.197393199326E-01 ,2.720130773746E-01 ,2.324965529032E-01 ,1.996589546065E-01 ,1.722704126914E-01 ,1.493405660168E-01 ,1.300700206922E-01 ,1.138119324644E-01 ,1.000415587559E-01 ,8.833209084540E-02 ,7.833544019350E-02 ,6.976693743449E-02 ,6.239312536719E-02 };
+
+// http://www.itl.nist.gov/div898/strd/nls/data/lanczos1.shtml
+void testNistLanczos1(void)
+{
+ const int n=6;
+ int info;
+
+ VectorXd x(n);
+
+ /*
+ * First try
+ */
+ x<< 1.2, 0.3, 5.6, 5.5, 6.5, 7.6;
+ // do the computation
+ lanczos1_functor functor;
+ LevenbergMarquardt<lanczos1_functor> lm(functor);
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 2);
+ VERIFY_IS_EQUAL(lm.nfev(), 79);
+ VERIFY_IS_EQUAL(lm.njev(), 72);
+ // check norm^2
+// VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 1.430899764097e-25); // should be 1.4307867721E-25, but nist results are on 128-bit floats
+ // check x
+ VERIFY_IS_APPROX(x[0], 9.5100000027E-02);
+ VERIFY_IS_APPROX(x[1], 1.0000000001E+00);
+ VERIFY_IS_APPROX(x[2], 8.6070000013E-01);
+ VERIFY_IS_APPROX(x[3], 3.0000000002E+00);
+ VERIFY_IS_APPROX(x[4], 1.5575999998E+00);
+ VERIFY_IS_APPROX(x[5], 5.0000000001E+00);
+
+ /*
+ * Second try
+ */
+ x<< 0.5, 0.7, 3.6, 4.2, 4., 6.3;
+ // do the computation
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 2);
+ VERIFY_IS_EQUAL(lm.nfev(), 9);
+ VERIFY_IS_EQUAL(lm.njev(), 8);
+ // check norm^2
+// VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 1.428595533845e-25); // should be 1.4307867721E-25, but nist results are on 128-bit floats
+ // check x
+ VERIFY_IS_APPROX(x[0], 9.5100000027E-02);
+ VERIFY_IS_APPROX(x[1], 1.0000000001E+00);
+ VERIFY_IS_APPROX(x[2], 8.6070000013E-01);
+ VERIFY_IS_APPROX(x[3], 3.0000000002E+00);
+ VERIFY_IS_APPROX(x[4], 1.5575999998E+00);
+ VERIFY_IS_APPROX(x[5], 5.0000000001E+00);
+
+}
+
+struct rat42_functor : DenseFunctor<double>
+{
+ rat42_functor(void) : DenseFunctor<double>(3,9) {}
+ static const double x[9];
+ static const double y[9];
+ int operator()(const VectorXd &b, VectorXd &fvec)
+ {
+ assert(b.size()==3);
+ assert(fvec.size()==9);
+ for(int i=0; i<9; i++) {
+ fvec[i] = b[0] / (1.+exp(b[1]-b[2]*x[i])) - y[i];
+ }
+ return 0;
+ }
+
+ int df(const VectorXd &b, MatrixXd &fjac)
+ {
+ assert(b.size()==3);
+ assert(fjac.rows()==9);
+ assert(fjac.cols()==3);
+ for(int i=0; i<9; i++) {
+ double e = exp(b[1]-b[2]*x[i]);
+ fjac(i,0) = 1./(1.+e);
+ fjac(i,1) = -b[0]*e/(1.+e)/(1.+e);
+ fjac(i,2) = +b[0]*e*x[i]/(1.+e)/(1.+e);
+ }
+ return 0;
+ }
+};
+const double rat42_functor::x[9] = { 9.000E0, 14.000E0, 21.000E0, 28.000E0, 42.000E0, 57.000E0, 63.000E0, 70.000E0, 79.000E0 };
+const double rat42_functor::y[9] = { 8.930E0 ,10.800E0 ,18.590E0 ,22.330E0 ,39.350E0 ,56.110E0 ,61.730E0 ,64.620E0 ,67.080E0 };
+
+// http://www.itl.nist.gov/div898/strd/nls/data/ratkowsky2.shtml
+void testNistRat42(void)
+{
+ const int n=3;
+ int info;
+
+ VectorXd x(n);
+
+ /*
+ * First try
+ */
+ x<< 100., 1., 0.1;
+ // do the computation
+ rat42_functor functor;
+ LevenbergMarquardt<rat42_functor> lm(functor);
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 10);
+ VERIFY_IS_EQUAL(lm.njev(), 8);
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 8.0565229338E+00);
+ // check x
+ VERIFY_IS_APPROX(x[0], 7.2462237576E+01);
+ VERIFY_IS_APPROX(x[1], 2.6180768402E+00);
+ VERIFY_IS_APPROX(x[2], 6.7359200066E-02);
+
+ /*
+ * Second try
+ */
+ x<< 75., 2.5, 0.07;
+ // do the computation
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 6);
+ VERIFY_IS_EQUAL(lm.njev(), 5);
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 8.0565229338E+00);
+ // check x
+ VERIFY_IS_APPROX(x[0], 7.2462237576E+01);
+ VERIFY_IS_APPROX(x[1], 2.6180768402E+00);
+ VERIFY_IS_APPROX(x[2], 6.7359200066E-02);
+}
+
+struct MGH10_functor : DenseFunctor<double>
+{
+ MGH10_functor(void) : DenseFunctor<double>(3,16) {}
+ static const double x[16];
+ static const double y[16];
+ int operator()(const VectorXd &b, VectorXd &fvec)
+ {
+ assert(b.size()==3);
+ assert(fvec.size()==16);
+ for(int i=0; i<16; i++)
+ fvec[i] = b[0] * exp(b[1]/(x[i]+b[2])) - y[i];
+ return 0;
+ }
+ int df(const VectorXd &b, MatrixXd &fjac)
+ {
+ assert(b.size()==3);
+ assert(fjac.rows()==16);
+ assert(fjac.cols()==3);
+ for(int i=0; i<16; i++) {
+ double factor = 1./(x[i]+b[2]);
+ double e = exp(b[1]*factor);
+ fjac(i,0) = e;
+ fjac(i,1) = b[0]*factor*e;
+ fjac(i,2) = -b[1]*b[0]*factor*factor*e;
+ }
+ return 0;
+ }
+};
+const double MGH10_functor::x[16] = { 5.000000E+01, 5.500000E+01, 6.000000E+01, 6.500000E+01, 7.000000E+01, 7.500000E+01, 8.000000E+01, 8.500000E+01, 9.000000E+01, 9.500000E+01, 1.000000E+02, 1.050000E+02, 1.100000E+02, 1.150000E+02, 1.200000E+02, 1.250000E+02 };
+const double MGH10_functor::y[16] = { 3.478000E+04, 2.861000E+04, 2.365000E+04, 1.963000E+04, 1.637000E+04, 1.372000E+04, 1.154000E+04, 9.744000E+03, 8.261000E+03, 7.030000E+03, 6.005000E+03, 5.147000E+03, 4.427000E+03, 3.820000E+03, 3.307000E+03, 2.872000E+03 };
+
+// http://www.itl.nist.gov/div898/strd/nls/data/mgh10.shtml
+void testNistMGH10(void)
+{
+ const int n=3;
+ int info;
+
+ VectorXd x(n);
+
+ /*
+ * First try
+ */
+ x<< 2., 400000., 25000.;
+ // do the computation
+ MGH10_functor functor;
+ LevenbergMarquardt<MGH10_functor> lm(functor);
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 284 );
+ VERIFY_IS_EQUAL(lm.njev(), 249 );
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 8.7945855171E+01);
+ // check x
+ VERIFY_IS_APPROX(x[0], 5.6096364710E-03);
+ VERIFY_IS_APPROX(x[1], 6.1813463463E+03);
+ VERIFY_IS_APPROX(x[2], 3.4522363462E+02);
+
+ /*
+ * Second try
+ */
+ x<< 0.02, 4000., 250.;
+ // do the computation
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 126);
+ VERIFY_IS_EQUAL(lm.njev(), 116);
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 8.7945855171E+01);
+ // check x
+ VERIFY_IS_APPROX(x[0], 5.6096364710E-03);
+ VERIFY_IS_APPROX(x[1], 6.1813463463E+03);
+ VERIFY_IS_APPROX(x[2], 3.4522363462E+02);
+}
+
+
+struct BoxBOD_functor : DenseFunctor<double>
+{
+ BoxBOD_functor(void) : DenseFunctor<double>(2,6) {}
+ static const double x[6];
+ int operator()(const VectorXd &b, VectorXd &fvec)
+ {
+ static const double y[6] = { 109., 149., 149., 191., 213., 224. };
+ assert(b.size()==2);
+ assert(fvec.size()==6);
+ for(int i=0; i<6; i++)
+ fvec[i] = b[0]*(1.-exp(-b[1]*x[i])) - y[i];
+ return 0;
+ }
+ int df(const VectorXd &b, MatrixXd &fjac)
+ {
+ assert(b.size()==2);
+ assert(fjac.rows()==6);
+ assert(fjac.cols()==2);
+ for(int i=0; i<6; i++) {
+ double e = exp(-b[1]*x[i]);
+ fjac(i,0) = 1.-e;
+ fjac(i,1) = b[0]*x[i]*e;
+ }
+ return 0;
+ }
+};
+const double BoxBOD_functor::x[6] = { 1., 2., 3., 5., 7., 10. };
+
+// http://www.itl.nist.gov/div898/strd/nls/data/boxbod.shtml
+void testNistBoxBOD(void)
+{
+ const int n=2;
+ int info;
+
+ VectorXd x(n);
+
+ /*
+ * First try
+ */
+ x<< 1., 1.;
+ // do the computation
+ BoxBOD_functor functor;
+ LevenbergMarquardt<BoxBOD_functor> lm(functor);
+ lm.setFtol(1.E6*NumTraits<double>::epsilon());
+ lm.setXtol(1.E6*NumTraits<double>::epsilon());
+ lm.setFactor(10);
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 31);
+ VERIFY_IS_EQUAL(lm.njev(), 25);
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 1.1680088766E+03);
+ // check x
+ VERIFY_IS_APPROX(x[0], 2.1380940889E+02);
+ VERIFY_IS_APPROX(x[1], 5.4723748542E-01);
+
+ /*
+ * Second try
+ */
+ x<< 100., 0.75;
+ // do the computation
+ lm.resetParameters();
+ lm.setFtol(NumTraits<double>::epsilon());
+ lm.setXtol( NumTraits<double>::epsilon());
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 15 );
+ VERIFY_IS_EQUAL(lm.njev(), 14 );
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 1.1680088766E+03);
+ // check x
+ VERIFY_IS_APPROX(x[0], 2.1380940889E+02);
+ VERIFY_IS_APPROX(x[1], 5.4723748542E-01);
+}
+
+struct MGH17_functor : DenseFunctor<double>
+{
+ MGH17_functor(void) : DenseFunctor<double>(5,33) {}
+ static const double x[33];
+ static const double y[33];
+ int operator()(const VectorXd &b, VectorXd &fvec)
+ {
+ assert(b.size()==5);
+ assert(fvec.size()==33);
+ for(int i=0; i<33; i++)
+ fvec[i] = b[0] + b[1]*exp(-b[3]*x[i]) + b[2]*exp(-b[4]*x[i]) - y[i];
+ return 0;
+ }
+ int df(const VectorXd &b, MatrixXd &fjac)
+ {
+ assert(b.size()==5);
+ assert(fjac.rows()==33);
+ assert(fjac.cols()==5);
+ for(int i=0; i<33; i++) {
+ fjac(i,0) = 1.;
+ fjac(i,1) = exp(-b[3]*x[i]);
+ fjac(i,2) = exp(-b[4]*x[i]);
+ fjac(i,3) = -x[i]*b[1]*exp(-b[3]*x[i]);
+ fjac(i,4) = -x[i]*b[2]*exp(-b[4]*x[i]);
+ }
+ return 0;
+ }
+};
+const double MGH17_functor::x[33] = { 0.000000E+00, 1.000000E+01, 2.000000E+01, 3.000000E+01, 4.000000E+01, 5.000000E+01, 6.000000E+01, 7.000000E+01, 8.000000E+01, 9.000000E+01, 1.000000E+02, 1.100000E+02, 1.200000E+02, 1.300000E+02, 1.400000E+02, 1.500000E+02, 1.600000E+02, 1.700000E+02, 1.800000E+02, 1.900000E+02, 2.000000E+02, 2.100000E+02, 2.200000E+02, 2.300000E+02, 2.400000E+02, 2.500000E+02, 2.600000E+02, 2.700000E+02, 2.800000E+02, 2.900000E+02, 3.000000E+02, 3.100000E+02, 3.200000E+02 };
+const double MGH17_functor::y[33] = { 8.440000E-01, 9.080000E-01, 9.320000E-01, 9.360000E-01, 9.250000E-01, 9.080000E-01, 8.810000E-01, 8.500000E-01, 8.180000E-01, 7.840000E-01, 7.510000E-01, 7.180000E-01, 6.850000E-01, 6.580000E-01, 6.280000E-01, 6.030000E-01, 5.800000E-01, 5.580000E-01, 5.380000E-01, 5.220000E-01, 5.060000E-01, 4.900000E-01, 4.780000E-01, 4.670000E-01, 4.570000E-01, 4.480000E-01, 4.380000E-01, 4.310000E-01, 4.240000E-01, 4.200000E-01, 4.140000E-01, 4.110000E-01, 4.060000E-01 };
+
+// http://www.itl.nist.gov/div898/strd/nls/data/mgh17.shtml
+void testNistMGH17(void)
+{
+ const int n=5;
+ int info;
+
+ VectorXd x(n);
+
+ /*
+ * First try
+ */
+ x<< 50., 150., -100., 1., 2.;
+ // do the computation
+ MGH17_functor functor;
+ LevenbergMarquardt<MGH17_functor> lm(functor);
+ lm.setFtol(NumTraits<double>::epsilon());
+ lm.setXtol(NumTraits<double>::epsilon());
+ lm.setMaxfev(1000);
+ info = lm.minimize(x);
+
+ // check return value
+// VERIFY_IS_EQUAL(info, 2); //FIXME Use (lm.info() == Success)
+// VERIFY_IS_EQUAL(lm.nfev(), 602 );
+ VERIFY_IS_EQUAL(lm.njev(), 545 );
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 5.4648946975E-05);
+ // check x
+ VERIFY_IS_APPROX(x[0], 3.7541005211E-01);
+ VERIFY_IS_APPROX(x[1], 1.9358469127E+00);
+ VERIFY_IS_APPROX(x[2], -1.4646871366E+00);
+ VERIFY_IS_APPROX(x[3], 1.2867534640E-02);
+ VERIFY_IS_APPROX(x[4], 2.2122699662E-02);
+
+ /*
+ * Second try
+ */
+ x<< 0.5 ,1.5 ,-1 ,0.01 ,0.02;
+ // do the computation
+ lm.resetParameters();
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 18);
+ VERIFY_IS_EQUAL(lm.njev(), 15);
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 5.4648946975E-05);
+ // check x
+ VERIFY_IS_APPROX(x[0], 3.7541005211E-01);
+ VERIFY_IS_APPROX(x[1], 1.9358469127E+00);
+ VERIFY_IS_APPROX(x[2], -1.4646871366E+00);
+ VERIFY_IS_APPROX(x[3], 1.2867534640E-02);
+ VERIFY_IS_APPROX(x[4], 2.2122699662E-02);
+}
+
+struct MGH09_functor : DenseFunctor<double>
+{
+ MGH09_functor(void) : DenseFunctor<double>(4,11) {}
+ static const double _x[11];
+ static const double y[11];
+ int operator()(const VectorXd &b, VectorXd &fvec)
+ {
+ assert(b.size()==4);
+ assert(fvec.size()==11);
+ for(int i=0; i<11; i++) {
+ double x = _x[i], xx=x*x;
+ fvec[i] = b[0]*(xx+x*b[1])/(xx+x*b[2]+b[3]) - y[i];
+ }
+ return 0;
+ }
+ int df(const VectorXd &b, MatrixXd &fjac)
+ {
+ assert(b.size()==4);
+ assert(fjac.rows()==11);
+ assert(fjac.cols()==4);
+ for(int i=0; i<11; i++) {
+ double x = _x[i], xx=x*x;
+ double factor = 1./(xx+x*b[2]+b[3]);
+ fjac(i,0) = (xx+x*b[1]) * factor;
+ fjac(i,1) = b[0]*x* factor;
+ fjac(i,2) = - b[0]*(xx+x*b[1]) * x * factor * factor;
+ fjac(i,3) = - b[0]*(xx+x*b[1]) * factor * factor;
+ }
+ return 0;
+ }
+};
+const double MGH09_functor::_x[11] = { 4., 2., 1., 5.E-1 , 2.5E-01, 1.670000E-01, 1.250000E-01, 1.E-01, 8.330000E-02, 7.140000E-02, 6.250000E-02 };
+const double MGH09_functor::y[11] = { 1.957000E-01, 1.947000E-01, 1.735000E-01, 1.600000E-01, 8.440000E-02, 6.270000E-02, 4.560000E-02, 3.420000E-02, 3.230000E-02, 2.350000E-02, 2.460000E-02 };
+
+// http://www.itl.nist.gov/div898/strd/nls/data/mgh09.shtml
+void testNistMGH09(void)
+{
+ const int n=4;
+ int info;
+
+ VectorXd x(n);
+
+ /*
+ * First try
+ */
+ x<< 25., 39, 41.5, 39.;
+ // do the computation
+ MGH09_functor functor;
+ LevenbergMarquardt<MGH09_functor> lm(functor);
+ lm.setMaxfev(1000);
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 490 );
+ VERIFY_IS_EQUAL(lm.njev(), 376 );
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 3.0750560385E-04);
+ // check x
+ VERIFY_IS_APPROX(x[0], 0.1928077089); // should be 1.9280693458E-01
+ VERIFY_IS_APPROX(x[1], 0.19126423573); // should be 1.9128232873E-01
+ VERIFY_IS_APPROX(x[2], 0.12305309914); // should be 1.2305650693E-01
+ VERIFY_IS_APPROX(x[3], 0.13605395375); // should be 1.3606233068E-01
+
+ /*
+ * Second try
+ */
+ x<< 0.25, 0.39, 0.415, 0.39;
+ // do the computation
+ lm.resetParameters();
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 18);
+ VERIFY_IS_EQUAL(lm.njev(), 16);
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 3.0750560385E-04);
+ // check x
+ VERIFY_IS_APPROX(x[0], 0.19280781); // should be 1.9280693458E-01
+ VERIFY_IS_APPROX(x[1], 0.19126265); // should be 1.9128232873E-01
+ VERIFY_IS_APPROX(x[2], 0.12305280); // should be 1.2305650693E-01
+ VERIFY_IS_APPROX(x[3], 0.13605322); // should be 1.3606233068E-01
+}
+
+
+
+struct Bennett5_functor : DenseFunctor<double>
+{
+ Bennett5_functor(void) : DenseFunctor<double>(3,154) {}
+ static const double x[154];
+ static const double y[154];
+ int operator()(const VectorXd &b, VectorXd &fvec)
+ {
+ assert(b.size()==3);
+ assert(fvec.size()==154);
+ for(int i=0; i<154; i++)
+ fvec[i] = b[0]* pow(b[1]+x[i],-1./b[2]) - y[i];
+ return 0;
+ }
+ int df(const VectorXd &b, MatrixXd &fjac)
+ {
+ assert(b.size()==3);
+ assert(fjac.rows()==154);
+ assert(fjac.cols()==3);
+ for(int i=0; i<154; i++) {
+ double e = pow(b[1]+x[i],-1./b[2]);
+ fjac(i,0) = e;
+ fjac(i,1) = - b[0]*e/b[2]/(b[1]+x[i]);
+ fjac(i,2) = b[0]*e*log(b[1]+x[i])/b[2]/b[2];
+ }
+ return 0;
+ }
+};
+const double Bennett5_functor::x[154] = { 7.447168E0, 8.102586E0, 8.452547E0, 8.711278E0, 8.916774E0, 9.087155E0, 9.232590E0, 9.359535E0, 9.472166E0, 9.573384E0, 9.665293E0, 9.749461E0, 9.827092E0, 9.899128E0, 9.966321E0, 10.029280E0, 10.088510E0, 10.144430E0, 10.197380E0, 10.247670E0, 10.295560E0, 10.341250E0, 10.384950E0, 10.426820E0, 10.467000E0, 10.505640E0, 10.542830E0, 10.578690E0, 10.613310E0, 10.646780E0, 10.679150E0, 10.710520E0, 10.740920E0, 10.770440E0, 10.799100E0, 10.826970E0, 10.854080E0, 10.880470E0, 10.906190E0, 10.931260E0, 10.955720E0, 10.979590E0, 11.002910E0, 11.025700E0, 11.047980E0, 11.069770E0, 11.091100E0, 11.111980E0, 11.132440E0, 11.152480E0, 11.172130E0, 11.191410E0, 11.210310E0, 11.228870E0, 11.247090E0, 11.264980E0, 11.282560E0, 11.299840E0, 11.316820E0, 11.333520E0, 11.349940E0, 11.366100E0, 11.382000E0, 11.397660E0, 11.413070E0, 11.428240E0, 11.443200E0, 11.457930E0, 11.472440E0, 11.486750E0, 11.500860E0, 11.514770E0, 11.528490E0, 11.542020E0, 11.555380E0, 11.568550E0,
+11.581560E0, 11.594420E0, 11.607121E0, 11.619640E0, 11.632000E0, 11.644210E0, 11.656280E0, 11.668200E0, 11.679980E0, 11.691620E0, 11.703130E0, 11.714510E0, 11.725760E0, 11.736880E0, 11.747890E0, 11.758780E0, 11.769550E0, 11.780200E0, 11.790730E0, 11.801160E0, 11.811480E0, 11.821700E0, 11.831810E0, 11.841820E0, 11.851730E0, 11.861550E0, 11.871270E0, 11.880890E0, 11.890420E0, 11.899870E0, 11.909220E0, 11.918490E0, 11.927680E0, 11.936780E0, 11.945790E0, 11.954730E0, 11.963590E0, 11.972370E0, 11.981070E0, 11.989700E0, 11.998260E0, 12.006740E0, 12.015150E0, 12.023490E0, 12.031760E0, 12.039970E0, 12.048100E0, 12.056170E0, 12.064180E0, 12.072120E0, 12.080010E0, 12.087820E0, 12.095580E0, 12.103280E0, 12.110920E0, 12.118500E0, 12.126030E0, 12.133500E0, 12.140910E0, 12.148270E0, 12.155570E0, 12.162830E0, 12.170030E0, 12.177170E0, 12.184270E0, 12.191320E0, 12.198320E0, 12.205270E0, 12.212170E0, 12.219030E0, 12.225840E0, 12.232600E0, 12.239320E0, 12.245990E0, 12.252620E0, 12.259200E0, 12.265750E0, 12.272240E0 };
+const double Bennett5_functor::y[154] = { -34.834702E0 ,-34.393200E0 ,-34.152901E0 ,-33.979099E0 ,-33.845901E0 ,-33.732899E0 ,-33.640301E0 ,-33.559200E0 ,-33.486801E0 ,-33.423100E0 ,-33.365101E0 ,-33.313000E0 ,-33.260899E0 ,-33.217400E0 ,-33.176899E0 ,-33.139198E0 ,-33.101601E0 ,-33.066799E0 ,-33.035000E0 ,-33.003101E0 ,-32.971298E0 ,-32.942299E0 ,-32.916302E0 ,-32.890202E0 ,-32.864101E0 ,-32.841000E0 ,-32.817799E0 ,-32.797501E0 ,-32.774300E0 ,-32.757000E0 ,-32.733799E0 ,-32.716400E0 ,-32.699100E0 ,-32.678799E0 ,-32.661400E0 ,-32.644001E0 ,-32.626701E0 ,-32.612202E0 ,-32.597698E0 ,-32.583199E0 ,-32.568699E0 ,-32.554298E0 ,-32.539799E0 ,-32.525299E0 ,-32.510799E0 ,-32.499199E0 ,-32.487598E0 ,-32.473202E0 ,-32.461601E0 ,-32.435501E0 ,-32.435501E0 ,-32.426800E0 ,-32.412300E0 ,-32.400799E0 ,-32.392101E0 ,-32.380501E0 ,-32.366001E0 ,-32.357300E0 ,-32.348598E0 ,-32.339901E0 ,-32.328400E0 ,-32.319698E0 ,-32.311001E0 ,-32.299400E0 ,-32.290699E0 ,-32.282001E0 ,-32.273300E0 ,-32.264599E0 ,-32.256001E0 ,-32.247299E0
+,-32.238602E0 ,-32.229900E0 ,-32.224098E0 ,-32.215401E0 ,-32.203800E0 ,-32.198002E0 ,-32.189400E0 ,-32.183601E0 ,-32.174900E0 ,-32.169102E0 ,-32.163300E0 ,-32.154598E0 ,-32.145901E0 ,-32.140099E0 ,-32.131401E0 ,-32.125599E0 ,-32.119801E0 ,-32.111198E0 ,-32.105400E0 ,-32.096699E0 ,-32.090900E0 ,-32.088001E0 ,-32.079300E0 ,-32.073502E0 ,-32.067699E0 ,-32.061901E0 ,-32.056099E0 ,-32.050301E0 ,-32.044498E0 ,-32.038799E0 ,-32.033001E0 ,-32.027199E0 ,-32.024300E0 ,-32.018501E0 ,-32.012699E0 ,-32.004002E0 ,-32.001099E0 ,-31.995300E0 ,-31.989500E0 ,-31.983700E0 ,-31.977900E0 ,-31.972099E0 ,-31.969299E0 ,-31.963501E0 ,-31.957701E0 ,-31.951900E0 ,-31.946100E0 ,-31.940300E0 ,-31.937401E0 ,-31.931601E0 ,-31.925800E0 ,-31.922899E0 ,-31.917101E0 ,-31.911301E0 ,-31.908400E0 ,-31.902599E0 ,-31.896900E0 ,-31.893999E0 ,-31.888201E0 ,-31.885300E0 ,-31.882401E0 ,-31.876600E0 ,-31.873699E0 ,-31.867901E0 ,-31.862101E0 ,-31.859200E0 ,-31.856300E0 ,-31.850500E0 ,-31.844700E0 ,-31.841801E0 ,-31.838900E0 ,-31.833099E0 ,-31.830200E0 ,
+-31.827299E0 ,-31.821600E0 ,-31.818701E0 ,-31.812901E0 ,-31.809999E0 ,-31.807100E0 ,-31.801300E0 ,-31.798401E0 ,-31.795500E0 ,-31.789700E0 ,-31.786800E0 };
+
+// http://www.itl.nist.gov/div898/strd/nls/data/bennett5.shtml
+void testNistBennett5(void)
+{
+ const int n=3;
+ int info;
+
+ VectorXd x(n);
+
+ /*
+ * First try
+ */
+ x<< -2000., 50., 0.8;
+ // do the computation
+ Bennett5_functor functor;
+ LevenbergMarquardt<Bennett5_functor> lm(functor);
+ lm.setMaxfev(1000);
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 758);
+ VERIFY_IS_EQUAL(lm.njev(), 744);
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 5.2404744073E-04);
+ // check x
+ VERIFY_IS_APPROX(x[0], -2.5235058043E+03);
+ VERIFY_IS_APPROX(x[1], 4.6736564644E+01);
+ VERIFY_IS_APPROX(x[2], 9.3218483193E-01);
+ /*
+ * Second try
+ */
+ x<< -1500., 45., 0.85;
+ // do the computation
+ lm.resetParameters();
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 203);
+ VERIFY_IS_EQUAL(lm.njev(), 192);
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 5.2404744073E-04);
+ // check x
+ VERIFY_IS_APPROX(x[0], -2523.3007865); // should be -2.5235058043E+03
+ VERIFY_IS_APPROX(x[1], 46.735705771); // should be 4.6736564644E+01);
+ VERIFY_IS_APPROX(x[2], 0.93219881891); // should be 9.3218483193E-01);
+}
+
+struct thurber_functor : DenseFunctor<double>
+{
+ thurber_functor(void) : DenseFunctor<double>(7,37) {}
+ static const double _x[37];
+ static const double _y[37];
+ int operator()(const VectorXd &b, VectorXd &fvec)
+ {
+ // int called=0; printf("call hahn1_functor with iflag=%d, called=%d\n", iflag, called); if (iflag==1) called++;
+ assert(b.size()==7);
+ assert(fvec.size()==37);
+ for(int i=0; i<37; i++) {
+ double x=_x[i], xx=x*x, xxx=xx*x;
+ fvec[i] = (b[0]+b[1]*x+b[2]*xx+b[3]*xxx) / (1.+b[4]*x+b[5]*xx+b[6]*xxx) - _y[i];
+ }
+ return 0;
+ }
+ int df(const VectorXd &b, MatrixXd &fjac)
+ {
+ assert(b.size()==7);
+ assert(fjac.rows()==37);
+ assert(fjac.cols()==7);
+ for(int i=0; i<37; i++) {
+ double x=_x[i], xx=x*x, xxx=xx*x;
+ double fact = 1./(1.+b[4]*x+b[5]*xx+b[6]*xxx);
+ fjac(i,0) = 1.*fact;
+ fjac(i,1) = x*fact;
+ fjac(i,2) = xx*fact;
+ fjac(i,3) = xxx*fact;
+ fact = - (b[0]+b[1]*x+b[2]*xx+b[3]*xxx) * fact * fact;
+ fjac(i,4) = x*fact;
+ fjac(i,5) = xx*fact;
+ fjac(i,6) = xxx*fact;
+ }
+ return 0;
+ }
+};
+const double thurber_functor::_x[37] = { -3.067E0, -2.981E0, -2.921E0, -2.912E0, -2.840E0, -2.797E0, -2.702E0, -2.699E0, -2.633E0, -2.481E0, -2.363E0, -2.322E0, -1.501E0, -1.460E0, -1.274E0, -1.212E0, -1.100E0, -1.046E0, -0.915E0, -0.714E0, -0.566E0, -0.545E0, -0.400E0, -0.309E0, -0.109E0, -0.103E0, 0.010E0, 0.119E0, 0.377E0, 0.790E0, 0.963E0, 1.006E0, 1.115E0, 1.572E0, 1.841E0, 2.047E0, 2.200E0 };
+const double thurber_functor::_y[37] = { 80.574E0, 84.248E0, 87.264E0, 87.195E0, 89.076E0, 89.608E0, 89.868E0, 90.101E0, 92.405E0, 95.854E0, 100.696E0, 101.060E0, 401.672E0, 390.724E0, 567.534E0, 635.316E0, 733.054E0, 759.087E0, 894.206E0, 990.785E0, 1090.109E0, 1080.914E0, 1122.643E0, 1178.351E0, 1260.531E0, 1273.514E0, 1288.339E0, 1327.543E0, 1353.863E0, 1414.509E0, 1425.208E0, 1421.384E0, 1442.962E0, 1464.350E0, 1468.705E0, 1447.894E0, 1457.628E0};
+
+// http://www.itl.nist.gov/div898/strd/nls/data/thurber.shtml
+void testNistThurber(void)
+{
+ const int n=7;
+ int info;
+
+ VectorXd x(n);
+
+ /*
+ * First try
+ */
+ x<< 1000 ,1000 ,400 ,40 ,0.7,0.3,0.0 ;
+ // do the computation
+ thurber_functor functor;
+ LevenbergMarquardt<thurber_functor> lm(functor);
+ lm.setFtol(1.E4*NumTraits<double>::epsilon());
+ lm.setXtol(1.E4*NumTraits<double>::epsilon());
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 39);
+ VERIFY_IS_EQUAL(lm.njev(), 36);
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 5.6427082397E+03);
+ // check x
+ VERIFY_IS_APPROX(x[0], 1.2881396800E+03);
+ VERIFY_IS_APPROX(x[1], 1.4910792535E+03);
+ VERIFY_IS_APPROX(x[2], 5.8323836877E+02);
+ VERIFY_IS_APPROX(x[3], 7.5416644291E+01);
+ VERIFY_IS_APPROX(x[4], 9.6629502864E-01);
+ VERIFY_IS_APPROX(x[5], 3.9797285797E-01);
+ VERIFY_IS_APPROX(x[6], 4.9727297349E-02);
+
+ /*
+ * Second try
+ */
+ x<< 1300 ,1500 ,500 ,75 ,1 ,0.4 ,0.05 ;
+ // do the computation
+ lm.resetParameters();
+ lm.setFtol(1.E4*NumTraits<double>::epsilon());
+ lm.setXtol(1.E4*NumTraits<double>::epsilon());
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 29);
+ VERIFY_IS_EQUAL(lm.njev(), 28);
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 5.6427082397E+03);
+ // check x
+ VERIFY_IS_APPROX(x[0], 1.2881396800E+03);
+ VERIFY_IS_APPROX(x[1], 1.4910792535E+03);
+ VERIFY_IS_APPROX(x[2], 5.8323836877E+02);
+ VERIFY_IS_APPROX(x[3], 7.5416644291E+01);
+ VERIFY_IS_APPROX(x[4], 9.6629502864E-01);
+ VERIFY_IS_APPROX(x[5], 3.9797285797E-01);
+ VERIFY_IS_APPROX(x[6], 4.9727297349E-02);
+}
+
+struct rat43_functor : DenseFunctor<double>
+{
+ rat43_functor(void) : DenseFunctor<double>(4,15) {}
+ static const double x[15];
+ static const double y[15];
+ int operator()(const VectorXd &b, VectorXd &fvec)
+ {
+ assert(b.size()==4);
+ assert(fvec.size()==15);
+ for(int i=0; i<15; i++)
+ fvec[i] = b[0] * pow(1.+exp(b[1]-b[2]*x[i]),-1./b[3]) - y[i];
+ return 0;
+ }
+ int df(const VectorXd &b, MatrixXd &fjac)
+ {
+ assert(b.size()==4);
+ assert(fjac.rows()==15);
+ assert(fjac.cols()==4);
+ for(int i=0; i<15; i++) {
+ double e = exp(b[1]-b[2]*x[i]);
+ double power = -1./b[3];
+ fjac(i,0) = pow(1.+e, power);
+ fjac(i,1) = power*b[0]*e*pow(1.+e, power-1.);
+ fjac(i,2) = -power*b[0]*e*x[i]*pow(1.+e, power-1.);
+ fjac(i,3) = b[0]*power*power*log(1.+e)*pow(1.+e, power);
+ }
+ return 0;
+ }
+};
+const double rat43_functor::x[15] = { 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15. };
+const double rat43_functor::y[15] = { 16.08, 33.83, 65.80, 97.20, 191.55, 326.20, 386.87, 520.53, 590.03, 651.92, 724.93, 699.56, 689.96, 637.56, 717.41 };
+
+// http://www.itl.nist.gov/div898/strd/nls/data/ratkowsky3.shtml
+void testNistRat43(void)
+{
+ const int n=4;
+ int info;
+
+ VectorXd x(n);
+
+ /*
+ * First try
+ */
+ x<< 100., 10., 1., 1.;
+ // do the computation
+ rat43_functor functor;
+ LevenbergMarquardt<rat43_functor> lm(functor);
+ lm.setFtol(1.E6*NumTraits<double>::epsilon());
+ lm.setXtol(1.E6*NumTraits<double>::epsilon());
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 27);
+ VERIFY_IS_EQUAL(lm.njev(), 20);
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 8.7864049080E+03);
+ // check x
+ VERIFY_IS_APPROX(x[0], 6.9964151270E+02);
+ VERIFY_IS_APPROX(x[1], 5.2771253025E+00);
+ VERIFY_IS_APPROX(x[2], 7.5962938329E-01);
+ VERIFY_IS_APPROX(x[3], 1.2792483859E+00);
+
+ /*
+ * Second try
+ */
+ x<< 700., 5., 0.75, 1.3;
+ // do the computation
+ lm.resetParameters();
+ lm.setFtol(1.E5*NumTraits<double>::epsilon());
+ lm.setXtol(1.E5*NumTraits<double>::epsilon());
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 9);
+ VERIFY_IS_EQUAL(lm.njev(), 8);
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 8.7864049080E+03);
+ // check x
+ VERIFY_IS_APPROX(x[0], 6.9964151270E+02);
+ VERIFY_IS_APPROX(x[1], 5.2771253025E+00);
+ VERIFY_IS_APPROX(x[2], 7.5962938329E-01);
+ VERIFY_IS_APPROX(x[3], 1.2792483859E+00);
+}
+
+
+
+struct eckerle4_functor : DenseFunctor<double>
+{
+ eckerle4_functor(void) : DenseFunctor<double>(3,35) {}
+ static const double x[35];
+ static const double y[35];
+ int operator()(const VectorXd &b, VectorXd &fvec)
+ {
+ assert(b.size()==3);
+ assert(fvec.size()==35);
+ for(int i=0; i<35; i++)
+ fvec[i] = b[0]/b[1] * exp(-0.5*(x[i]-b[2])*(x[i]-b[2])/(b[1]*b[1])) - y[i];
+ return 0;
+ }
+ int df(const VectorXd &b, MatrixXd &fjac)
+ {
+ assert(b.size()==3);
+ assert(fjac.rows()==35);
+ assert(fjac.cols()==3);
+ for(int i=0; i<35; i++) {
+ double b12 = b[1]*b[1];
+ double e = exp(-0.5*(x[i]-b[2])*(x[i]-b[2])/b12);
+ fjac(i,0) = e / b[1];
+ fjac(i,1) = ((x[i]-b[2])*(x[i]-b[2])/b12-1.) * b[0]*e/b12;
+ fjac(i,2) = (x[i]-b[2])*e*b[0]/b[1]/b12;
+ }
+ return 0;
+ }
+};
+const double eckerle4_functor::x[35] = { 400.0, 405.0, 410.0, 415.0, 420.0, 425.0, 430.0, 435.0, 436.5, 438.0, 439.5, 441.0, 442.5, 444.0, 445.5, 447.0, 448.5, 450.0, 451.5, 453.0, 454.5, 456.0, 457.5, 459.0, 460.5, 462.0, 463.5, 465.0, 470.0, 475.0, 480.0, 485.0, 490.0, 495.0, 500.0};
+const double eckerle4_functor::y[35] = { 0.0001575, 0.0001699, 0.0002350, 0.0003102, 0.0004917, 0.0008710, 0.0017418, 0.0046400, 0.0065895, 0.0097302, 0.0149002, 0.0237310, 0.0401683, 0.0712559, 0.1264458, 0.2073413, 0.2902366, 0.3445623, 0.3698049, 0.3668534, 0.3106727, 0.2078154, 0.1164354, 0.0616764, 0.0337200, 0.0194023, 0.0117831, 0.0074357, 0.0022732, 0.0008800, 0.0004579, 0.0002345, 0.0001586, 0.0001143, 0.0000710 };
+
+// http://www.itl.nist.gov/div898/strd/nls/data/eckerle4.shtml
+void testNistEckerle4(void)
+{
+ const int n=3;
+ int info;
+
+ VectorXd x(n);
+
+ /*
+ * First try
+ */
+ x<< 1., 10., 500.;
+ // do the computation
+ eckerle4_functor functor;
+ LevenbergMarquardt<eckerle4_functor> lm(functor);
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 18);
+ VERIFY_IS_EQUAL(lm.njev(), 15);
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 1.4635887487E-03);
+ // check x
+ VERIFY_IS_APPROX(x[0], 1.5543827178);
+ VERIFY_IS_APPROX(x[1], 4.0888321754);
+ VERIFY_IS_APPROX(x[2], 4.5154121844E+02);
+
+ /*
+ * Second try
+ */
+ x<< 1.5, 5., 450.;
+ // do the computation
+ info = lm.minimize(x);
+
+ // check return value
+ VERIFY_IS_EQUAL(info, 1);
+ VERIFY_IS_EQUAL(lm.nfev(), 7);
+ VERIFY_IS_EQUAL(lm.njev(), 6);
+ // check norm^2
+ VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 1.4635887487E-03);
+ // check x
+ VERIFY_IS_APPROX(x[0], 1.5543827178);
+ VERIFY_IS_APPROX(x[1], 4.0888321754);
+ VERIFY_IS_APPROX(x[2], 4.5154121844E+02);
+}
+
+void test_levenberg_marquardt()
+{
+ // Tests using the examples provided by (c)minpack
+ CALL_SUBTEST(testLmder1());
+ CALL_SUBTEST(testLmder());
+ CALL_SUBTEST(testLmdif1());
+// CALL_SUBTEST(testLmstr1());
+// CALL_SUBTEST(testLmstr());
+ CALL_SUBTEST(testLmdif());
+
+ // NIST tests, level of difficulty = "Lower"
+ CALL_SUBTEST(testNistMisra1a());
+ CALL_SUBTEST(testNistChwirut2());
+
+ // NIST tests, level of difficulty = "Average"
+ CALL_SUBTEST(testNistHahn1());
+ CALL_SUBTEST(testNistMisra1d());
+ CALL_SUBTEST(testNistMGH17());
+ CALL_SUBTEST(testNistLanczos1());
+
+// // NIST tests, level of difficulty = "Higher"
+ CALL_SUBTEST(testNistRat42());
+ CALL_SUBTEST(testNistMGH10());
+ CALL_SUBTEST(testNistBoxBOD());
+// CALL_SUBTEST(testNistMGH09());
+ CALL_SUBTEST(testNistBennett5());
+ CALL_SUBTEST(testNistThurber());
+ CALL_SUBTEST(testNistRat43());
+ CALL_SUBTEST(testNistEckerle4());
+}
diff --git a/unsupported/test/matrix_exponential.cpp b/unsupported/test/matrix_exponential.cpp
index 695472f91..50dec083d 100644
--- a/unsupported/test/matrix_exponential.cpp
+++ b/unsupported/test/matrix_exponential.cpp
@@ -7,8 +7,7 @@
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#include "main.h"
-#include <unsupported/Eigen/MatrixFunctions>
+#include "matrix_functions.h"
double binom(int n, int k)
{
@@ -18,12 +17,6 @@ double binom(int n, int k)
return res;
}
-template <typename Derived, typename OtherDerived>
-double relerr(const MatrixBase<Derived>& A, const MatrixBase<OtherDerived>& B)
-{
- return std::sqrt((A - B).cwiseAbs2().sum() / (std::min)(A.cwiseAbs2().sum(), B.cwiseAbs2().sum()));
-}
-
template <typename T>
T expfn(T x, int)
{
@@ -109,8 +102,7 @@ void randomTest(const MatrixType& m, double tol)
*/
typename MatrixType::Index rows = m.rows();
typename MatrixType::Index cols = m.cols();
- MatrixType m1(rows, cols), m2(rows, cols), m3(rows, cols),
- identity = MatrixType::Identity(rows, rows);
+ MatrixType m1(rows, cols), m2(rows, cols), identity = MatrixType::Identity(rows, cols);
typedef typename NumTraits<typename internal::traits<MatrixType>::Scalar>::Real RealScalar;
diff --git a/unsupported/test/matrix_function.cpp b/unsupported/test/matrix_function.cpp
index 0439c5a7d..3c76cfb65 100644
--- a/unsupported/test/matrix_function.cpp
+++ b/unsupported/test/matrix_function.cpp
@@ -110,7 +110,6 @@ void testMatrixLogarithm(const MatrixType& A)
{
typedef typename internal::traits<MatrixType>::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef std::complex<RealScalar> ComplexScalar;
MatrixType scaledA;
RealScalar maxImagPartOfSpectrum = A.eigenvalues().imag().cwiseAbs().maxCoeff();
diff --git a/unsupported/test/matrix_functions.h b/unsupported/test/matrix_functions.h
new file mode 100644
index 000000000..5817caef6
--- /dev/null
+++ b/unsupported/test/matrix_functions.h
@@ -0,0 +1,47 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009-2011 Jitse Niesen <jitse@maths.leeds.ac.uk>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <unsupported/Eigen/MatrixFunctions>
+
+template <typename MatrixType, int IsComplex = NumTraits<typename internal::traits<MatrixType>::Scalar>::IsComplex>
+struct generateTestMatrix;
+
+// for real matrices, make sure none of the eigenvalues are negative
+template <typename MatrixType>
+struct generateTestMatrix<MatrixType,0>
+{
+ static void run(MatrixType& result, typename MatrixType::Index size)
+ {
+ MatrixType mat = MatrixType::Random(size, size);
+ EigenSolver<MatrixType> es(mat);
+ typename EigenSolver<MatrixType>::EigenvalueType eivals = es.eigenvalues();
+ for (typename MatrixType::Index i = 0; i < size; ++i) {
+ if (eivals(i).imag() == 0 && eivals(i).real() < 0)
+ eivals(i) = -eivals(i);
+ }
+ result = (es.eigenvectors() * eivals.asDiagonal() * es.eigenvectors().inverse()).real();
+ }
+};
+
+// for complex matrices, any matrix is fine
+template <typename MatrixType>
+struct generateTestMatrix<MatrixType,1>
+{
+ static void run(MatrixType& result, typename MatrixType::Index size)
+ {
+ result = MatrixType::Random(size, size);
+ }
+};
+
+template <typename Derived, typename OtherDerived>
+double relerr(const MatrixBase<Derived>& A, const MatrixBase<OtherDerived>& B)
+{
+ return std::sqrt((A - B).cwiseAbs2().sum() / (std::min)(A.cwiseAbs2().sum(), B.cwiseAbs2().sum()));
+}
diff --git a/unsupported/test/matrix_power.cpp b/unsupported/test/matrix_power.cpp
new file mode 100644
index 000000000..b9d513b45
--- /dev/null
+++ b/unsupported/test/matrix_power.cpp
@@ -0,0 +1,133 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Chen-Pang He <jdh8@ms63.hinet.net>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "matrix_functions.h"
+
+template <typename MatrixType, int IsComplex = NumTraits<typename MatrixType::Scalar>::IsComplex>
+struct generateTriangularMatrix;
+
+// for real matrices, make sure none of the eigenvalues are negative
+template <typename MatrixType>
+struct generateTriangularMatrix<MatrixType,0>
+{
+ static void run(MatrixType& result, typename MatrixType::Index size)
+ {
+ result.resize(size, size);
+ result.template triangularView<Upper>() = MatrixType::Random(size, size);
+ for (typename MatrixType::Index i = 0; i < size; ++i)
+ result.coeffRef(i,i) = std::abs(result.coeff(i,i));
+ }
+};
+
+// for complex matrices, any matrix is fine
+template <typename MatrixType>
+struct generateTriangularMatrix<MatrixType,1>
+{
+ static void run(MatrixType& result, typename MatrixType::Index size)
+ {
+ result.resize(size, size);
+ result.template triangularView<Upper>() = MatrixType::Random(size, size);
+ }
+};
+
+template<typename T>
+void test2dRotation(double tol)
+{
+ Matrix<T,2,2> A, B, C;
+ T angle, c, s;
+
+ A << 0, 1, -1, 0;
+ MatrixPower<Matrix<T,2,2> > Apow(A);
+
+ for (int i=0; i<=20; ++i) {
+ angle = pow(10, (i-10) / 5.);
+ c = std::cos(angle);
+ s = std::sin(angle);
+ B << c, s, -s, c;
+
+ C = Apow(std::ldexp(angle,1) / M_PI);
+ std::cout << "test2dRotation: i = " << i << " error powerm = " << relerr(C,B) << '\n';
+ VERIFY(C.isApprox(B, static_cast<T>(tol)));
+ }
+}
+
+template<typename T>
+void test2dHyperbolicRotation(double tol)
+{
+ Matrix<std::complex<T>,2,2> A, B, C;
+ T angle, ch = std::cosh((T)1);
+ std::complex<T> ish(0, std::sinh((T)1));
+
+ A << ch, ish, -ish, ch;
+ MatrixPower<Matrix<std::complex<T>,2,2> > Apow(A);
+
+ for (int i=0; i<=20; ++i) {
+ angle = std::ldexp(static_cast<T>(i-10), -1);
+ ch = std::cosh(angle);
+ ish = std::complex<T>(0, std::sinh(angle));
+ B << ch, ish, -ish, ch;
+
+ C = Apow(angle);
+ std::cout << "test2dHyperbolicRotation: i = " << i << " error powerm = " << relerr(C,B) << '\n';
+ VERIFY(C.isApprox(B, static_cast<T>(tol)));
+ }
+}
+
+template<typename MatrixType>
+void testExponentLaws(const MatrixType& m, double tol)
+{
+ typedef typename MatrixType::RealScalar RealScalar;
+ MatrixType m1, m2, m3, m4, m5;
+ RealScalar x, y;
+
+ for (int i=0; i < g_repeat; ++i) {
+ generateTestMatrix<MatrixType>::run(m1, m.rows());
+ MatrixPower<MatrixType> mpow(m1);
+
+ x = internal::random<RealScalar>();
+ y = internal::random<RealScalar>();
+ m2 = mpow(x);
+ m3 = mpow(y);
+
+ m4 = mpow(x+y);
+ m5.noalias() = m2 * m3;
+ VERIFY(m4.isApprox(m5, static_cast<RealScalar>(tol)));
+
+ m4 = mpow(x*y);
+ m5 = m2.pow(y);
+ VERIFY(m4.isApprox(m5, static_cast<RealScalar>(tol)));
+
+ m4 = (std::abs(x) * m1).pow(y);
+ m5 = std::pow(std::abs(x), y) * m3;
+ VERIFY(m4.isApprox(m5, static_cast<RealScalar>(tol)));
+ }
+}
+
+typedef Matrix<double,3,3,RowMajor> Matrix3dRowMajor;
+typedef Matrix<long double,Dynamic,Dynamic> MatrixXe;
+
+void test_matrix_power()
+{
+ CALL_SUBTEST_2(test2dRotation<double>(1e-13));
+ CALL_SUBTEST_1(test2dRotation<float>(2e-5)); // was 1e-5, relaxed for clang 2.8 / linux / x86-64
+ CALL_SUBTEST_9(test2dRotation<long double>(1e-13));
+ CALL_SUBTEST_2(test2dHyperbolicRotation<double>(1e-14));
+ CALL_SUBTEST_1(test2dHyperbolicRotation<float>(1e-5));
+ CALL_SUBTEST_9(test2dHyperbolicRotation<long double>(1e-14));
+
+ CALL_SUBTEST_2(testExponentLaws(Matrix2d(), 1e-13));
+ CALL_SUBTEST_7(testExponentLaws(Matrix3dRowMajor(), 1e-13));
+ CALL_SUBTEST_3(testExponentLaws(Matrix4cd(), 1e-13));
+ CALL_SUBTEST_4(testExponentLaws(MatrixXd(8,8), 2e-12));
+ CALL_SUBTEST_1(testExponentLaws(Matrix2f(), 1e-4));
+ CALL_SUBTEST_5(testExponentLaws(Matrix3cf(), 1e-4));
+ CALL_SUBTEST_8(testExponentLaws(Matrix4f(), 1e-4));
+ CALL_SUBTEST_6(testExponentLaws(MatrixXf(2,2), 1e-3)); // see bug 614
+ CALL_SUBTEST_9(testExponentLaws(MatrixXe(7,7), 1e-13));
+}
diff --git a/unsupported/test/matrix_square_root.cpp b/unsupported/test/matrix_square_root.cpp
index 508619a7a..ea541e1ea 100644
--- a/unsupported/test/matrix_square_root.cpp
+++ b/unsupported/test/matrix_square_root.cpp
@@ -7,38 +7,7 @@
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#include "main.h"
-#include <unsupported/Eigen/MatrixFunctions>
-
-template <typename MatrixType, int IsComplex = NumTraits<typename internal::traits<MatrixType>::Scalar>::IsComplex>
-struct generateTestMatrix;
-
-// for real matrices, make sure none of the eigenvalues are negative
-template <typename MatrixType>
-struct generateTestMatrix<MatrixType,0>
-{
- static void run(MatrixType& result, typename MatrixType::Index size)
- {
- MatrixType mat = MatrixType::Random(size, size);
- EigenSolver<MatrixType> es(mat);
- typename EigenSolver<MatrixType>::EigenvalueType eivals = es.eigenvalues();
- for (typename MatrixType::Index i = 0; i < size; ++i) {
- if (eivals(i).imag() == 0 && eivals(i).real() < 0)
- eivals(i) = -eivals(i);
- }
- result = (es.eigenvectors() * eivals.asDiagonal() * es.eigenvectors().inverse()).real();
- }
-};
-
-// for complex matrices, any matrix is fine
-template <typename MatrixType>
-struct generateTestMatrix<MatrixType,1>
-{
- static void run(MatrixType& result, typename MatrixType::Index size)
- {
- result = MatrixType::Random(size, size);
- }
-};
+#include "matrix_functions.h"
template<typename MatrixType>
void testMatrixSqrt(const MatrixType& m)
diff --git a/unsupported/test/minres.cpp b/unsupported/test/minres.cpp
new file mode 100644
index 000000000..fd12da548
--- /dev/null
+++ b/unsupported/test/minres.cpp
@@ -0,0 +1,32 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2011 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2012 Giacomo Po <gpo@ucla.edu>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#include <cmath>
+
+#include "../../test/sparse_solver.h"
+#include <Eigen/IterativeSolvers>
+
+template<typename T> void test_minres_T()
+{
+ MINRES<SparseMatrix<T>, Lower, DiagonalPreconditioner<T> > minres_colmajor_diag;
+ MINRES<SparseMatrix<T>, Lower, IdentityPreconditioner > minres_colmajor_I;
+// MINRES<SparseMatrix<T>, Lower, IncompleteLUT<T> > minres_colmajor_ilut;
+ //minres<SparseMatrix<T>, SSORPreconditioner<T> > minres_colmajor_ssor;
+
+ CALL_SUBTEST( check_sparse_square_solving(minres_colmajor_diag) );
+ CALL_SUBTEST( check_sparse_spd_solving(minres_colmajor_I) );
+ // CALL_SUBTEST( check_sparse_square_solving(minres_colmajor_ilut) );
+ //CALL_SUBTEST( check_sparse_square_solving(minres_colmajor_ssor) );
+}
+
+void test_minres()
+{
+ CALL_SUBTEST_1(test_minres_T<double>());
+// CALL_SUBTEST_2(test_minres_T<std::complex<double> >());
+}
diff --git a/unsupported/test/mpreal/dlmalloc.c b/unsupported/test/mpreal/dlmalloc.c
deleted file mode 100755
index 7ce8feb07..000000000
--- a/unsupported/test/mpreal/dlmalloc.c
+++ /dev/null
@@ -1,5703 +0,0 @@
-/*
- This is a version (aka dlmalloc) of malloc/free/realloc written by
- Doug Lea and released to the public domain, as explained at
- http://creativecommons.org/licenses/publicdomain. Send questions,
- comments, complaints, performance data, etc to dl@cs.oswego.edu
-
-* Version 2.8.4 Wed May 27 09:56:23 2009 Doug Lea (dl at gee)
-
- Note: There may be an updated version of this malloc obtainable at
- ftp://gee.cs.oswego.edu/pub/misc/malloc.c
- Check before installing!
-
-* Quickstart
-
- This library is all in one file to simplify the most common usage:
- ftp it, compile it (-O3), and link it into another program. All of
- the compile-time options default to reasonable values for use on
- most platforms. You might later want to step through various
- compile-time and dynamic tuning options.
-
- For convenience, an include file for code using this malloc is at:
- ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.4.h
- You don't really need this .h file unless you call functions not
- defined in your system include files. The .h file contains only the
- excerpts from this file needed for using this malloc on ANSI C/C++
- systems, so long as you haven't changed compile-time options about
- naming and tuning parameters. If you do, then you can create your
- own malloc.h that does include all settings by cutting at the point
- indicated below. Note that you may already by default be using a C
- library containing a malloc that is based on some version of this
- malloc (for example in linux). You might still want to use the one
- in this file to customize settings or to avoid overheads associated
- with library versions.
-
-* Vital statistics:
-
- Supported pointer/size_t representation: 4 or 8 bytes
- size_t MUST be an unsigned type of the same width as
- pointers. (If you are using an ancient system that declares
- size_t as a signed type, or need it to be a different width
- than pointers, you can use a previous release of this malloc
- (e.g. 2.7.2) supporting these.)
-
- Alignment: 8 bytes (default)
- This suffices for nearly all current machines and C compilers.
- However, you can define MALLOC_ALIGNMENT to be wider than this
- if necessary (up to 128bytes), at the expense of using more space.
-
- Minimum overhead per allocated chunk: 4 or 8 bytes (if 4byte sizes)
- 8 or 16 bytes (if 8byte sizes)
- Each malloced chunk has a hidden word of overhead holding size
- and status information, and additional cross-check word
- if FOOTERS is defined.
-
- Minimum allocated size: 4-byte ptrs: 16 bytes (including overhead)
- 8-byte ptrs: 32 bytes (including overhead)
-
- Even a request for zero bytes (i.e., malloc(0)) returns a
- pointer to something of the minimum allocatable size.
- The maximum overhead wastage (i.e., number of extra bytes
- allocated than were requested in malloc) is less than or equal
- to the minimum size, except for requests >= mmap_threshold that
- are serviced via mmap(), where the worst case wastage is about
- 32 bytes plus the remainder from a system page (the minimal
- mmap unit); typically 4096 or 8192 bytes.
-
- Security: static-safe; optionally more or less
- The "security" of malloc refers to the ability of malicious
- code to accentuate the effects of errors (for example, freeing
- space that is not currently malloc'ed or overwriting past the
- ends of chunks) in code that calls malloc. This malloc
- guarantees not to modify any memory locations below the base of
- heap, i.e., static variables, even in the presence of usage
- errors. The routines additionally detect most improper frees
- and reallocs. All this holds as long as the static bookkeeping
- for malloc itself is not corrupted by some other means. This
- is only one aspect of security -- these checks do not, and
- cannot, detect all possible programming errors.
-
- If FOOTERS is defined nonzero, then each allocated chunk
- carries an additional check word to verify that it was malloced
- from its space. These check words are the same within each
- execution of a program using malloc, but differ across
- executions, so externally crafted fake chunks cannot be
- freed. This improves security by rejecting frees/reallocs that
- could corrupt heap memory, in addition to the checks preventing
- writes to statics that are always on. This may further improve
- security at the expense of time and space overhead. (Note that
- FOOTERS may also be worth using with MSPACES.)
-
- By default detected errors cause the program to abort (calling
- "abort()"). You can override this to instead proceed past
- errors by defining PROCEED_ON_ERROR. In this case, a bad free
- has no effect, and a malloc that encounters a bad address
- caused by user overwrites will ignore the bad address by
- dropping pointers and indices to all known memory. This may
- be appropriate for programs that should continue if at all
- possible in the face of programming errors, although they may
- run out of memory because dropped memory is never reclaimed.
-
- If you don't like either of these options, you can define
- CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything
- else. And if if you are sure that your program using malloc has
- no errors or vulnerabilities, you can define INSECURE to 1,
- which might (or might not) provide a small performance improvement.
-
- Thread-safety: NOT thread-safe unless USE_LOCKS defined
- When USE_LOCKS is defined, each public call to malloc, free,
- etc is surrounded with either a pthread mutex or a win32
- spinlock (depending on WIN32). This is not especially fast, and
- can be a major bottleneck. It is designed only to provide
- minimal protection in concurrent environments, and to provide a
- basis for extensions. If you are using malloc in a concurrent
- program, consider instead using nedmalloc
- (http://www.nedprod.com/programs/portable/nedmalloc/) or
- ptmalloc (See http://www.malloc.de), which are derived
- from versions of this malloc.
-
- System requirements: Any combination of MORECORE and/or MMAP/MUNMAP
- This malloc can use unix sbrk or any emulation (invoked using
- the CALL_MORECORE macro) and/or mmap/munmap or any emulation
- (invoked using CALL_MMAP/CALL_MUNMAP) to get and release system
- memory. On most unix systems, it tends to work best if both
- MORECORE and MMAP are enabled. On Win32, it uses emulations
- based on VirtualAlloc. It also uses common C library functions
- like memset.
-
- Compliance: I believe it is compliant with the Single Unix Specification
- (See http://www.unix.org). Also SVID/XPG, ANSI C, and probably
- others as well.
-
-* Overview of algorithms
-
- This is not the fastest, most space-conserving, most portable, or
- most tunable malloc ever written. However it is among the fastest
- while also being among the most space-conserving, portable and
- tunable. Consistent balance across these factors results in a good
- general-purpose allocator for malloc-intensive programs.
-
- In most ways, this malloc is a best-fit allocator. Generally, it
- chooses the best-fitting existing chunk for a request, with ties
- broken in approximately least-recently-used order. (This strategy
- normally maintains low fragmentation.) However, for requests less
- than 256bytes, it deviates from best-fit when there is not an
- exactly fitting available chunk by preferring to use space adjacent
- to that used for the previous small request, as well as by breaking
- ties in approximately most-recently-used order. (These enhance
- locality of series of small allocations.) And for very large requests
- (>= 256Kb by default), it relies on system memory mapping
- facilities, if supported. (This helps avoid carrying around and
- possibly fragmenting memory used only for large chunks.)
-
- All operations (except malloc_stats and mallinfo) have execution
- times that are bounded by a constant factor of the number of bits in
- a size_t, not counting any clearing in calloc or copying in realloc,
- or actions surrounding MORECORE and MMAP that have times
- proportional to the number of non-contiguous regions returned by
- system allocation routines, which is often just 1. In real-time
- applications, you can optionally suppress segment traversals using
- NO_SEGMENT_TRAVERSAL, which assures bounded execution even when
- system allocators return non-contiguous spaces, at the typical
- expense of carrying around more memory and increased fragmentation.
-
- The implementation is not very modular and seriously overuses
- macros. Perhaps someday all C compilers will do as good a job
- inlining modular code as can now be done by brute-force expansion,
- but now, enough of them seem not to.
-
- Some compilers issue a lot of warnings about code that is
- dead/unreachable only on some platforms, and also about intentional
- uses of negation on unsigned types. All known cases of each can be
- ignored.
-
- For a longer but out of date high-level description, see
- http://gee.cs.oswego.edu/dl/html/malloc.html
-
-* MSPACES
- If MSPACES is defined, then in addition to malloc, free, etc.,
- this file also defines mspace_malloc, mspace_free, etc. These
- are versions of malloc routines that take an "mspace" argument
- obtained using create_mspace, to control all internal bookkeeping.
- If ONLY_MSPACES is defined, only these versions are compiled.
- So if you would like to use this allocator for only some allocations,
- and your system malloc for others, you can compile with
- ONLY_MSPACES and then do something like...
- static mspace mymspace = create_mspace(0,0); // for example
- #define mymalloc(bytes) mspace_malloc(mymspace, bytes)
-
- (Note: If you only need one instance of an mspace, you can instead
- use "USE_DL_PREFIX" to relabel the global malloc.)
-
- You can similarly create thread-local allocators by storing
- mspaces as thread-locals. For example:
- static __thread mspace tlms = 0;
- void* tlmalloc(size_t bytes) {
- if (tlms == 0) tlms = create_mspace(0, 0);
- return mspace_malloc(tlms, bytes);
- }
- void tlfree(void* mem) { mspace_free(tlms, mem); }
-
- Unless FOOTERS is defined, each mspace is completely independent.
- You cannot allocate from one and free to another (although
- conformance is only weakly checked, so usage errors are not always
- caught). If FOOTERS is defined, then each chunk carries around a tag
- indicating its originating mspace, and frees are directed to their
- originating spaces.
-
- ------------------------- Compile-time options ---------------------------
-
-Be careful in setting #define values for numerical constants of type
-size_t. On some systems, literal values are not automatically extended
-to size_t precision unless they are explicitly casted. You can also
-use the symbolic values MAX_SIZE_T, SIZE_T_ONE, etc below.
-
-WIN32 default: defined if _WIN32 defined
- Defining WIN32 sets up defaults for MS environment and compilers.
- Otherwise defaults are for unix. Beware that there seem to be some
- cases where this malloc might not be a pure drop-in replacement for
- Win32 malloc: Random-looking failures from Win32 GDI API's (eg;
- SetDIBits()) may be due to bugs in some video driver implementations
- when pixel buffers are malloc()ed, and the region spans more than
- one VirtualAlloc()ed region. Because dlmalloc uses a small (64Kb)
- default granularity, pixel buffers may straddle virtual allocation
- regions more often than when using the Microsoft allocator. You can
- avoid this by using VirtualAlloc() and VirtualFree() for all pixel
- buffers rather than using malloc(). If this is not possible,
- recompile this malloc with a larger DEFAULT_GRANULARITY.
-
-MALLOC_ALIGNMENT default: (size_t)8
- Controls the minimum alignment for malloc'ed chunks. It must be a
- power of two and at least 8, even on machines for which smaller
- alignments would suffice. It may be defined as larger than this
- though. Note however that code and data structures are optimized for
- the case of 8-byte alignment.
-
-MSPACES default: 0 (false)
- If true, compile in support for independent allocation spaces.
- This is only supported if HAVE_MMAP is true.
-
-ONLY_MSPACES default: 0 (false)
- If true, only compile in mspace versions, not regular versions.
-
-USE_LOCKS default: 0 (false)
- Causes each call to each public routine to be surrounded with
- pthread or WIN32 mutex lock/unlock. (If set true, this can be
- overridden on a per-mspace basis for mspace versions.) If set to a
- non-zero value other than 1, locks are used, but their
- implementation is left out, so lock functions must be supplied manually,
- as described below.
-
-USE_SPIN_LOCKS default: 1 iff USE_LOCKS and on x86 using gcc or MSC
- If true, uses custom spin locks for locking. This is currently
- supported only for x86 platforms using gcc or recent MS compilers.
- Otherwise, posix locks or win32 critical sections are used.
-
-FOOTERS default: 0
- If true, provide extra checking and dispatching by placing
- information in the footers of allocated chunks. This adds
- space and time overhead.
-
-INSECURE default: 0
- If true, omit checks for usage errors and heap space overwrites.
-
-USE_DL_PREFIX default: NOT defined
- Causes compiler to prefix all public routines with the string 'dl'.
- This can be useful when you only want to use this malloc in one part
- of a program, using your regular system malloc elsewhere.
-
-ABORT default: defined as abort()
- Defines how to abort on failed checks. On most systems, a failed
- check cannot die with an "assert" or even print an informative
- message, because the underlying print routines in turn call malloc,
- which will fail again. Generally, the best policy is to simply call
- abort(). It's not very useful to do more than this because many
- errors due to overwriting will show up as address faults (null, odd
- addresses etc) rather than malloc-triggered checks, so will also
- abort. Also, most compilers know that abort() does not return, so
- can better optimize code conditionally calling it.
-
-PROCEED_ON_ERROR default: defined as 0 (false)
- Controls whether detected bad addresses cause them to bypassed
- rather than aborting. If set, detected bad arguments to free and
- realloc are ignored. And all bookkeeping information is zeroed out
- upon a detected overwrite of freed heap space, thus losing the
- ability to ever return it from malloc again, but enabling the
- application to proceed. If PROCEED_ON_ERROR is defined, the
- static variable malloc_corruption_error_count is compiled in
- and can be examined to see if errors have occurred. This option
- generates slower code than the default abort policy.
-
-DEBUG default: NOT defined
- The DEBUG setting is mainly intended for people trying to modify
- this code or diagnose problems when porting to new platforms.
- However, it may also be able to better isolate user errors than just
- using runtime checks. The assertions in the check routines spell
- out in more detail the assumptions and invariants underlying the
- algorithms. The checking is fairly extensive, and will slow down
- execution noticeably. Calling malloc_stats or mallinfo with DEBUG
- set will attempt to check every non-mmapped allocated and free chunk
- in the course of computing the summaries.
-
-ABORT_ON_ASSERT_FAILURE default: defined as 1 (true)
- Debugging assertion failures can be nearly impossible if your
- version of the assert macro causes malloc to be called, which will
- lead to a cascade of further failures, blowing the runtime stack.
- ABORT_ON_ASSERT_FAILURE cause assertions failures to call abort(),
- which will usually make debugging easier.
-
-MALLOC_FAILURE_ACTION default: sets errno to ENOMEM, or no-op on win32
- The action to take before "return 0" when malloc fails to be able to
- return memory because there is none available.
-
-HAVE_MORECORE default: 1 (true) unless win32 or ONLY_MSPACES
- True if this system supports sbrk or an emulation of it.
-
-MORECORE default: sbrk
- The name of the sbrk-style system routine to call to obtain more
- memory. See below for guidance on writing custom MORECORE
- functions. The type of the argument to sbrk/MORECORE varies across
- systems. It cannot be size_t, because it supports negative
- arguments, so it is normally the signed type of the same width as
- size_t (sometimes declared as "intptr_t"). It doesn't much matter
- though. Internally, we only call it with arguments less than half
- the max value of a size_t, which should work across all reasonable
- possibilities, although sometimes generating compiler warnings.
-
-MORECORE_CONTIGUOUS default: 1 (true) if HAVE_MORECORE
- If true, take advantage of fact that consecutive calls to MORECORE
- with positive arguments always return contiguous increasing
- addresses. This is true of unix sbrk. It does not hurt too much to
- set it true anyway, since malloc copes with non-contiguities.
- Setting it false when definitely non-contiguous saves time
- and possibly wasted space it would take to discover this though.
-
-MORECORE_CANNOT_TRIM default: NOT defined
- True if MORECORE cannot release space back to the system when given
- negative arguments. This is generally necessary only if you are
- using a hand-crafted MORECORE function that cannot handle negative
- arguments.
-
-NO_SEGMENT_TRAVERSAL default: 0
- If non-zero, suppresses traversals of memory segments
- returned by either MORECORE or CALL_MMAP. This disables
- merging of segments that are contiguous, and selectively
- releasing them to the OS if unused, but bounds execution times.
-
-HAVE_MMAP default: 1 (true)
- True if this system supports mmap or an emulation of it. If so, and
- HAVE_MORECORE is not true, MMAP is used for all system
- allocation. If set and HAVE_MORECORE is true as well, MMAP is
- primarily used to directly allocate very large blocks. It is also
- used as a backup strategy in cases where MORECORE fails to provide
- space from system. Note: A single call to MUNMAP is assumed to be
- able to unmap memory that may have be allocated using multiple calls
- to MMAP, so long as they are adjacent.
-
-HAVE_MREMAP default: 1 on linux, else 0
- If true realloc() uses mremap() to re-allocate large blocks and
- extend or shrink allocation spaces.
-
-MMAP_CLEARS default: 1 except on WINCE.
- True if mmap clears memory so calloc doesn't need to. This is true
- for standard unix mmap using /dev/zero and on WIN32 except for WINCE.
-
-USE_BUILTIN_FFS default: 0 (i.e., not used)
- Causes malloc to use the builtin ffs() function to compute indices.
- Some compilers may recognize and intrinsify ffs to be faster than the
- supplied C version. Also, the case of x86 using gcc is special-cased
- to an asm instruction, so is already as fast as it can be, and so
- this setting has no effect. Similarly for Win32 under recent MS compilers.
- (On most x86s, the asm version is only slightly faster than the C version.)
-
-malloc_getpagesize default: derive from system includes, or 4096.
- The system page size. To the extent possible, this malloc manages
- memory from the system in page-size units. This may be (and
- usually is) a function rather than a constant. This is ignored
- if WIN32, where page size is determined using getSystemInfo during
- initialization.
-
-USE_DEV_RANDOM default: 0 (i.e., not used)
- Causes malloc to use /dev/random to initialize secure magic seed for
- stamping footers. Otherwise, the current time is used.
-
-NO_MALLINFO default: 0
- If defined, don't compile "mallinfo". This can be a simple way
- of dealing with mismatches between system declarations and
- those in this file.
-
-MALLINFO_FIELD_TYPE default: size_t
- The type of the fields in the mallinfo struct. This was originally
- defined as "int" in SVID etc, but is more usefully defined as
- size_t. The value is used only if HAVE_USR_INCLUDE_MALLOC_H is not set
-
-REALLOC_ZERO_BYTES_FREES default: not defined
- This should be set if a call to realloc with zero bytes should
- be the same as a call to free. Some people think it should. Otherwise,
- since this malloc returns a unique pointer for malloc(0), so does
- realloc(p, 0).
-
-LACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H
-LACKS_STRINGS_H, LACKS_STRING_H, LACKS_SYS_TYPES_H, LACKS_ERRNO_H
-LACKS_STDLIB_H default: NOT defined unless on WIN32
- Define these if your system does not have these header files.
- You might need to manually insert some of the declarations they provide.
-
-DEFAULT_GRANULARITY default: page size if MORECORE_CONTIGUOUS,
- system_info.dwAllocationGranularity in WIN32,
- otherwise 64K.
- Also settable using mallopt(M_GRANULARITY, x)
- The unit for allocating and deallocating memory from the system. On
- most systems with contiguous MORECORE, there is no reason to
- make this more than a page. However, systems with MMAP tend to
- either require or encourage larger granularities. You can increase
- this value to prevent system allocation functions to be called so
- often, especially if they are slow. The value must be at least one
- page and must be a power of two. Setting to 0 causes initialization
- to either page size or win32 region size. (Note: In previous
- versions of malloc, the equivalent of this option was called
- "TOP_PAD")
-
-DEFAULT_TRIM_THRESHOLD default: 2MB
- Also settable using mallopt(M_TRIM_THRESHOLD, x)
- The maximum amount of unused top-most memory to keep before
- releasing via malloc_trim in free(). Automatic trimming is mainly
- useful in long-lived programs using contiguous MORECORE. Because
- trimming via sbrk can be slow on some systems, and can sometimes be
- wasteful (in cases where programs immediately afterward allocate
- more large chunks) the value should be high enough so that your
- overall system performance would improve by releasing this much
- memory. As a rough guide, you might set to a value close to the
- average size of a process (program) running on your system.
- Releasing this much memory would allow such a process to run in
- memory. Generally, it is worth tuning trim thresholds when a
- program undergoes phases where several large chunks are allocated
- and released in ways that can reuse each other's storage, perhaps
- mixed with phases where there are no such chunks at all. The trim
- value must be greater than page size to have any useful effect. To
- disable trimming completely, you can set to MAX_SIZE_T. Note that the trick
- some people use of mallocing a huge space and then freeing it at
- program startup, in an attempt to reserve system memory, doesn't
- have the intended effect under automatic trimming, since that memory
- will immediately be returned to the system.
-
-DEFAULT_MMAP_THRESHOLD default: 256K
- Also settable using mallopt(M_MMAP_THRESHOLD, x)
- The request size threshold for using MMAP to directly service a
- request. Requests of at least this size that cannot be allocated
- using already-existing space will be serviced via mmap. (If enough
- normal freed space already exists it is used instead.) Using mmap
- segregates relatively large chunks of memory so that they can be
- individually obtained and released from the host system. A request
- serviced through mmap is never reused by any other request (at least
- not directly; the system may just so happen to remap successive
- requests to the same locations). Segregating space in this way has
- the benefits that: Mmapped space can always be individually released
- back to the system, which helps keep the system level memory demands
- of a long-lived program low. Also, mapped memory doesn't become
- `locked' between other chunks, as can happen with normally allocated
- chunks, which means that even trimming via malloc_trim would not
- release them. However, it has the disadvantage that the space
- cannot be reclaimed, consolidated, and then used to service later
- requests, as happens with normal chunks. The advantages of mmap
- nearly always outweigh disadvantages for "large" chunks, but the
- value of "large" may vary across systems. The default is an
- empirically derived value that works well in most systems. You can
- disable mmap by setting to MAX_SIZE_T.
-
-MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP
- The number of consolidated frees between checks to release
- unused segments when freeing. When using non-contiguous segments,
- especially with multiple mspaces, checking only for topmost space
- doesn't always suffice to trigger trimming. To compensate for this,
- free() will, with a period of MAX_RELEASE_CHECK_RATE (or the
- current number of segments, if greater) try to release unused
- segments to the OS when freeing chunks that result in
- consolidation. The best value for this parameter is a compromise
- between slowing down frees with relatively costly checks that
- rarely trigger versus holding on to unused memory. To effectively
- disable, set to MAX_SIZE_T. This may lead to a very slight speed
- improvement at the expense of carrying around more memory.
-*/
-
-#define USE_DL_PREFIX
-//#define HAVE_USR_INCLUDE_MALLOC_H
-//#define MSPACES 1
-#define NO_SEGMENT_TRAVERSAL 1
-
-/* Version identifier to allow people to support multiple versions */
-#ifndef DLMALLOC_VERSION
-#define DLMALLOC_VERSION 20804
-#endif /* DLMALLOC_VERSION */
-
-#ifndef WIN32
-#ifdef _WIN32
-#define WIN32 1
-#endif /* _WIN32 */
-#ifdef _WIN32_WCE
-#define LACKS_FCNTL_H
-#define WIN32 1
-#endif /* _WIN32_WCE */
-#endif /* WIN32 */
-#ifdef WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#define HAVE_MMAP 1
-#define HAVE_MORECORE 0
-#define LACKS_UNISTD_H
-#define LACKS_SYS_PARAM_H
-#define LACKS_SYS_MMAN_H
-#define LACKS_STRING_H
-#define LACKS_STRINGS_H
-#define LACKS_SYS_TYPES_H
-#define LACKS_ERRNO_H
-#ifndef MALLOC_FAILURE_ACTION
-#define MALLOC_FAILURE_ACTION
-#endif /* MALLOC_FAILURE_ACTION */
-#ifdef _WIN32_WCE /* WINCE reportedly does not clear */
-#define MMAP_CLEARS 0
-#else
-#define MMAP_CLEARS 1
-#endif /* _WIN32_WCE */
-#endif /* WIN32 */
-
-#if defined(DARWIN) || defined(_DARWIN)
-/* Mac OSX docs advise not to use sbrk; it seems better to use mmap */
-#ifndef HAVE_MORECORE
-#define HAVE_MORECORE 0
-#define HAVE_MMAP 1
-/* OSX allocators provide 16 byte alignment */
-#ifndef MALLOC_ALIGNMENT
-#define MALLOC_ALIGNMENT ((size_t)16U)
-#endif
-#endif /* HAVE_MORECORE */
-#endif /* DARWIN */
-
-#ifndef LACKS_SYS_TYPES_H
-#include <sys/types.h> /* For size_t */
-#endif /* LACKS_SYS_TYPES_H */
-
-#if (defined(__GNUC__) && ((defined(__i386__) || defined(__x86_64__)))) || (defined(_MSC_VER) && _MSC_VER>=1310)
-#define SPIN_LOCKS_AVAILABLE 1
-#else
-#define SPIN_LOCKS_AVAILABLE 0
-#endif
-
-/* The maximum possible size_t value has all bits set */
-#define MAX_SIZE_T (~(size_t)0)
-
-#ifndef ONLY_MSPACES
-#define ONLY_MSPACES 0 /* define to a value */
-#else
-#define ONLY_MSPACES 1
-#endif /* ONLY_MSPACES */
-#ifndef MSPACES
-#if ONLY_MSPACES
-#define MSPACES 1
-#else /* ONLY_MSPACES */
-#define MSPACES 0
-#endif /* ONLY_MSPACES */
-#endif /* MSPACES */
-#ifndef MALLOC_ALIGNMENT
-#define MALLOC_ALIGNMENT ((size_t)8U)
-#endif /* MALLOC_ALIGNMENT */
-#ifndef FOOTERS
-#define FOOTERS 0
-#endif /* FOOTERS */
-#ifndef ABORT
-#define ABORT abort()
-#endif /* ABORT */
-#ifndef ABORT_ON_ASSERT_FAILURE
-#define ABORT_ON_ASSERT_FAILURE 1
-#endif /* ABORT_ON_ASSERT_FAILURE */
-#ifndef PROCEED_ON_ERROR
-#define PROCEED_ON_ERROR 0
-#endif /* PROCEED_ON_ERROR */
-#ifndef USE_LOCKS
-#define USE_LOCKS 0
-#endif /* USE_LOCKS */
-#ifndef USE_SPIN_LOCKS
-#if USE_LOCKS && SPIN_LOCKS_AVAILABLE
-#define USE_SPIN_LOCKS 1
-#else
-#define USE_SPIN_LOCKS 0
-#endif /* USE_LOCKS && SPIN_LOCKS_AVAILABLE. */
-#endif /* USE_SPIN_LOCKS */
-#ifndef INSECURE
-#define INSECURE 0
-#endif /* INSECURE */
-#ifndef HAVE_MMAP
-#define HAVE_MMAP 1
-#endif /* HAVE_MMAP */
-#ifndef MMAP_CLEARS
-#define MMAP_CLEARS 1
-#endif /* MMAP_CLEARS */
-#ifndef HAVE_MREMAP
-#ifdef linux
-#define HAVE_MREMAP 1
-#else /* linux */
-#define HAVE_MREMAP 0
-#endif /* linux */
-#endif /* HAVE_MREMAP */
-#ifndef MALLOC_FAILURE_ACTION
-#define MALLOC_FAILURE_ACTION errno = ENOMEM;
-#endif /* MALLOC_FAILURE_ACTION */
-#ifndef HAVE_MORECORE
-#if ONLY_MSPACES
-#define HAVE_MORECORE 0
-#else /* ONLY_MSPACES */
-#define HAVE_MORECORE 1
-#endif /* ONLY_MSPACES */
-#endif /* HAVE_MORECORE */
-#if !HAVE_MORECORE
-#define MORECORE_CONTIGUOUS 0
-#else /* !HAVE_MORECORE */
-#define MORECORE_DEFAULT sbrk
-#ifndef MORECORE_CONTIGUOUS
-#define MORECORE_CONTIGUOUS 1
-#endif /* MORECORE_CONTIGUOUS */
-#endif /* HAVE_MORECORE */
-#ifndef DEFAULT_GRANULARITY
-#if (MORECORE_CONTIGUOUS || defined(WIN32))
-#define DEFAULT_GRANULARITY (0) /* 0 means to compute in init_mparams */
-#else /* MORECORE_CONTIGUOUS */
-#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U)
-#endif /* MORECORE_CONTIGUOUS */
-#endif /* DEFAULT_GRANULARITY */
-#ifndef DEFAULT_TRIM_THRESHOLD
-#ifndef MORECORE_CANNOT_TRIM
-#define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U)
-#else /* MORECORE_CANNOT_TRIM */
-#define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T
-#endif /* MORECORE_CANNOT_TRIM */
-#endif /* DEFAULT_TRIM_THRESHOLD */
-#ifndef DEFAULT_MMAP_THRESHOLD
-#if HAVE_MMAP
-#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U)
-#else /* HAVE_MMAP */
-#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
-#endif /* HAVE_MMAP */
-#endif /* DEFAULT_MMAP_THRESHOLD */
-#ifndef MAX_RELEASE_CHECK_RATE
-#if HAVE_MMAP
-#define MAX_RELEASE_CHECK_RATE 4095
-#else
-#define MAX_RELEASE_CHECK_RATE MAX_SIZE_T
-#endif /* HAVE_MMAP */
-#endif /* MAX_RELEASE_CHECK_RATE */
-#ifndef USE_BUILTIN_FFS
-#define USE_BUILTIN_FFS 0
-#endif /* USE_BUILTIN_FFS */
-#ifndef USE_DEV_RANDOM
-#define USE_DEV_RANDOM 0
-#endif /* USE_DEV_RANDOM */
-#ifndef NO_MALLINFO
-#define NO_MALLINFO 0
-#endif /* NO_MALLINFO */
-#ifndef MALLINFO_FIELD_TYPE
-#define MALLINFO_FIELD_TYPE size_t
-#endif /* MALLINFO_FIELD_TYPE */
-#ifndef NO_SEGMENT_TRAVERSAL
-#define NO_SEGMENT_TRAVERSAL 0
-#endif /* NO_SEGMENT_TRAVERSAL */
-
-/*
- mallopt tuning options. SVID/XPG defines four standard parameter
- numbers for mallopt, normally defined in malloc.h. None of these
- are used in this malloc, so setting them has no effect. But this
- malloc does support the following options.
-*/
-
-#define M_TRIM_THRESHOLD (-1)
-#define M_GRANULARITY (-2)
-#define M_MMAP_THRESHOLD (-3)
-
-/* ------------------------ Mallinfo declarations ------------------------ */
-
-#if !NO_MALLINFO
-/*
- This version of malloc supports the standard SVID/XPG mallinfo
- routine that returns a struct containing usage properties and
- statistics. It should work on any system that has a
- /usr/include/malloc.h defining struct mallinfo. The main
- declaration needed is the mallinfo struct that is returned (by-copy)
- by mallinfo(). The malloinfo struct contains a bunch of fields that
- are not even meaningful in this version of malloc. These fields are
- are instead filled by mallinfo() with other numbers that might be of
- interest.
-
- HAVE_USR_INCLUDE_MALLOC_H should be set if you have a
- /usr/include/malloc.h file that includes a declaration of struct
- mallinfo. If so, it is included; else a compliant version is
- declared below. These must be precisely the same for mallinfo() to
- work. The original SVID version of this struct, defined on most
- systems with mallinfo, declares all fields as ints. But some others
- define as unsigned long. If your system defines the fields using a
- type of different width than listed here, you MUST #include your
- system version and #define HAVE_USR_INCLUDE_MALLOC_H.
-*/
-
-/* #define HAVE_USR_INCLUDE_MALLOC_H */
-
-#ifdef HAVE_USR_INCLUDE_MALLOC_H
-#include "/usr/include/malloc.h"
-#else /* HAVE_USR_INCLUDE_MALLOC_H */
-#ifndef STRUCT_MALLINFO_DECLARED
-#define STRUCT_MALLINFO_DECLARED 1
-struct mallinfo {
- MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */
- MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */
- MALLINFO_FIELD_TYPE smblks; /* always 0 */
- MALLINFO_FIELD_TYPE hblks; /* always 0 */
- MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */
- MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */
- MALLINFO_FIELD_TYPE fsmblks; /* always 0 */
- MALLINFO_FIELD_TYPE uordblks; /* total allocated space */
- MALLINFO_FIELD_TYPE fordblks; /* total free space */
- MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */
-};
-#endif /* STRUCT_MALLINFO_DECLARED */
-#endif /* HAVE_USR_INCLUDE_MALLOC_H */
-#endif /* NO_MALLINFO */
-
-/*
- Try to persuade compilers to inline. The most critical functions for
- inlining are defined as macros, so these aren't used for them.
-*/
-
-#ifndef FORCEINLINE
- #if defined(__GNUC__)
-#define FORCEINLINE __inline __attribute__ ((always_inline))
- #elif defined(_MSC_VER)
- #define FORCEINLINE __forceinline
- #endif
-#endif
-#ifndef NOINLINE
- #if defined(__GNUC__)
- #define NOINLINE __attribute__ ((noinline))
- #elif defined(_MSC_VER)
- #define NOINLINE __declspec(noinline)
- #else
- #define NOINLINE
- #endif
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#ifndef FORCEINLINE
- #define FORCEINLINE inline
-#endif
-#endif /* __cplusplus */
-#ifndef FORCEINLINE
- #define FORCEINLINE
-#endif
-
-#if !ONLY_MSPACES
-
-/* ------------------- Declarations of public routines ------------------- */
-
-#ifndef USE_DL_PREFIX
-#define dlcalloc calloc
-#define dlfree free
-#define dlmalloc malloc
-#define dlmemalign memalign
-#define dlrealloc realloc
-#define dlvalloc valloc
-#define dlpvalloc pvalloc
-#define dlmallinfo mallinfo
-#define dlmallopt mallopt
-#define dlmalloc_trim malloc_trim
-#define dlmalloc_stats malloc_stats
-#define dlmalloc_usable_size malloc_usable_size
-#define dlmalloc_footprint malloc_footprint
-#define dlmalloc_max_footprint malloc_max_footprint
-#define dlindependent_calloc independent_calloc
-#define dlindependent_comalloc independent_comalloc
-#endif /* USE_DL_PREFIX */
-
-
-/*
- malloc(size_t n)
- Returns a pointer to a newly allocated chunk of at least n bytes, or
- null if no space is available, in which case errno is set to ENOMEM
- on ANSI C systems.
-
- If n is zero, malloc returns a minimum-sized chunk. (The minimum
- size is 16 bytes on most 32bit systems, and 32 bytes on 64bit
- systems.) Note that size_t is an unsigned type, so calls with
- arguments that would be negative if signed are interpreted as
- requests for huge amounts of space, which will often fail. The
- maximum supported value of n differs across systems, but is in all
- cases less than the maximum representable value of a size_t.
-*/
-void* dlmalloc(size_t);
-
-/*
- free(void* p)
- Releases the chunk of memory pointed to by p, that had been previously
- allocated using malloc or a related routine such as realloc.
- It has no effect if p is null. If p was not malloced or already
- freed, free(p) will by default cause the current program to abort.
-*/
-void dlfree(void*);
-
-/*
- calloc(size_t n_elements, size_t element_size);
- Returns a pointer to n_elements * element_size bytes, with all locations
- set to zero.
-*/
-void* dlcalloc(size_t, size_t);
-
-/*
- realloc(void* p, size_t n)
- Returns a pointer to a chunk of size n that contains the same data
- as does chunk p up to the minimum of (n, p's size) bytes, or null
- if no space is available.
-
- The returned pointer may or may not be the same as p. The algorithm
- prefers extending p in most cases when possible, otherwise it
- employs the equivalent of a malloc-copy-free sequence.
-
- If p is null, realloc is equivalent to malloc.
-
- If space is not available, realloc returns null, errno is set (if on
- ANSI) and p is NOT freed.
-
- if n is for fewer bytes than already held by p, the newly unused
- space is lopped off and freed if possible. realloc with a size
- argument of zero (re)allocates a minimum-sized chunk.
-
- The old unix realloc convention of allowing the last-free'd chunk
- to be used as an argument to realloc is not supported.
-*/
-
-void* dlrealloc(void*, size_t);
-
-/*
- memalign(size_t alignment, size_t n);
- Returns a pointer to a newly allocated chunk of n bytes, aligned
- in accord with the alignment argument.
-
- The alignment argument should be a power of two. If the argument is
- not a power of two, the nearest greater power is used.
- 8-byte alignment is guaranteed by normal malloc calls, so don't
- bother calling memalign with an argument of 8 or less.
-
- Overreliance on memalign is a sure way to fragment space.
-*/
-void* dlmemalign(size_t, size_t);
-
-/*
- valloc(size_t n);
- Equivalent to memalign(pagesize, n), where pagesize is the page
- size of the system. If the pagesize is unknown, 4096 is used.
-*/
-void* dlvalloc(size_t);
-
-/*
- mallopt(int parameter_number, int parameter_value)
- Sets tunable parameters The format is to provide a
- (parameter-number, parameter-value) pair. mallopt then sets the
- corresponding parameter to the argument value if it can (i.e., so
- long as the value is meaningful), and returns 1 if successful else
- 0. To workaround the fact that mallopt is specified to use int,
- not size_t parameters, the value -1 is specially treated as the
- maximum unsigned size_t value.
-
- SVID/XPG/ANSI defines four standard param numbers for mallopt,
- normally defined in malloc.h. None of these are use in this malloc,
- so setting them has no effect. But this malloc also supports other
- options in mallopt. See below for details. Briefly, supported
- parameters are as follows (listed defaults are for "typical"
- configurations).
-
- Symbol param # default allowed param values
- M_TRIM_THRESHOLD -1 2*1024*1024 any (-1 disables)
- M_GRANULARITY -2 page size any power of 2 >= page size
- M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support)
-*/
-int dlmallopt(int, int);
-
-/*
- malloc_footprint();
- Returns the number of bytes obtained from the system. The total
- number of bytes allocated by malloc, realloc etc., is less than this
- value. Unlike mallinfo, this function returns only a precomputed
- result, so can be called frequently to monitor memory consumption.
- Even if locks are otherwise defined, this function does not use them,
- so results might not be up to date.
-*/
-size_t dlmalloc_footprint(void);
-
-/*
- malloc_max_footprint();
- Returns the maximum number of bytes obtained from the system. This
- value will be greater than current footprint if deallocated space
- has been reclaimed by the system. The peak number of bytes allocated
- by malloc, realloc etc., is less than this value. Unlike mallinfo,
- this function returns only a precomputed result, so can be called
- frequently to monitor memory consumption. Even if locks are
- otherwise defined, this function does not use them, so results might
- not be up to date.
-*/
-size_t dlmalloc_max_footprint(void);
-
-#if !NO_MALLINFO
-/*
- mallinfo()
- Returns (by copy) a struct containing various summary statistics:
-
- arena: current total non-mmapped bytes allocated from system
- ordblks: the number of free chunks
- smblks: always zero.
- hblks: current number of mmapped regions
- hblkhd: total bytes held in mmapped regions
- usmblks: the maximum total allocated space. This will be greater
- than current total if trimming has occurred.
- fsmblks: always zero
- uordblks: current total allocated space (normal or mmapped)
- fordblks: total free space
- keepcost: the maximum number of bytes that could ideally be released
- back to system via malloc_trim. ("ideally" means that
- it ignores page restrictions etc.)
-
- Because these fields are ints, but internal bookkeeping may
- be kept as longs, the reported values may wrap around zero and
- thus be inaccurate.
-*/
-struct mallinfo dlmallinfo(void);
-#endif /* NO_MALLINFO */
-
-/*
- independent_calloc(size_t n_elements, size_t element_size, void* chunks[]);
-
- independent_calloc is similar to calloc, but instead of returning a
- single cleared space, it returns an array of pointers to n_elements
- independent elements that can hold contents of size elem_size, each
- of which starts out cleared, and can be independently freed,
- realloc'ed etc. The elements are guaranteed to be adjacently
- allocated (this is not guaranteed to occur with multiple callocs or
- mallocs), which may also improve cache locality in some
- applications.
-
- The "chunks" argument is optional (i.e., may be null, which is
- probably the most typical usage). If it is null, the returned array
- is itself dynamically allocated and should also be freed when it is
- no longer needed. Otherwise, the chunks array must be of at least
- n_elements in length. It is filled in with the pointers to the
- chunks.
-
- In either case, independent_calloc returns this pointer array, or
- null if the allocation failed. If n_elements is zero and "chunks"
- is null, it returns a chunk representing an array with zero elements
- (which should be freed if not wanted).
-
- Each element must be individually freed when it is no longer
- needed. If you'd like to instead be able to free all at once, you
- should instead use regular calloc and assign pointers into this
- space to represent elements. (In this case though, you cannot
- independently free elements.)
-
- independent_calloc simplifies and speeds up implementations of many
- kinds of pools. It may also be useful when constructing large data
- structures that initially have a fixed number of fixed-sized nodes,
- but the number is not known at compile time, and some of the nodes
- may later need to be freed. For example:
-
- struct Node { int item; struct Node* next; };
-
- struct Node* build_list() {
- struct Node** pool;
- int n = read_number_of_nodes_needed();
- if (n <= 0) return 0;
- pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0);
- if (pool == 0) die();
- // organize into a linked list...
- struct Node* first = pool[0];
- for (i = 0; i < n-1; ++i)
- pool[i]->next = pool[i+1];
- free(pool); // Can now free the array (or not, if it is needed later)
- return first;
- }
-*/
-void** dlindependent_calloc(size_t, size_t, void**);
-
-/*
- independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]);
-
- independent_comalloc allocates, all at once, a set of n_elements
- chunks with sizes indicated in the "sizes" array. It returns
- an array of pointers to these elements, each of which can be
- independently freed, realloc'ed etc. The elements are guaranteed to
- be adjacently allocated (this is not guaranteed to occur with
- multiple callocs or mallocs), which may also improve cache locality
- in some applications.
-
- The "chunks" argument is optional (i.e., may be null). If it is null
- the returned array is itself dynamically allocated and should also
- be freed when it is no longer needed. Otherwise, the chunks array
- must be of at least n_elements in length. It is filled in with the
- pointers to the chunks.
-
- In either case, independent_comalloc returns this pointer array, or
- null if the allocation failed. If n_elements is zero and chunks is
- null, it returns a chunk representing an array with zero elements
- (which should be freed if not wanted).
-
- Each element must be individually freed when it is no longer
- needed. If you'd like to instead be able to free all at once, you
- should instead use a single regular malloc, and assign pointers at
- particular offsets in the aggregate space. (In this case though, you
- cannot independently free elements.)
-
- independent_comallac differs from independent_calloc in that each
- element may have a different size, and also that it does not
- automatically clear elements.
-
- independent_comalloc can be used to speed up allocation in cases
- where several structs or objects must always be allocated at the
- same time. For example:
-
- struct Head { ... }
- struct Foot { ... }
-
- void send_message(char* msg) {
- int msglen = strlen(msg);
- size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) };
- void* chunks[3];
- if (independent_comalloc(3, sizes, chunks) == 0)
- die();
- struct Head* head = (struct Head*)(chunks[0]);
- char* body = (char*)(chunks[1]);
- struct Foot* foot = (struct Foot*)(chunks[2]);
- // ...
- }
-
- In general though, independent_comalloc is worth using only for
- larger values of n_elements. For small values, you probably won't
- detect enough difference from series of malloc calls to bother.
-
- Overuse of independent_comalloc can increase overall memory usage,
- since it cannot reuse existing noncontiguous small chunks that
- might be available for some of the elements.
-*/
-void** dlindependent_comalloc(size_t, size_t*, void**);
-
-
-/*
- pvalloc(size_t n);
- Equivalent to valloc(minimum-page-that-holds(n)), that is,
- round up n to nearest pagesize.
- */
-void* dlpvalloc(size_t);
-
-/*
- malloc_trim(size_t pad);
-
- If possible, gives memory back to the system (via negative arguments
- to sbrk) if there is unused memory at the `high' end of the malloc
- pool or in unused MMAP segments. You can call this after freeing
- large blocks of memory to potentially reduce the system-level memory
- requirements of a program. However, it cannot guarantee to reduce
- memory. Under some allocation patterns, some large free blocks of
- memory will be locked between two used chunks, so they cannot be
- given back to the system.
-
- The `pad' argument to malloc_trim represents the amount of free
- trailing space to leave untrimmed. If this argument is zero, only
- the minimum amount of memory to maintain internal data structures
- will be left. Non-zero arguments can be supplied to maintain enough
- trailing space to service future expected allocations without having
- to re-obtain memory from the system.
-
- Malloc_trim returns 1 if it actually released any memory, else 0.
-*/
-int dlmalloc_trim(size_t);
-
-/*
- malloc_stats();
- Prints on stderr the amount of space obtained from the system (both
- via sbrk and mmap), the maximum amount (which may be more than
- current if malloc_trim and/or munmap got called), and the current
- number of bytes allocated via malloc (or realloc, etc) but not yet
- freed. Note that this is the number of bytes allocated, not the
- number requested. It will be larger than the number requested
- because of alignment and bookkeeping overhead. Because it includes
- alignment wastage as being in use, this figure may be greater than
- zero even when no user-level chunks are allocated.
-
- The reported current and maximum system memory can be inaccurate if
- a program makes other calls to system memory allocation functions
- (normally sbrk) outside of malloc.
-
- malloc_stats prints only the most commonly interesting statistics.
- More information can be obtained by calling mallinfo.
-*/
-void dlmalloc_stats(void);
-
-#endif /* ONLY_MSPACES */
-
-/*
- malloc_usable_size(void* p);
-
- Returns the number of bytes you can actually use in
- an allocated chunk, which may be more than you requested (although
- often not) due to alignment and minimum size constraints.
- You can use this many bytes without worrying about
- overwriting other allocated objects. This is not a particularly great
- programming practice. malloc_usable_size can be more useful in
- debugging and assertions, for example:
-
- p = malloc(n);
- assert(malloc_usable_size(p) >= 256);
-*/
-size_t dlmalloc_usable_size(void*);
-
-
-#if MSPACES
-
-/*
- mspace is an opaque type representing an independent
- region of space that supports mspace_malloc, etc.
-*/
-typedef void* mspace;
-
-/*
- create_mspace creates and returns a new independent space with the
- given initial capacity, or, if 0, the default granularity size. It
- returns null if there is no system memory available to create the
- space. If argument locked is non-zero, the space uses a separate
- lock to control access. The capacity of the space will grow
- dynamically as needed to service mspace_malloc requests. You can
- control the sizes of incremental increases of this space by
- compiling with a different DEFAULT_GRANULARITY or dynamically
- setting with mallopt(M_GRANULARITY, value).
-*/
-mspace create_mspace(size_t capacity, int locked);
-
-/*
- destroy_mspace destroys the given space, and attempts to return all
- of its memory back to the system, returning the total number of
- bytes freed. After destruction, the results of access to all memory
- used by the space become undefined.
-*/
-size_t destroy_mspace(mspace msp);
-
-/*
- create_mspace_with_base uses the memory supplied as the initial base
- of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this
- space is used for bookkeeping, so the capacity must be at least this
- large. (Otherwise 0 is returned.) When this initial space is
- exhausted, additional memory will be obtained from the system.
- Destroying this space will deallocate all additionally allocated
- space (if possible) but not the initial base.
-*/
-mspace create_mspace_with_base(void* base, size_t capacity, int locked);
-
-/*
- mspace_track_large_chunks controls whether requests for large chunks
- are allocated in their own untracked mmapped regions, separate from
- others in this mspace. By default large chunks are not tracked,
- which reduces fragmentation. However, such chunks are not
- necessarily released to the system upon destroy_mspace. Enabling
- tracking by setting to true may increase fragmentation, but avoids
- leakage when relying on destroy_mspace to release all memory
- allocated using this space. The function returns the previous
- setting.
-*/
-int mspace_track_large_chunks(mspace msp, int enable);
-
-
-/*
- mspace_malloc behaves as malloc, but operates within
- the given space.
-*/
-void* mspace_malloc(mspace msp, size_t bytes);
-
-/*
- mspace_free behaves as free, but operates within
- the given space.
-
- If compiled with FOOTERS==1, mspace_free is not actually needed.
- free may be called instead of mspace_free because freed chunks from
- any space are handled by their originating spaces.
-*/
-void mspace_free(mspace msp, void* mem);
-
-/*
- mspace_realloc behaves as realloc, but operates within
- the given space.
-
- If compiled with FOOTERS==1, mspace_realloc is not actually
- needed. realloc may be called instead of mspace_realloc because
- realloced chunks from any space are handled by their originating
- spaces.
-*/
-void* mspace_realloc(mspace msp, void* mem, size_t newsize);
-
-/*
- mspace_calloc behaves as calloc, but operates within
- the given space.
-*/
-void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size);
-
-/*
- mspace_memalign behaves as memalign, but operates within
- the given space.
-*/
-void* mspace_memalign(mspace msp, size_t alignment, size_t bytes);
-
-/*
- mspace_independent_calloc behaves as independent_calloc, but
- operates within the given space.
-*/
-void** mspace_independent_calloc(mspace msp, size_t n_elements,
- size_t elem_size, void* chunks[]);
-
-/*
- mspace_independent_comalloc behaves as independent_comalloc, but
- operates within the given space.
-*/
-void** mspace_independent_comalloc(mspace msp, size_t n_elements,
- size_t sizes[], void* chunks[]);
-
-/*
- mspace_footprint() returns the number of bytes obtained from the
- system for this space.
-*/
-size_t mspace_footprint(mspace msp);
-
-/*
- mspace_max_footprint() returns the peak number of bytes obtained from the
- system for this space.
-*/
-size_t mspace_max_footprint(mspace msp);
-
-
-#if !NO_MALLINFO
-/*
- mspace_mallinfo behaves as mallinfo, but reports properties of
- the given space.
-*/
-struct mallinfo mspace_mallinfo(mspace msp);
-#endif /* NO_MALLINFO */
-
-/*
- malloc_usable_size(void* p) behaves the same as malloc_usable_size;
-*/
- size_t mspace_usable_size(void* mem);
-
-/*
- mspace_malloc_stats behaves as malloc_stats, but reports
- properties of the given space.
-*/
-void mspace_malloc_stats(mspace msp);
-
-/*
- mspace_trim behaves as malloc_trim, but
- operates within the given space.
-*/
-int mspace_trim(mspace msp, size_t pad);
-
-/*
- An alias for mallopt.
-*/
-int mspace_mallopt(int, int);
-
-#endif /* MSPACES */
-
-#ifdef __cplusplus
-} /* end of extern "C" */
-#endif /* __cplusplus */
-
-/*
- ========================================================================
- To make a fully customizable malloc.h header file, cut everything
- above this line, put into file malloc.h, edit to suit, and #include it
- on the next line, as well as in programs that use this malloc.
- ========================================================================
-*/
-
-/* #include "malloc.h" */
-
-/*------------------------------ internal #includes ---------------------- */
-
-#ifdef WIN32
-#pragma warning( disable : 4146 ) /* no "unsigned" warnings */
-#endif /* WIN32 */
-
-#include <stdio.h> /* for printing in malloc_stats */
-
-#ifndef LACKS_ERRNO_H
-#include <errno.h> /* for MALLOC_FAILURE_ACTION */
-#endif /* LACKS_ERRNO_H */
-/*#if FOOTERS || DEBUG
-*/
-#include <time.h> /* for magic initialization */
-/*#endif*/ /* FOOTERS */
-#ifndef LACKS_STDLIB_H
-#include <stdlib.h> /* for abort() */
-#endif /* LACKS_STDLIB_H */
-#ifdef DEBUG
-#if ABORT_ON_ASSERT_FAILURE
-#undef assert
-#define assert(x) if(!(x)) ABORT
-#else /* ABORT_ON_ASSERT_FAILURE */
-#include <assert.h>
-#endif /* ABORT_ON_ASSERT_FAILURE */
-#else /* DEBUG */
-#ifndef assert
-#define assert(x)
-#endif
-#define DEBUG 0
-#endif /* DEBUG */
-#ifndef LACKS_STRING_H
-#include <string.h> /* for memset etc */
-#endif /* LACKS_STRING_H */
-#if USE_BUILTIN_FFS
-#ifndef LACKS_STRINGS_H
-#include <strings.h> /* for ffs */
-#endif /* LACKS_STRINGS_H */
-#endif /* USE_BUILTIN_FFS */
-#if HAVE_MMAP
-#ifndef LACKS_SYS_MMAN_H
-/* On some versions of linux, mremap decl in mman.h needs __USE_GNU set */
-#if (defined(linux) && !defined(__USE_GNU))
-#define __USE_GNU 1
-#include <sys/mman.h> /* for mmap */
-#undef __USE_GNU
-#else
-#include <sys/mman.h> /* for mmap */
-#endif /* linux */
-#endif /* LACKS_SYS_MMAN_H */
-#ifndef LACKS_FCNTL_H
-#include <fcntl.h>
-#endif /* LACKS_FCNTL_H */
-#endif /* HAVE_MMAP */
-#ifndef LACKS_UNISTD_H
-#include <unistd.h> /* for sbrk, sysconf */
-#else /* LACKS_UNISTD_H */
-#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
-extern void* sbrk(ptrdiff_t);
-#endif /* FreeBSD etc */
-#endif /* LACKS_UNISTD_H */
-
-/* Declarations for locking */
-#if USE_LOCKS
-#ifndef WIN32
-#include <pthread.h>
-#if defined (__SVR4) && defined (__sun) /* solaris */
-#include <thread.h>
-#endif /* solaris */
-#else
-#ifndef _M_AMD64
-/* These are already defined on AMD64 builds */
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-LONG __cdecl _InterlockedCompareExchange(LONG volatile *Dest, LONG Exchange, LONG Comp);
-LONG __cdecl _InterlockedExchange(LONG volatile *Target, LONG Value);
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-#endif /* _M_AMD64 */
-#pragma intrinsic (_InterlockedCompareExchange)
-#pragma intrinsic (_InterlockedExchange)
-#define interlockedcompareexchange _InterlockedCompareExchange
-#define interlockedexchange _InterlockedExchange
-#endif /* Win32 */
-#endif /* USE_LOCKS */
-
-/* Declarations for bit scanning on win32 */
-#if defined(_MSC_VER) && _MSC_VER>=1300
-#ifndef BitScanForward /* Try to avoid pulling in WinNT.h */
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-unsigned char _BitScanForward(unsigned long *index, unsigned long mask);
-unsigned char _BitScanReverse(unsigned long *index, unsigned long mask);
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#define BitScanForward _BitScanForward
-#define BitScanReverse _BitScanReverse
-#pragma intrinsic(_BitScanForward)
-#pragma intrinsic(_BitScanReverse)
-#endif /* BitScanForward */
-#endif /* defined(_MSC_VER) && _MSC_VER>=1300 */
-
-#ifndef WIN32
-#ifndef malloc_getpagesize
-# ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */
-# ifndef _SC_PAGE_SIZE
-# define _SC_PAGE_SIZE _SC_PAGESIZE
-# endif
-# endif
-# ifdef _SC_PAGE_SIZE
-# define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
-# else
-# if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
- extern size_t getpagesize();
-# define malloc_getpagesize getpagesize()
-# else
-# ifdef WIN32 /* use supplied emulation of getpagesize */
-# define malloc_getpagesize getpagesize()
-# else
-# ifndef LACKS_SYS_PARAM_H
-# include <sys/param.h>
-# endif
-# ifdef EXEC_PAGESIZE
-# define malloc_getpagesize EXEC_PAGESIZE
-# else
-# ifdef NBPG
-# ifndef CLSIZE
-# define malloc_getpagesize NBPG
-# else
-# define malloc_getpagesize (NBPG * CLSIZE)
-# endif
-# else
-# ifdef NBPC
-# define malloc_getpagesize NBPC
-# else
-# ifdef PAGESIZE
-# define malloc_getpagesize PAGESIZE
-# else /* just guess */
-# define malloc_getpagesize ((size_t)4096U)
-# endif
-# endif
-# endif
-# endif
-# endif
-# endif
-# endif
-#endif
-#endif
-
-
-
-/* ------------------- size_t and alignment properties -------------------- */
-
-/* The byte and bit size of a size_t */
-#define SIZE_T_SIZE (sizeof(size_t))
-#define SIZE_T_BITSIZE (sizeof(size_t) << 3)
-
-/* Some constants coerced to size_t */
-/* Annoying but necessary to avoid errors on some platforms */
-#define SIZE_T_ZERO ((size_t)0)
-#define SIZE_T_ONE ((size_t)1)
-#define SIZE_T_TWO ((size_t)2)
-#define SIZE_T_FOUR ((size_t)4)
-#define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1)
-#define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2)
-#define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES)
-#define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U)
-
-/* The bit mask value corresponding to MALLOC_ALIGNMENT */
-#define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE)
-
-/* True if address a has acceptable alignment */
-#define is_aligned(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0)
-
-/* the number of bytes to offset an address to align it */
-#define align_offset(A)\
- ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\
- ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK))
-
-/* -------------------------- MMAP preliminaries ------------------------- */
-
-/*
- If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and
- checks to fail so compiler optimizer can delete code rather than
- using so many "#if"s.
-*/
-
-
-/* MORECORE and MMAP must return MFAIL on failure */
-#define MFAIL ((void*)(MAX_SIZE_T))
-#define CMFAIL ((char*)(MFAIL)) /* defined for convenience */
-
-#if HAVE_MMAP
-
-#ifndef WIN32
-#define MUNMAP_DEFAULT(a, s) munmap((a), (s))
-#define MMAP_PROT (PROT_READ|PROT_WRITE)
-#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
-#define MAP_ANONYMOUS MAP_ANON
-#endif /* MAP_ANON */
-#ifdef MAP_ANONYMOUS
-#define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS)
-#define MMAP_DEFAULT(s) mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0)
-#else /* MAP_ANONYMOUS */
-/*
- Nearly all versions of mmap support MAP_ANONYMOUS, so the following
- is unlikely to be needed, but is supplied just in case.
-*/
-#define MMAP_FLAGS (MAP_PRIVATE)
-static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */
-#define MMAP_DEFAULT(s) ((dev_zero_fd < 0) ? \
- (dev_zero_fd = open("/dev/zero", O_RDWR), \
- mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \
- mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0))
-#endif /* MAP_ANONYMOUS */
-
-#define DIRECT_MMAP_DEFAULT(s) MMAP_DEFAULT(s)
-
-#else /* WIN32 */
-
-/* Win32 MMAP via VirtualAlloc */
-static FORCEINLINE void* win32mmap(size_t size) {
- void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
- return (ptr != 0)? ptr: MFAIL;
-}
-
-/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
-static FORCEINLINE void* win32direct_mmap(size_t size) {
- void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
- PAGE_READWRITE);
- return (ptr != 0)? ptr: MFAIL;
-}
-
-/* This function supports releasing coalesed segments */
-static FORCEINLINE int win32munmap(void* ptr, size_t size) {
- MEMORY_BASIC_INFORMATION minfo;
- char* cptr = (char*)ptr;
- while (size) {
- if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0)
- return -1;
- if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr ||
- minfo.State != MEM_COMMIT || minfo.RegionSize > size)
- return -1;
- if (VirtualFree(cptr, 0, MEM_RELEASE) == 0)
- return -1;
- cptr += minfo.RegionSize;
- size -= minfo.RegionSize;
- }
- return 0;
-}
-
-#define MMAP_DEFAULT(s) win32mmap(s)
-#define MUNMAP_DEFAULT(a, s) win32munmap((a), (s))
-#define DIRECT_MMAP_DEFAULT(s) win32direct_mmap(s)
-#endif /* WIN32 */
-#endif /* HAVE_MMAP */
-
-#if HAVE_MREMAP
-#ifndef WIN32
-#define MREMAP_DEFAULT(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv))
-#endif /* WIN32 */
-#endif /* HAVE_MREMAP */
-
-
-/**
- * Define CALL_MORECORE
- */
-#if HAVE_MORECORE
- #ifdef MORECORE
- #define CALL_MORECORE(S) MORECORE(S)
- #else /* MORECORE */
- #define CALL_MORECORE(S) MORECORE_DEFAULT(S)
- #endif /* MORECORE */
-#else /* HAVE_MORECORE */
- #define CALL_MORECORE(S) MFAIL
-#endif /* HAVE_MORECORE */
-
-/**
- * Define CALL_MMAP/CALL_MUNMAP/CALL_DIRECT_MMAP
- */
-#if HAVE_MMAP
- #define USE_MMAP_BIT (SIZE_T_ONE)
-
- #ifdef MMAP
- #define CALL_MMAP(s) MMAP(s)
- #else /* MMAP */
- #define CALL_MMAP(s) MMAP_DEFAULT(s)
- #endif /* MMAP */
- #ifdef MUNMAP
- #define CALL_MUNMAP(a, s) MUNMAP((a), (s))
- #else /* MUNMAP */
- #define CALL_MUNMAP(a, s) MUNMAP_DEFAULT((a), (s))
- #endif /* MUNMAP */
- #ifdef DIRECT_MMAP
- #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s)
- #else /* DIRECT_MMAP */
- #define CALL_DIRECT_MMAP(s) DIRECT_MMAP_DEFAULT(s)
- #endif /* DIRECT_MMAP */
-#else /* HAVE_MMAP */
- #define USE_MMAP_BIT (SIZE_T_ZERO)
-
- #define MMAP(s) MFAIL
- #define MUNMAP(a, s) (-1)
- #define DIRECT_MMAP(s) MFAIL
- #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s)
- #define CALL_MMAP(s) MMAP(s)
- #define CALL_MUNMAP(a, s) MUNMAP((a), (s))
-#endif /* HAVE_MMAP */
-
-/**
- * Define CALL_MREMAP
- */
-#if HAVE_MMAP && HAVE_MREMAP
- #ifdef MREMAP
- #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP((addr), (osz), (nsz), (mv))
- #else /* MREMAP */
- #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP_DEFAULT((addr), (osz), (nsz), (mv))
- #endif /* MREMAP */
-#else /* HAVE_MMAP && HAVE_MREMAP */
- #define CALL_MREMAP(addr, osz, nsz, mv) MFAIL
-#endif /* HAVE_MMAP && HAVE_MREMAP */
-
-/* mstate bit set if continguous morecore disabled or failed */
-#define USE_NONCONTIGUOUS_BIT (4U)
-
-/* segment bit set in create_mspace_with_base */
-#define EXTERN_BIT (8U)
-
-
-/* --------------------------- Lock preliminaries ------------------------ */
-
-/*
- When locks are defined, there is one global lock, plus
- one per-mspace lock.
-
- The global lock_ensures that mparams.magic and other unique
- mparams values are initialized only once. It also protects
- sequences of calls to MORECORE. In many cases sys_alloc requires
- two calls, that should not be interleaved with calls by other
- threads. This does not protect against direct calls to MORECORE
- by other threads not using this lock, so there is still code to
- cope the best we can on interference.
-
- Per-mspace locks surround calls to malloc, free, etc. To enable use
- in layered extensions, per-mspace locks are reentrant.
-
- Because lock-protected regions generally have bounded times, it is
- OK to use the supplied simple spinlocks in the custom versions for
- x86. Spinlocks are likely to improve performance for lightly
- contended applications, but worsen performance under heavy
- contention.
-
- If USE_LOCKS is > 1, the definitions of lock routines here are
- bypassed, in which case you will need to define the type MLOCK_T,
- and at least INITIAL_LOCK, ACQUIRE_LOCK, RELEASE_LOCK and possibly
- TRY_LOCK (which is not used in this malloc, but commonly needed in
- extensions.) You must also declare a
- static MLOCK_T malloc_global_mutex = { initialization values };.
-
-*/
-
-#if USE_LOCKS == 1
-
-#if USE_SPIN_LOCKS && SPIN_LOCKS_AVAILABLE
-#ifndef WIN32
-
-/* Custom pthread-style spin locks on x86 and x64 for gcc */
-struct pthread_mlock_t {
- volatile unsigned int l;
- unsigned int c;
- pthread_t threadid;
-};
-#define MLOCK_T struct pthread_mlock_t
-#define CURRENT_THREAD pthread_self()
-#define INITIAL_LOCK(sl) ((sl)->threadid = 0, (sl)->l = (sl)->c = 0, 0)
-#define ACQUIRE_LOCK(sl) pthread_acquire_lock(sl)
-#define RELEASE_LOCK(sl) pthread_release_lock(sl)
-#define TRY_LOCK(sl) pthread_try_lock(sl)
-#define SPINS_PER_YIELD 63
-
-static MLOCK_T malloc_global_mutex = { 0, 0, 0};
-
-static FORCEINLINE int pthread_acquire_lock (MLOCK_T *sl) {
- int spins = 0;
- volatile unsigned int* lp = &sl->l;
- for (;;) {
- if (*lp != 0) {
- if (sl->threadid == CURRENT_THREAD) {
- ++sl->c;
- return 0;
- }
- }
- else {
- /* place args to cmpxchgl in locals to evade oddities in some gccs */
- int cmp = 0;
- int val = 1;
- int ret;
- __asm__ __volatile__ ("lock; cmpxchgl %1, %2"
- : "=a" (ret)
- : "r" (val), "m" (*(lp)), "0"(cmp)
- : "memory", "cc");
- if (!ret) {
- assert(!sl->threadid);
- sl->threadid = CURRENT_THREAD;
- sl->c = 1;
- return 0;
- }
- }
- if ((++spins & SPINS_PER_YIELD) == 0) {
-#if defined (__SVR4) && defined (__sun) /* solaris */
- thr_yield();
-#else
-#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
- sched_yield();
-#else /* no-op yield on unknown systems */
- ;
-#endif /* __linux__ || __FreeBSD__ || __APPLE__ */
-#endif /* solaris */
- }
- }
-}
-
-static FORCEINLINE void pthread_release_lock (MLOCK_T *sl) {
- volatile unsigned int* lp = &sl->l;
- assert(*lp != 0);
- assert(sl->threadid == CURRENT_THREAD);
- if (--sl->c == 0) {
- sl->threadid = 0;
- int prev = 0;
- int ret;
- __asm__ __volatile__ ("lock; xchgl %0, %1"
- : "=r" (ret)
- : "m" (*(lp)), "0"(prev)
- : "memory");
- }
-}
-
-static FORCEINLINE int pthread_try_lock (MLOCK_T *sl) {
- volatile unsigned int* lp = &sl->l;
- if (*lp != 0) {
- if (sl->threadid == CURRENT_THREAD) {
- ++sl->c;
- return 1;
- }
- }
- else {
- int cmp = 0;
- int val = 1;
- int ret;
- __asm__ __volatile__ ("lock; cmpxchgl %1, %2"
- : "=a" (ret)
- : "r" (val), "m" (*(lp)), "0"(cmp)
- : "memory", "cc");
- if (!ret) {
- assert(!sl->threadid);
- sl->threadid = CURRENT_THREAD;
- sl->c = 1;
- return 1;
- }
- }
- return 0;
-}
-
-
-#else /* WIN32 */
-/* Custom win32-style spin locks on x86 and x64 for MSC */
-struct win32_mlock_t {
- volatile long l;
- unsigned int c;
- long threadid;
-};
-
-#define MLOCK_T struct win32_mlock_t
-#define CURRENT_THREAD GetCurrentThreadId()
-#define INITIAL_LOCK(sl) ((sl)->threadid = 0, (sl)->l = (sl)->c = 0, 0)
-#define ACQUIRE_LOCK(sl) win32_acquire_lock(sl)
-#define RELEASE_LOCK(sl) win32_release_lock(sl)
-#define TRY_LOCK(sl) win32_try_lock(sl)
-#define SPINS_PER_YIELD 63
-
-static MLOCK_T malloc_global_mutex = { 0, 0, 0};
-
-static FORCEINLINE int win32_acquire_lock (MLOCK_T *sl) {
- int spins = 0;
- for (;;) {
- if (sl->l != 0) {
- if (sl->threadid == CURRENT_THREAD) {
- ++sl->c;
- return 0;
- }
- }
- else {
- if (!interlockedexchange(&sl->l, 1)) {
- assert(!sl->threadid);
- sl->threadid = CURRENT_THREAD;
- sl->c = 1;
- return 0;
- }
- }
- if ((++spins & SPINS_PER_YIELD) == 0)
- SleepEx(0, FALSE);
- }
-}
-
-static FORCEINLINE void win32_release_lock (MLOCK_T *sl) {
- assert(sl->threadid == CURRENT_THREAD);
- assert(sl->l != 0);
- if (--sl->c == 0) {
- sl->threadid = 0;
- interlockedexchange (&sl->l, 0);
- }
-}
-
-static FORCEINLINE int win32_try_lock (MLOCK_T *sl) {
- if (sl->l != 0) {
- if (sl->threadid == CURRENT_THREAD) {
- ++sl->c;
- return 1;
- }
- }
- else {
- if (!interlockedexchange(&sl->l, 1)){
- assert(!sl->threadid);
- sl->threadid = CURRENT_THREAD;
- sl->c = 1;
- return 1;
- }
- }
- return 0;
-}
-
-#endif /* WIN32 */
-#else /* USE_SPIN_LOCKS */
-
-#ifndef WIN32
-/* pthreads-based locks */
-
-#define MLOCK_T pthread_mutex_t
-#define CURRENT_THREAD pthread_self()
-#define INITIAL_LOCK(sl) pthread_init_lock(sl)
-#define ACQUIRE_LOCK(sl) pthread_mutex_lock(sl)
-#define RELEASE_LOCK(sl) pthread_mutex_unlock(sl)
-#define TRY_LOCK(sl) (!pthread_mutex_trylock(sl))
-
-static MLOCK_T malloc_global_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-/* Cope with old-style linux recursive lock initialization by adding */
-/* skipped internal declaration from pthread.h */
-#ifdef linux
-#ifndef PTHREAD_MUTEX_RECURSIVE
-extern int pthread_mutexattr_setkind_np __P ((pthread_mutexattr_t *__attr,
- int __kind));
-#define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP
-#define pthread_mutexattr_settype(x,y) pthread_mutexattr_setkind_np(x,y)
-#endif
-#endif
-
-static int pthread_init_lock (MLOCK_T *sl) {
- pthread_mutexattr_t attr;
- if (pthread_mutexattr_init(&attr)) return 1;
- if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) return 1;
- if (pthread_mutex_init(sl, &attr)) return 1;
- if (pthread_mutexattr_destroy(&attr)) return 1;
- return 0;
-}
-
-#else /* WIN32 */
-/* Win32 critical sections */
-#define MLOCK_T CRITICAL_SECTION
-#define CURRENT_THREAD GetCurrentThreadId()
-#define INITIAL_LOCK(s) (!InitializeCriticalSectionAndSpinCount((s), 0x80000000|4000))
-#define ACQUIRE_LOCK(s) (EnterCriticalSection(sl), 0)
-#define RELEASE_LOCK(s) LeaveCriticalSection(sl)
-#define TRY_LOCK(s) TryEnterCriticalSection(sl)
-#define NEED_GLOBAL_LOCK_INIT
-
-static MLOCK_T malloc_global_mutex;
-static volatile long malloc_global_mutex_status;
-
-/* Use spin loop to initialize global lock */
-static void init_malloc_global_mutex() {
- for (;;) {
- long stat = malloc_global_mutex_status;
- if (stat > 0)
- return;
- /* transition to < 0 while initializing, then to > 0) */
- if (stat == 0 &&
- interlockedcompareexchange(&malloc_global_mutex_status, -1, 0) == 0) {
- InitializeCriticalSection(&malloc_global_mutex);
- interlockedexchange(&malloc_global_mutex_status,1);
- return;
- }
- SleepEx(0, FALSE);
- }
-}
-
-#endif /* WIN32 */
-#endif /* USE_SPIN_LOCKS */
-#endif /* USE_LOCKS == 1 */
-
-/* ----------------------- User-defined locks ------------------------ */
-
-#if USE_LOCKS > 1
-/* Define your own lock implementation here */
-/* #define INITIAL_LOCK(sl) ... */
-/* #define ACQUIRE_LOCK(sl) ... */
-/* #define RELEASE_LOCK(sl) ... */
-/* #define TRY_LOCK(sl) ... */
-/* static MLOCK_T malloc_global_mutex = ... */
-#endif /* USE_LOCKS > 1 */
-
-/* ----------------------- Lock-based state ------------------------ */
-
-#if USE_LOCKS
-#define USE_LOCK_BIT (2U)
-#else /* USE_LOCKS */
-#define USE_LOCK_BIT (0U)
-#define INITIAL_LOCK(l)
-#endif /* USE_LOCKS */
-
-#if USE_LOCKS
-#ifndef ACQUIRE_MALLOC_GLOBAL_LOCK
-#define ACQUIRE_MALLOC_GLOBAL_LOCK() ACQUIRE_LOCK(&malloc_global_mutex);
-#endif
-#ifndef RELEASE_MALLOC_GLOBAL_LOCK
-#define RELEASE_MALLOC_GLOBAL_LOCK() RELEASE_LOCK(&malloc_global_mutex);
-#endif
-#else /* USE_LOCKS */
-#define ACQUIRE_MALLOC_GLOBAL_LOCK()
-#define RELEASE_MALLOC_GLOBAL_LOCK()
-#endif /* USE_LOCKS */
-
-
-/* ----------------------- Chunk representations ------------------------ */
-
-/*
- (The following includes lightly edited explanations by Colin Plumb.)
-
- The malloc_chunk declaration below is misleading (but accurate and
- necessary). It declares a "view" into memory allowing access to
- necessary fields at known offsets from a given base.
-
- Chunks of memory are maintained using a `boundary tag' method as
- originally described by Knuth. (See the paper by Paul Wilson
- ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such
- techniques.) Sizes of free chunks are stored both in the front of
- each chunk and at the end. This makes consolidating fragmented
- chunks into bigger chunks fast. The head fields also hold bits
- representing whether chunks are free or in use.
-
- Here are some pictures to make it clearer. They are "exploded" to
- show that the state of a chunk can be thought of as extending from
- the high 31 bits of the head field of its header through the
- prev_foot and PINUSE_BIT bit of the following chunk header.
-
- A chunk that's in use looks like:
-
- chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Size of previous chunk (if P = 0) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
- | Size of this chunk 1| +-+
- mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | |
- +- -+
- | |
- +- -+
- | :
- +- size - sizeof(size_t) available payload bytes -+
- : |
- chunk-> +- -+
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1|
- | Size of next chunk (may or may not be in use) | +-+
- mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- And if it's free, it looks like this:
-
- chunk-> +- -+
- | User payload (must be in use, or we would have merged!) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
- | Size of this chunk 0| +-+
- mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Next pointer |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Prev pointer |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | :
- +- size - sizeof(struct chunk) unused bytes -+
- : |
- chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Size of this chunk |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0|
- | Size of next chunk (must be in use, or we would have merged)| +-+
- mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | :
- +- User payload -+
- : |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- |0|
- +-+
- Note that since we always merge adjacent free chunks, the chunks
- adjacent to a free chunk must be in use.
-
- Given a pointer to a chunk (which can be derived trivially from the
- payload pointer) we can, in O(1) time, find out whether the adjacent
- chunks are free, and if so, unlink them from the lists that they
- are on and merge them with the current chunk.
-
- Chunks always begin on even word boundaries, so the mem portion
- (which is returned to the user) is also on an even word boundary, and
- thus at least double-word aligned.
-
- The P (PINUSE_BIT) bit, stored in the unused low-order bit of the
- chunk size (which is always a multiple of two words), is an in-use
- bit for the *previous* chunk. If that bit is *clear*, then the
- word before the current chunk size contains the previous chunk
- size, and can be used to find the front of the previous chunk.
- The very first chunk allocated always has this bit set, preventing
- access to non-existent (or non-owned) memory. If pinuse is set for
- any given chunk, then you CANNOT determine the size of the
- previous chunk, and might even get a memory addressing fault when
- trying to do so.
-
- The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of
- the chunk size redundantly records whether the current chunk is
- inuse (unless the chunk is mmapped). This redundancy enables usage
- checks within free and realloc, and reduces indirection when freeing
- and consolidating chunks.
-
- Each freshly allocated chunk must have both cinuse and pinuse set.
- That is, each allocated chunk borders either a previously allocated
- and still in-use chunk, or the base of its memory arena. This is
- ensured by making all allocations from the the `lowest' part of any
- found chunk. Further, no free chunk physically borders another one,
- so each free chunk is known to be preceded and followed by either
- inuse chunks or the ends of memory.
-
- Note that the `foot' of the current chunk is actually represented
- as the prev_foot of the NEXT chunk. This makes it easier to
- deal with alignments etc but can be very confusing when trying
- to extend or adapt this code.
-
- The exceptions to all this are
-
- 1. The special chunk `top' is the top-most available chunk (i.e.,
- the one bordering the end of available memory). It is treated
- specially. Top is never included in any bin, is used only if
- no other chunk is available, and is released back to the
- system if it is very large (see M_TRIM_THRESHOLD). In effect,
- the top chunk is treated as larger (and thus less well
- fitting) than any other available chunk. The top chunk
- doesn't update its trailing size field since there is no next
- contiguous chunk that would have to index off it. However,
- space is still allocated for it (TOP_FOOT_SIZE) to enable
- separation or merging when space is extended.
-
- 3. Chunks allocated via mmap, have both cinuse and pinuse bits
- cleared in their head fields. Because they are allocated
- one-by-one, each must carry its own prev_foot field, which is
- also used to hold the offset this chunk has within its mmapped
- region, which is needed to preserve alignment. Each mmapped
- chunk is trailed by the first two fields of a fake next-chunk
- for sake of usage checks.
-
-*/
-
-struct malloc_chunk {
- size_t prev_foot; /* Size of previous chunk (if free). */
- size_t head; /* Size and inuse bits. */
- struct malloc_chunk* fd; /* double links -- used only if free. */
- struct malloc_chunk* bk;
-};
-
-typedef struct malloc_chunk mchunk;
-typedef struct malloc_chunk* mchunkptr;
-typedef struct malloc_chunk* sbinptr; /* The type of bins of chunks */
-typedef unsigned int bindex_t; /* Described below */
-typedef unsigned int binmap_t; /* Described below */
-typedef unsigned int flag_t; /* The type of various bit flag sets */
-
-/* ------------------- Chunks sizes and alignments ----------------------- */
-
-#define MCHUNK_SIZE (sizeof(mchunk))
-
-#if FOOTERS
-#define CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
-#else /* FOOTERS */
-#define CHUNK_OVERHEAD (SIZE_T_SIZE)
-#endif /* FOOTERS */
-
-/* MMapped chunks need a second word of overhead ... */
-#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
-/* ... and additional padding for fake next-chunk at foot */
-#define MMAP_FOOT_PAD (FOUR_SIZE_T_SIZES)
-
-/* The smallest size we can malloc is an aligned minimal chunk */
-#define MIN_CHUNK_SIZE\
- ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
-
-/* conversion from malloc headers to user pointers, and back */
-#define chunk2mem(p) ((void*)((char*)(p) + TWO_SIZE_T_SIZES))
-#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES))
-/* chunk associated with aligned address A */
-#define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A)))
-
-/* Bounds on request (not chunk) sizes. */
-#define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2)
-#define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE)
-
-/* pad request bytes into a usable size */
-#define pad_request(req) \
- (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
-
-/* pad request, checking for minimum (but not maximum) */
-#define request2size(req) \
- (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req))
-
-
-/* ------------------ Operations on head and foot fields ----------------- */
-
-/*
- The head field of a chunk is or'ed with PINUSE_BIT when previous
- adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in
- use, unless mmapped, in which case both bits are cleared.
-
- FLAG4_BIT is not used by this malloc, but might be useful in extensions.
-*/
-
-#define PINUSE_BIT (SIZE_T_ONE)
-#define CINUSE_BIT (SIZE_T_TWO)
-#define FLAG4_BIT (SIZE_T_FOUR)
-#define INUSE_BITS (PINUSE_BIT|CINUSE_BIT)
-#define FLAG_BITS (PINUSE_BIT|CINUSE_BIT|FLAG4_BIT)
-
-/* Head value for fenceposts */
-#define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE)
-
-/* extraction of fields from head words */
-#define cinuse(p) ((p)->head & CINUSE_BIT)
-#define pinuse(p) ((p)->head & PINUSE_BIT)
-#define is_inuse(p) (((p)->head & INUSE_BITS) != PINUSE_BIT)
-#define is_mmapped(p) (((p)->head & INUSE_BITS) == 0)
-
-#define chunksize(p) ((p)->head & ~(FLAG_BITS))
-
-#define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT)
-
-/* Treat space at ptr +/- offset as a chunk */
-#define chunk_plus_offset(p, s) ((mchunkptr)(((char*)(p)) + (s)))
-#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s)))
-
-/* Ptr to next or previous physical malloc_chunk. */
-#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~FLAG_BITS)))
-#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) ))
-
-/* extract next chunk's pinuse bit */
-#define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT)
-
-/* Get/set size at footer */
-#define get_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot)
-#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s))
-
-/* Set size, pinuse bit, and foot */
-#define set_size_and_pinuse_of_free_chunk(p, s)\
- ((p)->head = (s|PINUSE_BIT), set_foot(p, s))
-
-/* Set size, pinuse bit, foot, and clear next pinuse */
-#define set_free_with_pinuse(p, s, n)\
- (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s))
-
-/* Get the internal overhead associated with chunk p */
-#define overhead_for(p)\
- (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD)
-
-/* Return true if malloced space is not necessarily cleared */
-#if MMAP_CLEARS
-#define calloc_must_clear(p) (!is_mmapped(p))
-#else /* MMAP_CLEARS */
-#define calloc_must_clear(p) (1)
-#endif /* MMAP_CLEARS */
-
-/* ---------------------- Overlaid data structures ----------------------- */
-
-/*
- When chunks are not in use, they are treated as nodes of either
- lists or trees.
-
- "Small" chunks are stored in circular doubly-linked lists, and look
- like this:
-
- chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Size of previous chunk |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- `head:' | Size of chunk, in bytes |P|
- mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Forward pointer to next chunk in list |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Back pointer to previous chunk in list |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Unused space (may be 0 bytes long) .
- . .
- . |
-nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- `foot:' | Size of chunk, in bytes |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- Larger chunks are kept in a form of bitwise digital trees (aka
- tries) keyed on chunksizes. Because malloc_tree_chunks are only for
- free chunks greater than 256 bytes, their size doesn't impose any
- constraints on user chunk sizes. Each node looks like:
-
- chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Size of previous chunk |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- `head:' | Size of chunk, in bytes |P|
- mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Forward pointer to next chunk of same size |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Back pointer to previous chunk of same size |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Pointer to left child (child[0]) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Pointer to right child (child[1]) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Pointer to parent |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | bin index of this chunk |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Unused space .
- . |
-nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- `foot:' | Size of chunk, in bytes |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- Each tree holding treenodes is a tree of unique chunk sizes. Chunks
- of the same size are arranged in a circularly-linked list, with only
- the oldest chunk (the next to be used, in our FIFO ordering)
- actually in the tree. (Tree members are distinguished by a non-null
- parent pointer.) If a chunk with the same size an an existing node
- is inserted, it is linked off the existing node using pointers that
- work in the same way as fd/bk pointers of small chunks.
-
- Each tree contains a power of 2 sized range of chunk sizes (the
- smallest is 0x100 <= x < 0x180), which is is divided in half at each
- tree level, with the chunks in the smaller half of the range (0x100
- <= x < 0x140 for the top nose) in the left subtree and the larger
- half (0x140 <= x < 0x180) in the right subtree. This is, of course,
- done by inspecting individual bits.
-
- Using these rules, each node's left subtree contains all smaller
- sizes than its right subtree. However, the node at the root of each
- subtree has no particular ordering relationship to either. (The
- dividing line between the subtree sizes is based on trie relation.)
- If we remove the last chunk of a given size from the interior of the
- tree, we need to replace it with a leaf node. The tree ordering
- rules permit a node to be replaced by any leaf below it.
-
- The smallest chunk in a tree (a common operation in a best-fit
- allocator) can be found by walking a path to the leftmost leaf in
- the tree. Unlike a usual binary tree, where we follow left child
- pointers until we reach a null, here we follow the right child
- pointer any time the left one is null, until we reach a leaf with
- both child pointers null. The smallest chunk in the tree will be
- somewhere along that path.
-
- The worst case number of steps to add, find, or remove a node is
- bounded by the number of bits differentiating chunks within
- bins. Under current bin calculations, this ranges from 6 up to 21
- (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case
- is of course much better.
-*/
-
-struct malloc_tree_chunk {
- /* The first four fields must be compatible with malloc_chunk */
- size_t prev_foot;
- size_t head;
- struct malloc_tree_chunk* fd;
- struct malloc_tree_chunk* bk;
-
- struct malloc_tree_chunk* child[2];
- struct malloc_tree_chunk* parent;
- bindex_t index;
-};
-
-typedef struct malloc_tree_chunk tchunk;
-typedef struct malloc_tree_chunk* tchunkptr;
-typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */
-
-/* A little helper macro for trees */
-#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1])
-
-/* ----------------------------- Segments -------------------------------- */
-
-/*
- Each malloc space may include non-contiguous segments, held in a
- list headed by an embedded malloc_segment record representing the
- top-most space. Segments also include flags holding properties of
- the space. Large chunks that are directly allocated by mmap are not
- included in this list. They are instead independently created and
- destroyed without otherwise keeping track of them.
-
- Segment management mainly comes into play for spaces allocated by
- MMAP. Any call to MMAP might or might not return memory that is
- adjacent to an existing segment. MORECORE normally contiguously
- extends the current space, so this space is almost always adjacent,
- which is simpler and faster to deal with. (This is why MORECORE is
- used preferentially to MMAP when both are available -- see
- sys_alloc.) When allocating using MMAP, we don't use any of the
- hinting mechanisms (inconsistently) supported in various
- implementations of unix mmap, or distinguish reserving from
- committing memory. Instead, we just ask for space, and exploit
- contiguity when we get it. It is probably possible to do
- better than this on some systems, but no general scheme seems
- to be significantly better.
-
- Management entails a simpler variant of the consolidation scheme
- used for chunks to reduce fragmentation -- new adjacent memory is
- normally prepended or appended to an existing segment. However,
- there are limitations compared to chunk consolidation that mostly
- reflect the fact that segment processing is relatively infrequent
- (occurring only when getting memory from system) and that we
- don't expect to have huge numbers of segments:
-
- * Segments are not indexed, so traversal requires linear scans. (It
- would be possible to index these, but is not worth the extra
- overhead and complexity for most programs on most platforms.)
- * New segments are only appended to old ones when holding top-most
- memory; if they cannot be prepended to others, they are held in
- different segments.
-
- Except for the top-most segment of an mstate, each segment record
- is kept at the tail of its segment. Segments are added by pushing
- segment records onto the list headed by &mstate.seg for the
- containing mstate.
-
- Segment flags control allocation/merge/deallocation policies:
- * If EXTERN_BIT set, then we did not allocate this segment,
- and so should not try to deallocate or merge with others.
- (This currently holds only for the initial segment passed
- into create_mspace_with_base.)
- * If USE_MMAP_BIT set, the segment may be merged with
- other surrounding mmapped segments and trimmed/de-allocated
- using munmap.
- * If neither bit is set, then the segment was obtained using
- MORECORE so can be merged with surrounding MORECORE'd segments
- and deallocated/trimmed using MORECORE with negative arguments.
-*/
-
-struct malloc_segment {
- char* base; /* base address */
- size_t size; /* allocated size */
- struct malloc_segment* next; /* ptr to next segment */
- flag_t sflags; /* mmap and extern flag */
-};
-
-#define is_mmapped_segment(S) ((S)->sflags & USE_MMAP_BIT)
-#define is_extern_segment(S) ((S)->sflags & EXTERN_BIT)
-
-typedef struct malloc_segment msegment;
-typedef struct malloc_segment* msegmentptr;
-
-/* ---------------------------- malloc_state ----------------------------- */
-
-/*
- A malloc_state holds all of the bookkeeping for a space.
- The main fields are:
-
- Top
- The topmost chunk of the currently active segment. Its size is
- cached in topsize. The actual size of topmost space is
- topsize+TOP_FOOT_SIZE, which includes space reserved for adding
- fenceposts and segment records if necessary when getting more
- space from the system. The size at which to autotrim top is
- cached from mparams in trim_check, except that it is disabled if
- an autotrim fails.
-
- Designated victim (dv)
- This is the preferred chunk for servicing small requests that
- don't have exact fits. It is normally the chunk split off most
- recently to service another small request. Its size is cached in
- dvsize. The link fields of this chunk are not maintained since it
- is not kept in a bin.
-
- SmallBins
- An array of bin headers for free chunks. These bins hold chunks
- with sizes less than MIN_LARGE_SIZE bytes. Each bin contains
- chunks of all the same size, spaced 8 bytes apart. To simplify
- use in double-linked lists, each bin header acts as a malloc_chunk
- pointing to the real first node, if it exists (else pointing to
- itself). This avoids special-casing for headers. But to avoid
- waste, we allocate only the fd/bk pointers of bins, and then use
- repositioning tricks to treat these as the fields of a chunk.
-
- TreeBins
- Treebins are pointers to the roots of trees holding a range of
- sizes. There are 2 equally spaced treebins for each power of two
- from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything
- larger.
-
- Bin maps
- There is one bit map for small bins ("smallmap") and one for
- treebins ("treemap). Each bin sets its bit when non-empty, and
- clears the bit when empty. Bit operations are then used to avoid
- bin-by-bin searching -- nearly all "search" is done without ever
- looking at bins that won't be selected. The bit maps
- conservatively use 32 bits per map word, even if on 64bit system.
- For a good description of some of the bit-based techniques used
- here, see Henry S. Warren Jr's book "Hacker's Delight" (and
- supplement at http://hackersdelight.org/). Many of these are
- intended to reduce the branchiness of paths through malloc etc, as
- well as to reduce the number of memory locations read or written.
-
- Segments
- A list of segments headed by an embedded malloc_segment record
- representing the initial space.
-
- Address check support
- The least_addr field is the least address ever obtained from
- MORECORE or MMAP. Attempted frees and reallocs of any address less
- than this are trapped (unless INSECURE is defined).
-
- Magic tag
- A cross-check field that should always hold same value as mparams.magic.
-
- Flags
- Bits recording whether to use MMAP, locks, or contiguous MORECORE
-
- Statistics
- Each space keeps track of current and maximum system memory
- obtained via MORECORE or MMAP.
-
- Trim support
- Fields holding the amount of unused topmost memory that should trigger
- timming, and a counter to force periodic scanning to release unused
- non-topmost segments.
-
- Locking
- If USE_LOCKS is defined, the "mutex" lock is acquired and released
- around every public call using this mspace.
-
- Extension support
- A void* pointer and a size_t field that can be used to help implement
- extensions to this malloc.
-*/
-
-/* Bin types, widths and sizes */
-#define NSMALLBINS (32U)
-#define NTREEBINS (32U)
-#define SMALLBIN_SHIFT (3U)
-#define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT)
-#define TREEBIN_SHIFT (8U)
-#define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT)
-#define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE)
-#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD)
-
-struct malloc_state {
- binmap_t smallmap;
- binmap_t treemap;
- size_t dvsize;
- size_t topsize;
- char* least_addr;
- mchunkptr dv;
- mchunkptr top;
- size_t trim_check;
- size_t release_checks;
- size_t magic;
- mchunkptr smallbins[(NSMALLBINS+1)*2];
- tbinptr treebins[NTREEBINS];
- size_t footprint;
- size_t max_footprint;
- flag_t mflags;
-#if USE_LOCKS
- MLOCK_T mutex; /* locate lock among fields that rarely change */
-#endif /* USE_LOCKS */
- msegment seg;
- void* extp; /* Unused but available for extensions */
- size_t exts;
-};
-
-typedef struct malloc_state* mstate;
-
-/* ------------- Global malloc_state and malloc_params ------------------- */
-
-/*
- malloc_params holds global properties, including those that can be
- dynamically set using mallopt. There is a single instance, mparams,
- initialized in init_mparams. Note that the non-zeroness of "magic"
- also serves as an initialization flag.
-*/
-
-struct malloc_params {
- volatile size_t magic;
- size_t page_size;
- size_t granularity;
- size_t mmap_threshold;
- size_t trim_threshold;
- flag_t default_mflags;
-};
-
-static struct malloc_params mparams;
-
-/* Ensure mparams initialized */
-#define ensure_initialization() (void)(mparams.magic != 0 || init_mparams())
-
-#if !ONLY_MSPACES
-
-/* The global malloc_state used for all non-"mspace" calls */
-static struct malloc_state _gm_;
-#define gm (&_gm_)
-#define is_global(M) ((M) == &_gm_)
-
-#endif /* !ONLY_MSPACES */
-
-#define is_initialized(M) ((M)->top != 0)
-
-/* -------------------------- system alloc setup ------------------------- */
-
-/* Operations on mflags */
-
-#define use_lock(M) ((M)->mflags & USE_LOCK_BIT)
-#define enable_lock(M) ((M)->mflags |= USE_LOCK_BIT)
-#define disable_lock(M) ((M)->mflags &= ~USE_LOCK_BIT)
-
-#define use_mmap(M) ((M)->mflags & USE_MMAP_BIT)
-#define enable_mmap(M) ((M)->mflags |= USE_MMAP_BIT)
-#define disable_mmap(M) ((M)->mflags &= ~USE_MMAP_BIT)
-
-#define use_noncontiguous(M) ((M)->mflags & USE_NONCONTIGUOUS_BIT)
-#define disable_contiguous(M) ((M)->mflags |= USE_NONCONTIGUOUS_BIT)
-
-#define set_lock(M,L)\
- ((M)->mflags = (L)?\
- ((M)->mflags | USE_LOCK_BIT) :\
- ((M)->mflags & ~USE_LOCK_BIT))
-
-/* page-align a size */
-#define page_align(S)\
- (((S) + (mparams.page_size - SIZE_T_ONE)) & ~(mparams.page_size - SIZE_T_ONE))
-
-/* granularity-align a size */
-#define granularity_align(S)\
- (((S) + (mparams.granularity - SIZE_T_ONE))\
- & ~(mparams.granularity - SIZE_T_ONE))
-
-
-/* For mmap, use granularity alignment on windows, else page-align */
-#ifdef WIN32
-#define mmap_align(S) granularity_align(S)
-#else
-#define mmap_align(S) page_align(S)
-#endif
-
-/* For sys_alloc, enough padding to ensure can malloc request on success */
-#define SYS_ALLOC_PADDING (TOP_FOOT_SIZE + MALLOC_ALIGNMENT)
-
-#define is_page_aligned(S)\
- (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0)
-#define is_granularity_aligned(S)\
- (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0)
-
-/* True if segment S holds address A */
-#define segment_holds(S, A)\
- ((char*)(A) >= S->base && (char*)(A) < S->base + S->size)
-
-/* Return segment holding given address */
-static msegmentptr segment_holding(mstate m, char* addr) {
- msegmentptr sp = &m->seg;
- for (;;) {
- if (addr >= sp->base && addr < sp->base + sp->size)
- return sp;
- if ((sp = sp->next) == 0)
- return 0;
- }
-}
-
-/* Return true if segment contains a segment link */
-static int has_segment_link(mstate m, msegmentptr ss) {
- msegmentptr sp = &m->seg;
- for (;;) {
- if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size)
- return 1;
- if ((sp = sp->next) == 0)
- return 0;
- }
-}
-
-#ifndef MORECORE_CANNOT_TRIM
-#define should_trim(M,s) ((s) > (M)->trim_check)
-#else /* MORECORE_CANNOT_TRIM */
-#define should_trim(M,s) (0)
-#endif /* MORECORE_CANNOT_TRIM */
-
-/*
- TOP_FOOT_SIZE is padding at the end of a segment, including space
- that may be needed to place segment records and fenceposts when new
- noncontiguous segments are added.
-*/
-#define TOP_FOOT_SIZE\
- (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE)
-
-
-/* ------------------------------- Hooks -------------------------------- */
-
-/*
- PREACTION should be defined to return 0 on success, and nonzero on
- failure. If you are not using locking, you can redefine these to do
- anything you like.
-*/
-
-#if USE_LOCKS
-
-#define PREACTION(M) ((use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0)
-#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); }
-#else /* USE_LOCKS */
-
-#ifndef PREACTION
-#define PREACTION(M) (0)
-#endif /* PREACTION */
-
-#ifndef POSTACTION
-#define POSTACTION(M)
-#endif /* POSTACTION */
-
-#endif /* USE_LOCKS */
-
-/*
- CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses.
- USAGE_ERROR_ACTION is triggered on detected bad frees and
- reallocs. The argument p is an address that might have triggered the
- fault. It is ignored by the two predefined actions, but might be
- useful in custom actions that try to help diagnose errors.
-*/
-
-#if PROCEED_ON_ERROR
-
-/* A count of the number of corruption errors causing resets */
-int malloc_corruption_error_count;
-
-/* default corruption action */
-static void reset_on_error(mstate m);
-
-#define CORRUPTION_ERROR_ACTION(m) reset_on_error(m)
-#define USAGE_ERROR_ACTION(m, p)
-
-#else /* PROCEED_ON_ERROR */
-
-#ifndef CORRUPTION_ERROR_ACTION
-#define CORRUPTION_ERROR_ACTION(m) ABORT
-#endif /* CORRUPTION_ERROR_ACTION */
-
-#ifndef USAGE_ERROR_ACTION
-#define USAGE_ERROR_ACTION(m,p) ABORT
-#endif /* USAGE_ERROR_ACTION */
-
-#endif /* PROCEED_ON_ERROR */
-
-/* -------------------------- Debugging setup ---------------------------- */
-
-#if ! DEBUG
-
-#define check_free_chunk(M,P)
-#define check_inuse_chunk(M,P)
-#define check_malloced_chunk(M,P,N)
-#define check_mmapped_chunk(M,P)
-#define check_malloc_state(M)
-#define check_top_chunk(M,P)
-
-#else /* DEBUG */
-#define check_free_chunk(M,P) do_check_free_chunk(M,P)
-#define check_inuse_chunk(M,P) do_check_inuse_chunk(M,P)
-#define check_top_chunk(M,P) do_check_top_chunk(M,P)
-#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N)
-#define check_mmapped_chunk(M,P) do_check_mmapped_chunk(M,P)
-#define check_malloc_state(M) do_check_malloc_state(M)
-
-static void do_check_any_chunk(mstate m, mchunkptr p);
-static void do_check_top_chunk(mstate m, mchunkptr p);
-static void do_check_mmapped_chunk(mstate m, mchunkptr p);
-static void do_check_inuse_chunk(mstate m, mchunkptr p);
-static void do_check_free_chunk(mstate m, mchunkptr p);
-static void do_check_malloced_chunk(mstate m, void* mem, size_t s);
-static void do_check_tree(mstate m, tchunkptr t);
-static void do_check_treebin(mstate m, bindex_t i);
-static void do_check_smallbin(mstate m, bindex_t i);
-static void do_check_malloc_state(mstate m);
-static int bin_find(mstate m, mchunkptr x);
-static size_t traverse_and_check(mstate m);
-#endif /* DEBUG */
-
-/* ---------------------------- Indexing Bins ---------------------------- */
-
-#define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS)
-#define small_index(s) ((s) >> SMALLBIN_SHIFT)
-#define small_index2size(i) ((i) << SMALLBIN_SHIFT)
-#define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE))
-
-/* addressing by index. See above about smallbin repositioning */
-#define smallbin_at(M, i) ((sbinptr)((char*)&((M)->smallbins[(i)<<1])))
-#define treebin_at(M,i) (&((M)->treebins[i]))
-
-/* assign tree index for size S to variable I. Use x86 asm if possible */
-#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
-#define compute_tree_index(S, I)\
-{\
- unsigned int X = S >> TREEBIN_SHIFT;\
- if (X == 0)\
- I = 0;\
- else if (X > 0xFFFF)\
- I = NTREEBINS-1;\
- else {\
- unsigned int K;\
- __asm__("bsrl\t%1, %0\n\t" : "=r" (K) : "g" (X));\
- I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
- }\
-}
-
-#elif defined (__INTEL_COMPILER)
-#define compute_tree_index(S, I)\
-{\
- size_t X = S >> TREEBIN_SHIFT;\
- if (X == 0)\
- I = 0;\
- else if (X > 0xFFFF)\
- I = NTREEBINS-1;\
- else {\
- unsigned int K = _bit_scan_reverse (X); \
- I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
- }\
-}
-
-#elif defined(_MSC_VER) && _MSC_VER>=1300
-#define compute_tree_index(S, I)\
-{\
- size_t X = S >> TREEBIN_SHIFT;\
- if (X == 0)\
- I = 0;\
- else if (X > 0xFFFF)\
- I = NTREEBINS-1;\
- else {\
- unsigned int K;\
- _BitScanReverse((DWORD *) &K, X);\
- I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
- }\
-}
-
-#else /* GNUC */
-#define compute_tree_index(S, I)\
-{\
- size_t X = S >> TREEBIN_SHIFT;\
- if (X == 0)\
- I = 0;\
- else if (X > 0xFFFF)\
- I = NTREEBINS-1;\
- else {\
- unsigned int Y = (unsigned int)X;\
- unsigned int N = ((Y - 0x100) >> 16) & 8;\
- unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\
- N += K;\
- N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\
- K = 14 - N + ((Y <<= K) >> 15);\
- I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\
- }\
-}
-#endif /* GNUC */
-
-/* Bit representing maximum resolved size in a treebin at i */
-#define bit_for_tree_index(i) \
- (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2)
-
-/* Shift placing maximum resolved bit in a treebin at i as sign bit */
-#define leftshift_for_tree_index(i) \
- ((i == NTREEBINS-1)? 0 : \
- ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2)))
-
-/* The size of the smallest chunk held in bin with index i */
-#define minsize_for_tree_index(i) \
- ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \
- (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1)))
-
-
-/* ------------------------ Operations on bin maps ----------------------- */
-
-/* bit corresponding to given index */
-#define idx2bit(i) ((binmap_t)(1) << (i))
-
-/* Mark/Clear bits with given index */
-#define mark_smallmap(M,i) ((M)->smallmap |= idx2bit(i))
-#define clear_smallmap(M,i) ((M)->smallmap &= ~idx2bit(i))
-#define smallmap_is_marked(M,i) ((M)->smallmap & idx2bit(i))
-
-#define mark_treemap(M,i) ((M)->treemap |= idx2bit(i))
-#define clear_treemap(M,i) ((M)->treemap &= ~idx2bit(i))
-#define treemap_is_marked(M,i) ((M)->treemap & idx2bit(i))
-
-/* isolate the least set bit of a bitmap */
-#define least_bit(x) ((x) & -(x))
-
-/* mask with all bits to left of least bit of x on */
-#define left_bits(x) ((x<<1) | -(x<<1))
-
-/* mask with all bits to left of or equal to least bit of x on */
-#define same_or_left_bits(x) ((x) | -(x))
-
-/* index corresponding to given bit. Use x86 asm if possible */
-
-#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
-#define compute_bit2idx(X, I)\
-{\
- unsigned int J;\
- __asm__("bsfl\t%1, %0\n\t" : "=r" (J) : "g" (X));\
- I = (bindex_t)J;\
-}
-
-#elif defined (__INTEL_COMPILER)
-#define compute_bit2idx(X, I)\
-{\
- unsigned int J;\
- J = _bit_scan_forward (X); \
- I = (bindex_t)J;\
-}
-
-#elif defined(_MSC_VER) && _MSC_VER>=1300
-#define compute_bit2idx(X, I)\
-{\
- unsigned int J;\
- _BitScanForward((DWORD *) &J, X);\
- I = (bindex_t)J;\
-}
-
-#elif USE_BUILTIN_FFS
-#define compute_bit2idx(X, I) I = ffs(X)-1
-
-#else
-#define compute_bit2idx(X, I)\
-{\
- unsigned int Y = X - 1;\
- unsigned int K = Y >> (16-4) & 16;\
- unsigned int N = K; Y >>= K;\
- N += K = Y >> (8-3) & 8; Y >>= K;\
- N += K = Y >> (4-2) & 4; Y >>= K;\
- N += K = Y >> (2-1) & 2; Y >>= K;\
- N += K = Y >> (1-0) & 1; Y >>= K;\
- I = (bindex_t)(N + Y);\
-}
-#endif /* GNUC */
-
-
-/* ----------------------- Runtime Check Support ------------------------- */
-
-/*
- For security, the main invariant is that malloc/free/etc never
- writes to a static address other than malloc_state, unless static
- malloc_state itself has been corrupted, which cannot occur via
- malloc (because of these checks). In essence this means that we
- believe all pointers, sizes, maps etc held in malloc_state, but
- check all of those linked or offsetted from other embedded data
- structures. These checks are interspersed with main code in a way
- that tends to minimize their run-time cost.
-
- When FOOTERS is defined, in addition to range checking, we also
- verify footer fields of inuse chunks, which can be used guarantee
- that the mstate controlling malloc/free is intact. This is a
- streamlined version of the approach described by William Robertson
- et al in "Run-time Detection of Heap-based Overflows" LISA'03
- http://www.usenix.org/events/lisa03/tech/robertson.html The footer
- of an inuse chunk holds the xor of its mstate and a random seed,
- that is checked upon calls to free() and realloc(). This is
- (probablistically) unguessable from outside the program, but can be
- computed by any code successfully malloc'ing any chunk, so does not
- itself provide protection against code that has already broken
- security through some other means. Unlike Robertson et al, we
- always dynamically check addresses of all offset chunks (previous,
- next, etc). This turns out to be cheaper than relying on hashes.
-*/
-
-#if !INSECURE
-/* Check if address a is at least as high as any from MORECORE or MMAP */
-#define ok_address(M, a) ((char*)(a) >= (M)->least_addr)
-/* Check if address of next chunk n is higher than base chunk p */
-#define ok_next(p, n) ((char*)(p) < (char*)(n))
-/* Check if p has inuse status */
-#define ok_inuse(p) is_inuse(p)
-/* Check if p has its pinuse bit on */
-#define ok_pinuse(p) pinuse(p)
-
-#else /* !INSECURE */
-#define ok_address(M, a) (1)
-#define ok_next(b, n) (1)
-#define ok_inuse(p) (1)
-#define ok_pinuse(p) (1)
-#endif /* !INSECURE */
-
-#if (FOOTERS && !INSECURE)
-/* Check if (alleged) mstate m has expected magic field */
-#define ok_magic(M) ((M)->magic == mparams.magic)
-#else /* (FOOTERS && !INSECURE) */
-#define ok_magic(M) (1)
-#endif /* (FOOTERS && !INSECURE) */
-
-
-/* In gcc, use __builtin_expect to minimize impact of checks */
-#if !INSECURE
-#if defined(__GNUC__) && __GNUC__ >= 3
-#define RTCHECK(e) __builtin_expect(e, 1)
-#else /* GNUC */
-#define RTCHECK(e) (e)
-#endif /* GNUC */
-#else /* !INSECURE */
-#define RTCHECK(e) (1)
-#endif /* !INSECURE */
-
-/* macros to set up inuse chunks with or without footers */
-
-#if !FOOTERS
-
-#define mark_inuse_foot(M,p,s)
-
-/* Macros for setting head/foot of non-mmapped chunks */
-
-/* Set cinuse bit and pinuse bit of next chunk */
-#define set_inuse(M,p,s)\
- ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
- ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
-
-/* Set cinuse and pinuse of this chunk and pinuse of next chunk */
-#define set_inuse_and_pinuse(M,p,s)\
- ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
- ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
-
-/* Set size, cinuse and pinuse bit of this chunk */
-#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
- ((p)->head = (s|PINUSE_BIT|CINUSE_BIT))
-
-#else /* FOOTERS */
-
-/* Set foot of inuse chunk to be xor of mstate and seed */
-#define mark_inuse_foot(M,p,s)\
- (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic))
-
-#define get_mstate_for(p)\
- ((mstate)(((mchunkptr)((char*)(p) +\
- (chunksize(p))))->prev_foot ^ mparams.magic))
-
-#define set_inuse(M,p,s)\
- ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
- (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \
- mark_inuse_foot(M,p,s))
-
-#define set_inuse_and_pinuse(M,p,s)\
- ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
- (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\
- mark_inuse_foot(M,p,s))
-
-#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
- ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
- mark_inuse_foot(M, p, s))
-
-#endif /* !FOOTERS */
-
-/* ---------------------------- setting mparams -------------------------- */
-
-/* Initialize mparams */
-static int init_mparams(void) {
-#ifdef NEED_GLOBAL_LOCK_INIT
- if (malloc_global_mutex_status <= 0)
- init_malloc_global_mutex();
-#endif
-
- ACQUIRE_MALLOC_GLOBAL_LOCK();
- if (mparams.magic == 0) {
- size_t magic;
- size_t psize;
- size_t gsize;
-
-#ifndef WIN32
- psize = malloc_getpagesize;
- gsize = ((DEFAULT_GRANULARITY != 0)? DEFAULT_GRANULARITY : psize);
-#else /* WIN32 */
- {
- SYSTEM_INFO system_info;
- GetSystemInfo(&system_info);
- psize = system_info.dwPageSize;
- gsize = ((DEFAULT_GRANULARITY != 0)?
- DEFAULT_GRANULARITY : system_info.dwAllocationGranularity);
- }
-#endif /* WIN32 */
-
- /* Sanity-check configuration:
- size_t must be unsigned and as wide as pointer type.
- ints must be at least 4 bytes.
- alignment must be at least 8.
- Alignment, min chunk size, and page size must all be powers of 2.
- */
- if ((sizeof(size_t) != sizeof(char*)) ||
- (MAX_SIZE_T < MIN_CHUNK_SIZE) ||
- (sizeof(int) < 4) ||
- (MALLOC_ALIGNMENT < (size_t)8U) ||
- ((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-SIZE_T_ONE)) != 0) ||
- ((MCHUNK_SIZE & (MCHUNK_SIZE-SIZE_T_ONE)) != 0) ||
- ((gsize & (gsize-SIZE_T_ONE)) != 0) ||
- ((psize & (psize-SIZE_T_ONE)) != 0))
- ABORT;
-
- mparams.granularity = gsize;
- mparams.page_size = psize;
- mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD;
- mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD;
-#if MORECORE_CONTIGUOUS
- mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT;
-#else /* MORECORE_CONTIGUOUS */
- mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT;
-#endif /* MORECORE_CONTIGUOUS */
-
-#if !ONLY_MSPACES
- /* Set up lock for main malloc area */
- gm->mflags = mparams.default_mflags;
- INITIAL_LOCK(&gm->mutex);
-#endif
-
- {
-#if USE_DEV_RANDOM
- int fd;
- unsigned char buf[sizeof(size_t)];
- /* Try to use /dev/urandom, else fall back on using time */
- if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 &&
- read(fd, buf, sizeof(buf)) == sizeof(buf)) {
- magic = *((size_t *) buf);
- close(fd);
- }
- else
-#endif /* USE_DEV_RANDOM */
-#ifdef WIN32
- magic = (size_t)(GetTickCount() ^ (size_t)0x55555555U);
-#else
- magic = (size_t)(time(0) ^ (size_t)0x55555555U);
-#endif
- magic |= (size_t)8U; /* ensure nonzero */
- magic &= ~(size_t)7U; /* improve chances of fault for bad values */
- mparams.magic = magic;
- }
- }
-
- RELEASE_MALLOC_GLOBAL_LOCK();
- return 1;
-}
-
-/* support for mallopt */
-static int change_mparam(int param_number, int value) {
- size_t val;
- ensure_initialization();
- val = (value == -1)? MAX_SIZE_T : (size_t)value;
- switch(param_number) {
- case M_TRIM_THRESHOLD:
- mparams.trim_threshold = val;
- return 1;
- case M_GRANULARITY:
- if (val >= mparams.page_size && ((val & (val-1)) == 0)) {
- mparams.granularity = val;
- return 1;
- }
- else
- return 0;
- case M_MMAP_THRESHOLD:
- mparams.mmap_threshold = val;
- return 1;
- default:
- return 0;
- }
-}
-
-#if DEBUG
-/* ------------------------- Debugging Support --------------------------- */
-
-/* Check properties of any chunk, whether free, inuse, mmapped etc */
-static void do_check_any_chunk(mstate m, mchunkptr p) {
- assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
- assert(ok_address(m, p));
-}
-
-/* Check properties of top chunk */
-static void do_check_top_chunk(mstate m, mchunkptr p) {
- msegmentptr sp = segment_holding(m, (char*)p);
- size_t sz = p->head & ~INUSE_BITS; /* third-lowest bit can be set! */
- assert(sp != 0);
- assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
- assert(ok_address(m, p));
- assert(sz == m->topsize);
- assert(sz > 0);
- assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE);
- assert(pinuse(p));
- assert(!pinuse(chunk_plus_offset(p, sz)));
-}
-
-/* Check properties of (inuse) mmapped chunks */
-static void do_check_mmapped_chunk(mstate m, mchunkptr p) {
- size_t sz = chunksize(p);
- size_t len = (sz + (p->prev_foot) + MMAP_FOOT_PAD);
- assert(is_mmapped(p));
- assert(use_mmap(m));
- assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
- assert(ok_address(m, p));
- assert(!is_small(sz));
- assert((len & (mparams.page_size-SIZE_T_ONE)) == 0);
- assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD);
- assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0);
-}
-
-/* Check properties of inuse chunks */
-static void do_check_inuse_chunk(mstate m, mchunkptr p) {
- do_check_any_chunk(m, p);
- assert(is_inuse(p));
- assert(next_pinuse(p));
- /* If not pinuse and not mmapped, previous chunk has OK offset */
- assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p);
- if (is_mmapped(p))
- do_check_mmapped_chunk(m, p);
-}
-
-/* Check properties of free chunks */
-static void do_check_free_chunk(mstate m, mchunkptr p) {
- size_t sz = chunksize(p);
- mchunkptr next = chunk_plus_offset(p, sz);
- do_check_any_chunk(m, p);
- assert(!is_inuse(p));
- assert(!next_pinuse(p));
- assert (!is_mmapped(p));
- if (p != m->dv && p != m->top) {
- if (sz >= MIN_CHUNK_SIZE) {
- assert((sz & CHUNK_ALIGN_MASK) == 0);
- assert(is_aligned(chunk2mem(p)));
- assert(next->prev_foot == sz);
- assert(pinuse(p));
- assert (next == m->top || is_inuse(next));
- assert(p->fd->bk == p);
- assert(p->bk->fd == p);
- }
- else /* markers are always of size SIZE_T_SIZE */
- assert(sz == SIZE_T_SIZE);
- }
-}
-
-/* Check properties of malloced chunks at the point they are malloced */
-static void do_check_malloced_chunk(mstate m, void* mem, size_t s) {
- if (mem != 0) {
- mchunkptr p = mem2chunk(mem);
- size_t sz = p->head & ~INUSE_BITS;
- do_check_inuse_chunk(m, p);
- assert((sz & CHUNK_ALIGN_MASK) == 0);
- assert(sz >= MIN_CHUNK_SIZE);
- assert(sz >= s);
- /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */
- assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE));
- }
-}
-
-/* Check a tree and its subtrees. */
-static void do_check_tree(mstate m, tchunkptr t) {
- tchunkptr head = 0;
- tchunkptr u = t;
- bindex_t tindex = t->index;
- size_t tsize = chunksize(t);
- bindex_t idx;
- compute_tree_index(tsize, idx);
- assert(tindex == idx);
- assert(tsize >= MIN_LARGE_SIZE);
- assert(tsize >= minsize_for_tree_index(idx));
- assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1))));
-
- do { /* traverse through chain of same-sized nodes */
- do_check_any_chunk(m, ((mchunkptr)u));
- assert(u->index == tindex);
- assert(chunksize(u) == tsize);
- assert(!is_inuse(u));
- assert(!next_pinuse(u));
- assert(u->fd->bk == u);
- assert(u->bk->fd == u);
- if (u->parent == 0) {
- assert(u->child[0] == 0);
- assert(u->child[1] == 0);
- }
- else {
- assert(head == 0); /* only one node on chain has parent */
- head = u;
- assert(u->parent != u);
- assert (u->parent->child[0] == u ||
- u->parent->child[1] == u ||
- *((tbinptr*)(u->parent)) == u);
- if (u->child[0] != 0) {
- assert(u->child[0]->parent == u);
- assert(u->child[0] != u);
- do_check_tree(m, u->child[0]);
- }
- if (u->child[1] != 0) {
- assert(u->child[1]->parent == u);
- assert(u->child[1] != u);
- do_check_tree(m, u->child[1]);
- }
- if (u->child[0] != 0 && u->child[1] != 0) {
- assert(chunksize(u->child[0]) < chunksize(u->child[1]));
- }
- }
- u = u->fd;
- } while (u != t);
- assert(head != 0);
-}
-
-/* Check all the chunks in a treebin. */
-static void do_check_treebin(mstate m, bindex_t i) {
- tbinptr* tb = treebin_at(m, i);
- tchunkptr t = *tb;
- int empty = (m->treemap & (1U << i)) == 0;
- if (t == 0)
- assert(empty);
- if (!empty)
- do_check_tree(m, t);
-}
-
-/* Check all the chunks in a smallbin. */
-static void do_check_smallbin(mstate m, bindex_t i) {
- sbinptr b = smallbin_at(m, i);
- mchunkptr p = b->bk;
- unsigned int empty = (m->smallmap & (1U << i)) == 0;
- if (p == b)
- assert(empty);
- if (!empty) {
- for (; p != b; p = p->bk) {
- size_t size = chunksize(p);
- mchunkptr q;
- /* each chunk claims to be free */
- do_check_free_chunk(m, p);
- /* chunk belongs in bin */
- assert(small_index(size) == i);
- assert(p->bk == b || chunksize(p->bk) == chunksize(p));
- /* chunk is followed by an inuse chunk */
- q = next_chunk(p);
- if (q->head != FENCEPOST_HEAD)
- do_check_inuse_chunk(m, q);
- }
- }
-}
-
-/* Find x in a bin. Used in other check functions. */
-static int bin_find(mstate m, mchunkptr x) {
- size_t size = chunksize(x);
- if (is_small(size)) {
- bindex_t sidx = small_index(size);
- sbinptr b = smallbin_at(m, sidx);
- if (smallmap_is_marked(m, sidx)) {
- mchunkptr p = b;
- do {
- if (p == x)
- return 1;
- } while ((p = p->fd) != b);
- }
- }
- else {
- bindex_t tidx;
- compute_tree_index(size, tidx);
- if (treemap_is_marked(m, tidx)) {
- tchunkptr t = *treebin_at(m, tidx);
- size_t sizebits = size << leftshift_for_tree_index(tidx);
- while (t != 0 && chunksize(t) != size) {
- t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
- sizebits <<= 1;
- }
- if (t != 0) {
- tchunkptr u = t;
- do {
- if (u == (tchunkptr)x)
- return 1;
- } while ((u = u->fd) != t);
- }
- }
- }
- return 0;
-}
-
-/* Traverse each chunk and check it; return total */
-static size_t traverse_and_check(mstate m) {
- size_t sum = 0;
- if (is_initialized(m)) {
- msegmentptr s = &m->seg;
- sum += m->topsize + TOP_FOOT_SIZE;
- while (s != 0) {
- mchunkptr q = align_as_chunk(s->base);
- mchunkptr lastq = 0;
- assert(pinuse(q));
- while (segment_holds(s, q) &&
- q != m->top && q->head != FENCEPOST_HEAD) {
- sum += chunksize(q);
- if (is_inuse(q)) {
- assert(!bin_find(m, q));
- do_check_inuse_chunk(m, q);
- }
- else {
- assert(q == m->dv || bin_find(m, q));
- assert(lastq == 0 || is_inuse(lastq)); /* Not 2 consecutive free */
- do_check_free_chunk(m, q);
- }
- lastq = q;
- q = next_chunk(q);
- }
- s = s->next;
- }
- }
- return sum;
-}
-
-/* Check all properties of malloc_state. */
-static void do_check_malloc_state(mstate m) {
- bindex_t i;
- size_t total;
- /* check bins */
- for (i = 0; i < NSMALLBINS; ++i)
- do_check_smallbin(m, i);
- for (i = 0; i < NTREEBINS; ++i)
- do_check_treebin(m, i);
-
- if (m->dvsize != 0) { /* check dv chunk */
- do_check_any_chunk(m, m->dv);
- assert(m->dvsize == chunksize(m->dv));
- assert(m->dvsize >= MIN_CHUNK_SIZE);
- assert(bin_find(m, m->dv) == 0);
- }
-
- if (m->top != 0) { /* check top chunk */
- do_check_top_chunk(m, m->top);
- /*assert(m->topsize == chunksize(m->top)); redundant */
- assert(m->topsize > 0);
- assert(bin_find(m, m->top) == 0);
- }
-
- total = traverse_and_check(m);
- assert(total <= m->footprint);
- assert(m->footprint <= m->max_footprint);
-}
-#endif /* DEBUG */
-
-/* ----------------------------- statistics ------------------------------ */
-
-#if !NO_MALLINFO
-static struct mallinfo internal_mallinfo(mstate m) {
- struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- ensure_initialization();
- if (!PREACTION(m)) {
- check_malloc_state(m);
- if (is_initialized(m)) {
- size_t nfree = SIZE_T_ONE; /* top always free */
- size_t mfree = m->topsize + TOP_FOOT_SIZE;
- size_t sum = mfree;
- msegmentptr s = &m->seg;
- while (s != 0) {
- mchunkptr q = align_as_chunk(s->base);
- while (segment_holds(s, q) &&
- q != m->top && q->head != FENCEPOST_HEAD) {
- size_t sz = chunksize(q);
- sum += sz;
- if (!is_inuse(q)) {
- mfree += sz;
- ++nfree;
- }
- q = next_chunk(q);
- }
- s = s->next;
- }
-
- nm.arena = sum;
- nm.ordblks = nfree;
- nm.hblkhd = m->footprint - sum;
- nm.usmblks = m->max_footprint;
- nm.uordblks = m->footprint - mfree;
- nm.fordblks = mfree;
- nm.keepcost = m->topsize;
- }
-
- POSTACTION(m);
- }
- return nm;
-}
-#endif /* !NO_MALLINFO */
-
-static void internal_malloc_stats(mstate m) {
- ensure_initialization();
- if (!PREACTION(m)) {
- size_t maxfp = 0;
- size_t fp = 0;
- size_t used = 0;
- check_malloc_state(m);
- if (is_initialized(m)) {
- msegmentptr s = &m->seg;
- maxfp = m->max_footprint;
- fp = m->footprint;
- used = fp - (m->topsize + TOP_FOOT_SIZE);
-
- while (s != 0) {
- mchunkptr q = align_as_chunk(s->base);
- while (segment_holds(s, q) &&
- q != m->top && q->head != FENCEPOST_HEAD) {
- if (!is_inuse(q))
- used -= chunksize(q);
- q = next_chunk(q);
- }
- s = s->next;
- }
- }
-
- fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp));
- fprintf(stderr, "system bytes = %10lu\n", (unsigned long)(fp));
- fprintf(stderr, "in use bytes = %10lu\n", (unsigned long)(used));
-
- POSTACTION(m);
- }
-}
-
-/* ----------------------- Operations on smallbins ----------------------- */
-
-/*
- Various forms of linking and unlinking are defined as macros. Even
- the ones for trees, which are very long but have very short typical
- paths. This is ugly but reduces reliance on inlining support of
- compilers.
-*/
-
-/* Link a free chunk into a smallbin */
-#define insert_small_chunk(M, P, S) {\
- bindex_t I = small_index(S);\
- mchunkptr B = smallbin_at(M, I);\
- mchunkptr F = B;\
- assert(S >= MIN_CHUNK_SIZE);\
- if (!smallmap_is_marked(M, I))\
- mark_smallmap(M, I);\
- else if (RTCHECK(ok_address(M, B->fd)))\
- F = B->fd;\
- else {\
- CORRUPTION_ERROR_ACTION(M);\
- }\
- B->fd = P;\
- F->bk = P;\
- P->fd = F;\
- P->bk = B;\
-}
-
-/* Unlink a chunk from a smallbin */
-#define unlink_small_chunk(M, P, S) {\
- mchunkptr F = P->fd;\
- mchunkptr B = P->bk;\
- bindex_t I = small_index(S);\
- assert(P != B);\
- assert(P != F);\
- assert(chunksize(P) == small_index2size(I));\
- if (F == B)\
- clear_smallmap(M, I);\
- else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\
- (B == smallbin_at(M,I) || ok_address(M, B)))) {\
- F->bk = B;\
- B->fd = F;\
- }\
- else {\
- CORRUPTION_ERROR_ACTION(M);\
- }\
-}
-
-/* Unlink the first chunk from a smallbin */
-#define unlink_first_small_chunk(M, B, P, I) {\
- mchunkptr F = P->fd;\
- assert(P != B);\
- assert(P != F);\
- assert(chunksize(P) == small_index2size(I));\
- if (B == F)\
- clear_smallmap(M, I);\
- else if (RTCHECK(ok_address(M, F))) {\
- B->fd = F;\
- F->bk = B;\
- }\
- else {\
- CORRUPTION_ERROR_ACTION(M);\
- }\
-}
-
-
-
-/* Replace dv node, binning the old one */
-/* Used only when dvsize known to be small */
-#define replace_dv(M, P, S) {\
- size_t DVS = M->dvsize;\
- if (DVS != 0) {\
- mchunkptr DV = M->dv;\
- assert(is_small(DVS));\
- insert_small_chunk(M, DV, DVS);\
- }\
- M->dvsize = S;\
- M->dv = P;\
-}
-
-/* ------------------------- Operations on trees ------------------------- */
-
-/* Insert chunk into tree */
-#define insert_large_chunk(M, X, S) {\
- tbinptr* H;\
- bindex_t I;\
- compute_tree_index(S, I);\
- H = treebin_at(M, I);\
- X->index = I;\
- X->child[0] = X->child[1] = 0;\
- if (!treemap_is_marked(M, I)) {\
- mark_treemap(M, I);\
- *H = X;\
- X->parent = (tchunkptr)H;\
- X->fd = X->bk = X;\
- }\
- else {\
- tchunkptr T = *H;\
- size_t K = S << leftshift_for_tree_index(I);\
- for (;;) {\
- if (chunksize(T) != S) {\
- tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\
- K <<= 1;\
- if (*C != 0)\
- T = *C;\
- else if (RTCHECK(ok_address(M, C))) {\
- *C = X;\
- X->parent = T;\
- X->fd = X->bk = X;\
- break;\
- }\
- else {\
- CORRUPTION_ERROR_ACTION(M);\
- break;\
- }\
- }\
- else {\
- tchunkptr F = T->fd;\
- if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\
- T->fd = F->bk = X;\
- X->fd = F;\
- X->bk = T;\
- X->parent = 0;\
- break;\
- }\
- else {\
- CORRUPTION_ERROR_ACTION(M);\
- break;\
- }\
- }\
- }\
- }\
-}
-
-/*
- Unlink steps:
-
- 1. If x is a chained node, unlink it from its same-sized fd/bk links
- and choose its bk node as its replacement.
- 2. If x was the last node of its size, but not a leaf node, it must
- be replaced with a leaf node (not merely one with an open left or
- right), to make sure that lefts and rights of descendents
- correspond properly to bit masks. We use the rightmost descendent
- of x. We could use any other leaf, but this is easy to locate and
- tends to counteract removal of leftmosts elsewhere, and so keeps
- paths shorter than minimally guaranteed. This doesn't loop much
- because on average a node in a tree is near the bottom.
- 3. If x is the base of a chain (i.e., has parent links) relink
- x's parent and children to x's replacement (or null if none).
-*/
-
-#define unlink_large_chunk(M, X) {\
- tchunkptr XP = X->parent;\
- tchunkptr R;\
- if (X->bk != X) {\
- tchunkptr F = X->fd;\
- R = X->bk;\
- if (RTCHECK(ok_address(M, F))) {\
- F->bk = R;\
- R->fd = F;\
- }\
- else {\
- CORRUPTION_ERROR_ACTION(M);\
- }\
- }\
- else {\
- tchunkptr* RP;\
- if (((R = *(RP = &(X->child[1]))) != 0) ||\
- ((R = *(RP = &(X->child[0]))) != 0)) {\
- tchunkptr* CP;\
- while ((*(CP = &(R->child[1])) != 0) ||\
- (*(CP = &(R->child[0])) != 0)) {\
- R = *(RP = CP);\
- }\
- if (RTCHECK(ok_address(M, RP)))\
- *RP = 0;\
- else {\
- CORRUPTION_ERROR_ACTION(M);\
- }\
- }\
- }\
- if (XP != 0) {\
- tbinptr* H = treebin_at(M, X->index);\
- if (X == *H) {\
- if ((*H = R) == 0) \
- clear_treemap(M, X->index);\
- }\
- else if (RTCHECK(ok_address(M, XP))) {\
- if (XP->child[0] == X) \
- XP->child[0] = R;\
- else \
- XP->child[1] = R;\
- }\
- else\
- CORRUPTION_ERROR_ACTION(M);\
- if (R != 0) {\
- if (RTCHECK(ok_address(M, R))) {\
- tchunkptr C0, C1;\
- R->parent = XP;\
- if ((C0 = X->child[0]) != 0) {\
- if (RTCHECK(ok_address(M, C0))) {\
- R->child[0] = C0;\
- C0->parent = R;\
- }\
- else\
- CORRUPTION_ERROR_ACTION(M);\
- }\
- if ((C1 = X->child[1]) != 0) {\
- if (RTCHECK(ok_address(M, C1))) {\
- R->child[1] = C1;\
- C1->parent = R;\
- }\
- else\
- CORRUPTION_ERROR_ACTION(M);\
- }\
- }\
- else\
- CORRUPTION_ERROR_ACTION(M);\
- }\
- }\
-}
-
-/* Relays to large vs small bin operations */
-
-#define insert_chunk(M, P, S)\
- if (is_small(S)) insert_small_chunk(M, P, S)\
- else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }
-
-#define unlink_chunk(M, P, S)\
- if (is_small(S)) unlink_small_chunk(M, P, S)\
- else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }
-
-
-/* Relays to internal calls to malloc/free from realloc, memalign etc */
-
-#if ONLY_MSPACES
-#define internal_malloc(m, b) mspace_malloc(m, b)
-#define internal_free(m, mem) mspace_free(m,mem);
-#else /* ONLY_MSPACES */
-#if MSPACES
-#define internal_malloc(m, b)\
- (m == gm)? dlmalloc(b) : mspace_malloc(m, b)
-#define internal_free(m, mem)\
- if (m == gm) dlfree(mem); else mspace_free(m,mem);
-#else /* MSPACES */
-#define internal_malloc(m, b) dlmalloc(b)
-#define internal_free(m, mem) dlfree(mem)
-#endif /* MSPACES */
-#endif /* ONLY_MSPACES */
-
-/* ----------------------- Direct-mmapping chunks ----------------------- */
-
-/*
- Directly mmapped chunks are set up with an offset to the start of
- the mmapped region stored in the prev_foot field of the chunk. This
- allows reconstruction of the required argument to MUNMAP when freed,
- and also allows adjustment of the returned chunk to meet alignment
- requirements (especially in memalign).
-*/
-
-/* Malloc using mmap */
-static void* mmap_alloc(mstate m, size_t nb) {
- size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
- if (mmsize > nb) { /* Check for wrap around 0 */
- char* mm = (char*)(CALL_DIRECT_MMAP(mmsize));
- if (mm != CMFAIL) {
- size_t offset = align_offset(chunk2mem(mm));
- size_t psize = mmsize - offset - MMAP_FOOT_PAD;
- mchunkptr p = (mchunkptr)(mm + offset);
- p->prev_foot = offset;
- p->head = psize;
- mark_inuse_foot(m, p, psize);
- chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD;
- chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0;
-
- if (m->least_addr == 0 || mm < m->least_addr)
- m->least_addr = mm;
- if ((m->footprint += mmsize) > m->max_footprint)
- m->max_footprint = m->footprint;
- assert(is_aligned(chunk2mem(p)));
- check_mmapped_chunk(m, p);
- return chunk2mem(p);
- }
- }
- return 0;
-}
-
-/* Realloc using mmap */
-static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) {
- size_t oldsize = chunksize(oldp);
- if (is_small(nb)) /* Can't shrink mmap regions below small size */
- return 0;
- /* Keep old chunk if big enough but not too big */
- if (oldsize >= nb + SIZE_T_SIZE &&
- (oldsize - nb) <= (mparams.granularity << 1))
- return oldp;
- else {
- size_t offset = oldp->prev_foot;
- size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD;
- size_t newmmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
- char* cp = (char*)CALL_MREMAP((char*)oldp - offset,
- oldmmsize, newmmsize, 1);
- if (cp != CMFAIL) {
- mchunkptr newp = (mchunkptr)(cp + offset);
- size_t psize = newmmsize - offset - MMAP_FOOT_PAD;
- newp->head = psize;
- mark_inuse_foot(m, newp, psize);
- chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD;
- chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0;
-
- if (cp < m->least_addr)
- m->least_addr = cp;
- if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint)
- m->max_footprint = m->footprint;
- check_mmapped_chunk(m, newp);
- return newp;
- }
- }
- return 0;
-}
-
-/* -------------------------- mspace management -------------------------- */
-
-/* Initialize top chunk and its size */
-static void init_top(mstate m, mchunkptr p, size_t psize) {
- /* Ensure alignment */
- size_t offset = align_offset(chunk2mem(p));
- p = (mchunkptr)((char*)p + offset);
- psize -= offset;
-
- m->top = p;
- m->topsize = psize;
- p->head = psize | PINUSE_BIT;
- /* set size of fake trailing chunk holding overhead space only once */
- chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;
- m->trim_check = mparams.trim_threshold; /* reset on each update */
-}
-
-/* Initialize bins for a new mstate that is otherwise zeroed out */
-static void init_bins(mstate m) {
- /* Establish circular links for smallbins */
- bindex_t i;
- for (i = 0; i < NSMALLBINS; ++i) {
- sbinptr bin = smallbin_at(m,i);
- bin->fd = bin->bk = bin;
- }
-}
-
-#if PROCEED_ON_ERROR
-
-/* default corruption action */
-static void reset_on_error(mstate m) {
- int i;
- ++malloc_corruption_error_count;
- /* Reinitialize fields to forget about all memory */
- m->smallbins = m->treebins = 0;
- m->dvsize = m->topsize = 0;
- m->seg.base = 0;
- m->seg.size = 0;
- m->seg.next = 0;
- m->top = m->dv = 0;
- for (i = 0; i < NTREEBINS; ++i)
- *treebin_at(m, i) = 0;
- init_bins(m);
-}
-#endif /* PROCEED_ON_ERROR */
-
-/* Allocate chunk and prepend remainder with chunk in successor base. */
-static void* prepend_alloc(mstate m, char* newbase, char* oldbase,
- size_t nb) {
- mchunkptr p = align_as_chunk(newbase);
- mchunkptr oldfirst = align_as_chunk(oldbase);
- size_t psize = (char*)oldfirst - (char*)p;
- mchunkptr q = chunk_plus_offset(p, nb);
- size_t qsize = psize - nb;
- set_size_and_pinuse_of_inuse_chunk(m, p, nb);
-
- assert((char*)oldfirst > (char*)q);
- assert(pinuse(oldfirst));
- assert(qsize >= MIN_CHUNK_SIZE);
-
- /* consolidate remainder with first chunk of old base */
- if (oldfirst == m->top) {
- size_t tsize = m->topsize += qsize;
- m->top = q;
- q->head = tsize | PINUSE_BIT;
- check_top_chunk(m, q);
- }
- else if (oldfirst == m->dv) {
- size_t dsize = m->dvsize += qsize;
- m->dv = q;
- set_size_and_pinuse_of_free_chunk(q, dsize);
- }
- else {
- if (!is_inuse(oldfirst)) {
- size_t nsize = chunksize(oldfirst);
- unlink_chunk(m, oldfirst, nsize);
- oldfirst = chunk_plus_offset(oldfirst, nsize);
- qsize += nsize;
- }
- set_free_with_pinuse(q, qsize, oldfirst);
- insert_chunk(m, q, qsize);
- check_free_chunk(m, q);
- }
-
- check_malloced_chunk(m, chunk2mem(p), nb);
- return chunk2mem(p);
-}
-
-/* Add a segment to hold a new noncontiguous region */
-static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) {
- /* Determine locations and sizes of segment, fenceposts, old top */
- char* old_top = (char*)m->top;
- msegmentptr oldsp = segment_holding(m, old_top);
- char* old_end = oldsp->base + oldsp->size;
- size_t ssize = pad_request(sizeof(struct malloc_segment));
- char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
- size_t offset = align_offset(chunk2mem(rawsp));
- char* asp = rawsp + offset;
- char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp;
- mchunkptr sp = (mchunkptr)csp;
- msegmentptr ss = (msegmentptr)(chunk2mem(sp));
- mchunkptr tnext = chunk_plus_offset(sp, ssize);
- mchunkptr p = tnext;
- int nfences = 0;
-
- /* reset top to new space */
- init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
-
- /* Set up segment record */
- assert(is_aligned(ss));
- set_size_and_pinuse_of_inuse_chunk(m, sp, ssize);
- *ss = m->seg; /* Push current record */
- m->seg.base = tbase;
- m->seg.size = tsize;
- m->seg.sflags = mmapped;
- m->seg.next = ss;
-
- /* Insert trailing fenceposts */
- for (;;) {
- mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE);
- p->head = FENCEPOST_HEAD;
- ++nfences;
- if ((char*)(&(nextp->head)) < old_end)
- p = nextp;
- else
- break;
- }
- assert(nfences >= 2);
-
- /* Insert the rest of old top into a bin as an ordinary free chunk */
- if (csp != old_top) {
- mchunkptr q = (mchunkptr)old_top;
- size_t psize = csp - old_top;
- mchunkptr tn = chunk_plus_offset(q, psize);
- set_free_with_pinuse(q, psize, tn);
- insert_chunk(m, q, psize);
- }
-
- check_top_chunk(m, m->top);
-}
-
-/* -------------------------- System allocation -------------------------- */
-
-/* Get memory from system using MORECORE or MMAP */
-static void* sys_alloc(mstate m, size_t nb) {
- char* tbase = CMFAIL;
- size_t tsize = 0;
- flag_t mmap_flag = 0;
-
- ensure_initialization();
-
- /* Directly map large chunks, but only if already initialized */
- if (use_mmap(m) && nb >= mparams.mmap_threshold && m->topsize != 0) {
- void* mem = mmap_alloc(m, nb);
- if (mem != 0)
- return mem;
- }
-
- /*
- Try getting memory in any of three ways (in most-preferred to
- least-preferred order):
- 1. A call to MORECORE that can normally contiguously extend memory.
- (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or
- or main space is mmapped or a previous contiguous call failed)
- 2. A call to MMAP new space (disabled if not HAVE_MMAP).
- Note that under the default settings, if MORECORE is unable to
- fulfill a request, and HAVE_MMAP is true, then mmap is
- used as a noncontiguous system allocator. This is a useful backup
- strategy for systems with holes in address spaces -- in this case
- sbrk cannot contiguously expand the heap, but mmap may be able to
- find space.
- 3. A call to MORECORE that cannot usually contiguously extend memory.
- (disabled if not HAVE_MORECORE)
-
- In all cases, we need to request enough bytes from system to ensure
- we can malloc nb bytes upon success, so pad with enough space for
- top_foot, plus alignment-pad to make sure we don't lose bytes if
- not on boundary, and round this up to a granularity unit.
- */
-
- if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) {
- char* br = CMFAIL;
- msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top);
- size_t asize = 0;
- ACQUIRE_MALLOC_GLOBAL_LOCK();
-
- if (ss == 0) { /* First time through or recovery */
- char* base = (char*)CALL_MORECORE(0);
- if (base != CMFAIL) {
- asize = granularity_align(nb + SYS_ALLOC_PADDING);
- /* Adjust to end on a page boundary */
- if (!is_page_aligned(base))
- asize += (page_align((size_t)base) - (size_t)base);
- /* Can't call MORECORE if size is negative when treated as signed */
- if (asize < HALF_MAX_SIZE_T &&
- (br = (char*)(CALL_MORECORE(asize))) == base) {
- tbase = base;
- tsize = asize;
- }
- }
- }
- else {
- /* Subtract out existing available top space from MORECORE request. */
- asize = granularity_align(nb - m->topsize + SYS_ALLOC_PADDING);
- /* Use mem here only if it did continuously extend old space */
- if (asize < HALF_MAX_SIZE_T &&
- (br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) {
- tbase = br;
- tsize = asize;
- }
- }
-
- if (tbase == CMFAIL) { /* Cope with partial failure */
- if (br != CMFAIL) { /* Try to use/extend the space we did get */
- if (asize < HALF_MAX_SIZE_T &&
- asize < nb + SYS_ALLOC_PADDING) {
- size_t esize = granularity_align(nb + SYS_ALLOC_PADDING - asize);
- if (esize < HALF_MAX_SIZE_T) {
- char* end = (char*)CALL_MORECORE(esize);
- if (end != CMFAIL)
- asize += esize;
- else { /* Can't use; try to release */
- (void) CALL_MORECORE(-asize);
- br = CMFAIL;
- }
- }
- }
- }
- if (br != CMFAIL) { /* Use the space we did get */
- tbase = br;
- tsize = asize;
- }
- else
- disable_contiguous(m); /* Don't try contiguous path in the future */
- }
-
- RELEASE_MALLOC_GLOBAL_LOCK();
- }
-
- if (HAVE_MMAP && tbase == CMFAIL) { /* Try MMAP */
- size_t rsize = granularity_align(nb + SYS_ALLOC_PADDING);
- if (rsize > nb) { /* Fail if wraps around zero */
- char* mp = (char*)(CALL_MMAP(rsize));
- if (mp != CMFAIL) {
- tbase = mp;
- tsize = rsize;
- mmap_flag = USE_MMAP_BIT;
- }
- }
- }
-
- if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */
- size_t asize = granularity_align(nb + SYS_ALLOC_PADDING);
- if (asize < HALF_MAX_SIZE_T) {
- char* br = CMFAIL;
- char* end = CMFAIL;
- ACQUIRE_MALLOC_GLOBAL_LOCK();
- br = (char*)(CALL_MORECORE(asize));
- end = (char*)(CALL_MORECORE(0));
- RELEASE_MALLOC_GLOBAL_LOCK();
- if (br != CMFAIL && end != CMFAIL && br < end) {
- size_t ssize = end - br;
- if (ssize > nb + TOP_FOOT_SIZE) {
- tbase = br;
- tsize = ssize;
- }
- }
- }
- }
-
- if (tbase != CMFAIL) {
-
- if ((m->footprint += tsize) > m->max_footprint)
- m->max_footprint = m->footprint;
-
- if (!is_initialized(m)) { /* first-time initialization */
- if (m->least_addr == 0 || tbase < m->least_addr)
- m->least_addr = tbase;
- m->seg.base = tbase;
- m->seg.size = tsize;
- m->seg.sflags = mmap_flag;
- m->magic = mparams.magic;
- m->release_checks = MAX_RELEASE_CHECK_RATE;
- init_bins(m);
-#if !ONLY_MSPACES
- if (is_global(m))
- init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
- else
-#endif
- {
- /* Offset top by embedded malloc_state */
- mchunkptr mn = next_chunk(mem2chunk(m));
- init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE);
- }
- }
-
- else {
- /* Try to merge with an existing segment */
- msegmentptr sp = &m->seg;
- /* Only consider most recent segment if traversal suppressed */
- while (sp != 0 && tbase != sp->base + sp->size)
- sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next;
- if (sp != 0 &&
- !is_extern_segment(sp) &&
- (sp->sflags & USE_MMAP_BIT) == mmap_flag &&
- segment_holds(sp, m->top)) { /* append */
- sp->size += tsize;
- init_top(m, m->top, m->topsize + tsize);
- }
- else {
- if (tbase < m->least_addr)
- m->least_addr = tbase;
- sp = &m->seg;
- while (sp != 0 && sp->base != tbase + tsize)
- sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next;
- if (sp != 0 &&
- !is_extern_segment(sp) &&
- (sp->sflags & USE_MMAP_BIT) == mmap_flag) {
- char* oldbase = sp->base;
- sp->base = tbase;
- sp->size += tsize;
- return prepend_alloc(m, tbase, oldbase, nb);
- }
- else
- add_segment(m, tbase, tsize, mmap_flag);
- }
- }
-
- if (nb < m->topsize) { /* Allocate from new or extended top space */
- size_t rsize = m->topsize -= nb;
- mchunkptr p = m->top;
- mchunkptr r = m->top = chunk_plus_offset(p, nb);
- r->head = rsize | PINUSE_BIT;
- set_size_and_pinuse_of_inuse_chunk(m, p, nb);
- check_top_chunk(m, m->top);
- check_malloced_chunk(m, chunk2mem(p), nb);
- return chunk2mem(p);
- }
- }
-
- MALLOC_FAILURE_ACTION;
- return 0;
-}
-
-/* ----------------------- system deallocation -------------------------- */
-
-/* Unmap and unlink any mmapped segments that don't contain used chunks */
-static size_t release_unused_segments(mstate m) {
- size_t released = 0;
- int nsegs = 0;
- msegmentptr pred = &m->seg;
- msegmentptr sp = pred->next;
- while (sp != 0) {
- char* base = sp->base;
- size_t size = sp->size;
- msegmentptr next = sp->next;
- ++nsegs;
- if (is_mmapped_segment(sp) && !is_extern_segment(sp)) {
- mchunkptr p = align_as_chunk(base);
- size_t psize = chunksize(p);
- /* Can unmap if first chunk holds entire segment and not pinned */
- if (!is_inuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) {
- tchunkptr tp = (tchunkptr)p;
- assert(segment_holds(sp, (char*)sp));
- if (p == m->dv) {
- m->dv = 0;
- m->dvsize = 0;
- }
- else {
- unlink_large_chunk(m, tp);
- }
- if (CALL_MUNMAP(base, size) == 0) {
- released += size;
- m->footprint -= size;
- /* unlink obsoleted record */
- sp = pred;
- sp->next = next;
- }
- else { /* back out if cannot unmap */
- insert_large_chunk(m, tp, psize);
- }
- }
- }
- if (NO_SEGMENT_TRAVERSAL) /* scan only first segment */
- break;
- pred = sp;
- sp = next;
- }
- /* Reset check counter */
- m->release_checks = ((nsegs > MAX_RELEASE_CHECK_RATE)?
- nsegs : MAX_RELEASE_CHECK_RATE);
- return released;
-}
-
-static int sys_trim(mstate m, size_t pad) {
- size_t released = 0;
- ensure_initialization();
- if (pad < MAX_REQUEST && is_initialized(m)) {
- pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */
-
- if (m->topsize > pad) {
- /* Shrink top space in granularity-size units, keeping at least one */
- size_t unit = mparams.granularity;
- size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit -
- SIZE_T_ONE) * unit;
- msegmentptr sp = segment_holding(m, (char*)m->top);
-
- if (!is_extern_segment(sp)) {
- if (is_mmapped_segment(sp)) {
- if (HAVE_MMAP &&
- sp->size >= extra &&
- !has_segment_link(m, sp)) { /* can't shrink if pinned */
- size_t newsize = sp->size - extra;
- /* Prefer mremap, fall back to munmap */
- if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) ||
- (CALL_MUNMAP(sp->base + newsize, extra) == 0)) {
- released = extra;
- }
- }
- }
- else if (HAVE_MORECORE) {
- if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */
- extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit;
- ACQUIRE_MALLOC_GLOBAL_LOCK();
- {
- /* Make sure end of memory is where we last set it. */
- char* old_br = (char*)(CALL_MORECORE(0));
- if (old_br == sp->base + sp->size) {
- char* rel_br = (char*)(CALL_MORECORE(-extra));
- char* new_br = (char*)(CALL_MORECORE(0));
- if (rel_br != CMFAIL && new_br < old_br)
- released = old_br - new_br;
- }
- }
- RELEASE_MALLOC_GLOBAL_LOCK();
- }
- }
-
- if (released != 0) {
- sp->size -= released;
- m->footprint -= released;
- init_top(m, m->top, m->topsize - released);
- check_top_chunk(m, m->top);
- }
- }
-
- /* Unmap any unused mmapped segments */
- if (HAVE_MMAP)
- released += release_unused_segments(m);
-
- /* On failure, disable autotrim to avoid repeated failed future calls */
- if (released == 0 && m->topsize > m->trim_check)
- m->trim_check = MAX_SIZE_T;
- }
-
- return (released != 0)? 1 : 0;
-}
-
-
-/* ---------------------------- malloc support --------------------------- */
-
-/* allocate a large request from the best fitting chunk in a treebin */
-static void* tmalloc_large(mstate m, size_t nb) {
- tchunkptr v = 0;
- size_t rsize = -nb; /* Unsigned negation */
- tchunkptr t;
- bindex_t idx;
- compute_tree_index(nb, idx);
- if ((t = *treebin_at(m, idx)) != 0) {
- /* Traverse tree for this bin looking for node with size == nb */
- size_t sizebits = nb << leftshift_for_tree_index(idx);
- tchunkptr rst = 0; /* The deepest untaken right subtree */
- for (;;) {
- tchunkptr rt;
- size_t trem = chunksize(t) - nb;
- if (trem < rsize) {
- v = t;
- if ((rsize = trem) == 0)
- break;
- }
- rt = t->child[1];
- t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
- if (rt != 0 && rt != t)
- rst = rt;
- if (t == 0) {
- t = rst; /* set t to least subtree holding sizes > nb */
- break;
- }
- sizebits <<= 1;
- }
- }
- if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */
- binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;
- if (leftbits != 0) {
- bindex_t i;
- binmap_t leastbit = least_bit(leftbits);
- compute_bit2idx(leastbit, i);
- t = *treebin_at(m, i);
- }
- }
-
- while (t != 0) { /* find smallest of tree or subtree */
- size_t trem = chunksize(t) - nb;
- if (trem < rsize) {
- rsize = trem;
- v = t;
- }
- t = leftmost_child(t);
- }
-
- /* If dv is a better fit, return 0 so malloc will use it */
- if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {
- if (RTCHECK(ok_address(m, v))) { /* split */
- mchunkptr r = chunk_plus_offset(v, nb);
- assert(chunksize(v) == rsize + nb);
- if (RTCHECK(ok_next(v, r))) {
- unlink_large_chunk(m, v);
- if (rsize < MIN_CHUNK_SIZE)
- set_inuse_and_pinuse(m, v, (rsize + nb));
- else {
- set_size_and_pinuse_of_inuse_chunk(m, v, nb);
- set_size_and_pinuse_of_free_chunk(r, rsize);
- insert_chunk(m, r, rsize);
- }
- return chunk2mem(v);
- }
- }
- CORRUPTION_ERROR_ACTION(m);
- }
- return 0;
-}
-
-/* allocate a small request from the best fitting chunk in a treebin */
-static void* tmalloc_small(mstate m, size_t nb) {
- tchunkptr t, v;
- size_t rsize;
- bindex_t i;
- binmap_t leastbit = least_bit(m->treemap);
- compute_bit2idx(leastbit, i);
- v = t = *treebin_at(m, i);
- rsize = chunksize(t) - nb;
-
- while ((t = leftmost_child(t)) != 0) {
- size_t trem = chunksize(t) - nb;
- if (trem < rsize) {
- rsize = trem;
- v = t;
- }
- }
-
- if (RTCHECK(ok_address(m, v))) {
- mchunkptr r = chunk_plus_offset(v, nb);
- assert(chunksize(v) == rsize + nb);
- if (RTCHECK(ok_next(v, r))) {
- unlink_large_chunk(m, v);
- if (rsize < MIN_CHUNK_SIZE)
- set_inuse_and_pinuse(m, v, (rsize + nb));
- else {
- set_size_and_pinuse_of_inuse_chunk(m, v, nb);
- set_size_and_pinuse_of_free_chunk(r, rsize);
- replace_dv(m, r, rsize);
- }
- return chunk2mem(v);
- }
- }
-
- CORRUPTION_ERROR_ACTION(m);
- return 0;
-}
-
-/* --------------------------- realloc support --------------------------- */
-
-static void* internal_realloc(mstate m, void* oldmem, size_t bytes) {
- if (bytes >= MAX_REQUEST) {
- MALLOC_FAILURE_ACTION;
- return 0;
- }
- if (!PREACTION(m)) {
- mchunkptr oldp = mem2chunk(oldmem);
- size_t oldsize = chunksize(oldp);
- mchunkptr next = chunk_plus_offset(oldp, oldsize);
- mchunkptr newp = 0;
- void* extra = 0;
-
- /* Try to either shrink or extend into top. Else malloc-copy-free */
-
- if (RTCHECK(ok_address(m, oldp) && ok_inuse(oldp) &&
- ok_next(oldp, next) && ok_pinuse(next))) {
- size_t nb = request2size(bytes);
- if (is_mmapped(oldp))
- newp = mmap_resize(m, oldp, nb);
- else if (oldsize >= nb) { /* already big enough */
- size_t rsize = oldsize - nb;
- newp = oldp;
- if (rsize >= MIN_CHUNK_SIZE) {
- mchunkptr remainder = chunk_plus_offset(newp, nb);
- set_inuse(m, newp, nb);
- set_inuse_and_pinuse(m, remainder, rsize);
- extra = chunk2mem(remainder);
- }
- }
- else if (next == m->top && oldsize + m->topsize > nb) {
- /* Expand into top */
- size_t newsize = oldsize + m->topsize;
- size_t newtopsize = newsize - nb;
- mchunkptr newtop = chunk_plus_offset(oldp, nb);
- set_inuse(m, oldp, nb);
- newtop->head = newtopsize |PINUSE_BIT;
- m->top = newtop;
- m->topsize = newtopsize;
- newp = oldp;
- }
- }
- else {
- USAGE_ERROR_ACTION(m, oldmem);
- POSTACTION(m);
- return 0;
- }
-#if DEBUG
- if (newp != 0) {
- check_inuse_chunk(m, newp); /* Check requires lock */
- }
-#endif
-
- POSTACTION(m);
-
- if (newp != 0) {
- if (extra != 0) {
- internal_free(m, extra);
- }
- return chunk2mem(newp);
- }
- else {
- void* newmem = internal_malloc(m, bytes);
- if (newmem != 0) {
- size_t oc = oldsize - overhead_for(oldp);
- memcpy(newmem, oldmem, (oc < bytes)? oc : bytes);
- internal_free(m, oldmem);
- }
- return newmem;
- }
- }
- return 0;
-}
-
-/* --------------------------- memalign support -------------------------- */
-
-static void* internal_memalign(mstate m, size_t alignment, size_t bytes) {
- if (alignment <= MALLOC_ALIGNMENT) /* Can just use malloc */
- return internal_malloc(m, bytes);
- if (alignment < MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */
- alignment = MIN_CHUNK_SIZE;
- if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */
- size_t a = MALLOC_ALIGNMENT << 1;
- while (a < alignment) a <<= 1;
- alignment = a;
- }
-
- if (bytes >= MAX_REQUEST - alignment) {
- if (m != 0) { /* Test isn't needed but avoids compiler warning */
- MALLOC_FAILURE_ACTION;
- }
- }
- else {
- size_t nb = request2size(bytes);
- size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;
- char* mem = (char*)internal_malloc(m, req);
- if (mem != 0) {
- void* leader = 0;
- void* trailer = 0;
- mchunkptr p = mem2chunk(mem);
-
- if (PREACTION(m)) return 0;
- if ((((size_t)(mem)) % alignment) != 0) { /* misaligned */
- /*
- Find an aligned spot inside chunk. Since we need to give
- back leading space in a chunk of at least MIN_CHUNK_SIZE, if
- the first calculation places us at a spot with less than
- MIN_CHUNK_SIZE leader, we can move to the next aligned spot.
- We've allocated enough total room so that this is always
- possible.
- */
- char* br = (char*)mem2chunk((size_t)(((size_t)(mem +
- alignment -
- SIZE_T_ONE)) &
- -alignment));
- char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)?
- br : br+alignment;
- mchunkptr newp = (mchunkptr)pos;
- size_t leadsize = pos - (char*)(p);
- size_t newsize = chunksize(p) - leadsize;
-
- if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */
- newp->prev_foot = p->prev_foot + leadsize;
- newp->head = newsize;
- }
- else { /* Otherwise, give back leader, use the rest */
- set_inuse(m, newp, newsize);
- set_inuse(m, p, leadsize);
- leader = chunk2mem(p);
- }
- p = newp;
- }
-
- /* Give back spare room at the end */
- if (!is_mmapped(p)) {
- size_t size = chunksize(p);
- if (size > nb + MIN_CHUNK_SIZE) {
- size_t remainder_size = size - nb;
- mchunkptr remainder = chunk_plus_offset(p, nb);
- set_inuse(m, p, nb);
- set_inuse(m, remainder, remainder_size);
- trailer = chunk2mem(remainder);
- }
- }
-
- assert (chunksize(p) >= nb);
- assert((((size_t)(chunk2mem(p))) % alignment) == 0);
- check_inuse_chunk(m, p);
- POSTACTION(m);
- if (leader != 0) {
- internal_free(m, leader);
- }
- if (trailer != 0) {
- internal_free(m, trailer);
- }
- return chunk2mem(p);
- }
- }
- return 0;
-}
-
-/* ------------------------ comalloc/coalloc support --------------------- */
-
-static void** ialloc(mstate m,
- size_t n_elements,
- size_t* sizes,
- int opts,
- void* chunks[]) {
- /*
- This provides common support for independent_X routines, handling
- all of the combinations that can result.
-
- The opts arg has:
- bit 0 set if all elements are same size (using sizes[0])
- bit 1 set if elements should be zeroed
- */
-
- size_t element_size; /* chunksize of each element, if all same */
- size_t contents_size; /* total size of elements */
- size_t array_size; /* request size of pointer array */
- void* mem; /* malloced aggregate space */
- mchunkptr p; /* corresponding chunk */
- size_t remainder_size; /* remaining bytes while splitting */
- void** marray; /* either "chunks" or malloced ptr array */
- mchunkptr array_chunk; /* chunk for malloced ptr array */
- flag_t was_enabled; /* to disable mmap */
- size_t size;
- size_t i;
-
- ensure_initialization();
- /* compute array length, if needed */
- if (chunks != 0) {
- if (n_elements == 0)
- return chunks; /* nothing to do */
- marray = chunks;
- array_size = 0;
- }
- else {
- /* if empty req, must still return chunk representing empty array */
- if (n_elements == 0)
- return (void**)internal_malloc(m, 0);
- marray = 0;
- array_size = request2size(n_elements * (sizeof(void*)));
- }
-
- /* compute total element size */
- if (opts & 0x1) { /* all-same-size */
- element_size = request2size(*sizes);
- contents_size = n_elements * element_size;
- }
- else { /* add up all the sizes */
- element_size = 0;
- contents_size = 0;
- for (i = 0; i != n_elements; ++i)
- contents_size += request2size(sizes[i]);
- }
-
- size = contents_size + array_size;
-
- /*
- Allocate the aggregate chunk. First disable direct-mmapping so
- malloc won't use it, since we would not be able to later
- free/realloc space internal to a segregated mmap region.
- */
- was_enabled = use_mmap(m);
- disable_mmap(m);
- mem = internal_malloc(m, size - CHUNK_OVERHEAD);
- if (was_enabled)
- enable_mmap(m);
- if (mem == 0)
- return 0;
-
- if (PREACTION(m)) return 0;
- p = mem2chunk(mem);
- remainder_size = chunksize(p);
-
- assert(!is_mmapped(p));
-
- if (opts & 0x2) { /* optionally clear the elements */
- memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size);
- }
-
- /* If not provided, allocate the pointer array as final part of chunk */
- if (marray == 0) {
- size_t array_chunk_size;
- array_chunk = chunk_plus_offset(p, contents_size);
- array_chunk_size = remainder_size - contents_size;
- marray = (void**) (chunk2mem(array_chunk));
- set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size);
- remainder_size = contents_size;
- }
-
- /* split out elements */
- for (i = 0; ; ++i) {
- marray[i] = chunk2mem(p);
- if (i != n_elements-1) {
- if (element_size != 0)
- size = element_size;
- else
- size = request2size(sizes[i]);
- remainder_size -= size;
- set_size_and_pinuse_of_inuse_chunk(m, p, size);
- p = chunk_plus_offset(p, size);
- }
- else { /* the final element absorbs any overallocation slop */
- set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size);
- break;
- }
- }
-
-#if DEBUG
- if (marray != chunks) {
- /* final element must have exactly exhausted chunk */
- if (element_size != 0) {
- assert(remainder_size == element_size);
- }
- else {
- assert(remainder_size == request2size(sizes[i]));
- }
- check_inuse_chunk(m, mem2chunk(marray));
- }
- for (i = 0; i != n_elements; ++i)
- check_inuse_chunk(m, mem2chunk(marray[i]));
-
-#endif /* DEBUG */
-
- POSTACTION(m);
- return marray;
-}
-
-
-/* -------------------------- public routines ---------------------------- */
-
-#if !ONLY_MSPACES
-
-void* dlmalloc(size_t bytes) {
- /*
- Basic algorithm:
- If a small request (< 256 bytes minus per-chunk overhead):
- 1. If one exists, use a remainderless chunk in associated smallbin.
- (Remainderless means that there are too few excess bytes to
- represent as a chunk.)
- 2. If it is big enough, use the dv chunk, which is normally the
- chunk adjacent to the one used for the most recent small request.
- 3. If one exists, split the smallest available chunk in a bin,
- saving remainder in dv.
- 4. If it is big enough, use the top chunk.
- 5. If available, get memory from system and use it
- Otherwise, for a large request:
- 1. Find the smallest available binned chunk that fits, and use it
- if it is better fitting than dv chunk, splitting if necessary.
- 2. If better fitting than any binned chunk, use the dv chunk.
- 3. If it is big enough, use the top chunk.
- 4. If request size >= mmap threshold, try to directly mmap this chunk.
- 5. If available, get memory from system and use it
-
- The ugly goto's here ensure that postaction occurs along all paths.
- */
-
-#if USE_LOCKS
- ensure_initialization(); /* initialize in sys_alloc if not using locks */
-#endif
-
- if (!PREACTION(gm)) {
- void* mem;
- size_t nb;
- if (bytes <= MAX_SMALL_REQUEST) {
- bindex_t idx;
- binmap_t smallbits;
- nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
- idx = small_index(nb);
- smallbits = gm->smallmap >> idx;
-
- if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
- mchunkptr b, p;
- idx += ~smallbits & 1; /* Uses next bin if idx empty */
- b = smallbin_at(gm, idx);
- p = b->fd;
- assert(chunksize(p) == small_index2size(idx));
- unlink_first_small_chunk(gm, b, p, idx);
- set_inuse_and_pinuse(gm, p, small_index2size(idx));
- mem = chunk2mem(p);
- check_malloced_chunk(gm, mem, nb);
- goto postaction;
- }
-
- else if (nb > gm->dvsize) {
- if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
- mchunkptr b, p, r;
- size_t rsize;
- bindex_t i;
- binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
- binmap_t leastbit = least_bit(leftbits);
- compute_bit2idx(leastbit, i);
- b = smallbin_at(gm, i);
- p = b->fd;
- assert(chunksize(p) == small_index2size(i));
- unlink_first_small_chunk(gm, b, p, i);
- rsize = small_index2size(i) - nb;
- /* Fit here cannot be remainderless if 4byte sizes */
- if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
- set_inuse_and_pinuse(gm, p, small_index2size(i));
- else {
- set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
- r = chunk_plus_offset(p, nb);
- set_size_and_pinuse_of_free_chunk(r, rsize);
- replace_dv(gm, r, rsize);
- }
- mem = chunk2mem(p);
- check_malloced_chunk(gm, mem, nb);
- goto postaction;
- }
-
- else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) {
- check_malloced_chunk(gm, mem, nb);
- goto postaction;
- }
- }
- }
- else if (bytes >= MAX_REQUEST)
- nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
- else {
- nb = pad_request(bytes);
- if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) {
- check_malloced_chunk(gm, mem, nb);
- goto postaction;
- }
- }
-
- if (nb <= gm->dvsize) {
- size_t rsize = gm->dvsize - nb;
- mchunkptr p = gm->dv;
- if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
- mchunkptr r = gm->dv = chunk_plus_offset(p, nb);
- gm->dvsize = rsize;
- set_size_and_pinuse_of_free_chunk(r, rsize);
- set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
- }
- else { /* exhaust dv */
- size_t dvs = gm->dvsize;
- gm->dvsize = 0;
- gm->dv = 0;
- set_inuse_and_pinuse(gm, p, dvs);
- }
- mem = chunk2mem(p);
- check_malloced_chunk(gm, mem, nb);
- goto postaction;
- }
-
- else if (nb < gm->topsize) { /* Split top */
- size_t rsize = gm->topsize -= nb;
- mchunkptr p = gm->top;
- mchunkptr r = gm->top = chunk_plus_offset(p, nb);
- r->head = rsize | PINUSE_BIT;
- set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
- mem = chunk2mem(p);
- check_top_chunk(gm, gm->top);
- check_malloced_chunk(gm, mem, nb);
- goto postaction;
- }
-
- mem = sys_alloc(gm, nb);
-
- postaction:
- POSTACTION(gm);
- return mem;
- }
-
- return 0;
-}
-
-void dlfree(void* mem) {
- /*
- Consolidate freed chunks with preceeding or succeeding bordering
- free chunks, if they exist, and then place in a bin. Intermixed
- with special cases for top, dv, mmapped chunks, and usage errors.
- */
-
- if (mem != 0) {
- mchunkptr p = mem2chunk(mem);
-#if FOOTERS
- mstate fm = get_mstate_for(p);
- if (!ok_magic(fm)) {
- USAGE_ERROR_ACTION(fm, p);
- return;
- }
-#else /* FOOTERS */
-#define fm gm
-#endif /* FOOTERS */
- if (!PREACTION(fm)) {
- check_inuse_chunk(fm, p);
- if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) {
- size_t psize = chunksize(p);
- mchunkptr next = chunk_plus_offset(p, psize);
- if (!pinuse(p)) {
- size_t prevsize = p->prev_foot;
- if (is_mmapped(p)) {
- psize += prevsize + MMAP_FOOT_PAD;
- if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
- fm->footprint -= psize;
- goto postaction;
- }
- else {
- mchunkptr prev = chunk_minus_offset(p, prevsize);
- psize += prevsize;
- p = prev;
- if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
- if (p != fm->dv) {
- unlink_chunk(fm, p, prevsize);
- }
- else if ((next->head & INUSE_BITS) == INUSE_BITS) {
- fm->dvsize = psize;
- set_free_with_pinuse(p, psize, next);
- goto postaction;
- }
- }
- else
- goto erroraction;
- }
- }
-
- if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
- if (!cinuse(next)) { /* consolidate forward */
- if (next == fm->top) {
- size_t tsize = fm->topsize += psize;
- fm->top = p;
- p->head = tsize | PINUSE_BIT;
- if (p == fm->dv) {
- fm->dv = 0;
- fm->dvsize = 0;
- }
- if (should_trim(fm, tsize))
- sys_trim(fm, 0);
- goto postaction;
- }
- else if (next == fm->dv) {
- size_t dsize = fm->dvsize += psize;
- fm->dv = p;
- set_size_and_pinuse_of_free_chunk(p, dsize);
- goto postaction;
- }
- else {
- size_t nsize = chunksize(next);
- psize += nsize;
- unlink_chunk(fm, next, nsize);
- set_size_and_pinuse_of_free_chunk(p, psize);
- if (p == fm->dv) {
- fm->dvsize = psize;
- goto postaction;
- }
- }
- }
- else
- set_free_with_pinuse(p, psize, next);
-
- if (is_small(psize)) {
- insert_small_chunk(fm, p, psize);
- check_free_chunk(fm, p);
- }
- else {
- tchunkptr tp = (tchunkptr)p;
- insert_large_chunk(fm, tp, psize);
- check_free_chunk(fm, p);
- if (--fm->release_checks == 0)
- release_unused_segments(fm);
- }
- goto postaction;
- }
- }
- erroraction:
- USAGE_ERROR_ACTION(fm, p);
- postaction:
- POSTACTION(fm);
- }
- }
-#if !FOOTERS
-#undef fm
-#endif /* FOOTERS */
-}
-
-void* dlcalloc(size_t n_elements, size_t elem_size) {
- void* mem;
- size_t req = 0;
- if (n_elements != 0) {
- req = n_elements * elem_size;
- if (((n_elements | elem_size) & ~(size_t)0xffff) &&
- (req / n_elements != elem_size))
- req = MAX_SIZE_T; /* force downstream failure on overflow */
- }
- mem = dlmalloc(req);
- if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
- memset(mem, 0, req);
- return mem;
-}
-
-void* dlrealloc(void* oldmem, size_t bytes) {
- if (oldmem == 0)
- return dlmalloc(bytes);
-#ifdef REALLOC_ZERO_BYTES_FREES
- if (bytes == 0) {
- dlfree(oldmem);
- return 0;
- }
-#endif /* REALLOC_ZERO_BYTES_FREES */
- else {
-#if ! FOOTERS
- mstate m = gm;
-#else /* FOOTERS */
- mstate m = get_mstate_for(mem2chunk(oldmem));
- if (!ok_magic(m)) {
- USAGE_ERROR_ACTION(m, oldmem);
- return 0;
- }
-#endif /* FOOTERS */
- return internal_realloc(m, oldmem, bytes);
- }
-}
-
-void* dlmemalign(size_t alignment, size_t bytes) {
- return internal_memalign(gm, alignment, bytes);
-}
-
-void** dlindependent_calloc(size_t n_elements, size_t elem_size,
- void* chunks[]) {
- size_t sz = elem_size; /* serves as 1-element array */
- return ialloc(gm, n_elements, &sz, 3, chunks);
-}
-
-void** dlindependent_comalloc(size_t n_elements, size_t sizes[],
- void* chunks[]) {
- return ialloc(gm, n_elements, sizes, 0, chunks);
-}
-
-void* dlvalloc(size_t bytes) {
- size_t pagesz;
- ensure_initialization();
- pagesz = mparams.page_size;
- return dlmemalign(pagesz, bytes);
-}
-
-void* dlpvalloc(size_t bytes) {
- size_t pagesz;
- ensure_initialization();
- pagesz = mparams.page_size;
- return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE));
-}
-
-int dlmalloc_trim(size_t pad) {
- int result = 0;
- ensure_initialization();
- if (!PREACTION(gm)) {
- result = sys_trim(gm, pad);
- POSTACTION(gm);
- }
- return result;
-}
-
-size_t dlmalloc_footprint(void) {
- return gm->footprint;
-}
-
-size_t dlmalloc_max_footprint(void) {
- return gm->max_footprint;
-}
-
-#if !NO_MALLINFO
-struct mallinfo dlmallinfo(void) {
- return internal_mallinfo(gm);
-}
-#endif /* NO_MALLINFO */
-
-void dlmalloc_stats() {
- internal_malloc_stats(gm);
-}
-
-int dlmallopt(int param_number, int value) {
- return change_mparam(param_number, value);
-}
-
-#endif /* !ONLY_MSPACES */
-
-size_t dlmalloc_usable_size(void* mem) {
- if (mem != 0) {
- mchunkptr p = mem2chunk(mem);
- if (is_inuse(p))
- return chunksize(p) - overhead_for(p);
- }
- return 0;
-}
-
-/* ----------------------------- user mspaces ---------------------------- */
-
-#if MSPACES
-
-static mstate init_user_mstate(char* tbase, size_t tsize) {
- size_t msize = pad_request(sizeof(struct malloc_state));
- mchunkptr mn;
- mchunkptr msp = align_as_chunk(tbase);
- mstate m = (mstate)(chunk2mem(msp));
- memset(m, 0, msize);
- INITIAL_LOCK(&m->mutex);
- msp->head = (msize|INUSE_BITS);
- m->seg.base = m->least_addr = tbase;
- m->seg.size = m->footprint = m->max_footprint = tsize;
- m->magic = mparams.magic;
- m->release_checks = MAX_RELEASE_CHECK_RATE;
- m->mflags = mparams.default_mflags;
- m->extp = 0;
- m->exts = 0;
- disable_contiguous(m);
- init_bins(m);
- mn = next_chunk(mem2chunk(m));
- init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE);
- check_top_chunk(m, m->top);
- return m;
-}
-
-mspace create_mspace(size_t capacity, int locked) {
- mstate m = 0;
- size_t msize;
- ensure_initialization();
- msize = pad_request(sizeof(struct malloc_state));
- if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
- size_t rs = ((capacity == 0)? mparams.granularity :
- (capacity + TOP_FOOT_SIZE + msize));
- size_t tsize = granularity_align(rs);
- char* tbase = (char*)(CALL_MMAP(tsize));
- if (tbase != CMFAIL) {
- m = init_user_mstate(tbase, tsize);
- m->seg.sflags = USE_MMAP_BIT;
- set_lock(m, locked);
- }
- }
- return (mspace)m;
-}
-
-mspace create_mspace_with_base(void* base, size_t capacity, int locked) {
- mstate m = 0;
- size_t msize;
- ensure_initialization();
- msize = pad_request(sizeof(struct malloc_state));
- if (capacity > msize + TOP_FOOT_SIZE &&
- capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
- m = init_user_mstate((char*)base, capacity);
- m->seg.sflags = EXTERN_BIT;
- set_lock(m, locked);
- }
- return (mspace)m;
-}
-
-int mspace_track_large_chunks(mspace msp, int enable) {
- int ret = 0;
- mstate ms = (mstate)msp;
- if (!PREACTION(ms)) {
- if (!use_mmap(ms))
- ret = 1;
- if (!enable)
- enable_mmap(ms);
- else
- disable_mmap(ms);
- POSTACTION(ms);
- }
- return ret;
-}
-
-size_t destroy_mspace(mspace msp) {
- size_t freed = 0;
- mstate ms = (mstate)msp;
- if (ok_magic(ms)) {
- msegmentptr sp = &ms->seg;
- while (sp != 0) {
- char* base = sp->base;
- size_t size = sp->size;
- flag_t flag = sp->sflags;
- sp = sp->next;
- if ((flag & USE_MMAP_BIT) && !(flag & EXTERN_BIT) &&
- CALL_MUNMAP(base, size) == 0)
- freed += size;
- }
- }
- else {
- USAGE_ERROR_ACTION(ms,ms);
- }
- return freed;
-}
-
-/*
- mspace versions of routines are near-clones of the global
- versions. This is not so nice but better than the alternatives.
-*/
-
-
-void* mspace_malloc(mspace msp, size_t bytes) {
- mstate ms = (mstate)msp;
- if (!ok_magic(ms)) {
- USAGE_ERROR_ACTION(ms,ms);
- return 0;
- }
- if (!PREACTION(ms)) {
- void* mem;
- size_t nb;
- if (bytes <= MAX_SMALL_REQUEST) {
- bindex_t idx;
- binmap_t smallbits;
- nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
- idx = small_index(nb);
- smallbits = ms->smallmap >> idx;
-
- if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
- mchunkptr b, p;
- idx += ~smallbits & 1; /* Uses next bin if idx empty */
- b = smallbin_at(ms, idx);
- p = b->fd;
- assert(chunksize(p) == small_index2size(idx));
- unlink_first_small_chunk(ms, b, p, idx);
- set_inuse_and_pinuse(ms, p, small_index2size(idx));
- mem = chunk2mem(p);
- check_malloced_chunk(ms, mem, nb);
- goto postaction;
- }
-
- else if (nb > ms->dvsize) {
- if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
- mchunkptr b, p, r;
- size_t rsize;
- bindex_t i;
- binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
- binmap_t leastbit = least_bit(leftbits);
- compute_bit2idx(leastbit, i);
- b = smallbin_at(ms, i);
- p = b->fd;
- assert(chunksize(p) == small_index2size(i));
- unlink_first_small_chunk(ms, b, p, i);
- rsize = small_index2size(i) - nb;
- /* Fit here cannot be remainderless if 4byte sizes */
- if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
- set_inuse_and_pinuse(ms, p, small_index2size(i));
- else {
- set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
- r = chunk_plus_offset(p, nb);
- set_size_and_pinuse_of_free_chunk(r, rsize);
- replace_dv(ms, r, rsize);
- }
- mem = chunk2mem(p);
- check_malloced_chunk(ms, mem, nb);
- goto postaction;
- }
-
- else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) {
- check_malloced_chunk(ms, mem, nb);
- goto postaction;
- }
- }
- }
- else if (bytes >= MAX_REQUEST)
- nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
- else {
- nb = pad_request(bytes);
- if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) {
- check_malloced_chunk(ms, mem, nb);
- goto postaction;
- }
- }
-
- if (nb <= ms->dvsize) {
- size_t rsize = ms->dvsize - nb;
- mchunkptr p = ms->dv;
- if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
- mchunkptr r = ms->dv = chunk_plus_offset(p, nb);
- ms->dvsize = rsize;
- set_size_and_pinuse_of_free_chunk(r, rsize);
- set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
- }
- else { /* exhaust dv */
- size_t dvs = ms->dvsize;
- ms->dvsize = 0;
- ms->dv = 0;
- set_inuse_and_pinuse(ms, p, dvs);
- }
- mem = chunk2mem(p);
- check_malloced_chunk(ms, mem, nb);
- goto postaction;
- }
-
- else if (nb < ms->topsize) { /* Split top */
- size_t rsize = ms->topsize -= nb;
- mchunkptr p = ms->top;
- mchunkptr r = ms->top = chunk_plus_offset(p, nb);
- r->head = rsize | PINUSE_BIT;
- set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
- mem = chunk2mem(p);
- check_top_chunk(ms, ms->top);
- check_malloced_chunk(ms, mem, nb);
- goto postaction;
- }
-
- mem = sys_alloc(ms, nb);
-
- postaction:
- POSTACTION(ms);
- return mem;
- }
-
- return 0;
-}
-
-void mspace_free(mspace msp, void* mem) {
- if (mem != 0) {
- mchunkptr p = mem2chunk(mem);
-#if FOOTERS
- mstate fm = get_mstate_for(p);
- msp = msp; /* placate people compiling -Wunused */
-#else /* FOOTERS */
- mstate fm = (mstate)msp;
-#endif /* FOOTERS */
- if (!ok_magic(fm)) {
- USAGE_ERROR_ACTION(fm, p);
- return;
- }
- if (!PREACTION(fm)) {
- check_inuse_chunk(fm, p);
- if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) {
- size_t psize = chunksize(p);
- mchunkptr next = chunk_plus_offset(p, psize);
- if (!pinuse(p)) {
- size_t prevsize = p->prev_foot;
- if (is_mmapped(p)) {
- psize += prevsize + MMAP_FOOT_PAD;
- if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
- fm->footprint -= psize;
- goto postaction;
- }
- else {
- mchunkptr prev = chunk_minus_offset(p, prevsize);
- psize += prevsize;
- p = prev;
- if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
- if (p != fm->dv) {
- unlink_chunk(fm, p, prevsize);
- }
- else if ((next->head & INUSE_BITS) == INUSE_BITS) {
- fm->dvsize = psize;
- set_free_with_pinuse(p, psize, next);
- goto postaction;
- }
- }
- else
- goto erroraction;
- }
- }
-
- if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
- if (!cinuse(next)) { /* consolidate forward */
- if (next == fm->top) {
- size_t tsize = fm->topsize += psize;
- fm->top = p;
- p->head = tsize | PINUSE_BIT;
- if (p == fm->dv) {
- fm->dv = 0;
- fm->dvsize = 0;
- }
- if (should_trim(fm, tsize))
- sys_trim(fm, 0);
- goto postaction;
- }
- else if (next == fm->dv) {
- size_t dsize = fm->dvsize += psize;
- fm->dv = p;
- set_size_and_pinuse_of_free_chunk(p, dsize);
- goto postaction;
- }
- else {
- size_t nsize = chunksize(next);
- psize += nsize;
- unlink_chunk(fm, next, nsize);
- set_size_and_pinuse_of_free_chunk(p, psize);
- if (p == fm->dv) {
- fm->dvsize = psize;
- goto postaction;
- }
- }
- }
- else
- set_free_with_pinuse(p, psize, next);
-
- if (is_small(psize)) {
- insert_small_chunk(fm, p, psize);
- check_free_chunk(fm, p);
- }
- else {
- tchunkptr tp = (tchunkptr)p;
- insert_large_chunk(fm, tp, psize);
- check_free_chunk(fm, p);
- if (--fm->release_checks == 0)
- release_unused_segments(fm);
- }
- goto postaction;
- }
- }
- erroraction:
- USAGE_ERROR_ACTION(fm, p);
- postaction:
- POSTACTION(fm);
- }
- }
-}
-
-void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) {
- void* mem;
- size_t req = 0;
- mstate ms = (mstate)msp;
- if (!ok_magic(ms)) {
- USAGE_ERROR_ACTION(ms,ms);
- return 0;
- }
- if (n_elements != 0) {
- req = n_elements * elem_size;
- if (((n_elements | elem_size) & ~(size_t)0xffff) &&
- (req / n_elements != elem_size))
- req = MAX_SIZE_T; /* force downstream failure on overflow */
- }
- mem = internal_malloc(ms, req);
- if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
- memset(mem, 0, req);
- return mem;
-}
-
-void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) {
- if (oldmem == 0)
- return mspace_malloc(msp, bytes);
-#ifdef REALLOC_ZERO_BYTES_FREES
- if (bytes == 0) {
- mspace_free(msp, oldmem);
- return 0;
- }
-#endif /* REALLOC_ZERO_BYTES_FREES */
- else {
-#if FOOTERS
- mchunkptr p = mem2chunk(oldmem);
- mstate ms = get_mstate_for(p);
-#else /* FOOTERS */
- mstate ms = (mstate)msp;
-#endif /* FOOTERS */
- if (!ok_magic(ms)) {
- USAGE_ERROR_ACTION(ms,ms);
- return 0;
- }
- return internal_realloc(ms, oldmem, bytes);
- }
-}
-
-void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) {
- mstate ms = (mstate)msp;
- if (!ok_magic(ms)) {
- USAGE_ERROR_ACTION(ms,ms);
- return 0;
- }
- return internal_memalign(ms, alignment, bytes);
-}
-
-void** mspace_independent_calloc(mspace msp, size_t n_elements,
- size_t elem_size, void* chunks[]) {
- size_t sz = elem_size; /* serves as 1-element array */
- mstate ms = (mstate)msp;
- if (!ok_magic(ms)) {
- USAGE_ERROR_ACTION(ms,ms);
- return 0;
- }
- return ialloc(ms, n_elements, &sz, 3, chunks);
-}
-
-void** mspace_independent_comalloc(mspace msp, size_t n_elements,
- size_t sizes[], void* chunks[]) {
- mstate ms = (mstate)msp;
- if (!ok_magic(ms)) {
- USAGE_ERROR_ACTION(ms,ms);
- return 0;
- }
- return ialloc(ms, n_elements, sizes, 0, chunks);
-}
-
-int mspace_trim(mspace msp, size_t pad) {
- int result = 0;
- mstate ms = (mstate)msp;
- if (ok_magic(ms)) {
- if (!PREACTION(ms)) {
- result = sys_trim(ms, pad);
- POSTACTION(ms);
- }
- }
- else {
- USAGE_ERROR_ACTION(ms,ms);
- }
- return result;
-}
-
-void mspace_malloc_stats(mspace msp) {
- mstate ms = (mstate)msp;
- if (ok_magic(ms)) {
- internal_malloc_stats(ms);
- }
- else {
- USAGE_ERROR_ACTION(ms,ms);
- }
-}
-
-size_t mspace_footprint(mspace msp) {
- size_t result = 0;
- mstate ms = (mstate)msp;
- if (ok_magic(ms)) {
- result = ms->footprint;
- }
- else {
- USAGE_ERROR_ACTION(ms,ms);
- }
- return result;
-}
-
-
-size_t mspace_max_footprint(mspace msp) {
- size_t result = 0;
- mstate ms = (mstate)msp;
- if (ok_magic(ms)) {
- result = ms->max_footprint;
- }
- else {
- USAGE_ERROR_ACTION(ms,ms);
- }
- return result;
-}
-
-
-#if !NO_MALLINFO
-struct mallinfo mspace_mallinfo(mspace msp) {
- mstate ms = (mstate)msp;
- if (!ok_magic(ms)) {
- USAGE_ERROR_ACTION(ms,ms);
- }
- return internal_mallinfo(ms);
-}
-#endif /* NO_MALLINFO */
-
-size_t mspace_usable_size(void* mem) {
- if (mem != 0) {
- mchunkptr p = mem2chunk(mem);
- if (is_inuse(p))
- return chunksize(p) - overhead_for(p);
- }
- return 0;
-}
-
-int mspace_mallopt(int param_number, int value) {
- return change_mparam(param_number, value);
-}
-
-#endif /* MSPACES */
-
-
-/* -------------------- Alternative MORECORE functions ------------------- */
-
-/*
- Guidelines for creating a custom version of MORECORE:
-
- * For best performance, MORECORE should allocate in multiples of pagesize.
- * MORECORE may allocate more memory than requested. (Or even less,
- but this will usually result in a malloc failure.)
- * MORECORE must not allocate memory when given argument zero, but
- instead return one past the end address of memory from previous
- nonzero call.
- * For best performance, consecutive calls to MORECORE with positive
- arguments should return increasing addresses, indicating that
- space has been contiguously extended.
- * Even though consecutive calls to MORECORE need not return contiguous
- addresses, it must be OK for malloc'ed chunks to span multiple
- regions in those cases where they do happen to be contiguous.
- * MORECORE need not handle negative arguments -- it may instead
- just return MFAIL when given negative arguments.
- Negative arguments are always multiples of pagesize. MORECORE
- must not misinterpret negative args as large positive unsigned
- args. You can suppress all such calls from even occurring by defining
- MORECORE_CANNOT_TRIM,
-
- As an example alternative MORECORE, here is a custom allocator
- kindly contributed for pre-OSX macOS. It uses virtually but not
- necessarily physically contiguous non-paged memory (locked in,
- present and won't get swapped out). You can use it by uncommenting
- this section, adding some #includes, and setting up the appropriate
- defines above:
-
- #define MORECORE osMoreCore
-
- There is also a shutdown routine that should somehow be called for
- cleanup upon program exit.
-
- #define MAX_POOL_ENTRIES 100
- #define MINIMUM_MORECORE_SIZE (64 * 1024U)
- static int next_os_pool;
- void *our_os_pools[MAX_POOL_ENTRIES];
-
- void *osMoreCore(int size)
- {
- void *ptr = 0;
- static void *sbrk_top = 0;
-
- if (size > 0)
- {
- if (size < MINIMUM_MORECORE_SIZE)
- size = MINIMUM_MORECORE_SIZE;
- if (CurrentExecutionLevel() == kTaskLevel)
- ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0);
- if (ptr == 0)
- {
- return (void *) MFAIL;
- }
- // save ptrs so they can be freed during cleanup
- our_os_pools[next_os_pool] = ptr;
- next_os_pool++;
- ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK);
- sbrk_top = (char *) ptr + size;
- return ptr;
- }
- else if (size < 0)
- {
- // we don't currently support shrink behavior
- return (void *) MFAIL;
- }
- else
- {
- return sbrk_top;
- }
- }
-
- // cleanup any allocated memory pools
- // called as last thing before shutting down driver
-
- void osCleanupMem(void)
- {
- void **ptr;
-
- for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++)
- if (*ptr)
- {
- PoolDeallocate(*ptr);
- *ptr = 0;
- }
- }
-
-*/
-
-
-/* -----------------------------------------------------------------------
-History:
- V2.8.4 Wed May 27 09:56:23 2009 Doug Lea (dl at gee)
- * Use zeros instead of prev foot for is_mmapped
- * Add mspace_track_large_chunks; thanks to Jean Brouwers
- * Fix set_inuse in internal_realloc; thanks to Jean Brouwers
- * Fix insufficient sys_alloc padding when using 16byte alignment
- * Fix bad error check in mspace_footprint
- * Adaptations for ptmalloc; thanks to Wolfram Gloger.
- * Reentrant spin locks; thanks to Earl Chew and others
- * Win32 improvements; thanks to Niall Douglas and Earl Chew
- * Add NO_SEGMENT_TRAVERSAL and MAX_RELEASE_CHECK_RATE options
- * Extension hook in malloc_state
- * Various small adjustments to reduce warnings on some compilers
- * Various configuration extensions/changes for more platforms. Thanks
- to all who contributed these.
-
- V2.8.3 Thu Sep 22 11:16:32 2005 Doug Lea (dl at gee)
- * Add max_footprint functions
- * Ensure all appropriate literals are size_t
- * Fix conditional compilation problem for some #define settings
- * Avoid concatenating segments with the one provided
- in create_mspace_with_base
- * Rename some variables to avoid compiler shadowing warnings
- * Use explicit lock initialization.
- * Better handling of sbrk interference.
- * Simplify and fix segment insertion, trimming and mspace_destroy
- * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x
- * Thanks especially to Dennis Flanagan for help on these.
-
- V2.8.2 Sun Jun 12 16:01:10 2005 Doug Lea (dl at gee)
- * Fix memalign brace error.
-
- V2.8.1 Wed Jun 8 16:11:46 2005 Doug Lea (dl at gee)
- * Fix improper #endif nesting in C++
- * Add explicit casts needed for C++
-
- V2.8.0 Mon May 30 14:09:02 2005 Doug Lea (dl at gee)
- * Use trees for large bins
- * Support mspaces
- * Use segments to unify sbrk-based and mmap-based system allocation,
- removing need for emulation on most platforms without sbrk.
- * Default safety checks
- * Optional footer checks. Thanks to William Robertson for the idea.
- * Internal code refactoring
- * Incorporate suggestions and platform-specific changes.
- Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas,
- Aaron Bachmann, Emery Berger, and others.
- * Speed up non-fastbin processing enough to remove fastbins.
- * Remove useless cfree() to avoid conflicts with other apps.
- * Remove internal memcpy, memset. Compilers handle builtins better.
- * Remove some options that no one ever used and rename others.
-
- V2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
- * Fix malloc_state bitmap array misdeclaration
-
- V2.7.1 Thu Jul 25 10:58:03 2002 Doug Lea (dl at gee)
- * Allow tuning of FIRST_SORTED_BIN_SIZE
- * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte.
- * Better detection and support for non-contiguousness of MORECORE.
- Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger
- * Bypass most of malloc if no frees. Thanks To Emery Berger.
- * Fix freeing of old top non-contiguous chunk im sysmalloc.
- * Raised default trim and map thresholds to 256K.
- * Fix mmap-related #defines. Thanks to Lubos Lunak.
- * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield.
- * Branch-free bin calculation
- * Default trim and mmap thresholds now 256K.
-
- V2.7.0 Sun Mar 11 14:14:06 2001 Doug Lea (dl at gee)
- * Introduce independent_comalloc and independent_calloc.
- Thanks to Michael Pachos for motivation and help.
- * Make optional .h file available
- * Allow > 2GB requests on 32bit systems.
- * new WIN32 sbrk, mmap, munmap, lock code from <Walter@GeNeSys-e.de>.
- Thanks also to Andreas Mueller <a.mueller at paradatec.de>,
- and Anonymous.
- * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for
- helping test this.)
- * memalign: check alignment arg
- * realloc: don't try to shift chunks backwards, since this
- leads to more fragmentation in some programs and doesn't
- seem to help in any others.
- * Collect all cases in malloc requiring system memory into sysmalloc
- * Use mmap as backup to sbrk
- * Place all internal state in malloc_state
- * Introduce fastbins (although similar to 2.5.1)
- * Many minor tunings and cosmetic improvements
- * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK
- * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS
- Thanks to Tony E. Bennett <tbennett@nvidia.com> and others.
- * Include errno.h to support default failure action.
-
- V2.6.6 Sun Dec 5 07:42:19 1999 Doug Lea (dl at gee)
- * return null for negative arguments
- * Added Several WIN32 cleanups from Martin C. Fong <mcfong at yahoo.com>
- * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h'
- (e.g. WIN32 platforms)
- * Cleanup header file inclusion for WIN32 platforms
- * Cleanup code to avoid Microsoft Visual C++ compiler complaints
- * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
- memory allocation routines
- * Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
- * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
- usage of 'assert' in non-WIN32 code
- * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
- avoid infinite loop
- * Always call 'fREe()' rather than 'free()'
-
- V2.6.5 Wed Jun 17 15:57:31 1998 Doug Lea (dl at gee)
- * Fixed ordering problem with boundary-stamping
-
- V2.6.3 Sun May 19 08:17:58 1996 Doug Lea (dl at gee)
- * Added pvalloc, as recommended by H.J. Liu
- * Added 64bit pointer support mainly from Wolfram Gloger
- * Added anonymously donated WIN32 sbrk emulation
- * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
- * malloc_extend_top: fix mask error that caused wastage after
- foreign sbrks
- * Add linux mremap support code from HJ Liu
-
- V2.6.2 Tue Dec 5 06:52:55 1995 Doug Lea (dl at gee)
- * Integrated most documentation with the code.
- * Add support for mmap, with help from
- Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
- * Use last_remainder in more cases.
- * Pack bins using idea from colin@nyx10.cs.du.edu
- * Use ordered bins instead of best-fit threshhold
- * Eliminate block-local decls to simplify tracing and debugging.
- * Support another case of realloc via move into top
- * Fix error occuring when initial sbrk_base not word-aligned.
- * Rely on page size for units instead of SBRK_UNIT to
- avoid surprises about sbrk alignment conventions.
- * Add mallinfo, mallopt. Thanks to Raymond Nijssen
- (raymond@es.ele.tue.nl) for the suggestion.
- * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
- * More precautions for cases where other routines call sbrk,
- courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
- * Added macros etc., allowing use in linux libc from
- H.J. Lu (hjl@gnu.ai.mit.edu)
- * Inverted this history list
-
- V2.6.1 Sat Dec 2 14:10:57 1995 Doug Lea (dl at gee)
- * Re-tuned and fixed to behave more nicely with V2.6.0 changes.
- * Removed all preallocation code since under current scheme
- the work required to undo bad preallocations exceeds
- the work saved in good cases for most test programs.
- * No longer use return list or unconsolidated bins since
- no scheme using them consistently outperforms those that don't
- given above changes.
- * Use best fit for very large chunks to prevent some worst-cases.
- * Added some support for debugging
-
- V2.6.0 Sat Nov 4 07:05:23 1995 Doug Lea (dl at gee)
- * Removed footers when chunks are in use. Thanks to
- Paul Wilson (wilson@cs.texas.edu) for the suggestion.
-
- V2.5.4 Wed Nov 1 07:54:51 1995 Doug Lea (dl at gee)
- * Added malloc_trim, with help from Wolfram Gloger
- (wmglo@Dent.MED.Uni-Muenchen.DE).
-
- V2.5.3 Tue Apr 26 10:16:01 1994 Doug Lea (dl at g)
-
- V2.5.2 Tue Apr 5 16:20:40 1994 Doug Lea (dl at g)
- * realloc: try to expand in both directions
- * malloc: swap order of clean-bin strategy;
- * realloc: only conditionally expand backwards
- * Try not to scavenge used bins
- * Use bin counts as a guide to preallocation
- * Occasionally bin return list chunks in first scan
- * Add a few optimizations from colin@nyx10.cs.du.edu
-
- V2.5.1 Sat Aug 14 15:40:43 1993 Doug Lea (dl at g)
- * faster bin computation & slightly different binning
- * merged all consolidations to one part of malloc proper
- (eliminating old malloc_find_space & malloc_clean_bin)
- * Scan 2 returns chunks (not just 1)
- * Propagate failure in realloc if malloc returns 0
- * Add stuff to allow compilation on non-ANSI compilers
- from kpv@research.att.com
-
- V2.5 Sat Aug 7 07:41:59 1993 Doug Lea (dl at g.oswego.edu)
- * removed potential for odd address access in prev_chunk
- * removed dependency on getpagesize.h
- * misc cosmetics and a bit more internal documentation
- * anticosmetics: mangled names in macros to evade debugger strangeness
- * tested on sparc, hp-700, dec-mips, rs6000
- with gcc & native cc (hp, dec only) allowing
- Detlefs & Zorn comparison study (in SIGPLAN Notices.)
-
- Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu)
- * Based loosely on libg++-1.2X malloc. (It retains some of the overall
- structure of old version, but most details differ.)
-
-*/
-
diff --git a/unsupported/test/mpreal/dlmalloc.h b/unsupported/test/mpreal/dlmalloc.h
deleted file mode 100755
index a90dcb6f5..000000000
--- a/unsupported/test/mpreal/dlmalloc.h
+++ /dev/null
@@ -1,562 +0,0 @@
-/*
- Default header file for malloc-2.8.x, written by Doug Lea
- and released to the public domain, as explained at
- http://creativecommons.org/licenses/publicdomain.
-
- last update: Wed May 27 14:25:17 2009 Doug Lea (dl at gee)
-
- This header is for ANSI C/C++ only. You can set any of
- the following #defines before including:
-
- * If USE_DL_PREFIX is defined, it is assumed that malloc.c
- was also compiled with this option, so all routines
- have names starting with "dl".
-
- * If HAVE_USR_INCLUDE_MALLOC_H is defined, it is assumed that this
- file will be #included AFTER <malloc.h>. This is needed only if
- your system defines a struct mallinfo that is incompatible with the
- standard one declared here. Otherwise, you can include this file
- INSTEAD of your system system <malloc.h>. At least on ANSI, all
- declarations should be compatible with system versions
-
- * If MSPACES is defined, declarations for mspace versions are included.
-*/
-
-#ifndef MALLOC_280_H
-#define MALLOC_280_H
-
-#define USE_DL_PREFIX
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stddef.h> /* for size_t */
-
-#ifndef ONLY_MSPACES
-#define ONLY_MSPACES 0 /* define to a value */
-#endif /* ONLY_MSPACES */
-#ifndef NO_MALLINFO
-#define NO_MALLINFO 0
-#endif /* NO_MALLINFO */
-
-
-#if !ONLY_MSPACES
-
-#ifndef USE_DL_PREFIX
-#define dlcalloc calloc
-#define dlfree free
-#define dlmalloc malloc
-#define dlmemalign memalign
-#define dlrealloc realloc
-#define dlvalloc valloc
-#define dlpvalloc pvalloc
-#define dlmallinfo mallinfo
-#define dlmallopt mallopt
-#define dlmalloc_trim malloc_trim
-#define dlmalloc_stats malloc_stats
-#define dlmalloc_usable_size malloc_usable_size
-#define dlmalloc_footprint malloc_footprint
-#define dlindependent_calloc independent_calloc
-#define dlindependent_comalloc independent_comalloc
-#endif /* USE_DL_PREFIX */
-#if !NO_MALLINFO
-#ifndef HAVE_USR_INCLUDE_MALLOC_H
-#ifndef _MALLOC_H
-#ifndef MALLINFO_FIELD_TYPE
-#define MALLINFO_FIELD_TYPE size_t
-#endif /* MALLINFO_FIELD_TYPE */
-#ifndef STRUCT_MALLINFO_DECLARED
-#define STRUCT_MALLINFO_DECLARED 1
-struct mallinfo {
- MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */
- MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */
- MALLINFO_FIELD_TYPE smblks; /* always 0 */
- MALLINFO_FIELD_TYPE hblks; /* always 0 */
- MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */
- MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */
- MALLINFO_FIELD_TYPE fsmblks; /* always 0 */
- MALLINFO_FIELD_TYPE uordblks; /* total allocated space */
- MALLINFO_FIELD_TYPE fordblks; /* total free space */
- MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */
-};
-#endif /* STRUCT_MALLINFO_DECLARED */
-#endif /* _MALLOC_H */
-#endif /* HAVE_USR_INCLUDE_MALLOC_H */
-#endif /* !NO_MALLINFO */
-
-/*
- malloc(size_t n)
- Returns a pointer to a newly allocated chunk of at least n bytes, or
- null if no space is available, in which case errno is set to ENOMEM
- on ANSI C systems.
-
- If n is zero, malloc returns a minimum-sized chunk. (The minimum
- size is 16 bytes on most 32bit systems, and 32 bytes on 64bit
- systems.) Note that size_t is an unsigned type, so calls with
- arguments that would be negative if signed are interpreted as
- requests for huge amounts of space, which will often fail. The
- maximum supported value of n differs across systems, but is in all
- cases less than the maximum representable value of a size_t.
-*/
-void* dlmalloc(size_t);
-
-/*
- free(void* p)
- Releases the chunk of memory pointed to by p, that had been previously
- allocated using malloc or a related routine such as realloc.
- It has no effect if p is null. If p was not malloced or already
- freed, free(p) will by default cuase the current program to abort.
-*/
-void dlfree(void*);
-
-/*
- calloc(size_t n_elements, size_t element_size);
- Returns a pointer to n_elements * element_size bytes, with all locations
- set to zero.
-*/
-void* dlcalloc(size_t, size_t);
-
-/*
- realloc(void* p, size_t n)
- Returns a pointer to a chunk of size n that contains the same data
- as does chunk p up to the minimum of (n, p's size) bytes, or null
- if no space is available.
-
- The returned pointer may or may not be the same as p. The algorithm
- prefers extending p in most cases when possible, otherwise it
- employs the equivalent of a malloc-copy-free sequence.
-
- If p is null, realloc is equivalent to malloc.
-
- If space is not available, realloc returns null, errno is set (if on
- ANSI) and p is NOT freed.
-
- if n is for fewer bytes than already held by p, the newly unused
- space is lopped off and freed if possible. realloc with a size
- argument of zero (re)allocates a minimum-sized chunk.
-
- The old unix realloc convention of allowing the last-free'd chunk
- to be used as an argument to realloc is not supported.
-*/
-
-void* dlrealloc(void*, size_t);
-
-/*
- memalign(size_t alignment, size_t n);
- Returns a pointer to a newly allocated chunk of n bytes, aligned
- in accord with the alignment argument.
-
- The alignment argument should be a power of two. If the argument is
- not a power of two, the nearest greater power is used.
- 8-byte alignment is guaranteed by normal malloc calls, so don't
- bother calling memalign with an argument of 8 or less.
-
- Overreliance on memalign is a sure way to fragment space.
-*/
-void* dlmemalign(size_t, size_t);
-
-/*
- valloc(size_t n);
- Equivalent to memalign(pagesize, n), where pagesize is the page
- size of the system. If the pagesize is unknown, 4096 is used.
-*/
-void* dlvalloc(size_t);
-
-/*
- mallopt(int parameter_number, int parameter_value)
- Sets tunable parameters The format is to provide a
- (parameter-number, parameter-value) pair. mallopt then sets the
- corresponding parameter to the argument value if it can (i.e., so
- long as the value is meaningful), and returns 1 if successful else
- 0. SVID/XPG/ANSI defines four standard param numbers for mallopt,
- normally defined in malloc.h. None of these are use in this malloc,
- so setting them has no effect. But this malloc also supports other
- options in mallopt:
-
- Symbol param # default allowed param values
- M_TRIM_THRESHOLD -1 2*1024*1024 any (-1U disables trimming)
- M_GRANULARITY -2 page size any power of 2 >= page size
- M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support)
-*/
-int dlmallopt(int, int);
-
-#define M_TRIM_THRESHOLD (-1)
-#define M_GRANULARITY (-2)
-#define M_MMAP_THRESHOLD (-3)
-
-
-/*
- malloc_footprint();
- Returns the number of bytes obtained from the system. The total
- number of bytes allocated by malloc, realloc etc., is less than this
- value. Unlike mallinfo, this function returns only a precomputed
- result, so can be called frequently to monitor memory consumption.
- Even if locks are otherwise defined, this function does not use them,
- so results might not be up to date.
-*/
-size_t dlmalloc_footprint();
-
-#if !NO_MALLINFO
-/*
- mallinfo()
- Returns (by copy) a struct containing various summary statistics:
-
- arena: current total non-mmapped bytes allocated from system
- ordblks: the number of free chunks
- smblks: always zero.
- hblks: current number of mmapped regions
- hblkhd: total bytes held in mmapped regions
- usmblks: the maximum total allocated space. This will be greater
- than current total if trimming has occurred.
- fsmblks: always zero
- uordblks: current total allocated space (normal or mmapped)
- fordblks: total free space
- keepcost: the maximum number of bytes that could ideally be released
- back to system via malloc_trim. ("ideally" means that
- it ignores page restrictions etc.)
-
- Because these fields are ints, but internal bookkeeping may
- be kept as longs, the reported values may wrap around zero and
- thus be inaccurate.
-*/
-
-struct mallinfo dlmallinfo(void);
-#endif /* NO_MALLINFO */
-
-/*
- independent_calloc(size_t n_elements, size_t element_size, void* chunks[]);
-
- independent_calloc is similar to calloc, but instead of returning a
- single cleared space, it returns an array of pointers to n_elements
- independent elements that can hold contents of size elem_size, each
- of which starts out cleared, and can be independently freed,
- realloc'ed etc. The elements are guaranteed to be adjacently
- allocated (this is not guaranteed to occur with multiple callocs or
- mallocs), which may also improve cache locality in some
- applications.
-
- The "chunks" argument is optional (i.e., may be null, which is
- probably the most typical usage). If it is null, the returned array
- is itself dynamically allocated and should also be freed when it is
- no longer needed. Otherwise, the chunks array must be of at least
- n_elements in length. It is filled in with the pointers to the
- chunks.
-
- In either case, independent_calloc returns this pointer array, or
- null if the allocation failed. If n_elements is zero and "chunks"
- is null, it returns a chunk representing an array with zero elements
- (which should be freed if not wanted).
-
- Each element must be individually freed when it is no longer
- needed. If you'd like to instead be able to free all at once, you
- should instead use regular calloc and assign pointers into this
- space to represent elements. (In this case though, you cannot
- independently free elements.)
-
- independent_calloc simplifies and speeds up implementations of many
- kinds of pools. It may also be useful when constructing large data
- structures that initially have a fixed number of fixed-sized nodes,
- but the number is not known at compile time, and some of the nodes
- may later need to be freed. For example:
-
- struct Node { int item; struct Node* next; };
-
- struct Node* build_list() {
- struct Node** pool;
- int n = read_number_of_nodes_needed();
- if (n <= 0) return 0;
- pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0);
- if (pool == 0) die();
- // organize into a linked list...
- struct Node* first = pool[0];
- for (i = 0; i < n-1; ++i)
- pool[i]->next = pool[i+1];
- free(pool); // Can now free the array (or not, if it is needed later)
- return first;
- }
-*/
-void** dlindependent_calloc(size_t, size_t, void**);
-
-/*
- independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]);
-
- independent_comalloc allocates, all at once, a set of n_elements
- chunks with sizes indicated in the "sizes" array. It returns
- an array of pointers to these elements, each of which can be
- independently freed, realloc'ed etc. The elements are guaranteed to
- be adjacently allocated (this is not guaranteed to occur with
- multiple callocs or mallocs), which may also improve cache locality
- in some applications.
-
- The "chunks" argument is optional (i.e., may be null). If it is null
- the returned array is itself dynamically allocated and should also
- be freed when it is no longer needed. Otherwise, the chunks array
- must be of at least n_elements in length. It is filled in with the
- pointers to the chunks.
-
- In either case, independent_comalloc returns this pointer array, or
- null if the allocation failed. If n_elements is zero and chunks is
- null, it returns a chunk representing an array with zero elements
- (which should be freed if not wanted).
-
- Each element must be individually freed when it is no longer
- needed. If you'd like to instead be able to free all at once, you
- should instead use a single regular malloc, and assign pointers at
- particular offsets in the aggregate space. (In this case though, you
- cannot independently free elements.)
-
- independent_comallac differs from independent_calloc in that each
- element may have a different size, and also that it does not
- automatically clear elements.
-
- independent_comalloc can be used to speed up allocation in cases
- where several structs or objects must always be allocated at the
- same time. For example:
-
- struct Head { ... }
- struct Foot { ... }
-
- void send_message(char* msg) {
- int msglen = strlen(msg);
- size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) };
- void* chunks[3];
- if (independent_comalloc(3, sizes, chunks) == 0)
- die();
- struct Head* head = (struct Head*)(chunks[0]);
- char* body = (char*)(chunks[1]);
- struct Foot* foot = (struct Foot*)(chunks[2]);
- // ...
- }
-
- In general though, independent_comalloc is worth using only for
- larger values of n_elements. For small values, you probably won't
- detect enough difference from series of malloc calls to bother.
-
- Overuse of independent_comalloc can increase overall memory usage,
- since it cannot reuse existing noncontiguous small chunks that
- might be available for some of the elements.
-*/
-void** dlindependent_comalloc(size_t, size_t*, void**);
-
-
-/*
- pvalloc(size_t n);
- Equivalent to valloc(minimum-page-that-holds(n)), that is,
- round up n to nearest pagesize.
- */
-void* dlpvalloc(size_t);
-
-/*
- malloc_trim(size_t pad);
-
- If possible, gives memory back to the system (via negative arguments
- to sbrk) if there is unused memory at the `high' end of the malloc
- pool or in unused MMAP segments. You can call this after freeing
- large blocks of memory to potentially reduce the system-level memory
- requirements of a program. However, it cannot guarantee to reduce
- memory. Under some allocation patterns, some large free blocks of
- memory will be locked between two used chunks, so they cannot be
- given back to the system.
-
- The `pad' argument to malloc_trim represents the amount of free
- trailing space to leave untrimmed. If this argument is zero, only
- the minimum amount of memory to maintain internal data structures
- will be left. Non-zero arguments can be supplied to maintain enough
- trailing space to service future expected allocations without having
- to re-obtain memory from the system.
-
- Malloc_trim returns 1 if it actually released any memory, else 0.
-*/
-int dlmalloc_trim(size_t);
-
-/*
- malloc_stats();
- Prints on stderr the amount of space obtained from the system (both
- via sbrk and mmap), the maximum amount (which may be more than
- current if malloc_trim and/or munmap got called), and the current
- number of bytes allocated via malloc (or realloc, etc) but not yet
- freed. Note that this is the number of bytes allocated, not the
- number requested. It will be larger than the number requested
- because of alignment and bookkeeping overhead. Because it includes
- alignment wastage as being in use, this figure may be greater than
- zero even when no user-level chunks are allocated.
-
- The reported current and maximum system memory can be inaccurate if
- a program makes other calls to system memory allocation functions
- (normally sbrk) outside of malloc.
-
- malloc_stats prints only the most commonly interesting statistics.
- More information can be obtained by calling mallinfo.
-*/
-void dlmalloc_stats();
-
-#endif /* !ONLY_MSPACES */
-
-/*
- malloc_usable_size(void* p);
-
- Returns the number of bytes you can actually use in
- an allocated chunk, which may be more than you requested (although
- often not) due to alignment and minimum size constraints.
- You can use this many bytes without worrying about
- overwriting other allocated objects. This is not a particularly great
- programming practice. malloc_usable_size can be more useful in
- debugging and assertions, for example:
-
- p = malloc(n);
- assert(malloc_usable_size(p) >= 256);
-*/
-size_t dlmalloc_usable_size(void*);
-
-
-#if MSPACES
-
-/*
- mspace is an opaque type representing an independent
- region of space that supports mspace_malloc, etc.
-*/
-typedef void* mspace;
-
-/*
- create_mspace creates and returns a new independent space with the
- given initial capacity, or, if 0, the default granularity size. It
- returns null if there is no system memory available to create the
- space. If argument locked is non-zero, the space uses a separate
- lock to control access. The capacity of the space will grow
- dynamically as needed to service mspace_malloc requests. You can
- control the sizes of incremental increases of this space by
- compiling with a different DEFAULT_GRANULARITY or dynamically
- setting with mallopt(M_GRANULARITY, value).
-*/
-mspace create_mspace(size_t capacity, int locked);
-
-/*
- destroy_mspace destroys the given space, and attempts to return all
- of its memory back to the system, returning the total number of
- bytes freed. After destruction, the results of access to all memory
- used by the space become undefined.
-*/
-size_t destroy_mspace(mspace msp);
-
-/*
- create_mspace_with_base uses the memory supplied as the initial base
- of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this
- space is used for bookkeeping, so the capacity must be at least this
- large. (Otherwise 0 is returned.) When this initial space is
- exhausted, additional memory will be obtained from the system.
- Destroying this space will deallocate all additionally allocated
- space (if possible) but not the initial base.
-*/
-mspace create_mspace_with_base(void* base, size_t capacity, int locked);
-
-/*
- mspace_track_large_chunks controls whether requests for large chunks
- are allocated in their own untracked mmapped regions, separate from
- others in this mspace. By default large chunks are not tracked,
- which reduces fragmentation. However, such chunks are not
- necessarily released to the system upon destroy_mspace. Enabling
- tracking by setting to true may increase fragmentation, but avoids
- leakage when relying on destroy_mspace to release all memory
- allocated using this space. The function returns the previous
- setting.
-*/
-int mspace_track_large_chunks(mspace msp, int enable);
-
-/*
- mspace_malloc behaves as malloc, but operates within
- the given space.
-*/
-void* mspace_malloc(mspace msp, size_t bytes);
-
-/*
- mspace_free behaves as free, but operates within
- the given space.
-
- If compiled with FOOTERS==1, mspace_free is not actually needed.
- free may be called instead of mspace_free because freed chunks from
- any space are handled by their originating spaces.
-*/
-void mspace_free(mspace msp, void* mem);
-
-/*
- mspace_realloc behaves as realloc, but operates within
- the given space.
-
- If compiled with FOOTERS==1, mspace_realloc is not actually
- needed. realloc may be called instead of mspace_realloc because
- realloced chunks from any space are handled by their originating
- spaces.
-*/
-void* mspace_realloc(mspace msp, void* mem, size_t newsize);
-
-/*
- mspace_calloc behaves as calloc, but operates within
- the given space.
-*/
-void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size);
-
-/*
- mspace_memalign behaves as memalign, but operates within
- the given space.
-*/
-void* mspace_memalign(mspace msp, size_t alignment, size_t bytes);
-
-/*
- mspace_independent_calloc behaves as independent_calloc, but
- operates within the given space.
-*/
-void** mspace_independent_calloc(mspace msp, size_t n_elements,
- size_t elem_size, void* chunks[]);
-
-/*
- mspace_independent_comalloc behaves as independent_comalloc, but
- operates within the given space.
-*/
-void** mspace_independent_comalloc(mspace msp, size_t n_elements,
- size_t sizes[], void* chunks[]);
-
-/*
- mspace_footprint() returns the number of bytes obtained from the
- system for this space.
-*/
-size_t mspace_footprint(mspace msp);
-
-
-#if !NO_MALLINFO
-/*
- mspace_mallinfo behaves as mallinfo, but reports properties of
- the given space.
-*/
-struct mallinfo mspace_mallinfo(mspace msp);
-#endif /* NO_MALLINFO */
-
-/*
- malloc_usable_size(void* p) behaves the same as malloc_usable_size;
-*/
- size_t mspace_usable_size(void* mem);
-
-/*
- mspace_malloc_stats behaves as malloc_stats, but reports
- properties of the given space.
-*/
-void mspace_malloc_stats(mspace msp);
-
-/*
- mspace_trim behaves as malloc_trim, but
- operates within the given space.
-*/
-int mspace_trim(mspace msp, size_t pad);
-
-/*
- An alias for mallopt.
-*/
-int mspace_mallopt(int, int);
-
-#endif /* MSPACES */
-
-#ifdef __cplusplus
-}; /* end of extern "C" */
-#endif
-
-#endif /* MALLOC_280_H */
diff --git a/unsupported/test/mpreal/mpreal.cpp b/unsupported/test/mpreal/mpreal.cpp
deleted file mode 100644
index 5c23544ef..000000000
--- a/unsupported/test/mpreal/mpreal.cpp
+++ /dev/null
@@ -1,597 +0,0 @@
-/*
- Multi-precision real number class. C++ interface fo MPFR library.
- Project homepage: http://www.holoborodko.com/pavel/
- Contact e-mail: pavel@holoborodko.com
-
- Copyright (c) 2008-2011 Pavel Holoborodko
-
- Core Developers:
- Pavel Holoborodko, Dmitriy Gubanov, Konstantin Holoborodko.
-
- Contributors:
- Brian Gladman, Helmut Jarausch, Fokko Beekhof, Ulrich Mutze,
- Heinz van Saanen, Pere Constans, Peter van Hoof, Gael Guennebaud,
- Tsai Chia Cheng, Alexei Zubanov.
-
- ****************************************************************************
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- ****************************************************************************
- ****************************************************************************
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- 3. The name of the author may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- SUCH DAMAGE.
-*/
-#include <cstring>
-#include "mpreal.h"
-
-#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
-#include "dlmalloc.h"
-#endif
-
-using std::ws;
-using std::cerr;
-using std::endl;
-using std::string;
-using std::ostream;
-using std::istream;
-
-namespace mpfr{
-
-mp_rnd_t mpreal::default_rnd = MPFR_RNDN; //(mpfr_get_default_rounding_mode)();
-mp_prec_t mpreal::default_prec = 64; //(mpfr_get_default_prec)();
-int mpreal::default_base = 10;
-int mpreal::double_bits = -1;
-
-#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
-bool mpreal::is_custom_malloc = false;
-#endif
-
-// Default constructor: creates mp number and initializes it to 0.
-mpreal::mpreal()
-{
-
-#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
- set_custom_malloc();
-#endif
-
- mpfr_init2(mp,default_prec);
- mpfr_set_ui(mp,0,default_rnd);
-
- MPREAL_MSVC_DEBUGVIEW_CODE;
-}
-
-mpreal::mpreal(const mpreal& u)
-{
-
-#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
- set_custom_malloc();
-#endif
-
- mpfr_init2(mp,mpfr_get_prec(u.mp));
- mpfr_set(mp,u.mp,default_rnd);
-
- MPREAL_MSVC_DEBUGVIEW_CODE;
-}
-
-mpreal::mpreal(const mpfr_t u)
-{
-
-#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
- set_custom_malloc();
-#endif
-
- mpfr_init2(mp,mpfr_get_prec(u));
- mpfr_set(mp,u,default_rnd);
-
- MPREAL_MSVC_DEBUGVIEW_CODE;
-}
-
-mpreal::mpreal(const mpf_t u)
-{
-
-#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
- set_custom_malloc();
-#endif
-
- mpfr_init2(mp,(mp_prec_t) mpf_get_prec(u)); // (gmp: mp_bitcnt_t) unsigned long -> long (mpfr: mp_prec_t)
- mpfr_set_f(mp,u,default_rnd);
-
- MPREAL_MSVC_DEBUGVIEW_CODE;
-}
-
-mpreal::mpreal(const mpz_t u, mp_prec_t prec, mp_rnd_t mode)
-{
-
-#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
- set_custom_malloc();
-#endif
-
- mpfr_init2(mp,prec);
- mpfr_set_z(mp,u,mode);
-
- MPREAL_MSVC_DEBUGVIEW_CODE;
-}
-
-mpreal::mpreal(const mpq_t u, mp_prec_t prec, mp_rnd_t mode)
-{
-
-#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
- set_custom_malloc();
-#endif
-
- mpfr_init2(mp,prec);
- mpfr_set_q(mp,u,mode);
-
- MPREAL_MSVC_DEBUGVIEW_CODE;
-}
-
-mpreal::mpreal(const double u, mp_prec_t prec, mp_rnd_t mode)
-{
-
-#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
- set_custom_malloc();
-#endif
-
- if(double_bits == -1 || fits_in_bits(u, double_bits))
- {
- mpfr_init2(mp,prec);
- mpfr_set_d(mp,u,mode);
-
- MPREAL_MSVC_DEBUGVIEW_CODE;
- }
- else
- throw conversion_overflow();
-}
-
-mpreal::mpreal(const long double u, mp_prec_t prec, mp_rnd_t mode)
-{
-
-#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
- set_custom_malloc();
-#endif
-
- mpfr_init2(mp,prec);
- mpfr_set_ld(mp,u,mode);
-
- MPREAL_MSVC_DEBUGVIEW_CODE;
-}
-
-mpreal::mpreal(const unsigned long int u, mp_prec_t prec, mp_rnd_t mode)
-{
-
-#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
- set_custom_malloc();
-#endif
-
- mpfr_init2(mp,prec);
- mpfr_set_ui(mp,u,mode);
-
- MPREAL_MSVC_DEBUGVIEW_CODE;
-}
-
-mpreal::mpreal(const unsigned int u, mp_prec_t prec, mp_rnd_t mode)
-{
-
-#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
- set_custom_malloc();
-#endif
-
- mpfr_init2(mp,prec);
- mpfr_set_ui(mp,u,mode);
-
- MPREAL_MSVC_DEBUGVIEW_CODE;
-}
-
-mpreal::mpreal(const long int u, mp_prec_t prec, mp_rnd_t mode)
-{
-
-#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
- set_custom_malloc();
-#endif
-
- mpfr_init2(mp,prec);
- mpfr_set_si(mp,u,mode);
-
- MPREAL_MSVC_DEBUGVIEW_CODE;
-}
-
-mpreal::mpreal(const int u, mp_prec_t prec, mp_rnd_t mode)
-{
-
-#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
- set_custom_malloc();
-#endif
-
- mpfr_init2(mp,prec);
- mpfr_set_si(mp,u,mode);
-
- MPREAL_MSVC_DEBUGVIEW_CODE;
-}
-
-#if defined (MPREAL_HAVE_INT64_SUPPORT)
-mpreal::mpreal(const uint64_t u, mp_prec_t prec, mp_rnd_t mode)
-{
-
-#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
- set_custom_malloc();
-#endif
-
- mpfr_init2(mp,prec);
- mpfr_set_uj(mp, u, mode);
-
- MPREAL_MSVC_DEBUGVIEW_CODE;
-}
-
-mpreal::mpreal(const int64_t u, mp_prec_t prec, mp_rnd_t mode)
-{
-
-#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
- set_custom_malloc();
-#endif
-
- mpfr_init2(mp,prec);
- mpfr_set_sj(mp, u, mode);
-
- MPREAL_MSVC_DEBUGVIEW_CODE;
-}
-#endif
-
-mpreal::mpreal(const char* s, mp_prec_t prec, int base, mp_rnd_t mode)
-{
-
-#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
- set_custom_malloc();
-#endif
-
- mpfr_init2(mp,prec);
- mpfr_set_str(mp, s, base, mode);
-
- MPREAL_MSVC_DEBUGVIEW_CODE;
-}
-
-mpreal::mpreal(const std::string& s, mp_prec_t prec, int base, mp_rnd_t mode)
-{
-
-#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
- set_custom_malloc();
-#endif
-
- mpfr_init2(mp,prec);
- mpfr_set_str(mp, s.c_str(), base, mode);
-
- MPREAL_MSVC_DEBUGVIEW_CODE;
-}
-
-mpreal::~mpreal()
-{
- mpfr_clear(mp);
-}
-
-// Operators - Assignment
-mpreal& mpreal::operator=(const char* s)
-{
- mpfr_t t;
-
-#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
- set_custom_malloc();
-#endif
-
- if(0==mpfr_init_set_str(t,s,default_base,default_rnd))
- {
- // We will rewrite mp anyway, so flash it and resize
- mpfr_set_prec(mp,mpfr_get_prec(t));
- mpfr_set(mp,t,mpreal::default_rnd);
- mpfr_clear(t);
-
- MPREAL_MSVC_DEBUGVIEW_CODE;
-
- }else{
- mpfr_clear(t);
- }
-
- return *this;
-}
-
-const mpreal fma (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode)
-{
- mpreal a;
- mp_prec_t p1, p2, p3;
-
- p1 = v1.get_prec();
- p2 = v2.get_prec();
- p3 = v3.get_prec();
-
- a.set_prec(p3>p2?(p3>p1?p3:p1):(p2>p1?p2:p1));
-
- mpfr_fma(a.mp,v1.mp,v2.mp,v3.mp,rnd_mode);
- return a;
-}
-
-const mpreal fms (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode)
-{
- mpreal a;
- mp_prec_t p1, p2, p3;
-
- p1 = v1.get_prec();
- p2 = v2.get_prec();
- p3 = v3.get_prec();
-
- a.set_prec(p3>p2?(p3>p1?p3:p1):(p2>p1?p2:p1));
-
- mpfr_fms(a.mp,v1.mp,v2.mp,v3.mp,rnd_mode);
- return a;
-}
-
-const mpreal agm (const mpreal& v1, const mpreal& v2, mp_rnd_t rnd_mode)
-{
- mpreal a;
- mp_prec_t p1, p2;
-
- p1 = v1.get_prec();
- p2 = v2.get_prec();
-
- a.set_prec(p1>p2?p1:p2);
-
- mpfr_agm(a.mp, v1.mp, v2.mp, rnd_mode);
-
- return a;
-}
-
-const mpreal sum (const mpreal tab[], unsigned long int n, mp_rnd_t rnd_mode)
-{
- mpreal x;
- mpfr_ptr* t;
- unsigned long int i;
-
- t = new mpfr_ptr[n];
- for (i=0;i<n;i++) t[i] = (mpfr_ptr)tab[i].mp;
- mpfr_sum(x.mp,t,n,rnd_mode);
- delete[] t;
- return x;
-}
-
-const mpreal remquo (long* q, const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
-{
- mpreal a;
- mp_prec_t yp, xp;
-
- yp = y.get_prec();
- xp = x.get_prec();
-
- a.set_prec(yp>xp?yp:xp);
-
- mpfr_remquo(a.mp,q, x.mp, y.mp, rnd_mode);
-
- return a;
-}
-
-template <class T>
-std::string toString(T t, std::ios_base & (*f)(std::ios_base&))
-{
- std::ostringstream oss;
- oss << f << t;
- return oss.str();
-}
-
-#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
-
-std::string mpreal::toString(const std::string& format) const
-{
- char *s = NULL;
- string out;
-
- if( !format.empty() )
- {
- if(!(mpfr_asprintf(&s,format.c_str(),mp) < 0))
- {
- out = std::string(s);
-
- mpfr_free_str(s);
- }
- }
-
- return out;
-}
-
-#endif
-
-std::string mpreal::toString(int n, int b, mp_rnd_t mode) const
-{
- (void)b;
- (void)mode;
-#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
-
- // Use MPFR native function for output
- char format[128];
- int digits;
-
- digits = n > 0 ? n : bits2digits(mpfr_get_prec(mp));
-
- sprintf(format,"%%.%dRNg",digits); // Default format
-
- return toString(std::string(format));
-
-#else
-
- char *s, *ns = NULL;
- size_t slen, nslen;
- mp_exp_t exp;
- string out;
-
-#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
- set_custom_malloc();
-#endif
-
- if(mpfr_inf_p(mp))
- {
- if(mpfr_sgn(mp)>0) return "+Inf";
- else return "-Inf";
- }
-
- if(mpfr_zero_p(mp)) return "0";
- if(mpfr_nan_p(mp)) return "NaN";
-
- s = mpfr_get_str(NULL,&exp,b,0,mp,mode);
- ns = mpfr_get_str(NULL,&exp,b,n,mp,mode);
-
- if(s!=NULL && ns!=NULL)
- {
- slen = strlen(s);
- nslen = strlen(ns);
- if(nslen<=slen)
- {
- mpfr_free_str(s);
- s = ns;
- slen = nslen;
- }
- else {
- mpfr_free_str(ns);
- }
-
- // Make human eye-friendly formatting if possible
- if (exp>0 && static_cast<size_t>(exp)<slen)
- {
- if(s[0]=='-')
- {
- // Remove zeros starting from right end
- char* ptr = s+slen-1;
- while (*ptr=='0' && ptr>s+exp) ptr--;
-
- if(ptr==s+exp) out = string(s,exp+1);
- else out = string(s,exp+1)+'.'+string(s+exp+1,ptr-(s+exp+1)+1);
-
- //out = string(s,exp+1)+'.'+string(s+exp+1);
- }
- else
- {
- // Remove zeros starting from right end
- char* ptr = s+slen-1;
- while (*ptr=='0' && ptr>s+exp-1) ptr--;
-
- if(ptr==s+exp-1) out = string(s,exp);
- else out = string(s,exp)+'.'+string(s+exp,ptr-(s+exp)+1);
-
- //out = string(s,exp)+'.'+string(s+exp);
- }
-
- }else{ // exp<0 || exp>slen
- if(s[0]=='-')
- {
- // Remove zeros starting from right end
- char* ptr = s+slen-1;
- while (*ptr=='0' && ptr>s+1) ptr--;
-
- if(ptr==s+1) out = string(s,2);
- else out = string(s,2)+'.'+string(s+2,ptr-(s+2)+1);
-
- //out = string(s,2)+'.'+string(s+2);
- }
- else
- {
- // Remove zeros starting from right end
- char* ptr = s+slen-1;
- while (*ptr=='0' && ptr>s) ptr--;
-
- if(ptr==s) out = string(s,1);
- else out = string(s,1)+'.'+string(s+1,ptr-(s+1)+1);
-
- //out = string(s,1)+'.'+string(s+1);
- }
-
- // Make final string
- if(--exp)
- {
- if(exp>0) out += "e+"+mpfr::toString<mp_exp_t>(exp,std::dec);
- else out += "e"+mpfr::toString<mp_exp_t>(exp,std::dec);
- }
- }
-
- mpfr_free_str(s);
- return out;
- }else{
- return "conversion error!";
- }
-#endif
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-// I/O
-ostream& operator<<(ostream& os, const mpreal& v)
-{
- return os<<v.toString(static_cast<int>(os.precision()));
-}
-
-istream& operator>>(istream &is, mpreal& v)
-{
- string tmp;
- is >> tmp;
- mpfr_set_str(v.mp, tmp.c_str(),mpreal::default_base,mpreal::default_rnd);
- return is;
-}
-
-
-#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
- // Optimized dynamic memory allocation/(re-)deallocation.
- void * mpreal::mpreal_allocate(size_t alloc_size)
- {
- return(dlmalloc(alloc_size));
- }
-
- void * mpreal::mpreal_reallocate(void *ptr, size_t old_size, size_t new_size)
- {
- return(dlrealloc(ptr,new_size));
- }
-
- void mpreal::mpreal_free(void *ptr, size_t size)
- {
- dlfree(ptr);
- }
-
- inline void mpreal::set_custom_malloc(void)
- {
- if(!is_custom_malloc)
- {
- mp_set_memory_functions(mpreal_allocate,mpreal_reallocate,mpreal_free);
- is_custom_malloc = true;
- }
- }
-#endif
-
-}
-
diff --git a/unsupported/test/mpreal/mpreal.h b/unsupported/test/mpreal/mpreal.h
index c640af947..ef0a6a9f0 100644
--- a/unsupported/test/mpreal/mpreal.h
+++ b/unsupported/test/mpreal/mpreal.h
@@ -1,59 +1,59 @@
/*
- Multi-precision real number class. C++ interface for MPFR library.
- Project homepage: http://www.holoborodko.com/pavel/
- Contact e-mail: pavel@holoborodko.com
-
- Copyright (c) 2008-2012 Pavel Holoborodko
-
- Core Developers:
- Pavel Holoborodko, Dmitriy Gubanov, Konstantin Holoborodko.
-
- Contributors:
- Brian Gladman, Helmut Jarausch, Fokko Beekhof, Ulrich Mutze,
- Heinz van Saanen, Pere Constans, Peter van Hoof, Gael Guennebaud,
- Tsai Chia Cheng, Alexei Zubanov.
-
- ****************************************************************************
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- ****************************************************************************
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- 3. The name of the author may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- SUCH DAMAGE.
+ Multi-precision floating point number class for C++.
+ Based on MPFR library: http://mpfr.org
+
+ Project homepage: http://www.holoborodko.com/pavel/mpfr
+ Contact e-mail: pavel@holoborodko.com
+
+ Copyright (c) 2008-2012 Pavel Holoborodko
+
+ Contributors:
+ Dmitriy Gubanov, Konstantin Holoborodko, Brian Gladman,
+ Helmut Jarausch, Fokko Beekhof, Ulrich Mutze, Heinz van Saanen,
+ Pere Constans, Peter van Hoof, Gael Guennebaud, Tsai Chia Cheng,
+ Alexei Zubanov, Jauhien Piatlicki, Victor Berger, John Westwood.
+
+ ****************************************************************************
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ ****************************************************************************
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
*/
#ifndef __MPREAL_H__
@@ -65,627 +65,785 @@
#include <stdexcept>
#include <cfloat>
#include <cmath>
+#include <limits>
// Options
-#define MPREAL_HAVE_INT64_SUPPORT // int64_t support: available only for MSVC 2010 & GCC
-#define MPREAL_HAVE_MSVC_DEBUGVIEW // Enable Debugger Visualizer (valid only for MSVC in "Debug" builds)
+#define MPREAL_HAVE_INT64_SUPPORT // Enable int64_t support if possible. Available only for MSVC 2010 & GCC.
+#define MPREAL_HAVE_MSVC_DEBUGVIEW // Enable Debugger Visualizer for "Debug" builds in MSVC.
// Detect compiler using signatures from http://predef.sourceforge.net/
#if defined(__GNUC__) && defined(__INTEL_COMPILER)
- #define IsInf(x) isinf(x) // Intel ICC compiler on Linux
-
-#elif defined(_MSC_VER) // Microsoft Visual C++
- #define IsInf(x) (!_finite(x))
+ #define IsInf(x) isinf(x) // Intel ICC compiler on Linux
-#elif defined(__GNUC__)
- #define IsInf(x) std::isinf(x) // GNU C/C++
+#elif defined(_MSC_VER) // Microsoft Visual C++
+ #define IsInf(x) (!_finite(x))
#else
- #define IsInf(x) std::isinf(x) // Unknown compiler, just hope for C99 conformance
+ #define IsInf(x) std::isinf(x) // GNU C/C++ (and/or other compilers), just hope for C99 conformance
#endif
#if defined(MPREAL_HAVE_INT64_SUPPORT)
-
- #define MPFR_USE_INTMAX_T // should be defined before mpfr.h
-
- #if defined(_MSC_VER) // <stdint.h> is available only in msvc2010!
- #if (_MSC_VER >= 1600)
- #include <stdint.h>
- #else // MPFR relies on intmax_t which is available only in msvc2010
- #undef MPREAL_HAVE_INT64_SUPPORT // Besides, MPFR - MPIR have to be compiled with msvc2010
- #undef MPFR_USE_INTMAX_T // Since we cannot detect this, disable x64 by default
- // Someone should change this manually if needed.
- #endif
- #endif
-
- #if defined (__MINGW32__) || defined(__MINGW64__)
- #include <stdint.h> // equivalent to msvc2010
- #elif defined (__GNUC__)
- #if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
- #undef MPREAL_HAVE_INT64_SUPPORT // remove all shaman dances for x64 builds since
- #undef MPFR_USE_INTMAX_T // GCC already support x64 as of "long int" is 64-bit integer, nothing left to do
- #else
- #include <stdint.h> // use int64_t, uint64_t otherwise.
- #endif
- #endif
+
+ #define MPFR_USE_INTMAX_T // Should be defined before mpfr.h
+
+ #if defined(_MSC_VER) // MSVC + Windows
+ #if (_MSC_VER >= 1600)
+ #include <stdint.h> // <stdint.h> is available only in msvc2010!
+
+ #else // MPFR relies on intmax_t which is available only in msvc2010
+ #undef MPREAL_HAVE_INT64_SUPPORT // Besides, MPFR & MPIR have to be compiled with msvc2010
+ #undef MPFR_USE_INTMAX_T // Since we cannot detect this, disable x64 by default
+ // Someone should change this manually if needed.
+ #endif
+
+ #elif defined (__GNUC__) && defined(__linux__)
+ #if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(__ia64) || defined(__itanium__) || defined(_M_IA64)
+ #undef MPREAL_HAVE_INT64_SUPPORT // Remove all shaman dances for x64 builds since
+ #undef MPFR_USE_INTMAX_T // GCC already supports x64 as of "long int" is 64-bit integer, nothing left to do
+ #else
+ #include <stdint.h> // use int64_t, uint64_t otherwise
+ #endif
+
+ #else
+ #include <stdint.h> // rely on int64_t, uint64_t in all other cases, Mac OSX, etc.
+ #endif
#endif
#if defined(MPREAL_HAVE_MSVC_DEBUGVIEW) && defined(_MSC_VER) && defined(_DEBUG)
-#define MPREAL_MSVC_DEBUGVIEW_CODE DebugView = toString()
- #define MPREAL_MSVC_DEBUGVIEW_DATA std::string DebugView
+#define MPREAL_MSVC_DEBUGVIEW_CODE DebugView = toString();
+ #define MPREAL_MSVC_DEBUGVIEW_DATA std::string DebugView;
#else
- #define MPREAL_MSVC_DEBUGVIEW_CODE
- #define MPREAL_MSVC_DEBUGVIEW_DATA
+ #define MPREAL_MSVC_DEBUGVIEW_CODE
+ #define MPREAL_MSVC_DEBUGVIEW_DATA
#endif
#include <mpfr.h>
#if (MPFR_VERSION < MPFR_VERSION_NUM(3,0,0))
- #include <cstdlib> // needed for random()
+ #include <cstdlib> // Needed for random()
+#endif
+
+// Less important options
+#define MPREAL_DOUBLE_BITS_OVERFLOW -1 // Triggers overflow exception during conversion to double if mpreal
+ // cannot fit in MPREAL_DOUBLE_BITS_OVERFLOW bits
+ // = -1 disables overflow checks (default)
+#if defined(__GNUC__)
+ #define MPREAL_PERMISSIVE_EXPR __extension__
+#else
+ #define MPREAL_PERMISSIVE_EXPR
#endif
namespace mpfr {
class mpreal {
private:
- mpfr_t mp;
-
-public:
- static mp_rnd_t default_rnd;
- static mp_prec_t default_prec;
- static int default_base;
- static int double_bits;
+ mpfr_t mp;
public:
- // Constructors && type conversion
- mpreal();
- mpreal(const mpreal& u);
- mpreal(const mpfr_t u);
- mpreal(const mpf_t u);
- mpreal(const mpz_t u, mp_prec_t prec = default_prec, mp_rnd_t mode = default_rnd);
- mpreal(const mpq_t u, mp_prec_t prec = default_prec, mp_rnd_t mode = default_rnd);
- mpreal(const double u, mp_prec_t prec = default_prec, mp_rnd_t mode = default_rnd);
- mpreal(const long double u, mp_prec_t prec = default_prec, mp_rnd_t mode = default_rnd);
- mpreal(const unsigned long int u, mp_prec_t prec = default_prec, mp_rnd_t mode = default_rnd);
- mpreal(const unsigned int u, mp_prec_t prec = default_prec, mp_rnd_t mode = default_rnd);
- mpreal(const long int u, mp_prec_t prec = default_prec, mp_rnd_t mode = default_rnd);
- mpreal(const int u, mp_prec_t prec = default_prec, mp_rnd_t mode = default_rnd);
+
+ // Get default rounding mode & precision
+ inline static mp_rnd_t get_default_rnd() { return (mp_rnd_t)(mpfr_get_default_rounding_mode()); }
+ inline static mp_prec_t get_default_prec() { return mpfr_get_default_prec(); }
+
+ // Constructors && type conversions
+ mpreal();
+ mpreal(const mpreal& u);
+ mpreal(const mpfr_t u);
+ mpreal(const mpf_t u);
+ mpreal(const mpz_t u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());
+ mpreal(const mpq_t u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());
+ mpreal(const double u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());
+ mpreal(const long double u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());
+ mpreal(const unsigned long int u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());
+ mpreal(const unsigned int u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());
+ mpreal(const long int u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());
+ mpreal(const int u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());
#if defined (MPREAL_HAVE_INT64_SUPPORT)
- mpreal(const uint64_t u, mp_prec_t prec = default_prec, mp_rnd_t mode = default_rnd);
- mpreal(const int64_t u, mp_prec_t prec = default_prec, mp_rnd_t mode = default_rnd);
+ mpreal(const uint64_t u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());
+ mpreal(const int64_t u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());
#endif
- mpreal(const char* s, mp_prec_t prec = default_prec, int base = default_base, mp_rnd_t mode = default_rnd);
- mpreal(const std::string& s, mp_prec_t prec = default_prec, int base = default_base, mp_rnd_t mode = default_rnd);
-
- ~mpreal();
-
- // Operations
- // =
- // +, -, *, /, ++, --, <<, >>
- // *=, +=, -=, /=,
- // <, >, ==, <=, >=
-
- // =
- mpreal& operator=(const mpreal& v);
- mpreal& operator=(const mpf_t v);
- mpreal& operator=(const mpz_t v);
- mpreal& operator=(const mpq_t v);
- mpreal& operator=(const long double v);
- mpreal& operator=(const double v);
- mpreal& operator=(const unsigned long int v);
- mpreal& operator=(const unsigned int v);
- mpreal& operator=(const long int v);
- mpreal& operator=(const int v);
- mpreal& operator=(const char* s);
-
- // +
- mpreal& operator+=(const mpreal& v);
- mpreal& operator+=(const mpf_t v);
- mpreal& operator+=(const mpz_t v);
- mpreal& operator+=(const mpq_t v);
- mpreal& operator+=(const long double u);
- mpreal& operator+=(const double u);
- mpreal& operator+=(const unsigned long int u);
- mpreal& operator+=(const unsigned int u);
- mpreal& operator+=(const long int u);
- mpreal& operator+=(const int u);
+ mpreal(const char* s, mp_prec_t prec = mpreal::get_default_prec(), int base = 10, mp_rnd_t mode = mpreal::get_default_rnd());
+ mpreal(const std::string& s, mp_prec_t prec = mpreal::get_default_prec(), int base = 10, mp_rnd_t mode = mpreal::get_default_rnd());
+
+ ~mpreal();
+
+ // Operations
+ // =
+ // +, -, *, /, ++, --, <<, >>
+ // *=, +=, -=, /=,
+ // <, >, ==, <=, >=
+
+ // =
+ mpreal& operator=(const mpreal& v);
+ mpreal& operator=(const mpf_t v);
+ mpreal& operator=(const mpz_t v);
+ mpreal& operator=(const mpq_t v);
+ mpreal& operator=(const long double v);
+ mpreal& operator=(const double v);
+ mpreal& operator=(const unsigned long int v);
+ mpreal& operator=(const unsigned int v);
+ mpreal& operator=(const long int v);
+ mpreal& operator=(const int v);
+ mpreal& operator=(const char* s);
+ mpreal& operator=(const std::string& s);
+
+ // +
+ mpreal& operator+=(const mpreal& v);
+ mpreal& operator+=(const mpf_t v);
+ mpreal& operator+=(const mpz_t v);
+ mpreal& operator+=(const mpq_t v);
+ mpreal& operator+=(const long double u);
+ mpreal& operator+=(const double u);
+ mpreal& operator+=(const unsigned long int u);
+ mpreal& operator+=(const unsigned int u);
+ mpreal& operator+=(const long int u);
+ mpreal& operator+=(const int u);
#if defined (MPREAL_HAVE_INT64_SUPPORT)
- mpreal& operator+=(const int64_t u);
- mpreal& operator+=(const uint64_t u);
- mpreal& operator-=(const int64_t u);
- mpreal& operator-=(const uint64_t u);
- mpreal& operator*=(const int64_t u);
- mpreal& operator*=(const uint64_t u);
- mpreal& operator/=(const int64_t u);
- mpreal& operator/=(const uint64_t u);
+ mpreal& operator+=(const int64_t u);
+ mpreal& operator+=(const uint64_t u);
+ mpreal& operator-=(const int64_t u);
+ mpreal& operator-=(const uint64_t u);
+ mpreal& operator*=(const int64_t u);
+ mpreal& operator*=(const uint64_t u);
+ mpreal& operator/=(const int64_t u);
+ mpreal& operator/=(const uint64_t u);
#endif
- const mpreal operator+() const;
- mpreal& operator++ ();
- const mpreal operator++ (int);
-
- // -
- mpreal& operator-=(const mpreal& v);
- mpreal& operator-=(const mpz_t v);
- mpreal& operator-=(const mpq_t v);
- mpreal& operator-=(const long double u);
- mpreal& operator-=(const double u);
- mpreal& operator-=(const unsigned long int u);
- mpreal& operator-=(const unsigned int u);
- mpreal& operator-=(const long int u);
- mpreal& operator-=(const int u);
- const mpreal operator-() const;
- friend const mpreal operator-(const unsigned long int b, const mpreal& a);
- friend const mpreal operator-(const unsigned int b, const mpreal& a);
- friend const mpreal operator-(const long int b, const mpreal& a);
- friend const mpreal operator-(const int b, const mpreal& a);
- friend const mpreal operator-(const double b, const mpreal& a);
- mpreal& operator-- ();
- const mpreal operator-- (int);
-
- // *
- mpreal& operator*=(const mpreal& v);
- mpreal& operator*=(const mpz_t v);
- mpreal& operator*=(const mpq_t v);
- mpreal& operator*=(const long double v);
- mpreal& operator*=(const double v);
- mpreal& operator*=(const unsigned long int v);
- mpreal& operator*=(const unsigned int v);
- mpreal& operator*=(const long int v);
- mpreal& operator*=(const int v);
-
- // /
- mpreal& operator/=(const mpreal& v);
- mpreal& operator/=(const mpz_t v);
- mpreal& operator/=(const mpq_t v);
- mpreal& operator/=(const long double v);
- mpreal& operator/=(const double v);
- mpreal& operator/=(const unsigned long int v);
- mpreal& operator/=(const unsigned int v);
- mpreal& operator/=(const long int v);
- mpreal& operator/=(const int v);
- friend const mpreal operator/(const unsigned long int b, const mpreal& a);
- friend const mpreal operator/(const unsigned int b, const mpreal& a);
- friend const mpreal operator/(const long int b, const mpreal& a);
- friend const mpreal operator/(const int b, const mpreal& a);
- friend const mpreal operator/(const double b, const mpreal& a);
-
- //<<= Fast Multiplication by 2^u
- mpreal& operator<<=(const unsigned long int u);
- mpreal& operator<<=(const unsigned int u);
- mpreal& operator<<=(const long int u);
- mpreal& operator<<=(const int u);
-
- //>>= Fast Division by 2^u
- mpreal& operator>>=(const unsigned long int u);
- mpreal& operator>>=(const unsigned int u);
- mpreal& operator>>=(const long int u);
- mpreal& operator>>=(const int u);
-
- // Boolean Operators
- friend bool operator > (const mpreal& a, const mpreal& b);
- friend bool operator >= (const mpreal& a, const mpreal& b);
- friend bool operator < (const mpreal& a, const mpreal& b);
- friend bool operator <= (const mpreal& a, const mpreal& b);
- friend bool operator == (const mpreal& a, const mpreal& b);
- friend bool operator != (const mpreal& a, const mpreal& b);
-
- // Optimized specializations for boolean operators
- friend bool operator == (const mpreal& a, const unsigned long int b);
- friend bool operator == (const mpreal& a, const unsigned int b);
- friend bool operator == (const mpreal& a, const long int b);
- friend bool operator == (const mpreal& a, const int b);
- friend bool operator == (const mpreal& a, const long double b);
- friend bool operator == (const mpreal& a, const double b);
-
- // Type Conversion operators
- long toLong() const;
- unsigned long toULong() const;
- double toDouble() const;
- long double toLDouble() const;
+ const mpreal operator+() const;
+ mpreal& operator++ ();
+ const mpreal operator++ (int);
+
+ // -
+ mpreal& operator-=(const mpreal& v);
+ mpreal& operator-=(const mpz_t v);
+ mpreal& operator-=(const mpq_t v);
+ mpreal& operator-=(const long double u);
+ mpreal& operator-=(const double u);
+ mpreal& operator-=(const unsigned long int u);
+ mpreal& operator-=(const unsigned int u);
+ mpreal& operator-=(const long int u);
+ mpreal& operator-=(const int u);
+ const mpreal operator-() const;
+ friend const mpreal operator-(const unsigned long int b, const mpreal& a);
+ friend const mpreal operator-(const unsigned int b, const mpreal& a);
+ friend const mpreal operator-(const long int b, const mpreal& a);
+ friend const mpreal operator-(const int b, const mpreal& a);
+ friend const mpreal operator-(const double b, const mpreal& a);
+ mpreal& operator-- ();
+ const mpreal operator-- (int);
+
+ // *
+ mpreal& operator*=(const mpreal& v);
+ mpreal& operator*=(const mpz_t v);
+ mpreal& operator*=(const mpq_t v);
+ mpreal& operator*=(const long double v);
+ mpreal& operator*=(const double v);
+ mpreal& operator*=(const unsigned long int v);
+ mpreal& operator*=(const unsigned int v);
+ mpreal& operator*=(const long int v);
+ mpreal& operator*=(const int v);
+
+ // /
+ mpreal& operator/=(const mpreal& v);
+ mpreal& operator/=(const mpz_t v);
+ mpreal& operator/=(const mpq_t v);
+ mpreal& operator/=(const long double v);
+ mpreal& operator/=(const double v);
+ mpreal& operator/=(const unsigned long int v);
+ mpreal& operator/=(const unsigned int v);
+ mpreal& operator/=(const long int v);
+ mpreal& operator/=(const int v);
+ friend const mpreal operator/(const unsigned long int b, const mpreal& a);
+ friend const mpreal operator/(const unsigned int b, const mpreal& a);
+ friend const mpreal operator/(const long int b, const mpreal& a);
+ friend const mpreal operator/(const int b, const mpreal& a);
+ friend const mpreal operator/(const double b, const mpreal& a);
+
+ //<<= Fast Multiplication by 2^u
+ mpreal& operator<<=(const unsigned long int u);
+ mpreal& operator<<=(const unsigned int u);
+ mpreal& operator<<=(const long int u);
+ mpreal& operator<<=(const int u);
+
+ //>>= Fast Division by 2^u
+ mpreal& operator>>=(const unsigned long int u);
+ mpreal& operator>>=(const unsigned int u);
+ mpreal& operator>>=(const long int u);
+ mpreal& operator>>=(const int u);
+
+ // Boolean Operators
+ friend bool operator > (const mpreal& a, const mpreal& b);
+ friend bool operator >= (const mpreal& a, const mpreal& b);
+ friend bool operator < (const mpreal& a, const mpreal& b);
+ friend bool operator <= (const mpreal& a, const mpreal& b);
+ friend bool operator == (const mpreal& a, const mpreal& b);
+ friend bool operator != (const mpreal& a, const mpreal& b);
+
+ // Optimized specializations for boolean operators
+ friend bool operator == (const mpreal& a, const unsigned long int b);
+ friend bool operator == (const mpreal& a, const unsigned int b);
+ friend bool operator == (const mpreal& a, const long int b);
+ friend bool operator == (const mpreal& a, const int b);
+ friend bool operator == (const mpreal& a, const long double b);
+ friend bool operator == (const mpreal& a, const double b);
+
+ // Type Conversion operators
+ long toLong (mp_rnd_t mode = GMP_RNDZ) const;
+ unsigned long toULong (mp_rnd_t mode = GMP_RNDZ) const;
+ double toDouble (mp_rnd_t mode = GMP_RNDN) const;
+ long double toLDouble (mp_rnd_t mode = GMP_RNDN) const;
#if defined (MPREAL_HAVE_INT64_SUPPORT)
- int64_t toInt64() const;
- uint64_t toUInt64() const;
+ int64_t toInt64 (mp_rnd_t mode = GMP_RNDZ) const;
+ uint64_t toUInt64 (mp_rnd_t mode = GMP_RNDZ) const;
#endif
- // Get raw pointers
- ::mpfr_ptr mpfr_ptr();
- ::mpfr_srcptr mpfr_srcptr() const;
+ // Get raw pointers so that mpreal can be directly used in raw mpfr_* functions
+ ::mpfr_ptr mpfr_ptr();
+ ::mpfr_srcptr mpfr_ptr() const;
+ ::mpfr_srcptr mpfr_srcptr() const;
- // Convert mpreal to string with n significant digits in base b
- // n = 0 -> convert with the maximum available digits
- std::string toString(int n = 0, int b = default_base, mp_rnd_t mode = default_rnd) const;
+ // Convert mpreal to string with n significant digits in base b
+ // n = 0 -> convert with the maximum available digits
+ std::string toString(int n = 0, int b = 10, mp_rnd_t mode = mpreal::get_default_rnd()) const;
#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
- std::string toString(const std::string& format) const;
+ std::string toString(const std::string& format) const;
#endif
- // Math Functions
- friend const mpreal sqr (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal sqrt(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal sqrt(const unsigned long int v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal cbrt(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal root(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal pow (const mpreal& a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal pow (const mpreal& a, const mpz_t b, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal pow (const mpreal& a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal pow (const mpreal& a, const long int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal pow (const unsigned long int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal pow (const unsigned long int a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal fabs(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
-
- friend const mpreal abs(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal dim(const mpreal& a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend inline const mpreal mul_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend inline const mpreal mul_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend inline const mpreal div_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend inline const mpreal div_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend int cmpabs(const mpreal& a,const mpreal& b);
-
- friend const mpreal log (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal log2 (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal log10(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal exp (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal exp2 (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal exp10(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal log1p(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal expm1(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
-
- friend const mpreal cos(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal sin(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal tan(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal sec(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal csc(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal cot(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend int sin_cos(mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
-
- friend const mpreal acos (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal asin (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal atan (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal atan2 (const mpreal& y, const mpreal& x, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal acot (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal asec (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal acsc (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
-
- friend const mpreal cosh (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal sinh (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal tanh (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal sech (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal csch (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal coth (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal acosh (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal asinh (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal atanh (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal acoth (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal asech (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal acsch (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
-
- friend const mpreal hypot (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::default_rnd);
-
- friend const mpreal fac_ui (unsigned long int v, mp_prec_t prec = mpreal::default_prec, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal eint (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
-
- friend const mpreal gamma (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal lngamma (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal lgamma (const mpreal& v, int *signp = 0, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal zeta (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal erf (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal erfc (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal besselj0 (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal besselj1 (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal besseljn (long n, const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal bessely0 (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal bessely1 (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal besselyn (long n, const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal fma (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal fms (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal agm (const mpreal& v1, const mpreal& v2, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal sum (const mpreal tab[], unsigned long int n, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend int sgn(const mpreal& v); // -1 or +1
+ // Math Functions
+ friend const mpreal sqr (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal sqrt(const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal sqrt(const unsigned long int v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal cbrt(const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal root(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal pow (const mpreal& a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal pow (const mpreal& a, const mpz_t b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal pow (const mpreal& a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal pow (const mpreal& a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal pow (const unsigned long int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal pow (const unsigned long int a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal fabs(const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+
+ friend const mpreal abs(const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal dim(const mpreal& a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend inline const mpreal mul_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend inline const mpreal mul_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend inline const mpreal div_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend inline const mpreal div_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend int cmpabs(const mpreal& a,const mpreal& b);
+
+ friend const mpreal log (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal log2 (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal log10(const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal exp (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal exp2 (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal exp10(const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal log1p(const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal expm1(const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+
+ friend const mpreal cos(const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal sin(const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal tan(const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal sec(const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal csc(const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal cot(const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend int sin_cos(mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+
+ friend const mpreal acos (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal asin (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal atan (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal atan2 (const mpreal& y, const mpreal& x, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal acot (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal asec (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal acsc (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+
+ friend const mpreal cosh (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal sinh (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal tanh (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal sech (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal csch (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal coth (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal acosh (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal asinh (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal atanh (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal acoth (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal asech (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal acsch (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+
+ friend const mpreal hypot (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+
+ friend const mpreal fac_ui (unsigned long int v, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal eint (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+
+ friend const mpreal gamma (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal lngamma (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal lgamma (const mpreal& v, int *signp = 0, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal zeta (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal erf (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal erfc (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal besselj0 (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal besselj1 (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal besseljn (long n, const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal bessely0 (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal bessely1 (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal besselyn (long n, const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal fma (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal fms (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal agm (const mpreal& v1, const mpreal& v2, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal sum (const mpreal tab[], unsigned long int n, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend int sgn(const mpreal& v); // returns -1 or +1
// MPFR 2.4.0 Specifics
#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
- friend int sinh_cosh(mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal li2(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal fmod (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal rec_sqrt(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
+ friend int sinh_cosh (mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal li2 (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal fmod (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal rec_sqrt (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+
+ // MATLAB's semantic equivalents
+ friend const mpreal rem (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); // Remainder after division
+ friend const mpreal mod (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); // Modulus after division
#endif
// MPFR 3.0.0 Specifics
#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))
- friend const mpreal digamma(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal ai(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal urandom (gmp_randstate_t& state,mp_rnd_t rnd_mode = mpreal::default_rnd); // use gmp_randinit_default() to init state, gmp_randclear() to clear
- friend bool isregular(const mpreal& v);
+ friend const mpreal digamma (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal ai (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal urandom (gmp_randstate_t& state, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); // use gmp_randinit_default() to init state, gmp_randclear() to clear
#endif
-
- // Uniformly distributed random number generation in [0,1] using
- // Mersenne-Twister algorithm by default.
- // Use parameter to setup seed, e.g.: random((unsigned)time(NULL))
- // Check urandom() for more precise control.
- friend const mpreal random(unsigned int seed = 0);
-
- // Exponent and mantissa manipulation
- friend const mpreal frexp(const mpreal& v, mp_exp_t* exp);
- friend const mpreal ldexp(const mpreal& v, mp_exp_t exp);
-
- // Splits mpreal value into fractional and integer parts.
- // Returns fractional part and stores integer part in n.
- friend const mpreal modf(const mpreal& v, mpreal& n);
-
- // Constants
- // don't forget to call mpfr_free_cache() for every thread where you are using const-functions
- friend const mpreal const_log2 (mp_prec_t prec = mpreal::default_prec, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal const_pi (mp_prec_t prec = mpreal::default_prec, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal const_euler (mp_prec_t prec = mpreal::default_prec, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal const_catalan (mp_prec_t prec = mpreal::default_prec, mp_rnd_t rnd_mode = mpreal::default_rnd);
- // returns +inf iff sign>=0 otherwise -inf
- friend const mpreal const_infinity(int sign = 1, mp_prec_t prec = mpreal::default_prec, mp_rnd_t rnd_mode = mpreal::default_rnd);
-
- // Output/ Input
- friend std::ostream& operator<<(std::ostream& os, const mpreal& v);
+
+ // Uniformly distributed random number generation in [0,1] using
+ // Mersenne-Twister algorithm by default.
+ // Use parameter to setup seed, e.g.: random((unsigned)time(NULL))
+ // Check urandom() for more precise control.
+ friend const mpreal random(unsigned int seed = 0);
+
+ // Exponent and mantissa manipulation
+ friend const mpreal frexp(const mpreal& v, mp_exp_t* exp);
+ friend const mpreal ldexp(const mpreal& v, mp_exp_t exp);
+
+ // Splits mpreal value into fractional and integer parts.
+ // Returns fractional part and stores integer part in n.
+ friend const mpreal modf(const mpreal& v, mpreal& n);
+
+ // Constants
+ // don't forget to call mpfr_free_cache() for every thread where you are using const-functions
+ friend const mpreal const_log2 (mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal const_pi (mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal const_euler (mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal const_catalan (mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+
+ // returns +inf iff sign>=0 otherwise -inf
+ friend const mpreal const_infinity(int sign = 1, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+
+ // Output/ Input
+ friend std::ostream& operator<<(std::ostream& os, const mpreal& v);
friend std::istream& operator>>(std::istream& is, mpreal& v);
- // Integer Related Functions
- friend const mpreal rint (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal ceil (const mpreal& v);
- friend const mpreal floor(const mpreal& v);
- friend const mpreal round(const mpreal& v);
- friend const mpreal trunc(const mpreal& v);
- friend const mpreal rint_ceil (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal rint_floor(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal rint_round(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal rint_trunc(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal frac (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal remainder (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::default_rnd);
- friend const mpreal remquo (long* q, const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::default_rnd);
-
- // Miscellaneous Functions
- friend const mpreal nexttoward (const mpreal& x, const mpreal& y);
- friend const mpreal nextabove (const mpreal& x);
- friend const mpreal nextbelow (const mpreal& x);
-
- // use gmp_randinit_default() to init state, gmp_randclear() to clear
- friend const mpreal urandomb (gmp_randstate_t& state);
+ // Integer Related Functions
+ friend const mpreal rint (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal ceil (const mpreal& v);
+ friend const mpreal floor(const mpreal& v);
+ friend const mpreal round(const mpreal& v);
+ friend const mpreal trunc(const mpreal& v);
+ friend const mpreal rint_ceil (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal rint_floor (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal rint_round (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal rint_trunc (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal frac (const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal remainder ( const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal remquo (long* q, const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+
+ // Miscellaneous Functions
+ friend const mpreal nexttoward (const mpreal& x, const mpreal& y);
+ friend const mpreal nextabove (const mpreal& x);
+ friend const mpreal nextbelow (const mpreal& x);
+
+ // use gmp_randinit_default() to init state, gmp_randclear() to clear
+ friend const mpreal urandomb (gmp_randstate_t& state);
// MPFR < 2.4.2 Specifics
#if (MPFR_VERSION <= MPFR_VERSION_NUM(2,4,2))
- friend const mpreal random2 (mp_size_t size, mp_exp_t exp);
+ friend const mpreal random2 (mp_size_t size, mp_exp_t exp);
#endif
- // Instance Checkers
- friend bool isnan (const mpreal& v);
- friend bool isinf (const mpreal& v);
- friend bool isfinite(const mpreal& v);
-
- friend bool isnum(const mpreal& v);
- friend bool iszero(const mpreal& v);
- friend bool isint(const mpreal& v);
-
- // Set/Get instance properties
- inline mp_prec_t get_prec() const;
- inline void set_prec(mp_prec_t prec, mp_rnd_t rnd_mode = default_rnd); // Change precision with rounding mode
-
- // Aliases for get_prec(), set_prec() - needed for compatibility with std::complex<mpreal> interface
- inline mpreal& setPrecision(int Precision, mp_rnd_t RoundingMode = (mpfr_get_default_rounding_mode)());
- inline int getPrecision() const;
-
- // Set mpreal to +/- inf, NaN, +/-0
- mpreal& setInf (int Sign = +1);
- mpreal& setNan ();
- mpreal& setZero (int Sign = +1);
- mpreal& setSign (int Sign, mp_rnd_t RoundingMode = (mpfr_get_default_rounding_mode)());
-
- //Exponent
- mp_exp_t get_exp();
- int set_exp(mp_exp_t e);
- int check_range (int t, mp_rnd_t rnd_mode = default_rnd);
- int subnormalize (int t,mp_rnd_t rnd_mode = default_rnd);
-
- // Inexact conversion from float
- inline bool fits_in_bits(double x, int n);
-
- // Set/Get global properties
- static void set_default_prec(mp_prec_t prec);
- static mp_prec_t get_default_prec();
- static void set_default_base(int base);
- static int get_default_base();
- static void set_double_bits(int dbits);
- static int get_double_bits();
- static void set_default_rnd(mp_rnd_t rnd_mode);
- static mp_rnd_t get_default_rnd();
- static mp_exp_t get_emin (void);
- static mp_exp_t get_emax (void);
- static mp_exp_t get_emin_min (void);
- static mp_exp_t get_emin_max (void);
- static mp_exp_t get_emax_min (void);
- static mp_exp_t get_emax_max (void);
- static int set_emin (mp_exp_t exp);
- static int set_emax (mp_exp_t exp);
-
- // Efficient swapping of two mpreal values
- friend void swap(mpreal& x, mpreal& y);
-
- //Min Max - macros is evil. Needed for systems which defines max and min globally as macros (e.g. Windows)
- //Hope that globally defined macros use > < operations only
- friend const mpreal fmax(const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = default_rnd);
- friend const mpreal fmin(const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = default_rnd);
-
-#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
+ // Instance Checkers
+ friend bool isnan (const mpreal& v);
+ friend bool isinf (const mpreal& v);
+ friend bool isfinite (const mpreal& v);
-private:
- // Optimized dynamic memory allocation/(re-)deallocation.
- static bool is_custom_malloc;
- static void *mpreal_allocate (size_t alloc_size);
- static void *mpreal_reallocate (void *ptr, size_t old_size, size_t new_size);
- static void mpreal_free (void *ptr, size_t size);
- inline static void set_custom_malloc (void);
+ friend bool isnum (const mpreal& v);
+ friend bool iszero (const mpreal& v);
+ friend bool isint (const mpreal& v);
+#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))
+ friend bool isregular(const mpreal& v);
#endif
+ // Set/Get instance properties
+ inline mp_prec_t get_prec() const;
+ inline void set_prec(mp_prec_t prec, mp_rnd_t rnd_mode = get_default_rnd()); // Change precision with rounding mode
+
+ // Aliases for get_prec(), set_prec() - needed for compatibility with std::complex<mpreal> interface
+ inline mpreal& setPrecision(int Precision, mp_rnd_t RoundingMode = get_default_rnd());
+ inline int getPrecision() const;
+
+ // Set mpreal to +/- inf, NaN, +/-0
+ mpreal& setInf (int Sign = +1);
+ mpreal& setNan ();
+ mpreal& setZero (int Sign = +1);
+ mpreal& setSign (int Sign, mp_rnd_t RoundingMode = get_default_rnd());
+
+ //Exponent
+ mp_exp_t get_exp();
+ int set_exp(mp_exp_t e);
+ int check_range (int t, mp_rnd_t rnd_mode = get_default_rnd());
+ int subnormalize (int t,mp_rnd_t rnd_mode = get_default_rnd());
+
+ // Inexact conversion from float
+ inline bool fits_in_bits(double x, int n);
+
+ // Set/Get global properties
+ static void set_default_prec(mp_prec_t prec);
+ static void set_default_rnd(mp_rnd_t rnd_mode);
+
+ static mp_exp_t get_emin (void);
+ static mp_exp_t get_emax (void);
+ static mp_exp_t get_emin_min (void);
+ static mp_exp_t get_emin_max (void);
+ static mp_exp_t get_emax_min (void);
+ static mp_exp_t get_emax_max (void);
+ static int set_emin (mp_exp_t exp);
+ static int set_emax (mp_exp_t exp);
+
+ // Efficient swapping of two mpreal values - needed for std algorithms
+ friend void swap(mpreal& x, mpreal& y);
+
+ friend const mpreal fmax(const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+ friend const mpreal fmin(const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
private:
- // Human friendly Debug Preview in Visual Studio.
- // Put one of these lines:
- //
- // mpfr::mpreal=<DebugView> ; Show value only
- // mpfr::mpreal=<DebugView>, <mp[0]._mpfr_prec,u>bits ; Show value & precision
- //
- // at the beginning of
- // [Visual Studio Installation Folder]\Common7\Packages\Debugger\autoexp.dat
- MPREAL_MSVC_DEBUGVIEW_DATA
+ // Human friendly Debug Preview in Visual Studio.
+ // Put one of these lines:
+ //
+ // mpfr::mpreal=<DebugView> ; Show value only
+ // mpfr::mpreal=<DebugView>, <mp[0]._mpfr_prec,u>bits ; Show value & precision
+ //
+ // at the beginning of
+ // [Visual Studio Installation Folder]\Common7\Packages\Debugger\autoexp.dat
+ MPREAL_MSVC_DEBUGVIEW_DATA
};
//////////////////////////////////////////////////////////////////////////
// Exceptions
class conversion_overflow : public std::exception {
public:
- std::string why() { return "inexact conversion from floating point"; }
+ std::string why() { return "inexact conversion from floating point"; }
};
+//////////////////////////////////////////////////////////////////////////
+// Constructors & converters
+// Default constructor: creates mp number and initializes it to 0.
+inline mpreal::mpreal()
+{
+ mpfr_init2(mp,mpreal::get_default_prec());
+ mpfr_set_ui(mp,0,mpreal::get_default_rnd());
+
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+}
+
+inline mpreal::mpreal(const mpreal& u)
+{
+ mpfr_init2(mp,mpfr_get_prec(u.mp));
+ mpfr_set(mp,u.mp,mpreal::get_default_rnd());
+
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+}
+
+inline mpreal::mpreal(const mpfr_t u)
+{
+ mpfr_init2(mp,mpfr_get_prec(u));
+ mpfr_set(mp,u,mpreal::get_default_rnd());
+
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+}
+
+inline mpreal::mpreal(const mpf_t u)
+{
+ mpfr_init2(mp,(mp_prec_t) mpf_get_prec(u)); // (gmp: mp_bitcnt_t) unsigned long -> long (mpfr: mp_prec_t)
+ mpfr_set_f(mp,u,mpreal::get_default_rnd());
+
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+}
+
+inline mpreal::mpreal(const mpz_t u, mp_prec_t prec, mp_rnd_t mode)
+{
+ mpfr_init2(mp,prec);
+ mpfr_set_z(mp,u,mode);
+
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+}
+
+inline mpreal::mpreal(const mpq_t u, mp_prec_t prec, mp_rnd_t mode)
+{
+ mpfr_init2(mp,prec);
+ mpfr_set_q(mp,u,mode);
+
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+}
+
+inline mpreal::mpreal(const double u, mp_prec_t prec, mp_rnd_t mode)
+{
+ mpfr_init2(mp, prec);
+
+#if (MPREAL_DOUBLE_BITS_OVERFLOW > -1)
+ if(fits_in_bits(u, MPREAL_DOUBLE_BITS_OVERFLOW))
+ {
+ mpfr_set_d(mp, u, mode);
+ }else
+ throw conversion_overflow();
+#else
+ mpfr_set_d(mp, u, mode);
+#endif
+
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+}
+
+inline mpreal::mpreal(const long double u, mp_prec_t prec, mp_rnd_t mode)
+{
+ mpfr_init2(mp,prec);
+ mpfr_set_ld(mp,u,mode);
+
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+}
+
+inline mpreal::mpreal(const unsigned long int u, mp_prec_t prec, mp_rnd_t mode)
+{
+ mpfr_init2(mp,prec);
+ mpfr_set_ui(mp,u,mode);
+
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+}
+
+inline mpreal::mpreal(const unsigned int u, mp_prec_t prec, mp_rnd_t mode)
+{
+ mpfr_init2(mp,prec);
+ mpfr_set_ui(mp,u,mode);
+
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+}
+
+inline mpreal::mpreal(const long int u, mp_prec_t prec, mp_rnd_t mode)
+{
+ mpfr_init2(mp,prec);
+ mpfr_set_si(mp,u,mode);
+
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+}
+
+inline mpreal::mpreal(const int u, mp_prec_t prec, mp_rnd_t mode)
+{
+ mpfr_init2(mp,prec);
+ mpfr_set_si(mp,u,mode);
+
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+}
+
+#if defined (MPREAL_HAVE_INT64_SUPPORT)
+inline mpreal::mpreal(const uint64_t u, mp_prec_t prec, mp_rnd_t mode)
+{
+ mpfr_init2(mp,prec);
+ mpfr_set_uj(mp, u, mode);
+
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+}
+
+inline mpreal::mpreal(const int64_t u, mp_prec_t prec, mp_rnd_t mode)
+{
+ mpfr_init2(mp,prec);
+ mpfr_set_sj(mp, u, mode);
+
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+}
+#endif
+
+inline mpreal::mpreal(const char* s, mp_prec_t prec, int base, mp_rnd_t mode)
+{
+ mpfr_init2(mp, prec);
+ mpfr_set_str(mp, s, base, mode);
+
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+}
+
+inline mpreal::mpreal(const std::string& s, mp_prec_t prec, int base, mp_rnd_t mode)
+{
+ mpfr_init2(mp, prec);
+ mpfr_set_str(mp, s.c_str(), base, mode);
+
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+}
+
+inline mpreal::~mpreal()
+{
+ mpfr_clear(mp);
+}
+
+// internal namespace needed for template magic
namespace internal{
- // Use SFINAE to restrict arithmetic operations instantiation only for numeric types
- // This is needed for smooth integration with libraries based on expression templates
- template <typename ArgumentType> struct result_type {};
-
- template <> struct result_type<mpreal> {typedef mpreal type;};
- template <> struct result_type<mpz_t> {typedef mpreal type;};
- template <> struct result_type<mpq_t> {typedef mpreal type;};
- template <> struct result_type<long double> {typedef mpreal type;};
- template <> struct result_type<double> {typedef mpreal type;};
- template <> struct result_type<unsigned long int> {typedef mpreal type;};
- template <> struct result_type<unsigned int> {typedef mpreal type;};
- template <> struct result_type<long int> {typedef mpreal type;};
- template <> struct result_type<int> {typedef mpreal type;};
+ // Use SFINAE to restrict arithmetic operations instantiation only for numeric types
+ // This is needed for smooth integration with libraries based on expression templates, like Eigen.
+ // TODO: Do the same for boolean operators.
+ template <typename ArgumentType> struct result_type {};
+
+ template <> struct result_type<mpreal> {typedef mpreal type;};
+ template <> struct result_type<mpz_t> {typedef mpreal type;};
+ template <> struct result_type<mpq_t> {typedef mpreal type;};
+ template <> struct result_type<long double> {typedef mpreal type;};
+ template <> struct result_type<double> {typedef mpreal type;};
+ template <> struct result_type<unsigned long int> {typedef mpreal type;};
+ template <> struct result_type<unsigned int> {typedef mpreal type;};
+ template <> struct result_type<long int> {typedef mpreal type;};
+ template <> struct result_type<int> {typedef mpreal type;};
#if defined (MPREAL_HAVE_INT64_SUPPORT)
- template <> struct result_type<int64_t > {typedef mpreal type;};
- template <> struct result_type<uint64_t > {typedef mpreal type;};
+ template <> struct result_type<int64_t > {typedef mpreal type;};
+ template <> struct result_type<uint64_t > {typedef mpreal type;};
#endif
}
// + Addition
template <typename Rhs>
inline const typename internal::result_type<Rhs>::type
- operator+(const mpreal& lhs, const Rhs& rhs){ return mpreal(lhs) += rhs; }
+ operator+(const mpreal& lhs, const Rhs& rhs){ return mpreal(lhs) += rhs; }
template <typename Lhs>
inline const typename internal::result_type<Lhs>::type
- operator+(const Lhs& lhs, const mpreal& rhs){ return mpreal(rhs) += lhs; }
+ operator+(const Lhs& lhs, const mpreal& rhs){ return mpreal(rhs) += lhs; }
// - Subtraction
template <typename Rhs>
inline const typename internal::result_type<Rhs>::type
- operator-(const mpreal& lhs, const Rhs& rhs){ return mpreal(lhs) -= rhs; }
+ operator-(const mpreal& lhs, const Rhs& rhs){ return mpreal(lhs) -= rhs; }
template <typename Lhs>
inline const typename internal::result_type<Lhs>::type
- operator-(const Lhs& lhs, const mpreal& rhs){ return mpreal(lhs) -= rhs; }
+ operator-(const Lhs& lhs, const mpreal& rhs){ return mpreal(lhs) -= rhs; }
// * Multiplication
template <typename Rhs>
inline const typename internal::result_type<Rhs>::type
- operator*(const mpreal& lhs, const Rhs& rhs){ return mpreal(lhs) *= rhs; }
+ operator*(const mpreal& lhs, const Rhs& rhs){ return mpreal(lhs) *= rhs; }
template <typename Lhs>
inline const typename internal::result_type<Lhs>::type
- operator*(const Lhs& lhs, const mpreal& rhs){ return mpreal(rhs) *= lhs; }
+ operator*(const Lhs& lhs, const mpreal& rhs){ return mpreal(rhs) *= lhs; }
// / Division
template <typename Rhs>
inline const typename internal::result_type<Rhs>::type
- operator/(const mpreal& lhs, const Rhs& rhs){ return mpreal(lhs) /= rhs; }
+ operator/(const mpreal& lhs, const Rhs& rhs){ return mpreal(lhs) /= rhs; }
template <typename Lhs>
inline const typename internal::result_type<Lhs>::type
- operator/(const Lhs& lhs, const mpreal& rhs){ return mpreal(lhs) /= rhs; }
+ operator/(const Lhs& lhs, const mpreal& rhs){ return mpreal(lhs) /= rhs; }
//////////////////////////////////////////////////////////////////////////
// sqrt
-const mpreal sqrt(const unsigned int v, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal sqrt(const long int v, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal sqrt(const int v, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal sqrt(const long double v, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal sqrt(const double v, mp_rnd_t rnd_mode = mpreal::default_rnd);
+const mpreal sqrt(const unsigned int v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal sqrt(const long int v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal sqrt(const int v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal sqrt(const long double v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal sqrt(const double v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
//////////////////////////////////////////////////////////////////////////
// pow
-const mpreal pow(const mpreal& a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const mpreal& a, const int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const mpreal& a, const long double b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const mpreal& a, const double b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-
-const mpreal pow(const unsigned int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const long int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const long double a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const double a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-
-const mpreal pow(const unsigned long int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const unsigned long int a, const long int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const unsigned long int a, const int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const unsigned long int a, const long double b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const unsigned long int a, const double b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-
-const mpreal pow(const unsigned int a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const unsigned int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const unsigned int a, const long int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const unsigned int a, const int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const unsigned int a, const long double b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const unsigned int a, const double b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-
-const mpreal pow(const long int a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const long int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const long int a, const long int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const long int a, const int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const long int a, const long double b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const long int a, const double b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-
-const mpreal pow(const int a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const int a, const long int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const int a, const int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const int a, const long double b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const int a, const double b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-
-const mpreal pow(const long double a, const long double b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const long double a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const long double a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const long double a, const long int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const long double a, const int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-
-const mpreal pow(const double a, const double b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const double a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const double a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const double a, const long int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
-const mpreal pow(const double a, const int b, mp_rnd_t rnd_mode = mpreal::default_rnd);
+const mpreal pow(const mpreal& a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const mpreal& a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const mpreal& a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const mpreal& a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+
+const mpreal pow(const unsigned int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const long int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const long double a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const double a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+
+const mpreal pow(const unsigned long int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const unsigned long int a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const unsigned long int a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const unsigned long int a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const unsigned long int a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+
+const mpreal pow(const unsigned int a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const unsigned int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const unsigned int a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const unsigned int a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const unsigned int a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const unsigned int a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+
+const mpreal pow(const long int a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const long int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const long int a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const long int a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const long int a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const long int a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+
+const mpreal pow(const int a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const int a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const int a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const int a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const int a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+
+const mpreal pow(const long double a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const long double a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const long double a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const long double a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const long double a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+
+const mpreal pow(const double a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const double a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const double a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const double a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
+const mpreal pow(const double a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
//////////////////////////////////////////////////////////////////////////
// Estimate machine epsilon for the given precision
// Returns smallest eps such that 1.0 + eps != 1.0
-inline const mpreal machine_epsilon(mp_prec_t prec = mpreal::get_default_prec());
+inline mpreal machine_epsilon(mp_prec_t prec = mpreal::get_default_prec());
-// Returns the positive distance from abs(x) to the next larger in magnitude floating point number of the same precision as x
-inline const mpreal machine_epsilon(const mpreal& x);
+// Returns smallest eps such that x + eps != x (relative machine epsilon)
+inline mpreal machine_epsilon(const mpreal& x);
-inline const mpreal mpreal_min(mp_prec_t prec = mpreal::get_default_prec());
-inline const mpreal mpreal_max(mp_prec_t prec = mpreal::get_default_prec());
+// Gives max & min values for the required precision,
+// minval is 'safe' meaning 1 / minval does not overflow
+// maxval is 'safe' meaning 1 / maxval does not underflow
+inline mpreal minval(mp_prec_t prec = mpreal::get_default_prec());
+inline mpreal maxval(mp_prec_t prec = mpreal::get_default_prec());
+
+// 'Dirty' equality check 1: |a-b| < min{|a|,|b|} * eps
inline bool isEqualFuzzy(const mpreal& a, const mpreal& b, const mpreal& eps);
+
+// 'Dirty' equality check 2: |a-b| < min{|a|,|b|} * eps( min{|a|,|b|} )
+inline bool isEqualFuzzy(const mpreal& a, const mpreal& b);
+
+// 'Bitwise' equality check
+// maxUlps - a and b can be apart by maxUlps binary numbers.
inline bool isEqualUlps(const mpreal& a, const mpreal& b, int maxUlps);
//////////////////////////////////////////////////////////////////////////
-// Bits - decimal digits relation
-// bits = ceil(digits*log[2](10))
-// digits = floor(bits*log[10](2))
+// Convert precision in 'bits' to decimal digits and vice versa.
+// bits = ceil(digits*log[2](10))
+// digits = floor(bits*log[10](2))
inline mp_prec_t digits2bits(int d);
-inline int bits2digits(mp_prec_t b);
+inline int bits2digits(mp_prec_t b);
//////////////////////////////////////////////////////////////////////////
// min, max
@@ -700,541 +858,586 @@ const mpreal (min)(const mpreal& x, const mpreal& y);
// Operators - Assignment
inline mpreal& mpreal::operator=(const mpreal& v)
{
- if (this != &v)
- {
- mpfr_clear(mp);
- mpfr_init2(mp,mpfr_get_prec(v.mp));
- mpfr_set(mp,v.mp,default_rnd);
+ if (this != &v)
+ {
+ mp_prec_t tp = mpfr_get_prec(mp);
+ mp_prec_t vp = mpfr_get_prec(v.mp);
+
+ if(tp != vp){
+ mpfr_clear(mp);
+ mpfr_init2(mp, vp);
+ }
+
+ mpfr_set(mp, v.mp, mpreal::get_default_rnd());
- MPREAL_MSVC_DEBUGVIEW_CODE;
- }
- return *this;
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ }
+ return *this;
}
inline mpreal& mpreal::operator=(const mpf_t v)
{
- mpfr_set_f(mp,v,default_rnd);
-
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_set_f(mp, v, mpreal::get_default_rnd());
+
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator=(const mpz_t v)
{
- mpfr_set_z(mp,v,default_rnd);
-
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_set_z(mp, v, mpreal::get_default_rnd());
+
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator=(const mpq_t v)
{
- mpfr_set_q(mp,v,default_rnd);
+ mpfr_set_q(mp, v, mpreal::get_default_rnd());
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
-inline mpreal& mpreal::operator=(const long double v)
-{
- mpfr_set_ld(mp,v,default_rnd);
+inline mpreal& mpreal::operator=(const long double v)
+{
+ mpfr_set_ld(mp, v, mpreal::get_default_rnd());
+
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
+}
+
+inline mpreal& mpreal::operator=(const double v)
+{
+#if (MPREAL_DOUBLE_BITS_OVERFLOW > -1)
+ if(fits_in_bits(v, MPREAL_DOUBLE_BITS_OVERFLOW))
+ {
+ mpfr_set_d(mp,v,mpreal::get_default_rnd());
+ }else
+ throw conversion_overflow();
+#else
+ mpfr_set_d(mp,v,mpreal::get_default_rnd());
+#endif
MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ return *this;
}
-inline mpreal& mpreal::operator=(const double v)
-{
- if(double_bits == -1 || fits_in_bits(v, double_bits))
- {
- mpfr_set_d(mp,v,default_rnd);
+inline mpreal& mpreal::operator=(const unsigned long int v)
+{
+ mpfr_set_ui(mp, v, mpreal::get_default_rnd());
- MPREAL_MSVC_DEBUGVIEW_CODE;
- }
- else
- throw conversion_overflow();
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
+}
- return *this;
+inline mpreal& mpreal::operator=(const unsigned int v)
+{
+ mpfr_set_ui(mp, v, mpreal::get_default_rnd());
+
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
-inline mpreal& mpreal::operator=(const unsigned long int v)
-{
- mpfr_set_ui(mp,v,default_rnd);
+inline mpreal& mpreal::operator=(const long int v)
+{
+ mpfr_set_si(mp, v, mpreal::get_default_rnd());
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
-inline mpreal& mpreal::operator=(const unsigned int v)
-{
- mpfr_set_ui(mp,v,default_rnd);
+inline mpreal& mpreal::operator=(const int v)
+{
+ mpfr_set_si(mp, v, mpreal::get_default_rnd());
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
-inline mpreal& mpreal::operator=(const long int v)
-{
- mpfr_set_si(mp,v,default_rnd);
+inline mpreal& mpreal::operator=(const char* s)
+{
+ // Use other converters for more precise control on base & precision & rounding:
+ //
+ // mpreal(const char* s, mp_prec_t prec, int base, mp_rnd_t mode)
+ // mpreal(const std::string& s,mp_prec_t prec, int base, mp_rnd_t mode)
+ //
+ // Here we assume base = 10 and we use precision of target variable.
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_t t;
+
+ mpfr_init2(t, mpfr_get_prec(mp));
+
+ if(0 == mpfr_set_str(t, s, 10, mpreal::get_default_rnd()))
+ {
+ mpfr_set(mp, t, mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ }
+
+ mpfr_clear(t);
+ return *this;
}
-inline mpreal& mpreal::operator=(const int v)
-{
- mpfr_set_si(mp,v,default_rnd);
+inline mpreal& mpreal::operator=(const std::string& s)
+{
+ // Use other converters for more precise control on base & precision & rounding:
+ //
+ // mpreal(const char* s, mp_prec_t prec, int base, mp_rnd_t mode)
+ // mpreal(const std::string& s,mp_prec_t prec, int base, mp_rnd_t mode)
+ //
+ // Here we assume base = 10 and we use precision of target variable.
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_t t;
+
+ mpfr_init2(t, mpfr_get_prec(mp));
+
+ if(0 == mpfr_set_str(t, s.c_str(), 10, mpreal::get_default_rnd()))
+ {
+ mpfr_set(mp, t, mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ }
+
+ mpfr_clear(t);
+ return *this;
}
+
//////////////////////////////////////////////////////////////////////////
// + Addition
inline mpreal& mpreal::operator+=(const mpreal& v)
{
- mpfr_add(mp,mp,v.mp,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_add(mp,mp,v.mp,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator+=(const mpf_t u)
{
- *this += mpreal(u);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ *this += mpreal(u);
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator+=(const mpz_t u)
{
- mpfr_add_z(mp,mp,u,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_add_z(mp,mp,u,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator+=(const mpq_t u)
{
- mpfr_add_q(mp,mp,u,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_add_q(mp,mp,u,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator+= (const long double u)
{
- *this += mpreal(u);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ *this += mpreal(u);
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator+= (const double u)
{
#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
- mpfr_add_d(mp,mp,u,default_rnd);
+ mpfr_add_d(mp,mp,u,mpreal::get_default_rnd());
#else
- *this += mpreal(u);
+ *this += mpreal(u);
#endif
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator+=(const unsigned long int u)
{
- mpfr_add_ui(mp,mp,u,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_add_ui(mp,mp,u,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator+=(const unsigned int u)
{
- mpfr_add_ui(mp,mp,u,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_add_ui(mp,mp,u,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator+=(const long int u)
{
- mpfr_add_si(mp,mp,u,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_add_si(mp,mp,u,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator+=(const int u)
{
- mpfr_add_si(mp,mp,u,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_add_si(mp,mp,u,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
#if defined (MPREAL_HAVE_INT64_SUPPORT)
-inline mpreal& mpreal::operator+=(const int64_t u){ *this += mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; }
-inline mpreal& mpreal::operator+=(const uint64_t u){ *this += mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; }
-inline mpreal& mpreal::operator-=(const int64_t u){ *this -= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; }
-inline mpreal& mpreal::operator-=(const uint64_t u){ *this -= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; }
-inline mpreal& mpreal::operator*=(const int64_t u){ *this *= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; }
-inline mpreal& mpreal::operator*=(const uint64_t u){ *this *= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; }
-inline mpreal& mpreal::operator/=(const int64_t u){ *this /= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; }
-inline mpreal& mpreal::operator/=(const uint64_t u){ *this /= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; }
+inline mpreal& mpreal::operator+=(const int64_t u){ *this += mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; }
+inline mpreal& mpreal::operator+=(const uint64_t u){ *this += mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; }
+inline mpreal& mpreal::operator-=(const int64_t u){ *this -= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; }
+inline mpreal& mpreal::operator-=(const uint64_t u){ *this -= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; }
+inline mpreal& mpreal::operator*=(const int64_t u){ *this *= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; }
+inline mpreal& mpreal::operator*=(const uint64_t u){ *this *= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; }
+inline mpreal& mpreal::operator/=(const int64_t u){ *this /= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; }
+inline mpreal& mpreal::operator/=(const uint64_t u){ *this /= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; }
#endif
-inline const mpreal mpreal::operator+()const { return mpreal(*this); }
+inline const mpreal mpreal::operator+()const { return mpreal(*this); }
inline const mpreal operator+(const mpreal& a, const mpreal& b)
{
- // prec(a+b) = max(prec(a),prec(b))
- if(a.get_prec()>b.get_prec()) return mpreal(a) += b;
- else return mpreal(b) += a;
+ mpreal c(0, (std::max)(mpfr_get_prec(a.mpfr_ptr()), mpfr_get_prec(b.mpfr_ptr())));
+ mpfr_add(c.mpfr_ptr(), a.mpfr_srcptr(), b.mpfr_srcptr(), mpreal::get_default_rnd());
+ return c;
}
inline mpreal& mpreal::operator++()
{
- return *this += 1;
+ return *this += 1;
}
inline const mpreal mpreal::operator++ (int)
{
- mpreal x(*this);
- *this += 1;
- return x;
+ mpreal x(*this);
+ *this += 1;
+ return x;
}
inline mpreal& mpreal::operator--()
{
- return *this -= 1;
+ return *this -= 1;
}
inline const mpreal mpreal::operator-- (int)
{
- mpreal x(*this);
- *this -= 1;
- return x;
+ mpreal x(*this);
+ *this -= 1;
+ return x;
}
//////////////////////////////////////////////////////////////////////////
// - Subtraction
-inline mpreal& mpreal::operator-= (const mpreal& v)
+inline mpreal& mpreal::operator-=(const mpreal& v)
{
- mpfr_sub(mp,mp,v.mp,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_sub(mp,mp,v.mp,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator-=(const mpz_t v)
{
- mpfr_sub_z(mp,mp,v,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_sub_z(mp,mp,v,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator-=(const mpq_t v)
{
- mpfr_sub_q(mp,mp,v,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_sub_q(mp,mp,v,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator-=(const long double v)
{
- *this -= mpreal(v);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ *this -= mpreal(v);
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator-=(const double v)
{
#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
- mpfr_sub_d(mp,mp,v,default_rnd);
+ mpfr_sub_d(mp,mp,v,mpreal::get_default_rnd());
#else
- *this -= mpreal(v);
+ *this -= mpreal(v);
#endif
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator-=(const unsigned long int v)
{
- mpfr_sub_ui(mp,mp,v,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_sub_ui(mp,mp,v,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator-=(const unsigned int v)
{
- mpfr_sub_ui(mp,mp,v,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_sub_ui(mp,mp,v,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator-=(const long int v)
{
- mpfr_sub_si(mp,mp,v,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_sub_si(mp,mp,v,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator-=(const int v)
{
- mpfr_sub_si(mp,mp,v,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_sub_si(mp,mp,v,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline const mpreal mpreal::operator-()const
{
- mpreal u(*this);
- mpfr_neg(u.mp,u.mp,default_rnd);
- return u;
+ mpreal u(*this);
+ mpfr_neg(u.mp,u.mp,mpreal::get_default_rnd());
+ return u;
}
inline const mpreal operator-(const mpreal& a, const mpreal& b)
{
- // prec(a-b) = max(prec(a),prec(b))
- if(a.getPrecision() >= b.getPrecision())
- {
- return mpreal(a) -= b;
- }else{
- mpreal x(a);
- x.setPrecision(b.getPrecision());
- return x -= b;
- }
+ mpreal c(0, (std::max)(mpfr_get_prec(a.mpfr_ptr()), mpfr_get_prec(b.mpfr_ptr())));
+ mpfr_sub(c.mpfr_ptr(), a.mpfr_srcptr(), b.mpfr_srcptr(), mpreal::get_default_rnd());
+ return c;
}
inline const mpreal operator-(const double b, const mpreal& a)
{
#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
- mpreal x(a);
- mpfr_d_sub(x.mp,b,a.mp,mpreal::default_rnd);
- return x;
+ mpreal x(0, mpfr_get_prec(a.mpfr_ptr()));
+ mpfr_d_sub(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());
+ return x;
#else
- return mpreal(b) -= a;
+ mpreal x(b, mpfr_get_prec(a.mpfr_ptr()));
+ x -= a;
+ return x;
#endif
}
inline const mpreal operator-(const unsigned long int b, const mpreal& a)
{
- mpreal x(a);
- mpfr_ui_sub(x.mp,b,a.mp,mpreal::default_rnd);
- return x;
+ mpreal x(0, mpfr_get_prec(a.mpfr_ptr()));
+ mpfr_ui_sub(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());
+ return x;
}
inline const mpreal operator-(const unsigned int b, const mpreal& a)
{
- mpreal x(a);
- mpfr_ui_sub(x.mp,b,a.mp,mpreal::default_rnd);
- return x;
+ mpreal x(0, mpfr_get_prec(a.mpfr_ptr()));
+ mpfr_ui_sub(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());
+ return x;
}
inline const mpreal operator-(const long int b, const mpreal& a)
{
- mpreal x(a);
- mpfr_si_sub(x.mp,b,a.mp,mpreal::default_rnd);
- return x;
+ mpreal x(0, mpfr_get_prec(a.mpfr_ptr()));
+ mpfr_si_sub(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());
+ return x;
}
inline const mpreal operator-(const int b, const mpreal& a)
{
- mpreal x(a);
- mpfr_si_sub(x.mp,b,a.mp,mpreal::default_rnd);
- return x;
+ mpreal x(0, mpfr_get_prec(a.mpfr_ptr()));
+ mpfr_si_sub(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());
+ return x;
}
//////////////////////////////////////////////////////////////////////////
// * Multiplication
inline mpreal& mpreal::operator*= (const mpreal& v)
{
- mpfr_mul(mp,mp,v.mp,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_mul(mp,mp,v.mp,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator*=(const mpz_t v)
{
- mpfr_mul_z(mp,mp,v,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_mul_z(mp,mp,v,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator*=(const mpq_t v)
{
- mpfr_mul_q(mp,mp,v,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_mul_q(mp,mp,v,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator*=(const long double v)
{
- *this *= mpreal(v);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ *this *= mpreal(v);
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator*=(const double v)
{
#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
- mpfr_mul_d(mp,mp,v,default_rnd);
+ mpfr_mul_d(mp,mp,v,mpreal::get_default_rnd());
#else
- *this *= mpreal(v);
+ *this *= mpreal(v);
#endif
-
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator*=(const unsigned long int v)
{
- mpfr_mul_ui(mp,mp,v,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_mul_ui(mp,mp,v,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator*=(const unsigned int v)
{
- mpfr_mul_ui(mp,mp,v,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_mul_ui(mp,mp,v,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator*=(const long int v)
{
- mpfr_mul_si(mp,mp,v,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_mul_si(mp,mp,v,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator*=(const int v)
{
- mpfr_mul_si(mp,mp,v,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_mul_si(mp,mp,v,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline const mpreal operator*(const mpreal& a, const mpreal& b)
{
- // prec(a*b) = max(prec(a),prec(b))
- if(a.getPrecision() >= b.getPrecision()) return mpreal(a) *= b;
- else return mpreal(b) *= a;
+ mpreal c(0, (std::max)(mpfr_get_prec(a.mpfr_ptr()), mpfr_get_prec(b.mpfr_ptr())));
+ mpfr_mul(c.mpfr_ptr(), a.mpfr_srcptr(), b.mpfr_srcptr(), mpreal::get_default_rnd());
+ return c;
}
//////////////////////////////////////////////////////////////////////////
// / Division
inline mpreal& mpreal::operator/=(const mpreal& v)
{
- mpfr_div(mp,mp,v.mp,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_div(mp,mp,v.mp,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator/=(const mpz_t v)
{
- mpfr_div_z(mp,mp,v,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_div_z(mp,mp,v,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator/=(const mpq_t v)
{
- mpfr_div_q(mp,mp,v,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_div_q(mp,mp,v,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator/=(const long double v)
{
- *this /= mpreal(v);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ *this /= mpreal(v);
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator/=(const double v)
{
#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
- mpfr_div_d(mp,mp,v,default_rnd);
+ mpfr_div_d(mp,mp,v,mpreal::get_default_rnd());
#else
- *this /= mpreal(v);
+ *this /= mpreal(v);
#endif
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator/=(const unsigned long int v)
{
- mpfr_div_ui(mp,mp,v,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_div_ui(mp,mp,v,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator/=(const unsigned int v)
{
- mpfr_div_ui(mp,mp,v,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_div_ui(mp,mp,v,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator/=(const long int v)
{
- mpfr_div_si(mp,mp,v,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_div_si(mp,mp,v,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator/=(const int v)
{
- mpfr_div_si(mp,mp,v,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_div_si(mp,mp,v,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline const mpreal operator/(const mpreal& a, const mpreal& b)
{
- // prec(a/b) = max(prec(a),prec(b))
- if(a.getPrecision() >= b.getPrecision())
- {
- return mpreal(a) /= b;
- }else{
-
- mpreal x(a);
- x.setPrecision(b.getPrecision());
- return x /= b;
- }
+ mpreal c(0, (std::max)(mpfr_get_prec(a.mpfr_ptr()), mpfr_get_prec(b.mpfr_ptr())));
+ mpfr_div(c.mpfr_ptr(), a.mpfr_srcptr(), b.mpfr_srcptr(), mpreal::get_default_rnd());
+ return c;
}
inline const mpreal operator/(const unsigned long int b, const mpreal& a)
{
- mpreal x(a);
- mpfr_ui_div(x.mp,b,a.mp,mpreal::default_rnd);
- return x;
+ mpreal x(0, mpfr_get_prec(a.mpfr_ptr()));
+ mpfr_ui_div(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());
+ return x;
}
inline const mpreal operator/(const unsigned int b, const mpreal& a)
{
- mpreal x(a);
- mpfr_ui_div(x.mp,b,a.mp,mpreal::default_rnd);
- return x;
+ mpreal x(0, mpfr_get_prec(a.mpfr_ptr()));
+ mpfr_ui_div(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());
+ return x;
}
inline const mpreal operator/(const long int b, const mpreal& a)
{
- mpreal x(a);
- mpfr_si_div(x.mp,b,a.mp,mpreal::default_rnd);
- return x;
+ mpreal x(0, mpfr_get_prec(a.mpfr_ptr()));
+ mpfr_si_div(x.mpfr_ptr(), b, a.mpfr_srcptr(),mpreal::get_default_rnd());
+ return x;
}
inline const mpreal operator/(const int b, const mpreal& a)
{
- mpreal x(a);
- mpfr_si_div(x.mp,b,a.mp,mpreal::default_rnd);
- return x;
+ mpreal x(0, mpfr_get_prec(a.mpfr_ptr()));
+ mpfr_si_div(x.mpfr_ptr(), b, a.mpfr_srcptr(),mpreal::get_default_rnd());
+ return x;
}
inline const mpreal operator/(const double b, const mpreal& a)
{
#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
- mpreal x(a);
- mpfr_d_div(x.mp,b,a.mp,mpreal::default_rnd);
- return x;
+ mpreal x(0, mpfr_get_prec(a.mpfr_ptr()));
+ mpfr_d_div(x.mpfr_ptr(), b, a.mpfr_srcptr(),mpreal::get_default_rnd());
+ return x;
#else
- return mpreal(b) /= a;
+ mpreal x(0, mpfr_get_prec(a.mpfr_ptr()));
+ x /= a;
+ return x;
#endif
}
@@ -1242,1106 +1445,1034 @@ inline const mpreal operator/(const double b, const mpreal& a)
// Shifts operators - Multiplication/Division by power of 2
inline mpreal& mpreal::operator<<=(const unsigned long int u)
{
- mpfr_mul_2ui(mp,mp,u,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_mul_2ui(mp,mp,u,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator<<=(const unsigned int u)
{
- mpfr_mul_2ui(mp,mp,static_cast<unsigned long int>(u),default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_mul_2ui(mp,mp,static_cast<unsigned long int>(u),mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator<<=(const long int u)
{
- mpfr_mul_2si(mp,mp,u,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_mul_2si(mp,mp,u,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator<<=(const int u)
{
- mpfr_mul_2si(mp,mp,static_cast<long int>(u),default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_mul_2si(mp,mp,static_cast<long int>(u),mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator>>=(const unsigned long int u)
{
- mpfr_div_2ui(mp,mp,u,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_div_2ui(mp,mp,u,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator>>=(const unsigned int u)
{
- mpfr_div_2ui(mp,mp,static_cast<unsigned long int>(u),default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_div_2ui(mp,mp,static_cast<unsigned long int>(u),mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator>>=(const long int u)
{
- mpfr_div_2si(mp,mp,u,default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_div_2si(mp,mp,u,mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::operator>>=(const int u)
{
- mpfr_div_2si(mp,mp,static_cast<long int>(u),default_rnd);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_div_2si(mp,mp,static_cast<long int>(u),mpreal::get_default_rnd());
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline const mpreal operator<<(const mpreal& v, const unsigned long int k)
{
- return mul_2ui(v,k);
+ return mul_2ui(v,k);
}
inline const mpreal operator<<(const mpreal& v, const unsigned int k)
{
- return mul_2ui(v,static_cast<unsigned long int>(k));
+ return mul_2ui(v,static_cast<unsigned long int>(k));
}
inline const mpreal operator<<(const mpreal& v, const long int k)
{
- return mul_2si(v,k);
+ return mul_2si(v,k);
}
inline const mpreal operator<<(const mpreal& v, const int k)
{
- return mul_2si(v,static_cast<long int>(k));
+ return mul_2si(v,static_cast<long int>(k));
}
inline const mpreal operator>>(const mpreal& v, const unsigned long int k)
{
- return div_2ui(v,k);
+ return div_2ui(v,k);
}
inline const mpreal operator>>(const mpreal& v, const long int k)
{
- return div_2si(v,k);
+ return div_2si(v,k);
}
inline const mpreal operator>>(const mpreal& v, const unsigned int k)
{
- return div_2ui(v,static_cast<unsigned long int>(k));
+ return div_2ui(v,static_cast<unsigned long int>(k));
}
inline const mpreal operator>>(const mpreal& v, const int k)
{
- return div_2si(v,static_cast<long int>(k));
+ return div_2si(v,static_cast<long int>(k));
}
// mul_2ui
inline const mpreal mul_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode)
{
- mpreal x(v);
- mpfr_mul_2ui(x.mp,v.mp,k,rnd_mode);
- return x;
+ mpreal x(v);
+ mpfr_mul_2ui(x.mp,v.mp,k,rnd_mode);
+ return x;
}
// mul_2si
inline const mpreal mul_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode)
{
- mpreal x(v);
- mpfr_mul_2si(x.mp,v.mp,k,rnd_mode);
- return x;
+ mpreal x(v);
+ mpfr_mul_2si(x.mp,v.mp,k,rnd_mode);
+ return x;
}
inline const mpreal div_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode)
{
- mpreal x(v);
- mpfr_div_2ui(x.mp,v.mp,k,rnd_mode);
- return x;
+ mpreal x(v);
+ mpfr_div_2ui(x.mp,v.mp,k,rnd_mode);
+ return x;
}
inline const mpreal div_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode)
{
- mpreal x(v);
- mpfr_div_2si(x.mp,v.mp,k,rnd_mode);
- return x;
+ mpreal x(v);
+ mpfr_div_2si(x.mp,v.mp,k,rnd_mode);
+ return x;
}
//////////////////////////////////////////////////////////////////////////
//Boolean operators
-inline bool operator > (const mpreal& a, const mpreal& b){ return (mpfr_greater_p(a.mp,b.mp) !=0); }
-inline bool operator >= (const mpreal& a, const mpreal& b){ return (mpfr_greaterequal_p(a.mp,b.mp) !=0); }
-inline bool operator < (const mpreal& a, const mpreal& b){ return (mpfr_less_p(a.mp,b.mp) !=0); }
-inline bool operator <= (const mpreal& a, const mpreal& b){ return (mpfr_lessequal_p(a.mp,b.mp) !=0); }
-inline bool operator == (const mpreal& a, const mpreal& b){ return (mpfr_equal_p(a.mp,b.mp) !=0); }
-inline bool operator != (const mpreal& a, const mpreal& b){ return (mpfr_lessgreater_p(a.mp,b.mp) !=0); }
-
-inline bool operator == (const mpreal& a, const unsigned long int b ){ return (mpfr_cmp_ui(a.mp,b) == 0); }
-inline bool operator == (const mpreal& a, const unsigned int b ){ return (mpfr_cmp_ui(a.mp,b) == 0); }
-inline bool operator == (const mpreal& a, const long int b ){ return (mpfr_cmp_si(a.mp,b) == 0); }
-inline bool operator == (const mpreal& a, const int b ){ return (mpfr_cmp_si(a.mp,b) == 0); }
-inline bool operator == (const mpreal& a, const long double b ){ return (mpfr_cmp_ld(a.mp,b) == 0); }
-inline bool operator == (const mpreal& a, const double b ){ return (mpfr_cmp_d(a.mp,b) == 0); }
-
-
-inline bool isnan (const mpreal& v){ return (mpfr_nan_p(v.mp) != 0); }
-inline bool isinf (const mpreal& v){ return (mpfr_inf_p(v.mp) != 0); }
-inline bool isfinite(const mpreal& v){ return (mpfr_number_p(v.mp) != 0); }
-inline bool iszero (const mpreal& v){ return (mpfr_zero_p(v.mp) != 0); }
-inline bool isint (const mpreal& v){ return (mpfr_integer_p(v.mp) != 0); }
+inline bool operator > (const mpreal& a, const mpreal& b){ return (mpfr_greater_p(a.mp,b.mp) !=0); }
+inline bool operator >= (const mpreal& a, const mpreal& b){ return (mpfr_greaterequal_p(a.mp,b.mp) !=0); }
+inline bool operator < (const mpreal& a, const mpreal& b){ return (mpfr_less_p(a.mp,b.mp) !=0); }
+inline bool operator <= (const mpreal& a, const mpreal& b){ return (mpfr_lessequal_p(a.mp,b.mp) !=0); }
+inline bool operator == (const mpreal& a, const mpreal& b){ return (mpfr_equal_p(a.mp,b.mp) !=0); }
+inline bool operator != (const mpreal& a, const mpreal& b){ return (mpfr_lessgreater_p(a.mp,b.mp) !=0); }
+
+inline bool operator == (const mpreal& a, const unsigned long int b ){ return (mpfr_cmp_ui(a.mp,b) == 0); }
+inline bool operator == (const mpreal& a, const unsigned int b ){ return (mpfr_cmp_ui(a.mp,b) == 0); }
+inline bool operator == (const mpreal& a, const long int b ){ return (mpfr_cmp_si(a.mp,b) == 0); }
+inline bool operator == (const mpreal& a, const int b ){ return (mpfr_cmp_si(a.mp,b) == 0); }
+inline bool operator == (const mpreal& a, const long double b ){ return (mpfr_cmp_ld(a.mp,b) == 0); }
+inline bool operator == (const mpreal& a, const double b ){ return (mpfr_cmp_d(a.mp,b) == 0); }
+
+
+inline bool isnan (const mpreal& v){ return (mpfr_nan_p(v.mp) != 0); }
+inline bool isinf (const mpreal& v){ return (mpfr_inf_p(v.mp) != 0); }
+inline bool isfinite (const mpreal& v){ return (mpfr_number_p(v.mp) != 0); }
+inline bool iszero (const mpreal& v){ return (mpfr_zero_p(v.mp) != 0); }
+inline bool isint (const mpreal& v){ return (mpfr_integer_p(v.mp) != 0); }
#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))
-inline bool isregular(const mpreal& v){ return (mpfr_regular_p(v.mp));}
+inline bool isregular(const mpreal& v){ return (mpfr_regular_p(v.mp));}
#endif
//////////////////////////////////////////////////////////////////////////
// Type Converters
-inline long mpreal::toLong() const { return mpfr_get_si(mp,GMP_RNDZ); }
-inline unsigned long mpreal::toULong() const { return mpfr_get_ui(mp,GMP_RNDZ); }
-inline double mpreal::toDouble() const { return mpfr_get_d(mp,default_rnd); }
-inline long double mpreal::toLDouble() const { return mpfr_get_ld(mp,default_rnd); }
+inline long mpreal::toLong (mp_rnd_t mode) const { return mpfr_get_si(mp, mode); }
+inline unsigned long mpreal::toULong (mp_rnd_t mode) const { return mpfr_get_ui(mp, mode); }
+inline double mpreal::toDouble (mp_rnd_t mode) const { return mpfr_get_d (mp, mode); }
+inline long double mpreal::toLDouble(mp_rnd_t mode) const { return mpfr_get_ld(mp, mode); }
#if defined (MPREAL_HAVE_INT64_SUPPORT)
-inline int64_t mpreal::toInt64() const{ return mpfr_get_sj(mp,GMP_RNDZ); }
-inline uint64_t mpreal::toUInt64() const{ return mpfr_get_uj(mp,GMP_RNDZ); }
+inline int64_t mpreal::toInt64 (mp_rnd_t mode) const{ return mpfr_get_sj(mp, mode); }
+inline uint64_t mpreal::toUInt64(mp_rnd_t mode) const{ return mpfr_get_uj(mp, mode); }
+#endif
+
+inline ::mpfr_ptr mpreal::mpfr_ptr() { return mp; }
+inline ::mpfr_srcptr mpreal::mpfr_ptr() const { return mp; }
+inline ::mpfr_srcptr mpreal::mpfr_srcptr() const { return mp; }
+
+template <class T>
+inline std::string toString(T t, std::ios_base & (*f)(std::ios_base&))
+{
+ std::ostringstream oss;
+ oss << f << t;
+ return oss.str();
+}
+
+#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
+
+inline std::string mpreal::toString(const std::string& format) const
+{
+ char *s = NULL;
+ std::string out;
+
+ if( !format.empty() )
+ {
+ if(!(mpfr_asprintf(&s,format.c_str(),mp) < 0))
+ {
+ out = std::string(s);
+
+ mpfr_free_str(s);
+ }
+ }
+
+ return out;
+}
+
+#endif
+
+inline std::string mpreal::toString(int n, int b, mp_rnd_t mode) const
+{
+ (void)b;
+ (void)mode;
+
+#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
+
+ // Use MPFR native function for output
+ char format[128];
+ int digits;
+
+ digits = n > 0 ? n : bits2digits(mpfr_get_prec(mp));
+
+ sprintf(format,"%%.%dRNg",digits); // Default format
+
+ return toString(std::string(format));
+
+#else
+
+ char *s, *ns = NULL;
+ size_t slen, nslen;
+ mp_exp_t exp;
+ std::string out;
+
+ if(mpfr_inf_p(mp))
+ {
+ if(mpfr_sgn(mp)>0) return "+Inf";
+ else return "-Inf";
+ }
+
+ if(mpfr_zero_p(mp)) return "0";
+ if(mpfr_nan_p(mp)) return "NaN";
+
+ s = mpfr_get_str(NULL,&exp,b,0,mp,mode);
+ ns = mpfr_get_str(NULL,&exp,b,n,mp,mode);
+
+ if(s!=NULL && ns!=NULL)
+ {
+ slen = strlen(s);
+ nslen = strlen(ns);
+ if(nslen<=slen)
+ {
+ mpfr_free_str(s);
+ s = ns;
+ slen = nslen;
+ }
+ else {
+ mpfr_free_str(ns);
+ }
+
+ // Make human eye-friendly formatting if possible
+ if (exp>0 && static_cast<size_t>(exp)<slen)
+ {
+ if(s[0]=='-')
+ {
+ // Remove zeros starting from right end
+ char* ptr = s+slen-1;
+ while (*ptr=='0' && ptr>s+exp) ptr--;
+
+ if(ptr==s+exp) out = std::string(s,exp+1);
+ else out = std::string(s,exp+1)+'.'+std::string(s+exp+1,ptr-(s+exp+1)+1);
+
+ //out = string(s,exp+1)+'.'+string(s+exp+1);
+ }
+ else
+ {
+ // Remove zeros starting from right end
+ char* ptr = s+slen-1;
+ while (*ptr=='0' && ptr>s+exp-1) ptr--;
+
+ if(ptr==s+exp-1) out = std::string(s,exp);
+ else out = std::string(s,exp)+'.'+std::string(s+exp,ptr-(s+exp)+1);
+
+ //out = string(s,exp)+'.'+string(s+exp);
+ }
+
+ }else{ // exp<0 || exp>slen
+ if(s[0]=='-')
+ {
+ // Remove zeros starting from right end
+ char* ptr = s+slen-1;
+ while (*ptr=='0' && ptr>s+1) ptr--;
+
+ if(ptr==s+1) out = std::string(s,2);
+ else out = std::string(s,2)+'.'+std::string(s+2,ptr-(s+2)+1);
+
+ //out = string(s,2)+'.'+string(s+2);
+ }
+ else
+ {
+ // Remove zeros starting from right end
+ char* ptr = s+slen-1;
+ while (*ptr=='0' && ptr>s) ptr--;
+
+ if(ptr==s) out = std::string(s,1);
+ else out = std::string(s,1)+'.'+std::string(s+1,ptr-(s+1)+1);
+
+ //out = string(s,1)+'.'+string(s+1);
+ }
+
+ // Make final string
+ if(--exp)
+ {
+ if(exp>0) out += "e+"+mpfr::toString<mp_exp_t>(exp,std::dec);
+ else out += "e"+mpfr::toString<mp_exp_t>(exp,std::dec);
+ }
+ }
+
+ mpfr_free_str(s);
+ return out;
+ }else{
+ return "conversion error!";
+ }
#endif
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// I/O
+inline std::ostream& operator<<(std::ostream& os, const mpreal& v)
+{
+ return os<<v.toString(static_cast<int>(os.precision()));
+}
-inline ::mpfr_ptr mpreal::mpfr_ptr() { return mp; }
-inline ::mpfr_srcptr mpreal::mpfr_srcptr() const { return const_cast< ::mpfr_srcptr >(mp); }
+inline std::istream& operator>>(std::istream &is, mpreal& v)
+{
+ // ToDo, use cout::hexfloat and other flags to setup base
+ std::string tmp;
+ is >> tmp;
+ mpfr_set_str(v.mp, tmp.c_str(), 10, mpreal::get_default_rnd());
+ return is;
+}
//////////////////////////////////////////////////////////////////////////
-// Bits - decimal digits relation
-// bits = ceil(digits*log[2](10))
-// digits = floor(bits*log[10](2))
+// Bits - decimal digits relation
+// bits = ceil(digits*log[2](10))
+// digits = floor(bits*log[10](2))
inline mp_prec_t digits2bits(int d)
{
- const double LOG2_10 = 3.3219280948873624;
-
- d = 10>d?10:d;
+ const double LOG2_10 = 3.3219280948873624;
- return (mp_prec_t)std::ceil((d)*LOG2_10);
+ return (mp_prec_t) std::ceil( d * LOG2_10 );
}
inline int bits2digits(mp_prec_t b)
{
- const double LOG10_2 = 0.30102999566398119;
+ const double LOG10_2 = 0.30102999566398119;
- b = 34>b?34:b;
-
- return (int)std::floor((b)*LOG10_2);
+ return (int) std::floor( b * LOG10_2 );
}
//////////////////////////////////////////////////////////////////////////
// Set/Get number properties
inline int sgn(const mpreal& v)
{
- int r = mpfr_signbit(v.mp);
- return (r>0?-1:1);
+ int r = mpfr_signbit(v.mp);
+ return (r>0?-1:1);
}
inline mpreal& mpreal::setSign(int sign, mp_rnd_t RoundingMode)
{
- mpfr_setsign(mp,mp,(sign<0?1:0),RoundingMode);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_setsign(mp,mp,(sign < 0 ? 1 : 0),RoundingMode);
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline int mpreal::getPrecision() const
{
- return mpfr_get_prec(mp);
+ return mpfr_get_prec(mp);
}
inline mpreal& mpreal::setPrecision(int Precision, mp_rnd_t RoundingMode)
{
- mpfr_prec_round(mp,Precision, RoundingMode);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_prec_round(mp, Precision, RoundingMode);
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mpreal& mpreal::setInf(int sign)
{
- mpfr_set_inf(mp,sign);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
-}
+ mpfr_set_inf(mp,sign);
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
+}
inline mpreal& mpreal::setNan()
{
- mpfr_set_nan(mp);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+ mpfr_set_nan(mp);
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
-inline mpreal& mpreal::setZero(int sign)
+inline mpreal& mpreal::setZero(int sign)
{
- mpfr_set_zero(mp,sign);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return *this;
+
+#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))
+ mpfr_set_zero(mp, sign);
+#else
+ mpfr_set_si(mp, 0, (mpfr_get_default_rounding_mode)());
+ setSign(sign);
+#endif
+
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return *this;
}
inline mp_prec_t mpreal::get_prec() const
{
- return mpfr_get_prec(mp);
+ return mpfr_get_prec(mp);
}
inline void mpreal::set_prec(mp_prec_t prec, mp_rnd_t rnd_mode)
{
- mpfr_prec_round(mp,prec,rnd_mode);
- MPREAL_MSVC_DEBUGVIEW_CODE;
+ mpfr_prec_round(mp,prec,rnd_mode);
+ MPREAL_MSVC_DEBUGVIEW_CODE;
}
inline mp_exp_t mpreal::get_exp ()
{
- return mpfr_get_exp(mp);
+ return mpfr_get_exp(mp);
}
inline int mpreal::set_exp (mp_exp_t e)
{
- int x = mpfr_set_exp(mp, e);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return x;
+ int x = mpfr_set_exp(mp, e);
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return x;
}
inline const mpreal frexp(const mpreal& v, mp_exp_t* exp)
{
- mpreal x(v);
- *exp = x.get_exp();
- x.set_exp(0);
- return x;
+ mpreal x(v);
+ *exp = x.get_exp();
+ x.set_exp(0);
+ return x;
}
inline const mpreal ldexp(const mpreal& v, mp_exp_t exp)
{
- mpreal x(v);
+ mpreal x(v);
- // rounding is not important since we just increasing the exponent
- mpfr_mul_2si(x.mp,x.mp,exp,mpreal::default_rnd);
- return x;
+ // rounding is not important since we just increasing the exponent
+ mpfr_mul_2si(x.mp,x.mp,exp,mpreal::get_default_rnd());
+ return x;
}
-inline const mpreal machine_epsilon(mp_prec_t prec)
+inline mpreal machine_epsilon(mp_prec_t prec)
{
- // the smallest eps such that 1.0+eps != 1.0
- // depends (of cause) on the precision
- return machine_epsilon(mpreal(1,prec));
+ /* the smallest eps such that 1 + eps != 1 */
+ return machine_epsilon(mpreal(1, prec));
}
-inline const mpreal machine_epsilon(const mpreal& x)
-{
- if( x < 0)
- {
- return nextabove(-x)+x;
- }else{
- return nextabove(x)-x;
- }
+inline mpreal machine_epsilon(const mpreal& x)
+{
+ /* the smallest eps such that x + eps != x */
+ if( x < 0)
+ {
+ return nextabove(-x)+x;
+ }else{
+ return nextabove(x)-x;
+ }
}
-inline const mpreal mpreal_min(mp_prec_t prec)
+// minval is 'safe' meaning 1 / minval does not overflow
+inline mpreal minval(mp_prec_t prec)
{
- // min = 1/2*2^emin = 2^(emin-1)
-
- return mpreal(1,prec) << mpreal::get_emin()-1;
+ /* min = 1/2 * 2^emin = 2^(emin - 1) */
+ return mpreal(1, prec) << mpreal::get_emin()-1;
}
-inline const mpreal mpreal_max(mp_prec_t prec)
+// maxval is 'safe' meaning 1 / maxval does not underflow
+inline mpreal maxval(mp_prec_t prec)
{
- // max = (1-eps)*2^emax, assume eps = 0?,
- // and use emax-1 to prevent value to be +inf
- // max = 2^(emax-1)
-
- return mpreal(1,prec) << mpreal::get_emax()-1;
+ /* max = (1 - eps) * 2^emax, eps is machine epsilon */
+ return (mpreal(1, prec) - machine_epsilon(prec)) << mpreal::get_emax();
}
inline bool isEqualUlps(const mpreal& a, const mpreal& b, int maxUlps)
{
- /*
- maxUlps - a and b can be apart by maxUlps binary numbers.
- */
return abs(a - b) <= machine_epsilon((max)(abs(a), abs(b))) * maxUlps;
}
inline bool isEqualFuzzy(const mpreal& a, const mpreal& b, const mpreal& eps)
{
- return abs(a - b) <= (min)(abs(a), abs(b)) * eps;
+ return abs(a - b) <= (min)(abs(a), abs(b)) * eps;
}
inline bool isEqualFuzzy(const mpreal& a, const mpreal& b)
{
- return isEqualFuzzy(a,b,machine_epsilon((std::min)(abs(a), abs(b))));
+ return isEqualFuzzy(a, b, machine_epsilon((min)(abs(a), abs(b))));
}
inline const mpreal modf(const mpreal& v, mpreal& n)
{
- mpreal frac(v);
+ mpreal frac(v);
- // rounding is not important since we are using the same number
- mpfr_frac(frac.mp,frac.mp,mpreal::default_rnd);
- mpfr_trunc(n.mp,v.mp);
- return frac;
+ // rounding is not important since we are using the same number
+ mpfr_frac(frac.mp,frac.mp,mpreal::get_default_rnd());
+ mpfr_trunc(n.mp,v.mp);
+ return frac;
}
inline int mpreal::check_range (int t, mp_rnd_t rnd_mode)
{
- return mpfr_check_range(mp,t,rnd_mode);
+ return mpfr_check_range(mp,t,rnd_mode);
}
inline int mpreal::subnormalize (int t,mp_rnd_t rnd_mode)
{
- int r = mpfr_subnormalize(mp,t,rnd_mode);
- MPREAL_MSVC_DEBUGVIEW_CODE;
- return r;
+ int r = mpfr_subnormalize(mp,t,rnd_mode);
+ MPREAL_MSVC_DEBUGVIEW_CODE;
+ return r;
}
inline mp_exp_t mpreal::get_emin (void)
{
- return mpfr_get_emin();
+ return mpfr_get_emin();
}
inline int mpreal::set_emin (mp_exp_t exp)
{
- return mpfr_set_emin(exp);
+ return mpfr_set_emin(exp);
}
inline mp_exp_t mpreal::get_emax (void)
{
- return mpfr_get_emax();
+ return mpfr_get_emax();
}
inline int mpreal::set_emax (mp_exp_t exp)
{
- return mpfr_set_emax(exp);
+ return mpfr_set_emax(exp);
}
inline mp_exp_t mpreal::get_emin_min (void)
{
- return mpfr_get_emin_min();
+ return mpfr_get_emin_min();
}
inline mp_exp_t mpreal::get_emin_max (void)
{
- return mpfr_get_emin_max();
+ return mpfr_get_emin_max();
}
inline mp_exp_t mpreal::get_emax_min (void)
{
- return mpfr_get_emax_min();
+ return mpfr_get_emax_min();
}
inline mp_exp_t mpreal::get_emax_max (void)
{
- return mpfr_get_emax_max();
+ return mpfr_get_emax_max();
}
//////////////////////////////////////////////////////////////////////////
// Mathematical Functions
//////////////////////////////////////////////////////////////////////////
-inline const mpreal sqr(const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_sqr(x.mp,x.mp,rnd_mode);
- return x;
-}
+#define MPREAL_UNARY_MATH_FUNCTION_BODY(f) \
+ mpreal y(0, mpfr_get_prec(x.mpfr_srcptr())); \
+ mpfr_##f(y.mpfr_ptr(), x.mpfr_srcptr(), r); \
+ return y;
-inline const mpreal sqrt(const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_sqrt(x.mp,x.mp,rnd_mode);
- return x;
-}
+inline const mpreal sqr (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(sqr ); }
+inline const mpreal sqrt (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(sqrt); }
-inline const mpreal sqrt(const unsigned long int v, mp_rnd_t rnd_mode)
+inline const mpreal sqrt(const unsigned long int x, mp_rnd_t r)
{
- mpreal x;
- mpfr_sqrt_ui(x.mp,v,rnd_mode);
- return x;
+ mpreal y;
+ mpfr_sqrt_ui(y.mpfr_ptr(), x, r);
+ return y;
}
inline const mpreal sqrt(const unsigned int v, mp_rnd_t rnd_mode)
{
- return sqrt(static_cast<unsigned long int>(v),rnd_mode);
+ return sqrt(static_cast<unsigned long int>(v),rnd_mode);
}
inline const mpreal sqrt(const long int v, mp_rnd_t rnd_mode)
{
- if (v>=0) return sqrt(static_cast<unsigned long int>(v),rnd_mode);
- else return mpreal().setNan(); // NaN
+ if (v>=0) return sqrt(static_cast<unsigned long int>(v),rnd_mode);
+ else return mpreal().setNan(); // NaN
}
inline const mpreal sqrt(const int v, mp_rnd_t rnd_mode)
{
- if (v>=0) return sqrt(static_cast<unsigned long int>(v),rnd_mode);
- else return mpreal().setNan(); // NaN
+ if (v>=0) return sqrt(static_cast<unsigned long int>(v),rnd_mode);
+ else return mpreal().setNan(); // NaN
}
-inline const mpreal sqrt(const long double v, mp_rnd_t rnd_mode)
+inline const mpreal root(const mpreal& x, unsigned long int k, mp_rnd_t r)
{
- return sqrt(mpreal(v),rnd_mode);
+ mpreal y(0, mpfr_get_prec(x.mpfr_srcptr()));
+ mpfr_root(y.mpfr_ptr(), x.mpfr_srcptr(), k, r);
+ return y;
}
-inline const mpreal sqrt(const double v, mp_rnd_t rnd_mode)
+inline const mpreal dim(const mpreal& a, const mpreal& b, mp_rnd_t r)
{
- return sqrt(mpreal(v),rnd_mode);
-}
-
-inline const mpreal cbrt(const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_cbrt(x.mp,x.mp,rnd_mode);
- return x;
-}
-
-inline const mpreal root(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_root(x.mp,x.mp,k,rnd_mode);
- return x;
-}
-
-inline const mpreal fabs(const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_abs(x.mp,x.mp,rnd_mode);
- return x;
-}
-
-inline const mpreal abs(const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_abs(x.mp,x.mp,rnd_mode);
- return x;
-}
-
-inline const mpreal dim(const mpreal& a, const mpreal& b, mp_rnd_t rnd_mode)
-{
- mpreal x(a);
- mpfr_dim(x.mp,a.mp,b.mp,rnd_mode);
- return x;
+ mpreal y(0, mpfr_get_prec(a.mpfr_srcptr()));
+ mpfr_dim(y.mpfr_ptr(), a.mpfr_srcptr(), b.mpfr_srcptr(), r);
+ return y;
}
inline int cmpabs(const mpreal& a,const mpreal& b)
{
- return mpfr_cmpabs(a.mp,b.mp);
-}
-
-inline const mpreal log (const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_log(x.mp,v.mp,rnd_mode);
- return x;
-}
-
-inline const mpreal log2(const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_log2(x.mp,v.mp,rnd_mode);
- return x;
+ return mpfr_cmpabs(a.mp,b.mp);
}
-inline const mpreal log10(const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_log10(x.mp,v.mp,rnd_mode);
- return x;
-}
-
-inline const mpreal exp(const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_exp(x.mp,v.mp,rnd_mode);
- return x;
-}
-
-inline const mpreal exp2(const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_exp2(x.mp,v.mp,rnd_mode);
- return x;
-}
-
-inline const mpreal exp10(const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_exp10(x.mp,v.mp,rnd_mode);
- return x;
-}
-
-inline const mpreal cos(const mpreal& v, mp_rnd_t rnd_mode)
+inline int sin_cos(mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode)
{
- mpreal x(v);
- mpfr_cos(x.mp,v.mp,rnd_mode);
- return x;
-}
+ return mpfr_sin_cos(s.mp,c.mp,v.mp,rnd_mode);
+}
+
+inline const mpreal sqrt (const long double v, mp_rnd_t rnd_mode) { return sqrt(mpreal(v),rnd_mode); }
+inline const mpreal sqrt (const double v, mp_rnd_t rnd_mode) { return sqrt(mpreal(v),rnd_mode); }
+
+inline const mpreal cbrt (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(cbrt ); }
+inline const mpreal fabs (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(abs ); }
+inline const mpreal abs (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(abs ); }
+inline const mpreal log (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(log ); }
+inline const mpreal log2 (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(log2 ); }
+inline const mpreal log10 (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(log10); }
+inline const mpreal exp (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(exp ); }
+inline const mpreal exp2 (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(exp2 ); }
+inline const mpreal exp10 (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(exp10); }
+inline const mpreal cos (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(cos ); }
+inline const mpreal sin (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(sin ); }
+inline const mpreal tan (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(tan ); }
+inline const mpreal sec (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(sec ); }
+inline const mpreal csc (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(csc ); }
+inline const mpreal cot (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(cot ); }
+inline const mpreal acos (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(acos); }
+inline const mpreal asin (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(asin); }
+inline const mpreal atan (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(atan); }
+
+inline const mpreal acot (const mpreal& v, mp_rnd_t r) { return atan (1/v, r); }
+inline const mpreal asec (const mpreal& v, mp_rnd_t r) { return acos (1/v, r); }
+inline const mpreal acsc (const mpreal& v, mp_rnd_t r) { return asin (1/v, r); }
+inline const mpreal acoth (const mpreal& v, mp_rnd_t r) { return atanh(1/v, r); }
+inline const mpreal asech (const mpreal& v, mp_rnd_t r) { return acosh(1/v, r); }
+inline const mpreal acsch (const mpreal& v, mp_rnd_t r) { return asinh(1/v, r); }
+
+inline const mpreal cosh (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(cosh ); }
+inline const mpreal sinh (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(sinh ); }
+inline const mpreal tanh (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(tanh ); }
+inline const mpreal sech (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(sech ); }
+inline const mpreal csch (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(csch ); }
+inline const mpreal coth (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(coth ); }
+inline const mpreal acosh (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(acosh); }
+inline const mpreal asinh (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(asinh); }
+inline const mpreal atanh (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(atanh); }
+
+inline const mpreal log1p (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(log1p ); }
+inline const mpreal expm1 (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(expm1 ); }
+inline const mpreal eint (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(eint ); }
+inline const mpreal gamma (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(gamma ); }
+inline const mpreal lngamma (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(lngamma); }
+inline const mpreal zeta (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(zeta ); }
+inline const mpreal erf (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(erf ); }
+inline const mpreal erfc (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(erfc ); }
+inline const mpreal besselj0(const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(j0 ); }
+inline const mpreal besselj1(const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(j1 ); }
+inline const mpreal bessely0(const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(y0 ); }
+inline const mpreal bessely1(const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(y1 ); }
-inline const mpreal sin(const mpreal& v, mp_rnd_t rnd_mode)
+inline const mpreal atan2 (const mpreal& y, const mpreal& x, mp_rnd_t rnd_mode)
{
- mpreal x(v);
- mpfr_sin(x.mp,v.mp,rnd_mode);
- return x;
-}
+ mpreal a;
+ mp_prec_t yp, xp;
-inline const mpreal tan(const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_tan(x.mp,v.mp,rnd_mode);
- return x;
-}
+ yp = y.get_prec();
+ xp = x.get_prec();
-inline const mpreal sec(const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_sec(x.mp,v.mp,rnd_mode);
- return x;
-}
+ a.set_prec(yp>xp?yp:xp);
-inline const mpreal csc(const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_csc(x.mp,v.mp,rnd_mode);
- return x;
-}
+ mpfr_atan2(a.mp, y.mp, x.mp, rnd_mode);
-inline const mpreal cot(const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_cot(x.mp,v.mp,rnd_mode);
- return x;
+ return a;
}
-inline int sin_cos(mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode)
+inline const mpreal hypot (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
{
- return mpfr_sin_cos(s.mp,c.mp,v.mp,rnd_mode);
-}
+ mpreal a;
+ mp_prec_t yp, xp;
-inline const mpreal acos (const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_acos(x.mp,v.mp,rnd_mode);
- return x;
-}
+ yp = y.get_prec();
+ xp = x.get_prec();
-inline const mpreal asin (const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_asin(x.mp,v.mp,rnd_mode);
- return x;
-}
+ a.set_prec(yp>xp?yp:xp);
-inline const mpreal atan (const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_atan(x.mp,v.mp,rnd_mode);
- return x;
-}
+ mpfr_hypot(a.mp, x.mp, y.mp, rnd_mode);
-inline const mpreal acot (const mpreal& v, mp_rnd_t rnd_mode)
-{
- return atan(1/v, rnd_mode);
+ return a;
}
-inline const mpreal asec (const mpreal& v, mp_rnd_t rnd_mode)
-{
- return acos(1/v, rnd_mode);
-}
+inline const mpreal remainder (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
+{
+ mpreal a;
+ mp_prec_t yp, xp;
-inline const mpreal acsc (const mpreal& v, mp_rnd_t rnd_mode)
-{
- return asin(1/v, rnd_mode);
-}
+ yp = y.get_prec();
+ xp = x.get_prec();
-inline const mpreal acoth (const mpreal& v, mp_rnd_t rnd_mode)
-{
- return atanh(1/v, rnd_mode);
-}
+ a.set_prec(yp>xp?yp:xp);
-inline const mpreal asech (const mpreal& v, mp_rnd_t rnd_mode)
-{
- return acosh(1/v, rnd_mode);
-}
+ mpfr_remainder(a.mp, x.mp, y.mp, rnd_mode);
-inline const mpreal acsch (const mpreal& v, mp_rnd_t rnd_mode)
-{
- return asinh(1/v, rnd_mode);
+ return a;
}
-inline const mpreal atan2 (const mpreal& y, const mpreal& x, mp_rnd_t rnd_mode)
+inline const mpreal remquo (long* q, const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
{
- mpreal a;
- mp_prec_t yp, xp;
+ mpreal a;
+ mp_prec_t yp, xp;
- yp = y.get_prec();
- xp = x.get_prec();
+ yp = y.get_prec();
+ xp = x.get_prec();
- a.set_prec(yp>xp?yp:xp);
+ a.set_prec(yp>xp?yp:xp);
- mpfr_atan2(a.mp, y.mp, x.mp, rnd_mode);
+ mpfr_remquo(a.mp,q, x.mp, y.mp, rnd_mode);
- return a;
+ return a;
}
-inline const mpreal cosh (const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_cosh(x.mp,v.mp,rnd_mode);
- return x;
-}
-
-inline const mpreal sinh (const mpreal& v, mp_rnd_t rnd_mode)
+inline const mpreal fac_ui (unsigned long int v, mp_prec_t prec, mp_rnd_t rnd_mode)
{
- mpreal x(v);
- mpfr_sinh(x.mp,v.mp,rnd_mode);
- return x;
+ mpreal x(0, prec);
+ mpfr_fac_ui(x.mp,v,rnd_mode);
+ return x;
}
-inline const mpreal tanh (const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_tanh(x.mp,v.mp,rnd_mode);
- return x;
-}
-inline const mpreal sech (const mpreal& v, mp_rnd_t rnd_mode)
+inline const mpreal lgamma (const mpreal& v, int *signp, mp_rnd_t rnd_mode)
{
- mpreal x(v);
- mpfr_sech(x.mp,v.mp,rnd_mode);
- return x;
-}
+ mpreal x(v);
+ int tsignp;
-inline const mpreal csch (const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_csch(x.mp,v.mp,rnd_mode);
- return x;
-}
+ if(signp) mpfr_lgamma(x.mp,signp,v.mp,rnd_mode);
+ else mpfr_lgamma(x.mp,&tsignp,v.mp,rnd_mode);
-inline const mpreal coth (const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_coth(x.mp,v.mp,rnd_mode);
- return x;
+ return x;
}
-inline const mpreal acosh (const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_acosh(x.mp,v.mp,rnd_mode);
- return x;
-}
-inline const mpreal asinh (const mpreal& v, mp_rnd_t rnd_mode)
+inline const mpreal besseljn (long n, const mpreal& x, mp_rnd_t r)
{
- mpreal x(v);
- mpfr_asinh(x.mp,v.mp,rnd_mode);
- return x;
+ mpreal y(0, mpfr_get_prec(x.mpfr_srcptr()));
+ mpfr_jn(y.mpfr_ptr(), n, x.mpfr_srcptr(), r);
+ return y;
}
-inline const mpreal atanh (const mpreal& v, mp_rnd_t rnd_mode)
+inline const mpreal besselyn (long n, const mpreal& x, mp_rnd_t r)
{
- mpreal x(v);
- mpfr_atanh(x.mp,v.mp,rnd_mode);
- return x;
+ mpreal y(0, mpfr_get_prec(x.mpfr_srcptr()));
+ mpfr_yn(y.mpfr_ptr(), n, x.mpfr_srcptr(), r);
+ return y;
}
-inline const mpreal hypot (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
+inline const mpreal fma (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode)
{
- mpreal a;
- mp_prec_t yp, xp;
-
- yp = y.get_prec();
- xp = x.get_prec();
-
- a.set_prec(yp>xp?yp:xp);
-
- mpfr_hypot(a.mp, x.mp, y.mp, rnd_mode);
-
- return a;
-}
+ mpreal a;
+ mp_prec_t p1, p2, p3;
-inline const mpreal remainder (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
-{
- mpreal a;
- mp_prec_t yp, xp;
-
- yp = y.get_prec();
- xp = x.get_prec();
+ p1 = v1.get_prec();
+ p2 = v2.get_prec();
+ p3 = v3.get_prec();
- a.set_prec(yp>xp?yp:xp);
+ a.set_prec(p3>p2?(p3>p1?p3:p1):(p2>p1?p2:p1));
- mpfr_remainder(a.mp, x.mp, y.mp, rnd_mode);
-
- return a;
+ mpfr_fma(a.mp,v1.mp,v2.mp,v3.mp,rnd_mode);
+ return a;
}
-inline const mpreal fac_ui (unsigned long int v, mp_prec_t prec, mp_rnd_t rnd_mode)
+inline const mpreal fms (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode)
{
- mpreal x(0,prec);
- mpfr_fac_ui(x.mp,v,rnd_mode);
- return x;
-}
+ mpreal a;
+ mp_prec_t p1, p2, p3;
-inline const mpreal log1p (const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_log1p(x.mp,v.mp,rnd_mode);
- return x;
-}
+ p1 = v1.get_prec();
+ p2 = v2.get_prec();
+ p3 = v3.get_prec();
-inline const mpreal expm1 (const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_expm1(x.mp,v.mp,rnd_mode);
- return x;
-}
+ a.set_prec(p3>p2?(p3>p1?p3:p1):(p2>p1?p2:p1));
-inline const mpreal eint (const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_eint(x.mp,v.mp,rnd_mode);
- return x;
+ mpfr_fms(a.mp,v1.mp,v2.mp,v3.mp,rnd_mode);
+ return a;
}
-inline const mpreal gamma (const mpreal& x, mp_rnd_t rnd_mode)
+inline const mpreal agm (const mpreal& v1, const mpreal& v2, mp_rnd_t rnd_mode)
{
- mpreal FunctionValue(x);
+ mpreal a;
+ mp_prec_t p1, p2;
- // x < 0: gamma(-x) = -pi/(x * gamma(x) * sin(pi*x))
+ p1 = v1.get_prec();
+ p2 = v2.get_prec();
- mpfr_gamma(FunctionValue.mp, x.mp, rnd_mode);
+ a.set_prec(p1>p2?p1:p2);
- return FunctionValue;
-}
+ mpfr_agm(a.mp, v1.mp, v2.mp, rnd_mode);
-inline const mpreal lngamma (const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_lngamma(x.mp,v.mp,rnd_mode);
- return x;
+ return a;
}
-inline const mpreal lgamma (const mpreal& v, int *signp, mp_rnd_t rnd_mode)
+inline const mpreal sum (const mpreal tab[], unsigned long int n, mp_rnd_t rnd_mode)
{
- mpreal x(v);
- int tsignp;
-
- if(signp)
- mpfr_lgamma(x.mp,signp,v.mp,rnd_mode);
- else
- mpfr_lgamma(x.mp,&tsignp,v.mp,rnd_mode);
+ mpreal x;
+ mpfr_ptr* t;
+ unsigned long int i;
- return x;
+ t = new mpfr_ptr[n];
+ for (i=0;i<n;i++) t[i] = (mpfr_ptr)tab[i].mp;
+ mpfr_sum(x.mp,t,n,rnd_mode);
+ delete[] t;
+ return x;
}
-inline const mpreal zeta (const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_zeta(x.mp,v.mp,rnd_mode);
- return x;
-}
-
-inline const mpreal erf (const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_erf(x.mp,v.mp,rnd_mode);
- return x;
-}
-
-inline const mpreal erfc (const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_erfc(x.mp,v.mp,rnd_mode);
- return x;
-}
+//////////////////////////////////////////////////////////////////////////
+// MPFR 2.4.0 Specifics
+#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
-inline const mpreal besselj0 (const mpreal& v, mp_rnd_t rnd_mode)
+inline int sinh_cosh(mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode)
{
- mpreal x(v);
- mpfr_j0(x.mp,v.mp,rnd_mode);
- return x;
+ return mpfr_sinh_cosh(s.mp,c.mp,v.mp,rnd_mode);
}
-inline const mpreal besselj1 (const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_j1(x.mp,v.mp,rnd_mode);
- return x;
+inline const mpreal li2 (const mpreal& x, mp_rnd_t r)
+{
+ MPREAL_UNARY_MATH_FUNCTION_BODY(li2);
}
-inline const mpreal besseljn (long n, const mpreal& v, mp_rnd_t rnd_mode)
+inline const mpreal rem (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
{
- mpreal x(v);
- mpfr_jn(x.mp,n,v.mp,rnd_mode);
- return x;
+ /* R = rem(X,Y) if Y != 0, returns X - n * Y where n = trunc(X/Y). */
+ return fmod(x, y, rnd_mode);
}
-inline const mpreal bessely0 (const mpreal& v, mp_rnd_t rnd_mode)
+inline const mpreal mod (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
{
- mpreal x(v);
- mpfr_y0(x.mp,v.mp,rnd_mode);
- return x;
-}
+ (void)rnd_mode;
+
+ /*
-inline const mpreal bessely1 (const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_y1(x.mp,v.mp,rnd_mode);
- return x;
-}
+ m = mod(x,y) if y != 0, returns x - n*y where n = floor(x/y)
-inline const mpreal besselyn (long n, const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_yn(x.mp,n,v.mp,rnd_mode);
- return x;
-}
+ The following are true by convention:
+ - mod(x,0) is x
+ - mod(x,x) is 0
+ - mod(x,y) for x != y and y != 0 has the same sign as y.
+
+ */
-//////////////////////////////////////////////////////////////////////////
-// MPFR 2.4.0 Specifics
-#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
+ if(iszero(y)) return x;
+ if(x == y) return 0;
-inline int sinh_cosh(mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode)
-{
- return mpfr_sinh_cosh(s.mp,c.mp,v.mp,rnd_mode);
-}
+ mpreal m = x - floor(x / y) * y;
+
+ m.setSign(sgn(y)); // make sure result has the same sign as Y
-inline const mpreal li2(const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_li2(x.mp,v.mp,rnd_mode);
- return x;
+ return m;
}
inline const mpreal fmod (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
{
- mpreal a;
- mp_prec_t yp, xp;
+ mpreal a;
+ mp_prec_t yp, xp;
- yp = y.get_prec();
- xp = x.get_prec();
+ yp = y.get_prec();
+ xp = x.get_prec();
- a.set_prec(yp>xp?yp:xp);
+ a.set_prec(yp>xp?yp:xp);
- mpfr_fmod(a.mp, x.mp, y.mp, rnd_mode);
+ mpfr_fmod(a.mp, x.mp, y.mp, rnd_mode);
- return a;
+ return a;
}
inline const mpreal rec_sqrt(const mpreal& v, mp_rnd_t rnd_mode)
{
- mpreal x(v);
- mpfr_rec_sqrt(x.mp,v.mp,rnd_mode);
- return x;
+ mpreal x(v);
+ mpfr_rec_sqrt(x.mp,v.mp,rnd_mode);
+ return x;
}
#endif // MPFR 2.4.0 Specifics
//////////////////////////////////////////////////////////////////////////
// MPFR 3.0.0 Specifics
#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))
-
-inline const mpreal digamma(const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_digamma(x.mp,v.mp,rnd_mode);
- return x;
-}
-
-inline const mpreal ai(const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_ai(x.mp,v.mp,rnd_mode);
- return x;
-}
-
+inline const mpreal digamma (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(digamma); }
+inline const mpreal ai (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(ai); }
#endif // MPFR 3.0.0 Specifics
//////////////////////////////////////////////////////////////////////////
// Constants
-inline const mpreal const_log2 (mp_prec_t prec, mp_rnd_t rnd_mode)
+inline const mpreal const_log2 (mp_prec_t p, mp_rnd_t r)
{
- mpreal x;
- x.set_prec(prec);
- mpfr_const_log2(x.mp,rnd_mode);
- return x;
+ mpreal x(0, p);
+ mpfr_const_log2(x.mpfr_ptr(), r);
+ return x;
}
-inline const mpreal const_pi (mp_prec_t prec, mp_rnd_t rnd_mode)
+inline const mpreal const_pi (mp_prec_t p, mp_rnd_t r)
{
- mpreal x;
- x.set_prec(prec);
- mpfr_const_pi(x.mp,rnd_mode);
- return x;
+ mpreal x(0, p);
+ mpfr_const_pi(x.mpfr_ptr(), r);
+ return x;
}
-inline const mpreal const_euler (mp_prec_t prec, mp_rnd_t rnd_mode)
+inline const mpreal const_euler (mp_prec_t p, mp_rnd_t r)
{
- mpreal x;
- x.set_prec(prec);
- mpfr_const_euler(x.mp,rnd_mode);
- return x;
+ mpreal x(0, p);
+ mpfr_const_euler(x.mpfr_ptr(), r);
+ return x;
}
-inline const mpreal const_catalan (mp_prec_t prec, mp_rnd_t rnd_mode)
+inline const mpreal const_catalan (mp_prec_t p, mp_rnd_t r)
{
- mpreal x;
- x.set_prec(prec);
- mpfr_const_catalan(x.mp,rnd_mode);
- return x;
+ mpreal x(0, p);
+ mpfr_const_catalan(x.mpfr_ptr(), r);
+ return x;
}
-inline const mpreal const_infinity (int sign, mp_prec_t prec, mp_rnd_t rnd_mode)
+inline const mpreal const_infinity (int sign, mp_prec_t p, mp_rnd_t /*r*/)
{
- mpreal x;
- x.set_prec(prec,rnd_mode);
- mpfr_set_inf(x.mp, sign);
- return x;
+ mpreal x(0, p);
+ mpfr_set_inf(x.mpfr_ptr(), sign);
+ return x;
}
//////////////////////////////////////////////////////////////////////////
// Integer Related Functions
-inline const mpreal rint(const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_rint(x.mp,v.mp,rnd_mode);
- return x;
-}
-
inline const mpreal ceil(const mpreal& v)
{
- mpreal x(v);
- mpfr_ceil(x.mp,v.mp);
- return x;
-
+ mpreal x(v);
+ mpfr_ceil(x.mp,v.mp);
+ return x;
}
inline const mpreal floor(const mpreal& v)
{
- mpreal x(v);
- mpfr_floor(x.mp,v.mp);
- return x;
+ mpreal x(v);
+ mpfr_floor(x.mp,v.mp);
+ return x;
}
inline const mpreal round(const mpreal& v)
{
- mpreal x(v);
- mpfr_round(x.mp,v.mp);
- return x;
+ mpreal x(v);
+ mpfr_round(x.mp,v.mp);
+ return x;
}
inline const mpreal trunc(const mpreal& v)
{
- mpreal x(v);
- mpfr_trunc(x.mp,v.mp);
- return x;
+ mpreal x(v);
+ mpfr_trunc(x.mp,v.mp);
+ return x;
}
-inline const mpreal rint_ceil (const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_rint_ceil(x.mp,v.mp,rnd_mode);
- return x;
-}
-
-inline const mpreal rint_floor(const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_rint_floor(x.mp,v.mp,rnd_mode);
- return x;
-}
-
-inline const mpreal rint_round(const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_rint_round(x.mp,v.mp,rnd_mode);
- return x;
-}
-
-inline const mpreal rint_trunc(const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_rint_trunc(x.mp,v.mp,rnd_mode);
- return x;
-}
-
-inline const mpreal frac (const mpreal& v, mp_rnd_t rnd_mode)
-{
- mpreal x(v);
- mpfr_frac(x.mp,v.mp,rnd_mode);
- return x;
-}
+inline const mpreal rint (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(rint ); }
+inline const mpreal rint_ceil (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(rint_ceil ); }
+inline const mpreal rint_floor (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(rint_floor); }
+inline const mpreal rint_round (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(rint_round); }
+inline const mpreal rint_trunc (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(rint_trunc); }
+inline const mpreal frac (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(frac ); }
//////////////////////////////////////////////////////////////////////////
// Miscellaneous Functions
-inline void swap(mpreal& a, mpreal& b)
-{
- mpfr_swap(a.mp,b.mp);
-}
-
-inline const mpreal (max)(const mpreal& x, const mpreal& y)
-{
- return (x>y?x:y);
-}
-
-inline const mpreal (min)(const mpreal& x, const mpreal& y)
-{
- return (x<y?x:y);
-}
+inline void swap (mpreal& a, mpreal& b) { mpfr_swap(a.mp,b.mp); }
+inline const mpreal (max)(const mpreal& x, const mpreal& y){ return (x>y?x:y); }
+inline const mpreal (min)(const mpreal& x, const mpreal& y){ return (x<y?x:y); }
inline const mpreal fmax(const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
{
- mpreal a;
- mpfr_max(a.mp,x.mp,y.mp,rnd_mode);
- return a;
+ mpreal a;
+ mpfr_max(a.mp,x.mp,y.mp,rnd_mode);
+ return a;
}
inline const mpreal fmin(const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
{
- mpreal a;
- mpfr_min(a.mp,x.mp,y.mp,rnd_mode);
- return a;
+ mpreal a;
+ mpfr_min(a.mp,x.mp,y.mp,rnd_mode);
+ return a;
}
inline const mpreal nexttoward (const mpreal& x, const mpreal& y)
{
- mpreal a(x);
- mpfr_nexttoward(a.mp,y.mp);
- return a;
+ mpreal a(x);
+ mpfr_nexttoward(a.mp,y.mp);
+ return a;
}
inline const mpreal nextabove (const mpreal& x)
{
- mpreal a(x);
- mpfr_nextabove(a.mp);
- return a;
+ mpreal a(x);
+ mpfr_nextabove(a.mp);
+ return a;
}
inline const mpreal nextbelow (const mpreal& x)
{
- mpreal a(x);
- mpfr_nextbelow(a.mp);
- return a;
+ mpreal a(x);
+ mpfr_nextbelow(a.mp);
+ return a;
}
inline const mpreal urandomb (gmp_randstate_t& state)
{
- mpreal x;
- mpfr_urandomb(x.mp,state);
- return x;
+ mpreal x;
+ mpfr_urandomb(x.mp,state);
+ return x;
}
#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))
// use gmp_randinit_default() to init state, gmp_randclear() to clear
inline const mpreal urandom (gmp_randstate_t& state, mp_rnd_t rnd_mode)
{
- mpreal x;
- mpfr_urandom(x.mp,state,rnd_mode);
- return x;
+ mpreal x;
+ mpfr_urandom(x.mp,state,rnd_mode);
+ return x;
}
#endif
#if (MPFR_VERSION <= MPFR_VERSION_NUM(2,4,2))
inline const mpreal random2 (mp_size_t size, mp_exp_t exp)
{
- mpreal x;
- mpfr_random2(x.mp,size,exp);
- return x;
+ mpreal x;
+ mpfr_random2(x.mp,size,exp);
+ return x;
}
#endif
@@ -2353,22 +2484,22 @@ inline const mpreal random(unsigned int seed)
{
#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))
- static gmp_randstate_t state;
- static bool isFirstTime = true;
+ static gmp_randstate_t state;
+ static bool isFirstTime = true;
- if(isFirstTime)
- {
- gmp_randinit_default(state);
- gmp_randseed_ui(state,0);
- isFirstTime = false;
- }
+ if(isFirstTime)
+ {
+ gmp_randinit_default(state);
+ gmp_randseed_ui(state,0);
+ isFirstTime = false;
+ }
- if(seed != 0) gmp_randseed_ui(state,seed);
+ if(seed != 0) gmp_randseed_ui(state,seed);
- return mpfr::urandom(state);
+ return mpfr::urandom(state);
#else
- if(seed != 0) std::srand(seed);
- return mpfr::mpreal(std::rand()/(double)RAND_MAX);
+ if(seed != 0) std::srand(seed);
+ return mpfr::mpreal(std::rand()/(double)RAND_MAX);
#endif
}
@@ -2377,346 +2508,314 @@ inline const mpreal random(unsigned int seed)
// Set/Get global properties
inline void mpreal::set_default_prec(mp_prec_t prec)
{
- default_prec = prec;
- mpfr_set_default_prec(prec);
-}
-
-inline mp_prec_t mpreal::get_default_prec()
-{
- return (mpfr_get_default_prec)();
-}
-
-inline void mpreal::set_default_base(int base)
-{
- default_base = base;
-}
-
-inline int mpreal::get_default_base()
-{
- return default_base;
+ mpfr_set_default_prec(prec);
}
inline void mpreal::set_default_rnd(mp_rnd_t rnd_mode)
{
- default_rnd = rnd_mode;
- mpfr_set_default_rounding_mode(rnd_mode);
-}
-
-inline mp_rnd_t mpreal::get_default_rnd()
-{
- return static_cast<mp_rnd_t>((mpfr_get_default_rounding_mode)());
-}
-
-inline void mpreal::set_double_bits(int dbits)
-{
- double_bits = dbits;
-}
-
-inline int mpreal::get_double_bits()
-{
- return double_bits;
+ mpfr_set_default_rounding_mode(rnd_mode);
}
inline bool mpreal::fits_in_bits(double x, int n)
{
- int i;
- double t;
- return IsInf(x) || (std::modf ( std::ldexp ( std::frexp ( x, &i ), n ), &t ) == 0.0);
+ int i;
+ double t;
+ return IsInf(x) || (std::modf ( std::ldexp ( std::frexp ( x, &i ), n ), &t ) == 0.0);
}
inline const mpreal pow(const mpreal& a, const mpreal& b, mp_rnd_t rnd_mode)
{
- mpreal x(a);
- mpfr_pow(x.mp,x.mp,b.mp,rnd_mode);
- return x;
+ mpreal x(a);
+ mpfr_pow(x.mp,x.mp,b.mp,rnd_mode);
+ return x;
}
inline const mpreal pow(const mpreal& a, const mpz_t b, mp_rnd_t rnd_mode)
{
- mpreal x(a);
- mpfr_pow_z(x.mp,x.mp,b,rnd_mode);
- return x;
+ mpreal x(a);
+ mpfr_pow_z(x.mp,x.mp,b,rnd_mode);
+ return x;
}
inline const mpreal pow(const mpreal& a, const unsigned long int b, mp_rnd_t rnd_mode)
{
- mpreal x(a);
- mpfr_pow_ui(x.mp,x.mp,b,rnd_mode);
- return x;
+ mpreal x(a);
+ mpfr_pow_ui(x.mp,x.mp,b,rnd_mode);
+ return x;
}
inline const mpreal pow(const mpreal& a, const unsigned int b, mp_rnd_t rnd_mode)
{
- return pow(a,static_cast<unsigned long int>(b),rnd_mode);
+ return pow(a,static_cast<unsigned long int>(b),rnd_mode);
}
inline const mpreal pow(const mpreal& a, const long int b, mp_rnd_t rnd_mode)
{
- mpreal x(a);
- mpfr_pow_si(x.mp,x.mp,b,rnd_mode);
- return x;
+ mpreal x(a);
+ mpfr_pow_si(x.mp,x.mp,b,rnd_mode);
+ return x;
}
inline const mpreal pow(const mpreal& a, const int b, mp_rnd_t rnd_mode)
{
- return pow(a,static_cast<long int>(b),rnd_mode);
+ return pow(a,static_cast<long int>(b),rnd_mode);
}
inline const mpreal pow(const mpreal& a, const long double b, mp_rnd_t rnd_mode)
{
- return pow(a,mpreal(b),rnd_mode);
+ return pow(a,mpreal(b),rnd_mode);
}
inline const mpreal pow(const mpreal& a, const double b, mp_rnd_t rnd_mode)
{
- return pow(a,mpreal(b),rnd_mode);
+ return pow(a,mpreal(b),rnd_mode);
}
inline const mpreal pow(const unsigned long int a, const mpreal& b, mp_rnd_t rnd_mode)
{
- mpreal x(a);
- mpfr_ui_pow(x.mp,a,b.mp,rnd_mode);
- return x;
+ mpreal x(a);
+ mpfr_ui_pow(x.mp,a,b.mp,rnd_mode);
+ return x;
}
inline const mpreal pow(const unsigned int a, const mpreal& b, mp_rnd_t rnd_mode)
{
- return pow(static_cast<unsigned long int>(a),b,rnd_mode);
+ return pow(static_cast<unsigned long int>(a),b,rnd_mode);
}
inline const mpreal pow(const long int a, const mpreal& b, mp_rnd_t rnd_mode)
{
- if (a>=0) return pow(static_cast<unsigned long int>(a),b,rnd_mode);
- else return pow(mpreal(a),b,rnd_mode);
+ if (a>=0) return pow(static_cast<unsigned long int>(a),b,rnd_mode);
+ else return pow(mpreal(a),b,rnd_mode);
}
inline const mpreal pow(const int a, const mpreal& b, mp_rnd_t rnd_mode)
{
- if (a>=0) return pow(static_cast<unsigned long int>(a),b,rnd_mode);
- else return pow(mpreal(a),b,rnd_mode);
+ if (a>=0) return pow(static_cast<unsigned long int>(a),b,rnd_mode);
+ else return pow(mpreal(a),b,rnd_mode);
}
inline const mpreal pow(const long double a, const mpreal& b, mp_rnd_t rnd_mode)
{
- return pow(mpreal(a),b,rnd_mode);
+ return pow(mpreal(a),b,rnd_mode);
}
inline const mpreal pow(const double a, const mpreal& b, mp_rnd_t rnd_mode)
{
- return pow(mpreal(a),b,rnd_mode);
+ return pow(mpreal(a),b,rnd_mode);
}
// pow unsigned long int
inline const mpreal pow(const unsigned long int a, const unsigned long int b, mp_rnd_t rnd_mode)
{
- mpreal x(a);
- mpfr_ui_pow_ui(x.mp,a,b,rnd_mode);
- return x;
+ mpreal x(a);
+ mpfr_ui_pow_ui(x.mp,a,b,rnd_mode);
+ return x;
}
inline const mpreal pow(const unsigned long int a, const unsigned int b, mp_rnd_t rnd_mode)
{
- return pow(a,static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
+ return pow(a,static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
}
inline const mpreal pow(const unsigned long int a, const long int b, mp_rnd_t rnd_mode)
{
- if(b>0) return pow(a,static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
- else return pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow
+ if(b>0) return pow(a,static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
+ else return pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow
}
inline const mpreal pow(const unsigned long int a, const int b, mp_rnd_t rnd_mode)
{
- if(b>0) return pow(a,static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
- else return pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow
+ if(b>0) return pow(a,static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
+ else return pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow
}
inline const mpreal pow(const unsigned long int a, const long double b, mp_rnd_t rnd_mode)
{
- return pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow
+ return pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow
}
inline const mpreal pow(const unsigned long int a, const double b, mp_rnd_t rnd_mode)
{
- return pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow
+ return pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow
}
// pow unsigned int
inline const mpreal pow(const unsigned int a, const unsigned long int b, mp_rnd_t rnd_mode)
{
- return pow(static_cast<unsigned long int>(a),b,rnd_mode); //mpfr_ui_pow_ui
+ return pow(static_cast<unsigned long int>(a),b,rnd_mode); //mpfr_ui_pow_ui
}
inline const mpreal pow(const unsigned int a, const unsigned int b, mp_rnd_t rnd_mode)
{
- return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
+ return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
}
inline const mpreal pow(const unsigned int a, const long int b, mp_rnd_t rnd_mode)
{
- if(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
- else return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
+ if(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
+ else return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
}
inline const mpreal pow(const unsigned int a, const int b, mp_rnd_t rnd_mode)
{
- if(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
- else return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
+ if(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
+ else return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
}
inline const mpreal pow(const unsigned int a, const long double b, mp_rnd_t rnd_mode)
{
- return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
+ return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
}
inline const mpreal pow(const unsigned int a, const double b, mp_rnd_t rnd_mode)
{
- return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
+ return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
}
// pow long int
inline const mpreal pow(const long int a, const unsigned long int b, mp_rnd_t rnd_mode)
{
- if (a>0) return pow(static_cast<unsigned long int>(a),b,rnd_mode); //mpfr_ui_pow_ui
- else return pow(mpreal(a),b,rnd_mode); //mpfr_pow_ui
+ if (a>0) return pow(static_cast<unsigned long int>(a),b,rnd_mode); //mpfr_ui_pow_ui
+ else return pow(mpreal(a),b,rnd_mode); //mpfr_pow_ui
}
inline const mpreal pow(const long int a, const unsigned int b, mp_rnd_t rnd_mode)
{
- if (a>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
- else return pow(mpreal(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_pow_ui
+ if (a>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
+ else return pow(mpreal(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_pow_ui
}
inline const mpreal pow(const long int a, const long int b, mp_rnd_t rnd_mode)
{
- if (a>0)
- {
- if(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
- else return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
- }else{
- return pow(mpreal(a),b,rnd_mode); // mpfr_pow_si
- }
+ if (a>0)
+ {
+ if(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
+ else return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
+ }else{
+ return pow(mpreal(a),b,rnd_mode); // mpfr_pow_si
+ }
}
inline const mpreal pow(const long int a, const int b, mp_rnd_t rnd_mode)
{
- if (a>0)
- {
- if(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
- else return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
- }else{
- return pow(mpreal(a),static_cast<long int>(b),rnd_mode); // mpfr_pow_si
- }
+ if (a>0)
+ {
+ if(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
+ else return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
+ }else{
+ return pow(mpreal(a),static_cast<long int>(b),rnd_mode); // mpfr_pow_si
+ }
}
inline const mpreal pow(const long int a, const long double b, mp_rnd_t rnd_mode)
{
- if (a>=0) return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
- else return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow
+ if (a>=0) return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
+ else return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow
}
inline const mpreal pow(const long int a, const double b, mp_rnd_t rnd_mode)
{
- if (a>=0) return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
- else return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow
+ if (a>=0) return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
+ else return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow
}
// pow int
inline const mpreal pow(const int a, const unsigned long int b, mp_rnd_t rnd_mode)
{
- if (a>0) return pow(static_cast<unsigned long int>(a),b,rnd_mode); //mpfr_ui_pow_ui
- else return pow(mpreal(a),b,rnd_mode); //mpfr_pow_ui
+ if (a>0) return pow(static_cast<unsigned long int>(a),b,rnd_mode); //mpfr_ui_pow_ui
+ else return pow(mpreal(a),b,rnd_mode); //mpfr_pow_ui
}
inline const mpreal pow(const int a, const unsigned int b, mp_rnd_t rnd_mode)
{
- if (a>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
- else return pow(mpreal(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_pow_ui
+ if (a>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
+ else return pow(mpreal(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_pow_ui
}
inline const mpreal pow(const int a, const long int b, mp_rnd_t rnd_mode)
{
- if (a>0)
- {
- if(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
- else return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
- }else{
- return pow(mpreal(a),b,rnd_mode); // mpfr_pow_si
- }
+ if (a>0)
+ {
+ if(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
+ else return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
+ }else{
+ return pow(mpreal(a),b,rnd_mode); // mpfr_pow_si
+ }
}
inline const mpreal pow(const int a, const int b, mp_rnd_t rnd_mode)
{
- if (a>0)
- {
- if(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
- else return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
- }else{
- return pow(mpreal(a),static_cast<long int>(b),rnd_mode); // mpfr_pow_si
- }
+ if (a>0)
+ {
+ if(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
+ else return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
+ }else{
+ return pow(mpreal(a),static_cast<long int>(b),rnd_mode); // mpfr_pow_si
+ }
}
inline const mpreal pow(const int a, const long double b, mp_rnd_t rnd_mode)
{
- if (a>=0) return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
- else return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow
+ if (a>=0) return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
+ else return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow
}
inline const mpreal pow(const int a, const double b, mp_rnd_t rnd_mode)
{
- if (a>=0) return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
- else return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow
+ if (a>=0) return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
+ else return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow
}
// pow long double
inline const mpreal pow(const long double a, const long double b, mp_rnd_t rnd_mode)
{
- return pow(mpreal(a),mpreal(b),rnd_mode);
+ return pow(mpreal(a),mpreal(b),rnd_mode);
}
inline const mpreal pow(const long double a, const unsigned long int b, mp_rnd_t rnd_mode)
{
- return pow(mpreal(a),b,rnd_mode); //mpfr_pow_ui
+ return pow(mpreal(a),b,rnd_mode); //mpfr_pow_ui
}
inline const mpreal pow(const long double a, const unsigned int b, mp_rnd_t rnd_mode)
{
- return pow(mpreal(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_pow_ui
+ return pow(mpreal(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_pow_ui
}
inline const mpreal pow(const long double a, const long int b, mp_rnd_t rnd_mode)
{
- return pow(mpreal(a),b,rnd_mode); // mpfr_pow_si
+ return pow(mpreal(a),b,rnd_mode); // mpfr_pow_si
}
inline const mpreal pow(const long double a, const int b, mp_rnd_t rnd_mode)
{
- return pow(mpreal(a),static_cast<long int>(b),rnd_mode); // mpfr_pow_si
+ return pow(mpreal(a),static_cast<long int>(b),rnd_mode); // mpfr_pow_si
}
inline const mpreal pow(const double a, const double b, mp_rnd_t rnd_mode)
{
- return pow(mpreal(a),mpreal(b),rnd_mode);
+ return pow(mpreal(a),mpreal(b),rnd_mode);
}
inline const mpreal pow(const double a, const unsigned long int b, mp_rnd_t rnd_mode)
{
- return pow(mpreal(a),b,rnd_mode); // mpfr_pow_ui
+ return pow(mpreal(a),b,rnd_mode); // mpfr_pow_ui
}
inline const mpreal pow(const double a, const unsigned int b, mp_rnd_t rnd_mode)
{
- return pow(mpreal(a),static_cast<unsigned long int>(b),rnd_mode); // mpfr_pow_ui
+ return pow(mpreal(a),static_cast<unsigned long int>(b),rnd_mode); // mpfr_pow_ui
}
inline const mpreal pow(const double a, const long int b, mp_rnd_t rnd_mode)
{
- return pow(mpreal(a),b,rnd_mode); // mpfr_pow_si
+ return pow(mpreal(a),b,rnd_mode); // mpfr_pow_si
}
inline const mpreal pow(const double a, const int b, mp_rnd_t rnd_mode)
{
- return pow(mpreal(a),static_cast<long int>(b),rnd_mode); // mpfr_pow_si
+ return pow(mpreal(a),static_cast<long int>(b),rnd_mode); // mpfr_pow_si
}
} // End of mpfr namespace
@@ -2725,11 +2824,99 @@ inline const mpreal pow(const double a, const int b, mp_rnd_t rnd_mode)
// Non-throwing swap C++ idiom: http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Non-throwing_swap
namespace std
{
- template <>
- inline void swap(mpfr::mpreal& x, mpfr::mpreal& y)
- {
- return mpfr::swap(x, y);
- }
+ // only allowed to extend namespace std with specializations
+ template <>
+ inline void swap(mpfr::mpreal& x, mpfr::mpreal& y)
+ {
+ return mpfr::swap(x, y);
+ }
+
+ template<>
+ class numeric_limits<mpfr::mpreal>
+ {
+ public:
+ static const bool is_specialized = true;
+ static const bool is_signed = true;
+ static const bool is_integer = false;
+ static const bool is_exact = false;
+ static const int radix = 2;
+
+ static const bool has_infinity = true;
+ static const bool has_quiet_NaN = true;
+ static const bool has_signaling_NaN = true;
+
+ static const bool is_iec559 = true; // = IEEE 754
+ static const bool is_bounded = true;
+ static const bool is_modulo = false;
+ static const bool traps = true;
+ static const bool tinyness_before = true;
+
+ static const float_denorm_style has_denorm = denorm_absent;
+
+ inline static float_round_style round_style()
+ {
+ mp_rnd_t r = mpfr::mpreal::get_default_rnd();
+
+ switch (r)
+ {
+ case MPFR_RNDN: return round_to_nearest;
+ case MPFR_RNDZ: return round_toward_zero;
+ case MPFR_RNDU: return round_toward_infinity;
+ case MPFR_RNDD: return round_toward_neg_infinity;
+ default: return round_indeterminate;
+ }
+ }
+
+ inline static mpfr::mpreal (min) (mp_prec_t precision = mpfr::mpreal::get_default_prec()) { return mpfr::minval(precision); }
+ inline static mpfr::mpreal (max) (mp_prec_t precision = mpfr::mpreal::get_default_prec()) { return mpfr::maxval(precision); }
+ inline static mpfr::mpreal lowest (mp_prec_t precision = mpfr::mpreal::get_default_prec()) { return -mpfr::maxval(precision); }
+
+ // Returns smallest eps such that 1 + eps != 1 (classic machine epsilon)
+ inline static mpfr::mpreal epsilon(mp_prec_t precision = mpfr::mpreal::get_default_prec()) { return mpfr::machine_epsilon(precision); }
+
+ // Returns smallest eps such that x + eps != x (relative machine epsilon)
+ inline static mpfr::mpreal epsilon(const mpfr::mpreal& x) { return mpfr::machine_epsilon(x); }
+
+ inline static mpfr::mpreal round_error(mp_prec_t precision = mpfr::mpreal::get_default_prec())
+ {
+ mp_rnd_t r = mpfr::mpreal::get_default_rnd();
+
+ if(r == MPFR_RNDN) return mpfr::mpreal(0.5, precision);
+ else return mpfr::mpreal(1.0, precision);
+ }
+
+ inline static const mpfr::mpreal infinity() { return mpfr::const_infinity(); }
+ inline static const mpfr::mpreal quiet_NaN() { return mpfr::mpreal().setNan(); }
+ inline static const mpfr::mpreal signaling_NaN() { return mpfr::mpreal().setNan(); }
+ inline static const mpfr::mpreal denorm_min() { return (min)(); }
+
+ // Please note, exponent range is not fixed in MPFR
+ static const int min_exponent = MPFR_EMIN_DEFAULT;
+ static const int max_exponent = MPFR_EMAX_DEFAULT;
+ MPREAL_PERMISSIVE_EXPR static const int min_exponent10 = (int) (MPFR_EMIN_DEFAULT * 0.3010299956639811);
+ MPREAL_PERMISSIVE_EXPR static const int max_exponent10 = (int) (MPFR_EMAX_DEFAULT * 0.3010299956639811);
+
+ // Should be constant according to standard, but 'digits' depends on precision in MPFR
+
+ inline static int digits() { return mpfr::mpreal::get_default_prec(); }
+ inline static int digits(const mpfr::mpreal& x) { return x.getPrecision(); }
+
+ inline static int digits10(mp_prec_t precision = mpfr::mpreal::get_default_prec())
+ {
+ return mpfr::bits2digits(precision);
+ }
+
+ inline static int digits10(const mpfr::mpreal& x)
+ {
+ return mpfr::bits2digits(x.getPrecision());
+ }
+
+ inline static int max_digits10(mp_prec_t precision = mpfr::mpreal::get_default_prec())
+ {
+ return digits10(precision);
+ }
+ };
+
}
#endif /* __MPREAL_H__ */
diff --git a/unsupported/test/mpreal_support.cpp b/unsupported/test/mpreal_support.cpp
index 551af9db8..bc00382be 100644
--- a/unsupported/test/mpreal_support.cpp
+++ b/unsupported/test/mpreal_support.cpp
@@ -5,7 +5,6 @@
#include <sstream>
using namespace mpfr;
-using namespace std;
using namespace Eigen;
void test_mpreal_support()
@@ -46,8 +45,7 @@ void test_mpreal_support()
// symmetric eigenvalues
SelfAdjointEigenSolver<MatrixXmp> eig(S);
VERIFY_IS_EQUAL(eig.info(), Success);
- VERIFY_IS_APPROX((S.selfadjointView<Lower>() * eig.eigenvectors()),
- eig.eigenvectors() * eig.eigenvalues().asDiagonal());
+ VERIFY( (S.selfadjointView<Lower>() * eig.eigenvectors()).isApprox(eig.eigenvectors() * eig.eigenvalues().asDiagonal(), NumTraits<mpreal>::dummy_precision()*1e3) );
}
{
@@ -57,8 +55,3 @@ void test_mpreal_support()
stream << A;
}
}
-
-extern "C" {
-#include "mpreal/dlmalloc.c"
-}
-#include "mpreal/mpreal.cpp"
diff --git a/unsupported/test/polynomialsolver.cpp b/unsupported/test/polynomialsolver.cpp
index fefeaff01..13f92169e 100644
--- a/unsupported/test/polynomialsolver.cpp
+++ b/unsupported/test/polynomialsolver.cpp
@@ -92,6 +92,7 @@ void evalSolver( const POLYNOMIAL& pols )
template< int Deg, typename POLYNOMIAL, typename ROOTS, typename REAL_ROOTS >
void evalSolverSugarFunction( const POLYNOMIAL& pols, const ROOTS& roots, const REAL_ROOTS& real_roots )
{
+ using std::sqrt;
typedef typename POLYNOMIAL::Scalar Scalar;
typedef PolynomialSolver<Scalar, Deg > PolynomialSolverType;
@@ -105,17 +106,14 @@ void evalSolverSugarFunction( const POLYNOMIAL& pols, const ROOTS& roots, const
typedef typename POLYNOMIAL::Scalar Scalar;
typedef typename REAL_ROOTS::Scalar Real;
-
typedef PolynomialSolver<Scalar, Deg > PolynomialSolverType;
- typedef typename PolynomialSolverType::RootsType RootsType;
- typedef Matrix<Scalar,Deg,1> EvalRootsType;
//Test realRoots
std::vector< Real > calc_realRoots;
psolve.realRoots( calc_realRoots );
VERIFY( calc_realRoots.size() == (size_t)real_roots.size() );
- const Scalar psPrec = internal::sqrt( test_precision<Scalar>() );
+ const Scalar psPrec = sqrt( test_precision<Scalar>() );
for( size_t i=0; i<calc_realRoots.size(); ++i )
{
@@ -130,24 +128,24 @@ void evalSolverSugarFunction( const POLYNOMIAL& pols, const ROOTS& roots, const
//Test greatestRoot
VERIFY( internal::isApprox( roots.array().abs().maxCoeff(),
- internal::abs( psolve.greatestRoot() ), psPrec ) );
+ abs( psolve.greatestRoot() ), psPrec ) );
//Test smallestRoot
VERIFY( internal::isApprox( roots.array().abs().minCoeff(),
- internal::abs( psolve.smallestRoot() ), psPrec ) );
+ abs( psolve.smallestRoot() ), psPrec ) );
bool hasRealRoot;
//Test absGreatestRealRoot
Real r = psolve.absGreatestRealRoot( hasRealRoot );
VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
if( hasRealRoot ){
- VERIFY( internal::isApprox( real_roots.array().abs().maxCoeff(), internal::abs(r), psPrec ) ); }
+ VERIFY( internal::isApprox( real_roots.array().abs().maxCoeff(), abs(r), psPrec ) ); }
//Test absSmallestRealRoot
r = psolve.absSmallestRealRoot( hasRealRoot );
VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
if( hasRealRoot ){
- VERIFY( internal::isApprox( real_roots.array().abs().minCoeff(), internal::abs( r ), psPrec ) ); }
+ VERIFY( internal::isApprox( real_roots.array().abs().minCoeff(), abs( r ), psPrec ) ); }
//Test greatestRealRoot
r = psolve.greatestRealRoot( hasRealRoot );
diff --git a/unsupported/test/sparse_extra.cpp b/unsupported/test/sparse_extra.cpp
index 5dc333424..1ee791b0f 100644
--- a/unsupported/test/sparse_extra.cpp
+++ b/unsupported/test/sparse_extra.cpp
@@ -17,7 +17,6 @@
template<typename SetterType,typename DenseType, typename Scalar, int Options>
bool test_random_setter(SparseMatrix<Scalar,Options>& sm, const DenseType& ref, const std::vector<Vector2i>& nonzeroCoords)
{
- typedef SparseMatrix<Scalar,Options> SparseType;
{
sm.setZero();
SetterType w(sm);
diff --git a/unsupported/test/splines.cpp b/unsupported/test/splines.cpp
index 1043453dc..a7eb3e0c4 100644
--- a/unsupported/test/splines.cpp
+++ b/unsupported/test/splines.cpp
@@ -11,6 +11,8 @@
#include <unsupported/Eigen/Splines>
+namespace Eigen {
+
// lets do some explicit instantiations and thus
// force the compilation of all spline functions...
template class Spline<double, 2, Dynamic>;
@@ -29,6 +31,8 @@ template class Spline<float, 3, 3>;
template class Spline<float, 3, 4>;
template class Spline<float, 3, 5>;
+}
+
Spline<double, 2, Dynamic> closed_spline2d()
{
RowVectorXd knots(12);
diff --git a/unsupported/test/svd_common.h b/unsupported/test/svd_common.h
new file mode 100644
index 000000000..b40c23a2b
--- /dev/null
+++ b/unsupported/test/svd_common.h
@@ -0,0 +1,261 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Copyright (C) 2013 Gauthier Brun <brun.gauthier@gmail.com>
+// Copyright (C) 2013 Nicolas Carre <nicolas.carre@ensimag.fr>
+// Copyright (C) 2013 Jean Ceccato <jean.ceccato@ensimag.fr>
+// Copyright (C) 2013 Pierre Zoppitelli <pierre.zoppitelli@ensimag.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+// discard stack allocation as that too bypasses malloc
+#define EIGEN_STACK_ALLOCATION_LIMIT 0
+#define EIGEN_RUNTIME_NO_MALLOC
+
+#include "main.h"
+#include <unsupported/Eigen/SVD>
+#include <Eigen/LU>
+
+
+// check if "svd" is the good image of "m"
+template<typename MatrixType, typename SVD>
+void svd_check_full(const MatrixType& m, const SVD& svd)
+{
+ typedef typename MatrixType::Index Index;
+ Index rows = m.rows();
+ Index cols = m.cols();
+ enum {
+ RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+ ColsAtCompileTime = MatrixType::ColsAtCompileTime
+ };
+
+ typedef typename MatrixType::Scalar Scalar;
+ typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime> MatrixUType;
+ typedef Matrix<Scalar, ColsAtCompileTime, ColsAtCompileTime> MatrixVType;
+
+
+ MatrixType sigma = MatrixType::Zero(rows, cols);
+ sigma.diagonal() = svd.singularValues().template cast<Scalar>();
+ MatrixUType u = svd.matrixU();
+ MatrixVType v = svd.matrixV();
+ VERIFY_IS_APPROX(m, u * sigma * v.adjoint());
+ VERIFY_IS_UNITARY(u);
+ VERIFY_IS_UNITARY(v);
+} // end svd_check_full
+
+
+
+// Compare to a reference value
+template<typename MatrixType, typename SVD>
+void svd_compare_to_full(const MatrixType& m,
+ unsigned int computationOptions,
+ const SVD& referenceSvd)
+{
+ typedef typename MatrixType::Index Index;
+ Index rows = m.rows();
+ Index cols = m.cols();
+ Index diagSize = (std::min)(rows, cols);
+
+ SVD svd(m, computationOptions);
+
+ VERIFY_IS_APPROX(svd.singularValues(), referenceSvd.singularValues());
+ if(computationOptions & ComputeFullU)
+ VERIFY_IS_APPROX(svd.matrixU(), referenceSvd.matrixU());
+ if(computationOptions & ComputeThinU)
+ VERIFY_IS_APPROX(svd.matrixU(), referenceSvd.matrixU().leftCols(diagSize));
+ if(computationOptions & ComputeFullV)
+ VERIFY_IS_APPROX(svd.matrixV(), referenceSvd.matrixV());
+ if(computationOptions & ComputeThinV)
+ VERIFY_IS_APPROX(svd.matrixV(), referenceSvd.matrixV().leftCols(diagSize));
+} // end svd_compare_to_full
+
+
+
+template<typename MatrixType, typename SVD>
+void svd_solve(const MatrixType& m, unsigned int computationOptions)
+{
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::Index Index;
+ Index rows = m.rows();
+ Index cols = m.cols();
+
+ enum {
+ RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+ ColsAtCompileTime = MatrixType::ColsAtCompileTime
+ };
+
+ typedef Matrix<Scalar, RowsAtCompileTime, Dynamic> RhsType;
+ typedef Matrix<Scalar, ColsAtCompileTime, Dynamic> SolutionType;
+
+ RhsType rhs = RhsType::Random(rows, internal::random<Index>(1, cols));
+ SVD svd(m, computationOptions);
+ SolutionType x = svd.solve(rhs);
+ // evaluate normal equation which works also for least-squares solutions
+ VERIFY_IS_APPROX(m.adjoint()*m*x,m.adjoint()*rhs);
+} // end svd_solve
+
+
+// test computations options
+// 2 functions because Jacobisvd can return before the second function
+template<typename MatrixType, typename SVD>
+void svd_test_computation_options_1(const MatrixType& m, const SVD& fullSvd)
+{
+ svd_check_full< MatrixType, SVD >(m, fullSvd);
+ svd_solve< MatrixType, SVD >(m, ComputeFullU | ComputeFullV);
+}
+
+
+template<typename MatrixType, typename SVD>
+void svd_test_computation_options_2(const MatrixType& m, const SVD& fullSvd)
+{
+ svd_compare_to_full< MatrixType, SVD >(m, ComputeFullU, fullSvd);
+ svd_compare_to_full< MatrixType, SVD >(m, ComputeFullV, fullSvd);
+ svd_compare_to_full< MatrixType, SVD >(m, 0, fullSvd);
+
+ if (MatrixType::ColsAtCompileTime == Dynamic) {
+ // thin U/V are only available with dynamic number of columns
+
+ svd_compare_to_full< MatrixType, SVD >(m, ComputeFullU|ComputeThinV, fullSvd);
+ svd_compare_to_full< MatrixType, SVD >(m, ComputeThinV, fullSvd);
+ svd_compare_to_full< MatrixType, SVD >(m, ComputeThinU|ComputeFullV, fullSvd);
+ svd_compare_to_full< MatrixType, SVD >(m, ComputeThinU , fullSvd);
+ svd_compare_to_full< MatrixType, SVD >(m, ComputeThinU|ComputeThinV, fullSvd);
+ svd_solve<MatrixType, SVD>(m, ComputeFullU | ComputeThinV);
+ svd_solve<MatrixType, SVD>(m, ComputeThinU | ComputeFullV);
+ svd_solve<MatrixType, SVD>(m, ComputeThinU | ComputeThinV);
+
+ typedef typename MatrixType::Index Index;
+ Index diagSize = (std::min)(m.rows(), m.cols());
+ SVD svd(m, ComputeThinU | ComputeThinV);
+ VERIFY_IS_APPROX(m, svd.matrixU().leftCols(diagSize) * svd.singularValues().asDiagonal() * svd.matrixV().leftCols(diagSize).adjoint());
+ }
+}
+
+template<typename MatrixType, typename SVD>
+void svd_verify_assert(const MatrixType& m)
+{
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::Index Index;
+ Index rows = m.rows();
+ Index cols = m.cols();
+
+ enum {
+ RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+ ColsAtCompileTime = MatrixType::ColsAtCompileTime
+ };
+
+ typedef Matrix<Scalar, RowsAtCompileTime, 1> RhsType;
+ RhsType rhs(rows);
+ SVD svd;
+ VERIFY_RAISES_ASSERT(svd.matrixU())
+ VERIFY_RAISES_ASSERT(svd.singularValues())
+ VERIFY_RAISES_ASSERT(svd.matrixV())
+ VERIFY_RAISES_ASSERT(svd.solve(rhs))
+ MatrixType a = MatrixType::Zero(rows, cols);
+ a.setZero();
+ svd.compute(a, 0);
+ VERIFY_RAISES_ASSERT(svd.matrixU())
+ VERIFY_RAISES_ASSERT(svd.matrixV())
+ svd.singularValues();
+ VERIFY_RAISES_ASSERT(svd.solve(rhs))
+
+ if (ColsAtCompileTime == Dynamic)
+ {
+ svd.compute(a, ComputeThinU);
+ svd.matrixU();
+ VERIFY_RAISES_ASSERT(svd.matrixV())
+ VERIFY_RAISES_ASSERT(svd.solve(rhs))
+ svd.compute(a, ComputeThinV);
+ svd.matrixV();
+ VERIFY_RAISES_ASSERT(svd.matrixU())
+ VERIFY_RAISES_ASSERT(svd.solve(rhs))
+ }
+ else
+ {
+ VERIFY_RAISES_ASSERT(svd.compute(a, ComputeThinU))
+ VERIFY_RAISES_ASSERT(svd.compute(a, ComputeThinV))
+ }
+}
+
+// work around stupid msvc error when constructing at compile time an expression that involves
+// a division by zero, even if the numeric type has floating point
+template<typename Scalar>
+EIGEN_DONT_INLINE Scalar zero() { return Scalar(0); }
+
+// workaround aggressive optimization in ICC
+template<typename T> EIGEN_DONT_INLINE T sub(T a, T b) { return a - b; }
+
+
+template<typename MatrixType, typename SVD>
+void svd_inf_nan()
+{
+ // all this function does is verify we don't iterate infinitely on nan/inf values
+
+ SVD svd;
+ typedef typename MatrixType::Scalar Scalar;
+ Scalar some_inf = Scalar(1) / zero<Scalar>();
+ VERIFY(sub(some_inf, some_inf) != sub(some_inf, some_inf));
+ svd.compute(MatrixType::Constant(10,10,some_inf), ComputeFullU | ComputeFullV);
+
+ Scalar some_nan = zero<Scalar> () / zero<Scalar> ();
+ VERIFY(some_nan != some_nan);
+ svd.compute(MatrixType::Constant(10,10,some_nan), ComputeFullU | ComputeFullV);
+
+ MatrixType m = MatrixType::Zero(10,10);
+ m(internal::random<int>(0,9), internal::random<int>(0,9)) = some_inf;
+ svd.compute(m, ComputeFullU | ComputeFullV);
+
+ m = MatrixType::Zero(10,10);
+ m(internal::random<int>(0,9), internal::random<int>(0,9)) = some_nan;
+ svd.compute(m, ComputeFullU | ComputeFullV);
+}
+
+
+template<typename SVD>
+void svd_preallocate()
+{
+ Vector3f v(3.f, 2.f, 1.f);
+ MatrixXf m = v.asDiagonal();
+
+ internal::set_is_malloc_allowed(false);
+ VERIFY_RAISES_ASSERT(VectorXf v(10);)
+ SVD svd;
+ internal::set_is_malloc_allowed(true);
+ svd.compute(m);
+ VERIFY_IS_APPROX(svd.singularValues(), v);
+
+ SVD svd2(3,3);
+ internal::set_is_malloc_allowed(false);
+ svd2.compute(m);
+ internal::set_is_malloc_allowed(true);
+ VERIFY_IS_APPROX(svd2.singularValues(), v);
+ VERIFY_RAISES_ASSERT(svd2.matrixU());
+ VERIFY_RAISES_ASSERT(svd2.matrixV());
+ svd2.compute(m, ComputeFullU | ComputeFullV);
+ VERIFY_IS_APPROX(svd2.matrixU(), Matrix3f::Identity());
+ VERIFY_IS_APPROX(svd2.matrixV(), Matrix3f::Identity());
+ internal::set_is_malloc_allowed(false);
+ svd2.compute(m);
+ internal::set_is_malloc_allowed(true);
+
+ SVD svd3(3,3,ComputeFullU|ComputeFullV);
+ internal::set_is_malloc_allowed(false);
+ svd2.compute(m);
+ internal::set_is_malloc_allowed(true);
+ VERIFY_IS_APPROX(svd2.singularValues(), v);
+ VERIFY_IS_APPROX(svd2.matrixU(), Matrix3f::Identity());
+ VERIFY_IS_APPROX(svd2.matrixV(), Matrix3f::Identity());
+ internal::set_is_malloc_allowed(false);
+ svd2.compute(m, ComputeFullU|ComputeFullV);
+ internal::set_is_malloc_allowed(true);
+}
+
+
+
+
+