umappp 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (395) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +25 -0
  3. data/README.md +110 -0
  4. data/ext/umappp/extconf.rb +25 -0
  5. data/ext/umappp/numo.hpp +867 -0
  6. data/ext/umappp/umappp.cpp +225 -0
  7. data/lib/umappp/version.rb +5 -0
  8. data/lib/umappp.rb +41 -0
  9. data/vendor/Eigen/Cholesky +45 -0
  10. data/vendor/Eigen/CholmodSupport +48 -0
  11. data/vendor/Eigen/Core +384 -0
  12. data/vendor/Eigen/Dense +7 -0
  13. data/vendor/Eigen/Eigen +2 -0
  14. data/vendor/Eigen/Eigenvalues +60 -0
  15. data/vendor/Eigen/Geometry +59 -0
  16. data/vendor/Eigen/Householder +29 -0
  17. data/vendor/Eigen/IterativeLinearSolvers +48 -0
  18. data/vendor/Eigen/Jacobi +32 -0
  19. data/vendor/Eigen/KLUSupport +41 -0
  20. data/vendor/Eigen/LU +47 -0
  21. data/vendor/Eigen/MetisSupport +35 -0
  22. data/vendor/Eigen/OrderingMethods +70 -0
  23. data/vendor/Eigen/PaStiXSupport +49 -0
  24. data/vendor/Eigen/PardisoSupport +35 -0
  25. data/vendor/Eigen/QR +50 -0
  26. data/vendor/Eigen/QtAlignedMalloc +39 -0
  27. data/vendor/Eigen/SPQRSupport +34 -0
  28. data/vendor/Eigen/SVD +50 -0
  29. data/vendor/Eigen/Sparse +34 -0
  30. data/vendor/Eigen/SparseCholesky +37 -0
  31. data/vendor/Eigen/SparseCore +69 -0
  32. data/vendor/Eigen/SparseLU +50 -0
  33. data/vendor/Eigen/SparseQR +36 -0
  34. data/vendor/Eigen/StdDeque +27 -0
  35. data/vendor/Eigen/StdList +26 -0
  36. data/vendor/Eigen/StdVector +27 -0
  37. data/vendor/Eigen/SuperLUSupport +64 -0
  38. data/vendor/Eigen/UmfPackSupport +40 -0
  39. data/vendor/Eigen/src/Cholesky/LDLT.h +688 -0
  40. data/vendor/Eigen/src/Cholesky/LLT.h +558 -0
  41. data/vendor/Eigen/src/Cholesky/LLT_LAPACKE.h +99 -0
  42. data/vendor/Eigen/src/CholmodSupport/CholmodSupport.h +682 -0
  43. data/vendor/Eigen/src/Core/ArithmeticSequence.h +413 -0
  44. data/vendor/Eigen/src/Core/Array.h +417 -0
  45. data/vendor/Eigen/src/Core/ArrayBase.h +226 -0
  46. data/vendor/Eigen/src/Core/ArrayWrapper.h +209 -0
  47. data/vendor/Eigen/src/Core/Assign.h +90 -0
  48. data/vendor/Eigen/src/Core/AssignEvaluator.h +1010 -0
  49. data/vendor/Eigen/src/Core/Assign_MKL.h +178 -0
  50. data/vendor/Eigen/src/Core/BandMatrix.h +353 -0
  51. data/vendor/Eigen/src/Core/Block.h +448 -0
  52. data/vendor/Eigen/src/Core/BooleanRedux.h +162 -0
  53. data/vendor/Eigen/src/Core/CommaInitializer.h +164 -0
  54. data/vendor/Eigen/src/Core/ConditionEstimator.h +175 -0
  55. data/vendor/Eigen/src/Core/CoreEvaluators.h +1741 -0
  56. data/vendor/Eigen/src/Core/CoreIterators.h +132 -0
  57. data/vendor/Eigen/src/Core/CwiseBinaryOp.h +183 -0
  58. data/vendor/Eigen/src/Core/CwiseNullaryOp.h +1001 -0
  59. data/vendor/Eigen/src/Core/CwiseTernaryOp.h +197 -0
  60. data/vendor/Eigen/src/Core/CwiseUnaryOp.h +103 -0
  61. data/vendor/Eigen/src/Core/CwiseUnaryView.h +132 -0
  62. data/vendor/Eigen/src/Core/DenseBase.h +701 -0
  63. data/vendor/Eigen/src/Core/DenseCoeffsBase.h +685 -0
  64. data/vendor/Eigen/src/Core/DenseStorage.h +652 -0
  65. data/vendor/Eigen/src/Core/Diagonal.h +258 -0
  66. data/vendor/Eigen/src/Core/DiagonalMatrix.h +391 -0
  67. data/vendor/Eigen/src/Core/DiagonalProduct.h +28 -0
  68. data/vendor/Eigen/src/Core/Dot.h +318 -0
  69. data/vendor/Eigen/src/Core/EigenBase.h +160 -0
  70. data/vendor/Eigen/src/Core/ForceAlignedAccess.h +150 -0
  71. data/vendor/Eigen/src/Core/Fuzzy.h +155 -0
  72. data/vendor/Eigen/src/Core/GeneralProduct.h +465 -0
  73. data/vendor/Eigen/src/Core/GenericPacketMath.h +1040 -0
  74. data/vendor/Eigen/src/Core/GlobalFunctions.h +194 -0
  75. data/vendor/Eigen/src/Core/IO.h +258 -0
  76. data/vendor/Eigen/src/Core/IndexedView.h +237 -0
  77. data/vendor/Eigen/src/Core/Inverse.h +117 -0
  78. data/vendor/Eigen/src/Core/Map.h +171 -0
  79. data/vendor/Eigen/src/Core/MapBase.h +310 -0
  80. data/vendor/Eigen/src/Core/MathFunctions.h +2057 -0
  81. data/vendor/Eigen/src/Core/MathFunctionsImpl.h +200 -0
  82. data/vendor/Eigen/src/Core/Matrix.h +565 -0
  83. data/vendor/Eigen/src/Core/MatrixBase.h +547 -0
  84. data/vendor/Eigen/src/Core/NestByValue.h +85 -0
  85. data/vendor/Eigen/src/Core/NoAlias.h +109 -0
  86. data/vendor/Eigen/src/Core/NumTraits.h +335 -0
  87. data/vendor/Eigen/src/Core/PartialReduxEvaluator.h +232 -0
  88. data/vendor/Eigen/src/Core/PermutationMatrix.h +605 -0
  89. data/vendor/Eigen/src/Core/PlainObjectBase.h +1128 -0
  90. data/vendor/Eigen/src/Core/Product.h +191 -0
  91. data/vendor/Eigen/src/Core/ProductEvaluators.h +1179 -0
  92. data/vendor/Eigen/src/Core/Random.h +218 -0
  93. data/vendor/Eigen/src/Core/Redux.h +515 -0
  94. data/vendor/Eigen/src/Core/Ref.h +381 -0
  95. data/vendor/Eigen/src/Core/Replicate.h +142 -0
  96. data/vendor/Eigen/src/Core/Reshaped.h +454 -0
  97. data/vendor/Eigen/src/Core/ReturnByValue.h +119 -0
  98. data/vendor/Eigen/src/Core/Reverse.h +217 -0
  99. data/vendor/Eigen/src/Core/Select.h +164 -0
  100. data/vendor/Eigen/src/Core/SelfAdjointView.h +365 -0
  101. data/vendor/Eigen/src/Core/SelfCwiseBinaryOp.h +47 -0
  102. data/vendor/Eigen/src/Core/Solve.h +188 -0
  103. data/vendor/Eigen/src/Core/SolveTriangular.h +235 -0
  104. data/vendor/Eigen/src/Core/SolverBase.h +168 -0
  105. data/vendor/Eigen/src/Core/StableNorm.h +251 -0
  106. data/vendor/Eigen/src/Core/StlIterators.h +463 -0
  107. data/vendor/Eigen/src/Core/Stride.h +116 -0
  108. data/vendor/Eigen/src/Core/Swap.h +68 -0
  109. data/vendor/Eigen/src/Core/Transpose.h +464 -0
  110. data/vendor/Eigen/src/Core/Transpositions.h +386 -0
  111. data/vendor/Eigen/src/Core/TriangularMatrix.h +1001 -0
  112. data/vendor/Eigen/src/Core/VectorBlock.h +96 -0
  113. data/vendor/Eigen/src/Core/VectorwiseOp.h +784 -0
  114. data/vendor/Eigen/src/Core/Visitor.h +381 -0
  115. data/vendor/Eigen/src/Core/arch/AVX/Complex.h +372 -0
  116. data/vendor/Eigen/src/Core/arch/AVX/MathFunctions.h +228 -0
  117. data/vendor/Eigen/src/Core/arch/AVX/PacketMath.h +1574 -0
  118. data/vendor/Eigen/src/Core/arch/AVX/TypeCasting.h +115 -0
  119. data/vendor/Eigen/src/Core/arch/AVX512/Complex.h +422 -0
  120. data/vendor/Eigen/src/Core/arch/AVX512/MathFunctions.h +362 -0
  121. data/vendor/Eigen/src/Core/arch/AVX512/PacketMath.h +2303 -0
  122. data/vendor/Eigen/src/Core/arch/AVX512/TypeCasting.h +89 -0
  123. data/vendor/Eigen/src/Core/arch/AltiVec/Complex.h +417 -0
  124. data/vendor/Eigen/src/Core/arch/AltiVec/MathFunctions.h +90 -0
  125. data/vendor/Eigen/src/Core/arch/AltiVec/MatrixProduct.h +2937 -0
  126. data/vendor/Eigen/src/Core/arch/AltiVec/MatrixProductCommon.h +221 -0
  127. data/vendor/Eigen/src/Core/arch/AltiVec/MatrixProductMMA.h +629 -0
  128. data/vendor/Eigen/src/Core/arch/AltiVec/PacketMath.h +2711 -0
  129. data/vendor/Eigen/src/Core/arch/CUDA/Complex.h +258 -0
  130. data/vendor/Eigen/src/Core/arch/Default/BFloat16.h +700 -0
  131. data/vendor/Eigen/src/Core/arch/Default/ConjHelper.h +117 -0
  132. data/vendor/Eigen/src/Core/arch/Default/GenericPacketMathFunctions.h +1649 -0
  133. data/vendor/Eigen/src/Core/arch/Default/GenericPacketMathFunctionsFwd.h +110 -0
  134. data/vendor/Eigen/src/Core/arch/Default/Half.h +942 -0
  135. data/vendor/Eigen/src/Core/arch/Default/Settings.h +49 -0
  136. data/vendor/Eigen/src/Core/arch/Default/TypeCasting.h +120 -0
  137. data/vendor/Eigen/src/Core/arch/GPU/MathFunctions.h +103 -0
  138. data/vendor/Eigen/src/Core/arch/GPU/PacketMath.h +1685 -0
  139. data/vendor/Eigen/src/Core/arch/GPU/TypeCasting.h +80 -0
  140. data/vendor/Eigen/src/Core/arch/HIP/hcc/math_constants.h +23 -0
  141. data/vendor/Eigen/src/Core/arch/MSA/Complex.h +648 -0
  142. data/vendor/Eigen/src/Core/arch/MSA/MathFunctions.h +387 -0
  143. data/vendor/Eigen/src/Core/arch/MSA/PacketMath.h +1233 -0
  144. data/vendor/Eigen/src/Core/arch/NEON/Complex.h +584 -0
  145. data/vendor/Eigen/src/Core/arch/NEON/GeneralBlockPanelKernel.h +183 -0
  146. data/vendor/Eigen/src/Core/arch/NEON/MathFunctions.h +75 -0
  147. data/vendor/Eigen/src/Core/arch/NEON/PacketMath.h +4587 -0
  148. data/vendor/Eigen/src/Core/arch/NEON/TypeCasting.h +1419 -0
  149. data/vendor/Eigen/src/Core/arch/SSE/Complex.h +351 -0
  150. data/vendor/Eigen/src/Core/arch/SSE/MathFunctions.h +199 -0
  151. data/vendor/Eigen/src/Core/arch/SSE/PacketMath.h +1505 -0
  152. data/vendor/Eigen/src/Core/arch/SSE/TypeCasting.h +142 -0
  153. data/vendor/Eigen/src/Core/arch/SVE/MathFunctions.h +44 -0
  154. data/vendor/Eigen/src/Core/arch/SVE/PacketMath.h +752 -0
  155. data/vendor/Eigen/src/Core/arch/SVE/TypeCasting.h +49 -0
  156. data/vendor/Eigen/src/Core/arch/SYCL/InteropHeaders.h +232 -0
  157. data/vendor/Eigen/src/Core/arch/SYCL/MathFunctions.h +301 -0
  158. data/vendor/Eigen/src/Core/arch/SYCL/PacketMath.h +670 -0
  159. data/vendor/Eigen/src/Core/arch/SYCL/SyclMemoryModel.h +694 -0
  160. data/vendor/Eigen/src/Core/arch/SYCL/TypeCasting.h +85 -0
  161. data/vendor/Eigen/src/Core/arch/ZVector/Complex.h +426 -0
  162. data/vendor/Eigen/src/Core/arch/ZVector/MathFunctions.h +233 -0
  163. data/vendor/Eigen/src/Core/arch/ZVector/PacketMath.h +1060 -0
  164. data/vendor/Eigen/src/Core/functors/AssignmentFunctors.h +177 -0
  165. data/vendor/Eigen/src/Core/functors/BinaryFunctors.h +541 -0
  166. data/vendor/Eigen/src/Core/functors/NullaryFunctors.h +189 -0
  167. data/vendor/Eigen/src/Core/functors/StlFunctors.h +166 -0
  168. data/vendor/Eigen/src/Core/functors/TernaryFunctors.h +25 -0
  169. data/vendor/Eigen/src/Core/functors/UnaryFunctors.h +1131 -0
  170. data/vendor/Eigen/src/Core/products/GeneralBlockPanelKernel.h +2645 -0
  171. data/vendor/Eigen/src/Core/products/GeneralMatrixMatrix.h +517 -0
  172. data/vendor/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h +317 -0
  173. data/vendor/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h +145 -0
  174. data/vendor/Eigen/src/Core/products/GeneralMatrixMatrix_BLAS.h +124 -0
  175. data/vendor/Eigen/src/Core/products/GeneralMatrixVector.h +518 -0
  176. data/vendor/Eigen/src/Core/products/GeneralMatrixVector_BLAS.h +136 -0
  177. data/vendor/Eigen/src/Core/products/Parallelizer.h +180 -0
  178. data/vendor/Eigen/src/Core/products/SelfadjointMatrixMatrix.h +544 -0
  179. data/vendor/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h +295 -0
  180. data/vendor/Eigen/src/Core/products/SelfadjointMatrixVector.h +262 -0
  181. data/vendor/Eigen/src/Core/products/SelfadjointMatrixVector_BLAS.h +118 -0
  182. data/vendor/Eigen/src/Core/products/SelfadjointProduct.h +133 -0
  183. data/vendor/Eigen/src/Core/products/SelfadjointRank2Update.h +94 -0
  184. data/vendor/Eigen/src/Core/products/TriangularMatrixMatrix.h +472 -0
  185. data/vendor/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h +317 -0
  186. data/vendor/Eigen/src/Core/products/TriangularMatrixVector.h +350 -0
  187. data/vendor/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h +255 -0
  188. data/vendor/Eigen/src/Core/products/TriangularSolverMatrix.h +337 -0
  189. data/vendor/Eigen/src/Core/products/TriangularSolverMatrix_BLAS.h +167 -0
  190. data/vendor/Eigen/src/Core/products/TriangularSolverVector.h +148 -0
  191. data/vendor/Eigen/src/Core/util/BlasUtil.h +583 -0
  192. data/vendor/Eigen/src/Core/util/ConfigureVectorization.h +512 -0
  193. data/vendor/Eigen/src/Core/util/Constants.h +563 -0
  194. data/vendor/Eigen/src/Core/util/DisableStupidWarnings.h +106 -0
  195. data/vendor/Eigen/src/Core/util/ForwardDeclarations.h +322 -0
  196. data/vendor/Eigen/src/Core/util/IndexedViewHelper.h +186 -0
  197. data/vendor/Eigen/src/Core/util/IntegralConstant.h +272 -0
  198. data/vendor/Eigen/src/Core/util/MKL_support.h +137 -0
  199. data/vendor/Eigen/src/Core/util/Macros.h +1464 -0
  200. data/vendor/Eigen/src/Core/util/Memory.h +1163 -0
  201. data/vendor/Eigen/src/Core/util/Meta.h +812 -0
  202. data/vendor/Eigen/src/Core/util/NonMPL2.h +3 -0
  203. data/vendor/Eigen/src/Core/util/ReenableStupidWarnings.h +31 -0
  204. data/vendor/Eigen/src/Core/util/ReshapedHelper.h +51 -0
  205. data/vendor/Eigen/src/Core/util/StaticAssert.h +221 -0
  206. data/vendor/Eigen/src/Core/util/SymbolicIndex.h +293 -0
  207. data/vendor/Eigen/src/Core/util/XprHelper.h +856 -0
  208. data/vendor/Eigen/src/Eigenvalues/ComplexEigenSolver.h +346 -0
  209. data/vendor/Eigen/src/Eigenvalues/ComplexSchur.h +462 -0
  210. data/vendor/Eigen/src/Eigenvalues/ComplexSchur_LAPACKE.h +91 -0
  211. data/vendor/Eigen/src/Eigenvalues/EigenSolver.h +622 -0
  212. data/vendor/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h +418 -0
  213. data/vendor/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h +226 -0
  214. data/vendor/Eigen/src/Eigenvalues/HessenbergDecomposition.h +374 -0
  215. data/vendor/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h +158 -0
  216. data/vendor/Eigen/src/Eigenvalues/RealQZ.h +657 -0
  217. data/vendor/Eigen/src/Eigenvalues/RealSchur.h +558 -0
  218. data/vendor/Eigen/src/Eigenvalues/RealSchur_LAPACKE.h +77 -0
  219. data/vendor/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h +904 -0
  220. data/vendor/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h +87 -0
  221. data/vendor/Eigen/src/Eigenvalues/Tridiagonalization.h +561 -0
  222. data/vendor/Eigen/src/Geometry/AlignedBox.h +486 -0
  223. data/vendor/Eigen/src/Geometry/AngleAxis.h +247 -0
  224. data/vendor/Eigen/src/Geometry/EulerAngles.h +114 -0
  225. data/vendor/Eigen/src/Geometry/Homogeneous.h +501 -0
  226. data/vendor/Eigen/src/Geometry/Hyperplane.h +282 -0
  227. data/vendor/Eigen/src/Geometry/OrthoMethods.h +235 -0
  228. data/vendor/Eigen/src/Geometry/ParametrizedLine.h +232 -0
  229. data/vendor/Eigen/src/Geometry/Quaternion.h +870 -0
  230. data/vendor/Eigen/src/Geometry/Rotation2D.h +199 -0
  231. data/vendor/Eigen/src/Geometry/RotationBase.h +206 -0
  232. data/vendor/Eigen/src/Geometry/Scaling.h +188 -0
  233. data/vendor/Eigen/src/Geometry/Transform.h +1563 -0
  234. data/vendor/Eigen/src/Geometry/Translation.h +202 -0
  235. data/vendor/Eigen/src/Geometry/Umeyama.h +166 -0
  236. data/vendor/Eigen/src/Geometry/arch/Geometry_SIMD.h +168 -0
  237. data/vendor/Eigen/src/Householder/BlockHouseholder.h +110 -0
  238. data/vendor/Eigen/src/Householder/Householder.h +176 -0
  239. data/vendor/Eigen/src/Householder/HouseholderSequence.h +545 -0
  240. data/vendor/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h +226 -0
  241. data/vendor/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h +212 -0
  242. data/vendor/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h +229 -0
  243. data/vendor/Eigen/src/IterativeLinearSolvers/IncompleteCholesky.h +394 -0
  244. data/vendor/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h +453 -0
  245. data/vendor/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h +444 -0
  246. data/vendor/Eigen/src/IterativeLinearSolvers/LeastSquareConjugateGradient.h +198 -0
  247. data/vendor/Eigen/src/IterativeLinearSolvers/SolveWithGuess.h +117 -0
  248. data/vendor/Eigen/src/Jacobi/Jacobi.h +483 -0
  249. data/vendor/Eigen/src/KLUSupport/KLUSupport.h +358 -0
  250. data/vendor/Eigen/src/LU/Determinant.h +117 -0
  251. data/vendor/Eigen/src/LU/FullPivLU.h +877 -0
  252. data/vendor/Eigen/src/LU/InverseImpl.h +432 -0
  253. data/vendor/Eigen/src/LU/PartialPivLU.h +624 -0
  254. data/vendor/Eigen/src/LU/PartialPivLU_LAPACKE.h +83 -0
  255. data/vendor/Eigen/src/LU/arch/InverseSize4.h +351 -0
  256. data/vendor/Eigen/src/MetisSupport/MetisSupport.h +137 -0
  257. data/vendor/Eigen/src/OrderingMethods/Amd.h +435 -0
  258. data/vendor/Eigen/src/OrderingMethods/Eigen_Colamd.h +1863 -0
  259. data/vendor/Eigen/src/OrderingMethods/Ordering.h +153 -0
  260. data/vendor/Eigen/src/PaStiXSupport/PaStiXSupport.h +678 -0
  261. data/vendor/Eigen/src/PardisoSupport/PardisoSupport.h +545 -0
  262. data/vendor/Eigen/src/QR/ColPivHouseholderQR.h +674 -0
  263. data/vendor/Eigen/src/QR/ColPivHouseholderQR_LAPACKE.h +97 -0
  264. data/vendor/Eigen/src/QR/CompleteOrthogonalDecomposition.h +635 -0
  265. data/vendor/Eigen/src/QR/FullPivHouseholderQR.h +713 -0
  266. data/vendor/Eigen/src/QR/HouseholderQR.h +434 -0
  267. data/vendor/Eigen/src/QR/HouseholderQR_LAPACKE.h +68 -0
  268. data/vendor/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h +335 -0
  269. data/vendor/Eigen/src/SVD/BDCSVD.h +1366 -0
  270. data/vendor/Eigen/src/SVD/JacobiSVD.h +812 -0
  271. data/vendor/Eigen/src/SVD/JacobiSVD_LAPACKE.h +91 -0
  272. data/vendor/Eigen/src/SVD/SVDBase.h +376 -0
  273. data/vendor/Eigen/src/SVD/UpperBidiagonalization.h +414 -0
  274. data/vendor/Eigen/src/SparseCholesky/SimplicialCholesky.h +697 -0
  275. data/vendor/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h +174 -0
  276. data/vendor/Eigen/src/SparseCore/AmbiVector.h +378 -0
  277. data/vendor/Eigen/src/SparseCore/CompressedStorage.h +274 -0
  278. data/vendor/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h +352 -0
  279. data/vendor/Eigen/src/SparseCore/MappedSparseMatrix.h +67 -0
  280. data/vendor/Eigen/src/SparseCore/SparseAssign.h +270 -0
  281. data/vendor/Eigen/src/SparseCore/SparseBlock.h +571 -0
  282. data/vendor/Eigen/src/SparseCore/SparseColEtree.h +206 -0
  283. data/vendor/Eigen/src/SparseCore/SparseCompressedBase.h +370 -0
  284. data/vendor/Eigen/src/SparseCore/SparseCwiseBinaryOp.h +722 -0
  285. data/vendor/Eigen/src/SparseCore/SparseCwiseUnaryOp.h +150 -0
  286. data/vendor/Eigen/src/SparseCore/SparseDenseProduct.h +342 -0
  287. data/vendor/Eigen/src/SparseCore/SparseDiagonalProduct.h +138 -0
  288. data/vendor/Eigen/src/SparseCore/SparseDot.h +98 -0
  289. data/vendor/Eigen/src/SparseCore/SparseFuzzy.h +29 -0
  290. data/vendor/Eigen/src/SparseCore/SparseMap.h +305 -0
  291. data/vendor/Eigen/src/SparseCore/SparseMatrix.h +1518 -0
  292. data/vendor/Eigen/src/SparseCore/SparseMatrixBase.h +398 -0
  293. data/vendor/Eigen/src/SparseCore/SparsePermutation.h +178 -0
  294. data/vendor/Eigen/src/SparseCore/SparseProduct.h +181 -0
  295. data/vendor/Eigen/src/SparseCore/SparseRedux.h +49 -0
  296. data/vendor/Eigen/src/SparseCore/SparseRef.h +397 -0
  297. data/vendor/Eigen/src/SparseCore/SparseSelfAdjointView.h +659 -0
  298. data/vendor/Eigen/src/SparseCore/SparseSolverBase.h +124 -0
  299. data/vendor/Eigen/src/SparseCore/SparseSparseProductWithPruning.h +198 -0
  300. data/vendor/Eigen/src/SparseCore/SparseTranspose.h +92 -0
  301. data/vendor/Eigen/src/SparseCore/SparseTriangularView.h +189 -0
  302. data/vendor/Eigen/src/SparseCore/SparseUtil.h +186 -0
  303. data/vendor/Eigen/src/SparseCore/SparseVector.h +478 -0
  304. data/vendor/Eigen/src/SparseCore/SparseView.h +254 -0
  305. data/vendor/Eigen/src/SparseCore/TriangularSolver.h +315 -0
  306. data/vendor/Eigen/src/SparseLU/SparseLU.h +923 -0
  307. data/vendor/Eigen/src/SparseLU/SparseLUImpl.h +66 -0
  308. data/vendor/Eigen/src/SparseLU/SparseLU_Memory.h +226 -0
  309. data/vendor/Eigen/src/SparseLU/SparseLU_Structs.h +110 -0
  310. data/vendor/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h +375 -0
  311. data/vendor/Eigen/src/SparseLU/SparseLU_Utils.h +80 -0
  312. data/vendor/Eigen/src/SparseLU/SparseLU_column_bmod.h +181 -0
  313. data/vendor/Eigen/src/SparseLU/SparseLU_column_dfs.h +179 -0
  314. data/vendor/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h +107 -0
  315. data/vendor/Eigen/src/SparseLU/SparseLU_gemm_kernel.h +280 -0
  316. data/vendor/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h +126 -0
  317. data/vendor/Eigen/src/SparseLU/SparseLU_kernel_bmod.h +130 -0
  318. data/vendor/Eigen/src/SparseLU/SparseLU_panel_bmod.h +223 -0
  319. data/vendor/Eigen/src/SparseLU/SparseLU_panel_dfs.h +258 -0
  320. data/vendor/Eigen/src/SparseLU/SparseLU_pivotL.h +137 -0
  321. data/vendor/Eigen/src/SparseLU/SparseLU_pruneL.h +136 -0
  322. data/vendor/Eigen/src/SparseLU/SparseLU_relax_snode.h +83 -0
  323. data/vendor/Eigen/src/SparseQR/SparseQR.h +758 -0
  324. data/vendor/Eigen/src/StlSupport/StdDeque.h +116 -0
  325. data/vendor/Eigen/src/StlSupport/StdList.h +106 -0
  326. data/vendor/Eigen/src/StlSupport/StdVector.h +131 -0
  327. data/vendor/Eigen/src/StlSupport/details.h +84 -0
  328. data/vendor/Eigen/src/SuperLUSupport/SuperLUSupport.h +1025 -0
  329. data/vendor/Eigen/src/UmfPackSupport/UmfPackSupport.h +642 -0
  330. data/vendor/Eigen/src/misc/Image.h +82 -0
  331. data/vendor/Eigen/src/misc/Kernel.h +79 -0
  332. data/vendor/Eigen/src/misc/RealSvd2x2.h +55 -0
  333. data/vendor/Eigen/src/misc/blas.h +440 -0
  334. data/vendor/Eigen/src/misc/lapack.h +152 -0
  335. data/vendor/Eigen/src/misc/lapacke.h +16292 -0
  336. data/vendor/Eigen/src/misc/lapacke_mangling.h +17 -0
  337. data/vendor/Eigen/src/plugins/ArrayCwiseBinaryOps.h +358 -0
  338. data/vendor/Eigen/src/plugins/ArrayCwiseUnaryOps.h +696 -0
  339. data/vendor/Eigen/src/plugins/BlockMethods.h +1442 -0
  340. data/vendor/Eigen/src/plugins/CommonCwiseBinaryOps.h +115 -0
  341. data/vendor/Eigen/src/plugins/CommonCwiseUnaryOps.h +177 -0
  342. data/vendor/Eigen/src/plugins/IndexedViewMethods.h +262 -0
  343. data/vendor/Eigen/src/plugins/MatrixCwiseBinaryOps.h +152 -0
  344. data/vendor/Eigen/src/plugins/MatrixCwiseUnaryOps.h +95 -0
  345. data/vendor/Eigen/src/plugins/ReshapedMethods.h +149 -0
  346. data/vendor/aarand/aarand.hpp +114 -0
  347. data/vendor/annoy/annoylib.h +1495 -0
  348. data/vendor/annoy/kissrandom.h +120 -0
  349. data/vendor/annoy/mman.h +242 -0
  350. data/vendor/hnswlib/bruteforce.h +152 -0
  351. data/vendor/hnswlib/hnswalg.h +1192 -0
  352. data/vendor/hnswlib/hnswlib.h +108 -0
  353. data/vendor/hnswlib/space_ip.h +282 -0
  354. data/vendor/hnswlib/space_l2.h +281 -0
  355. data/vendor/hnswlib/visited_list_pool.h +79 -0
  356. data/vendor/irlba/irlba.hpp +575 -0
  357. data/vendor/irlba/lanczos.hpp +212 -0
  358. data/vendor/irlba/parallel.hpp +474 -0
  359. data/vendor/irlba/utils.hpp +224 -0
  360. data/vendor/irlba/wrappers.hpp +228 -0
  361. data/vendor/kmeans/Base.hpp +75 -0
  362. data/vendor/kmeans/Details.hpp +79 -0
  363. data/vendor/kmeans/HartiganWong.hpp +492 -0
  364. data/vendor/kmeans/InitializeKmeansPP.hpp +144 -0
  365. data/vendor/kmeans/InitializeNone.hpp +44 -0
  366. data/vendor/kmeans/InitializePCAPartition.hpp +309 -0
  367. data/vendor/kmeans/InitializeRandom.hpp +91 -0
  368. data/vendor/kmeans/Kmeans.hpp +161 -0
  369. data/vendor/kmeans/Lloyd.hpp +134 -0
  370. data/vendor/kmeans/MiniBatch.hpp +269 -0
  371. data/vendor/kmeans/QuickSearch.hpp +179 -0
  372. data/vendor/kmeans/compute_centroids.hpp +32 -0
  373. data/vendor/kmeans/compute_wcss.hpp +27 -0
  374. data/vendor/kmeans/is_edge_case.hpp +42 -0
  375. data/vendor/kmeans/random.hpp +55 -0
  376. data/vendor/knncolle/Annoy/Annoy.hpp +193 -0
  377. data/vendor/knncolle/BruteForce/BruteForce.hpp +120 -0
  378. data/vendor/knncolle/Hnsw/Hnsw.hpp +225 -0
  379. data/vendor/knncolle/Kmknn/Kmknn.hpp +286 -0
  380. data/vendor/knncolle/VpTree/VpTree.hpp +256 -0
  381. data/vendor/knncolle/knncolle.hpp +34 -0
  382. data/vendor/knncolle/utils/Base.hpp +100 -0
  383. data/vendor/knncolle/utils/NeighborQueue.hpp +94 -0
  384. data/vendor/knncolle/utils/distances.hpp +98 -0
  385. data/vendor/knncolle/utils/find_nearest_neighbors.hpp +112 -0
  386. data/vendor/powerit/PowerIterations.hpp +157 -0
  387. data/vendor/umappp/NeighborList.hpp +37 -0
  388. data/vendor/umappp/Umap.hpp +662 -0
  389. data/vendor/umappp/combine_neighbor_sets.hpp +95 -0
  390. data/vendor/umappp/find_ab.hpp +157 -0
  391. data/vendor/umappp/neighbor_similarities.hpp +136 -0
  392. data/vendor/umappp/optimize_layout.hpp +285 -0
  393. data/vendor/umappp/spectral_init.hpp +181 -0
  394. data/vendor/umappp/umappp.hpp +13 -0
  395. metadata +465 -0
@@ -0,0 +1,1863 @@
1
+ // // This file is part of Eigen, a lightweight C++ template library
2
+ // for linear algebra.
3
+ //
4
+ // Copyright (C) 2012 Desire Nuentsa Wakam <desire.nuentsa_wakam@inria.fr>
5
+ //
6
+ // This Source Code Form is subject to the terms of the Mozilla
7
+ // Public License v. 2.0. If a copy of the MPL was not distributed
8
+ // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
+
10
+ // This file is modified from the colamd/symamd library. The copyright is below
11
+
12
+ // The authors of the code itself are Stefan I. Larimore and Timothy A.
13
+ // Davis (davis@cise.ufl.edu), University of Florida. The algorithm was
14
+ // developed in collaboration with John Gilbert, Xerox PARC, and Esmond
15
+ // Ng, Oak Ridge National Laboratory.
16
+ //
17
+ // Date:
18
+ //
19
+ // September 8, 2003. Version 2.3.
20
+ //
21
+ // Acknowledgements:
22
+ //
23
+ // This work was supported by the National Science Foundation, under
24
+ // grants DMS-9504974 and DMS-9803599.
25
+ //
26
+ // Notice:
27
+ //
28
+ // Copyright (c) 1998-2003 by the University of Florida.
29
+ // All Rights Reserved.
30
+ //
31
+ // THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
32
+ // EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
33
+ //
34
+ // Permission is hereby granted to use, copy, modify, and/or distribute
35
+ // this program, provided that the Copyright, this License, and the
36
+ // Availability of the original version is retained on all copies and made
37
+ // accessible to the end-user of any code or package that includes COLAMD
38
+ // or any modified version of COLAMD.
39
+ //
40
+ // Availability:
41
+ //
42
+ // The colamd/symamd library is available at
43
+ //
44
+ // http://www.suitesparse.com
45
+
46
+
47
+ #ifndef EIGEN_COLAMD_H
48
+ #define EIGEN_COLAMD_H
49
+
50
+ namespace internal {
51
+
52
+ namespace Colamd {
53
+
54
+ /* Ensure that debugging is turned off: */
55
+ #ifndef COLAMD_NDEBUG
56
+ #define COLAMD_NDEBUG
57
+ #endif /* NDEBUG */
58
+
59
+
60
+ /* ========================================================================== */
61
+ /* === Knob and statistics definitions ====================================== */
62
+ /* ========================================================================== */
63
+
64
+ /* size of the knobs [ ] array. Only knobs [0..1] are currently used. */
65
+ const int NKnobs = 20;
66
+
67
+ /* number of output statistics. Only stats [0..6] are currently used. */
68
+ const int NStats = 20;
69
+
70
+ /* Indices into knobs and stats array. */
71
+ enum KnobsStatsIndex {
72
+ /* knobs [0] and stats [0]: dense row knob and output statistic. */
73
+ DenseRow = 0,
74
+
75
+ /* knobs [1] and stats [1]: dense column knob and output statistic. */
76
+ DenseCol = 1,
77
+
78
+ /* stats [2]: memory defragmentation count output statistic */
79
+ DefragCount = 2,
80
+
81
+ /* stats [3]: colamd status: zero OK, > 0 warning or notice, < 0 error */
82
+ Status = 3,
83
+
84
+ /* stats [4..6]: error info, or info on jumbled columns */
85
+ Info1 = 4,
86
+ Info2 = 5,
87
+ Info3 = 6
88
+ };
89
+
90
+ /* error codes returned in stats [3]: */
91
+ enum Status {
92
+ Ok = 0,
93
+ OkButJumbled = 1,
94
+ ErrorANotPresent = -1,
95
+ ErrorPNotPresent = -2,
96
+ ErrorNrowNegative = -3,
97
+ ErrorNcolNegative = -4,
98
+ ErrorNnzNegative = -5,
99
+ ErrorP0Nonzero = -6,
100
+ ErrorATooSmall = -7,
101
+ ErrorColLengthNegative = -8,
102
+ ErrorRowIndexOutOfBounds = -9,
103
+ ErrorOutOfMemory = -10,
104
+ ErrorInternalError = -999
105
+ };
106
+ /* ========================================================================== */
107
+ /* === Definitions ========================================================== */
108
+ /* ========================================================================== */
109
+
110
+ template <typename IndexType>
111
+ IndexType ones_complement(const IndexType r) {
112
+ return (-(r)-1);
113
+ }
114
+
115
+ /* -------------------------------------------------------------------------- */
116
+ const int Empty = -1;
117
+
118
+ /* Row and column status */
119
+ enum RowColumnStatus {
120
+ Alive = 0,
121
+ Dead = -1
122
+ };
123
+
124
+ /* Column status */
125
+ enum ColumnStatus {
126
+ DeadPrincipal = -1,
127
+ DeadNonPrincipal = -2
128
+ };
129
+
130
+ /* ========================================================================== */
131
+ /* === Colamd reporting mechanism =========================================== */
132
+ /* ========================================================================== */
133
+
134
+ // == Row and Column structures ==
135
+ template <typename IndexType>
136
+ struct ColStructure
137
+ {
138
+ IndexType start ; /* index for A of first row in this column, or Dead */
139
+ /* if column is dead */
140
+ IndexType length ; /* number of rows in this column */
141
+ union
142
+ {
143
+ IndexType thickness ; /* number of original columns represented by this */
144
+ /* col, if the column is alive */
145
+ IndexType parent ; /* parent in parent tree super-column structure, if */
146
+ /* the column is dead */
147
+ } shared1 ;
148
+ union
149
+ {
150
+ IndexType score ; /* the score used to maintain heap, if col is alive */
151
+ IndexType order ; /* pivot ordering of this column, if col is dead */
152
+ } shared2 ;
153
+ union
154
+ {
155
+ IndexType headhash ; /* head of a hash bucket, if col is at the head of */
156
+ /* a degree list */
157
+ IndexType hash ; /* hash value, if col is not in a degree list */
158
+ IndexType prev ; /* previous column in degree list, if col is in a */
159
+ /* degree list (but not at the head of a degree list) */
160
+ } shared3 ;
161
+ union
162
+ {
163
+ IndexType degree_next ; /* next column, if col is in a degree list */
164
+ IndexType hash_next ; /* next column, if col is in a hash list */
165
+ } shared4 ;
166
+
167
+ inline bool is_dead() const { return start < Alive; }
168
+
169
+ inline bool is_alive() const { return start >= Alive; }
170
+
171
+ inline bool is_dead_principal() const { return start == DeadPrincipal; }
172
+
173
+ inline void kill_principal() { start = DeadPrincipal; }
174
+
175
+ inline void kill_non_principal() { start = DeadNonPrincipal; }
176
+
177
+ };
178
+
179
+ template <typename IndexType>
180
+ struct RowStructure
181
+ {
182
+ IndexType start ; /* index for A of first col in this row */
183
+ IndexType length ; /* number of principal columns in this row */
184
+ union
185
+ {
186
+ IndexType degree ; /* number of principal & non-principal columns in row */
187
+ IndexType p ; /* used as a row pointer in init_rows_cols () */
188
+ } shared1 ;
189
+ union
190
+ {
191
+ IndexType mark ; /* for computing set differences and marking dead rows*/
192
+ IndexType first_column ;/* first column in row (used in garbage collection) */
193
+ } shared2 ;
194
+
195
+ inline bool is_dead() const { return shared2.mark < Alive; }
196
+
197
+ inline bool is_alive() const { return shared2.mark >= Alive; }
198
+
199
+ inline void kill() { shared2.mark = Dead; }
200
+
201
+ };
202
+
203
+ /* ========================================================================== */
204
+ /* === Colamd recommended memory size ======================================= */
205
+ /* ========================================================================== */
206
+
207
+ /*
208
+ The recommended length Alen of the array A passed to colamd is given by
209
+ the COLAMD_RECOMMENDED (nnz, n_row, n_col) macro. It returns -1 if any
210
+ argument is negative. 2*nnz space is required for the row and column
211
+ indices of the matrix. colamd_c (n_col) + colamd_r (n_row) space is
212
+ required for the Col and Row arrays, respectively, which are internal to
213
+ colamd. An additional n_col space is the minimal amount of "elbow room",
214
+ and nnz/5 more space is recommended for run time efficiency.
215
+
216
+ This macro is not needed when using symamd.
217
+
218
+ Explicit typecast to IndexType added Sept. 23, 2002, COLAMD version 2.2, to avoid
219
+ gcc -pedantic warning messages.
220
+ */
221
+ template <typename IndexType>
222
+ inline IndexType colamd_c(IndexType n_col)
223
+ { return IndexType( ((n_col) + 1) * sizeof (ColStructure<IndexType>) / sizeof (IndexType) ) ; }
224
+
225
+ template <typename IndexType>
226
+ inline IndexType colamd_r(IndexType n_row)
227
+ { return IndexType(((n_row) + 1) * sizeof (RowStructure<IndexType>) / sizeof (IndexType)); }
228
+
229
+ // Prototypes of non-user callable routines
230
+ template <typename IndexType>
231
+ static IndexType init_rows_cols (IndexType n_row, IndexType n_col, RowStructure<IndexType> Row [], ColStructure<IndexType> col [], IndexType A [], IndexType p [], IndexType stats[NStats] );
232
+
233
+ template <typename IndexType>
234
+ static void init_scoring (IndexType n_row, IndexType n_col, RowStructure<IndexType> Row [], ColStructure<IndexType> Col [], IndexType A [], IndexType head [], double knobs[NKnobs], IndexType *p_n_row2, IndexType *p_n_col2, IndexType *p_max_deg);
235
+
236
+ template <typename IndexType>
237
+ static IndexType find_ordering (IndexType n_row, IndexType n_col, IndexType Alen, RowStructure<IndexType> Row [], ColStructure<IndexType> Col [], IndexType A [], IndexType head [], IndexType n_col2, IndexType max_deg, IndexType pfree);
238
+
239
+ template <typename IndexType>
240
+ static void order_children (IndexType n_col, ColStructure<IndexType> Col [], IndexType p []);
241
+
242
+ template <typename IndexType>
243
+ static void detect_super_cols (ColStructure<IndexType> Col [], IndexType A [], IndexType head [], IndexType row_start, IndexType row_length ) ;
244
+
245
+ template <typename IndexType>
246
+ static IndexType garbage_collection (IndexType n_row, IndexType n_col, RowStructure<IndexType> Row [], ColStructure<IndexType> Col [], IndexType A [], IndexType *pfree) ;
247
+
248
+ template <typename IndexType>
249
+ static inline IndexType clear_mark (IndexType n_row, RowStructure<IndexType> Row [] ) ;
250
+
251
+ /* === No debugging ========================================================= */
252
+
253
+ #define COLAMD_DEBUG0(params) ;
254
+ #define COLAMD_DEBUG1(params) ;
255
+ #define COLAMD_DEBUG2(params) ;
256
+ #define COLAMD_DEBUG3(params) ;
257
+ #define COLAMD_DEBUG4(params) ;
258
+
259
+ #define COLAMD_ASSERT(expression) ((void) 0)
260
+
261
+
262
+ /**
263
+ * \brief Returns the recommended value of Alen
264
+ *
265
+ * Returns recommended value of Alen for use by colamd.
266
+ * Returns -1 if any input argument is negative.
267
+ * The use of this routine or macro is optional.
268
+ * Note that the macro uses its arguments more than once,
269
+ * so be careful for side effects, if you pass expressions as arguments to COLAMD_RECOMMENDED.
270
+ *
271
+ * \param nnz nonzeros in A
272
+ * \param n_row number of rows in A
273
+ * \param n_col number of columns in A
274
+ * \return recommended value of Alen for use by colamd
275
+ */
276
+ template <typename IndexType>
277
+ inline IndexType recommended ( IndexType nnz, IndexType n_row, IndexType n_col)
278
+ {
279
+ if ((nnz) < 0 || (n_row) < 0 || (n_col) < 0)
280
+ return (-1);
281
+ else
282
+ return (2 * (nnz) + colamd_c (n_col) + colamd_r (n_row) + (n_col) + ((nnz) / 5));
283
+ }
284
+
285
+ /**
286
+ * \brief set default parameters The use of this routine is optional.
287
+ *
288
+ * Colamd: rows with more than (knobs [DenseRow] * n_col)
289
+ * entries are removed prior to ordering. Columns with more than
290
+ * (knobs [DenseCol] * n_row) entries are removed prior to
291
+ * ordering, and placed last in the output column ordering.
292
+ *
293
+ * DenseRow and DenseCol are defined as 0 and 1,
294
+ * respectively, in colamd.h. Default values of these two knobs
295
+ * are both 0.5. Currently, only knobs [0] and knobs [1] are
296
+ * used, but future versions may use more knobs. If so, they will
297
+ * be properly set to their defaults by the future version of
298
+ * colamd_set_defaults, so that the code that calls colamd will
299
+ * not need to change, assuming that you either use
300
+ * colamd_set_defaults, or pass a (double *) NULL pointer as the
301
+ * knobs array to colamd or symamd.
302
+ *
303
+ * \param knobs parameter settings for colamd
304
+ */
305
+
306
+ static inline void set_defaults(double knobs[NKnobs])
307
+ {
308
+ /* === Local variables ================================================== */
309
+
310
+ int i ;
311
+
312
+ if (!knobs)
313
+ {
314
+ return ; /* no knobs to initialize */
315
+ }
316
+ for (i = 0 ; i < NKnobs ; i++)
317
+ {
318
+ knobs [i] = 0 ;
319
+ }
320
+ knobs [Colamd::DenseRow] = 0.5 ; /* ignore rows over 50% dense */
321
+ knobs [Colamd::DenseCol] = 0.5 ; /* ignore columns over 50% dense */
322
+ }
323
+
324
+ /**
325
+ * \brief Computes a column ordering using the column approximate minimum degree ordering
326
+ *
327
+ * Computes a column ordering (Q) of A such that P(AQ)=LU or
328
+ * (AQ)'AQ=LL' have less fill-in and require fewer floating point
329
+ * operations than factorizing the unpermuted matrix A or A'A,
330
+ * respectively.
331
+ *
332
+ *
333
+ * \param n_row number of rows in A
334
+ * \param n_col number of columns in A
335
+ * \param Alen, size of the array A
336
+ * \param A row indices of the matrix, of size ALen
337
+ * \param p column pointers of A, of size n_col+1
338
+ * \param knobs parameter settings for colamd
339
+ * \param stats colamd output statistics and error codes
340
+ */
341
+ template <typename IndexType>
342
+ static bool compute_ordering(IndexType n_row, IndexType n_col, IndexType Alen, IndexType *A, IndexType *p, double knobs[NKnobs], IndexType stats[NStats])
343
+ {
344
+ /* === Local variables ================================================== */
345
+
346
+ IndexType i ; /* loop index */
347
+ IndexType nnz ; /* nonzeros in A */
348
+ IndexType Row_size ; /* size of Row [], in integers */
349
+ IndexType Col_size ; /* size of Col [], in integers */
350
+ IndexType need ; /* minimum required length of A */
351
+ Colamd::RowStructure<IndexType> *Row ; /* pointer into A of Row [0..n_row] array */
352
+ Colamd::ColStructure<IndexType> *Col ; /* pointer into A of Col [0..n_col] array */
353
+ IndexType n_col2 ; /* number of non-dense, non-empty columns */
354
+ IndexType n_row2 ; /* number of non-dense, non-empty rows */
355
+ IndexType ngarbage ; /* number of garbage collections performed */
356
+ IndexType max_deg ; /* maximum row degree */
357
+ double default_knobs [NKnobs] ; /* default knobs array */
358
+
359
+
360
+ /* === Check the input arguments ======================================== */
361
+
362
+ if (!stats)
363
+ {
364
+ COLAMD_DEBUG0 (("colamd: stats not present\n")) ;
365
+ return (false) ;
366
+ }
367
+ for (i = 0 ; i < NStats ; i++)
368
+ {
369
+ stats [i] = 0 ;
370
+ }
371
+ stats [Colamd::Status] = Colamd::Ok ;
372
+ stats [Colamd::Info1] = -1 ;
373
+ stats [Colamd::Info2] = -1 ;
374
+
375
+ if (!A) /* A is not present */
376
+ {
377
+ stats [Colamd::Status] = Colamd::ErrorANotPresent ;
378
+ COLAMD_DEBUG0 (("colamd: A not present\n")) ;
379
+ return (false) ;
380
+ }
381
+
382
+ if (!p) /* p is not present */
383
+ {
384
+ stats [Colamd::Status] = Colamd::ErrorPNotPresent ;
385
+ COLAMD_DEBUG0 (("colamd: p not present\n")) ;
386
+ return (false) ;
387
+ }
388
+
389
+ if (n_row < 0) /* n_row must be >= 0 */
390
+ {
391
+ stats [Colamd::Status] = Colamd::ErrorNrowNegative ;
392
+ stats [Colamd::Info1] = n_row ;
393
+ COLAMD_DEBUG0 (("colamd: nrow negative %d\n", n_row)) ;
394
+ return (false) ;
395
+ }
396
+
397
+ if (n_col < 0) /* n_col must be >= 0 */
398
+ {
399
+ stats [Colamd::Status] = Colamd::ErrorNcolNegative ;
400
+ stats [Colamd::Info1] = n_col ;
401
+ COLAMD_DEBUG0 (("colamd: ncol negative %d\n", n_col)) ;
402
+ return (false) ;
403
+ }
404
+
405
+ nnz = p [n_col] ;
406
+ if (nnz < 0) /* nnz must be >= 0 */
407
+ {
408
+ stats [Colamd::Status] = Colamd::ErrorNnzNegative ;
409
+ stats [Colamd::Info1] = nnz ;
410
+ COLAMD_DEBUG0 (("colamd: number of entries negative %d\n", nnz)) ;
411
+ return (false) ;
412
+ }
413
+
414
+ if (p [0] != 0)
415
+ {
416
+ stats [Colamd::Status] = Colamd::ErrorP0Nonzero ;
417
+ stats [Colamd::Info1] = p [0] ;
418
+ COLAMD_DEBUG0 (("colamd: p[0] not zero %d\n", p [0])) ;
419
+ return (false) ;
420
+ }
421
+
422
+ /* === If no knobs, set default knobs =================================== */
423
+
424
+ if (!knobs)
425
+ {
426
+ set_defaults (default_knobs) ;
427
+ knobs = default_knobs ;
428
+ }
429
+
430
+ /* === Allocate the Row and Col arrays from array A ===================== */
431
+
432
+ Col_size = colamd_c (n_col) ;
433
+ Row_size = colamd_r (n_row) ;
434
+ need = 2*nnz + n_col + Col_size + Row_size ;
435
+
436
+ if (need > Alen)
437
+ {
438
+ /* not enough space in array A to perform the ordering */
439
+ stats [Colamd::Status] = Colamd::ErrorATooSmall ;
440
+ stats [Colamd::Info1] = need ;
441
+ stats [Colamd::Info2] = Alen ;
442
+ COLAMD_DEBUG0 (("colamd: Need Alen >= %d, given only Alen = %d\n", need,Alen));
443
+ return (false) ;
444
+ }
445
+
446
+ Alen -= Col_size + Row_size ;
447
+ Col = (ColStructure<IndexType> *) &A [Alen] ;
448
+ Row = (RowStructure<IndexType> *) &A [Alen + Col_size] ;
449
+
450
+ /* === Construct the row and column data structures ===================== */
451
+
452
+ if (!Colamd::init_rows_cols (n_row, n_col, Row, Col, A, p, stats))
453
+ {
454
+ /* input matrix is invalid */
455
+ COLAMD_DEBUG0 (("colamd: Matrix invalid\n")) ;
456
+ return (false) ;
457
+ }
458
+
459
+ /* === Initialize scores, kill dense rows/columns ======================= */
460
+
461
+ Colamd::init_scoring (n_row, n_col, Row, Col, A, p, knobs,
462
+ &n_row2, &n_col2, &max_deg) ;
463
+
464
+ /* === Order the supercolumns =========================================== */
465
+
466
+ ngarbage = Colamd::find_ordering (n_row, n_col, Alen, Row, Col, A, p,
467
+ n_col2, max_deg, 2*nnz) ;
468
+
469
+ /* === Order the non-principal columns ================================== */
470
+
471
+ Colamd::order_children (n_col, Col, p) ;
472
+
473
+ /* === Return statistics in stats ======================================= */
474
+
475
+ stats [Colamd::DenseRow] = n_row - n_row2 ;
476
+ stats [Colamd::DenseCol] = n_col - n_col2 ;
477
+ stats [Colamd::DefragCount] = ngarbage ;
478
+ COLAMD_DEBUG0 (("colamd: done.\n")) ;
479
+ return (true) ;
480
+ }
481
+
482
+ /* ========================================================================== */
483
+ /* === NON-USER-CALLABLE ROUTINES: ========================================== */
484
+ /* ========================================================================== */
485
+
486
+ /* There are no user-callable routines beyond this point in the file */
487
+
488
+ /* ========================================================================== */
489
+ /* === init_rows_cols ======================================================= */
490
+ /* ========================================================================== */
491
+
492
+ /*
493
+ Takes the column form of the matrix in A and creates the row form of the
494
+ matrix. Also, row and column attributes are stored in the Col and Row
495
+ structs. If the columns are un-sorted or contain duplicate row indices,
496
+ this routine will also sort and remove duplicate row indices from the
497
+ column form of the matrix. Returns false if the matrix is invalid,
498
+ true otherwise. Not user-callable.
499
+ */
500
+ template <typename IndexType>
501
+ static IndexType init_rows_cols /* returns true if OK, or false otherwise */
502
+ (
503
+ /* === Parameters ======================================================= */
504
+
505
+ IndexType n_row, /* number of rows of A */
506
+ IndexType n_col, /* number of columns of A */
507
+ RowStructure<IndexType> Row [], /* of size n_row+1 */
508
+ ColStructure<IndexType> Col [], /* of size n_col+1 */
509
+ IndexType A [], /* row indices of A, of size Alen */
510
+ IndexType p [], /* pointers to columns in A, of size n_col+1 */
511
+ IndexType stats [NStats] /* colamd statistics */
512
+ )
513
+ {
514
+ /* === Local variables ================================================== */
515
+
516
+ IndexType col ; /* a column index */
517
+ IndexType row ; /* a row index */
518
+ IndexType *cp ; /* a column pointer */
519
+ IndexType *cp_end ; /* a pointer to the end of a column */
520
+ IndexType *rp ; /* a row pointer */
521
+ IndexType *rp_end ; /* a pointer to the end of a row */
522
+ IndexType last_row ; /* previous row */
523
+
524
+ /* === Initialize columns, and check column pointers ==================== */
525
+
526
+ for (col = 0 ; col < n_col ; col++)
527
+ {
528
+ Col [col].start = p [col] ;
529
+ Col [col].length = p [col+1] - p [col] ;
530
+
531
+ if ((Col [col].length) < 0) // extra parentheses to work-around gcc bug 10200
532
+ {
533
+ /* column pointers must be non-decreasing */
534
+ stats [Colamd::Status] = Colamd::ErrorColLengthNegative ;
535
+ stats [Colamd::Info1] = col ;
536
+ stats [Colamd::Info2] = Col [col].length ;
537
+ COLAMD_DEBUG0 (("colamd: col %d length %d < 0\n", col, Col [col].length)) ;
538
+ return (false) ;
539
+ }
540
+
541
+ Col [col].shared1.thickness = 1 ;
542
+ Col [col].shared2.score = 0 ;
543
+ Col [col].shared3.prev = Empty ;
544
+ Col [col].shared4.degree_next = Empty ;
545
+ }
546
+
547
+ /* p [0..n_col] no longer needed, used as "head" in subsequent routines */
548
+
549
+ /* === Scan columns, compute row degrees, and check row indices ========= */
550
+
551
+ stats [Info3] = 0 ; /* number of duplicate or unsorted row indices*/
552
+
553
+ for (row = 0 ; row < n_row ; row++)
554
+ {
555
+ Row [row].length = 0 ;
556
+ Row [row].shared2.mark = -1 ;
557
+ }
558
+
559
+ for (col = 0 ; col < n_col ; col++)
560
+ {
561
+ last_row = -1 ;
562
+
563
+ cp = &A [p [col]] ;
564
+ cp_end = &A [p [col+1]] ;
565
+
566
+ while (cp < cp_end)
567
+ {
568
+ row = *cp++ ;
569
+
570
+ /* make sure row indices within range */
571
+ if (row < 0 || row >= n_row)
572
+ {
573
+ stats [Colamd::Status] = Colamd::ErrorRowIndexOutOfBounds ;
574
+ stats [Colamd::Info1] = col ;
575
+ stats [Colamd::Info2] = row ;
576
+ stats [Colamd::Info3] = n_row ;
577
+ COLAMD_DEBUG0 (("colamd: row %d col %d out of bounds\n", row, col)) ;
578
+ return (false) ;
579
+ }
580
+
581
+ if (row <= last_row || Row [row].shared2.mark == col)
582
+ {
583
+ /* row index are unsorted or repeated (or both), thus col */
584
+ /* is jumbled. This is a notice, not an error condition. */
585
+ stats [Colamd::Status] = Colamd::OkButJumbled ;
586
+ stats [Colamd::Info1] = col ;
587
+ stats [Colamd::Info2] = row ;
588
+ (stats [Colamd::Info3]) ++ ;
589
+ COLAMD_DEBUG1 (("colamd: row %d col %d unsorted/duplicate\n",row,col));
590
+ }
591
+
592
+ if (Row [row].shared2.mark != col)
593
+ {
594
+ Row [row].length++ ;
595
+ }
596
+ else
597
+ {
598
+ /* this is a repeated entry in the column, */
599
+ /* it will be removed */
600
+ Col [col].length-- ;
601
+ }
602
+
603
+ /* mark the row as having been seen in this column */
604
+ Row [row].shared2.mark = col ;
605
+
606
+ last_row = row ;
607
+ }
608
+ }
609
+
610
+ /* === Compute row pointers ============================================= */
611
+
612
+ /* row form of the matrix starts directly after the column */
613
+ /* form of matrix in A */
614
+ Row [0].start = p [n_col] ;
615
+ Row [0].shared1.p = Row [0].start ;
616
+ Row [0].shared2.mark = -1 ;
617
+ for (row = 1 ; row < n_row ; row++)
618
+ {
619
+ Row [row].start = Row [row-1].start + Row [row-1].length ;
620
+ Row [row].shared1.p = Row [row].start ;
621
+ Row [row].shared2.mark = -1 ;
622
+ }
623
+
624
+ /* === Create row form ================================================== */
625
+
626
+ if (stats [Status] == OkButJumbled)
627
+ {
628
+ /* if cols jumbled, watch for repeated row indices */
629
+ for (col = 0 ; col < n_col ; col++)
630
+ {
631
+ cp = &A [p [col]] ;
632
+ cp_end = &A [p [col+1]] ;
633
+ while (cp < cp_end)
634
+ {
635
+ row = *cp++ ;
636
+ if (Row [row].shared2.mark != col)
637
+ {
638
+ A [(Row [row].shared1.p)++] = col ;
639
+ Row [row].shared2.mark = col ;
640
+ }
641
+ }
642
+ }
643
+ }
644
+ else
645
+ {
646
+ /* if cols not jumbled, we don't need the mark (this is faster) */
647
+ for (col = 0 ; col < n_col ; col++)
648
+ {
649
+ cp = &A [p [col]] ;
650
+ cp_end = &A [p [col+1]] ;
651
+ while (cp < cp_end)
652
+ {
653
+ A [(Row [*cp++].shared1.p)++] = col ;
654
+ }
655
+ }
656
+ }
657
+
658
+ /* === Clear the row marks and set row degrees ========================== */
659
+
660
+ for (row = 0 ; row < n_row ; row++)
661
+ {
662
+ Row [row].shared2.mark = 0 ;
663
+ Row [row].shared1.degree = Row [row].length ;
664
+ }
665
+
666
+ /* === See if we need to re-create columns ============================== */
667
+
668
+ if (stats [Status] == OkButJumbled)
669
+ {
670
+ COLAMD_DEBUG0 (("colamd: reconstructing column form, matrix jumbled\n")) ;
671
+
672
+
673
+ /* === Compute col pointers ========================================= */
674
+
675
+ /* col form of the matrix starts at A [0]. */
676
+ /* Note, we may have a gap between the col form and the row */
677
+ /* form if there were duplicate entries, if so, it will be */
678
+ /* removed upon the first garbage collection */
679
+ Col [0].start = 0 ;
680
+ p [0] = Col [0].start ;
681
+ for (col = 1 ; col < n_col ; col++)
682
+ {
683
+ /* note that the lengths here are for pruned columns, i.e. */
684
+ /* no duplicate row indices will exist for these columns */
685
+ Col [col].start = Col [col-1].start + Col [col-1].length ;
686
+ p [col] = Col [col].start ;
687
+ }
688
+
689
+ /* === Re-create col form =========================================== */
690
+
691
+ for (row = 0 ; row < n_row ; row++)
692
+ {
693
+ rp = &A [Row [row].start] ;
694
+ rp_end = rp + Row [row].length ;
695
+ while (rp < rp_end)
696
+ {
697
+ A [(p [*rp++])++] = row ;
698
+ }
699
+ }
700
+ }
701
+
702
+ /* === Done. Matrix is not (or no longer) jumbled ====================== */
703
+
704
+ return (true) ;
705
+ }
706
+
707
+
708
+ /* ========================================================================== */
709
+ /* === init_scoring ========================================================= */
710
+ /* ========================================================================== */
711
+
712
+ /*
713
+ Kills dense or empty columns and rows, calculates an initial score for
714
+ each column, and places all columns in the degree lists. Not user-callable.
715
+ */
716
+ template <typename IndexType>
717
+ static void init_scoring
718
+ (
719
+ /* === Parameters ======================================================= */
720
+
721
+ IndexType n_row, /* number of rows of A */
722
+ IndexType n_col, /* number of columns of A */
723
+ RowStructure<IndexType> Row [], /* of size n_row+1 */
724
+ ColStructure<IndexType> Col [], /* of size n_col+1 */
725
+ IndexType A [], /* column form and row form of A */
726
+ IndexType head [], /* of size n_col+1 */
727
+ double knobs [NKnobs],/* parameters */
728
+ IndexType *p_n_row2, /* number of non-dense, non-empty rows */
729
+ IndexType *p_n_col2, /* number of non-dense, non-empty columns */
730
+ IndexType *p_max_deg /* maximum row degree */
731
+ )
732
+ {
733
+ /* === Local variables ================================================== */
734
+
735
+ IndexType c ; /* a column index */
736
+ IndexType r, row ; /* a row index */
737
+ IndexType *cp ; /* a column pointer */
738
+ IndexType deg ; /* degree of a row or column */
739
+ IndexType *cp_end ; /* a pointer to the end of a column */
740
+ IndexType *new_cp ; /* new column pointer */
741
+ IndexType col_length ; /* length of pruned column */
742
+ IndexType score ; /* current column score */
743
+ IndexType n_col2 ; /* number of non-dense, non-empty columns */
744
+ IndexType n_row2 ; /* number of non-dense, non-empty rows */
745
+ IndexType dense_row_count ; /* remove rows with more entries than this */
746
+ IndexType dense_col_count ; /* remove cols with more entries than this */
747
+ IndexType min_score ; /* smallest column score */
748
+ IndexType max_deg ; /* maximum row degree */
749
+ IndexType next_col ; /* Used to add to degree list.*/
750
+
751
+
752
+ /* === Extract knobs ==================================================== */
753
+
754
+ dense_row_count = numext::maxi(IndexType(0), numext::mini(IndexType(knobs [Colamd::DenseRow] * n_col), n_col)) ;
755
+ dense_col_count = numext::maxi(IndexType(0), numext::mini(IndexType(knobs [Colamd::DenseCol] * n_row), n_row)) ;
756
+ COLAMD_DEBUG1 (("colamd: densecount: %d %d\n", dense_row_count, dense_col_count)) ;
757
+ max_deg = 0 ;
758
+ n_col2 = n_col ;
759
+ n_row2 = n_row ;
760
+
761
+ /* === Kill empty columns =============================================== */
762
+
763
+ /* Put the empty columns at the end in their natural order, so that LU */
764
+ /* factorization can proceed as far as possible. */
765
+ for (c = n_col-1 ; c >= 0 ; c--)
766
+ {
767
+ deg = Col [c].length ;
768
+ if (deg == 0)
769
+ {
770
+ /* this is a empty column, kill and order it last */
771
+ Col [c].shared2.order = --n_col2 ;
772
+ Col[c].kill_principal() ;
773
+ }
774
+ }
775
+ COLAMD_DEBUG1 (("colamd: null columns killed: %d\n", n_col - n_col2)) ;
776
+
777
+ /* === Kill dense columns =============================================== */
778
+
779
+ /* Put the dense columns at the end, in their natural order */
780
+ for (c = n_col-1 ; c >= 0 ; c--)
781
+ {
782
+ /* skip any dead columns */
783
+ if (Col[c].is_dead())
784
+ {
785
+ continue ;
786
+ }
787
+ deg = Col [c].length ;
788
+ if (deg > dense_col_count)
789
+ {
790
+ /* this is a dense column, kill and order it last */
791
+ Col [c].shared2.order = --n_col2 ;
792
+ /* decrement the row degrees */
793
+ cp = &A [Col [c].start] ;
794
+ cp_end = cp + Col [c].length ;
795
+ while (cp < cp_end)
796
+ {
797
+ Row [*cp++].shared1.degree-- ;
798
+ }
799
+ Col[c].kill_principal() ;
800
+ }
801
+ }
802
+ COLAMD_DEBUG1 (("colamd: Dense and null columns killed: %d\n", n_col - n_col2)) ;
803
+
804
+ /* === Kill dense and empty rows ======================================== */
805
+
806
+ for (r = 0 ; r < n_row ; r++)
807
+ {
808
+ deg = Row [r].shared1.degree ;
809
+ COLAMD_ASSERT (deg >= 0 && deg <= n_col) ;
810
+ if (deg > dense_row_count || deg == 0)
811
+ {
812
+ /* kill a dense or empty row */
813
+ Row[r].kill() ;
814
+ --n_row2 ;
815
+ }
816
+ else
817
+ {
818
+ /* keep track of max degree of remaining rows */
819
+ max_deg = numext::maxi(max_deg, deg) ;
820
+ }
821
+ }
822
+ COLAMD_DEBUG1 (("colamd: Dense and null rows killed: %d\n", n_row - n_row2)) ;
823
+
824
+ /* === Compute initial column scores ==================================== */
825
+
826
+ /* At this point the row degrees are accurate. They reflect the number */
827
+ /* of "live" (non-dense) columns in each row. No empty rows exist. */
828
+ /* Some "live" columns may contain only dead rows, however. These are */
829
+ /* pruned in the code below. */
830
+
831
+ /* now find the initial matlab score for each column */
832
+ for (c = n_col-1 ; c >= 0 ; c--)
833
+ {
834
+ /* skip dead column */
835
+ if (Col[c].is_dead())
836
+ {
837
+ continue ;
838
+ }
839
+ score = 0 ;
840
+ cp = &A [Col [c].start] ;
841
+ new_cp = cp ;
842
+ cp_end = cp + Col [c].length ;
843
+ while (cp < cp_end)
844
+ {
845
+ /* get a row */
846
+ row = *cp++ ;
847
+ /* skip if dead */
848
+ if (Row[row].is_dead())
849
+ {
850
+ continue ;
851
+ }
852
+ /* compact the column */
853
+ *new_cp++ = row ;
854
+ /* add row's external degree */
855
+ score += Row [row].shared1.degree - 1 ;
856
+ /* guard against integer overflow */
857
+ score = numext::mini(score, n_col) ;
858
+ }
859
+ /* determine pruned column length */
860
+ col_length = (IndexType) (new_cp - &A [Col [c].start]) ;
861
+ if (col_length == 0)
862
+ {
863
+ /* a newly-made null column (all rows in this col are "dense" */
864
+ /* and have already been killed) */
865
+ COLAMD_DEBUG2 (("Newly null killed: %d\n", c)) ;
866
+ Col [c].shared2.order = --n_col2 ;
867
+ Col[c].kill_principal() ;
868
+ }
869
+ else
870
+ {
871
+ /* set column length and set score */
872
+ COLAMD_ASSERT (score >= 0) ;
873
+ COLAMD_ASSERT (score <= n_col) ;
874
+ Col [c].length = col_length ;
875
+ Col [c].shared2.score = score ;
876
+ }
877
+ }
878
+ COLAMD_DEBUG1 (("colamd: Dense, null, and newly-null columns killed: %d\n",
879
+ n_col-n_col2)) ;
880
+
881
+ /* At this point, all empty rows and columns are dead. All live columns */
882
+ /* are "clean" (containing no dead rows) and simplicial (no supercolumns */
883
+ /* yet). Rows may contain dead columns, but all live rows contain at */
884
+ /* least one live column. */
885
+
886
+ /* === Initialize degree lists ========================================== */
887
+
888
+
889
+ /* clear the hash buckets */
890
+ for (c = 0 ; c <= n_col ; c++)
891
+ {
892
+ head [c] = Empty ;
893
+ }
894
+ min_score = n_col ;
895
+ /* place in reverse order, so low column indices are at the front */
896
+ /* of the lists. This is to encourage natural tie-breaking */
897
+ for (c = n_col-1 ; c >= 0 ; c--)
898
+ {
899
+ /* only add principal columns to degree lists */
900
+ if (Col[c].is_alive())
901
+ {
902
+ COLAMD_DEBUG4 (("place %d score %d minscore %d ncol %d\n",
903
+ c, Col [c].shared2.score, min_score, n_col)) ;
904
+
905
+ /* === Add columns score to DList =============================== */
906
+
907
+ score = Col [c].shared2.score ;
908
+
909
+ COLAMD_ASSERT (min_score >= 0) ;
910
+ COLAMD_ASSERT (min_score <= n_col) ;
911
+ COLAMD_ASSERT (score >= 0) ;
912
+ COLAMD_ASSERT (score <= n_col) ;
913
+ COLAMD_ASSERT (head [score] >= Empty) ;
914
+
915
+ /* now add this column to dList at proper score location */
916
+ next_col = head [score] ;
917
+ Col [c].shared3.prev = Empty ;
918
+ Col [c].shared4.degree_next = next_col ;
919
+
920
+ /* if there already was a column with the same score, set its */
921
+ /* previous pointer to this new column */
922
+ if (next_col != Empty)
923
+ {
924
+ Col [next_col].shared3.prev = c ;
925
+ }
926
+ head [score] = c ;
927
+
928
+ /* see if this score is less than current min */
929
+ min_score = numext::mini(min_score, score) ;
930
+
931
+
932
+ }
933
+ }
934
+
935
+
936
+ /* === Return number of remaining columns, and max row degree =========== */
937
+
938
+ *p_n_col2 = n_col2 ;
939
+ *p_n_row2 = n_row2 ;
940
+ *p_max_deg = max_deg ;
941
+ }
942
+
943
+
944
+ /* ========================================================================== */
945
+ /* === find_ordering ======================================================== */
946
+ /* ========================================================================== */
947
+
948
+ /*
949
+ Order the principal columns of the supercolumn form of the matrix
950
+ (no supercolumns on input). Uses a minimum approximate column minimum
951
+ degree ordering method. Not user-callable.
952
+ */
953
+ template <typename IndexType>
954
+ static IndexType find_ordering /* return the number of garbage collections */
955
+ (
956
+ /* === Parameters ======================================================= */
957
+
958
+ IndexType n_row, /* number of rows of A */
959
+ IndexType n_col, /* number of columns of A */
960
+ IndexType Alen, /* size of A, 2*nnz + n_col or larger */
961
+ RowStructure<IndexType> Row [], /* of size n_row+1 */
962
+ ColStructure<IndexType> Col [], /* of size n_col+1 */
963
+ IndexType A [], /* column form and row form of A */
964
+ IndexType head [], /* of size n_col+1 */
965
+ IndexType n_col2, /* Remaining columns to order */
966
+ IndexType max_deg, /* Maximum row degree */
967
+ IndexType pfree /* index of first free slot (2*nnz on entry) */
968
+ )
969
+ {
970
+ /* === Local variables ================================================== */
971
+
972
+ IndexType k ; /* current pivot ordering step */
973
+ IndexType pivot_col ; /* current pivot column */
974
+ IndexType *cp ; /* a column pointer */
975
+ IndexType *rp ; /* a row pointer */
976
+ IndexType pivot_row ; /* current pivot row */
977
+ IndexType *new_cp ; /* modified column pointer */
978
+ IndexType *new_rp ; /* modified row pointer */
979
+ IndexType pivot_row_start ; /* pointer to start of pivot row */
980
+ IndexType pivot_row_degree ; /* number of columns in pivot row */
981
+ IndexType pivot_row_length ; /* number of supercolumns in pivot row */
982
+ IndexType pivot_col_score ; /* score of pivot column */
983
+ IndexType needed_memory ; /* free space needed for pivot row */
984
+ IndexType *cp_end ; /* pointer to the end of a column */
985
+ IndexType *rp_end ; /* pointer to the end of a row */
986
+ IndexType row ; /* a row index */
987
+ IndexType col ; /* a column index */
988
+ IndexType max_score ; /* maximum possible score */
989
+ IndexType cur_score ; /* score of current column */
990
+ unsigned int hash ; /* hash value for supernode detection */
991
+ IndexType head_column ; /* head of hash bucket */
992
+ IndexType first_col ; /* first column in hash bucket */
993
+ IndexType tag_mark ; /* marker value for mark array */
994
+ IndexType row_mark ; /* Row [row].shared2.mark */
995
+ IndexType set_difference ; /* set difference size of row with pivot row */
996
+ IndexType min_score ; /* smallest column score */
997
+ IndexType col_thickness ; /* "thickness" (no. of columns in a supercol) */
998
+ IndexType max_mark ; /* maximum value of tag_mark */
999
+ IndexType pivot_col_thickness ; /* number of columns represented by pivot col */
1000
+ IndexType prev_col ; /* Used by Dlist operations. */
1001
+ IndexType next_col ; /* Used by Dlist operations. */
1002
+ IndexType ngarbage ; /* number of garbage collections performed */
1003
+
1004
+
1005
+ /* === Initialization and clear mark ==================================== */
1006
+
1007
+ max_mark = INT_MAX - n_col ; /* INT_MAX defined in <limits.h> */
1008
+ tag_mark = Colamd::clear_mark (n_row, Row) ;
1009
+ min_score = 0 ;
1010
+ ngarbage = 0 ;
1011
+ COLAMD_DEBUG1 (("colamd: Ordering, n_col2=%d\n", n_col2)) ;
1012
+
1013
+ /* === Order the columns ================================================ */
1014
+
1015
+ for (k = 0 ; k < n_col2 ; /* 'k' is incremented below */)
1016
+ {
1017
+
1018
+ /* === Select pivot column, and order it ============================ */
1019
+
1020
+ /* make sure degree list isn't empty */
1021
+ COLAMD_ASSERT (min_score >= 0) ;
1022
+ COLAMD_ASSERT (min_score <= n_col) ;
1023
+ COLAMD_ASSERT (head [min_score] >= Empty) ;
1024
+
1025
+ /* get pivot column from head of minimum degree list */
1026
+ while (min_score < n_col && head [min_score] == Empty)
1027
+ {
1028
+ min_score++ ;
1029
+ }
1030
+ pivot_col = head [min_score] ;
1031
+ COLAMD_ASSERT (pivot_col >= 0 && pivot_col <= n_col) ;
1032
+ next_col = Col [pivot_col].shared4.degree_next ;
1033
+ head [min_score] = next_col ;
1034
+ if (next_col != Empty)
1035
+ {
1036
+ Col [next_col].shared3.prev = Empty ;
1037
+ }
1038
+
1039
+ COLAMD_ASSERT (Col[pivot_col].is_alive()) ;
1040
+ COLAMD_DEBUG3 (("Pivot col: %d\n", pivot_col)) ;
1041
+
1042
+ /* remember score for defrag check */
1043
+ pivot_col_score = Col [pivot_col].shared2.score ;
1044
+
1045
+ /* the pivot column is the kth column in the pivot order */
1046
+ Col [pivot_col].shared2.order = k ;
1047
+
1048
+ /* increment order count by column thickness */
1049
+ pivot_col_thickness = Col [pivot_col].shared1.thickness ;
1050
+ k += pivot_col_thickness ;
1051
+ COLAMD_ASSERT (pivot_col_thickness > 0) ;
1052
+
1053
+ /* === Garbage_collection, if necessary ============================= */
1054
+
1055
+ needed_memory = numext::mini(pivot_col_score, n_col - k) ;
1056
+ if (pfree + needed_memory >= Alen)
1057
+ {
1058
+ pfree = Colamd::garbage_collection (n_row, n_col, Row, Col, A, &A [pfree]) ;
1059
+ ngarbage++ ;
1060
+ /* after garbage collection we will have enough */
1061
+ COLAMD_ASSERT (pfree + needed_memory < Alen) ;
1062
+ /* garbage collection has wiped out the Row[].shared2.mark array */
1063
+ tag_mark = Colamd::clear_mark (n_row, Row) ;
1064
+
1065
+ }
1066
+
1067
+ /* === Compute pivot row pattern ==================================== */
1068
+
1069
+ /* get starting location for this new merged row */
1070
+ pivot_row_start = pfree ;
1071
+
1072
+ /* initialize new row counts to zero */
1073
+ pivot_row_degree = 0 ;
1074
+
1075
+ /* tag pivot column as having been visited so it isn't included */
1076
+ /* in merged pivot row */
1077
+ Col [pivot_col].shared1.thickness = -pivot_col_thickness ;
1078
+
1079
+ /* pivot row is the union of all rows in the pivot column pattern */
1080
+ cp = &A [Col [pivot_col].start] ;
1081
+ cp_end = cp + Col [pivot_col].length ;
1082
+ while (cp < cp_end)
1083
+ {
1084
+ /* get a row */
1085
+ row = *cp++ ;
1086
+ COLAMD_DEBUG4 (("Pivot col pattern %d %d\n", Row[row].is_alive(), row)) ;
1087
+ /* skip if row is dead */
1088
+ if (Row[row].is_dead())
1089
+ {
1090
+ continue ;
1091
+ }
1092
+ rp = &A [Row [row].start] ;
1093
+ rp_end = rp + Row [row].length ;
1094
+ while (rp < rp_end)
1095
+ {
1096
+ /* get a column */
1097
+ col = *rp++ ;
1098
+ /* add the column, if alive and untagged */
1099
+ col_thickness = Col [col].shared1.thickness ;
1100
+ if (col_thickness > 0 && Col[col].is_alive())
1101
+ {
1102
+ /* tag column in pivot row */
1103
+ Col [col].shared1.thickness = -col_thickness ;
1104
+ COLAMD_ASSERT (pfree < Alen) ;
1105
+ /* place column in pivot row */
1106
+ A [pfree++] = col ;
1107
+ pivot_row_degree += col_thickness ;
1108
+ }
1109
+ }
1110
+ }
1111
+
1112
+ /* clear tag on pivot column */
1113
+ Col [pivot_col].shared1.thickness = pivot_col_thickness ;
1114
+ max_deg = numext::maxi(max_deg, pivot_row_degree) ;
1115
+
1116
+
1117
+ /* === Kill all rows used to construct pivot row ==================== */
1118
+
1119
+ /* also kill pivot row, temporarily */
1120
+ cp = &A [Col [pivot_col].start] ;
1121
+ cp_end = cp + Col [pivot_col].length ;
1122
+ while (cp < cp_end)
1123
+ {
1124
+ /* may be killing an already dead row */
1125
+ row = *cp++ ;
1126
+ COLAMD_DEBUG3 (("Kill row in pivot col: %d\n", row)) ;
1127
+ Row[row].kill() ;
1128
+ }
1129
+
1130
+ /* === Select a row index to use as the new pivot row =============== */
1131
+
1132
+ pivot_row_length = pfree - pivot_row_start ;
1133
+ if (pivot_row_length > 0)
1134
+ {
1135
+ /* pick the "pivot" row arbitrarily (first row in col) */
1136
+ pivot_row = A [Col [pivot_col].start] ;
1137
+ COLAMD_DEBUG3 (("Pivotal row is %d\n", pivot_row)) ;
1138
+ }
1139
+ else
1140
+ {
1141
+ /* there is no pivot row, since it is of zero length */
1142
+ pivot_row = Empty ;
1143
+ COLAMD_ASSERT (pivot_row_length == 0) ;
1144
+ }
1145
+ COLAMD_ASSERT (Col [pivot_col].length > 0 || pivot_row_length == 0) ;
1146
+
1147
+ /* === Approximate degree computation =============================== */
1148
+
1149
+ /* Here begins the computation of the approximate degree. The column */
1150
+ /* score is the sum of the pivot row "length", plus the size of the */
1151
+ /* set differences of each row in the column minus the pattern of the */
1152
+ /* pivot row itself. The column ("thickness") itself is also */
1153
+ /* excluded from the column score (we thus use an approximate */
1154
+ /* external degree). */
1155
+
1156
+ /* The time taken by the following code (compute set differences, and */
1157
+ /* add them up) is proportional to the size of the data structure */
1158
+ /* being scanned - that is, the sum of the sizes of each column in */
1159
+ /* the pivot row. Thus, the amortized time to compute a column score */
1160
+ /* is proportional to the size of that column (where size, in this */
1161
+ /* context, is the column "length", or the number of row indices */
1162
+ /* in that column). The number of row indices in a column is */
1163
+ /* monotonically non-decreasing, from the length of the original */
1164
+ /* column on input to colamd. */
1165
+
1166
+ /* === Compute set differences ====================================== */
1167
+
1168
+ COLAMD_DEBUG3 (("** Computing set differences phase. **\n")) ;
1169
+
1170
+ /* pivot row is currently dead - it will be revived later. */
1171
+
1172
+ COLAMD_DEBUG3 (("Pivot row: ")) ;
1173
+ /* for each column in pivot row */
1174
+ rp = &A [pivot_row_start] ;
1175
+ rp_end = rp + pivot_row_length ;
1176
+ while (rp < rp_end)
1177
+ {
1178
+ col = *rp++ ;
1179
+ COLAMD_ASSERT (Col[col].is_alive() && col != pivot_col) ;
1180
+ COLAMD_DEBUG3 (("Col: %d\n", col)) ;
1181
+
1182
+ /* clear tags used to construct pivot row pattern */
1183
+ col_thickness = -Col [col].shared1.thickness ;
1184
+ COLAMD_ASSERT (col_thickness > 0) ;
1185
+ Col [col].shared1.thickness = col_thickness ;
1186
+
1187
+ /* === Remove column from degree list =========================== */
1188
+
1189
+ cur_score = Col [col].shared2.score ;
1190
+ prev_col = Col [col].shared3.prev ;
1191
+ next_col = Col [col].shared4.degree_next ;
1192
+ COLAMD_ASSERT (cur_score >= 0) ;
1193
+ COLAMD_ASSERT (cur_score <= n_col) ;
1194
+ COLAMD_ASSERT (cur_score >= Empty) ;
1195
+ if (prev_col == Empty)
1196
+ {
1197
+ head [cur_score] = next_col ;
1198
+ }
1199
+ else
1200
+ {
1201
+ Col [prev_col].shared4.degree_next = next_col ;
1202
+ }
1203
+ if (next_col != Empty)
1204
+ {
1205
+ Col [next_col].shared3.prev = prev_col ;
1206
+ }
1207
+
1208
+ /* === Scan the column ========================================== */
1209
+
1210
+ cp = &A [Col [col].start] ;
1211
+ cp_end = cp + Col [col].length ;
1212
+ while (cp < cp_end)
1213
+ {
1214
+ /* get a row */
1215
+ row = *cp++ ;
1216
+ /* skip if dead */
1217
+ if (Row[row].is_dead())
1218
+ {
1219
+ continue ;
1220
+ }
1221
+ row_mark = Row [row].shared2.mark ;
1222
+ COLAMD_ASSERT (row != pivot_row) ;
1223
+ set_difference = row_mark - tag_mark ;
1224
+ /* check if the row has been seen yet */
1225
+ if (set_difference < 0)
1226
+ {
1227
+ COLAMD_ASSERT (Row [row].shared1.degree <= max_deg) ;
1228
+ set_difference = Row [row].shared1.degree ;
1229
+ }
1230
+ /* subtract column thickness from this row's set difference */
1231
+ set_difference -= col_thickness ;
1232
+ COLAMD_ASSERT (set_difference >= 0) ;
1233
+ /* absorb this row if the set difference becomes zero */
1234
+ if (set_difference == 0)
1235
+ {
1236
+ COLAMD_DEBUG3 (("aggressive absorption. Row: %d\n", row)) ;
1237
+ Row[row].kill() ;
1238
+ }
1239
+ else
1240
+ {
1241
+ /* save the new mark */
1242
+ Row [row].shared2.mark = set_difference + tag_mark ;
1243
+ }
1244
+ }
1245
+ }
1246
+
1247
+
1248
+ /* === Add up set differences for each column ======================= */
1249
+
1250
+ COLAMD_DEBUG3 (("** Adding set differences phase. **\n")) ;
1251
+
1252
+ /* for each column in pivot row */
1253
+ rp = &A [pivot_row_start] ;
1254
+ rp_end = rp + pivot_row_length ;
1255
+ while (rp < rp_end)
1256
+ {
1257
+ /* get a column */
1258
+ col = *rp++ ;
1259
+ COLAMD_ASSERT (Col[col].is_alive() && col != pivot_col) ;
1260
+ hash = 0 ;
1261
+ cur_score = 0 ;
1262
+ cp = &A [Col [col].start] ;
1263
+ /* compact the column */
1264
+ new_cp = cp ;
1265
+ cp_end = cp + Col [col].length ;
1266
+
1267
+ COLAMD_DEBUG4 (("Adding set diffs for Col: %d.\n", col)) ;
1268
+
1269
+ while (cp < cp_end)
1270
+ {
1271
+ /* get a row */
1272
+ row = *cp++ ;
1273
+ COLAMD_ASSERT(row >= 0 && row < n_row) ;
1274
+ /* skip if dead */
1275
+ if (Row [row].is_dead())
1276
+ {
1277
+ continue ;
1278
+ }
1279
+ row_mark = Row [row].shared2.mark ;
1280
+ COLAMD_ASSERT (row_mark > tag_mark) ;
1281
+ /* compact the column */
1282
+ *new_cp++ = row ;
1283
+ /* compute hash function */
1284
+ hash += row ;
1285
+ /* add set difference */
1286
+ cur_score += row_mark - tag_mark ;
1287
+ /* integer overflow... */
1288
+ cur_score = numext::mini(cur_score, n_col) ;
1289
+ }
1290
+
1291
+ /* recompute the column's length */
1292
+ Col [col].length = (IndexType) (new_cp - &A [Col [col].start]) ;
1293
+
1294
+ /* === Further mass elimination ================================= */
1295
+
1296
+ if (Col [col].length == 0)
1297
+ {
1298
+ COLAMD_DEBUG4 (("further mass elimination. Col: %d\n", col)) ;
1299
+ /* nothing left but the pivot row in this column */
1300
+ Col[col].kill_principal() ;
1301
+ pivot_row_degree -= Col [col].shared1.thickness ;
1302
+ COLAMD_ASSERT (pivot_row_degree >= 0) ;
1303
+ /* order it */
1304
+ Col [col].shared2.order = k ;
1305
+ /* increment order count by column thickness */
1306
+ k += Col [col].shared1.thickness ;
1307
+ }
1308
+ else
1309
+ {
1310
+ /* === Prepare for supercolumn detection ==================== */
1311
+
1312
+ COLAMD_DEBUG4 (("Preparing supercol detection for Col: %d.\n", col)) ;
1313
+
1314
+ /* save score so far */
1315
+ Col [col].shared2.score = cur_score ;
1316
+
1317
+ /* add column to hash table, for supercolumn detection */
1318
+ hash %= n_col + 1 ;
1319
+
1320
+ COLAMD_DEBUG4 ((" Hash = %d, n_col = %d.\n", hash, n_col)) ;
1321
+ COLAMD_ASSERT (hash <= n_col) ;
1322
+
1323
+ head_column = head [hash] ;
1324
+ if (head_column > Empty)
1325
+ {
1326
+ /* degree list "hash" is non-empty, use prev (shared3) of */
1327
+ /* first column in degree list as head of hash bucket */
1328
+ first_col = Col [head_column].shared3.headhash ;
1329
+ Col [head_column].shared3.headhash = col ;
1330
+ }
1331
+ else
1332
+ {
1333
+ /* degree list "hash" is empty, use head as hash bucket */
1334
+ first_col = - (head_column + 2) ;
1335
+ head [hash] = - (col + 2) ;
1336
+ }
1337
+ Col [col].shared4.hash_next = first_col ;
1338
+
1339
+ /* save hash function in Col [col].shared3.hash */
1340
+ Col [col].shared3.hash = (IndexType) hash ;
1341
+ COLAMD_ASSERT (Col[col].is_alive()) ;
1342
+ }
1343
+ }
1344
+
1345
+ /* The approximate external column degree is now computed. */
1346
+
1347
+ /* === Supercolumn detection ======================================== */
1348
+
1349
+ COLAMD_DEBUG3 (("** Supercolumn detection phase. **\n")) ;
1350
+
1351
+ Colamd::detect_super_cols (Col, A, head, pivot_row_start, pivot_row_length) ;
1352
+
1353
+ /* === Kill the pivotal column ====================================== */
1354
+
1355
+ Col[pivot_col].kill_principal() ;
1356
+
1357
+ /* === Clear mark =================================================== */
1358
+
1359
+ tag_mark += (max_deg + 1) ;
1360
+ if (tag_mark >= max_mark)
1361
+ {
1362
+ COLAMD_DEBUG2 (("clearing tag_mark\n")) ;
1363
+ tag_mark = Colamd::clear_mark (n_row, Row) ;
1364
+ }
1365
+
1366
+ /* === Finalize the new pivot row, and column scores ================ */
1367
+
1368
+ COLAMD_DEBUG3 (("** Finalize scores phase. **\n")) ;
1369
+
1370
+ /* for each column in pivot row */
1371
+ rp = &A [pivot_row_start] ;
1372
+ /* compact the pivot row */
1373
+ new_rp = rp ;
1374
+ rp_end = rp + pivot_row_length ;
1375
+ while (rp < rp_end)
1376
+ {
1377
+ col = *rp++ ;
1378
+ /* skip dead columns */
1379
+ if (Col[col].is_dead())
1380
+ {
1381
+ continue ;
1382
+ }
1383
+ *new_rp++ = col ;
1384
+ /* add new pivot row to column */
1385
+ A [Col [col].start + (Col [col].length++)] = pivot_row ;
1386
+
1387
+ /* retrieve score so far and add on pivot row's degree. */
1388
+ /* (we wait until here for this in case the pivot */
1389
+ /* row's degree was reduced due to mass elimination). */
1390
+ cur_score = Col [col].shared2.score + pivot_row_degree ;
1391
+
1392
+ /* calculate the max possible score as the number of */
1393
+ /* external columns minus the 'k' value minus the */
1394
+ /* columns thickness */
1395
+ max_score = n_col - k - Col [col].shared1.thickness ;
1396
+
1397
+ /* make the score the external degree of the union-of-rows */
1398
+ cur_score -= Col [col].shared1.thickness ;
1399
+
1400
+ /* make sure score is less or equal than the max score */
1401
+ cur_score = numext::mini(cur_score, max_score) ;
1402
+ COLAMD_ASSERT (cur_score >= 0) ;
1403
+
1404
+ /* store updated score */
1405
+ Col [col].shared2.score = cur_score ;
1406
+
1407
+ /* === Place column back in degree list ========================= */
1408
+
1409
+ COLAMD_ASSERT (min_score >= 0) ;
1410
+ COLAMD_ASSERT (min_score <= n_col) ;
1411
+ COLAMD_ASSERT (cur_score >= 0) ;
1412
+ COLAMD_ASSERT (cur_score <= n_col) ;
1413
+ COLAMD_ASSERT (head [cur_score] >= Empty) ;
1414
+ next_col = head [cur_score] ;
1415
+ Col [col].shared4.degree_next = next_col ;
1416
+ Col [col].shared3.prev = Empty ;
1417
+ if (next_col != Empty)
1418
+ {
1419
+ Col [next_col].shared3.prev = col ;
1420
+ }
1421
+ head [cur_score] = col ;
1422
+
1423
+ /* see if this score is less than current min */
1424
+ min_score = numext::mini(min_score, cur_score) ;
1425
+
1426
+ }
1427
+
1428
+ /* === Resurrect the new pivot row ================================== */
1429
+
1430
+ if (pivot_row_degree > 0)
1431
+ {
1432
+ /* update pivot row length to reflect any cols that were killed */
1433
+ /* during super-col detection and mass elimination */
1434
+ Row [pivot_row].start = pivot_row_start ;
1435
+ Row [pivot_row].length = (IndexType) (new_rp - &A[pivot_row_start]) ;
1436
+ Row [pivot_row].shared1.degree = pivot_row_degree ;
1437
+ Row [pivot_row].shared2.mark = 0 ;
1438
+ /* pivot row is no longer dead */
1439
+ }
1440
+ }
1441
+
1442
+ /* === All principal columns have now been ordered ====================== */
1443
+
1444
+ return (ngarbage) ;
1445
+ }
1446
+
1447
+
1448
+ /* ========================================================================== */
1449
+ /* === order_children ======================================================= */
1450
+ /* ========================================================================== */
1451
+
1452
+ /*
1453
+ The find_ordering routine has ordered all of the principal columns (the
1454
+ representatives of the supercolumns). The non-principal columns have not
1455
+ yet been ordered. This routine orders those columns by walking up the
1456
+ parent tree (a column is a child of the column which absorbed it). The
1457
+ final permutation vector is then placed in p [0 ... n_col-1], with p [0]
1458
+ being the first column, and p [n_col-1] being the last. It doesn't look
1459
+ like it at first glance, but be assured that this routine takes time linear
1460
+ in the number of columns. Although not immediately obvious, the time
1461
+ taken by this routine is O (n_col), that is, linear in the number of
1462
+ columns. Not user-callable.
1463
+ */
1464
+ template <typename IndexType>
1465
+ static inline void order_children
1466
+ (
1467
+ /* === Parameters ======================================================= */
1468
+
1469
+ IndexType n_col, /* number of columns of A */
1470
+ ColStructure<IndexType> Col [], /* of size n_col+1 */
1471
+ IndexType p [] /* p [0 ... n_col-1] is the column permutation*/
1472
+ )
1473
+ {
1474
+ /* === Local variables ================================================== */
1475
+
1476
+ IndexType i ; /* loop counter for all columns */
1477
+ IndexType c ; /* column index */
1478
+ IndexType parent ; /* index of column's parent */
1479
+ IndexType order ; /* column's order */
1480
+
1481
+ /* === Order each non-principal column ================================== */
1482
+
1483
+ for (i = 0 ; i < n_col ; i++)
1484
+ {
1485
+ /* find an un-ordered non-principal column */
1486
+ COLAMD_ASSERT (col_is_dead(Col, i)) ;
1487
+ if (!Col[i].is_dead_principal() && Col [i].shared2.order == Empty)
1488
+ {
1489
+ parent = i ;
1490
+ /* once found, find its principal parent */
1491
+ do
1492
+ {
1493
+ parent = Col [parent].shared1.parent ;
1494
+ } while (!Col[parent].is_dead_principal()) ;
1495
+
1496
+ /* now, order all un-ordered non-principal columns along path */
1497
+ /* to this parent. collapse tree at the same time */
1498
+ c = i ;
1499
+ /* get order of parent */
1500
+ order = Col [parent].shared2.order ;
1501
+
1502
+ do
1503
+ {
1504
+ COLAMD_ASSERT (Col [c].shared2.order == Empty) ;
1505
+
1506
+ /* order this column */
1507
+ Col [c].shared2.order = order++ ;
1508
+ /* collaps tree */
1509
+ Col [c].shared1.parent = parent ;
1510
+
1511
+ /* get immediate parent of this column */
1512
+ c = Col [c].shared1.parent ;
1513
+
1514
+ /* continue until we hit an ordered column. There are */
1515
+ /* guaranteed not to be anymore unordered columns */
1516
+ /* above an ordered column */
1517
+ } while (Col [c].shared2.order == Empty) ;
1518
+
1519
+ /* re-order the super_col parent to largest order for this group */
1520
+ Col [parent].shared2.order = order ;
1521
+ }
1522
+ }
1523
+
1524
+ /* === Generate the permutation ========================================= */
1525
+
1526
+ for (c = 0 ; c < n_col ; c++)
1527
+ {
1528
+ p [Col [c].shared2.order] = c ;
1529
+ }
1530
+ }
1531
+
1532
+
1533
+ /* ========================================================================== */
1534
+ /* === detect_super_cols ==================================================== */
1535
+ /* ========================================================================== */
1536
+
1537
+ /*
1538
+ Detects supercolumns by finding matches between columns in the hash buckets.
1539
+ Check amongst columns in the set A [row_start ... row_start + row_length-1].
1540
+ The columns under consideration are currently *not* in the degree lists,
1541
+ and have already been placed in the hash buckets.
1542
+
1543
+ The hash bucket for columns whose hash function is equal to h is stored
1544
+ as follows:
1545
+
1546
+ if head [h] is >= 0, then head [h] contains a degree list, so:
1547
+
1548
+ head [h] is the first column in degree bucket h.
1549
+ Col [head [h]].headhash gives the first column in hash bucket h.
1550
+
1551
+ otherwise, the degree list is empty, and:
1552
+
1553
+ -(head [h] + 2) is the first column in hash bucket h.
1554
+
1555
+ For a column c in a hash bucket, Col [c].shared3.prev is NOT a "previous
1556
+ column" pointer. Col [c].shared3.hash is used instead as the hash number
1557
+ for that column. The value of Col [c].shared4.hash_next is the next column
1558
+ in the same hash bucket.
1559
+
1560
+ Assuming no, or "few" hash collisions, the time taken by this routine is
1561
+ linear in the sum of the sizes (lengths) of each column whose score has
1562
+ just been computed in the approximate degree computation.
1563
+ Not user-callable.
1564
+ */
1565
+ template <typename IndexType>
1566
+ static void detect_super_cols
1567
+ (
1568
+ /* === Parameters ======================================================= */
1569
+
1570
+ ColStructure<IndexType> Col [], /* of size n_col+1 */
1571
+ IndexType A [], /* row indices of A */
1572
+ IndexType head [], /* head of degree lists and hash buckets */
1573
+ IndexType row_start, /* pointer to set of columns to check */
1574
+ IndexType row_length /* number of columns to check */
1575
+ )
1576
+ {
1577
+ /* === Local variables ================================================== */
1578
+
1579
+ IndexType hash ; /* hash value for a column */
1580
+ IndexType *rp ; /* pointer to a row */
1581
+ IndexType c ; /* a column index */
1582
+ IndexType super_c ; /* column index of the column to absorb into */
1583
+ IndexType *cp1 ; /* column pointer for column super_c */
1584
+ IndexType *cp2 ; /* column pointer for column c */
1585
+ IndexType length ; /* length of column super_c */
1586
+ IndexType prev_c ; /* column preceding c in hash bucket */
1587
+ IndexType i ; /* loop counter */
1588
+ IndexType *rp_end ; /* pointer to the end of the row */
1589
+ IndexType col ; /* a column index in the row to check */
1590
+ IndexType head_column ; /* first column in hash bucket or degree list */
1591
+ IndexType first_col ; /* first column in hash bucket */
1592
+
1593
+ /* === Consider each column in the row ================================== */
1594
+
1595
+ rp = &A [row_start] ;
1596
+ rp_end = rp + row_length ;
1597
+ while (rp < rp_end)
1598
+ {
1599
+ col = *rp++ ;
1600
+ if (Col[col].is_dead())
1601
+ {
1602
+ continue ;
1603
+ }
1604
+
1605
+ /* get hash number for this column */
1606
+ hash = Col [col].shared3.hash ;
1607
+ COLAMD_ASSERT (hash <= n_col) ;
1608
+
1609
+ /* === Get the first column in this hash bucket ===================== */
1610
+
1611
+ head_column = head [hash] ;
1612
+ if (head_column > Empty)
1613
+ {
1614
+ first_col = Col [head_column].shared3.headhash ;
1615
+ }
1616
+ else
1617
+ {
1618
+ first_col = - (head_column + 2) ;
1619
+ }
1620
+
1621
+ /* === Consider each column in the hash bucket ====================== */
1622
+
1623
+ for (super_c = first_col ; super_c != Empty ;
1624
+ super_c = Col [super_c].shared4.hash_next)
1625
+ {
1626
+ COLAMD_ASSERT (Col [super_c].is_alive()) ;
1627
+ COLAMD_ASSERT (Col [super_c].shared3.hash == hash) ;
1628
+ length = Col [super_c].length ;
1629
+
1630
+ /* prev_c is the column preceding column c in the hash bucket */
1631
+ prev_c = super_c ;
1632
+
1633
+ /* === Compare super_c with all columns after it ================ */
1634
+
1635
+ for (c = Col [super_c].shared4.hash_next ;
1636
+ c != Empty ; c = Col [c].shared4.hash_next)
1637
+ {
1638
+ COLAMD_ASSERT (c != super_c) ;
1639
+ COLAMD_ASSERT (Col[c].is_alive()) ;
1640
+ COLAMD_ASSERT (Col [c].shared3.hash == hash) ;
1641
+
1642
+ /* not identical if lengths or scores are different */
1643
+ if (Col [c].length != length ||
1644
+ Col [c].shared2.score != Col [super_c].shared2.score)
1645
+ {
1646
+ prev_c = c ;
1647
+ continue ;
1648
+ }
1649
+
1650
+ /* compare the two columns */
1651
+ cp1 = &A [Col [super_c].start] ;
1652
+ cp2 = &A [Col [c].start] ;
1653
+
1654
+ for (i = 0 ; i < length ; i++)
1655
+ {
1656
+ /* the columns are "clean" (no dead rows) */
1657
+ COLAMD_ASSERT ( cp1->is_alive() );
1658
+ COLAMD_ASSERT ( cp2->is_alive() );
1659
+ /* row indices will same order for both supercols, */
1660
+ /* no gather scatter necessary */
1661
+ if (*cp1++ != *cp2++)
1662
+ {
1663
+ break ;
1664
+ }
1665
+ }
1666
+
1667
+ /* the two columns are different if the for-loop "broke" */
1668
+ if (i != length)
1669
+ {
1670
+ prev_c = c ;
1671
+ continue ;
1672
+ }
1673
+
1674
+ /* === Got it! two columns are identical =================== */
1675
+
1676
+ COLAMD_ASSERT (Col [c].shared2.score == Col [super_c].shared2.score) ;
1677
+
1678
+ Col [super_c].shared1.thickness += Col [c].shared1.thickness ;
1679
+ Col [c].shared1.parent = super_c ;
1680
+ Col[c].kill_non_principal() ;
1681
+ /* order c later, in order_children() */
1682
+ Col [c].shared2.order = Empty ;
1683
+ /* remove c from hash bucket */
1684
+ Col [prev_c].shared4.hash_next = Col [c].shared4.hash_next ;
1685
+ }
1686
+ }
1687
+
1688
+ /* === Empty this hash bucket ======================================= */
1689
+
1690
+ if (head_column > Empty)
1691
+ {
1692
+ /* corresponding degree list "hash" is not empty */
1693
+ Col [head_column].shared3.headhash = Empty ;
1694
+ }
1695
+ else
1696
+ {
1697
+ /* corresponding degree list "hash" is empty */
1698
+ head [hash] = Empty ;
1699
+ }
1700
+ }
1701
+ }
1702
+
1703
+
1704
+ /* ========================================================================== */
1705
+ /* === garbage_collection =================================================== */
1706
+ /* ========================================================================== */
1707
+
1708
+ /*
1709
+ Defragments and compacts columns and rows in the workspace A. Used when
1710
+ all available memory has been used while performing row merging. Returns
1711
+ the index of the first free position in A, after garbage collection. The
1712
+ time taken by this routine is linear is the size of the array A, which is
1713
+ itself linear in the number of nonzeros in the input matrix.
1714
+ Not user-callable.
1715
+ */
1716
+ template <typename IndexType>
1717
+ static IndexType garbage_collection /* returns the new value of pfree */
1718
+ (
1719
+ /* === Parameters ======================================================= */
1720
+
1721
+ IndexType n_row, /* number of rows */
1722
+ IndexType n_col, /* number of columns */
1723
+ RowStructure<IndexType> Row [], /* row info */
1724
+ ColStructure<IndexType> Col [], /* column info */
1725
+ IndexType A [], /* A [0 ... Alen-1] holds the matrix */
1726
+ IndexType *pfree /* &A [0] ... pfree is in use */
1727
+ )
1728
+ {
1729
+ /* === Local variables ================================================== */
1730
+
1731
+ IndexType *psrc ; /* source pointer */
1732
+ IndexType *pdest ; /* destination pointer */
1733
+ IndexType j ; /* counter */
1734
+ IndexType r ; /* a row index */
1735
+ IndexType c ; /* a column index */
1736
+ IndexType length ; /* length of a row or column */
1737
+
1738
+ /* === Defragment the columns =========================================== */
1739
+
1740
+ pdest = &A[0] ;
1741
+ for (c = 0 ; c < n_col ; c++)
1742
+ {
1743
+ if (Col[c].is_alive())
1744
+ {
1745
+ psrc = &A [Col [c].start] ;
1746
+
1747
+ /* move and compact the column */
1748
+ COLAMD_ASSERT (pdest <= psrc) ;
1749
+ Col [c].start = (IndexType) (pdest - &A [0]) ;
1750
+ length = Col [c].length ;
1751
+ for (j = 0 ; j < length ; j++)
1752
+ {
1753
+ r = *psrc++ ;
1754
+ if (Row[r].is_alive())
1755
+ {
1756
+ *pdest++ = r ;
1757
+ }
1758
+ }
1759
+ Col [c].length = (IndexType) (pdest - &A [Col [c].start]) ;
1760
+ }
1761
+ }
1762
+
1763
+ /* === Prepare to defragment the rows =================================== */
1764
+
1765
+ for (r = 0 ; r < n_row ; r++)
1766
+ {
1767
+ if (Row[r].is_alive())
1768
+ {
1769
+ if (Row [r].length == 0)
1770
+ {
1771
+ /* this row is of zero length. cannot compact it, so kill it */
1772
+ COLAMD_DEBUG3 (("Defrag row kill\n")) ;
1773
+ Row[r].kill() ;
1774
+ }
1775
+ else
1776
+ {
1777
+ /* save first column index in Row [r].shared2.first_column */
1778
+ psrc = &A [Row [r].start] ;
1779
+ Row [r].shared2.first_column = *psrc ;
1780
+ COLAMD_ASSERT (Row[r].is_alive()) ;
1781
+ /* flag the start of the row with the one's complement of row */
1782
+ *psrc = ones_complement(r) ;
1783
+
1784
+ }
1785
+ }
1786
+ }
1787
+
1788
+ /* === Defragment the rows ============================================== */
1789
+
1790
+ psrc = pdest ;
1791
+ while (psrc < pfree)
1792
+ {
1793
+ /* find a negative number ... the start of a row */
1794
+ if (*psrc++ < 0)
1795
+ {
1796
+ psrc-- ;
1797
+ /* get the row index */
1798
+ r = ones_complement(*psrc) ;
1799
+ COLAMD_ASSERT (r >= 0 && r < n_row) ;
1800
+ /* restore first column index */
1801
+ *psrc = Row [r].shared2.first_column ;
1802
+ COLAMD_ASSERT (Row[r].is_alive()) ;
1803
+
1804
+ /* move and compact the row */
1805
+ COLAMD_ASSERT (pdest <= psrc) ;
1806
+ Row [r].start = (IndexType) (pdest - &A [0]) ;
1807
+ length = Row [r].length ;
1808
+ for (j = 0 ; j < length ; j++)
1809
+ {
1810
+ c = *psrc++ ;
1811
+ if (Col[c].is_alive())
1812
+ {
1813
+ *pdest++ = c ;
1814
+ }
1815
+ }
1816
+ Row [r].length = (IndexType) (pdest - &A [Row [r].start]) ;
1817
+
1818
+ }
1819
+ }
1820
+ /* ensure we found all the rows */
1821
+ COLAMD_ASSERT (debug_rows == 0) ;
1822
+
1823
+ /* === Return the new value of pfree ==================================== */
1824
+
1825
+ return ((IndexType) (pdest - &A [0])) ;
1826
+ }
1827
+
1828
+
1829
+ /* ========================================================================== */
1830
+ /* === clear_mark =========================================================== */
1831
+ /* ========================================================================== */
1832
+
1833
+ /*
1834
+ Clears the Row [].shared2.mark array, and returns the new tag_mark.
1835
+ Return value is the new tag_mark. Not user-callable.
1836
+ */
1837
+ template <typename IndexType>
1838
+ static inline IndexType clear_mark /* return the new value for tag_mark */
1839
+ (
1840
+ /* === Parameters ======================================================= */
1841
+
1842
+ IndexType n_row, /* number of rows in A */
1843
+ RowStructure<IndexType> Row [] /* Row [0 ... n_row-1].shared2.mark is set to zero */
1844
+ )
1845
+ {
1846
+ /* === Local variables ================================================== */
1847
+
1848
+ IndexType r ;
1849
+
1850
+ for (r = 0 ; r < n_row ; r++)
1851
+ {
1852
+ if (Row[r].is_alive())
1853
+ {
1854
+ Row [r].shared2.mark = 0 ;
1855
+ }
1856
+ }
1857
+ return (1) ;
1858
+ }
1859
+
1860
+ } // namespace Colamd
1861
+
1862
+ } // namespace internal
1863
+ #endif