@smake/eigen 1.0.2 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (435) hide show
  1. package/README.md +1 -1
  2. package/eigen/Eigen/AccelerateSupport +52 -0
  3. package/eigen/Eigen/Cholesky +18 -21
  4. package/eigen/Eigen/CholmodSupport +28 -28
  5. package/eigen/Eigen/Core +235 -326
  6. package/eigen/Eigen/Eigenvalues +16 -14
  7. package/eigen/Eigen/Geometry +21 -24
  8. package/eigen/Eigen/Householder +9 -8
  9. package/eigen/Eigen/IterativeLinearSolvers +8 -4
  10. package/eigen/Eigen/Jacobi +14 -14
  11. package/eigen/Eigen/KLUSupport +43 -0
  12. package/eigen/Eigen/LU +16 -20
  13. package/eigen/Eigen/MetisSupport +12 -12
  14. package/eigen/Eigen/OrderingMethods +54 -54
  15. package/eigen/Eigen/PaStiXSupport +23 -20
  16. package/eigen/Eigen/PardisoSupport +17 -14
  17. package/eigen/Eigen/QR +18 -21
  18. package/eigen/Eigen/QtAlignedMalloc +5 -13
  19. package/eigen/Eigen/SPQRSupport +21 -14
  20. package/eigen/Eigen/SVD +23 -18
  21. package/eigen/Eigen/Sparse +1 -4
  22. package/eigen/Eigen/SparseCholesky +18 -23
  23. package/eigen/Eigen/SparseCore +18 -17
  24. package/eigen/Eigen/SparseLU +12 -8
  25. package/eigen/Eigen/SparseQR +16 -14
  26. package/eigen/Eigen/StdDeque +5 -2
  27. package/eigen/Eigen/StdList +5 -2
  28. package/eigen/Eigen/StdVector +5 -2
  29. package/eigen/Eigen/SuperLUSupport +30 -24
  30. package/eigen/Eigen/ThreadPool +80 -0
  31. package/eigen/Eigen/UmfPackSupport +19 -17
  32. package/eigen/Eigen/Version +14 -0
  33. package/eigen/Eigen/src/AccelerateSupport/AccelerateSupport.h +423 -0
  34. package/eigen/Eigen/src/AccelerateSupport/InternalHeaderCheck.h +3 -0
  35. package/eigen/Eigen/src/Cholesky/InternalHeaderCheck.h +3 -0
  36. package/eigen/Eigen/src/Cholesky/LDLT.h +377 -401
  37. package/eigen/Eigen/src/Cholesky/LLT.h +332 -360
  38. package/eigen/Eigen/src/Cholesky/LLT_LAPACKE.h +81 -56
  39. package/eigen/Eigen/src/CholmodSupport/CholmodSupport.h +620 -521
  40. package/eigen/Eigen/src/CholmodSupport/InternalHeaderCheck.h +3 -0
  41. package/eigen/Eigen/src/Core/ArithmeticSequence.h +239 -0
  42. package/eigen/Eigen/src/Core/Array.h +341 -294
  43. package/eigen/Eigen/src/Core/ArrayBase.h +190 -203
  44. package/eigen/Eigen/src/Core/ArrayWrapper.h +127 -171
  45. package/eigen/Eigen/src/Core/Assign.h +30 -40
  46. package/eigen/Eigen/src/Core/AssignEvaluator.h +711 -589
  47. package/eigen/Eigen/src/Core/Assign_MKL.h +130 -125
  48. package/eigen/Eigen/src/Core/BandMatrix.h +268 -283
  49. package/eigen/Eigen/src/Core/Block.h +375 -398
  50. package/eigen/Eigen/src/Core/CommaInitializer.h +86 -97
  51. package/eigen/Eigen/src/Core/ConditionEstimator.h +51 -53
  52. package/eigen/Eigen/src/Core/CoreEvaluators.h +1356 -1026
  53. package/eigen/Eigen/src/Core/CoreIterators.h +73 -59
  54. package/eigen/Eigen/src/Core/CwiseBinaryOp.h +114 -132
  55. package/eigen/Eigen/src/Core/CwiseNullaryOp.h +726 -617
  56. package/eigen/Eigen/src/Core/CwiseTernaryOp.h +77 -103
  57. package/eigen/Eigen/src/Core/CwiseUnaryOp.h +56 -68
  58. package/eigen/Eigen/src/Core/CwiseUnaryView.h +132 -95
  59. package/eigen/Eigen/src/Core/DenseBase.h +632 -571
  60. package/eigen/Eigen/src/Core/DenseCoeffsBase.h +511 -624
  61. package/eigen/Eigen/src/Core/DenseStorage.h +512 -509
  62. package/eigen/Eigen/src/Core/DeviceWrapper.h +153 -0
  63. package/eigen/Eigen/src/Core/Diagonal.h +169 -210
  64. package/eigen/Eigen/src/Core/DiagonalMatrix.h +351 -274
  65. package/eigen/Eigen/src/Core/DiagonalProduct.h +12 -10
  66. package/eigen/Eigen/src/Core/Dot.h +172 -222
  67. package/eigen/Eigen/src/Core/EigenBase.h +75 -85
  68. package/eigen/Eigen/src/Core/Fill.h +138 -0
  69. package/eigen/Eigen/src/Core/FindCoeff.h +464 -0
  70. package/eigen/Eigen/src/Core/ForceAlignedAccess.h +90 -109
  71. package/eigen/Eigen/src/Core/Fuzzy.h +82 -105
  72. package/eigen/Eigen/src/Core/GeneralProduct.h +327 -263
  73. package/eigen/Eigen/src/Core/GenericPacketMath.h +1472 -360
  74. package/eigen/Eigen/src/Core/GlobalFunctions.h +194 -151
  75. package/eigen/Eigen/src/Core/IO.h +147 -139
  76. package/eigen/Eigen/src/Core/IndexedView.h +321 -0
  77. package/eigen/Eigen/src/Core/InnerProduct.h +260 -0
  78. package/eigen/Eigen/src/Core/InternalHeaderCheck.h +3 -0
  79. package/eigen/Eigen/src/Core/Inverse.h +56 -66
  80. package/eigen/Eigen/src/Core/Map.h +124 -142
  81. package/eigen/Eigen/src/Core/MapBase.h +256 -281
  82. package/eigen/Eigen/src/Core/MathFunctions.h +1620 -938
  83. package/eigen/Eigen/src/Core/MathFunctionsImpl.h +233 -71
  84. package/eigen/Eigen/src/Core/Matrix.h +491 -416
  85. package/eigen/Eigen/src/Core/MatrixBase.h +468 -453
  86. package/eigen/Eigen/src/Core/NestByValue.h +66 -85
  87. package/eigen/Eigen/src/Core/NoAlias.h +79 -85
  88. package/eigen/Eigen/src/Core/NumTraits.h +235 -148
  89. package/eigen/Eigen/src/Core/PartialReduxEvaluator.h +253 -0
  90. package/eigen/Eigen/src/Core/PermutationMatrix.h +461 -511
  91. package/eigen/Eigen/src/Core/PlainObjectBase.h +871 -894
  92. package/eigen/Eigen/src/Core/Product.h +260 -139
  93. package/eigen/Eigen/src/Core/ProductEvaluators.h +863 -714
  94. package/eigen/Eigen/src/Core/Random.h +161 -136
  95. package/eigen/Eigen/src/Core/RandomImpl.h +262 -0
  96. package/eigen/Eigen/src/Core/RealView.h +250 -0
  97. package/eigen/Eigen/src/Core/Redux.h +366 -336
  98. package/eigen/Eigen/src/Core/Ref.h +308 -209
  99. package/eigen/Eigen/src/Core/Replicate.h +94 -106
  100. package/eigen/Eigen/src/Core/Reshaped.h +398 -0
  101. package/eigen/Eigen/src/Core/ReturnByValue.h +49 -55
  102. package/eigen/Eigen/src/Core/Reverse.h +136 -145
  103. package/eigen/Eigen/src/Core/Select.h +70 -140
  104. package/eigen/Eigen/src/Core/SelfAdjointView.h +262 -285
  105. package/eigen/Eigen/src/Core/SelfCwiseBinaryOp.h +23 -20
  106. package/eigen/Eigen/src/Core/SkewSymmetricMatrix3.h +382 -0
  107. package/eigen/Eigen/src/Core/Solve.h +97 -111
  108. package/eigen/Eigen/src/Core/SolveTriangular.h +131 -129
  109. package/eigen/Eigen/src/Core/SolverBase.h +138 -101
  110. package/eigen/Eigen/src/Core/StableNorm.h +156 -160
  111. package/eigen/Eigen/src/Core/StlIterators.h +619 -0
  112. package/eigen/Eigen/src/Core/Stride.h +91 -88
  113. package/eigen/Eigen/src/Core/Swap.h +70 -38
  114. package/eigen/Eigen/src/Core/Transpose.h +295 -273
  115. package/eigen/Eigen/src/Core/Transpositions.h +272 -317
  116. package/eigen/Eigen/src/Core/TriangularMatrix.h +670 -755
  117. package/eigen/Eigen/src/Core/VectorBlock.h +59 -72
  118. package/eigen/Eigen/src/Core/VectorwiseOp.h +668 -630
  119. package/eigen/Eigen/src/Core/Visitor.h +480 -216
  120. package/eigen/Eigen/src/Core/arch/AVX/Complex.h +407 -293
  121. package/eigen/Eigen/src/Core/arch/AVX/MathFunctions.h +79 -388
  122. package/eigen/Eigen/src/Core/arch/AVX/PacketMath.h +2935 -491
  123. package/eigen/Eigen/src/Core/arch/AVX/Reductions.h +353 -0
  124. package/eigen/Eigen/src/Core/arch/AVX/TypeCasting.h +279 -22
  125. package/eigen/Eigen/src/Core/arch/AVX512/Complex.h +472 -0
  126. package/eigen/Eigen/src/Core/arch/AVX512/GemmKernel.h +1245 -0
  127. package/eigen/Eigen/src/Core/arch/AVX512/MathFunctions.h +85 -333
  128. package/eigen/Eigen/src/Core/arch/AVX512/MathFunctionsFP16.h +75 -0
  129. package/eigen/Eigen/src/Core/arch/AVX512/PacketMath.h +2490 -649
  130. package/eigen/Eigen/src/Core/arch/AVX512/PacketMathFP16.h +1413 -0
  131. package/eigen/Eigen/src/Core/arch/AVX512/Reductions.h +297 -0
  132. package/eigen/Eigen/src/Core/arch/AVX512/TrsmKernel.h +1167 -0
  133. package/eigen/Eigen/src/Core/arch/AVX512/TrsmUnrolls.inc +1219 -0
  134. package/eigen/Eigen/src/Core/arch/AVX512/TypeCasting.h +277 -0
  135. package/eigen/Eigen/src/Core/arch/AVX512/TypeCastingFP16.h +130 -0
  136. package/eigen/Eigen/src/Core/arch/AltiVec/Complex.h +521 -298
  137. package/eigen/Eigen/src/Core/arch/AltiVec/MathFunctions.h +39 -280
  138. package/eigen/Eigen/src/Core/arch/AltiVec/MatrixProduct.h +3686 -0
  139. package/eigen/Eigen/src/Core/arch/AltiVec/MatrixProductCommon.h +205 -0
  140. package/eigen/Eigen/src/Core/arch/AltiVec/MatrixProductMMA.h +901 -0
  141. package/eigen/Eigen/src/Core/arch/AltiVec/MatrixProductMMAbfloat16.h +742 -0
  142. package/eigen/Eigen/src/Core/arch/AltiVec/MatrixVectorProduct.inc +2818 -0
  143. package/eigen/Eigen/src/Core/arch/AltiVec/PacketMath.h +3391 -723
  144. package/eigen/Eigen/src/Core/arch/AltiVec/TypeCasting.h +153 -0
  145. package/eigen/Eigen/src/Core/arch/Default/BFloat16.h +866 -0
  146. package/eigen/Eigen/src/Core/arch/Default/ConjHelper.h +113 -14
  147. package/eigen/Eigen/src/Core/arch/Default/GenericPacketMathFunctions.h +2634 -0
  148. package/eigen/Eigen/src/Core/arch/Default/GenericPacketMathFunctionsFwd.h +227 -0
  149. package/eigen/Eigen/src/Core/arch/Default/Half.h +1091 -0
  150. package/eigen/Eigen/src/Core/arch/Default/Settings.h +11 -13
  151. package/eigen/Eigen/src/Core/arch/GPU/Complex.h +244 -0
  152. package/eigen/Eigen/src/Core/arch/GPU/MathFunctions.h +104 -0
  153. package/eigen/Eigen/src/Core/arch/GPU/PacketMath.h +1712 -0
  154. package/eigen/Eigen/src/Core/arch/GPU/Tuple.h +268 -0
  155. package/eigen/Eigen/src/Core/arch/GPU/TypeCasting.h +77 -0
  156. package/eigen/Eigen/src/Core/arch/HIP/hcc/math_constants.h +23 -0
  157. package/eigen/Eigen/src/Core/arch/HVX/PacketMath.h +1088 -0
  158. package/eigen/Eigen/src/Core/arch/LSX/Complex.h +520 -0
  159. package/eigen/Eigen/src/Core/arch/LSX/GeneralBlockPanelKernel.h +23 -0
  160. package/eigen/Eigen/src/Core/arch/LSX/MathFunctions.h +43 -0
  161. package/eigen/Eigen/src/Core/arch/LSX/PacketMath.h +2866 -0
  162. package/eigen/Eigen/src/Core/arch/LSX/TypeCasting.h +526 -0
  163. package/eigen/Eigen/src/Core/arch/MSA/Complex.h +620 -0
  164. package/eigen/Eigen/src/Core/arch/MSA/MathFunctions.h +379 -0
  165. package/eigen/Eigen/src/Core/arch/MSA/PacketMath.h +1237 -0
  166. package/eigen/Eigen/src/Core/arch/NEON/Complex.h +531 -289
  167. package/eigen/Eigen/src/Core/arch/NEON/GeneralBlockPanelKernel.h +243 -0
  168. package/eigen/Eigen/src/Core/arch/NEON/MathFunctions.h +50 -73
  169. package/eigen/Eigen/src/Core/arch/NEON/PacketMath.h +5915 -579
  170. package/eigen/Eigen/src/Core/arch/NEON/TypeCasting.h +1642 -0
  171. package/eigen/Eigen/src/Core/arch/NEON/UnaryFunctors.h +57 -0
  172. package/eigen/Eigen/src/Core/arch/SSE/Complex.h +366 -334
  173. package/eigen/Eigen/src/Core/arch/SSE/MathFunctions.h +40 -514
  174. package/eigen/Eigen/src/Core/arch/SSE/PacketMath.h +2164 -675
  175. package/eigen/Eigen/src/Core/arch/SSE/Reductions.h +324 -0
  176. package/eigen/Eigen/src/Core/arch/SSE/TypeCasting.h +188 -35
  177. package/eigen/Eigen/src/Core/arch/SVE/MathFunctions.h +48 -0
  178. package/eigen/Eigen/src/Core/arch/SVE/PacketMath.h +674 -0
  179. package/eigen/Eigen/src/Core/arch/SVE/TypeCasting.h +52 -0
  180. package/eigen/Eigen/src/Core/arch/SYCL/InteropHeaders.h +227 -0
  181. package/eigen/Eigen/src/Core/arch/SYCL/MathFunctions.h +303 -0
  182. package/eigen/Eigen/src/Core/arch/SYCL/PacketMath.h +576 -0
  183. package/eigen/Eigen/src/Core/arch/SYCL/TypeCasting.h +83 -0
  184. package/eigen/Eigen/src/Core/arch/ZVector/Complex.h +434 -261
  185. package/eigen/Eigen/src/Core/arch/ZVector/MathFunctions.h +160 -53
  186. package/eigen/Eigen/src/Core/arch/ZVector/PacketMath.h +1073 -605
  187. package/eigen/Eigen/src/Core/functors/AssignmentFunctors.h +123 -117
  188. package/eigen/Eigen/src/Core/functors/BinaryFunctors.h +594 -322
  189. package/eigen/Eigen/src/Core/functors/NullaryFunctors.h +204 -118
  190. package/eigen/Eigen/src/Core/functors/StlFunctors.h +110 -97
  191. package/eigen/Eigen/src/Core/functors/TernaryFunctors.h +34 -7
  192. package/eigen/Eigen/src/Core/functors/UnaryFunctors.h +1158 -530
  193. package/eigen/Eigen/src/Core/products/GeneralBlockPanelKernel.h +2329 -1333
  194. package/eigen/Eigen/src/Core/products/GeneralMatrixMatrix.h +328 -364
  195. package/eigen/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h +191 -178
  196. package/eigen/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h +85 -82
  197. package/eigen/Eigen/src/Core/products/GeneralMatrixMatrix_BLAS.h +154 -73
  198. package/eigen/Eigen/src/Core/products/GeneralMatrixVector.h +396 -542
  199. package/eigen/Eigen/src/Core/products/GeneralMatrixVector_BLAS.h +80 -77
  200. package/eigen/Eigen/src/Core/products/Parallelizer.h +208 -92
  201. package/eigen/Eigen/src/Core/products/SelfadjointMatrixMatrix.h +331 -375
  202. package/eigen/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h +206 -224
  203. package/eigen/Eigen/src/Core/products/SelfadjointMatrixVector.h +139 -146
  204. package/eigen/Eigen/src/Core/products/SelfadjointMatrixVector_BLAS.h +58 -61
  205. package/eigen/Eigen/src/Core/products/SelfadjointProduct.h +71 -71
  206. package/eigen/Eigen/src/Core/products/SelfadjointRank2Update.h +48 -46
  207. package/eigen/Eigen/src/Core/products/TriangularMatrixMatrix.h +294 -369
  208. package/eigen/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h +246 -238
  209. package/eigen/Eigen/src/Core/products/TriangularMatrixVector.h +244 -247
  210. package/eigen/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h +212 -192
  211. package/eigen/Eigen/src/Core/products/TriangularSolverMatrix.h +328 -275
  212. package/eigen/Eigen/src/Core/products/TriangularSolverMatrix_BLAS.h +108 -109
  213. package/eigen/Eigen/src/Core/products/TriangularSolverVector.h +70 -93
  214. package/eigen/Eigen/src/Core/util/Assert.h +158 -0
  215. package/eigen/Eigen/src/Core/util/BlasUtil.h +413 -290
  216. package/eigen/Eigen/src/Core/util/ConfigureVectorization.h +543 -0
  217. package/eigen/Eigen/src/Core/util/Constants.h +314 -263
  218. package/eigen/Eigen/src/Core/util/DisableStupidWarnings.h +130 -78
  219. package/eigen/Eigen/src/Core/util/EmulateArray.h +270 -0
  220. package/eigen/Eigen/src/Core/util/ForwardDeclarations.h +450 -224
  221. package/eigen/Eigen/src/Core/util/GpuHipCudaDefines.inc +101 -0
  222. package/eigen/Eigen/src/Core/util/GpuHipCudaUndefines.inc +45 -0
  223. package/eigen/Eigen/src/Core/util/IndexedViewHelper.h +487 -0
  224. package/eigen/Eigen/src/Core/util/IntegralConstant.h +279 -0
  225. package/eigen/Eigen/src/Core/util/MKL_support.h +39 -30
  226. package/eigen/Eigen/src/Core/util/Macros.h +939 -646
  227. package/eigen/Eigen/src/Core/util/MaxSizeVector.h +139 -0
  228. package/eigen/Eigen/src/Core/util/Memory.h +1042 -650
  229. package/eigen/Eigen/src/Core/util/Meta.h +618 -426
  230. package/eigen/Eigen/src/Core/util/MoreMeta.h +638 -0
  231. package/eigen/Eigen/src/Core/util/ReenableStupidWarnings.h +32 -19
  232. package/eigen/Eigen/src/Core/util/ReshapedHelper.h +51 -0
  233. package/eigen/Eigen/src/Core/util/Serializer.h +209 -0
  234. package/eigen/Eigen/src/Core/util/StaticAssert.h +51 -164
  235. package/eigen/Eigen/src/Core/util/SymbolicIndex.h +445 -0
  236. package/eigen/Eigen/src/Core/util/XprHelper.h +793 -538
  237. package/eigen/Eigen/src/Eigenvalues/ComplexEigenSolver.h +246 -277
  238. package/eigen/Eigen/src/Eigenvalues/ComplexSchur.h +299 -319
  239. package/eigen/Eigen/src/Eigenvalues/ComplexSchur_LAPACKE.h +52 -48
  240. package/eigen/Eigen/src/Eigenvalues/EigenSolver.h +413 -456
  241. package/eigen/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h +309 -325
  242. package/eigen/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h +157 -171
  243. package/eigen/Eigen/src/Eigenvalues/HessenbergDecomposition.h +292 -310
  244. package/eigen/Eigen/src/Eigenvalues/InternalHeaderCheck.h +3 -0
  245. package/eigen/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h +91 -107
  246. package/eigen/Eigen/src/Eigenvalues/RealQZ.h +539 -606
  247. package/eigen/Eigen/src/Eigenvalues/RealSchur.h +348 -382
  248. package/eigen/Eigen/src/Eigenvalues/RealSchur_LAPACKE.h +41 -35
  249. package/eigen/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h +579 -600
  250. package/eigen/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h +47 -44
  251. package/eigen/Eigen/src/Eigenvalues/Tridiagonalization.h +434 -461
  252. package/eigen/Eigen/src/Geometry/AlignedBox.h +307 -214
  253. package/eigen/Eigen/src/Geometry/AngleAxis.h +135 -137
  254. package/eigen/Eigen/src/Geometry/EulerAngles.h +163 -74
  255. package/eigen/Eigen/src/Geometry/Homogeneous.h +289 -333
  256. package/eigen/Eigen/src/Geometry/Hyperplane.h +152 -161
  257. package/eigen/Eigen/src/Geometry/InternalHeaderCheck.h +3 -0
  258. package/eigen/Eigen/src/Geometry/OrthoMethods.h +168 -145
  259. package/eigen/Eigen/src/Geometry/ParametrizedLine.h +141 -104
  260. package/eigen/Eigen/src/Geometry/Quaternion.h +595 -497
  261. package/eigen/Eigen/src/Geometry/Rotation2D.h +110 -108
  262. package/eigen/Eigen/src/Geometry/RotationBase.h +148 -145
  263. package/eigen/Eigen/src/Geometry/Scaling.h +115 -90
  264. package/eigen/Eigen/src/Geometry/Transform.h +896 -953
  265. package/eigen/Eigen/src/Geometry/Translation.h +100 -98
  266. package/eigen/Eigen/src/Geometry/Umeyama.h +79 -84
  267. package/eigen/Eigen/src/Geometry/arch/Geometry_SIMD.h +154 -0
  268. package/eigen/Eigen/src/Householder/BlockHouseholder.h +54 -42
  269. package/eigen/Eigen/src/Householder/Householder.h +104 -122
  270. package/eigen/Eigen/src/Householder/HouseholderSequence.h +416 -382
  271. package/eigen/Eigen/src/Householder/InternalHeaderCheck.h +3 -0
  272. package/eigen/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h +153 -166
  273. package/eigen/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h +127 -138
  274. package/eigen/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h +95 -124
  275. package/eigen/Eigen/src/IterativeLinearSolvers/IncompleteCholesky.h +269 -267
  276. package/eigen/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h +246 -259
  277. package/eigen/Eigen/src/IterativeLinearSolvers/InternalHeaderCheck.h +3 -0
  278. package/eigen/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h +218 -217
  279. package/eigen/Eigen/src/IterativeLinearSolvers/LeastSquareConjugateGradient.h +80 -103
  280. package/eigen/Eigen/src/IterativeLinearSolvers/SolveWithGuess.h +59 -63
  281. package/eigen/Eigen/src/Jacobi/InternalHeaderCheck.h +3 -0
  282. package/eigen/Eigen/src/Jacobi/Jacobi.h +256 -291
  283. package/eigen/Eigen/src/KLUSupport/InternalHeaderCheck.h +3 -0
  284. package/eigen/Eigen/src/KLUSupport/KLUSupport.h +339 -0
  285. package/eigen/Eigen/src/LU/Determinant.h +60 -63
  286. package/eigen/Eigen/src/LU/FullPivLU.h +561 -626
  287. package/eigen/Eigen/src/LU/InternalHeaderCheck.h +3 -0
  288. package/eigen/Eigen/src/LU/InverseImpl.h +213 -275
  289. package/eigen/Eigen/src/LU/PartialPivLU.h +407 -435
  290. package/eigen/Eigen/src/LU/PartialPivLU_LAPACKE.h +54 -40
  291. package/eigen/Eigen/src/LU/arch/InverseSize4.h +353 -0
  292. package/eigen/Eigen/src/MetisSupport/InternalHeaderCheck.h +3 -0
  293. package/eigen/Eigen/src/MetisSupport/MetisSupport.h +81 -93
  294. package/eigen/Eigen/src/OrderingMethods/Amd.h +250 -282
  295. package/eigen/Eigen/src/OrderingMethods/Eigen_Colamd.h +950 -1103
  296. package/eigen/Eigen/src/OrderingMethods/InternalHeaderCheck.h +3 -0
  297. package/eigen/Eigen/src/OrderingMethods/Ordering.h +111 -122
  298. package/eigen/Eigen/src/PaStiXSupport/InternalHeaderCheck.h +3 -0
  299. package/eigen/Eigen/src/PaStiXSupport/PaStiXSupport.h +524 -570
  300. package/eigen/Eigen/src/PardisoSupport/InternalHeaderCheck.h +3 -0
  301. package/eigen/Eigen/src/PardisoSupport/PardisoSupport.h +385 -429
  302. package/eigen/Eigen/src/QR/ColPivHouseholderQR.h +494 -473
  303. package/eigen/Eigen/src/QR/ColPivHouseholderQR_LAPACKE.h +120 -56
  304. package/eigen/Eigen/src/QR/CompleteOrthogonalDecomposition.h +223 -137
  305. package/eigen/Eigen/src/QR/FullPivHouseholderQR.h +517 -460
  306. package/eigen/Eigen/src/QR/HouseholderQR.h +412 -278
  307. package/eigen/Eigen/src/QR/HouseholderQR_LAPACKE.h +32 -23
  308. package/eigen/Eigen/src/QR/InternalHeaderCheck.h +3 -0
  309. package/eigen/Eigen/src/SPQRSupport/InternalHeaderCheck.h +3 -0
  310. package/eigen/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h +263 -261
  311. package/eigen/Eigen/src/SVD/BDCSVD.h +872 -679
  312. package/eigen/Eigen/src/SVD/BDCSVD_LAPACKE.h +174 -0
  313. package/eigen/Eigen/src/SVD/InternalHeaderCheck.h +3 -0
  314. package/eigen/Eigen/src/SVD/JacobiSVD.h +585 -543
  315. package/eigen/Eigen/src/SVD/JacobiSVD_LAPACKE.h +85 -49
  316. package/eigen/Eigen/src/SVD/SVDBase.h +281 -160
  317. package/eigen/Eigen/src/SVD/UpperBidiagonalization.h +202 -237
  318. package/eigen/Eigen/src/SparseCholesky/InternalHeaderCheck.h +3 -0
  319. package/eigen/Eigen/src/SparseCholesky/SimplicialCholesky.h +769 -590
  320. package/eigen/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h +318 -129
  321. package/eigen/Eigen/src/SparseCore/AmbiVector.h +202 -251
  322. package/eigen/Eigen/src/SparseCore/CompressedStorage.h +184 -236
  323. package/eigen/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h +140 -184
  324. package/eigen/Eigen/src/SparseCore/InternalHeaderCheck.h +3 -0
  325. package/eigen/Eigen/src/SparseCore/SparseAssign.h +174 -111
  326. package/eigen/Eigen/src/SparseCore/SparseBlock.h +408 -477
  327. package/eigen/Eigen/src/SparseCore/SparseColEtree.h +100 -112
  328. package/eigen/Eigen/src/SparseCore/SparseCompressedBase.h +531 -280
  329. package/eigen/Eigen/src/SparseCore/SparseCwiseBinaryOp.h +559 -347
  330. package/eigen/Eigen/src/SparseCore/SparseCwiseUnaryOp.h +100 -108
  331. package/eigen/Eigen/src/SparseCore/SparseDenseProduct.h +185 -191
  332. package/eigen/Eigen/src/SparseCore/SparseDiagonalProduct.h +71 -71
  333. package/eigen/Eigen/src/SparseCore/SparseDot.h +49 -47
  334. package/eigen/Eigen/src/SparseCore/SparseFuzzy.h +13 -11
  335. package/eigen/Eigen/src/SparseCore/SparseMap.h +243 -253
  336. package/eigen/Eigen/src/SparseCore/SparseMatrix.h +1614 -1142
  337. package/eigen/Eigen/src/SparseCore/SparseMatrixBase.h +403 -357
  338. package/eigen/Eigen/src/SparseCore/SparsePermutation.h +186 -115
  339. package/eigen/Eigen/src/SparseCore/SparseProduct.h +100 -91
  340. package/eigen/Eigen/src/SparseCore/SparseRedux.h +22 -24
  341. package/eigen/Eigen/src/SparseCore/SparseRef.h +268 -295
  342. package/eigen/Eigen/src/SparseCore/SparseSelfAdjointView.h +371 -414
  343. package/eigen/Eigen/src/SparseCore/SparseSolverBase.h +78 -87
  344. package/eigen/Eigen/src/SparseCore/SparseSparseProductWithPruning.h +81 -95
  345. package/eigen/Eigen/src/SparseCore/SparseTranspose.h +62 -71
  346. package/eigen/Eigen/src/SparseCore/SparseTriangularView.h +132 -144
  347. package/eigen/Eigen/src/SparseCore/SparseUtil.h +146 -115
  348. package/eigen/Eigen/src/SparseCore/SparseVector.h +426 -372
  349. package/eigen/Eigen/src/SparseCore/SparseView.h +164 -193
  350. package/eigen/Eigen/src/SparseCore/TriangularSolver.h +129 -170
  351. package/eigen/Eigen/src/SparseLU/InternalHeaderCheck.h +3 -0
  352. package/eigen/Eigen/src/SparseLU/SparseLU.h +814 -618
  353. package/eigen/Eigen/src/SparseLU/SparseLUImpl.h +61 -48
  354. package/eigen/Eigen/src/SparseLU/SparseLU_Memory.h +102 -118
  355. package/eigen/Eigen/src/SparseLU/SparseLU_Structs.h +38 -35
  356. package/eigen/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h +273 -255
  357. package/eigen/Eigen/src/SparseLU/SparseLU_Utils.h +44 -49
  358. package/eigen/Eigen/src/SparseLU/SparseLU_column_bmod.h +104 -108
  359. package/eigen/Eigen/src/SparseLU/SparseLU_column_dfs.h +90 -101
  360. package/eigen/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h +57 -58
  361. package/eigen/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h +43 -55
  362. package/eigen/Eigen/src/SparseLU/SparseLU_kernel_bmod.h +74 -71
  363. package/eigen/Eigen/src/SparseLU/SparseLU_panel_bmod.h +125 -133
  364. package/eigen/Eigen/src/SparseLU/SparseLU_panel_dfs.h +136 -159
  365. package/eigen/Eigen/src/SparseLU/SparseLU_pivotL.h +51 -52
  366. package/eigen/Eigen/src/SparseLU/SparseLU_pruneL.h +67 -73
  367. package/eigen/Eigen/src/SparseLU/SparseLU_relax_snode.h +24 -26
  368. package/eigen/Eigen/src/SparseQR/InternalHeaderCheck.h +3 -0
  369. package/eigen/Eigen/src/SparseQR/SparseQR.h +451 -490
  370. package/eigen/Eigen/src/StlSupport/StdDeque.h +28 -105
  371. package/eigen/Eigen/src/StlSupport/StdList.h +28 -84
  372. package/eigen/Eigen/src/StlSupport/StdVector.h +28 -108
  373. package/eigen/Eigen/src/StlSupport/details.h +48 -50
  374. package/eigen/Eigen/src/SuperLUSupport/InternalHeaderCheck.h +3 -0
  375. package/eigen/Eigen/src/SuperLUSupport/SuperLUSupport.h +634 -732
  376. package/eigen/Eigen/src/ThreadPool/Barrier.h +70 -0
  377. package/eigen/Eigen/src/ThreadPool/CoreThreadPoolDevice.h +336 -0
  378. package/eigen/Eigen/src/ThreadPool/EventCount.h +241 -0
  379. package/eigen/Eigen/src/ThreadPool/ForkJoin.h +140 -0
  380. package/eigen/Eigen/src/ThreadPool/InternalHeaderCheck.h +4 -0
  381. package/eigen/Eigen/src/ThreadPool/NonBlockingThreadPool.h +587 -0
  382. package/eigen/Eigen/src/ThreadPool/RunQueue.h +230 -0
  383. package/eigen/Eigen/src/ThreadPool/ThreadCancel.h +21 -0
  384. package/eigen/Eigen/src/ThreadPool/ThreadEnvironment.h +43 -0
  385. package/eigen/Eigen/src/ThreadPool/ThreadLocal.h +289 -0
  386. package/eigen/Eigen/src/ThreadPool/ThreadPoolInterface.h +50 -0
  387. package/eigen/Eigen/src/ThreadPool/ThreadYield.h +16 -0
  388. package/eigen/Eigen/src/UmfPackSupport/InternalHeaderCheck.h +3 -0
  389. package/eigen/Eigen/src/UmfPackSupport/UmfPackSupport.h +480 -380
  390. package/eigen/Eigen/src/misc/Image.h +41 -43
  391. package/eigen/Eigen/src/misc/InternalHeaderCheck.h +3 -0
  392. package/eigen/Eigen/src/misc/Kernel.h +39 -41
  393. package/eigen/Eigen/src/misc/RealSvd2x2.h +19 -21
  394. package/eigen/Eigen/src/misc/blas.h +83 -426
  395. package/eigen/Eigen/src/misc/lapacke.h +9976 -16182
  396. package/eigen/Eigen/src/misc/lapacke_helpers.h +163 -0
  397. package/eigen/Eigen/src/misc/lapacke_mangling.h +4 -5
  398. package/eigen/Eigen/src/plugins/ArrayCwiseBinaryOps.inc +344 -0
  399. package/eigen/Eigen/src/plugins/ArrayCwiseUnaryOps.inc +544 -0
  400. package/eigen/Eigen/src/plugins/BlockMethods.inc +1370 -0
  401. package/eigen/Eigen/src/plugins/CommonCwiseBinaryOps.inc +116 -0
  402. package/eigen/Eigen/src/plugins/CommonCwiseUnaryOps.inc +167 -0
  403. package/eigen/Eigen/src/plugins/IndexedViewMethods.inc +192 -0
  404. package/eigen/Eigen/src/plugins/InternalHeaderCheck.inc +3 -0
  405. package/eigen/Eigen/src/plugins/MatrixCwiseBinaryOps.inc +331 -0
  406. package/eigen/Eigen/src/plugins/MatrixCwiseUnaryOps.inc +118 -0
  407. package/eigen/Eigen/src/plugins/ReshapedMethods.inc +133 -0
  408. package/lib/LibEigen.d.ts +4 -0
  409. package/lib/LibEigen.js +14 -0
  410. package/lib/index.d.ts +1 -1
  411. package/lib/index.js +7 -3
  412. package/package.json +2 -10
  413. package/eigen/Eigen/CMakeLists.txt +0 -19
  414. package/eigen/Eigen/src/Core/BooleanRedux.h +0 -164
  415. package/eigen/Eigen/src/Core/arch/CUDA/Complex.h +0 -103
  416. package/eigen/Eigen/src/Core/arch/CUDA/Half.h +0 -675
  417. package/eigen/Eigen/src/Core/arch/CUDA/MathFunctions.h +0 -91
  418. package/eigen/Eigen/src/Core/arch/CUDA/PacketMath.h +0 -333
  419. package/eigen/Eigen/src/Core/arch/CUDA/PacketMathHalf.h +0 -1124
  420. package/eigen/Eigen/src/Core/arch/CUDA/TypeCasting.h +0 -212
  421. package/eigen/Eigen/src/Core/util/NonMPL2.h +0 -3
  422. package/eigen/Eigen/src/Geometry/arch/Geometry_SSE.h +0 -161
  423. package/eigen/Eigen/src/LU/arch/Inverse_SSE.h +0 -338
  424. package/eigen/Eigen/src/SparseCore/MappedSparseMatrix.h +0 -67
  425. package/eigen/Eigen/src/SparseLU/SparseLU_gemm_kernel.h +0 -280
  426. package/eigen/Eigen/src/misc/lapack.h +0 -152
  427. package/eigen/Eigen/src/plugins/ArrayCwiseBinaryOps.h +0 -332
  428. package/eigen/Eigen/src/plugins/ArrayCwiseUnaryOps.h +0 -552
  429. package/eigen/Eigen/src/plugins/BlockMethods.h +0 -1058
  430. package/eigen/Eigen/src/plugins/CommonCwiseBinaryOps.h +0 -115
  431. package/eigen/Eigen/src/plugins/CommonCwiseUnaryOps.h +0 -163
  432. package/eigen/Eigen/src/plugins/MatrixCwiseBinaryOps.h +0 -152
  433. package/eigen/Eigen/src/plugins/MatrixCwiseUnaryOps.h +0 -85
  434. package/lib/eigen.d.ts +0 -2
  435. package/lib/eigen.js +0 -15
@@ -1,9 +1,9 @@
1
1
  // This file is part of Eigen, a lightweight C++ template library
2
2
  // for linear algebra.
3
- //
3
+ //
4
4
  // We used the "A Divide-And-Conquer Algorithm for the Bidiagonal SVD"
5
5
  // research report written by Ming Gu and Stanley C.Eisenstat
6
- // The code variable names correspond to the names they used in their
6
+ // The code variable names correspond to the names they used in their
7
7
  // report
8
8
  //
9
9
  // Copyright (C) 2013 Gauthier Brun <brun.gauthier@gmail.com>
@@ -22,25 +22,36 @@
22
22
  // #define EIGEN_BDCSVD_DEBUG_VERBOSE
23
23
  // #define EIGEN_BDCSVD_SANITY_CHECKS
24
24
 
25
+ #ifdef EIGEN_BDCSVD_SANITY_CHECKS
26
+ #undef eigen_internal_assert
27
+ #define eigen_internal_assert(X) assert(X);
28
+ #endif
29
+
30
+ // IWYU pragma: private
31
+ #include "./InternalHeaderCheck.h"
32
+
33
+ #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
34
+ #include <iostream>
35
+ #endif
36
+
25
37
  namespace Eigen {
26
38
 
27
39
  #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
28
40
  IOFormat bdcsvdfmt(8, 0, ", ", "\n", " [", "]");
29
41
  #endif
30
-
31
- template<typename _MatrixType> class BDCSVD;
42
+
43
+ template <typename MatrixType_, int Options>
44
+ class BDCSVD;
32
45
 
33
46
  namespace internal {
34
47
 
35
- template<typename _MatrixType>
36
- struct traits<BDCSVD<_MatrixType> >
37
- {
38
- typedef _MatrixType MatrixType;
39
- };
48
+ template <typename MatrixType_, int Options>
49
+ struct traits<BDCSVD<MatrixType_, Options> > : svd_traits<MatrixType_, Options> {
50
+ typedef MatrixType_ MatrixType;
51
+ };
52
+
53
+ } // end namespace internal
40
54
 
41
- } // end namespace internal
42
-
43
-
44
55
  /** \ingroup SVD_Module
45
56
  *
46
57
  *
@@ -48,7 +59,14 @@ struct traits<BDCSVD<_MatrixType> >
48
59
  *
49
60
  * \brief class Bidiagonal Divide and Conquer SVD
50
61
  *
51
- * \tparam _MatrixType the type of the matrix of which we are computing the SVD decomposition
62
+ * \tparam MatrixType_ the type of the matrix of which we are computing the SVD decomposition
63
+ *
64
+ * \tparam Options_ this optional parameter allows one to specify options for computing unitaries \a U and \a V.
65
+ * Possible values are #ComputeThinU, #ComputeThinV, #ComputeFullU, #ComputeFullV, and
66
+ * #DisableQRDecomposition. It is not possible to request both the thin and full version of \a U or
67
+ * \a V. By default, unitaries are not computed. BDCSVD uses R-Bidiagonalization to improve
68
+ * performance on tall and wide matrices. For backwards compatility, the option
69
+ * #DisableQRDecomposition can be used to disable this optimization.
52
70
  *
53
71
  * This class first reduces the input matrix to bi-diagonal form using class UpperBidiagonalization,
54
72
  * and then performs a divide-and-conquer diagonalization. Small blocks are diagonalized using class JacobiSVD.
@@ -57,46 +75,50 @@ struct traits<BDCSVD<_MatrixType> >
57
75
  * recommended and can several order of magnitude faster.
58
76
  *
59
77
  * \warning this algorithm is unlikely to provide accurate result when compiled with unsafe math optimizations.
60
- * For instance, this concerns Intel's compiler (ICC), which perfroms such optimization by default unless
78
+ * For instance, this concerns Intel's compiler (ICC), which performs such optimization by default unless
61
79
  * you compile with the \c -fp-model \c precise option. Likewise, the \c -ffast-math option of GCC or clang will
62
80
  * significantly degrade the accuracy.
63
81
  *
64
82
  * \sa class JacobiSVD
65
83
  */
66
- template<typename _MatrixType>
67
- class BDCSVD : public SVDBase<BDCSVD<_MatrixType> >
68
- {
84
+ template <typename MatrixType_, int Options_>
85
+ class BDCSVD : public SVDBase<BDCSVD<MatrixType_, Options_> > {
69
86
  typedef SVDBase<BDCSVD> Base;
70
-
71
- public:
72
- using Base::rows;
87
+
88
+ public:
73
89
  using Base::cols;
74
90
  using Base::computeU;
75
91
  using Base::computeV;
76
-
77
- typedef _MatrixType MatrixType;
78
- typedef typename MatrixType::Scalar Scalar;
79
- typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
92
+ using Base::diagSize;
93
+ using Base::rows;
94
+
95
+ typedef MatrixType_ MatrixType;
96
+ typedef typename Base::Scalar Scalar;
97
+ typedef typename Base::RealScalar RealScalar;
80
98
  typedef typename NumTraits<RealScalar>::Literal Literal;
99
+ typedef typename Base::Index Index;
81
100
  enum {
82
- RowsAtCompileTime = MatrixType::RowsAtCompileTime,
83
- ColsAtCompileTime = MatrixType::ColsAtCompileTime,
84
- DiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_DYNAMIC(RowsAtCompileTime, ColsAtCompileTime),
85
- MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
86
- MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
87
- MaxDiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(MaxRowsAtCompileTime, MaxColsAtCompileTime),
88
- MatrixOptions = MatrixType::Options
101
+ Options = Options_,
102
+ QRDecomposition = Options & internal::QRPreconditionerBits,
103
+ ComputationOptions = Options & internal::ComputationOptionsBits,
104
+ RowsAtCompileTime = Base::RowsAtCompileTime,
105
+ ColsAtCompileTime = Base::ColsAtCompileTime,
106
+ DiagSizeAtCompileTime = Base::DiagSizeAtCompileTime,
107
+ MaxRowsAtCompileTime = Base::MaxRowsAtCompileTime,
108
+ MaxColsAtCompileTime = Base::MaxColsAtCompileTime,
109
+ MaxDiagSizeAtCompileTime = Base::MaxDiagSizeAtCompileTime,
110
+ MatrixOptions = Base::MatrixOptions
89
111
  };
90
112
 
91
113
  typedef typename Base::MatrixUType MatrixUType;
92
114
  typedef typename Base::MatrixVType MatrixVType;
93
115
  typedef typename Base::SingularValuesType SingularValuesType;
94
-
116
+
95
117
  typedef Matrix<Scalar, Dynamic, Dynamic, ColMajor> MatrixX;
96
118
  typedef Matrix<RealScalar, Dynamic, Dynamic, ColMajor> MatrixXr;
97
119
  typedef Matrix<RealScalar, Dynamic, 1> VectorType;
98
120
  typedef Array<RealScalar, Dynamic, 1> ArrayXr;
99
- typedef Array<Index,1,Dynamic> ArrayXi;
121
+ typedef Array<Index, 1, Dynamic> ArrayXi;
100
122
  typedef Ref<ArrayXr> ArrayRef;
101
123
  typedef Ref<ArrayXi> IndicesRef;
102
124
 
@@ -105,459 +127,554 @@ public:
105
127
  * The default constructor is useful in cases in which the user intends to
106
128
  * perform decompositions via BDCSVD::compute(const MatrixType&).
107
129
  */
108
- BDCSVD() : m_algoswap(16), m_numIters(0)
109
- {}
130
+ BDCSVD() : m_algoswap(16), m_isTranspose(false), m_compU(false), m_compV(false), m_numIters(0) {}
110
131
 
132
+ /** \brief Default Constructor with memory preallocation
133
+ *
134
+ * Like the default constructor but with preallocation of the internal data
135
+ * according to the specified problem size and \a Options template parameter.
136
+ * \sa BDCSVD()
137
+ */
138
+ BDCSVD(Index rows, Index cols) : m_algoswap(16), m_numIters(0) {
139
+ allocate(rows, cols, internal::get_computation_options(Options));
140
+ }
111
141
 
112
142
  /** \brief Default Constructor with memory preallocation
113
143
  *
114
144
  * Like the default constructor but with preallocation of the internal data
115
- * according to the specified problem size.
145
+ * according to the specified problem size and the \a computationOptions.
146
+ *
147
+ * One \b cannot request unitaries using both the \a Options template parameter
148
+ * and the constructor. If possible, prefer using the \a Options template parameter.
149
+ *
150
+ * \param rows number of rows for the input matrix
151
+ * \param cols number of columns for the input matrix
152
+ * \param computationOptions specification for computing Thin/Full unitaries U/V
116
153
  * \sa BDCSVD()
154
+ *
155
+ * \deprecated Will be removed in the next major Eigen version. Options should
156
+ * be specified in the \a Options template parameter.
117
157
  */
118
- BDCSVD(Index rows, Index cols, unsigned int computationOptions = 0)
119
- : m_algoswap(16), m_numIters(0)
120
- {
158
+ EIGEN_DEPRECATED_WITH_REASON("Options should be specified using the class template parameter.")
159
+ BDCSVD(Index rows, Index cols, unsigned int computationOptions) : m_algoswap(16), m_numIters(0) {
160
+ internal::check_svd_options_assertions<MatrixType, Options>(computationOptions, rows, cols);
121
161
  allocate(rows, cols, computationOptions);
122
162
  }
123
163
 
124
- /** \brief Constructor performing the decomposition of given matrix.
164
+ /** \brief Constructor performing the decomposition of given matrix, using the custom options specified
165
+ * with the \a Options template parameter.
125
166
  *
126
167
  * \param matrix the matrix to decompose
127
- * \param computationOptions optional parameter allowing to specify if you want full or thin U or V unitaries to be computed.
128
- * By default, none is computed. This is a bit - field, the possible bits are #ComputeFullU, #ComputeThinU,
129
- * #ComputeFullV, #ComputeThinV.
130
- *
131
- * Thin unitaries are only available if your matrix type has a Dynamic number of columns (for example MatrixXf). They also are not
132
- * available with the (non - default) FullPivHouseholderQR preconditioner.
133
168
  */
134
- BDCSVD(const MatrixType& matrix, unsigned int computationOptions = 0)
135
- : m_algoswap(16), m_numIters(0)
136
- {
137
- compute(matrix, computationOptions);
169
+ template <typename Derived>
170
+ BDCSVD(const MatrixBase<Derived>& matrix) : m_algoswap(16), m_numIters(0) {
171
+ compute_impl(matrix, internal::get_computation_options(Options));
138
172
  }
139
173
 
140
- ~BDCSVD()
141
- {
142
- }
143
-
144
- /** \brief Method performing the decomposition of given matrix using custom options.
174
+ /** \brief Constructor performing the decomposition of given matrix using specified options
175
+ * for computing unitaries.
176
+ *
177
+ * One \b cannot request unitaries using both the \a Options template parameter
178
+ * and the constructor. If possible, prefer using the \a Options template parameter.
145
179
  *
146
180
  * \param matrix the matrix to decompose
147
- * \param computationOptions optional parameter allowing to specify if you want full or thin U or V unitaries to be computed.
148
- * By default, none is computed. This is a bit - field, the possible bits are #ComputeFullU, #ComputeThinU,
149
- * #ComputeFullV, #ComputeThinV.
181
+ * \param computationOptions specification for computing Thin/Full unitaries U/V
150
182
  *
151
- * Thin unitaries are only available if your matrix type has a Dynamic number of columns (for example MatrixXf). They also are not
152
- * available with the (non - default) FullPivHouseholderQR preconditioner.
183
+ * \deprecated Will be removed in the next major Eigen version. Options should
184
+ * be specified in the \a Options template parameter.
153
185
  */
154
- BDCSVD& compute(const MatrixType& matrix, unsigned int computationOptions);
186
+ template <typename Derived>
187
+ EIGEN_DEPRECATED_WITH_REASON("Options should be specified using the class template parameter.")
188
+ BDCSVD(const MatrixBase<Derived>& matrix, unsigned int computationOptions) : m_algoswap(16), m_numIters(0) {
189
+ internal::check_svd_options_assertions<MatrixType, Options>(computationOptions, matrix.rows(), matrix.cols());
190
+ compute_impl(matrix, computationOptions);
191
+ }
155
192
 
156
- /** \brief Method performing the decomposition of given matrix using current options.
193
+ ~BDCSVD() {}
194
+
195
+ /** \brief Method performing the decomposition of given matrix. Computes Thin/Full unitaries U/V if specified
196
+ * using the \a Options template parameter or the class constructor.
157
197
  *
158
198
  * \param matrix the matrix to decompose
199
+ */
200
+ template <typename Derived>
201
+ BDCSVD& compute(const MatrixBase<Derived>& matrix) {
202
+ return compute_impl(matrix, m_computationOptions);
203
+ }
204
+
205
+ /** \brief Method performing the decomposition of given matrix, as specified by
206
+ * the `computationOptions` parameter.
159
207
  *
160
- * This method uses the current \a computationOptions, as already passed to the constructor or to compute(const MatrixType&, unsigned int).
208
+ * \param matrix the matrix to decompose
209
+ * \param computationOptions specify whether to compute Thin/Full unitaries U/V
210
+ *
211
+ * \deprecated Will be removed in the next major Eigen version. Options should
212
+ * be specified in the \a Options template parameter.
161
213
  */
162
- BDCSVD& compute(const MatrixType& matrix)
163
- {
164
- return compute(matrix, this->m_computationOptions);
214
+ template <typename Derived>
215
+ EIGEN_DEPRECATED_WITH_REASON("Options should be specified using the class template parameter.")
216
+ BDCSVD& compute(const MatrixBase<Derived>& matrix, unsigned int computationOptions) {
217
+ internal::check_svd_options_assertions<MatrixType, Options>(computationOptions, matrix.rows(), matrix.cols());
218
+ return compute_impl(matrix, computationOptions);
165
219
  }
166
220
 
167
- void setSwitchSize(int s)
168
- {
169
- eigen_assert(s>3 && "BDCSVD the size of the algo switch has to be greater than 3");
221
+ void setSwitchSize(int s) {
222
+ eigen_assert(s >= 3 && "BDCSVD the size of the algo switch has to be at least 3.");
170
223
  m_algoswap = s;
171
224
  }
172
-
173
- private:
174
- void allocate(Index rows, Index cols, unsigned int computationOptions);
225
+
226
+ private:
227
+ template <typename Derived>
228
+ BDCSVD& compute_impl(const MatrixBase<Derived>& matrix, unsigned int computationOptions);
175
229
  void divide(Index firstCol, Index lastCol, Index firstRowW, Index firstColW, Index shift);
176
230
  void computeSVDofM(Index firstCol, Index n, MatrixXr& U, VectorType& singVals, MatrixXr& V);
177
- void computeSingVals(const ArrayRef& col0, const ArrayRef& diag, const IndicesRef& perm, VectorType& singVals, ArrayRef shifts, ArrayRef mus);
178
- void perturbCol0(const ArrayRef& col0, const ArrayRef& diag, const IndicesRef& perm, const VectorType& singVals, const ArrayRef& shifts, const ArrayRef& mus, ArrayRef zhat);
179
- void computeSingVecs(const ArrayRef& zhat, const ArrayRef& diag, const IndicesRef& perm, const VectorType& singVals, const ArrayRef& shifts, const ArrayRef& mus, MatrixXr& U, MatrixXr& V);
231
+ void computeSingVals(const ArrayRef& col0, const ArrayRef& diag, const IndicesRef& perm, VectorType& singVals,
232
+ ArrayRef shifts, ArrayRef mus);
233
+ void perturbCol0(const ArrayRef& col0, const ArrayRef& diag, const IndicesRef& perm, const VectorType& singVals,
234
+ const ArrayRef& shifts, const ArrayRef& mus, ArrayRef zhat);
235
+ void computeSingVecs(const ArrayRef& zhat, const ArrayRef& diag, const IndicesRef& perm, const VectorType& singVals,
236
+ const ArrayRef& shifts, const ArrayRef& mus, MatrixXr& U, MatrixXr& V);
180
237
  void deflation43(Index firstCol, Index shift, Index i, Index size);
181
- void deflation44(Index firstColu , Index firstColm, Index firstRowW, Index firstColW, Index i, Index j, Index size);
238
+ void deflation44(Index firstColu, Index firstColm, Index firstRowW, Index firstColW, Index i, Index j, Index size);
182
239
  void deflation(Index firstCol, Index lastCol, Index k, Index firstRowW, Index firstColW, Index shift);
183
- template<typename HouseholderU, typename HouseholderV, typename NaiveU, typename NaiveV>
184
- void copyUV(const HouseholderU &householderU, const HouseholderV &householderV, const NaiveU &naiveU, const NaiveV &naivev);
185
- void structured_update(Block<MatrixXr,Dynamic,Dynamic> A, const MatrixXr &B, Index n1);
186
- static RealScalar secularEq(RealScalar x, const ArrayRef& col0, const ArrayRef& diag, const IndicesRef &perm, const ArrayRef& diagShifted, RealScalar shift);
187
-
188
- protected:
240
+ template <typename HouseholderU, typename HouseholderV, typename NaiveU, typename NaiveV>
241
+ void copyUV(const HouseholderU& householderU, const HouseholderV& householderV, const NaiveU& naiveU,
242
+ const NaiveV& naivev);
243
+ void structured_update(Block<MatrixXr, Dynamic, Dynamic> A, const MatrixXr& B, Index n1);
244
+ static RealScalar secularEq(RealScalar x, const ArrayRef& col0, const ArrayRef& diag, const IndicesRef& perm,
245
+ const ArrayRef& diagShifted, RealScalar shift);
246
+ template <typename SVDType>
247
+ void computeBaseCase(SVDType& svd, Index n, Index firstCol, Index firstRowW, Index firstColW, Index shift);
248
+
249
+ protected:
250
+ void allocate(Index rows, Index cols, unsigned int computationOptions);
189
251
  MatrixXr m_naiveU, m_naiveV;
190
252
  MatrixXr m_computed;
191
253
  Index m_nRec;
192
254
  ArrayXr m_workspace;
193
255
  ArrayXi m_workspaceI;
194
256
  int m_algoswap;
195
- bool m_isTranspose, m_compU, m_compV;
196
-
197
- using Base::m_singularValues;
198
- using Base::m_diagSize;
199
- using Base::m_computeFullU;
200
- using Base::m_computeFullV;
257
+ bool m_isTranspose, m_compU, m_compV, m_useQrDecomp;
258
+ JacobiSVD<MatrixType, ComputationOptions> smallSvd;
259
+ HouseholderQR<MatrixX> qrDecomp;
260
+ internal::UpperBidiagonalization<MatrixX> bid;
261
+ MatrixX copyWorkspace;
262
+ MatrixX reducedTriangle;
263
+
264
+ using Base::m_computationOptions;
201
265
  using Base::m_computeThinU;
202
266
  using Base::m_computeThinV;
267
+ using Base::m_info;
268
+ using Base::m_isInitialized;
203
269
  using Base::m_matrixU;
204
270
  using Base::m_matrixV;
205
- using Base::m_isInitialized;
206
271
  using Base::m_nonzeroSingularValues;
272
+ using Base::m_singularValues;
207
273
 
208
- public:
274
+ public:
209
275
  int m_numIters;
210
- }; //end class BDCSVD
211
-
276
+ }; // end class BDCSVD
212
277
 
213
278
  // Method to allocate and initialize matrix and attributes
214
- template<typename MatrixType>
215
- void BDCSVD<MatrixType>::allocate(Index rows, Index cols, unsigned int computationOptions)
216
- {
217
- m_isTranspose = (cols > rows);
279
+ template <typename MatrixType, int Options>
280
+ void BDCSVD<MatrixType, Options>::allocate(Index rows, Index cols, unsigned int computationOptions) {
281
+ if (Base::allocate(rows, cols, computationOptions)) return;
218
282
 
219
- if (Base::allocate(rows, cols, computationOptions))
220
- return;
221
-
222
- m_computed = MatrixXr::Zero(m_diagSize + 1, m_diagSize );
283
+ if (cols < m_algoswap)
284
+ smallSvd.allocate(rows, cols, Options == 0 ? computationOptions : internal::get_computation_options(Options));
285
+
286
+ m_computed = MatrixXr::Zero(diagSize() + 1, diagSize());
223
287
  m_compU = computeV();
224
288
  m_compV = computeU();
225
- if (m_isTranspose)
226
- std::swap(m_compU, m_compV);
227
-
228
- if (m_compU) m_naiveU = MatrixXr::Zero(m_diagSize + 1, m_diagSize + 1 );
229
- else m_naiveU = MatrixXr::Zero(2, m_diagSize + 1 );
230
-
231
- if (m_compV) m_naiveV = MatrixXr::Zero(m_diagSize, m_diagSize);
232
-
233
- m_workspace.resize((m_diagSize+1)*(m_diagSize+1)*3);
234
- m_workspaceI.resize(3*m_diagSize);
235
- }// end allocate
236
-
237
- template<typename MatrixType>
238
- BDCSVD<MatrixType>& BDCSVD<MatrixType>::compute(const MatrixType& matrix, unsigned int computationOptions)
239
- {
289
+ m_isTranspose = (cols > rows);
290
+ if (m_isTranspose) std::swap(m_compU, m_compV);
291
+
292
+ // kMinAspectRatio is the crossover point that determines if we perform R-Bidiagonalization
293
+ // or bidiagonalize the input matrix directly.
294
+ // It is based off of LAPACK's dgesdd routine, which uses 11.0/6.0
295
+ // we use a larger scalar to prevent a regression for relatively square matrices.
296
+ constexpr Index kMinAspectRatio = 4;
297
+ constexpr bool disableQrDecomp = static_cast<int>(QRDecomposition) == static_cast<int>(DisableQRDecomposition);
298
+ m_useQrDecomp = !disableQrDecomp && ((rows / kMinAspectRatio > cols) || (cols / kMinAspectRatio > rows));
299
+ if (m_useQrDecomp) {
300
+ qrDecomp = HouseholderQR<MatrixX>((std::max)(rows, cols), (std::min)(rows, cols));
301
+ reducedTriangle = MatrixX(diagSize(), diagSize());
302
+ }
303
+
304
+ copyWorkspace = MatrixX(m_isTranspose ? cols : rows, m_isTranspose ? rows : cols);
305
+ bid = internal::UpperBidiagonalization<MatrixX>(m_useQrDecomp ? diagSize() : copyWorkspace.rows(),
306
+ m_useQrDecomp ? diagSize() : copyWorkspace.cols());
307
+
308
+ if (m_compU)
309
+ m_naiveU = MatrixXr::Zero(diagSize() + 1, diagSize() + 1);
310
+ else
311
+ m_naiveU = MatrixXr::Zero(2, diagSize() + 1);
312
+
313
+ if (m_compV) m_naiveV = MatrixXr::Zero(diagSize(), diagSize());
314
+
315
+ m_workspace.resize((diagSize() + 1) * (diagSize() + 1) * 3);
316
+ m_workspaceI.resize(3 * diagSize());
317
+ } // end allocate
318
+
319
+ template <typename MatrixType, int Options>
320
+ template <typename Derived>
321
+ BDCSVD<MatrixType, Options>& BDCSVD<MatrixType, Options>::compute_impl(const MatrixBase<Derived>& matrix,
322
+ unsigned int computationOptions) {
323
+ EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived, MatrixType);
324
+ EIGEN_STATIC_ASSERT((std::is_same<typename Derived::Scalar, typename MatrixType::Scalar>::value),
325
+ Input matrix must have the same Scalar type as the BDCSVD object.);
326
+
240
327
  #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
241
- std::cout << "\n\n\n======================================================================================================================\n\n\n";
328
+ std::cout << "\n\n\n================================================================================================="
329
+ "=====================\n\n\n";
242
330
  #endif
243
- allocate(matrix.rows(), matrix.cols(), computationOptions);
244
331
  using std::abs;
245
332
 
333
+ allocate(matrix.rows(), matrix.cols(), computationOptions);
334
+
246
335
  const RealScalar considerZero = (std::numeric_limits<RealScalar>::min)();
247
-
336
+
248
337
  //**** step -1 - If the problem is too small, directly falls back to JacobiSVD and return
249
- if(matrix.cols() < m_algoswap)
250
- {
251
- // FIXME this line involves temporaries
252
- JacobiSVD<MatrixType> jsvd(matrix,computationOptions);
253
- if(computeU()) m_matrixU = jsvd.matrixU();
254
- if(computeV()) m_matrixV = jsvd.matrixV();
255
- m_singularValues = jsvd.singularValues();
256
- m_nonzeroSingularValues = jsvd.nonzeroSingularValues();
338
+ if (matrix.cols() < m_algoswap) {
339
+ smallSvd.compute(matrix);
257
340
  m_isInitialized = true;
341
+ m_info = smallSvd.info();
342
+ if (m_info == Success || m_info == NoConvergence) {
343
+ if (computeU()) m_matrixU = smallSvd.matrixU();
344
+ if (computeV()) m_matrixV = smallSvd.matrixV();
345
+ m_singularValues = smallSvd.singularValues();
346
+ m_nonzeroSingularValues = smallSvd.nonzeroSingularValues();
347
+ }
258
348
  return *this;
259
349
  }
260
-
350
+
261
351
  //**** step 0 - Copy the input matrix and apply scaling to reduce over/under-flows
262
- RealScalar scale = matrix.cwiseAbs().maxCoeff();
263
- if(scale==Literal(0)) scale = Literal(1);
264
- MatrixX copy;
265
- if (m_isTranspose) copy = matrix.adjoint()/scale;
266
- else copy = matrix/scale;
267
-
268
- //**** step 1 - Bidiagonalization
269
- // FIXME this line involves temporaries
270
- internal::UpperBidiagonalization<MatrixX> bid(copy);
352
+ RealScalar scale = matrix.cwiseAbs().template maxCoeff<PropagateNaN>();
353
+ if (!(numext::isfinite)(scale)) {
354
+ m_isInitialized = true;
355
+ m_info = InvalidInput;
356
+ return *this;
357
+ }
358
+
359
+ if (numext::is_exactly_zero(scale)) scale = Literal(1);
360
+
361
+ if (m_isTranspose)
362
+ copyWorkspace = matrix.adjoint() / scale;
363
+ else
364
+ copyWorkspace = matrix / scale;
365
+
366
+ //**** step 1 - Bidiagonalization.
367
+ // If the problem is sufficiently rectangular, we perform R-Bidiagonalization: compute A = Q(R/0)
368
+ // and then bidiagonalize R. Otherwise, if the problem is relatively square, we
369
+ // bidiagonalize the input matrix directly.
370
+ if (m_useQrDecomp) {
371
+ qrDecomp.compute(copyWorkspace);
372
+ reducedTriangle = qrDecomp.matrixQR().topRows(diagSize());
373
+ reducedTriangle.template triangularView<StrictlyLower>().setZero();
374
+ bid.compute(reducedTriangle);
375
+ } else {
376
+ bid.compute(copyWorkspace);
377
+ }
271
378
 
272
379
  //**** step 2 - Divide & Conquer
273
380
  m_naiveU.setZero();
274
381
  m_naiveV.setZero();
275
382
  // FIXME this line involves a temporary matrix
276
- m_computed.topRows(m_diagSize) = bid.bidiagonal().toDenseMatrix().transpose();
383
+ m_computed.topRows(diagSize()) = bid.bidiagonal().toDenseMatrix().transpose();
277
384
  m_computed.template bottomRows<1>().setZero();
278
- divide(0, m_diagSize - 1, 0, 0, 0);
385
+ divide(0, diagSize() - 1, 0, 0, 0);
386
+ if (m_info != Success && m_info != NoConvergence) {
387
+ m_isInitialized = true;
388
+ return *this;
389
+ }
279
390
 
280
391
  //**** step 3 - Copy singular values and vectors
281
- for (int i=0; i<m_diagSize; i++)
282
- {
392
+ for (int i = 0; i < diagSize(); i++) {
283
393
  RealScalar a = abs(m_computed.coeff(i, i));
284
394
  m_singularValues.coeffRef(i) = a * scale;
285
- if (a<considerZero)
286
- {
395
+ if (a < considerZero) {
287
396
  m_nonzeroSingularValues = i;
288
- m_singularValues.tail(m_diagSize - i - 1).setZero();
397
+ m_singularValues.tail(diagSize() - i - 1).setZero();
289
398
  break;
290
- }
291
- else if (i == m_diagSize - 1)
292
- {
399
+ } else if (i == diagSize() - 1) {
293
400
  m_nonzeroSingularValues = i + 1;
294
401
  break;
295
402
  }
296
403
  }
297
404
 
298
- #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
299
- // std::cout << "m_naiveU\n" << m_naiveU << "\n\n";
300
- // std::cout << "m_naiveV\n" << m_naiveV << "\n\n";
301
- #endif
302
- if(m_isTranspose) copyUV(bid.householderV(), bid.householderU(), m_naiveV, m_naiveU);
303
- else copyUV(bid.householderU(), bid.householderV(), m_naiveU, m_naiveV);
405
+ //**** step 4 - Finalize unitaries U and V
406
+ if (m_isTranspose)
407
+ copyUV(bid.householderV(), bid.householderU(), m_naiveV, m_naiveU);
408
+ else
409
+ copyUV(bid.householderU(), bid.householderV(), m_naiveU, m_naiveV);
410
+
411
+ if (m_useQrDecomp) {
412
+ if (m_isTranspose && computeV())
413
+ m_matrixV.applyOnTheLeft(qrDecomp.householderQ());
414
+ else if (!m_isTranspose && computeU())
415
+ m_matrixU.applyOnTheLeft(qrDecomp.householderQ());
416
+ }
304
417
 
305
418
  m_isInitialized = true;
306
419
  return *this;
307
- }// end compute
308
-
420
+ } // end compute
309
421
 
310
- template<typename MatrixType>
311
- template<typename HouseholderU, typename HouseholderV, typename NaiveU, typename NaiveV>
312
- void BDCSVD<MatrixType>::copyUV(const HouseholderU &householderU, const HouseholderV &householderV, const NaiveU &naiveU, const NaiveV &naiveV)
313
- {
422
+ template <typename MatrixType, int Options>
423
+ template <typename HouseholderU, typename HouseholderV, typename NaiveU, typename NaiveV>
424
+ void BDCSVD<MatrixType, Options>::copyUV(const HouseholderU& householderU, const HouseholderV& householderV,
425
+ const NaiveU& naiveU, const NaiveV& naiveV) {
314
426
  // Note exchange of U and V: m_matrixU is set from m_naiveV and vice versa
315
- if (computeU())
316
- {
317
- Index Ucols = m_computeThinU ? m_diagSize : householderU.cols();
318
- m_matrixU = MatrixX::Identity(householderU.cols(), Ucols);
319
- m_matrixU.topLeftCorner(m_diagSize, m_diagSize) = naiveV.template cast<Scalar>().topLeftCorner(m_diagSize, m_diagSize);
320
- householderU.applyThisOnTheLeft(m_matrixU); // FIXME this line involves a temporary buffer
427
+ if (computeU()) {
428
+ Index Ucols = m_computeThinU ? diagSize() : rows();
429
+ m_matrixU = MatrixX::Identity(rows(), Ucols);
430
+ m_matrixU.topLeftCorner(diagSize(), diagSize()) =
431
+ naiveV.template cast<Scalar>().topLeftCorner(diagSize(), diagSize());
432
+ // FIXME the following conditionals involve temporary buffers
433
+ if (m_useQrDecomp)
434
+ m_matrixU.topLeftCorner(householderU.cols(), diagSize()).applyOnTheLeft(householderU);
435
+ else
436
+ m_matrixU.applyOnTheLeft(householderU);
321
437
  }
322
- if (computeV())
323
- {
324
- Index Vcols = m_computeThinV ? m_diagSize : householderV.cols();
325
- m_matrixV = MatrixX::Identity(householderV.cols(), Vcols);
326
- m_matrixV.topLeftCorner(m_diagSize, m_diagSize) = naiveU.template cast<Scalar>().topLeftCorner(m_diagSize, m_diagSize);
327
- householderV.applyThisOnTheLeft(m_matrixV); // FIXME this line involves a temporary buffer
438
+ if (computeV()) {
439
+ Index Vcols = m_computeThinV ? diagSize() : cols();
440
+ m_matrixV = MatrixX::Identity(cols(), Vcols);
441
+ m_matrixV.topLeftCorner(diagSize(), diagSize()) =
442
+ naiveU.template cast<Scalar>().topLeftCorner(diagSize(), diagSize());
443
+ // FIXME the following conditionals involve temporary buffers
444
+ if (m_useQrDecomp)
445
+ m_matrixV.topLeftCorner(householderV.cols(), diagSize()).applyOnTheLeft(householderV);
446
+ else
447
+ m_matrixV.applyOnTheLeft(householderV);
328
448
  }
329
449
  }
330
450
 
331
451
  /** \internal
332
- * Performs A = A * B exploiting the special structure of the matrix A. Splitting A as:
333
- * A = [A1]
334
- * [A2]
335
- * such that A1.rows()==n1, then we assume that at least half of the columns of A1 and A2 are zeros.
336
- * We can thus pack them prior to the the matrix product. However, this is only worth the effort if the matrix is large
337
- * enough.
338
- */
339
- template<typename MatrixType>
340
- void BDCSVD<MatrixType>::structured_update(Block<MatrixXr,Dynamic,Dynamic> A, const MatrixXr &B, Index n1)
341
- {
452
+ * Performs A = A * B exploiting the special structure of the matrix A. Splitting A as:
453
+ * A = [A1]
454
+ * [A2]
455
+ * such that A1.rows()==n1, then we assume that at least half of the columns of A1 and A2 are zeros.
456
+ * We can thus pack them prior to the the matrix product. However, this is only worth the effort if the matrix is large
457
+ * enough.
458
+ */
459
+ template <typename MatrixType, int Options>
460
+ void BDCSVD<MatrixType, Options>::structured_update(Block<MatrixXr, Dynamic, Dynamic> A, const MatrixXr& B, Index n1) {
342
461
  Index n = A.rows();
343
- if(n>100)
344
- {
462
+ if (n > 100) {
345
463
  // If the matrices are large enough, let's exploit the sparse structure of A by
346
464
  // splitting it in half (wrt n1), and packing the non-zero columns.
347
465
  Index n2 = n - n1;
348
- Map<MatrixXr> A1(m_workspace.data() , n1, n);
349
- Map<MatrixXr> A2(m_workspace.data()+ n1*n, n2, n);
350
- Map<MatrixXr> B1(m_workspace.data()+ n*n, n, n);
351
- Map<MatrixXr> B2(m_workspace.data()+2*n*n, n, n);
352
- Index k1=0, k2=0;
353
- for(Index j=0; j<n; ++j)
354
- {
355
- if( (A.col(j).head(n1).array()!=Literal(0)).any() )
356
- {
466
+ Map<MatrixXr> A1(m_workspace.data(), n1, n);
467
+ Map<MatrixXr> A2(m_workspace.data() + n1 * n, n2, n);
468
+ Map<MatrixXr> B1(m_workspace.data() + n * n, n, n);
469
+ Map<MatrixXr> B2(m_workspace.data() + 2 * n * n, n, n);
470
+ Index k1 = 0, k2 = 0;
471
+ for (Index j = 0; j < n; ++j) {
472
+ if ((A.col(j).head(n1).array() != Literal(0)).any()) {
357
473
  A1.col(k1) = A.col(j).head(n1);
358
474
  B1.row(k1) = B.row(j);
359
475
  ++k1;
360
476
  }
361
- if( (A.col(j).tail(n2).array()!=Literal(0)).any() )
362
- {
477
+ if ((A.col(j).tail(n2).array() != Literal(0)).any()) {
363
478
  A2.col(k2) = A.col(j).tail(n2);
364
479
  B2.row(k2) = B.row(j);
365
480
  ++k2;
366
481
  }
367
482
  }
368
-
369
- A.topRows(n1).noalias() = A1.leftCols(k1) * B1.topRows(k1);
483
+
484
+ A.topRows(n1).noalias() = A1.leftCols(k1) * B1.topRows(k1);
370
485
  A.bottomRows(n2).noalias() = A2.leftCols(k2) * B2.topRows(k2);
371
- }
372
- else
373
- {
374
- Map<MatrixXr,Aligned> tmp(m_workspace.data(),n,n);
375
- tmp.noalias() = A*B;
486
+ } else {
487
+ Map<MatrixXr, Aligned> tmp(m_workspace.data(), n, n);
488
+ tmp.noalias() = A * B;
376
489
  A = tmp;
377
490
  }
378
491
  }
379
492
 
380
- // The divide algorithm is done "in place", we are always working on subsets of the same matrix. The divide methods takes as argument the
381
- // place of the submatrix we are currently working on.
493
+ template <typename MatrixType, int Options>
494
+ template <typename SVDType>
495
+ void BDCSVD<MatrixType, Options>::computeBaseCase(SVDType& svd, Index n, Index firstCol, Index firstRowW,
496
+ Index firstColW, Index shift) {
497
+ svd.compute(m_computed.block(firstCol, firstCol, n + 1, n));
498
+ m_info = svd.info();
499
+ if (m_info != Success && m_info != NoConvergence) return;
500
+ if (m_compU)
501
+ m_naiveU.block(firstCol, firstCol, n + 1, n + 1).real() = svd.matrixU();
502
+ else {
503
+ m_naiveU.row(0).segment(firstCol, n + 1).real() = svd.matrixU().row(0);
504
+ m_naiveU.row(1).segment(firstCol, n + 1).real() = svd.matrixU().row(n);
505
+ }
506
+ if (m_compV) m_naiveV.block(firstRowW, firstColW, n, n).real() = svd.matrixV();
507
+ m_computed.block(firstCol + shift, firstCol + shift, n + 1, n).setZero();
508
+ m_computed.diagonal().segment(firstCol + shift, n) = svd.singularValues().head(n);
509
+ }
510
+
511
+ // The divide algorithm is done "in place", we are always working on subsets of the same matrix. The divide methods
512
+ // takes as argument the place of the submatrix we are currently working on.
382
513
 
383
514
  //@param firstCol : The Index of the first column of the submatrix of m_computed and for m_naiveU;
384
- //@param lastCol : The Index of the last column of the submatrix of m_computed and for m_naiveU;
515
+ //@param lastCol : The Index of the last column of the submatrix of m_computed and for m_naiveU;
385
516
  // lastCol + 1 - firstCol is the size of the submatrix.
386
- //@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)
387
- //@param firstRowW : Same as firstRowW with the column.
388
- //@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
389
- // to become the first column (*coeff) and to shift all the other columns to the right. There are more details on the reference paper.
390
- template<typename MatrixType>
391
- void BDCSVD<MatrixType>::divide (Index firstCol, Index lastCol, Index firstRowW, Index firstColW, Index shift)
392
- {
517
+ //@param firstRowW : The Index of the first row of the matrix W that we are to change. (see the reference paper section
518
+ // 1 for more information on W)
519
+ //@param firstColW : Same as firstRowW with the column.
520
+ //@param shift : Each time one takes the left submatrix, one must add 1 to the shift. Why? Because! We actually want the
521
+ // last column of the U submatrix
522
+ // to become the first column (*coeff) and to shift all the other columns to the right. There are more details on the
523
+ // reference paper.
524
+ template <typename MatrixType, int Options>
525
+ void BDCSVD<MatrixType, Options>::divide(Index firstCol, Index lastCol, Index firstRowW, Index firstColW, Index shift) {
393
526
  // requires rows = cols + 1;
527
+ using std::abs;
394
528
  using std::pow;
395
529
  using std::sqrt;
396
- using std::abs;
397
530
  const Index n = lastCol - firstCol + 1;
398
- const Index k = n/2;
531
+ const Index k = n / 2;
399
532
  const RealScalar considerZero = (std::numeric_limits<RealScalar>::min)();
400
533
  RealScalar alphaK;
401
- RealScalar betaK;
402
- RealScalar r0;
534
+ RealScalar betaK;
535
+ RealScalar r0;
403
536
  RealScalar lambda, phi, c0, s0;
404
537
  VectorType l, f;
405
- // We use the other algorithm which is more efficient for small
538
+ // We use the other algorithm which is more efficient for small
406
539
  // matrices.
407
- if (n < m_algoswap)
408
- {
409
- // FIXME this line involves temporaries
410
- JacobiSVD<MatrixXr> b(m_computed.block(firstCol, firstCol, n + 1, n), ComputeFullU | (m_compV ? ComputeFullV : 0));
411
- if (m_compU)
412
- m_naiveU.block(firstCol, firstCol, n + 1, n + 1).real() = b.matrixU();
413
- else
414
- {
415
- m_naiveU.row(0).segment(firstCol, n + 1).real() = b.matrixU().row(0);
416
- m_naiveU.row(1).segment(firstCol, n + 1).real() = b.matrixU().row(n);
540
+ if (n < m_algoswap) {
541
+ // FIXME this block involves temporaries
542
+ if (m_compV) {
543
+ JacobiSVD<MatrixXr, ComputeFullU | ComputeFullV> baseSvd;
544
+ computeBaseCase(baseSvd, n, firstCol, firstRowW, firstColW, shift);
545
+ } else {
546
+ JacobiSVD<MatrixXr, ComputeFullU> baseSvd;
547
+ computeBaseCase(baseSvd, n, firstCol, firstRowW, firstColW, shift);
417
548
  }
418
- if (m_compV) m_naiveV.block(firstRowW, firstColW, n, n).real() = b.matrixV();
419
- m_computed.block(firstCol + shift, firstCol + shift, n + 1, n).setZero();
420
- m_computed.diagonal().segment(firstCol + shift, n) = b.singularValues().head(n);
421
549
  return;
422
550
  }
423
551
  // We use the divide and conquer algorithm
424
- alphaK = m_computed(firstCol + k, firstCol + k);
552
+ alphaK = m_computed(firstCol + k, firstCol + k);
425
553
  betaK = m_computed(firstCol + k + 1, firstCol + k);
426
554
  // The divide must be done in that order in order to have good results. Divide change the data inside the submatrices
427
- // and the divide of the right submatrice reads one column of the left submatrice. That's why we need to treat the
428
- // right submatrix before the left one.
555
+ // and the divide of the right submatrice reads one column of the left submatrice. That's why we need to treat the
556
+ // right submatrix before the left one.
429
557
  divide(k + 1 + firstCol, lastCol, k + 1 + firstRowW, k + 1 + firstColW, shift);
558
+ if (m_info != Success && m_info != NoConvergence) return;
430
559
  divide(firstCol, k - 1 + firstCol, firstRowW, firstColW + 1, shift + 1);
560
+ if (m_info != Success && m_info != NoConvergence) return;
431
561
 
432
- if (m_compU)
433
- {
562
+ if (m_compU) {
434
563
  lambda = m_naiveU(firstCol + k, firstCol + k);
435
564
  phi = m_naiveU(firstCol + k + 1, lastCol + 1);
436
- }
437
- else
438
- {
565
+ } else {
439
566
  lambda = m_naiveU(1, firstCol + k);
440
567
  phi = m_naiveU(0, lastCol + 1);
441
568
  }
442
569
  r0 = sqrt((abs(alphaK * lambda) * abs(alphaK * lambda)) + abs(betaK * phi) * abs(betaK * phi));
443
- if (m_compU)
444
- {
570
+ if (m_compU) {
445
571
  l = m_naiveU.row(firstCol + k).segment(firstCol, k);
446
572
  f = m_naiveU.row(firstCol + k + 1).segment(firstCol + k + 1, n - k - 1);
447
- }
448
- else
449
- {
573
+ } else {
450
574
  l = m_naiveU.row(1).segment(firstCol, k);
451
575
  f = m_naiveU.row(0).segment(firstCol + k + 1, n - k - 1);
452
576
  }
453
- if (m_compV) m_naiveV(firstRowW+k, firstColW) = Literal(1);
454
- if (r0<considerZero)
455
- {
577
+ if (m_compV) m_naiveV(firstRowW + k, firstColW) = Literal(1);
578
+ if (r0 < considerZero) {
456
579
  c0 = Literal(1);
457
580
  s0 = Literal(0);
458
- }
459
- else
460
- {
581
+ } else {
461
582
  c0 = alphaK * lambda / r0;
462
583
  s0 = betaK * phi / r0;
463
584
  }
464
-
585
+
465
586
  #ifdef EIGEN_BDCSVD_SANITY_CHECKS
466
- assert(m_naiveU.allFinite());
467
- assert(m_naiveV.allFinite());
468
- assert(m_computed.allFinite());
587
+ eigen_internal_assert(m_naiveU.allFinite());
588
+ eigen_internal_assert(m_naiveV.allFinite());
589
+ eigen_internal_assert(m_computed.allFinite());
469
590
  #endif
470
-
471
- if (m_compU)
472
- {
473
- MatrixXr q1 (m_naiveU.col(firstCol + k).segment(firstCol, k + 1));
591
+
592
+ if (m_compU) {
593
+ MatrixXr q1(m_naiveU.col(firstCol + k).segment(firstCol, k + 1));
474
594
  // we shiftW Q1 to the right
475
- for (Index i = firstCol + k - 1; i >= firstCol; i--)
595
+ for (Index i = firstCol + k - 1; i >= firstCol; i--)
476
596
  m_naiveU.col(i + 1).segment(firstCol, k + 1) = m_naiveU.col(i).segment(firstCol, k + 1);
477
597
  // we shift q1 at the left with a factor c0
478
- m_naiveU.col(firstCol).segment( firstCol, k + 1) = (q1 * c0);
598
+ m_naiveU.col(firstCol).segment(firstCol, k + 1) = (q1 * c0);
479
599
  // last column = q1 * - s0
480
- m_naiveU.col(lastCol + 1).segment(firstCol, k + 1) = (q1 * ( - s0));
600
+ m_naiveU.col(lastCol + 1).segment(firstCol, k + 1) = (q1 * (-s0));
481
601
  // first column = q2 * s0
482
- m_naiveU.col(firstCol).segment(firstCol + k + 1, n - k) = m_naiveU.col(lastCol + 1).segment(firstCol + k + 1, n - k) * s0;
602
+ m_naiveU.col(firstCol).segment(firstCol + k + 1, n - k) =
603
+ m_naiveU.col(lastCol + 1).segment(firstCol + k + 1, n - k) * s0;
483
604
  // q2 *= c0
484
605
  m_naiveU.col(lastCol + 1).segment(firstCol + k + 1, n - k) *= c0;
485
- }
486
- else
487
- {
606
+ } else {
488
607
  RealScalar q1 = m_naiveU(0, firstCol + k);
489
608
  // we shift Q1 to the right
490
- for (Index i = firstCol + k - 1; i >= firstCol; i--)
491
- m_naiveU(0, i + 1) = m_naiveU(0, i);
609
+ for (Index i = firstCol + k - 1; i >= firstCol; i--) m_naiveU(0, i + 1) = m_naiveU(0, i);
492
610
  // we shift q1 at the left with a factor c0
493
611
  m_naiveU(0, firstCol) = (q1 * c0);
494
612
  // last column = q1 * - s0
495
- m_naiveU(0, lastCol + 1) = (q1 * ( - s0));
613
+ m_naiveU(0, lastCol + 1) = (q1 * (-s0));
496
614
  // first column = q2 * s0
497
- m_naiveU(1, firstCol) = m_naiveU(1, lastCol + 1) *s0;
615
+ m_naiveU(1, firstCol) = m_naiveU(1, lastCol + 1) * s0;
498
616
  // q2 *= c0
499
617
  m_naiveU(1, lastCol + 1) *= c0;
500
618
  m_naiveU.row(1).segment(firstCol + 1, k).setZero();
501
619
  m_naiveU.row(0).segment(firstCol + k + 1, n - k - 1).setZero();
502
620
  }
503
-
621
+
504
622
  #ifdef EIGEN_BDCSVD_SANITY_CHECKS
505
- assert(m_naiveU.allFinite());
506
- assert(m_naiveV.allFinite());
507
- assert(m_computed.allFinite());
623
+ eigen_internal_assert(m_naiveU.allFinite());
624
+ eigen_internal_assert(m_naiveV.allFinite());
625
+ eigen_internal_assert(m_computed.allFinite());
508
626
  #endif
509
-
627
+
510
628
  m_computed(firstCol + shift, firstCol + shift) = r0;
511
629
  m_computed.col(firstCol + shift).segment(firstCol + shift + 1, k) = alphaK * l.transpose().real();
512
630
  m_computed.col(firstCol + shift).segment(firstCol + shift + k + 1, n - k - 1) = betaK * f.transpose().real();
513
631
 
514
632
  #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
515
- ArrayXr tmp1 = (m_computed.block(firstCol+shift, firstCol+shift, n, n)).jacobiSvd().singularValues();
633
+ ArrayXr tmp1 = (m_computed.block(firstCol + shift, firstCol + shift, n, n)).jacobiSvd().singularValues();
516
634
  #endif
517
635
  // Second part: try to deflate singular values in combined matrix
518
636
  deflation(firstCol, lastCol, k, firstRowW, firstColW, shift);
519
637
  #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
520
- ArrayXr tmp2 = (m_computed.block(firstCol+shift, firstCol+shift, n, n)).jacobiSvd().singularValues();
638
+ ArrayXr tmp2 = (m_computed.block(firstCol + shift, firstCol + shift, n, n)).jacobiSvd().singularValues();
521
639
  std::cout << "\n\nj1 = " << tmp1.transpose().format(bdcsvdfmt) << "\n";
522
640
  std::cout << "j2 = " << tmp2.transpose().format(bdcsvdfmt) << "\n\n";
523
- std::cout << "err: " << ((tmp1-tmp2).abs()>1e-12*tmp2.abs()).transpose() << "\n";
641
+ std::cout << "err: " << ((tmp1 - tmp2).abs() > 1e-12 * tmp2.abs()).transpose() << "\n";
524
642
  static int count = 0;
525
643
  std::cout << "# " << ++count << "\n\n";
526
- assert((tmp1-tmp2).matrix().norm() < 1e-14*tmp2.matrix().norm());
527
- // assert(count<681);
528
- // assert(((tmp1-tmp2).abs()<1e-13*tmp2.abs()).all());
644
+ eigen_internal_assert((tmp1 - tmp2).matrix().norm() < 1e-14 * tmp2.matrix().norm());
645
+ // eigen_internal_assert(count<681);
646
+ // eigen_internal_assert(((tmp1-tmp2).abs()<1e-13*tmp2.abs()).all());
529
647
  #endif
530
-
648
+
531
649
  // Third part: compute SVD of combined matrix
532
650
  MatrixXr UofSVD, VofSVD;
533
651
  VectorType singVals;
534
652
  computeSVDofM(firstCol + shift, n, UofSVD, singVals, VofSVD);
535
-
653
+
536
654
  #ifdef EIGEN_BDCSVD_SANITY_CHECKS
537
- assert(UofSVD.allFinite());
538
- assert(VofSVD.allFinite());
655
+ eigen_internal_assert(UofSVD.allFinite());
656
+ eigen_internal_assert(VofSVD.allFinite());
539
657
  #endif
540
-
658
+
541
659
  if (m_compU)
542
- structured_update(m_naiveU.block(firstCol, firstCol, n + 1, n + 1), UofSVD, (n+2)/2);
543
- else
544
- {
545
- Map<Matrix<RealScalar,2,Dynamic>,Aligned> tmp(m_workspace.data(),2,n+1);
546
- tmp.noalias() = m_naiveU.middleCols(firstCol, n+1) * UofSVD;
660
+ structured_update(m_naiveU.block(firstCol, firstCol, n + 1, n + 1), UofSVD, (n + 2) / 2);
661
+ else {
662
+ Map<Matrix<RealScalar, 2, Dynamic>, Aligned> tmp(m_workspace.data(), 2, n + 1);
663
+ tmp.noalias() = m_naiveU.middleCols(firstCol, n + 1) * UofSVD;
547
664
  m_naiveU.middleCols(firstCol, n + 1) = tmp;
548
665
  }
549
-
550
- if (m_compV) structured_update(m_naiveV.block(firstRowW, firstColW, n, n), VofSVD, (n+1)/2);
551
-
666
+
667
+ if (m_compV) structured_update(m_naiveV.block(firstRowW, firstColW, n, n), VofSVD, (n + 1) / 2);
668
+
552
669
  #ifdef EIGEN_BDCSVD_SANITY_CHECKS
553
- assert(m_naiveU.allFinite());
554
- assert(m_naiveV.allFinite());
555
- assert(m_computed.allFinite());
670
+ eigen_internal_assert(m_naiveU.allFinite());
671
+ eigen_internal_assert(m_naiveV.allFinite());
672
+ eigen_internal_assert(m_computed.allFinite());
556
673
  #endif
557
-
674
+
558
675
  m_computed.block(firstCol + shift, firstCol + shift, n, n).setZero();
559
676
  m_computed.block(firstCol + shift, firstCol + shift, n, n).diagonal() = singVals;
560
- }// end divide
677
+ } // end divide
561
678
 
562
679
  // Compute SVD of m_computed.block(firstCol, firstCol, n + 1, n); this block only has non-zeros in
563
680
  // the first column and on the diagonal and has undergone deflation, so diagonal is in increasing
@@ -566,658 +683,722 @@ void BDCSVD<MatrixType>::divide (Index firstCol, Index lastCol, Index firstRowW,
566
683
  //
567
684
  // TODO Opportunities for optimization: better root finding algo, better stopping criterion, better
568
685
  // handling of round-off errors, be consistent in ordering
569
- // For instance, to solve the secular equation using FMM, see http://www.stat.uchicago.edu/~lekheng/courses/302/classics/greengard-rokhlin.pdf
570
- template <typename MatrixType>
571
- void BDCSVD<MatrixType>::computeSVDofM(Index firstCol, Index n, MatrixXr& U, VectorType& singVals, MatrixXr& V)
572
- {
686
+ // For instance, to solve the secular equation using FMM, see
687
+ // http://www.stat.uchicago.edu/~lekheng/courses/302/classics/greengard-rokhlin.pdf
688
+ template <typename MatrixType, int Options>
689
+ void BDCSVD<MatrixType, Options>::computeSVDofM(Index firstCol, Index n, MatrixXr& U, VectorType& singVals,
690
+ MatrixXr& V) {
573
691
  const RealScalar considerZero = (std::numeric_limits<RealScalar>::min)();
574
692
  using std::abs;
575
693
  ArrayRef col0 = m_computed.col(firstCol).segment(firstCol, n);
576
- m_workspace.head(n) = m_computed.block(firstCol, firstCol, n, n).diagonal();
694
+ m_workspace.head(n) = m_computed.block(firstCol, firstCol, n, n).diagonal();
577
695
  ArrayRef diag = m_workspace.head(n);
578
696
  diag(0) = Literal(0);
579
697
 
580
698
  // Allocate space for singular values and vectors
581
699
  singVals.resize(n);
582
- U.resize(n+1, n+1);
700
+ U.resize(n + 1, n + 1);
583
701
  if (m_compV) V.resize(n, n);
584
702
 
585
703
  #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
586
- if (col0.hasNaN() || diag.hasNaN())
587
- std::cout << "\n\nHAS NAN\n\n";
704
+ if (col0.hasNaN() || diag.hasNaN()) std::cout << "\n\nHAS NAN\n\n";
588
705
  #endif
589
-
706
+
590
707
  // Many singular values might have been deflated, the zero ones have been moved to the end,
591
708
  // but others are interleaved and we must ignore them at this stage.
592
709
  // To this end, let's compute a permutation skipping them:
593
710
  Index actual_n = n;
594
- while(actual_n>1 && diag(actual_n-1)==Literal(0)) --actual_n;
595
- Index m = 0; // size of the deflated problem
596
- for(Index k=0;k<actual_n;++k)
597
- if(abs(col0(k))>considerZero)
598
- m_workspaceI(m++) = k;
599
- Map<ArrayXi> perm(m_workspaceI.data(),m);
600
-
601
- Map<ArrayXr> shifts(m_workspace.data()+1*n, n);
602
- Map<ArrayXr> mus(m_workspace.data()+2*n, n);
603
- Map<ArrayXr> zhat(m_workspace.data()+3*n, n);
711
+ while (actual_n > 1 && numext::is_exactly_zero(diag(actual_n - 1))) {
712
+ --actual_n;
713
+ eigen_internal_assert(numext::is_exactly_zero(col0(actual_n)));
714
+ }
715
+ Index m = 0; // size of the deflated problem
716
+ for (Index k = 0; k < actual_n; ++k)
717
+ if (abs(col0(k)) > considerZero) m_workspaceI(m++) = k;
718
+ Map<ArrayXi> perm(m_workspaceI.data(), m);
719
+
720
+ Map<ArrayXr> shifts(m_workspace.data() + 1 * n, n);
721
+ Map<ArrayXr> mus(m_workspace.data() + 2 * n, n);
722
+ Map<ArrayXr> zhat(m_workspace.data() + 3 * n, n);
604
723
 
605
724
  #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
606
725
  std::cout << "computeSVDofM using:\n";
607
726
  std::cout << " z: " << col0.transpose() << "\n";
608
727
  std::cout << " d: " << diag.transpose() << "\n";
609
728
  #endif
610
-
729
+
611
730
  // Compute singVals, shifts, and mus
612
731
  computeSingVals(col0, diag, perm, singVals, shifts, mus);
613
-
732
+
614
733
  #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
615
- std::cout << " j: " << (m_computed.block(firstCol, firstCol, n, n)).jacobiSvd().singularValues().transpose().reverse() << "\n\n";
734
+ std::cout << " j: "
735
+ << (m_computed.block(firstCol, firstCol, n, n)).jacobiSvd().singularValues().transpose().reverse()
736
+ << "\n\n";
616
737
  std::cout << " sing-val: " << singVals.transpose() << "\n";
617
738
  std::cout << " mu: " << mus.transpose() << "\n";
618
739
  std::cout << " shift: " << shifts.transpose() << "\n";
619
-
740
+
620
741
  {
621
- Index actual_n = n;
622
- while(actual_n>1 && abs(col0(actual_n-1))<considerZero) --actual_n;
623
742
  std::cout << "\n\n mus: " << mus.head(actual_n).transpose() << "\n\n";
624
- std::cout << " check1 (expect0) : " << ((singVals.array()-(shifts+mus)) / singVals.array()).head(actual_n).transpose() << "\n\n";
625
- std::cout << " check2 (>0) : " << ((singVals.array()-diag) / singVals.array()).head(actual_n).transpose() << "\n\n";
626
- std::cout << " check3 (>0) : " << ((diag.segment(1,actual_n-1)-singVals.head(actual_n-1).array()) / singVals.head(actual_n-1).array()).transpose() << "\n\n\n";
627
- std::cout << " check4 (>0) : " << ((singVals.segment(1,actual_n-1)-singVals.head(actual_n-1))).transpose() << "\n\n\n";
743
+ std::cout << " check1 (expect0) : "
744
+ << ((singVals.array() - (shifts + mus)) / singVals.array()).head(actual_n).transpose() << "\n\n";
745
+ eigen_internal_assert((((singVals.array() - (shifts + mus)) / singVals.array()).head(actual_n) >= 0).all());
746
+ std::cout << " check2 (>0) : " << ((singVals.array() - diag) / singVals.array()).head(actual_n).transpose()
747
+ << "\n\n";
748
+ eigen_internal_assert((((singVals.array() - diag) / singVals.array()).head(actual_n) >= 0).all());
628
749
  }
629
750
  #endif
630
-
751
+
631
752
  #ifdef EIGEN_BDCSVD_SANITY_CHECKS
632
- assert(singVals.allFinite());
633
- assert(mus.allFinite());
634
- assert(shifts.allFinite());
753
+ eigen_internal_assert(singVals.allFinite());
754
+ eigen_internal_assert(mus.allFinite());
755
+ eigen_internal_assert(shifts.allFinite());
635
756
  #endif
636
-
757
+
637
758
  // Compute zhat
638
759
  perturbCol0(col0, diag, perm, singVals, shifts, mus, zhat);
639
- #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
760
+ #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
640
761
  std::cout << " zhat: " << zhat.transpose() << "\n";
641
762
  #endif
642
-
763
+
643
764
  #ifdef EIGEN_BDCSVD_SANITY_CHECKS
644
- assert(zhat.allFinite());
765
+ eigen_internal_assert(zhat.allFinite());
645
766
  #endif
646
-
767
+
647
768
  computeSingVecs(zhat, diag, perm, singVals, shifts, mus, U, V);
648
-
649
- #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
650
- std::cout << "U^T U: " << (U.transpose() * U - MatrixXr(MatrixXr::Identity(U.cols(),U.cols()))).norm() << "\n";
651
- std::cout << "V^T V: " << (V.transpose() * V - MatrixXr(MatrixXr::Identity(V.cols(),V.cols()))).norm() << "\n";
769
+
770
+ #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
771
+ std::cout << "U^T U: " << (U.transpose() * U - MatrixXr(MatrixXr::Identity(U.cols(), U.cols()))).norm() << "\n";
772
+ std::cout << "V^T V: " << (V.transpose() * V - MatrixXr(MatrixXr::Identity(V.cols(), V.cols()))).norm() << "\n";
652
773
  #endif
653
-
774
+
654
775
  #ifdef EIGEN_BDCSVD_SANITY_CHECKS
655
- assert(U.allFinite());
656
- assert(V.allFinite());
657
- assert((U.transpose() * U - MatrixXr(MatrixXr::Identity(U.cols(),U.cols()))).norm() < 1e-14 * n);
658
- assert((V.transpose() * V - MatrixXr(MatrixXr::Identity(V.cols(),V.cols()))).norm() < 1e-14 * n);
659
- assert(m_naiveU.allFinite());
660
- assert(m_naiveV.allFinite());
661
- assert(m_computed.allFinite());
776
+ eigen_internal_assert(m_naiveU.allFinite());
777
+ eigen_internal_assert(m_naiveV.allFinite());
778
+ eigen_internal_assert(m_computed.allFinite());
779
+ eigen_internal_assert(U.allFinite());
780
+ eigen_internal_assert(V.allFinite());
781
+ // eigen_internal_assert((U.transpose() * U - MatrixXr(MatrixXr::Identity(U.cols(),U.cols()))).norm() <
782
+ // 100*NumTraits<RealScalar>::epsilon() * n); eigen_internal_assert((V.transpose() * V -
783
+ // MatrixXr(MatrixXr::Identity(V.cols(),V.cols()))).norm() < 100*NumTraits<RealScalar>::epsilon() * n);
662
784
  #endif
663
-
785
+
664
786
  // Because of deflation, the singular values might not be completely sorted.
665
787
  // Fortunately, reordering them is a O(n) problem
666
- for(Index i=0; i<actual_n-1; ++i)
667
- {
668
- if(singVals(i)>singVals(i+1))
669
- {
788
+ for (Index i = 0; i < actual_n - 1; ++i) {
789
+ if (singVals(i) > singVals(i + 1)) {
670
790
  using std::swap;
671
- swap(singVals(i),singVals(i+1));
672
- U.col(i).swap(U.col(i+1));
673
- if(m_compV) V.col(i).swap(V.col(i+1));
791
+ swap(singVals(i), singVals(i + 1));
792
+ U.col(i).swap(U.col(i + 1));
793
+ if (m_compV) V.col(i).swap(V.col(i + 1));
674
794
  }
675
795
  }
676
-
796
+
797
+ #ifdef EIGEN_BDCSVD_SANITY_CHECKS
798
+ {
799
+ bool singular_values_sorted =
800
+ (((singVals.segment(1, actual_n - 1) - singVals.head(actual_n - 1))).array() >= 0).all();
801
+ if (!singular_values_sorted)
802
+ std::cout << "Singular values are not sorted: " << singVals.segment(1, actual_n).transpose() << "\n";
803
+ eigen_internal_assert(singular_values_sorted);
804
+ }
805
+ #endif
806
+
677
807
  // Reverse order so that singular values in increased order
678
808
  // Because of deflation, the zeros singular-values are already at the end
679
809
  singVals.head(actual_n).reverseInPlace();
680
810
  U.leftCols(actual_n).rowwise().reverseInPlace();
681
811
  if (m_compV) V.leftCols(actual_n).rowwise().reverseInPlace();
682
-
812
+
683
813
  #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
684
- JacobiSVD<MatrixXr> jsvd(m_computed.block(firstCol, firstCol, n, n) );
814
+ JacobiSVD<MatrixXr> jsvd(m_computed.block(firstCol, firstCol, n, n));
685
815
  std::cout << " * j: " << jsvd.singularValues().transpose() << "\n\n";
686
816
  std::cout << " * sing-val: " << singVals.transpose() << "\n";
687
817
  // std::cout << " * err: " << ((jsvd.singularValues()-singVals)>1e-13*singVals.norm()).transpose() << "\n";
688
818
  #endif
689
819
  }
690
820
 
691
- template <typename MatrixType>
692
- typename BDCSVD<MatrixType>::RealScalar BDCSVD<MatrixType>::secularEq(RealScalar mu, const ArrayRef& col0, const ArrayRef& diag, const IndicesRef &perm, const ArrayRef& diagShifted, RealScalar shift)
693
- {
821
+ template <typename MatrixType, int Options>
822
+ typename BDCSVD<MatrixType, Options>::RealScalar BDCSVD<MatrixType, Options>::secularEq(
823
+ RealScalar mu, const ArrayRef& col0, const ArrayRef& diag, const IndicesRef& perm, const ArrayRef& diagShifted,
824
+ RealScalar shift) {
694
825
  Index m = perm.size();
695
826
  RealScalar res = Literal(1);
696
- for(Index i=0; i<m; ++i)
697
- {
827
+ for (Index i = 0; i < m; ++i) {
698
828
  Index j = perm(i);
699
829
  // The following expression could be rewritten to involve only a single division,
700
830
  // but this would make the expression more sensitive to overflow.
701
831
  res += (col0(j) / (diagShifted(j) - mu)) * (col0(j) / (diag(j) + shift + mu));
702
832
  }
703
833
  return res;
704
-
705
834
  }
706
835
 
707
- template <typename MatrixType>
708
- void BDCSVD<MatrixType>::computeSingVals(const ArrayRef& col0, const ArrayRef& diag, const IndicesRef &perm,
709
- VectorType& singVals, ArrayRef shifts, ArrayRef mus)
710
- {
836
+ template <typename MatrixType, int Options>
837
+ void BDCSVD<MatrixType, Options>::computeSingVals(const ArrayRef& col0, const ArrayRef& diag, const IndicesRef& perm,
838
+ VectorType& singVals, ArrayRef shifts, ArrayRef mus) {
711
839
  using std::abs;
712
- using std::swap;
713
840
  using std::sqrt;
841
+ using std::swap;
714
842
 
715
843
  Index n = col0.size();
716
844
  Index actual_n = n;
717
845
  // Note that here actual_n is computed based on col0(i)==0 instead of diag(i)==0 as above
718
846
  // because 1) we have diag(i)==0 => col0(i)==0 and 2) if col0(i)==0, then diag(i) is already a singular value.
719
- while(actual_n>1 && col0(actual_n-1)==Literal(0)) --actual_n;
847
+ while (actual_n > 1 && numext::is_exactly_zero(col0(actual_n - 1))) --actual_n;
720
848
 
721
- for (Index k = 0; k < n; ++k)
722
- {
723
- if (col0(k) == Literal(0) || actual_n==1)
724
- {
849
+ for (Index k = 0; k < n; ++k) {
850
+ if (numext::is_exactly_zero(col0(k)) || actual_n == 1) {
725
851
  // if col0(k) == 0, then entry is deflated, so singular value is on diagonal
726
852
  // if actual_n==1, then the deflated problem is already diagonalized
727
- singVals(k) = k==0 ? col0(0) : diag(k);
853
+ singVals(k) = k == 0 ? col0(0) : diag(k);
728
854
  mus(k) = Literal(0);
729
- shifts(k) = k==0 ? col0(0) : diag(k);
855
+ shifts(k) = k == 0 ? col0(0) : diag(k);
730
856
  continue;
731
- }
857
+ }
732
858
 
733
859
  // otherwise, use secular equation to find singular value
734
860
  RealScalar left = diag(k);
735
- RealScalar right; // was: = (k != actual_n-1) ? diag(k+1) : (diag(actual_n-1) + col0.matrix().norm());
736
- if(k==actual_n-1)
737
- right = (diag(actual_n-1) + col0.matrix().norm());
738
- else
739
- {
861
+ RealScalar right; // was: = (k != actual_n-1) ? diag(k+1) : (diag(actual_n-1) + col0.matrix().norm());
862
+ if (k == actual_n - 1)
863
+ right = (diag(actual_n - 1) + col0.matrix().norm());
864
+ else {
740
865
  // Skip deflated singular values,
741
866
  // recall that at this stage we assume that z[j]!=0 and all entries for which z[j]==0 have been put aside.
742
867
  // This should be equivalent to using perm[]
743
- Index l = k+1;
744
- while(col0(l)==Literal(0)) { ++l; eigen_internal_assert(l<actual_n); }
868
+ Index l = k + 1;
869
+ while (numext::is_exactly_zero(col0(l))) {
870
+ ++l;
871
+ eigen_internal_assert(l < actual_n);
872
+ }
745
873
  right = diag(l);
746
874
  }
747
875
 
748
876
  // first decide whether it's closer to the left end or the right end
749
- RealScalar mid = left + (right-left) / Literal(2);
877
+ RealScalar mid = left + (right - left) / Literal(2);
750
878
  RealScalar fMid = secularEq(mid, col0, diag, perm, diag, Literal(0));
751
879
  #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
752
- std::cout << right-left << "\n";
753
- std::cout << "fMid = " << fMid << " " << secularEq(mid-left, col0, diag, perm, diag-left, left) << " " << secularEq(mid-right, col0, diag, perm, diag-right, right) << "\n";
754
- std::cout << " = " << secularEq(0.1*(left+right), col0, diag, perm, diag, 0)
755
- << " " << secularEq(0.2*(left+right), col0, diag, perm, diag, 0)
756
- << " " << secularEq(0.3*(left+right), col0, diag, perm, diag, 0)
757
- << " " << secularEq(0.4*(left+right), col0, diag, perm, diag, 0)
758
- << " " << secularEq(0.49*(left+right), col0, diag, perm, diag, 0)
759
- << " " << secularEq(0.5*(left+right), col0, diag, perm, diag, 0)
760
- << " " << secularEq(0.51*(left+right), col0, diag, perm, diag, 0)
761
- << " " << secularEq(0.6*(left+right), col0, diag, perm, diag, 0)
762
- << " " << secularEq(0.7*(left+right), col0, diag, perm, diag, 0)
763
- << " " << secularEq(0.8*(left+right), col0, diag, perm, diag, 0)
764
- << " " << secularEq(0.9*(left+right), col0, diag, perm, diag, 0) << "\n";
880
+ std::cout << "right-left = " << right - left << "\n";
881
+ // std::cout << "fMid = " << fMid << " " << secularEq(mid-left, col0, diag, perm, ArrayXr(diag-left), left)
882
+ // << " " << secularEq(mid-right, col0, diag, perm, ArrayXr(diag-right), right) <<
883
+ // "\n";
884
+ std::cout << " = " << secularEq(left + RealScalar(0.000001) * (right - left), col0, diag, perm, diag, 0) << " "
885
+ << secularEq(left + RealScalar(0.1) * (right - left), col0, diag, perm, diag, 0) << " "
886
+ << secularEq(left + RealScalar(0.2) * (right - left), col0, diag, perm, diag, 0) << " "
887
+ << secularEq(left + RealScalar(0.3) * (right - left), col0, diag, perm, diag, 0) << " "
888
+ << secularEq(left + RealScalar(0.4) * (right - left), col0, diag, perm, diag, 0) << " "
889
+ << secularEq(left + RealScalar(0.49) * (right - left), col0, diag, perm, diag, 0) << " "
890
+ << secularEq(left + RealScalar(0.5) * (right - left), col0, diag, perm, diag, 0) << " "
891
+ << secularEq(left + RealScalar(0.51) * (right - left), col0, diag, perm, diag, 0) << " "
892
+ << secularEq(left + RealScalar(0.6) * (right - left), col0, diag, perm, diag, 0) << " "
893
+ << secularEq(left + RealScalar(0.7) * (right - left), col0, diag, perm, diag, 0) << " "
894
+ << secularEq(left + RealScalar(0.8) * (right - left), col0, diag, perm, diag, 0) << " "
895
+ << secularEq(left + RealScalar(0.9) * (right - left), col0, diag, perm, diag, 0) << " "
896
+ << secularEq(left + RealScalar(0.999999) * (right - left), col0, diag, perm, diag, 0) << "\n";
765
897
  #endif
766
- RealScalar shift = (k == actual_n-1 || fMid > Literal(0)) ? left : right;
767
-
898
+ RealScalar shift = (k == actual_n - 1 || fMid > Literal(0)) ? left : right;
899
+
768
900
  // measure everything relative to shift
769
- Map<ArrayXr> diagShifted(m_workspace.data()+4*n, n);
901
+ Map<ArrayXr> diagShifted(m_workspace.data() + 4 * n, n);
770
902
  diagShifted = diag - shift;
771
903
 
772
- if(k!=actual_n-1)
773
- {
904
+ if (k != actual_n - 1) {
774
905
  // check that after the shift, f(mid) is still negative:
775
906
  RealScalar midShifted = (right - left) / RealScalar(2);
776
- if(shift==right)
777
- midShifted = -midShifted;
907
+ // we can test exact equality here, because shift comes from `... ? left : right`
908
+ if (numext::equal_strict(shift, right)) midShifted = -midShifted;
778
909
  RealScalar fMidShifted = secularEq(midShifted, col0, diag, perm, diagShifted, shift);
779
- if(fMidShifted>0)
780
- {
910
+ if (fMidShifted > 0) {
781
911
  // fMid was erroneous, fix it:
782
- shift = fMidShifted > Literal(0) ? left : right;
912
+ shift = fMidShifted > Literal(0) ? left : right;
783
913
  diagShifted = diag - shift;
784
914
  }
785
915
  }
786
-
916
+
787
917
  // initial guess
788
918
  RealScalar muPrev, muCur;
789
- if (shift == left)
790
- {
919
+ // we can test exact equality here, because shift comes from `... ? left : right`
920
+ if (numext::equal_strict(shift, left)) {
791
921
  muPrev = (right - left) * RealScalar(0.1);
792
- if (k == actual_n-1) muCur = right - left;
793
- else muCur = (right - left) * RealScalar(0.5);
794
- }
795
- else
796
- {
922
+ if (k == actual_n - 1)
923
+ muCur = right - left;
924
+ else
925
+ muCur = (right - left) * RealScalar(0.5);
926
+ } else {
797
927
  muPrev = -(right - left) * RealScalar(0.1);
798
928
  muCur = -(right - left) * RealScalar(0.5);
799
929
  }
800
930
 
801
931
  RealScalar fPrev = secularEq(muPrev, col0, diag, perm, diagShifted, shift);
802
932
  RealScalar fCur = secularEq(muCur, col0, diag, perm, diagShifted, shift);
803
- if (abs(fPrev) < abs(fCur))
804
- {
933
+ if (abs(fPrev) < abs(fCur)) {
805
934
  swap(fPrev, fCur);
806
935
  swap(muPrev, muCur);
807
936
  }
808
937
 
809
938
  // rational interpolation: fit a function of the form a / mu + b through the two previous
810
939
  // iterates and use its zero to compute the next iterate
811
- bool useBisection = fPrev*fCur>Literal(0);
812
- while (fCur!=Literal(0) && abs(muCur - muPrev) > Literal(8) * NumTraits<RealScalar>::epsilon() * numext::maxi<RealScalar>(abs(muCur), abs(muPrev)) && abs(fCur - fPrev)>NumTraits<RealScalar>::epsilon() && !useBisection)
813
- {
940
+ bool useBisection = fPrev * fCur > Literal(0);
941
+ while (!numext::is_exactly_zero(fCur) &&
942
+ abs(muCur - muPrev) >
943
+ Literal(8) * NumTraits<RealScalar>::epsilon() * numext::maxi<RealScalar>(abs(muCur), abs(muPrev)) &&
944
+ abs(fCur - fPrev) > NumTraits<RealScalar>::epsilon() && !useBisection) {
814
945
  ++m_numIters;
815
946
 
816
947
  // Find a and b such that the function f(mu) = a / mu + b matches the current and previous samples.
817
- RealScalar a = (fCur - fPrev) / (Literal(1)/muCur - Literal(1)/muPrev);
948
+ RealScalar a = (fCur - fPrev) / (Literal(1) / muCur - Literal(1) / muPrev);
818
949
  RealScalar b = fCur - a / muCur;
819
950
  // And find mu such that f(mu)==0:
820
- RealScalar muZero = -a/b;
951
+ RealScalar muZero = -a / b;
821
952
  RealScalar fZero = secularEq(muZero, col0, diag, perm, diagShifted, shift);
822
-
953
+
954
+ #ifdef EIGEN_BDCSVD_SANITY_CHECKS
955
+ eigen_internal_assert((numext::isfinite)(fZero));
956
+ #endif
957
+
823
958
  muPrev = muCur;
824
959
  fPrev = fCur;
825
960
  muCur = muZero;
826
961
  fCur = fZero;
827
-
828
-
829
- if (shift == left && (muCur < Literal(0) || muCur > right - left)) useBisection = true;
830
- if (shift == right && (muCur < -(right - left) || muCur > Literal(0))) useBisection = true;
831
- if (abs(fCur)>abs(fPrev)) useBisection = true;
962
+
963
+ // we can test exact equality here, because shift comes from `... ? left : right`
964
+ if (numext::equal_strict(shift, left) && (muCur < Literal(0) || muCur > right - left)) useBisection = true;
965
+ if (numext::equal_strict(shift, right) && (muCur < -(right - left) || muCur > Literal(0))) useBisection = true;
966
+ if (abs(fCur) > abs(fPrev)) useBisection = true;
832
967
  }
833
968
 
834
969
  // fall back on bisection method if rational interpolation did not work
835
- if (useBisection)
836
- {
837
- #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
970
+ if (useBisection) {
971
+ #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
838
972
  std::cout << "useBisection for k = " << k << ", actual_n = " << actual_n << "\n";
839
973
  #endif
840
974
  RealScalar leftShifted, rightShifted;
841
- if (shift == left)
842
- {
975
+ // we can test exact equality here, because shift comes from `... ? left : right`
976
+ if (numext::equal_strict(shift, left)) {
843
977
  // to avoid overflow, we must have mu > max(real_min, |z(k)|/sqrt(real_max)),
844
978
  // the factor 2 is to be more conservative
845
- leftShifted = numext::maxi<RealScalar>( (std::numeric_limits<RealScalar>::min)(), Literal(2) * abs(col0(k)) / sqrt((std::numeric_limits<RealScalar>::max)()) );
979
+ leftShifted =
980
+ numext::maxi<RealScalar>((std::numeric_limits<RealScalar>::min)(),
981
+ Literal(2) * abs(col0(k)) / sqrt((std::numeric_limits<RealScalar>::max)()));
846
982
 
847
983
  // check that we did it right:
848
- eigen_internal_assert( (numext::isfinite)( (col0(k)/leftShifted)*(col0(k)/(diag(k)+shift+leftShifted)) ) );
984
+ eigen_internal_assert(
985
+ (numext::isfinite)((col0(k) / leftShifted) * (col0(k) / (diag(k) + shift + leftShifted))));
849
986
  // I don't understand why the case k==0 would be special there:
850
987
  // if (k == 0) rightShifted = right - left; else
851
- rightShifted = (k==actual_n-1) ? right : ((right - left) * RealScalar(0.51)); // theoretically we can take 0.5, but let's be safe
852
- }
853
- else
854
- {
988
+ rightShifted = (k == actual_n - 1)
989
+ ? right
990
+ : ((right - left) * RealScalar(0.51)); // theoretically we can take 0.5, but let's be safe
991
+ } else {
855
992
  leftShifted = -(right - left) * RealScalar(0.51);
856
- if(k+1<n)
857
- rightShifted = -numext::maxi<RealScalar>( (std::numeric_limits<RealScalar>::min)(), abs(col0(k+1)) / sqrt((std::numeric_limits<RealScalar>::max)()) );
993
+ if (k + 1 < n)
994
+ rightShifted = -numext::maxi<RealScalar>((std::numeric_limits<RealScalar>::min)(),
995
+ abs(col0(k + 1)) / sqrt((std::numeric_limits<RealScalar>::max)()));
858
996
  else
859
997
  rightShifted = -(std::numeric_limits<RealScalar>::min)();
860
998
  }
861
-
999
+
862
1000
  RealScalar fLeft = secularEq(leftShifted, col0, diag, perm, diagShifted, shift);
863
- eigen_internal_assert(fLeft<Literal(0));
1001
+ eigen_internal_assert(fLeft < Literal(0));
864
1002
 
865
- #if defined EIGEN_INTERNAL_DEBUGGING || defined EIGEN_BDCSVD_DEBUG_VERBOSE
1003
+ #if defined EIGEN_BDCSVD_DEBUG_VERBOSE || defined EIGEN_BDCSVD_SANITY_CHECKS || defined EIGEN_INTERNAL_DEBUGGING
866
1004
  RealScalar fRight = secularEq(rightShifted, col0, diag, perm, diagShifted, shift);
867
1005
  #endif
868
1006
 
1007
+ #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1008
+ if (!(numext::isfinite)(fLeft))
1009
+ std::cout << "f(" << leftShifted << ") =" << fLeft << " ; " << left << " " << shift << " " << right << "\n";
1010
+ eigen_internal_assert((numext::isfinite)(fLeft));
869
1011
 
870
- #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
871
- if(!(fLeft * fRight<0))
872
- {
873
- std::cout << "fLeft: " << leftShifted << " - " << diagShifted.head(10).transpose() << "\n ; " << bool(left==shift) << " " << (left-shift) << "\n";
874
- std::cout << k << " : " << fLeft << " * " << fRight << " == " << fLeft * fRight << " ; " << left << " - " << right << " -> " << leftShifted << " " << rightShifted << " shift=" << shift << "\n";
1012
+ if (!(numext::isfinite)(fRight))
1013
+ std::cout << "f(" << rightShifted << ") =" << fRight << " ; " << left << " " << shift << " " << right << "\n";
1014
+ // eigen_internal_assert((numext::isfinite)(fRight));
1015
+ #endif
1016
+
1017
+ #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1018
+ if (!(fLeft * fRight < 0)) {
1019
+ std::cout << "f(leftShifted) using leftShifted=" << leftShifted
1020
+ << " ; diagShifted(1:10):" << diagShifted.head(10).transpose() << "\n ; "
1021
+ << "left==shift=" << bool(left == shift) << " ; left-shift = " << (left - shift) << "\n";
1022
+ std::cout << "k=" << k << ", " << fLeft << " * " << fRight << " == " << fLeft * fRight << " ; "
1023
+ << "[" << left << " .. " << right << "] -> [" << leftShifted << " " << rightShifted
1024
+ << "], shift=" << shift << " , f(right)=" << secularEq(0, col0, diag, perm, diagShifted, shift)
1025
+ << " == " << secularEq(right, col0, diag, perm, diag, 0) << " == " << fRight << "\n";
875
1026
  }
876
1027
  #endif
877
1028
  eigen_internal_assert(fLeft * fRight < Literal(0));
878
1029
 
879
- if(fLeft<Literal(0))
880
- {
881
- while (rightShifted - leftShifted > Literal(2) * NumTraits<RealScalar>::epsilon() * numext::maxi<RealScalar>(abs(leftShifted), abs(rightShifted)))
882
- {
1030
+ if (fLeft < Literal(0)) {
1031
+ while (rightShifted - leftShifted > Literal(2) * NumTraits<RealScalar>::epsilon() *
1032
+ numext::maxi<RealScalar>(abs(leftShifted), abs(rightShifted))) {
883
1033
  RealScalar midShifted = (leftShifted + rightShifted) / Literal(2);
884
1034
  fMid = secularEq(midShifted, col0, diag, perm, diagShifted, shift);
885
1035
  eigen_internal_assert((numext::isfinite)(fMid));
886
1036
 
887
- if (fLeft * fMid < Literal(0))
888
- {
1037
+ if (fLeft * fMid < Literal(0)) {
889
1038
  rightShifted = midShifted;
890
- }
891
- else
892
- {
1039
+ } else {
893
1040
  leftShifted = midShifted;
894
1041
  fLeft = fMid;
895
1042
  }
896
1043
  }
897
1044
  muCur = (leftShifted + rightShifted) / Literal(2);
898
- }
899
- else
900
- {
1045
+ } else {
901
1046
  // We have a problem as shifting on the left or right give either a positive or negative value
902
1047
  // at the middle of [left,right]...
903
- // Instead fo abbording or entering an infinite loop,
1048
+ // Instead of abbording or entering an infinite loop,
904
1049
  // let's just use the middle as the estimated zero-crossing:
905
1050
  muCur = (right - left) * RealScalar(0.5);
906
- if(shift == right)
907
- muCur = -muCur;
1051
+ // we can test exact equality here, because shift comes from `... ? left : right`
1052
+ if (numext::equal_strict(shift, right)) muCur = -muCur;
908
1053
  }
909
1054
  }
910
-
1055
+
911
1056
  singVals[k] = shift + muCur;
912
1057
  shifts[k] = shift;
913
1058
  mus[k] = muCur;
914
1059
 
1060
+ #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1061
+ if (k + 1 < n)
1062
+ std::cout << "found " << singVals[k] << " == " << shift << " + " << muCur << " from " << diag(k) << " .. "
1063
+ << diag(k + 1) << "\n";
1064
+ #endif
1065
+ #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1066
+ eigen_internal_assert(k == 0 || singVals[k] >= singVals[k - 1]);
1067
+ eigen_internal_assert(singVals[k] >= diag(k));
1068
+ #endif
1069
+
915
1070
  // perturb singular value slightly if it equals diagonal entry to avoid division by zero later
916
1071
  // (deflation is supposed to avoid this from happening)
917
1072
  // - this does no seem to be necessary anymore -
918
- // if (singVals[k] == left) singVals[k] *= 1 + NumTraits<RealScalar>::epsilon();
919
- // if (singVals[k] == right) singVals[k] *= 1 - NumTraits<RealScalar>::epsilon();
1073
+ // if (singVals[k] == left) singVals[k] *= 1 + NumTraits<RealScalar>::epsilon();
1074
+ // if (singVals[k] == right) singVals[k] *= 1 - NumTraits<RealScalar>::epsilon();
920
1075
  }
921
1076
  }
922
1077
 
923
-
924
1078
  // zhat is perturbation of col0 for which singular vectors can be computed stably (see Section 3.1)
925
- template <typename MatrixType>
926
- void BDCSVD<MatrixType>::perturbCol0
927
- (const ArrayRef& col0, const ArrayRef& diag, const IndicesRef &perm, const VectorType& singVals,
928
- const ArrayRef& shifts, const ArrayRef& mus, ArrayRef zhat)
929
- {
1079
+ template <typename MatrixType, int Options>
1080
+ void BDCSVD<MatrixType, Options>::perturbCol0(const ArrayRef& col0, const ArrayRef& diag, const IndicesRef& perm,
1081
+ const VectorType& singVals, const ArrayRef& shifts, const ArrayRef& mus,
1082
+ ArrayRef zhat) {
930
1083
  using std::sqrt;
931
1084
  Index n = col0.size();
932
1085
  Index m = perm.size();
933
- if(m==0)
934
- {
1086
+ if (m == 0) {
935
1087
  zhat.setZero();
936
1088
  return;
937
1089
  }
938
- Index last = perm(m-1);
1090
+ Index lastIdx = perm(m - 1);
939
1091
  // The offset permits to skip deflated entries while computing zhat
940
- for (Index k = 0; k < n; ++k)
941
- {
942
- if (col0(k) == Literal(0)) // deflated
1092
+ for (Index k = 0; k < n; ++k) {
1093
+ if (numext::is_exactly_zero(col0(k))) // deflated
943
1094
  zhat(k) = Literal(0);
944
- else
945
- {
1095
+ else {
946
1096
  // see equation (3.6)
947
1097
  RealScalar dk = diag(k);
948
- RealScalar prod = (singVals(last) + dk) * (mus(last) + (shifts(last) - dk));
1098
+ RealScalar prod = (singVals(lastIdx) + dk) * (mus(lastIdx) + (shifts(lastIdx) - dk));
1099
+ #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1100
+ if (prod < 0) {
1101
+ std::cout << "k = " << k << " ; z(k)=" << col0(k) << ", diag(k)=" << dk << "\n";
1102
+ std::cout << "prod = "
1103
+ << "(" << singVals(lastIdx) << " + " << dk << ") * (" << mus(lastIdx) << " + (" << shifts(lastIdx)
1104
+ << " - " << dk << "))"
1105
+ << "\n";
1106
+ std::cout << " = " << singVals(lastIdx) + dk << " * " << mus(lastIdx) + (shifts(lastIdx) - dk) << "\n";
1107
+ }
1108
+ eigen_internal_assert(prod >= 0);
1109
+ #endif
949
1110
 
950
- for(Index l = 0; l<m; ++l)
951
- {
1111
+ for (Index l = 0; l < m; ++l) {
952
1112
  Index i = perm(l);
953
- if(i!=k)
954
- {
955
- Index j = i<k ? i : perm(l-1);
956
- prod *= ((singVals(j)+dk) / ((diag(i)+dk))) * ((mus(j)+(shifts(j)-dk)) / ((diag(i)-dk)));
1113
+ if (i != k) {
1114
+ #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1115
+ if (i >= k && (l == 0 || l - 1 >= m)) {
1116
+ std::cout << "Error in perturbCol0\n";
1117
+ std::cout << " " << k << "/" << n << " " << l << "/" << m << " " << i << "/" << n << " ; " << col0(k)
1118
+ << " " << diag(k) << " "
1119
+ << "\n";
1120
+ std::cout << " " << diag(i) << "\n";
1121
+ Index j = (i < k /*|| l==0*/) ? i : perm(l - 1);
1122
+ std::cout << " "
1123
+ << "j=" << j << "\n";
1124
+ }
1125
+ #endif
1126
+ Index j = i < k ? i : l > 0 ? perm(l - 1) : i;
1127
+ #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1128
+ if (!(dk != Literal(0) || diag(i) != Literal(0))) {
1129
+ std::cout << "k=" << k << ", i=" << i << ", l=" << l << ", perm.size()=" << perm.size() << "\n";
1130
+ }
1131
+ eigen_internal_assert(dk != Literal(0) || diag(i) != Literal(0));
1132
+ #endif
1133
+ prod *= ((singVals(j) + dk) / ((diag(i) + dk))) * ((mus(j) + (shifts(j) - dk)) / ((diag(i) - dk)));
1134
+ #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1135
+ eigen_internal_assert(prod >= 0);
1136
+ #endif
957
1137
  #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
958
- if(i!=k && numext::abs(((singVals(j)+dk)*(mus(j)+(shifts(j)-dk)))/((diag(i)+dk)*(diag(i)-dk)) - 1) > 0.9 )
959
- std::cout << " " << ((singVals(j)+dk)*(mus(j)+(shifts(j)-dk)))/((diag(i)+dk)*(diag(i)-dk)) << " == (" << (singVals(j)+dk) << " * " << (mus(j)+(shifts(j)-dk))
960
- << ") / (" << (diag(i)+dk) << " * " << (diag(i)-dk) << ")\n";
1138
+ if (i != k &&
1139
+ numext::abs(((singVals(j) + dk) * (mus(j) + (shifts(j) - dk))) / ((diag(i) + dk) * (diag(i) - dk)) - 1) >
1140
+ 0.9)
1141
+ std::cout << " "
1142
+ << ((singVals(j) + dk) * (mus(j) + (shifts(j) - dk))) / ((diag(i) + dk) * (diag(i) - dk))
1143
+ << " == (" << (singVals(j) + dk) << " * " << (mus(j) + (shifts(j) - dk)) << ") / ("
1144
+ << (diag(i) + dk) << " * " << (diag(i) - dk) << ")\n";
961
1145
  #endif
962
1146
  }
963
1147
  }
964
1148
  #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
965
- std::cout << "zhat(" << k << ") = sqrt( " << prod << ") ; " << (singVals(last) + dk) << " * " << mus(last) + shifts(last) << " - " << dk << "\n";
1149
+ std::cout << "zhat(" << k << ") = sqrt( " << prod << ") ; " << (singVals(lastIdx) + dk) << " * "
1150
+ << mus(lastIdx) + shifts(lastIdx) << " - " << dk << "\n";
966
1151
  #endif
967
1152
  RealScalar tmp = sqrt(prod);
1153
+ #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1154
+ eigen_internal_assert((numext::isfinite)(tmp));
1155
+ #endif
968
1156
  zhat(k) = col0(k) > Literal(0) ? RealScalar(tmp) : RealScalar(-tmp);
969
1157
  }
970
1158
  }
971
1159
  }
972
1160
 
973
1161
  // compute singular vectors
974
- template <typename MatrixType>
975
- void BDCSVD<MatrixType>::computeSingVecs
976
- (const ArrayRef& zhat, const ArrayRef& diag, const IndicesRef &perm, const VectorType& singVals,
977
- const ArrayRef& shifts, const ArrayRef& mus, MatrixXr& U, MatrixXr& V)
978
- {
1162
+ template <typename MatrixType, int Options>
1163
+ void BDCSVD<MatrixType, Options>::computeSingVecs(const ArrayRef& zhat, const ArrayRef& diag, const IndicesRef& perm,
1164
+ const VectorType& singVals, const ArrayRef& shifts,
1165
+ const ArrayRef& mus, MatrixXr& U, MatrixXr& V) {
979
1166
  Index n = zhat.size();
980
1167
  Index m = perm.size();
981
-
982
- for (Index k = 0; k < n; ++k)
983
- {
984
- if (zhat(k) == Literal(0))
985
- {
986
- U.col(k) = VectorType::Unit(n+1, k);
1168
+
1169
+ for (Index k = 0; k < n; ++k) {
1170
+ if (numext::is_exactly_zero(zhat(k))) {
1171
+ U.col(k) = VectorType::Unit(n + 1, k);
987
1172
  if (m_compV) V.col(k) = VectorType::Unit(n, k);
988
- }
989
- else
990
- {
1173
+ } else {
991
1174
  U.col(k).setZero();
992
- for(Index l=0;l<m;++l)
993
- {
1175
+ for (Index l = 0; l < m; ++l) {
994
1176
  Index i = perm(l);
995
- U(i,k) = zhat(i)/(((diag(i) - shifts(k)) - mus(k)) )/( (diag(i) + singVals[k]));
1177
+ U(i, k) = zhat(i) / (((diag(i) - shifts(k)) - mus(k))) / ((diag(i) + singVals[k]));
996
1178
  }
997
- U(n,k) = Literal(0);
1179
+ U(n, k) = Literal(0);
998
1180
  U.col(k).normalize();
999
-
1000
- if (m_compV)
1001
- {
1181
+
1182
+ if (m_compV) {
1002
1183
  V.col(k).setZero();
1003
- for(Index l=1;l<m;++l)
1004
- {
1184
+ for (Index l = 1; l < m; ++l) {
1005
1185
  Index i = perm(l);
1006
- V(i,k) = diag(i) * zhat(i) / (((diag(i) - shifts(k)) - mus(k)) )/( (diag(i) + singVals[k]));
1186
+ V(i, k) = diag(i) * zhat(i) / (((diag(i) - shifts(k)) - mus(k))) / ((diag(i) + singVals[k]));
1007
1187
  }
1008
- V(0,k) = Literal(-1);
1188
+ V(0, k) = Literal(-1);
1009
1189
  V.col(k).normalize();
1010
1190
  }
1011
1191
  }
1012
1192
  }
1013
- U.col(n) = VectorType::Unit(n+1, n);
1193
+ U.col(n) = VectorType::Unit(n + 1, n);
1014
1194
  }
1015
1195
 
1016
-
1017
1196
  // page 12_13
1018
1197
  // i >= 1, di almost null and zi non null.
1019
- // We use a rotation to zero out zi applied to the left of M
1020
- template <typename MatrixType>
1021
- void BDCSVD<MatrixType>::deflation43(Index firstCol, Index shift, Index i, Index size)
1022
- {
1198
+ // We use a rotation to zero out zi applied to the left of M, and set di = 0.
1199
+ template <typename MatrixType, int Options>
1200
+ void BDCSVD<MatrixType, Options>::deflation43(Index firstCol, Index shift, Index i, Index size) {
1023
1201
  using std::abs;
1024
- using std::sqrt;
1025
1202
  using std::pow;
1203
+ using std::sqrt;
1026
1204
  Index start = firstCol + shift;
1027
1205
  RealScalar c = m_computed(start, start);
1028
- RealScalar s = m_computed(start+i, start);
1029
- RealScalar r = numext::hypot(c,s);
1030
- if (r == Literal(0))
1031
- {
1032
- m_computed(start+i, start+i) = Literal(0);
1206
+ RealScalar s = m_computed(start + i, start);
1207
+ RealScalar r = numext::hypot(c, s);
1208
+ if (numext::is_exactly_zero(r)) {
1209
+ m_computed(start + i, start + i) = Literal(0);
1033
1210
  return;
1034
1211
  }
1035
- m_computed(start,start) = r;
1036
- m_computed(start+i, start) = Literal(0);
1037
- m_computed(start+i, start+i) = Literal(0);
1038
-
1039
- JacobiRotation<RealScalar> J(c/r,-s/r);
1040
- if (m_compU) m_naiveU.middleRows(firstCol, size+1).applyOnTheRight(firstCol, firstCol+i, J);
1041
- else m_naiveU.applyOnTheRight(firstCol, firstCol+i, J);
1042
- }// end deflation 43
1212
+ m_computed(start, start) = r;
1213
+ m_computed(start + i, start) = Literal(0);
1214
+ m_computed(start + i, start + i) = Literal(0);
1043
1215
 
1216
+ JacobiRotation<RealScalar> J(c / r, -s / r);
1217
+ if (m_compU)
1218
+ m_naiveU.middleRows(firstCol, size + 1).applyOnTheRight(firstCol, firstCol + i, J);
1219
+ else
1220
+ m_naiveU.applyOnTheRight(firstCol, firstCol + i, J);
1221
+ } // end deflation 43
1044
1222
 
1045
1223
  // page 13
1046
- // i,j >= 1, i!=j and |di - dj| < epsilon * norm2(M)
1047
- // We apply two rotations to have zj = 0;
1048
- // TODO deflation44 is still broken and not properly tested
1049
- template <typename MatrixType>
1050
- void BDCSVD<MatrixType>::deflation44(Index firstColu , Index firstColm, Index firstRowW, Index firstColW, Index i, Index j, Index size)
1051
- {
1224
+ // i,j >= 1, i > j, and |di - dj| < epsilon * norm2(M)
1225
+ // We apply two rotations to have zi = 0, and dj = di.
1226
+ template <typename MatrixType, int Options>
1227
+ void BDCSVD<MatrixType, Options>::deflation44(Index firstColu, Index firstColm, Index firstRowW, Index firstColW,
1228
+ Index i, Index j, Index size) {
1052
1229
  using std::abs;
1053
- using std::sqrt;
1054
1230
  using std::conj;
1055
1231
  using std::pow;
1056
- RealScalar c = m_computed(firstColm+i, firstColm);
1057
- RealScalar s = m_computed(firstColm+j, firstColm);
1058
- RealScalar r = sqrt(numext::abs2(c) + numext::abs2(s));
1059
- #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1232
+ using std::sqrt;
1233
+
1234
+ RealScalar s = m_computed(firstColm + i, firstColm);
1235
+ RealScalar c = m_computed(firstColm + j, firstColm);
1236
+ RealScalar r = numext::hypot(c, s);
1237
+ #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1060
1238
  std::cout << "deflation 4.4: " << i << "," << j << " -> " << c << " " << s << " " << r << " ; "
1061
- << m_computed(firstColm + i-1, firstColm) << " "
1062
- << m_computed(firstColm + i, firstColm) << " "
1063
- << m_computed(firstColm + i+1, firstColm) << " "
1064
- << m_computed(firstColm + i+2, firstColm) << "\n";
1065
- std::cout << m_computed(firstColm + i-1, firstColm + i-1) << " "
1066
- << m_computed(firstColm + i, firstColm+i) << " "
1067
- << m_computed(firstColm + i+1, firstColm+i+1) << " "
1068
- << m_computed(firstColm + i+2, firstColm+i+2) << "\n";
1239
+ << m_computed(firstColm + i - 1, firstColm) << " " << m_computed(firstColm + i, firstColm) << " "
1240
+ << m_computed(firstColm + i + 1, firstColm) << " " << m_computed(firstColm + i + 2, firstColm) << "\n";
1241
+ std::cout << m_computed(firstColm + i - 1, firstColm + i - 1) << " " << m_computed(firstColm + i, firstColm + i)
1242
+ << " " << m_computed(firstColm + i + 1, firstColm + i + 1) << " "
1243
+ << m_computed(firstColm + i + 2, firstColm + i + 2) << "\n";
1069
1244
  #endif
1070
- if (r==Literal(0))
1071
- {
1072
- m_computed(firstColm + i, firstColm + i) = m_computed(firstColm + j, firstColm + j);
1245
+ if (numext::is_exactly_zero(r)) {
1246
+ m_computed(firstColm + j, firstColm + j) = m_computed(firstColm + i, firstColm + i);
1073
1247
  return;
1074
1248
  }
1075
- c/=r;
1076
- s/=r;
1077
- m_computed(firstColm + i, firstColm) = r;
1249
+ c /= r;
1250
+ s /= r;
1251
+ m_computed(firstColm + j, firstColm) = r;
1078
1252
  m_computed(firstColm + j, firstColm + j) = m_computed(firstColm + i, firstColm + i);
1079
- m_computed(firstColm + j, firstColm) = Literal(0);
1080
-
1081
- JacobiRotation<RealScalar> J(c,-s);
1082
- if (m_compU) m_naiveU.middleRows(firstColu, size+1).applyOnTheRight(firstColu + i, firstColu + j, J);
1083
- else m_naiveU.applyOnTheRight(firstColu+i, firstColu+j, J);
1084
- if (m_compV) m_naiveV.middleRows(firstRowW, size).applyOnTheRight(firstColW + i, firstColW + j, J);
1085
- }// end deflation 44
1253
+ m_computed(firstColm + i, firstColm) = Literal(0);
1086
1254
 
1255
+ JacobiRotation<RealScalar> J(c, -s);
1256
+ if (m_compU)
1257
+ m_naiveU.middleRows(firstColu, size + 1).applyOnTheRight(firstColu + j, firstColu + i, J);
1258
+ else
1259
+ m_naiveU.applyOnTheRight(firstColu + j, firstColu + i, J);
1260
+ if (m_compV) m_naiveV.middleRows(firstRowW, size).applyOnTheRight(firstColW + j, firstColW + i, J);
1261
+ } // end deflation 44
1087
1262
 
1088
1263
  // acts on block from (firstCol+shift, firstCol+shift) to (lastCol+shift, lastCol+shift) [inclusive]
1089
- template <typename MatrixType>
1090
- void BDCSVD<MatrixType>::deflation(Index firstCol, Index lastCol, Index k, Index firstRowW, Index firstColW, Index shift)
1091
- {
1092
- using std::sqrt;
1264
+ template <typename MatrixType, int Options>
1265
+ void BDCSVD<MatrixType, Options>::deflation(Index firstCol, Index lastCol, Index k, Index firstRowW, Index firstColW,
1266
+ Index shift) {
1093
1267
  using std::abs;
1268
+ using std::sqrt;
1094
1269
  const Index length = lastCol + 1 - firstCol;
1095
-
1096
- Block<MatrixXr,Dynamic,1> col0(m_computed, firstCol+shift, firstCol+shift, length, 1);
1270
+
1271
+ Block<MatrixXr, Dynamic, 1> col0(m_computed, firstCol + shift, firstCol + shift, length, 1);
1097
1272
  Diagonal<MatrixXr> fulldiag(m_computed);
1098
- VectorBlock<Diagonal<MatrixXr>,Dynamic> diag(fulldiag, firstCol+shift, length);
1099
-
1273
+ VectorBlock<Diagonal<MatrixXr>, Dynamic> diag(fulldiag, firstCol + shift, length);
1274
+
1100
1275
  const RealScalar considerZero = (std::numeric_limits<RealScalar>::min)();
1101
- RealScalar maxDiag = diag.tail((std::max)(Index(1),length-1)).cwiseAbs().maxCoeff();
1102
- RealScalar epsilon_strict = numext::maxi<RealScalar>(considerZero,NumTraits<RealScalar>::epsilon() * maxDiag);
1103
- RealScalar epsilon_coarse = Literal(8) * NumTraits<RealScalar>::epsilon() * numext::maxi<RealScalar>(col0.cwiseAbs().maxCoeff(), maxDiag);
1104
-
1276
+ RealScalar maxDiag = diag.tail((std::max)(Index(1), length - 1)).cwiseAbs().maxCoeff();
1277
+ RealScalar epsilon_strict = numext::maxi<RealScalar>(considerZero, NumTraits<RealScalar>::epsilon() * maxDiag);
1278
+ RealScalar epsilon_coarse =
1279
+ Literal(8) * NumTraits<RealScalar>::epsilon() * numext::maxi<RealScalar>(col0.cwiseAbs().maxCoeff(), maxDiag);
1280
+
1105
1281
  #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1106
- assert(m_naiveU.allFinite());
1107
- assert(m_naiveV.allFinite());
1108
- assert(m_computed.allFinite());
1282
+ eigen_internal_assert(m_naiveU.allFinite());
1283
+ eigen_internal_assert(m_naiveV.allFinite());
1284
+ eigen_internal_assert(m_computed.allFinite());
1109
1285
  #endif
1110
1286
 
1111
- #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1112
- std::cout << "\ndeflate:" << diag.head(k+1).transpose() << " | " << diag.segment(k+1,length-k-1).transpose() << "\n";
1287
+ #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1288
+ std::cout << "\ndeflate:" << diag.head(k + 1).transpose() << " | "
1289
+ << diag.segment(k + 1, length - k - 1).transpose() << "\n";
1113
1290
  #endif
1114
-
1115
- //condition 4.1
1116
- if (diag(0) < epsilon_coarse)
1117
- {
1118
- #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1291
+
1292
+ // condition 4.1
1293
+ if (diag(0) < epsilon_coarse) {
1294
+ #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1119
1295
  std::cout << "deflation 4.1, because " << diag(0) << " < " << epsilon_coarse << "\n";
1120
1296
  #endif
1121
1297
  diag(0) = epsilon_coarse;
1122
1298
  }
1123
1299
 
1124
- //condition 4.2
1125
- for (Index i=1;i<length;++i)
1126
- if (abs(col0(i)) < epsilon_strict)
1127
- {
1128
- #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1129
- std::cout << "deflation 4.2, set z(" << i << ") to zero because " << abs(col0(i)) << " < " << epsilon_strict << " (diag(" << i << ")=" << diag(i) << ")\n";
1300
+ // condition 4.2
1301
+ for (Index i = 1; i < length; ++i)
1302
+ if (abs(col0(i)) < epsilon_strict) {
1303
+ #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1304
+ std::cout << "deflation 4.2, set z(" << i << ") to zero because " << abs(col0(i)) << " < " << epsilon_strict
1305
+ << " (diag(" << i << ")=" << diag(i) << ")\n";
1130
1306
  #endif
1131
1307
  col0(i) = Literal(0);
1132
1308
  }
1133
1309
 
1134
- //condition 4.3
1135
- for (Index i=1;i<length; i++)
1136
- if (diag(i) < epsilon_coarse)
1137
- {
1138
- #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1139
- std::cout << "deflation 4.3, cancel z(" << i << ")=" << col0(i) << " because diag(" << i << ")=" << diag(i) << " < " << epsilon_coarse << "\n";
1310
+ // condition 4.3
1311
+ for (Index i = 1; i < length; i++)
1312
+ if (diag(i) < epsilon_coarse) {
1313
+ #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1314
+ std::cout << "deflation 4.3, cancel z(" << i << ")=" << col0(i) << " because diag(" << i << ")=" << diag(i)
1315
+ << " < " << epsilon_coarse << "\n";
1140
1316
  #endif
1141
1317
  deflation43(firstCol, shift, i, length);
1142
1318
  }
1143
1319
 
1144
1320
  #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1145
- assert(m_naiveU.allFinite());
1146
- assert(m_naiveV.allFinite());
1147
- assert(m_computed.allFinite());
1321
+ eigen_internal_assert(m_naiveU.allFinite());
1322
+ eigen_internal_assert(m_naiveV.allFinite());
1323
+ eigen_internal_assert(m_computed.allFinite());
1148
1324
  #endif
1149
1325
  #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1150
1326
  std::cout << "to be sorted: " << diag.transpose() << "\n\n";
1327
+ std::cout << " : " << col0.transpose() << "\n\n";
1151
1328
  #endif
1152
1329
  {
1153
- // Check for total deflation
1154
- // If we have a total deflation, then we have to consider col0(0)==diag(0) as a singular value during sorting
1155
- bool total_deflation = (col0.tail(length-1).array()<considerZero).all();
1156
-
1330
+ // Check for total deflation:
1331
+ // If we have a total deflation, then we have to consider col0(0)==diag(0) as a singular value during sorting.
1332
+ const bool total_deflation = (col0.tail(length - 1).array().abs() < considerZero).all();
1333
+
1157
1334
  // Sort the diagonal entries, since diag(1:k-1) and diag(k:length) are already sorted, let's do a sorted merge.
1158
1335
  // First, compute the respective permutation.
1159
- Index *permutation = m_workspaceI.data();
1336
+ Index* permutation = m_workspaceI.data();
1160
1337
  {
1161
1338
  permutation[0] = 0;
1162
1339
  Index p = 1;
1163
-
1340
+
1164
1341
  // Move deflated diagonal entries at the end.
1165
- for(Index i=1; i<length; ++i)
1166
- if(abs(diag(i))<considerZero)
1167
- permutation[p++] = i;
1168
-
1169
- Index i=1, j=k+1;
1170
- for( ; p < length; ++p)
1171
- {
1172
- if (i > k) permutation[p] = j++;
1173
- else if (j >= length) permutation[p] = i++;
1174
- else if (diag(i) < diag(j)) permutation[p] = j++;
1175
- else permutation[p] = i++;
1342
+ for (Index i = 1; i < length; ++i)
1343
+ if (diag(i) < considerZero) permutation[p++] = i;
1344
+
1345
+ Index i = 1, j = k + 1;
1346
+ for (; p < length; ++p) {
1347
+ if (i > k)
1348
+ permutation[p] = j++;
1349
+ else if (j >= length)
1350
+ permutation[p] = i++;
1351
+ else if (diag(i) < diag(j))
1352
+ permutation[p] = j++;
1353
+ else
1354
+ permutation[p] = i++;
1176
1355
  }
1177
1356
  }
1178
-
1357
+
1179
1358
  // If we have a total deflation, then we have to insert diag(0) at the right place
1180
- if(total_deflation)
1181
- {
1182
- for(Index i=1; i<length; ++i)
1183
- {
1359
+ if (total_deflation) {
1360
+ for (Index i = 1; i < length; ++i) {
1184
1361
  Index pi = permutation[i];
1185
- if(abs(diag(pi))<considerZero || diag(0)<diag(pi))
1186
- permutation[i-1] = permutation[i];
1187
- else
1188
- {
1189
- permutation[i-1] = 0;
1362
+ if (diag(pi) < considerZero || diag(0) < diag(pi))
1363
+ permutation[i - 1] = permutation[i];
1364
+ else {
1365
+ permutation[i - 1] = 0;
1190
1366
  break;
1191
1367
  }
1192
1368
  }
1193
1369
  }
1194
-
1370
+
1195
1371
  // Current index of each col, and current column of each index
1196
- Index *realInd = m_workspaceI.data()+length;
1197
- Index *realCol = m_workspaceI.data()+2*length;
1198
-
1199
- for(int pos = 0; pos< length; pos++)
1200
- {
1372
+ Index* realInd = m_workspaceI.data() + length;
1373
+ Index* realCol = m_workspaceI.data() + 2 * length;
1374
+
1375
+ for (int pos = 0; pos < length; pos++) {
1201
1376
  realCol[pos] = pos;
1202
1377
  realInd[pos] = pos;
1203
1378
  }
1204
-
1205
- for(Index i = total_deflation?0:1; i < length; i++)
1206
- {
1207
- const Index pi = permutation[length - (total_deflation ? i+1 : i)];
1379
+
1380
+ for (Index i = total_deflation ? 0 : 1; i < length; i++) {
1381
+ const Index pi = permutation[length - (total_deflation ? i + 1 : i)];
1208
1382
  const Index J = realCol[pi];
1209
-
1383
+
1210
1384
  using std::swap;
1211
1385
  // swap diagonal and first column entries:
1212
1386
  swap(diag(i), diag(J));
1213
- if(i!=0 && J!=0) swap(col0(i), col0(J));
1387
+ if (i != 0 && J != 0) swap(col0(i), col0(J));
1214
1388
 
1215
1389
  // change columns
1216
- if (m_compU) m_naiveU.col(firstCol+i).segment(firstCol, length + 1).swap(m_naiveU.col(firstCol+J).segment(firstCol, length + 1));
1217
- else m_naiveU.col(firstCol+i).segment(0, 2) .swap(m_naiveU.col(firstCol+J).segment(0, 2));
1218
- if (m_compV) m_naiveV.col(firstColW + i).segment(firstRowW, length).swap(m_naiveV.col(firstColW + J).segment(firstRowW, length));
1390
+ if (m_compU)
1391
+ m_naiveU.col(firstCol + i)
1392
+ .segment(firstCol, length + 1)
1393
+ .swap(m_naiveU.col(firstCol + J).segment(firstCol, length + 1));
1394
+ else
1395
+ m_naiveU.col(firstCol + i).segment(0, 2).swap(m_naiveU.col(firstCol + J).segment(0, 2));
1396
+ if (m_compV)
1397
+ m_naiveV.col(firstColW + i)
1398
+ .segment(firstRowW, length)
1399
+ .swap(m_naiveV.col(firstColW + J).segment(firstRowW, length));
1219
1400
 
1220
- //update real pos
1401
+ // update real pos
1221
1402
  const Index realI = realInd[i];
1222
1403
  realCol[realI] = J;
1223
1404
  realCol[pi] = i;
@@ -1229,49 +1410,61 @@ void BDCSVD<MatrixType>::deflation(Index firstCol, Index lastCol, Index k, Index
1229
1410
  std::cout << "sorted: " << diag.transpose().format(bdcsvdfmt) << "\n";
1230
1411
  std::cout << " : " << col0.transpose() << "\n\n";
1231
1412
  #endif
1232
-
1233
- //condition 4.4
1413
+
1414
+ // condition 4.4
1234
1415
  {
1235
- Index i = length-1;
1236
- while(i>0 && (abs(diag(i))<considerZero || abs(col0(i))<considerZero)) --i;
1237
- for(; i>1;--i)
1238
- if( (diag(i) - diag(i-1)) < NumTraits<RealScalar>::epsilon()*maxDiag )
1239
- {
1416
+ Index i = length - 1;
1417
+ // Find last non-deflated entry.
1418
+ while (i > 0 && (diag(i) < considerZero || abs(col0(i)) < considerZero)) --i;
1419
+
1420
+ for (; i > 1; --i)
1421
+ if ((diag(i) - diag(i - 1)) < epsilon_strict) {
1240
1422
  #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1241
- std::cout << "deflation 4.4 with i = " << i << " because " << (diag(i) - diag(i-1)) << " < " << NumTraits<RealScalar>::epsilon()*diag(i) << "\n";
1423
+ std::cout << "deflation 4.4 with i = " << i << " because " << diag(i) << " - " << diag(i - 1)
1424
+ << " == " << (diag(i) - diag(i - 1)) << " < " << epsilon_strict << "\n";
1242
1425
  #endif
1243
- eigen_internal_assert(abs(diag(i) - diag(i-1))<epsilon_coarse && " diagonal entries are not properly sorted");
1244
- deflation44(firstCol, firstCol + shift, firstRowW, firstColW, i-1, i, length);
1426
+ eigen_internal_assert(abs(diag(i) - diag(i - 1)) < epsilon_coarse &&
1427
+ " diagonal entries are not properly sorted");
1428
+ deflation44(firstCol, firstCol + shift, firstRowW, firstColW, i, i - 1, length);
1245
1429
  }
1246
1430
  }
1247
-
1431
+
1248
1432
  #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1249
- for(Index j=2;j<length;++j)
1250
- assert(diag(j-1)<=diag(j) || abs(diag(j))<considerZero);
1433
+ for (Index j = 2; j < length; ++j) eigen_internal_assert(diag(j - 1) <= diag(j) || abs(diag(j)) < considerZero);
1251
1434
  #endif
1252
-
1435
+
1253
1436
  #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1254
- assert(m_naiveU.allFinite());
1255
- assert(m_naiveV.allFinite());
1256
- assert(m_computed.allFinite());
1437
+ eigen_internal_assert(m_naiveU.allFinite());
1438
+ eigen_internal_assert(m_naiveV.allFinite());
1439
+ eigen_internal_assert(m_computed.allFinite());
1257
1440
  #endif
1258
- }//end deflation
1441
+ } // end deflation
1259
1442
 
1260
- #ifndef __CUDACC__
1261
1443
  /** \svd_module
1262
- *
1263
- * \return the singular value decomposition of \c *this computed by Divide & Conquer algorithm
1264
- *
1265
- * \sa class BDCSVD
1266
- */
1267
- template<typename Derived>
1268
- BDCSVD<typename MatrixBase<Derived>::PlainObject>
1269
- MatrixBase<Derived>::bdcSvd(unsigned int computationOptions) const
1270
- {
1271
- return BDCSVD<PlainObject>(*this, computationOptions);
1444
+ *
1445
+ * \return the singular value decomposition of \c *this computed by Divide & Conquer algorithm
1446
+ *
1447
+ * \sa class BDCSVD
1448
+ */
1449
+ template <typename Derived>
1450
+ template <int Options>
1451
+ BDCSVD<typename MatrixBase<Derived>::PlainObject, Options> MatrixBase<Derived>::bdcSvd() const {
1452
+ return BDCSVD<PlainObject, Options>(*this);
1453
+ }
1454
+
1455
+ /** \svd_module
1456
+ *
1457
+ * \return the singular value decomposition of \c *this computed by Divide & Conquer algorithm
1458
+ *
1459
+ * \sa class BDCSVD
1460
+ */
1461
+ template <typename Derived>
1462
+ template <int Options>
1463
+ BDCSVD<typename MatrixBase<Derived>::PlainObject, Options> MatrixBase<Derived>::bdcSvd(
1464
+ unsigned int computationOptions) const {
1465
+ return BDCSVD<PlainObject, Options>(*this, computationOptions);
1272
1466
  }
1273
- #endif
1274
1467
 
1275
- } // end namespace Eigen
1468
+ } // end namespace Eigen
1276
1469
 
1277
1470
  #endif