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 "Generator_System.defs.hh"
00027 #include "Generator_System.inlines.hh"
00028 #include "Constraint.defs.hh"
00029 #include "Scalar_Products.defs.hh"
00030 #include "assert.hh"
00031 #include <string>
00032 #include <vector>
00033 #include <iostream>
00034 #include <stdexcept>
00035
00036 namespace PPL = Parma_Polyhedra_Library;
00037
00038 bool
00039 PPL::Generator_System::
00040 adjust_topology_and_space_dimension(const Topology new_topology,
00041 const dimension_type new_space_dim) {
00042 PPL_ASSERT(space_dimension() <= new_space_dim);
00043
00044 const dimension_type old_space_dim = space_dimension();
00045 const Topology old_topology = topology();
00046 dimension_type cols_to_be_added = new_space_dim - old_space_dim;
00047
00048
00049 if (has_no_rows()) {
00050 if (num_columns() == 0)
00051 if (new_topology == NECESSARILY_CLOSED) {
00052 add_zero_columns(cols_to_be_added + 1);
00053 set_necessarily_closed();
00054 }
00055 else {
00056 add_zero_columns(cols_to_be_added + 2);
00057 set_not_necessarily_closed();
00058 }
00059 else
00060
00061 if (old_topology != new_topology)
00062 if (new_topology == NECESSARILY_CLOSED) {
00063 switch (cols_to_be_added) {
00064 case 0:
00065 remove_trailing_columns(1);
00066 break;
00067 case 1:
00068
00069 break;
00070 default:
00071 add_zero_columns(cols_to_be_added - 1);
00072 }
00073 set_necessarily_closed();
00074 }
00075 else {
00076
00077
00078 add_zero_columns(cols_to_be_added + 1);
00079 set_not_necessarily_closed();
00080 }
00081 else
00082
00083 if (cols_to_be_added > 0)
00084 add_zero_columns(cols_to_be_added);
00085 PPL_ASSERT(OK());
00086 return true;
00087 }
00088
00089
00090 if (cols_to_be_added > 0)
00091 if (old_topology != new_topology)
00092 if (new_topology == NECESSARILY_CLOSED) {
00093
00094
00095
00096
00097 if (has_closure_points())
00098 return false;
00099
00100
00101
00102
00103 Generator_System& gs = *this;
00104 dimension_type num_closure_points = 0;
00105 dimension_type gs_end = gs.num_rows();
00106 for (dimension_type i = 0; i < gs_end; ) {
00107
00108
00109 if (num_closure_points > 0)
00110
00111 std::swap(gs[i], gs[i+num_closure_points]);
00112 if (gs[i].is_closure_point()) {
00113 ++num_closure_points;
00114 --gs_end;
00115 }
00116 else
00117 ++i;
00118 }
00119
00120 if (num_closure_points > 0) {
00121 PPL_ASSERT(num_closure_points == num_rows() - gs_end);
00122 erase_to_end(gs_end);
00123 }
00124
00125
00126
00127 remove_trailing_columns(1);
00128 set_necessarily_closed();
00129 normalize();
00130 add_zero_columns(cols_to_be_added);
00131 }
00132 else {
00133
00134
00135
00136
00137 add_zero_columns(cols_to_be_added + 1);
00138 Generator_System& gs = *this;
00139 const dimension_type eps_index = new_space_dim + 1;
00140 for (dimension_type i = num_rows(); i-- > 0; )
00141 gs[i][eps_index] = gs[i][0];
00142 set_not_necessarily_closed();
00143 }
00144 else {
00145
00146 add_zero_columns(cols_to_be_added);
00147
00148
00149 if (old_topology == NOT_NECESSARILY_CLOSED)
00150 swap_columns(old_space_dim + 1, new_space_dim + 1);
00151 }
00152 else
00153
00154 if (old_topology != new_topology) {
00155 if (new_topology == NECESSARILY_CLOSED) {
00156
00157
00158
00159 if (has_closure_points())
00160 return false;
00161
00162 remove_trailing_columns(1);
00163 set_necessarily_closed();
00164 }
00165 else {
00166
00167
00168
00169 add_zero_columns(1);
00170 Generator_System& gs = *this;
00171 const dimension_type eps_index = new_space_dim + 1;
00172 for (dimension_type i = num_rows(); i-- > 0; )
00173 gs[i][eps_index] = gs[i][0];
00174 set_not_necessarily_closed();
00175 }
00176 }
00177
00178 PPL_ASSERT(OK());
00179 return true;
00180 }
00181
00182
00183
00184
00185
00186 void
00187 PPL::Generator_System::add_corresponding_closure_points() {
00188 PPL_ASSERT(!is_necessarily_closed());
00189
00190
00191 Generator_System& gs = *this;
00192 const dimension_type n_rows = gs.num_rows();
00193 const dimension_type eps_index = gs.num_columns() - 1;
00194 for (dimension_type i = n_rows; i-- > 0; ) {
00195 const Generator& g = gs[i];
00196 if (g[eps_index] > 0) {
00197
00198 Generator cp = g;
00199 cp[eps_index] = 0;
00200
00201 cp.normalize();
00202 gs.add_pending_row(cp);
00203 }
00204 }
00205 PPL_ASSERT(OK());
00206 }
00207
00208
00209
00210
00211
00212
00213 void
00214 PPL::Generator_System::add_corresponding_points() {
00215 PPL_ASSERT(!is_necessarily_closed());
00216
00217
00218 Generator_System& gs = *this;
00219 const dimension_type n_rows = gs.num_rows();
00220 const dimension_type eps_index = gs.num_columns() - 1;
00221 for (dimension_type i = 0; i < n_rows; i++) {
00222 const Generator& g = gs[i];
00223 if (!g.is_line_or_ray() && g[eps_index] == 0) {
00224
00225
00226 Generator p = g;
00227 p[eps_index] = p[0];
00228 gs.add_pending_row(p);
00229 }
00230 }
00231 PPL_ASSERT(OK());
00232 }
00233
00234 bool
00235 PPL::Generator_System::has_closure_points() const {
00236 if (is_necessarily_closed())
00237 return false;
00238
00239 for (Generator_System::const_iterator i = begin(),
00240 this_end = end(); i != this_end; ++i)
00241 if (i->is_closure_point())
00242 return true;
00243 return false;
00244 }
00245
00246 bool
00247 PPL::Generator_System::has_points() const {
00248 const Generator_System& gs = *this;
00249
00250 if (is_necessarily_closed())
00251 for (dimension_type i = num_rows(); i-- > 0; ) {
00252 if (!gs[i].is_line_or_ray())
00253 return true;
00254 }
00255 else {
00256
00257 const dimension_type eps_index = gs.num_columns() - 1;
00258 for (dimension_type i = num_rows(); i-- > 0; )
00259 if (gs[i][eps_index] != 0)
00260 return true;
00261 }
00262 return false;
00263 }
00264
00265 void
00266 PPL::Generator_System::const_iterator::skip_forward() {
00267 const Linear_System::const_iterator gsp_end = gsp->end();
00268 if (i != gsp_end) {
00269 Linear_System::const_iterator i_next = i;
00270 ++i_next;
00271 if (i_next != gsp_end) {
00272 const Generator& cp = static_cast<const Generator&>(*i);
00273 const Generator& p = static_cast<const Generator&>(*i_next);
00274 if (cp.is_closure_point()
00275 && p.is_point()
00276 && cp.is_matching_closure_point(p))
00277 i = i_next;
00278 }
00279 }
00280 }
00281
00282 void
00283 PPL::Generator_System::insert(const Generator& g) {
00284
00285
00286 PPL_ASSERT(num_pending_rows() == 0);
00287 if (topology() == g.topology())
00288 Linear_System::insert(g);
00289 else
00290
00291 if (is_necessarily_closed()) {
00292
00293
00294
00295
00296
00297
00298 const dimension_type eps_index = num_columns();
00299 add_zero_columns(1);
00300 Generator_System& gs = *this;
00301 for (dimension_type i = num_rows(); i-- > 0; ) {
00302 Generator& gen = gs[i];
00303 if (!gen.is_line_or_ray())
00304 gen[eps_index] = gen[0];
00305 }
00306 set_not_necessarily_closed();
00307
00308 Linear_System::insert(g);
00309 }
00310 else {
00311
00312
00313
00314 const dimension_type new_size = 2 + std::max(g.space_dimension(),
00315 space_dimension());
00316 Generator tmp_g(g, new_size);
00317
00318
00319
00320 if (!tmp_g.is_line_or_ray())
00321 tmp_g[new_size - 1] = tmp_g[0];
00322 tmp_g.set_not_necessarily_closed();
00323
00324 Linear_System::insert(tmp_g);
00325 }
00326 PPL_ASSERT(OK());
00327 }
00328
00329 void
00330 PPL::Generator_System::insert_pending(const Generator& g) {
00331 if (topology() == g.topology())
00332 Linear_System::insert_pending(g);
00333 else
00334
00335 if (is_necessarily_closed()) {
00336
00337
00338
00339
00340
00341
00342 const dimension_type eps_index = num_columns();
00343 add_zero_columns(1);
00344 Generator_System& gs = *this;
00345 for (dimension_type i = num_rows(); i-- > 0; ) {
00346 Generator& gen = gs[i];
00347 if (!gen.is_line_or_ray())
00348 gen[eps_index] = gen[0];
00349 }
00350 set_not_necessarily_closed();
00351
00352 Linear_System::insert_pending(g);
00353 }
00354 else {
00355
00356
00357
00358 const dimension_type new_size = 2 + std::max(g.space_dimension(),
00359 space_dimension());
00360 Generator tmp_g(g, new_size);
00361
00362
00363
00364 if (!tmp_g.is_line_or_ray())
00365 tmp_g[new_size - 1] = tmp_g[0];
00366 tmp_g.set_not_necessarily_closed();
00367
00368 Linear_System::insert_pending(tmp_g);
00369 }
00370 PPL_ASSERT(OK());
00371 }
00372
00373 PPL::dimension_type
00374 PPL::Generator_System::num_lines() const {
00375
00376
00377 PPL_ASSERT(num_pending_rows() == 0);
00378 const Generator_System& gs = *this;
00379 dimension_type n = 0;
00380
00381
00382 if (is_sorted()) {
00383 dimension_type nrows = num_rows();
00384 for (dimension_type i = 0; i < nrows && gs[i].is_line(); ++i)
00385 ++n;
00386 }
00387 else
00388 for (dimension_type i = num_rows(); i-- > 0 ; )
00389 if (gs[i].is_line())
00390 ++n;
00391 return n;
00392 }
00393
00394 PPL::dimension_type
00395 PPL::Generator_System::num_rays() const {
00396
00397
00398 PPL_ASSERT(num_pending_rows() == 0);
00399 const Generator_System& gs = *this;
00400 dimension_type n = 0;
00401
00402
00403
00404 if (is_sorted()) {
00405 for (dimension_type i = num_rows(); i != 0 && gs[--i].is_ray_or_point(); )
00406 if (gs[i].is_line_or_ray())
00407 ++n;
00408 }
00409 else
00410 for (dimension_type i = num_rows(); i-- > 0 ; )
00411 if (gs[i].is_ray())
00412 ++n;
00413 return n;
00414 }
00415
00416 PPL::Poly_Con_Relation
00417 PPL::Generator_System::relation_with(const Constraint& c) const {
00418
00419
00420
00421 PPL_ASSERT(space_dimension() >= c.space_dimension());
00422
00423
00424 const dimension_type n_rows = num_rows();
00425 PPL_ASSERT(n_rows > 0);
00426 const Generator_System& gs = *this;
00427
00428
00429
00430 Poly_Con_Relation result = Poly_Con_Relation::saturates();
00431
00432 switch (c.type()) {
00433
00434 case Constraint::EQUALITY:
00435 {
00436
00437
00438 result = result && Poly_Con_Relation::is_included();
00439
00440
00441
00442
00443 int first_point_or_nonsaturating_ray_sign = 2;
00444
00445 for (dimension_type i = n_rows; i-- > 0; ) {
00446 const Generator& g = gs[i];
00447 const int sp_sign = Scalar_Products::sign(c, g);
00448
00449
00450
00451 if (sp_sign == 0) {
00452 if (g.is_point()) {
00453 if (first_point_or_nonsaturating_ray_sign == 2)
00454
00455
00456 first_point_or_nonsaturating_ray_sign = 0;
00457 else
00458
00459 if (first_point_or_nonsaturating_ray_sign != 0)
00460 return Poly_Con_Relation::strictly_intersects();
00461 }
00462 }
00463 else
00464
00465 switch (g.type()) {
00466
00467 case Generator::LINE:
00468
00469
00470
00471 return Poly_Con_Relation::strictly_intersects();
00472
00473 case Generator::RAY:
00474 if (first_point_or_nonsaturating_ray_sign == 2) {
00475
00476
00477 first_point_or_nonsaturating_ray_sign = sp_sign;
00478 result = Poly_Con_Relation::is_disjoint();
00479 }
00480 else
00481
00482 if (sp_sign != first_point_or_nonsaturating_ray_sign)
00483 return Poly_Con_Relation::strictly_intersects();
00484 break;
00485
00486 case Generator::POINT:
00487 case Generator::CLOSURE_POINT:
00488
00489
00490 if (first_point_or_nonsaturating_ray_sign == 2) {
00491
00492
00493 first_point_or_nonsaturating_ray_sign = sp_sign;
00494 result = Poly_Con_Relation::is_disjoint();
00495 }
00496 else
00497
00498 if (sp_sign != first_point_or_nonsaturating_ray_sign)
00499 return Poly_Con_Relation::strictly_intersects();
00500 break;
00501 }
00502 }
00503 }
00504 break;
00505
00506 case Constraint::NONSTRICT_INEQUALITY:
00507 {
00508
00509
00510 result = result && Poly_Con_Relation::is_included();
00511
00512
00513
00514 bool first_point_or_nonsaturating_ray = true;
00515
00516 for (dimension_type i = n_rows; i-- > 0; ) {
00517 const Generator& g = gs[i];
00518 const int sp_sign = Scalar_Products::sign(c, g);
00519
00520
00521
00522 if (sp_sign == 0) {
00523 if (g.is_point()) {
00524 if (first_point_or_nonsaturating_ray)
00525
00526
00527 first_point_or_nonsaturating_ray = false;
00528 else
00529
00530 if (result == Poly_Con_Relation::is_disjoint())
00531
00532
00533 return Poly_Con_Relation::strictly_intersects();
00534 }
00535 }
00536 else
00537
00538 switch (g.type()) {
00539
00540 case Generator::LINE:
00541
00542
00543
00544 return Poly_Con_Relation::strictly_intersects();
00545
00546 case Generator::RAY:
00547 if (first_point_or_nonsaturating_ray) {
00548
00549
00550 first_point_or_nonsaturating_ray = false;
00551 result = (sp_sign > 0)
00552 ? Poly_Con_Relation::is_included()
00553 : Poly_Con_Relation::is_disjoint();
00554 }
00555 else {
00556
00557 if ((sp_sign > 0
00558 && result == Poly_Con_Relation::is_disjoint())
00559 || (sp_sign < 0
00560 && result.implies(Poly_Con_Relation::is_included())))
00561
00562
00563
00564
00565
00566 return Poly_Con_Relation::strictly_intersects();
00567 if (sp_sign > 0)
00568
00569
00570
00571 result = Poly_Con_Relation::is_included();
00572 }
00573 break;
00574
00575 case Generator::POINT:
00576 case Generator::CLOSURE_POINT:
00577
00578
00579 if (first_point_or_nonsaturating_ray) {
00580
00581
00582
00583
00584
00585
00586
00587
00588 first_point_or_nonsaturating_ray = false;
00589 if (sp_sign > 0)
00590 result = Poly_Con_Relation::is_included();
00591 else if (sp_sign < 0)
00592 result = Poly_Con_Relation::is_disjoint();
00593 }
00594 else {
00595
00596 if ((sp_sign > 0
00597 && result == Poly_Con_Relation::is_disjoint())
00598 || (sp_sign < 0
00599 && result.implies(Poly_Con_Relation::is_included())))
00600
00601
00602
00603
00604
00605 return Poly_Con_Relation::strictly_intersects();
00606 if (sp_sign > 0)
00607
00608
00609
00610 result = Poly_Con_Relation::is_included();
00611 }
00612 break;
00613 }
00614 }
00615 }
00616 break;
00617
00618 case Constraint::STRICT_INEQUALITY:
00619 {
00620
00621
00622 result = result && Poly_Con_Relation::is_disjoint();
00623
00624
00625
00626 bool first_point_or_nonsaturating_ray = true;
00627 for (dimension_type i = n_rows; i-- > 0; ) {
00628 const Generator& g = gs[i];
00629
00630
00631 const int sp_sign = Scalar_Products::reduced_sign(c, g);
00632
00633
00634
00635 if (sp_sign == 0) {
00636 if (g.is_point()) {
00637 if (first_point_or_nonsaturating_ray)
00638
00639
00640 first_point_or_nonsaturating_ray = false;
00641 else
00642
00643 if (result == Poly_Con_Relation::is_included())
00644 return Poly_Con_Relation::strictly_intersects();
00645 }
00646 }
00647 else
00648
00649 switch (g.type()) {
00650
00651 case Generator::LINE:
00652
00653
00654
00655 return Poly_Con_Relation::strictly_intersects();
00656
00657 case Generator::RAY:
00658 if (first_point_or_nonsaturating_ray) {
00659
00660
00661 first_point_or_nonsaturating_ray = false;
00662 result = (sp_sign > 0)
00663 ? Poly_Con_Relation::is_included()
00664 : Poly_Con_Relation::is_disjoint();
00665 }
00666 else {
00667
00668 if ((sp_sign > 0
00669 && result.implies(Poly_Con_Relation::is_disjoint()))
00670 ||
00671 (sp_sign <= 0
00672 && result == Poly_Con_Relation::is_included()))
00673 return Poly_Con_Relation::strictly_intersects();
00674 if (sp_sign < 0)
00675
00676
00677
00678 result = Poly_Con_Relation::is_disjoint();
00679 }
00680 break;
00681
00682 case Generator::POINT:
00683 case Generator::CLOSURE_POINT:
00684 if (first_point_or_nonsaturating_ray) {
00685
00686
00687
00688
00689
00690
00691
00692
00693 first_point_or_nonsaturating_ray = false;
00694 if (sp_sign > 0)
00695 result = Poly_Con_Relation::is_included();
00696 else if (sp_sign < 0)
00697 result = Poly_Con_Relation::is_disjoint();
00698 }
00699 else {
00700
00701 if ((sp_sign > 0
00702 && result.implies(Poly_Con_Relation::is_disjoint()))
00703 ||
00704 (sp_sign <= 0
00705 && result == Poly_Con_Relation::is_included()))
00706 return Poly_Con_Relation::strictly_intersects();
00707 if (sp_sign < 0)
00708
00709
00710
00711 result = Poly_Con_Relation::is_disjoint();
00712 }
00713 break;
00714 }
00715 }
00716 }
00717 break;
00718 }
00719
00720 return result;
00721 }
00722
00723
00724 bool
00725 PPL::Generator_System::satisfied_by_all_generators(const Constraint& c) const {
00726 PPL_ASSERT(c.space_dimension() <= space_dimension());
00727
00728
00729
00730
00731 Topology_Adjusted_Scalar_Product_Sign sps(c);
00732
00733 const Generator_System& gs = *this;
00734 switch (c.type()) {
00735 case Constraint::EQUALITY:
00736
00737 for (dimension_type i = gs.num_rows(); i-- > 0; )
00738 if (sps(c, gs[i]) != 0)
00739 return false;
00740 break;
00741 case Constraint::NONSTRICT_INEQUALITY:
00742
00743
00744 for (dimension_type i = gs.num_rows(); i-- > 0; ) {
00745 const Generator& g = gs[i];
00746 const int sp_sign = sps(c, g);
00747 if (g.is_line()) {
00748 if (sp_sign != 0)
00749 return false;
00750 }
00751 else
00752
00753 if (sp_sign < 0)
00754 return false;
00755 }
00756 break;
00757 case Constraint::STRICT_INEQUALITY:
00758
00759
00760 for (dimension_type i = gs.num_rows(); i-- > 0; ) {
00761 const Generator& g = gs[i];
00762 const int sp_sign = sps(c, g);
00763 switch (g.type()) {
00764 case Generator::POINT:
00765 if (sp_sign <= 0)
00766 return false;
00767 break;
00768 case Generator::LINE:
00769 if (sp_sign != 0)
00770 return false;
00771 break;
00772 default:
00773
00774 if (sp_sign < 0)
00775 return false;
00776 break;
00777 }
00778 }
00779 break;
00780 }
00781
00782 return true;
00783 }
00784
00785
00786 void
00787 PPL::Generator_System
00788 ::affine_image(dimension_type v,
00789 const Linear_Expression& expr,
00790 Coefficient_traits::const_reference denominator) {
00791 Generator_System& x = *this;
00792
00793
00794
00795 PPL_ASSERT(v > 0 && v <= x.space_dimension());
00796 PPL_ASSERT(expr.space_dimension() <= x.space_dimension());
00797 PPL_ASSERT(denominator > 0);
00798
00799 const dimension_type n_columns = x.num_columns();
00800 const dimension_type n_rows = x.num_rows();
00801
00802
00803
00804 PPL_DIRTY_TEMP_COEFFICIENT(numerator);
00805 for (dimension_type i = n_rows; i-- > 0; ) {
00806 Generator& row = x[i];
00807 Scalar_Products::assign(numerator, expr, row);
00808 std::swap(numerator, row[v]);
00809 }
00810
00811 if (denominator != 1) {
00812
00813
00814
00815 for (dimension_type i = n_rows; i-- > 0; ) {
00816 Generator& row = x[i];
00817 for (dimension_type j = n_columns; j-- > 0; )
00818 if (j != v)
00819 row[j] *= denominator;
00820 }
00821 }
00822
00823
00824
00825 const bool not_invertible = (v > expr.space_dimension() || expr[v] == 0);
00826 if (not_invertible)
00827 x.remove_invalid_lines_and_rays();
00828
00829
00830 x.strong_normalize();
00831 }
00832
00833 void
00834 PPL::Generator_System::ascii_dump(std::ostream& s) const {
00835 const Generator_System& x = *this;
00836 const dimension_type x_num_rows = x.num_rows();
00837 const dimension_type x_num_columns = x.num_columns();
00838 s << "topology " << (is_necessarily_closed()
00839 ? "NECESSARILY_CLOSED"
00840 : "NOT_NECESSARILY_CLOSED")
00841 << "\n"
00842 << x_num_rows << " x " << x_num_columns << ' '
00843 << (x.is_sorted() ? "(sorted)" : "(not_sorted)")
00844 << "\n"
00845 << "index_first_pending " << x.first_pending_row()
00846 << "\n";
00847 for (dimension_type i = 0; i < x_num_rows; ++i) {
00848 const Generator& g = x[i];
00849 for (dimension_type j = 0; j < x_num_columns; ++j)
00850 s << g[j] << ' ';
00851 switch (g.type()) {
00852 case Generator::LINE:
00853 s << "L";
00854 break;
00855 case Generator::RAY:
00856 s << "R";
00857 break;
00858 case Generator::POINT:
00859 s << "P";
00860 break;
00861 case Generator::CLOSURE_POINT:
00862 s << "C";
00863 break;
00864 }
00865 s << "\n";
00866 }
00867 }
00868
00869 PPL_OUTPUT_DEFINITIONS(Generator_System)
00870
00871 bool
00872 PPL::Generator_System::ascii_load(std::istream& s) {
00873 std::string str;
00874 if (!(s >> str) || str != "topology")
00875 return false;
00876 if (!(s >> str))
00877 return false;
00878 if (str == "NECESSARILY_CLOSED")
00879 set_necessarily_closed();
00880 else {
00881 if (str != "NOT_NECESSARILY_CLOSED")
00882 return false;
00883 set_not_necessarily_closed();
00884 }
00885
00886 dimension_type nrows;
00887 dimension_type ncols;
00888 if (!(s >> nrows))
00889 return false;
00890 if (!(s >> str) || str != "x")
00891 return false;
00892 if (!(s >> ncols))
00893 return false;
00894 resize_no_copy(nrows, ncols);
00895
00896 if (!(s >> str) || (str != "(sorted)" && str != "(not_sorted)"))
00897 return false;
00898 set_sorted(str == "(sorted)");
00899 dimension_type index;
00900 if (!(s >> str) || str != "index_first_pending")
00901 return false;
00902 if (!(s >> index))
00903 return false;
00904 set_index_first_pending_row(index);
00905
00906 Generator_System& x = *this;
00907 for (dimension_type i = 0; i < x.num_rows(); ++i) {
00908 for (dimension_type j = 0; j < x.num_columns(); ++j)
00909 if (!(s >> x[i][j]))
00910 return false;
00911
00912 if (!(s >> str))
00913 return false;
00914 if (str == "L")
00915 x[i].set_is_line();
00916 else if (str == "R" || str == "P" || str == "C")
00917 x[i].set_is_ray_or_point();
00918 else
00919 return false;
00920
00921
00922 switch (x[i].type()) {
00923 case Generator::LINE:
00924 if (str == "L")
00925 continue;
00926 break;
00927 case Generator::RAY:
00928 if (str == "R")
00929 continue;
00930 break;
00931 case Generator::POINT:
00932 if (str == "P")
00933 continue;
00934 break;
00935 case Generator::CLOSURE_POINT:
00936 if (str == "C")
00937 continue;
00938 break;
00939 }
00940
00941 return false;
00942 }
00943
00944
00945 PPL_ASSERT(OK());
00946 return true;
00947 }
00948
00949 void
00950 PPL::Generator_System::remove_invalid_lines_and_rays() {
00951
00952
00953
00954
00955 Generator_System& gs = *this;
00956 dimension_type n_rows = gs.num_rows();
00957 if (num_pending_rows() == 0) {
00958 for (dimension_type i = n_rows; i-- > 0; ) {
00959 Generator& g = gs[i];
00960 if (g.is_line_or_ray() && g.all_homogeneous_terms_are_zero()) {
00961
00962 --n_rows;
00963 std::swap(g, gs[n_rows]);
00964 gs.set_sorted(false);
00965 }
00966 }
00967 set_index_first_pending_row(n_rows);
00968 }
00969 else {
00970
00971
00972
00973
00974
00975
00976
00977 PPL_ASSERT(num_pending_rows() > 0);
00978 dimension_type first_pending = first_pending_row();
00979 for (dimension_type i = first_pending; i-- > 0; ) {
00980 Generator& g = gs[i];
00981 if (g.is_line_or_ray() && g.all_homogeneous_terms_are_zero()) {
00982
00983 --first_pending;
00984 std::swap(g, gs[first_pending]);
00985 gs.set_sorted(false);
00986 }
00987 }
00988 const dimension_type num_invalid_rows
00989 = first_pending_row() - first_pending;
00990 set_index_first_pending_row(first_pending);
00991 for (dimension_type i = 0; i < num_invalid_rows; ++i)
00992 std::swap(gs[n_rows - i], gs[first_pending + i]);
00993 n_rows -= num_invalid_rows;
00994 for (dimension_type i = n_rows; i-- > first_pending; ) {
00995 Generator& g = gs[i];
00996 if (g.is_line_or_ray() && g.all_homogeneous_terms_are_zero()) {
00997
00998 --n_rows;
00999 std::swap(g, gs[n_rows]);
01000 gs.set_sorted(false);
01001 }
01002 }
01003 }
01004 gs.erase_to_end(n_rows);
01005 }
01006
01007 const PPL::Generator_System* PPL::Generator_System::zero_dim_univ_p = 0;
01008
01009 void
01010 PPL::Generator_System::initialize() {
01011 PPL_ASSERT(zero_dim_univ_p == 0);
01012 zero_dim_univ_p
01013 = new Generator_System(Generator::zero_dim_point());
01014 }
01015
01016 void
01017 PPL::Generator_System::finalize() {
01018 PPL_ASSERT(zero_dim_univ_p != 0);
01019 delete zero_dim_univ_p;
01020 zero_dim_univ_p = 0;
01021 }
01022
01023 bool
01024 PPL::Generator_System::OK() const {
01025
01026
01027
01028 if (!Linear_System::OK(false))
01029 return false;
01030
01031
01032 const Generator_System& x = *this;
01033 for (dimension_type i = num_rows(); i-- > 0; )
01034 if (!x[i].OK())
01035 return false;
01036
01037
01038 return true;
01039 }
01040
01042 std::ostream&
01043 PPL::IO_Operators::operator<<(std::ostream& s, const Generator_System& gs) {
01044 Generator_System::const_iterator i = gs.begin();
01045 const Generator_System::const_iterator gs_end = gs.end();
01046 if (i == gs_end)
01047 return s << "false";
01048 while (true) {
01049 s << *i++;
01050 if (i == gs_end)
01051 return s;
01052 s << ", ";
01053 }
01054 }