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.

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)

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.
template<typename Box>
 Grid (const Box &box, From_Covering_Box dummy)
 Builds a grid out of a generic, interval-based covering box.
 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 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.
template<typename Interval>
void get_covering_box (Box< Interval > &box) const
 Writes the covering box for *this into box.
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.
bool add_congruence_and_minimize (const Congruence &c)
 Adds a copy of congruence cg to the system of congruences of this, reducing the result.
void add_grid_generator (const Grid_Generator &g)
 Adds a copy of grid generator g to the system of generators of *this.
bool add_grid_generator_and_minimize (const Grid_Generator &g)
 Adds a copy of grid generator g to the system of generators of *this, reducing the result.
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.
bool add_congruences_and_minimize (const Congruence_System &cgs)
 Adds a copy of the congruences in cgs to the system of congruences of *this, reducing the result.
bool add_recycled_congruences_and_minimize (Congruence_System &cgs)
 Adds the congruences in cgs to the system of congruences of this, reducing the result.
void add_constraint (const Constraint &c)
 If the constraint c is an equality, it is added to *this.
bool add_constraint_and_minimize (const Constraint &c)
 If the constraint c is an equality, it is added to *this, reducing the result.
void add_constraints (const Constraint_System &cs)
 If all constraints in cs are equality constraints, then copies are added to *this.
bool add_constraints_and_minimize (const Constraint_System &cs)
 If all the constraints in cs are equality constraints, then copies are added to *this, reducing the result.
void add_recycled_constraints (Constraint_System &cs)
 If all the constraints in cs are equality constraints, then they are added to *this.
bool add_recycled_constraints_and_minimize (Constraint_System &cs)
 If all the constraints in cs are equality constraints, then they are added to *this, reducing the result.
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.
bool add_grid_generators_and_minimize (const Grid_Generator_System &gs)
 Adds a copy of the generators in gs to the system of generators of *this, reducing the result.
bool add_recycled_grid_generators_and_minimize (Grid_Generator_System &gs)
 Adds the generators in gs to the system of generators of this, reducing the result.
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 &to_be_unconstrained)
 Computes the cylindrification of *this with respect to the set of space dimensions to_be_unconstrained, assigning the result to *this.
void intersection_assign (const Grid &y)
 Assigns to *this the intersection of *this and y.
bool intersection_assign_and_minimize (const Grid &y)
 Assigns to *this the intersection of *this and y, reducing the result.
void upper_bound_assign (const Grid &y)
 Assigns to *this the least upper bound of *this and y.
bool upper_bound_assign_and_minimize (const Grid &y)
 Assigns to *this the least upper bound of *this and y, reducing the result.
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 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 &to_be_removed)
 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 &to_be_folded, Variable var)
 Folds the space dimensions in to_be_folded into var.
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.
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.

Classes

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


Detailed Description

A grid.

An object of the class Grid represents a rational grid.

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 to_be_removed;
  to_be_removed.insert(y);
  to_be_removed.insert(z);
  gr.remove_space_dimensions(to_be_removed);
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> to_be_removed1;
  to_be_removed1.insert(y);
  gr.remove_space_dimensions(to_be_removed1);
  set<Variable> to_be_removed2;
  to_be_removed2.insert(z);
  gr.remove_space_dimensions(to_be_removed2);
In this case, the result is the grid $\bigl\{(3, 0)^\transpose \bigr\} \sseq \Rset^2$: when removing the set of dimensions to_be_removed2 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 352 of file Grid.defs.hh.


Member Typedef Documentation

The numeric type of coefficients.

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

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


Member Enumeration Documentation

Enumerator:
PARAMETER 
LINE 
GEN_VIRTUAL 
PROPER_CONGRUENCE 
CON_VIRTUAL 
EQUALITY 

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

Enumerator:
TVB_TRUE 
TVB_FALSE 
TVB_DONT_KNOW 

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


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 121 of file Grid.inlines.hh.

References construct(), and OK().

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

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 135 of file Grid.inlines.hh.

References construct().

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

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 148 of file Grid.inlines.hh.

References construct().

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

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 59 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().

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

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 98 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().

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

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 160 of file Grid.inlines.hh.

References construct().

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

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 173 of file Grid.inlines.hh.

References construct().

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

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 35 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(), 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(), TEMP_INTEGER, throw_space_dimension_overflow(), and Parma_Polyhedra_Library::Grid_Generator_System::unset_pending_rows().

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

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 186 of file Grid.inlines.hh.

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

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

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 201 of file Grid.inlines.hh.

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

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

template<typename Box>
Parma_Polyhedra_Library::Grid::Grid ( const Box box,
From_Covering_Box  dummy 
) [inline]

Builds a grid out of a generic, interval-based covering box.

The covering box is a set of upper and lower values for each dimension. When a covering box is tiled onto empty space the corners of the tiles form a rectilinear grid.

A box interval with only one bound fixes the values of all grid points in the dimension associated with the box to the value of the bound. A box interval which has upper and lower bounds of equal value allows all grid points with any value in the dimension associated with the interval. The presence of a universe interval results in the empty grid. The empty box produces the empty grid of the same dimension as the box.

Parameters:
box The covering box representing the grid to be built;
dummy A dummy tag to make this constructor syntactically unique.
Exceptions:
std::length_error Thrown if the space dimension of box exceeds the maximum allowed space dimension.
std::invalid_argument Thrown if box contains any topologically open bounds.
The template class Box must provide the following methods. returns the dimension of the vector space enclosing the grid represented by the covering box.
      bool is_empty() const
returns true if and only if the covering box describes the empty set.
      bool get_lower_bound(dimension_type k, bool& closed,
                           Coefficient& n, Coefficient& d) const
Let $I$ be the interval corresponding to the k-th space dimension. If $I$ is not bounded from below, simply return false. Otherwise, set closed, n and d as follows: closed is set to true if the lower boundary of $I$ is closed and is set to false otherwise; n and d are assigned the integers $n$ and $d$ such that the canonical fraction $n/d$ corresponds to the greatest lower bound of $I$. The fraction $n/d$ is in canonical form if and only if $n$ and $d$ have no common factors and $d$ is positive, $0/1$ being the unique representation for zero.
      bool get_upper_bound(dimension_type k, bool& closed,
                           Coefficient& n, Coefficient& d) const
Let $I$ be the interval corresponding to the k-th space dimension. If $I$ is not bounded from above, simply return false. Otherwise, set closed, n and d as follows: closed is set to true if the upper boundary of $I$ is closed and is set to false otherwise; n and d are assigned the integers $n$ and $d$ such that the canonical fraction $n/d$ corresponds to the least upper bound of $I$.

Definition at line 108 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(), normalize_divisors(), OK(), 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(), TEMP_INTEGER, throw_invalid_argument(), throw_space_dimension_overflow(), and Parma_Polyhedra_Library::Grid_Generator_System::unset_pending_rows().

00109   : con_sys(),
00110     gen_sys() {
00111 
00112   if (box.space_dimension() > max_space_dimension())
00113     throw_space_dimension_overflow("Grid(box, from_covering_box)",
00114                                    "the space dimension of box "
00115                                    "exceeds the maximum allowed "
00116                                    "space dimension");
00117 
00118   space_dim = box.space_dimension();
00119 
00120   TEMP_INTEGER(l_n);
00121   TEMP_INTEGER(l_d);
00122 
00123   // Check that all bounds are closed.  This check must be done before
00124   // the empty test below, as an open bound might mean an empty box.
00125   for (dimension_type k = space_dim; k-- > 0; ) {
00126     bool closed = false;
00127     // FIXME: Perhaps introduce box::is_bounded_and_closed.
00128     if (box.get_lower_bound(k, closed, l_n, l_d) && !closed)
00129       throw_invalid_argument("Grid(box, from_covering_box)", "box");
00130     if (box.get_upper_bound(k, closed, l_n, l_d) && !closed)
00131       throw_invalid_argument("Grid(box, from_covering_box)", "box");
00132   }
00133 
00134   if (box.is_empty()) {
00135     // Empty grid.
00136     set_empty();
00137     assert(OK());
00138     return;
00139   }
00140 
00141   if (space_dim == 0)
00142     set_zero_dim_univ();
00143   else {
00144     // Initialize the space dimension as indicated by the box.
00145     con_sys.increase_space_dimension(space_dim);
00146     // Add congruences according to `box'.
00147     TEMP_INTEGER(u_n);
00148     TEMP_INTEGER(u_d);
00149     TEMP_INTEGER(d);
00150     gen_sys.insert(grid_point(0*Variable(space_dim-1)));
00151     Grid_Generator& point = gen_sys[0];
00152     for (dimension_type k = space_dim; k-- > 0; ) {
00153       bool closed = false;
00154       // TODO: Consider producing the system(s) in minimized form.
00155       if (box.get_lower_bound(k, closed, l_n, l_d)) {
00156 
00157         const Coefficient& point_divisor = point.divisor();
00158         assert(l_d > 0);
00159         assert(point_divisor > 0);
00160         // Use `d' to hold the gcd.
00161         gcd_assign(d, l_d, point_divisor);
00162         // Scale the point to use as divisor the lcm of the existing
00163         // point divisor and the divisor of the lower bound.
00164         exact_div_assign(d, point_divisor, d);
00165         // l_d * d == abs(l_d) * (point_divisor / gcd(l_d, point_divisor))
00166         point.scale_to_divisor(l_d * d);
00167         // Set dimension k of the point to the lower bound.
00168         // point[k + 1] = l_n * (point_divisor / gcd(l_d, point_divisor))
00169         point[k + 1] = l_n * d;
00170 
00171         if (box.get_upper_bound(k, closed, u_n, u_d)) {
00172           if (l_n * u_d == u_n * l_d) {
00173             // A point interval allows any point along the dimension
00174             // k axis.
00175             gen_sys.insert(grid_line(Variable(k)));
00176             continue;
00177           }
00178           assert(l_d > 0);
00179           assert(u_d > 0);
00180           gcd_assign(d, l_d, u_d);
00181           // `d' is the gcd of the divisors.
00182           exact_div_assign(l_d, l_d, d);
00183           exact_div_assign(d, u_d, d);
00184           l_n *= d;
00185           // `l_d' is now the smallest integer expression of the size of
00186           // the original l_d relative to u_d.
00187           u_n = (u_n * l_d) - l_n;
00188           // `u_n' is now the distance between u_n and l_n (given a
00189           // divisor of lcm of l_d and u_d.
00190           l_d *= u_d;
00191           // `l_d' is now the lcm of the divisors.
00192           con_sys.insert((l_d * Variable(k) %= l_n) / u_n);
00193           gen_sys.insert(parameter(u_n * Variable(k), l_d));
00194         }
00195         else
00196           // An interval bounded only from below produces an
00197           // equality.
00198           con_sys.insert(l_d * Variable(k) == l_n);
00199       }
00200       else
00201         if (box.get_upper_bound(k, closed, u_n, u_d)) {
00202           const Coefficient& point_divisor = point.divisor();
00203           assert(u_d > 0);
00204           assert(point_divisor > 0);
00205           // Use `d' to hold the gcd.
00206           gcd_assign(d, u_d, point_divisor);
00207           // Scale the point to use as divisor the lcm of the existing
00208           // point divisor and the divisor of the lower bound.
00209           exact_div_assign(d, point_divisor, d);
00210           // u_d * d == abs(u_d) * (point_divisor / gcd(u_d, point_divisor))
00211           point.scale_to_divisor(u_d * d);
00212           // Set dimension k of the point to the lower bound.
00213           // point[k + 1] = u_n * (point_divisor / gcd(u_d, point_divisor))
00214           point[k + 1] = u_n * d;
00215 
00216           // An interval bounded only from above produces an equality.
00217           con_sys.insert(u_d * Variable(k) == u_n);
00218         }
00219         else {
00220           // Any universe interval produces an empty grid.
00221           set_empty();
00222           assert(OK());
00223           return;
00224         }
00225     }
00226     normalize_divisors(gen_sys);
00227     set_congruences_up_to_date();
00228     set_generators_up_to_date();
00229     gen_sys.set_sorted(false);
00230     gen_sys.unset_pending_rows();
00231   }
00232 
00233   assert(OK());
00234 }

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 137 of file Grid_public.cc.

References Parma_Polyhedra_Library::Linear_Row::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(), gen_sys, 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(), set_empty(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Polyhedron::space_dimension(), and TEMP_INTEGER.

00139   : con_sys(ph.space_dimension() > max_space_dimension()
00140             ? throw_space_dimension_overflow("Grid(ph)",
00141                                              "the space dimension of ph "
00142                                              "exceeds the maximum allowed "
00143                                              "space dimension"), 0
00144             : ph.space_dimension()),
00145     gen_sys(ph.space_dimension()) {
00146   space_dim = ph.space_dimension();
00147 
00148   // A zero-dim polyhedron causes no complexity problems.
00149   if (space_dim == 0) {
00150     if (ph.is_empty())
00151       set_empty();
00152     else
00153       set_zero_dim_univ();
00154     return;
00155   }
00156 
00157   // A polyhedron known to be empty causes no complexity problems.
00158   if (ph.marked_empty()) {
00159     set_empty();
00160     return;
00161   }
00162 
00163   bool use_constraints = ph.constraints_are_minimized()
00164     || !ph.generators_are_up_to_date();
00165 
00166   // Minimize the constraint description if it is needed and
00167   // the complexity allows it.
00168   if (use_constraints && complexity == ANY_COMPLEXITY)
00169     if (!ph.minimize()) {
00170       set_empty();
00171       return;
00172     }
00173 
00174   if (use_constraints) {
00175     // Only the equality constraints need be used.
00176     assert(ph.constraints_are_up_to_date());
00177     const Constraint_System& cs = ph.constraints();
00178     Congruence_System cgs;
00179     cgs.insert(0*Variable(space_dim - 1) %= 1);
00180     for (Constraint_System::const_iterator i = cs.begin(),
00181            cs_end = cs.end(); i != cs_end; ++i)
00182       if (i->is_equality())
00183         cgs.insert(*i);
00184     construct(cgs);
00185   }
00186   else {
00187     gen_sys = Grid_Generator_System(space_dim);
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     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     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     TEMP_INTEGER(coeff);
00212     for (Generator_System::const_iterator g = gs.begin(),
00213            gs_end = gs.end(); g != gs_end; ++g) {
00214       Linear_Expression e;
00215       if (g->is_point() || g->is_closure_point()) {
00216         Coefficient g_divisor = g->divisor();
00217         for (dimension_type i = space_dim; i-- > 0; ) {
00218           const Variable v(i);
00219           coeff = point_expr.coefficient(v) * g_divisor;
00220           coeff -= g->coefficient(v) * point_divisor;
00221           e += coeff * v;
00222         }
00223         if (e.all_homogeneous_terms_are_zero())
00224           continue;
00225       }
00226       else
00227         for (dimension_type i = space_dim; i-- > 0; ) {
00228           const Variable v(i);
00229           e += g->coefficient(v) * v;
00230         }
00231       ggs.insert(grid_line(e));
00232     }
00233     construct(ggs);
00234   }
00235   assert(OK());
00236 }

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

Ordinary copy-constructor.

The complexity argument is ignored.

Definition at line 37 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.

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

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

Destructor.

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

00215             {
00216 }


Member Function Documentation

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 110 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().

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

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 297 of file Grid.inlines.hh.

00297                                      {
00298   return true;
00299 }

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 292 of file Grid.inlines.hh.

00292                                      {
00293   return true;
00294 }

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

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

Definition at line 239 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.

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

dimension_type Parma_Polyhedra_Library::Grid::space_dimension (  )  const [inline]

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 257 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.

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

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 234 of file Grid.inlines.hh.

References congruences().

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

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

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 239 of file Grid.inlines.hh.

References minimized_congruences().

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

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

Returns the system of congruences.

Definition at line 278 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< PS >::approximate_partition(), Parma_Polyhedra_Library::Pointset_Powerset< PS >::approximate_partition_aux(), concatenate_assign(), constraints(), difference_assign(), expand_space_dimension(), and minimized_congruences().

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

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

Returns the system of congruences in minimal form.

Definition at line 295 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< PS >::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<<().

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

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

Returns the system of generators.

Definition at line 308 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().

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

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

Returns the minimized system of generators.

Definition at line 330 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().

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

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 360 of file Grid_public.cc.

References 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, Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), space_dim, Parma_Polyhedra_Library::Congruence::space_dimension(), Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects(), TEMP_INTEGER, throw_dimension_incompatible(), and update_generators().

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

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

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 513 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().

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

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 537 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().

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

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 577 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().

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

bool Parma_Polyhedra_Library::Grid::is_empty (  )  const

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

Definition at line 677 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< PS >::approximate_partition_aux(), Parma_Polyhedra_Library::Pointset_Powerset< PS >::check_containment(), contains(), contains_integer_point(), generalized_affine_image(), generalized_affine_preimage(), is_disjoint_from(), operator<<(), Parma_Polyhedra_Library::Pointset_Powerset< PS >::Pointset_Powerset(), and remove_higher_space_dimensions().

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

bool Parma_Polyhedra_Library::Grid::is_universe (  )  const

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

Definition at line 700 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<<().

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

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 772 of file Grid_public.cc.

00772                                        {
00773   return true;
00774 }

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 2458 of file Grid_public.cc.

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

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

02458                                              {
02459   // Dimension-compatibility check.
02460   if (space_dim != y.space_dim)
02461     throw_dimension_incompatible("is_disjoint_from(y)", "y", y);
02462   Grid z = *this;
02463   z.intersection_assign(y);
02464   return z.is_empty();
02465 }

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 754 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().

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

bool Parma_Polyhedra_Library::Grid::is_bounded (  )  const

Returns true if and only if *this is bounded.

Definition at line 730 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().

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

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 777 of file Grid_public.cc.

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

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

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 799 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().

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

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 335 of file Grid.inlines.hh.

References bounds().

00335                                                            {
00336   return bounds(expr, "bounds_from_above(e)");
00337 }

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 340 of file Grid.inlines.hh.

References bounds().

00340                                                            {
00341   return bounds(expr, "bounds_from_below(e)");
00342 }

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 345 of file Grid.inlines.hh.

References max_min().

00346                                                                             {
00347   return max_min(expr, "maximize(e, ...)", sup_n, sup_d, maximum);
00348 }

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 351 of file Grid.inlines.hh.

References max_min().

00353                                        {
00354   return max_min(expr, "maximize(e, ...)", sup_n, sup_d, maximum, &point);
00355 }

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 358 of file Grid.inlines.hh.

References max_min().

Referenced by is_included_in().

00359                                                                             {
00360   return max_min(expr, "minimize(e, ...)", inf_n, inf_d, minimum);
00361 }

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 364 of file Grid.inlines.hh.

References max_min().

00366                                        {
00367   return max_min(expr, "minimize(e, ...)", inf_n, inf_d, minimum, &point);
00368 }

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 2439 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< PS >::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().

02439                                      {
02440   const Grid& x = *this;
02441 
02442   // Dimension-compatibility check.
02443   if (x.space_dim != y.space_dim)
02444     throw_dimension_incompatible("contains(y)", "y", y);
02445 
02446   if (y.marked_empty())
02447     return true;
02448   if (x.marked_empty())
02449     return y.is_empty();
02450   if (y.space_dim == 0)
02451     return true;
02452   if (x.quick_equivalence_test(y) == Grid::TVB_TRUE)
02453     return true;
02454   return y.is_included_in(x);
02455 }

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 384 of file Grid.inlines.hh.

References contains().

00384                                            {
00385   const Grid& x = *this;
00386   return x.contains(y) && !y.contains(x);
00387 }

template<typename Interval>
void Parma_Polyhedra_Library::Grid::get_covering_box ( Box< Interval > &  box  )  const [inline]

Writes the covering box for *this into box.

The covering box is a set of upper and lower values for each dimension. When the covering box written into box is tiled onto empty space the corners of the tiles form the sparsest rectilinear grid that includes *this.

The value of the lower bound of each interval of the resulting box are as close as possible to the origin, with positive values taking preference when the lowest positive value equals the lowest negative value.

If all the points have a single value in a particular dimension of the grid then there is only a lower bound on the interval produced in box, and the lower bound denotes the single value for the dimension. If the coordinates of the points in a particular dimension include every value then the upper and lower bounds of the associated interval in box are set equal. The empty grid produces the empty box. The zero dimension universe grid produces the zero dimension universe box.

Parameters:
box The Box into which the covering box is written.
Exceptions:
std::invalid_argument Thrown if *this and box are dimension-incompatible.

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

References Parma_Polyhedra_Library::Grid_Generator::divisor(), Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::gcd_assign(), gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Matrix::has_no_rows(), Parma_Polyhedra_Library::Grid_Generator::is_line(), Parma_Polyhedra_Library::Grid_Generator::is_point(), marked_empty(), Parma_Polyhedra_Library::Grid_Generator_System::num_columns(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), Parma_Polyhedra_Library::Grid_Generator::set_divisor(), Parma_Polyhedra_Library::Box< ITV >::set_empty(), space_dim, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::swap(), TEMP_INTEGER, throw_dimension_incompatible(), and update_generators().

00238                                                {
00239   // Dimension-compatibility check.
00240   if (space_dim > box.space_dimension())
00241     throw_dimension_incompatible("get_covering_box(box)", "box",
00242                                  box.space_dimension());
00243 
00244   Box<Interval> new_box(box.space_dimension());
00245 
00246   if (marked_empty()) {
00247     box = new_box;
00248     box.set_empty();
00249     return;
00250   }
00251   if (space_dim == 0) {
00252     return;
00253   }
00254   if (!generators_are_up_to_date() && !update_generators()) {
00255     // Updating found the grid empty.
00256     box = new_box;
00257     box.set_empty();
00258     return;
00259   }
00260 
00261   assert(!gen_sys.has_no_rows());
00262 
00263   dimension_type num_dims = gen_sys.num_columns() - 2 /* parameter divisor */;
00264   dimension_type num_rows = gen_sys.num_rows();
00265 
00266   TEMP_INTEGER(gcd);
00267   TEMP_INTEGER(bound);
00268 
00269   if (num_rows > 1) {
00270     Row interval_sizes(num_dims, Row::Flags());
00271     std::vector<bool> interval_emptiness(num_dims, false);
00272 
00273     // Store in `interval_sizes', for each column (that is, for each
00274     // dimension), the GCD of all the values in that column where the
00275     // row is of type parameter.
00276 
00277     for (dimension_type dim = num_dims; dim-- > 0; )
00278       interval_sizes[dim] = 0;
00279     const Grid_Generator *first_point = NULL;
00280     for (dimension_type row = 0; row < num_rows; ++row) {
00281       Grid_Generator& gen = const_cast<Grid_Generator&>(gen_sys[row]);
00282       if (gen.is_line()) {
00283         for (dimension_type dim = 0; dim < num_dims; ++dim)
00284           if (!interval_emptiness[dim] && gen[dim+1] != 0) {
00285             // Empty interval, set both bounds for associated
00286             // dimension to zero.
00287             new_box.add_constraint(Variable(dim) == 0);
00288             interval_emptiness[dim] = true;
00289           }
00290         continue;
00291       }
00292       if (gen.is_point()) {
00293         if (first_point == NULL) {
00294           first_point = &gen_sys[row];
00295           continue;
00296         }
00297         const Grid_Generator& point = *first_point;
00298         // Convert the point `gen' to a parameter.
00299         dimension_type dim = num_dims;
00300         do {
00301           gen[dim] -= point[dim];
00302         }
00303         while (dim-- > 0);
00304         gen.set_divisor(point.divisor());
00305       }
00306       for (dimension_type dim = num_dims; dim-- > 0; )
00307         if (!interval_emptiness[dim])
00308           gcd_assign(interval_sizes[dim], interval_sizes[dim], gen[dim+1]);
00309     }
00310 
00311     // For each dimension set the lower bound of the interval to the
00312     // grid value closest to the origin, and the upper bound to the
00313     // addition of the lower bound and the shortest distance in the
00314     // given dimension between any two grid points.
00315     const Grid_Generator& point = *first_point;
00316     const Coefficient& divisor = point.divisor();
00317     TEMP_INTEGER(lower_bound);
00318     for (dimension_type dim = num_dims; dim-- > 0; ) {
00319       if (interval_emptiness[dim])
00320         continue;
00321 
00322       lower_bound = point[dim+1];
00323 
00324       // If the interval size is zero then all points have the same
00325       // value in this dimension, so set only the lower bound.
00326       if (interval_sizes[dim] != 0) {
00327         // Make the lower bound as close as possible to the origin,
00328         // leaving the sign the same.
00329         lower_bound %= interval_sizes[dim];
00330         // Check if the lowest value the other side of the origin is
00331         // closer to the origin, preferring the lowest positive if they
00332         // are equal.
00333         if (lower_bound > 0) {
00334           if (interval_sizes[dim] - lower_bound < lower_bound)
00335             lower_bound -= interval_sizes[dim];
00336         }
00337         else if (lower_bound < 0
00338                  && interval_sizes[dim] + lower_bound < - lower_bound)
00339           lower_bound += interval_sizes[dim];
00340 
00341         // Reduce the bound fraction first.
00342         bound = interval_sizes[dim] + lower_bound;
00343         gcd_assign(gcd, bound, divisor);
00344         exact_div_assign(bound, bound, gcd);
00345         exact_div_assign(gcd, divisor, gcd);
00346         // `gcd' now holds the reduced divisor.
00347         new_box.add_constraint(gcd*Variable(dim) <= bound);
00348       }
00349 
00350       // Reduce the bound fraction first.
00351       gcd_assign(gcd, lower_bound, divisor);
00352       exact_div_assign(lower_bound, lower_bound, gcd);
00353       exact_div_assign(gcd, divisor, gcd);
00354       // `gcd' now holds the reduced divisor.
00355       new_box.add_constraint(gcd*Variable(dim) >= lower_bound);
00356     }
00357   }
00358   else {
00359     const Grid_Generator& point = gen_sys[0];
00360     const Coefficient& divisor = point.divisor();
00361     // The covering box of a single point has only lower bounds.
00362     for (dimension_type dim = num_dims; dim-- > 0; ) {
00363       // Reduce the bound fraction first.
00364       gcd_assign(gcd, point[dim+1], divisor);
00365       exact_div_assign(bound, point[dim+1], gcd);
00366       exact_div_assign(gcd, divisor, gcd);
00367       // `gcd' now holds the reduced divisor.
00368       new_box.add_constraint(gcd*Variable(dim) >= bound);
00369     }
00370   }
00371 
00372   box.swap(new_box);
00373 }

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 863 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, Parma_Polyhedra_Library::swap(), update_generators(), and upper_triangular().

Referenced by add_congruence_no_check(), add_grid_generator(), add_recycled_congruences(), add_recycled_congruences_and_minimize(), add_recycled_grid_generators(), add_recycled_grid_generators_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_image(), affine_preimage(), ascii_load(), bounded_affine_image(), bounded_affine_preimage(), concatenate_assign(), congruence_widening_assign(), construct(), difference_assign(), 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(), time_elapse_assign(), unconstrain(), and upper_bound_assign().

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

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 253 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< PS >::approximate_partition_aux(), and refine_with_congruence().

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

bool Parma_Polyhedra_Library::Grid::add_congruence_and_minimize ( const Congruence c  ) 

Adds a copy of congruence cg to the system of congruences of this, reducing the result.

Returns:
false if and only if the result is empty.
Exceptions:
std::invalid_argument Thrown if *this and congruence cg are dimension-incompatible.
Deprecated:
See A Note on the Implementation of the Operators.

Definition at line 1122 of file Grid_public.cc.

References add_recycled_congruences_and_minimize().

01122                                                          {
01123   Congruence_System cgs(cg);
01124   return add_recycled_congruences_and_minimize(cgs);
01125 }

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 1144 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(), and generalized_affine_preimage().

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

bool Parma_Polyhedra_Library::Grid::add_grid_generator_and_minimize ( const Grid_Generator g  ) 

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

Returns:
false if and only if the result is empty.
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.
Deprecated:
See A Note on the Implementation of the Operators.

Definition at line 1188 of file Grid_public.cc.

References add_recycled_grid_generators_and_minimize().

01188                                                                 {
01189   Grid_Generator_System gs(g);
01190   return add_recycled_grid_generators_and_minimize(gs);
01191 }

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 263 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().

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

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 cs 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 1194 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(), and limited_generator_extrapolation_assign().

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

bool Parma_Polyhedra_Library::Grid::add_congruences_and_minimize ( const Congruence_System cgs  )  [inline]

Adds a copy of the congruences in cgs to the system of congruences of *this, reducing the result.

Returns:
false if and only if the result is empty.
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.
Deprecated:
See A Note on the Implementation of the Operators.

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

References add_recycled_congruences_and_minimize().

00276                                                                {
00277   Congruence_System cgs_copy = cgs;
00278   return add_recycled_congruences_and_minimize(cgs_copy);
00279 }

bool Parma_Polyhedra_Library::Grid::add_recycled_congruences_and_minimize ( Congruence_System cgs  ) 

Adds the congruences in cgs to the system of congruences of this, reducing the result.

Returns:
false if and only if the result is empty.
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.
Deprecated:
See A Note on the Implementation of the Operators.

Definition at line 1234 of file Grid_public.cc.

References Parma_Polyhedra_Library::Congruence_System::begin(), clear_congruences_minimized(), con_sys, congruences_are_up_to_date(), Parma_Polyhedra_Library::Congruence_System::end(), Parma_Polyhedra_Library::Matrix::has_no_rows(), marked_empty(), minimize(), OK(), Parma_Polyhedra_Library::Congruence_System::recycling_insert(), set_empty(), space_dim, Parma_Polyhedra_Library::Congruence_System::space_dimension(), status, Parma_Polyhedra_Library::Grid::Status::test_zero_dim_univ(), throw_dimension_incompatible(), update_congruences(), and update_generators().

Referenced by add_congruence_and_minimize(), and add_congruences_and_minimize().

01234                                                                      {
01235   // Dimension-compatibility check.
01236   const dimension_type cgs_space_dim = cgs.space_dimension();
01237   if (space_dim < cgs_space_dim)
01238     throw_dimension_incompatible("add_recycled_congruences_and_minimize(cgs)",
01239                                  "cgs", cgs);
01240 
01241   // Adding no congruences: just minimize.
01242   if (cgs.has_no_rows())
01243     return minimize();
01244 
01245   // Dealing with zero-dimensional space grids first.
01246   if (space_dim == 0) {
01247     // In a 0-dimensional space the congruences are trivial (e.g., 0
01248     // == 0 or 1 %= 0) or false (e.g., 1 == 0).  In a system of
01249     // congruences `begin()' and `end()' are equal if and only if the
01250     // system contains only trivial congruences.
01251     if (cgs.begin() == cgs.end())
01252       return true;
01253     // There is a congruence, it must be false, the grid is empty.
01254     if (status.test_zero_dim_univ())
01255       set_empty();
01256     return false;
01257   }
01258 
01259   if (marked_empty())
01260     return false;
01261 
01262   if (!congruences_are_up_to_date())
01263     update_congruences();
01264 
01265   con_sys.recycling_insert(cgs);
01266 
01267   clear_congruences_minimized();
01268 
01269 #ifndef NDEBUG
01270   bool ret = update_generators();
01271   assert(OK());
01272   return ret;
01273 #else
01274   return update_generators();
01275 #endif
01276 }

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

If the constraint c is an equality, it is added to *this.

Parameters:
c The constraint.
Exceptions:
std::invalid_argument Thrown if c is not an equality constraint or if *this and c are dimension-incompatible.

Definition at line 302 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 add_constraint_and_minimize().

00302                                         {
00303   // Space dimension compatibility check.
00304   if (space_dim < c.space_dimension())
00305     throw_dimension_incompatible("add_constraint(c)", "c", c);
00306   if (!marked_empty())
00307     add_constraint_no_check(c);
00308 }

bool Parma_Polyhedra_Library::Grid::add_constraint_and_minimize ( const Constraint c  )  [inline]

If the constraint c is an equality, it is added to *this, reducing the result.

Parameters:
c The constraint.
Returns:
false if and only if the result is empty.
Exceptions:
std::invalid_argument Thrown if *this and c are dimension-incompatible.
Deprecated:
See A Note on the Implementation of the Operators.

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

References add_constraint(), and minimize().

00311                                                      {
00312   add_constraint(c);
00313   return minimize();
00314 }

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

If all constraints in cs are equality constraints, then copies are added to *this.

Parameters:
cs The constraints to be added.
Exceptions:
std::invalid_argument Thrown if cs contains an equality constraint or if *this and cs are dimension-incompatible.

Definition at line 1128 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_constraints_and_minimize(), add_recycled_constraints(), and add_recycled_constraints_and_minimize().

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

bool Parma_Polyhedra_Library::Grid::add_constraints_and_minimize ( const Constraint_System cs  )  [inline]

If all the constraints in cs are equality constraints, then copies are added to *this, reducing the result.

Parameters:
cs The constraints to be added.
Returns:
false if and only if the result is empty.
Exceptions:
std::invalid_argument Thrown if *this and cs are dimension-incompatible.
Deprecated:
See A Note on the Implementation of the Operators.

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

References add_constraints(), and minimize().

00317                                                               {
00318   add_constraints(cs);
00319   return minimize();
00320 }

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

If all the constraints in cs are equality constraints, then they are added to *this.

Parameters:
cs The constraint system to be added to *this. The equalities in cs may be recycled.
Exceptions:
std::invalid_argument Thrown if cs contains an equality constraint or if *this and cs are dimension-incompatible.
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 323 of file Grid.inlines.hh.

References add_constraints().

00323                                                     {
00324   // TODO: really recycle the constraints.
00325   add_constraints(cs);
00326 }

bool Parma_Polyhedra_Library::Grid::add_recycled_constraints_and_minimize ( Constraint_System cs  )  [inline]

If all the constraints in cs are equality constraints, then they are added to *this, reducing the result.

Parameters:
cs The constraint system to be added to *this. The equalities in cs may be recycled.
Returns:
false if and only if the result is empty.
Exceptions:
std::invalid_argument Thrown if *this and cs are dimension-incompatible.
Warning:
The only assumption that can be made about cs upon successful or exceptional return is that it can be safely destroyed.
Deprecated:
See A Note on the Implementation of the Operators.

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

References add_constraints(), and minimize().

00329                                                                  {
00330   add_constraints(cs);
00331   return minimize();
00332 }

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 282 of file Grid.inlines.hh.

References add_congruence().

00282                                                  {
00283   add_congruence(cg);
00284 }

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 287 of file Grid.inlines.hh.

References add_congruences().

00287                                                           {
00288   add_congruences(cgs);
00289 }

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 1407 of file Grid_public.cc.

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

01407                                                    {
01408   // The dimension of `c' must be at most `space_dim'.
01409   if (space_dim < c.space_dimension())
01410     throw_dimension_incompatible("refine_with_constraint(c)", "c", c);
01411   if (marked_empty())
01412     return;
01413   refine_no_check(c);
01414 }

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 1417 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().

01417                                                             {
01418   // The dimension of `cs' must be at most `space_dim'.
01419   if (space_dim < cs.space_dimension())
01420     throw_dimension_incompatible("refine_with_constraints(cs)", "cs", cs);
01421 
01422   for (Constraint_System::const_iterator i = cs.begin(),
01423          cs_end = cs.end(); !marked_empty() && i != cs_end; ++i)
01424     refine_no_check(*i);
01425 }

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 1338 of file Grid_public.cc.

References add_recycled_grid_generators().

01338                                                             {
01339   // TODO: this is just an executable specification.
01340   Grid_Generator_System gs_copy = gs;
01341   add_recycled_grid_generators(gs_copy);
01342 }

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 1279 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(), Parma_Polyhedra_Library::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().

01279                                                                {
01280   // Dimension-compatibility check.
01281   const dimension_type gs_space_dim = gs.space_dimension();
01282   if (space_dim < gs_space_dim)
01283     throw_dimension_incompatible("add_recycled_grid_generators(gs)", "gs", gs);
01284 
01285   // Adding no generators leaves the grid the same.
01286   if (gs.has_no_rows())
01287     return;
01288 
01289   // Adding valid generators to a zero-dimensional grid transforms it
01290   // to the zero-dimensional universe grid.
01291   if (space_dim == 0) {
01292     if (marked_empty())
01293       set_zero_dim_univ();
01294     else
01295       assert(gs.has_points());
01296     assert(OK(true));
01297     return;
01298   }
01299 
01300   if (!marked_empty()) {
01301     // The grid contains at least one point.
01302 
01303     if (!generators_are_up_to_date())
01304       update_generators();
01305     normalize_divisors(gs, gen_sys);
01306 
01307     gen_sys.recycling_insert(gs);
01308 
01309     // Congruences are out of date and generators are not minimized.
01310     clear_congruences_up_to_date();
01311     clear_generators_minimized();
01312 
01313     assert(OK(true));
01314     return;
01315   }
01316 
01317   // The grid is empty.
01318 
01319   // `gs' must contain at least one point.
01320   if (!gs.has_points())
01321     throw_invalid_generators("add_recycled_grid_generators(gs)", "gs");
01322 
01323   // Adjust `gs' to the right dimension.
01324   gs.insert(parameter(0*Variable(space_dim-1)));
01325 
01326   std::swap(gen_sys, gs);
01327 
01328   normalize_divisors(gen_sys);
01329 
01330   // The grid is no longer empty and generators are up-to-date.
01331   set_generators_up_to_date();
01332   clear_empty();
01333 
01334   assert(OK());
01335 }

bool Parma_Polyhedra_Library::Grid::add_grid_generators_and_minimize ( const Grid_Generator_System gs  ) 

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

Returns:
false if and only if the result is empty.
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.
Deprecated:
See A Note on the Implementation of the Operators.

Definition at line 1400 of file Grid_public.cc.

References add_recycled_grid_generators_and_minimize().

01400                                                                          {
01401   // TODO: this is just an executable specification.
01402   Grid_Generator_System gs_copy = gs;
01403   return add_recycled_grid_generators_and_minimize(gs_copy);
01404 }

bool Parma_Polyhedra_Library::Grid::add_recycled_grid_generators_and_minimize ( Grid_Generator_System gs  ) 

Adds the generators in gs to the system of generators of this, reducing the result.

Returns:
false if and only if the result is empty.
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.
Deprecated:
See A Note on the Implementation of the Operators.

Definition at line 1346 of file Grid_public.cc.

References 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(), minimize(), normalize_divisors(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), OK(), Parma_Polyhedra_Library::Grid_Generator_System::recycling_insert(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), Parma_Polyhedra_Library::swap(), throw_dimension_incompatible(), throw_invalid_generators(), update_congruences(), and update_generators().

Referenced by add_grid_generator_and_minimize(), and add_grid_generators_and_minimize().

01346                                                                      {
01347   // Dimension-compatibility check: the dimension of `gs' must be less
01348   // than or equal to that of space_dim.
01349   const dimension_type gs_space_dim = gs.space_dimension();
01350   if (space_dim < gs_space_dim)
01351     throw_dimension_incompatible("add_recycled_generators_and_minimize(gs)",
01352                                  "gs", gs);
01353 
01354   // Adding no generators is equivalent to just requiring reduction.
01355   if (gs.has_no_rows())
01356     return minimize();
01357 
01358   // Adding valid generators to a zero-dimensional grid produces the
01359   // zero-dimensional universe grid.
01360   if (space_dim == 0) {
01361     if (marked_empty())
01362       set_zero_dim_univ();
01363     else
01364       assert(gs.has_points());
01365     assert(OK(true));
01366     return true;
01367   }
01368 
01369   // Adjust `gs' to the right dimension.
01370   gs.insert(parameter(0*Variable(space_dim-1)));
01371 
01372   if (!marked_empty()) {
01373     // The grid contains at least one point.
01374 
01375     if (!generators_are_up_to_date())
01376       update_generators();
01377     normalize_divisors(gs, gen_sys);
01378 
01379     for (dimension_type row = 0,
01380            gs_num_rows = gs.num_rows(); row < gs_num_rows; ++row)
01381       gen_sys.recycling_insert(gs[row]);
01382   }
01383   else {
01384     // The grid is empty: check if `gs' contains a point.
01385     if (!gs.has_points())
01386       throw_invalid_generators("add_recycled_generators_and_minimize(gs)",
01387                                "gs");
01388     std::swap(gen_sys, gs);
01389     normalize_divisors(gen_sys);
01390     clear_empty();
01391   }
01392   clear_generators_minimized();
01393   update_congruences();
01394 
01395   assert(OK(true));
01396   return true;
01397 }

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 1428 of file Grid_public.cc.

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

01428                                        {
01429   // Dimension-compatibility check.
01430   if (space_dim < var.id())
01431     throw_dimension_incompatible("unconstrain(var)", var.id());
01432 
01433   // Do something only if the grid is non-empty.
01434   if (marked_empty()
01435       || (!generators_are_up_to_date() && !update_generators()))
01436     // Empty: do nothing.
01437     return;
01438 
01439   assert(generators_are_up_to_date());
01440   Grid_Generator l = grid_line(var);
01441   gen_sys.recycling_insert(l);
01442   // With the added generator, congruences are out of date.
01443   clear_congruences_up_to_date();
01444   clear_generators_minimized();
01445   assert(OK());
01446 }

void Parma_Polyhedra_Library::Grid::unconstrain ( const Variables_Set &  to_be_unconstrained  ) 

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

Parameters:
to_be_unconstrained 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 to_be_removed.

Definition at line 1449 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, throw_dimension_incompatible(), and update_generators().

01449                                                              {
01450   // The cylindrification wrt no dimensions is a no-op.
01451   // This case also captures the only legal cylindrification
01452   // of a grid in a 0-dim space.
01453   if (to_be_unconstrained.empty())
01454     return;
01455 
01456   // Dimension-compatibility check.
01457   const dimension_type min_space_dim = to_be_unconstrained.space_dimension();
01458   if (space_dim < min_space_dim)
01459     throw_dimension_incompatible("unconstrain(vs)", min_space_dim);
01460 
01461   // Do something only if the grid is non-empty.
01462   if (marked_empty()
01463       || (!generators_are_up_to_date() && !update_generators()))
01464     // Empty: do nothing.
01465     return;
01466 
01467   assert(generators_are_up_to_date());
01468   // Since `gen_sys' is not empty, the space dimension of the inserted
01469   // generators are automatically adjusted.
01470   for (Variables_Set::const_iterator tbu = to_be_unconstrained.begin(),
01471          tbu_end = to_be_unconstrained.end(); tbu != tbu_end; ++tbu) {
01472     Grid_Generator l = grid_line(Variable(*tbu));
01473     gen_sys.recycling_insert(l);
01474   }
01475   // Constraints are no longer up-to-date.
01476   clear_generators_minimized();
01477   clear_congruences_up_to_date();
01478   assert(OK());
01479 }

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 1482 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 intersection_assign_and_minimize(), and is_disjoint_from().

01482                                           {
01483   Grid& x = *this;
01484   // Dimension-compatibility check.
01485   if (x.space_dim != y.space_dim)
01486     throw_dimension_incompatible("intersection_assign(y)", "y", y);
01487 
01488   // If one of the two grids is empty, the intersection is empty.
01489   if (x.marked_empty())
01490     return;
01491   if (y.marked_empty()) {
01492     x.set_empty();
01493     return;
01494   }
01495 
01496   // If both grids are zero-dimensional, then at this point they are
01497   // necessarily universe, so the intersection is also universe.
01498   if (x.space_dim == 0)
01499     return;
01500 
01501   // The congruences must be up-to-date.
01502   if (!x.congruences_are_up_to_date())
01503     x.update_congruences();
01504   if (!y.congruences_are_up_to_date())
01505     y.update_congruences();
01506 
01507   if (!y.con_sys.has_no_rows()) {
01508     x.con_sys.insert(y.con_sys);
01509     // Grid_Generators may be out of date and congruences may have changed
01510     // from minimal form.
01511     x.clear_generators_up_to_date();
01512     x.clear_congruences_minimized();
01513   }
01514 
01515   assert(x.OK() && y.OK());
01516 }

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

Assigns to *this the intersection of *this and y, reducing the result.

Returns:
false if and only if the result is empty.
Exceptions:
std::invalid_argument Thrown if *this and y are dimension-incompatible.
Deprecated:
See A Note on the Implementation of the Operators.

Definition at line 1519 of file Grid_public.cc.

References intersection_assign(), and minimize().

01519                                                        {
01520   intersection_assign(y);
01521   return minimize();
01522 }

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 1525 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(), upper_bound_assign_and_minimize(), and upper_bound_assign_if_exact().

01525                                          {
01526   Grid& x = *this;
01527   // Dimension-compatibility check.
01528   if (x.space_dim != y.space_dim)
01529     throw_dimension_incompatible("upper_bound_assign(y)", "y", y);
01530 
01531   // The join of a grid `gr' with an empty grid is `gr'.
01532   if (y.marked_empty())
01533     return;
01534   if (x.marked_empty()) {
01535     x = y;
01536     return;
01537   }
01538 
01539   // If both grids are zero-dimensional, then they are necessarily
01540   // universe grids, and so is their join.
01541   if (x.space_dim == 0)
01542     return;
01543 
01544   // The generators must be up-to-date.
01545   if (!x.generators_are_up_to_date() && !x.update_generators()) {
01546     // Discovered `x' empty when updating generators.
01547     x = y;
01548     return;
01549   }
01550   if (!y.generators_are_up_to_date() && !y.update_generators())
01551     // Discovered `y' empty when updating generators.
01552     return;
01553 
01554   // Match the divisors of the x and y generator systems.
01555   Grid_Generator_System gs(y.gen_sys);
01556   normalize_divisors(x.gen_sys, gs);
01557   x.gen_sys.recycling_insert(gs);
01558   // Congruences may be out of date and generators may have lost
01559   // minimal form.
01560   x.clear_congruences_up_to_date();
01561   x.clear_generators_minimized();
01562 
01563   // At this point both `x' and `y' are not empty.
01564   assert(x.OK(true) && y.OK(true));
01565 }

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

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

Returns:
false if and only if the result is empty.
Exceptions:
std::invalid_argument Thrown if *this and y are dimension-incompatible.
Deprecated:
See A Note on the Implementation of the Operators.

Definition at line 1568 of file Grid_public.cc.

References minimize(), and upper_bound_assign().

01568                                                       {
01569   upper_bound_assign(y);
01570   return minimize();
01571 }

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 1574 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().

01574                                                   {
01575   Grid& x = *this;
01576 
01577   // Dimension-compatibility check.
01578   if (x.space_dim != y.space_dim)
01579     throw_dimension_incompatible("upper_bound_assign_if_exact(y)", "y", y);
01580 
01581   if (x.marked_empty()
01582       || y.marked_empty()
01583       || x.space_dim == 0
01584       || x.is_included_in(y)
01585       || y.is_included_in(x)) {
01586     upper_bound_assign(y);
01587     return true;
01588   }
01589 
01590   // The above test 'x.is_included_in(y)' will ensure the generators of x
01591   // are up to date.
01592   assert(generators_are_up_to_date());
01593 
01594   Grid x_copy = x;
01595   x_copy.upper_bound_assign(y);
01596   x_copy.difference_assign(y);
01597   if (x_copy.is_included_in(x)) {
01598     upper_bound_assign(y);
01599     return true;
01600   }
01601 
01602   return false;
01603 }

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 1606 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().

01606                                         {
01607   Grid& x = *this;
01608   // Dimension-compatibility check.
01609   if (x.space_dim != y.space_dim)
01610     throw_dimension_incompatible("difference_assign(y)", "y", y);
01611 
01612   if (y.marked_empty() || x.marked_empty())
01613     return;
01614 
01615   // If both grids are zero-dimensional, then they are necessarily
01616   // universe grids, so the result is empty.
01617   if (x.space_dim == 0) {
01618     x.set_empty();
01619     return;
01620   }
01621 
01622   if (y.contains(x)) {
01623     x.set_empty();
01624     return;
01625   }
01626 
01627   Grid new_grid(x.space_dim, EMPTY);
01628 
01629   const Congruence_System& y_cgs = y.congruences();
01630   for (Congruence_System::const_iterator i = y_cgs.begin(),
01631          y_cgs_end = y_cgs.end(); i != y_cgs_end; ++i) {
01632     const Congruence& cg = *i;
01633 
01634     // The 2-complement cg2 of cg = ((e %= 0) / m) is the congruence
01635     // defining the sets of points exactly half-way between successive
01636     // hyperplanes e = km and e = (k+1)m, for any integer k; that is,
01637     // the hyperplanes defined by 2e = (2k + 1)m, for any integer k.
01638     // Thus `cg2' is the congruence ((2e %= m) / 2m).
01639 
01640     // As the grid difference must be a grid, only add the
01641     // 2-complement congruence to x if the resulting grid includes all
01642     // the points in x that did not satisfy `cg'.
01643 
01644     // The 2-complement of cg can be included in the result only if x
01645     // holds points other than those in cg.
01646     if (x.relation_with(cg).implies(Poly_Con_Relation::is_included()))
01647       continue;
01648 
01649     if (cg.is_proper_congruence()) {
01650       const Linear_Expression e = Linear_Expression(cg);
01651       // Congruence cg is ((e %= 0) / m).
01652       const Coefficient& m = cg.modulus();
01653       // If x is included in the grid defined by the congruences cg
01654       // and its 2-complement (i.e. the grid defined by the congruence
01655       // (2e %= 0) / m) then add the 2-complement to the potential
01656       // result.
01657       if (x.relation_with((2*e %= 0) / m)
01658           .implies(Poly_Con_Relation::is_included())) {
01659         Grid z = x;
01660         z.add_congruence_no_check((2*e %= m) / (2*m));
01661         new_grid.upper_bound_assign(z);
01662         continue;
01663       }
01664     }
01665     return;
01666   }
01667 
01668   *this = new_grid;
01669 
01670   assert(OK());
01671 }

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 1674 of file Grid_public.cc.

01674                                                     {
01675   // FIXME: provide a real implementation.
01676   used(y);
01677   return true;
01678 }

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 1681 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().

01683                                                                        {
01684   // The denominator cannot be zero.
01685   if (denominator == 0)
01686     throw_invalid_argument("affine_image(v, e, d)", "d == 0");
01687 
01688   // Dimension-compatibility checks.
01689   // The dimension of `expr' must be at most the dimension of `*this'.
01690   const dimension_type expr_space_dim = expr.space_dimension();
01691   if (space_dim < expr_space_dim)
01692     throw_dimension_incompatible("affine_image(v, e, d)", "e", expr);
01693   // `var' must be one of the dimensions of the grid.
01694   const dimension_type var_space_dim = var.space_dimension();
01695   if (space_dim < var_space_dim)
01696     throw_dimension_incompatible("affine_image(v, e, d)", "v", var);
01697 
01698   if (marked_empty())
01699     return;
01700 
01701   if (var_space_dim <= expr_space_dim && expr[var_space_dim] != 0) {
01702     // The transformation is invertible.
01703     if (generators_are_up_to_date()) {
01704       // Grid_Generator_System::affine_image() requires the third argument
01705       // to be a positive Coefficient.
01706       if (denominator > 0)
01707         gen_sys.affine_image(var_space_dim, expr, denominator);
01708       else
01709         gen_sys.affine_image(var_space_dim, -expr, -denominator);
01710       clear_generators_minimized();
01711       // Strong normalization in gs::affine_image may have modified
01712       // divisors.
01713       normalize_divisors(gen_sys);
01714     }
01715     if (congruences_are_up_to_date()) {
01716       // To build the inverse transformation,
01717       // after copying and negating `expr',
01718       // we exchange the roles of `expr[var_space_dim]' and `denominator'.
01719       Linear_Expression inverse;
01720       if (expr[var_space_dim] > 0) {
01721         inverse = -expr;
01722         inverse[var_space_dim] = denominator;
01723         con_sys.affine_preimage(var_space_dim, inverse, expr[var_space_dim]);
01724       }
01725       else {
01726         // The new denominator is negative: we negate everything once
01727         // more, as Congruence_System::affine_preimage() requires the
01728         // third argument to be positive.
01729         inverse = expr;
01730         inverse[var_space_dim] = denominator;
01731         neg_assign(inverse[var_space_dim]);
01732         con_sys.affine_preimage(var_space_dim, inverse, -expr[var_space_dim]);
01733       }
01734       clear_congruences_minimized();
01735     }
01736   }
01737   else {
01738     // The transformation is not invertible.
01739     // We need an up-to-date system of generators.
01740     if (!generators_are_up_to_date())
01741       minimize();
01742     if (!marked_empty()) {
01743       // Grid_Generator_System::affine_image() requires the third argument
01744       // to be a positive Coefficient.
01745       if (denominator > 0)
01746         gen_sys.affine_image(var_space_dim, expr, denominator);
01747       else
01748         gen_sys.affine_image(var_space_dim, -expr, -denominator);
01749 
01750       clear_congruences_up_to_date();
01751       clear_generators_minimized();
01752       // Strong normalization in gs::affine_image may have modified
01753       // divisors.
01754       normalize_divisors(gen_sys);
01755     }
01756   }
01757   assert(OK());
01758 }

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 1762 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().

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

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 1836 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().

01840                                                                     {
01841 
01842   // The denominator cannot be zero.
01843   if (denominator == 0)
01844     throw_invalid_argument("generalized_affine_image(v, r, e, d, m)",
01845                            "d == 0");
01846 
01847   // Dimension-compatibility checks.
01848   // The dimension of `expr' should not be greater than the dimension
01849   // of `*this'.
01850   const dimension_type expr_space_dim = expr.space_dimension();
01851   if (space_dim < expr_space_dim)
01852     throw_dimension_incompatible("generalized_affine_image(v, r, e, d, m)",
01853                                  "e", expr);
01854   // `var' should be one of the dimensions of the grid.
01855   const dimension_type var_space_dim = var.space_dimension();
01856   if (space_dim < var_space_dim)
01857     throw_dimension_incompatible("generalized_affine_image(v, r, e, d, m)",
01858                                  "v", var);
01859 
01860   // Any image of an empty grid is empty.
01861   if (marked_empty())
01862     return;
01863 
01864   // If relsym is not EQUAL, then we return a safe approximation
01865   // by adding a line in the direction of var.
01866   if (relsym != EQUAL) {
01867 
01868     if (modulus != 0)
01869       throw_invalid_argument("generalized_affine_image(v, r, e, d, m)",
01870                              "r != EQUAL && m != 0");
01871 
01872     if (!generators_are_up_to_date())
01873       minimize();
01874 
01875     // Any image of an empty grid is empty.
01876     if (marked_empty())
01877       return;
01878 
01879     add_grid_generator(grid_line(var));
01880 
01881     assert(OK());
01882     return;
01883   }
01884 
01885   assert(relsym == EQUAL);
01886 
01887   affine_image(var, expr, denominator);
01888 
01889   if (modulus == 0)
01890     return;
01891 
01892   // Modulate dimension `var' according to `modulus'.
01893 
01894   if (!generators_are_up_to_date())
01895     minimize();
01896 
01897   // Test if minimization, possibly in affine_image, found an empty
01898   // grid.
01899   if (marked_empty())
01900     return;
01901 
01902   if (modulus < 0)
01903     gen_sys.insert(parameter(-modulus * var));
01904   else
01905     gen_sys.insert(parameter(modulus * var));
01906 
01907   normalize_divisors(gen_sys);
01908 
01909   clear_generators_minimized();
01910   clear_congruences_up_to_date();
01911 
01912   assert(OK());
01913 }

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 1916 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(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), TEMP_INTEGER, throw_dimension_incompatible(), and throw_invalid_argument().

Referenced by bounded_affine_preimage().

01920                                                                        {
01921   // The denominator cannot be zero.
01922   if (denominator == 0)
01923     throw_invalid_argument("generalized_affine_preimage(v, e, d, m)",
01924                            "d == 0");
01925 
01926   // The dimension of `expr' should be at most the dimension of
01927   // `*this'.
01928   const dimension_type expr_space_dim = expr.space_dimension();
01929   if (space_dim < expr_space_dim)
01930     throw_dimension_incompatible("generalized_affine_preimage(v, e, d, m)",
01931                                  "e", expr);
01932   // `var' should be one of the dimensions of the grid.
01933   const dimension_type var_space_dim = var.space_dimension();
01934   if (space_dim < var_space_dim)
01935     throw_dimension_incompatible("generalized_affine_preimage(v, e, d, m)",
01936                                  "v", var);
01937 
01938   // If relsym is not EQUAL, then we return a safe approximation
01939   // by adding a line in the direction of var.
01940   if (relsym != EQUAL) {
01941 
01942     if (modulus != 0)
01943       throw_invalid_argument("generalized_affine_preimage(v, r, e, d, m)",
01944                              "r != EQUAL && m != 0");
01945 
01946     if (!generators_are_up_to_date())
01947       minimize();
01948 
01949     // Any image of an empty grid is empty.
01950     if (marked_empty())
01951       return;
01952 
01953     add_grid_generator(grid_line(var));
01954 
01955     assert(OK());
01956     return;
01957   }
01958 
01959   assert(relsym == EQUAL);
01960   // Any image of an empty grid is empty.
01961   if (marked_empty())
01962     return;
01963 
01964   // Check whether the affine relation is an affine function.
01965   if (modulus == 0) {
01966     affine_preimage(var, expr, denominator);
01967     return;
01968   }
01969 
01970   // Check whether the preimage of this affine relation can be easily
01971   // computed as the image of its inverse relation.
01972   const Coefficient& var_coefficient = expr.coefficient(var);
01973   if (var_space_dim <= expr_space_dim && var_coefficient != 0) {
01974     Linear_Expression inverse_expr
01975       = expr - (denominator + var_coefficient) * var;
01976     TEMP_INTEGER(inverse_denominator);
01977     neg_assign(inverse_denominator, var_coefficient);
01978     if (modulus < 0)
01979       generalized_affine_image(var, EQUAL, inverse_expr, inverse_denominator,
01980                                - modulus);
01981     else
01982       generalized_affine_image(var, EQUAL, inverse_expr, inverse_denominator,
01983                                modulus);
01984     return;
01985   }
01986 
01987   // Here `var_coefficient == 0', so that the preimage cannot be
01988   // easily computed by inverting the affine relation.  Add the
01989   // congruence induced by the affine relation.
01990   {
01991     Congruence cg((denominator*var %= expr) / denominator);
01992     if (modulus < 0)
01993       cg /= -modulus;
01994     else
01995       cg /= modulus;
01996     add_congruence_no_check(cg);
01997   }
01998 
01999   // If the resulting grid is empty, its preimage is empty too.
02000   // Note: DO check for emptiness here, as we will later add a line.
02001   if (is_empty())
02002     return;
02003   add_grid_generator(grid_line(var));
02004   assert(OK());
02005 }

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 2009 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(), Parma_Polyhedra_Library::Grid_Generator_System::recycling_insert(), remove_higher_space_dimensions(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), TEMP_INTEGER, throw_dimension_incompatible(), throw_invalid_argument(), and update_generators().

02012                                                                     {
02013   // Dimension-compatibility checks.
02014   // The dimension of `lhs' should be at most the dimension of
02015   // `*this'.
02016   dimension_type lhs_space_dim = lhs.space_dimension();
02017   if (space_dim < lhs_space_dim)
02018     throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
02019                                  "e1", lhs);
02020   // The dimension of `rhs' should be at most the dimension of
02021   // `*this'.
02022   const dimension_type rhs_space_dim = rhs.space_dimension();
02023   if (space_dim < rhs_space_dim)
02024     throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
02025                                  "e2", rhs);
02026 
02027   // Any image of an empty grid is empty.
02028   if (marked_empty())
02029     return;
02030 
02031   // If relsym is not EQUAL, then we return a safe approximation
02032   // by adding a line in the direction of var.
02033   if (relsym != EQUAL) {
02034 
02035     if (modulus != 0)
02036       throw_invalid_argument("generalized_affine_image(e1, r, e2, m)",
02037                              "r != EQUAL && m != 0");
02038 
02039     if (!generators_are_up_to_date())
02040       minimize();
02041 
02042     // Any image of an empty grid is empty.
02043     if (marked_empty())
02044       return;
02045 
02046     for (dimension_type i = space_dim; i-- > 0; )
02047       if (lhs.coefficient(Variable(i)) != 0)
02048         add_grid_generator(grid_line(Variable(i)));
02049 
02050     assert(OK());
02051     return;
02052   }
02053 
02054   assert(relsym == EQUAL);
02055 
02056   TEMP_INTEGER(tmp_modulus);
02057   tmp_modulus = modulus;
02058   if (tmp_modulus < 0)
02059     neg_assign(tmp_modulus);
02060 
02061   // Compute the actual space dimension of `lhs',
02062   // i.e., the highest dimension having a non-zero coefficient in `lhs'.
02063   do {
02064     if (lhs_space_dim == 0) {
02065       // All variables have zero coefficients, so `lhs' is a constant.
02066       add_congruence_no_check((lhs %= rhs) / tmp_modulus);
02067       return;
02068     }
02069   }
02070   while (lhs.coefficient(Variable(--lhs_space_dim)) == 0);
02071 
02072   // Gather in `new_lines' the collections of all the lines having the
02073   // direction of variables occurring in `lhs'.  While at it, check
02074   // whether there exists a variable occurring in both `lhs' and
02075   // `rhs'.
02076   Grid_Generator_System new_lines;
02077   bool lhs_vars_intersect_rhs_vars = false;
02078   for (dimension_type i = lhs_space_dim + 1; i-- > 0; )
02079     if (lhs.coefficient(Variable(i)) != 0) {
02080       new_lines.insert(grid_line(Variable(i)));
02081       if (rhs.coefficient(Variable(i)) != 0)
02082         lhs_vars_intersect_rhs_vars = true;
02083     }
02084 
02085   if (lhs_vars_intersect_rhs_vars) {
02086     // Some variables in `lhs' also occur in `rhs'.
02087     // To ease the computation, add an additional dimension.
02088     const Variable new_var = Variable(space_dim);
02089     add_space_dimensions_and_embed(1);
02090 
02091     // Constrain the new dimension to be equal to the right hand side.
02092     // TODO: Use add_congruence() when it has been updated.
02093     Congruence_System new_cgs1(new_var == rhs);
02094     add_recycled_congruences(new_cgs1);
02095     if (!is_empty()) {
02096       // The grid still contains points.
02097 
02098       // Existentially quantify all the variables occurring in the left
02099       // hand side expression.
02100 
02101       // Adjust `new_lines' to the right dimension.
02102       new_lines.insert(parameter(0*Variable(space_dim-1)));
02103       // Add the lines to `gen_sys' (first make sure they are up-to-date).
02104       update_generators();
02105       gen_sys.recycling_insert(new_lines);
02106       normalize_divisors(gen_sys);
02107       // Update the flags.
02108       clear_congruences_up_to_date();
02109       clear_generators_minimized();
02110 
02111       // Constrain the new dimension so that it is congruent to the left
02112       // hand side expression modulo `modulus'.
02113       // TODO: Use add_congruence() when it has been updated.
02114       Congruence_System new_cgs2((lhs %= new_var) / tmp_modulus);
02115       add_recycled_congruences(new_cgs2);
02116     }
02117 
02118     // Remove the temporarily added dimension.
02119     remove_higher_space_dimensions(space_dim-1);
02120   }
02121   else {
02122     // `lhs' and `rhs' variables are disjoint:
02123     // there is no need to add a further dimension.
02124 
02125     // Only add the lines and congruence if there are points.
02126     if (is_empty())
02127       return;
02128 
02129     // Existentially quantify all the variables occurring in the left hand
02130     // side expression.
02131     add_recycled_grid_generators(new_lines);
02132 
02133     // Constrain the left hand side expression so that it is congruent to
02134     // the right hand side expression modulo `modulus'.
02135     add_congruence_no_check((lhs %= rhs) / tmp_modulus);
02136   }
02137 
02138   assert(OK());
02139 }

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 2142 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(), Parma_Polyhedra_Library::Grid_Generator_System::recycling_insert(), remove_higher_space_dimensions(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), TEMP_INTEGER, throw_dimension_incompatible(), throw_invalid_argument(), and update_generators().

02145                                                                        {
02146 
02147   // The dimension of `lhs' must be at most the dimension of `*this'.
02148   dimension_type lhs_space_dim = lhs.space_dimension();
02149   if (space_dim < lhs_space_dim)
02150     throw_dimension_incompatible("generalized_affine_preimage(e1, e2, m)",
02151                                  "lhs", lhs);
02152   // The dimension of `rhs' must be at most the dimension of `*this'.
02153   const dimension_type rhs_space_dim = rhs.space_dimension();
02154   if (space_dim < rhs_space_dim)
02155     throw_dimension_incompatible("generalized_affine_preimage(e1, e2, m)",
02156                                  "e2", rhs);
02157 
02158   // Any preimage of an empty polyhedron is empty.
02159   if (marked_empty())
02160     return;
02161 
02162   // If relsym is not EQUAL, then we return a safe approximation
02163   // by adding a line in the direction of var.
02164   if (relsym != EQUAL) {
02165 
02166     if (modulus != 0)
02167       throw_invalid_argument("generalized_affine_preimage(e1, r, e2, m)",
02168                              "r != EQUAL && m != 0");
02169 
02170     if (!generators_are_up_to_date())
02171       minimize();
02172 
02173     // Any image of an empty grid is empty.
02174     if (marked_empty())
02175       return;
02176 
02177     for (dimension_type i = lhs_space_dim + 1; i-- > 0; )
02178       if (lhs.coefficient(Variable(i)) != 0)
02179         add_grid_generator(grid_line(Variable(i)));
02180 
02181     assert(OK());
02182     return;
02183   }
02184 
02185   assert(relsym == EQUAL);
02186 
02187   TEMP_INTEGER(tmp_modulus);
02188   tmp_modulus = modulus;
02189   if (tmp_modulus < 0)
02190     neg_assign(tmp_modulus);
02191 
02192   // Compute the actual space dimension of `lhs',
02193   // i.e., the highest dimension having a non-zero coefficient in `lhs'.
02194   do {
02195     if (lhs_space_dim == 0) {
02196       // All variables have zero coefficients, so `lhs' is a constant.
02197       // In this case, preimage and image happen to be the same.
02198       add_congruence_no_check((lhs %= rhs) / tmp_modulus);
02199       return;
02200     }
02201   }
02202   while (lhs.coefficient(Variable(--lhs_space_dim)) == 0);
02203 
02204   // Gather in `new_lines' the collections of all the lines having
02205   // the direction of variables occurring in `lhs'.
02206   // While at it, check whether or not there exists a variable
02207   // occurring in both `lhs' and `rhs'.
02208   Grid_Generator_System new_lines;
02209   bool lhs_vars_intersect_rhs_vars = false;
02210   for (dimension_type i = lhs_space_dim + 1; i-- > 0; )
02211     if (lhs.coefficient(Variable(i)) != 0) {
02212       new_lines.insert(grid_line(Variable(i)));
02213       if (rhs.coefficient(Variable(i)) != 0)
02214         lhs_vars_intersect_rhs_vars = true;
02215     }
02216 
02217   if (lhs_vars_intersect_rhs_vars) {
02218     // Some variables in `lhs' also occur in `rhs'.
02219     // To ease the computation, add an additional dimension.
02220     const Variable new_var = Variable(space_dim);
02221     add_space_dimensions_and_embed(1);
02222 
02223     // Constrain the new dimension to be equal to `lhs'
02224     // TODO: Use add_congruence() when it has been updated.
02225     Congruence_System new_cgs1(new_var == lhs);
02226     add_recycled_congruences(new_cgs1);
02227     if (!is_empty()) {
02228       // The grid still contains points.
02229 
02230       // Existentially quantify all the variables occurring in the left
02231       // hand side
02232 
02233       // Adjust `new_lines' to the right dimension.
02234       new_lines.insert(parameter(0*Variable(space_dim-1)));
02235       // Add the lines to `gen_sys' (first make sure they are up-to-date).
02236       update_generators();
02237       gen_sys.recycling_insert(new_lines);
02238       normalize_divisors(gen_sys);
02239       // Update the flags.
02240       clear_congruences_up_to_date();
02241       clear_generators_minimized();
02242 
02243       // Constrain the new dimension so that it is related to
02244       // the right hand side modulo `modulus'.
02245       // TODO: Use add_congruence() when it has been updated.
02246       Congruence_System new_cgs2((rhs %= new_var) / tmp_modulus);
02247       add_recycled_congruences(new_cgs2);
02248     }
02249 
02250     // Remove the temporarily added dimension.
02251     remove_higher_space_dimensions(space_dim-1);
02252   }
02253   else {
02254     // `lhs' and `rhs' variables are disjoint:
02255     // there is no need to add a further dimension.
02256 
02257     // Constrain the left hand side expression so that it is congruent to
02258     // the right hand side expression modulo `mod'.
02259     add_congruence_no_check((lhs %= rhs) / tmp_modulus);
02260 
02261     // Any image of an empty grid is empty.
02262     if (is_empty())
02263       return;
02264 
02265     // Existentially quantify all the variables occurring in `lhs'.
02266     add_recycled_grid_generators(new_lines);
02267   }
02268   assert(OK());
02269 }

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 2273 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().

02276                                                                     {
02277 
02278   // The denominator cannot be zero.
02279   if (denominator == 0)
02280     throw_invalid_argument("bounded_affine_image(v, lb, ub, d)", "d == 0");
02281 
02282   // Dimension-compatibility checks.
02283   // `var' should be one of the dimensions of the polyhedron.
02284   const dimension_type var_space_dim = var.space_dimension();
02285   if (space_dim < var_space_dim)
02286     throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
02287                                  "v", var);
02288   // The dimension of `lb_expr' and `ub_expr' should not be
02289   // greater than the dimension of `*this'.
02290   const dimension_type lb_space_dim = lb_expr.space_dimension();
02291   if (space_dim < lb_space_dim)
02292     throw_dimension_incompatible("bounded_affine_image(v, lb, ub)",
02293                                  "lb", lb_expr);
02294   const dimension_type ub_space_dim = ub_expr.space_dimension();
02295   if (space_dim < ub_space_dim)
02296     throw_dimension_incompatible("bounded_affine_image(v, lb, ub)",
02297                                  "ub", ub_expr);
02298 
02299   // Any image of an empty grid is empty.
02300   if (marked_empty())
02301     return;
02302 
02303   // In all other cases, generalized_affine_preimage() must
02304   // just add a line in the direction of var.
02305   generalized_affine_image(var,
02306                            LESS_OR_EQUAL,
02307                            ub_expr,
02308                            denominator);
02309 
02310   assert(OK());
02311 }

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 2316 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().

02319                                                                        {
02320 
02321   // The denominator cannot be zero.
02322   if (denominator == 0)
02323     throw_invalid_argument("bounded_affine_preimage(v, lb, ub, d)", "d == 0");
02324 
02325   // Dimension-compatibility checks.
02326   // `var' should be one of the dimensions of the polyhedron.
02327   const dimension_type var_space_dim = var.space_dimension();
02328   if (space_dim < var_space_dim)
02329     throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
02330                                  "v", var);
02331   // The dimension of `lb_expr' and `ub_expr' should not be
02332   // greater than the dimension of `*this'.
02333   const dimension_type lb_space_dim = lb_expr.space_dimension();
02334   if (space_dim < lb_space_dim)
02335     throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)",
02336                                  "lb", lb_expr);
02337   const dimension_type ub_space_dim = ub_expr.space_dimension();
02338   if (space_dim < ub_space_dim)
02339     throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)",
02340                                  "ub", ub_expr);
02341 
02342   // Any preimage of an empty polyhedron is empty.
02343   if (marked_empty())
02344     return;
02345 
02346   // In all other cases, generalized_affine_preimage() must
02347   // just add a line in the direction of var.
02348   generalized_affine_preimage(var,
02349                               LESS_OR_EQUAL,
02350                               ub_expr,
02351                               denominator);
02352 
02353   assert(OK());
02354 }

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 2357 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().

02357                                          {
02358   Grid& x = *this;
02359   // Check dimension-compatibility.
02360   if (x.space_dim != y.space_dim)
02361     throw_dimension_incompatible("time_elapse_assign(y)", "y", y);
02362 
02363   // Deal with the zero-dimensional case.
02364   if (x.space_dim == 0) {
02365     if (y.marked_empty())
02366       x.set_empty();
02367     return;
02368   }
02369 
02370   // If either one of `x' or `y' is empty, the result is empty too.
02371   if (x.marked_empty())
02372     return;
02373   if (y.marked_empty()
02374       || (!x.generators_are_up_to_date() && !x.update_generators())
02375       || (!y.generators_are_up_to_date() && !y.update_generators())) {
02376     x.set_empty();
02377     return;
02378   }
02379 
02380   // At this point both generator systems are up-to-date.
02381   Grid_Generator_System gs = y.gen_sys;
02382   dimension_type gs_num_rows = gs.num_rows();
02383 
02384   normalize_divisors(gs, gen_sys);
02385 
02386   for (dimension_type i = gs_num_rows; i-- > 0; ) {
02387     Grid_Generator& g = gs[i];
02388     if (g.is_point())
02389       // Transform the point into a parameter.
02390       g.set_is_parameter();
02391   }
02392 
02393   if (gs_num_rows == 0)
02394     // `y' was the grid containing a single point at the origin, so
02395     // the result is `x'.
02396     return;
02397 
02398   // Append `gs' to the generators of `x'.
02399 
02400   gen_sys.recycling_insert(gs);
02401 
02402   x.clear_congruences_up_to_date();
02403   x.clear_generators_minimized();
02404 
02405   assert(x.OK(true) && y.OK(true));
02406 }

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

Assigns to *this its topological closure.

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

00390                                  {
00391   return;
00392 }

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 75 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, Parma_Polyhedra_Library::swap(), throw_dimension_incompatible(), and update_congruences().

Referenced by limited_congruence_extrapolation_assign(), and widening_assign().

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

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 277 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, Parma_Polyhedra_Library::swap(), throw_dimension_incompatible(), and update_generators().

Referenced by limited_generator_extrapolation_assign(), and widening_assign().

00277                                                                     {
00278   Grid& x = *this;
00279   Grid& y = const_cast<Grid&>(const_y);
00280   // Dimension-compatibility check.
00281   if (x.space_dim != y.space_dim)
00282     throw_dimension_incompatible("generator_widening_assign(y)", "y", y);
00283 
00284   // Stable behavior is only guaranteed if y is contained in or equal
00285   // to x.
00286 #ifndef NDEBUG
00287   {
00288     // Assume y is contained in or equal to x.
00289     const Grid x_copy = x;
00290     const Grid y_copy = y;
00291     assert(x_copy.contains(y_copy));
00292   }
00293 #endif
00294 
00295   // Leave `x' the same if `x' or `y' is zero-dimensional or empty.
00296   if (x.space_dim == 0 || x.marked_empty() || y.marked_empty())
00297     return;
00298 
00299   // Ensure that the `x' generators are in minimal form.
00300   if (x.generators_are_up_to_date()) {
00301     if (!x.generators_are_minimized()) {
00302       simplify(x.gen_sys, x.dim_kinds);
00303       assert(!x.gen_sys.has_no_rows());
00304       x.set_generators_minimized();
00305     }
00306   }
00307   else
00308     x.update_generators();
00309 
00310   if (x.marked_empty())
00311     return;
00312 
00313   // Ensure that the `y' generators are in minimal form.
00314   if (y.generators_are_up_to_date()) {
00315     if (!y.generators_are_minimized()) {
00316       simplify(y.gen_sys, y.dim_kinds);
00317       assert(!y.gen_sys.has_no_rows());
00318       y.set_generators_minimized();
00319     }
00320   }
00321   else
00322     y.update_generators();
00323 
00324   if (gen_sys.num_rows() > y.gen_sys.num_rows())
00325     return;
00326 
00327   if (gen_sys.num_lines() > y.gen_sys.num_lines())
00328     return;
00329 
00330   // Copy into `ggs' the generators of `x' that are common to `y',
00331   // according to the grid widening.
00332   Grid_Generator_System ggs;
00333   x.select_wider_generators(y, ggs);
00334 
00335   if (ggs.num_parameters() == gen_sys.num_parameters())
00336     // All parameters are kept as parameters, thus the result is `x'.
00337     return;
00338 
00339   // A strict subset of the parameters was selected.
00340 
00341   Grid result(x.space_dim, EMPTY);
00342   result.add_recycled_grid_generators(ggs);
00343 
00344   // Check whether we are using the widening-with-tokens technique
00345   // and there are still tokens available.
00346   if (tp && *tp > 0) {
00347     // There are tokens available.  If `result' is not a subset of
00348     // `x', then it is less precise and we use one of the available
00349     // tokens.
00350     if (!x.contains(result))
00351       --(*tp);
00352   }
00353   else
00354     // No tokens.
00355     std::swap(x, result);
00356 
00357   assert(x.OK(true));
00358 }

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 431 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().

00431                                                           {
00432   Grid& x = *this;
00433   Grid& y = const_cast<Grid&>(const_y);
00434   // Dimension-compatibility check.
00435   if (x.space_dim != y.space_dim)
00436     throw_dimension_incompatible("widening_assign(y)", "y", y);
00437 
00438   // Stable behavior is only guaranteed if y is contained in or equal
00439   // to x.
00440 #ifndef NDEBUG
00441   {
00442     // Assume y is contained in or equal to x.
00443     const Grid x_copy = x;
00444     const Grid y_copy = y;
00445     assert(x_copy.contains(y_copy));
00446   }
00447 #endif
00448 
00449   // If the `x' congruences are up to date and `y' congruences are up
00450   // to date use the congruence widening.
00451   if (x.congruences_are_up_to_date() && y.congruences_are_up_to_date()) {
00452     x.congruence_widening_assign(y, tp);
00453     return;
00454   }
00455 
00456   // If the `x' generators are up to date and `y' generators are up to
00457   // date use the generator widening.
00458   if (x.generators_are_up_to_date() && y.generators_are_up_to_date()) {
00459     x.generator_widening_assign(y, tp);
00460     return;
00461   }
00462 
00463   x.congruence_widening_assign(y, tp);
00464 }

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 cs are dimension-incompatible.

Definition at line 159 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().

00161                                                                  {
00162   Grid& x = *this;
00163 
00164   // Check dimension compatibility.
00165   if (x.space_dim != y.space_dim)
00166     throw_dimension_incompatible("limited_extrapolation_assign(y, cgs)",
00167                                  "y", y);
00168   // `cgs' must be dimension-compatible with the two grids.
00169   const dimension_type cgs_space_dim = cgs.space_dimension();
00170   if (x.space_dim < cgs_space_dim)
00171     throw_dimension_incompatible("limited_extrapolation_assign(y, cgs)",
00172                                  "cgs", cgs);
00173 
00174   const dimension_type cgs_num_rows = cgs.num_rows();
00175   // If `cgs' is empty (of rows), fall back to ordinary widening.
00176   if (cgs_num_rows == 0) {
00177     x.widening_assign(y, tp);
00178     return;
00179   }
00180 
00181 #ifndef NDEBUG
00182   {
00183     // Assume that y is contained in or equal to x.
00184     const Grid x_copy = x;
00185     const Grid y_copy = y;
00186     assert(x_copy.contains(y_copy));
00187   }
00188 #endif
00189 
00190   if (y.marked_empty())
00191     return;
00192   if (x.marked_empty())
00193     return;
00194 
00195   // The limited widening between two grids in a zero-dimensional
00196   // space is also a grid in a zero-dimensional space.
00197   if (x.space_dim == 0)
00198     return;
00199 
00200   // Update the generators of `x': these are used to select, from the
00201   // congruences in `cgs', those that must be added to the widened
00202   // grid.
00203   if (!x.generators_are_up_to_date() && !x.update_generators())
00204     // `x' is empty.
00205     return;
00206 
00207   if (tp == NULL || *tp == 0) {
00208     // Widening may change the grid, so add the congruences.
00209     Congruence_System new_cgs;
00210     // The congruences to be added need only be satisfied by all the
00211     // generators of `x', as `y <= x'.  Iterate upwards here, to keep
00212     // the relative ordering of congruences (just for aesthetics).
00213     for (dimension_type i = 0; i < cgs_num_rows; ++i) {
00214       const Congruence& cg = cgs[i];
00215       if (x.relation_with(cg) == Poly_Con_Relation::is_included())
00216         new_cgs.insert(cg);
00217     }
00218     x.congruence_widening_assign(y, tp);
00219     x.add_recycled_congruences(new_cgs);
00220   }
00221   else
00222     // There are tokens, so widening will leave the grid the same.
00223     x.congruence_widening_assign(y, tp);
00224 
00225   assert(OK());
00226 }

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 cs are dimension-incompatible.

Definition at line 361 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().

00363                                                                 {
00364   Grid& x = *this;
00365 
00366   // Check dimension compatibility.
00367   if (x.space_dim != y.space_dim)
00368     throw_dimension_incompatible("limited_extrapolation_assign(y, cgs)",
00369                                  "y", y);
00370   // `cgs' must be dimension-compatible with the two grids.
00371   const dimension_type cgs_space_dim = cgs.space_dimension();
00372   if (x.space_dim < cgs_space_dim)
00373     throw_dimension_incompatible("limited_extrapolation_assign(y, cgs)",
00374                                  "cgs", cgs);
00375 
00376   const dimension_type cgs_num_rows = cgs.num_rows();
00377   // If `cgs' is empty (of rows), fall back to ordinary widening.
00378   if (cgs_num_rows == 0) {
00379     x.generator_widening_assign(y, tp);
00380     return;
00381   }
00382 
00383 #ifndef NDEBUG
00384   {
00385     // Assume that y is contained in or equal to x.
00386     const Grid x_copy = x;
00387     const Grid y_copy = y;
00388     assert(x_copy.contains(y_copy));
00389   }
00390 #endif
00391 
00392   if (y.marked_empty())
00393     return;
00394   if (x.marked_empty())
00395     return;
00396 
00397   // The limited widening between two grids in a zero-dimensional
00398   // space is also a grid in a zero-dimensional space.
00399   if (x.space_dim == 0)
00400     return;
00401 
00402   // Update the generators of `x': these are used to select, from the
00403   // congruences in `cgs', those that must be added to the widened
00404   // grid.
00405   if (!x.generators_are_up_to_date() && !x.update_generators())
00406     // `x' is empty.
00407     return;
00408 
00409   if (tp == NULL || *tp == 0) {
00410     // Widening may change the grid, so add the congruences.
00411     Congruence_System new_cgs;
00412     // The congruences to be added need only be satisfied by all the
00413     // generators of `x', as `y <= x'.  Iterate upwards here, to keep
00414     // the relative ordering of congruences (just for aesthetics).
00415     for (dimension_type i = 0; i < cgs_num_rows; ++i) {
00416       const Congruence& cg = cgs[i];
00417       if (x.relation_with(cg) == Poly_Con_Relation::is_included())
00418         new_cgs.insert(cg);
00419     }
00420     x.generator_widening_assign(y, tp);
00421     x.add_recycled_congruences(new_cgs);
00422   }
00423   else
00424     // There are tokens, so widening will leave the grid the same.
00425     x.generator_widening_assign(y, tp);
00426 
00427   assert(OK());
00428 }

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 cs are dimension-incompatible.

Definition at line 467 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().

00469                                                       {
00470   Grid& x = *this;
00471 
00472   // Check dimension compatibility.
00473   if (x.space_dim != y.space_dim)
00474     throw_dimension_incompatible("limited_extrapolation_assign(y, cgs)",
00475                                  "y", y);
00476   // `cgs' must be dimension-compatible with the two grids.
00477   const dimension_type cgs_space_dim = cgs.space_dimension();
00478   if (x.space_dim < cgs_space_dim)
00479     throw_dimension_incompatible("limited_extrapolation_assign(y, cgs)",
00480                                  "cgs", cgs);
00481 
00482   const dimension_type cgs_num_rows = cgs.num_rows();
00483   // If `cgs' is empty (of rows), fall back to ordinary widening.
00484   if (cgs_num_rows == 0) {
00485     x.widening_assign(y, tp);
00486     return;
00487   }
00488 
00489 #ifndef NDEBUG
00490   {
00491     // Assume that y is contained in or equal to x.
00492     const Grid x_copy = x;
00493     const Grid y_copy = y;
00494     assert(x_copy.contains(y_copy));
00495   }
00496 #endif
00497 
00498   if (y.marked_empty())
00499     return;
00500   if (x.marked_empty())
00501     return;
00502 
00503   // The limited widening between two grids in a zero-dimensional
00504   // space is also a grid in a zero-dimensional space.
00505   if (x.space_dim == 0)
00506     return;
00507 
00508   // Update the generators of `x': these are used to select, from the
00509   // congruences in `cgs', those that must be added to the widened
00510   // grid.
00511   if (!x.generators_are_up_to_date() && !x.update_generators())
00512     // `x' is empty.
00513     return;
00514 
00515   if (tp == NULL || *tp == 0) {
00516     // Widening may change the grid, so add the congruences.
00517     Congruence_System new_cgs;
00518     // The congruences to be added need only be satisfied by all the
00519     // generators of `x', as `y <= x'.  Iterate upwards here, to keep
00520     // the relative ordering of congruences (just for aesthetics).
00521     for (dimension_type i = 0; i < cgs_num_rows; ++i) {
00522       const Congruence& cg = cgs[i];
00523       if (x.relation_with(cg) == Poly_Con_Relation::is_included())
00524         new_cgs.insert(cg);
00525     }
00526     x.widening_assign(y, tp);
00527     x.add_recycled_congruences(new_cgs);
00528   }
00529   else
00530     // There are tokens, so widening will leave the grid the same.
00531     x.widening_assign(y, tp);
00532 
00533   assert(OK());
00534 }

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 78 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(), and generalized_affine_preimage().

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

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 152 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.

00152                                                           {
00153   if (m == 0)
00154     return;
00155 
00156   // The space dimension of the resulting grid should be at most the
00157   // maximum allowed space dimension.
00158   if (m > max_space_dimension() - space_dimension())
00159     throw_space_dimension_overflow("add_space_dimensions_and_project(m)",
00160                                    "adding m new space dimensions exceeds "
00161                                    "the maximum allowed space dimension");
00162 
00163   // Adding dimensions to an empty grid is obtained by merely
00164   // adjusting `space_dim'.
00165   if (marked_empty()) {
00166     space_dim += m;
00167     set_empty();
00168     return;
00169   }
00170 
00171   if (space_dim == 0) {
00172     assert(status.test_zero_dim_univ());
00173     // Swap *this with a newly created `n'-dimensional universe grid.
00174     Grid gr(m, UNIVERSE);
00175     swap(gr);
00176     return;
00177   }
00178 
00179   // To project an n-dimension space grid in a (n+m)-dimension space,
00180   // we just add to the system of generators `m' zero-columns; in
00181   // contrast, in the system of congruences, new rows are needed in
00182   // order to avoid embedding the old grid in the new space.  Thus,
00183   // for each new dimensions `x[k]', we add the constraint x[k] = 0;
00184   // this is done by invoking the function add_space_dimensions()
00185   // giving the system of constraints as the second argument.
00186   if (congruences_are_up_to_date())
00187     if (generators_are_up_to_date())
00188       // Add rows and/or columns to both matrices.
00189       add_space_dimensions(gen_sys, con_sys, m);
00190     else {
00191       // Only congruences are up-to-date so modify only them.
00192       con_sys.add_unit_rows_and_columns(m);
00193       if (congruences_are_minimized())
00194         dim_kinds.resize(con_sys.num_columns() - 1, EQUALITY);
00195     }
00196   else {
00197     // Only generators are up-to-date so modify only them.
00198     assert(generators_are_up_to_date());
00199 
00200     // Add m zero columns onto gs.
00201     gen_sys.insert(parameter(0*Variable(space_dim + m - 1)));
00202 
00203     normalize_divisors(gen_sys);
00204 
00205     if (generators_are_minimized())
00206       dim_kinds.resize(gen_sys.space_dimension() + 1, EQUALITY);
00207   }
00208   // Now update the space dimension.
00209   space_dim += m;
00210 
00211   // Note: we do not check for satisfiability, because the system of
00212   // congruences may be unsatisfiable.
00213   assert(OK());
00214 }

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 217 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().

00217                                          {
00218   // The space dimension of the resulting grid must be at most the
00219   // maximum allowed space dimension.
00220   if (y.space_dim > max_space_dimension() - space_dimension())
00221     throw_space_dimension_overflow("concatenate_assign(y)",
00222                                    "concatenation exceeds the maximum "
00223                                    "allowed space dimension");
00224 
00225   const dimension_type added_columns = y.space_dim;
00226 
00227   // If `*this' or `y' are empty grids just adjust the space
00228   // dimension.
00229   if (marked_empty() || y.marked_empty()) {
00230     space_dim += added_columns;
00231     set_empty();
00232     return;
00233   }
00234 
00235   // If `y' is a universe 0-dim grid, the result is `*this'.
00236   if (added_columns == 0)
00237     return;
00238 
00239   // If `*this' is a universe 0-dim space grid, the result is `y'.
00240   if (space_dim == 0) {
00241     *this = y;
00242     return;
00243   }
00244 
00245   if (!congruences_are_up_to_date())
00246     update_congruences();
00247 
00248   con_sys.concatenate(y.congruences());
00249 
00250   space_dim += added_columns;
00251 
00252   clear_congruences_minimized();
00253   clear_generators_up_to_date();
00254 
00255   // Check that the system is OK, taking into account that the system
00256   // of congruences may now be empty.
00257   assert(OK());
00258 }

void Parma_Polyhedra_Library::Grid::remove_space_dimensions ( const Variables_Set &  to_be_removed  ) 

Removes all the specified dimensions from the vector space.

Parameters:
to_be_removed 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 to_be_removed.

Definition at line 261 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, throw_dimension_incompatible(), and update_generators().

Referenced by fold_space_dimensions().

00261                                                                    {
00262   // The removal of no dimensions from any grid is a no-op.  This case
00263   // also captures the only legal removal of dimensions from a grid in
00264   // a 0-dim space.
00265   if (to_be_removed.empty()) {
00266     assert(OK());
00267     return;
00268   }
00269 
00270   // Dimension-compatibility check.
00271   const dimension_type min_space_dim = to_be_removed.space_dimension();
00272   if (space_dim < min_space_dim)
00273     throw_dimension_incompatible("remove_space_dimensions(vs)", min_space_dim);
00274 
00275   const dimension_type new_space_dim = space_dim - to_be_removed.size();
00276 
00277   if (marked_empty()
00278       || (!generators_are_up_to_date() && !update_generators())) {
00279     // Update the space dimension.
00280     space_dim = new_space_dim;
00281     set_empty();
00282     assert(OK());
00283     return;
00284   }
00285 
00286   // Removing _all_ dimensions from a non-empty grid obtains the
00287   // zero-dimensional universe grid.
00288   if (new_space_dim == 0) {
00289     set_zero_dim_univ();
00290     return;
00291   }
00292 
00293   gen_sys.remove_space_dimensions(to_be_removed);
00294 
00295   clear_congruences_up_to_date();
00296   clear_generators_minimized();
00297 
00298   // Update the space dimension.
00299   space_dim = new_space_dim;
00300 
00301   assert(OK(true));
00302 }

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 305 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().

00305                                                                           {
00306   // Dimension-compatibility check.
00307   if (new_dimension > space_dim)
00308     throw_dimension_incompatible("remove_higher_space_dimensions(nd)",
00309                                  new_dimension);
00310 
00311   // The removal of no dimensions from any grid is a no-op.
00312   // Note that this case also captures the only legal removal of
00313   // dimensions from a grid in a 0-dim space.
00314   if (new_dimension == space_dim) {
00315     assert(OK());
00316     return;
00317   }
00318 
00319   if (is_empty()) {
00320     // Removing dimensions from the empty grid just updates the space
00321     // dimension.
00322     space_dim = new_dimension;
00323     set_empty();
00324     assert(OK());
00325     return;
00326   }
00327 
00328   if (new_dimension == 0) {
00329     // Removing all dimensions from a non-empty grid just returns the
00330     // zero-dimensional universe grid.
00331     set_zero_dim_univ();
00332     return;
00333   }
00334 
00335   // Favor the generators, as is done by is_empty().
00336   if (generators_are_up_to_date()) {
00337     gen_sys.remove_higher_space_dimensions(new_dimension);
00338     if (generators_are_minimized()) {
00339       // Count the actual number of rows that are now redundant.
00340       dimension_type num_redundant = 0;
00341       const dimension_type num_old_gs = space_dim - new_dimension;
00342       for (dimension_type row = 0; row < num_old_gs; ++row)
00343         dim_kinds[row] == GEN_VIRTUAL || ++num_redundant;
00344       if (num_redundant > 0) {
00345         // Chop zero rows from end of system, to keep minimal form.
00346         gen_sys.erase_to_end(gen_sys.num_rows() - num_redundant);
00347         gen_sys.unset_pending_rows();
00348       }
00349       dim_kinds.erase(dim_kinds.begin() + new_dimension + 1, dim_kinds.end());
00350       // TODO: Consider if it is worth also preserving the congruences
00351       //       if they are also in minimal form.
00352     }
00353     clear_congruences_up_to_date();
00354     // Extend the zero dim false congruence system to the appropriate
00355     // dimension and then swap it with `con_sys'.
00356     Congruence_System cgs(Congruence::zero_dim_false());
00357     // Extra 2 columns for inhomogeneous term and modulus.
00358     cgs.increase_space_dimension(new_dimension + 2);
00359     con_sys.swap(cgs);
00360   }
00361   else {
00362     assert(congruences_are_minimized());
00363     con_sys.remove_higher_space_dimensions(new_dimension);
00364     // Count the actual number of rows that are now redundant.
00365     dimension_type num_redundant = 0;
00366     for (dimension_type row = space_dim; row > new_dimension; --row)
00367       dim_kinds[row] == CON_VIRTUAL || ++num_redundant;
00368     if (num_redundant > 0) {
00369       dimension_type rows = con_sys.num_rows();
00370       // Shuffle the remaining rows upwards.
00371       for (dimension_type low = 0, high = num_redundant;
00372            high < rows;
00373            ++high, ++low)
00374         std::swap(con_sys[low], con_sys[high]);
00375       // Chop newly redundant rows from end of system, to keep minimal
00376       // form.
00377       con_sys.erase_to_end(rows - num_redundant);
00378     }
00379     dim_kinds.erase(dim_kinds.begin() + new_dimension + 1, dim_kinds.end());
00380     clear_generators_up_to_date();
00381     // Replace gen_sys with an empty system of the right dimension.
00382     // Extra 2 columns for inhomogeneous term and modulus.
00383     Grid_Generator_System gs(new_dimension + 2);
00384     gen_sys.swap(gs);
00385   }
00386 
00387   // Update the space dimension.
00388   space_dim = new_dimension;
00389 
00390   assert(OK(true));
00391 }

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 class 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 377 of file Grid.templates.hh.

References Parma_Polyhedra_Library::Grid_Generator_System::begin(), clear_congruences_minimized(), clear_generators_minimized(), Parma_Polyhedra_Library::Generator::CLOSURE_POINT, 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, Parma_Polyhedra_Library::swap(), throw_invalid_argument(), Parma_Polyhedra_Library::Grid_Generator::type(), and update_generators().

00377                                                         {
00378   if (space_dim == 0)
00379     return;
00380 
00381   if (pfunc.has_empty_codomain()) {
00382     // All dimensions vanish: the grid becomes zero_dimensional.
00383     if (marked_empty()
00384         || (!generators_are_up_to_date() && !update_generators())) {
00385       // Removing all dimensions from the empty grid.
00386       space_dim = 0;
00387       set_empty();
00388     }
00389     else
00390       // Removing all dimensions from a non-empty grid.
00391       set_zero_dim_univ();
00392 
00393     assert(OK());
00394     return;
00395   }
00396 
00397   dimension_type new_space_dimension = pfunc.max_in_codomain() + 1;
00398 
00399   if (new_space_dimension == space_dim) {
00400     // The partial function `pfunc' is indeed total and thus specifies
00401     // a permutation, that is, a renaming of the dimensions.  For
00402     // maximum efficiency, we will simply permute the columns of the
00403     // constraint system and/or the generator system.
00404 
00405     // We first compute suitable permutation cycles for the columns of
00406     // the `con_sys' and `gen_sys' matrices.  We will represent them
00407     // with a linear array, using 0 as a terminator for each cycle
00408     // (notice that the columns with index 0 of `con_sys' and
00409     // `gen_sys' represent the inhomogeneous terms, and thus are
00410     // unaffected by the permutation of dimensions).
00411     // Cycles of length 1 will be omitted so that, in the worst case,
00412     // we will have `space_dim' elements organized in `space_dim/2'
00413     // cycles, which means we will have at most `space_dim/2'
00414     // terminators.
00415     std::vector<dimension_type> cycles;
00416     cycles.reserve(space_dim + space_dim/2);
00417 
00418     // Used to mark elements as soon as they are inserted in a cycle.
00419     std::deque<bool> visited(space_dim);
00420 
00421     for (dimension_type i = space_dim; i-- > 0; ) {
00422       if (!visited[i]) {
00423         dimension_type j = i;
00424         do {
00425           visited[j] = true;
00426           // The following initialization is only to make the compiler happy.
00427           dimension_type k = 0;
00428           if (!pfunc.maps(j, k))
00429             throw_invalid_argument("map_space_dimensions(pfunc)",
00430                                    " pfunc is inconsistent");
00431           if (k == j)
00432             // Cycle of length 1: skip it.
00433             goto skip;
00434 
00435           cycles.push_back(j+1);
00436           // Go along the cycle.
00437           j = k;
00438         } while (!visited[j]);
00439         // End of cycle: mark it.
00440         cycles.push_back(0);
00441       skip:
00442         ;
00443       }
00444     }
00445 
00446     // If `cycles' is empty then `pfunc' is the identity.
00447     if (cycles.empty())
00448       return;
00449 
00450     // Permute all that is up-to-date.
00451     if (congruences_are_up_to_date()) {
00452       con_sys.permute_columns(cycles);
00453       clear_congruences_minimized();
00454     }
00455 
00456     if (generators_are_up_to_date()) {
00457       gen_sys.permute_columns(cycles);
00458       clear_generators_minimized();
00459     }
00460 
00461     assert(OK());
00462     return;
00463   }
00464 
00465   // If control gets here, then `pfunc' is not a permutation and some
00466   // dimensions must be projected away.
00467 
00468   const Grid_Generator_System& old_gensys = grid_generators();
00469 
00470   if (old_gensys.has_no_rows()) {
00471     // The grid is empty.
00472     Grid new_grid(new_space_dimension, EMPTY);
00473     std::swap(*this, new_grid);
00474     assert(OK());
00475     return;
00476   }
00477 
00478   // Make a local copy of the partial function.
00479   std::vector<dimension_type> pfunc_maps(space_dim, not_a_dimension());
00480   for (dimension_type j = space_dim; j-- > 0; ) {
00481     dimension_type pfunc_j;
00482     if (pfunc.maps(j, pfunc_j))
00483       pfunc_maps[j] = pfunc_j;
00484   }
00485 
00486   Grid_Generator_System new_gensys;
00487   // Set sortedness, for the assertion met via gs::insert.
00488   new_gensys.set_sorted(false);
00489   // Get the divisor of the first point.
00490   Grid_Generator_System::const_iterator i;
00491   Grid_Generator_System::const_iterator old_gensys_end = old_gensys.end();
00492   for (i = old_gensys.begin(); i != old_gensys_end; ++i)
00493     if (i->is_point())
00494       break;
00495   assert(i != old_gensys_end);
00496   const Coefficient& system_divisor = i->divisor();
00497   for (i = old_gensys.begin(); i != old_gensys_end; ++i) {
00498     const Grid_Generator& old_g = *i;
00499     Linear_Expression e(0 * Variable(new_space_dimension-1));
00500     bool all_zeroes = true;
00501     for (dimension_type j = space_dim; j-- > 0; ) {
00502       if (old_g.coefficient(Variable(j)) != 0
00503           && pfunc_maps[j] != not_a_dimension()) {
00504         e += Variable(pfunc_maps[j]) * old_g.coefficient(Variable(j));
00505         all_zeroes = false;
00506       }
00507     }
00508     switch (old_g.type()) {
00509     case Grid_Generator::LINE:
00510       if (!all_zeroes)
00511         new_gensys.insert(grid_line(e));
00512       break;
00513     case Grid_Generator::PARAMETER:
00514       if (!all_zeroes)
00515         new_gensys.insert(parameter(e, system_divisor));
00516       break;
00517     case Grid_Generator::POINT:
00518       new_gensys.insert(grid_point(e, old_g.divisor()));
00519       break;
00520     case Grid_Generator::CLOSURE_POINT:
00521     default:
00522       assert(0);
00523     }
00524   }
00525 
00526   Grid new_grid(new_gensys);
00527   std::swap(*this, new_grid);
00528 
00529   assert(OK(true));
00530 }

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 394 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().

00394                                                               {
00395   // TODO: this implementation is _really_ an executable specification.
00396 
00397   // `var' must be one of the dimensions of the vector space.
00398   if (var.space_dimension() > space_dim)
00399     throw_dimension_incompatible("expand_space_dimension(v, m)", "v", var);
00400 
00401   // Adding 0 dimensions leaves the same grid.
00402   if (m == 0)
00403     return;
00404 
00405   // The resulting space dimension must be at most the maximum.
00406   if (m > max_space_dimension() - space_dimension())
00407     throw_space_dimension_overflow("expand_space_dimension(v, m)",
00408                                    "adding m new space dimensions exceeds "
00409                                    "the maximum allowed space dimension");
00410 
00411   // Save the number of dimensions before adding new ones.
00412   dimension_type old_dim = space_dim;
00413 
00414   // Add the required new dimensions.
00415   add_space_dimensions_and_embed(m);
00416 
00417   const dimension_type src_d = var.id();
00418   const Congruence_System& cgs = congruences();
00419   Congruence_System new_congruences;
00420   for (Congruence_System::const_iterator i = cgs.begin(),
00421          cgs_end = cgs.end(); i != cgs_end; ++i) {
00422     const Congruence& cg = *i;
00423 
00424     // Only consider congruences that constrain `var'.
00425     if (cg.coefficient(var) == 0)
00426       continue;
00427 
00428     // Each relevant congruence results in `m' new congruences.
00429     for (dimension_type dst_d = old_dim; dst_d < old_dim+m; ++dst_d) {
00430       Linear_Expression e;
00431       for (dimension_type j = old_dim; j-- > 0; )
00432         e +=
00433           cg.coefficient(Variable(j))
00434           * (j == src_d ? Variable(dst_d) : Variable(j));
00435       new_congruences.insert_verbatim((e + cg.inhomogeneous_term() %= 0)
00436                                       / cg.modulus());
00437     }
00438   }
00439   add_recycled_congruences(new_congruences);
00440   assert(OK());
00441 }

void Parma_Polyhedra_Library::Grid::fold_space_dimensions ( const Variables_Set &  to_be_folded,
Variable  var 
)

Folds the space dimensions in to_be_folded into var.

Parameters:
to_be_folded The set of Variable objects corresponding to the space dimensions to be folded;
var 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 var or with one of the Variable objects contained in to_be_folded. Also thrown if var is contained in to_be_folded.
If *this has space dimension $n$, with $n > 0$, var has space dimension $k \leq n$, to_be_folded is a set of variables whose maximum space dimension is also less than or equal to $n$, and var is not a member of to_be_folded, then the space dimensions corresponding to variables in to_be_folded are folded into the $k$-th space dimension.

Definition at line 444 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::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   // `var' should be one of the dimensions of the grid.
00449   if (var.space_dimension() > space_dim)
00450     throw_dimension_incompatible("fold_space_dimensions(tbf, v)", "v", var);
00451 
00452   // Folding only has effect if dimensions are given.
00453   if (to_be_folded.empty())
00454     return;
00455 
00456   // All variables in `to_be_folded' must be dimensions of the grid.
00457   if (to_be_folded.space_dimension() > space_dim)
00458     throw_dimension_incompatible("fold_space_dimensions(tbf, v)",
00459                                  "tbf.space_dimension()",
00460                                  to_be_folded.space_dimension());
00461 
00462   // Moreover, `var.id()' must not occur in `to_be_folded'.
00463   if (to_be_folded.find(var.id()) != to_be_folded.end())
00464     throw_invalid_argument("fold_space_dimensions(tbf, v)",
00465                            "v should not occur in tbf");
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 = to_be_folded.begin(),
00475            tbf_end = to_be_folded.end(); i != tbf_end; ++i) {
00476       Grid copy = *this;
00477       copy.affine_image(var, Linear_Expression(Variable(*i)));
00478       upper_bound_assign(copy);
00479     }
00480   }
00481   remove_space_dimensions(to_be_folded);
00482   assert(OK());
00483 }

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

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

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

References con_sys, dim_kinds, gen_sys, space_dim, status, and Parma_Polyhedra_Library::swap().

Referenced by add_space_dimensions_and_embed(), add_space_dimensions_and_project(), construct(), set_empty(), and swap().

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

void Parma_Polyhedra_Library::Grid::ascii_dump (  )  const

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

Referenced by OK().

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

Writes to s an ASCII representation of *this.

Definition at line 2468 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.

02468                                        {
02469   using std::endl;
02470 
02471   s << "space_dim "
02472     << space_dim
02473     << endl;
02474   status.ascii_dump(s);
02475   s << "con_sys ("
02476     << (congruences_are_up_to_date() ? "" : "not_")
02477     << "up-to-date)"
02478     << endl;
02479   con_sys.ascii_dump(s);
02480   s << "gen_sys ("
02481     << (generators_are_up_to_date() ? "" : "not_")
02482     << "up-to-date)"
02483     << endl;
02484   gen_sys.ascii_dump(s);
02485   s << "dimension_kinds";
02486   if ((generators_are_up_to_date() && generators_are_minimized())
02487       || (congruences_are_up_to_date() && congruences_are_minimized()))
02488     for (Dimension_Kinds::const_iterator i = dim_kinds.begin();
02489          i != dim_kinds.end();
02490          ++i)
02491       s << " " << *i;
02492   s << endl;
02493 }

void Parma_Polyhedra_Library::Grid::print (  )  const

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

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 2498 of file Grid_public.cc.

References Parma_Polyhedra_Library::Grid_Generator_System::ascii_load(), Parma_Polyhedra_Library::Congruence_System::ascii_load(), Parma_Polyhedra_Library::Grid::Status::ascii_load(), con_sys, congruences_are_minimized(), congruences_are_up_to_date(), dim_kinds, gen_sys, GEN_VIRTUAL, generators_are_minimized(), generators_are_up_to_date(), LINE, marked_empty(), OK(), PARAMETER, set_congruences_up_to_date(), set_generators_up_to_date(), space_dim, and status.

02498                                  {
02499   std::string str;
02500 
02501   if (!(s >> str) || str != "space_dim")
02502     return false;
02503 
02504   if (!(s >> space_dim))
02505     return false;
02506 
02507   if (!status.ascii_load(s))
02508     return false;
02509 
02510   if (!(s >> str) || str != "con_sys")
02511     return false;
02512 
02513   if (s >> str) {
02514     if (str == "(up-to-date)")
02515       set_congruences_up_to_date();
02516     else if (str != "(not_up-to-date)")
02517       return false;
02518   }
02519   else
02520     return false;
02521 
02522   if (!con_sys.ascii_load(s))
02523     return false;
02524 
02525   if (!(s >> str) || str != "gen_sys")
02526     return false;
02527 
02528   if (s >> str) {
02529     if (str == "(up-to-date)")
02530       set_generators_up_to_date();
02531     else if (str != "(not_up-to-date)")
02532       return false;
02533   }
02534   else
02535     return false;
02536 
02537   if (!gen_sys.ascii_load(s))
02538     return false;
02539 
02540   if (!(s >> str) || str != "dimension_kinds")
02541     return false;
02542 
02543   if (!marked_empty()
02544       && ((generators_are_up_to_date() && generators_are_minimized())
02545           || (congruences_are_up_to_date() && congruences_are_minimized()))) {
02546     dim_kinds.resize(space_dim + 1);
02547     for (Dimension_Kinds::size_type dim = 0; dim <= space_dim; ++dim) {
02548       short unsigned int dim_kind;
02549       if (!(s >> dim_kind))
02550         return false;
02551       switch(dim_kind) {
02552       case 0: dim_kinds[dim] = PARAMETER; break;
02553       case 1: dim_kinds[dim] = LINE; break;
02554       case 2: dim_kinds[dim] = GEN_VIRTUAL; break;
02555       default: return false;
02556       }
02557     }
02558   }
02559 
02560   // Check invariants.
02561   assert(OK());
02562   return true;
02563 }

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 224 of file Grid.inlines.hh.

References external_memory_in_bytes().

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

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 2566 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().

02566                                         {
02567   return
02568     con_sys.external_memory_in_bytes()
02569     + gen_sys.external_memory_in_bytes();
02570 }

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 229 of file Grid.inlines.hh.

References space_dimension().

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

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 51 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().

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

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 104 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, Parma_Polyhedra_Library::swap(), and Parma_Polyhedra_Library::Congruence::zero_dim_false().

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

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 142 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, Parma_Polyhedra_Library::swap(), throw_invalid_generators(), and Parma_Polyhedra_Library::Congruence::zero_dim_false().

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

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 34 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_congruences_and_minimize(), add_recycled_grid_generators(), add_recycled_grid_generators_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_image(), affine_preimage(), ascii_load(), bounded_affine_image(), bounded_affine_preimage(), bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), concatenate_assign(), congruence_widening_assign(), congruences(), constrains(), contains(), contains_integer_point(), difference_assign(), fold_space_dimensions(), generalized_affine_image(), generalized_affine_preimage(), generator_widening_assign(), get_covering_box(), 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(), and upper_bound_assign_if_exact().

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

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

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

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

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

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

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

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

Definition at line 357 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_recycled_congruences_and_minimize(), 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(), and update_generators().

00357                    {
00358   status.set_empty();
00359 
00360   // Replace gen_sys with an empty system of the right dimension.
00361   Grid_Generator_System gs(space_dim);
00362   gen_sys.swap(gs);
00363 
00364   // Extend the zero dim false congruence system to the appropriate
00365   // dimension and then swap it with `con_sys'.
00366   Congruence_System cgs(Congruence::zero_dim_false());
00367   cgs.increase_space_dimension(space_dim);
00368   const_cast<Congruence_System&>(con_sys).swap(cgs);
00369 }

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 64 of file Grid.inlines.hh.

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

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

00064                                  {
00065   status.set_c_up_to_date();
00066 }

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 59 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(), ascii_load(), construct(), Grid(), and set_generators_minimized().

00059                                 {
00060   status.set_g_up_to_date();
00061 }

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

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

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

Clears the status flag indicating that the grid is empty.

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

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

Referenced by add_grid_generator(), add_recycled_grid_generators(), and add_recycled_grid_generators_and_minimize().

00081                   {
00082   status.reset_empty();
00083 }

void Parma_Polyhedra_Library::Grid::clear_congruences_up_to_date (  )  [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 103 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().

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

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

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

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

Updates and minimizes the congruences from the generators.

Definition at line 372 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(), add_recycled_congruences_and_minimize(), add_recycled_grid_generators_and_minimize(), concatenate_assign(), congruence_widening_assign(), congruences(), constrains(), intersection_assign(), is_included_in(), is_universe(), minimize(), and relation_with().

00372                                   {
00373   // The caller must ensure that the generators are up to date.
00374   assert(space_dim > 0);
00375   assert(!marked_empty());
00376   assert(!gen_sys.has_no_rows());
00377   assert(gen_sys.space_dimension() > 0);
00378 
00379   Grid& gr = const_cast<Grid&>(*this);
00380 
00381   if (!generators_are_minimized())
00382     gr.simplify(gr.gen_sys, gr.dim_kinds);
00383 
00384   // `gen_sys' contained rows before being reduced, so it should
00385   // contain at least a single point afterward.
00386   assert(!gen_sys.has_no_rows());
00387 
00388   // Populate `con_sys' with congruences characterizing the grid
00389   // described by `gen_sys'.
00390   gr.conversion(gr.gen_sys, gr.con_sys, gr.dim_kinds);
00391 
00392   // Both systems are minimized.
00393   gr.set_congruences_minimized();
00394   gr.set_generators_minimized();
00395 }

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 398 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_congruences_and_minimize(), add_recycled_grid_generators(), add_recycled_grid_generators_and_minimize(), bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), generalized_affine_image(), generalized_affine_preimage(), generator_widening_assign(), get_covering_box(), 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().

00398                                  {
00399   assert(space_dim > 0);
00400   assert(!marked_empty());
00401   assert(congruences_are_up_to_date());
00402 
00403   Grid& x = const_cast<Grid&>(*this);
00404 
00405   if (!congruences_are_minimized())
00406     // Either the system of congruences is consistent, or the grid is
00407     // empty.
00408     if (simplify(x.con_sys, x.dim_kinds)) {
00409       x.set_empty();
00410       return false;
00411     }
00412 
00413   // Populate gen_sys with generators characterizing the grid
00414   // described by con_sys.
00415   conversion(x.con_sys, x.gen_sys, x.dim_kinds);
00416 
00417   // Both systems are minimized.
00418   x.set_congruences_minimized();
00419   x.set_generators_minimized();
00420   return true;
00421 }

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 424 of file Grid_nonpublic.cc.

References con_sys, congruences_are_minimized(), congruences_are_up_to_date(), dim_kinds, empty, 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 add_constraint_and_minimize(), add_constraints_and_minimize(), add_recycled_congruences_and_minimize(), add_recycled_constraints_and_minimize(), add_recycled_grid_generators_and_minimize(), affine_image(), affine_preimage(), constrains(), generalized_affine_image(), generalized_affine_preimage(), intersection_assign_and_minimize(), and upper_bound_assign_and_minimize().

00424                         {
00425   // 0-dimension and empty grids are already minimized.
00426   if (marked_empty())
00427     return false;
00428   if (space_dim == 0)
00429     return true;
00430 
00431   // Are both systems already minimized?
00432   if (congruences_are_minimized() && generators_are_minimized())
00433     return true;
00434 
00435   // Invoke update_generators, update_congruences or simplify,
00436   // depending on the state of the systems.
00437   if (congruences_are_up_to_date()) {
00438     if (generators_are_up_to_date()) {
00439       Grid& gr = const_cast<Grid&>(*this);
00440       // Only one of the systems can be minimized here.
00441       if (congruences_are_minimized()) {
00442         // Minimize the generator system.
00443         gr.simplify(gr.gen_sys, gr.dim_kinds);
00444         gr.set_generators_minimized();
00445       }
00446       else {
00447 #ifndef NDEBUG
00448         // Both systems are up to date, and the empty case is handled
00449         // above, so the grid should contain points.
00450         bool empty = simplify(gr.con_sys, gr.dim_kinds);
00451         assert(!empty);
00452 #else
00453         simplify(gr.con_sys, gr.dim_kinds);
00454 #endif
00455         gr.set_congruences_minimized();
00456         if (!generators_are_minimized()) {
00457           // Minimize the generator system.
00458           gr.simplify(gr.gen_sys, gr.dim_kinds);
00459           gr.set_generators_minimized();
00460         }
00461       }
00462     }
00463     else {
00464       // Updating the generators may reveal that `*this' is empty.
00465       const bool ret = update_generators();
00466       assert(OK());
00467       return ret;
00468     }
00469   }
00470   else {
00471     assert(generators_are_up_to_date());
00472     update_congruences();
00473   }
00474   assert(OK());
00475   return true;
00476 }

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 181 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().

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

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 237 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(), and upper_bound_assign_if_exact().

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

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 274 of file Grid_nonpublic.cc.

References gen_sys, generators_are_up_to_date(), 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, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and update_generators().

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

00275                                                  {
00276   // The dimension of `expr' must be at most the dimension of *this.
00277   if (space_dim < expr.space_dimension())
00278     throw_dimension_incompatible(method_call, "e", expr);
00279 
00280   // A zero-dimensional or empty grid bounds everything.
00281   if (space_dim == 0
00282       || marked_empty()
00283       || (!generators_are_up_to_date() && !update_generators()))
00284     return true;
00285 
00286   // The generators are up to date.
00287   for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) {
00288     const Grid_Generator& g = gen_sys[i];
00289     // Only lines and parameters in `*this' can cause `expr' to be
00290     // unbounded.
00291     if (g.is_line_or_parameter()) {
00292       const int sp_sign = Scalar_Products::homogeneous_sign(expr, g);
00293       if (sp_sign != 0)
00294         // `*this' does not bound `expr'.
00295         return false;
00296     }
00297   }
00298   return true;
00299 }

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 302 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(), set_generators_minimized(), simplify(), space_dim, and TEMP_INTEGER.

Referenced by maximize(), and minimize().

00305                                            {
00306   if (bounds(expr, method_call)) {
00307     if (marked_empty())
00308       return false;
00309     if (space_dim == 0) {
00310       ext_n = 0;
00311       ext_d = 1;
00312       included = true;
00313       if (point)
00314         *point = Generator::point();
00315       return true;
00316     }
00317     // Grid::bounds above ensures the generators are up to date.
00318     if (!generators_are_minimized()) {
00319       // Minimize the generator system.
00320       Grid& gr = const_cast<Grid&>(*this);
00321       gr.simplify(gr.gen_sys, gr.dim_kinds);
00322       gr.set_generators_minimized();
00323     }
00324 
00325     const Grid_Generator& gen = gen_sys[0];
00326     Scalar_Products::homogeneous_assign(ext_n, expr, gen);
00327     ext_n += expr.inhomogeneous_term();
00328     ext_d = gen.divisor();
00329     // Reduce ext_n and ext_d.
00330     TEMP_INTEGER(gcd);
00331     gcd_assign(gcd, ext_n, ext_d);
00332     exact_div_assign(ext_n, ext_n, gcd);
00333     exact_div_assign(ext_d, ext_d, gcd);
00334 
00335     included = true;
00336     if (point) {
00337       Linear_Expression e;
00338       for (dimension_type i = space_dim; i-- > 0; )
00339         e += gen.coefficient(Variable(i)) * Variable(i);
00340       *point = Generator::point(e, gen.divisor());
00341     }
00342     return true;
00343   }
00344   return false;
00345 }

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 behavior is undefined.

Definition at line 555 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().

00555                                                      {
00556   assert(!marked_empty());
00557   assert(space_dim >= cg.space_dimension());
00558 
00559   // Dealing with a zero-dimensional space grid first.
00560   if (space_dim == 0) {
00561     if (cg.is_inconsistent())
00562       set_empty();
00563     return;
00564   }
00565 
00566   if (!congruences_are_up_to_date())
00567     update_congruences();
00568 
00569   con_sys.insert(cg);
00570 
00571   clear_congruences_minimized();
00572   set_congruences_up_to_date();
00573   clear_generators_up_to_date();
00574 
00575   // Note: the congruence system may have become unsatisfiable, thus
00576   // we do not check for satisfiability.
00577   assert(OK());
00578 }

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 581 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().

00581                                                     {
00582   assert(!marked_empty());
00583   assert(space_dim >= c.space_dimension());
00584 
00585   if (c.is_inequality()) {
00586     // Only trivial inequalities can be handled.
00587     if (c.is_inconsistent()) {
00588       set_empty();
00589       return;
00590     }
00591     if (c.is_tautological())
00592       return;
00593     // Non-trivial inequality constraints are not allowed.
00594     throw_invalid_constraint("add_constraint(c)", "c");
00595   }
00596 
00597   assert(c.is_equality());
00598   Congruence cg(c);
00599   add_congruence_no_check(cg);
00600 }

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 603 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().

00603                                             {
00604   assert(!marked_empty());
00605   assert(space_dim >= c.space_dimension());
00606 
00607   if (c.is_equality()) {
00608     Congruence cg(c);
00609     add_congruence_no_check(cg);
00610   }
00611   else if (c.is_inconsistent())
00612     set_empty();
00613 }

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 34 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().

00035                                                                            {
00036   // Private method: the caller must ensure the following conditions
00037   // (beside the inclusion `y <= x').
00038   assert(space_dim == y.space_dim);
00039   assert(!marked_empty());
00040   assert(!y.marked_empty());
00041   assert(congruences_are_minimized());
00042   assert(y.congruences_are_minimized());
00043 
00044   // Note: row counters start at 0, to preserve the original order in
00045   // the selected congruences.
00046   for (dimension_type dim = con_sys.space_dimension(), x_row = 0, y_row = 0;
00047        dim > 0; --dim) {
00048     assert(dim_kinds[dim] == CON_VIRTUAL
00049            || dim_kinds[dim] == y.dim_kinds[dim]);
00050     switch (dim_kinds[dim]) {
00051     case PROPER_CONGRUENCE:
00052       {
00053         const Congruence& cg = con_sys[x_row];
00054         const Congruence& y_cg = y.con_sys[y_row];
00055         if (cg.is_equal_at_dimension(dim, y_cg))
00056           // The leading diagonal entries are equal.
00057           cgs_selected.insert(cg);
00058         ++x_row;
00059         ++y_row;
00060       }
00061       break;
00062     case EQUALITY:
00063       cgs_selected.insert(con_sys[x_row]);
00064       ++x_row;
00065       ++y_row;
00066       break;
00067     case CON_VIRTUAL:
00068       y.dim_kinds[dim] == CON_VIRTUAL || ++y_row;
00069       break;
00070     }
00071   }
00072 }

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 229 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().

00230                                                                               {
00231   // Private method: the caller must ensure the following conditions
00232   // (beside the inclusion `y <= x').
00233   assert(space_dim == y.space_dim);
00234   assert(!marked_empty());
00235   assert(!y.marked_empty());
00236   assert(generators_are_minimized());
00237   assert(y.generators_are_minimized());
00238 
00239   // Note: row counters start at 0, to preserve the original order in
00240   // the selected generators.
00241   for (dimension_type dim = 0, x_row = 0, y_row = 0;
00242        dim <= gen_sys.space_dimension(); ++dim) {
00243     assert(dim_kinds[dim] == LINE
00244            || y.dim_kinds[dim] == GEN_VIRTUAL
00245            || dim_kinds[dim] == y.dim_kinds[dim]);
00246     switch (dim_kinds[dim]) {
00247     case PARAMETER:
00248       {
00249         const Grid_Generator& gg = gen_sys[x_row];
00250         const Grid_Generator& y_gg = y.gen_sys[y_row];
00251         if (gg.is_equal_at_dimension(dim, y_gg))
00252           // The leading diagonal entry is equal.
00253           ggs_selected.insert(gg);
00254         else {
00255           Linear_Expression e;
00256           for (dimension_type i = gg.space_dimension(); i-- > 0; )
00257             e += gg.coefficient(Variable(i)) * Variable(i);
00258           ggs_selected.insert(grid_line(e));
00259         }
00260         ++x_row;
00261         ++y_row;
00262       }
00263       break;
00264     case LINE:
00265       ggs_selected.insert(gen_sys[x_row]);
00266       ++x_row;
00267       ++y_row;
00268       break;
00269     case GEN_VIRTUAL:
00270       y.dim_kinds[dim] == GEN_VIRTUAL || ++y_row;
00271       break;
00272     }
00273   }
00274 }

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 34 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().

00036                                                            {
00037   assert(cgs.num_columns() - 1 == gs.space_dimension() + 1);
00038   assert(dims > 0);
00039 
00040   const dimension_type old_modulus_index = cgs.num_columns() - 1;
00041   cgs.add_zero_columns(dims);
00042   // Move the moduli.
00043   cgs.swap_columns(old_modulus_index, old_modulus_index + dims);
00044 
00045   if (congruences_are_minimized() || generators_are_minimized())
00046     dim_kinds.resize(old_modulus_index + dims, CON_VIRTUAL /* a.k.a. LINE */);
00047 
00048   gs.add_universe_rows_and_columns(dims);
00049 }

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 53 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().

00055                                                            {
00056   assert(cgs.num_columns() - 1 == gs.space_dimension() + 1);
00057   assert(dims > 0);
00058 
00059   cgs.add_unit_rows_and_columns(dims);
00060 
00061   // Add `dims' zero columns onto gs.
00062   gs.insert(parameter(0*Variable(space_dim + dims - 1)));
00063 
00064   normalize_divisors(gs);
00065 
00066   dim_kinds.resize(cgs.num_columns() - 1, EQUALITY /* a.k.a GEN_VIRTUAL */);
00067 }

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 519 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_recycled_grid_generators_and_minimize(), add_space_dimensions(), add_space_dimensions_and_project(), affine_image(), construct(), generalized_affine_image(), generalized_affine_preimage(), Grid(), normalize_divisors(), time_elapse_assign(), and upper_bound_assign().

00521                                                                  {
00522   assert(divisor >= 0);
00523   if (sys.space_dimension() > 0 && divisor > 0) {
00524     dimension_type row = 0;
00525     dimension_type num_rows = sys.num_rows();
00526 
00527     if (first_point)
00528       lcm_assign(divisor, divisor, (*first_point).divisor());
00529     else {
00530       assert(num_rows > 0);
00531       // Move to the first point or parameter.
00532       while (sys[row].is_line())
00533         if (++row == num_rows)
00534           // All rows are lines.
00535           return;
00536 
00537       // Calculate the LCM of the given divisor and the divisor of
00538       // every point or parameter.
00539       while (row < num_rows) {
00540         const Grid_Generator& g = sys[row];
00541         if (g.is_parameter_or_point())
00542           lcm_assign(divisor, divisor, g.divisor());
00543         ++row;
00544       }
00545     }
00546 
00547     // Represent every point and every parameter using the newly
00548     // calculated divisor.
00549     for (row = num_rows; row-- > 0; )
00550       sys[row].scale_to_divisor(divisor);
00551   }
00552 }

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 371 of file Grid.inlines.hh.

References normalize_divisors(), and TEMP_INTEGER.

00371                                                    {
00372   TEMP_INTEGER(divisor);
00373   divisor = 1;
00374   normalize_divisors(sys, divisor);
00375 }

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 479 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 TEMP_INTEGER.

00480                                                               {
00481 #ifndef NDEBUG
00482   const dimension_type num_rows = gen_sys.num_rows();
00483 #endif
00484   assert(num_rows > 0);
00485 
00486   // Find the first point in gen_sys.
00487   dimension_type row = 0;
00488   while (gen_sys[row].is_line_or_parameter()) {
00489     ++row;
00490     // gen_sys should have at least one point.
00491     assert(row < num_rows);
00492   }
00493   Grid_Generator& first_point = gen_sys[row];
00494   const Coefficient& gen_sys_divisor = first_point.divisor();
00495 
00496 #ifndef NDEBUG
00497   // Check that the divisors in gen_sys are equal.
00498   for (dimension_type i = row + 1; i < num_rows; ++i) {
00499     Grid_Generator& g = gen_sys[i];
00500     if (g.is_parameter_or_point())
00501       assert(gen_sys_divisor == g.divisor());
00502   }
00503 #endif // !defined(NDEBUG)
00504 
00505   TEMP_INTEGER(divisor);
00506   divisor = gen_sys_divisor;
00507   // Adjust sys to include the gen_sys divisor.
00508   normalize_divisors(sys, divisor);
00509   if (divisor != gen_sys_divisor)
00510     // Adjust gen_sys to use the new divisor.
00511     //
00512     // The points and parameters in gen_sys share a common divisor
00513     // value, so the new divisor will be the LCM of this common
00514     // divisor and `divisor', hence the third argument.
00515     normalize_divisors(gen_sys, divisor, &first_point);
00516 }

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 313 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, 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(), TEMP_INTEGER, and upper_triangular().

Referenced by update_generators().

00314                                              {
00315   // Quite similar to the generator to congruence version above.
00316   // Changes here may be needed there too.
00317 
00318   assert(lower_triangular(source, dim_kinds));
00319 
00320   // Initialize matrix row number counters and compute the LCM of the
00321   // diagonal entries of the proper congruences in `source'.
00322   dimension_type source_num_rows = 0, dest_num_rows = 0;
00323   TEMP_INTEGER(diagonal_lcm);
00324   diagonal_lcm = 1;
00325   dimension_type dims = source.num_columns() - 1;
00326   for (dimension_type dim = dims; dim-- > 0; )
00327     if (dim_kinds[dim] == CON_VIRTUAL)
00328       // Virtual congruences map to lines.
00329       ++dest_num_rows;
00330     else {
00331       if (dim_kinds[dim] == PROPER_CONGRUENCE) {
00332         // Dimension `dim' has a proper congruence row at
00333         // `source_num_rows' in `source', so include in `diagonal_lcm'
00334         // the `dim'th element of that row.
00335         lcm_assign(diagonal_lcm, diagonal_lcm, source[source_num_rows][dim]);
00336         // Proper congruences map to parameters.
00337         ++dest_num_rows;
00338       }
00339       // Equalities map to virtual generators.
00340       ++source_num_rows;
00341     }
00342 
00343   // `source' must be regular.
00344   if (diagonal_lcm == 0)
00345     throw std::runtime_error("PPL internal error: Grid::conversion:"
00346                              " source matrix is singular.");
00347 
00348   dest.set_index_first_pending_row(dest_num_rows);
00349   dest.resize_no_copy(dest_num_rows, dims + 1 /* parameter divisor */);
00350 
00351   // In `dest' initialize row types and elements, including setting
00352   // the diagonal elements to the inverse ratio of the `source'
00353   // diagonal elements.
00354   //
00355   // The top-down order of the congruence system rows corresponds to
00356   // the right-left order of the dimensions.
00357   dimension_type source_index = 0;
00358   // The generator system has a bottom-up ordering.
00359   dimension_type dest_index = dest_num_rows - 1;
00360   for (dimension_type dim = dims; dim-- > 0; ) {
00361     if (dim_kinds[dim] == EQUALITY) {
00362       ++source_index;
00363     }
00364     else {
00365       Grid_Generator& g = dest[dest_index];
00366       for (dimension_type j = dim; j-- > 0; )
00367         g[j] = 0;
00368       for (dimension_type j = dim + 1; j < dims; ++j)
00369         g[j] = 0;
00370 
00371       if (dim_kinds[dim] == CON_VIRTUAL) {
00372         g.set_is_line();
00373         g[dim] = 1;
00374       }
00375       else {
00376         assert(dim_kinds[dim] == PROPER_CONGRUENCE);
00377         g.set_is_parameter_or_point();
00378         exact_div_assign(g[dim], diagonal_lcm, source[source_index][dim]);
00379         ++source_index;
00380       }
00381       --dest_index;
00382     }
00383   }
00384 
00385   assert(upper_triangular(dest, dim_kinds));
00386 
00387   // Convert.
00388   //
00389   // `source_index' and `dest_index' hold the positions of pivot rows
00390   // in `source' and `dest'.  The order of the rows in `dest' is the
00391   // reverse of the order in `source', so the rows are iterated from
00392   // last to first (index 0) in `source' and from first to last in
00393   // `dest'.
00394   source_index = source_num_rows;
00395   dest_index = 0;
00396   TEMP_INTEGER(reduced_source_dim);
00397 
00398   for (dimension_type dim = 0; dim < dims; ++dim) {
00399     if (dim_kinds[dim] != CON_VIRTUAL) {
00400       --source_index;
00401       const Coefficient& source_dim = source[source_index][dim];
00402 
00403       // In the rows in `dest' above `dest_index' divide each element
00404       // at column `dim' by `source_dim'.
00405       for (dimension_type row = dest_index; row-- > 0; ) {
00406         Grid_Generator& g = dest[row];
00407 
00408         // Multiply the representation of `dest' such that entry `dim'
00409         // of `g' is a multiple of `source_dim'.  This ensures that
00410         // the result of the division that follows is a whole number.
00411         gcd_assign(reduced_source_dim, g[dim], source_dim);
00412         exact_div_assign(reduced_source_dim, source_dim, reduced_source_dim);
00413         multiply_grid(reduced_source_dim, g, dest, dest_num_rows,
00414                       dims + 1 /* parameter divisor */);
00415 
00416         Coefficient& g_dim = g[dim];
00417         exact_div_assign(g_dim, g_dim, source_dim);
00418       }
00419     }
00420 
00421     // Invert and transpose the source row at `source_index' into the
00422     // destination row at `dest_index'.
00423     //
00424     // Consider each dimension `dim_fol' that follows `dim', as the
00425     // rows in `dest' that follow row `dest_index' are zero at index
00426     // `dim'.
00427     dimension_type tmp_source_index = source_index;
00428     if (dim_kinds[dim] != EQUALITY)
00429       ++dest_index;
00430     for (dimension_type dim_fol = dim + 1; dim_fol < dims; ++dim_fol) {
00431       if (dim_kinds[dim_fol] != CON_VIRTUAL) {
00432         --tmp_source_index;
00433         const Coefficient& source_dim = source[tmp_source_index][dim];
00434         // In order to compute the transpose of the inverse of
00435         // `source', subtract source[tmp_source_index][dim] times the
00436         // column vector in `dest' at `dim' from the column vector in
00437         // `dest' at `dim_fol'.
00438         //
00439         // I.e., for each row `dest_index' in `dest' that is above the
00440         // row `dest_index', subtract dest[tmp_source_index][dim]
00441         // times the entry `dim' from the entry at `dim_fol'.
00442         for (dimension_type row = dest_index; row-- > 0; ) {
00443           assert(row < dest_num_rows);
00444           Grid_Generator& g = dest[row];
00445           sub_mul_assign(g[dim_fol], source_dim, g[dim]);
00446         }
00447       }
00448     }
00449   }
00450 
00451   assert(upper_triangular(dest, dim_kinds));
00452 
00453 #ifdef STRONG_REDUCTION
00454   for (dimension_type dim = 0, i = 0; dim < dims; ++dim)
00455     if (dim_kinds[dim] != GEN_VIRTUAL)
00456       // Factor the "diagonal" generator out of the preceding rows.
00457       reduce_reduced<Grid_Generator_System, Grid_Generator>
00458         (dest, dim, i++, dim, dims - 1, dim_kinds);
00459 #endif
00460 
00461   // Ensure that the parameter divisors are the same as the divisor of
00462   // the point.
00463   const Coefficient& system_divisor = dest[0][0];
00464   for (dimension_type row = dest.num_rows() - 1, dim = dims;
00465        dim-- > 1; )
00466     switch (dim_kinds[dim]) {
00467     case PARAMETER:
00468       dest[row].set_divisor(system_divisor);
00469     case LINE:
00470       --row;
00471     case GEN_VIRTUAL:
00472       break;
00473     }
00474 }

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 154 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, Parma_Polyhedra_Library::Congruence_System::resize_no_copy(), Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), Parma_Polyhedra_Library::sub_mul_assign(), TEMP_INTEGER, and upper_triangular().

00155                                              {
00156   // Quite similar to the congruence to generator version below.
00157   // Changes here may be needed there too.
00158 
00159   assert(upper_triangular(source, dim_kinds));
00160 
00161   // Initialize matrix row number counters and compute the LCM of the
00162   // diagonal entries of the parameters in `source'.
00163   //
00164   // The top-down order of the generator system rows corresponds to
00165   // the left-right order of the dimensions, while the congruence
00166   // system rows have a bottom-up ordering.
00167   dimension_type dest_num_rows = 0;
00168   TEMP_INTEGER(diagonal_lcm);
00169   diagonal_lcm = 1;
00170   const dimension_type dims = source.space_dimension() + 1;
00171   dimension_type source_index = source.num_rows();
00172   for (dimension_type dim = dims; dim-- > 0; )
00173     if (dim_kinds[dim] == GEN_VIRTUAL)
00174       // Virtual generators map to equalities.
00175       ++dest_num_rows;
00176     else {
00177       --source_index;
00178       if (dim_kinds[dim] == PARAMETER) {
00179         // Dimension `dim' has a parameter row at `source_index' in
00180         // `source', so include in `diagonal_lcm' the `dim'th element
00181         // of that row.
00182         lcm_assign(diagonal_lcm, diagonal_lcm, source[source_index][dim]);
00183         // Parameters map to proper congruences.
00184         ++dest_num_rows;
00185       }
00186       // Lines map to virtual congruences.
00187     }
00188   assert(source_index == 0);
00189 
00190   // `source' must be regular.
00191   if (diagonal_lcm == 0)
00192     throw std::runtime_error("PPL internal error: Grid::conversion:"
00193                              " source matrix is singular.");
00194 
00195   dest.resize_no_copy(dest_num_rows, dims + 1 /* moduli */);
00196 
00197   // In `dest' initialize row types and elements, including setting
00198   // the diagonal elements to the inverse ratio of the `source'
00199   // diagonal elements.
00200   dimension_type dest_index = 0;
00201   source_index = source.num_rows();
00202   for (dimension_type dim = dims; dim-- > 0; ) {
00203     if (dim_kinds[dim] == LINE)
00204       --source_index;
00205     else {
00206       Congruence& cg = dest[dest_index];
00207       for (dimension_type j = dim; j-- > 0; )
00208         cg[j] = 0;
00209       for (dimension_type j = dim + 1; j < dims; ++j)
00210         cg[j] = 0;
00211 
00212       if (dim_kinds[dim] == GEN_VIRTUAL) {
00213         cg[dims] = 0;           // An equality.
00214         cg[dim] = 1;
00215       }
00216       else {
00217         assert(dim_kinds[dim] == PARAMETER);
00218         --source_index;
00219         cg[dims] = 1;           // A proper congruence.
00220         exact_div_assign(cg[dim], diagonal_lcm, source[source_index][dim]);
00221       }
00222       ++dest_index;
00223     }
00224   }
00225 
00226   assert(source_index == 0);
00227   assert(dest_index == dest_num_rows);
00228   assert(lower_triangular(dest, dim_kinds));
00229 
00230   // Convert.
00231   //
00232   // `source_index' and `dest_index' hold the positions of pivot rows
00233   // in `source' and `dest'.  The order of the rows in `dest' is the
00234   // reverse of the order in `source', so the rows are iterated from
00235   // last to first (index 0) in `source' and from first to last in
00236   // `dest'.
00237   source_index = source.num_rows();
00238   dest_index = 0;
00239   TEMP_INTEGER(multiplier);
00240 
00241   for (dimension_type dim = dims; dim-- > 0; ) {
00242     if (dim_kinds[dim] != GEN_VIRTUAL) {
00243       --source_index;
00244       const Coefficient& source_dim = source[source_index][dim];
00245 
00246       // In the rows in `dest' above `dest_index' divide each element
00247       // at column `dim' by `source_dim'.
00248       for (dimension_type row = dest_index; row-- > 0; ) {
00249         Congruence& cg = dest[row];
00250 
00251         // Multiply the representation of `dest' such that entry `dim'
00252         // of `g' is a multiple of `source_dim'.  This ensures that
00253         // the result of the division that follows is a whole number.
00254         gcd_assign(multiplier, cg[dim], source_dim);
00255         exact_div_assign(multiplier, source_dim, multiplier);
00256         multiply_grid(multiplier, cg, dest, dest_num_rows, dims);
00257 
00258         Coefficient& cg_dim = cg[dim];
00259         exact_div_assign(cg_dim, cg_dim, source_dim);
00260       }
00261     }
00262 
00263     // Invert and transpose the source row at `source_index' into the
00264     // destination row at `dest_index'.
00265     //
00266     // Consider each dimension `dim_prec' that precedes `dim', as the
00267     // rows in `dest' that follow `dim_index' have zeroes at index
00268     // `dim'.
00269     dimension_type tmp_source_index = source_index;
00270     if (dim_kinds[dim] != LINE)
00271       ++dest_index;
00272     for (dimension_type dim_prec = dim; dim_prec-- > 0; ) {
00273       if (dim_kinds[dim_prec] != GEN_VIRTUAL) {
00274         --tmp_source_index;
00275         const Coefficient& source_dim = source[tmp_source_index][dim];
00276         // In order to compute the transpose of the inverse of
00277         // `source', subtract source[tmp_source_index][dim] times the
00278         // column vector in `dest' at `dim' from the column vector in
00279         // `dest' at `dim_prec'.
00280         //
00281         // I.e., for each row `dest_index' in `dest' that is above the
00282         // row `dest_index', subtract dest[tmp_source_index][dim]
00283         // times the entry `dim' from the entry at `dim_prec'.
00284         for (dimension_type row = dest_index; row-- > 0; ) {
00285           assert(row < dest_num_rows);
00286           Congruence& cg = dest[row];
00287           sub_mul_assign(cg[dim_prec], source_dim, cg[dim]);
00288         }
00289       }
00290     }
00291   }
00292   // Set the modulus in every congruence.
00293   const Coefficient& modulus = dest[dest_num_rows - 1][0];
00294   for (dimension_type row = dest_num_rows; row-- > 0; ) {
00295     Congruence& cg = dest[row];
00296     if (cg[dims] > 0)
00297       // `cg' is a proper congruence.
00298       cg[dims] = modulus;
00299   }
00300 
00301   assert(lower_triangular(dest, dim_kinds));
00302 
00303 #ifdef STRONG_REDUCTION
00304   for (dimension_type dim = dims, i = 0; dim-- > 0; )
00305     if (dim_kinds[dim] != CON_VIRTUAL)
00306       // Factor the "diagonal" congruence out of the preceding rows.
00307       reduce_reduced<Congruence_System, Congruence>
00308         (dest, dim, i++, 0, dim, dim_kinds, false);
00309 #endif
00310 }

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 375 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 Parma_Polyhedra_Library::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().

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

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 249 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(), Parma_Polyhedra_Library::swap(), and Parma_Polyhedra_Library::Grid_Generator_System::unset_pending_rows().

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

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 31 of file Grid_simplify.cc.

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

Referenced by simplify().

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

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 57 of file Grid_simplify.cc.

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

Referenced by simplify().

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

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 84 of file Grid_simplify.cc.

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

Referenced by simplify().

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

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 125 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(), Parma_Polyhedra_Library::sub_mul_assign(), and TEMP_INTEGER.

Referenced by simplify().

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

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 180 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(), Parma_Polyhedra_Library::sub_mul_assign(), and TEMP_INTEGER.

Referenced by simplify().

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

template<typename M, typename R>
static 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.

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.

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 127 of file Grid_conversion.cc.

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

Referenced by conversion().

00129                                                    {
00130   if (multiplier == 1)
00131     return;
00132 
00133   if (cg.is_proper_congruence())
00134     // Multiply every element of every congruence.
00135     for (dimension_type index = num_rows; index-- > 0; ) {
00136       Congruence& congruence = dest[index];
00137       if (congruence.is_proper_congruence())
00138         for (dimension_type column = num_dims; column-- > 0; )
00139           congruence[column] *= multiplier;
00140     }
00141   else {
00142     assert(cg.is_equality());
00143     // Multiply every element of the equality.
00144     for (dimension_type column = num_dims; column-- > 0; )
00145       cg[column] *= multiplier;
00146   }
00147 }

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 104 of file Grid_conversion.cc.

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

00106                                                    {
00107   if (multiplier == 1)
00108     return;
00109 
00110   if (gen.is_line())
00111     // Multiply every element of the line.
00112     for (dimension_type column = num_dims; column-- > 0; )
00113       gen[column] *= multiplier;
00114   else {
00115     assert(gen.is_parameter_or_point());
00116     // Multiply every element of every parameter.
00117     for (dimension_type index = num_rows; index-- > 0; ) {
00118       Grid_Generator& generator = dest[index];
00119       if (generator.is_parameter_or_point())
00120         for (dimension_type column = num_dims; column-- > 0; )
00121           generator[column] *= multiplier;
00122     }
00123   }
00124 }

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 37 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().

00038                                                          {
00039   const dimension_type num_columns = sys.num_columns() - 1;
00040 
00041   // Check for easy square failure case.
00042   if (sys.num_rows() > num_columns)
00043     return false;
00044 
00045   // Check triangularity.
00046 
00047   dimension_type row = 0;
00048   for (dimension_type dim = num_columns; dim-- > 0; ) {
00049     if (dim_kinds[dim] == CON_VIRTUAL)
00050       continue;
00051     const Congruence& cg = sys[row];
00052     ++row;
00053     // Check diagonal.
00054     if (cg[dim] <= 0)
00055       return false;
00056     // Check elements following diagonal.
00057     dimension_type col = dim;
00058     while (++col < num_columns)
00059       if (cg[col] != 0)
00060         return false;
00061   }
00062 
00063   // Check squareness.
00064   return row == sys.num_rows();
00065 }

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 74 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().

00075                                                          {
00076   dimension_type num_columns = sys.space_dimension() + 1;
00077   dimension_type row = sys.num_rows();
00078 
00079   // Check for easy square fail case.
00080   if (row > num_columns)
00081     return false;
00082 
00083   // Check triangularity.
00084   while (num_columns > 0) {
00085     --num_columns;
00086     if (dim_kinds[num_columns] == GEN_VIRTUAL)
00087       continue;
00088     const Grid_Generator& gen = sys[--row];
00089     // Check diagonal.
00090     if (gen[num_columns] <= 0)
00091       return false;
00092     // Check elements preceding diagonal.
00093     dimension_type col = num_columns;
00094     while (col-- > 0)
00095       if (gen[col] != 0)
00096         return false;
00097   }
00098 
00099   // Check for squareness.
00100   return num_columns == row;
00101 }

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 236 of file Grid_simplify.cc.

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

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

Definition at line 616 of file Grid_nonpublic.cc.

00616                                                      {
00617   std::ostringstream s;
00618   s << "PPL::Grid::" << method << "." << std::endl;
00619   throw std::runtime_error(s.str());
00620 }

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

Definition at line 623 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(), Grid(), and map_space_dimensions().

00624                                                             {
00625   std::ostringstream s;
00626   s << "PPL::Grid::" << method << ":" << std::endl
00627     << reason << ".";
00628   throw std::invalid_argument(s.str());
00629 }

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_dimension_incompatible ( const char *  method,
const char *  gr_name,
const Grid gr 
) const [protected]

Definition at line 643 of file Grid_nonpublic.cc.

References space_dimension(), and throw_dimension_incompatible().

00645                                                               {
00646   throw_dimension_incompatible(method, gr_name, gr.space_dimension());
00647 }

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

Definition at line 650 of file Grid_nonpublic.cc.

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

00652                                                                           {
00653   throw_dimension_incompatible(method, e_name, e.space_dimension());
00654 }

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

Definition at line 657 of file Grid_nonpublic.cc.

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

00659                                                                     {
00660   throw_dimension_incompatible(method, cg_name, cg.space_dimension());
00661 }

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

Definition at line 664 of file Grid_nonpublic.cc.

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

00666                                                                    {
00667   throw_dimension_incompatible(method, c_name, c.space_dimension());
00668 }

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

Definition at line 671 of file Grid_nonpublic.cc.

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

00673                                                                        {
00674   throw_dimension_incompatible(method, g_name, g.space_dimension());
00675 }

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

Definition at line 678 of file Grid_nonpublic.cc.

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

00680                                                                   {
00681   throw_dimension_incompatible(method, g_name, g.space_dimension());
00682 }

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

Definition at line 685 of file Grid_nonpublic.cc.

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

00687                                                                             {
00688   throw_dimension_incompatible(method, cgs_name, cgs.space_dimension());
00689 }

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

Definition at line 692 of file Grid_nonpublic.cc.

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

00694                                                                            {
00695   throw_dimension_incompatible(method, cs_name, cs.space_dimension());
00696 }

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 699 of file Grid_nonpublic.cc.

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

00701                                                                                {
00702   throw_dimension_incompatible(method, gs_name, gs.space_dimension());
00703 }

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

Definition at line 706 of file Grid_nonpublic.cc.

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

00708                                                                   {
00709   std::ostringstream s;
00710   s << "PPL::Grid::" << method << ":" << std::endl
00711     << "this->space_dimension() == " << space_dimension() << ", "
00712     << var_name << ".space_dimension() == " << var.space_dimension() << ".";
00713   throw std::invalid_argument(s.str());
00714 }

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

Definition at line 718 of file Grid_nonpublic.cc.

References space_dimension().

00719                                                                       {
00720   std::ostringstream s;
00721   s << "PPL::Grid::" << method << ":" << std::endl
00722     << "this->space_dimension() == " << space_dimension()
00723     << ", required space dimension == " << required_space_dim << ".";
00724   throw std::invalid_argument(s.str());
00725 }

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

Definition at line 728 of file Grid_nonpublic.cc.

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

00729                                                               {
00730   std::ostringstream s;
00731   s << "PPL::Grid::" << method << ":" << std::endl
00732     << reason << ".";
00733   throw std::length_error(s.str());
00734 }

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

Definition at line 737 of file Grid_nonpublic.cc.

Referenced by add_constraint_no_check(), and Grid().

00738                                                               {
00739   std::ostringstream s;
00740   s << "PPL::Grid::" << method << ":" << std::endl
00741     << c_name << " is not an equality constraint.";
00742   throw std::invalid_argument(s.str());
00743 }

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

Definition at line 746 of file Grid_nonpublic.cc.

Referenced by Grid().

00747                                                                {
00748   std::ostringstream s;
00749   s << "PPL::Grid::" << method << ":" << std::endl
00750     << "the constraint system " << cs_name
00751     << " contains inequalities.";
00752   throw std::invalid_argument(s.str());
00753 }

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

Definition at line 756 of file Grid_nonpublic.cc.

Referenced by add_grid_generator().

00757                                                              {
00758   std::ostringstream s;
00759   s << "PPL::Grid::" << method << ":" << std::endl
00760     << "*this is an empty grid and "
00761     << g_name << " is not a point.";
00762   throw std::invalid_argument(s.str());
00763 }

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

Definition at line 766 of file Grid_nonpublic.cc.

Referenced by add_recycled_grid_generators(), add_recycled_grid_generators_and_minimize(), and construct().

00767                                                                {
00768   std::ostringstream s;
00769   s << "PPL::Grid::" << method << ":" << std::endl
00770     << "*this is an empty grid and" << std::endl
00771     << "the non-empty generator system " << gs_name << " contains no points.";
00772   throw std::invalid_argument(s.str());
00773 }


Friends And Related Function Documentation

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

friend class Parma_Polyhedra_Library::Box [friend]

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

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 2410 of file Grid_public.cc.

02410                                             {
02411   if (x.space_dim != y.space_dim)
02412     return false;
02413 
02414   if (x.marked_empty())
02415     return y.is_empty();
02416   if (y.marked_empty())
02417     return x.is_empty();
02418   if (x.space_dim == 0)
02419     return true;
02420 
02421   switch (x.quick_equivalence_test(y)) {
02422   case Grid::TVB_TRUE:
02423     return true;
02424 
02425   case Grid::TVB_FALSE:
02426     return false;
02427 
02428   default:
02429     if (x.is_included_in(y)) {
02430       if (x.marked_empty())
02431         return y.is_empty();
02432       return y.is_included_in(x);
02433     }
02434     return false;
02435   }
02436 }

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 2574 of file Grid_public.cc.

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

02574                                                          {
02575   if (gr.is_empty())
02576     s << "false";
02577   else if (gr.is_universe())
02578     s << "true";
02579   else
02580     s << gr.minimized_congruences();
02581   return s;
02582 }

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 379 of file Grid.inlines.hh.

00379                                          {
00380   return !(x == y);
00381 }

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

Specializes std::swap.

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

References swap().

00401                                      {
00402   x.swap(y);
00403 }


Member Data Documentation

The number of dimensions of the enclosing vector space.

Definition at line 2328 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_congruences_and_minimize(), add_recycled_grid_generators(), add_recycled_grid_generators_and_minimize(), add_space_dimensions(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_dimension(), affine_image(), affine_preimage(), ascii_dump(), ascii_load(), bounded_affine_image(), bounded_affine_preimage(), bounds(), concatenate_assign(), congruence_widening_assign(), congruences(), constrains(), construct(), contains(), contains_integer_point(), difference_assign(), expand_space_dimension(), fold_space_dimensions(), generalized_affine_image(), generalized_affine_preimage(), generator_widening_assign(), get_covering_box(), 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(), space_dimension(), swap(), time_elapse_assign(), unconstrain(), update_congruences(), update_generators(), upper_bound_assign(), upper_bound_assign_if_exact(), and widening_assign().


The documentation for this class was generated from the following files:

Generated on Sat Oct 11 10:41:11 2008 for PPL by  doxygen 1.5.6