Parma_Polyhedra_Library::Octagonal_Shape< T > Class Template Reference

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.

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 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 (without minimizing the result).
void add_congruence (const Congruence &cg)
 Adds a copy of congruence cg to the system of congruences of this (without minimizing the result).
void add_congruences (const Congruence_System &cgs)
 Adds to *this constraints equivalent to the congruences in cgs (without minimizing the result).
void add_recycled_congruences (Congruence_System &cgs)
 Adds the congruences in cs to the system of congruences of *this (without minimizing the result).
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 &to_be_unconstrained)
 Computes the cylindrification of *this with respect to the set of space dimensions to_be_unconstrained, assigning the result to *this.
void intersection_assign (const 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.
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 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 &to_be_removed)
 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 &to_be_folded, Variable var)
 Folds the space dimensions in to_be_folded into var.

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,
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 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 incremental_strong_closure_assign (Variable var) const
 Puts in *this all implicit constraints and computes the tighter ones.
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.
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 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 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 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 & operator<< (std::ostream &s, const Octagonal_Shape< T > &c)
 Output operator.

Related Functions

(Note that these are not member functions.)

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.
dimension_type coherent_index (dimension_type i)
 Returns the index coherent to i.
template<typename T>
void swap (Parma_Polyhedra_Library::Octagonal_Shape< T > &x, Parma_Polyhedra_Library::Octagonal_Shape< T > &y)
 Specializes std::swap.

Classes

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


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. At the interface level, octagonal constraints are specified using objects of type Constraint: such a constraint is an octagonal constraint if it is of 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 Constraint object will be mapped into a correct approximation that, depending on the expressive power of the chosen template argument T, may loose some precision. In particular, constraint objects that do not encode an octagonal constraint will be simply (and safely) ignored.

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

On the other hand, a Constraint object encoding $3x - y \leq 1$ will be safely ignored in all of the above cases.

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);
Since only those constraints having the syntactic form of an octagonal constraint are considered, the following code will build the same OS as above (i.e., the constraints 7, 8, and 9 are ignored):
    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 404 of file Octagonal_Shape.defs.hh.


Member Typedef Documentation

template<typename T>
typedef Checked_Number<T, 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 411 of file Octagonal_Shape.defs.hh.

The numeric base type upon which OSs are built.

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

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

00098   : matrix(num_dimensions), space_dim(num_dimensions), status() {
00099   if (kind == EMPTY)
00100     set_empty();
00101   else if (num_dimensions > 0)
00102     // A (non zero-dim) universe octagon is strongly closed.
00103     set_strongly_closed();
00104   assert(OK());
00105 }

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

00110   : matrix(y.matrix), space_dim(y.space_dim), status(y.status) {
00111 }

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

00120   : matrix((y.strong_closure_assign(), y.matrix)),
00121     space_dim(y.space_dim),
00122     status() {
00123   // TODO: handle flags properly, possibly taking special cases into account.
00124   if (y.marked_empty())
00125     set_empty();
00126   else if (y.marked_zero_dim_univ())
00127     set_zero_dim_univ();
00128 }

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 constraints: constraints that are not octagonal constraints are ignored (even though they may have contributed to the space dimension).
Exceptions:
std::invalid_argument Thrown if the system of constraints cs contains strict inequalities.

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

00133   : matrix(cs.space_dimension()),
00134     space_dim(cs.space_dimension()),
00135     status() {
00136   if (cs.space_dimension() > 0)
00137     // A (non zero-dim) universe octagon is strongly closed.
00138     set_strongly_closed();
00139   add_constraints(cs);
00140 }

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: some elements may be safely ignored.

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

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

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 196 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(), PLUS_INFINITY, Parma_Polyhedra_Library::Generator::POINT, Parma_Polyhedra_Library::Generator::RAY, 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().

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

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

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

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 BDS 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 157 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().

00159   : matrix(box.space_dimension()),
00160     space_dim(box.space_dimension()),
00161     status() {
00162   // Check for emptyness for maximum precision.
00163   if (box.is_empty())
00164     set_empty();
00165   else if (box.space_dimension() > 0) {
00166     // A (non zero-dim) universe OS is strongly closed.
00167     set_strongly_closed();
00168     refine_with_constraints(box.constraints());
00169   }
00170 }

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

00176   : matrix(grid.space_dimension()),
00177     space_dim(grid.space_dimension()),
00178     status() {
00179   if (grid.space_dimension() > 0)
00180     // A (non zero-dim) universe OS is strongly closed.
00181     set_strongly_closed();
00182   // Taking minimized congruences ensures maximum precision.
00183   refine_with_congruences(grid.minimized_congruences());
00184 }

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

00191   : matrix(bd.space_dimension()),
00192     space_dim(bd.space_dimension()),
00193     status() {
00194   // Check for emptyness for maximum precision.
00195   if (bd.is_empty())
00196     set_empty();
00197   else if (bd.space_dimension() > 0) {
00198     // A (non zero-dim) universe OS is strongly closed.
00199     set_strongly_closed();
00200     refine_with_constraints(bd.constraints());
00201   }
00202 }

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

Destructor.

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

00221                                      {
00222 }


Member Function Documentation

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

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

00048                                         {
00049   return OR_Matrix<N>::max_num_rows()/2;
00050 }

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

00507                                                    {
00508   return false;
00509 }

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

00513                                                    {
00514   return false;
00515 }

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

00212                                                       {
00213   matrix = y.matrix;
00214   space_dim = y.space_dim;
00215   status = y.status;
00216   return *this;
00217 }

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

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

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

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

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

Returns the system of constraints defining *this.

Definition at line 5735 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(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, TEMP_INTEGER, 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().

05735                                       {
05736   Constraint_System cs;
05737   if (space_dim == 0) {
05738     if (marked_empty())
05739       cs = Constraint_System::zero_dim_empty();
05740   }
05741   else if (marked_empty())
05742     cs.insert(0*Variable(space_dim-1) <= -1);
05743   else {
05744     // KLUDGE: in the future `cs' will be constructed of the right dimension.
05745     // For the time being, we force the dimension with the following line.
05746     cs.insert(0*Variable(space_dim-1) <= 0);
05747 
05748     typedef typename OR_Matrix<N>::const_row_iterator Row_Iterator;
05749     typedef typename OR_Matrix<N>::const_row_reference_type Row_Reference;
05750 
05751     Row_Iterator m_begin = matrix.row_begin();
05752     Row_Iterator m_end = matrix.row_end();
05753 
05754     TEMP_INTEGER(a);
05755     TEMP_INTEGER(b);
05756 
05757     // Go through all the unary constraints in `matrix'.
05758     for (Row_Iterator i_iter = m_begin; i_iter != m_end; ) {
05759       const dimension_type i = i_iter.index();
05760       const Variable x(i/2);
05761       const N& c_i_ii = (*i_iter)[i+1];
05762       ++i_iter;
05763       const N& c_ii_i = (*i_iter)[i];
05764       ++i_iter;
05765       // Go through unary constraints.
05766       if (is_additive_inverse(c_i_ii, c_ii_i)) {
05767         // We have a unary equality constraint.
05768         numer_denom(c_ii_i, b, a);
05769         a *= 2;
05770         cs.insert(a*x == b);
05771       }
05772       else {
05773         // We have 0, 1 or 2 inequality constraints.
05774         if (!is_plus_infinity(c_i_ii)) {
05775           numer_denom(c_i_ii, b, a);
05776           a *= 2;
05777           cs.insert(-a*x <= b);
05778         }
05779         if (!is_plus_infinity(c_ii_i)) {
05780           numer_denom(c_ii_i, b, a);
05781           a *= 2;
05782           cs.insert(a*x <= b);
05783         }
05784       }
05785     }
05786     //  Go through all the binary constraints in `matrix'.
05787     for (Row_Iterator i_iter = m_begin; i_iter != m_end; ) {
05788       const dimension_type i = i_iter.index();
05789       Row_Reference r_i = *i_iter;
05790       ++i_iter;
05791       Row_Reference r_ii = *i_iter;
05792       ++i_iter;
05793       const Variable y(i/2);
05794       for (dimension_type j = 0; j < i; j += 2) {
05795         const N& c_i_j = r_i[j];
05796         const N& c_ii_jj = r_ii[j+1];
05797         const Variable x(j/2);
05798         if (is_additive_inverse(c_ii_jj, c_i_j)) {
05799           // We have an equality constraint of the form ax - ay = b.
05800           numer_denom(c_i_j, b, a);
05801           cs.insert(a*x - a*y == b);
05802         }
05803         else {
05804           // We have 0, 1 or 2 inequality constraints.
05805           if (!is_plus_infinity(c_i_j)) {
05806             numer_denom(c_i_j, b, a);
05807             cs.insert(a*x - a*y <= b);
05808           }
05809           if (!is_plus_infinity(c_ii_jj)) {
05810             numer_denom(c_ii_jj, b, a);
05811             cs.insert(a*y - a*x <= b);
05812           }
05813         }
05814 
05815         const N& c_ii_j = r_ii[j];
05816         const N& c_i_jj = r_i[j+1];
05817         if (is_additive_inverse(c_i_jj, c_ii_j)) {
05818           // We have an equality constraint of the form ax + ay = b.
05819           numer_denom(c_ii_j, b, a);
05820           cs.insert(a*x + a*y == b);
05821         }
05822         else {
05823           // We have 0, 1 or 2 inequality constraints.
05824           if (!is_plus_infinity(c_i_jj)) {
05825             numer_denom(c_i_jj, b, a);
05826             cs.insert(-a*x - a*y <= b);
05827           }
05828           if (!is_plus_infinity(c_ii_j)) {
05829             numer_denom(c_ii_j, b, a);
05830             cs.insert(a*x + a*y <= b);
05831           }
05832         }
05833       }
05834     }
05835   }
05836   return cs;
05837 }

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

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

00367                                                 {
00368   strong_reduction_assign();
00369   return constraints();
00370 }

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

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

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

00206                                       {
00207   return minimized_congruences();
00208 }

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 579 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(), 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(), TEMP_INTEGER, and Parma_Polyhedra_Library::Congruence_System::zero_dim_empty().

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

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

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 709 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 >::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(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strictly_contains().

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

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

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

00584                                                                     {
00585   const Octagonal_Shape<T>& x = *this;
00586   return x.contains(y) && !y.contains(x);
00587 }

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 743 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::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

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

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 1249 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(), 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(), TEMP_INTEGER, 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().

01249                                                            {
01250   dimension_type c_space_dim = c.space_dimension();
01251 
01252   // Dimension-compatibility check.
01253   if (c_space_dim > space_dim)
01254     throw_dimension_incompatible("relation_with(c)", c);
01255 
01256   // The closure needs to make explicit the implicit constraints.
01257   strong_closure_assign();
01258 
01259   if (marked_empty())
01260     return Poly_Con_Relation::saturates()
01261       && Poly_Con_Relation::is_included()
01262       && Poly_Con_Relation::is_disjoint();
01263 
01264   if (space_dim == 0) {
01265     // Trivially false zero-dimensional constraint.
01266     if ((c.is_equality() && c.inhomogeneous_term() != 0)
01267         || (c.is_inequality() && c.inhomogeneous_term() < 0))
01268       return Poly_Con_Relation::is_disjoint();
01269     else if (c.is_strict_inequality() && c.inhomogeneous_term() == 0)
01270       // The constraint 0 > 0 implicitly defines the hyperplane 0 = 0;
01271       // thus, the zero-dimensional point also saturates it.
01272       return Poly_Con_Relation::saturates()
01273         && Poly_Con_Relation::is_disjoint();
01274 
01275     // Trivially true zero-dimensional constraint.
01276     else if (c.is_equality() || c.inhomogeneous_term() == 0)
01277       return Poly_Con_Relation::saturates()
01278         && Poly_Con_Relation::is_included();
01279     else
01280       // The zero-dimensional point saturates
01281       // neither the positivity constraint 1 >= 0,
01282       // nor the strict positivity constraint 1 > 0.
01283       return Poly_Con_Relation::is_included();
01284   }
01285 
01286   dimension_type num_vars = 0;
01287   dimension_type i = 0;
01288   dimension_type j = 0;
01289   TEMP_INTEGER(coeff);
01290   TEMP_INTEGER(c_term);
01291   if (!extract_octagonal_difference(c, c_space_dim, num_vars,
01292                                     i, j, coeff, c_term)) {
01293     // Constraints that are not octagonal differences.
01294     // Use maximize() and minimize() to do much of the work.
01295 
01296     // Find the linear expression for the constraint and use that to
01297     // find if the expression is bounded from above or below and if it
01298     // is, find the maximum and minimum values.
01299     Linear_Expression le;
01300     for (dimension_type k = c_space_dim; k-- > 0; ) {
01301       Variable vk(k);
01302       le += c.coefficient(vk) * vk;
01303     }
01304     DIRTY_TEMP(Coefficient, max_num);
01305     DIRTY_TEMP(Coefficient, max_den);
01306     bool max_included;
01307     DIRTY_TEMP(Coefficient, min_num);
01308     DIRTY_TEMP(Coefficient, min_den);
01309     bool min_included;
01310     bool bounded_above = maximize(le, max_num, max_den, max_included);
01311     bool bounded_below = minimize(le, min_num, min_den, min_included);
01312     if (!bounded_above) {
01313       if (!bounded_below)
01314         return Poly_Con_Relation::strictly_intersects();
01315       min_num += c.inhomogeneous_term() * min_den;
01316       switch (sgn(min_num)) {
01317       case 1:
01318         if (c.is_equality())
01319           return  Poly_Con_Relation::is_disjoint();
01320         return  Poly_Con_Relation::is_included();
01321       case 0:
01322         if (c.is_strict_inequality() || c.is_equality())
01323           return  Poly_Con_Relation::strictly_intersects();
01324         return  Poly_Con_Relation::is_included();
01325       case -1:
01326         return  Poly_Con_Relation::strictly_intersects();
01327       }
01328     }
01329     if (!bounded_below) {
01330       max_num += c.inhomogeneous_term() * max_den;
01331       switch (sgn(max_num)) {
01332       case 1:
01333         return  Poly_Con_Relation::strictly_intersects();
01334       case 0:
01335         if (c.is_strict_inequality())
01336           return  Poly_Con_Relation::is_disjoint();
01337         return  Poly_Con_Relation::strictly_intersects();
01338       case -1:
01339         return  Poly_Con_Relation::is_disjoint();
01340       }
01341     }
01342     else {
01343       max_num += c.inhomogeneous_term() * max_den;
01344       min_num += c.inhomogeneous_term() * min_den;
01345       switch (sgn(max_num)) {
01346       case 1:
01347         switch (sgn(min_num)) {
01348         case 1:
01349           if (c.is_equality())
01350             return  Poly_Con_Relation::is_disjoint();
01351           return  Poly_Con_Relation::is_included();
01352         case 0:
01353           if (c.is_equality())
01354             return  Poly_Con_Relation::strictly_intersects();
01355           if (c.is_strict_inequality())
01356             return  Poly_Con_Relation::strictly_intersects();
01357           return  Poly_Con_Relation::is_included();
01358         case -1:
01359           return  Poly_Con_Relation::strictly_intersects();
01360         }
01361      case 0:
01362         if (min_num == 0) {
01363           if (c.is_strict_inequality())
01364             return  Poly_Con_Relation::is_disjoint()
01365               && Poly_Con_Relation::saturates();
01366           return  Poly_Con_Relation::is_included()
01367             && Poly_Con_Relation::saturates();
01368         }
01369         if (c.is_strict_inequality())
01370           return  Poly_Con_Relation::is_disjoint();
01371         return  Poly_Con_Relation::strictly_intersects();
01372       case -1:
01373         return  Poly_Con_Relation::is_disjoint();
01374       }
01375     }
01376   }
01377 
01378   if (num_vars == 0) {
01379     // Dealing with a trivial constraint.
01380     switch (sgn(c.inhomogeneous_term())) {
01381     case -1:
01382       return Poly_Con_Relation::is_disjoint();
01383     case 0:
01384       if (c.is_strict_inequality())
01385         return Poly_Con_Relation::saturates()
01386           && Poly_Con_Relation::is_disjoint();
01387       else
01388         return Poly_Con_Relation::saturates()
01389           && Poly_Con_Relation::is_included();
01390     case 1:
01391       if (c.is_equality())
01392         return Poly_Con_Relation::is_disjoint();
01393       else
01394         return Poly_Con_Relation::is_included();
01395     }
01396   }
01397 
01398   // Select the cell to be checked for the "<=" part of constraint.
01399   typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin() + i;
01400   typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter;
01401   const N& m_i_j = m_i[j];
01402   // Set `coeff' to the absolute value of itself.
01403   if (coeff < 0)
01404     neg_assign(coeff);
01405 
01406   // Select the cell to be checked for the ">=" part of constraint.
01407   // Select the right row of the cell.
01408   if (i%2 == 0)
01409     ++i_iter;
01410   else
01411     --i_iter;
01412   typename OR_Matrix<N>::const_row_reference_type m_ci = *i_iter;
01413   const N& m_ci_cj = m_ci[coherent_index(j)];
01414   TEMP_INTEGER(numer);
01415   TEMP_INTEGER(denom);
01416   // The following variables of mpq_class type are used to be precise
01417   // when the octagon is defined by integer constraints.
01418   DIRTY_TEMP0(mpq_class, q_x);
01419   DIRTY_TEMP0(mpq_class, q_y);
01420   DIRTY_TEMP0(mpq_class, d);
01421   DIRTY_TEMP0(mpq_class, d1);
01422   DIRTY_TEMP0(mpq_class, c_den);
01423   DIRTY_TEMP0(mpq_class, q_den);
01424   assign_r(c_den, coeff, ROUND_NOT_NEEDED);
01425   assign_r(d, c_term, ROUND_NOT_NEEDED);
01426   neg_assign_r(d1, d, ROUND_NOT_NEEDED);
01427   div_assign_r(d, d, c_den, ROUND_NOT_NEEDED);
01428   div_assign_r(d1, d1, c_den, ROUND_NOT_NEEDED);
01429 
01430   if (is_plus_infinity(m_i_j)) {
01431     if (!is_plus_infinity(m_ci_cj)) {
01432       // `*this' is in the following form:
01433       // `-m_ci_cj <= v - u'.
01434       // In this case `*this' is disjoint from `c' if
01435       // `-m_ci_cj > d' (`-m_ci_cj >= d' if c is a strict inequality),
01436       // i.e. if `m_ci_cj < d1' (`m_ci_cj <= d1' if c is a strict inequality).
01437       numer_denom(m_ci_cj, numer, denom);
01438       assign_r(q_den, denom, ROUND_NOT_NEEDED);
01439       assign_r(q_y, numer, ROUND_NOT_NEEDED);
01440       div_assign_r(q_y, q_y, q_den, ROUND_NOT_NEEDED);
01441       if (q_y < d1)
01442         return Poly_Con_Relation::is_disjoint();
01443       if (q_y == d1 && c.is_strict_inequality())
01444         return Poly_Con_Relation::is_disjoint();
01445     }
01446 
01447     // In all other cases `*this' intersects `c'.
01448     return Poly_Con_Relation::strictly_intersects();
01449   }
01450 
01451   // Here `m_i_j' is not plus-infinity.
01452   numer_denom(m_i_j, numer, denom);
01453   assign_r(q_den, denom, ROUND_NOT_NEEDED);
01454   assign_r(q_x, numer, ROUND_NOT_NEEDED);
01455   div_assign_r(q_x, q_x, q_den, ROUND_NOT_NEEDED);
01456 
01457   if (!is_plus_infinity(m_ci_cj)) {
01458     numer_denom(m_ci_cj, numer, denom);
01459     assign_r(q_den, denom, ROUND_NOT_NEEDED);
01460     assign_r(q_y, numer, ROUND_NOT_NEEDED);
01461     div_assign_r(q_y, q_y, q_den, ROUND_NOT_NEEDED);
01462     if (q_x == d && q_y == d1) {
01463       if (c.is_strict_inequality())
01464         return Poly_Con_Relation::saturates()
01465           && Poly_Con_Relation::is_disjoint();
01466       else
01467         return Poly_Con_Relation::saturates()
01468           && Poly_Con_Relation::is_included();
01469     }
01470     // `*this' is disjoint from `c' when
01471     // `m_ci_cj < d1' (`m_ci_cj <= d1' if `c' is a strict inequality).
01472     if (q_y < d1)
01473       return Poly_Con_Relation::is_disjoint();
01474     if (q_y == d1 && c.is_strict_inequality())
01475       return Poly_Con_Relation::is_disjoint();
01476   }
01477 
01478   // Here `m_ci_cj' can be also plus-infinity.
01479   // If `c' is an equality, `*this' is disjoint from `c' if
01480   // `m_i_j < d'.
01481   if (d > q_x) {
01482     if (c.is_equality())
01483       return Poly_Con_Relation::is_disjoint();
01484     else
01485       return Poly_Con_Relation::is_included();
01486   }
01487 
01488   if (d == q_x && c.is_nonstrict_inequality())
01489     return Poly_Con_Relation::is_included();
01490 
01491   // In all other cases `*this' intersects `c'.
01492   return Poly_Con_Relation::strictly_intersects();
01493 }

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

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Congruence::coefficient(), Parma_Polyhedra_Library::Congruence::inhomogeneous_term(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Checked::le(), Parma_Polyhedra_Library::lower(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimize(), Parma_Polyhedra_Library::Congruence::modulus(), Parma_Polyhedra_Library::neg_assign(), 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(), TEMP_INTEGER, and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

01189                                                             {
01190   dimension_type cg_space_dim = cg.space_dimension();
01191 
01192   // Dimension-compatibility check.
01193   if (cg_space_dim > space_dim) {
01194     throw_dimension_incompatible("relation_with(cg)", cg);
01195   }
01196 
01197   // If the congruence is an equality,
01198   // find the relation with the equivalent equality constraint.
01199   if (cg.is_equality()) {
01200     Constraint c(cg);
01201     return relation_with(c);
01202   }
01203 
01204   strong_closure_assign();
01205 
01206   if (marked_empty())
01207     return Poly_Con_Relation::saturates()
01208       && Poly_Con_Relation::is_included()
01209       && Poly_Con_Relation::is_disjoint();
01210 
01211   if (space_dim == 0) {
01212     if (cg.is_inconsistent())
01213       return Poly_Con_Relation::is_disjoint();
01214     else if (cg.inhomogeneous_term() % cg.modulus() == 0)
01215       return Poly_Con_Relation::saturates()
01216         && Poly_Con_Relation::is_included();
01217   }
01218 
01219   DIRTY_TEMP(Coefficient, min_num);
01220   DIRTY_TEMP(Coefficient, min_den);
01221   bool min_included;
01222   TEMP_INTEGER(mod);
01223   mod = cg.modulus();
01224   Linear_Expression le;
01225   for (dimension_type i = cg_space_dim; i-- > 0; )
01226     le += cg.coefficient(Variable(i)) * Variable(i);
01227   bool bounded_below = minimize(le, min_num, min_den, min_included);
01228 
01229   if (!bounded_below)
01230     return Poly_Con_Relation::strictly_intersects();
01231 
01232   TEMP_INTEGER(v);
01233   TEMP_INTEGER(lower_num);
01234   TEMP_INTEGER(lower_den);
01235   TEMP_INTEGER(lower);
01236   assign_r(lower_num, min_num, ROUND_NOT_NEEDED);
01237   assign_r(lower_den, min_den, ROUND_NOT_NEEDED);
01238   neg_assign(v, cg.inhomogeneous_term());
01239   lower = lower_num / lower_den;
01240   v += ((lower / mod) * mod);
01241   if (v * lower_den < lower_num)
01242     v += mod;
01243   const Constraint& c(le == v);
01244   return relation_with(c);
01245 }

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

References Parma_Polyhedra_Library::add_mul_assign(), Parma_Polyhedra_Library::Generator::coefficient(), 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(), 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(), TEMP_INTEGER, and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

01497                                                           {
01498   const dimension_type g_space_dim = g.space_dimension();
01499 
01500   // Dimension-compatibility check.
01501   if (space_dim < g_space_dim)
01502     throw_dimension_incompatible("relation_with(g)", g);
01503 
01504   // The closure needs to make explicit the implicit constraints and if the
01505   // octagon is empty.
01506   strong_closure_assign();
01507 
01508   // The empty octagon cannot subsume a generator.
01509   if (marked_empty())
01510     return Poly_Gen_Relation::nothing();
01511 
01512   // A universe octagon in a zero-dimensional space subsumes
01513   // all the generators of a zero-dimensional space.
01514   if (space_dim == 0)
01515     return Poly_Gen_Relation::subsumes();
01516 
01517   const bool is_line = g.is_line();
01518   const bool is_line_or_ray = g.is_line_or_ray();
01519 
01520   // The relation between the octagon and the given generator is obtained
01521   // checking if the generator satisfies all the constraints in the octagon.
01522   // To check if the generator satisfies all the constraints it's enough
01523   // studying the sign of the scalar product between the generator and
01524   // all the constraints in the octagon.
01525 
01526   typedef typename OR_Matrix<N>::const_row_iterator Row_Iterator;
01527   typedef typename OR_Matrix<N>::const_row_reference_type Row_Reference;
01528 
01529   const Row_Iterator m_begin = matrix.row_begin();
01530   const Row_Iterator m_end = matrix.row_end();
01531 
01532   TEMP_INTEGER(num);
01533   TEMP_INTEGER(den);
01534   TEMP_INTEGER(product);
01535 
01536   // We find in `*this' all the constraints.
01537   for (Row_Iterator i_iter = m_begin; i_iter != m_end; i_iter += 2) {
01538     dimension_type i = i_iter.index();
01539     Row_Reference m_i = *i_iter;
01540     Row_Reference m_ii = *(i_iter+1);
01541     const N& m_i_ii = m_i[i+1];
01542     const N& m_ii_i = m_ii[i];
01543     // We have the unary constraints.
01544     const Variable x(i/2);
01545     const Coefficient& g_coeff_x = (x.space_dimension() > g_space_dim)
01546       ? Coefficient(0) : g.coefficient(x);
01547     if (is_additive_inverse(m_i_ii, m_ii_i)) {
01548       // The constraint has form ax = b.
01549       // To satisfy the constraint it's necessary that the scalar product
01550       // is not zero. The scalar product has the form:
01551       // 'den * g_coeff_x - num * g.divisor()'.
01552       numer_denom(m_ii_i, num, den);
01553       den *= 2;
01554       product = den * g_coeff_x;
01555       // Note that if the generator `g' is a line or a ray,
01556       // its divisor is zero.
01557       if (!is_line_or_ray) {
01558         neg_assign(num);
01559         add_mul_assign(product, num, g.divisor());
01560       }
01561       if (product != 0)
01562         return Poly_Gen_Relation::nothing();
01563     }
01564     // We have 0, 1 or 2 inequality constraints.
01565     else {
01566       if (!is_plus_infinity(m_i_ii)) {
01567         // The constraint has form -ax <= b.
01568         // If the generator is a line it's necessary to check if
01569         // the scalar product is not zero, if it is positive otherwise.
01570         numer_denom(m_i_ii, num, den);
01571         den *= -2;
01572         product = den * g_coeff_x;
01573         // Note that if the generator `g' is a line or a ray,
01574         // its divisor is zero.
01575         if (!is_line_or_ray) {
01576           neg_assign(num);
01577           add_mul_assign(product, num, g.divisor());
01578         }
01579         if (is_line && product != 0)
01580           return Poly_Gen_Relation::nothing();
01581         else
01582           // If the generator is not a line it's necessary to check
01583           // that the scalar product sign is not positive and the scalar
01584           // product has the form:
01585           // '-den * g.coeff_x - num * g.divisor()'.
01586           if (product > 0)
01587             return Poly_Gen_Relation::nothing();
01588       }
01589       if (!is_plus_infinity(m_ii_i)) {
01590         // The constraint has form ax <= b.
01591         numer_denom(m_ii_i, num, den);
01592         den *= 2;
01593         product = den * g_coeff_x;
01594          // Note that if the generator `g' is a line or a ray,
01595         // its divisor is zero.
01596         if (!is_line_or_ray) {
01597           neg_assign(num);
01598           add_mul_assign(product, num , g.divisor());
01599         }
01600         if (is_line && product != 0)
01601           return Poly_Gen_Relation::nothing();
01602         else
01603           // If the generator is not a line it's necessary to check
01604           // that the scalar product sign is not positive and the scalar
01605           // product has the form:
01606           // 'den * g_coeff_x - num * g.divisor()'.
01607           if (product > 0)
01608             return Poly_Gen_Relation::nothing();
01609       }
01610     }
01611   }
01612 
01613   // We have the binary constraints.
01614   for (Row_Iterator i_iter = m_begin ; i_iter != m_end; i_iter += 2) {
01615     dimension_type i = i_iter.index();
01616     Row_Reference m_i = *i_iter;
01617     Row_Reference m_ii = *(i_iter+1);
01618     for (dimension_type j = 0; j < i; j += 2) {
01619       const N& m_i_j = m_i[j];
01620       const N& m_ii_jj = m_ii[j+1];
01621       const N& m_ii_j = m_ii[j];
01622       const N& m_i_jj = m_i[j+1];
01623       const Variable x(j/2);
01624       const Variable y(i/2);
01625       const Coefficient& g_coeff_x = (x.space_dimension() > g_space_dim)
01626         ? Coefficient(0) : g.coefficient(x);
01627       const Coefficient& g_coeff_y = (y.space_dimension() > g_space_dim)
01628         ? Coefficient(0) : g.coefficient(y);
01629 
01630       // FIXME! Find better names.
01631       const bool is_binary_equality = is_additive_inverse(m_ii_jj, m_i_j);
01632       const bool is_a_binary_equality = is_additive_inverse(m_i_jj, m_ii_j);
01633       if (is_binary_equality) {
01634         // The constraint has form ax - ay = b.
01635         // The scalar product has the form
01636         // 'den * coeff_x - den * coeff_y - num * g.divisor()'.
01637         // To satisfy the constraint it's necessary that the scalar product
01638         // is not zero.
01639         numer_denom(m_i_j, num, den);
01640         product = den * g_coeff_x;
01641         neg_assign(den);
01642         add_mul_assign(product, den, g_coeff_y);
01643         // Note that if the generator `g' is a line or a ray,
01644         // its divisor is zero.
01645         if (!is_line_or_ray) {
01646           neg_assign(num);
01647           add_mul_assign(product, num, g.divisor());
01648         }
01649         if (product != 0)
01650           return Poly_Gen_Relation::nothing();
01651       }
01652       else {
01653         if (!is_plus_infinity(m_i_j)) {
01654           // The constraint has form ax - ay <= b.
01655           // The scalar product has the form
01656           // 'den * coeff_x - den * coeff_y - num * g.divisor()'.
01657           // If the generator is not a line it's necessary to check
01658           // that the scalar product sign is not positive.
01659           numer_denom(m_i_j, num, den);
01660           product = den * g_coeff_x;
01661           neg_assign(den);
01662           add_mul_assign(product, den, g_coeff_y);
01663           // Note that if the generator `g' is a line or a ray,
01664           // its divisor is zero.
01665           if (!is_line_or_ray) {
01666             neg_assign(num);
01667             add_mul_assign(product, num, g.divisor());
01668           }
01669           if (is_line && product != 0)
01670             return Poly_Gen_Relation::nothing();
01671           else if (product > 0)
01672             return Poly_Gen_Relation::nothing();
01673         }
01674         if (!is_plus_infinity(m_ii_jj)) {
01675           // The constraint has form -ax + ay <= b.
01676           // The scalar product has the form
01677           // '-den * coeff_x + den * coeff_y - num * g.divisor()'.
01678           // If the generator is not a line it's necessary to check
01679           // that the scalar product sign is not positive.
01680           numer_denom(m_ii_jj, num, den);
01681           product = den * g_coeff_y;
01682           neg_assign(den);
01683           add_mul_assign(product, den, g_coeff_x);
01684           // Note that if the generator `g' is a line or a ray,
01685           // its divisor is zero.
01686           if (!is_line_or_ray) {
01687             neg_assign(num);
01688             add_mul_assign(product, num, g.divisor());
01689           }
01690           if (is_line && product != 0)
01691             return Poly_Gen_Relation::nothing();
01692           else if (product > 0)
01693             return Poly_Gen_Relation::nothing();
01694         }
01695       }
01696 
01697       if (is_a_binary_equality) {
01698         // The constraint has form ax + ay = b.
01699         // The scalar product has the form
01700         // 'den * coeff_x + den * coeff_y - num * g.divisor()'.
01701         // To satisfy the constraint it's necessary that the scalar product
01702         // is not zero.
01703         numer_denom(m_ii_j, num, den);
01704         product = den * g_coeff_x;
01705         add_mul_assign(product, den, g_coeff_y);
01706         // Note that if the generator `g' is a line or a ray,
01707         // its divisor is zero.
01708         if (!is_line_or_ray) {
01709           neg_assign(num);
01710           add_mul_assign(product, num, g.divisor());
01711         }
01712         if (product != 0)
01713           return Poly_Gen_Relation::nothing();
01714       }
01715       else {
01716         if (!is_plus_infinity(m_i_jj)) {
01717           // The constraint has form -ax - ay <= b.
01718           // The scalar product has the form
01719           // '-den * coeff_x - den * coeff_y - num * g.divisor()'.
01720           // If the generator is not a line it's necessary to check
01721           // that the scalar product sign is not positive.
01722           numer_denom(m_i_jj, num, den);
01723           neg_assign(den);
01724           product = den * g_coeff_x;
01725           add_mul_assign(product, den, g_coeff_y);
01726           // Note that if the generator `g' is a line or a ray,
01727           // its divisor is zero.
01728           if (!is_line_or_ray) {
01729             neg_assign(num);
01730             add_mul_assign(product, num, g.divisor());
01731           }
01732           if (is_line && product != 0)
01733             return Poly_Gen_Relation::nothing();
01734           else if (product > 0)
01735             return Poly_Gen_Relation::nothing();
01736         }
01737         if (!is_plus_infinity(m_ii_j)) {
01738           // The constraint has form ax + ay <= b.
01739           // The scalar product has the form
01740           // 'den * coeff_x + den * coeff_y - num * g.divisor()'.
01741           // If the generator is not a line it's necessary to check
01742           // that the scalar product sign is not positive.
01743           numer_denom(m_ii_j, num, den);
01744           product = den * g_coeff_x;
01745           add_mul_assign(product, den, g_coeff_y);
01746           // Note that if the generator `g' is a line or a ray,
01747           // its divisor is zero.
01748           if (!is_line_or_ray) {
01749             neg_assign(num);
01750             add_mul_assign(product, num, g.divisor());
01751           }
01752           if (is_line && product != 0)
01753             return Poly_Gen_Relation::nothing();
01754           else if (product > 0)
01755             return Poly_Gen_Relation::nothing();
01756         }
01757       }
01758     }
01759   }
01760   // If this point is reached the constraint 'g' satisfies
01761   // all the constraints in the octagon.
01762   return Poly_Gen_Relation::subsumes();
01763 }

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_universe (  )  const [inline]

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

Definition at line 797 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, and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim.

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

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

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

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

00240                                       {
00241   return affine_dimension() == 0;
00242 }

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 820 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::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().

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

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

00299                                                   {
00300   return true;
00301 }

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

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

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 897 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_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().

00897                                                        {
00898   // `var' should be one of the dimensions of the polyhedron.
00899   const dimension_type var_space_dim = var.space_dimension();
00900   if (space_dimension() < var_space_dim)
00901     throw_dimension_incompatible("constrains(v)", "v", var);
00902 
00903   // A polyhedron known to be empty constrains all variables.
00904   // (Note: do not force emptiness check _yet_)
00905   if (marked_empty())
00906     return true;
00907 
00908   // Check whether `var' is syntactically constrained.
00909   const dimension_type n_v = 2*(var_space_dim - 1);
00910   typename OR_Matrix<N>::const_row_iterator m_iter = matrix.row_begin() + n_v;
00911   typename OR_Matrix<N>::const_row_reference_type r_v = *m_iter;
00912   typename OR_Matrix<N>::const_row_reference_type r_cv = *(++m_iter);
00913   for (dimension_type h = m_iter.row_size(); h-- > 0; ) {
00914     if (!is_plus_infinity(r_v[h]) || !is_plus_infinity(r_cv[h]))
00915       return true;
00916   }
00917   ++m_iter;
00918   for (typename OR_Matrix<N>::const_row_iterator m_end = matrix.row_end();
00919        m_iter != m_end; ++m_iter) {
00920     typename OR_Matrix<N>::const_row_reference_type r = *m_iter;
00921     if (!is_plus_infinity(r[n_v]) || !is_plus_infinity(r[n_v+1]))
00922       return true;
00923   }
00924 
00925   // `var' is not syntactically constrained:
00926   // now force an emptiness check.
00927   return is_empty();
00928 }

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

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

00253                                                                          {
00254   return bounds(expr, true);
00255 }

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

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

00259                                                                          {
00260   return bounds(expr, false);
00261 }

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

00267                                                   {
00268   return max_min(expr, true, sup_n, sup_d, maximum);
00269 }

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

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

00276                                                  {
00277   return max_min(expr, true, sup_n, sup_d, maximum, g);
00278 }

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

00284                                                   {
00285   return max_min(expr, false, inf_n, inf_d, minimum);
00286 }

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

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

00293                                                  {
00294   return max_min(expr, false, inf_n, inf_d, minimum, g);
00295 }

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

Checks if all the invariants are satisfied.

Definition at line 6209 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::Octagonal_Shape< T >::reset_strongly_closed(), 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 >::ascii_load(), 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 >::expand_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage(), 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_higher_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), 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().

06209                              {
06210   // Check whether the matrix is well-formed.
06211   if (!matrix.OK())
06212     return false;
06213 
06214   // Check whether the status information is legal.
06215   if (!status.OK())
06216     return false;
06217 
06218   // All empty octagons are OK.
06219   if (marked_empty())
06220     return true;
06221 
06222   // 0-dim universe octagon is OK.
06223   if (space_dim == 0)
06224     return true;
06225 
06226   // MINUS_INFINITY cannot occur at all.
06227   for (typename OR_Matrix<N>::const_row_iterator i = matrix.row_begin(),
06228          matrix_row_end = matrix.row_end(); i != matrix_row_end; ++i) {
06229     typename OR_Matrix<N>::const_row_reference_type x_i = *i;
06230     for (dimension_type j = i.row_size(); j-- > 0; )
06231       if (is_minus_infinity(x_i[j])) {
06232 #ifndef NDEBUG
06233         using namespace Parma_Polyhedra_Library::IO_Operators;
06234         std::cerr << "Octagonal_Shape::"
06235                   << "matrix[" << i.index() << "][" << j << "] = "
06236                   << x_i[j] << "!"
06237                   << std::endl;
06238 #endif
06239         return false;
06240       }
06241   }
06242 
06243   // On the main diagonal only PLUS_INFINITY can occur.
06244   for (typename OR_Matrix<N>::const_row_iterator i = matrix.row_begin(),
06245          m_end = matrix.row_end(); i != m_end; ++i) {
06246     typename OR_Matrix<N>::const_row_reference_type r = *i;
06247     const N& m_i_i = r[i.index()];
06248     if (!is_plus_infinity(m_i_i)) {
06249 #ifndef NDEBUG
06250       const dimension_type j = i.index();
06251       using namespace Parma_Polyhedra_Library::IO_Operators;
06252       std::cerr << "Octagonal_Shape::matrix[" << j << "][" << j << "] = "
06253                 << m_i_i << "!  (+inf was expected.)\n";
06254 #endif
06255       return false;
06256     }
06257   }
06258 
06259   // The following tests might result in false alarms when using floating
06260   // point coefficients: they are only meaningful if the coefficient type
06261   // base is exact (since otherwise strong closure is approximated).
06262   if (std::numeric_limits<coefficient_type_base>::is_exact) {
06263 
06264     // Check whether the closure information is legal.
06265     if (marked_strongly_closed()) {
06266       Octagonal_Shape x = *this;
06267       x.reset_strongly_closed();
06268       x.strong_closure_assign();
06269       if (x.matrix != matrix) {
06270 #ifndef NDEBUG
06271         std::cerr << "Octagonal_Shape is marked as strongly closed "
06272                   << "but it is not!\n";
06273 #endif
06274         return false;
06275       }
06276     }
06277 
06278     // A closed octagon must be strong-coherent.
06279     if (marked_strongly_closed())
06280       if (!is_strong_coherent()) {
06281 #ifndef NDEBUG
06282         std::cerr << "Octagonal_Shape is not strong-coherent!\n";
06283 #endif
06284         return false;
06285       }
06286   }
06287 
06288   // All checks passed.
06289   return true;
06290 }

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. If it is not an octagonal constraint, it will be simply ignored.
Exceptions:
std::invalid_argument Thrown if *this and constraint c are dimension-incompatible, or c is a strict inequality.

Definition at line 370 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(), 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, Parma_Polyhedra_Library::Constraint::space_dimension(), TEMP_INTEGER, 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().

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

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. Constraints that are not octagonal constraints will be simply ignored.
Exceptions:
std::invalid_argument Thrown if *this and cs are dimension-incompatible, or if cs contains a strict inequality.

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

00412                                                                {
00413   for (Constraint_System::const_iterator i = cs.begin(),
00414          i_end = cs.end(); i != i_end; ++i)
00415     add_constraint(*i);
00416 }

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 (without minimizing the result).

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 topology-incompatible or dimension-incompatible.
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 420 of file Octagonal_Shape.inlines.hh.

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

00420                                                                   {
00421   add_constraints(cs);
00422 }

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

Adds a copy of congruence cg to the system of congruences of this (without minimizing the result).

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

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

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

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 (without minimizing the result).

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

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

00432                                                                 {
00433   for (Congruence_System::const_iterator i = cgs.begin(),
00434          cgs_end = cgs.end(); i != cgs_end; ++i)
00435     add_congruence(*i);
00436 }

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

Adds the congruences in cs to the system of congruences of *this (without minimizing the result).

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

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

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

00426                                                                    {
00427   add_congruences(cgs);
00428 }

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

00440                                                               {
00441   // Dimension-compatibility check.
00442   if (c.space_dimension() > space_dimension())
00443     throw_dimension_incompatible("refine_with_constraint(c)", c);
00444 
00445   if (!marked_empty())
00446     refine_no_check(c);
00447 }

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

00464                                                                {
00465   const dimension_type cg_space_dim = cg.space_dimension();
00466   // Dimension-compatibility check.
00467   if (cg_space_dim > space_dimension())
00468     throw_dimension_incompatible("refine_with_congruence(cg)", cg);
00469 
00470   if (!marked_empty())
00471     refine_no_check(cg);
00472 }

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

00451                                                                        {
00452   // Dimension-compatibility check.
00453   if (cs.space_dimension() > space_dimension())
00454     throw_generic("refine_with_constraints(cs)",
00455                   "cs and *this are space-dimension incompatible");
00456 
00457   for (Constraint_System::const_iterator i = cs.begin(),
00458          cs_end = cs.end(); !marked_empty() && i != cs_end; ++i)
00459     refine_no_check(*i);
00460 }

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

00476                                                                         {
00477   // Dimension-compatibility check.
00478   if (cgs.space_dimension() > space_dimension())
00479     throw_generic("refine_with_congruences(cgs)",
00480                   "cgs and *this are space-dimension incompatible");
00481 
00482   for (Congruence_System::const_iterator i = cgs.begin(),
00483          cgs_end = cgs.end(); !marked_empty() && i != cgs_end; ++i)
00484     refine_no_check(*i);
00485 }

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

03341                                                   {
03342   // Dimension-compatibility check.
03343   const dimension_type dim = var.id();
03344   if (space_dimension() < dim)
03345     throw_dimension_incompatible("unconstrain(var)", dim);
03346 
03347   // Enforce strong closure for precision.
03348   strong_closure_assign();
03349 
03350   // If the shape is empty, this is a no-op.
03351   if (marked_empty())
03352     return;
03353 
03354   forget_all_octagonal_constraints(dim);
03355   // Strong closure is preserved.
03356   assert(OK());
03357 }

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

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

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

Definition at line 3361 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::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

03361                                                                         {
03362   // The cylindrification wrt no dimensions is a no-op.
03363   // This case captures the only legal cylindrification in a 0-dim space.
03364   if (to_be_unconstrained.empty())
03365     return;
03366 
03367   // Dimension-compatibility check.
03368   const dimension_type min_space_dim = to_be_unconstrained.space_dimension();
03369   if (space_dimension() < min_space_dim)
03370     throw_dimension_incompatible("unconstrain(vs)", min_space_dim);
03371 
03372   // Enforce strong closure for precision.
03373   strong_closure_assign();
03374 
03375   // If the shape is empty, this is a no-op.
03376   if (marked_empty())
03377     return;
03378 
03379   for (Variables_Set::const_iterator tbu = to_be_unconstrained.begin(),
03380          tbu_end = to_be_unconstrained.end(); tbu != tbu_end; ++tbu)
03381     forget_all_octagonal_constraints(*tbu);
03382   // Strong closure is preserved.
03383   assert(OK());
03384 }

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

References 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 >::limited_BHMZ05_extrapolation_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_CC76_extrapolation_assign().

02654                                                                 {
02655   // Dimension-compatibility check.
02656   if (space_dim != y.space_dim)
02657     throw_dimension_incompatible("intersection_assign(y)", y);
02658 
02659   // If one of the two octagons is empty, the intersection is empty.
02660   if (marked_empty())
02661     return;
02662   if (y.marked_empty()) {
02663     set_empty();
02664     return;
02665   }
02666   // If both octagons are zero-dimensional,then at this point
02667   // they are necessarily non-empty,
02668   // so that their intersection is non-empty too.
02669   if (space_dim == 0)
02670     return;
02671 
02672   // To intersect two octagons we compare the constraints
02673   // and we choose the less values.
02674   bool changed = false;
02675 
02676   typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin();
02677   for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(),
02678          matrix_element_end = matrix.element_end();
02679        i != matrix_element_end;
02680        ++i, ++j) {
02681     N& elem = *i;
02682     const N& y_elem = *j;
02683     if (y_elem < elem) {
02684       elem = y_elem;
02685       changed = true;
02686     }
02687   }
02688 
02689   // This method not preserve the closure.
02690   if (changed && marked_strongly_closed())
02691     reset_strongly_closed();
02692   assert(OK());
02693 }

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

02341                                                                {
02342   // Dimension-compatibility check.
02343   if (space_dim != y.space_dim)
02344     throw_dimension_incompatible("upper_bound_assign(y)", y);
02345 
02346   // The hull of an octagon `x' with an empty octagon is `x'.
02347   y.strong_closure_assign();
02348   if (y.marked_empty())
02349     return;
02350   strong_closure_assign();
02351   if (marked_empty()) {
02352     *this = y;
02353     return;
02354   }
02355 
02356   // The oct-hull is obtained by computing maxima.
02357   typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin();
02358   for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(),
02359          matrix_element_end = matrix.element_end();
02360        i != matrix_element_end; ++i, ++j)
02361     max_assign(*i, *j);
02362 
02363   // The result is still closed.
02364   assert(OK());
02365 }

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.

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

00591                                                                         {
00592   // TODO: this must be properly implemented.
00593   used(y);
00594   return false;
00595 }

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

02369                                                               {
02370   // Dimension-compatibility check.
02371   if (space_dim != y.space_dim)
02372     throw_dimension_incompatible("difference_assign(y)", y);
02373 
02374   Octagonal_Shape& x = *this;
02375 
02376   // Being lazy here is only harmful.
02377   // We close.
02378   x.strong_closure_assign();
02379   // The difference of an empty octagon and of an octagon `p' is empty.
02380   if (x.marked_empty())
02381     return;
02382   // The difference of a octagon `p' and an empty octagon is `p'.
02383   if (y.marked_empty())
02384     return;
02385 
02386   // If both octagons are zero-dimensional,
02387   // then at this point they are necessarily universe octagons,
02388   // so that their difference is empty.
02389   if (x.space_dim == 0) {
02390     x.set_empty();
02391     return;
02392   }
02393 
02394   // TODO: This is just an executable specification.
02395   //       Have to find a more efficient method.
02396   if (y.contains(x)) {
02397     x.set_empty();
02398     return;
02399   }
02400 
02401   Octagonal_Shape new_oct(space_dim, EMPTY);
02402   // We take a constraint of the octagon y at the time and we
02403   // consider its complementary. Then we intersect the union
02404   // of these complementaries with the octagon x.
02405   const Constraint_System& y_cs = y.constraints();
02406   for (Constraint_System::const_iterator i = y_cs.begin(),
02407          y_cs_end = y_cs.end(); i != y_cs_end; ++i) {
02408     const Constraint& c = *i;
02409     // If the octagon `x' is included the octagon defined by `c',
02410     // then `c' _must_ be skipped, as adding its complement to `x'
02411     // would result in the empty octagon, and as we would obtain
02412     // a result that is less precise than the difference.
02413     if (x.relation_with(c).implies(Poly_Con_Relation::is_included()))
02414       continue;
02415     Octagonal_Shape z = x;
02416     const Linear_Expression e = Linear_Expression(c);
02417     z.add_constraint(e <= 0);
02418     if (!z.is_empty())
02419       new_oct.upper_bound_assign(z);
02420     if (c.is_equality()) {
02421       z = x;
02422       z.add_constraint(e >= 0);
02423       if (!z.is_empty())
02424         new_oct.upper_bound_assign(z);
02425     }
02426   }
02427   *this = new_oct;
02428   assert(OK());
02429 }

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

02434                                                         {
02435   // FIXME: provide a real implementation.
02436   used(y);
02437   return true;
02438 }

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 3942 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::Octagonal_Shape< T >::forget_binary_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(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), 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::swap(), TEMP_INTEGER, 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(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage().

03945                                               {
03946   // The denominator cannot be zero.
03947   if (denominator == 0)
03948     throw_generic("affine_image(v, e, d)", "d == 0");
03949 
03950   // Dimension-compatibility checks.
03951   // The dimension of `expr' should not be greater than the dimension
03952   // of `*this'.
03953   const dimension_type expr_space_dim = expr.space_dimension();
03954   if (space_dim < expr_space_dim)
03955     throw_dimension_incompatible("affine_image(v, e, d)", "e", expr);
03956 
03957   // `var' should be one of the dimensions of the octagon.
03958   const dimension_type var_id = var.id();
03959   if (space_dim < var_id + 1)
03960     throw_dimension_incompatible("affine_image(v, e, d)", var.id()+1);
03961 
03962   strong_closure_assign();
03963   // The image of an empty octagon is empty too.
03964   if (marked_empty())
03965     return;
03966 
03967   // Number of non-zero coefficients in `expr': will be set to
03968   // 0, 1, or 2, the latter value meaning any value greater than 1.
03969   dimension_type t = 0;
03970   // Variable-index of the last non-zero coefficient in `expr', if any.
03971   dimension_type w_id = 0;
03972 
03973   // Get information about the number of non-zero coefficients in `expr'.
03974   // The `expr' must not be in two or plus variables.
03975   for (dimension_type i = expr_space_dim; i-- > 0; )
03976     if (expr.coefficient(Variable(i)) != 0) {
03977       if (t++ == 1)
03978         break;
03979       else
03980         w_id = i;
03981     }
03982 
03983   typedef typename OR_Matrix<N>::row_iterator Row_Iterator;
03984   typedef typename OR_Matrix<N>::row_reference_type Row_Reference;
03985   typedef typename OR_Matrix<N>::const_row_iterator Row_iterator;
03986   typedef typename OR_Matrix<N>::const_row_reference_type Row_reference;
03987 
03988   const Row_Iterator m_begin = matrix.row_begin();
03989   const Row_Iterator m_end = matrix.row_end();
03990   const dimension_type n_var = 2*var_id;
03991   const Coefficient& b = expr.inhomogeneous_term();
03992   TEMP_INTEGER(minus_den);
03993   neg_assign_r(minus_den, denominator, ROUND_NOT_NEEDED);
03994 
03995   // `w' is the variable with index `w_id'.
03996   // Now we know the form of `expr':
03997   // - If t == 0, then expr == b, with `b' a constant;
03998   // - If t == 1, then expr == a*w + b, where `w' can be `v' or another
03999   //   variable; in this second case we have to check whether `a' is
04000   //   equal to `denominator' or `-denominator', since otherwise we have
04001   //   to fall back on the general form;
04002   // - If t == 2, the `expr' is of the general form.
04003 
04004   if (t == 0) {
04005     // Case 1: expr == b.
04006     // Remove all constraints on `var'.
04007     forget_all_octagonal_constraints(var_id);
04008     TEMP_INTEGER(two_b);
04009     two_b = 2*b;
04010     // Add the constraint `var == b/denominator'.
04011     add_octagonal_constraint(n_var+1, n_var, two_b, denominator);
04012     add_octagonal_constraint(n_var, n_var+1, two_b, minus_den);
04013     assert(OK());
04014     return;
04015   }
04016 
04017   if (t == 1) {
04018     // The one and only non-zero homogeneous coefficient in `expr'.
04019     const Coefficient& w_coeff = expr.coefficient(Variable(w_id));
04020     if (w_coeff == denominator || w_coeff == minus_den) {
04021       // Case 2: expr = w_coeff*w + b, with w_coeff = +/- denominator.
04022       if (w_id == var_id) {
04023         // Here `expr' is of the form: +/- denominator * v + b.
04024         if (w_coeff == denominator) {
04025           if (b == 0)
04026             // The transformation is the identity function.
04027             return;
04028           else {
04029             // Translate all the constraints on `var' adding or
04030             // subtracting the value `b/denominator'.
04031             DIRTY_TEMP(N, d);
04032             div_round_up(d, b, denominator);
04033             DIRTY_TEMP(N, minus_d);
04034             div_round_up(minus_d, b, minus_den);
04035             Row_Iterator m_iter = m_begin + n_var;
04036             N& m_v_cv = (*m_iter)[n_var+1];
04037             ++m_iter;
04038             N& m_cv_v = (*m_iter)[n_var];
04039             ++m_iter;
04040             // NOTE: delay update of m_v_cv and m_cv_v.
04041             for ( ; m_iter != m_end; ++m_iter) {
04042               Row_Reference m_i = *m_iter;
04043               N& m_i_v = m_i[n_var];
04044               add_assign_r(m_i_v, m_i_v, d, ROUND_UP);
04045               N& m_i_cv = m_i[n_var+1];
04046               add_assign_r(m_i_cv, m_i_cv, minus_d, ROUND_UP);
04047             }
04048             // Now update m_v_cv and m_cv_v.
04049             mul2exp_assign_r(d, d, 1, ROUND_IGNORE);
04050             add_assign_r(m_cv_v, m_cv_v, d, ROUND_UP);
04051             mul2exp_assign_r(minus_d, minus_d, 1, ROUND_IGNORE);
04052             add_assign_r(m_v_cv, m_v_cv, minus_d, ROUND_UP);
04053            }
04054           reset_strongly_closed();
04055         }
04056 
04057         else {
04058           // Here `w_coeff == -denominator'.
04059           // Remove the binary constraints on `var'.
04060           forget_binary_octagonal_constraints(var_id);
04061            Row_Iterator m_iter = m_begin + n_var;
04062           N& m_v_cv = (*m_iter)[n_var+1];
04063           ++m_iter;
04064           N& m_cv_v = (*m_iter)[n_var];
04065           // Swap the unary constraints on `var'.
04066           std::swap(m_v_cv, m_cv_v);
04067           // Strong closure is not preserved.
04068           reset_strongly_closed();
04069           if (b != 0) {
04070             // Translate all the constraints on `var' adding or
04071             // subtracting the value `b/denominator'.
04072             DIRTY_TEMP(N, d);
04073             div_round_up(d, b, denominator);
04074             DIRTY_TEMP(N, minus_d);
04075             div_round_up(minus_d, b, minus_den);
04076             ++m_iter;
04077             for ( ; m_iter != m_end; ++m_iter) {
04078               Row_Reference m_i = *m_iter;
04079               N& m_i_v = m_i[n_var];
04080               add_assign_r(m_i_v, m_i_v, d, ROUND_UP);
04081               N& m_i_cv = m_i[n_var+1];
04082               add_assign_r(m_i_cv, m_i_cv, minus_d, ROUND_UP);
04083             }
04084             mul2exp_assign_r(d, d, 1, ROUND_IGNORE);
04085             add_assign_r(m_cv_v, m_cv_v, d, ROUND_UP);
04086             mul2exp_assign_r(minus_d, minus_d, 1, ROUND_IGNORE);
04087             add_assign_r(m_v_cv, m_v_cv, minus_d, ROUND_UP);
04088           }
04089           incremental_strong_closure_assign(var);
04090          }
04091       }
04092 
04093       else {
04094         // Here `w != var', so that `expr' is of the form
04095         // +/-denominator * w + b.
04096         // Remove all constraints on `var'.
04097         forget_all_octagonal_constraints(var_id);
04098         const dimension_type n_w = 2*w_id;
04099         // Add the new constraint `var - w = b/denominator'.
04100         if (w_coeff == denominator)
04101           if (var_id < w_id) {
04102             add_octagonal_constraint(n_w, n_var, b, denominator);
04103             add_octagonal_constraint(n_w+1, n_var+1, b, minus_den);
04104           }
04105           else {
04106             add_octagonal_constraint(n_var+1, n_w+1, b, denominator);
04107             add_octagonal_constraint(n_var, n_w, b, minus_den);
04108           }
04109         else
04110           // Add the new constraint `var + w = b/denominator'.
04111           if (var_id < w_id) {
04112             add_octagonal_constraint(n_w+1, n_var, b, denominator);
04113             add_octagonal_constraint(n_w, n_var+1, b, minus_den);
04114           }
04115           else {
04116             add_octagonal_constraint(n_var+1, n_w, b, denominator);
04117             add_octagonal_constraint(n_var, n_w+1, b, minus_den);
04118           }
04119         incremental_strong_closure_assign(var);
04120       }
04121       assert(OK());
04122       return;
04123     }
04124   }
04125 
04126   // General case.
04127   // Either t == 2, so that
04128   // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
04129   // or t == 1, expr == a*w + b, but a <> +/- denominator.
04130   // We will remove all the constraints on `var' and add back
04131   // constraints providing upper and lower bounds for `var'.
04132 
04133   // Compute upper approximations for `expr' and `-expr'
04134   // into `pos_sum' and `neg_sum', respectively, taking into account
04135   // the sign of `denominator'.
04136   // Note: approximating `-expr' from above and then negating the
04137   // result is the same as approximating `expr' from below.
04138   const bool is_sc = (denominator > 0);
04139   TEMP_INTEGER(minus_b);
04140   neg_assign_r(minus_b, b, ROUND_NOT_NEEDED);
04141 
04142   const Coefficient& sc_b = is_sc ? b : minus_b;
04143   const Coefficient& minus_sc_b = is_sc ? minus_b : b;
04144   const Coefficient& sc_den = is_sc ? denominator : minus_den;
04145   const Coefficient& minus_sc_den = is_sc ? minus_den : denominator;
04146   // NOTE: here, for optimization purposes, `minus_expr' is only assigned
04147   // when `denominator' is negative. Do not use it unless you are sure
04148   // it has been correctly assigned.
04149   Linear_Expression minus_expr;
04150   if (!is_sc)
04151     minus_expr = -expr;
04152   const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
04153 
04154   DIRTY_TEMP(N, pos_sum);
04155   DIRTY_TEMP(N, neg_sum);
04156   // Indices of the variables that are unbounded in `this->matrix'.
04157   PPL_UNINITIALIZED(dimension_type, pos_pinf_index);
04158   PPL_UNINITIALIZED(dimension_type, neg_pinf_index);
04159   // Number of unbounded variables found.
04160   dimension_type pos_pinf_count = 0;
04161   dimension_type neg_pinf_count = 0;
04162 
04163   // Approximate the inhomogeneous term.
04164   assign_r(pos_sum, sc_b, ROUND_UP);
04165   assign_r(neg_sum, minus_sc_b, ROUND_UP);
04166 
04167   // Approximate the homogeneous part of `sc_expr'.
04168   DIRTY_TEMP(N, coeff_i);
04169   DIRTY_TEMP(N, minus_coeff_i);
04170   DIRTY_TEMP(N, half);
04171   TEMP_INTEGER(minus_sc_i);
04172   // Note: indices above `w' can be disregarded, as they all have
04173   // a zero coefficient in `sc_expr'.
04174   for (Row_iterator m_iter = m_begin, m_iter_end = m_iter + (2*w_id) + 2;
04175        m_iter != m_iter_end; ) {
04176     const dimension_type n_i = m_iter.index();
04177     const dimension_type id = n_i/2;
04178     Row_reference m_i = *m_iter;
04179     ++m_iter;
04180     Row_reference m_ci = *m_iter;
04181     ++m_iter;
04182     const Coefficient& sc_i = sc_expr.coefficient(Variable(id));
04183     const int sign_i = sgn(sc_i);
04184     if (sign_i > 0) {
04185       assign_r(coeff_i, sc_i, ROUND_UP);
04186       // Approximating `sc_expr'.
04187       if (pos_pinf_count <= 1) {
04188         const N& double_up_approx_i = m_ci[n_i];
04189         if (!is_plus_infinity(double_up_approx_i)) {
04190           // Let half = double_up_approx_i / 2.
04191           div2exp_assign_r(half, double_up_approx_i, 1, ROUND_UP);
04192           add_mul_assign_r(pos_sum, coeff_i, half, ROUND_UP);
04193         }
04194         else {
04195           ++pos_pinf_count;
04196           pos_pinf_index = id;
04197         }
04198       }
04199       // Approximating `-sc_expr'.
04200       if (neg_pinf_count <= 1) {
04201         const N& double_up_approx_minus_i = m_i[n_i+1];
04202         if (!is_plus_infinity(double_up_approx_minus_i)) {
04203           // Let half = double_up_approx_minus_i / 2.
04204           div2exp_assign_r(half, double_up_approx_minus_i, 1, ROUND_UP);
04205           add_mul_assign_r(neg_sum, coeff_i, half, ROUND_UP);
04206         }
04207         else {
04208           ++neg_pinf_count;
04209           neg_pinf_index = id;
04210         }
04211       }
04212     }
04213     else if (sign_i < 0) {
04214       neg_assign_r(minus_sc_i, sc_i, ROUND_NOT_NEEDED);
04215       assign_r(minus_coeff_i, minus_sc_i, ROUND_UP);
04216       // Approximating `sc_expr'.
04217       if (pos_pinf_count <= 1) {
04218         const N& double_up_approx_minus_i = m_i[n_i+1];
04219         if (!is_plus_infinity(double_up_approx_minus_i)) {
04220           // Let half = double_up_approx_minus_i / 2.
04221           div2exp_assign_r(half, double_up_approx_minus_i, 1, ROUND_UP);
04222           add_mul_assign_r(pos_sum, minus_coeff_i, half, ROUND_UP);
04223         }
04224         else {
04225           ++pos_pinf_count;
04226           pos_pinf_index = id;
04227         }
04228       }
04229       // Approximating `-sc_expr'.
04230       if (neg_pinf_count <= 1) {
04231         const N& double_up_approx_i = m_ci[n_i];
04232         if (!is_plus_infinity(double_up_approx_i)) {
04233           // Let half = double_up_approx_i / 2.
04234           div2exp_assign_r(half, double_up_approx_i, 1, ROUND_UP);
04235           add_mul_assign_r(neg_sum, minus_coeff_i, half, ROUND_UP);
04236         }
04237         else {
04238           ++neg_pinf_count;
04239           neg_pinf_index = id;
04240         }
04241       }
04242     }
04243   }
04244 
04245   // Remove all constraints on `var'.
04246   forget_all_octagonal_constraints(var_id);
04247   // Return immediately if no approximation could be computed.
04248   if (pos_pinf_count > 1 && neg_pinf_count > 1) {
04249     assert(OK());
04250     return;
04251   }
04252 
04253   // In the following, strong closure will be definitely lost.
04254   reset_strongly_closed();
04255 
04256   // Exploit the upper approximation, if possible.
04257   if (pos_pinf_count <= 1) {
04258     // Compute quotient (if needed).
04259     if (sc_den != 1) {
04260       // Before computing quotients, the denominator should be approximated
04261       // towards zero. Since `sc_den' is known to be positive, this amounts to
04262       // rounding downwards, which is achieved as usual by rounding upwards
04263       // `minus_sc_den' and negating again the result.
04264       DIRTY_TEMP(N, down_sc_den);
04265       assign_r(down_sc_den, minus_sc_den, ROUND_UP);
04266       neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
04267       div_assign_r(pos_sum, pos_sum, down_sc_den, ROUND_UP);
04268     }
04269     // Add the upper bound constraint, if meaningful.
04270     if (pos_pinf_count == 0) {
04271       // Add the constraint `v <= pos_sum'.
04272       DIRTY_TEMP(N, double_pos_sum);
04273       mul2exp_assign_r(double_pos_sum, pos_sum, 1, ROUND_IGNORE);
04274       matrix[n_var+1][n_var] = double_pos_sum;
04275       // Deduce constraints of the form `v +/- u', where `u != v'.
04276       deduce_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, pos_sum);
04277     }
04278     else
04279       // Here `pos_pinf_count == 1'.
04280       if (pos_pinf_index != var_id) {
04281         const Coefficient& ppi = sc_expr.coefficient(Variable(pos_pinf_index));
04282         if (ppi == sc_den)
04283           // Add the constraint `v - pos_pinf_index <= pos_sum'.
04284           if (var_id < pos_pinf_index)
04285             matrix[2*pos_pinf_index][n_var] = pos_sum;
04286           else
04287             matrix[n_var+1][2*pos_pinf_index+1] = pos_sum;
04288         else
04289           if (ppi == minus_sc_den) {
04290             // Add the constraint `v + pos_pinf_index <= pos_sum'.
04291             if (var_id < pos_pinf_index)
04292               matrix[2*pos_pinf_index+1][n_var] = pos_sum;
04293             else
04294               matrix[n_var+1][2*pos_pinf_index] = pos_sum;
04295           }
04296       }
04297   }
04298 
04299   // Exploit the lower approximation, if possible.
04300   if (neg_pinf_count <= 1) {
04301     // Compute quotient (if needed).
04302     if (sc_den != 1) {
04303       // Before computing quotients, the denominator should be approximated
04304       // towards zero. Since `sc_den' is known to be positive, this amounts to
04305       // rounding downwards, which is achieved as usual by rounding upwards
04306       // `minus_sc_den' and negating again the result.
04307       DIRTY_TEMP(N, down_sc_den);
04308       assign_r(down_sc_den, minus_sc_den, ROUND_UP);
04309       neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
04310       div_assign_r(neg_sum, neg_sum, down_sc_den, ROUND_UP);
04311     }
04312     // Add the lower bound constraint, if meaningful.
04313     if (neg_pinf_count == 0) {
04314       // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
04315       DIRTY_TEMP(N, double_neg_sum);
04316       mul2exp_assign_r(double_neg_sum, neg_sum, 1, ROUND_IGNORE);
04317       matrix[n_var][n_var+1] = double_neg_sum;
04318       // Deduce constraints of the form `-v +/- u', where `u != v'.
04319       deduce_minus_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, neg_sum);
04320     }
04321     else
04322       // Here `neg_pinf_count == 1'.
04323       if (neg_pinf_index != var_id) {
04324         const Coefficient& npi = sc_expr.coefficient(Variable(neg_pinf_index));
04325         if (npi == sc_den)
04326           // Add the constraint `v - neg_pinf_index >= -neg_sum',
04327           // i.e., `neg_pinf_index - v <= neg_sum'.
04328           if (neg_pinf_index < var_id)
04329             matrix[n_var][2*neg_pinf_index] = neg_sum;
04330           else
04331             matrix[2*neg_pinf_index+1][n_var+1] = neg_sum;
04332         else
04333           if (npi == minus_sc_den) {
04334             // Add the constraint `v + neg_pinf_index >= -neg_sum',
04335             // i.e., `-neg_pinf_index - v <= neg_sum'.
04336             if (neg_pinf_index < var_id)
04337               matrix[n_var][2*neg_pinf_index+1] = neg_sum;
04338             else
04339               matrix[2*neg_pinf_index][n_var+1] = neg_sum;
04340           }
04341       }
04342   }
04343 
04344   incremental_strong_closure_assign(var);
04345   assert(OK());
04346 }

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 4350 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(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), TEMP_INTEGER, 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 >::generalized_affine_preimage().

04353                                                  {
04354 
04355   // The denominator cannot be zero.
04356   if (denominator == 0)
04357     throw_generic("affine_preimage(v, e, d)", "d == 0");
04358 
04359   // Dimension-compatibility checks.
04360   // The dimension of `expr' should not be greater than the dimension
04361   // of `*this'.
04362   const dimension_type expr_space_dim = expr.space_dimension();
04363   if (space_dim < expr_space_dim)
04364     throw_dimension_incompatible("affine_preimage(v, e, d)", "e", expr);
04365 
04366   // `var' should be one of the dimensions of the octagon.
04367   dimension_type var_id = var.id();
04368   if (space_dim < var_id + 1)
04369     throw_dimension_incompatible("affine_preimage(v, e, d)", var.id()+1);
04370 
04371   strong_closure_assign();
04372   // The image of an empty octagon is empty too.
04373   if (marked_empty())
04374     return;
04375 
04376   const Coefficient& b = expr.inhomogeneous_term();
04377 
04378   // Number of non-zero coefficients in `expr': will be set to
04379   // 0, 1, or 2, the latter value meaning any value greater than 1.
04380   dimension_type t = 0;
04381 
04382   // Variable-index of the last non-zero coefficient in `expr', if any.
04383   dimension_type w_id = 0;
04384 
04385   // Get information about the number of the non-zero coefficients of `expr'.
04386   for (dimension_type i = expr_space_dim; i-- > 0; )
04387     if (expr.coefficient(Variable(i)) != 0) {
04388       if (t++ == 1)
04389         break;
04390       else
04391         w_id = i;
04392     }
04393 
04394   // `w' is the variable with index `w_id'.
04395   // Now we know the form of `expr':
04396   // - If t == 0, then expr == b, with `b' a constant;
04397   // - If t == 1, then expr == a*w + b, where `w' can be `v' or another
04398   //   variable; in this second case we have to check whether `a' is
04399   //   equal to `denominator' or `-denominator', since otherwise we have
04400   //   to fall back on the general form;
04401   // - If t == 2, the `expr' is of the general form.
04402 
04403   if (t == 0) {
04404     // Case 1: expr = n; remove all constraints on `var'.
04405     forget_all_octagonal_constraints(var_id);
04406     assert(OK());
04407     return;
04408   }
04409 
04410   if (t == 1) {
04411     // Value of the one and only non-zero coefficient in `expr'.
04412     const Coefficient& w_coeff = expr.coefficient(Variable(w_id));
04413     if (w_coeff == denominator || w_coeff == -denominator) {
04414       // Case 2: expr = w_coeff*w + b, with w_coeff = +/- denominator.
04415       if (w_id == var_id) {
04416         // Apply affine_image() on the inverse of this transformation.
04417         affine_image(var, denominator*var - b, w_coeff);
04418       }
04419       else {
04420         // `expr == w_coeff*w + b', where `w != var'.
04421         // Remove all constraints on `var'.
04422         forget_all_octagonal_constraints(var_id);
04423         assert(OK());
04424       }
04425       return;
04426     }
04427   }
04428   // General case.
04429   // Either t == 2, so that
04430   // expr = a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
04431   // or t = 1, expr = a*w + b, but a <> +/- denominator.
04432   const Coefficient& coeff_v = expr.coefficient(var);
04433   if (coeff_v != 0) {
04434     if (coeff_v > 0) {
04435       // The transformation is invertible.
04436       Linear_Expression inverse = ((coeff_v + denominator)*var);
04437       inverse -= expr;
04438       affine_image(var, inverse, coeff_v);
04439     }
04440     else {
04441       // The transformation is invertible.
04442       TEMP_INTEGER(minus_coeff_v);
04443       neg_assign(minus_coeff_v, coeff_v);
04444       Linear_Expression inverse = ((minus_coeff_v - denominator)*var);
04445       inverse += expr;
04446       affine_image(var, inverse, minus_coeff_v);
04447     }
04448   }
04449   else {
04450     // The transformation is not invertible: all constraints on `var' are lost.
04451     forget_all_octagonal_constraints(var_id);
04452     assert(OK());
04453   }
04454 }

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

References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), 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 >::deduce_v_pm_u_bounds(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_binary_octagonal_constraints(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, 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::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), PLUS_INFINITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), TEMP_INTEGER, 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 >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage().

04462                                                                           {
04463   // The denominator cannot be zero.
04464   if (denominator == 0)
04465     throw_generic("generalized_affine_image(v, r, e, d)", "d == 0");
04466 
04467   // Dimension-compatibility checks.
04468   // The dimension of `expr' should not be greater than the dimension
04469   // of `*this'.
04470   const dimension_type expr_space_dim = expr.space_dimension();
04471   if (space_dim < expr_space_dim)
04472     throw_dimension_incompatible("generalized_affine_image(v, r, e, d)", "e",
04473                                  expr);
04474 
04475   // `var' should be one of the dimensions of the octagon.
04476   dimension_type var_id = var.id();
04477   if (space_dim < var_id + 1)
04478     throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
04479                                  var.id()+1);
04480 
04481   // The relation symbol cannot be a strict relation symbol.
04482   if (relsym == LESS_THAN || relsym == GREATER_THAN)
04483     throw_generic("generalized_affine_image(v, r, e, d)",
04484                   "r is a strict relation symbol and "
04485                   "*this is an Octagonal_Shape");
04486 
04487   if (relsym == EQUAL) {
04488     // The relation symbol is "==":
04489     // this is just an affine image computation.
04490     affine_image(var, expr, denominator);
04491     return;
04492   }
04493 
04494   strong_closure_assign();
04495   // The image of an empty octagon is empty too.
04496   if (marked_empty())
04497     return;
04498 
04499   // Number of non-zero coefficients in `expr': will be set to
04500   // 0, 1, or 2, the latter value meaning any value greater than 1.
04501   dimension_type t = 0;
04502   // Variable-index of the last non-zero coefficient in `expr', if any.
04503   dimension_type w_id = 0;
04504 
04505   // Get information about the number of non-zero coefficients in `expr'.
04506   // The `expr' must not be in two or plus variables.
04507   for (dimension_type i = expr_space_dim; i-- > 0; )
04508     if (expr.coefficient(Variable(i)) != 0) {
04509       if (t++ == 1)
04510         break;
04511       else
04512         w_id = i;
04513     }
04514 
04515   typedef typename OR_Matrix<N>::row_iterator Row_Iterator;
04516   typedef typename OR_Matrix<N>::row_reference_type Row_Reference;
04517   typedef typename OR_Matrix<N>::const_row_iterator Row_iterator;
04518   typedef typename OR_Matrix<N>::const_row_reference_type Row_reference;
04519 
04520   const Row_Iterator m_begin = matrix.row_begin();
04521   const Row_Iterator m_end = matrix.row_end();
04522   const dimension_type n_var = 2*var_id;
04523   const Coefficient& b = expr.inhomogeneous_term();
04524   TEMP_INTEGER(minus_den);
04525   neg_assign_r(minus_den, denominator, ROUND_NOT_NEEDED);
04526 
04527   // `w' is the variable with index `w_id'.
04528   // Now we know the form of `expr':
04529   // - If t == 0, then expr == b, with `b' a constant;
04530   // - If t == 1, then expr == a*w + b, where `w' can be `v' or another
04531   //   variable; in this second case we have to check whether `a' is
04532   //   equal to `denominator' or `-denominator', since otherwise we have
04533   //   to fall back on the general form;
04534   // - If t == 2, the `expr' is of the general form.
04535 
04536   if (t == 0) {
04537     // Case 1: expr = b.
04538     TEMP_INTEGER(two_b);
04539     two_b = 2*b;
04540     // Remove all constraints on `var'.
04541     forget_all_octagonal_constraints(var_id);
04542     // Strong closure is lost.
04543     reset_strongly_closed();
04544     switch (relsym) {
04545     case LESS_OR_EQUAL:
04546       // Add the constraint `var <= b/denominator'.
04547       add_octagonal_constraint(n_var+1, n_var, two_b, denominator);
04548       break;
04549     case GREATER_OR_EQUAL:
04550       // Add the constraint `var >= n/denominator',
04551       // i.e., `-var <= -b/denominator'.
04552       add_octagonal_constraint(n_var, n_var+1, two_b, minus_den);
04553       break;
04554     default:
04555       // We already dealt with the other cases.
04556       throw std::runtime_error("PPL internal error");
04557     }
04558     assert(OK());
04559     return;
04560   }
04561 
04562   if (t == 1) {
04563     // The one and only non-zero homogeneous coefficient in `expr'.
04564     const Coefficient& w_coeff = expr.coefficient(Variable(w_id));
04565     if (w_coeff == denominator || w_coeff == minus_den) {
04566       // Case 2: expr == w_coeff*w + b, with w_coeff == +/- denominator.
04567       switch (relsym) {
04568       case LESS_OR_EQUAL:
04569         {
04570           DIRTY_TEMP(N, d);
04571           div_round_up(d, b, denominator);
04572           if (w_id == var_id) {
04573             // Here `expr' is of the form: +/- denominator * v + b.
04574             // Strong closure is not preserved.
04575             reset_strongly_closed();
04576             if (w_coeff == denominator) {
04577               // Translate all the constraints of the form `v - w <= cost'
04578               // into the constraint `v - w <= cost + b/denominator';
04579               // forget each constraint `w - v <= cost1'.
04580               Row_Iterator m_iter = m_begin + n_var;
04581               Row_Reference m_v = *m_iter;
04582               N& m_v_cv = m_v[n_var+1];
04583               ++m_iter;
04584               Row_Reference m_cv = *m_iter;
04585               N& m_cv_v = m_cv[n_var];
04586               ++m_iter;
04587               // NOTE: delay update of m_v_cv and m_cv_v.
04588               for ( ; m_iter != m_end; ++m_iter) {
04589                 Row_Reference m_i = *m_iter;
04590                 N& m_i_v = m_i[n_var];
04591                 add_assign_r(m_i_v, m_i_v, d, ROUND_UP);
04592                 assign_r(m_i[n_var+1], PLUS_INFINITY, ROUND_NOT_NEEDED);
04593               }
04594               for (dimension_type k = n_var; k-- > 0; ) {
04595                 assign_r(m_v[k], PLUS_INFINITY, ROUND_NOT_NEEDED);
04596                 add_assign_r(m_cv[k], m_cv[k], d, ROUND_UP);
04597               }
04598               mul2exp_assign_r(d, d, 1, ROUND_IGNORE);
04599               add_assign_r(m_cv_v, m_cv_v, d, ROUND_UP);
04600               assign_r(m_v_cv, PLUS_INFINITY, ROUND_NOT_NEEDED);
04601             }
04602             else {
04603               // Here `w_coeff == -denominator'.
04604               // `expr' is of the form: -a*var + b.
04605               N& m_v_cv = matrix[n_var][n_var+1];
04606               mul2exp_assign_r(d, d, 1, ROUND_IGNORE);
04607               add_assign_r(matrix[n_var+1][n_var], m_v_cv, d, ROUND_UP);
04608               assign_r(m_v_cv, PLUS_INFINITY, ROUND_NOT_NEEDED);
04609               forget_binary_octagonal_constraints(var_id);
04610             }
04611           }
04612           else {
04613             // Here `w != v', so that `expr' is the form
04614             // +/- denominator*w + b.
04615             // Remove all constraints on `v'.
04616             forget_all_octagonal_constraints(var_id);
04617             const dimension_type n_w = 2*w_id;
04618             if (w_coeff == denominator) {
04619               // Add the new constraint `v - w <= b/denominator'.
04620               if (var_id < w_id)
04621                 add_octagonal_constraint(n_w, n_var, b, denominator);
04622               else
04623                 add_octagonal_constraint(n_var+1, n_w+1, b, denominator);
04624             }
04625             else {
04626               // Add the new constraint `v + w <= b/denominator'.
04627               if (var_id < w_id)
04628                 add_octagonal_constraint(n_w+1, n_var, b, denominator);
04629               else
04630                 add_octagonal_constraint(n_var+1, n_w, b, denominator);
04631             }
04632           }
04633           break;
04634         }
04635 
04636       case GREATER_OR_EQUAL:
04637         {
04638           DIRTY_TEMP(N, d);
04639           div_round_up(d, b, minus_den);
04640           if (w_id == var_id) {
04641             // Here `expr' is of the form: +/- denominator * v + b.
04642             // Strong closure is not preserved.
04643             reset_strongly_closed();
04644             if (w_coeff == denominator) {
04645               // Translate each constraint `w - v <= cost'
04646               // into the constraint `w - v <= cost - b/denominator';
04647               // forget each constraint `v - w <= cost1'.
04648               Row_Iterator m_iter = m_begin + n_var;
04649               Row_Reference m_v = *m_iter;
04650               N& m_v_cv = m_v[n_var+1];
04651               ++m_iter;
04652               Row_Reference m_cv = *m_iter;
04653               N& m_cv_v = m_cv[n_var];
04654               ++m_iter;
04655               // NOTE: delay update of m_v_cv and m_cv_v.
04656               for ( ; m_iter != m_end; ++m_iter) {
04657                 Row_Reference m_i = *m_iter;
04658                 assign_r(m_i[n_var], PLUS_INFINITY, ROUND_NOT_NEEDED);
04659                 add_assign_r(m_i[n_var+1], m_i[n_var+1], d, ROUND_UP);
04660               }
04661               for (dimension_type k = n_var; k-- > 0; ) {
04662                 add_assign_r(m_v[k], m_v[k], d, ROUND_UP);
04663                 assign_r(m_cv[k], PLUS_INFINITY, ROUND_NOT_NEEDED);
04664               }
04665               mul2exp_assign_r(d, d, 1, ROUND_IGNORE);
04666               add_assign_r(m_v_cv, m_v_cv, d, ROUND_UP);
04667               assign_r(m_cv_v, PLUS_INFINITY, ROUND_NOT_NEEDED);
04668             }
04669             else {
04670               // Here `w_coeff == -denominator'.
04671               // `expr' is of the form: -a*var + b.
04672               N& m_cv_v = matrix[n_var+1][n_var];
04673               mul2exp_assign_r(d, d, 1, ROUND_IGNORE);
04674               add_assign_r(matrix[n_var][n_var+1], m_cv_v, d, ROUND_UP);
04675               assign_r(m_cv_v, PLUS_INFINITY, ROUND_NOT_NEEDED);
04676               forget_binary_octagonal_constraints(var_id);
04677             }
04678           }
04679           else {
04680             // Here `w != v', so that `expr' is of the form
04681             // +/-denominator * w + b, with `w != v'.
04682             // Remove all constraints on `v'.
04683             forget_all_octagonal_constraints(var_id);
04684             const dimension_type n_w = 2*w_id;
04685             // We have got an expression of the following form:
04686             // var1 + n, with `var1' != `var'.
04687             // We remove all constraints of the form `var (+/- var1) >= const'
04688             // and we add the new constraint `var +/- var1 >= n/denominator'.
04689             if (w_coeff == denominator) {
04690               // Add the new constraint `var - w >= b/denominator',
04691               // i.e., `w - var <= -b/denominator'.
04692               if (var_id < w_id)
04693                 add_octagonal_constraint(n_w+1, n_var+1, b, minus_den);
04694               else
04695                 add_octagonal_constraint(n_var, n_w, b, minus_den);
04696             }
04697             else {
04698               // Add the new constraint `var + w >= b/denominator',
04699               // i.e., `-w - var <= -b/denominator'.
04700               if (var_id < w_id)
04701                 add_octagonal_constraint(n_w, n_var+1, b, minus_den);
04702               else
04703                 add_octagonal_constraint(n_var, n_w+1, b, minus_den);
04704             }
04705           }
04706           break;
04707         }
04708 
04709       default:
04710         // We already dealt with the other cases.
04711         throw std::runtime_error("PPL internal error");
04712       }
04713       assert(OK());
04714       return;
04715     }
04716   }
04717 
04718   // General case.
04719   // Either t == 2, so that
04720   // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
04721   // or t == 1, expr == a*w + b, but a <> +/- denominator.
04722   // We will remove all the constraints on `v' and add back
04723   // a constraint providing an upper or a lower bound for `v'
04724   // (depending on `relsym').
04725   const bool is_sc = (denominator > 0);
04726   TEMP_INTEGER(minus_b);
04727   neg_assign(minus_b, b);
04728   const Coefficient& sc_b = is_sc ? b : minus_b;
04729   const Coefficient& minus_sc_b = is_sc ? minus_b : b;
04730   const Coefficient& sc_den = is_sc ? denominator : minus_den;
04731   const Coefficient& minus_sc_den = is_sc ? minus_den : denominator;
04732   // NOTE: here, for optimization purposes, `minus_expr' is only assigned
04733   // when `denominator' is negative. Do not use it unless you are sure
04734   // it has been correctly assigned.
04735   Linear_Expression minus_expr;
04736   if (!is_sc)
04737     minus_expr = -expr;
04738   const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
04739 
04740   DIRTY_TEMP(N, sum);
04741   // Index of variable that is unbounded in `this->matrix'.
04742   PPL_UNINITIALIZED(dimension_type, pinf_index);
04743   // Number of unbounded variables found.
04744   dimension_type pinf_count = 0;
04745 
04746   switch (relsym) {
04747   case LESS_OR_EQUAL:
04748     {
04749       // Compute an upper approximation for `sc_expr' into `sum'.
04750 
04751       // Approximate the inhomogeneous term.
04752       assign_r(sum, sc_b, ROUND_UP);
04753       // Approximate the homogeneous part of `sc_expr'.
04754       DIRTY_TEMP(N, coeff_i);
04755       DIRTY_TEMP(N, approx_i);
04756       TEMP_INTEGER(minus_sc_i);
04757       // Note: indices above `w' can be disregarded, as they all have
04758       // a zero coefficient in `sc_expr'.
04759       for (Row_iterator m_iter = m_begin, m_iter_end = m_iter + (2*w_id) + 2;
04760            m_iter != m_iter_end; ) {
04761         const dimension_type n_i = m_iter.index();
04762         const dimension_type id = n_i/2;
04763         Row_reference m_i = *m_iter;
04764         ++m_iter;
04765         Row_reference m_ci = *m_iter;
04766         ++m_iter;
04767         const Coefficient& sc_i = sc_expr.coefficient(Variable(id));
04768         const int sign_i = sgn(sc_i);
04769         if (sign_i == 0)
04770           continue;
04771         // Choose carefully: we are approximating `sc_expr'.
04772         const N& double_approx_i = (sign_i > 0) ? m_ci[n_i] : m_i[n_i+1];
04773         if (is_plus_infinity(double_approx_i)) {
04774           if (++pinf_count > 1)
04775             break;
04776           pinf_index = id;
04777           continue;
04778         }
04779         if (sign_i > 0)
04780           assign_r(coeff_i, sc_i, ROUND_UP);
04781         else {
04782           neg_assign(minus_sc_i, sc_i);
04783           assign_r(coeff_i, minus_sc_i, ROUND_UP);
04784         }
04785         div2exp_assign_r(approx_i, double_approx_i, 1, ROUND_UP);
04786         add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
04787       }
04788       // Remove all constraints on `v'.
04789       forget_all_octagonal_constraints(var_id);
04790       reset_strongly_closed();
04791       // Return immediately if no approximation could be computed.
04792       if (pinf_count > 1) {
04793         assert(OK());
04794         return;
04795       }
04796 
04797       // Divide by the (sign corrected) denominator (if needed).
04798       if (sc_den != 1) {
04799         // Before computing the quotient, the denominator should be
04800         // approximated towards zero. Since `sc_den' is known to be
04801         // positive, this amounts to rounding downwards, which is
04802         // achieved as usual by rounding upwards
04803         // `minus_sc_den' and negating again the result.
04804         DIRTY_TEMP(N, down_sc_den);
04805         assign_r(down_sc_den, minus_sc_den, ROUND_UP);
04806         neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
04807         div_assign_r(sum, sum, down_sc_den, ROUND_UP);
04808       }
04809 
04810       if (pinf_count == 0) {
04811         // Add the constraint `v <= pos_sum'.
04812         DIRTY_TEMP(N, double_sum);
04813         mul2exp_assign_r(double_sum, sum, 1, ROUND_IGNORE);
04814         matrix[n_var+1][n_var] = double_sum;
04815         // Deduce constraints of the form `v +/- u', where `u != v'.
04816         deduce_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, sum);
04817       }
04818       else if (pinf_count == 1)
04819         if (pinf_index != var_id) {
04820           const Coefficient& pi = expr.coefficient(Variable(pinf_index));
04821           if (pi == denominator ) {
04822             // Add the constraint `v - pinf_index <= sum'.
04823             if (var_id < pinf_index)
04824               matrix[2*pinf_index][n_var] = sum;
04825             else
04826               matrix[n_var+1][2*pinf_index+1] = sum;
04827           }
04828           else {
04829             if (pi == minus_den) {
04830               // Add the constraint `v + pinf_index <= sum'.
04831               if (var_id < pinf_index)
04832                 matrix[2*pinf_index+1][n_var] = sum;
04833               else
04834                 matrix[n_var+1][2*pinf_index] = sum;
04835             }
04836           }
04837         }
04838       break;
04839     }
04840 
04841   case GREATER_OR_EQUAL:
04842     {
04843       // Compute an upper approximation for `-sc_expr' into `sum'.
04844       // Note: approximating `-sc_expr' from above and then negating the
04845       // result is the same as approximating `sc_expr' from below.
04846 
04847       // Approximate the inhomogeneous term.
04848       assign_r(sum, minus_sc_b, ROUND_UP);
04849       DIRTY_TEMP(N, coeff_i);
04850       TEMP_INTEGER(minus_sc_i);
04851       DIRTY_TEMP(N, approx_i);
04852       // Approximate the homogeneous part of `-sc_expr'.
04853       for (Row_iterator m_iter = m_begin, m_iter_end = m_iter + (2*w_id) + 2;
04854            m_iter != m_iter_end; ) {
04855         const dimension_type n_i = m_iter.index();
04856         const dimension_type id = n_i/2;
04857         Row_reference m_i = *m_iter;
04858         ++m_iter;
04859         Row_reference m_ci = *m_iter;
04860         ++m_iter;
04861         const Coefficient& sc_i = sc_expr.coefficient(Variable(id));
04862         const int sign_i = sgn(sc_i);
04863         if (sign_i == 0)
04864           continue;
04865         // Choose carefully: we are approximating `-sc_expr'.
04866         const N& double_approx_i = (sign_i > 0) ? m_i[n_i+1] : m_ci[n_i];
04867         if (is_plus_infinity(double_approx_i)) {
04868           if (++pinf_count > 1)
04869             break;
04870           pinf_index = id;
04871           continue;
04872         }
04873         if (sign_i > 0)
04874           assign_r(coeff_i, sc_i, ROUND_UP);
04875         else {
04876           neg_assign(minus_sc_i, sc_i);
04877           assign_r(coeff_i, minus_sc_i, ROUND_UP);
04878         }
04879         div2exp_assign_r(approx_i, double_approx_i, 1, ROUND_UP);
04880         add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
04881       }
04882 
04883       // Remove all constraints on `var'.
04884       forget_all_octagonal_constraints(var_id);
04885       reset_strongly_closed();
04886       // Return immediately if no approximation could be computed.
04887       if (pinf_count > 1) {
04888         assert(OK());
04889         return;
04890       }
04891 
04892       // Divide by the (sign corrected) denominator (if needed).
04893       if (sc_den != 1) {
04894         // Before computing the quotient, the denominator should be
04895         // approximated towards zero. Since `sc_den' is known to be
04896         // positive, this amounts to rounding downwards, which is
04897         // achieved as usual by rounding upwards
04898         // `minus_sc_den' and negating again the result.
04899         DIRTY_TEMP(N, down_sc_den);
04900         assign_r(down_sc_den, minus_sc_den, ROUND_UP);
04901         neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
04902         div_assign_r(sum, sum, down_sc_den, ROUND_UP);
04903       }
04904 
04905       if (pinf_count == 0) {
04906         // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
04907         DIRTY_TEMP(N, double_sum);
04908         mul2exp_assign_r(double_sum, sum, 1, ROUND_IGNORE);
04909         matrix[n_var][n_var+1] = double_sum;
04910         // Deduce constraints of the form `-v +/- u', where `u != v'.
04911         deduce_minus_v_pm_u_bounds(var_id, pinf_index, sc_expr, sc_den, sum);
04912       }
04913       else if (pinf_count == 1)
04914         if (pinf_index != var_id) {
04915           const Coefficient& pi = expr.coefficient(Variable(pinf_index));
04916           if (pi == denominator) {
04917             // Add the constraint `v - pinf_index >= -sum',
04918             // i.e., `pinf_index - v <= sum'.
04919             if (pinf_index < var_id)
04920               matrix[n_var][2*pinf_index] = sum;
04921             else
04922               matrix[2*pinf_index+1][n_var+1] = sum;
04923           }
04924           else {
04925             if (pi == minus_den) {
04926               // Add the constraint `v + pinf_index >= -sum',
04927               // i.e., `-pinf_index - v <= sum'.
04928               if (pinf_index < var_id)
04929                 matrix[n_var][2*pinf_index+1] = sum;
04930               else
04931                 matrix[2*pinf_index][n_var+1] = sum;
04932             }
04933           }
04934         }
04935       break;
04936     }
04937 
04938   default:
04939     // We already dealt with the other cases.
04940     throw std::runtime_error("PPL internal error");
04941   }
04942   incremental_strong_closure_assign(var);
04943   assert(OK());
04944 }

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

04950                                                                            {
04951   // Dimension-compatibility checks.
04952   // The dimension of `lhs' should not be greater than the dimension
04953   // of `*this'.
04954   dimension_type lhs_space_dim = lhs.space_dimension();
04955   if (space_dim < lhs_space_dim)
04956     throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
04957                                  "e1", lhs);
04958 
04959   // The dimension of `rhs' should not be greater than the dimension
04960   // of `*this'.
04961   const dimension_type rhs_space_dim = rhs.space_dimension();
04962   if (space_dim < rhs_space_dim)
04963     throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
04964                                  "e2", rhs);
04965 
04966   // Strict relation symbols are not admitted for octagons.
04967   if (relsym == LESS_THAN || relsym == GREATER_THAN)
04968     throw_generic("generalized_affine_image(e1, r, e2)",
04969                   "r is a strict relation symbol and "
04970                   "*this is an Octagonal_Shape");
04971 
04972   strong_closure_assign();
04973   // The image of an empty octagon is empty.
04974   if (marked_empty())
04975     return;
04976 
04977   // Number of non-zero coefficients in `lhs': will be set to
04978   // 0, 1, or 2, the latter value meaning any value greater than 1.
04979   dimension_type t_lhs = 0;
04980   // Index of the last non-zero coefficient in `lhs', if any.
04981   dimension_type j_lhs = 0;
04982 
04983   // Compute the number of the non-zero components of `lhs'.
04984   for (dimension_type i = lhs_space_dim; i-- > 0; )
04985     if (lhs.coefficient(Variable(i)) != 0) {
04986       if (t_lhs++ == 1)
04987         break;
04988       else
04989         j_lhs = i;
04990     }
04991 
04992   const Coefficient& b_lhs = lhs.inhomogeneous_term();
04993 
04994   if (t_lhs == 0) {
04995     // `lhs' is a constant.
04996     // In principle, it is sufficient to add the constraint `lhs relsym rhs'.
04997     // Note that this constraint is an octagonal difference if `t_rhs <= 1'
04998     // or `t_rhs > 1' and `rhs == a*v - a*w + b_rhs' or
04999     // `rhs == a*v + a*w + b_rhs'. If `rhs' is of a
05000     // more general form, it will be simply ignored.
05001     // TODO: if it is not an octagonal difference, should we compute
05002     // approximations for this constraint?
05003     switch (relsym) {
05004     case LESS_OR_EQUAL:
05005       refine_no_check(lhs <= rhs);
05006       break;
05007     case EQUAL:
05008       refine_no_check(lhs == rhs);
05009       break;
05010     case GREATER_OR_EQUAL:
05011       refine_no_check(lhs >= rhs);
05012       break;
05013     default:
05014       // We already dealt with the other cases.
05015       throw std::runtime_error("PPL internal error");
05016     }
05017   }
05018 
05019   else if (t_lhs == 1) {
05020     // Here `lhs == a_lhs * v + b_lhs'.
05021     // Independently from the form of `rhs', we can exploit the
05022     // method computing generalized affine images for a single variable.
05023     Variable v(j_lhs);
05024     // Compute a sign-corrected relation symbol.
05025     const Coefficient& den = lhs.coefficient(v);
05026     Relation_Symbol new_relsym = relsym;
05027     if (den < 0) {
05028       if (relsym == LESS_OR_EQUAL)
05029         new_relsym = GREATER_OR_EQUAL;
05030       else if (relsym == GREATER_OR_EQUAL)
05031         new_relsym = LESS_OR_EQUAL;
05032     }
05033     Linear_Expression expr = rhs - b_lhs;
05034     generalized_affine_image(v, new_relsym, expr, den);
05035   }
05036   else {
05037     // Here `lhs' is of the general form, having at least two variables.
05038     // Compute the set of variables occurring in `lhs'.
05039     bool lhs_vars_intersects_rhs_vars = false;
05040     std::vector<Variable> lhs_vars;
05041     for (dimension_type i = lhs_space_dim; i-- > 0; )
05042       if (lhs.coefficient(Variable(i)) != 0) {
05043         lhs_vars.push_back(Variable(i));
05044         if (rhs.coefficient(Variable(i)) != 0)
05045           lhs_vars_intersects_rhs_vars = true;
05046       }
05047 
05048     if (!lhs_vars_intersects_rhs_vars) {
05049       // `lhs' and `rhs' variables are disjoint.
05050       // Existentially quantify all variables in the lhs.
05051       for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
05052         dimension_type lhs_vars_i = lhs_vars[i].id();
05053         forget_all_octagonal_constraints(lhs_vars_i);
05054       }
05055       // Constrain the left hand side expression so that it is related to
05056       // the right hand side expression as dictated by `relsym'.
05057       // TODO: if the following constraint is NOT an octagonal difference,
05058       // it will be simply ignored. Should we compute approximations for it?
05059       switch (relsym) {
05060       case LESS_OR_EQUAL:
05061         refine_no_check(lhs <= rhs);
05062         break;
05063       case EQUAL:
05064         refine_no_check(lhs == rhs);
05065         break;
05066       case GREATER_OR_EQUAL:
05067         refine_no_check(lhs >= rhs);
05068         break;
05069       default:
05070         // We already dealt with the other cases.
05071         throw std::runtime_error("PPL internal error");
05072       }
05073     }
05074     else {
05075       // Some variables in `lhs' also occur in `rhs'.
05076 
05077 #if 1 // Simplified computation (see the TODO note below).
05078 
05079       for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
05080         dimension_type lhs_vars_i = lhs_vars[i].id();
05081         forget_all_octagonal_constraints(lhs_vars_i);
05082       }
05083 
05084 #else // Currently unnecessarily complex computation.
05085 
05086       // More accurate computation that is worth doing only if
05087       // the following TODO note is accurately dealt with.
05088 
05089       // To ease the computation, we add an additional dimension.
05090       const Variable new_var = Variable(space_dim);
05091       add_space_dimensions_and_embed(1);
05092       // Constrain the new dimension to be equal to `rhs'.
05093       // NOTE: calling affine_image() instead of refine_no_check()
05094       // ensures some approximation is tried even when the constraint
05095       // is not an octagonal constraint.
05096       affine_image(new_var, rhs);
05097       // Existentially quantify all variables in the lhs.
05098       // NOTE: enforce strong closure for precision.
05099       strong_closure_assign();
05100       assert(!marked_empty());
05101       for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
05102         dimension_type lhs_vars_i = lhs_vars[i].id();
05103         forget_all_octagonal_constraints(lhs_vars_i);
05104       }
05105       // Constrain the new dimension so that it is related to
05106       // the left hand side as dictated by `relsym'.
05107       // TODO: each one of the following constraints is definitely NOT
05108       // an octagonal difference (since it has 3 variables at least).
05109       // Thus, the method refine_no_check() will simply ignore it.
05110       // Should we compute approximations for this constraint?
05111       switch (relsym) {
05112       case LESS_OR_EQUAL:
05113         refine_no_check(lhs <= new_var);
05114         break;
05115       case EQUAL:
05116         refine_no_check(lhs == new_var);
05117         break;
05118       case GREATER_OR_EQUAL:
05119         refine_no_check(lhs >= new_var);
05120         break;
05121       default:
05122         // We already dealt with the other cases.
05123         throw std::runtime_error("PPL internal error");
05124       }
05125       // Remove the temporarily added dimension.
05126       remove_higher_space_dimensions(space_dim-1);
05127 #endif // Currently unnecessarily complex computation.
05128     }
05129   }
05130 
05131   assert(OK());
05132 }

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 5136 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(), 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::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), TEMP_INTEGER, Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().

05140                                                       {
05141   // The denominator cannot be zero.
05142   if (denominator == 0)
05143     throw_generic("bounded_affine_image(v, lb, ub, d)", "d == 0");
05144 
05145   // `var' should be one of the dimensions of the octagon.
05146   const dimension_type var_id = var.id();
05147   if (space_dim < var_id + 1)
05148     throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
05149                                  var.id()+1);
05150 
05151   // The dimension of `lb_expr' and `ub_expr' should not be
05152   // greater than the dimension of `*this'.
05153   const dimension_type lb_space_dim = lb_expr.space_dimension();
05154   if (space_dim < lb_space_dim)
05155     throw_dimension_incompatible("bounded_affine_image(v, lb, ub)",
05156                                  "lb", lb_expr);
05157   const dimension_type ub_space_dim = ub_expr.space_dimension();
05158   if (space_dim < ub_space_dim)
05159     throw_dimension_incompatible("bounded_affine_image(v, lb, ub)",
05160                                  "ub", ub_expr);
05161 
05162   strong_closure_assign();
05163   // The image of an empty octagon is empty too.
05164   if (marked_empty())
05165     return;
05166 
05167   // Number of non-zero coefficients in `lb_expr': will be set to
05168   // 0, 1, or 2, the latter value meaning any value greater than 1.
05169   dimension_type t = 0;
05170   // Variable-index of the last non-zero coefficient in `lb_expr', if any.
05171   dimension_type w_id = 0;
05172 
05173   // Get information about the number of non-zero coefficients in `lb_expr'.
05174   // The `expr' must not be in two or plus variables.
05175   for (dimension_type i = lb_space_dim; i-- > 0; )
05176     if (lb_expr.coefficient(Variable(i)) != 0) {
05177       if (t++ == 1)
05178         break;
05179       else
05180         w_id = i;
05181     }
05182 
05183   typedef typename OR_Matrix<N>::row_iterator Row_Iterator;
05184   typedef typename OR_Matrix<N>::row_reference_type Row_Reference;
05185   typedef typename OR_Matrix<N>::const_row_iterator Row_iterator;
05186   typedef typename OR_Matrix<N>::const_row_reference_type Row_reference;
05187 
05188   const Row_Iterator m_begin = matrix.row_begin();
05189   const Row_Iterator m_end = matrix.row_end();
05190   const dimension_type n_var = 2*var_id;
05191   const Coefficient& b = lb_expr.inhomogeneous_term();
05192   TEMP_INTEGER(minus_den);
05193   neg_assign_r(minus_den, denominator, ROUND_NOT_NEEDED);
05194 
05195   // `w' is the variable with index `w_id'.
05196   // Now we know the form of `lb_expr':
05197   // - If t == 0, then lb_expr == b, with `b' a constant;
05198   // - If t == 1, then lb_expr == a*w + b, where `w' can be `v' or another
05199   //   variable; in this second case we have to check whether `a' is
05200   //   equal to `denominator' or `-denominator', since otherwise we have
05201   //   to fall back on the general form;
05202   // - If t == 2, the `lb_expr' is of the general form.
05203 
05204   if (t == 0) {
05205     // Case 1: lb_expr == b.
05206     generalized_affine_image(var,
05207                              LESS_OR_EQUAL,
05208                              ub_expr,
05209                              denominator);
05210     TEMP_INTEGER(two_b);
05211     two_b = 2*b;
05212     // Add the constraint `var >= b/denominator'.
05213     add_octagonal_constraint(n_var, n_var+1, two_b, minus_den);
05214     assert(OK());
05215     return;
05216   }
05217 
05218   if (t == 1) {
05219     // The one and only non-zero homogeneous coefficient in `lb_expr'.
05220     const Coefficient& w_coeff = lb_expr.coefficient(Variable(w_id));
05221     if (w_coeff == denominator || w_coeff == minus_den) {
05222       // Case 2: lb_expr = w_coeff*w + b, with w_coeff = +/- denominator.
05223      if (w_id == var_id) {
05224         // Here `var' occurs in `lb_expr'.
05225         // To ease the computation, we add an additional dimension.
05226         const Variable new_var = Variable(space_dim);
05227         add_space_dimensions_and_embed(1);
05228         // Constrain the new dimension to be equal to `lb_expr'.
05229         // Here `lb_expr' is of the form: +/- denominator * v + b.
05230         affine_image(new_var, lb_expr, denominator);
05231         // Enforce the strong closure for precision.
05232         strong_closure_assign();
05233         assert(!marked_empty());
05234         // Apply the affine upper bound.
05235         generalized_affine_image(var,
05236                                  LESS_OR_EQUAL,
05237                                  ub_expr,
05238                                  denominator);
05239         // Now apply the affine lower bound, as recorded in `new_var'
05240         refine_no_check(var >= new_var);
05241         // Remove the temporarily added dimension.
05242         remove_higher_space_dimensions(space_dim-1);
05243         return;
05244       }
05245       else {
05246         // Apply the affine upper bound.
05247         generalized_affine_image(var,
05248                                  LESS_OR_EQUAL,
05249                                  ub_expr,
05250                                  denominator);
05251         // Here `w != var', so that `lb_expr' is of the form
05252         // +/-denominator * w + b.
05253         const dimension_type n_w = 2*w_id;
05254         // Add the new constraint `var - w >= b/denominator'.
05255         if (w_coeff == denominator)
05256           if (var_id < w_id)
05257             add_octagonal_constraint(n_w+1, n_var+1, b, minus_den);
05258           else
05259             add_octagonal_constraint(n_var, n_w, b, minus_den);
05260         else {
05261           // Add the new constraint `var + w >= b/denominator'.
05262           if (var_id < w_id)
05263             add_octagonal_constraint(n_w, n_var+1, b, minus_den);
05264           else
05265             add_octagonal_constraint(n_var, n_w+1, b, minus_den);
05266         }
05267         assert(OK());
05268         return;
05269       }
05270     }
05271   }
05272 
05273   // General case.
05274   // Either t == 2, so that
05275   // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
05276   // or t == 1, expr == a*w + b, but a <> +/- denominator.
05277   // We will remove all the constraints on `var' and add back
05278   // constraints providing upper and lower bounds for `var'.
05279 
05280   // Compute upper approximations for `expr' and `-expr'
05281   // into `pos_sum' and `neg_sum', respectively, taking into account
05282   // the sign of `denominator'.
05283   // Note: approximating `-expr' from above and then negating the
05284   // result is the same as approximating `expr' from below.
05285   const bool is_sc = (denominator > 0);
05286   TEMP_INTEGER(minus_b);
05287   neg_assign_r(minus_b, b, ROUND_NOT_NEEDED);
05288 
05289   const Coefficient& minus_sc_b = is_sc ? minus_b : b;
05290   const Coefficient& sc_den = is_sc ? denominator : minus_den;
05291   const Coefficient& minus_sc_den = is_sc ? minus_den : denominator;
05292   // NOTE: here, for optimization purposes, `minus_expr' is only assigned
05293   // when `denominator' is negative. Do not use it unless you are sure
05294   // it has been correctly assigned.
05295   Linear_Expression minus_expr;
05296   if (!is_sc)
05297     minus_expr = -lb_expr;
05298   const Linear_Expression& sc_expr = is_sc ? lb_expr : minus_expr;
05299 
05300   DIRTY_TEMP(N, neg_sum);
05301   // Indices of the variables that are unbounded in `this->matrix'.
05302   PPL_UNINITIALIZED(dimension_type, neg_pinf_index);
05303   // Number of unbounded variables found.
05304   dimension_type neg_pinf_count = 0;
05305 
05306   // Approximate the inhomogeneous term.
05307   assign_r(neg_sum, minus_sc_b, ROUND_UP);
05308 
05309   // Approximate the homogeneous part of `sc_expr'.
05310   DIRTY_TEMP(N, coeff_i);
05311   DIRTY_TEMP(N, minus_coeff_i);
05312   DIRTY_TEMP(N, half);
05313   TEMP_INTEGER(minus_sc_i);
05314   // Note: indices above `w' can be disregarded, as they all have
05315   // a zero coefficient in `sc_expr'.
05316   for (Row_iterator m_iter = m_begin, m_iter_end = m_iter + (2*w_id) + 2;
05317        m_iter != m_iter_end; ) {
05318     const dimension_type n_i = m_iter.index();
05319     const dimension_type id = n_i/2;
05320     Row_reference m_i = *m_iter;
05321     ++m_iter;
05322     Row_reference m_ci = *m_iter;
05323     ++m_iter;
05324     const Coefficient& sc_i = sc_expr.coefficient(Variable(id));
05325     const int sign_i = sgn(sc_i);
05326     if (sign_i > 0) {
05327       assign_r(coeff_i, sc_i, ROUND_UP);
05328       // Approximating `-sc_expr'.
05329       if (neg_pinf_count <= 1) {
05330         const N& double_up_approx_minus_i = m_i[n_i+1];
05331         if (!is_plus_infinity(double_up_approx_minus_i)) {
05332           // Let half = double_up_approx_minus_i / 2.
05333           div2exp_assign_r(half, double_up_approx_minus_i, 1, ROUND_UP);
05334           add_mul_assign_r(neg_sum, coeff_i, half, ROUND_UP);
05335         }
05336         else {
05337           ++neg_pinf_count;
05338           neg_pinf_index = id;
05339         }
05340       }
05341     }
05342     else if (sign_i < 0) {
05343       neg_assign_r(minus_sc_i, sc_i, ROUND_NOT_NEEDED);
05344       assign_r(minus_coeff_i, minus_sc_i, ROUND_UP);
05345       // Approximating `-sc_expr'.
05346       if (neg_pinf_count <= 1) {
05347         const N& double_up_approx_i = m_ci[n_i];
05348         if (!is_plus_infinity(double_up_approx_i)) {
05349           // Let half = double_up_approx_i / 2.
05350           div2exp_assign_r(half, double_up_approx_i, 1, ROUND_UP);
05351           add_mul_assign_r(neg_sum, minus_coeff_i, half, ROUND_UP);
05352         }
05353         else {
05354           ++neg_pinf_count;
05355           neg_pinf_index = id;
05356         }
05357       }
05358     }
05359   }
05360 
05361   // Apply the affine upper bound.
05362   generalized_affine_image(var,
05363                            LESS_OR_EQUAL,
05364                            ub_expr,
05365                            denominator);
05366 
05367   // Return immediately if no approximation could be computed.
05368   if (neg_pinf_count > 1) {
05369     return;
05370   }
05371 
05372   // In the following, strong closure will be definitely lost.
05373   reset_strongly_closed();
05374 
05375   // Exploit the lower approximation, if possible.
05376   if (neg_pinf_count <= 1) {
05377     // Compute quotient (if needed).
05378     if (sc_den != 1) {
05379       // Before computing quotients, the denominator should be approximated
05380       // towards zero. Since `sc_den' is known to be positive, this amounts to
05381       // rounding downwards, which is achieved as usual by rounding upwards
05382       // `minus_sc_den' and negating again the result.
05383       DIRTY_TEMP(N, down_sc_den);
05384       assign_r(down_sc_den, minus_sc_den, ROUND_UP);
05385       neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
05386       div_assign_r(neg_sum, neg_sum, down_sc_den, ROUND_UP);
05387     }
05388     // Add the lower bound constraint, if meaningful.
05389     if (neg_pinf_count == 0) {
05390       // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
05391       DIRTY_TEMP(N, double_neg_sum);
05392       mul2exp_assign_r(double_neg_sum, neg_sum, 1, ROUND_IGNORE);
05393       matrix[n_var][n_var+1] = double_neg_sum;
05394       // Deduce constraints of the form `-v +/- u', where `u != v'.
05395       deduce_minus_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, neg_sum);
05396     }
05397     else
05398       // Here `neg_pinf_count == 1'.
05399       if (neg_pinf_index != var_id) {
05400         const Coefficient& npi = sc_expr.coefficient(Variable(neg_pinf_index));
05401         if (npi == sc_den)
05402           // Add the constraint `v - neg_pinf_index >= -neg_sum',
05403           // i.e., `neg_pinf_index - v <= neg_sum'.
05404           if (neg_pinf_index < var_id)
05405             matrix[n_var][2*neg_pinf_index] = neg_sum;
05406           else
05407             matrix[2*neg_pinf_index+1][n_var+1] = neg_sum;
05408         else
05409           if (npi == minus_sc_den) {
05410             // Add the constraint `v + neg_pinf_index >= -neg_sum',
05411             // i.e., `-neg_pinf_index - v <= neg_sum'.
05412             if (neg_pinf_index < var_id)
05413               matrix[n_var][2*neg_pinf_index+1] = neg_sum;
05414             else
05415               matrix[2*neg_pinf_index][n_var+1] = neg_sum;
05416           }
05417       }
05418   }
05419 
05420   assert(OK());
05421 }

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

References Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), 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::Variable::id(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), TEMP_INTEGER, 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 >::bounded_affine_preimage(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage().

05431                                            {
05432   // The denominator cannot be zero.
05433   if (denominator == 0)
05434     throw_generic("generalized_affine_preimage(v, r, e, d)", "d == 0");
05435 
05436   // Dimension-compatibility checks.
05437   // The dimension of `expr' should not be greater than the dimension
05438   // of `*this'.
05439   const dimension_type expr_space_dim = expr.space_dimension();
05440   if (space_dim < expr_space_dim)
05441     throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
05442                                  "e", expr);
05443 
05444   // `var' should be one of the dimensions of the octagon.
05445   const dimension_type var_id = var.id();
05446   if (space_dim < var_id + 1)
05447     throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
05448                                  var.id()+1);
05449 
05450   // The relation symbol cannot be a strict relation symbol.
05451   if (relsym == LESS_THAN || relsym == GREATER_THAN)
05452     throw_generic("generalized_affine_preimage(v, r, e, d)",
05453                   "r is a strict relation symbol and "
05454                   "*this is an Octagonal_Shape");
05455 
05456   if (relsym == EQUAL) {
05457     // The relation symbol is "==":
05458     // this is just an affine preimage computation.
05459     affine_preimage(var, expr, denominator);
05460     return;
05461   }
05462 
05463   // The image of an empty octagon is empty too.
05464   strong_closure_assign();
05465   if (marked_empty())
05466     return;
05467 
05468   // Check whether the preimage of this affine relation can be easily
05469   // computed as the image of its inverse relation.
05470   const Coefficient& expr_v = expr.coefficient(var);
05471   if (expr_v != 0) {
05472     const Relation_Symbol reversed_relsym = (relsym == LESS_OR_EQUAL)
05473       ? GREATER_OR_EQUAL : LESS_OR_EQUAL;
05474     const Linear_Expression inverse
05475       = expr - (expr_v + denominator)*var;
05476     TEMP_INTEGER(inverse_den);
05477     neg_assign(inverse_den, expr_v);
05478     const Relation_Symbol inverse_relsym
05479       = (sgn(denominator) == sgn(inverse_den)) ? relsym : reversed_relsym;
05480     generalized_affine_image(var, inverse_relsym, inverse, inverse_den);
05481     return;
05482   }
05483 
05484   // Here `var_coefficient == 0', so that the preimage cannot
05485   // be easily computed by inverting the affine relation.
05486   // Shrink the Octagonal_Shape by adding the constraint induced
05487   // by the affine relation.
05488   refine(var, relsym, expr, denominator);
05489 
05490   // If the shrunk OS is empty, its preimage is empty too; ...
05491   if (is_empty())
05492     return;
05493   // ...  otherwise, since the relation was not invertible,
05494   // we just forget all constraints on `var'.
05495   forget_all_octagonal_constraints(var_id);
05496   assert(OK());
05497 }

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 5502 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::Octagonal_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), 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().

05504                                                             {
05505   // Dimension-compatibility checks.
05506   // The dimension of `lhs' should not be greater than the dimension
05507   // of `*this'.
05508   dimension_type lhs_space_dim = lhs.space_dimension();
05509   if (space_dim < lhs_space_dim)
05510     throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)",
05511                                  "e1", lhs);
05512 
05513   // The dimension of `rhs' should not be greater than the dimension
05514   // of `*this'.
05515   const dimension_type rhs_space_dim = rhs.space_dimension();
05516   if (space_dim < rhs_space_dim)
05517     throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)",
05518                                  "e2", rhs);
05519 
05520   // Strict relation symbols are not admitted for octagons.
05521   if (relsym == LESS_THAN || relsym == GREATER_THAN)
05522     throw_generic("generalized_affine_preimage(e1, r, e2)",
05523                   "r is a strict relation symbol and "
05524                   "*this is an Octagonal_Shape");
05525 
05526   strong_closure_assign();
05527   // The image of an empty octagon is empty.
05528   if (marked_empty())
05529     return;
05530 
05531   // Number of non-zero coefficients in `lhs': will be set to
05532   // 0, 1, or 2, the latter value meaning any value greater than 1.
05533   dimension_type t_lhs = 0;
05534   // Index of the last non-zero coefficient in `lhs', if any.
05535   dimension_type j_lhs = 0;
05536 
05537   // Compute the number of the non-zero components of `lhs'.
05538   for (dimension_type i = lhs_space_dim; i-- > 0; )
05539     if (lhs.coefficient(Variable(i)) != 0) {
05540       if (t_lhs++ == 1)
05541         break;
05542       else
05543         j_lhs = i;
05544     }
05545 
05546   const Coefficient& b_lhs = lhs.inhomogeneous_term();
05547 
05548   // If all variables have a zero coefficient, then `lhs' is a constant:
05549   // in this case, preimage and image happen to be the same.
05550   if (t_lhs == 0) {
05551     generalized_affine_image(lhs, relsym, rhs);
05552     return;
05553   }
05554 
05555   else if (t_lhs == 1) {
05556     // Here `lhs == a_lhs * v + b_lhs'.
05557     // Independently from the form of `rhs', we can exploit the
05558     // method computing generalized affine preimages for a single variable.
05559     Variable v(j_lhs);
05560     // Compute a sign-corrected relation symbol.
05561     const Coefficient& den = lhs.coefficient(v);
05562     Relation_Symbol new_relsym = relsym;
05563     if (den < 0) {
05564       if (relsym == LESS_OR_EQUAL)
05565         new_relsym = GREATER_OR_EQUAL;
05566       else if (relsym == GREATER_OR_EQUAL)
05567         new_relsym = LESS_OR_EQUAL;
05568     }
05569     Linear_Expression expr = rhs - b_lhs;
05570     generalized_affine_preimage(v, new_relsym, expr, den);
05571   }
05572 
05573   else {
05574     // Here `lhs' is of the general form, having at least two variables.
05575     // Compute the set of variables occurring in `lhs'.
05576     bool lhs_vars_intersects_rhs_vars = false;
05577     std::vector<Variable> lhs_vars;
05578     for (dimension_type i = lhs_space_dim; i-- > 0; )
05579       if (lhs.coefficient(Variable(i)) != 0) {
05580         lhs_vars.push_back(Variable(i));
05581         if (rhs.coefficient(Variable(i)) != 0)
05582           lhs_vars_intersects_rhs_vars = true;
05583       }
05584 
05585     if (!lhs_vars_intersects_rhs_vars) {
05586       // `lhs' and `rhs' variables are disjoint.
05587       // Constrain the left hand side expression so that it is related to
05588       // the right hand side expression as dictated by `relsym'.
05589       // TODO: if the following constraint is NOT an octagonal difference,
05590       // it will be simply ignored. Should we compute approximations for it?
05591       switch (relsym) {
05592       case LESS_OR_EQUAL:
05593         refine_no_check(lhs <= rhs);
05594         break;
05595       case EQUAL:
05596         refine_no_check(lhs == rhs);
05597         break;
05598       case GREATER_OR_EQUAL:
05599         refine_no_check(lhs >= rhs);
05600         break;
05601       default:
05602         // We already dealt with the other cases.
05603         throw std::runtime_error("PPL internal error");
05604       }
05605 
05606       // Any image of an empty octagon is empty.
05607       if (is_empty())
05608         return;
05609       // Existentially quantify all variables in the lhs.
05610       for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
05611         dimension_type lhs_vars_i = lhs_vars[i].id();
05612         forget_all_octagonal_constraints(lhs_vars_i);
05613       }
05614     }
05615     else {
05616       // Some variables in `lhs' also occur in `rhs'.
05617 
05618       // More accurate computation that is worth doing only if
05619       // the following TODO note is accurately dealt with.
05620 
05621       // To ease the computation, we add an additional dimension.
05622       const Variable new_var = Variable(space_dim);
05623       add_space_dimensions_and_embed(1);
05624       // Constrain the new dimension to be equal to `rhs'.
05625       // NOTE: calling affine_image() instead of refine_no_check()
05626       // ensures some approximation is tried even when the constraint
05627       // is not an octagonal difference.
05628       affine_image(new_var, lhs);
05629       // Existentially quantify all variables in the lhs.
05630       // NOTE: enforce strong closure for precision.
05631       strong_closure_assign();
05632       assert(!marked_empty());
05633       for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
05634         dimension_type lhs_vars_i = lhs_vars[i].id();
05635         forget_all_octagonal_constraints(lhs_vars_i);
05636       }
05637       // Constrain the new dimension so that it is related to
05638       // the left hand side as dictated by `relsym'.
05639       // Note: if `rhs == v + b_rhs' or `rhs == -v + b_rhs' or `rhs == b_rhs',
05640       // one of the following constraints will be added, because they
05641       // are octagonal differences.
05642       // Else the following constraints are NOT octagonal differences,
05643       // so the method refine_no_check() will ignore them.
05644       switch (relsym) {
05645       case LESS_OR_EQUAL:
05646         refine_no_check(new_var <= rhs);
05647         break;
05648       case EQUAL:
05649         refine_no_check(new_var == rhs);
05650         break;
05651       case GREATER_OR_EQUAL:
05652         refine_no_check(new_var >= rhs);
05653         break;
05654       default:
05655         // We already dealt with the other cases.
05656         throw std::runtime_error("PPL internal error");
05657       }
05658       // Remove the temporarily added dimension.
05659       remove_higher_space_dimensions(space_dim-1);
05660     }
05661   }
05662   assert(OK());
05663 }

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 5667 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(), 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(), TEMP_INTEGER, Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().

05671                                                          {
05672   // The denominator cannot be zero.
05673   if (denominator == 0)
05674     throw_generic("bounded_affine_preimage(v, lb, ub, d)", "d == 0");
05675 
05676   // `var' should be one of the dimensions of the octagon.
05677   const dimension_type var_id = var.id();
05678   if (space_dim < var_id + 1)
05679     throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
05680                                  var.id()+1);
05681 
05682   // The dimension of `lb_expr' and `ub_expr' should not be
05683   // greater than the dimension of `*this'.
05684   const dimension_type lb_space_dim = lb_expr.space_dimension();
05685   if (space_dim < lb_space_dim)
05686     throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)",
05687                                  "lb", lb_expr);
05688   const dimension_type ub_space_dim = ub_expr.space_dimension();
05689   if (space_dim < ub_space_dim)
05690     throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)",
05691                                  "ub", ub_expr);
05692 
05693   strong_closure_assign();
05694   // The image of an empty octagon is empty too.
05695   if (marked_empty())
05696     return;
05697 
05698   if (ub_expr.coefficient(var) == 0) {
05699     refine(var, LESS_OR_EQUAL, ub_expr, denominator);
05700     generalized_affine_preimage(var, GREATER_OR_EQUAL,
05701                                 lb_expr, denominator);
05702     return;
05703   }
05704   if (lb_expr.coefficient(var) == 0) {
05705     refine(var, GREATER_OR_EQUAL, lb_expr, denominator);
05706     generalized_affine_preimage(var, LESS_OR_EQUAL,
05707                                 ub_expr, denominator);
05708     return;
05709   }
05710 
05711   const Coefficient& expr_v = lb_expr.coefficient(var);
05712   // Here `var' occurs in `lb_expr' and `ub_expr'.
05713   // To ease the computation, we add an additional dimension.
05714   const Variable new_var = Variable(space_dim);
05715   add_space_dimensions_and_embed(1);
05716   const Linear_Expression lb_inverse
05717     = lb_expr - (expr_v + denominator)*var;
05718   TEMP_INTEGER(inverse_den);
05719   neg_assign(inverse_den, expr_v);
05720   affine_image(new_var, lb_inverse, inverse_den);
05721   strong_closure_assign();
05722   assert(!marked_empty());
05723   generalized_affine_preimage(var, LESS_OR_EQUAL,
05724                               ub_expr, denominator);
05725   if (sgn(denominator) == sgn(inverse_den))
05726     refine_no_check(var >= new_var) ;
05727   else
05728     refine_no_check(var <= new_var);
05729   // Remove the temporarily added dimension.
05730   remove_higher_space_dimensions(space_dim-1);
05731 }

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

00569                                                                {
00570   // Dimension-compatibility check.
00571   if (space_dimension() != y.space_dimension())
00572     throw_dimension_incompatible("time_elapse_assign(y)", y);
00573   // See the polyhedra documentation.
00574   C_Polyhedron px(constraints());
00575   C_Polyhedron py(y.constraints());
00576   px.time_elapse_assign(py);
00577   Octagonal_Shape<T> x(px);
00578   swap(x);
00579   assert(OK());
00580 }

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

Assigns to *this its topological closure.

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

00305                                                {
00306   // Nothing to be done.
00307   return;
00308 }

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

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

00552                                                             {
00553   static N stop_points[] = {
00554     N(-2, ROUND_UP),
00555     N(-1, ROUND_UP),
00556     N( 0, ROUND_UP),
00557     N( 1, ROUND_UP),
00558     N( 2, ROUND_UP)
00559   };
00560   CC76_extrapolation_assign(y,
00561                             stop_points,
00562                             stop_points
00563                             + sizeof(stop_points)/sizeof(stop_points[0]),
00564                             tp);
00565 }

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 2698 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::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), 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().

02700                                                             {
02701   // Dimension-compatibility check.
02702   if (space_dim != y.space_dim)
02703     throw_dimension_incompatible("CC76_extrapolation_assign(y)", y);
02704 
02705 #ifndef NDEBUG
02706   {
02707     // We assume that `y' is contained in or equal to `*this'.
02708     const Octagonal_Shape x_copy = *this;
02709     const Octagonal_Shape y_copy = y;
02710     assert(x_copy.contains(y_copy));
02711   }
02712 #endif
02713 
02714   // If both octagons are zero-dimensional,
02715   // since `*this' contains `y', we simply return `*this'.
02716   if (space_dim == 0)
02717     return;
02718 
02719   strong_closure_assign();
02720   // If `*this' is empty, since `*this' contains `y', `y' is empty too.
02721   if (marked_empty())
02722     return;
02723   y.strong_closure_assign();
02724   // If `y' is empty, we return.
02725   if (y.marked_empty())
02726     return;
02727 
02728   // If there are tokens available, work on a temporary copy.
02729   if (tp != 0 && *tp > 0) {
02730     Octagonal_Shape x_tmp(*this);
02731     x_tmp.CC76_extrapolation_assign(y, first, last, 0);
02732     // If the widening was not precise, use one of the available tokens.
02733     if (!contains(x_tmp))
02734       --(*tp);
02735     return;
02736   }
02737 
02738   // Compare each constraint in `y' to the corresponding one in `*this'.
02739   // The constraint in `*this' is kept as is if it is stronger than or
02740   // equal to the constraint in `y'; otherwise, the inhomogeneous term
02741   // of the constraint in `*this' is further compared with elements taken
02742   // from a sorted container (the stop-points, provided by the user), and
02743   // is replaced by the first entry, if any, which is greater than or equal
02744   // to the inhomogeneous term. If no such entry exists, the constraint
02745   // is removed altogether.
02746   typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin();
02747   for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(),
02748          matrix_element_end = matrix.element_end();
02749        i != matrix_element_end;
02750        ++i, ++j) {
02751     const N& y_elem = *j;
02752     N& elem = *i;
02753     if (y_elem < elem) {
02754       Iterator k = std::lower_bound(first, last, elem);
02755       if (k != last) {
02756         if (elem < *k)
02757           assign_r(elem, *k, ROUND_UP);
02758       }
02759       else
02760         assign_r(elem, PLUS_INFINITY, ROUND_NOT_NEEDED);
02761     }
02762   }
02763 
02764   reset_strongly_closed();
02765   assert(OK());
02766 }

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 2898 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::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), 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(), Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_BHMZ05_extrapolation_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::widening_assign().

02899                                                          {
02900   // Dimension-compatibility check.
02901   if (space_dim != y.space_dim)
02902     throw_dimension_incompatible("BHMZ05_widening_assign(y)", y);
02903 
02904 #ifndef NDEBUG
02905   {
02906     // We assume that `y' is contained in or equal to `*this'.
02907     const Octagonal_Shape x_copy = *this;
02908     const Octagonal_Shape y_copy = y;
02909     assert(x_copy.contains(y_copy));
02910   }
02911 #endif
02912 
02913   // Compute the affine dimension of `y'.
02914   const dimension_type y_affine_dim = y.affine_dimension();
02915   // If the affine dimension of `y' is zero, then either `y' is
02916   // zero-dimensional, or it is empty, or it is a singleton.
02917   // In all cases, due to the inclusion hypothesis, the result is `*this'.
02918   if (y_affine_dim == 0)
02919     return;
02920 
02921   // If the affine dimension has changed, due to the inclusion hypothesis,
02922   // the result is `*this'.
02923   const dimension_type x_affine_dim = affine_dimension();
02924   assert(x_affine_dim >= y_affine_dim);
02925   if (x_affine_dim != y_affine_dim)
02926     return;
02927 
02928   // If there are tokens available, work on a temporary copy.
02929   if (tp != 0 && *tp > 0) {
02930     Octagonal_Shape x_tmp(*this);
02931     x_tmp.BHMZ05_widening_assign(y, 0);
02932     // If the widening was not precise, use one of the available tokens.
02933     if (!contains(x_tmp))
02934       --(*tp);
02935     return;
02936   }
02937 
02938   // Here no token is available.
02939   assert(marked_strongly_closed() && y.marked_strongly_closed());
02940   // Minimize `y'.
02941   y.strong_reduction_assign();
02942 
02943   // Extrapolate unstable bounds.
02944   typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin();
02945   for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(),
02946        matrix_element_end = matrix.element_end();
02947        i != matrix_element_end;
02948        ++i, ++j) {
02949     N& elem = *i;
02950       // Note: in the following line the use of `!=' (as opposed to
02951       // the use of `<' that would seem -but is not- equivalent) is
02952       // intentional.
02953     if (*j != elem)
02954       assign_r(elem, PLUS_INFINITY, ROUND_NOT_NEEDED);
02955   }
02956   reset_strongly_closed();
02957   assert(OK());
02958 }

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

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

00545                                                                           {
00546   BHMZ05_widening_assign(y, tp);
00547 }

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

References Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::get_limiting_octagon(), Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_constraint_incompatible(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::UNIVERSE.

02965                                                     {
02966 
02967   // Dimension-compatibility check.
02968   if (space_dim != y.space_dim)
02969     throw_dimension_incompatible("limited_BHMZ05_extrapolation_assign(y, cs)",
02970                                  y);
02971   // `cs' must be dimension-compatible with the two octagons.
02972   const dimension_type cs_space_dim = cs.space_dimension();
02973   if (space_dim < cs_space_dim)
02974     throw_constraint_incompatible("limited_CH78_extrapolation_assign(y, cs)");
02975 
02976   // Strict inequalities not allowed.
02977   if (cs.has_strict_inequalities())
02978     throw_constraint_incompatible("limited_CH78_extrapolation_assign(y, cs)");
02979 
02980   // The limited BHMZ05-extrapolation between two octagons in a
02981   // zero-dimensional space is a octagon in a zero-dimensional
02982   // space, too.
02983   if (space_dim == 0)
02984     return;
02985 
02986 #ifndef NDEBUG
02987   {
02988     // We assume that `y' is contained in or equal to `*this'.
02989     const Octagonal_Shape x_copy = *this;
02990     const Octagonal_Shape y_copy = y;
02991     assert(x_copy.contains(y_copy));
02992   }
02993 #endif
02994 
02995   // If `*this' is empty, since `*this' contains `y', `y' is empty too.
02996   if (marked_empty())
02997     return;
02998   // If `y' is empty, we return.
02999   if (y.marked_empty())
03000     return;
03001 
03002   Octagonal_Shape limiting_octagon(space_dim, UNIVERSE);
03003   get_limiting_octagon(cs, limiting_octagon);
03004   BHMZ05_widening_assign(y, tp);
03005   intersection_assign(limiting_octagon);
03006 }

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

References Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), 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().

03010                                                                   {
03011   // Dimension-compatibility check.
03012   if (space_dim != y.space_dim)
03013     throw_dimension_incompatible("CC76_narrowing_assign(y)", y);
03014 
03015 #ifndef NDEBUG
03016   {
03017     // We assume that `*this' is contained in or equal to `y'.
03018     const Octagonal_Shape x_copy = *this;
03019     const Octagonal_Shape y_copy = y;
03020     assert(y_copy.contains(x_copy));
03021   }
03022 #endif
03023 
03024   // If both octagons are zero-dimensional, since `*this' contains `y',
03025   // we simply return '*this'.
03026   if (space_dim == 0)
03027     return;
03028 
03029   y.strong_closure_assign();
03030   // If `y' is empty, since `y' contains `*this', `*this' is empty too.
03031   if (y.marked_empty())
03032     return;
03033   strong_closure_assign();
03034   // If `*this' is empty, we return.
03035   if (marked_empty())
03036     return;
03037 
03038   // We consider a constraint of `*this', if its value is `plus_infinity',
03039   // we take the value of the corresponding constraint of `y'.
03040   bool is_oct_changed = false;
03041   typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin();
03042   for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(),
03043        matrix_element_end = matrix.element_end();
03044        i != matrix_element_end;
03045        ++i, ++j) {
03046      if (!is_plus_infinity(*i)
03047          && !is_plus_infinity(*j)
03048          && *i != *j) {
03049       *i = *j;
03050       is_oct_changed = true;
03051     }
03052   }
03053 
03054   if (is_oct_changed && marked_strongly_closed())
03055     reset_strongly_closed();
03056   assert(OK());
03057 }

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

References Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::get_limiting_octagon(), Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_constraint_incompatible(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::UNIVERSE.

02853                                                   {
02854 
02855   // Dimension-compatibility check.
02856   if (space_dim != y.space_dim)
02857     throw_dimension_incompatible("limited_CC76_extrapolation_assign(y, cs)",
02858                                  y);
02859   // `cs' must be dimension-compatible with the two octagons.
02860   const dimension_type cs_space_dim = cs.space_dimension();
02861   if (space_dim < cs_space_dim)
02862     throw_constraint_incompatible("limited_CC76_extrapolation_assign(y, cs)");
02863 
02864   // Strict inequalities not allowed.
02865   if (cs.has_strict_inequalities())
02866     throw_constraint_incompatible("limited_CC76_extrapolation_assign(y, cs)");
02867 
02868   // The limited CC76-extrapolation between two octagons in a
02869   // zero-dimensional space is a octagon in a zero-dimensional
02870   // space, too.
02871   if (space_dim == 0)
02872     return;
02873 
02874 #ifndef NDEBUG
02875   {
02876     // We assume that `y' is contained in or equal to `*this'.
02877     const Octagonal_Shape x_copy = *this;
02878     const Octagonal_Shape y_copy = y;
02879     assert(x_copy.contains(y_copy));
02880   }
02881 #endif
02882 
02883   // If `*this' is empty, since `*this' contains `y', `y' is empty too.
02884   if (marked_empty())
02885     return;
02886   // If `y' is empty, we return.
02887   if (y.marked_empty())
02888     return;
02889 
02890   Octagonal_Shape limiting_octagon(space_dim, UNIVERSE);
02891   get_limiting_octagon(cs, limiting_octagon);
02892   CC76_extrapolation_assign(y, tp);
02893   intersection_assign(limiting_octagon);
02894 }

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 2442 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 >::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(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage().

02442                                                                    {
02443   // Adding no dimensions is a no-op.
02444   if (m == 0)
02445     return;
02446 
02447   const dimension_type new_dim = space_dim + m;
02448   const bool was_zero_dim_univ = !marked_empty() && space_dim == 0;
02449 
02450   // To embed an n-dimension space octagon in a (n+m)-dimension space,
02451   // we just add `m' variables in the matrix of constraints.
02452   matrix.grow(new_dim);
02453   space_dim = new_dim;
02454   // If `*this' was the zero-dim space universe octagon,
02455   // then we can set the strongly closure flag.
02456   if (was_zero_dim_univ)
02457     set_strongly_closed();
02458 
02459   assert(OK());
02460 }

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 2464 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::Octagonal_Shape< T >::OK(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed().

02464                                                                      {
02465   // Adding no dimensions is a no-op.
02466   if (m == 0)
02467     return;
02468 
02469   const dimension_type n = matrix.num_rows();
02470 
02471   // To project an n-dimension space OS in a (space_dim+m)-dimension space,
02472   // we just add `m' columns and rows in the matrix of constraints.
02473   add_space_dimensions_and_embed(m);
02474   // We insert 0 where it needs.
02475   // Attention: now num_rows of matrix is update!
02476   for (typename OR_Matrix<N>::row_iterator i = matrix.row_begin() + n,
02477          matrix_row_end =  matrix.row_end(); i != matrix_row_end; i += 2) {
02478     typename OR_Matrix<N>::row_reference_type x_i = *i;
02479     typename OR_Matrix<N>::row_reference_type x_ci = *(i+1);
02480     const dimension_type ind = i.index();
02481     assign_r(x_i[ind+1], 0, ROUND_NOT_NEEDED);
02482     assign_r(x_ci[ind], 0, ROUND_NOT_NEEDED);
02483   }
02484 
02485   if (marked_strongly_closed())
02486     reset_strongly_closed();
02487   assert(OK());
02488 }

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

References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), 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(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim.

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

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

Removes all the specified dimensions.

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

Definition at line 2493 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 >::set_zero_dim_univ(), 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 >::fold_space_dimensions().

02493                                                             {
02494   // The removal of no dimensions from any octagon is a no-op.
02495   // Note that this case also captures the only legal removal of
02496   // dimensions from a octagon in a 0-dim space.
02497   if (to_be_removed.empty()) {
02498     assert(OK());
02499     return;
02500   }
02501 
02502   // Dimension-compatibility check.
02503   const dimension_type min_space_dim = to_be_removed.space_dimension();
02504   if (space_dim < min_space_dim)
02505     throw_dimension_incompatible("remove_space_dimensions(vs)", min_space_dim);
02506 
02507   const dimension_type new_space_dim = space_dim - to_be_removed.size();
02508 
02509   strong_closure_assign();
02510   // When removing _all_ dimensions from an octagon,
02511   // we obtain the zero-dimensional octagon.
02512   if (new_space_dim == 0) {
02513     matrix.shrink(0);
02514     if (!marked_empty())
02515       // We set the zero_dim_univ flag.
02516       set_zero_dim_univ();
02517     space_dim = 0;
02518     assert(OK());
02519     return;
02520   }
02521 
02522   // We consider every variable and we check if it is to be removed.
02523   // If it is to be removed, we pass to the successive one, elsewhere
02524   // we move its elements in the right position.
02525   Variables_Set::const_iterator tbr = to_be_removed.begin();
02526   dimension_type ftr = *tbr;
02527   dimension_type ftr_size = 2*ftr*(ftr+1);
02528   typename OR_Matrix<N>::element_iterator
02529     iter = matrix.element_begin()+ftr_size;
02530 
02531   dimension_type i = ftr + 1;
02532   while (i < space_dim) {
02533     if (to_be_removed.count(i) != 0)
02534       ++i;
02535     else {
02536       typename OR_Matrix<N>::row_iterator
02537         row_iter = matrix.row_begin()+2*i;
02538       typename OR_Matrix<N>::row_reference_type
02539         row_ref = *row_iter;
02540       typename OR_Matrix<N>::row_reference_type
02541         row_ref1 = *(++row_iter);
02542       // If variable(j) is to remove, we pass another variable,
02543       // else we shift its cells to up right.
02544       // Attention: first we shift the cells corrispondent to the first
02545       // row of variable(j), then we shift the cells corrispondent to the
02546       // second row. We recall that every variable is represented
02547       // in the `matrix' by two rows and two rows.
02548       for (dimension_type j = 0; j <= i; ++j)
02549         if (to_be_removed.count(j) == 0) {
02550           assign_or_swap(*(iter++), row_ref[2*j]);
02551           assign_or_swap(*(iter++), row_ref[2*j+1]);
02552         }
02553       for (dimension_type j = 0; j <= i; ++j)
02554         if (to_be_removed.count(j) == 0) {
02555           assign_or_swap(*(iter++), row_ref1[2*j]);
02556           assign_or_swap(*(iter++), row_ref1[2*j+1]);
02557         }
02558       ++i;
02559     }
02560   }
02561   // Update the space dimension.
02562   matrix.shrink(new_space_dim);
02563   space_dim = new_space_dim;
02564   assert(OK());
02565 }

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 520 of file Octagonal_Shape.inlines.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 >::set_zero_dim_univ(), 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 >::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 >::generalized_affine_preimage(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::map_space_dimensions().

00520                                                                    {
00521   // Dimension-compatibility check.
00522   if (new_dimension > space_dim)
00523     throw_dimension_incompatible("remove_higher_space_dimension(nd)",
00524                                  new_dimension);
00525   // The removal of no dimensions from any octagon is a no-op.
00526   // Note that this case also captures the only legal removal of
00527   // dimensions from an octagon in a 0-dim space.
00528   if (new_dimension == space_dim) {
00529     assert(OK());
00530     return;
00531   }
00532 
00533   strong_closure_assign();
00534   matrix.shrink(new_dimension);
00535   // When we remove all dimensions from a non-empty octagon,
00536   // we obtain the zero-dimensional universe octagon.
00537   if (new_dimension == 0 && !marked_empty())
00538     set_zero_dim_univ();
00539   space_dim = new_dimension;
00540   assert(OK());
00541 }

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 class Partial_Function must provide the following methods.
      bool has_empty_codomain() const
returns true if and only if the represented partial function has an empty codomain (i.e., it is always undefined). The has_empty_codomain() method will always be called before the methods below. However, if has_empty_codomain() returns true, none of the functions below will be called.
      dimension_type max_in_codomain() const
returns the maximum value that belongs to the codomain of the partial function.
      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 2570 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::swap().

02570                                                                       {
02571   if (space_dim == 0)
02572     return;
02573 
02574   if (pfunc.has_empty_codomain()) {
02575     // All dimensions vanish: the octagon becomes zero_dimensional.
02576     remove_higher_space_dimensions(0);
02577     return;
02578   }
02579 
02580   const dimension_type new_space_dim = pfunc.max_in_codomain() + 1;
02581   // If we are going to actually reduce the space dimension,
02582   // then shortest-path closure is required to keep precision.
02583   if (new_space_dim < space_dim)
02584     strong_closure_assign();
02585 
02586   // If the octagon is empty, then it is sufficient to adjust
02587   // the space dimension of the octagon.
02588   if (marked_empty()) {
02589     remove_higher_space_dimensions(new_space_dim);
02590     return;
02591   }
02592 
02593   // We create a new matrix with the new space dimension.
02594   OR_Matrix<N> x(new_space_dim);
02595 
02596   typedef typename OR_Matrix<N>::row_iterator Row_Iterator;
02597   typedef typename OR_Matrix<N>::row_reference_type Row_Reference;
02598 
02599   Row_Iterator m_begin = x.row_begin();
02600   Row_Iterator m_end = x.row_end();
02601 
02602   for (Row_Iterator i_iter = matrix.row_begin(), i_end = matrix.row_end();
02603        i_iter != i_end; i_iter += 2) {
02604     dimension_type new_i;
02605     dimension_type i = i_iter.index()/2;
02606     // We copy and place in the position into `x' the only cells of
02607     // the `matrix' that refer to both mapped variables,
02608     // the variable `i' and `j'.
02609     if (pfunc.maps(i, new_i)) {
02610       Row_Reference r_i = *i_iter;
02611       Row_Reference r_ii = *(i_iter + 1);
02612       dimension_type double_new_i = 2*new_i;
02613       Row_Iterator x_iter = m_begin + double_new_i;
02614       Row_Reference x_i = *x_iter;
02615       Row_Reference x_ii = *(x_iter + 1);
02616       for (dimension_type j = 0; j <= i; ++j) {
02617         dimension_type new_j;
02618         // If also the second variable is mapped, we work.
02619         if (pfunc.maps(j, new_j)) {
02620           dimension_type dj = 2*j;
02621           dimension_type double_new_j = 2*new_j;
02622           // Mapped the constraints, exchanging the indexes.
02623           // Attention: our matrix is pseudo-triangular.
02624           // If new_j > new_i, we must consider, as rows, the rows of
02625           // the variable new_j, and not of new_i ones.
02626           if (new_i >= new_j) {
02627             assign_or_swap(x_i[double_new_j], r_i[dj]);
02628             assign_or_swap(x_ii[double_new_j], r_ii[dj]);
02629             assign_or_swap(x_ii[double_new_j+1], r_ii[dj + 1]);
02630             assign_or_swap(x_i[double_new_j+1], r_i[dj + 1]);
02631           }
02632           else {
02633             Row_Iterator xj_iter = m_begin + double_new_j;
02634             Row_Reference x_j = *xj_iter;
02635             Row_Reference x_jj = *(xj_iter + 1);
02636             assign_or_swap(x_jj[double_new_i+1], r_i[dj]);
02637             assign_or_swap(x_jj[double_new_i], r_ii[dj]);
02638             assign_or_swap(x_j[double_new_i+1], r_i[dj+1]);
02639             assign_or_swap(x_j[double_new_i], r_ii[dj+1]);
02640           }
02641 
02642         }
02643       }
02644     }
02645   }
02646 
02647   std::swap(matrix, x);
02648   space_dim = new_space_dim;
02649   assert(OK());
02650 }

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 5841 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::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 >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().

05841                                                                          {
05842   // `var' should be one of the dimensions of the vector space.
05843   const dimension_type var_id = var.id();
05844   if (var_id+1 > space_dim)
05845     throw_dimension_incompatible("expand_space_dimension(v, m)", var_id+1);
05846 
05847   // The space dimension of the resulting octagon should not
05848   // overflow the maximum allowed space dimension.
05849   if (m > max_space_dimension() - space_dim)
05850     throw_generic("expand_dimension(v, m)",
05851                   "adding m new space dimensions exceeds "
05852                   "the maximum allowed space dimension");
05853 
05854   // Nothing to do, if no dimensions must be added.
05855   if (m == 0)
05856     return;
05857 
05858   // Keep track of the dimension before adding the new ones.
05859   const dimension_type old_num_rows = matrix.num_rows();
05860 
05861   // Add the required new dimensions.
05862   add_space_dimensions_and_embed(m);
05863 
05864   // For each constraints involving variable `var', we add a
05865   // similar constraint with the new variable substituted for
05866   // variable `var'.
05867   typedef typename OR_Matrix<N>::row_iterator Row_Iterator;
05868   typedef typename OR_Matrix<N>::row_reference_type Row_Reference;
05869   typedef typename OR_Matrix<N>::const_row_iterator Row_iterator;
05870   typedef typename OR_Matrix<N>::const_row_reference_type Row_reference;
05871 
05872   const Row_Iterator m_begin = matrix.row_begin();
05873   const Row_Iterator m_end = matrix.row_end();
05874   const dimension_type n_var = 2*var_id;
05875   Row_iterator v_iter = m_begin + n_var;
05876   Row_reference m_v = *v_iter;
05877   Row_reference m_cv = *(v_iter+1);
05878 
05879   for (Row_Iterator i_iter = m_begin + old_num_rows; i_iter != m_end;
05880        i_iter += 2) {
05881     Row_Reference m_i = *i_iter;
05882     Row_Reference m_ci = *(i_iter+1);
05883     const dimension_type i = i_iter.index();
05884     const dimension_type ci = i+1;
05885     m_i[ci] = m_v[n_var+1];
05886     m_ci[i] = m_cv[n_var];
05887     for (dimension_type j = 0; j < n_var; ++j) {
05888       m_i[j] = m_v[j];
05889       m_ci[j] = m_cv[j];
05890     }
05891     for (dimension_type j = n_var+2; j < old_num_rows; ++j) {
05892       Row_Iterator j_iter = m_begin + j;
05893       Row_Reference m_j = *j_iter;
05894       Row_Reference m_cj = (j%2) ? *(j_iter-1) : *(j_iter+1);
05895       m_i[j] = m_cj[n_var+1];
05896       m_ci[j] = m_cj[n_var];
05897     }
05898   }
05899   // In general, adding a constraint does not preserve the strong closure
05900   // of the octagon.
05901   if (marked_strongly_closed())
05902     reset_strongly_closed();
05903   assert(OK());
05904 }

template<typename T>
void Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions ( const Variables_Set &  to_be_folded,
Variable  var 
) [inline]

Folds the space dimensions in to_be_folded into var.

Parameters:
to_be_folded The set of Variable objects corresponding to the space dimensions to be folded;
var The variable corresponding to the space dimension that is the destination of the folding operation.
Exceptions:
std::invalid_argument Thrown if *this is dimension-incompatible with var or with one of the Variable objects contained in to_be_folded. Also thrown if var is contained in to_be_folded.
If *this has space dimension $n$, with $n > 0$, var has space dimension $k \leq n$, to_be_folded is a set of variables whose maximum space dimension is also less than or equal to $n$, and var is not a member of to_be_folded, then the space dimensions corresponding to variables in to_be_folded are folded into the $k$-th space dimension.

Definition at line 5908 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::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, 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().

05909                                                         {
05910   // `var' should be one of the dimensions of the octagon.
05911   if (var.space_dimension() > space_dim)
05912     throw_dimension_incompatible("fold_space_dimensions(tbf, v)", "v", var);
05913 
05914   // The folding of no dimensions is a no-op.
05915   if (to_be_folded.empty())
05916     return;
05917 
05918   // All variables in `to_be_folded' should be dimensions of the octagon.
05919   if (to_be_folded.space_dimension() > space_dim)
05920     throw_dimension_incompatible("fold_space_dimensions(tbf, ...)",
05921                                  to_be_folded.space_dimension());
05922 
05923   // Moreover, `var.id()' should not occur in `to_be_folded'.
05924   if (to_be_folded.find(var.id()) != to_be_folded.end())
05925     throw_generic("fold_space_dimensions(tbf, v)",
05926                   "v should not occur in tbf");
05927 
05928   // Recompute the elements of the row and the column corresponding
05929   // to variable `var' by taking the join of their value with the
05930   // value of the corresponding elements in the row and column of the
05931   // variable `to_be_folded'.
05932   typedef typename OR_Matrix<N>::row_iterator Row_Iterator;
05933   typedef typename OR_Matrix<N>::row_reference_type Row_Reference;
05934 
05935   const Row_Iterator m_begin = matrix.row_begin();
05936   const Row_Iterator m_end = matrix.row_end();
05937 
05938   strong_closure_assign();
05939   const dimension_type n_rows = matrix.num_rows();
05940   const dimension_type n_var = 2*var.id();
05941   Row_Iterator v_iter = m_begin + n_var;
05942   Row_Reference m_v = *v_iter;
05943   Row_Reference m_cv = *(v_iter+1);
05944   for (Variables_Set::const_iterator i = to_be_folded.begin(),
05945          tbf_end = to_be_folded.end(); i != tbf_end; ++i) {
05946     const dimension_type tbf_id = *i;
05947     const dimension_type tbf_var = 2*tbf_id;
05948     Row_Iterator tbf_iter = m_begin + tbf_var;
05949     Row_Reference m_tbf = *tbf_iter;
05950     Row_Reference m_ctbf = *(tbf_iter+1);
05951     max_assign(m_v[n_var+1], m_tbf[tbf_var+1]);
05952     max_assign(m_cv[n_var], m_ctbf[tbf_var]);
05953 
05954     const dimension_type min_id = std::min(n_var, tbf_var);
05955     const dimension_type max_id = std::max(n_var, tbf_var);
05956 
05957     for (dimension_type j = 0; j < min_id; ++j) {
05958       const dimension_type cj = coherent_index(j);
05959       max_assign(m_v[j], m_tbf[j]);
05960       max_assign(m_cv[j], m_ctbf[j]);
05961       max_assign(m_cv[cj], m_ctbf[cj]);
05962       max_assign(m_v[cj], m_tbf[cj]);
05963     }
05964     for (dimension_type j = min_id+2; j < max_id; ++j) {
05965       const dimension_type cj = coherent_index(j);
05966       Row_Iterator j_iter = m_begin + j;
05967       Row_Reference m_j = *j_iter;
05968       Row_Reference m_cj = (j%2) ? *(j_iter-1) : *(j_iter+1);
05969       if (n_var == min_id) {
05970         max_assign(m_cj[n_var+1], m_tbf[j]);
05971         max_assign(m_cj[n_var], m_ctbf[j]);
05972         max_assign(m_j[n_var], m_ctbf[cj]);
05973         max_assign(m_j[n_var+1], m_tbf[cj]);
05974       }
05975       else {
05976         max_assign(m_v[j], m_cj[tbf_var+1]);
05977         max_assign(m_cv[j], m_cj[tbf_var]);
05978         max_assign(m_cv[cj], m_j[tbf_var]);
05979         max_assign(m_v[cj], m_j[tbf_var+1]);
05980       }
05981     }
05982     for (dimension_type j = max_id+2; j < n_rows; ++j) {
05983       Row_Iterator j_iter = m_begin + j;
05984       Row_Reference m_j = *j_iter;
05985       Row_Reference m_cj = (j%2) ? *(j_iter-1) : *(j_iter+1);
05986       max_assign(m_cj[n_var+1], m_cj[tbf_var+1]);
05987       max_assign(m_cj[n_var], m_cj[tbf_var]);
05988       max_assign(m_j[n_var], m_j[tbf_var]);
05989       max_assign(m_j[n_var+1], m_j[tbf_var+1]);
05990     }
05991   }
05992   remove_space_dimensions(to_be_folded);
05993 }

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>
void Parma_Polyhedra_Library::Octagonal_Shape< T >::ascii_dump ( std::ostream &  s  )  const [inline]

Writes to s an ASCII representation of *this.

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

References Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::ascii_dump(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::status.

06169                                                   {
06170   s << "space_dim "
06171     << space_dim
06172     << "\n";
06173   status.ascii_dump(s);
06174   s << "\n";
06175   matrix.ascii_dump(s);
06176 }

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

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

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

References Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::ascii_load(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::status.

06182                                             {
06183   std::string str;
06184 
06185   if (!(s >> str) || str != "space_dim")
06186     return false;
06187 
06188   if (!(s >> space_dim))
06189     return false;
06190 
06191   if (!status.ascii_load(s))
06192     return false;
06193 
06194   if (!matrix.ascii_load(s))
06195     return false;
06196 
06197   assert(OK());
06198   return true;
06199 }

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

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

00794                                                 {
00795   return sizeof(*this) + external_memory_in_bytes();
00796 }

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

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

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

06203                                                    {
06204   return matrix.external_memory_in_bytes();
06205 }

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

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

00800                                     {
00801   return space_dimension() & 0x7fffffff;
00802 }

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

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 66 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 >::compute_leaders(), Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_successors(), 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 >::euclidean_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), 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_higher_space_dimensions(), 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_reduction_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign().

00066                                        {
00067   return status.test_empty();
00068 }

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 60 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 >::compute_leaders(), Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_successors(), 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 >::incremental_strong_closure_assign(), 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 >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty().

00060                                                  {
00061   return status.test_strongly_closed();
00062 }

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

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 >::reset_strongly_closed (  )  [inline, private]

Marks *this as possibly not strongly closed.

Definition at line 90 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 >::expand_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), 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(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign().

00090                                           {
00091   status.reset_strongly_closed();
00092 }

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

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

00358                                                       {
00359   assert(i < matrix.num_rows() && j < matrix.num_rows());
00360   return (j < matrix.row_size(i))
00361     ? matrix[i][j]
00362     : matrix[coherent_index(j)][coherent_index(i)];
00363 }

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

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

00348                                                             {
00349   assert(i < matrix.num_rows() && j < matrix.num_rows());
00350   return (j < matrix.row_size(i))
00351     ? matrix[i][j]
00352     : matrix[coherent_index(j)][coherent_index(i)];
00353 }

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 478 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(), 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, Parma_Polyhedra_Library::Constraint::space_dimension(), and TEMP_INTEGER.

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

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

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

00489                                                         {
00490   assert(!marked_empty());
00491   assert(cg.space_dimension() <= space_dimension());
00492 
00493   if (cg.is_proper_congruence()) {
00494     if (cg.is_inconsistent())
00495       set_empty();
00496     // Other proper congruences are just ignored.
00497     return;
00498   }
00499 
00500   assert(cg.is_equality());
00501   Constraint c(cg);
00502   refine_no_check(c);
00503 }

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

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

References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::OR_Matrix< T >::row_size(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim.

00397                                                                   {
00398 #ifndef NDEBUG
00399   // Private method: the caller has to ensure the following.
00400   assert(i < 2*space_dim && j < 2*space_dim && i != j);
00401   typename OR_Matrix<N>::row_iterator m_i = matrix.row_begin() + i;
00402   assert(j < m_i.row_size());
00403   assert(den != 0);
00404 #endif
00405   DIRTY_TEMP(N, k);
00406   div_round_up(k, num, den);
00407   add_octagonal_constraint(i, j, k);
00408 }

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 3388 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(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and TEMP_INTEGER.

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

03391                                                                           {
03392   assert(denominator != 0);
03393   const dimension_type expr_space_dim = expr.space_dimension();
03394   assert(space_dim >= expr_space_dim);
03395   const dimension_type var_id = var.id();
03396   assert(var_id <= space_dim);
03397   assert(expr.coefficient(var) == 0);
03398   assert(relsym != LESS_THAN && relsym != GREATER_THAN);
03399 
03400   const Coefficient& b = expr.inhomogeneous_term();
03401   // Number of non-zero coefficients in `expr': will be set to
03402   // 0, 1, or 2, the latter value meaning any value greater than 1.
03403   dimension_type t = 0;
03404 
03405   // Variable index of the last non-zero coefficient in `expr', if any.
03406   dimension_type w_id = 0;
03407 
03408   // Get information about the number of non-zero coefficients in `expr'.
03409   for (dimension_type i = expr_space_dim; i-- > 0; )
03410     if (expr.coefficient(Variable(i)) != 0) {
03411       if (t++ == 1)
03412         break;
03413       else
03414         w_id = i;
03415     }
03416 
03417   // Now we know the form of `expr':
03418   // - If t == 0, then expr == b, with `b' a constant;
03419   // - If t == 1, then expr == a*j + b, where `j != v';
03420   // - If t == 2, the `expr' is of the general form.
03421   typedef typename OR_Matrix<N>::row_iterator Row_Iterator;
03422   typedef typename OR_Matrix<N>::row_reference_type Row_Reference;
03423   typedef typename OR_Matrix<N>::const_row_iterator Row_iterator;
03424   typedef typename OR_Matrix<N>::const_row_reference_type Row_reference;
03425 
03426   const Row_Iterator m_begin = matrix.row_begin();
03427   const dimension_type n_var = 2*var_id;
03428   TEMP_INTEGER(minus_den);
03429   neg_assign(minus_den, denominator);
03430 
03431   // Since we are only able to record octagonal differences, we can
03432   // precisely deal with the case of a single variable only if its
03433   // coefficient (taking into account the denominator) is 1.
03434   // If this is not the case, we fall back to the general case
03435   // so as to over-approximate the constraint.
03436   if (t == 1 && expr.coefficient(Variable(w_id)) != denominator
03437       && expr.coefficient(Variable(w_id)) != minus_den)
03438     t = 2;
03439 
03440   if (t == 0) {
03441     // Case 1: expr == b.
03442     TEMP_INTEGER(two_b);
03443     two_b = 2*b;
03444     switch (relsym) {
03445     case EQUAL:
03446       // Add the constraint `var == b/denominator'.
03447       add_octagonal_constraint(n_var+1, n_var, two_b, denominator);
03448       add_octagonal_constraint(n_var, n_var+1, two_b, minus_den);
03449       break;
03450     case LESS_OR_EQUAL:
03451       // Add the constraint `var <= b/denominator'.
03452       add_octagonal_constraint(n_var+1, n_var, two_b, denominator);
03453       break;
03454     case GREATER_OR_EQUAL:
03455       // Add the constraint `var >= b/denominator',
03456       // i.e., `-var <= -b/denominator',
03457       add_octagonal_constraint(n_var, n_var+1, two_b, minus_den);
03458       break;
03459     default:
03460       // We already dealt with the other cases.
03461       throw std::runtime_error("PPL internal error");
03462     }
03463   }
03464   else if (t == 1) {
03465     // Value of the one and only non-zero coefficient in `expr'.
03466     const Coefficient& w_coeff = expr.coefficient(Variable(w_id));
03467     const dimension_type n_w = 2*w_id;
03468     switch (relsym) {
03469     case EQUAL:
03470       if (w_coeff == denominator)
03471         // Add the new constraint `var - w = b/denominator'.
03472         if (var_id < w_id) {
03473           add_octagonal_constraint(n_w, n_var, b, denominator);
03474           add_octagonal_constraint(n_w+1, n_var+1, b, minus_den);
03475         }
03476         else {
03477           add_octagonal_constraint(n_var+1, n_w+1, b, denominator);
03478           add_octagonal_constraint(n_var, n_w, b, minus_den);
03479         }
03480       else
03481         // Add the new constraint `var + w = b/denominator'.
03482         if (var_id < w_id) {
03483           add_octagonal_constraint(n_w+1, n_var, b, denominator);
03484           add_octagonal_constraint(n_w, n_var+1, b, minus_den);
03485         }
03486         else {
03487           add_octagonal_constraint(n_var+1, n_w, b, denominator);
03488           add_octagonal_constraint(n_var, n_w+1, b, minus_den);
03489         }
03490       break;
03491     case LESS_OR_EQUAL:
03492       {
03493         DIRTY_TEMP(N, d);
03494         div_round_up(d, b, denominator);
03495         // Note that: `w_id != v', so that `expr' is of the form
03496         // w_coeff * w + b, with `w_id != v'.
03497         if (w_coeff == denominator) {
03498           // Add the new constraints `v - w <= b/denominator'.
03499           if (var_id < w_id)
03500             add_octagonal_constraint(n_w, n_var, d);
03501           else
03502             add_octagonal_constraint(n_var+1, n_w+1, d);
03503         }
03504         else if (w_coeff == minus_den) {
03505           // Add the new constraints `v + w <= b/denominator'.
03506           if (var_id < w_id)
03507             add_octagonal_constraint(n_w+1, n_var, d);
03508           else
03509             add_octagonal_constraint(n_var+1, n_w, d);
03510         }
03511         break;
03512       }
03513 
03514     case GREATER_OR_EQUAL:
03515       {
03516         DIRTY_TEMP(N, d);
03517         div_round_up(d, b, minus_den);
03518         // Note that: `w_id != v', so that `expr' is of the form
03519         // w_coeff * w + b, with `w_id != v'.
03520         if (w_coeff == denominator) {
03521           // Add the new constraint `v - w >= b/denominator',
03522           // i.e.,  `-v + w <= -b/denominator'.
03523           if (var_id < w_id)
03524             add_octagonal_constraint(n_w+1, n_var+1, d);
03525           else
03526             add_octagonal_constraint(n_var, n_w, d);
03527         }
03528         else if (w_coeff == minus_den) {
03529           // Add the new constraints `v + w >= b/denominator',
03530           // i.e.,  `-v - w <= -b/denominator'.
03531           if (var_id < w_id)
03532             add_octagonal_constraint(n_w, n_var+1, d);
03533           else
03534             add_octagonal_constraint(n_var, n_w+1, d);
03535         }
03536         break;
03537       }
03538 
03539     default:
03540       // We already dealt with the other cases.
03541       throw std::runtime_error("PPL internal error");
03542     }
03543   }
03544   else {
03545     // Here t == 2, so that
03546     // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2.
03547     const bool is_sc = (denominator > 0);
03548     TEMP_INTEGER(minus_b);
03549     neg_assign(minus_b, b);
03550     const Coefficient& sc_b = is_sc ? b : minus_b;
03551     const Coefficient& minus_sc_b = is_sc ? minus_b : b;
03552     const Coefficient& sc_den = is_sc ? denominator : minus_den;
03553     const Coefficient& minus_sc_den = is_sc ? minus_den : denominator;
03554     // NOTE: here, for optimization purposes, `minus_expr' is only assigned
03555     // when `denominator' is negative. Do not use it unless you are sure
03556     // it has been correctly assigned.
03557     Linear_Expression minus_expr;
03558     if (!is_sc)
03559       minus_expr = -expr;
03560     const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
03561 
03562     DIRTY_TEMP(N, sum);
03563     // Index of variable that is unbounded in `this'.
03564     PPL_UNINITIALIZED(dimension_type, pinf_index);
03565     // Number of unbounded variables found.
03566     dimension_type pinf_count = 0;
03567 
03568     switch (relsym) {
03569     case EQUAL:
03570       {
03571         DIRTY_TEMP(N, neg_sum);
03572         // Index of variable that is unbounded in `this'.
03573         PPL_UNINITIALIZED(dimension_type, neg_pinf_index);
03574         // Number of unbounded variables found.
03575         dimension_type neg_pinf_count = 0;
03576 
03577         // Approximate the inhomogeneous term.
03578         assign_r(sum, sc_b, ROUND_UP);
03579         assign_r(neg_sum, minus_sc_b, ROUND_UP);
03580 
03581         // Approximate the homogeneous part of `sc_expr'.
03582         DIRTY_TEMP(N, coeff_i);
03583         DIRTY_TEMP(N, half);
03584         TEMP_INTEGER(minus_sc_i);
03585         DIRTY_TEMP(N, minus_coeff_i);
03586         // Note: indices above `w' can be disregarded, as they all have
03587         // a zero coefficient in `sc_expr'.
03588         for (Row_iterator m_iter = m_begin, m_iter_end = m_iter + (2*w_id) + 2;
03589              m_iter != m_iter_end; ) {
03590           const dimension_type n_i = m_iter.index();
03591           const dimension_type id = n_i/2;
03592           Row_reference m_i = *m_iter;
03593           ++m_iter;
03594           Row_reference m_ci = *m_iter;
03595           ++m_iter;
03596           const Coefficient& sc_i = sc_expr.coefficient(Variable(id));
03597           const int sign_i = sgn(sc_i);
03598           if (sign_i > 0) {
03599             assign_r(coeff_i, sc_i, ROUND_UP);
03600             // Approximating `sc_expr'.
03601             if (pinf_count <= 1) {
03602               const N& double_approx_i = m_ci[n_i];
03603               if (!is_plus_infinity(double_approx_i)) {
03604                 // Let half = double_approx_i / 2.
03605                 div2exp_assign_r(half, double_approx_i, 1, ROUND_UP);
03606                 add_mul_assign_r(sum, coeff_i, half, ROUND_UP);
03607               }
03608               else {
03609                 ++pinf_count;
03610                 pinf_index = id;
03611               }
03612             }
03613             // Approximating `-sc_expr'.
03614             if (neg_pinf_count <= 1) {
03615               const N& double_approx_minus_i = m_i[n_i+1];
03616               if (!is_plus_infinity(double_approx_minus_i)) {
03617                 // Let half = double_approx_minus_i / 2.
03618                 div2exp_assign_r(half, double_approx_minus_i, 1, ROUND_UP);
03619                 add_mul_assign_r(neg_sum, coeff_i, half, ROUND_UP);
03620               }
03621               else {
03622                 ++neg_pinf_count;
03623                 neg_pinf_index = id;
03624               }
03625             }
03626           }
03627           else if (sign_i < 0) {
03628             neg_assign_r(minus_sc_i, sc_i, ROUND_NOT_NEEDED);
03629             assign_r(minus_coeff_i, minus_sc_i, ROUND_UP);
03630             // Approximating `sc_expr'.
03631             if (pinf_count <= 1) {
03632               const N& double_approx_minus_i = m_i[n_i+1];
03633               if (!is_plus_infinity(double_approx_minus_i)) {
03634                 // Let half = double_approx_minus_i / 2.
03635                 div2exp_assign_r(half, double_approx_minus_i, 1, ROUND_UP);
03636                 add_mul_assign_r(sum, minus_coeff_i, half, ROUND_UP);
03637               }
03638               else {
03639                 ++pinf_count;
03640                 pinf_index = id;
03641               }
03642             }
03643             // Approximating `-sc_expr'.
03644             if (neg_pinf_count <= 1) {
03645               const N& double_approx_i = m_ci[n_i];
03646               if (!is_plus_infinity(double_approx_i)) {
03647                 // Let half = double_approx_i / 2.
03648                 div2exp_assign_r(half, double_approx_i, 1, ROUND_UP);
03649                 add_mul_assign_r(neg_sum, minus_coeff_i, half, ROUND_UP);
03650               }
03651               else {
03652                 ++neg_pinf_count;
03653                 neg_pinf_index = id;
03654               }
03655             }
03656           }
03657         }
03658         // Return immediately if no approximation could be computed.
03659         if (pinf_count > 1 && neg_pinf_count > 1) {
03660           assert(OK());
03661           return;
03662         }
03663 
03664         // In the following, strong closure will be definitely lost.
03665         reset_strongly_closed();
03666 
03667         // Exploit the upper approximation, if possible.
03668         if (pinf_count <= 1) {
03669           // Compute quotient (if needed).
03670           if (sc_den != 1) {
03671             // Before computing quotients, the denominator should be
03672             // approximated towards zero. Since `sc_den' is known to be
03673             // positive, this amounts to rounding downwards, which is
03674             // achieved as usual by rounding upwards `minus_sc_den'
03675             // and negating again the result.
03676             DIRTY_TEMP(N, down_sc_den);
03677             assign_r(down_sc_den, minus_sc_den, ROUND_UP);
03678             neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
03679             div_assign_r(sum, sum, down_sc_den, ROUND_UP);
03680           }
03681           // Add the upper bound constraint, if meaningful.
03682           if (pinf_count == 0) {
03683             // Add the constraint `v <= sum'.
03684             DIRTY_TEMP(N, double_sum);
03685             mul2exp_assign_r(double_sum, sum, 1, ROUND_IGNORE);
03686             matrix[n_var+1][n_var] = double_sum;
03687             // Deduce constraints of the form `v +/- u', where `u != v'.
03688             deduce_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, sum);
03689           }
03690           else
03691             // Here `pinf_count == 1'.
03692             if (pinf_index != var_id) {
03693               const Coefficient& ppi =
03694                 sc_expr.coefficient(Variable(pinf_index));
03695               if (ppi == sc_den)
03696                 // Add the constraint `v - pinf_index <= sum'.
03697                 if (var_id < pinf_index)
03698                   matrix[2*pinf_index][n_var] = sum;
03699                 else
03700                   matrix[n_var+1][2*pinf_index+1] = sum;
03701               else
03702                 if (ppi == minus_sc_den) {
03703                   // Add the constraint `v + pinf_index <= sum'.
03704                   if (var_id < pinf_index)
03705                     matrix[2*pinf_index+1][n_var] = sum;
03706                   else
03707                     matrix[n_var+1][2*pinf_index] = sum;
03708                 }
03709             }
03710         }
03711 
03712         // Exploit the lower approximation, if possible.
03713         if (neg_pinf_count <= 1) {
03714           // Compute quotient (if needed).
03715           if (sc_den != 1) {
03716             // Before computing quotients, the denominator should be
03717             // approximated towards zero. Since `sc_den' is known to be
03718             // positive, this amounts to rounding downwards, which is
03719             // achieved as usual by rounding upwards `minus_sc_den'
03720             // and negating again the result.
03721             DIRTY_TEMP(N, down_sc_den);
03722             assign_r(down_sc_den, minus_sc_den, ROUND_UP);
03723             neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
03724             div_assign_r(neg_sum, neg_sum, down_sc_den, ROUND_UP);
03725           }
03726           // Add the lower bound constraint, if meaningful.
03727           if (neg_pinf_count == 0) {
03728             // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
03729             DIRTY_TEMP(N, double_neg_sum);
03730             mul2exp_assign_r(double_neg_sum, neg_sum, 1, ROUND_IGNORE);
03731             matrix[n_var][n_var+1] = double_neg_sum;
03732             // Deduce constraints of the form `-v +/- u', where `u != v'.
03733             deduce_minus_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, neg_sum);
03734           }
03735           else
03736             // Here `neg_pinf_count == 1'.
03737             if (neg_pinf_index != var_id) {
03738               const Coefficient& npi =
03739                 sc_expr.coefficient(Variable(neg_pinf_index));
03740               if (npi == sc_den)
03741                 // Add the constraint `v - neg_pinf_index >= -neg_sum',
03742                 // i.e., `neg_pinf_index - v <= neg_sum'.
03743                 if (neg_pinf_index < var_id)
03744                   matrix[n_var][2*neg_pinf_index] = neg_sum;
03745                 else
03746                   matrix[2*neg_pinf_index+1][n_var+1] = neg_sum;
03747               else
03748                 if (npi == minus_sc_den) {
03749                   // Add the constraint `v + neg_pinf_index >= -neg_sum',
03750                   // i.e., `-neg_pinf_index - v <= neg_sum'.
03751                   if (neg_pinf_index < var_id)
03752                     matrix[n_var][2*neg_pinf_index+1] = neg_sum;
03753                   else
03754                     matrix[2*neg_pinf_index][n_var+1] = neg_sum;
03755                 }
03756             }
03757         }
03758         break;
03759       }
03760 
03761     case LESS_OR_EQUAL:
03762       {
03763         // Compute an upper approximation for `expr' into `sum',
03764         // taking into account the sign of `denominator'.
03765 
03766         // Approximate the inhomogeneous term.
03767         assign_r(sum, sc_b, ROUND_UP);
03768 
03769         // Approximate the homogeneous part of `sc_expr'.
03770         DIRTY_TEMP(N, coeff_i);
03771         DIRTY_TEMP(N, approx_i);
03772         TEMP_INTEGER(minus_sc_i);
03773         // Note: indices above `w_id' can be disregarded, as they all have
03774         // a zero coefficient in `expr'.
03775         for (Row_Iterator m_iter = m_begin, m_end = m_iter + (2*w_id) + 2;
03776              m_iter != m_end; ) {
03777           const dimension_type n_i = m_iter.index();
03778           const dimension_type id = n_i/2;
03779           Row_Reference m_i = *m_iter;
03780           ++m_iter;
03781           Row_Reference m_ci = *m_iter;
03782           ++m_iter;
03783           const Coefficient& sc_i = sc_expr.coefficient(Variable(id));
03784           const int sign_i = sgn(sc_i);
03785           if (sign_i == 0)
03786             continue;
03787           // Choose carefully: we are approximating `sc_expr'.
03788           const N& double_approx_i = (sign_i > 0) ? m_ci[n_i] : m_i[n_i+1];
03789           if (is_plus_infinity(double_approx_i)) {
03790             if (++pinf_count > 1)
03791               break;
03792             pinf_index = id;
03793             continue;
03794           }
03795           if (sign_i > 0)
03796             assign_r(coeff_i, sc_i, ROUND_UP);
03797           else {
03798             neg_assign(minus_sc_i, sc_i);
03799             assign_r(coeff_i, minus_sc_i, ROUND_UP);
03800           }
03801           div2exp_assign_r(approx_i, double_approx_i, 1, ROUND_UP);
03802           add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
03803         }
03804         // Divide by the (sign corrected) denominator (if needed).
03805         if (sc_den != 1) {
03806           // Before computing the quotient, the denominator should be
03807           // approximated towards zero. Since `sc_den' is known to be
03808           // positive, this amounts to rounding downwards, which is achieved
03809           // by rounding upwards `minus_sc-den' and negating again the result.
03810           DIRTY_TEMP(N, down_sc_den);
03811           assign_r(down_sc_den, minus_sc_den, ROUND_UP);
03812           neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
03813           div_assign_r(sum, sum, down_sc_den, ROUND_UP);
03814         }
03815 
03816         if (pinf_count == 0) {
03817           // Add the constraint `v <= sum'.
03818           DIRTY_TEMP(N, double_sum);
03819           mul2exp_assign_r(double_sum, sum, 1, ROUND_IGNORE);
03820           add_octagonal_constraint(n_var+1, n_var, double_sum);
03821           // Deduce constraints of the form `v +/- u', where `u != v'.
03822           deduce_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, sum);
03823         }
03824         else if (pinf_count == 1) {
03825           dimension_type pinf_ind = 2*pinf_index;
03826           if (expr.coefficient(Variable(pinf_index)) == denominator ) {
03827             // Add the constraint `v - pinf_index <= sum'.
03828             if (var_id < pinf_index)
03829               add_octagonal_constraint(pinf_ind, n_var, sum);
03830             else
03831               add_octagonal_constraint(n_var+1, pinf_ind+1, sum);
03832           }
03833           else {
03834             if (expr.coefficient(Variable(pinf_index)) == minus_den) {
03835               // Add the constraint `v + pinf_index <= sum'.
03836               if (var_id < pinf_index)
03837                 add_octagonal_constraint(pinf_ind+1, n_var, sum);
03838               else
03839                 add_octagonal_constraint(n_var+1, pinf_ind, sum);
03840             }
03841           }
03842         }
03843         break;
03844       }
03845 
03846     case GREATER_OR_EQUAL:
03847       {
03848         // Compute an upper approximation for `-sc_expr' into `sum'.
03849         // Note: approximating `-sc_expr' from above and then negating the
03850         // result is the same as approximating `sc_expr' from below.
03851 
03852         // Approximate the inhomogeneous term.
03853         assign_r(sum, minus_sc_b, ROUND_UP);
03854 
03855         // Approximate the homogeneous part of `-sc_expr'.
03856         DIRTY_TEMP(N, coeff_i);
03857         DIRTY_TEMP(N, approx_i);
03858         TEMP_INTEGER(minus_sc_i);
03859         for (Row_Iterator m_iter = m_begin, m_end = m_iter + (2*w_id) + 2;
03860              m_iter != m_end; ) {
03861           const dimension_type n_i = m_iter.index();
03862           const dimension_type id = n_i/2;
03863           Row_Reference m_i = *m_iter;
03864           ++m_iter;
03865           Row_Reference m_ci = *m_iter;
03866           ++m_iter;
03867           const Coefficient& sc_i = sc_expr.coefficient(Variable(id));
03868           const int sign_i = sgn(sc_i);
03869           if (sign_i == 0)
03870             continue;
03871           // Choose carefully: we are approximating `-sc_expr'.
03872           const N& double_approx_i = (sign_i > 0) ? m_i[n_i+1] : m_ci[n_i];
03873           if (is_plus_infinity(double_approx_i)) {
03874             if (++pinf_count > 1)
03875               break;
03876             pinf_index = id;
03877             continue;
03878           }
03879           if (sign_i > 0)
03880             assign_r(coeff_i, sc_i, ROUND_UP);
03881           else {
03882             neg_assign(minus_sc_i, sc_i);
03883             assign_r(coeff_i, minus_sc_i, ROUND_UP);
03884           }
03885           div2exp_assign_r(approx_i, double_approx_i, 1, ROUND_UP);
03886           add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
03887         }
03888 
03889         // Divide by the (sign corrected) denominator (if needed).
03890         if (sc_den != 1) {
03891           // Before computing the quotient, the denominator should be
03892           // approximated towards zero. Since `sc_den' is known to be positive,
03893           // this amounts to rounding downwards, which is achieved by rounding
03894           // upwards `minus_sc_den' and negating again the result.
03895           DIRTY_TEMP(N, down_sc_den);
03896           assign_r(down_sc_den, minus_sc_den, ROUND_UP);
03897           neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
03898           div_assign_r(sum, sum, down_sc_den, ROUND_UP);
03899         }
03900 
03901         if (pinf_count == 0) {
03902           // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
03903           DIRTY_TEMP(N, double_sum);
03904           mul2exp_assign_r(double_sum, sum, 1, ROUND_IGNORE);
03905           add_octagonal_constraint(n_var, n_var+1, double_sum);
03906           // Deduce constraints of the form `-v +/- u', where `u != v'.
03907           deduce_minus_v_pm_u_bounds(var_id, pinf_index, sc_expr, sc_den, sum);
03908         }
03909         else if (pinf_count == 1) {
03910           dimension_type pinf_ind = 2*pinf_index;
03911           if (expr.coefficient(Variable(pinf_index)) == denominator) {
03912             // Add the constraint `v - pinf_index >= -sum',
03913             // i.e., `pinf_index - v <= sum'.
03914             if (pinf_index < var_id)
03915               add_octagonal_constraint(n_var, pinf_ind, sum);
03916             else
03917               add_octagonal_constraint(pinf_ind+1, n_var, sum);
03918           }
03919           else {
03920             if (expr.coefficient(Variable(pinf_index)) == minus_den) {
03921               // Add the constraint `v + pinf_index >= -sum',
03922               // i.e., `-pinf_index - v <= sum'.
03923               if (pinf_index < var_id)
03924                 add_octagonal_constraint(n_var, pinf_ind+1, sum);
03925               else
03926                 add_octagonal_constraint(pinf_ind, n_var+1, sum);
03927             }
03928           }
03929         }
03930         break;
03931       }
03932 
03933     default:
03934       // We already dealt with the other cases.
03935       throw std::runtime_error("PPL internal error");
03936     }
03937   }
03938 }

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

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, PLUS_INFINITY, 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 >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain().

03298                                                             {
03299   assert(v_id < space_dim);
03300   const dimension_type n_v = 2*v_id;
03301   typename OR_Matrix<N>::row_iterator m_iter = matrix.row_begin() + n_v;
03302   typename OR_Matrix<N>::row_reference_type r_v = *m_iter;
03303   typename OR_Matrix<N>::row_reference_type r_cv = *(++m_iter);
03304   for (dimension_type h = m_iter.row_size(); h-- > 0; ) {
03305     assign_r(r_v[h], PLUS_INFINITY, ROUND_NOT_NEEDED);
03306     assign_r(r_cv[h], PLUS_INFINITY, ROUND_NOT_NEEDED);
03307   }
03308   ++m_iter;
03309   for (typename OR_Matrix<N>::row_iterator m_end = matrix.row_end();
03310        m_iter != m_end; ++m_iter) {
03311     typename OR_Matrix<N>::row_reference_type r = *m_iter;
03312     assign_r(r[n_v], PLUS_INFINITY, ROUND_NOT_NEEDED);
03313     assign_r(r[n_v+1], PLUS_INFINITY, ROUND_NOT_NEEDED);
03314   }
03315 }

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

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

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

03320                                                                {
03321   assert(v_id < space_dim);
03322   const dimension_type n_v = 2*v_id;
03323   typename OR_Matrix<N>::row_iterator m_iter = matrix.row_begin() + n_v;
03324   typename OR_Matrix<N>::row_reference_type r_v = *m_iter;
03325   typename OR_Matrix<N>::row_reference_type r_cv = *(++m_iter);
03326   for (dimension_type k = n_v; k-- > 0; ) {
03327     assign_r(r_v[k], PLUS_INFINITY, ROUND_NOT_NEEDED);
03328     assign_r(r_cv[k], PLUS_INFINITY, ROUND_NOT_NEEDED);
03329   }
03330   ++m_iter;
03331   for (typename OR_Matrix<N>::row_iterator m_end = matrix.row_end();
03332        m_iter != m_end; ++m_iter) {
03333     typename OR_Matrix<N>::row_reference_type r = *m_iter;
03334     assign_r(r[n_v], PLUS_INFINITY, ROUND_NOT_NEEDED);
03335     assign_r(r[n_v+1], PLUS_INFINITY, ROUND_NOT_NEEDED);
03336   }
03337 }

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 3062 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::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::neg_assign(), and TEMP_INTEGER.

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

03066                                       {
03067   // Private method: the caller has to ensure the following.
03068   assert(sc_den > 0);
03069   assert(!is_plus_infinity(ub_v));
03070 
03071   DIRTY_TEMP0(mpq_class, mpq_sc_den);
03072   assign_r(mpq_sc_den, sc_den, ROUND_NOT_NEEDED);
03073 
03074   // No need to consider indices greater than `last_id'.
03075   const dimension_type n_v = 2*v_id;
03076   typename OR_Matrix<N>::row_reference_type m_cv = matrix[n_v+1];
03077 
03078   // Speculatively allocate temporaries out of the loop.
03079   DIRTY_TEMP(N, half);
03080   DIRTY_TEMP0(mpq_class, minus_lb_u);
03081   DIRTY_TEMP0(mpq_class, q);
03082   DIRTY_TEMP0(mpq_class, minus_q);
03083   DIRTY_TEMP0(mpq_class, ub_u);
03084   DIRTY_TEMP0(mpq_class, lb_u);
03085   DIRTY_TEMP(N, up_approx);
03086   TEMP_INTEGER(minus_expr_u);
03087 
03088   for (dimension_type u_id = last_id+1; u_id-- > 0; ) {
03089     // Skip the case when `u_id == v_id'.
03090     if (u_id == v_id)
03091       continue;
03092     const Coefficient& expr_u = sc_expr.coefficient(Variable(u_id));
03093     // Skip the case when `expr_u == 0'.
03094     if (expr_u == 0)
03095       continue;
03096 
03097     const dimension_type n_u = u_id*2;
03098     // If `expr_u' is positive, we can improve `v - u'.
03099     if (expr_u > 0) {
03100       if (expr_u >= sc_den) {
03101         // Here q >= 1: deducing `v - u <= ub_v - ub_u'.
03102         // We avoid to check if `ub_u' is plus infinity, because
03103         // it is used for the computation of `ub_v'.
03104         // Let half = m_cu_u / 2.
03105         div2exp_assign_r(half, matrix[n_u+1][n_u], 1, ROUND_UP);
03106         N& m_v_minus_u = (n_v < n_u) ? matrix[n_u][n_v] : m_cv[n_u+1];
03107         sub_assign_r(m_v_minus_u, ub_v, half, ROUND_UP);
03108       }
03109       else {
03110         // Here 0 < q < 1.
03111         typename OR_Matrix<N>::row_reference_type m_u = matrix[n_u];
03112         const N& m_u_cu = m_u[n_u+1];
03113         if (!is_plus_infinity(m_u_cu)) {
03114           // Let `ub_u' and `lb_u' be the known upper and lower bound
03115           // for `u', respectively. The upper bound for `v - u' is
03116           // computed as `ub_v - (q * ub_u + (1-q) * lb_u)',
03117           // i.e., `ub_v + (-lb_u) - q * (ub_u + (-lb_u))'.
03118           assign_r(minus_lb_u, m_u_cu, ROUND_NOT_NEEDED);
03119           div2exp_assign_r(minus_lb_u, minus_lb_u, 1, ROUND_NOT_NEEDED);
03120           assign_r(q, expr_u, ROUND_NOT_NEEDED);
03121           div_assign_r(q, q, mpq_sc_den, ROUND_NOT_NEEDED);
03122           assign_r(ub_u, matrix[n_u+1][n_u], ROUND_NOT_NEEDED);
03123           div2exp_assign_r(ub_u, ub_u, 1, ROUND_NOT_NEEDED);
03124           // Compute `ub_u - lb_u'.
03125           add_assign_r(ub_u, ub_u, minus_lb_u, ROUND_NOT_NEEDED);
03126           // Compute `(-lb_u) - q * (ub_u - lb_u)'.
03127           sub_mul_assign_r(minus_lb_u, q, ub_u, ROUND_NOT_NEEDED);
03128           assign_r(up_approx, minus_lb_u, ROUND_UP);
03129           // Deducing `v - u <= ub_v - (q * ub_u + (1-q) * lb_u)'.
03130           N& m_v_minus_u = (n_v < n_u) ? m_u[n_v] : m_cv[n_u+1];
03131           add_assign_r(m_v_minus_u, ub_v, up_approx, ROUND_UP);
03132         }
03133       }
03134     }
03135     else {
03136       assert(expr_u < 0);
03137       // If `expr_u' is negative, we can improve `v + u'.
03138       neg_assign(minus_expr_u, expr_u);
03139       if (minus_expr_u >= sc_den) {
03140         // Here q <= -1: Deducing `v + u <= ub_v + lb_u'.
03141         // We avoid to check if `lb_u' is plus infinity, because
03142         // it is used for the computation of `ub_v'.
03143         // Let half = m_u_cu / 2.
03144         div2exp_assign_r(half, matrix[n_u][n_u+1], 1, ROUND_UP);
03145         N& m_v_plus_u = (n_v < n_u) ? matrix[n_u+1][n_v] : m_cv[n_u];
03146         sub_assign_r(m_v_plus_u, ub_v, half, ROUND_UP);
03147       }
03148       else {
03149         // Here -1 < q < 0.
03150         typename OR_Matrix<N>::row_reference_type m_cu = matrix[n_u+1];
03151         const N& m_cu_u = m_cu[n_u];
03152         if (!is_plus_infinity(m_cu_u)) {
03153           // Let `ub_u' and `lb_u' be the known upper and lower bound
03154           // for `u', respectively. The upper bound for `v + u' is
03155           // computed as `ub_v + ((-q) * lb_u + (1+q) * ub_u)',
03156           // i.e., `ub_v + ub_u + (-q) * (lb_u - ub_u)'.
03157           assign_r(ub_u, m_cu[n_u], ROUND_NOT_NEEDED);
03158           div2exp_assign_r(ub_u, ub_u, 1, ROUND_NOT_NEEDED);
03159           assign_r(minus_q, minus_expr_u, ROUND_NOT_NEEDED);
03160           div_assign_r(minus_q, minus_q, mpq_sc_den, ROUND_NOT_NEEDED);
03161           assign_r(lb_u, matrix[n_u][n_u+1], ROUND_NOT_NEEDED);
03162           div2exp_assign_r(lb_u, lb_u, 1, ROUND_NOT_NEEDED);
03163           neg_assign_r(lb_u, lb_u, ROUND_NOT_NEEDED);
03164           // Compute `lb_u - ub_u'.
03165           sub_assign_r(lb_u, lb_u, ub_u, ROUND_NOT_NEEDED);
03166           // Compute `ub_u + (-q) * (lb_u - ub_u)'.
03167           add_mul_assign_r(ub_u, minus_q, lb_u, ROUND_NOT_NEEDED);
03168           assign_r(up_approx, ub_u, ROUND_UP);
03169           // Deducing `v + u <= ub_v + ((-q) * lb_u + (1+q) * ub_u)'.
03170           N& m_v_plus_u = (n_v < n_u) ? m_cu[n_v] : m_cv[n_u];
03171           add_assign_r(m_v_plus_u, ub_v, up_approx, ROUND_UP);
03172         }
03173       }
03174     }
03175   }
03176 }

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 3181 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::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::neg_assign(), and TEMP_INTEGER.

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

03185                                                   {
03186   // Private method: the caller has to ensure the following.
03187   assert(sc_den > 0);
03188   assert(!is_plus_infinity(minus_lb_v));
03189 
03190   DIRTY_TEMP0(mpq_class, mpq_sc_den);
03191   assign_r(mpq_sc_den, sc_den, ROUND_NOT_NEEDED);
03192 
03193   // No need to consider indices greater than `last_id'.
03194   const dimension_type n_v = 2*v_id;
03195   typename OR_Matrix<N>::row_reference_type m_v = matrix[n_v];
03196 
03197   // Speculatively allocate temporaries out of the loop.
03198   DIRTY_TEMP(N, half);
03199   DIRTY_TEMP0(mpq_class, ub_u);
03200   DIRTY_TEMP0(mpq_class, q);
03201   DIRTY_TEMP0(mpq_class, minus_lb_u);
03202   DIRTY_TEMP(N, up_approx);
03203   TEMP_INTEGER(minus_expr_u);
03204 
03205   for (dimension_type u_id = last_id+1; u_id-- > 0; ) {
03206     // Skip the case when `u_id == v_id'.
03207     if (u_id == v_id)
03208       continue;
03209     const Coefficient& expr_u = sc_expr.coefficient(Variable(u_id));
03210     // Skip the case when `expr_u == 0'.
03211     if (expr_u == 0)
03212       continue;
03213 
03214     const dimension_type n_u = u_id*2;
03215     // If `expr_u' is positive, we can improve `-v + u'.
03216     if (expr_u > 0) {
03217       if (expr_u >= sc_den) {
03218         // Here q >= 1: deducing `-v + u <= lb_u - lb_v',
03219         // i.e., `u - v <= (-lb_v) - (-lb_u)'.
03220         // We avoid to check if `lb_u' is plus infinity, because
03221         // it is used for the computation of `lb_v'.
03222         // Let half = m_u_cu / 2.
03223         div2exp_assign_r(half, matrix[n_u][n_u+1], 1, ROUND_UP);
03224         N& m_u_minus_v = (n_v < n_u) ? matrix[n_u+1][n_v+1] : m_v[n_u];
03225         sub_assign_r(m_u_minus_v, minus_lb_v, half, ROUND_UP);
03226       }
03227       else {
03228         // Here 0 < q < 1.
03229         typename OR_Matrix<N>::row_reference_type m_cu = matrix[n_u+1];
03230         const N& m_cu_u = m_cu[n_u];
03231         if (!is_plus_infinity(m_cu_u)) {
03232           // Let `ub_u' and `lb_u' be the known upper and lower bound
03233           // for `u', respectively. The upper bound for `u - v' is
03234           // computed as `(q * lb_u + (1-q) * ub_u) - lb_v',
03235           // i.e., `ub_u - q * (ub_u + (-lb_u)) + minus_lb_v'.
03236           assign_r(ub_u, m_cu[n_u], ROUND_NOT_NEEDED);
03237           div2exp_assign_r(ub_u, ub_u, 1, ROUND_NOT_NEEDED);
03238           assign_r(q, expr_u, ROUND_NOT_NEEDED);
03239           div_assign_r(q, q, mpq_sc_den, ROUND_NOT_NEEDED);
03240           assign_r(minus_lb_u, matrix[n_u][n_u+1], ROUND_NOT_NEEDED);
03241           div2exp_assign_r(minus_lb_u, minus_lb_u, 1, ROUND_NOT_NEEDED);
03242           // Compute `ub_u - lb_u'.
03243           add_assign_r(minus_lb_u, ub_u, minus_lb_u, ROUND_NOT_NEEDED);
03244           // Compute `ub_u - q * (ub_u - lb_u)'.
03245           sub_mul_assign_r(ub_u, q, minus_lb_u, ROUND_NOT_NEEDED);
03246           assign_r(up_approx, ub_u, ROUND_UP);
03247           // Deducing `u - v <= -lb_v - (q * lb_u + (1-q) * ub_u)'.
03248           N& m_u_minus_v = (n_v < n_u) ? m_cu[n_v+1] : m_v[n_u];
03249           add_assign_r(m_u_minus_v, minus_lb_v, up_approx, ROUND_UP);
03250         }
03251       }
03252     }
03253     else {
03254       assert(expr_u < 0);
03255       // If `expr_u' is negative, we can improve `-v - u'.
03256       neg_assign(minus_expr_u, expr_u);
03257       if (minus_expr_u >= sc_den) {
03258         // Here q <= -1: Deducing `-v - u <= -lb_v - ub_u'.
03259         // We avoid to check if `ub_u' is plus infinity, because
03260         // it is used for the computation of `lb_v'.
03261         // Let half = m_cu_u / 2.
03262         div2exp_assign_r(half, matrix[n_u+1][n_u], 1, ROUND_UP);
03263         N& m_minus_v_minus_u = (n_v < n_u) ? matrix[n_u][n_v+1] : m_v[n_u+1];
03264         sub_assign_r(m_minus_v_minus_u, minus_lb_v, half, ROUND_UP);
03265       }
03266       else {
03267         // Here -1 < q < 0.
03268         typename OR_Matrix<N>::row_reference_type m_u = matrix[n_u];
03269         const N& m_u_cu = m_u[n_u+1];
03270         if (!is_plus_infinity(m_u_cu)) {
03271           // Let `ub_u' and `lb_u' be the known upper and lower bound
03272           // for `u', respectively. The upper bound for `-v - u' is
03273           // computed as `-lb_v - ((-q)*ub_u + (1+q)*lb_u)',
03274           // i.e., `minus_lb_v - lb_u + q*(ub_u - lb_u)'.
03275           assign_r(ub_u, matrix[n_u+1][n_u], ROUND_NOT_NEEDED);
03276           div2exp_assign_r(ub_u, ub_u, 1, ROUND_NOT_NEEDED);
03277           assign_r(q, expr_u, ROUND_NOT_NEEDED);
03278           div_assign_r(q, q, mpq_sc_den, ROUND_NOT_NEEDED);
03279           assign_r(minus_lb_u, m_u[n_u+1], ROUND_NOT_NEEDED);
03280           div2exp_assign_r(minus_lb_u, minus_lb_u, 1, ROUND_NOT_NEEDED);
03281           // Compute `ub_u - lb_u'.
03282           add_assign_r(ub_u, ub_u, minus_lb_u, ROUND_NOT_NEEDED);
03283           // Compute `-lb_u + q*(ub_u - lb_u)'.
03284           add_mul_assign_r(minus_lb_u, q, ub_u, ROUND_NOT_NEEDED);
03285           assign_r(up_approx, minus_lb_u, ROUND_UP);
03286           // Deducing `-v - u <= -lb_v - ((-q) * ub_u + (1+q) * lb_u)'.
03287           N& m_minus_v_minus_u = (n_v < n_u) ? m_u[n_v+1] : m_v[n_u+1];
03288           add_assign_r(m_minus_v_minus_u, minus_lb_v, up_approx, ROUND_UP);
03289         }
03290       }
03291     }
03292   }
03293 }

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

References Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::extract_octagonal_difference(), 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(), 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::Constraint_System::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and TEMP_INTEGER.

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

02772                                                                 {
02773   const dimension_type cs_space_dim = cs.space_dimension();
02774   // Private method: the caller has to ensure the following.
02775   assert(cs_space_dim <= space_dim);
02776 
02777   strong_closure_assign();
02778   bool is_oct_changed = false;
02779 
02780   // Allocate temporaries outside of the loop.
02781   TEMP_INTEGER(coeff);
02782   TEMP_INTEGER(term);
02783   DIRTY_TEMP(N, d);
02784 
02785   for (Constraint_System::const_iterator cs_i = cs.begin(),
02786          cs_end = cs.end(); cs_i != cs_end; ++cs_i) {
02787     const Constraint& c = *cs_i;
02788     dimension_type num_vars = 0;
02789     dimension_type i = 0;
02790     dimension_type j = 0;
02791     // Constraints that are not octagonal differences are ignored.
02792     if (!extract_octagonal_difference(c, cs_space_dim, num_vars, i, j,
02793                                       coeff, term))
02794       continue;
02795 
02796     typedef typename OR_Matrix<N>::const_row_iterator Row_iterator;
02797     typedef typename OR_Matrix<N>::const_row_reference_type Row_reference;
02798     typedef typename OR_Matrix<N>::row_iterator Row_Iterator;
02799     typedef typename OR_Matrix<N>::row_reference_type Row_Reference;
02800     Row_iterator m_begin = matrix.row_begin();
02801     // Select the cell to be modified for the "<=" part of the constraint.
02802     Row_iterator i_iter = m_begin + i;
02803     Row_reference m_i = *i_iter;
02804     OR_Matrix<N>& lo_mat = limiting_octagon.matrix;
02805     Row_Iterator lo_iter = lo_mat.row_begin() + i;
02806     Row_Reference lo_m_i = *lo_iter;
02807     N& lo_m_i_j = lo_m_i[j];
02808     if (coeff < 0)
02809       neg_assign(coeff);
02810     // Compute the bound for `m_i_j', rounding towards plus infinity.
02811     div_round_up(d, term, coeff);
02812     if (m_i[j] <= d)
02813       if (c.is_inequality()) {
02814         if (lo_m_i_j > d) {
02815           lo_m_i_j = d;
02816           is_oct_changed = true;
02817         }
02818         else {
02819           // Select the right row of the cell.
02820           if (i%2 == 0) {
02821             ++i_iter;
02822             ++lo_iter;
02823           }
02824           else {
02825             --i_iter;
02826             --lo_iter;
02827           }
02828           Row_reference m_ci = *i_iter;
02829           Row_Reference lo_m_ci = *lo_iter;
02830           // Select the right column of the cell.
02831           dimension_type cj = coherent_index(j);
02832           N& lo_m_ci_cj = lo_m_ci[cj];
02833           neg_assign(term);
02834           div_round_up(d, term, coeff);
02835           if (m_ci[cj] <= d && lo_m_ci_cj > d) {
02836             lo_m_ci_cj = d;
02837             is_oct_changed = true;
02838           }
02839         }
02840       }
02841   }
02842   // In general, adding a constraint does not preserve the strongly
02843   // closure of the octagon.
02844   if (is_oct_changed && limiting_octagon.marked_strongly_closed())
02845     limiting_octagon.reset_strongly_closed();
02846 }

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

References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix.

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

02100                                                                {
02101   assert(!marked_empty() && marked_strongly_closed());
02102   assert(successor.size() == 0);
02103   // Variables are ordered according to their index.
02104   // The vector `successor' is used to indicate which variable
02105   // immediately follows a given one in the corresponding equivalence class.
02106   const dimension_type successor_size = matrix.num_rows();
02107   // Initially, each variable is successor of its own zero-equivalence class.
02108   successor.reserve(successor_size);
02109   for (dimension_type i = 0; i < successor_size; ++i)
02110     successor.push_back(i);
02111   // Now compute actual successors.
02112   for (dimension_type i = successor_size; i-- > 0; )  {
02113     typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin()+i;
02114     typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter;
02115     typename OR_Matrix<N>::const_row_reference_type m_ci = (i%2) ?
02116           *(i_iter-1) : *(i_iter+1);
02117     for (dimension_type j = 0; j < i; ++j) {
02118     //for (dimension_type j = i; j-- > 0; ) {
02119       dimension_type cj = coherent_index(j);
02120       if (is_additive_inverse(m_ci[cj], m_i[j]))
02121         // Choose as successor the variable having the greatest index.
02122         successor[j] = i;
02123     }
02124   }
02125 }

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

References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed().

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

02164                                                      {
02165   assert(!marked_empty() && marked_strongly_closed());
02166   assert(no_sing_leaders.size() == 0);
02167   dimension_type successor_size = successor.size();
02168   std::deque<bool> dealt_with(successor_size, false);
02169   for (dimension_type i = 0; i < successor_size; ++i) {
02170     dimension_type next_i = successor[i];
02171     if (!dealt_with[i]) {
02172       // The index is a leader.
02173       // Now check if it is a leader of a singular class or not.
02174       if (next_i == coherent_index(i)) {
02175         exist_sing_class = true;
02176         sing_leader = i;
02177       }
02178       else
02179         no_sing_leaders.push_back(i);
02180     }
02181     // The following index isn't a leader.
02182     dealt_with[next_i] = true;
02183   }
02184 }

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

References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix.

02130                                                           {
02131   assert(!marked_empty() && marked_strongly_closed());
02132   assert(leaders.size() == 0);
02133   // Variables are ordered according to their index.
02134   // The vector `leaders' is used to indicate the smallest variable
02135   // that belongs to the corresponding equivalence class.
02136   const dimension_type leader_size = matrix.num_rows();
02137   // Initially, each variable is leader of its own zero-equivalence class.
02138   leaders.reserve(leader_size);
02139   for (dimension_type i = 0; i < leader_size; ++i)
02140     leaders.push_back(i);
02141   // Now compute actual leaders.
02142   for (typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin(),
02143          matrix_row_end = matrix.row_end();
02144        i_iter != matrix_row_end; ++i_iter) {
02145     typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter;
02146     dimension_type i = i_iter.index();
02147     typename OR_Matrix<N>::const_row_reference_type m_ci =
02148       (i%2) ? *(i_iter-1) : *(i_iter+1);
02149     for (dimension_type j = 0; j < i; ++j) {
02150       dimension_type cj = coherent_index(j);
02151       if (is_additive_inverse(m_ci[cj], m_i[j]))
02152         // Choose as leader the variable having the smaller index.
02153         leaders[i] = leaders[j];
02154     }
02155   }
02156 }

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 2188 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::Octagonal_Shape< T >::compute_successors(), 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 >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::swap().

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

02188                                                   {
02189   // Zero-dimensional Octagonal shapes are necessarily reduced.
02190   if (space_dim == 0)
02191     return;
02192 
02193   // First find the tightest constraints for this octagon.
02194   strong_closure_assign();
02195 
02196   // If `*this' is empty, then there is nothing to reduce.
02197   if (marked_empty())
02198     return;
02199 
02200   // Step 1: compute zero-equivalence classes.
02201   // Variables corresponding to indices `i' and `j' are zero-equivalent
02202   // if they lie on a zero-weight loop; since the matrix is strongly
02203   // closed, this happens if and only if matrix[i][j] == -matrix[ci][cj].
02204   std::vector<dimension_type> no_sing_leaders;
02205   dimension_type sing_leader = 0;
02206   bool exist_sing_class = false;
02207   std::vector<dimension_type> successor;
02208   compute_successors(successor);
02209   compute_leaders(successor, no_sing_leaders, exist_sing_class, sing_leader);
02210   const dimension_type num_no_sing_leaders = no_sing_leaders.size();
02211 
02212   Octagonal_Shape aux(space_dim);
02213   // Step 2: add to auxiliary octagon only non-redundant
02214   // constraints and construct a 0-cycle using only
02215   // the leaders of the non-singular classes.
02216   for (dimension_type li = 0; li < num_no_sing_leaders; ++li) {
02217     const dimension_type i = no_sing_leaders[li];
02218     const dimension_type ci = coherent_index(i);
02219     typename OR_Matrix<N>::const_row_reference_type m_i =
02220       *(matrix.row_begin()+i);
02221     typename OR_Matrix<N>::row_reference_type aux_i =
02222       *(aux.matrix.row_begin()+i);
02223     if (i%2 == 0) {
02224       // Each positive equivalence class must have a single 0-cycle
02225       // connecting all equivalent variables in increasing order.
02226       // Note: by coherence assumption, the variables in the
02227       // corresponding negative equivalence class are
02228       // automatically connected.
02229       if (i != successor[i]) {
02230         dimension_type j = i;
02231         dimension_type next_j = successor[j];
02232         while (j != next_j) {
02233           aux.matrix[next_j][j] = matrix[next_j][j];
02234           j = next_j;
02235           next_j = successor[j];
02236         }
02237         const dimension_type cj = coherent_index(j);
02238         aux.matrix[cj][ci] = matrix[cj][ci];
02239       }
02240     }
02241 
02242     dimension_type rs_li = (li%2) ? li :li+1;
02243     // Check if the constraint is redundant.
02244     DIRTY_TEMP(N, tmp);
02245     for (dimension_type lj = 0 ; lj <= rs_li; ++lj) {
02246       const dimension_type j = no_sing_leaders[lj];
02247       const dimension_type cj = coherent_index(j);
02248       const N& m_i_j = m_i[j];
02249       const N& m_i_ci = m_i[ci];
02250       bool to_add = true;
02251       // Control if the constraint is redundant by strong-coherence,
02252       // that is:
02253       // m_i_j >= (m_i_ci + m_cj_j)/2,   where j != ci.
02254       if (j != ci) {
02255         add_assign_r(tmp, m_i_ci, matrix[cj][j], ROUND_UP);
02256         div2exp_assign_r(tmp, tmp, 1, ROUND_UP);
02257         if (m_i_j >= tmp) {
02258           to_add = false;
02259           continue;
02260         }
02261       }
02262       // Control if the constraint is redundant by strong closure, that is
02263       // if there is a path from i to j (i = i_0, ... , i_n = j), such that
02264       // m_i_j = sum_{k=0}^{n-1} m_{i_k}_{i_(k+1)}.
02265       // Since the octagon is already strongly closed, the above relation
02266       // is reduced to three case, in accordance with k, i, j inter-depend:
02267       // exit k such that
02268       // 1.) m_i_j >= m_i_k   + m_cj_ck,   if k < j < i; or
02269       // 2.) m_i_j >= m_i_k   + m_k,_j,    if j < k < i; or
02270       // 3.) m_i_j >= m_ck_ci + m_k_j,     if j < i < k.
02271       // Note: `i > j'.
02272       for (dimension_type lk = 0; lk < num_no_sing_leaders; ++lk) {
02273         const dimension_type k = no_sing_leaders[lk];
02274         if (k != i && k != j) {
02275           dimension_type ck = coherent_index(k);
02276           if (k < j)
02277             // Case 1.
02278             add_assign_r(tmp, m_i[k], matrix[cj][ck], ROUND_UP);
02279           else if (k < i)
02280             // Case 2.
02281             add_assign_r(tmp, m_i[k], matrix[k][j], ROUND_UP);
02282           else
02283             // Case 3.
02284             add_assign_r(tmp, matrix[ck][ci], matrix[k][j], ROUND_UP);
02285 
02286           // Checks if the constraint is redundant.
02287           if (m_i_j >= tmp) {
02288             to_add = false;
02289             break;
02290           }
02291         }
02292       }
02293 
02294       // The constraint is not redundant.
02295       if (to_add)
02296         aux_i[j] = m_i_j;
02297     }
02298   }
02299 
02300   // If there exist a singular equivalence class, then it must have a
02301   // single 0-cycle connecting all the positive and negative equivalent
02302   // variables.
02303   // Note: the singular class is not connected with the other classes.
02304   if (exist_sing_class) {
02305     aux.matrix[sing_leader][sing_leader+1]
02306       = matrix[sing_leader][sing_leader+1];
02307     if (successor[sing_leader+1] != sing_leader+1) {
02308       dimension_type j = sing_leader;
02309       dimension_type next_jj = successor[j+1];
02310       while (next_jj != j+1) {
02311         aux.matrix[next_jj][j] = matrix[next_jj][j];
02312         j = next_jj;
02313         next_jj = successor[j+1];
02314       }
02315       aux.matrix[j+1][j] = matrix[j+1][j];
02316     }
02317     else
02318       aux.matrix[sing_leader+1][sing_leader]
02319         = matrix[sing_leader+1][sing_leader];
02320   }
02321 
02322   Octagonal_Shape<T>& x = const_cast<Octagonal_Shape<T>&>(*this);
02323   aux.reset_strongly_closed();
02324 
02325 #ifndef NDEBUG
02326   {
02327     // We assume that `aux' is equal to `*this'.
02328     const Octagonal_Shape x_copy = *this;
02329     const Octagonal_Shape y_copy = aux;
02330     assert(x_copy == y_copy);
02331   }
02332 #endif
02333 
02334   std::swap(x, aux);
02335   assert(is_strongly_reduced());
02336 }

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 968 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, and PLUS_INFINITY.

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

00968                                               {
00969   // This method is only used in assertions: efficiency is not a must.
00970 
00971   // An empty octagon is already transitively reduced.
00972   if (marked_empty())
00973     return true;
00974 
00975   Octagonal_Shape x = *this;
00976   // The matrix representing an OS is strongly reduced if, by removing
00977   // any constraint, the resulting matrix describes a different OS.
00978   for (typename OR_Matrix<N>::const_row_iterator iter = matrix.row_begin(),
00979          matrix_row_end = matrix.row_end(); iter != matrix_row_end; ++iter) {
00980     typename OR_Matrix<N>::const_row_reference_type m_i = *iter;
00981     const dimension_type i = iter.index();
00982     for (dimension_type j = iter.row_size(); j-- > 0; ) {
00983       if (!is_plus_infinity(m_i[j])) {
00984         Octagonal_Shape x_copy = *this;
00985         assign_r(x_copy.matrix[i][j], PLUS_INFINITY, ROUND_NOT_NEEDED);
00986         if (x == x_copy)
00987           return false;
00988       }
00989     }
00990   }
00991   // The octagon is just reduced.
00992   return true;
00993 }

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

References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::is_plus_infinity(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix.

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

00932                                              {
00933   // This method is only used by method OK() so as to check if a
00934   // strongly closed matrix is also strong-coherent, as it must be.
00935   const dimension_type num_rows = matrix.num_rows();
00936 
00937   // Allocated here once and for all.
00938   DIRTY_TEMP(N, semi_sum);
00939   // The strong-coherence is: for every indexes i and j (and i != j)
00940   // matrix[i][j] <= (matrix[i][ci] + matrix[cj][j])/2
00941   // where ci = i + 1, if i is even number or
00942   //       ci = i - 1, if i is odd.
00943   // Ditto for cj.
00944   for (dimension_type i = num_rows; i-- > 0; ) {
00945     typename OR_Matrix<N>::const_row_iterator iter = matrix.row_begin() + i;
00946     typename OR_Matrix<N>::const_row_reference_type m_i = *iter;
00947     const N& m_i_ci = m_i[coherent_index(i)];
00948     for (dimension_type j = matrix.row_size(i); j-- > 0; )
00949       // Note: on the main diagonal only PLUS_INFINITY can occur.
00950       if (i != j) {
00951         const N& m_cj_j = matrix[coherent_index(j)][j];
00952         if (!is_plus_infinity(m_i_ci)
00953             && !is_plus_infinity(m_cj_j)) {
00954           // Compute (m_i_ci + m_cj_j)/2 into `semi_sum',
00955           // rounding the result towards plus infinity.
00956           add_assign_r(semi_sum, m_i_ci, m_cj_j, ROUND_UP);
00957           div2exp_assign_r(semi_sum, semi_sum, 1, ROUND_UP);
00958           if (m_i[j] > semi_sum)
00959             return false;
00960         }
00961       }
00962   }
00963   return true;
00964 }

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

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

References Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::is_even(), Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension().

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

01935                                                            {
01936   assert(std::numeric_limits<N>::is_integer);
01937   assert(marked_strongly_closed());
01938   const dimension_type space_dim = space_dimension();
01939   for (dimension_type i = 0; i < 2*space_dim; i += 2) {
01940     const dimension_type ci = i+1;
01941     const N& mat_i_ci = matrix[i][ci];
01942     if (!is_plus_infinity(mat_i_ci)
01943         // Check for oddness of `mat_i_ci'.
01944         && !is_even(mat_i_ci)
01945         // Check for zero-equivalence of `i' and `ci'.
01946         && is_additive_inverse(mat_i_ci, matrix[ci][i]))
01947       return true;
01948   }
01949   return false;
01950 }

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

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), 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(), PLUS_INFINITY, 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 >::euclidean_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::get_limiting_octagon(), 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_higher_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign().

01767                                                 {
01768   // Do something only if necessary (zero-dim implies strong closure).
01769   if (marked_empty() || marked_strongly_closed() || space_dim == 0)
01770     return;
01771 
01772   // Even though the octagon will not change, its internal representation
01773   // is going to be modified by the closure algorithm.
01774   Octagonal_Shape& x = const_cast<Octagonal_Shape<T>&>(*this);
01775 
01776   typedef typename OR_Matrix<N>::row_iterator Row_Iterator;
01777   typedef typename OR_Matrix<N>::row_reference_type Row_Reference;
01778 
01779   const dimension_type n_rows = x.matrix.num_rows();
01780   const Row_Iterator m_begin = x.matrix.row_begin();
01781   const Row_Iterator m_end = x.matrix.row_end();
01782 
01783   // Fill the main diagonal with zeros.
01784   for (Row_Iterator i = m_begin; i != m_end; ++i) {
01785     assert(is_plus_infinity((*i)[i.index()]));
01786     assign_r((*i)[i.index()], 0, ROUND_NOT_NEEDED);
01787   }
01788 
01789   // This algorithm is given by two steps: the first one is a simple
01790   // adaptation of the `shortest-path closure' using the Floyd-Warshall
01791   // algorithm; the second one is the `strong-coherence' algorithm.
01792   // It is important to note that after the strong-coherence,
01793   // the octagon is still shortest-path closed and hence, strongly closed.
01794 
01795   // Recall that, given an index `h', we indicate with `ch' the coherent
01796   // index, i.e., the index such that:
01797   //   ch = h + 1, if h is an even number;
01798   //   ch = h - 1, if h is an odd number.
01799 
01800   typename OR_Matrix<N>::element_iterator iter_ij;
01801   std::vector<N> vec_k(n_rows);
01802   std::vector<N> vec_ck(n_rows);
01803   DIRTY_TEMP(N, sum1);
01804   DIRTY_TEMP(N, sum2);
01805   Row_Reference x_k;
01806   Row_Reference x_ck;
01807   Row_Reference x_i;
01808   Row_Reference x_ci;
01809 
01810   // Since the index `j' of the inner loop will go from 0 up to `i',
01811   // the three nested loops have to be executed twice.
01812   for (int twice = 0; twice < 2; ++twice) {
01813 
01814     Row_Iterator x_k_iter = m_begin;
01815     Row_Iterator x_i_iter = m_begin;
01816     for (dimension_type k = 0; k < n_rows; k += 2) {
01817       const dimension_type ck = k+1;
01818       // Re-initialize the element iterator.
01819       iter_ij = x.matrix.element_begin();
01820       // Compute the row references `x_k' and `x_ck'.
01821       x_k  = *x_k_iter;
01822       ++x_k_iter;
01823       x_ck = *x_k_iter;
01824       ++x_k_iter;
01825 
01826       for (dimension_type i = 0; i <= k; i += 2) {
01827         const dimension_type ci = i+1;
01828         // Storing x_k_i == x_ci_ck.
01829         vec_k[i] = x_k[i];
01830         // Storing x_k_ci == x_i_ck.
01831         vec_k[ci] = x_k[ci];
01832         // Storing x_ck_i == x_ci_k.
01833         vec_ck[i] = x_ck[i];
01834         // Storing x_ck_ci == x_i_k.
01835         vec_ck[ci] = x_ck[ci];
01836       }
01837       x_i_iter = x_k_iter;
01838       for (dimension_type i = k+2; i < n_rows; i += 2) {
01839         const dimension_type ci = i+1;
01840         x_i = *x_i_iter;
01841         ++x_i_iter;
01842         x_ci = *x_i_iter;
01843         ++x_i_iter;
01844         // Storing x_k_i == x_ci_ck.
01845         vec_k[i] = x_ci[ck];
01846         // Storing x_k_ci == x_i_ck.
01847         vec_k[ci] = x_i[ck];
01848         // Storing x_ck_i == x_ci_k.
01849         vec_ck[i] = x_ci[k];
01850         // Storing x_ck_ci == x_i_k.
01851         vec_ck[ci] = x_i[k];
01852       }
01853 
01854       for (dimension_type i = 0; i < n_rows; ++i) {
01855         const dimension_type ci = coherent_index(i);
01856         const N& vec_k_ci = vec_k[ci];
01857         const N& vec_ck_ci = vec_ck[ci];
01858         // Unfolding two iterations on `j': this ensures that
01859         // the loop exit condition `j <= i' is OK.
01860         for (dimension_type j = 0; j <= i; ) {
01861           // First iteration:
01862           // sum1 = x_i_k + x_k_j == x_ck_ci + x_k_j;
01863           // sum2 = x_i_ck + x_ck_j == x_k_ci + x_ck_j.
01864           add_assign_r(sum1, vec_ck_ci, vec_k[j], ROUND_UP);
01865           add_assign_r(sum2, vec_k_ci, vec_ck[j], ROUND_UP);
01866           min_assign(sum1, sum2);
01867           min_assign(*iter_ij, sum1);
01868           // Exiting the first iteration: loop index control.
01869           ++j;
01870           ++iter_ij;
01871           // Second iteration: ditto.
01872           add_assign_r(sum1, vec_ck_ci, vec_k[j], ROUND_UP);
01873           add_assign_r(sum2, vec_k_ci, vec_ck[j], ROUND_UP);
01874           min_assign(sum1, sum2);
01875           min_assign(*iter_ij, sum1);
01876           // Exiting the second iteration: loop index control.
01877           ++j;
01878           ++iter_ij;
01879         }
01880       }
01881     }
01882   }
01883 
01884   // Check for emptiness: the octagon is empty if and only if there is a
01885   // negative value in the main diagonal.
01886   for (Row_Iterator i = m_begin; i != m_end; ++i) {
01887     N& x_i_i = (*i)[i.index()];
01888     if (sgn(x_i_i) < 0) {
01889       x.set_empty();
01890       return;
01891     }
01892     else {
01893       assert(sgn(x_i_i) == 0);
01894       // Restore PLUS_INFINITY on the main diagonal.
01895       assign_r(x_i_i, PLUS_INFINITY, ROUND_NOT_NEEDED);
01896     }
01897   }
01898 
01899   // Step 2: we enforce the strong coherence.
01900   x.strong_coherence_assign();
01901   // The octagon is not empty and it is now strongly closed.
01902   x.set_strongly_closed();
01903 }

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 1907 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, and Parma_Polyhedra_Library::min_assign().

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

01907                                             {
01908   // The strong-coherence is: for every indexes i and j
01909   // m_i_j <= (m_i_ci + m_cj_j)/2
01910   // where ci = i + 1, if i is even number or
01911   //       ci = i - 1, if i is odd.
01912   // Ditto for cj.
01913   DIRTY_TEMP(N, semi_sum);
01914   for (typename OR_Matrix<N>::row_iterator i_iter = matrix.row_begin(),
01915          i_end = matrix.row_end(); i_iter != i_end; ++i_iter) {
01916     typename OR_Matrix<N>::row_reference_type x_i = *i_iter;
01917     const dimension_type i = i_iter.index();
01918     const N& x_i_ci = x_i[coherent_index(i)];
01919     // Avoid to do unnecessary sums.
01920     if (!is_plus_infinity(x_i_ci))
01921       for (dimension_type j = 0, rs_i = i_iter.row_size(); j < rs_i; ++j)
01922         if (i != j) {
01923           const N& x_cj_j = matrix[coherent_index(j)][j];
01924           if (!is_plus_infinity(x_cj_j)) {
01925             add_assign_r(semi_sum, x_i_ci, x_cj_j, ROUND_UP);
01926             div2exp_assign_r(semi_sum, semi_sum, 1, ROUND_UP);
01927             min_assign(x_i[j], semi_sum);
01928           }
01929         }
01930   }
01931 }

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

Puts in *this all implicit constraints and computes the tighter ones.

Parameters:
var The variable of the altered constraints.
The octagon `*this' was transitively closed except for the constraint on variable `var'. This operation costs only $O(n^2)$.

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

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Variable::id(), 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(), PLUS_INFINITY, 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 >::strong_coherence_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().

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

01955                                                             {
01956   // `var' should be one of the dimensions of the octagon.
01957   if (var.id() >= space_dim)
01958     throw_dimension_incompatible("incremental_strong_closure_assign(v)",
01959                                  var.id());
01960 
01961   // Do something only if necessary.
01962   if (marked_empty() || marked_strongly_closed())
01963     return;
01964 
01965   // Zero-dimensional octagons are necessarily strongly closed.
01966   if (space_dim == 0)
01967     return;
01968 
01969   Octagonal_Shape& x = const_cast<Octagonal_Shape<T>&>(*this);
01970 
01971   typedef typename OR_Matrix<N>::row_iterator Row_Iterator;
01972   typedef typename OR_Matrix<N>::row_reference_type Row_Reference;
01973 
01974   const Row_Iterator m_begin = x.matrix.row_begin();
01975   const Row_Iterator m_end = x.matrix.row_end();
01976 
01977   // Fill the main diagonal with zeros.
01978   for (Row_Iterator i = m_begin; i != m_end; ++i) {
01979     assert(is_plus_infinity((*i)[i.index()]));
01980     assign_r((*i)[i.index()], 0, ROUND_NOT_NEEDED);
01981   }
01982 
01983   // Using the incremental Floyd-Warshall algorithm.
01984   // Step 1: Improve all constraints on variable `var'.
01985   const dimension_type v = 2*var.id();
01986   const dimension_type cv = v+1;
01987   Row_Iterator v_iter = m_begin + v;
01988   Row_Iterator cv_iter = v_iter + 1;
01989   Row_Reference x_v = *v_iter;
01990   Row_Reference x_cv = *cv_iter;
01991   const dimension_type rs_v = v_iter.row_size();
01992   const dimension_type n_rows = x.matrix.num_rows();
01993   DIRTY_TEMP(N, sum);
01994   for (Row_Iterator k_iter = m_begin; k_iter != m_end; ++k_iter) {
01995     const dimension_type k = k_iter.index();
01996     const dimension_type ck = coherent_index(k);
01997     const dimension_type rs_k = k_iter.row_size();
01998     Row_Reference x_k = *k_iter;
01999     Row_Reference x_ck = (k%2) ? *(k_iter-1) : *(k_iter+1);
02000 
02001     for (Row_Iterator i_iter = m_begin; i_iter != m_end; ++i_iter) {
02002       const dimension_type i = i_iter.index();
02003       const dimension_type ci = coherent_index(i);
02004       const dimension_type rs_i = i_iter.row_size();
02005       Row_Reference x_i = *i_iter;
02006       Row_Reference x_ci = (i%2) ? *(i_iter-1) : *(i_iter+1);
02007 
02008       const N& x_i_k = (k < rs_i) ? x_i[k] : x_ck[ci];
02009       if (!is_plus_infinity(x_i_k)) {
02010         const N& x_k_v = (v < rs_k) ? x_k[v] : x_cv[ck];
02011         if (!is_plus_infinity(x_k_v)) {
02012           add_assign_r(sum, x_i_k, x_k_v, ROUND_UP);
02013           N& x_i_v = (v < rs_i) ? x_i[v] : x_cv[ci];
02014           min_assign(x_i_v, sum);
02015         }
02016         const N& x_k_cv = (cv < rs_k) ? x_k[cv] : x_v[ck];
02017         if (!is_plus_infinity(x_k_cv)) {
02018           add_assign_r(sum, x_i_k, x_k_cv, ROUND_UP);
02019           N& x_i_cv = (cv < rs_i) ? x_i[cv] : x_v[ci];
02020           min_assign(x_i_cv, sum);
02021         }
02022       }
02023       const N& x_k_i = (i < rs_k) ? x_k[i] : x_ci[ck];
02024       if (!is_plus_infinity(x_k_i)) {
02025         const N& x_v_k = (k < rs_v) ? x_v[k] : x_ck[cv];
02026         if (!is_plus_infinity(x_v_k)) {
02027           N& x_v_i = (i < rs_v) ? x_v[i] : x_ci[cv];
02028           add_assign_r(sum, x_v_k, x_k_i, ROUND_UP);
02029           min_assign(x_v_i, sum);
02030         }
02031         const N& x_cv_k = (k < rs_v) ? x_cv[k] : x_ck[v];
02032         if (!is_plus_infinity(x_cv_k)) {
02033           N& x_cv_i = (i < rs_v) ? x_cv[i] : x_ci[v];
02034           add_assign_r(sum, x_cv_k, x_k_i, ROUND_UP);
02035           min_assign(x_cv_i, sum);
02036         }
02037       }
02038 
02039     }
02040   }
02041 
02042   // Step 2: improve the other bounds by using the precise bounds
02043   // for the constraints on `var'.
02044   for (Row_Iterator i_iter = m_begin; i_iter != m_end; ++i_iter) {
02045     const dimension_type i = i_iter.index();
02046     const dimension_type ci = coherent_index(i);
02047     const dimension_type rs_i = i_iter.row_size();
02048     Row_Reference x_i = *i_iter;
02049     Row_Reference x_ci = (i%2) ? *(i_iter-1) : *(i_iter+1);
02050     const N& x_i_v = (v < rs_i) ? x_i[v] : x_cv[ci];
02051     // TODO: see if it is possible to optimize this inner loop
02052     // by splitting it into several parts, so as to avoid
02053     // conditional expressions.
02054     for (dimension_type j = 0; j < n_rows; ++j) {
02055       const dimension_type cj = coherent_index(j);
02056       Row_Reference x_cj = *(m_begin+cj);
02057       N& x_i_j = (j < rs_i) ? x_i[j] : x_cj[ci];
02058       if (!is_plus_infinity(x_i_v)) {
02059         const N& x_v_j = (j < rs_v) ? x_v[j] : x_cj[cv];
02060         if (!is_plus_infinity(x_v_j)) {
02061           add_assign_r(sum, x_i_v, x_v_j, ROUND_UP);
02062           min_assign(x_i_j, sum);
02063         }
02064       }
02065       const N& x_i_cv = (cv < rs_i) ? x_i[cv] : x_v[ci];
02066       if (!is_plus_infinity(x_i_cv)) {
02067         const N& x_cv_j = (j < rs_v) ? x_cv[j] : x_cj[v];
02068         if (!is_plus_infinity(x_cv_j)) {
02069           add_assign_r(sum, x_i_cv, x_cv_j, ROUND_UP);
02070           min_assign(x_i_j, sum);
02071         }
02072       }
02073     }
02074   }
02075 
02076   // Check for emptiness: the octagon is empty if and only if there is a
02077   // negative value on the main diagonal.
02078   for (Row_Iterator i = m_begin; i != m_end; ++i) {
02079     N& x_i_i = (*i)[i.index()];
02080     if (sgn(x_i_i) < 0) {
02081       x.set_empty();
02082       return;
02083     }
02084     else {
02085       // Restore PLUS_INFINITY on the main diagonal.
02086       assert(sgn(x_i_i) == 0);
02087       assign_r(x_i_i, PLUS_INFINITY, ROUND_NOT_NEEDED);
02088     }
02089   }
02090 
02091   // Step 3: we enforce the strong coherence.
02092   x.strong_coherence_assign();
02093   // The octagon is not empty and it is now strongly closed.
02094   x.set_strongly_closed();
02095 }

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 997 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, 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(), TEMP_INTEGER, 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().

00998                                                         {
00999   // The dimension of `expr' should not be greater than the dimension
01000   // of `*this'.
01001   const dimension_type expr_space_dim = expr.space_dimension();
01002   if (space_dim < expr_space_dim)
01003     throw_dimension_incompatible((from_above
01004                                   ? "bounds_from_above(e)"
01005                                   : "bounds_from_below(e)"), "e", expr);
01006   strong_closure_assign();
01007 
01008   // A zero-dimensional or empty octagon bounds everything.
01009   if (space_dim == 0 || marked_empty())
01010     return true;
01011 
01012   // The constraint `c' is used to check if `expr' is an octagonal difference
01013   // and, in this case, to select the cell.
01014   const Constraint& c = (from_above) ? expr <= 0 : expr >= 0;
01015   dimension_type num_vars = 0;
01016   dimension_type i = 0;
01017   dimension_type j = 0;
01018   TEMP_INTEGER(coeff);
01019   TEMP_INTEGER(term);
01020   if (extract_octagonal_difference(c, c.space_dimension(), num_vars,
01021                                    i, j, coeff, term)) {
01022     if (num_vars == 0)
01023       return true;
01024     // Select the cell to be checked.
01025     typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin() + i;
01026     typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter;
01027     return !is_plus_infinity(m_i[j]);
01028   }
01029   else {
01030     // `c' is not an octagonal constraint: use the MIP solver.
01031     Optimization_Mode mode_bounds =
01032       from_above ? MAXIMIZATION : MINIMIZATION;
01033     MIP_Problem mip(space_dim, constraints(), expr, mode_bounds);
01034     return (mip.solve() == OPTIMIZED_MIP_PROBLEM);
01035   }
01036 }

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 1040 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, 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(), TEMP_INTEGER, 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().

01043                                                   {
01044   // The dimension of `expr' should not be greater than the dimension
01045   // of `*this'.
01046   const dimension_type expr_space_dim = expr.space_dimension();
01047   if (space_dim < expr_space_dim)
01048     throw_dimension_incompatible((maximize
01049                                   ? "maximize(e, ...)"
01050                                   : "minimize(e, ...)"), "e", expr);
01051   // Deal with zero-dim octagons first.
01052   if (space_dim == 0) {
01053     if (marked_empty())
01054       return false;
01055     else {
01056       ext_n = expr.inhomogeneous_term();
01057       ext_d = 1;
01058       included = true;
01059       return true;
01060     }
01061   }
01062 
01063   strong_closure_assign();
01064   // For an empty OS we simply return false.
01065   if (marked_empty())
01066     return false;
01067 
01068   // The constraint `c' is used to check if `expr' is an octagonal difference
01069   // and, in this case, to select the cell.
01070   const Constraint& c = (maximize) ? expr <= 0 : expr >= 0;
01071   dimension_type num_vars = 0;
01072   dimension_type i = 0;
01073   dimension_type j = 0;
01074   TEMP_INTEGER(coeff);
01075   TEMP_INTEGER(term);
01076   if (!extract_octagonal_difference(c, c.space_dimension(), num_vars,
01077                                     i, j, coeff, term)) {
01078     // `c' is not an octagonal constraint: use the MIP solver.
01079     Optimization_Mode max_min = (maximize) ? MAXIMIZATION : MINIMIZATION;
01080     MIP_Problem mip(space_dim, constraints(), expr, max_min);
01081     if (mip.solve() == OPTIMIZED_MIP_PROBLEM) {
01082       mip.optimal_value(ext_n, ext_d);
01083       included = true;
01084       return true;
01085     }
01086     else
01087       // Here`expr' is unbounded in `*this'.
01088       return false;
01089   }
01090   else {
01091     // `c' is an octagonal constraint.
01092     if (num_vars == 0) {
01093       ext_n = expr.inhomogeneous_term();
01094       ext_d = 1;
01095       included = true;
01096       return true;
01097     }
01098 
01099     // Select the cell to be checked.
01100     typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin() + i;
01101     typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter;
01102     DIRTY_TEMP(N, d);
01103     if (!is_plus_infinity(m_i[j])) {
01104       const Coefficient& b = expr.inhomogeneous_term();
01105       TEMP_INTEGER(minus_b);
01106       neg_assign(minus_b, b);
01107       const Coefficient& sc_b = maximize ? b : minus_b;
01108       assign_r(d, sc_b, ROUND_UP);
01109       // Set `coeff_expr' to the absolute value of coefficient of a variable
01110       // of `expr'.
01111       DIRTY_TEMP(N, coeff_expr);
01112       const Coefficient& coeff_i = expr.coefficient(Variable(i/2));
01113       const int sign_i = sgn(coeff_i);
01114       if (sign_i > 0)
01115         assign_r(coeff_expr, coeff_i, ROUND_UP);
01116       else {
01117         TEMP_INTEGER(minus_coeff_i);
01118         neg_assign(minus_coeff_i, expr.coefficient(Variable(i/2)));
01119         assign_r(coeff_expr, minus_coeff_i, ROUND_UP);
01120       }
01121       // Approximating the maximum/minimum of `expr'.
01122       if (num_vars == 1) {
01123         DIRTY_TEMP(N, m_i_j);
01124         div2exp_assign_r(m_i_j, m_i[j], 1, ROUND_UP);
01125         add_mul_assign_r(d, coeff_expr, m_i_j, ROUND_UP);
01126       }
01127       else
01128         add_mul_assign_r(d, coeff_expr, m_i[j], ROUND_UP);
01129       numer_denom(d, ext_n, ext_d);
01130       if (!maximize)
01131         neg_assign(ext_n);
01132       included = true;
01133       return true;
01134     }
01135 
01136     // The `expr' is unbounded.
01137     return false;
01138   }
01139 }

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

01146                                                                 {
01147   // The dimension of `expr' should not be greater than the dimension
01148   // of `*this'.
01149   const dimension_type expr_space_dim = expr.space_dimension();
01150   if (space_dim < expr_space_dim)
01151     throw_dimension_incompatible((maximize
01152                                   ? "maximize(e, ...)"
01153                                   : "minimize(e, ...)"), "e", expr);
01154   // Deal with zero-dim octagons first.
01155   if (space_dim == 0) {
01156     if (marked_empty())
01157       return false;
01158     else {
01159       ext_n = expr.inhomogeneous_term();
01160       ext_d = 1;
01161       included = true;
01162       g = point();
01163       return true;
01164     }
01165   }
01166 
01167   strong_closure_assign();
01168   // For an empty OS we simply return false.
01169   if (marked_empty())
01170     return false;
01171   if (!is_universe()) {
01172     // We use MIP_Problems to handle constraints that are not
01173     // octagonal difference.
01174     Optimization_Mode max_min = (maximize) ? MAXIMIZATION : MINIMIZATION;
01175     MIP_Problem mip(space_dim, constraints(), expr, max_min);
01176     if (mip.solve() == OPTIMIZED_MIP_PROBLEM) {
01177       g = mip.optimizing_point();
01178       mip.evaluate_objective_function(g, ext_n, ext_d);
01179       included = true;
01180       return true;
01181     }
01182   }
01183   // The `expr' is unbounded.
01184   return false;
01185 }

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 6296 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 >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_disjoint_from(), 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 >::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_higher_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), 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().

06297                                                                {
06298   std::ostringstream s;
06299   s << "PPL::Octagonal_Shape::" << method << ":\n"
06300     << "this->space_dimension() == " << space_dimension()
06301     << ", y->space_dimension() == " << y.space_dimension() << ".";
06302   throw std::invalid_argument(s.str());
06303 }

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

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

06309                                                                   {
06310   std::ostringstream s;
06311   s << "PPL::Octagonal_Shape::" << method << ":\n"
06312     << "this->space_dimension() == " << space_dimension()
06313     << ", required dimension == " << required_dim << ".";
06314   throw std::invalid_argument(s.str());
06315 }

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

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

06320                                                                             {
06321   std::ostringstream s;
06322   s << "PPL::Octagonal_Shape::" << method << ":\n"
06323     << "this->space_dimension() == " << space_dimension()
06324     << ", c->space_dimension == " << c.space_dimension() << ".";
06325   throw std::invalid_argument(s.str());
06326 }

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

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

06331                                                                              {
06332   std::ostringstream s;
06333   s << "PPL::Octagonal_Shape::" << method << ":\n"
06334     << "this->space_dimension() == " << space_dimension()
06335     << ", cg->space_dimension == " << cg.space_dimension() << ".";
06336   throw std::invalid_argument(s.str());
06337 }

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

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

06342                                                                            {
06343   std::ostringstream s;
06344   s << "PPL::Octagonal_Shape::" << method << ":\n"
06345     << "this->space_dimension() == " << space_dimension()
06346     << ", g->space_dimension == " << g.space_dimension() << ".";
06347   throw std::invalid_argument(s.str());
06348 }

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

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

06376                                                                  {
06377   std::ostringstream s;
06378   s << "PPL::Octagonal_Shape::" << method << ":\n"
06379     << "this->space_dimension() == " << space_dimension()
06380     << ", " << name_row << "->space_dimension() == "
06381     << y.space_dimension() << ".";
06382   throw std::invalid_argument(s.str());
06383 }

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

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

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

06352                                                                           {
06353   std::ostringstream s;
06354   s << "PPL::Octagonal_Shape::" << method << ":\n"
06355     << "the constraint is incompatible.";
06356   throw std::invalid_argument(s.str());
06357 }

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

06363                                                                  {
06364   using namespace IO_Operators;
06365   std::ostringstream s;
06366   s << "PPL::Octagonal_Shape::" << method << ":\n"
06367     << e << " is too complex.";
06368   throw std::invalid_argument(s.str());
06369 }

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


Friends And Related Function Documentation

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

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

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

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

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

00313                                                                      {
00314   if (x.space_dim != y.space_dim)
00315     // Dimension-incompatible OSs are different.
00316     return false;
00317 
00318   // Zero-dim OSs are equal if and only if they are both empty or universe.
00319   if (x.space_dim == 0) {
00320     if (x.marked_empty())
00321       return y.marked_empty();
00322     else
00323       return !y.marked_empty();
00324   }
00325 
00326   x.strong_closure_assign();
00327   y.strong_closure_assign();
00328   // If one of two octagons is empty, then they are equal if and only if
00329   // the other octagon is empty too.
00330   if (x.marked_empty())
00331     return y.marked_empty();
00332   if (y.marked_empty())
00333     return false;
00334   // Strong closure is a canonical form.
00335   return x.matrix == y.matrix;
00336 }

template<typename T>
template<typename Temp, typename To, typename U>
bool 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 T>
template<typename Temp, typename To, typename U>
bool 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>
template<typename Temp, typename To, typename U>
bool 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>
std::ostream & operator<< ( std::ostream &  s,
const Octagonal_Shape< T > &  x 
) [friend]

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

05998                                                                    {
05999   // Handle special cases first.
06000   if (x.marked_empty()) {
06001     s << "false";
06002     return s;
06003   }
06004   if (x.is_universe()) {
06005     s << "true";
06006     return s;
06007   }
06008 
06009   typedef typename Octagonal_Shape<T>::coefficient_type N;
06010   typedef typename OR_Matrix<N>::const_row_iterator Row_Iterator;
06011   typedef typename OR_Matrix<N>::const_row_reference_type Row_Reference;
06012 
06013   // Records whether or not we still have to print the first constraint.
06014   bool first = true;
06015 
06016   Row_Iterator m_begin = x.matrix.row_begin();
06017   Row_Iterator m_end = x.matrix.row_end();
06018 
06019   // Temporaries.
06020   DIRTY_TEMP(N, negation);
06021   DIRTY_TEMP(N, half);
06022   // Go through all the unary constraints.
06023   // (Note: loop iterator is incremented in the loop body.)
06024   for (Row_Iterator i_iter = m_begin; i_iter != m_end; ) {
06025     const dimension_type i = i_iter.index();
06026     const Variable v_i = Variable(i/2);
06027     const N& x_i_ii = (*i_iter)[i+1];
06028     ++i_iter;
06029     const N& x_ii_i = (*i_iter)[i];
06030     ++i_iter;
06031     // Check whether or not it is an equality constraint.
06032     if (is_additive_inverse(x_i_ii, x_ii_i)) {
06033       // It is an equality.
06034       assert(!is_plus_infinity(x_i_ii) && !is_plus_infinity(x_ii_i));
06035       if (first)
06036         first = false;
06037       else
06038         s << ", ";
06039       // If the value bound can NOT be divided by 2 exactly,
06040       // then we output the constraint `2*v_i == bound'.
06041       if (div2exp_assign_r(half, x_ii_i, 1, ROUND_UP) == V_EQ)
06042         s << v_i << " == " << half;
06043       else
06044         s << "2*" << v_i << " == " << x_ii_i;
06045     }
06046     else {
06047       // We will print unary non-strict inequalities, if any.
06048       if (!is_plus_infinity(x_i_ii)) {
06049         if (first)
06050           first = false;
06051         else
06052           s << ", ";
06053         neg_assign_r(negation, x_i_ii, ROUND_NOT_NEEDED);
06054         // If the value bound can NOT be divided by 2 exactly,
06055         // then we output the constraint `2*v_i >= negation'.
06056         if (div2exp_assign_r(half, negation, 1, ROUND_UP) == V_EQ)
06057           s << v_i << " >= " << half;
06058         else
06059           s << "2*" << v_i << " >= " << negation;
06060       }
06061       if (!is_plus_infinity(x_ii_i)) {
06062         if (first)
06063           first = false;
06064         else
06065           s << ", ";
06066         // If the value bound can NOT be divided by 2 exactly,
06067         // then we output the constraint `2*v_i <= bound'.
06068         if (div2exp_assign_r(half, x_ii_i, 1, ROUND_UP) == V_EQ)
06069           s << v_i << " <= " << half;
06070         else
06071           s << "2*" << v_i << " <= " << x_ii_i;
06072       }
06073     }
06074   }
06075 
06076   // Go through all the binary constraints.
06077   // (Note: loop iterator is incremented in the loop body.)
06078   for (Row_Iterator i_iter = m_begin; i_iter != m_end; ) {
06079     const dimension_type i = i_iter.index();
06080     const Variable v_i = Variable(i/2);
06081     Row_Reference r_i = *i_iter;
06082     ++i_iter;
06083     Row_Reference r_ii = *i_iter;
06084     ++i_iter;
06085 
06086     for (dimension_type j = 0; j < i; j += 2) {
06087       const Variable v_j = Variable(j/2);
06088       // Print binary differences.
06089       const N& x_ii_jj = r_ii[j+1];
06090       const N& x_i_j = r_i[j];
06091       // Check whether or not it is an equality constraint.
06092       if (is_additive_inverse(x_ii_jj, x_i_j)) {
06093         // It is an equality.
06094         assert(!is_plus_infinity(x_i_j) && !is_plus_infinity(x_ii_jj));
06095         if (first)
06096           first = false;
06097         else
06098           s << ", ";
06099         if (sgn(x_i_j) >= 0)
06100           s << v_j << " - " << v_i << " == " << x_i_j;
06101         else
06102           s << v_i << " - " << v_j << " == " << x_ii_jj;
06103       }
06104       else {
06105         // We will print non-strict inequalities, if any.
06106         if (!is_plus_infinity(x_i_j)) {
06107           if (first)
06108             first = false;
06109           else
06110             s << ", ";
06111           if (sgn(x_i_j) >= 0)
06112             s << v_j << " - " << v_i << " <= " << x_i_j;
06113           else {
06114             neg_assign_r(negation, x_i_j, ROUND_DOWN);
06115             s << v_i << " - " << v_j << " >= " << negation;
06116           }
06117         }
06118         if (!is_plus_infinity(x_ii_jj)) {
06119           if (first)
06120             first = false;
06121           else
06122             s << ", ";
06123           if (sgn(x_ii_jj) >= 0)
06124             s << v_i << " - " << v_j << " <= " << x_ii_jj;
06125           else {
06126             neg_assign_r(negation, x_ii_jj, ROUND_DOWN);
06127             s << v_j << " - " << v_i << " >= " << negation;
06128           }
06129         }
06130       }
06131       // Print binary sums.
06132       const N& x_i_jj = r_i[j+1];
06133       const N& x_ii_j = r_ii[j];
06134       // Check whether or not it is an equality constraint.
06135       if (is_additive_inverse(x_i_jj, x_ii_j)) {
06136         // It is an equality.
06137         assert(!is_plus_infinity(x_i_jj) && !is_plus_infinity(x_ii_j));
06138         if (first)
06139           first = false;
06140         else
06141           s << ", ";
06142         s << v_j << " + " << v_i << " == " << x_ii_j;
06143       }
06144       else {
06145         // We will print non-strict inequalities, if any.
06146         if (!is_plus_infinity(x_i_jj)) {
06147           if (first)
06148             first = false;
06149           else
06150             s << ", ";
06151           neg_assign_r(negation, x_i_jj, ROUND_DOWN);
06152           s << v_j << " + " << v_i << " >= " << negation;
06153         }
06154         if (!is_plus_infinity(x_ii_j)) {
06155           if (first)
06156             first = false;
06157           else
06158             s << ", ";
06159           s << v_j << " + " << v_i << " <= " << x_ii_j;
06160         }
06161       }
06162     }
06163   }
06164   return s;
06165 }

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

00341                                                                      {
00342   return !(x == y);
00343 }

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

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

00644                                                     {
00645   typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
00646   DIRTY_TEMP(Checked_Temp, tmp0);
00647   DIRTY_TEMP(Checked_Temp, tmp1);
00648   DIRTY_TEMP(Checked_Temp, tmp2);
00649   return rectilinear_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
00650 }

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 600 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, PLUS_INFINITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::rectilinear_distance_assign, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().

00606                                         {
00607   // Dimension-compatibility check.
00608   if (x.space_dim != y.space_dim)
00609     return false;
00610 
00611   // Zero-dim OSs are equal if and only if they are both empty or universe.
00612   if (x.space_dim == 0) {
00613     if (x.marked_empty() == y.marked_empty())
00614       assign_r(r, 0, ROUND_NOT_NEEDED);
00615     else
00616       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00617     return true;
00618   }
00619 
00620   // The distance computation requires strong closure.
00621   x.strong_closure_assign();
00622   y.strong_closure_assign();
00623 
00624   // If one of two OSs is empty, then they are equal if and only if
00625   // the other OS is empty too.
00626   if (x.marked_empty() ||  y.marked_empty()) {
00627    if (x.marked_empty() == y.marked_empty())
00628       assign_r(r, 0, ROUND_NOT_NEEDED);
00629     else
00630       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00631    return true;
00632   }
00633 
00634   return rectilinear_distance_assign(r, x.matrix, y.matrix, dir,
00635                                      tmp0, tmp1, tmp2);
00636 }

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

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

00709                                                   {
00710   typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
00711   DIRTY_TEMP(Checked_Temp, tmp0);
00712   DIRTY_TEMP(Checked_Temp, tmp1);
00713   DIRTY_TEMP(Checked_Temp, tmp2);
00714   return euclidean_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
00715 }

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

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

00671                                       {
00672   // Dimension-compatibility check.
00673   if (x.space_dim != y.space_dim)
00674     return false;
00675 
00676   // Zero-dim OSs are equal if and only if they are both empty or universe.
00677   if (x.space_dim == 0) {
00678     if (x.marked_empty() == y.marked_empty())
00679       assign_r(r, 0, ROUND_NOT_NEEDED);
00680     else
00681       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00682     return true;
00683   }
00684 
00685   // The distance computation requires strong closure.
00686   x.strong_closure_assign();
00687   y.strong_closure_assign();
00688 
00689   // If one of two OSs is empty, then they are equal if and only if
00690   // the other OS is empty too.
00691   if (x.marked_empty() ||  y.marked_empty()) {
00692    if (x.marked_empty() == y.marked_empty())
00693       assign_r(r, 0, ROUND_NOT_NEEDED);
00694     else
00695       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00696    return true;
00697   }
00698 
00699   return euclidean_distance_assign(r, x.matrix, y.matrix, dir,
00700                                    tmp0, tmp1, tmp2);
00701 }

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

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

00774                                                    {
00775   typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
00776   DIRTY_TEMP(Checked_Temp, tmp0);
00777   DIRTY_TEMP(Checked_Temp, tmp1);
00778   DIRTY_TEMP(Checked_Temp, tmp2);
00779   return l_infinity_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
00780 }

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

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

00736                                        {
00737   // Dimension-compatibility check.
00738   if (x.space_dim != y.space_dim)
00739     return false;
00740 
00741   // Zero-dim OSs are equal if and only if they are both empty or universe.
00742   if (x.space_dim == 0) {
00743     if (x.marked_empty() == y.marked_empty())
00744       assign_r(r, 0, ROUND_NOT_NEEDED);
00745     else
00746       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00747     return true;
00748   }
00749 
00750   // The distance computation requires strong closure.
00751   x.strong_closure_assign();
00752   y.strong_closure_assign();
00753 
00754   // If one of two OSs is empty, then they are equal if and only if
00755   // the other OS is empty too.
00756   if (x.marked_empty() ||  y.marked_empty()) {
00757    if (x.marked_empty() == y.marked_empty())
00758       assign_r(r, 0, ROUND_NOT_NEEDED);
00759     else
00760       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00761    return true;
00762   }
00763 
00764   return l_infinity_distance_assign(r, x.matrix, y.matrix, dir,
00765                                     tmp0, tmp1, tmp2);
00766 }

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

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

template<typename T>
dimension_type coherent_index ( dimension_type  i  )  [related]

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

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

00812                                                    {
00813   x.swap(y);
00814 }


Member Data Documentation

template<typename T>
OR_Matrix<N> Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix [private]

The matrix that represents the octagonal shape.

Definition at line 1620 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 >::ascii_load(), 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 >::compute_leaders(), Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_successors(), 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 >::deduce_minus_v_pm_u_bounds(), Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_v_pm_u_bounds(), 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 >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_binary_octagonal_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), 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 >::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_higher_space_dimensions(), 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_coherence_would_make_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign().

Dimension of the space of the octagonal shape.

Definition at line 1623 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 >::ascii_load(), 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 >::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 >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_binary_octagonal_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage(), 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 >::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_higher_space_dimensions(), 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_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]

template<typename T>
T Parma_Polyhedra_Library::Octagonal_Shape< T >::default_stop_points[] [static, private]

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


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

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