// Copyright (c) 2005-2008 Inria Loria (France). /* * author: Bruno Levy, INRIA, project ALICE * website: http://www.loria.fr/~levy/software * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Scientific work that use this software can reference the website and * the following publication: * * @INPROCEEDINGS {levy:NMDGP:05, * AUTHOR = Bruno Levy, * TITLE = Numerical Methods for Digital Geometry Processing, * BOOKTITLE =Israel Korea Bi-National Conference, * YEAR=November 2005, * URL=http://www.loria.fr/~levy/php/article.php?pub=../publications/papers/2005/Numerics * } * * Laurent Saboret 01/2005: Change for CGAL: * - Added OpenNL namespace * - SparseMatrix is now a model of the SparseLinearAlgebraTraits_d::Matrix concept * * $URL$ * $Id$ * SPDX-License-Identifier: LGPL-3.0+ */ #ifndef __OPENNL_SPARSE_MATRIX__ #define __OPENNL_SPARSE_MATRIX__ #include #include #include #include #include namespace OpenNL { //________________________________________________________________ // Class SparseMatrix // Model of the SparseLinearAlgebraTraits_d::Matrix concept template class SparseMatrix { // Public types public: typedef T CoeffType ; // added for SparseLinearAlgebraTraits_d::Matrix concept typedef T NT; struct Coeff { Coeff() { } Coeff(unsigned int i, T val) : index(i), a(val) { } unsigned int index ; T a ; } ; //__________________________________________________ /** * A row or a column of a SparseMatrix. The row/column is * compressed, and stored in the form of a list of * (value,index) couples. */ class Row : public std::vector { typedef typename std::vector superclass ; public: /** a_{index} <- a_{index} + val */ void add_coef(unsigned int index, T val) { // search for coefficient in superclass vector for(typename superclass::iterator it = superclass::begin() ; it != superclass::end() ; it++) { if(it->index == index) { it->a += val ; // += return ; } } // coefficient doesn't exist yet if we reach this point superclass::push_back(Coeff(index, val)) ; } // a_{index} <- val // (added for SparseLinearAlgebraTraits_d::Matrix concept) // // Optimization: // - Caller can optimize this call by setting 'new_coef' to true // if the coefficient does not already exists in the matrix. void set_coef(unsigned int index, T val, bool new_coef) { if (!new_coef) { // search for coefficient in superclass vector for(typename superclass::iterator it = superclass::begin() ; it != superclass::end() ; it++) { if(it->index == index) { it->a = val ; // = return ; } } } // coefficient doesn't exist yet if we reach this point superclass::push_back(Coeff(index, val)) ; } // return a_{index} (0 by default) // (added for SparseLinearAlgebraTraits_d::Matrix concept) T get_coef(unsigned int index) const { // search for coefficient in superclass vector for(typename superclass::const_iterator it = superclass::begin() ; it != superclass::end() ; it++) { if(it->index == index) return it->a ; // return value } // coefficient doesn't exist if we reach this point return 0 ; } } ; // Public operations public: //__________ constructors / destructor _____ // Create a square matrix initialized with zeros SparseMatrix(unsigned int dim) { CGAL_assertion(dim > 0); dimension_ = dim ; row_ = new Row[dimension_] ; } // Create a rectangular matrix initialized with zeros // (added for SparseLinearAlgebraTraits_d::Matrix concept) // WARNING: this class supports square matrices only SparseMatrix (unsigned int rows, unsigned int columns ) { CGAL_USE(rows); CGAL_assertion(rows == columns); CGAL_assertion(columns > 0); dimension_ = columns ; row_ = new Row[dimension_] ; } ~SparseMatrix() { delete[] row_ ; row_ = NULL ; } //___________ access ________________________ // Return the matrix dimension unsigned int dimension() const { return dimension_ ; } // Added for SparseLinearAlgebraTraits_d::Matrix concept: // Return the matrix number of rows unsigned int row_dimension() const { return dimension(); } // Return the matrix number of columns unsigned int column_dimension() const { return dimension(); } Row& row(unsigned int i) { CGAL_assertion(i < dimension_) ; return row_[i] ; } const Row& row(unsigned int i) const { CGAL_assertion(i < dimension_) ; return row_[i] ; } // Read access to 1 matrix coefficient // (added for SparseLinearAlgebraTraits_d::Matrix concept) // // Preconditions: // * 0 <= i < row_dimension() // * 0 <= j < column_dimension() NT get_coef (unsigned int i, unsigned int j) const { CGAL_assertion(i < dimension_) ; CGAL_assertion(j < dimension_) ; return row(i).get_coef(j) ; } // Write access to 1 matrix coefficient: a_ij <- a_ij + val // // Preconditions: // * 0 <= i < row_dimension() // * 0 <= j < column_dimension() void add_coef(unsigned int i, unsigned int j, T val) { CGAL_assertion(i < dimension_) ; CGAL_assertion(j < dimension_) ; row(i).add_coef(j, val) ; } // Write access to 1 matrix coefficient: a_ij <- val //(added for SparseLinearAlgebraTraits_d::Matrix concept) // // Optimization: // - Caller can optimize this call by setting 'new_coef' to true // if the coefficient does not already exists in the matrix. // // Preconditions: // - 0 <= i < row_dimension(). // - 0 <= j < column_dimension(). void set_coef(unsigned int i, unsigned int j, NT val, bool new_coef = false) { CGAL_assertion(i < dimension_) ; CGAL_assertion(j < dimension_) ; row(i).set_coef(j, val, new_coef) ; } /** * removes all the coefficients and frees the allocated * space. */ void clear() { for(unsigned int i=0; i void mult(const SparseMatrix& M, const FullVector& x, FullVector& y) { unsigned int N = M.dimension() ; CGAL_assertion(x.dimension() == N) ; CGAL_assertion(y.dimension() == N) ; for(unsigned int i=0; i::Row& R = M.row(i) ; for(unsigned int jj=0; jj