Parma_Polyhedra_Library::Octagonal_Shape< T > Class Template Reference
[C++ Language Interface]

An octagonal shape. More...

#include <Octagonal_Shape.defs.hh>

Collaboration diagram for Parma_Polyhedra_Library::Octagonal_Shape< T >:
Collaboration graph
[legend]

List of all members.

Classes

class  Status
 A conjunctive assertion about a Octagonal_Shape<T> object. More...

Public Types

typedef T coefficient_type_base
 The numeric base type upon which OSs are built.
typedef N coefficient_type
 The (extended) numeric type of the inhomogeneous term of the inequalities defining an OS.

Public Member Functions

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

 Octagonal_Shape (dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
 Builds an universe or empty OS of the specified space dimension.
 Octagonal_Shape (const Octagonal_Shape &x, Complexity_Class complexity=ANY_COMPLEXITY)
 Ordinary copy constructor.
template<typename U >
 Octagonal_Shape (const Octagonal_Shape< U > &y, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds a conservative, upward approximation of y.
 Octagonal_Shape (const Constraint_System &cs)
 Builds an OS from the system of constraints cs.
 Octagonal_Shape (const Congruence_System &cgs)
 Builds an OS from a system of congruences.
 Octagonal_Shape (const Generator_System &gs)
 Builds an OS from the system of generators gs.
 Octagonal_Shape (const Polyhedron &ph, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds an OS from the polyhedron ph.
template<typename Interval >
 Octagonal_Shape (const Box< Interval > &box, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds an OS out of a box.
 Octagonal_Shape (const Grid &grid, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds an OS that approximates a grid.
template<typename U >
 Octagonal_Shape (const BD_Shape< U > &bd, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds an OS from a BD shape.
Octagonal_Shapeoperator= (const Octagonal_Shape &y)
 The assignment operator. (*this and y can be dimension-incompatible.).
void swap (Octagonal_Shape &y)
 Swaps *this with octagon y. (*this and y can be dimension-incompatible.).
 ~Octagonal_Shape ()
 Destructor.
Member Functions that Do Not Modify the Octagonal_Shape

dimension_type space_dimension () const
 Returns the dimension of the vector space enclosing *this.
dimension_type affine_dimension () const
 Returns $0$, if *this is empty; otherwise, returns the affine dimension of *this.
Constraint_System constraints () const
 Returns the system of constraints defining *this.
Constraint_System minimized_constraints () const
 Returns a minimized system of constraints defining *this.
Congruence_System congruences () const
 Returns a system of (equality) congruences satisfied by *this.
Congruence_System minimized_congruences () const
 Returns a minimal system of (equality) congruences satisfied by *this with the same affine dimension as *this.
bool contains (const Octagonal_Shape &y) const
 Returns true if and only if *this contains y.
bool strictly_contains (const Octagonal_Shape &y) const
 Returns true if and only if *this strictly contains y.
bool is_disjoint_from (const Octagonal_Shape &y) const
 Returns true if and only if *this and y are disjoint.
Poly_Con_Relation relation_with (const Constraint &c) const
 Returns the relations holding between *this and the constraint c.
Poly_Con_Relation relation_with (const Congruence &cg) const
 Returns the relations holding between *this and the congruence cg.
Poly_Gen_Relation relation_with (const Generator &g) const
 Returns the relations holding between *this and the generator g.
bool is_empty () const
 Returns true if and only if *this is an empty OS.
bool is_universe () const
 Returns true if and only if *this is a universe OS.
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 a bounded OS.
bool is_topologically_closed () const
 Returns true if and only if *this is a topologically closed subset of the vector space.
bool contains_integer_point () const
 Returns true if and only if *this contains (at least) an integer point.
bool constrains (Variable var) const
 Returns true if and only if var is constrained in *this.
bool bounds_from_above (const Linear_Expression &expr) const
 Returns true if and only if expr is bounded from above in *this.
bool bounds_from_below (const Linear_Expression &expr) const
 Returns true if and only if expr is bounded from below in *this.
bool maximize (const Linear_Expression &expr, Coefficient &sup_n, Coefficient &sup_d, bool &maximum) const
 Returns true if and only if *this is not empty and expr is bounded from above in *this, in which case the supremum value is computed.
bool maximize (const Linear_Expression &expr, Coefficient &sup_n, Coefficient &sup_d, bool &maximum, Generator &g) const
 Returns true if and only if *this is not empty and expr is bounded from above in *this, in which case the supremum value and a point where expr reaches it are computed.
bool minimize (const Linear_Expression &expr, Coefficient &inf_n, Coefficient &inf_d, bool &minimum) const
 Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value is computed.
bool minimize (const Linear_Expression &expr, Coefficient &inf_n, Coefficient &inf_d, bool &minimum, Generator &g) const
 Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value and a point where expr reaches it are computed.
bool frequency (const Linear_Expression &expr, Coefficient &freq_n, Coefficient &freq_d, Coefficient &val_n, Coefficient &val_d) const
 Returns true if and only if there exist a unique value val such that *this saturates the equality expr = val.
bool OK () const
 Checks if all the invariants are satisfied.
Space-Dimension Preserving Member Functions that May Modify the Octagonal_Shape

void add_constraint (const Constraint &c)
 Adds a copy of constraint c to the system of constraints defining *this.
void add_constraints (const Constraint_System &cs)
 Adds the constraints in cs to the system of constraints defining *this.
void add_recycled_constraints (Constraint_System &cs)
 Adds the constraints in cs to the system of constraints of *this.
void add_congruence (const Congruence &cg)
 Adds to *this a constraint equivalent to the congruence cg.
void add_congruences (const Congruence_System &cgs)
 Adds to *this constraints equivalent to the congruences in cgs.
void add_recycled_congruences (Congruence_System &cgs)
 Adds to *this constraints equivalent to the congruences in cgs.
void refine_with_constraint (const Constraint &c)
 Uses a copy of constraint c to refine the system of octagonal constraints defining *this.
void refine_with_congruence (const Congruence &cg)
 Uses a copy of congruence cg to refine the system of octagonal constraints of *this.
void refine_with_constraints (const Constraint_System &cs)
 Uses a copy of the constraints in cs to refine the system of octagonal constraints defining *this.
void refine_with_congruences (const Congruence_System &cgs)
 Uses a copy of the congruences in cgs to refine the system of octagonal constraints defining *this.
void unconstrain (Variable var)
 Computes the cylindrification of *this with respect to space dimension var, assigning the result to *this.
void unconstrain (const Variables_Set &vars)
 Computes the cylindrification of *this with respect to the set of space dimensions vars, assigning the result to *this.
void intersection_assign (const Octagonal_Shape &y)
 Assigns to *this the intersection of *this and y.
void upper_bound_assign (const Octagonal_Shape &y)
 Assigns to *this the smallest OS that contains the convex union of *this and y.
bool upper_bound_assign_if_exact (const Octagonal_Shape &y)
 If the upper bound of *this and y is exact, it is assigned to *this and true is returned, otherwise false is returned.
bool integer_upper_bound_assign_if_exact (const Octagonal_Shape &y)
 If the integer upper bound of *this and y is exact, it is assigned to *this and true is returned; otherwise false is returned.
void difference_assign (const Octagonal_Shape &y)
 Assigns to *this the smallest octagon containing the set difference of *this and y.
bool simplify_using_context_assign (const Octagonal_Shape &y)
 Assigns to *this a meet-preserving simplification of *this with respect to y. If false is returned, then the intersection is empty.
void affine_image (Variable var, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the affine image of *this under the function mapping variable var into 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 into the affine expression specified by expr and denominator.
void generalized_affine_image (Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the image of *this with respect to the generalized affine transfer function $\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym.
void generalized_affine_image (const Linear_Expression &lhs, Relation_Symbol relsym, const Linear_Expression &rhs)
 Assigns to *this the image of *this with respect to the generalized affine transfer function $\mathrm{lhs}' \relsym \mathrm{rhs}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym.
void bounded_affine_image (Variable var, const Linear_Expression &lb_expr, const Linear_Expression &ub_expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the image of *this with respect to the bounded affine relation $\frac{\mathrm{lb\_expr}}{\mathrm{denominator}} \leq \mathrm{var}' \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}$.
void generalized_affine_preimage (Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the preimage of *this with respect to the affine relation $\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym.
void generalized_affine_preimage (const Linear_Expression &lhs, Relation_Symbol relsym, const Linear_Expression &rhs)
 Assigns to *this the preimage of *this with respect to the generalized affine relation $\mathrm{lhs}' \relsym \mathrm{rhs}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym.
void bounded_affine_preimage (Variable var, const Linear_Expression &lb_expr, const Linear_Expression &ub_expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the preimage of *this with respect to the bounded affine relation $\frac{\mathrm{lb\_expr}}{\mathrm{denominator}} \leq \mathrm{var}' \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}$.
void time_elapse_assign (const Octagonal_Shape &y)
 Assigns to *this the result of computing the time-elapse between *this and y.
void wrap_assign (const Variables_Set &vars, Bounded_Integer_Type_Width w, Bounded_Integer_Type_Representation r, Bounded_Integer_Type_Overflow o, const Constraint_System *pcs=0, unsigned complexity_threshold=16, bool wrap_individually=true)
 Wraps the specified dimensions of the vector space.
void drop_some_non_integer_points (Complexity_Class complexity=ANY_COMPLEXITY)
 Possibly tightens *this by dropping some points with non-integer coordinates.
void drop_some_non_integer_points (const Variables_Set &vars, Complexity_Class complexity=ANY_COMPLEXITY)
 Possibly tightens *this by dropping some points with non-integer coordinates for the space dimensions corresponding to vars.
void topological_closure_assign ()
 Assigns to *this its topological closure.
void CC76_extrapolation_assign (const Octagonal_Shape &y, unsigned *tp=0)
 Assigns to *this the result of computing the CC76-extrapolation between *this and y.
template<typename Iterator >
void CC76_extrapolation_assign (const Octagonal_Shape &y, Iterator first, Iterator last, unsigned *tp=0)
 Assigns to *this the result of computing the CC76-extrapolation between *this and y.
void BHMZ05_widening_assign (const Octagonal_Shape &y, unsigned *tp=0)
 Assigns to *this the result of computing the BHMZ05-widening between *this and y.
void widening_assign (const Octagonal_Shape &y, unsigned *tp=0)
 Same as BHMZ05_widening_assign(y, tp).
void limited_BHMZ05_extrapolation_assign (const Octagonal_Shape &y, const Constraint_System &cs, unsigned *tp=0)
 Improves the result of the BHMZ05-widening computation by also enforcing those constraints in cs that are satisfied by all the points of *this.
void CC76_narrowing_assign (const Octagonal_Shape &y)
 Restores from y the constraints of *this, lost by CC76-extrapolation applications.
void limited_CC76_extrapolation_assign (const Octagonal_Shape &y, const Constraint_System &cs, unsigned *tp=0)
 Improves the result of the CC76-extrapolation computation by also enforcing those constraints in cs 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 dimensions and embeds the old OS into the new space.
void add_space_dimensions_and_project (dimension_type m)
 Adds m new dimensions to the OS and does not embed it in the new space.
void concatenate_assign (const Octagonal_Shape &y)
 Assigns to *this the concatenation of *this and y, taken in this order.
void remove_space_dimensions (const Variables_Set &vars)
 Removes all the specified dimensions.
void remove_higher_space_dimensions (dimension_type new_dimension)
 Removes the higher dimensions so that the resulting space will have dimension new_dimension.
template<typename Partial_Function >
void map_space_dimensions (const Partial_Function &pfunc)
 Remaps the dimensions of the vector space according to a partial function.
void expand_space_dimension (Variable var, dimension_type m)
 Creates m copies of the space dimension corresponding to var.
void fold_space_dimensions (const Variables_Set &vars, Variable dest)
 Folds the space dimensions in vars into dest.
template<typename Interval_Info >
void refine_fp_interval_abstract_store (Box< Interval< T, Interval_Info > > &store) const
 Refines store with the constraints defining *this.

Static Public Member Functions

static dimension_type max_space_dimension ()
 Returns the maximum space dimension that an OS can handle.
static bool can_recycle_constraint_systems ()
 Returns false indicating that this domain cannot recycle constraints.
static bool can_recycle_congruence_systems ()
 Returns false indicating that this domain cannot recycle congruences.

Private Types

typedef Checked_Number< T,
Debug_WRD_Extended_Number_Policy > 
N
 The (extended) numeric type of the inhomogeneous term of the inequalities defining an OS.

Private Member Functions

bool marked_zero_dim_univ () const
 Returns true if the OS is the zero-dimensional universe.
bool marked_empty () const
 Returns true if the OS is known to be empty.
bool marked_strongly_closed () const
 Returns true if this->matrix is known to be strongly closed.
void set_zero_dim_univ ()
 Turns *this into a zero-dimensional universe OS.
void set_empty ()
 Turns *this into an empty OS.
void set_strongly_closed ()
 Marks *this as strongly closed.
void reset_strongly_closed ()
 Marks *this as possibly not strongly closed.
Nmatrix_at (dimension_type i, dimension_type j)
const Nmatrix_at (dimension_type i, dimension_type j) const
void refine_no_check (const Constraint &c)
 Uses the constraint c to refine *this.
void refine_no_check (const Congruence &cg)
 Uses the congruence cg to refine *this.
void add_octagonal_constraint (dimension_type i, dimension_type j, const N &k)
 Adds the constraint matrix[i][j] <= k.
void add_octagonal_constraint (dimension_type i, dimension_type j, Coefficient_traits::const_reference num, Coefficient_traits::const_reference den)
 Adds the constraint matrix[i][j] <= num/den.
void refine (Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Adds to the Octagonal_Shape the constraint $\mathrm{var} \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}$.
void forget_all_octagonal_constraints (dimension_type v_id)
 Removes all the constraints on variable v_id.
void forget_binary_octagonal_constraints (dimension_type v_id)
 Removes all binary constraints on variable v_id.
void deduce_v_pm_u_bounds (dimension_type v_id, dimension_type last_id, const Linear_Expression &sc_expr, Coefficient_traits::const_reference sc_den, const N &ub_v)
 An helper function for the computation of affine relations.
void deduce_minus_v_pm_u_bounds (dimension_type v, dimension_type last_v, const Linear_Expression &sc_expr, Coefficient_traits::const_reference sc_den, const N &minus_lb_v)
 An helper function for the computation of affine relations.
void get_limiting_octagon (const Constraint_System &cs, Octagonal_Shape &limiting_octagon) const
 Adds to limiting_octagon the octagonal differences in cs that are satisfied by *this.
void compute_successors (std::vector< dimension_type > &successor) const
 Compute the (zero-equivalence classes) successor relation.
void compute_leaders (std::vector< dimension_type > &successor, std::vector< dimension_type > &no_sing_leaders, bool &exist_sing_class, dimension_type &sing_leader) const
 Compute the leaders of zero-equivalence classes.
void compute_leaders (std::vector< dimension_type > &leaders) const
 Compute the leaders of zero-equivalence classes.
void non_redundant_matrix_entries (std::vector< Bit_Row > &non_redundant) const
 Stores into non_redundant information about the matrix entries that are non-redundant (i.e., will occur in strongly reduced matrix).
void strong_reduction_assign () const
 Removes the redundant constraints from this->matrix.
bool is_strongly_reduced () const
 Returns true if and only if this->matrix is strongly reduced.
bool is_strong_coherent () const
 Returns true if in the octagon taken two at a time unary constraints, there is also the constraint that represent their sum.
bool tight_coherence_would_make_empty () const
void strong_closure_assign () const
 Assigns to this->matrix its strong closure.
void strong_coherence_assign ()
 Applies the strong-coherence step to this->matrix.
void tight_closure_assign ()
 Assigns to this->matrix its tight closure.
void incremental_strong_closure_assign (Variable var) const
 Incrementally computes strong closure, assuming that only constraints affecting variable var need to be considered.
bool bounds (const Linear_Expression &expr, bool from_above) const
 Checks if and how expr is bounded in *this.
bool max_min (const Linear_Expression &expr, bool maximize, Coefficient &ext_n, Coefficient &ext_d, bool &included) const
 Maximizes or minimizes expr subject to *this.
bool max_min (const Linear_Expression &expr, bool maximize, Coefficient &ext_n, Coefficient &ext_d, bool &included, Generator &g) const
 Maximizes or minimizes expr subject to *this.
void drop_some_non_integer_points_helper (N &elem)
Exception Throwers

void throw_dimension_incompatible (const char *method, const Octagonal_Shape &x) const
void throw_dimension_incompatible (const char *method, dimension_type required_dim) const
void throw_dimension_incompatible (const char *method, const Constraint &c) const
void throw_dimension_incompatible (const char *method, const Congruence &cg) const
void throw_dimension_incompatible (const char *method, const Generator &g) const
void throw_dimension_incompatible (const char *method, const char *name_row, const Linear_Expression &y) const
void throw_constraint_incompatible (const char *method) const
void throw_expression_too_complex (const char *method, const Linear_Expression &e) const
void throw_generic (const char *method, const char *reason) const

Private Attributes

OR_Matrix< Nmatrix
 The matrix that represents the octagonal shape.
dimension_type space_dim
 Dimension of the space of the octagonal shape.
Status status
 The status flags to keep track of the internal state.

Static Private Attributes

static T default_stop_points []

Friends

class Parma_Polyhedra_Library::Octagonal_Shape
class Parma_Polyhedra_Library::Box
bool operator== (const Octagonal_Shape< T > &x, const Octagonal_Shape< T > &y)
 Returns true if and only if x and y are the same octagon.
template<typename Temp , typename To , typename U >
bool Parma_Polyhedra_Library::rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Octagonal_Shape< U > &x, const Octagonal_Shape< U > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
template<typename Temp , typename To , typename U >
bool Parma_Polyhedra_Library::euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Octagonal_Shape< U > &x, const Octagonal_Shape< U > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
template<typename Temp , typename To , typename U >
bool Parma_Polyhedra_Library::l_infinity_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Octagonal_Shape< U > &x, const Octagonal_Shape< U > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
std::ostream & Parma_Polyhedra_Library::IO_Operators::operator<< (std::ostream &s, const Octagonal_Shape< T > &c)

Related Functions

(Note that these are not member functions.)



template<typename T >
std::ostream & operator<< (std::ostream &s, const Octagonal_Shape< T > &oct)
 Output operator.
template<typename T >
bool operator!= (const Octagonal_Shape< T > &x, const Octagonal_Shape< T > &y)
 Returns true if and only if x and y are different shapes.
template<typename To , typename T >
bool rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Octagonal_Shape< T > &x, const Octagonal_Shape< T > &y, Rounding_Dir dir)
 Computes the rectilinear (or Manhattan) distance between x and y.
template<typename Temp , typename To , typename T >
bool rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Octagonal_Shape< T > &x, const Octagonal_Shape< T > &y, Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
 Computes the rectilinear (or Manhattan) distance between x and y.
template<typename To , typename T >
bool euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Octagonal_Shape< T > &x, const Octagonal_Shape< T > &y, Rounding_Dir dir)
 Computes the euclidean distance between x and y.
template<typename Temp , typename To , typename T >
bool euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Octagonal_Shape< T > &x, const Octagonal_Shape< T > &y, Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
 Computes the euclidean distance between x and y.
template<typename To , typename T >
bool l_infinity_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Octagonal_Shape< T > &x, const Octagonal_Shape< T > &y, Rounding_Dir dir)
 Computes the $L_\infty$ distance between x and y.
template<typename Temp , typename To , typename T >
bool l_infinity_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Octagonal_Shape< T > &x, const Octagonal_Shape< T > &y, Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
 Computes the $L_\infty$ distance between x and y.
bool extract_octagonal_difference (const Constraint &c, dimension_type c_space_dim, dimension_type &c_num_vars, dimension_type &c_first_var, dimension_type &c_second_var, Coefficient &c_coeff, Coefficient &c_term)
 Decodes the constraint c as an octagonal difference.
template<typename T >
void swap (Parma_Polyhedra_Library::Octagonal_Shape< T > &x, Parma_Polyhedra_Library::Octagonal_Shape< T > &y)
 Specializes std::swap.
dimension_type coherent_index (const dimension_type i)
 Returns the index coherent to i.

Detailed Description

template<typename T>
class Parma_Polyhedra_Library::Octagonal_Shape< T >

An octagonal shape.

The class template Octagonal_Shape<T> allows for the efficient representation of a restricted kind of topologically closed convex polyhedra called octagonal shapes (OSs, for short). The name comes from the fact that, in a vector space of dimension 2, bounded OSs are polygons with at most eight sides. The closed affine half-spaces that characterize the OS can be expressed by constraints of the form

\[ ax_i + bx_j \leq k \]

where $a, b \in \{-1, 0, 1\}$ and $k$ is a rational number, which are called octagonal constraints.

Based on the class template type parameter T, a family of extended numbers is built and used to approximate the inhomogeneous term of octagonal constraints. These extended numbers provide a representation for the value $+\infty$, as well as rounding-aware implementations for several arithmetic functions. The value of the type parameter T may be one of the following:

The user interface for OSs is meant to be as similar as possible to the one developed for the polyhedron class C_Polyhedron.

The OS domain optimally supports:

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

A constraint is octagonal if it has the form

\[ \pm a_i x_i \pm a_j x_j \relsym b \]

where $\mathord{\relsym} \in \{ \leq, =, \geq \}$ and $a_i$, $a_j$, $b$ are integer coefficients such that $a_i = 0$, or $a_j = 0$, or $a_i = a_j$. The user is warned that the above octagonal Constraint object will be mapped into a correct and optimal approximation that, depending on the expressive power of the chosen template argument T, may loose some precision. Also note that strict constraints are not octagonal.

For instance, a Constraint object encoding $3x + 3y \leq 1$ will be approximated by:

On the other hand, depending from the context, a Constraint object encoding $3x - y \leq 1$ will be either upward approximated (e.g., by safely ignoring it) or it will cause an exception.

In the following examples it is assumed that the type argument T is one of the possible instances listed above and that variables x, y and z are defined (where they are used) as follows:

    Variable x(0);
    Variable y(1);
    Variable z(2);
Example 1
The following code builds an OS corresponding to a cube in $\Rset^3$, given as a system of constraints:
    Constraint_System cs;
    cs.insert(x >= 0);
    cs.insert(x <= 3);
    cs.insert(y >= 0);
    cs.insert(y <= 3);
    cs.insert(z >= 0);
    cs.insert(z <= 3);
    Octagonal_Shape<T> oct(cs);
In contrast, the following code will raise an exception, since constraints 7, 8, and 9 are not octagonal:
    Constraint_System cs;
    cs.insert(x >= 0);
    cs.insert(x <= 3);
    cs.insert(y >= 0);
    cs.insert(y <= 3);
    cs.insert(z >= 0);
    cs.insert(z <= 3);
    cs.insert(x - 3*y <= 5);    // (7)
    cs.insert(x - y + z <= 5);  // (8)
    cs.insert(x + y + z <= 5);  // (9)
    Octagonal_Shape<T> oct(cs);

Definition at line 408 of file Octagonal_Shape.defs.hh.


Member Typedef Documentation

template<typename T>
typedef N Parma_Polyhedra_Library::Octagonal_Shape< T >::coefficient_type

The (extended) numeric type of the inhomogeneous term of the inequalities defining an OS.

Definition at line 429 of file Octagonal_Shape.defs.hh.

The numeric base type upon which OSs are built.

Definition at line 423 of file Octagonal_Shape.defs.hh.

template<typename T>
typedef Checked_Number<T, Debug_WRD_Extended_Number_Policy> Parma_Polyhedra_Library::Octagonal_Shape< T >::N [private]

The (extended) numeric type of the inhomogeneous term of the inequalities defining an OS.

Definition at line 415 of file Octagonal_Shape.defs.hh.


Constructor & Destructor Documentation

template<typename T >
Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape ( dimension_type  num_dimensions = 0,
Degenerate_Element  kind = UNIVERSE 
) [inline, explicit]

Builds an universe or empty OS of the specified space dimension.

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

Definition at line 108 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape().

00110   : matrix(num_dimensions), space_dim(num_dimensions), status() {
00111   if (kind == EMPTY)
00112     set_empty();
00113   else if (num_dimensions > 0)
00114     // A (non zero-dim) universe octagon is strongly closed.
00115     set_strongly_closed();
00116   PPL_ASSERT(OK());
00117 }

template<typename T >
Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape ( const Octagonal_Shape< T > &  x,
Complexity_Class  complexity = ANY_COMPLEXITY 
) [inline]

Ordinary copy constructor.

The complexity argument is ignored.

Definition at line 121 of file Octagonal_Shape.inlines.hh.

00122   : matrix(y.matrix), space_dim(y.space_dim), status(y.status) {
00123 }

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

Builds a conservative, upward approximation of y.

The complexity argument is ignored.

Definition at line 128 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_zero_dim_univ(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::set_zero_dim_univ().

00132   : matrix((y.strong_closure_assign(), y.matrix)),
00133     space_dim(y.space_dim),
00134     status() {
00135   // TODO: handle flags properly, possibly taking special cases into account.
00136   if (y.marked_empty())
00137     set_empty();
00138   else if (y.marked_zero_dim_univ())
00139     set_zero_dim_univ();
00140 }

template<typename T >
Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape ( const Constraint_System cs  )  [inline, explicit]

Builds an OS from the system of constraints cs.

The OS inherits the space dimension of cs.

Parameters:
cs A system of octagonal constraints.
Exceptions:
std::invalid_argument Thrown if cs contains a constraint which is not optimally supported by the Octagonal shape domain.

Definition at line 144 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), and Parma_Polyhedra_Library::Constraint_System::space_dimension().

00145   : matrix(cs.space_dimension()),
00146     space_dim(cs.space_dimension()),
00147     status() {
00148   if (cs.space_dimension() > 0)
00149     // A (non zero-dim) universe octagon is strongly closed.
00150     set_strongly_closed();
00151   add_constraints(cs);
00152 }

template<typename T >
Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape ( const Congruence_System cgs  )  [inline, explicit]

Builds an OS from a system of congruences.

The OS inherits the space dimension of cgs

Parameters:
cgs A system of congruences.
Exceptions:
std::invalid_argument Thrown if cgs contains a congruence which is not optimally supported by the Octagonal shape domain.

Definition at line 156 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), and Parma_Polyhedra_Library::Congruence_System::space_dimension().

00157   : matrix(cgs.space_dimension()),
00158     space_dim(cgs.space_dimension()),
00159     status() {
00160   if (cgs.space_dimension() > 0)
00161     // A (non zero-dim) universe octagon is strongly closed.
00162     set_strongly_closed();
00163   add_congruences(cgs);
00164 }

template<typename T >
Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape ( const Generator_System gs  )  [inline, explicit]

Builds an OS from the system of generators gs.

Builds the smallest OS containing the polyhedron defined by gs. The OS inherits the space dimension of gs.

Exceptions:
std::invalid_argument Thrown if the system of generators is not empty but has no points.

Definition at line 198 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Generator_System::begin(), Parma_Polyhedra_Library::Generator::CLOSURE_POINT, Parma_Polyhedra_Library::Generator::coefficient(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Generator::divisor(), Parma_Polyhedra_Library::Generator_System::end(), Parma_Polyhedra_Library::Generator::LINE, Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::max_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::Generator::POINT, Parma_Polyhedra_Library::Generator::RAY, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic(), and Parma_Polyhedra_Library::Generator::type().

00199   : matrix(gs.space_dimension()),
00200     space_dim(gs.space_dimension()),
00201     status() {
00202   const Generator_System::const_iterator gs_begin = gs.begin();
00203   const Generator_System::const_iterator gs_end = gs.end();
00204   if (gs_begin == gs_end) {
00205     // An empty generator system defines the empty polyhedron.
00206     set_empty();
00207     return;
00208   }
00209 
00210   typedef typename OR_Matrix<N>::row_reference_type Row_Reference;
00211   typename OR_Matrix<N>::row_iterator mat_begin = matrix.row_begin();
00212 
00213   PPL_DIRTY_TEMP(N, tmp);
00214   bool mat_initialized = false;
00215   bool point_seen = false;
00216   // Going through all the points and closure points.
00217   for (Generator_System::const_iterator k = gs_begin; k != gs_end; ++k) {
00218     const Generator& g = *k;
00219     switch (g.type()) {
00220     case Generator::POINT:
00221       point_seen = true;
00222       // Intentionally fall through.
00223     case Generator::CLOSURE_POINT:
00224       if (!mat_initialized) {
00225         // When handling the first (closure) point, we initialize the matrix.
00226         mat_initialized = true;
00227         const Coefficient& d = g.divisor();
00228         for (dimension_type i = 0; i < space_dim; ++i) {
00229           const Coefficient& g_i = g.coefficient(Variable(i));
00230           const dimension_type di = 2*i;
00231           Row_Reference x_i = *(mat_begin+di);
00232           Row_Reference x_ii = *(mat_begin+di+1);
00233           for (dimension_type j = 0; j < i; ++j) {
00234             const Coefficient& g_j = g.coefficient(Variable(j));
00235             const dimension_type dj = 2*j;
00236             // Set for any point the hyperplanes passing in the point
00237             // and having the octagonal gradient.
00238             // Let be P = [P_1, P_2, ..., P_n] point.
00239             // Hyperplanes: X_i - X_j = P_i - P_j.
00240             div_round_up(x_i[dj], g_j - g_i, d);
00241             div_round_up(x_ii[dj+1], g_i - g_j, d);
00242             // Hyperplanes: X_i + X_j = P_i + P_j.
00243             div_round_up(x_i[dj+1], -g_j - g_i, d);
00244             div_round_up(x_ii[dj], g_i + g_j, d);
00245           }
00246           // Hyperplanes: X_i = P_i.
00247           div_round_up(x_i[di+1], -g_i - g_i, d);
00248           div_round_up(x_ii[di], g_i + g_i, d);
00249         }
00250       }
00251       else {
00252         // This is not the first point: the matrix already contains
00253         // valid values and we must compute maxima.
00254         const Coefficient& d = g.divisor();
00255         for (dimension_type i = 0; i < space_dim; ++i) {
00256           const Coefficient& g_i = g.coefficient(Variable(i));
00257           const dimension_type di = 2*i;
00258           Row_Reference x_i = *(mat_begin+di);
00259           Row_Reference x_ii = *(mat_begin+di+1);
00260           for (dimension_type j = 0; j < i; ++j) {
00261             const Coefficient& g_j = g.coefficient(Variable(j));
00262             const dimension_type dj = 2*j;
00263             // Set for any point the straight lines passing in the point
00264             // and having the octagonal gradient; compute maxima values.
00265             // Let be P = [P_1, P_2, ..., P_n] point.
00266             // Hyperplane: X_i - X_j = max (P_i - P_j, const).
00267             div_round_up(tmp, g_j - g_i, d);
00268             max_assign(x_i[dj], tmp);
00269             div_round_up(tmp, g_i - g_j, d);
00270             max_assign(x_ii[dj+1], tmp);
00271             // Hyperplane: X_i + X_j = max (P_i + P_j, const).
00272             div_round_up(tmp, -g_j - g_i, d);
00273             max_assign(x_i[dj+1], tmp);
00274             div_round_up(tmp, g_i + g_j, d);
00275             max_assign(x_ii[dj], tmp);
00276           }
00277           // Hyperplane: X_i = max (P_i, const).
00278           div_round_up(tmp, -g_i - g_i, d);
00279           max_assign(x_i[di+1], tmp);
00280           div_round_up(tmp, g_i + g_i, d);
00281           max_assign(x_ii[di], tmp);
00282         }
00283       }
00284       break;
00285     default:
00286       // Lines and rays temporarily ignored.
00287       break;
00288     }
00289   }
00290 
00291   if (!point_seen)
00292     // The generator system is not empty, but contains no points.
00293     throw_generic("Octagonal_Shape(gs)",
00294                   "the non-empty generator system gs contains no points.");
00295 
00296   // Going through all the lines and rays.
00297   for (Generator_System::const_iterator k = gs_begin; k != gs_end; ++k) {
00298     const Generator& g = *k;
00299     switch (g.type()) {
00300     case Generator::LINE:
00301         for (dimension_type i = 0; i < space_dim; ++i) {
00302           const Coefficient& g_i = g.coefficient(Variable(i));
00303           const dimension_type di = 2*i;
00304           Row_Reference x_i = *(mat_begin+di);
00305           Row_Reference x_ii = *(mat_begin+di+1);
00306           for (dimension_type j = 0; j < i; ++j) {
00307             const Coefficient& g_j = g.coefficient(Variable(j));
00308             const dimension_type dj = 2*j;
00309             // Set for any line the right limit.
00310             if (g_i != g_j) {
00311               // Hyperplane: X_i - X_j <=/>= +Inf.
00312               assign_r(x_i[dj], PLUS_INFINITY, ROUND_NOT_NEEDED);
00313               assign_r(x_ii[dj+1], PLUS_INFINITY, ROUND_NOT_NEEDED);
00314             }
00315             if (g_i != -g_j) {
00316               // Hyperplane: X_i + X_j <=/>= +Inf.
00317               assign_r(x_i[dj+1], PLUS_INFINITY, ROUND_NOT_NEEDED);
00318               assign_r(x_ii[dj], PLUS_INFINITY, ROUND_NOT_NEEDED);
00319             }
00320           }
00321           if (g_i != 0) {
00322             // Hyperplane: X_i <=/>= +Inf.
00323             assign_r(x_i[di+1], PLUS_INFINITY, ROUND_NOT_NEEDED);
00324             assign_r(x_ii[di], PLUS_INFINITY, ROUND_NOT_NEEDED);
00325           }
00326         }
00327       break;
00328     case Generator::RAY:
00329         for (dimension_type i = 0; i < space_dim; ++i) {
00330           const Coefficient& g_i = g.coefficient(Variable(i));
00331           const dimension_type di = 2*i;
00332           Row_Reference x_i = *(mat_begin+di);
00333           Row_Reference x_ii = *(mat_begin+di+1);
00334           for (dimension_type j = 0; j < i; ++j) {
00335             const Coefficient& g_j = g.coefficient(Variable(j));
00336             const dimension_type dj = 2*j;
00337             // Set for any ray the right limit in the case
00338             // of the binary constraints.
00339             if (g_i < g_j)
00340               // Hyperplane: X_i - X_j >= +Inf.
00341               assign_r(x_i[dj], PLUS_INFINITY, ROUND_NOT_NEEDED);
00342             if (g_i > g_j)
00343               // Hyperplane: X_i - X_j <= +Inf.
00344               assign_r(x_ii[dj+1], PLUS_INFINITY, ROUND_NOT_NEEDED);
00345             if (g_i < -g_j)
00346               // Hyperplane: X_i + X_j >= +Inf.
00347               assign_r(x_i[dj+1], PLUS_INFINITY, ROUND_NOT_NEEDED);
00348             if (g_i > -g_j)
00349               // Hyperplane: X_i + X_j <= +Inf.
00350               assign_r(x_ii[dj], PLUS_INFINITY, ROUND_NOT_NEEDED);
00351           }
00352           // Case: unary constraints.
00353           if (g_i < 0)
00354             // Hyperplane: X_i  = +Inf.
00355             assign_r(x_i[di+1], PLUS_INFINITY, ROUND_NOT_NEEDED);
00356           if (g_i > 0)
00357             // Hyperplane: X_i  = +Inf.
00358             assign_r(x_ii[di], PLUS_INFINITY, ROUND_NOT_NEEDED);
00359         }
00360       break;
00361     default:
00362       // Points and closure points already dealt with.
00363       break;
00364     }
00365   }
00366   set_strongly_closed();
00367   PPL_ASSERT(OK());
00368 }

template<typename T >
Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape ( const Polyhedron ph,
Complexity_Class  complexity = ANY_COMPLEXITY 
) [inline, explicit]

Builds an OS from the polyhedron ph.

Builds an OS containing ph using algorithms whose complexity does not exceed the one specified by complexity. If complexity is ANY_COMPLEXITY, then the OS built is the smallest one containing ph.

Definition at line 44 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::MIP_Problem::add_constraint(), Parma_Polyhedra_Library::MIP_Problem::add_constraints(), Parma_Polyhedra_Library::ANY_COMPLEXITY, Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Polyhedron::con_sys, Parma_Polyhedra_Library::Polyhedron::constraints(), Parma_Polyhedra_Library::Polyhedron::constraints_are_minimized(), Parma_Polyhedra_Library::Polyhedron::constraints_are_up_to_date(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::MIP_Problem::evaluate_objective_function(), Parma_Polyhedra_Library::Polyhedron::generators(), Parma_Polyhedra_Library::Polyhedron::generators_are_up_to_date(), Parma_Polyhedra_Library::Polyhedron::has_pending_constraints(), Parma_Polyhedra_Library::Polyhedron::has_something_pending(), Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::MIP_Problem::is_satisfiable(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Polyhedron::is_universe(), Parma_Polyhedra_Library::Polyhedron::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, Parma_Polyhedra_Library::MIP_Problem::optimizing_point(), Parma_Polyhedra_Library::POLYNOMIAL_COMPLEXITY, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::MIP_Problem::set_objective_function(), Parma_Polyhedra_Library::MIP_Problem::set_optimization_mode(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), Parma_Polyhedra_Library::SIMPLEX_COMPLEXITY, Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::Polyhedron::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.

00046   : matrix(0), space_dim(0), status() {
00047   const dimension_type num_dimensions = ph.space_dimension();
00048 
00049   if (ph.marked_empty()) {
00050     *this = Octagonal_Shape(num_dimensions, EMPTY);
00051     return;
00052   }
00053 
00054   if (num_dimensions == 0) {
00055     *this = Octagonal_Shape(num_dimensions, UNIVERSE);
00056     return;
00057   }
00058 
00059   // Build from generators when we do not care about complexity
00060   // or when the process has polynomial complexity.
00061   if (complexity == ANY_COMPLEXITY
00062       || (!ph.has_pending_constraints() && ph.generators_are_up_to_date())) {
00063     *this = Octagonal_Shape(ph.generators());
00064     return;
00065   }
00066 
00067   // We cannot afford exponential complexity, we do not have a complete set
00068   // of generators for the polyhedron, and the polyhedron is not trivially
00069   // empty or zero-dimensional.  Constraints, however, are up to date.
00070   PPL_ASSERT(ph.constraints_are_up_to_date());
00071 
00072   if (!ph.has_something_pending() && ph.constraints_are_minimized()) {
00073     // If the constraint system of the polyhedron is minimized,
00074     // the test `is_universe()' has polynomial complexity.
00075     if (ph.is_universe()) {
00076       *this = Octagonal_Shape(num_dimensions, UNIVERSE);
00077       return;
00078     }
00079   }
00080 
00081   // See if there is at least one inconsistent constraint in `ph.con_sys'.
00082   for (Constraint_System::const_iterator i = ph.con_sys.begin(),
00083          cs_end = ph.con_sys.end(); i != cs_end; ++i)
00084     if (i->is_inconsistent()) {
00085       *this = Octagonal_Shape(num_dimensions, EMPTY);
00086       return;
00087     }
00088 
00089   // If `complexity' allows it, use simplex to derive the exact (modulo
00090   // the fact that our OSs are topologically closed) variable bounds.
00091   if (complexity == SIMPLEX_COMPLEXITY) {
00092     MIP_Problem lp(num_dimensions);
00093     lp.set_optimization_mode(MAXIMIZATION);
00094 
00095     const Constraint_System& ph_cs = ph.constraints();
00096     if (!ph_cs.has_strict_inequalities())
00097       lp.add_constraints(ph_cs);
00098     else
00099       // Adding to `lp' a topologically closed version of `ph_cs'.
00100       for (Constraint_System::const_iterator i = ph_cs.begin(),
00101              ph_cs_end = ph_cs.end(); i != ph_cs_end; ++i) {
00102         const Constraint& c = *i;
00103         if (c.is_strict_inequality())
00104           lp.add_constraint(Linear_Expression(c) >= 0);
00105         else
00106           lp.add_constraint(c);
00107       }
00108 
00109     // Check for unsatisfiability.
00110     if (!lp.is_satisfiable()) {
00111       *this = Octagonal_Shape<T>(num_dimensions, EMPTY);
00112       return;
00113     }
00114 
00115     // Start with a universe OS that will be refined by the simplex.
00116     *this = Octagonal_Shape<T>(num_dimensions, UNIVERSE);
00117     // Get all the upper bounds.
00118     Generator g(point());
00119     PPL_DIRTY_TEMP_COEFFICIENT(num);
00120     PPL_DIRTY_TEMP_COEFFICIENT(den);
00121     for (dimension_type i = 0; i < num_dimensions; ++i) {
00122       Variable x(i);
00123       // Evaluate optimal upper bound for `x <= ub'.
00124       lp.set_objective_function(x);
00125       if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
00126         g = lp.optimizing_point();
00127         lp.evaluate_objective_function(g, num, den);
00128         num *= 2;
00129         div_round_up(matrix[2*i+1][2*i], num, den);
00130       }
00131       // Evaluate optimal upper bounds for `x + y <= ub'.
00132       for (dimension_type j = 0; j < i; ++j) {
00133         Variable y(j);
00134         lp.set_objective_function(x + y);
00135         if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
00136           g = lp.optimizing_point();
00137           lp.evaluate_objective_function(g, num, den);
00138           div_round_up(matrix[2*i+1][2*j], num, den);
00139         }
00140       }
00141       // Evaluate optimal upper bound for `x - y <= ub'.
00142       for (dimension_type j = 0; j < num_dimensions; ++j) {
00143         if (i == j)
00144           continue;
00145         Variable y(j);
00146         lp.set_objective_function(x - y);
00147         if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
00148           g = lp.optimizing_point();
00149           lp.evaluate_objective_function(g, num, den);
00150           div_round_up((i < j ? matrix[2*j][2*i] : matrix[2*i+1][2*j+1]),
00151                        num, den);
00152         }
00153       }
00154       // Evaluate optimal upper bound for `y - x <= ub'.
00155       for (dimension_type j = 0; j < num_dimensions; ++j) {
00156         if (i == j)
00157           continue;
00158         Variable y(j);
00159         lp.set_objective_function(x - y);
00160         if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
00161           g = lp.optimizing_point();
00162           lp.evaluate_objective_function(g, num, den);
00163           div_round_up((i < j ? matrix[2*j][2*i] : matrix[2*i+1][2*j+1]),
00164                        num, den);
00165         }
00166       }
00167       // Evaluate optimal upper bound for `-x - y <= ub'.
00168       for (dimension_type j = 0; j < i; ++j) {
00169         Variable y(j);
00170         lp.set_objective_function(-x - y);
00171         if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
00172           g = lp.optimizing_point();
00173           lp.evaluate_objective_function(g, num, den);
00174            div_round_up(matrix[2*i][2*j+1], num, den);
00175         }
00176       }
00177       // Evaluate optimal upper bound for `-x <= ub'.
00178       lp.set_objective_function(-x);
00179       if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
00180         g = lp.optimizing_point();
00181         lp.evaluate_objective_function(g, num, den);
00182         num *= 2;
00183         div_round_up(matrix[2*i][2*i+1], num, den);
00184       }
00185     }
00186     set_strongly_closed();
00187     PPL_ASSERT(OK());
00188     return;
00189   }
00190 
00191   // Extract easy-to-find bounds from constraints.
00192   PPL_ASSERT(complexity == POLYNOMIAL_COMPLEXITY);
00193   *this = Octagonal_Shape(num_dimensions, UNIVERSE);
00194   refine_with_constraints(ph.constraints());
00195 }

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

Builds an OS out of a box.

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

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

Definition at line 169 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Box< ITV >::constraints(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), and Parma_Polyhedra_Library::Box< ITV >::space_dimension().

00171   : matrix(box.space_dimension()),
00172     space_dim(box.space_dimension()),
00173     status() {
00174   // Check for emptyness for maximum precision.
00175   if (box.is_empty())
00176     set_empty();
00177   else if (box.space_dimension() > 0) {
00178     // A (non zero-dim) universe OS is strongly closed.
00179     set_strongly_closed();
00180     refine_with_constraints(box.constraints());
00181   }
00182 }

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

Builds an OS that approximates a grid.

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

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

Definition at line 186 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Grid::minimized_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), and Parma_Polyhedra_Library::Grid::space_dimension().

00188   : matrix(grid.space_dimension()),
00189     space_dim(grid.space_dimension()),
00190     status() {
00191   if (grid.space_dimension() > 0)
00192     // A (non zero-dim) universe OS is strongly closed.
00193     set_strongly_closed();
00194   // Taking minimized congruences ensures maximum precision.
00195   refine_with_congruences(grid.minimized_congruences());
00196 }

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

Builds an OS from a BD shape.

The OS inherits the space dimension of the BD shape. The built OS is the most precise OS that includes the BD shape.

Parameters:
bd The BD shape used to build the OS.
complexity This argument is ignored as the algorithm used has polynomial complexity.
Exceptions:
std::length_error Thrown if the space dimension of bd exceeds the maximum allowed space dimension.

Definition at line 201 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::constraints(), Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

00203   : matrix(bd.space_dimension()),
00204     space_dim(bd.space_dimension()),
00205     status() {
00206   // Check for emptyness for maximum precision.
00207   if (bd.is_empty())
00208     set_empty();
00209   else if (bd.space_dimension() > 0) {
00210     // A (non zero-dim) universe OS is strongly closed.
00211     set_strongly_closed();
00212     refine_with_constraints(bd.constraints());
00213   }
00214 }

template<typename T >
Parma_Polyhedra_Library::Octagonal_Shape< T >::~Octagonal_Shape (  )  [inline]

Destructor.

Definition at line 233 of file Octagonal_Shape.inlines.hh.

00233                                      {
00234 }


Member Function Documentation

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruence ( const Congruence cg  )  [inline]

Adds to *this a constraint equivalent to the congruence cg.

Parameters:
cg The congruence to be added.
Exceptions:
std::invalid_argument Thrown if *this and congruence cg are dimension-incompatible, or cg is not optimally supported by the OS domain.

Definition at line 454 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Congruence::is_proper_congruence(), Parma_Polyhedra_Library::Congruence::is_tautological(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Congruence::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruences().

00454                                                        {
00455   const dimension_type cg_space_dim = cg.space_dimension();
00456   // Dimension-compatibility check:
00457   // the dimension of `cg' can not be greater than space_dim.
00458   if (space_dimension() < cg_space_dim)
00459     throw_dimension_incompatible("add_congruence(cg)", cg);
00460 
00461   // Handle the case of proper congruences first.
00462   if (cg.is_proper_congruence()) {
00463     if (cg.is_tautological())
00464       return;
00465     if (cg.is_inconsistent()) {
00466       set_empty();
00467       return;
00468     }
00469     // Non-trivial and proper congruences are not allowed.
00470     throw_generic("add_congruence(cg)",
00471                   "cg is a non-trivial, proper congruence");
00472   }
00473 
00474   PPL_ASSERT(cg.is_equality());
00475   Constraint c(cg);
00476   add_constraint(c);
00477 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruences ( const Congruence_System cgs  )  [inline]

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

Parameters:
cgs The congruences to be added.
Exceptions:
std::invalid_argument Thrown if *this and cgs are dimension-incompatible, or cgs contains a congruence which is not optimally supported by the OS domain.

Definition at line 444 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruence(), Parma_Polyhedra_Library::Congruence_System::begin(), and Parma_Polyhedra_Library::Congruence_System::end().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_recycled_congruences(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape().

00444                                                                 {
00445   for (Congruence_System::const_iterator i = cgs.begin(),
00446          cgs_end = cgs.end(); i != cgs_end; ++i)
00447     add_congruence(*i);
00448 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint ( const Constraint c  )  [inline]

Adds a copy of constraint c to the system of constraints defining *this.

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

Definition at line 372 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Octagonal_Shape< T >::extract_octagonal_difference(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_inconsistent(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Constraint::is_tautological(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraints(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign().

00372                                                       {
00373   const dimension_type c_space_dim = c.space_dimension();
00374   // Dimension-compatibility check.
00375   if (c_space_dim > space_dim)
00376     throw_dimension_incompatible("add_constraint(c)", c);
00377 
00378   // Get rid of strict inequalities.
00379   if (c.is_strict_inequality()) {
00380     if (c.is_inconsistent()) {
00381       set_empty();
00382       return;
00383     }
00384     if (c.is_tautological())
00385       return;
00386     // Nontrivial strict inequalities are not allowed.
00387     throw_generic("add_constraint(c)", "strict inequalities are not allowed");
00388   }
00389 
00390   dimension_type num_vars = 0;
00391   dimension_type i = 0;
00392   dimension_type j = 0;
00393   PPL_DIRTY_TEMP_COEFFICIENT(coeff);
00394   PPL_DIRTY_TEMP_COEFFICIENT(term);
00395   // Constraints that are not octagonal differences are not allowed.
00396   if (!extract_octagonal_difference(c, c_space_dim, num_vars,
00397                                     i, j, coeff, term))
00398     throw_generic("add_constraint(c)",
00399                   "c is not an octagonal constraint");
00400 
00401   if (num_vars == 0) {
00402     // Dealing with a trivial constraint (not a strict inequality).
00403     if (c.inhomogeneous_term() < 0
00404         || (c.is_equality() && c.inhomogeneous_term() != 0))
00405       set_empty();
00406     return;
00407   }
00408 
00409   // Select the cell to be modified for the "<=" part of constraint.
00410   typename OR_Matrix<N>::row_iterator i_iter = matrix.row_begin() + i;
00411   typename OR_Matrix<N>::row_reference_type m_i = *i_iter;
00412   N& m_i_j = m_i[j];
00413   // Set `coeff' to the absolute value of itself.
00414   if (coeff < 0)
00415     neg_assign(coeff);
00416 
00417   bool is_oct_changed = false;
00418   // Compute the bound for `m_i_j', rounding towards plus infinity.
00419   PPL_DIRTY_TEMP(N, d);
00420   div_round_up(d, term, coeff);
00421   if (m_i_j > d) {
00422     m_i_j = d;
00423     is_oct_changed = true;
00424   }
00425 
00426   if (c.is_equality()) {
00427     // Select the cell to be modified for the ">=" part of constraint.
00428     if (i % 2 == 0)
00429       ++i_iter;
00430     else
00431       --i_iter;
00432 
00433     typename OR_Matrix<N>::row_reference_type m_ci = *i_iter;
00434     using namespace Implementation::Octagonal_Shapes;
00435     dimension_type cj = coherent_index(j);
00436     N& m_ci_cj = m_ci[cj];
00437     // Also compute the bound for `m_ci_cj', rounding towards plus infinity.
00438     neg_assign(term);
00439     div_round_up(d, term, coeff);
00440     if (m_ci_cj > d) {
00441       m_ci_cj = d;
00442       is_oct_changed = true;
00443     }
00444   }
00445 
00446   // This method does not preserve closure.
00447   if (is_oct_changed && marked_strongly_closed())
00448     reset_strongly_closed();
00449   PPL_ASSERT(OK());
00450 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraints ( const Constraint_System cs  )  [inline]

Adds the constraints in cs to the system of constraints defining *this.

Parameters:
cs The constraints that will be added.
Exceptions:
std::invalid_argument Thrown if *this and cs are dimension-incompatible, or cs contains a constraint which is not optimally supported by the OS domain.

Definition at line 424 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Constraint_System::begin(), and Parma_Polyhedra_Library::Constraint_System::end().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_recycled_constraints(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape().

00424                                                                {
00425   for (Constraint_System::const_iterator i = cs.begin(),
00426          i_end = cs.end(); i != i_end; ++i)
00427     add_constraint(*i);
00428 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint ( dimension_type  i,
dimension_type  j,
Coefficient_traits::const_reference  num,
Coefficient_traits::const_reference  den 
) [inline, private]

Adds the constraint matrix[i][j] <= num/den.

Definition at line 406 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::div_round_up(), and Parma_Polyhedra_Library::OR_Matrix< T >::row_size().

00409                                                                   {
00410 #ifndef NDEBUG
00411   // Private method: the caller has to ensure the following.
00412   PPL_ASSERT(i < 2*space_dim && j < 2*space_dim && i != j);
00413   typename OR_Matrix<N>::row_iterator m_i = matrix.row_begin() + i;
00414   PPL_ASSERT(j < m_i.row_size());
00415   PPL_ASSERT(den != 0);
00416 #endif
00417   PPL_DIRTY_TEMP(N, k);
00418   div_round_up(k, num, den);
00419   add_octagonal_constraint(i, j, k);
00420 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint ( dimension_type  i,
dimension_type  j,
const N k 
) [inline, private]

Adds the constraint matrix[i][j] <= k.

Definition at line 386 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_size(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim.

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::refine().

00388                                                          {
00389   // Private method: the caller has to ensure the following.
00390 #ifndef NDEBUG
00391   PPL_ASSERT(i < 2*space_dim && j < 2*space_dim && i != j);
00392   typename OR_Matrix<N>::row_iterator m_i = matrix.row_begin() + i;
00393   PPL_ASSERT(j < m_i.row_size());
00394 #endif
00395   N& r_i_j = matrix[i][j];
00396   if (r_i_j > k) {
00397     r_i_j = k;
00398     if (marked_strongly_closed())
00399       reset_strongly_closed();
00400   }
00401 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_recycled_congruences ( Congruence_System cgs  )  [inline]

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

Parameters:
cgs The congruence system to be added to *this. The congruences in cgs may be recycled.
Exceptions:
std::invalid_argument Thrown if *this and cgs are dimension-incompatible, or cgs contains a congruence which is not optimally supported by the OS domain.
Warning:
The only assumption that can be made on cgs upon successful or exceptional return is that it can be safely destroyed.

Definition at line 438 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruences().

00438                                                                    {
00439   add_congruences(cgs);
00440 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_recycled_constraints ( Constraint_System cs  )  [inline]

Adds the constraints in cs to the system of constraints of *this.

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

Definition at line 432 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraints().

00432                                                                   {
00433   add_constraints(cs);
00434 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed ( dimension_type  m  )  [inline]

Adds m new dimensions and embeds the old OS into the new space.

Parameters:
m The number of dimensions to add.

The new dimensions will be those having the highest indexes in the new OS, which is characterized by a system of constraints in which the variables running through the new dimensions are not constrained. For instance, when starting from the OS $\cO \sseq \Rset^2$ and adding a third dimension, the result will be the OS

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

Definition at line 2918 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::OR_Matrix< T >::grow(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim.

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image().

02918                                                                    {
02919   // Adding no dimensions is a no-op.
02920   if (m == 0)
02921     return;
02922 
02923   const dimension_type new_dim = space_dim + m;
02924   const bool was_zero_dim_univ = !marked_empty() && space_dim == 0;
02925 
02926   // To embed an n-dimension space octagon in a (n+m)-dimension space,
02927   // we just add `m' variables in the matrix of constraints.
02928   matrix.grow(new_dim);
02929   space_dim = new_dim;
02930   // If `*this' was the zero-dim space universe octagon,
02931   // then we can set the strongly closure flag.
02932   if (was_zero_dim_univ)
02933     set_strongly_closed();
02934 
02935   PPL_ASSERT(OK());
02936 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_project ( dimension_type  m  )  [inline]

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

Parameters:
m The number of dimensions to add.

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

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

Definition at line 2940 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), and Parma_Polyhedra_Library::OR_Matrix< T >::row_end().

02940                                                                      {
02941   // Adding no dimensions is a no-op.
02942   if (m == 0)
02943     return;
02944 
02945   const dimension_type n = matrix.num_rows();
02946 
02947   // To project an n-dimension space OS in a (space_dim+m)-dimension space,
02948   // we just add `m' columns and rows in the matrix of constraints.
02949   add_space_dimensions_and_embed(m);
02950   // We insert 0 where it needs.
02951   // Attention: now num_rows of matrix is update!
02952   for (typename OR_Matrix<N>::row_iterator i = matrix.row_begin() + n,
02953          matrix_row_end =  matrix.row_end(); i != matrix_row_end; i += 2) {
02954     typename OR_Matrix<N>::row_reference_type x_i = *i;
02955     typename OR_Matrix<N>::row_reference_type x_ci = *(i+1);
02956     const dimension_type ind = i.index();
02957     assign_r(x_i[ind+1], 0, ROUND_NOT_NEEDED);
02958     assign_r(x_ci[ind], 0, ROUND_NOT_NEEDED);
02959   }
02960 
02961   if (marked_strongly_closed())
02962     reset_strongly_closed();
02963   PPL_ASSERT(OK());
02964 }

template<typename T >
dimension_type Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_dimension (  )  const [inline]

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

Definition at line 551 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::is_discrete().

00551                                            {
00552   const dimension_type n_rows = matrix.num_rows();
00553   // A zero-space-dim shape always has affine dimension zero.
00554   if (n_rows == 0)
00555     return 0;
00556 
00557   // Strong closure is necessary to detect emptiness
00558   // and all (possibly implicit) equalities.
00559   strong_closure_assign();
00560   if (marked_empty())
00561     return 0;
00562 
00563   // The vector `leaders' is used to represent non-singular
00564   // equivalence classes:
00565   // `leaders[i] == i' if and only if `i' is the leader of its
00566   // equivalence class (i.e., the minimum index in the class);
00567   std::vector<dimension_type> leaders;
00568   compute_leaders(leaders);
00569 
00570   // Due to the splitting of variables, the affine dimension is the
00571   // number of non-singular positive zero-equivalence classes.
00572   dimension_type affine_dim = 0;
00573   for (dimension_type i = 0; i < n_rows; i += 2)
00574     // Note: disregard the singular equivalence class.
00575     if (leaders[i] == i && leaders[i+1] == i+1)
00576       ++affine_dim;
00577 
00578   return affine_dim;
00579 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image ( Variable  var,
const Linear_Expression expr,
Coefficient_traits::const_reference  denominator = Coefficient_one() 
) [inline]

Assigns to *this the affine image of *this under the function mapping variable var into 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.
Exceptions:
std::invalid_argument Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a dimension of *this.

Definition at line 4417 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_minus_v_pm_u_bounds(), Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_v_pm_u_bounds(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::swap(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image().

04420                                               {
04421   // The denominator cannot be zero.
04422   if (denominator == 0)
04423     throw_generic("affine_image(v, e, d)", "d == 0");
04424 
04425   // Dimension-compatibility checks.
04426   // The dimension of `expr' should not be greater than the dimension
04427   // of `*this'.
04428   const dimension_type expr_space_dim = expr.space_dimension();
04429   if (space_dim < expr_space_dim)
04430     throw_dimension_incompatible("affine_image(v, e, d)", "e", expr);
04431 
04432   // `var' should be one of the dimensions of the octagon.
04433   const dimension_type var_id = var.id();
04434   if (space_dim < var_id + 1)
04435     throw_dimension_incompatible("affine_image(v, e, d)", var_id + 1);
04436 
04437   strong_closure_assign();
04438   // The image of an empty octagon is empty too.
04439   if (marked_empty())
04440     return;
04441 
04442   // Number of non-zero coefficients in `expr': will be set to
04443   // 0, 1, or 2, the latter value meaning any value greater than 1.
04444   dimension_type t = 0;
04445   // Variable-index of the last non-zero coefficient in `expr', if any.
04446   dimension_type w_id = 0;
04447 
04448   // Get information about the number of non-zero coefficients in `expr'.
04449   // The `expr' must not be in two or plus variables.
04450   for (dimension_type i = expr_space_dim; i-- > 0; )
04451     if (expr.coefficient(Variable(i)) != 0) {
04452       if (t++ == 1)
04453         break;
04454       else
04455         w_id = i;
04456     }
04457 
04458   typedef typename OR_Matrix<N>::row_iterator Row_Iterator;
04459   typedef typename OR_Matrix<N>::row_reference_type Row_Reference;
04460   typedef typename OR_Matrix<N>::const_row_iterator Row_iterator;
04461   typedef typename OR_Matrix<N>::const_row_reference_type Row_reference;
04462 
04463   const dimension_type n_var = 2*var_id;
04464   const Coefficient& b = expr.inhomogeneous_term();
04465   PPL_DIRTY_TEMP_COEFFICIENT(minus_den);
04466   neg_assign_r(minus_den, denominator, ROUND_NOT_NEEDED);
04467 
04468   // `w' is the variable with index `w_id'.
04469   // Now we know the form of `expr':
04470   // - If t == 0, then expr == b, with `b' a constant;
04471   // - If t == 1, then expr == a*w + b, where `w' can be `v' or another
04472   //   variable; in this second case we have to check whether `a' is
04473   //   equal to `denominator' or `-denominator', since otherwise we have
04474   //   to fall back on the general form;
04475   // - If t == 2, the `expr' is of the general form.
04476 
04477   if (t == 0) {
04478     // Case 1: expr == b.
04479     // Remove all constraints on `var'.
04480     forget_all_octagonal_constraints(var_id);
04481     PPL_DIRTY_TEMP_COEFFICIENT(two_b);
04482     two_b = 2*b;
04483     // Add the constraint `var == b/denominator'.
04484     add_octagonal_constraint(n_var+1, n_var, two_b, denominator);
04485     add_octagonal_constraint(n_var, n_var+1, two_b, minus_den);
04486     PPL_ASSERT(OK());
04487     return;
04488   }
04489 
04490   if (t == 1) {
04491     // The one and only non-zero homogeneous coefficient in `expr'.
04492     const Coefficient& w_coeff = expr.coefficient(Variable(w_id));
04493     if (w_coeff == denominator || w_coeff == minus_den) {
04494       // Case 2: expr = w_coeff*w + b, with w_coeff = +/- denominator.
04495       if (w_id == var_id) {
04496         // Here `expr' is of the form: +/- denominator * v + b.
04497         const bool sign_symmetry = (w_coeff != denominator);
04498         if (!sign_symmetry && b == 0)
04499           // The transformation is the identity function.
04500           return;
04501         // Translate all the constraints on `var' adding or
04502         // subtracting the value `b/denominator'.
04503         PPL_DIRTY_TEMP(N, d);
04504         div_round_up(d, b, denominator);
04505         PPL_DIRTY_TEMP(N, minus_d);
04506         div_round_up(minus_d, b, minus_den);
04507         if (sign_symmetry)
04508           std::swap(d, minus_d);
04509         const Row_Iterator m_begin = matrix.row_begin();
04510         const Row_Iterator m_end = matrix.row_end();
04511         Row_Iterator m_iter = m_begin + n_var;
04512         Row_Reference m_v = *m_iter;
04513         ++m_iter;
04514         Row_Reference m_cv = *m_iter;
04515         ++m_iter;
04516         // NOTE: delay update of unary constraints on `var'.
04517         for (dimension_type j = n_var; j-- > 0; ) {
04518           N& m_v_j = m_v[j];
04519           add_assign_r(m_v_j, m_v_j, minus_d, ROUND_UP);
04520           N& m_cv_j = m_cv[j];
04521           add_assign_r(m_cv_j, m_cv_j, d, ROUND_UP);
04522           if (sign_symmetry)
04523             std::swap(m_v_j, m_cv_j);
04524         }
04525         for ( ; m_iter != m_end; ++m_iter) {
04526           Row_Reference m_i = *m_iter;
04527           N& m_i_v = m_i[n_var];
04528           add_assign_r(m_i_v, m_i_v, d, ROUND_UP);
04529           N& m_i_cv = m_i[n_var+1];
04530           add_assign_r(m_i_cv, m_i_cv, minus_d, ROUND_UP);
04531           if (sign_symmetry)
04532             std::swap(m_i_v, m_i_cv);
04533         }
04534         // Now update unary constraints on var.
04535         mul_2exp_assign_r(d, d, 1, ROUND_UP);
04536         N& m_cv_v = m_cv[n_var];
04537         add_assign_r(m_cv_v, m_cv_v, d, ROUND_UP);
04538         mul_2exp_assign_r(minus_d, minus_d, 1, ROUND_UP);
04539         N& m_v_cv = m_v[n_var+1];
04540         add_assign_r(m_v_cv, m_v_cv, minus_d, ROUND_UP);
04541         if (sign_symmetry)
04542           std::swap(m_cv_v, m_v_cv);
04543         // Note: strong closure is preserved.
04544       }
04545       else {
04546         // Here `w != var', so that `expr' is of the form
04547         // +/-denominator * w + b.
04548         // Remove all constraints on `var'.
04549         forget_all_octagonal_constraints(var_id);
04550         const dimension_type n_w = 2*w_id;
04551         // Add the new constraint `var - w = b/denominator'.
04552         if (w_coeff == denominator) {
04553           if (var_id < w_id) {
04554             add_octagonal_constraint(n_w, n_var, b, denominator);
04555             add_octagonal_constraint(n_w+1, n_var+1, b, minus_den);
04556           }
04557           else {
04558             add_octagonal_constraint(n_var+1, n_w+1, b, denominator);
04559             add_octagonal_constraint(n_var, n_w, b, minus_den);
04560           }
04561         }
04562         else {
04563           // Add the new constraint `var + w = b/denominator'.
04564           if (var_id < w_id) {
04565             add_octagonal_constraint(n_w+1, n_var, b, denominator);
04566             add_octagonal_constraint(n_w, n_var+1, b, minus_den);
04567           }
04568           else {
04569             add_octagonal_constraint(n_var+1, n_w, b, denominator);
04570             add_octagonal_constraint(n_var, n_w+1, b, minus_den);
04571           }
04572         }
04573         incremental_strong_closure_assign(var);
04574       }
04575       PPL_ASSERT(OK());
04576       return;
04577     }
04578   }
04579 
04580   // General case.
04581   // Either t == 2, so that
04582   // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
04583   // or t == 1, expr == a*w + b, but a <> +/- denominator.
04584   // We will remove all the constraints on `var' and add back
04585   // constraints providing upper and lower bounds for `var'.
04586 
04587   // Compute upper approximations for `expr' and `-expr'
04588   // into `pos_sum' and `neg_sum', respectively, taking into account
04589   // the sign of `denominator'.
04590   // Note: approximating `-expr' from above and then negating the
04591   // result is the same as approximating `expr' from below.
04592   const bool is_sc = (denominator > 0);
04593   PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
04594   neg_assign_r(minus_b, b, ROUND_NOT_NEEDED);
04595 
04596   const Coefficient& sc_b = is_sc ? b : minus_b;
04597   const Coefficient& minus_sc_b = is_sc ? minus_b : b;
04598   const Coefficient& sc_den = is_sc ? denominator : minus_den;
04599   const Coefficient& minus_sc_den = is_sc ? minus_den : denominator;
04600   // NOTE: here, for optimization purposes, `minus_expr' is only assigned
04601   // when `denominator' is negative. Do not use it unless you are sure
04602   // it has been correctly assigned.
04603   Linear_Expression minus_expr;
04604   if (!is_sc)
04605     minus_expr = -expr;
04606   const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
04607 
04608   PPL_DIRTY_TEMP(N, pos_sum);
04609   PPL_DIRTY_TEMP(N, neg_sum);
04610   // Indices of the variables that are unbounded in `this->matrix'.
04611   PPL_UNINITIALIZED(dimension_type, pos_pinf_index);
04612   PPL_UNINITIALIZED(dimension_type, neg_pinf_index);
04613   // Number of unbounded variables found.
04614   dimension_type pos_pinf_count = 0;
04615   dimension_type neg_pinf_count = 0;
04616 
04617   // Approximate the inhomogeneous term.
04618   assign_r(pos_sum, sc_b, ROUND_UP);
04619   assign_r(neg_sum, minus_sc_b, ROUND_UP);
04620 
04621   // Approximate the homogeneous part of `sc_expr'.
04622   PPL_DIRTY_TEMP(N, coeff_i);
04623   PPL_DIRTY_TEMP(N, minus_coeff_i);
04624   PPL_DIRTY_TEMP(N, half);
04625   PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
04626   // Note: indices above `w' can be disregarded, as they all have
04627   // a zero coefficient in `sc_expr'.
04628   const Row_Iterator m_begin = matrix.row_begin();
04629   for (Row_iterator m_iter = m_begin,
04630          m_iter_end = m_iter + (2*w_id) + 2; m_iter != m_iter_end; ) {
04631     const dimension_type n_i = m_iter.index();
04632     const dimension_type id = n_i/2;
04633     Row_reference m_i = *m_iter;
04634     ++m_iter;
04635     Row_reference m_ci = *m_iter;
04636     ++m_iter;
04637     const Coefficient& sc_i = sc_expr.coefficient(Variable(id));
04638     const int sign_i = sgn(sc_i);
04639     if (sign_i > 0) {
04640       assign_r(coeff_i, sc_i, ROUND_UP);
04641       // Approximating `sc_expr'.
04642       if (pos_pinf_count <= 1) {
04643         const N& double_up_approx_i = m_ci[n_i];
04644         if (!is_plus_infinity(double_up_approx_i)) {
04645           // Let half = double_up_approx_i / 2.
04646           div_2exp_assign_r(half, double_up_approx_i, 1, ROUND_UP);
04647           add_mul_assign_r(pos_sum, coeff_i, half, ROUND_UP);
04648         }
04649         else {
04650           ++pos_pinf_count;
04651           pos_pinf_index = id;
04652         }
04653       }
04654       // Approximating `-sc_expr'.
04655       if (neg_pinf_count <= 1) {
04656         const N& double_up_approx_minus_i = m_i[n_i+1];
04657         if (!is_plus_infinity(double_up_approx_minus_i)) {
04658           // Let half = double_up_approx_minus_i / 2.
04659           div_2exp_assign_r(half, double_up_approx_minus_i, 1, ROUND_UP);
04660           add_mul_assign_r(neg_sum, coeff_i, half, ROUND_UP);
04661         }
04662         else {
04663           ++neg_pinf_count;
04664           neg_pinf_index = id;
04665         }
04666       }
04667     }
04668     else if (sign_i < 0) {
04669       neg_assign_r(minus_sc_i, sc_i, ROUND_NOT_NEEDED);
04670       assign_r(minus_coeff_i, minus_sc_i, ROUND_UP);
04671       // Approximating `sc_expr'.
04672       if (pos_pinf_count <= 1) {
04673         const N& double_up_approx_minus_i = m_i[n_i+1];
04674         if (!is_plus_infinity(double_up_approx_minus_i)) {
04675           // Let half = double_up_approx_minus_i / 2.
04676           div_2exp_assign_r(half, double_up_approx_minus_i, 1, ROUND_UP);
04677           add_mul_assign_r(pos_sum, minus_coeff_i, half, ROUND_UP);
04678         }
04679         else {
04680           ++pos_pinf_count;
04681           pos_pinf_index = id;
04682         }
04683       }
04684       // Approximating `-sc_expr'.
04685       if (neg_pinf_count <= 1) {
04686         const N& double_up_approx_i = m_ci[n_i];
04687         if (!is_plus_infinity(double_up_approx_i)) {
04688           // Let half = double_up_approx_i / 2.
04689           div_2exp_assign_r(half, double_up_approx_i, 1, ROUND_UP);
04690           add_mul_assign_r(neg_sum, minus_coeff_i, half, ROUND_UP);
04691         }
04692         else {
04693           ++neg_pinf_count;
04694           neg_pinf_index = id;
04695         }
04696       }
04697     }
04698   }
04699 
04700   // Remove all constraints on `var'.
04701   forget_all_octagonal_constraints(var_id);
04702   // Return immediately if no approximation could be computed.
04703   if (pos_pinf_count > 1 && neg_pinf_count > 1) {
04704     PPL_ASSERT(OK());
04705     return;
04706   }
04707 
04708   // In the following, strong closure will be definitely lost.
04709   reset_strongly_closed();
04710 
04711   // Exploit the upper approximation, if possible.
04712   if (pos_pinf_count <= 1) {
04713     // Compute quotient (if needed).
04714     if (sc_den != 1) {
04715       // Before computing quotients, the denominator should be approximated
04716       // towards zero. Since `sc_den' is known to be positive, this amounts to
04717       // rounding downwards, which is achieved as usual by rounding upwards
04718       // `minus_sc_den' and negating again the result.
04719       PPL_DIRTY_TEMP(N, down_sc_den);
04720       assign_r(down_sc_den, minus_sc_den, ROUND_UP);
04721       neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
04722       div_assign_r(pos_sum, pos_sum, down_sc_den, ROUND_UP);
04723     }
04724     // Add the upper bound constraint, if meaningful.
04725     if (pos_pinf_count == 0) {
04726       // Add the constraint `v <= pos_sum'.
04727       PPL_DIRTY_TEMP(N, double_pos_sum);
04728       mul_2exp_assign_r(double_pos_sum, pos_sum, 1, ROUND_UP);
04729       matrix[n_var+1][n_var] = double_pos_sum;
04730       // Deduce constraints of the form `v +/- u', where `u != v'.
04731       deduce_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, pos_sum);
04732     }
04733     else
04734       // Here `pos_pinf_count == 1'.
04735       if (pos_pinf_index != var_id) {
04736         const Coefficient& ppi = sc_expr.coefficient(Variable(pos_pinf_index));
04737         if (ppi == sc_den)
04738           // Add the constraint `v - pos_pinf_index <= pos_sum'.
04739           if (var_id < pos_pinf_index)
04740             matrix[2*pos_pinf_index][n_var] = pos_sum;
04741           else
04742             matrix[n_var+1][2*pos_pinf_index+1] = pos_sum;
04743         else
04744           if (ppi == minus_sc_den) {
04745             // Add the constraint `v + pos_pinf_index <= pos_sum'.
04746             if (var_id < pos_pinf_index)
04747               matrix[2*pos_pinf_index+1][n_var] = pos_sum;
04748             else
04749               matrix[n_var+1][2*pos_pinf_index] = pos_sum;
04750           }
04751       }
04752   }
04753 
04754   // Exploit the lower approximation, if possible.
04755   if (neg_pinf_count <= 1) {
04756     // Compute quotient (if needed).
04757     if (sc_den != 1) {
04758       // Before computing quotients, the denominator should be approximated
04759       // towards zero. Since `sc_den' is known to be positive, this amounts to
04760       // rounding downwards, which is achieved as usual by rounding upwards
04761       // `minus_sc_den' and negating again the result.
04762       PPL_DIRTY_TEMP(N, down_sc_den);
04763       assign_r(down_sc_den, minus_sc_den, ROUND_UP);
04764       neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
04765       div_assign_r(neg_sum, neg_sum, down_sc_den, ROUND_UP);
04766     }
04767     // Add the lower bound constraint, if meaningful.
04768     if (neg_pinf_count == 0) {
04769       // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
04770       PPL_DIRTY_TEMP(N, double_neg_sum);
04771       mul_2exp_assign_r(double_neg_sum, neg_sum, 1, ROUND_UP);
04772       matrix[n_var][n_var+1] = double_neg_sum;
04773       // Deduce constraints of the form `-v +/- u', where `u != v'.
04774       deduce_minus_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, neg_sum);
04775     }
04776     else
04777       // Here `neg_pinf_count == 1'.
04778       if (neg_pinf_index != var_id) {
04779         const Coefficient& npi = sc_expr.coefficient(Variable(neg_pinf_index));
04780         if (npi == sc_den)
04781           // Add the constraint `v - neg_pinf_index >= -neg_sum',
04782           // i.e., `neg_pinf_index - v <= neg_sum'.
04783           if (neg_pinf_index < var_id)
04784             matrix[n_var][2*neg_pinf_index] = neg_sum;
04785           else
04786             matrix[2*neg_pinf_index+1][n_var+1] = neg_sum;
04787         else
04788           if (npi == minus_sc_den) {
04789             // Add the constraint `v + neg_pinf_index >= -neg_sum',
04790             // i.e., `-neg_pinf_index - v <= neg_sum'.
04791             if (neg_pinf_index < var_id)
04792               matrix[n_var][2*neg_pinf_index+1] = neg_sum;
04793             else
04794               matrix[2*neg_pinf_index][n_var+1] = neg_sum;
04795           }
04796       }
04797   }
04798 
04799   incremental_strong_closure_assign(var);
04800   PPL_ASSERT(OK());
04801 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage ( Variable  var,
const Linear_Expression expr,
Coefficient_traits::const_reference  denominator = Coefficient_one() 
) [inline]

Assigns to *this the affine preimage of *this under the function mapping variable var into 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.
Exceptions:
std::invalid_argument Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a dimension of *this.

Definition at line 4805 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().

04808                                                  {
04809 
04810   // The denominator cannot be zero.
04811   if (denominator == 0)
04812     throw_generic("affine_preimage(v, e, d)", "d == 0");
04813 
04814   // Dimension-compatibility checks.
04815   // The dimension of `expr' should not be greater than the dimension
04816   // of `*this'.
04817   const dimension_type expr_space_dim = expr.space_dimension();
04818   if (space_dim < expr_space_dim)
04819     throw_dimension_incompatible("affine_preimage(v, e, d)", "e", expr);
04820 
04821   // `var' should be one of the dimensions of the octagon.
04822   dimension_type var_id = var.id();
04823   if (space_dim < var_id + 1)
04824     throw_dimension_incompatible("affine_preimage(v, e, d)", var_id + 1);
04825 
04826   strong_closure_assign();
04827   // The image of an empty octagon is empty too.
04828   if (marked_empty())
04829     return;
04830 
04831   const Coefficient& b = expr.inhomogeneous_term();
04832 
04833   // Number of non-zero coefficients in `expr': will be set to
04834   // 0, 1, or 2, the latter value meaning any value greater than 1.
04835   dimension_type t = 0;
04836 
04837   // Variable-index of the last non-zero coefficient in `expr', if any.
04838   dimension_type w_id = 0;
04839 
04840   // Get information about the number of the non-zero coefficients of `expr'.
04841   for (dimension_type i = expr_space_dim; i-- > 0; )
04842     if (expr.coefficient(Variable(i)) != 0) {
04843       if (t++ == 1)
04844         break;
04845       else
04846         w_id = i;
04847     }
04848 
04849   // `w' is the variable with index `w_id'.
04850   // Now we know the form of `expr':
04851   // - If t == 0, then expr == b, with `b' a constant;
04852   // - If t == 1, then expr == a*w + b, where `w' can be `v' or another
04853   //   variable; in this second case we have to check whether `a' is
04854   //   equal to `denominator' or `-denominator', since otherwise we have
04855   //   to fall back on the general form;
04856   // - If t == 2, the `expr' is of the general form.
04857 
04858   if (t == 0) {
04859     // Case 1: expr = n; remove all constraints on `var'.
04860     forget_all_octagonal_constraints(var_id);
04861     PPL_ASSERT(OK());
04862     return;
04863   }
04864 
04865   if (t == 1) {
04866     // Value of the one and only non-zero coefficient in `expr'.
04867     const Coefficient& w_coeff = expr.coefficient(Variable(w_id));
04868     if (w_coeff == denominator || w_coeff == -denominator) {
04869       // Case 2: expr = w_coeff*w + b, with w_coeff = +/- denominator.
04870       if (w_id == var_id) {
04871         // Apply affine_image() on the inverse of this transformation.
04872         affine_image(var, denominator*var - b, w_coeff);
04873       }
04874       else {
04875         // `expr == w_coeff*w + b', where `w != var'.
04876         // Remove all constraints on `var'.
04877         forget_all_octagonal_constraints(var_id);
04878         PPL_ASSERT(OK());
04879       }
04880       return;
04881     }
04882   }
04883   // General case.
04884   // Either t == 2, so that
04885   // expr = a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
04886   // or t = 1, expr = a*w + b, but a <> +/- denominator.
04887   const Coefficient& coeff_v = expr.coefficient(var);
04888   if (coeff_v != 0) {
04889     if (coeff_v > 0) {
04890       // The transformation is invertible.
04891       Linear_Expression inverse = ((coeff_v + denominator)*var);
04892       inverse -= expr;
04893       affine_image(var, inverse, coeff_v);
04894     }
04895     else {
04896       // The transformation is invertible.
04897       PPL_DIRTY_TEMP_COEFFICIENT(minus_coeff_v);
04898       neg_assign(minus_coeff_v, coeff_v);
04899       Linear_Expression inverse = ((minus_coeff_v - denominator)*var);
04900       inverse += expr;
04901       affine_image(var, inverse, minus_coeff_v);
04902     }
04903   }
04904   else {
04905     // The transformation is not invertible: all constraints on `var' are lost.
04906     forget_all_octagonal_constraints(var_id);
04907     PPL_ASSERT(OK());
04908   }
04909 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::ascii_dump ( std::ostream &  s  )  const [inline]
template<typename T>
void Parma_Polyhedra_Library::Octagonal_Shape< T >::ascii_dump (  )  const

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

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::ascii_load ( std::istream &  s  )  [inline]

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

Definition at line 7066 of file Octagonal_Shape.templates.hh.

07066                                             {
07067   std::string str;
07068 
07069   if (!(s >> str) || str != "space_dim")
07070     return false;
07071 
07072   if (!(s >> space_dim))
07073     return false;
07074 
07075   if (!status.ascii_load(s))
07076     return false;
07077 
07078   if (!matrix.ascii_load(s))
07079     return false;
07080 
07081   PPL_ASSERT(OK());
07082   return true;
07083 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign ( const Octagonal_Shape< T > &  y,
unsigned *  tp = 0 
) [inline]

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

Parameters:
y An OS 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 3373 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::element_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::widening_assign().

03374                                                          {
03375   // Dimension-compatibility check.
03376   if (space_dim != y.space_dim)
03377     throw_dimension_incompatible("BHMZ05_widening_assign(y)", y);
03378 
03379 #ifndef NDEBUG
03380   {
03381     // We assume that `y' is contained in or equal to `*this'.
03382     const Octagonal_Shape x_copy = *this;
03383     const Octagonal_Shape y_copy = y;
03384     PPL_ASSERT(x_copy.contains(y_copy));
03385   }
03386 #endif
03387 
03388   // Compute the affine dimension of `y'.
03389   const dimension_type y_affine_dim = y.affine_dimension();
03390   // If the affine dimension of `y' is zero, then either `y' is
03391   // zero-dimensional, or it is empty, or it is a singleton.
03392   // In all cases, due to the inclusion hypothesis, the result is `*this'.
03393   if (y_affine_dim == 0)
03394     return;
03395 
03396   // If the affine dimension has changed, due to the inclusion hypothesis,
03397   // the result is `*this'.
03398   const dimension_type x_affine_dim = affine_dimension();
03399   PPL_ASSERT(x_affine_dim >= y_affine_dim);
03400   if (x_affine_dim != y_affine_dim)
03401     return;
03402 
03403   // If there are tokens available, work on a temporary copy.
03404   if (tp != 0 && *tp > 0) {
03405     Octagonal_Shape x_tmp(*this);
03406     x_tmp.BHMZ05_widening_assign(y, 0);
03407     // If the widening was not precise, use one of the available tokens.
03408     if (!contains(x_tmp))
03409       --(*tp);
03410     return;
03411   }
03412 
03413   // Here no token is available.
03414   PPL_ASSERT(marked_strongly_closed() && y.marked_strongly_closed());
03415   // Minimize `y'.
03416   y.strong_reduction_assign();
03417 
03418   // Extrapolate unstable bounds.
03419   typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin();
03420   for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(),
03421        matrix_element_end = matrix.element_end();
03422        i != matrix_element_end;
03423        ++i, ++j) {
03424     N& elem = *i;
03425       // Note: in the following line the use of `!=' (as opposed to
03426       // the use of `<' that would seem -but is not- equivalent) is
03427       // intentional.
03428     if (*j != elem)
03429       assign_r(elem, PLUS_INFINITY, ROUND_NOT_NEEDED);
03430   }
03431   reset_strongly_closed();
03432   PPL_ASSERT(OK());
03433 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image ( Variable  var,
const Linear_Expression lb_expr,
const Linear_Expression ub_expr,
Coefficient_traits::const_reference  denominator = Coefficient_one() 
) [inline]

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

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

Definition at line 5591 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_minus_v_pm_u_bounds(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().

05595                                                       {
05596   // The denominator cannot be zero.
05597   if (denominator == 0)
05598     throw_generic("bounded_affine_image(v, lb, ub, d)", "d == 0");
05599 
05600   // `var' should be one of the dimensions of the octagon.
05601   const dimension_type var_id = var.id();
05602   if (space_dim < var_id + 1)
05603     throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
05604                                  var_id + 1);
05605 
05606   // The dimension of `lb_expr' and `ub_expr' should not be
05607   // greater than the dimension of `*this'.
05608   const dimension_type lb_space_dim = lb_expr.space_dimension();
05609   if (space_dim < lb_space_dim)
05610     throw_dimension_incompatible("bounded_affine_image(v, lb, ub)",
05611                                  "lb", lb_expr);
05612   const dimension_type ub_space_dim = ub_expr.space_dimension();
05613   if (space_dim < ub_space_dim)
05614     throw_dimension_incompatible("bounded_affine_image(v, lb, ub)",
05615                                  "ub", ub_expr);
05616 
05617   strong_closure_assign();
05618   // The image of an empty octagon is empty too.
05619   if (marked_empty())
05620     return;
05621 
05622   // Number of non-zero coefficients in `lb_expr': will be set to
05623   // 0, 1, or 2, the latter value meaning any value greater than 1.
05624   dimension_type t = 0;
05625   // Variable-index of the last non-zero coefficient in `lb_expr', if any.
05626   dimension_type w_id = 0;
05627 
05628   // Get information about the number of non-zero coefficients in `lb_expr'.
05629   // The `expr' must not be in two or plus variables.
05630   for (dimension_type i = lb_space_dim; i-- > 0; )
05631     if (lb_expr.coefficient(Variable(i)) != 0) {
05632       if (t++ == 1)
05633         break;
05634       else
05635         w_id = i;
05636     }
05637 
05638   typedef typename OR_Matrix<N>::row_iterator Row_Iterator;
05639   typedef typename OR_Matrix<N>::row_reference_type Row_Reference;
05640   typedef typename OR_Matrix<N>::const_row_iterator Row_iterator;
05641   typedef typename OR_Matrix<N>::const_row_reference_type Row_reference;
05642 
05643   const Row_Iterator m_begin = matrix.row_begin();
05644   const dimension_type n_var = 2*var_id;
05645   const Coefficient& b = lb_expr.inhomogeneous_term();
05646   PPL_DIRTY_TEMP_COEFFICIENT(minus_den);
05647   neg_assign_r(minus_den, denominator, ROUND_NOT_NEEDED);
05648 
05649   // `w' is the variable with index `w_id'.
05650   // Now we know the form of `lb_expr':
05651   // - If t == 0, then lb_expr == b, with `b' a constant;
05652   // - If t == 1, then lb_expr == a*w + b, where `w' can be `v' or another
05653   //   variable; in this second case we have to check whether `a' is
05654   //   equal to `denominator' or `-denominator', since otherwise we have
05655   //   to fall back on the general form;
05656   // - If t == 2, the `lb_expr' is of the general form.
05657 
05658   if (t == 0) {
05659     // Case 1: lb_expr == b.
05660     generalized_affine_image(var,
05661                              LESS_OR_EQUAL,
05662                              ub_expr,
05663                              denominator);
05664     PPL_DIRTY_TEMP_COEFFICIENT(two_b);
05665     two_b = 2*b;
05666     // Add the constraint `var >= b/denominator'.
05667     add_octagonal_constraint(n_var, n_var+1, two_b, minus_den);
05668     PPL_ASSERT(OK());
05669     return;
05670   }
05671 
05672   if (t == 1) {
05673     // The one and only non-zero homogeneous coefficient in `lb_expr'.
05674     const Coefficient& w_coeff = lb_expr.coefficient(Variable(w_id));
05675     if (w_coeff == denominator || w_coeff == minus_den) {
05676       // Case 2: lb_expr = w_coeff*w + b, with w_coeff = +/- denominator.
05677      if (w_id == var_id) {
05678         // Here `var' occurs in `lb_expr'.
05679         // To ease the computation, we add an additional dimension.
05680         const Variable new_var = Variable(space_dim);
05681         add_space_dimensions_and_embed(1);
05682         // Constrain the new dimension to be equal to `lb_expr'.
05683         // Here `lb_expr' is of the form: +/- denominator * v + b.
05684         affine_image(new_var, lb_expr, denominator);
05685         // Enforce the strong closure for precision.
05686         strong_closure_assign();
05687         PPL_ASSERT(!marked_empty());
05688         // Apply the affine upper bound.
05689         generalized_affine_image(var,
05690                                  LESS_OR_EQUAL,
05691                                  ub_expr,
05692                                  denominator);
05693         // Now apply the affine lower bound, as recorded in `new_var'
05694         refine_no_check(var >= new_var);
05695         // Remove the temporarily added dimension.
05696         remove_higher_space_dimensions(space_dim-1);
05697         return;
05698       }
05699       else {
05700         // Apply the affine upper bound.
05701         generalized_affine_image(var,
05702                                  LESS_OR_EQUAL,
05703                                  ub_expr,
05704                                  denominator);
05705         // Here `w != var', so that `lb_expr' is of the form
05706         // +/-denominator * w + b.
05707         const dimension_type n_w = 2*w_id;
05708         // Add the new constraint `var - w >= b/denominator'.
05709         if (w_coeff == denominator)
05710           if (var_id < w_id)
05711             add_octagonal_constraint(n_w+1, n_var+1, b, minus_den);
05712           else
05713             add_octagonal_constraint(n_var, n_w, b, minus_den);
05714         else {
05715           // Add the new constraint `var + w >= b/denominator'.
05716           if (var_id < w_id)
05717             add_octagonal_constraint(n_w, n_var+1, b, minus_den);
05718           else
05719             add_octagonal_constraint(n_var, n_w+1, b, minus_den);
05720         }
05721         PPL_ASSERT(OK());
05722         return;
05723       }
05724     }
05725   }
05726 
05727   // General case.
05728   // Either t == 2, so that
05729   // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
05730   // or t == 1, expr == a*w + b, but a <> +/- denominator.
05731   // We will remove all the constraints on `var' and add back
05732   // constraints providing upper and lower bounds for `var'.
05733 
05734   // Compute upper approximations for `expr' and `-expr'
05735   // into `pos_sum' and `neg_sum', respectively, taking into account
05736   // the sign of `denominator'.
05737   // Note: approximating `-expr' from above and then negating the
05738   // result is the same as approximating `expr' from below.
05739   const bool is_sc = (denominator > 0);
05740   PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
05741   neg_assign_r(minus_b, b, ROUND_NOT_NEEDED);
05742 
05743   const Coefficient& minus_sc_b = is_sc ? minus_b : b;
05744   const Coefficient& sc_den = is_sc ? denominator : minus_den;
05745   const Coefficient& minus_sc_den = is_sc ? minus_den : denominator;
05746   // NOTE: here, for optimization purposes, `minus_expr' is only assigned
05747   // when `denominator' is negative. Do not use it unless you are sure
05748   // it has been correctly assigned.
05749   Linear_Expression minus_expr;
05750   if (!is_sc)
05751     minus_expr = -lb_expr;
05752   const Linear_Expression& sc_expr = is_sc ? lb_expr : minus_expr;
05753 
05754   PPL_DIRTY_TEMP(N, neg_sum);
05755   // Indices of the variables that are unbounded in `this->matrix'.
05756   PPL_UNINITIALIZED(dimension_type, neg_pinf_index);
05757   // Number of unbounded variables found.
05758   dimension_type neg_pinf_count = 0;
05759 
05760   // Approximate the inhomogeneous term.
05761   assign_r(neg_sum, minus_sc_b, ROUND_UP);
05762 
05763   // Approximate the homogeneous part of `sc_expr'.
05764   PPL_DIRTY_TEMP(N, coeff_i);
05765   PPL_DIRTY_TEMP(N, minus_coeff_i);
05766   PPL_DIRTY_TEMP(N, half);
05767   PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
05768   // Note: indices above `w' can be disregarded, as they all have
05769   // a zero coefficient in `sc_expr'.
05770   for (Row_iterator m_iter = m_begin, m_iter_end = m_iter + (2*w_id) + 2;
05771        m_iter != m_iter_end; ) {
05772     const dimension_type n_i = m_iter.index();
05773     const dimension_type id = n_i/2;
05774     Row_reference m_i = *m_iter;
05775     ++m_iter;
05776     Row_reference m_ci = *m_iter;
05777     ++m_iter;
05778     const Coefficient& sc_i = sc_expr.coefficient(Variable(id));
05779     const int sign_i = sgn(sc_i);
05780     if (sign_i > 0) {
05781       assign_r(coeff_i, sc_i, ROUND_UP);
05782       // Approximating `-sc_expr'.
05783       if (neg_pinf_count <= 1) {
05784         const N& double_up_approx_minus_i = m_i[n_i+1];
05785         if (!is_plus_infinity(double_up_approx_minus_i)) {
05786           // Let half = double_up_approx_minus_i / 2.
05787           div_2exp_assign_r(half, double_up_approx_minus_i, 1, ROUND_UP);
05788           add_mul_assign_r(neg_sum, coeff_i, half, ROUND_UP);
05789         }
05790         else {
05791           ++neg_pinf_count;
05792           neg_pinf_index = id;
05793         }
05794       }
05795     }
05796     else if (sign_i < 0) {
05797       neg_assign_r(minus_sc_i, sc_i, ROUND_NOT_NEEDED);
05798       assign_r(minus_coeff_i, minus_sc_i, ROUND_UP);
05799       // Approximating `-sc_expr'.
05800       if (neg_pinf_count <= 1) {
05801         const N& double_up_approx_i = m_ci[n_i];
05802         if (!is_plus_infinity(double_up_approx_i)) {
05803           // Let half = double_up_approx_i / 2.
05804           div_2exp_assign_r(half, double_up_approx_i, 1, ROUND_UP);
05805           add_mul_assign_r(neg_sum, minus_coeff_i, half, ROUND_UP);
05806         }
05807         else {
05808           ++neg_pinf_count;
05809           neg_pinf_index = id;
05810         }
05811       }
05812     }
05813   }
05814 
05815   // Apply the affine upper bound.
05816   generalized_affine_image(var,
05817                            LESS_OR_EQUAL,
05818                            ub_expr,
05819                            denominator);
05820 
05821   // Return immediately if no approximation could be computed.
05822   if (neg_pinf_count > 1) {
05823     return;
05824   }
05825 
05826   // In the following, strong closure will be definitely lost.
05827   reset_strongly_closed();
05828 
05829   // Exploit the lower approximation, if possible.
05830   if (neg_pinf_count <= 1) {
05831     // Compute quotient (if needed).
05832     if (sc_den != 1) {
05833       // Before computing quotients, the denominator should be approximated
05834       // towards zero. Since `sc_den' is known to be positive, this amounts to
05835       // rounding downwards, which is achieved as usual by rounding upwards
05836       // `minus_sc_den' and negating again the result.
05837       PPL_DIRTY_TEMP(N, down_sc_den);
05838       assign_r(down_sc_den, minus_sc_den, ROUND_UP);
05839       neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
05840       div_assign_r(neg_sum, neg_sum, down_sc_den, ROUND_UP);
05841     }
05842     // Add the lower bound constraint, if meaningful.
05843     if (neg_pinf_count == 0) {
05844       // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
05845       PPL_DIRTY_TEMP(N, double_neg_sum);
05846       mul_2exp_assign_r(double_neg_sum, neg_sum, 1, ROUND_UP);
05847       matrix[n_var][n_var+1] = double_neg_sum;
05848       // Deduce constraints of the form `-v +/- u', where `u != v'.
05849       deduce_minus_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, neg_sum);
05850     }
05851     else
05852       // Here `neg_pinf_count == 1'.
05853       if (neg_pinf_index != var_id) {
05854         const Coefficient& npi = sc_expr.coefficient(Variable(neg_pinf_index));
05855         if (npi == sc_den)
05856           // Add the constraint `v - neg_pinf_index >= -neg_sum',
05857           // i.e., `neg_pinf_index - v <= neg_sum'.
05858           if (neg_pinf_index < var_id)
05859             matrix[n_var][2*neg_pinf_index] = neg_sum;
05860           else
05861             matrix[2*neg_pinf_index+1][n_var+1] = neg_sum;
05862         else
05863           if (npi == minus_sc_den) {
05864             // Add the constraint `v + neg_pinf_index >= -neg_sum',
05865             // i.e., `-neg_pinf_index - v <= neg_sum'.
05866             if (neg_pinf_index < var_id)
05867               matrix[n_var][2*neg_pinf_index+1] = neg_sum;
05868             else
05869               matrix[2*neg_pinf_index][n_var+1] = neg_sum;
05870           }
05871       }
05872   }
05873 
05874   PPL_ASSERT(OK());
05875 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage ( Variable  var,
const Linear_Expression lb_expr,
const Linear_Expression ub_expr,
Coefficient_traits::const_reference  denominator = Coefficient_one() 
) [inline]

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

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

Definition at line 6121 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::neg_assign(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Octagonal_Shape< T >::refine(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().

06125                                                          {
06126   // The denominator cannot be zero.
06127   if (denominator == 0)
06128     throw_generic("bounded_affine_preimage(v, lb, ub, d)", "d == 0");
06129 
06130   // `var' should be one of the dimensions of the octagon.
06131   const dimension_type var_id = var.id();
06132   if (space_dim < var_id + 1)
06133     throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
06134                                  var_id + 1);
06135 
06136   // The dimension of `lb_expr' and `ub_expr' should not be
06137   // greater than the dimension of `*this'.
06138   const dimension_type lb_space_dim = lb_expr.space_dimension();
06139   if (space_dim < lb_space_dim)
06140     throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)",
06141                                  "lb", lb_expr);
06142   const dimension_type ub_space_dim = ub_expr.space_dimension();
06143   if (space_dim < ub_space_dim)
06144     throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)",
06145                                  "ub", ub_expr);
06146 
06147   strong_closure_assign();
06148   // The image of an empty octagon is empty too.
06149   if (marked_empty())
06150     return;
06151 
06152   if (ub_expr.coefficient(var) == 0) {
06153     refine(var, LESS_OR_EQUAL, ub_expr, denominator);
06154     generalized_affine_preimage(var, GREATER_OR_EQUAL,
06155                                 lb_expr, denominator);
06156     return;
06157   }
06158   if (lb_expr.coefficient(var) == 0) {
06159     refine(var, GREATER_OR_EQUAL, lb_expr, denominator);
06160     generalized_affine_preimage(var, LESS_OR_EQUAL,
06161                                 ub_expr, denominator);
06162     return;
06163   }
06164 
06165   const Coefficient& expr_v = lb_expr.coefficient(var);
06166   // Here `var' occurs in `lb_expr' and `ub_expr'.
06167   // To ease the computation, we add an additional dimension.
06168   const Variable new_var = Variable(space_dim);
06169   add_space_dimensions_and_embed(1);
06170   const Linear_Expression lb_inverse
06171     = lb_expr - (expr_v + denominator)*var;
06172   PPL_DIRTY_TEMP_COEFFICIENT(inverse_den);
06173   neg_assign(inverse_den, expr_v);
06174   affine_image(new_var, lb_inverse, inverse_den);
06175   strong_closure_assign();
06176   PPL_ASSERT(!marked_empty());
06177   generalized_affine_preimage(var, LESS_OR_EQUAL,
06178                               ub_expr, denominator);
06179   if (sgn(denominator) == sgn(inverse_den))
06180     refine_no_check(var >= new_var) ;
06181   else
06182     refine_no_check(var <= new_var);
06183   // Remove the temporarily added dimension.
06184   remove_higher_space_dimensions(space_dim-1);
06185 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds ( const Linear_Expression expr,
bool  from_above 
) const [inline, 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;
from_above true if and only if the boundedness of interest is "from above".
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

Definition at line 1147 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::extract_octagonal_difference(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::MINIMIZATION, Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds_from_above(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds_from_below().

01148                                                         {
01149   // The dimension of `expr' should not be greater than the dimension
01150   // of `*this'.
01151   const dimension_type expr_space_dim = expr.space_dimension();
01152   if (space_dim < expr_space_dim)
01153     throw_dimension_incompatible((from_above
01154                                   ? "bounds_from_above(e)"
01155                                   : "bounds_from_below(e)"), "e", expr);
01156   strong_closure_assign();
01157 
01158   // A zero-dimensional or empty octagon bounds everything.
01159   if (space_dim == 0 || marked_empty())
01160     return true;
01161 
01162   // The constraint `c' is used to check if `expr' is an octagonal difference
01163   // and, in this case, to select the cell.
01164   const Constraint& c = (from_above) ? expr <= 0 : expr >= 0;
01165   dimension_type num_vars = 0;
01166   dimension_type i = 0;
01167   dimension_type j = 0;
01168   PPL_DIRTY_TEMP_COEFFICIENT(coeff);
01169   PPL_DIRTY_TEMP_COEFFICIENT(term);
01170   if (extract_octagonal_difference(c, c.space_dimension(), num_vars,
01171                                    i, j, coeff, term)) {
01172     if (num_vars == 0)
01173       return true;
01174     // Select the cell to be checked.
01175     typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin() + i;
01176     typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter;
01177     return !is_plus_infinity(m_i[j]);
01178   }
01179   else {
01180     // `c' is not an octagonal constraint: use the MIP solver.
01181     Optimization_Mode mode_bounds =
01182       from_above ? MAXIMIZATION : MINIMIZATION;
01183     MIP_Problem mip(space_dim, constraints(), expr, mode_bounds);
01184     return mip.solve() == OPTIMIZED_MIP_PROBLEM;
01185   }
01186 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds_from_above ( const Linear_Expression expr  )  const [inline]

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

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

Definition at line 265 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds().

00265                                                                          {
00266   return bounds(expr, true);
00267 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds_from_below ( const Linear_Expression expr  )  const [inline]

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

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

Definition at line 271 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds().

00271                                                                          {
00272   return bounds(expr, false);
00273 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::can_recycle_congruence_systems (  )  [inline, static]

Returns false indicating that this domain cannot recycle congruences.

Definition at line 525 of file Octagonal_Shape.inlines.hh.

00525                                                    {
00526   return false;
00527 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::can_recycle_constraint_systems (  )  [inline, static]

Returns false indicating that this domain cannot recycle constraints.

Definition at line 519 of file Octagonal_Shape.inlines.hh.

00519                                                    {
00520   return false;
00521 }

template<typename T >
template<typename Iterator >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign ( const Octagonal_Shape< T > &  y,
Iterator  first,
Iterator  last,
unsigned *  tp = 0 
) [inline]

Assigns to *this the result of computing the CC76-extrapolation between *this and y.

Parameters:
y An OS that must be contained in *this.
first An iterator that points to the first stop_point.
last An iterator that points to the last stop_point.
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 3172 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::element_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

03174                                                             {
03175   // Dimension-compatibility check.
03176   if (space_dim != y.space_dim)
03177     throw_dimension_incompatible("CC76_extrapolation_assign(y)", y);
03178 
03179 #ifndef NDEBUG
03180   {
03181     // We assume that `y' is contained in or equal to `*this'.
03182     const Octagonal_Shape x_copy = *this;
03183     const Octagonal_Shape y_copy = y;
03184     PPL_ASSERT(x_copy.contains(y_copy));
03185   }
03186 #endif
03187 
03188   // If both octagons are zero-dimensional,
03189   // since `*this' contains `y', we simply return `*this'.
03190   if (space_dim == 0)
03191     return;
03192 
03193   strong_closure_assign();
03194   // If `*this' is empty, since `*this' contains `y', `y' is empty too.
03195   if (marked_empty())
03196     return;
03197   y.strong_closure_assign();
03198   // If `y' is empty, we return.
03199   if (y.marked_empty())
03200     return;
03201 
03202   // If there are tokens available, work on a temporary copy.
03203   if (tp != 0 && *tp > 0) {
03204     Octagonal_Shape x_tmp(*this);
03205     x_tmp.CC76_extrapolation_assign(y, first, last, 0);
03206     // If the widening was not precise, use one of the available tokens.
03207     if (!contains(x_tmp))
03208       --(*tp);
03209     return;
03210   }
03211 
03212   // Compare each constraint in `y' to the corresponding one in `*this'.
03213   // The constraint in `*this' is kept as is if it is stronger than or
03214   // equal to the constraint in `y'; otherwise, the inhomogeneous term
03215   // of the constraint in `*this' is further compared with elements taken
03216   // from a sorted container (the stop-points, provided by the user), and
03217   // is replaced by the first entry, if any, which is greater than or equal
03218   // to the inhomogeneous term. If no such entry exists, the constraint
03219   // is removed altogether.
03220   typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin();
03221   for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(),
03222          matrix_element_end = matrix.element_end();
03223        i != matrix_element_end;
03224        ++i, ++j) {
03225     const N& y_elem = *j;
03226     N& elem = *i;
03227     if (y_elem < elem) {
03228       Iterator k = std::lower_bound(first, last, elem);
03229       if (k != last) {
03230         if (elem < *k)
03231           assign_r(elem, *k, ROUND_UP);
03232       }
03233       else
03234         assign_r(elem, PLUS_INFINITY, ROUND_NOT_NEEDED);
03235     }
03236   }
03237 
03238   reset_strongly_closed();
03239   PPL_ASSERT(OK());
03240 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign ( const Octagonal_Shape< T > &  y,
unsigned *  tp = 0 
) [inline]

Assigns to *this the result of computing the CC76-extrapolation between *this and y.

Parameters:
y An OS 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 578 of file Octagonal_Shape.inlines.hh.

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign().

00579                                                             {
00580   static N stop_points[] = {
00581     N(-2, ROUND_UP),
00582     N(-1, ROUND_UP),
00583     N( 0, ROUND_UP),
00584     N( 1, ROUND_UP),
00585     N( 2, ROUND_UP)
00586   };
00587   CC76_extrapolation_assign(y,
00588                             stop_points,
00589                             stop_points
00590                             + sizeof(stop_points)/sizeof(stop_points[0]),
00591                             tp);
00592 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign ( const Octagonal_Shape< T > &  y  )  [inline]

Restores from y the constraints of *this, lost by CC76-extrapolation applications.

Parameters:
y An OS that must contain *this.
Exceptions:
std::invalid_argument Thrown if *this and y are dimension-incompatible.

Definition at line 3485 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::element_end(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

03485                                                                   {
03486   // Dimension-compatibility check.
03487   if (space_dim != y.space_dim)
03488     throw_dimension_incompatible("CC76_narrowing_assign(y)", y);
03489 
03490 #ifndef NDEBUG
03491   {
03492     // We assume that `*this' is contained in or equal to `y'.
03493     const Octagonal_Shape x_copy = *this;
03494     const Octagonal_Shape y_copy = y;
03495     PPL_ASSERT(y_copy.contains(x_copy));
03496   }
03497 #endif
03498 
03499   // If both octagons are zero-dimensional, since `*this' contains `y',
03500   // we simply return '*this'.
03501   if (space_dim == 0)
03502     return;
03503 
03504   y.strong_closure_assign();
03505   // If `y' is empty, since `y' contains `*this', `*this' is empty too.
03506   if (y.marked_empty())
03507     return;
03508   strong_closure_assign();
03509   // If `*this' is empty, we return.
03510   if (marked_empty())
03511     return;
03512 
03513   // We consider a constraint of `*this', if its value is `plus_infinity',
03514   // we take the value of the corresponding constraint of `y'.
03515   bool is_oct_changed = false;
03516   typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin();
03517   for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(),
03518        matrix_element_end = matrix.element_end();
03519        i != matrix_element_end;
03520        ++i, ++j) {
03521      if (!is_plus_infinity(*i)
03522          && !is_plus_infinity(*j)
03523          && *i != *j) {
03524       *i = *j;
03525       is_oct_changed = true;
03526     }
03527   }
03528 
03529   if (is_oct_changed && marked_strongly_closed())
03530     reset_strongly_closed();
03531   PPL_ASSERT(OK());
03532 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_leaders ( std::vector< dimension_type > &  leaders  )  const [inline, private]

Compute the leaders of zero-equivalence classes.

It is assumed that the OS is not empty and strongly closed.

Definition at line 2349 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::is_additive_inverse().

02349                                                           {
02350   PPL_ASSERT(!marked_empty() && marked_strongly_closed());
02351   PPL_ASSERT(leaders.size() == 0);
02352   // Variables are ordered according to their index.
02353   // The vector `leaders' is used to indicate the smallest variable
02354   // that belongs to the corresponding equivalence class.
02355   const dimension_type leader_size = matrix.num_rows();
02356   // Initially, each variable is leader of its own zero-equivalence class.
02357   leaders.reserve(leader_size);
02358   for (dimension_type i = 0; i < leader_size; ++i)
02359     leaders.push_back(i);
02360   // Now compute actual leaders.
02361   for (typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin(),
02362          matrix_row_end = matrix.row_end();
02363        i_iter != matrix_row_end; ++i_iter) {
02364     typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter;
02365     dimension_type i = i_iter.index();
02366     typename OR_Matrix<N>::const_row_reference_type m_ci
02367       = (i % 2 != 0) ? *(i_iter-1) : *(i_iter+1);
02368     for (dimension_type j = 0; j < i; ++j) {
02369       using namespace Implementation::Octagonal_Shapes;
02370       dimension_type cj = coherent_index(j);
02371       if (is_additive_inverse(m_ci[cj], m_i[j]))
02372         // Choose as leader the variable having the smaller index.
02373         leaders[i] = leaders[j];
02374     }
02375   }
02376 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_leaders ( std::vector< dimension_type > &  successor,
std::vector< dimension_type > &  no_sing_leaders,
bool &  exist_sing_class,
dimension_type sing_leader 
) const [inline, private]

Compute the leaders of zero-equivalence classes.

It is assumed that the OS is not empty and strongly closed.

Definition at line 2381 of file Octagonal_Shape.templates.hh.

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign().

02384                                                      {
02385   PPL_ASSERT(!marked_empty() && marked_strongly_closed());
02386   PPL_ASSERT(no_sing_leaders.size() == 0);
02387   dimension_type successor_size = successor.size();
02388   std::deque<bool> dealt_with(successor_size, false);
02389   for (dimension_type i = 0; i < successor_size; ++i) {
02390     dimension_type next_i = successor[i];
02391     if (!dealt_with[i]) {
02392       // The index is a leader.
02393       // Now check if it is a leader of a singular class or not.
02394       using namespace Implementation::Octagonal_Shapes;
02395       if (next_i == coherent_index(i)) {
02396         exist_sing_class = true;
02397         sing_leader = i;
02398       }
02399       else
02400         no_sing_leaders.push_back(i);
02401     }
02402     // The following index isn't a leader.
02403     dealt_with[next_i] = true;
02404   }
02405 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_successors ( std::vector< dimension_type > &  successor  )  const [inline, private]

Compute the (zero-equivalence classes) successor relation.

It is assumed that the octagon is not empty and strongly closed.

Definition at line 2317 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::is_additive_inverse().

02317                                                                {
02318   PPL_ASSERT(!marked_empty() && marked_strongly_closed());
02319   PPL_ASSERT(successor.size() == 0);
02320   // Variables are ordered according to their index.
02321   // The vector `successor' is used to indicate which variable
02322   // immediately follows a given one in the corresponding equivalence class.
02323   const dimension_type successor_size = matrix.num_rows();
02324   // Initially, each variable is successor of its own zero-equivalence class.
02325   successor.reserve(successor_size);
02326   for (dimension_type i = 0; i < successor_size; ++i)
02327     successor.push_back(i);
02328   // Now compute actual successors.
02329   for (dimension_type i = successor_size; i-- > 0; )  {
02330     typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin()+i;
02331     typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter;
02332     typename OR_Matrix<N>::const_row_reference_type m_ci
02333       = (i % 2 != 0) ? *(i_iter-1) : *(i_iter+1);
02334     for (dimension_type j = 0; j < i; ++j) {
02335       // FIXME: what is the following, commented-out for?
02336     //for (dimension_type j = i; j-- > 0; ) {
02337       using namespace Implementation::Octagonal_Shapes;
02338       dimension_type cj = coherent_index(j);
02339       if (is_additive_inverse(m_ci[cj], m_i[j]))
02340         // Choose as successor the variable having the greatest index.
02341         successor[j] = i;
02342     }
02343   }
02344 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign ( const Octagonal_Shape< T > &  y  )  [inline]

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 670 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim.

00670                                                                {
00671   // If `y' is an empty 0-dim space octagon, let `*this' become empty.
00672   // If `y' is an universal 0-dim space octagon, we simply return.
00673   if (y.space_dim == 0) {
00674     if (y.marked_empty())
00675       set_empty();
00676     return;
00677   }
00678 
00679   // If `*this' is an empty 0-dim space octagon, then it is sufficient
00680   // to adjust the dimension of the vector space.
00681   if (space_dim == 0 && marked_empty()) {
00682     add_space_dimensions_and_embed(y.space_dim);
00683     return;
00684   }
00685 
00686   // This is the old number of rows in the matrix. It is equal to
00687   // the first index of columns to change.
00688   dimension_type old_num_rows = matrix.num_rows();
00689   // First we increase the space dimension of `*this' by adding
00690   // `y.space_dimension()' new dimensions.
00691   // The matrix for the new octagon is obtained
00692   // by leaving the old system of constraints in the upper left-hand side
00693   // (where they are at the present) and placing the constraints of `y' in the
00694   // lower right-hand side.
00695   add_space_dimensions_and_embed(y.space_dim);
00696   typename OR_Matrix<N>::const_element_iterator
00697     y_it = y.matrix.element_begin();
00698   for (typename OR_Matrix<N>::row_iterator i = matrix.row_begin()+old_num_rows,
00699         matrix_row_end = matrix.row_end(); i != matrix_row_end; ++i) {
00700     typename OR_Matrix<N>::row_reference_type r = *i;
00701     dimension_type rs_i = i.row_size();
00702     for (dimension_type j = old_num_rows; j < rs_i; ++j, ++y_it)
00703       r[j] = *y_it;
00704   }
00705 
00706   // The concatenation doesn't preserve the closure.
00707   if (marked_strongly_closed())
00708     reset_strongly_closed();
00709   PPL_ASSERT(OK());
00710 }

template<typename T >
Congruence_System Parma_Polyhedra_Library::Octagonal_Shape< T >::congruences (  )  const [inline]

Returns a system of (equality) congruences satisfied by *this.

Definition at line 218 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences().

Referenced by Parma_Polyhedra_Library::Grid::Grid().

00218                                       {
00219   return minimized_congruences();
00220 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::constrains ( Variable  var  )  const [inline]

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

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

Definition at line 1046 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::OR_Matrix< T >::row_size(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

01046                                                        {
01047   // `var' should be one of the dimensions of the octagonal shape.
01048   const dimension_type var_space_dim = var.space_dimension();
01049   if (space_dimension() < var_space_dim)
01050     throw_dimension_incompatible("constrains(v)", "v", var);
01051 
01052   // An octagon known to be empty constrains all variables.
01053   // (Note: do not force emptiness check _yet_)
01054   if (marked_empty())
01055     return true;
01056 
01057   // Check whether `var' is syntactically constrained.
01058   const dimension_type n_v = 2*(var_space_dim - 1);
01059   typename OR_Matrix<N>::const_row_iterator m_iter = matrix.row_begin() + n_v;
01060   typename OR_Matrix<N>::const_row_reference_type r_v = *m_iter;
01061   typename OR_Matrix<N>::const_row_reference_type r_cv = *(++m_iter);
01062   for (dimension_type h = m_iter.row_size(); h-- > 0; ) {
01063     if (!is_plus_infinity(r_v[h]) || !is_plus_infinity(r_cv[h]))
01064       return true;
01065   }
01066   ++m_iter;
01067   for (typename OR_Matrix<N>::const_row_iterator m_end = matrix.row_end();
01068        m_iter != m_end; ++m_iter) {
01069     typename OR_Matrix<N>::const_row_reference_type r = *m_iter;
01070     if (!is_plus_infinity(r[n_v]) || !is_plus_infinity(r[n_v+1]))
01071       return true;
01072   }
01073 
01074   // `var' is not syntactically constrained:
01075   // now force an emptiness check.
01076   return is_empty();
01077 }

template<typename T >
Constraint_System Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints (  )  const [inline]

Returns the system of constraints defining *this.

Definition at line 6189 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Constraint_System::zero_dim_empty().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds(), Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_constraints(), Parma_Polyhedra_Library::NNC_Polyhedron::NNC_Polyhedron(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::time_elapse_assign().

06189                                       {
06190   Constraint_System cs;
06191   if (space_dim == 0) {
06192     if (marked_empty())
06193       cs = Constraint_System::zero_dim_empty();
06194   }
06195   else if (marked_empty())
06196     cs.insert(0*Variable(space_dim-1) <= -1);
06197   else {
06198     // KLUDGE: in the future `cs' will be constructed of the right dimension.
06199     // For the time being, we force the dimension with the following line.
06200     cs.insert(0*Variable(space_dim-1) <= 0);
06201 
06202     typedef typename OR_Matrix<N>::const_row_iterator Row_Iterator;
06203     typedef typename OR_Matrix<N>::const_row_reference_type Row_Reference;
06204 
06205     Row_Iterator m_begin = matrix.row_begin();
06206     Row_Iterator m_end = matrix.row_end();
06207 
06208     PPL_DIRTY_TEMP_COEFFICIENT(a);
06209     PPL_DIRTY_TEMP_COEFFICIENT(b);
06210 
06211     // Go through all the unary constraints in `matrix'.
06212     for (Row_Iterator i_iter = m_begin; i_iter != m_end; ) {
06213       const dimension_type i = i_iter.index();
06214       const Variable x(i/2);
06215       const N& c_i_ii = (*i_iter)[i+1];
06216       ++i_iter;
06217       const N& c_ii_i = (*i_iter)[i];
06218       ++i_iter;
06219       // Go through unary constraints.
06220       if (is_additive_inverse(c_i_ii, c_ii_i)) {
06221         // We have a unary equality constraint.
06222         numer_denom(c_ii_i, b, a);
06223         a *= 2;
06224         cs.insert(a*x == b);
06225       }
06226       else {
06227         // We have 0, 1 or 2 inequality constraints.
06228         if (!is_plus_infinity(c_i_ii)) {
06229           numer_denom(c_i_ii, b, a);
06230           a *= 2;
06231           cs.insert(-a*x <= b);
06232         }
06233         if (!is_plus_infinity(c_ii_i)) {
06234           numer_denom(c_ii_i, b, a);
06235           a *= 2;
06236           cs.insert(a*x <= b);
06237         }
06238       }
06239     }
06240     //  Go through all the binary constraints in `matrix'.
06241     for (Row_Iterator i_iter = m_begin; i_iter != m_end; ) {
06242       const dimension_type i = i_iter.index();
06243       Row_Reference r_i = *i_iter;
06244       ++i_iter;
06245       Row_Reference r_ii = *i_iter;
06246       ++i_iter;
06247       const Variable y(i/2);
06248       for (dimension_type j = 0; j < i; j += 2) {
06249         const N& c_i_j = r_i[j];
06250         const N& c_ii_jj = r_ii[j+1];
06251         const Variable x(j/2);
06252         if (is_additive_inverse(c_ii_jj, c_i_j)) {
06253           // We have an equality constraint of the form ax - ay = b.
06254           numer_denom(c_i_j, b, a);
06255           cs.insert(a*x - a*y == b);
06256         }
06257         else {
06258           // We have 0, 1 or 2 inequality constraints.
06259           if (!is_plus_infinity(c_i_j)) {
06260             numer_denom(c_i_j, b, a);
06261             cs.insert(a*x - a*y <= b);
06262           }
06263           if (!is_plus_infinity(c_ii_jj)) {
06264             numer_denom(c_ii_jj, b, a);
06265             cs.insert(a*y - a*x <= b);
06266           }
06267         }
06268 
06269         const N& c_ii_j = r_ii[j];
06270         const N& c_i_jj = r_i[j+1];
06271         if (is_additive_inverse(c_i_jj, c_ii_j)) {
06272           // We have an equality constraint of the form ax + ay = b.
06273           numer_denom(c_ii_j, b, a);
06274           cs.insert(a*x + a*y == b);
06275         }
06276         else {
06277           // We have 0, 1 or 2 inequality constraints.
06278           if (!is_plus_infinity(c_i_jj)) {
06279             numer_denom(c_i_jj, b, a);
06280             cs.insert(-a*x - a*y <= b);
06281           }
06282           if (!is_plus_infinity(c_ii_j)) {
06283             numer_denom(c_ii_j, b, a);
06284             cs.insert(a*x + a*y <= b);
06285           }
06286         }
06287       }
06288     }
06289   }
06290   return cs;
06291 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::contains ( const Octagonal_Shape< T > &  y  )  const [inline]

Returns true if and only if *this contains y.

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

Definition at line 714 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::element_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_BHMZ05_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strictly_contains().

00714                                                            {
00715   // Dimension-compatibility check.
00716   if (space_dim != y.space_dim)
00717     throw_dimension_incompatible("contains(y)", y);
00718 
00719   // The zero-dimensional universe octagon contains any other
00720   // dimension-compatible octagon.
00721   // The zero-dimensional empty octagon only contains another
00722   // zero-dimensional empty octagon.
00723   if (space_dim == 0) {
00724     if (!marked_empty())
00725       return true;
00726     else
00727       return y.marked_empty();
00728   }
00729 
00730   // `y' needs to be transitively closed.
00731   y.strong_closure_assign();
00732   // An empty octagon is in any other dimension-compatible octagons.
00733   if (y.marked_empty())
00734     return true;
00735 
00736   // `*this' contains `y' if and only if every element of `*this'
00737   // is greater than or equal to the correspondent one of `y'.
00738   for (typename OR_Matrix<N>::const_element_iterator
00739          i = matrix.element_begin(), j = y.matrix.element_begin(),
00740          matrix_element_end = matrix.element_end(); i != matrix_element_end; ++i, ++j)
00741     if (*i < *j)
00742       return false;
00743   return true;
00744 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point (  )  const [inline]

Returns true if and only if *this contains (at least) an integer point.

Definition at line 846 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::element_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty().

00846                                                  {
00847   // Force strong closure.
00848   if (is_empty())
00849     return false;
00850   const dimension_type space_dim = space_dimension();
00851   if (space_dim == 0)
00852     return true;
00853 
00854   // A strongly closed and consistent Octagonal_Shape defined by
00855   // integer constraints can only be empty due to tight coeherence.
00856   if (std::numeric_limits<T>::is_integer)
00857     return !tight_coherence_would_make_empty();
00858 
00859   // Build an integer Octagonal_Shape oct_z with bounds at least as
00860   // tight as those in *this and then recheck for emptiness, also
00861   // exploiting tight-coherence.
00862   Octagonal_Shape<mpz_class> oct_z(space_dim);
00863   oct_z.reset_strongly_closed();
00864 
00865   typedef Octagonal_Shape<mpz_class>::N Z;
00866   bool all_integers = true;
00867   typename OR_Matrix<N>::const_element_iterator x_i = matrix.element_begin();
00868   for (typename OR_Matrix<Z>::element_iterator
00869          z_i = oct_z.matrix.element_begin(),
00870          z_end = oct_z.matrix.element_end(); z_i != z_end; ++z_i, ++x_i) {
00871     const N& d = *x_i;
00872     if (is_plus_infinity(d))
00873       continue;
00874     if (is_integer(d))
00875       assign_r(*z_i, d, ROUND_NOT_NEEDED);
00876     else {
00877       all_integers = false;
00878       assign_r(*z_i, d, ROUND_DOWN);
00879     }
00880   }
00881   // Restore strong closure.
00882   if (all_integers)
00883     // oct_z unchanged, so it is still strongly closed.
00884     oct_z.set_strongly_closed();
00885   else {
00886     // oct_z changed: recompute strong closure.
00887     oct_z.strong_closure_assign();
00888     if (oct_z.marked_empty())
00889       return false;
00890   }
00891   return !oct_z.tight_coherence_would_make_empty();
00892 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_minus_v_pm_u_bounds ( dimension_type  v,
dimension_type  last_v,
const Linear_Expression sc_expr,
Coefficient_traits::const_reference  sc_den,
const N minus_lb_v 
) [inline, private]

An helper function for the computation of affine relations.

For each variable index u_id (less than or equal to last_id and different from v_id), deduce constraints of the form -v + u <= k and -v - u <= k, starting from minus_lb_v, which is the negation of a lower bound for v computed according to sc_expr and sc_den.

Strong-closure will be able to deduce the constraints -v - u <= -lb_v - lb_u and -v + u <= -lb_v + ub_u. We can be more precise if variable u played an active role in the computation of (the negation of) the lower bound for v.

Namely, if the corresponding coefficient q == sc_expr[u]/sc_den of u in sc_expr is greater than zero, we can improve the bound for -v + u. In particular:

  • if q >= 1, then -v + u <= -lb_v + lb_u;
  • if 0 < q < 1, then -v + u <= -lb_v + (q*lb_u + (1-q)*ub_u).

Conversely, if q is less than zero, we can improve the bound for -v - u. In particular:

  • if q <= -1, then -v - u <= -lb_v - ub_u;
  • if -1 < q < 0, then -v - u <= -lb_v - ((-q)*ub_u + (1+q)*lb_u).

Definition at line 3656 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::neg_assign(), and PPL_DIRTY_TEMP_COEFFICIENT.

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::refine().

03660                                                   {
03661   // Private method: the caller has to ensure the following.
03662   PPL_ASSERT(sc_den > 0);
03663   PPL_ASSERT(!is_plus_infinity(minus_lb_v));
03664 
03665   PPL_DIRTY_TEMP0(mpq_class, mpq_sc_den);
03666   assign_r(mpq_sc_den, sc_den, ROUND_NOT_NEEDED);
03667 
03668   // No need to consider indices greater than `last_id'.
03669   const dimension_type n_v = 2*v_id;
03670   typename OR_Matrix<N>::row_reference_type m_v = matrix[n_v];
03671 
03672   // Speculatively allocate temporaries out of the loop.
03673   PPL_DIRTY_TEMP(N, half);
03674   PPL_DIRTY_TEMP0(mpq_class, ub_u);
03675   PPL_DIRTY_TEMP0(mpq_class, q);
03676   PPL_DIRTY_TEMP0(mpq_class, minus_lb_u);
03677   PPL_DIRTY_TEMP(N, up_approx);
03678   PPL_DIRTY_TEMP_COEFFICIENT(minus_expr_u);
03679 
03680   for (dimension_type u_id = last_id+1; u_id-- > 0; ) {
03681     // Skip the case when `u_id == v_id'.
03682     if (u_id == v_id)
03683       continue;
03684     const Coefficient& expr_u = sc_expr.coefficient(Variable(u_id));
03685     // Skip the case when `expr_u == 0'.
03686     if (expr_u == 0)
03687       continue;
03688 
03689     const dimension_type n_u = u_id*2;
03690     // If `expr_u' is positive, we can improve `-v + u'.
03691     if (expr_u > 0) {
03692       if (expr_u >= sc_den) {
03693         // Here q >= 1: deducing `-v + u <= lb_u - lb_v',
03694         // i.e., `u - v <= (-lb_v) - (-lb_u)'.
03695         // We avoid to check if `lb_u' is plus infinity, because
03696         // it is used for the computation of `lb_v'.
03697         // Let half = m_u_cu / 2.
03698         div_2exp_assign_r(half, matrix[n_u][n_u+1], 1, ROUND_UP);
03699         N& m_u_minus_v = (n_v < n_u) ? matrix[n_u+1][n_v+1] : m_v[n_u];
03700         sub_assign_r(m_u_minus_v, minus_lb_v, half, ROUND_UP);
03701       }
03702       else {
03703         // Here 0 < q < 1.
03704         typename OR_Matrix<N>::row_reference_type m_cu = matrix[n_u+1];
03705         const N& m_cu_u = m_cu[n_u];
03706         if (!is_plus_infinity(m_cu_u)) {
03707           // Let `ub_u' and `lb_u' be the known upper and lower bound
03708           // for `u', respectively. The upper bound for `u - v' is
03709           // computed as `(q * lb_u + (1-q) * ub_u) - lb_v',
03710           // i.e., `ub_u - q * (ub_u + (-lb_u)) + minus_lb_v'.
03711           assign_r(ub_u, m_cu[n_u], ROUND_NOT_NEEDED);
03712           div_2exp_assign_r(ub_u, ub_u, 1, ROUND_NOT_NEEDED);
03713           assign_r(q, expr_u, ROUND_NOT_NEEDED);
03714           div_assign_r(q, q, mpq_sc_den, ROUND_NOT_NEEDED);
03715           assign_r(minus_lb_u, matrix[n_u][n_u+1], ROUND_NOT_NEEDED);
03716           div_2exp_assign_r(minus_lb_u, minus_lb_u, 1, ROUND_NOT_NEEDED);
03717           // Compute `ub_u - lb_u'.
03718           add_assign_r(minus_lb_u, ub_u, minus_lb_u, ROUND_NOT_NEEDED);
03719           // Compute `ub_u - q * (ub_u - lb_u)'.
03720           sub_mul_assign_r(ub_u, q, minus_lb_u, ROUND_NOT_NEEDED);
03721           assign_r(up_approx, ub_u, ROUND_UP);
03722           // Deducing `u - v <= -lb_v - (q * lb_u + (1-q) * ub_u)'.
03723           N& m_u_minus_v = (n_v < n_u) ? m_cu[n_v+1] : m_v[n_u];
03724           add_assign_r(m_u_minus_v, minus_lb_v, up_approx, ROUND_UP);
03725         }
03726       }
03727     }
03728     else {
03729       PPL_ASSERT(expr_u < 0);
03730       // If `expr_u' is negative, we can improve `-v - u'.
03731       neg_assign(minus_expr_u, expr_u);
03732       if (minus_expr_u >= sc_den) {
03733         // Here q <= -1: Deducing `-v - u <= -lb_v - ub_u'.
03734         // We avoid to check if `ub_u' is plus infinity, because
03735         // it is used for the computation of `lb_v'.
03736         // Let half = m_cu_u / 2.
03737         div_2exp_assign_r(half, matrix[n_u+1][n_u], 1, ROUND_UP);
03738         N& m_minus_v_minus_u = (n_v < n_u) ? matrix[n_u][n_v+1] : m_v[n_u+1];
03739         sub_assign_r(m_minus_v_minus_u, minus_lb_v, half, ROUND_UP);
03740       }
03741       else {
03742         // Here -1 < q < 0.
03743         typename OR_Matrix<N>::row_reference_type m_u = matrix[n_u];
03744         const N& m_u_cu = m_u[n_u+1];
03745         if (!is_plus_infinity(m_u_cu)) {
03746           // Let `ub_u' and `lb_u' be the known upper and lower bound
03747           // for `u', respectively. The upper bound for `-v - u' is
03748           // computed as `-lb_v - ((-q)*ub_u + (1+q)*lb_u)',
03749           // i.e., `minus_lb_v - lb_u + q*(ub_u - lb_u)'.
03750           assign_r(ub_u, matrix[n_u+1][n_u], ROUND_NOT_NEEDED);
03751           div_2exp_assign_r(ub_u, ub_u, 1, ROUND_NOT_NEEDED);
03752           assign_r(q, expr_u, ROUND_NOT_NEEDED);
03753           div_assign_r(q, q, mpq_sc_den, ROUND_NOT_NEEDED);
03754           assign_r(minus_lb_u, m_u[n_u+1], ROUND_NOT_NEEDED);
03755           div_2exp_assign_r(minus_lb_u, minus_lb_u, 1, ROUND_NOT_NEEDED);
03756           // Compute `ub_u - lb_u'.
03757           add_assign_r(ub_u, ub_u, minus_lb_u, ROUND_NOT_NEEDED);
03758           // Compute `-lb_u + q*(ub_u - lb_u)'.
03759           add_mul_assign_r(minus_lb_u, q, ub_u, ROUND_NOT_NEEDED);
03760           assign_r(up_approx, minus_lb_u, ROUND_UP);
03761           // Deducing `-v - u <= -lb_v - ((-q) * ub_u + (1+q) * lb_u)'.
03762           N& m_minus_v_minus_u = (n_v < n_u) ? m_u[n_v+1] : m_v[n_u+1];
03763           add_assign_r(m_minus_v_minus_u, minus_lb_v, up_approx, ROUND_UP);
03764         }
03765       }
03766     }
03767   }
03768 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_v_pm_u_bounds ( dimension_type  v_id,
dimension_type  last_id,
const Linear_Expression sc_expr,
Coefficient_traits::const_reference  sc_den,
const N ub_v 
) [inline, private]

An helper function for the computation of affine relations.

For each variable index u_id (less than or equal to last_id and different from v_id), deduce constraints of the form v - u <= k and v + u <= k, starting from ub_v, which is an upper bound for v computed according to sc_expr and sc_den.

Strong-closure will be able to deduce the constraints v - u <= ub_v - lb_u and v + u <= ub_v + ub_u. We can be more precise if variable u played an active role in the computation of the upper bound for v.

Namely, if the corresponding coefficient q == sc_expr[u]/sc_den of u in sc_expr is greater than zero, we can improve the bound for v - u. In particular:

  • if q >= 1, then v - u <= ub_v - ub_u;
  • if 0 < q < 1, then v - u <= ub_v - (q*ub_u + (1-q)*lb_u).

Conversely, if q is less than zero, we can improve the bound for v + u. In particular:

  • if q <= -1, then v + u <= ub_v + lb_u;
  • if -1 < q < 0, then v + u <= ub_v + ((-q)*lb_u + (1+q)*ub_u).

Definition at line 3537 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::neg_assign(), and PPL_DIRTY_TEMP_COEFFICIENT.

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::refine().

03541                                       {
03542   // Private method: the caller has to ensure the following.
03543   PPL_ASSERT(sc_den > 0);
03544   PPL_ASSERT(!is_plus_infinity(ub_v));
03545 
03546   PPL_DIRTY_TEMP0(mpq_class, mpq_sc_den);
03547   assign_r(mpq_sc_den, sc_den, ROUND_NOT_NEEDED);
03548 
03549   // No need to consider indices greater than `last_id'.
03550   const dimension_type n_v = 2*v_id;
03551   typename OR_Matrix<N>::row_reference_type m_cv = matrix[n_v+1];
03552 
03553   // Speculatively allocate temporaries out of the loop.
03554   PPL_DIRTY_TEMP(N, half);
03555   PPL_DIRTY_TEMP0(mpq_class, minus_lb_u);
03556   PPL_DIRTY_TEMP0(mpq_class, q);
03557   PPL_DIRTY_TEMP0(mpq_class, minus_q);
03558   PPL_DIRTY_TEMP0(mpq_class, ub_u);
03559   PPL_DIRTY_TEMP0(mpq_class, lb_u);
03560   PPL_DIRTY_TEMP(N, up_approx);
03561   PPL_DIRTY_TEMP_COEFFICIENT(minus_expr_u);
03562 
03563   for (dimension_type u_id = last_id+1; u_id-- > 0; ) {
03564     // Skip the case when `u_id == v_id'.
03565     if (u_id == v_id)
03566       continue;
03567     const Coefficient& expr_u = sc_expr.coefficient(Variable(u_id));
03568     // Skip the case when `expr_u == 0'.
03569     if (expr_u == 0)
03570       continue;
03571 
03572     const dimension_type n_u = u_id*2;
03573     // If `expr_u' is positive, we can improve `v - u'.
03574     if (expr_u > 0) {
03575       if (expr_u >= sc_den) {
03576         // Here q >= 1: deducing `v - u <= ub_v - ub_u'.
03577         // We avoid to check if `ub_u' is plus infinity, because
03578         // it is used for the computation of `ub_v'.
03579         // Let half = m_cu_u / 2.
03580         div_2exp_assign_r(half, matrix[n_u+1][n_u], 1, ROUND_UP);
03581         N& m_v_minus_u = (n_v < n_u) ? matrix[n_u][n_v] : m_cv[n_u+1];
03582         sub_assign_r(m_v_minus_u, ub_v, half, ROUND_UP);
03583       }
03584       else {
03585         // Here 0 < q < 1.
03586         typename OR_Matrix<N>::row_reference_type m_u = matrix[n_u];
03587         const N& m_u_cu = m_u[n_u+1];
03588         if (!is_plus_infinity(m_u_cu)) {
03589           // Let `ub_u' and `lb_u' be the known upper and lower bound
03590           // for `u', respectively. The upper bound for `v - u' is
03591           // computed as `ub_v - (q * ub_u + (1-q) * lb_u)',
03592           // i.e., `ub_v + (-lb_u) - q * (ub_u + (-lb_u))'.
03593           assign_r(minus_lb_u, m_u_cu, ROUND_NOT_NEEDED);
03594           div_2exp_assign_r(minus_lb_u, minus_lb_u, 1, ROUND_NOT_NEEDED);
03595           assign_r(q, expr_u, ROUND_NOT_NEEDED);
03596           div_assign_r(q, q, mpq_sc_den, ROUND_NOT_NEEDED);
03597           assign_r(ub_u, matrix[n_u+1][n_u], ROUND_NOT_NEEDED);
03598           div_2exp_assign_r(ub_u, ub_u, 1, ROUND_NOT_NEEDED);
03599           // Compute `ub_u - lb_u'.
03600           add_assign_r(ub_u, ub_u, minus_lb_u, ROUND_NOT_NEEDED);
03601           // Compute `(-lb_u) - q * (ub_u - lb_u)'.
03602           sub_mul_assign_r(minus_lb_u, q, ub_u, ROUND_NOT_NEEDED);
03603           assign_r(up_approx, minus_lb_u, ROUND_UP);
03604           // Deducing `v - u <= ub_v - (q * ub_u + (1-q) * lb_u)'.
03605           N& m_v_minus_u = (n_v < n_u) ? m_u[n_v] : m_cv[n_u+1];
03606           add_assign_r(m_v_minus_u, ub_v, up_approx, ROUND_UP);
03607         }
03608       }
03609     }
03610     else {
03611       PPL_ASSERT(expr_u < 0);
03612       // If `expr_u' is negative, we can improve `v + u'.
03613       neg_assign(minus_expr_u, expr_u);
03614       if (minus_expr_u >= sc_den) {
03615         // Here q <= -1: Deducing `v + u <= ub_v + lb_u'.
03616         // We avoid to check if `lb_u' is plus infinity, because
03617         // it is used for the computation of `ub_v'.
03618         // Let half = m_u_cu / 2.
03619         div_2exp_assign_r(half, matrix[n_u][n_u+1], 1, ROUND_UP);
03620         N& m_v_plus_u = (n_v < n_u) ? matrix[n_u+1][n_v] : m_cv[n_u];
03621         sub_assign_r(m_v_plus_u, ub_v, half, ROUND_UP);
03622       }
03623       else {
03624         // Here -1 < q < 0.
03625         typename OR_Matrix<N>::row_reference_type m_cu = matrix[n_u+1];
03626         const N& m_cu_u = m_cu[n_u];
03627         if (!is_plus_infinity(m_cu_u)) {
03628           // Let `ub_u' and `lb_u' be the known upper and lower bound
03629           // for `u', respectively. The upper bound for `v + u' is
03630           // computed as `ub_v + ((-q) * lb_u + (1+q) * ub_u)',
03631           // i.e., `ub_v + ub_u + (-q) * (lb_u - ub_u)'.
03632           assign_r(ub_u, m_cu[n_u], ROUND_NOT_NEEDED);
03633           div_2exp_assign_r(ub_u, ub_u, 1, ROUND_NOT_NEEDED);
03634           assign_r(minus_q, minus_expr_u, ROUND_NOT_NEEDED);
03635           div_assign_r(minus_q, minus_q, mpq_sc_den, ROUND_NOT_NEEDED);
03636           assign_r(lb_u, matrix[n_u][n_u+1], ROUND_NOT_NEEDED);
03637           div_2exp_assign_r(lb_u, lb_u, 1, ROUND_NOT_NEEDED);
03638           neg_assign_r(lb_u, lb_u, ROUND_NOT_NEEDED);
03639           // Compute `lb_u - ub_u'.
03640           sub_assign_r(lb_u, lb_u, ub_u, ROUND_NOT_NEEDED);
03641           // Compute `ub_u + (-q) * (lb_u - ub_u)'.
03642           add_mul_assign_r(ub_u, minus_q, lb_u, ROUND_NOT_NEEDED);
03643           assign_r(up_approx, ub_u, ROUND_UP);
03644           // Deducing `v + u <= ub_v + ((-q) * lb_u + (1+q) * ub_u)'.
03645           N& m_v_plus_u = (n_v < n_u) ? m_cu[n_v] : m_cv[n_u];
03646           add_assign_r(m_v_plus_u, ub_v, up_approx, ROUND_UP);
03647         }
03648       }
03649     }
03650   }
03651 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign ( const Octagonal_Shape< T > &  y  )  [inline]

Assigns to *this the smallest octagon containing the set difference of *this and y.

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

Definition at line 2605 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Poly_Con_Relation::implies(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign().

02605                                                               {
02606   // Dimension-compatibility check.
02607   if (space_dim != y.space_dim)
02608     throw_dimension_incompatible("difference_assign(y)", y);
02609 
02610   Octagonal_Shape& x = *this;
02611 
02612   // Being lazy here is only harmful.
02613   // We close.
02614   x.strong_closure_assign();
02615   // The difference of an empty octagon and of an octagon `p' is empty.
02616   if (x.marked_empty())
02617     return;
02618   // The difference of a octagon `p' and an empty octagon is `p'.
02619   if (y.marked_empty())
02620     return;
02621 
02622   // If both octagons are zero-dimensional,
02623   // then at this point they are necessarily universe octagons,
02624   // so that their difference is empty.
02625   if (x.space_dim == 0) {
02626     x.set_empty();
02627     return;
02628   }
02629 
02630   // TODO: This is just an executable specification.
02631   //       Have to find a more efficient method.
02632   if (y.contains(x)) {
02633     x.set_empty();
02634     return;
02635   }
02636 
02637   Octagonal_Shape new_oct(space_dim, EMPTY);
02638   // We take a constraint of the octagon y at the time and we
02639   // consider its complementary. Then we intersect the union
02640   // of these complementaries with the octagon x.
02641   const Constraint_System& y_cs = y.constraints();
02642   for (Constraint_System::const_iterator i = y_cs.begin(),
02643          y_cs_end = y_cs.end(); i != y_cs_end; ++i) {
02644     const Constraint& c = *i;
02645     // If the octagon `x' is included the octagon defined by `c',
02646     // then `c' _must_ be skipped, as adding its complement to `x'
02647     // would result in the empty octagon, and as we would obtain
02648     // a result that is less precise than the difference.
02649     if (x.relation_with(c).implies(Poly_Con_Relation::is_included()))
02650       continue;
02651     Octagonal_Shape z = x;
02652     const Linear_Expression e = Linear_Expression(c);
02653     z.add_constraint(e <= 0);
02654     if (!z.is_empty())
02655       new_oct.upper_bound_assign(z);
02656     if (c.is_equality()) {
02657       z = x;
02658       z.add_constraint(e >= 0);
02659       if (!z.is_empty())
02660         new_oct.upper_bound_assign(z);
02661     }
02662   }
02663   *this = new_oct;
02664   PPL_ASSERT(OK());
02665 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points ( const Variables_Set vars,
Complexity_Class  complexity = ANY_COMPLEXITY 
) [inline]

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

Parameters:
vars Points with non-integer coordinates for these variables/space-dimensions can be discarded.
complexity The maximal complexity of any algorithms used.
Note:
Currently there is no optimality guarantee, not even if complexity is ANY_COMPLEXITY.

Definition at line 6820 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::is_even(), Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::is_plus_infinity(), and Parma_Polyhedra_Library::Variables_Set::space_dimension().

06821                                                  {
06822   // Dimension-compatibility check.
06823   const dimension_type min_space_dim = vars.space_dimension();
06824   if (space_dimension() < min_space_dim)
06825     throw_dimension_incompatible("drop_some_non_integer_points(vs, cmpl)",
06826                                  min_space_dim);
06827 
06828   if (std::numeric_limits<T>::is_integer || min_space_dim == 0)
06829     return;
06830 
06831   strong_closure_assign();
06832   if (marked_empty())
06833     return;
06834 
06835   PPL_DIRTY_TEMP(N, temp_one);
06836   assign_r(temp_one, 1, ROUND_NOT_NEEDED);
06837 
06838   const Variables_Set::const_iterator v_begin = vars.begin();
06839   const Variables_Set::const_iterator v_end = vars.end();
06840   PPL_ASSERT(v_begin != v_end);
06841   typedef typename OR_Matrix<N>::row_reference_type Row_Reference;
06842   for (Variables_Set::const_iterator v_i = v_begin; v_i != v_end; ++v_i) {
06843     const dimension_type i = 2 * (*v_i);
06844     const dimension_type ci = i + 1;
06845     Row_Reference m_i = matrix[i];
06846     Row_Reference m_ci = matrix[ci];
06847 
06848     // Unary constaints: should be even integers.
06849     N& m_i_ci = m_i[ci];
06850     if (!is_plus_infinity(m_i_ci)) {
06851       drop_some_non_integer_points_helper(m_i_ci);
06852       if (!is_even(m_i_ci)) {
06853         sub_assign_r(m_i_ci, m_i_ci, temp_one, ROUND_UP);
06854         reset_strongly_closed();
06855       }
06856     }
06857     N& m_ci_i = m_ci[i];
06858     if (!is_plus_infinity(m_ci_i)) {
06859       drop_some_non_integer_points_helper(m_ci_i);
06860       if (!is_even(m_ci_i)) {
06861         sub_assign_r(m_ci_i, m_ci_i, temp_one, ROUND_UP);
06862         reset_strongly_closed();
06863       }
06864     }
06865 
06866     // Binary constraints (note: only consider j < i).
06867     for (Variables_Set::const_iterator v_j = v_begin; v_j != v_i; ++v_j) {
06868       const dimension_type j = 2 * (*v_j);
06869       const dimension_type cj = j + 1;
06870       drop_some_non_integer_points_helper(m_i[j]);
06871       drop_some_non_integer_points_helper(m_i[cj]);
06872       drop_some_non_integer_points_helper(m_ci[j]);
06873       drop_some_non_integer_points_helper(m_ci[cj]);
06874     }
06875   }
06876   PPL_ASSERT(OK());
06877 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points ( Complexity_Class  complexity = ANY_COMPLEXITY  )  [inline]

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

Parameters:
complexity The maximal complexity of any algorithms used.
Note:
Currently there is no optimality guarantee, not even if complexity is ANY_COMPLEXITY.

Definition at line 6784 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points_helper(), Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::element_end(), Parma_Polyhedra_Library::is_even(), Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().

06784                                                                  {
06785   if (std::numeric_limits<T>::is_integer)
06786     return;
06787 
06788   const dimension_type space_dim = space_dimension();
06789   strong_closure_assign();
06790   if (space_dim == 0 || marked_empty())
06791     return;
06792 
06793   for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(),
06794          i_end = matrix.element_end(); i != i_end; ++i)
06795     drop_some_non_integer_points_helper(*i);
06796 
06797   // Unary constraints should have an even integer boundary.
06798   PPL_DIRTY_TEMP(N, temp_one);
06799   assign_r(temp_one, 1, ROUND_NOT_NEEDED);
06800   for (dimension_type i = 0; i < 2*space_dim; i += 2) {
06801     const dimension_type ci = i+1;
06802     N& mat_i_ci = matrix[i][ci];
06803     if (!is_plus_infinity(mat_i_ci) && !is_even(mat_i_ci)) {
06804       sub_assign_r(mat_i_ci, mat_i_ci, temp_one, ROUND_UP);
06805       reset_strongly_closed();
06806     }
06807     N& mat_ci_i = matrix[ci][i];
06808     if (!is_plus_infinity(mat_ci_i) && !is_even(mat_ci_i)) {
06809       sub_assign_r(mat_ci_i, mat_ci_i, temp_one, ROUND_UP);
06810       reset_strongly_closed();
06811     }
06812   }
06813 
06814   PPL_ASSERT(OK());
06815 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points_helper ( N elem  )  [inline, private]

Definition at line 825 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), and Parma_Polyhedra_Library::Checked::Result.

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points().

00825                                                                {
00826   if (!is_integer(elem)) {
00827 #ifndef NDEBUG
00828     Result r =
00829 #endif
00830     floor_assign_r(elem, elem, ROUND_DOWN);
00831     PPL_ASSERT(r == V_EQ);
00832     reset_strongly_closed();
00833   }
00834 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension ( Variable  var,
dimension_type  m 
) [inline]

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 6295 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::max_space_dimension(), Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().

06295                                                                          {
06296   // `var' should be one of the dimensions of the vector space.
06297   const dimension_type var_id = var.id();
06298   if (var_id+1 > space_dim)
06299     throw_dimension_incompatible("expand_space_dimension(v, m)", var_id+1);
06300 
06301   // The space dimension of the resulting octagon should not
06302   // overflow the maximum allowed space dimension.
06303   if (m > max_space_dimension() - space_dim)
06304     throw_generic("expand_dimension(v, m)",
06305                   "adding m new space dimensions exceeds "
06306                   "the maximum allowed space dimension");
06307 
06308   // Nothing to do, if no dimensions must be added.
06309   if (m == 0)
06310     return;
06311 
06312   // Keep track of the dimension before adding the new ones.
06313   const dimension_type old_num_rows = matrix.num_rows();
06314 
06315   // Add the required new dimensions.
06316   add_space_dimensions_and_embed(m);
06317 
06318   // For each constraints involving variable `var', we add a
06319   // similar constraint with the new variable substituted for
06320   // variable `var'.
06321   typedef typename OR_Matrix<N>::row_iterator Row_Iterator;
06322   typedef typename OR_Matrix<N>::row_reference_type Row_Reference;
06323   typedef typename OR_Matrix<N>::const_row_iterator Row_iterator;
06324   typedef typename OR_Matrix<N>::const_row_reference_type Row_reference;
06325 
06326   const Row_Iterator m_begin = matrix.row_begin();
06327   const Row_Iterator m_end = matrix.row_end();
06328   const dimension_type n_var = 2*var_id;
06329   Row_iterator v_iter = m_begin + n_var;
06330   Row_reference m_v = *v_iter;
06331   Row_reference m_cv = *(v_iter+1);
06332 
06333   for (Row_Iterator i_iter = m_begin + old_num_rows; i_iter != m_end;
06334        i_iter += 2) {
06335     Row_Reference m_i = *i_iter;
06336     Row_Reference m_ci = *(i_iter+1);
06337     const dimension_type i = i_iter.index();
06338     const dimension_type ci = i+1;
06339     m_i[ci] = m_v[n_var+1];
06340     m_ci[i] = m_cv[n_var];
06341     for (dimension_type j = 0; j < n_var; ++j) {
06342       m_i[j] = m_v[j];
06343       m_ci[j] = m_cv[j];
06344     }
06345     for (dimension_type j = n_var+2; j < old_num_rows; ++j) {
06346       Row_Iterator j_iter = m_begin + j;
06347       Row_Reference m_cj = (j % 2 != 0) ? *(j_iter-1) : *(j_iter+1);
06348       m_i[j] = m_cj[n_var+1];
06349       m_ci[j] = m_cj[n_var];
06350     }
06351   }
06352   // In general, adding a constraint does not preserve the strong closure
06353   // of the octagon.
06354   if (marked_strongly_closed())
06355     reset_strongly_closed();
06356   PPL_ASSERT(OK());
06357 }

template<typename T >
memory_size_type Parma_Polyhedra_Library::Octagonal_Shape< T >::external_memory_in_bytes (  )  const [inline]

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

Definition at line 7087 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::OR_Matrix< T >::external_memory_in_bytes(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix.

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::total_memory_in_bytes().

07087                                                    {
07088   return matrix.external_memory_in_bytes();
07089 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions ( const Variables_Set vars,
Variable  dest 
) [inline]

Folds the space dimensions in vars into dest.

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

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

Definition at line 6361 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::max_assign(), Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().

06362                                                          {
06363   // `dest' should be one of the dimensions of the octagon.
06364   if (dest.space_dimension() > space_dim)
06365     throw_dimension_incompatible("fold_space_dimensions(vs, v)", "v", dest);
06366 
06367   // The folding of no dimensions is a no-op.
06368   if (vars.empty())
06369     return;
06370 
06371   // All variables in `vars' should be dimensions of the octagon.
06372   if (vars.space_dimension() > space_dim)
06373     throw_dimension_incompatible("fold_space_dimensions(vs, v)",
06374                                  vars.space_dimension());
06375 
06376   // Moreover, `dest.id()' should not occur in `vars'.
06377   if (vars.find(dest.id()) != vars.end())
06378     throw_generic("fold_space_dimensions(vs, v)",
06379                   "v should not occur in vs");
06380 
06381   // Recompute the elements of the row and the column corresponding
06382   // to variable `dest' by taking the join of their value with the
06383   // value of the corresponding elements in the row and column of the
06384   // variable `vars'.
06385   typedef typename OR_Matrix<N>::row_iterator Row_Iterator;
06386   typedef typename OR_Matrix<N>::row_reference_type Row_Reference;
06387 
06388   const Row_Iterator m_begin = matrix.row_begin();
06389 
06390   strong_closure_assign();
06391   const dimension_type n_rows = matrix.num_rows();
06392   const dimension_type n_dest = 2*dest.id();
06393   Row_Iterator v_iter = m_begin + n_dest;
06394   Row_Reference m_v = *v_iter;
06395   Row_Reference m_cv = *(v_iter+1);
06396   for (Variables_Set::const_iterator i = vars.begin(),
06397          vs_end = vars.end(); i != vs_end; ++i) {
06398     const dimension_type tbf_id = *i;
06399     const dimension_type tbf_var = 2*tbf_id;
06400     Row_Iterator tbf_iter = m_begin + tbf_var;
06401     Row_Reference m_tbf = *tbf_iter;
06402     Row_Reference m_ctbf = *(tbf_iter+1);
06403     max_assign(m_v[n_dest+1], m_tbf[tbf_var+1]);
06404     max_assign(m_cv[n_dest], m_ctbf[tbf_var]);
06405 
06406     const dimension_type min_id = std::min(n_dest, tbf_var);
06407     const dimension_type max_id = std::max(n_dest, tbf_var);
06408 
06409     using namespace Implementation::Octagonal_Shapes;
06410     for (dimension_type j = 0; j < min_id; ++j) {
06411       const dimension_type cj = coherent_index(j);
06412       max_assign(m_v[j], m_tbf[j]);
06413       max_assign(m_cv[j], m_ctbf[j]);
06414       max_assign(m_cv[cj], m_ctbf[cj]);
06415       max_assign(m_v[cj], m_tbf[cj]);
06416     }
06417     for (dimension_type j = min_id+2; j < max_id; ++j) {
06418       const dimension_type cj = coherent_index(j);
06419       Row_Iterator j_iter = m_begin + j;
06420       Row_Reference m_j = *j_iter;
06421       Row_Reference m_cj = (j % 2 != 0) ? *(j_iter-1) : *(j_iter+1);
06422       if (n_dest == min_id) {
06423         max_assign(m_cj[n_dest+1], m_tbf[j]);
06424         max_assign(m_cj[n_dest], m_ctbf[j]);
06425         max_assign(m_j[n_dest], m_ctbf[cj]);
06426         max_assign(m_j[n_dest+1], m_tbf[cj]);
06427       }
06428       else {
06429         max_assign(m_v[j], m_cj[tbf_var+1]);
06430         max_assign(m_cv[j], m_cj[tbf_var]);
06431         max_assign(m_cv[cj], m_j[tbf_var]);
06432         max_assign(m_v[cj], m_j[tbf_var+1]);
06433       }
06434     }
06435     for (dimension_type j = max_id+2; j < n_rows; ++j) {
06436       Row_Iterator j_iter = m_begin + j;
06437       Row_Reference m_j = *j_iter;
06438       Row_Reference m_cj = (j % 2 != 0) ? *(j_iter-1) : *(j_iter+1);
06439       max_assign(m_cj[n_dest+1], m_cj[tbf_var+1]);
06440       max_assign(m_cj[n_dest], m_cj[tbf_var]);
06441       max_assign(m_j[n_dest], m_j[tbf_var]);
06442       max_assign(m_j[n_dest+1], m_j[tbf_var+1]);
06443     }
06444   }
06445   remove_space_dimensions(vars);
06446 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints ( dimension_type  v_id  )  [inline, private]

Removes all the constraints on variable v_id.

Definition at line 3773 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::PLUS_INFINITY, and Parma_Polyhedra_Library::OR_Matrix< T >::row_size().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain().

03773                                                             {
03774   PPL_ASSERT(v_id < space_dim);
03775   const dimension_type n_v = 2*v_id;
03776   typename OR_Matrix<N>::row_iterator m_iter = matrix.row_begin() + n_v;
03777   typename OR_Matrix<N>::row_reference_type r_v = *m_iter;
03778   typename OR_Matrix<N>::row_reference_type r_cv = *(++m_iter);
03779   for (dimension_type h = m_iter.row_size(); h-- > 0; ) {
03780     assign_r(r_v[h], PLUS_INFINITY, ROUND_NOT_NEEDED);
03781     assign_r(r_cv[h], PLUS_INFINITY, ROUND_NOT_NEEDED);
03782   }
03783   ++m_iter;
03784   for (typename OR_Matrix<N>::row_iterator m_end = matrix.row_end();
03785        m_iter != m_end; ++m_iter) {
03786     typename OR_Matrix<N>::row_reference_type r = *m_iter;
03787     assign_r(r[n_v], PLUS_INFINITY, ROUND_NOT_NEEDED);
03788     assign_r(r[n_v+1], PLUS_INFINITY, ROUND_NOT_NEEDED);
03789   }
03790 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_binary_octagonal_constraints ( dimension_type  v_id  )  [inline, private]

Removes all binary constraints on variable v_id.

Definition at line 3795 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), and Parma_Polyhedra_Library::PLUS_INFINITY.

03795                                                                {
03796   PPL_ASSERT(v_id < space_dim);
03797   const dimension_type n_v = 2*v_id;
03798   typename OR_Matrix<N>::row_iterator m_iter = matrix.row_begin() + n_v;
03799   typename OR_Matrix<N>::row_reference_type r_v = *m_iter;
03800   typename OR_Matrix<N>::row_reference_type r_cv = *(++m_iter);
03801   for (dimension_type k = n_v; k-- > 0; ) {
03802     assign_r(r_v[k], PLUS_INFINITY, ROUND_NOT_NEEDED);
03803     assign_r(r_cv[k], PLUS_INFINITY, ROUND_NOT_NEEDED);
03804   }
03805   ++m_iter;
03806   for (typename OR_Matrix<N>::row_iterator m_end = matrix.row_end();
03807        m_iter != m_end; ++m_iter) {
03808     typename OR_Matrix<N>::row_reference_type r = *m_iter;
03809     assign_r(r[n_v], PLUS_INFINITY, ROUND_NOT_NEEDED);
03810     assign_r(r[n_v+1], PLUS_INFINITY, ROUND_NOT_NEEDED);
03811   }
03812 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::frequency ( const Linear_Expression expr,
Coefficient freq_n,
Coefficient freq_d,
Coefficient val_n,
Coefficient val_d 
) const [inline]

Returns true if and only if there exist a unique value val such that *this saturates the equality expr = val.

Parameters:
expr The linear expression for which the frequency is needed;
freq_n If true is returned, the value is set to $0$; Present for interface compatibility with class Grid, where the frequency can have a non-zero value;
freq_d If true is returned, the value is set to $1$;
val_n The numerator of val;
val_d The denominator of val;
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

If false is returned, then freq_n, freq_d, val_n and val_d are left untouched.

Definition at line 896 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Checked::le, Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::normalize2(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

00898                                                                             {
00899   dimension_type space_dim = space_dimension();
00900   // The dimension of `expr' must be at most the dimension of *this.
00901   if (space_dim < expr.space_dimension())
00902     throw_dimension_incompatible("frequency(e, ...)", "e", expr);
00903 
00904   // Check if `expr' has a constant value.
00905   // If it is constant, set the frequency `freq_n' to 0
00906   // and return true. Otherwise the values for \p expr
00907   // are not discrete so return false.
00908 
00909   // Space dimension = 0: if empty, then return false;
00910   // otherwise the frequency is 0 and the value is the inhomogeneous term.
00911   if (space_dim == 0) {
00912     if (is_empty())
00913       return false;
00914     freq_n = 0;
00915     freq_d = 1;
00916     val_n = expr.inhomogeneous_term();
00917     val_d = 1;
00918     return true;
00919   }
00920 
00921   strong_closure_assign();
00922   // For an empty Octagonal shape, we simply return false.
00923   if (marked_empty())
00924     return false;
00925 
00926   // The Octagonal shape has at least 1 dimension and is not empty.
00927   PPL_DIRTY_TEMP_COEFFICIENT(coeff);
00928   PPL_DIRTY_TEMP_COEFFICIENT(coeff_j);
00929   PPL_DIRTY_TEMP_COEFFICIENT(num);
00930   PPL_DIRTY_TEMP_COEFFICIENT(den);
00931   Linear_Expression le = expr;
00932   // Boolean to keep track of a variable `v' in expression `le'.
00933   // If we can replace `v' by an expression using variables other
00934   // than `v' and are already in `le', then this is set to true.
00935   bool constant_v = false;
00936 
00937   typedef typename OR_Matrix<N>::const_row_iterator Row_Iterator;
00938   typedef typename OR_Matrix<N>::const_row_reference_type Row_Reference;
00939 
00940   const Row_Iterator m_begin = matrix.row_begin();
00941   const Row_Iterator m_end = matrix.row_end();
00942 
00943   PPL_DIRTY_TEMP_COEFFICIENT(val_den);
00944   val_den = 1;
00945 
00946   for (Row_Iterator i_iter = m_begin; i_iter != m_end; i_iter += 2) {
00947     constant_v = false;
00948     dimension_type i = i_iter.index();
00949     const Variable v(i/2);
00950     coeff = le.coefficient(v);
00951     if (coeff == 0) {
00952       constant_v = true;
00953       continue;
00954     }
00955     // We check the unary constraints.
00956     Row_Reference m_i = *i_iter;
00957     Row_Reference m_ii = *(i_iter+1);
00958     const N& m_i_ii = m_i[i+1];
00959     const N& m_ii_i = m_ii[i];
00960     if ((!is_plus_infinity(m_i_ii) && !is_plus_infinity(m_ii_i))
00961         && (is_additive_inverse(m_i_ii, m_ii_i))) {
00962       // If `v' is constant, replace it in `le' by the value.
00963       numer_denom(m_i_ii, num, den);
00964       den *= 2;
00965       le -= coeff*v;
00966       le *= den;
00967       le -= num*coeff;
00968       val_den *= den;
00969       constant_v = true;
00970       continue;
00971     }
00972     // Check the octagonal constraints between `v' and the other dimensions
00973     // that have non-zero coefficient in `le'.
00974     else {
00975       PPL_ASSERT(!constant_v);
00976       using namespace Implementation::Octagonal_Shapes;
00977       const dimension_type ci = coherent_index(i);
00978       for (Row_Iterator j_iter = i_iter; j_iter != m_end; j_iter += 2) {
00979         dimension_type j = j_iter.index();
00980         const Variable vj(j/2);
00981         coeff_j = le.coefficient(vj);
00982         if (coeff_j == 0)
00983           // The coefficient in `le' is 0, so do nothing.
00984           continue;
00985         const dimension_type cj = coherent_index(j);
00986         const dimension_type cjj = coherent_index(j+1);
00987 
00988         Row_Reference m_j = *(m_begin + j);
00989         Row_Reference m_cj = *(m_begin + cj);
00990         const N& m_j_i = m_j[i];
00991         const N& m_i_j = m_cj[ci];
00992         if ((!is_plus_infinity(m_i_j) && !is_plus_infinity(m_j_i))
00993             && (is_additive_inverse(m_i_j, m_j_i))) {
00994           // The coefficient for `vj' in `le' is not 0
00995           // and the constraint with `v' is an equality.
00996           // So apply this equality to eliminate `v' in `le'.
00997           numer_denom(m_i_j, num, den);
00998           le -= coeff*v;
00999           le += coeff*vj;
01000           le *= den;
01001           le -= num*coeff;
01002           val_den *= den;
01003           constant_v = true;
01004           break;
01005         }
01006 
01007         m_j = *(m_begin + j + 1);
01008         m_cj = *(m_begin + cjj);
01009         const N& m_j_i1 = m_j[i];
01010         const N& m_i_j1 = m_cj[ci];
01011         if ((!is_plus_infinity(m_i_j1) && !is_plus_infinity(m_j_i1))
01012             && (is_additive_inverse(m_i_j1, m_j_i1))) {
01013           // The coefficient for `vj' in `le' is not 0
01014           // and the constraint with `v' is an equality.
01015           // So apply this equality to eliminate `v' in `le'.
01016           numer_denom(m_i_j1, num, den);
01017           le -= coeff*v;
01018           le -= coeff*vj;
01019           le *= den;
01020           le -= num*coeff;
01021           val_den *= den;
01022           constant_v = true;
01023           break;
01024         }
01025       }
01026       if (!constant_v)
01027         // The expression `expr' is not constant.
01028         return false;
01029     }
01030   }
01031   if (!constant_v)
01032     // The expression `expr' is not constant.
01033     return false;
01034 
01035   // The expression 'expr' is constant.
01036   freq_n = 0;
01037   freq_d = 1;
01038 
01039   // Reduce `val_n' and `val_d'.
01040   normalize2(le.inhomogeneous_term(), val_den, val_n, val_d);
01041   return true;
01042 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image ( const Linear_Expression lhs,
Relation_Symbol  relsym,
const Linear_Expression rhs 
) [inline]

Assigns to *this the image of *this with respect to the generalized affine transfer function $\mathrm{lhs}' \relsym \mathrm{rhs}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym.

Parameters:
lhs The left hand side affine expression.
relsym The relation symbol.
rhs The right hand side affine expression.
Exceptions:
std::invalid_argument Thrown if *this is dimension-incompatible with lhs or rhs or if relsym is a strict relation symbol.

Definition at line 5403 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().

05405                                                                            {
05406   // Dimension-compatibility checks.
05407   // The dimension of `lhs' should not be greater than the dimension
05408   // of `*this'.
05409   dimension_type lhs_space_dim = lhs.space_dimension();
05410   if (space_dim < lhs_space_dim)
05411     throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
05412                                  "e1", lhs);
05413 
05414   // The dimension of `rhs' should not be greater than the dimension
05415   // of `*this'.
05416   const dimension_type rhs_space_dim = rhs.space_dimension();
05417   if (space_dim < rhs_space_dim)
05418     throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
05419                                  "e2", rhs);
05420 
05421   // Strict relation symbols are not admitted for octagons.
05422   if (relsym == LESS_THAN || relsym == GREATER_THAN)
05423     throw_generic("generalized_affine_image(e1, r, e2)",
05424                   "r is a strict relation symbol and "
05425                   "*this is an Octagonal_Shape");
05426 
05427   strong_closure_assign();
05428   // The image of an empty octagon is empty.
05429   if (marked_empty())
05430     return;
05431 
05432   // Number of non-zero coefficients in `lhs': will be set to
05433   // 0, 1, or 2, the latter value meaning any value greater than 1.
05434   dimension_type t_lhs = 0;
05435   // Index of the last non-zero coefficient in `lhs', if any.
05436   dimension_type j_lhs = 0;
05437 
05438   // Compute the number of the non-zero components of `lhs'.
05439   for (dimension_type i = lhs_space_dim; i-- > 0; )
05440     if (lhs.coefficient(Variable(i)) != 0) {
05441       if (t_lhs++ == 1)
05442         break;
05443       else
05444         j_lhs = i;
05445     }
05446 
05447   const Coefficient& b_lhs = lhs.inhomogeneous_term();
05448 
05449   if (t_lhs == 0) {
05450     // `lhs' is a constant.
05451     // In principle, it is sufficient to add the constraint `lhs relsym rhs'.
05452     // Note that this constraint is an octagonal difference if `t_rhs <= 1'
05453     // or `t_rhs > 1' and `rhs == a*v - a*w + b_rhs' or
05454     // `rhs == a*v + a*w + b_rhs'. If `rhs' is of a
05455     // more general form, it will be simply ignored.
05456     // TODO: if it is not an octagonal difference, should we compute
05457     // approximations for this constraint?
05458     switch (relsym) {
05459     case LESS_OR_EQUAL:
05460       refine_no_check(lhs <= rhs);
05461       break;
05462     case EQUAL:
05463       refine_no_check(lhs == rhs);
05464       break;
05465     case GREATER_OR_EQUAL:
05466       refine_no_check(lhs >= rhs);
05467       break;
05468     default:
05469       // We already dealt with the other cases.
05470       throw std::runtime_error("PPL internal error");
05471     }
05472   }
05473 
05474   else if (t_lhs == 1) {
05475     // Here `lhs == a_lhs * v + b_lhs'.
05476     // Independently from the form of `rhs', we can exploit the
05477     // method computing generalized affine images for a single variable.
05478     Variable v(j_lhs);
05479     // Compute a sign-corrected relation symbol.
05480     const Coefficient& den = lhs.coefficient(v);
05481     Relation_Symbol new_relsym = relsym;
05482     if (den < 0) {
05483       if (relsym == LESS_OR_EQUAL)
05484         new_relsym = GREATER_OR_EQUAL;
05485       else if (relsym == GREATER_OR_EQUAL)
05486         new_relsym = LESS_OR_EQUAL;
05487     }
05488     Linear_Expression expr = rhs - b_lhs;
05489     generalized_affine_image(v, new_relsym, expr, den);
05490   }
05491   else {
05492     // Here `lhs' is of the general form, having at least two variables.
05493     // Compute the set of variables occurring in `lhs'.
05494     bool lhs_vars_intersects_rhs_vars = false;
05495     std::vector<Variable> lhs_vars;
05496     for (dimension_type i = lhs_space_dim; i-- > 0; )
05497       if (lhs.coefficient(Variable(i)) != 0) {
05498         lhs_vars.push_back(Variable(i));
05499         if (rhs.coefficient(Variable(i)) != 0)
05500           lhs_vars_intersects_rhs_vars = true;
05501       }
05502 
05503     if (!lhs_vars_intersects_rhs_vars) {
05504       // `lhs' and `rhs' variables are disjoint.
05505       // Existentially quantify all variables in the lhs.
05506       for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
05507         dimension_type lhs_vars_i = lhs_vars[i].id();
05508         forget_all_octagonal_constraints(lhs_vars_i);
05509       }
05510       // Constrain the left hand side expression so that it is related to
05511       // the right hand side expression as dictated by `relsym'.
05512       // TODO: if the following constraint is NOT an octagonal difference,
05513       // it will be simply ignored. Should we compute approximations for it?
05514       switch (relsym) {
05515       case LESS_OR_EQUAL:
05516         refine_no_check(lhs <= rhs);
05517         break;
05518       case EQUAL:
05519         refine_no_check(lhs == rhs);
05520         break;
05521       case GREATER_OR_EQUAL:
05522         refine_no_check(lhs >= rhs);
05523         break;
05524       default:
05525         // We already dealt with the other cases.
05526         throw std::runtime_error("PPL internal error");
05527       }
05528     }
05529     else {
05530       // Some variables in `lhs' also occur in `rhs'.
05531 
05532 #if 1 // Simplified computation (see the TODO note below).
05533 
05534       for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
05535         dimension_type lhs_vars_i = lhs_vars[i].id();
05536         forget_all_octagonal_constraints(lhs_vars_i);
05537       }
05538 
05539 #else // Currently unnecessarily complex computation.
05540 
05541       // More accurate computation that is worth doing only if
05542       // the following TODO note is accurately dealt with.
05543 
05544       // To ease the computation, we add an additional dimension.
05545       const Variable new_var = Variable(space_dim);
05546       add_space_dimensions_and_embed(1);
05547       // Constrain the new dimension to be equal to `rhs'.
05548       // NOTE: calling affine_image() instead of refine_no_check()
05549       // ensures some approximation is tried even when the constraint
05550       // is not an octagonal constraint.
05551       affine_image(new_var, rhs);
05552       // Existentially quantify all variables in the lhs.
05553       // NOTE: enforce strong closure for precision.
05554       strong_closure_assign();
05555       PPL_ASSERT(!marked_empty());
05556       for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
05557         dimension_type lhs_vars_i = lhs_vars[i].id();
05558         forget_all_octagonal_constraints(lhs_vars_i);
05559       }
05560       // Constrain the new dimension so that it is related to
05561       // the left hand side as dictated by `relsym'.
05562       // TODO: each one of the following constraints is definitely NOT
05563       // an octagonal difference (since it has 3 variables at least).
05564       // Thus, the method refine_no_check() will simply ignore it.
05565       // Should we compute approximations for this constraint?
05566       switch (relsym) {
05567       case LESS_OR_EQUAL:
05568         refine_no_check(lhs <= new_var);
05569         break;
05570       case EQUAL:
05571         refine_no_check(lhs == new_var);
05572         break;
05573       case GREATER_OR_EQUAL:
05574         refine_no_check(lhs >= new_var);
05575         break;
05576       default:
05577         // We already dealt with the other cases.
05578         throw std::runtime_error("PPL internal error");
05579       }
05580       // Remove the temporarily added dimension.
05581       remove_higher_space_dimensions(space_dim-1);
05582 #endif // Currently unnecessarily complex computation.
05583     }
05584   }
05585 
05586   PPL_ASSERT(OK());
05587 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image ( Variable  var,
Relation_Symbol  relsym,
const Linear_Expression expr,
Coefficient_traits::const_reference  denominator = Coefficient_one() 
) [inline]

Assigns to *this the image of *this with respect to the generalized affine transfer function $\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym.

Parameters:
var The left hand side variable of the generalized affine transfer function.
relsym The relation symbol.
expr The numerator of the right hand side affine expression.
denominator The denominator of the right hand side affine expression.
Exceptions:
std::invalid_argument Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a dimension of *this or if relsym is a strict relation symbol.

Definition at line 4914 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::PLUS_INFINITY, PPL_DIRTY_TEMP_COEFFICIENT, and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image().

04917                                                                           {
04918   // The denominator cannot be zero.
04919   if (denominator == 0)
04920     throw_generic("generalized_affine_image(v, r, e, d)", "d == 0");
04921 
04922   // Dimension-compatibility checks.
04923   // The dimension of `expr' should not be greater than the dimension
04924   // of `*this'.
04925   const dimension_type expr_space_dim = expr.space_dimension();
04926   if (space_dim < expr_space_dim)
04927     throw_dimension_incompatible("generalized_affine_image(v, r, e, d)", "e",
04928                                  expr);
04929 
04930   // `var' should be one of the dimensions of the octagon.
04931   dimension_type var_id = var.id();
04932   if (space_dim < var_id + 1)
04933     throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
04934                                  var_id + 1);
04935 
04936   // The relation symbol cannot be a strict relation symbol.
04937   if (relsym == LESS_THAN || relsym == GREATER_THAN)
04938     throw_generic("generalized_affine_image(v, r, e, d)",
04939                   "r is a strict relation symbol and "
04940                   "*this is an Octagonal_Shape");
04941 
04942   if (relsym == EQUAL) {
04943     // The relation symbol is "=":
04944     // this is just an affine image computation.
04945     affine_image(var, expr, denominator);
04946     return;
04947   }
04948 
04949   strong_closure_assign();
04950   // The image of an empty octagon is empty too.
04951   if (marked_empty())
04952     return;
04953 
04954   // Number of non-zero coefficients in `expr': will be set to
04955   // 0, 1, or 2, the latter value meaning any value greater than 1.
04956   dimension_type t = 0;
04957   // Variable-index of the last non-zero coefficient in `expr', if any.
04958   dimension_type w_id = 0;
04959 
04960   // Get information about the number of non-zero coefficients in `expr'.
04961   // The `expr' must not be in two or plus variables.
04962   for (dimension_type i = expr_space_dim; i-- > 0; )
04963     if (expr.coefficient(Variable(i)) != 0) {
04964       if (t++ == 1)
04965         break;
04966       else
04967         w_id = i;
04968     }
04969 
04970   typedef typename OR_Matrix<N>::row_iterator Row_Iterator;
04971   typedef typename OR_Matrix<N>::row_reference_type Row_Reference;
04972   typedef typename OR_Matrix<N>::const_row_iterator Row_iterator;
04973   typedef typename OR_Matrix<N>::const_row_reference_type Row_reference;
04974 
04975   const Row_Iterator m_begin = matrix.row_begin();
04976   const Row_Iterator m_end = matrix.row_end();
04977   const dimension_type n_var = 2*var_id;
04978   const Coefficient& b = expr.inhomogeneous_term();
04979   PPL_DIRTY_TEMP_COEFFICIENT(minus_den);
04980   neg_assign_r(minus_den, denominator, ROUND_NOT_NEEDED);
04981 
04982   // `w' is the variable with index `w_id'.
04983   // Now we know the form of `expr':
04984   // - If t == 0, then expr == b, with `b' a constant;
04985   // - If t == 1, then expr == a*w + b, where `w' can be `v' or another
04986   //   variable; in this second case we have to check whether `a' is
04987   //   equal to `denominator' or `-denominator', since otherwise we have
04988   //   to fall back on the general form;
04989   // - If t == 2, the `expr' is of the general form.
04990 
04991   if (t == 0) {
04992     // Case 1: expr = b.
04993     PPL_DIRTY_TEMP_COEFFICIENT(two_b);
04994     two_b = 2*b;
04995     // Remove all constraints on `var'.
04996     forget_all_octagonal_constraints(var_id);
04997     // Strong closure is lost.
04998     reset_strongly_closed();
04999     switch (relsym) {
05000     case LESS_OR_EQUAL:
05001       // Add the constraint `var <= b/denominator'.
05002       add_octagonal_constraint(n_var+1, n_var, two_b, denominator);
05003       break;
05004     case GREATER_OR_EQUAL:
05005       // Add the constraint `var >= n/denominator',
05006       // i.e., `-var <= -b/denominator'.
05007       add_octagonal_constraint(n_var, n_var+1, two_b, minus_den);
05008       break;
05009     default:
05010       // We already dealt with the other cases.
05011       throw std::runtime_error("PPL internal error");
05012     }
05013     PPL_ASSERT(OK());
05014     return;
05015   }
05016 
05017   if (t == 1) {
05018     // The one and only non-zero homogeneous coefficient in `expr'.
05019     const Coefficient& w_coeff = expr.coefficient(Variable(w_id));
05020     if (w_coeff == denominator || w_coeff == minus_den) {
05021       // Case 2: expr == w_coeff*w + b, with w_coeff == +/- denominator.
05022       switch (relsym) {
05023       case LESS_OR_EQUAL:
05024         {
05025           PPL_DIRTY_TEMP(N, d);
05026           div_round_up(d, b, denominator);
05027           if (w_id == var_id) {
05028             // Here `expr' is of the form: +/- denominator * v + b.
05029             // Strong closure is not preserved.
05030             reset_strongly_closed();
05031             if (w_coeff == denominator) {
05032               // Translate all the constraints of the form `v - w <= cost'
05033               // into the constraint `v - w <= cost + b/denominator';
05034               // forget each constraint `w - v <= cost1'.
05035               Row_Iterator m_iter = m_begin + n_var;
05036               Row_Reference m_v = *m_iter;
05037               N& m_v_cv = m_v[n_var+1];
05038               ++m_iter;
05039               Row_Reference m_cv = *m_iter;
05040               N& m_cv_v = m_cv[n_var];
05041               ++m_iter;
05042               // NOTE: delay update of m_v_cv and m_cv_v.
05043               for ( ; m_iter != m_end; ++m_iter) {
05044                 Row_Reference m_i = *m_iter;
05045                 N& m_i_v = m_i[n_var];
05046                 add_assign_r(m_i_v, m_i_v, d, ROUND_UP);
05047                 assign_r(m_i[n_var+1], PLUS_INFINITY, ROUND_NOT_NEEDED);
05048               }
05049               for (dimension_type k = n_var; k-- > 0; ) {
05050                 assign_r(m_v[k], PLUS_INFINITY, ROUND_NOT_NEEDED);
05051                 add_assign_r(m_cv[k], m_cv[k], d, ROUND_UP);
05052               }
05053               mul_2exp_assign_r(d, d, 1, ROUND_UP);
05054               add_assign_r(m_cv_v, m_cv_v, d, ROUND_UP);
05055               assign_r(m_v_cv, PLUS_INFINITY, ROUND_NOT_NEEDED);
05056             }
05057             else {
05058               // Here `w_coeff == -denominator'.
05059               // `expr' is of the form: -a*var + b.
05060               N& m_v_cv = matrix[n_var][n_var+1];
05061               mul_2exp_assign_r(d, d, 1, ROUND_UP);
05062               add_assign_r(matrix[n_var+1][n_var], m_v_cv, d, ROUND_UP);
05063               assign_r(m_v_cv, PLUS_INFINITY, ROUND_NOT_NEEDED);
05064               forget_binary_octagonal_constraints(var_id);
05065             }
05066           }
05067           else {
05068             // Here `w != v', so that `expr' is the form
05069             // +/- denominator*w + b.
05070             // Remove all constraints on `v'.
05071             forget_all_octagonal_constraints(var_id);
05072             const dimension_type n_w = 2*w_id;
05073             if (w_coeff == denominator) {
05074               // Add the new constraint `v - w <= b/denominator'.
05075               if (var_id < w_id)
05076                 add_octagonal_constraint(n_w, n_var, b, denominator);
05077               else
05078                 add_octagonal_constraint(n_var+1, n_w+1, b, denominator);
05079             }
05080             else {
05081               // Add the new constraint `v + w <= b/denominator'.
05082               if (var_id < w_id)
05083                 add_octagonal_constraint(n_w+1, n_var, b, denominator);
05084               else
05085                 add_octagonal_constraint(n_var+1, n_w, b, denominator);
05086             }
05087           }
05088           break;
05089         }
05090 
05091       case GREATER_OR_EQUAL:
05092         {
05093           PPL_DIRTY_TEMP(N, d);
05094           div_round_up(d, b, minus_den);
05095           if (w_id == var_id) {
05096             // Here `expr' is of the form: +/- denominator * v + b.
05097             // Strong closure is not preserved.
05098             reset_strongly_closed();
05099             if (w_coeff == denominator) {
05100               // Translate each constraint `w - v <= cost'
05101               // into the constraint `w - v <= cost - b/denominator';
05102               // forget each constraint `v - w <= cost1'.
05103               Row_Iterator m_iter = m_begin + n_var;
05104               Row_Reference m_v = *m_iter;
05105               N& m_v_cv = m_v[n_var+1];
05106               ++m_iter;
05107               Row_Reference m_cv = *m_iter;
05108               N& m_cv_v = m_cv[n_var];
05109               ++m_iter;
05110               // NOTE: delay update of m_v_cv and m_cv_v.
05111               for ( ; m_iter != m_end; ++m_iter) {
05112                 Row_Reference m_i = *m_iter;
05113                 assign_r(m_i[n_var], PLUS_INFINITY, ROUND_NOT_NEEDED);
05114                 add_assign_r(m_i[n_var+1], m_i[n_var+1], d, ROUND_UP);
05115               }
05116               for (dimension_type k = n_var; k-- > 0; ) {
05117                 add_assign_r(m_v[k], m_v[k], d, ROUND_UP);
05118                 assign_r(m_cv[k], PLUS_INFINITY, ROUND_NOT_NEEDED);
05119               }
05120               mul_2exp_assign_r(d, d, 1, ROUND_UP);
05121               add_assign_r(m_v_cv, m_v_cv, d, ROUND_UP);
05122               assign_r(m_cv_v, PLUS_INFINITY, ROUND_NOT_NEEDED);
05123             }
05124             else {
05125               // Here `w_coeff == -denominator'.
05126               // `expr' is of the form: -a*var + b.
05127               N& m_cv_v = matrix[n_var+1][n_var];
05128               mul_2exp_assign_r(d, d, 1, ROUND_UP);
05129               add_assign_r(matrix[n_var][n_var+1], m_cv_v, d, ROUND_UP);
05130               assign_r(m_cv_v, PLUS_INFINITY, ROUND_NOT_NEEDED);
05131               forget_binary_octagonal_constraints(var_id);
05132             }
05133           }
05134           else {
05135             // Here `w != v', so that `expr' is of the form
05136             // +/-denominator * w + b, with `w != v'.
05137             // Remove all constraints on `v'.
05138             forget_all_octagonal_constraints(var_id);
05139             const dimension_type n_w = 2*w_id;
05140             // We have got an expression of the following form:
05141             // var1 + n, with `var1' != `var'.
05142             // We remove all constraints of the form `var (+/- var1) >= const'
05143             // and we add the new constraint `var +/- var1 >= n/denominator'.
05144             if (w_coeff == denominator) {
05145               // Add the new constraint `var - w >= b/denominator',
05146               // i.e., `w - var <= -b/denominator'.
05147               if (var_id < w_id)
05148                 add_octagonal_constraint(n_w+1, n_var+1, b, minus_den);
05149               else
05150                 add_octagonal_constraint(n_var, n_w, b, minus_den);
05151             }
05152             else {
05153               // Add the new constraint `var + w >= b/denominator',
05154               // i.e., `-w - var <= -b/denominator'.
05155               if (var_id < w_id)
05156                 add_octagonal_constraint(n_w, n_var+1, b, minus_den);
05157               else
05158                 add_octagonal_constraint(n_var, n_w+1, b, minus_den);
05159             }
05160           }
05161           break;
05162         }
05163 
05164       default:
05165         // We already dealt with the other cases.
05166         throw std::runtime_error("PPL internal error");
05167       }
05168       PPL_ASSERT(OK());
05169       return;
05170     }
05171   }
05172 
05173   // General case.
05174   // Either t == 2, so that
05175   // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
05176   // or t == 1, expr == a*w + b, but a <> +/- denominator.
05177   // We will remove all the constraints on `v' and add back
05178   // a constraint providing an upper or a lower bound for `v'
05179   // (depending on `relsym').
05180   const bool is_sc = (denominator > 0);
05181   PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
05182   neg_assign(minus_b, b);
05183   const Coefficient& sc_b = is_sc ? b : minus_b;
05184   const Coefficient& minus_sc_b = is_sc ? minus_b : b;
05185   const Coefficient& sc_den = is_sc ? denominator : minus_den;
05186   const Coefficient& minus_sc_den = is_sc ? minus_den : denominator;
05187   // NOTE: here, for optimization purposes, `minus_expr' is only assigned
05188   // when `denominator' is negative. Do not use it unless you are sure
05189   // it has been correctly assigned.
05190   Linear_Expression minus_expr;
05191   if (!is_sc)
05192     minus_expr = -expr;
05193   const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
05194 
05195   PPL_DIRTY_TEMP(N, sum);
05196   // Index of variable that is unbounded in `this->matrix'.
05197   PPL_UNINITIALIZED(dimension_type, pinf_index);
05198   // Number of unbounded variables found.
05199   dimension_type pinf_count = 0;
05200 
05201   switch (relsym) {
05202   case LESS_OR_EQUAL:
05203     {
05204       // Compute an upper approximation for `sc_expr' into `sum'.
05205 
05206       // Approximate the inhomogeneous term.
05207       assign_r(sum, sc_b, ROUND_UP);
05208       // Approximate the homogeneous part of `sc_expr'.
05209       PPL_DIRTY_TEMP(N, coeff_i);
05210       PPL_DIRTY_TEMP(N, approx_i);
05211       PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
05212       // Note: indices above `w' can be disregarded, as they all have
05213       // a zero coefficient in `sc_expr'.
05214       for (Row_iterator m_iter = m_begin, m_iter_end = m_iter + (2*w_id) + 2;
05215            m_iter != m_iter_end; ) {
05216         const dimension_type n_i = m_iter.index();
05217         const dimension_type id = n_i/2;
05218         Row_reference m_i = *m_iter;
05219         ++m_iter;
05220         Row_reference m_ci = *m_iter;
05221         ++m_iter;
05222         const Coefficient& sc_i = sc_expr.coefficient(Variable(id));
05223         const int sign_i = sgn(sc_i);
05224         if (sign_i == 0)
05225           continue;
05226         // Choose carefully: we are approximating `sc_expr'.
05227         const N& double_approx_i = (sign_i > 0) ? m_ci[n_i] : m_i[n_i+1];
05228         if (is_plus_infinity(double_approx_i)) {
05229           if (++pinf_count > 1)
05230             break;
05231           pinf_index = id;
05232           continue;
05233         }
05234         if (sign_i > 0)
05235           assign_r(coeff_i, sc_i, ROUND_UP);
05236         else {
05237           neg_assign(minus_sc_i, sc_i);
05238           assign_r(coeff_i, minus_sc_i, ROUND_UP);
05239         }
05240         div_2exp_assign_r(approx_i, double_approx_i, 1, ROUND_UP);
05241         add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
05242       }
05243       // Remove all constraints on `v'.
05244       forget_all_octagonal_constraints(var_id);
05245       reset_strongly_closed();
05246       // Return immediately if no approximation could be computed.
05247       if (pinf_count > 1) {
05248         PPL_ASSERT(OK());
05249         return;
05250       }
05251 
05252       // Divide by the (sign corrected) denominator (if needed).
05253       if (sc_den != 1) {
05254         // Before computing the quotient, the denominator should be
05255         // approximated towards zero. Since `sc_den' is known to be
05256         // positive, this amounts to rounding downwards, which is
05257         // achieved as usual by rounding upwards
05258         // `minus_sc_den' and negating again the result.
05259         PPL_DIRTY_TEMP(N, down_sc_den);
05260         assign_r(down_sc_den, minus_sc_den, ROUND_UP);
05261         neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
05262         div_assign_r(sum, sum, down_sc_den, ROUND_UP);
05263       }
05264 
05265       if (pinf_count == 0) {
05266         // Add the constraint `v <= pos_sum'.
05267         PPL_DIRTY_TEMP(N, double_sum);
05268         mul_2exp_assign_r(double_sum, sum, 1, ROUND_UP);
05269         matrix[n_var+1][n_var] = double_sum;
05270         // Deduce constraints of the form `v +/- u', where `u != v'.
05271         deduce_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, sum);
05272       }
05273       else if (pinf_count == 1)
05274         if (pinf_index != var_id) {
05275           const Coefficient& pi = expr.coefficient(Variable(pinf_index));
05276           if (pi == denominator ) {
05277             // Add the constraint `v - pinf_index <= sum'.
05278             if (var_id < pinf_index)
05279               matrix[2*pinf_index][n_var] = sum;
05280             else
05281               matrix[n_var+1][2*pinf_index+1] = sum;
05282           }
05283           else {
05284             if (pi == minus_den) {
05285               // Add the constraint `v + pinf_index <= sum'.
05286               if (var_id < pinf_index)
05287                 matrix[2*pinf_index+1][n_var] = sum;
05288               else
05289                 matrix[n_var+1][2*pinf_index] = sum;
05290             }
05291           }
05292         }
05293       break;
05294     }
05295 
05296   case GREATER_OR_EQUAL:
05297     {
05298       // Compute an upper approximation for `-sc_expr' into `sum'.
05299       // Note: approximating `-sc_expr' from above and then negating the
05300       // result is the same as approximating `sc_expr' from below.
05301 
05302       // Approximate the inhomogeneous term.
05303       assign_r(sum, minus_sc_b, ROUND_UP);
05304       PPL_DIRTY_TEMP(N, coeff_i);
05305       PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
05306       PPL_DIRTY_TEMP(N, approx_i);
05307       // Approximate the homogeneous part of `-sc_expr'.
05308       for (Row_iterator m_iter = m_begin, m_iter_end = m_iter + (2*w_id) + 2;
05309            m_iter != m_iter_end; ) {
05310         const dimension_type n_i = m_iter.index();
05311         const dimension_type id = n_i/2;
05312         Row_reference m_i = *m_iter;
05313         ++m_iter;
05314         Row_reference m_ci = *m_iter;
05315         ++m_iter;
05316         const Coefficient& sc_i = sc_expr.coefficient(Variable(id));
05317         const int sign_i = sgn(sc_i);
05318         if (sign_i == 0)
05319           continue;
05320         // Choose carefully: we are approximating `-sc_expr'.
05321         const N& double_approx_i = (sign_i > 0) ? m_i[n_i+1] : m_ci[n_i];
05322         if (is_plus_infinity(double_approx_i)) {
05323           if (++pinf_count > 1)
05324             break;
05325           pinf_index = id;
05326           continue;
05327         }
05328         if (sign_i > 0)
05329           assign_r(coeff_i, sc_i, ROUND_UP);
05330         else {
05331           neg_assign(minus_sc_i, sc_i);
05332           assign_r(coeff_i, minus_sc_i, ROUND_UP);
05333         }
05334         div_2exp_assign_r(approx_i, double_approx_i, 1, ROUND_UP);
05335         add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
05336       }
05337 
05338       // Remove all constraints on `var'.
05339       forget_all_octagonal_constraints(var_id);
05340       reset_strongly_closed();
05341       // Return immediately if no approximation could be computed.
05342       if (pinf_count > 1) {
05343         PPL_ASSERT(OK());
05344         return;
05345       }
05346 
05347       // Divide by the (sign corrected) denominator (if needed).
05348       if (sc_den != 1) {
05349         // Before computing the quotient, the denominator should be
05350         // approximated towards zero. Since `sc_den' is known to be
05351         // positive, this amounts to rounding downwards, which is
05352         // achieved as usual by rounding upwards
05353         // `minus_sc_den' and negating again the result.
05354         PPL_DIRTY_TEMP(N, down_sc_den);
05355         assign_r(down_sc_den, minus_sc_den, ROUND_UP);
05356         neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
05357         div_assign_r(sum, sum, down_sc_den, ROUND_UP);
05358       }
05359 
05360       if (pinf_count == 0) {
05361         // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
05362         PPL_DIRTY_TEMP(N, double_sum);
05363         mul_2exp_assign_r(double_sum, sum, 1, ROUND_UP);
05364         matrix[n_var][n_var+1] = double_sum;
05365         // Deduce constraints of the form `-v +/- u', where `u != v'.
05366         deduce_minus_v_pm_u_bounds(var_id, pinf_index, sc_expr, sc_den, sum);
05367       }
05368       else if (pinf_count == 1)
05369         if (pinf_index != var_id) {
05370           const Coefficient& pi = expr.coefficient(Variable(pinf_index));
05371           if (pi == denominator) {
05372             // Add the constraint `v - pinf_index >= -sum',
05373             // i.e., `pinf_index - v <= sum'.
05374             if (pinf_index < var_id)
05375               matrix[n_var][2*pinf_index] = sum;
05376             else
05377               matrix[2*pinf_index+1][n_var+1] = sum;
05378           }
05379           else {
05380             if (pi == minus_den) {
05381               // Add the constraint `v + pinf_index >= -sum',
05382               // i.e., `-pinf_index - v <= sum'.
05383               if (pinf_index < var_id)
05384                 matrix[n_var][2*pinf_index+1] = sum;
05385               else
05386                 matrix[2*pinf_index][n_var+1] = sum;
05387             }
05388           }
05389         }
05390       break;
05391     }
05392 
05393   default:
05394     // We already dealt with the other cases.
05395     throw std::runtime_error("PPL internal error");
05396   }
05397   incremental_strong_closure_assign(var);
05398   PPL_ASSERT(OK());
05399 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage ( const Linear_Expression lhs,
Relation_Symbol  relsym,
const Linear_Expression rhs 
) [inline]

Assigns to *this the preimage of *this with respect to the generalized affine relation $\mathrm{lhs}' \relsym \mathrm{rhs}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym.

Parameters:
lhs The left hand side affine expression;
relsym The relation symbol;
rhs The right hand side affine expression.
Exceptions:
std::invalid_argument Thrown if *this is dimension-incompatible with lhs or rhs or if relsym is a strict relation symbol.

Definition at line 5956 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

05958                                                             {
05959   // Dimension-compatibility checks.
05960   // The dimension of `lhs' should not be greater than the dimension
05961   // of `*this'.
05962   dimension_type lhs_space_dim = lhs.space_dimension();
05963   if (space_dim < lhs_space_dim)
05964     throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)",
05965                                  "e1", lhs);
05966 
05967   // The dimension of `rhs' should not be greater than the dimension
05968   // of `*this'.
05969   const dimension_type rhs_space_dim = rhs.space_dimension();
05970   if (space_dim < rhs_space_dim)
05971     throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)",
05972                                  "e2", rhs);
05973 
05974   // Strict relation symbols are not admitted for octagons.
05975   if (relsym == LESS_THAN || relsym == GREATER_THAN)
05976     throw_generic("generalized_affine_preimage(e1, r, e2)",
05977                   "r is a strict relation symbol and "
05978                   "*this is an Octagonal_Shape");
05979 
05980   strong_closure_assign();
05981   // The image of an empty octagon is empty.
05982   if (marked_empty())
05983     return;
05984 
05985   // Number of non-zero coefficients in `lhs': will be set to
05986   // 0, 1, or 2, the latter value meaning any value greater than 1.
05987   dimension_type t_lhs = 0;
05988   // Index of the last non-zero coefficient in `lhs', if any.
05989   dimension_type j_lhs = 0;
05990 
05991   // Compute the number of the non-zero components of `lhs'.
05992   for (dimension_type i = lhs_space_dim; i-- > 0; )
05993     if (lhs.coefficient(Variable(i)) != 0) {
05994       if (t_lhs++ == 1)
05995         break;
05996       else
05997         j_lhs = i;
05998     }
05999 
06000   const Coefficient& b_lhs = lhs.inhomogeneous_term();
06001 
06002   // If all variables have a zero coefficient, then `lhs' is a constant:
06003   // in this case, preimage and image happen to be the same.
06004   if (t_lhs == 0) {
06005     generalized_affine_image(lhs, relsym, rhs);
06006     return;
06007   }
06008 
06009   else if (t_lhs == 1) {
06010     // Here `lhs == a_lhs * v + b_lhs'.
06011     // Independently from the form of `rhs', we can exploit the
06012     // method computing generalized affine preimages for a single variable.
06013     Variable v(j_lhs);
06014     // Compute a sign-corrected relation symbol.
06015     const Coefficient& den = lhs.coefficient(v);
06016     Relation_Symbol new_relsym = relsym;
06017     if (den < 0) {
06018       if (relsym == LESS_OR_EQUAL)
06019         new_relsym = GREATER_OR_EQUAL;
06020       else if (relsym == GREATER_OR_EQUAL)
06021         new_relsym = LESS_OR_EQUAL;
06022     }
06023     Linear_Expression expr = rhs - b_lhs;
06024     generalized_affine_preimage(v, new_relsym, expr, den);
06025   }
06026 
06027   else {
06028     // Here `lhs' is of the general form, having at least two variables.
06029     // Compute the set of variables occurring in `lhs'.
06030     bool lhs_vars_intersects_rhs_vars = false;
06031     std::vector<Variable> lhs_vars;
06032     for (dimension_type i = lhs_space_dim; i-- > 0; )
06033       if (lhs.coefficient(Variable(i)) != 0) {
06034         lhs_vars.push_back(Variable(i));
06035         if (rhs.coefficient(Variable(i)) != 0)
06036           lhs_vars_intersects_rhs_vars = true;
06037       }
06038 
06039     if (!lhs_vars_intersects_rhs_vars) {
06040       // `lhs' and `rhs' variables are disjoint.
06041       // Constrain the left hand side expression so that it is related to
06042       // the right hand side expression as dictated by `relsym'.
06043       // TODO: if the following constraint is NOT an octagonal difference,
06044       // it will be simply ignored. Should we compute approximations for it?
06045       switch (relsym) {
06046       case LESS_OR_EQUAL:
06047         refine_no_check(lhs <= rhs);
06048         break;
06049       case EQUAL:
06050         refine_no_check(lhs == rhs);
06051         break;
06052       case GREATER_OR_EQUAL:
06053         refine_no_check(lhs >= rhs);
06054         break;
06055       default:
06056         // We already dealt with the other cases.
06057         throw std::runtime_error("PPL internal error");
06058       }
06059 
06060       // Any image of an empty octagon is empty.
06061       if (is_empty())
06062         return;
06063       // Existentially quantify all variables in the lhs.
06064       for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
06065         dimension_type lhs_vars_i = lhs_vars[i].id();
06066         forget_all_octagonal_constraints(lhs_vars_i);
06067       }
06068     }
06069     else {
06070       // Some variables in `lhs' also occur in `rhs'.
06071 
06072       // More accurate computation that is worth doing only if
06073       // the following TODO note is accurately dealt with.
06074 
06075       // To ease the computation, we add an additional dimension.
06076       const Variable new_var = Variable(space_dim);
06077       add_space_dimensions_and_embed(1);
06078       // Constrain the new dimension to be equal to `rhs'.
06079       // NOTE: calling affine_image() instead of refine_no_check()
06080       // ensures some approximation is tried even when the constraint
06081       // is not an octagonal difference.
06082       affine_image(new_var, lhs);
06083       // Existentially quantify all variables in the lhs.
06084       // NOTE: enforce strong closure for precision.
06085       strong_closure_assign();
06086       PPL_ASSERT(!marked_empty());
06087       for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
06088         dimension_type lhs_vars_i = lhs_vars[i].id();
06089         forget_all_octagonal_constraints(lhs_vars_i);
06090       }
06091       // Constrain the new dimension so that it is related to
06092       // the left hand side as dictated by `relsym'.
06093       // Note: if `rhs == v + b_rhs' or `rhs == -v + b_rhs' or `rhs == b_rhs',
06094       // one of the following constraints will be added, because they
06095       // are octagonal differences.
06096       // Else the following constraints are NOT octagonal differences,
06097       // so the method refine_no_check() will ignore them.
06098       switch (relsym) {
06099       case LESS_OR_EQUAL:
06100         refine_no_check(new_var <= rhs);
06101         break;
06102       case EQUAL:
06103         refine_no_check(new_var == rhs);
06104         break;
06105       case GREATER_OR_EQUAL:
06106         refine_no_check(new_var >= rhs);
06107         break;
06108       default:
06109         // We already dealt with the other cases.
06110         throw std::runtime_error("PPL internal error");
06111       }
06112       // Remove the temporarily added dimension.
06113       remove_higher_space_dimensions(space_dim-1);
06114     }
06115   }
06116   PPL_ASSERT(OK());
06117 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage ( Variable  var,
Relation_Symbol  relsym,
const Linear_Expression expr,
Coefficient_traits::const_reference  denominator = Coefficient_one() 
) [inline]

Assigns to *this the preimage of *this with respect to the affine relation $\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym.

Parameters:
var The left hand side variable of the generalized affine transfer function.
relsym The relation symbol.
expr The numerator of the right hand side affine expression.
denominator The denominator of the right hand side affine expression.
Exceptions:
std::invalid_argument Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a dimension of *this or if relsym is a strict relation symbol.

Definition at line 5881 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::neg_assign(), PPL_DIRTY_TEMP_COEFFICIENT, and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage().

05885                                            {
05886   // The denominator cannot be zero.
05887   if (denominator == 0)
05888     throw_generic("generalized_affine_preimage(v, r, e, d)", "d == 0");
05889 
05890   // Dimension-compatibility checks.
05891   // The dimension of `expr' should not be greater than the dimension
05892   // of `*this'.
05893   const dimension_type expr_space_dim = expr.space_dimension();
05894   if (space_dim < expr_space_dim)
05895     throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
05896                                  "e", expr);
05897 
05898   // `var' should be one of the dimensions of the octagon.
05899   const dimension_type var_id = var.id();
05900   if (space_dim < var_id + 1)
05901     throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
05902                                  var_id + 1);
05903 
05904   // The relation symbol cannot be a strict relation symbol.
05905   if (relsym == LESS_THAN || relsym == GREATER_THAN)
05906     throw_generic("generalized_affine_preimage(v, r, e, d)",
05907                   "r is a strict relation symbol and "
05908                   "*this is an Octagonal_Shape");
05909 
05910   if (relsym == EQUAL) {
05911     // The relation symbol is "=":
05912     // this is just an affine preimage computation.
05913     affine_preimage(var, expr, denominator);
05914     return;
05915   }
05916 
05917   // The image of an empty octagon is empty too.
05918   strong_closure_assign();
05919   if (marked_empty())
05920     return;
05921 
05922   // Check whether the preimage of this affine relation can be easily
05923   // computed as the image of its inverse relation.
05924   const Coefficient& expr_v = expr.coefficient(var);
05925   if (expr_v != 0) {
05926     const Relation_Symbol reversed_relsym = (relsym == LESS_OR_EQUAL)
05927       ? GREATER_OR_EQUAL : LESS_OR_EQUAL;
05928     const Linear_Expression inverse
05929       = expr - (expr_v + denominator)*var;
05930     PPL_DIRTY_TEMP_COEFFICIENT(inverse_den);
05931     neg_assign(inverse_den, expr_v);
05932     const Relation_Symbol inverse_relsym
05933       = (sgn(denominator) == sgn(inverse_den)) ? relsym : reversed_relsym;
05934     generalized_affine_image(var, inverse_relsym, inverse, inverse_den);
05935     return;
05936   }
05937 
05938   // Here `var_coefficient == 0', so that the preimage cannot
05939   // be easily computed by inverting the affine relation.
05940   // Shrink the Octagonal_Shape by adding the constraint induced
05941   // by the affine relation.
05942   refine(var, relsym, expr, denominator);
05943 
05944   // If the shrunk OS is empty, its preimage is empty too; ...
05945   if (is_empty())
05946     return;
05947   // ...  otherwise, since the relation was not invertible,
05948   // we just forget all constraints on `var'.
05949   forget_all_octagonal_constraints(var_id);
05950   PPL_ASSERT(OK());
05951 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::get_limiting_octagon ( const Constraint_System cs,
Octagonal_Shape< T > &  limiting_octagon 
) const [inline, private]

Adds to limiting_octagon the octagonal differences in cs that are satisfied by *this.

Definition at line 3245 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Constraint::is_inequality(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::neg_assign(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), and Parma_Polyhedra_Library::Constraint_System::space_dimension().

03246                                                                 {
03247   const dimension_type cs_space_dim = cs.space_dimension();
03248   // Private method: the caller has to ensure the following.
03249   PPL_ASSERT(cs_space_dim <= space_dim);
03250 
03251   strong_closure_assign();
03252   bool is_oct_changed = false;
03253 
03254   // Allocate temporaries outside of the loop.
03255   PPL_DIRTY_TEMP_COEFFICIENT(coeff);
03256   PPL_DIRTY_TEMP_COEFFICIENT(term);
03257   PPL_DIRTY_TEMP(N, d);
03258 
03259   for (Constraint_System::const_iterator cs_i = cs.begin(),
03260          cs_end = cs.end(); cs_i != cs_end; ++cs_i) {
03261     const Constraint& c = *cs_i;
03262     dimension_type num_vars = 0;
03263     dimension_type i = 0;
03264     dimension_type j = 0;
03265     // Constraints that are not octagonal differences are ignored.
03266     if (!extract_octagonal_difference(c, cs_space_dim, num_vars, i, j,
03267                                       coeff, term))
03268       continue;
03269 
03270     typedef typename OR_Matrix<N>::const_row_iterator Row_iterator;
03271     typedef typename OR_Matrix<N>::const_row_reference_type Row_reference;
03272     typedef typename OR_Matrix<N>::row_iterator Row_Iterator;
03273     typedef typename OR_Matrix<N>::row_reference_type Row_Reference;
03274     Row_iterator m_begin = matrix.row_begin();
03275     // Select the cell to be modified for the "<=" part of the constraint.
03276     Row_iterator i_iter = m_begin + i;
03277     Row_reference m_i = *i_iter;
03278     OR_Matrix<N>& lo_mat = limiting_octagon.matrix;
03279     Row_Iterator lo_iter = lo_mat.row_begin() + i;
03280     Row_Reference lo_m_i = *lo_iter;
03281     N& lo_m_i_j = lo_m_i[j];
03282     if (coeff < 0)
03283       neg_assign(coeff);
03284     // Compute the bound for `m_i_j', rounding towards plus infinity.
03285     div_round_up(d, term, coeff);
03286     if (m_i[j] <= d)
03287       if (c.is_inequality()) {
03288         if (lo_m_i_j > d) {
03289           lo_m_i_j = d;
03290           is_oct_changed = true;
03291         }
03292         else {
03293           // Select the right row of the cell.
03294           if (i % 2 == 0) {
03295             ++i_iter;
03296             ++lo_iter;
03297           }
03298           else {
03299             --i_iter;
03300             --lo_iter;
03301           }
03302           Row_reference m_ci = *i_iter;
03303           Row_Reference lo_m_ci = *lo_iter;
03304           // Select the right column of the cell.
03305           using namespace Implementation::Octagonal_Shapes;
03306           dimension_type cj = coherent_index(j);
03307           N& lo_m_ci_cj = lo_m_ci[cj];
03308           neg_assign(term);
03309           div_round_up(d, term, coeff);
03310           if (m_ci[cj] <= d && lo_m_ci_cj > d) {
03311             lo_m_ci_cj = d;
03312             is_oct_changed = true;
03313           }
03314         }
03315       }
03316   }
03317   // In general, adding a constraint does not preserve the strongly
03318   // closure of the octagon.
03319   if (is_oct_changed && limiting_octagon.marked_strongly_closed())
03320     limiting_octagon.reset_strongly_closed();
03321 }

template<typename T >
int32_t Parma_Polyhedra_Library::Octagonal_Shape< T >::hash_code (  )  const [inline]

Returns a 32-bit hash code for *this.

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

Definition at line 819 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension().

00819                                     {
00820   return space_dimension() & 0x7fffffff;
00821 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign ( Variable  var  )  const [inline, private]

Incrementally computes strong closure, assuming that only constraints affecting variable var need to be considered.

Note:
It is assumed that *this, which was strongly closed, has only been modified by adding constraints affecting variable var. If this assumption is not satisfied, i.e., if a non-redundant constraint not affecting variable var has been added, the behavior is undefined. Worst-case complexity is $O(n^2)$.

Definition at line 2176 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::min_assign(), Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_coherence_assign().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign().

02176                                                             {
02177   // `var' should be one of the dimensions of the octagon.
02178   if (var.id() >= space_dim)
02179     throw_dimension_incompatible("incremental_strong_closure_assign(v)",
02180                                  var.id());
02181 
02182   // Do something only if necessary.
02183   if (marked_empty() || marked_strongly_closed())
02184     return;
02185 
02186   Octagonal_Shape& x = const_cast<Octagonal_Shape<T>&>(*this);
02187 
02188   typedef typename OR_Matrix<N>::row_iterator Row_Iterator;
02189   typedef typename OR_Matrix<N>::row_reference_type Row_Reference;
02190 
02191   const Row_Iterator m_begin = x.matrix.row_begin();
02192   const Row_Iterator m_end = x.matrix.row_end();
02193 
02194   // Fill the main diagonal with zeros.
02195   for (Row_Iterator i = m_begin; i != m_end; ++i) {
02196     PPL_ASSERT(is_plus_infinity((*i)[i.index()]));
02197     assign_r((*i)[i.index()], 0, ROUND_NOT_NEEDED);
02198   }
02199 
02200   // Using the incremental Floyd-Warshall algorithm.
02201   // Step 1: Improve all constraints on variable `var'.
02202   const dimension_type v = 2*var.id();
02203   const dimension_type cv = v+1;
02204   Row_Iterator v_iter = m_begin + v;
02205   Row_Iterator cv_iter = v_iter + 1;
02206   Row_Reference x_v = *v_iter;
02207   Row_Reference x_cv = *cv_iter;
02208   const dimension_type rs_v = v_iter.row_size();
02209   const dimension_type n_rows = x.matrix.num_rows();
02210   PPL_DIRTY_TEMP(N, sum);
02211   using namespace Implementation::Octagonal_Shapes;
02212   for (Row_Iterator k_iter = m_begin; k_iter != m_end; ++k_iter) {
02213     const dimension_type k = k_iter.index();
02214     const dimension_type ck = coherent_index(k);
02215     const dimension_type rs_k = k_iter.row_size();
02216     Row_Reference x_k = *k_iter;
02217     Row_Reference x_ck = (k % 2 != 0) ? *(k_iter-1) : *(k_iter+1);
02218 
02219     for (Row_Iterator i_iter = m_begin; i_iter != m_end; ++i_iter) {
02220       const dimension_type i = i_iter.index();
02221       const dimension_type ci = coherent_index(i);
02222       const dimension_type rs_i = i_iter.row_size();
02223       Row_Reference x_i = *i_iter;
02224       Row_Reference x_ci = (i % 2 != 0) ? *(i_iter-1) : *(i_iter+1);
02225 
02226       const N& x_i_k = (k < rs_i) ? x_i[k] : x_ck[ci];
02227       if (!is_plus_infinity(x_i_k)) {
02228         const N& x_k_v = (v < rs_k) ? x_k[v] : x_cv[ck];
02229         if (!is_plus_infinity(x_k_v)) {
02230           add_assign_r(sum, x_i_k, x_k_v, ROUND_UP);
02231           N& x_i_v = (v < rs_i) ? x_i[v] : x_cv[ci];
02232           min_assign(x_i_v, sum);
02233         }
02234         const N& x_k_cv = (cv < rs_k) ? x_k[cv] : x_v[ck];
02235         if (!is_plus_infinity(x_k_cv)) {
02236           add_assign_r(sum, x_i_k, x_k_cv, ROUND_UP);
02237           N& x_i_cv = (cv < rs_i) ? x_i[cv] : x_v[ci];
02238           min_assign(x_i_cv, sum);
02239         }
02240       }
02241       const N& x_k_i = (i < rs_k) ? x_k[i] : x_ci[ck];
02242       if (!is_plus_infinity(x_k_i)) {
02243         const N& x_v_k = (k < rs_v) ? x_v[k] : x_ck[cv];
02244         if (!is_plus_infinity(x_v_k)) {
02245           N& x_v_i = (i < rs_v) ? x_v[i] : x_ci[cv];
02246           add_assign_r(sum, x_v_k, x_k_i, ROUND_UP);
02247           min_assign(x_v_i, sum);
02248         }
02249         const N& x_cv_k = (k < rs_v) ? x_cv[k] : x_ck[v];
02250         if (!is_plus_infinity(x_cv_k)) {
02251           N& x_cv_i = (i < rs_v) ? x_cv[i] : x_ci[v];
02252           add_assign_r(sum, x_cv_k, x_k_i, ROUND_UP);
02253           min_assign(x_cv_i, sum);
02254         }
02255       }
02256 
02257     }
02258   }
02259 
02260   // Step 2: improve the other bounds by using the precise bounds
02261   // for the constraints on `var'.
02262   for (Row_Iterator i_iter = m_begin; i_iter != m_end; ++i_iter) {
02263     const dimension_type i = i_iter.index();
02264     const dimension_type ci = coherent_index(i);
02265     const dimension_type rs_i = i_iter.row_size();
02266     Row_Reference x_i = *i_iter;
02267     const N& x_i_v = (v < rs_i) ? x_i[v] : x_cv[ci];
02268     // TODO: see if it is possible to optimize this inner loop
02269     // by splitting it into several parts, so as to avoid
02270     // conditional expressions.
02271     for (dimension_type j = 0; j < n_rows; ++j) {
02272       const dimension_type cj = coherent_index(j);
02273       Row_Reference x_cj = *(m_begin+cj);
02274       N& x_i_j = (j < rs_i) ? x_i[j] : x_cj[ci];
02275       if (!is_plus_infinity(x_i_v)) {
02276         const N& x_v_j = (j < rs_v) ? x_v[j] : x_cj[cv];
02277         if (!is_plus_infinity(x_v_j)) {
02278           add_assign_r(sum, x_i_v, x_v_j, ROUND_UP);
02279           min_assign(x_i_j, sum);
02280         }
02281       }
02282       const N& x_i_cv = (cv < rs_i) ? x_i[cv] : x_v[ci];
02283       if (!is_plus_infinity(x_i_cv)) {
02284         const N& x_cv_j = (j < rs_v) ? x_cv[j] : x_cj[v];
02285         if (!is_plus_infinity(x_cv_j)) {
02286           add_assign_r(sum, x_i_cv, x_cv_j, ROUND_UP);
02287           min_assign(x_i_j, sum);
02288         }
02289       }
02290     }
02291   }
02292 
02293   // Check for emptiness: the octagon is empty if and only if there is a
02294   // negative value on the main diagonal.
02295   for (Row_Iterator i = m_begin; i != m_end; ++i) {
02296     N& x_i_i = (*i)[i.index()];
02297     if (sgn(x_i_i) < 0) {
02298       x.set_empty();
02299       return;
02300     }
02301     else {
02302       // Restore PLUS_INFINITY on the main diagonal.
02303       PPL_ASSERT(sgn(x_i_i) == 0);
02304       assign_r(x_i_i, PLUS_INFINITY, ROUND_NOT_NEEDED);
02305     }
02306   }
02307 
02308   // Step 3: we enforce the strong coherence.
02309   x.strong_coherence_assign();
02310   // The octagon is not empty and it is now strongly closed.
02311   x.set_strongly_closed();
02312 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::integer_upper_bound_assign_if_exact ( const Octagonal_Shape< T > &  y  )  [inline]

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

Exceptions:
std::invalid_argument Thrown if *this and y are dimension-incompatible.
Note:
This operator is only available when the class template parameter T is bound to an integer datatype.
The integer upper bound of two rational OS is the smallest rational OS containing all the integral points in the two arguments. In general, the result is not an upper bound for the two input arguments, as it may cut away non-integral portions of the two rational shapes.

Implementation is based on Theorem 6.8 of [BHZ09b].

Definition at line 6603 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::non_redundant_matrix_entries(), PPL_COMPILE_TIME_CHECK, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_size(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::swap(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign().

06603                                                               {
06604   PPL_COMPILE_TIME_CHECK(std::numeric_limits<T>::is_integer,
06605                          "Octagonal_Shape<T>::"
06606                          "integer_upper_bound_assign_if_exact(y):"
06607                          " T in not an integer datatype.");
06608   // Declare a const reference to *this (to avoid accidental modifications).
06609   const Octagonal_Shape& x = *this;
06610   const dimension_type x_space_dim = x.space_dimension();
06611 
06612   if (x_space_dim != y.space_dimension())
06613     throw_dimension_incompatible("integer_upper_bound_assign_if_exact(y)", y);
06614 
06615   // The zero-dim case is trivial.
06616   if (x_space_dim == 0) {
06617     upper_bound_assign(y);
06618     return true;
06619   }
06620 
06621   // If `x' or `y' is (known to) contain no integral point,
06622   // then the integer upper bound can be computed exactly by tight closure.
06623   if (x.marked_empty()) {
06624     *this = y;
06625     tight_closure_assign();
06626     return true;
06627   }
06628   else if (y.marked_empty()) {
06629     tight_closure_assign();
06630     return true;
06631   }
06632   else if (x.is_empty() || x.tight_coherence_would_make_empty()) {
06633     *this = y;
06634     tight_closure_assign();
06635     return true;
06636   }
06637   else if (y.is_empty() || y.tight_coherence_would_make_empty()) {
06638     tight_closure_assign();
06639     return true;
06640   }
06641 
06642   // Here both `x' and `y' are known to be non-empty (and Z-consistent).
06643   PPL_ASSERT(x.marked_strongly_closed());
06644   PPL_ASSERT(y.marked_strongly_closed());
06645   // Pre-compute the integer upper bound of `x' and `y':
06646   // have to take copies, since tight closure might modify the rational shape.
06647   Octagonal_Shape<T> tx(x);
06648   tx.tight_closure_assign();
06649   Octagonal_Shape<T> ty(y);
06650   ty.tight_closure_assign();
06651   Octagonal_Shape<T> ub(tx);
06652   ub.upper_bound_assign(ty);
06653 
06654   // Compute redundancy information for tx and ty.
06655   // TODO: provide a nicer data structure for redundancy.
06656   // NOTE: there is no need to identify all redundancies, since this is
06657   // an optimization; hence we reuse the strong-reduction helper methods.
06658   std::vector<Bit_Row> tx_non_red;
06659   tx.non_redundant_matrix_entries(tx_non_red);
06660   std::vector<Bit_Row> ty_non_red;
06661   ty.non_redundant_matrix_entries(ty_non_red);
06662 
06663   PPL_DIRTY_TEMP(N, lhs_i_j);
06664   PPL_DIRTY_TEMP(N, lhs_k_ell);
06665   PPL_DIRTY_TEMP(N, lhs);
06666   PPL_DIRTY_TEMP(N, lhs_copy);
06667   PPL_DIRTY_TEMP(N, rhs);
06668   PPL_DIRTY_TEMP(N, temp_zero);
06669   assign_r(temp_zero, 0, ROUND_NOT_NEEDED);
06670   PPL_DIRTY_TEMP(N, temp_one);
06671   assign_r(temp_one, 1, ROUND_NOT_NEEDED);
06672   PPL_DIRTY_TEMP(N, temp_two);
06673   assign_r(temp_two, 2, ROUND_NOT_NEEDED);
06674 
06675   typedef typename OR_Matrix<N>::const_row_iterator Row_Iterator;
06676   typedef typename OR_Matrix<N>::const_row_reference_type Row_Reference;
06677   const dimension_type n_rows = tx.matrix.num_rows();
06678   const Row_Iterator tx_m_begin = tx.matrix.row_begin();
06679   const Row_Iterator ty_m_begin = ty.matrix.row_begin();
06680   const Row_Iterator ub_m_begin = ub.matrix.row_begin();
06681 
06682   for (dimension_type i = n_rows; i-- > 0; ) {
06683     const Bit_Row& tx_non_red_i = tx_non_red[i];
06684     using namespace Implementation::Octagonal_Shapes;
06685     const dimension_type ci = coherent_index(i);
06686     const dimension_type row_size_i = OR_Matrix<N>::row_size(i);
06687     Row_Reference tx_i = *(tx_m_begin + i);
06688     Row_Reference ty_i = *(ty_m_begin + i);
06689     Row_Reference ub_i = *(ub_m_begin + i);
06690     const N& ub_i_ci = ub_i[ci];
06691     for (dimension_type j = row_size_i; j-- > 0; ) {
06692       // Check redundancy of tx_i_j.
06693       if (!tx_non_red_i[j])
06694         continue;
06695       const N& tx_i_j = tx_i[j];
06696       const dimension_type cj = coherent_index(j);
06697       const N& eps_i_j = (i == cj) ? temp_two : temp_one;
06698       // Check condition 1a in BHZ09 Theorem 6.8.
06699       add_assign_r(lhs_i_j, tx_i_j, eps_i_j, ROUND_NOT_NEEDED);
06700       if (lhs_i_j > ty_i[j])
06701         continue;
06702       const dimension_type row_size_cj = OR_Matrix<N>::row_size(cj);
06703       Row_Reference ub_cj = *(ub_m_begin + cj);
06704       const N& ub_cj_j = ub_cj[j];
06705       for (dimension_type k = 0; k < n_rows; ++k) {
06706         const Bit_Row& ty_non_red_k = ty_non_red[k];
06707         const dimension_type ck = coherent_index(k);
06708         const dimension_type row_size_k = OR_Matrix<N>::row_size(k);
06709         Row_Reference tx_k = *(tx_m_begin + k);
06710         Row_Reference ty_k = *(ty_m_begin + k);
06711         Row_Reference ub_k = *(ub_m_begin + k);
06712         const N& ub_k_ck = ub_k[ck];
06713         // Be careful: for each index h, the diagonal element m[h][h]
06714         // is (by convention) +infty in our implementation; however,
06715         // BHZ09 theorem assumes that it is equal to 0.
06716         const N& ub_k_j = (k == j) ? temp_zero
06717           : (j < row_size_k ? ub_k[j] : ub_cj[ck]);
06718         const N& ub_i_ck = (i == ck) ? temp_zero
06719           : (ck < row_size_i ? ub_i[ck] : ub_k[ci]);
06720 
06721         for (dimension_type ell = row_size_k; ell-- > 0; ) {
06722           // Check redundancy of y_k_ell.
06723           if (!ty_non_red_k[ell])
06724             continue;
06725           const N& ty_k_ell = ty_k[ell];
06726           const dimension_type cell = coherent_index(ell);
06727           const N& eps_k_ell = (k == cell) ? temp_two : temp_one;
06728           // Check condition 1b in BHZ09 Theorem 6.8.
06729           add_assign_r(lhs_k_ell, ty_k_ell, eps_k_ell, ROUND_NOT_NEEDED);
06730           if (lhs_k_ell > tx_k[ell])
06731             continue;
06732           Row_Reference ub_cell = *(ub_m_begin + cell);
06733           const N& ub_i_ell = (i == ell) ? temp_zero
06734             : (ell < row_size_i ? ub_i[ell] : ub_cell[ci]);
06735           const N& ub_cj_ell = (cj == ell) ? temp_zero
06736             : (ell < row_size_cj ? ub_cj[ell] : ub_cell[j]);
06737           // Check condition 2a in BHZ09 Theorem 6.8.
06738           add_assign_r(lhs, lhs_i_j, lhs_k_ell, ROUND_NOT_NEEDED);
06739           add_assign_r(rhs, ub_i_ell, ub_k_j, ROUND_NOT_NEEDED);
06740           if (lhs > rhs)
06741             continue;
06742           // Check condition 2b in BHZ09 Theorem 6.8.
06743           add_assign_r(rhs, ub_i_ck, ub_cj_ell, ROUND_NOT_NEEDED);
06744           if (lhs > rhs)
06745             continue;
06746           // Check condition 3a in BHZ09 Theorem 6.8.
06747           assign_r(lhs_copy, lhs, ROUND_NOT_NEEDED);
06748           add_assign_r(lhs, lhs, lhs_i_j, ROUND_NOT_NEEDED);
06749           add_assign_r(rhs, ub_i_ell, ub_i_ck, ROUND_NOT_NEEDED);
06750           add_assign_r(rhs, rhs, ub_cj_j, ROUND_NOT_NEEDED);
06751           if (lhs > rhs)
06752             continue;
06753           // Check condition 3b in BHZ09 Theorem 6.8.
06754           add_assign_r(rhs, ub_k_j, ub_cj_ell, ROUND_NOT_NEEDED);
06755           add_assign_r(rhs, rhs, ub_i_ci, ROUND_NOT_NEEDED);
06756           if (lhs > rhs)
06757             continue;
06758           // Check condition 4a in BHZ09 Theorem 6.8.
06759           add_assign_r(lhs, lhs_copy, lhs_k_ell, ROUND_NOT_NEEDED);
06760           add_assign_r(rhs, ub_i_ell, ub_cj_ell, ROUND_NOT_NEEDED);
06761           add_assign_r(rhs, rhs, ub_k_ck, ROUND_NOT_NEEDED);
06762           if (lhs > rhs)
06763             continue;
06764           // Check condition 4b in BHZ09 Theorem 6.8.
06765           add_assign_r(rhs, ub_k_j, ub_i_ck, ROUND_NOT_NEEDED);
06766           add_assign_r(rhs, rhs, ub_cell[ell], ROUND_NOT_NEEDED);
06767           if (lhs <= rhs)
06768             // All 8 conditions are satisfied:
06769             // integer upper bound is not exact.
06770             return false;
06771         }
06772       }
06773     }
06774   }
06775 
06776   // The upper bound of x and y is indeed exact.
06777   swap(ub);
06778   PPL_ASSERT(OK());
06779   return true;
06780 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign ( const Octagonal_Shape< T > &  y  )  [inline]

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

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

Definition at line 3128 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::element_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign().

03128                                                                 {
03129   // Dimension-compatibility check.
03130   if (space_dim != y.space_dim)
03131     throw_dimension_incompatible("intersection_assign(y)", y);
03132 
03133   // If one of the two octagons is empty, the intersection is empty.
03134   if (marked_empty())
03135     return;
03136   if (y.marked_empty()) {
03137     set_empty();
03138     return;
03139   }
03140   // If both octagons are zero-dimensional,then at this point
03141   // they are necessarily non-empty,
03142   // so that their intersection is non-empty too.
03143   if (space_dim == 0)
03144     return;
03145 
03146   // To intersect two octagons we compare the constraints
03147   // and we choose the less values.
03148   bool changed = false;
03149 
03150   typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin();
03151   for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(),
03152          matrix_element_end = matrix.element_end();
03153        i != matrix_element_end;
03154        ++i, ++j) {
03155     N& elem = *i;
03156     const N& y_elem = *j;
03157     if (y_elem < elem) {
03158       elem = y_elem;
03159       changed = true;
03160     }
03161   }
03162 
03163   // This method not preserve the closure.
03164   if (changed && marked_strongly_closed())
03165     reset_strongly_closed();
03166   PPL_ASSERT(OK());
03167 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::is_bounded (  )  const [inline]

Returns true if and only if *this is a bounded OS.

Definition at line 824 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().

00824                                      {
00825   strong_closure_assign();
00826   // A zero-dimensional or empty octagon is bounded.
00827   if (marked_empty() || space_dim == 0)
00828     return true;
00829 
00830   // A bounded octagon never can contains trivial constraints.
00831   for (typename OR_Matrix<N>::const_row_iterator i = matrix.row_begin(),
00832          matrix_row_end = matrix.row_end(); i != matrix_row_end; ++i) {
00833     typename OR_Matrix<N>::const_row_reference_type x_i = *i;
00834     const dimension_type i_index = i.index();
00835     for (dimension_type j = i.row_size(); j-- > 0; )
00836       if (i_index != j)
00837         if (is_plus_infinity(x_i[j]))
00838           return false;
00839   }
00840 
00841   return true;
00842 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::is_discrete (  )  const [inline]

Returns true if and only if *this is discrete.

Definition at line 252 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_dimension().

00252                                       {
00253   return affine_dimension() == 0;
00254 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::is_disjoint_from ( const Octagonal_Shape< T > &  y  )  const [inline]

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

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

Definition at line 748 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

00748                                                                    {
00749   // Dimension-compatibility check.
00750   if (space_dim != y.space_dim)
00751     throw_dimension_incompatible("is_disjoint_from(y)", y);
00752 
00753   // If one Octagonal_Shape is empty, the Octagonal_Shapes are disjoint.
00754   strong_closure_assign();
00755   if (marked_empty())
00756     return true;
00757   y.strong_closure_assign();
00758   if (y.marked_empty())
00759     return true;
00760 
00761   // Two Octagonal_Shapes are disjoint if and only if their intersection
00762   // is empty, i.e., if and only if there exists a variable such that
00763   // the upper bound of the constraint on that variable in the first
00764   // Octagonal_Shape is strictly less than the lower bound of
00765   // the correspomding constraint in the second Octagonal_Shape or vice versa.
00766 
00767   const dimension_type n_rows = matrix.num_rows();
00768 
00769   typedef typename OR_Matrix<N>::const_row_iterator Row_Iterator;
00770   typedef typename OR_Matrix<N>::const_row_reference_type Row_Reference;
00771 
00772   const Row_Iterator m_begin = matrix.row_begin();
00773   const Row_Iterator m_end = matrix.row_end();
00774 
00775   const Row_Iterator y_begin = y.matrix.row_begin();
00776 
00777   PPL_DIRTY_TEMP(N, neg_y_ci_cj);
00778     for (Row_Iterator i_iter = m_begin; i_iter != m_end; ++i_iter) {
00779     using namespace Implementation::Octagonal_Shapes;
00780     const dimension_type i = i_iter.index();
00781     const dimension_type ci = coherent_index(i);
00782     const dimension_type rs_i = i_iter.row_size();
00783     Row_Reference m_i = *i_iter;
00784     for (dimension_type j = 0; j < n_rows; ++j) {
00785       const dimension_type cj = coherent_index(j);
00786       Row_Reference m_cj = *(m_begin + cj);
00787       const N& m_i_j = (j < rs_i) ? m_i[j] : m_cj[ci];
00788       Row_Reference y_ci = *(y_begin + ci);
00789       Row_Reference y_j = *(y_begin + j);
00790       const N& y_ci_cj = (j < rs_i) ? y_ci[cj] : y_j[i];
00791       neg_assign_r(neg_y_ci_cj, y_ci_cj, ROUND_UP);
00792       if (m_i_j < neg_y_ci_cj)
00793         return true;
00794     }
00795   }
00796   return false;
00797 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty (  )  const [inline]
template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strong_coherent (  )  const [inline, private]

Returns true if in the octagon taken two at a time unary constraints, there is also the constraint that represent their sum.

Definition at line 1081 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), and Parma_Polyhedra_Library::OR_Matrix< T >::row_size().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::OK().

01081                                              {
01082   // This method is only used by method OK() so as to check if a
01083   // strongly closed matrix is also strong-coherent, as it must be.
01084   const dimension_type num_rows = matrix.num_rows();
01085 
01086   // Allocated here once and for all.
01087   PPL_DIRTY_TEMP(N, semi_sum);
01088   // The strong-coherence is: for every indexes i and j (and i != j)
01089   // matrix[i][j] <= (matrix[i][ci] + matrix[cj][j])/2
01090   // where ci = i + 1, if i is even number or
01091   //       ci = i - 1, if i is odd.
01092   // Ditto for cj.
01093   for (dimension_type i = num_rows; i-- > 0; ) {
01094     typename OR_Matrix<N>::const_row_iterator iter = matrix.row_begin() + i;
01095     typename OR_Matrix<N>::const_row_reference_type m_i = *iter;
01096     using namespace Implementation::Octagonal_Shapes;
01097     const N& m_i_ci = m_i[coherent_index(i)];
01098     for (dimension_type j = matrix.row_size(i); j-- > 0; )
01099       // Note: on the main diagonal only PLUS_INFINITY can occur.
01100       if (i != j) {
01101         const N& m_cj_j = matrix[coherent_index(j)][j];
01102         if (!is_plus_infinity(m_i_ci)
01103             && !is_plus_infinity(m_cj_j)) {
01104           // Compute (m_i_ci + m_cj_j)/2 into `semi_sum',
01105           // rounding the result towards plus infinity.
01106           add_assign_r(semi_sum, m_i_ci, m_cj_j, ROUND_UP);
01107           div_2exp_assign_r(semi_sum, semi_sum, 1, ROUND_UP);
01108           if (m_i[j] > semi_sum)
01109             return false;
01110         }
01111       }
01112   }
01113   return true;
01114 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strongly_reduced (  )  const [inline, private]

Returns true if and only if this->matrix is strongly reduced.

Definition at line 1118 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), and Parma_Polyhedra_Library::OR_Matrix< T >::row_end().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign().

01118                                               {
01119   // This method is only used in assertions: efficiency is not a must.
01120 
01121   // An empty octagon is already transitively reduced.
01122   if (marked_empty())
01123     return true;
01124 
01125   Octagonal_Shape x = *this;
01126   // The matrix representing an OS is strongly reduced if, by removing
01127   // any constraint, the resulting matrix describes a different OS.
01128   for (typename OR_Matrix<N>::const_row_iterator iter = matrix.row_begin(),
01129          matrix_row_end = matrix.row_end(); iter != matrix_row_end; ++iter) {
01130     typename OR_Matrix<N>::const_row_reference_type m_i = *iter;
01131     const dimension_type i = iter.index();
01132     for (dimension_type j = iter.row_size(); j-- > 0; ) {
01133       if (!is_plus_infinity(m_i[j])) {
01134         Octagonal_Shape x_copy = *this;
01135         assign_r(x_copy.matrix[i][j], PLUS_INFINITY, ROUND_NOT_NEEDED);
01136         if (x == x_copy)
01137           return false;
01138       }
01139     }
01140   }
01141   // The octagon is just reduced.
01142   return true;
01143 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::is_topologically_closed (  )  const [inline]

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

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

00311                                                   {
00312   return true;
00313 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::is_universe (  )  const [inline]

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

Definition at line 801 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::element_end(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim.

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min().

00801                                       {
00802   // An empty octagon isn't, of course, universe.
00803   if (marked_empty())
00804     return false;
00805 
00806   // If the octagon is non-empty and zero-dimensional,
00807   // then it is necessarily the universe octagon.
00808   if (space_dim == 0)
00809     return true;
00810 
00811   // An universe octagon can only contains trivial  constraints.
00812   for (typename OR_Matrix<N>::const_element_iterator
00813          i = matrix.element_begin(), matrix_element_end = matrix.element_end();
00814        i != matrix_element_end;
00815        ++i)
00816     if (!is_plus_infinity(*i))
00817       return false;
00818 
00819   return true;
00820 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_BHMZ05_extrapolation_assign ( const Octagonal_Shape< T > &  y,
const Constraint_System cs,
unsigned *  tp = 0 
) [inline]

Improves the result of the BHMZ05-widening computation by also enforcing those constraints in cs that are satisfied by all the points of *this.

Parameters:
y An OS that must be contained in *this.
cs The system of constraints used to improve the widened OS.
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 or if there is in cs a strict inequality.

Definition at line 3438 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.

03440                                                     {
03441 
03442   // Dimension-compatibility check.
03443   if (space_dim != y.space_dim)
03444     throw_dimension_incompatible("limited_BHMZ05_extrapolation_assign(y, cs)",
03445                                  y);
03446   // `cs' must be dimension-compatible with the two octagons.
03447   const dimension_type cs_space_dim = cs.space_dimension();
03448   if (space_dim < cs_space_dim)
03449     throw_constraint_incompatible("limited_CH78_extrapolation_assign(y, cs)");
03450 
03451   // Strict inequalities not allowed.
03452   if (cs.has_strict_inequalities())
03453     throw_constraint_incompatible("limited_CH78_extrapolation_assign(y, cs)");
03454 
03455   // The limited BHMZ05-extrapolation between two octagons in a
03456   // zero-dimensional space is a octagon in a zero-dimensional
03457   // space, too.
03458   if (space_dim == 0)
03459     return;
03460 
03461 #ifndef NDEBUG
03462   {
03463     // We assume that `y' is contained in or equal to `*this'.
03464     const Octagonal_Shape x_copy = *this;
03465     const Octagonal_Shape y_copy = y;
03466     PPL_ASSERT(x_copy.contains(y_copy));
03467   }
03468 #endif
03469 
03470   // If `*this' is empty, since `*this' contains `y', `y' is empty too.
03471   if (marked_empty())
03472     return;
03473   // If `y' is empty, we return.
03474   if (y.marked_empty())
03475     return;
03476 
03477   Octagonal_Shape limiting_octagon(space_dim, UNIVERSE);
03478   get_limiting_octagon(cs, limiting_octagon);
03479   BHMZ05_widening_assign(y, tp);
03480   intersection_assign(limiting_octagon);
03481 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_CC76_extrapolation_assign ( const Octagonal_Shape< T > &  y,
const Constraint_System cs,
unsigned *  tp = 0 
) [inline]

Improves the result of the CC76-extrapolation computation by also enforcing those constraints in cs that are satisfied by all the points of *this.

Parameters:
y An OS that must be contained in *this.
cs The system of constraints used to improve the widened OS.
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 or if cs contains a strict inequality.

Definition at line 3326 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.

03328                                                   {
03329 
03330   // Dimension-compatibility check.
03331   if (space_dim != y.space_dim)
03332     throw_dimension_incompatible("limited_CC76_extrapolation_assign(y, cs)",
03333                                  y);
03334   // `cs' must be dimension-compatible with the two octagons.
03335   const dimension_type cs_space_dim = cs.space_dimension();
03336   if (space_dim < cs_space_dim)
03337     throw_constraint_incompatible("limited_CC76_extrapolation_assign(y, cs)");
03338 
03339   // Strict inequalities not allowed.
03340   if (cs.has_strict_inequalities())
03341     throw_constraint_incompatible("limited_CC76_extrapolation_assign(y, cs)");
03342 
03343   // The limited CC76-extrapolation between two octagons in a
03344   // zero-dimensional space is a octagon in a zero-dimensional
03345   // space, too.
03346   if (space_dim == 0)
03347     return;
03348 
03349 #ifndef NDEBUG
03350   {
03351     // We assume that `y' is contained in or equal to `*this'.
03352     const Octagonal_Shape x_copy = *this;
03353     const Octagonal_Shape y_copy = y;
03354     PPL_ASSERT(x_copy.contains(y_copy));
03355   }
03356 #endif
03357 
03358   // If `*this' is empty, since `*this' contains `y', `y' is empty too.
03359   if (marked_empty())
03360     return;
03361   // If `y' is empty, we return.
03362   if (y.marked_empty())
03363     return;
03364 
03365   Octagonal_Shape limiting_octagon(space_dim, UNIVERSE);
03366   get_limiting_octagon(cs, limiting_octagon);
03367   CC76_extrapolation_assign(y, tp);
03368   intersection_assign(limiting_octagon);
03369 }

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

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

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

The template type parameter Partial_Function must provide the following methods.

      bool has_empty_codomain() const

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

      dimension_type max_in_codomain() const

returns the maximum value that belongs to the codomain of the partial function.

      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.

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 3045 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::swap().

03045                                                                       {
03046   if (space_dim == 0)
03047     return;
03048 
03049   if (pfunc.has_empty_codomain()) {
03050     // All dimensions vanish: the octagon becomes zero_dimensional.
03051     remove_higher_space_dimensions(0);
03052     return;
03053   }
03054 
03055   const dimension_type new_space_dim = pfunc.max_in_codomain() + 1;
03056   // If we are going to actually reduce the space dimension,
03057   // then shortest-path closure is required to keep precision.
03058   if (new_space_dim < space_dim)
03059     strong_closure_assign();
03060 
03061   // If the octagon is empty, then it is sufficient to adjust
03062   // the space dimension of the octagon.
03063   if (marked_empty()) {
03064     remove_higher_space_dimensions(new_space_dim);
03065     return;
03066   }
03067 
03068   // We create a new matrix with the new space dimension.
03069   OR_Matrix<N> x(new_space_dim);
03070 
03071   typedef typename OR_Matrix<N>::row_iterator Row_Iterator;
03072   typedef typename OR_Matrix<N>::row_reference_type Row_Reference;
03073 
03074   Row_Iterator m_begin = x.row_begin();
03075 
03076   for (Row_Iterator i_iter = matrix.row_begin(), i_end = matrix.row_end();
03077        i_iter != i_end; i_iter += 2) {
03078     dimension_type new_i;
03079     dimension_type i = i_iter.index()/2;
03080     // We copy and place in the position into `x' the only cells of
03081     // the `matrix' that refer to both mapped variables,
03082     // the variable `i' and `j'.
03083     if (pfunc.maps(i, new_i)) {
03084       Row_Reference r_i = *i_iter;
03085       Row_Reference r_ii = *(i_iter + 1);
03086       dimension_type double_new_i = 2*new_i;
03087       Row_Iterator x_iter = m_begin + double_new_i;
03088       Row_Reference x_i = *x_iter;
03089       Row_Reference x_ii = *(x_iter + 1);
03090       for (dimension_type j = 0; j <= i; ++j) {
03091         dimension_type new_j;
03092         // If also the second variable is mapped, we work.
03093         if (pfunc.maps(j, new_j)) {
03094           dimension_type dj = 2*j;
03095           dimension_type double_new_j = 2*new_j;
03096           // Mapped the constraints, exchanging the indexes.
03097           // Attention: our matrix is pseudo-triangular.
03098           // If new_j > new_i, we must consider, as rows, the rows of
03099           // the variable new_j, and not of new_i ones.
03100           if (new_i >= new_j) {
03101             assign_or_swap(x_i[double_new_j], r_i[dj]);
03102             assign_or_swap(x_ii[double_new_j], r_ii[dj]);
03103             assign_or_swap(x_ii[double_new_j+1], r_ii[dj + 1]);
03104             assign_or_swap(x_i[double_new_j+1], r_i[dj + 1]);
03105           }
03106           else {
03107             Row_Iterator xj_iter = m_begin + double_new_j;
03108             Row_Reference x_j = *xj_iter;
03109             Row_Reference x_jj = *(xj_iter + 1);
03110             assign_or_swap(x_jj[double_new_i+1], r_i[dj]);
03111             assign_or_swap(x_jj[double_new_i], r_ii[dj]);
03112             assign_or_swap(x_j[double_new_i+1], r_i[dj+1]);
03113             assign_or_swap(x_j[double_new_i], r_ii[dj+1]);
03114           }
03115 
03116         }
03117       }
03118     }
03119   }
03120 
03121   std::swap(matrix, x);
03122   space_dim = new_space_dim;
03123   PPL_ASSERT(OK());
03124 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty (  )  const [inline, private]

Returns true if the OS is known to be empty.

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

Definition at line 78 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::status, and Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::test_empty().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constrains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Octagonal_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::frequency(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::integer_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_bounded(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strongly_reduced(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_universe(), Parma_Polyhedra_Library::Octagonal_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_BHMZ05_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain(), Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign_if_exact().

00078                                        {
00079   return status.test_empty();
00080 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed (  )  const [inline, private]

Returns true if this->matrix is known to be strongly closed.

The return value false does not necessarily implies that this->matrix is not strongly closed.

Definition at line 72 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::status, and Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::test_strongly_closed().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::get_limiting_octagon(), Parma_Polyhedra_Library::Octagonal_Shape< T >::integer_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign_if_exact().

00072                                                  {
00073   return status.test_strongly_closed();
00074 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_zero_dim_univ (  )  const [inline, private]
template<typename T >
const Octagonal_Shape< T >::coefficient_type & Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix_at ( dimension_type  i,
dimension_type  j 
) const [inline, private]

Definition at line 357 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), and Parma_Polyhedra_Library::OR_Matrix< T >::row_size().

00358                                                             {
00359   PPL_ASSERT(i < matrix.num_rows() && j < matrix.num_rows());
00360   using namespace Implementation::Octagonal_Shapes;
00361   return (j < matrix.row_size(i))
00362     ? matrix[i][j]
00363     : matrix[coherent_index(j)][coherent_index(i)];
00364 }

template<typename T >
Octagonal_Shape< T >::coefficient_type & Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix_at ( dimension_type  i,
dimension_type  j 
) [inline, private]

Definition at line 368 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), and Parma_Polyhedra_Library::OR_Matrix< T >::row_size().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign().

00369                                                       {
00370   PPL_ASSERT(i < matrix.num_rows() && j < matrix.num_rows());
00371   using namespace Implementation::Octagonal_Shapes;
00372   return (j < matrix.row_size(i))
00373     ? matrix[i][j]
00374     : matrix[coherent_index(j)][coherent_index(i)];
00375 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min ( const Linear_Expression expr,
bool  maximize,
Coefficient ext_n,
Coefficient ext_d,
bool &  included,
Generator g 
) const [inline, private]

Maximizes or minimizes expr subject to *this.

Parameters:
expr The linear expression to be maximized or minimized subject to this;
maximize true if maximization is what is wanted;
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 can actually be reached in * this;
g When maximization or minimization succeeds, will be assigned a point or closure point where expr reaches the corresponding 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 g are left untouched.

Definition at line 1293 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::MIP_Problem::evaluate_objective_function(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_universe(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::MINIMIZATION, Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, Parma_Polyhedra_Library::MIP_Problem::optimizing_point(), Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

01296                                                                 {
01297   // The dimension of `expr' should not be greater than the dimension
01298   // of `*this'.
01299   const dimension_type expr_space_dim = expr.space_dimension();
01300   if (space_dim < expr_space_dim)
01301     throw_dimension_incompatible((maximize
01302                                   ? "maximize(e, ...)"
01303                                   : "minimize(e, ...)"), "e", expr);
01304   // Deal with zero-dim octagons first.
01305   if (space_dim == 0) {
01306     if (marked_empty())
01307       return false;
01308     else {
01309       ext_n = expr.inhomogeneous_term();
01310       ext_d = 1;
01311       included = true;
01312       g = point();
01313       return true;
01314     }
01315   }
01316 
01317   strong_closure_assign();
01318   // For an empty OS we simply return false.
01319   if (marked_empty())
01320     return false;
01321   if (!is_universe()) {
01322     // We use MIP_Problems to handle constraints that are not
01323     // octagonal difference.
01324     Optimization_Mode max_min = (maximize) ? MAXIMIZATION : MINIMIZATION;
01325     MIP_Problem mip(space_dim, constraints(), expr, max_min);
01326     if (mip.solve() == OPTIMIZED_MIP_PROBLEM) {
01327       g = mip.optimizing_point();
01328       mip.evaluate_objective_function(g, ext_n, ext_d);
01329       included = true;
01330       return true;
01331     }
01332   }
01333   // The `expr' is unbounded.
01334   return false;
01335 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min ( const Linear_Expression expr,
bool  maximize,
Coefficient ext_n,
Coefficient ext_d,
bool &  included 
) const [inline, private]

Maximizes or minimizes expr subject to *this.

Parameters:
expr The linear expression to be maximized or minimized subject to this;
maximize true if maximization is what is wanted;
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 can actually be reached in * this;
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 and included are left untouched.

Definition at line 1190 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::extract_octagonal_difference(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::MINIMIZATION, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::numer_denom(), Parma_Polyhedra_Library::MIP_Problem::optimal_value(), Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::maximize(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::minimize().

01193                                                   {
01194   // The dimension of `expr' should not be greater than the dimension
01195   // of `*this'.
01196   const dimension_type expr_space_dim = expr.space_dimension();
01197   if (space_dim < expr_space_dim)
01198     throw_dimension_incompatible((maximize
01199                                   ? "maximize(e, ...)"
01200                                   : "minimize(e, ...)"), "e", expr);
01201   // Deal with zero-dim octagons first.
01202   if (space_dim == 0) {
01203     if (marked_empty())
01204       return false;
01205     else {
01206       ext_n = expr.inhomogeneous_term();
01207       ext_d = 1;
01208       included = true;
01209       return true;
01210     }
01211   }
01212 
01213   strong_closure_assign();
01214   // For an empty OS we simply return false.
01215   if (marked_empty())
01216     return false;
01217 
01218   // The constraint `c' is used to check if `expr' is an octagonal difference
01219   // and, in this case, to select the cell.
01220   const Constraint& c = (maximize) ? expr <= 0 : expr >= 0;
01221   dimension_type num_vars = 0;
01222   dimension_type i = 0;
01223   dimension_type j = 0;
01224   PPL_DIRTY_TEMP_COEFFICIENT(coeff);
01225   PPL_DIRTY_TEMP_COEFFICIENT(term);
01226   if (!extract_octagonal_difference(c, c.space_dimension(), num_vars,
01227                                     i, j, coeff, term)) {
01228     // `c' is not an octagonal constraint: use the MIP solver.
01229     Optimization_Mode max_min = (maximize) ? MAXIMIZATION : MINIMIZATION;
01230     MIP_Problem mip(space_dim, constraints(), expr, max_min);
01231     if (mip.solve() == OPTIMIZED_MIP_PROBLEM) {
01232       mip.optimal_value(ext_n, ext_d);
01233       included = true;
01234       return true;
01235     }
01236     else
01237       // Here`expr' is unbounded in `*this'.
01238       return false;
01239   }
01240   else {
01241     // `c' is an octagonal constraint.
01242     if (num_vars == 0) {
01243       ext_n = expr.inhomogeneous_term();
01244       ext_d = 1;
01245       included = true;
01246       return true;
01247     }
01248 
01249     // Select the cell to be checked.
01250     typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin() + i;
01251     typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter;
01252     PPL_DIRTY_TEMP(N, d);
01253     if (!is_plus_infinity(m_i[j])) {
01254       const Coefficient& b = expr.inhomogeneous_term();
01255       PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
01256       neg_assign(minus_b, b);
01257       const Coefficient& sc_b = maximize ? b : minus_b;
01258       assign_r(d, sc_b, ROUND_UP);
01259       // Set `coeff_expr' to the absolute value of coefficient of a variable
01260       // of `expr'.
01261       PPL_DIRTY_TEMP(N, coeff_expr);
01262       const Coefficient& coeff_i = expr.coefficient(Variable(i/2));
01263       const int sign_i = sgn(coeff_i);
01264       if (sign_i > 0)
01265         assign_r(coeff_expr, coeff_i, ROUND_UP);
01266       else {
01267         PPL_DIRTY_TEMP_COEFFICIENT(minus_coeff_i);
01268         neg_assign(minus_coeff_i, expr.coefficient(Variable(i/2)));
01269         assign_r(coeff_expr, minus_coeff_i, ROUND_UP);
01270       }
01271       // Approximating the maximum/minimum of `expr'.
01272       if (num_vars == 1) {
01273         PPL_DIRTY_TEMP(N, m_i_j);
01274         div_2exp_assign_r(m_i_j, m_i[j], 1, ROUND_UP);
01275         add_mul_assign_r(d, coeff_expr, m_i_j, ROUND_UP);
01276       }
01277       else
01278         add_mul_assign_r(d, coeff_expr, m_i[j], ROUND_UP);
01279       numer_denom(d, ext_n, ext_d);
01280       if (!maximize)
01281         neg_assign(ext_n);
01282       included = true;
01283       return true;
01284     }
01285 
01286     // The `expr' is unbounded.
01287     return false;
01288   }
01289 }

template<typename T >
dimension_type Parma_Polyhedra_Library::Octagonal_Shape< T >::max_space_dimension (  )  [inline, static]

Returns the maximum space dimension that an OS can handle.

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

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension().

00060                                         {
00061   return OR_Matrix<N>::max_num_rows()/2;
00062 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::maximize ( const Linear_Expression expr,
Coefficient sup_n,
Coefficient sup_d,
bool &  maximum,
Generator g 
) 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 and only if the supremum is also the maximum value;
g When maximization succeeds, will be assigned the point or closure 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 from above, false is returned and sup_n, sup_d, maximum and g are left untouched.

Definition at line 285 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min().

00288                                                  {
00289   return max_min(expr, true, sup_n, sup_d, maximum, g);
00290 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::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 and only if the supremum is also the maximum value.
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

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

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

References Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with().

00279                                                   {
00280   return max_min(expr, true, sup_n, sup_d, maximum);
00281 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::minimize ( const Linear_Expression expr,
Coefficient inf_n,
Coefficient inf_d,
bool &  minimum,
Generator g 
) 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 and only if the infimum is also the minimum value;
g When minimization succeeds, will be assigned a point or closure 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 g are left untouched.

Definition at line 302 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min().

00305                                                  {
00306   return max_min(expr, false, inf_n, inf_d, minimum, g);
00307 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::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 and only if the infimum is also the minimum 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 and minimum are left untouched.

Definition at line 294 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with().

00296                                                   {
00297   return max_min(expr, false, inf_n, inf_d, minimum);
00298 }

template<typename T >
Congruence_System Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences (  )  const [inline]

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

Definition at line 583 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::Congruence_System::insert(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Congruence_System::zero_dim_empty().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::congruences().

00583                                                 {
00584   // Strong closure is necessary to detect emptiness
00585   // and all (possibly implicit) equalities.
00586   strong_closure_assign();
00587   const dimension_type space_dim = space_dimension();
00588   Congruence_System cgs;
00589   if (space_dim == 0) {
00590     if (marked_empty())
00591       cgs = Congruence_System::zero_dim_empty();
00592   }
00593   else if (marked_empty())
00594     cgs.insert((0*Variable(space_dim-1) %= 1) / 0);
00595   else {
00596     // KLUDGE: in the future `cgs' will be constructed of the right dimension.
00597     // For the time being, we force the dimension with the following line.
00598     cgs.insert(0*Variable(space_dim-1) == 0);
00599 
00600     // The vector `leaders' is used to represent equivalence classes:
00601     // `leaders[i] == i' if and only if `i' is the leader of its
00602     // equivalence class (i.e., the minimum index in the class);
00603     std::vector<dimension_type> leaders;
00604     compute_leaders(leaders);
00605 
00606     PPL_DIRTY_TEMP_COEFFICIENT(num);
00607     PPL_DIRTY_TEMP_COEFFICIENT(den);
00608     for (dimension_type i = 0, i_end = 2*space_dim; i != i_end; i += 2) {
00609       const dimension_type lead_i = leaders[i];
00610       if (i == lead_i) {
00611         if (leaders[i+1] == i)
00612           // `i' is the leader of the singular equivalence class.
00613           goto singular;
00614         else
00615           // `i' is the leader of a non-singular equivalence class.
00616           continue;
00617       }
00618       else {
00619         // `i' is not a leader.
00620         if (leaders[i+1] == lead_i)
00621           // `i' belongs to the singular equivalence class.
00622           goto singular;
00623         else
00624           // `i' does not belong to the singular equivalence class.
00625           goto non_singular;
00626       }
00627 
00628     singular:
00629       // `i' belongs to the singular equivalence class:
00630       // we have a unary equality constraint.
00631       {
00632         const Variable x(i/2);
00633         const N& c_ii_i = matrix[i+1][i];
00634 #ifndef NDEBUG
00635         const N& c_i_ii = matrix[i][i+1];
00636         PPL_ASSERT(is_additive_inverse(c_i_ii, c_ii_i));
00637 #endif
00638         numer_denom(c_ii_i, num, den);
00639         den *= 2;
00640         cgs.insert(den*x == num);
00641       }
00642       continue;
00643 
00644     non_singular:
00645       // `i' does not belong to the singular equivalence class.
00646       // we have a binary equality constraint.
00647       {
00648         const N& c_i_li = matrix[i][lead_i];
00649 #ifndef NDEBUG
00650         using namespace Implementation::Octagonal_Shapes;
00651         const N& c_ii_lii = matrix[i+1][coherent_index(lead_i)];
00652         PPL_ASSERT(is_additive_inverse(c_ii_lii, c_i_li));
00653 #endif
00654         const Variable x(lead_i/2);
00655         const Variable y(i/2);
00656         numer_denom(c_i_li, num, den);
00657         if (lead_i % 2 == 0)
00658           cgs.insert(den*x - den*y == num);
00659         else
00660           cgs.insert(den*x + den*y + num == 0);
00661       }
00662       continue;
00663     }
00664   }
00665   return cgs;
00666 }

template<typename T >
Constraint_System Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_constraints (  )  const [inline]

Returns a minimized system of constraints defining *this.

Definition at line 379 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign().

00379                                                 {
00380   strong_reduction_assign();
00381   return constraints();
00382 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::non_redundant_matrix_entries ( std::vector< Bit_Row > &  non_redundant  )  const [inline, private]

Stores into non_redundant information about the matrix entries that are non-redundant (i.e., will occur in strongly reduced matrix).

It is assumed that the OS is not empty and strongly closed; moreover, argument non_redundant is assumed to be empty.

Definition at line 2448 of file Octagonal_Shape.templates.hh.

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::integer_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign_if_exact().

02448                                                                 {
02449   // Private method: the caller has to ensure the following.
02450   PPL_ASSERT(space_dim > 0 && !marked_empty() && marked_strongly_closed());
02451   PPL_ASSERT(nr_rows.empty());
02452 
02453   // Initialize `non_redundant' as if it was an OR_Matrix of booleans
02454   // (initially set to false).
02455   nr_rows.resize(2*space_dim);
02456 
02457   // Step 1: compute zero-equivalence classes.
02458   // Variables corresponding to indices `i' and `j' are zero-equivalent
02459   // if they lie on a zero-weight loop; since the matrix is strongly
02460   // closed, this happens if and only if matrix[i][j] == -matrix[ci][cj].
02461   std::vector<dimension_type> no_sing_leaders;
02462   dimension_type sing_leader = 0;
02463   bool exist_sing_class = false;
02464   std::vector<dimension_type> successor;
02465   compute_successors(successor);
02466   compute_leaders(successor, no_sing_leaders, exist_sing_class, sing_leader);
02467   const dimension_type num_no_sing_leaders = no_sing_leaders.size();
02468 
02469 
02470   // Step 2: flag redundant constraints in `redundancy'.
02471   // Go through non-singular leaders first.
02472   for (dimension_type li = 0; li < num_no_sing_leaders; ++li) {
02473     const dimension_type i = no_sing_leaders[li];
02474     using namespace Implementation::Octagonal_Shapes;
02475     const dimension_type ci = coherent_index(i);
02476     typename OR_Matrix<N>::const_row_reference_type
02477       m_i = *(matrix.row_begin()+i);
02478     if (i % 2 == 0) {
02479       // Each positive equivalence class must have a single 0-cycle
02480       // connecting all equivalent variables in increasing order.
02481       // Note: by coherence assumption, the variables in the
02482       // corresponding negative equivalence class are
02483       // automatically connected.
02484       if (i != successor[i]) {
02485         dimension_type j = i;
02486         dimension_type next_j = successor[j];
02487         while (j != next_j) {
02488           nr_rows[next_j].set(j);
02489           j = next_j;
02490           next_j = successor[j];
02491         }
02492         const dimension_type cj = coherent_index(j);
02493         nr_rows[cj].set(ci);
02494       }
02495     }
02496 
02497     dimension_type rs_li = (li % 2 != 0) ? li :li+1;
02498     // Check if the constraint is redundant.
02499     PPL_DIRTY_TEMP(N, tmp);
02500     for (dimension_type lj = 0 ; lj <= rs_li; ++lj) {
02501       const dimension_type j = no_sing_leaders[lj];
02502       const dimension_type cj = coherent_index(j);
02503       const N& m_i_j = m_i[j];
02504       const N& m_i_ci = m_i[ci];
02505       bool to_add = true;
02506       // Control if the constraint is redundant by strong-coherence,
02507       // that is:
02508       // m_i_j >= (m_i_ci + m_cj_j)/2,   where j != ci.
02509       if (j != ci) {
02510         add_assign_r(tmp, m_i_ci, matrix[cj][j], ROUND_UP);
02511         div_2exp_assign_r(tmp, tmp, 1, ROUND_UP);
02512         if (m_i_j >= tmp)
02513           // The constraint is redundant.
02514           continue;
02515       }
02516       // Control if the constraint is redundant by strong closure, that is
02517       // if there is a path from i to j (i = i_0, ... , i_n = j), such that
02518       // m_i_j = sum_{k=0}^{n-1} m_{i_k}_{i_(k+1)}.
02519       // Since the octagon is already strongly closed, the above relation
02520       // is reduced to three case, in accordance with k, i, j inter-depend:
02521       // exit k such that
02522       // 1.) m_i_j >= m_i_k   + m_cj_ck,   if k < j < i; or
02523       // 2.) m_i_j >= m_i_k   + m_k,_j,    if j < k < i; or
02524       // 3.) m_i_j >= m_ck_ci + m_k_j,     if j < i < k.
02525       // Note: `i > j'.
02526       for (dimension_type lk = 0; lk < num_no_sing_leaders; ++lk) {
02527         const dimension_type k = no_sing_leaders[lk];
02528         if (k != i && k != j) {
02529           dimension_type ck = coherent_index(k);
02530           if (k < j)
02531             // Case 1.
02532             add_assign_r(tmp, m_i[k], matrix[cj][ck], ROUND_UP);
02533           else if (k < i)
02534             // Case 2.
02535             add_assign_r(tmp, m_i[k], matrix[k][j], ROUND_UP);
02536           else
02537             // Case 3.
02538             add_assign_r(tmp, matrix[ck][ci], matrix[k][j], ROUND_UP);
02539 
02540           // Checks if the constraint is redundant.
02541           if (m_i_j >= tmp) {
02542             to_add = false;
02543             break;
02544           }
02545         }
02546       }
02547 
02548       if (to_add)
02549         // The constraint is not redundant.
02550         nr_rows[i].set(j);
02551     }
02552   }
02553 
02554   // If there exist a singular equivalence class, then it must have a
02555   // single 0-cycle connecting all the positive and negative equivalent
02556   // variables.
02557   // Note: the singular class is not connected with the other classes.
02558   if (exist_sing_class) {
02559     nr_rows[sing_leader].set(sing_leader+1);
02560     if (successor[sing_leader+1] != sing_leader+1) {
02561       dimension_type j = sing_leader;
02562       dimension_type next_jj = successor[j+1];
02563       while (next_jj != j+1) {
02564         nr_rows[next_jj].set(j);
02565         j = next_jj;
02566         next_jj = successor[j+1];
02567       }
02568       nr_rows[j+1].set(j);
02569     }
02570     else
02571       nr_rows[sing_leader+1].set(sing_leader);
02572   }
02573 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::OK (  )  const [inline]

Checks if all the invariants are satisfied.

Definition at line 7093 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::is_minus_infinity(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strong_coherent(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::OK(), Parma_Polyhedra_Library::OR_Matrix< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::status, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::time_elapse_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain(), Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign_if_exact().

07093                              {
07094   // Check whether the matrix is well-formed.
07095   if (!matrix.OK())
07096     return false;
07097 
07098   // Check whether the status information is legal.
07099   if (!status.OK())
07100     return false;
07101 
07102   // All empty octagons are OK.
07103   if (marked_empty())
07104     return true;
07105 
07106   // 0-dim universe octagon is OK.
07107   if (space_dim == 0)
07108     return true;
07109 
07110   // MINUS_INFINITY cannot occur at all.
07111   for (typename OR_Matrix<N>::const_row_iterator i = matrix.row_begin(),
07112          matrix_row_end = matrix.row_end(); i != matrix_row_end; ++i) {
07113     typename OR_Matrix<N>::const_row_reference_type x_i = *i;
07114     for (dimension_type j = i.row_size(); j-- > 0; )
07115       if (is_minus_infinity(x_i[j])) {
07116 #ifndef NDEBUG
07117         using namespace Parma_Polyhedra_Library::IO_Operators;
07118         std::cerr << "Octagonal_Shape::"
07119                   << "matrix[" << i.index() << "][" << j << "] = "
07120                   << x_i[j] << "!"
07121                   << std::endl;
07122 #endif
07123         return false;
07124       }
07125   }
07126 
07127   // On the main diagonal only PLUS_INFINITY can occur.
07128   for (typename OR_Matrix<N>::const_row_iterator i = matrix.row_begin(),
07129          m_end = matrix.row_end(); i != m_end; ++i) {
07130     typename OR_Matrix<N>::const_row_reference_type r = *i;
07131     const N& m_i_i = r[i.index()];
07132     if (!is_plus_infinity(m_i_i)) {
07133 #ifndef NDEBUG
07134       const dimension_type j = i.index();
07135       using namespace Parma_Polyhedra_Library::IO_Operators;
07136       std::cerr << "Octagonal_Shape::matrix[" << j << "][" << j << "] = "
07137                 << m_i_i << "!  (+inf was expected.)\n";
07138 #endif
07139       return false;
07140     }
07141   }
07142 
07143   // The following tests might result in false alarms when using floating
07144   // point coefficients: they are only meaningful if the coefficient type
07145   // base is exact (since otherwise strong closure is approximated).
07146   if (std::numeric_limits<coefficient_type_base>::is_exact) {
07147 
07148     // Check whether the closure information is legal.
07149     if (marked_strongly_closed()) {
07150       Octagonal_Shape x = *this;
07151       x.reset_strongly_closed();
07152       x.strong_closure_assign();
07153       if (x.matrix != matrix) {
07154 #ifndef NDEBUG
07155         std::cerr << "Octagonal_Shape is marked as strongly closed "
07156                   << "but it is not!\n";
07157 #endif
07158         return false;
07159       }
07160     }
07161 
07162     // A closed octagon must be strong-coherent.
07163     if (marked_strongly_closed())
07164       if (!is_strong_coherent()) {
07165 #ifndef NDEBUG
07166         std::cerr << "Octagonal_Shape is not strong-coherent!\n";
07167 #endif
07168         return false;
07169       }
07170   }
07171 
07172   // All checks passed.
07173   return true;
07174 }

template<typename T >
Octagonal_Shape< T > & Parma_Polyhedra_Library::Octagonal_Shape< T >::operator= ( const Octagonal_Shape< T > &  y  )  [inline]

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

Definition at line 224 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::status.

00224                                                       {
00225   matrix = y.matrix;
00226   space_dim = y.space_dim;
00227   status = y.status;
00228   return *this;
00229 }

template<typename T>
void Parma_Polyhedra_Library::Octagonal_Shape< T >::print (  )  const

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

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::refine ( Variable  var,
Relation_Symbol  relsym,
const Linear_Expression expr,
Coefficient_traits::const_reference  denominator = Coefficient_one() 
) [inline, private]

Adds to the Octagonal_Shape the constraint $\mathrm{var} \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}$.

Note that the coefficient of var in expr is null.

Definition at line 3863 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_minus_v_pm_u_bounds(), Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_v_pm_u_bounds(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage().

03866                                                                           {
03867   PPL_ASSERT(denominator != 0);
03868   const dimension_type expr_space_dim = expr.space_dimension();
03869   PPL_ASSERT(space_dim >= expr_space_dim);
03870   const dimension_type var_id = var.id();
03871   PPL_ASSERT(var_id <= space_dim);
03872   PPL_ASSERT(expr.coefficient(var) == 0);
03873   PPL_ASSERT(relsym != LESS_THAN && relsym != GREATER_THAN);
03874 
03875   const Coefficient& b = expr.inhomogeneous_term();
03876   // Number of non-zero coefficients in `expr': will be set to
03877   // 0, 1, or 2, the latter value meaning any value greater than 1.
03878   dimension_type t = 0;
03879 
03880   // Variable index of the last non-zero coefficient in `expr', if any.
03881   dimension_type w_id = 0;
03882 
03883   // Get information about the number of non-zero coefficients in `expr'.
03884   for (dimension_type i = expr_space_dim; i-- > 0; )
03885     if (expr.coefficient(Variable(i)) != 0) {
03886       if (t++ == 1)
03887         break;
03888       else
03889         w_id = i;
03890     }
03891 
03892   // Now we know the form of `expr':
03893   // - If t == 0, then expr == b, with `b' a constant;
03894   // - If t == 1, then expr == a*j + b, where `j != v';
03895   // - If t == 2, the `expr' is of the general form.
03896   typedef typename OR_Matrix<N>::row_iterator Row_Iterator;
03897   typedef typename OR_Matrix<N>::row_reference_type Row_Reference;
03898   typedef typename OR_Matrix<N>::const_row_iterator Row_iterator;
03899   typedef typename OR_Matrix<N>::const_row_reference_type Row_reference;
03900 
03901   const Row_Iterator m_begin = matrix.row_begin();
03902   const dimension_type n_var = 2*var_id;
03903   PPL_DIRTY_TEMP_COEFFICIENT(minus_den);
03904   neg_assign(minus_den, denominator);
03905 
03906   // Since we are only able to record octagonal differences, we can
03907   // precisely deal with the case of a single variable only if its
03908   // coefficient (taking into account the denominator) is 1.
03909   // If this is not the case, we fall back to the general case
03910   // so as to over-approximate the constraint.
03911   if (t == 1 && expr.coefficient(Variable(w_id)) != denominator
03912       && expr.coefficient(Variable(w_id)) != minus_den)
03913     t = 2;
03914 
03915   if (t == 0) {
03916     // Case 1: expr == b.
03917     PPL_DIRTY_TEMP_COEFFICIENT(two_b);
03918     two_b = 2*b;
03919     switch (relsym) {
03920     case EQUAL:
03921       // Add the constraint `var == b/denominator'.
03922       add_octagonal_constraint(n_var+1, n_var, two_b, denominator);
03923       add_octagonal_constraint(n_var, n_var+1, two_b, minus_den);
03924       break;
03925     case LESS_OR_EQUAL:
03926       // Add the constraint `var <= b/denominator'.
03927       add_octagonal_constraint(n_var+1, n_var, two_b, denominator);
03928       break;
03929     case GREATER_OR_EQUAL:
03930       // Add the constraint `var >= b/denominator',
03931       // i.e., `-var <= -b/denominator',
03932       add_octagonal_constraint(n_var, n_var+1, two_b, minus_den);
03933       break;
03934     default:
03935       // We already dealt with the other cases.
03936       throw std::runtime_error("PPL internal error");
03937     }
03938   }
03939   else if (t == 1) {
03940     // Value of the one and only non-zero coefficient in `expr'.
03941     const Coefficient& w_coeff = expr.coefficient(Variable(w_id));
03942     const dimension_type n_w = 2*w_id;
03943     switch (relsym) {
03944     case EQUAL:
03945       if (w_coeff == denominator)
03946         // Add the new constraint `var - w = b/denominator'.
03947         if (var_id < w_id) {
03948           add_octagonal_constraint(n_w, n_var, b, denominator);
03949           add_octagonal_constraint(n_w+1, n_var+1, b, minus_den);
03950         }
03951         else {
03952           add_octagonal_constraint(n_var+1, n_w+1, b, denominator);
03953           add_octagonal_constraint(n_var, n_w, b, minus_den);
03954         }
03955       else
03956         // Add the new constraint `var + w = b/denominator'.
03957         if (var_id < w_id) {
03958           add_octagonal_constraint(n_w+1, n_var, b, denominator);
03959           add_octagonal_constraint(n_w, n_var+1, b, minus_den);
03960         }
03961         else {
03962           add_octagonal_constraint(n_var+1, n_w, b, denominator);
03963           add_octagonal_constraint(n_var, n_w+1, b, minus_den);
03964         }
03965       break;
03966     case LESS_OR_EQUAL:
03967       {
03968         PPL_DIRTY_TEMP(N, d);
03969         div_round_up(d, b, denominator);
03970         // Note that: `w_id != v', so that `expr' is of the form
03971         // w_coeff * w + b, with `w_id != v'.
03972         if (w_coeff == denominator) {
03973           // Add the new constraints `v - w <= b/denominator'.
03974           if (var_id < w_id)
03975             add_octagonal_constraint(n_w, n_var, d);
03976           else
03977             add_octagonal_constraint(n_var+1, n_w+1, d);
03978         }
03979         else if (w_coeff == minus_den) {
03980           // Add the new constraints `v + w <= b/denominator'.
03981           if (var_id < w_id)
03982             add_octagonal_constraint(n_w+1, n_var, d);
03983           else
03984             add_octagonal_constraint(n_var+1, n_w, d);
03985         }
03986         break;
03987       }
03988 
03989     case GREATER_OR_EQUAL:
03990       {
03991         PPL_DIRTY_TEMP(N, d);
03992         div_round_up(d, b, minus_den);
03993         // Note that: `w_id != v', so that `expr' is of the form
03994         // w_coeff * w + b, with `w_id != v'.
03995         if (w_coeff == denominator) {
03996           // Add the new constraint `v - w >= b/denominator',
03997           // i.e.,  `-v + w <= -b/denominator'.
03998           if (var_id < w_id)
03999             add_octagonal_constraint(n_w+1, n_var+1, d);
04000           else
04001             add_octagonal_constraint(n_var, n_w, d);
04002         }
04003         else if (w_coeff == minus_den) {
04004           // Add the new constraints `v + w >= b/denominator',
04005           // i.e.,  `-v - w <= -b/denominator'.
04006           if (var_id < w_id)
04007             add_octagonal_constraint(n_w, n_var+1, d);
04008           else
04009             add_octagonal_constraint(n_var, n_w+1, d);
04010         }
04011         break;
04012       }
04013 
04014     default:
04015       // We already dealt with the other cases.
04016       throw std::runtime_error("PPL internal error");
04017     }
04018   }
04019   else {
04020     // Here t == 2, so that
04021     // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2.
04022     const bool is_sc = (denominator > 0);
04023     PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
04024     neg_assign(minus_b, b);
04025     const Coefficient& sc_b = is_sc ? b : minus_b;
04026     const Coefficient& minus_sc_b = is_sc ? minus_b : b;
04027     const Coefficient& sc_den = is_sc ? denominator : minus_den;
04028     const Coefficient& minus_sc_den = is_sc ? minus_den : denominator;
04029     // NOTE: here, for optimization purposes, `minus_expr' is only assigned
04030     // when `denominator' is negative. Do not use it unless you are sure
04031     // it has been correctly assigned.
04032     Linear_Expression minus_expr;
04033     if (!is_sc)
04034       minus_expr = -expr;
04035     const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
04036 
04037     PPL_DIRTY_TEMP(N, sum);
04038     // Index of variable that is unbounded in `this'.
04039     PPL_UNINITIALIZED(dimension_type, pinf_index);
04040     // Number of unbounded variables found.
04041     dimension_type pinf_count = 0;
04042 
04043     switch (relsym) {
04044     case EQUAL:
04045       {
04046         PPL_DIRTY_TEMP(N, neg_sum);
04047         // Index of variable that is unbounded in `this'.
04048         PPL_UNINITIALIZED(dimension_type, neg_pinf_index);
04049         // Number of unbounded variables found.
04050         dimension_type neg_pinf_count = 0;
04051 
04052         // Approximate the inhomogeneous term.
04053         assign_r(sum, sc_b, ROUND_UP);
04054         assign_r(neg_sum, minus_sc_b, ROUND_UP);
04055 
04056         // Approximate the homogeneous part of `sc_expr'.
04057         PPL_DIRTY_TEMP(N, coeff_i);
04058         PPL_DIRTY_TEMP(N, half);
04059         PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
04060         PPL_DIRTY_TEMP(N, minus_coeff_i);
04061         // Note: indices above `w' can be disregarded, as they all have
04062         // a zero coefficient in `sc_expr'.
04063         for (Row_iterator m_iter = m_begin, m_iter_end = m_iter + (2*w_id) + 2;
04064              m_iter != m_iter_end; ) {
04065           const dimension_type n_i = m_iter.index();
04066           const dimension_type id = n_i/2;
04067           Row_reference m_i = *m_iter;
04068           ++m_iter;
04069           Row_reference m_ci = *m_iter;
04070           ++m_iter;
04071           const Coefficient& sc_i = sc_expr.coefficient(Variable(id));
04072           const int sign_i = sgn(sc_i);
04073           if (sign_i > 0) {
04074             assign_r(coeff_i, sc_i, ROUND_UP);
04075             // Approximating `sc_expr'.
04076             if (pinf_count <= 1) {
04077               const N& double_approx_i = m_ci[n_i];
04078               if (!is_plus_infinity(double_approx_i)) {
04079                 // Let half = double_approx_i / 2.
04080                 div_2exp_assign_r(half, double_approx_i, 1, ROUND_UP);
04081                 add_mul_assign_r(sum, coeff_i, half, ROUND_UP);
04082               }
04083               else {
04084                 ++pinf_count;
04085                 pinf_index = id;
04086               }
04087             }
04088             // Approximating `-sc_expr'.
04089             if (neg_pinf_count <= 1) {
04090               const N& double_approx_minus_i = m_i[n_i+1];
04091               if (!is_plus_infinity(double_approx_minus_i)) {
04092                 // Let half = double_approx_minus_i / 2.
04093                 div_2exp_assign_r(half, double_approx_minus_i, 1, ROUND_UP);
04094                 add_mul_assign_r(neg_sum, coeff_i, half, ROUND_UP);
04095               }
04096               else {
04097                 ++neg_pinf_count;
04098                 neg_pinf_index = id;
04099               }
04100             }
04101           }
04102           else if (sign_i < 0) {
04103             neg_assign_r(minus_sc_i, sc_i, ROUND_NOT_NEEDED);
04104             assign_r(minus_coeff_i, minus_sc_i, ROUND_UP);
04105             // Approximating `sc_expr'.
04106             if (pinf_count <= 1) {
04107               const N& double_approx_minus_i = m_i[n_i+1];
04108               if (!is_plus_infinity(double_approx_minus_i)) {
04109                 // Let half = double_approx_minus_i / 2.
04110                 div_2exp_assign_r(half, double_approx_minus_i, 1, ROUND_UP);
04111                 add_mul_assign_r(sum, minus_coeff_i, half, ROUND_UP);
04112               }
04113               else {
04114                 ++pinf_count;
04115                 pinf_index = id;
04116               }
04117             }
04118             // Approximating `-sc_expr'.
04119             if (neg_pinf_count <= 1) {
04120               const N& double_approx_i = m_ci[n_i];
04121               if (!is_plus_infinity(double_approx_i)) {
04122                 // Let half = double_approx_i / 2.
04123                 div_2exp_assign_r(half, double_approx_i, 1, ROUND_UP);
04124                 add_mul_assign_r(neg_sum, minus_coeff_i, half, ROUND_UP);
04125               }
04126               else {
04127                 ++neg_pinf_count;
04128                 neg_pinf_index = id;
04129               }
04130             }
04131           }
04132         }
04133         // Return immediately if no approximation could be computed.
04134         if (pinf_count > 1 && neg_pinf_count > 1) {
04135           PPL_ASSERT(OK());
04136           return;
04137         }
04138 
04139         // In the following, strong closure will be definitely lost.
04140         reset_strongly_closed();
04141 
04142         // Exploit the upper approximation, if possible.
04143         if (pinf_count <= 1) {
04144           // Compute quotient (if needed).
04145           if (sc_den != 1) {
04146             // Before computing quotients, the denominator should be
04147             // approximated towards zero. Since `sc_den' is known to be
04148             // positive, this amounts to rounding downwards, which is
04149             // achieved as usual by rounding upwards `minus_sc_den'
04150             // and negating again the result.
04151             PPL_DIRTY_TEMP(N, down_sc_den);
04152             assign_r(down_sc_den, minus_sc_den, ROUND_UP);
04153             neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
04154             div_assign_r(sum, sum, down_sc_den, ROUND_UP);
04155           }
04156           // Add the upper bound constraint, if meaningful.
04157           if (pinf_count == 0) {
04158             // Add the constraint `v <= sum'.
04159             PPL_DIRTY_TEMP(N, double_sum);
04160             mul_2exp_assign_r(double_sum, sum, 1, ROUND_UP);
04161             matrix[n_var+1][n_var] = double_sum;
04162             // Deduce constraints of the form `v +/- u', where `u != v'.
04163             deduce_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, sum);
04164           }
04165           else
04166             // Here `pinf_count == 1'.
04167             if (pinf_index != var_id) {
04168               const Coefficient& ppi =
04169                 sc_expr.coefficient(Variable(pinf_index));
04170               if (ppi == sc_den)
04171                 // Add the constraint `v - pinf_index <= sum'.
04172                 if (var_id < pinf_index)
04173                   matrix[2*pinf_index][n_var] = sum;
04174                 else
04175                   matrix[n_var+1][2*pinf_index+1] = sum;
04176               else
04177                 if (ppi == minus_sc_den) {
04178                   // Add the constraint `v + pinf_index <= sum'.
04179                   if (var_id < pinf_index)
04180                     matrix[2*pinf_index+1][n_var] = sum;
04181                   else
04182                     matrix[n_var+1][2*pinf_index] = sum;
04183                 }
04184             }
04185         }
04186 
04187         // Exploit the lower approximation, if possible.
04188         if (neg_pinf_count <= 1) {
04189           // Compute quotient (if needed).
04190           if (sc_den != 1) {
04191             // Before computing quotients, the denominator should be
04192             // approximated towards zero. Since `sc_den' is known to be
04193             // positive, this amounts to rounding downwards, which is
04194             // achieved as usual by rounding upwards `minus_sc_den'
04195             // and negating again the result.
04196             PPL_DIRTY_TEMP(N, down_sc_den);
04197             assign_r(down_sc_den, minus_sc_den, ROUND_UP);
04198             neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
04199             div_assign_r(neg_sum, neg_sum, down_sc_den, ROUND_UP);
04200           }
04201           // Add the lower bound constraint, if meaningful.
04202           if (neg_pinf_count == 0) {
04203             // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
04204             PPL_DIRTY_TEMP(N, double_neg_sum);
04205             mul_2exp_assign_r(double_neg_sum, neg_sum, 1, ROUND_UP);
04206             matrix[n_var][n_var+1] = double_neg_sum;
04207             // Deduce constraints of the form `-v +/- u', where `u != v'.
04208             deduce_minus_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, neg_sum);
04209           }
04210           else
04211             // Here `neg_pinf_count == 1'.
04212             if (neg_pinf_index != var_id) {
04213               const Coefficient& npi =
04214                 sc_expr.coefficient(Variable(neg_pinf_index));
04215               if (npi == sc_den)
04216                 // Add the constraint `v - neg_pinf_index >= -neg_sum',
04217                 // i.e., `neg_pinf_index - v <= neg_sum'.
04218                 if (neg_pinf_index < var_id)
04219                   matrix[n_var][2*neg_pinf_index] = neg_sum;
04220                 else
04221                   matrix[2*neg_pinf_index+1][n_var+1] = neg_sum;
04222               else
04223                 if (npi == minus_sc_den) {
04224                   // Add the constraint `v + neg_pinf_index >= -neg_sum',
04225                   // i.e., `-neg_pinf_index - v <= neg_sum'.
04226                   if (neg_pinf_index < var_id)
04227                     matrix[n_var][2*neg_pinf_index+1] = neg_sum;
04228                   else
04229                     matrix[2*neg_pinf_index][n_var+1] = neg_sum;
04230                 }
04231             }
04232         }
04233         break;
04234       }
04235 
04236     case LESS_OR_EQUAL:
04237       {
04238         // Compute an upper approximation for `expr' into `sum',
04239         // taking into account the sign of `denominator'.
04240 
04241         // Approximate the inhomogeneous term.
04242         assign_r(sum, sc_b, ROUND_UP);
04243 
04244         // Approximate the homogeneous part of `sc_expr'.
04245         PPL_DIRTY_TEMP(N, coeff_i);
04246         PPL_DIRTY_TEMP(N, approx_i);
04247         PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
04248         // Note: indices above `w_id' can be disregarded, as they all have
04249         // a zero coefficient in `expr'.
04250         for (Row_Iterator m_iter = m_begin, m_end = m_iter + (2*w_id) + 2;
04251              m_iter != m_end; ) {
04252           const dimension_type n_i = m_iter.index();
04253           const dimension_type id = n_i/2;
04254           Row_Reference m_i = *m_iter;
04255           ++m_iter;
04256           Row_Reference m_ci = *m_iter;
04257           ++m_iter;
04258           const Coefficient& sc_i = sc_expr.coefficient(Variable(id));
04259           const int sign_i = sgn(sc_i);
04260           if (sign_i == 0)
04261             continue;
04262           // Choose carefully: we are approximating `sc_expr'.
04263           const N& double_approx_i = (sign_i > 0) ? m_ci[n_i] : m_i[n_i+1];
04264           if (is_plus_infinity(double_approx_i)) {
04265             if (++pinf_count > 1)
04266               break;
04267             pinf_index = id;
04268             continue;
04269           }
04270           if (sign_i > 0)
04271             assign_r(coeff_i, sc_i, ROUND_UP);
04272           else {
04273             neg_assign(minus_sc_i, sc_i);
04274             assign_r(coeff_i, minus_sc_i, ROUND_UP);
04275           }
04276           div_2exp_assign_r(approx_i, double_approx_i, 1, ROUND_UP);
04277           add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
04278         }
04279         // Divide by the (sign corrected) denominator (if needed).
04280         if (sc_den != 1) {
04281           // Before computing the quotient, the denominator should be
04282           // approximated towards zero. Since `sc_den' is known to be
04283           // positive, this amounts to rounding downwards, which is achieved
04284           // by rounding upwards `minus_sc-den' and negating again the result.
04285           PPL_DIRTY_TEMP(N, down_sc_den);
04286           assign_r(down_sc_den, minus_sc_den, ROUND_UP);
04287           neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
04288           div_assign_r(sum, sum, down_sc_den, ROUND_UP);
04289         }
04290 
04291         if (pinf_count == 0) {
04292           // Add the constraint `v <= sum'.
04293           PPL_DIRTY_TEMP(N, double_sum);
04294           mul_2exp_assign_r(double_sum, sum, 1, ROUND_UP);
04295           add_octagonal_constraint(n_var+1, n_var, double_sum);
04296           // Deduce constraints of the form `v +/- u', where `u != v'.
04297           deduce_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, sum);
04298         }
04299         else if (pinf_count == 1) {
04300           dimension_type pinf_ind = 2*pinf_index;
04301           if (expr.coefficient(Variable(pinf_index)) == denominator ) {
04302             // Add the constraint `v - pinf_index <= sum'.
04303             if (var_id < pinf_index)
04304               add_octagonal_constraint(pinf_ind, n_var, sum);
04305             else
04306               add_octagonal_constraint(n_var+1, pinf_ind+1, sum);
04307           }
04308           else {
04309             if (expr.coefficient(Variable(pinf_index)) == minus_den) {
04310               // Add the constraint `v + pinf_index <= sum'.
04311               if (var_id < pinf_index)
04312                 add_octagonal_constraint(pinf_ind+1, n_var, sum);
04313               else
04314                 add_octagonal_constraint(n_var+1, pinf_ind, sum);
04315             }
04316           }
04317         }
04318         break;
04319       }
04320 
04321     case GREATER_OR_EQUAL:
04322       {
04323         // Compute an upper approximation for `-sc_expr' into `sum'.
04324         // Note: approximating `-sc_expr' from above and then negating the
04325         // result is the same as approximating `sc_expr' from below.
04326 
04327         // Approximate the inhomogeneous term.
04328         assign_r(sum, minus_sc_b, ROUND_UP);
04329 
04330         // Approximate the homogeneous part of `-sc_expr'.
04331         PPL_DIRTY_TEMP(N, coeff_i);
04332         PPL_DIRTY_TEMP(N, approx_i);
04333         PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
04334         for (Row_Iterator m_iter = m_begin, m_end = m_iter + (2*w_id) + 2;
04335              m_iter != m_end; ) {
04336           const dimension_type n_i = m_iter.index();
04337           const dimension_type id = n_i/2;
04338           Row_Reference m_i = *m_iter;
04339           ++m_iter;
04340           Row_Reference m_ci = *m_iter;
04341           ++m_iter;
04342           const Coefficient& sc_i = sc_expr.coefficient(Variable(id));
04343           const int sign_i = sgn(sc_i);
04344           if (sign_i == 0)
04345             continue;
04346           // Choose carefully: we are approximating `-sc_expr'.
04347           const N& double_approx_i = (sign_i > 0) ? m_i[n_i+1] : m_ci[n_i];
04348           if (is_plus_infinity(double_approx_i)) {
04349             if (++pinf_count > 1)
04350               break;
04351             pinf_index = id;
04352             continue;
04353           }
04354           if (sign_i > 0)
04355             assign_r(coeff_i, sc_i, ROUND_UP);
04356           else {
04357             neg_assign(minus_sc_i, sc_i);
04358             assign_r(coeff_i, minus_sc_i, ROUND_UP);
04359           }
04360           div_2exp_assign_r(approx_i, double_approx_i, 1, ROUND_UP);
04361           add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
04362         }
04363 
04364         // Divide by the (sign corrected) denominator (if needed).
04365         if (sc_den != 1) {
04366           // Before computing the quotient, the denominator should be
04367           // approximated towards zero. Since `sc_den' is known to be positive,
04368           // this amounts to rounding downwards, which is achieved by rounding
04369           // upwards `minus_sc_den' and negating again the result.
04370           PPL_DIRTY_TEMP(N, down_sc_den);
04371           assign_r(down_sc_den, minus_sc_den, ROUND_UP);
04372           neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
04373           div_assign_r(sum, sum, down_sc_den, ROUND_UP);
04374         }
04375 
04376         if (pinf_count == 0) {
04377           // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
04378           PPL_DIRTY_TEMP(N, double_sum);
04379           mul_2exp_assign_r(double_sum, sum, 1, ROUND_UP);
04380           add_octagonal_constraint(n_var, n_var+1, double_sum);
04381           // Deduce constraints of the form `-v +/- u', where `u != v'.
04382           deduce_minus_v_pm_u_bounds(var_id, pinf_index, sc_expr, sc_den, sum);
04383         }
04384         else if (pinf_count == 1) {
04385           dimension_type pinf_ind = 2*pinf_index;
04386           if (expr.coefficient(Variable(pinf_index)) == denominator) {
04387             // Add the constraint `v - pinf_index >= -sum',
04388             // i.e., `pinf_index - v <= sum'.
04389             if (pinf_index < var_id)
04390               add_octagonal_constraint(n_var, pinf_ind, sum);
04391             else
04392               add_octagonal_constraint(pinf_ind+1, n_var, sum);
04393           }
04394           else {
04395             if (expr.coefficient(Variable(pinf_index)) == minus_den) {
04396               // Add the constraint `v + pinf_index >= -sum',
04397               // i.e., `-pinf_index - v <= sum'.
04398               if (pinf_index < var_id)
04399                 add_octagonal_constraint(n_var, pinf_ind+1, sum);
04400               else
04401                 add_octagonal_constraint(pinf_ind, n_var+1, sum);
04402             }
04403           }
04404         }
04405         break;
04406       }
04407 
04408     default:
04409       // We already dealt with the other cases.
04410       throw std::runtime_error("PPL internal error");
04411     }
04412   }
04413 }

template<typename T>
template<typename Interval_Info >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_fp_interval_abstract_store ( Box< Interval< T, Interval_Info > > &  store  )  const [inline]

Refines store with the constraints defining *this.

Parameters:
store The interval floating point abstract store to refine.
template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check ( const Congruence cg  )  [inline, private]

Uses the congruence cg to refine *this.

Parameters:
cg The congruence to be added. Nontrivial proper congruences are ignored. Non-octagonal equalities are ignored.
Warning:
If cg and *this are dimension-incompatible, the behavior is undefined.

Definition at line 501 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Congruence::is_proper_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::Congruence::space_dimension().

00501                                                         {
00502   PPL_ASSERT(!marked_empty());
00503   PPL_ASSERT(cg.space_dimension() <= space_dimension());
00504 
00505   if (cg.is_proper_congruence()) {
00506     if (cg.is_inconsistent())
00507       set_empty();
00508     // Other proper congruences are just ignored.
00509     return;
00510   }
00511 
00512   PPL_ASSERT(cg.is_equality());
00513   Constraint c(cg);
00514   refine_no_check(c);
00515 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check ( const Constraint c  )  [inline, private]

Uses the constraint c to refine *this.

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

Definition at line 481 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Octagonal_Shape< T >::extract_octagonal_difference(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Constraint::space_dimension().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraint(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraints().

00481                                                        {
00482   PPL_ASSERT(!marked_empty());
00483   const dimension_type c_space_dim = c.space_dimension();
00484   PPL_ASSERT(c_space_dim <= space_dim);
00485 
00486   dimension_type num_vars = 0;
00487   dimension_type i = 0;
00488   dimension_type j = 0;
00489   PPL_DIRTY_TEMP_COEFFICIENT(coeff);
00490   PPL_DIRTY_TEMP_COEFFICIENT(term);
00491   // Constraints that are not octagonal differences are ignored.
00492   if (!extract_octagonal_difference(c, c_space_dim, num_vars,
00493                                     i, j, coeff, term))
00494     return;
00495 
00496   if (num_vars == 0) {
00497     const Coefficient& c_inhomo = c.inhomogeneous_term();
00498     // Dealing with a trivial constraint (maybe a strict inequality).
00499     if (c_inhomo < 0
00500         || (c_inhomo != 0 && c.is_equality())
00501         || (c_inhomo == 0 && c.is_strict_inequality()))
00502       set_empty();
00503     return;
00504   }
00505 
00506   // Select the cell to be modified for the "<=" part of constraint.
00507   typename OR_Matrix<N>::row_iterator i_iter = matrix.row_begin() + i;
00508   typename OR_Matrix<N>::row_reference_type m_i = *i_iter;
00509   N& m_i_j = m_i[j];
00510   // Set `coeff' to the absolute value of itself.
00511   if (coeff < 0)
00512     neg_assign(coeff);
00513 
00514   bool is_oct_changed = false;
00515   // Compute the bound for `m_i_j', rounding towards plus infinity.
00516   PPL_DIRTY_TEMP(N, d);
00517   div_round_up(d, term, coeff);
00518   if (m_i_j > d) {
00519     m_i_j = d;
00520     is_oct_changed = true;
00521   }
00522 
00523   if (c.is_equality()) {
00524     // Select the cell to be modified for the ">=" part of constraint.
00525     if (i % 2 == 0)
00526       ++i_iter;
00527     else
00528       --i_iter;
00529 
00530     typename OR_Matrix<N>::row_reference_type m_ci = *i_iter;
00531     using namespace Implementation::Octagonal_Shapes;
00532     dimension_type cj = coherent_index(j);
00533     N& m_ci_cj = m_ci[cj];
00534     // Also compute the bound for `m_ci_cj', rounding towards plus infinity.
00535     neg_assign(term);
00536     div_round_up(d, term, coeff);
00537     if (m_ci_cj > d) {
00538       m_ci_cj = d;
00539       is_oct_changed = true;
00540     }
00541   }
00542 
00543   // This method does not preserve closure.
00544   if (is_oct_changed && marked_strongly_closed())
00545     reset_strongly_closed();
00546   PPL_ASSERT(OK());
00547 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruence ( const Congruence cg  )  [inline]

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

Parameters:
cg The congruence. If it is not a octagonal equality, it will be ignored.
Exceptions:
std::invalid_argument Thrown if *this and congruence cg are dimension-incompatible.

Definition at line 476 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Congruence::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

00476                                                                {
00477   const dimension_type cg_space_dim = cg.space_dimension();
00478   // Dimension-compatibility check.
00479   if (cg_space_dim > space_dimension())
00480     throw_dimension_incompatible("refine_with_congruence(cg)", cg);
00481 
00482   if (!marked_empty())
00483     refine_no_check(cg);
00484 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruences ( const Congruence_System cgs  )  [inline]

Uses a copy of the congruences in cgs to refine the system of octagonal constraints defining *this.

Parameters:
cgs The congruence system to be used. Congruences that are not octagonal equalities are ignored.
Exceptions:
std::invalid_argument Thrown if *this and cgs are dimension-incompatible.

Definition at line 488 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Congruence_System::begin(), Parma_Polyhedra_Library::Congruence_System::end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Congruence_System::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape().

00488                                                                         {
00489   // Dimension-compatibility check.
00490   if (cgs.space_dimension() > space_dimension())
00491     throw_generic("refine_with_congruences(cgs)",
00492                   "cgs and *this are space-dimension incompatible");
00493 
00494   for (Congruence_System::const_iterator i = cgs.begin(),
00495          cgs_end = cgs.end(); !marked_empty() && i != cgs_end; ++i)
00496     refine_no_check(*i);
00497 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraint ( const Constraint c  )  [inline]

Uses a copy of constraint c to refine the system of octagonal constraints defining *this.

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

Definition at line 452 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

00452                                                               {
00453   // Dimension-compatibility check.
00454   if (c.space_dimension() > space_dimension())
00455     throw_dimension_incompatible("refine_with_constraint(c)", c);
00456 
00457   if (!marked_empty())
00458     refine_no_check(c);
00459 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraints ( const Constraint_System cs  )  [inline]

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

Parameters:
cs The constraint system to be used. Constraints that are not octagonal are ignored.
Exceptions:
std::invalid_argument Thrown if *this and cs are dimension-incompatible.

Definition at line 463 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape().

00463                                                                        {
00464   // Dimension-compatibility check.
00465   if (cs.space_dimension() > space_dimension())
00466     throw_generic("refine_with_constraints(cs)",
00467                   "cs and *this are space-dimension incompatible");
00468 
00469   for (Constraint_System::const_iterator i = cs.begin(),
00470          cs_end = cs.end(); !marked_empty() && i != cs_end; ++i)
00471     refine_no_check(*i);
00472 }

template<typename T >
Poly_Gen_Relation Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with ( const Generator g  )  const [inline]

Returns the relations holding between *this and the generator g.

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

Definition at line 1678 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::add_mul_assign(), Parma_Polyhedra_Library::Generator::coefficient(), Parma_Polyhedra_Library::Coefficient_zero(), Parma_Polyhedra_Library::Generator::divisor(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::Generator::is_line(), Parma_Polyhedra_Library::Generator::is_line_or_ray(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Poly_Gen_Relation::nothing(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Generator::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Poly_Gen_Relation::subsumes(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

01678                                                           {
01679   const dimension_type g_space_dim = g.space_dimension();
01680 
01681   // Dimension-compatibility check.
01682   if (space_dim < g_space_dim)
01683     throw_dimension_incompatible("relation_with(g)", g);
01684 
01685   // The closure needs to make explicit the implicit constraints and if the
01686   // octagon is empty.
01687   strong_closure_assign();
01688 
01689   // The empty octagon cannot subsume a generator.
01690   if (marked_empty())
01691     return Poly_Gen_Relation::nothing();
01692 
01693   // A universe octagon in a zero-dimensional space subsumes
01694   // all the generators of a zero-dimensional space.
01695   if (space_dim == 0)
01696     return Poly_Gen_Relation::subsumes();
01697 
01698   const bool is_line = g.is_line();
01699   const bool is_line_or_ray = g.is_line_or_ray();
01700 
01701   // The relation between the octagon and the given generator is obtained
01702   // checking if the generator satisfies all the constraints in the octagon.
01703   // To check if the generator satisfies all the constraints it's enough
01704   // studying the sign of the scalar product between the generator and
01705   // all the constraints in the octagon.
01706 
01707   typedef typename OR_Matrix<N>::const_row_iterator Row_Iterator;
01708   typedef typename OR_Matrix<N>::const_row_reference_type Row_Reference;
01709 
01710   const Row_Iterator m_begin = matrix.row_begin();
01711   const Row_Iterator m_end = matrix.row_end();
01712 
01713   PPL_DIRTY_TEMP_COEFFICIENT(num);
01714   PPL_DIRTY_TEMP_COEFFICIENT(den);
01715   PPL_DIRTY_TEMP_COEFFICIENT(product);
01716 
01717   // We find in `*this' all the constraints.
01718   for (Row_Iterator i_iter = m_begin; i_iter != m_end; i_iter += 2) {
01719     dimension_type i = i_iter.index();
01720     Row_Reference m_i = *i_iter;
01721     Row_Reference m_ii = *(i_iter+1);
01722     const N& m_i_ii = m_i[i+1];
01723     const N& m_ii_i = m_ii[i];
01724     // We have the unary constraints.
01725     const Variable x(i/2);
01726     const Coefficient& g_coeff_x
01727       = (x.space_dimension() > g_space_dim)
01728       ? Coefficient_zero()
01729       : g.coefficient(x);
01730     if (is_additive_inverse(m_i_ii, m_ii_i)) {
01731       // The constraint has form ax = b.
01732       // To satisfy the constraint it's necessary that the scalar product
01733       // is not zero. The scalar product has the form:
01734       // 'den * g_coeff_x - num * g.divisor()'.
01735       numer_denom(m_ii_i, num, den);
01736       den *= 2;
01737       product = den * g_coeff_x;
01738       // Note that if the generator `g' is a line or a ray,
01739       // its divisor is zero.
01740       if (!is_line_or_ray) {
01741         neg_assign(num);
01742         add_mul_assign(product, num, g.divisor());
01743       }
01744       if (product != 0)
01745         return Poly_Gen_Relation::nothing();
01746     }
01747     // We have 0, 1 or 2 inequality constraints.
01748     else {
01749       if (!is_plus_infinity(m_i_ii)) {
01750         // The constraint has form -ax <= b.
01751         // If the generator is a line it's necessary to check if
01752         // the scalar product is not zero, if it is positive otherwise.
01753         numer_denom(m_i_ii, num, den);
01754         den *= -2;
01755         product = den * g_coeff_x;
01756         // Note that if the generator `g' is a line or a ray,
01757         // its divisor is zero.
01758         if (!is_line_or_ray) {
01759           neg_assign(num);
01760           add_mul_assign(product, num, g.divisor());
01761         }
01762         if (is_line && product != 0)
01763           return Poly_Gen_Relation::nothing();
01764         else
01765           // If the generator is not a line it's necessary to check
01766           // that the scalar product sign is not positive and the scalar
01767           // product has the form:
01768           // '-den * g.coeff_x - num * g.divisor()'.
01769           if (product > 0)
01770             return Poly_Gen_Relation::nothing();
01771       }
01772       if (!is_plus_infinity(m_ii_i)) {
01773         // The constraint has form ax <= b.
01774         numer_denom(m_ii_i, num, den);
01775         den *= 2;
01776         product = den * g_coeff_x;
01777          // Note that if the generator `g' is a line or a ray,
01778         // its divisor is zero.
01779         if (!is_line_or_ray) {
01780           neg_assign(num);
01781           add_mul_assign(product, num , g.divisor());
01782         }
01783         if (is_line && product != 0)
01784           return Poly_Gen_Relation::nothing();
01785         else
01786           // If the generator is not a line it's necessary to check
01787           // that the scalar product sign is not positive and the scalar
01788           // product has the form:
01789           // 'den * g_coeff_x - num * g.divisor()'.
01790           if (product > 0)
01791             return Poly_Gen_Relation::nothing();
01792       }
01793     }
01794   }
01795 
01796   // We have the binary constraints.
01797   for (Row_Iterator i_iter = m_begin ; i_iter != m_end; i_iter += 2) {
01798     dimension_type i = i_iter.index();
01799     Row_Reference m_i = *i_iter;
01800     Row_Reference m_ii = *(i_iter+1);
01801     for (dimension_type j = 0; j < i; j += 2) {
01802       const N& m_i_j = m_i[j];
01803       const N& m_ii_jj = m_ii[j+1];
01804       const N& m_ii_j = m_ii[j];
01805       const N& m_i_jj = m_i[j+1];
01806       const Variable x(j/2);
01807       const Variable y(i/2);
01808       const Coefficient& g_coeff_x
01809         = (x.space_dimension() > g_space_dim)
01810         ? Coefficient_zero()
01811         : g.coefficient(x);
01812       const Coefficient& g_coeff_y
01813         = (y.space_dimension() > g_space_dim)
01814         ? Coefficient_zero()
01815         : g.coefficient(y);
01816 
01817       const bool difference_is_equality = is_additive_inverse(m_ii_jj, m_i_j);
01818       if (difference_is_equality) {
01819         // The constraint has form ax - ay = b.
01820         // The scalar product has the form
01821         // 'den * coeff_x - den * coeff_y - num * g.divisor()'.
01822         // To satisfy the constraint it's necessary that the scalar product
01823         // is not zero.
01824         numer_denom(m_i_j, num, den);
01825         product = den * g_coeff_x;
01826         neg_assign(den);
01827         add_mul_assign(product, den, g_coeff_y);
01828         // Note that if the generator `g' is a line or a ray,
01829         // its divisor is zero.
01830         if (!is_line_or_ray) {
01831           neg_assign(num);
01832           add_mul_assign(product, num, g.divisor());
01833         }
01834         if (product != 0)
01835           return Poly_Gen_Relation::nothing();
01836       }
01837       else {
01838         if (!is_plus_infinity(m_i_j)) {
01839           // The constraint has form ax - ay <= b.
01840           // The scalar product has the form
01841           // 'den * coeff_x - den * coeff_y - num * g.divisor()'.
01842           // If the generator is not a line it's necessary to check
01843           // that the scalar product sign is not positive.
01844           numer_denom(m_i_j, num, den);
01845           product = den * g_coeff_x;
01846           neg_assign(den);
01847           add_mul_assign(product, den, g_coeff_y);
01848           // Note that if the generator `g' is a line or a ray,
01849           // its divisor is zero.
01850           if (!is_line_or_ray) {
01851             neg_assign(num);
01852             add_mul_assign(product, num, g.divisor());
01853           }
01854           if (is_line && product != 0)
01855             return Poly_Gen_Relation::nothing();
01856           else if (product > 0)
01857             return Poly_Gen_Relation::nothing();
01858         }
01859         if (!is_plus_infinity(m_ii_jj)) {
01860           // The constraint has form -ax + ay <= b.
01861           // The scalar product has the form
01862           // '-den * coeff_x + den * coeff_y - num * g.divisor()'.
01863           // If the generator is not a line it's necessary to check
01864           // that the scalar product sign is not positive.
01865           numer_denom(m_ii_jj, num, den);
01866           product = den * g_coeff_y;
01867           neg_assign(den);
01868           add_mul_assign(product, den, g_coeff_x);
01869           // Note that if the generator `g' is a line or a ray,
01870           // its divisor is zero.
01871           if (!is_line_or_ray) {
01872             neg_assign(num);
01873             add_mul_assign(product, num, g.divisor());
01874           }
01875           if (is_line && product != 0)
01876             return Poly_Gen_Relation::nothing();
01877           else if (product > 0)
01878             return Poly_Gen_Relation::nothing();
01879         }
01880       }
01881 
01882       const bool sum_is_equality = is_additive_inverse(m_i_jj, m_ii_j);
01883       if (sum_is_equality) {
01884         // The constraint has form ax + ay = b.
01885         // The scalar product has the form
01886         // 'den * coeff_x + den * coeff_y - num * g.divisor()'.
01887         // To satisfy the constraint it's necessary that the scalar product
01888         // is not zero.
01889         numer_denom(m_ii_j, num, den);
01890         product = den * g_coeff_x;
01891         add_mul_assign(product, den, g_coeff_y);
01892         // Note that if the generator `g' is a line or a ray,
01893         // its divisor is zero.
01894         if (!is_line_or_ray) {
01895           neg_assign(num);
01896           add_mul_assign(product, num, g.divisor());
01897         }
01898         if (product != 0)
01899           return Poly_Gen_Relation::nothing();
01900       }
01901       else {
01902         if (!is_plus_infinity(m_i_jj)) {
01903           // The constraint has form -ax - ay <= b.
01904           // The scalar product has the form
01905           // '-den * coeff_x - den * coeff_y - num * g.divisor()'.
01906           // If the generator is not a line it's necessary to check
01907           // that the scalar product sign is not positive.
01908           numer_denom(m_i_jj, num, den);
01909           neg_assign(den);
01910           product = den * g_coeff_x;
01911           add_mul_assign(product, den, g_coeff_y);
01912           // Note that if the generator `g' is a line or a ray,
01913           // its divisor is zero.
01914           if (!is_line_or_ray) {
01915             neg_assign(num);
01916             add_mul_assign(product, num, g.divisor());
01917           }
01918           if (is_line && product != 0)
01919             return Poly_Gen_Relation::nothing();
01920           else if (product > 0)
01921             return Poly_Gen_Relation::nothing();
01922         }
01923         if (!is_plus_infinity(m_ii_j)) {
01924           // The constraint has form ax + ay <= b.
01925           // The scalar product has the form
01926           // 'den * coeff_x + den * coeff_y - num * g.divisor()'.
01927           // If the generator is not a line it's necessary to check
01928           // that the scalar product sign is not positive.
01929           numer_denom(m_ii_j, num, den);
01930           product = den * g_coeff_x;
01931           add_mul_assign(product, den, g_coeff_y);
01932           // Note that if the generator `g' is a line or a ray,
01933           // its divisor is zero.
01934           if (!is_line_or_ray) {
01935             neg_assign(num);
01936             add_mul_assign(product, num, g.divisor());
01937           }
01938           if (is_line && product != 0)
01939             return Poly_Gen_Relation::nothing();
01940           else if (product > 0)
01941             return Poly_Gen_Relation::nothing();
01942         }
01943       }
01944     }
01945   }
01946   // If this point is reached the constraint 'g' satisfies
01947   // all the constraints in the octagon.
01948   return Poly_Gen_Relation::subsumes();
01949 }

template<typename T >
Poly_Con_Relation Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with ( const Congruence cg  )  const [inline]

Returns the relations holding between *this and the congruence cg.

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

Definition at line 1339 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Checked::le, Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::maximize(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimize(), Parma_Polyhedra_Library::Congruence::modulus(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Congruence::space_dimension(), Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

01339                                                             {
01340   dimension_type cg_space_dim = cg.space_dimension();
01341 
01342   // Dimension-compatibility check.
01343   if (cg_space_dim > space_dim)
01344     throw_dimension_incompatible("relation_with(cg)", cg);
01345 
01346   // If the congruence is an equality,
01347   // find the relation with the equivalent equality constraint.
01348   if (cg.is_equality()) {
01349     Constraint c(cg);
01350     return relation_with(c);
01351   }
01352 
01353   strong_closure_assign();
01354 
01355   if (marked_empty())
01356     return Poly_Con_Relation::saturates()
01357       && Poly_Con_Relation::is_included()
01358       && Poly_Con_Relation::is_disjoint();
01359 
01360   if (space_dim == 0) {
01361     if (cg.is_inconsistent())
01362       return Poly_Con_Relation::is_disjoint();
01363     else
01364       return Poly_Con_Relation::saturates()
01365         && Poly_Con_Relation::is_included();
01366   }
01367 
01368   // Find the lower bound for a hyperplane with direction
01369   // defined by the congruence.
01370   Linear_Expression le = Linear_Expression(cg);
01371   PPL_DIRTY_TEMP_COEFFICIENT(min_num);
01372   PPL_DIRTY_TEMP_COEFFICIENT(min_den);
01373   bool min_included;
01374   bool bounded_below = minimize(le, min_num, min_den, min_included);
01375 
01376   // If there is no lower bound, then some of the hyperplanes defined by
01377   // the congruence will strictly intersect the shape.
01378   if (!bounded_below)
01379     return Poly_Con_Relation::strictly_intersects();
01380 
01381   // TODO: Consider adding a max_and_min() method, performing both
01382   // maximization and minimization so as to possibly exploit
01383   // incrementality of the MIP solver.
01384 
01385   // Find the upper bound for a hyperplane with direction
01386   // defined by the congruence.
01387   PPL_DIRTY_TEMP_COEFFICIENT(max_num);
01388   PPL_DIRTY_TEMP_COEFFICIENT(max_den);
01389   bool max_included;
01390   bool bounded_above = maximize(le, max_num, max_den, max_included);
01391 
01392   // If there is no upper bound, then some of the hyperplanes defined by
01393   // the congruence will strictly intersect the shape.
01394   if (!bounded_above)
01395     return Poly_Con_Relation::strictly_intersects();
01396 
01397   PPL_DIRTY_TEMP_COEFFICIENT(signed_distance);
01398 
01399   // Find the position value for the hyperplane that satisfies the congruence
01400   // and is above the lower bound for the shape.
01401   PPL_DIRTY_TEMP_COEFFICIENT(min_value);
01402   min_value = min_num / min_den;
01403   const Coefficient& modulus = cg.modulus();
01404   signed_distance = min_value % modulus;
01405   min_value -= signed_distance;
01406   if (min_value * min_den < min_num)
01407     min_value += modulus;
01408 
01409   // Find the position value for the hyperplane that satisfies the congruence
01410   // and is below the upper bound for the shape.
01411   PPL_DIRTY_TEMP_COEFFICIENT(max_value);
01412   max_value = max_num / max_den;
01413   signed_distance = max_value % modulus;
01414   max_value += signed_distance;
01415   if (max_value * max_den > max_num)
01416     max_value -= modulus;
01417 
01418   // If the upper bound value is less than the lower bound value,
01419   // then there is an empty intersection with the congruence;
01420   // otherwise it will strictly intersect.
01421   if (max_value < min_value)
01422     return Poly_Con_Relation::is_disjoint();
01423   else
01424     return Poly_Con_Relation::strictly_intersects();
01425 }

template<typename T >
Poly_Con_Relation Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with ( const Constraint c  )  const [inline]

Returns the relations holding between *this and the constraint c.

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

Definition at line 1429 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Octagonal_Shape< T >::extract_octagonal_difference(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Constraint::is_inequality(), Parma_Polyhedra_Library::Constraint::is_nonstrict_inequality(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Checked::le, Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::maximize(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimize(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with().

01429                                                            {
01430   dimension_type c_space_dim = c.space_dimension();
01431 
01432   // Dimension-compatibility check.
01433   if (c_space_dim > space_dim)
01434     throw_dimension_incompatible("relation_with(c)", c);
01435 
01436   // The closure needs to make explicit the implicit constraints.
01437   strong_closure_assign();
01438 
01439   if (marked_empty())
01440     return Poly_Con_Relation::saturates()
01441       && Poly_Con_Relation::is_included()
01442       && Poly_Con_Relation::is_disjoint();
01443 
01444   if (space_dim == 0) {
01445     // Trivially false zero-dimensional constraint.
01446     if ((c.is_equality() && c.inhomogeneous_term() != 0)
01447         || (c.is_inequality() && c.inhomogeneous_term() < 0))
01448       return Poly_Con_Relation::is_disjoint();
01449     else if (c.is_strict_inequality() && c.inhomogeneous_term() == 0)
01450       // The constraint 0 > 0 implicitly defines the hyperplane 0 = 0;
01451       // thus, the zero-dimensional point also saturates it.
01452       return Poly_Con_Relation::saturates()
01453         && Poly_Con_Relation::is_disjoint();
01454 
01455     // Trivially true zero-dimensional constraint.
01456     else if (c.is_equality() || c.inhomogeneous_term() == 0)
01457       return Poly_Con_Relation::saturates()
01458         && Poly_Con_Relation::is_included();
01459     else
01460       // The zero-dimensional point saturates
01461       // neither the positivity constraint 1 >= 0,
01462       // nor the strict positivity constraint 1 > 0.
01463       return Poly_Con_Relation::is_included();
01464   }
01465 
01466   dimension_type num_vars = 0;
01467   dimension_type i = 0;
01468   dimension_type j = 0;
01469   PPL_DIRTY_TEMP_COEFFICIENT(coeff);
01470   PPL_DIRTY_TEMP_COEFFICIENT(c_term);
01471   if (!extract_octagonal_difference(c, c_space_dim, num_vars,
01472                                     i, j, coeff, c_term)) {
01473     // Constraints that are not octagonal differences.
01474     // Use maximize() and minimize() to do much of the work.
01475 
01476     // Find the linear expression for the constraint and use that to
01477     // find if the expression is bounded from above or below and if it
01478     // is, find the maximum and minimum values.
01479     Linear_Expression le;
01480     for (dimension_type k = c_space_dim; k-- > 0; ) {
01481       Variable vk(k);
01482       le += c.coefficient(vk) * vk;
01483     }
01484     PPL_DIRTY_TEMP(Coefficient, max_num);
01485     PPL_DIRTY_TEMP(Coefficient, max_den);
01486     bool max_included;
01487     PPL_DIRTY_TEMP(Coefficient, min_num);
01488     PPL_DIRTY_TEMP(Coefficient, min_den);
01489     bool min_included;
01490     bool bounded_above = maximize(le, max_num, max_den, max_included);
01491     bool bounded_below = minimize(le, min_num, min_den, min_included);
01492     if (!bounded_above) {
01493       if (!bounded_below)
01494         return Poly_Con_Relation::strictly_intersects();
01495       min_num += c.inhomogeneous_term() * min_den;
01496       switch (sgn(min_num)) {
01497       case 1:
01498         if (c.is_equality())
01499           return  Poly_Con_Relation::is_disjoint();
01500         return  Poly_Con_Relation::is_included();
01501       case 0:
01502         if (c.is_strict_inequality() || c.is_equality())
01503           return  Poly_Con_Relation::strictly_intersects();
01504         return  Poly_Con_Relation::is_included();
01505       case -1:
01506         return  Poly_Con_Relation::strictly_intersects();
01507       }
01508     }
01509     if (!bounded_below) {
01510       max_num += c.inhomogeneous_term() * max_den;
01511       switch (sgn(max_num)) {
01512       case 1:
01513         return  Poly_Con_Relation::strictly_intersects();
01514       case 0:
01515         if (c.is_strict_inequality())
01516           return  Poly_Con_Relation::is_disjoint();
01517         return  Poly_Con_Relation::strictly_intersects();
01518       case -1:
01519         return  Poly_Con_Relation::is_disjoint();
01520       }
01521     }
01522     else {
01523       max_num += c.inhomogeneous_term() * max_den;
01524       min_num += c.inhomogeneous_term() * min_den;
01525       switch (sgn(max_num)) {
01526       case 1:
01527         switch (sgn(min_num)) {
01528         case 1:
01529           if (c.is_equality())
01530             return  Poly_Con_Relation::is_disjoint();
01531           return  Poly_Con_Relation::is_included();
01532         case 0:
01533           if (c.is_equality())
01534             return  Poly_Con_Relation::strictly_intersects();
01535           if (c.is_strict_inequality())
01536             return  Poly_Con_Relation::strictly_intersects();
01537           return  Poly_Con_Relation::is_included();
01538         case -1:
01539           return  Poly_Con_Relation::strictly_intersects();
01540         }
01541      case 0:
01542         if (min_num == 0) {
01543           if (c.is_strict_inequality())
01544             return  Poly_Con_Relation::is_disjoint()
01545               && Poly_Con_Relation::saturates();
01546           return  Poly_Con_Relation::is_included()
01547             && Poly_Con_Relation::saturates();
01548         }
01549         if (c.is_strict_inequality())
01550           return  Poly_Con_Relation::is_disjoint();
01551         return  Poly_Con_Relation::strictly_intersects();
01552       case -1:
01553         return  Poly_Con_Relation::is_disjoint();
01554       }
01555     }
01556   }
01557 
01558   if (num_vars == 0) {
01559     // Dealing with a trivial constraint.
01560     switch (sgn(c.inhomogeneous_term())) {
01561     case -1:
01562       return Poly_Con_Relation::is_disjoint();
01563     case 0:
01564       if (c.is_strict_inequality())
01565         return Poly_Con_Relation::saturates()
01566           && Poly_Con_Relation::is_disjoint();
01567       else
01568         return Poly_Con_Relation::saturates()
01569           && Poly_Con_Relation::is_included();
01570     case 1:
01571       if (c.is_equality())
01572         return Poly_Con_Relation::is_disjoint();
01573       else
01574         return Poly_Con_Relation::is_included();
01575     }
01576   }
01577 
01578   // Select the cell to be checked for the "<=" part of constraint.
01579   typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin() + i;
01580   typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter;
01581   const N& m_i_j = m_i[j];
01582   // Set `coeff' to the absolute value of itself.
01583   if (coeff < 0)
01584     neg_assign(coeff);
01585 
01586   // Select the cell to be checked for the ">=" part of constraint.
01587   // Select the right row of the cell.
01588   if (i % 2 == 0)
01589     ++i_iter;
01590   else
01591     --i_iter;
01592   typename OR_Matrix<N>::const_row_reference_type m_ci = *i_iter;
01593   using namespace Implementation::Octagonal_Shapes;
01594   const N& m_ci_cj = m_ci[coherent_index(j)];
01595   PPL_DIRTY_TEMP_COEFFICIENT(numer);
01596   PPL_DIRTY_TEMP_COEFFICIENT(denom);
01597   // The following variables of mpq_class type are used to be precise
01598   // when the octagon is defined by integer constraints.
01599   PPL_DIRTY_TEMP0(mpq_class, q_x);
01600   PPL_DIRTY_TEMP0(mpq_class, q_y);
01601   PPL_DIRTY_TEMP0(mpq_class, d);
01602   PPL_DIRTY_TEMP0(mpq_class, d1);
01603   PPL_DIRTY_TEMP0(mpq_class, c_den);
01604   PPL_DIRTY_TEMP0(mpq_class, q_den);
01605   assign_r(c_den, coeff, ROUND_NOT_NEEDED);
01606   assign_r(d, c_term, ROUND_NOT_NEEDED);
01607   neg_assign_r(d1, d, ROUND_NOT_NEEDED);
01608   div_assign_r(d, d, c_den, ROUND_NOT_NEEDED);
01609   div_assign_r(d1, d1, c_den, ROUND_NOT_NEEDED);
01610 
01611   if (is_plus_infinity(m_i_j)) {
01612     if (!is_plus_infinity(m_ci_cj)) {
01613       // `*this' is in the following form:
01614       // `-m_ci_cj <= v - u'.
01615       // In this case `*this' is disjoint from `c' if
01616       // `-m_ci_cj > d' (`-m_ci_cj >= d' if c is a strict inequality),
01617       // i.e. if `m_ci_cj < d1' (`m_ci_cj <= d1' if c is a strict inequality).
01618       numer_denom(m_ci_cj, numer, denom);
01619       assign_r(q_den, denom, ROUND_NOT_NEEDED);
01620       assign_r(q_y, numer, ROUND_NOT_NEEDED);
01621       div_assign_r(q_y, q_y, q_den, ROUND_NOT_NEEDED);
01622       if (q_y < d1)
01623         return Poly_Con_Relation::is_disjoint();
01624       if (q_y == d1 && c.is_strict_inequality())
01625         return Poly_Con_Relation::is_disjoint();
01626     }
01627 
01628     // In all other cases `*this' intersects `c'.
01629     return Poly_Con_Relation::strictly_intersects();
01630   }
01631 
01632   // Here `m_i_j' is not plus-infinity.
01633   numer_denom(m_i_j, numer, denom);
01634   assign_r(q_den, denom, ROUND_NOT_NEEDED);
01635   assign_r(q_x, numer, ROUND_NOT_NEEDED);
01636   div_assign_r(q_x, q_x, q_den, ROUND_NOT_NEEDED);
01637 
01638   if (!is_plus_infinity(m_ci_cj)) {
01639     numer_denom(m_ci_cj, numer, denom);
01640     assign_r(q_den, denom, ROUND_NOT_NEEDED);
01641     assign_r(q_y, numer, ROUND_NOT_NEEDED);
01642     div_assign_r(q_y, q_y, q_den, ROUND_NOT_NEEDED);
01643     if (q_x == d && q_y == d1) {
01644       if (c.is_strict_inequality())
01645         return Poly_Con_Relation::saturates()
01646           && Poly_Con_Relation::is_disjoint();
01647       else
01648         return Poly_Con_Relation::saturates()
01649           && Poly_Con_Relation::is_included();
01650     }
01651     // `*this' is disjoint from `c' when
01652     // `m_ci_cj < d1' (`m_ci_cj <= d1' if `c' is a strict inequality).
01653     if (q_y < d1)
01654       return Poly_Con_Relation::is_disjoint();
01655     if (q_y == d1 && c.is_strict_inequality())
01656       return Poly_Con_Relation::is_disjoint();
01657   }
01658 
01659   // Here `m_ci_cj' can be also plus-infinity.
01660   // If `c' is an equality, `*this' is disjoint from `c' if
01661   // `m_i_j < d'.
01662   if (d > q_x) {
01663     if (c.is_equality())
01664       return Poly_Con_Relation::is_disjoint();
01665     else
01666       return Poly_Con_Relation::is_included();
01667   }
01668 
01669   if (d == q_x && c.is_nonstrict_inequality())
01670     return Poly_Con_Relation::is_included();
01671 
01672   // In all other cases `*this' intersects `c'.
01673   return Poly_Con_Relation::strictly_intersects();
01674 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_higher_space_dimensions ( dimension_type  new_dimension  )  [inline]

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

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

Definition at line 532 of file Octagonal_Shape.inlines.hh.

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::map_space_dimensions().

00532                                                                    {
00533   // Dimension-compatibility check.
00534   if (new_dimension > space_dim)
00535     throw_dimension_incompatible("remove_higher_space_dimension(nd)",
00536                                  new_dimension);
00537   // The removal of no dimensions from any octagon is a no-op.
00538   // Note that this case also captures the only legal removal of
00539   // dimensions from an octagon in a 0-dim space.
00540   if (new_dimension == space_dim) {
00541     PPL_ASSERT(OK());
00542     return;
00543   }
00544 
00545   strong_closure_assign();
00546   matrix.shrink(new_dimension);
00547   // When we remove all dimensions from a non-empty octagon,
00548   // we obtain the zero-dimensional universe octagon.
00549   if (new_dimension == 0 && !marked_empty())
00550     set_zero_dim_univ();
00551   space_dim = new_dimension;
00552   PPL_ASSERT(OK());
00553 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions ( const Variables_Set vars  )  [inline]

Removes all the specified dimensions.

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

Definition at line 2968 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_zero_dim_univ(), Parma_Polyhedra_Library::OR_Matrix< T >::shrink(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions().

02968                                                                      {
02969   // The removal of no dimensions from any octagon is a no-op.
02970   // Note that this case also captures the only legal removal of
02971   // dimensions from a octagon in a 0-dim space.
02972   if (vars.empty()) {
02973     PPL_ASSERT(OK());
02974     return;
02975   }
02976 
02977   // Dimension-compatibility check.
02978   const dimension_type min_space_dim = vars.space_dimension();
02979   if (space_dim < min_space_dim)
02980     throw_dimension_incompatible("remove_space_dimensions(vs)", min_space_dim);
02981 
02982   const dimension_type new_space_dim = space_dim - vars.size();
02983 
02984   strong_closure_assign();
02985   // When removing _all_ dimensions from an octagon,
02986   // we obtain the zero-dimensional octagon.
02987   if (new_space_dim == 0) {
02988     matrix.shrink(0);
02989     if (!marked_empty())
02990       // We set the zero_dim_univ flag.
02991       set_zero_dim_univ();
02992     space_dim = 0;
02993     PPL_ASSERT(OK());
02994     return;
02995   }
02996 
02997   // We consider every variable and we check if it is to be removed.
02998   // If it is to be removed, we pass to the successive one, elsewhere
02999   // we move its elements in the right position.
03000   Variables_Set::const_iterator vsi = vars.begin();
03001   dimension_type ftr = *vsi;
03002   dimension_type ftr_size = 2*ftr*(ftr+1);
03003   typename OR_Matrix<N>::element_iterator
03004     iter = matrix.element_begin()+ftr_size;
03005 
03006   dimension_type i = ftr + 1;
03007   while (i < space_dim) {
03008     if (vars.count(i) != 0)
03009       ++i;
03010     else {
03011       typename OR_Matrix<N>::row_iterator
03012         row_iter = matrix.row_begin()+2*i;
03013       typename OR_Matrix<N>::row_reference_type
03014         row_ref = *row_iter;
03015       typename OR_Matrix<N>::row_reference_type
03016         row_ref1 = *(++row_iter);
03017       // If variable(j) is to remove, we pass another variable,
03018       // else we shift its cells to up right.
03019       // Attention: first we shift the cells corrispondent to the first
03020       // row of variable(j), then we shift the cells corrispondent to the
03021       // second row. We recall that every variable is represented
03022       // in the `matrix' by two rows and two rows.
03023       for (dimension_type j = 0; j <= i; ++j)
03024         if (vars.count(j) == 0) {
03025           assign_or_swap(*(iter++), row_ref[2*j]);
03026           assign_or_swap(*(iter++), row_ref[2*j+1]);
03027         }
03028       for (dimension_type j = 0; j <= i; ++j)
03029         if (vars.count(j) == 0) {
03030           assign_or_swap(*(iter++), row_ref1[2*j]);
03031           assign_or_swap(*(iter++), row_ref1[2*j+1]);
03032         }
03033       ++i;
03034     }
03035   }
03036   // Update the space dimension.
03037   matrix.shrink(new_space_dim);
03038   space_dim = new_space_dim;
03039   PPL_ASSERT(OK());
03040 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed (  )  [inline, private]

Marks *this as possibly not strongly closed.

Definition at line 102 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::reset_strongly_closed(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::status.

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points_helper(), Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::get_limiting_octagon(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign().

00102                                           {
00103   status.reset_strongly_closed();
00104 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty (  )  [inline, private]
template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed (  )  [inline, private]
template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::set_zero_dim_univ (  )  [inline, private]
template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign ( const Octagonal_Shape< T > &  y  )  [inline]

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

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

Definition at line 2669 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix_at(), Parma_Polyhedra_Library::Octagonal_Shape< T >::non_redundant_matrix_entries(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_zero_dim_univ(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::swap(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::UNIVERSE.

02669                                                                           {
02670   Octagonal_Shape& x = *this;
02671   const dimension_type dim = x.space_dimension();
02672   // Dimension-compatibility check.
02673   if (dim != y.space_dimension())
02674     throw_dimension_incompatible("simplify_using_context_assign(y)", y);
02675 
02676   // Filter away the zero-dimensional case.
02677   if (dim == 0) {
02678     if (y.marked_empty()) {
02679       x.set_zero_dim_univ();
02680       return false;
02681     }
02682     else
02683       return !x.marked_empty();
02684   }
02685 
02686   // Filter away the case where `x' contains `y'
02687   // (this subsumes the case when `y' is empty).
02688   if (x.contains(y)) {
02689     Octagonal_Shape<T> res(dim, UNIVERSE);
02690     x.swap(res);
02691     return false;
02692   }
02693 
02694   typedef typename OR_Matrix<N>::row_iterator Row_Iter;
02695   typedef typename OR_Matrix<N>::const_row_iterator Row_CIter;
02696   typedef typename OR_Matrix<N>::element_iterator Elem_Iter;
02697   typedef typename OR_Matrix<N>::const_element_iterator Elem_CIter;
02698 
02699   // Filter away the case where `x' is empty.
02700   x.strong_closure_assign();
02701   if (x.marked_empty()) {
02702     // Search for a constraint of `y' that is not a tautology.
02703     dimension_type i;
02704     dimension_type j;
02705     // Prefer unary constraints.
02706     for (i = 0; i < 2*dim; i += 2) {
02707       // FIXME: if N is a float or bounded integer type, then
02708       // we also need to check that we are actually able to construct
02709       // a constraint inconsistent wrt this one.
02710       // Use something like !is_maximal()?
02711       if (!is_plus_infinity(y.matrix_at(i, i+1))) {
02712         j = i+1;
02713         goto found;
02714       }
02715       // Use something like !is_maximal()?
02716       if (!is_plus_infinity(y.matrix_at(i+1, i))) {
02717         j = i;
02718         ++i;
02719         goto found;
02720       }
02721     }
02722     // Then search binary constraints.
02723     // TODO: use better iteration scheme.
02724     for (i = 2; i < 2*dim; ++i)
02725       for (j = 0; j < i; ++j) {
02726         // Use something like !is_maximal()?
02727         if (!is_plus_infinity(y.matrix_at(i, j)))
02728           goto found;
02729       }
02730 
02731     // Not found: we were not able to build a constraint contradicting
02732     // one of the constraints in `y': `x' cannot be enlarged.
02733     return false;
02734 
02735   found:
02736     // Found: build a new OS contradicting the constraint found.
02737     PPL_ASSERT(i < dim && j < dim && i != j);
02738     Octagonal_Shape<T> res(dim, UNIVERSE);
02739     // FIXME: compute a proper contradicting constraint.
02740     PPL_DIRTY_TEMP(N, tmp);
02741     assign_r(tmp, 1, ROUND_UP);
02742     add_assign_r(tmp, tmp, y.matrix_at(i, j), ROUND_UP);
02743     // CHECKME: round down is really meant.
02744     neg_assign_r(res.matrix_at(j, i), tmp, ROUND_DOWN);
02745     PPL_ASSERT(!is_plus_infinity(res.matrix_at(j, i)));
02746     x.swap(res);
02747     return false;
02748   }
02749 
02750   // Here `x' and `y' are not empty and strongly closed;
02751   // also, `x' does not contain `y'.
02752   // Let `target' be the intersection of `x' and `y'.
02753   Octagonal_Shape<T> target = x;
02754   target.intersection_assign(y);
02755   const bool bool_result = !target.is_empty();
02756 
02757   // Compute redundancy information for x and ...
02758   // TODO: provide a nicer data structure for redundancy.
02759   std::vector<Bit_Row> x_nonred;
02760   x.non_redundant_matrix_entries(x_nonred);
02761   // ... count the non-redundant constraints.
02762   dimension_type x_num_nonred = 0;
02763   for (size_t i = x_nonred.size(); i-- > 0 ; )
02764     x_num_nonred += x_nonred[i].count_ones();
02765   PPL_ASSERT(x_num_nonred > 0);
02766 
02767   // Let `yy' be a copy of `y': we will keep adding to `yy'
02768   // the non-redundant constraints of `x',
02769   // stopping as soon as `yy' becomes equal to `target'.
02770   Octagonal_Shape<T> yy = y;
02771 
02772   // The constraints added to `yy' will be recorded in `res' ...
02773   Octagonal_Shape<T> res(dim, UNIVERSE);
02774   // ... and we will count them too.
02775   dimension_type res_num_nonred = 0;
02776 
02777   // Compute leader information for `x'.
02778   std::vector<dimension_type> x_leaders;
02779   x.compute_leaders(x_leaders);
02780 
02781   // First go through the unary equality constraints.
02782   // Find the leader of the singular equivalence class (it is even!).
02783   dimension_type sing_leader;
02784   for (sing_leader = 0; sing_leader < 2*dim; sing_leader += 2) {
02785     if (sing_leader == x_leaders[sing_leader]) {
02786       const N& x_s_ss = x.matrix_at(sing_leader, sing_leader+1);
02787       const N& x_ss_s = x.matrix_at(sing_leader+1, sing_leader);
02788       if (is_additive_inverse(x_s_ss, x_ss_s))
02789         // Singular leader found.
02790         break;
02791     }
02792   }
02793 
02794   // Unary equalities have `sing_leader' as a leader.
02795   for (dimension_type i = sing_leader; i < 2*dim; i += 2) {
02796     if (x_leaders[i] != sing_leader)
02797       continue;
02798     // Found a unary equality constraint:
02799     // see if any of the two inequalities have to be added.
02800     const N& x_i_ii = x.matrix_at(i, i+1);
02801     N& yy_i_ii = yy.matrix_at(i, i+1);
02802     if (x_i_ii < yy_i_ii) {
02803       // The \leq inequality is not implied by context.
02804       res.matrix_at(i, i+1) = x_i_ii;
02805       ++res_num_nonred;
02806       // Tighten context `yy' using the newly added constraint.
02807       yy_i_ii = x_i_ii;
02808       yy.reset_strongly_closed();
02809     }
02810     const N& x_ii_i = x.matrix_at(i+1, i);
02811     N& yy_ii_i = yy.matrix_at(i+1, i);
02812     if (x_ii_i < yy_ii_i) {
02813       // The \geq inequality is not implied by context.
02814       res.matrix_at(i+1, i) = x_ii_i;
02815       ++res_num_nonred;
02816       // Tighten context `yy' using the newly added constraint.
02817       yy_ii_i = x_ii_i;
02818       yy.reset_strongly_closed();
02819     }
02820     // Restore strong closure, if it was lost.
02821     if (!yy.marked_strongly_closed()) {
02822       Variable var_i(i/2);
02823       yy.incremental_strong_closure_assign(var_i);
02824       if (target.contains(yy)) {
02825         // Target reached: swap `x' and `res' if needed.
02826         if (res_num_nonred < x_num_nonred) {
02827           res.reset_strongly_closed();
02828           x.swap(res);
02829         }
02830         return bool_result;
02831       }
02832     }
02833   }
02834 
02835   // Go through the binary equality constraints.
02836   for (dimension_type i = 0; i < 2*dim; ++i) {
02837     const dimension_type j = x_leaders[i];
02838     if (j == i || j == sing_leader)
02839       continue;
02840     const N& x_i_j = x.matrix_at(i, j);
02841     PPL_ASSERT(!is_plus_infinity(x_i_j));
02842     N& yy_i_j = yy.matrix_at(i, j);
02843     if (x_i_j < yy_i_j) {
02844       res.matrix_at(i, j) = x_i_j;
02845       ++res_num_nonred;
02846       // Tighten context `yy' using the newly added constraint.
02847       yy_i_j = x_i_j;
02848       yy.reset_strongly_closed();
02849     }
02850     const N& x_j_i = x.matrix_at(j, i);
02851     N& yy_j_i = yy.matrix_at(j, i);
02852     PPL_ASSERT(!is_plus_infinity(x_j_i));
02853     if (x_j_i < yy_j_i) {
02854       res.matrix_at(j, i) = x_j_i;
02855       ++res_num_nonred;
02856       // Tighten context `yy' using the newly added constraint.
02857       yy_j_i = x_j_i;
02858       yy.reset_strongly_closed();
02859     }
02860     // Restore strong closure, if it was lost.
02861     if (!yy.marked_strongly_closed()) {
02862       Variable var_j(j/2);
02863       yy.incremental_strong_closure_assign(var_j);
02864       if (target.contains(yy)) {
02865         // Target reached: swap `x' and `res' if needed.
02866         if (res_num_nonred < x_num_nonred) {
02867           res.reset_strongly_closed();
02868           x.swap(res);
02869         }
02870         return bool_result;
02871       }
02872     }
02873   }
02874 
02875   // Finally go through the (proper) inequality constraints:
02876   // both indices i and j should be leaders.
02877   // FIXME: improve iteration scheme (are we doing twice the work?)
02878   for (dimension_type i = 0; i < 2*dim; ++i) {
02879     if (i != x_leaders[i])
02880       continue;
02881     const Bit_Row& x_nonred_i = x_nonred[i];
02882     for (dimension_type j = 0; j < 2*dim; ++j) {
02883       if (j != x_leaders[j])
02884         continue;
02885       if (i >= j) {
02886         if (!x_nonred_i[j])
02887           continue;
02888       }
02889       else if (!x_nonred[j][i])
02890         continue;
02891       N& yy_i_j = yy.matrix_at(i, j);
02892       const N& x_i_j = x.matrix_at(i, j);
02893       if (x_i_j < yy_i_j) {
02894         res.matrix_at(i, j) = x_i_j;
02895         ++res_num_nonred;
02896         // Tighten context `yy' using the newly added constraint.
02897         yy_i_j = x_i_j;
02898         yy.reset_strongly_closed();
02899         Variable var(i/2);
02900         yy.incremental_strong_closure_assign(var);
02901         if (target.contains(yy)) {
02902           // Target reached: swap `x' and `res' if needed.
02903           if (res_num_nonred < x_num_nonred) {
02904             res.reset_strongly_closed();
02905             x.swap(res);
02906           }
02907           return bool_result;
02908         }
02909       }
02910     }
02911   }
02912   // This point should be unreachable.
02913   throw std::runtime_error("PPL internal error");
02914 }

template<typename T >
dimension_type Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension (  )  const [inline]

Returns the dimension of the vector space enclosing *this.

Definition at line 246 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim.

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruence(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constrains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Octagonal_Shape< T >::frequency(), Parma_Polyhedra_Library::Octagonal_Shape< T >::hash_code(), Parma_Polyhedra_Library::Octagonal_Shape< T >::integer_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::time_elapse_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign_if_exact().

00246                                           {
00247   return space_dim;
00248 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::strictly_contains ( const Octagonal_Shape< T > &  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 611 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::contains().

00611                                                                     {
00612   const Octagonal_Shape<T>& x = *this;
00613   return x.contains(y) && !y.contains(x);
00614 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign (  )  const [inline, private]

Assigns to this->matrix its strong closure.

Strong closure is a necessary condition for the precision and/or the correctness of many methods. It explicitly records into matrix those constraints that are implicitly obtainable by the other ones, therefore obtaining a canonical representation for the OS.

Definition at line 1953 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::min_assign(), Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_coherence_assign().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Octagonal_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::frequency(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_bounded(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign().

01953                                                 {
01954   // Do something only if necessary (zero-dim implies strong closure).
01955   if (marked_empty() || marked_strongly_closed() || space_dim == 0)
01956     return;
01957 
01958   // Even though the octagon will not change, its internal representation
01959   // is going to be modified by the closure algorithm.
01960   Octagonal_Shape& x = const_cast<Octagonal_Shape<T>&>(*this);
01961 
01962   typedef typename OR_Matrix<N>::row_iterator Row_Iterator;
01963   typedef typename OR_Matrix<N>::row_reference_type Row_Reference;
01964 
01965   const dimension_type n_rows = x.matrix.num_rows();
01966   const Row_Iterator m_begin = x.matrix.row_begin();
01967   const Row_Iterator m_end = x.matrix.row_end();
01968 
01969   // Fill the main diagonal with zeros.
01970   for (Row_Iterator i = m_begin; i != m_end; ++i) {
01971     PPL_ASSERT(is_plus_infinity((*i)[i.index()]));
01972     assign_r((*i)[i.index()], 0, ROUND_NOT_NEEDED);
01973   }
01974 
01975   // This algorithm is given by two steps: the first one is a simple
01976   // adaptation of the `shortest-path closure' using the Floyd-Warshall
01977   // algorithm; the second one is the `strong-coherence' algorithm.
01978   // It is important to note that after the strong-coherence,
01979   // the octagon is still shortest-path closed and hence, strongly closed.
01980 
01981   // Recall that, given an index `h', we indicate with `ch' the coherent
01982   // index, i.e., the index such that:
01983   //   ch = h + 1, if h is an even number;
01984   //   ch = h - 1, if h is an odd number.
01985 
01986   typename OR_Matrix<N>::element_iterator iter_ij;
01987   std::vector<N> vec_k(n_rows);
01988   std::vector<N> vec_ck(n_rows);
01989   PPL_DIRTY_TEMP(N, sum1);
01990   PPL_DIRTY_TEMP(N, sum2);
01991   Row_Reference x_k;
01992   Row_Reference x_ck;
01993   Row_Reference x_i;
01994   Row_Reference x_ci;
01995 
01996   // Since the index `j' of the inner loop will go from 0 up to `i',
01997   // the three nested loops have to be executed twice.
01998   for (int twice = 0; twice < 2; ++twice) {
01999 
02000     Row_Iterator x_k_iter = m_begin;
02001     Row_Iterator x_i_iter = m_begin;
02002     for (dimension_type k = 0; k < n_rows; k += 2) {
02003       const dimension_type ck = k+1;
02004       // Re-initialize the element iterator.
02005       iter_ij = x.matrix.element_begin();
02006       // Compute the row references `x_k' and `x_ck'.
02007       x_k  = *x_k_iter;
02008       ++x_k_iter;
02009       x_ck = *x_k_iter;
02010       ++x_k_iter;
02011 
02012       for (dimension_type i = 0; i <= k; i += 2) {
02013         const dimension_type ci = i+1;
02014         // Storing x_k_i == x_ci_ck.
02015         vec_k[i] = x_k[i];
02016         // Storing x_k_ci == x_i_ck.
02017         vec_k[ci] = x_k[ci];
02018         // Storing x_ck_i == x_ci_k.
02019         vec_ck[i] = x_ck[i];
02020         // Storing x_ck_ci == x_i_k.
02021         vec_ck[ci] = x_ck[ci];
02022       }
02023       x_i_iter = x_k_iter;
02024       for (dimension_type i = k+2; i < n_rows; i += 2) {
02025         const dimension_type ci = i+1;
02026         x_i = *x_i_iter;
02027         ++x_i_iter;
02028         x_ci = *x_i_iter;
02029         ++x_i_iter;
02030         // Storing x_k_i == x_ci_ck.
02031         vec_k[i] = x_ci[ck];
02032         // Storing x_k_ci == x_i_ck.
02033         vec_k[ci] = x_i[ck];
02034         // Storing x_ck_i == x_ci_k.
02035         vec_ck[i] = x_ci[k];
02036         // Storing x_ck_ci == x_i_k.
02037         vec_ck[ci] = x_i[k];
02038       }
02039 
02040       for (dimension_type i = 0; i < n_rows; ++i) {
02041         using namespace Implementation::Octagonal_Shapes;
02042         const dimension_type ci = coherent_index(i);
02043         const N& vec_k_ci = vec_k[ci];
02044         const N& vec_ck_ci = vec_ck[ci];
02045         // Unfolding two iterations on `j': this ensures that
02046         // the loop exit condition `j <= i' is OK.
02047         for (dimension_type j = 0; j <= i; ) {
02048           // First iteration:
02049           // sum1 = x_i_k + x_k_j == x_ck_ci + x_k_j;
02050           // sum2 = x_i_ck + x_ck_j == x_k_ci + x_ck_j.
02051           add_assign_r(sum1, vec_ck_ci, vec_k[j], ROUND_UP);
02052           add_assign_r(sum2, vec_k_ci, vec_ck[j], ROUND_UP);
02053           min_assign(sum1, sum2);
02054           min_assign(*iter_ij, sum1);
02055           // Exiting the first iteration: loop index control.
02056           ++j;
02057           ++iter_ij;
02058           // Second iteration: ditto.
02059           add_assign_r(sum1, vec_ck_ci, vec_k[j], ROUND_UP);
02060           add_assign_r(sum2, vec_k_ci, vec_ck[j], ROUND_UP);
02061           min_assign(sum1, sum2);
02062           min_assign(*iter_ij, sum1);
02063           // Exiting the second iteration: loop index control.
02064           ++j;
02065           ++iter_ij;
02066         }
02067       }
02068     }
02069   }
02070 
02071   // Check for emptiness: the octagon is empty if and only if there is a
02072   // negative value in the main diagonal.
02073   for (Row_Iterator i = m_begin; i != m_end; ++i) {
02074     N& x_i_i = (*i)[i.index()];
02075     if (sgn(x_i_i) < 0) {
02076       x.set_empty();
02077       return;
02078     }
02079     else {
02080       PPL_ASSERT(sgn(x_i_i) == 0);
02081       // Restore PLUS_INFINITY on the main diagonal.
02082       assign_r(x_i_i, PLUS_INFINITY, ROUND_NOT_NEEDED);
02083     }
02084   }
02085 
02086   // Step 2: we enforce the strong coherence.
02087   x.strong_coherence_assign();
02088   // The octagon is not empty and it is now strongly closed.
02089   x.set_strongly_closed();
02090 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_coherence_assign (  )  [inline, private]

Applies the strong-coherence step to this->matrix.

Definition at line 2094 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::min_assign(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), and Parma_Polyhedra_Library::OR_Matrix< T >::row_end().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_closure_assign().

02094                                             {
02095   // The strong-coherence is: for every indexes i and j
02096   // m_i_j <= (m_i_ci + m_cj_j)/2
02097   // where ci = i + 1, if i is even number or
02098   //       ci = i - 1, if i is odd.
02099   // Ditto for cj.
02100   PPL_DIRTY_TEMP(N, semi_sum);
02101   for (typename OR_Matrix<N>::row_iterator i_iter = matrix.row_begin(),
02102          i_end = matrix.row_end(); i_iter != i_end; ++i_iter) {
02103     typename OR_Matrix<N>::row_reference_type x_i = *i_iter;
02104     const dimension_type i = i_iter.index();
02105     using namespace Implementation::Octagonal_Shapes;
02106     const N& x_i_ci = x_i[coherent_index(i)];
02107     // Avoid to do unnecessary sums.
02108     if (!is_plus_infinity(x_i_ci))
02109       for (dimension_type j = 0, rs_i = i_iter.row_size(); j < rs_i; ++j)
02110         if (i != j) {
02111           const N& x_cj_j = matrix[coherent_index(j)][j];
02112           if (!is_plus_infinity(x_cj_j)) {
02113             add_assign_r(semi_sum, x_i_ci, x_cj_j, ROUND_UP);
02114             div_2exp_assign_r(semi_sum, semi_sum, 1, ROUND_UP);
02115             min_assign(x_i[j], semi_sum);
02116           }
02117         }
02118   }
02119 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign (  )  const [inline, private]

Removes the redundant constraints from this->matrix.

Definition at line 2409 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strongly_reduced(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::non_redundant_matrix_entries(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_constraints().

02409                                                   {
02410   // Zero-dimensional octagonal shapes are necessarily reduced.
02411   if (space_dim == 0)
02412     return;
02413   strong_closure_assign();
02414   // If `*this' is empty, then there is nothing to reduce.
02415   if (marked_empty())
02416     return;
02417 
02418   // Detect non-redundant constraints.
02419   std::vector<Bit_Row> non_red;
02420   non_redundant_matrix_entries(non_red);
02421 
02422   // Throw away redundant constraints.
02423   Octagonal_Shape<T>& x = const_cast<Octagonal_Shape<T>&>(*this);
02424 #ifndef NDEBUG
02425   const Octagonal_Shape x_copy_before(x);
02426 #endif
02427   typename OR_Matrix<N>::element_iterator x_i = x.matrix.element_begin();
02428   for (dimension_type i = 0; i < 2 * space_dim; ++i) {
02429     const Bit_Row& non_red_i = non_red[i];
02430     for (dimension_type j = 0,
02431            j_end = OR_Matrix<N>::row_size(i); j < j_end; ++j, ++x_i) {
02432       if (!non_red_i[j])
02433         assign_r(*x_i, PLUS_INFINITY, ROUND_NOT_NEEDED);
02434     }
02435   }
02436   x.reset_strongly_closed();
02437 #ifndef NDEBUG
02438   const Octagonal_Shape x_copy_after(x);
02439   PPL_ASSERT(x_copy_before == x_copy_after);
02440   PPL_ASSERT(x.is_strongly_reduced());
02441   PPL_ASSERT(x.OK());
02442 #endif
02443 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::swap ( Octagonal_Shape< T > &  y  )  [inline]
template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_constraint_incompatible ( const char *  method  )  const [inline, private]

Definition at line 7236 of file Octagonal_Shape.templates.hh.

07236                                                                           {
07237   std::ostringstream s;
07238   s << "PPL::Octagonal_Shape::" << method << ":\n"
07239     << "the constraint is incompatible.";
07240   throw std::invalid_argument(s.str());
07241 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible ( const char *  method,
const char *  name_row,
const Linear_Expression y 
) const [inline, private]

Definition at line 7258 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::space_dimension().

07260                                                                  {
07261   std::ostringstream s;
07262   s << "PPL::Octagonal_Shape::" << method << ":\n"
07263     << "this->space_dimension() == " << space_dimension()
07264     << ", " << name_row << "->space_dimension() == "
07265     << y.space_dimension() << ".";
07266   throw std::invalid_argument(s.str());
07267 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible ( const char *  method,
const Generator g 
) const [inline, private]

Definition at line 7225 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Generator::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension().

07226                                                                            {
07227   std::ostringstream s;
07228   s << "PPL::Octagonal_Shape::" << method << ":\n"
07229     << "this->space_dimension() == " << space_dimension()
07230     << ", g->space_dimension == " << g.space_dimension() << ".";
07231   throw std::invalid_argument(s.str());
07232 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible ( const char *  method,
const Congruence cg 
) const [inline, private]

Definition at line 7214 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Congruence::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension().

07215                                                                              {
07216   std::ostringstream s;
07217   s << "PPL::Octagonal_Shape::" << method << ":\n"
07218     << "this->space_dimension() == " << space_dimension()
07219     << ", cg->space_dimension == " << cg.space_dimension() << ".";
07220   throw std::invalid_argument(s.str());
07221 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible ( const char *  method,
const Constraint c 
) const [inline, private]

Definition at line 7203 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Constraint::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension().

07204                                                                             {
07205   std::ostringstream s;
07206   s << "PPL::Octagonal_Shape::" << method << ":\n"
07207     << "this->space_dimension() == " << space_dimension()
07208     << ", c->space_dimension == " << c.space_dimension() << ".";
07209   throw std::invalid_argument(s.str());
07210 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible ( const char *  method,
dimension_type  required_dim 
) const [inline, private]

Definition at line 7192 of file Octagonal_Shape.templates.hh.

07193                                                                   {
07194   std::ostringstream s;
07195   s << "PPL::Octagonal_Shape::" << method << ":\n"
07196     << "this->space_dimension() == " << space_dimension()
07197     << ", required dimension == " << required_dim << ".";
07198   throw std::invalid_argument(s.str());
07199 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible ( const char *  method,
const Octagonal_Shape< T > &  x 
) const [inline, private]

Definition at line 7180 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constrains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::frequency(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::time_elapse_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain(), Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign_if_exact().

07181                                                                {
07182   std::ostringstream s;
07183   s << "PPL::Octagonal_Shape::" << method << ":\n"
07184     << "this->space_dimension() == " << space_dimension()
07185     << ", y->space_dimension() == " << y.space_dimension() << ".";
07186   throw std::invalid_argument(s.str());
07187 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_expression_too_complex ( const char *  method,
const Linear_Expression e 
) const [inline, private]

Definition at line 7246 of file Octagonal_Shape.templates.hh.

07247                                                                  {
07248   using namespace IO_Operators;
07249   std::ostringstream s;
07250   s << "PPL::Octagonal_Shape::" << method << ":\n"
07251     << e << " is too complex.";
07252   throw std::invalid_argument(s.str());
07253 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic ( const char *  method,
const char *  reason 
) const [inline, private]
template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_closure_assign (  )  [inline, private]

Assigns to this->matrix its tight closure.

Note:
This is not marked as a const method, as it may modify the rational-valued geometric shape by cutting away non-integral points. The method is only available if the template parameter T is bound to an integer datatype.

Definition at line 2142 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::is_even(), Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), PPL_COMPILE_TIME_CHECK, Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_coherence_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::integer_upper_bound_assign_if_exact().

02142                                          {
02143   PPL_COMPILE_TIME_CHECK(std::numeric_limits<T>::is_integer,
02144                          "Octagonal_Shape<T>::tight_closure_assign():"
02145                          " T in not an integer datatype.");
02146   // FIXME: this is just an executable specification.
02147   // (The following call could be replaced by shortest-path closure.)
02148   strong_closure_assign();
02149   if (marked_empty())
02150     return;
02151   if (tight_coherence_would_make_empty())
02152     set_empty();
02153   else {
02154     // Tighten the unary constraints.
02155     PPL_DIRTY_TEMP(N, temp_one);
02156     assign_r(temp_one, 1, ROUND_NOT_NEEDED);
02157     const dimension_type space_dim = space_dimension();
02158     for (dimension_type i = 0; i < 2*space_dim; i += 2) {
02159       const dimension_type ci = i+1;
02160       N& mat_i_ci = matrix[i][ci];
02161       if (!is_plus_infinity(mat_i_ci) && !is_even(mat_i_ci))
02162         sub_assign_r(mat_i_ci, mat_i_ci, temp_one, ROUND_UP);
02163       N& mat_ci_i = matrix[ci][i];
02164       if (!is_plus_infinity(mat_ci_i) && !is_even(mat_ci_i))
02165         sub_assign_r(mat_ci_i, mat_ci_i, temp_one, ROUND_UP);
02166     }
02167     // Propagate tightened unary constraints.
02168     strong_coherence_assign();
02169   }
02170   PPL_ASSERT(OK());
02171 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty (  )  const [inline, private]
template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::time_elapse_assign ( const Octagonal_Shape< T > &  y  )  [inline]

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 596 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::swap(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Polyhedron::time_elapse_assign().

00596                                                                {
00597   // Dimension-compatibility check.
00598   if (space_dimension() != y.space_dimension())
00599     throw_dimension_incompatible("time_elapse_assign(y)", y);
00600   // See the polyhedra documentation.
00601   C_Polyhedron px(constraints());
00602   C_Polyhedron py(y.constraints());
00603   px.time_elapse_assign(py);
00604   Octagonal_Shape<T> x(px);
00605   swap(x);
00606   PPL_ASSERT(OK());
00607 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::topological_closure_assign (  )  [inline]

Assigns to *this its topological closure.

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

00317                                                {
00318 }

template<typename T >
memory_size_type Parma_Polyhedra_Library::Octagonal_Shape< T >::total_memory_in_bytes (  )  const [inline]

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

Definition at line 813 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::external_memory_in_bytes().

00813                                                 {
00814   return sizeof(*this) + external_memory_in_bytes();
00815 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain ( const Variables_Set vars  )  [inline]

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

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

Definition at line 3836 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

03836                                                          {
03837   // The cylindrification wrt no dimensions is a no-op.
03838   // This case captures the only legal cylindrification in a 0-dim space.
03839   if (vars.empty())
03840     return;
03841 
03842   // Dimension-compatibility check.
03843   const dimension_type min_space_dim = vars.space_dimension();
03844   if (space_dimension() < min_space_dim)
03845     throw_dimension_incompatible("unconstrain(vs)", min_space_dim);
03846 
03847   // Enforce strong closure for precision.
03848   strong_closure_assign();
03849 
03850   // If the shape is empty, this is a no-op.
03851   if (marked_empty())
03852     return;
03853 
03854   for (Variables_Set::const_iterator vsi = vars.begin(),
03855          vsi_end = vars.end(); vsi != vsi_end; ++vsi)
03856     forget_all_octagonal_constraints(*vsi);
03857   // Strong closure is preserved.
03858   PPL_ASSERT(OK());
03859 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain ( Variable  var  )  [inline]

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

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

Definition at line 3816 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

03816                                                   {
03817   // Dimension-compatibility check.
03818   const dimension_type var_id = var.id();
03819   if (space_dimension() < var_id + 1)
03820     throw_dimension_incompatible("unconstrain(var)", var_id + 1);
03821 
03822   // Enforce strong closure for precision.
03823   strong_closure_assign();
03824 
03825   // If the shape is empty, this is a no-op.
03826   if (marked_empty())
03827     return;
03828 
03829   forget_all_octagonal_constraints(var_id);
03830   // Strong closure is preserved.
03831   PPL_ASSERT(OK());
03832 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign ( const Octagonal_Shape< T > &  y  )  [inline]

Assigns to *this the smallest OS that contains the convex union of *this and y.

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

Definition at line 2577 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::element_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::max_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::integer_upper_bound_assign_if_exact(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign_if_exact().

02577                                                                {
02578   // Dimension-compatibility check.
02579   if (space_dim != y.space_dim)
02580     throw_dimension_incompatible("upper_bound_assign(y)", y);
02581 
02582   // The hull of an octagon `x' with an empty octagon is `x'.
02583   y.strong_closure_assign();
02584   if (y.marked_empty())
02585     return;
02586   strong_closure_assign();
02587   if (marked_empty()) {
02588     *this = y;
02589     return;
02590   }
02591 
02592   // The oct-hull is obtained by computing maxima.
02593   typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin();
02594   for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(),
02595          matrix_element_end = matrix.element_end();
02596        i != matrix_element_end; ++i, ++j)
02597     max_assign(*i, *j);
02598 
02599   // The result is still closed.
02600   PPL_ASSERT(OK());
02601 }

template<typename T >
bool Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign_if_exact ( const Octagonal_Shape< T > &  y  )  [inline]

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

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

Implementation is based on Theorem 6.3 of [BHZ09b].

Definition at line 6450 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::non_redundant_matrix_entries(), Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::swap(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign().

06450                                                                         {
06451   // FIXME, CHECKME: what about inexact computations?
06452 
06453   // Declare a const reference to *this (to avoid accidental modifications).
06454   const Octagonal_Shape& x = *this;
06455   const dimension_type x_space_dim = x.space_dimension();
06456 
06457   if (x_space_dim != y.space_dimension())
06458     throw_dimension_incompatible("upper_bound_assign_if_exact(y)", y);
06459 
06460   // The zero-dim case is trivial.
06461   if (x_space_dim == 0) {
06462     upper_bound_assign(y);
06463     return true;
06464   }
06465   // If `x' or `y' is (known to be) empty, the upper bound is exact.
06466   if (x.marked_empty()) {
06467     *this = y;
06468     return true;
06469   }
06470   else if (y.is_empty())
06471     return true;
06472   else if (x.is_empty()) {
06473     *this = y;
06474     return true;
06475   }
06476 
06477   // Here both `x' and `y' are known to be non-empty.
06478   PPL_ASSERT(x.marked_strongly_closed());
06479   PPL_ASSERT(y.marked_strongly_closed());
06480   // Pre-compute the upper bound of `x' and `y'.
06481   Octagonal_Shape<T> ub(x);
06482   ub.upper_bound_assign(y);
06483 
06484   // Compute redundancy information for x and y.
06485   // TODO: provide a nicer data structure for redundancy.
06486   std::vector<Bit_Row> x_non_red;
06487   x.non_redundant_matrix_entries(x_non_red);
06488   std::vector<Bit_Row> y_non_red;
06489   y.non_redundant_matrix_entries(y_non_red);
06490 
06491   PPL_DIRTY_TEMP(N, lhs);
06492   PPL_DIRTY_TEMP(N, lhs_copy);
06493   PPL_DIRTY_TEMP(N, rhs);
06494   PPL_DIRTY_TEMP(N, temp_zero);
06495   assign_r(temp_zero, 0, ROUND_NOT_NEEDED);
06496 
06497   typedef typename OR_Matrix<N>::const_row_iterator Row_Iterator;
06498   typedef typename OR_Matrix<N>::const_row_reference_type Row_Reference;
06499   const dimension_type n_rows = x.matrix.num_rows();
06500   const Row_Iterator x_m_begin = x.matrix.row_begin();
06501   const Row_Iterator y_m_begin = y.matrix.row_begin();
06502   const Row_Iterator ub_m_begin = ub.matrix.row_begin();
06503 
06504   for (dimension_type i = n_rows; i-- > 0; ) {
06505     const Bit_Row& x_non_red_i = x_non_red[i];
06506     using namespace Implementation::Octagonal_Shapes;
06507     const dimension_type ci = coherent_index(i);
06508     const dimension_type row_size_i = OR_Matrix<N>::row_size(i);
06509     Row_Reference x_i = *(x_m_begin + i);
06510     Row_Reference y_i = *(y_m_begin + i);
06511     Row_Reference ub_i = *(ub_m_begin + i);
06512     const N& ub_i_ci = ub_i[ci];
06513     for (dimension_type j = row_size_i; j-- > 0; ) {
06514       // Check redundancy of x_i_j.
06515       if (!x_non_red_i[j])
06516         continue;
06517       const N& x_i_j = x_i[j];
06518       // Check 1st condition in BHZ09 theorem.
06519       if (x_i_j >= y_i[j])
06520         continue;
06521       const dimension_type cj = coherent_index(j);
06522       const dimension_type row_size_cj = OR_Matrix<N>::row_size(cj);
06523       Row_Reference ub_cj = *(ub_m_begin + cj);
06524       const N& ub_cj_j = ub_cj[j];
06525       for (dimension_type k = 0; k < n_rows; ++k) {
06526         const Bit_Row& y_non_red_k = y_non_red[k];
06527         const dimension_type ck = coherent_index(k);
06528         const dimension_type row_size_k = OR_Matrix<N>::row_size(k);
06529         Row_Reference x_k = *(x_m_begin + k);
06530         Row_Reference y_k = *(y_m_begin + k);
06531         Row_Reference ub_k = *(ub_m_begin + k);
06532         const N& ub_k_ck = ub_k[ck];
06533         // Be careful: for each index h, the diagonal element m[h][h]
06534         // is (by convention) +infty in our implementation; however,
06535         // BHZ09 theorem assumes that it is equal to 0.
06536         const N& ub_k_j = (k == j) ? temp_zero
06537           : (j < row_size_k ? ub_k[j] : ub_cj[ck]);
06538         const N& ub_i_ck = (i == ck) ? temp_zero
06539           : (ck < row_size_i ? ub_i[ck] : ub_k[ci]);
06540 
06541         for (dimension_type ell = row_size_k; ell-- > 0; ) {
06542           // Check redundancy of y_k_ell.
06543           if (!y_non_red_k[ell])
06544             continue;
06545           const N& y_k_ell = y_k[ell];
06546           // Check 2nd condition in BHZ09 theorem.
06547           if (y_k_ell >= x_k[ell])
06548             continue;
06549           const dimension_type cell = coherent_index(ell);
06550           Row_Reference ub_cell = *(ub_m_begin + cell);
06551           const N& ub_i_ell = (i == ell) ? temp_zero
06552             : (ell < row_size_i ? ub_i[ell] : ub_cell[ci]);
06553           const N& ub_cj_ell = (cj == ell) ? temp_zero
06554             : (ell < row_size_cj ? ub_cj[ell] : ub_cell[j]);
06555           // Check 3rd condition in BHZ09 theorem.
06556           add_assign_r(lhs, x_i_j, y_k_ell, ROUND_UP);
06557           add_assign_r(rhs, ub_i_ell, ub_k_j, ROUND_UP);
06558           if (lhs >= rhs)
06559             continue;
06560           // Check 4th condition in BHZ09 theorem.
06561           add_assign_r(rhs, ub_i_ck, ub_cj_ell, ROUND_UP);
06562           if (lhs >= rhs)
06563             continue;
06564           // Check 5th condition in BHZ09 theorem.
06565           assign_r(lhs_copy, lhs, ROUND_NOT_NEEDED);
06566           add_assign_r(lhs, lhs_copy, x_i_j, ROUND_UP);
06567           add_assign_r(rhs, ub_i_ell, ub_i_ck, ROUND_UP);
06568           add_assign_r(rhs, rhs, ub_cj_j, ROUND_UP);
06569           if (lhs >= rhs)
06570             continue;
06571           // Check 6th condition in BHZ09 theorem.
06572           add_assign_r(rhs, ub_k_j, ub_cj_ell, ROUND_UP);
06573           add_assign_r(rhs, rhs, ub_i_ci, ROUND_UP);
06574           if (lhs >= rhs)
06575             continue;
06576           // Check 7th condition of BHZ09 theorem.
06577           add_assign_r(lhs, lhs_copy, y_k_ell, ROUND_UP);
06578           add_assign_r(rhs, ub_i_ell, ub_cj_ell, ROUND_UP);
06579           add_assign_r(rhs, rhs, ub_k_ck, ROUND_UP);
06580           if (lhs >= rhs)
06581             continue;
06582           // Check 8th (last) condition in BHZ09 theorem.
06583           add_assign_r(rhs, ub_k_j, ub_i_ck, ROUND_UP);
06584           add_assign_r(rhs, rhs, ub_cell[ell], ROUND_UP);
06585           if (lhs < rhs)
06586             // All 8 conditions are satisfied:
06587             // upper bound is not exact.
06588             return false;
06589         }
06590       }
06591     }
06592   }
06593 
06594   // The upper bound of x and y is indeed exact.
06595   swap(ub);
06596   PPL_ASSERT(OK());
06597   return true;
06598 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::widening_assign ( const Octagonal_Shape< T > &  y,
unsigned *  tp = 0 
) [inline]

Same as BHMZ05_widening_assign(y, tp).

Definition at line 572 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign().

00572                                                                           {
00573   BHMZ05_widening_assign(y, tp);
00574 }

template<typename T >
void Parma_Polyhedra_Library::Octagonal_Shape< T >::wrap_assign ( const Variables_Set vars,
Bounded_Integer_Type_Width  w,
Bounded_Integer_Type_Representation  r,
Bounded_Integer_Type_Overflow  o,
const Constraint_System pcs = 0,
unsigned  complexity_threshold = 16,
bool  wrap_individually = true 
) [inline]

Wraps the specified dimensions of the vector space.

Parameters:
vars The set of Variable objects corresponding to the space dimensions to be wrapped.
w The width of the bounded integer type corresponding to all the dimensions to be wrapped.
r The representation of the bounded integer type corresponding to all the dimensions to be wrapped.
o The overflow behavior of the bounded integer type corresponding to all the dimensions to be wrapped.
pcs Possibly null pointer to a constraint system whose variables are contained in vars. If *pcs depends on variables not in vars, the behavior is undefined. When non-null, the pointed-to constraint system is assumed to represent the conditional or looping construct guard with respect to which wrapping is performed. Since wrapping requires the computation of upper bounds and due to non-distributivity of constraint refinement over upper bounds, passing a constraint system in this way can be more precise than refining the result of the wrapping operation with the constraints in *pcs.
complexity_threshold A precision parameter of the wrapping operator: higher values result in possibly improved precision.
wrap_individually true if the dimensions should be wrapped individually (something that results in much greater efficiency to the detriment of precision).
Exceptions:
std::invalid_argument Thrown if *pcs is dimension-incompatible with vars, or if *this is dimension-incompatible vars or with *pcs.

Definition at line 557 of file Octagonal_Shape.inlines.hh.

00563                                                         {
00564   Implementation::wrap_assign(*this,
00565                               vars, w, r, o, pcs,
00566                               complexity_threshold, wrap_individually,
00567                               "Octagonal_Shape");
00568 }


Friends And Related Function Documentation

template<typename T>
dimension_type coherent_index ( const dimension_type  i  )  [related]
template<typename Temp , typename To , typename T >
bool euclidean_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const Octagonal_Shape< T > &  x,
const Octagonal_Shape< T > &  y,
Rounding_Dir  dir,
Temp &  tmp0,
Temp &  tmp1,
Temp &  tmp2 
) [related]

Computes the euclidean distance between x and y.

If the euclidean distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.

The direction of the approximation is specified by dir.

All computations are performed using the temporary variables tmp0, tmp1 and tmp2.

Definition at line 684 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().

00690                                       {
00691   // Dimension-compatibility check.
00692   if (x.space_dim != y.space_dim)
00693     return false;
00694 
00695   // Zero-dim OSs are equal if and only if they are both empty or universe.
00696   if (x.space_dim == 0) {
00697     if (x.marked_empty() == y.marked_empty())
00698       assign_r(r, 0, ROUND_NOT_NEEDED);
00699     else
00700       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00701     return true;
00702   }
00703 
00704   // The distance computation requires strong closure.
00705   x.strong_closure_assign();
00706   y.strong_closure_assign();
00707 
00708   // If one of two OSs is empty, then they are equal if and only if
00709   // the other OS is empty too.
00710   if (x.marked_empty() ||  y.marked_empty()) {
00711    if (x.marked_empty() == y.marked_empty())
00712       assign_r(r, 0, ROUND_NOT_NEEDED);
00713     else
00714       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00715    return true;
00716   }
00717 
00718   return euclidean_distance_assign(r, x.matrix, y.matrix, dir,
00719                                    tmp0, tmp1, tmp2);
00720 }

template<typename To , typename T >
bool euclidean_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const Octagonal_Shape< T > &  x,
const Octagonal_Shape< T > &  y,
Rounding_Dir  dir 
) [related]

Computes the euclidean distance between x and y.

If the euclidean distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.

The direction of the approximation is specified by dir.

All computations are performed using variables of type Checked_Number<To, Extended_Number_Policy>.

If the euclidean distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.

The direction of the approximation is specified by dir.

All computations are performed using variables of type Checked_Number<Temp, Extended_Number_Policy>.

Definition at line 725 of file Octagonal_Shape.inlines.hh.

00728                                                   {
00729   typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
00730   PPL_DIRTY_TEMP(Checked_Temp, tmp0);
00731   PPL_DIRTY_TEMP(Checked_Temp, tmp1);
00732   PPL_DIRTY_TEMP(Checked_Temp, tmp2);
00733   return euclidean_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
00734 }

template<typename T>
bool extract_octagonal_difference ( const Constraint c,
dimension_type  c_space_dim,
dimension_type c_num_vars,
dimension_type c_first_var,
dimension_type c_second_var,
Coefficient c_coeff,
Coefficient c_term 
) [related]

Decodes the constraint c as an octagonal difference.

Returns:
true if the constraint c is an octagonal difference; false otherwise.
Parameters:
c The constraint to be decoded.
c_space_dim The space dimension of the constraint c (it is assumed to match the actual space dimension of c).
c_num_vars If true is returned, then it will be set to the number of variables having a non-zero coefficient. The only legal values will therefore be 0, 1 and 2.
c_first_var If true is returned and if c_num_vars is not set to 0, then it will be set to the index of the first variable having a non-zero coefficient in c.
c_second_var If true is returned and if c_num_vars is set to 2, then it will be set to the index of the second variable having a non-zero coefficient in c.
c_coeff If true is returned and if c_num_vars is not set to 0, then it will be set to the value of the first non-zero coefficient in c.
c_term If true is returned and if c_num_vars is not set to 0, then it will be set to the right value of the inhomogeneous term of c.

Definition at line 34 of file Octagonal_Shape.cc.

References Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), and Parma_Polyhedra_Library::Constraint::space_dimension().

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with().

00040                                                        {
00041   // Check for preconditions.
00042   PPL_ASSERT(c.space_dimension() == c_space_dim);
00043   PPL_ASSERT(c_num_vars == 0 && c_first_var == 0 && c_second_var == 0);
00044   // Store the indices of the non-zero components of `c',
00045   dimension_type non_zero_index[2] = { 0, 0 };
00046   // Collect the non-zero components of `c'.
00047   for (dimension_type i = c_space_dim; i-- > 0; )
00048     if (c.coefficient(Variable(i)) != 0) {
00049       if (c_num_vars <= 1)
00050         non_zero_index[c_num_vars++] = i;
00051       else
00052         // Constraint `c' is not an octagonal difference.
00053         return false;
00054     }
00055 
00056   // Make sure that `c' is indeed an octagonal difference,
00057   // i.e., it has one of the following forms:
00058   //           0           <=/= b, if c_num_vars == 0;
00059   //   (+/-) a*x           <=/= b, if c_num_vars == 1;
00060   //   (+/-) a*x (+/-) a*y <=/= b, if c_num_vars == 2.
00061   c_term = c.inhomogeneous_term();
00062   switch (c_num_vars) {
00063   case 2:
00064     {
00065       const Coefficient& c0 = c.coefficient(Variable(non_zero_index[0]));
00066       const Coefficient& c1 = c.coefficient(Variable(non_zero_index[1]));
00067       if (c0 != c1 && c0 != -c1)
00068         // Constraint `c' is not an octagonal difference.
00069         return false;
00070       c_first_var = non_zero_index[0];
00071       c_second_var = non_zero_index[1];
00072       c_first_var *= 2;
00073       if (sgn(c0) < 0)
00074         ++c_first_var;
00075       c_second_var *= 2;
00076       if (sgn(c1) > 0)
00077         ++c_second_var;
00078       c_coeff = c0;
00079     }
00080     break;
00081   case 1:
00082     {
00083       c_term *= 2;
00084       c_first_var = non_zero_index[0];
00085       c_first_var *= 2;
00086       if (sgn(c.coefficient(Variable(non_zero_index[0]))) < 0) {
00087         c_second_var = c_first_var;
00088         ++c_first_var;
00089       }
00090       else
00091         c_second_var = c_first_var + 1;
00092       c_coeff = c.coefficient(Variable(non_zero_index[0]));
00093     }
00094     break;
00095   default:
00096     PPL_ASSERT(c_num_vars == 0);
00097     break;
00098   }
00099   return true;
00100 }

template<typename Temp , typename To , typename T >
bool l_infinity_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const Octagonal_Shape< T > &  x,
const Octagonal_Shape< T > &  y,
Rounding_Dir  dir,
Temp &  tmp0,
Temp &  tmp1,
Temp &  tmp2 
) [related]

Computes the $L_\infty$ distance between x and y.

If the $L_\infty$ distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.

The direction of the approximation is specified by dir.

All computations are performed using the temporary variables tmp0, tmp1 and tmp2.

Definition at line 749 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().

00755                                        {
00756   // Dimension-compatibility check.
00757   if (x.space_dim != y.space_dim)
00758     return false;
00759 
00760   // Zero-dim OSs are equal if and only if they are both empty or universe.
00761   if (x.space_dim == 0) {
00762     if (x.marked_empty() == y.marked_empty())
00763       assign_r(r, 0, ROUND_NOT_NEEDED);
00764     else
00765       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00766     return true;
00767   }
00768 
00769   // The distance computation requires strong closure.
00770   x.strong_closure_assign();
00771   y.strong_closure_assign();
00772 
00773   // If one of two OSs is empty, then they are equal if and only if
00774   // the other OS is empty too.
00775   if (x.marked_empty() ||  y.marked_empty()) {
00776    if (x.marked_empty() == y.marked_empty())
00777       assign_r(r, 0, ROUND_NOT_NEEDED);
00778     else
00779       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00780    return true;
00781   }
00782 
00783   return l_infinity_distance_assign(r, x.matrix, y.matrix, dir,
00784                                     tmp0, tmp1, tmp2);
00785 }

template<typename To , typename T >
bool l_infinity_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const Octagonal_Shape< T > &  x,
const Octagonal_Shape< T > &  y,
Rounding_Dir  dir 
) [related]

Computes the $L_\infty$ distance between x and y.

If the $L_\infty$ distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.

The direction of the approximation is specified by dir.

All computations are performed using variables of type Checked_Number<To, Extended_Number_Policy>.

If the $L_\infty$ distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.

The direction of the approximation is specified by dir.

All computations are performed using variables of type Checked_Number<Temp, Extended_Number_Policy>.

Definition at line 790 of file Octagonal_Shape.inlines.hh.

00793                                                    {
00794   typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
00795   PPL_DIRTY_TEMP(Checked_Temp, tmp0);
00796   PPL_DIRTY_TEMP(Checked_Temp, tmp1);
00797   PPL_DIRTY_TEMP(Checked_Temp, tmp2);
00798   return l_infinity_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
00799 }

template<typename T >
bool operator!= ( const Octagonal_Shape< T > &  x,
const Octagonal_Shape< T > &  y 
) [related]

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

Note that x and y may be dimension-incompatible shapes: in this case, the value true is returned.

Definition at line 351 of file Octagonal_Shape.inlines.hh.

00351                                                                      {
00352   return !(x == y);
00353 }

template<typename T >
std::ostream & operator<< ( std::ostream &  s,
const Octagonal_Shape< T > &  x 
) [related]

Output operator.

Writes a textual representation of oct on s: false is written if oct is an empty polyhedron; true is written if oct is a universe polyhedron; a system of constraints defining oct is written otherwise, all constraints separated by ", ".

Definition at line 6882 of file Octagonal_Shape.templates.hh.

References Parma_Polyhedra_Library::is_additive_inverse(), and Parma_Polyhedra_Library::is_plus_infinity().

06882                                                                    {
06883   // Handle special cases first.
06884   if (x.marked_empty()) {
06885     s << "false";
06886     return s;
06887   }
06888   if (x.is_universe()) {
06889     s << "true";
06890     return s;
06891   }
06892 
06893   typedef typename Octagonal_Shape<T>::coefficient_type N;
06894   typedef typename OR_Matrix<N>::const_row_iterator Row_Iterator;
06895   typedef typename OR_Matrix<N>::const_row_reference_type Row_Reference;
06896 
06897   // Records whether or not we still have to print the first constraint.
06898   bool first = true;
06899 
06900   Row_Iterator m_begin = x.matrix.row_begin();
06901   Row_Iterator m_end = x.matrix.row_end();
06902 
06903   // Temporaries.
06904   PPL_DIRTY_TEMP(N, negation);
06905   PPL_DIRTY_TEMP(N, half);
06906   // Go through all the unary constraints.
06907   // (Note: loop iterator is incremented in the loop body.)
06908   for (Row_Iterator i_iter = m_begin; i_iter != m_end; ) {
06909     const dimension_type i = i_iter.index();
06910     const Variable v_i = Variable(i/2);
06911     const N& x_i_ii = (*i_iter)[i+1];
06912     ++i_iter;
06913     const N& x_ii_i = (*i_iter)[i];
06914     ++i_iter;
06915     // Check whether or not it is an equality constraint.
06916     if (is_additive_inverse(x_i_ii, x_ii_i)) {
06917       // It is an equality.
06918       PPL_ASSERT(!is_plus_infinity(x_i_ii) && !is_plus_infinity(x_ii_i));
06919       if (first)
06920         first = false;
06921       else
06922         s << ", ";
06923       // If the value bound can NOT be divided by 2 exactly,
06924       // then we output the constraint `2*v_i = bound'.
06925       if (div_2exp_assign_r(half, x_ii_i, 1, ROUND_UP | ROUND_STRICT_RELATION) == V_EQ)
06926         s << v_i << " = " << half;
06927       else
06928         s << "2*" << v_i << " = " << x_ii_i;
06929     }
06930     else {
06931       // We will print unary non-strict inequalities, if any.
06932       if (!is_plus_infinity(x_i_ii)) {
06933         if (first)
06934           first = false;
06935         else
06936           s << ", ";
06937         neg_assign_r(negation, x_i_ii, ROUND_NOT_NEEDED);
06938         // If the value bound can NOT be divided by 2 exactly,
06939         // then we output the constraint `2*v_i >= negation'.
06940         if (div_2exp_assign_r(half, negation, 1, ROUND_UP | ROUND_STRICT_RELATION) == V_EQ)
06941           s << v_i << " >= " << half;
06942         else
06943           s << "2*" << v_i << " >= " << negation;
06944       }
06945       if (!is_plus_infinity(x_ii_i)) {
06946         if (first)
06947           first = false;
06948         else
06949           s << ", ";
06950         // If the value bound can NOT be divided by 2 exactly,
06951         // then we output the constraint `2*v_i <= bound'.
06952         if (div_2exp_assign_r(half, x_ii_i, 1, ROUND_UP | ROUND_STRICT_RELATION) == V_EQ)
06953           s << v_i << " <= " << half;
06954         else
06955           s << "2*" << v_i << " <= " << x_ii_i;
06956       }
06957     }
06958   }
06959 
06960   // Go through all the binary constraints.
06961   // (Note: loop iterator is incremented in the loop body.)
06962   for (Row_Iterator i_iter = m_begin; i_iter != m_end; ) {
06963     const dimension_type i = i_iter.index();
06964     const Variable v_i = Variable(i/2);
06965     Row_Reference r_i = *i_iter;
06966     ++i_iter;
06967     Row_Reference r_ii = *i_iter;
06968     ++i_iter;
06969 
06970     for (dimension_type j = 0; j < i; j += 2) {
06971       const Variable v_j = Variable(j/2);
06972       // Print binary differences.
06973       const N& x_ii_jj = r_ii[j+1];
06974       const N& x_i_j = r_i[j];
06975       // Check whether or not it is an equality constraint.
06976       if (is_additive_inverse(x_ii_jj, x_i_j)) {
06977         // It is an equality.
06978         PPL_ASSERT(!is_plus_infinity(x_i_j) && !is_plus_infinity(x_ii_jj));
06979         if (first)
06980           first = false;
06981         else
06982           s << ", ";
06983         if (sgn(x_i_j) >= 0)
06984           s << v_j << " - " << v_i << " = " << x_i_j;
06985         else
06986           s << v_i << " - " << v_j << " = " << x_ii_jj;
06987       }
06988       else {
06989         // We will print non-strict inequalities, if any.
06990         if (!is_plus_infinity(x_i_j)) {
06991           if (first)
06992             first = false;
06993           else
06994             s << ", ";
06995           if (sgn(x_i_j) >= 0)
06996             s << v_j << " - " << v_i << " <= " << x_i_j;
06997           else {
06998             neg_assign_r(negation, x_i_j, ROUND_DOWN);
06999             s << v_i << " - " << v_j << " >= " << negation;
07000           }
07001         }
07002         if (!is_plus_infinity(x_ii_jj)) {
07003           if (first)
07004             first = false;
07005           else
07006             s << ", ";
07007           if (sgn(x_ii_jj) >= 0)
07008             s << v_i << " - " << v_j << " <= " << x_ii_jj;
07009           else {
07010             neg_assign_r(negation, x_ii_jj, ROUND_DOWN);
07011             s << v_j << " - " << v_i << " >= " << negation;
07012           }
07013         }
07014       }
07015       // Print binary sums.
07016       const N& x_i_jj = r_i[j+1];
07017       const N& x_ii_j = r_ii[j];
07018       // Check whether or not it is an equality constraint.
07019       if (is_additive_inverse(x_i_jj, x_ii_j)) {
07020         // It is an equality.
07021         PPL_ASSERT(!is_plus_infinity(x_i_jj) && !is_plus_infinity(x_ii_j));
07022         if (first)
07023           first = false;
07024         else
07025           s << ", ";
07026         s << v_j << " + " << v_i << " = " << x_ii_j;
07027       }
07028       else {
07029         // We will print non-strict inequalities, if any.
07030         if (!is_plus_infinity(x_i_jj)) {
07031           if (first)
07032             first = false;
07033           else
07034             s << ", ";
07035           neg_assign_r(negation, x_i_jj, ROUND_DOWN);
07036           s << v_j << " + " << v_i << " >= " << negation;
07037         }
07038         if (!is_plus_infinity(x_ii_j)) {
07039           if (first)
07040             first = false;
07041           else
07042             s << ", ";
07043           s << v_j << " + " << v_i << " <= " << x_ii_j;
07044         }
07045       }
07046     }
07047   }
07048   return s;
07049 }

template<typename T>
bool operator== ( const Octagonal_Shape< T > &  x,
const Octagonal_Shape< T > &  y 
) [friend]

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

Note that x and y may be dimension-incompatible shapes: in this case, the value false is returned.

Definition at line 323 of file Octagonal_Shape.inlines.hh.

00323                                                                      {
00324   if (x.space_dim != y.space_dim)
00325     // Dimension-incompatible OSs are different.
00326     return false;
00327 
00328   // Zero-dim OSs are equal if and only if they are both empty or universe.
00329   if (x.space_dim == 0) {
00330     if (x.marked_empty())
00331       return y.marked_empty();
00332     else
00333       return !y.marked_empty();
00334   }
00335 
00336   x.strong_closure_assign();
00337   y.strong_closure_assign();
00338   // If one of two octagons is empty, then they are equal if and only if
00339   // the other octagon is empty too.
00340   if (x.marked_empty())
00341     return y.marked_empty();
00342   if (y.marked_empty())
00343     return false;
00344   // Strong closure is a canonical form.
00345   return x.matrix == y.matrix;
00346 }

template<typename T>
friend class Parma_Polyhedra_Library::Box [friend]

Definition at line 1777 of file Octagonal_Shape.defs.hh.

template<typename T>
template<typename Temp , typename To , typename U >
bool Parma_Polyhedra_Library::euclidean_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const Octagonal_Shape< U > &  x,
const Octagonal_Shape< U > &  y,
const Rounding_Dir  dir,
Temp &  tmp0,
Temp &  tmp1,
Temp &  tmp2 
) [friend]
template<typename T>
std::ostream& Parma_Polyhedra_Library::IO_Operators::operator<< ( std::ostream &  s,
const Octagonal_Shape< T > &  c 
) [friend]
template<typename T>
template<typename Temp , typename To , typename U >
bool Parma_Polyhedra_Library::l_infinity_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const Octagonal_Shape< U > &  x,
const Octagonal_Shape< U > &  y,
const Rounding_Dir  dir,
Temp &  tmp0,
Temp &  tmp1,
Temp &  tmp2 
) [friend]
template<typename T>
friend class Parma_Polyhedra_Library::Octagonal_Shape [friend]

Definition at line 1776 of file Octagonal_Shape.defs.hh.

template<typename T>
template<typename Temp , typename To , typename U >
bool Parma_Polyhedra_Library::rectilinear_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const Octagonal_Shape< U > &  x,
const Octagonal_Shape< U > &  y,
const Rounding_Dir  dir,
Temp &  tmp0,
Temp &  tmp1,
Temp &  tmp2 
) [friend]
template<typename Temp , typename To , typename T >
bool rectilinear_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const Octagonal_Shape< T > &  x,
const Octagonal_Shape< T > &  y,
Rounding_Dir  dir,
Temp &  tmp0,
Temp &  tmp1,
Temp &  tmp2 
) [related]

Computes the rectilinear (or Manhattan) distance between x and y.

If the rectilinear distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.

The direction of the approximation is specified by dir.

All computations are performed using the temporary variables tmp0, tmp1 and tmp2.

Definition at line 619 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().

00625                                         {
00626   // Dimension-compatibility check.
00627   if (x.space_dim != y.space_dim)
00628     return false;
00629 
00630   // Zero-dim OSs are equal if and only if they are both empty or universe.
00631   if (x.space_dim == 0) {
00632     if (x.marked_empty() == y.marked_empty())
00633       assign_r(r, 0, ROUND_NOT_NEEDED);
00634     else
00635       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00636     return true;
00637   }
00638 
00639   // The distance computation requires strong closure.
00640   x.strong_closure_assign();
00641   y.strong_closure_assign();
00642 
00643   // If one of two OSs is empty, then they are equal if and only if
00644   // the other OS is empty too.
00645   if (x.marked_empty() ||  y.marked_empty()) {
00646    if (x.marked_empty() == y.marked_empty())
00647       assign_r(r, 0, ROUND_NOT_NEEDED);
00648     else
00649       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00650    return true;
00651   }
00652 
00653   return rectilinear_distance_assign(r, x.matrix, y.matrix, dir,
00654                                      tmp0, tmp1, tmp2);
00655 }

template<typename To , typename T >
bool rectilinear_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const Octagonal_Shape< T > &  x,
const Octagonal_Shape< T > &  y,
Rounding_Dir  dir 
) [related]

Computes the rectilinear (or Manhattan) distance between x and y.

If the rectilinear distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.

The direction of the approximation is specified by dir.

All computations are performed using variables of type Checked_Number<To, Extended_Number_Policy>.

If the rectilinear distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.

The direction of the approximation is specified by dir.

All computations are performed using variables of type Checked_Number<Temp, Extended_Number_Policy>.

Definition at line 660 of file Octagonal_Shape.inlines.hh.

00663                                                     {
00664   typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
00665   PPL_DIRTY_TEMP(Checked_Temp, tmp0);
00666   PPL_DIRTY_TEMP(Checked_Temp, tmp1);
00667   PPL_DIRTY_TEMP(Checked_Temp, tmp2);
00668   return rectilinear_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
00669 }

template<typename T >
void swap ( Parma_Polyhedra_Library::Octagonal_Shape< T > &  x,
Parma_Polyhedra_Library::Octagonal_Shape< T > &  y 
) [related]

Specializes std::swap.

Definition at line 843 of file Octagonal_Shape.inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::swap().

00844                                                    {
00845   x.swap(y);
00846 }


Member Data Documentation

template<typename T>
T Parma_Polyhedra_Library::Octagonal_Shape< T >::default_stop_points[] [static, private]

Definition at line 2162 of file Octagonal_Shape.defs.hh.

template<typename T>
OR_Matrix<N> Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix [private]

The matrix that represents the octagonal shape.

Definition at line 1780 of file Octagonal_Shape.defs.hh.

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::ascii_dump(), Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constrains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Octagonal_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::external_memory_in_bytes(), Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::frequency(), Parma_Polyhedra_Library::Octagonal_Shape< T >::get_limiting_octagon(), Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::integer_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_bounded(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strong_coherent(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strongly_reduced(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_universe(), Parma_Polyhedra_Library::Octagonal_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix_at(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::operator=(), Parma_Polyhedra_Library::Octagonal_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_coherence_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::swap(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign_if_exact().

Dimension of the space of the octagonal shape.

Definition at line 1783 of file Octagonal_Shape.defs.hh.

Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::ascii_dump(), Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Octagonal_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::frequency(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_bounded(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_universe(), Parma_Polyhedra_Library::Octagonal_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_BHMZ05_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::operator=(), Parma_Polyhedra_Library::Octagonal_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::swap(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign().

template<typename T>
Status Parma_Polyhedra_Library::Octagonal_Shape< T >::status [private]

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