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