Parma_Polyhedra_Library::Grid Class Reference
[C++ Language Interface]

A grid. More...

#include <Grid.defs.hh>

Collaboration diagram for Parma_Polyhedra_Library::Grid:
Collaboration graph
[legend]

List of all members.

Classes

class  Status
 A conjunctive assertion about a grid. More...

Public Types

typedef Coefficient coefficient_type
 The numeric type of coefficients.

Public Member Functions

 Grid (dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
 Builds a grid having the specified properties.
 Grid (const Congruence_System &cgs)
 Builds a grid, copying a system of congruences.
 Grid (Congruence_System &cgs, Recycle_Input dummy)
 Builds a grid, recycling a system of congruences.
 Grid (const Constraint_System &cs)
 Builds a grid, copying a system of constraints.
 Grid (Constraint_System &cs, Recycle_Input dummy)
 Builds a grid, recycling a system of constraints.
 Grid (const Grid_Generator_System &const_gs)
 Builds a grid, copying a system of grid generators.
 Grid (Grid_Generator_System &gs, Recycle_Input dummy)
 Builds a grid, recycling a system of grid generators.
template<typename Interval >
 Grid (const Box< Interval > &box, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds a grid out of a box.
template<typename U >
 Grid (const BD_Shape< U > &bd, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds a grid out of a bounded-difference shape.
template<typename U >
 Grid (const Octagonal_Shape< U > &os, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds a grid out of an octagonal shape.
 Grid (const Polyhedron &ph, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds a grid from a polyhedron using algorithms whose complexity does not exceed the one specified by complexity. If complexity is ANY_COMPLEXITY, then the grid built is the smallest one containing ph.
 Grid (const Grid &y, Complexity_Class complexity=ANY_COMPLEXITY)
 Ordinary copy constructor.
Gridoperator= (const Grid &y)
 The assignment operator. (*this and y can be dimension-incompatible.).
Member Functions that Do Not Modify the Grid

dimension_type space_dimension () const
 Returns the dimension of the vector space enclosing *this.
dimension_type affine_dimension () const
 Returns $0$, if *this is empty; otherwise, returns the affine dimension of *this.
Constraint_System constraints () const
 Returns a system of equality constraints satisfied by *this with the same affine dimension as *this.
Constraint_System minimized_constraints () const
 Returns a minimal system of equality constraints satisfied by *this with the same affine dimension as *this.
const Congruence_Systemcongruences () const
 Returns the system of congruences.
const Congruence_Systemminimized_congruences () const
 Returns the system of congruences in minimal form.
const Grid_Generator_Systemgrid_generators () const
 Returns the system of generators.
const Grid_Generator_Systemminimized_grid_generators () const
 Returns the minimized system of generators.
Poly_Con_Relation relation_with (const Congruence &cg) const
 Returns the relations holding between *this and cg.
Poly_Gen_Relation relation_with (const Grid_Generator &g) const
 Returns the relations holding between *this and g.
Poly_Gen_Relation relation_with (const Generator &g) const
 Returns the relations holding between *this and g.
Poly_Con_Relation relation_with (const Constraint &c) const
 Returns the relations holding between *this and c.
bool is_empty () const
 Returns true if and only if *this is an empty grid.
bool is_universe () const
 Returns true if and only if *this is a universe grid.
bool is_topologically_closed () const
 Returns true if and only if *this is a topologically closed subset of the vector space.
bool is_disjoint_from (const Grid &y) const
 Returns true if and only if *this and y are disjoint.
bool is_discrete () const
 Returns true if and only if *this is discrete.
bool is_bounded () const
 Returns true if and only if *this is bounded.
bool contains_integer_point () const
 Returns true if and only if *this contains at least one integer point.
bool constrains (Variable var) const
 Returns true if and only if var is constrained in *this.
bool bounds_from_above (const Linear_Expression &expr) const
 Returns true if and only if expr is bounded in *this.
bool bounds_from_below (const Linear_Expression &expr) const
 Returns true if and only if expr is bounded in *this.
bool maximize (const Linear_Expression &expr, Coefficient &sup_n, Coefficient &sup_d, bool &maximum) const
 Returns true if and only if *this is not empty and expr is bounded from above in *this, in which case the supremum value is computed.
bool maximize (const Linear_Expression &expr, Coefficient &sup_n, Coefficient &sup_d, bool &maximum, Generator &point) const
 Returns true if and only if *this is not empty and expr is bounded from above in *this, in which case the supremum value and a point where expr reaches it are computed.
bool minimize (const Linear_Expression &expr, Coefficient &inf_n, Coefficient &inf_d, bool &minimum) const
 Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value is computed.
bool minimize (const Linear_Expression &expr, Coefficient &inf_n, Coefficient &inf_d, bool &minimum, Generator &point) const
 Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value and a point where expr reaches it are computed.
bool frequency (const Linear_Expression &expr, Coefficient &freq_n, Coefficient &freq_d, Coefficient &val_n, Coefficient &val_d) const
 Returns true if and only if *this is not empty and frequency for *this with respect to expr is defined, in which case the frequency and the value for expr that is closest to zero are computed.
bool contains (const Grid &y) const
 Returns true if and only if *this contains y.
bool strictly_contains (const Grid &y) const
 Returns true if and only if *this strictly contains y.
bool OK (bool check_not_empty=false) const
 Checks if all the invariants are satisfied.
Space Dimension Preserving Member Functions that May Modify the Grid

void add_congruence (const Congruence &cg)
 Adds a copy of congruence cg to *this.
void add_grid_generator (const Grid_Generator &g)
 Adds a copy of grid generator g to the system of generators of *this.
void add_congruences (const Congruence_System &cgs)
 Adds a copy of each congruence in cgs to *this.
void add_recycled_congruences (Congruence_System &cgs)
 Adds the congruences in cgs to *this.
void add_constraint (const Constraint &c)
 Adds to *this a congruence equivalent to constraint c.
void add_constraints (const Constraint_System &cs)
 Adds to *this congruences equivalent to the constraints in cs.
void add_recycled_constraints (Constraint_System &cs)
 Adds to *this congruences equivalent to the constraints in cs.
void refine_with_congruence (const Congruence &cg)
 Uses a copy of the congruence cg to refine *this.
void refine_with_congruences (const Congruence_System &cgs)
 Uses a copy of the congruences in cgs to refine *this.
void refine_with_constraint (const Constraint &c)
 Uses a copy of the constraint c to refine *this.
void refine_with_constraints (const Constraint_System &cs)
 Uses a copy of the constraints in cs to refine *this.
void add_grid_generators (const Grid_Generator_System &gs)
 Adds a copy of the generators in gs to the system of generators of *this.
void add_recycled_grid_generators (Grid_Generator_System &gs)
 Adds the generators in gs to the system of generators of this.
void unconstrain (Variable var)
 Computes the cylindrification of *this with respect to space dimension var, assigning the result to *this.
void unconstrain (const Variables_Set &vars)
 Computes the cylindrification of *this with respect to the set of space dimensions vars, assigning the result to *this.
void intersection_assign (const Grid &y)
 Assigns to *this the intersection of *this and y.
void upper_bound_assign (const Grid &y)
 Assigns to *this the least upper bound of *this and y.
bool upper_bound_assign_if_exact (const Grid &y)
 If the upper bound of *this and y is exact it is assigned to this and true is returned, otherwise false is returned.
void difference_assign (const Grid &y)
 Assigns to *this the grid-difference of *this and y.
bool simplify_using_context_assign (const Grid &y)
 Assigns to *this a meet-preserving simplification of *this with respect to y. If false is returned, then the intersection is empty.
void affine_image (Variable var, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the affine image of this under the function mapping variable var to the affine expression specified by expr and denominator.
void affine_preimage (Variable var, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the affine preimage of *this under the function mapping variable var to the affine expression specified by expr and denominator.
void generalized_affine_image (Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one(), Coefficient_traits::const_reference modulus=Coefficient_zero())
 Assigns to *this the image of *this with respect to the generalized affine relation $\mathrm{var}' = \frac{\mathrm{expr}}{\mathrm{denominator}} \pmod{\mathrm{modulus}}$.
void generalized_affine_preimage (Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one(), Coefficient_traits::const_reference modulus=Coefficient_zero())
 Assigns to *this the preimage of *this with respect to the generalized affine relation $\mathrm{var}' = \frac{\mathrm{expr}}{\mathrm{denominator}} \pmod{\mathrm{modulus}}$.
void generalized_affine_image (const Linear_Expression &lhs, Relation_Symbol relsym, const Linear_Expression &rhs, Coefficient_traits::const_reference modulus=Coefficient_zero())
 Assigns to *this the image of *this with respect to the generalized affine relation $\mathrm{lhs}' = \mathrm{rhs} \pmod{\mathrm{modulus}}$.
void generalized_affine_preimage (const Linear_Expression &lhs, Relation_Symbol relsym, const Linear_Expression &rhs, Coefficient_traits::const_reference modulus=Coefficient_zero())
 Assigns to *this the preimage of *this with respect to the generalized affine relation $\mathrm{lhs}' = \mathrm{rhs} \pmod{\mathrm{modulus}}$.
void bounded_affine_image (Variable var, const Linear_Expression &lb_expr, const Linear_Expression &ub_expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the image of *this with respect to the bounded affine relation $\frac{\mathrm{lb\_expr}}{\mathrm{denominator}} \leq \mathrm{var}' \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}$.
void bounded_affine_preimage (Variable var, const Linear_Expression &lb_expr, const Linear_Expression &ub_expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the preimage of *this with respect to the bounded affine relation $\frac{\mathrm{lb\_expr}}{\mathrm{denominator}} \leq \mathrm{var}' \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}$.
void time_elapse_assign (const Grid &y)
 Assigns to *this the result of computing the time-elapse between *this and y.
void wrap_assign (const Variables_Set &vars, Bounded_Integer_Type_Width w, Bounded_Integer_Type_Representation r, Bounded_Integer_Type_Overflow o, const Constraint_System *pcs=0, unsigned complexity_threshold=16, bool wrap_individually=true)
 Wraps the specified dimensions of the vector space.
void drop_some_non_integer_points (Complexity_Class complexity=ANY_COMPLEXITY)
 Possibly tightens *this by dropping all points with non-integer coordinates.
void drop_some_non_integer_points (const Variables_Set &vars, Complexity_Class complexity=ANY_COMPLEXITY)
 Possibly tightens *this by dropping all points with non-integer coordinates for the space dimensions corresponding to vars.
void topological_closure_assign ()
 Assigns to *this its topological closure.
void congruence_widening_assign (const Grid &y, unsigned *tp=NULL)
 Assigns to *this the result of computing the Grid widening between *this and y using congruence systems.
void generator_widening_assign (const Grid &y, unsigned *tp=NULL)
 Assigns to *this the result of computing the Grid widening between *this and y using generator systems.
void widening_assign (const Grid &y, unsigned *tp=NULL)
 Assigns to *this the result of computing the Grid widening between *this and y.
void limited_congruence_extrapolation_assign (const Grid &y, const Congruence_System &cgs, unsigned *tp=NULL)
 Improves the result of the congruence variant of Grid widening computation by also enforcing those congruences in cgs that are satisfied by all the points of *this.
void limited_generator_extrapolation_assign (const Grid &y, const Congruence_System &cgs, unsigned *tp=NULL)
 Improves the result of the generator variant of the Grid widening computation by also enforcing those congruences in cgs that are satisfied by all the points of *this.
void limited_extrapolation_assign (const Grid &y, const Congruence_System &cgs, unsigned *tp=NULL)
 Improves the result of the Grid widening computation by also enforcing those congruences in cgs that are satisfied by all the points of *this.
Member Functions that May Modify the Dimension of the Vector Space

void add_space_dimensions_and_embed (dimension_type m)
 Adds m new space dimensions and embeds the old grid in the new vector space.
void add_space_dimensions_and_project (dimension_type m)
 Adds m new space dimensions to the grid and does not embed it in the new vector space.
void concatenate_assign (const Grid &y)
 Assigns to *this the concatenation of *this and y, taken in this order.
void remove_space_dimensions (const Variables_Set &vars)
 Removes all the specified dimensions from the vector space.
void remove_higher_space_dimensions (dimension_type new_dimension)
 Removes the higher dimensions of the vector space so that the resulting space will have dimension new_dimension..
template<typename Partial_Function >
void map_space_dimensions (const Partial_Function &pfunc)
 Remaps the dimensions of the vector space according to a partial function.
void expand_space_dimension (Variable var, dimension_type m)
 Creates m copies of the space dimension corresponding to var.
void fold_space_dimensions (const Variables_Set &vars, Variable dest)
 Folds the space dimensions in vars into dest.
Miscellaneous Member Functions

 ~Grid ()
 Destructor.
void swap (Grid &y)
 Swaps *this with grid y. (*this and y can be dimension-incompatible.).
void ascii_dump () const
 Writes to std::cerr an ASCII representation of *this.
void ascii_dump (std::ostream &s) const
 Writes to s an ASCII representation of *this.
void print () const
 Prints *this to std::cerr using operator<<.
bool ascii_load (std::istream &s)
 Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this accordingly. Returns true if successful, false otherwise.
memory_size_type total_memory_in_bytes () const
 Returns the total size in bytes of the memory occupied by *this.
memory_size_type external_memory_in_bytes () const
 Returns the size in bytes of the memory managed by *this.
int32_t hash_code () const
 Returns a 32-bit hash code for *this.

Static Public Member Functions

static dimension_type max_space_dimension ()
 Returns the maximum space dimension all kinds of Grid can handle.
static bool can_recycle_congruence_systems ()
 Returns true indicating that this domain has methods that can recycle congruences.
static bool can_recycle_constraint_systems ()
 Returns true indicating that this domain has methods that can recycle constraints.

Private Types

enum  Dimension_Kind {
  PARAMETER, LINE, GEN_VIRTUAL, PROPER_CONGRUENCE = PARAMETER,
  CON_VIRTUAL = LINE, EQUALITY = GEN_VIRTUAL
}
enum  Three_Valued_Boolean { TVB_TRUE, TVB_FALSE, TVB_DONT_KNOW }
typedef std::vector
< Dimension_Kind
Dimension_Kinds

Private Member Functions

void construct (dimension_type num_dimensions, Degenerate_Element kind)
 Builds a grid universe or empty grid.
void construct (Congruence_System &cgs)
 Builds a grid from a system of congruences.
void construct (Grid_Generator_System &ggs)
 Builds a grid from a system of grid generators.
Three_Valued_Boolean quick_equivalence_test (const Grid &y) const
 Polynomial but incomplete equivalence test between grids.
bool is_included_in (const Grid &y) const
 Returns true if and only if *this is included in y.
bool bounds (const Linear_Expression &expr, const char *method_call) const
 Checks if and how expr is bounded in *this.
bool max_min (const Linear_Expression &expr, const char *method_call, Coefficient &ext_n, Coefficient &ext_d, bool &included, Generator *point=NULL) const
 Maximizes or minimizes expr subject to *this.
bool frequency_no_check (const Linear_Expression &expr, Coefficient &freq_n, Coefficient &freq_d, Coefficient &val_n, Coefficient &val_d) const
 Returns true if and only if *this is not empty and frequency for *this with respect to expr is defined, in which case the frequency and the value for expr that is closest to zero are computed.
bool bounds_no_check (const Linear_Expression &expr) const
 Checks if and how expr is bounded in *this.
void add_congruence_no_check (const Congruence &cg)
 Adds the congruence cg to *this.
void add_constraint_no_check (const Constraint &c)
 Uses the constraint c to refine *this.
void refine_no_check (const Constraint &c)
 Uses the constraint c to refine *this.
void add_space_dimensions (Congruence_System &cgs, Grid_Generator_System &gs, dimension_type dims)
 Adds new space dimensions to the given systems.
void add_space_dimensions (Grid_Generator_System &gs, Congruence_System &cgs, dimension_type dims)
 Adds new space dimensions to the given systems.
Private Verifiers: Verify if Individual Flags are Set

bool marked_empty () const
 Returns true if the grid is known to be empty.
bool congruences_are_up_to_date () const
 Returns true if the system of congruences is up-to-date.
bool generators_are_up_to_date () const
 Returns true if the system of generators is up-to-date.
bool congruences_are_minimized () const
 Returns true if the system of congruences is minimized.
bool generators_are_minimized () const
 Returns true if the system of generators is minimized.
State Flag Setters: Set Only the Specified Flags

void set_zero_dim_univ ()
 Sets status to express that the grid is the universe 0-dimension vector space, clearing all corresponding matrices.
void set_empty ()
 Sets status to express that the grid is empty, clearing all corresponding matrices.
void set_congruences_up_to_date ()
 Sets status to express that congruences are up-to-date.
void set_generators_up_to_date ()
 Sets status to express that generators are up-to-date.
void set_congruences_minimized ()
 Sets status to express that congruences are minimized.
void set_generators_minimized ()
 Sets status to express that generators are minimized.
State Flag Cleaners: Clear Only the Specified Flag

void clear_empty ()
 Clears the status flag indicating that the grid is empty.
void clear_congruences_up_to_date ()
 Sets status to express that congruences are out of date.
void clear_generators_up_to_date ()
 Sets status to express that generators are out of date.
void clear_congruences_minimized ()
 Sets status to express that congruences are no longer minimized.
void clear_generators_minimized ()
 Sets status to express that generators are no longer minimized.
Updating Matrices

void update_congruences () const
 Updates and minimizes the congruences from the generators.
bool update_generators () const
 Updates and minimizes the generators from the congruences.
Minimization of Descriptions

bool minimize () const
 Minimizes both the congruences and the generators.
Widening- and Extrapolation-Related Functions

void select_wider_congruences (const Grid &y, Congruence_System &selected_cgs) const
 Copies a widened selection of congruences from y to selected_cgs.
void select_wider_generators (const Grid &y, Grid_Generator_System &widened_ggs) const
 Copies widened generators from y to widened_ggs.

Static Private Member Functions

Minimization-related Static Member Functions

static void normalize_divisors (Grid_Generator_System &sys, Coefficient &divisor, const Grid_Generator *first_point=NULL)
 Normalizes the divisors in sys.
static void normalize_divisors (Grid_Generator_System &sys)
 Normalizes the divisors in sys.
static void normalize_divisors (Grid_Generator_System &sys, Grid_Generator_System &gen_sys)
 Normalize all the divisors in sys and gen_sys.
static void conversion (Congruence_System &source, Grid_Generator_System &dest, Dimension_Kinds &dim_kinds)
 Converts generator system dest to be equivalent to congruence system source.
static void conversion (Grid_Generator_System &source, Congruence_System &dest, Dimension_Kinds &dim_kinds)
 Converts congruence system dest to be equivalent to generator system source.
static bool simplify (Congruence_System &cgs, Dimension_Kinds &dim_kinds)
 Converts cgs to upper triangular (i.e. minimized) form.
static void simplify (Grid_Generator_System &gs, Dimension_Kinds &dim_kinds)
 Converts gs to lower triangular (i.e. minimized) form.
static void reduce_line_with_line (Grid_Generator &row, Grid_Generator &pivot, dimension_type col)
 Reduces the line row using the line pivot.
static void reduce_equality_with_equality (Congruence &row, const Congruence &pivot, dimension_type col)
 Reduces the equality row using the equality pivot.
template<typename R >
static void reduce_pc_with_pc (R &row, R &pivot, dimension_type col, dimension_type start, dimension_type end)
 Reduces row using pivot.
static void reduce_parameter_with_line (Grid_Generator &row, const Grid_Generator &pivot, dimension_type col, Grid_Generator_System &sys)
 Reduce row using pivot.
static void reduce_congruence_with_equality (Congruence &row, const Congruence &pivot, dimension_type col, Congruence_System &sys)
 Reduce row using pivot.
template<typename M , typename R >
static void reduce_reduced (M &sys, dimension_type dim, dimension_type pivot_index, dimension_type start, dimension_type end, const Dimension_Kinds &dim_kinds, bool generators=true)
 Reduce column dim in rows preceding pivot_index in sys.
static void multiply_grid (const Coefficient &multiplier, Congruence &cg, Congruence_System &dest, dimension_type num_rows, dimension_type num_dims)
 Multiply the elements of dest by multiplier.
static void multiply_grid (const Coefficient &multiplier, Grid_Generator &gen, Grid_Generator_System &dest, dimension_type num_rows, dimension_type num_dims)
 Multiply the elements of dest by multiplier.
static bool lower_triangular (const Congruence_System &sys, const Dimension_Kinds &dim_kinds)
 If sys is lower triangular return true, else return false.
static bool upper_triangular (const Grid_Generator_System &sys, const Dimension_Kinds &dim_kinds)
 If sys is upper triangular return true, else return false.
template<typename M , typename R >
static bool rows_are_zero (M &system, dimension_type first, dimension_type last, dimension_type row_size)
 Checks that trailing rows contain only zero terms.

Private Attributes

Congruence_System con_sys
 The system of congruences.
Grid_Generator_System gen_sys
 The system of generators.
Status status
 The status flags to keep track of the grid's internal state.
dimension_type space_dim
 The number of dimensions of the enclosing vector space.
Dimension_Kinds dim_kinds

Friends

class Parma_Polyhedra_Library::Grid_Certificate
class Parma_Polyhedra_Library::Box
bool operator== (const Grid &x, const Grid &y)
 Returns true if and only if x and y are the same grid.

Related Functions

(Note that these are not member functions.)



std::ostream & operator<< (std::ostream &s, const Grid &gr)
 Output operator.
bool operator!= (const Grid &x, const Grid &y)
 Returns true if and only if x and y are different grids.
void swap (Parma_Polyhedra_Library::Grid &x, Parma_Polyhedra_Library::Grid &y)
 Specializes std::swap.

Exception Throwers



void throw_runtime_error (const char *method) const
void throw_invalid_argument (const char *method, const char *reason) const
void throw_dimension_incompatible (const char *method, const char *other_name, dimension_type other_dim) const
void throw_dimension_incompatible (const char *method, const char *gr_name, const Grid &gr) const
void throw_dimension_incompatible (const char *method, const char *e_name, const Linear_Expression &e) const
void throw_dimension_incompatible (const char *method, const char *cg_name, const Congruence &cg) const
void throw_dimension_incompatible (const char *method, const char *c_name, const Constraint &c) const
void throw_dimension_incompatible (const char *method, const char *g_name, const Grid_Generator &g) const
void throw_dimension_incompatible (const char *method, const char *g_name, const Generator &g) const
void throw_dimension_incompatible (const char *method, const char *cgs_name, const Congruence_System &cgs) const
void throw_dimension_incompatible (const char *method, const char *cs_name, const Constraint_System &cs) const
void throw_dimension_incompatible (const char *method, const char *gs_name, const Grid_Generator_System &gs) const
void throw_dimension_incompatible (const char *method, const char *var_name, Variable var) const
void throw_dimension_incompatible (const char *method, dimension_type required_space_dim) const
void throw_invalid_constraint (const char *method, const char *c_name) const
void throw_invalid_constraints (const char *method, const char *cs_name) const
void throw_invalid_generator (const char *method, const char *g_name) const
void throw_invalid_generators (const char *method, const char *gs_name) const
static void throw_space_dimension_overflow (const char *method, const char *reason)

Detailed Description

A grid.

An object of the class Grid represents a rational grid.

The domain of grids optimally supports:

Depending on the method, using a constraint that is not optimally supported by the domain will either raise an exception or result in a (possibly non-optimal) upward approximation.

The domain of grids support a concept of double description similar to the one developed for polyhedra: hence, a grid can be specified as either a finite system of congruences or a finite system of generators (see Section Rational Grids) and it is always possible to obtain either representation. That is, if we know the system of congruences, we can obtain from this a system of generators that define the same grid and vice versa. These systems can contain redundant members, or they can be in the minimal form.

A key attribute of any grid is its space dimension (the dimension $n \in \Nset$ of the enclosing vector space):

Note that two different grids can be defined on the zero-dimension space: the empty grid and the universe grid $R^0$.

In all the examples it is assumed that variables x and y are defined (where they are used) as follows:
  Variable x(0);
  Variable y(1);
Example 1
The following code builds a grid corresponding to the even integer pairs in $\Rset^2$, given as a system of congruences:
  Congruence_System cgs;
  cgs.insert((x %= 0) / 2);
  cgs.insert((y %= 0) / 2);
  Grid gr(cgs);
The following code builds the same grid as above, but starting from a system of generators specifying three of the points:
  Grid_Generator_System gs;
  gs.insert(grid_point(0*x + 0*y));
  gs.insert(grid_point(0*x + 2*y));
  gs.insert(grid_point(2*x + 0*y));
  Grid gr(gs);
Example 2
The following code builds a grid corresponding to a line in $\Rset^2$ by adding a single congruence to the universe grid:
  Congruence_System cgs;
  cgs.insert(x - y == 0);
  Grid gr(cgs);
The following code builds the same grid as above, but starting from a system of generators specifying a point and a line:
  Grid_Generator_System gs;
  gs.insert(grid_point(0*x + 0*y));
  gs.insert(grid_line(x + y));
  Grid gr(gs);
Example 3
The following code builds a grid corresponding to the integral points on the line $x = y$ in $\Rset^2$ constructed by adding an equality and congruence to the universe grid:
  Congruence_System cgs;
  cgs.insert(x - y == 0);
  cgs.insert(x %= 0);
  Grid gr(cgs);
The following code builds the same grid as above, but starting from a system of generators specifying a point and a parameter:
  Grid_Generator_System gs;
  gs.insert(grid_point(0*x + 0*y));
  gs.insert(parameter(x + y));
  Grid gr(gs);
Example 4
The following code builds the grid corresponding to a plane by creating the universe grid in $\Rset^2$:
  Grid gr(2);
The following code builds the same grid as above, but starting from the empty grid in $\Rset^2$ and inserting the appropriate generators (a point, and two lines).
  Grid gr(2, EMPTY);
  gr.add_grid_generator(grid_point(0*x + 0*y));
  gr.add_grid_generator(grid_line(x));
  gr.add_grid_generator(grid_line(y));
Note that a generator system must contain a point when describing a grid. To ensure that this is always the case it is required that the first generator inserted in an empty grid is a point (otherwise, an exception is thrown).
Example 5
The following code shows the use of the function add_space_dimensions_and_embed:
  Grid gr(1);
  gr.add_congruence(x == 2);
  gr.add_space_dimensions_and_embed(1);
We build the universe grid in the 1-dimension space $\Rset$. Then we add a single equality congruence, thus obtaining the grid corresponding to the singleton set $\{ 2 \} \sseq \Rset$. After the last line of code, the resulting grid is

\[ \bigl\{\, (2, y)^\transpose \in \Rset^2 \bigm| y \in \Rset \,\bigr\}. \]

Example 6
The following code shows the use of the function add_space_dimensions_and_project:
  Grid gr(1);
  gr.add_congruence(x == 2);
  gr.add_space_dimensions_and_project(1);
The first two lines of code are the same as in Example 4 for add_space_dimensions_and_embed. After the last line of code, the resulting grid is the singleton set $\bigl\{ (2, 0)^\transpose \bigr\} \sseq \Rset^2$.
Example 7
The following code shows the use of the function affine_image:
  Grid gr(2, EMPTY);
  gr.add_grid_generator(grid_point(0*x + 0*y));
  gr.add_grid_generator(grid_point(4*x + 0*y));
  gr.add_grid_generator(grid_point(0*x + 2*y));
  Linear_Expression expr = x + 3;
  gr.affine_image(x, expr);
In this example the starting grid is all the pairs of $x$ and $y$ in $\Rset^2$ where $x$ is an integer multiple of 4 and $y$ is an integer multiple of 2. The considered variable is $x$ and the affine expression is $x+3$. The resulting grid is the given grid translated 3 integers to the right (all the pairs $(x, y)$ where $x$ is -1 plus an integer multiple of 4 and $y$ is an integer multiple of 2). Moreover, if the affine transformation for the same variable x is instead $x+y$:
  Linear_Expression expr = x + y;
the resulting grid is every second integral point along the $x=y$ line, with this line of points repeated at every fourth integral value along the $x$ axis. Instead, if we do not use an invertible transformation for the same variable; for example, the affine expression $y$:
  Linear_Expression expr = y;
the resulting grid is every second point along the $x=y$ line.
Example 8
The following code shows the use of the function affine_preimage:
  Grid gr(2, EMPTY);
  gr.add_grid_generator(grid_point(0*x + 0*y));
  gr.add_grid_generator(grid_point(4*x + 0*y));
  gr.add_grid_generator(grid_point(0*x + 2*y));
  Linear_Expression expr = x + 3;
  gr.affine_preimage(x, expr);
In this example the starting grid, var and the affine expression and the denominator are the same as in Example 6, while the resulting grid is similar but translated 3 integers to the left (all the pairs $(x, y)$ where $x$ is -3 plus an integer multiple of 4 and $y$ is an integer multiple of 2).. Moreover, if the affine transformation for x is $x+y$
  Linear_Expression expr = x + y;
the resulting grid is a similar grid to the result in Example 6, only the grid is slanted along $x=-y$. Instead, if we do not use an invertible transformation for the same variable x, for example, the affine expression $y$:
  Linear_Expression expr = y;
the resulting grid is every fourth line parallel to the $x$ axis.
Example 9
For this example we also use the variables:
  Variable z(2);
  Variable w(3);
The following code shows the use of the function remove_space_dimensions:
  Grid_Generator_System gs;
  gs.insert(grid_point(3*x + y +0*z + 2*w));
  Grid gr(gs);
  Variables_Set vars;
  vars.insert(y);
  vars.insert(z);
  gr.remove_space_dimensions(vars);
The starting grid is the singleton set $\bigl\{ (3, 1, 0, 2)^\transpose \bigr\} \sseq \Rset^4$, while the resulting grid is $\bigl\{ (3, 2)^\transpose \bigr\} \sseq \Rset^2$. Be careful when removing space dimensions incrementally: since dimensions are automatically renamed after each application of the remove_space_dimensions operator, unexpected results can be obtained. For instance, by using the following code we would obtain a different result:
  set<Variable> vars1;
  vars1.insert(y);
  gr.remove_space_dimensions(vars1);
  set<Variable> vars2;
  vars2.insert(z);
  gr.remove_space_dimensions(vars2);
In this case, the result is the grid $\bigl\{(3, 0)^\transpose \bigr\} \sseq \Rset^2$: when removing the set of dimensions vars2 we are actually removing variable $w$ of the original grid. For the same reason, the operator remove_space_dimensions is not idempotent: removing twice the same non-empty set of dimensions is never the same as removing them just once.

Definition at line 359 of file Grid.defs.hh.


Member Typedef Documentation

The numeric type of coefficients.

Definition at line 362 of file Grid.defs.hh.

Definition at line 1990 of file Grid.defs.hh.


Member Enumeration Documentation

Enumerator:
PARAMETER 
LINE 
GEN_VIRTUAL 
PROPER_CONGRUENCE 
CON_VIRTUAL 
EQUALITY 

Definition at line 1981 of file Grid.defs.hh.

01981                       {
01982     PARAMETER,
01983     LINE,
01984     GEN_VIRTUAL,
01985     PROPER_CONGRUENCE = PARAMETER,
01986     CON_VIRTUAL = LINE,
01987     EQUALITY = GEN_VIRTUAL
01988   };

Enumerator:
TVB_TRUE 
TVB_FALSE 
TVB_DONT_KNOW 

Definition at line 2138 of file Grid.defs.hh.

02138                             {
02139     TVB_TRUE,
02140     TVB_FALSE,
02141     TVB_DONT_KNOW
02142   };


Constructor & Destructor Documentation

Parma_Polyhedra_Library::Grid::Grid ( dimension_type  num_dimensions = 0,
Degenerate_Element  kind = UNIVERSE 
) [inline, explicit]

Builds a grid having the specified properties.

Parameters:
num_dimensions The number of dimensions of the vector space enclosing the grid;
kind Specifies whether the universe or the empty grid has to be built.
Exceptions:
std::length_error Thrown if num_dimensions exceeds the maximum allowed space dimension.

Definition at line 122 of file Grid.inlines.hh.

References construct(), and OK().

00124   : con_sys(),
00125     gen_sys(num_dimensions > max_space_dimension()
00126             ? (throw_space_dimension_overflow("Grid(n, k)",
00127                                               "n exceeds the maximum "
00128                                               "allowed space dimension"),
00129                0)
00130             : num_dimensions) {
00131   construct(num_dimensions, kind);
00132   PPL_ASSERT(OK());
00133 }

Parma_Polyhedra_Library::Grid::Grid ( const Congruence_System cgs  )  [inline, explicit]

Builds a grid, copying a system of congruences.

The grid inherits the space dimension of the congruence system.

Parameters:
cgs The system of congruences defining the grid.
Exceptions:
std::length_error Thrown if num_dimensions exceeds the maximum allowed space dimension.

Definition at line 136 of file Grid.inlines.hh.

References construct().

00137   : con_sys(cgs.space_dimension() > max_space_dimension()
00138             ? throw_space_dimension_overflow("Grid(cgs)",
00139                                              "the space dimension of cgs "
00140                                              "exceeds the maximum allowed "
00141                                              "space dimension"), 0
00142             : cgs.space_dimension()),
00143     gen_sys(cgs.space_dimension()) {
00144   Congruence_System cgs_copy(cgs);
00145   construct(cgs_copy);
00146 }

Parma_Polyhedra_Library::Grid::Grid ( Congruence_System cgs,
Recycle_Input  dummy 
) [inline]

Builds a grid, recycling a system of congruences.

The grid inherits the space dimension of the congruence system.

Parameters:
cgs The system of congruences defining the grid. Its data-structures may be recycled to build the grid.
dummy A dummy tag to syntactically differentiate this one from the other constructors.
Exceptions:
std::length_error Thrown if num_dimensions exceeds the maximum allowed space dimension.

Definition at line 149 of file Grid.inlines.hh.

References construct().

00150   : con_sys(cgs.space_dimension() > max_space_dimension()
00151             ? throw_space_dimension_overflow("Grid(cgs, recycle)",
00152                                              "the space dimension of cgs "
00153                                              "exceeds the maximum allowed "
00154                                              "space dimension"), 0
00155             : cgs.space_dimension()),
00156     gen_sys(cgs.space_dimension()) {
00157   construct(cgs);
00158 }

Parma_Polyhedra_Library::Grid::Grid ( const Constraint_System cs  )  [explicit]

Builds a grid, copying a system of constraints.

The grid inherits the space dimension of the constraint system.

Parameters:
cs The system of constraints defining the grid.
Exceptions:
std::invalid_argument Thrown if the constraint system cs contains inequality constraints.
std::length_error Thrown if num_dimensions exceeds the maximum allowed space dimension.

Definition at line 60 of file Grid_public.cc.

References Parma_Polyhedra_Library::Constraint_System::begin(), con_sys, construct(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Congruence_System::insert(), OK(), Parma_Polyhedra_Library::Grid::Status::set_empty(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), status, throw_invalid_constraints(), and Parma_Polyhedra_Library::Congruence::zero_dim_false().

00061   : con_sys(cs.space_dimension() > max_space_dimension()
00062             ? throw_space_dimension_overflow("Grid(cs)",
00063                                              "the space dimension of cs "
00064                                              "exceeds the maximum allowed "
00065                                              "space dimension"), 0
00066             : cs.space_dimension()),
00067     gen_sys(cs.space_dimension()) {
00068   space_dim = cs.space_dimension();
00069 
00070   if (space_dim == 0) {
00071     // See if an inconsistent constraint has been passed.
00072     for (Constraint_System::const_iterator i = cs.begin(),
00073          cs_end = cs.end(); i != cs_end; ++i)
00074       if (i->is_inconsistent()) {
00075         // Inconsistent constraint found: the grid is empty.
00076         status.set_empty();
00077         // Insert the zero dim false congruence system into `con_sys'.
00078         // `gen_sys' is already in empty form.
00079         con_sys.insert(Congruence::zero_dim_false());
00080         PPL_ASSERT(OK());
00081         return;
00082       }
00083     set_zero_dim_univ();
00084     PPL_ASSERT(OK());
00085     return;
00086   }
00087 
00088   Congruence_System cgs;
00089   cgs.insert(0*Variable(space_dim - 1) %= 1);
00090   for (Constraint_System::const_iterator i = cs.begin(),
00091          cs_end = cs.end(); i != cs_end; ++i)
00092     if (i->is_equality())
00093       cgs.insert(*i);
00094     else
00095       throw_invalid_constraints("Grid(cs)", "cs");
00096   construct(cgs);
00097 }

Parma_Polyhedra_Library::Grid::Grid ( Constraint_System cs,
Recycle_Input  dummy 
)

Builds a grid, recycling a system of constraints.

The grid inherits the space dimension of the constraint system.

Parameters:
cs The system of constraints defining the grid. Its data-structures may be recycled to build the grid.
dummy A dummy tag to syntactically differentiate this one from the other constructors.
Exceptions:
std::invalid_argument Thrown if the constraint system cs contains inequality constraints.
std::length_error Thrown if num_dimensions exceeds the maximum allowed space dimension.

Definition at line 99 of file Grid_public.cc.

References Parma_Polyhedra_Library::Constraint_System::begin(), con_sys, construct(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Congruence_System::insert(), OK(), Parma_Polyhedra_Library::Grid::Status::set_empty(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), status, throw_invalid_constraint(), and Parma_Polyhedra_Library::Congruence::zero_dim_false().

00100  : con_sys(cs.space_dimension() > max_space_dimension()
00101            ? throw_space_dimension_overflow("Grid(cs, recycle)",
00102                                             "the space dimension of cs "
00103                                             "exceeds the maximum allowed "
00104                                             "space dimension"), 0
00105            : cs.space_dimension()),
00106    gen_sys(cs.space_dimension()) {
00107   space_dim = cs.space_dimension();
00108 
00109   if (space_dim == 0) {
00110     // See if an inconsistent constraint has been passed.
00111     for (Constraint_System::const_iterator i = cs.begin(),
00112          cs_end = cs.end(); i != cs_end; ++i)
00113       if (i->is_inconsistent()) {
00114         // Inconsistent constraint found: the grid is empty.
00115         status.set_empty();
00116         // Insert the zero dim false congruence system into `con_sys'.
00117         // `gen_sys' is already in empty form.
00118         con_sys.insert(Congruence::zero_dim_false());
00119         PPL_ASSERT(OK());
00120         return;
00121       }
00122     set_zero_dim_univ();
00123     PPL_ASSERT(OK());
00124     return;
00125   }
00126 
00127   Congruence_System cgs;
00128   cgs.insert(0*Variable(space_dim - 1) %= 1);
00129   for (Constraint_System::const_iterator i = cs.begin(),
00130          cs_end = cs.end(); i != cs_end; ++i)
00131     if (i->is_equality())
00132       cgs.insert(*i);
00133     else
00134       throw_invalid_constraint("Grid(cs)", "cs");
00135   construct(cgs);
00136 }

Parma_Polyhedra_Library::Grid::Grid ( const Grid_Generator_System const_gs  )  [inline, explicit]

Builds a grid, copying a system of grid generators.

The grid inherits the space dimension of the generator system.

Parameters:
const_gs The system of generators defining the grid.
Exceptions:
std::invalid_argument Thrown if the system of generators is not empty but has no points.
std::length_error Thrown if num_dimensions exceeds the maximum allowed space dimension.

Definition at line 161 of file Grid.inlines.hh.

References construct().

00162   : con_sys(ggs.space_dimension() > max_space_dimension()
00163             ? throw_space_dimension_overflow("Grid(ggs)",
00164                                              "the space dimension of ggs "
00165                                              "exceeds the maximum allowed "
00166                                              "space dimension"), 0
00167             : ggs.space_dimension()),
00168     gen_sys(ggs.space_dimension()) {
00169   Grid_Generator_System ggs_copy(ggs);
00170   construct(ggs_copy);
00171 }

Parma_Polyhedra_Library::Grid::Grid ( Grid_Generator_System gs,
Recycle_Input  dummy 
) [inline]

Builds a grid, recycling a system of grid generators.

The grid inherits the space dimension of the generator system.

Parameters:
gs The system of generators defining the grid. Its data-structures may be recycled to build the grid.
dummy A dummy tag to syntactically differentiate this one from the other constructors.
Exceptions:
std::invalid_argument Thrown if the system of generators is not empty but has no points.
std::length_error Thrown if num_dimensions exceeds the maximum allowed space dimension.

Definition at line 174 of file Grid.inlines.hh.

References construct().

00175   : con_sys(ggs.space_dimension() > max_space_dimension()
00176             ? throw_space_dimension_overflow("Grid(ggs, recycle)",
00177                                              "the space dimension of ggs "
00178                                              "exceeds the maximum allowed "
00179                                              "space dimension"), 0
00180             : ggs.space_dimension()),
00181     gen_sys(ggs.space_dimension()) {
00182   construct(ggs);
00183 }

template<typename Interval >
Parma_Polyhedra_Library::Grid::Grid ( const Box< Interval > &  box,
Complexity_Class  complexity = ANY_COMPLEXITY 
) [inline, explicit]

Builds a grid out of a box.

The grid inherits the space dimension of the box. The built grid is the most precise grid that includes the box.

Parameters:
box The box representing the grid to be built.
complexity This argument is ignored as the algorithm used has polynomial complexity.
Exceptions:
std::length_error Thrown if the space dimension of box exceeds the maximum allowed space dimension.

Definition at line 36 of file Grid.templates.hh.

References con_sys, Parma_Polyhedra_Library::Grid_Generator::divisor(), Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::gcd_assign(), gen_sys, Parma_Polyhedra_Library::Box< ITV >::get_lower_bound(), Parma_Polyhedra_Library::Box< ITV >::get_upper_bound(), Parma_Polyhedra_Library::Congruence_System::increase_space_dimension(), Parma_Polyhedra_Library::Congruence_System::insert(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), max_space_dimension(), Parma_Polyhedra_Library::neg_assign(), OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Grid_Generator::scale_to_divisor(), set_congruences_up_to_date(), set_empty(), set_generators_up_to_date(), Parma_Polyhedra_Library::Grid_Generator_System::set_sorted(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), throw_space_dimension_overflow(), and Parma_Polyhedra_Library::Grid_Generator_System::unset_pending_rows().

00038   : con_sys(),
00039     gen_sys() {
00040   if (box.space_dimension() > max_space_dimension())
00041     throw_space_dimension_overflow("Grid(box, from_bounding_box)",
00042                                    "the space dimension of box "
00043                                    "exceeds the maximum allowed "
00044                                    "space dimension");
00045 
00046   space_dim = box.space_dimension();
00047 
00048   if (box.is_empty()) {
00049     // Empty grid.
00050     set_empty();
00051     PPL_ASSERT(OK());
00052     return;
00053   }
00054 
00055   if (space_dim == 0)
00056     set_zero_dim_univ();
00057   else {
00058     // Initialize the space dimension as indicated by the box.
00059     con_sys.increase_space_dimension(space_dim);
00060     // Add congruences and generators according to `box'.
00061     PPL_DIRTY_TEMP_COEFFICIENT(l_n);
00062     PPL_DIRTY_TEMP_COEFFICIENT(l_d);
00063     PPL_DIRTY_TEMP_COEFFICIENT(u_n);
00064     PPL_DIRTY_TEMP_COEFFICIENT(u_d);
00065     gen_sys.insert(grid_point(0*Variable(space_dim-1)));
00066     for (dimension_type k = space_dim; k-- > 0; ) {
00067       // This is declared here because it may be invalidated by the call to
00068       // gen_sys.insert() at the end of the loop.
00069       Grid_Generator& point = gen_sys[0];
00070       bool closed = false;
00071       // TODO: Consider producing the system(s) in minimized form.
00072       if (box.get_lower_bound(k, closed, l_n, l_d)) {
00073         if (box.get_upper_bound(k, closed, u_n, u_d))
00074           if (l_n * u_d == u_n * l_d) {
00075             // A point interval sets dimension k of every point to a
00076             // single value.
00077             con_sys.insert(l_d * Variable(k) == l_n);
00078 
00079             // Scale the point to use as divisor the lcm of the
00080             // divisors of the existing point and the lower bound.
00081             const Coefficient& point_divisor = point.divisor();
00082             gcd_assign(u_n, l_d, point_divisor);
00083             // `u_n' now holds the gcd.
00084             exact_div_assign(u_n, point_divisor, u_n);
00085             if (l_d < 0)
00086               neg_assign(u_n);
00087             // l_d * u_n == abs(l_d * (point_divisor / gcd(l_d, point_divisor)))
00088             point.scale_to_divisor(l_d * u_n);
00089             // Set dimension k of the point to the lower bound.
00090             if (l_d < 0)
00091               neg_assign(u_n);
00092             // point[k + 1] = l_n * point_divisor / gcd(l_d, point_divisor)
00093             point[k + 1] = l_n * u_n;
00094 
00095             continue;
00096           }
00097       }
00098       // A universe interval allows any value in dimension k.
00099       gen_sys.insert(grid_line(Variable(k)));
00100     }
00101     set_congruences_up_to_date();
00102     set_generators_up_to_date();
00103     gen_sys.unset_pending_rows();
00104     gen_sys.set_sorted(false);
00105   }
00106 
00107   PPL_ASSERT(OK());
00108 }

template<typename U >
Parma_Polyhedra_Library::Grid::Grid ( const BD_Shape< U > &  bd,
Complexity_Class  complexity = ANY_COMPLEXITY 
) [inline, explicit]

Builds a grid out of a bounded-difference shape.

The grid inherits the space dimension of the BDS. The built grid is the most precise grid that includes the BDS.

Parameters:
bd The BDS representing the grid to be built.
complexity This argument is ignored as the algorithm used has polynomial complexity.
Exceptions:
std::length_error Thrown if the space dimension of bd exceeds the maximum allowed space dimension.

Definition at line 187 of file Grid.inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::congruences(), and construct().

00189   : con_sys(bd.space_dimension() > max_space_dimension()
00190             ? throw_space_dimension_overflow("Grid(bd)",
00191                                              "the space dimension of bd "
00192                                              "exceeds the maximum allowed "
00193                                              "space dimension"), 0
00194             : bd.space_dimension()),
00195     gen_sys(bd.space_dimension()) {
00196   Congruence_System cgs = bd.congruences();
00197   construct(cgs);
00198 }

template<typename U >
Parma_Polyhedra_Library::Grid::Grid ( const Octagonal_Shape< U > &  os,
Complexity_Class  complexity = ANY_COMPLEXITY 
) [inline, explicit]

Builds a grid out of an octagonal shape.

The grid inherits the space dimension of the octagonal shape. The built grid is the most precise grid that includes the octagonal shape.

Parameters:
os The octagonal shape representing the grid to be built.
complexity This argument is ignored as the algorithm used has polynomial complexity.
Exceptions:
std::length_error Thrown if the space dimension of os exceeds the maximum allowed space dimension.

Definition at line 202 of file Grid.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::congruences(), and construct().

00204   : con_sys(os.space_dimension() > max_space_dimension()
00205             ? throw_space_dimension_overflow("Grid(os)",
00206                                              "the space dimension of os "
00207                                              "exceeds the maximum allowed "
00208                                              "space dimension"), 0
00209             : os.space_dimension()),
00210     gen_sys(os.space_dimension()) {
00211   Congruence_System cgs = os.congruences();
00212   construct(cgs);
00213 }

Parma_Polyhedra_Library::Grid::Grid ( const Polyhedron ph,
Complexity_Class  complexity = ANY_COMPLEXITY 
) [explicit]

Builds a grid from a polyhedron using algorithms whose complexity does not exceed the one specified by complexity. If complexity is ANY_COMPLEXITY, then the grid built is the smallest one containing ph.

The grid inherits the space dimension of polyhedron.

Parameters:
ph The polyhedron.
complexity The complexity class.
Exceptions:
std::length_error Thrown if num_dimensions exceeds the maximum allowed space dimension.

Definition at line 138 of file Grid_public.cc.

References Parma_Polyhedra_Library::Linear_Expression::all_homogeneous_terms_are_zero(), Parma_Polyhedra_Library::ANY_COMPLEXITY, Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Polyhedron::constraints(), Parma_Polyhedra_Library::Polyhedron::constraints_are_minimized(), Parma_Polyhedra_Library::Polyhedron::constraints_are_up_to_date(), construct(), Parma_Polyhedra_Library::Polyhedron::generators(), Parma_Polyhedra_Library::Polyhedron::generators_are_up_to_date(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), Parma_Polyhedra_Library::Congruence_System::insert(), Parma_Polyhedra_Library::Polyhedron::is_empty(), Parma_Polyhedra_Library::Polyhedron::marked_empty(), Parma_Polyhedra_Library::Polyhedron::minimize(), OK(), PPL_DIRTY_TEMP_COEFFICIENT, set_empty(), set_zero_dim_univ(), space_dim, and Parma_Polyhedra_Library::Polyhedron::space_dimension().

00140   : con_sys(ph.space_dimension() > max_space_dimension()
00141             ? throw_space_dimension_overflow("Grid(ph)",
00142                                              "the space dimension of ph "
00143                                              "exceeds the maximum allowed "
00144                                              "space dimension"), 0
00145             : ph.space_dimension()),
00146     gen_sys(ph.space_dimension()) {
00147   space_dim = ph.space_dimension();
00148 
00149   // A zero-dim polyhedron causes no complexity problems.
00150   if (space_dim == 0) {
00151     if (ph.is_empty())
00152       set_empty();
00153     else
00154       set_zero_dim_univ();
00155     return;
00156   }
00157 
00158   // A polyhedron known to be empty causes no complexity problems.
00159   if (ph.marked_empty()) {
00160     set_empty();
00161     return;
00162   }
00163 
00164   bool use_constraints = ph.constraints_are_minimized()
00165     || !ph.generators_are_up_to_date();
00166 
00167   // Minimize the constraint description if it is needed and
00168   // the complexity allows it.
00169   if (use_constraints && complexity == ANY_COMPLEXITY)
00170     if (!ph.minimize()) {
00171       set_empty();
00172       return;
00173     }
00174 
00175   if (use_constraints) {
00176     // Only the equality constraints need be used.
00177     PPL_ASSERT(ph.constraints_are_up_to_date());
00178     const Constraint_System& cs = ph.constraints();
00179     Congruence_System cgs;
00180     cgs.insert(0*Variable(space_dim - 1) %= 1);
00181     for (Constraint_System::const_iterator i = cs.begin(),
00182            cs_end = cs.end(); i != cs_end; ++i)
00183       if (i->is_equality())
00184         cgs.insert(*i);
00185     construct(cgs);
00186   }
00187   else {
00188     // First find a point or closure point and convert it to a
00189     // grid point and add to the (initially empty) set of grid generators.
00190     PPL_ASSERT(ph.generators_are_up_to_date());
00191     const Generator_System& gs = ph.generators();
00192     Grid_Generator_System ggs(space_dim);
00193     Linear_Expression point_expr;
00194     PPL_DIRTY_TEMP_COEFFICIENT(point_divisor);
00195     for (Generator_System::const_iterator g = gs.begin(),
00196            gs_end = gs.end(); g != gs_end; ++g) {
00197       if (g->is_point() || g->is_closure_point()) {
00198         for (dimension_type i = space_dim; i-- > 0; ) {
00199           const Variable v(i);
00200           point_expr += g->coefficient(v) * v;
00201           point_divisor = g->divisor();
00202         }
00203         ggs.insert(grid_point(point_expr, point_divisor));
00204         break;
00205       }
00206     }
00207     // Add grid lines for all the other generators.
00208     // If the polyhedron's generator is a (closure) point, the grid line must
00209     // have the direction given by a line that joins the grid point already
00210     // inserted and the new point.
00211     PPL_DIRTY_TEMP_COEFFICIENT(coeff);
00212     PPL_DIRTY_TEMP_COEFFICIENT(g_divisor);
00213     for (Generator_System::const_iterator g = gs.begin(),
00214            gs_end = gs.end(); g != gs_end; ++g) {
00215       Linear_Expression e;
00216       if (g->is_point() || g->is_closure_point()) {
00217         g_divisor = g->divisor();
00218         for (dimension_type i = space_dim; i-- > 0; ) {
00219           const Variable v(i);
00220           coeff = point_expr.coefficient(v) * g_divisor;
00221           coeff -= g->coefficient(v) * point_divisor;
00222           e += coeff * v;
00223         }
00224         if (e.all_homogeneous_terms_are_zero())
00225           continue;
00226       }
00227       else
00228         for (dimension_type i = space_dim; i-- > 0; ) {
00229           const Variable v(i);
00230           e += g->coefficient(v) * v;
00231         }
00232       ggs.insert(grid_line(e));
00233     }
00234     construct(ggs);
00235   }
00236   PPL_ASSERT(OK());
00237 }

Parma_Polyhedra_Library::Grid::Grid ( const Grid y,
Complexity_Class  complexity = ANY_COMPLEXITY 
)

Ordinary copy constructor.

The complexity argument is ignored.

Definition at line 38 of file Grid_public.cc.

References con_sys, congruences_are_up_to_date(), gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Congruence_System::increase_space_dimension(), and space_dim.

00039   : con_sys(),
00040     gen_sys(),
00041     status(y.status),
00042     space_dim(y.space_dim),
00043     dim_kinds(y.dim_kinds) {
00044   if (space_dim == 0) {
00045     con_sys = y.con_sys;
00046     gen_sys = y.gen_sys;
00047   }
00048   else {
00049     if (y.congruences_are_up_to_date())
00050       con_sys = y.con_sys;
00051     else
00052       con_sys.increase_space_dimension(space_dim);
00053     if (y.generators_are_up_to_date())
00054       gen_sys = y.gen_sys;
00055     else
00056       gen_sys = Grid_Generator_System(y.space_dim);
00057   }
00058 }

Parma_Polyhedra_Library::Grid::~Grid (  )  [inline]

Destructor.

Definition at line 216 of file Grid.inlines.hh.

00216             {
00217 }


Member Function Documentation

void Parma_Polyhedra_Library::Grid::add_congruence ( const Congruence cg  )  [inline]

Adds a copy of congruence cg to *this.

Exceptions:
std::invalid_argument Thrown if *this and congruence cg are dimension-incompatible.

Definition at line 254 of file Grid.inlines.hh.

References add_congruence_no_check(), marked_empty(), space_dim, Parma_Polyhedra_Library::Congruence::space_dimension(), and throw_dimension_incompatible().

Referenced by Parma_Polyhedra_Library::Pointset_Powerset< PSET >::approximate_partition_aux(), drop_some_non_integer_points(), refine_with_congruence(), simplify_using_context_assign(), and wrap_assign().

00254                                          {
00255   // Dimension-compatibility check.
00256   if (space_dim < cg.space_dimension())
00257     throw_dimension_incompatible("add_congruence(cg)", "cg", cg);
00258 
00259   if (!marked_empty())
00260     add_congruence_no_check(cg);
00261 }

void Parma_Polyhedra_Library::Grid::add_congruence_no_check ( const Congruence cg  )  [private]

Adds the congruence cg to *this.

Warning:
If cg and *this are dimension-incompatible, the grid generator system is not minimized or *this is empty, then the behavior is undefined.

Definition at line 647 of file Grid_nonpublic.cc.

References clear_congruences_minimized(), clear_generators_up_to_date(), con_sys, congruences_are_up_to_date(), Parma_Polyhedra_Library::Congruence_System::insert(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), marked_empty(), OK(), set_congruences_up_to_date(), set_empty(), space_dim, Parma_Polyhedra_Library::Congruence::space_dimension(), and update_congruences().

Referenced by add_congruence(), add_constraint_no_check(), difference_assign(), generalized_affine_image(), generalized_affine_preimage(), and refine_no_check().

00647                                                      {
00648   PPL_ASSERT(!marked_empty());
00649   PPL_ASSERT(space_dim >= cg.space_dimension());
00650 
00651   // Dealing with a zero-dimensional space grid first.
00652   if (space_dim == 0) {
00653     if (cg.is_inconsistent())
00654       set_empty();
00655     return;
00656   }
00657 
00658   if (!congruences_are_up_to_date())
00659     update_congruences();
00660 
00661   con_sys.insert(cg);
00662 
00663   clear_congruences_minimized();
00664   set_congruences_up_to_date();
00665   clear_generators_up_to_date();
00666 
00667   // Note: the congruence system may have become unsatisfiable, thus
00668   // we do not check for satisfiability.
00669   PPL_ASSERT(OK());
00670 }

void Parma_Polyhedra_Library::Grid::add_congruences ( const Congruence_System cgs  )  [inline]

Adds a copy of each congruence in cgs to *this.

Parameters:
cgs Contains the congruences that will be added to the system of congruences of *this.
Exceptions:
std::invalid_argument Thrown if *this and cgs are dimension-incompatible.

Definition at line 264 of file Grid.inlines.hh.

References add_recycled_congruences(), marked_empty(), space_dim, Parma_Polyhedra_Library::Congruence_System::space_dimension(), and throw_dimension_incompatible().

Referenced by refine_with_congruences(), and simplify_using_context_assign().

00264                                                   {
00265   // TODO: this is just an executable specification.
00266   // Space dimension compatibility check.
00267   if (space_dim < cgs.space_dimension())
00268     throw_dimension_incompatible("add_congruences(cgs)", "cgs", cgs);
00269 
00270   if (!marked_empty()) {
00271     Congruence_System cgs_copy = cgs;
00272     add_recycled_congruences(cgs_copy);
00273   }
00274 }

void Parma_Polyhedra_Library::Grid::add_constraint ( const Constraint c  )  [inline]

Adds to *this a congruence equivalent to constraint c.

Parameters:
c The constraint to be added.
Exceptions:
std::invalid_argument Thrown if *this and c are dimension-incompatible or if constraint c is not optimally supported by the grid domain.

Definition at line 297 of file Grid.inlines.hh.

References add_constraint_no_check(), marked_empty(), space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), and throw_dimension_incompatible().

Referenced by wrap_assign().

00297                                         {
00298   // Space dimension compatibility check.
00299   if (space_dim < c.space_dimension())
00300     throw_dimension_incompatible("add_constraint(c)", "c", c);
00301   if (!marked_empty())
00302     add_constraint_no_check(c);
00303 }

void Parma_Polyhedra_Library::Grid::add_constraint_no_check ( const Constraint c  )  [private]

Uses the constraint c to refine *this.

Parameters:
c The constraint to be added.
Exceptions:
std::invalid_argument Thrown if c is a non-trivial inequality constraint.
Warning:
If c and *this are dimension-incompatible, the behavior is undefined.

Definition at line 673 of file Grid_nonpublic.cc.

References add_congruence_no_check(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_inconsistent(), Parma_Polyhedra_Library::Constraint::is_inequality(), Parma_Polyhedra_Library::Constraint::is_tautological(), marked_empty(), set_empty(), space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), and throw_invalid_constraint().

Referenced by add_constraint(), and add_constraints().

00673                                                     {
00674   PPL_ASSERT(!marked_empty());
00675   PPL_ASSERT(space_dim >= c.space_dimension());
00676 
00677   if (c.is_inequality()) {
00678     // Only trivial inequalities can be handled.
00679     if (c.is_inconsistent()) {
00680       set_empty();
00681       return;
00682     }
00683     if (c.is_tautological())
00684       return;
00685     // Non-trivial inequality constraints are not allowed.
00686     throw_invalid_constraint("add_constraint(c)", "c");
00687   }
00688 
00689   PPL_ASSERT(c.is_equality());
00690   Congruence cg(c);
00691   add_congruence_no_check(cg);
00692 }

void Parma_Polyhedra_Library::Grid::add_constraints ( const Constraint_System cs  ) 

Adds to *this congruences equivalent to the constraints in cs.

Parameters:
cs The constraints to be added.
Exceptions:
std::invalid_argument Thrown if *this and cs are dimension-incompatible or if cs contains a constraint whcih is not optimally supported by the grid domain.

Definition at line 1130 of file Grid_public.cc.

References add_constraint_no_check(), Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint_System::end(), marked_empty(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), and throw_dimension_incompatible().

Referenced by add_recycled_constraints().

01130                                                     {
01131   // The dimension of `cs' must be at most `space_dim'.
01132   if (space_dim < cs.space_dimension())
01133     throw_dimension_incompatible("add_constraints(cs)", "cs", cs);
01134   if (marked_empty())
01135     return;
01136 
01137   for (Constraint_System::const_iterator i = cs.begin(),
01138          cs_end = cs.end(); i != cs_end; ++i) {
01139     add_constraint_no_check(*i);
01140     if (marked_empty())
01141       return;
01142   }
01143 }

void Parma_Polyhedra_Library::Grid::add_grid_generator ( const Grid_Generator g  ) 

Adds a copy of grid generator g to the system of generators of *this.

Exceptions:
std::invalid_argument Thrown if *this and generator g are dimension-incompatible, or if *this is an empty grid and g is not a point.

Definition at line 1146 of file Grid_public.cc.

References clear_congruences_up_to_date(), clear_empty(), clear_generators_minimized(), gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), Parma_Polyhedra_Library::Grid_Generator::is_line_or_parameter(), Parma_Polyhedra_Library::Grid_Generator::is_parameter(), Parma_Polyhedra_Library::Grid_Generator::is_parameter_or_point(), marked_empty(), normalize_divisors(), OK(), set_generators_up_to_date(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Grid_Generator::space_dimension(), throw_dimension_incompatible(), throw_invalid_generator(), and update_generators().

Referenced by generalized_affine_image(), generalized_affine_preimage(), and wrap_assign().

01146                                                    {
01147   // The dimension of `g' must be at most space_dim.
01148   const dimension_type g_space_dim = g.space_dimension();
01149   if (space_dim < g_space_dim)
01150     throw_dimension_incompatible("add_grid_generator(g)", "g", g);
01151 
01152   // Deal with zero-dimension case first.
01153   if (space_dim == 0) {
01154     // Points and parameters are the only zero-dimension generators
01155     // that can be created.
01156     if (marked_empty()) {
01157       if (g.is_parameter())
01158         throw_invalid_generator("add_grid_generator(g)", "g");
01159       set_zero_dim_univ();
01160     }
01161     PPL_ASSERT(OK());
01162     return;
01163   }
01164 
01165   if (marked_empty()
01166       || (!generators_are_up_to_date() && !update_generators())) {
01167     // Here the grid is empty: the specification says we can only
01168     // insert a point.
01169     if (g.is_line_or_parameter())
01170       throw_invalid_generator("add_grid_generator(g)", "g");
01171     gen_sys.insert(g);
01172     clear_empty();
01173   }
01174   else {
01175     PPL_ASSERT(generators_are_up_to_date());
01176     gen_sys.insert(g);
01177     if (g.is_parameter_or_point())
01178       normalize_divisors(gen_sys);
01179   }
01180 
01181   // With the added generator, congruences are out of date.
01182   clear_congruences_up_to_date();
01183 
01184   clear_generators_minimized();
01185   set_generators_up_to_date();
01186   PPL_ASSERT(OK());
01187 }

void Parma_Polyhedra_Library::Grid::add_grid_generators ( const Grid_Generator_System gs  ) 

Adds a copy of the generators in gs to the system of generators of *this.

Parameters:
gs Contains the generators that will be added to the system of generators of *this.
Exceptions:
std::invalid_argument Thrown if *this and gs are dimension-incompatible, or if *this is empty and the system of generators gs is not empty, but has no points.

Definition at line 1290 of file Grid_public.cc.

References add_recycled_grid_generators().

01290                                                             {
01291   // TODO: this is just an executable specification.
01292   Grid_Generator_System gs_copy = gs;
01293   add_recycled_grid_generators(gs_copy);
01294 }

void Parma_Polyhedra_Library::Grid::add_recycled_congruences ( Congruence_System cgs  ) 

Adds the congruences in cgs to *this.

Parameters:
cgs The congruence system to be added to *this. The congruences in cgs may be recycled.
Exceptions:
std::invalid_argument Thrown if *this and cgs are dimension-incompatible.
Warning:
The only assumption that can be made about cgs upon successful or exceptional return is that it can be safely destroyed.

Definition at line 1190 of file Grid_public.cc.

References Parma_Polyhedra_Library::Congruence_System::begin(), clear_congruences_minimized(), clear_generators_up_to_date(), con_sys, congruences_are_up_to_date(), Parma_Polyhedra_Library::Congruence_System::end(), Parma_Polyhedra_Library::Matrix::has_no_rows(), marked_empty(), OK(), Parma_Polyhedra_Library::Congruence_System::recycling_insert(), set_empty(), space_dim, Parma_Polyhedra_Library::Congruence_System::space_dimension(), throw_dimension_incompatible(), and update_congruences().

Referenced by add_congruences(), congruence_widening_assign(), contains_integer_point(), expand_space_dimension(), generalized_affine_image(), generalized_affine_preimage(), limited_congruence_extrapolation_assign(), limited_extrapolation_assign(), limited_generator_extrapolation_assign(), and simplify_using_context_assign().

01190                                                         {
01191   // Dimension-compatibility check.
01192   const dimension_type cgs_space_dim = cgs.space_dimension();
01193   if (space_dim < cgs_space_dim)
01194     throw_dimension_incompatible("add_recycled_congruences(cgs)", "cgs", cgs);
01195 
01196   if (cgs.has_no_rows())
01197     return;
01198 
01199   if (marked_empty())
01200     return;
01201 
01202   if (space_dim == 0) {
01203     // In a 0-dimensional space the congruences are trivial (e.g., 0
01204     // == 0 or 1 %= 0) or false (e.g., 1 == 0).  In a system of
01205     // congruences `begin()' and `end()' are equal if and only if the
01206     // system contains only trivial congruences.
01207     if (cgs.begin() != cgs.end())
01208       // There is a congruence, it must be false, the grid becomes empty.
01209       set_empty();
01210     return;
01211   }
01212 
01213   // The congruences are required.
01214   if (!congruences_are_up_to_date())
01215     update_congruences();
01216 
01217   // Swap (instead of copying) the coefficients of `cgs' (which is
01218   // writable).
01219   con_sys.recycling_insert(cgs);
01220 
01221   // Congruences may not be minimized and generators are out of date.
01222   clear_congruences_minimized();
01223   clear_generators_up_to_date();
01224   // Note: the congruence system may have become unsatisfiable, thus
01225   // we do not check for satisfiability.
01226   PPL_ASSERT(OK());
01227 }

void Parma_Polyhedra_Library::Grid::add_recycled_constraints ( Constraint_System cs  )  [inline]

Adds to *this congruences equivalent to the constraints in cs.

Parameters:
cs The constraints to be added. They may be recycled.
Exceptions:
std::invalid_argument Thrown if *this and cs are dimension-incompatible or if cs contains a constraint whcih is not optimally supported by the grid domain.
Warning:
The only assumption that can be made about cs upon successful or exceptional return is that it can be safely destroyed.

Definition at line 306 of file Grid.inlines.hh.

References add_constraints().

00306                                                     {
00307   // TODO: really recycle the constraints.
00308   add_constraints(cs);
00309 }

void Parma_Polyhedra_Library::Grid::add_recycled_grid_generators ( Grid_Generator_System gs  ) 

Adds the generators in gs to the system of generators of this.

Parameters:
gs The generator system to be added to *this. The generators in gs may be recycled.
Exceptions:
std::invalid_argument Thrown if *this and gs are dimension-incompatible.
Warning:
The only assumption that can be made about gs upon successful or exceptional return is that it can be safely destroyed.

Definition at line 1230 of file Grid_public.cc.

References clear_congruences_up_to_date(), clear_empty(), clear_generators_minimized(), gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Matrix::has_no_rows(), Parma_Polyhedra_Library::Grid_Generator_System::has_points(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), marked_empty(), normalize_divisors(), OK(), Parma_Polyhedra_Library::Grid_Generator_System::recycling_insert(), set_generators_up_to_date(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), swap(), throw_dimension_incompatible(), throw_invalid_generators(), and update_generators().

Referenced by add_grid_generators(), generalized_affine_image(), generalized_affine_preimage(), and generator_widening_assign().

01230                                                                {
01231   // Dimension-compatibility check.
01232   const dimension_type gs_space_dim = gs.space_dimension();
01233   if (space_dim < gs_space_dim)
01234     throw_dimension_incompatible("add_recycled_grid_generators(gs)", "gs", gs);
01235 
01236   // Adding no generators leaves the grid the same.
01237   if (gs.has_no_rows())
01238     return;
01239 
01240   // Adding valid generators to a zero-dimensional grid transforms it
01241   // to the zero-dimensional universe grid.
01242   if (space_dim == 0) {
01243     if (marked_empty())
01244       set_zero_dim_univ();
01245     else {
01246       PPL_ASSERT(gs.has_points());
01247     }
01248     PPL_ASSERT(OK(true));
01249     return;
01250   }
01251 
01252   if (!marked_empty()) {
01253     // The grid contains at least one point.
01254 
01255     if (!generators_are_up_to_date())
01256       update_generators();
01257     normalize_divisors(gs, gen_sys);
01258 
01259     gen_sys.recycling_insert(gs);
01260 
01261     // Congruences are out of date and generators are not minimized.
01262     clear_congruences_up_to_date();
01263     clear_generators_minimized();
01264 
01265     PPL_ASSERT(OK(true));
01266     return;
01267   }
01268 
01269   // The grid is empty.
01270 
01271   // `gs' must contain at least one point.
01272   if (!gs.has_points())
01273     throw_invalid_generators("add_recycled_grid_generators(gs)", "gs");
01274 
01275   // Adjust `gs' to the right dimension.
01276   gs.insert(parameter(0*Variable(space_dim-1)));
01277 
01278   std::swap(gen_sys, gs);
01279 
01280   normalize_divisors(gen_sys);
01281 
01282   // The grid is no longer empty and generators are up-to-date.
01283   set_generators_up_to_date();
01284   clear_empty();
01285 
01286   PPL_ASSERT(OK());
01287 }

void Parma_Polyhedra_Library::Grid::add_space_dimensions ( Grid_Generator_System gs,
Congruence_System cgs,
dimension_type  dims 
) [private]

Adds new space dimensions to the given systems.

Parameters:
gs A generator system, to which columns are added;
cgs A congruence system, to which rows and columns are added;
dims The number of space dimensions to add.

This method is invoked only by add_space_dimensions_and_project().

Definition at line 54 of file Grid_chdims.cc.

References Parma_Polyhedra_Library::Congruence_System::add_unit_rows_and_columns(), dim_kinds, EQUALITY, Parma_Polyhedra_Library::Grid_Generator_System::insert(), normalize_divisors(), Parma_Polyhedra_Library::Matrix::num_columns(), space_dim, and Parma_Polyhedra_Library::Grid_Generator_System::space_dimension().

00056                                                            {
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   // Add `dims' zero columns onto gs.
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 /* a.k.a GEN_VIRTUAL */);
00068 }

void Parma_Polyhedra_Library::Grid::add_space_dimensions ( Congruence_System cgs,
Grid_Generator_System gs,
dimension_type  dims 
) [private]

Adds new space dimensions to the given systems.

Parameters:
cgs A congruence system, to which columns are added;
gs A generator system, to which rows and columns are added;
dims The number of space dimensions to add.

This method is invoked only by add_space_dimensions_and_embed().

Definition at line 35 of file Grid_chdims.cc.

References Parma_Polyhedra_Library::Grid_Generator_System::add_universe_rows_and_columns(), Parma_Polyhedra_Library::Matrix::add_zero_columns(), CON_VIRTUAL, congruences_are_minimized(), dim_kinds, generators_are_minimized(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), and Parma_Polyhedra_Library::Matrix::swap_columns().

Referenced by add_space_dimensions_and_embed(), and add_space_dimensions_and_project().

00037                                                            {
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   // Move the moduli.
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 /* a.k.a. LINE */);
00048 
00049   gs.add_universe_rows_and_columns(dims);
00050 }

void Parma_Polyhedra_Library::Grid::add_space_dimensions_and_embed ( dimension_type  m  ) 

Adds m new space dimensions and embeds the old grid in the new vector space.

Parameters:
m The number of dimensions to add.
Exceptions:
std::length_error Thrown if adding m new space dimensions would cause the vector space to exceed dimension max_space_dimension().

The new space dimensions will be those having the highest indexes in the new grid, which is characterized by a system of congruences in which the variables which are the new dimensions can have any value. For instance, when starting from the grid $\cL \sseq \Rset^2$ and adding a third space dimension, the result will be the grid

\[ \bigl\{\, (x, y, z)^\transpose \in \Rset^3 \bigm| (x, y)^\transpose \in \cL \,\bigr\}. \]

Definition at line 79 of file Grid_chdims.cc.

References add_space_dimensions(), Parma_Polyhedra_Library::Grid_Generator_System::add_universe_rows_and_columns(), Parma_Polyhedra_Library::Matrix::add_zero_columns(), con_sys, CON_VIRTUAL, congruences_are_minimized(), congruences_are_up_to_date(), dim_kinds, gen_sys, generators_are_minimized(), generators_are_up_to_date(), LINE, marked_empty(), max_space_dimension(), Parma_Polyhedra_Library::Matrix::num_columns(), OK(), set_empty(), space_dim, Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), space_dimension(), status, swap(), Parma_Polyhedra_Library::Matrix::swap_columns(), Parma_Polyhedra_Library::Grid::Status::test_zero_dim_univ(), throw_space_dimension_overflow(), and Parma_Polyhedra_Library::UNIVERSE.

Referenced by expand_space_dimension(), generalized_affine_image(), generalized_affine_preimage(), and simplify_using_context_assign().

00079                                                         {
00080   if (m == 0)
00081     return;
00082 
00083   // The space dimension of the resulting grid must be at most the
00084   // maximum allowed space dimension.
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   // Adding dimensions to an empty grid is obtained by adjusting
00091   // `space_dim' and clearing `con_sys' (since it can contain the
00092   // integrality congruence of the current dimension).
00093   if (marked_empty()) {
00094     space_dim += m;
00095     set_empty();
00096     return;
00097   }
00098 
00099   // The case of a zero-dimension space grid.
00100   if (space_dim == 0) {
00101     // Since it is not empty, it has to be the universe grid.
00102     PPL_ASSERT(status.test_zero_dim_univ());
00103     // Swap *this with a newly created `m'-dimensional universe grid.
00104     Grid gr(m, UNIVERSE);
00105     swap(gr);
00106     return;
00107   }
00108 
00109   // To embed an n-dimension space grid in a (n+m)-dimension space, we
00110   // add `m' zero-columns to the rows in the system of congruences; in
00111   // contrast, the system of generators needs additional rows,
00112   // corresponding to the vectors of the canonical basis for the added
00113   // dimensions. That is, for each new dimension we add the line
00114   // having that direction. This is done by invoking the function
00115   // add_space_dimensions().
00116   if (congruences_are_up_to_date())
00117     if (generators_are_up_to_date())
00118       // Adds rows and/or columns to both matrices.
00119       add_space_dimensions(con_sys, gen_sys, m);
00120     else {
00121       // Only congruences are up-to-date, so modify only them.
00122       con_sys.add_zero_columns(m);
00123       dimension_type size = con_sys.num_columns() - 1;
00124       // Move the moduli.
00125       con_sys.swap_columns(size - m, size);
00126       if (congruences_are_minimized())
00127         dim_kinds.resize(size, CON_VIRTUAL);
00128     }
00129   else {
00130     // Only generators are up-to-date, so modify only them.
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   // Update the space dimension.
00137   space_dim += m;
00138 
00139   // Note: we do not check for satisfiability, because the system of
00140   // congruences may be unsatisfiable.
00141   PPL_ASSERT(OK());
00142 }

void Parma_Polyhedra_Library::Grid::add_space_dimensions_and_project ( dimension_type  m  ) 

Adds m new space dimensions to the grid and does not embed it in the new vector space.

Parameters:
m The number of space dimensions to add.
Exceptions:
std::length_error Thrown if adding m new space dimensions would cause the vector space to exceed dimension max_space_dimension().

The new space dimensions will be those having the highest indexes in the new grid, which is characterized by a system of congruences in which the variables running through the new dimensions are all constrained to be equal to 0. For instance, when starting from the grid $\cL \sseq \Rset^2$ and adding a third space dimension, the result will be the grid

\[ \bigl\{\, (x, y, 0)^\transpose \in \Rset^3 \bigm| (x, y)^\transpose \in \cL \,\bigr\}. \]

Definition at line 153 of file Grid_chdims.cc.

References add_space_dimensions(), Parma_Polyhedra_Library::Congruence_System::add_unit_rows_and_columns(), con_sys, congruences_are_minimized(), congruences_are_up_to_date(), dim_kinds, EQUALITY, gen_sys, generators_are_minimized(), generators_are_up_to_date(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), marked_empty(), max_space_dimension(), normalize_divisors(), Parma_Polyhedra_Library::Matrix::num_columns(), OK(), set_empty(), space_dim, Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), space_dimension(), status, swap(), Parma_Polyhedra_Library::Grid::Status::test_zero_dim_univ(), throw_space_dimension_overflow(), and Parma_Polyhedra_Library::UNIVERSE.

00153                                                           {
00154   if (m == 0)
00155     return;
00156 
00157   // The space dimension of the resulting grid should be at most the
00158   // maximum allowed space dimension.
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   // Adding dimensions to an empty grid is obtained by merely
00165   // adjusting `space_dim'.
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     // Swap *this with a newly created `n'-dimensional universe grid.
00175     Grid gr(m, UNIVERSE);
00176     swap(gr);
00177     return;
00178   }
00179 
00180   // To project an n-dimension space grid in a (n+m)-dimension space,
00181   // we just add to the system of generators `m' zero-columns; in
00182   // contrast, in the system of congruences, new rows are needed in
00183   // order to avoid embedding the old grid in the new space.  Thus,
00184   // for each new dimensions `x[k]', we add the constraint x[k] = 0;
00185   // this is done by invoking the function add_space_dimensions()
00186   // giving the system of constraints as the second argument.
00187   if (congruences_are_up_to_date())
00188     if (generators_are_up_to_date())
00189       // Add rows and/or columns to both matrices.
00190       add_space_dimensions(gen_sys, con_sys, m);
00191     else {
00192       // Only congruences are up-to-date so modify only them.
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     // Only generators are up-to-date so modify only them.
00199     PPL_ASSERT(generators_are_up_to_date());
00200 
00201     // Add m zero columns onto gs.
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   // Now update the space dimension.
00210   space_dim += m;
00211 
00212   // Note: we do not check for satisfiability, because the system of
00213   // congruences may be unsatisfiable.
00214   PPL_ASSERT(OK());
00215 }

PPL::dimension_type Parma_Polyhedra_Library::Grid::affine_dimension (  )  const

Returns $0$, if *this is empty; otherwise, returns the affine dimension of *this.

Definition at line 258 of file Grid_public.cc.

References con_sys, congruences_are_minimized(), congruences_are_up_to_date(), gen_sys, generators_are_minimized(), generators_are_up_to_date(), is_empty(), minimized_congruences(), minimized_grid_generators(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), and space_dim.

00258                                 {
00259   if (space_dim == 0 || is_empty())
00260     return 0;
00261 
00262   if (generators_are_up_to_date()) {
00263     if (generators_are_minimized())
00264       return gen_sys.num_rows() - 1;
00265     if (!(congruences_are_up_to_date() && congruences_are_minimized()))
00266       return minimized_grid_generators().num_rows() - 1;
00267   }
00268   else
00269     minimized_congruences();
00270   PPL_ASSERT(congruences_are_minimized());
00271   dimension_type d = space_dim;
00272   for (dimension_type i = con_sys.num_rows(); i-- > 0; )
00273     if (con_sys[i].is_equality())
00274       --d;
00275   return d;
00276 }

void Parma_Polyhedra_Library::Grid::affine_image ( Variable  var,
const Linear_Expression expr,
Coefficient_traits::const_reference  denominator = Coefficient_one() 
)

Assigns to *this the affine image of this under the function mapping variable var to the affine expression specified by expr and denominator.

Parameters:
var The variable to which the affine expression is assigned;
expr The numerator of the affine expression;
denominator The denominator of the affine expression (optional argument with default value 1).
Exceptions:
std::invalid_argument Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of *this.

When considering the generators of a grid, the affine transformation

\[ \frac{\sum_{i=0}^{n-1} a_i x_i + b}{\mathrm{denominator}} \]

is assigned to var where expr is $\sum_{i=0}^{n-1} a_i x_i + b$ ($b$ is the inhomogeneous term).

If congruences are up-to-date, it uses the specialized function affine_preimage() (for the system of congruences) and inverse transformation to reach the same result. To obtain the inverse transformation we use the following observation.

Observation:

  1. The affine transformation is invertible if the coefficient of var in this transformation (i.e., $a_\mathrm{var}$) is different from zero.
  2. If the transformation is invertible, then we can write

    \[ \mathrm{denominator} * {x'}_\mathrm{var} = \sum_{i = 0}^{n - 1} a_i x_i + b = a_\mathrm{var} x_\mathrm{var} + \sum_{i \neq var} a_i x_i + b, \]

    so that the inverse transformation is

    \[ a_\mathrm{var} x_\mathrm{var} = \mathrm{denominator} * {x'}_\mathrm{var} - \sum_{i \neq j} a_i x_i - b. \]

Then, if the transformation is invertible, all the entities that were up-to-date remain up-to-date. Otherwise only generators remain up-to-date.

Definition at line 1757 of file Grid_public.cc.

References Parma_Polyhedra_Library::Grid_Generator_System::affine_image(), Parma_Polyhedra_Library::Congruence_System::affine_preimage(), clear_congruences_minimized(), clear_congruences_up_to_date(), clear_generators_minimized(), con_sys, congruences_are_up_to_date(), gen_sys, generators_are_up_to_date(), marked_empty(), minimize(), Parma_Polyhedra_Library::neg_assign(), normalize_divisors(), OK(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().

Referenced by fold_space_dimensions(), and generalized_affine_image().

01759                                                                        {
01760   // The denominator cannot be zero.
01761   if (denominator == 0)
01762     throw_invalid_argument("affine_image(v, e, d)", "d == 0");
01763 
01764   // Dimension-compatibility checks.
01765   // The dimension of `expr' must be at most the dimension of `*this'.
01766   const dimension_type expr_space_dim = expr.space_dimension();
01767   if (space_dim < expr_space_dim)
01768     throw_dimension_incompatible("affine_image(v, e, d)", "e", expr);
01769   // `var' must be one of the dimensions of the grid.
01770   const dimension_type var_space_dim = var.space_dimension();
01771   if (space_dim < var_space_dim)
01772     throw_dimension_incompatible("affine_image(v, e, d)", "v", var);
01773 
01774   if (marked_empty())
01775     return;
01776 
01777   if (var_space_dim <= expr_space_dim && expr[var_space_dim] != 0) {
01778     // The transformation is invertible.
01779     if (generators_are_up_to_date()) {
01780       // Grid_Generator_System::affine_image() requires the third argument
01781       // to be a positive Coefficient.
01782       if (denominator > 0)
01783         gen_sys.affine_image(var_space_dim, expr, denominator);
01784       else
01785         gen_sys.affine_image(var_space_dim, -expr, -denominator);
01786       clear_generators_minimized();
01787       // Strong normalization in gs::affine_image may have modified
01788       // divisors.
01789       normalize_divisors(gen_sys);
01790     }
01791     if (congruences_are_up_to_date()) {
01792       // To build the inverse transformation,
01793       // after copying and negating `expr',
01794       // we exchange the roles of `expr[var_space_dim]' and `denominator'.
01795       Linear_Expression inverse;
01796       if (expr[var_space_dim] > 0) {
01797         inverse = -expr;
01798         inverse[var_space_dim] = denominator;
01799         con_sys.affine_preimage(var_space_dim, inverse, expr[var_space_dim]);
01800       }
01801       else {
01802         // The new denominator is negative: we negate everything once
01803         // more, as Congruence_System::affine_preimage() requires the
01804         // third argument to be positive.
01805         inverse = expr;
01806         inverse[var_space_dim] = denominator;
01807         neg_assign(inverse[var_space_dim]);
01808         con_sys.affine_preimage(var_space_dim, inverse, -expr[var_space_dim]);
01809       }
01810       clear_congruences_minimized();
01811     }
01812   }
01813   else {
01814     // The transformation is not invertible.
01815     // We need an up-to-date system of generators.
01816     if (!generators_are_up_to_date())
01817       minimize();
01818     if (!marked_empty()) {
01819       // Grid_Generator_System::affine_image() requires the third argument
01820       // to be a positive Coefficient.
01821       if (denominator > 0)
01822         gen_sys.affine_image(var_space_dim, expr, denominator);
01823       else
01824         gen_sys.affine_image(var_space_dim, -expr, -denominator);
01825 
01826       clear_congruences_up_to_date();
01827       clear_generators_minimized();
01828       // Strong normalization in gs::affine_image may have modified
01829       // divisors.
01830       normalize_divisors(gen_sys);
01831     }
01832   }
01833   PPL_ASSERT(OK());
01834 }

void Parma_Polyhedra_Library::Grid::affine_preimage ( Variable  var,
const Linear_Expression expr,
Coefficient_traits::const_reference  denominator = Coefficient_one() 
)

Assigns to *this the affine preimage of *this under the function mapping variable var to the affine expression specified by expr and denominator.

Parameters:
var The variable to which the affine expression is substituted;
expr The numerator of the affine expression;
denominator The denominator of the affine expression (optional argument with default value 1).
Exceptions:
std::invalid_argument Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of *this.

When considering congruences of a grid, the affine transformation

\[ \frac{\sum_{i=0}^{n-1} a_i x_i + b}{denominator}, \]

is assigned to var where expr is $\sum_{i=0}^{n-1} a_i x_i + b$ ($b$ is the inhomogeneous term).

If generators are up-to-date, then the specialized function affine_image() is used (for the system of generators) and inverse transformation to reach the same result. To obtain the inverse transformation, we use the following observation.

Observation:

  1. The affine transformation is invertible if the coefficient of var in this transformation (i.e. $a_\mathrm{var}$) is different from zero.
  2. If the transformation is invertible, then we can write

    \[ \mathrm{denominator} * {x'}_\mathrm{var} = \sum_{i = 0}^{n - 1} a_i x_i + b = a_\mathrm{var} x_\mathrm{var} + \sum_{i \neq \mathrm{var}} a_i x_i + b, \]

    , the inverse transformation is

    \[ a_\mathrm{var} x_\mathrm{var} = \mathrm{denominator} * {x'}_\mathrm{var} - \sum_{i \neq j} a_i x_i - b. \]

    .

Then, if the transformation is invertible, all the entities that were up-to-date remain up-to-date. Otherwise only congruences remain up-to-date.

Definition at line 1838 of file Grid_public.cc.

References Parma_Polyhedra_Library::Grid_Generator_System::affine_image(), Parma_Polyhedra_Library::Congruence_System::affine_preimage(), clear_congruences_minimized(), clear_generators_minimized(), clear_generators_up_to_date(), con_sys, congruences_are_up_to_date(), gen_sys, generators_are_up_to_date(), marked_empty(), minimize(), Parma_Polyhedra_Library::neg_assign(), OK(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().

Referenced by generalized_affine_preimage().

01840                                                                {
01841   // The denominator cannot be zero.
01842   if (denominator == 0)
01843     throw_invalid_argument("affine_preimage(v, e, d)", "d == 0");
01844 
01845   // Dimension-compatibility checks.
01846   // The dimension of `expr' should not be greater than the dimension
01847   // of `*this'.
01848   const dimension_type expr_space_dim = expr.space_dimension();
01849   if (space_dim < expr_space_dim)
01850     throw_dimension_incompatible("affine_preimage(v, e, d)", "e", expr);
01851   // `var' should be one of the dimensions of the grid.
01852   const dimension_type var_space_dim = var.space_dimension();
01853   if (space_dim < var_space_dim)
01854     throw_dimension_incompatible("affine_preimage(v, e, d)", "v", var);
01855 
01856   if (marked_empty())
01857     return;
01858 
01859   if (var_space_dim <= expr_space_dim && expr[var_space_dim] != 0) {
01860     // The transformation is invertible.
01861     if (congruences_are_up_to_date()) {
01862       // Congruence_System::affine_preimage() requires the third argument
01863       // to be a positive Coefficient.
01864       if (denominator > 0)
01865         con_sys.affine_preimage(var_space_dim, expr, denominator);
01866       else
01867         con_sys.affine_preimage(var_space_dim, -expr, -denominator);
01868       clear_congruences_minimized();
01869     }
01870     if (generators_are_up_to_date()) {
01871       // To build the inverse transformation,
01872       // after copying and negating `expr',
01873       // we exchange the roles of `expr[var_space_dim]' and `denominator'.
01874       Linear_Expression inverse;
01875       if (expr[var_space_dim] > 0) {
01876         inverse = -expr;
01877         inverse[var_space_dim] = denominator;
01878         gen_sys.affine_image(var_space_dim, inverse, expr[var_space_dim]);
01879       }
01880       else {
01881         // The new denominator is negative: we negate everything once
01882         // more, as Grid_Generator_System::affine_image() requires the
01883         // third argument to be positive.
01884         inverse = expr;
01885         inverse[var_space_dim] = denominator;
01886         neg_assign(inverse[var_space_dim]);
01887         gen_sys.affine_image(var_space_dim, inverse, -expr[var_space_dim]);
01888       }
01889       clear_generators_minimized();
01890     }
01891   }
01892   else {
01893     // The transformation is not invertible.
01894     // We need an up-to-date system of congruences.
01895     if (!congruences_are_up_to_date())
01896       minimize();
01897     // Congruence_System::affine_preimage() requires the third argument
01898     // to be a positive Coefficient.
01899     if (denominator > 0)
01900       con_sys.affine_preimage(var_space_dim, expr, denominator);
01901     else
01902       con_sys.affine_preimage(var_space_dim, -expr, -denominator);
01903 
01904     clear_generators_up_to_date();
01905     clear_congruences_minimized();
01906   }
01907   PPL_ASSERT(OK());
01908 }

void Parma_Polyhedra_Library::Grid::ascii_dump ( std::ostream &  s  )  const

Writes to s an ASCII representation of *this.

Definition at line 2572 of file Grid_public.cc.

References Parma_Polyhedra_Library::Grid_Generator_System::ascii_dump(), Parma_Polyhedra_Library::Congruence_System::ascii_dump(), Parma_Polyhedra_Library::Grid::Status::ascii_dump(), con_sys, congruences_are_minimized(), congruences_are_up_to_date(), dim_kinds, gen_sys, generators_are_minimized(), generators_are_up_to_date(), space_dim, and status.

02572                                        {
02573   using std::endl;
02574 
02575   s << "space_dim "
02576     << space_dim
02577     << endl;
02578   status.ascii_dump(s);
02579   s << "con_sys ("
02580     << (congruences_are_up_to_date() ? "" : "not_")
02581     << "up-to-date)"
02582     << endl;
02583   con_sys.ascii_dump(s);
02584   s << "gen_sys ("
02585     << (generators_are_up_to_date() ? "" : "not_")
02586     << "up-to-date)"
02587     << endl;
02588   gen_sys.ascii_dump(s);
02589   s << "dimension_kinds";
02590   if ((generators_are_up_to_date() && generators_are_minimized())
02591       || (congruences_are_up_to_date() && congruences_are_minimized()))
02592     for (Dimension_Kinds::const_iterator i = dim_kinds.begin();
02593          i != dim_kinds.end();
02594          ++i)
02595       s << " " << *i;
02596   s << endl;
02597 }

void Parma_Polyhedra_Library::Grid::ascii_dump (  )  const

Writes to std::cerr an ASCII representation of *this.

Referenced by OK().

bool Parma_Polyhedra_Library::Grid::ascii_load ( std::istream &  s  ) 

Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this accordingly. Returns true if successful, false otherwise.

Definition at line 2602 of file Grid_public.cc.

02602                                  {
02603   std::string str;
02604 
02605   if (!(s >> str) || str != "space_dim")
02606     return false;
02607 
02608   if (!(s >> space_dim))
02609     return false;
02610 
02611   if (!status.ascii_load(s))
02612     return false;
02613 
02614   if (!(s >> str) || str != "con_sys")
02615     return false;
02616 
02617   if (s >> str) {
02618     if (str == "(up-to-date)")
02619       set_congruences_up_to_date();
02620     else if (str != "(not_up-to-date)")
02621       return false;
02622   }
02623   else
02624     return false;
02625 
02626   if (!con_sys.ascii_load(s))
02627     return false;
02628 
02629   if (!(s >> str) || str != "gen_sys")
02630     return false;
02631 
02632   if (s >> str) {
02633     if (str == "(up-to-date)")
02634       set_generators_up_to_date();
02635     else if (str != "(not_up-to-date)")
02636       return false;
02637   }
02638   else
02639     return false;
02640 
02641   if (!gen_sys.ascii_load(s))
02642     return false;
02643 
02644   if (!(s >> str) || str != "dimension_kinds")
02645     return false;
02646 
02647   if (!marked_empty()
02648       && ((generators_are_up_to_date() && generators_are_minimized())
02649           || (congruences_are_up_to_date() && congruences_are_minimized()))) {
02650     dim_kinds.resize(space_dim + 1);
02651     for (Dimension_Kinds::size_type dim = 0; dim <= space_dim; ++dim) {
02652       short unsigned int dim_kind;
02653       if (!(s >> dim_kind))
02654         return false;
02655       switch(dim_kind) {
02656       case 0: dim_kinds[dim] = PARAMETER; break;
02657       case 1: dim_kinds[dim] = LINE; break;
02658       case 2: dim_kinds[dim] = GEN_VIRTUAL; break;
02659       default: return false;
02660       }
02661     }
02662   }
02663 
02664   // Check invariants.
02665   PPL_ASSERT(OK());
02666   return true;
02667 }

void Parma_Polyhedra_Library::Grid::bounded_affine_image ( Variable  var,
const Linear_Expression lb_expr,
const Linear_Expression ub_expr,
Coefficient_traits::const_reference  denominator = Coefficient_one() 
)

Assigns to *this the image of *this with respect to the bounded affine relation $\frac{\mathrm{lb\_expr}}{\mathrm{denominator}} \leq \mathrm{var}' \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}$.

Parameters:
var The variable updated by the affine relation;
lb_expr The numerator of the lower bounding affine expression;
ub_expr The numerator of the upper bounding affine expression;
denominator The (common) denominator for the lower and upper bounding affine expressions (optional argument with default value 1).
Exceptions:
std::invalid_argument Thrown if denominator is zero or if lb_expr (resp., ub_expr) and *this are dimension-incompatible or if var is not a space dimension of *this.

Definition at line 2351 of file Grid_public.cc.

References generalized_affine_image(), Parma_Polyhedra_Library::LESS_OR_EQUAL, marked_empty(), OK(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().

02354                                                                     {
02355 
02356   // The denominator cannot be zero.
02357   if (denominator == 0)
02358     throw_invalid_argument("bounded_affine_image(v, lb, ub, d)", "d == 0");
02359 
02360   // Dimension-compatibility checks.
02361   // `var' should be one of the dimensions of the grid.
02362   const dimension_type var_space_dim = var.space_dimension();
02363   if (space_dim < var_space_dim)
02364     throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
02365                                  "v", var);
02366   // The dimension of `lb_expr' and `ub_expr' should not be
02367   // greater than the dimension of `*this'.
02368   const dimension_type lb_space_dim = lb_expr.space_dimension();
02369   if (space_dim < lb_space_dim)
02370     throw_dimension_incompatible("bounded_affine_image(v, lb, ub)",
02371                                  "lb", lb_expr);
02372   const dimension_type ub_space_dim = ub_expr.space_dimension();
02373   if (space_dim < ub_space_dim)
02374     throw_dimension_incompatible("bounded_affine_image(v, lb, ub)",
02375                                  "ub", ub_expr);
02376 
02377   // Any image of an empty grid is empty.
02378   if (marked_empty())
02379     return;
02380 
02381   // In all other cases, generalized_affine_preimage() must
02382   // just add a line in the direction of var.
02383   generalized_affine_image(var,
02384                            LESS_OR_EQUAL,
02385                            ub_expr,
02386                            denominator);
02387 
02388   PPL_ASSERT(OK());
02389 }

void Parma_Polyhedra_Library::Grid::bounded_affine_preimage ( Variable  var,
const Linear_Expression lb_expr,
const Linear_Expression ub_expr,
Coefficient_traits::const_reference  denominator = Coefficient_one() 
)

Assigns to *this the preimage of *this with respect to the bounded affine relation $\frac{\mathrm{lb\_expr}}{\mathrm{denominator}} \leq \mathrm{var}' \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}$.

Parameters:
var The variable updated by the affine relation;
lb_expr The numerator of the lower bounding affine expression;
ub_expr The numerator of the upper bounding affine expression;
denominator The (common) denominator for the lower and upper bounding affine expressions (optional argument with default value 1).
Exceptions:
std::invalid_argument Thrown if denominator is zero or if lb_expr (resp., ub_expr) and *this are dimension-incompatible or if var is not a space dimension of *this.

Definition at line 2394 of file Grid_public.cc.

References generalized_affine_preimage(), Parma_Polyhedra_Library::LESS_OR_EQUAL, marked_empty(), OK(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().

02397                                                                        {
02398 
02399   // The denominator cannot be zero.
02400   if (denominator == 0)
02401     throw_invalid_argument("bounded_affine_preimage(v, lb, ub, d)", "d == 0");
02402 
02403   // Dimension-compatibility checks.
02404   // `var' should be one of the dimensions of the grid.
02405   const dimension_type var_space_dim = var.space_dimension();
02406   if (space_dim < var_space_dim)
02407     throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
02408                                  "v", var);
02409   // The dimension of `lb_expr' and `ub_expr' should not be
02410   // greater than the dimension of `*this'.
02411   const dimension_type lb_space_dim = lb_expr.space_dimension();
02412   if (space_dim < lb_space_dim)
02413     throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)",
02414                                  "lb", lb_expr);
02415   const dimension_type ub_space_dim = ub_expr.space_dimension();
02416   if (space_dim < ub_space_dim)
02417     throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)",
02418                                  "ub", ub_expr);
02419 
02420   // Any preimage of an empty grid is empty.
02421   if (marked_empty())
02422     return;
02423 
02424   // In all other cases, generalized_affine_preimage() must
02425   // just add a line in the direction of var.
02426   generalized_affine_preimage(var,
02427                               LESS_OR_EQUAL,
02428                               ub_expr,
02429                               denominator);
02430 
02431   PPL_ASSERT(OK());
02432 }

bool Parma_Polyhedra_Library::Grid::bounds ( const Linear_Expression expr,
const char *  method_call 
) const [private]

Checks if and how expr is bounded in *this.

Returns true if and only if from_above is true and expr is bounded from above in *this, or from_above is false and expr is bounded from below in *this.

Parameters:
expr The linear expression to test;
method_call The call description of the public parent method, for example "bounded_from_above(e)". Passed to throw_dimension_incompatible, as the first argument.
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

Definition at line 275 of file Grid_nonpublic.cc.

References bounds_no_check(), generators_are_minimized(), generators_are_up_to_date(), marked_empty(), minimize(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and update_generators().

Referenced by bounds_from_above(), bounds_from_below(), and max_min().

00276                                                  {
00277   // The dimension of `expr' must be at most the dimension of *this.
00278   if (space_dim < expr.space_dimension())
00279     throw_dimension_incompatible(method_call, "e", expr);
00280 
00281   // A zero-dimensional or empty grid bounds everything.
00282   if (space_dim == 0
00283       || marked_empty()
00284       || (!generators_are_up_to_date() && !update_generators()))
00285     return true;
00286   if (!generators_are_minimized() && !minimize())
00287     // Minimizing found `this' empty.
00288     return true;
00289 
00290   return bounds_no_check(expr);
00291 }

bool Parma_Polyhedra_Library::Grid::bounds_from_above ( const Linear_Expression expr  )  const [inline]

Returns true if and only if expr is bounded in *this.

This method is the same as bounds_from_below.

Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

Definition at line 312 of file Grid.inlines.hh.

References bounds().

00312                                                            {
00313   return bounds(expr, "bounds_from_above(e)");
00314 }

bool Parma_Polyhedra_Library::Grid::bounds_from_below ( const Linear_Expression expr  )  const [inline]

Returns true if and only if expr is bounded in *this.

This method is the same as bounds_from_above.

Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

Definition at line 317 of file Grid.inlines.hh.

References bounds().

00317                                                            {
00318   return bounds(expr, "bounds_from_below(e)");
00319 }

bool Parma_Polyhedra_Library::Grid::bounds_no_check ( const Linear_Expression expr  )  const [private]

Checks if and how expr is bounded in *this.

Returns true if and only if from_above is true and expr is bounded from above in *this, or from_above is false and expr is bounded from below in *this.

Parameters:
expr The linear expression to test;

Definition at line 294 of file Grid_nonpublic.cc.

References gen_sys, generators_are_minimized(), Parma_Polyhedra_Library::Scalar_Products::homogeneous_sign(), Parma_Polyhedra_Library::Grid_Generator::is_line_or_parameter(), marked_empty(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), space_dim, and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

Referenced by bounds(), frequency_no_check(), and wrap_assign().

00294                                                             {
00295   // The dimension of `expr' must be at most the dimension of *this.
00296   PPL_ASSERT(space_dim > 0 && space_dim >= expr.space_dimension());
00297   PPL_ASSERT(generators_are_minimized() && !marked_empty());
00298 
00299   // The generators are up to date and minimized.
00300   for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) {
00301     const Grid_Generator& g = gen_sys[i];
00302     // Only lines and parameters in `*this' can cause `expr' to be
00303     // unbounded.
00304     if (g.is_line_or_parameter()) {
00305       const int sp_sign = Scalar_Products::homogeneous_sign(expr, g);
00306       if (sp_sign != 0)
00307         // `*this' does not bound `expr'.
00308         return false;
00309     }
00310   }
00311   return true;
00312 }

bool Parma_Polyhedra_Library::Grid::can_recycle_congruence_systems (  )  [inline, static]

Returns true indicating that this domain has methods that can recycle congruences.

Definition at line 292 of file Grid.inlines.hh.

00292                                      {
00293   return true;
00294 }

bool Parma_Polyhedra_Library::Grid::can_recycle_constraint_systems (  )  [inline, static]

Returns true indicating that this domain has methods that can recycle constraints.

Definition at line 287 of file Grid.inlines.hh.

00287                                      {
00288   return true;
00289 }

void Parma_Polyhedra_Library::Grid::clear_congruences_minimized (  )  [inline, private]
void Parma_Polyhedra_Library::Grid::clear_congruences_up_to_date (  )  [inline, private]
void Parma_Polyhedra_Library::Grid::clear_empty (  )  [inline, private]

Clears the status flag indicating that the grid is empty.

Definition at line 82 of file Grid.inlines.hh.

References Parma_Polyhedra_Library::Grid::Status::reset_empty(), and status.

Referenced by add_grid_generator(), and add_recycled_grid_generators().

00082                   {
00083   status.reset_empty();
00084 }

void Parma_Polyhedra_Library::Grid::clear_generators_minimized (  )  [inline, private]
void Parma_Polyhedra_Library::Grid::clear_generators_up_to_date (  )  [inline, private]

Sets status to express that generators are out of date.

Definition at line 104 of file Grid.inlines.hh.

References clear_generators_minimized(), Parma_Polyhedra_Library::Grid::Status::reset_g_up_to_date(), and status.

Referenced by add_congruence_no_check(), add_recycled_congruences(), affine_preimage(), concatenate_assign(), intersection_assign(), OK(), and remove_higher_space_dimensions().

00104                                   {
00105   clear_generators_minimized();
00106   status.reset_g_up_to_date();
00107   // Can get rid of gen_sys here.
00108 }

void Parma_Polyhedra_Library::Grid::concatenate_assign ( const Grid y  ) 

Assigns to *this the concatenation of *this and y, taken in this order.

Exceptions:
std::length_error Thrown if the concatenation would cause the vector space to exceed dimension max_space_dimension().

Definition at line 218 of file Grid_chdims.cc.

References clear_congruences_minimized(), clear_generators_up_to_date(), con_sys, Parma_Polyhedra_Library::Congruence_System::concatenate(), congruences(), congruences_are_up_to_date(), marked_empty(), max_space_dimension(), OK(), set_empty(), space_dim, space_dimension(), throw_space_dimension_overflow(), and update_congruences().

00218                                          {
00219   // The space dimension of the resulting grid must be at most the
00220   // maximum allowed space dimension.
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   // If `*this' or `y' are empty grids just adjust the space
00229   // dimension.
00230   if (marked_empty() || y.marked_empty()) {
00231     space_dim += added_columns;
00232     set_empty();
00233     return;
00234   }
00235 
00236   // If `y' is a universe 0-dim grid, the result is `*this'.
00237   if (added_columns == 0)
00238     return;
00239 
00240   // If `*this' is a universe 0-dim space grid, the result is `y'.
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   // Check that the system is OK, taking into account that the system
00257   // of congruences may now be empty.
00258   PPL_ASSERT(OK());
00259 }

void Parma_Polyhedra_Library::Grid::congruence_widening_assign ( const Grid y,
unsigned *  tp = NULL 
)

Assigns to *this the result of computing the Grid widening between *this and y using congruence systems.

Parameters:
y A grid that must be contained in *this;
tp An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique).
Exceptions:
std::invalid_argument Thrown if *this and y are dimension-incompatible.

Definition at line 76 of file Grid_widenings.cc.

References add_recycled_congruences(), con_sys, congruences_are_minimized(), congruences_are_up_to_date(), contains(), dim_kinds, marked_empty(), Parma_Polyhedra_Library::Congruence_System::num_equalities(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), select_wider_congruences(), set_congruences_minimized(), set_empty(), simplify(), space_dim, swap(), throw_dimension_incompatible(), and update_congruences().

Referenced by limited_congruence_extrapolation_assign(), and widening_assign().

00076                                                                      {
00077   Grid& x = *this;
00078   Grid& y = const_cast<Grid&>(const_y);
00079   // Dimension-compatibility check.
00080   if (x.space_dim != y.space_dim)
00081     throw_dimension_incompatible("widening_assign(y)", "y", y);
00082 
00083   // Stable behavior is only guaranteed if y is contained in or equal
00084   // to x.
00085 #ifndef NDEBUG
00086   {
00087     // Assume y is contained in or equal to x.
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   // Leave `x' the same if `x' or `y' is zero-dimensional or empty.
00095   if (x.space_dim == 0 || x.marked_empty() || y.marked_empty())
00096     return;
00097 
00098   // Ensure that the `x' congruences are in minimal form.
00099   if (x.congruences_are_up_to_date()) {
00100     if (!x.congruences_are_minimized()) {
00101       if (simplify(x.con_sys, x.dim_kinds)) {
00102         // `x' is empty.
00103         x.set_empty();
00104         return;
00105       }
00106       x.set_congruences_minimized();
00107     }
00108   }
00109   else
00110     x.update_congruences();
00111 
00112   // Ensure that the `y' congruences are in minimal form.
00113   if (y.congruences_are_up_to_date()) {
00114     if (!y.congruences_are_minimized()) {
00115       if (simplify(y.con_sys, y.dim_kinds)) {
00116         // `y' is empty.
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   // Copy into `cgs' the congruences of `x' that are common to `y',
00130   // according to the grid widening.
00131   Congruence_System cgs;
00132   x.select_wider_congruences(y, cgs);
00133 
00134   if (cgs.num_rows() == con_sys.num_rows())
00135     // All congruences were selected, thus the result is `x'.
00136     return;
00137 
00138   // A strict subset of the congruences was selected.
00139 
00140   Grid result(x.space_dim);
00141   result.add_recycled_congruences(cgs);
00142 
00143   // Check whether we are using the widening-with-tokens technique
00144   // and there are still tokens available.
00145   if (tp && *tp > 0) {
00146     // There are tokens available.  If `result' is not a subset of
00147     // `x', then it is less precise and we use one of the available
00148     // tokens.
00149     if (!x.contains(result))
00150       --(*tp);
00151   }
00152   else
00153     // No tokens.
00154     std::swap(x, result);
00155 
00156   PPL_ASSERT(x.OK(true));
00157 }

const PPL::Congruence_System & Parma_Polyhedra_Library::Grid::congruences (  )  const

Returns the system of congruences.

Definition at line 279 of file Grid_public.cc.

References con_sys, congruences_are_up_to_date(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), space_dim, and update_congruences().

Referenced by Parma_Polyhedra_Library::Pointset_Powerset< PSET >::approximate_partition(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::approximate_partition_aux(), concatenate_assign(), constraints(), difference_assign(), expand_space_dimension(), and minimized_congruences().

00279                            {
00280   if (marked_empty())
00281     return con_sys;
00282 
00283   if (space_dim == 0) {
00284     // Zero-dimensional universe.
00285     PPL_ASSERT(con_sys.num_rows() == 0 && con_sys.num_columns() == 2);
00286     return con_sys;
00287   }
00288 
00289   if (!congruences_are_up_to_date())
00290     update_congruences();
00291 
00292   return con_sys;
00293 }

bool Parma_Polyhedra_Library::Grid::congruences_are_minimized (  )  const [inline, private]
bool Parma_Polyhedra_Library::Grid::congruences_are_up_to_date (  )  const [inline, private]
bool Parma_Polyhedra_Library::Grid::constrains ( Variable  var  )  const

Returns true if and only if var is constrained in *this.

Exceptions:
std::invalid_argument Thrown if var is not a space dimension of *this.

Definition at line 800 of file Grid_public.cc.

References Parma_Polyhedra_Library::Grid_Generator::coefficient(), con_sys, congruences_are_up_to_date(), gen_sys, generators_are_minimized(), generators_are_up_to_date(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Grid_Generator::is_line(), marked_empty(), minimize(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), and update_congruences().

00800                                             {
00801   // `var' should be one of the dimensions of the grid.
00802   const dimension_type var_space_dim = var.space_dimension();
00803   if (space_dim < var_space_dim)
00804     throw_dimension_incompatible("constrains(v)", "v", var);
00805 
00806   // An empty grid constrains all variables.
00807   if (marked_empty())
00808     return true;
00809 
00810   if (generators_are_up_to_date()) {
00811     // Since generators are up-to-date, the generator system (since it is
00812     // well formed) contains a point.  Hence the grid is not empty.
00813     if (congruences_are_up_to_date())
00814       // Here a variable is constrained if and only if it is
00815       // syntactically constrained.
00816       goto syntactic_check;
00817 
00818     if (generators_are_minimized()) {
00819       // Try a quick, incomplete check for the universe grid:
00820       // a universe grid constrains no variable.
00821       // Count the number of lines (they are linearly independent).
00822       dimension_type num_lines = 0;
00823       for (dimension_type i = gen_sys.num_rows(); i-- > 0; )
00824         if (gen_sys[i].is_line())
00825           ++num_lines;
00826 
00827       if (num_lines == space_dim)
00828         return false;
00829     }
00830 
00831     // Scan generators: perhaps we will find line(var).
00832     const dimension_type var_id = var.id();
00833     for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) {
00834       const Grid_Generator& g_i = gen_sys[i];
00835       if (g_i.is_line()) {
00836         if (sgn(g_i.coefficient(var)) != 0) {
00837           for (dimension_type j = 0; j < space_dim; ++j)
00838             if (g_i.coefficient(Variable(j)) != 0 && j != var_id)
00839               goto next;
00840           return true;
00841         }
00842       }
00843     next:
00844       ;
00845     }
00846 
00847     // We are still here: at least we know that the grid is not empty.
00848     update_congruences();
00849     goto syntactic_check;
00850   }
00851 
00852   // We must minimize to detect emptiness and obtain constraints.
00853   if (!minimize())
00854     return true;
00855 
00856  syntactic_check:
00857   for (dimension_type i = con_sys.num_rows(); i-- > 0; )
00858     if (con_sys[i].coefficient(var) != 0)
00859       return true;
00860   return false;
00861 }

Constraint_System Parma_Polyhedra_Library::Grid::constraints (  )  const [inline]

Returns a system of equality constraints satisfied by *this with the same affine dimension as *this.

Definition at line 235 of file Grid.inlines.hh.

References congruences().

Referenced by Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), and Parma_Polyhedra_Library::NNC_Polyhedron::NNC_Polyhedron().

00235                         {
00236   return Constraint_System(congruences());;
00237 }

void Parma_Polyhedra_Library::Grid::construct ( Grid_Generator_System ggs  )  [private]

Builds a grid from a system of grid generators.

The grid inherits the space dimension of the generator system.

Parameters:
ggs The system of grid generators defining the grid. Its data-structures may be recycled to build the grid.

Definition at line 143 of file Grid_nonpublic.cc.

References con_sys, gen_sys, Parma_Polyhedra_Library::Matrix::has_no_rows(), Parma_Polyhedra_Library::Grid_Generator_System::has_points(), Parma_Polyhedra_Library::Congruence_System::insert(), max_space_dimension(), normalize_divisors(), OK(), Parma_Polyhedra_Library::Grid::Status::set_empty(), set_generators_up_to_date(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Congruence_System::space_dimension(), Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), status, swap(), throw_invalid_generators(), and Parma_Polyhedra_Library::Congruence::zero_dim_false().

00143                                              {
00144   // Protecting against space dimension overflow is up to the caller.
00145   PPL_ASSERT(ggs.space_dimension() <= max_space_dimension());
00146   // Preparing con_sys and gen_sys is up to the caller.
00147   PPL_ASSERT(ggs.space_dimension() == con_sys.space_dimension());
00148   PPL_ASSERT(ggs.space_dimension() == gen_sys.space_dimension());
00149   PPL_ASSERT(con_sys.has_no_rows());
00150   PPL_ASSERT(gen_sys.has_no_rows());
00151 
00152   // Set the space dimension.
00153   space_dim = ggs.space_dimension();
00154 
00155   // An empty set of generators defines the empty grid.
00156   if (ggs.has_no_rows()) {
00157     status.set_empty();
00158     // Insert the zero dim false congruence system into `con_sys'.
00159     // `gen_sys' is already in empty form.
00160     con_sys.insert(Congruence::zero_dim_false());
00161     return;
00162   }
00163 
00164   // Non-empty valid generator systems have a supporting point, at least.
00165   if (!ggs.has_points())
00166     throw_invalid_generators("Grid(ggs)", "ggs");
00167 
00168   if (space_dim == 0)
00169     set_zero_dim_univ();
00170   else {
00171     // Steal the rows from `ggs'.
00172     std::swap(gen_sys, ggs);
00173     normalize_divisors(gen_sys);
00174     // Generators are now up-to-date.
00175     set_generators_up_to_date();
00176   }
00177 
00178   PPL_ASSERT(OK());
00179 }

void Parma_Polyhedra_Library::Grid::construct ( Congruence_System cgs  )  [private]

Builds a grid from a system of congruences.

The grid inherits the space dimension of the congruence system.

Parameters:
cgs The system of congruences defining the grid. Its data-structures may be recycled to build the grid.

Definition at line 105 of file Grid_nonpublic.cc.

References con_sys, gen_sys, Parma_Polyhedra_Library::Matrix::has_no_rows(), Parma_Polyhedra_Library::Congruence_System::insert(), max_space_dimension(), Parma_Polyhedra_Library::Congruence_System::normalize_moduli(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), set_congruences_up_to_date(), Parma_Polyhedra_Library::Grid::Status::set_empty(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), Parma_Polyhedra_Library::Congruence_System::space_dimension(), status, swap(), and Parma_Polyhedra_Library::Congruence::zero_dim_false().

00105                                          {
00106   // Protecting against space dimension overflow is up to the caller.
00107   PPL_ASSERT(cgs.space_dimension() <= max_space_dimension());
00108   // Preparing con_sys and gen_sys is up to the caller.
00109   PPL_ASSERT(cgs.space_dimension() == con_sys.space_dimension());
00110   PPL_ASSERT(cgs.space_dimension() == gen_sys.space_dimension());
00111   PPL_ASSERT(con_sys.has_no_rows());
00112   PPL_ASSERT(gen_sys.has_no_rows());
00113 
00114   // Set the space dimension.
00115   space_dim = cgs.space_dimension();
00116 
00117   if (space_dim > 0) {
00118     // Stealing the rows from `cgs'.
00119     std::swap(con_sys, cgs);
00120     con_sys.normalize_moduli();
00121     set_congruences_up_to_date();
00122   }
00123   else {
00124     // Here `space_dim == 0'.
00125     if (cgs.num_columns() > 1)
00126       // See if an inconsistent congruence has been passed.
00127       for (dimension_type i = cgs.num_rows(); i-- > 0; )
00128         if (cgs[i].is_inconsistent()) {
00129           // Inconsistent congruence found: the grid is empty.
00130           status.set_empty();
00131           // Insert the zero dim false congruence system into `con_sys'.
00132           // `gen_sys' is already in empty form.
00133           con_sys.insert(Congruence::zero_dim_false());
00134           PPL_ASSERT(OK());
00135           return;
00136         }
00137     set_zero_dim_univ();
00138   }
00139   PPL_ASSERT(OK());
00140 }

void Parma_Polyhedra_Library::Grid::construct ( dimension_type  num_dimensions,
Degenerate_Element  kind 
) [private]

Builds a grid universe or empty grid.

Parameters:
num_dimensions The number of dimensions of the vector space enclosing the grid;
kind specifies whether the universe or the empty grid has to be built.

Definition at line 52 of file Grid_nonpublic.cc.

References con_sys, CON_VIRTUAL, dim_kinds, Parma_Polyhedra_Library::EMPTY, gen_sys, Parma_Polyhedra_Library::Congruence_System::increase_space_dimension(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), OK(), PROPER_CONGRUENCE, set_congruences_minimized(), Parma_Polyhedra_Library::Grid::Status::set_empty(), set_generators_minimized(), set_zero_dim_univ(), space_dim, status, Parma_Polyhedra_Library::Congruence_System::swap(), swap(), Parma_Polyhedra_Library::Congruence::zero_dim_false(), and Parma_Polyhedra_Library::Congruence::zero_dim_integrality().

Referenced by Grid().

00053                                                     {
00054   space_dim = num_dimensions;
00055 
00056   if (kind == EMPTY) {
00057     // Set emptiness directly instead of with set_empty, as gen_sys is
00058     // already correctly initialized.
00059 
00060     status.set_empty();
00061 
00062     // Extend the zero dim false congruence system to the appropriate
00063     // dimension and then store it in `con_sys'.
00064     Congruence_System cgs(Congruence::zero_dim_false());
00065     cgs.increase_space_dimension(space_dim);
00066     const_cast<Congruence_System&>(con_sys).swap(cgs);
00067 
00068     PPL_ASSERT(OK());
00069     return;
00070   }
00071 
00072   if (num_dimensions > 0) {
00073     con_sys.increase_space_dimension(num_dimensions);
00074 
00075     // Initialize both systems to universe representations.
00076 
00077     set_congruences_minimized();
00078     set_generators_minimized();
00079     dim_kinds.resize(num_dimensions + 1);
00080 
00081     // Extend the zero dim integrality congruence system to the
00082     // appropriate dimension and then store it in `con_sys'.
00083     Congruence_System cgs(Congruence::zero_dim_integrality());
00084     cgs.increase_space_dimension(space_dim);
00085     cgs[0][0] = 1; // Recover minimal form after cgs(zdi) normalization.
00086     con_sys.swap(cgs);
00087 
00088     dim_kinds[0] = PROPER_CONGRUENCE /* a.k.a. PARAMETER */;
00089 
00090     // Trivially true point.
00091     gen_sys.insert(grid_point(0*(Variable(0))));
00092 
00093     // A line for each dimension.
00094     dimension_type dim = 0;
00095     while (dim < num_dimensions) {
00096       gen_sys.insert(grid_line(Variable(dim)));
00097       dim_kinds[++dim] = CON_VIRTUAL /* a.k.a. LINE */;
00098     }
00099   }
00100   else
00101     set_zero_dim_univ();
00102 }

bool Parma_Polyhedra_Library::Grid::contains ( const Grid y  )  const

Returns true if and only if *this contains y.

Exceptions:
std::invalid_argument Thrown if *this and y are dimension-incompatible.

Definition at line 2543 of file Grid_public.cc.

References is_empty(), is_included_in(), marked_empty(), quick_equivalence_test(), space_dim, throw_dimension_incompatible(), and TVB_TRUE.

Referenced by Parma_Polyhedra_Library::Pointset_Powerset< PSET >::check_containment(), congruence_widening_assign(), difference_assign(), generator_widening_assign(), limited_congruence_extrapolation_assign(), limited_extrapolation_assign(), limited_generator_extrapolation_assign(), strictly_contains(), and widening_assign().

02543                                      {
02544   const Grid& x = *this;
02545 
02546   // Dimension-compatibility check.
02547   if (x.space_dim != y.space_dim)
02548     throw_dimension_incompatible("contains(y)", "y", y);
02549 
02550   if (y.marked_empty())
02551     return true;
02552   if (x.marked_empty())
02553     return y.is_empty();
02554   if (y.space_dim == 0)
02555     return true;
02556   if (x.quick_equivalence_test(y) == Grid::TVB_TRUE)
02557     return true;
02558   return y.is_included_in(x);
02559 }

bool Parma_Polyhedra_Library::Grid::contains_integer_point (  )  const

Returns true if and only if *this contains at least one integer point.

Definition at line 778 of file Grid_public.cc.

References add_recycled_congruences(), Parma_Polyhedra_Library::Congruence_System::insert(), is_empty(), marked_empty(), and space_dim.

00778                                       {
00779   // Empty grids have no points.
00780   if (marked_empty())
00781     return false;
00782 
00783   // A zero-dimensional, universe grid has, by convention, an
00784   // integer point.
00785   if (space_dim == 0)
00786     return true;
00787 
00788   // A grid has an integer point if its intersection with the integer
00789   // grid is non-empty.
00790   Congruence_System cgs;
00791   for (dimension_type var_index = space_dim; var_index-- > 0; )
00792     cgs.insert(Variable(var_index) %= 0);
00793 
00794   Grid gr = *this;
00795   gr.add_recycled_congruences(cgs);
00796   return !gr.is_empty();
00797 }

void Parma_Polyhedra_Library::Grid::conversion ( Grid_Generator_System source,
Congruence_System dest,
Dimension_Kinds dim_kinds 
) [static, private]

Converts congruence system dest to be equivalent to generator system source.

Definition at line 155 of file Grid_conversion.cc.

References CON_VIRTUAL, Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::gcd_assign(), GEN_VIRTUAL, Parma_Polyhedra_Library::lcm_assign(), LINE, lower_triangular(), multiply_grid(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), PARAMETER, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Congruence_System::resize_no_copy(), Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), Parma_Polyhedra_Library::sub_mul_assign(), and upper_triangular().

00156                                              {
00157   // Quite similar to the congruence to generator version below.
00158   // Changes here may be needed there too.
00159 
00160   PPL_ASSERT(upper_triangular(source, dim_kinds));
00161 
00162   // Initialize matrix row number counters and compute the LCM of the
00163   // diagonal entries of the parameters in `source'.
00164   //
00165   // The top-down order of the generator system rows corresponds to
00166   // the left-right order of the dimensions, while the congruence
00167   // system rows have a bottom-up ordering.
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       // Virtual generators map to equalities.
00176       ++dest_num_rows;
00177     else {
00178       --source_index;
00179       if (dim_kinds[dim] == PARAMETER) {
00180         // Dimension `dim' has a parameter row at `source_index' in
00181         // `source', so include in `diagonal_lcm' the `dim'th element
00182         // of that row.
00183         lcm_assign(diagonal_lcm, diagonal_lcm, source[source_index][dim]);
00184         // Parameters map to proper congruences.
00185         ++dest_num_rows;
00186       }
00187       // Lines map to virtual congruences.
00188     }
00189   PPL_ASSERT(source_index == 0);
00190 
00191   // `source' must be regular.
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 /* moduli */);
00197 
00198   // In `dest' initialize row types and elements, including setting
00199   // the diagonal elements to the inverse ratio of the `source'
00200   // diagonal elements.
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;           // An equality.
00215         cg[dim] = 1;
00216       }
00217       else {
00218         PPL_ASSERT(dim_kinds[dim] == PARAMETER);
00219         --source_index;
00220         cg[dims] = 1;           // A proper congruence.
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   // Convert.
00232   //
00233   // `source_index' and `dest_index' hold the positions of pivot rows
00234   // in `source' and `dest'.  The order of the rows in `dest' is the
00235   // reverse of the order in `source', so the rows are iterated from
00236   // last to first (index 0) in `source' and from first to last in
00237   // `dest'.
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       // In the rows in `dest' above `dest_index' divide each element
00248       // at column `dim' by `source_dim'.
00249       for (dimension_type row = dest_index; row-- > 0; ) {
00250         Congruence& cg = dest[row];
00251 
00252         // Multiply the representation of `dest' such that entry `dim'
00253         // of `g' is a multiple of `source_dim'.  This ensures that
00254         // the result of the division that follows is a whole number.
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     // Invert and transpose the source row at `source_index' into the
00265     // destination row at `dest_index'.
00266     //
00267     // Consider each dimension `dim_prec' that precedes `dim', as the
00268     // rows in `dest' that follow `dim_index' have zeroes at index
00269     // `dim'.
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         // In order to compute the transpose of the inverse of
00278         // `source', subtract source[tmp_source_index][dim] times the
00279         // column vector in `dest' at `dim' from the column vector in
00280         // `dest' at `dim_prec'.
00281         //
00282         // I.e., for each row `dest_index' in `dest' that is above the
00283         // row `dest_index', subtract dest[tmp_source_index][dim]
00284         // times the entry `dim' from the entry at `dim_prec'.
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   // Set the modulus in every congruence.
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       // `cg' is a proper congruence.
00299       cg[dims] = modulus;
00300   }
00301 
00302   PPL_ASSERT(lower_triangular(dest, dim_kinds));
00303 
00304   // Since we are reducing the system to "strong minimal form",
00305   // reduce the coefficients in the congruence system
00306   // using "diagonal" values.
00307   for (dimension_type dim = dims, i = 0; dim-- > 0; )
00308     if (dim_kinds[dim] != CON_VIRTUAL)
00309       // Factor the "diagonal" congruence out of the preceding rows.
00310       reduce_reduced<Congruence_System, Congruence>
00311         (dest, dim, i++, 0, dim, dim_kinds, false);
00312 }

void Parma_Polyhedra_Library::Grid::conversion ( Congruence_System source,
Grid_Generator_System dest,
Dimension_Kinds dim_kinds 
) [static, private]

Converts generator system dest to be equivalent to congruence system source.

Definition at line 315 of file Grid_conversion.cc.

References CON_VIRTUAL, EQUALITY, Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::gcd_assign(), GEN_VIRTUAL, Parma_Polyhedra_Library::lcm_assign(), LINE, lower_triangular(), multiply_grid(), Parma_Polyhedra_Library::Matrix::num_columns(), PARAMETER, PPL_DIRTY_TEMP_COEFFICIENT, PROPER_CONGRUENCE, Parma_Polyhedra_Library::Grid_Generator_System::resize_no_copy(), Parma_Polyhedra_Library::Grid_Generator_System::set_index_first_pending_row(), Parma_Polyhedra_Library::Grid_Generator::set_is_line(), Parma_Polyhedra_Library::Grid_Generator::set_is_parameter_or_point(), Parma_Polyhedra_Library::sub_mul_assign(), and upper_triangular().

Referenced by update_generators().

00316                                              {
00317   // Quite similar to the generator to congruence version above.
00318   // Changes here may be needed there too.
00319 
00320   PPL_ASSERT(lower_triangular(source, dim_kinds));
00321 
00322   // Initialize matrix row number counters and compute the LCM of the
00323   // diagonal entries of the proper congruences in `source'.
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       // Virtual congruences map to lines.
00331       ++dest_num_rows;
00332     else {
00333       if (dim_kinds[dim] == PROPER_CONGRUENCE) {
00334         // Dimension `dim' has a proper congruence row at
00335         // `source_num_rows' in `source', so include in `diagonal_lcm'
00336         // the `dim'th element of that row.
00337         lcm_assign(diagonal_lcm, diagonal_lcm, source[source_num_rows][dim]);
00338         // Proper congruences map to parameters.
00339         ++dest_num_rows;
00340       }
00341       // Equalities map to virtual generators.
00342       ++source_num_rows;
00343     }
00344 
00345   // `source' must be regular.
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 /* parameter divisor */);
00352 
00353   // In `dest' initialize row types and elements, including setting
00354   // the diagonal elements to the inverse ratio of the `source'
00355   // diagonal elements.
00356   //
00357   // The top-down order of the congruence system rows corresponds to
00358   // the right-left order of the dimensions.
00359   dimension_type source_index = 0;
00360   // The generator system has a bottom-up ordering.
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   // Convert.
00390   //
00391   // `source_index' and `dest_index' hold the positions of pivot rows
00392   // in `source' and `dest'.  The order of the rows in `dest' is the
00393   // reverse of the order in `source', so the rows are iterated from
00394   // last to first (index 0) in `source' and from first to last in
00395   // `dest'.
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       // In the rows in `dest' above `dest_index' divide each element
00406       // at column `dim' by `source_dim'.
00407       for (dimension_type row = dest_index; row-- > 0; ) {
00408         Grid_Generator& g = dest[row];
00409 
00410         // Multiply the representation of `dest' such that entry `dim'
00411         // of `g' is a multiple of `source_dim'.  This ensures that
00412         // the result of the division that follows is a whole number.
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 /* parameter divisor */);
00417 
00418         Coefficient& g_dim = g[dim];
00419         exact_div_assign(g_dim, g_dim, source_dim);
00420       }
00421     }
00422 
00423     // Invert and transpose the source row at `source_index' into the
00424     // destination row at `dest_index'.
00425     //
00426     // Consider each dimension `dim_fol' that follows `dim', as the
00427     // rows in `dest' that follow row `dest_index' are zero at index
00428     // `dim'.
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         // In order to compute the transpose of the inverse of
00437         // `source', subtract source[tmp_source_index][dim] times the
00438         // column vector in `dest' at `dim' from the column vector in
00439         // `dest' at `dim_fol'.
00440         //
00441         // I.e., for each row `dest_index' in `dest' that is above the
00442         // row `dest_index', subtract dest[tmp_source_index][dim]
00443         // times the entry `dim' from the entry at `dim_fol'.
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   // Since we are reducing the system to "strong minimal form",
00456   // reduce the coordinates in the grid_generator system
00457   // using "diagonal" values.
00458   for (dimension_type dim = 0, i = 0; dim < dims; ++dim)
00459     if (dim_kinds[dim] != GEN_VIRTUAL)
00460       // Factor the "diagonal" generator out of the preceding rows.
00461       reduce_reduced<Grid_Generator_System, Grid_Generator>
00462         (dest, dim, i++, dim, dims - 1, dim_kinds);
00463 
00464   // Ensure that the parameter divisors are the same as the divisor of
00465   // the point.
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 }

void Parma_Polyhedra_Library::Grid::difference_assign ( const Grid y  ) 

Assigns to *this the grid-difference of *this and y.

The grid difference between grids x and y is the smallest grid containing all the points from x and y that are only in x.

Exceptions:
std::invalid_argument Thrown if *this and y are dimension-incompatible.

Definition at line 1484 of file Grid_public.cc.

References add_congruence_no_check(), Parma_Polyhedra_Library::Congruence_System::begin(), congruences(), contains(), Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Congruence_System::end(), Parma_Polyhedra_Library::Poly_Con_Relation::implies(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Congruence::is_proper_congruence(), marked_empty(), Parma_Polyhedra_Library::Congruence::modulus(), OK(), relation_with(), set_empty(), space_dim, throw_dimension_incompatible(), and upper_bound_assign().

Referenced by upper_bound_assign_if_exact().

01484                                         {
01485   Grid& x = *this;
01486   // Dimension-compatibility check.
01487   if (x.space_dim != y.space_dim)
01488     throw_dimension_incompatible("difference_assign(y)", "y", y);
01489 
01490   if (y.marked_empty() || x.marked_empty())
01491     return;
01492 
01493   // If both grids are zero-dimensional, then they are necessarily
01494   // universe grids, so the result is empty.
01495   if (x.space_dim == 0) {
01496     x.set_empty();
01497     return;
01498   }
01499 
01500   if (y.contains(x)) {
01501     x.set_empty();
01502     return;
01503   }
01504 
01505   Grid new_grid(x.space_dim, EMPTY);
01506 
01507   const Congruence_System& y_cgs = y.congruences();
01508   for (Congruence_System::const_iterator i = y_cgs.begin(),
01509          y_cgs_end = y_cgs.end(); i != y_cgs_end; ++i) {
01510     const Congruence& cg = *i;
01511 
01512     // The 2-complement cg2 of cg = ((e %= 0) / m) is the congruence
01513     // defining the sets of points exactly half-way between successive
01514     // hyperplanes e = km and e = (k+1)m, for any integer k; that is,
01515     // the hyperplanes defined by 2e = (2k + 1)m, for any integer k.
01516     // Thus `cg2' is the congruence ((2e %= m) / 2m).
01517 
01518     // As the grid difference must be a grid, only add the
01519     // 2-complement congruence to x if the resulting grid includes all
01520     // the points in x that did not satisfy `cg'.
01521 
01522     // The 2-complement of cg can be included in the result only if x
01523     // holds points other than those in cg.
01524     if (x.relation_with(cg).implies(Poly_Con_Relation::is_included()))
01525       continue;
01526 
01527     if (cg.is_proper_congruence()) {
01528       const Linear_Expression e = Linear_Expression(cg);
01529       // Congruence cg is ((e %= 0) / m).
01530       const Coefficient& m = cg.modulus();
01531       // If x is included in the grid defined by the congruences cg
01532       // and its 2-complement (i.e. the grid defined by the congruence
01533       // (2e %= 0) / m) then add the 2-complement to the potential
01534       // result.
01535       if (x.relation_with((2*e %= 0) / m)
01536           .implies(Poly_Con_Relation::is_included())) {
01537         Grid z = x;
01538         z.add_congruence_no_check((2*e %= m) / (2*m));
01539         new_grid.upper_bound_assign(z);
01540         continue;
01541       }
01542     }
01543     return;
01544   }
01545 
01546   *this = new_grid;
01547 
01548   PPL_ASSERT(OK());
01549 }

void Parma_Polyhedra_Library::Grid::drop_some_non_integer_points ( const Variables_Set vars,
Complexity_Class  complexity = ANY_COMPLEXITY 
)

Possibly tightens *this by dropping all points with non-integer coordinates for the space dimensions corresponding to vars.

Parameters:
vars Points with non-integer coordinates for these variables/space-dimensions can be discarded.
complexity This argument is ignored as the algorithm used has polynomial complexity.

Definition at line 2872 of file Grid_public.cc.

References add_congruence(), marked_empty(), OK(), space_dimension(), Parma_Polyhedra_Library::Variables_Set::space_dimension(), and throw_dimension_incompatible().

02873                                                           {
02874   // Dimension-compatibility check.
02875   const dimension_type min_space_dim = vars.space_dimension();
02876   if (space_dimension() < min_space_dim)
02877     throw_dimension_incompatible("drop_some_non_integer_points(vs, cmpl)",
02878                                  min_space_dim);
02879 
02880   if (marked_empty() || min_space_dim == 0)
02881     return;
02882 
02883   // By adding the integral congruences for each dimension in vars to
02884   // the congruence system defining \p *this, the grid will keep only
02885   // those points that have integer coordinates for all the dimensions
02886   // in vars. All points in \p *this with non-integral coordinates for
02887   // the dimensions in vars are removed.
02888   for (Variables_Set::const_iterator i = vars.begin(),
02889          vars_end = vars.end(); i != vars.end(); ++i)
02890     add_congruence(Variable(*i) %= 0);
02891 
02892   PPL_ASSERT(OK());
02893 }

void Parma_Polyhedra_Library::Grid::drop_some_non_integer_points ( Complexity_Class  complexity = ANY_COMPLEXITY  ) 

Possibly tightens *this by dropping all points with non-integer coordinates.

Parameters:
complexity This argument is ignored as the algorithm used has polynomial complexity.

Definition at line 2857 of file Grid_public.cc.

References add_congruence(), marked_empty(), OK(), and space_dim.

02857                                                       {
02858   if (marked_empty() || space_dim == 0)
02859     return;
02860 
02861   // By adding integral congruences for each dimension to the
02862   // congruence system, defining \p *this, the grid will keep only
02863   // those points that have integral coordinates. All points in \p
02864   // *this with non-integral coordinates are removed.
02865   for (dimension_type i = space_dim; i-- > 0; )
02866     add_congruence(Variable(i) %= 0);
02867 
02868   PPL_ASSERT(OK());
02869 }

void Parma_Polyhedra_Library::Grid::expand_space_dimension ( Variable  var,
dimension_type  m 
)

Creates m copies of the space dimension corresponding to var.

Parameters:
var The variable corresponding to the space dimension to be replicated;
m The number of replicas to be created.
Exceptions:
std::invalid_argument Thrown if var does not correspond to a dimension of the vector space.
std::length_error Thrown if adding m new space dimensions would cause the vector space to exceed dimension max_space_dimension().

If *this has space dimension $n$, with $n > 0$, and var has space dimension $k \leq n$, then the $k$-th space dimension is expanded to m new space dimensions $n$, $n+1$, $\dots$, $n+m-1$.

Definition at line 395 of file Grid_chdims.cc.

References add_recycled_congruences(), add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Congruence_System::begin(), Parma_Polyhedra_Library::Congruence::coefficient(), congruences(), Parma_Polyhedra_Library::Congruence_System::end(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Congruence::inhomogeneous_term(), Parma_Polyhedra_Library::Congruence_System::insert_verbatim(), max_space_dimension(), Parma_Polyhedra_Library::Congruence::modulus(), OK(), space_dim, space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), and throw_space_dimension_overflow().

00395                                                               {
00396   // TODO: this implementation is _really_ an executable specification.
00397 
00398   // `var' must be one of the dimensions of the vector space.
00399   if (var.space_dimension() > space_dim)
00400     throw_dimension_incompatible("expand_space_dimension(v, m)", "v", var);
00401 
00402   // Adding 0 dimensions leaves the same grid.
00403   if (m == 0)
00404     return;
00405 
00406   // The resulting space dimension must be at most the maximum.
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   // Save the number of dimensions before adding new ones.
00413   dimension_type old_dim = space_dim;
00414 
00415   // Add the required new dimensions.
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     // Only consider congruences that constrain `var'.
00426     if (cg.coefficient(var) == 0)
00427       continue;
00428 
00429     // Each relevant congruence results in `m' new congruences.
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 }

PPL::memory_size_type Parma_Polyhedra_Library::Grid::external_memory_in_bytes (  )  const

Returns the size in bytes of the memory managed by *this.

Definition at line 2670 of file Grid_public.cc.

References con_sys, Parma_Polyhedra_Library::Grid_Generator_System::external_memory_in_bytes(), Parma_Polyhedra_Library::Congruence_System::external_memory_in_bytes(), and gen_sys.

Referenced by total_memory_in_bytes().

02670                                         {
02671   return
02672     con_sys.external_memory_in_bytes()
02673     + gen_sys.external_memory_in_bytes();
02674 }

void Parma_Polyhedra_Library::Grid::fold_space_dimensions ( const Variables_Set vars,
Variable  dest 
)

Folds the space dimensions in vars into dest.

Parameters:
vars The set of Variable objects corresponding to the space dimensions to be folded;
dest The variable corresponding to the space dimension that is the destination of the folding operation.
Exceptions:
std::invalid_argument Thrown if *this is dimension-incompatible with dest or with one of the Variable objects contained in vars. Also thrown if dest is contained in vars.

If *this has space dimension $n$, with $n > 0$, dest has space dimension $k \leq n$, vars is a set of variables whose maximum space dimension is also less than or equal to $n$, and dest is not a member of vars, then the space dimensions corresponding to variables in vars are folded into the $k$-th space dimension.

Definition at line 445 of file Grid_chdims.cc.

References affine_image(), grid_generators(), Parma_Polyhedra_Library::Variable::id(), marked_empty(), OK(), remove_space_dimensions(), space_dim, Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), throw_invalid_argument(), and upper_bound_assign().

00445                                                                        {
00446   // TODO: this implementation is _really_ an executable specification.
00447 
00448   // `dest' should be one of the dimensions of the grid.
00449   if (dest.space_dimension() > space_dim)
00450     throw_dimension_incompatible("fold_space_dimensions(vs, v)", "v", dest);
00451 
00452   // Folding only has effect if dimensions are given.
00453   if (vars.empty())
00454     return;
00455 
00456   // All variables in `vars' must be dimensions of the grid.
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   // Moreover, `dest.id()' must not occur in `vars'.
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   // All of the affine images we are going to compute are not invertible,
00467   // hence we will need to compute the grid generators of the polyhedron.
00468   // Since we keep taking copies, make sure that a single conversion
00469   // from congruences to grid generators is computed.
00470   (void) grid_generators();
00471   // Having grid generators, we now know if the grid is empty:
00472   // in that case, folding is equivalent to just removing space dimensions.
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 }

bool Parma_Polyhedra_Library::Grid::frequency ( const Linear_Expression expr,
Coefficient freq_n,
Coefficient freq_d,
Coefficient val_n,
Coefficient val_d 
) const

Returns true if and only if *this is not empty and frequency for *this with respect to expr is defined, in which case the frequency and the value for expr that is closest to zero are computed.

Parameters:
expr The linear expression for which the frequency is needed;
freq_n The numerator of the maximum frequency of expr;
freq_d The denominator of the maximum frequency of expr;
val_n The numerator of them value of expr at a point in the grid that is closest to zero;
val_d The denominator of a value of expr at a point in the grid that is closest to zero;
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

If *this is empty or frequency is undefined with respect to expr, then false is returned and freq_n, freq_d, val_n and val_d are left untouched.

Definition at line 2487 of file Grid_public.cc.

References frequency_no_check(), generators_are_minimized(), is_empty(), minimize(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and throw_dimension_incompatible().

02489                                                                    {
02490   // The dimension of `expr' must be at most the dimension of *this.
02491   if (space_dim < expr.space_dimension())
02492     throw_dimension_incompatible("frequency(e, ...)", "e", expr);
02493 
02494   // Space dimension = 0: if empty, then return false;
02495   // otherwise the frequency is 1 and the value is 0
02496   if (space_dim == 0) {
02497     if (is_empty())
02498       return false;
02499     freq_n = 0;
02500     freq_d = 1;
02501     val_n = 0;
02502     val_d = 1;
02503     return true;
02504   }
02505   if (!generators_are_minimized() && !minimize())
02506     // Minimizing found `this' empty.
02507     return false;
02508 
02509   return frequency_no_check(expr, freq_n, freq_d, val_n, val_d);
02510 }

bool Parma_Polyhedra_Library::Grid::frequency_no_check ( const Linear_Expression expr,
Coefficient freq_n,
Coefficient freq_d,
Coefficient val_n,
Coefficient val_d 
) const [private]

Returns true if and only if *this is not empty and frequency for *this with respect to expr is defined, in which case the frequency and the value for expr that is closest to zero are computed.

Parameters:
expr The linear expression for which the frequency is needed;
freq_n The numerator of the maximum frequency of expr;
freq_d The denominator of the maximum frequency of expr;
val_n The numerator of a value of expr at a point in the grid that is closest to zero;
val_d The denominator of a value of expr at a point in the grid that is closest to zero;

If *this is empty or frequency is undefined with respect to expr, then false is returned and freq_n, freq_d, val_n and val_d are left untouched.

Warning:
If expr and *this are dimension-incompatible, the grid generator system is not minimized or *this is empty, then the behavior is undefined.

Definition at line 315 of file Grid_nonpublic.cc.

References bounds_no_check(), Parma_Polyhedra_Library::Grid_Generator::divisor(), Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::gcd_assign(), gen_sys, generators_are_minimized(), Parma_Polyhedra_Library::Scalar_Products::homogeneous_assign(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Grid_Generator::is_line(), Parma_Polyhedra_Library::Grid_Generator::is_parameter(), Parma_Polyhedra_Library::Grid_Generator::is_point(), marked_empty(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), PPL_DIRTY_TEMP_COEFFICIENT, space_dim, and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

Referenced by frequency(), and wrap_assign().

00317                                                                    {
00318 
00319   // The dimension of `expr' must be at most the dimension of *this.
00320   PPL_ASSERT(space_dim >= expr.space_dimension());
00321   PPL_ASSERT(generators_are_minimized() && !marked_empty());
00322 
00323   // The generators are up to date and minimized and the grid is non-empty.
00324 
00325   // If the grid is bounded for the expression `expr',
00326   // then `expr' has a constant value and the frequency is 0.
00327   if (bounds_no_check(expr)) {
00328     freq_n = 0;
00329     freq_d = 1;
00330     // Find the value of the constant expression.
00331     const Grid_Generator& point = gen_sys[0];
00332     val_d = point.divisor();
00333     Scalar_Products::homogeneous_assign(val_n, expr, point);
00334     val_n += expr.inhomogeneous_term() * val_d;
00335     // Reduce `val_n' and `val_d'.
00336     PPL_DIRTY_TEMP_COEFFICIENT(gcd);
00337     gcd_assign(gcd, val_n, val_d);
00338     exact_div_assign(val_n, val_n, gcd);
00339     exact_div_assign(val_d, val_d, gcd);
00340     return true;
00341   }
00342 
00343   // The frequency is the gcd of the scalar products of the parameters
00344   // in `gen_sys'.
00345   dimension_type num_rows = gen_sys.num_rows();
00346   PPL_DIRTY_TEMP_COEFFICIENT(sp);
00347   freq_n = 0;
00348 
00349   // As the generators are minimized, `gen_sys[0]' is a point
00350   // and considered later.
00351   for (dimension_type row = 1; row < num_rows; ++row) {
00352     const Grid_Generator& gen = gen_sys[row];
00353     Scalar_Products::homogeneous_assign(sp, expr, gen);
00354     if (gen.is_line()) {
00355       if (sgn(sp) != 0)
00356           return false;
00357       continue;
00358     }
00359     // `gen' must be a parameter.
00360     PPL_ASSERT(gen.is_parameter());
00361     if (sgn(sp) != 0)
00362     gcd_assign(freq_n, freq_n, sp);
00363   }
00364   const Grid_Generator& point = gen_sys[0];
00365   PPL_ASSERT(point.is_point());
00366 
00367   // The denominator of the frequency and of the value is
00368   // the divisor for the generators.
00369   freq_d = point.divisor();
00370   val_d = freq_d;
00371 
00372   // As point is a grid generator, homogeneous_assign() must be used.
00373   Scalar_Products::homogeneous_assign(val_n, expr, point);
00374   val_n += expr.inhomogeneous_term() * val_d;
00375 
00376   // Reduce `val_n' by the frequency `freq_n'.
00377   val_n %= freq_n;
00378 
00379   PPL_DIRTY_TEMP_COEFFICIENT(gcd);
00380   // Reduce `freq_n' and `freq_d'.
00381   gcd_assign(gcd, freq_n, freq_d);
00382   exact_div_assign(freq_n, freq_n, gcd);
00383   exact_div_assign(freq_d, freq_d, gcd);
00384 
00385   // Reduce `val_n' and `val_d'.
00386   gcd_assign(gcd, val_n, val_d);
00387   exact_div_assign(val_n, val_n, gcd);
00388   exact_div_assign(val_d, val_d, gcd);
00389 
00390   return true;
00391 }

void Parma_Polyhedra_Library::Grid::generalized_affine_image ( const Linear_Expression lhs,
Relation_Symbol  relsym,
const Linear_Expression rhs,
Coefficient_traits::const_reference  modulus = Coefficient_zero() 
)

Assigns to *this the image of *this with respect to the generalized affine relation $\mathrm{lhs}' = \mathrm{rhs} \pmod{\mathrm{modulus}}$.

Parameters:
lhs The left hand side affine expression.
relsym The relation symbol where EQUAL is the symbol for a congruence relation;
rhs The right hand side affine expression.
modulus The modulus of the congruence lhs = rhs. A modulus of zero indicates lhs == rhs. Optional argument with an automatic value of zero.
Exceptions:
std::invalid_argument Thrown if *this is dimension-incompatible with lhs or rhs.

Definition at line 2086 of file Grid_public.cc.

References add_congruence_no_check(), add_grid_generator(), add_recycled_congruences(), add_recycled_grid_generators(), add_space_dimensions_and_embed(), clear_congruences_up_to_date(), clear_generators_minimized(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), is_empty(), marked_empty(), minimize(), Parma_Polyhedra_Library::neg_assign(), normalize_divisors(), OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Grid_Generator_System::recycling_insert(), remove_higher_space_dimensions(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), throw_invalid_argument(), and update_generators().

02089                                                                     {
02090   // Dimension-compatibility checks.
02091   // The dimension of `lhs' should be at most the dimension of
02092   // `*this'.
02093   dimension_type lhs_space_dim = lhs.space_dimension();
02094   if (space_dim < lhs_space_dim)
02095     throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
02096                                  "e1", lhs);
02097   // The dimension of `rhs' should be at most the dimension of
02098   // `*this'.
02099   const dimension_type rhs_space_dim = rhs.space_dimension();
02100   if (space_dim < rhs_space_dim)
02101     throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
02102                                  "e2", rhs);
02103 
02104   // Any image of an empty grid is empty.
02105   if (marked_empty())
02106     return;
02107 
02108   // If relsym is not EQUAL, then we return a safe approximation
02109   // by adding a line in the direction of var.
02110   if (relsym != EQUAL) {
02111 
02112     if (modulus != 0)
02113       throw_invalid_argument("generalized_affine_image(e1, r, e2, m)",
02114                              "r != EQUAL && m != 0");
02115 
02116     if (!generators_are_up_to_date())
02117       minimize();
02118 
02119     // Any image of an empty grid is empty.
02120     if (marked_empty())
02121       return;
02122 
02123     for (dimension_type i = space_dim; i-- > 0; )
02124       if (lhs.coefficient(Variable(i)) != 0)
02125         add_grid_generator(grid_line(Variable(i)));
02126 
02127     PPL_ASSERT(OK());
02128     return;
02129   }
02130 
02131   PPL_ASSERT(relsym == EQUAL);
02132 
02133   PPL_DIRTY_TEMP_COEFFICIENT(tmp_modulus);
02134   tmp_modulus = modulus;
02135   if (tmp_modulus < 0)
02136     neg_assign(tmp_modulus);
02137 
02138   // Compute the actual space dimension of `lhs',
02139   // i.e., the highest dimension having a non-zero coefficient in `lhs'.
02140   do {
02141     if (lhs_space_dim == 0) {
02142       // All variables have zero coefficients, so `lhs' is a constant.
02143       add_congruence_no_check((lhs %= rhs) / tmp_modulus);
02144       return;
02145     }
02146   }
02147   while (lhs.coefficient(Variable(--lhs_space_dim)) == 0);
02148 
02149   // Gather in `new_lines' the collections of all the lines having the
02150   // direction of variables occurring in `lhs'.  While at it, check
02151   // whether there exists a variable occurring in both `lhs' and
02152   // `rhs'.
02153   Grid_Generator_System new_lines;
02154   bool lhs_vars_intersect_rhs_vars = false;
02155   for (dimension_type i = lhs_space_dim + 1; i-- > 0; )
02156     if (lhs.coefficient(Variable(i)) != 0) {
02157       new_lines.insert(grid_line(Variable(i)));
02158       if (rhs.coefficient(Variable(i)) != 0)
02159         lhs_vars_intersect_rhs_vars = true;
02160     }
02161 
02162   if (lhs_vars_intersect_rhs_vars) {
02163     // Some variables in `lhs' also occur in `rhs'.
02164     // To ease the computation, add an additional dimension.
02165     const Variable new_var = Variable(space_dim);
02166     add_space_dimensions_and_embed(1);
02167 
02168     // Constrain the new dimension to be equal to the right hand side.
02169     // TODO: Use add_congruence() when it has been updated.
02170     Congruence_System new_cgs1(new_var == rhs);
02171     add_recycled_congruences(new_cgs1);
02172     if (!is_empty()) {
02173       // The grid still contains points.
02174 
02175       // Existentially quantify all the variables occurring in the left
02176       // hand side expression.
02177 
02178       // Adjust `new_lines' to the right dimension.
02179       new_lines.insert(parameter(0*Variable(space_dim-1)));
02180       // Add the lines to `gen_sys' (first make sure they are up-to-date).
02181       update_generators();
02182       gen_sys.recycling_insert(new_lines);
02183       normalize_divisors(gen_sys);
02184       // Update the flags.
02185       clear_congruences_up_to_date();
02186       clear_generators_minimized();
02187 
02188       // Constrain the new dimension so that it is congruent to the left
02189       // hand side expression modulo `modulus'.
02190       // TODO: Use add_congruence() when it has been updated.
02191       Congruence_System new_cgs2((lhs %= new_var) / tmp_modulus);
02192       add_recycled_congruences(new_cgs2);
02193     }
02194 
02195     // Remove the temporarily added dimension.
02196     remove_higher_space_dimensions(space_dim-1);
02197   }
02198   else {
02199     // `lhs' and `rhs' variables are disjoint:
02200     // there is no need to add a further dimension.
02201 
02202     // Only add the lines and congruence if there are points.
02203     if (is_empty())
02204       return;
02205 
02206     // Existentially quantify all the variables occurring in the left hand
02207     // side expression.
02208     add_recycled_grid_generators(new_lines);
02209 
02210     // Constrain the left hand side expression so that it is congruent to
02211     // the right hand side expression modulo `modulus'.
02212     add_congruence_no_check((lhs %= rhs) / tmp_modulus);
02213   }
02214 
02215   PPL_ASSERT(OK());
02216 }

void Parma_Polyhedra_Library::Grid::generalized_affine_image ( Variable  var,
Relation_Symbol  relsym,
const Linear_Expression expr,
Coefficient_traits::const_reference  denominator = Coefficient_one(),
Coefficient_traits::const_reference  modulus = Coefficient_zero() 
)

Assigns to *this the image of *this with respect to the generalized affine relation $\mathrm{var}' = \frac{\mathrm{expr}}{\mathrm{denominator}} \pmod{\mathrm{modulus}}$.

Parameters:
var The left hand side variable of the generalized affine relation;
relsym The relation symbol where EQUAL is the symbol for a congruence relation;
expr The numerator of the right hand side affine expression;
denominator The denominator of the right hand side affine expression. Optional argument with an automatic value of one;
modulus The modulus of the congruence lhs = rhs. A modulus of zero indicates lhs == rhs. Optional argument with an automatic value of zero.
Exceptions:
std::invalid_argument Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of this.

Definition at line 1912 of file Grid_public.cc.

References add_grid_generator(), affine_image(), clear_congruences_up_to_date(), clear_generators_minimized(), Parma_Polyhedra_Library::EQUAL, gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), marked_empty(), minimize(), normalize_divisors(), OK(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().

Referenced by bounded_affine_image(), and generalized_affine_preimage().

01916                                                                     {
01917 
01918   // The denominator cannot be zero.
01919   if (denominator == 0)
01920     throw_invalid_argument("generalized_affine_image(v, r, e, d, m)",
01921                            "d == 0");
01922 
01923   // Dimension-compatibility checks.
01924   // The dimension of `expr' should not be greater than the dimension
01925   // of `*this'.
01926   const dimension_type expr_space_dim = expr.space_dimension();
01927   if (space_dim < expr_space_dim)
01928     throw_dimension_incompatible("generalized_affine_image(v, r, e, d, m)",
01929                                  "e", expr);
01930   // `var' should be one of the dimensions of the grid.
01931   const dimension_type var_space_dim = var.space_dimension();
01932   if (space_dim < var_space_dim)
01933     throw_dimension_incompatible("generalized_affine_image(v, r, e, d, m)",
01934                                  "v", var);
01935 
01936   // Any image of an empty grid is empty.
01937   if (marked_empty())
01938     return;
01939 
01940   // If relsym is not EQUAL, then we return a safe approximation
01941   // by adding a line in the direction of var.
01942   if (relsym != EQUAL) {
01943 
01944     if (modulus != 0)
01945       throw_invalid_argument("generalized_affine_image(v, r, e, d, m)",
01946                              "r != EQUAL && m != 0");
01947 
01948     if (!generators_are_up_to_date())
01949       minimize();
01950 
01951     // Any image of an empty grid is empty.
01952     if (marked_empty())
01953       return;
01954 
01955     add_grid_generator(grid_line(var));
01956 
01957     PPL_ASSERT(OK());
01958     return;
01959   }
01960 
01961   PPL_ASSERT(relsym == EQUAL);
01962 
01963   affine_image(var, expr, denominator);
01964 
01965   if (modulus == 0)
01966     return;
01967 
01968   // Modulate dimension `var' according to `modulus'.
01969 
01970   if (!generators_are_up_to_date())
01971     minimize();
01972 
01973   // Test if minimization, possibly in affine_image, found an empty
01974   // grid.
01975   if (marked_empty())
01976     return;
01977 
01978   if (modulus < 0)
01979     gen_sys.insert(parameter(-modulus * var));
01980   else
01981     gen_sys.insert(parameter(modulus * var));
01982 
01983   normalize_divisors(gen_sys);
01984 
01985   clear_generators_minimized();
01986   clear_congruences_up_to_date();
01987 
01988   PPL_ASSERT(OK());
01989 }

void Parma_Polyhedra_Library::Grid::generalized_affine_preimage ( const Linear_Expression lhs,
Relation_Symbol  relsym,
const Linear_Expression rhs,
Coefficient_traits::const_reference  modulus = Coefficient_zero() 
)

Assigns to *this the preimage of *this with respect to the generalized affine relation $\mathrm{lhs}' = \mathrm{rhs} \pmod{\mathrm{modulus}}$.

Parameters:
lhs The left hand side affine expression;
relsym The relation symbol where EQUAL is the symbol for a congruence relation;
rhs The right hand side affine expression;
modulus The modulus of the congruence lhs = rhs. A modulus of zero indicates lhs == rhs. Optional argument with an automatic value of zero.
Exceptions:
std::invalid_argument Thrown if *this is dimension-incompatible with lhs or rhs.

Definition at line 2220 of file Grid_public.cc.

References add_congruence_no_check(), add_grid_generator(), add_recycled_congruences(), add_recycled_grid_generators(), add_space_dimensions_and_embed(), clear_congruences_up_to_date(), clear_generators_minimized(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), is_empty(), marked_empty(), minimize(), Parma_Polyhedra_Library::neg_assign(), normalize_divisors(), OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Grid_Generator_System::recycling_insert(), remove_higher_space_dimensions(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), throw_invalid_argument(), and update_generators().

02223                                                                        {
02224 
02225   // The dimension of `lhs' must be at most the dimension of `*this'.
02226   dimension_type lhs_space_dim = lhs.space_dimension();
02227   if (space_dim < lhs_space_dim)
02228     throw_dimension_incompatible("generalized_affine_preimage(e1, e2, m)",
02229                                  "lhs", lhs);
02230   // The dimension of `rhs' must be at most the dimension of `*this'.
02231   const dimension_type rhs_space_dim = rhs.space_dimension();
02232   if (space_dim < rhs_space_dim)
02233     throw_dimension_incompatible("generalized_affine_preimage(e1, e2, m)",
02234                                  "e2", rhs);
02235 
02236   // Any preimage of an empty grid is empty.
02237   if (marked_empty())
02238     return;
02239 
02240   // If relsym is not EQUAL, then we return a safe approximation
02241   // by adding a line in the direction of var.
02242   if (relsym != EQUAL) {
02243 
02244     if (modulus != 0)
02245       throw_invalid_argument("generalized_affine_preimage(e1, r, e2, m)",
02246                              "r != EQUAL && m != 0");
02247 
02248     if (!generators_are_up_to_date())
02249       minimize();
02250 
02251     // Any image of an empty grid is empty.
02252     if (marked_empty())
02253       return;
02254 
02255     for (dimension_type i = lhs_space_dim + 1; i-- > 0; )
02256       if (lhs.coefficient(Variable(i)) != 0)
02257         add_grid_generator(grid_line(Variable(i)));
02258 
02259     PPL_ASSERT(OK());
02260     return;
02261   }
02262 
02263   PPL_ASSERT(relsym == EQUAL);
02264 
02265   PPL_DIRTY_TEMP_COEFFICIENT(tmp_modulus);
02266   tmp_modulus = modulus;
02267   if (tmp_modulus < 0)
02268     neg_assign(tmp_modulus);
02269 
02270   // Compute the actual space dimension of `lhs',
02271   // i.e., the highest dimension having a non-zero coefficient in `lhs'.
02272   do {
02273     if (lhs_space_dim == 0) {
02274       // All variables have zero coefficients, so `lhs' is a constant.
02275       // In this case, preimage and image happen to be the same.
02276       add_congruence_no_check((lhs %= rhs) / tmp_modulus);
02277       return;
02278     }
02279   }
02280   while (lhs.coefficient(Variable(--lhs_space_dim)) == 0);
02281 
02282   // Gather in `new_lines' the collections of all the lines having
02283   // the direction of variables occurring in `lhs'.
02284   // While at it, check whether or not there exists a variable
02285   // occurring in both `lhs' and `rhs'.
02286   Grid_Generator_System new_lines;
02287   bool lhs_vars_intersect_rhs_vars = false;
02288   for (dimension_type i = lhs_space_dim + 1; i-- > 0; )
02289     if (lhs.coefficient(Variable(i)) != 0) {
02290       new_lines.insert(grid_line(Variable(i)));
02291       if (rhs.coefficient(Variable(i)) != 0)
02292         lhs_vars_intersect_rhs_vars = true;
02293     }
02294 
02295   if (lhs_vars_intersect_rhs_vars) {
02296     // Some variables in `lhs' also occur in `rhs'.
02297     // To ease the computation, add an additional dimension.
02298     const Variable new_var = Variable(space_dim);
02299     add_space_dimensions_and_embed(1);
02300 
02301     // Constrain the new dimension to be equal to `lhs'
02302     // TODO: Use add_congruence() when it has been updated.
02303     Congruence_System new_cgs1(new_var == lhs);
02304     add_recycled_congruences(new_cgs1);
02305     if (!is_empty()) {
02306       // The grid still contains points.
02307 
02308       // Existentially quantify all the variables occurring in the left
02309       // hand side
02310 
02311       // Adjust `new_lines' to the right dimension.
02312       new_lines.insert(parameter(0*Variable(space_dim-1)));
02313       // Add the lines to `gen_sys' (first make sure they are up-to-date).
02314       update_generators();
02315       gen_sys.recycling_insert(new_lines);
02316       normalize_divisors(gen_sys);
02317       // Update the flags.
02318       clear_congruences_up_to_date();
02319       clear_generators_minimized();
02320 
02321       // Constrain the new dimension so that it is related to
02322       // the right hand side modulo `modulus'.
02323       // TODO: Use add_congruence() when it has been updated.
02324       Congruence_System new_cgs2((rhs %= new_var) / tmp_modulus);
02325       add_recycled_congruences(new_cgs2);
02326     }
02327 
02328     // Remove the temporarily added dimension.
02329     remove_higher_space_dimensions(space_dim-1);
02330   }
02331   else {
02332     // `lhs' and `rhs' variables are disjoint:
02333     // there is no need to add a further dimension.
02334 
02335     // Constrain the left hand side expression so that it is congruent to
02336     // the right hand side expression modulo `mod'.
02337     add_congruence_no_check((lhs %= rhs) / tmp_modulus);
02338 
02339     // Any image of an empty grid is empty.
02340     if (is_empty())
02341       return;
02342 
02343     // Existentially quantify all the variables occurring in `lhs'.
02344     add_recycled_grid_generators(new_lines);
02345   }
02346   PPL_ASSERT(OK());
02347 }

void Parma_Polyhedra_Library::Grid::generalized_affine_preimage ( Variable  var,
Relation_Symbol  relsym,
const Linear_Expression expr,
Coefficient_traits::const_reference  denominator = Coefficient_one(),
Coefficient_traits::const_reference  modulus = Coefficient_zero() 
)

Assigns to *this the preimage of *this with respect to the generalized affine relation $\mathrm{var}' = \frac{\mathrm{expr}}{\mathrm{denominator}} \pmod{\mathrm{modulus}}$.

Parameters:
var The left hand side variable of the generalized affine relation;
relsym The relation symbol where EQUAL is the symbol for a congruence relation;
expr The numerator of the right hand side affine expression;
denominator The denominator of the right hand side affine expression. Optional argument with an automatic value of one;
modulus The modulus of the congruence lhs = rhs. A modulus of zero indicates lhs == rhs. Optional argument with an automatic value of zero.
Exceptions:
std::invalid_argument Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of this.

Definition at line 1993 of file Grid_public.cc.

References add_congruence_no_check(), add_grid_generator(), affine_preimage(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, generalized_affine_image(), generators_are_up_to_date(), is_empty(), marked_empty(), minimize(), Parma_Polyhedra_Library::neg_assign(), OK(), PPL_DIRTY_TEMP_COEFFICIENT, space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().

Referenced by bounded_affine_preimage().

01997                                                                        {
01998   // The denominator cannot be zero.
01999   if (denominator == 0)
02000     throw_invalid_argument("generalized_affine_preimage(v, e, d, m)",
02001                            "d == 0");
02002 
02003   // The dimension of `expr' should be at most the dimension of
02004   // `*this'.
02005   const dimension_type expr_space_dim = expr.space_dimension();
02006   if (space_dim < expr_space_dim)
02007     throw_dimension_incompatible("generalized_affine_preimage(v, e, d, m)",
02008                                  "e", expr);
02009   // `var' should be one of the dimensions of the grid.
02010   const dimension_type var_space_dim = var.space_dimension();
02011   if (space_dim < var_space_dim)
02012     throw_dimension_incompatible("generalized_affine_preimage(v, e, d, m)",
02013                                  "v", var);
02014 
02015   // If relsym is not EQUAL, then we return a safe approximation
02016   // by adding a line in the direction of var.
02017   if (relsym != EQUAL) {
02018 
02019     if (modulus != 0)
02020       throw_invalid_argument("generalized_affine_preimage(v, r, e, d, m)",
02021                              "r != EQUAL && m != 0");
02022 
02023     if (!generators_are_up_to_date())
02024       minimize();
02025 
02026     // Any image of an empty grid is empty.
02027     if (marked_empty())
02028       return;
02029 
02030     add_grid_generator(grid_line(var));
02031 
02032     PPL_ASSERT(OK());
02033     return;
02034   }
02035 
02036   PPL_ASSERT(relsym == EQUAL);
02037   // Any image of an empty grid is empty.
02038   if (marked_empty())
02039     return;
02040 
02041   // Check whether the affine relation is an affine function.
02042   if (modulus == 0) {
02043     affine_preimage(var, expr, denominator);
02044     return;
02045   }
02046 
02047   // Check whether the preimage of this affine relation can be easily
02048   // computed as the image of its inverse relation.
02049   const Coefficient& var_coefficient = expr.coefficient(var);
02050   if (var_space_dim <= expr_space_dim && var_coefficient != 0) {
02051     Linear_Expression inverse_expr
02052       = expr - (denominator + var_coefficient) * var;
02053     PPL_DIRTY_TEMP_COEFFICIENT(inverse_denominator);
02054     neg_assign(inverse_denominator, var_coefficient);
02055     if (modulus < 0)
02056       generalized_affine_image(var, EQUAL, inverse_expr, inverse_denominator,
02057                                - modulus);
02058     else
02059       generalized_affine_image(var, EQUAL, inverse_expr, inverse_denominator,
02060                                modulus);
02061     return;
02062   }
02063 
02064   // Here `var_coefficient == 0', so that the preimage cannot be
02065   // easily computed by inverting the affine relation.  Add the
02066   // congruence induced by the affine relation.
02067   {
02068     Congruence cg((denominator*var %= expr) / denominator);
02069     if (modulus < 0)
02070       cg /= -modulus;
02071     else
02072       cg /= modulus;
02073     add_congruence_no_check(cg);
02074   }
02075 
02076   // If the resulting grid is empty, its preimage is empty too.
02077   // Note: DO check for emptiness here, as we will later add a line.
02078   if (is_empty())
02079     return;
02080   add_grid_generator(grid_line(var));
02081   PPL_ASSERT(OK());
02082 }

void Parma_Polyhedra_Library::Grid::generator_widening_assign ( const Grid y,
unsigned *  tp = NULL 
)

Assigns to *this the result of computing the Grid widening between *this and y using generator systems.

Parameters:
y A grid that must be contained in *this;
tp An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique).
Exceptions:
std::invalid_argument Thrown if *this and y are dimension-incompatible.

Definition at line 278 of file Grid_widenings.cc.

References add_recycled_grid_generators(), contains(), dim_kinds, Parma_Polyhedra_Library::EMPTY, gen_sys, generators_are_minimized(), generators_are_up_to_date(), Parma_Polyhedra_Library::Matrix::has_no_rows(), marked_empty(), Parma_Polyhedra_Library::Grid_Generator_System::num_lines(), Parma_Polyhedra_Library::Grid_Generator_System::num_parameters(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), OK(), select_wider_generators(), set_generators_minimized(), simplify(), space_dim, swap(), throw_dimension_incompatible(), and update_generators().

Referenced by limited_generator_extrapolation_assign(), and widening_assign().

00278                                                                     {
00279   Grid& x = *this;
00280   Grid& y = const_cast<Grid&>(const_y);
00281   // Dimension-compatibility check.
00282   if (x.space_dim != y.space_dim)
00283     throw_dimension_incompatible("generator_widening_assign(y)", "y", y);
00284 
00285   // Stable behavior is only guaranteed if y is contained in or equal
00286   // to x.
00287 #ifndef NDEBUG
00288   {
00289     // Assume y is contained in or equal to x.
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   // Leave `x' the same if `x' or `y' is zero-dimensional or empty.
00297   if (x.space_dim == 0 || x.marked_empty() || y.marked_empty())
00298     return;
00299 
00300   // Ensure that the `x' generators are in minimal form.
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   // Ensure that the `y' generators are in minimal form.
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   // Copy into `ggs' the generators of `x' that are common to `y',
00332   // according to the grid widening.
00333   Grid_Generator_System ggs;
00334   x.select_wider_generators(y, ggs);
00335 
00336   if (ggs.num_parameters() == gen_sys.num_parameters())
00337     // All parameters are kept as parameters, thus the result is `x'.
00338     return;
00339 
00340   // A strict subset of the parameters was selected.
00341 
00342   Grid result(x.space_dim, EMPTY);
00343   result.add_recycled_grid_generators(ggs);
00344 
00345   // Check whether we are using the widening-with-tokens technique
00346   // and there are still tokens available.
00347   if (tp && *tp > 0) {
00348     // There are tokens available.  If `result' is not a subset of
00349     // `x', then it is less precise and we use one of the available
00350     // tokens.
00351     if (!x.contains(result))
00352       --(*tp);
00353   }
00354   else
00355     // No tokens.
00356     std::swap(x, result);
00357 
00358   PPL_ASSERT(x.OK(true));
00359 }

bool Parma_Polyhedra_Library::Grid::generators_are_minimized (  )  const [inline, private]
bool Parma_Polyhedra_Library::Grid::generators_are_up_to_date (  )  const [inline, private]
const PPL::Grid_Generator_System & Parma_Polyhedra_Library::Grid::grid_generators (  )  const

Returns the system of generators.

Definition at line 309 of file Grid_public.cc.

References gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Matrix::has_no_rows(), marked_empty(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), space_dim, Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), and update_generators().

Referenced by fold_space_dimensions(), and map_space_dimensions().

00309                                {
00310   if (space_dim == 0) {
00311     PPL_ASSERT(gen_sys.space_dimension() == 0
00312            && gen_sys.num_rows() == (marked_empty() ? 0 : 1));
00313     return gen_sys;
00314   }
00315 
00316   if (marked_empty()) {
00317     PPL_ASSERT(gen_sys.has_no_rows());
00318     return gen_sys;
00319   }
00320 
00321   if (!generators_are_up_to_date() && !update_generators()) {
00322     // Updating found the grid empty.
00323     const_cast<Grid&>(*this).set_empty();
00324     return gen_sys;
00325   }
00326 
00327   return gen_sys;
00328 }

int32_t Parma_Polyhedra_Library::Grid::hash_code (  )  const [inline]

Returns a 32-bit hash code for *this.

If x and y are such that x == y, then x.hash_code() == y.hash_code().

Definition at line 230 of file Grid.inlines.hh.

References space_dimension().

00230                       {
00231   return space_dimension() & 0x7fffffff;
00232 }

void Parma_Polyhedra_Library::Grid::intersection_assign ( const Grid y  ) 

Assigns to *this the intersection of *this and y.

Exceptions:
std::invalid_argument Thrown if *this and y are dimension-incompatible.

Definition at line 1372 of file Grid_public.cc.

References clear_congruences_minimized(), clear_generators_up_to_date(), con_sys, congruences_are_up_to_date(), Parma_Polyhedra_Library::Matrix::has_no_rows(), Parma_Polyhedra_Library::Congruence_System::insert(), marked_empty(), OK(), set_empty(), space_dim, throw_dimension_incompatible(), and update_congruences().

Referenced by is_disjoint_from().

01372                                           {
01373   Grid& x = *this;
01374   // Dimension-compatibility check.
01375   if (x.space_dim != y.space_dim)
01376     throw_dimension_incompatible("intersection_assign(y)", "y", y);
01377 
01378   // If one of the two grids is empty, the intersection is empty.
01379   if (x.marked_empty())
01380     return;
01381   if (y.marked_empty()) {
01382     x.set_empty();
01383     return;
01384   }
01385 
01386   // If both grids are zero-dimensional, then at this point they are
01387   // necessarily universe, so the intersection is also universe.
01388   if (x.space_dim == 0)
01389     return;
01390 
01391   // The congruences must be up-to-date.
01392   if (!x.congruences_are_up_to_date())
01393     x.update_congruences();
01394   if (!y.congruences_are_up_to_date())
01395     y.update_congruences();
01396 
01397   if (!y.con_sys.has_no_rows()) {
01398     x.con_sys.insert(y.con_sys);
01399     // Grid_Generators may be out of date and congruences may have changed
01400     // from minimal form.
01401     x.clear_generators_up_to_date();
01402     x.clear_congruences_minimized();
01403   }
01404 
01405   PPL_ASSERT(x.OK() && y.OK());
01406 }

bool Parma_Polyhedra_Library::Grid::is_bounded (  )  const

Returns true if and only if *this is bounded.

Definition at line 731 of file Grid_public.cc.

References gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Grid_Generator::is_line_or_parameter(), marked_empty(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), space_dim, and update_generators().

00731                           {
00732   // A zero-dimensional or empty grid is bounded.
00733   if (space_dim == 0
00734       || marked_empty()
00735       || (!generators_are_up_to_date() && !update_generators()))
00736     return true;
00737 
00738   // TODO: Consider using con_sys when gen_sys is out of date.
00739 
00740   if (gen_sys.num_rows() > 1) {
00741     // Check if all generators are the same point.
00742     const Grid_Generator& first_point = gen_sys[0];
00743     if (first_point.is_line_or_parameter())
00744       return false;
00745     for (dimension_type row = gen_sys.num_rows(); row-- > 0; ) {
00746       const Grid_Generator& gen = gen_sys[row];
00747       if (gen.is_line_or_parameter() || gen != first_point)
00748         return false;
00749     }
00750   }
00751   return true;
00752 }

bool Parma_Polyhedra_Library::Grid::is_discrete (  )  const

Returns true if and only if *this is discrete.

A grid is discrete if it can be defined by a generator system which contains only points and parameters. This includes the empty grid and any grid in dimension zero.

Definition at line 755 of file Grid_public.cc.

References gen_sys, generators_are_up_to_date(), marked_empty(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), space_dim, and update_generators().

00755                            {
00756   // A zero-dimensional or empty grid is discrete.
00757   if (space_dim == 0
00758       || marked_empty()
00759       || (!generators_are_up_to_date() && !update_generators()))
00760     return true;
00761 
00762   // Search for lines in the generator system.
00763   for (dimension_type row = gen_sys.num_rows(); row-- > 1; )
00764     if (gen_sys[row].is_line())
00765       return false;
00766 
00767   // The system of generators is composed only by
00768   // points and parameters: the grid is discrete.
00769   return true;
00770 }

bool Parma_Polyhedra_Library::Grid::is_disjoint_from ( const Grid y  )  const

Returns true if and only if *this and y are disjoint.

Exceptions:
std::invalid_argument Thrown if x and y are dimension-incompatible.

Definition at line 2562 of file Grid_public.cc.

References intersection_assign(), is_empty(), space_dim, and throw_dimension_incompatible().

Referenced by Parma_Polyhedra_Library::Pointset_Powerset< PSET >::check_containment().

02562                                              {
02563   // Dimension-compatibility check.
02564   if (space_dim != y.space_dim)
02565     throw_dimension_incompatible("is_disjoint_from(y)", "y", y);
02566   Grid z = *this;
02567   z.intersection_assign(y);
02568   return z.is_empty();
02569 }

bool Parma_Polyhedra_Library::Grid::is_empty (  )  const

Returns true if and only if *this is an empty grid.

Definition at line 678 of file Grid_public.cc.

References con_sys, congruences_are_minimized(), dim_kinds, generators_are_up_to_date(), marked_empty(), set_congruences_minimized(), set_empty(), simplify(), and space_dim.

Referenced by affine_dimension(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::approximate_partition_aux(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::check_containment(), contains(), contains_integer_point(), frequency(), generalized_affine_image(), generalized_affine_preimage(), is_disjoint_from(), operator<<(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::Pointset_Powerset(), remove_higher_space_dimensions(), and simplify_using_context_assign().

00678                         {
00679   if (marked_empty())
00680     return true;
00681   // Try a fast-fail test: if generators are up-to-date then the
00682   // generator system (since it is well formed) contains a point.
00683   if (generators_are_up_to_date())
00684     return false;
00685   if (space_dim == 0)
00686     return false;
00687   if (congruences_are_minimized())
00688     // If the grid was empty it would be marked empty.
00689     return false;
00690   // Minimize the congruences to check if the grid is empty.
00691   Grid& gr = const_cast<Grid&>(*this);
00692   if (gr.simplify(gr.con_sys, gr.dim_kinds)) {
00693     gr.set_empty();
00694     return true;
00695   }
00696   gr.set_congruences_minimized();
00697   return false;
00698 }

bool Parma_Polyhedra_Library::Grid::is_included_in ( const Grid y  )  const [private]

Returns true if and only if *this is included in y.

Definition at line 238 of file Grid_nonpublic.cc.

References con_sys, congruences_are_minimized(), congruences_are_up_to_date(), marked_empty(), minimize(), OK(), Parma_Polyhedra_Library::Congruence_System::satisfies_all_congruences(), space_dim, and update_congruences().

Referenced by contains(), simplify_using_context_assign(), and upper_bound_assign_if_exact().

00238                                            {
00239   // Private method: the caller must ensure the following.
00240   PPL_ASSERT(space_dim == y.space_dim);
00241   PPL_ASSERT(!marked_empty() && !y.marked_empty() && space_dim > 0);
00242 
00243   const Grid& x = *this;
00244 
00245 #if BE_LAZY
00246   if (!x.generators_are_up_to_date() && !x.update_generators())
00247     // Updating found `x' empty.
00248     return true;
00249   if (!y.congruences_are_up_to_date())
00250     y.update_congruences();
00251 #else
00252   if (!x.generators_are_minimized() && !x.minimize())
00253     // Minimizing found `x' empty.
00254     return true;
00255   if (!y.congruences_are_minimized())
00256     y.minimize();
00257 #endif
00258 
00259   PPL_ASSERT(x.OK());
00260   PPL_ASSERT(y.OK());
00261 
00262   const Grid_Generator_System& gs = x.gen_sys;
00263   const Congruence_System& cgs = y.con_sys;
00264 
00265   dimension_type num_rows = gs.num_rows();
00266   for (dimension_type i = num_rows; i-- > 0; )
00267     if (!cgs.satisfies_all_congruences(gs[i]))
00268       return false;
00269 
00270   // Inclusion holds.
00271   return true;
00272 }

bool Parma_Polyhedra_Library::Grid::is_topologically_closed (  )  const

Returns true if and only if *this is a topologically closed subset of the vector space.

A grid is always topologically closed.

Definition at line 773 of file Grid_public.cc.

00773                                        {
00774   return true;
00775 }

bool Parma_Polyhedra_Library::Grid::is_universe (  )  const

Returns true if and only if *this is a universe grid.

Definition at line 701 of file Grid_public.cc.

References con_sys, congruences_are_minimized(), congruences_are_up_to_date(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Congruence_System::satisfies_all_congruences(), space_dim, and update_congruences().

Referenced by operator<<().

00701                            {
00702   if (marked_empty())
00703     return false;
00704 
00705   if (space_dim == 0)
00706     return true;
00707 
00708   if (congruences_are_up_to_date()) {
00709     if (congruences_are_minimized())
00710       // The minimized universe congruence system has only one row,
00711       // the integrality congruence.
00712       return con_sys.num_rows() == 1 && con_sys[0].is_tautological();
00713   }
00714   else {
00715     update_congruences();
00716     return con_sys.num_rows() == 1 && con_sys[0].is_tautological();
00717   }
00718 
00719   // Test con_sys's inclusion in a universe generator system.
00720 
00721   // The zero dimension cases are handled above.
00722   Variable var(space_dim - 1);
00723   for (dimension_type i = space_dim; i-- > 0; )
00724     if (!con_sys.satisfies_all_congruences(grid_line(Variable(i) + var)))
00725       return false;
00726   PPL_ASSERT(con_sys.satisfies_all_congruences(grid_point(0*var)));
00727   return true;
00728 }

void Parma_Polyhedra_Library::Grid::limited_congruence_extrapolation_assign ( const Grid y,
const Congruence_System cgs,
unsigned *  tp = NULL 
)

Improves the result of the congruence variant of Grid widening computation by also enforcing those congruences in cgs that are satisfied by all the points of *this.

Parameters:
y A grid that must be contained in *this;
cgs The system of congruences used to improve the widened grid;
tp An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique).
Exceptions:
std::invalid_argument Thrown if *this, y and cgs are dimension-incompatible.

Definition at line 160 of file Grid_widenings.cc.

References add_recycled_congruences(), congruence_widening_assign(), contains(), generators_are_up_to_date(), Parma_Polyhedra_Library::Congruence_System::insert(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), relation_with(), space_dim, Parma_Polyhedra_Library::Congruence_System::space_dimension(), throw_dimension_incompatible(), update_generators(), and widening_assign().

00162                                                                  {
00163   Grid& x = *this;
00164 
00165   // Check dimension compatibility.
00166   if (x.space_dim != y.space_dim)
00167     throw_dimension_incompatible("limited_extrapolation_assign(y, cgs)",
00168                                  "y", y);
00169   // `cgs' must be dimension-compatible with the two grids.
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   // If `cgs' is empty (of rows), fall back to ordinary widening.
00177   if (cgs_num_rows == 0) {
00178     x.widening_assign(y, tp);
00179     return;
00180   }
00181 
00182 #ifndef NDEBUG
00183   {
00184     // Assume that y is contained in or equal to x.
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   // The limited widening between two grids in a zero-dimensional
00197   // space is also a grid in a zero-dimensional space.
00198   if (x.space_dim == 0)
00199     return;
00200 
00201   // Update the generators of `x': these are used to select, from the
00202   // congruences in `cgs', those that must be added to the widened
00203   // grid.
00204   if (!x.generators_are_up_to_date() && !x.update_generators())
00205     // `x' is empty.
00206     return;
00207 
00208   if (tp == NULL || *tp == 0) {
00209     // Widening may change the grid, so add the congruences.
00210     Congruence_System new_cgs;
00211     // The congruences to be added need only be satisfied by all the
00212     // generators of `x', as `y <= x'.  Iterate upwards here, to keep
00213     // the relative ordering of congruences (just for aesthetics).
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     // There are tokens, so widening will leave the grid the same.
00224     x.congruence_widening_assign(y, tp);
00225 
00226   PPL_ASSERT(OK());
00227 }

void Parma_Polyhedra_Library::Grid::limited_extrapolation_assign ( const Grid y,
const Congruence_System cgs,
unsigned *  tp = NULL 
)

Improves the result of the Grid widening computation by also enforcing those congruences in cgs that are satisfied by all the points of *this.

Parameters:
y A grid that must be contained in *this;
cgs The system of congruences used to improve the widened grid;
tp An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique).
Exceptions:
std::invalid_argument Thrown if *this, y and cgs are dimension-incompatible.

Definition at line 468 of file Grid_widenings.cc.

References add_recycled_congruences(), contains(), generators_are_up_to_date(), Parma_Polyhedra_Library::Congruence_System::insert(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), relation_with(), space_dim, Parma_Polyhedra_Library::Congruence_System::space_dimension(), throw_dimension_incompatible(), update_generators(), and widening_assign().

00470                                                       {
00471   Grid& x = *this;
00472 
00473   // Check dimension compatibility.
00474   if (x.space_dim != y.space_dim)
00475     throw_dimension_incompatible("limited_extrapolation_assign(y, cgs)",
00476                                  "y", y);
00477   // `cgs' must be dimension-compatible with the two grids.
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   // If `cgs' is empty (of rows), fall back to ordinary widening.
00485   if (cgs_num_rows == 0) {
00486     x.widening_assign(y, tp);
00487     return;
00488   }
00489 
00490 #ifndef NDEBUG
00491   {
00492     // Assume that y is contained in or equal to x.
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   // The limited widening between two grids in a zero-dimensional
00505   // space is also a grid in a zero-dimensional space.
00506   if (x.space_dim == 0)
00507     return;
00508 
00509   // Update the generators of `x': these are used to select, from the
00510   // congruences in `cgs', those that must be added to the widened
00511   // grid.
00512   if (!x.generators_are_up_to_date() && !x.update_generators())
00513     // `x' is empty.
00514     return;
00515 
00516   if (tp == NULL || *tp == 0) {
00517     // Widening may change the grid, so add the congruences.
00518     Congruence_System new_cgs;
00519     // The congruences to be added need only be satisfied by all the
00520     // generators of `x', as `y <= x'.  Iterate upwards here, to keep
00521     // the relative ordering of congruences (just for aesthetics).
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     // There are tokens, so widening will leave the grid the same.
00532     x.widening_assign(y, tp);
00533 
00534   PPL_ASSERT(OK());
00535 }

void Parma_Polyhedra_Library::Grid::limited_generator_extrapolation_assign ( const Grid y,
const Congruence_System cgs,
unsigned *  tp = NULL 
)

Improves the result of the generator variant of the Grid widening computation by also enforcing those congruences in cgs that are satisfied by all the points of *this.

Parameters:
y A grid that must be contained in *this;
cgs The system of congruences used to improve the widened grid;
tp An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique).
Exceptions:
std::invalid_argument Thrown if *this, y and cgs are dimension-incompatible.

Definition at line 362 of file Grid_widenings.cc.

References add_recycled_congruences(), contains(), generator_widening_assign(), generators_are_up_to_date(), Parma_Polyhedra_Library::Congruence_System::insert(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), relation_with(), space_dim, Parma_Polyhedra_Library::Congruence_System::space_dimension(), throw_dimension_incompatible(), and update_generators().

00364                                                                 {
00365   Grid& x = *this;
00366 
00367   // Check dimension compatibility.
00368   if (x.space_dim != y.space_dim)
00369     throw_dimension_incompatible("limited_extrapolation_assign(y, cgs)",
00370                                  "y", y);
00371   // `cgs' must be dimension-compatible with the two grids.
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   // If `cgs' is empty (of rows), fall back to ordinary widening.
00379   if (cgs_num_rows == 0) {
00380     x.generator_widening_assign(y, tp);
00381     return;
00382   }
00383 
00384 #ifndef NDEBUG
00385   {
00386     // Assume that y is contained in or equal to x.
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   // The limited widening between two grids in a zero-dimensional
00399   // space is also a grid in a zero-dimensional space.
00400   if (x.space_dim == 0)
00401     return;
00402 
00403   // Update the generators of `x': these are used to select, from the
00404   // congruences in `cgs', those that must be added to the widened
00405   // grid.
00406   if (!x.generators_are_up_to_date() && !x.update_generators())
00407     // `x' is empty.
00408     return;
00409 
00410   if (tp == NULL || *tp == 0) {
00411     // Widening may change the grid, so add the congruences.
00412     Congruence_System new_cgs;
00413     // The congruences to be added need only be satisfied by all the
00414     // generators of `x', as `y <= x'.  Iterate upwards here, to keep
00415     // the relative ordering of congruences (just for aesthetics).
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     // There are tokens, so widening will leave the grid the same.
00426     x.generator_widening_assign(y, tp);
00427 
00428   PPL_ASSERT(OK());
00429 }

bool Parma_Polyhedra_Library::Grid::lower_triangular ( const Congruence_System sys,
const Dimension_Kinds dim_kinds 
) [static, private]

If sys is lower triangular return true, else return false.

Definition at line 38 of file Grid_conversion.cc.

References CON_VIRTUAL, Parma_Polyhedra_Library::Matrix::num_columns(), and Parma_Polyhedra_Library::Matrix::num_rows().

Referenced by conversion(), and OK().

00039                                                          {
00040   const dimension_type num_columns = sys.num_columns() - 1;
00041 
00042   // Check for easy square failure case.
00043   if (sys.num_rows() > num_columns)
00044     return false;
00045 
00046   // Check triangularity.
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     // Check diagonal.
00055     if (cg[dim] <= 0)
00056       return false;
00057     // Check elements following diagonal.
00058     dimension_type col = dim;
00059     while (++col < num_columns)
00060       if (cg[col] != 0)
00061         return false;
00062   }
00063 
00064   // Check squareness.
00065   return row == sys.num_rows();
00066 }

template<typename Partial_Function >
void Parma_Polyhedra_Library::Grid::map_space_dimensions ( const Partial_Function &  pfunc  )  [inline]

Remaps the dimensions of the vector space according to a partial function.

If pfunc maps only some of the dimensions of *this then the rest will be projected away.

If the highest dimension mapped to by pfunc is higher than the highest dimension in *this then the number of dimensions in this will be increased to the highest dimension mapped to by pfunc.

Parameters:
pfunc The partial function specifying the destiny of each space dimension.

The template type parameter Partial_Function must provide the following methods.

      bool has_empty_codomain() const

returns true if and only if the represented partial function has an empty codomain (i.e., it is always undefined). The has_empty_codomain() method will always be called before the methods below. However, if has_empty_codomain() returns true, none of the functions below will be called.

      dimension_type max_in_codomain() const

returns the maximum value that belongs to the codomain of the partial function. The max_in_codomain() method is called at most once.

      bool maps(dimension_type i, dimension_type& j) const

Let $f$ be the represented function and $k$ be the value of i. If $f$ is defined in $k$, then $f(k)$ is assigned to j and true is returned. If $f$ is undefined in $k$, then false is returned. This method is called at most $n$ times, where $n$ is the dimension of the vector space enclosing the grid.

The result is undefined if pfunc does not encode a partial function with the properties described in the specification of the mapping operator.

Definition at line 112 of file Grid.templates.hh.

References Parma_Polyhedra_Library::Grid_Generator_System::begin(), clear_congruences_minimized(), clear_generators_minimized(), Parma_Polyhedra_Library::Grid_Generator::coefficient(), con_sys, congruences_are_up_to_date(), Parma_Polyhedra_Library::Grid_Generator::divisor(), Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Grid_Generator_System::end(), gen_sys, generators_are_up_to_date(), grid_generators(), Parma_Polyhedra_Library::Matrix::has_no_rows(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), Parma_Polyhedra_Library::Grid_Generator::LINE, marked_empty(), Parma_Polyhedra_Library::not_a_dimension(), OK(), Parma_Polyhedra_Library::Grid_Generator::PARAMETER, Parma_Polyhedra_Library::Grid_Generator_System::permute_columns(), Parma_Polyhedra_Library::Matrix::permute_columns(), Parma_Polyhedra_Library::Grid_Generator::POINT, set_empty(), Parma_Polyhedra_Library::Grid_Generator_System::set_sorted(), set_zero_dim_univ(), space_dim, swap(), throw_invalid_argument(), Parma_Polyhedra_Library::Grid_Generator::type(), and update_generators().

00112                                                         {
00113   if (space_dim == 0)
00114     return;
00115 
00116   if (pfunc.has_empty_codomain()) {
00117     // All dimensions vanish: the grid becomes zero_dimensional.
00118     if (marked_empty()
00119         || (!generators_are_up_to_date() && !update_generators())) {
00120       // Removing all dimensions from the empty grid.
00121       space_dim = 0;
00122       set_empty();
00123     }
00124     else
00125       // Removing all dimensions from a non-empty grid.
00126       set_zero_dim_univ();
00127 
00128     PPL_ASSERT(OK());
00129     return;
00130   }
00131 
00132   dimension_type new_space_dimension = pfunc.max_in_codomain() + 1;
00133 
00134   if (new_space_dimension == space_dim) {
00135     // The partial function `pfunc' is indeed total and thus specifies
00136     // a permutation, that is, a renaming of the dimensions.  For
00137     // maximum efficiency, we will simply permute the columns of the
00138     // constraint system and/or the generator system.
00139 
00140     // We first compute suitable permutation cycles for the columns of
00141     // the `con_sys' and `gen_sys' matrices.  We will represent them
00142     // with a linear array, using 0 as a terminator for each cycle
00143     // (notice that the columns with index 0 of `con_sys' and
00144     // `gen_sys' represent the inhomogeneous terms, and thus are
00145     // unaffected by the permutation of dimensions).
00146     // Cycles of length 1 will be omitted so that, in the worst case,
00147     // we will have `space_dim' elements organized in `space_dim/2'
00148     // cycles, which means we will have at most `space_dim/2'
00149     // terminators.
00150     std::vector<dimension_type> cycles;
00151     cycles.reserve(space_dim + space_dim/2);
00152 
00153     // Used to mark elements as soon as they are inserted in a cycle.
00154     std::deque<bool> visited(space_dim);
00155 
00156     for (dimension_type i = space_dim; i-- > 0; ) {
00157       if (!visited[i]) {
00158         dimension_type j = i;
00159         do {
00160           visited[j] = true;
00161           // The following initialization is only to make the compiler happy.
00162           dimension_type k = 0;
00163           if (!pfunc.maps(j, k))
00164             throw_invalid_argument("map_space_dimensions(pfunc)",
00165                                    " pfunc is inconsistent");
00166           if (k == j)
00167             // Cycle of length 1: skip it.
00168             goto skip;
00169 
00170           cycles.push_back(j+1);
00171           // Go along the cycle.
00172           j = k;
00173         } while (!visited[j]);
00174         // End of cycle: mark it.
00175         cycles.push_back(0);
00176       skip:
00177         ;
00178       }
00179     }
00180 
00181     // If `cycles' is empty then `pfunc' is the identity.
00182     if (cycles.empty())
00183       return;
00184 
00185     // Permute all that is up-to-date.
00186     if (congruences_are_up_to_date()) {
00187       con_sys.permute_columns(cycles);
00188       clear_congruences_minimized();
00189     }
00190 
00191     if (generators_are_up_to_date()) {
00192       gen_sys.permute_columns(cycles);
00193       clear_generators_minimized();
00194     }
00195 
00196     PPL_ASSERT(OK());
00197     return;
00198   }
00199 
00200   // If control gets here, then `pfunc' is not a permutation and some
00201   // dimensions must be projected away.
00202 
00203   const Grid_Generator_System& old_gensys = grid_generators();
00204 
00205   if (old_gensys.has_no_rows()) {
00206     // The grid is empty.
00207     Grid new_grid(new_space_dimension, EMPTY);
00208     std::swap(*this, new_grid);
00209     PPL_ASSERT(OK());
00210     return;
00211   }
00212 
00213   // Make a local copy of the partial function.
00214   std::vector<dimension_type> pfunc_maps(space_dim, not_a_dimension());
00215   for (dimension_type j = space_dim; j-- > 0; ) {
00216     dimension_type pfunc_j;
00217     if (pfunc.maps(j, pfunc_j))
00218       pfunc_maps[j] = pfunc_j;
00219   }
00220 
00221   Grid_Generator_System new_gensys;
00222   // Set sortedness, for the assertion met via gs::insert.
00223   new_gensys.set_sorted(false);
00224   // Get the divisor of the first point.
00225   Grid_Generator_System::const_iterator i;
00226   Grid_Generator_System::const_iterator old_gensys_end = old_gensys.end();
00227   for (i = old_gensys.begin(); i != old_gensys_end; ++i)
00228     if (i->is_point())
00229       break;
00230   PPL_ASSERT(i != old_gensys_end);
00231   const Coefficient& system_divisor = i->divisor();
00232   for (i = old_gensys.begin(); i != old_gensys_end; ++i) {
00233     const Grid_Generator& old_g = *i;
00234     Linear_Expression e(0 * Variable(new_space_dimension-1));
00235     bool all_zeroes = true;
00236     for (dimension_type j = space_dim; j-- > 0; ) {
00237       if (old_g.coefficient(Variable(j)) != 0
00238           && pfunc_maps[j] != not_a_dimension()) {
00239         e += Variable(pfunc_maps[j]) * old_g.coefficient(Variable(j));
00240         all_zeroes = false;
00241       }
00242     }
00243     switch (old_g.type()) {
00244     case Grid_Generator::LINE:
00245       if (!all_zeroes)
00246         new_gensys.insert(grid_line(e));
00247       break;
00248     case Grid_Generator::PARAMETER:
00249       if (!all_zeroes)
00250         new_gensys.insert(parameter(e, system_divisor));
00251       break;
00252     case Grid_Generator::POINT:
00253       new_gensys.insert(grid_point(e, old_g.divisor()));
00254       break;
00255     default:
00256       PPL_ASSERT(0);
00257     }
00258   }
00259 
00260   Grid new_grid(new_gensys);
00261   std::swap(*this, new_grid);
00262 
00263   PPL_ASSERT(OK(true));
00264 }

bool Parma_Polyhedra_Library::Grid::marked_empty (  )  const [inline, private]

Returns true if the grid is known to be empty.

The return value false does not necessarily implies that *this is non-empty.

Definition at line 35 of file Grid.inlines.hh.

References status, and Parma_Polyhedra_Library::Grid::Status::test_empty().

Referenced by add_congruence(), add_congruence_no_check(), add_congruences(), add_constraint(), add_constraint_no_check(), add_constraints(), add_grid_generator(), add_recycled_congruences(), add_recycled_grid_generators(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_image(), affine_preimage(), bounded_affine_image(), bounded_affine_preimage(), bounds(), bounds_no_check(), Parma_Polyhedra_Library::Box< ITV >::Box(), concatenate_assign(), congruence_widening_assign(), congruences(), constrains(), contains(), contains_integer_point(), difference_assign(), drop_some_non_integer_points(), fold_space_dimensions(), frequency_no_check(), generalized_affine_image(), generalized_affine_preimage(), generator_widening_assign(), Parma_Polyhedra_Library::Grid_Certificate::Grid_Certificate(), grid_generators(), intersection_assign(), is_bounded(), is_discrete(), is_empty(), is_included_in(), is_universe(), limited_congruence_extrapolation_assign(), limited_extrapolation_assign(), limited_generator_extrapolation_assign(), map_space_dimensions(), max_min(), minimize(), minimized_grid_generators(), OK(), operator=(), quick_equivalence_test(), refine_no_check(), refine_with_constraint(), refine_with_constraints(), relation_with(), remove_space_dimensions(), select_wider_congruences(), select_wider_generators(), time_elapse_assign(), unconstrain(), update_congruences(), update_generators(), upper_bound_assign(), upper_bound_assign_if_exact(), and wrap_assign().

00035                          {
00036   return status.test_empty();
00037 }

bool Parma_Polyhedra_Library::Grid::max_min ( const Linear_Expression expr,
const char *  method_call,
Coefficient ext_n,
Coefficient ext_d,
bool &  included,
Generator point = NULL 
) const [private]

Maximizes or minimizes expr subject to *this.

Parameters:
expr The linear expression to be maximized or minimized subject to this;
method_call The call description of the public parent method, for example "maximize(e)". Passed to throw_dimension_incompatible, as the first argument;
ext_n The numerator of the extremum value;
ext_d The denominator of the extremum value;
included true if and only if the extremum of expr in this can actually be reached (which is always the case);
point When maximization or minimization succeeds, will be assigned the point where expr reaches the extremum value.
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

If *this is empty or expr is not bounded in the appropriate direction, false is returned and ext_n, ext_d, included and point are left untouched.

Definition at line 394 of file Grid_nonpublic.cc.

References bounds(), Parma_Polyhedra_Library::Grid_Generator::coefficient(), dim_kinds, Parma_Polyhedra_Library::Grid_Generator::divisor(), Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::gcd_assign(), gen_sys, generators_are_minimized(), Parma_Polyhedra_Library::Scalar_Products::homogeneous_assign(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), marked_empty(), Parma_Polyhedra_Library::Generator::point(), PPL_DIRTY_TEMP_COEFFICIENT, set_generators_minimized(), simplify(), and space_dim.

Referenced by maximize(), and minimize().

00397                                            {
00398   if (bounds(expr, method_call)) {
00399     if (marked_empty())
00400       return false;
00401     if (space_dim == 0) {
00402       ext_n = 0;
00403       ext_d = 1;
00404       included = true;
00405       if (point)
00406         *point = Generator::point();
00407       return true;
00408     }
00409     // Grid::bounds above ensures the generators are up to date.
00410     if (!generators_are_minimized()) {
00411       // Minimize the generator system.
00412       Grid& gr = const_cast<Grid&>(*this);
00413       gr.simplify(gr.gen_sys, gr.dim_kinds);
00414       gr.set_generators_minimized();
00415     }
00416 
00417     const Grid_Generator& gen = gen_sys[0];
00418     Scalar_Products::homogeneous_assign(ext_n, expr, gen);
00419     ext_n += expr.inhomogeneous_term();
00420     ext_d = gen.divisor();
00421     // Reduce ext_n and ext_d.
00422     PPL_DIRTY_TEMP_COEFFICIENT(gcd);
00423     gcd_assign(gcd, ext_n, ext_d);
00424     exact_div_assign(ext_n, ext_n, gcd);
00425     exact_div_assign(ext_d, ext_d, gcd);
00426 
00427     included = true;
00428     if (point) {
00429       Linear_Expression e;
00430       for (dimension_type i = space_dim; i-- > 0; )
00431         e += gen.coefficient(Variable(i)) * Variable(i);
00432       *point = Generator::point(e, gen.divisor());
00433     }
00434     return true;
00435   }
00436   return false;
00437 }

dimension_type Parma_Polyhedra_Library::Grid::max_space_dimension (  )  [inline, static]

Returns the maximum space dimension all kinds of Grid can handle.

Definition at line 111 of file Grid.inlines.hh.

References Parma_Polyhedra_Library::Grid_Generator_System::max_space_dimension(), and Parma_Polyhedra_Library::Congruence_System::max_space_dimension().

Referenced by add_space_dimensions_and_embed(), add_space_dimensions_and_project(), concatenate_assign(), construct(), expand_space_dimension(), and Grid().

00111                           {
00112   // One dimension is reserved to have a value of type dimension_type
00113   // that does not represent a legal dimension.
00114   return std::min(std::numeric_limits<dimension_type>::max() - 1,
00115                   std::min(Congruence_System::max_space_dimension(),
00116                            Grid_Generator_System::max_space_dimension()
00117                            )
00118                   );
00119 }

bool Parma_Polyhedra_Library::Grid::maximize ( const Linear_Expression expr,
Coefficient sup_n,
Coefficient sup_d,
bool &  maximum,
Generator point 
) const [inline]

Returns true if and only if *this is not empty and expr is bounded from above in *this, in which case the supremum value and a point where expr reaches it are computed.

Parameters:
expr The linear expression to be maximized subject to *this;
sup_n The numerator of the supremum value;
sup_d The denominator of the supremum value;
maximum true if the supremum value can be reached in this. Always true when this bounds expr. Present for interface compatibility with class Polyhedron, where closure points can result in a value of false;
point When maximization succeeds, will be assigned a point where expr reaches its supremum value.
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

If *this is empty or expr is not bounded by *this, false is returned and sup_n, sup_d, maximum and point are left untouched.

Definition at line 328 of file Grid.inlines.hh.

References max_min().

00330                                        {
00331   return max_min(expr, "maximize(e, ...)", sup_n, sup_d, maximum, &point);
00332 }

bool Parma_Polyhedra_Library::Grid::maximize ( const Linear_Expression expr,
Coefficient sup_n,
Coefficient sup_d,
bool &  maximum 
) const [inline]

Returns true if and only if *this is not empty and expr is bounded from above in *this, in which case the supremum value is computed.

Parameters:
expr The linear expression to be maximized subject to *this;
sup_n The numerator of the supremum value;
sup_d The denominator of the supremum value;
maximum true if the supremum value can be reached in this. Always true when this bounds expr. Present for interface compatibility with class Polyhedron, where closure points can result in a value of false.
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

If *this is empty or expr is not bounded by *this, false is returned and sup_n, sup_d and maximum are left untouched.

Definition at line 322 of file Grid.inlines.hh.

References max_min().

Referenced by Parma_Polyhedra_Library::Box< ITV >::Box().

00323                                                                             {
00324   return max_min(expr, "maximize(e, ...)", sup_n, sup_d, maximum);
00325 }

bool Parma_Polyhedra_Library::Grid::minimize (  )  const [private]

Minimizes both the congruences and the generators.

Returns:
false if and only if *this turns out to be an empty grid.

Minimization is performed on each system only if the minimized Status field is clear.

Definition at line 516 of file Grid_nonpublic.cc.

References con_sys, congruences_are_minimized(), congruences_are_up_to_date(), dim_kinds, gen_sys, generators_are_minimized(), generators_are_up_to_date(), marked_empty(), OK(), set_congruences_minimized(), set_generators_minimized(), simplify(), space_dim, update_congruences(), and update_generators().

Referenced by affine_image(), affine_preimage(), bounds(), constrains(), frequency(), generalized_affine_image(), generalized_affine_preimage(), and wrap_assign().

00516                         {
00517   // 0-dimension and empty grids are already minimized.
00518   if (marked_empty())
00519     return false;
00520   if (space_dim == 0)
00521     return true;
00522 
00523   // Are both systems already minimized?
00524   if (congruences_are_minimized() && generators_are_minimized())
00525     return true;
00526 
00527   // Invoke update_generators, update_congruences or simplify,
00528   // depending on the state of the systems.
00529   if (congruences_are_up_to_date()) {
00530     if (generators_are_up_to_date()) {
00531       Grid& gr = const_cast<Grid&>(*this);
00532       // Only one of the systems can be minimized here.
00533       if (congruences_are_minimized()) {
00534         // Minimize the generator system.
00535         gr.simplify(gr.gen_sys, gr.dim_kinds);
00536         gr.set_generators_minimized();
00537       }
00538       else {
00539 #ifndef NDEBUG
00540         // Both systems are up to date, and the empty case is handled
00541         // above, so the grid should contain points.
00542         bool empty = simplify(gr.con_sys, gr.dim_kinds);
00543         PPL_ASSERT(!empty);
00544 #else
00545         simplify(gr.con_sys, gr.dim_kinds);
00546 #endif
00547         gr.set_congruences_minimized();
00548         if (!generators_are_minimized()) {
00549           // Minimize the generator system.
00550           gr.simplify(gr.gen_sys, gr.dim_kinds);
00551           gr.set_generators_minimized();
00552         }
00553       }
00554     }
00555     else {
00556       // Updating the generators may reveal that `*this' is empty.
00557       const bool ret = update_generators();
00558       PPL_ASSERT(OK());
00559       return ret;
00560     }
00561   }
00562   else {
00563     PPL_ASSERT(generators_are_up_to_date());
00564     update_congruences();
00565   }
00566   PPL_ASSERT(OK());
00567   return true;
00568 }

bool Parma_Polyhedra_Library::Grid::minimize ( const Linear_Expression expr,
Coefficient inf_n,
Coefficient inf_d,
bool &  minimum,
Generator point 
) const [inline]

Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value and a point where expr reaches it are computed.

Parameters:
expr The linear expression to be minimized subject to *this;
inf_n The numerator of the infimum value;
inf_d The denominator of the infimum value;
minimum true if the is the infimum value can be reached in this. Always true when this bounds expr. Present for interface compatibility with class Polyhedron, where closure points can result in a value of false;
point When minimization succeeds, will be assigned a point where expr reaches its infimum value.
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

If *this is empty or expr is not bounded from below, false is returned and inf_n, inf_d, minimum and point are left untouched.

Definition at line 341 of file Grid.inlines.hh.

References max_min().

00343                                        {
00344   return max_min(expr, "minimize(e, ...)", inf_n, inf_d, minimum, &point);
00345 }

bool Parma_Polyhedra_Library::Grid::minimize ( const Linear_Expression expr,
Coefficient inf_n,
Coefficient inf_d,
bool &  minimum 
) const [inline]

Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value is computed.

Parameters:
expr The linear expression to be minimized subject to *this;
inf_n The numerator of the infimum value;
inf_d The denominator of the infimum value;
minimum true if the is the infimum value can be reached in this. Always true when this bounds expr. Present for interface compatibility with class Polyhedron, where closure points can result in a value of false.
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

If *this is empty or expr is not bounded from below, false is returned and inf_n, inf_d and minimum are left untouched.

Definition at line 335 of file Grid.inlines.hh.

References max_min().

Referenced by is_included_in(), and simplify_using_context_assign().

00336                                                                             {
00337   return max_min(expr, "minimize(e, ...)", inf_n, inf_d, minimum);
00338 }

const PPL::Congruence_System & Parma_Polyhedra_Library::Grid::minimized_congruences (  )  const

Returns the system of congruences in minimal form.

Definition at line 296 of file Grid_public.cc.

References con_sys, congruences(), congruences_are_minimized(), congruences_are_up_to_date(), dim_kinds, set_congruences_minimized(), set_empty(), and simplify().

Referenced by affine_dimension(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::approximate_partition(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::Partially_Reduced_Product< D1, D2, R >::minimized_congruences(), minimized_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), and operator<<().

00296                                      {
00297   if (congruences_are_up_to_date() && !congruences_are_minimized()) {
00298     // Minimize the congruences.
00299     Grid& gr = const_cast<Grid&>(*this);
00300     if (gr.simplify(gr.con_sys, gr.dim_kinds))
00301       gr.set_empty();
00302     else
00303       gr.set_congruences_minimized();
00304   }
00305   return congruences();
00306 }

Constraint_System Parma_Polyhedra_Library::Grid::minimized_constraints (  )  const [inline]

Returns a minimal system of equality constraints satisfied by *this with the same affine dimension as *this.

Definition at line 240 of file Grid.inlines.hh.

References minimized_congruences().

00240                                   {
00241   return Constraint_System(minimized_congruences());;
00242 }

const PPL::Grid_Generator_System & Parma_Polyhedra_Library::Grid::minimized_grid_generators (  )  const

Returns the minimized system of generators.

Definition at line 331 of file Grid_public.cc.

References dim_kinds, gen_sys, generators_are_minimized(), generators_are_up_to_date(), Parma_Polyhedra_Library::Matrix::has_no_rows(), marked_empty(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), set_generators_minimized(), simplify(), space_dim, Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), and update_generators().

Referenced by affine_dimension().

00331                                          {
00332   if (space_dim == 0) {
00333     PPL_ASSERT(gen_sys.space_dimension() == 0
00334            && gen_sys.num_rows() == (marked_empty() ? 0 : 1));
00335     return gen_sys;
00336   }
00337 
00338   if (marked_empty()) {
00339     PPL_ASSERT(gen_sys.has_no_rows());
00340     return gen_sys;
00341   }
00342 
00343   if (generators_are_up_to_date()) {
00344     if (!generators_are_minimized()) {
00345       // Minimize the generators.
00346       Grid& gr = const_cast<Grid&>(*this);
00347       gr.simplify(gr.gen_sys, gr.dim_kinds);
00348       gr.set_generators_minimized();
00349     }
00350   }
00351   else if (!update_generators()) {
00352     // Updating found the grid empty.
00353     const_cast<Grid&>(*this).set_empty();
00354     return gen_sys;
00355   }
00356 
00357   return gen_sys;
00358 }

void Parma_Polyhedra_Library::Grid::multiply_grid ( const Coefficient multiplier,
Grid_Generator gen,
Grid_Generator_System dest,
dimension_type  num_rows,
dimension_type  num_dims 
) [static, private]

Multiply the elements of dest by multiplier.

Definition at line 105 of file Grid_conversion.cc.

References Parma_Polyhedra_Library::Grid_Generator::is_line(), and Parma_Polyhedra_Library::Grid_Generator::is_parameter_or_point().

00107                                                    {
00108   if (multiplier == 1)
00109     return;
00110 
00111   if (gen.is_line())
00112     // Multiply every element of the line.
00113     for (dimension_type column = num_dims; column-- > 0; )
00114       gen[column] *= multiplier;
00115   else {
00116     PPL_ASSERT(gen.is_parameter_or_point());
00117     // Multiply every element of every parameter.
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 }

void Parma_Polyhedra_Library::Grid::multiply_grid ( const Coefficient multiplier,
Congruence cg,
Congruence_System dest,
dimension_type  num_rows,
dimension_type  num_dims 
) [static, private]

Multiply the elements of dest by multiplier.

Definition at line 128 of file Grid_conversion.cc.

References Parma_Polyhedra_Library::Congruence::is_equality(), and Parma_Polyhedra_Library::Congruence::is_proper_congruence().

Referenced by conversion().

00130                                                    {
00131   if (multiplier == 1)
00132     return;
00133 
00134   if (cg.is_proper_congruence())
00135     // Multiply every element of every congruence.
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     // Multiply every element of the equality.
00145     for (dimension_type column = num_dims; column-- > 0; )
00146       cg[column] *= multiplier;
00147   }
00148 }

void Parma_Polyhedra_Library::Grid::normalize_divisors ( Grid_Generator_System sys,
Grid_Generator_System gen_sys 
) [static, private]

Normalize all the divisors in sys and gen_sys.

Modify sys and gen_sys to use the same single divisor value for all generators, leaving each system representing the grid it represented originally.

Parameters:
sys The first of the generator systems to be normalized.
gen_sys The second of the generator systems to be normalized. This system must have at least one row and the divisors of the generators in this system must be equal.
Exceptions:
std::runtime_error Thrown if all rows in gen_sys are lines and/or parameters.

Definition at line 571 of file Grid_nonpublic.cc.

References Parma_Polyhedra_Library::Grid_Generator::divisor(), Parma_Polyhedra_Library::Grid_Generator::is_parameter_or_point(), normalize_divisors(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), and PPL_DIRTY_TEMP_COEFFICIENT.

00572                                                               {
00573 #ifndef NDEBUG
00574   const dimension_type num_rows = gen_sys.num_rows();
00575 #endif
00576   PPL_ASSERT(num_rows > 0);
00577 
00578   // Find the first point in gen_sys.
00579   dimension_type row = 0;
00580   while (gen_sys[row].is_line_or_parameter()) {
00581     ++row;
00582     // gen_sys should have at least one point.
00583     PPL_ASSERT(row < num_rows);
00584   }
00585   Grid_Generator& first_point = gen_sys[row];
00586   const Coefficient& gen_sys_divisor = first_point.divisor();
00587 
00588 #ifndef NDEBUG
00589   // Check that the divisors in gen_sys are equal.
00590   for (dimension_type i = row + 1; i < num_rows; ++i) {
00591     Grid_Generator& g = gen_sys[i];
00592     if (g.is_parameter_or_point())
00593       PPL_ASSERT(gen_sys_divisor == g.divisor());
00594   }
00595 #endif // !defined(NDEBUG)
00596 
00597   PPL_DIRTY_TEMP_COEFFICIENT(divisor);
00598   divisor = gen_sys_divisor;
00599   // Adjust sys to include the gen_sys divisor.
00600   normalize_divisors(sys, divisor);
00601   if (divisor != gen_sys_divisor)
00602     // Adjust gen_sys to use the new divisor.
00603     //
00604     // The points and parameters in gen_sys share a common divisor
00605     // value, so the new divisor will be the LCM of this common
00606     // divisor and `divisor', hence the third argument.
00607     normalize_divisors(gen_sys, divisor, &first_point);
00608 }

void Parma_Polyhedra_Library::Grid::normalize_divisors ( Grid_Generator_System sys  )  [inline, static, private]

Normalizes the divisors in sys.

Converts sys to an equivalent system in which the divisors are of equal value.

Parameters:
sys The generator system to be normalized. It must have at least one row.

Definition at line 348 of file Grid.inlines.hh.

References normalize_divisors(), and PPL_DIRTY_TEMP_COEFFICIENT.

00348                                                    {
00349   PPL_DIRTY_TEMP_COEFFICIENT(divisor);
00350   divisor = 1;
00351   normalize_divisors(sys, divisor);
00352 }

void Parma_Polyhedra_Library::Grid::normalize_divisors ( Grid_Generator_System sys,
Coefficient divisor,
const Grid_Generator first_point = NULL 
) [static, private]

Normalizes the divisors in sys.

Converts sys to an equivalent system in which the divisors are of equal value.

Parameters:
sys The generator system to be normalized. It must have at least one row.
divisor A reference to the initial value of the divisor. The resulting value of this object is the new system divisor.
first_point If first_point has a value other than NULL then it is taken as the first point in sys, and it is assumed that any following points have the same divisor as first_point.

Definition at line 611 of file Grid_nonpublic.cc.

References Parma_Polyhedra_Library::Grid_Generator::divisor(), Parma_Polyhedra_Library::Grid_Generator::is_parameter_or_point(), Parma_Polyhedra_Library::lcm_assign(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), and Parma_Polyhedra_Library::Grid_Generator_System::space_dimension().

Referenced by add_grid_generator(), add_recycled_grid_generators(), add_space_dimensions(), add_space_dimensions_and_project(), affine_image(), construct(), generalized_affine_image(), generalized_affine_preimage(), normalize_divisors(), time_elapse_assign(), and upper_bound_assign().

00613                                                                  {
00614   PPL_ASSERT(divisor >= 0);
00615   if (sys.space_dimension() > 0 && divisor > 0) {
00616     dimension_type row = 0;
00617     dimension_type num_rows = sys.num_rows();
00618 
00619     if (first_point)
00620       lcm_assign(divisor, divisor, (*first_point).divisor());
00621     else {
00622       PPL_ASSERT(num_rows > 0);
00623       // Move to the first point or parameter.
00624       while (sys[row].is_line())
00625         if (++row == num_rows)
00626           // All rows are lines.
00627           return;
00628 
00629       // Calculate the LCM of the given divisor and the divisor of
00630       // every point or parameter.
00631       while (row < num_rows) {
00632         const Grid_Generator& g = sys[row];
00633         if (g.is_parameter_or_point())
00634           lcm_assign(divisor, divisor, g.divisor());
00635         ++row;
00636       }
00637     }
00638 
00639     // Represent every point and every parameter using the newly
00640     // calculated divisor.
00641     for (row = num_rows; row-- > 0; )
00642       sys[row].scale_to_divisor(divisor);
00643   }
00644 }

bool Parma_Polyhedra_Library::Grid::OK ( bool  check_not_empty = false  )  const

Checks if all the invariants are satisfied.

Returns:
true if and only if *this satisfies all the invariants and either check_not_empty is false or *this is not empty.
Parameters:
check_not_empty true if and only if, in addition to checking the invariants, *this must be checked to be not empty.

The check is performed so as to intrude as little as possible. If the library has been compiled with run-time assertions enabled, error messages are written on std::cerr in case invariants are violated. This is useful for the purpose of debugging the library.

Definition at line 864 of file Grid_public.cc.

References ascii_dump(), Parma_Polyhedra_Library::Congruence_System::ascii_dump(), Parma_Polyhedra_Library::Grid_Generator_System::ascii_dump(), clear_generators_up_to_date(), con_sys, CON_VIRTUAL, congruences_are_minimized(), congruences_are_up_to_date(), dim_kinds, EQUALITY, gen_sys, GEN_VIRTUAL, generators_are_minimized(), generators_are_up_to_date(), Parma_Polyhedra_Library::Matrix::has_no_rows(), Parma_Polyhedra_Library::Grid_Generator_System::has_points(), Parma_Polyhedra_Library::Congruence_System::is_equal_to(), Parma_Polyhedra_Library::Grid_Generator::is_equal_to(), LINE, lower_triangular(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), Parma_Polyhedra_Library::Congruence_System::OK(), Parma_Polyhedra_Library::Grid_Generator_System::OK(), Parma_Polyhedra_Library::Grid::Status::OK(), PARAMETER, PROPER_CONGRUENCE, simplify(), Parma_Polyhedra_Library::Grid_Generator::size(), space_dim, Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), Parma_Polyhedra_Library::Congruence_System::space_dimension(), status, swap(), update_generators(), and upper_triangular().

Referenced by add_congruence_no_check(), add_grid_generator(), add_recycled_congruences(), add_recycled_grid_generators(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_image(), affine_preimage(), bounded_affine_image(), bounded_affine_preimage(), concatenate_assign(), congruence_widening_assign(), construct(), difference_assign(), drop_some_non_integer_points(), expand_space_dimension(), fold_space_dimensions(), generalized_affine_image(), generalized_affine_preimage(), generator_widening_assign(), Grid(), intersection_assign(), is_included_in(), limited_congruence_extrapolation_assign(), limited_extrapolation_assign(), limited_generator_extrapolation_assign(), map_space_dimensions(), minimize(), remove_higher_space_dimensions(), remove_space_dimensions(), simplify_using_context_assign(), time_elapse_assign(), unconstrain(), and upper_bound_assign().

00864                                       {
00865 #ifndef NDEBUG
00866   using std::endl;
00867   using std::cerr;
00868 #endif
00869 
00870   // Check whether the status information is legal.
00871   if (!status.OK())
00872     goto fail;
00873 
00874   if (marked_empty()) {
00875     if (check_not_empty) {
00876       // The caller does not want the grid to be empty.
00877 #ifndef NDEBUG
00878       cerr << "Empty grid!" << endl;
00879 #endif
00880       goto fail;
00881     }
00882 
00883     if (con_sys.space_dimension() != space_dim) {
00884 #ifndef NDEBUG
00885       cerr << "The grid is in a space of dimension " << space_dim
00886            << " while the system of congruences is in a space of dimension "
00887            << con_sys.space_dimension()
00888            << endl;
00889 #endif
00890       goto fail;
00891     }
00892     return true;
00893   }
00894 
00895   // A zero-dimensional universe grid is legal only if the system of
00896   // congruences `con_sys' is empty, and the generator system contains
00897   // one point.
00898   if (space_dim == 0) {
00899     if (con_sys.has_no_rows())
00900       if (gen_sys.num_rows() == 1 && gen_sys[0].is_point())
00901         return true;
00902 #ifndef NDEBUG
00903     cerr << "Zero-dimensional grid should have an empty congruence" << endl
00904          << "system and a generator system of a single point." << endl;
00905 #endif
00906     goto fail;
00907   }
00908 
00909   // A grid is defined by a system of congruences or a system of
00910   // generators.  At least one of them must be up to date.
00911   if (!congruences_are_up_to_date() && !generators_are_up_to_date()) {
00912 #ifndef NDEBUG
00913     cerr << "Grid not empty, not zero-dimensional" << endl
00914          << "and with neither congruences nor generators up-to-date!"
00915          << endl;
00916 #endif
00917     goto fail;
00918   }
00919 
00920   {
00921     // The expected number of columns in the congruence and generator
00922     // systems, if they are not empty.
00923     const dimension_type num_columns = space_dim + 1;
00924 
00925     // Here we check if the size of the matrices is consistent.
00926     // Let us suppose that all the matrices are up-to-date; this means:
00927     // `con_sys' : number of congruences x poly_num_columns
00928     // `gen_sys' : number of generators  x poly_num_columns
00929     if (congruences_are_up_to_date())
00930       if (con_sys.num_columns() != num_columns + 1 /* moduli */) {
00931 #ifndef NDEBUG
00932         cerr << "Incompatible size! (con_sys and space_dim)"
00933              << endl;
00934 #endif
00935         goto fail;
00936       }
00937 
00938     if (generators_are_up_to_date()) {
00939       if (gen_sys.space_dimension() + 1 != num_columns) {
00940 #ifndef NDEBUG
00941         cerr << "Incompatible size! (gen_sys and space_dim)"
00942              << endl;
00943 #endif
00944         goto fail;
00945       }
00946 
00947       // Check if the system of generators is well-formed.
00948       if (!gen_sys.OK())
00949         goto fail;
00950 
00951       // Check each generator in the system.
00952       for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) {
00953         const Grid_Generator& g = gen_sys[i];
00954 
00955         if (g.size() < 1) {
00956 #ifndef NDEBUG
00957           cerr << "Parameter should have coefficients." << endl;
00958 #endif
00959           goto fail;
00960         }
00961       }
00962 
00963       // A non-empty system of generators describing a grid is valid
00964       // if and only if it contains a point.
00965       if (!gen_sys.has_no_rows() && !gen_sys.has_points()) {
00966 #ifndef NDEBUG
00967         cerr << "Non-empty generator system declared up-to-date "
00968              << "has no points!"
00969              << endl;
00970 #endif
00971         goto fail;
00972       }
00973 
00974       if (generators_are_minimized()) {
00975         Grid_Generator_System gs = gen_sys;
00976 
00977         if (dim_kinds.size() != num_columns) {
00978 #ifndef NDEBUG
00979           cerr << "Size of dim_kinds should equal the number of columns."
00980                << endl;
00981 #endif
00982           goto fail;
00983         }
00984 
00985         if (!upper_triangular(gs, dim_kinds)) {
00986 #ifndef NDEBUG
00987           cerr << "Reduced generators should be upper triangular."
00988                << endl;
00989 #endif
00990           goto fail;
00991         }
00992 
00993         // Check that dim_kinds corresponds to the row kinds in gen_sys.
00994         for (dimension_type dim = space_dim,
00995                row = gen_sys.num_rows(); dim > 0; --dim) {
00996           if (dim_kinds[dim] == GEN_VIRTUAL)
00997             goto ok;
00998           if (gen_sys[--row].is_parameter_or_point()
00999               && dim_kinds[dim] == PARAMETER)
01000             goto ok;
01001           PPL_ASSERT(gen_sys[row].is_line());
01002           if (dim_kinds[dim] == LINE)
01003             goto ok;
01004 #ifndef NDEBUG
01005           cerr << "Kinds in dim_kinds should match those in gen_sys."
01006                << endl;
01007 #endif
01008           goto fail;
01009         ok:
01010           PPL_ASSERT(row <= dim);
01011         }
01012 
01013         // A reduced generator system must be the same as a temporary
01014         // reduced copy.
01015         Dimension_Kinds dk = dim_kinds;
01016         // `gs' is minimized and marked_empty returned false, so `gs'
01017         // should contain rows.
01018         PPL_ASSERT(!gs.has_no_rows());
01019         simplify(gs, dk);
01020         // gs contained rows before being reduced, so it should
01021         // contain at least a single point afterward.
01022         PPL_ASSERT(!gs.has_no_rows());
01023         for (dimension_type row = gen_sys.num_rows(); row-- > 0; ) {
01024           Grid_Generator& g = gs[row];
01025           const Grid_Generator& g_copy = gen_sys[row];
01026           if (g.is_equal_to(g_copy))
01027             continue;
01028 #ifndef NDEBUG
01029           cerr << "Generators are declared minimized,"
01030             " but they change under reduction.\n"
01031                << "Here is the generator system:\n";
01032           gen_sys.ascii_dump(cerr);
01033           cerr << "and here is the minimized form of the temporary copy:\n";
01034           gs.ascii_dump(cerr);
01035 #endif
01036           goto fail;
01037         }
01038       }
01039 
01040     } // if (congruences_are_up_to_date())
01041   }
01042 
01043   if (congruences_are_up_to_date()) {
01044     // Check if the system of congruences is well-formed.
01045     if (!con_sys.OK())
01046       goto fail;
01047 
01048     Grid tmp_gr = *this;
01049     Congruence_System cs_copy = tmp_gr.con_sys;
01050 
01051     // Clear the generators in tmp_gr.
01052     Grid_Generator_System gs(space_dim);
01053     std::swap(tmp_gr.gen_sys, gs);
01054     tmp_gr.clear_generators_up_to_date();
01055 
01056     if (!tmp_gr.update_generators()) {
01057       if (check_not_empty) {
01058         // Want to know the satisfiability of the congruences.
01059 #ifndef NDEBUG
01060         cerr << "Unsatisfiable system of congruences!"
01061              << endl;
01062 #endif
01063         goto fail;
01064       }
01065       // The grid is empty, all checks are done.
01066       return true;
01067     }
01068 
01069     if (congruences_are_minimized()) {
01070       // A reduced congruence system must be lower triangular.
01071       if (!lower_triangular(con_sys, dim_kinds)) {
01072 #ifndef NDEBUG
01073         cerr << "Reduced congruences should be lower triangular." << endl;
01074 #endif
01075         goto fail;
01076       }
01077 
01078       // If the congruences are minimized, all the elements in the
01079       // congruence system must be the same as those in the temporary,
01080       // minimized system `cs_copy'.
01081       if (!con_sys.is_equal_to(cs_copy)) {
01082 #ifndef NDEBUG
01083         cerr << "Congruences are declared minimized, but they change under reduction!"
01084              << endl
01085              << "Here is the minimized form of the congruence system:"
01086              << endl;
01087         cs_copy.ascii_dump(cerr);
01088         cerr << endl;
01089 #endif
01090         goto fail;
01091       }
01092 
01093       if (dim_kinds.size() != con_sys.num_columns() - 1 /* modulus */) {
01094 #ifndef NDEBUG
01095         cerr << "Size of dim_kinds should equal the number of columns."
01096              << endl;
01097 #endif
01098         goto fail;
01099       }
01100 
01101       // Check that dim_kinds corresponds to the row kinds in con_sys.
01102       for (dimension_type dim = space_dim, row = 0; dim > 0; --dim) {
01103         if (dim_kinds[dim] == CON_VIRTUAL)
01104             continue;
01105         if (con_sys[row++].is_proper_congruence()
01106             && dim_kinds[dim] == PROPER_CONGRUENCE)
01107           continue;
01108         PPL_ASSERT(con_sys[row-1].is_equality());
01109         if (dim_kinds[dim] == EQUALITY)
01110           continue;
01111 #ifndef NDEBUG
01112         cerr << "Kinds in dim_kinds should match those in con_sys." << endl;
01113 #endif
01114         goto fail;
01115       }
01116     }
01117   }
01118 
01119   return true;
01120 
01121  fail:
01122 #ifndef NDEBUG
01123   cerr << "Here is the grid under check:" << endl;
01124   ascii_dump(cerr);
01125 #endif
01126   return false;
01127 }

PPL::Grid & Parma_Polyhedra_Library::Grid::operator= ( const Grid y  ) 

The assignment operator. (*this and y can be dimension-incompatible.).

Definition at line 240 of file Grid_public.cc.

References con_sys, congruences_are_up_to_date(), dim_kinds, gen_sys, generators_are_up_to_date(), marked_empty(), set_empty(), set_zero_dim_univ(), space_dim, and status.

00240                                 {
00241   space_dim = y.space_dim;
00242   dim_kinds = y.dim_kinds;
00243   if (y.marked_empty())
00244     set_empty();
00245   else if (space_dim == 0)
00246     set_zero_dim_univ();
00247   else {
00248     status = y.status;
00249     if (y.congruences_are_up_to_date())
00250       con_sys = y.con_sys;
00251     if (y.generators_are_up_to_date())
00252       gen_sys = y.gen_sys;
00253   }
00254   return *this;
00255 }

void Parma_Polyhedra_Library::Grid::print (  )  const

Prints *this to std::cerr using operator<<.

PPL::Grid::Three_Valued_Boolean Parma_Polyhedra_Library::Grid::quick_equivalence_test ( const Grid y  )  const [private]

Polynomial but incomplete equivalence test between grids.

Definition at line 182 of file Grid_nonpublic.cc.

References con_sys, congruences_are_minimized(), gen_sys, generators_are_minimized(), marked_empty(), Parma_Polyhedra_Library::Congruence_System::num_equalities(), Parma_Polyhedra_Library::Grid_Generator_System::num_lines(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), Parma_Polyhedra_Library::Matrix::num_rows(), space_dim, TVB_DONT_KNOW, TVB_FALSE, and TVB_TRUE.

Referenced by contains().

00182                                                    {
00183   // Private method: the caller must ensure the following.
00184   PPL_ASSERT(space_dim == y.space_dim);
00185   PPL_ASSERT(!marked_empty() && !y.marked_empty() && space_dim > 0);
00186 
00187   const Grid& x = *this;
00188 
00189   bool css_normalized = false;
00190 
00191   if (x.congruences_are_minimized() && y.congruences_are_minimized()) {
00192     // Equivalent minimized congruence systems have:
00193     //  - the same number of congruences; ...
00194     if (x.con_sys.num_rows() != y.con_sys.num_rows())
00195       return Grid::TVB_FALSE;
00196     //  - the same number of equalities; ...
00197     dimension_type x_num_equalities = x.con_sys.num_equalities();
00198     if (x_num_equalities != y.con_sys.num_equalities())
00199       return Grid::TVB_FALSE;
00200     //  - and if there are no equalities, the same congruences.
00201     //    Delay this test: try cheaper tests on generators first.
00202     css_normalized = (x_num_equalities == 0);
00203   }
00204 
00205   if (x.generators_are_minimized() && y.generators_are_minimized()) {
00206     // Equivalent minimized generator systems have:
00207     //  - the same number of generators; ...
00208     if (x.gen_sys.num_rows() != y.gen_sys.num_rows())
00209       return Grid::TVB_FALSE;
00210     //  - the same number of lines; ...
00211     const dimension_type x_num_lines = x.gen_sys.num_lines();
00212     if (x_num_lines != y.gen_sys.num_lines())
00213       return Grid::TVB_FALSE;
00214       //  - and if there are no lines, the same generators.
00215     if (x_num_lines == 0) {
00216       // Check for syntactic identity.
00217       if (x.gen_sys == y.gen_sys)
00218         return Grid::TVB_TRUE;
00219       else
00220         return Grid::TVB_FALSE;
00221     }
00222   }
00223 
00224   // TODO: Consider minimizing the systems and re-performing these
00225   //       checks.
00226 
00227   if (css_normalized) {
00228     if (x.con_sys == y.con_sys)
00229       return Grid::TVB_TRUE;
00230     else
00231       return Grid::TVB_FALSE;
00232   }
00233 
00234   return Grid::TVB_DONT_KNOW;
00235 }

void Parma_Polyhedra_Library::Grid::reduce_congruence_with_equality ( Congruence row,
const Congruence pivot,
dimension_type  col,
Congruence_System sys 
) [static, private]

Reduce row using pivot.

Use the equality pivot to change the representation of the congruence row such that element at index col of row is zero.

Definition at line 182 of file Grid_simplify.cc.

References Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::gcd_assign(), Parma_Polyhedra_Library::Congruence::is_proper_congruence(), Parma_Polyhedra_Library::Congruence::modulus(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), PPL_DIRTY_TEMP_COEFFICIENT, and Parma_Polyhedra_Library::sub_mul_assign().

Referenced by simplify().

00185                                                               {
00186   // Very similar to reduce_parameter_with_line above.  Any change
00187   // here may be needed there too.
00188   PPL_ASSERT(row.modulus() > 0 && pivot.modulus() == 0);
00189 
00190   const Coefficient& pivot_column = pivot[column];
00191   Coefficient& row_column = row[column];
00192 
00193   dimension_type num_columns = sys.num_columns();
00194 
00195   // If the elements at `column' in row and pivot are the same, then
00196   // just subtract `pivot' from `row'.
00197   if (row_column == pivot_column) {
00198     for (dimension_type col = num_columns; col-- > 0; )
00199       row[col] -= pivot[col];
00200     return;
00201   }
00202 
00203   PPL_DIRTY_TEMP_COEFFICIENT(reduced_row_col);
00204   // Use reduced_row_col temporarily to hold the gcd.
00205   gcd_assign(reduced_row_col, pivot_column, row_column);
00206   PPL_DIRTY_TEMP_COEFFICIENT(reduced_pivot_col);
00207   exact_div_assign(reduced_pivot_col, pivot_column, reduced_row_col);
00208   exact_div_assign(reduced_row_col, row_column, reduced_row_col);
00209   // Ensure that `reduced_pivot_col' is positive, so that the modulus
00210   // remains positive when multiplying the proper congruences below.
00211   // It's safe to swap the signs as row[column] will still come out 0.
00212   if (reduced_pivot_col < 0) {
00213     neg_assign(reduced_pivot_col);
00214     neg_assign(reduced_row_col);
00215   }
00216   // Multiply `row', including the modulus, by reduced_pivot_col.  To
00217   // keep all the moduli the same this requires multiplying all the
00218   // other proper congruences in the same way.
00219   for (dimension_type index = sys.num_rows(); index-- > 0; ) {
00220     Congruence& cg = sys[index];
00221     if (cg.is_proper_congruence())
00222       for (dimension_type col = num_columns; col-- > 0; )
00223         cg[col] *= reduced_pivot_col;
00224   }
00225   // Column num_columns contains the modulus, so start at the next
00226   // column.
00227   --num_columns;
00228   row_column = 0;
00229   // Subtract from row a multiple of pivot such that the result in
00230   // row[column] is zero.
00231   for (dimension_type col = column; col-- > 0; )
00232     sub_mul_assign(row[col], reduced_row_col, pivot[col]);
00233 }

void Parma_Polyhedra_Library::Grid::reduce_equality_with_equality ( Congruence row,
const Congruence pivot,
dimension_type  col 
) [static, private]

Reduces the equality row using the equality pivot.

Uses the equality pivot to change the representation of the equality row so that the element at index col of row is zero.

Definition at line 58 of file Grid_simplify.cc.

References Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::gcd_assign(), Parma_Polyhedra_Library::Congruence::modulus(), PPL_DIRTY_TEMP_COEFFICIENT, and Parma_Polyhedra_Library::sub_mul_assign().

Referenced by simplify().

00060                                                                  {
00061   // Assume two equalities.
00062   PPL_ASSERT(row.modulus() == 0 && pivot.modulus() == 0);
00063 
00064   const Coefficient& pivot_column = pivot[column];
00065   Coefficient& row_column = row[column];
00066   PPL_DIRTY_TEMP_COEFFICIENT(reduced_row_col);
00067   // Use reduced_row_col temporarily to hold the gcd.
00068   gcd_assign(reduced_row_col, pivot_column, row_column);
00069   // Store the reduced ratio between pivot[column] and row[column].
00070   PPL_DIRTY_TEMP_COEFFICIENT(reduced_pivot_col);
00071   exact_div_assign(reduced_pivot_col, pivot_column, reduced_row_col);
00072   exact_div_assign(reduced_row_col, row_column, reduced_row_col);
00073   // Multiply row, then subtract from it a multiple of pivot such that
00074   // the result in row[column] is zero.
00075   row_column = 0;
00076   for (dimension_type col = column; col-- > 0; ) {
00077     Coefficient& row_col = row[col];
00078     row_col *= reduced_pivot_col;
00079     sub_mul_assign(row_col, reduced_row_col, pivot[col]);
00080   }
00081 }

void Parma_Polyhedra_Library::Grid::reduce_line_with_line ( Grid_Generator row,
Grid_Generator pivot,
dimension_type  col 
) [static, private]

Reduces the line row using the line pivot.

Uses the line pivot to change the representation of the line row so that the element at index col of row is zero.

Definition at line 32 of file Grid_simplify.cc.

References Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::gcd_assign(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Grid_Generator::size(), and Parma_Polyhedra_Library::sub_mul_assign().

Referenced by simplify().

00033                                                    {
00034   const Coefficient& pivot_column = pivot[column];
00035   Coefficient& row_column = row[column];
00036   PPL_DIRTY_TEMP_COEFFICIENT(reduced_row_col);
00037   // Use reduced_row_col temporarily to hold the gcd.
00038   gcd_assign(reduced_row_col, pivot_column, row_column);
00039   // Store the reduced ratio between pivot[column] and row[column].
00040   PPL_DIRTY_TEMP_COEFFICIENT(reduced_pivot_col);
00041   exact_div_assign(reduced_pivot_col, pivot_column, reduced_row_col);
00042   exact_div_assign(reduced_row_col, row_column, reduced_row_col);
00043   // Multiply row, then subtract from it a multiple of pivot such that
00044   // the result in row[column] is zero.
00045   row_column = 0;
00046   // pivot.size() - 1 is the index for the parameter divisor so we
00047   // start reducing the line at index pivot.size() - 2.
00048   for (dimension_type col = pivot.size() - 2;
00049        col > column;
00050        --col) {
00051     Coefficient& row_col = row[col];
00052     row_col *= reduced_pivot_col;
00053     sub_mul_assign(row_col, reduced_row_col, pivot[col]);
00054   }
00055 }

void Parma_Polyhedra_Library::Grid::reduce_parameter_with_line ( Grid_Generator row,
const Grid_Generator pivot,
dimension_type  col,
Grid_Generator_System sys 
) [static, private]

Reduce row using pivot.

Use the line pivot to change the representation of the parameter row such that the element at index col of row is zero.

Definition at line 126 of file Grid_simplify.cc.

References Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::gcd_assign(), Parma_Polyhedra_Library::Grid_Generator::is_parameter_or_point(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Grid_Generator_System::num_columns(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), PPL_DIRTY_TEMP_COEFFICIENT, and Parma_Polyhedra_Library::sub_mul_assign().

Referenced by simplify().

00129                                                              {
00130   // Very similar to reduce_congruence_with_equality below.  Any
00131   // change here may be needed there too.
00132 
00133   const Coefficient& pivot_column = pivot[column];
00134   Coefficient& row_column = row[column];
00135 
00136   // Subtract one to allow for the parameter divisor column
00137   const dimension_type num_columns = sys.num_columns() - 1;
00138 
00139   // If the elements at column in row and pivot are the same, then
00140   // just subtract pivot from row.
00141   if (row_column == pivot_column) {
00142     for (dimension_type col = num_columns; col-- > 0; )
00143       row[col] -= pivot[col];
00144     return;
00145   }
00146 
00147   PPL_DIRTY_TEMP_COEFFICIENT(reduced_row_col);
00148   // Use reduced_row_col temporarily to hold the gcd.
00149   gcd_assign(reduced_row_col, pivot_column, row_column);
00150   // Store the reduced ratio between pivot[column] and row[column].
00151   PPL_DIRTY_TEMP_COEFFICIENT(reduced_pivot_col);
00152   exact_div_assign(reduced_pivot_col, pivot_column, reduced_row_col);
00153   exact_div_assign(reduced_row_col, row_column, reduced_row_col);
00154 
00155 
00156   // Since we are reducing the system to "strong minimal form",
00157   // ensure that the multiplier is positive, so that the preceding
00158   // diagonals (including the divisor) remain positive.  It's safe to
00159   // swap the signs as row[column] will still come out 0.
00160   if (reduced_pivot_col < 0) {
00161     neg_assign(reduced_pivot_col);
00162     neg_assign(reduced_row_col);
00163   }
00164 
00165   // Multiply row such that a multiple of pivot can be subtracted from
00166   // it below to render row[column] zero.  This requires multiplying
00167   // all other parameters to match.
00168   for (dimension_type index = sys.num_rows(); index-- > 0; ) {
00169     Grid_Generator& gen = sys[index];
00170     if (gen.is_parameter_or_point())
00171       for (dimension_type col = num_columns; col-- > 0; )
00172         gen[col] *= reduced_pivot_col;
00173   }
00174   // Subtract from row a multiple of pivot such that the result in
00175   // row[column] is zero.
00176   row_column = 0;
00177   for (dimension_type col = num_columns - 1; col > column; --col)
00178     sub_mul_assign(row[col], reduced_row_col, pivot[col]);
00179 }

template<typename R >
void Parma_Polyhedra_Library::Grid::reduce_pc_with_pc ( R &  row,
R &  pivot,
dimension_type  col,
dimension_type  start,
dimension_type  end 
) [inline, static, private]

Reduces row using pivot.

Uses the point, parameter or proper congruence at pivot to change the representation of the point, parameter or proper congruence at row so that the element at index col of row is zero. Only elements from index start to index end are modified (i.e. it is assumed that all other elements are zero).

Definition at line 85 of file Grid_simplify.cc.

References Parma_Polyhedra_Library::add_mul_assign(), Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::gcdext_assign(), PPL_DIRTY_TEMP_COEFFICIENT, and Parma_Polyhedra_Library::sub_mul_assign().

Referenced by simplify().

00088                                                   {
00089   Coefficient& pivot_column = pivot[column];
00090   Coefficient& row_column = row[column];
00091 
00092   PPL_DIRTY_TEMP_COEFFICIENT(s);
00093   PPL_DIRTY_TEMP_COEFFICIENT(t);
00094   PPL_DIRTY_TEMP_COEFFICIENT(reduced_row_col);
00095   // Use reduced_row_col temporarily to hold the gcd.
00096   gcdext_assign(reduced_row_col, s, t, pivot_column, row_column);
00097   // Now pivot[column] * s + row[column] * t == gcd.
00098 
00099   // Store the reduced ratio between pivot[column] and row[column].
00100   PPL_DIRTY_TEMP_COEFFICIENT(reduced_pivot_col);
00101   exact_div_assign(reduced_pivot_col, pivot_column, reduced_row_col);
00102   pivot_column = reduced_row_col /* gcd */;
00103   exact_div_assign(reduced_row_col, row_column, reduced_row_col);
00104 
00105   // Multiply row, then subtract from it a multiple of pivot such that
00106   // the result in row[column] is zero.  Afterward, multiply pivot,
00107   // then add to it a (possibly negative) multiple of row such that
00108   // the result in pivot[column] is the smallest possible positive
00109   // integer.
00110   PPL_ASSERT(pivot.size() > 0);
00111   PPL_ASSERT(row.size() > 0);
00112   row_column = 0;
00113   PPL_DIRTY_TEMP_COEFFICIENT(old_pivot_col);
00114   for (dimension_type col = start; col < end; ++col) {
00115     Coefficient& pivot_col = pivot[col];
00116     old_pivot_col = pivot_col;
00117     pivot_col *= s;
00118     Coefficient& row_col = row[col];
00119     add_mul_assign(pivot_col, t, row_col);
00120     row_col *= reduced_pivot_col;
00121     sub_mul_assign(row_col, reduced_row_col, old_pivot_col);
00122   }
00123 }

template<typename M , typename R >
void Parma_Polyhedra_Library::Grid::reduce_reduced ( M &  sys,
dimension_type  dim,
dimension_type  pivot_index,
dimension_type  start,
dimension_type  end,
const Dimension_Kinds dim_kinds,
bool  generators = true 
) [inline, static, private]

Reduce column dim in rows preceding pivot_index in sys.

Required when converting (or simplifying) a congruence or generator system to "strong minimal form"; informally, strong minimal form means that, not only is the system in minimal form (ie a triangular matrix), but also the absolute values of the coefficients of the proper congruences and parameters are minimal. As a simple example, the set of congruences $\{3x \equiv_3 0, 4x + y \equiv_3 1\}$, (which is in minimal form) is equivalent to the set $\{3x \equiv_3 0, x + y \equiv_3 1\}$ (which is in strong minimal form).

Only consider from index start to index end of the row at pivot_index. Flag generators indicates whether sys is a congruence or generator system.

Definition at line 270 of file Grid.templates.hh.

References CON_VIRTUAL, EQUALITY, GEN_VIRTUAL, LINE, PARAMETER, PPL_DIRTY_TEMP_COEFFICIENT, and Parma_Polyhedra_Library::sub_mul_assign().

00276                                             {
00277   R& pivot = sys[pivot_index];
00278 
00279   const Coefficient& pivot_dim = pivot[dim];
00280 
00281   if (pivot_dim == 0)
00282     return;
00283 
00284   PPL_DIRTY_TEMP_COEFFICIENT(pivot_dim_half);
00285   pivot_dim_half = (pivot_dim + 1) / 2;
00286   Dimension_Kind row_kind = dim_kinds[dim];
00287   Dimension_Kind line_or_equality, virtual_kind;
00288   int jump;
00289   if (generators) {
00290     line_or_equality = LINE;
00291     virtual_kind = GEN_VIRTUAL;
00292     jump = -1;
00293   }
00294   else {
00295     line_or_equality = EQUALITY;
00296     virtual_kind = CON_VIRTUAL;
00297     jump = 1;
00298   }
00299 
00300   PPL_DIRTY_TEMP_COEFFICIENT(num_rows_to_subtract);
00301   PPL_DIRTY_TEMP_COEFFICIENT(row_dim_remainder);
00302   for (dimension_type row_index = pivot_index, kinds_index = dim + jump;
00303        row_index-- > 0;
00304        kinds_index += jump) {
00305     // Move over any virtual rows.
00306     while (dim_kinds[kinds_index] == virtual_kind)
00307       kinds_index += jump;
00308 
00309     // row_kind CONGRUENCE is included as PARAMETER
00310     if (row_kind == line_or_equality
00311         || (row_kind == PARAMETER
00312             && dim_kinds[kinds_index] == PARAMETER)) {
00313       R& row = sys[row_index];
00314 
00315       const Coefficient& row_dim = row[dim];
00316       // num_rows_to_subtract may be positive or negative.
00317       num_rows_to_subtract = row_dim / pivot_dim;
00318 
00319       // Ensure that after subtracting num_rows_to_subtract * r_dim
00320       // from row_dim, -pivot_dim_half < row_dim <= pivot_dim_half.
00321       // E.g., if pivot[dim] = 9, then after this reduction
00322       // -5 < row_dim <= 5.
00323       row_dim_remainder = row_dim % pivot_dim;
00324       if (row_dim_remainder < 0) {
00325         if (row_dim_remainder <= -pivot_dim_half)
00326           --num_rows_to_subtract;
00327       }
00328       else if (row_dim_remainder > 0 && row_dim_remainder > pivot_dim_half)
00329         ++num_rows_to_subtract;
00330 
00331       // Subtract num_rows_to_subtract copies of pivot from row i.  Only the
00332       // entries from dim need to be subtracted, as the preceding
00333       // entries are all zero.
00334       // If num_rows_to_subtract is negative, these copies of pivot are
00335       // added to row i.
00336       if (num_rows_to_subtract != 0)
00337         for (dimension_type col = start; col <= end; ++col)
00338           sub_mul_assign(row[col], num_rows_to_subtract, pivot[col]);
00339     }
00340   }
00341 }

void Parma_Polyhedra_Library::Grid::refine_no_check ( const Constraint c  )  [private]

Uses the constraint c to refine *this.

Parameters:
c The constraint to be added. Non-trivial inequalities are ignored.
Warning:
If c and *this are dimension-incompatible, the behavior is undefined.

Definition at line 695 of file Grid_nonpublic.cc.

References add_congruence_no_check(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_inconsistent(), marked_empty(), set_empty(), space_dim, and Parma_Polyhedra_Library::Constraint::space_dimension().

Referenced by refine_with_constraint(), and refine_with_constraints().

00695                                             {
00696   PPL_ASSERT(!marked_empty());
00697   PPL_ASSERT(space_dim >= c.space_dimension());
00698 
00699   if (c.is_equality()) {
00700     Congruence cg(c);
00701     add_congruence_no_check(cg);
00702   }
00703   else if (c.is_inconsistent())
00704     set_empty();
00705 }

void Parma_Polyhedra_Library::Grid::refine_with_congruence ( const Congruence cg  )  [inline]

Uses a copy of the congruence cg to refine *this.

Parameters:
cg The congruence used.
Exceptions:
std::invalid_argument Thrown if *this and congruence cg are dimension-incompatible.

Definition at line 277 of file Grid.inlines.hh.

References add_congruence().

00277                                                  {
00278   add_congruence(cg);
00279 }

void Parma_Polyhedra_Library::Grid::refine_with_congruences ( const Congruence_System cgs  )  [inline]

Uses a copy of the congruences in cgs to refine *this.

Parameters:
cgs The congruences used.
Exceptions:
std::invalid_argument Thrown if *this and cgs are dimension-incompatible.

Definition at line 282 of file Grid.inlines.hh.

References add_congruences().

00282                                                           {
00283   add_congruences(cgs);
00284 }

void Parma_Polyhedra_Library::Grid::refine_with_constraint ( const Constraint c  ) 

Uses a copy of the constraint c to refine *this.

Parameters:
c The constraint used. If it is not an equality, it will be ignored
Exceptions:
std::invalid_argument Thrown if *this and c are dimension-incompatible.

Definition at line 1297 of file Grid_public.cc.

References marked_empty(), refine_no_check(), space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), and throw_dimension_incompatible().

01297                                                    {
01298   // The dimension of `c' must be at most `space_dim'.
01299   if (space_dim < c.space_dimension())
01300     throw_dimension_incompatible("refine_with_constraint(c)", "c", c);
01301   if (marked_empty())
01302     return;
01303   refine_no_check(c);
01304 }

void Parma_Polyhedra_Library::Grid::refine_with_constraints ( const Constraint_System cs  ) 

Uses a copy of the constraints in cs to refine *this.

Parameters:
cs The constraints used. Constraints that are not equalities are ignored.
Exceptions:
std::invalid_argument Thrown if *this and cs are dimension-incompatible.

Definition at line 1307 of file Grid_public.cc.

References Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint_System::end(), marked_empty(), refine_no_check(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), and throw_dimension_incompatible().

01307                                                             {
01308   // The dimension of `cs' must be at most `space_dim'.
01309   if (space_dim < cs.space_dimension())
01310     throw_dimension_incompatible("refine_with_constraints(cs)", "cs", cs);
01311 
01312   for (Constraint_System::const_iterator i = cs.begin(),
01313          cs_end = cs.end(); !marked_empty() && i != cs_end; ++i)
01314     refine_no_check(*i);
01315 }

PPL::Poly_Con_Relation Parma_Polyhedra_Library::Grid::relation_with ( const Constraint c  )  const

Returns the relations holding between *this and c.

Definition at line 578 of file Grid_public.cc.

References Parma_Polyhedra_Library::Grid_Generator_System::begin(), Parma_Polyhedra_Library::Grid_Generator::coefficient(), Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Grid_Generator_System::end(), gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Constraint::is_inconsistent(), Parma_Polyhedra_Library::Grid_Generator::is_line_or_parameter(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Grid_Generator::LINE, marked_empty(), Parma_Polyhedra_Library::Constraint::NONSTRICT_INEQUALITY, Parma_Polyhedra_Library::Grid_Generator::PARAMETER, Parma_Polyhedra_Library::Grid_Generator::POINT, relation_with(), Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), Parma_Polyhedra_Library::Grid_Generator::set_is_parameter(), Parma_Polyhedra_Library::Scalar_Products::sign(), Parma_Polyhedra_Library::Grid_Generator::size(), space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects(), throw_dimension_incompatible(), Parma_Polyhedra_Library::Constraint::type(), and update_generators().

00578                                                 {
00579   // Dimension-compatibility check.
00580   if (space_dim < c.space_dimension())
00581     throw_dimension_incompatible("relation_with(c)", "c", c);
00582 
00583   if (c.is_equality()) {
00584     Congruence cg(c);
00585     return relation_with(cg);
00586   }
00587 
00588   if (marked_empty())
00589     return Poly_Con_Relation::saturates()
00590       &&  Poly_Con_Relation::is_included()
00591       && Poly_Con_Relation::is_disjoint();
00592 
00593   if (space_dim == 0) {
00594     if (c.is_inconsistent())
00595       if (c.is_strict_inequality() && c.inhomogeneous_term() == 0)
00596         // The constraint 0 > 0 implicitly defines the hyperplane 0 = 0;
00597         // thus, the zero-dimensional point also saturates it.
00598         return Poly_Con_Relation::saturates()
00599           && Poly_Con_Relation::is_disjoint();
00600       else
00601         return Poly_Con_Relation::is_disjoint();
00602     else if (c.inhomogeneous_term() == 0)
00603       return Poly_Con_Relation::saturates()
00604         && Poly_Con_Relation::is_included();
00605     else
00606       // The zero-dimensional point saturates
00607       // neither the positivity constraint 1 >= 0,
00608       // nor the strict positivity constraint 1 > 0.
00609       return Poly_Con_Relation::is_included();
00610   }
00611 
00612   if (!generators_are_up_to_date() && !update_generators())
00613     // Updating found the grid empty.
00614     return Poly_Con_Relation::saturates()
00615       && Poly_Con_Relation::is_included()
00616       && Poly_Con_Relation::is_disjoint();
00617 
00618   // Return one of the relations
00619   // 'strictly_intersects'   a strict subset of the grid points satisfy c
00620   // 'is_included'           every grid point satisfies c
00621   // 'is_disjoint'           c and the grid occupy separate spaces.
00622 
00623   // There is always a point.
00624 
00625   bool point_is_included = false;
00626   bool point_saturates = false;
00627   const Grid_Generator* first_point = NULL;
00628 
00629   for (Grid_Generator_System::const_iterator g = gen_sys.begin(),
00630          gen_sys_end = gen_sys.end(); g != gen_sys_end; ++g)
00631     switch (g->type()) {
00632 
00633     case Grid_Generator::POINT:
00634       {
00635         Grid_Generator& gen = const_cast<Grid_Generator&>(*g);
00636         if (first_point == NULL) {
00637           first_point = &gen;
00638           const int sign = Scalar_Products::sign(c, gen);
00639           Constraint::Type type = c.type();
00640           if ((type == Constraint::NONSTRICT_INEQUALITY && sign == 0)) {
00641             point_saturates = true;
00642           }
00643           else if (sign > 0)
00644             point_is_included = true;
00645           break;
00646         }
00647         // Else convert g to a parameter, and continue into the
00648         // parameter case.
00649         gen.set_is_parameter();
00650         const Grid_Generator& first = *first_point;
00651         for (dimension_type i = gen.size() - 1; i-- > 0; )
00652           gen[i] -= first[i];
00653       }
00654 
00655     case Grid_Generator::PARAMETER:
00656     case Grid_Generator::LINE:
00657       Grid_Generator& gen = const_cast<Grid_Generator&>(*g);
00658       if (gen.is_line_or_parameter())
00659         for (dimension_type i = c.space_dimension(); i-- > 0; ) {
00660           Variable v(i);
00661           if (c.coefficient(v) != 0 && gen.coefficient(v) != 0)
00662             return Poly_Con_Relation::strictly_intersects();
00663         }
00664       break;
00665     }
00666 
00667   if (point_saturates)
00668     // Any parameters and lines are also included.
00669     return Poly_Con_Relation::saturates()
00670       && Poly_Con_Relation::is_included();
00671   if (point_is_included)
00672     // Any parameters and lines are also included.
00673     return Poly_Con_Relation::is_included();
00674   return Poly_Con_Relation::is_disjoint();
00675 }

PPL::Poly_Gen_Relation Parma_Polyhedra_Library::Grid::relation_with ( const Generator g  )  const

Returns the relations holding between *this and g.

Definition at line 538 of file Grid_public.cc.

References Parma_Polyhedra_Library::Generator::coefficient(), con_sys, congruences_are_up_to_date(), Parma_Polyhedra_Library::Generator::divisor(), Parma_Polyhedra_Library::Generator::is_closure_point(), Parma_Polyhedra_Library::Generator::is_point(), marked_empty(), Parma_Polyhedra_Library::Poly_Gen_Relation::nothing(), Parma_Polyhedra_Library::Congruence_System::satisfies_all_congruences(), space_dim, Parma_Polyhedra_Library::Generator::space_dimension(), Parma_Polyhedra_Library::Poly_Gen_Relation::subsumes(), throw_dimension_incompatible(), and update_congruences().

00538                                                {
00539   dimension_type g_space_dim = g.space_dimension();
00540 
00541   // Dimension-compatibility check.
00542   if (space_dim < g_space_dim)
00543     throw_dimension_incompatible("relation_with(g)", "g", g);
00544 
00545   // The empty grid cannot subsume a generator.
00546   if (marked_empty())
00547     return Poly_Gen_Relation::nothing();
00548 
00549   // A universe grid in a zero-dimensional space subsumes all the
00550   // generators of a zero-dimensional space.
00551   if (space_dim == 0)
00552     return Poly_Gen_Relation::subsumes();
00553 
00554   if (!congruences_are_up_to_date())
00555     update_congruences();
00556 
00557   Linear_Expression expr;
00558   for (dimension_type i = g_space_dim; i-- > 0; ) {
00559     const Variable v(i);
00560     expr += g.coefficient(v) * v;
00561   }
00562   Grid_Generator gg(grid_point());
00563   if (g.is_point() || g.is_closure_point())
00564     // Points and closure points are converted to grid points.
00565     gg = grid_point(expr, g.divisor());
00566   else
00567     // The generator is a ray or line.
00568     // In both cases, we convert it to a grid line
00569     gg = grid_line(expr);
00570 
00571   return
00572     con_sys.satisfies_all_congruences(gg)
00573     ? Poly_Gen_Relation::subsumes()
00574     : Poly_Gen_Relation::nothing();
00575 }

PPL::Poly_Gen_Relation Parma_Polyhedra_Library::Grid::relation_with ( const Grid_Generator g  )  const

Returns the relations holding between *this and g.

Definition at line 514 of file Grid_public.cc.

References con_sys, congruences_are_up_to_date(), marked_empty(), Parma_Polyhedra_Library::Poly_Gen_Relation::nothing(), Parma_Polyhedra_Library::Congruence_System::satisfies_all_congruences(), space_dim, Parma_Polyhedra_Library::Grid_Generator::space_dimension(), Parma_Polyhedra_Library::Poly_Gen_Relation::subsumes(), throw_dimension_incompatible(), and update_congruences().

00514                                                     {
00515   // Dimension-compatibility check.
00516   if (space_dim < g.space_dimension())
00517     throw_dimension_incompatible("relation_with(g)", "g", g);
00518 
00519   // The empty grid cannot subsume a generator.
00520   if (marked_empty())
00521     return Poly_Gen_Relation::nothing();
00522 
00523   // A universe grid in a zero-dimensional space subsumes all the
00524   // generators of a zero-dimensional space.
00525   if (space_dim == 0)
00526     return Poly_Gen_Relation::subsumes();
00527 
00528   if (!congruences_are_up_to_date())
00529     update_congruences();
00530 
00531   return
00532     con_sys.satisfies_all_congruences(g)
00533     ? Poly_Gen_Relation::subsumes()
00534     : Poly_Gen_Relation::nothing();
00535 }

PPL::Poly_Con_Relation Parma_Polyhedra_Library::Grid::relation_with ( const Congruence cg  )  const

Returns the relations holding between *this and cg.

Definition at line 361 of file Grid_public.cc.

References Parma_Polyhedra_Library::Scalar_Products::assign(), Parma_Polyhedra_Library::Grid_Generator_System::begin(), Parma_Polyhedra_Library::Grid_Generator_System::end(), Parma_Polyhedra_Library::gcd_assign(), gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Congruence::inhomogeneous_term(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Congruence::is_proper_congruence(), Parma_Polyhedra_Library::Grid_Generator::LINE, marked_empty(), Parma_Polyhedra_Library::Congruence::modulus(), Parma_Polyhedra_Library::Grid_Generator::PARAMETER, Parma_Polyhedra_Library::Grid_Generator::POINT, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), space_dim, Parma_Polyhedra_Library::Congruence::space_dimension(), Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects(), throw_dimension_incompatible(), and update_generators().

Referenced by difference_assign(), limited_congruence_extrapolation_assign(), limited_extrapolation_assign(), limited_generator_extrapolation_assign(), relation_with(), and simplify_using_context_assign().

00361                                                  {
00362   // Dimension-compatibility check.
00363   if (space_dim < cg.space_dimension())
00364     throw_dimension_incompatible("relation_with(cg)", "cg", cg);
00365 
00366   if (marked_empty())
00367     return Poly_Con_Relation::saturates()
00368       && Poly_Con_Relation::is_included()
00369       && Poly_Con_Relation::is_disjoint();
00370 
00371   if (space_dim == 0) {
00372     if (cg.is_inconsistent())
00373       return Poly_Con_Relation::is_disjoint();
00374     else if (cg.is_equality())
00375       return Poly_Con_Relation::saturates()
00376         && Poly_Con_Relation::is_included();
00377     else if (cg.inhomogeneous_term() % cg.modulus() == 0)
00378       return Poly_Con_Relation::saturates()
00379         && Poly_Con_Relation::is_included();
00380   }
00381 
00382   if (!generators_are_up_to_date() && !update_generators())
00383     // Updating found the grid empty.
00384     return Poly_Con_Relation::saturates()
00385       && Poly_Con_Relation::is_included()
00386       && Poly_Con_Relation::is_disjoint();
00387 
00388   // Return one of the relations
00389   // 'strictly_intersects'   a strict subset of the grid points satisfy cg
00390   // 'is_included'           every grid point satisfies cg
00391   // 'is_disjoint'           cg and the grid occupy separate spaces.
00392 
00393   // There is always a point.
00394 
00395   // Scalar product of the congruence and the first point that
00396   // satisfies the congruence.
00397   PPL_DIRTY_TEMP_COEFFICIENT(point_sp);
00398   point_sp = 0;
00399 
00400   const Coefficient& modulus = cg.modulus();
00401 
00402   PPL_DIRTY_TEMP_COEFFICIENT(div);
00403   div = modulus;
00404 
00405   PPL_DIRTY_TEMP_COEFFICIENT(sp);
00406 
00407   bool known_to_intersect = false;
00408 
00409   for (Grid_Generator_System::const_iterator g = gen_sys.begin(),
00410          gen_sys_end = gen_sys.end(); g != gen_sys_end; ++g) {
00411     Scalar_Products::assign(sp, cg, *g);
00412 
00413     switch (g->type()) {
00414 
00415     case Grid_Generator::POINT:
00416       if (cg.is_proper_congruence())
00417         sp %= div;
00418       if (sp == 0)
00419         // The point satisfies the congruence.
00420         if (point_sp == 0)
00421           // Any previous points satisfied the congruence.
00422           known_to_intersect = true;
00423         else
00424           return Poly_Con_Relation::strictly_intersects();
00425       else
00426         if (point_sp == 0) {
00427           if (known_to_intersect)
00428             return Poly_Con_Relation::strictly_intersects();
00429           // Assign `sp' to `point_sp' as `sp' is the scalar product
00430           // of cg and a point g and is non-zero.
00431           point_sp = sp;
00432         }
00433         else {
00434           // A previously considered point p failed to satisfy cg such that
00435           // `point_sp' = `scalar_prod(p, cg)'
00436           // so, if we consider the parameter g-p instead of g, we have
00437           // scalar_prod(g-p, cg) = scalar_prod(g, cg) - scalar_prod(p, cg)
00438           //                      = sp - point_sp
00439           sp -= point_sp;
00440 
00441           if (sp != 0) {
00442             // Find the GCD between sp and the previous GCD.
00443             gcd_assign(div, div, sp);
00444             if (point_sp % div == 0)
00445               // There is a point in the grid satisfying cg.
00446               return Poly_Con_Relation::strictly_intersects();
00447           }
00448         }
00449       break;
00450 
00451     case Grid_Generator::PARAMETER:
00452       if (cg.is_proper_congruence())
00453         sp %= (div * g->divisor());
00454       if (sp == 0)
00455         // Parameter g satisfies the cg so the relation depends
00456         // entirely on the other generators.
00457         break;
00458 
00459       if (known_to_intersect)
00460         // At least one point satisfies cg.  However, the sum of such
00461         // a point and the parameter g fails to satisfy cg (due to g).
00462         return Poly_Con_Relation::strictly_intersects();
00463 
00464       // Find the GCD between sp and the previous GCD.
00465       gcd_assign(div, div, sp);
00466       if (point_sp != 0)
00467         // At least one of any previously encountered points fails to
00468         // satisfy cg.
00469         if (point_sp % div == 0)
00471           // There is also a grid point that satisfies cg.
00472           return Poly_Con_Relation::strictly_intersects();
00473 
00474       break;
00475 
00476     case Grid_Generator::LINE:
00477       if (sp == 0)
00478         // Line g satisfies the cg so the relation depends entirely on
00479         // the other generators.
00480         break;
00481 
00482       // Line g intersects the congruence.
00483       //
00484       // There is a point p in the grid.  Suppose <p*cg> = p_sp.  Then
00485       // (-p_sp/sp)*g + p is a point that satisfies cg: <((-p_sp/sp)*g
00486       // + p).cg> = -(p_sp/sp)*sp + p_sp) = 0.  If p does not satisfy
00487       // `cg' and hence is not in the grid defined by `cg', the grid
00488       // `*this' strictly intersects the `cg' grid.  On the other
00489       // hand, if `p' is in the grid defined by `cg' so that p_sp = 0,
00490       // then <p+g.cg> = p_sp + sp != 0; thus `p+g' is a point in
00491       // *this that does not satisfy `cg' and hence `p+g' is a point
00492       // in *this not in the grid defined by `cg'; therefore `*this'
00493       // strictly intersects the `cg' grid.
00494 
00495       return Poly_Con_Relation::strictly_intersects();
00496     }
00497   }
00498 
00499   if (point_sp == 0) {
00500     if (cg.is_equality())
00501       // Every generator satisfied the cg.
00502       return Poly_Con_Relation::is_included()
00503         && Poly_Con_Relation::saturates();
00504     else
00505       // Every generator satisfied the cg.
00506       return Poly_Con_Relation::is_included();
00507   }
00508 
00509   PPL_ASSERT(!known_to_intersect);
00510   return Poly_Con_Relation::is_disjoint();
00511 }

void Parma_Polyhedra_Library::Grid::remove_higher_space_dimensions ( dimension_type  new_dimension  ) 

Removes the higher dimensions of the vector space so that the resulting space will have dimension new_dimension..

Exceptions:
std::invalid_argument Thrown if new_dimensions is greater than the space dimension of *this.

Definition at line 306 of file Grid_chdims.cc.

References clear_congruences_up_to_date(), clear_generators_up_to_date(), con_sys, CON_VIRTUAL, congruences_are_minimized(), dim_kinds, Parma_Polyhedra_Library::Matrix::erase_to_end(), Parma_Polyhedra_Library::Grid_Generator_System::erase_to_end(), gen_sys, GEN_VIRTUAL, generators_are_minimized(), generators_are_up_to_date(), Parma_Polyhedra_Library::Congruence_System::increase_space_dimension(), is_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), OK(), Parma_Polyhedra_Library::Congruence_System::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Grid_Generator_System::remove_higher_space_dimensions(), set_empty(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Grid_Generator_System::swap(), Parma_Polyhedra_Library::swap(), Parma_Polyhedra_Library::Congruence_System::swap(), throw_dimension_incompatible(), Parma_Polyhedra_Library::Grid_Generator_System::unset_pending_rows(), and Parma_Polyhedra_Library::Congruence::zero_dim_false().

Referenced by generalized_affine_image(), and generalized_affine_preimage().

00306                                                                           {
00307   // Dimension-compatibility check.
00308   if (new_dimension > space_dim)
00309     throw_dimension_incompatible("remove_higher_space_dimensions(nd)",
00310                                  new_dimension);
00311 
00312   // The removal of no dimensions from any grid is a no-op.
00313   // Note that this case also captures the only legal removal of
00314   // dimensions from a grid in a 0-dim space.
00315   if (new_dimension == space_dim) {
00316     PPL_ASSERT(OK());
00317     return;
00318   }
00319 
00320   if (is_empty()) {
00321     // Removing dimensions from the empty grid just updates the space
00322     // dimension.
00323     space_dim = new_dimension;
00324     set_empty();
00325     PPL_ASSERT(OK());
00326     return;
00327   }
00328 
00329   if (new_dimension == 0) {
00330     // Removing all dimensions from a non-empty grid just returns the
00331     // zero-dimensional universe grid.
00332     set_zero_dim_univ();
00333     return;
00334   }
00335 
00336   // Favor the generators, as is done by is_empty().
00337   if (generators_are_up_to_date()) {
00338     gen_sys.remove_higher_space_dimensions(new_dimension);
00339     if (generators_are_minimized()) {
00340       // Count the actual number of rows that are now redundant.
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         // Chop zero rows from end of system, to keep minimal form.
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       // TODO: Consider if it is worth also preserving the congruences
00352       //       if they are also in minimal form.
00353     }
00354     clear_congruences_up_to_date();
00355     // Extend the zero dim false congruence system to the appropriate
00356     // dimension and then swap it with `con_sys'.
00357     Congruence_System cgs(Congruence::zero_dim_false());
00358     // Extra 2 columns for inhomogeneous term and modulus.
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     // Count the actual number of rows that are now redundant.
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       // Shuffle the remaining rows upwards.
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       // Chop newly redundant rows from end of system, to keep minimal
00377       // form.
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     // Replace gen_sys with an empty system of the right dimension.
00383     // Extra 2 columns for inhomogeneous term and modulus.
00384     Grid_Generator_System gs(new_dimension + 2);
00385     gen_sys.swap(gs);
00386   }
00387 
00388   // Update the space dimension.
00389   space_dim = new_dimension;
00390 
00391   PPL_ASSERT(OK(true));
00392 }

void Parma_Polyhedra_Library::Grid::remove_space_dimensions ( const Variables_Set vars  ) 

Removes all the specified dimensions from the vector space.

Parameters:
vars The set of Variable objects corresponding to the space dimensions to be removed.
Exceptions:
std::invalid_argument Thrown if *this is dimension-incompatible with one of the Variable objects contained in vars.

Definition at line 262 of file Grid_chdims.cc.

References clear_congruences_up_to_date(), clear_generators_minimized(), gen_sys, generators_are_up_to_date(), marked_empty(), OK(), Parma_Polyhedra_Library::Grid_Generator_System::remove_space_dimensions(), set_empty(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Variables_Set::space_dimension(), throw_dimension_incompatible(), and update_generators().

Referenced by fold_space_dimensions().

00262                                                           {
00263   // The removal of no dimensions from any grid is a no-op.  This case
00264   // also captures the only legal removal of dimensions from a grid in
00265   // a 0-dim space.
00266   if (vars.empty()) {
00267     PPL_ASSERT(OK());
00268     return;
00269   }
00270 
00271   // Dimension-compatibility check.
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     // Update the space dimension.
00281     space_dim = new_space_dim;
00282     set_empty();
00283     PPL_ASSERT(OK());
00284     return;
00285   }
00286 
00287   // Removing _all_ dimensions from a non-empty grid obtains the
00288   // zero-dimensional universe grid.
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   // Update the space dimension.
00300   space_dim = new_space_dim;
00301 
00302   PPL_ASSERT(OK(true));
00303 }

template<typename M , typename R >
bool Parma_Polyhedra_Library::Grid::rows_are_zero ( M &  system,
dimension_type  first,
dimension_type  last,
dimension_type  row_size 
) [inline, static, private]

Checks that trailing rows contain only zero terms.

If all columns contain zero in the rows of system from row index first to row index last then return true, else return false. row_size gives the number of columns in each row.

This method is only used in assertions in the simplify methods.

Definition at line 238 of file Grid_simplify.cc.

00239                                                                   {
00240   while (first <= last) {
00241     const R& row = system[first++];
00242     for (dimension_type col = 0; col < row_size; ++col)
00243       if (row[col] != 0)
00244         return false;
00245   }
00246   return true;
00247 }

void Parma_Polyhedra_Library::Grid::select_wider_congruences ( const Grid y,
Congruence_System selected_cgs 
) const [private]

Copies a widened selection of congruences from y to selected_cgs.

Definition at line 35 of file Grid_widenings.cc.

References con_sys, CON_VIRTUAL, congruences_are_minimized(), dim_kinds, EQUALITY, Parma_Polyhedra_Library::Congruence_System::insert(), Parma_Polyhedra_Library::Congruence::is_equal_at_dimension(), marked_empty(), PROPER_CONGRUENCE, space_dim, and Parma_Polyhedra_Library::Congruence_System::space_dimension().

Referenced by congruence_widening_assign().

00036                                                                            {
00037   // Private method: the caller must ensure the following conditions
00038   // (beside the inclusion `y <= x').
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   // Note: row counters start at 0, to preserve the original order in
00046   // the selected congruences.
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           // The leading diagonal entries are equal.
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 }

void Parma_Polyhedra_Library::Grid::select_wider_generators ( const Grid y,
Grid_Generator_System widened_ggs 
) const [private]

Copies widened generators from y to widened_ggs.

Definition at line 230 of file Grid_widenings.cc.

References Parma_Polyhedra_Library::Grid_Generator::coefficient(), dim_kinds, gen_sys, GEN_VIRTUAL, generators_are_minimized(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), Parma_Polyhedra_Library::Grid_Generator::is_equal_at_dimension(), LINE, marked_empty(), PARAMETER, space_dim, Parma_Polyhedra_Library::Grid_Generator::space_dimension(), and Parma_Polyhedra_Library::Grid_Generator_System::space_dimension().

Referenced by generator_widening_assign().

00231                                                                               {
00232   // Private method: the caller must ensure the following conditions
00233   // (beside the inclusion `y <= x').
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   // Note: row counters start at 0, to preserve the original order in
00241   // the selected generators.
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           // The leading diagonal entry is equal.
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 }

void Parma_Polyhedra_Library::Grid::set_congruences_minimized (  )  [inline, private]
void Parma_Polyhedra_Library::Grid::set_congruences_up_to_date (  )  [inline, private]

Sets status to express that congruences are up-to-date.

Definition at line 65 of file Grid.inlines.hh.

References Parma_Polyhedra_Library::Grid::Status::set_c_up_to_date(), and status.

Referenced by add_congruence_no_check(), construct(), Grid(), and set_congruences_minimized().

00065                                  {
00066   status.set_c_up_to_date();
00067 }

void Parma_Polyhedra_Library::Grid::set_empty (  )  [private]

Sets status to express that the grid is empty, clearing all corresponding matrices.

Definition at line 449 of file Grid_nonpublic.cc.

References con_sys, gen_sys, Parma_Polyhedra_Library::Congruence_System::increase_space_dimension(), Parma_Polyhedra_Library::Grid::Status::set_empty(), space_dim, status, swap(), Parma_Polyhedra_Library::Grid_Generator_System::swap(), and Parma_Polyhedra_Library::Congruence::zero_dim_false().

Referenced by add_congruence_no_check(), add_constraint_no_check(), add_recycled_congruences(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), concatenate_assign(), congruence_widening_assign(), difference_assign(), Grid(), intersection_assign(), is_empty(), map_space_dimensions(), minimized_congruences(), operator=(), refine_no_check(), remove_higher_space_dimensions(), remove_space_dimensions(), time_elapse_assign(), update_generators(), and wrap_assign().

00449                    {
00450   status.set_empty();
00451 
00452   // Replace gen_sys with an empty system of the right dimension.
00453   Grid_Generator_System gs(space_dim);
00454   gen_sys.swap(gs);
00455 
00456   // Extend the zero dim false congruence system to the appropriate
00457   // dimension and then swap it with `con_sys'.
00458   Congruence_System cgs(Congruence::zero_dim_false());
00459   cgs.increase_space_dimension(space_dim);
00460   const_cast<Congruence_System&>(con_sys).swap(cgs);
00461 }

void Parma_Polyhedra_Library::Grid::set_generators_minimized (  )  [inline, private]
void Parma_Polyhedra_Library::Grid::set_generators_up_to_date (  )  [inline, private]

Sets status to express that generators are up-to-date.

Definition at line 60 of file Grid.inlines.hh.

References Parma_Polyhedra_Library::Grid::Status::set_g_up_to_date(), and status.

Referenced by add_grid_generator(), add_recycled_grid_generators(), construct(), Grid(), and set_generators_minimized().

00060                                 {
00061   status.set_g_up_to_date();
00062 }

void Parma_Polyhedra_Library::Grid::set_zero_dim_univ (  )  [private]
void Parma_Polyhedra_Library::Grid::simplify ( Grid_Generator_System gs,
Dimension_Kinds dim_kinds 
) [static, private]

Converts gs to lower triangular (i.e. minimized) form.

Expects gs to contain at least one point.

Definition at line 251 of file Grid_simplify.cc.

References GEN_VIRTUAL, Parma_Polyhedra_Library::Matrix::has_no_rows(), Parma_Polyhedra_Library::Grid_Generator::is_line(), Parma_Polyhedra_Library::Grid_Generator::is_parameter_or_point(), LINE, Parma_Polyhedra_Library::Grid_Generator::negate(), Parma_Polyhedra_Library::Grid_Generator_System::num_columns(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), Parma_Polyhedra_Library::Grid_Generator_System::OK(), PARAMETER, reduce_line_with_line(), reduce_parameter_with_line(), reduce_pc_with_pc(), swap(), and Parma_Polyhedra_Library::Grid_Generator_System::unset_pending_rows().

00251                                                                      {
00252   PPL_ASSERT(!sys.has_no_rows());
00253   // For reduce_pc_with_pc.
00254   PPL_ASSERT(sys.num_columns() > 0);
00255 
00256   // Changes here may also be required in the congruence version
00257   // below.
00258 
00259   // Subtract one to allow for the parameter divisor column
00260   const dimension_type num_columns = sys.num_columns() - 1;
00261 
00262   if (dim_kinds.size() != num_columns)
00263     dim_kinds.resize(num_columns);
00264 
00265   const dimension_type num_rows = sys.num_rows();
00266 
00267   // For each dimension `dim' move or construct a row into position
00268   // `pivot_index' such that the row has zero in all elements
00269   // following column `dim' and a value other than zero in column
00270   // `dim'.
00271   dimension_type pivot_index = 0;
00272   for (dimension_type dim = 0; dim < num_columns; ++dim) {
00273     // Consider the pivot and following rows.
00274     dimension_type row_index = pivot_index;
00275 
00276     // Move down over rows which have zero in column `dim'.
00277     while (row_index < num_rows && sys[row_index][dim] == 0)
00278       ++row_index;
00279 
00280     if (row_index == num_rows)
00281       // Element in column `dim' is zero in all rows from the pivot.
00282       dim_kinds[dim] = GEN_VIRTUAL;
00283     else {
00284       if (row_index != pivot_index)
00285         std::swap(sys[row_index], sys[pivot_index]);
00286       Grid_Generator& pivot = sys[pivot_index];
00287       bool pivot_is_line = pivot.is_line();
00288 
00289       // Change the matrix so that the value at `dim' in every row
00290       // following `pivot_index' is 0, leaving an equivalent grid.
00291       while (row_index < num_rows - 1) {
00292         ++row_index;
00293 
00294         Grid_Generator& row = sys[row_index];
00295 
00296         if (row[dim] == 0)
00297           continue;
00298 
00299         if (row.is_line())
00300           if (pivot_is_line)
00301             reduce_line_with_line(row, pivot, dim);
00302           else {
00303             PPL_ASSERT(pivot.is_parameter_or_point());
00304             std::swap(row, pivot);
00305             pivot_is_line = true;
00306             reduce_parameter_with_line(row, pivot, dim, sys);
00307           }
00308         else {
00309           PPL_ASSERT(row.is_parameter_or_point());
00310           if (pivot_is_line)
00311             reduce_parameter_with_line(row, pivot, dim, sys);
00312           else {
00313             PPL_ASSERT(pivot.is_parameter_or_point());
00314             reduce_pc_with_pc(row, pivot, dim, dim + 1, num_columns);
00315           }
00316         }
00317       }
00318 
00319       if (pivot_is_line)
00320         dim_kinds[dim] = LINE;
00321       else {
00322         PPL_ASSERT(pivot.is_parameter_or_point());
00323         dim_kinds[dim] = PARAMETER;
00324       }
00325 
00326       // Since we are reducing the system to "strong minimal form",
00327       // ensure that a positive value follows the leading zeros.
00328       if (pivot[dim] < 0)
00329         pivot.negate(dim, num_columns - 1);
00330 
00331       // Factor this row out of the preceding rows.
00332       reduce_reduced<Grid_Generator_System, Grid_Generator>
00333         (sys, dim, pivot_index, dim, num_columns - 1, dim_kinds);
00334 
00335       ++pivot_index;
00336     }
00337   }
00338 
00339   // Clip any zero rows from the end of the matrix.
00340   if (num_rows > pivot_index) {
00341 #ifndef NDEBUG
00342     const bool ret = rows_are_zero<Grid_Generator_System, Grid_Generator>
00343       (sys,
00344        // index of first
00345        pivot_index,
00346        // index of last
00347        sys.num_rows() - 1,
00348        // row size
00349        sys.num_columns() - 1);
00350     PPL_ASSERT(ret == true);
00351 #endif
00352     sys.erase_to_end(pivot_index);
00353   }
00354 
00355   sys.unset_pending_rows();
00356 
00357   // Ensure that the parameter divisors are the same as the system
00358   // divisor.
00359   const Coefficient& system_divisor = sys[0][0];
00360   for (dimension_type row = sys.num_rows() - 1,
00361          dim = sys.num_columns() - 2;
00362        dim > 0; --dim)
00363     switch (dim_kinds[dim]) {
00364     case PARAMETER:
00365       sys[row].set_divisor(system_divisor);
00366     case LINE:
00367       --row;
00368     case GEN_VIRTUAL:
00369       break;
00370     }
00371 
00372   PPL_ASSERT(sys.OK());
00373 }

bool Parma_Polyhedra_Library::Grid::simplify ( Congruence_System cgs,
Dimension_Kinds dim_kinds 
) [static, private]

Converts cgs to upper triangular (i.e. minimized) form.

Returns true if cgs represents the empty set, otherwise returns false.

Definition at line 376 of file Grid_simplify.cc.

References Parma_Polyhedra_Library::Matrix::add_zero_rows(), CON_VIRTUAL, EQUALITY, Parma_Polyhedra_Library::Matrix::erase_to_end(), Parma_Polyhedra_Library::Congruence::inhomogeneous_term(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Congruence::is_proper_congruence(), Parma_Polyhedra_Library::Congruence::modulus(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, Parma_Polyhedra_Library::Congruence::negate(), Parma_Polyhedra_Library::Congruence_System::normalize_moduli(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Congruence_System::OK(), PROPER_CONGRUENCE, Parma_Polyhedra_Library::Linear_Row::RAY_OR_POINT_OR_INEQUALITY, reduce_congruence_with_equality(), reduce_equality_with_equality(), reduce_pc_with_pc(), Parma_Polyhedra_Library::Matrix::rows, Parma_Polyhedra_Library::Congruence::set_is_equality(), and swap().

Referenced by congruence_widening_assign(), generator_widening_assign(), Parma_Polyhedra_Library::Grid_Certificate::Grid_Certificate(), is_empty(), max_min(), minimize(), minimized_congruences(), minimized_grid_generators(), OK(), and update_generators().

00376                                                                  {
00377   PPL_ASSERT(sys.num_columns() > 2);
00378 
00379   // Changes here may also be required in the generator version above.
00380 
00381   // TODO: Consider normalizing the moduli only when congruences are
00382   //       added to con_sys.
00383   sys.normalize_moduli();
00384 
00385   const dimension_type num_columns = sys.num_columns() - 1 /* modulus */;
00386 
00387   if (dim_kinds.size() != num_columns)
00388     dim_kinds.resize(num_columns);
00389 
00390   const dimension_type num_rows = sys.num_rows();
00391 
00392   // For each dimension `dim' move or construct a row into position
00393   // `pivot_index' such that the row has a value of zero in all
00394   // elements preceding column `dim' and some other value in column
00395   // `dim'.
00396   dimension_type pivot_index = 0;
00397   for (dimension_type dim = num_columns; dim-- > 0; ) {
00398     // Consider the pivot and following rows.
00399     dimension_type row_index = pivot_index;
00400 
00401     // Move down over rows which have zero in column `dim'.
00402     while (row_index < num_rows && sys[row_index][dim] == 0)
00403       ++row_index;
00404 
00405     if (row_index == num_rows)
00406       // Element in column `dim' is zero in all rows from the pivot,
00407       // or `sys' is empty of rows.
00408       dim_kinds[dim] = CON_VIRTUAL;
00409     else {
00410       // row_index != num_rows
00411       if (row_index != pivot_index)
00412         std::swap(sys[row_index], sys[pivot_index]);
00413       Congruence& pivot = sys[pivot_index];
00414       bool pivot_is_equality = pivot.is_equality();
00415 
00416       // Change the matrix so that the value at `dim' in every row
00417       // following `pivot_index' is 0, leaving an equivalent grid.
00418       while (row_index < num_rows - 1) {
00419         ++row_index;
00420 
00421         Congruence& row = sys[row_index];
00422 
00423         if (row[dim] == 0)
00424           continue;
00425 
00426         if (row.is_equality())
00427           if (pivot_is_equality)
00428             reduce_equality_with_equality(row, pivot, dim);
00429           else {
00430             PPL_ASSERT(pivot.is_proper_congruence());
00431             std::swap(row, pivot);
00432             pivot_is_equality = true;
00433             reduce_congruence_with_equality(row, pivot, dim, sys);
00434           }
00435         else {
00436           PPL_ASSERT(row.is_proper_congruence());
00437           if (pivot_is_equality)
00438             reduce_congruence_with_equality(row, pivot, dim, sys);
00439           else {
00440             PPL_ASSERT(pivot.is_proper_congruence());
00441             reduce_pc_with_pc(row, pivot, dim, 0, dim);
00442           }
00443         }
00444       }
00445 
00446       if (pivot_is_equality)
00447         dim_kinds[dim] = EQUALITY;
00448       else {
00449         PPL_ASSERT(pivot.is_proper_congruence());
00450         dim_kinds[dim] = PROPER_CONGRUENCE;
00451       }
00452 
00453       // Since we are reducing the system to "strong minimal form",
00454       // ensure that a positive value follows the leading zeros.
00455       if (pivot[dim] < 0)
00456         pivot.negate(0, dim);
00457       // Factor this row out of the preceding ones.
00458       reduce_reduced<Congruence_System, Congruence>
00459         (sys, dim, pivot_index, 0, dim, dim_kinds, false);
00460 
00461       ++pivot_index;
00462     }
00463   } // end for (dimension_type dim = num_columns; dim-- > 0; )
00464 
00465   // For clearer naming.
00466   dimension_type& reduced_num_rows = pivot_index;
00467 
00468   if (reduced_num_rows > 0) {
00469     // If the last row is false then make it the equality 1 = 0, and
00470     // make it the only row.
00471     Congruence& last_row = sys[reduced_num_rows - 1];
00472     if (dim_kinds[0] == PROPER_CONGRUENCE) {
00473       if (last_row.inhomogeneous_term() % last_row.modulus() != 0) {
00474         // The last row is a false proper congruence.
00475         last_row.set_is_equality();
00476         dim_kinds[0] = EQUALITY;
00477         goto return_empty;
00478       }
00479     }
00480     else if (dim_kinds[0] == EQUALITY) {
00481       // The last row is a false equality, as all the coefficient terms
00482       // are zero while the inhomogeneous term (as a result of the
00483       // reduced form) is some other value.
00484     return_empty:
00485       last_row[0] = 1;
00486       dim_kinds.resize(1);
00487       std::swap(sys.rows[0], sys.rows.back());
00488       sys.erase_to_end(1);
00489 
00490       PPL_ASSERT(sys.OK());
00491       return true;
00492     }
00493   }
00494   else {
00495     // Either sys is empty (it defines the universe) or every column
00496     // before the modulus column contains only zeroes.
00497 
00498     // Set up the integrality congruence.
00499     dim_kinds[0] = PROPER_CONGRUENCE;
00500     if (num_rows == 0) {
00501       sys.add_zero_rows(1,
00502                         Linear_Row::Flags(NECESSARILY_CLOSED,
00503                                           Linear_Row::RAY_OR_POINT_OR_INEQUALITY));
00504       Congruence& cg = sys[0];
00505       cg[num_columns] = 1;
00506       cg[0] = 1;
00507 
00508       PPL_ASSERT(sys.OK());
00509       return false;
00510     }
00511     sys[0][num_columns] = 1;
00512     // Ensure that, after any zero row clipping below, a single row
00513     // will remain for the integrality congruence.
00514     reduced_num_rows = 1;
00515   }
00516 
00517   // Clip any zero rows from the end of the matrix.
00518   if (num_rows > 1 && num_rows > reduced_num_rows) {
00519 #ifndef NDEBUG
00520     const bool ret = rows_are_zero<Congruence_System, Congruence>
00521       (sys,
00522        // index of first
00523        reduced_num_rows,
00524        // index of last
00525        num_rows - 1,
00526        // row size
00527        num_columns);
00528     PPL_ASSERT(ret == true);
00529 #endif
00530     sys.erase_to_end(reduced_num_rows);
00531   }
00532 
00533   PPL_ASSERT(sys.num_rows() == reduced_num_rows);
00534 
00535   // Ensure that the last row is the integrality congruence.
00536   const dimension_type mod_index = num_columns;
00537   if (dim_kinds[0] == CON_VIRTUAL) {
00538     // The last row is virtual, append the integrality congruence.
00539     dim_kinds[0] = PROPER_CONGRUENCE;
00540     sys.add_zero_rows(1,
00541                       Linear_Row::Flags(NECESSARILY_CLOSED,
00542                                         Linear_Row::RAY_OR_POINT_OR_INEQUALITY));
00543     Congruence& new_last_row = sys[reduced_num_rows];
00544     new_last_row[mod_index] = 1;
00545     // Try use an existing modulus.
00546     dimension_type row_index = reduced_num_rows;
00547     while (row_index-- > 0) {
00548       Congruence& row = sys[row_index];
00549       if (row[mod_index] > 0) {
00550         new_last_row[mod_index] = row[mod_index];
00551         break;
00552       }
00553     }
00554     new_last_row[0] = new_last_row[mod_index];
00555     // Since we are reducing the system to "strong minimal form",
00556     // increment the number of reduced rows.
00557     ++reduced_num_rows;
00558   }
00559   else {
00560     Congruence& last_row = sys[reduced_num_rows - 1];
00561     last_row[0] = last_row[mod_index];
00562   }
00563 
00564   // Since we are reducing the system to "strong minimal form",
00565   // factor the modified integrality congruence out of the other rows;
00566   reduce_reduced<Congruence_System, Congruence>
00567     (sys, 0, reduced_num_rows - 1, 0, 0, dim_kinds, false);
00568 
00569   PPL_ASSERT(sys.OK());
00570   return false;
00571 }

bool Parma_Polyhedra_Library::Grid::simplify_using_context_assign ( const Grid y  ) 

Assigns to *this a meet-preserving simplification of *this with respect to y. If false is returned, then the intersection is empty.

Exceptions:
std::invalid_argument Thrown if *this and y are topology-incompatible or dimension-incompatible.

Definition at line 1568 of file Grid_public.cc.

References add_congruence(), add_congruences(), add_recycled_congruences(), add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Scalar_Products::assign(), Parma_Polyhedra_Library::Grid_Generator_System::begin(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), con_sys, congruences_are_minimized(), congruences_are_up_to_date(), Parma_Polyhedra_Library::Grid_Generator::divisor(), Parma_Polyhedra_Library::Grid_Generator_System::end(), gen_sys, generators_are_minimized(), Parma_Polyhedra_Library::Poly_Con_Relation::implies(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Congruence_System::insert(), is_empty(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), is_included_in(), Parma_Polyhedra_Library::Grid_Generator::is_parameter(), Parma_Polyhedra_Library::Grid_Generator::is_point(), Parma_Polyhedra_Library::Congruence::is_proper_congruence(), Parma_Polyhedra_Library::Congruence::is_tautological(), Parma_Polyhedra_Library::Checked::le, minimize(), Parma_Polyhedra_Library::Congruence::modulus(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), PPL_DIRTY_TEMP_COEFFICIENT, relation_with(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), swap(), throw_dimension_incompatible(), and Parma_Polyhedra_Library::UNIVERSE.

01568                                                     {
01569   Grid& x = *this;
01570   // Dimension-compatibility check.
01571   if (x.space_dim != y.space_dim)
01572     throw_dimension_incompatible("simplify_using_context_assign(y)", "y", y);
01573 
01574   // Filter away the zero-dimensional case.
01575   if (x.space_dim == 0) {
01576     if (y.is_empty()) {
01577       set_zero_dim_univ();
01578       PPL_ASSERT(OK());
01579       return false;
01580     }
01581     else
01582       return !x.is_empty();
01583   }
01584 
01585   // If `y' is empty, the biggest enlargement for `x' is the universe.
01586   if (!y.minimize()) {
01587     Grid gr(x.space_dim, UNIVERSE);
01588     swap(gr);
01589     return false;
01590   }
01591 
01592   // If `x' is empty, the intersection is empty.
01593   if (!x.minimize()) {
01594     // Search for a congruence of `y' that is not a tautology.
01595     PPL_ASSERT(y.congruences_are_up_to_date());
01596     Grid gr(x.space_dim, UNIVERSE);
01597     for (dimension_type i = y.con_sys.num_rows(); i-- > 0; ) {
01598       const Congruence& y_con_sys_i = y.con_sys[i];
01599       if (!y_con_sys_i.is_tautological()) {
01600         // Found: we obtain a congruence `c' contradicting the one we
01601         // found, and assign to `x' the grid `gr' with `c' as
01602         // the only congruence.
01603         const Linear_Expression le(y_con_sys_i);
01604         if (y_con_sys_i.is_equality()) {
01605           gr.refine_no_check(le == 1);
01606           break;
01607         }
01608         else {
01609           const Coefficient& y_modulus_i = y_con_sys_i.modulus();
01610           if (y_modulus_i > 1)
01611             gr.refine_no_check(le == 1);
01612           else {
01613             Linear_Expression le2;
01614             for (dimension_type j = le.space_dimension(); j-- > 0; )
01615               le2 += 2 * le.coefficient(Variable(j)) * Variable(j);
01616             le2 += 2 * le.inhomogeneous_term();
01617             gr.refine_no_check(le2 == y_modulus_i);
01618           }
01619           break;
01620         }
01621       }
01622     }
01623     swap(gr);
01624     PPL_ASSERT(OK());
01625     return false;
01626   }
01627 
01628   PPL_ASSERT(x.congruences_are_minimized()
01629          && y.generators_are_minimized());
01630 
01631   const Congruence_System& x_cs = x.con_sys;
01632   const dimension_type x_cs_num_rows = x_cs.num_rows();
01633   const Grid_Generator_System& y_gs = y.gen_sys;
01634 
01635   // Record into `redundant_by_y' the info about which congruences of
01636   // `x' are redundant in the context `y'.  Count the number of
01637   // redundancies found.
01638   std::vector<bool> redundant_by_y(x_cs_num_rows, false);
01639   dimension_type num_redundant_by_y = 0;
01640   for (dimension_type i = 0; i < x_cs_num_rows; ++i)
01641     if (y.relation_with(x_cs[i])
01642         .implies(Poly_Con_Relation::is_included())) {
01643       redundant_by_y[i] = true;
01644       ++num_redundant_by_y;
01645     }
01646 
01647   if (num_redundant_by_y < x_cs_num_rows) {
01648 
01649     // Some congruences were not identified as redundant.
01650 
01651     Congruence_System result_cs;
01652     const Congruence_System& y_cs = y.con_sys;
01653     const dimension_type y_cs_num_rows = y_cs.num_rows();
01654     // Compute into `z' the intersection of `x' and `y'.
01655     const bool x_first = (x_cs_num_rows > y_cs_num_rows);
01656     Grid z(x_first ? x : y);
01657     if (x_first)
01658       z.add_congruences(y_cs);
01659     else {
01660       // Only copy (and then recycle) the non-redundant congruences.
01661       Congruence_System tmp_cs;
01662       for (dimension_type i = 0; i < x_cs_num_rows; ++i) {
01663         if (!redundant_by_y[i])
01664           tmp_cs.insert(x_cs[i]);
01665       }
01666       z.add_recycled_congruences(tmp_cs);
01667     }
01668 
01669     // Congruences are added to `w' until it equals `z'.
01670     // We do not care about minimization or maximization, since
01671     // we are only interested in satisfiability.
01672     Grid w;
01673     w.add_space_dimensions_and_embed(x.space_dim);
01674     // First add the congruences for `y'.
01675     w.add_congruences(y_cs);
01676 
01677     // We apply the following heuristics here: congruences of `x' that
01678     // are not made redundant by `y' are added to `w' depending on
01679     // the number of generators of `y' they rule out (the more generators)
01680     // (they rule out, the sooner they are added).  Of course, as soon
01681     // as `w' becomes empty, we stop adding.
01682     std::vector<Ruled_Out_Pair>
01683       ruled_out_vec(x_cs_num_rows - num_redundant_by_y);
01684 
01685     PPL_DIRTY_TEMP_COEFFICIENT(sp);
01686     PPL_DIRTY_TEMP_COEFFICIENT(div);
01687 
01688     for (dimension_type i = 0, j = 0; i < x_cs_num_rows; ++i) {
01689       if (!redundant_by_y[i]) {
01690         const Congruence& c = x_cs[i];
01691         const Coefficient& modulus = c.modulus();
01692         div = modulus;
01693 
01694         dimension_type num_ruled_out_generators = 0;
01695         for (Grid_Generator_System::const_iterator k = y_gs.begin(),
01696                y_gs_end = y_gs.end(); k != y_gs_end; ++k) {
01697           const Grid_Generator& g = *k;
01698           // If the generator is not to be ruled out,
01699           // it must saturate the congruence.
01700           Scalar_Products::assign(sp, c, g);
01701           // If `c' is a proper congruence the scalar product must be
01702           // reduced modulo a (possibly scaled) modulus.
01703           if (c.is_proper_congruence()) {
01704             // If `g' is a parameter the congruence modulus must be scaled
01705             // up by the divisor of the generator.
01706             if (g.is_parameter())
01707               sp %= (div * g.divisor());
01708             else
01709               if (g.is_point())
01710                 sp %= div;
01711           }
01712           if (sp == 0)
01713             continue;
01714           ++num_ruled_out_generators;
01715         }
01716         ruled_out_vec[j].congruence_index = i;
01717         ruled_out_vec[j].num_ruled_out = num_ruled_out_generators;
01718         ++j;
01719       }
01720     }
01721     std::sort(ruled_out_vec.begin(), ruled_out_vec.end(),
01722               Ruled_Out_Less_Than());
01723 
01724     bool empty_intersection = (!z.minimize());
01725 
01726     // Add the congruences in the "ruled out" order to `w'
01727     // until the result is the intersection.
01728     for (std::vector<Ruled_Out_Pair>::const_iterator
01729            j = ruled_out_vec.begin(), rov_end = ruled_out_vec.end();
01730          j != rov_end;
01731          ++j) {
01732       const Congruence& c = x_cs[j->congruence_index];
01733       result_cs.insert(c);
01734       w.add_congruence(c);
01735       if ((empty_intersection && w.is_empty())
01736           || (!empty_intersection && w.is_included_in(z))) {
01737         Grid result_gr(x.space_dim, UNIVERSE);
01738         result_gr.add_congruences(result_cs);
01739         x.swap(result_gr);
01740         PPL_ASSERT(x.OK());
01741         return !empty_intersection;
01742       }
01743     }
01744       // Cannot exit from here.
01745     PPL_ASSERT(false);
01746   }
01747 
01748   // All the congruences are redundant so that the simplified grid
01749   // is the universe.
01750   Grid result_gr(x.space_dim, UNIVERSE);
01751   x.swap(result_gr);
01752   PPL_ASSERT(x.OK());
01753   return true;
01754 }

dimension_type Parma_Polyhedra_Library::Grid::space_dimension (  )  const [inline]
bool Parma_Polyhedra_Library::Grid::strictly_contains ( const Grid y  )  const [inline]

Returns true if and only if *this strictly contains y.

Exceptions:
std::invalid_argument Thrown if *this and y are dimension-incompatible.

Definition at line 361 of file Grid.inlines.hh.

References contains().

00361                                            {
00362   const Grid& x = *this;
00363   return x.contains(y) && !y.contains(x);
00364 }

void Parma_Polyhedra_Library::Grid::swap ( Grid y  )  [inline]

Swaps *this with grid y. (*this and y can be dimension-incompatible.).

Definition at line 245 of file Grid.inlines.hh.

References con_sys, dim_kinds, gen_sys, space_dim, and status.

Referenced by add_recycled_grid_generators(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), congruence_widening_assign(), construct(), generator_widening_assign(), map_space_dimensions(), OK(), set_empty(), simplify(), simplify_using_context_assign(), and swap().

00245                   {
00246   std::swap(con_sys, y.con_sys);
00247   std::swap(gen_sys, y.gen_sys);
00248   std::swap(status, y.status);
00249   std::swap(space_dim, y.space_dim);
00250   std::swap(dim_kinds, y.dim_kinds);
00251 }

void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible ( const char *  method,
dimension_type  required_space_dim 
) const [protected]

Definition at line 810 of file Grid_nonpublic.cc.

References space_dimension().

00811                                                                       {
00812   std::ostringstream s;
00813   s << "PPL::Grid::" << method << ":" << std::endl
00814     << "this->space_dimension() == " << space_dimension()
00815     << ", required space dimension == " << required_space_dim << ".";
00816   throw std::invalid_argument(s.str());
00817 }

void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible ( const char *  method,
const char *  var_name,
Variable  var 
) const [protected]

Definition at line 798 of file Grid_nonpublic.cc.

References Parma_Polyhedra_Library::Variable::space_dimension(), and space_dimension().

00800                                                                   {
00801   std::ostringstream s;
00802   s << "PPL::Grid::" << method << ":" << std::endl
00803     << "this->space_dimension() == " << space_dimension() << ", "
00804     << var_name << ".space_dimension() == " << var.space_dimension() << ".";
00805   throw std::invalid_argument(s.str());
00806 }

void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible ( const char *  method,
const char *  gs_name,
const Grid_Generator_System gs 
) const [protected]

Definition at line 791 of file Grid_nonpublic.cc.

References Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), and throw_dimension_incompatible().

00793                                                                                {
00794   throw_dimension_incompatible(method, gs_name, gs.space_dimension());
00795 }

void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible ( const char *  method,
const char *  cs_name,
const Constraint_System cs 
) const [protected]

Definition at line 784 of file Grid_nonpublic.cc.

References Parma_Polyhedra_Library::Constraint_System::space_dimension(), and throw_dimension_incompatible().

00786                                                                            {
00787   throw_dimension_incompatible(method, cs_name, cs.space_dimension());
00788 }

void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible ( const char *  method,
const char *  cgs_name,
const Congruence_System cgs 
) const [protected]

Definition at line 777 of file Grid_nonpublic.cc.

References Parma_Polyhedra_Library::Congruence_System::space_dimension(), and throw_dimension_incompatible().

00779                                                                             {
00780   throw_dimension_incompatible(method, cgs_name, cgs.space_dimension());
00781 }

void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible ( const char *  method,
const char *  g_name,
const Generator g 
) const [protected]

Definition at line 770 of file Grid_nonpublic.cc.

References Parma_Polyhedra_Library::Generator::space_dimension(), and throw_dimension_incompatible().

00772                                                                   {
00773   throw_dimension_incompatible(method, g_name, g.space_dimension());
00774 }

void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible ( const char *  method,
const char *  g_name,
const Grid_Generator g 
) const [protected]

Definition at line 763 of file Grid_nonpublic.cc.

References Parma_Polyhedra_Library::Grid_Generator::space_dimension(), and throw_dimension_incompatible().

00765                                                                        {
00766   throw_dimension_incompatible(method, g_name, g.space_dimension());
00767 }

void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible ( const char *  method,
const char *  c_name,
const Constraint c 
) const [protected]

Definition at line 756 of file Grid_nonpublic.cc.

References Parma_Polyhedra_Library::Constraint::space_dimension(), and throw_dimension_incompatible().

00758                                                                    {
00759   throw_dimension_incompatible(method, c_name, c.space_dimension());
00760 }

void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible ( const char *  method,
const char *  cg_name,
const Congruence cg 
) const [protected]

Definition at line 749 of file Grid_nonpublic.cc.

References Parma_Polyhedra_Library::Congruence::space_dimension(), and throw_dimension_incompatible().

00751                                                                     {
00752   throw_dimension_incompatible(method, cg_name, cg.space_dimension());
00753 }

void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible ( const char *  method,
const char *  e_name,
const Linear_Expression e 
) const [protected]

Definition at line 742 of file Grid_nonpublic.cc.

References Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and throw_dimension_incompatible().

00744                                                                           {
00745   throw_dimension_incompatible(method, e_name, e.space_dimension());
00746 }

void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible ( const char *  method,
const char *  gr_name,
const Grid gr 
) const [protected]

Definition at line 735 of file Grid_nonpublic.cc.

References space_dimension(), and throw_dimension_incompatible().

00737                                                               {
00738   throw_dimension_incompatible(method, gr_name, gr.space_dimension());
00739 }

void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible ( const char *  method,
const char *  other_name,
dimension_type  other_dim 
) const [protected]
void Parma_Polyhedra_Library::Grid::throw_invalid_argument ( const char *  method,
const char *  reason 
) const [protected]

Definition at line 715 of file Grid_nonpublic.cc.

Referenced by affine_image(), affine_preimage(), bounded_affine_image(), bounded_affine_preimage(), fold_space_dimensions(), generalized_affine_image(), generalized_affine_preimage(), and map_space_dimensions().

00716                                                             {
00717   std::ostringstream s;
00718   s << "PPL::Grid::" << method << ":" << std::endl
00719     << reason << ".";
00720   throw std::invalid_argument(s.str());
00721 }

void Parma_Polyhedra_Library::Grid::throw_invalid_constraint ( const char *  method,
const char *  c_name 
) const [protected]

Definition at line 829 of file Grid_nonpublic.cc.

Referenced by add_constraint_no_check(), and Grid().

00830                                                               {
00831   std::ostringstream s;
00832   s << "PPL::Grid::" << method << ":" << std::endl
00833     << c_name << " is not an equality constraint.";
00834   throw std::invalid_argument(s.str());
00835 }

void Parma_Polyhedra_Library::Grid::throw_invalid_constraints ( const char *  method,
const char *  cs_name 
) const [protected]

Definition at line 838 of file Grid_nonpublic.cc.

Referenced by Grid().

00839                                                                {
00840   std::ostringstream s;
00841   s << "PPL::Grid::" << method << ":" << std::endl
00842     << "the constraint system " << cs_name
00843     << " contains inequalities.";
00844   throw std::invalid_argument(s.str());
00845 }

void Parma_Polyhedra_Library::Grid::throw_invalid_generator ( const char *  method,
const char *  g_name 
) const [protected]

Definition at line 848 of file Grid_nonpublic.cc.

Referenced by add_grid_generator().

00849                                                              {
00850   std::ostringstream s;
00851   s << "PPL::Grid::" << method << ":" << std::endl
00852     << "*this is an empty grid and "
00853     << g_name << " is not a point.";
00854   throw std::invalid_argument(s.str());
00855 }

void Parma_Polyhedra_Library::Grid::throw_invalid_generators ( const char *  method,
const char *  gs_name 
) const [protected]

Definition at line 858 of file Grid_nonpublic.cc.

Referenced by add_recycled_grid_generators(), and construct().

00859                                                                {
00860   std::ostringstream s;
00861   s << "PPL::Grid::" << method << ":" << std::endl
00862     << "*this is an empty grid and" << std::endl
00863     << "the non-empty generator system " << gs_name << " contains no points.";
00864   throw std::invalid_argument(s.str());
00865 }

void Parma_Polyhedra_Library::Grid::throw_runtime_error ( const char *  method  )  const [protected]

Definition at line 708 of file Grid_nonpublic.cc.

00708                                                      {
00709   std::ostringstream s;
00710   s << "PPL::Grid::" << method << "." << std::endl;
00711   throw std::runtime_error(s.str());
00712 }

void Parma_Polyhedra_Library::Grid::throw_space_dimension_overflow ( const char *  method,
const char *  reason 
) [static, protected]

Definition at line 820 of file Grid_nonpublic.cc.

Referenced by add_space_dimensions_and_embed(), add_space_dimensions_and_project(), concatenate_assign(), expand_space_dimension(), and Grid().

00821                                                               {
00822   std::ostringstream s;
00823   s << "PPL::Grid::" << method << ":" << std::endl
00824     << reason << ".";
00825   throw std::length_error(s.str());
00826 }

void Parma_Polyhedra_Library::Grid::time_elapse_assign ( const Grid y  ) 

Assigns to *this the result of computing the time-elapse between *this and y.

Exceptions:
std::invalid_argument Thrown if *this and y are dimension-incompatible.

Definition at line 2435 of file Grid_public.cc.

References clear_congruences_up_to_date(), clear_generators_minimized(), gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Grid_Generator::is_point(), marked_empty(), normalize_divisors(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), OK(), Parma_Polyhedra_Library::Grid_Generator_System::recycling_insert(), set_empty(), Parma_Polyhedra_Library::Grid_Generator::set_is_parameter(), space_dim, throw_dimension_incompatible(), and update_generators().

02435                                          {
02436   Grid& x = *this;
02437   // Check dimension-compatibility.
02438   if (x.space_dim != y.space_dim)
02439     throw_dimension_incompatible("time_elapse_assign(y)", "y", y);
02440 
02441   // Deal with the zero-dimensional case.
02442   if (x.space_dim == 0) {
02443     if (y.marked_empty())
02444       x.set_empty();
02445     return;
02446   }
02447 
02448   // If either one of `x' or `y' is empty, the result is empty too.
02449   if (x.marked_empty())
02450     return;
02451   if (y.marked_empty()
02452       || (!x.generators_are_up_to_date() && !x.update_generators())
02453       || (!y.generators_are_up_to_date() && !y.update_generators())) {
02454     x.set_empty();
02455     return;
02456   }
02457 
02458   // At this point both generator systems are up-to-date.
02459   Grid_Generator_System gs = y.gen_sys;
02460   dimension_type gs_num_rows = gs.num_rows();
02461 
02462   normalize_divisors(gs, gen_sys);
02463 
02464   for (dimension_type i = gs_num_rows; i-- > 0; ) {
02465     Grid_Generator& g = gs[i];
02466     if (g.is_point())
02467       // Transform the point into a parameter.
02468       g.set_is_parameter();
02469   }
02470 
02471   if (gs_num_rows == 0)
02472     // `y' was the grid containing a single point at the origin, so
02473     // the result is `x'.
02474     return;
02475 
02476   // Append `gs' to the generators of `x'.
02477 
02478   gen_sys.recycling_insert(gs);
02479 
02480   x.clear_congruences_up_to_date();
02481   x.clear_generators_minimized();
02482 
02483   PPL_ASSERT(x.OK(true) && y.OK(true));
02484 }

void Parma_Polyhedra_Library::Grid::topological_closure_assign (  )  [inline]

Assigns to *this its topological closure.

Definition at line 367 of file Grid.inlines.hh.

00367                                  {
00368 }

memory_size_type Parma_Polyhedra_Library::Grid::total_memory_in_bytes (  )  const [inline]

Returns the total size in bytes of the memory occupied by *this.

Definition at line 225 of file Grid.inlines.hh.

References external_memory_in_bytes().

00225                                   {
00226   return sizeof(*this) + external_memory_in_bytes();
00227 }

void Parma_Polyhedra_Library::Grid::unconstrain ( const Variables_Set vars  ) 

Computes the cylindrification of *this with respect to the set of space dimensions vars, assigning the result to *this.

Parameters:
vars The set of space dimension that will be unconstrained.
Exceptions:
std::invalid_argument Thrown if *this is dimension-incompatible with one of the Variable objects contained in vars.

Definition at line 1339 of file Grid_public.cc.

References clear_congruences_up_to_date(), clear_generators_minimized(), gen_sys, generators_are_up_to_date(), marked_empty(), OK(), Parma_Polyhedra_Library::Grid_Generator_System::recycling_insert(), space_dim, Parma_Polyhedra_Library::Variables_Set::space_dimension(), throw_dimension_incompatible(), and update_generators().

01339                                               {
01340   // The cylindrification wrt no dimensions is a no-op.
01341   // This case also captures the only legal cylindrification
01342   // of a grid in a 0-dim space.
01343   if (vars.empty())
01344     return;
01345 
01346   // Dimension-compatibility check.
01347   const dimension_type min_space_dim = vars.space_dimension();
01348   if (space_dim < min_space_dim)
01349     throw_dimension_incompatible("unconstrain(vs)", min_space_dim);
01350 
01351   // Do something only if the grid is non-empty.
01352   if (marked_empty()
01353       || (!generators_are_up_to_date() && !update_generators()))
01354     // Empty: do nothing.
01355     return;
01356 
01357   PPL_ASSERT(generators_are_up_to_date());
01358   // Since `gen_sys' is not empty, the space dimension of the inserted
01359   // generators are automatically adjusted.
01360   for (Variables_Set::const_iterator vsi = vars.begin(),
01361          vsi_end = vars.end(); vsi != vsi_end; ++vsi) {
01362     Grid_Generator l = grid_line(Variable(*vsi));
01363     gen_sys.recycling_insert(l);
01364   }
01365   // Constraints are no longer up-to-date.
01366   clear_generators_minimized();
01367   clear_congruences_up_to_date();
01368   PPL_ASSERT(OK());
01369 }

void Parma_Polyhedra_Library::Grid::unconstrain ( Variable  var  ) 

Computes the cylindrification of *this with respect to space dimension var, assigning the result to *this.

Parameters:
var The space dimension that will be unconstrained.
Exceptions:
std::invalid_argument Thrown if var is not a space dimension of *this.

Definition at line 1318 of file Grid_public.cc.

References clear_congruences_up_to_date(), clear_generators_minimized(), gen_sys, generators_are_up_to_date(), marked_empty(), OK(), Parma_Polyhedra_Library::Grid_Generator_System::recycling_insert(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), and update_generators().

Referenced by wrap_assign().

01318                                        {
01319   // Dimension-compatibility check.
01320   if (space_dim < var.space_dimension())
01321     throw_dimension_incompatible("unconstrain(var)", var.space_dimension());
01322 
01323   // Do something only if the grid is non-empty.
01324   if (marked_empty()
01325       || (!generators_are_up_to_date() && !update_generators()))
01326     // Empty: do nothing.
01327     return;
01328 
01329   PPL_ASSERT(generators_are_up_to_date());
01330   Grid_Generator l = grid_line(var);
01331   gen_sys.recycling_insert(l);
01332   // With the added generator, congruences are out of date.
01333   clear_congruences_up_to_date();
01334   clear_generators_minimized();
01335   PPL_ASSERT(OK());
01336 }

void Parma_Polyhedra_Library::Grid::update_congruences (  )  const [private]

Updates and minimizes the congruences from the generators.

Definition at line 464 of file Grid_nonpublic.cc.

References gen_sys, generators_are_minimized(), Parma_Polyhedra_Library::Matrix::has_no_rows(), marked_empty(), space_dim, and Parma_Polyhedra_Library::Grid_Generator_System::space_dimension().

Referenced by add_congruence_no_check(), add_recycled_congruences(), concatenate_assign(), congruence_widening_assign(), congruences(), constrains(), intersection_assign(), is_included_in(), is_universe(), minimize(), and relation_with().

00464                                   {
00465   // The caller must ensure that the generators are up to date.
00466   PPL_ASSERT(space_dim > 0);
00467   PPL_ASSERT(!marked_empty());
00468   PPL_ASSERT(!gen_sys.has_no_rows());
00469   PPL_ASSERT(gen_sys.space_dimension() > 0);
00470 
00471   Grid& gr = const_cast<Grid&>(*this);
00472 
00473   if (!generators_are_minimized())
00474     gr.simplify(gr.gen_sys, gr.dim_kinds);
00475 
00476   // `gen_sys' contained rows before being reduced, so it should
00477   // contain at least a single point afterward.
00478   PPL_ASSERT(!gen_sys.has_no_rows());
00479 
00480   // Populate `con_sys' with congruences characterizing the grid
00481   // described by `gen_sys'.
00482   gr.conversion(gr.gen_sys, gr.con_sys, gr.dim_kinds);
00483 
00484   // Both systems are minimized.
00485   gr.set_congruences_minimized();
00486   gr.set_generators_minimized();
00487 }

bool Parma_Polyhedra_Library::Grid::update_generators (  )  const [private]

Updates and minimizes the generators from the congruences.

Returns:
false if and only if *this turns out to be an empty grid.

It is illegal to call this method when the Status field already declares the grid to be empty.

Definition at line 490 of file Grid_nonpublic.cc.

References con_sys, congruences_are_minimized(), congruences_are_up_to_date(), conversion(), dim_kinds, gen_sys, marked_empty(), set_congruences_minimized(), set_empty(), set_generators_minimized(), simplify(), and space_dim.

Referenced by add_grid_generator(), add_recycled_grid_generators(), bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), generalized_affine_image(), generalized_affine_preimage(), generator_widening_assign(), grid_generators(), is_bounded(), is_discrete(), limited_congruence_extrapolation_assign(), limited_extrapolation_assign(), limited_generator_extrapolation_assign(), map_space_dimensions(), minimize(), minimized_grid_generators(), OK(), relation_with(), remove_space_dimensions(), time_elapse_assign(), unconstrain(), and upper_bound_assign().

00490                                  {
00491   PPL_ASSERT(space_dim > 0);
00492   PPL_ASSERT(!marked_empty());
00493   PPL_ASSERT(congruences_are_up_to_date());
00494 
00495   Grid& x = const_cast<Grid&>(*this);
00496 
00497   if (!congruences_are_minimized())
00498     // Either the system of congruences is consistent, or the grid is
00499     // empty.
00500     if (simplify(x.con_sys, x.dim_kinds)) {
00501       x.set_empty();
00502       return false;
00503     }
00504 
00505   // Populate gen_sys with generators characterizing the grid
00506   // described by con_sys.
00507   conversion(x.con_sys, x.gen_sys, x.dim_kinds);
00508 
00509   // Both systems are minimized.
00510   x.set_congruences_minimized();
00511   x.set_generators_minimized();
00512   return true;
00513 }

void Parma_Polyhedra_Library::Grid::upper_bound_assign ( const Grid y  ) 

Assigns to *this the least upper bound of *this and y.

Exceptions:
std::invalid_argument Thrown if *this and y are dimension-incompatible.

Definition at line 1409 of file Grid_public.cc.

References clear_congruences_up_to_date(), clear_generators_minimized(), gen_sys, generators_are_up_to_date(), marked_empty(), normalize_divisors(), OK(), Parma_Polyhedra_Library::Grid_Generator_System::recycling_insert(), space_dim, throw_dimension_incompatible(), and update_generators().

Referenced by difference_assign(), fold_space_dimensions(), and upper_bound_assign_if_exact().

01409                                          {
01410   Grid& x = *this;
01411   // Dimension-compatibility check.
01412   if (x.space_dim != y.space_dim)
01413     throw_dimension_incompatible("upper_bound_assign(y)", "y", y);
01414 
01415   // The join of a grid `gr' with an empty grid is `gr'.
01416   if (y.marked_empty())
01417     return;
01418   if (x.marked_empty()) {
01419     x = y;
01420     return;
01421   }
01422 
01423   // If both grids are zero-dimensional, then they are necessarily
01424   // universe grids, and so is their join.
01425   if (x.space_dim == 0)
01426     return;
01427 
01428   // The generators must be up-to-date.
01429   if (!x.generators_are_up_to_date() && !x.update_generators()) {
01430     // Discovered `x' empty when updating generators.
01431     x = y;
01432     return;
01433   }
01434   if (!y.generators_are_up_to_date() && !y.update_generators())
01435     // Discovered `y' empty when updating generators.
01436     return;
01437 
01438   // Match the divisors of the x and y generator systems.
01439   Grid_Generator_System gs(y.gen_sys);
01440   normalize_divisors(x.gen_sys, gs);
01441   x.gen_sys.recycling_insert(gs);
01442   // Congruences may be out of date and generators may have lost
01443   // minimal form.
01444   x.clear_congruences_up_to_date();
01445   x.clear_generators_minimized();
01446 
01447   // At this point both `x' and `y' are not empty.
01448   PPL_ASSERT(x.OK(true) && y.OK(true));
01449 }

bool Parma_Polyhedra_Library::Grid::upper_bound_assign_if_exact ( const Grid y  ) 

If the upper bound of *this and y is exact it is assigned to this and true is returned, otherwise false is returned.

Exceptions:
std::invalid_argument Thrown if *this and y are dimension-incompatible.

Definition at line 1452 of file Grid_public.cc.

References difference_assign(), generators_are_up_to_date(), is_included_in(), marked_empty(), space_dim, throw_dimension_incompatible(), and upper_bound_assign().

01452                                                   {
01453   Grid& x = *this;
01454 
01455   // Dimension-compatibility check.
01456   if (x.space_dim != y.space_dim)
01457     throw_dimension_incompatible("upper_bound_assign_if_exact(y)", "y", y);
01458 
01459   if (x.marked_empty()
01460       || y.marked_empty()
01461       || x.space_dim == 0
01462       || x.is_included_in(y)
01463       || y.is_included_in(x)) {
01464     upper_bound_assign(y);
01465     return true;
01466   }
01467 
01468   // The above test 'x.is_included_in(y)' will ensure the generators of x
01469   // are up to date.
01470   PPL_ASSERT(generators_are_up_to_date());
01471 
01472   Grid x_copy = x;
01473   x_copy.upper_bound_assign(y);
01474   x_copy.difference_assign(y);
01475   if (x_copy.is_included_in(x)) {
01476     upper_bound_assign(y);
01477     return true;
01478   }
01479 
01480   return false;
01481 }

bool Parma_Polyhedra_Library::Grid::upper_triangular ( const Grid_Generator_System sys,
const Dimension_Kinds dim_kinds 
) [static, private]

If sys is upper triangular return true, else return false.

Definition at line 75 of file Grid_conversion.cc.

References GEN_VIRTUAL, Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), and Parma_Polyhedra_Library::Grid_Generator_System::space_dimension().

Referenced by conversion(), and OK().

00076                                                          {
00077   dimension_type num_columns = sys.space_dimension() + 1;
00078   dimension_type row = sys.num_rows();
00079 
00080   // Check for easy square fail case.
00081   if (row > num_columns)
00082     return false;
00083 
00084   // Check triangularity.
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     // Check diagonal.
00091     if (gen[num_columns] <= 0)
00092       return false;
00093     // Check elements preceding diagonal.
00094     dimension_type col = num_columns;
00095     while (col-- > 0)
00096       if (gen[col] != 0)
00097         return false;
00098   }
00099 
00100   // Check for squareness.
00101   return num_columns == row;
00102 }

void Parma_Polyhedra_Library::Grid::widening_assign ( const Grid y,
unsigned *  tp = NULL 
)

Assigns to *this the result of computing the Grid widening between *this and y.

This widening uses either the congruence or generator systems depending on which of the systems describing x and y are up to date and minimized.

Parameters:
y A grid that must be contained in *this;
tp An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique).
Exceptions:
std::invalid_argument Thrown if *this and y are dimension-incompatible.

Definition at line 432 of file Grid_widenings.cc.

References congruence_widening_assign(), congruences_are_up_to_date(), contains(), generator_widening_assign(), generators_are_up_to_date(), space_dim, and throw_dimension_incompatible().

Referenced by limited_congruence_extrapolation_assign(), and limited_extrapolation_assign().

00432                                                           {
00433   Grid& x = *this;
00434   Grid& y = const_cast<Grid&>(const_y);
00435   // Dimension-compatibility check.
00436   if (x.space_dim != y.space_dim)
00437     throw_dimension_incompatible("widening_assign(y)", "y", y);
00438 
00439   // Stable behavior is only guaranteed if y is contained in or equal
00440   // to x.
00441 #ifndef NDEBUG
00442   {
00443     // Assume y is contained in or equal to x.
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   // If the `x' congruences are up to date and `y' congruences are up
00451   // to date use the congruence widening.
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   // If the `x' generators are up to date and `y' generators are up to
00458   // date use the generator widening.
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 }

void Parma_Polyhedra_Library::Grid::wrap_assign ( const Variables_Set vars,
Bounded_Integer_Type_Width  w,
Bounded_Integer_Type_Representation  r,
Bounded_Integer_Type_Overflow  o,
const Constraint_System pcs = 0,
unsigned  complexity_threshold = 16,
bool  wrap_individually = true 
)

Wraps the specified dimensions of the vector space.

Parameters:
vars The set of Variable objects corresponding to the space dimensions to be wrapped.
w The width of the bounded integer type corresponding to all the dimensions to be wrapped.
r The representation of the bounded integer type corresponding to all the dimensions to be wrapped.
o The overflow behavior of the bounded integer type corresponding to all the dimensions to be wrapped.
pcs Possibly null pointer to a constraint system. This argument is for compatibility with wrap_assign() for the other domains and only checked for dimension-compatibility.
complexity_threshold A precision parameter of the wrapping operator. This argument is for compatibility with wrap_assign() for the other domains and is ignored.
wrap_individually true if the dimensions should be wrapped individually. As wrapping dimensions collectively does not improve the precision, this argument is ignored.
Exceptions:
std::invalid_argument Thrown if *this is dimension-incompatible with one of the Variable objects contained in vars or with *pcs.
Warning:
It is assumed that variables in Vars represent integers. Thus, where the extra cost is negligible, the integrality of these variables is enforced; possibly causing a non-integral grid to become empty.

Definition at line 2677 of file Grid_public.cc.

References add_congruence(), add_constraint(), add_grid_generator(), bounds_no_check(), Parma_Polyhedra_Library::Grid_Generator::coefficient(), Parma_Polyhedra_Library::Coefficient_one(), Parma_Polyhedra_Library::Grid_Generator::divisor(), frequency_no_check(), gen_sys, generators_are_minimized(), marked_empty(), minimize(), Parma_Polyhedra_Library::mul_2exp_assign(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::OVERFLOW_IMPOSSIBLE, Parma_Polyhedra_Library::OVERFLOW_UNDEFINED, Parma_Polyhedra_Library::OVERFLOW_WRAPS, PPL_DIRTY_TEMP_COEFFICIENT, set_empty(), Parma_Polyhedra_Library::SIGNED_2_COMPLEMENT, space_dim, Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), throw_dimension_incompatible(), unconstrain(), and Parma_Polyhedra_Library::UNSIGNED.

02683                                                      {
02684 
02685   // Dimension-compatibility check of `*pcs', if any.
02686   if (pcs != 0) {
02687    const dimension_type pcs_space_dim  = pcs->space_dimension();
02688    if (pcs->space_dimension() > space_dim)
02689      throw_dimension_incompatible("wrap_assign(vs, ...)", pcs_space_dim);
02690   }
02691 
02692   // Wrapping no variable is a no-op.
02693   if (vars.empty())
02694     return;
02695 
02696   // Dimension-compatibility check of `vars'.
02697   const dimension_type min_space_dim = vars.space_dimension();
02698   if (space_dim < min_space_dim)
02699     throw_dimension_incompatible("wrap_assign(vs, ...)", min_space_dim);
02700 
02701   // Wrapping an empty grid is a no-op.
02702   if (marked_empty())
02703     return;
02704   if (!generators_are_minimized() && !minimize())
02705     // Minimizing found `this' empty.
02706     return;
02707 
02708   // Set the wrap frequency for variables of width `w'.
02709   // This is independent of the signedness `s'.
02710   PPL_DIRTY_TEMP_COEFFICIENT(wrap_frequency);
02711   mul_2exp_assign(wrap_frequency, Coefficient_one(), w);
02712   // Set `min_value' and `max_value' to the minimum and maximum values
02713   // a variable of width `w' and signedness `s' can take.
02714   PPL_DIRTY_TEMP_COEFFICIENT(min_value);
02715   PPL_DIRTY_TEMP_COEFFICIENT(max_value);
02716   if (r == UNSIGNED) {
02717     min_value = 0;
02718     mul_2exp_assign(max_value, Coefficient_one(), w);
02719     --max_value;
02720   }
02721   else {
02722     PPL_ASSERT(r == SIGNED_2_COMPLEMENT);
02723     mul_2exp_assign(max_value, Coefficient_one(), w-1);
02724     neg_assign(min_value, max_value);
02725     --max_value;
02726   }
02727 
02728   // Generators are up-to-date and minimized.
02729   const Grid gr = *this;
02730 
02731   // Overflow is impossible or wraps.
02732   if (o == OVERFLOW_IMPOSSIBLE || o == OVERFLOW_WRAPS) {
02733     PPL_DIRTY_TEMP_COEFFICIENT(f_n);
02734     PPL_DIRTY_TEMP_COEFFICIENT(f_d);
02735     PPL_DIRTY_TEMP_COEFFICIENT(v_n);
02736     PPL_DIRTY_TEMP_COEFFICIENT(v_d);
02737     for (Variables_Set::const_iterator i = vars.begin(),
02738            vars_end = vars.end(); i != vars.end(); ++i) {
02739       const Variable x = Variable(*i);
02740       // Find the frequency and a value for `x' in `gr'.
02741       if (!gr.frequency_no_check(x, f_n, f_d, v_n, v_d))
02742         continue;
02743       if (f_n == 0) {
02744 
02745         // `x' is a constant in `gr'.
02746         if (v_d != 1) {
02747           // The value for `x' is not integral (`frequency_no_check()'
02748           // ensures that `v_n' and `v_d' have no common divisors).
02749           set_empty();
02750           return;
02751         }
02752 
02753         // `x' is a constant and has an integral value.
02754         if ((v_n > max_value) || (v_n < min_value)) {
02755           // The value is outside the range of the bounded integer type.
02756           if (o == OVERFLOW_IMPOSSIBLE) {
02757             // Then `x' has no possible value and hence set empty.
02758             set_empty();
02759             return;
02760           }
02761           PPL_ASSERT(o == OVERFLOW_WRAPS);
02762           // The value v_n for `x' is wrapped modulo the 'wrap_frequency'.
02763           v_n %= wrap_frequency;
02764           // `v_n' is the value closest to 0 and may be negative.
02765           if (r == UNSIGNED && v_n < 0)
02766             v_n += wrap_frequency;
02767           unconstrain(x);
02768           add_constraint(x == v_n);
02769         }
02770         continue;
02771       }
02772 
02773       // `x' is not a constant in `gr'.
02774       PPL_ASSERT(f_n != 0);
02775 
02776       if (f_d % v_d != 0) {
02777         // Then `x' has no integral value and hence `gr' is set empty.
02778         set_empty();
02779         return;
02780       }
02781       if (f_d != 1) {
02782         // `x' has non-integral values, so add the integrality
02783         // congruence for `x'.
02784         add_congruence((x %= 0) / 1);
02785       }
02786       if (o == OVERFLOW_WRAPS && f_n != wrap_frequency)
02787         // We know that `x' is not a constant, so, if overflow wraps,
02788         // `x' may wrap to a value modulo the `wrap_frequency'.
02789         add_grid_generator(parameter(wrap_frequency * x));
02790       else if ((o == OVERFLOW_IMPOSSIBLE && 2*f_n >= wrap_frequency)
02791                || (f_n == wrap_frequency)) {
02792         // In these cases, `x' can only take a unique (ie constant)
02793         // value.
02794         if (r == UNSIGNED && v_n < 0) {
02795           // `v_n' is the value closest to 0 and may be negative.
02796           v_n += f_n;
02797         }
02798         unconstrain(x);
02799         add_constraint(x == v_n);
02800       }
02801       else {
02802         // If overflow is impossible but the grid frequency is less than
02803         // half the wrap frequency, then there is more than one possible
02804         // value for `x' in the range of the bounded integer type,
02805         // so the grid is unchanged.
02806         PPL_ASSERT(o == OVERFLOW_IMPOSSIBLE && 2*f_n < wrap_frequency);
02807       }
02808     }
02809     return;
02810   }
02811 
02812   PPL_ASSERT(o == OVERFLOW_UNDEFINED);
02813   // If overflow is undefined, then all we know is that the variable
02814   // may take any integer within the range of the bounded integer type.
02815   const Grid_Generator& point = gr.gen_sys[0];
02816   const Coefficient& div = point.divisor();
02817   max_value *= div;
02818   min_value *= div;
02819   for (Variables_Set::const_iterator i = vars.begin(),
02820          vars_end = vars.end(); i != vars.end(); ++i) {
02821     const Variable x = Variable(*i);
02822     if (!gr.bounds_no_check(x)) {
02823       // `x' is not a constant in `gr'.
02824       // We know that `x' is not a constant, so `x' may wrap to any
02825       // value `x + z' where z is an integer.
02826       if (point.coefficient(x) % div != 0) {
02827         // We know that `x' can take non-integral values, so enforce
02828         // integrality.
02829         unconstrain(x);
02830         add_congruence(x %= 0);
02831       }
02832       else
02833         // `x' has at least one integral value.
02834         // `x' may also take other non-integral values,
02835         // but checking could be costly so we ignore this.
02836         add_grid_generator(parameter(x));
02837     }
02838     else {
02839       // `x' is a constant `v' in `gr'.
02840       const Coefficient& coeff_x = point.coefficient(x);
02841       // `x' should be integral.
02842       if (coeff_x % div != 0) {
02843         set_empty();
02844         return;
02845       }
02846       // If the value `v' for `x' is not within the range for the
02847       // bounded integer type, then `x' may wrap to any value `v + z'
02848       // where `z' is an integer; otherwise `x' is unchanged.
02849       if (coeff_x > max_value || coeff_x < min_value) {
02850         add_grid_generator(parameter(x));
02851       }
02852     }
02853   }
02854 }


Friends And Related Function Documentation

bool operator!= ( const Grid x,
const Grid y 
) [related]

Returns true if and only if x and y are different grids.

Note that x and y may be dimension-incompatible grids: in those cases, the value true is returned.

Definition at line 356 of file Grid.inlines.hh.

00356                                          {
00357   return !(x == y);
00358 }

std::ostream & operator<< ( std::ostream &  s,
const Grid gr 
) [related]

Output operator.

Writes a textual representation of gr on s: false is written if gr is an empty grid; true is written if gr is a universe grid; a minimized system of congruences defining gr is written otherwise, all congruences in one row separated by ", "s.

Definition at line 2897 of file Grid_public.cc.

References is_empty(), is_universe(), and minimized_congruences().

02897                                                          {
02898   if (gr.is_empty())
02899     s << "false";
02900   else if (gr.is_universe())
02901     s << "true";
02902   else
02903     s << gr.minimized_congruences();
02904   return s;
02905 }

bool operator== ( const Grid x,
const Grid y 
) [friend]

Returns true if and only if x and y are the same grid.

Note that x and y may be dimension-incompatible grids: in those cases, the value false is returned.

Definition at line 2514 of file Grid_public.cc.

02514                                             {
02515   if (x.space_dim != y.space_dim)
02516     return false;
02517 
02518   if (x.marked_empty())
02519     return y.is_empty();
02520   if (y.marked_empty())
02521     return x.is_empty();
02522   if (x.space_dim == 0)
02523     return true;
02524 
02525   switch (x.quick_equivalence_test(y)) {
02526   case Grid::TVB_TRUE:
02527     return true;
02528 
02529   case Grid::TVB_FALSE:
02530     return false;
02531 
02532   default:
02533     if (x.is_included_in(y)) {
02534       if (x.marked_empty())
02535         return y.is_empty();
02536       return y.is_included_in(x);
02537     }
02538     return false;
02539   }
02540 }

friend class Parma_Polyhedra_Library::Box [friend]

Definition at line 1924 of file Grid.defs.hh.

Definition at line 1922 of file Grid.defs.hh.

void swap ( Parma_Polyhedra_Library::Grid x,
Parma_Polyhedra_Library::Grid y 
) [related]

Specializes std::swap.

Definition at line 376 of file Grid.inlines.hh.

References swap().

00377                                      {
00378   x.swap(y);
00379 }


Member Data Documentation

The number of dimensions of the enclosing vector space.

Definition at line 1979 of file Grid.defs.hh.

Referenced by add_congruence(), add_congruence_no_check(), add_congruences(), add_constraint(), add_constraint_no_check(), add_constraints(), add_grid_generator(), add_recycled_congruences(), add_recycled_grid_generators(), add_space_dimensions(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_dimension(), affine_image(), affine_preimage(), ascii_dump(), bounded_affine_image(), bounded_affine_preimage(), bounds(), bounds_no_check(), concatenate_assign(), congruence_widening_assign(), congruences(), constrains(), construct(), contains(), contains_integer_point(), difference_assign(), drop_some_non_integer_points(), expand_space_dimension(), fold_space_dimensions(), frequency(), frequency_no_check(), generalized_affine_image(), generalized_affine_preimage(), generator_widening_assign(), Grid(), grid_generators(), intersection_assign(), is_bounded(), is_discrete(), is_disjoint_from(), is_empty(), is_included_in(), is_universe(), limited_congruence_extrapolation_assign(), limited_extrapolation_assign(), limited_generator_extrapolation_assign(), map_space_dimensions(), max_min(), minimize(), minimized_grid_generators(), OK(), operator=(), quick_equivalence_test(), refine_no_check(), refine_with_constraint(), refine_with_constraints(), relation_with(), remove_higher_space_dimensions(), remove_space_dimensions(), select_wider_congruences(), select_wider_generators(), set_empty(), set_zero_dim_univ(), simplify_using_context_assign(), space_dimension(), swap(), time_elapse_assign(), unconstrain(), update_congruences(), update_generators(), upper_bound_assign(), upper_bound_assign_if_exact(), widening_assign(), and wrap_assign().


The documentation for this class was generated from the following files:
Generated on Sun Feb 27 16:20:26 2011 for PPL by  doxygen 1.6.3