PPL  0.12.1
Bit_Matrix.cc
Go to the documentation of this file.
00001 /* Bit_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 "Bit_Matrix.defs.hh"
00026 #include "globals.defs.hh"
00027 #include "swapping_sort.templates.hh"
00028 #include "C_Integer.hh"
00029 #include <iostream>
00030 #include <string>
00031 
00032 namespace PPL = Parma_Polyhedra_Library;
00033 
00034 PPL::Bit_Matrix&
00035 PPL::Bit_Matrix::operator=(const Bit_Matrix& y){
00036   rows = y.rows;
00037   row_size = y.row_size;
00038   PPL_ASSERT(OK());
00039   return *this;
00040 }
00041 
00042 void
00043 PPL::Bit_Matrix::sort_rows() {
00044   typedef std::vector<Bit_Row>::iterator Iter;
00045   // Sorting without removing duplicates.
00046   Iter first = rows.begin();
00047   Iter last = rows.end();
00048   Implementation::swapping_sort(first, last, Bit_Row_Less_Than());
00049   // Moving all the duplicate elements at the end of the vector.
00050   Iter new_last = Implementation::swapping_unique(first, last);
00051   // Removing duplicates.
00052   rows.erase(new_last, last);
00053   PPL_ASSERT(OK());
00054 }
00055 
00056 void
00057 PPL::Bit_Matrix::add_recycled_row(Bit_Row& row) {
00058   const dimension_type new_rows_size = rows.size() + 1;
00059   if (rows.capacity() < new_rows_size) {
00060     // Reallocation will take place.
00061     std::vector<Bit_Row> new_rows;
00062     new_rows.reserve(compute_capacity(new_rows_size, max_num_rows()));
00063     new_rows.insert(new_rows.end(), new_rows_size, Bit_Row());
00064     // Put the new row in place.
00065     dimension_type i = new_rows_size-1;
00066     new_rows[i].m_swap(row);
00067     // Steal the old rows.
00068     while (i-- > 0)
00069       new_rows[i].m_swap(rows[i]);
00070     // Put the new rows into place.
00071     using std::swap;
00072     swap(rows, new_rows);
00073   }
00074   else
00075     // Reallocation will NOT take place: append an empty row
00076     // and swap it with the new row.
00077     rows.insert(rows.end(), Bit_Row())->m_swap(row);
00078   PPL_ASSERT(OK());
00079 }
00080 
00081 void
00082 PPL::Bit_Matrix::transpose() {
00083   const Bit_Matrix& x = *this;
00084   const dimension_type nrows = num_rows();
00085   const dimension_type ncols = num_columns();
00086   Bit_Matrix tmp(ncols, nrows);
00087   for (dimension_type i = nrows; i-- > 0; )
00088     for (unsigned long j = x[i].last();
00089          j != C_Integer<unsigned long>::max; j = x[i].prev(j))
00090       tmp[j].set(i);
00091   m_swap(tmp);
00092   PPL_ASSERT(OK());
00093 }
00094 
00095 void
00096 PPL::Bit_Matrix::transpose_assign(const Bit_Matrix& y) {
00097   const dimension_type y_num_rows = y.num_rows();
00098   const dimension_type y_num_columns = y.num_columns();
00099   Bit_Matrix tmp(y_num_columns, y_num_rows);
00100   for (dimension_type i = y_num_rows; i-- > 0; )
00101     for (unsigned long j = y[i].last();
00102          j != C_Integer<unsigned long>::max; j = y[i].prev(j))
00103       tmp[j].set(i);
00104   m_swap(tmp);
00105   PPL_ASSERT(OK());
00106 }
00107 
00108 void
00109 PPL::Bit_Matrix::resize(dimension_type new_n_rows,
00110                        dimension_type new_n_columns) {
00111   PPL_ASSERT(OK());
00112   const dimension_type old_num_rows = num_rows();
00113   if (new_n_columns < row_size) {
00114     const dimension_type num_preserved_rows
00115       = std::min(old_num_rows, new_n_rows);
00116     Bit_Matrix& x = *this;
00117     for (dimension_type i = num_preserved_rows; i-- > 0; )
00118       x[i].clear_from(new_n_columns);
00119   }
00120   row_size = new_n_columns;
00121   if (new_n_rows > old_num_rows) {
00122     if (rows.capacity() < new_n_rows) {
00123       // Reallocation will take place.
00124       std::vector<Bit_Row> new_rows;
00125       new_rows.reserve(compute_capacity(new_n_rows, max_num_rows()));
00126       new_rows.insert(new_rows.end(), new_n_rows, Bit_Row());
00127       // Steal the old rows.
00128       for (dimension_type i = old_num_rows; i-- > 0; )
00129         new_rows[i].m_swap(rows[i]);
00130       // Put the new vector into place.
00131       using std::swap;
00132       swap(rows, new_rows);
00133     }
00134     else
00135       // Reallocation will NOT take place.
00136       rows.insert(rows.end(), new_n_rows - old_num_rows, Bit_Row());
00137   }
00138   else if (new_n_rows < old_num_rows)
00139     // Drop some rows.
00140     rows.resize(new_n_rows);
00141 
00142   PPL_ASSERT(OK());
00143 }
00144 
00145 void
00146 PPL::Bit_Matrix::ascii_dump(std::ostream& s) const {
00147   const Bit_Matrix& x = *this;
00148   const char separator = ' ';
00149   s << num_rows() << separator << 'x' << separator
00150     << num_columns() << "\n";
00151   for (dimension_type i = 0; i < num_rows(); ++i) {
00152     for (dimension_type j = 0; j < num_columns(); ++j)
00153       s << x[i][j] << separator;
00154     s << "\n";
00155   }
00156 }
00157 
00158 PPL_OUTPUT_DEFINITIONS_ASCII_ONLY(Bit_Matrix)
00159 
00160 bool
00161 PPL::Bit_Matrix::ascii_load(std::istream& s) {
00162   Bit_Matrix& x = *this;
00163   dimension_type nrows;
00164   dimension_type ncols;
00165   std::string str;
00166   if (!(s >> nrows))
00167     return false;
00168   if (!(s >> str) || str != "x")
00169     return false;
00170   if (!(s >> ncols))
00171     return false;
00172   resize(nrows, ncols);
00173 
00174   for (dimension_type i = 0; i < num_rows(); ++i)
00175     for (dimension_type j = 0; j < num_columns(); ++j) {
00176       int bit;
00177       if (!(s >> bit))
00178         return false;
00179       if (bit != 0)
00180         x[i].set(j);
00181       else
00182         x[i].clear(j);
00183     }
00184 
00185   // Check invariants.
00186   PPL_ASSERT(OK());
00187   return true;
00188 }
00189 
00190 PPL::memory_size_type
00191 PPL::Bit_Matrix::external_memory_in_bytes() const {
00192   memory_size_type n = rows.capacity() * sizeof(Dense_Row);
00193   for (dimension_type i = num_rows(); i-- > 0; )
00194     n += rows[i].external_memory_in_bytes();
00195   return n;
00196 }
00197 
00198 bool
00199 PPL::Bit_Matrix::OK() const {
00200 #ifndef NDEBUG
00201   using std::endl;
00202   using std::cerr;
00203 #endif
00204 
00205   const Bit_Matrix& x = *this;
00206   for (dimension_type i = num_rows(); i-- > 0; ) {
00207     const Bit_Row& row = x[i];
00208     if (!row.OK())
00209       return false;
00210     else if (row.last() != C_Integer<unsigned long>::max
00211              && row.last() >= row_size) {
00212 #ifndef NDEBUG
00213       cerr << "Bit_Matrix[" << i << "] is a row with too many bits!"
00214            << endl
00215            << "(row_size == " << row_size
00216            << ", row.last() == " << row.last() << ")"
00217            << endl;
00218 #endif
00219       return false;
00220     }
00221   }
00222   return true;
00223 }
00224 
00225 #ifndef NDEBUG
00226 bool
00227 PPL::Bit_Matrix::check_sorted() const {
00228   const Bit_Matrix& x = *this;
00229   for (dimension_type i = num_rows(); i-- > 1; )
00230     if (compare(x[i-1], x[i]) > 0)
00231       return false;
00232   return true;
00233 }
00234 #endif
00235 
00237 bool
00238 PPL::operator==(const Bit_Matrix& x, const Bit_Matrix& y) {
00239   const dimension_type x_num_rows = x.num_rows();
00240   if (x_num_rows != y.num_rows()
00241       || x.num_columns() != y.num_columns())
00242     return false;
00243   for (dimension_type i = x_num_rows; i-- > 0; )
00244     if (x[i] != y[i])
00245       return false;
00246   return true;
00247 }
00248