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 "Grid.defs.hh"
00027 #include <cstddef>
00028
00029 namespace Parma_Polyhedra_Library {
00030
00031
00032
00033
00034
00035
00036
00037 bool
00038 Grid::lower_triangular(const Congruence_System& sys,
00039 const Dimension_Kinds& dim_kinds) {
00040 const dimension_type num_columns = sys.num_columns() - 1;
00041
00042
00043 if (sys.num_rows() > num_columns)
00044 return false;
00045
00046
00047
00048 dimension_type row = 0;
00049 for (dimension_type dim = num_columns; dim-- > 0; ) {
00050 if (dim_kinds[dim] == CON_VIRTUAL)
00051 continue;
00052 const Congruence& cg = sys[row];
00053 ++row;
00054
00055 if (cg[dim] <= 0)
00056 return false;
00057
00058 dimension_type col = dim;
00059 while (++col < num_columns)
00060 if (cg[col] != 0)
00061 return false;
00062 }
00063
00064
00065 return row == sys.num_rows();
00066 }
00067
00068
00069
00070
00071
00072
00073
00074 bool
00075 Grid::upper_triangular(const Grid_Generator_System& sys,
00076 const Dimension_Kinds& dim_kinds) {
00077 dimension_type num_columns = sys.space_dimension() + 1;
00078 dimension_type row = sys.num_rows();
00079
00080
00081 if (row > num_columns)
00082 return false;
00083
00084
00085 while (num_columns > 0) {
00086 --num_columns;
00087 if (dim_kinds[num_columns] == GEN_VIRTUAL)
00088 continue;
00089 const Grid_Generator& gen = sys[--row];
00090
00091 if (gen[num_columns] <= 0)
00092 return false;
00093
00094 dimension_type col = num_columns;
00095 while (col-- > 0)
00096 if (gen[col] != 0)
00097 return false;
00098 }
00099
00100
00101 return num_columns == row;
00102 }
00103
00104 void
00105 Grid::multiply_grid(const Coefficient& multiplier, Grid_Generator& gen,
00106 Grid_Generator_System& dest, const dimension_type num_rows,
00107 const dimension_type num_dims) {
00108 if (multiplier == 1)
00109 return;
00110
00111 if (gen.is_line())
00112
00113 for (dimension_type column = num_dims; column-- > 0; )
00114 gen[column] *= multiplier;
00115 else {
00116 PPL_ASSERT(gen.is_parameter_or_point());
00117
00118 for (dimension_type index = num_rows; index-- > 0; ) {
00119 Grid_Generator& generator = dest[index];
00120 if (generator.is_parameter_or_point())
00121 for (dimension_type column = num_dims; column-- > 0; )
00122 generator[column] *= multiplier;
00123 }
00124 }
00125 }
00126
00127 void
00128 Grid::multiply_grid(const Coefficient& multiplier, Congruence& cg,
00129 Congruence_System& dest, const dimension_type num_rows,
00130 const dimension_type num_dims) {
00131 if (multiplier == 1)
00132 return;
00133
00134 if (cg.is_proper_congruence())
00135
00136 for (dimension_type index = num_rows; index-- > 0; ) {
00137 Congruence& congruence = dest[index];
00138 if (congruence.is_proper_congruence())
00139 for (dimension_type column = num_dims; column-- > 0; )
00140 congruence[column] *= multiplier;
00141 }
00142 else {
00143 PPL_ASSERT(cg.is_equality());
00144
00145 for (dimension_type column = num_dims; column-- > 0; )
00146 cg[column] *= multiplier;
00147 }
00148 }
00149
00150
00151
00152
00153
00154 void
00155 Grid::conversion(Grid_Generator_System& source, Congruence_System& dest,
00156 Dimension_Kinds& dim_kinds) {
00157
00158
00159
00160 PPL_ASSERT(upper_triangular(source, dim_kinds));
00161
00162
00163
00164
00165
00166
00167
00168 dimension_type dest_num_rows = 0;
00169 PPL_DIRTY_TEMP_COEFFICIENT(diagonal_lcm);
00170 diagonal_lcm = 1;
00171 const dimension_type dims = source.space_dimension() + 1;
00172 dimension_type source_index = source.num_rows();
00173 for (dimension_type dim = dims; dim-- > 0; )
00174 if (dim_kinds[dim] == GEN_VIRTUAL)
00175
00176 ++dest_num_rows;
00177 else {
00178 --source_index;
00179 if (dim_kinds[dim] == PARAMETER) {
00180
00181
00182
00183 lcm_assign(diagonal_lcm, diagonal_lcm, source[source_index][dim]);
00184
00185 ++dest_num_rows;
00186 }
00187
00188 }
00189 PPL_ASSERT(source_index == 0);
00190
00191
00192 if (diagonal_lcm == 0)
00193 throw std::runtime_error("PPL internal error: Grid::conversion:"
00194 " source matrix is singular.");
00195
00196 dest.resize_no_copy(dest_num_rows, dims + 1 );
00197
00198
00199
00200
00201 dimension_type dest_index = 0;
00202 source_index = source.num_rows();
00203 for (dimension_type dim = dims; dim-- > 0; ) {
00204 if (dim_kinds[dim] == LINE)
00205 --source_index;
00206 else {
00207 Congruence& cg = dest[dest_index];
00208 for (dimension_type j = dim; j-- > 0; )
00209 cg[j] = 0;
00210 for (dimension_type j = dim + 1; j < dims; ++j)
00211 cg[j] = 0;
00212
00213 if (dim_kinds[dim] == GEN_VIRTUAL) {
00214 cg[dims] = 0;
00215 cg[dim] = 1;
00216 }
00217 else {
00218 PPL_ASSERT(dim_kinds[dim] == PARAMETER);
00219 --source_index;
00220 cg[dims] = 1;
00221 exact_div_assign(cg[dim], diagonal_lcm, source[source_index][dim]);
00222 }
00223 ++dest_index;
00224 }
00225 }
00226
00227 PPL_ASSERT(source_index == 0);
00228 PPL_ASSERT(dest_index == dest_num_rows);
00229 PPL_ASSERT(lower_triangular(dest, dim_kinds));
00230
00231
00232
00233
00234
00235
00236
00237
00238 source_index = source.num_rows();
00239 dest_index = 0;
00240 PPL_DIRTY_TEMP_COEFFICIENT(multiplier);
00241
00242 for (dimension_type dim = dims; dim-- > 0; ) {
00243 if (dim_kinds[dim] != GEN_VIRTUAL) {
00244 --source_index;
00245 const Coefficient& source_dim = source[source_index][dim];
00246
00247
00248
00249 for (dimension_type row = dest_index; row-- > 0; ) {
00250 Congruence& cg = dest[row];
00251
00252
00253
00254
00255 gcd_assign(multiplier, cg[dim], source_dim);
00256 exact_div_assign(multiplier, source_dim, multiplier);
00257 multiply_grid(multiplier, cg, dest, dest_num_rows, dims);
00258
00259 Coefficient& cg_dim = cg[dim];
00260 exact_div_assign(cg_dim, cg_dim, source_dim);
00261 }
00262 }
00263
00264
00265
00266
00267
00268
00269
00270 dimension_type tmp_source_index = source_index;
00271 if (dim_kinds[dim] != LINE)
00272 ++dest_index;
00273 for (dimension_type dim_prec = dim; dim_prec-- > 0; ) {
00274 if (dim_kinds[dim_prec] != GEN_VIRTUAL) {
00275 --tmp_source_index;
00276 const Coefficient& source_dim = source[tmp_source_index][dim];
00277
00278
00279
00280
00281
00282
00283
00284
00285 for (dimension_type row = dest_index; row-- > 0; ) {
00286 PPL_ASSERT(row < dest_num_rows);
00287 Congruence& cg = dest[row];
00288 sub_mul_assign(cg[dim_prec], source_dim, cg[dim]);
00289 }
00290 }
00291 }
00292 }
00293
00294 const Coefficient& modulus = dest[dest_num_rows - 1][0];
00295 for (dimension_type row = dest_num_rows; row-- > 0; ) {
00296 Congruence& cg = dest[row];
00297 if (cg[dims] > 0)
00298
00299 cg[dims] = modulus;
00300 }
00301
00302 PPL_ASSERT(lower_triangular(dest, dim_kinds));
00303
00304
00305
00306
00307 for (dimension_type dim = dims, i = 0; dim-- > 0; )
00308 if (dim_kinds[dim] != CON_VIRTUAL)
00309
00310 reduce_reduced<Congruence_System, Congruence>
00311 (dest, dim, i++, 0, dim, dim_kinds, false);
00312 }
00313
00314 void
00315 Grid::conversion(Congruence_System& source, Grid_Generator_System& dest,
00316 Dimension_Kinds& dim_kinds) {
00317
00318
00319
00320 PPL_ASSERT(lower_triangular(source, dim_kinds));
00321
00322
00323
00324 dimension_type source_num_rows = 0, dest_num_rows = 0;
00325 PPL_DIRTY_TEMP_COEFFICIENT(diagonal_lcm);
00326 diagonal_lcm = 1;
00327 dimension_type dims = source.num_columns() - 1;
00328 for (dimension_type dim = dims; dim-- > 0; )
00329 if (dim_kinds[dim] == CON_VIRTUAL)
00330
00331 ++dest_num_rows;
00332 else {
00333 if (dim_kinds[dim] == PROPER_CONGRUENCE) {
00334
00335
00336
00337 lcm_assign(diagonal_lcm, diagonal_lcm, source[source_num_rows][dim]);
00338
00339 ++dest_num_rows;
00340 }
00341
00342 ++source_num_rows;
00343 }
00344
00345
00346 if (diagonal_lcm == 0)
00347 throw std::runtime_error("PPL internal error: Grid::conversion:"
00348 " source matrix is singular.");
00349
00350 dest.set_index_first_pending_row(dest_num_rows);
00351 dest.resize_no_copy(dest_num_rows, dims + 1 );
00352
00353
00354
00355
00356
00357
00358
00359 dimension_type source_index = 0;
00360
00361 dimension_type dest_index = dest_num_rows - 1;
00362 for (dimension_type dim = dims; dim-- > 0; ) {
00363 if (dim_kinds[dim] == EQUALITY) {
00364 ++source_index;
00365 }
00366 else {
00367 Grid_Generator& g = dest[dest_index];
00368 for (dimension_type j = dim; j-- > 0; )
00369 g[j] = 0;
00370 for (dimension_type j = dim + 1; j < dims; ++j)
00371 g[j] = 0;
00372
00373 if (dim_kinds[dim] == CON_VIRTUAL) {
00374 g.set_is_line();
00375 g[dim] = 1;
00376 }
00377 else {
00378 PPL_ASSERT(dim_kinds[dim] == PROPER_CONGRUENCE);
00379 g.set_is_parameter_or_point();
00380 exact_div_assign(g[dim], diagonal_lcm, source[source_index][dim]);
00381 ++source_index;
00382 }
00383 --dest_index;
00384 }
00385 }
00386
00387 PPL_ASSERT(upper_triangular(dest, dim_kinds));
00388
00389
00390
00391
00392
00393
00394
00395
00396 source_index = source_num_rows;
00397 dest_index = 0;
00398 PPL_DIRTY_TEMP_COEFFICIENT(reduced_source_dim);
00399
00400 for (dimension_type dim = 0; dim < dims; ++dim) {
00401 if (dim_kinds[dim] != CON_VIRTUAL) {
00402 --source_index;
00403 const Coefficient& source_dim = source[source_index][dim];
00404
00405
00406
00407 for (dimension_type row = dest_index; row-- > 0; ) {
00408 Grid_Generator& g = dest[row];
00409
00410
00411
00412
00413 gcd_assign(reduced_source_dim, g[dim], source_dim);
00414 exact_div_assign(reduced_source_dim, source_dim, reduced_source_dim);
00415 multiply_grid(reduced_source_dim, g, dest, dest_num_rows,
00416 dims + 1 );
00417
00418 Coefficient& g_dim = g[dim];
00419 exact_div_assign(g_dim, g_dim, source_dim);
00420 }
00421 }
00422
00423
00424
00425
00426
00427
00428
00429 dimension_type tmp_source_index = source_index;
00430 if (dim_kinds[dim] != EQUALITY)
00431 ++dest_index;
00432 for (dimension_type dim_fol = dim + 1; dim_fol < dims; ++dim_fol) {
00433 if (dim_kinds[dim_fol] != CON_VIRTUAL) {
00434 --tmp_source_index;
00435 const Coefficient& source_dim = source[tmp_source_index][dim];
00436
00437
00438
00439
00440
00441
00442
00443
00444 for (dimension_type row = dest_index; row-- > 0; ) {
00445 PPL_ASSERT(row < dest_num_rows);
00446 Grid_Generator& g = dest[row];
00447 sub_mul_assign(g[dim_fol], source_dim, g[dim]);
00448 }
00449 }
00450 }
00451 }
00452
00453 PPL_ASSERT(upper_triangular(dest, dim_kinds));
00454
00455
00456
00457
00458 for (dimension_type dim = 0, i = 0; dim < dims; ++dim)
00459 if (dim_kinds[dim] != GEN_VIRTUAL)
00460
00461 reduce_reduced<Grid_Generator_System, Grid_Generator>
00462 (dest, dim, i++, dim, dims - 1, dim_kinds);
00463
00464
00465
00466 const Coefficient& system_divisor = dest[0][0];
00467 for (dimension_type row = dest.num_rows() - 1, dim = dims;
00468 dim-- > 1; )
00469 switch (dim_kinds[dim]) {
00470 case PARAMETER:
00471 dest[row].set_divisor(system_divisor);
00472 case LINE:
00473 --row;
00474 case GEN_VIRTUAL:
00475 break;
00476 }
00477 }
00478
00479 }