PPL  0.12.1
Sparse_Matrix.cc
Go to the documentation of this file.
00001 /* Sparse_Matrix class implementation (non-inline functions).
00002    Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
00003    Copyright (C) 2010-2012 BUGSENG srl (http://bugseng.com)
00004 
00005 This file is part of the Parma Polyhedra Library (PPL).
00006 
00007 The PPL is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 The PPL is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with this program; if not, write to the Free Software Foundation,
00019 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
00020 
00021 For the most up-to-date information see the Parma Polyhedra Library
00022 site: http://bugseng.com/products/ppl/ . */
00023 
00024 #include "ppl-config.h"
00025 #include "Sparse_Matrix.defs.hh"
00026 
00027 namespace PPL = Parma_Polyhedra_Library;
00028 
00029 PPL::Sparse_Matrix::Sparse_Matrix(dimension_type n, Flags row_flags)
00030   : rows(n), num_columns_(n) {
00031   for (dimension_type i = 0; i < rows.size(); ++i) {
00032     rows[i].set_flags(row_flags);
00033     rows[i].resize(num_columns_);
00034   }
00035   PPL_ASSERT(OK());
00036 }
00037 
00038 PPL::Sparse_Matrix::Sparse_Matrix(dimension_type num_rows,
00039                                   dimension_type num_columns,
00040                                   Flags row_flags)
00041   : rows(num_rows), num_columns_(num_columns) {
00042   for (dimension_type i = 0; i < rows.size(); ++i) {
00043     rows[i].set_flags(row_flags);
00044     rows[i].resize(num_columns_);
00045   }
00046   PPL_ASSERT(OK());
00047 }
00048 
00049 void
00050 PPL::Sparse_Matrix::resize(dimension_type num_rows,
00051                            dimension_type num_columns,
00052                            Flags row_flags) {
00053   const dimension_type old_num_rows = rows.size();
00054   rows.resize(num_rows);
00055   if (old_num_rows < num_rows) {
00056     for (dimension_type i = old_num_rows; i < num_rows; ++i) {
00057       rows[i].set_flags(row_flags);
00058       rows[i].resize(num_columns);
00059     }
00060     if (num_columns_ != num_columns) {
00061       num_columns_ = num_columns;
00062       for (dimension_type i = 0; i < old_num_rows; ++i)
00063         rows[i].resize(num_columns);
00064     }
00065   } else
00066     if (num_columns_ != num_columns) {
00067       num_columns_ = num_columns;
00068       for (dimension_type i = 0; i < num_rows; ++i)
00069         rows[i].resize(num_columns);
00070     }
00071   PPL_ASSERT(OK());
00072 }
00073 
00074 void
00075 PPL::Sparse_Matrix
00076 ::permute_columns(const std::vector<dimension_type>& cycles) {
00077   PPL_DIRTY_TEMP_COEFFICIENT(tmp);
00078   const dimension_type n = cycles.size();
00079   PPL_ASSERT(cycles[n - 1] == 0);
00080   for (dimension_type k = num_rows(); k-- > 0; ) {
00081     Sparse_Row& rows_k = (*this)[k];
00082     for (dimension_type i = 0, j = 0; i < n; i = ++j) {
00083       // Make `j' be the index of the next cycle terminator.
00084       while (cycles[j] != 0)
00085         ++j;
00086       // Cycles of length less than 2 are not allowed.
00087       PPL_ASSERT(j - i >= 2);
00088       if (j - i == 2)
00089         // For cycles of length 2 no temporary is needed, just a swap.
00090         rows_k.m_swap(cycles[i], cycles[i + 1]);
00091       else {
00092         // Longer cycles need a temporary.
00093         tmp = rows_k.get(cycles[j - 1]);
00094         for (dimension_type l = (j - 1); l > i; --l)
00095           rows_k.m_swap(cycles[l-1], cycles[l]);
00096         if (tmp == 0)
00097           rows_k.reset(cycles[i]);
00098         else {
00099           using std::swap;
00100           swap(tmp, rows_k[cycles[i]]);
00101         }
00102       }
00103     }
00104   }
00105 }
00106 
00107 void
00108 PPL::Sparse_Matrix::add_zero_columns(dimension_type n, dimension_type i) {
00109   for (dimension_type j = rows.size(); j-- > 0; )
00110     rows[j].add_zeroes_and_shift(n, i);
00111   num_columns_ += n;
00112   PPL_ASSERT(OK());
00113 }
00114 
00115 void
00116 PPL::Sparse_Matrix::remove_column(dimension_type i) {
00117   for (dimension_type j = rows.size(); j-- > 0; )
00118     rows[j].delete_element_and_shift(i);
00119   --num_columns_;
00120   PPL_ASSERT(OK());
00121 }
00122 
00123 void
00124 PPL::Sparse_Matrix::ascii_dump(std::ostream& s) const {
00125   s << num_rows() << " x ";
00126   s << num_columns() << "\n";
00127   for (const_iterator i = begin(), i_end = end(); i !=i_end; ++i)
00128     i->ascii_dump(s);
00129 }
00130 
00131 PPL_OUTPUT_DEFINITIONS_ASCII_ONLY(Sparse_Matrix)
00132 
00133 bool
00134 PPL::Sparse_Matrix::ascii_load(std::istream& s) {
00135   std::string str;
00136   dimension_type new_num_rows;
00137   dimension_type new_num_cols;
00138   if (!(s >> new_num_rows))
00139     return false;
00140   if (!(s >> str) || str != "x")
00141     return false;
00142   if (!(s >> new_num_cols))
00143     return false;
00144 
00145   for (iterator i = rows.begin(), i_end = rows.end(); i != i_end; ++i)
00146     i->clear();
00147 
00148   resize(new_num_rows, new_num_cols);
00149 
00150   for (dimension_type row = 0; row < new_num_rows; ++row)
00151     if (!rows[row].ascii_load(s))
00152       return false;
00153 
00154   // Check invariants.
00155   PPL_ASSERT(OK());
00156   return true;
00157 }
00158 
00159 PPL::memory_size_type
00160 PPL::Sparse_Matrix::external_memory_in_bytes() const {
00161   // Estimate the size of vector.
00162   memory_size_type n = rows.capacity() * sizeof(Sparse_Row);
00163   for (const_iterator i = begin(), i_end = end(); i != i_end; ++i)
00164     n += i->external_memory_in_bytes();
00165   return n;
00166 }
00167 
00168 bool
00169 PPL::Sparse_Matrix::OK() const {
00170   for (const_iterator i = begin(), i_end = end(); i != i_end; ++i)
00171     if (i->size() != num_columns_)
00172       return false;
00173   return true;
00174 }
00175 
00177 bool
00178 PPL::operator==(const Sparse_Matrix& x, const Sparse_Matrix& y) {
00179   if (x.num_rows() != y.num_rows())
00180     return false;
00181   if (x.num_columns() != y.num_columns())
00182     return false;
00183   for (dimension_type i = x.num_rows(); i-- > 0; )
00184     if (x[i] != y[i])
00185       return false;
00186   return true;
00187 }
00188 
00190 bool
00191 PPL::operator!=(const Sparse_Matrix& x, const Sparse_Matrix& y) {
00192   return !(x == y);
00193 }