Gael Guennebaud | 86ccd99 | 2008-11-05 13:47:55 +0000 | [diff] [blame] | 1 | // This file is part of Eigen, a lightweight C++ template library |
Benoit Jacob | 6347b1d | 2009-05-22 20:25:33 +0200 | [diff] [blame] | 2 | // for linear algebra. |
Gael Guennebaud | 86ccd99 | 2008-11-05 13:47:55 +0000 | [diff] [blame] | 3 | // |
Gael Guennebaud | 22c7609 | 2011-03-22 11:58:22 +0100 | [diff] [blame] | 4 | // Copyright (C) 2008-2011 Gael Guennebaud <gael.guennebaud@inria.fr> |
Gael Guennebaud | 86ccd99 | 2008-11-05 13:47:55 +0000 | [diff] [blame] | 5 | // |
Benoit Jacob | 69124cf | 2012-07-13 14:42:47 -0400 | [diff] [blame] | 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/. |
Gael Guennebaud | 86ccd99 | 2008-11-05 13:47:55 +0000 | [diff] [blame] | 9 | |
| 10 | #ifndef EIGEN_TESTSPARSE_H |
Gael Guennebaud | 70df09b | 2011-10-24 09:31:33 +0200 | [diff] [blame] | 11 | #define EIGEN_TESTSPARSE_H |
Gael Guennebaud | 86ccd99 | 2008-11-05 13:47:55 +0000 | [diff] [blame] | 12 | |
Gael Guennebaud | 32124bc | 2011-01-27 17:36:58 +0100 | [diff] [blame] | 13 | #define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET |
| 14 | |
Gael Guennebaud | 6a72260 | 2009-01-23 12:26:32 +0000 | [diff] [blame] | 15 | #include "main.h" |
| 16 | |
Gael Guennebaud | 42e2578 | 2011-08-19 14:18:05 +0200 | [diff] [blame] | 17 | #ifdef min |
| 18 | #undef min |
| 19 | #endif |
| 20 | |
| 21 | #ifdef max |
| 22 | #undef max |
| 23 | #endif |
| 24 | |
Gael Guennebaud | 4e8047c | 2019-02-20 13:59:34 +0100 | [diff] [blame] | 25 | #include <unordered_map> |
Gael Guennebaud | 6a72260 | 2009-01-23 12:26:32 +0000 | [diff] [blame] | 26 | #define EIGEN_UNORDERED_MAP_SUPPORT |
Gael Guennebaud | 4e8047c | 2019-02-20 13:59:34 +0100 | [diff] [blame] | 27 | |
Gael Guennebaud | 86ccd99 | 2008-11-05 13:47:55 +0000 | [diff] [blame] | 28 | #include <Eigen/Cholesky> |
| 29 | #include <Eigen/LU> |
| 30 | #include <Eigen/Sparse> |
| 31 | |
Antonio Sánchez | 46e9cdb | 2023-12-05 21:22:55 +0000 | [diff] [blame] | 32 | enum { ForceNonZeroDiag = 1, MakeLowerTriangular = 2, MakeUpperTriangular = 4, ForceRealDiag = 8 }; |
Gael Guennebaud | 86ccd99 | 2008-11-05 13:47:55 +0000 | [diff] [blame] | 33 | |
| 34 | /* Initializes both a sparse and dense matrix with same random values, |
| 35 | * and a ratio of \a density non zero entries. |
| 36 | * \param flags is a union of ForceNonZeroDiag, MakeLowerTriangular and MakeUpperTriangular |
| 37 | * allowing to control the shape of the matrix. |
| 38 | * \param zeroCoords and nonzeroCoords allows to get the coordinate lists of the non zero, |
| 39 | * and zero coefficients respectively. |
| 40 | */ |
Antonio Sánchez | 46e9cdb | 2023-12-05 21:22:55 +0000 | [diff] [blame] | 41 | template <typename Scalar, int Opt1, int Opt2, typename StorageIndex> |
| 42 | void initSparse(double density, Matrix<Scalar, Dynamic, Dynamic, Opt1>& refMat, |
| 43 | SparseMatrix<Scalar, Opt2, StorageIndex>& sparseMat, int flags = 0, |
| 44 | std::vector<Matrix<StorageIndex, 2, 1> >* zeroCoords = 0, |
| 45 | std::vector<Matrix<StorageIndex, 2, 1> >* nonzeroCoords = 0) { |
| 46 | enum { IsRowMajor = SparseMatrix<Scalar, Opt2, StorageIndex>::IsRowMajor }; |
Gael Guennebaud | 2829314 | 2009-05-04 14:25:12 +0000 | [diff] [blame] | 47 | sparseMat.setZero(); |
Antonio Sánchez | 46e9cdb | 2023-12-05 21:22:55 +0000 | [diff] [blame] | 48 | // sparseMat.reserve(int(refMat.rows()*refMat.cols()*density)); |
Erik Schultheis | d271a7d | 2022-01-26 18:16:19 +0000 | [diff] [blame] | 49 | int nnz = static_cast<int>((1.5 * density) * static_cast<double>(IsRowMajor ? refMat.cols() : refMat.rows())); |
| 50 | sparseMat.reserve(VectorXi::Constant(IsRowMajor ? refMat.rows() : refMat.cols(), nnz)); |
Erik Schultheis | b0fb541 | 2021-11-18 18:33:31 +0000 | [diff] [blame] | 51 | |
| 52 | Index insert_count = 0; |
Antonio Sánchez | 46e9cdb | 2023-12-05 21:22:55 +0000 | [diff] [blame] | 53 | for (Index j = 0; j < sparseMat.outerSize(); j++) { |
| 54 | // sparseMat.startVec(j); |
| 55 | for (Index i = 0; i < sparseMat.innerSize(); i++) { |
Gael Guennebaud | b47ef14 | 2014-07-08 16:47:11 +0200 | [diff] [blame] | 56 | Index ai(i), aj(j); |
Antonio Sánchez | 46e9cdb | 2023-12-05 21:22:55 +0000 | [diff] [blame] | 57 | if (IsRowMajor) std::swap(ai, aj); |
| 58 | Scalar v = (internal::random<double>(0, 1) < density) ? internal::random<Scalar>() : Scalar(0); |
| 59 | if ((flags & ForceNonZeroDiag) && (i == j)) { |
Gael Guennebaud | b986c14 | 2015-08-04 16:12:16 +0200 | [diff] [blame] | 60 | // FIXME: the following is too conservative |
Antonio Sánchez | 46e9cdb | 2023-12-05 21:22:55 +0000 | [diff] [blame] | 61 | v = internal::random<Scalar>() * Scalar(3.); |
| 62 | v = v * v; |
| 63 | if (numext::real(v) > 0) |
| 64 | v += Scalar(5); |
| 65 | else |
| 66 | v -= Scalar(5); |
Gael Guennebaud | 86ccd99 | 2008-11-05 13:47:55 +0000 | [diff] [blame] | 67 | } |
Antonio Sánchez | 46e9cdb | 2023-12-05 21:22:55 +0000 | [diff] [blame] | 68 | if ((flags & MakeLowerTriangular) && aj > ai) |
Gael Guennebaud | 86ccd99 | 2008-11-05 13:47:55 +0000 | [diff] [blame] | 69 | v = Scalar(0); |
Antonio Sánchez | 46e9cdb | 2023-12-05 21:22:55 +0000 | [diff] [blame] | 70 | else if ((flags & MakeUpperTriangular) && aj < ai) |
Gael Guennebaud | 86ccd99 | 2008-11-05 13:47:55 +0000 | [diff] [blame] | 71 | v = Scalar(0); |
Gael Guennebaud | 8710bd2 | 2010-06-02 13:32:13 +0200 | [diff] [blame] | 72 | |
Antonio Sánchez | 46e9cdb | 2023-12-05 21:22:55 +0000 | [diff] [blame] | 73 | if ((flags & ForceRealDiag) && (i == j)) v = numext::real(v); |
Gael Guennebaud | 8710bd2 | 2010-06-02 13:32:13 +0200 | [diff] [blame] | 74 | |
Antonio Sánchez | 46e9cdb | 2023-12-05 21:22:55 +0000 | [diff] [blame] | 75 | if (!numext::is_exactly_zero(v)) { |
| 76 | // sparseMat.insertBackByOuterInner(j,i) = v; |
| 77 | sparseMat.insertByOuterInner(j, i) = v; |
Erik Schultheis | b0fb541 | 2021-11-18 18:33:31 +0000 | [diff] [blame] | 78 | ++insert_count; |
Antonio Sánchez | 46e9cdb | 2023-12-05 21:22:55 +0000 | [diff] [blame] | 79 | if (nonzeroCoords) nonzeroCoords->push_back(Matrix<StorageIndex, 2, 1>(ai, aj)); |
| 80 | } else if (zeroCoords) { |
| 81 | zeroCoords->push_back(Matrix<StorageIndex, 2, 1>(ai, aj)); |
Gael Guennebaud | 86ccd99 | 2008-11-05 13:47:55 +0000 | [diff] [blame] | 82 | } |
Antonio Sánchez | 46e9cdb | 2023-12-05 21:22:55 +0000 | [diff] [blame] | 83 | refMat(ai, aj) = v; |
Erik Schultheis | b0fb541 | 2021-11-18 18:33:31 +0000 | [diff] [blame] | 84 | |
| 85 | // make sure we only insert as many as the sparse matrix supports |
Antonio Sánchez | 46e9cdb | 2023-12-05 21:22:55 +0000 | [diff] [blame] | 86 | if (insert_count == NumTraits<StorageIndex>::highest()) return; |
Gael Guennebaud | 86ccd99 | 2008-11-05 13:47:55 +0000 | [diff] [blame] | 87 | } |
| 88 | } |
Antonio Sánchez | 46e9cdb | 2023-12-05 21:22:55 +0000 | [diff] [blame] | 89 | // sparseMat.finalize(); |
Gael Guennebaud | 86ccd99 | 2008-11-05 13:47:55 +0000 | [diff] [blame] | 90 | } |
| 91 | |
Antonio Sánchez | 46e9cdb | 2023-12-05 21:22:55 +0000 | [diff] [blame] | 92 | template <typename Scalar, int Options, typename Index> |
| 93 | void initSparse(double density, Matrix<Scalar, Dynamic, 1>& refVec, SparseVector<Scalar, Options, Index>& sparseVec, |
| 94 | std::vector<int>* zeroCoords = 0, std::vector<int>* nonzeroCoords = 0) { |
| 95 | sparseVec.reserve(int(refVec.size() * density)); |
Gael Guennebaud | 709e903 | 2009-01-07 17:01:57 +0000 | [diff] [blame] | 96 | sparseVec.setZero(); |
Antonio Sánchez | 46e9cdb | 2023-12-05 21:22:55 +0000 | [diff] [blame] | 97 | for (int i = 0; i < refVec.size(); i++) { |
| 98 | Scalar v = (internal::random<double>(0, 1) < density) ? internal::random<Scalar>() : Scalar(0); |
| 99 | if (!numext::is_exactly_zero(v)) { |
Gael Guennebaud | 2829314 | 2009-05-04 14:25:12 +0000 | [diff] [blame] | 100 | sparseVec.insertBack(i) = v; |
Antonio Sánchez | 46e9cdb | 2023-12-05 21:22:55 +0000 | [diff] [blame] | 101 | if (nonzeroCoords) nonzeroCoords->push_back(i); |
| 102 | } else if (zeroCoords) |
| 103 | zeroCoords->push_back(i); |
Gael Guennebaud | 709e903 | 2009-01-07 17:01:57 +0000 | [diff] [blame] | 104 | refVec[i] = v; |
| 105 | } |
| 106 | } |
| 107 | |
Antonio Sánchez | 46e9cdb | 2023-12-05 21:22:55 +0000 | [diff] [blame] | 108 | template <typename Scalar, int Options, typename Index> |
| 109 | void initSparse(double density, Matrix<Scalar, 1, Dynamic>& refVec, SparseVector<Scalar, Options, Index>& sparseVec, |
| 110 | std::vector<int>* zeroCoords = 0, std::vector<int>* nonzeroCoords = 0) { |
| 111 | sparseVec.reserve(int(refVec.size() * density)); |
Gael Guennebaud | 98ce445 | 2013-03-06 11:58:22 +0100 | [diff] [blame] | 112 | sparseVec.setZero(); |
Antonio Sánchez | 46e9cdb | 2023-12-05 21:22:55 +0000 | [diff] [blame] | 113 | for (int i = 0; i < refVec.size(); i++) { |
| 114 | Scalar v = (internal::random<double>(0, 1) < density) ? internal::random<Scalar>() : Scalar(0); |
| 115 | if (v != Scalar(0)) { |
Gael Guennebaud | 98ce445 | 2013-03-06 11:58:22 +0100 | [diff] [blame] | 116 | sparseVec.insertBack(i) = v; |
Antonio Sánchez | 46e9cdb | 2023-12-05 21:22:55 +0000 | [diff] [blame] | 117 | if (nonzeroCoords) nonzeroCoords->push_back(i); |
| 118 | } else if (zeroCoords) |
| 119 | zeroCoords->push_back(i); |
Gael Guennebaud | 98ce445 | 2013-03-06 11:58:22 +0100 | [diff] [blame] | 120 | refVec[i] = v; |
| 121 | } |
| 122 | } |
| 123 | |
Antonio Sánchez | 46e9cdb | 2023-12-05 21:22:55 +0000 | [diff] [blame] | 124 | #endif // EIGEN_TESTSPARSE_H |