// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2026 Rasmus Munk Larsen // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. // SPDX-License-Identifier: MPL-2.0 #include "sparse.h" #include template void verify_is_permutation(const PermutationMatrix& perm) { typedef Matrix Vec; Vec sorted = perm.indices(); std::sort(sorted.data(), sorted.data() + sorted.size()); Vec expected = Vec::LinSpaced(perm.size(), 0, Idx(perm.size() - 1)); VERIFY_IS_EQUAL(sorted, expected); } template void test_colamd_uncompressed() { typedef int Idx; typedef SparseMatrix SpMat; const int n = 32; SpMat A(n, n); A.reserve(VectorXi::Constant(n, 5)); for (int j = 0; j < n; ++j) { A.insert(j, j) = Scalar(2) + Scalar(j); if (j > 0) A.insert(j - 1, j) = Scalar(-1); if (j + 1 < n) A.insert(j + 1, j) = Scalar(-1); } A.insert(0, n - 1) = Scalar(0.5); A.insert(n - 1, 0) = Scalar(0.25); VERIFY(!A.isCompressed()); // Regression for #649: COLAMD on uncompressed input used to silently corrupt // the permutation in release builds. PermutationMatrix perm_u, perm_c; COLAMDOrdering ord; ord(A, perm_u); verify_is_permutation(perm_u); SpMat B = A; B.makeCompressed(); ord(B, perm_c); verify_is_permutation(perm_c); VERIFY_IS_EQUAL(perm_u.indices(), perm_c.indices()); } void test_colamd_mixed_index_types() { typedef SparseMatrix SpMat; const int n = 8; SpMat A(n, n); A.reserve(VectorXi::Constant(n, 3)); for (int j = 0; j < n; ++j) { A.insert(j, j) = 2.0 + j; if (j > 0) A.insert(j - 1, j) = -1.0; if (j + 1 < n) A.insert(j + 1, j) = -1.0; } A.makeCompressed(); // COLAMDOrdering is a public API choice independent of the // source matrix's StorageIndex. Keep accepting mixed index types. PermutationMatrix perm; COLAMDOrdering ord; ord(A, perm); verify_is_permutation(perm); } template void test_amd_uncompressed() { typedef int Idx; typedef SparseMatrix SpMat; const int n = 24; SpMat A(n, n); A.reserve(VectorXi::Constant(n, 4)); for (int j = 0; j < n; ++j) { A.insert(j, j) = Scalar(2) + Scalar(j); if (j > 0) { A.insert(j - 1, j) = Scalar(-1); A.insert(j, j - 1) = Scalar(-1); } } VERIFY(!A.isCompressed()); PermutationMatrix perm; AMDOrdering ord; ord(A, perm); verify_is_permutation(perm); } EIGEN_DECLARE_TEST(sparse_ordering) { for (int i = 0; i < g_repeat; ++i) { CALL_SUBTEST_1(test_colamd_uncompressed()); CALL_SUBTEST_2(test_colamd_uncompressed >()); CALL_SUBTEST_3(test_amd_uncompressed()); CALL_SUBTEST_4(test_colamd_mixed_index_types()); } }