00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <ppl-config.h>
00026
00027 #include "Grid.defs.hh"
00028
00029 #include "assert.hh"
00030 #include <iostream>
00031
00032 namespace PPL = Parma_Polyhedra_Library;
00033
00034 void
00035 PPL::Grid::select_wider_congruences(const Grid& y,
00036 Congruence_System& cgs_selected) const {
00037
00038
00039 PPL_ASSERT(space_dim == y.space_dim);
00040 PPL_ASSERT(!marked_empty());
00041 PPL_ASSERT(!y.marked_empty());
00042 PPL_ASSERT(congruences_are_minimized());
00043 PPL_ASSERT(y.congruences_are_minimized());
00044
00045
00046
00047 for (dimension_type dim = con_sys.space_dimension(), x_row = 0, y_row = 0;
00048 dim > 0; --dim) {
00049 PPL_ASSERT(dim_kinds[dim] == CON_VIRTUAL
00050 || dim_kinds[dim] == y.dim_kinds[dim]);
00051 switch (dim_kinds[dim]) {
00052 case PROPER_CONGRUENCE:
00053 {
00054 const Congruence& cg = con_sys[x_row];
00055 const Congruence& y_cg = y.con_sys[y_row];
00056 if (cg.is_equal_at_dimension(dim, y_cg))
00057
00058 cgs_selected.insert(cg);
00059 ++x_row;
00060 ++y_row;
00061 }
00062 break;
00063 case EQUALITY:
00064 cgs_selected.insert(con_sys[x_row]);
00065 ++x_row;
00066 ++y_row;
00067 break;
00068 case CON_VIRTUAL:
00069 y.dim_kinds[dim] == CON_VIRTUAL || ++y_row;
00070 break;
00071 }
00072 }
00073 }
00074
00075 void
00076 PPL::Grid::congruence_widening_assign(const Grid& const_y, unsigned* tp) {
00077 Grid& x = *this;
00078 Grid& y = const_cast<Grid&>(const_y);
00079
00080 if (x.space_dim != y.space_dim)
00081 throw_dimension_incompatible("widening_assign(y)", "y", y);
00082
00083
00084
00085 #ifndef NDEBUG
00086 {
00087
00088 const Grid x_copy = x;
00089 const Grid y_copy = y;
00090 PPL_ASSERT(x_copy.contains(y_copy));
00091 }
00092 #endif
00093
00094
00095 if (x.space_dim == 0 || x.marked_empty() || y.marked_empty())
00096 return;
00097
00098
00099 if (x.congruences_are_up_to_date()) {
00100 if (!x.congruences_are_minimized()) {
00101 if (simplify(x.con_sys, x.dim_kinds)) {
00102
00103 x.set_empty();
00104 return;
00105 }
00106 x.set_congruences_minimized();
00107 }
00108 }
00109 else
00110 x.update_congruences();
00111
00112
00113 if (y.congruences_are_up_to_date()) {
00114 if (!y.congruences_are_minimized()) {
00115 if (simplify(y.con_sys, y.dim_kinds)) {
00116
00117 y.set_empty();
00118 return;
00119 }
00120 y.set_congruences_minimized();
00121 }
00122 }
00123 else
00124 y.update_congruences();
00125
00126 if (con_sys.num_equalities() < y.con_sys.num_equalities())
00127 return;
00128
00129
00130
00131 Congruence_System cgs;
00132 x.select_wider_congruences(y, cgs);
00133
00134 if (cgs.num_rows() == con_sys.num_rows())
00135
00136 return;
00137
00138
00139
00140 Grid result(x.space_dim);
00141 result.add_recycled_congruences(cgs);
00142
00143
00144
00145 if (tp && *tp > 0) {
00146
00147
00148
00149 if (!x.contains(result))
00150 --(*tp);
00151 }
00152 else
00153
00154 std::swap(x, result);
00155
00156 PPL_ASSERT(x.OK(true));
00157 }
00158
00159 void
00160 PPL::Grid::limited_congruence_extrapolation_assign(const Grid& y,
00161 const Congruence_System& cgs,
00162 unsigned* tp) {
00163 Grid& x = *this;
00164
00165
00166 if (x.space_dim != y.space_dim)
00167 throw_dimension_incompatible("limited_extrapolation_assign(y, cgs)",
00168 "y", y);
00169
00170 const dimension_type cgs_space_dim = cgs.space_dimension();
00171 if (x.space_dim < cgs_space_dim)
00172 throw_dimension_incompatible("limited_extrapolation_assign(y, cgs)",
00173 "cgs", cgs);
00174
00175 const dimension_type cgs_num_rows = cgs.num_rows();
00176
00177 if (cgs_num_rows == 0) {
00178 x.widening_assign(y, tp);
00179 return;
00180 }
00181
00182 #ifndef NDEBUG
00183 {
00184
00185 const Grid x_copy = x;
00186 const Grid y_copy = y;
00187 PPL_ASSERT(x_copy.contains(y_copy));
00188 }
00189 #endif
00190
00191 if (y.marked_empty())
00192 return;
00193 if (x.marked_empty())
00194 return;
00195
00196
00197
00198 if (x.space_dim == 0)
00199 return;
00200
00201
00202
00203
00204 if (!x.generators_are_up_to_date() && !x.update_generators())
00205
00206 return;
00207
00208 if (tp == NULL || *tp == 0) {
00209
00210 Congruence_System new_cgs;
00211
00212
00213
00214 for (dimension_type i = 0; i < cgs_num_rows; ++i) {
00215 const Congruence& cg = cgs[i];
00216 if (x.relation_with(cg) == Poly_Con_Relation::is_included())
00217 new_cgs.insert(cg);
00218 }
00219 x.congruence_widening_assign(y, tp);
00220 x.add_recycled_congruences(new_cgs);
00221 }
00222 else
00223
00224 x.congruence_widening_assign(y, tp);
00225
00226 PPL_ASSERT(OK());
00227 }
00228
00229 void
00230 PPL::Grid::select_wider_generators(const Grid& y,
00231 Grid_Generator_System& ggs_selected) const {
00232
00233
00234 PPL_ASSERT(space_dim == y.space_dim);
00235 PPL_ASSERT(!marked_empty());
00236 PPL_ASSERT(!y.marked_empty());
00237 PPL_ASSERT(generators_are_minimized());
00238 PPL_ASSERT(y.generators_are_minimized());
00239
00240
00241
00242 for (dimension_type dim = 0, x_row = 0, y_row = 0;
00243 dim <= gen_sys.space_dimension(); ++dim) {
00244 PPL_ASSERT(dim_kinds[dim] == LINE
00245 || y.dim_kinds[dim] == GEN_VIRTUAL
00246 || dim_kinds[dim] == y.dim_kinds[dim]);
00247 switch (dim_kinds[dim]) {
00248 case PARAMETER:
00249 {
00250 const Grid_Generator& gg = gen_sys[x_row];
00251 const Grid_Generator& y_gg = y.gen_sys[y_row];
00252 if (gg.is_equal_at_dimension(dim, y_gg))
00253
00254 ggs_selected.insert(gg);
00255 else {
00256 Linear_Expression e;
00257 for (dimension_type i = gg.space_dimension(); i-- > 0; )
00258 e += gg.coefficient(Variable(i)) * Variable(i);
00259 ggs_selected.insert(grid_line(e));
00260 }
00261 ++x_row;
00262 ++y_row;
00263 }
00264 break;
00265 case LINE:
00266 ggs_selected.insert(gen_sys[x_row]);
00267 ++x_row;
00268 ++y_row;
00269 break;
00270 case GEN_VIRTUAL:
00271 y.dim_kinds[dim] == GEN_VIRTUAL || ++y_row;
00272 break;
00273 }
00274 }
00275 }
00276
00277 void
00278 PPL::Grid::generator_widening_assign(const Grid& const_y, unsigned* tp) {
00279 Grid& x = *this;
00280 Grid& y = const_cast<Grid&>(const_y);
00281
00282 if (x.space_dim != y.space_dim)
00283 throw_dimension_incompatible("generator_widening_assign(y)", "y", y);
00284
00285
00286
00287 #ifndef NDEBUG
00288 {
00289
00290 const Grid x_copy = x;
00291 const Grid y_copy = y;
00292 PPL_ASSERT(x_copy.contains(y_copy));
00293 }
00294 #endif
00295
00296
00297 if (x.space_dim == 0 || x.marked_empty() || y.marked_empty())
00298 return;
00299
00300
00301 if (x.generators_are_up_to_date()) {
00302 if (!x.generators_are_minimized()) {
00303 simplify(x.gen_sys, x.dim_kinds);
00304 PPL_ASSERT(!x.gen_sys.has_no_rows());
00305 x.set_generators_minimized();
00306 }
00307 }
00308 else
00309 x.update_generators();
00310
00311 if (x.marked_empty())
00312 return;
00313
00314
00315 if (y.generators_are_up_to_date()) {
00316 if (!y.generators_are_minimized()) {
00317 simplify(y.gen_sys, y.dim_kinds);
00318 PPL_ASSERT(!y.gen_sys.has_no_rows());
00319 y.set_generators_minimized();
00320 }
00321 }
00322 else
00323 y.update_generators();
00324
00325 if (gen_sys.num_rows() > y.gen_sys.num_rows())
00326 return;
00327
00328 if (gen_sys.num_lines() > y.gen_sys.num_lines())
00329 return;
00330
00331
00332
00333 Grid_Generator_System ggs;
00334 x.select_wider_generators(y, ggs);
00335
00336 if (ggs.num_parameters() == gen_sys.num_parameters())
00337
00338 return;
00339
00340
00341
00342 Grid result(x.space_dim, EMPTY);
00343 result.add_recycled_grid_generators(ggs);
00344
00345
00346
00347 if (tp && *tp > 0) {
00348
00349
00350
00351 if (!x.contains(result))
00352 --(*tp);
00353 }
00354 else
00355
00356 std::swap(x, result);
00357
00358 PPL_ASSERT(x.OK(true));
00359 }
00360
00361 void
00362 PPL::Grid::limited_generator_extrapolation_assign(const Grid& y,
00363 const Congruence_System& cgs,
00364 unsigned* tp) {
00365 Grid& x = *this;
00366
00367
00368 if (x.space_dim != y.space_dim)
00369 throw_dimension_incompatible("limited_extrapolation_assign(y, cgs)",
00370 "y", y);
00371
00372 const dimension_type cgs_space_dim = cgs.space_dimension();
00373 if (x.space_dim < cgs_space_dim)
00374 throw_dimension_incompatible("limited_extrapolation_assign(y, cgs)",
00375 "cgs", cgs);
00376
00377 const dimension_type cgs_num_rows = cgs.num_rows();
00378
00379 if (cgs_num_rows == 0) {
00380 x.generator_widening_assign(y, tp);
00381 return;
00382 }
00383
00384 #ifndef NDEBUG
00385 {
00386
00387 const Grid x_copy = x;
00388 const Grid y_copy = y;
00389 PPL_ASSERT(x_copy.contains(y_copy));
00390 }
00391 #endif
00392
00393 if (y.marked_empty())
00394 return;
00395 if (x.marked_empty())
00396 return;
00397
00398
00399
00400 if (x.space_dim == 0)
00401 return;
00402
00403
00404
00405
00406 if (!x.generators_are_up_to_date() && !x.update_generators())
00407
00408 return;
00409
00410 if (tp == NULL || *tp == 0) {
00411
00412 Congruence_System new_cgs;
00413
00414
00415
00416 for (dimension_type i = 0; i < cgs_num_rows; ++i) {
00417 const Congruence& cg = cgs[i];
00418 if (x.relation_with(cg) == Poly_Con_Relation::is_included())
00419 new_cgs.insert(cg);
00420 }
00421 x.generator_widening_assign(y, tp);
00422 x.add_recycled_congruences(new_cgs);
00423 }
00424 else
00425
00426 x.generator_widening_assign(y, tp);
00427
00428 PPL_ASSERT(OK());
00429 }
00430
00431 void
00432 PPL::Grid::widening_assign(const Grid& const_y, unsigned* tp) {
00433 Grid& x = *this;
00434 Grid& y = const_cast<Grid&>(const_y);
00435
00436 if (x.space_dim != y.space_dim)
00437 throw_dimension_incompatible("widening_assign(y)", "y", y);
00438
00439
00440
00441 #ifndef NDEBUG
00442 {
00443
00444 const Grid x_copy = x;
00445 const Grid y_copy = y;
00446 PPL_ASSERT(x_copy.contains(y_copy));
00447 }
00448 #endif
00449
00450
00451
00452 if (x.congruences_are_up_to_date() && y.congruences_are_up_to_date()) {
00453 x.congruence_widening_assign(y, tp);
00454 return;
00455 }
00456
00457
00458
00459 if (x.generators_are_up_to_date() && y.generators_are_up_to_date()) {
00460 x.generator_widening_assign(y, tp);
00461 return;
00462 }
00463
00464 x.congruence_widening_assign(y, tp);
00465 }
00466
00467 void
00468 PPL::Grid::limited_extrapolation_assign(const Grid& y,
00469 const Congruence_System& cgs,
00470 unsigned* tp) {
00471 Grid& x = *this;
00472
00473
00474 if (x.space_dim != y.space_dim)
00475 throw_dimension_incompatible("limited_extrapolation_assign(y, cgs)",
00476 "y", y);
00477
00478 const dimension_type cgs_space_dim = cgs.space_dimension();
00479 if (x.space_dim < cgs_space_dim)
00480 throw_dimension_incompatible("limited_extrapolation_assign(y, cgs)",
00481 "cgs", cgs);
00482
00483 const dimension_type cgs_num_rows = cgs.num_rows();
00484
00485 if (cgs_num_rows == 0) {
00486 x.widening_assign(y, tp);
00487 return;
00488 }
00489
00490 #ifndef NDEBUG
00491 {
00492
00493 const Grid x_copy = x;
00494 const Grid y_copy = y;
00495 PPL_ASSERT(x_copy.contains(y_copy));
00496 }
00497 #endif
00498
00499 if (y.marked_empty())
00500 return;
00501 if (x.marked_empty())
00502 return;
00503
00504
00505
00506 if (x.space_dim == 0)
00507 return;
00508
00509
00510
00511
00512 if (!x.generators_are_up_to_date() && !x.update_generators())
00513
00514 return;
00515
00516 if (tp == NULL || *tp == 0) {
00517
00518 Congruence_System new_cgs;
00519
00520
00521
00522 for (dimension_type i = 0; i < cgs_num_rows; ++i) {
00523 const Congruence& cg = cgs[i];
00524 if (x.relation_with(cg) == Poly_Con_Relation::is_included())
00525 new_cgs.insert(cg);
00526 }
00527 x.widening_assign(y, tp);
00528 x.add_recycled_congruences(new_cgs);
00529 }
00530 else
00531
00532 x.widening_assign(y, tp);
00533
00534 PPL_ASSERT(OK());
00535 }