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 #include "Variables_Set.defs.hh"
00029 #include "assert.hh"
00030
00031 namespace PPL = Parma_Polyhedra_Library;
00032
00033
00034 void
00035 PPL::Grid::add_space_dimensions(Congruence_System& cgs,
00036 Grid_Generator_System& gs,
00037 const dimension_type dims) {
00038 PPL_ASSERT(cgs.num_columns() - 1 == gs.space_dimension() + 1);
00039 PPL_ASSERT(dims > 0);
00040
00041 const dimension_type old_modulus_index = cgs.num_columns() - 1;
00042 cgs.add_zero_columns(dims);
00043
00044 cgs.swap_columns(old_modulus_index, old_modulus_index + dims);
00045
00046 if (congruences_are_minimized() || generators_are_minimized())
00047 dim_kinds.resize(old_modulus_index + dims, CON_VIRTUAL );
00048
00049 gs.add_universe_rows_and_columns(dims);
00050 }
00051
00052
00053 void
00054 PPL::Grid::add_space_dimensions(Grid_Generator_System& gs,
00055 Congruence_System& cgs,
00056 const dimension_type dims) {
00057 PPL_ASSERT(cgs.num_columns() - 1 == gs.space_dimension() + 1);
00058 PPL_ASSERT(dims > 0);
00059
00060 cgs.add_unit_rows_and_columns(dims);
00061
00062
00063 gs.insert(parameter(0*Variable(space_dim + dims - 1)));
00064
00065 normalize_divisors(gs);
00066
00067 dim_kinds.resize(cgs.num_columns() - 1, EQUALITY );
00068 }
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 void
00079 PPL::Grid::add_space_dimensions_and_embed(dimension_type m) {
00080 if (m == 0)
00081 return;
00082
00083
00084
00085 if (m > max_space_dimension() - space_dimension())
00086 throw_space_dimension_overflow("add_space_dimensions_and_embed(m)",
00087 "adding m new space dimensions exceeds "
00088 "the maximum allowed space dimension");
00089
00090
00091
00092
00093 if (marked_empty()) {
00094 space_dim += m;
00095 set_empty();
00096 return;
00097 }
00098
00099
00100 if (space_dim == 0) {
00101
00102 PPL_ASSERT(status.test_zero_dim_univ());
00103
00104 Grid gr(m, UNIVERSE);
00105 swap(gr);
00106 return;
00107 }
00108
00109
00110
00111
00112
00113
00114
00115
00116 if (congruences_are_up_to_date())
00117 if (generators_are_up_to_date())
00118
00119 add_space_dimensions(con_sys, gen_sys, m);
00120 else {
00121
00122 con_sys.add_zero_columns(m);
00123 dimension_type size = con_sys.num_columns() - 1;
00124
00125 con_sys.swap_columns(size - m, size);
00126 if (congruences_are_minimized())
00127 dim_kinds.resize(size, CON_VIRTUAL);
00128 }
00129 else {
00130
00131 PPL_ASSERT(generators_are_up_to_date());
00132 gen_sys.add_universe_rows_and_columns(m);
00133 if (generators_are_minimized())
00134 dim_kinds.resize(gen_sys.space_dimension() + 1, LINE);
00135 }
00136
00137 space_dim += m;
00138
00139
00140
00141 PPL_ASSERT(OK());
00142 }
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 void
00153 PPL::Grid::add_space_dimensions_and_project(dimension_type m) {
00154 if (m == 0)
00155 return;
00156
00157
00158
00159 if (m > max_space_dimension() - space_dimension())
00160 throw_space_dimension_overflow("add_space_dimensions_and_project(m)",
00161 "adding m new space dimensions exceeds "
00162 "the maximum allowed space dimension");
00163
00164
00165
00166 if (marked_empty()) {
00167 space_dim += m;
00168 set_empty();
00169 return;
00170 }
00171
00172 if (space_dim == 0) {
00173 PPL_ASSERT(status.test_zero_dim_univ());
00174
00175 Grid gr(m, UNIVERSE);
00176 swap(gr);
00177 return;
00178 }
00179
00180
00181
00182
00183
00184
00185
00186
00187 if (congruences_are_up_to_date())
00188 if (generators_are_up_to_date())
00189
00190 add_space_dimensions(gen_sys, con_sys, m);
00191 else {
00192
00193 con_sys.add_unit_rows_and_columns(m);
00194 if (congruences_are_minimized())
00195 dim_kinds.resize(con_sys.num_columns() - 1, EQUALITY);
00196 }
00197 else {
00198
00199 PPL_ASSERT(generators_are_up_to_date());
00200
00201
00202 gen_sys.insert(parameter(0*Variable(space_dim + m - 1)));
00203
00204 normalize_divisors(gen_sys);
00205
00206 if (generators_are_minimized())
00207 dim_kinds.resize(gen_sys.space_dimension() + 1, EQUALITY);
00208 }
00209
00210 space_dim += m;
00211
00212
00213
00214 PPL_ASSERT(OK());
00215 }
00216
00217 void
00218 PPL::Grid::concatenate_assign(const Grid& y) {
00219
00220
00221 if (y.space_dim > max_space_dimension() - space_dimension())
00222 throw_space_dimension_overflow("concatenate_assign(y)",
00223 "concatenation exceeds the maximum "
00224 "allowed space dimension");
00225
00226 const dimension_type added_columns = y.space_dim;
00227
00228
00229
00230 if (marked_empty() || y.marked_empty()) {
00231 space_dim += added_columns;
00232 set_empty();
00233 return;
00234 }
00235
00236
00237 if (added_columns == 0)
00238 return;
00239
00240
00241 if (space_dim == 0) {
00242 *this = y;
00243 return;
00244 }
00245
00246 if (!congruences_are_up_to_date())
00247 update_congruences();
00248
00249 con_sys.concatenate(y.congruences());
00250
00251 space_dim += added_columns;
00252
00253 clear_congruences_minimized();
00254 clear_generators_up_to_date();
00255
00256
00257
00258 PPL_ASSERT(OK());
00259 }
00260
00261 void
00262 PPL::Grid::remove_space_dimensions(const Variables_Set& vars) {
00263
00264
00265
00266 if (vars.empty()) {
00267 PPL_ASSERT(OK());
00268 return;
00269 }
00270
00271
00272 const dimension_type min_space_dim = vars.space_dimension();
00273 if (space_dim < min_space_dim)
00274 throw_dimension_incompatible("remove_space_dimensions(vs)", min_space_dim);
00275
00276 const dimension_type new_space_dim = space_dim - vars.size();
00277
00278 if (marked_empty()
00279 || (!generators_are_up_to_date() && !update_generators())) {
00280
00281 space_dim = new_space_dim;
00282 set_empty();
00283 PPL_ASSERT(OK());
00284 return;
00285 }
00286
00287
00288
00289 if (new_space_dim == 0) {
00290 set_zero_dim_univ();
00291 return;
00292 }
00293
00294 gen_sys.remove_space_dimensions(vars);
00295
00296 clear_congruences_up_to_date();
00297 clear_generators_minimized();
00298
00299
00300 space_dim = new_space_dim;
00301
00302 PPL_ASSERT(OK(true));
00303 }
00304
00305 void
00306 PPL::Grid::remove_higher_space_dimensions(const dimension_type new_dimension) {
00307
00308 if (new_dimension > space_dim)
00309 throw_dimension_incompatible("remove_higher_space_dimensions(nd)",
00310 new_dimension);
00311
00312
00313
00314
00315 if (new_dimension == space_dim) {
00316 PPL_ASSERT(OK());
00317 return;
00318 }
00319
00320 if (is_empty()) {
00321
00322
00323 space_dim = new_dimension;
00324 set_empty();
00325 PPL_ASSERT(OK());
00326 return;
00327 }
00328
00329 if (new_dimension == 0) {
00330
00331
00332 set_zero_dim_univ();
00333 return;
00334 }
00335
00336
00337 if (generators_are_up_to_date()) {
00338 gen_sys.remove_higher_space_dimensions(new_dimension);
00339 if (generators_are_minimized()) {
00340
00341 dimension_type num_redundant = 0;
00342 const dimension_type num_old_gs = space_dim - new_dimension;
00343 for (dimension_type row = 0; row < num_old_gs; ++row)
00344 dim_kinds[row] == GEN_VIRTUAL || ++num_redundant;
00345 if (num_redundant > 0) {
00346
00347 gen_sys.erase_to_end(gen_sys.num_rows() - num_redundant);
00348 gen_sys.unset_pending_rows();
00349 }
00350 dim_kinds.erase(dim_kinds.begin() + new_dimension + 1, dim_kinds.end());
00351
00352
00353 }
00354 clear_congruences_up_to_date();
00355
00356
00357 Congruence_System cgs(Congruence::zero_dim_false());
00358
00359 cgs.increase_space_dimension(new_dimension + 2);
00360 con_sys.swap(cgs);
00361 }
00362 else {
00363 PPL_ASSERT(congruences_are_minimized());
00364 con_sys.remove_higher_space_dimensions(new_dimension);
00365
00366 dimension_type num_redundant = 0;
00367 for (dimension_type row = space_dim; row > new_dimension; --row)
00368 dim_kinds[row] == CON_VIRTUAL || ++num_redundant;
00369 if (num_redundant > 0) {
00370 dimension_type rows = con_sys.num_rows();
00371
00372 for (dimension_type low = 0, high = num_redundant;
00373 high < rows;
00374 ++high, ++low)
00375 std::swap(con_sys[low], con_sys[high]);
00376
00377
00378 con_sys.erase_to_end(rows - num_redundant);
00379 }
00380 dim_kinds.erase(dim_kinds.begin() + new_dimension + 1, dim_kinds.end());
00381 clear_generators_up_to_date();
00382
00383
00384 Grid_Generator_System gs(new_dimension + 2);
00385 gen_sys.swap(gs);
00386 }
00387
00388
00389 space_dim = new_dimension;
00390
00391 PPL_ASSERT(OK(true));
00392 }
00393
00394 void
00395 PPL::Grid::expand_space_dimension(Variable var, dimension_type m) {
00396
00397
00398
00399 if (var.space_dimension() > space_dim)
00400 throw_dimension_incompatible("expand_space_dimension(v, m)", "v", var);
00401
00402
00403 if (m == 0)
00404 return;
00405
00406
00407 if (m > max_space_dimension() - space_dimension())
00408 throw_space_dimension_overflow("expand_space_dimension(v, m)",
00409 "adding m new space dimensions exceeds "
00410 "the maximum allowed space dimension");
00411
00412
00413 dimension_type old_dim = space_dim;
00414
00415
00416 add_space_dimensions_and_embed(m);
00417
00418 const dimension_type src_d = var.id();
00419 const Congruence_System& cgs = congruences();
00420 Congruence_System new_congruences;
00421 for (Congruence_System::const_iterator i = cgs.begin(),
00422 cgs_end = cgs.end(); i != cgs_end; ++i) {
00423 const Congruence& cg = *i;
00424
00425
00426 if (cg.coefficient(var) == 0)
00427 continue;
00428
00429
00430 for (dimension_type dst_d = old_dim; dst_d < old_dim+m; ++dst_d) {
00431 Linear_Expression e;
00432 for (dimension_type j = old_dim; j-- > 0; )
00433 e +=
00434 cg.coefficient(Variable(j))
00435 * (j == src_d ? Variable(dst_d) : Variable(j));
00436 new_congruences.insert_verbatim((e + cg.inhomogeneous_term() %= 0)
00437 / cg.modulus());
00438 }
00439 }
00440 add_recycled_congruences(new_congruences);
00441 PPL_ASSERT(OK());
00442 }
00443
00444 void
00445 PPL::Grid::fold_space_dimensions(const Variables_Set& vars, Variable dest) {
00446
00447
00448
00449 if (dest.space_dimension() > space_dim)
00450 throw_dimension_incompatible("fold_space_dimensions(vs, v)", "v", dest);
00451
00452
00453 if (vars.empty())
00454 return;
00455
00456
00457 if (vars.space_dimension() > space_dim)
00458 throw_dimension_incompatible("fold_space_dimensions(vs, v)",
00459 "vs.space_dimension()",
00460 vars.space_dimension());
00461
00462
00463 if (vars.find(dest.id()) != vars.end())
00464 throw_invalid_argument("fold_space_dimensions(vs, v)",
00465 "v should not occur in vs");
00466
00467
00468
00469
00470 (void) grid_generators();
00471
00472
00473 if (!marked_empty()) {
00474 for (Variables_Set::const_iterator i = vars.begin(),
00475 vs_end = vars.end(); i != vs_end; ++i) {
00476 Grid copy = *this;
00477 copy.affine_image(dest, Linear_Expression(Variable(*i)));
00478 upper_bound_assign(copy);
00479 }
00480 }
00481 remove_space_dimensions(vars);
00482 PPL_ASSERT(OK());
00483 }