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 *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, const Variable var) const
void throw_dimension_incompatible (const char *method, dimension_type required_space_dim) 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 Member Functions

 Grid (dimension_type num_dimensions=0, const 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)
 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)
 Builds a grid, recycling a system of constraints.
 Grid (const Grid_Generator_System &const_gs)
 Builds a grid, copying a system of generators.
 Grid (Grid_Generator_System &gs)
 Builds a grid, recycling a system of generators.
template<typename Box>
 Grid (const Box &box, From_Bounding_Box dummy)
 Builds a grid out of a generic, interval-based bounding box.
template<typename Box>
 Grid (const Box &box, From_Covering_Box dummy)
 Builds a grid out of a generic, interval-based covering box.
 Grid (const Grid &y)
 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.
const Congruence_Systemcongruences () const
 Returns the system of congruences.
const Congruence_Systemminimized_congruences () const
 Returns the system of congruences in reduced form.
const Grid_Generator_Systemgenerators () const
 Returns the system of generators.
const Grid_Generator_Systemminimized_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.
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 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, Grid_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, Grid_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 Box>
void shrink_bounding_box (Box &box) const
 Uses *this to shrink a generic, interval-based bounding box.
template<typename Box>
void get_covering_box (Box &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.
void add_congruence (const Constraint &c)
 Adds constraint c 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.
bool add_congruence_and_minimize (const Constraint &c)
 Adds a copy of constraint c to *this, reducing the result.
void add_generator (const Grid_Generator &g)
 Adds a copy of generator g to the system of generators of this.
bool add_generator_and_minimize (const Grid_Generator &g)
 Adds a copy of 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_congruences (const Constraint_System &cs)
 Adds a copy of each equality constraint in cs to *this.
void add_recycled_congruences (Congruence_System &cgs)
 Adds the congruences in cgs to *this.
void add_recycled_congruences (Constraint_System &cs)
 Adds the equality constraints in cs 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_congruences_and_minimize (const Constraint_System &cs)
 Adds a copy of each equality constraint in cs to *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.
bool add_recycled_congruences_and_minimize (Constraint_System &cs)
 Adds the equalities in cs to *this, reducing the result.
void add_constraint (const Constraint &c)
 Adds constraint c to *this.
bool add_constraint_and_minimize (const Constraint &c)
 Adds constraint c to *this, reducing the result.
void add_constraints (const Constraint_System &cs)
 Adds copies of the equality constraints in cs to *this.
bool add_constraints_and_minimize (const Constraint_System &cs)
 Adds copies of the equality constraints in cs to *this, reducing the result.
void add_recycled_constraints (Constraint_System &cs)
 Adds the equality constraints in cs to *this.
bool add_recycled_constraints_and_minimize (Constraint_System &cs)
void add_generators (const Grid_Generator_System &gs)
 Adds a copy of the generators in gs to the system of generators of *this.
void add_recycled_generators (Grid_Generator_System &gs)
 Adds the generators in gs to the system of generators of this.
bool add_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_generators_and_minimize (Grid_Generator_System &gs)
 Adds the generators in gs to the system of generators of this, reducing the result.
void intersection_assign (const Grid &y)
 Assigns to *this the intersection of *this and y. The result is not guaranteed to be reduced.
bool intersection_assign_and_minimize (const Grid &y)
 Assigns to *this the intersection of *this and y, reducing the result.
void join_assign (const Grid &y)
 Assigns to *this the join of *this and y.
bool join_assign_and_minimize (const Grid &y)
 Assigns to *this the join of *this and y, reducing the result.
void upper_bound_assign (const Grid &y)
 Same as join_assign(y).
bool join_assign_if_exact (const Grid &y)
 If the join of *this and y is exact it is assigned to this and true is returned, otherwise false is returned.
bool upper_bound_assign_if_exact (const Grid &y)
 Same as join_assign_if_exact(y).
void grid_difference_assign (const Grid &y)
 Assigns to *this the grid-difference of *this and y.
void difference_assign (const Grid &y)
 Same as grid_difference_assign(y).
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, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one(), Coefficient_traits::const_reference modulus=Coefficient_one())
 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, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one(), Coefficient_traits::const_reference modulus=Coefficient_one())
 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, const Linear_Expression &rhs, Coefficient_traits::const_reference modulus=Coefficient_one())
 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, const Linear_Expression &rhs, Coefficient_traits::const_reference modulus=Coefficient_one())
 Assigns to *this the preimage of *this with respect to the generalized affine relation $\mathrm{lhs}' = \mathrm{rhs} \pmod{\mathrm{modulus}}$.
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 widening_assign (const Grid &y, unsigned *tp=NULL)
 Assigns to *this the result of computing the Grid widening between *this and y.
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) and sets *this accordingly.
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.

Static Public Member Functions

static dimension_type max_space_dimension ()
 Returns the maximum space dimension all kinds of Grid can handle.

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 (const Congruence_System &cgs)
 Builds a grid from a system of congruences.
void construct (const Grid_Generator_System &gs)
 Builds a grid from a system of 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, char *method_call, Coefficient &ext_n, Coefficient &ext_d, bool &included, Grid_Generator *point=NULL) const
 Maximizes or minimizes expr subject to *this.
void add_space_dimensions (Congruence_System &cgs, Grid_Generator_System &gs, const dimension_type dims)
 Adds new space dimensions to the given systems.
void add_space_dimensions (Grid_Generator_System &gs, Congruence_System &cgs, const 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 parameters 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
bool 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.

Static Private Member Functions

Minimization-related Static Member Functions
static Coefficient normalize_divisors (Grid_Generator_System &sys, Coefficient_traits::const_reference divisor=Coefficient_one(), Grid_Generator *first_point=NULL)
 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, 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, Grid_Generator &pivot, dimension_type col, Grid_Generator_System &sys)
 Reduce row using pivot.
static void reduce_congruence_with_equality (Congruence &row, 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, 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, const dimension_type num_rows, const 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, const dimension_type num_rows, const 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
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 the 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. Most operators on grids are provided with two implementations: one of these, denoted <operator-name>_and_minimize, also enforces the minimization of the representations, and returns the boolean value false whenever the resulting grid turns out to be empty.

A key attributes 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_generator(grid_point(0*x + 0*y));
  gr.add_generator(grid_line(x));
  gr.add_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_generator(grid_point(0*x + 0*y));
  gr.add_generator(grid_point(4*x + 0*y));
  gr.add_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_generator(grid_point(0*x + 0*y));
  gr.add_generator(grid_point(4*x + 0*y));
  gr.add_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 362 of file Grid.defs.hh.


Member Typedef Documentation

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


Member Enumeration Documentation

Enumerator:
PARAMETER 
LINE 
GEN_VIRTUAL 
PROPER_CONGRUENCE 
CON_VIRTUAL 
EQUALITY 

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

Enumerator:
TVB_TRUE 
TVB_FALSE 
TVB_DONT_KNOW 

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


Constructor & Destructor Documentation

Parma_Polyhedra_Library::Grid::Grid ( dimension_type  num_dimensions = 0,
const Degenerate_Element  kind = UNIVERSE 
) [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 34 of file Grid_public.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().

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

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

References construct(), max_space_dimension(), Parma_Polyhedra_Library::Congruence_System::space_dimension(), and throw_space_dimension_overflow().

00050                                         {
00051   if (ccgs.space_dimension() > max_space_dimension())
00052     throw_space_dimension_overflow("Grid(ccgs)",
00053                                    "the space dimension of ccgs "
00054                                    "exceeds the maximum allowed "
00055                                    "space dimension");
00056   construct(ccgs);
00057 }

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

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 will be recycled to build the grid.
Exceptions:
std::length_error Thrown if num_dimensions exceeds the maximum allowed space dimension.

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

References construct(), max_space_dimension(), Parma_Polyhedra_Library::Congruence_System::space_dimension(), and throw_space_dimension_overflow().

00060                                  {
00061   if (cgs.space_dimension() > max_space_dimension())
00062     throw_space_dimension_overflow("Grid(cgs)",
00063                                    "the space dimension of cgs "
00064                                    "exceeds the maximum allowed "
00065                                    "space dimension");
00066   construct(cgs);
00067 }

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::length_error Thrown if num_dimensions exceeds the maximum allowed space dimension.

Definition at line 118 of file Grid_public.cc.

References Parma_Polyhedra_Library::Constraint_System::begin(), construct(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Congruence_System::insert(), max_space_dimension(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), and throw_space_dimension_overflow().

00118                                           {
00119   if (ccs.space_dimension() > max_space_dimension())
00120     throw_space_dimension_overflow("Grid(ccs)",
00121                                    "the space dimension of ccs "
00122                                    "exceeds the maximum allowed "
00123                                    "space dimension");
00124   Congruence_System cgs;
00125   cgs.insert(0*Variable(ccs.space_dimension() - 1) %= 1);
00126   for (Constraint_System::const_iterator i = ccs.begin(),
00127          ccs_end = ccs.end(); i != ccs_end; ++i)
00128     if (i->is_equality())
00129       cgs.insert(*i);
00130   construct(cgs);
00131 }

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

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.
Exceptions:
std::length_error Thrown if num_dimensions exceeds the maximum allowed space dimension.

Definition at line 133 of file Grid_public.cc.

References Parma_Polyhedra_Library::Constraint_System::begin(), construct(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Congruence_System::insert(), max_space_dimension(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), and throw_space_dimension_overflow().

00133                                    {
00134   if (cs.space_dimension() > max_space_dimension())
00135     throw_space_dimension_overflow("Grid(cs)",
00136                                    "the space dimension of cs "
00137                                    "exceeds the maximum allowed "
00138                                    "space dimension");
00139   // FIXME: Adapt and use cs instead of using a copy.
00140   Congruence_System cgs;
00141   cgs.insert(0*Variable(cs.space_dimension() - 1) %= 1);
00142   for (Constraint_System::const_iterator i = cs.begin(),
00143          cs_end = cs.end(); i != cs_end; ++i)
00144     if (i->is_equality())
00145       cgs.insert(*i);
00146   construct(cgs);
00147 }

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

Builds a grid, copying a system of 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 70 of file Grid.inlines.hh.

References construct(), max_space_dimension(), Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), and throw_space_dimension_overflow().

00070                                           {
00071   if (gs.space_dimension() > max_space_dimension())
00072     throw_space_dimension_overflow("Grid(gs)",
00073                                    "the space dimension of gs "
00074                                    "exceeds the maximum allowed "
00075                                    "space dimension");
00076   construct(gs);
00077 }

Parma_Polyhedra_Library::Grid::Grid ( Grid_Generator_System gs  )  [inline, explicit]

Builds a grid, recycling a system of generators.

The grid inherits the space dimension of the generator system.

Parameters:
gs The system of generators defining the grid. Its data-structures will be recycled to build 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 80 of file Grid.inlines.hh.

References construct(), max_space_dimension(), Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), and throw_space_dimension_overflow().

00080                                     {
00081   if (gs.space_dimension() > max_space_dimension())
00082     throw_space_dimension_overflow("Grid(gs)",
00083                                    "the space dimension of gs "
00084                                    "exceeds the maximum allowed "
00085                                    "space dimension");
00086   construct(gs);
00087 }

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

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

Parameters:
box The bounding box representing the grid to be built. The box can contain only point and universe intervals;
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 at least one interval with: a topologically open bound, a single bound, or two bounds which have space between them.
The template class Box must provide the following methods. returns the dimension of the vector space enclosing the grid represented by the bounding box.
      bool is_empty() const
returns true if and only if the bounding 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 35 of file Grid.templates.hh.

References con_sys, gen_sys, Parma_Polyhedra_Library::Congruence_System::increase_space_dimension(), Parma_Polyhedra_Library::Congruence_System::insert(), max_space_dimension(), OK(), set_congruences_up_to_date(), set_empty(), Parma_Polyhedra_Library::Grid_Generator_System::set_sorted(), set_zero_dim_univ(), space_dim, TEMP_INTEGER, throw_invalid_argument(), throw_space_dimension_overflow(), and Parma_Polyhedra_Library::Grid_Generator_System::unset_pending_rows().

00036   : con_sys(),
00037     gen_sys(NECESSARILY_CLOSED) {
00038   used(dummy);
00039 
00040   if (box.space_dimension() > max_space_dimension())
00041     throw_space_dimension_overflow("Grid(box, from_bounding_box)",
00042                                    "the space dimension of box "
00043                                    "exceeds the maximum allowed "
00044                                    "space dimension");
00045 
00046   space_dim = box.space_dimension();
00047 
00048   TEMP_INTEGER(l_n);
00049   TEMP_INTEGER(l_d);
00050 
00051   // Check that all bounds are closed.  This must be done before the
00052   // empty check below, in case an open bound makes the grid empty.
00053   for (dimension_type k = space_dim; k-- > 0; ) {
00054     bool closed;
00055     // FIXME: Perhaps introduce box::is_bounded_and_closed.
00056     if (box.get_lower_bound(k, closed, l_n, l_d) && !closed)
00057       throw_invalid_argument("Grid(box, from_bounding_box)", "box");
00058     if (box.get_upper_bound(k, closed, l_n, l_d) && !closed)
00059       throw_invalid_argument("Grid(box, from_bounding_box)", "box");
00060   }
00061 
00062   if (box.is_empty()) {
00063     // Empty grid.
00064     set_empty();
00065     assert(OK());
00066     return;
00067   }
00068 
00069   if (space_dim == 0)
00070     set_zero_dim_univ();
00071   else {
00072     // Initialize the space dimension as indicated by the box.
00073     con_sys.increase_space_dimension(space_dim);
00074     // Add congruences according to `box'.
00075     TEMP_INTEGER(u_n);
00076     TEMP_INTEGER(u_d);
00077     for (dimension_type k = space_dim; k-- > 0; ) {
00078       bool closed;
00079       // TODO: Consider producing the system(s) in minimized form.
00080       // FIXME: Also create the generator system.
00081       if (box.get_lower_bound(k, closed, l_n, l_d)) {
00082         if (box.get_upper_bound(k, closed, u_n, u_d))
00083           if (l_n * u_d == u_n * l_d) {
00084             // A point interval sets dimension k of every point to a
00085             // single value.
00086             con_sys.insert(l_d * Variable(k) == l_n);
00087             continue;
00088           }
00089         // The only valid bounded interval is a point interval.
00090         throw_invalid_argument("Grid(box, from_bounding_box)", "box");
00091       }
00092       else if (box.get_upper_bound(k, closed, u_n, u_d))
00093         // An interval can only be a point or the universe.
00094         throw_invalid_argument("Grid(box, from_covering_box)",
00095                                "box");
00096       // A universe interval allows any value in dimension k.
00097     }
00098     set_congruences_up_to_date();
00099     gen_sys.unset_pending_rows();
00100     gen_sys.set_sorted(false);
00101   }
00102 
00103   assert(OK());
00104 }

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

References con_sys, Parma_Polyhedra_Library::gcd_assign(), gen_sys, Parma_Polyhedra_Library::Congruence_System::increase_space_dimension(), Parma_Polyhedra_Library::Congruence_System::insert(), max_space_dimension(), OK(), set_congruences_up_to_date(), set_empty(), Parma_Polyhedra_Library::Grid_Generator_System::set_sorted(), set_zero_dim_univ(), space_dim, TEMP_INTEGER, throw_invalid_argument(), throw_space_dimension_overflow(), and Parma_Polyhedra_Library::Grid_Generator_System::unset_pending_rows().

00108   : con_sys(),
00109     gen_sys(NECESSARILY_CLOSED) {
00110   used(dummy);
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 must be done before the
00124   // empty check below, in case an open bound makes the grid empty.
00125   for (dimension_type k = space_dim; k-- > 0; ) {
00126     bool closed;
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     for (dimension_type k = space_dim; k-- > 0; ) {
00151       bool closed;
00152       // TODO: Consider producing the system(s) in minimized form.
00153       // FIXME: Also create the generator system.
00154       if (box.get_lower_bound(k, closed, l_n, l_d)) {
00155         if (box.get_upper_bound(k, closed, u_n, u_d)) {
00156           if (l_n * u_d == u_n * l_d)
00157             // A point interval allows any point along the dimension
00158             // k axis.
00159             continue;
00160           gcd_assign(d, l_d, u_d);
00161           // `d' is the gcd of the divisors.
00162           l_n *= (u_d / d);
00163           d = l_d / d;
00164           // `d' is now the smallest integer expression of the size
00165           // of l_d relative to u_d.  `d * u_d' is the lcm of the
00166           // divisors.
00167           con_sys.insert((d * u_d * Variable(k) %= l_n) / ((u_n * d) - l_n));
00168         }
00169         else
00170           // An interval bounded only from below produces an
00171           // equality.
00172           con_sys.insert(l_d * Variable(k) == l_n);
00173       }
00174       else
00175         if (box.get_upper_bound(k, closed, u_n, u_d))
00176           // An interval bounded only from above produces an equality.
00177           con_sys.insert(u_d * Variable(k) == u_n);
00178         else {
00179           // Any universe interval produces an empty grid.
00180           set_empty();
00181           assert(OK());
00182           return;
00183         }
00184     }
00185     set_congruences_up_to_date();
00186     gen_sys.set_sorted(false);
00187     gen_sys.unset_pending_rows();
00188   }
00189 
00190   assert(OK());
00191 }

Parma_Polyhedra_Library::Grid::Grid ( const Grid y  ) 

Ordinary copy-constructor.

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

00097   : con_sys(),
00098     gen_sys(),
00099     status(y.status),
00100     space_dim(y.space_dim),
00101     dim_kinds(y.dim_kinds) {
00102   if (space_dim == 0) {
00103     con_sys = y.con_sys;
00104     gen_sys = y.gen_sys;
00105   }
00106   else {
00107     if (y.congruences_are_up_to_date())
00108       con_sys = y.con_sys;
00109     else
00110       con_sys.increase_space_dimension(space_dim);
00111     if (y.generators_are_up_to_date())
00112       gen_sys = y.gen_sys;
00113     else
00114       gen_sys = Grid_Generator_System(y.space_dim);
00115   }
00116 }

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

Destructor.

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

00090             {
00091 }


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

00033                           {
00034   using std::min;
00035   // One dimension is reserved to have a value of type dimension_type
00036   // that does not represent a legal dimension.
00037   return min(std::numeric_limits<dimension_type>::max() - 1,
00038              min(Congruence_System::max_space_dimension(),
00039                  Grid_Generator_System::max_space_dimension()
00040                  )
00041              );
00042 }

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

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

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

00150                                 {
00151   space_dim = y.space_dim;
00152   dim_kinds = y.dim_kinds;
00153   if (y.marked_empty())
00154     set_empty();
00155   else if (space_dim == 0)
00156     set_zero_dim_univ();
00157   else {
00158     status = y.status;
00159     if (y.congruences_are_up_to_date())
00160       con_sys = y.con_sys;
00161     if (y.generators_are_up_to_date())
00162       gen_sys = y.gen_sys;
00163   }
00164   return *this;
00165 }

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

Returns the dimension of the vector space enclosing *this.

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

References space_dim.

Referenced by add_space_dimensions_and_embed(), add_space_dimensions_and_project(), concatenate_assign(), expand_space_dimension(), Parma_Polyhedra_Library::Grid_Certificate::Grid_Certificate(), and throw_dimension_incompatible().

00099                             {
00100   return space_dim;
00101 }

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

References is_empty(), minimized_congruences(), Parma_Polyhedra_Library::Matrix::num_rows(), and space_dim.

00168                                 {
00169   if (space_dim == 0 || is_empty())
00170     return 0;
00171 
00172   // FIXME: Use the minimized congruence system, or the generator
00173   //        system in any form.
00174 
00175   const Congruence_System& cgs = minimized_congruences();
00176   dimension_type d = space_dim;
00177   for (dimension_type i = cgs.num_rows(); i-- > 0; )
00178     if (cgs[i].is_equality())
00179       --d;
00180   return d;
00181 }

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

Returns the system of congruences.

Definition at line 184 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 concatenate_assign(), expand_space_dimension(), grid_difference_assign(), and minimized_congruences().

00184                            {
00185   if (marked_empty())
00186     return con_sys;
00187 
00188   if (space_dim == 0) {
00189     // Zero-dimensional universe.
00190     assert(con_sys.num_columns() == 2 && con_sys.num_rows() == 0);
00191     return con_sys;
00192   }
00193 
00194   congruences_are_up_to_date() || update_congruences();
00195 
00196   return con_sys;
00197 }

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

Returns the system of congruences in reduced form.

Definition at line 200 of file Grid_public.cc.

References con_sys, congruences(), congruences_are_minimized(), congruences_are_up_to_date(), dim_kinds, Parma_Polyhedra_Library::Congruence_System::increase_space_dimension(), marked_empty(), set_congruences_minimized(), set_empty(), simplify(), space_dim, swap(), and Parma_Polyhedra_Library::Congruence::zero_dim_integrality().

Referenced by affine_dimension(), and operator<<().

00200                                      {
00201   if (space_dim == 0) {
00202     if (!marked_empty()) {
00203       // Ensure the congruences are minimal by extending a zero dim
00204       // universe congruence system to the appropriate dimension and
00205       // then storing it in `con_sys'.
00206       Congruence_System cgs(Congruence::zero_dim_integrality());
00207       cgs.increase_space_dimension(space_dim);
00208       cgs[0][0] = 1; // Recover minimal form after cgs(zdi) normalization.
00209       const_cast<Congruence_System&>(con_sys).swap(cgs);
00210     }
00211     return con_sys;
00212   }
00213   if (congruences_are_up_to_date() && !congruences_are_minimized()) {
00214     // Minimize the congruences.
00215     Grid& gr = const_cast<Grid&>(*this);
00216     if (gr.simplify(gr.con_sys, gr.dim_kinds))
00217       gr.set_empty();
00218     else
00219       gr.set_congruences_minimized();
00220   }
00221   return congruences();
00222 }

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

Returns the system of generators.

Definition at line 225 of file Grid_public.cc.

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

Referenced by map_space_dimensions().

00225                           {
00226   if (space_dim == 0) {
00227     assert(gen_sys.space_dimension() == 0
00228            && gen_sys.num_generators() == (marked_empty() ? 0 : 1));
00229     return gen_sys;
00230   }
00231 
00232   if (marked_empty()) {
00233     assert(gen_sys.num_generators() == 0);
00234     return gen_sys;
00235   }
00236 
00237   if (!generators_are_up_to_date() && !update_generators()) {
00238     // Updating found the grid empty.
00239     const_cast<Grid&>(*this).set_empty();
00240     return gen_sys;
00241   }
00242 
00243   return gen_sys;
00244 }

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

Returns the minimized system of generators.

Definition at line 247 of file Grid_public.cc.

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

00247                                     {
00248   if (space_dim == 0) {
00249     assert(gen_sys.space_dimension() == 0
00250            && gen_sys.num_generators() == (marked_empty() ? 0 : 1));
00251     return gen_sys;
00252   }
00253 
00254   if (marked_empty()) {
00255     assert(gen_sys.num_generators() == 0);
00256     return gen_sys;
00257   }
00258 
00259   if (generators_are_up_to_date()) {
00260     if (!generators_are_minimized()) {
00261       // Minimize the generators.
00262       Grid& gr = const_cast<Grid&>(*this);
00263       gr.simplify(gr.gen_sys, gr.dim_kinds);
00264       gr.set_generators_minimized();
00265     }
00266   }
00267   else if (!update_generators()) {
00268     // Updating found the grid empty.
00269     const_cast<Grid&>(*this).set_empty();
00270     return gen_sys;
00271   }
00272 
00273   return gen_sys;
00274 }

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

References Parma_Polyhedra_Library::Scalar_Products::assign(), Parma_Polyhedra_Library::Grid_Generator_System::begin(), Parma_Polyhedra_Library::Grid_Generator_System::end(), Parma_Polyhedra_Library::gcd_assign(), gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Congruence::inhomogeneous_term(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Congruence::is_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, 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 grid_difference_assign(), and limited_extrapolation_assign().

00277                                                  {
00278   // Dimension-compatibility check.
00279   if (space_dim < cg.space_dimension())
00280     throw_dimension_incompatible("relation_with(cg)", "cg", cg);
00281 
00282   if (marked_empty())
00283     return Poly_Con_Relation::is_included()
00284       && Poly_Con_Relation::is_disjoint();
00285 
00286   if (space_dim == 0)
00287     // FIXME: Confirm that the relation with the false cg is correct.
00288     //        Does the false congruence define the empty grid?  If so,
00289     //        is the empty grid disjoint from the universe grid?
00290     if (cg.inhomogeneous_term() == 0)
00291       return Poly_Con_Relation::is_included();
00292     else if (cg.is_equality())
00293       return Poly_Con_Relation::is_disjoint();
00294     else if (cg.inhomogeneous_term() % cg.modulus() == 0)
00295       return Poly_Con_Relation::is_included();
00296     else
00297       // cg is false.
00298       return Poly_Con_Relation::is_disjoint();
00299 
00300   if (!generators_are_up_to_date() && !update_generators())
00301     // Updating found the grid empty.
00302     return Poly_Con_Relation::is_included()
00303       && Poly_Con_Relation::is_disjoint();
00304 
00305   // Return one of the relations
00306   // 'strictly_intersects'   a strict subset of the grid points satisfy cg
00307   // 'is_included'           every grid point satisfies cg
00308   // 'is_disjoint'           cg and the grid occupy seperate spaces.
00309 
00310   // There is always a point.
00311 
00312   // Scalar product of the congruence and the first point that
00313   // satisfies the congruence.
00314   TEMP_INTEGER(point_sp);
00315   point_sp = 0;
00316 
00317   TEMP_INTEGER(modulus);
00318   modulus = cg.modulus();
00319 
00320   TEMP_INTEGER(div);
00321   div = 0;
00322 
00323   bool known_to_intersect = false;
00324 
00325   for (Grid_Generator_System::const_iterator g = gen_sys.begin(),
00326          gen_sys_end = gen_sys.end(); g != gen_sys_end; ++g) {
00327     TEMP_INTEGER(sp);
00328     Scalar_Products::assign(sp, cg, *g);
00329 
00330     switch (g->type()) {
00331 
00332     case Grid_Generator::POINT:
00333       if (cg.is_proper_congruence())
00334         sp %= modulus;
00335       if (sp == 0)
00336         // The point satisfies the congruence.
00337         if (point_sp == 0)
00338           // Any previous points satisfied the congruence.
00339           known_to_intersect = true;
00340         else
00341           return Poly_Con_Relation::strictly_intersects();
00342       else
00343         if (point_sp == 0) {
00344           if (known_to_intersect)
00345             return Poly_Con_Relation::strictly_intersects();
00346           // Assign `sp' to `point_sp' as `sp' is the scalar product
00347           // of cg and a point g and is non-zero.
00348           point_sp = sp;
00349         }
00350         else {
00351           // A previously considered point p failed to satisfy cg such that
00352           // `point_sp' = `scalar_prod(p,cg)'
00353           // so, if we consider the parameter g-p instead of g, we have
00354           // scalar_prod(g-p, cg) = scalar_prod(g,cg) - scalar_prod(p,cg)
00355           //                      = sp - point_sp
00356           sp -= point_sp;
00357 
00358           if (sp != 0) {
00359             // Find the GCD between sp and the previous GCD.
00360             gcd_assign(div, div, sp);
00361             if (point_sp % div == 0)
00362               // There is a point in the grid satisfying cg.
00363               return Poly_Con_Relation::strictly_intersects();
00364           }
00365         }
00366       break;
00367 
00368     case Grid_Generator::PARAMETER:
00369       if (cg.is_proper_congruence())
00370         sp %= (modulus * g->divisor());
00371       if (sp == 0)
00372         // Parameter g satisfies the cg so the relation depends
00373         // entirely on the other generators.
00374         break;
00375 
00376       if (known_to_intersect)
00377         // At least one point satisfies cg.  However, the sum of such
00378         // a point and the parameter g fails to satisfy cg (due to g).
00379         return Poly_Con_Relation::strictly_intersects();
00380 
00381       // Find the GCD between sp and the previous GCD.
00382       gcd_assign(div, div, sp);
00383       if (point_sp != 0)
00384         // At least one of any previously encountered points fails to
00385         // satisfy cg.
00386         if (point_sp == div)
00387           // There is also a grid point that satisfies cg.
00388           return Poly_Con_Relation::strictly_intersects();
00389 
00390       break;
00391 
00392     case Grid_Generator::LINE:
00393       if (sp == 0)
00394         // Line g satisfies the cg so the relation depends entirely on
00395         // the other generators.
00396         break;
00397 
00398       // Line g intersects the congruence.
00399       //
00400       // There is a point p in the grid.  Suppose <p*cg> = p_sp.  Then
00401       // (-p_sp/sp)*g + p is a point that satisfies cg: <((-p_sp/sp)*g
00402       // + p).cg> = -(p_sp/sp)*sp + p_sp) = 0.  If p does not satisfy
00403       // `cg' and hence is not in the grid defined by `cg', the grid
00404       // `*this' strictly intersects the `cg' grid.  On the other
00405       // hand, if `p' is in the grid defined by `cg' so that p_sp = 0,
00406       // then <p+g.cg> = p_sp + sp != 0; thus `p+g' is a point in
00407       // *this that does not satisfy `cg' and hence `p+g' is a point
00408       // in *this not in the grid defined by `cg'; therefore `*this'
00409       // strictly intersects the `cg' grid.
00410 
00411       return Poly_Con_Relation::strictly_intersects();
00412     }
00413   }
00414 
00415   if (point_sp == 0)
00416     // Every generator satisfied the cg.
00417     return Poly_Con_Relation::is_included();
00418 
00419   assert(!known_to_intersect);
00420   return Poly_Con_Relation::is_disjoint();
00421 }

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

00424                                                     {
00425   // Dimension-compatibility check.
00426   if (space_dim < g.space_dimension())
00427     throw_dimension_incompatible("relation_with(g)", "g", g);
00428 
00429   // The empty grid cannot subsume a generator.
00430   if (marked_empty())
00431     return Poly_Gen_Relation::nothing();
00432 
00433   // A universe grid in a zero-dimensional space subsumes all the
00434   // generators of a zero-dimensional space.
00435   if (space_dim == 0)
00436     return Poly_Gen_Relation::subsumes();
00437 
00438   congruences_are_up_to_date() || update_congruences();
00439 
00440   return
00441     con_sys.satisfies_all_congruences(g)
00442     ? Poly_Gen_Relation::subsumes()
00443     : Poly_Gen_Relation::nothing();
00444 }

bool Parma_Polyhedra_Library::Grid::is_empty (  )  const

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

Definition at line 447 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(), contains(), generalized_affine_image(), generalized_affine_preimage(), and operator<<().

00447                         {
00448   if (marked_empty())
00449     return true;
00450   // Try a fast-fail test: if generators are up-to-date then the
00451   // generator system (since it is well formed) contains a point.
00452   if (generators_are_up_to_date())
00453     return false;
00454   if (space_dim == 0)
00455     return false;
00456   if (congruences_are_minimized())
00457     // If the grid was empty it would be marked empty.
00458     return false;
00459   // Minimize the congruences to check if the grid is empty.
00460   Grid& gr = const_cast<Grid&>(*this);
00461   if (gr.simplify(gr.con_sys, gr.dim_kinds)) {
00462     gr.set_empty();
00463     return true;
00464   }
00465   gr.set_congruences_minimized();
00466   return false;
00467 }

bool Parma_Polyhedra_Library::Grid::is_universe (  )  const

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

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

00470                            {
00471   if (marked_empty())
00472     return false;
00473 
00474   if (space_dim == 0)
00475     return true;
00476 
00477   if (congruences_are_up_to_date()) {
00478     if (congruences_are_minimized())
00479       // The minimized universe congruence system has only one row,
00480       // the integrality congruence.
00481       return con_sys.num_rows() == 1 && con_sys[0].is_trivial_true();
00482   }
00483   else {
00484     update_congruences();
00485     return con_sys.num_rows() == 1 && con_sys[0].is_trivial_true();
00486   }
00487 
00488   // Test con_sys's inclusion in a universe generator system.
00489 
00490   // The zero dimension cases are handled above.
00491   Variable var(space_dim - 1);
00492   for (dimension_type i = space_dim; i-- > 0; )
00493     if (!con_sys.satisfies_all_congruences(grid_line(Variable(i) + var)))
00494       return false;
00495   assert(con_sys.satisfies_all_congruences(grid_point(0*var)));
00496   return true;
00497 }

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.

Definition at line 564 of file Grid_public.cc.

References con_sys, congruences_are_minimized(), dim_kinds, gen_sys, generators_are_minimized(), generators_are_up_to_date(), marked_empty(), Parma_Polyhedra_Library::Grid_Generator_System::num_generators(), Parma_Polyhedra_Library::Matrix::num_rows(), set_congruences_minimized(), set_empty(), set_generators_minimized(), simplify(), and space_dim.

00564                                        {
00565   // Any empty or zero-dimensional grid is closed.
00566   if (marked_empty() || space_dim == 0)
00567     return true;
00568 
00569   if (generators_are_minimized()) {
00570   param_search:
00571     // Search for a parameter in the minimized generator system.
00572     for (dimension_type row = gen_sys.num_generators(); row-- > 1; )
00573       if (gen_sys[row].is_parameter())
00574         return false;
00575     return true;
00576   }
00577 
00578   if (congruences_are_minimized()) {
00579   proper_cg_search:
00580     // Search for a proper congruence following the integrality
00581     // congruence, in the minimized congruence system.
00582     for (dimension_type row = con_sys.num_rows() - 1; row-- > 0; )
00583       if (con_sys[row].is_proper_congruence())
00584         return false;
00585     return true;
00586   }
00587 
00588   Grid& gr = const_cast<Grid&>(*this);
00589   if (generators_are_up_to_date()) {
00590     gr.simplify(gr.gen_sys, gr.dim_kinds);
00591     gr.set_generators_minimized();
00592     goto param_search;
00593   }
00594 
00595   // Minimize the congruence system.
00596   if (gr.simplify(gr.con_sys, gr.dim_kinds)) {
00597     // The congruence system reduced to the empty grid.
00598     gr.set_empty();
00599     return true;
00600   }
00601   gr.set_congruences_minimized();
00602   goto proper_cg_search;
00603 }

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

References intersection_assign_and_minimize(), space_dim, and throw_dimension_incompatible().

02094                                              {
02095   // Dimension-compatibility check.
02096   if (space_dim != y.space_dim)
02097     throw_dimension_incompatible("is_disjoint_from(y)", "y", y);
02098   Grid z = *this;
02099   return !z.intersection_assign_and_minimize(y);
02100 }

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

References con_sys, congruences_are_minimized(), dim_kinds, gen_sys, generators_are_minimized(), generators_are_up_to_date(), Parma_Polyhedra_Library::Congruence_System::has_a_free_dimension(), marked_empty(), Parma_Polyhedra_Library::Grid_Generator_System::num_generators(), set_congruences_minimized(), set_empty(), set_generators_minimized(), simplify(), and space_dim.

00524                            {
00525   // A zero-dimensional or empty grid is discrete.
00526   if (space_dim == 0 || marked_empty())
00527     return true;
00528 
00529   if (generators_are_minimized()) {
00530   line_search:
00531     // Search for lines in the minimized generator system.
00532     for (dimension_type row = gen_sys.num_generators(); row-- > 1; )
00533       if (gen_sys[row].is_line())
00534         return false;
00535     return true;
00536   }
00537 
00538   if (congruences_are_minimized())
00539     return con_sys.has_a_free_dimension();
00540 
00541   Grid& gr = const_cast<Grid&>(*this);
00542   if (generators_are_up_to_date()) {
00543     // Minimize the generator system.
00544     gr.simplify(gr.gen_sys, gr.dim_kinds);
00545     gr.set_generators_minimized();
00546 
00547     goto line_search;
00548   }
00549 
00550   // Generators are out of date.
00551 
00552   // Minimize the congruence system to find out whether it is empty.
00553   if (gr.simplify(gr.con_sys, gr.dim_kinds)) {
00554     // The congruence system reduced to the empty grid.
00555     gr.set_empty();
00556     return true;
00557   }
00558   gr.set_congruences_minimized();
00559 
00560   return gr.con_sys.has_a_free_dimension();
00561 }

bool Parma_Polyhedra_Library::Grid::is_bounded (  )  const

Returns true if and only if *this is bounded.

Definition at line 500 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_generators(), space_dim, and update_generators().

00500                           {
00501   // A zero-dimensional or empty grid is bounded.
00502   if (space_dim == 0
00503       || marked_empty()
00504       || (!generators_are_up_to_date() && !update_generators()))
00505     return true;
00506 
00507   // TODO: Consider using con_sys when gen_sys is out of date.
00508 
00509   if (gen_sys.num_generators() > 1) {
00510     // Check if all generators are the same point.
00511     const Grid_Generator& first_point = gen_sys[0];
00512     if (first_point.is_line_or_parameter())
00513       return false;
00514     for (dimension_type row = gen_sys.num_generators(); row-- > 0; ) {
00515       const Grid_Generator& gen = gen_sys[row];
00516       if (gen.is_line_or_parameter() || gen != first_point)
00517         return false;
00518     }
00519   }
00520   return true;
00521 }

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

References bounds().

00210                                                            {
00211   return bounds(expr, "bounds_from_above(e)");
00212 }

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

References bounds().

00215                                                            {
00216   return bounds(expr, "bounds_from_below(e)");
00217 }

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

References max_min().

00221                                                                             {
00222   return max_min(expr, "maximize(e, ...)", sup_n, sup_d, maximum);
00223 }

bool Parma_Polyhedra_Library::Grid::maximize ( const Linear_Expression expr,
Coefficient sup_n,
Coefficient sup_d,
bool &  maximum,
Grid_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 226 of file Grid.inlines.hh.

References max_min().

00228                                             {
00229   return max_min(expr, "maximize(e, ...)", sup_n, sup_d, maximum, &point);
00230 }

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

References max_min().

Referenced by is_included_in().

00234                                                                             {
00235   return max_min(expr, "minimize(e, ...)", inf_n, inf_d, minimum);
00236 }

bool Parma_Polyhedra_Library::Grid::minimize ( const Linear_Expression expr,
Coefficient inf_n,
Coefficient inf_d,
bool &  minimum,
Grid_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 239 of file Grid.inlines.hh.

References max_min().

00241                                             {
00242   return max_min(expr, "minimize(e, ...)", inf_n, inf_d, minimum, &point);
00243 }

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 2075 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 grid_difference_assign(), limited_extrapolation_assign(), strictly_contains(), and widening_assign().

02075                                      {
02076   const Grid& x = *this;
02077 
02078   // Dimension-compatibility check.
02079   if (x.space_dim != y.space_dim)
02080     throw_dimension_incompatible("contains(y)", "y", y);
02081 
02082   if (y.marked_empty())
02083     return true;
02084   if (x.marked_empty())
02085     return y.is_empty();
02086   if (y.space_dim == 0)
02087     return true;
02088   if (x.quick_equivalence_test(y) == Grid::TVB_TRUE)
02089     return true;
02090   return y.is_included_in(x);
02091 }

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

References contains().

00252                                            {
00253   const Grid& x = *this;
00254   return x.contains(y) && !y.contains(x);
00255 }

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

Uses *this to shrink a generic, interval-based bounding box.

Parameters:
box The bounding box to be shrunk.
Exceptions:
std::invalid_argument Thrown if *this and box are dimension-incompatible, or 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 bounding box.
      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$. Causes the box to become empty, i.e., to represent the empty set.
      raise_lower_bound(dimension_type k, bool closed,
                        Coefficient_traits::const_reference n,
                        Coefficient_traits::const_reference d)
intersects the interval corresponding to the k-th space dimension with $[n/d, +\infty)$. closed is always passed as true.
      lower_upper_bound(dimension_type k, bool closed,
                        Coefficient_traits::const_reference n,
                        Coefficient_traits::const_reference d)
intersects the interval corresponding to the k-th space dimension with $(-\infty, n/d]$. closed is always passed as true.

The function raise_lower_bound(k, closed, n, d) will be called at most once for each possible value for k and for all such calls the fraction $n/d$ will be in canonical form, that is, $n$ and $d$ have no common factors and $d$ is positive, $0/1$ being the unique representation for zero. The same guarantee is offered for the function lower_upper_bound(k, closed, n, d).

Definition at line 195 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::Grid_Generator::is_point(), marked_empty(), Parma_Polyhedra_Library::Grid_Generator_System::num_columns(), Parma_Polyhedra_Library::Grid_Generator_System::num_generators(), space_dim, TEMP_INTEGER, throw_dimension_incompatible(), throw_invalid_argument(), and update_generators().

00195                                         {
00196   // Dimension-compatibility check.
00197   if (space_dim > box.space_dimension())
00198     throw_dimension_incompatible("shrink_bounding_box(box)", "box",
00199                                  box.space_dimension());
00200 
00201   TEMP_INTEGER(l_n);
00202   TEMP_INTEGER(l_d);
00203 
00204   // Check that all bounds are closed.
00205   for (dimension_type k = space_dim; k-- > 0; ) {
00206     bool closed;
00207     // FIXME: Perhaps introduce box::is_bounded_and_closed.
00208     if (box.get_lower_bound(k, closed, l_n, l_d) && !closed)
00209       throw_invalid_argument("shrink_bounding_box(box)", "box");
00210     if (box.get_upper_bound(k, closed, l_n, l_d) && !closed)
00211       throw_invalid_argument("shrink_bounding_box(box)", "box");
00212   }
00213 
00214   if (marked_empty()) {
00215     box.set_empty();
00216     return;
00217   }
00218   if (space_dim == 0)
00219     return;
00220   if (!generators_are_up_to_date() && !update_generators()) {
00221     // Updating found the grid empty.
00222     box.set_empty();
00223     return;
00224   }
00225 
00226   assert(gen_sys.num_generators() > 0);
00227 
00228   dimension_type num_dims = gen_sys.num_columns() - 2 /* parameter divisor */;
00229   dimension_type num_rows = gen_sys.num_generators();
00230 
00231   // Create a vector to record which dimensions are bounded.
00232   std::vector<bool> bounded_interval(num_dims, true);
00233 
00234   const Grid_Generator *first_point = NULL;
00235   // Clear the bound flag in `bounded_interval' for all dimensions in
00236   // which a line or sequence of points extends away from a single
00237   // value in the dimension.
00238   for (dimension_type row = 0; row < num_rows; ++row) {
00239     Grid_Generator& gen = const_cast<Grid_Generator&>(gen_sys[row]);
00240     if (gen.is_point()) {
00241       if (first_point == NULL) {
00242         first_point = &gen_sys[row];
00243         continue;
00244       }
00245       const Grid_Generator& point = *first_point;
00246       // Convert the point `gen' to a parameter.
00247       for (dimension_type dim = 0; dim < num_dims; ++dim)
00248         gen[dim] -= point[dim];
00249       gen.divisor() = point.divisor();
00250     }
00251     for (dimension_type col = num_dims; col > 0; )
00252       if (gen[col--] != 0)
00253         bounded_interval[col] = false;
00254   }
00255 
00256   // Attempt to set both bounds of each boundable interval to the
00257   // value of the associated coefficient in the point.
00258   const Grid_Generator& point = *first_point;
00259   TEMP_INTEGER(divisor);
00260   TEMP_INTEGER(gcd);
00261   TEMP_INTEGER(bound);
00262   TEMP_INTEGER(reduced_divisor);
00263   divisor = point.divisor();
00264   for (dimension_type dim = 0; dim < num_dims; ++dim)
00265     if (bounded_interval[dim]) {
00266       // Reduce the bound fraction first.
00267       gcd_assign(gcd, point[dim+1], divisor);
00268       exact_div_assign(bound, point[dim+1], gcd);
00269       exact_div_assign(reduced_divisor, divisor, gcd);
00270       box.raise_lower_bound(dim, true, bound, reduced_divisor);
00271       box.lower_upper_bound(dim, true, bound, reduced_divisor);
00272     }
00273 }

template<typename Box>
void Parma_Polyhedra_Library::Grid::get_covering_box ( Box &  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.
The template class Box must provide the following methods Creates a universe box of space_dimension dimensions. returns the dimension of the vector space enclosing the grid represented by the covering box. Causes the box to become empty, i.e., to represent the empty set.
      raise_lower_bound(dimension_type k, bool closed,
                        Coefficient_traits::const_reference n,
                        Coefficient_traits::const_reference d)
intersects the interval corresponding to the k-th space dimension with $[n/d, +\infty)$. closed is always passed as true.
      lower_upper_bound(dimension_type k, bool closed,
                        Coefficient_traits::const_reference n,
                        Coefficient_traits::const_reference d)
intersects the interval corresponding to the k-th space dimension with $(-\infty, n/d]$. closed is always passed as true.

The function raise_lower_bound(k, closed, n, d) will be called at most once for each possible value for k and for all such calls the fraction $n/d$ will be in canonical form, that is, $n$ and $d$ have no common factors and $d$ is positive, $0/1$ being the unique representation for zero. The same guarantee is offered for the function lower_upper_bound(k, closed, n, d).

Definition at line 277 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::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_generators(), space_dim, TEMP_INTEGER, throw_dimension_incompatible(), and update_generators().

00277                                      {
00278   // Dimension-compatibility check.
00279   if (space_dim > box.space_dimension())
00280     throw_dimension_incompatible("get_covering_box(box)", "box",
00281                                  box.space_dimension());
00282 
00283   Box new_box(box.space_dimension());
00284 
00285   if (marked_empty()) {
00286     box = new_box;
00287     box.set_empty();
00288     return;
00289   }
00290   if (space_dim == 0) {
00291     return;
00292   }
00293   if (!generators_are_up_to_date() && !update_generators()) {
00294     // Updating found the grid empty.
00295     box = new_box;
00296     box.set_empty();
00297     return;
00298   }
00299 
00300   assert(gen_sys.num_generators() > 0);
00301 
00302   dimension_type num_dims = gen_sys.num_columns() - 2 /* parameter divisor */;
00303   dimension_type num_rows = gen_sys.num_generators();
00304 
00305   TEMP_INTEGER(divisor);
00306   TEMP_INTEGER(gcd);
00307   TEMP_INTEGER(bound);
00308   TEMP_INTEGER(reduced_divisor);
00309 
00310   if (num_rows > 1) {
00311     Row interval_sizes(num_dims, Row::Flags());
00312     std::vector<bool> interval_emptiness(num_dims, false);
00313 
00314     // Store in `interval_sizes', for each column (that is, for each
00315     // dimension), the GCD of all the values in that column where the
00316     // row is of type parameter.
00317 
00318     for (dimension_type dim = num_dims; dim-- > 0; )
00319       interval_sizes[dim] = 0;
00320     const Grid_Generator *first_point = NULL;
00321     for (dimension_type row = 0; row < num_rows; ++row) {
00322       Grid_Generator& gen = const_cast<Grid_Generator&>(gen_sys[row]);
00323       if (gen.is_line()) {
00324         for (dimension_type dim = 0; dim < num_dims; ++dim)
00325           if (!interval_emptiness[dim] && gen[dim+1] != 0) {
00326             // Empty interval, set both bounds for associated
00327             // dimension to zero.
00328             new_box.lower_upper_bound(dim, true, 0, 1);
00329             new_box.raise_lower_bound(dim, true, 0, 1);
00330             interval_emptiness[dim] = true;
00331           }
00332         continue;
00333       }
00334       if (gen.is_point()) {
00335         if (first_point == NULL) {
00336           first_point = &gen_sys[row];
00337           continue;
00338         }
00339         const Grid_Generator& point = *first_point;
00340         // Convert the point `gen' to a parameter.
00341         for (dimension_type dim = 0; dim <= num_dims; ++dim)
00342           gen[dim] -= point[dim];
00343         gen.divisor() = point.divisor();
00344       }
00345       for (dimension_type dim = 0; dim < num_dims; ++dim)
00346         if (!interval_emptiness[dim])
00347           gcd_assign(interval_sizes[dim], interval_sizes[dim], gen[dim+1]);
00348     }
00349 
00350     // For each dimension set the lower bound of the interval to the
00351     // grid value closest to the origin, and the upper bound to the
00352     // addition of the lower bound and the shortest distance in the
00353     // given dimension between any two grid points.
00354     const Grid_Generator& point = *first_point;
00355     divisor = point.divisor();
00356     TEMP_INTEGER(lower_bound);
00357     for (dimension_type dim = 0; dim < num_dims; ++dim) {
00358       if (interval_emptiness[dim])
00359         continue;
00360 
00361       lower_bound = point[dim+1];
00362 
00363       // If the interval size is zero then all points have the same
00364       // value in this dimension, so set only the lower bound.
00365       if (interval_sizes[dim] != 0) {
00366         // Make the lower bound as close as possible to the origin,
00367         // leaving the sign the same.
00368         lower_bound %= interval_sizes[dim];
00369         // Check if the lowest value the other side of the origin is
00370         // closer to the origin, prefering the lowest positive if they
00371         // are equal.
00372         if (lower_bound > 0) {
00373           if (interval_sizes[dim] - lower_bound < lower_bound)
00374             lower_bound -= interval_sizes[dim];
00375         }
00376         else if (lower_bound < 0
00377                  && interval_sizes[dim] + lower_bound < - lower_bound)
00378           lower_bound += interval_sizes[dim];
00379 
00380         // Reduce the bound fraction first.
00381         bound = interval_sizes[dim] + lower_bound;
00382         gcd_assign(gcd, bound, divisor);
00383         exact_div_assign(bound, bound, gcd);
00384         exact_div_assign(reduced_divisor, divisor, gcd);
00385         new_box.lower_upper_bound(dim, true, bound, reduced_divisor);
00386       }
00387 
00388       // Reduce the bound fraction first.
00389       gcd_assign(gcd, lower_bound, divisor);
00390       exact_div_assign(lower_bound, lower_bound, gcd);
00391       exact_div_assign(reduced_divisor, divisor, gcd);
00392       new_box.raise_lower_bound(dim, true, lower_bound, reduced_divisor);
00393     }
00394   }
00395   else {
00396     const Grid_Generator& point = gen_sys[0];
00397     divisor = point.divisor();
00398     // The covering box of a single point has only lower bounds.
00399     for (dimension_type dim = 0; dim < num_dims; ++dim) {
00400       // Reduce the bound fraction first.
00401       gcd_assign(gcd, point[dim+1], divisor);
00402       exact_div_assign(bound, point[dim+1], gcd);
00403       exact_div_assign(reduced_divisor, divisor, gcd);
00404       new_box.raise_lower_bound(dim, true, bound, reduced_divisor);
00405     }
00406   }
00407 
00408   box = new_box;
00409 }

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 606 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::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_generators(), Parma_Polyhedra_Library::Matrix::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, update_generators(), and upper_triangular().

Referenced by add_congruence(), add_generator(), add_recycled_congruences(), add_recycled_congruences_and_minimize(), add_recycled_generators(), add_recycled_generators_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_image(), affine_preimage(), ascii_load(), concatenate_assign(), construct(), expand_space_dimension(), fold_space_dimensions(), generalized_affine_image(), generalized_affine_preimage(), Grid(), grid_difference_assign(), intersection_assign(), is_included_in(), join_assign(), limited_extrapolation_assign(), map_space_dimensions(), minimize(), remove_higher_space_dimensions(), remove_space_dimensions(), time_elapse_assign(), and widening_assign().

00606                                       {
00607 #ifndef NDEBUG
00608   using std::endl;
00609   using std::cerr;
00610 #endif
00611 
00612   // Check whether the status information is legal.
00613   if (!status.OK())
00614     goto fail;
00615 
00616   if (marked_empty()) {
00617     if (check_not_empty) {
00618       // The caller does not want the grid to be empty.
00619 #ifndef NDEBUG
00620       cerr << "Empty grid!" << endl;
00621 #endif
00622       goto fail;
00623     }
00624 
00625     if (con_sys.space_dimension() != space_dim) {
00626 #ifndef NDEBUG
00627       cerr << "The grid is in a space of dimension " << space_dim
00628            << " while the system of congruences is in a space of dimension "
00629            << con_sys.space_dimension()
00630            << endl;
00631 #endif
00632       goto fail;
00633     }
00634     return true;
00635   }
00636 
00637   // A zero-dimensional universe grid is legal only if the system of
00638   // congruences `con_sys' is empty, and the generator system contains
00639   // one point.
00640   if (space_dim == 0) {
00641     if (con_sys.num_rows() == 0)
00642       if (gen_sys.num_generators() == 1 && gen_sys[0].is_point())
00643         return true;
00644 #ifndef NDEBUG
00645     cerr << "Zero-dimensional grid should have an empty congruence" << endl
00646          << "system and a generator system of a single point." << endl;
00647 #endif
00648     goto fail;
00649   }
00650 
00651   // A grid is defined by a system of congruences or a system of
00652   // generators.  At least one of them must be up to date.
00653   if (!congruences_are_up_to_date() && !generators_are_up_to_date()) {
00654 #ifndef NDEBUG
00655     cerr << "Grid not empty, not zero-dimensional" << endl
00656          << "and with neither congruences nor generators up-to-date!"
00657          << endl;
00658 #endif
00659     goto fail;
00660   }
00661 
00662   {
00663     // This block is to limit the scope of num_columns, at least for
00664     // GCC < 3.4.
00665 
00666     // The expected number of columns in the congruence and generator
00667     // systems, if they are not empty.
00668     const dimension_type num_columns = space_dim + 1;
00669 
00670     // Here we check if the size of the matrices is consistent.
00671     // Let us suppose that all the matrices are up-to-date; this means:
00672     // `con_sys' : number of congruences x poly_num_columns
00673     // `gen_sys' : number of generators  x poly_num_columns
00674     if (congruences_are_up_to_date())
00675       if (con_sys.num_columns() != num_columns + 1 /* moduli */) {
00676 #ifndef NDEBUG
00677         cerr << "Incompatible size! (con_sys and space_dim)"
00678              << endl;
00679 #endif
00680         goto fail;
00681       }
00682 
00683     if (generators_are_up_to_date()) {
00684       if (gen_sys.space_dimension() + 1 != num_columns) {
00685 #ifndef NDEBUG
00686         cerr << "Incompatible size! (gen_sys and space_dim)"
00687              << endl;
00688 #endif
00689         goto fail;
00690       }
00691 
00692       // Check if the system of generators is well-formed.
00693       if (!gen_sys.OK()) {
00694 #ifndef NDEBUG
00695         cerr << "gen_sys OK failed." << endl;
00696 #endif
00697         goto fail;
00698       }
00699       // Check each generator in the system.
00700       for (dimension_type i = gen_sys.num_generators(); i-- > 0; ) {
00701         const Grid_Generator& g = gen_sys[i];
00702 
00703         if (g.size() < 1) {
00704 #ifndef NDEBUG
00705           cerr << "Parameter should have coefficients." << endl;
00706 #endif
00707           goto fail;
00708         }
00709       }
00710 
00711       // A non-empty system of generators describing a grid is valid iff
00712       // it contains a point.
00713       if (gen_sys.num_generators() > 0 && !gen_sys.has_points()) {
00714 #ifndef NDEBUG
00715         cerr << "Non-empty generator system declared up-to-date "
00716              << "has no points!"
00717              << endl;
00718 #endif
00719         goto fail;
00720       }
00721 
00722       if (generators_are_minimized()) {
00723         Grid_Generator_System gs = gen_sys;
00724 
00725         if (dim_kinds.size() != num_columns) {
00726 #ifndef NDEBUG
00727           cerr << "Size of dim_kinds should equal the number of columns."
00728                << endl;
00729 #endif
00730           goto fail;
00731         }
00732 
00733         if (!upper_triangular(gs, dim_kinds)) {
00734 #ifndef NDEBUG
00735           cerr << "Reduced generators should be upper triangular."
00736                << endl;
00737 #endif
00738           goto fail;
00739         }
00740 
00741         // Check that dim_kinds corresponds to the row kinds in gen_sys.
00742         for (dimension_type dim = 0, row = 0;
00743              dim < space_dim + 1;
00744              ++dim, assert(row <= dim)) {
00745           if (dim_kinds[dim] == GEN_VIRTUAL
00746               || (gen_sys[row++].is_parameter_or_point()
00747                   && dim_kinds[dim] == PARAMETER)
00748               || (assert(gen_sys[row-1].is_line()), dim_kinds[dim] == LINE))
00749             continue;
00750 #ifndef NDEBUG
00751           cerr << "Kinds in dim_kinds should match those in gen_sys."
00752                << endl;
00753 #endif
00754           goto fail;
00755         }
00756 
00757         // A reduced generator system must be the same as a temporary
00758         // reduced copy.
00759         Dimension_Kinds dk = dim_kinds;
00760         // `gs' is minimized and marked_empty returned false, so `gs'
00761         // should contain rows.
00762         assert(gs.num_generators() > 0);
00763         simplify(gs, dk);
00764         // gs contained rows before being reduced, so it should
00765         // contain at least a single point afterwards.
00766         assert(gs.num_generators() > 0);
00767         for (dimension_type row = 0; row < gen_sys.num_generators(); ++row) {
00768           Grid_Generator& g = gs[row];
00769           const Grid_Generator& g_copy = gen_sys[row];
00770           if (g.is_equal_to(g_copy))
00771             continue;
00772 #ifndef NDEBUG
00773           cerr << "Generators are declared minimized,"
00774             " but they change under reduction.\n"
00775                << "Here is the generator system:\n";
00776           gen_sys.ascii_dump(cerr);
00777           cerr << "and here is the minimized form of the temporary copy:\n";
00778           gs.ascii_dump(cerr);
00779 #endif
00780           goto fail;
00781         }
00782       }
00783 
00784     } // if (congruences_are_up_to_date())
00785   } // scope block
00786 
00787   if (congruences_are_up_to_date()) {
00788     // Check if the system of congruences is well-formed.
00789     if (!con_sys.OK()) {
00790 #ifndef NDEBUG
00791       cerr << "con_sys OK failed." << endl;
00792 #endif
00793       goto fail;
00794     }
00795 
00796     Grid tem_gr = *this;
00797     Congruence_System cs_copy = tem_gr.con_sys;
00798 
00799     // Clear the generators in tem_gr.
00800     Grid_Generator_System gs(space_dim);
00801     std::swap(tem_gr.gen_sys, gs);
00802     tem_gr.clear_generators_up_to_date();
00803 
00804     if (!tem_gr.update_generators()) {
00805       if (check_not_empty) {
00806         // Want to know the satisfiability of the congruences.
00807 #ifndef NDEBUG
00808         cerr << "Unsatisfiable system of congruences!"
00809              << endl;
00810 #endif
00811         goto fail;
00812       }
00813       // The grid is empty, all checks are done.
00814       return true;
00815     }
00816 
00817     if (congruences_are_minimized()) {
00818       // A reduced congruence system must be lower triangular.
00819       if (!lower_triangular(con_sys, dim_kinds)) {
00820 #ifndef NDEBUG
00821         cerr << "Reduced congruences should be lower triangular." << endl;
00822 #endif
00823         goto fail;
00824       }
00825 
00826       // If the congruences are minimized, all the elements in the
00827       // congruence system must be the same as those in the temporary,
00828       // minimized system `cs_copy'.
00829       if (!con_sys.is_equal_to(cs_copy)) {
00830 #ifndef NDEBUG
00831         cerr << "Congruences are declared minimized, but they change under reduction!"
00832              << endl
00833              << "Here is the minimized form of the congruence system:"
00834              << endl;
00835         cs_copy.ascii_dump(cerr);
00836         cerr << endl;
00837 #endif
00838         goto fail;
00839       }
00840 
00841       if (dim_kinds.size() != con_sys.num_columns() - 1 /* modulus */) {
00842 #ifndef NDEBUG
00843         cerr << "Size of dim_kinds should equal the number of columns."
00844              << endl;
00845 #endif
00846         goto fail;
00847       }
00848 
00849       // Check that dim_kinds corresponds to the row kinds in con_sys.
00850       for (dimension_type dim = 0, row = con_sys.num_rows() - 1;
00851            dim < space_dim + 1;
00852            ++dim) {
00853         if (dim_kinds[dim] == CON_VIRTUAL
00854             || (con_sys[row--].is_proper_congruence()
00855                 && dim_kinds[dim] == PROPER_CONGRUENCE)
00856             || (assert(con_sys[row+1].is_equality()),
00857                 dim_kinds[dim] == EQUALITY))
00858           continue;
00859 #ifndef NDEBUG
00860         cerr << "Kinds in dim_kinds should match those in con_sys." << endl;
00861 #endif
00862         goto fail;
00863       }
00864     }
00865   }
00866 
00867   return true;
00868 
00869  fail:
00870 #ifndef NDEBUG
00871   cerr << "Here is the grid under check:" << endl;
00872   ascii_dump(cerr);
00873 #endif
00874   return false;
00875 }

void Parma_Polyhedra_Library::Grid::add_congruence ( const Congruence cg  ) 

Adds a copy of congruence cg to *this.

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

Definition at line 878 of file Grid_public.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_trivial_true(), marked_empty(), OK(), set_congruences_up_to_date(), set_empty(), space_dim, Parma_Polyhedra_Library::Congruence::space_dimension(), throw_dimension_incompatible(), and update_congruences().

Referenced by add_constraint(), generalized_affine_image(), generalized_affine_preimage(), and grid_difference_assign().

00878                                             {
00879   // Dimension-compatibility check: the dimension of `cg' can not be
00880   // greater than space_dim.
00881   if (space_dim < cg.space_dimension())
00882     throw_dimension_incompatible("add_congruence(cg)", "cg", cg);
00883 
00884   // Adding a new congruence to an empty grid results in an empty
00885   // grid.
00886   if (marked_empty())
00887     return;
00888 
00889   // Dealing with a zero-dimensional space grid first.
00890   if (space_dim == 0) {
00891     if (!cg.is_trivial_true())
00892       set_empty();
00893     return;
00894   }
00895 
00896   congruences_are_up_to_date() || update_congruences();
00897 
00898   con_sys.insert(cg);
00899 
00900   clear_congruences_minimized();
00901   set_congruences_up_to_date();
00902   clear_generators_up_to_date();
00903 
00904   // Note: the congruence system may have become unsatisfiable, thus
00905   // we do not check for satisfiability.
00906   assert(OK());
00907 }

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

Adds constraint c to *this.

The addition can only affect *this if c is an equality.

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

Definition at line 910 of file Grid_public.cc.

References add_recycled_congruences(), and Parma_Polyhedra_Library::Constraint::is_equality().

00910                                            {
00911   // TODO: this is just an executable specification.
00912   if (c.is_equality()) {
00913     Congruence_System cgs(c);
00914     add_recycled_congruences(cgs);
00915   }
00916 }

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.

Definition at line 919 of file Grid_public.cc.

References add_recycled_congruences_and_minimize().

Referenced by add_constraint_and_minimize().

00919                                                          {
00920   // TODO: this is just an executable specification.
00921   Congruence_System cgs(cg);
00922   return add_recycled_congruences_and_minimize(cgs);
00923 }

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

Adds a copy of constraint c to *this, reducing the result.

The addition can only affect *this if c is an equality.

Returns:
false if and only if the result is empty.
Exceptions:
std::invalid_argument Thrown if *this and constraint c are dimension-incompatible.

Definition at line 926 of file Grid_public.cc.

References add_recycled_congruences_and_minimize(), Parma_Polyhedra_Library::Constraint::is_equality(), and minimize().

00926                                                         {
00927   // TODO: this is just an executable specification.
00928   if (c.is_equality()) {
00929     Congruence_System cgs(c);
00930     return add_recycled_congruences_and_minimize(cgs);
00931   }
00932   return minimize();
00933 }

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

Adds a copy of 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 936 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_preimage().

00936                                               {
00937   // The dimension of `g' must be at most space_dim.
00938   const dimension_type g_space_dim = g.space_dimension();
00939   if (space_dim < g_space_dim)
00940     throw_dimension_incompatible("add_generator(g)", "g", g);
00941 
00942   // Deal with zero-dimension case first.
00943   if (space_dim == 0) {
00944     // Points and parameters are the only zero-dimension generators
00945     // that can be created.
00946     if (marked_empty()) {
00947       if (g.is_parameter())
00948         throw_invalid_generator("add_generator(g)", "g");
00949       set_zero_dim_univ();
00950     }
00951     assert(OK());
00952     return;
00953   }
00954 
00955   if (marked_empty()
00956       || (!generators_are_up_to_date() && !update_generators())) {
00957     // Here the grid is empty: the specification says we can only
00958     // insert a point.
00959     if (g.is_line_or_parameter())
00960       throw_invalid_generator("add_generator(g)", "g");
00961     gen_sys.insert(g);
00962     clear_empty();
00963   }
00964   else {
00965     assert(generators_are_up_to_date());
00966     gen_sys.insert(g);
00967     if (g.is_parameter_or_point())
00968       normalize_divisors(gen_sys);
00969   }
00970 
00971   // With the added generator, congruences are out of date.
00972   clear_congruences_up_to_date();
00973 
00974   clear_generators_minimized();
00975   set_generators_up_to_date();
00976   assert(OK());
00977 }

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

Adds a copy of 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.

Definition at line 980 of file Grid_public.cc.

References add_recycled_generators_and_minimize().

00980                                                            {
00981   // TODO: this is just an executable specification.
00982   Grid_Generator_System gs(g);
00983   return add_recycled_generators_and_minimize(gs);
00984 }

void Parma_Polyhedra_Library::Grid::add_congruences ( const Congruence_System cgs  ) 

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

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

Referenced by expand_space_dimension(), and limited_extrapolation_assign().

01040                                                      {
01041   // TODO: this is just an executable specification.
01042   // The dimension of `cgs' must be at most `space_dim'.
01043   if (space_dim < cgs.space_dimension())
01044     throw_dimension_incompatible("add_congruences(cgs)", "cgs", cgs);
01045   Congruence_System cgs_copy = cgs;
01046   add_recycled_congruences(cgs_copy);
01047 }

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

Adds a copy of each equality constraint in cs to *this.

Parameters:
cs The congruences that will be considered for addition to the system of congruences of *this.
Exceptions:
std::invalid_argument Thrown if *this and cgs are dimension-incompatible.

Definition at line 1050 of file Grid_public.cc.

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

01050                                                     {
01051   // TODO: this is just an executable specification.
01052   // The dimension of `cs' must be at most `space_dim'.
01053   if (space_dim < cs.space_dimension())
01054     throw_dimension_incompatible("add_congruences(cs)", "cs", cs);
01055   Congruence_System cgs(cs);
01056   add_recycled_congruences(cgs);
01057 }

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

Adds the congruences in cgs to *this.

Parameters:
cgs The congruence system that will be recycled, adding its congruences to the system of congruences of *this.
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 987 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(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), 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(), and update_congruences().

Referenced by add_congruence(), add_congruences(), add_constraints(), add_recycled_congruences(), add_recycled_constraints(), generalized_affine_image(), generalized_affine_preimage(), and widening_assign().

00987                                                         {
00988   // Dimension-compatibility check: the dimension of `cgs' can not be
00989   // greater than space_dim.
00990   const dimension_type cgs_space_dim = cgs.space_dimension();
00991   if (space_dim < cgs_space_dim)
00992     throw_dimension_incompatible("add_recycled_congruences(cgs)", "cgs", cgs);
00993 
00994   if (cgs.num_rows() == 0)
00995     return;
00996 
00997   if (space_dim == 0) {
00998     // In a 0-dimensional space the congruences are trivial (e.g., 0
00999     // == 0 or 1 %= 0) or false (e.g., 1 == 0).  In a system of
01000     // congruences `begin()' and `end()' are equal if and only if the
01001     // system contains only trivial congruences.
01002     if (cgs.begin() != cgs.end())
01003       // There is a congruence, it must be false, the grid is empty.
01004       if (status.test_zero_dim_univ())
01005         set_empty();
01006     return;
01007   }
01008 
01009   if (marked_empty()) {
01010     assert(OK());
01011     return;
01012   }
01013 
01014   // The congruences are required.
01015   congruences_are_up_to_date() || update_congruences();
01016 
01017   // Swap (instead of copying) the coefficients of `cgs' (which is
01018   // writable).
01019   con_sys.recycling_insert(cgs);
01020 
01021   // Congruences may not be minimized and generators are out of date.
01022   clear_congruences_minimized();
01023   clear_generators_up_to_date();
01024   // Note: the congruence system may have become unsatisfiable, thus
01025   // we do not check for satisfiability.
01026   assert(OK());
01027 }

void Parma_Polyhedra_Library::Grid::add_recycled_congruences ( Constraint_System cs  ) 

Adds the equality constraints in cs to *this.

Parameters:
cs The constraint system from which constraints will be considered for addition to the system of congruences of *this.
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.

Definition at line 1030 of file Grid_public.cc.

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

01030                                                        {
01031   // TODO: this is just an executable specification.
01032   // The dimension of `cs' must be at most `space_dim'.
01033   if (space_dim < cs.space_dimension())
01034     throw_dimension_incompatible("add_recycled_congruences(cs)", "cs", cs);
01035   Congruence_System cgs(cs);
01036   add_recycled_congruences(cgs);
01037 }

bool Parma_Polyhedra_Library::Grid::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.

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.

Definition at line 1116 of file Grid_public.cc.

References add_recycled_congruences_and_minimize().

01116                                                                   {
01117   // TODO: this is just an executable specification.
01118   Congruence_System cgs_copy = cgs;
01119   return add_recycled_congruences_and_minimize(cgs_copy);
01120 }

bool Parma_Polyhedra_Library::Grid::add_congruences_and_minimize ( const Constraint_System cs  ) 

Adds a copy of each equality constraint in cs to *this, reducing the result.

Returns:
false if and only if the result is empty.
Parameters:
cs Contains the constraints that will be added to the system of congruences of *this.
Exceptions:
std::invalid_argument Thrown if *this and cs are dimension-incompatible.

Definition at line 1123 of file Grid_public.cc.

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

01123                                                                  {
01124   // TODO: this is just an executable specification.
01125   // The dimension of `cs' must be at most `space_dim'.
01126   if (space_dim < cs.space_dimension())
01127     throw_dimension_incompatible("add_congruences_and_minimize(cs)", "cs", cs);
01128   Congruence_System cgs(cs);
01129   return add_recycled_congruences_and_minimize(cgs);
01130 }

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 that will be recycled, adding its congruences to the system of congruences of *this.
Exceptions:
std::invalid_argument Thrown if *this and cgs are dimension-incompatible.
Warning:
The only assumption that can be made about cgs upon successful or exceptional return is that it can be safely destroyed.

Definition at line 1060 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(), marked_empty(), minimize(), Parma_Polyhedra_Library::Matrix::num_rows(), 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(), add_congruences_and_minimize(), add_constraints_and_minimize(), add_recycled_congruences_and_minimize(), add_recycled_constraints_and_minimize(), generalized_affine_image(), and generalized_affine_preimage().

01060                                                                      {
01061   // Dimension-compatibility check: the dimension of `cgs' can not be
01062   // greater than space_dim.
01063   const dimension_type cgs_space_dim = cgs.space_dimension();
01064   if (space_dim < cgs_space_dim)
01065     throw_dimension_incompatible("add_recycled_congruences_and_minimize(cgs)",
01066                                  "cgs", cgs);
01067 
01068   // Adding no congruences: just minimize.
01069   if (cgs.num_rows() == 0)
01070     return minimize();
01071 
01072   // Dealing with zero-dimensional space grids first.
01073   if (space_dim == 0) {
01074     // In a 0-dimensional space the congruences are trivial (e.g., 0
01075     // == 0 or 1 %= 0) or false (e.g., 1 == 0).  In a system of
01076     // congruences `begin()' and `end()' are equal if and only if the
01077     // system contains only trivial congruences.
01078     if (cgs.begin() == cgs.end())
01079       return true;
01080     // There is a congruence, it must be false, the grid is empty.
01081     if (status.test_zero_dim_univ())
01082       set_empty();
01083     return false;
01084   }
01085 
01086   if (marked_empty())
01087     return false;
01088 
01089   congruences_are_up_to_date() || update_congruences();
01090 
01091   con_sys.recycling_insert(cgs);
01092 
01093   clear_congruences_minimized();
01094 
01095 #ifndef NDEBUG
01096   bool ret = update_generators();
01097   assert(OK());
01098   return ret;
01099 #else
01100   return update_generators();
01101 #endif
01102 }

bool Parma_Polyhedra_Library::Grid::add_recycled_congruences_and_minimize ( Constraint_System cs  ) 

Adds the equalities in cs to *this, reducing the result.

Returns:
false if and only if the result is empty.
Parameters:
cs The constraint system that will be recycled, adding its equalities to the system of congruences of *this.
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.

Definition at line 1105 of file Grid_public.cc.

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

01105                                                                     {
01106   // TODO: this is just an executable specification.
01107   // The dimension of `cs' must be at most `space_dim'.
01108   if (space_dim < cs.space_dimension())
01109     throw_dimension_incompatible("add_recycled_congruences_and_minimize(cs)",
01110                                  "cs", cs);
01111   Congruence_System cgs(cs);
01112   return add_recycled_congruences_and_minimize(cgs);
01113 }

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

Adds constraint c to *this.

The addition can only affect *this if c is an equality.

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

Definition at line 1133 of file Grid_public.cc.

References add_congruence(), Parma_Polyhedra_Library::Constraint::is_equality(), space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), and throw_dimension_incompatible().

01133                                            {
01134   // The dimension of `c' must be at most `space_dim'.
01135   if (space_dim < c.space_dimension())
01136     throw_dimension_incompatible("add_constraint(c)", "c", c);
01137   if (c.is_equality()) {
01138     Congruence cg(c);
01139     add_congruence(cg);
01140   }
01141 }

bool Parma_Polyhedra_Library::Grid::add_constraint_and_minimize ( const Constraint c  ) 

Adds constraint c to *this, reducing the result.

The addition can only affect *this if c is an equality.

Returns:
false if and only if the result is empty.
Exceptions:
std::invalid_argument Thrown if *this and c are dimension-incompatible.

Definition at line 1144 of file Grid_public.cc.

References add_congruence_and_minimize(), Parma_Polyhedra_Library::Constraint::is_equality(), minimize(), space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), and throw_dimension_incompatible().

01144                                                         {
01145   // The dimension of `c' must be at most `space_dim'.
01146   if (space_dim < c.space_dimension())
01147     throw_dimension_incompatible("add_constraint_and_minimize(c)", "c", c);
01148   if (c.is_equality()) {
01149     Congruence cg(c);
01150     return add_congruence_and_minimize(cg);
01151   }
01152   return minimize();
01153 }

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

Adds copies of the equality constraints in cs to *this.

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

Definition at line 1156 of file Grid_public.cc.

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

01156                                                     {
01157   // The dimension of `cs' must be at most `space_dim'.
01158   if (space_dim < cs.space_dimension())
01159     throw_dimension_incompatible("add_constraints(cs)", "cs", cs);
01160   Congruence_System cgs(cs);
01161   add_recycled_congruences(cgs);
01162 }

bool Parma_Polyhedra_Library::Grid::add_constraints_and_minimize ( const Constraint_System cs  ) 

Adds copies of the equality constraints in cs to *this, reducing the result.

Returns:
false if and only if the result is empty.
Exceptions:
std::invalid_argument Thrown if *this and cs are dimension-incompatible.

Definition at line 1165 of file Grid_public.cc.

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

01165                                                                  {
01166   // The dimension of `cs' must be at most `space_dim'.
01167   if (space_dim < cs.space_dimension())
01168     throw_dimension_incompatible("add_constraints_and_minimize(cs)",
01169                                  "cs", cs);
01170   Congruence_System cgs(cs);
01171   return add_recycled_congruences_and_minimize(cgs);
01172 }

void Parma_Polyhedra_Library::Grid::add_recycled_constraints ( Constraint_System cs  ) 

Adds the equality constraints in cs to *this.

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.

Definition at line 1175 of file Grid_public.cc.

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

01175                                                        {
01176   // The dimension of `cs' must be at most `space_dim'.
01177   if (space_dim < cs.space_dimension())
01178     throw_dimension_incompatible("add_recycled_constraints(cs)",
01179                                  "cs", cs);
01180   Congruence_System cgs(cs);
01181   add_recycled_congruences(cgs);
01182 }

bool Parma_Polyhedra_Library::Grid::add_recycled_constraints_and_minimize ( Constraint_System cs  ) 

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.

Definition at line 1185 of file Grid_public.cc.

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

01185                                                                     {
01186   // The dimension of `cs' must be at most `space_dim'.
01187   if (space_dim < cs.space_dimension())
01188     throw_dimension_incompatible("add_recycled_constraints_and_minimize(cs)",
01189                                  "cs", cs);
01190   Congruence_System cgs(cs);
01191   return add_recycled_congruences_and_minimize(cgs);
01192 }

void Parma_Polyhedra_Library::Grid::add_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 1255 of file Grid_public.cc.

References add_recycled_generators().

01255                                                        {
01256   // TODO: this is just an executable specification.
01257   Grid_Generator_System gs_copy = gs;
01258   add_recycled_generators(gs_copy);
01259 }

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

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

Parameters:
gs The generator system that will be recycled, adding its generators 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.
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 1195 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::has_points(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), marked_empty(), normalize_divisors(), Parma_Polyhedra_Library::Grid_Generator_System::num_generators(), 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(), throw_dimension_incompatible(), throw_invalid_generators(), and update_generators().

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

01195                                                           {
01196   // Dimension-compatibility check:
01197   // the dimension of `gs' can not be greater than space_dim.
01198   const dimension_type gs_space_dim = gs.space_dimension();
01199   if (space_dim < gs_space_dim)
01200     throw_dimension_incompatible("add_recycled_generators(gs)", "gs", gs);
01201 
01202   // Adding no generators leaves the grid the same.
01203   if (gs.num_generators() == 0)
01204     return;
01205 
01206   // Adding valid generators to a zero-dimensional grid transforms it
01207   // to the zero-dimensional universe grid.
01208   if (space_dim == 0) {
01209     if (marked_empty())
01210       if (gs.has_points())
01211         set_zero_dim_univ();
01212       else
01213         throw_invalid_generators("add_recycled_generators(gs)", "gs");
01214     assert(OK(true));
01215     return;
01216   }
01217 
01218   if (!marked_empty()
01219       && (generators_are_up_to_date() || update_generators())) {
01220     // The grid contains at least one point.
01221 
01222     normalize_divisors(gs, gen_sys);
01223 
01224     gen_sys.recycling_insert(gs);
01225 
01226     // Congruences are out of date and generators are not minimized.
01227     clear_congruences_up_to_date();
01228     clear_generators_minimized();
01229 
01230     assert(OK(true));
01231     return;
01232   }
01233 
01234   // The grid is empty.
01235 
01236   // `gs' must contain at least one point.
01237   if (!gs.has_points())
01238     throw_invalid_generators("add_recycled_generators(gs)", "gs");
01239 
01240   // Adjust `gs' to the right dimension.
01241   gs.insert(parameter(0*Variable(space_dim-1)));
01242 
01243   std::swap(gen_sys, gs);
01244 
01245   normalize_divisors(gen_sys);
01246 
01247   // The grid is no longer empty and generators are up-to-date.
01248   set_generators_up_to_date();
01249   clear_empty();
01250 
01251   assert(OK());
01252 }

bool Parma_Polyhedra_Library::Grid::add_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.

Definition at line 1315 of file Grid_public.cc.

References add_recycled_generators_and_minimize().

01315                                                                     {
01316   // TODO: this is just an executable specification.
01317   Grid_Generator_System gs_copy = gs;
01318   return add_recycled_generators_and_minimize(gs_copy);
01319 }

bool Parma_Polyhedra_Library::Grid::add_recycled_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 that will be recycled, adding its generators 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.
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 1262 of file Grid_public.cc.

References clear_empty(), clear_generators_minimized(), gen_sys, generators_are_up_to_date(), 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_generators(), OK(), Parma_Polyhedra_Library::Grid_Generator_System::recycling_insert(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), throw_dimension_incompatible(), throw_invalid_generators(), update_congruences(), and update_generators().

Referenced by add_generator_and_minimize(), and add_generators_and_minimize().

01262                                                                        {
01263   // Dimension-compatibility check: the dimension of `gs' must be less
01264   // than or equal to that of space_dim.
01265   const dimension_type gs_space_dim = gs.space_dimension();
01266   if (space_dim < gs_space_dim)
01267     throw_dimension_incompatible("add_recycled_generators_and_minimize(gs)",
01268                                  "gs", gs);
01269 
01270   // Adding no generators is equivalent to just requiring reduction.
01271   if (gs.num_generators() == 0)
01272     return minimize();
01273 
01274   // Adding valid generators to a zero-dimensional grid produces the
01275   // zero-dimensional universe grid.
01276   if (space_dim == 0) {
01277     if (marked_empty())
01278       if (gs.has_points())
01279         set_zero_dim_univ();
01280       else
01281         throw_invalid_generators("add_recycled_generators_and_minimize(gs)",
01282                                  "gs");
01283     assert(OK(true));
01284     return true;
01285   }
01286 
01287   // Adjust `gs' to the right dimension.
01288   gs.insert(parameter(0*Variable(space_dim-1)));
01289 
01290   if (!marked_empty()
01291       && (generators_are_up_to_date() || update_generators())) {
01292     // The grid contains at least one point.
01293     normalize_divisors(gs, gen_sys);
01294 
01295     for (dimension_type row = 0; row < gs.num_generators(); ++row)
01296       gen_sys.recycling_insert(gs[row]);
01297   }
01298   else {
01299     // The grid is empty: check if `gs' contains a point.
01300     if (!gs.has_points())
01301       throw_invalid_generators("add_recycled_generators_and_minimize(gs)",
01302                                "gs");
01303     std::swap(gen_sys, gs);
01304     normalize_divisors(gen_sys);
01305     clear_empty();
01306   }
01307   clear_generators_minimized();
01308   update_congruences();
01309 
01310   assert(OK(true));
01311   return true;
01312 }

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

Assigns to *this the intersection of *this and y. The result is not guaranteed to be reduced.

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

Definition at line 1322 of file Grid_public.cc.

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

Referenced by intersection_assign_and_minimize().

01322                                           {
01323   Grid& x = *this;
01324   // Dimension-compatibility check.
01325   if (x.space_dim != y.space_dim)
01326     throw_dimension_incompatible("intersection_assign(y)", "y", y);
01327 
01328   // If one of the two grids is empty, the intersection is empty.
01329   if (x.marked_empty())
01330     return;
01331   if (y.marked_empty()) {
01332     x.set_empty();
01333     return;
01334   }
01335 
01336   // If both grids are zero-dimensional, then at this point they are
01337   // necessarily universe, so the intersection is also universe.
01338   if (x.space_dim == 0)
01339     return;
01340 
01341   // The congruences must be up-to-date.
01342   x.congruences_are_up_to_date() || x.update_congruences();
01343   y.congruences_are_up_to_date() || y.update_congruences();
01344 
01345   if (y.con_sys.num_rows() > 0 ) {
01346     x.con_sys.insert(y.con_sys);
01347     // Grid_Generators may be out of date and congruences may have changed
01348     // from minimal form.
01349     x.clear_generators_up_to_date();
01350     x.clear_congruences_minimized();
01351   }
01352 
01353   // `y' should still contain a point.
01354   assert(x.OK() && y.OK(true));
01355 }

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.

Definition at line 1358 of file Grid_public.cc.

References intersection_assign(), and minimize().

Referenced by is_disjoint_from().

01358                                                        {
01359   intersection_assign(y);
01360   return minimize();
01361 }

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

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

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

Definition at line 1364 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 fold_space_dimensions(), grid_difference_assign(), join_assign_and_minimize(), join_assign_if_exact(), and upper_bound_assign().

01364                                   {
01365   Grid& x = *this;
01366   // Dimension-compatibility check.
01367   if (x.space_dim != y.space_dim)
01368     throw_dimension_incompatible("join_assign(y)", "y", y);
01369 
01370   // The join of a grid `gr' with an empty grid is `gr'.
01371   if (y.marked_empty())
01372     return;
01373   if (x.marked_empty()) {
01374     x = y;
01375     return;
01376   }
01377 
01378   // If both grids are zero-dimensional, then they are necessarily
01379   // universe grids, and so is their join.
01380   if (x.space_dim == 0)
01381     return;
01382 
01383   // The generators must be up-to-date.
01384   if (!x.generators_are_up_to_date() && !x.update_generators()) {
01385     // Discovered `x' empty when updating generators.
01386     x = y;
01387     return;
01388   }
01389   if (!y.generators_are_up_to_date() && !y.update_generators())
01390     // Discovered `y' empty when updating generators.
01391     return;
01392 
01393   // Match the divisors of the x and y generator systems.
01394   Grid_Generator_System gs(y.gen_sys);
01395   normalize_divisors(x.gen_sys, gs);
01396   x.gen_sys.recycling_insert(gs);
01397   // Congruences may be out of date and generators may have lost
01398   // minimal form.
01399   x.clear_congruences_up_to_date();
01400   x.clear_generators_minimized();
01401 
01402   // At this point both `x' and `y' are not empty.
01403   assert(x.OK(true) && y.OK(true));
01404 }

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

Assigns to *this the join 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.

Definition at line 1407 of file Grid_public.cc.

References join_assign(), and minimize().

01407                                                {
01408   join_assign(y);
01409   return minimize();
01410 }

void Parma_Polyhedra_Library::Grid::upper_bound_assign ( const Grid y  )  [inline]

Same as join_assign(y).

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

References join_assign().

00104                                       {
00105   join_assign(y);
00106 }

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

If the join 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 1413 of file Grid_public.cc.

References grid_difference_assign(), is_included_in(), join_assign(), marked_empty(), space_dim, and throw_dimension_incompatible().

Referenced by upper_bound_assign_if_exact().

01413                                            {
01414   Grid& x = *this;
01415 
01416   // Dimension-compatibility check.
01417   if (x.space_dim != y.space_dim)
01418     throw_dimension_incompatible("join_assign_if_exact(y)", "y", y);
01419 
01420   if (x.marked_empty()
01421       || y.marked_empty()
01422       || x.space_dim == 0
01423       || x.is_included_in(y)
01424       || y.is_included_in(x)) {
01425     join_assign(y);
01426     return true;
01427   }
01428 
01429   Grid x_copy = x;
01430   x_copy.join_assign(y);
01431   x_copy.grid_difference_assign(y);
01432   if (x_copy.is_included_in(x)) {
01433     join_assign(y);
01434     return true;
01435   }
01436 
01437   return false;
01438 }

bool Parma_Polyhedra_Library::Grid::upper_bound_assign_if_exact ( const Grid y  )  [inline]

Same as join_assign_if_exact(y).

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

References join_assign_if_exact().

00109                                                {
00110   return join_assign_if_exact(y);
00111 }

void Parma_Polyhedra_Library::Grid::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 1441 of file Grid_public.cc.

References add_congruence(), 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(), join_assign(), marked_empty(), Parma_Polyhedra_Library::Congruence::modulus(), OK(), relation_with(), set_empty(), space_dim, and throw_dimension_incompatible().

Referenced by difference_assign(), and join_assign_if_exact().

01441                                              {
01442   Grid& x = *this;
01443   // Dimension-compatibility check.
01444   if (x.space_dim != y.space_dim)
01445     throw_dimension_incompatible("poly_difference_assign(y)", "y", y);
01446 
01447   if (y.marked_empty() || x.marked_empty())
01448     return;
01449 
01450   // If both grids are zero-dimensional, then they are necessarily
01451   // universe grids, so the result is empty.
01452   if (x.space_dim == 0) {
01453     x.set_empty();
01454     return;
01455   }
01456 
01457   if (y.contains(x)) {
01458     x.set_empty();
01459     return;
01460   }
01461 
01462   Grid new_grid(x.space_dim, EMPTY);
01463 
01464   const Congruence_System& y_cgs = y.congruences();
01465   for (Congruence_System::const_iterator i = y_cgs.begin(),
01466          y_cgs_end = y_cgs.end(); i != y_cgs_end; ++i) {
01467     const Congruence& cg = *i;
01468 
01469     // The 2-complement cg2 of cg = ((e %= 0) / m) is the congruence
01470     // defining the sets of points exactly half-way between successive
01471     // hyperplanes e = km and e = (k+1)m, for any integer k; that is,
01472     // the hyperplanes defined by 2e = (2k + 1)m, for any integer k.
01473     // Thus `cg2' is the congruence ((2e %= m) / 2m).
01474 
01475     // As the grid difference must be a grid, only add the
01476     // 2-complement congruence to x if the resulting grid includes all
01477     // the points in x that did not satisfy `cg'.
01478 
01479     // The 2-complement of cg can be included in the result only if x
01480     // holds points other than those in cg.
01481     if (x.relation_with(cg).implies(Poly_Con_Relation::is_included()))
01482       continue;
01483 
01484     if (cg.is_proper_congruence()) {
01485       const Linear_Expression e = Linear_Expression(cg);
01486       // Congruence cg is ((e %= 0) / m).
01487       Coefficient_traits::const_reference m = cg.modulus();
01488       // If x is included in the grid defined by the congruences cg
01489       // and its 2-complement (i.e. the grid defined by the congruence
01490       // (2e %= 0) / m) then add the 2-complement to the potential
01491       // result.
01492       if (x.relation_with((2*e %= 0) / m)
01493           .implies(Poly_Con_Relation::is_included())) {
01494         Grid z = x;
01495         z.add_congruence((2*e %= m) / (2*m));
01496         new_grid.join_assign(z);
01497         continue;
01498       }
01499     }
01500     return;
01501   }
01502 
01503   *this = new_grid;
01504 
01505   assert(OK());
01506 }

void Parma_Polyhedra_Library::Grid::difference_assign ( const Grid y  )  [inline]

Same as grid_difference_assign(y).

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

References grid_difference_assign().

00114                                      {
00115   grid_difference_assign(y);
00116 }

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

01511                                                                        {
01512   // The denominator cannot be zero.
01513   if (denominator == 0)
01514     throw_invalid_argument("affine_image(v, e, d)", "d == 0");
01515 
01516   // Dimension-compatibility checks.
01517   // The dimension of `expr' must be at most the dimension of `*this'.
01518   const dimension_type expr_space_dim = expr.space_dimension();
01519   if (space_dim < expr_space_dim)
01520     throw_dimension_incompatible("affine_image(v, e, d)", "e", expr);
01521   // `var' must be one of the dimensions of the grid.
01522   const dimension_type var_space_dim = var.space_dimension();
01523   if (space_dim < var_space_dim)
01524     throw_dimension_incompatible("affine_image(v, e, d)", "v", var);
01525 
01526   if (marked_empty())
01527     return;
01528 
01529   if (var_space_dim <= expr_space_dim && expr[var_space_dim] != 0) {
01530     // The transformation is invertible.
01531     if (generators_are_up_to_date()) {
01532       // Grid_Generator_System::affine_image() requires the third argument
01533       // to be a positive Coefficient.
01534       if (denominator > 0)
01535         gen_sys.affine_image(var_space_dim, expr, denominator);
01536       else
01537         gen_sys.affine_image(var_space_dim, -expr, -denominator);
01538       clear_generators_minimized();
01539       // Strong normalization in gs::affine_image may have modified
01540       // divisors.
01541       normalize_divisors(gen_sys);
01542     }
01543     if (congruences_are_up_to_date()) {
01544       // To build the inverse transformation,
01545       // after copying and negating `expr',
01546       // we exchange the roles of `expr[var_space_dim]' and `denominator'.
01547       Linear_Expression inverse;
01548       if (expr[var_space_dim] > 0) {
01549         inverse = -expr;
01550         inverse[var_space_dim] = denominator;
01551         con_sys.affine_preimage(var_space_dim, inverse, expr[var_space_dim]);
01552       }
01553       else {
01554         // The new denominator is negative:
01555         // we negate everything once more, as Congruence_System::affine_preimage()
01556         // requires the third argument to be positive.
01557         inverse = expr;
01558         inverse[var_space_dim] = denominator;
01559         neg_assign(inverse[var_space_dim]);
01560         con_sys.affine_preimage(var_space_dim, inverse, -expr[var_space_dim]);
01561       }
01562       clear_congruences_minimized();
01563     }
01564   }
01565   else {
01566     // The transformation is not invertible.
01567     // We need an up-to-date system of generators.
01568     if (!generators_are_up_to_date())
01569       minimize();
01570     if (!marked_empty()) {
01571       // Grid_Generator_System::affine_image() requires the third argument
01572       // to be a positive Coefficient.
01573       if (denominator > 0)
01574         gen_sys.affine_image(var_space_dim, expr, denominator);
01575       else
01576         gen_sys.affine_image(var_space_dim, -expr, -denominator);
01577 
01578       clear_congruences_up_to_date();
01579       clear_generators_minimized();
01580       // Strong normalization in gs::affine_image may have modified
01581       // divisors.
01582       normalize_divisors(gen_sys);
01583     }
01584   }
01585   assert(OK());
01586 }

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

01592                                                                {
01593   // The denominator cannot be zero.
01594   if (denominator == 0)
01595     throw_invalid_argument("affine_preimage(v, e, d)", "d == 0");
01596 
01597   // Dimension-compatibility checks.
01598   // The dimension of `expr' should not be greater than the dimension
01599   // of `*this'.
01600   const dimension_type expr_space_dim = expr.space_dimension();
01601   if (space_dim < expr_space_dim)
01602     throw_dimension_incompatible("affine_preimage(v, e, d)", "e", expr);
01603   // `var' should be one of the dimensions of the polyhedron.
01604   const dimension_type var_space_dim = var.space_dimension();
01605   if (space_dim < var_space_dim)
01606     throw_dimension_incompatible("affine_preimage(v, e, d)", "v", var);
01607 
01608   if (marked_empty())
01609     return;
01610 
01611   if (var_space_dim <= expr_space_dim && expr[var_space_dim] != 0) {
01612     // The transformation is invertible.
01613     if (congruences_are_up_to_date()) {
01614       // Congruence_System::affine_preimage() requires the third argument
01615       // to be a positive Coefficient.
01616       if (denominator > 0)
01617         con_sys.affine_preimage(var_space_dim, expr, denominator);
01618       else
01619         con_sys.affine_preimage(var_space_dim, -expr, -denominator);
01620       clear_congruences_minimized();
01621     }
01622     if (generators_are_up_to_date()) {
01623       // To build the inverse transformation,
01624       // after copying and negating `expr',
01625       // we exchange the roles of `expr[var_space_dim]' and `denominator'.
01626       Linear_Expression inverse;
01627       if (expr[var_space_dim] > 0) {
01628         inverse = -expr;
01629         inverse[var_space_dim] = denominator;
01630         gen_sys.affine_image(var_space_dim, inverse, expr[var_space_dim]);
01631       }
01632       else {
01633         // The new denominator is negative:
01634         // we negate everything once more, as Grid_Generator_System::affine_image()
01635         // requires the third argument to be positive.
01636         inverse = expr;
01637         inverse[var_space_dim] = denominator;
01638         neg_assign(inverse[var_space_dim]);
01639         gen_sys.affine_image(var_space_dim, inverse, -expr[var_space_dim]);
01640       }
01641       clear_generators_minimized();
01642     }
01643   }
01644   else {
01645     // The transformation is not invertible.
01646     // We need an up-to-date system of congruences.
01647     if (!congruences_are_up_to_date())
01648       minimize();
01649     // Congruence_System::affine_preimage() requires the third argument
01650     // to be a positive Coefficient.
01651     if (denominator > 0)
01652       con_sys.affine_preimage(var_space_dim, expr, denominator);
01653     else
01654       con_sys.affine_preimage(var_space_dim, -expr, -denominator);
01655 
01656     clear_generators_up_to_date();
01657     clear_congruences_minimized();
01658   }
01659   assert(OK());
01660 }

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

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;
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 one.
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 1664 of file Grid_public.cc.

References affine_image(), clear_congruences_up_to_date(), clear_generators_minimized(), 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 generalized_affine_preimage().

01667                                                                     {
01668   // The denominator cannot be zero.
01669   if (denominator == 0)
01670     throw_invalid_argument("generalized_affine_image(v, r, e, d)", "d == 0");
01671 
01672   // Dimension-compatibility checks.
01673   // The dimension of `expr' should not be greater than the dimension
01674   // of `*this'.
01675   const dimension_type expr_space_dim = expr.space_dimension();
01676   if (space_dim < expr_space_dim)
01677     throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
01678                                  "e", expr);
01679   // `var' should be one of the dimensions of the grid.
01680   const dimension_type var_space_dim = var.space_dimension();
01681   if (space_dim < var_space_dim)
01682     throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
01683                                  "v", var);
01684 
01685   // Any image of an empty grid is empty.
01686   if (marked_empty())
01687     return;
01688 
01689   affine_image(var, expr, denominator);
01690 
01691   if (modulus == 0)
01692     return;
01693 
01694   // Modulate dimension `var' according to `modulus'.
01695 
01696   generators_are_up_to_date() || minimize();
01697 
01698   // Test if minimization, possibly in affine_image, found an empty
01699   // grid.
01700   if (marked_empty())
01701     return;
01702 
01703   if (modulus < 0)
01704     gen_sys.insert(parameter(-modulus * var));
01705   else
01706     gen_sys.insert(parameter(modulus * var));
01707 
01708   normalize_divisors(gen_sys);
01709 
01710   clear_generators_minimized();
01711   clear_congruences_up_to_date();
01712 
01713   assert(OK());
01714 }

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

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;
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 one.
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 1717 of file Grid_public.cc.

References add_congruence(), add_generator(), affine_preimage(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), generalized_affine_image(), is_empty(), OK(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().

01720                                                                        {
01721   // The denominator cannot be zero.
01722   if (denominator == 0)
01723     throw_invalid_argument("generalized_affine_preimage(v, e, d, m)",
01724                            "d == 0");
01725 
01726   // The dimension of `expr' should be at most the dimension of
01727   // `*this'.
01728   const dimension_type expr_space_dim = expr.space_dimension();
01729   if (space_dim < expr_space_dim)
01730     throw_dimension_incompatible("generalized_affine_preimage(v, e, d, m)",
01731                                  "e", expr);
01732   // `var' should be one of the dimensions of the grid.
01733   const dimension_type var_space_dim = var.space_dimension();
01734   if (space_dim < var_space_dim)
01735     throw_dimension_incompatible("generalized_affine_preimage(v, e, d, m)",
01736                                  "v", var);
01737 
01738   // Check whether the affine relation is an affine function.
01739   if (modulus == 0) {
01740     affine_preimage(var, expr, denominator);
01741     return;
01742   }
01743 
01744   // Check whether the preimage of this affine relation can be easily
01745   // computed as the image of its inverse relation.
01746   Coefficient_traits::const_reference var_coefficient = expr.coefficient(var);
01747   if (var_space_dim <= expr_space_dim && var_coefficient != 0) {
01748     Linear_Expression inverse_expr
01749       = expr - (denominator + var_coefficient) * var;
01750     Coefficient inverse_denominator = - var_coefficient;
01751     if (modulus < 0)
01752       generalized_affine_image(var, inverse_expr, inverse_denominator,
01753                                - modulus);
01754     else
01755       generalized_affine_image(var, inverse_expr, inverse_denominator,
01756                                modulus);
01757     return;
01758   }
01759 
01760   // Here `var_coefficient == 0', so that the preimage cannot be
01761   // easily computed by inverting the affine relation.  Add the
01762   // congruence induced by the affine relation.
01763   if (modulus < 0)
01764     add_congruence((denominator*var %= expr) / denominator /= - modulus);
01765   else
01766     add_congruence((denominator*var %= expr) / denominator /= modulus);
01767 
01768   // If the resulting grid is empty, its preimage is empty too.
01769   // Note: DO check for emptyness here, as we will later add a line.
01770   if (is_empty())
01771     return;
01772   add_generator(grid_line(var));
01773   assert(OK());
01774 }

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

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.
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 one.
Exceptions:
std::invalid_argument Thrown if *this is dimension-incompatible with lhs or rhs.

Definition at line 1778 of file Grid_public.cc.

References add_congruence(), add_recycled_congruences(), add_recycled_congruences_and_minimize(), add_recycled_generators(), add_space_dimensions_and_embed(), clear_congruences_up_to_date(), clear_generators_minimized(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), gen_sys, Parma_Polyhedra_Library::Grid_Generator_System::insert(), is_empty(), Parma_Polyhedra_Library::Grid_Generator::line(), marked_empty(), 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, and throw_dimension_incompatible().

01780                                                                     {
01781   // Dimension-compatibility checks.
01782   // The dimension of `lhs' should be at most the dimension of
01783   // `*this'.
01784   dimension_type lhs_space_dim = lhs.space_dimension();
01785   if (space_dim < lhs_space_dim)
01786     throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
01787                                  "e1", lhs);
01788   // The dimension of `rhs' should be at most the dimension of
01789   // `*this'.
01790   const dimension_type rhs_space_dim = rhs.space_dimension();
01791   if (space_dim < rhs_space_dim)
01792     throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
01793                                  "e2", rhs);
01794 
01795   // Any image of an empty grid is empty.
01796   if (marked_empty())
01797     return;
01798 
01799   TEMP_INTEGER(mod);
01800   if (modulus < 0)
01801     mod = -modulus;
01802   else
01803     mod = modulus;
01804 
01805   // Compute the actual space dimension of `lhs',
01806   // i.e., the highest dimension having a non-zero coefficient in `lhs'.
01807   do {
01808     if (lhs_space_dim == 0) {
01809       // All variables have zero coefficients, so `lhs' is a constant.
01810       add_congruence((lhs %= rhs) / mod);
01811       return;
01812     }
01813   }
01814   while (lhs.coefficient(Variable(--lhs_space_dim)) == 0);
01815 
01816   // Gather in `new_lines' the collections of all the lines having the
01817   // direction of variables occurring in `lhs'.  While at it, check
01818   // whether there exists a variable occurring in both `lhs' and
01819   // `rhs'.
01820   Grid_Generator_System new_lines;
01821   bool lhs_vars_intersect_rhs_vars = false;
01822   for (dimension_type i = lhs_space_dim + 1; i-- > 0; )
01823     if (lhs.coefficient(Variable(i)) != 0) {
01824       new_lines.insert(Grid_Generator::line(Variable(i)));
01825       if (rhs.coefficient(Variable(i)) != 0)
01826         lhs_vars_intersect_rhs_vars = true;
01827     }
01828 
01829   if (lhs_vars_intersect_rhs_vars) {
01830     // Some variables in `lhs' also occur in `rhs'.
01831     // To ease the computation, add an additional dimension.
01832     const Variable new_var = Variable(space_dim);
01833     add_space_dimensions_and_embed(1);
01834 
01835     // Constrain the new dimension to be equal to the right hand side.
01836     // TODO: Use add_congruence_and_minimize() when it has been updated.
01837     Congruence_System new_cgs1(new_var == rhs);
01838     if (add_recycled_congruences_and_minimize(new_cgs1)) {
01839       // The grid still contains points.
01840 
01841       // Cylindrificate on all the variables occurring in the left
01842       // hand side expression.
01843 
01844       // Ajust `new_lines' to the right dimension.
01845       new_lines.insert(parameter(0*Variable(space_dim-1)));
01846       // Add the lines to `gen_sys'.
01847       gen_sys.recycling_insert(new_lines);
01848       normalize_divisors(gen_sys);
01849       // Update the flags.
01850       clear_congruences_up_to_date();
01851       clear_generators_minimized();
01852 
01853       // Constrain the new dimension so that it is congruent to the left
01854       // hand side expression modulo `mod'.
01855       // TODO: Use add_congruence() when it has been updated.
01856       Congruence_System new_cgs2((lhs %= new_var) / mod);
01857       add_recycled_congruences(new_cgs2);
01858     }
01859 
01860     // Remove the temporarily added dimension.
01861     remove_higher_space_dimensions(space_dim-1);
01862   }
01863   else {
01864     // `lhs' and `rhs' variables are disjoint:
01865     // there is no need to add a further dimension.
01866 
01867     // Only add the lines and congruence if there are points.
01868     if (is_empty())
01869       return;
01870 
01871     // Cylindrificate on all the variables occurring in the left hand
01872     // side expression.
01873     add_recycled_generators(new_lines);
01874 
01875     // Constrain the left hand side expression so that it is congruent to
01876     // the right hand side expression modulo `mod'.
01877     add_congruence((lhs %= rhs) / mod);
01878   }
01879 
01880   assert(OK());
01881 }

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

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;
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 one.
Exceptions:
std::invalid_argument Thrown if *this is dimension-incompatible with lhs or rhs.

Definition at line 1884 of file Grid_public.cc.

References add_congruence(), add_recycled_congruences(), add_recycled_congruences_and_minimize(), add_recycled_generators(), add_space_dimensions_and_embed(), clear_congruences_up_to_date(), clear_generators_minimized(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), gen_sys, Parma_Polyhedra_Library::Grid_Generator_System::insert(), is_empty(), Parma_Polyhedra_Library::Grid_Generator::line(), marked_empty(), 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, and throw_dimension_incompatible().

01886                                                                        {
01887   // The dimension of `lhs' must be at most the dimension of `*this'.
01888   dimension_type lhs_space_dim = lhs.space_dimension();
01889   if (space_dim < lhs_space_dim)
01890     throw_dimension_incompatible("generalized_affine_preimage(e1, e2, m)",
01891                                  "lhs", lhs);
01892   // The dimension of `rhs' must be at most the dimension of `*this'.
01893   const dimension_type rhs_space_dim = rhs.space_dimension();
01894   if (space_dim < rhs_space_dim)
01895     throw_dimension_incompatible("generalized_affine_preimage(e1, e2, m)",
01896                                  "e2", rhs);
01897 
01898   // Any preimage of an empty polyhedron is empty.
01899   if (marked_empty())
01900     return;
01901 
01902   TEMP_INTEGER(mod);
01903   if (modulus < 0)
01904     mod = -modulus;
01905   else
01906     mod = modulus;
01907 
01908   // Compute the actual space dimension of `lhs',
01909   // i.e., the highest dimension having a non-zero coefficient in `lhs'.
01910   do {
01911     if (lhs_space_dim == 0) {
01912       // All variables have zero coefficients, so `lhs' is a constant.
01913       // In this case, preimage and image happen to be the same.
01914       add_congruence((lhs %= rhs) / mod);
01915       return;
01916     }
01917   }
01918   while (lhs.coefficient(Variable(--lhs_space_dim)) == 0);
01919 
01920   // Gather in `new_lines' the collections of all the lines having
01921   // the direction of variables occurring in `lhs'.
01922   // While at it, check whether or not there exists a variable
01923   // occurring in both `lhs' and `rhs'.
01924   Grid_Generator_System new_lines;
01925   bool lhs_vars_intersect_rhs_vars = false;
01926   for (dimension_type i = lhs_space_dim + 1; i-- > 0; )
01927     if (lhs.coefficient(Variable(i)) != 0) {
01928       new_lines.insert(Grid_Generator::line(Variable(i)));
01929       if (rhs.coefficient(Variable(i)) != 0)
01930         lhs_vars_intersect_rhs_vars = true;
01931     }
01932 
01933   if (lhs_vars_intersect_rhs_vars) {
01934     // Some variables in `lhs' also occur in `rhs'.
01935     // To ease the computation, add an additional dimension.
01936     const Variable new_var = Variable(space_dim);
01937     add_space_dimensions_and_embed(1);
01938 
01939     // Constrain the new dimension to be equal to `lhs'
01940     // TODO: Use add_congruence_and_minimize() when it has been updated.
01941     Congruence_System new_cgs1(new_var == lhs);
01942     if (add_recycled_congruences_and_minimize(new_cgs1)) {
01943       // The grid still contains points.
01944 
01945       // Cylindrificate on all the variables occurring in the left
01946       // hand side
01947 
01948       // Ajust `new_lines' to the right dimension.
01949       new_lines.insert(parameter(0*Variable(space_dim-1)));
01950       // Add the lines to `gen_sys'.
01951       gen_sys.recycling_insert(new_lines);
01952       normalize_divisors(gen_sys);
01953       // Update the flags.
01954       clear_congruences_up_to_date();
01955       clear_generators_minimized();
01956 
01957       // Constrain the new dimension so that it is related to
01958       // the right hand side modulo `mod'.
01959       // TODO: Use add_congruence() when it has been updated.
01960       Congruence_System new_cgs2((rhs %= new_var) / mod);
01961       add_recycled_congruences(new_cgs2);
01962     }
01963 
01964     // Remove the temporarily added dimension.
01965     remove_higher_space_dimensions(space_dim-1);
01966   }
01967   else {
01968     // `lhs' and `rhs' variables are disjoint:
01969     // there is no need to add a further dimension.
01970 
01971     // Constrain the left hand side expression so that it is congruent to
01972     // the right hand side expression modulo `mod'.
01973     add_congruence((lhs %= rhs) / mod);
01974 
01975     // Any image of an empty grid is empty.
01976     if (is_empty())
01977       return;
01978 
01979     // FIXME: Confirm that it is OK for this to follow the
01980     //        add_congruence, whereas in the branch above (and in
01981     //        affine_image, and in Polyhedron) it comes first.
01982     // Cylindrificate on all the variables occurring in `lhs'.
01983     add_recycled_generators(new_lines);
01984   }
01985   assert(OK());
01986 }

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

References clear_congruences_up_to_date(), clear_generators_minimized(), Parma_Polyhedra_Library::Grid_Generator::divisor(), 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_generators(), OK(), Parma_Polyhedra_Library::Grid_Generator_System::recycling_insert(), set_empty(), space_dim, TEMP_INTEGER, throw_dimension_incompatible(), and update_generators().

01989                                          {
01990   Grid& x = *this;
01991   // Check dimension-compatibility.
01992   if (x.space_dim != y.space_dim)
01993     throw_dimension_incompatible("time_elapse_assign(y)", "y", y);
01994 
01995   // Deal with the zero-dimensional case.
01996   if (x.space_dim == 0) {
01997     if (y.marked_empty())
01998       x.set_empty();
01999     return;
02000   }
02001 
02002   // If either one of `x' or `y' is empty, the result is empty too.
02003   if (x.marked_empty())
02004     return;
02005   if (y.marked_empty()
02006       || (!x.generators_are_up_to_date() && !x.update_generators())
02007       || (!y.generators_are_up_to_date() && !y.update_generators())) {
02008     x.set_empty();
02009     return;
02010   }
02011 
02012   // At this point both generator systems are up-to-date.
02013   Grid_Generator_System gs = y.gen_sys;
02014   dimension_type gs_num_rows = gs.num_generators();
02015 
02016   normalize_divisors(gs, gen_sys);
02017 
02018   for (dimension_type i = gs_num_rows; i-- > 0; ) {
02019     Grid_Generator& g = gs[i];
02020     if (g.is_point()) {
02021       // Transform the point into a parameter.
02022       TEMP_INTEGER(div);
02023       div = g.divisor();
02024       g.divisor() = 0;
02025       g.divisor() = div;
02026     }
02027   }
02028 
02029   if (gs_num_rows == 0)
02030     // `y' was the grid containing a single point at the origin, so
02031     // the result is `x'.
02032     return;
02033 
02034   // Append `gs' to the generators of `x'.
02035 
02036   gen_sys.recycling_insert(gs);
02037 
02038   x.clear_congruences_up_to_date();
02039   x.clear_generators_minimized();
02040 
02041   assert(x.OK(true) && y.OK(true));
02042 }

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

Assigns to *this its topological closure.

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

00258                                  {
00259   return;
00260 }

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.

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, throw_dimension_incompatible(), and update_congruences().

Referenced by limited_extrapolation_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   // As noted in definitions.dox, stable behaviour is only garaunteed
00083   // if y is contained in or equal 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::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 159 of file Grid_widenings.cc.

References add_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().

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   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.widening_assign(y, tp);
00219     x.add_congruences(new_cgs);
00220   }
00221   else
00222     // There are tokens, so widening will leave the grid the same.
00223     x.widening_assign(y, tp);
00224 
00225   assert(OK());
00226 }

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

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

Parameters:
m The number of dimensions to add.
Exceptions:
std::length_error Thrown if adding m new space dimensions would cause the vector space to exceed dimension max_space_dimension().
The new space dimensions will be those having the highest indexes in the new grid, which is characterized by a system of congruences in which the variables which are the new dimensions can have any value. For instance, when starting from the grid $\cL \sseq \Rset^2$ and adding a third space dimension, the result will be the grid

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

Definition at line 79 of file Grid_chdims.cc.

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

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

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

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

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

Parameters:
m The number of space dimensions to add.
Exceptions:
std::length_error Thrown if adding m new space dimensions would cause the vector space to exceed dimension max_space_dimension().
The new space dimensions will be those having the highest indexes in the new grid, which is characterized by a system of congruences in which the variables running through the new dimensions are all constrained to be equal to 0. For instance, when starting from the grid $\cL \sseq \Rset^2$ and adding a third space dimension, the result will be the grid

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

Definition at line 153 of file Grid_chdims.cc.

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

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

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

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

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

Definition at line 218 of file Grid_chdims.cc.

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

00218                                          {
00219   // The space dimension of the resulting grid must be at most the
00220   // maximum allowed space dimension.
00221   if (y.space_dim > max_space_dimension() - space_dimension())
00222     throw_space_dimension_overflow("concatenate_assign(y)",
00223                                    "concatenation exceeds the maximum "
00224                                    "allowed space dimension");
00225 
00226   const dimension_type added_columns = y.space_dim;
00227 
00228   // If `*this' or `y' are empty grids just adjust the space
00229   // dimension.
00230   if (marked_empty() || y.marked_empty()) {
00231     space_dim += added_columns;
00232     set_empty();
00233     return;
00234   }
00235 
00236   // If `y' is a universe 0-dim grid, the result is `*this'.
00237   if (added_columns == 0)
00238     return;
00239 
00240   // If `*this' is a universe 0-dim space grid, the result is `y'.
00241   if (space_dim == 0) {
00242     *this = y;
00243     return;
00244   }
00245 
00246   congruences_are_up_to_date() || 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: the variable having maximum space
00271   // dimension is the one occurring last in the set.
00272   const dimension_type
00273     min_space_dim = to_be_removed.rbegin()->space_dimension();
00274   if (space_dim < min_space_dim)
00275     throw_dimension_incompatible("remove_space_dimensions(vs)", min_space_dim);
00276 
00277   const dimension_type new_space_dim = space_dim - to_be_removed.size();
00278 
00279   if (marked_empty()
00280       || (!generators_are_up_to_date() && !update_generators())) {
00281     // Update the space dimension.
00282     space_dim = new_space_dim;
00283     set_empty();
00284     assert(OK());
00285     return;
00286   }
00287 
00288   // Removing _all_ dimensions from a non-empty grid obtains the
00289   // zero-dimensional universe grid.
00290   if (new_space_dim == 0) {
00291     set_zero_dim_univ();
00292     return;
00293   }
00294 
00295   // FIXME: Can this operate on the congruence system if only the
00296   //        congruence system is up to date?
00297 
00298   gen_sys.remove_space_dimensions(to_be_removed);
00299 
00300   clear_congruences_up_to_date();
00301   clear_generators_minimized();
00302 
00303   // Update the space dimension.
00304   space_dim = new_space_dim;
00305 
00306   assert(OK(true));
00307 }

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 310 of file Grid_chdims.cc.

References clear_congruences_up_to_date(), clear_generators_minimized(), dim_kinds, Parma_Polyhedra_Library::Grid_Generator_System::erase_to_end(), gen_sys, generators_are_minimized(), generators_are_up_to_date(), marked_empty(), OK(), Parma_Polyhedra_Library::Grid_Generator_System::remove_higher_space_dimensions(), set_empty(), set_zero_dim_univ(), space_dim, throw_dimension_incompatible(), and update_generators().

Referenced by generalized_affine_image(), and generalized_affine_preimage().

00310                                                                     {
00311   // Dimension-compatibility check.
00312   if (new_dimension > space_dim)
00313     throw_dimension_incompatible("remove_higher_space_dimensions(nd)",
00314                                  new_dimension);
00315 
00316   // The removal of no dimensions from any grid is a no-op.
00317   // Note that this case also captures the only legal removal of
00318   // dimensions from a grid in a 0-dim space.
00319   if (new_dimension == space_dim) {
00320     assert(OK());
00321     return;
00322   }
00323 
00324   if (marked_empty()
00325       || (!generators_are_up_to_date() && !update_generators())) {
00326     // Removing dimensions from the empty grid just updates the space
00327     // dimension.
00328     space_dim = new_dimension;
00329     set_empty();
00330     assert(OK());
00331     return;
00332   }
00333 
00334   if (new_dimension == 0) {
00335     // Removing all dimensions from a non-empty grid just returns the
00336     // zero-dimensional universe grid.
00337     set_zero_dim_univ();
00338     return;
00339   }
00340 
00341   gen_sys.remove_higher_space_dimensions(new_dimension);
00342 
00343 #if 0
00344   // FIXME: Perhaps add something like remove_rows_and_columns(dims)
00345   //        to Grid_Generator_System for this.
00346   if (generators_are_minimized()) {
00347     gen_sys.erase_to_end(new_dimension + 1);
00348     dim_kinds.erase(dim_kinds.begin() + new_dimension + 1, dim_kinds.end());
00349   }
00350 #else
00351   clear_generators_minimized();
00352 #endif
00353 
00354   clear_congruences_up_to_date();
00355 
00356   // Update the space dimension.
00357   space_dim = new_dimension;
00358 
00359   assert(OK(true));
00360 }

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 413 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::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(), generators_are_up_to_date(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), Parma_Polyhedra_Library::Grid_Generator::LINE, marked_empty(), Parma_Polyhedra_Library::not_a_dimension(), Parma_Polyhedra_Library::Grid_Generator_System::num_generators(), 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::Grid_Generator::type(), and update_generators().

00413                                                         {
00414   if (space_dim == 0)
00415     return;
00416 
00417   if (pfunc.has_empty_codomain()) {
00418     // All dimensions vanish: the grid becomes zero_dimensional.
00419     if (marked_empty()
00420         || (!generators_are_up_to_date() && !update_generators())) {
00421       // Removing all dimensions from the empty grid.
00422       space_dim = 0;
00423       set_empty();
00424     }
00425     else
00426       // Removing all dimensions from a non-empty grid.
00427       set_zero_dim_univ();
00428 
00429     assert(OK());
00430     return;
00431   }
00432 
00433   dimension_type new_space_dimension = pfunc.max_in_codomain() + 1;
00434 
00435   if (new_space_dimension == space_dim) {
00436     // The partial function `pfunc' is indeed total and thus specifies
00437     // a permutation, that is, a renaming of the dimensions.  For
00438     // maximum efficiency, we will simply permute the columns of the
00439     // constraint system and/or the generator system.
00440 
00441     // We first compute suitable permutation cycles for the columns of
00442     // the `con_sys' and `gen_sys' matrices.  We will represent them
00443     // with a linear array, using 0 as a terminator for each cycle
00444     // (notice that the columns with index 0 of `con_sys' and
00445     // `gen_sys' represent the inhomogeneous terms, and thus are
00446     // unaffected by the permutation of dimensions).
00447     // Cycles of length 1 will be omitted so that, in the worst case,
00448     // we will have `space_dim' elements organized in `space_dim/2'
00449     // cycles, which means we will have at most `space_dim/2'
00450     // terminators.
00451     std::vector<dimension_type> cycles;
00452     cycles.reserve(space_dim + space_dim/2);
00453 
00454     // Used to mark elements as soon as they are inserted in a cycle.
00455     std::deque<bool> visited(space_dim);
00456 
00457     for (dimension_type i = space_dim; i-- > 0; ) {
00458       if (!visited[i]) {
00459         dimension_type j = i;
00460         do {
00461           visited[j] = true;
00462           dimension_type k;
00463           (void) pfunc.maps(j, k);
00464           if (k == j)
00465             // Cycle of length 1: skip it.
00466             goto skip;
00467 
00468           cycles.push_back(j+1);
00469           // Go along the cycle.
00470           j = k;
00471         } while (!visited[j]);
00472         // End of cycle: mark it.
00473         cycles.push_back(0);
00474       skip:
00475         ;
00476       }
00477     }
00478 
00479     // If `cycles' is empty then `pfunc' is the identity.
00480     if (cycles.empty())
00481       return;
00482 
00483     // Permute all that is up-to-date.
00484     if (congruences_are_up_to_date()) {
00485       con_sys.permute_columns(cycles);
00486       clear_congruences_minimized();
00487     }
00488 
00489     if (generators_are_up_to_date()) {
00490       gen_sys.permute_columns(cycles);
00491       clear_generators_minimized();
00492     }
00493 
00494     assert(OK());
00495     return;
00496   }
00497 
00498   // If control gets here, then `pfunc' is not a permutation and some
00499   // dimensions must be projected away.
00500 
00501   const Grid_Generator_System& old_gensys = generators();
00502 
00503   if (old_gensys.num_generators() == 0) {
00504     // The grid is empty.
00505     Grid new_grid(new_space_dimension, EMPTY);
00506     std::swap(*this, new_grid);
00507     assert(OK());
00508     return;
00509   }
00510 
00511   // Make a local copy of the partial function.
00512   std::vector<dimension_type> pfunc_maps(space_dim, not_a_dimension());
00513   for (dimension_type j = space_dim; j-- > 0; ) {
00514     dimension_type pfunc_j;
00515     if (pfunc.maps(j, pfunc_j))
00516       pfunc_maps[j] = pfunc_j;
00517   }
00518 
00519   Grid_Generator_System new_gensys;
00520   // Set sortedness, for the assertion met via gs::insert.
00521   new_gensys.set_sorted(false);
00522   // Get the divisor of the first point.
00523   Grid_Generator_System::const_iterator i;
00524   Grid_Generator_System::const_iterator old_gensys_end = old_gensys.end();
00525   for (i = old_gensys.begin(); i != old_gensys_end; ++i)
00526     if (i->is_point())
00527       break;
00528   assert(i != old_gensys_end);
00529   Coefficient_traits::const_reference system_divisor = i->divisor();
00530   for (Grid_Generator_System::const_iterator i = old_gensys.begin();
00531        i != old_gensys_end;
00532        ++i) {
00533     const Grid_Generator& old_g = *i;
00534     Linear_Expression e(0 * Variable(new_space_dimension-1));
00535     bool all_zeroes = true;
00536     for (dimension_type j = space_dim; j-- > 0; ) {
00537       if (old_g.coefficient(Variable(j)) != 0
00538           && pfunc_maps[j] != not_a_dimension()) {
00539         e += Variable(pfunc_maps[j]) * old_g.coefficient(Variable(j));
00540         all_zeroes = false;
00541       }
00542     }
00543     switch (old_g.type()) {
00544     case Grid_Generator::LINE:
00545       if (!all_zeroes)
00546         new_gensys.insert(grid_line(e));
00547       break;
00548     case Grid_Generator::PARAMETER:
00549       if (!all_zeroes)
00550         new_gensys.insert(parameter(e, system_divisor));
00551       break;
00552     case Grid_Generator::POINT:
00553       new_gensys.insert(grid_point(e, old_g.divisor()));
00554       break;
00555     case Grid_Generator::CLOSURE_POINT:
00556     default:
00557       assert(0);
00558     }
00559   }
00560 
00561   Grid new_grid(new_gensys);
00562   std::swap(*this, new_grid);
00563 
00564   assert(OK(true));
00565 }

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 363 of file Grid_chdims.cc.

References add_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().

00363                                                               {
00364   // FIXME: this implementation is _really_ an executable specification.
00365 
00366   // `var' must be one of the dimensions of the vector space.
00367   if (var.space_dimension() > space_dim)
00368     throw_dimension_incompatible("expand_space_dimension(v, m)", "v", var);
00369 
00370   // Adding 0 dimensions leaves the same grid.
00371   if (m == 0)
00372     return;
00373 
00374   // The resulting space dimension must be at most the maximum.
00375   if (m > max_space_dimension() - space_dimension())
00376     throw_space_dimension_overflow("expand_space_dimension(v, m)",
00377                                    "adding m new space dimensions exceeds "
00378                                    "the maximum allowed space dimension");
00379 
00380   // Save the number of dimensions before adding new ones.
00381   dimension_type old_dim = space_dim;
00382 
00383   // Add the required new dimensions.
00384   add_space_dimensions_and_embed(m);
00385 
00386   const dimension_type src_d = var.id();
00387   const Congruence_System& cgs = congruences();
00388   Congruence_System new_congruences;
00389   for (Congruence_System::const_iterator i = cgs.begin(),
00390          cgs_end = cgs.end(); i != cgs_end; ++i) {
00391     const Congruence& cg = *i;
00392 
00393     // Only consider congruences that constrain `var'.
00394     if (cg.coefficient(var) == 0)
00395       continue;
00396 
00397     // Each relevant congruence results in `m' new congruences.
00398     for (dimension_type dst_d = old_dim; dst_d < old_dim+m; ++dst_d) {
00399       Linear_Expression e;
00400       for (dimension_type j = old_dim; j-- > 0; )
00401         e +=
00402           cg.coefficient(Variable(j))
00403           * (j == src_d ? Variable(dst_d) : Variable(j));
00404       new_congruences.insert_verbatim((e + cg.inhomogeneous_term() %= 0)
00405                                       / cg.modulus());
00406     }
00407   }
00408   add_congruences(new_congruences);
00409   assert(OK());
00410 }

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 413 of file Grid_chdims.cc.

References affine_image(), join_assign(), OK(), remove_space_dimensions(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().

00414                                                {
00415   // FIXME: this implementation is _really_ an executable specification.
00416 
00417   // `var' should be one of the dimensions of the grid.
00418   if (var.space_dimension() > space_dim)
00419     throw_dimension_incompatible("fold_space_dimensions(tbf, v)", "v", var);
00420 
00421   // Folding only has effect if dimensions are given.
00422   if (to_be_folded.empty())
00423     return;
00424 
00425   // All variables in `to_be_folded' must be dimensions of the grid.
00426   if (to_be_folded.rbegin()->space_dimension() > space_dim)
00427     throw_dimension_incompatible("fold_space_dimensions(tbf, v)",
00428                                  "*tbf.rbegin()",
00429                                  *to_be_folded.rbegin());
00430 
00431   // Moreover, `var' must not occur in `to_be_folded'.
00432   if (to_be_folded.find(var) != to_be_folded.end())
00433     throw_invalid_argument("fold_space_dimensions(tbf, v)",
00434                            "v should not occur in tbf");
00435 
00436   for (Variables_Set::const_iterator i = to_be_folded.begin(),
00437          tbf_end = to_be_folded.end(); i != tbf_end; ++i) {
00438     Grid copy = *this;
00439     copy.affine_image(var, Linear_Expression(*i));
00440     join_assign(copy);
00441   }
00442   remove_space_dimensions(to_be_folded);
00443   assert(OK());
00444 }

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

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

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

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

Referenced by add_space_dimensions_and_embed(), add_space_dimensions_and_project(), Grid(), minimized_congruences(), set_empty(), and swap().

00119                   {
00120   std::swap(con_sys, y.con_sys);
00121   std::swap(gen_sys, y.gen_sys);
00122   std::swap(status, y.status);
00123   std::swap(space_dim, y.space_dim);
00124   std::swap(dim_kinds, y.dim_kinds);
00125 }

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

02103                                        {
02104   using std::endl;
02105 
02106   s << "space_dim "
02107     << space_dim
02108     << endl;
02109   status.ascii_dump(s);
02110   s << "con_sys ("
02111     << (congruences_are_up_to_date() ? "" : "not_")
02112     << "up-to-date)"
02113     << endl;
02114   con_sys.ascii_dump(s);
02115   s << "gen_sys ("
02116     << (generators_are_up_to_date() ? "" : "not_")
02117     << "up-to-date)"
02118     << endl;
02119   gen_sys.ascii_dump(s);
02120   s << "dimension_kinds";
02121   if ((generators_are_up_to_date() && generators_are_minimized())
02122       || (congruences_are_up_to_date() && congruences_are_minimized()))
02123     for (Dimension_Kinds::const_iterator i = dim_kinds.begin();
02124          i != dim_kinds.end();
02125          ++i)
02126       s << " " << *i;
02127   s << endl;
02128 }

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) and sets *this accordingly.

Returns:
true if successful, else false.

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

02133                                  {
02134   std::string str;
02135 
02136   if (!(s >> str) || str != "space_dim")
02137     return false;
02138 
02139   if (!(s >> space_dim))
02140     return false;
02141 
02142   if (!status.ascii_load(s))
02143     return false;
02144 
02145   if (!(s >> str) || str != "con_sys")
02146     return false;
02147 
02148   if (s >> str) {
02149     if (str == "(up-to-date)")
02150       set_congruences_up_to_date();
02151     else if (str != "(not_up-to-date)")
02152       return false;
02153   }
02154   else
02155     return false;
02156 
02157   if (!con_sys.ascii_load(s))
02158     return false;
02159 
02160   if (!(s >> str) || str != "gen_sys")
02161     return false;
02162 
02163   if (s >> str) {
02164     if (str == "(up-to-date)")
02165       set_generators_up_to_date();
02166     else if (str != "(not_up-to-date)")
02167       return false;
02168   }
02169   else
02170     return false;
02171 
02172   if (!gen_sys.ascii_load(s))
02173     return false;
02174 
02175   if (!(s >> str) || str != "dimension_kinds")
02176     return false;
02177 
02178   if (!marked_empty()
02179       && ((generators_are_up_to_date() && generators_are_minimized())
02180           || (congruences_are_up_to_date() && congruences_are_minimized()))) {
02181     dim_kinds.resize(space_dim + 1);
02182     for (Dimension_Kinds::size_type dim = 0; dim <= space_dim; ++dim) {
02183       short unsigned int dim_kind;
02184       if (!(s >> dim_kind))
02185         return false;
02186       switch(dim_kind) {
02187       case 0: dim_kinds[dim] = PARAMETER; break;
02188       case 1: dim_kinds[dim] = LINE; break;
02189       case 2: dim_kinds[dim] = GEN_VIRTUAL; break;
02190       default: return false;
02191       }
02192     }
02193   }
02194 
02195 
02196   // Check for well-formedness.
02197   assert(OK());
02198   return true;
02199 }

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

References external_memory_in_bytes().

00094                                   {
00095   return sizeof(*this) + external_memory_in_bytes();
00096 }

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

02202                                         {
02203   return
02204     con_sys.external_memory_in_bytes()
02205     + gen_sys.external_memory_in_bytes();
02206 }

void Parma_Polyhedra_Library::Grid::construct ( const 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.

Definition at line 51 of file Grid_nonpublic.cc.

References con_sys, max_space_dimension(), Parma_Polyhedra_Library::Congruence_System::normalize_moduli(), OK(), set_congruences_up_to_date(), set_empty(), set_zero_dim_univ(), space_dim, and Parma_Polyhedra_Library::Congruence_System::space_dimension().

Referenced by Grid().

00051                                                 {
00052   // Protecting against space dimension overflow is up to the caller.
00053   assert(ccgs.space_dimension() <= max_space_dimension());
00054 
00055   // TODO: this implementation is just an executable specification.
00056   Congruence_System cgs = ccgs;
00057 
00058   // Set the space dimension.
00059   space_dim = cgs.space_dimension();
00060 
00061   if (space_dim > 0) {
00062     // Stealing the rows from `cgs'.
00063     std::swap(con_sys, cgs);
00064     con_sys.normalize_moduli();
00065     set_congruences_up_to_date();
00066   }
00067   else {
00068     // Here `space_dim == 0'.
00069     if (cgs.num_columns() > 1)
00070       // See if an inconsistent congruence has been passed.
00071       for (dimension_type i = cgs.num_rows(); i-- > 0; )
00072         if (cgs[i].is_trivial_false()) {
00073           // Inconsistent congruence found: the grid is empty.
00074           // FIXME: Initialize con_sys to the correct dimension in the
00075           //        caller constructors, and copy the necessary parts
00076           //        of set_empty into here.
00077           set_empty();
00078           assert(OK());
00079           return;
00080         }
00081     set_zero_dim_univ();
00082   }
00083 
00084   assert(OK());
00085 }

void Parma_Polyhedra_Library::Grid::construct ( const Grid_Generator_System gs  )  [private]

Builds a grid from a system of generators.

The grid inherits the space dimension of the generator system.

Parameters:
gs The system of generators defining the grid;

Definition at line 88 of file Grid_nonpublic.cc.

References gen_sys, max_space_dimension(), normalize_divisors(), OK(), set_empty(), set_generators_up_to_date(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), and throw_invalid_generators().

00088                                                         {
00089   // Protecting against space dimension overflow is up to the caller.
00090   assert(const_gs.space_dimension() <= max_space_dimension());
00091 
00092   // TODO: this implementation is just an executable specification.
00093   Grid_Generator_System gs = const_gs;
00094 
00095   // Set the space dimension.
00096   space_dim = gs.space_dimension();
00097 
00098   // An empty set of generators defines the empty grid.
00099   if (gs.num_generators() == 0) {
00100     // FIXME: Initialize gen_sys to the correct dimension in the
00101     //        caller constructors, and copy the necessary parts of
00102     //        set_empty into here.
00103     set_empty();
00104     return;
00105   }
00106 
00107   // Non-empty valid generator systems have a supporting point, at least.
00108   if (!gs.has_points())
00109     throw_invalid_generators("Grid(const_gs)", "gs");
00110 
00111   if (space_dim > 0) {
00112     // Steal the rows from `gs'.
00113     std::swap(gen_sys, gs);
00114     normalize_divisors(gen_sys);
00115 
00116     // Generators are now up-to-date.
00117     set_generators_up_to_date();
00118   }
00119   else
00120     set_zero_dim_univ();
00121 
00122   assert(OK());
00123 }

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

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 296 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(), add_recycled_congruences(), add_recycled_congruences_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), concatenate_assign(), construct(), Grid(), grid_difference_assign(), intersection_assign(), is_discrete(), is_empty(), is_topologically_closed(), map_space_dimensions(), minimized_congruences(), operator=(), remove_higher_space_dimensions(), remove_space_dimensions(), time_elapse_assign(), update_generators(), and widening_assign().

00296                    {
00297   status.set_empty();
00298 
00299   // Replace gen_sys with an empty system of the right dimension.
00300   Grid_Generator_System gs(space_dim);
00301   gen_sys.swap(gs);
00302 
00303   // Extend the zero dim false congruence system to the appropriate
00304   // dimension and then swap it with `con_sys'.
00305   Congruence_System cgs(Congruence::zero_dim_false());
00306   cgs.increase_space_dimension(space_dim);
00307   const_cast<Congruence_System&>(con_sys).swap(cgs);
00308 }

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

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

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

00045                                  {
00046   status.set_c_up_to_date();
00047 }

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

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

Referenced by add_generator(), add_recycled_generators(), ascii_load(), construct(), and set_generators_minimized().

00164                                 {
00165   status.set_g_up_to_date();
00166 }

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

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

Referenced by add_generator(), add_recycled_generators(), and add_recycled_generators_and_minimize().

00181                   {
00182   status.reset_empty();
00183 }

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 parameters are out of date.

Definition at line 203 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(), add_recycled_congruences(), affine_preimage(), concatenate_assign(), intersection_assign(), and OK().

00203                                   {
00204   clear_generators_minimized();
00205   status.reset_g_up_to_date();
00206   // Can get rid of gen_sys here.
00207 }

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

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

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

Updates and minimizes the congruences from the generators.

Returns:
Always true.

Definition at line 311 of file Grid_nonpublic.cc.

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

Referenced by add_congruence(), add_recycled_congruences(), add_recycled_congruences_and_minimize(), add_recycled_generators_and_minimize(), concatenate_assign(), congruences(), intersection_assign(), is_included_in(), is_universe(), minimize(), relation_with(), and widening_assign().

00311                                   {
00312   // The caller must ensure that the generators are up to date.
00313   assert(space_dim > 0);
00314   assert(!marked_empty());
00315   assert(gen_sys.num_generators() > 0);
00316   assert(gen_sys.space_dimension() > 0);
00317 
00318   Grid& gr = const_cast<Grid&>(*this);
00319 
00320   if (!generators_are_minimized())
00321     gr.simplify(gr.gen_sys, gr.dim_kinds);
00322 
00323   // `gen_sys' contained rows before being reduced, so it should
00324   // contain at least a single point afterwards.
00325   assert(gen_sys.num_generators() > 0);
00326 
00327   // Populate `con_sys' with congruences characterizing the grid
00328   // described by `gen_sys'.
00329   gr.conversion(gr.gen_sys, gr.con_sys, gr.dim_kinds);
00330 
00331   // Both systems are minimized.
00332   gr.set_congruences_minimized();
00333   gr.set_generators_minimized();
00334   return true;
00335 }

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 338 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_generator(), add_recycled_congruences_and_minimize(), add_recycled_generators(), add_recycled_generators_and_minimize(), bounds(), generators(), get_covering_box(), is_bounded(), join_assign(), limited_extrapolation_assign(), map_space_dimensions(), minimize(), minimized_generators(), OK(), relation_with(), remove_higher_space_dimensions(), remove_space_dimensions(), shrink_bounding_box(), and time_elapse_assign().

00338                                  {
00339   assert(space_dim > 0);
00340   assert(!marked_empty());
00341   assert(congruences_are_up_to_date());
00342 
00343   Grid& x = const_cast<Grid&>(*this);
00344 
00345   if (!congruences_are_minimized())
00346     // Either the system of congruences is consistent, or the grid is
00347     // empty.
00348     if (simplify(x.con_sys, x.dim_kinds)) {
00349       x.set_empty();
00350       return false;
00351     }
00352 
00353   // Populate gen_sys with generators characterizing the grid
00354   // described by con_sys.
00355   conversion(x.con_sys, x.gen_sys, x.dim_kinds);
00356 
00357   // Both systems are minimized.
00358   x.set_congruences_minimized();
00359   x.set_generators_minimized();
00360   return true;
00361 }

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 364 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_congruence_and_minimize(), add_constraint_and_minimize(), add_recycled_congruences_and_minimize(), add_recycled_generators_and_minimize(), affine_image(), affine_preimage(), generalized_affine_image(), intersection_assign_and_minimize(), and join_assign_and_minimize().

00364                         {
00365   // 0-dimension and empty grids are already minimized.
00366   if (marked_empty())
00367     return false;
00368   if (space_dim == 0)
00369     return true;
00370 
00371   // Are both systems already minimized?
00372   if (congruences_are_minimized() && generators_are_minimized())
00373     return true;
00374 
00375   // Invoke update_generators, update_congruences or simplify,
00376   // depending on the state of the systems.
00377   if (congruences_are_up_to_date()) {
00378     if (generators_are_up_to_date()) {
00379       Grid& gr = const_cast<Grid&>(*this);
00380       // Only one of the systems can be minimized here.
00381       if (congruences_are_minimized()) {
00382         // Minimize the generator system.
00383         gr.simplify(gr.gen_sys, gr.dim_kinds);
00384         gr.set_generators_minimized();
00385       }
00386       else {
00387 #ifndef NDEBUG
00388         // Both systems are up to date, and the empty case is handled
00389         // above, so the grid should contain points.
00390         bool empty = simplify(gr.con_sys, gr.dim_kinds);
00391         assert(!empty);
00392 #else
00393         simplify(gr.con_sys, gr.dim_kinds);
00394 #endif
00395         gr.set_congruences_minimized();
00396         if (!generators_are_minimized()) {
00397           // Minimize the generator system.
00398           gr.simplify(gr.gen_sys, gr.dim_kinds);
00399           gr.set_generators_minimized();
00400         }
00401       }
00402     }
00403     else {
00404       // Updating the generators may reveal that `*this' is empty.
00405       const bool ret = update_generators();
00406       assert(OK());
00407       return ret;
00408     }
00409   }
00410   else {
00411     assert(generators_are_up_to_date());
00412     update_congruences();
00413   }
00414   assert(OK());
00415   return true;
00416 }

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 126 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_generators(), Parma_Polyhedra_Library::Grid_Generator_System::num_lines(), Parma_Polyhedra_Library::Matrix::num_rows(), space_dim, TVB_DONT_KNOW, TVB_FALSE, and TVB_TRUE.

Referenced by contains().

00126                                                    {
00127   // Private method: the caller must ensure the following.
00128   assert(space_dim == y.space_dim);
00129   assert(!marked_empty() && !y.marked_empty() && space_dim > 0);
00130 
00131   const Grid& x = *this;
00132 
00133   bool css_normalized = false;
00134 
00135   if (x.congruences_are_minimized() && y.congruences_are_minimized()) {
00136     // Equivalent minimized congruence systems have:
00137     //  - the same number of congruences; ...
00138     if (x.con_sys.num_rows() != y.con_sys.num_rows())
00139       return Grid::TVB_FALSE;
00140     //  - the same number of equalities; ...
00141     dimension_type x_num_equalities = x.con_sys.num_equalities();
00142     if (x_num_equalities != y.con_sys.num_equalities())
00143       return Grid::TVB_FALSE;
00144     //  - and if there are no equalities, the same congruences.
00145     //    Delay this test: try cheaper tests on generators first.
00146     css_normalized = (x_num_equalities == 0);
00147   }
00148 
00149   if (x.generators_are_minimized() && y.generators_are_minimized()) {
00150     // Equivalent minimized generator systems have:
00151     //  - the same number of generators; ...
00152     if (x.gen_sys.num_generators() != y.gen_sys.num_generators())
00153       return Grid::TVB_FALSE;
00154     //  - the same number of lines; ...
00155     const dimension_type x_num_lines = x.gen_sys.num_lines();
00156     if (x_num_lines != y.gen_sys.num_lines())
00157       return Grid::TVB_FALSE;
00158       //  - and if there are no lines, the same generators.
00159     if (x_num_lines == 0) {
00160       // Check for syntactic identity.
00161       if (x.gen_sys == y.gen_sys)
00162         return Grid::TVB_TRUE;
00163       else
00164         return Grid::TVB_FALSE;
00165     }
00166   }
00167 
00168   // TODO: Consider minimizing the systems and re-performing these
00169   //       checks.
00170 
00171   if (css_normalized)
00172     if (x.con_sys == y.con_sys)
00173       return Grid::TVB_TRUE;
00174     else
00175       return Grid::TVB_FALSE;
00176 
00177   return Grid::TVB_DONT_KNOW;
00178 }

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

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 #if BE_LAZY
00189   if (!x.generators_are_up_to_date() && !x.update_generators())
00190     // Updating found `x' empty.
00191     return true;
00192   y.congruences_are_up_to_date() || y.update_congruences();
00193 #else
00194   if (!x.generators_are_minimized() && !x.minimize())
00195     // Minimizing found `x' empty.
00196     return true;
00197   y.congruences_are_minimized() || y.minimize();
00198 #endif
00199 
00200   assert(x.OK());
00201   assert(y.OK());
00202 
00203   const Grid_Generator_System& gs = x.gen_sys;
00204   const Congruence_System& cgs = y.con_sys;
00205 
00206   dimension_type num_rows = gs.num_generators();
00207   for (dimension_type i = num_rows; i-- > 0; )
00208     if (!cgs.satisfies_all_congruences(gs[i]))
00209       return false;
00210 
00211   // Inclusion holds.
00212   return true;
00213 }

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 216 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_generators(), 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().

00217                                                  {
00218   // The dimension of `expr' must be at most the dimension of *this.
00219   if (space_dim < expr.space_dimension())
00220     throw_dimension_incompatible(method_call, "e", expr);
00221 
00222   // A zero-dimensional or empty grid bounds everything.
00223   if (space_dim == 0
00224       || marked_empty()
00225       || (!generators_are_up_to_date() && !update_generators()))
00226     return true;
00227 
00228   // The generators are up to date.
00229   for (dimension_type i = gen_sys.num_generators(); i-- > 0; ) {
00230     const Grid_Generator& g = gen_sys[i];
00231     // Only lines and parameters in `*this' can cause `expr' to be
00232     // unbounded.
00233     if (g.is_line_or_parameter()) {
00234       const int sp_sign = Scalar_Products::homogeneous_sign(expr, g);
00235       if (sp_sign != 0)
00236         // `*this' does not bound `expr'.
00237         return false;
00238     }
00239   }
00240   return true;
00241 }

bool Parma_Polyhedra_Library::Grid::max_min ( const Linear_Expression expr,
char *  method_call,
Coefficient ext_n,
Coefficient ext_d,
bool &  included,
Grid_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 244 of file Grid_nonpublic.cc.

References bounds(), 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::Grid_Generator::point(), set_generators_minimized(), simplify(), space_dim, Parma_Polyhedra_Library::Grid_Generator::strong_normalize(), and TEMP_INTEGER.

Referenced by maximize(), and minimize().

00247                                                 {
00248   if (bounds(expr, method_call)) {
00249     if (marked_empty())
00250       return false;
00251     if (space_dim == 0) {
00252       ext_n = 0;
00253       ext_d = 1;
00254       included = true;
00255       if (point)
00256         *point = Grid_Generator::point();
00257       return true;
00258     }
00259     if (!generators_are_minimized()) {
00260       // Minimize the generator system.
00261       Grid& gr = const_cast<Grid&>(*this);
00262       gr.simplify(gr.gen_sys, gr.dim_kinds);
00263       gr.set_generators_minimized();
00264     }
00265 
00266     const Grid_Generator& gen = gen_sys[0];
00267     Scalar_Products::homogeneous_assign(ext_n, expr, gen);
00268     ext_n += expr.inhomogeneous_term();
00269     ext_d = gen.divisor();
00270     // Reduce ext_n and ext_d.
00271     TEMP_INTEGER(gcd);
00272     gcd_assign(gcd, ext_n, ext_d);
00273     exact_div_assign(ext_n, ext_n, gcd);
00274     exact_div_assign(ext_d, ext_d, gcd);
00275 
00276     included = true;
00277     if (point) {
00278       *point = gen;
00279       point->strong_normalize();
00280     }
00281     return true;
00282   }
00283   return false;
00284 }

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 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::add_space_dimensions ( Congruence_System cgs,
Grid_Generator_System gs,
const dimension_type  dims 
) [inline, private]

Adds new space dimensions to the given systems.

Parameters:
cgs A congruence system, to which columns are added;
gs A generator system, to which rows and columns are added;
dims The number of space dimensions to add.
This method is invoked only by add_space_dimensions_and_embed().

Definition at line 35 of file Grid_chdims.cc.

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

Referenced by add_space_dimensions_and_embed(), and add_space_dimensions_and_project().

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

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

Adds new space dimensions to the given systems.

Parameters:
gs A generator system, to which columns are added;
cgs A congruence system, to which rows and columns are added;
dims The number of space dimensions to add.
This method is invoked only by add_space_dimensions_and_project().

Definition at line 54 of file Grid_chdims.cc.

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

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

PPL::Coefficient Parma_Polyhedra_Library::Grid::normalize_divisors ( Grid_Generator_System sys,
Coefficient_traits::const_reference  divisor = Coefficient_one(),
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.

Returns:
The new system divisor, or zero if divisor was zero.
Parameters:
sys The generator system to be normalized.
divisor An extra divisor to include in the calculation of the common divisor of sys.
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 440 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_generators(), Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), and TEMP_INTEGER.

Referenced by add_generator(), add_recycled_generators(), add_recycled_generators_and_minimize(), add_space_dimensions(), add_space_dimensions_and_project(), affine_image(), construct(), generalized_affine_image(), generalized_affine_preimage(), join_assign(), normalize_divisors(), and time_elapse_assign().

00442                                                            {
00443   assert(divisor >= 0);
00444   if (sys.space_dimension() > 0 && divisor > 0) {
00445     TEMP_INTEGER(lcm);
00446     lcm = divisor;
00447 
00448     dimension_type row = 0;
00449     dimension_type num_rows = sys.num_generators();
00450 
00451     if (first_point)
00452       lcm_assign(lcm, lcm, (*first_point).divisor());
00453     else {
00454       // Move to the first point or parameter.
00455       while (sys[row].is_line())
00456         if (++row == num_rows)
00457           // All rows are lines.
00458           return divisor;
00459 
00460       // Calculate the LCM of `divisor' and the divisor of every
00461       // point or parameter.
00462       while (row < num_rows) {
00463         Grid_Generator& g = sys[row];
00464         if (g.is_parameter_or_point())
00465           lcm_assign(lcm, lcm, g.divisor());
00466         ++row;
00467       }
00468     }
00469 
00470     // Represent every point and every parameter using the LCM as the
00471     // divisor.
00472     for (dimension_type row = 0; row < num_rows; ++row)
00473       sys[row].scale_to_divisor(lcm);
00474 
00475     return lcm;
00476   }
00477   return divisor;
00478 }

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.

Definition at line 419 of file Grid_nonpublic.cc.

References Parma_Polyhedra_Library::Grid_Generator::divisor(), normalize_divisors(), and Parma_Polyhedra_Library::Grid_Generator_System::num_generators().

00420                                                               {
00421   dimension_type row = 0;
00422   dimension_type num_rows = gen_sys.num_generators();
00423   // Find first point in gen_sys.
00424   while (gen_sys[row].is_line_or_parameter())
00425     if (++row == num_rows)
00426       // All rows are lines or parameters; generators should always
00427       // contain a point.
00428       throw std::runtime_error("PPL::Grid::normalize_divisors(sys, gen_sys).");
00429   Grid_Generator& first_point = gen_sys[row];
00430   Coefficient_traits::const_reference gen_sys_divisor = first_point.divisor();
00431   Coefficient divisor = normalize_divisors(sys, gen_sys_divisor);
00432   if (divisor != gen_sys_divisor)
00433     // The divisors of the points in gen_sys are always the same, so
00434     // the new divisor will be the LCM of this value and `divisor',
00435     // hence the third argument.
00436     normalize_divisors(gen_sys, divisor, &first_point);
00437 }

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

References Parma_Polyhedra_Library::Grid_Generator_System::ascii_dump(), Parma_Polyhedra_Library::Congruence_System::ascii_dump(), CON_VIRTUAL, EQUALITY, 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(), TEMP_INTEGER, Parma_Polyhedra_Library::TRACE(), trace_dim_kinds, and upper_triangular().

Referenced by update_generators().

00356                                              {
00357   TRACE(cerr << "============= convert cgs to gs" << endl);
00358   TRACE(cerr << "source:" << endl);
00359   TRACE(source.ascii_dump(cerr));
00360   TRACE(cerr << "dest:" << endl);
00361   TRACE(dest.ascii_dump(cerr));
00362   trace_dim_kinds("cgs to gs ", dim_kinds);
00363 
00364   // Quite similar to the generator to congruence version above.
00365   // Changes here may be needed there too.
00366 
00367   assert(lower_triangular(source, dim_kinds));
00368 
00369   // Initialise matrix row number counters and compute the LCM of the
00370   // diagonal entries of the proper congruences in `source'.
00371   dimension_type source_num_rows = 0, dest_num_rows = 0;
00372   TEMP_INTEGER(diagonal_lcm);
00373   diagonal_lcm = 1;
00374   dimension_type dims = source.num_columns() - 1;
00375   for (dimension_type dim = dims; dim-- > 0; )
00376     if (dim_kinds[dim] == CON_VIRTUAL)
00377       // Virtual congruences map to lines.
00378       ++dest_num_rows;
00379     else {
00380       if (dim_kinds[dim] == PROPER_CONGRUENCE) {
00381         // Dimension `dim' has a proper congruence row at
00382         // `source_num_rows' in `source', so include in `diagonal_lcm'
00383         // the `dim'th element of that row.
00384         lcm_assign(diagonal_lcm, diagonal_lcm, source[source_num_rows][dim]);
00385         // Proper congruences map to parameters.
00386         ++dest_num_rows;
00387       }
00388       // Equalities map to virtual generators.
00389       ++source_num_rows;
00390     }
00391   TRACE(cerr << "diagonal_lcm: " << diagonal_lcm << endl);
00392   TRACE(cerr << "source_num_rows: " << source_num_rows << endl);
00393   TRACE(cerr << "dest_num_rows: " << dest_num_rows << endl);
00394 
00395   // `source' must be regular.
00396   if (diagonal_lcm == 0)
00397     throw std::runtime_error("PPL internal error: Grid::conversion:"
00398                              " source matrix is singular.");
00399 
00400   dest.set_index_first_pending_row(dest_num_rows);
00401   dest.resize_no_copy(dest_num_rows, dims + 1 /* parameter divisor */);
00402 
00403   // In `dest' initialize row types and elements, including setting
00404   // the diagonal elements to the inverse ratio of the `source'
00405   // diagonal elements.
00406   //
00407   // The top-down order of the congruence system rows corresponds to
00408   // the right-left order of the dimensions.
00409   dimension_type source_index = 0;
00410   // The generator system has a bottom-up ordering.
00411   dimension_type dest_index = dest_num_rows - 1;
00412   for (dimension_type dim = dims; dim-- > 0; ) {
00413     TRACE(cerr << "init dim " << dim << endl);
00414     if (dim_kinds[dim] == EQUALITY) {
00415       TRACE(cerr << "  equality" << endl);
00416       ++source_index;
00417     }
00418     else {
00419       Grid_Generator& g = dest[dest_index];
00420       for (dimension_type j = 0; j < dim; ++j)
00421         g[j] = 0;
00422       for (dimension_type j = dim + 1; j < dims; ++j)
00423         g[j] = 0;
00424 
00425       if (dim_kinds[dim] == CON_VIRTUAL) {
00426         TRACE(cerr << "  con_virtual" << endl);
00427         g.set_is_line();
00428         g[dim] = 1;
00429       }
00430       else {
00431         assert(dim_kinds[dim] == PROPER_CONGRUENCE);
00432         TRACE(cerr << "  proper_congruence" << endl);
00433         g.set_is_parameter_or_point();
00434         g[dim] = diagonal_lcm / source[source_index][dim];
00435         ++source_index;
00436       }
00437       --dest_index;
00438     }
00439   }
00440 
00441   assert(upper_triangular(dest, dim_kinds));
00442 
00443   TRACE(cerr << "dest after init:" << endl);
00444   TRACE(dest.ascii_dump(cerr));
00445 
00446   // Convert.
00447   //
00448   // `source_index' and `dest_index' hold the positions of pivot rows
00449   // in `source' and `dest'.  The order of the rows in `dest' is the
00450   // reverse of the order in `source', so the rows are iterated from
00451   // last to first (index 0) in `source' and from first to last in
00452   // `dest'.
00453   source_index = source_num_rows;
00454   dest_index = 0;
00455 
00456   for (dimension_type dim = 0; dim < dims; ++dim) {
00457     TRACE(cerr << "dim: " << dim << endl);
00458 
00459     if (dim_kinds[dim] != CON_VIRTUAL) {
00460       --source_index;
00461       TEMP_INTEGER(source_dim);
00462       source_dim = source[source_index][dim];
00463 
00464       // In the rows in `dest' above `dest_index' divide each element
00465       // at column `dim' by `source_dim'.
00466       for (dimension_type row = dest_index; row-- > 0; ) {
00467         TRACE(cerr << "  row " << row << endl);
00468         TRACE(dest.ascii_dump(cerr));
00469 
00470         Grid_Generator& g = dest[row];
00471 
00472         // Multiply the representation of `dest' such that entry `dim'
00473         // of `g' is a multiple of `source_dim'.  This ensures that
00474         // the result of the division that follows is a whole number.
00475         TEMP_INTEGER(red_source_dim);
00476         gcd_assign(red_source_dim, g[dim], source_dim);
00477         red_source_dim = source_dim / red_source_dim;
00478         multiply_grid(red_source_dim, g, dest, dest_num_rows,
00479                       dims + 1 /* parameter divisor */);
00480 
00481         g[dim] /= source_dim;
00482       }
00483       TRACE(cerr << "dest after dividing grid:" << endl);
00484       TRACE(dest.ascii_dump(cerr));
00485     }
00486 
00487     // Invert and transpose the source row at `source_index' into the
00488     // destination row at `dest_index'.
00489     //
00490     // Consider each dimension `dim_fol' that follows `dim', as the
00491     // rows in `dest' that follow row `dest_index' are zero at index
00492     // `dim'.
00493     dimension_type tem_source_index = source_index;
00494     if (dim_kinds[dim] != EQUALITY)
00495       ++dest_index;
00496     for (dimension_type dim_fol = dim + 1; dim_fol < dims; ++dim_fol) {
00497       TRACE(cerr << "  dim_fol: " << dim_fol);
00498       TRACE(cerr << "  dest_index: " << dest_index);
00499       TRACE(cerr << "  tem_source_index: " << tem_source_index << endl);
00500       if (dim_kinds[dim_fol] != CON_VIRTUAL) {
00501         --tem_source_index;
00502         TEMP_INTEGER(source_dim);
00503         source_dim = source[tem_source_index][dim];
00504         TRACE(cerr << "  rows:" << endl);
00505         // In order to compute the transpose of the inverse of
00506         // `source', subtract source[tem_source_index][dim] times the
00507         // column vector in `dest' at `dim' from the column vector in
00508         // `dest' at `dim_fol'.
00509         //
00510         // I.e., for each row `dest_index' in `dest' that is above the
00511         // row `dest_index', subtract dest[tem_source_index][dim]
00512         // times the entry `dim' from the entry at `dim_fol'.
00513         for (dimension_type row = dest_index; row-- > 0; ) {
00514           assert(row < dest_num_rows);
00515           TRACE(cerr << "       " << row << endl);
00516           Grid_Generator& g = dest[row];
00517           g[dim_fol] -= source_dim * g[dim];
00518         }
00519       }
00520     }
00521     TRACE(cerr << "dest after processing preceding rows:" << endl);
00522     TRACE(dest.ascii_dump(cerr));
00523   }
00524 
00525   assert(upper_triangular(dest, dim_kinds));
00526 
00527 #ifdef STRONG_REDUCTION
00528   for (dimension_type dim = 0, i = 0; dim < dims; ++dim)
00529     if (dim_kinds[dim] != GEN_VIRTUAL)
00530       // Factor the "diagonal" generator out of the preceding rows.
00531       reduce_reduced<Grid_Generator_System, Grid_Generator>
00532         (dest, dim, i++, dim, dims - 1, dim_kinds);
00533   TRACE(cerr << "dest after strong reduction:" << endl);
00534   TRACE(dest.ascii_dump(cerr));
00535 #endif
00536 
00537   // Ensure that the parameter divisors are the same as the divisor of
00538   // the point.
00539   Coefficient_traits::const_reference system_divisor = dest[0][0];
00540   for (dimension_type row = 1, dim = 1; dim < dims; ++dim)
00541     switch (dim_kinds[dim]) {
00542     case PARAMETER:
00543       dest[row].divisor() = system_divisor;
00544     case LINE:
00545       ++row;
00546     case GEN_VIRTUAL:
00547       break;
00548     }
00549   TRACE(cerr << "dest after updating param divisors:" << endl);
00550   TRACE(dest.ascii_dump(cerr));
00551 
00552   trace_dim_kinds("cgs to gs end ", dim_kinds);
00553 
00554   TRACE(cerr << "------------------- cgs to gs conversion done." << endl);
00555 }

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

References Parma_Polyhedra_Library::Congruence_System::ascii_dump(), Parma_Polyhedra_Library::Grid_Generator_System::ascii_dump(), CON_VIRTUAL, Parma_Polyhedra_Library::gcd_assign(), GEN_VIRTUAL, Parma_Polyhedra_Library::lcm_assign(), LINE, lower_triangular(), multiply_grid(), PARAMETER, Parma_Polyhedra_Library::Congruence_System::resize_no_copy(), Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), TEMP_INTEGER, Parma_Polyhedra_Library::TRACE(), trace_dim_kinds, and upper_triangular().

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

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

References Parma_Polyhedra_Library::Matrix::add_zero_rows(), Parma_Polyhedra_Library::Congruence_System::ascii_dump(), 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(), Parma_Polyhedra_Library::TRACE(), and trace_dim_kinds.

Referenced by Parma_Polyhedra_Library::Grid_Certificate::Grid_Certificate(), is_discrete(), is_empty(), is_topologically_closed(), max_min(), minimize(), minimized_congruences(), minimized_generators(), OK(), update_generators(), and widening_assign().

00452                                                                  {
00453   TRACE(cerr << "======== simplify (reduce) cgs:" << endl);
00454   TRACE(cerr << "sys:" << endl);
00455   TRACE(sys.ascii_dump(cerr));
00456   assert(sys.num_columns() > 2);
00457 
00458   // Changes here may also be required in the generator version above.
00459 
00460   // TODO: Consider normalizing the moduli only when congruences are
00461   //       added to con_sys.
00462   sys.normalize_moduli();
00463 
00464   dimension_type num_cols = sys.num_columns() - 1 /* modulus */;
00465 
00466   if (dim_kinds.size() != num_cols)
00467     dim_kinds.resize(num_cols);
00468 
00469   dimension_type num_rows = sys.num_rows();
00470   TRACE(cerr << "  num_rows " << num_rows << endl);
00471 
00472   // For each dimension `dim' move or construct a row into position
00473   // `pivot_index' such that the row has a value of zero in all
00474   // elements preceding column `dim' and some other value in column
00475   // `dim'.
00476   dimension_type pivot_index = 0;
00477   for (dimension_type dim = num_cols; dim-- > 0; ) {
00478     TRACE(cerr << "dim " << dim << endl);
00479     trace_dim_kinds("  ", dim_kinds);
00480 
00481     // Consider the pivot and following rows.
00482     dimension_type row_index = pivot_index;
00483     TRACE(cerr << "  row_index " << row_index << endl);
00484 
00485     // Move down over rows which have zero in column `dim'.
00486     while (row_index < num_rows && sys[row_index][dim] == 0) {
00487       TRACE(cerr << "  .");
00488       ++row_index;
00489     }
00490     TRACE(cerr << endl);
00491 
00492     if (row_index == num_rows) {
00493       // Element in column `dim' is zero in all rows from the pivot,
00494       // or `sys' is empty of rows.
00495       TRACE(cerr << "  Marking virtual row" << endl);
00496       dim_kinds[dim] = CON_VIRTUAL;
00497     }
00498     else {
00499       // row_index != num_rows
00500       if (row_index != pivot_index)
00501         std::swap(sys[row_index], sys[pivot_index]);
00502       Congruence& pivot = sys[pivot_index];
00503       bool pivot_is_equality = pivot.is_equality();
00504 
00505       // Change the matrix so that the value at `dim' in every row
00506       // following `pivot_index' is 0, leaving an equivalent grid.
00507       TRACE(cerr << "  Reducing all following rows" << endl);
00508       while (row_index < num_rows - 1) {
00509         ++row_index;
00510         TRACE(cerr << "    row_index " << row_index << endl);
00511 
00512         Congruence& row = sys[row_index];
00513 
00514         if (row[dim] == 0)
00515           continue;
00516 
00517         if (row.is_equality())
00518           if (pivot_is_equality)
00519             reduce_equality_with_equality(row, pivot, dim);
00520           else {
00521             assert(pivot.is_proper_congruence());
00522             std::swap(row, pivot);
00523             pivot_is_equality = true;
00524             reduce_congruence_with_equality(row, pivot, dim, sys);
00525           }
00526         else {
00527           assert(row.is_proper_congruence());
00528           if (pivot_is_equality)
00529             reduce_congruence_with_equality(row, pivot, dim, sys);
00530           else {
00531             assert(pivot.is_proper_congruence());
00532             reduce_pc_with_pc(row, pivot, dim, 0, dim);
00533           }
00534         }
00535       }
00536 
00537       if (pivot_is_equality)
00538         dim_kinds[dim] = EQUALITY;
00539       else {
00540         assert(pivot.is_proper_congruence());
00541         dim_kinds[dim] = PROPER_CONGRUENCE;
00542       }
00543 
00544 #ifdef STRONG_REDUCTION
00545       // Ensure a positive follows the leading zeros.
00546       if (pivot[dim] < 0)
00547         pivot.negate(0, dim);
00548       // Factor this row out of the preceding ones.
00549       reduce_reduced<Congruence_System, Congruence>
00550         (sys, dim, pivot_index, 0, dim, dim_kinds, false);
00551 #endif
00552       ++pivot_index;
00553     }
00554     TRACE(sys.ascii_dump(cerr));
00555   } // end for (dimension_type dim = num_cols; dim-- > 0; )
00556 
00557   dimension_type& reduced_num_rows = pivot_index; // For clearer naming.
00558 
00559   // Clip any zero rows from the end of the matrix.
00560   if (num_rows > 1 && num_rows > reduced_num_rows) {
00561     TRACE(cerr << "clipping trailing" << endl);
00562 #ifndef NDEBUG
00563     bool ret = rows_are_zero<Congruence_System,Congruence>
00564       (sys,
00565        reduced_num_rows,        // index of first
00566        num_rows - 1,            // index of last
00567        num_cols);               // row size
00568     assert(ret == true);
00569 #endif
00570     // Don't erase the last row as this will be changed to the integrality row.
00571     // FIXME Simplify and improve code if possible.
00572     if (reduced_num_rows > 0)
00573       sys.erase_to_end(reduced_num_rows);
00574     else
00575       sys.erase_to_end(1);
00576   }
00577 
00578   assert(sys.num_rows() == reduced_num_rows
00579          || (sys.num_rows() == 1 && reduced_num_rows == 0));
00580 
00581   if (reduced_num_rows > 0) {
00582     // If the last row is false then make it the equality 1 = 0, and
00583     // make it the only row.
00584     Congruence& last_row = sys[reduced_num_rows - 1];
00585     if (dim_kinds[0] == PROPER_CONGRUENCE) {
00586       if (last_row.inhomogeneous_term() % last_row.modulus() != 0) {
00587         // The last row is a false proper congruence.
00588         last_row.set_is_equality();
00589         dim_kinds[0] = EQUALITY;
00590         goto return_empty;
00591       }
00592     }
00593     else if (dim_kinds[0] == EQUALITY) {
00594       // The last row is a false equality, as all the coefficient terms
00595       // are zero while the inhomogeneous term (as a result of the
00596       // reduced form) is some other value.
00597     return_empty:
00598       last_row[0] = 1;
00599       dim_kinds.resize(1);
00600       std::swap(sys.rows[0], sys.rows.back());
00601       sys.erase_to_end(1);
00602 
00603       trace_dim_kinds("cgs simpl end ", dim_kinds);
00604       assert(sys.OK());
00605       TRACE(cerr << "---- simplify (reduce) cgs done (empty)." << endl);
00606       return true;
00607     }
00608   }
00609   else if (num_rows > 0) {
00610     assert(sys.num_rows() == 1);
00611     // All columns up to the modulus column must have been zero, set
00612     // up the integrality congruence.
00613     dim_kinds[0] = PROPER_CONGRUENCE;
00614     sys[0][num_cols] = 1;
00615     reduced_num_rows = 1;
00616   }
00617 
00618   // Ensure that the last row is the integrality congruence.
00619   dimension_type mod_index = num_cols;
00620   if (dim_kinds[0] == CON_VIRTUAL) {
00621     // The last row is virtual, append the integrality congruence.
00622     dim_kinds[0] = PROPER_CONGRUENCE;
00623     sys.add_zero_rows(1, Linear_Row::Flags(NECESSARILY_CLOSED,
00624                                            Linear_Row::RAY_OR_POINT_OR_INEQUALITY));
00625     Congruence& new_last_row = sys[reduced_num_rows];
00626     new_last_row[mod_index] = 1;
00627     // Try use an existing modulus.
00628     dimension_type row_index = reduced_num_rows;
00629     while (row_index-- > 0) {
00630       Congruence& row = sys[row_index];
00631       if (row[mod_index] > 0) {
00632         new_last_row[mod_index] = row[mod_index];
00633         break;
00634       }
00635     }
00636     new_last_row[0] = new_last_row[mod_index];
00637 #ifdef STRONG_REDUCTION
00638     ++reduced_num_rows;
00639 #endif
00640   }
00641   else {
00642     Congruence& last_row = sys[reduced_num_rows - 1];
00643     last_row[0] = last_row[mod_index];
00644   }
00645 
00646 #ifdef STRONG_REDUCTION
00647   // Factor the modified integrality congruence out of the other rows.
00648   reduce_reduced<Congruence_System, Congruence>
00649     (sys, 0, reduced_num_rows - 1, 0, 0, dim_kinds, false);
00650 #endif
00651 
00652   trace_dim_kinds("cgs simpl end ", dim_kinds);
00653   assert(sys.OK());
00654   TRACE(cerr << "---- simplify (reduce) cgs done." << endl);
00655   return false;
00656 }

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

References Parma_Polyhedra_Library::Grid_Generator_System::ascii_dump(), GEN_VIRTUAL, 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_generators(), Parma_Polyhedra_Library::Grid_Generator_System::OK(), PARAMETER, reduce_line_with_line(), reduce_parameter_with_line(), reduce_pc_with_pc(), Parma_Polyhedra_Library::TRACE(), trace_dim_kinds, and Parma_Polyhedra_Library::Grid_Generator_System::unset_pending_rows().

00309                                                                      {
00310   TRACE(cerr << "==== simplify (reduce) gs:" << endl);
00311   TRACE(cerr << "sys:" << endl);
00312   TRACE(sys.ascii_dump(cerr));
00313   assert(sys.num_generators() > 0);
00314   assert(sys.num_columns() > 0); // For reduce_pc_with_pc.
00315 
00316   // Changes here may also be required in the congruence version
00317   // below.
00318 
00319   dimension_type num_cols = sys.num_columns() - 1 /* parameter divisor */;
00320 
00321   if (dim_kinds.size() != num_cols)
00322     dim_kinds.resize(num_cols);
00323 
00324   dimension_type num_rows = sys.num_generators();
00325   TRACE(cerr << "  num_rows " << num_rows << endl);
00326 
00327   // For each dimension `dim' move or construct a row into position
00328   // `pivot_index' such that the row has zero in all elements
00329   // following column `dim' and a value other than zero in column
00330   // `dim'.
00331   dimension_type pivot_index = 0;
00332   for (dimension_type dim = 0; dim < num_cols; ++dim) {
00333     TRACE(cerr << "dim " << dim << endl);
00334     trace_dim_kinds("  ", dim_kinds);
00335 
00336     // Consider the pivot and following rows.
00337     dimension_type row_index = pivot_index;
00338     TRACE(cerr << "  row_index " << row_index << endl);
00339 
00340     // Move down over rows which have zero in column `dim'.
00341     while (row_index < num_rows && sys[row_index][dim] == 0) {
00342       TRACE(cerr << "  .");
00343       ++row_index;
00344     }
00345     TRACE(cerr << endl);
00346 
00347     if (row_index == num_rows) {
00348       // Element in column `dim' is zero in all rows from the pivot.
00349       TRACE(cerr << "  Marking virtual row" << endl);
00350       dim_kinds[dim] = GEN_VIRTUAL;
00351     }
00352     else {
00353       if (row_index != pivot_index)
00354         std::swap(sys[row_index], sys[pivot_index]);
00355       Grid_Generator& pivot = sys[pivot_index];
00356       bool pivot_is_line = pivot.is_line();
00357 
00358       // Change the matrix so that the value at `dim' in every row
00359       // following `pivot_index' is 0, leaving an equivalent grid.
00360       TRACE(cerr << "  Reducing all following rows" << endl);
00361       while (row_index < num_rows - 1) {
00362         ++row_index;
00363         TRACE(cerr << "    row_index " << row_index << endl);
00364 
00365         Grid_Generator& row = sys[row_index];
00366 
00367         if (row[dim] == 0)
00368           continue;
00369 
00370         if (row.is_line())
00371           if (pivot_is_line)
00372             reduce_line_with_line(row, pivot, dim);
00373           else {
00374             assert(pivot.is_parameter_or_point());
00375             std::swap(row, pivot);
00376             pivot_is_line = true;
00377             reduce_parameter_with_line(row, pivot, dim, sys);
00378           }
00379         else {
00380           assert(row.is_parameter_or_point());
00381           if (pivot_is_line)
00382             reduce_parameter_with_line(row, pivot, dim, sys);
00383           else {
00384             assert(pivot.is_parameter_or_point());
00385             reduce_pc_with_pc(row, pivot, dim, dim + 1, num_cols);
00386           }
00387         }
00388       }
00389 
00390       if (pivot_is_line)
00391         dim_kinds[dim] = LINE;
00392       else {
00393         assert(pivot.is_parameter_or_point());
00394         dim_kinds[dim] = PARAMETER;
00395       }
00396 
00397 #ifdef STRONG_REDUCTION
00398       // Ensure a positive follows the leading zeros.
00399       if (pivot[dim] < 0)
00400         pivot.negate(dim, num_cols - 1);
00401       TRACE(cerr << "  rr pivot_index " << pivot_index << endl);
00402       TRACE(sys.ascii_dump(cerr));
00403       // Factor this row out of the preceding rows.
00404       reduce_reduced<Grid_Generator_System, Grid_Generator>
00405         (sys, dim, pivot_index, dim, num_cols - 1, dim_kinds);
00406 #endif
00407 
00408       ++pivot_index;
00409     }
00410     TRACE(sys.ascii_dump(cerr));
00411   }
00412   trace_dim_kinds("gs simpl end ", dim_kinds);
00413 
00414   // Clip any zero rows from the end of the matrix.
00415   if (num_rows > pivot_index) {
00416     TRACE(cerr << "clipping trailing" << endl);
00417 #ifndef NDEBUG
00418     bool ret = rows_are_zero<Grid_Generator_System,Grid_Generator>
00419       (sys,
00420        pivot_index,              // index of first
00421        sys.num_generators() - 1, // index of last
00422        sys.num_columns() - 1);   // row size
00423     assert(ret == true);
00424 #endif
00425     sys.erase_to_end(pivot_index);
00426   }
00427 
00428   sys.unset_pending_rows();
00429 
00430   // Ensure that the parameter divisors are the same as the system
00431   // divisor.
00432   TRACE(cerr << "updating param divisors" << endl);
00433   Coefficient_traits::const_reference system_divisor = sys[0][0];
00434   for (dimension_type row = 1, dim = 1, num_cols = sys.num_columns() - 1;
00435        dim < num_cols;
00436        ++dim)
00437     switch (dim_kinds[dim]) {
00438     case PARAMETER:
00439       sys[row].divisor() = system_divisor;
00440     case LINE:
00441       ++row;
00442     case GEN_VIRTUAL:
00443       break;
00444     }
00445 
00446   assert(sys.OK());
00447 
00448   TRACE(cerr << "---- simplify (reduce) gs done." << endl);
00449 }

void Parma_Polyhedra_Library::Grid::reduce_line_with_line ( Grid_Generator row,
Grid_Generator pivot,
dimension_type  col 
) [inline, 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 110 of file Grid_simplify.cc.

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

Referenced by simplify().

00111                                                    {
00112   TRACE(cerr << "reduce_line_with_line" << endl);
00113 
00114   TEMP_INTEGER(gcd);
00115   gcd_assign(gcd, pivot[column], row[column]);
00116   // Store the reduced ratio between pivot[column] and row[column].
00117   TEMP_INTEGER(red_pivot_col);
00118   TEMP_INTEGER(red_row_col);
00119   red_pivot_col = pivot[column] / gcd;
00120   red_row_col = row[column] / gcd;
00121   // Multiply row, then subtract from it a multiple of pivot such that
00122   // the result in row[column] is zero.
00123   row[column] = 0;
00124   for (dimension_type col = pivot.size() - 2 /* parameter divisor, index */;
00125        col > column;
00126        --col)
00127     row[col] = (red_pivot_col * row[col]) - (red_row_col * pivot[col]);
00128 }

void Parma_Polyhedra_Library::Grid::reduce_equality_with_equality ( Congruence row,
Congruence pivot,
dimension_type  col 
) [inline, 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 131 of file Grid_simplify.cc.

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

Referenced by simplify().

00132                                                            {
00133   TRACE(cerr << "reduce_equality_with_equality" << endl);
00134   // Assume two equalities.
00135   assert(row.modulus() == 0 && pivot.modulus() == 0);
00136 
00137   TEMP_INTEGER(gcd);
00138   gcd_assign(gcd, pivot[column], row[column]);
00139   // Store the reduced ratio between pivot[column] and row[column].
00140   TEMP_INTEGER(red_pivot_col);
00141   TEMP_INTEGER(red_row_col);
00142   red_pivot_col = pivot[column] / gcd;
00143   red_row_col = row[column] / gcd;
00144   // Multiply row, then subtract from it a multiple of pivot such that
00145   // the result in row[column] is zero.
00146   row[column] = 0;
00147   for (dimension_type col = 0; col < column; ++col)
00148     row[col] = (red_pivot_col * row[col]) - (red_row_col * pivot[col]);
00149 }

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

References Parma_Polyhedra_Library::gcdext_assign(), TEMP_INTEGER, and Parma_Polyhedra_Library::TRACE().

Referenced by simplify().

00156                                             {
00157   TEMP_INTEGER(gcd);
00158   TEMP_INTEGER(s);
00159   TEMP_INTEGER(t);
00160   gcdext_assign(gcd, pivot[column], row[column], s, t);
00161   // Now pivot[column] * s + row[column] * t == gcd.
00162   TRACE(cerr << "  gcd " << gcd << ", s " << s << ", t " << t << endl);
00163 
00164   // Store the reduced ratio between pivot[column] and row[column].
00165   TEMP_INTEGER(red_pivot_col);
00166   TEMP_INTEGER(red_row_col);
00167   red_pivot_col = pivot[column] / gcd;
00168   red_row_col = row[column] / gcd;
00169   TRACE(cerr << "  red_pivot_col " << red_pivot_col
00170              << ", red_row_col " << red_row_col << endl);
00171 
00172   // Multiply row, then subtract from it a multiple of pivot such that
00173   // the result in row[column] is zero.  Afterwards, multiply pivot,
00174   // then add to it a (possibly negative) multiple of row such that
00175   // the result in pivot[column] is the smallest possible positive
00176   // integer.
00177   assert(pivot.size() > 0);
00178   assert(row.size() > 0);
00179   pivot[column] = gcd;
00180   row[column] = 0;
00181   for (dimension_type col = start; col < end; ++col) {
00182     TEMP_INTEGER(pivot_col);
00183     TEMP_INTEGER(row_col);
00184     pivot_col = pivot[col];
00185     row_col = row[col];
00186     pivot[col] = (s * pivot_col) + (t * row_col);
00187     row[col] = (red_pivot_col * row_col) - (red_row_col * pivot_col);
00188   }
00189 }

void Parma_Polyhedra_Library::Grid::reduce_parameter_with_line ( Grid_Generator row,
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 192 of file Grid_simplify.cc.

References 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_generators(), TEMP_INTEGER, and Parma_Polyhedra_Library::TRACE().

Referenced by simplify().

00195                                                              {
00196   // Very similar to reduce_congruence_with_equality below.  Any
00197   // change here may be needed there too.
00198   TRACE(cerr << "reduce_parameter_with_line" << endl);
00199 
00200   dimension_type num_cols = sys.num_columns() - 1 /* parameter divisor */;
00201 
00202   // If the elements at column in row and pivot are the same, then
00203   // just subtract pivot from row.
00204   if (row[column] == pivot[column]) {
00205     for (dimension_type col = 0; col < num_cols; ++col)
00206       row[col] -= pivot[col];
00207     return;
00208   }
00209 
00210   TEMP_INTEGER(gcd);
00211   gcd_assign(gcd, pivot[column], row[column]);
00212   // Store the reduced ratio between pivot[column] and row[column].
00213   TEMP_INTEGER(red_pivot_col);
00214   TEMP_INTEGER(red_row_col);
00215   red_pivot_col = pivot[column] / gcd;
00216   red_row_col = row[column] / gcd;
00217 
00218   // Multiply row such that a multiple of pivot can be subtracted from
00219   // it below to render row[column] zero.  This requires multiplying
00220   // all other parameters to match.
00221 #ifdef STRONG_REDUCTION
00222   // Ensure that the multiplier is positive, so that the preceding
00223   // diagonals (including the divisor) remain positive.  It's safe to
00224   // swap the signs as row[column] will still come out 0.
00225   if (red_pivot_col < 0) {
00226     neg_assign(red_pivot_col);
00227     neg_assign(red_row_col);
00228   }
00229 #endif
00230   for (dimension_type index = 0; index < sys.num_generators(); ++index) {
00231     Grid_Generator& row = sys[index];
00232     if (row.is_parameter_or_point())
00233       for (dimension_type col = 0; col < num_cols; ++col)
00234         row[col] *= red_pivot_col;
00235   }
00236   // Subtract from row a multiple of pivot such that the result in
00237   // row[column] is zero.
00238   row[column] = 0;
00239   for (dimension_type col = num_cols - 1; col > column; --col)
00240     row[col] -= red_row_col * pivot[col];
00241 }

void Parma_Polyhedra_Library::Grid::reduce_congruence_with_equality ( Congruence row,
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 244 of file Grid_simplify.cc.

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

Referenced by simplify().

00247                                                               {
00248   // Very similar to reduce_parameter_with_line above.  Any change
00249   // here may be needed there too.
00250   TRACE(cerr << "reduce_congruence_with_equality" << endl);
00251   assert(row.modulus() > 0 && pivot.modulus() == 0);
00252 
00253   dimension_type num_cols = sys.num_columns();
00254 
00255   // If the elements at `column' in row and pivot are the same, then
00256   // just subtract `pivot' from `row'.
00257   if (row[column] == pivot[column]) {
00258     for (dimension_type col = 0; col < num_cols; ++col)
00259       row[col] -= pivot[col];
00260     return;
00261   }
00262 
00263   TEMP_INTEGER(gcd);
00264   gcd_assign(gcd, pivot[column], row[column]);
00265   TEMP_INTEGER(red_pivot_col);
00266   TEMP_INTEGER(red_row_a);
00267   red_pivot_col = pivot[column] / gcd;
00268   red_row_a = row[column] / gcd;
00269   // Ensure that `red_pivot_col' is positive, so that the modulus
00270   // remains positive when multiplying the proper congruences below.
00271   // It's safe to swap the signs as row[column] will still come out 0.
00272   if (red_pivot_col < 0) {
00273     neg_assign(red_pivot_col);
00274     neg_assign(red_row_a);
00275   }
00276   // Multiply `row', including the modulus, by red_pivot_col.  To keep
00277   // all the moduli the same this requires multiplying all the other
00278   // proper congruences in the same way.
00279   for (dimension_type index = 0; index < sys.num_rows(); ++index) {
00280     Congruence& row = sys[index];
00281     if (row.is_proper_congruence())
00282       for (dimension_type col = 0; col < num_cols; ++col)
00283         row[col] *= red_pivot_col;
00284   }
00285   --num_cols;                   // Modulus.
00286   row[column] = 0;
00287   // Subtract from row a multiple of pivot such that the result in
00288   // row[column] is zero.
00289   for (dimension_type col = 0; col < column; ++col)
00290     row[col] -= red_row_a * pivot[col];
00291 }

template<typename M, typename R>
void Parma_Polyhedra_Library::Grid::reduce_reduced ( M &  sys,
dimension_type  dim,
dimension_type  pivot_index,
dimension_type  start,
dimension_type  end,
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.

Definition at line 39 of file Grid_simplify.cc.

References CON_VIRTUAL, EQUALITY, GEN_VIRTUAL, LINE, PARAMETER, and TEMP_INTEGER.

00041                                                                   {
00042   R& pivot = sys[pivot_index];
00043 
00044   TEMP_INTEGER(pivot_dim);
00045   pivot_dim = pivot[dim];
00046 
00047   if (pivot_dim == 0)
00048     return;
00049 
00050   TEMP_INTEGER(pivot_dim_half);
00051   pivot_dim_half = (pivot_dim + 1) / 2;
00052   Dimension_Kind row_kind = dim_kinds[dim];
00053   Dimension_Kind line_or_equality, virtual_kind;
00054   int jump;
00055   if (generators) {
00056     line_or_equality = LINE;
00057     virtual_kind = GEN_VIRTUAL;
00058     jump = -1;
00059   } else {
00060     line_or_equality = EQUALITY;
00061     virtual_kind = CON_VIRTUAL;
00062     jump = 1;
00063   }
00064 
00065   for (dimension_type row_index = pivot_index, kinds_index = dim + jump;
00066        row_index-- > 0;
00067        kinds_index += jump) {
00068     // Move over any virtual rows.
00069     while (dim_kinds[kinds_index] == virtual_kind)
00070       kinds_index += jump;
00071 
00072     if (row_kind == line_or_equality
00073         || (row_kind == PARAMETER // a.k.a. CONGRUENCE
00074             && dim_kinds[kinds_index] == PARAMETER)) {
00075       R& row = sys[row_index];
00076 
00077       TEMP_INTEGER(row_dim);
00078       row_dim = row[dim];
00079       // num_rows_to_subtract may be positive or negative.
00080       TEMP_INTEGER(num_rows_to_subtract);
00081       num_rows_to_subtract = row_dim / pivot_dim;
00082 
00083       // Ensure that after subtracting num_rows_to_subtract * r_dim
00084       // from row_dim,
00085       // -pivot_dim_half < row_dim <= pivot_dim_half.  E.g., if pivot[dim] =
00086       // 9, then after strong reduction -5 < row_dim <= 5.
00087       Coefficient& row_dim_rem = row_dim;
00088       row_dim_rem %= pivot_dim;
00089       if (row_dim_rem < 0) {
00090         if (row_dim_rem <= -pivot_dim_half)
00091           --num_rows_to_subtract;
00092       }
00093       else if (row_dim_rem > 0 && row_dim_rem > pivot_dim_half)
00094         num_rows_to_subtract++;
00095 
00096       // Subtract num_rows_to_subtract copies of pivot from row i.  Only the
00097       // entries from dim need to be subtracted, as the preceding
00098       // entries are all zero.
00099       // If num_rows_to_subtract is negative, these copies of pivot are
00100       // added to row i.
00101       if (num_rows_to_subtract != 0)
00102         for (dimension_type col = start; col <= end; ++col)
00103           row[col] -= num_rows_to_subtract * pivot[col];
00104     }
00105   }
00106 }

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

Multiply the elements of dest by multiplier.

Definition at line 131 of file Grid_conversion.cc.

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

Referenced by conversion().

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

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

Multiply the elements of dest by multiplier.

Definition at line 108 of file Grid_conversion.cc.

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

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

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

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

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

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

Referenced by conversion(), and OK().

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

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

00297                                                                   {
00298   while (first <= last) {
00299     R& row = system[first++];
00300     for (dimension_type col = 0; col < row_size; ++col)
00301       if (row[col] != 0)
00302         return false;
00303   }
00304   return true;
00305 }

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

Definition at line 481 of file Grid_nonpublic.cc.

00481                                                      {
00482   std::ostringstream s;
00483   s << "PPL::Grid::" << method << "." << std::endl;
00484   throw std::runtime_error(s.str());
00485 }

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

Definition at line 488 of file Grid_nonpublic.cc.

Referenced by affine_image(), affine_preimage(), fold_space_dimensions(), generalized_affine_image(), generalized_affine_preimage(), Grid(), and shrink_bounding_box().

00489                                                             {
00490   std::ostringstream s;
00491   s << "PPL::Grid::" << method << ":" << std::endl
00492     << reason << ".";
00493   throw std::invalid_argument(s.str());
00494 }

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

References space_dimension(), and throw_dimension_incompatible().

00510                                                               {
00511   throw_dimension_incompatible(method, gr_name, gr.space_dimension());
00512 }

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

Definition at line 515 of file Grid_nonpublic.cc.

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

00517                                                                           {
00518   throw_dimension_incompatible(method, e_name, e.space_dimension());
00519 }

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

Definition at line 522 of file Grid_nonpublic.cc.

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

00524                                                                     {
00525   throw_dimension_incompatible(method, cg_name, cg.space_dimension());
00526 }

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

Definition at line 529 of file Grid_nonpublic.cc.

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

00531                                                                    {
00532   throw_dimension_incompatible(method, c_name, c.space_dimension());
00533 }

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

Definition at line 536 of file Grid_nonpublic.cc.

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

00538                                                                        {
00539   throw_dimension_incompatible(method, g_name, g.space_dimension());
00540 }

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

Definition at line 543 of file Grid_nonpublic.cc.

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

00545                                                                             {
00546   throw_dimension_incompatible(method, cgs_name, cgs.space_dimension());
00547 }

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

Definition at line 550 of file Grid_nonpublic.cc.

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

00552                                                                            {
00553   throw_dimension_incompatible(method, cs_name, cs.space_dimension());
00554 }

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

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

00559                                                                                {
00560   throw_dimension_incompatible(method, gs_name, gs.space_dimension());
00561 }

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

Definition at line 564 of file Grid_nonpublic.cc.

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

00566                                                                   {
00567   std::ostringstream s;
00568   s << "PPL::Grid::" << method << ":" << std::endl
00569     << "this->space_dimension() == " << space_dimension() << ", "
00570     << var_name << ".space_dimension() == " << var.space_dimension() << ".";
00571   throw std::invalid_argument(s.str());
00572 }

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

Definition at line 576 of file Grid_nonpublic.cc.

References space_dimension().

00577                                                                       {
00578   std::ostringstream s;
00579   s << "PPL::Grid::" << method << ":" << std::endl
00580     << "this->space_dimension() == " << space_dimension()
00581     << ", required space dimension == " << required_space_dim << ".";
00582   throw std::invalid_argument(s.str());
00583 }

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

Definition at line 586 of file Grid_nonpublic.cc.

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

00587                                                               {
00588   std::ostringstream s;
00589   s << "PPL::Grid::" << method << ":" << std::endl
00590     << reason << ".";
00591   throw std::length_error(s.str());
00592 }

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

Definition at line 595 of file Grid_nonpublic.cc.

Referenced by add_generator().

00596                                                              {
00597   std::ostringstream s;
00598   s << "PPL::Grid::" << method << ":" << std::endl
00599     << "*this is an empty grid and "
00600     << g_name << " is not a point.";
00601   throw std::invalid_argument(s.str());
00602 }

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

Definition at line 605 of file Grid_nonpublic.cc.

Referenced by add_recycled_generators(), add_recycled_generators_and_minimize(), and construct().

00606                                                                {
00607   std::ostringstream s;
00608   s << "PPL::Grid::" << method << ":" << std::endl
00609     << "*this is an empty grid and" << std::endl
00610     << "the non-empty generator system " << gs_name << " contains no points.";
00611   throw std::invalid_argument(s.str());
00612 }


Friends And Related Function Documentation

Definition at line 1914 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 2046 of file Grid_public.cc.

02046                                             {
02047   if (x.space_dim != y.space_dim)
02048     return false;
02049 
02050   if (x.marked_empty())
02051     return y.is_empty();
02052   if (y.marked_empty())
02053     return x.is_empty();
02054   if (x.space_dim == 0)
02055     return true;
02056 
02057   switch (x.quick_equivalence_test(y)) {
02058   case Grid::TVB_TRUE:
02059     return true;
02060 
02061   case Grid::TVB_FALSE:
02062     return false;
02063 
02064   default:
02065     if (x.is_included_in(y)) {
02066       if (x.marked_empty())
02067         return y.is_empty();
02068       return y.is_included_in(x);
02069     }
02070     return false;
02071   }
02072 }

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

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

02210                                                          {
02211   if (gr.is_empty())
02212     s << "false";
02213   else if (gr.is_universe())
02214     s << "true";
02215   else
02216     s << gr.minimized_congruences();
02217   return s;
02218 }

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

00247                                          {
00248   return !(x == y);
00249 }

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

Specializes std::swap.

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

References swap().

00132                                           {
00133   x.swap(y);
00134 }


Member Data Documentation

The number of dimensions of the enclosing vector space.

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

Referenced by add_congruence(), add_congruences(), add_congruences_and_minimize(), add_constraint(), add_constraint_and_minimize(), add_constraints(), add_constraints_and_minimize(), add_generator(), add_recycled_congruences(), add_recycled_congruences_and_minimize(), add_recycled_constraints(), add_recycled_constraints_and_minimize(), add_recycled_generators(), add_recycled_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(), bounds(), concatenate_assign(), congruences(), construct(), contains(), expand_space_dimension(), fold_space_dimensions(), generalized_affine_image(), generalized_affine_preimage(), generators(), get_covering_box(), Grid(), grid_difference_assign(), intersection_assign(), is_bounded(), is_discrete(), is_disjoint_from(), is_empty(), is_included_in(), is_topologically_closed(), is_universe(), join_assign(), join_assign_if_exact(), limited_extrapolation_assign(), map_space_dimensions(), max_min(), minimize(), minimized_congruences(), minimized_generators(), OK(), operator=(), quick_equivalence_test(), relation_with(), remove_higher_space_dimensions(), remove_space_dimensions(), select_wider_congruences(), set_empty(), set_zero_dim_univ(), shrink_bounding_box(), space_dimension(), swap(), time_elapse_assign(), update_congruences(), update_generators(), and widening_assign().


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

Generated on Wed Jul 16 22:55:50 2008 for PPL by  doxygen 1.5.6