PPL  0.12.1
Affine_Space.cc
Go to the documentation of this file.
00001 /* Affine_Space class implementation.
00002    Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
00003    Copyright (C) 2010-2012 BUGSENG srl (http://bugseng.com)
00004 
00005 This file is part of the Parma Polyhedra Library (PPL).
00006 
00007 The PPL is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 The PPL is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with this program; if not, write to the Free Software Foundation,
00019 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
00020 
00021 For the most up-to-date information see the Parma Polyhedra Library
00022 site: http://bugseng.com/products/ppl/ . */
00023 
00024 #include "ppl-config.h"
00025 #include "Affine_Space.defs.hh"
00026 #include <iostream>
00027 
00028 namespace PPL = Parma_Polyhedra_Library;
00029 
00030 PPL::Affine_Space::Affine_Space(const Generator_System& gs) {
00031   dimension_type space_dim = gs.space_dimension();
00032   // First find a point or closure point and convert it to a
00033   // grid point and add to the (initially empty) set of grid generators.
00034   Grid_Generator_System ggs(space_dim);
00035   Linear_Expression point_expr;
00036   PPL_DIRTY_TEMP_COEFFICIENT(point_divisor);
00037   for (Generator_System::const_iterator g = gs.begin(),
00038          gs_end = gs.end(); g != gs_end; ++g) {
00039     if (g->is_ray())
00040       throw std::invalid_argument("Affine_Space::Affine_Space(gs):\n"
00041                                   "gs contains rays.");
00042     else if (g->is_point() || g->is_closure_point()) {
00043       for (dimension_type i = space_dim; i-- > 0; ) {
00044         const Variable v(i);
00045         point_expr += g->coefficient(v) * v;
00046         point_divisor = g->divisor();
00047       }
00048       ggs.insert(grid_point(point_expr, point_divisor));
00049       goto non_empty;
00050     }
00051   }
00052   // No (closure) point was found.
00053   Grid(EMPTY).m_swap(gr);
00054   return;
00055 
00056  non_empty:
00057   // Add a grid line for each line.  If the generator is a (closure)
00058   // point, the grid line must have the direction given by a line
00059   // that joins the grid point already inserted and the new point.
00060   PPL_DIRTY_TEMP_COEFFICIENT(coeff);
00061   PPL_DIRTY_TEMP_COEFFICIENT(g_divisor);
00062   for (Generator_System::const_iterator g = gs.begin(),
00063          gs_end = gs.end(); g != gs_end; ++g) {
00064     Linear_Expression e;
00065     if (g->is_point() || g->is_closure_point()) {
00066       g_divisor = g->divisor();
00067       for (dimension_type i = space_dim; i-- > 0; ) {
00068         const Variable v(i);
00069         coeff = point_expr.coefficient(v) * g_divisor;
00070         coeff -= g->coefficient(v) * point_divisor;
00071         e += coeff * v;
00072       }
00073       if (e.all_homogeneous_terms_are_zero())
00074         continue;
00075     }
00076     else
00077       for (dimension_type i = space_dim; i-- > 0; ) {
00078         const Variable v(i);
00079         e += g->coefficient(v) * v;
00080       }
00081     ggs.insert(grid_line(e));
00082   }
00083   Grid(ggs).m_swap(gr);
00084   PPL_ASSERT(OK());
00085 }
00086 
00087 
00088 PPL::Affine_Space&
00089 PPL::Affine_Space::operator=(const Affine_Space& y) {
00090   gr = y.gr;
00091   return *this;
00092 }
00093 
00094 PPL::dimension_type
00095 PPL::Affine_Space::affine_dimension() const {
00096   return gr.affine_dimension();
00097 }
00098 
00099 const PPL::Congruence_System&
00100 PPL::Affine_Space::congruences() const {
00101   return gr.congruences();
00102 }
00103 
00104 const PPL::Congruence_System&
00105 PPL::Affine_Space::minimized_congruences() const {
00106   return gr.minimized_congruences();
00107 }
00108 
00109 PPL::Generator_System
00110 PPL::Affine_Space::generators() const {
00111   // FIXME: implement by filtering the grid generators.
00112   abort();
00113 }
00114 
00115 PPL::Generator_System
00116 PPL::Affine_Space::minimized_generators() const {
00117   // FIXME: implement by filtering the grid generators.
00118   abort();
00119 }
00120 
00121 PPL::Poly_Con_Relation
00122 PPL::Affine_Space::relation_with(const Congruence& cg) const {
00123   return gr.relation_with(cg);
00124 }
00125 
00126 PPL::Poly_Gen_Relation
00127 PPL::Affine_Space::relation_with(const Generator& g) const {
00128   return gr.relation_with(g);
00129 }
00130 
00131 PPL::Poly_Con_Relation
00132 PPL::Affine_Space::relation_with(const Constraint& c) const {
00133   return gr.relation_with(c);
00134 }
00135 
00136 bool
00137 PPL::Affine_Space::is_empty() const {
00138   return gr.is_empty();
00139 }
00140 
00141 bool
00142 PPL::Affine_Space::is_universe() const {
00143   return gr.is_universe();
00144 }
00145 
00146 bool
00147 PPL::Affine_Space::is_bounded() const {
00148   return gr.is_bounded();
00149 }
00150 
00151 bool
00152 PPL::Affine_Space::is_discrete() const {
00153   return gr.is_discrete();
00154 }
00155 
00156 bool
00157 PPL::Affine_Space::is_topologically_closed() const {
00158   return true;
00159 }
00160 
00161 bool
00162 PPL::Affine_Space::contains_integer_point() const {
00163   return gr.contains_integer_point();
00164 }
00165 
00166 bool
00167 PPL::Affine_Space::constrains(const Variable var) const {
00168   return gr.constrains(var);
00169 }
00170 
00171 bool
00172 PPL::Affine_Space::OK(bool check_not_empty) const {
00173   return gr.OK(check_not_empty);
00174 }
00175 
00176 void
00177 PPL::Affine_Space::add_constraints(const Constraint_System& cs) {
00178   gr.add_constraints(cs);
00179 }
00180 
00181 void
00182 PPL::Affine_Space::add_generator(const Generator& /*g*/) {
00183   // FIXME: do we want this method?
00184   abort();
00185 }
00186 
00187 void
00188 PPL::Affine_Space::add_recycled_congruences(Congruence_System& /*cgs*/) {
00189   // FIXME: do we want this method?
00190   abort();
00191 }
00192 
00193 void
00194 PPL::Affine_Space::add_recycled_generators(Generator_System& /*gs*/) {
00195   // FIXME: do we want this method?
00196   abort();
00197 }
00198 
00199 void
00200 PPL::Affine_Space::add_generators(const Generator_System& /*gs*/) {
00201   // FIXME: do we want this method?
00202   abort();
00203 }
00204 
00205 void
00206 PPL::Affine_Space::refine_with_constraint(const Constraint& c) {
00207   gr.refine_with_constraint(c);
00208 }
00209 
00210 void
00211 PPL::Affine_Space::refine_with_constraints(const Constraint_System& cs) {
00212   gr.refine_with_constraints(cs);
00213 }
00214 
00215 void
00216 PPL::Affine_Space::unconstrain(const Variable var) {
00217   gr.unconstrain(var);
00218 }
00219 
00220 void
00221 PPL::Affine_Space::unconstrain(const Variables_Set& vars) {
00222   gr.unconstrain(vars);
00223 }
00224 
00225 void
00226 PPL::Affine_Space::intersection_assign(const Affine_Space& y) {
00227   gr.intersection_assign(y.gr);
00228 }
00229 
00230 void
00231 PPL::Affine_Space::upper_bound_assign(const Affine_Space& y) {
00232   // FIXME: horrible kludge to filter congruences away.
00233   gr.upper_bound_assign(y.gr);
00234   Affine_Space a(gr.constraints());
00235   m_swap(a);
00236 }
00237 
00238 bool
00239 PPL::Affine_Space::upper_bound_assign_if_exact(const Affine_Space& y) {
00240   return gr.upper_bound_assign_if_exact(y.gr);
00241 }
00242 
00243 void
00244 PPL::Affine_Space::difference_assign(const Affine_Space& y) {
00245   gr.difference_assign(y.gr);
00246 }
00247 
00248 bool
00249 PPL::Affine_Space::simplify_using_context_assign(const Affine_Space& y) {
00250   return gr.simplify_using_context_assign(y.gr);
00251 }
00252 
00253 void
00254 PPL::Affine_Space::affine_image(const Variable var,
00255                                 const Linear_Expression& expr,
00256                                 Coefficient_traits::const_reference
00257                                 denominator) {
00258   gr.affine_image(var, expr, denominator);
00259 }
00260 
00261 void
00262 PPL::Affine_Space::
00263 affine_preimage(const Variable var,
00264                 const Linear_Expression& expr,
00265                 Coefficient_traits::const_reference denominator) {
00266   gr.affine_preimage(var, expr, denominator);
00267 }
00268 
00269 void
00270 PPL::Affine_Space::
00271 generalized_affine_image(const Variable var,
00272                          const Relation_Symbol relsym,
00273                          const Linear_Expression& expr,
00274                          Coefficient_traits::const_reference denominator) {
00275   gr.generalized_affine_image(var, relsym, expr, denominator);
00276 }
00277 
00278 void
00279 PPL::Affine_Space::
00280 generalized_affine_preimage(const Variable var,
00281                             const Relation_Symbol relsym,
00282                             const Linear_Expression& expr,
00283                             Coefficient_traits::const_reference denominator) {
00284   gr.generalized_affine_preimage(var, relsym, expr, denominator);
00285 }
00286 
00287 void
00288 PPL::Affine_Space::
00289 generalized_affine_image(const Linear_Expression& lhs,
00290                          const Relation_Symbol relsym,
00291                          const Linear_Expression& rhs) {
00292   gr.generalized_affine_image(lhs, relsym, rhs);
00293 }
00294 
00295 void
00296 PPL::Affine_Space::
00297 generalized_affine_preimage(const Linear_Expression& lhs,
00298                             const Relation_Symbol relsym,
00299                             const Linear_Expression& rhs) {
00300   gr.generalized_affine_preimage(lhs, relsym, rhs);
00301 }
00302 
00303 void
00304 PPL::Affine_Space::
00305 bounded_affine_image(const Variable var,
00306                      const Linear_Expression& lb_expr,
00307                      const Linear_Expression& ub_expr,
00308                      Coefficient_traits::const_reference denominator) {
00309   gr.bounded_affine_image(var, lb_expr, ub_expr, denominator);
00310 }
00311 
00312 
00313 void
00314 PPL::Affine_Space::
00315 bounded_affine_preimage(const Variable var,
00316                         const Linear_Expression& lb_expr,
00317                         const Linear_Expression& ub_expr,
00318                         Coefficient_traits::const_reference denominator) {
00319   gr.bounded_affine_preimage(var, lb_expr, ub_expr, denominator);
00320 }
00321 
00322 void
00323 PPL::Affine_Space::time_elapse_assign(const Affine_Space& y) {
00324   gr.time_elapse_assign(y.gr);
00325 }
00326 
00328 bool
00329 PPL::operator==(const Affine_Space& x, const Affine_Space& y) {
00330   return x.gr == y.gr;
00331 }
00332 
00333 bool
00334 PPL::Affine_Space::contains(const Affine_Space& y) const {
00335   return gr.contains(y.gr);
00336 }
00337 
00338 bool
00339 PPL::Affine_Space::is_disjoint_from(const Affine_Space& y) const {
00340   return gr.is_disjoint_from(y.gr);
00341 }
00342 
00343 void
00344 PPL::Affine_Space::ascii_dump(std::ostream& s) const {
00345   gr.ascii_dump(s);
00346 }
00347 
00348 PPL_OUTPUT_DEFINITIONS(Affine_Space)
00349 
00350 bool
00351 PPL::Affine_Space::ascii_load(std::istream& s) {
00352   return gr.ascii_load(s);
00353 }
00354 
00355 PPL::memory_size_type
00356 PPL::Affine_Space::external_memory_in_bytes() const {
00357   return gr.external_memory_in_bytes();
00358 }
00359 
00360 void
00361 PPL::Affine_Space::add_space_dimensions_and_embed(dimension_type m) {
00362   gr.add_space_dimensions_and_embed(m);
00363 }
00364 
00365 void
00366 PPL::Affine_Space::add_space_dimensions_and_project(dimension_type m) {
00367   gr.add_space_dimensions_and_project(m);
00368 }
00369 
00370 void
00371 PPL::Affine_Space::concatenate_assign(const Affine_Space& y) {
00372   gr.concatenate_assign(y.gr);
00373 }
00374 
00375 void
00376 PPL::Affine_Space::remove_space_dimensions(const Variables_Set& vars) {
00377   gr.remove_space_dimensions(vars);
00378 }
00379 
00380 void
00381 PPL::Affine_Space::remove_higher_space_dimensions(const dimension_type
00382                                                   new_dimension) {
00383   gr.remove_higher_space_dimensions(new_dimension);
00384 }
00385 
00386 void
00387 PPL::Affine_Space::expand_space_dimension(Variable var, dimension_type m) {
00388   gr.expand_space_dimension(var, m);
00389 }
00390 
00391 void
00392 PPL::Affine_Space::fold_space_dimensions(const Variables_Set& to_be_folded,
00393                                          Variable var) {
00394   gr.fold_space_dimensions(to_be_folded, var);
00395 }
00396 
00397 void
00398 PPL::Affine_Space::widening_assign(const Affine_Space& y, unsigned*) {
00399   Affine_Space& x = *this;
00400 
00401   // Dimension-compatibility check.
00402   if (x.space_dimension() != y.space_dimension())
00403     throw_dimension_incompatible("widening_assign(y)", "y", y);
00404 
00405   // Assume `y' is contained in or equal to `x'.
00406   PPL_EXPECT_HEAVY(copy_contains(x, y));
00407 }
00408 
00409 void
00410 PPL::Affine_Space::limited_extrapolation_assign(const Affine_Space& y,
00411                                                 const Constraint_System&,
00412                                                 unsigned*) {
00413   Affine_Space& x = *this;
00414 
00415   // Dimension-compatibility check.
00416   if (x.space_dimension() != y.space_dimension())
00417     throw_dimension_incompatible("widening_assign(y)", "y", y);
00418 
00419   // Assume `y' is contained in or equal to `x'.
00420   PPL_EXPECT_HEAVY(copy_contains(x, y));
00421 }
00422 
00424 std::ostream&
00425 PPL::IO_Operators::operator<<(std::ostream& s, const Affine_Space& gr) {
00426   s << gr;
00427   return s;
00428 }
00429 
00430 void
00431 PPL::Affine_Space
00432 ::throw_dimension_incompatible(const char* method,
00433                                const char* other_name,
00434                                dimension_type other_dim) const {
00435   std::ostringstream s;
00436   s << "PPL::Affine_Space::" << method << ":\n"
00437     << "this->space_dimension() == " << space_dimension() << ", "
00438     << other_name << ".space_dimension() == " << other_dim << ".";
00439   throw std::invalid_argument(s.str());
00440 }
00441 
00442 void
00443 PPL::Affine_Space
00444 ::throw_dimension_incompatible(const char* method,
00445                                const char* as_name,
00446                                const Affine_Space& as) const {
00447   throw_dimension_incompatible(method, as_name, as.space_dimension());
00448 }
00449