00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <ppl-config.h>
00024
00025 #include "Matrix.defs.hh"
00026 #include "Row.defs.hh"
00027 #include <algorithm>
00028 #include <iostream>
00029 #include <string>
00030
00031 namespace PPL = Parma_Polyhedra_Library;
00032
00033 PPL::Matrix::Matrix(const dimension_type n_rows,
00034 const dimension_type n_columns,
00035 Row::Flags row_flags)
00036 :
00037 #ifdef NDEBUG
00038 rows(n_rows),
00039 #else
00040 rows(n_rows <= max_num_rows() ? n_rows : 0),
00041 #endif
00042 row_size(n_columns),
00043 row_capacity(compute_capacity(n_columns, max_num_columns())) {
00044 PPL_ASSERT(n_rows <= max_num_rows());
00045
00046 for (dimension_type i = 0; i < n_rows; ++i)
00047 rows[i].construct(n_columns, row_capacity, row_flags);
00048 PPL_ASSERT(OK());
00049 }
00050
00051 void
00052 PPL::Matrix::add_zero_rows(const dimension_type n, Row::Flags row_flags) {
00053 PPL_ASSERT(n > 0);
00054 PPL_ASSERT(n <= max_num_rows() - num_rows());
00055 const dimension_type old_num_rows = rows.size();
00056 const dimension_type new_num_rows = old_num_rows + n;
00057
00058 if (rows.capacity() < new_num_rows) {
00059
00060 std::vector<Row> new_rows;
00061 new_rows.reserve(compute_capacity(new_num_rows, max_num_rows()));
00062 new_rows.insert(new_rows.end(), new_num_rows, Row());
00063
00064 dimension_type i = new_num_rows;
00065 while (i-- > old_num_rows)
00066 new_rows[i].construct(row_size, row_capacity, row_flags);
00067
00068 ++i;
00069 while (i-- > 0)
00070 new_rows[i].swap(rows[i]);
00071
00072 std::swap(rows, new_rows);
00073 }
00074 else {
00075
00076 rows.insert(rows.end(), n, Row());
00077 for (dimension_type i = new_num_rows; i-- > old_num_rows; )
00078 rows[i].construct(row_size, row_capacity, row_flags);
00079 }
00080 }
00081
00082 void
00083 PPL::Matrix::add_zero_columns(const dimension_type n) {
00084 PPL_ASSERT(n > 0);
00085 PPL_ASSERT(n <= max_num_columns() - num_columns());
00086 const dimension_type num_rows = rows.size();
00087 const dimension_type new_num_columns = row_size + n;
00088
00089 if (new_num_columns <= row_capacity)
00090
00091 for (dimension_type i = num_rows; i-- > 0; )
00092 rows[i].expand_within_capacity(new_num_columns);
00093 else {
00094
00095
00096 const dimension_type new_row_capacity
00097 = compute_capacity(new_num_columns, max_num_columns());
00098 PPL_ASSERT(new_row_capacity <= max_num_columns());
00099 for (dimension_type i = num_rows; i-- > 0; ) {
00100 Row new_row(rows[i], new_num_columns, new_row_capacity);
00101 std::swap(rows[i], new_row);
00102 }
00103 row_capacity = new_row_capacity;
00104 }
00105
00106 row_size = new_num_columns;
00107 }
00108
00109 void
00110 PPL::Matrix::add_zero_rows_and_columns(const dimension_type n,
00111 const dimension_type m,
00112 Row::Flags row_flags) {
00113 PPL_ASSERT(n > 0);
00114 PPL_ASSERT(n <= max_num_rows() - num_rows());
00115 PPL_ASSERT(m > 0);
00116 PPL_ASSERT(m <= max_num_columns() - num_columns());
00117 const dimension_type old_num_rows = rows.size();
00118 const dimension_type new_num_rows = old_num_rows + n;
00119 const dimension_type new_num_columns = row_size + m;
00120
00121 if (new_num_columns <= row_capacity) {
00122
00123 if (rows.capacity() < new_num_rows) {
00124
00125 std::vector<Row> new_rows;
00126 new_rows.reserve(compute_capacity(new_num_rows, max_num_rows()));
00127 new_rows.insert(new_rows.end(), new_num_rows, Row());
00128
00129 dimension_type i = new_num_rows;
00130 while (i-- > old_num_rows)
00131 new_rows[i].construct(new_num_columns, row_capacity, row_flags);
00132
00133 ++i;
00134 while (i-- > 0) {
00135 rows[i].expand_within_capacity(new_num_columns);
00136 new_rows[i].swap(rows[i]);
00137 }
00138
00139 std::swap(rows, new_rows);
00140 }
00141 else {
00142
00143 rows.insert(rows.end(), n, Row());
00144
00145 dimension_type i = new_num_rows;
00146 while (i-- > old_num_rows)
00147 rows[i].construct(new_num_columns, row_capacity, row_flags);
00148
00149 ++i;
00150 while (i-- > 0)
00151 rows[i].expand_within_capacity(new_num_columns);
00152 }
00153 row_size = new_num_columns;
00154 }
00155 else {
00156
00157 Matrix new_matrix;
00158 new_matrix.rows.reserve(compute_capacity(new_num_rows, max_num_rows()));
00159 new_matrix.rows.insert(new_matrix.rows.end(), new_num_rows, Row());
00160
00161 new_matrix.row_size = new_num_columns;
00162 new_matrix.row_capacity = compute_capacity(new_num_columns,
00163 max_num_columns());
00164 dimension_type i = new_num_rows;
00165 while (i-- > old_num_rows)
00166 new_matrix.rows[i].construct(new_matrix.row_size,
00167 new_matrix.row_capacity,
00168 row_flags);
00169
00170 ++i;
00171 while (i-- > 0) {
00172 Row new_row(rows[i],
00173 new_matrix.row_size,
00174 new_matrix.row_capacity);
00175 std::swap(new_matrix.rows[i], new_row);
00176 }
00177
00178 swap(new_matrix);
00179 }
00180 }
00181
00182 void
00183 PPL::Matrix::add_recycled_row(Row& y) {
00184
00185
00186 PPL_ASSERT(y.OK(row_size, row_capacity));
00187 const dimension_type new_rows_size = rows.size() + 1;
00188 if (rows.capacity() < new_rows_size) {
00189
00190 std::vector<Row> new_rows;
00191 new_rows.reserve(compute_capacity(new_rows_size, max_num_rows()));
00192 new_rows.insert(new_rows.end(), new_rows_size, Row());
00193
00194 dimension_type i = new_rows_size-1;
00195 std::swap(new_rows[i], y);
00196
00197 while (i-- > 0)
00198 new_rows[i].swap(rows[i]);
00199
00200 std::swap(rows, new_rows);
00201 }
00202 else
00203
00204
00205
00206 std::swap(*rows.insert(rows.end(), Row()), y);
00207
00208 PPL_ASSERT(OK());
00209 }
00210
00211 void
00212 PPL::Matrix::resize_no_copy(const dimension_type new_n_rows,
00213 const dimension_type new_n_columns,
00214 Row::Flags row_flags) {
00215 dimension_type old_n_rows = rows.size();
00216
00217
00218
00219
00220
00221 if (new_n_rows > old_n_rows) {
00222 if (new_n_columns <= row_capacity) {
00223
00224 if (rows.capacity() < new_n_rows) {
00225
00226 std::vector<Row> new_rows;
00227 new_rows.reserve(compute_capacity(new_n_rows, max_num_rows()));
00228 new_rows.insert(new_rows.end(), new_n_rows, Row());
00229
00230
00231 dimension_type i = new_n_rows;
00232 while (i-- > old_n_rows)
00233 new_rows[i].construct(new_n_columns, row_capacity, row_flags);
00234
00235 ++i;
00236 while (i-- > 0)
00237 new_rows[i].swap(rows[i]);
00238
00239 std::swap(rows, new_rows);
00240 }
00241 else {
00242
00243 rows.insert(rows.end(), new_n_rows - old_n_rows, Row());
00244
00245
00246 for (dimension_type i = new_n_rows; i-- > old_n_rows; )
00247 rows[i].construct(new_n_columns, row_capacity, row_flags);
00248 }
00249 }
00250 else {
00251
00252 Matrix new_matrix(new_n_rows, new_n_columns, row_flags);
00253 swap(new_matrix);
00254 return;
00255 }
00256 }
00257 else if (new_n_rows < old_n_rows) {
00258
00259 rows.erase(rows.begin() + new_n_rows, rows.end());
00260 old_n_rows = new_n_rows;
00261 }
00262
00263 if (new_n_columns != row_size) {
00264 if (new_n_columns < row_size) {
00265
00266 for (dimension_type i = old_n_rows; i-- > 0; )
00267 rows[i].shrink(new_n_columns);
00268 }
00269 else
00270
00271 if (new_n_columns <= row_capacity)
00272
00273 for (dimension_type i = old_n_rows; i-- > 0; )
00274 rows[i].expand_within_capacity(new_n_columns);
00275 else {
00276
00277
00278 const dimension_type new_row_capacity
00279 = compute_capacity(new_n_columns, max_num_columns());
00280 for (dimension_type i = old_n_rows; i-- > 0; ) {
00281 Row new_row(new_n_columns, new_row_capacity, row_flags);
00282 std::swap(rows[i], new_row);
00283 }
00284 row_capacity = new_row_capacity;
00285 }
00286
00287 row_size = new_n_columns;
00288 }
00289 }
00290
00291 void
00292 PPL::Matrix::ascii_dump(std::ostream& s) const {
00293 const Matrix& x = *this;
00294 dimension_type x_num_rows = x.num_rows();
00295 dimension_type x_num_columns = x.num_columns();
00296 s << x_num_rows << " x " << x_num_columns << "\n";
00297 for (dimension_type i = 0; i < x_num_rows; ++i)
00298 x[i].ascii_dump(s);
00299 }
00300
00301 PPL_OUTPUT_DEFINITIONS_ASCII_ONLY(Matrix)
00302
00303 bool
00304 PPL::Matrix::ascii_load(std::istream& s) {
00305 Matrix& x = *this;
00306 std::string str;
00307 dimension_type x_num_rows;
00308 dimension_type x_num_cols;
00309 if (!(s >> x_num_rows))
00310 return false;
00311 if (!(s >> str) || str != "x")
00312 return false;
00313 if (!(s >> x_num_cols))
00314 return false;
00315
00316 resize_no_copy(x_num_rows, x_num_cols, Row::Flags());
00317
00318 for (dimension_type row = 0; row < x_num_rows; ++row)
00319 if (!x[row].ascii_load(s))
00320 return false;
00321
00322
00323 PPL_ASSERT(OK());
00324 return true;
00325 }
00326
00327 void
00328 PPL::Matrix::swap_columns(const dimension_type i, const dimension_type j) {
00329 PPL_ASSERT(i != j && i < num_columns() && j < num_columns());
00330 for (dimension_type k = num_rows(); k-- > 0; ) {
00331 Row& rows_k = rows[k];
00332 std::swap(rows_k[i], rows_k[j]);
00333 }
00334 }
00335
00336 void
00337 PPL::Matrix::remove_trailing_columns(const dimension_type n) {
00338 PPL_ASSERT(n > 0);
00339 PPL_ASSERT(n <= row_size);
00340 row_size -= n;
00341 for (dimension_type i = num_rows(); i-- > 0; )
00342 rows[i].shrink(row_size);
00343 }
00344
00345 void
00346 PPL::Matrix::permute_columns(const std::vector<dimension_type>& cycles) {
00347 PPL_DIRTY_TEMP_COEFFICIENT(tmp);
00348 const dimension_type n = cycles.size();
00349 PPL_ASSERT(cycles[n - 1] == 0);
00350 for (dimension_type k = num_rows(); k-- > 0; ) {
00351 Row& rows_k = rows[k];
00352 for (dimension_type i = 0, j = 0; i < n; i = ++j) {
00353
00354 while (cycles[j] != 0)
00355 ++j;
00356
00357 PPL_ASSERT(j - i >= 2);
00358 if (j - i == 2)
00359
00360 std::swap(rows_k[cycles[i]], rows_k[cycles[i+1]]);
00361 else {
00362
00363 std::swap(rows_k[cycles[j-1]], tmp);
00364 for (dimension_type l = j-1; l > i; --l)
00365 std::swap(rows_k[cycles[l-1]], rows_k[cycles[l]]);
00366 std::swap(tmp, rows_k[cycles[i]]);
00367 }
00368 }
00369 }
00370 }
00371
00373 bool
00374 PPL::operator==(const Matrix& x, const Matrix& y) {
00375 if (x.num_columns() != y.num_columns())
00376 return false;
00377 const dimension_type x_num_rows = x.num_rows();
00378 const dimension_type y_num_rows = y.num_rows();
00379 if (x_num_rows != y_num_rows)
00380 return false;
00381 for (dimension_type i = x_num_rows; i-- > 0; )
00382 if (x[i] != y[i])
00383 return false;
00384 return true;
00385 }
00386
00387 PPL::memory_size_type
00388 PPL::Matrix::external_memory_in_bytes() const {
00389 memory_size_type n = rows.capacity() * sizeof(Row);
00390 for (dimension_type i = num_rows(); i-- > 0; )
00391 n += rows[i].external_memory_in_bytes(row_capacity);
00392 return n;
00393 }
00394
00395 bool
00396 PPL::Matrix::OK() const {
00397 if (row_size > row_capacity) {
00398 #ifndef NDEBUG
00399 std::cerr << "Matrix completely broken: "
00400 << "row_capacity is " << row_capacity
00401 << ", row_size is " << row_size
00402 << std::endl;
00403 #endif
00404 return false;
00405 }
00406
00407 const Matrix& x = *this;
00408 for (dimension_type i = 0, n_rows = num_rows(); i < n_rows; ++i)
00409 if (!x[i].OK(row_size, row_capacity))
00410 return false;
00411
00412
00413 return true;
00414 }