An octagonal shape. More...
#include <Octagonal_Shape.defs.hh>

Classes | |
| class | Status |
| A conjunctive assertion about a Octagonal_Shape<T> object. More... | |
Public Types | |
| typedef T | coefficient_type_base |
| The numeric base type upon which OSs are built. | |
| typedef N | coefficient_type |
| The (extended) numeric type of the inhomogeneous term of the inequalities defining an OS. | |
Public Member Functions | |
| void | ascii_dump () const |
Writes to std::cerr an ASCII representation of *this. | |
| void | ascii_dump (std::ostream &s) const |
Writes to s an ASCII representation of *this. | |
| void | print () const |
Prints *this to std::cerr using operator<<. | |
| bool | ascii_load (std::istream &s) |
Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this accordingly. Returns true if successful, false otherwise. | |
| memory_size_type | total_memory_in_bytes () const |
Returns the total size in bytes of the memory occupied by *this. | |
| memory_size_type | external_memory_in_bytes () const |
Returns the size in bytes of the memory managed by *this. | |
| int32_t | hash_code () const |
Returns a 32-bit hash code for *this. | |
Constructors, Assignment, Swap and Destructor | |
| Octagonal_Shape (dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE) | |
| Builds an universe or empty OS of the specified space dimension. | |
| Octagonal_Shape (const Octagonal_Shape &x, Complexity_Class complexity=ANY_COMPLEXITY) | |
| Ordinary copy constructor. | |
| template<typename U > | |
| Octagonal_Shape (const Octagonal_Shape< U > &y, Complexity_Class complexity=ANY_COMPLEXITY) | |
Builds a conservative, upward approximation of y. | |
| Octagonal_Shape (const Constraint_System &cs) | |
Builds an OS from the system of constraints cs. | |
| Octagonal_Shape (const Congruence_System &cgs) | |
| Builds an OS from a system of congruences. | |
| Octagonal_Shape (const Generator_System &gs) | |
Builds an OS from the system of generators gs. | |
| Octagonal_Shape (const Polyhedron &ph, Complexity_Class complexity=ANY_COMPLEXITY) | |
Builds an OS from the polyhedron ph. | |
| template<typename Interval > | |
| Octagonal_Shape (const Box< Interval > &box, Complexity_Class complexity=ANY_COMPLEXITY) | |
| Builds an OS out of a box. | |
| Octagonal_Shape (const Grid &grid, Complexity_Class complexity=ANY_COMPLEXITY) | |
| Builds an OS that approximates a grid. | |
| template<typename U > | |
| Octagonal_Shape (const BD_Shape< U > &bd, Complexity_Class complexity=ANY_COMPLEXITY) | |
| Builds an OS from a BD shape. | |
| Octagonal_Shape & | operator= (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 , if *this is empty; otherwise, returns the affine dimension of *this. | |
| Constraint_System | constraints () const |
Returns the system of constraints defining *this. | |
| Constraint_System | minimized_constraints () const |
Returns a minimized system of constraints defining *this. | |
| Congruence_System | congruences () const |
Returns a system of (equality) congruences satisfied by *this. | |
| Congruence_System | minimized_congruences () const |
Returns a minimal system of (equality) congruences satisfied by *this with the same affine dimension as *this. | |
| bool | contains (const Octagonal_Shape &y) const |
Returns true if and only if *this contains y. | |
| bool | strictly_contains (const Octagonal_Shape &y) const |
Returns true if and only if *this strictly contains y. | |
| bool | is_disjoint_from (const Octagonal_Shape &y) const |
Returns true if and only if *this and y are disjoint. | |
| Poly_Con_Relation | relation_with (const Constraint &c) const |
Returns the relations holding between *this and the constraint c. | |
| Poly_Con_Relation | relation_with (const Congruence &cg) const |
Returns the relations holding between *this and the congruence cg. | |
| Poly_Gen_Relation | relation_with (const Generator &g) const |
Returns the relations holding between *this and the generator g. | |
| bool | is_empty () const |
Returns true if and only if *this is an empty OS. | |
| bool | is_universe () const |
Returns true if and only if *this is a universe OS. | |
| bool | is_discrete () const |
Returns true if and only if *this is discrete. | |
| bool | is_bounded () const |
Returns true if and only if *this is a bounded OS. | |
| bool | is_topologically_closed () const |
Returns true if and only if *this is a topologically closed subset of the vector space. | |
| bool | contains_integer_point () const |
Returns true if and only if *this contains (at least) an integer point. | |
| bool | constrains (Variable var) const |
Returns true if and only if var is constrained in *this. | |
| bool | bounds_from_above (const Linear_Expression &expr) const |
Returns true if and only if expr is bounded from above in *this. | |
| bool | bounds_from_below (const Linear_Expression &expr) const |
Returns true if and only if expr is bounded from below in *this. | |
| bool | maximize (const Linear_Expression &expr, Coefficient &sup_n, Coefficient &sup_d, bool &maximum) const |
Returns true if and only if *this is not empty and expr is bounded from above in *this, in which case the supremum value is computed. | |
| bool | maximize (const Linear_Expression &expr, Coefficient &sup_n, Coefficient &sup_d, bool &maximum, Generator &g) const |
Returns true if and only if *this is not empty and expr is bounded from above in *this, in which case the supremum value and a point where expr reaches it are computed. | |
| bool | minimize (const Linear_Expression &expr, Coefficient &inf_n, Coefficient &inf_d, bool &minimum) const |
Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value is computed. | |
| bool | minimize (const Linear_Expression &expr, Coefficient &inf_n, Coefficient &inf_d, bool &minimum, Generator &g) const |
Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value and a point where expr reaches it are computed. | |
| bool | frequency (const Linear_Expression &expr, Coefficient &freq_n, Coefficient &freq_d, Coefficient &val_n, Coefficient &val_d) const |
Returns true if and only if there exist a unique value val such that *this saturates the equality expr = val. | |
| bool | OK () const |
| Checks if all the invariants are satisfied. | |
Space-Dimension Preserving Member Functions that May Modify the Octagonal_Shape | |
| void | add_constraint (const Constraint &c) |
Adds a copy of constraint c to the system of constraints defining *this. | |
| void | add_constraints (const Constraint_System &cs) |
Adds the constraints in cs to the system of constraints defining *this. | |
| void | add_recycled_constraints (Constraint_System &cs) |
Adds the constraints in cs to the system of constraints of *this. | |
| void | add_congruence (const Congruence &cg) |
Adds to *this a constraint equivalent to the congruence cg. | |
| void | add_congruences (const Congruence_System &cgs) |
Adds to *this constraints equivalent to the congruences in cgs. | |
| void | add_recycled_congruences (Congruence_System &cgs) |
Adds to *this constraints equivalent to the congruences in cgs. | |
| void | refine_with_constraint (const Constraint &c) |
Uses a copy of constraint c to refine the system of octagonal constraints defining *this. | |
| void | refine_with_congruence (const Congruence &cg) |
Uses a copy of congruence cg to refine the system of octagonal constraints of *this. | |
| void | refine_with_constraints (const Constraint_System &cs) |
Uses a copy of the constraints in cs to refine the system of octagonal constraints defining *this. | |
| void | refine_with_congruences (const Congruence_System &cgs) |
Uses a copy of the congruences in cgs to refine the system of octagonal constraints defining *this. | |
| void | unconstrain (Variable var) |
Computes the cylindrification of *this with respect to space dimension var, assigning the result to *this. | |
| void | unconstrain (const Variables_Set &vars) |
Computes the cylindrification of *this with respect to the set of space dimensions vars, assigning the result to *this. | |
| void | intersection_assign (const Octagonal_Shape &y) |
Assigns to *this the intersection of *this and y. | |
| void | upper_bound_assign (const Octagonal_Shape &y) |
Assigns to *this the smallest OS that contains the convex union of *this and y. | |
| bool | upper_bound_assign_if_exact (const Octagonal_Shape &y) |
If the upper bound of *this and y is exact, it is assigned to *this and true is returned, otherwise false is returned. | |
| bool | integer_upper_bound_assign_if_exact (const Octagonal_Shape &y) |
If the integer upper bound of *this and y is exact, it is assigned to *this and true is returned; otherwise false is returned. | |
| void | difference_assign (const Octagonal_Shape &y) |
Assigns to *this the smallest octagon containing the set difference of *this and y. | |
| bool | simplify_using_context_assign (const Octagonal_Shape &y) |
Assigns to *this a meet-preserving simplification of *this with respect to y. If false is returned, then the intersection is empty. | |
| void | affine_image (Variable var, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one()) |
Assigns to *this the affine image of *this under the function mapping variable var into the affine expression specified by expr and denominator. | |
| void | affine_preimage (Variable var, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one()) |
Assigns to *this the affine preimage of *this under the function mapping variable var into the affine expression specified by expr and denominator. | |
| void | generalized_affine_image (Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one()) |
Assigns to *this the image of *this with respect to the generalized affine transfer function , where 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 , where 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 . | |
| 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 , where 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 , where 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 . | |
| void | time_elapse_assign (const Octagonal_Shape &y) |
Assigns to *this the result of computing the time-elapse between *this and y. | |
| void | wrap_assign (const Variables_Set &vars, Bounded_Integer_Type_Width w, Bounded_Integer_Type_Representation r, Bounded_Integer_Type_Overflow o, const Constraint_System *pcs=0, unsigned complexity_threshold=16, bool wrap_individually=true) |
| Wraps the specified dimensions of the vector space. | |
| void | drop_some_non_integer_points (Complexity_Class complexity=ANY_COMPLEXITY) |
Possibly tightens *this by dropping some points with non-integer coordinates. | |
| void | drop_some_non_integer_points (const Variables_Set &vars, Complexity_Class complexity=ANY_COMPLEXITY) |
Possibly tightens *this by dropping some points with non-integer coordinates for the space dimensions corresponding to vars. | |
| void | topological_closure_assign () |
Assigns to *this its topological closure. | |
| void | CC76_extrapolation_assign (const Octagonal_Shape &y, unsigned *tp=0) |
Assigns to *this the result of computing the CC76-extrapolation between *this and y. | |
| template<typename Iterator > | |
| void | CC76_extrapolation_assign (const Octagonal_Shape &y, Iterator first, Iterator last, unsigned *tp=0) |
Assigns to *this the result of computing the CC76-extrapolation between *this and y. | |
| void | BHMZ05_widening_assign (const Octagonal_Shape &y, unsigned *tp=0) |
Assigns to *this the result of computing the BHMZ05-widening between *this and y. | |
| void | widening_assign (const Octagonal_Shape &y, unsigned *tp=0) |
| Same as BHMZ05_widening_assign(y, tp). | |
| void | limited_BHMZ05_extrapolation_assign (const Octagonal_Shape &y, const Constraint_System &cs, unsigned *tp=0) |
Improves the result of the BHMZ05-widening computation by also enforcing those constraints in cs that are satisfied by all the points of *this. | |
| void | CC76_narrowing_assign (const Octagonal_Shape &y) |
Restores from y the constraints of *this, lost by CC76-extrapolation applications. | |
| void | limited_CC76_extrapolation_assign (const Octagonal_Shape &y, const Constraint_System &cs, unsigned *tp=0) |
Improves the result of the CC76-extrapolation computation by also enforcing those constraints in cs that are satisfied by all the points of *this. | |
Member Functions that May Modify the Dimension of the Vector Space | |
| void | add_space_dimensions_and_embed (dimension_type m) |
Adds m new dimensions and embeds the old OS into the new space. | |
| void | add_space_dimensions_and_project (dimension_type m) |
Adds m new dimensions to the OS and does not embed it in the new space. | |
| void | concatenate_assign (const Octagonal_Shape &y) |
Assigns to *this the concatenation of *this and y, taken in this order. | |
| void | remove_space_dimensions (const Variables_Set &vars) |
| Removes all the specified dimensions. | |
| void | remove_higher_space_dimensions (dimension_type new_dimension) |
Removes the higher dimensions so that the resulting space will have dimension new_dimension. | |
| template<typename Partial_Function > | |
| void | map_space_dimensions (const Partial_Function &pfunc) |
| Remaps the dimensions of the vector space according to a partial function. | |
| void | expand_space_dimension (Variable var, dimension_type m) |
Creates m copies of the space dimension corresponding to var. | |
| void | fold_space_dimensions (const Variables_Set &vars, Variable dest) |
Folds the space dimensions in vars into dest. | |
| template<typename Interval_Info > | |
| void | refine_fp_interval_abstract_store (Box< Interval< T, Interval_Info > > &store) const |
Refines store with the constraints defining *this. | |
Static Public Member Functions | |
| static dimension_type | max_space_dimension () |
| Returns the maximum space dimension that an OS can handle. | |
| static bool | can_recycle_constraint_systems () |
| Returns false indicating that this domain cannot recycle constraints. | |
| static bool | can_recycle_congruence_systems () |
| Returns false indicating that this domain cannot recycle congruences. | |
Private Types | |
| typedef Checked_Number< T, Debug_WRD_Extended_Number_Policy > | N |
| The (extended) numeric type of the inhomogeneous term of the inequalities defining an OS. | |
Private Member Functions | |
| bool | marked_zero_dim_univ () const |
Returns true if the OS is the zero-dimensional universe. | |
| bool | marked_empty () const |
Returns true if the OS is known to be empty. | |
| bool | marked_strongly_closed () const |
Returns true if this->matrix is known to be strongly closed. | |
| void | set_zero_dim_univ () |
Turns *this into a zero-dimensional universe OS. | |
| void | set_empty () |
Turns *this into an empty OS. | |
| void | set_strongly_closed () |
Marks *this as strongly closed. | |
| void | reset_strongly_closed () |
Marks *this as possibly not strongly closed. | |
| N & | matrix_at (dimension_type i, dimension_type j) |
| const N & | matrix_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 . | |
| void | forget_all_octagonal_constraints (dimension_type v_id) |
Removes all the constraints on variable v_id. | |
| void | forget_binary_octagonal_constraints (dimension_type v_id) |
Removes all binary constraints on variable v_id. | |
| void | deduce_v_pm_u_bounds (dimension_type v_id, dimension_type last_id, const Linear_Expression &sc_expr, Coefficient_traits::const_reference sc_den, const N &ub_v) |
| An helper function for the computation of affine relations. | |
| void | deduce_minus_v_pm_u_bounds (dimension_type v, dimension_type last_v, const Linear_Expression &sc_expr, Coefficient_traits::const_reference sc_den, const N &minus_lb_v) |
| An helper function for the computation of affine relations. | |
| void | get_limiting_octagon (const Constraint_System &cs, Octagonal_Shape &limiting_octagon) const |
Adds to limiting_octagon the octagonal differences in cs that are satisfied by *this. | |
| void | compute_successors (std::vector< dimension_type > &successor) const |
| Compute the (zero-equivalence classes) successor relation. | |
| void | compute_leaders (std::vector< dimension_type > &successor, std::vector< dimension_type > &no_sing_leaders, bool &exist_sing_class, dimension_type &sing_leader) const |
| Compute the leaders of zero-equivalence classes. | |
| void | compute_leaders (std::vector< dimension_type > &leaders) const |
| Compute the leaders of zero-equivalence classes. | |
| void | non_redundant_matrix_entries (std::vector< Bit_Row > &non_redundant) const |
Stores into non_redundant information about the matrix entries that are non-redundant (i.e., will occur in strongly reduced matrix). | |
| void | strong_reduction_assign () const |
Removes the redundant constraints from this->matrix. | |
| bool | is_strongly_reduced () const |
Returns true if and only if this->matrix is strongly reduced. | |
| bool | is_strong_coherent () const |
Returns true if in the octagon taken two at a time unary constraints, there is also the constraint that represent their sum. | |
| bool | tight_coherence_would_make_empty () const |
| void | strong_closure_assign () const |
Assigns to this->matrix its strong closure. | |
| void | strong_coherence_assign () |
Applies the strong-coherence step to this->matrix. | |
| void | tight_closure_assign () |
Assigns to this->matrix its tight closure. | |
| void | incremental_strong_closure_assign (Variable var) const |
Incrementally computes strong closure, assuming that only constraints affecting variable var need to be considered. | |
| bool | bounds (const Linear_Expression &expr, bool from_above) const |
Checks if and how expr is bounded in *this. | |
| bool | max_min (const Linear_Expression &expr, bool maximize, Coefficient &ext_n, Coefficient &ext_d, bool &included) const |
Maximizes or minimizes expr subject to *this. | |
| bool | max_min (const Linear_Expression &expr, bool maximize, Coefficient &ext_n, Coefficient &ext_d, bool &included, Generator &g) const |
Maximizes or minimizes expr subject to *this. | |
| void | drop_some_non_integer_points_helper (N &elem) |
Exception Throwers | |
| void | throw_dimension_incompatible (const char *method, const Octagonal_Shape &x) const |
| void | throw_dimension_incompatible (const char *method, dimension_type required_dim) const |
| void | throw_dimension_incompatible (const char *method, const Constraint &c) const |
| void | throw_dimension_incompatible (const char *method, const Congruence &cg) const |
| void | throw_dimension_incompatible (const char *method, const Generator &g) const |
| void | throw_dimension_incompatible (const char *method, const char *name_row, const Linear_Expression &y) const |
| void | throw_constraint_incompatible (const char *method) const |
| void | throw_expression_too_complex (const char *method, const Linear_Expression &e) const |
| void | throw_generic (const char *method, const char *reason) const |
Private Attributes | |
| OR_Matrix< N > | matrix |
| The matrix that represents the octagonal shape. | |
| dimension_type | space_dim |
| Dimension of the space of the octagonal shape. | |
| Status | status |
| The status flags to keep track of the internal state. | |
Static Private Attributes | |
| static T | default_stop_points [] |
Friends | |
| class | Parma_Polyhedra_Library::Octagonal_Shape |
| class | Parma_Polyhedra_Library::Box |
| bool | operator== (const Octagonal_Shape< T > &x, const Octagonal_Shape< T > &y) |
Returns true if and only if x and y are the same octagon. | |
| template<typename Temp , typename To , typename U > | |
| bool | Parma_Polyhedra_Library::rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Octagonal_Shape< U > &x, const Octagonal_Shape< U > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2) |
| template<typename Temp , typename To , typename U > | |
| bool | Parma_Polyhedra_Library::euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Octagonal_Shape< U > &x, const Octagonal_Shape< U > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2) |
| template<typename Temp , typename To , typename U > | |
| bool | Parma_Polyhedra_Library::l_infinity_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Octagonal_Shape< U > &x, const Octagonal_Shape< U > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2) |
| std::ostream & | Parma_Polyhedra_Library::IO_Operators::operator<< (std::ostream &s, const Octagonal_Shape< T > &c) |
Related Functions | |
(Note that these are not member functions.) | |
| template<typename T > | |
| std::ostream & | operator<< (std::ostream &s, const Octagonal_Shape< T > &oct) |
| Output operator. | |
| template<typename T > | |
| bool | operator!= (const Octagonal_Shape< T > &x, const Octagonal_Shape< T > &y) |
Returns true if and only if x and y are different shapes. | |
| template<typename To , typename T > | |
| bool | rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Octagonal_Shape< T > &x, const Octagonal_Shape< T > &y, Rounding_Dir dir) |
Computes the rectilinear (or Manhattan) distance between x and y. | |
| template<typename Temp , typename To , typename T > | |
| bool | rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Octagonal_Shape< T > &x, const Octagonal_Shape< T > &y, Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2) |
Computes the rectilinear (or Manhattan) distance between x and y. | |
| template<typename To , typename T > | |
| bool | euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Octagonal_Shape< T > &x, const Octagonal_Shape< T > &y, Rounding_Dir dir) |
Computes the euclidean distance between x and y. | |
| template<typename Temp , typename To , typename T > | |
| bool | euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Octagonal_Shape< T > &x, const Octagonal_Shape< T > &y, Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2) |
Computes the euclidean distance between x and y. | |
| template<typename To , typename T > | |
| bool | l_infinity_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Octagonal_Shape< T > &x, const Octagonal_Shape< T > &y, Rounding_Dir dir) |
Computes the 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 distance between x and y. | |
| bool | extract_octagonal_difference (const Constraint &c, dimension_type c_space_dim, dimension_type &c_num_vars, dimension_type &c_first_var, dimension_type &c_second_var, Coefficient &c_coeff, Coefficient &c_term) |
Decodes the constraint c as an octagonal difference. | |
| template<typename T > | |
| void | swap (Parma_Polyhedra_Library::Octagonal_Shape< T > &x, Parma_Polyhedra_Library::Octagonal_Shape< T > &y) |
Specializes std::swap. | |
| dimension_type | coherent_index (const dimension_type i) |
Returns the index coherent to i. | |
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
where
and
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
, as well as rounding-aware implementations for several arithmetic functions. The value of the type parameter T may be one of the following:
int32_t or int64_t);float or double);mpz_class or mpq_class).The user interface for OSs is meant to be as similar as possible to the one developed for the polyhedron class C_Polyhedron.
The OS domain optimally supports:
Depending on the method, using a constraint or congruence that is not optimally supported by the domain will either raise an exception or result in a (possibly non-optimal) upward approximation.
A constraint is octagonal if it has the form
where
and
,
,
are integer coefficients such that
, or
, or
. The user is warned that the above octagonal Constraint object will be mapped into a correct and optimal approximation that, depending on the expressive power of the chosen template argument T, may loose some precision. Also note that strict constraints are not octagonal.
For instance, a Constraint object encoding
will be approximated by:
, if T is a (bounded or unbounded) integer type;
, if T is the unbounded rational type mpq_class;
, where
, if T is a floating point type (having no exact representation for
).On the other hand, depending from the context, a Constraint object encoding
will be either upward approximated (e.g., by safely ignoring it) or it will cause an exception.
In the following examples it is assumed that the type argument T is one of the possible instances listed above and that variables x, y and z are defined (where they are used) as follows:
Variable x(0);
Variable y(1);
Variable z(2);
, 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);
Constraint_System cs;
cs.insert(x >= 0);
cs.insert(x <= 3);
cs.insert(y >= 0);
cs.insert(y <= 3);
cs.insert(z >= 0);
cs.insert(z <= 3);
cs.insert(x - 3*y <= 5); // (7)
cs.insert(x - y + z <= 5); // (8)
cs.insert(x + y + z <= 5); // (9)
Octagonal_Shape<T> oct(cs);
Definition at line 408 of file Octagonal_Shape.defs.hh.
| typedef N Parma_Polyhedra_Library::Octagonal_Shape< T >::coefficient_type |
The (extended) numeric type of the inhomogeneous term of the inequalities defining an OS.
Definition at line 429 of file Octagonal_Shape.defs.hh.
| typedef T Parma_Polyhedra_Library::Octagonal_Shape< T >::coefficient_type_base |
The numeric base type upon which OSs are built.
Definition at line 423 of file Octagonal_Shape.defs.hh.
typedef Checked_Number<T, Debug_WRD_Extended_Number_Policy> Parma_Polyhedra_Library::Octagonal_Shape< T >::N [private] |
The (extended) numeric type of the inhomogeneous term of the inequalities defining an OS.
Definition at line 415 of file Octagonal_Shape.defs.hh.
| 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.
| num_dimensions | The number of dimensions of the vector space enclosing the OS; | |
| kind | Specifies whether the universe or the empty OS has to be built. |
Definition at line 108 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape().
| Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape | ( | const Octagonal_Shape< T > & | x, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline] |
Ordinary copy constructor.
The complexity argument is ignored.
Definition at line 121 of file Octagonal_Shape.inlines.hh.
| Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape | ( | const Octagonal_Shape< U > & | y, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline, explicit] |
Builds a conservative, upward approximation of y.
The complexity argument is ignored.
Definition at line 128 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_zero_dim_univ(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::set_zero_dim_univ().
00132 : matrix((y.strong_closure_assign(), y.matrix)), 00133 space_dim(y.space_dim), 00134 status() { 00135 // TODO: handle flags properly, possibly taking special cases into account. 00136 if (y.marked_empty()) 00137 set_empty(); 00138 else if (y.marked_zero_dim_univ()) 00139 set_zero_dim_univ(); 00140 }
| 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.
| cs | A system of octagonal constraints. |
| std::invalid_argument | Thrown if cs contains a constraint which is not optimally supported by the Octagonal shape domain. |
Definition at line 144 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), and Parma_Polyhedra_Library::Constraint_System::space_dimension().
00145 : matrix(cs.space_dimension()), 00146 space_dim(cs.space_dimension()), 00147 status() { 00148 if (cs.space_dimension() > 0) 00149 // A (non zero-dim) universe octagon is strongly closed. 00150 set_strongly_closed(); 00151 add_constraints(cs); 00152 }
| 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
| cgs | A system of congruences. |
| std::invalid_argument | Thrown if cgs contains a congruence which is not optimally supported by the Octagonal shape domain. |
Definition at line 156 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), and Parma_Polyhedra_Library::Congruence_System::space_dimension().
00157 : matrix(cgs.space_dimension()), 00158 space_dim(cgs.space_dimension()), 00159 status() { 00160 if (cgs.space_dimension() > 0) 00161 // A (non zero-dim) universe octagon is strongly closed. 00162 set_strongly_closed(); 00163 add_congruences(cgs); 00164 }
| 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.
| std::invalid_argument | Thrown if the system of generators is not empty but has no points. |
Definition at line 198 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Generator_System::begin(), Parma_Polyhedra_Library::Generator::CLOSURE_POINT, Parma_Polyhedra_Library::Generator::coefficient(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Generator::divisor(), Parma_Polyhedra_Library::Generator_System::end(), Parma_Polyhedra_Library::Generator::LINE, Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::max_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::Generator::POINT, Parma_Polyhedra_Library::Generator::RAY, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic(), and Parma_Polyhedra_Library::Generator::type().
00199 : matrix(gs.space_dimension()), 00200 space_dim(gs.space_dimension()), 00201 status() { 00202 const Generator_System::const_iterator gs_begin = gs.begin(); 00203 const Generator_System::const_iterator gs_end = gs.end(); 00204 if (gs_begin == gs_end) { 00205 // An empty generator system defines the empty polyhedron. 00206 set_empty(); 00207 return; 00208 } 00209 00210 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 00211 typename OR_Matrix<N>::row_iterator mat_begin = matrix.row_begin(); 00212 00213 PPL_DIRTY_TEMP(N, tmp); 00214 bool mat_initialized = false; 00215 bool point_seen = false; 00216 // Going through all the points and closure points. 00217 for (Generator_System::const_iterator k = gs_begin; k != gs_end; ++k) { 00218 const Generator& g = *k; 00219 switch (g.type()) { 00220 case Generator::POINT: 00221 point_seen = true; 00222 // Intentionally fall through. 00223 case Generator::CLOSURE_POINT: 00224 if (!mat_initialized) { 00225 // When handling the first (closure) point, we initialize the matrix. 00226 mat_initialized = true; 00227 const Coefficient& d = g.divisor(); 00228 for (dimension_type i = 0; i < space_dim; ++i) { 00229 const Coefficient& g_i = g.coefficient(Variable(i)); 00230 const dimension_type di = 2*i; 00231 Row_Reference x_i = *(mat_begin+di); 00232 Row_Reference x_ii = *(mat_begin+di+1); 00233 for (dimension_type j = 0; j < i; ++j) { 00234 const Coefficient& g_j = g.coefficient(Variable(j)); 00235 const dimension_type dj = 2*j; 00236 // Set for any point the hyperplanes passing in the point 00237 // and having the octagonal gradient. 00238 // Let be P = [P_1, P_2, ..., P_n] point. 00239 // Hyperplanes: X_i - X_j = P_i - P_j. 00240 div_round_up(x_i[dj], g_j - g_i, d); 00241 div_round_up(x_ii[dj+1], g_i - g_j, d); 00242 // Hyperplanes: X_i + X_j = P_i + P_j. 00243 div_round_up(x_i[dj+1], -g_j - g_i, d); 00244 div_round_up(x_ii[dj], g_i + g_j, d); 00245 } 00246 // Hyperplanes: X_i = P_i. 00247 div_round_up(x_i[di+1], -g_i - g_i, d); 00248 div_round_up(x_ii[di], g_i + g_i, d); 00249 } 00250 } 00251 else { 00252 // This is not the first point: the matrix already contains 00253 // valid values and we must compute maxima. 00254 const Coefficient& d = g.divisor(); 00255 for (dimension_type i = 0; i < space_dim; ++i) { 00256 const Coefficient& g_i = g.coefficient(Variable(i)); 00257 const dimension_type di = 2*i; 00258 Row_Reference x_i = *(mat_begin+di); 00259 Row_Reference x_ii = *(mat_begin+di+1); 00260 for (dimension_type j = 0; j < i; ++j) { 00261 const Coefficient& g_j = g.coefficient(Variable(j)); 00262 const dimension_type dj = 2*j; 00263 // Set for any point the straight lines passing in the point 00264 // and having the octagonal gradient; compute maxima values. 00265 // Let be P = [P_1, P_2, ..., P_n] point. 00266 // Hyperplane: X_i - X_j = max (P_i - P_j, const). 00267 div_round_up(tmp, g_j - g_i, d); 00268 max_assign(x_i[dj], tmp); 00269 div_round_up(tmp, g_i - g_j, d); 00270 max_assign(x_ii[dj+1], tmp); 00271 // Hyperplane: X_i + X_j = max (P_i + P_j, const). 00272 div_round_up(tmp, -g_j - g_i, d); 00273 max_assign(x_i[dj+1], tmp); 00274 div_round_up(tmp, g_i + g_j, d); 00275 max_assign(x_ii[dj], tmp); 00276 } 00277 // Hyperplane: X_i = max (P_i, const). 00278 div_round_up(tmp, -g_i - g_i, d); 00279 max_assign(x_i[di+1], tmp); 00280 div_round_up(tmp, g_i + g_i, d); 00281 max_assign(x_ii[di], tmp); 00282 } 00283 } 00284 break; 00285 default: 00286 // Lines and rays temporarily ignored. 00287 break; 00288 } 00289 } 00290 00291 if (!point_seen) 00292 // The generator system is not empty, but contains no points. 00293 throw_generic("Octagonal_Shape(gs)", 00294 "the non-empty generator system gs contains no points."); 00295 00296 // Going through all the lines and rays. 00297 for (Generator_System::const_iterator k = gs_begin; k != gs_end; ++k) { 00298 const Generator& g = *k; 00299 switch (g.type()) { 00300 case Generator::LINE: 00301 for (dimension_type i = 0; i < space_dim; ++i) { 00302 const Coefficient& g_i = g.coefficient(Variable(i)); 00303 const dimension_type di = 2*i; 00304 Row_Reference x_i = *(mat_begin+di); 00305 Row_Reference x_ii = *(mat_begin+di+1); 00306 for (dimension_type j = 0; j < i; ++j) { 00307 const Coefficient& g_j = g.coefficient(Variable(j)); 00308 const dimension_type dj = 2*j; 00309 // Set for any line the right limit. 00310 if (g_i != g_j) { 00311 // Hyperplane: X_i - X_j <=/>= +Inf. 00312 assign_r(x_i[dj], PLUS_INFINITY, ROUND_NOT_NEEDED); 00313 assign_r(x_ii[dj+1], PLUS_INFINITY, ROUND_NOT_NEEDED); 00314 } 00315 if (g_i != -g_j) { 00316 // Hyperplane: X_i + X_j <=/>= +Inf. 00317 assign_r(x_i[dj+1], PLUS_INFINITY, ROUND_NOT_NEEDED); 00318 assign_r(x_ii[dj], PLUS_INFINITY, ROUND_NOT_NEEDED); 00319 } 00320 } 00321 if (g_i != 0) { 00322 // Hyperplane: X_i <=/>= +Inf. 00323 assign_r(x_i[di+1], PLUS_INFINITY, ROUND_NOT_NEEDED); 00324 assign_r(x_ii[di], PLUS_INFINITY, ROUND_NOT_NEEDED); 00325 } 00326 } 00327 break; 00328 case Generator::RAY: 00329 for (dimension_type i = 0; i < space_dim; ++i) { 00330 const Coefficient& g_i = g.coefficient(Variable(i)); 00331 const dimension_type di = 2*i; 00332 Row_Reference x_i = *(mat_begin+di); 00333 Row_Reference x_ii = *(mat_begin+di+1); 00334 for (dimension_type j = 0; j < i; ++j) { 00335 const Coefficient& g_j = g.coefficient(Variable(j)); 00336 const dimension_type dj = 2*j; 00337 // Set for any ray the right limit in the case 00338 // of the binary constraints. 00339 if (g_i < g_j) 00340 // Hyperplane: X_i - X_j >= +Inf. 00341 assign_r(x_i[dj], PLUS_INFINITY, ROUND_NOT_NEEDED); 00342 if (g_i > g_j) 00343 // Hyperplane: X_i - X_j <= +Inf. 00344 assign_r(x_ii[dj+1], PLUS_INFINITY, ROUND_NOT_NEEDED); 00345 if (g_i < -g_j) 00346 // Hyperplane: X_i + X_j >= +Inf. 00347 assign_r(x_i[dj+1], PLUS_INFINITY, ROUND_NOT_NEEDED); 00348 if (g_i > -g_j) 00349 // Hyperplane: X_i + X_j <= +Inf. 00350 assign_r(x_ii[dj], PLUS_INFINITY, ROUND_NOT_NEEDED); 00351 } 00352 // Case: unary constraints. 00353 if (g_i < 0) 00354 // Hyperplane: X_i = +Inf. 00355 assign_r(x_i[di+1], PLUS_INFINITY, ROUND_NOT_NEEDED); 00356 if (g_i > 0) 00357 // Hyperplane: X_i = +Inf. 00358 assign_r(x_ii[di], PLUS_INFINITY, ROUND_NOT_NEEDED); 00359 } 00360 break; 00361 default: 00362 // Points and closure points already dealt with. 00363 break; 00364 } 00365 } 00366 set_strongly_closed(); 00367 PPL_ASSERT(OK()); 00368 }
| Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape | ( | const Polyhedron & | ph, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline, explicit] |
Builds an OS from the polyhedron ph.
Builds an OS containing ph using algorithms whose complexity does not exceed the one specified by complexity. If complexity is ANY_COMPLEXITY, then the OS built is the smallest one containing ph.
Definition at line 44 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::MIP_Problem::add_constraint(), Parma_Polyhedra_Library::MIP_Problem::add_constraints(), Parma_Polyhedra_Library::ANY_COMPLEXITY, Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Polyhedron::con_sys, Parma_Polyhedra_Library::Polyhedron::constraints(), Parma_Polyhedra_Library::Polyhedron::constraints_are_minimized(), Parma_Polyhedra_Library::Polyhedron::constraints_are_up_to_date(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::MIP_Problem::evaluate_objective_function(), Parma_Polyhedra_Library::Polyhedron::generators(), Parma_Polyhedra_Library::Polyhedron::generators_are_up_to_date(), Parma_Polyhedra_Library::Polyhedron::has_pending_constraints(), Parma_Polyhedra_Library::Polyhedron::has_something_pending(), Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::MIP_Problem::is_satisfiable(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Polyhedron::is_universe(), Parma_Polyhedra_Library::Polyhedron::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, Parma_Polyhedra_Library::MIP_Problem::optimizing_point(), Parma_Polyhedra_Library::POLYNOMIAL_COMPLEXITY, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::MIP_Problem::set_objective_function(), Parma_Polyhedra_Library::MIP_Problem::set_optimization_mode(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), Parma_Polyhedra_Library::SIMPLEX_COMPLEXITY, Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::Polyhedron::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.
00046 : matrix(0), space_dim(0), status() { 00047 const dimension_type num_dimensions = ph.space_dimension(); 00048 00049 if (ph.marked_empty()) { 00050 *this = Octagonal_Shape(num_dimensions, EMPTY); 00051 return; 00052 } 00053 00054 if (num_dimensions == 0) { 00055 *this = Octagonal_Shape(num_dimensions, UNIVERSE); 00056 return; 00057 } 00058 00059 // Build from generators when we do not care about complexity 00060 // or when the process has polynomial complexity. 00061 if (complexity == ANY_COMPLEXITY 00062 || (!ph.has_pending_constraints() && ph.generators_are_up_to_date())) { 00063 *this = Octagonal_Shape(ph.generators()); 00064 return; 00065 } 00066 00067 // We cannot afford exponential complexity, we do not have a complete set 00068 // of generators for the polyhedron, and the polyhedron is not trivially 00069 // empty or zero-dimensional. Constraints, however, are up to date. 00070 PPL_ASSERT(ph.constraints_are_up_to_date()); 00071 00072 if (!ph.has_something_pending() && ph.constraints_are_minimized()) { 00073 // If the constraint system of the polyhedron is minimized, 00074 // the test `is_universe()' has polynomial complexity. 00075 if (ph.is_universe()) { 00076 *this = Octagonal_Shape(num_dimensions, UNIVERSE); 00077 return; 00078 } 00079 } 00080 00081 // See if there is at least one inconsistent constraint in `ph.con_sys'. 00082 for (Constraint_System::const_iterator i = ph.con_sys.begin(), 00083 cs_end = ph.con_sys.end(); i != cs_end; ++i) 00084 if (i->is_inconsistent()) { 00085 *this = Octagonal_Shape(num_dimensions, EMPTY); 00086 return; 00087 } 00088 00089 // If `complexity' allows it, use simplex to derive the exact (modulo 00090 // the fact that our OSs are topologically closed) variable bounds. 00091 if (complexity == SIMPLEX_COMPLEXITY) { 00092 MIP_Problem lp(num_dimensions); 00093 lp.set_optimization_mode(MAXIMIZATION); 00094 00095 const Constraint_System& ph_cs = ph.constraints(); 00096 if (!ph_cs.has_strict_inequalities()) 00097 lp.add_constraints(ph_cs); 00098 else 00099 // Adding to `lp' a topologically closed version of `ph_cs'. 00100 for (Constraint_System::const_iterator i = ph_cs.begin(), 00101 ph_cs_end = ph_cs.end(); i != ph_cs_end; ++i) { 00102 const Constraint& c = *i; 00103 if (c.is_strict_inequality()) 00104 lp.add_constraint(Linear_Expression(c) >= 0); 00105 else 00106 lp.add_constraint(c); 00107 } 00108 00109 // Check for unsatisfiability. 00110 if (!lp.is_satisfiable()) { 00111 *this = Octagonal_Shape<T>(num_dimensions, EMPTY); 00112 return; 00113 } 00114 00115 // Start with a universe OS that will be refined by the simplex. 00116 *this = Octagonal_Shape<T>(num_dimensions, UNIVERSE); 00117 // Get all the upper bounds. 00118 Generator g(point()); 00119 PPL_DIRTY_TEMP_COEFFICIENT(num); 00120 PPL_DIRTY_TEMP_COEFFICIENT(den); 00121 for (dimension_type i = 0; i < num_dimensions; ++i) { 00122 Variable x(i); 00123 // Evaluate optimal upper bound for `x <= ub'. 00124 lp.set_objective_function(x); 00125 if (lp.solve() == OPTIMIZED_MIP_PROBLEM) { 00126 g = lp.optimizing_point(); 00127 lp.evaluate_objective_function(g, num, den); 00128 num *= 2; 00129 div_round_up(matrix[2*i+1][2*i], num, den); 00130 } 00131 // Evaluate optimal upper bounds for `x + y <= ub'. 00132 for (dimension_type j = 0; j < i; ++j) { 00133 Variable y(j); 00134 lp.set_objective_function(x + y); 00135 if (lp.solve() == OPTIMIZED_MIP_PROBLEM) { 00136 g = lp.optimizing_point(); 00137 lp.evaluate_objective_function(g, num, den); 00138 div_round_up(matrix[2*i+1][2*j], num, den); 00139 } 00140 } 00141 // Evaluate optimal upper bound for `x - y <= ub'. 00142 for (dimension_type j = 0; j < num_dimensions; ++j) { 00143 if (i == j) 00144 continue; 00145 Variable y(j); 00146 lp.set_objective_function(x - y); 00147 if (lp.solve() == OPTIMIZED_MIP_PROBLEM) { 00148 g = lp.optimizing_point(); 00149 lp.evaluate_objective_function(g, num, den); 00150 div_round_up((i < j ? matrix[2*j][2*i] : matrix[2*i+1][2*j+1]), 00151 num, den); 00152 } 00153 } 00154 // Evaluate optimal upper bound for `y - x <= ub'. 00155 for (dimension_type j = 0; j < num_dimensions; ++j) { 00156 if (i == j) 00157 continue; 00158 Variable y(j); 00159 lp.set_objective_function(x - y); 00160 if (lp.solve() == OPTIMIZED_MIP_PROBLEM) { 00161 g = lp.optimizing_point(); 00162 lp.evaluate_objective_function(g, num, den); 00163 div_round_up((i < j ? matrix[2*j][2*i] : matrix[2*i+1][2*j+1]), 00164 num, den); 00165 } 00166 } 00167 // Evaluate optimal upper bound for `-x - y <= ub'. 00168 for (dimension_type j = 0; j < i; ++j) { 00169 Variable y(j); 00170 lp.set_objective_function(-x - y); 00171 if (lp.solve() == OPTIMIZED_MIP_PROBLEM) { 00172 g = lp.optimizing_point(); 00173 lp.evaluate_objective_function(g, num, den); 00174 div_round_up(matrix[2*i][2*j+1], num, den); 00175 } 00176 } 00177 // Evaluate optimal upper bound for `-x <= ub'. 00178 lp.set_objective_function(-x); 00179 if (lp.solve() == OPTIMIZED_MIP_PROBLEM) { 00180 g = lp.optimizing_point(); 00181 lp.evaluate_objective_function(g, num, den); 00182 num *= 2; 00183 div_round_up(matrix[2*i][2*i+1], num, den); 00184 } 00185 } 00186 set_strongly_closed(); 00187 PPL_ASSERT(OK()); 00188 return; 00189 } 00190 00191 // Extract easy-to-find bounds from constraints. 00192 PPL_ASSERT(complexity == POLYNOMIAL_COMPLEXITY); 00193 *this = Octagonal_Shape(num_dimensions, UNIVERSE); 00194 refine_with_constraints(ph.constraints()); 00195 }
| 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.
| box | The box representing the OS to be built. | |
| complexity | This argument is ignored as the algorithm used has polynomial complexity. |
| std::length_error | Thrown if the space dimension of box exceeds the maximum allowed space dimension. |
Definition at line 169 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::constraints(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), and Parma_Polyhedra_Library::Box< ITV >::space_dimension().
00171 : matrix(box.space_dimension()), 00172 space_dim(box.space_dimension()), 00173 status() { 00174 // Check for emptyness for maximum precision. 00175 if (box.is_empty()) 00176 set_empty(); 00177 else if (box.space_dimension() > 0) { 00178 // A (non zero-dim) universe OS is strongly closed. 00179 set_strongly_closed(); 00180 refine_with_constraints(box.constraints()); 00181 } 00182 }
| 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.
| grid | The grid used to build the OS. | |
| complexity | This argument is ignored as the algorithm used has polynomial complexity. |
| std::length_error | Thrown if the space dimension of grid exceeds the maximum allowed space dimension. |
Definition at line 186 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Grid::minimized_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), and Parma_Polyhedra_Library::Grid::space_dimension().
00188 : matrix(grid.space_dimension()), 00189 space_dim(grid.space_dimension()), 00190 status() { 00191 if (grid.space_dimension() > 0) 00192 // A (non zero-dim) universe OS is strongly closed. 00193 set_strongly_closed(); 00194 // Taking minimized congruences ensures maximum precision. 00195 refine_with_congruences(grid.minimized_congruences()); 00196 }
| 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.
| bd | The BD shape used to build the OS. | |
| complexity | This argument is ignored as the algorithm used has polynomial complexity. |
| std::length_error | Thrown if the space dimension of bd exceeds the maximum allowed space dimension. |
Definition at line 201 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::constraints(), Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
00203 : matrix(bd.space_dimension()), 00204 space_dim(bd.space_dimension()), 00205 status() { 00206 // Check for emptyness for maximum precision. 00207 if (bd.is_empty()) 00208 set_empty(); 00209 else if (bd.space_dimension() > 0) { 00210 // A (non zero-dim) universe OS is strongly closed. 00211 set_strongly_closed(); 00212 refine_with_constraints(bd.constraints()); 00213 } 00214 }
| Parma_Polyhedra_Library::Octagonal_Shape< T >::~Octagonal_Shape | ( | ) | [inline] |
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruence | ( | const Congruence & | cg | ) | [inline] |
Adds to *this a constraint equivalent to the congruence cg.
| cg | The congruence to be added. |
| std::invalid_argument | Thrown if *this and congruence cg are dimension-incompatible, or cg is not optimally supported by the OS domain. |
Definition at line 454 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Congruence::is_proper_congruence(), Parma_Polyhedra_Library::Congruence::is_tautological(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Congruence::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruences().
00454 { 00455 const dimension_type cg_space_dim = cg.space_dimension(); 00456 // Dimension-compatibility check: 00457 // the dimension of `cg' can not be greater than space_dim. 00458 if (space_dimension() < cg_space_dim) 00459 throw_dimension_incompatible("add_congruence(cg)", cg); 00460 00461 // Handle the case of proper congruences first. 00462 if (cg.is_proper_congruence()) { 00463 if (cg.is_tautological()) 00464 return; 00465 if (cg.is_inconsistent()) { 00466 set_empty(); 00467 return; 00468 } 00469 // Non-trivial and proper congruences are not allowed. 00470 throw_generic("add_congruence(cg)", 00471 "cg is a non-trivial, proper congruence"); 00472 } 00473 00474 PPL_ASSERT(cg.is_equality()); 00475 Constraint c(cg); 00476 add_constraint(c); 00477 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruences | ( | const Congruence_System & | cgs | ) | [inline] |
Adds to *this constraints equivalent to the congruences in cgs.
| cgs | The congruences to be added. |
| std::invalid_argument | Thrown if *this and cgs are dimension-incompatible, or cgs contains a congruence which is not optimally supported by the OS domain. |
Definition at line 444 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruence(), Parma_Polyhedra_Library::Congruence_System::begin(), and Parma_Polyhedra_Library::Congruence_System::end().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_recycled_congruences(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape().
00444 { 00445 for (Congruence_System::const_iterator i = cgs.begin(), 00446 cgs_end = cgs.end(); i != cgs_end; ++i) 00447 add_congruence(*i); 00448 }
| 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.
| c | The constraint to be added. |
| std::invalid_argument | Thrown if *this and constraint c are dimension-incompatible, or c is not optimally supported by the OS domain. |
Definition at line 372 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Octagonal_Shape< T >::extract_octagonal_difference(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_inconsistent(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Constraint::is_tautological(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraints(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign().
00372 { 00373 const dimension_type c_space_dim = c.space_dimension(); 00374 // Dimension-compatibility check. 00375 if (c_space_dim > space_dim) 00376 throw_dimension_incompatible("add_constraint(c)", c); 00377 00378 // Get rid of strict inequalities. 00379 if (c.is_strict_inequality()) { 00380 if (c.is_inconsistent()) { 00381 set_empty(); 00382 return; 00383 } 00384 if (c.is_tautological()) 00385 return; 00386 // Nontrivial strict inequalities are not allowed. 00387 throw_generic("add_constraint(c)", "strict inequalities are not allowed"); 00388 } 00389 00390 dimension_type num_vars = 0; 00391 dimension_type i = 0; 00392 dimension_type j = 0; 00393 PPL_DIRTY_TEMP_COEFFICIENT(coeff); 00394 PPL_DIRTY_TEMP_COEFFICIENT(term); 00395 // Constraints that are not octagonal differences are not allowed. 00396 if (!extract_octagonal_difference(c, c_space_dim, num_vars, 00397 i, j, coeff, term)) 00398 throw_generic("add_constraint(c)", 00399 "c is not an octagonal constraint"); 00400 00401 if (num_vars == 0) { 00402 // Dealing with a trivial constraint (not a strict inequality). 00403 if (c.inhomogeneous_term() < 0 00404 || (c.is_equality() && c.inhomogeneous_term() != 0)) 00405 set_empty(); 00406 return; 00407 } 00408 00409 // Select the cell to be modified for the "<=" part of constraint. 00410 typename OR_Matrix<N>::row_iterator i_iter = matrix.row_begin() + i; 00411 typename OR_Matrix<N>::row_reference_type m_i = *i_iter; 00412 N& m_i_j = m_i[j]; 00413 // Set `coeff' to the absolute value of itself. 00414 if (coeff < 0) 00415 neg_assign(coeff); 00416 00417 bool is_oct_changed = false; 00418 // Compute the bound for `m_i_j', rounding towards plus infinity. 00419 PPL_DIRTY_TEMP(N, d); 00420 div_round_up(d, term, coeff); 00421 if (m_i_j > d) { 00422 m_i_j = d; 00423 is_oct_changed = true; 00424 } 00425 00426 if (c.is_equality()) { 00427 // Select the cell to be modified for the ">=" part of constraint. 00428 if (i % 2 == 0) 00429 ++i_iter; 00430 else 00431 --i_iter; 00432 00433 typename OR_Matrix<N>::row_reference_type m_ci = *i_iter; 00434 using namespace Implementation::Octagonal_Shapes; 00435 dimension_type cj = coherent_index(j); 00436 N& m_ci_cj = m_ci[cj]; 00437 // Also compute the bound for `m_ci_cj', rounding towards plus infinity. 00438 neg_assign(term); 00439 div_round_up(d, term, coeff); 00440 if (m_ci_cj > d) { 00441 m_ci_cj = d; 00442 is_oct_changed = true; 00443 } 00444 } 00445 00446 // This method does not preserve closure. 00447 if (is_oct_changed && marked_strongly_closed()) 00448 reset_strongly_closed(); 00449 PPL_ASSERT(OK()); 00450 }
| 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.
| cs | The constraints that will be added. |
| std::invalid_argument | Thrown if *this and cs are dimension-incompatible, or cs contains a constraint which is not optimally supported by the OS domain. |
Definition at line 424 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Constraint_System::begin(), and Parma_Polyhedra_Library::Constraint_System::end().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_recycled_constraints(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape().
00424 { 00425 for (Constraint_System::const_iterator i = cs.begin(), 00426 i_end = cs.end(); i != i_end; ++i) 00427 add_constraint(*i); 00428 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint | ( | dimension_type | i, | |
| dimension_type | j, | |||
| Coefficient_traits::const_reference | num, | |||
| Coefficient_traits::const_reference | den | |||
| ) | [inline, private] |
Adds the constraint matrix[i][j] <= num/den.
Definition at line 406 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::div_round_up(), and Parma_Polyhedra_Library::OR_Matrix< T >::row_size().
00409 { 00410 #ifndef NDEBUG 00411 // Private method: the caller has to ensure the following. 00412 PPL_ASSERT(i < 2*space_dim && j < 2*space_dim && i != j); 00413 typename OR_Matrix<N>::row_iterator m_i = matrix.row_begin() + i; 00414 PPL_ASSERT(j < m_i.row_size()); 00415 PPL_ASSERT(den != 0); 00416 #endif 00417 PPL_DIRTY_TEMP(N, k); 00418 div_round_up(k, num, den); 00419 add_octagonal_constraint(i, j, k); 00420 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint | ( | dimension_type | i, | |
| dimension_type | j, | |||
| const N & | k | |||
| ) | [inline, private] |
Adds the constraint matrix[i][j] <= k.
Definition at line 386 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_size(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::refine().
00388 { 00389 // Private method: the caller has to ensure the following. 00390 #ifndef NDEBUG 00391 PPL_ASSERT(i < 2*space_dim && j < 2*space_dim && i != j); 00392 typename OR_Matrix<N>::row_iterator m_i = matrix.row_begin() + i; 00393 PPL_ASSERT(j < m_i.row_size()); 00394 #endif 00395 N& r_i_j = matrix[i][j]; 00396 if (r_i_j > k) { 00397 r_i_j = k; 00398 if (marked_strongly_closed()) 00399 reset_strongly_closed(); 00400 } 00401 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_recycled_congruences | ( | Congruence_System & | cgs | ) | [inline] |
Adds to *this constraints equivalent to the congruences in cgs.
| cgs | The congruence system to be added to *this. The congruences in cgs may be recycled. |
| std::invalid_argument | Thrown if *this and cgs are dimension-incompatible, or cgs contains a congruence which is not optimally supported by the OS domain. |
cgs upon successful or exceptional return is that it can be safely destroyed. Definition at line 438 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruences().
00438 { 00439 add_congruences(cgs); 00440 }
| 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.
| cs | The constraint system to be added to *this. The constraints in cs may be recycled. |
| std::invalid_argument | Thrown if *this and cs are dimension-incompatible, or cs contains a constraint which is not optimally supported by the OS domain. |
cs upon successful or exceptional return is that it can be safely destroyed. Definition at line 432 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraints().
00432 { 00433 add_constraints(cs); 00434 }
| 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.
| 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
and adding a third dimension, the result will be the OS
Definition at line 2918 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::OR_Matrix< T >::grow(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image().
02918 { 02919 // Adding no dimensions is a no-op. 02920 if (m == 0) 02921 return; 02922 02923 const dimension_type new_dim = space_dim + m; 02924 const bool was_zero_dim_univ = !marked_empty() && space_dim == 0; 02925 02926 // To embed an n-dimension space octagon in a (n+m)-dimension space, 02927 // we just add `m' variables in the matrix of constraints. 02928 matrix.grow(new_dim); 02929 space_dim = new_dim; 02930 // If `*this' was the zero-dim space universe octagon, 02931 // then we can set the strongly closure flag. 02932 if (was_zero_dim_univ) 02933 set_strongly_closed(); 02934 02935 PPL_ASSERT(OK()); 02936 }
| 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.
| 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
and adding a third dimension, the result will be the OS
Definition at line 2940 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), and Parma_Polyhedra_Library::OR_Matrix< T >::row_end().
02940 { 02941 // Adding no dimensions is a no-op. 02942 if (m == 0) 02943 return; 02944 02945 const dimension_type n = matrix.num_rows(); 02946 02947 // To project an n-dimension space OS in a (space_dim+m)-dimension space, 02948 // we just add `m' columns and rows in the matrix of constraints. 02949 add_space_dimensions_and_embed(m); 02950 // We insert 0 where it needs. 02951 // Attention: now num_rows of matrix is update! 02952 for (typename OR_Matrix<N>::row_iterator i = matrix.row_begin() + n, 02953 matrix_row_end = matrix.row_end(); i != matrix_row_end; i += 2) { 02954 typename OR_Matrix<N>::row_reference_type x_i = *i; 02955 typename OR_Matrix<N>::row_reference_type x_ci = *(i+1); 02956 const dimension_type ind = i.index(); 02957 assign_r(x_i[ind+1], 0, ROUND_NOT_NEEDED); 02958 assign_r(x_ci[ind], 0, ROUND_NOT_NEEDED); 02959 } 02960 02961 if (marked_strongly_closed()) 02962 reset_strongly_closed(); 02963 PPL_ASSERT(OK()); 02964 }
| dimension_type Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_dimension | ( | ) | const [inline] |
Returns
, if *this is empty; otherwise, returns the affine dimension of *this.
Definition at line 551 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::is_discrete().
00551 { 00552 const dimension_type n_rows = matrix.num_rows(); 00553 // A zero-space-dim shape always has affine dimension zero. 00554 if (n_rows == 0) 00555 return 0; 00556 00557 // Strong closure is necessary to detect emptiness 00558 // and all (possibly implicit) equalities. 00559 strong_closure_assign(); 00560 if (marked_empty()) 00561 return 0; 00562 00563 // The vector `leaders' is used to represent non-singular 00564 // equivalence classes: 00565 // `leaders[i] == i' if and only if `i' is the leader of its 00566 // equivalence class (i.e., the minimum index in the class); 00567 std::vector<dimension_type> leaders; 00568 compute_leaders(leaders); 00569 00570 // Due to the splitting of variables, the affine dimension is the 00571 // number of non-singular positive zero-equivalence classes. 00572 dimension_type affine_dim = 0; 00573 for (dimension_type i = 0; i < n_rows; i += 2) 00574 // Note: disregard the singular equivalence class. 00575 if (leaders[i] == i && leaders[i+1] == i+1) 00576 ++affine_dim; 00577 00578 return affine_dim; 00579 }
| 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.
| var | The variable to which the affine expression is assigned. | |
| expr | The numerator of the affine expression. | |
| denominator | The denominator of the affine expression. |
| std::invalid_argument | Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a dimension of *this. |
Definition at line 4417 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_minus_v_pm_u_bounds(), Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_v_pm_u_bounds(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::swap(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image().
04420 { 04421 // The denominator cannot be zero. 04422 if (denominator == 0) 04423 throw_generic("affine_image(v, e, d)", "d == 0"); 04424 04425 // Dimension-compatibility checks. 04426 // The dimension of `expr' should not be greater than the dimension 04427 // of `*this'. 04428 const dimension_type expr_space_dim = expr.space_dimension(); 04429 if (space_dim < expr_space_dim) 04430 throw_dimension_incompatible("affine_image(v, e, d)", "e", expr); 04431 04432 // `var' should be one of the dimensions of the octagon. 04433 const dimension_type var_id = var.id(); 04434 if (space_dim < var_id + 1) 04435 throw_dimension_incompatible("affine_image(v, e, d)", var_id + 1); 04436 04437 strong_closure_assign(); 04438 // The image of an empty octagon is empty too. 04439 if (marked_empty()) 04440 return; 04441 04442 // Number of non-zero coefficients in `expr': will be set to 04443 // 0, 1, or 2, the latter value meaning any value greater than 1. 04444 dimension_type t = 0; 04445 // Variable-index of the last non-zero coefficient in `expr', if any. 04446 dimension_type w_id = 0; 04447 04448 // Get information about the number of non-zero coefficients in `expr'. 04449 // The `expr' must not be in two or plus variables. 04450 for (dimension_type i = expr_space_dim; i-- > 0; ) 04451 if (expr.coefficient(Variable(i)) != 0) { 04452 if (t++ == 1) 04453 break; 04454 else 04455 w_id = i; 04456 } 04457 04458 typedef typename OR_Matrix<N>::row_iterator Row_Iterator; 04459 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 04460 typedef typename OR_Matrix<N>::const_row_iterator Row_iterator; 04461 typedef typename OR_Matrix<N>::const_row_reference_type Row_reference; 04462 04463 const dimension_type n_var = 2*var_id; 04464 const Coefficient& b = expr.inhomogeneous_term(); 04465 PPL_DIRTY_TEMP_COEFFICIENT(minus_den); 04466 neg_assign_r(minus_den, denominator, ROUND_NOT_NEEDED); 04467 04468 // `w' is the variable with index `w_id'. 04469 // Now we know the form of `expr': 04470 // - If t == 0, then expr == b, with `b' a constant; 04471 // - If t == 1, then expr == a*w + b, where `w' can be `v' or another 04472 // variable; in this second case we have to check whether `a' is 04473 // equal to `denominator' or `-denominator', since otherwise we have 04474 // to fall back on the general form; 04475 // - If t == 2, the `expr' is of the general form. 04476 04477 if (t == 0) { 04478 // Case 1: expr == b. 04479 // Remove all constraints on `var'. 04480 forget_all_octagonal_constraints(var_id); 04481 PPL_DIRTY_TEMP_COEFFICIENT(two_b); 04482 two_b = 2*b; 04483 // Add the constraint `var == b/denominator'. 04484 add_octagonal_constraint(n_var+1, n_var, two_b, denominator); 04485 add_octagonal_constraint(n_var, n_var+1, two_b, minus_den); 04486 PPL_ASSERT(OK()); 04487 return; 04488 } 04489 04490 if (t == 1) { 04491 // The one and only non-zero homogeneous coefficient in `expr'. 04492 const Coefficient& w_coeff = expr.coefficient(Variable(w_id)); 04493 if (w_coeff == denominator || w_coeff == minus_den) { 04494 // Case 2: expr = w_coeff*w + b, with w_coeff = +/- denominator. 04495 if (w_id == var_id) { 04496 // Here `expr' is of the form: +/- denominator * v + b. 04497 const bool sign_symmetry = (w_coeff != denominator); 04498 if (!sign_symmetry && b == 0) 04499 // The transformation is the identity function. 04500 return; 04501 // Translate all the constraints on `var' adding or 04502 // subtracting the value `b/denominator'. 04503 PPL_DIRTY_TEMP(N, d); 04504 div_round_up(d, b, denominator); 04505 PPL_DIRTY_TEMP(N, minus_d); 04506 div_round_up(minus_d, b, minus_den); 04507 if (sign_symmetry) 04508 std::swap(d, minus_d); 04509 const Row_Iterator m_begin = matrix.row_begin(); 04510 const Row_Iterator m_end = matrix.row_end(); 04511 Row_Iterator m_iter = m_begin + n_var; 04512 Row_Reference m_v = *m_iter; 04513 ++m_iter; 04514 Row_Reference m_cv = *m_iter; 04515 ++m_iter; 04516 // NOTE: delay update of unary constraints on `var'. 04517 for (dimension_type j = n_var; j-- > 0; ) { 04518 N& m_v_j = m_v[j]; 04519 add_assign_r(m_v_j, m_v_j, minus_d, ROUND_UP); 04520 N& m_cv_j = m_cv[j]; 04521 add_assign_r(m_cv_j, m_cv_j, d, ROUND_UP); 04522 if (sign_symmetry) 04523 std::swap(m_v_j, m_cv_j); 04524 } 04525 for ( ; m_iter != m_end; ++m_iter) { 04526 Row_Reference m_i = *m_iter; 04527 N& m_i_v = m_i[n_var]; 04528 add_assign_r(m_i_v, m_i_v, d, ROUND_UP); 04529 N& m_i_cv = m_i[n_var+1]; 04530 add_assign_r(m_i_cv, m_i_cv, minus_d, ROUND_UP); 04531 if (sign_symmetry) 04532 std::swap(m_i_v, m_i_cv); 04533 } 04534 // Now update unary constraints on var. 04535 mul_2exp_assign_r(d, d, 1, ROUND_UP); 04536 N& m_cv_v = m_cv[n_var]; 04537 add_assign_r(m_cv_v, m_cv_v, d, ROUND_UP); 04538 mul_2exp_assign_r(minus_d, minus_d, 1, ROUND_UP); 04539 N& m_v_cv = m_v[n_var+1]; 04540 add_assign_r(m_v_cv, m_v_cv, minus_d, ROUND_UP); 04541 if (sign_symmetry) 04542 std::swap(m_cv_v, m_v_cv); 04543 // Note: strong closure is preserved. 04544 } 04545 else { 04546 // Here `w != var', so that `expr' is of the form 04547 // +/-denominator * w + b. 04548 // Remove all constraints on `var'. 04549 forget_all_octagonal_constraints(var_id); 04550 const dimension_type n_w = 2*w_id; 04551 // Add the new constraint `var - w = b/denominator'. 04552 if (w_coeff == denominator) { 04553 if (var_id < w_id) { 04554 add_octagonal_constraint(n_w, n_var, b, denominator); 04555 add_octagonal_constraint(n_w+1, n_var+1, b, minus_den); 04556 } 04557 else { 04558 add_octagonal_constraint(n_var+1, n_w+1, b, denominator); 04559 add_octagonal_constraint(n_var, n_w, b, minus_den); 04560 } 04561 } 04562 else { 04563 // Add the new constraint `var + w = b/denominator'. 04564 if (var_id < w_id) { 04565 add_octagonal_constraint(n_w+1, n_var, b, denominator); 04566 add_octagonal_constraint(n_w, n_var+1, b, minus_den); 04567 } 04568 else { 04569 add_octagonal_constraint(n_var+1, n_w, b, denominator); 04570 add_octagonal_constraint(n_var, n_w+1, b, minus_den); 04571 } 04572 } 04573 incremental_strong_closure_assign(var); 04574 } 04575 PPL_ASSERT(OK()); 04576 return; 04577 } 04578 } 04579 04580 // General case. 04581 // Either t == 2, so that 04582 // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2, 04583 // or t == 1, expr == a*w + b, but a <> +/- denominator. 04584 // We will remove all the constraints on `var' and add back 04585 // constraints providing upper and lower bounds for `var'. 04586 04587 // Compute upper approximations for `expr' and `-expr' 04588 // into `pos_sum' and `neg_sum', respectively, taking into account 04589 // the sign of `denominator'. 04590 // Note: approximating `-expr' from above and then negating the 04591 // result is the same as approximating `expr' from below. 04592 const bool is_sc = (denominator > 0); 04593 PPL_DIRTY_TEMP_COEFFICIENT(minus_b); 04594 neg_assign_r(minus_b, b, ROUND_NOT_NEEDED); 04595 04596 const Coefficient& sc_b = is_sc ? b : minus_b; 04597 const Coefficient& minus_sc_b = is_sc ? minus_b : b; 04598 const Coefficient& sc_den = is_sc ? denominator : minus_den; 04599 const Coefficient& minus_sc_den = is_sc ? minus_den : denominator; 04600 // NOTE: here, for optimization purposes, `minus_expr' is only assigned 04601 // when `denominator' is negative. Do not use it unless you are sure 04602 // it has been correctly assigned. 04603 Linear_Expression minus_expr; 04604 if (!is_sc) 04605 minus_expr = -expr; 04606 const Linear_Expression& sc_expr = is_sc ? expr : minus_expr; 04607 04608 PPL_DIRTY_TEMP(N, pos_sum); 04609 PPL_DIRTY_TEMP(N, neg_sum); 04610 // Indices of the variables that are unbounded in `this->matrix'. 04611 PPL_UNINITIALIZED(dimension_type, pos_pinf_index); 04612 PPL_UNINITIALIZED(dimension_type, neg_pinf_index); 04613 // Number of unbounded variables found. 04614 dimension_type pos_pinf_count = 0; 04615 dimension_type neg_pinf_count = 0; 04616 04617 // Approximate the inhomogeneous term. 04618 assign_r(pos_sum, sc_b, ROUND_UP); 04619 assign_r(neg_sum, minus_sc_b, ROUND_UP); 04620 04621 // Approximate the homogeneous part of `sc_expr'. 04622 PPL_DIRTY_TEMP(N, coeff_i); 04623 PPL_DIRTY_TEMP(N, minus_coeff_i); 04624 PPL_DIRTY_TEMP(N, half); 04625 PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i); 04626 // Note: indices above `w' can be disregarded, as they all have 04627 // a zero coefficient in `sc_expr'. 04628 const Row_Iterator m_begin = matrix.row_begin(); 04629 for (Row_iterator m_iter = m_begin, 04630 m_iter_end = m_iter + (2*w_id) + 2; m_iter != m_iter_end; ) { 04631 const dimension_type n_i = m_iter.index(); 04632 const dimension_type id = n_i/2; 04633 Row_reference m_i = *m_iter; 04634 ++m_iter; 04635 Row_reference m_ci = *m_iter; 04636 ++m_iter; 04637 const Coefficient& sc_i = sc_expr.coefficient(Variable(id)); 04638 const int sign_i = sgn(sc_i); 04639 if (sign_i > 0) { 04640 assign_r(coeff_i, sc_i, ROUND_UP); 04641 // Approximating `sc_expr'. 04642 if (pos_pinf_count <= 1) { 04643 const N& double_up_approx_i = m_ci[n_i]; 04644 if (!is_plus_infinity(double_up_approx_i)) { 04645 // Let half = double_up_approx_i / 2. 04646 div_2exp_assign_r(half, double_up_approx_i, 1, ROUND_UP); 04647 add_mul_assign_r(pos_sum, coeff_i, half, ROUND_UP); 04648 } 04649 else { 04650 ++pos_pinf_count; 04651 pos_pinf_index = id; 04652 } 04653 } 04654 // Approximating `-sc_expr'. 04655 if (neg_pinf_count <= 1) { 04656 const N& double_up_approx_minus_i = m_i[n_i+1]; 04657 if (!is_plus_infinity(double_up_approx_minus_i)) { 04658 // Let half = double_up_approx_minus_i / 2. 04659 div_2exp_assign_r(half, double_up_approx_minus_i, 1, ROUND_UP); 04660 add_mul_assign_r(neg_sum, coeff_i, half, ROUND_UP); 04661 } 04662 else { 04663 ++neg_pinf_count; 04664 neg_pinf_index = id; 04665 } 04666 } 04667 } 04668 else if (sign_i < 0) { 04669 neg_assign_r(minus_sc_i, sc_i, ROUND_NOT_NEEDED); 04670 assign_r(minus_coeff_i, minus_sc_i, ROUND_UP); 04671 // Approximating `sc_expr'. 04672 if (pos_pinf_count <= 1) { 04673 const N& double_up_approx_minus_i = m_i[n_i+1]; 04674 if (!is_plus_infinity(double_up_approx_minus_i)) { 04675 // Let half = double_up_approx_minus_i / 2. 04676 div_2exp_assign_r(half, double_up_approx_minus_i, 1, ROUND_UP); 04677 add_mul_assign_r(pos_sum, minus_coeff_i, half, ROUND_UP); 04678 } 04679 else { 04680 ++pos_pinf_count; 04681 pos_pinf_index = id; 04682 } 04683 } 04684 // Approximating `-sc_expr'. 04685 if (neg_pinf_count <= 1) { 04686 const N& double_up_approx_i = m_ci[n_i]; 04687 if (!is_plus_infinity(double_up_approx_i)) { 04688 // Let half = double_up_approx_i / 2. 04689 div_2exp_assign_r(half, double_up_approx_i, 1, ROUND_UP); 04690 add_mul_assign_r(neg_sum, minus_coeff_i, half, ROUND_UP); 04691 } 04692 else { 04693 ++neg_pinf_count; 04694 neg_pinf_index = id; 04695 } 04696 } 04697 } 04698 } 04699 04700 // Remove all constraints on `var'. 04701 forget_all_octagonal_constraints(var_id); 04702 // Return immediately if no approximation could be computed. 04703 if (pos_pinf_count > 1 && neg_pinf_count > 1) { 04704 PPL_ASSERT(OK()); 04705 return; 04706 } 04707 04708 // In the following, strong closure will be definitely lost. 04709 reset_strongly_closed(); 04710 04711 // Exploit the upper approximation, if possible. 04712 if (pos_pinf_count <= 1) { 04713 // Compute quotient (if needed). 04714 if (sc_den != 1) { 04715 // Before computing quotients, the denominator should be approximated 04716 // towards zero. Since `sc_den' is known to be positive, this amounts to 04717 // rounding downwards, which is achieved as usual by rounding upwards 04718 // `minus_sc_den' and negating again the result. 04719 PPL_DIRTY_TEMP(N, down_sc_den); 04720 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 04721 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 04722 div_assign_r(pos_sum, pos_sum, down_sc_den, ROUND_UP); 04723 } 04724 // Add the upper bound constraint, if meaningful. 04725 if (pos_pinf_count == 0) { 04726 // Add the constraint `v <= pos_sum'. 04727 PPL_DIRTY_TEMP(N, double_pos_sum); 04728 mul_2exp_assign_r(double_pos_sum, pos_sum, 1, ROUND_UP); 04729 matrix[n_var+1][n_var] = double_pos_sum; 04730 // Deduce constraints of the form `v +/- u', where `u != v'. 04731 deduce_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, pos_sum); 04732 } 04733 else 04734 // Here `pos_pinf_count == 1'. 04735 if (pos_pinf_index != var_id) { 04736 const Coefficient& ppi = sc_expr.coefficient(Variable(pos_pinf_index)); 04737 if (ppi == sc_den) 04738 // Add the constraint `v - pos_pinf_index <= pos_sum'. 04739 if (var_id < pos_pinf_index) 04740 matrix[2*pos_pinf_index][n_var] = pos_sum; 04741 else 04742 matrix[n_var+1][2*pos_pinf_index+1] = pos_sum; 04743 else 04744 if (ppi == minus_sc_den) { 04745 // Add the constraint `v + pos_pinf_index <= pos_sum'. 04746 if (var_id < pos_pinf_index) 04747 matrix[2*pos_pinf_index+1][n_var] = pos_sum; 04748 else 04749 matrix[n_var+1][2*pos_pinf_index] = pos_sum; 04750 } 04751 } 04752 } 04753 04754 // Exploit the lower approximation, if possible. 04755 if (neg_pinf_count <= 1) { 04756 // Compute quotient (if needed). 04757 if (sc_den != 1) { 04758 // Before computing quotients, the denominator should be approximated 04759 // towards zero. Since `sc_den' is known to be positive, this amounts to 04760 // rounding downwards, which is achieved as usual by rounding upwards 04761 // `minus_sc_den' and negating again the result. 04762 PPL_DIRTY_TEMP(N, down_sc_den); 04763 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 04764 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 04765 div_assign_r(neg_sum, neg_sum, down_sc_den, ROUND_UP); 04766 } 04767 // Add the lower bound constraint, if meaningful. 04768 if (neg_pinf_count == 0) { 04769 // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'. 04770 PPL_DIRTY_TEMP(N, double_neg_sum); 04771 mul_2exp_assign_r(double_neg_sum, neg_sum, 1, ROUND_UP); 04772 matrix[n_var][n_var+1] = double_neg_sum; 04773 // Deduce constraints of the form `-v +/- u', where `u != v'. 04774 deduce_minus_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, neg_sum); 04775 } 04776 else 04777 // Here `neg_pinf_count == 1'. 04778 if (neg_pinf_index != var_id) { 04779 const Coefficient& npi = sc_expr.coefficient(Variable(neg_pinf_index)); 04780 if (npi == sc_den) 04781 // Add the constraint `v - neg_pinf_index >= -neg_sum', 04782 // i.e., `neg_pinf_index - v <= neg_sum'. 04783 if (neg_pinf_index < var_id) 04784 matrix[n_var][2*neg_pinf_index] = neg_sum; 04785 else 04786 matrix[2*neg_pinf_index+1][n_var+1] = neg_sum; 04787 else 04788 if (npi == minus_sc_den) { 04789 // Add the constraint `v + neg_pinf_index >= -neg_sum', 04790 // i.e., `-neg_pinf_index - v <= neg_sum'. 04791 if (neg_pinf_index < var_id) 04792 matrix[n_var][2*neg_pinf_index+1] = neg_sum; 04793 else 04794 matrix[2*neg_pinf_index][n_var+1] = neg_sum; 04795 } 04796 } 04797 } 04798 04799 incremental_strong_closure_assign(var); 04800 PPL_ASSERT(OK()); 04801 }
| 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.
| var | The variable to which the affine expression is substituted. | |
| expr | The numerator of the affine expression. | |
| denominator | The denominator of the affine expression. |
| std::invalid_argument | Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a dimension of *this. |
Definition at line 4805 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
04808 { 04809 04810 // The denominator cannot be zero. 04811 if (denominator == 0) 04812 throw_generic("affine_preimage(v, e, d)", "d == 0"); 04813 04814 // Dimension-compatibility checks. 04815 // The dimension of `expr' should not be greater than the dimension 04816 // of `*this'. 04817 const dimension_type expr_space_dim = expr.space_dimension(); 04818 if (space_dim < expr_space_dim) 04819 throw_dimension_incompatible("affine_preimage(v, e, d)", "e", expr); 04820 04821 // `var' should be one of the dimensions of the octagon. 04822 dimension_type var_id = var.id(); 04823 if (space_dim < var_id + 1) 04824 throw_dimension_incompatible("affine_preimage(v, e, d)", var_id + 1); 04825 04826 strong_closure_assign(); 04827 // The image of an empty octagon is empty too. 04828 if (marked_empty()) 04829 return; 04830 04831 const Coefficient& b = expr.inhomogeneous_term(); 04832 04833 // Number of non-zero coefficients in `expr': will be set to 04834 // 0, 1, or 2, the latter value meaning any value greater than 1. 04835 dimension_type t = 0; 04836 04837 // Variable-index of the last non-zero coefficient in `expr', if any. 04838 dimension_type w_id = 0; 04839 04840 // Get information about the number of the non-zero coefficients of `expr'. 04841 for (dimension_type i = expr_space_dim; i-- > 0; ) 04842 if (expr.coefficient(Variable(i)) != 0) { 04843 if (t++ == 1) 04844 break; 04845 else 04846 w_id = i; 04847 } 04848 04849 // `w' is the variable with index `w_id'. 04850 // Now we know the form of `expr': 04851 // - If t == 0, then expr == b, with `b' a constant; 04852 // - If t == 1, then expr == a*w + b, where `w' can be `v' or another 04853 // variable; in this second case we have to check whether `a' is 04854 // equal to `denominator' or `-denominator', since otherwise we have 04855 // to fall back on the general form; 04856 // - If t == 2, the `expr' is of the general form. 04857 04858 if (t == 0) { 04859 // Case 1: expr = n; remove all constraints on `var'. 04860 forget_all_octagonal_constraints(var_id); 04861 PPL_ASSERT(OK()); 04862 return; 04863 } 04864 04865 if (t == 1) { 04866 // Value of the one and only non-zero coefficient in `expr'. 04867 const Coefficient& w_coeff = expr.coefficient(Variable(w_id)); 04868 if (w_coeff == denominator || w_coeff == -denominator) { 04869 // Case 2: expr = w_coeff*w + b, with w_coeff = +/- denominator. 04870 if (w_id == var_id) { 04871 // Apply affine_image() on the inverse of this transformation. 04872 affine_image(var, denominator*var - b, w_coeff); 04873 } 04874 else { 04875 // `expr == w_coeff*w + b', where `w != var'. 04876 // Remove all constraints on `var'. 04877 forget_all_octagonal_constraints(var_id); 04878 PPL_ASSERT(OK()); 04879 } 04880 return; 04881 } 04882 } 04883 // General case. 04884 // Either t == 2, so that 04885 // expr = a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2, 04886 // or t = 1, expr = a*w + b, but a <> +/- denominator. 04887 const Coefficient& coeff_v = expr.coefficient(var); 04888 if (coeff_v != 0) { 04889 if (coeff_v > 0) { 04890 // The transformation is invertible. 04891 Linear_Expression inverse = ((coeff_v + denominator)*var); 04892 inverse -= expr; 04893 affine_image(var, inverse, coeff_v); 04894 } 04895 else { 04896 // The transformation is invertible. 04897 PPL_DIRTY_TEMP_COEFFICIENT(minus_coeff_v); 04898 neg_assign(minus_coeff_v, coeff_v); 04899 Linear_Expression inverse = ((minus_coeff_v - denominator)*var); 04900 inverse += expr; 04901 affine_image(var, inverse, minus_coeff_v); 04902 } 04903 } 04904 else { 04905 // The transformation is not invertible: all constraints on `var' are lost. 04906 forget_all_octagonal_constraints(var_id); 04907 PPL_ASSERT(OK()); 04908 } 04909 }
| 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 7053 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::OR_Matrix< T >::ascii_dump(), 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.
07053 { 07054 s << "space_dim " 07055 << space_dim 07056 << "\n"; 07057 status.ascii_dump(s); 07058 s << "\n"; 07059 matrix.ascii_dump(s); 07060 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::ascii_dump | ( | ) | const |
Writes to std::cerr an ASCII representation of *this.
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::ascii_load | ( | std::istream & | s | ) | [inline] |
Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this accordingly. Returns true if successful, false otherwise.
Definition at line 7066 of file Octagonal_Shape.templates.hh.
07066 { 07067 std::string str; 07068 07069 if (!(s >> str) || str != "space_dim") 07070 return false; 07071 07072 if (!(s >> space_dim)) 07073 return false; 07074 07075 if (!status.ascii_load(s)) 07076 return false; 07077 07078 if (!matrix.ascii_load(s)) 07079 return false; 07080 07081 PPL_ASSERT(OK()); 07082 return true; 07083 }
| 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.
| 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). |
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 3373 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::element_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::widening_assign().
03374 { 03375 // Dimension-compatibility check. 03376 if (space_dim != y.space_dim) 03377 throw_dimension_incompatible("BHMZ05_widening_assign(y)", y); 03378 03379 #ifndef NDEBUG 03380 { 03381 // We assume that `y' is contained in or equal to `*this'. 03382 const Octagonal_Shape x_copy = *this; 03383 const Octagonal_Shape y_copy = y; 03384 PPL_ASSERT(x_copy.contains(y_copy)); 03385 } 03386 #endif 03387 03388 // Compute the affine dimension of `y'. 03389 const dimension_type y_affine_dim = y.affine_dimension(); 03390 // If the affine dimension of `y' is zero, then either `y' is 03391 // zero-dimensional, or it is empty, or it is a singleton. 03392 // In all cases, due to the inclusion hypothesis, the result is `*this'. 03393 if (y_affine_dim == 0) 03394 return; 03395 03396 // If the affine dimension has changed, due to the inclusion hypothesis, 03397 // the result is `*this'. 03398 const dimension_type x_affine_dim = affine_dimension(); 03399 PPL_ASSERT(x_affine_dim >= y_affine_dim); 03400 if (x_affine_dim != y_affine_dim) 03401 return; 03402 03403 // If there are tokens available, work on a temporary copy. 03404 if (tp != 0 && *tp > 0) { 03405 Octagonal_Shape x_tmp(*this); 03406 x_tmp.BHMZ05_widening_assign(y, 0); 03407 // If the widening was not precise, use one of the available tokens. 03408 if (!contains(x_tmp)) 03409 --(*tp); 03410 return; 03411 } 03412 03413 // Here no token is available. 03414 PPL_ASSERT(marked_strongly_closed() && y.marked_strongly_closed()); 03415 // Minimize `y'. 03416 y.strong_reduction_assign(); 03417 03418 // Extrapolate unstable bounds. 03419 typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin(); 03420 for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(), 03421 matrix_element_end = matrix.element_end(); 03422 i != matrix_element_end; 03423 ++i, ++j) { 03424 N& elem = *i; 03425 // Note: in the following line the use of `!=' (as opposed to 03426 // the use of `<' that would seem -but is not- equivalent) is 03427 // intentional. 03428 if (*j != elem) 03429 assign_r(elem, PLUS_INFINITY, ROUND_NOT_NEEDED); 03430 } 03431 reset_strongly_closed(); 03432 PPL_ASSERT(OK()); 03433 }
| 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
.
| 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). |
| std::invalid_argument | Thrown if denominator is zero or if lb_expr (resp., ub_expr) and *this are dimension-incompatible or if var is not a space dimension of *this. |
Definition at line 5591 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_minus_v_pm_u_bounds(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
05595 { 05596 // The denominator cannot be zero. 05597 if (denominator == 0) 05598 throw_generic("bounded_affine_image(v, lb, ub, d)", "d == 0"); 05599 05600 // `var' should be one of the dimensions of the octagon. 05601 const dimension_type var_id = var.id(); 05602 if (space_dim < var_id + 1) 05603 throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)", 05604 var_id + 1); 05605 05606 // The dimension of `lb_expr' and `ub_expr' should not be 05607 // greater than the dimension of `*this'. 05608 const dimension_type lb_space_dim = lb_expr.space_dimension(); 05609 if (space_dim < lb_space_dim) 05610 throw_dimension_incompatible("bounded_affine_image(v, lb, ub)", 05611 "lb", lb_expr); 05612 const dimension_type ub_space_dim = ub_expr.space_dimension(); 05613 if (space_dim < ub_space_dim) 05614 throw_dimension_incompatible("bounded_affine_image(v, lb, ub)", 05615 "ub", ub_expr); 05616 05617 strong_closure_assign(); 05618 // The image of an empty octagon is empty too. 05619 if (marked_empty()) 05620 return; 05621 05622 // Number of non-zero coefficients in `lb_expr': will be set to 05623 // 0, 1, or 2, the latter value meaning any value greater than 1. 05624 dimension_type t = 0; 05625 // Variable-index of the last non-zero coefficient in `lb_expr', if any. 05626 dimension_type w_id = 0; 05627 05628 // Get information about the number of non-zero coefficients in `lb_expr'. 05629 // The `expr' must not be in two or plus variables. 05630 for (dimension_type i = lb_space_dim; i-- > 0; ) 05631 if (lb_expr.coefficient(Variable(i)) != 0) { 05632 if (t++ == 1) 05633 break; 05634 else 05635 w_id = i; 05636 } 05637 05638 typedef typename OR_Matrix<N>::row_iterator Row_Iterator; 05639 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 05640 typedef typename OR_Matrix<N>::const_row_iterator Row_iterator; 05641 typedef typename OR_Matrix<N>::const_row_reference_type Row_reference; 05642 05643 const Row_Iterator m_begin = matrix.row_begin(); 05644 const dimension_type n_var = 2*var_id; 05645 const Coefficient& b = lb_expr.inhomogeneous_term(); 05646 PPL_DIRTY_TEMP_COEFFICIENT(minus_den); 05647 neg_assign_r(minus_den, denominator, ROUND_NOT_NEEDED); 05648 05649 // `w' is the variable with index `w_id'. 05650 // Now we know the form of `lb_expr': 05651 // - If t == 0, then lb_expr == b, with `b' a constant; 05652 // - If t == 1, then lb_expr == a*w + b, where `w' can be `v' or another 05653 // variable; in this second case we have to check whether `a' is 05654 // equal to `denominator' or `-denominator', since otherwise we have 05655 // to fall back on the general form; 05656 // - If t == 2, the `lb_expr' is of the general form. 05657 05658 if (t == 0) { 05659 // Case 1: lb_expr == b. 05660 generalized_affine_image(var, 05661 LESS_OR_EQUAL, 05662 ub_expr, 05663 denominator); 05664 PPL_DIRTY_TEMP_COEFFICIENT(two_b); 05665 two_b = 2*b; 05666 // Add the constraint `var >= b/denominator'. 05667 add_octagonal_constraint(n_var, n_var+1, two_b, minus_den); 05668 PPL_ASSERT(OK()); 05669 return; 05670 } 05671 05672 if (t == 1) { 05673 // The one and only non-zero homogeneous coefficient in `lb_expr'. 05674 const Coefficient& w_coeff = lb_expr.coefficient(Variable(w_id)); 05675 if (w_coeff == denominator || w_coeff == minus_den) { 05676 // Case 2: lb_expr = w_coeff*w + b, with w_coeff = +/- denominator. 05677 if (w_id == var_id) { 05678 // Here `var' occurs in `lb_expr'. 05679 // To ease the computation, we add an additional dimension. 05680 const Variable new_var = Variable(space_dim); 05681 add_space_dimensions_and_embed(1); 05682 // Constrain the new dimension to be equal to `lb_expr'. 05683 // Here `lb_expr' is of the form: +/- denominator * v + b. 05684 affine_image(new_var, lb_expr, denominator); 05685 // Enforce the strong closure for precision. 05686 strong_closure_assign(); 05687 PPL_ASSERT(!marked_empty()); 05688 // Apply the affine upper bound. 05689 generalized_affine_image(var, 05690 LESS_OR_EQUAL, 05691 ub_expr, 05692 denominator); 05693 // Now apply the affine lower bound, as recorded in `new_var' 05694 refine_no_check(var >= new_var); 05695 // Remove the temporarily added dimension. 05696 remove_higher_space_dimensions(space_dim-1); 05697 return; 05698 } 05699 else { 05700 // Apply the affine upper bound. 05701 generalized_affine_image(var, 05702 LESS_OR_EQUAL, 05703 ub_expr, 05704 denominator); 05705 // Here `w != var', so that `lb_expr' is of the form 05706 // +/-denominator * w + b. 05707 const dimension_type n_w = 2*w_id; 05708 // Add the new constraint `var - w >= b/denominator'. 05709 if (w_coeff == denominator) 05710 if (var_id < w_id) 05711 add_octagonal_constraint(n_w+1, n_var+1, b, minus_den); 05712 else 05713 add_octagonal_constraint(n_var, n_w, b, minus_den); 05714 else { 05715 // Add the new constraint `var + w >= b/denominator'. 05716 if (var_id < w_id) 05717 add_octagonal_constraint(n_w, n_var+1, b, minus_den); 05718 else 05719 add_octagonal_constraint(n_var, n_w+1, b, minus_den); 05720 } 05721 PPL_ASSERT(OK()); 05722 return; 05723 } 05724 } 05725 } 05726 05727 // General case. 05728 // Either t == 2, so that 05729 // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2, 05730 // or t == 1, expr == a*w + b, but a <> +/- denominator. 05731 // We will remove all the constraints on `var' and add back 05732 // constraints providing upper and lower bounds for `var'. 05733 05734 // Compute upper approximations for `expr' and `-expr' 05735 // into `pos_sum' and `neg_sum', respectively, taking into account 05736 // the sign of `denominator'. 05737 // Note: approximating `-expr' from above and then negating the 05738 // result is the same as approximating `expr' from below. 05739 const bool is_sc = (denominator > 0); 05740 PPL_DIRTY_TEMP_COEFFICIENT(minus_b); 05741 neg_assign_r(minus_b, b, ROUND_NOT_NEEDED); 05742 05743 const Coefficient& minus_sc_b = is_sc ? minus_b : b; 05744 const Coefficient& sc_den = is_sc ? denominator : minus_den; 05745 const Coefficient& minus_sc_den = is_sc ? minus_den : denominator; 05746 // NOTE: here, for optimization purposes, `minus_expr' is only assigned 05747 // when `denominator' is negative. Do not use it unless you are sure 05748 // it has been correctly assigned. 05749 Linear_Expression minus_expr; 05750 if (!is_sc) 05751 minus_expr = -lb_expr; 05752 const Linear_Expression& sc_expr = is_sc ? lb_expr : minus_expr; 05753 05754 PPL_DIRTY_TEMP(N, neg_sum); 05755 // Indices of the variables that are unbounded in `this->matrix'. 05756 PPL_UNINITIALIZED(dimension_type, neg_pinf_index); 05757 // Number of unbounded variables found. 05758 dimension_type neg_pinf_count = 0; 05759 05760 // Approximate the inhomogeneous term. 05761 assign_r(neg_sum, minus_sc_b, ROUND_UP); 05762 05763 // Approximate the homogeneous part of `sc_expr'. 05764 PPL_DIRTY_TEMP(N, coeff_i); 05765 PPL_DIRTY_TEMP(N, minus_coeff_i); 05766 PPL_DIRTY_TEMP(N, half); 05767 PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i); 05768 // Note: indices above `w' can be disregarded, as they all have 05769 // a zero coefficient in `sc_expr'. 05770 for (Row_iterator m_iter = m_begin, m_iter_end = m_iter + (2*w_id) + 2; 05771 m_iter != m_iter_end; ) { 05772 const dimension_type n_i = m_iter.index(); 05773 const dimension_type id = n_i/2; 05774 Row_reference m_i = *m_iter; 05775 ++m_iter; 05776 Row_reference m_ci = *m_iter; 05777 ++m_iter; 05778 const Coefficient& sc_i = sc_expr.coefficient(Variable(id)); 05779 const int sign_i = sgn(sc_i); 05780 if (sign_i > 0) { 05781 assign_r(coeff_i, sc_i, ROUND_UP); 05782 // Approximating `-sc_expr'. 05783 if (neg_pinf_count <= 1) { 05784 const N& double_up_approx_minus_i = m_i[n_i+1]; 05785 if (!is_plus_infinity(double_up_approx_minus_i)) { 05786 // Let half = double_up_approx_minus_i / 2. 05787 div_2exp_assign_r(half, double_up_approx_minus_i, 1, ROUND_UP); 05788 add_mul_assign_r(neg_sum, coeff_i, half, ROUND_UP); 05789 } 05790 else { 05791 ++neg_pinf_count; 05792 neg_pinf_index = id; 05793 } 05794 } 05795 } 05796 else if (sign_i < 0) { 05797 neg_assign_r(minus_sc_i, sc_i, ROUND_NOT_NEEDED); 05798 assign_r(minus_coeff_i, minus_sc_i, ROUND_UP); 05799 // Approximating `-sc_expr'. 05800 if (neg_pinf_count <= 1) { 05801 const N& double_up_approx_i = m_ci[n_i]; 05802 if (!is_plus_infinity(double_up_approx_i)) { 05803 // Let half = double_up_approx_i / 2. 05804 div_2exp_assign_r(half, double_up_approx_i, 1, ROUND_UP); 05805 add_mul_assign_r(neg_sum, minus_coeff_i, half, ROUND_UP); 05806 } 05807 else { 05808 ++neg_pinf_count; 05809 neg_pinf_index = id; 05810 } 05811 } 05812 } 05813 } 05814 05815 // Apply the affine upper bound. 05816 generalized_affine_image(var, 05817 LESS_OR_EQUAL, 05818 ub_expr, 05819 denominator); 05820 05821 // Return immediately if no approximation could be computed. 05822 if (neg_pinf_count > 1) { 05823 return; 05824 } 05825 05826 // In the following, strong closure will be definitely lost. 05827 reset_strongly_closed(); 05828 05829 // Exploit the lower approximation, if possible. 05830 if (neg_pinf_count <= 1) { 05831 // Compute quotient (if needed). 05832 if (sc_den != 1) { 05833 // Before computing quotients, the denominator should be approximated 05834 // towards zero. Since `sc_den' is known to be positive, this amounts to 05835 // rounding downwards, which is achieved as usual by rounding upwards 05836 // `minus_sc_den' and negating again the result. 05837 PPL_DIRTY_TEMP(N, down_sc_den); 05838 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 05839 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 05840 div_assign_r(neg_sum, neg_sum, down_sc_den, ROUND_UP); 05841 } 05842 // Add the lower bound constraint, if meaningful. 05843 if (neg_pinf_count == 0) { 05844 // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'. 05845 PPL_DIRTY_TEMP(N, double_neg_sum); 05846 mul_2exp_assign_r(double_neg_sum, neg_sum, 1, ROUND_UP); 05847 matrix[n_var][n_var+1] = double_neg_sum; 05848 // Deduce constraints of the form `-v +/- u', where `u != v'. 05849 deduce_minus_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, neg_sum); 05850 } 05851 else 05852 // Here `neg_pinf_count == 1'. 05853 if (neg_pinf_index != var_id) { 05854 const Coefficient& npi = sc_expr.coefficient(Variable(neg_pinf_index)); 05855 if (npi == sc_den) 05856 // Add the constraint `v - neg_pinf_index >= -neg_sum', 05857 // i.e., `neg_pinf_index - v <= neg_sum'. 05858 if (neg_pinf_index < var_id) 05859 matrix[n_var][2*neg_pinf_index] = neg_sum; 05860 else 05861 matrix[2*neg_pinf_index+1][n_var+1] = neg_sum; 05862 else 05863 if (npi == minus_sc_den) { 05864 // Add the constraint `v + neg_pinf_index >= -neg_sum', 05865 // i.e., `-neg_pinf_index - v <= neg_sum'. 05866 if (neg_pinf_index < var_id) 05867 matrix[n_var][2*neg_pinf_index+1] = neg_sum; 05868 else 05869 matrix[2*neg_pinf_index][n_var+1] = neg_sum; 05870 } 05871 } 05872 } 05873 05874 PPL_ASSERT(OK()); 05875 }
| 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
.
| 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). |
| std::invalid_argument | Thrown if denominator is zero or if lb_expr (resp., ub_expr) and *this are dimension-incompatible or if var is not a space dimension of *this. |
Definition at line 6121 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::neg_assign(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Octagonal_Shape< T >::refine(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
06125 { 06126 // The denominator cannot be zero. 06127 if (denominator == 0) 06128 throw_generic("bounded_affine_preimage(v, lb, ub, d)", "d == 0"); 06129 06130 // `var' should be one of the dimensions of the octagon. 06131 const dimension_type var_id = var.id(); 06132 if (space_dim < var_id + 1) 06133 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)", 06134 var_id + 1); 06135 06136 // The dimension of `lb_expr' and `ub_expr' should not be 06137 // greater than the dimension of `*this'. 06138 const dimension_type lb_space_dim = lb_expr.space_dimension(); 06139 if (space_dim < lb_space_dim) 06140 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)", 06141 "lb", lb_expr); 06142 const dimension_type ub_space_dim = ub_expr.space_dimension(); 06143 if (space_dim < ub_space_dim) 06144 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)", 06145 "ub", ub_expr); 06146 06147 strong_closure_assign(); 06148 // The image of an empty octagon is empty too. 06149 if (marked_empty()) 06150 return; 06151 06152 if (ub_expr.coefficient(var) == 0) { 06153 refine(var, LESS_OR_EQUAL, ub_expr, denominator); 06154 generalized_affine_preimage(var, GREATER_OR_EQUAL, 06155 lb_expr, denominator); 06156 return; 06157 } 06158 if (lb_expr.coefficient(var) == 0) { 06159 refine(var, GREATER_OR_EQUAL, lb_expr, denominator); 06160 generalized_affine_preimage(var, LESS_OR_EQUAL, 06161 ub_expr, denominator); 06162 return; 06163 } 06164 06165 const Coefficient& expr_v = lb_expr.coefficient(var); 06166 // Here `var' occurs in `lb_expr' and `ub_expr'. 06167 // To ease the computation, we add an additional dimension. 06168 const Variable new_var = Variable(space_dim); 06169 add_space_dimensions_and_embed(1); 06170 const Linear_Expression lb_inverse 06171 = lb_expr - (expr_v + denominator)*var; 06172 PPL_DIRTY_TEMP_COEFFICIENT(inverse_den); 06173 neg_assign(inverse_den, expr_v); 06174 affine_image(new_var, lb_inverse, inverse_den); 06175 strong_closure_assign(); 06176 PPL_ASSERT(!marked_empty()); 06177 generalized_affine_preimage(var, LESS_OR_EQUAL, 06178 ub_expr, denominator); 06179 if (sgn(denominator) == sgn(inverse_den)) 06180 refine_no_check(var >= new_var) ; 06181 else 06182 refine_no_check(var <= new_var); 06183 // Remove the temporarily added dimension. 06184 remove_higher_space_dimensions(space_dim-1); 06185 }
| 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.
| expr | The linear expression to test; | |
| from_above | true if and only if the boundedness of interest is "from above". |
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
Definition at line 1147 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::extract_octagonal_difference(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::MINIMIZATION, Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds_from_above(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds_from_below().
01148 { 01149 // The dimension of `expr' should not be greater than the dimension 01150 // of `*this'. 01151 const dimension_type expr_space_dim = expr.space_dimension(); 01152 if (space_dim < expr_space_dim) 01153 throw_dimension_incompatible((from_above 01154 ? "bounds_from_above(e)" 01155 : "bounds_from_below(e)"), "e", expr); 01156 strong_closure_assign(); 01157 01158 // A zero-dimensional or empty octagon bounds everything. 01159 if (space_dim == 0 || marked_empty()) 01160 return true; 01161 01162 // The constraint `c' is used to check if `expr' is an octagonal difference 01163 // and, in this case, to select the cell. 01164 const Constraint& c = (from_above) ? expr <= 0 : expr >= 0; 01165 dimension_type num_vars = 0; 01166 dimension_type i = 0; 01167 dimension_type j = 0; 01168 PPL_DIRTY_TEMP_COEFFICIENT(coeff); 01169 PPL_DIRTY_TEMP_COEFFICIENT(term); 01170 if (extract_octagonal_difference(c, c.space_dimension(), num_vars, 01171 i, j, coeff, term)) { 01172 if (num_vars == 0) 01173 return true; 01174 // Select the cell to be checked. 01175 typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin() + i; 01176 typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter; 01177 return !is_plus_infinity(m_i[j]); 01178 } 01179 else { 01180 // `c' is not an octagonal constraint: use the MIP solver. 01181 Optimization_Mode mode_bounds = 01182 from_above ? MAXIMIZATION : MINIMIZATION; 01183 MIP_Problem mip(space_dim, constraints(), expr, mode_bounds); 01184 return mip.solve() == OPTIMIZED_MIP_PROBLEM; 01185 } 01186 }
| 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.
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
Definition at line 265 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds().
00265 { 00266 return bounds(expr, true); 00267 }
| 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.
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
Definition at line 271 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds().
00271 { 00272 return bounds(expr, false); 00273 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::can_recycle_congruence_systems | ( | ) | [inline, static] |
Returns false indicating that this domain cannot recycle congruences.
Definition at line 525 of file Octagonal_Shape.inlines.hh.
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::can_recycle_constraint_systems | ( | ) | [inline, static] |
Returns false indicating that this domain cannot recycle constraints.
Definition at line 519 of file Octagonal_Shape.inlines.hh.
| 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.
| 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). |
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 3172 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::element_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
03174 { 03175 // Dimension-compatibility check. 03176 if (space_dim != y.space_dim) 03177 throw_dimension_incompatible("CC76_extrapolation_assign(y)", y); 03178 03179 #ifndef NDEBUG 03180 { 03181 // We assume that `y' is contained in or equal to `*this'. 03182 const Octagonal_Shape x_copy = *this; 03183 const Octagonal_Shape y_copy = y; 03184 PPL_ASSERT(x_copy.contains(y_copy)); 03185 } 03186 #endif 03187 03188 // If both octagons are zero-dimensional, 03189 // since `*this' contains `y', we simply return `*this'. 03190 if (space_dim == 0) 03191 return; 03192 03193 strong_closure_assign(); 03194 // If `*this' is empty, since `*this' contains `y', `y' is empty too. 03195 if (marked_empty()) 03196 return; 03197 y.strong_closure_assign(); 03198 // If `y' is empty, we return. 03199 if (y.marked_empty()) 03200 return; 03201 03202 // If there are tokens available, work on a temporary copy. 03203 if (tp != 0 && *tp > 0) { 03204 Octagonal_Shape x_tmp(*this); 03205 x_tmp.CC76_extrapolation_assign(y, first, last, 0); 03206 // If the widening was not precise, use one of the available tokens. 03207 if (!contains(x_tmp)) 03208 --(*tp); 03209 return; 03210 } 03211 03212 // Compare each constraint in `y' to the corresponding one in `*this'. 03213 // The constraint in `*this' is kept as is if it is stronger than or 03214 // equal to the constraint in `y'; otherwise, the inhomogeneous term 03215 // of the constraint in `*this' is further compared with elements taken 03216 // from a sorted container (the stop-points, provided by the user), and 03217 // is replaced by the first entry, if any, which is greater than or equal 03218 // to the inhomogeneous term. If no such entry exists, the constraint 03219 // is removed altogether. 03220 typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin(); 03221 for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(), 03222 matrix_element_end = matrix.element_end(); 03223 i != matrix_element_end; 03224 ++i, ++j) { 03225 const N& y_elem = *j; 03226 N& elem = *i; 03227 if (y_elem < elem) { 03228 Iterator k = std::lower_bound(first, last, elem); 03229 if (k != last) { 03230 if (elem < *k) 03231 assign_r(elem, *k, ROUND_UP); 03232 } 03233 else 03234 assign_r(elem, PLUS_INFINITY, ROUND_NOT_NEEDED); 03235 } 03236 } 03237 03238 reset_strongly_closed(); 03239 PPL_ASSERT(OK()); 03240 }
| 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.
| 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). |
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 578 of file Octagonal_Shape.inlines.hh.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign().
00579 { 00580 static N stop_points[] = { 00581 N(-2, ROUND_UP), 00582 N(-1, ROUND_UP), 00583 N( 0, ROUND_UP), 00584 N( 1, ROUND_UP), 00585 N( 2, ROUND_UP) 00586 }; 00587 CC76_extrapolation_assign(y, 00588 stop_points, 00589 stop_points 00590 + sizeof(stop_points)/sizeof(stop_points[0]), 00591 tp); 00592 }
| 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.
| y | An OS that must contain *this. |
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 3485 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::element_end(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
03485 { 03486 // Dimension-compatibility check. 03487 if (space_dim != y.space_dim) 03488 throw_dimension_incompatible("CC76_narrowing_assign(y)", y); 03489 03490 #ifndef NDEBUG 03491 { 03492 // We assume that `*this' is contained in or equal to `y'. 03493 const Octagonal_Shape x_copy = *this; 03494 const Octagonal_Shape y_copy = y; 03495 PPL_ASSERT(y_copy.contains(x_copy)); 03496 } 03497 #endif 03498 03499 // If both octagons are zero-dimensional, since `*this' contains `y', 03500 // we simply return '*this'. 03501 if (space_dim == 0) 03502 return; 03503 03504 y.strong_closure_assign(); 03505 // If `y' is empty, since `y' contains `*this', `*this' is empty too. 03506 if (y.marked_empty()) 03507 return; 03508 strong_closure_assign(); 03509 // If `*this' is empty, we return. 03510 if (marked_empty()) 03511 return; 03512 03513 // We consider a constraint of `*this', if its value is `plus_infinity', 03514 // we take the value of the corresponding constraint of `y'. 03515 bool is_oct_changed = false; 03516 typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin(); 03517 for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(), 03518 matrix_element_end = matrix.element_end(); 03519 i != matrix_element_end; 03520 ++i, ++j) { 03521 if (!is_plus_infinity(*i) 03522 && !is_plus_infinity(*j) 03523 && *i != *j) { 03524 *i = *j; 03525 is_oct_changed = true; 03526 } 03527 } 03528 03529 if (is_oct_changed && marked_strongly_closed()) 03530 reset_strongly_closed(); 03531 PPL_ASSERT(OK()); 03532 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_leaders | ( | std::vector< dimension_type > & | leaders | ) | const [inline, private] |
Compute the leaders of zero-equivalence classes.
It is assumed that the OS is not empty and strongly closed.
Definition at line 2349 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::is_additive_inverse().
02349 { 02350 PPL_ASSERT(!marked_empty() && marked_strongly_closed()); 02351 PPL_ASSERT(leaders.size() == 0); 02352 // Variables are ordered according to their index. 02353 // The vector `leaders' is used to indicate the smallest variable 02354 // that belongs to the corresponding equivalence class. 02355 const dimension_type leader_size = matrix.num_rows(); 02356 // Initially, each variable is leader of its own zero-equivalence class. 02357 leaders.reserve(leader_size); 02358 for (dimension_type i = 0; i < leader_size; ++i) 02359 leaders.push_back(i); 02360 // Now compute actual leaders. 02361 for (typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin(), 02362 matrix_row_end = matrix.row_end(); 02363 i_iter != matrix_row_end; ++i_iter) { 02364 typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter; 02365 dimension_type i = i_iter.index(); 02366 typename OR_Matrix<N>::const_row_reference_type m_ci 02367 = (i % 2 != 0) ? *(i_iter-1) : *(i_iter+1); 02368 for (dimension_type j = 0; j < i; ++j) { 02369 using namespace Implementation::Octagonal_Shapes; 02370 dimension_type cj = coherent_index(j); 02371 if (is_additive_inverse(m_ci[cj], m_i[j])) 02372 // Choose as leader the variable having the smaller index. 02373 leaders[i] = leaders[j]; 02374 } 02375 } 02376 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_leaders | ( | std::vector< dimension_type > & | successor, | |
| std::vector< dimension_type > & | no_sing_leaders, | |||
| bool & | exist_sing_class, | |||
| dimension_type & | sing_leader | |||
| ) | const [inline, private] |
Compute the leaders of zero-equivalence classes.
It is assumed that the OS is not empty and strongly closed.
Definition at line 2381 of file Octagonal_Shape.templates.hh.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign().
02384 { 02385 PPL_ASSERT(!marked_empty() && marked_strongly_closed()); 02386 PPL_ASSERT(no_sing_leaders.size() == 0); 02387 dimension_type successor_size = successor.size(); 02388 std::deque<bool> dealt_with(successor_size, false); 02389 for (dimension_type i = 0; i < successor_size; ++i) { 02390 dimension_type next_i = successor[i]; 02391 if (!dealt_with[i]) { 02392 // The index is a leader. 02393 // Now check if it is a leader of a singular class or not. 02394 using namespace Implementation::Octagonal_Shapes; 02395 if (next_i == coherent_index(i)) { 02396 exist_sing_class = true; 02397 sing_leader = i; 02398 } 02399 else 02400 no_sing_leaders.push_back(i); 02401 } 02402 // The following index isn't a leader. 02403 dealt_with[next_i] = true; 02404 } 02405 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_successors | ( | std::vector< dimension_type > & | successor | ) | const [inline, private] |
Compute the (zero-equivalence classes) successor relation.
It is assumed that the octagon is not empty and strongly closed.
Definition at line 2317 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::is_additive_inverse().
02317 { 02318 PPL_ASSERT(!marked_empty() && marked_strongly_closed()); 02319 PPL_ASSERT(successor.size() == 0); 02320 // Variables are ordered according to their index. 02321 // The vector `successor' is used to indicate which variable 02322 // immediately follows a given one in the corresponding equivalence class. 02323 const dimension_type successor_size = matrix.num_rows(); 02324 // Initially, each variable is successor of its own zero-equivalence class. 02325 successor.reserve(successor_size); 02326 for (dimension_type i = 0; i < successor_size; ++i) 02327 successor.push_back(i); 02328 // Now compute actual successors. 02329 for (dimension_type i = successor_size; i-- > 0; ) { 02330 typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin()+i; 02331 typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter; 02332 typename OR_Matrix<N>::const_row_reference_type m_ci 02333 = (i % 2 != 0) ? *(i_iter-1) : *(i_iter+1); 02334 for (dimension_type j = 0; j < i; ++j) { 02335 // FIXME: what is the following, commented-out for? 02336 //for (dimension_type j = i; j-- > 0; ) { 02337 using namespace Implementation::Octagonal_Shapes; 02338 dimension_type cj = coherent_index(j); 02339 if (is_additive_inverse(m_ci[cj], m_i[j])) 02340 // Choose as successor the variable having the greatest index. 02341 successor[j] = i; 02342 } 02343 } 02344 }
| 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.
| std::length_error | Thrown if the concatenation would cause the vector space to exceed dimension max_space_dimension(). |
Definition at line 670 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim.
00670 { 00671 // If `y' is an empty 0-dim space octagon, let `*this' become empty. 00672 // If `y' is an universal 0-dim space octagon, we simply return. 00673 if (y.space_dim == 0) { 00674 if (y.marked_empty()) 00675 set_empty(); 00676 return; 00677 } 00678 00679 // If `*this' is an empty 0-dim space octagon, then it is sufficient 00680 // to adjust the dimension of the vector space. 00681 if (space_dim == 0 && marked_empty()) { 00682 add_space_dimensions_and_embed(y.space_dim); 00683 return; 00684 } 00685 00686 // This is the old number of rows in the matrix. It is equal to 00687 // the first index of columns to change. 00688 dimension_type old_num_rows = matrix.num_rows(); 00689 // First we increase the space dimension of `*this' by adding 00690 // `y.space_dimension()' new dimensions. 00691 // The matrix for the new octagon is obtained 00692 // by leaving the old system of constraints in the upper left-hand side 00693 // (where they are at the present) and placing the constraints of `y' in the 00694 // lower right-hand side. 00695 add_space_dimensions_and_embed(y.space_dim); 00696 typename OR_Matrix<N>::const_element_iterator 00697 y_it = y.matrix.element_begin(); 00698 for (typename OR_Matrix<N>::row_iterator i = matrix.row_begin()+old_num_rows, 00699 matrix_row_end = matrix.row_end(); i != matrix_row_end; ++i) { 00700 typename OR_Matrix<N>::row_reference_type r = *i; 00701 dimension_type rs_i = i.row_size(); 00702 for (dimension_type j = old_num_rows; j < rs_i; ++j, ++y_it) 00703 r[j] = *y_it; 00704 } 00705 00706 // The concatenation doesn't preserve the closure. 00707 if (marked_strongly_closed()) 00708 reset_strongly_closed(); 00709 PPL_ASSERT(OK()); 00710 }
| Congruence_System Parma_Polyhedra_Library::Octagonal_Shape< T >::congruences | ( | ) | const [inline] |
Returns a system of (equality) congruences satisfied by *this.
Definition at line 218 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences().
Referenced by Parma_Polyhedra_Library::Grid::Grid().
00218 { 00219 return minimized_congruences(); 00220 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::constrains | ( | Variable | var | ) | const [inline] |
Returns true if and only if var is constrained in *this.
| std::invalid_argument | Thrown if var is not a space dimension of *this. |
Definition at line 1046 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::OR_Matrix< T >::row_size(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
01046 { 01047 // `var' should be one of the dimensions of the octagonal shape. 01048 const dimension_type var_space_dim = var.space_dimension(); 01049 if (space_dimension() < var_space_dim) 01050 throw_dimension_incompatible("constrains(v)", "v", var); 01051 01052 // An octagon known to be empty constrains all variables. 01053 // (Note: do not force emptiness check _yet_) 01054 if (marked_empty()) 01055 return true; 01056 01057 // Check whether `var' is syntactically constrained. 01058 const dimension_type n_v = 2*(var_space_dim - 1); 01059 typename OR_Matrix<N>::const_row_iterator m_iter = matrix.row_begin() + n_v; 01060 typename OR_Matrix<N>::const_row_reference_type r_v = *m_iter; 01061 typename OR_Matrix<N>::const_row_reference_type r_cv = *(++m_iter); 01062 for (dimension_type h = m_iter.row_size(); h-- > 0; ) { 01063 if (!is_plus_infinity(r_v[h]) || !is_plus_infinity(r_cv[h])) 01064 return true; 01065 } 01066 ++m_iter; 01067 for (typename OR_Matrix<N>::const_row_iterator m_end = matrix.row_end(); 01068 m_iter != m_end; ++m_iter) { 01069 typename OR_Matrix<N>::const_row_reference_type r = *m_iter; 01070 if (!is_plus_infinity(r[n_v]) || !is_plus_infinity(r[n_v+1])) 01071 return true; 01072 } 01073 01074 // `var' is not syntactically constrained: 01075 // now force an emptiness check. 01076 return is_empty(); 01077 }
| Constraint_System Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints | ( | ) | const [inline] |
Returns the system of constraints defining *this.
Definition at line 6189 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Constraint_System::zero_dim_empty().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds(), Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_constraints(), Parma_Polyhedra_Library::NNC_Polyhedron::NNC_Polyhedron(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::time_elapse_assign().
06189 { 06190 Constraint_System cs; 06191 if (space_dim == 0) { 06192 if (marked_empty()) 06193 cs = Constraint_System::zero_dim_empty(); 06194 } 06195 else if (marked_empty()) 06196 cs.insert(0*Variable(space_dim-1) <= -1); 06197 else { 06198 // KLUDGE: in the future `cs' will be constructed of the right dimension. 06199 // For the time being, we force the dimension with the following line. 06200 cs.insert(0*Variable(space_dim-1) <= 0); 06201 06202 typedef typename OR_Matrix<N>::const_row_iterator Row_Iterator; 06203 typedef typename OR_Matrix<N>::const_row_reference_type Row_Reference; 06204 06205 Row_Iterator m_begin = matrix.row_begin(); 06206 Row_Iterator m_end = matrix.row_end(); 06207 06208 PPL_DIRTY_TEMP_COEFFICIENT(a); 06209 PPL_DIRTY_TEMP_COEFFICIENT(b); 06210 06211 // Go through all the unary constraints in `matrix'. 06212 for (Row_Iterator i_iter = m_begin; i_iter != m_end; ) { 06213 const dimension_type i = i_iter.index(); 06214 const Variable x(i/2); 06215 const N& c_i_ii = (*i_iter)[i+1]; 06216 ++i_iter; 06217 const N& c_ii_i = (*i_iter)[i]; 06218 ++i_iter; 06219 // Go through unary constraints. 06220 if (is_additive_inverse(c_i_ii, c_ii_i)) { 06221 // We have a unary equality constraint. 06222 numer_denom(c_ii_i, b, a); 06223 a *= 2; 06224 cs.insert(a*x == b); 06225 } 06226 else { 06227 // We have 0, 1 or 2 inequality constraints. 06228 if (!is_plus_infinity(c_i_ii)) { 06229 numer_denom(c_i_ii, b, a); 06230 a *= 2; 06231 cs.insert(-a*x <= b); 06232 } 06233 if (!is_plus_infinity(c_ii_i)) { 06234 numer_denom(c_ii_i, b, a); 06235 a *= 2; 06236 cs.insert(a*x <= b); 06237 } 06238 } 06239 } 06240 // Go through all the binary constraints in `matrix'. 06241 for (Row_Iterator i_iter = m_begin; i_iter != m_end; ) { 06242 const dimension_type i = i_iter.index(); 06243 Row_Reference r_i = *i_iter; 06244 ++i_iter; 06245 Row_Reference r_ii = *i_iter; 06246 ++i_iter; 06247 const Variable y(i/2); 06248 for (dimension_type j = 0; j < i; j += 2) { 06249 const N& c_i_j = r_i[j]; 06250 const N& c_ii_jj = r_ii[j+1]; 06251 const Variable x(j/2); 06252 if (is_additive_inverse(c_ii_jj, c_i_j)) { 06253 // We have an equality constraint of the form ax - ay = b. 06254 numer_denom(c_i_j, b, a); 06255 cs.insert(a*x - a*y == b); 06256 } 06257 else { 06258 // We have 0, 1 or 2 inequality constraints. 06259 if (!is_plus_infinity(c_i_j)) { 06260 numer_denom(c_i_j, b, a); 06261 cs.insert(a*x - a*y <= b); 06262 } 06263 if (!is_plus_infinity(c_ii_jj)) { 06264 numer_denom(c_ii_jj, b, a); 06265 cs.insert(a*y - a*x <= b); 06266 } 06267 } 06268 06269 const N& c_ii_j = r_ii[j]; 06270 const N& c_i_jj = r_i[j+1]; 06271 if (is_additive_inverse(c_i_jj, c_ii_j)) { 06272 // We have an equality constraint of the form ax + ay = b. 06273 numer_denom(c_ii_j, b, a); 06274 cs.insert(a*x + a*y == b); 06275 } 06276 else { 06277 // We have 0, 1 or 2 inequality constraints. 06278 if (!is_plus_infinity(c_i_jj)) { 06279 numer_denom(c_i_jj, b, a); 06280 cs.insert(-a*x - a*y <= b); 06281 } 06282 if (!is_plus_infinity(c_ii_j)) { 06283 numer_denom(c_ii_j, b, a); 06284 cs.insert(a*x + a*y <= b); 06285 } 06286 } 06287 } 06288 } 06289 } 06290 return cs; 06291 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::contains | ( | const Octagonal_Shape< T > & | y | ) | const [inline] |
Returns true if and only if *this contains y.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 714 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::element_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_BHMZ05_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strictly_contains().
00714 { 00715 // Dimension-compatibility check. 00716 if (space_dim != y.space_dim) 00717 throw_dimension_incompatible("contains(y)", y); 00718 00719 // The zero-dimensional universe octagon contains any other 00720 // dimension-compatible octagon. 00721 // The zero-dimensional empty octagon only contains another 00722 // zero-dimensional empty octagon. 00723 if (space_dim == 0) { 00724 if (!marked_empty()) 00725 return true; 00726 else 00727 return y.marked_empty(); 00728 } 00729 00730 // `y' needs to be transitively closed. 00731 y.strong_closure_assign(); 00732 // An empty octagon is in any other dimension-compatible octagons. 00733 if (y.marked_empty()) 00734 return true; 00735 00736 // `*this' contains `y' if and only if every element of `*this' 00737 // is greater than or equal to the correspondent one of `y'. 00738 for (typename OR_Matrix<N>::const_element_iterator 00739 i = matrix.element_begin(), j = y.matrix.element_begin(), 00740 matrix_element_end = matrix.element_end(); i != matrix_element_end; ++i, ++j) 00741 if (*i < *j) 00742 return false; 00743 return true; 00744 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point | ( | ) | const [inline] |
Returns true if and only if *this contains (at least) an integer point.
Definition at line 846 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::element_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty().
00846 { 00847 // Force strong closure. 00848 if (is_empty()) 00849 return false; 00850 const dimension_type space_dim = space_dimension(); 00851 if (space_dim == 0) 00852 return true; 00853 00854 // A strongly closed and consistent Octagonal_Shape defined by 00855 // integer constraints can only be empty due to tight coeherence. 00856 if (std::numeric_limits<T>::is_integer) 00857 return !tight_coherence_would_make_empty(); 00858 00859 // Build an integer Octagonal_Shape oct_z with bounds at least as 00860 // tight as those in *this and then recheck for emptiness, also 00861 // exploiting tight-coherence. 00862 Octagonal_Shape<mpz_class> oct_z(space_dim); 00863 oct_z.reset_strongly_closed(); 00864 00865 typedef Octagonal_Shape<mpz_class>::N Z; 00866 bool all_integers = true; 00867 typename OR_Matrix<N>::const_element_iterator x_i = matrix.element_begin(); 00868 for (typename OR_Matrix<Z>::element_iterator 00869 z_i = oct_z.matrix.element_begin(), 00870 z_end = oct_z.matrix.element_end(); z_i != z_end; ++z_i, ++x_i) { 00871 const N& d = *x_i; 00872 if (is_plus_infinity(d)) 00873 continue; 00874 if (is_integer(d)) 00875 assign_r(*z_i, d, ROUND_NOT_NEEDED); 00876 else { 00877 all_integers = false; 00878 assign_r(*z_i, d, ROUND_DOWN); 00879 } 00880 } 00881 // Restore strong closure. 00882 if (all_integers) 00883 // oct_z unchanged, so it is still strongly closed. 00884 oct_z.set_strongly_closed(); 00885 else { 00886 // oct_z changed: recompute strong closure. 00887 oct_z.strong_closure_assign(); 00888 if (oct_z.marked_empty()) 00889 return false; 00890 } 00891 return !oct_z.tight_coherence_would_make_empty(); 00892 }
| 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:
q >= 1, then -v + u <= -lb_v + lb_u;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:
q <= -1, then -v - u <= -lb_v - ub_u;-1 < q < 0, then -v - u <= -lb_v - ((-q)*ub_u + (1+q)*lb_u). Definition at line 3656 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::neg_assign(), and PPL_DIRTY_TEMP_COEFFICIENT.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::refine().
03660 { 03661 // Private method: the caller has to ensure the following. 03662 PPL_ASSERT(sc_den > 0); 03663 PPL_ASSERT(!is_plus_infinity(minus_lb_v)); 03664 03665 PPL_DIRTY_TEMP0(mpq_class, mpq_sc_den); 03666 assign_r(mpq_sc_den, sc_den, ROUND_NOT_NEEDED); 03667 03668 // No need to consider indices greater than `last_id'. 03669 const dimension_type n_v = 2*v_id; 03670 typename OR_Matrix<N>::row_reference_type m_v = matrix[n_v]; 03671 03672 // Speculatively allocate temporaries out of the loop. 03673 PPL_DIRTY_TEMP(N, half); 03674 PPL_DIRTY_TEMP0(mpq_class, ub_u); 03675 PPL_DIRTY_TEMP0(mpq_class, q); 03676 PPL_DIRTY_TEMP0(mpq_class, minus_lb_u); 03677 PPL_DIRTY_TEMP(N, up_approx); 03678 PPL_DIRTY_TEMP_COEFFICIENT(minus_expr_u); 03679 03680 for (dimension_type u_id = last_id+1; u_id-- > 0; ) { 03681 // Skip the case when `u_id == v_id'. 03682 if (u_id == v_id) 03683 continue; 03684 const Coefficient& expr_u = sc_expr.coefficient(Variable(u_id)); 03685 // Skip the case when `expr_u == 0'. 03686 if (expr_u == 0) 03687 continue; 03688 03689 const dimension_type n_u = u_id*2; 03690 // If `expr_u' is positive, we can improve `-v + u'. 03691 if (expr_u > 0) { 03692 if (expr_u >= sc_den) { 03693 // Here q >= 1: deducing `-v + u <= lb_u - lb_v', 03694 // i.e., `u - v <= (-lb_v) - (-lb_u)'. 03695 // We avoid to check if `lb_u' is plus infinity, because 03696 // it is used for the computation of `lb_v'. 03697 // Let half = m_u_cu / 2. 03698 div_2exp_assign_r(half, matrix[n_u][n_u+1], 1, ROUND_UP); 03699 N& m_u_minus_v = (n_v < n_u) ? matrix[n_u+1][n_v+1] : m_v[n_u]; 03700 sub_assign_r(m_u_minus_v, minus_lb_v, half, ROUND_UP); 03701 } 03702 else { 03703 // Here 0 < q < 1. 03704 typename OR_Matrix<N>::row_reference_type m_cu = matrix[n_u+1]; 03705 const N& m_cu_u = m_cu[n_u]; 03706 if (!is_plus_infinity(m_cu_u)) { 03707 // Let `ub_u' and `lb_u' be the known upper and lower bound 03708 // for `u', respectively. The upper bound for `u - v' is 03709 // computed as `(q * lb_u + (1-q) * ub_u) - lb_v', 03710 // i.e., `ub_u - q * (ub_u + (-lb_u)) + minus_lb_v'. 03711 assign_r(ub_u, m_cu[n_u], ROUND_NOT_NEEDED); 03712 div_2exp_assign_r(ub_u, ub_u, 1, ROUND_NOT_NEEDED); 03713 assign_r(q, expr_u, ROUND_NOT_NEEDED); 03714 div_assign_r(q, q, mpq_sc_den, ROUND_NOT_NEEDED); 03715 assign_r(minus_lb_u, matrix[n_u][n_u+1], ROUND_NOT_NEEDED); 03716 div_2exp_assign_r(minus_lb_u, minus_lb_u, 1, ROUND_NOT_NEEDED); 03717 // Compute `ub_u - lb_u'. 03718 add_assign_r(minus_lb_u, ub_u, minus_lb_u, ROUND_NOT_NEEDED); 03719 // Compute `ub_u - q * (ub_u - lb_u)'. 03720 sub_mul_assign_r(ub_u, q, minus_lb_u, ROUND_NOT_NEEDED); 03721 assign_r(up_approx, ub_u, ROUND_UP); 03722 // Deducing `u - v <= -lb_v - (q * lb_u + (1-q) * ub_u)'. 03723 N& m_u_minus_v = (n_v < n_u) ? m_cu[n_v+1] : m_v[n_u]; 03724 add_assign_r(m_u_minus_v, minus_lb_v, up_approx, ROUND_UP); 03725 } 03726 } 03727 } 03728 else { 03729 PPL_ASSERT(expr_u < 0); 03730 // If `expr_u' is negative, we can improve `-v - u'. 03731 neg_assign(minus_expr_u, expr_u); 03732 if (minus_expr_u >= sc_den) { 03733 // Here q <= -1: Deducing `-v - u <= -lb_v - ub_u'. 03734 // We avoid to check if `ub_u' is plus infinity, because 03735 // it is used for the computation of `lb_v'. 03736 // Let half = m_cu_u / 2. 03737 div_2exp_assign_r(half, matrix[n_u+1][n_u], 1, ROUND_UP); 03738 N& m_minus_v_minus_u = (n_v < n_u) ? matrix[n_u][n_v+1] : m_v[n_u+1]; 03739 sub_assign_r(m_minus_v_minus_u, minus_lb_v, half, ROUND_UP); 03740 } 03741 else { 03742 // Here -1 < q < 0. 03743 typename OR_Matrix<N>::row_reference_type m_u = matrix[n_u]; 03744 const N& m_u_cu = m_u[n_u+1]; 03745 if (!is_plus_infinity(m_u_cu)) { 03746 // Let `ub_u' and `lb_u' be the known upper and lower bound 03747 // for `u', respectively. The upper bound for `-v - u' is 03748 // computed as `-lb_v - ((-q)*ub_u + (1+q)*lb_u)', 03749 // i.e., `minus_lb_v - lb_u + q*(ub_u - lb_u)'. 03750 assign_r(ub_u, matrix[n_u+1][n_u], ROUND_NOT_NEEDED); 03751 div_2exp_assign_r(ub_u, ub_u, 1, ROUND_NOT_NEEDED); 03752 assign_r(q, expr_u, ROUND_NOT_NEEDED); 03753 div_assign_r(q, q, mpq_sc_den, ROUND_NOT_NEEDED); 03754 assign_r(minus_lb_u, m_u[n_u+1], ROUND_NOT_NEEDED); 03755 div_2exp_assign_r(minus_lb_u, minus_lb_u, 1, ROUND_NOT_NEEDED); 03756 // Compute `ub_u - lb_u'. 03757 add_assign_r(ub_u, ub_u, minus_lb_u, ROUND_NOT_NEEDED); 03758 // Compute `-lb_u + q*(ub_u - lb_u)'. 03759 add_mul_assign_r(minus_lb_u, q, ub_u, ROUND_NOT_NEEDED); 03760 assign_r(up_approx, minus_lb_u, ROUND_UP); 03761 // Deducing `-v - u <= -lb_v - ((-q) * ub_u + (1+q) * lb_u)'. 03762 N& m_minus_v_minus_u = (n_v < n_u) ? m_u[n_v+1] : m_v[n_u+1]; 03763 add_assign_r(m_minus_v_minus_u, minus_lb_v, up_approx, ROUND_UP); 03764 } 03765 } 03766 } 03767 } 03768 }
| 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:
q >= 1, then v - u <= ub_v - ub_u;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:
q <= -1, then v + u <= ub_v + lb_u;-1 < q < 0, then v + u <= ub_v + ((-q)*lb_u + (1+q)*ub_u). Definition at line 3537 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::neg_assign(), and PPL_DIRTY_TEMP_COEFFICIENT.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::refine().
03541 { 03542 // Private method: the caller has to ensure the following. 03543 PPL_ASSERT(sc_den > 0); 03544 PPL_ASSERT(!is_plus_infinity(ub_v)); 03545 03546 PPL_DIRTY_TEMP0(mpq_class, mpq_sc_den); 03547 assign_r(mpq_sc_den, sc_den, ROUND_NOT_NEEDED); 03548 03549 // No need to consider indices greater than `last_id'. 03550 const dimension_type n_v = 2*v_id; 03551 typename OR_Matrix<N>::row_reference_type m_cv = matrix[n_v+1]; 03552 03553 // Speculatively allocate temporaries out of the loop. 03554 PPL_DIRTY_TEMP(N, half); 03555 PPL_DIRTY_TEMP0(mpq_class, minus_lb_u); 03556 PPL_DIRTY_TEMP0(mpq_class, q); 03557 PPL_DIRTY_TEMP0(mpq_class, minus_q); 03558 PPL_DIRTY_TEMP0(mpq_class, ub_u); 03559 PPL_DIRTY_TEMP0(mpq_class, lb_u); 03560 PPL_DIRTY_TEMP(N, up_approx); 03561 PPL_DIRTY_TEMP_COEFFICIENT(minus_expr_u); 03562 03563 for (dimension_type u_id = last_id+1; u_id-- > 0; ) { 03564 // Skip the case when `u_id == v_id'. 03565 if (u_id == v_id) 03566 continue; 03567 const Coefficient& expr_u = sc_expr.coefficient(Variable(u_id)); 03568 // Skip the case when `expr_u == 0'. 03569 if (expr_u == 0) 03570 continue; 03571 03572 const dimension_type n_u = u_id*2; 03573 // If `expr_u' is positive, we can improve `v - u'. 03574 if (expr_u > 0) { 03575 if (expr_u >= sc_den) { 03576 // Here q >= 1: deducing `v - u <= ub_v - ub_u'. 03577 // We avoid to check if `ub_u' is plus infinity, because 03578 // it is used for the computation of `ub_v'. 03579 // Let half = m_cu_u / 2. 03580 div_2exp_assign_r(half, matrix[n_u+1][n_u], 1, ROUND_UP); 03581 N& m_v_minus_u = (n_v < n_u) ? matrix[n_u][n_v] : m_cv[n_u+1]; 03582 sub_assign_r(m_v_minus_u, ub_v, half, ROUND_UP); 03583 } 03584 else { 03585 // Here 0 < q < 1. 03586 typename OR_Matrix<N>::row_reference_type m_u = matrix[n_u]; 03587 const N& m_u_cu = m_u[n_u+1]; 03588 if (!is_plus_infinity(m_u_cu)) { 03589 // Let `ub_u' and `lb_u' be the known upper and lower bound 03590 // for `u', respectively. The upper bound for `v - u' is 03591 // computed as `ub_v - (q * ub_u + (1-q) * lb_u)', 03592 // i.e., `ub_v + (-lb_u) - q * (ub_u + (-lb_u))'. 03593 assign_r(minus_lb_u, m_u_cu, ROUND_NOT_NEEDED); 03594 div_2exp_assign_r(minus_lb_u, minus_lb_u, 1, ROUND_NOT_NEEDED); 03595 assign_r(q, expr_u, ROUND_NOT_NEEDED); 03596 div_assign_r(q, q, mpq_sc_den, ROUND_NOT_NEEDED); 03597 assign_r(ub_u, matrix[n_u+1][n_u], ROUND_NOT_NEEDED); 03598 div_2exp_assign_r(ub_u, ub_u, 1, ROUND_NOT_NEEDED); 03599 // Compute `ub_u - lb_u'. 03600 add_assign_r(ub_u, ub_u, minus_lb_u, ROUND_NOT_NEEDED); 03601 // Compute `(-lb_u) - q * (ub_u - lb_u)'. 03602 sub_mul_assign_r(minus_lb_u, q, ub_u, ROUND_NOT_NEEDED); 03603 assign_r(up_approx, minus_lb_u, ROUND_UP); 03604 // Deducing `v - u <= ub_v - (q * ub_u + (1-q) * lb_u)'. 03605 N& m_v_minus_u = (n_v < n_u) ? m_u[n_v] : m_cv[n_u+1]; 03606 add_assign_r(m_v_minus_u, ub_v, up_approx, ROUND_UP); 03607 } 03608 } 03609 } 03610 else { 03611 PPL_ASSERT(expr_u < 0); 03612 // If `expr_u' is negative, we can improve `v + u'. 03613 neg_assign(minus_expr_u, expr_u); 03614 if (minus_expr_u >= sc_den) { 03615 // Here q <= -1: Deducing `v + u <= ub_v + lb_u'. 03616 // We avoid to check if `lb_u' is plus infinity, because 03617 // it is used for the computation of `ub_v'. 03618 // Let half = m_u_cu / 2. 03619 div_2exp_assign_r(half, matrix[n_u][n_u+1], 1, ROUND_UP); 03620 N& m_v_plus_u = (n_v < n_u) ? matrix[n_u+1][n_v] : m_cv[n_u]; 03621 sub_assign_r(m_v_plus_u, ub_v, half, ROUND_UP); 03622 } 03623 else { 03624 // Here -1 < q < 0. 03625 typename OR_Matrix<N>::row_reference_type m_cu = matrix[n_u+1]; 03626 const N& m_cu_u = m_cu[n_u]; 03627 if (!is_plus_infinity(m_cu_u)) { 03628 // Let `ub_u' and `lb_u' be the known upper and lower bound 03629 // for `u', respectively. The upper bound for `v + u' is 03630 // computed as `ub_v + ((-q) * lb_u + (1+q) * ub_u)', 03631 // i.e., `ub_v + ub_u + (-q) * (lb_u - ub_u)'. 03632 assign_r(ub_u, m_cu[n_u], ROUND_NOT_NEEDED); 03633 div_2exp_assign_r(ub_u, ub_u, 1, ROUND_NOT_NEEDED); 03634 assign_r(minus_q, minus_expr_u, ROUND_NOT_NEEDED); 03635 div_assign_r(minus_q, minus_q, mpq_sc_den, ROUND_NOT_NEEDED); 03636 assign_r(lb_u, matrix[n_u][n_u+1], ROUND_NOT_NEEDED); 03637 div_2exp_assign_r(lb_u, lb_u, 1, ROUND_NOT_NEEDED); 03638 neg_assign_r(lb_u, lb_u, ROUND_NOT_NEEDED); 03639 // Compute `lb_u - ub_u'. 03640 sub_assign_r(lb_u, lb_u, ub_u, ROUND_NOT_NEEDED); 03641 // Compute `ub_u + (-q) * (lb_u - ub_u)'. 03642 add_mul_assign_r(ub_u, minus_q, lb_u, ROUND_NOT_NEEDED); 03643 assign_r(up_approx, ub_u, ROUND_UP); 03644 // Deducing `v + u <= ub_v + ((-q) * lb_u + (1+q) * ub_u)'. 03645 N& m_v_plus_u = (n_v < n_u) ? m_cu[n_v] : m_cv[n_u]; 03646 add_assign_r(m_v_plus_u, ub_v, up_approx, ROUND_UP); 03647 } 03648 } 03649 } 03650 } 03651 }
| 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.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 2605 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Poly_Con_Relation::implies(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign().
02605 { 02606 // Dimension-compatibility check. 02607 if (space_dim != y.space_dim) 02608 throw_dimension_incompatible("difference_assign(y)", y); 02609 02610 Octagonal_Shape& x = *this; 02611 02612 // Being lazy here is only harmful. 02613 // We close. 02614 x.strong_closure_assign(); 02615 // The difference of an empty octagon and of an octagon `p' is empty. 02616 if (x.marked_empty()) 02617 return; 02618 // The difference of a octagon `p' and an empty octagon is `p'. 02619 if (y.marked_empty()) 02620 return; 02621 02622 // If both octagons are zero-dimensional, 02623 // then at this point they are necessarily universe octagons, 02624 // so that their difference is empty. 02625 if (x.space_dim == 0) { 02626 x.set_empty(); 02627 return; 02628 } 02629 02630 // TODO: This is just an executable specification. 02631 // Have to find a more efficient method. 02632 if (y.contains(x)) { 02633 x.set_empty(); 02634 return; 02635 } 02636 02637 Octagonal_Shape new_oct(space_dim, EMPTY); 02638 // We take a constraint of the octagon y at the time and we 02639 // consider its complementary. Then we intersect the union 02640 // of these complementaries with the octagon x. 02641 const Constraint_System& y_cs = y.constraints(); 02642 for (Constraint_System::const_iterator i = y_cs.begin(), 02643 y_cs_end = y_cs.end(); i != y_cs_end; ++i) { 02644 const Constraint& c = *i; 02645 // If the octagon `x' is included the octagon defined by `c', 02646 // then `c' _must_ be skipped, as adding its complement to `x' 02647 // would result in the empty octagon, and as we would obtain 02648 // a result that is less precise than the difference. 02649 if (x.relation_with(c).implies(Poly_Con_Relation::is_included())) 02650 continue; 02651 Octagonal_Shape z = x; 02652 const Linear_Expression e = Linear_Expression(c); 02653 z.add_constraint(e <= 0); 02654 if (!z.is_empty()) 02655 new_oct.upper_bound_assign(z); 02656 if (c.is_equality()) { 02657 z = x; 02658 z.add_constraint(e >= 0); 02659 if (!z.is_empty()) 02660 new_oct.upper_bound_assign(z); 02661 } 02662 } 02663 *this = new_oct; 02664 PPL_ASSERT(OK()); 02665 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points | ( | const Variables_Set & | vars, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline] |
Possibly tightens *this by dropping some points with non-integer coordinates for the space dimensions corresponding to vars.
| vars | Points with non-integer coordinates for these variables/space-dimensions can be discarded. | |
| complexity | The maximal complexity of any algorithms used. |
complexity is ANY_COMPLEXITY. Definition at line 6820 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::is_even(), Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::is_plus_infinity(), and Parma_Polyhedra_Library::Variables_Set::space_dimension().
06821 { 06822 // Dimension-compatibility check. 06823 const dimension_type min_space_dim = vars.space_dimension(); 06824 if (space_dimension() < min_space_dim) 06825 throw_dimension_incompatible("drop_some_non_integer_points(vs, cmpl)", 06826 min_space_dim); 06827 06828 if (std::numeric_limits<T>::is_integer || min_space_dim == 0) 06829 return; 06830 06831 strong_closure_assign(); 06832 if (marked_empty()) 06833 return; 06834 06835 PPL_DIRTY_TEMP(N, temp_one); 06836 assign_r(temp_one, 1, ROUND_NOT_NEEDED); 06837 06838 const Variables_Set::const_iterator v_begin = vars.begin(); 06839 const Variables_Set::const_iterator v_end = vars.end(); 06840 PPL_ASSERT(v_begin != v_end); 06841 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 06842 for (Variables_Set::const_iterator v_i = v_begin; v_i != v_end; ++v_i) { 06843 const dimension_type i = 2 * (*v_i); 06844 const dimension_type ci = i + 1; 06845 Row_Reference m_i = matrix[i]; 06846 Row_Reference m_ci = matrix[ci]; 06847 06848 // Unary constaints: should be even integers. 06849 N& m_i_ci = m_i[ci]; 06850 if (!is_plus_infinity(m_i_ci)) { 06851 drop_some_non_integer_points_helper(m_i_ci); 06852 if (!is_even(m_i_ci)) { 06853 sub_assign_r(m_i_ci, m_i_ci, temp_one, ROUND_UP); 06854 reset_strongly_closed(); 06855 } 06856 } 06857 N& m_ci_i = m_ci[i]; 06858 if (!is_plus_infinity(m_ci_i)) { 06859 drop_some_non_integer_points_helper(m_ci_i); 06860 if (!is_even(m_ci_i)) { 06861 sub_assign_r(m_ci_i, m_ci_i, temp_one, ROUND_UP); 06862 reset_strongly_closed(); 06863 } 06864 } 06865 06866 // Binary constraints (note: only consider j < i). 06867 for (Variables_Set::const_iterator v_j = v_begin; v_j != v_i; ++v_j) { 06868 const dimension_type j = 2 * (*v_j); 06869 const dimension_type cj = j + 1; 06870 drop_some_non_integer_points_helper(m_i[j]); 06871 drop_some_non_integer_points_helper(m_i[cj]); 06872 drop_some_non_integer_points_helper(m_ci[j]); 06873 drop_some_non_integer_points_helper(m_ci[cj]); 06874 } 06875 } 06876 PPL_ASSERT(OK()); 06877 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points | ( | Complexity_Class | complexity = ANY_COMPLEXITY |
) | [inline] |
Possibly tightens *this by dropping some points with non-integer coordinates.
| complexity | The maximal complexity of any algorithms used. |
complexity is ANY_COMPLEXITY. Definition at line 6784 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points_helper(), Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::element_end(), Parma_Polyhedra_Library::is_even(), Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().
06784 { 06785 if (std::numeric_limits<T>::is_integer) 06786 return; 06787 06788 const dimension_type space_dim = space_dimension(); 06789 strong_closure_assign(); 06790 if (space_dim == 0 || marked_empty()) 06791 return; 06792 06793 for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(), 06794 i_end = matrix.element_end(); i != i_end; ++i) 06795 drop_some_non_integer_points_helper(*i); 06796 06797 // Unary constraints should have an even integer boundary. 06798 PPL_DIRTY_TEMP(N, temp_one); 06799 assign_r(temp_one, 1, ROUND_NOT_NEEDED); 06800 for (dimension_type i = 0; i < 2*space_dim; i += 2) { 06801 const dimension_type ci = i+1; 06802 N& mat_i_ci = matrix[i][ci]; 06803 if (!is_plus_infinity(mat_i_ci) && !is_even(mat_i_ci)) { 06804 sub_assign_r(mat_i_ci, mat_i_ci, temp_one, ROUND_UP); 06805 reset_strongly_closed(); 06806 } 06807 N& mat_ci_i = matrix[ci][i]; 06808 if (!is_plus_infinity(mat_ci_i) && !is_even(mat_ci_i)) { 06809 sub_assign_r(mat_ci_i, mat_ci_i, temp_one, ROUND_UP); 06810 reset_strongly_closed(); 06811 } 06812 } 06813 06814 PPL_ASSERT(OK()); 06815 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points_helper | ( | N & | elem | ) | [inline, private] |
Definition at line 825 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), and Parma_Polyhedra_Library::Checked::Result.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points().
00825 { 00826 if (!is_integer(elem)) { 00827 #ifndef NDEBUG 00828 Result r = 00829 #endif 00830 floor_assign_r(elem, elem, ROUND_DOWN); 00831 PPL_ASSERT(r == V_EQ); 00832 reset_strongly_closed(); 00833 } 00834 }
| 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.
| var | The variable corresponding to the space dimension to be replicated; | |
| m | The number of replicas to be created. |
| 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
, with
, and var has space dimension
, then the
-th space dimension is expanded to m new space dimensions
,
,
,
.
Definition at line 6295 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::max_space_dimension(), Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
06295 { 06296 // `var' should be one of the dimensions of the vector space. 06297 const dimension_type var_id = var.id(); 06298 if (var_id+1 > space_dim) 06299 throw_dimension_incompatible("expand_space_dimension(v, m)", var_id+1); 06300 06301 // The space dimension of the resulting octagon should not 06302 // overflow the maximum allowed space dimension. 06303 if (m > max_space_dimension() - space_dim) 06304 throw_generic("expand_dimension(v, m)", 06305 "adding m new space dimensions exceeds " 06306 "the maximum allowed space dimension"); 06307 06308 // Nothing to do, if no dimensions must be added. 06309 if (m == 0) 06310 return; 06311 06312 // Keep track of the dimension before adding the new ones. 06313 const dimension_type old_num_rows = matrix.num_rows(); 06314 06315 // Add the required new dimensions. 06316 add_space_dimensions_and_embed(m); 06317 06318 // For each constraints involving variable `var', we add a 06319 // similar constraint with the new variable substituted for 06320 // variable `var'. 06321 typedef typename OR_Matrix<N>::row_iterator Row_Iterator; 06322 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 06323 typedef typename OR_Matrix<N>::const_row_iterator Row_iterator; 06324 typedef typename OR_Matrix<N>::const_row_reference_type Row_reference; 06325 06326 const Row_Iterator m_begin = matrix.row_begin(); 06327 const Row_Iterator m_end = matrix.row_end(); 06328 const dimension_type n_var = 2*var_id; 06329 Row_iterator v_iter = m_begin + n_var; 06330 Row_reference m_v = *v_iter; 06331 Row_reference m_cv = *(v_iter+1); 06332 06333 for (Row_Iterator i_iter = m_begin + old_num_rows; i_iter != m_end; 06334 i_iter += 2) { 06335 Row_Reference m_i = *i_iter; 06336 Row_Reference m_ci = *(i_iter+1); 06337 const dimension_type i = i_iter.index(); 06338 const dimension_type ci = i+1; 06339 m_i[ci] = m_v[n_var+1]; 06340 m_ci[i] = m_cv[n_var]; 06341 for (dimension_type j = 0; j < n_var; ++j) { 06342 m_i[j] = m_v[j]; 06343 m_ci[j] = m_cv[j]; 06344 } 06345 for (dimension_type j = n_var+2; j < old_num_rows; ++j) { 06346 Row_Iterator j_iter = m_begin + j; 06347 Row_Reference m_cj = (j % 2 != 0) ? *(j_iter-1) : *(j_iter+1); 06348 m_i[j] = m_cj[n_var+1]; 06349 m_ci[j] = m_cj[n_var]; 06350 } 06351 } 06352 // In general, adding a constraint does not preserve the strong closure 06353 // of the octagon. 06354 if (marked_strongly_closed()) 06355 reset_strongly_closed(); 06356 PPL_ASSERT(OK()); 06357 }
| memory_size_type Parma_Polyhedra_Library::Octagonal_Shape< T >::external_memory_in_bytes | ( | ) | const [inline] |
Returns the size in bytes of the memory managed by *this.
Definition at line 7087 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::OR_Matrix< T >::external_memory_in_bytes(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::total_memory_in_bytes().
07087 { 07088 return matrix.external_memory_in_bytes(); 07089 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions | ( | const Variables_Set & | vars, | |
| Variable | dest | |||
| ) | [inline] |
Folds the space dimensions in vars into dest.
| vars | The set of Variable objects corresponding to the space dimensions to be folded; | |
| dest | The variable corresponding to the space dimension that is the destination of the folding operation. |
| std::invalid_argument | Thrown if *this is dimension-incompatible with dest or with one of the Variable objects contained in vars. Also thrown if dest is contained in vars. |
If *this has space dimension
, with
, dest has space dimension
, vars is a set of variables whose maximum space dimension is also less than or equal to
, and dest is not a member of vars, then the space dimensions corresponding to variables in vars are folded into the
-th space dimension.
Definition at line 6361 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::max_assign(), Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
06362 { 06363 // `dest' should be one of the dimensions of the octagon. 06364 if (dest.space_dimension() > space_dim) 06365 throw_dimension_incompatible("fold_space_dimensions(vs, v)", "v", dest); 06366 06367 // The folding of no dimensions is a no-op. 06368 if (vars.empty()) 06369 return; 06370 06371 // All variables in `vars' should be dimensions of the octagon. 06372 if (vars.space_dimension() > space_dim) 06373 throw_dimension_incompatible("fold_space_dimensions(vs, v)", 06374 vars.space_dimension()); 06375 06376 // Moreover, `dest.id()' should not occur in `vars'. 06377 if (vars.find(dest.id()) != vars.end()) 06378 throw_generic("fold_space_dimensions(vs, v)", 06379 "v should not occur in vs"); 06380 06381 // Recompute the elements of the row and the column corresponding 06382 // to variable `dest' by taking the join of their value with the 06383 // value of the corresponding elements in the row and column of the 06384 // variable `vars'. 06385 typedef typename OR_Matrix<N>::row_iterator Row_Iterator; 06386 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 06387 06388 const Row_Iterator m_begin = matrix.row_begin(); 06389 06390 strong_closure_assign(); 06391 const dimension_type n_rows = matrix.num_rows(); 06392 const dimension_type n_dest = 2*dest.id(); 06393 Row_Iterator v_iter = m_begin + n_dest; 06394 Row_Reference m_v = *v_iter; 06395 Row_Reference m_cv = *(v_iter+1); 06396 for (Variables_Set::const_iterator i = vars.begin(), 06397 vs_end = vars.end(); i != vs_end; ++i) { 06398 const dimension_type tbf_id = *i; 06399 const dimension_type tbf_var = 2*tbf_id; 06400 Row_Iterator tbf_iter = m_begin + tbf_var; 06401 Row_Reference m_tbf = *tbf_iter; 06402 Row_Reference m_ctbf = *(tbf_iter+1); 06403 max_assign(m_v[n_dest+1], m_tbf[tbf_var+1]); 06404 max_assign(m_cv[n_dest], m_ctbf[tbf_var]); 06405 06406 const dimension_type min_id = std::min(n_dest, tbf_var); 06407 const dimension_type max_id = std::max(n_dest, tbf_var); 06408 06409 using namespace Implementation::Octagonal_Shapes; 06410 for (dimension_type j = 0; j < min_id; ++j) { 06411 const dimension_type cj = coherent_index(j); 06412 max_assign(m_v[j], m_tbf[j]); 06413 max_assign(m_cv[j], m_ctbf[j]); 06414 max_assign(m_cv[cj], m_ctbf[cj]); 06415 max_assign(m_v[cj], m_tbf[cj]); 06416 } 06417 for (dimension_type j = min_id+2; j < max_id; ++j) { 06418 const dimension_type cj = coherent_index(j); 06419 Row_Iterator j_iter = m_begin + j; 06420 Row_Reference m_j = *j_iter; 06421 Row_Reference m_cj = (j % 2 != 0) ? *(j_iter-1) : *(j_iter+1); 06422 if (n_dest == min_id) { 06423 max_assign(m_cj[n_dest+1], m_tbf[j]); 06424 max_assign(m_cj[n_dest], m_ctbf[j]); 06425 max_assign(m_j[n_dest], m_ctbf[cj]); 06426 max_assign(m_j[n_dest+1], m_tbf[cj]); 06427 } 06428 else { 06429 max_assign(m_v[j], m_cj[tbf_var+1]); 06430 max_assign(m_cv[j], m_cj[tbf_var]); 06431 max_assign(m_cv[cj], m_j[tbf_var]); 06432 max_assign(m_v[cj], m_j[tbf_var+1]); 06433 } 06434 } 06435 for (dimension_type j = max_id+2; j < n_rows; ++j) { 06436 Row_Iterator j_iter = m_begin + j; 06437 Row_Reference m_j = *j_iter; 06438 Row_Reference m_cj = (j % 2 != 0) ? *(j_iter-1) : *(j_iter+1); 06439 max_assign(m_cj[n_dest+1], m_cj[tbf_var+1]); 06440 max_assign(m_cj[n_dest], m_cj[tbf_var]); 06441 max_assign(m_j[n_dest], m_j[tbf_var]); 06442 max_assign(m_j[n_dest+1], m_j[tbf_var+1]); 06443 } 06444 } 06445 remove_space_dimensions(vars); 06446 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints | ( | dimension_type | v_id | ) | [inline, private] |
Removes all the constraints on variable v_id.
Definition at line 3773 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::PLUS_INFINITY, and Parma_Polyhedra_Library::OR_Matrix< T >::row_size().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain().
03773 { 03774 PPL_ASSERT(v_id < space_dim); 03775 const dimension_type n_v = 2*v_id; 03776 typename OR_Matrix<N>::row_iterator m_iter = matrix.row_begin() + n_v; 03777 typename OR_Matrix<N>::row_reference_type r_v = *m_iter; 03778 typename OR_Matrix<N>::row_reference_type r_cv = *(++m_iter); 03779 for (dimension_type h = m_iter.row_size(); h-- > 0; ) { 03780 assign_r(r_v[h], PLUS_INFINITY, ROUND_NOT_NEEDED); 03781 assign_r(r_cv[h], PLUS_INFINITY, ROUND_NOT_NEEDED); 03782 } 03783 ++m_iter; 03784 for (typename OR_Matrix<N>::row_iterator m_end = matrix.row_end(); 03785 m_iter != m_end; ++m_iter) { 03786 typename OR_Matrix<N>::row_reference_type r = *m_iter; 03787 assign_r(r[n_v], PLUS_INFINITY, ROUND_NOT_NEEDED); 03788 assign_r(r[n_v+1], PLUS_INFINITY, ROUND_NOT_NEEDED); 03789 } 03790 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_binary_octagonal_constraints | ( | dimension_type | v_id | ) | [inline, private] |
Removes all binary constraints on variable v_id.
Definition at line 3795 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), and Parma_Polyhedra_Library::PLUS_INFINITY.
03795 { 03796 PPL_ASSERT(v_id < space_dim); 03797 const dimension_type n_v = 2*v_id; 03798 typename OR_Matrix<N>::row_iterator m_iter = matrix.row_begin() + n_v; 03799 typename OR_Matrix<N>::row_reference_type r_v = *m_iter; 03800 typename OR_Matrix<N>::row_reference_type r_cv = *(++m_iter); 03801 for (dimension_type k = n_v; k-- > 0; ) { 03802 assign_r(r_v[k], PLUS_INFINITY, ROUND_NOT_NEEDED); 03803 assign_r(r_cv[k], PLUS_INFINITY, ROUND_NOT_NEEDED); 03804 } 03805 ++m_iter; 03806 for (typename OR_Matrix<N>::row_iterator m_end = matrix.row_end(); 03807 m_iter != m_end; ++m_iter) { 03808 typename OR_Matrix<N>::row_reference_type r = *m_iter; 03809 assign_r(r[n_v], PLUS_INFINITY, ROUND_NOT_NEEDED); 03810 assign_r(r[n_v+1], PLUS_INFINITY, ROUND_NOT_NEEDED); 03811 } 03812 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::frequency | ( | const Linear_Expression & | expr, | |
| Coefficient & | freq_n, | |||
| Coefficient & | freq_d, | |||
| Coefficient & | val_n, | |||
| Coefficient & | val_d | |||
| ) | const [inline] |
Returns true if and only if there exist a unique value val such that *this saturates the equality expr = val.
| expr | The linear expression for which the frequency is needed; | |
| freq_n | If true is returned, the value is set to ; Present for interface compatibility with class Grid, where the frequency can have a non-zero value; | |
| freq_d | If true is returned, the value is set to ; | |
| val_n | The numerator of val; | |
| val_d | The denominator of val; |
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
If false is returned, then freq_n, freq_d, val_n and val_d are left untouched.
Definition at line 896 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Checked::le, Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::normalize2(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
00898 { 00899 dimension_type space_dim = space_dimension(); 00900 // The dimension of `expr' must be at most the dimension of *this. 00901 if (space_dim < expr.space_dimension()) 00902 throw_dimension_incompatible("frequency(e, ...)", "e", expr); 00903 00904 // Check if `expr' has a constant value. 00905 // If it is constant, set the frequency `freq_n' to 0 00906 // and return true. Otherwise the values for \p expr 00907 // are not discrete so return false. 00908 00909 // Space dimension = 0: if empty, then return false; 00910 // otherwise the frequency is 0 and the value is the inhomogeneous term. 00911 if (space_dim == 0) { 00912 if (is_empty()) 00913 return false; 00914 freq_n = 0; 00915 freq_d = 1; 00916 val_n = expr.inhomogeneous_term(); 00917 val_d = 1; 00918 return true; 00919 } 00920 00921 strong_closure_assign(); 00922 // For an empty Octagonal shape, we simply return false. 00923 if (marked_empty()) 00924 return false; 00925 00926 // The Octagonal shape has at least 1 dimension and is not empty. 00927 PPL_DIRTY_TEMP_COEFFICIENT(coeff); 00928 PPL_DIRTY_TEMP_COEFFICIENT(coeff_j); 00929 PPL_DIRTY_TEMP_COEFFICIENT(num); 00930 PPL_DIRTY_TEMP_COEFFICIENT(den); 00931 Linear_Expression le = expr; 00932 // Boolean to keep track of a variable `v' in expression `le'. 00933 // If we can replace `v' by an expression using variables other 00934 // than `v' and are already in `le', then this is set to true. 00935 bool constant_v = false; 00936 00937 typedef typename OR_Matrix<N>::const_row_iterator Row_Iterator; 00938 typedef typename OR_Matrix<N>::const_row_reference_type Row_Reference; 00939 00940 const Row_Iterator m_begin = matrix.row_begin(); 00941 const Row_Iterator m_end = matrix.row_end(); 00942 00943 PPL_DIRTY_TEMP_COEFFICIENT(val_den); 00944 val_den = 1; 00945 00946 for (Row_Iterator i_iter = m_begin; i_iter != m_end; i_iter += 2) { 00947 constant_v = false; 00948 dimension_type i = i_iter.index(); 00949 const Variable v(i/2); 00950 coeff = le.coefficient(v); 00951 if (coeff == 0) { 00952 constant_v = true; 00953 continue; 00954 } 00955 // We check the unary constraints. 00956 Row_Reference m_i = *i_iter; 00957 Row_Reference m_ii = *(i_iter+1); 00958 const N& m_i_ii = m_i[i+1]; 00959 const N& m_ii_i = m_ii[i]; 00960 if ((!is_plus_infinity(m_i_ii) && !is_plus_infinity(m_ii_i)) 00961 && (is_additive_inverse(m_i_ii, m_ii_i))) { 00962 // If `v' is constant, replace it in `le' by the value. 00963 numer_denom(m_i_ii, num, den); 00964 den *= 2; 00965 le -= coeff*v; 00966 le *= den; 00967 le -= num*coeff; 00968 val_den *= den; 00969 constant_v = true; 00970 continue; 00971 } 00972 // Check the octagonal constraints between `v' and the other dimensions 00973 // that have non-zero coefficient in `le'. 00974 else { 00975 PPL_ASSERT(!constant_v); 00976 using namespace Implementation::Octagonal_Shapes; 00977 const dimension_type ci = coherent_index(i); 00978 for (Row_Iterator j_iter = i_iter; j_iter != m_end; j_iter += 2) { 00979 dimension_type j = j_iter.index(); 00980 const Variable vj(j/2); 00981 coeff_j = le.coefficient(vj); 00982 if (coeff_j == 0) 00983 // The coefficient in `le' is 0, so do nothing. 00984 continue; 00985 const dimension_type cj = coherent_index(j); 00986 const dimension_type cjj = coherent_index(j+1); 00987 00988 Row_Reference m_j = *(m_begin + j); 00989 Row_Reference m_cj = *(m_begin + cj); 00990 const N& m_j_i = m_j[i]; 00991 const N& m_i_j = m_cj[ci]; 00992 if ((!is_plus_infinity(m_i_j) && !is_plus_infinity(m_j_i)) 00993 && (is_additive_inverse(m_i_j, m_j_i))) { 00994 // The coefficient for `vj' in `le' is not 0 00995 // and the constraint with `v' is an equality. 00996 // So apply this equality to eliminate `v' in `le'. 00997 numer_denom(m_i_j, num, den); 00998 le -= coeff*v; 00999 le += coeff*vj; 01000 le *= den; 01001 le -= num*coeff; 01002 val_den *= den; 01003 constant_v = true; 01004 break; 01005 } 01006 01007 m_j = *(m_begin + j + 1); 01008 m_cj = *(m_begin + cjj); 01009 const N& m_j_i1 = m_j[i]; 01010 const N& m_i_j1 = m_cj[ci]; 01011 if ((!is_plus_infinity(m_i_j1) && !is_plus_infinity(m_j_i1)) 01012 && (is_additive_inverse(m_i_j1, m_j_i1))) { 01013 // The coefficient for `vj' in `le' is not 0 01014 // and the constraint with `v' is an equality. 01015 // So apply this equality to eliminate `v' in `le'. 01016 numer_denom(m_i_j1, num, den); 01017 le -= coeff*v; 01018 le -= coeff*vj; 01019 le *= den; 01020 le -= num*coeff; 01021 val_den *= den; 01022 constant_v = true; 01023 break; 01024 } 01025 } 01026 if (!constant_v) 01027 // The expression `expr' is not constant. 01028 return false; 01029 } 01030 } 01031 if (!constant_v) 01032 // The expression `expr' is not constant. 01033 return false; 01034 01035 // The expression 'expr' is constant. 01036 freq_n = 0; 01037 freq_d = 1; 01038 01039 // Reduce `val_n' and `val_d'. 01040 normalize2(le.inhomogeneous_term(), val_den, val_n, val_d); 01041 return true; 01042 }
| 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
, where
is the relation symbol encoded by relsym.
| lhs | The left hand side affine expression. | |
| relsym | The relation symbol. | |
| rhs | The right hand side affine expression. |
| std::invalid_argument | Thrown if *this is dimension-incompatible with lhs or rhs or if relsym is a strict relation symbol. |
Definition at line 5403 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
05405 { 05406 // Dimension-compatibility checks. 05407 // The dimension of `lhs' should not be greater than the dimension 05408 // of `*this'. 05409 dimension_type lhs_space_dim = lhs.space_dimension(); 05410 if (space_dim < lhs_space_dim) 05411 throw_dimension_incompatible("generalized_affine_image(e1, r, e2)", 05412 "e1", lhs); 05413 05414 // The dimension of `rhs' should not be greater than the dimension 05415 // of `*this'. 05416 const dimension_type rhs_space_dim = rhs.space_dimension(); 05417 if (space_dim < rhs_space_dim) 05418 throw_dimension_incompatible("generalized_affine_image(e1, r, e2)", 05419 "e2", rhs); 05420 05421 // Strict relation symbols are not admitted for octagons. 05422 if (relsym == LESS_THAN || relsym == GREATER_THAN) 05423 throw_generic("generalized_affine_image(e1, r, e2)", 05424 "r is a strict relation symbol and " 05425 "*this is an Octagonal_Shape"); 05426 05427 strong_closure_assign(); 05428 // The image of an empty octagon is empty. 05429 if (marked_empty()) 05430 return; 05431 05432 // Number of non-zero coefficients in `lhs': will be set to 05433 // 0, 1, or 2, the latter value meaning any value greater than 1. 05434 dimension_type t_lhs = 0; 05435 // Index of the last non-zero coefficient in `lhs', if any. 05436 dimension_type j_lhs = 0; 05437 05438 // Compute the number of the non-zero components of `lhs'. 05439 for (dimension_type i = lhs_space_dim; i-- > 0; ) 05440 if (lhs.coefficient(Variable(i)) != 0) { 05441 if (t_lhs++ == 1) 05442 break; 05443 else 05444 j_lhs = i; 05445 } 05446 05447 const Coefficient& b_lhs = lhs.inhomogeneous_term(); 05448 05449 if (t_lhs == 0) { 05450 // `lhs' is a constant. 05451 // In principle, it is sufficient to add the constraint `lhs relsym rhs'. 05452 // Note that this constraint is an octagonal difference if `t_rhs <= 1' 05453 // or `t_rhs > 1' and `rhs == a*v - a*w + b_rhs' or 05454 // `rhs == a*v + a*w + b_rhs'. If `rhs' is of a 05455 // more general form, it will be simply ignored. 05456 // TODO: if it is not an octagonal difference, should we compute 05457 // approximations for this constraint? 05458 switch (relsym) { 05459 case LESS_OR_EQUAL: 05460 refine_no_check(lhs <= rhs); 05461 break; 05462 case EQUAL: 05463 refine_no_check(lhs == rhs); 05464 break; 05465 case GREATER_OR_EQUAL: 05466 refine_no_check(lhs >= rhs); 05467 break; 05468 default: 05469 // We already dealt with the other cases. 05470 throw std::runtime_error("PPL internal error"); 05471 } 05472 } 05473 05474 else if (t_lhs == 1) { 05475 // Here `lhs == a_lhs * v + b_lhs'. 05476 // Independently from the form of `rhs', we can exploit the 05477 // method computing generalized affine images for a single variable. 05478 Variable v(j_lhs); 05479 // Compute a sign-corrected relation symbol. 05480 const Coefficient& den = lhs.coefficient(v); 05481 Relation_Symbol new_relsym = relsym; 05482 if (den < 0) { 05483 if (relsym == LESS_OR_EQUAL) 05484 new_relsym = GREATER_OR_EQUAL; 05485 else if (relsym == GREATER_OR_EQUAL) 05486 new_relsym = LESS_OR_EQUAL; 05487 } 05488 Linear_Expression expr = rhs - b_lhs; 05489 generalized_affine_image(v, new_relsym, expr, den); 05490 } 05491 else { 05492 // Here `lhs' is of the general form, having at least two variables. 05493 // Compute the set of variables occurring in `lhs'. 05494 bool lhs_vars_intersects_rhs_vars = false; 05495 std::vector<Variable> lhs_vars; 05496 for (dimension_type i = lhs_space_dim; i-- > 0; ) 05497 if (lhs.coefficient(Variable(i)) != 0) { 05498 lhs_vars.push_back(Variable(i)); 05499 if (rhs.coefficient(Variable(i)) != 0) 05500 lhs_vars_intersects_rhs_vars = true; 05501 } 05502 05503 if (!lhs_vars_intersects_rhs_vars) { 05504 // `lhs' and `rhs' variables are disjoint. 05505 // Existentially quantify all variables in the lhs. 05506 for (dimension_type i = lhs_vars.size(); i-- > 0; ) { 05507 dimension_type lhs_vars_i = lhs_vars[i].id(); 05508 forget_all_octagonal_constraints(lhs_vars_i); 05509 } 05510 // Constrain the left hand side expression so that it is related to 05511 // the right hand side expression as dictated by `relsym'. 05512 // TODO: if the following constraint is NOT an octagonal difference, 05513 // it will be simply ignored. Should we compute approximations for it? 05514 switch (relsym) { 05515 case LESS_OR_EQUAL: 05516 refine_no_check(lhs <= rhs); 05517 break; 05518 case EQUAL: 05519 refine_no_check(lhs == rhs); 05520 break; 05521 case GREATER_OR_EQUAL: 05522 refine_no_check(lhs >= rhs); 05523 break; 05524 default: 05525 // We already dealt with the other cases. 05526 throw std::runtime_error("PPL internal error"); 05527 } 05528 } 05529 else { 05530 // Some variables in `lhs' also occur in `rhs'. 05531 05532 #if 1 // Simplified computation (see the TODO note below). 05533 05534 for (dimension_type i = lhs_vars.size(); i-- > 0; ) { 05535 dimension_type lhs_vars_i = lhs_vars[i].id(); 05536 forget_all_octagonal_constraints(lhs_vars_i); 05537 } 05538 05539 #else // Currently unnecessarily complex computation. 05540 05541 // More accurate computation that is worth doing only if 05542 // the following TODO note is accurately dealt with. 05543 05544 // To ease the computation, we add an additional dimension. 05545 const Variable new_var = Variable(space_dim); 05546 add_space_dimensions_and_embed(1); 05547 // Constrain the new dimension to be equal to `rhs'. 05548 // NOTE: calling affine_image() instead of refine_no_check() 05549 // ensures some approximation is tried even when the constraint 05550 // is not an octagonal constraint. 05551 affine_image(new_var, rhs); 05552 // Existentially quantify all variables in the lhs. 05553 // NOTE: enforce strong closure for precision. 05554 strong_closure_assign(); 05555 PPL_ASSERT(!marked_empty()); 05556 for (dimension_type i = lhs_vars.size(); i-- > 0; ) { 05557 dimension_type lhs_vars_i = lhs_vars[i].id(); 05558 forget_all_octagonal_constraints(lhs_vars_i); 05559 } 05560 // Constrain the new dimension so that it is related to 05561 // the left hand side as dictated by `relsym'. 05562 // TODO: each one of the following constraints is definitely NOT 05563 // an octagonal difference (since it has 3 variables at least). 05564 // Thus, the method refine_no_check() will simply ignore it. 05565 // Should we compute approximations for this constraint? 05566 switch (relsym) { 05567 case LESS_OR_EQUAL: 05568 refine_no_check(lhs <= new_var); 05569 break; 05570 case EQUAL: 05571 refine_no_check(lhs == new_var); 05572 break; 05573 case GREATER_OR_EQUAL: 05574 refine_no_check(lhs >= new_var); 05575 break; 05576 default: 05577 // We already dealt with the other cases. 05578 throw std::runtime_error("PPL internal error"); 05579 } 05580 // Remove the temporarily added dimension. 05581 remove_higher_space_dimensions(space_dim-1); 05582 #endif // Currently unnecessarily complex computation. 05583 } 05584 } 05585 05586 PPL_ASSERT(OK()); 05587 }
| 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
, where
is the relation symbol encoded by relsym.
| 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. |
| std::invalid_argument | Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a dimension of *this or if relsym is a strict relation symbol. |
Definition at line 4914 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::PLUS_INFINITY, PPL_DIRTY_TEMP_COEFFICIENT, and Parma_Polyhedra_Library::Linear_Expression::space_dimension().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image().
04917 { 04918 // The denominator cannot be zero. 04919 if (denominator == 0) 04920 throw_generic("generalized_affine_image(v, r, e, d)", "d == 0"); 04921 04922 // Dimension-compatibility checks. 04923 // The dimension of `expr' should not be greater than the dimension 04924 // of `*this'. 04925 const dimension_type expr_space_dim = expr.space_dimension(); 04926 if (space_dim < expr_space_dim) 04927 throw_dimension_incompatible("generalized_affine_image(v, r, e, d)", "e", 04928 expr); 04929 04930 // `var' should be one of the dimensions of the octagon. 04931 dimension_type var_id = var.id(); 04932 if (space_dim < var_id + 1) 04933 throw_dimension_incompatible("generalized_affine_image(v, r, e, d)", 04934 var_id + 1); 04935 04936 // The relation symbol cannot be a strict relation symbol. 04937 if (relsym == LESS_THAN || relsym == GREATER_THAN) 04938 throw_generic("generalized_affine_image(v, r, e, d)", 04939 "r is a strict relation symbol and " 04940 "*this is an Octagonal_Shape"); 04941 04942 if (relsym == EQUAL) { 04943 // The relation symbol is "=": 04944 // this is just an affine image computation. 04945 affine_image(var, expr, denominator); 04946 return; 04947 } 04948 04949 strong_closure_assign(); 04950 // The image of an empty octagon is empty too. 04951 if (marked_empty()) 04952 return; 04953 04954 // Number of non-zero coefficients in `expr': will be set to 04955 // 0, 1, or 2, the latter value meaning any value greater than 1. 04956 dimension_type t = 0; 04957 // Variable-index of the last non-zero coefficient in `expr', if any. 04958 dimension_type w_id = 0; 04959 04960 // Get information about the number of non-zero coefficients in `expr'. 04961 // The `expr' must not be in two or plus variables. 04962 for (dimension_type i = expr_space_dim; i-- > 0; ) 04963 if (expr.coefficient(Variable(i)) != 0) { 04964 if (t++ == 1) 04965 break; 04966 else 04967 w_id = i; 04968 } 04969 04970 typedef typename OR_Matrix<N>::row_iterator Row_Iterator; 04971 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 04972 typedef typename OR_Matrix<N>::const_row_iterator Row_iterator; 04973 typedef typename OR_Matrix<N>::const_row_reference_type Row_reference; 04974 04975 const Row_Iterator m_begin = matrix.row_begin(); 04976 const Row_Iterator m_end = matrix.row_end(); 04977 const dimension_type n_var = 2*var_id; 04978 const Coefficient& b = expr.inhomogeneous_term(); 04979 PPL_DIRTY_TEMP_COEFFICIENT(minus_den); 04980 neg_assign_r(minus_den, denominator, ROUND_NOT_NEEDED); 04981 04982 // `w' is the variable with index `w_id'. 04983 // Now we know the form of `expr': 04984 // - If t == 0, then expr == b, with `b' a constant; 04985 // - If t == 1, then expr == a*w + b, where `w' can be `v' or another 04986 // variable; in this second case we have to check whether `a' is 04987 // equal to `denominator' or `-denominator', since otherwise we have 04988 // to fall back on the general form; 04989 // - If t == 2, the `expr' is of the general form. 04990 04991 if (t == 0) { 04992 // Case 1: expr = b. 04993 PPL_DIRTY_TEMP_COEFFICIENT(two_b); 04994 two_b = 2*b; 04995 // Remove all constraints on `var'. 04996 forget_all_octagonal_constraints(var_id); 04997 // Strong closure is lost. 04998 reset_strongly_closed(); 04999 switch (relsym) { 05000 case LESS_OR_EQUAL: 05001 // Add the constraint `var <= b/denominator'. 05002 add_octagonal_constraint(n_var+1, n_var, two_b, denominator); 05003 break; 05004 case GREATER_OR_EQUAL: 05005 // Add the constraint `var >= n/denominator', 05006 // i.e., `-var <= -b/denominator'. 05007 add_octagonal_constraint(n_var, n_var+1, two_b, minus_den); 05008 break; 05009 default: 05010 // We already dealt with the other cases. 05011 throw std::runtime_error("PPL internal error"); 05012 } 05013 PPL_ASSERT(OK()); 05014 return; 05015 } 05016 05017 if (t == 1) { 05018 // The one and only non-zero homogeneous coefficient in `expr'. 05019 const Coefficient& w_coeff = expr.coefficient(Variable(w_id)); 05020 if (w_coeff == denominator || w_coeff == minus_den) { 05021 // Case 2: expr == w_coeff*w + b, with w_coeff == +/- denominator. 05022 switch (relsym) { 05023 case LESS_OR_EQUAL: 05024 { 05025 PPL_DIRTY_TEMP(N, d); 05026 div_round_up(d, b, denominator); 05027 if (w_id == var_id) { 05028 // Here `expr' is of the form: +/- denominator * v + b. 05029 // Strong closure is not preserved. 05030 reset_strongly_closed(); 05031 if (w_coeff == denominator) { 05032 // Translate all the constraints of the form `v - w <= cost' 05033 // into the constraint `v - w <= cost + b/denominator'; 05034 // forget each constraint `w - v <= cost1'. 05035 Row_Iterator m_iter = m_begin + n_var; 05036 Row_Reference m_v = *m_iter; 05037 N& m_v_cv = m_v[n_var+1]; 05038 ++m_iter; 05039 Row_Reference m_cv = *m_iter; 05040 N& m_cv_v = m_cv[n_var]; 05041 ++m_iter; 05042 // NOTE: delay update of m_v_cv and m_cv_v. 05043 for ( ; m_iter != m_end; ++m_iter) { 05044 Row_Reference m_i = *m_iter; 05045 N& m_i_v = m_i[n_var]; 05046 add_assign_r(m_i_v, m_i_v, d, ROUND_UP); 05047 assign_r(m_i[n_var+1], PLUS_INFINITY, ROUND_NOT_NEEDED); 05048 } 05049 for (dimension_type k = n_var; k-- > 0; ) { 05050 assign_r(m_v[k], PLUS_INFINITY, ROUND_NOT_NEEDED); 05051 add_assign_r(m_cv[k], m_cv[k], d, ROUND_UP); 05052 } 05053 mul_2exp_assign_r(d, d, 1, ROUND_UP); 05054 add_assign_r(m_cv_v, m_cv_v, d, ROUND_UP); 05055 assign_r(m_v_cv, PLUS_INFINITY, ROUND_NOT_NEEDED); 05056 } 05057 else { 05058 // Here `w_coeff == -denominator'. 05059 // `expr' is of the form: -a*var + b. 05060 N& m_v_cv = matrix[n_var][n_var+1]; 05061 mul_2exp_assign_r(d, d, 1, ROUND_UP); 05062 add_assign_r(matrix[n_var+1][n_var], m_v_cv, d, ROUND_UP); 05063 assign_r(m_v_cv, PLUS_INFINITY, ROUND_NOT_NEEDED); 05064 forget_binary_octagonal_constraints(var_id); 05065 } 05066 } 05067 else { 05068 // Here `w != v', so that `expr' is the form 05069 // +/- denominator*w + b. 05070 // Remove all constraints on `v'. 05071 forget_all_octagonal_constraints(var_id); 05072 const dimension_type n_w = 2*w_id; 05073 if (w_coeff == denominator) { 05074 // Add the new constraint `v - w <= b/denominator'. 05075 if (var_id < w_id) 05076 add_octagonal_constraint(n_w, n_var, b, denominator); 05077 else 05078 add_octagonal_constraint(n_var+1, n_w+1, b, denominator); 05079 } 05080 else { 05081 // Add the new constraint `v + w <= b/denominator'. 05082 if (var_id < w_id) 05083 add_octagonal_constraint(n_w+1, n_var, b, denominator); 05084 else 05085 add_octagonal_constraint(n_var+1, n_w, b, denominator); 05086 } 05087 } 05088 break; 05089 } 05090 05091 case GREATER_OR_EQUAL: 05092 { 05093 PPL_DIRTY_TEMP(N, d); 05094 div_round_up(d, b, minus_den); 05095 if (w_id == var_id) { 05096 // Here `expr' is of the form: +/- denominator * v + b. 05097 // Strong closure is not preserved. 05098 reset_strongly_closed(); 05099 if (w_coeff == denominator) { 05100 // Translate each constraint `w - v <= cost' 05101 // into the constraint `w - v <= cost - b/denominator'; 05102 // forget each constraint `v - w <= cost1'. 05103 Row_Iterator m_iter = m_begin + n_var; 05104 Row_Reference m_v = *m_iter; 05105 N& m_v_cv = m_v[n_var+1]; 05106 ++m_iter; 05107 Row_Reference m_cv = *m_iter; 05108 N& m_cv_v = m_cv[n_var]; 05109 ++m_iter; 05110 // NOTE: delay update of m_v_cv and m_cv_v. 05111 for ( ; m_iter != m_end; ++m_iter) { 05112 Row_Reference m_i = *m_iter; 05113 assign_r(m_i[n_var], PLUS_INFINITY, ROUND_NOT_NEEDED); 05114 add_assign_r(m_i[n_var+1], m_i[n_var+1], d, ROUND_UP); 05115 } 05116 for (dimension_type k = n_var; k-- > 0; ) { 05117 add_assign_r(m_v[k], m_v[k], d, ROUND_UP); 05118 assign_r(m_cv[k], PLUS_INFINITY, ROUND_NOT_NEEDED); 05119 } 05120 mul_2exp_assign_r(d, d, 1, ROUND_UP); 05121 add_assign_r(m_v_cv, m_v_cv, d, ROUND_UP); 05122 assign_r(m_cv_v, PLUS_INFINITY, ROUND_NOT_NEEDED); 05123 } 05124 else { 05125 // Here `w_coeff == -denominator'. 05126 // `expr' is of the form: -a*var + b. 05127 N& m_cv_v = matrix[n_var+1][n_var]; 05128 mul_2exp_assign_r(d, d, 1, ROUND_UP); 05129 add_assign_r(matrix[n_var][n_var+1], m_cv_v, d, ROUND_UP); 05130 assign_r(m_cv_v, PLUS_INFINITY, ROUND_NOT_NEEDED); 05131 forget_binary_octagonal_constraints(var_id); 05132 } 05133 } 05134 else { 05135 // Here `w != v', so that `expr' is of the form 05136 // +/-denominator * w + b, with `w != v'. 05137 // Remove all constraints on `v'. 05138 forget_all_octagonal_constraints(var_id); 05139 const dimension_type n_w = 2*w_id; 05140 // We have got an expression of the following form: 05141 // var1 + n, with `var1' != `var'. 05142 // We remove all constraints of the form `var (+/- var1) >= const' 05143 // and we add the new constraint `var +/- var1 >= n/denominator'. 05144 if (w_coeff == denominator) { 05145 // Add the new constraint `var - w >= b/denominator', 05146 // i.e., `w - var <= -b/denominator'. 05147 if (var_id < w_id) 05148 add_octagonal_constraint(n_w+1, n_var+1, b, minus_den); 05149 else 05150 add_octagonal_constraint(n_var, n_w, b, minus_den); 05151 } 05152 else { 05153 // Add the new constraint `var + w >= b/denominator', 05154 // i.e., `-w - var <= -b/denominator'. 05155 if (var_id < w_id) 05156 add_octagonal_constraint(n_w, n_var+1, b, minus_den); 05157 else 05158 add_octagonal_constraint(n_var, n_w+1, b, minus_den); 05159 } 05160 } 05161 break; 05162 } 05163 05164 default: 05165 // We already dealt with the other cases. 05166 throw std::runtime_error("PPL internal error"); 05167 } 05168 PPL_ASSERT(OK()); 05169 return; 05170 } 05171 } 05172 05173 // General case. 05174 // Either t == 2, so that 05175 // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2, 05176 // or t == 1, expr == a*w + b, but a <> +/- denominator. 05177 // We will remove all the constraints on `v' and add back 05178 // a constraint providing an upper or a lower bound for `v' 05179 // (depending on `relsym'). 05180 const bool is_sc = (denominator > 0); 05181 PPL_DIRTY_TEMP_COEFFICIENT(minus_b); 05182 neg_assign(minus_b, b); 05183 const Coefficient& sc_b = is_sc ? b : minus_b; 05184 const Coefficient& minus_sc_b = is_sc ? minus_b : b; 05185 const Coefficient& sc_den = is_sc ? denominator : minus_den; 05186 const Coefficient& minus_sc_den = is_sc ? minus_den : denominator; 05187 // NOTE: here, for optimization purposes, `minus_expr' is only assigned 05188 // when `denominator' is negative. Do not use it unless you are sure 05189 // it has been correctly assigned. 05190 Linear_Expression minus_expr; 05191 if (!is_sc) 05192 minus_expr = -expr; 05193 const Linear_Expression& sc_expr = is_sc ? expr : minus_expr; 05194 05195 PPL_DIRTY_TEMP(N, sum); 05196 // Index of variable that is unbounded in `this->matrix'. 05197 PPL_UNINITIALIZED(dimension_type, pinf_index); 05198 // Number of unbounded variables found. 05199 dimension_type pinf_count = 0; 05200 05201 switch (relsym) { 05202 case LESS_OR_EQUAL: 05203 { 05204 // Compute an upper approximation for `sc_expr' into `sum'. 05205 05206 // Approximate the inhomogeneous term. 05207 assign_r(sum, sc_b, ROUND_UP); 05208 // Approximate the homogeneous part of `sc_expr'. 05209 PPL_DIRTY_TEMP(N, coeff_i); 05210 PPL_DIRTY_TEMP(N, approx_i); 05211 PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i); 05212 // Note: indices above `w' can be disregarded, as they all have 05213 // a zero coefficient in `sc_expr'. 05214 for (Row_iterator m_iter = m_begin, m_iter_end = m_iter + (2*w_id) + 2; 05215 m_iter != m_iter_end; ) { 05216 const dimension_type n_i = m_iter.index(); 05217 const dimension_type id = n_i/2; 05218 Row_reference m_i = *m_iter; 05219 ++m_iter; 05220 Row_reference m_ci = *m_iter; 05221 ++m_iter; 05222 const Coefficient& sc_i = sc_expr.coefficient(Variable(id)); 05223 const int sign_i = sgn(sc_i); 05224 if (sign_i == 0) 05225 continue; 05226 // Choose carefully: we are approximating `sc_expr'. 05227 const N& double_approx_i = (sign_i > 0) ? m_ci[n_i] : m_i[n_i+1]; 05228 if (is_plus_infinity(double_approx_i)) { 05229 if (++pinf_count > 1) 05230 break; 05231 pinf_index = id; 05232 continue; 05233 } 05234 if (sign_i > 0) 05235 assign_r(coeff_i, sc_i, ROUND_UP); 05236 else { 05237 neg_assign(minus_sc_i, sc_i); 05238 assign_r(coeff_i, minus_sc_i, ROUND_UP); 05239 } 05240 div_2exp_assign_r(approx_i, double_approx_i, 1, ROUND_UP); 05241 add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP); 05242 } 05243 // Remove all constraints on `v'. 05244 forget_all_octagonal_constraints(var_id); 05245 reset_strongly_closed(); 05246 // Return immediately if no approximation could be computed. 05247 if (pinf_count > 1) { 05248 PPL_ASSERT(OK()); 05249 return; 05250 } 05251 05252 // Divide by the (sign corrected) denominator (if needed). 05253 if (sc_den != 1) { 05254 // Before computing the quotient, the denominator should be 05255 // approximated towards zero. Since `sc_den' is known to be 05256 // positive, this amounts to rounding downwards, which is 05257 // achieved as usual by rounding upwards 05258 // `minus_sc_den' and negating again the result. 05259 PPL_DIRTY_TEMP(N, down_sc_den); 05260 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 05261 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 05262 div_assign_r(sum, sum, down_sc_den, ROUND_UP); 05263 } 05264 05265 if (pinf_count == 0) { 05266 // Add the constraint `v <= pos_sum'. 05267 PPL_DIRTY_TEMP(N, double_sum); 05268 mul_2exp_assign_r(double_sum, sum, 1, ROUND_UP); 05269 matrix[n_var+1][n_var] = double_sum; 05270 // Deduce constraints of the form `v +/- u', where `u != v'. 05271 deduce_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, sum); 05272 } 05273 else if (pinf_count == 1) 05274 if (pinf_index != var_id) { 05275 const Coefficient& pi = expr.coefficient(Variable(pinf_index)); 05276 if (pi == denominator ) { 05277 // Add the constraint `v - pinf_index <= sum'. 05278 if (var_id < pinf_index) 05279 matrix[2*pinf_index][n_var] = sum; 05280 else 05281 matrix[n_var+1][2*pinf_index+1] = sum; 05282 } 05283 else { 05284 if (pi == minus_den) { 05285 // Add the constraint `v + pinf_index <= sum'. 05286 if (var_id < pinf_index) 05287 matrix[2*pinf_index+1][n_var] = sum; 05288 else 05289 matrix[n_var+1][2*pinf_index] = sum; 05290 } 05291 } 05292 } 05293 break; 05294 } 05295 05296 case GREATER_OR_EQUAL: 05297 { 05298 // Compute an upper approximation for `-sc_expr' into `sum'. 05299 // Note: approximating `-sc_expr' from above and then negating the 05300 // result is the same as approximating `sc_expr' from below. 05301 05302 // Approximate the inhomogeneous term. 05303 assign_r(sum, minus_sc_b, ROUND_UP); 05304 PPL_DIRTY_TEMP(N, coeff_i); 05305 PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i); 05306 PPL_DIRTY_TEMP(N, approx_i); 05307 // Approximate the homogeneous part of `-sc_expr'. 05308 for (Row_iterator m_iter = m_begin, m_iter_end = m_iter + (2*w_id) + 2; 05309 m_iter != m_iter_end; ) { 05310 const dimension_type n_i = m_iter.index(); 05311 const dimension_type id = n_i/2; 05312 Row_reference m_i = *m_iter; 05313 ++m_iter; 05314 Row_reference m_ci = *m_iter; 05315 ++m_iter; 05316 const Coefficient& sc_i = sc_expr.coefficient(Variable(id)); 05317 const int sign_i = sgn(sc_i); 05318 if (sign_i == 0) 05319 continue; 05320 // Choose carefully: we are approximating `-sc_expr'. 05321 const N& double_approx_i = (sign_i > 0) ? m_i[n_i+1] : m_ci[n_i]; 05322 if (is_plus_infinity(double_approx_i)) { 05323 if (++pinf_count > 1) 05324 break; 05325 pinf_index = id; 05326 continue; 05327 } 05328 if (sign_i > 0) 05329 assign_r(coeff_i, sc_i, ROUND_UP); 05330 else { 05331 neg_assign(minus_sc_i, sc_i); 05332 assign_r(coeff_i, minus_sc_i, ROUND_UP); 05333 } 05334 div_2exp_assign_r(approx_i, double_approx_i, 1, ROUND_UP); 05335 add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP); 05336 } 05337 05338 // Remove all constraints on `var'. 05339 forget_all_octagonal_constraints(var_id); 05340 reset_strongly_closed(); 05341 // Return immediately if no approximation could be computed. 05342 if (pinf_count > 1) { 05343 PPL_ASSERT(OK()); 05344 return; 05345 } 05346 05347 // Divide by the (sign corrected) denominator (if needed). 05348 if (sc_den != 1) { 05349 // Before computing the quotient, the denominator should be 05350 // approximated towards zero. Since `sc_den' is known to be 05351 // positive, this amounts to rounding downwards, which is 05352 // achieved as usual by rounding upwards 05353 // `minus_sc_den' and negating again the result. 05354 PPL_DIRTY_TEMP(N, down_sc_den); 05355 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 05356 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 05357 div_assign_r(sum, sum, down_sc_den, ROUND_UP); 05358 } 05359 05360 if (pinf_count == 0) { 05361 // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'. 05362 PPL_DIRTY_TEMP(N, double_sum); 05363 mul_2exp_assign_r(double_sum, sum, 1, ROUND_UP); 05364 matrix[n_var][n_var+1] = double_sum; 05365 // Deduce constraints of the form `-v +/- u', where `u != v'. 05366 deduce_minus_v_pm_u_bounds(var_id, pinf_index, sc_expr, sc_den, sum); 05367 } 05368 else if (pinf_count == 1) 05369 if (pinf_index != var_id) { 05370 const Coefficient& pi = expr.coefficient(Variable(pinf_index)); 05371 if (pi == denominator) { 05372 // Add the constraint `v - pinf_index >= -sum', 05373 // i.e., `pinf_index - v <= sum'. 05374 if (pinf_index < var_id) 05375 matrix[n_var][2*pinf_index] = sum; 05376 else 05377 matrix[2*pinf_index+1][n_var+1] = sum; 05378 } 05379 else { 05380 if (pi == minus_den) { 05381 // Add the constraint `v + pinf_index >= -sum', 05382 // i.e., `-pinf_index - v <= sum'. 05383 if (pinf_index < var_id) 05384 matrix[n_var][2*pinf_index+1] = sum; 05385 else 05386 matrix[2*pinf_index][n_var+1] = sum; 05387 } 05388 } 05389 } 05390 break; 05391 } 05392 05393 default: 05394 // We already dealt with the other cases. 05395 throw std::runtime_error("PPL internal error"); 05396 } 05397 incremental_strong_closure_assign(var); 05398 PPL_ASSERT(OK()); 05399 }
| 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
, where
is the relation symbol encoded by relsym.
| lhs | The left hand side affine expression; | |
| relsym | The relation symbol; | |
| rhs | The right hand side affine expression. |
| std::invalid_argument | Thrown if *this is dimension-incompatible with lhs or rhs or if relsym is a strict relation symbol. |
Definition at line 5956 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, and Parma_Polyhedra_Library::Linear_Expression::space_dimension().
05958 { 05959 // Dimension-compatibility checks. 05960 // The dimension of `lhs' should not be greater than the dimension 05961 // of `*this'. 05962 dimension_type lhs_space_dim = lhs.space_dimension(); 05963 if (space_dim < lhs_space_dim) 05964 throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)", 05965 "e1", lhs); 05966 05967 // The dimension of `rhs' should not be greater than the dimension 05968 // of `*this'. 05969 const dimension_type rhs_space_dim = rhs.space_dimension(); 05970 if (space_dim < rhs_space_dim) 05971 throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)", 05972 "e2", rhs); 05973 05974 // Strict relation symbols are not admitted for octagons. 05975 if (relsym == LESS_THAN || relsym == GREATER_THAN) 05976 throw_generic("generalized_affine_preimage(e1, r, e2)", 05977 "r is a strict relation symbol and " 05978 "*this is an Octagonal_Shape"); 05979 05980 strong_closure_assign(); 05981 // The image of an empty octagon is empty. 05982 if (marked_empty()) 05983 return; 05984 05985 // Number of non-zero coefficients in `lhs': will be set to 05986 // 0, 1, or 2, the latter value meaning any value greater than 1. 05987 dimension_type t_lhs = 0; 05988 // Index of the last non-zero coefficient in `lhs', if any. 05989 dimension_type j_lhs = 0; 05990 05991 // Compute the number of the non-zero components of `lhs'. 05992 for (dimension_type i = lhs_space_dim; i-- > 0; ) 05993 if (lhs.coefficient(Variable(i)) != 0) { 05994 if (t_lhs++ == 1) 05995 break; 05996 else 05997 j_lhs = i; 05998 } 05999 06000 const Coefficient& b_lhs = lhs.inhomogeneous_term(); 06001 06002 // If all variables have a zero coefficient, then `lhs' is a constant: 06003 // in this case, preimage and image happen to be the same. 06004 if (t_lhs == 0) { 06005 generalized_affine_image(lhs, relsym, rhs); 06006 return; 06007 } 06008 06009 else if (t_lhs == 1) { 06010 // Here `lhs == a_lhs * v + b_lhs'. 06011 // Independently from the form of `rhs', we can exploit the 06012 // method computing generalized affine preimages for a single variable. 06013 Variable v(j_lhs); 06014 // Compute a sign-corrected relation symbol. 06015 const Coefficient& den = lhs.coefficient(v); 06016 Relation_Symbol new_relsym = relsym; 06017 if (den < 0) { 06018 if (relsym == LESS_OR_EQUAL) 06019 new_relsym = GREATER_OR_EQUAL; 06020 else if (relsym == GREATER_OR_EQUAL) 06021 new_relsym = LESS_OR_EQUAL; 06022 } 06023 Linear_Expression expr = rhs - b_lhs; 06024 generalized_affine_preimage(v, new_relsym, expr, den); 06025 } 06026 06027 else { 06028 // Here `lhs' is of the general form, having at least two variables. 06029 // Compute the set of variables occurring in `lhs'. 06030 bool lhs_vars_intersects_rhs_vars = false; 06031 std::vector<Variable> lhs_vars; 06032 for (dimension_type i = lhs_space_dim; i-- > 0; ) 06033 if (lhs.coefficient(Variable(i)) != 0) { 06034 lhs_vars.push_back(Variable(i)); 06035 if (rhs.coefficient(Variable(i)) != 0) 06036 lhs_vars_intersects_rhs_vars = true; 06037 } 06038 06039 if (!lhs_vars_intersects_rhs_vars) { 06040 // `lhs' and `rhs' variables are disjoint. 06041 // Constrain the left hand side expression so that it is related to 06042 // the right hand side expression as dictated by `relsym'. 06043 // TODO: if the following constraint is NOT an octagonal difference, 06044 // it will be simply ignored. Should we compute approximations for it? 06045 switch (relsym) { 06046 case LESS_OR_EQUAL: 06047 refine_no_check(lhs <= rhs); 06048 break; 06049 case EQUAL: 06050 refine_no_check(lhs == rhs); 06051 break; 06052 case GREATER_OR_EQUAL: 06053 refine_no_check(lhs >= rhs); 06054 break; 06055 default: 06056 // We already dealt with the other cases. 06057 throw std::runtime_error("PPL internal error"); 06058 } 06059 06060 // Any image of an empty octagon is empty. 06061 if (is_empty()) 06062 return; 06063 // Existentially quantify all variables in the lhs. 06064 for (dimension_type i = lhs_vars.size(); i-- > 0; ) { 06065 dimension_type lhs_vars_i = lhs_vars[i].id(); 06066 forget_all_octagonal_constraints(lhs_vars_i); 06067 } 06068 } 06069 else { 06070 // Some variables in `lhs' also occur in `rhs'. 06071 06072 // More accurate computation that is worth doing only if 06073 // the following TODO note is accurately dealt with. 06074 06075 // To ease the computation, we add an additional dimension. 06076 const Variable new_var = Variable(space_dim); 06077 add_space_dimensions_and_embed(1); 06078 // Constrain the new dimension to be equal to `rhs'. 06079 // NOTE: calling affine_image() instead of refine_no_check() 06080 // ensures some approximation is tried even when the constraint 06081 // is not an octagonal difference. 06082 affine_image(new_var, lhs); 06083 // Existentially quantify all variables in the lhs. 06084 // NOTE: enforce strong closure for precision. 06085 strong_closure_assign(); 06086 PPL_ASSERT(!marked_empty()); 06087 for (dimension_type i = lhs_vars.size(); i-- > 0; ) { 06088 dimension_type lhs_vars_i = lhs_vars[i].id(); 06089 forget_all_octagonal_constraints(lhs_vars_i); 06090 } 06091 // Constrain the new dimension so that it is related to 06092 // the left hand side as dictated by `relsym'. 06093 // Note: if `rhs == v + b_rhs' or `rhs == -v + b_rhs' or `rhs == b_rhs', 06094 // one of the following constraints will be added, because they 06095 // are octagonal differences. 06096 // Else the following constraints are NOT octagonal differences, 06097 // so the method refine_no_check() will ignore them. 06098 switch (relsym) { 06099 case LESS_OR_EQUAL: 06100 refine_no_check(new_var <= rhs); 06101 break; 06102 case EQUAL: 06103 refine_no_check(new_var == rhs); 06104 break; 06105 case GREATER_OR_EQUAL: 06106 refine_no_check(new_var >= rhs); 06107 break; 06108 default: 06109 // We already dealt with the other cases. 06110 throw std::runtime_error("PPL internal error"); 06111 } 06112 // Remove the temporarily added dimension. 06113 remove_higher_space_dimensions(space_dim-1); 06114 } 06115 } 06116 PPL_ASSERT(OK()); 06117 }
| 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
, where
is the relation symbol encoded by relsym.
| 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. |
| std::invalid_argument | Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a dimension of *this or if relsym is a strict relation symbol. |
Definition at line 5881 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::neg_assign(), PPL_DIRTY_TEMP_COEFFICIENT, and Parma_Polyhedra_Library::Linear_Expression::space_dimension().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage().
05885 { 05886 // The denominator cannot be zero. 05887 if (denominator == 0) 05888 throw_generic("generalized_affine_preimage(v, r, e, d)", "d == 0"); 05889 05890 // Dimension-compatibility checks. 05891 // The dimension of `expr' should not be greater than the dimension 05892 // of `*this'. 05893 const dimension_type expr_space_dim = expr.space_dimension(); 05894 if (space_dim < expr_space_dim) 05895 throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)", 05896 "e", expr); 05897 05898 // `var' should be one of the dimensions of the octagon. 05899 const dimension_type var_id = var.id(); 05900 if (space_dim < var_id + 1) 05901 throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)", 05902 var_id + 1); 05903 05904 // The relation symbol cannot be a strict relation symbol. 05905 if (relsym == LESS_THAN || relsym == GREATER_THAN) 05906 throw_generic("generalized_affine_preimage(v, r, e, d)", 05907 "r is a strict relation symbol and " 05908 "*this is an Octagonal_Shape"); 05909 05910 if (relsym == EQUAL) { 05911 // The relation symbol is "=": 05912 // this is just an affine preimage computation. 05913 affine_preimage(var, expr, denominator); 05914 return; 05915 } 05916 05917 // The image of an empty octagon is empty too. 05918 strong_closure_assign(); 05919 if (marked_empty()) 05920 return; 05921 05922 // Check whether the preimage of this affine relation can be easily 05923 // computed as the image of its inverse relation. 05924 const Coefficient& expr_v = expr.coefficient(var); 05925 if (expr_v != 0) { 05926 const Relation_Symbol reversed_relsym = (relsym == LESS_OR_EQUAL) 05927 ? GREATER_OR_EQUAL : LESS_OR_EQUAL; 05928 const Linear_Expression inverse 05929 = expr - (expr_v + denominator)*var; 05930 PPL_DIRTY_TEMP_COEFFICIENT(inverse_den); 05931 neg_assign(inverse_den, expr_v); 05932 const Relation_Symbol inverse_relsym 05933 = (sgn(denominator) == sgn(inverse_den)) ? relsym : reversed_relsym; 05934 generalized_affine_image(var, inverse_relsym, inverse, inverse_den); 05935 return; 05936 } 05937 05938 // Here `var_coefficient == 0', so that the preimage cannot 05939 // be easily computed by inverting the affine relation. 05940 // Shrink the Octagonal_Shape by adding the constraint induced 05941 // by the affine relation. 05942 refine(var, relsym, expr, denominator); 05943 05944 // If the shrunk OS is empty, its preimage is empty too; ... 05945 if (is_empty()) 05946 return; 05947 // ... otherwise, since the relation was not invertible, 05948 // we just forget all constraints on `var'. 05949 forget_all_octagonal_constraints(var_id); 05950 PPL_ASSERT(OK()); 05951 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::get_limiting_octagon | ( | const Constraint_System & | cs, | |
| Octagonal_Shape< T > & | limiting_octagon | |||
| ) | const [inline, private] |
Adds to limiting_octagon the octagonal differences in cs that are satisfied by *this.
Definition at line 3245 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Constraint::is_inequality(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::neg_assign(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), and Parma_Polyhedra_Library::Constraint_System::space_dimension().
03246 { 03247 const dimension_type cs_space_dim = cs.space_dimension(); 03248 // Private method: the caller has to ensure the following. 03249 PPL_ASSERT(cs_space_dim <= space_dim); 03250 03251 strong_closure_assign(); 03252 bool is_oct_changed = false; 03253 03254 // Allocate temporaries outside of the loop. 03255 PPL_DIRTY_TEMP_COEFFICIENT(coeff); 03256 PPL_DIRTY_TEMP_COEFFICIENT(term); 03257 PPL_DIRTY_TEMP(N, d); 03258 03259 for (Constraint_System::const_iterator cs_i = cs.begin(), 03260 cs_end = cs.end(); cs_i != cs_end; ++cs_i) { 03261 const Constraint& c = *cs_i; 03262 dimension_type num_vars = 0; 03263 dimension_type i = 0; 03264 dimension_type j = 0; 03265 // Constraints that are not octagonal differences are ignored. 03266 if (!extract_octagonal_difference(c, cs_space_dim, num_vars, i, j, 03267 coeff, term)) 03268 continue; 03269 03270 typedef typename OR_Matrix<N>::const_row_iterator Row_iterator; 03271 typedef typename OR_Matrix<N>::const_row_reference_type Row_reference; 03272 typedef typename OR_Matrix<N>::row_iterator Row_Iterator; 03273 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 03274 Row_iterator m_begin = matrix.row_begin(); 03275 // Select the cell to be modified for the "<=" part of the constraint. 03276 Row_iterator i_iter = m_begin + i; 03277 Row_reference m_i = *i_iter; 03278 OR_Matrix<N>& lo_mat = limiting_octagon.matrix; 03279 Row_Iterator lo_iter = lo_mat.row_begin() + i; 03280 Row_Reference lo_m_i = *lo_iter; 03281 N& lo_m_i_j = lo_m_i[j]; 03282 if (coeff < 0) 03283 neg_assign(coeff); 03284 // Compute the bound for `m_i_j', rounding towards plus infinity. 03285 div_round_up(d, term, coeff); 03286 if (m_i[j] <= d) 03287 if (c.is_inequality()) { 03288 if (lo_m_i_j > d) { 03289 lo_m_i_j = d; 03290 is_oct_changed = true; 03291 } 03292 else { 03293 // Select the right row of the cell. 03294 if (i % 2 == 0) { 03295 ++i_iter; 03296 ++lo_iter; 03297 } 03298 else { 03299 --i_iter; 03300 --lo_iter; 03301 } 03302 Row_reference m_ci = *i_iter; 03303 Row_Reference lo_m_ci = *lo_iter; 03304 // Select the right column of the cell. 03305 using namespace Implementation::Octagonal_Shapes; 03306 dimension_type cj = coherent_index(j); 03307 N& lo_m_ci_cj = lo_m_ci[cj]; 03308 neg_assign(term); 03309 div_round_up(d, term, coeff); 03310 if (m_ci[cj] <= d && lo_m_ci_cj > d) { 03311 lo_m_ci_cj = d; 03312 is_oct_changed = true; 03313 } 03314 } 03315 } 03316 } 03317 // In general, adding a constraint does not preserve the strongly 03318 // closure of the octagon. 03319 if (is_oct_changed && limiting_octagon.marked_strongly_closed()) 03320 limiting_octagon.reset_strongly_closed(); 03321 }
| int32_t Parma_Polyhedra_Library::Octagonal_Shape< T >::hash_code | ( | ) | const [inline] |
Returns a 32-bit hash code for *this.
If x and y are such that x == y, then x.hash_code() == y.hash_code().
Definition at line 819 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension().
00819 { 00820 return space_dimension() & 0x7fffffff; 00821 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign | ( | Variable | var | ) | const [inline, private] |
Incrementally computes strong closure, assuming that only constraints affecting variable var need to be considered.
*this, which was strongly closed, has only been modified by adding constraints affecting variable var. If this assumption is not satisfied, i.e., if a non-redundant constraint not affecting variable var has been added, the behavior is undefined. Worst-case complexity is
. Definition at line 2176 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::min_assign(), Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_coherence_assign().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign().
02176 { 02177 // `var' should be one of the dimensions of the octagon. 02178 if (var.id() >= space_dim) 02179 throw_dimension_incompatible("incremental_strong_closure_assign(v)", 02180 var.id()); 02181 02182 // Do something only if necessary. 02183 if (marked_empty() || marked_strongly_closed()) 02184 return; 02185 02186 Octagonal_Shape& x = const_cast<Octagonal_Shape<T>&>(*this); 02187 02188 typedef typename OR_Matrix<N>::row_iterator Row_Iterator; 02189 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 02190 02191 const Row_Iterator m_begin = x.matrix.row_begin(); 02192 const Row_Iterator m_end = x.matrix.row_end(); 02193 02194 // Fill the main diagonal with zeros. 02195 for (Row_Iterator i = m_begin; i != m_end; ++i) { 02196 PPL_ASSERT(is_plus_infinity((*i)[i.index()])); 02197 assign_r((*i)[i.index()], 0, ROUND_NOT_NEEDED); 02198 } 02199 02200 // Using the incremental Floyd-Warshall algorithm. 02201 // Step 1: Improve all constraints on variable `var'. 02202 const dimension_type v = 2*var.id(); 02203 const dimension_type cv = v+1; 02204 Row_Iterator v_iter = m_begin + v; 02205 Row_Iterator cv_iter = v_iter + 1; 02206 Row_Reference x_v = *v_iter; 02207 Row_Reference x_cv = *cv_iter; 02208 const dimension_type rs_v = v_iter.row_size(); 02209 const dimension_type n_rows = x.matrix.num_rows(); 02210 PPL_DIRTY_TEMP(N, sum); 02211 using namespace Implementation::Octagonal_Shapes; 02212 for (Row_Iterator k_iter = m_begin; k_iter != m_end; ++k_iter) { 02213 const dimension_type k = k_iter.index(); 02214 const dimension_type ck = coherent_index(k); 02215 const dimension_type rs_k = k_iter.row_size(); 02216 Row_Reference x_k = *k_iter; 02217 Row_Reference x_ck = (k % 2 != 0) ? *(k_iter-1) : *(k_iter+1); 02218 02219 for (Row_Iterator i_iter = m_begin; i_iter != m_end; ++i_iter) { 02220 const dimension_type i = i_iter.index(); 02221 const dimension_type ci = coherent_index(i); 02222 const dimension_type rs_i = i_iter.row_size(); 02223 Row_Reference x_i = *i_iter; 02224 Row_Reference x_ci = (i % 2 != 0) ? *(i_iter-1) : *(i_iter+1); 02225 02226 const N& x_i_k = (k < rs_i) ? x_i[k] : x_ck[ci]; 02227 if (!is_plus_infinity(x_i_k)) { 02228 const N& x_k_v = (v < rs_k) ? x_k[v] : x_cv[ck]; 02229 if (!is_plus_infinity(x_k_v)) { 02230 add_assign_r(sum, x_i_k, x_k_v, ROUND_UP); 02231 N& x_i_v = (v < rs_i) ? x_i[v] : x_cv[ci]; 02232 min_assign(x_i_v, sum); 02233 } 02234 const N& x_k_cv = (cv < rs_k) ? x_k[cv] : x_v[ck]; 02235 if (!is_plus_infinity(x_k_cv)) { 02236 add_assign_r(sum, x_i_k, x_k_cv, ROUND_UP); 02237 N& x_i_cv = (cv < rs_i) ? x_i[cv] : x_v[ci]; 02238 min_assign(x_i_cv, sum); 02239 } 02240 } 02241 const N& x_k_i = (i < rs_k) ? x_k[i] : x_ci[ck]; 02242 if (!is_plus_infinity(x_k_i)) { 02243 const N& x_v_k = (k < rs_v) ? x_v[k] : x_ck[cv]; 02244 if (!is_plus_infinity(x_v_k)) { 02245 N& x_v_i = (i < rs_v) ? x_v[i] : x_ci[cv]; 02246 add_assign_r(sum, x_v_k, x_k_i, ROUND_UP); 02247 min_assign(x_v_i, sum); 02248 } 02249 const N& x_cv_k = (k < rs_v) ? x_cv[k] : x_ck[v]; 02250 if (!is_plus_infinity(x_cv_k)) { 02251 N& x_cv_i = (i < rs_v) ? x_cv[i] : x_ci[v]; 02252 add_assign_r(sum, x_cv_k, x_k_i, ROUND_UP); 02253 min_assign(x_cv_i, sum); 02254 } 02255 } 02256 02257 } 02258 } 02259 02260 // Step 2: improve the other bounds by using the precise bounds 02261 // for the constraints on `var'. 02262 for (Row_Iterator i_iter = m_begin; i_iter != m_end; ++i_iter) { 02263 const dimension_type i = i_iter.index(); 02264 const dimension_type ci = coherent_index(i); 02265 const dimension_type rs_i = i_iter.row_size(); 02266 Row_Reference x_i = *i_iter; 02267 const N& x_i_v = (v < rs_i) ? x_i[v] : x_cv[ci]; 02268 // TODO: see if it is possible to optimize this inner loop 02269 // by splitting it into several parts, so as to avoid 02270 // conditional expressions. 02271 for (dimension_type j = 0; j < n_rows; ++j) { 02272 const dimension_type cj = coherent_index(j); 02273 Row_Reference x_cj = *(m_begin+cj); 02274 N& x_i_j = (j < rs_i) ? x_i[j] : x_cj[ci]; 02275 if (!is_plus_infinity(x_i_v)) { 02276 const N& x_v_j = (j < rs_v) ? x_v[j] : x_cj[cv]; 02277 if (!is_plus_infinity(x_v_j)) { 02278 add_assign_r(sum, x_i_v, x_v_j, ROUND_UP); 02279 min_assign(x_i_j, sum); 02280 } 02281 } 02282 const N& x_i_cv = (cv < rs_i) ? x_i[cv] : x_v[ci]; 02283 if (!is_plus_infinity(x_i_cv)) { 02284 const N& x_cv_j = (j < rs_v) ? x_cv[j] : x_cj[v]; 02285 if (!is_plus_infinity(x_cv_j)) { 02286 add_assign_r(sum, x_i_cv, x_cv_j, ROUND_UP); 02287 min_assign(x_i_j, sum); 02288 } 02289 } 02290 } 02291 } 02292 02293 // Check for emptiness: the octagon is empty if and only if there is a 02294 // negative value on the main diagonal. 02295 for (Row_Iterator i = m_begin; i != m_end; ++i) { 02296 N& x_i_i = (*i)[i.index()]; 02297 if (sgn(x_i_i) < 0) { 02298 x.set_empty(); 02299 return; 02300 } 02301 else { 02302 // Restore PLUS_INFINITY on the main diagonal. 02303 PPL_ASSERT(sgn(x_i_i) == 0); 02304 assign_r(x_i_i, PLUS_INFINITY, ROUND_NOT_NEEDED); 02305 } 02306 } 02307 02308 // Step 3: we enforce the strong coherence. 02309 x.strong_coherence_assign(); 02310 // The octagon is not empty and it is now strongly closed. 02311 x.set_strongly_closed(); 02312 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::integer_upper_bound_assign_if_exact | ( | const Octagonal_Shape< T > & | y | ) | [inline] |
If the integer upper bound of *this and y is exact, it is assigned to *this and true is returned; otherwise false is returned.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
T is bound to an integer datatype.Implementation is based on Theorem 6.8 of [BHZ09b].
Definition at line 6603 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::non_redundant_matrix_entries(), PPL_COMPILE_TIME_CHECK, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_size(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::swap(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign().
06603 { 06604 PPL_COMPILE_TIME_CHECK(std::numeric_limits<T>::is_integer, 06605 "Octagonal_Shape<T>::" 06606 "integer_upper_bound_assign_if_exact(y):" 06607 " T in not an integer datatype."); 06608 // Declare a const reference to *this (to avoid accidental modifications). 06609 const Octagonal_Shape& x = *this; 06610 const dimension_type x_space_dim = x.space_dimension(); 06611 06612 if (x_space_dim != y.space_dimension()) 06613 throw_dimension_incompatible("integer_upper_bound_assign_if_exact(y)", y); 06614 06615 // The zero-dim case is trivial. 06616 if (x_space_dim == 0) { 06617 upper_bound_assign(y); 06618 return true; 06619 } 06620 06621 // If `x' or `y' is (known to) contain no integral point, 06622 // then the integer upper bound can be computed exactly by tight closure. 06623 if (x.marked_empty()) { 06624 *this = y; 06625 tight_closure_assign(); 06626 return true; 06627 } 06628 else if (y.marked_empty()) { 06629 tight_closure_assign(); 06630 return true; 06631 } 06632 else if (x.is_empty() || x.tight_coherence_would_make_empty()) { 06633 *this = y; 06634 tight_closure_assign(); 06635 return true; 06636 } 06637 else if (y.is_empty() || y.tight_coherence_would_make_empty()) { 06638 tight_closure_assign(); 06639 return true; 06640 } 06641 06642 // Here both `x' and `y' are known to be non-empty (and Z-consistent). 06643 PPL_ASSERT(x.marked_strongly_closed()); 06644 PPL_ASSERT(y.marked_strongly_closed()); 06645 // Pre-compute the integer upper bound of `x' and `y': 06646 // have to take copies, since tight closure might modify the rational shape. 06647 Octagonal_Shape<T> tx(x); 06648 tx.tight_closure_assign(); 06649 Octagonal_Shape<T> ty(y); 06650 ty.tight_closure_assign(); 06651 Octagonal_Shape<T> ub(tx); 06652 ub.upper_bound_assign(ty); 06653 06654 // Compute redundancy information for tx and ty. 06655 // TODO: provide a nicer data structure for redundancy. 06656 // NOTE: there is no need to identify all redundancies, since this is 06657 // an optimization; hence we reuse the strong-reduction helper methods. 06658 std::vector<Bit_Row> tx_non_red; 06659 tx.non_redundant_matrix_entries(tx_non_red); 06660 std::vector<Bit_Row> ty_non_red; 06661 ty.non_redundant_matrix_entries(ty_non_red); 06662 06663 PPL_DIRTY_TEMP(N, lhs_i_j); 06664 PPL_DIRTY_TEMP(N, lhs_k_ell); 06665 PPL_DIRTY_TEMP(N, lhs); 06666 PPL_DIRTY_TEMP(N, lhs_copy); 06667 PPL_DIRTY_TEMP(N, rhs); 06668 PPL_DIRTY_TEMP(N, temp_zero); 06669 assign_r(temp_zero, 0, ROUND_NOT_NEEDED); 06670 PPL_DIRTY_TEMP(N, temp_one); 06671 assign_r(temp_one, 1, ROUND_NOT_NEEDED); 06672 PPL_DIRTY_TEMP(N, temp_two); 06673 assign_r(temp_two, 2, ROUND_NOT_NEEDED); 06674 06675 typedef typename OR_Matrix<N>::const_row_iterator Row_Iterator; 06676 typedef typename OR_Matrix<N>::const_row_reference_type Row_Reference; 06677 const dimension_type n_rows = tx.matrix.num_rows(); 06678 const Row_Iterator tx_m_begin = tx.matrix.row_begin(); 06679 const Row_Iterator ty_m_begin = ty.matrix.row_begin(); 06680 const Row_Iterator ub_m_begin = ub.matrix.row_begin(); 06681 06682 for (dimension_type i = n_rows; i-- > 0; ) { 06683 const Bit_Row& tx_non_red_i = tx_non_red[i]; 06684 using namespace Implementation::Octagonal_Shapes; 06685 const dimension_type ci = coherent_index(i); 06686 const dimension_type row_size_i = OR_Matrix<N>::row_size(i); 06687 Row_Reference tx_i = *(tx_m_begin + i); 06688 Row_Reference ty_i = *(ty_m_begin + i); 06689 Row_Reference ub_i = *(ub_m_begin + i); 06690 const N& ub_i_ci = ub_i[ci]; 06691 for (dimension_type j = row_size_i; j-- > 0; ) { 06692 // Check redundancy of tx_i_j. 06693 if (!tx_non_red_i[j]) 06694 continue; 06695 const N& tx_i_j = tx_i[j]; 06696 const dimension_type cj = coherent_index(j); 06697 const N& eps_i_j = (i == cj) ? temp_two : temp_one; 06698 // Check condition 1a in BHZ09 Theorem 6.8. 06699 add_assign_r(lhs_i_j, tx_i_j, eps_i_j, ROUND_NOT_NEEDED); 06700 if (lhs_i_j > ty_i[j]) 06701 continue; 06702 const dimension_type row_size_cj = OR_Matrix<N>::row_size(cj); 06703 Row_Reference ub_cj = *(ub_m_begin + cj); 06704 const N& ub_cj_j = ub_cj[j]; 06705 for (dimension_type k = 0; k < n_rows; ++k) { 06706 const Bit_Row& ty_non_red_k = ty_non_red[k]; 06707 const dimension_type ck = coherent_index(k); 06708 const dimension_type row_size_k = OR_Matrix<N>::row_size(k); 06709 Row_Reference tx_k = *(tx_m_begin + k); 06710 Row_Reference ty_k = *(ty_m_begin + k); 06711 Row_Reference ub_k = *(ub_m_begin + k); 06712 const N& ub_k_ck = ub_k[ck]; 06713 // Be careful: for each index h, the diagonal element m[h][h] 06714 // is (by convention) +infty in our implementation; however, 06715 // BHZ09 theorem assumes that it is equal to 0. 06716 const N& ub_k_j = (k == j) ? temp_zero 06717 : (j < row_size_k ? ub_k[j] : ub_cj[ck]); 06718 const N& ub_i_ck = (i == ck) ? temp_zero 06719 : (ck < row_size_i ? ub_i[ck] : ub_k[ci]); 06720 06721 for (dimension_type ell = row_size_k; ell-- > 0; ) { 06722 // Check redundancy of y_k_ell. 06723 if (!ty_non_red_k[ell]) 06724 continue; 06725 const N& ty_k_ell = ty_k[ell]; 06726 const dimension_type cell = coherent_index(ell); 06727 const N& eps_k_ell = (k == cell) ? temp_two : temp_one; 06728 // Check condition 1b in BHZ09 Theorem 6.8. 06729 add_assign_r(lhs_k_ell, ty_k_ell, eps_k_ell, ROUND_NOT_NEEDED); 06730 if (lhs_k_ell > tx_k[ell]) 06731 continue; 06732 Row_Reference ub_cell = *(ub_m_begin + cell); 06733 const N& ub_i_ell = (i == ell) ? temp_zero 06734 : (ell < row_size_i ? ub_i[ell] : ub_cell[ci]); 06735 const N& ub_cj_ell = (cj == ell) ? temp_zero 06736 : (ell < row_size_cj ? ub_cj[ell] : ub_cell[j]); 06737 // Check condition 2a in BHZ09 Theorem 6.8. 06738 add_assign_r(lhs, lhs_i_j, lhs_k_ell, ROUND_NOT_NEEDED); 06739 add_assign_r(rhs, ub_i_ell, ub_k_j, ROUND_NOT_NEEDED); 06740 if (lhs > rhs) 06741 continue; 06742 // Check condition 2b in BHZ09 Theorem 6.8. 06743 add_assign_r(rhs, ub_i_ck, ub_cj_ell, ROUND_NOT_NEEDED); 06744 if (lhs > rhs) 06745 continue; 06746 // Check condition 3a in BHZ09 Theorem 6.8. 06747 assign_r(lhs_copy, lhs, ROUND_NOT_NEEDED); 06748 add_assign_r(lhs, lhs, lhs_i_j, ROUND_NOT_NEEDED); 06749 add_assign_r(rhs, ub_i_ell, ub_i_ck, ROUND_NOT_NEEDED); 06750 add_assign_r(rhs, rhs, ub_cj_j, ROUND_NOT_NEEDED); 06751 if (lhs > rhs) 06752 continue; 06753 // Check condition 3b in BHZ09 Theorem 6.8. 06754 add_assign_r(rhs, ub_k_j, ub_cj_ell, ROUND_NOT_NEEDED); 06755 add_assign_r(rhs, rhs, ub_i_ci, ROUND_NOT_NEEDED); 06756 if (lhs > rhs) 06757 continue; 06758 // Check condition 4a in BHZ09 Theorem 6.8. 06759 add_assign_r(lhs, lhs_copy, lhs_k_ell, ROUND_NOT_NEEDED); 06760 add_assign_r(rhs, ub_i_ell, ub_cj_ell, ROUND_NOT_NEEDED); 06761 add_assign_r(rhs, rhs, ub_k_ck, ROUND_NOT_NEEDED); 06762 if (lhs > rhs) 06763 continue; 06764 // Check condition 4b in BHZ09 Theorem 6.8. 06765 add_assign_r(rhs, ub_k_j, ub_i_ck, ROUND_NOT_NEEDED); 06766 add_assign_r(rhs, rhs, ub_cell[ell], ROUND_NOT_NEEDED); 06767 if (lhs <= rhs) 06768 // All 8 conditions are satisfied: 06769 // integer upper bound is not exact. 06770 return false; 06771 } 06772 } 06773 } 06774 } 06775 06776 // The upper bound of x and y is indeed exact. 06777 swap(ub); 06778 PPL_ASSERT(OK()); 06779 return true; 06780 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign | ( | const Octagonal_Shape< T > & | y | ) | [inline] |
Assigns to *this the intersection of *this and y.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 3128 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::element_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign().
03128 { 03129 // Dimension-compatibility check. 03130 if (space_dim != y.space_dim) 03131 throw_dimension_incompatible("intersection_assign(y)", y); 03132 03133 // If one of the two octagons is empty, the intersection is empty. 03134 if (marked_empty()) 03135 return; 03136 if (y.marked_empty()) { 03137 set_empty(); 03138 return; 03139 } 03140 // If both octagons are zero-dimensional,then at this point 03141 // they are necessarily non-empty, 03142 // so that their intersection is non-empty too. 03143 if (space_dim == 0) 03144 return; 03145 03146 // To intersect two octagons we compare the constraints 03147 // and we choose the less values. 03148 bool changed = false; 03149 03150 typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin(); 03151 for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(), 03152 matrix_element_end = matrix.element_end(); 03153 i != matrix_element_end; 03154 ++i, ++j) { 03155 N& elem = *i; 03156 const N& y_elem = *j; 03157 if (y_elem < elem) { 03158 elem = y_elem; 03159 changed = true; 03160 } 03161 } 03162 03163 // This method not preserve the closure. 03164 if (changed && marked_strongly_closed()) 03165 reset_strongly_closed(); 03166 PPL_ASSERT(OK()); 03167 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::is_bounded | ( | ) | const [inline] |
Returns true if and only if *this is a bounded OS.
Definition at line 824 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().
00824 { 00825 strong_closure_assign(); 00826 // A zero-dimensional or empty octagon is bounded. 00827 if (marked_empty() || space_dim == 0) 00828 return true; 00829 00830 // A bounded octagon never can contains trivial constraints. 00831 for (typename OR_Matrix<N>::const_row_iterator i = matrix.row_begin(), 00832 matrix_row_end = matrix.row_end(); i != matrix_row_end; ++i) { 00833 typename OR_Matrix<N>::const_row_reference_type x_i = *i; 00834 const dimension_type i_index = i.index(); 00835 for (dimension_type j = i.row_size(); j-- > 0; ) 00836 if (i_index != j) 00837 if (is_plus_infinity(x_i[j])) 00838 return false; 00839 } 00840 00841 return true; 00842 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::is_discrete | ( | ) | const [inline] |
Returns true if and only if *this is discrete.
Definition at line 252 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_dimension().
00252 { 00253 return affine_dimension() == 0; 00254 }
| 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.
| std::invalid_argument | Thrown if x and y are topology-incompatible or dimension-incompatible. |
Definition at line 748 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
00748 { 00749 // Dimension-compatibility check. 00750 if (space_dim != y.space_dim) 00751 throw_dimension_incompatible("is_disjoint_from(y)", y); 00752 00753 // If one Octagonal_Shape is empty, the Octagonal_Shapes are disjoint. 00754 strong_closure_assign(); 00755 if (marked_empty()) 00756 return true; 00757 y.strong_closure_assign(); 00758 if (y.marked_empty()) 00759 return true; 00760 00761 // Two Octagonal_Shapes are disjoint if and only if their intersection 00762 // is empty, i.e., if and only if there exists a variable such that 00763 // the upper bound of the constraint on that variable in the first 00764 // Octagonal_Shape is strictly less than the lower bound of 00765 // the correspomding constraint in the second Octagonal_Shape or vice versa. 00766 00767 const dimension_type n_rows = matrix.num_rows(); 00768 00769 typedef typename OR_Matrix<N>::const_row_iterator Row_Iterator; 00770 typedef typename OR_Matrix<N>::const_row_reference_type Row_Reference; 00771 00772 const Row_Iterator m_begin = matrix.row_begin(); 00773 const Row_Iterator m_end = matrix.row_end(); 00774 00775 const Row_Iterator y_begin = y.matrix.row_begin(); 00776 00777 PPL_DIRTY_TEMP(N, neg_y_ci_cj); 00778 for (Row_Iterator i_iter = m_begin; i_iter != m_end; ++i_iter) { 00779 using namespace Implementation::Octagonal_Shapes; 00780 const dimension_type i = i_iter.index(); 00781 const dimension_type ci = coherent_index(i); 00782 const dimension_type rs_i = i_iter.row_size(); 00783 Row_Reference m_i = *i_iter; 00784 for (dimension_type j = 0; j < n_rows; ++j) { 00785 const dimension_type cj = coherent_index(j); 00786 Row_Reference m_cj = *(m_begin + cj); 00787 const N& m_i_j = (j < rs_i) ? m_i[j] : m_cj[ci]; 00788 Row_Reference y_ci = *(y_begin + ci); 00789 Row_Reference y_j = *(y_begin + j); 00790 const N& y_ci_cj = (j < rs_i) ? y_ci[cj] : y_j[i]; 00791 neg_assign_r(neg_y_ci_cj, y_ci_cj, ROUND_UP); 00792 if (m_i_j < neg_y_ci_cj) 00793 return true; 00794 } 00795 } 00796 return false; 00797 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty | ( | ) | const [inline] |
Returns true if and only if *this is an empty OS.
Definition at line 258 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constrains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::frequency(), Parma_Polyhedra_Library::Octagonal_Shape< T >::integer_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::Pointset_Powerset(), Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign_if_exact().
00258 { 00259 strong_closure_assign(); 00260 return marked_empty(); 00261 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strong_coherent | ( | ) | const [inline, private] |
Returns true if in the octagon taken two at a time unary constraints, there is also the constraint that represent their sum.
Definition at line 1081 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), and Parma_Polyhedra_Library::OR_Matrix< T >::row_size().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::OK().
01081 { 01082 // This method is only used by method OK() so as to check if a 01083 // strongly closed matrix is also strong-coherent, as it must be. 01084 const dimension_type num_rows = matrix.num_rows(); 01085 01086 // Allocated here once and for all. 01087 PPL_DIRTY_TEMP(N, semi_sum); 01088 // The strong-coherence is: for every indexes i and j (and i != j) 01089 // matrix[i][j] <= (matrix[i][ci] + matrix[cj][j])/2 01090 // where ci = i + 1, if i is even number or 01091 // ci = i - 1, if i is odd. 01092 // Ditto for cj. 01093 for (dimension_type i = num_rows; i-- > 0; ) { 01094 typename OR_Matrix<N>::const_row_iterator iter = matrix.row_begin() + i; 01095 typename OR_Matrix<N>::const_row_reference_type m_i = *iter; 01096 using namespace Implementation::Octagonal_Shapes; 01097 const N& m_i_ci = m_i[coherent_index(i)]; 01098 for (dimension_type j = matrix.row_size(i); j-- > 0; ) 01099 // Note: on the main diagonal only PLUS_INFINITY can occur. 01100 if (i != j) { 01101 const N& m_cj_j = matrix[coherent_index(j)][j]; 01102 if (!is_plus_infinity(m_i_ci) 01103 && !is_plus_infinity(m_cj_j)) { 01104 // Compute (m_i_ci + m_cj_j)/2 into `semi_sum', 01105 // rounding the result towards plus infinity. 01106 add_assign_r(semi_sum, m_i_ci, m_cj_j, ROUND_UP); 01107 div_2exp_assign_r(semi_sum, semi_sum, 1, ROUND_UP); 01108 if (m_i[j] > semi_sum) 01109 return false; 01110 } 01111 } 01112 } 01113 return true; 01114 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strongly_reduced | ( | ) | const [inline, private] |
Returns true if and only if this->matrix is strongly reduced.
Definition at line 1118 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), and Parma_Polyhedra_Library::OR_Matrix< T >::row_end().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign().
01118 { 01119 // This method is only used in assertions: efficiency is not a must. 01120 01121 // An empty octagon is already transitively reduced. 01122 if (marked_empty()) 01123 return true; 01124 01125 Octagonal_Shape x = *this; 01126 // The matrix representing an OS is strongly reduced if, by removing 01127 // any constraint, the resulting matrix describes a different OS. 01128 for (typename OR_Matrix<N>::const_row_iterator iter = matrix.row_begin(), 01129 matrix_row_end = matrix.row_end(); iter != matrix_row_end; ++iter) { 01130 typename OR_Matrix<N>::const_row_reference_type m_i = *iter; 01131 const dimension_type i = iter.index(); 01132 for (dimension_type j = iter.row_size(); j-- > 0; ) { 01133 if (!is_plus_infinity(m_i[j])) { 01134 Octagonal_Shape x_copy = *this; 01135 assign_r(x_copy.matrix[i][j], PLUS_INFINITY, ROUND_NOT_NEEDED); 01136 if (x == x_copy) 01137 return false; 01138 } 01139 } 01140 } 01141 // The octagon is just reduced. 01142 return true; 01143 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::is_topologically_closed | ( | ) | const [inline] |
Returns true if and only if *this is a topologically closed subset of the vector space.
Definition at line 311 of file Octagonal_Shape.inlines.hh.
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::is_universe | ( | ) | const [inline] |
Returns true if and only if *this is a universe OS.
Definition at line 801 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::element_end(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min().
00801 { 00802 // An empty octagon isn't, of course, universe. 00803 if (marked_empty()) 00804 return false; 00805 00806 // If the octagon is non-empty and zero-dimensional, 00807 // then it is necessarily the universe octagon. 00808 if (space_dim == 0) 00809 return true; 00810 00811 // An universe octagon can only contains trivial constraints. 00812 for (typename OR_Matrix<N>::const_element_iterator 00813 i = matrix.element_begin(), matrix_element_end = matrix.element_end(); 00814 i != matrix_element_end; 00815 ++i) 00816 if (!is_plus_infinity(*i)) 00817 return false; 00818 00819 return true; 00820 }
| 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.
| 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). |
| std::invalid_argument | Thrown if *this, y and cs are dimension-incompatible or if there is in cs a strict inequality. |
Definition at line 3438 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.
03440 { 03441 03442 // Dimension-compatibility check. 03443 if (space_dim != y.space_dim) 03444 throw_dimension_incompatible("limited_BHMZ05_extrapolation_assign(y, cs)", 03445 y); 03446 // `cs' must be dimension-compatible with the two octagons. 03447 const dimension_type cs_space_dim = cs.space_dimension(); 03448 if (space_dim < cs_space_dim) 03449 throw_constraint_incompatible("limited_CH78_extrapolation_assign(y, cs)"); 03450 03451 // Strict inequalities not allowed. 03452 if (cs.has_strict_inequalities()) 03453 throw_constraint_incompatible("limited_CH78_extrapolation_assign(y, cs)"); 03454 03455 // The limited BHMZ05-extrapolation between two octagons in a 03456 // zero-dimensional space is a octagon in a zero-dimensional 03457 // space, too. 03458 if (space_dim == 0) 03459 return; 03460 03461 #ifndef NDEBUG 03462 { 03463 // We assume that `y' is contained in or equal to `*this'. 03464 const Octagonal_Shape x_copy = *this; 03465 const Octagonal_Shape y_copy = y; 03466 PPL_ASSERT(x_copy.contains(y_copy)); 03467 } 03468 #endif 03469 03470 // If `*this' is empty, since `*this' contains `y', `y' is empty too. 03471 if (marked_empty()) 03472 return; 03473 // If `y' is empty, we return. 03474 if (y.marked_empty()) 03475 return; 03476 03477 Octagonal_Shape limiting_octagon(space_dim, UNIVERSE); 03478 get_limiting_octagon(cs, limiting_octagon); 03479 BHMZ05_widening_assign(y, tp); 03480 intersection_assign(limiting_octagon); 03481 }
| 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.
| 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). |
| std::invalid_argument | Thrown if *this, y and cs are dimension-incompatible or if cs contains a strict inequality. |
Definition at line 3326 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.
03328 { 03329 03330 // Dimension-compatibility check. 03331 if (space_dim != y.space_dim) 03332 throw_dimension_incompatible("limited_CC76_extrapolation_assign(y, cs)", 03333 y); 03334 // `cs' must be dimension-compatible with the two octagons. 03335 const dimension_type cs_space_dim = cs.space_dimension(); 03336 if (space_dim < cs_space_dim) 03337 throw_constraint_incompatible("limited_CC76_extrapolation_assign(y, cs)"); 03338 03339 // Strict inequalities not allowed. 03340 if (cs.has_strict_inequalities()) 03341 throw_constraint_incompatible("limited_CC76_extrapolation_assign(y, cs)"); 03342 03343 // The limited CC76-extrapolation between two octagons in a 03344 // zero-dimensional space is a octagon in a zero-dimensional 03345 // space, too. 03346 if (space_dim == 0) 03347 return; 03348 03349 #ifndef NDEBUG 03350 { 03351 // We assume that `y' is contained in or equal to `*this'. 03352 const Octagonal_Shape x_copy = *this; 03353 const Octagonal_Shape y_copy = y; 03354 PPL_ASSERT(x_copy.contains(y_copy)); 03355 } 03356 #endif 03357 03358 // If `*this' is empty, since `*this' contains `y', `y' is empty too. 03359 if (marked_empty()) 03360 return; 03361 // If `y' is empty, we return. 03362 if (y.marked_empty()) 03363 return; 03364 03365 Octagonal_Shape limiting_octagon(space_dim, UNIVERSE); 03366 get_limiting_octagon(cs, limiting_octagon); 03367 CC76_extrapolation_assign(y, tp); 03368 intersection_assign(limiting_octagon); 03369 }
| 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.
| pfunc | The partial function specifying the destiny of each dimension. |
The template type parameter Partial_Function must provide the following methods.
bool has_empty_codomain() const
returns true if and only if the represented partial function has an empty codomain (i.e., it is always undefined). The has_empty_codomain() method will always be called before the methods below. However, if has_empty_codomain() returns true, none of the functions below will be called.
dimension_type max_in_codomain() const
returns the maximum value that belongs to the codomain of the partial function.
bool maps(dimension_type i, dimension_type& j) const
Let
be the represented function and
be the value of i. If
is defined in
, then
is assigned to j and true is returned. If
is undefined in
, then false is returned.
The result is undefined if pfunc does not encode a partial function with the properties described in the specification of the mapping operator.
Definition at line 3045 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::swap().
03045 { 03046 if (space_dim == 0) 03047 return; 03048 03049 if (pfunc.has_empty_codomain()) { 03050 // All dimensions vanish: the octagon becomes zero_dimensional. 03051 remove_higher_space_dimensions(0); 03052 return; 03053 } 03054 03055 const dimension_type new_space_dim = pfunc.max_in_codomain() + 1; 03056 // If we are going to actually reduce the space dimension, 03057 // then shortest-path closure is required to keep precision. 03058 if (new_space_dim < space_dim) 03059 strong_closure_assign(); 03060 03061 // If the octagon is empty, then it is sufficient to adjust 03062 // the space dimension of the octagon. 03063 if (marked_empty()) { 03064 remove_higher_space_dimensions(new_space_dim); 03065 return; 03066 } 03067 03068 // We create a new matrix with the new space dimension. 03069 OR_Matrix<N> x(new_space_dim); 03070 03071 typedef typename OR_Matrix<N>::row_iterator Row_Iterator; 03072 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 03073 03074 Row_Iterator m_begin = x.row_begin(); 03075 03076 for (Row_Iterator i_iter = matrix.row_begin(), i_end = matrix.row_end(); 03077 i_iter != i_end; i_iter += 2) { 03078 dimension_type new_i; 03079 dimension_type i = i_iter.index()/2; 03080 // We copy and place in the position into `x' the only cells of 03081 // the `matrix' that refer to both mapped variables, 03082 // the variable `i' and `j'. 03083 if (pfunc.maps(i, new_i)) { 03084 Row_Reference r_i = *i_iter; 03085 Row_Reference r_ii = *(i_iter + 1); 03086 dimension_type double_new_i = 2*new_i; 03087 Row_Iterator x_iter = m_begin + double_new_i; 03088 Row_Reference x_i = *x_iter; 03089 Row_Reference x_ii = *(x_iter + 1); 03090 for (dimension_type j = 0; j <= i; ++j) { 03091 dimension_type new_j; 03092 // If also the second variable is mapped, we work. 03093 if (pfunc.maps(j, new_j)) { 03094 dimension_type dj = 2*j; 03095 dimension_type double_new_j = 2*new_j; 03096 // Mapped the constraints, exchanging the indexes. 03097 // Attention: our matrix is pseudo-triangular. 03098 // If new_j > new_i, we must consider, as rows, the rows of 03099 // the variable new_j, and not of new_i ones. 03100 if (new_i >= new_j) { 03101 assign_or_swap(x_i[double_new_j], r_i[dj]); 03102 assign_or_swap(x_ii[double_new_j], r_ii[dj]); 03103 assign_or_swap(x_ii[double_new_j+1], r_ii[dj + 1]); 03104 assign_or_swap(x_i[double_new_j+1], r_i[dj + 1]); 03105 } 03106 else { 03107 Row_Iterator xj_iter = m_begin + double_new_j; 03108 Row_Reference x_j = *xj_iter; 03109 Row_Reference x_jj = *(xj_iter + 1); 03110 assign_or_swap(x_jj[double_new_i+1], r_i[dj]); 03111 assign_or_swap(x_jj[double_new_i], r_ii[dj]); 03112 assign_or_swap(x_j[double_new_i+1], r_i[dj+1]); 03113 assign_or_swap(x_j[double_new_i], r_ii[dj+1]); 03114 } 03115 03116 } 03117 } 03118 } 03119 } 03120 03121 std::swap(matrix, x); 03122 space_dim = new_space_dim; 03123 PPL_ASSERT(OK()); 03124 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty | ( | ) | const [inline, private] |
Returns true if the OS is known to be empty.
The return value false does not necessarily implies that *this is non-empty.
Definition at line 78 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::status, and Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::test_empty().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constrains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Octagonal_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::frequency(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::integer_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_bounded(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strongly_reduced(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_universe(), Parma_Polyhedra_Library::Octagonal_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_BHMZ05_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain(), Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign_if_exact().
00078 { 00079 return status.test_empty(); 00080 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed | ( | ) | const [inline, private] |
Returns true if this->matrix is known to be strongly closed.
The return value false does not necessarily implies that this->matrix is not strongly closed.
Definition at line 72 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::status, and Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::test_strongly_closed().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::get_limiting_octagon(), Parma_Polyhedra_Library::Octagonal_Shape< T >::integer_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign_if_exact().
00072 { 00073 return status.test_strongly_closed(); 00074 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_zero_dim_univ | ( | ) | const [inline, private] |
Returns true if the OS is the zero-dimensional universe.
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_zero_dim_univ().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape().
00066 { 00067 return status.test_zero_dim_univ(); 00068 }
| const Octagonal_Shape< T >::coefficient_type & Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix_at | ( | dimension_type | i, | |
| dimension_type | j | |||
| ) | const [inline, private] |
Definition at line 357 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), and Parma_Polyhedra_Library::OR_Matrix< T >::row_size().
00358 { 00359 PPL_ASSERT(i < matrix.num_rows() && j < matrix.num_rows()); 00360 using namespace Implementation::Octagonal_Shapes; 00361 return (j < matrix.row_size(i)) 00362 ? matrix[i][j] 00363 : matrix[coherent_index(j)][coherent_index(i)]; 00364 }
| Octagonal_Shape< T >::coefficient_type & Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix_at | ( | dimension_type | i, | |
| dimension_type | j | |||
| ) | [inline, private] |
Definition at line 368 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), and Parma_Polyhedra_Library::OR_Matrix< T >::row_size().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign().
00369 { 00370 PPL_ASSERT(i < matrix.num_rows() && j < matrix.num_rows()); 00371 using namespace Implementation::Octagonal_Shapes; 00372 return (j < matrix.row_size(i)) 00373 ? matrix[i][j] 00374 : matrix[coherent_index(j)][coherent_index(i)]; 00375 }
| 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.
| 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. |
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
If *this is empty or expr is not bounded in the appropriate direction, false is returned and ext_n, ext_d, included and g are left untouched.
Definition at line 1293 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::MIP_Problem::evaluate_objective_function(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_universe(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::MINIMIZATION, Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, Parma_Polyhedra_Library::MIP_Problem::optimizing_point(), Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
01296 { 01297 // The dimension of `expr' should not be greater than the dimension 01298 // of `*this'. 01299 const dimension_type expr_space_dim = expr.space_dimension(); 01300 if (space_dim < expr_space_dim) 01301 throw_dimension_incompatible((maximize 01302 ? "maximize(e, ...)" 01303 : "minimize(e, ...)"), "e", expr); 01304 // Deal with zero-dim octagons first. 01305 if (space_dim == 0) { 01306 if (marked_empty()) 01307 return false; 01308 else { 01309 ext_n = expr.inhomogeneous_term(); 01310 ext_d = 1; 01311 included = true; 01312 g = point(); 01313 return true; 01314 } 01315 } 01316 01317 strong_closure_assign(); 01318 // For an empty OS we simply return false. 01319 if (marked_empty()) 01320 return false; 01321 if (!is_universe()) { 01322 // We use MIP_Problems to handle constraints that are not 01323 // octagonal difference. 01324 Optimization_Mode max_min = (maximize) ? MAXIMIZATION : MINIMIZATION; 01325 MIP_Problem mip(space_dim, constraints(), expr, max_min); 01326 if (mip.solve() == OPTIMIZED_MIP_PROBLEM) { 01327 g = mip.optimizing_point(); 01328 mip.evaluate_objective_function(g, ext_n, ext_d); 01329 included = true; 01330 return true; 01331 } 01332 } 01333 // The `expr' is unbounded. 01334 return false; 01335 }
| 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.
| 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; |
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
If *this is empty or expr is not bounded in the appropriate direction, false is returned and ext_n, ext_d and included are left untouched.
Definition at line 1190 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::extract_octagonal_difference(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::MINIMIZATION, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::numer_denom(), Parma_Polyhedra_Library::MIP_Problem::optimal_value(), Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::maximize(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::minimize().
01193 { 01194 // The dimension of `expr' should not be greater than the dimension 01195 // of `*this'. 01196 const dimension_type expr_space_dim = expr.space_dimension(); 01197 if (space_dim < expr_space_dim) 01198 throw_dimension_incompatible((maximize 01199 ? "maximize(e, ...)" 01200 : "minimize(e, ...)"), "e", expr); 01201 // Deal with zero-dim octagons first. 01202 if (space_dim == 0) { 01203 if (marked_empty()) 01204 return false; 01205 else { 01206 ext_n = expr.inhomogeneous_term(); 01207 ext_d = 1; 01208 included = true; 01209 return true; 01210 } 01211 } 01212 01213 strong_closure_assign(); 01214 // For an empty OS we simply return false. 01215 if (marked_empty()) 01216 return false; 01217 01218 // The constraint `c' is used to check if `expr' is an octagonal difference 01219 // and, in this case, to select the cell. 01220 const Constraint& c = (maximize) ? expr <= 0 : expr >= 0; 01221 dimension_type num_vars = 0; 01222 dimension_type i = 0; 01223 dimension_type j = 0; 01224 PPL_DIRTY_TEMP_COEFFICIENT(coeff); 01225 PPL_DIRTY_TEMP_COEFFICIENT(term); 01226 if (!extract_octagonal_difference(c, c.space_dimension(), num_vars, 01227 i, j, coeff, term)) { 01228 // `c' is not an octagonal constraint: use the MIP solver. 01229 Optimization_Mode max_min = (maximize) ? MAXIMIZATION : MINIMIZATION; 01230 MIP_Problem mip(space_dim, constraints(), expr, max_min); 01231 if (mip.solve() == OPTIMIZED_MIP_PROBLEM) { 01232 mip.optimal_value(ext_n, ext_d); 01233 included = true; 01234 return true; 01235 } 01236 else 01237 // Here`expr' is unbounded in `*this'. 01238 return false; 01239 } 01240 else { 01241 // `c' is an octagonal constraint. 01242 if (num_vars == 0) { 01243 ext_n = expr.inhomogeneous_term(); 01244 ext_d = 1; 01245 included = true; 01246 return true; 01247 } 01248 01249 // Select the cell to be checked. 01250 typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin() + i; 01251 typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter; 01252 PPL_DIRTY_TEMP(N, d); 01253 if (!is_plus_infinity(m_i[j])) { 01254 const Coefficient& b = expr.inhomogeneous_term(); 01255 PPL_DIRTY_TEMP_COEFFICIENT(minus_b); 01256 neg_assign(minus_b, b); 01257 const Coefficient& sc_b = maximize ? b : minus_b; 01258 assign_r(d, sc_b, ROUND_UP); 01259 // Set `coeff_expr' to the absolute value of coefficient of a variable 01260 // of `expr'. 01261 PPL_DIRTY_TEMP(N, coeff_expr); 01262 const Coefficient& coeff_i = expr.coefficient(Variable(i/2)); 01263 const int sign_i = sgn(coeff_i); 01264 if (sign_i > 0) 01265 assign_r(coeff_expr, coeff_i, ROUND_UP); 01266 else { 01267 PPL_DIRTY_TEMP_COEFFICIENT(minus_coeff_i); 01268 neg_assign(minus_coeff_i, expr.coefficient(Variable(i/2))); 01269 assign_r(coeff_expr, minus_coeff_i, ROUND_UP); 01270 } 01271 // Approximating the maximum/minimum of `expr'. 01272 if (num_vars == 1) { 01273 PPL_DIRTY_TEMP(N, m_i_j); 01274 div_2exp_assign_r(m_i_j, m_i[j], 1, ROUND_UP); 01275 add_mul_assign_r(d, coeff_expr, m_i_j, ROUND_UP); 01276 } 01277 else 01278 add_mul_assign_r(d, coeff_expr, m_i[j], ROUND_UP); 01279 numer_denom(d, ext_n, ext_d); 01280 if (!maximize) 01281 neg_assign(ext_n); 01282 included = true; 01283 return true; 01284 } 01285 01286 // The `expr' is unbounded. 01287 return false; 01288 } 01289 }
| dimension_type Parma_Polyhedra_Library::Octagonal_Shape< T >::max_space_dimension | ( | ) | [inline, static] |
Returns the maximum space dimension that an OS can handle.
Definition at line 60 of file Octagonal_Shape.inlines.hh.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension().
00060 { 00061 return OR_Matrix<N>::max_num_rows()/2; 00062 }
| 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.
| 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. |
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
If *this is empty or expr is not bounded from above, false is returned and sup_n, sup_d, maximum and g are left untouched.
Definition at line 285 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min().
00288 { 00289 return max_min(expr, true, sup_n, sup_d, maximum, g); 00290 }
| 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.
| 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. |
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
If *this is empty or expr is not bounded from above, false is returned and sup_n, sup_d and maximum are left untouched.
Definition at line 277 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with().
00279 { 00280 return max_min(expr, true, sup_n, sup_d, maximum); 00281 }
| 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.
| 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. |
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
If *this is empty or expr is not bounded from below, false is returned and inf_n, inf_d, minimum and g are left untouched.
Definition at line 302 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min().
00305 { 00306 return max_min(expr, false, inf_n, inf_d, minimum, g); 00307 }
| 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.
| 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. |
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
If *this is empty or expr is not bounded from below, false is returned and inf_n, inf_d and minimum are left untouched.
Definition at line 294 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with().
00296 { 00297 return max_min(expr, false, inf_n, inf_d, minimum); 00298 }
| Congruence_System Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences | ( | ) | const [inline] |
Returns a minimal system of (equality) congruences satisfied by *this with the same affine dimension as *this.
Definition at line 583 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::Congruence_System::insert(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Congruence_System::zero_dim_empty().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::congruences().
00583 { 00584 // Strong closure is necessary to detect emptiness 00585 // and all (possibly implicit) equalities. 00586 strong_closure_assign(); 00587 const dimension_type space_dim = space_dimension(); 00588 Congruence_System cgs; 00589 if (space_dim == 0) { 00590 if (marked_empty()) 00591 cgs = Congruence_System::zero_dim_empty(); 00592 } 00593 else if (marked_empty()) 00594 cgs.insert((0*Variable(space_dim-1) %= 1) / 0); 00595 else { 00596 // KLUDGE: in the future `cgs' will be constructed of the right dimension. 00597 // For the time being, we force the dimension with the following line. 00598 cgs.insert(0*Variable(space_dim-1) == 0); 00599 00600 // The vector `leaders' is used to represent equivalence classes: 00601 // `leaders[i] == i' if and only if `i' is the leader of its 00602 // equivalence class (i.e., the minimum index in the class); 00603 std::vector<dimension_type> leaders; 00604 compute_leaders(leaders); 00605 00606 PPL_DIRTY_TEMP_COEFFICIENT(num); 00607 PPL_DIRTY_TEMP_COEFFICIENT(den); 00608 for (dimension_type i = 0, i_end = 2*space_dim; i != i_end; i += 2) { 00609 const dimension_type lead_i = leaders[i]; 00610 if (i == lead_i) { 00611 if (leaders[i+1] == i) 00612 // `i' is the leader of the singular equivalence class. 00613 goto singular; 00614 else 00615 // `i' is the leader of a non-singular equivalence class. 00616 continue; 00617 } 00618 else { 00619 // `i' is not a leader. 00620 if (leaders[i+1] == lead_i) 00621 // `i' belongs to the singular equivalence class. 00622 goto singular; 00623 else 00624 // `i' does not belong to the singular equivalence class. 00625 goto non_singular; 00626 } 00627 00628 singular: 00629 // `i' belongs to the singular equivalence class: 00630 // we have a unary equality constraint. 00631 { 00632 const Variable x(i/2); 00633 const N& c_ii_i = matrix[i+1][i]; 00634 #ifndef NDEBUG 00635 const N& c_i_ii = matrix[i][i+1]; 00636 PPL_ASSERT(is_additive_inverse(c_i_ii, c_ii_i)); 00637 #endif 00638 numer_denom(c_ii_i, num, den); 00639 den *= 2; 00640 cgs.insert(den*x == num); 00641 } 00642 continue; 00643 00644 non_singular: 00645 // `i' does not belong to the singular equivalence class. 00646 // we have a binary equality constraint. 00647 { 00648 const N& c_i_li = matrix[i][lead_i]; 00649 #ifndef NDEBUG 00650 using namespace Implementation::Octagonal_Shapes; 00651 const N& c_ii_lii = matrix[i+1][coherent_index(lead_i)]; 00652 PPL_ASSERT(is_additive_inverse(c_ii_lii, c_i_li)); 00653 #endif 00654 const Variable x(lead_i/2); 00655 const Variable y(i/2); 00656 numer_denom(c_i_li, num, den); 00657 if (lead_i % 2 == 0) 00658 cgs.insert(den*x - den*y == num); 00659 else 00660 cgs.insert(den*x + den*y + num == 0); 00661 } 00662 continue; 00663 } 00664 } 00665 return cgs; 00666 }
| Constraint_System Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_constraints | ( | ) | const [inline] |
Returns a minimized system of constraints defining *this.
Definition at line 379 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign().
00379 { 00380 strong_reduction_assign(); 00381 return constraints(); 00382 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::non_redundant_matrix_entries | ( | std::vector< Bit_Row > & | non_redundant | ) | const [inline, private] |
Stores into non_redundant information about the matrix entries that are non-redundant (i.e., will occur in strongly reduced matrix).
It is assumed that the OS is not empty and strongly closed; moreover, argument non_redundant is assumed to be empty.
Definition at line 2448 of file Octagonal_Shape.templates.hh.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::integer_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign_if_exact().
02448 { 02449 // Private method: the caller has to ensure the following. 02450 PPL_ASSERT(space_dim > 0 && !marked_empty() && marked_strongly_closed()); 02451 PPL_ASSERT(nr_rows.empty()); 02452 02453 // Initialize `non_redundant' as if it was an OR_Matrix of booleans 02454 // (initially set to false). 02455 nr_rows.resize(2*space_dim); 02456 02457 // Step 1: compute zero-equivalence classes. 02458 // Variables corresponding to indices `i' and `j' are zero-equivalent 02459 // if they lie on a zero-weight loop; since the matrix is strongly 02460 // closed, this happens if and only if matrix[i][j] == -matrix[ci][cj]. 02461 std::vector<dimension_type> no_sing_leaders; 02462 dimension_type sing_leader = 0; 02463 bool exist_sing_class = false; 02464 std::vector<dimension_type> successor; 02465 compute_successors(successor); 02466 compute_leaders(successor, no_sing_leaders, exist_sing_class, sing_leader); 02467 const dimension_type num_no_sing_leaders = no_sing_leaders.size(); 02468 02469 02470 // Step 2: flag redundant constraints in `redundancy'. 02471 // Go through non-singular leaders first. 02472 for (dimension_type li = 0; li < num_no_sing_leaders; ++li) { 02473 const dimension_type i = no_sing_leaders[li]; 02474 using namespace Implementation::Octagonal_Shapes; 02475 const dimension_type ci = coherent_index(i); 02476 typename OR_Matrix<N>::const_row_reference_type 02477 m_i = *(matrix.row_begin()+i); 02478 if (i % 2 == 0) { 02479 // Each positive equivalence class must have a single 0-cycle 02480 // connecting all equivalent variables in increasing order. 02481 // Note: by coherence assumption, the variables in the 02482 // corresponding negative equivalence class are 02483 // automatically connected. 02484 if (i != successor[i]) { 02485 dimension_type j = i; 02486 dimension_type next_j = successor[j]; 02487 while (j != next_j) { 02488 nr_rows[next_j].set(j); 02489 j = next_j; 02490 next_j = successor[j]; 02491 } 02492 const dimension_type cj = coherent_index(j); 02493 nr_rows[cj].set(ci); 02494 } 02495 } 02496 02497 dimension_type rs_li = (li % 2 != 0) ? li :li+1; 02498 // Check if the constraint is redundant. 02499 PPL_DIRTY_TEMP(N, tmp); 02500 for (dimension_type lj = 0 ; lj <= rs_li; ++lj) { 02501 const dimension_type j = no_sing_leaders[lj]; 02502 const dimension_type cj = coherent_index(j); 02503 const N& m_i_j = m_i[j]; 02504 const N& m_i_ci = m_i[ci]; 02505 bool to_add = true; 02506 // Control if the constraint is redundant by strong-coherence, 02507 // that is: 02508 // m_i_j >= (m_i_ci + m_cj_j)/2, where j != ci. 02509 if (j != ci) { 02510 add_assign_r(tmp, m_i_ci, matrix[cj][j], ROUND_UP); 02511 div_2exp_assign_r(tmp, tmp, 1, ROUND_UP); 02512 if (m_i_j >= tmp) 02513 // The constraint is redundant. 02514 continue; 02515 } 02516 // Control if the constraint is redundant by strong closure, that is 02517 // if there is a path from i to j (i = i_0, ... , i_n = j), such that 02518 // m_i_j = sum_{k=0}^{n-1} m_{i_k}_{i_(k+1)}. 02519 // Since the octagon is already strongly closed, the above relation 02520 // is reduced to three case, in accordance with k, i, j inter-depend: 02521 // exit k such that 02522 // 1.) m_i_j >= m_i_k + m_cj_ck, if k < j < i; or 02523 // 2.) m_i_j >= m_i_k + m_k,_j, if j < k < i; or 02524 // 3.) m_i_j >= m_ck_ci + m_k_j, if j < i < k. 02525 // Note: `i > j'. 02526 for (dimension_type lk = 0; lk < num_no_sing_leaders; ++lk) { 02527 const dimension_type k = no_sing_leaders[lk]; 02528 if (k != i && k != j) { 02529 dimension_type ck = coherent_index(k); 02530 if (k < j) 02531 // Case 1. 02532 add_assign_r(tmp, m_i[k], matrix[cj][ck], ROUND_UP); 02533 else if (k < i) 02534 // Case 2. 02535 add_assign_r(tmp, m_i[k], matrix[k][j], ROUND_UP); 02536 else 02537 // Case 3. 02538 add_assign_r(tmp, matrix[ck][ci], matrix[k][j], ROUND_UP); 02539 02540 // Checks if the constraint is redundant. 02541 if (m_i_j >= tmp) { 02542 to_add = false; 02543 break; 02544 } 02545 } 02546 } 02547 02548 if (to_add) 02549 // The constraint is not redundant. 02550 nr_rows[i].set(j); 02551 } 02552 } 02553 02554 // If there exist a singular equivalence class, then it must have a 02555 // single 0-cycle connecting all the positive and negative equivalent 02556 // variables. 02557 // Note: the singular class is not connected with the other classes. 02558 if (exist_sing_class) { 02559 nr_rows[sing_leader].set(sing_leader+1); 02560 if (successor[sing_leader+1] != sing_leader+1) { 02561 dimension_type j = sing_leader; 02562 dimension_type next_jj = successor[j+1]; 02563 while (next_jj != j+1) { 02564 nr_rows[next_jj].set(j); 02565 j = next_jj; 02566 next_jj = successor[j+1]; 02567 } 02568 nr_rows[j+1].set(j); 02569 } 02570 else 02571 nr_rows[sing_leader+1].set(sing_leader); 02572 } 02573 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::OK | ( | ) | const [inline] |
Checks if all the invariants are satisfied.
Definition at line 7093 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::is_minus_infinity(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strong_coherent(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::OK(), Parma_Polyhedra_Library::OR_Matrix< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::status, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::time_elapse_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain(), Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign_if_exact().
07093 { 07094 // Check whether the matrix is well-formed. 07095 if (!matrix.OK()) 07096 return false; 07097 07098 // Check whether the status information is legal. 07099 if (!status.OK()) 07100 return false; 07101 07102 // All empty octagons are OK. 07103 if (marked_empty()) 07104 return true; 07105 07106 // 0-dim universe octagon is OK. 07107 if (space_dim == 0) 07108 return true; 07109 07110 // MINUS_INFINITY cannot occur at all. 07111 for (typename OR_Matrix<N>::const_row_iterator i = matrix.row_begin(), 07112 matrix_row_end = matrix.row_end(); i != matrix_row_end; ++i) { 07113 typename OR_Matrix<N>::const_row_reference_type x_i = *i; 07114 for (dimension_type j = i.row_size(); j-- > 0; ) 07115 if (is_minus_infinity(x_i[j])) { 07116 #ifndef NDEBUG 07117 using namespace Parma_Polyhedra_Library::IO_Operators; 07118 std::cerr << "Octagonal_Shape::" 07119 << "matrix[" << i.index() << "][" << j << "] = " 07120 << x_i[j] << "!" 07121 << std::endl; 07122 #endif 07123 return false; 07124 } 07125 } 07126 07127 // On the main diagonal only PLUS_INFINITY can occur. 07128 for (typename OR_Matrix<N>::const_row_iterator i = matrix.row_begin(), 07129 m_end = matrix.row_end(); i != m_end; ++i) { 07130 typename OR_Matrix<N>::const_row_reference_type r = *i; 07131 const N& m_i_i = r[i.index()]; 07132 if (!is_plus_infinity(m_i_i)) { 07133 #ifndef NDEBUG 07134 const dimension_type j = i.index(); 07135 using namespace Parma_Polyhedra_Library::IO_Operators; 07136 std::cerr << "Octagonal_Shape::matrix[" << j << "][" << j << "] = " 07137 << m_i_i << "! (+inf was expected.)\n"; 07138 #endif 07139 return false; 07140 } 07141 } 07142 07143 // The following tests might result in false alarms when using floating 07144 // point coefficients: they are only meaningful if the coefficient type 07145 // base is exact (since otherwise strong closure is approximated). 07146 if (std::numeric_limits<coefficient_type_base>::is_exact) { 07147 07148 // Check whether the closure information is legal. 07149 if (marked_strongly_closed()) { 07150 Octagonal_Shape x = *this; 07151 x.reset_strongly_closed(); 07152 x.strong_closure_assign(); 07153 if (x.matrix != matrix) { 07154 #ifndef NDEBUG 07155 std::cerr << "Octagonal_Shape is marked as strongly closed " 07156 << "but it is not!\n"; 07157 #endif 07158 return false; 07159 } 07160 } 07161 07162 // A closed octagon must be strong-coherent. 07163 if (marked_strongly_closed()) 07164 if (!is_strong_coherent()) { 07165 #ifndef NDEBUG 07166 std::cerr << "Octagonal_Shape is not strong-coherent!\n"; 07167 #endif 07168 return false; 07169 } 07170 } 07171 07172 // All checks passed. 07173 return true; 07174 }
| Octagonal_Shape< T > & Parma_Polyhedra_Library::Octagonal_Shape< T >::operator= | ( | const Octagonal_Shape< T > & | y | ) | [inline] |
The assignment operator. (*this and y can be dimension-incompatible.).
Definition at line 224 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::status.
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::print | ( | ) | const |
Prints *this to std::cerr using operator<<.
| 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
.
Note that the coefficient of var in expr is null.
Definition at line 3863 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_minus_v_pm_u_bounds(), Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_v_pm_u_bounds(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Linear_Expression::space_dimension().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage().
03866 { 03867 PPL_ASSERT(denominator != 0); 03868 const dimension_type expr_space_dim = expr.space_dimension(); 03869 PPL_ASSERT(space_dim >= expr_space_dim); 03870 const dimension_type var_id = var.id(); 03871 PPL_ASSERT(var_id <= space_dim); 03872 PPL_ASSERT(expr.coefficient(var) == 0); 03873 PPL_ASSERT(relsym != LESS_THAN && relsym != GREATER_THAN); 03874 03875 const Coefficient& b = expr.inhomogeneous_term(); 03876 // Number of non-zero coefficients in `expr': will be set to 03877 // 0, 1, or 2, the latter value meaning any value greater than 1. 03878 dimension_type t = 0; 03879 03880 // Variable index of the last non-zero coefficient in `expr', if any. 03881 dimension_type w_id = 0; 03882 03883 // Get information about the number of non-zero coefficients in `expr'. 03884 for (dimension_type i = expr_space_dim; i-- > 0; ) 03885 if (expr.coefficient(Variable(i)) != 0) { 03886 if (t++ == 1) 03887 break; 03888 else 03889 w_id = i; 03890 } 03891 03892 // Now we know the form of `expr': 03893 // - If t == 0, then expr == b, with `b' a constant; 03894 // - If t == 1, then expr == a*j + b, where `j != v'; 03895 // - If t == 2, the `expr' is of the general form. 03896 typedef typename OR_Matrix<N>::row_iterator Row_Iterator; 03897 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 03898 typedef typename OR_Matrix<N>::const_row_iterator Row_iterator; 03899 typedef typename OR_Matrix<N>::const_row_reference_type Row_reference; 03900 03901 const Row_Iterator m_begin = matrix.row_begin(); 03902 const dimension_type n_var = 2*var_id; 03903 PPL_DIRTY_TEMP_COEFFICIENT(minus_den); 03904 neg_assign(minus_den, denominator); 03905 03906 // Since we are only able to record octagonal differences, we can 03907 // precisely deal with the case of a single variable only if its 03908 // coefficient (taking into account the denominator) is 1. 03909 // If this is not the case, we fall back to the general case 03910 // so as to over-approximate the constraint. 03911 if (t == 1 && expr.coefficient(Variable(w_id)) != denominator 03912 && expr.coefficient(Variable(w_id)) != minus_den) 03913 t = 2; 03914 03915 if (t == 0) { 03916 // Case 1: expr == b. 03917 PPL_DIRTY_TEMP_COEFFICIENT(two_b); 03918 two_b = 2*b; 03919 switch (relsym) { 03920 case EQUAL: 03921 // Add the constraint `var == b/denominator'. 03922 add_octagonal_constraint(n_var+1, n_var, two_b, denominator); 03923 add_octagonal_constraint(n_var, n_var+1, two_b, minus_den); 03924 break; 03925 case LESS_OR_EQUAL: 03926 // Add the constraint `var <= b/denominator'. 03927 add_octagonal_constraint(n_var+1, n_var, two_b, denominator); 03928 break; 03929 case GREATER_OR_EQUAL: 03930 // Add the constraint `var >= b/denominator', 03931 // i.e., `-var <= -b/denominator', 03932 add_octagonal_constraint(n_var, n_var+1, two_b, minus_den); 03933 break; 03934 default: 03935 // We already dealt with the other cases. 03936 throw std::runtime_error("PPL internal error"); 03937 } 03938 } 03939 else if (t == 1) { 03940 // Value of the one and only non-zero coefficient in `expr'. 03941 const Coefficient& w_coeff = expr.coefficient(Variable(w_id)); 03942 const dimension_type n_w = 2*w_id; 03943 switch (relsym) { 03944 case EQUAL: 03945 if (w_coeff == denominator) 03946 // Add the new constraint `var - w = b/denominator'. 03947 if (var_id < w_id) { 03948 add_octagonal_constraint(n_w, n_var, b, denominator); 03949 add_octagonal_constraint(n_w+1, n_var+1, b, minus_den); 03950 } 03951 else { 03952 add_octagonal_constraint(n_var+1, n_w+1, b, denominator); 03953 add_octagonal_constraint(n_var, n_w, b, minus_den); 03954 } 03955 else 03956 // Add the new constraint `var + w = b/denominator'. 03957 if (var_id < w_id) { 03958 add_octagonal_constraint(n_w+1, n_var, b, denominator); 03959 add_octagonal_constraint(n_w, n_var+1, b, minus_den); 03960 } 03961 else { 03962 add_octagonal_constraint(n_var+1, n_w, b, denominator); 03963 add_octagonal_constraint(n_var, n_w+1, b, minus_den); 03964 } 03965 break; 03966 case LESS_OR_EQUAL: 03967 { 03968 PPL_DIRTY_TEMP(N, d); 03969 div_round_up(d, b, denominator); 03970 // Note that: `w_id != v', so that `expr' is of the form 03971 // w_coeff * w + b, with `w_id != v'. 03972 if (w_coeff == denominator) { 03973 // Add the new constraints `v - w <= b/denominator'. 03974 if (var_id < w_id) 03975 add_octagonal_constraint(n_w, n_var, d); 03976 else 03977 add_octagonal_constraint(n_var+1, n_w+1, d); 03978 } 03979 else if (w_coeff == minus_den) { 03980 // Add the new constraints `v + w <= b/denominator'. 03981 if (var_id < w_id) 03982 add_octagonal_constraint(n_w+1, n_var, d); 03983 else 03984 add_octagonal_constraint(n_var+1, n_w, d); 03985 } 03986 break; 03987 } 03988 03989 case GREATER_OR_EQUAL: 03990 { 03991 PPL_DIRTY_TEMP(N, d); 03992 div_round_up(d, b, minus_den); 03993 // Note that: `w_id != v', so that `expr' is of the form 03994 // w_coeff * w + b, with `w_id != v'. 03995 if (w_coeff == denominator) { 03996 // Add the new constraint `v - w >= b/denominator', 03997 // i.e., `-v + w <= -b/denominator'. 03998 if (var_id < w_id) 03999 add_octagonal_constraint(n_w+1, n_var+1, d); 04000 else 04001 add_octagonal_constraint(n_var, n_w, d); 04002 } 04003 else if (w_coeff == minus_den) { 04004 // Add the new constraints `v + w >= b/denominator', 04005 // i.e., `-v - w <= -b/denominator'. 04006 if (var_id < w_id) 04007 add_octagonal_constraint(n_w, n_var+1, d); 04008 else 04009 add_octagonal_constraint(n_var, n_w+1, d); 04010 } 04011 break; 04012 } 04013 04014 default: 04015 // We already dealt with the other cases. 04016 throw std::runtime_error("PPL internal error"); 04017 } 04018 } 04019 else { 04020 // Here t == 2, so that 04021 // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2. 04022 const bool is_sc = (denominator > 0); 04023 PPL_DIRTY_TEMP_COEFFICIENT(minus_b); 04024 neg_assign(minus_b, b); 04025 const Coefficient& sc_b = is_sc ? b : minus_b; 04026 const Coefficient& minus_sc_b = is_sc ? minus_b : b; 04027 const Coefficient& sc_den = is_sc ? denominator : minus_den; 04028 const Coefficient& minus_sc_den = is_sc ? minus_den : denominator; 04029 // NOTE: here, for optimization purposes, `minus_expr' is only assigned 04030 // when `denominator' is negative. Do not use it unless you are sure 04031 // it has been correctly assigned. 04032 Linear_Expression minus_expr; 04033 if (!is_sc) 04034 minus_expr = -expr; 04035 const Linear_Expression& sc_expr = is_sc ? expr : minus_expr; 04036 04037 PPL_DIRTY_TEMP(N, sum); 04038 // Index of variable that is unbounded in `this'. 04039 PPL_UNINITIALIZED(dimension_type, pinf_index); 04040 // Number of unbounded variables found. 04041 dimension_type pinf_count = 0; 04042 04043 switch (relsym) { 04044 case EQUAL: 04045 { 04046 PPL_DIRTY_TEMP(N, neg_sum); 04047 // Index of variable that is unbounded in `this'. 04048 PPL_UNINITIALIZED(dimension_type, neg_pinf_index); 04049 // Number of unbounded variables found. 04050 dimension_type neg_pinf_count = 0; 04051 04052 // Approximate the inhomogeneous term. 04053 assign_r(sum, sc_b, ROUND_UP); 04054 assign_r(neg_sum, minus_sc_b, ROUND_UP); 04055 04056 // Approximate the homogeneous part of `sc_expr'. 04057 PPL_DIRTY_TEMP(N, coeff_i); 04058 PPL_DIRTY_TEMP(N, half); 04059 PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i); 04060 PPL_DIRTY_TEMP(N, minus_coeff_i); 04061 // Note: indices above `w' can be disregarded, as they all have 04062 // a zero coefficient in `sc_expr'. 04063 for (Row_iterator m_iter = m_begin, m_iter_end = m_iter + (2*w_id) + 2; 04064 m_iter != m_iter_end; ) { 04065 const dimension_type n_i = m_iter.index(); 04066 const dimension_type id = n_i/2; 04067 Row_reference m_i = *m_iter; 04068 ++m_iter; 04069 Row_reference m_ci = *m_iter; 04070 ++m_iter; 04071 const Coefficient& sc_i = sc_expr.coefficient(Variable(id)); 04072 const int sign_i = sgn(sc_i); 04073 if (sign_i > 0) { 04074 assign_r(coeff_i, sc_i, ROUND_UP); 04075 // Approximating `sc_expr'. 04076 if (pinf_count <= 1) { 04077 const N& double_approx_i = m_ci[n_i]; 04078 if (!is_plus_infinity(double_approx_i)) { 04079 // Let half = double_approx_i / 2. 04080 div_2exp_assign_r(half, double_approx_i, 1, ROUND_UP); 04081 add_mul_assign_r(sum, coeff_i, half, ROUND_UP); 04082 } 04083 else { 04084 ++pinf_count; 04085 pinf_index = id; 04086 } 04087 } 04088 // Approximating `-sc_expr'. 04089 if (neg_pinf_count <= 1) { 04090 const N& double_approx_minus_i = m_i[n_i+1]; 04091 if (!is_plus_infinity(double_approx_minus_i)) { 04092 // Let half = double_approx_minus_i / 2. 04093 div_2exp_assign_r(half, double_approx_minus_i, 1, ROUND_UP); 04094 add_mul_assign_r(neg_sum, coeff_i, half, ROUND_UP); 04095 } 04096 else { 04097 ++neg_pinf_count; 04098 neg_pinf_index = id; 04099 } 04100 } 04101 } 04102 else if (sign_i < 0) { 04103 neg_assign_r(minus_sc_i, sc_i, ROUND_NOT_NEEDED); 04104 assign_r(minus_coeff_i, minus_sc_i, ROUND_UP); 04105 // Approximating `sc_expr'. 04106 if (pinf_count <= 1) { 04107 const N& double_approx_minus_i = m_i[n_i+1]; 04108 if (!is_plus_infinity(double_approx_minus_i)) { 04109 // Let half = double_approx_minus_i / 2. 04110 div_2exp_assign_r(half, double_approx_minus_i, 1, ROUND_UP); 04111 add_mul_assign_r(sum, minus_coeff_i, half, ROUND_UP); 04112 } 04113 else { 04114 ++pinf_count; 04115 pinf_index = id; 04116 } 04117 } 04118 // Approximating `-sc_expr'. 04119 if (neg_pinf_count <= 1) { 04120 const N& double_approx_i = m_ci[n_i]; 04121 if (!is_plus_infinity(double_approx_i)) { 04122 // Let half = double_approx_i / 2. 04123 div_2exp_assign_r(half, double_approx_i, 1, ROUND_UP); 04124 add_mul_assign_r(neg_sum, minus_coeff_i, half, ROUND_UP); 04125 } 04126 else { 04127 ++neg_pinf_count; 04128 neg_pinf_index = id; 04129 } 04130 } 04131 } 04132 } 04133 // Return immediately if no approximation could be computed. 04134 if (pinf_count > 1 && neg_pinf_count > 1) { 04135 PPL_ASSERT(OK()); 04136 return; 04137 } 04138 04139 // In the following, strong closure will be definitely lost. 04140 reset_strongly_closed(); 04141 04142 // Exploit the upper approximation, if possible. 04143 if (pinf_count <= 1) { 04144 // Compute quotient (if needed). 04145 if (sc_den != 1) { 04146 // Before computing quotients, the denominator should be 04147 // approximated towards zero. Since `sc_den' is known to be 04148 // positive, this amounts to rounding downwards, which is 04149 // achieved as usual by rounding upwards `minus_sc_den' 04150 // and negating again the result. 04151 PPL_DIRTY_TEMP(N, down_sc_den); 04152 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 04153 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 04154 div_assign_r(sum, sum, down_sc_den, ROUND_UP); 04155 } 04156 // Add the upper bound constraint, if meaningful. 04157 if (pinf_count == 0) { 04158 // Add the constraint `v <= sum'. 04159 PPL_DIRTY_TEMP(N, double_sum); 04160 mul_2exp_assign_r(double_sum, sum, 1, ROUND_UP); 04161 matrix[n_var+1][n_var] = double_sum; 04162 // Deduce constraints of the form `v +/- u', where `u != v'. 04163 deduce_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, sum); 04164 } 04165 else 04166 // Here `pinf_count == 1'. 04167 if (pinf_index != var_id) { 04168 const Coefficient& ppi = 04169 sc_expr.coefficient(Variable(pinf_index)); 04170 if (ppi == sc_den) 04171 // Add the constraint `v - pinf_index <= sum'. 04172 if (var_id < pinf_index) 04173 matrix[2*pinf_index][n_var] = sum; 04174 else 04175 matrix[n_var+1][2*pinf_index+1] = sum; 04176 else 04177 if (ppi == minus_sc_den) { 04178 // Add the constraint `v + pinf_index <= sum'. 04179 if (var_id < pinf_index) 04180 matrix[2*pinf_index+1][n_var] = sum; 04181 else 04182 matrix[n_var+1][2*pinf_index] = sum; 04183 } 04184 } 04185 } 04186 04187 // Exploit the lower approximation, if possible. 04188 if (neg_pinf_count <= 1) { 04189 // Compute quotient (if needed). 04190 if (sc_den != 1) { 04191 // Before computing quotients, the denominator should be 04192 // approximated towards zero. Since `sc_den' is known to be 04193 // positive, this amounts to rounding downwards, which is 04194 // achieved as usual by rounding upwards `minus_sc_den' 04195 // and negating again the result. 04196 PPL_DIRTY_TEMP(N, down_sc_den); 04197 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 04198 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 04199 div_assign_r(neg_sum, neg_sum, down_sc_den, ROUND_UP); 04200 } 04201 // Add the lower bound constraint, if meaningful. 04202 if (neg_pinf_count == 0) { 04203 // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'. 04204 PPL_DIRTY_TEMP(N, double_neg_sum); 04205 mul_2exp_assign_r(double_neg_sum, neg_sum, 1, ROUND_UP); 04206 matrix[n_var][n_var+1] = double_neg_sum; 04207 // Deduce constraints of the form `-v +/- u', where `u != v'. 04208 deduce_minus_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, neg_sum); 04209 } 04210 else 04211 // Here `neg_pinf_count == 1'. 04212 if (neg_pinf_index != var_id) { 04213 const Coefficient& npi = 04214 sc_expr.coefficient(Variable(neg_pinf_index)); 04215 if (npi == sc_den) 04216 // Add the constraint `v - neg_pinf_index >= -neg_sum', 04217 // i.e., `neg_pinf_index - v <= neg_sum'. 04218 if (neg_pinf_index < var_id) 04219 matrix[n_var][2*neg_pinf_index] = neg_sum; 04220 else 04221 matrix[2*neg_pinf_index+1][n_var+1] = neg_sum; 04222 else 04223 if (npi == minus_sc_den) { 04224 // Add the constraint `v + neg_pinf_index >= -neg_sum', 04225 // i.e., `-neg_pinf_index - v <= neg_sum'. 04226 if (neg_pinf_index < var_id) 04227 matrix[n_var][2*neg_pinf_index+1] = neg_sum; 04228 else 04229 matrix[2*neg_pinf_index][n_var+1] = neg_sum; 04230 } 04231 } 04232 } 04233 break; 04234 } 04235 04236 case LESS_OR_EQUAL: 04237 { 04238 // Compute an upper approximation for `expr' into `sum', 04239 // taking into account the sign of `denominator'. 04240 04241 // Approximate the inhomogeneous term. 04242 assign_r(sum, sc_b, ROUND_UP); 04243 04244 // Approximate the homogeneous part of `sc_expr'. 04245 PPL_DIRTY_TEMP(N, coeff_i); 04246 PPL_DIRTY_TEMP(N, approx_i); 04247 PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i); 04248 // Note: indices above `w_id' can be disregarded, as they all have 04249 // a zero coefficient in `expr'. 04250 for (Row_Iterator m_iter = m_begin, m_end = m_iter + (2*w_id) + 2; 04251 m_iter != m_end; ) { 04252 const dimension_type n_i = m_iter.index(); 04253 const dimension_type id = n_i/2; 04254 Row_Reference m_i = *m_iter; 04255 ++m_iter; 04256 Row_Reference m_ci = *m_iter; 04257 ++m_iter; 04258 const Coefficient& sc_i = sc_expr.coefficient(Variable(id)); 04259 const int sign_i = sgn(sc_i); 04260 if (sign_i == 0) 04261 continue; 04262 // Choose carefully: we are approximating `sc_expr'. 04263 const N& double_approx_i = (sign_i > 0) ? m_ci[n_i] : m_i[n_i+1]; 04264 if (is_plus_infinity(double_approx_i)) { 04265 if (++pinf_count > 1) 04266 break; 04267 pinf_index = id; 04268 continue; 04269 } 04270 if (sign_i > 0) 04271 assign_r(coeff_i, sc_i, ROUND_UP); 04272 else { 04273 neg_assign(minus_sc_i, sc_i); 04274 assign_r(coeff_i, minus_sc_i, ROUND_UP); 04275 } 04276 div_2exp_assign_r(approx_i, double_approx_i, 1, ROUND_UP); 04277 add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP); 04278 } 04279 // Divide by the (sign corrected) denominator (if needed). 04280 if (sc_den != 1) { 04281 // Before computing the quotient, the denominator should be 04282 // approximated towards zero. Since `sc_den' is known to be 04283 // positive, this amounts to rounding downwards, which is achieved 04284 // by rounding upwards `minus_sc-den' and negating again the result. 04285 PPL_DIRTY_TEMP(N, down_sc_den); 04286 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 04287 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 04288 div_assign_r(sum, sum, down_sc_den, ROUND_UP); 04289 } 04290 04291 if (pinf_count == 0) { 04292 // Add the constraint `v <= sum'. 04293 PPL_DIRTY_TEMP(N, double_sum); 04294 mul_2exp_assign_r(double_sum, sum, 1, ROUND_UP); 04295 add_octagonal_constraint(n_var+1, n_var, double_sum); 04296 // Deduce constraints of the form `v +/- u', where `u != v'. 04297 deduce_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, sum); 04298 } 04299 else if (pinf_count == 1) { 04300 dimension_type pinf_ind = 2*pinf_index; 04301 if (expr.coefficient(Variable(pinf_index)) == denominator ) { 04302 // Add the constraint `v - pinf_index <= sum'. 04303 if (var_id < pinf_index) 04304 add_octagonal_constraint(pinf_ind, n_var, sum); 04305 else 04306 add_octagonal_constraint(n_var+1, pinf_ind+1, sum); 04307 } 04308 else { 04309 if (expr.coefficient(Variable(pinf_index)) == minus_den) { 04310 // Add the constraint `v + pinf_index <= sum'. 04311 if (var_id < pinf_index) 04312 add_octagonal_constraint(pinf_ind+1, n_var, sum); 04313 else 04314 add_octagonal_constraint(n_var+1, pinf_ind, sum); 04315 } 04316 } 04317 } 04318 break; 04319 } 04320 04321 case GREATER_OR_EQUAL: 04322 { 04323 // Compute an upper approximation for `-sc_expr' into `sum'. 04324 // Note: approximating `-sc_expr' from above and then negating the 04325 // result is the same as approximating `sc_expr' from below. 04326 04327 // Approximate the inhomogeneous term. 04328 assign_r(sum, minus_sc_b, ROUND_UP); 04329 04330 // Approximate the homogeneous part of `-sc_expr'. 04331 PPL_DIRTY_TEMP(N, coeff_i); 04332 PPL_DIRTY_TEMP(N, approx_i); 04333 PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i); 04334 for (Row_Iterator m_iter = m_begin, m_end = m_iter + (2*w_id) + 2; 04335 m_iter != m_end; ) { 04336 const dimension_type n_i = m_iter.index(); 04337 const dimension_type id = n_i/2; 04338 Row_Reference m_i = *m_iter; 04339 ++m_iter; 04340 Row_Reference m_ci = *m_iter; 04341 ++m_iter; 04342 const Coefficient& sc_i = sc_expr.coefficient(Variable(id)); 04343 const int sign_i = sgn(sc_i); 04344 if (sign_i == 0) 04345 continue; 04346 // Choose carefully: we are approximating `-sc_expr'. 04347 const N& double_approx_i = (sign_i > 0) ? m_i[n_i+1] : m_ci[n_i]; 04348 if (is_plus_infinity(double_approx_i)) { 04349 if (++pinf_count > 1) 04350 break; 04351 pinf_index = id; 04352 continue; 04353 } 04354 if (sign_i > 0) 04355 assign_r(coeff_i, sc_i, ROUND_UP); 04356 else { 04357 neg_assign(minus_sc_i, sc_i); 04358 assign_r(coeff_i, minus_sc_i, ROUND_UP); 04359 } 04360 div_2exp_assign_r(approx_i, double_approx_i, 1, ROUND_UP); 04361 add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP); 04362 } 04363 04364 // Divide by the (sign corrected) denominator (if needed). 04365 if (sc_den != 1) { 04366 // Before computing the quotient, the denominator should be 04367 // approximated towards zero. Since `sc_den' is known to be positive, 04368 // this amounts to rounding downwards, which is achieved by rounding 04369 // upwards `minus_sc_den' and negating again the result. 04370 PPL_DIRTY_TEMP(N, down_sc_den); 04371 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 04372 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 04373 div_assign_r(sum, sum, down_sc_den, ROUND_UP); 04374 } 04375 04376 if (pinf_count == 0) { 04377 // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'. 04378 PPL_DIRTY_TEMP(N, double_sum); 04379 mul_2exp_assign_r(double_sum, sum, 1, ROUND_UP); 04380 add_octagonal_constraint(n_var, n_var+1, double_sum); 04381 // Deduce constraints of the form `-v +/- u', where `u != v'. 04382 deduce_minus_v_pm_u_bounds(var_id, pinf_index, sc_expr, sc_den, sum); 04383 } 04384 else if (pinf_count == 1) { 04385 dimension_type pinf_ind = 2*pinf_index; 04386 if (expr.coefficient(Variable(pinf_index)) == denominator) { 04387 // Add the constraint `v - pinf_index >= -sum', 04388 // i.e., `pinf_index - v <= sum'. 04389 if (pinf_index < var_id) 04390 add_octagonal_constraint(n_var, pinf_ind, sum); 04391 else 04392 add_octagonal_constraint(pinf_ind+1, n_var, sum); 04393 } 04394 else { 04395 if (expr.coefficient(Variable(pinf_index)) == minus_den) { 04396 // Add the constraint `v + pinf_index >= -sum', 04397 // i.e., `-pinf_index - v <= sum'. 04398 if (pinf_index < var_id) 04399 add_octagonal_constraint(n_var, pinf_ind+1, sum); 04400 else 04401 add_octagonal_constraint(pinf_ind, n_var+1, sum); 04402 } 04403 } 04404 } 04405 break; 04406 } 04407 04408 default: 04409 // We already dealt with the other cases. 04410 throw std::runtime_error("PPL internal error"); 04411 } 04412 } 04413 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_fp_interval_abstract_store | ( | Box< Interval< T, Interval_Info > > & | store | ) | const [inline] |
Refines store with the constraints defining *this.
| store | The interval floating point abstract store to refine. |
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check | ( | const Congruence & | cg | ) | [inline, private] |
Uses the congruence cg to refine *this.
| cg | The congruence to be added. Nontrivial proper congruences are ignored. Non-octagonal equalities are ignored. |
cg and *this are dimension-incompatible, the behavior is undefined. Definition at line 501 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Congruence::is_proper_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::Congruence::space_dimension().
00501 { 00502 PPL_ASSERT(!marked_empty()); 00503 PPL_ASSERT(cg.space_dimension() <= space_dimension()); 00504 00505 if (cg.is_proper_congruence()) { 00506 if (cg.is_inconsistent()) 00507 set_empty(); 00508 // Other proper congruences are just ignored. 00509 return; 00510 } 00511 00512 PPL_ASSERT(cg.is_equality()); 00513 Constraint c(cg); 00514 refine_no_check(c); 00515 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check | ( | const Constraint & | c | ) | [inline, private] |
Uses the constraint c to refine *this.
| c | The constraint to be added. Non-octagonal constraints are ignored. |
c and *this are dimension-incompatible, the behavior is undefined. Definition at line 481 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Octagonal_Shape< T >::extract_octagonal_difference(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Constraint::space_dimension().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraint(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraints().
00481 { 00482 PPL_ASSERT(!marked_empty()); 00483 const dimension_type c_space_dim = c.space_dimension(); 00484 PPL_ASSERT(c_space_dim <= space_dim); 00485 00486 dimension_type num_vars = 0; 00487 dimension_type i = 0; 00488 dimension_type j = 0; 00489 PPL_DIRTY_TEMP_COEFFICIENT(coeff); 00490 PPL_DIRTY_TEMP_COEFFICIENT(term); 00491 // Constraints that are not octagonal differences are ignored. 00492 if (!extract_octagonal_difference(c, c_space_dim, num_vars, 00493 i, j, coeff, term)) 00494 return; 00495 00496 if (num_vars == 0) { 00497 const Coefficient& c_inhomo = c.inhomogeneous_term(); 00498 // Dealing with a trivial constraint (maybe a strict inequality). 00499 if (c_inhomo < 0 00500 || (c_inhomo != 0 && c.is_equality()) 00501 || (c_inhomo == 0 && c.is_strict_inequality())) 00502 set_empty(); 00503 return; 00504 } 00505 00506 // Select the cell to be modified for the "<=" part of constraint. 00507 typename OR_Matrix<N>::row_iterator i_iter = matrix.row_begin() + i; 00508 typename OR_Matrix<N>::row_reference_type m_i = *i_iter; 00509 N& m_i_j = m_i[j]; 00510 // Set `coeff' to the absolute value of itself. 00511 if (coeff < 0) 00512 neg_assign(coeff); 00513 00514 bool is_oct_changed = false; 00515 // Compute the bound for `m_i_j', rounding towards plus infinity. 00516 PPL_DIRTY_TEMP(N, d); 00517 div_round_up(d, term, coeff); 00518 if (m_i_j > d) { 00519 m_i_j = d; 00520 is_oct_changed = true; 00521 } 00522 00523 if (c.is_equality()) { 00524 // Select the cell to be modified for the ">=" part of constraint. 00525 if (i % 2 == 0) 00526 ++i_iter; 00527 else 00528 --i_iter; 00529 00530 typename OR_Matrix<N>::row_reference_type m_ci = *i_iter; 00531 using namespace Implementation::Octagonal_Shapes; 00532 dimension_type cj = coherent_index(j); 00533 N& m_ci_cj = m_ci[cj]; 00534 // Also compute the bound for `m_ci_cj', rounding towards plus infinity. 00535 neg_assign(term); 00536 div_round_up(d, term, coeff); 00537 if (m_ci_cj > d) { 00538 m_ci_cj = d; 00539 is_oct_changed = true; 00540 } 00541 } 00542 00543 // This method does not preserve closure. 00544 if (is_oct_changed && marked_strongly_closed()) 00545 reset_strongly_closed(); 00546 PPL_ASSERT(OK()); 00547 }
| 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.
| cg | The congruence. If it is not a octagonal equality, it will be ignored. |
| std::invalid_argument | Thrown if *this and congruence cg are dimension-incompatible. |
Definition at line 476 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Congruence::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
00476 { 00477 const dimension_type cg_space_dim = cg.space_dimension(); 00478 // Dimension-compatibility check. 00479 if (cg_space_dim > space_dimension()) 00480 throw_dimension_incompatible("refine_with_congruence(cg)", cg); 00481 00482 if (!marked_empty()) 00483 refine_no_check(cg); 00484 }
| 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.
| cgs | The congruence system to be used. Congruences that are not octagonal equalities are ignored. |
| std::invalid_argument | Thrown if *this and cgs are dimension-incompatible. |
Definition at line 488 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Congruence_System::begin(), Parma_Polyhedra_Library::Congruence_System::end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Congruence_System::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape().
00488 { 00489 // Dimension-compatibility check. 00490 if (cgs.space_dimension() > space_dimension()) 00491 throw_generic("refine_with_congruences(cgs)", 00492 "cgs and *this are space-dimension incompatible"); 00493 00494 for (Congruence_System::const_iterator i = cgs.begin(), 00495 cgs_end = cgs.end(); !marked_empty() && i != cgs_end; ++i) 00496 refine_no_check(*i); 00497 }
| 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.
| c | The constraint. If it is not a octagonal constraint, it will be ignored. |
| std::invalid_argument | Thrown if *this and constraint c are dimension-incompatible. |
Definition at line 452 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
00452 { 00453 // Dimension-compatibility check. 00454 if (c.space_dimension() > space_dimension()) 00455 throw_dimension_incompatible("refine_with_constraint(c)", c); 00456 00457 if (!marked_empty()) 00458 refine_no_check(c); 00459 }
| 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.
| cs | The constraint system to be used. Constraints that are not octagonal are ignored. |
| std::invalid_argument | Thrown if *this and cs are dimension-incompatible. |
Definition at line 463 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape().
00463 { 00464 // Dimension-compatibility check. 00465 if (cs.space_dimension() > space_dimension()) 00466 throw_generic("refine_with_constraints(cs)", 00467 "cs and *this are space-dimension incompatible"); 00468 00469 for (Constraint_System::const_iterator i = cs.begin(), 00470 cs_end = cs.end(); !marked_empty() && i != cs_end; ++i) 00471 refine_no_check(*i); 00472 }
| 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.
| std::invalid_argument | Thrown if *this and generator g are dimension-incompatible. |
Definition at line 1678 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::add_mul_assign(), Parma_Polyhedra_Library::Generator::coefficient(), Parma_Polyhedra_Library::Coefficient_zero(), Parma_Polyhedra_Library::Generator::divisor(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::Generator::is_line(), Parma_Polyhedra_Library::Generator::is_line_or_ray(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Poly_Gen_Relation::nothing(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Generator::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Poly_Gen_Relation::subsumes(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
01678 { 01679 const dimension_type g_space_dim = g.space_dimension(); 01680 01681 // Dimension-compatibility check. 01682 if (space_dim < g_space_dim) 01683 throw_dimension_incompatible("relation_with(g)", g); 01684 01685 // The closure needs to make explicit the implicit constraints and if the 01686 // octagon is empty. 01687 strong_closure_assign(); 01688 01689 // The empty octagon cannot subsume a generator. 01690 if (marked_empty()) 01691 return Poly_Gen_Relation::nothing(); 01692 01693 // A universe octagon in a zero-dimensional space subsumes 01694 // all the generators of a zero-dimensional space. 01695 if (space_dim == 0) 01696 return Poly_Gen_Relation::subsumes(); 01697 01698 const bool is_line = g.is_line(); 01699 const bool is_line_or_ray = g.is_line_or_ray(); 01700 01701 // The relation between the octagon and the given generator is obtained 01702 // checking if the generator satisfies all the constraints in the octagon. 01703 // To check if the generator satisfies all the constraints it's enough 01704 // studying the sign of the scalar product between the generator and 01705 // all the constraints in the octagon. 01706 01707 typedef typename OR_Matrix<N>::const_row_iterator Row_Iterator; 01708 typedef typename OR_Matrix<N>::const_row_reference_type Row_Reference; 01709 01710 const Row_Iterator m_begin = matrix.row_begin(); 01711 const Row_Iterator m_end = matrix.row_end(); 01712 01713 PPL_DIRTY_TEMP_COEFFICIENT(num); 01714 PPL_DIRTY_TEMP_COEFFICIENT(den); 01715 PPL_DIRTY_TEMP_COEFFICIENT(product); 01716 01717 // We find in `*this' all the constraints. 01718 for (Row_Iterator i_iter = m_begin; i_iter != m_end; i_iter += 2) { 01719 dimension_type i = i_iter.index(); 01720 Row_Reference m_i = *i_iter; 01721 Row_Reference m_ii = *(i_iter+1); 01722 const N& m_i_ii = m_i[i+1]; 01723 const N& m_ii_i = m_ii[i]; 01724 // We have the unary constraints. 01725 const Variable x(i/2); 01726 const Coefficient& g_coeff_x 01727 = (x.space_dimension() > g_space_dim) 01728 ? Coefficient_zero() 01729 : g.coefficient(x); 01730 if (is_additive_inverse(m_i_ii, m_ii_i)) { 01731 // The constraint has form ax = b. 01732 // To satisfy the constraint it's necessary that the scalar product 01733 // is not zero. The scalar product has the form: 01734 // 'den * g_coeff_x - num * g.divisor()'. 01735 numer_denom(m_ii_i, num, den); 01736 den *= 2; 01737 product = den * g_coeff_x; 01738 // Note that if the generator `g' is a line or a ray, 01739 // its divisor is zero. 01740 if (!is_line_or_ray) { 01741 neg_assign(num); 01742 add_mul_assign(product, num, g.divisor()); 01743 } 01744 if (product != 0) 01745 return Poly_Gen_Relation::nothing(); 01746 } 01747 // We have 0, 1 or 2 inequality constraints. 01748 else { 01749 if (!is_plus_infinity(m_i_ii)) { 01750 // The constraint has form -ax <= b. 01751 // If the generator is a line it's necessary to check if 01752 // the scalar product is not zero, if it is positive otherwise. 01753 numer_denom(m_i_ii, num, den); 01754 den *= -2; 01755 product = den * g_coeff_x; 01756 // Note that if the generator `g' is a line or a ray, 01757 // its divisor is zero. 01758 if (!is_line_or_ray) { 01759 neg_assign(num); 01760 add_mul_assign(product, num, g.divisor()); 01761 } 01762 if (is_line && product != 0) 01763 return Poly_Gen_Relation::nothing(); 01764 else 01765 // If the generator is not a line it's necessary to check 01766 // that the scalar product sign is not positive and the scalar 01767 // product has the form: 01768 // '-den * g.coeff_x - num * g.divisor()'. 01769 if (product > 0) 01770 return Poly_Gen_Relation::nothing(); 01771 } 01772 if (!is_plus_infinity(m_ii_i)) { 01773 // The constraint has form ax <= b. 01774 numer_denom(m_ii_i, num, den); 01775 den *= 2; 01776 product = den * g_coeff_x; 01777 // Note that if the generator `g' is a line or a ray, 01778 // its divisor is zero. 01779 if (!is_line_or_ray) { 01780 neg_assign(num); 01781 add_mul_assign(product, num , g.divisor()); 01782 } 01783 if (is_line && product != 0) 01784 return Poly_Gen_Relation::nothing(); 01785 else 01786 // If the generator is not a line it's necessary to check 01787 // that the scalar product sign is not positive and the scalar 01788 // product has the form: 01789 // 'den * g_coeff_x - num * g.divisor()'. 01790 if (product > 0) 01791 return Poly_Gen_Relation::nothing(); 01792 } 01793 } 01794 } 01795 01796 // We have the binary constraints. 01797 for (Row_Iterator i_iter = m_begin ; i_iter != m_end; i_iter += 2) { 01798 dimension_type i = i_iter.index(); 01799 Row_Reference m_i = *i_iter; 01800 Row_Reference m_ii = *(i_iter+1); 01801 for (dimension_type j = 0; j < i; j += 2) { 01802 const N& m_i_j = m_i[j]; 01803 const N& m_ii_jj = m_ii[j+1]; 01804 const N& m_ii_j = m_ii[j]; 01805 const N& m_i_jj = m_i[j+1]; 01806 const Variable x(j/2); 01807 const Variable y(i/2); 01808 const Coefficient& g_coeff_x 01809 = (x.space_dimension() > g_space_dim) 01810 ? Coefficient_zero() 01811 : g.coefficient(x); 01812 const Coefficient& g_coeff_y 01813 = (y.space_dimension() > g_space_dim) 01814 ? Coefficient_zero() 01815 : g.coefficient(y); 01816 01817 const bool difference_is_equality = is_additive_inverse(m_ii_jj, m_i_j); 01818 if (difference_is_equality) { 01819 // The constraint has form ax - ay = b. 01820 // The scalar product has the form 01821 // 'den * coeff_x - den * coeff_y - num * g.divisor()'. 01822 // To satisfy the constraint it's necessary that the scalar product 01823 // is not zero. 01824 numer_denom(m_i_j, num, den); 01825 product = den * g_coeff_x; 01826 neg_assign(den); 01827 add_mul_assign(product, den, g_coeff_y); 01828 // Note that if the generator `g' is a line or a ray, 01829 // its divisor is zero. 01830 if (!is_line_or_ray) { 01831 neg_assign(num); 01832 add_mul_assign(product, num, g.divisor()); 01833 } 01834 if (product != 0) 01835 return Poly_Gen_Relation::nothing(); 01836 } 01837 else { 01838 if (!is_plus_infinity(m_i_j)) { 01839 // The constraint has form ax - ay <= b. 01840 // The scalar product has the form 01841 // 'den * coeff_x - den * coeff_y - num * g.divisor()'. 01842 // If the generator is not a line it's necessary to check 01843 // that the scalar product sign is not positive. 01844 numer_denom(m_i_j, num, den); 01845 product = den * g_coeff_x; 01846 neg_assign(den); 01847 add_mul_assign(product, den, g_coeff_y); 01848 // Note that if the generator `g' is a line or a ray, 01849 // its divisor is zero. 01850 if (!is_line_or_ray) { 01851 neg_assign(num); 01852 add_mul_assign(product, num, g.divisor()); 01853 } 01854 if (is_line && product != 0) 01855 return Poly_Gen_Relation::nothing(); 01856 else if (product > 0) 01857 return Poly_Gen_Relation::nothing(); 01858 } 01859 if (!is_plus_infinity(m_ii_jj)) { 01860 // The constraint has form -ax + ay <= b. 01861 // The scalar product has the form 01862 // '-den * coeff_x + den * coeff_y - num * g.divisor()'. 01863 // If the generator is not a line it's necessary to check 01864 // that the scalar product sign is not positive. 01865 numer_denom(m_ii_jj, num, den); 01866 product = den * g_coeff_y; 01867 neg_assign(den); 01868 add_mul_assign(product, den, g_coeff_x); 01869 // Note that if the generator `g' is a line or a ray, 01870 // its divisor is zero. 01871 if (!is_line_or_ray) { 01872 neg_assign(num); 01873 add_mul_assign(product, num, g.divisor()); 01874 } 01875 if (is_line && product != 0) 01876 return Poly_Gen_Relation::nothing(); 01877 else if (product > 0) 01878 return Poly_Gen_Relation::nothing(); 01879 } 01880 } 01881 01882 const bool sum_is_equality = is_additive_inverse(m_i_jj, m_ii_j); 01883 if (sum_is_equality) { 01884 // The constraint has form ax + ay = b. 01885 // The scalar product has the form 01886 // 'den * coeff_x + den * coeff_y - num * g.divisor()'. 01887 // To satisfy the constraint it's necessary that the scalar product 01888 // is not zero. 01889 numer_denom(m_ii_j, num, den); 01890 product = den * g_coeff_x; 01891 add_mul_assign(product, den, g_coeff_y); 01892 // Note that if the generator `g' is a line or a ray, 01893 // its divisor is zero. 01894 if (!is_line_or_ray) { 01895 neg_assign(num); 01896 add_mul_assign(product, num, g.divisor()); 01897 } 01898 if (product != 0) 01899 return Poly_Gen_Relation::nothing(); 01900 } 01901 else { 01902 if (!is_plus_infinity(m_i_jj)) { 01903 // The constraint has form -ax - ay <= b. 01904 // The scalar product has the form 01905 // '-den * coeff_x - den * coeff_y - num * g.divisor()'. 01906 // If the generator is not a line it's necessary to check 01907 // that the scalar product sign is not positive. 01908 numer_denom(m_i_jj, num, den); 01909 neg_assign(den); 01910 product = den * g_coeff_x; 01911 add_mul_assign(product, den, g_coeff_y); 01912 // Note that if the generator `g' is a line or a ray, 01913 // its divisor is zero. 01914 if (!is_line_or_ray) { 01915 neg_assign(num); 01916 add_mul_assign(product, num, g.divisor()); 01917 } 01918 if (is_line && product != 0) 01919 return Poly_Gen_Relation::nothing(); 01920 else if (product > 0) 01921 return Poly_Gen_Relation::nothing(); 01922 } 01923 if (!is_plus_infinity(m_ii_j)) { 01924 // The constraint has form ax + ay <= b. 01925 // The scalar product has the form 01926 // 'den * coeff_x + den * coeff_y - num * g.divisor()'. 01927 // If the generator is not a line it's necessary to check 01928 // that the scalar product sign is not positive. 01929 numer_denom(m_ii_j, num, den); 01930 product = den * g_coeff_x; 01931 add_mul_assign(product, den, g_coeff_y); 01932 // Note that if the generator `g' is a line or a ray, 01933 // its divisor is zero. 01934 if (!is_line_or_ray) { 01935 neg_assign(num); 01936 add_mul_assign(product, num, g.divisor()); 01937 } 01938 if (is_line && product != 0) 01939 return Poly_Gen_Relation::nothing(); 01940 else if (product > 0) 01941 return Poly_Gen_Relation::nothing(); 01942 } 01943 } 01944 } 01945 } 01946 // If this point is reached the constraint 'g' satisfies 01947 // all the constraints in the octagon. 01948 return Poly_Gen_Relation::subsumes(); 01949 }
| 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.
| std::invalid_argument | Thrown if *this and cg are dimension-incompatible. |
Definition at line 1339 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Checked::le, Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::maximize(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimize(), Parma_Polyhedra_Library::Congruence::modulus(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Congruence::space_dimension(), Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
01339 { 01340 dimension_type cg_space_dim = cg.space_dimension(); 01341 01342 // Dimension-compatibility check. 01343 if (cg_space_dim > space_dim) 01344 throw_dimension_incompatible("relation_with(cg)", cg); 01345 01346 // If the congruence is an equality, 01347 // find the relation with the equivalent equality constraint. 01348 if (cg.is_equality()) { 01349 Constraint c(cg); 01350 return relation_with(c); 01351 } 01352 01353 strong_closure_assign(); 01354 01355 if (marked_empty()) 01356 return Poly_Con_Relation::saturates() 01357 && Poly_Con_Relation::is_included() 01358 && Poly_Con_Relation::is_disjoint(); 01359 01360 if (space_dim == 0) { 01361 if (cg.is_inconsistent()) 01362 return Poly_Con_Relation::is_disjoint(); 01363 else 01364 return Poly_Con_Relation::saturates() 01365 && Poly_Con_Relation::is_included(); 01366 } 01367 01368 // Find the lower bound for a hyperplane with direction 01369 // defined by the congruence. 01370 Linear_Expression le = Linear_Expression(cg); 01371 PPL_DIRTY_TEMP_COEFFICIENT(min_num); 01372 PPL_DIRTY_TEMP_COEFFICIENT(min_den); 01373 bool min_included; 01374 bool bounded_below = minimize(le, min_num, min_den, min_included); 01375 01376 // If there is no lower bound, then some of the hyperplanes defined by 01377 // the congruence will strictly intersect the shape. 01378 if (!bounded_below) 01379 return Poly_Con_Relation::strictly_intersects(); 01380 01381 // TODO: Consider adding a max_and_min() method, performing both 01382 // maximization and minimization so as to possibly exploit 01383 // incrementality of the MIP solver. 01384 01385 // Find the upper bound for a hyperplane with direction 01386 // defined by the congruence. 01387 PPL_DIRTY_TEMP_COEFFICIENT(max_num); 01388 PPL_DIRTY_TEMP_COEFFICIENT(max_den); 01389 bool max_included; 01390 bool bounded_above = maximize(le, max_num, max_den, max_included); 01391 01392 // If there is no upper bound, then some of the hyperplanes defined by 01393 // the congruence will strictly intersect the shape. 01394 if (!bounded_above) 01395 return Poly_Con_Relation::strictly_intersects(); 01396 01397 PPL_DIRTY_TEMP_COEFFICIENT(signed_distance); 01398 01399 // Find the position value for the hyperplane that satisfies the congruence 01400 // and is above the lower bound for the shape. 01401 PPL_DIRTY_TEMP_COEFFICIENT(min_value); 01402 min_value = min_num / min_den; 01403 const Coefficient& modulus = cg.modulus(); 01404 signed_distance = min_value % modulus; 01405 min_value -= signed_distance; 01406 if (min_value * min_den < min_num) 01407 min_value += modulus; 01408 01409 // Find the position value for the hyperplane that satisfies the congruence 01410 // and is below the upper bound for the shape. 01411 PPL_DIRTY_TEMP_COEFFICIENT(max_value); 01412 max_value = max_num / max_den; 01413 signed_distance = max_value % modulus; 01414 max_value += signed_distance; 01415 if (max_value * max_den > max_num) 01416 max_value -= modulus; 01417 01418 // If the upper bound value is less than the lower bound value, 01419 // then there is an empty intersection with the congruence; 01420 // otherwise it will strictly intersect. 01421 if (max_value < min_value) 01422 return Poly_Con_Relation::is_disjoint(); 01423 else 01424 return Poly_Con_Relation::strictly_intersects(); 01425 }
| 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.
| std::invalid_argument | Thrown if *this and constraint c are dimension-incompatible. |
Definition at line 1429 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Octagonal_Shape< T >::extract_octagonal_difference(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Constraint::is_inequality(), Parma_Polyhedra_Library::Constraint::is_nonstrict_inequality(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Checked::le, Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::maximize(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimize(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with().
01429 { 01430 dimension_type c_space_dim = c.space_dimension(); 01431 01432 // Dimension-compatibility check. 01433 if (c_space_dim > space_dim) 01434 throw_dimension_incompatible("relation_with(c)", c); 01435 01436 // The closure needs to make explicit the implicit constraints. 01437 strong_closure_assign(); 01438 01439 if (marked_empty()) 01440 return Poly_Con_Relation::saturates() 01441 && Poly_Con_Relation::is_included() 01442 && Poly_Con_Relation::is_disjoint(); 01443 01444 if (space_dim == 0) { 01445 // Trivially false zero-dimensional constraint. 01446 if ((c.is_equality() && c.inhomogeneous_term() != 0) 01447 || (c.is_inequality() && c.inhomogeneous_term() < 0)) 01448 return Poly_Con_Relation::is_disjoint(); 01449 else if (c.is_strict_inequality() && c.inhomogeneous_term() == 0) 01450 // The constraint 0 > 0 implicitly defines the hyperplane 0 = 0; 01451 // thus, the zero-dimensional point also saturates it. 01452 return Poly_Con_Relation::saturates() 01453 && Poly_Con_Relation::is_disjoint(); 01454 01455 // Trivially true zero-dimensional constraint. 01456 else if (c.is_equality() || c.inhomogeneous_term() == 0) 01457 return Poly_Con_Relation::saturates() 01458 && Poly_Con_Relation::is_included(); 01459 else 01460 // The zero-dimensional point saturates 01461 // neither the positivity constraint 1 >= 0, 01462 // nor the strict positivity constraint 1 > 0. 01463 return Poly_Con_Relation::is_included(); 01464 } 01465 01466 dimension_type num_vars = 0; 01467 dimension_type i = 0; 01468 dimension_type j = 0; 01469 PPL_DIRTY_TEMP_COEFFICIENT(coeff); 01470 PPL_DIRTY_TEMP_COEFFICIENT(c_term); 01471 if (!extract_octagonal_difference(c, c_space_dim, num_vars, 01472 i, j, coeff, c_term)) { 01473 // Constraints that are not octagonal differences. 01474 // Use maximize() and minimize() to do much of the work. 01475 01476 // Find the linear expression for the constraint and use that to 01477 // find if the expression is bounded from above or below and if it 01478 // is, find the maximum and minimum values. 01479 Linear_Expression le; 01480 for (dimension_type k = c_space_dim; k-- > 0; ) { 01481 Variable vk(k); 01482 le += c.coefficient(vk) * vk; 01483 } 01484 PPL_DIRTY_TEMP(Coefficient, max_num); 01485 PPL_DIRTY_TEMP(Coefficient, max_den); 01486 bool max_included; 01487 PPL_DIRTY_TEMP(Coefficient, min_num); 01488 PPL_DIRTY_TEMP(Coefficient, min_den); 01489 bool min_included; 01490 bool bounded_above = maximize(le, max_num, max_den, max_included); 01491 bool bounded_below = minimize(le, min_num, min_den, min_included); 01492 if (!bounded_above) { 01493 if (!bounded_below) 01494 return Poly_Con_Relation::strictly_intersects(); 01495 min_num += c.inhomogeneous_term() * min_den; 01496 switch (sgn(min_num)) { 01497 case 1: 01498 if (c.is_equality()) 01499 return Poly_Con_Relation::is_disjoint(); 01500 return Poly_Con_Relation::is_included(); 01501 case 0: 01502 if (c.is_strict_inequality() || c.is_equality()) 01503 return Poly_Con_Relation::strictly_intersects(); 01504 return Poly_Con_Relation::is_included(); 01505 case -1: 01506 return Poly_Con_Relation::strictly_intersects(); 01507 } 01508 } 01509 if (!bounded_below) { 01510 max_num += c.inhomogeneous_term() * max_den; 01511 switch (sgn(max_num)) { 01512 case 1: 01513 return Poly_Con_Relation::strictly_intersects(); 01514 case 0: 01515 if (c.is_strict_inequality()) 01516 return Poly_Con_Relation::is_disjoint(); 01517 return Poly_Con_Relation::strictly_intersects(); 01518 case -1: 01519 return Poly_Con_Relation::is_disjoint(); 01520 } 01521 } 01522 else { 01523 max_num += c.inhomogeneous_term() * max_den; 01524 min_num += c.inhomogeneous_term() * min_den; 01525 switch (sgn(max_num)) { 01526 case 1: 01527 switch (sgn(min_num)) { 01528 case 1: 01529 if (c.is_equality()) 01530 return Poly_Con_Relation::is_disjoint(); 01531 return Poly_Con_Relation::is_included(); 01532 case 0: 01533 if (c.is_equality()) 01534 return Poly_Con_Relation::strictly_intersects(); 01535 if (c.is_strict_inequality()) 01536 return Poly_Con_Relation::strictly_intersects(); 01537 return Poly_Con_Relation::is_included(); 01538 case -1: 01539 return Poly_Con_Relation::strictly_intersects(); 01540 } 01541 case 0: 01542 if (min_num == 0) { 01543 if (c.is_strict_inequality()) 01544 return Poly_Con_Relation::is_disjoint() 01545 && Poly_Con_Relation::saturates(); 01546 return Poly_Con_Relation::is_included() 01547 && Poly_Con_Relation::saturates(); 01548 } 01549 if (c.is_strict_inequality()) 01550 return Poly_Con_Relation::is_disjoint(); 01551 return Poly_Con_Relation::strictly_intersects(); 01552 case -1: 01553 return Poly_Con_Relation::is_disjoint(); 01554 } 01555 } 01556 } 01557 01558 if (num_vars == 0) { 01559 // Dealing with a trivial constraint. 01560 switch (sgn(c.inhomogeneous_term())) { 01561 case -1: 01562 return Poly_Con_Relation::is_disjoint(); 01563 case 0: 01564 if (c.is_strict_inequality()) 01565 return Poly_Con_Relation::saturates() 01566 && Poly_Con_Relation::is_disjoint(); 01567 else 01568 return Poly_Con_Relation::saturates() 01569 && Poly_Con_Relation::is_included(); 01570 case 1: 01571 if (c.is_equality()) 01572 return Poly_Con_Relation::is_disjoint(); 01573 else 01574 return Poly_Con_Relation::is_included(); 01575 } 01576 } 01577 01578 // Select the cell to be checked for the "<=" part of constraint. 01579 typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin() + i; 01580 typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter; 01581 const N& m_i_j = m_i[j]; 01582 // Set `coeff' to the absolute value of itself. 01583 if (coeff < 0) 01584 neg_assign(coeff); 01585 01586 // Select the cell to be checked for the ">=" part of constraint. 01587 // Select the right row of the cell. 01588 if (i % 2 == 0) 01589 ++i_iter; 01590 else 01591 --i_iter; 01592 typename OR_Matrix<N>::const_row_reference_type m_ci = *i_iter; 01593 using namespace Implementation::Octagonal_Shapes; 01594 const N& m_ci_cj = m_ci[coherent_index(j)]; 01595 PPL_DIRTY_TEMP_COEFFICIENT(numer); 01596 PPL_DIRTY_TEMP_COEFFICIENT(denom); 01597 // The following variables of mpq_class type are used to be precise 01598 // when the octagon is defined by integer constraints. 01599 PPL_DIRTY_TEMP0(mpq_class, q_x); 01600 PPL_DIRTY_TEMP0(mpq_class, q_y); 01601 PPL_DIRTY_TEMP0(mpq_class, d); 01602 PPL_DIRTY_TEMP0(mpq_class, d1); 01603 PPL_DIRTY_TEMP0(mpq_class, c_den); 01604 PPL_DIRTY_TEMP0(mpq_class, q_den); 01605 assign_r(c_den, coeff, ROUND_NOT_NEEDED); 01606 assign_r(d, c_term, ROUND_NOT_NEEDED); 01607 neg_assign_r(d1, d, ROUND_NOT_NEEDED); 01608 div_assign_r(d, d, c_den, ROUND_NOT_NEEDED); 01609 div_assign_r(d1, d1, c_den, ROUND_NOT_NEEDED); 01610 01611 if (is_plus_infinity(m_i_j)) { 01612 if (!is_plus_infinity(m_ci_cj)) { 01613 // `*this' is in the following form: 01614 // `-m_ci_cj <= v - u'. 01615 // In this case `*this' is disjoint from `c' if 01616 // `-m_ci_cj > d' (`-m_ci_cj >= d' if c is a strict inequality), 01617 // i.e. if `m_ci_cj < d1' (`m_ci_cj <= d1' if c is a strict inequality). 01618 numer_denom(m_ci_cj, numer, denom); 01619 assign_r(q_den, denom, ROUND_NOT_NEEDED); 01620 assign_r(q_y, numer, ROUND_NOT_NEEDED); 01621 div_assign_r(q_y, q_y, q_den, ROUND_NOT_NEEDED); 01622 if (q_y < d1) 01623 return Poly_Con_Relation::is_disjoint(); 01624 if (q_y == d1 && c.is_strict_inequality()) 01625 return Poly_Con_Relation::is_disjoint(); 01626 } 01627 01628 // In all other cases `*this' intersects `c'. 01629 return Poly_Con_Relation::strictly_intersects(); 01630 } 01631 01632 // Here `m_i_j' is not plus-infinity. 01633 numer_denom(m_i_j, numer, denom); 01634 assign_r(q_den, denom, ROUND_NOT_NEEDED); 01635 assign_r(q_x, numer, ROUND_NOT_NEEDED); 01636 div_assign_r(q_x, q_x, q_den, ROUND_NOT_NEEDED); 01637 01638 if (!is_plus_infinity(m_ci_cj)) { 01639 numer_denom(m_ci_cj, numer, denom); 01640 assign_r(q_den, denom, ROUND_NOT_NEEDED); 01641 assign_r(q_y, numer, ROUND_NOT_NEEDED); 01642 div_assign_r(q_y, q_y, q_den, ROUND_NOT_NEEDED); 01643 if (q_x == d && q_y == d1) { 01644 if (c.is_strict_inequality()) 01645 return Poly_Con_Relation::saturates() 01646 && Poly_Con_Relation::is_disjoint(); 01647 else 01648 return Poly_Con_Relation::saturates() 01649 && Poly_Con_Relation::is_included(); 01650 } 01651 // `*this' is disjoint from `c' when 01652 // `m_ci_cj < d1' (`m_ci_cj <= d1' if `c' is a strict inequality). 01653 if (q_y < d1) 01654 return Poly_Con_Relation::is_disjoint(); 01655 if (q_y == d1 && c.is_strict_inequality()) 01656 return Poly_Con_Relation::is_disjoint(); 01657 } 01658 01659 // Here `m_ci_cj' can be also plus-infinity. 01660 // If `c' is an equality, `*this' is disjoint from `c' if 01661 // `m_i_j < d'. 01662 if (d > q_x) { 01663 if (c.is_equality()) 01664 return Poly_Con_Relation::is_disjoint(); 01665 else 01666 return Poly_Con_Relation::is_included(); 01667 } 01668 01669 if (d == q_x && c.is_nonstrict_inequality()) 01670 return Poly_Con_Relation::is_included(); 01671 01672 // In all other cases `*this' intersects `c'. 01673 return Poly_Con_Relation::strictly_intersects(); 01674 }
| 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.
| std::invalid_argument | Thrown if new_dimension is greater than the space dimension of *this. |
Definition at line 532 of file Octagonal_Shape.inlines.hh.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::map_space_dimensions().
00532 { 00533 // Dimension-compatibility check. 00534 if (new_dimension > space_dim) 00535 throw_dimension_incompatible("remove_higher_space_dimension(nd)", 00536 new_dimension); 00537 // The removal of no dimensions from any octagon is a no-op. 00538 // Note that this case also captures the only legal removal of 00539 // dimensions from an octagon in a 0-dim space. 00540 if (new_dimension == space_dim) { 00541 PPL_ASSERT(OK()); 00542 return; 00543 } 00544 00545 strong_closure_assign(); 00546 matrix.shrink(new_dimension); 00547 // When we remove all dimensions from a non-empty octagon, 00548 // we obtain the zero-dimensional universe octagon. 00549 if (new_dimension == 0 && !marked_empty()) 00550 set_zero_dim_univ(); 00551 space_dim = new_dimension; 00552 PPL_ASSERT(OK()); 00553 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions | ( | const Variables_Set & | vars | ) | [inline] |
Removes all the specified dimensions.
| vars | The set of Variable objects corresponding to the dimensions to be removed. |
| std::invalid_argument | Thrown if *this is dimension-incompatible with one of the Variable objects contained in vars. |
Definition at line 2968 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_zero_dim_univ(), Parma_Polyhedra_Library::OR_Matrix< T >::shrink(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions().
02968 { 02969 // The removal of no dimensions from any octagon is a no-op. 02970 // Note that this case also captures the only legal removal of 02971 // dimensions from a octagon in a 0-dim space. 02972 if (vars.empty()) { 02973 PPL_ASSERT(OK()); 02974 return; 02975 } 02976 02977 // Dimension-compatibility check. 02978 const dimension_type min_space_dim = vars.space_dimension(); 02979 if (space_dim < min_space_dim) 02980 throw_dimension_incompatible("remove_space_dimensions(vs)", min_space_dim); 02981 02982 const dimension_type new_space_dim = space_dim - vars.size(); 02983 02984 strong_closure_assign(); 02985 // When removing _all_ dimensions from an octagon, 02986 // we obtain the zero-dimensional octagon. 02987 if (new_space_dim == 0) { 02988 matrix.shrink(0); 02989 if (!marked_empty()) 02990 // We set the zero_dim_univ flag. 02991 set_zero_dim_univ(); 02992 space_dim = 0; 02993 PPL_ASSERT(OK()); 02994 return; 02995 } 02996 02997 // We consider every variable and we check if it is to be removed. 02998 // If it is to be removed, we pass to the successive one, elsewhere 02999 // we move its elements in the right position. 03000 Variables_Set::const_iterator vsi = vars.begin(); 03001 dimension_type ftr = *vsi; 03002 dimension_type ftr_size = 2*ftr*(ftr+1); 03003 typename OR_Matrix<N>::element_iterator 03004 iter = matrix.element_begin()+ftr_size; 03005 03006 dimension_type i = ftr + 1; 03007 while (i < space_dim) { 03008 if (vars.count(i) != 0) 03009 ++i; 03010 else { 03011 typename OR_Matrix<N>::row_iterator 03012 row_iter = matrix.row_begin()+2*i; 03013 typename OR_Matrix<N>::row_reference_type 03014 row_ref = *row_iter; 03015 typename OR_Matrix<N>::row_reference_type 03016 row_ref1 = *(++row_iter); 03017 // If variable(j) is to remove, we pass another variable, 03018 // else we shift its cells to up right. 03019 // Attention: first we shift the cells corrispondent to the first 03020 // row of variable(j), then we shift the cells corrispondent to the 03021 // second row. We recall that every variable is represented 03022 // in the `matrix' by two rows and two rows. 03023 for (dimension_type j = 0; j <= i; ++j) 03024 if (vars.count(j) == 0) { 03025 assign_or_swap(*(iter++), row_ref[2*j]); 03026 assign_or_swap(*(iter++), row_ref[2*j+1]); 03027 } 03028 for (dimension_type j = 0; j <= i; ++j) 03029 if (vars.count(j) == 0) { 03030 assign_or_swap(*(iter++), row_ref1[2*j]); 03031 assign_or_swap(*(iter++), row_ref1[2*j+1]); 03032 } 03033 ++i; 03034 } 03035 } 03036 // Update the space dimension. 03037 matrix.shrink(new_space_dim); 03038 space_dim = new_space_dim; 03039 PPL_ASSERT(OK()); 03040 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed | ( | ) | [inline, private] |
Marks *this as possibly not strongly closed.
Definition at line 102 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::reset_strongly_closed(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::status.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points_helper(), Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::get_limiting_octagon(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign().
00102 { 00103 status.reset_strongly_closed(); 00104 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty | ( | ) | [inline, private] |
Turns *this into an empty OS.
Definition at line 90 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::set_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::status.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), 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_closure_assign().
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed | ( | ) | [inline, private] |
Marks *this as strongly closed.
Definition at line 96 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::set_strongly_closed(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::status.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().
00096 { 00097 status.set_strongly_closed(); 00098 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::set_zero_dim_univ | ( | ) | [inline, private] |
Turns *this into a zero-dimensional universe OS.
Definition at line 84 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::set_zero_dim_univ(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::status.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign().
00084 { 00085 status.set_zero_dim_univ(); 00086 }
| 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.
| std::invalid_argument | Thrown if *this and y are topology-incompatible or dimension-incompatible. |
Definition at line 2669 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix_at(), Parma_Polyhedra_Library::Octagonal_Shape< T >::non_redundant_matrix_entries(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_zero_dim_univ(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::swap(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::UNIVERSE.
02669 { 02670 Octagonal_Shape& x = *this; 02671 const dimension_type dim = x.space_dimension(); 02672 // Dimension-compatibility check. 02673 if (dim != y.space_dimension()) 02674 throw_dimension_incompatible("simplify_using_context_assign(y)", y); 02675 02676 // Filter away the zero-dimensional case. 02677 if (dim == 0) { 02678 if (y.marked_empty()) { 02679 x.set_zero_dim_univ(); 02680 return false; 02681 } 02682 else 02683 return !x.marked_empty(); 02684 } 02685 02686 // Filter away the case where `x' contains `y' 02687 // (this subsumes the case when `y' is empty). 02688 if (x.contains(y)) { 02689 Octagonal_Shape<T> res(dim, UNIVERSE); 02690 x.swap(res); 02691 return false; 02692 } 02693 02694 typedef typename OR_Matrix<N>::row_iterator Row_Iter; 02695 typedef typename OR_Matrix<N>::const_row_iterator Row_CIter; 02696 typedef typename OR_Matrix<N>::element_iterator Elem_Iter; 02697 typedef typename OR_Matrix<N>::const_element_iterator Elem_CIter; 02698 02699 // Filter away the case where `x' is empty. 02700 x.strong_closure_assign(); 02701 if (x.marked_empty()) { 02702 // Search for a constraint of `y' that is not a tautology. 02703 dimension_type i; 02704 dimension_type j; 02705 // Prefer unary constraints. 02706 for (i = 0; i < 2*dim; i += 2) { 02707 // FIXME: if N is a float or bounded integer type, then 02708 // we also need to check that we are actually able to construct 02709 // a constraint inconsistent wrt this one. 02710 // Use something like !is_maximal()? 02711 if (!is_plus_infinity(y.matrix_at(i, i+1))) { 02712 j = i+1; 02713 goto found; 02714 } 02715 // Use something like !is_maximal()? 02716 if (!is_plus_infinity(y.matrix_at(i+1, i))) { 02717 j = i; 02718 ++i; 02719 goto found; 02720 } 02721 } 02722 // Then search binary constraints. 02723 // TODO: use better iteration scheme. 02724 for (i = 2; i < 2*dim; ++i) 02725 for (j = 0; j < i; ++j) { 02726 // Use something like !is_maximal()? 02727 if (!is_plus_infinity(y.matrix_at(i, j))) 02728 goto found; 02729 } 02730 02731 // Not found: we were not able to build a constraint contradicting 02732 // one of the constraints in `y': `x' cannot be enlarged. 02733 return false; 02734 02735 found: 02736 // Found: build a new OS contradicting the constraint found. 02737 PPL_ASSERT(i < dim && j < dim && i != j); 02738 Octagonal_Shape<T> res(dim, UNIVERSE); 02739 // FIXME: compute a proper contradicting constraint. 02740 PPL_DIRTY_TEMP(N, tmp); 02741 assign_r(tmp, 1, ROUND_UP); 02742 add_assign_r(tmp, tmp, y.matrix_at(i, j), ROUND_UP); 02743 // CHECKME: round down is really meant. 02744 neg_assign_r(res.matrix_at(j, i), tmp, ROUND_DOWN); 02745 PPL_ASSERT(!is_plus_infinity(res.matrix_at(j, i))); 02746 x.swap(res); 02747 return false; 02748 } 02749 02750 // Here `x' and `y' are not empty and strongly closed; 02751 // also, `x' does not contain `y'. 02752 // Let `target' be the intersection of `x' and `y'. 02753 Octagonal_Shape<T> target = x; 02754 target.intersection_assign(y); 02755 const bool bool_result = !target.is_empty(); 02756 02757 // Compute redundancy information for x and ... 02758 // TODO: provide a nicer data structure for redundancy. 02759 std::vector<Bit_Row> x_nonred; 02760 x.non_redundant_matrix_entries(x_nonred); 02761 // ... count the non-redundant constraints. 02762 dimension_type x_num_nonred = 0; 02763 for (size_t i = x_nonred.size(); i-- > 0 ; ) 02764 x_num_nonred += x_nonred[i].count_ones(); 02765 PPL_ASSERT(x_num_nonred > 0); 02766 02767 // Let `yy' be a copy of `y': we will keep adding to `yy' 02768 // the non-redundant constraints of `x', 02769 // stopping as soon as `yy' becomes equal to `target'. 02770 Octagonal_Shape<T> yy = y; 02771 02772 // The constraints added to `yy' will be recorded in `res' ... 02773 Octagonal_Shape<T> res(dim, UNIVERSE); 02774 // ... and we will count them too. 02775 dimension_type res_num_nonred = 0; 02776 02777 // Compute leader information for `x'. 02778 std::vector<dimension_type> x_leaders; 02779 x.compute_leaders(x_leaders); 02780 02781 // First go through the unary equality constraints. 02782 // Find the leader of the singular equivalence class (it is even!). 02783 dimension_type sing_leader; 02784 for (sing_leader = 0; sing_leader < 2*dim; sing_leader += 2) { 02785 if (sing_leader == x_leaders[sing_leader]) { 02786 const N& x_s_ss = x.matrix_at(sing_leader, sing_leader+1); 02787 const N& x_ss_s = x.matrix_at(sing_leader+1, sing_leader); 02788 if (is_additive_inverse(x_s_ss, x_ss_s)) 02789 // Singular leader found. 02790 break; 02791 } 02792 } 02793 02794 // Unary equalities have `sing_leader' as a leader. 02795 for (dimension_type i = sing_leader; i < 2*dim; i += 2) { 02796 if (x_leaders[i] != sing_leader) 02797 continue; 02798 // Found a unary equality constraint: 02799 // see if any of the two inequalities have to be added. 02800 const N& x_i_ii = x.matrix_at(i, i+1); 02801 N& yy_i_ii = yy.matrix_at(i, i+1); 02802 if (x_i_ii < yy_i_ii) { 02803 // The \leq inequality is not implied by context. 02804 res.matrix_at(i, i+1) = x_i_ii; 02805 ++res_num_nonred; 02806 // Tighten context `yy' using the newly added constraint. 02807 yy_i_ii = x_i_ii; 02808 yy.reset_strongly_closed(); 02809 } 02810 const N& x_ii_i = x.matrix_at(i+1, i); 02811 N& yy_ii_i = yy.matrix_at(i+1, i); 02812 if (x_ii_i < yy_ii_i) { 02813 // The \geq inequality is not implied by context. 02814 res.matrix_at(i+1, i) = x_ii_i; 02815 ++res_num_nonred; 02816 // Tighten context `yy' using the newly added constraint. 02817 yy_ii_i = x_ii_i; 02818 yy.reset_strongly_closed(); 02819 } 02820 // Restore strong closure, if it was lost. 02821 if (!yy.marked_strongly_closed()) { 02822 Variable var_i(i/2); 02823 yy.incremental_strong_closure_assign(var_i); 02824 if (target.contains(yy)) { 02825 // Target reached: swap `x' and `res' if needed. 02826 if (res_num_nonred < x_num_nonred) { 02827 res.reset_strongly_closed(); 02828 x.swap(res); 02829 } 02830 return bool_result; 02831 } 02832 } 02833 } 02834 02835 // Go through the binary equality constraints. 02836 for (dimension_type i = 0; i < 2*dim; ++i) { 02837 const dimension_type j = x_leaders[i]; 02838 if (j == i || j == sing_leader) 02839 continue; 02840 const N& x_i_j = x.matrix_at(i, j); 02841 PPL_ASSERT(!is_plus_infinity(x_i_j)); 02842 N& yy_i_j = yy.matrix_at(i, j); 02843 if (x_i_j < yy_i_j) { 02844 res.matrix_at(i, j) = x_i_j; 02845 ++res_num_nonred; 02846 // Tighten context `yy' using the newly added constraint. 02847 yy_i_j = x_i_j; 02848 yy.reset_strongly_closed(); 02849 } 02850 const N& x_j_i = x.matrix_at(j, i); 02851 N& yy_j_i = yy.matrix_at(j, i); 02852 PPL_ASSERT(!is_plus_infinity(x_j_i)); 02853 if (x_j_i < yy_j_i) { 02854 res.matrix_at(j, i) = x_j_i; 02855 ++res_num_nonred; 02856 // Tighten context `yy' using the newly added constraint. 02857 yy_j_i = x_j_i; 02858 yy.reset_strongly_closed(); 02859 } 02860 // Restore strong closure, if it was lost. 02861 if (!yy.marked_strongly_closed()) { 02862 Variable var_j(j/2); 02863 yy.incremental_strong_closure_assign(var_j); 02864 if (target.contains(yy)) { 02865 // Target reached: swap `x' and `res' if needed. 02866 if (res_num_nonred < x_num_nonred) { 02867 res.reset_strongly_closed(); 02868 x.swap(res); 02869 } 02870 return bool_result; 02871 } 02872 } 02873 } 02874 02875 // Finally go through the (proper) inequality constraints: 02876 // both indices i and j should be leaders. 02877 // FIXME: improve iteration scheme (are we doing twice the work?) 02878 for (dimension_type i = 0; i < 2*dim; ++i) { 02879 if (i != x_leaders[i]) 02880 continue; 02881 const Bit_Row& x_nonred_i = x_nonred[i]; 02882 for (dimension_type j = 0; j < 2*dim; ++j) { 02883 if (j != x_leaders[j]) 02884 continue; 02885 if (i >= j) { 02886 if (!x_nonred_i[j]) 02887 continue; 02888 } 02889 else if (!x_nonred[j][i]) 02890 continue; 02891 N& yy_i_j = yy.matrix_at(i, j); 02892 const N& x_i_j = x.matrix_at(i, j); 02893 if (x_i_j < yy_i_j) { 02894 res.matrix_at(i, j) = x_i_j; 02895 ++res_num_nonred; 02896 // Tighten context `yy' using the newly added constraint. 02897 yy_i_j = x_i_j; 02898 yy.reset_strongly_closed(); 02899 Variable var(i/2); 02900 yy.incremental_strong_closure_assign(var); 02901 if (target.contains(yy)) { 02902 // Target reached: swap `x' and `res' if needed. 02903 if (res_num_nonred < x_num_nonred) { 02904 res.reset_strongly_closed(); 02905 x.swap(res); 02906 } 02907 return bool_result; 02908 } 02909 } 02910 } 02911 } 02912 // This point should be unreachable. 02913 throw std::runtime_error("PPL internal error"); 02914 }
| dimension_type Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension | ( | ) | const [inline] |
Returns the dimension of the vector space enclosing *this.
Definition at line 246 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruence(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constrains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Octagonal_Shape< T >::frequency(), Parma_Polyhedra_Library::Octagonal_Shape< T >::hash_code(), Parma_Polyhedra_Library::Octagonal_Shape< T >::integer_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::time_elapse_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign_if_exact().
00246 { 00247 return space_dim; 00248 }
| 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.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 611 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::contains().
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign | ( | ) | const [inline, private] |
Assigns to this->matrix its strong closure.
Strong closure is a necessary condition for the precision and/or the correctness of many methods. It explicitly records into matrix those constraints that are implicitly obtainable by the other ones, therefore obtaining a canonical representation for the OS.
Definition at line 1953 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::min_assign(), Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_coherence_assign().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Octagonal_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::frequency(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_bounded(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign().
01953 { 01954 // Do something only if necessary (zero-dim implies strong closure). 01955 if (marked_empty() || marked_strongly_closed() || space_dim == 0) 01956 return; 01957 01958 // Even though the octagon will not change, its internal representation 01959 // is going to be modified by the closure algorithm. 01960 Octagonal_Shape& x = const_cast<Octagonal_Shape<T>&>(*this); 01961 01962 typedef typename OR_Matrix<N>::row_iterator Row_Iterator; 01963 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 01964 01965 const dimension_type n_rows = x.matrix.num_rows(); 01966 const Row_Iterator m_begin = x.matrix.row_begin(); 01967 const Row_Iterator m_end = x.matrix.row_end(); 01968 01969 // Fill the main diagonal with zeros. 01970 for (Row_Iterator i = m_begin; i != m_end; ++i) { 01971 PPL_ASSERT(is_plus_infinity((*i)[i.index()])); 01972 assign_r((*i)[i.index()], 0, ROUND_NOT_NEEDED); 01973 } 01974 01975 // This algorithm is given by two steps: the first one is a simple 01976 // adaptation of the `shortest-path closure' using the Floyd-Warshall 01977 // algorithm; the second one is the `strong-coherence' algorithm. 01978 // It is important to note that after the strong-coherence, 01979 // the octagon is still shortest-path closed and hence, strongly closed. 01980 01981 // Recall that, given an index `h', we indicate with `ch' the coherent 01982 // index, i.e., the index such that: 01983 // ch = h + 1, if h is an even number; 01984 // ch = h - 1, if h is an odd number. 01985 01986 typename OR_Matrix<N>::element_iterator iter_ij; 01987 std::vector<N> vec_k(n_rows); 01988 std::vector<N> vec_ck(n_rows); 01989 PPL_DIRTY_TEMP(N, sum1); 01990 PPL_DIRTY_TEMP(N, sum2); 01991 Row_Reference x_k; 01992 Row_Reference x_ck; 01993 Row_Reference x_i; 01994 Row_Reference x_ci; 01995 01996 // Since the index `j' of the inner loop will go from 0 up to `i', 01997 // the three nested loops have to be executed twice. 01998 for (int twice = 0; twice < 2; ++twice) { 01999 02000 Row_Iterator x_k_iter = m_begin; 02001 Row_Iterator x_i_iter = m_begin; 02002 for (dimension_type k = 0; k < n_rows; k += 2) { 02003 const dimension_type ck = k+1; 02004 // Re-initialize the element iterator. 02005 iter_ij = x.matrix.element_begin(); 02006 // Compute the row references `x_k' and `x_ck'. 02007 x_k = *x_k_iter; 02008 ++x_k_iter; 02009 x_ck = *x_k_iter; 02010 ++x_k_iter; 02011 02012 for (dimension_type i = 0; i <= k; i += 2) { 02013 const dimension_type ci = i+1; 02014 // Storing x_k_i == x_ci_ck. 02015 vec_k[i] = x_k[i]; 02016 // Storing x_k_ci == x_i_ck. 02017 vec_k[ci] = x_k[ci]; 02018 // Storing x_ck_i == x_ci_k. 02019 vec_ck[i] = x_ck[i]; 02020 // Storing x_ck_ci == x_i_k. 02021 vec_ck[ci] = x_ck[ci]; 02022 } 02023 x_i_iter = x_k_iter; 02024 for (dimension_type i = k+2; i < n_rows; i += 2) { 02025 const dimension_type ci = i+1; 02026 x_i = *x_i_iter; 02027 ++x_i_iter; 02028 x_ci = *x_i_iter; 02029 ++x_i_iter; 02030 // Storing x_k_i == x_ci_ck. 02031 vec_k[i] = x_ci[ck]; 02032 // Storing x_k_ci == x_i_ck. 02033 vec_k[ci] = x_i[ck]; 02034 // Storing x_ck_i == x_ci_k. 02035 vec_ck[i] = x_ci[k]; 02036 // Storing x_ck_ci == x_i_k. 02037 vec_ck[ci] = x_i[k]; 02038 } 02039 02040 for (dimension_type i = 0; i < n_rows; ++i) { 02041 using namespace Implementation::Octagonal_Shapes; 02042 const dimension_type ci = coherent_index(i); 02043 const N& vec_k_ci = vec_k[ci]; 02044 const N& vec_ck_ci = vec_ck[ci]; 02045 // Unfolding two iterations on `j': this ensures that 02046 // the loop exit condition `j <= i' is OK. 02047 for (dimension_type j = 0; j <= i; ) { 02048 // First iteration: 02049 // sum1 = x_i_k + x_k_j == x_ck_ci + x_k_j; 02050 // sum2 = x_i_ck + x_ck_j == x_k_ci + x_ck_j. 02051 add_assign_r(sum1, vec_ck_ci, vec_k[j], ROUND_UP); 02052 add_assign_r(sum2, vec_k_ci, vec_ck[j], ROUND_UP); 02053 min_assign(sum1, sum2); 02054 min_assign(*iter_ij, sum1); 02055 // Exiting the first iteration: loop index control. 02056 ++j; 02057 ++iter_ij; 02058 // Second iteration: ditto. 02059 add_assign_r(sum1, vec_ck_ci, vec_k[j], ROUND_UP); 02060 add_assign_r(sum2, vec_k_ci, vec_ck[j], ROUND_UP); 02061 min_assign(sum1, sum2); 02062 min_assign(*iter_ij, sum1); 02063 // Exiting the second iteration: loop index control. 02064 ++j; 02065 ++iter_ij; 02066 } 02067 } 02068 } 02069 } 02070 02071 // Check for emptiness: the octagon is empty if and only if there is a 02072 // negative value in the main diagonal. 02073 for (Row_Iterator i = m_begin; i != m_end; ++i) { 02074 N& x_i_i = (*i)[i.index()]; 02075 if (sgn(x_i_i) < 0) { 02076 x.set_empty(); 02077 return; 02078 } 02079 else { 02080 PPL_ASSERT(sgn(x_i_i) == 0); 02081 // Restore PLUS_INFINITY on the main diagonal. 02082 assign_r(x_i_i, PLUS_INFINITY, ROUND_NOT_NEEDED); 02083 } 02084 } 02085 02086 // Step 2: we enforce the strong coherence. 02087 x.strong_coherence_assign(); 02088 // The octagon is not empty and it is now strongly closed. 02089 x.set_strongly_closed(); 02090 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_coherence_assign | ( | ) | [inline, private] |
Applies the strong-coherence step to this->matrix.
Definition at line 2094 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::min_assign(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), and Parma_Polyhedra_Library::OR_Matrix< T >::row_end().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_closure_assign().
02094 { 02095 // The strong-coherence is: for every indexes i and j 02096 // m_i_j <= (m_i_ci + m_cj_j)/2 02097 // where ci = i + 1, if i is even number or 02098 // ci = i - 1, if i is odd. 02099 // Ditto for cj. 02100 PPL_DIRTY_TEMP(N, semi_sum); 02101 for (typename OR_Matrix<N>::row_iterator i_iter = matrix.row_begin(), 02102 i_end = matrix.row_end(); i_iter != i_end; ++i_iter) { 02103 typename OR_Matrix<N>::row_reference_type x_i = *i_iter; 02104 const dimension_type i = i_iter.index(); 02105 using namespace Implementation::Octagonal_Shapes; 02106 const N& x_i_ci = x_i[coherent_index(i)]; 02107 // Avoid to do unnecessary sums. 02108 if (!is_plus_infinity(x_i_ci)) 02109 for (dimension_type j = 0, rs_i = i_iter.row_size(); j < rs_i; ++j) 02110 if (i != j) { 02111 const N& x_cj_j = matrix[coherent_index(j)][j]; 02112 if (!is_plus_infinity(x_cj_j)) { 02113 add_assign_r(semi_sum, x_i_ci, x_cj_j, ROUND_UP); 02114 div_2exp_assign_r(semi_sum, semi_sum, 1, ROUND_UP); 02115 min_assign(x_i[j], semi_sum); 02116 } 02117 } 02118 } 02119 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign | ( | ) | const [inline, private] |
Removes the redundant constraints from this->matrix.
Definition at line 2409 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strongly_reduced(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::non_redundant_matrix_entries(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_constraints().
02409 { 02410 // Zero-dimensional octagonal shapes are necessarily reduced. 02411 if (space_dim == 0) 02412 return; 02413 strong_closure_assign(); 02414 // If `*this' is empty, then there is nothing to reduce. 02415 if (marked_empty()) 02416 return; 02417 02418 // Detect non-redundant constraints. 02419 std::vector<Bit_Row> non_red; 02420 non_redundant_matrix_entries(non_red); 02421 02422 // Throw away redundant constraints. 02423 Octagonal_Shape<T>& x = const_cast<Octagonal_Shape<T>&>(*this); 02424 #ifndef NDEBUG 02425 const Octagonal_Shape x_copy_before(x); 02426 #endif 02427 typename OR_Matrix<N>::element_iterator x_i = x.matrix.element_begin(); 02428 for (dimension_type i = 0; i < 2 * space_dim; ++i) { 02429 const Bit_Row& non_red_i = non_red[i]; 02430 for (dimension_type j = 0, 02431 j_end = OR_Matrix<N>::row_size(i); j < j_end; ++j, ++x_i) { 02432 if (!non_red_i[j]) 02433 assign_r(*x_i, PLUS_INFINITY, ROUND_NOT_NEEDED); 02434 } 02435 } 02436 x.reset_strongly_closed(); 02437 #ifndef NDEBUG 02438 const Octagonal_Shape x_copy_after(x); 02439 PPL_ASSERT(x_copy_before == x_copy_after); 02440 PPL_ASSERT(x.is_strongly_reduced()); 02441 PPL_ASSERT(x.OK()); 02442 #endif 02443 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::swap | ( | Octagonal_Shape< T > & | y | ) | [inline] |
Swaps *this with octagon y. (*this and y can be dimension-incompatible.).
Definition at line 238 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.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::swap(), Parma_Polyhedra_Library::Octagonal_Shape< T >::time_elapse_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign_if_exact().
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_constraint_incompatible | ( | const char * | method | ) | const [inline, private] |
Definition at line 7236 of file Octagonal_Shape.templates.hh.
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | name_row, | |||
| const Linear_Expression & | y | |||
| ) | const [inline, private] |
Definition at line 7258 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Linear_Expression::space_dimension().
07260 { 07261 std::ostringstream s; 07262 s << "PPL::Octagonal_Shape::" << method << ":\n" 07263 << "this->space_dimension() == " << space_dimension() 07264 << ", " << name_row << "->space_dimension() == " 07265 << y.space_dimension() << "."; 07266 throw std::invalid_argument(s.str()); 07267 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible | ( | const char * | method, | |
| const Generator & | g | |||
| ) | const [inline, private] |
Definition at line 7225 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Generator::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension().
07226 { 07227 std::ostringstream s; 07228 s << "PPL::Octagonal_Shape::" << method << ":\n" 07229 << "this->space_dimension() == " << space_dimension() 07230 << ", g->space_dimension == " << g.space_dimension() << "."; 07231 throw std::invalid_argument(s.str()); 07232 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible | ( | const char * | method, | |
| const Congruence & | cg | |||
| ) | const [inline, private] |
Definition at line 7214 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Congruence::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension().
07215 { 07216 std::ostringstream s; 07217 s << "PPL::Octagonal_Shape::" << method << ":\n" 07218 << "this->space_dimension() == " << space_dimension() 07219 << ", cg->space_dimension == " << cg.space_dimension() << "."; 07220 throw std::invalid_argument(s.str()); 07221 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible | ( | const char * | method, | |
| const Constraint & | c | |||
| ) | const [inline, private] |
Definition at line 7203 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Constraint::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension().
07204 { 07205 std::ostringstream s; 07206 s << "PPL::Octagonal_Shape::" << method << ":\n" 07207 << "this->space_dimension() == " << space_dimension() 07208 << ", c->space_dimension == " << c.space_dimension() << "."; 07209 throw std::invalid_argument(s.str()); 07210 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible | ( | const char * | method, | |
| dimension_type | required_dim | |||
| ) | const [inline, private] |
Definition at line 7192 of file Octagonal_Shape.templates.hh.
07193 { 07194 std::ostringstream s; 07195 s << "PPL::Octagonal_Shape::" << method << ":\n" 07196 << "this->space_dimension() == " << space_dimension() 07197 << ", required dimension == " << required_dim << "."; 07198 throw std::invalid_argument(s.str()); 07199 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible | ( | const char * | method, | |
| const Octagonal_Shape< T > & | x | |||
| ) | const [inline, private] |
Definition at line 7180 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constrains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::frequency(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::time_elapse_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain(), Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign_if_exact().
07181 { 07182 std::ostringstream s; 07183 s << "PPL::Octagonal_Shape::" << method << ":\n" 07184 << "this->space_dimension() == " << space_dimension() 07185 << ", y->space_dimension() == " << y.space_dimension() << "."; 07186 throw std::invalid_argument(s.str()); 07187 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_expression_too_complex | ( | const char * | method, | |
| const Linear_Expression & | e | |||
| ) | const [inline, private] |
Definition at line 7246 of file Octagonal_Shape.templates.hh.
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic | ( | const char * | method, | |
| const char * | reason | |||
| ) | const [inline, private] |
Definition at line 7271 of file Octagonal_Shape.templates.hh.
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 >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), 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 >::Octagonal_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruences(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraints().
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_closure_assign | ( | ) | [inline, private] |
Assigns to this->matrix its tight closure.
const method, as it may modify the rational-valued geometric shape by cutting away non-integral points. The method is only available if the template parameter T is bound to an integer datatype. Definition at line 2142 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::is_even(), Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), PPL_COMPILE_TIME_CHECK, Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_coherence_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::integer_upper_bound_assign_if_exact().
02142 { 02143 PPL_COMPILE_TIME_CHECK(std::numeric_limits<T>::is_integer, 02144 "Octagonal_Shape<T>::tight_closure_assign():" 02145 " T in not an integer datatype."); 02146 // FIXME: this is just an executable specification. 02147 // (The following call could be replaced by shortest-path closure.) 02148 strong_closure_assign(); 02149 if (marked_empty()) 02150 return; 02151 if (tight_coherence_would_make_empty()) 02152 set_empty(); 02153 else { 02154 // Tighten the unary constraints. 02155 PPL_DIRTY_TEMP(N, temp_one); 02156 assign_r(temp_one, 1, ROUND_NOT_NEEDED); 02157 const dimension_type space_dim = space_dimension(); 02158 for (dimension_type i = 0; i < 2*space_dim; i += 2) { 02159 const dimension_type ci = i+1; 02160 N& mat_i_ci = matrix[i][ci]; 02161 if (!is_plus_infinity(mat_i_ci) && !is_even(mat_i_ci)) 02162 sub_assign_r(mat_i_ci, mat_i_ci, temp_one, ROUND_UP); 02163 N& mat_ci_i = matrix[ci][i]; 02164 if (!is_plus_infinity(mat_ci_i) && !is_even(mat_ci_i)) 02165 sub_assign_r(mat_ci_i, mat_ci_i, temp_one, ROUND_UP); 02166 } 02167 // Propagate tightened unary constraints. 02168 strong_coherence_assign(); 02169 } 02170 PPL_ASSERT(OK()); 02171 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty | ( | ) | const [inline, private] |
Definition at line 2123 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(), Parma_Polyhedra_Library::Octagonal_Shape< T >::integer_upper_bound_assign_if_exact(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_closure_assign().
02123 { 02124 PPL_ASSERT(std::numeric_limits<N>::is_integer); 02125 PPL_ASSERT(marked_strongly_closed()); 02126 const dimension_type space_dim = space_dimension(); 02127 for (dimension_type i = 0; i < 2*space_dim; i += 2) { 02128 const dimension_type ci = i+1; 02129 const N& mat_i_ci = matrix[i][ci]; 02130 if (!is_plus_infinity(mat_i_ci) 02131 // Check for oddness of `mat_i_ci'. 02132 && !is_even(mat_i_ci) 02133 // Check for zero-equivalence of `i' and `ci'. 02134 && is_additive_inverse(mat_i_ci, matrix[ci][i])) 02135 return true; 02136 } 02137 return false; 02138 }
| 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.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 596 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::swap(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Polyhedron::time_elapse_assign().
00596 { 00597 // Dimension-compatibility check. 00598 if (space_dimension() != y.space_dimension()) 00599 throw_dimension_incompatible("time_elapse_assign(y)", y); 00600 // See the polyhedra documentation. 00601 C_Polyhedron px(constraints()); 00602 C_Polyhedron py(y.constraints()); 00603 px.time_elapse_assign(py); 00604 Octagonal_Shape<T> x(px); 00605 swap(x); 00606 PPL_ASSERT(OK()); 00607 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::topological_closure_assign | ( | ) | [inline] |
Assigns to *this its topological closure.
Definition at line 317 of file Octagonal_Shape.inlines.hh.
| memory_size_type Parma_Polyhedra_Library::Octagonal_Shape< T >::total_memory_in_bytes | ( | ) | const [inline] |
Returns the total size in bytes of the memory occupied by *this.
Definition at line 813 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::external_memory_in_bytes().
00813 { 00814 return sizeof(*this) + external_memory_in_bytes(); 00815 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain | ( | const Variables_Set & | vars | ) | [inline] |
Computes the cylindrification of *this with respect to the set of space dimensions vars, assigning the result to *this.
| vars | The set of space dimension that will be unconstrained. |
| std::invalid_argument | Thrown if *this is dimension-incompatible with one of the Variable objects contained in vars. |
Definition at line 3836 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
03836 { 03837 // The cylindrification wrt no dimensions is a no-op. 03838 // This case captures the only legal cylindrification in a 0-dim space. 03839 if (vars.empty()) 03840 return; 03841 03842 // Dimension-compatibility check. 03843 const dimension_type min_space_dim = vars.space_dimension(); 03844 if (space_dimension() < min_space_dim) 03845 throw_dimension_incompatible("unconstrain(vs)", min_space_dim); 03846 03847 // Enforce strong closure for precision. 03848 strong_closure_assign(); 03849 03850 // If the shape is empty, this is a no-op. 03851 if (marked_empty()) 03852 return; 03853 03854 for (Variables_Set::const_iterator vsi = vars.begin(), 03855 vsi_end = vars.end(); vsi != vsi_end; ++vsi) 03856 forget_all_octagonal_constraints(*vsi); 03857 // Strong closure is preserved. 03858 PPL_ASSERT(OK()); 03859 }
| 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.
| var | The space dimension that will be unconstrained. |
| std::invalid_argument | Thrown if var is not a space dimension of *this. |
Definition at line 3816 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
03816 { 03817 // Dimension-compatibility check. 03818 const dimension_type var_id = var.id(); 03819 if (space_dimension() < var_id + 1) 03820 throw_dimension_incompatible("unconstrain(var)", var_id + 1); 03821 03822 // Enforce strong closure for precision. 03823 strong_closure_assign(); 03824 03825 // If the shape is empty, this is a no-op. 03826 if (marked_empty()) 03827 return; 03828 03829 forget_all_octagonal_constraints(var_id); 03830 // Strong closure is preserved. 03831 PPL_ASSERT(OK()); 03832 }
| 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.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 2577 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::OR_Matrix< T >::element_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::element_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::max_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::integer_upper_bound_assign_if_exact(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign_if_exact().
02577 { 02578 // Dimension-compatibility check. 02579 if (space_dim != y.space_dim) 02580 throw_dimension_incompatible("upper_bound_assign(y)", y); 02581 02582 // The hull of an octagon `x' with an empty octagon is `x'. 02583 y.strong_closure_assign(); 02584 if (y.marked_empty()) 02585 return; 02586 strong_closure_assign(); 02587 if (marked_empty()) { 02588 *this = y; 02589 return; 02590 } 02591 02592 // The oct-hull is obtained by computing maxima. 02593 typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin(); 02594 for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(), 02595 matrix_element_end = matrix.element_end(); 02596 i != matrix_element_end; ++i, ++j) 02597 max_assign(*i, *j); 02598 02599 // The result is still closed. 02600 PPL_ASSERT(OK()); 02601 }
| 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.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Implementation is based on Theorem 6.3 of [BHZ09b].
Definition at line 6450 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::non_redundant_matrix_entries(), Parma_Polyhedra_Library::OR_Matrix< T >::num_rows(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::swap(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign().
06450 { 06451 // FIXME, CHECKME: what about inexact computations? 06452 06453 // Declare a const reference to *this (to avoid accidental modifications). 06454 const Octagonal_Shape& x = *this; 06455 const dimension_type x_space_dim = x.space_dimension(); 06456 06457 if (x_space_dim != y.space_dimension()) 06458 throw_dimension_incompatible("upper_bound_assign_if_exact(y)", y); 06459 06460 // The zero-dim case is trivial. 06461 if (x_space_dim == 0) { 06462 upper_bound_assign(y); 06463 return true; 06464 } 06465 // If `x' or `y' is (known to be) empty, the upper bound is exact. 06466 if (x.marked_empty()) { 06467 *this = y; 06468 return true; 06469 } 06470 else if (y.is_empty()) 06471 return true; 06472 else if (x.is_empty()) { 06473 *this = y; 06474 return true; 06475 } 06476 06477 // Here both `x' and `y' are known to be non-empty. 06478 PPL_ASSERT(x.marked_strongly_closed()); 06479 PPL_ASSERT(y.marked_strongly_closed()); 06480 // Pre-compute the upper bound of `x' and `y'. 06481 Octagonal_Shape<T> ub(x); 06482 ub.upper_bound_assign(y); 06483 06484 // Compute redundancy information for x and y. 06485 // TODO: provide a nicer data structure for redundancy. 06486 std::vector<Bit_Row> x_non_red; 06487 x.non_redundant_matrix_entries(x_non_red); 06488 std::vector<Bit_Row> y_non_red; 06489 y.non_redundant_matrix_entries(y_non_red); 06490 06491 PPL_DIRTY_TEMP(N, lhs); 06492 PPL_DIRTY_TEMP(N, lhs_copy); 06493 PPL_DIRTY_TEMP(N, rhs); 06494 PPL_DIRTY_TEMP(N, temp_zero); 06495 assign_r(temp_zero, 0, ROUND_NOT_NEEDED); 06496 06497 typedef typename OR_Matrix<N>::const_row_iterator Row_Iterator; 06498 typedef typename OR_Matrix<N>::const_row_reference_type Row_Reference; 06499 const dimension_type n_rows = x.matrix.num_rows(); 06500 const Row_Iterator x_m_begin = x.matrix.row_begin(); 06501 const Row_Iterator y_m_begin = y.matrix.row_begin(); 06502 const Row_Iterator ub_m_begin = ub.matrix.row_begin(); 06503 06504 for (dimension_type i = n_rows; i-- > 0; ) { 06505 const Bit_Row& x_non_red_i = x_non_red[i]; 06506 using namespace Implementation::Octagonal_Shapes; 06507 const dimension_type ci = coherent_index(i); 06508 const dimension_type row_size_i = OR_Matrix<N>::row_size(i); 06509 Row_Reference x_i = *(x_m_begin + i); 06510 Row_Reference y_i = *(y_m_begin + i); 06511 Row_Reference ub_i = *(ub_m_begin + i); 06512 const N& ub_i_ci = ub_i[ci]; 06513 for (dimension_type j = row_size_i; j-- > 0; ) { 06514 // Check redundancy of x_i_j. 06515 if (!x_non_red_i[j]) 06516 continue; 06517 const N& x_i_j = x_i[j]; 06518 // Check 1st condition in BHZ09 theorem. 06519 if (x_i_j >= y_i[j]) 06520 continue; 06521 const dimension_type cj = coherent_index(j); 06522 const dimension_type row_size_cj = OR_Matrix<N>::row_size(cj); 06523 Row_Reference ub_cj = *(ub_m_begin + cj); 06524 const N& ub_cj_j = ub_cj[j]; 06525 for (dimension_type k = 0; k < n_rows; ++k) { 06526 const Bit_Row& y_non_red_k = y_non_red[k]; 06527 const dimension_type ck = coherent_index(k); 06528 const dimension_type row_size_k = OR_Matrix<N>::row_size(k); 06529 Row_Reference x_k = *(x_m_begin + k); 06530 Row_Reference y_k = *(y_m_begin + k); 06531 Row_Reference ub_k = *(ub_m_begin + k); 06532 const N& ub_k_ck = ub_k[ck]; 06533 // Be careful: for each index h, the diagonal element m[h][h] 06534 // is (by convention) +infty in our implementation; however, 06535 // BHZ09 theorem assumes that it is equal to 0. 06536 const N& ub_k_j = (k == j) ? temp_zero 06537 : (j < row_size_k ? ub_k[j] : ub_cj[ck]); 06538 const N& ub_i_ck = (i == ck) ? temp_zero 06539 : (ck < row_size_i ? ub_i[ck] : ub_k[ci]); 06540 06541 for (dimension_type ell = row_size_k; ell-- > 0; ) { 06542 // Check redundancy of y_k_ell. 06543 if (!y_non_red_k[ell]) 06544 continue; 06545 const N& y_k_ell = y_k[ell]; 06546 // Check 2nd condition in BHZ09 theorem. 06547 if (y_k_ell >= x_k[ell]) 06548 continue; 06549 const dimension_type cell = coherent_index(ell); 06550 Row_Reference ub_cell = *(ub_m_begin + cell); 06551 const N& ub_i_ell = (i == ell) ? temp_zero 06552 : (ell < row_size_i ? ub_i[ell] : ub_cell[ci]); 06553 const N& ub_cj_ell = (cj == ell) ? temp_zero 06554 : (ell < row_size_cj ? ub_cj[ell] : ub_cell[j]); 06555 // Check 3rd condition in BHZ09 theorem. 06556 add_assign_r(lhs, x_i_j, y_k_ell, ROUND_UP); 06557 add_assign_r(rhs, ub_i_ell, ub_k_j, ROUND_UP); 06558 if (lhs >= rhs) 06559 continue; 06560 // Check 4th condition in BHZ09 theorem. 06561 add_assign_r(rhs, ub_i_ck, ub_cj_ell, ROUND_UP); 06562 if (lhs >= rhs) 06563 continue; 06564 // Check 5th condition in BHZ09 theorem. 06565 assign_r(lhs_copy, lhs, ROUND_NOT_NEEDED); 06566 add_assign_r(lhs, lhs_copy, x_i_j, ROUND_UP); 06567 add_assign_r(rhs, ub_i_ell, ub_i_ck, ROUND_UP); 06568 add_assign_r(rhs, rhs, ub_cj_j, ROUND_UP); 06569 if (lhs >= rhs) 06570 continue; 06571 // Check 6th condition in BHZ09 theorem. 06572 add_assign_r(rhs, ub_k_j, ub_cj_ell, ROUND_UP); 06573 add_assign_r(rhs, rhs, ub_i_ci, ROUND_UP); 06574 if (lhs >= rhs) 06575 continue; 06576 // Check 7th condition of BHZ09 theorem. 06577 add_assign_r(lhs, lhs_copy, y_k_ell, ROUND_UP); 06578 add_assign_r(rhs, ub_i_ell, ub_cj_ell, ROUND_UP); 06579 add_assign_r(rhs, rhs, ub_k_ck, ROUND_UP); 06580 if (lhs >= rhs) 06581 continue; 06582 // Check 8th (last) condition in BHZ09 theorem. 06583 add_assign_r(rhs, ub_k_j, ub_i_ck, ROUND_UP); 06584 add_assign_r(rhs, rhs, ub_cell[ell], ROUND_UP); 06585 if (lhs < rhs) 06586 // All 8 conditions are satisfied: 06587 // upper bound is not exact. 06588 return false; 06589 } 06590 } 06591 } 06592 } 06593 06594 // The upper bound of x and y is indeed exact. 06595 swap(ub); 06596 PPL_ASSERT(OK()); 06597 return true; 06598 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::widening_assign | ( | const Octagonal_Shape< T > & | y, | |
| unsigned * | tp = 0 | |||
| ) | [inline] |
Same as BHMZ05_widening_assign(y, tp).
Definition at line 572 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign().
00572 { 00573 BHMZ05_widening_assign(y, tp); 00574 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::wrap_assign | ( | const Variables_Set & | vars, | |
| Bounded_Integer_Type_Width | w, | |||
| Bounded_Integer_Type_Representation | r, | |||
| Bounded_Integer_Type_Overflow | o, | |||
| const Constraint_System * | pcs = 0, |
|||
| unsigned | complexity_threshold = 16, |
|||
| bool | wrap_individually = true | |||
| ) | [inline] |
Wraps the specified dimensions of the vector space.
| vars | The set of Variable objects corresponding to the space dimensions to be wrapped. | |
| w | The width of the bounded integer type corresponding to all the dimensions to be wrapped. | |
| r | The representation of the bounded integer type corresponding to all the dimensions to be wrapped. | |
| o | The overflow behavior of the bounded integer type corresponding to all the dimensions to be wrapped. | |
| pcs | Possibly null pointer to a constraint system whose variables are contained in vars. If *pcs depends on variables not in vars, the behavior is undefined. When non-null, the pointed-to constraint system is assumed to represent the conditional or looping construct guard with respect to which wrapping is performed. Since wrapping requires the computation of upper bounds and due to non-distributivity of constraint refinement over upper bounds, passing a constraint system in this way can be more precise than refining the result of the wrapping operation with the constraints in *pcs. | |
| complexity_threshold | A precision parameter of the wrapping operator: higher values result in possibly improved precision. | |
| wrap_individually | true if the dimensions should be wrapped individually (something that results in much greater efficiency to the detriment of precision). |
| std::invalid_argument | Thrown if *pcs is dimension-incompatible with vars, or if *this is dimension-incompatible vars or with *pcs. |
Definition at line 557 of file Octagonal_Shape.inlines.hh.
00563 { 00564 Implementation::wrap_assign(*this, 00565 vars, w, r, o, pcs, 00566 complexity_threshold, wrap_individually, 00567 "Octagonal_Shape"); 00568 }
| dimension_type coherent_index | ( | const dimension_type | i | ) | [related] |
Returns the index coherent to i.
Definition at line 50 of file Octagonal_Shape.inlines.hh.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::frequency(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strong_coherent(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix_at(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_coherence_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign_if_exact().
| bool euclidean_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Octagonal_Shape< T > & | x, | |||
| const Octagonal_Shape< T > & | y, | |||
| Rounding_Dir | dir, | |||
| Temp & | tmp0, | |||
| Temp & | tmp1, | |||
| Temp & | tmp2 | |||
| ) | [related] |
Computes the euclidean distance between x and y.
If the euclidean distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.
The direction of the approximation is specified by dir.
All computations are performed using the temporary variables tmp0, tmp1 and tmp2.
Definition at line 684 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().
00690 { 00691 // Dimension-compatibility check. 00692 if (x.space_dim != y.space_dim) 00693 return false; 00694 00695 // Zero-dim OSs are equal if and only if they are both empty or universe. 00696 if (x.space_dim == 0) { 00697 if (x.marked_empty() == y.marked_empty()) 00698 assign_r(r, 0, ROUND_NOT_NEEDED); 00699 else 00700 assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED); 00701 return true; 00702 } 00703 00704 // The distance computation requires strong closure. 00705 x.strong_closure_assign(); 00706 y.strong_closure_assign(); 00707 00708 // If one of two OSs is empty, then they are equal if and only if 00709 // the other OS is empty too. 00710 if (x.marked_empty() || y.marked_empty()) { 00711 if (x.marked_empty() == y.marked_empty()) 00712 assign_r(r, 0, ROUND_NOT_NEEDED); 00713 else 00714 assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED); 00715 return true; 00716 } 00717 00718 return euclidean_distance_assign(r, x.matrix, y.matrix, dir, 00719 tmp0, tmp1, tmp2); 00720 }
| bool euclidean_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Octagonal_Shape< T > & | x, | |||
| const Octagonal_Shape< T > & | y, | |||
| Rounding_Dir | dir | |||
| ) | [related] |
Computes the euclidean distance between x and y.
If the euclidean distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.
The direction of the approximation is specified by dir.
All computations are performed using variables of type Checked_Number<To, Extended_Number_Policy>.
If the euclidean distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.
The direction of the approximation is specified by dir.
All computations are performed using variables of type Checked_Number<Temp, Extended_Number_Policy>.
Definition at line 725 of file Octagonal_Shape.inlines.hh.
00728 { 00729 typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp; 00730 PPL_DIRTY_TEMP(Checked_Temp, tmp0); 00731 PPL_DIRTY_TEMP(Checked_Temp, tmp1); 00732 PPL_DIRTY_TEMP(Checked_Temp, tmp2); 00733 return euclidean_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2); 00734 }
| 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.
true if the constraint c is an octagonal difference; false otherwise.| c | The constraint to be decoded. | |
| c_space_dim | The space dimension of the constraint c (it is assumed to match the actual space dimension of c). | |
| c_num_vars | If true is returned, then it will be set to the number of variables having a non-zero coefficient. The only legal values will therefore be 0, 1 and 2. | |
| c_first_var | If true is returned and if c_num_vars is not set to 0, then it will be set to the index of the first variable having a non-zero coefficient in c. | |
| c_second_var | If true is returned and if c_num_vars is set to 2, then it will be set to the index of the second variable having a non-zero coefficient in c. | |
| c_coeff | If true is returned and if c_num_vars is not set to 0, then it will be set to the value of the first non-zero coefficient in c. | |
| c_term | If true is returned and if c_num_vars is not set to 0, then it will be set to the right value of the inhomogeneous term of c. |
Definition at line 34 of file Octagonal_Shape.cc.
References Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), and Parma_Polyhedra_Library::Constraint::space_dimension().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with().
00040 { 00041 // Check for preconditions. 00042 PPL_ASSERT(c.space_dimension() == c_space_dim); 00043 PPL_ASSERT(c_num_vars == 0 && c_first_var == 0 && c_second_var == 0); 00044 // Store the indices of the non-zero components of `c', 00045 dimension_type non_zero_index[2] = { 0, 0 }; 00046 // Collect the non-zero components of `c'. 00047 for (dimension_type i = c_space_dim; i-- > 0; ) 00048 if (c.coefficient(Variable(i)) != 0) { 00049 if (c_num_vars <= 1) 00050 non_zero_index[c_num_vars++] = i; 00051 else 00052 // Constraint `c' is not an octagonal difference. 00053 return false; 00054 } 00055 00056 // Make sure that `c' is indeed an octagonal difference, 00057 // i.e., it has one of the following forms: 00058 // 0 <=/= b, if c_num_vars == 0; 00059 // (+/-) a*x <=/= b, if c_num_vars == 1; 00060 // (+/-) a*x (+/-) a*y <=/= b, if c_num_vars == 2. 00061 c_term = c.inhomogeneous_term(); 00062 switch (c_num_vars) { 00063 case 2: 00064 { 00065 const Coefficient& c0 = c.coefficient(Variable(non_zero_index[0])); 00066 const Coefficient& c1 = c.coefficient(Variable(non_zero_index[1])); 00067 if (c0 != c1 && c0 != -c1) 00068 // Constraint `c' is not an octagonal difference. 00069 return false; 00070 c_first_var = non_zero_index[0]; 00071 c_second_var = non_zero_index[1]; 00072 c_first_var *= 2; 00073 if (sgn(c0) < 0) 00074 ++c_first_var; 00075 c_second_var *= 2; 00076 if (sgn(c1) > 0) 00077 ++c_second_var; 00078 c_coeff = c0; 00079 } 00080 break; 00081 case 1: 00082 { 00083 c_term *= 2; 00084 c_first_var = non_zero_index[0]; 00085 c_first_var *= 2; 00086 if (sgn(c.coefficient(Variable(non_zero_index[0]))) < 0) { 00087 c_second_var = c_first_var; 00088 ++c_first_var; 00089 } 00090 else 00091 c_second_var = c_first_var + 1; 00092 c_coeff = c.coefficient(Variable(non_zero_index[0])); 00093 } 00094 break; 00095 default: 00096 PPL_ASSERT(c_num_vars == 0); 00097 break; 00098 } 00099 return true; 00100 }
| 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
distance between x and y.
If the
distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.
The direction of the approximation is specified by dir.
All computations are performed using the temporary variables tmp0, tmp1 and tmp2.
Definition at line 749 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().
00755 { 00756 // Dimension-compatibility check. 00757 if (x.space_dim != y.space_dim) 00758 return false; 00759 00760 // Zero-dim OSs are equal if and only if they are both empty or universe. 00761 if (x.space_dim == 0) { 00762 if (x.marked_empty() == y.marked_empty()) 00763 assign_r(r, 0, ROUND_NOT_NEEDED); 00764 else 00765 assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED); 00766 return true; 00767 } 00768 00769 // The distance computation requires strong closure. 00770 x.strong_closure_assign(); 00771 y.strong_closure_assign(); 00772 00773 // If one of two OSs is empty, then they are equal if and only if 00774 // the other OS is empty too. 00775 if (x.marked_empty() || y.marked_empty()) { 00776 if (x.marked_empty() == y.marked_empty()) 00777 assign_r(r, 0, ROUND_NOT_NEEDED); 00778 else 00779 assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED); 00780 return true; 00781 } 00782 00783 return l_infinity_distance_assign(r, x.matrix, y.matrix, dir, 00784 tmp0, tmp1, tmp2); 00785 }
| 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
distance between x and y.
If the
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
distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.
The direction of the approximation is specified by dir.
All computations are performed using variables of type Checked_Number<Temp, Extended_Number_Policy>.
Definition at line 790 of file Octagonal_Shape.inlines.hh.
00793 { 00794 typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp; 00795 PPL_DIRTY_TEMP(Checked_Temp, tmp0); 00796 PPL_DIRTY_TEMP(Checked_Temp, tmp1); 00797 PPL_DIRTY_TEMP(Checked_Temp, tmp2); 00798 return l_infinity_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2); 00799 }
| bool operator!= | ( | const Octagonal_Shape< T > & | x, | |
| const Octagonal_Shape< T > & | y | |||
| ) | [related] |
Returns true if and only if x and y are different shapes.
Note that x and y may be dimension-incompatible shapes: in this case, the value true is returned.
Definition at line 351 of file Octagonal_Shape.inlines.hh.
| std::ostream & operator<< | ( | std::ostream & | s, | |
| const Octagonal_Shape< T > & | x | |||
| ) | [related] |
Output operator.
Writes a textual representation of oct on s: false is written if oct is an empty polyhedron; true is written if oct is a universe polyhedron; a system of constraints defining oct is written otherwise, all constraints separated by ", ".
Definition at line 6882 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::is_additive_inverse(), and Parma_Polyhedra_Library::is_plus_infinity().
06882 { 06883 // Handle special cases first. 06884 if (x.marked_empty()) { 06885 s << "false"; 06886 return s; 06887 } 06888 if (x.is_universe()) { 06889 s << "true"; 06890 return s; 06891 } 06892 06893 typedef typename Octagonal_Shape<T>::coefficient_type N; 06894 typedef typename OR_Matrix<N>::const_row_iterator Row_Iterator; 06895 typedef typename OR_Matrix<N>::const_row_reference_type Row_Reference; 06896 06897 // Records whether or not we still have to print the first constraint. 06898 bool first = true; 06899 06900 Row_Iterator m_begin = x.matrix.row_begin(); 06901 Row_Iterator m_end = x.matrix.row_end(); 06902 06903 // Temporaries. 06904 PPL_DIRTY_TEMP(N, negation); 06905 PPL_DIRTY_TEMP(N, half); 06906 // Go through all the unary constraints. 06907 // (Note: loop iterator is incremented in the loop body.) 06908 for (Row_Iterator i_iter = m_begin; i_iter != m_end; ) { 06909 const dimension_type i = i_iter.index(); 06910 const Variable v_i = Variable(i/2); 06911 const N& x_i_ii = (*i_iter)[i+1]; 06912 ++i_iter; 06913 const N& x_ii_i = (*i_iter)[i]; 06914 ++i_iter; 06915 // Check whether or not it is an equality constraint. 06916 if (is_additive_inverse(x_i_ii, x_ii_i)) { 06917 // It is an equality. 06918 PPL_ASSERT(!is_plus_infinity(x_i_ii) && !is_plus_infinity(x_ii_i)); 06919 if (first) 06920 first = false; 06921 else 06922 s << ", "; 06923 // If the value bound can NOT be divided by 2 exactly, 06924 // then we output the constraint `2*v_i = bound'. 06925 if (div_2exp_assign_r(half, x_ii_i, 1, ROUND_UP | ROUND_STRICT_RELATION) == V_EQ) 06926 s << v_i << " = " << half; 06927 else 06928 s << "2*" << v_i << " = " << x_ii_i; 06929 } 06930 else { 06931 // We will print unary non-strict inequalities, if any. 06932 if (!is_plus_infinity(x_i_ii)) { 06933 if (first) 06934 first = false; 06935 else 06936 s << ", "; 06937 neg_assign_r(negation, x_i_ii, ROUND_NOT_NEEDED); 06938 // If the value bound can NOT be divided by 2 exactly, 06939 // then we output the constraint `2*v_i >= negation'. 06940 if (div_2exp_assign_r(half, negation, 1, ROUND_UP | ROUND_STRICT_RELATION) == V_EQ) 06941 s << v_i << " >= " << half; 06942 else 06943 s << "2*" << v_i << " >= " << negation; 06944 } 06945 if (!is_plus_infinity(x_ii_i)) { 06946 if (first) 06947 first = false; 06948 else 06949 s << ", "; 06950 // If the value bound can NOT be divided by 2 exactly, 06951 // then we output the constraint `2*v_i <= bound'. 06952 if (div_2exp_assign_r(half, x_ii_i, 1, ROUND_UP | ROUND_STRICT_RELATION) == V_EQ) 06953 s << v_i << " <= " << half; 06954 else 06955 s << "2*" << v_i << " <= " << x_ii_i; 06956 } 06957 } 06958 } 06959 06960 // Go through all the binary constraints. 06961 // (Note: loop iterator is incremented in the loop body.) 06962 for (Row_Iterator i_iter = m_begin; i_iter != m_end; ) { 06963 const dimension_type i = i_iter.index(); 06964 const Variable v_i = Variable(i/2); 06965 Row_Reference r_i = *i_iter; 06966 ++i_iter; 06967 Row_Reference r_ii = *i_iter; 06968 ++i_iter; 06969 06970 for (dimension_type j = 0; j < i; j += 2) { 06971 const Variable v_j = Variable(j/2); 06972 // Print binary differences. 06973 const N& x_ii_jj = r_ii[j+1]; 06974 const N& x_i_j = r_i[j]; 06975 // Check whether or not it is an equality constraint. 06976 if (is_additive_inverse(x_ii_jj, x_i_j)) { 06977 // It is an equality. 06978 PPL_ASSERT(!is_plus_infinity(x_i_j) && !is_plus_infinity(x_ii_jj)); 06979 if (first) 06980 first = false; 06981 else 06982 s << ", "; 06983 if (sgn(x_i_j) >= 0) 06984 s << v_j << " - " << v_i << " = " << x_i_j; 06985 else 06986 s << v_i << " - " << v_j << " = " << x_ii_jj; 06987 } 06988 else { 06989 // We will print non-strict inequalities, if any. 06990 if (!is_plus_infinity(x_i_j)) { 06991 if (first) 06992 first = false; 06993 else 06994 s << ", "; 06995 if (sgn(x_i_j) >= 0) 06996 s << v_j << " - " << v_i << " <= " << x_i_j; 06997 else { 06998 neg_assign_r(negation, x_i_j, ROUND_DOWN); 06999 s << v_i << " - " << v_j << " >= " << negation; 07000 } 07001 } 07002 if (!is_plus_infinity(x_ii_jj)) { 07003 if (first) 07004 first = false; 07005 else 07006 s << ", "; 07007 if (sgn(x_ii_jj) >= 0) 07008 s << v_i << " - " << v_j << " <= " << x_ii_jj; 07009 else { 07010 neg_assign_r(negation, x_ii_jj, ROUND_DOWN); 07011 s << v_j << " - " << v_i << " >= " << negation; 07012 } 07013 } 07014 } 07015 // Print binary sums. 07016 const N& x_i_jj = r_i[j+1]; 07017 const N& x_ii_j = r_ii[j]; 07018 // Check whether or not it is an equality constraint. 07019 if (is_additive_inverse(x_i_jj, x_ii_j)) { 07020 // It is an equality. 07021 PPL_ASSERT(!is_plus_infinity(x_i_jj) && !is_plus_infinity(x_ii_j)); 07022 if (first) 07023 first = false; 07024 else 07025 s << ", "; 07026 s << v_j << " + " << v_i << " = " << x_ii_j; 07027 } 07028 else { 07029 // We will print non-strict inequalities, if any. 07030 if (!is_plus_infinity(x_i_jj)) { 07031 if (first) 07032 first = false; 07033 else 07034 s << ", "; 07035 neg_assign_r(negation, x_i_jj, ROUND_DOWN); 07036 s << v_j << " + " << v_i << " >= " << negation; 07037 } 07038 if (!is_plus_infinity(x_ii_j)) { 07039 if (first) 07040 first = false; 07041 else 07042 s << ", "; 07043 s << v_j << " + " << v_i << " <= " << x_ii_j; 07044 } 07045 } 07046 } 07047 } 07048 return s; 07049 }
| bool operator== | ( | const Octagonal_Shape< T > & | x, | |
| const Octagonal_Shape< T > & | y | |||
| ) | [friend] |
Returns true if and only if x and y are the same octagon.
Note that x and y may be dimension-incompatible shapes: in this case, the value false is returned.
Definition at line 323 of file Octagonal_Shape.inlines.hh.
00323 { 00324 if (x.space_dim != y.space_dim) 00325 // Dimension-incompatible OSs are different. 00326 return false; 00327 00328 // Zero-dim OSs are equal if and only if they are both empty or universe. 00329 if (x.space_dim == 0) { 00330 if (x.marked_empty()) 00331 return y.marked_empty(); 00332 else 00333 return !y.marked_empty(); 00334 } 00335 00336 x.strong_closure_assign(); 00337 y.strong_closure_assign(); 00338 // If one of two octagons is empty, then they are equal if and only if 00339 // the other octagon is empty too. 00340 if (x.marked_empty()) 00341 return y.marked_empty(); 00342 if (y.marked_empty()) 00343 return false; 00344 // Strong closure is a canonical form. 00345 return x.matrix == y.matrix; 00346 }
friend class Parma_Polyhedra_Library::Box [friend] |
Definition at line 1777 of file Octagonal_Shape.defs.hh.
| bool Parma_Polyhedra_Library::euclidean_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Octagonal_Shape< U > & | x, | |||
| const Octagonal_Shape< U > & | y, | |||
| const Rounding_Dir | dir, | |||
| Temp & | tmp0, | |||
| Temp & | tmp1, | |||
| Temp & | tmp2 | |||
| ) | [friend] |
| std::ostream& Parma_Polyhedra_Library::IO_Operators::operator<< | ( | std::ostream & | s, | |
| const Octagonal_Shape< T > & | c | |||
| ) | [friend] |
| bool Parma_Polyhedra_Library::l_infinity_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Octagonal_Shape< U > & | x, | |||
| const Octagonal_Shape< U > & | y, | |||
| const Rounding_Dir | dir, | |||
| Temp & | tmp0, | |||
| Temp & | tmp1, | |||
| Temp & | tmp2 | |||
| ) | [friend] |
friend class Parma_Polyhedra_Library::Octagonal_Shape [friend] |
Definition at line 1776 of file Octagonal_Shape.defs.hh.
| bool Parma_Polyhedra_Library::rectilinear_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Octagonal_Shape< U > & | x, | |||
| const Octagonal_Shape< U > & | y, | |||
| const Rounding_Dir | dir, | |||
| Temp & | tmp0, | |||
| Temp & | tmp1, | |||
| Temp & | tmp2 | |||
| ) | [friend] |
| bool rectilinear_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Octagonal_Shape< T > & | x, | |||
| const Octagonal_Shape< T > & | y, | |||
| Rounding_Dir | dir, | |||
| Temp & | tmp0, | |||
| Temp & | tmp1, | |||
| Temp & | tmp2 | |||
| ) | [related] |
Computes the rectilinear (or Manhattan) distance between x and y.
If the rectilinear distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.
The direction of the approximation is specified by dir.
All computations are performed using the temporary variables tmp0, tmp1 and tmp2.
Definition at line 619 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().
00625 { 00626 // Dimension-compatibility check. 00627 if (x.space_dim != y.space_dim) 00628 return false; 00629 00630 // Zero-dim OSs are equal if and only if they are both empty or universe. 00631 if (x.space_dim == 0) { 00632 if (x.marked_empty() == y.marked_empty()) 00633 assign_r(r, 0, ROUND_NOT_NEEDED); 00634 else 00635 assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED); 00636 return true; 00637 } 00638 00639 // The distance computation requires strong closure. 00640 x.strong_closure_assign(); 00641 y.strong_closure_assign(); 00642 00643 // If one of two OSs is empty, then they are equal if and only if 00644 // the other OS is empty too. 00645 if (x.marked_empty() || y.marked_empty()) { 00646 if (x.marked_empty() == y.marked_empty()) 00647 assign_r(r, 0, ROUND_NOT_NEEDED); 00648 else 00649 assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED); 00650 return true; 00651 } 00652 00653 return rectilinear_distance_assign(r, x.matrix, y.matrix, dir, 00654 tmp0, tmp1, tmp2); 00655 }
| bool rectilinear_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Octagonal_Shape< T > & | x, | |||
| const Octagonal_Shape< T > & | y, | |||
| Rounding_Dir | dir | |||
| ) | [related] |
Computes the rectilinear (or Manhattan) distance between x and y.
If the rectilinear distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.
The direction of the approximation is specified by dir.
All computations are performed using variables of type Checked_Number<To, Extended_Number_Policy>.
If the rectilinear distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.
The direction of the approximation is specified by dir.
All computations are performed using variables of type Checked_Number<Temp, Extended_Number_Policy>.
Definition at line 660 of file Octagonal_Shape.inlines.hh.
00663 { 00664 typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp; 00665 PPL_DIRTY_TEMP(Checked_Temp, tmp0); 00666 PPL_DIRTY_TEMP(Checked_Temp, tmp1); 00667 PPL_DIRTY_TEMP(Checked_Temp, tmp2); 00668 return rectilinear_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2); 00669 }
| void swap | ( | Parma_Polyhedra_Library::Octagonal_Shape< T > & | x, | |
| Parma_Polyhedra_Library::Octagonal_Shape< T > & | y | |||
| ) | [related] |
Specializes std::swap.
Definition at line 843 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::swap().
00844 { 00845 x.swap(y); 00846 }
T Parma_Polyhedra_Library::Octagonal_Shape< T >::default_stop_points[] [static, private] |
Definition at line 2162 of file Octagonal_Shape.defs.hh.
OR_Matrix<N> Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix [private] |
The matrix that represents the octagonal shape.
Definition at line 1780 of file Octagonal_Shape.defs.hh.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::ascii_dump(), Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constrains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Octagonal_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::external_memory_in_bytes(), Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::frequency(), Parma_Polyhedra_Library::Octagonal_Shape< T >::get_limiting_octagon(), Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::integer_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_bounded(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strong_coherent(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strongly_reduced(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_universe(), Parma_Polyhedra_Library::Octagonal_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix_at(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::operator=(), Parma_Polyhedra_Library::Octagonal_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_coherence_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::swap(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign_if_exact().
dimension_type Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim [private] |
Dimension of the space of the octagonal shape.
Definition at line 1783 of file Octagonal_Shape.defs.hh.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::ascii_dump(), Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Octagonal_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::frequency(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_bounded(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_universe(), Parma_Polyhedra_Library::Octagonal_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_BHMZ05_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::operator=(), Parma_Polyhedra_Library::Octagonal_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::swap(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign().
Status Parma_Polyhedra_Library::Octagonal_Shape< T >::status [private] |
The status flags to keep track of the internal state.
Definition at line 1796 of file Octagonal_Shape.defs.hh.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::ascii_dump(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_zero_dim_univ(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::operator=(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_zero_dim_univ(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::swap().
1.6.3