00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <ppl-config.h>
00025
00026 #include "Linear_System.defs.hh"
00027 #include "Coefficient.defs.hh"
00028 #include "Row.defs.hh"
00029 #include "Bit_Matrix.defs.hh"
00030 #include "Scalar_Products.defs.hh"
00031 #include <algorithm>
00032 #include <iostream>
00033 #include <string>
00034 #include <deque>
00035
00036 #include "swapping_sort.icc"
00037
00038 namespace PPL = Parma_Polyhedra_Library;
00039
00040 PPL::dimension_type
00041 PPL::Linear_System::num_lines_or_equalities() const {
00042 PPL_ASSERT(num_pending_rows() == 0);
00043 const Linear_System& x = *this;
00044 dimension_type n = 0;
00045 for (dimension_type i = num_rows(); i-- > 0; )
00046 if (x[i].is_line_or_equality())
00047 ++n;
00048 return n;
00049 }
00050
00051 void
00052 PPL::Linear_System::merge_rows_assign(const Linear_System& y) {
00053 PPL_ASSERT(row_size >= y.row_size);
00054
00055 PPL_ASSERT(check_sorted() && y.check_sorted());
00056 PPL_ASSERT(num_pending_rows() == 0 && y.num_pending_rows() == 0);
00057
00058 Linear_System& x = *this;
00059
00060
00061 std::vector<Row> tmp;
00062
00063 tmp.reserve(compute_capacity(x.num_rows() + y.num_rows(), max_num_rows()));
00064
00065 dimension_type xi = 0;
00066 dimension_type x_num_rows = x.num_rows();
00067 dimension_type yi = 0;
00068 dimension_type y_num_rows = y.num_rows();
00069
00070 while (xi < x_num_rows && yi < y_num_rows) {
00071 const int comp = compare(x[xi], y[yi]);
00072 if (comp <= 0) {
00073
00074 std::swap(x[xi++], *tmp.insert(tmp.end(), Linear_Row()));
00075 if (comp == 0)
00076
00077 ++yi;
00078 }
00079 else {
00080
00081 Linear_Row copy(y[yi++], row_size, row_capacity);
00082 std::swap(copy, *tmp.insert(tmp.end(), Linear_Row()));
00083 }
00084 }
00085
00086 if (xi < x_num_rows)
00087 while (xi < x_num_rows)
00088 std::swap(x[xi++], *tmp.insert(tmp.end(), Linear_Row()));
00089 else
00090 while (yi < y_num_rows) {
00091 Linear_Row copy(y[yi++], row_size, row_capacity);
00092 std::swap(copy, *tmp.insert(tmp.end(), Linear_Row()));
00093 }
00094
00095
00096 std::swap(tmp, rows);
00097
00098 unset_pending_rows();
00099 PPL_ASSERT(check_sorted());
00100 }
00101
00102 void
00103 PPL::Linear_System::set_rows_topology() {
00104 Linear_System& x = *this;
00105 if (is_necessarily_closed())
00106 for (dimension_type i = num_rows(); i-- > 0; )
00107 x[i].set_necessarily_closed();
00108 else
00109 for (dimension_type i = num_rows(); i-- > 0; )
00110 x[i].set_not_necessarily_closed();
00111 }
00112
00113 void
00114 PPL::Linear_System::ascii_dump(std::ostream& s) const {
00115
00116
00117
00118
00119 const Linear_System& x = *this;
00120 dimension_type x_num_rows = x.num_rows();
00121 dimension_type x_num_columns = x.num_columns();
00122 s << "topology " << (is_necessarily_closed()
00123 ? "NECESSARILY_CLOSED"
00124 : "NOT_NECESSARILY_CLOSED")
00125 << "\n"
00126 << x_num_rows << " x " << x_num_columns
00127 << (x.sorted ? "(sorted)" : "(not_sorted)")
00128 << "\n"
00129 << "index_first_pending " << x.first_pending_row()
00130 << "\n";
00131 for (dimension_type i = 0; i < x_num_rows; ++i)
00132 x[i].ascii_dump(s);
00133 }
00134
00135 PPL_OUTPUT_DEFINITIONS_ASCII_ONLY(Linear_System)
00136
00137 bool
00138 PPL::Linear_System::ascii_load(std::istream& s) {
00139 std::string str;
00140 if (!(s >> str) || str != "topology")
00141 return false;
00142 if (!(s >> str))
00143 return false;
00144 if (str == "NECESSARILY_CLOSED")
00145 set_necessarily_closed();
00146 else {
00147 if (str != "NOT_NECESSARILY_CLOSED")
00148 return false;
00149 set_not_necessarily_closed();
00150 }
00151
00152 dimension_type nrows;
00153 dimension_type ncols;
00154 if (!(s >> nrows))
00155 return false;
00156 if (!(s >> str) || str != "x")
00157 return false;
00158 if (!(s >> ncols))
00159 return false;
00160 resize_no_copy(nrows, ncols);
00161
00162 if (!(s >> str) || (str != "(sorted)" && str != "(not_sorted)"))
00163 return false;
00164 set_sorted(str == "(sorted)");
00165 dimension_type index;
00166 if (!(s >> str) || str != "index_first_pending")
00167 return false;
00168 if (!(s >> index))
00169 return false;
00170 set_index_first_pending_row(index);
00171
00172 Linear_System& x = *this;
00173 for (dimension_type row = 0; row < nrows; ++row)
00174 if (!x[row].ascii_load(s))
00175 return false;
00176
00177
00178 PPL_ASSERT(OK(true));
00179 return true;
00180 }
00181
00182 void
00183 PPL::Linear_System::insert(const Linear_Row& r) {
00184
00185
00186 PPL_ASSERT(r.check_strong_normalized());
00187 PPL_ASSERT(topology() == r.topology());
00188
00189 PPL_ASSERT(num_pending_rows() == 0);
00190
00191 const dimension_type old_num_rows = num_rows();
00192 const dimension_type old_num_columns = num_columns();
00193 const dimension_type r_size = r.size();
00194
00195
00196 if (r_size > old_num_columns) {
00197 add_zero_columns(r_size - old_num_columns);
00198 if (!is_necessarily_closed() && old_num_rows != 0)
00199
00200
00201 swap_columns(old_num_columns - 1, r_size - 1);
00202 add_row(r);
00203 }
00204 else if (r_size < old_num_columns) {
00205
00206 Linear_Row tmp_row(r, old_num_columns, row_capacity);
00207
00208 if (!is_necessarily_closed())
00209 std::swap(tmp_row[r_size - 1], tmp_row[old_num_columns - 1]);
00210 add_row(tmp_row);
00211 }
00212 else
00213
00214 add_row(r);
00215
00216
00217 PPL_ASSERT(num_pending_rows() == 0);
00218
00219
00220 PPL_ASSERT(OK(false));
00221 }
00222
00223 void
00224 PPL::Linear_System::insert_pending(const Linear_Row& r) {
00225
00226
00227 PPL_ASSERT(r.check_strong_normalized());
00228 PPL_ASSERT(topology() == r.topology());
00229
00230 const dimension_type old_num_rows = num_rows();
00231 const dimension_type old_num_columns = num_columns();
00232 const dimension_type r_size = r.size();
00233
00234
00235 if (r_size > old_num_columns) {
00236 add_zero_columns(r_size - old_num_columns);
00237 if (!is_necessarily_closed() && old_num_rows != 0)
00238
00239
00240 swap_columns(old_num_columns - 1, r_size - 1);
00241 add_pending_row(r);
00242 }
00243 else if (r_size < old_num_columns)
00244 if (is_necessarily_closed() || old_num_rows == 0)
00245 add_pending_row(Linear_Row(r, old_num_columns, row_capacity));
00246 else {
00247
00248
00249 Linear_Row tmp_row(r, old_num_columns, row_capacity);
00250 std::swap(tmp_row[r_size - 1], tmp_row[old_num_columns - 1]);
00251 add_pending_row(tmp_row);
00252 }
00253 else
00254
00255 add_pending_row(r);
00256
00257
00258 PPL_ASSERT(num_pending_rows() > 0);
00259
00260
00261 PPL_ASSERT(OK(false));
00262 }
00263
00264 void
00265 PPL::Linear_System::add_pending_rows(const Linear_System& y) {
00266 Linear_System& x = *this;
00267 PPL_ASSERT(x.row_size == y.row_size);
00268
00269 const dimension_type x_n_rows = x.num_rows();
00270 const dimension_type y_n_rows = y.num_rows();
00271
00272 const bool was_sorted = sorted;
00273 add_zero_rows(y_n_rows, Linear_Row::Flags(row_topology));
00274 sorted = was_sorted;
00275
00276
00277 for (dimension_type i = y_n_rows; i-- > 0; ) {
00278 Row copy(y[i], x.row_size, x.row_capacity);
00279 std::swap(copy, x[x_n_rows+i]);
00280 }
00281
00282
00283 PPL_ASSERT(OK(false));
00284 }
00285
00286 void
00287 PPL::Linear_System::add_rows(const Linear_System& y) {
00288 PPL_ASSERT(num_pending_rows() == 0);
00289
00290
00291 if (y.has_no_rows())
00292 return;
00293
00294
00295 if (is_sorted()) {
00296 if (!y.is_sorted() || y.num_pending_rows() > 0)
00297 set_sorted(false);
00298 else {
00299
00300 const dimension_type n_rows = num_rows();
00301 if (n_rows > 0)
00302 set_sorted(compare((*this)[n_rows-1], y[0]) <= 0);
00303 }
00304 }
00305
00306
00307 add_pending_rows(y);
00308
00309 unset_pending_rows();
00310
00311
00312
00313 PPL_ASSERT(OK(false));
00314 }
00315
00316 void
00317 PPL::Linear_System::sort_rows() {
00318 const dimension_type num_pending = num_pending_rows();
00319
00320 sort_rows(0, first_pending_row());
00321 set_index_first_pending_row(num_rows() - num_pending);
00322 sorted = true;
00323
00324
00325 PPL_ASSERT(OK(false));
00326 }
00327
00328 void
00329 PPL::Linear_System::sort_rows(const dimension_type first_row,
00330 const dimension_type last_row) {
00331 PPL_ASSERT(first_row <= last_row && last_row <= num_rows());
00332
00333 PPL_ASSERT(first_row >= first_pending_row()
00334 || last_row <= first_pending_row());
00335
00336 const dimension_type num_elems = last_row - first_row;
00337 if (num_elems < 2)
00338 return;
00339
00340
00341
00342 typedef std::vector<Row> Cont;
00343 Indirect_Sort_Compare<Cont, Row_Less_Than> sort_cmp(rows, first_row);
00344 Indirect_Unique_Compare<Cont> unique_cmp(rows, first_row);
00345 Indirect_Swapper<Cont> swapper(rows, first_row);
00346
00347 const dimension_type num_duplicates
00348 = indirect_sort_and_unique(num_elems, sort_cmp, unique_cmp, swapper);
00349
00350 if (num_duplicates > 0)
00351 rows.erase(rows.begin() + (last_row - num_duplicates),
00352 rows.begin() + last_row);
00353
00354
00355
00356 }
00357
00358 void
00359 PPL::Linear_System::add_row(const Linear_Row& r) {
00360
00361
00362 PPL_ASSERT(r.check_strong_normalized());
00363 PPL_ASSERT(r.size() == row_size);
00364
00365 PPL_ASSERT(num_pending_rows() == 0);
00366
00367 const bool was_sorted = is_sorted();
00368
00369 Matrix::add_row(r);
00370
00371
00372
00373 set_index_first_pending_row(num_rows());
00374
00375 if (was_sorted) {
00376 const dimension_type nrows = num_rows();
00377
00378 if (nrows > 1) {
00379
00380
00381
00382 Linear_System& x = *this;
00383 set_sorted(compare(x[nrows-2], x[nrows-1]) <= 0);
00384 }
00385 else
00386
00387 set_sorted(true);
00388 }
00389
00390 PPL_ASSERT(num_pending_rows() == 0);
00391
00392
00393 PPL_ASSERT(OK(false));
00394 }
00395
00396 void
00397 PPL::Linear_System::add_pending_row(const Linear_Row& r) {
00398
00399
00400 PPL_ASSERT(r.check_strong_normalized());
00401 PPL_ASSERT(r.size() == row_size);
00402
00403 const dimension_type new_rows_size = rows.size() + 1;
00404 if (rows.capacity() < new_rows_size) {
00405
00406 std::vector<Row> new_rows;
00407 new_rows.reserve(compute_capacity(new_rows_size, max_num_rows()));
00408 new_rows.insert(new_rows.end(), new_rows_size, Row());
00409
00410 Row new_row(r, row_capacity);
00411 dimension_type i = new_rows_size-1;
00412 std::swap(new_rows[i], new_row);
00413
00414 while (i-- > 0)
00415 new_rows[i].swap(rows[i]);
00416
00417 std::swap(rows, new_rows);
00418 }
00419 else {
00420
00421
00422
00423 Row tmp(r, row_capacity);
00424 std::swap(*rows.insert(rows.end(), Row()), tmp);
00425 }
00426
00427
00428 PPL_ASSERT(num_pending_rows() > 0);
00429
00430
00431 PPL_ASSERT(OK(false));
00432 }
00433
00434 void
00435 PPL::Linear_System::add_pending_row(const Linear_Row::Flags flags) {
00436 const dimension_type new_rows_size = rows.size() + 1;
00437 if (rows.capacity() < new_rows_size) {
00438
00439 std::vector<Row> new_rows;
00440 new_rows.reserve(compute_capacity(new_rows_size, max_num_rows()));
00441 new_rows.insert(new_rows.end(), new_rows_size, Row());
00442
00443 Linear_Row new_row(row_size, row_capacity, flags);
00444 dimension_type i = new_rows_size-1;
00445 std::swap(new_rows[i], new_row);
00446
00447 while (i-- > 0)
00448 new_rows[i].swap(rows[i]);
00449
00450 std::swap(rows, new_rows);
00451 }
00452 else {
00453
00454
00455
00456 Row& new_row = *rows.insert(rows.end(), Row());
00457 static_cast<Linear_Row&>(new_row).construct(row_size, row_capacity, flags);
00458 }
00459
00460
00461 PPL_ASSERT(num_pending_rows() > 0);
00462 }
00463
00464 void
00465 PPL::Linear_System::normalize() {
00466 Linear_System& x = *this;
00467 const dimension_type nrows = x.num_rows();
00468
00469 for (dimension_type i = nrows; i-- > 0; )
00470 x[i].normalize();
00471 set_sorted(nrows <= 1);
00472 }
00473
00474 void
00475 PPL::Linear_System::strong_normalize() {
00476 Linear_System& x = *this;
00477 const dimension_type nrows = x.num_rows();
00478
00479 for (dimension_type i = nrows; i-- > 0; )
00480 x[i].strong_normalize();
00481 set_sorted(nrows <= 1);
00482 }
00483
00484 void
00485 PPL::Linear_System::sign_normalize() {
00486 Linear_System& x = *this;
00487 const dimension_type nrows = x.num_rows();
00488
00489 for (dimension_type i = num_rows(); i-- > 0; )
00490 x[i].sign_normalize();
00491 set_sorted(nrows <= 1);
00492 }
00493
00495 bool
00496 PPL::operator==(const Linear_System& x, const Linear_System& y) {
00497 if (x.num_columns() != y.num_columns())
00498 return false;
00499 const dimension_type x_num_rows = x.num_rows();
00500 const dimension_type y_num_rows = y.num_rows();
00501 if (x_num_rows != y_num_rows)
00502 return false;
00503 if (x.first_pending_row() != y.first_pending_row())
00504 return false;
00505
00506
00507
00508 for (dimension_type i = x_num_rows; i-- > 0; )
00509 if (x[i] != y[i])
00510 return false;
00511 return true;
00512 }
00513
00514 void
00515 PPL::Linear_System::sort_and_remove_with_sat(Bit_Matrix& sat) {
00516 Linear_System& sys = *this;
00517
00518 PPL_ASSERT(sys.first_pending_row() == sat.num_rows());
00519 if (sys.first_pending_row() <= 1) {
00520 sys.set_sorted(true);
00521 return;
00522 }
00523
00524 const dimension_type num_elems = sat.num_rows();
00525
00526
00527 typedef std::vector<Row> Cont;
00528 Indirect_Sort_Compare<Cont, Row_Less_Than> sort_cmp(rows);
00529 Indirect_Unique_Compare<Cont> unique_cmp(rows);
00530 Indirect_Swapper2<Cont, Bit_Matrix> swapper(rows, sat);
00531
00532 const dimension_type num_duplicates
00533 = indirect_sort_and_unique(num_elems, sort_cmp, unique_cmp, swapper);
00534
00535 const dimension_type new_first_pending_row
00536 = sys.first_pending_row() - num_duplicates;
00537
00538 if (sys.num_pending_rows() > 0) {
00539
00540 const dimension_type n_rows = sys.num_rows() - 1;
00541 for (dimension_type i = 0; i < num_duplicates; ++i)
00542 std::swap(sys[new_first_pending_row + i], sys[n_rows - i]);
00543 }
00544
00545 sys.erase_to_end(sys.num_rows() - num_duplicates);
00546 sys.set_index_first_pending_row(new_first_pending_row);
00547
00548 sat.rows_erase_to_end(num_elems - num_duplicates);
00549 PPL_ASSERT(sys.check_sorted());
00550
00551 sys.set_sorted(true);
00552 }
00553
00554 PPL::dimension_type
00555 PPL::Linear_System::gauss(const dimension_type n_lines_or_equalities) {
00556 Linear_System& x = *this;
00557
00558
00559
00560
00561 PPL_ASSERT(x.OK(true));
00562 PPL_ASSERT(x.num_pending_rows() == 0);
00563 PPL_ASSERT(n_lines_or_equalities == x.num_lines_or_equalities());
00564 #ifndef NDEBUG
00565 for (dimension_type i = n_lines_or_equalities; i-- > 0; )
00566 PPL_ASSERT(x[i].is_line_or_equality());
00567 #endif
00568
00569 dimension_type rank = 0;
00570
00571 bool changed = false;
00572 for (dimension_type j = x.num_columns(); j-- > 0; )
00573 for (dimension_type i = rank; i < n_lines_or_equalities; ++i) {
00574
00575
00576 if (x[i][j] == 0)
00577 continue;
00578
00579
00580 if (i > rank) {
00581 std::swap(x[i], x[rank]);
00582
00583 changed = true;
00584 }
00585
00586
00587
00588 for (dimension_type k = i + 1; k < n_lines_or_equalities; ++k)
00589 if (x[k][j] != 0) {
00590 x[k].linear_combine(x[rank], j);
00591 changed = true;
00592 }
00593
00594 ++rank;
00595
00596 break;
00597 }
00598 if (changed)
00599 x.set_sorted(false);
00600
00601 PPL_ASSERT(x.OK(true));
00602 return rank;
00603 }
00604
00605 void
00606 PPL::Linear_System
00607 ::back_substitute(const dimension_type n_lines_or_equalities) {
00608 Linear_System& x = *this;
00609
00610
00611
00612
00613 PPL_ASSERT(x.OK(true));
00614 PPL_ASSERT(x.num_columns() >= 1);
00615 PPL_ASSERT(x.num_pending_rows() == 0);
00616 PPL_ASSERT(n_lines_or_equalities <= x.num_lines_or_equalities());
00617 #ifndef NDEBUG
00618 for (dimension_type i = n_lines_or_equalities; i-- > 0; )
00619 PPL_ASSERT(x[i].is_line_or_equality());
00620 #endif
00621
00622 const dimension_type nrows = x.num_rows();
00623 const dimension_type ncols = x.num_columns();
00624
00625 bool still_sorted = x.is_sorted();
00626
00627
00628 std::deque<bool> check_for_sortedness;
00629 if (still_sorted)
00630 check_for_sortedness.insert(check_for_sortedness.end(), nrows, false);
00631
00632 for (dimension_type k = n_lines_or_equalities; k-- > 0; ) {
00633
00634
00635
00636 Linear_Row& x_k = x[k];
00637 dimension_type j = ncols - 1;
00638 while (j != 0 && x_k[j] == 0)
00639 --j;
00640
00641
00642 for (dimension_type i = k; i-- > 0; ) {
00643 Linear_Row& x_i = x[i];
00644 if (x_i[j] != 0) {
00645
00646
00647 x_i.linear_combine(x_k, j);
00648 if (still_sorted) {
00649
00650
00651 if (i > 0)
00652 check_for_sortedness[i-1] = true;
00653 check_for_sortedness[i] = true;
00654 }
00655 }
00656 }
00657
00658
00659
00660
00661
00662
00663 const bool have_to_negate = (x_k[j] < 0);
00664 if (have_to_negate)
00665 for (dimension_type h = ncols; h-- > 0; )
00666 PPL::neg_assign(x_k[h]);
00667
00668
00669
00670
00671 for (dimension_type i = n_lines_or_equalities; i < nrows; ++i) {
00672 Linear_Row& x_i = x[i];
00673 if (x_i[j] != 0) {
00674
00675
00676 x_i.linear_combine(x_k, j);
00677 if (still_sorted) {
00678
00679
00680 if (i > n_lines_or_equalities)
00681 check_for_sortedness[i-1] = true;
00682 check_for_sortedness[i] = true;
00683 }
00684 }
00685 }
00686 if (have_to_negate)
00687
00688 for (dimension_type h = ncols; h-- > 0; )
00689 PPL::neg_assign(x_k[h]);
00690 }
00691
00692
00693 for (dimension_type i = 0; still_sorted && i+1 < nrows; ++i)
00694 if (check_for_sortedness[i])
00695
00696 still_sorted = (compare(x[i], x[i+1]) <= 0);
00697
00698 x.set_sorted(still_sorted);
00699
00700
00701 PPL_ASSERT(x.OK(true));
00702 }
00703
00704 void
00705 PPL::Linear_System::simplify() {
00706 Linear_System& x = *this;
00707
00708
00709 PPL_ASSERT(x.OK(true));
00710 PPL_ASSERT(x.num_pending_rows() == 0);
00711
00712
00713 dimension_type nrows = x.num_rows();
00714 dimension_type n_lines_or_equalities = 0;
00715 for (dimension_type i = 0; i < nrows; ++i)
00716 if (x[i].is_line_or_equality()) {
00717 if (n_lines_or_equalities < i) {
00718 std::swap(x[i], x[n_lines_or_equalities]);
00719
00720 PPL_ASSERT(!x.sorted);
00721 }
00722 ++n_lines_or_equalities;
00723 }
00724
00725 const dimension_type rank = x.gauss(n_lines_or_equalities);
00726
00727 if (rank < n_lines_or_equalities) {
00728 const dimension_type
00729 n_rays_or_points_or_inequalities = nrows - n_lines_or_equalities;
00730 const dimension_type
00731 num_swaps = std::min(n_lines_or_equalities - rank,
00732 n_rays_or_points_or_inequalities);
00733 for (dimension_type i = num_swaps; i-- > 0; )
00734 std::swap(x[--nrows], x[rank + i]);
00735 x.erase_to_end(nrows);
00736 x.unset_pending_rows();
00737 if (n_rays_or_points_or_inequalities > num_swaps)
00738 x.set_sorted(false);
00739 n_lines_or_equalities = rank;
00740 }
00741
00742 x.back_substitute(n_lines_or_equalities);
00743
00744 PPL_ASSERT(x.OK(true));
00745 }
00746
00747 void
00748 PPL::Linear_System::add_rows_and_columns(const dimension_type n) {
00749 PPL_ASSERT(n > 0);
00750 const bool was_sorted = is_sorted();
00751 const dimension_type old_n_rows = num_rows();
00752 const dimension_type old_n_columns = num_columns();
00753 add_zero_rows_and_columns(n, n, Linear_Row::Flags(row_topology));
00754 Linear_System& x = *this;
00755
00756 for (dimension_type i = old_n_rows; i-- > 0; )
00757 std::swap(x[i], x[i + n]);
00758 for (dimension_type i = n, c = old_n_columns; i-- > 0; ) {
00759
00760
00761
00762 Linear_Row& r = x[i];
00763 r[c++] = 1;
00764 r.set_is_line_or_equality();
00765
00766 }
00767
00768
00769 if (old_n_columns == 0) {
00770 x[n-1].set_is_ray_or_point_or_inequality();
00771
00772
00773 set_sorted(true);
00774 }
00775 else if (was_sorted)
00776 set_sorted(compare(x[n-1], x[n]) <= 0);
00777
00778
00779 PPL_ASSERT(OK(true));
00780 }
00781
00782 void
00783 PPL::Linear_System::sort_pending_and_remove_duplicates() {
00784 PPL_ASSERT(num_pending_rows() > 0);
00785 PPL_ASSERT(is_sorted());
00786 Linear_System& x = *this;
00787
00788
00789
00790 const dimension_type first_pending = x.first_pending_row();
00791 x.sort_rows(first_pending, x.num_rows());
00792
00793
00794 dimension_type num_rows = x.num_rows();
00795
00796 dimension_type k1 = 0;
00797 dimension_type k2 = first_pending;
00798 dimension_type num_duplicates = 0;
00799
00800
00801 while (k1 < first_pending && k2 < num_rows) {
00802 const int cmp = compare(x[k1], x[k2]);
00803 if (cmp == 0) {
00804
00805 ++num_duplicates;
00806 --num_rows;
00807
00808 ++k1;
00809
00810 if (k2 < num_rows)
00811 std::swap(x[k2], x[k2 + num_duplicates]);
00812 }
00813 else if (cmp < 0)
00814
00815 ++k1;
00816 else {
00817
00818
00819
00820 ++k2;
00821 if (num_duplicates > 0 && k2 < num_rows)
00822 std::swap(x[k2], x[k2 + num_duplicates]);
00823 }
00824 }
00825
00826
00827 if (num_duplicates > 0) {
00828 if (k2 < num_rows)
00829 for (++k2; k2 < num_rows; ++k2)
00830 std::swap(x[k2], x[k2 + num_duplicates]);
00831 x.erase_to_end(num_rows);
00832 }
00833
00834
00835 PPL_ASSERT(OK(false));
00836 }
00837
00838 bool
00839 PPL::Linear_System::check_sorted() const {
00840 const Linear_System& x = *this;
00841 for (dimension_type i = first_pending_row(); i-- > 1; )
00842 if (compare(x[i], x[i-1]) < 0)
00843 return false;
00844 return true;
00845 }
00846
00847 bool
00848 PPL::Linear_System::OK(const bool check_strong_normalized) const {
00849 #ifndef NDEBUG
00850 using std::endl;
00851 using std::cerr;
00852 #endif
00853
00854
00855 if (first_pending_row() > num_rows()) {
00856 #ifndef NDEBUG
00857 cerr << "Linear_System has a negative number of pending rows!"
00858 << endl;
00859 #endif
00860 return false;
00861 }
00862
00863
00864
00865 if (has_no_rows()) {
00866 if (is_necessarily_closed() || num_columns() != 1)
00867 return true;
00868 else {
00869 #ifndef NDEBUG
00870 cerr << "NNC Linear_System has one column" << endl;
00871 #endif
00872 return false;
00873 }
00874 }
00875
00876
00877
00878
00879 const dimension_type min_cols = is_necessarily_closed() ? 1 : 2;
00880 if (num_columns() < min_cols) {
00881 #ifndef NDEBUG
00882 cerr << "Linear_System has fewer columns than the minimum "
00883 << "allowed by its topology:"
00884 << endl
00885 << "num_columns is " << num_columns()
00886 << ", minimum is " << min_cols
00887 << endl;
00888 #endif
00889 return false;
00890 }
00891
00892 const Linear_System& x = *this;
00893 const dimension_type n_rows = num_rows();
00894 for (dimension_type i = 0; i < n_rows; ++i) {
00895 if (!x[i].OK(row_size, row_capacity))
00896 return false;
00897
00898 if (x.topology() != x[i].topology()) {
00899 #ifndef NDEBUG
00900 cerr << "Topology mismatch between the system "
00901 << "and one of its rows!"
00902 << endl;
00903 #endif
00904 return false;
00905 }
00906 }
00907
00908 if (check_strong_normalized) {
00909
00910
00911
00912
00913
00914 Linear_System tmp(x, With_Pending());
00915 tmp.strong_normalize();
00916 if (x != tmp) {
00917 #ifndef NDEBUG
00918 cerr << "Linear_System rows are not strongly normalized!"
00919 << endl;
00920 #endif
00921 return false;
00922 }
00923 }
00924
00925 if (sorted && !check_sorted()) {
00926 #ifndef NDEBUG
00927 cerr << "The system declares itself to be sorted but it is not!"
00928 << endl;
00929 #endif
00930 return false;
00931 }
00932
00933
00934 return true;
00935 }