A not necessarily closed, iso-oriented hyperrectangle. More...
#include <Box.defs.hh>

Classes | |
| class | Status |
Public Types | |
| typedef ITV | interval_type |
| The type of intervals used to implement the box. | |
Public Member Functions | |
| const ITV & | get_interval (Variable var) const |
Returns a reference the interval that bounds var. | |
| void | set_interval (Variable var, const ITV &i) |
Sets to i the interval that bounds var. | |
| bool | get_lower_bound (dimension_type k, bool &closed, Coefficient &n, Coefficient &d) const |
If the k-th space dimension is unbounded below, returns false. Otherwise returns true and set closed, n and d accordingly. | |
| bool | get_upper_bound (dimension_type k, bool &closed, Coefficient &n, Coefficient &d) const |
If the k-th space dimension is unbounded above, returns false. Otherwise returns true and set closed, n and d accordingly. | |
| Constraint_System | constraints () const |
Returns a 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 congruences approximating *this. | |
| Congruence_System | minimized_congruences () const |
Returns a minimized system of congruences approximating *this. | |
| 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. | |
| 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. | |
| void | set_empty () |
| Causes the box to become empty, i.e., to represent the empty set. | |
Constructors, Assignment, Swap and Destructor | |
| Box (dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE) | |
| Builds a universe or empty box of the specified space dimension. | |
| Box (const Box &y, Complexity_Class complexity=ANY_COMPLEXITY) | |
| Ordinary copy constructor. | |
| template<typename Other_ITV > | |
| Box (const Box< Other_ITV > &y, Complexity_Class complexity=ANY_COMPLEXITY) | |
Builds a conservative, upward approximation of y. | |
| Box (const Constraint_System &cs) | |
Builds a box from the system of constraints cs. | |
| Box (const Constraint_System &cs, Recycle_Input dummy) | |
Builds a box recycling a system of constraints cs. | |
| Box (const Generator_System &gs) | |
Builds a box from the system of generators gs. | |
| Box (const Generator_System &gs, Recycle_Input dummy) | |
Builds a box recycling the system of generators gs. | |
| Box (const Congruence_System &cgs) | |
| Box (const Congruence_System &cgs, Recycle_Input dummy) | |
| template<typename T > | |
| Box (const BD_Shape< T > &bds, Complexity_Class complexity=POLYNOMIAL_COMPLEXITY) | |
Builds a box containing the BDS bds. | |
| template<typename T > | |
| Box (const Octagonal_Shape< T > &oct, Complexity_Class complexity=POLYNOMIAL_COMPLEXITY) | |
Builds a box containing the octagonal shape oct. | |
| Box (const Polyhedron &ph, Complexity_Class complexity=ANY_COMPLEXITY) | |
Builds a box containing the polyhedron ph. | |
| Box (const Grid &ph, Complexity_Class complexity=POLYNOMIAL_COMPLEXITY) | |
Builds a box containing the grid gr. | |
| template<typename D1 , typename D2 , typename R > | |
| Box (const Partially_Reduced_Product< D1, D2, R > &dp, Complexity_Class complexity=ANY_COMPLEXITY) | |
Builds a box containing the partially reduced product dp. | |
| Box & | operator= (const Box &y) |
The assignment operator (*this and y can be dimension-incompatible). | |
| void | swap (Box &y) |
Swaps *this with y (*this and y can be dimension-incompatible). | |
Member Functions that Do Not Modify the Box | |
| 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. | |
| bool | is_empty () const |
Returns true if and only if *this is an empty box. | |
| bool | is_universe () const |
Returns true if and only if *this is a universe box. | |
| bool | is_topologically_closed () const |
Returns true if and only if *this is a topologically closed subset of the vector space. | |
| 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 box. | |
| bool | contains_integer_point () const |
Returns true if and only if *this contains at least one integer point. | |
| bool | constrains (Variable var) const |
Returns true if and only if var is constrained in *this. | |
| 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 | 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 | contains (const Box &y) const |
Returns true if and only if *this contains y. | |
| bool | strictly_contains (const Box &y) const |
Returns true if and only if *this strictly contains y. | |
| bool | is_disjoint_from (const Box &y) const |
Returns true if and only if *this and y are disjoint. | |
| bool | OK () const |
Returns true if and only if *this satisfies all its invariants. | |
Space-Dimension Preserving Member Functions that May Modify the Box | |
| 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 defining *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) |
Use the constraint c to refine *this. | |
| void | refine_with_constraints (const Constraint_System &cs) |
Use the constraints in cs to refine *this. | |
| void | refine_with_congruence (const Congruence &cg) |
Use the congruence cg to refine *this. | |
| void | refine_with_congruences (const Congruence_System &cgs) |
Use the congruences in cgs to refine *this. | |
| void | propagate_constraint (const Constraint &c) |
Use the constraint c for constraint propagation on *this. | |
| void | propagate_constraints (const Constraint_System &cs, dimension_type max_iterations=0) |
Use the constraints in cs for constraint propagagion on *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 Box &y) |
Assigns to *this the intersection of *this and y. | |
| void | upper_bound_assign (const Box &y) |
Assigns to *this the smallest box containing the union of *this and y. | |
| bool | upper_bound_assign_if_exact (const Box &y) |
If the upper bound of *this and y is exact, it is assigned to *this and true is returned, otherwise false is returned. | |
| void | difference_assign (const Box &y) |
Assigns to *this the difference of *this and y. | |
| bool | simplify_using_context_assign (const Box &y) |
Assigns to *this a meet-preserving simplification of *this with respect to y. If false is returned, then the intersection is empty. | |
| void | affine_image (Variable var, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one()) |
Assigns to *this the affine image of *this under the function mapping variable var to the affine expression specified by expr and denominator. | |
| void | affine_preimage (Variable var, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one()) |
Assigns to *this the affine preimage of *this under the function mapping variable var to the affine expression specified by expr and denominator. | |
| void | generalized_affine_image (Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one()) |
Assigns to *this the image of *this with respect to the generalized affine relation , where is the relation symbol encoded by relsym. | |
| 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 generalized affine relation , 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 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_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 | 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 Box &y) |
Assigns to *this the result of computing the time-elapse between *this and y. | |
| void | topological_closure_assign () |
Assigns to *this its topological closure. | |
| void | 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. | |
| template<typename T > | |
| Enable_If< Is_Same< T, Box > ::value &&Is_Same_Or_Derived < Interval_Base, ITV >::value, void >::type | CC76_widening_assign (const T &y, unsigned *tp=0) |
Assigns to *this the result of computing the CC76-widening between *this and y. | |
| template<typename T , typename Iterator > | |
| Enable_If< Is_Same< T, Box > ::value &&Is_Same_Or_Derived < Interval_Base, ITV >::value, void >::type | CC76_widening_assign (const T &y, Iterator first, Iterator last) |
Assigns to *this the result of computing the CC76-widening between *this and y. | |
| void | widening_assign (const Box &y, unsigned *tp=0) |
| Same as CC76_widening_assign(y, tp). | |
| void | limited_CC76_extrapolation_assign (const Box &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. | |
| template<typename T > | |
| Enable_If< Is_Same< T, Box > ::value &&Is_Same_Or_Derived < Interval_Base, ITV >::value, void >::type | CC76_narrowing_assign (const T &y) |
Assigns to *this the result of restoring in y the constraints of *this that were lost by CC76-extrapolation applications. | |
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 box into the new space. | |
| void | add_space_dimensions_and_project (dimension_type m) |
Adds m new dimensions to the box and does not embed it in the new vector space. | |
| void | concatenate_assign (const Box &y) |
Seeing a box as a set of tuples (its points), assigns to *this all the tuples that can be obtained by concatenating, in the order given, a tuple of *this with a tuple of y. | |
| 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. | |
Static Public Member Functions | |
| static dimension_type | max_space_dimension () |
| Returns the maximum space dimension that a Box can handle. | |
| static bool | can_recycle_constraint_systems () |
| Returns false indicating that this domain does not recycle constraints. | |
| static bool | can_recycle_congruence_systems () |
| Returns false indicating that this domain does not recycle congruences. | |
Private Types | |
| typedef std::vector< ITV > | Sequence |
| The type of sequence used to implement the box. | |
| typedef ITV | Tmp_Interval_Type |
| The type of intervals used by inner computations when trying to limit the cumulative effect of approximation errors. | |
Private Member Functions | |
| bool | marked_empty () const |
Returns true if and only if the box is known to be empty. | |
| void | set_nonempty () |
Marks *this as definitely not empty. | |
| void | set_empty_up_to_date () |
Asserts the validity of the empty flag of *this. | |
| void | reset_empty_up_to_date () |
Invalidates empty flag of *this. | |
| bool | check_empty () const |
Checks the hard way whether *this is an empty box: returns true if and only if it is so. | |
| const ITV & | operator[] (dimension_type k) const |
Returns a reference the interval that bounds the box on the k-th space dimension. | |
| void | add_interval_constraint_no_check (dimension_type var_id, Constraint::Type type, Coefficient_traits::const_reference num, Coefficient_traits::const_reference den) |
| WRITE ME. | |
| void | add_constraint_no_check (const Constraint &c) |
| WRITE ME. | |
| void | add_constraints_no_check (const Constraint_System &cs) |
| WRITE ME. | |
| void | add_congruence_no_check (const Congruence &cg) |
| WRITE ME. | |
| void | add_congruences_no_check (const Congruence_System &cgs) |
| WRITE ME. | |
| void | refine_no_check (const Constraint &c) |
Uses the constraint c to refine *this. | |
| void | refine_no_check (const Constraint_System &cs) |
Uses the constraints in cs to refine *this. | |
| void | refine_no_check (const Congruence &cg) |
Uses the congruence cg to refine *this. | |
| void | refine_no_check (const Congruence_System &cgs) |
Uses the congruences in cgs to refine *this. | |
| void | propagate_constraint_no_check (const Constraint &c) |
Propagates the constraint c to refine *this. | |
| void | propagate_constraints_no_check (const Constraint_System &cs, dimension_type max_iterations) |
Propagates the constraints in cs to refine *this. | |
| 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, Generator &g) 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) const |
Maximizes or minimizes expr subject to *this. | |
| void | get_limiting_box (const Constraint_System &cs, Box &limiting_box) const |
Adds to limiting_box the interval constraints in cs that are satisfied by *this. | |
Static Private Member Functions | |
| static I_Result | refine_interval_no_check (ITV &itv, Constraint::Type type, Coefficient_traits::const_reference num, Coefficient_traits::const_reference den) |
| WRITE ME. | |
Private Attributes | |
| Sequence | seq |
| A sequence of intervals, one for each dimension of the vector space. | |
| Status | status |
| The status flags to keep track of the internal state. | |
Friends | |
| class | Parma_Polyhedra_Library::Box |
| bool | operator== (const Box< ITV > &x, const Box< ITV > &y) |
Returns true if and only if x and y are the same box. | |
| std::ostream & | Parma_Polyhedra_Library::IO_Operators::operator<< (std::ostream &s, const Box< ITV > &box) |
| template<typename Specialization , typename Temp , typename To , typename I > | |
| bool | Parma_Polyhedra_Library::l_m_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Box< I > &x, const Box< I > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2) |
Related Functions | |
(Note that these are not member functions.) | |
| template<typename ITV > | |
| bool | operator!= (const Box< ITV > &x, const Box< ITV > &y) |
Returns true if and only if x and y aren't the same box. | |
| template<typename ITV > | |
| std::ostream & | operator<< (std::ostream &s, const Box< ITV > &box) |
| Output operator. | |
| template<typename To , typename ITV > | |
| bool | rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Box< ITV > &x, const Box< ITV > &y, Rounding_Dir dir) |
Computes the rectilinear (or Manhattan) distance between x and y. | |
| template<typename Temp , typename To , typename ITV > | |
| bool | rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Box< ITV > &x, const Box< ITV > &y, Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2) |
Computes the rectilinear (or Manhattan) distance between x and y. | |
| template<typename To , typename ITV > | |
| bool | euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Box< ITV > &x, const Box< ITV > &y, Rounding_Dir dir) |
Computes the euclidean distance between x and y. | |
| template<typename Temp , typename To , typename ITV > | |
| bool | euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Box< ITV > &x, const Box< ITV > &y, Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2) |
Computes the euclidean distance between x and y. | |
| template<typename To , typename ITV > | |
| bool | l_infinity_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Box< ITV > &x, const Box< ITV > &y, Rounding_Dir dir) |
Computes the distance between x and y. | |
| template<typename Temp , typename To , typename ITV > | |
| bool | l_infinity_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Box< ITV > &x, const Box< ITV > &y, Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2) |
Computes the distance between x and y. | |
| template<typename Specialization , typename Temp , typename To , typename ITV > | |
| bool | l_m_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Box< ITV > &x, const Box< ITV > &y, Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2) |
| bool | extract_interval_constraint (const Constraint &c, dimension_type c_space_dim, dimension_type &c_num_vars, dimension_type &c_only_var) |
Decodes the constraint c as an interval constraint. | |
Exception Throwers | |
|
| |
| void | throw_dimension_incompatible (const char *method, const Box &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 Constraint_System &cs) const |
| void | throw_dimension_incompatible (const char *method, const Congruence_System &cgs) 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 |
| static void | throw_space_dimension_overflow (const char *method, const char *reason) |
| static void | throw_constraint_incompatible (const char *method) |
| static void | throw_expression_too_complex (const char *method, const Linear_Expression &e) |
| static void | throw_generic (const char *method, const char *reason) |
A not necessarily closed, iso-oriented hyperrectangle.
A Box object represents the smash product of
not necessarily closed and possibly unbounded intervals represented by objects of class ITV, where
is the space dimension of the box.
An interval constraint (resp., interval congruence) is a syntactic constraint (resp., congruence) that only mentions a single space dimension.
The Box domain optimally supports:
ITV;ITV.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.
The user interface for the Box domain is meant to be as similar as possible to the one developed for the polyhedron class C_Polyhedron.
Definition at line 292 of file Box.defs.hh.
| typedef ITV Parma_Polyhedra_Library::Box< ITV >::interval_type |
The type of intervals used to implement the box.
Definition at line 295 of file Box.defs.hh.
typedef std::vector<ITV> Parma_Polyhedra_Library::Box< ITV >::Sequence [private] |
The type of sequence used to implement the box.
Definition at line 1693 of file Box.defs.hh.
typedef ITV Parma_Polyhedra_Library::Box< ITV >::Tmp_Interval_Type [private] |
The type of intervals used by inner computations when trying to limit the cumulative effect of approximation errors.
Definition at line 1699 of file Box.defs.hh.
| Parma_Polyhedra_Library::Box< ITV >::Box | ( | dimension_type | num_dimensions = 0, |
|
| Degenerate_Element | kind = UNIVERSE | |||
| ) | [inline, explicit] |
Builds a universe or empty box of the specified space dimension.
| num_dimensions | The number of dimensions of the vector space enclosing the box; | |
| kind | Specifies whether the universe or the empty box has to be built. |
Definition at line 48 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::set_empty_up_to_date(), and Parma_Polyhedra_Library::UNIVERSE.
00049 : seq(num_dimensions <= max_space_dimension() 00050 ? num_dimensions 00051 : (throw_space_dimension_overflow("Box(n, k)", 00052 "n exceeds the maximum " 00053 "allowed space dimension"), 00054 num_dimensions)), 00055 status() { 00056 // In a box that is marked empty the intervals are completely 00057 // meaningless: we exploit this by avoiding their initialization. 00058 if (kind == UNIVERSE) { 00059 for (dimension_type i = num_dimensions; i-- > 0; ) 00060 seq[i].assign(UNIVERSE); 00061 set_empty_up_to_date(); 00062 } 00063 else 00064 set_empty(); 00065 PPL_ASSERT(OK()); 00066 }
| Parma_Polyhedra_Library::Box< ITV >::Box | ( | const Box< ITV > & | y, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline] |
Ordinary copy constructor.
The complexity argument is ignored.
Definition at line 70 of file Box.inlines.hh.
| Parma_Polyhedra_Library::Box< ITV >::Box | ( | const Box< Other_ITV > & | y, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline, explicit] |
Builds a conservative, upward approximation of y.
The complexity argument is ignored.
Definition at line 103 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), and Parma_Polyhedra_Library::Box< ITV >::space_dimension().
00104 : seq(y.space_dimension()), 00105 // FIXME: why the following does not work? 00106 // status(y.status) { 00107 status() { 00108 // FIXME: remove when the above is fixed. 00109 if (y.marked_empty()) 00110 set_empty(); 00111 00112 if (!y.marked_empty()) 00113 for (dimension_type k = y.space_dimension(); k-- > 0; ) 00114 seq[k].assign(y.seq[k]); 00115 PPL_ASSERT(OK()); 00116 }
| Parma_Polyhedra_Library::Box< ITV >::Box | ( | const Constraint_System & | cs | ) | [inline, explicit] |
Builds a box from the system of constraints cs.
The box inherits the space dimension of cs.
| cs | A system of constraints: constraints that are not interval constraints are ignored (even though they may have contributed to the space dimension). |
Definition at line 70 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::add_constraints_no_check(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Constraint_System::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.
00071 : seq(cs.space_dimension() <= max_space_dimension() 00072 ? cs.space_dimension() 00073 : (throw_space_dimension_overflow("Box(cs)", 00074 "cs exceeds the maximum " 00075 "allowed space dimension"), 00076 cs.space_dimension())), 00077 status() { 00078 // FIXME: check whether we can avoid the double initialization. 00079 for (dimension_type i = cs.space_dimension(); i-- > 0; ) 00080 seq[i].assign(UNIVERSE); 00081 add_constraints_no_check(cs); 00082 }
| Parma_Polyhedra_Library::Box< ITV >::Box | ( | const Constraint_System & | cs, | |
| Recycle_Input | dummy | |||
| ) | [inline] |
Builds a box recycling a system of constraints cs.
The box inherits the space dimension of cs.
| cs | A system of constraints: constraints that are not interval constraints are ignored (even though they may have contributed to the space dimension). | |
| dummy | A dummy tag to syntactically differentiate this one from the other constructors. |
Definition at line 92 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::swap().
00092 { 00093 // Recycling is useless: just delegate. 00094 Box<ITV> tmp(cs); 00095 this->swap(tmp); 00096 }
| Parma_Polyhedra_Library::Box< ITV >::Box | ( | const Generator_System & | gs | ) | [inline, explicit] |
Builds a box from the system of generators gs.
Builds the smallest box containing the polyhedron defined by gs. The box 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 119 of file Box.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::Generator::divisor(), Parma_Polyhedra_Library::Generator_System::end(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Generator::is_point(), Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::Generator::LINE, Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Generator::RAY, Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::set_empty_up_to_date(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Generator::type(), and Parma_Polyhedra_Library::UNIVERSE.
00120 : seq(gs.space_dimension() <= max_space_dimension() 00121 ? gs.space_dimension() 00122 : (throw_space_dimension_overflow("Box(gs)", 00123 "gs exceeds the maximum " 00124 "allowed space dimension"), 00125 gs.space_dimension())), 00126 status() { 00127 const Generator_System::const_iterator gs_begin = gs.begin(); 00128 const Generator_System::const_iterator gs_end = gs.end(); 00129 if (gs_begin == gs_end) { 00130 // An empty generator system defines the empty box. 00131 set_empty(); 00132 return; 00133 } 00134 00135 // The empty flag will be meaningful, whatever happens from now on. 00136 set_empty_up_to_date(); 00137 00138 const dimension_type space_dim = space_dimension(); 00139 PPL_DIRTY_TEMP(mpq_class, q); 00140 bool point_seen = false; 00141 // Going through all the points. 00142 for (Generator_System::const_iterator 00143 gs_i = gs_begin; gs_i != gs_end; ++gs_i) { 00144 const Generator& g = *gs_i; 00145 if (g.is_point()) { 00146 const Coefficient& d = g.divisor(); 00147 if (point_seen) { 00148 // This is not the first point: `seq' already contains valid values. 00149 for (dimension_type i = space_dim; i-- > 0; ) { 00150 assign_r(q.get_num(), g.coefficient(Variable(i)), ROUND_NOT_NEEDED); 00151 assign_r(q.get_den(), d, ROUND_NOT_NEEDED); 00152 q.canonicalize(); 00153 PPL_DIRTY_TEMP(ITV, iq); 00154 iq.build(i_constraint(EQUAL, q)); 00155 seq[i].join_assign(iq); 00156 } 00157 } 00158 else { 00159 // This is the first point seen: initialize `seq'. 00160 point_seen = true; 00161 for (dimension_type i = space_dim; i-- > 0; ) { 00162 assign_r(q.get_num(), g.coefficient(Variable(i)), ROUND_NOT_NEEDED); 00163 assign_r(q.get_den(), d, ROUND_NOT_NEEDED); 00164 q.canonicalize(); 00165 seq[i].build(i_constraint(EQUAL, q)); 00166 } 00167 } 00168 } 00169 } 00170 00171 if (!point_seen) 00172 // The generator system is not empty, but contains no points. 00173 throw std::invalid_argument("PPL::Box<ITV>::Box(gs):\n" 00174 "the non-empty generator system gs " 00175 "contains no points."); 00176 00177 // Going through all the lines, rays and closure points. 00178 ITV q_interval; 00179 for (Generator_System::const_iterator gs_i = gs_begin; 00180 gs_i != gs_end; ++gs_i) { 00181 const Generator& g = *gs_i; 00182 switch (g.type()) { 00183 case Generator::LINE: 00184 for (dimension_type i = space_dim; i-- > 0; ) 00185 if (g.coefficient(Variable(i)) != 0) 00186 seq[i].assign(UNIVERSE); 00187 break; 00188 case Generator::RAY: 00189 for (dimension_type i = space_dim; i-- > 0; ) 00190 switch (sgn(g.coefficient(Variable(i)))) { 00191 case 1: 00192 seq[i].upper_extend(); 00193 break; 00194 case -1: 00195 seq[i].lower_extend(); 00196 break; 00197 default: 00198 break; 00199 } 00200 break; 00201 case Generator::CLOSURE_POINT: 00202 { 00203 const Coefficient& d = g.divisor(); 00204 for (dimension_type i = space_dim; i-- > 0; ) { 00205 assign_r(q.get_num(), g.coefficient(Variable(i)), ROUND_NOT_NEEDED); 00206 assign_r(q.get_den(), d, ROUND_NOT_NEEDED); 00207 q.canonicalize(); 00208 ITV& seq_i = seq[i]; 00209 seq_i.lower_extend(i_constraint(GREATER_THAN, q)); 00210 seq_i.upper_extend(i_constraint(LESS_THAN, q)); 00211 } 00212 } 00213 break; 00214 default: 00215 // Points already dealt with. 00216 break; 00217 } 00218 } 00219 PPL_ASSERT(OK()); 00220 }
| Parma_Polyhedra_Library::Box< ITV >::Box | ( | const Generator_System & | gs, | |
| Recycle_Input | dummy | |||
| ) | [inline] |
Builds a box recycling the system of generators gs.
Builds the smallest box containing the polyhedron defined by gs. The box inherits the space dimension of gs.
| gs | The generator system describing the polyhedron to be approximated. | |
| dummy | A dummy tag to syntactically differentiate this one from the other constructors. |
| std::invalid_argument | Thrown if the system of generators is not empty but has no points. |
Definition at line 100 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::swap().
00100 { 00101 // Recycling is useless: just delegate. 00102 Box<ITV> tmp(gs); 00103 this->swap(tmp); 00104 }
| Parma_Polyhedra_Library::Box< ITV >::Box | ( | const Congruence_System & | cgs | ) | [inline, explicit] |
Builds the smallest box containing the grid defined by a system of congruences cgs. The box inherits the space dimension of cgs.
| cgs | A system of congruences: congruences that are not non-relational equality constraints are ignored (though they may have contributed to the space dimension). |
Definition at line 86 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::add_congruences_no_check(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Congruence_System::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.
00087 : seq(cgs.space_dimension() <= max_space_dimension() 00088 ? cgs.space_dimension() 00089 : (throw_space_dimension_overflow("Box(cgs)", 00090 "cgs exceeds the maximum " 00091 "allowed space dimension"), 00092 cgs.space_dimension())), 00093 status() { 00094 // FIXME: check whether we can avoid the double initialization. 00095 for (dimension_type i = cgs.space_dimension(); i-- > 0; ) 00096 seq[i].assign(UNIVERSE); 00097 add_congruences_no_check(cgs); 00098 }
| Parma_Polyhedra_Library::Box< ITV >::Box | ( | const Congruence_System & | cgs, | |
| Recycle_Input | dummy | |||
| ) | [inline] |
Builds the smallest box containing the grid defined by a system of congruences cgs, recycling cgs. The box inherits the space dimension of cgs.
| cgs | A system of congruences: congruences that are not non-relational equality constraints are ignored (though they will contribute to the space dimension). | |
| dummy | A dummy tag to syntactically differentiate this one from the other constructors. |
Definition at line 108 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::swap().
00108 { 00109 // Recycling is useless: just delegate. 00110 Box<ITV> tmp(cgs); 00111 this->swap(tmp); 00112 }
| Parma_Polyhedra_Library::Box< ITV >::Box | ( | const BD_Shape< T > & | bds, | |
| Complexity_Class | complexity = POLYNOMIAL_COMPLEXITY | |||
| ) | [inline, explicit] |
Builds a box containing the BDS bds.
Builds the smallest box containing bds using a polynomial algorithm. The complexity argument is ignored.
Definition at line 224 of file Box.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::set_empty_up_to_date(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), and Parma_Polyhedra_Library::Box< ITV >::space_dimension().
00225 : seq(bds.space_dimension() <= max_space_dimension() 00226 ? bds.space_dimension() 00227 : (throw_space_dimension_overflow("Box(bds)", 00228 "bds exceeds the maximum " 00229 "allowed space dimension"), 00230 bds.space_dimension())), 00231 status() { 00232 // Expose all the interval constraints. 00233 bds.shortest_path_closure_assign(); 00234 if (bds.marked_empty()) { 00235 set_empty(); 00236 PPL_ASSERT(OK()); 00237 return; 00238 } 00239 00240 // The empty flag will be meaningful, whatever happens from now on. 00241 set_empty_up_to_date(); 00242 00243 const dimension_type space_dim = space_dimension(); 00244 if (space_dim == 0) { 00245 PPL_ASSERT(OK()); 00246 return; 00247 } 00248 00249 typedef typename BD_Shape<T>::coefficient_type Coeff; 00250 PPL_DIRTY_TEMP(Coeff, tmp); 00251 const DB_Row<Coeff>& dbm_0 = bds.dbm[0]; 00252 for (dimension_type i = space_dim; i-- > 0; ) { 00253 I_Constraint<Coeff> lower; 00254 I_Constraint<Coeff> upper; 00255 ITV& seq_i = seq[i]; 00256 00257 // Set the upper bound. 00258 const Coeff& u = dbm_0[i+1]; 00259 if (!is_plus_infinity(u)) 00260 upper.set(LESS_OR_EQUAL, u, true); 00261 00262 // Set the lower bound. 00263 const Coeff& negated_l = bds.dbm[i+1][0]; 00264 if (!is_plus_infinity(negated_l)) { 00265 neg_assign_r(tmp, negated_l, ROUND_DOWN); 00266 lower.set(GREATER_OR_EQUAL, tmp); 00267 } 00268 00269 seq_i.build(lower, upper); 00270 } 00271 PPL_ASSERT(OK()); 00272 }
| Parma_Polyhedra_Library::Box< ITV >::Box | ( | const Octagonal_Shape< T > & | oct, | |
| Complexity_Class | complexity = POLYNOMIAL_COMPLEXITY | |||
| ) | [inline, explicit] |
Builds a box containing the octagonal shape oct.
Builds the smallest box containing oct using a polynomial algorithm. The complexity argument is ignored.
Definition at line 276 of file Box.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, 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::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::set_empty_up_to_date(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().
00277 : seq(oct.space_dimension() <= max_space_dimension() 00278 ? oct.space_dimension() 00279 : (throw_space_dimension_overflow("Box(oct)", 00280 "oct exceeds the maximum " 00281 "allowed space dimension"), 00282 oct.space_dimension())), 00283 status() { 00284 // Expose all the interval constraints. 00285 oct.strong_closure_assign(); 00286 if (oct.marked_empty()) { 00287 set_empty(); 00288 return; 00289 } 00290 00291 // The empty flag will be meaningful, whatever happens from now on. 00292 set_empty_up_to_date(); 00293 00294 const dimension_type space_dim = space_dimension(); 00295 if (space_dim == 0) 00296 return; 00297 00298 PPL_DIRTY_TEMP0(mpq_class, lbound); 00299 PPL_DIRTY_TEMP0(mpq_class, ubound); 00300 for (dimension_type i = space_dim; i-- > 0; ) { 00301 typedef typename Octagonal_Shape<T>::coefficient_type Coeff; 00302 I_Constraint<mpq_class> lower; 00303 I_Constraint<mpq_class> upper; 00304 ITV& seq_i = seq[i]; 00305 const dimension_type ii = 2*i; 00306 const dimension_type cii = ii + 1; 00307 00308 // Set the upper bound. 00309 const Coeff& twice_ub = oct.matrix[cii][ii]; 00310 if (!is_plus_infinity(twice_ub)) { 00311 assign_r(ubound, twice_ub, ROUND_NOT_NEEDED); 00312 div_2exp_assign_r(ubound, ubound, 1, ROUND_NOT_NEEDED); 00313 upper.set(LESS_OR_EQUAL, ubound); 00314 } 00315 00316 // Set the lower bound. 00317 const Coeff& twice_lb = oct.matrix[ii][cii]; 00318 if (!is_plus_infinity(twice_lb)) { 00319 assign_r(lbound, twice_lb, ROUND_NOT_NEEDED); 00320 neg_assign_r(lbound, lbound, ROUND_NOT_NEEDED); 00321 div_2exp_assign_r(lbound, lbound, 1, ROUND_NOT_NEEDED); 00322 lower.set(GREATER_OR_EQUAL, lbound); 00323 } 00324 seq_i.build(lower, upper); 00325 } 00326 }
| Parma_Polyhedra_Library::Box< ITV >::Box | ( | const Polyhedron & | ph, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline, explicit] |
Builds a box containing the polyhedron ph.
Builds a box containing ph using algorithms whose complexity does not exceed the one specified by complexity. If complexity is ANY_COMPLEXITY, then the built box is the smallest one containing ph.
Definition at line 329 of file Box.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::assign_r(), Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Polyhedron::constraints(), Parma_Polyhedra_Library::Polyhedron::constraints_are_up_to_date(), 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::GREATER_OR_EQUAL, Parma_Polyhedra_Library::Polyhedron::has_pending_constraints(), Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::is_canonical(), Parma_Polyhedra_Library::Polyhedron::is_empty(), Parma_Polyhedra_Library::MIP_Problem::is_satisfiable(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::Polyhedron::marked_empty(), Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::MINIMIZATION, Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, Parma_Polyhedra_Library::MIP_Problem::optimizing_point(), Parma_Polyhedra_Library::POLYNOMIAL_COMPLEXITY, Parma_Polyhedra_Library::Box< ITV >::propagate_constraints_no_check(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::set_empty_up_to_date(), Parma_Polyhedra_Library::MIP_Problem::set_objective_function(), Parma_Polyhedra_Library::MIP_Problem::set_optimization_mode(), Parma_Polyhedra_Library::SIMPLEX_COMPLEXITY, Parma_Polyhedra_Library::Polyhedron::simplified_constraints(), Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::Polyhedron::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::swap(), and Parma_Polyhedra_Library::UNIVERSE.
00330 : seq(ph.space_dimension() <= max_space_dimension() 00331 ? ph.space_dimension() 00332 : (throw_space_dimension_overflow("Box(ph)", 00333 "ph exceeds the maximum " 00334 "allowed space dimension"), 00335 ph.space_dimension())), 00336 status() { 00337 // The empty flag will be meaningful, whatever happens from now on. 00338 set_empty_up_to_date(); 00339 00340 // We do not need to bother about `complexity' if: 00341 // a) the polyhedron is already marked empty; or ... 00342 if (ph.marked_empty()) { 00343 set_empty(); 00344 return; 00345 } 00346 00347 // b) the polyhedron is zero-dimensional; or ... 00348 const dimension_type space_dim = ph.space_dimension(); 00349 if (space_dim == 0) 00350 return; 00351 00352 // c) the polyhedron is already described by a generator system. 00353 if (ph.generators_are_up_to_date() && !ph.has_pending_constraints()) { 00354 Box tmp(ph.generators()); 00355 swap(tmp); 00356 return; 00357 } 00358 00359 // Here generators are not up-to-date or there are pending constraints. 00360 PPL_ASSERT(ph.constraints_are_up_to_date()); 00361 00362 if (complexity == POLYNOMIAL_COMPLEXITY) { 00363 // FIXME: is there a way to avoid this initialization? 00364 for (dimension_type i = space_dim; i-- > 0; ) 00365 seq[i].assign(UNIVERSE); 00366 // Get a simplified version of the constraints. 00367 Constraint_System cs = ph.simplified_constraints(); 00368 // Propagate easy-to-find bounds from the constraints, 00369 // allowing for a limited number of iterations. 00370 // FIXME: 20 is just a wild guess. 00371 const dimension_type max_iterations = 20; 00372 propagate_constraints_no_check(cs, max_iterations); 00373 } 00374 else if (complexity == SIMPLEX_COMPLEXITY) { 00375 MIP_Problem lp(space_dim); 00376 const Constraint_System& ph_cs = ph.constraints(); 00377 if (!ph_cs.has_strict_inequalities()) 00378 lp.add_constraints(ph_cs); 00379 else 00380 // Adding to `lp' a topologically closed version of `ph_cs'. 00381 for (Constraint_System::const_iterator i = ph_cs.begin(), 00382 ph_cs_end = ph_cs.end(); i != ph_cs_end; ++i) { 00383 const Constraint& c = *i; 00384 if (c.is_strict_inequality()) 00385 lp.add_constraint(Linear_Expression(c) >= 0); 00386 else 00387 lp.add_constraint(c); 00388 } 00389 // Check for unsatisfiability. 00390 if (!lp.is_satisfiable()) { 00391 set_empty(); 00392 return; 00393 } 00394 // Get all the bounds for the space dimensions. 00395 Generator g(point()); 00396 PPL_DIRTY_TEMP0(mpq_class, lbound); 00397 PPL_DIRTY_TEMP0(mpq_class, ubound); 00398 PPL_DIRTY_TEMP(Coefficient, bound_num); 00399 PPL_DIRTY_TEMP(Coefficient, bound_den); 00400 for (dimension_type i = space_dim; i-- > 0; ) { 00401 I_Constraint<mpq_class> lower; 00402 I_Constraint<mpq_class> upper; 00403 ITV& seq_i = seq[i]; 00404 lp.set_objective_function(Variable(i)); 00405 // Evaluate upper bound. 00406 lp.set_optimization_mode(MAXIMIZATION); 00407 if (lp.solve() == OPTIMIZED_MIP_PROBLEM) { 00408 g = lp.optimizing_point(); 00409 lp.evaluate_objective_function(g, bound_num, bound_den); 00410 assign_r(ubound.get_num(), bound_num, ROUND_NOT_NEEDED); 00411 assign_r(ubound.get_den(), bound_den, ROUND_NOT_NEEDED); 00412 PPL_ASSERT(is_canonical(ubound)); 00413 upper.set(LESS_OR_EQUAL, ubound); 00414 } 00415 // Evaluate optimal lower bound. 00416 lp.set_optimization_mode(MINIMIZATION); 00417 if (lp.solve() == OPTIMIZED_MIP_PROBLEM) { 00418 g = lp.optimizing_point(); 00419 lp.evaluate_objective_function(g, bound_num, bound_den); 00420 assign_r(lbound.get_num(), bound_num, ROUND_NOT_NEEDED); 00421 assign_r(lbound.get_den(), bound_den, ROUND_NOT_NEEDED); 00422 PPL_ASSERT(is_canonical(lbound)); 00423 lower.set(GREATER_OR_EQUAL, lbound); 00424 } 00425 seq_i.build(lower, upper); 00426 } 00427 } 00428 else { 00429 PPL_ASSERT(complexity == ANY_COMPLEXITY); 00430 if (ph.is_empty()) 00431 set_empty(); 00432 else { 00433 Box tmp(ph.generators()); 00434 swap(tmp); 00435 } 00436 } 00437 }
| Parma_Polyhedra_Library::Box< ITV >::Box | ( | const Grid & | ph, | |
| Complexity_Class | complexity = POLYNOMIAL_COMPLEXITY | |||
| ) | [inline, explicit] |
Builds a box containing the grid gr.
Builds the smallest box containing gr using a polynomial algorithm. The complexity argument is ignored.
Definition at line 440 of file Box.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Grid_Generator_System::empty(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::Grid::gen_sys, Parma_Polyhedra_Library::Grid::generators_are_up_to_date(), Parma_Polyhedra_Library::Grid::marked_empty(), Parma_Polyhedra_Library::Grid::maximize(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::set_empty_up_to_date(), Parma_Polyhedra_Library::Grid::space_dimension(), Parma_Polyhedra_Library::UNIVERSE, and Parma_Polyhedra_Library::Grid::update_generators().
00441 : seq(gr.space_dimension() <= max_space_dimension() 00442 ? gr.space_dimension() 00443 : (throw_space_dimension_overflow("Box(gr)", 00444 "gr exceeds the maximum " 00445 "allowed space dimension"), 00446 gr.space_dimension())), 00447 status() { 00448 00449 // FIXME: here we are not taking advantage of intervals with restrictions! 00450 00451 if (gr.marked_empty()) { 00452 set_empty(); 00453 return; 00454 } 00455 00456 // The empty flag will be meaningful, whatever happens from now on. 00457 set_empty_up_to_date(); 00458 00459 const dimension_type space_dim = gr.space_dimension(); 00460 00461 if (space_dim == 0) 00462 return; 00463 00464 if (!gr.generators_are_up_to_date() && !gr.update_generators()) { 00465 // Updating found the grid empty. 00466 set_empty(); 00467 return; 00468 } 00469 00470 PPL_ASSERT(!gr.gen_sys.empty()); 00471 00472 // For each dimension that is bounded by the grid, set both bounds 00473 // of the interval to the value of the associated coefficient in a 00474 // generator point. 00475 PPL_DIRTY_TEMP0(mpq_class, bound); 00476 PPL_DIRTY_TEMP(Coefficient, bound_num); 00477 PPL_DIRTY_TEMP(Coefficient, bound_den); 00478 for (dimension_type i = space_dim; i-- > 0; ) { 00479 ITV& seq_i = seq[i]; 00480 Variable var(i); 00481 bool max; 00482 if (gr.maximize(var, bound_num, bound_den, max)) { 00483 assign_r(bound.get_num(), bound_num, ROUND_NOT_NEEDED); 00484 assign_r(bound.get_den(), bound_den, ROUND_NOT_NEEDED); 00485 bound.canonicalize(); 00486 seq_i.build(i_constraint(EQUAL, bound)); 00487 } 00488 else 00489 seq_i.assign(UNIVERSE); 00490 } 00491 }
| Parma_Polyhedra_Library::Box< ITV >::Box | ( | const Partially_Reduced_Product< D1, D2, R > & | dp, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline, explicit] |
Builds a box containing the partially reduced product dp.
Builds a box containing ph using algorithms whose complexity does not exceed the one specified by complexity.
Definition at line 495 of file Box.templates.hh.
References Parma_Polyhedra_Library::Partially_Reduced_Product< D1, D2, R >::domain1(), Parma_Polyhedra_Library::Partially_Reduced_Product< D1, D2, R >::domain2(), Parma_Polyhedra_Library::Box< ITV >::max_space_dimension(), Parma_Polyhedra_Library::Partially_Reduced_Product< D1, D2, R >::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::swap(), and Parma_Polyhedra_Library::Box< ITV >::throw_space_dimension_overflow().
00497 : seq(), status() { 00498 if (dp.space_dimension() > max_space_dimension()) 00499 throw_space_dimension_overflow("Box(dp)", 00500 "dp exceeds the maximum " 00501 "allowed space dimension"); 00502 Box tmp1(dp.domain1(), complexity); 00503 Box tmp2(dp.domain2(), complexity); 00504 tmp1.intersection_assign(tmp2); 00505 swap(tmp1); 00506 }
| void Parma_Polyhedra_Library::Box< ITV >::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 box domain. |
Definition at line 327 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::add_congruence_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Congruence::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
00327 { 00328 const dimension_type cg_space_dim = cg.space_dimension(); 00329 // Dimension-compatibility check. 00330 if (cg_space_dim > space_dimension()) 00331 throw_dimension_incompatible("add_congruence(cg)", cg); 00332 00333 add_congruence_no_check(cg); 00334 }
| void Parma_Polyhedra_Library::Box< ITV >::add_congruence_no_check | ( | const Congruence & | cg | ) | [inline, private] |
WRITE ME.
Definition at line 2170 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::add_interval_constraint_no_check(), Parma_Polyhedra_Library::Congruence::coefficient(), Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::extract_interval_congruence(), Parma_Polyhedra_Library::Congruence::inhomogeneous_term(), 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::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Congruence::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_generic().
Referenced by Parma_Polyhedra_Library::Box< ITV >::add_congruence(), and Parma_Polyhedra_Library::Box< ITV >::add_congruences_no_check().
02170 { 02171 const dimension_type cg_space_dim = cg.space_dimension(); 02172 PPL_ASSERT(cg_space_dim <= space_dimension()); 02173 02174 // Set aside the case of proper congruences. 02175 if (cg.is_proper_congruence()) { 02176 if (cg.is_inconsistent()) { 02177 set_empty(); 02178 return; 02179 } 02180 else if (cg.is_tautological()) 02181 return; 02182 else 02183 // FIXME: what about intervals with restrictions? 02184 throw_generic("add_congruence(cg)", 02185 "cg is a nontrivial proper congruence"); 02186 } 02187 02188 PPL_ASSERT(cg.is_equality()); 02189 dimension_type cg_num_vars = 0; 02190 dimension_type cg_only_var = 0; 02191 // Throw an exception if c is not an interval congruence. 02192 if (!extract_interval_congruence(cg, cg_space_dim, cg_num_vars, cg_only_var)) 02193 throw_generic("add_congruence(cg)", "cg is not an interval congruence"); 02194 02195 // Avoid doing useless work if the box is known to be empty. 02196 if (marked_empty()) 02197 return; 02198 02199 const Coefficient& n = cg.inhomogeneous_term(); 02200 if (cg_num_vars == 0) { 02201 // Dealing with a trivial equality congruence. 02202 if (n != 0) 02203 set_empty(); 02204 return; 02205 } 02206 02207 PPL_ASSERT(cg_num_vars == 1); 02208 const Coefficient& d = cg.coefficient(Variable(cg_only_var)); 02209 add_interval_constraint_no_check(cg_only_var, Constraint::EQUALITY, n, d); 02210 }
| void Parma_Polyhedra_Library::Box< ITV >::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 box domain. |
Definition at line 338 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::add_congruences_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Congruence_System::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Box< ITV >::add_recycled_congruences().
00338 { 00339 if (cgs.space_dimension() > space_dimension()) 00340 throw_dimension_incompatible("add_congruences(cgs)", cgs); 00341 add_congruences_no_check(cgs); 00342 }
| void Parma_Polyhedra_Library::Box< ITV >::add_congruences_no_check | ( | const Congruence_System & | cgs | ) | [inline, private] |
WRITE ME.
Definition at line 2214 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::add_congruence_no_check(), Parma_Polyhedra_Library::Congruence_System::begin(), Parma_Polyhedra_Library::Congruence_System::end(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Congruence_System::space_dimension().
Referenced by Parma_Polyhedra_Library::Box< ITV >::add_congruences(), and Parma_Polyhedra_Library::Box< ITV >::Box().
02214 { 02215 PPL_ASSERT(cgs.space_dimension() <= space_dimension()); 02216 // Note: even when the box is known to be empty, we need to go 02217 // through all the congruences to fulfill the method's contract 02218 // for what concerns exception throwing. 02219 for (Congruence_System::const_iterator i = cgs.begin(), 02220 cgs_end = cgs.end(); i != cgs_end; ++i) 02221 add_congruence_no_check(*i); 02222 PPL_ASSERT(OK()); 02223 }
| void Parma_Polyhedra_Library::Box< ITV >::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 Box domain. |
Definition at line 300 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::add_constraint_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
00300 { 00301 const dimension_type c_space_dim = c.space_dimension(); 00302 // Dimension-compatibility check. 00303 if (c_space_dim > space_dimension()) 00304 throw_dimension_incompatible("add_constraint(c)", c); 00305 00306 add_constraint_no_check(c); 00307 }
| void Parma_Polyhedra_Library::Box< ITV >::add_constraint_no_check | ( | const Constraint & | c | ) | [inline, private] |
WRITE ME.
Definition at line 2120 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::add_interval_constraint_no_check(), Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Box< ITV >::extract_interval_constraint(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::throw_generic(), and Parma_Polyhedra_Library::Constraint::type().
Referenced by Parma_Polyhedra_Library::Box< ITV >::add_constraint(), and Parma_Polyhedra_Library::Box< ITV >::add_constraints_no_check().
02120 { 02121 const dimension_type c_space_dim = c.space_dimension(); 02122 PPL_ASSERT(c_space_dim <= space_dimension()); 02123 02124 dimension_type c_num_vars = 0; 02125 dimension_type c_only_var = 0; 02126 // Throw an exception if c is not an interval constraints. 02127 if (!extract_interval_constraint(c, c_space_dim, c_num_vars, c_only_var)) 02128 throw_generic("add_constraint(c)", "c is not an interval constraint"); 02129 02130 // Throw an exception if c is a nontrivial strict constraint 02131 // and ITV does not support open boundaries. 02132 if (c.is_strict_inequality() && c_num_vars != 0 02133 && ITV::is_always_topologically_closed()) 02134 throw_generic("add_constraint(c)", "c is a nontrivial strict constraint"); 02135 02136 // Avoid doing useless work if the box is known to be empty. 02137 if (marked_empty()) 02138 return; 02139 02140 const Coefficient& n = c.inhomogeneous_term(); 02141 if (c_num_vars == 0) { 02142 // Dealing with a trivial constraint. 02143 if (n < 0 02144 || (c.is_equality() && n != 0) 02145 || (c.is_strict_inequality() && n == 0)) 02146 set_empty(); 02147 return; 02148 } 02149 02150 PPL_ASSERT(c_num_vars == 1); 02151 const Coefficient& d = c.coefficient(Variable(c_only_var)); 02152 add_interval_constraint_no_check(c_only_var, c.type(), n, d); 02153 }
| void Parma_Polyhedra_Library::Box< ITV >::add_constraints | ( | const Constraint_System & | cs | ) | [inline] |
Adds the constraints in cs to the system of constraints defining *this.
| cs | The constraints to 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 box domain. |
Definition at line 311 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::add_constraints_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Box< ITV >::add_recycled_constraints().
00311 { 00312 // Dimension-compatibility check. 00313 if (cs.space_dimension() > space_dimension()) 00314 throw_dimension_incompatible("add_constraints(cs)", cs); 00315 00316 add_constraints_no_check(cs); 00317 }
| void Parma_Polyhedra_Library::Box< ITV >::add_constraints_no_check | ( | const Constraint_System & | cs | ) | [inline, private] |
WRITE ME.
Definition at line 2157 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::add_constraint_no_check(), Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Constraint_System::space_dimension().
Referenced by Parma_Polyhedra_Library::Box< ITV >::add_constraints(), and Parma_Polyhedra_Library::Box< ITV >::Box().
02157 { 02158 PPL_ASSERT(cs.space_dimension() <= space_dimension()); 02159 // Note: even when the box is known to be empty, we need to go 02160 // through all the constraints to fulfill the method's contract 02161 // for what concerns exception throwing. 02162 for (Constraint_System::const_iterator i = cs.begin(), 02163 cs_end = cs.end(); i != cs_end; ++i) 02164 add_constraint_no_check(*i); 02165 PPL_ASSERT(OK()); 02166 }
| void Parma_Polyhedra_Library::Box< ITV >::add_interval_constraint_no_check | ( | dimension_type | var_id, | |
| Constraint::Type | type, | |||
| Coefficient_traits::const_reference | num, | |||
| Coefficient_traits::const_reference | den | |||
| ) | [inline, private] |
WRITE ME.
Definition at line 421 of file Box.inlines.hh.
Referenced by Parma_Polyhedra_Library::Box< ITV >::add_congruence_no_check(), Parma_Polyhedra_Library::Box< ITV >::add_constraint_no_check(), Parma_Polyhedra_Library::Box< ITV >::get_limiting_box(), and Parma_Polyhedra_Library::Box< ITV >::refine_no_check().
00424 { 00425 PPL_ASSERT(!marked_empty()); 00426 PPL_ASSERT(var_id < space_dimension()); 00427 PPL_ASSERT(den != 0); 00428 refine_interval_no_check(seq[var_id], type, num, den); 00429 // FIXME: do check the value returned and set `empty' and 00430 // `empty_up_to_date' as appropriate. 00431 // This has to be done after reimplementation of intervals. 00432 reset_empty_up_to_date(); 00433 PPL_ASSERT(OK()); 00434 }
| void Parma_Polyhedra_Library::Box< 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 box domain. |
cgs upon successful or exceptional return is that it can be safely destroyed. Definition at line 346 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::add_congruences().
00346 { 00347 add_congruences(cgs); 00348 }
| void Parma_Polyhedra_Library::Box< T >::add_recycled_constraints | ( | Constraint_System & | cs | ) | [inline] |
Adds the constraints in cs to the system of constraints defining *this.
| cs | The constraints to be added. They 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 box domain. |
cs upon successful or exceptional return is that it can be safely destroyed. Definition at line 321 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::add_constraints().
00321 { 00322 add_constraints(cs); 00323 }
| void Parma_Polyhedra_Library::Box< ITV >::add_space_dimensions_and_embed | ( | dimension_type | m | ) | [inline] |
Adds m new dimensions and embeds the old box into the new space.
| m | The number of dimensions to add. |
The new dimensions will be those having the highest indexes in the new box, which is defined by a system of interval constraints in which the variables running through the new dimensions are unconstrained. For instance, when starting from the box
and adding a third dimension, the result will be the box
Definition at line 510 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, and Parma_Polyhedra_Library::UNIVERSE.
| void Parma_Polyhedra_Library::Box< ITV >::add_space_dimensions_and_project | ( | dimension_type | m | ) | [inline] |
Adds m new dimensions to the box and does not embed it in the new vector space.
| m | The number of dimensions to add. |
The new dimensions will be those having the highest indexes in the new box, which is defined by a system of bounded differences in which the variables running through the new dimensions are all constrained to be equal to 0. For instance, when starting from the box
and adding a third dimension, the result will be the box
Definition at line 522 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::OK(), and Parma_Polyhedra_Library::Box< ITV >::seq.
| dimension_type Parma_Polyhedra_Library::Box< ITV >::affine_dimension | ( | ) | const [inline] |
Returns
, if *this is empty; otherwise, returns the affine dimension of *this.
Definition at line 1270 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::seq, and Parma_Polyhedra_Library::Box< ITV >::space_dimension().
01270 { 01271 dimension_type d = space_dimension(); 01272 // A zero-space-dim box always has affine dimension zero. 01273 if (d == 0) 01274 return 0; 01275 01276 // An empty box has affine dimension zero. 01277 if (is_empty()) 01278 return 0; 01279 01280 for (dimension_type k = d; k-- > 0; ) 01281 if (seq[k].is_singleton()) 01282 --d; 01283 01284 return d; 01285 }
| void Parma_Polyhedra_Library::Box< ITV >::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 to 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 (optional argument with default value 1). |
| std::invalid_argument | Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of *this. |
Definition at line 2727 of file Box.templates.hh.
References Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Box< ITV >::throw_generic().
Referenced by Parma_Polyhedra_Library::Box< ITV >::affine_preimage().
02729 { 02730 // The denominator cannot be zero. 02731 if (denominator == 0) 02732 throw_generic("affine_image(v, e, d)", "d == 0"); 02733 02734 // Dimension-compatibility checks. 02735 const dimension_type space_dim = space_dimension(); 02736 const dimension_type expr_space_dim = expr.space_dimension(); 02737 if (space_dim < expr_space_dim) 02738 throw_dimension_incompatible("affine_image(v, e, d)", "e", expr); 02739 // `var' should be one of the dimensions of the polyhedron. 02740 const dimension_type var_space_dim = var.space_dimension(); 02741 if (space_dim < var_space_dim) 02742 throw_dimension_incompatible("affine_image(v, e, d)", "v", var); 02743 02744 if (is_empty()) 02745 return; 02746 02747 Tmp_Interval_Type expr_value, temp0, temp1; 02748 expr_value.assign(expr.inhomogeneous_term()); 02749 for (dimension_type i = expr_space_dim; i-- > 0; ) { 02750 const Coefficient& coeff = expr.coefficient(Variable(i)); 02751 if (coeff != 0) { 02752 temp0.assign(coeff); 02753 temp1.assign(seq[i]); 02754 temp0.mul_assign(temp0, temp1); 02755 expr_value.add_assign(expr_value, temp0); 02756 } 02757 } 02758 if (denominator != 1) { 02759 temp0.assign(denominator); 02760 expr_value.div_assign(expr_value, temp0); 02761 } 02762 seq[var.id()].assign(expr_value); 02763 02764 PPL_ASSERT(OK()); 02765 }
| void Parma_Polyhedra_Library::Box< ITV >::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 to 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 (optional argument with default value 1). |
| std::invalid_argument | Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of *this. |
Definition at line 2769 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::affine_image(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible(), Parma_Polyhedra_Library::Box< ITV >::throw_generic(), and Parma_Polyhedra_Library::UNIVERSE.
02772 { 02773 // The denominator cannot be zero. 02774 if (denominator == 0) 02775 throw_generic("affine_preimage(v, e, d)", "d == 0"); 02776 02777 // Dimension-compatibility checks. 02778 const dimension_type x_space_dim = space_dimension(); 02779 const dimension_type expr_space_dim = expr.space_dimension(); 02780 if (x_space_dim < expr_space_dim) 02781 throw_dimension_incompatible("affine_preimage(v, e, d)", "e", expr); 02782 // `var' should be one of the dimensions of the polyhedron. 02783 const dimension_type var_space_dim = var.space_dimension(); 02784 if (x_space_dim < var_space_dim) 02785 throw_dimension_incompatible("affine_preimage(v, e, d)", "v", var); 02786 02787 if (is_empty()) 02788 return; 02789 02790 const Coefficient& expr_v = expr.coefficient(var); 02791 const bool invertible = (expr_v != 0); 02792 if (!invertible) { 02793 Tmp_Interval_Type expr_value, temp0, temp1; 02794 expr_value.assign(expr.inhomogeneous_term()); 02795 for (dimension_type i = expr_space_dim; i-- > 0; ) { 02796 const Coefficient& coeff = expr.coefficient(Variable(i)); 02797 if (coeff != 0) { 02798 temp0.assign(coeff); 02799 temp1.assign(seq[i]); 02800 temp0.mul_assign(temp0, temp1); 02801 expr_value.add_assign(expr_value, temp0); 02802 } 02803 } 02804 if (denominator != 1) { 02805 temp0.assign(denominator); 02806 expr_value.div_assign(expr_value, temp0); 02807 } 02808 ITV& x_seq_v = seq[var.id()]; 02809 expr_value.intersect_assign(x_seq_v); 02810 if (expr_value.is_empty()) 02811 set_empty(); 02812 else 02813 x_seq_v.assign(UNIVERSE); 02814 } 02815 else { 02816 // The affine transformation is invertible. 02817 // CHECKME: for efficiency, would it be meaningful to avoid 02818 // the computation of inverse by partially evaluating the call 02819 // to affine_image? 02820 Linear_Expression inverse; 02821 inverse -= expr; 02822 inverse += (expr_v + denominator) * var; 02823 affine_image(var, inverse, expr_v); 02824 } 02825 PPL_ASSERT(OK()); 02826 }
| void Parma_Polyhedra_Library::Box< ITV >::ascii_dump | ( | std::ostream & | s | ) | const [inline] |
Writes to s an ASCII representation of *this.
Definition at line 3908 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::ascii_dump(), Parma_Polyhedra_Library::Box< ITV >::Status::ascii_dump(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::status.
03908 { 03909 const char separator = ' '; 03910 status.ascii_dump(s); 03911 const dimension_type space_dim = space_dimension(); 03912 s << "space_dim" << separator << space_dim; 03913 s << "\n"; 03914 for (dimension_type i = 0; i < space_dim; ++i) 03915 seq[i].ascii_dump(s); 03916 }
| void Parma_Polyhedra_Library::Box< ITV >::ascii_dump | ( | ) | const |
Writes to std::cerr an ASCII representation of *this.
Referenced by Parma_Polyhedra_Library::Box< ITV >::ascii_dump().
| bool Parma_Polyhedra_Library::Box< ITV >::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 3922 of file Box.templates.hh.
03922 { 03923 if (!status.ascii_load(s)) 03924 return false; 03925 03926 std::string str; 03927 dimension_type space_dim; 03928 if (!(s >> str) || str != "space_dim") 03929 return false; 03930 if (!(s >> space_dim)) 03931 return false; 03932 03933 seq.clear(); 03934 ITV seq_i; 03935 for (dimension_type i = 0; i < space_dim; ++i) { 03936 if (seq_i.ascii_load(s)) 03937 seq.push_back(seq_i); 03938 else 03939 return false; 03940 } 03941 03942 // Check invariants. 03943 PPL_ASSERT(OK()); 03944 return true; 03945 }
| void Parma_Polyhedra_Library::Box< ITV >::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 2831 of file Box.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), 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::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.
02834 { 02835 // The denominator cannot be zero. 02836 if (denominator == 0) 02837 throw_generic("bounded_affine_image(v, lb, ub, d)", "d == 0"); 02838 02839 // Dimension-compatibility checks. 02840 const dimension_type space_dim = space_dimension(); 02841 // The dimension of `lb_expr' and `ub_expr' should not be 02842 // greater than the dimension of `*this'. 02843 const dimension_type lb_space_dim = lb_expr.space_dimension(); 02844 if (space_dim < lb_space_dim) 02845 throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)", 02846 "lb", lb_expr); 02847 const dimension_type ub_space_dim = ub_expr.space_dimension(); 02848 if (space_dim < ub_space_dim) 02849 throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)", 02850 "ub", ub_expr); 02851 // `var' should be one of the dimensions of the box. 02852 const dimension_type var_space_dim = var.space_dimension(); 02853 if (space_dim < var_space_dim) 02854 throw_dimension_incompatible("affine_image(v, e, d)", "v", var); 02855 02856 // Any image of an empty box is empty. 02857 if (is_empty()) 02858 return; 02859 02860 // Add the constraint implied by the `lb_expr' and `ub_expr'. 02861 if (denominator > 0) 02862 refine_with_constraint(lb_expr <= ub_expr); 02863 else 02864 refine_with_constraint(lb_expr >= ub_expr); 02865 02866 // Check whether `var' occurs in `lb_expr' and/or `ub_expr'. 02867 if (lb_expr.coefficient(var) == 0) { 02868 // Here `var' can only occur in `ub_expr'. 02869 generalized_affine_image(var, 02870 LESS_OR_EQUAL, 02871 ub_expr, 02872 denominator); 02873 if (denominator > 0) 02874 refine_with_constraint(lb_expr <= denominator*var); 02875 else 02876 refine_with_constraint(denominator*var <= lb_expr); 02877 } 02878 else if (ub_expr.coefficient(var) == 0) { 02879 // Here `var' can only occur in `lb_expr'. 02880 generalized_affine_image(var, 02881 GREATER_OR_EQUAL, 02882 lb_expr, 02883 denominator); 02884 if (denominator > 0) 02885 refine_with_constraint(denominator*var <= ub_expr); 02886 else 02887 refine_with_constraint(ub_expr <= denominator*var); 02888 } 02889 else { 02890 // Here `var' occurs in both `lb_expr' and `ub_expr'. As boxes 02891 // can only use the non-relational constraints, we find the 02892 // maximum/minimum values `ub_expr' and `lb_expr' obtain with the 02893 // box and use these instead of the `ub-expr' and `lb-expr'. 02894 PPL_DIRTY_TEMP(Coefficient, max_num); 02895 PPL_DIRTY_TEMP(Coefficient, max_den); 02896 bool max_included; 02897 PPL_DIRTY_TEMP(Coefficient, min_num); 02898 PPL_DIRTY_TEMP(Coefficient, min_den); 02899 bool min_included; 02900 ITV& seq_v = seq[var.id()]; 02901 if (maximize(ub_expr, max_num, max_den, max_included)) { 02902 if (minimize(lb_expr, min_num, min_den, min_included)) { 02903 // The `ub_expr' has a maximum value and the `lb_expr' 02904 // has a minimum value for the box. 02905 // Set the bounds for `var' using the minimum for `lb_expr'. 02906 min_den *= denominator; 02907 PPL_DIRTY_TEMP0(mpq_class, q1); 02908 PPL_DIRTY_TEMP0(mpq_class, q2); 02909 assign_r(q1.get_num(), min_num, ROUND_NOT_NEEDED); 02910 assign_r(q1.get_den(), min_den, ROUND_NOT_NEEDED); 02911 q1.canonicalize(); 02912 // Now make the maximum of lb_expr the upper bound. If the 02913 // maximum is not at a box point, then inequality is strict. 02914 max_den *= denominator; 02915 assign_r(q2.get_num(), max_num, ROUND_NOT_NEEDED); 02916 assign_r(q2.get_den(), max_den, ROUND_NOT_NEEDED); 02917 q2.canonicalize(); 02918 if (denominator > 0) 02919 seq_v.build(i_constraint(min_included ? GREATER_OR_EQUAL : GREATER_THAN, q1), 02920 i_constraint(max_included ? LESS_OR_EQUAL : LESS_THAN, q2)); 02921 else 02922 seq_v.build(i_constraint(max_included ? GREATER_OR_EQUAL : GREATER_THAN, q2), 02923 i_constraint(min_included ? LESS_OR_EQUAL : LESS_THAN, q1)); 02924 } 02925 else { 02926 // The `ub_expr' has a maximum value but the `lb_expr' 02927 // has no minimum value for the box. 02928 // Set the bounds for `var' using the maximum for `lb_expr'. 02929 PPL_DIRTY_TEMP0(mpq_class, q); 02930 max_den *= denominator; 02931 assign_r(q.get_num(), max_num, ROUND_NOT_NEEDED); 02932 assign_r(q.get_den(), max_den, ROUND_NOT_NEEDED); 02933 q.canonicalize(); 02934 if (denominator > 0) 02935 seq_v.build(i_constraint(max_included ? LESS_OR_EQUAL : LESS_THAN, q)); 02936 else 02937 seq_v.build(i_constraint(max_included ? GREATER_OR_EQUAL : GREATER_THAN, q)); 02938 } 02939 } 02940 else if (minimize(lb_expr, min_num, min_den, min_included)) { 02941 // The `ub_expr' has no maximum value but the `lb_expr' 02942 // has a minimum value for the box. 02943 // Set the bounds for `var' using the minimum for `lb_expr'. 02944 min_den *= denominator; 02945 PPL_DIRTY_TEMP0(mpq_class, q); 02946 assign_r(q.get_num(), min_num, ROUND_NOT_NEEDED); 02947 assign_r(q.get_den(), min_den, ROUND_NOT_NEEDED); 02948 q.canonicalize(); 02949 if (denominator > 0) 02950 seq_v.build(i_constraint(min_included ? GREATER_OR_EQUAL : GREATER_THAN, q)); 02951 else 02952 seq_v.build(i_constraint(min_included ? LESS_OR_EQUAL : LESS_THAN, q)); 02953 } 02954 else { 02955 // The `ub_expr' has no maximum value and the `lb_expr' 02956 // has no minimum value for the box. 02957 // So we set the bounds to be unbounded. 02958 seq_v.assign(UNIVERSE); 02959 } 02960 } 02961 PPL_ASSERT(OK()); 02962 }
| void Parma_Polyhedra_Library::Box< ITV >::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 2967 of file Box.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), 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, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and Parma_Polyhedra_Library::Variable::space_dimension().
02970 { 02971 // The denominator cannot be zero. 02972 const dimension_type space_dim = space_dimension(); 02973 if (denominator == 0) 02974 throw_generic("bounded_affine_preimage(v, lb, ub, d)", "d == 0"); 02975 02976 // Dimension-compatibility checks. 02977 // `var' should be one of the dimensions of the polyhedron. 02978 const dimension_type var_space_dim = var.space_dimension(); 02979 if (space_dim < var_space_dim) 02980 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)", 02981 "v", var); 02982 // The dimension of `lb_expr' and `ub_expr' should not be 02983 // greater than the dimension of `*this'. 02984 const dimension_type lb_space_dim = lb_expr.space_dimension(); 02985 if (space_dim < lb_space_dim) 02986 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)", 02987 "lb", lb_expr); 02988 const dimension_type ub_space_dim = ub_expr.space_dimension(); 02989 if (space_dim < ub_space_dim) 02990 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)", 02991 "ub", ub_expr); 02992 02993 // Any preimage of an empty polyhedron is empty. 02994 if (marked_empty()) 02995 return; 02996 02997 const bool negative_denom = (denominator < 0); 02998 const Coefficient& lb_var_coeff = lb_expr.coefficient(var); 02999 const Coefficient& ub_var_coeff = ub_expr.coefficient(var); 03000 03001 // If the implied constraint between `ub_expr and `lb_expr' is 03002 // independent of `var', then impose it now. 03003 if (lb_var_coeff == ub_var_coeff) { 03004 if (negative_denom) 03005 refine_with_constraint(lb_expr >= ub_expr); 03006 else 03007 refine_with_constraint(lb_expr <= ub_expr); 03008 } 03009 03010 ITV& seq_var = seq[var.id()]; 03011 if (!seq_var.is_universe()) { 03012 // We want to work with a positive denominator, 03013 // so the sign and its (unsigned) value are separated. 03014 PPL_DIRTY_TEMP_COEFFICIENT(pos_denominator); 03015 pos_denominator = denominator; 03016 if (negative_denom) 03017 neg_assign(pos_denominator, pos_denominator); 03018 // Store all the information about the upper and lower bounds 03019 // for `var' before making this interval unbounded. 03020 bool open_lower = seq_var.lower_is_open(); 03021 bool unbounded_lower = seq_var.lower_is_boundary_infinity(); 03022 PPL_DIRTY_TEMP0(mpq_class, q_seq_var_lower); 03023 PPL_DIRTY_TEMP(Coefficient, num_lower); 03024 PPL_DIRTY_TEMP(Coefficient, den_lower); 03025 if (!unbounded_lower) { 03026 assign_r(q_seq_var_lower, seq_var.lower(), ROUND_NOT_NEEDED); 03027 assign_r(num_lower, q_seq_var_lower.get_num(), ROUND_NOT_NEEDED); 03028 assign_r(den_lower, q_seq_var_lower.get_den(), ROUND_NOT_NEEDED); 03029 if (negative_denom) 03030 neg_assign(den_lower, den_lower); 03031 num_lower *= pos_denominator; 03032 seq_var.lower_extend(); 03033 } 03034 bool open_upper = seq_var.upper_is_open(); 03035 bool unbounded_upper = seq_var.upper_is_boundary_infinity(); 03036 PPL_DIRTY_TEMP0(mpq_class, q_seq_var_upper); 03037 PPL_DIRTY_TEMP(Coefficient, num_upper); 03038 PPL_DIRTY_TEMP(Coefficient, den_upper); 03039 if (!unbounded_upper) { 03040 assign_r(q_seq_var_upper, seq_var.upper(), ROUND_NOT_NEEDED); 03041 assign_r(num_upper, q_seq_var_upper.get_num(), ROUND_NOT_NEEDED); 03042 assign_r(den_upper, q_seq_var_upper.get_den(), ROUND_NOT_NEEDED); 03043 if (negative_denom) 03044 neg_assign(den_upper, den_upper); 03045 num_upper *= pos_denominator; 03046 seq_var.upper_extend(); 03047 } 03048 03049 if (!unbounded_lower) { 03050 // `lb_expr' is revised by removing the `var' component, 03051 // multiplying by `-' denominator of the lower bound for `var', 03052 // and adding the lower bound for `var' to the inhomogeneous term. 03053 Linear_Expression revised_lb_expr(ub_expr); 03054 revised_lb_expr -= ub_var_coeff * var; 03055 PPL_DIRTY_TEMP(Coefficient, d); 03056 neg_assign(d, den_lower); 03057 revised_lb_expr *= d; 03058 revised_lb_expr += num_lower; 03059 03060 // Find the minimum value for the revised lower bound expression 03061 // and use this to refine the appropriate bound. 03062 bool included; 03063 PPL_DIRTY_TEMP(Coefficient, den); 03064 if (minimize(revised_lb_expr, num_lower, den, included)) { 03065 den_lower *= (den * ub_var_coeff); 03066 PPL_DIRTY_TEMP0(mpq_class, q); 03067 assign_r(q.get_num(), num_lower, ROUND_NOT_NEEDED); 03068 assign_r(q.get_den(), den_lower, ROUND_NOT_NEEDED); 03069 q.canonicalize(); 03070 open_lower |= !included; 03071 if ((ub_var_coeff >= 0) ? !negative_denom : negative_denom) 03072 seq_var.add_constraint(i_constraint(open_lower ? GREATER_THAN : GREATER_OR_EQUAL, q)); 03073 else 03074 seq_var.add_constraint(i_constraint(open_lower ? LESS_THAN : LESS_OR_EQUAL, q)); 03075 if (seq_var.is_empty()) { 03076 set_empty(); 03077 return; 03078 } 03079 } 03080 } 03081 03082 if (!unbounded_upper) { 03083 // `ub_expr' is revised by removing the `var' component, 03084 // multiplying by `-' denominator of the upper bound for `var', 03085 // and adding the upper bound for `var' to the inhomogeneous term. 03086 Linear_Expression revised_ub_expr(lb_expr); 03087 revised_ub_expr -= lb_var_coeff * var; 03088 PPL_DIRTY_TEMP(Coefficient, d); 03089 neg_assign(d, den_upper); 03090 revised_ub_expr *= d; 03091 revised_ub_expr += num_upper; 03092 03093 // Find the maximum value for the revised upper bound expression 03094 // and use this to refine the appropriate bound. 03095 bool included; 03096 PPL_DIRTY_TEMP(Coefficient, den); 03097 if (maximize(revised_ub_expr, num_upper, den, included)) { 03098 den_upper *= (den * lb_var_coeff); 03099 PPL_DIRTY_TEMP0(mpq_class, q); 03100 assign_r(q.get_num(), num_upper, ROUND_NOT_NEEDED); 03101 assign_r(q.get_den(), den_upper, ROUND_NOT_NEEDED); 03102 q.canonicalize(); 03103 open_upper |= !included; 03104 if ((lb_var_coeff >= 0) ? !negative_denom : negative_denom) 03105 seq_var.add_constraint(i_constraint(open_upper ? LESS_THAN : LESS_OR_EQUAL, q)); 03106 else 03107 seq_var.add_constraint(i_constraint(open_upper ? GREATER_THAN : GREATER_OR_EQUAL, q)); 03108 if (seq_var.is_empty()) { 03109 set_empty(); 03110 return; 03111 } 03112 } 03113 } 03114 } 03115 03116 // If the implied constraint between `ub_expr and `lb_expr' is 03117 // dependent on `var', then impose on the new box. 03118 if (lb_var_coeff != ub_var_coeff) { 03119 if (denominator > 0) 03120 refine_with_constraint(lb_expr <= ub_expr); 03121 else 03122 refine_with_constraint(lb_expr >= ub_expr); 03123 } 03124 03125 PPL_ASSERT(OK()); 03126 }
| bool Parma_Polyhedra_Library::Box< ITV >::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 552 of file Box.templates.hh.
References Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Box< ITV >::bounds_from_above(), and Parma_Polyhedra_Library::Box< ITV >::bounds_from_below().
00552 { 00553 // `expr' should be dimension-compatible with `*this'. 00554 const dimension_type expr_space_dim = expr.space_dimension(); 00555 const dimension_type space_dim = space_dimension(); 00556 if (space_dim < expr_space_dim) 00557 throw_dimension_incompatible((from_above 00558 ? "bounds_from_above(e)" 00559 : "bounds_from_below(e)"), "e", expr); 00560 // A zero-dimensional or empty Box bounds everything. 00561 if (space_dim == 0 || is_empty()) 00562 return true; 00563 00564 const int from_above_sign = from_above ? 1 : -1; 00565 for (dimension_type i = expr_space_dim; i-- > 0; ) 00566 switch (sgn(expr.coefficient(Variable(i))) * from_above_sign) { 00567 case 1: 00568 if (seq[i].upper_is_boundary_infinity()) 00569 return false; 00570 break; 00571 case 0: 00572 // Nothing to do. 00573 break; 00574 case -1: 00575 if (seq[i].lower_is_boundary_infinity()) 00576 return false; 00577 break; 00578 } 00579 return true; 00580 }
| bool Parma_Polyhedra_Library::Box< ITV >::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 181 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::bounds().
00181 { 00182 return bounds(expr, true); 00183 }
| bool Parma_Polyhedra_Library::Box< ITV >::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 187 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::bounds().
00187 { 00188 return bounds(expr, false); 00189 }
| bool Parma_Polyhedra_Library::Box< T >::can_recycle_congruence_systems | ( | ) | [inline, static] |
Returns false indicating that this domain does not recycle congruences.
Definition at line 358 of file Box.inlines.hh.
| bool Parma_Polyhedra_Library::Box< T >::can_recycle_constraint_systems | ( | ) | [inline, static] |
Returns false indicating that this domain does not recycle constraints.
Definition at line 352 of file Box.inlines.hh.
| Enable_If< Is_Same< T, Box< ITV > >::value &&Is_Same_Or_Derived< Interval_Base, ITV >::value, void >::type Parma_Polyhedra_Library::Box< ITV >::CC76_narrowing_assign | ( | const T & | y | ) | [inline] |
Assigns to *this the result of restoring in y the constraints of *this that were lost by CC76-extrapolation applications.
| y | A Box that must contain *this. |
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
y is meant to denote the value computed in the previous iteration step, whereas *this denotes the value computed in the current iteration step (in the decreasing iteration sequence). Hence, the call x.CC76_narrowing_assign(y) will assign to x the result of the computation
. Definition at line 3720 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::contains(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
03720 { 03721 const dimension_type space_dim = space_dimension(); 03722 03723 // Dimension-compatibility check. 03724 if (space_dim != y.space_dimension()) 03725 throw_dimension_incompatible("CC76_narrowing_assign(y)", y); 03726 03727 #ifndef NDEBUG 03728 { 03729 // We assume that `*this' is contained in or equal to `y'. 03730 const Box x_copy = *this; 03731 const Box y_copy = y; 03732 PPL_ASSERT(y_copy.contains(x_copy)); 03733 } 03734 #endif 03735 03736 // If both boxes are zero-dimensional, 03737 // since `y' contains `*this', we simply return `*this'. 03738 if (space_dim == 0) 03739 return; 03740 03741 // If `y' is empty, since `y' contains `this', `*this' is empty too. 03742 if (y.is_empty()) 03743 return; 03744 // If `*this' is empty, we return. 03745 if (is_empty()) 03746 return; 03747 03748 // Replace each constraint in `*this' by the corresponding constraint 03749 // in `y' if the corresponding inhomogeneous terms are both finite. 03750 for (dimension_type i = space_dim; i-- > 0; ) { 03751 ITV& x_i = seq[i]; 03752 const ITV& y_i = y.seq[i]; 03753 if (!x_i.lower_is_boundary_infinity() 03754 && !y_i.lower_is_boundary_infinity() 03755 && x_i.lower() != y_i.lower()) 03756 x_i.lower() = y_i.lower(); 03757 if (!x_i.upper_is_boundary_infinity() 03758 && !y_i.upper_is_boundary_infinity() 03759 && x_i.upper() != y_i.upper()) 03760 x_i.upper() = y_i.upper(); 03761 } 03762 PPL_ASSERT(OK()); 03763 }
| Enable_If< Is_Same< T, Box< ITV > >::value &&Is_Same_Or_Derived< Interval_Base, ITV >::value, void >::type Parma_Polyhedra_Library::Box< ITV >::CC76_widening_assign | ( | const T & | y, | |
| Iterator | first, | |||
| Iterator | last | |||
| ) | [inline] |
Assigns to *this the result of computing the CC76-widening between *this and y.
| y | A box that must be contained in *this. | |
| first | An iterator that points to the first stop-point. | |
| last | An iterator that points one past the last stop-point. |
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 3596 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::CC76_widening_assign(), Parma_Polyhedra_Library::Box< ITV >::OK(), and Parma_Polyhedra_Library::Box< ITV >::seq.
03596 { 03597 if (y.is_empty()) 03598 return; 03599 03600 for (dimension_type i = seq.size(); i-- > 0; ) 03601 seq[i].CC76_widening_assign(y.seq[i], first, last); 03602 03603 PPL_ASSERT(OK()); 03604 }
| Enable_If< Is_Same< T, Box< ITV > >::value &&Is_Same_Or_Derived< Interval_Base, ITV >::value, void >::type Parma_Polyhedra_Library::Box< ITV >::CC76_widening_assign | ( | const T & | y, | |
| unsigned * | tp = 0 | |||
| ) | [inline] |
Assigns to *this the result of computing the CC76-widening between *this and y.
| y | A box 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 3611 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::CC76_widening_assign(), and Parma_Polyhedra_Library::Box< ITV >::contains().
Referenced by Parma_Polyhedra_Library::Box< ITV >::CC76_widening_assign(), Parma_Polyhedra_Library::Box< ITV >::limited_CC76_extrapolation_assign(), and Parma_Polyhedra_Library::Box< ITV >::widening_assign().
03611 { 03612 static typename ITV::boundary_type stop_points[] = { 03613 typename ITV::boundary_type(-2), 03614 typename ITV::boundary_type(-1), 03615 typename ITV::boundary_type(0), 03616 typename ITV::boundary_type(1), 03617 typename ITV::boundary_type(2) 03618 }; 03619 03620 Box& x = *this; 03621 // If there are tokens available, work on a temporary copy. 03622 if (tp != 0 && *tp > 0) { 03623 Box<ITV> x_tmp(x); 03624 x_tmp.CC76_widening_assign(y, 0); 03625 // If the widening was not precise, use one of the available tokens. 03626 if (!x.contains(x_tmp)) 03627 --(*tp); 03628 return; 03629 } 03630 x.CC76_widening_assign(y, 03631 stop_points, 03632 stop_points 03633 + sizeof(stop_points)/sizeof(stop_points[0])); 03634 }
| bool Parma_Polyhedra_Library::Box< ITV >::check_empty | ( | ) | const [inline, private] |
Checks the hard way whether *this is an empty box: returns true if and only if it is so.
Definition at line 1289 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), and Parma_Polyhedra_Library::Box< ITV >::set_nonempty().
Referenced by Parma_Polyhedra_Library::Box< ITV >::is_empty(), and Parma_Polyhedra_Library::Box< ITV >::OK().
01289 { 01290 PPL_ASSERT(!marked_empty()); 01291 Box<ITV>& x = const_cast<Box<ITV>&>(*this); 01292 for (dimension_type k = seq.size(); k-- > 0; ) 01293 if (seq[k].is_empty()) { 01294 x.set_empty(); 01295 return true; 01296 } 01297 x.set_nonempty();; 01298 return false; 01299 }
| void Parma_Polyhedra_Library::Box< ITV >::concatenate_assign | ( | const Box< ITV > & | y | ) | [inline] |
Seeing a box as a set of tuples (its points), assigns to *this all the tuples that can be obtained by concatenating, in the order given, a tuple of *this with a tuple of y.
Let
and
be the boxes corresponding, on entry, to *this and y, respectively. Upon successful completion, *this will represent the box
such that
Another way of seeing it is as follows: first increases the space dimension of *this by adding y.space_dimension() new dimensions; then adds to the system of constraints of *this a renamed-apart version of the constraints of y.
Definition at line 1767 of file Box.templates.hh.
References Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::reset_empty_up_to_date(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::status, and Parma_Polyhedra_Library::Box< ITV >::Status::test_empty_up_to_date().
01767 { 01768 Box& x = *this; 01769 const dimension_type x_space_dim = x.space_dimension(); 01770 const dimension_type y_space_dim = y.space_dimension(); 01771 01772 // If `y' is marked empty, the result will be empty too. 01773 if (y.marked_empty()) 01774 x.set_empty(); 01775 01776 // If `y' is a 0-dim space box, there is nothing left to do. 01777 if (y_space_dim == 0) 01778 return; 01779 01780 // Here `y_space_dim > 0', so that a non-trivial concatenation will occur: 01781 // make sure that reallocation will occur once at most. 01782 x.seq.reserve(x_space_dim + y_space_dim); 01783 01784 // If `x' is marked empty, then it is sufficient to adjust 01785 // the dimension of the vector space. 01786 if (x.marked_empty()) { 01787 x.seq.insert(x.seq.end(), y_space_dim, ITV(EMPTY)); 01788 PPL_ASSERT(x.OK()); 01789 return; 01790 } 01791 01792 // Here neither `x' nor `y' are marked empty: concatenate them. 01793 std::copy(y.seq.begin(), y.seq.end(), 01794 std::back_insert_iterator<Sequence>(x.seq)); 01795 // Update the `empty_up_to_date' flag. 01796 if (!y.status.test_empty_up_to_date()) 01797 reset_empty_up_to_date(); 01798 01799 PPL_ASSERT(x.OK()); 01800 }
| Congruence_System Parma_Polyhedra_Library::Box< ITV >::congruences | ( | ) | const [inline] |
Returns a system of congruences approximating *this.
Definition at line 3848 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::get_lower_bound(), Parma_Polyhedra_Library::Congruence_System::insert(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Congruence_System::zero_dim_empty().
Referenced by Parma_Polyhedra_Library::Box< ITV >::minimized_congruences().
03848 { 03849 Congruence_System cgs; 03850 const dimension_type space_dim = space_dimension(); 03851 if (space_dim == 0) { 03852 if (marked_empty()) 03853 cgs = Congruence_System::zero_dim_empty(); 03854 } 03855 // Make sure emptiness is detected. 03856 else if (is_empty()) 03857 cgs.insert((0*Variable(space_dim-1) %= -1) / 0); 03858 else { 03859 // KLUDGE: in the future `cgs' will be constructed of the right dimension. 03860 // For the time being, we force the dimension with the following line. 03861 cgs.insert(0*Variable(space_dim-1) %= 0); 03862 03863 for (dimension_type k = 0; k < space_dim; ++k) { 03864 bool closed = false; 03865 PPL_DIRTY_TEMP(Coefficient, n); 03866 PPL_DIRTY_TEMP(Coefficient, d); 03867 if (get_lower_bound(k, closed, n, d) && closed) 03868 // Make sure equality congruences are detected. 03869 if (seq[k].is_singleton()) 03870 cgs.insert((d*Variable(k) %= n) / 0); 03871 } 03872 } 03873 return cgs; 03874 }
| bool Parma_Polyhedra_Library::Box< ITV >::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 1433 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::is_universe(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
01433 { 01434 // `var' should be one of the dimensions of the polyhedron. 01435 const dimension_type var_space_dim = var.space_dimension(); 01436 if (space_dimension() < var_space_dim) 01437 throw_dimension_incompatible("constrains(v)", "v", var); 01438 01439 if (marked_empty() || !seq[var_space_dim-1].is_universe()) 01440 return true; 01441 // Now force an emptiness check. 01442 return is_empty(); 01443 }
| Constraint_System Parma_Polyhedra_Library::Box< ITV >::constraints | ( | ) | const [inline] |
Returns a system of constraints defining *this.
Definition at line 3767 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::get_lower_bound(), Parma_Polyhedra_Library::Box< ITV >::get_upper_bound(), Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Constraint_System::zero_dim_empty().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape().
03767 { 03768 Constraint_System cs; 03769 const dimension_type space_dim = space_dimension(); 03770 if (space_dim == 0) { 03771 if (marked_empty()) 03772 cs = Constraint_System::zero_dim_empty(); 03773 } 03774 else if (marked_empty()) 03775 cs.insert(0*Variable(space_dim-1) <= -1); 03776 else { 03777 // KLUDGE: in the future `cs' will be constructed of the right dimension. 03778 // For the time being, we force the dimension with the following line. 03779 cs.insert(0*Variable(space_dim-1) <= 0); 03780 03781 for (dimension_type k = 0; k < space_dim; ++k) { 03782 bool closed = false; 03783 PPL_DIRTY_TEMP(Coefficient, n); 03784 PPL_DIRTY_TEMP(Coefficient, d); 03785 if (get_lower_bound(k, closed, n, d)) { 03786 if (closed) 03787 cs.insert(d*Variable(k) >= n); 03788 else 03789 cs.insert(d*Variable(k) > n); 03790 } 03791 if (get_upper_bound(k, closed, n, d)) { 03792 if (closed) 03793 cs.insert(d*Variable(k) <= n); 03794 else 03795 cs.insert(d*Variable(k) < n); 03796 } 03797 } 03798 } 03799 return cs; 03800 }
| bool Parma_Polyhedra_Library::Box< ITV >::contains | ( | const Box< ITV > & | y | ) | const [inline] |
Returns true if and only if *this contains y.
| std::invalid_argument | Thrown if x and y are dimension-incompatible. |
Definition at line 1153 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Box< ITV >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Box< ITV >::CC76_widening_assign(), Parma_Polyhedra_Library::Box< ITV >::limited_CC76_extrapolation_assign(), and Parma_Polyhedra_Library::Box< ITV >::strictly_contains().
01153 { 01154 const Box& x = *this; 01155 // Dimension-compatibility check. 01156 if (x.space_dimension() != y.space_dimension()) 01157 x.throw_dimension_incompatible("contains(y)", y); 01158 01159 // If `y' is empty, then `x' contains `y'. 01160 if (y.is_empty()) 01161 return true; 01162 01163 // If `x' is empty, then `x' cannot contain `y'. 01164 if (x.is_empty()) 01165 return false; 01166 01167 for (dimension_type k = x.seq.size(); k-- > 0; ) 01168 // FIXME: fix this name qualification issue. 01169 if (!x.seq[k].contains(y.seq[k])) 01170 return false; 01171 return true; 01172 }
| bool Parma_Polyhedra_Library::Box< ITV >::contains_integer_point | ( | ) | const [inline] |
Returns true if and only if *this contains at least one integer point.
Definition at line 1348 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), and Parma_Polyhedra_Library::Box< ITV >::seq.
01348 { 01349 if (marked_empty()) 01350 return false; 01351 for (dimension_type k = seq.size(); k-- > 0; ) 01352 if (!seq[k].contains_integer_point()) 01353 return false; 01354 return true; 01355 }
| void Parma_Polyhedra_Library::Box< ITV >::difference_assign | ( | const Box< ITV > & | y | ) | [inline] |
Assigns to *this the difference of *this and y.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 1804 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
01804 { 01805 const dimension_type space_dim = space_dimension(); 01806 01807 // Dimension-compatibility check. 01808 if (space_dim != y.space_dimension()) 01809 throw_dimension_incompatible("difference_assign(y)", y); 01810 01811 Box& x = *this; 01812 if (x.is_empty() || y.is_empty()) 01813 return; 01814 01815 switch (space_dim) { 01816 case 0: 01817 // If `x' is zero-dimensional, then at this point both `x' and `y' 01818 // are the universe box, so that their difference is empty. 01819 x.set_empty(); 01820 break; 01821 01822 case 1: 01823 x.seq[0].difference_assign(y.seq[0]); 01824 if (x.seq[0].is_empty()) 01825 x.set_empty(); 01826 break; 01827 01828 default: 01829 { 01830 dimension_type index_non_contained = space_dim; 01831 dimension_type number_non_contained = 0; 01832 for (dimension_type i = space_dim; i-- > 0; ) 01833 if (!y.seq[i].contains(x.seq[i])) { 01834 if (++number_non_contained == 1) 01835 index_non_contained = i; 01836 else 01837 break; 01838 } 01839 01840 switch (number_non_contained) { 01841 case 0: 01842 // `y' covers `x': the difference is empty. 01843 x.set_empty(); 01844 break; 01845 case 1: 01846 x.seq[index_non_contained] 01847 .difference_assign(y.seq[index_non_contained]); 01848 if (x.seq[index_non_contained].is_empty()) 01849 x.set_empty(); 01850 break; 01851 default: 01852 // Nothing to do: the difference is `x'. 01853 break; 01854 } 01855 } 01856 break; 01857 } 01858 PPL_ASSERT(OK()); 01859 }
| void Parma_Polyhedra_Library::Box< ITV >::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 1687 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::drop_some_non_integer_points(), Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Variables_Set::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
01688 { 01689 // Dimension-compatibility check. 01690 const dimension_type min_space_dim = vars.space_dimension(); 01691 if (space_dimension() < min_space_dim) 01692 throw_dimension_incompatible("drop_some_non_integer_points(vs, cmpl)", 01693 min_space_dim); 01694 01695 if (std::numeric_limits<typename ITV::boundary_type>::is_integer 01696 && !ITV::info_type::store_open) 01697 return; 01698 01699 if (marked_empty()) 01700 return; 01701 01702 for (Variables_Set::const_iterator v_i = vars.begin(), 01703 v_end = vars.end(); v_i != v_end; ++v_i) 01704 seq[*v_i].drop_some_non_integer_points(); 01705 01706 PPL_ASSERT(OK()); 01707 }
| void Parma_Polyhedra_Library::Box< ITV >::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 1671 of file Box.templates.hh.
References Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), and Parma_Polyhedra_Library::Box< ITV >::seq.
Referenced by Parma_Polyhedra_Library::Box< ITV >::drop_some_non_integer_points().
01671 { 01672 if (std::numeric_limits<typename ITV::boundary_type>::is_integer 01673 && !ITV::info_type::store_open) 01674 return; 01675 01676 if (marked_empty()) 01677 return; 01678 01679 for (dimension_type k = seq.size(); k-- > 0; ) 01680 seq[k].drop_some_non_integer_points(); 01681 01682 PPL_ASSERT(OK()); 01683 }
| void Parma_Polyhedra_Library::Box< ITV >::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 232 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Box< ITV >::max_space_dimension(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Box< ITV >::throw_generic().
00233 { 00234 const dimension_type space_dim = space_dimension(); 00235 // `var' should be one of the dimensions of the vector space. 00236 if (var.space_dimension() > space_dim) 00237 throw_dimension_incompatible("expand_space_dimension(v, m)", "v", var); 00238 00239 // The space dimension of the resulting Box should not 00240 // overflow the maximum allowed space dimension. 00241 if (m > max_space_dimension() - space_dim) 00242 throw_generic("expand_dimension(v, m)", 00243 "adding m new space dimensions exceeds " 00244 "the maximum allowed space dimension"); 00245 00246 // To expand the space dimension corresponding to variable `var', 00247 // we append to the box `m' copies of the corresponding interval. 00248 seq.insert(seq.end(), m, seq[var.id()]); 00249 PPL_ASSERT(OK()); 00250 }
| memory_size_type Parma_Polyhedra_Library::Box< ITV >::external_memory_in_bytes | ( | ) | const [inline] |
Returns the size in bytes of the memory managed by *this.
Definition at line 3878 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::seq.
Referenced by Parma_Polyhedra_Library::Box< ITV >::total_memory_in_bytes().
03878 { 03879 memory_size_type n = seq.capacity() * sizeof(ITV); 03880 for (dimension_type k = seq.size(); k-- > 0; ) 03881 n += seq[k].external_memory_in_bytes(); 03882 return n; 03883 }
| void Parma_Polyhedra_Library::Box< ITV >::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 2085 of file Box.templates.hh.
References Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::remove_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Box< ITV >::throw_generic().
02086 { 02087 const dimension_type space_dim = space_dimension(); 02088 // `dest' should be one of the dimensions of the box. 02089 if (dest.space_dimension() > space_dim) 02090 throw_dimension_incompatible("fold_space_dimensions(vs, v)", "v", dest); 02091 02092 // The folding of no dimensions is a no-op. 02093 if (vars.empty()) 02094 return; 02095 02096 // All variables in `vars' should be dimensions of the box. 02097 if (vars.space_dimension() > space_dim) 02098 throw_dimension_incompatible("fold_space_dimensions(vs, v)", 02099 vars.space_dimension()); 02100 02101 // Moreover, `dest.id()' should not occur in `vars'. 02102 if (vars.find(dest.id()) != vars.end()) 02103 throw_generic("fold_space_dimensions(vs, v)", 02104 "v should not occur in vs"); 02105 02106 // Note: the check for emptiness is needed for correctness. 02107 if (!is_empty()) { 02108 // Join the interval corresponding to variable `dest' with the intervals 02109 // corresponding to the variables in `vars'. 02110 ITV& seq_v = seq[dest.id()]; 02111 for (Variables_Set::const_iterator i = vars.begin(), 02112 vs_end = vars.end(); i != vs_end; ++i) 02113 seq_v.join_assign(seq[*i]); 02114 } 02115 remove_space_dimensions(vars); 02116 }
| bool Parma_Polyhedra_Library::Box< ITV >::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 1359 of file Box.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Checked::le, Parma_Polyhedra_Library::normalize2(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
01361 { 01362 dimension_type space_dim = space_dimension(); 01363 // The dimension of `expr' must be at most the dimension of *this. 01364 if (space_dim < expr.space_dimension()) 01365 throw_dimension_incompatible("frequency(e, ...)", "e", expr); 01366 01367 // Check if `expr' has a constant value. 01368 // If it is constant, set the frequency `freq_n' to 0 01369 // and return true. Otherwise the values for \p expr 01370 // are not discrete so return false. 01371 01372 // Space dimension = 0: if empty, then return false; 01373 // otherwise the frequency is 0 and the value is the inhomogeneous term. 01374 if (space_dim == 0) { 01375 if (is_empty()) 01376 return false; 01377 freq_n = 0; 01378 freq_d = 1; 01379 val_n = expr.inhomogeneous_term(); 01380 val_d = 1; 01381 return true; 01382 } 01383 01384 // For an empty Box, we simply return false. 01385 if (is_empty()) 01386 return false; 01387 01388 // The Box has at least 1 dimension and is not empty. 01389 PPL_DIRTY_TEMP_COEFFICIENT(coeff); 01390 PPL_DIRTY_TEMP_COEFFICIENT(num); 01391 PPL_DIRTY_TEMP_COEFFICIENT(den); 01392 PPL_DIRTY_TEMP0(mpq_class, tmp); 01393 Linear_Expression le = expr; 01394 01395 PPL_DIRTY_TEMP_COEFFICIENT(val_den); 01396 val_den = 1; 01397 01398 for (dimension_type i = space_dim; i-- > 0; ) { 01399 const Variable v(i); 01400 coeff = le.coefficient(v); 01401 if (coeff == 0) { 01402 continue; 01403 } 01404 01405 const ITV& seq_i = seq[i]; 01406 // Check if `v' is constant in the BD shape. 01407 if (seq_i.is_singleton()) { 01408 // If `v' is constant, replace it in `le' by the value. 01409 assign_r(tmp, seq_i.lower(), ROUND_NOT_NEEDED); 01410 num = tmp.get_num(); 01411 den = tmp.get_den(); 01412 le -= coeff*v; 01413 le *= den; 01414 le += num*coeff; 01415 val_den *= den; 01416 continue; 01417 } 01418 // The expression `expr' is not constant. 01419 return false; 01420 } 01421 01422 // The expression `expr' is constant. 01423 freq_n = 0; 01424 freq_d = 1; 01425 01426 // Reduce `val_n' and `val_d'. 01427 normalize2(le.inhomogeneous_term(), val_den, val_n, val_d); 01428 return true; 01429 }
| void Parma_Polyhedra_Library::Box< ITV >::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 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. |
Definition at line 3341 of file Box.templates.hh.
References Parma_Polyhedra_Library::assign_r(), 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, Parma_Polyhedra_Library::NOT_EQUAL, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.
03343 { 03344 // Dimension-compatibility checks. 03345 // The dimension of `lhs' should not be greater than the dimension 03346 // of `*this'. 03347 dimension_type lhs_space_dim = lhs.space_dimension(); 03348 const dimension_type space_dim = space_dimension(); 03349 if (space_dim < lhs_space_dim) 03350 throw_dimension_incompatible("generalized_affine_image(e1, r, e2)", 03351 "e1", lhs); 03352 // The dimension of `rhs' should not be greater than the dimension 03353 // of `*this'. 03354 const dimension_type rhs_space_dim = rhs.space_dimension(); 03355 if (space_dim < rhs_space_dim) 03356 throw_dimension_incompatible("generalized_affine_image(e1, r, e2)", 03357 "e2", rhs); 03358 03359 // The relation symbol cannot be a disequality. 03360 if (relsym == NOT_EQUAL) 03361 throw_generic("generalized_affine_image(e1, r, e2)", 03362 "r is the disequality relation symbol"); 03363 03364 // Any image of an empty box is empty. 03365 if (marked_empty()) 03366 return; 03367 03368 // Compute the maximum and minimum value reached by the rhs on the box. 03369 PPL_DIRTY_TEMP(Coefficient, max_num); 03370 PPL_DIRTY_TEMP(Coefficient, max_den); 03371 bool max_included; 03372 bool max_rhs = maximize(rhs, max_num, max_den, max_included); 03373 PPL_DIRTY_TEMP(Coefficient, min_num); 03374 PPL_DIRTY_TEMP(Coefficient, min_den); 03375 bool min_included; 03376 bool min_rhs = minimize(rhs, min_num, min_den, min_included); 03377 03378 // Check whether there is 0, 1 or more than one variable in the lhs 03379 // and record the variable with the highest dimension; set the box 03380 // intervals to be unbounded for all other dimensions with non-zero 03381 // coefficients in the lhs. 03382 bool has_var = false; 03383 bool has_more_than_one_var = false; 03384 // Initialization is just to avoid an annoying warning. 03385 dimension_type has_var_id = 0; 03386 for ( ; lhs_space_dim > 0; --lhs_space_dim) 03387 if (lhs.coefficient(Variable(lhs_space_dim - 1)) != 0) { 03388 if (has_var) { 03389 ITV& seq_i = seq[lhs_space_dim - 1]; 03390 seq_i.assign(UNIVERSE); 03391 has_more_than_one_var = true; 03392 } 03393 else { 03394 has_var = true; 03395 has_var_id = lhs_space_dim - 1; 03396 } 03397 } 03398 03399 if (has_more_than_one_var) { 03400 // There is more than one dimension with non-zero coefficient, so 03401 // we cannot have any information about the dimensions in the lhs. 03402 // Since all but the highest dimension with non-zero coefficient 03403 // in the lhs have been set unbounded, it remains to set the 03404 // highest dimension in the lhs unbounded. 03405 ITV& seq_var = seq[has_var_id]; 03406 seq_var.assign(UNIVERSE); 03407 PPL_ASSERT(OK()); 03408 return; 03409 } 03410 03411 if (has_var) { 03412 // There is exactly one dimension with non-zero coefficient. 03413 ITV& seq_var = seq[has_var_id]; 03414 03415 // Compute the new bounds for this dimension defined by the rhs 03416 // expression. 03417 const Coefficient& inhomo = lhs.inhomogeneous_term(); 03418 const Coefficient& coeff = lhs.coefficient(Variable(has_var_id)); 03419 PPL_DIRTY_TEMP0(mpq_class, q_max); 03420 PPL_DIRTY_TEMP0(mpq_class, q_min); 03421 if (max_rhs) { 03422 max_num -= inhomo * max_den; 03423 max_den *= coeff; 03424 assign_r(q_max.get_num(), max_num, ROUND_NOT_NEEDED); 03425 assign_r(q_max.get_den(), max_den, ROUND_NOT_NEEDED); 03426 q_max.canonicalize(); 03427 } 03428 if (min_rhs) { 03429 min_num -= inhomo * min_den; 03430 min_den *= coeff; 03431 assign_r(q_min.get_num(), min_num, ROUND_NOT_NEEDED); 03432 assign_r(q_min.get_den(), min_den, ROUND_NOT_NEEDED); 03433 q_min.canonicalize(); 03434 } 03435 03436 // The choice as to which bounds should be set depends on the sign 03437 // of the coefficient of the dimension `has_var_id' in the lhs. 03438 if (coeff > 0) 03439 // The coefficient of the dimension in the lhs is +ve. 03440 switch (relsym) { 03441 case LESS_OR_EQUAL: 03442 max_rhs 03443 ? seq_var.build(i_constraint(max_included ? LESS_OR_EQUAL : LESS_THAN, q_max)) 03444 : seq_var.assign(UNIVERSE); 03445 break; 03446 case LESS_THAN: 03447 max_rhs 03448 ? seq_var.build(i_constraint(LESS_THAN, q_max)) 03449 : seq_var.assign(UNIVERSE); 03450 break; 03451 case EQUAL: 03452 { 03453 I_Constraint<mpq_class> l; 03454 I_Constraint<mpq_class> u; 03455 if (max_rhs) 03456 u.set(max_included ? LESS_OR_EQUAL : LESS_THAN, q_max); 03457 if (min_rhs) 03458 l.set(min_included ? GREATER_OR_EQUAL : GREATER_THAN, q_min); 03459 seq_var.build(l, u); 03460 break; 03461 } 03462 case GREATER_OR_EQUAL: 03463 min_rhs 03464 ? seq_var.build(i_constraint(min_included ? GREATER_OR_EQUAL : GREATER_THAN, q_min)) 03465 : seq_var.assign(UNIVERSE); 03466 break; 03467 case GREATER_THAN: 03468 min_rhs 03469 ? seq_var.build(i_constraint(GREATER_THAN, q_min)) 03470 : seq_var.assign(UNIVERSE); 03471 break; 03472 default: 03473 // The NOT_EQUAL case has been already dealt with. 03474 throw std::runtime_error("PPL internal error"); 03475 } 03476 else 03477 // The coefficient of the dimension in the lhs is -ve. 03478 switch (relsym) { 03479 case GREATER_OR_EQUAL: 03480 min_rhs 03481 ? seq_var.build(i_constraint(min_included ? LESS_OR_EQUAL : LESS_THAN, q_min)) 03482 : seq_var.assign(UNIVERSE); 03483 break; 03484 case GREATER_THAN: 03485 min_rhs 03486 ? seq_var.build(i_constraint(LESS_THAN, q_min)) 03487 : seq_var.assign(UNIVERSE); 03488 break; 03489 case EQUAL: 03490 { 03491 I_Constraint<mpq_class> l; 03492 I_Constraint<mpq_class> u; 03493 if (max_rhs) 03494 l.set(max_included ? GREATER_OR_EQUAL : GREATER_THAN, q_max); 03495 if (min_rhs) 03496 u.set(min_included ? LESS_OR_EQUAL : LESS_THAN, q_min); 03497 seq_var.build(l, u); 03498 break; 03499 } 03500 case LESS_OR_EQUAL: 03501 max_rhs 03502 ? seq_var.build(i_constraint(max_included ? GREATER_OR_EQUAL : GREATER_THAN, q_max)) 03503 : seq_var.assign(UNIVERSE); 03504 break; 03505 case LESS_THAN: 03506 max_rhs 03507 ? seq_var.build(i_constraint(GREATER_THAN, q_max)) 03508 : seq_var.assign(UNIVERSE); 03509 break; 03510 default: 03511 // The NOT_EQUAL case has been already dealt with. 03512 throw std::runtime_error("PPL internal error"); 03513 } 03514 } 03515 03516 else { 03517 // The lhs is a constant value, so we just need to add the 03518 // appropriate constraint. 03519 const Coefficient& inhomo = lhs.inhomogeneous_term(); 03520 switch (relsym) { 03521 case LESS_THAN: 03522 refine_with_constraint(inhomo < rhs); 03523 break; 03524 case LESS_OR_EQUAL: 03525 refine_with_constraint(inhomo <= rhs); 03526 break; 03527 case EQUAL: 03528 refine_with_constraint(inhomo == rhs); 03529 break; 03530 case GREATER_OR_EQUAL: 03531 refine_with_constraint(inhomo >= rhs); 03532 break; 03533 case GREATER_THAN: 03534 refine_with_constraint(inhomo > rhs); 03535 break; 03536 default: 03537 // The NOT_EQUAL case has been already dealt with. 03538 throw std::runtime_error("PPL internal error"); 03539 } 03540 } 03541 PPL_ASSERT(OK()); 03542 }
| void Parma_Polyhedra_Library::Box< ITV >::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 relation
, where
is the relation symbol encoded by relsym.
| var | The left hand side variable of the generalized affine relation; | |
| relsym | The relation symbol; | |
| expr | The numerator of the right hand side affine expression; | |
| denominator | The denominator of the right hand side affine expression (optional argument with default value 1). |
| std::invalid_argument | Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of *this. |
Definition at line 3131 of file Box.templates.hh.
References 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::NOT_EQUAL, Parma_Polyhedra_Library::Variable::space_dimension(), and Parma_Polyhedra_Library::Linear_Expression::space_dimension().
Referenced by Parma_Polyhedra_Library::Box< ITV >::generalized_affine_preimage().
03134 { 03135 // The denominator cannot be zero. 03136 if (denominator == 0) 03137 throw_generic("generalized_affine_image(v, r, e, d)", "d == 0"); 03138 03139 // Dimension-compatibility checks. 03140 const dimension_type space_dim = space_dimension(); 03141 // The dimension of `expr' should not be greater than the dimension 03142 // of `*this'. 03143 if (space_dim < expr.space_dimension()) 03144 throw_dimension_incompatible("generalized_affine_image(v, r, e, d)", 03145 "e", expr); 03146 // `var' should be one of the dimensions of the box. 03147 const dimension_type var_space_dim = var.space_dimension(); 03148 if (space_dim < var_space_dim) 03149 throw_dimension_incompatible("generalized_affine_image(v, r, e, d)", 03150 "v", var); 03151 03152 // The relation symbol cannot be a disequality. 03153 if (relsym == NOT_EQUAL) 03154 throw_generic("generalized_affine_image(v, r, e, d)", 03155 "r is the disequality relation symbol"); 03156 03157 // First compute the affine image. 03158 affine_image(var, expr, denominator); 03159 03160 if (relsym == EQUAL) 03161 // The affine relation is indeed an affine function. 03162 return; 03163 03164 // Any image of an empty box is empty. 03165 if (is_empty()) 03166 return; 03167 03168 ITV& seq_var = seq[var.id()]; 03169 switch (relsym) { 03170 case LESS_OR_EQUAL: 03171 seq_var.lower_extend(); 03172 break; 03173 case LESS_THAN: 03174 seq_var.lower_extend(); 03175 if (!seq_var.upper_is_boundary_infinity()) 03176 seq_var.remove_sup(); 03177 break; 03178 case GREATER_OR_EQUAL: 03179 seq_var.upper_extend(); 03180 break; 03181 case GREATER_THAN: 03182 seq_var.upper_extend(); 03183 if (!seq_var.lower_is_boundary_infinity()) 03184 seq_var.remove_inf(); 03185 break; 03186 default: 03187 // The EQUAL and NOT_EQUAL cases have been already dealt with. 03188 throw std::runtime_error("PPL internal error"); 03189 } 03190 PPL_ASSERT(OK()); 03191 }
| void Parma_Polyhedra_Library::Box< ITV >::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. |
Definition at line 3546 of file Box.templates.hh.
References Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Box< ITV >::generalized_affine_image(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::NOT_EQUAL, Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Box< ITV >::throw_generic().
03548 { 03549 // Dimension-compatibility checks. 03550 // The dimension of `lhs' should not be greater than the dimension 03551 // of `*this'. 03552 dimension_type lhs_space_dim = lhs.space_dimension(); 03553 const dimension_type space_dim = space_dimension(); 03554 if (space_dim < lhs_space_dim) 03555 throw_dimension_incompatible("generalized_affine_image(e1, r, e2)", 03556 "e1", lhs); 03557 // The dimension of `rhs' should not be greater than the dimension 03558 // of `*this'. 03559 const dimension_type rhs_space_dim = rhs.space_dimension(); 03560 if (space_dim < rhs_space_dim) 03561 throw_dimension_incompatible("generalized_affine_image(e1, r, e2)", 03562 "e2", rhs); 03563 03564 // The relation symbol cannot be a disequality. 03565 if (relsym == NOT_EQUAL) 03566 throw_generic("generalized_affine_image(e1, r, e2)", 03567 "r is the disequality relation symbol"); 03568 03569 // Any image of an empty box is empty. 03570 if (marked_empty()) 03571 return; 03572 03573 // For any dimension occurring in the lhs, swap and change the sign 03574 // of this component for the rhs and lhs. Then use these in a call 03575 // to generalized_affine_image/3. 03576 Linear_Expression revised_lhs = lhs; 03577 Linear_Expression revised_rhs = rhs; 03578 for (dimension_type d = lhs_space_dim; d-- > 0; ) { 03579 const Variable& var = Variable(d); 03580 if (lhs.coefficient(var) != 0) { 03581 PPL_DIRTY_TEMP(Coefficient, temp); 03582 temp = rhs.coefficient(var) + lhs.coefficient(var); 03583 revised_rhs -= temp * var; 03584 revised_lhs -= temp * var; 03585 } 03586 } 03587 generalized_affine_image(revised_lhs, relsym, revised_rhs); 03588 PPL_ASSERT(OK()); 03589 }
| void Parma_Polyhedra_Library::Box< ITV >::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 generalized affine relation
, where
is the relation symbol encoded by relsym.
| var | The left hand side variable of the generalized affine relation; | |
| relsym | The relation symbol; | |
| expr | The numerator of the right hand side affine expression; | |
| denominator | The denominator of the right hand side affine expression (optional argument with default value 1). |
| std::invalid_argument | Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of *this. |
Definition at line 3196 of file Box.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::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::NOT_EQUAL, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.
03200 { 03201 // The denominator cannot be zero. 03202 if (denominator == 0) 03203 throw_generic("generalized_affine_preimage(v, r, e, d)", 03204 "d == 0"); 03205 03206 // Dimension-compatibility checks. 03207 const dimension_type space_dim = space_dimension(); 03208 // The dimension of `expr' should not be greater than the dimension 03209 // of `*this'. 03210 if (space_dim < expr.space_dimension()) 03211 throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)", 03212 "e", expr); 03213 // `var' should be one of the dimensions of the box. 03214 const dimension_type var_space_dim = var.space_dimension(); 03215 if (space_dim < var_space_dim) 03216 throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)", 03217 "v", var); 03218 // The relation symbol cannot be a disequality. 03219 if (relsym == NOT_EQUAL) 03220 throw_generic("generalized_affine_preimage(v, r, e, d)", 03221 "r is the disequality relation symbol"); 03222 03223 // Check whether the affine relation is indeed an affine function. 03224 if (relsym == EQUAL) { 03225 affine_preimage(var, expr, denominator); 03226 return; 03227 } 03228 03229 // Compute the reversed relation symbol to simplify later coding. 03230 Relation_Symbol reversed_relsym; 03231 switch (relsym) { 03232 case LESS_THAN: 03233 reversed_relsym = GREATER_THAN; 03234 break; 03235 case LESS_OR_EQUAL: 03236 reversed_relsym = GREATER_OR_EQUAL; 03237 break; 03238 case GREATER_OR_EQUAL: 03239 reversed_relsym = LESS_OR_EQUAL; 03240 break; 03241 case GREATER_THAN: 03242 reversed_relsym = LESS_THAN; 03243 break; 03244 default: 03245 // The EQUAL and NOT_EQUAL cases have been already dealt with. 03246 throw std::runtime_error("PPL internal error"); 03247 } 03248 03249 // Check whether the preimage of this affine relation can be easily 03250 // computed as the image of its inverse relation. 03251 const Coefficient& var_coefficient = expr.coefficient(var); 03252 if (var_coefficient != 0) { 03253 Linear_Expression inverse_expr 03254 = expr - (denominator + var_coefficient) * var; 03255 PPL_DIRTY_TEMP_COEFFICIENT(inverse_denominator); 03256 neg_assign(inverse_denominator, var_coefficient); 03257 Relation_Symbol inverse_relsym 03258 = (sgn(denominator) == sgn(inverse_denominator)) 03259 ? relsym : reversed_relsym; 03260 generalized_affine_image(var, inverse_relsym, inverse_expr, 03261 inverse_denominator); 03262 return; 03263 } 03264 03265 // Here `var_coefficient == 0', so that the preimage cannot 03266 // be easily computed by inverting the affine relation. 03267 // Shrink the box by adding the constraint induced 03268 // by the affine relation. 03269 // First, compute the maximum and minimum value reached by 03270 // `denominator*var' on the box as we need to use non-relational 03271 // expressions. 03272 PPL_DIRTY_TEMP(Coefficient, max_num); 03273 PPL_DIRTY_TEMP(Coefficient, max_den); 03274 bool max_included; 03275 bool bound_above = maximize(denominator*var, max_num, max_den, max_included); 03276 PPL_DIRTY_TEMP(Coefficient, min_num); 03277 PPL_DIRTY_TEMP(Coefficient, min_den); 03278 bool min_included; 03279 bool bound_below = minimize(denominator*var, min_num, min_den, min_included); 03280 // Use the correct relation symbol 03281 const Relation_Symbol corrected_relsym 03282 = (denominator > 0) ? relsym : reversed_relsym; 03283 // Revise the expression to take into account the denominator of the 03284 // maximum/minimim value for `var'. 03285 PPL_DIRTY_TEMP(Linear_Expression, revised_expr); 03286 dimension_type dim = space_dim; 03287 PPL_DIRTY_TEMP_COEFFICIENT(d); 03288 if (corrected_relsym == LESS_THAN || corrected_relsym == LESS_OR_EQUAL) { 03289 if (bound_below) { 03290 for ( ; dim > 0; dim--) { 03291 d = min_den * expr.coefficient(Variable(dim - 1)); 03292 revised_expr += d * Variable(dim - 1); 03293 } 03294 } 03295 } 03296 else { 03297 if (bound_above) { 03298 for ( ; dim > 0; dim--) { 03299 d = max_den * expr.coefficient(Variable(dim - 1)); 03300 revised_expr += d * Variable(dim - 1); 03301 } 03302 } 03303 } 03304 03305 switch (corrected_relsym) { 03306 case LESS_THAN: 03307 if (bound_below) 03308 refine_with_constraint(min_num < revised_expr); 03309 break; 03310 case LESS_OR_EQUAL: 03311 if (bound_below) 03312 (min_included) 03313 ? refine_with_constraint(min_num <= revised_expr) 03314 : refine_with_constraint(min_num < revised_expr); 03315 break; 03316 case GREATER_OR_EQUAL: 03317 if (bound_above) 03318 (max_included) 03319 ? refine_with_constraint(max_num >= revised_expr) 03320 : refine_with_constraint(max_num > revised_expr); 03321 break; 03322 case GREATER_THAN: 03323 if (bound_above) 03324 refine_with_constraint(max_num > revised_expr); 03325 break; 03326 default: 03327 // The EQUAL and NOT_EQUAL cases have been already dealt with. 03328 throw std::runtime_error("PPL internal error"); 03329 } 03330 // If the shrunk box is empty, its preimage is empty too. 03331 if (is_empty()) 03332 return; 03333 ITV& seq_v = seq[var.id()]; 03334 seq_v.assign(UNIVERSE); 03335 PPL_ASSERT(OK()); 03336 }
| const ITV & Parma_Polyhedra_Library::Box< ITV >::get_interval | ( | Variable | var | ) | const [inline] |
Returns a reference the interval that bounds var.
| std::invalid_argument | Thrown if var is not a space dimension of *this. |
Definition at line 143 of file Box.inlines.hh.
References Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
00143 { 00144 if (space_dimension() < var.space_dimension()) 00145 throw_dimension_incompatible("get_interval(v)", "v", var); 00146 00147 if (is_empty()) { 00148 static ITV empty_interval(EMPTY); 00149 return empty_interval; 00150 } 00151 00152 return seq[var.id()]; 00153 }
| void Parma_Polyhedra_Library::Box< ITV >::get_limiting_box | ( | const Constraint_System & | cs, | |
| Box< ITV > & | limiting_box | |||
| ) | const [inline, private] |
Adds to limiting_box the interval constraints in cs that are satisfied by *this.
Definition at line 3638 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::add_interval_constraint_no_check(), Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Box< ITV >::extract_interval_constraint(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::interval_relation(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), and Parma_Polyhedra_Library::Constraint::type().
Referenced by Parma_Polyhedra_Library::Box< ITV >::limited_CC76_extrapolation_assign().
03639 { 03640 const dimension_type cs_space_dim = cs.space_dimension(); 03641 // Private method: the caller has to ensure the following. 03642 PPL_ASSERT(cs_space_dim <= space_dimension()); 03643 03644 for (Constraint_System::const_iterator cs_i = cs.begin(), 03645 cs_end = cs.end(); cs_i != cs_end; ++cs_i) { 03646 const Constraint& c = *cs_i; 03647 dimension_type c_num_vars = 0; 03648 dimension_type c_only_var = 0; 03649 // Constraints that are not interval constraints are ignored. 03650 if (!extract_interval_constraint(c, cs_space_dim, c_num_vars, c_only_var)) 03651 continue; 03652 // Trivial constraints are ignored. 03653 if (c_num_vars != 0) { 03654 // c is a non-trivial interval constraint. 03655 // add interval constraint to limiting box 03656 const Coefficient& n = c.inhomogeneous_term(); 03657 const Coefficient& d = c.coefficient(Variable(c_only_var)); 03658 if (interval_relation(seq[c_only_var], c.type(), n, d) 03659 == Poly_Con_Relation::is_included()) 03660 limiting_box.add_interval_constraint_no_check(c_only_var, c.type(), 03661 n, d); 03662 } 03663 } 03664 }
| bool Parma_Polyhedra_Library::Box< ITV >::get_lower_bound | ( | dimension_type | k, | |
| bool & | closed, | |||
| Coefficient & | n, | |||
| Coefficient & | d | |||
| ) | const [inline] |
If the k-th space dimension is unbounded below, returns false. Otherwise returns true and set closed, n and d accordingly.
Let
the interval corresponding to the k-th space dimension. If
is not bounded from below, simply return false. Otherwise, set closed, n and d as follows: closed is set to true if the the lower boundary of
is closed and is set to false otherwise; n and d are assigned the integers
and
such that the canonical fraction
corresponds to the greatest lower bound of
. The fraction
is in canonical form if and only if
and
have no common factors and
is positive,
being the unique representation for zero.
An undefined behavior is obtained if k is greater than or equal to the space dimension of *this.
Definition at line 260 of file Box.inlines.hh.
References Parma_Polyhedra_Library::assign_r(), and Parma_Polyhedra_Library::Box< ITV >::seq.
Referenced by Parma_Polyhedra_Library::Box< ITV >::congruences(), Parma_Polyhedra_Library::Box< ITV >::constraints(), Parma_Polyhedra_Library::Grid::Grid(), Parma_Polyhedra_Library::Box< ITV >::minimized_constraints(), and Parma_Polyhedra_Library::Polyhedron::Polyhedron().
00261 { 00262 PPL_ASSERT(k < seq.size()); 00263 const ITV& seq_k = seq[k]; 00264 00265 if (seq_k.lower_is_boundary_infinity()) 00266 return false; 00267 00268 closed = !seq_k.lower_is_open(); 00269 00270 PPL_DIRTY_TEMP0(mpq_class, lr); 00271 assign_r(lr, seq_k.lower(), ROUND_NOT_NEEDED); 00272 n = lr.get_num(); 00273 d = lr.get_den(); 00274 00275 return true; 00276 }
| bool Parma_Polyhedra_Library::Box< ITV >::get_upper_bound | ( | dimension_type | k, | |
| bool & | closed, | |||
| Coefficient & | n, | |||
| Coefficient & | d | |||
| ) | const [inline] |
If the k-th space dimension is unbounded above, returns false. Otherwise returns true and set closed, n and d accordingly.
Let
the interval corresponding to the k-th space dimension. If
is not bounded from above, simply return false. Otherwise, set closed, n and d as follows: closed is set to true if the the upper boundary of
is closed and is set to false otherwise; n and d are assigned the integers
and
such that the canonical fraction
corresponds to the least upper bound of
.
An undefined behavior is obtained if k is greater than or equal to the space dimension of *this.
Definition at line 280 of file Box.inlines.hh.
References Parma_Polyhedra_Library::assign_r(), and Parma_Polyhedra_Library::Box< ITV >::seq.
Referenced by Parma_Polyhedra_Library::Box< ITV >::constraints(), Parma_Polyhedra_Library::Grid::Grid(), Parma_Polyhedra_Library::Box< ITV >::minimized_constraints(), and Parma_Polyhedra_Library::Polyhedron::Polyhedron().
00281 { 00282 PPL_ASSERT(k < seq.size()); 00283 const ITV& seq_k = seq[k]; 00284 00285 if (seq_k.upper_is_boundary_infinity()) 00286 return false; 00287 00288 closed = !seq_k.upper_is_open(); 00289 00290 PPL_DIRTY_TEMP0(mpq_class, ur); 00291 assign_r(ur, seq_k.upper(), ROUND_NOT_NEEDED); 00292 n = ur.get_num(); 00293 d = ur.get_den(); 00294 00295 return true; 00296 }
| void Parma_Polyhedra_Library::Box< ITV >::intersection_assign | ( | const Box< ITV > & | 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 1711 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::reset_empty_up_to_date(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Box< ITV >::limited_CC76_extrapolation_assign().
01711 { 01712 Box& x = *this; 01713 const dimension_type space_dim = space_dimension(); 01714 01715 // Dimension-compatibility check. 01716 if (space_dim != y.space_dimension()) 01717 x.throw_dimension_incompatible("intersection_assign(y)", y); 01718 01719 // If one of the two boxes is empty, the intersection is empty. 01720 if (x.marked_empty()) 01721 return; 01722 if (y.marked_empty()) { 01723 x.set_empty(); 01724 return; 01725 } 01726 01727 // If both boxes are zero-dimensional, then at this point they are 01728 // necessarily non-empty, so that their intersection is non-empty too. 01729 if (space_dim == 0) 01730 return; 01731 01732 // FIXME: here we may conditionally exploit a capability of the 01733 // underlying interval to eagerly detect empty results. 01734 reset_empty_up_to_date(); 01735 01736 for (dimension_type k = space_dim; k-- > 0; ) 01737 x.seq[k].intersect_assign(y.seq[k]); 01738 01739 PPL_ASSERT(x.OK()); 01740 }
| bool Parma_Polyhedra_Library::Box< ITV >::is_bounded | ( | ) | const [inline] |
Returns true if and only if *this is a bounded box.
Definition at line 1337 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::is_empty(), and Parma_Polyhedra_Library::Box< ITV >::seq.
01337 { 01338 if (is_empty()) 01339 return true; 01340 for (dimension_type k = seq.size(); k-- > 0; ) 01341 if (!seq[k].is_bounded()) 01342 return false; 01343 return true; 01344 }
| bool Parma_Polyhedra_Library::Box< ITV >::is_discrete | ( | ) | const [inline] |
Returns true if and only if *this is discrete.
Definition at line 1326 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::is_empty(), and Parma_Polyhedra_Library::Box< ITV >::seq.
01326 { 01327 if (is_empty()) 01328 return true; 01329 for (dimension_type k = seq.size(); k-- > 0; ) 01330 if (!seq[k].is_singleton()) 01331 return false; 01332 return true; 01333 }
| bool Parma_Polyhedra_Library::Box< ITV >::is_disjoint_from | ( | const Box< ITV > & | y | ) | const [inline] |
Returns true if and only if *this and y are disjoint.
| std::invalid_argument | Thrown if x and y are dimension-incompatible. |
Definition at line 1176 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
01176 { 01177 const Box& x = *this; 01178 // Dimension-compatibility check. 01179 if (x.space_dimension() != y.space_dimension()) 01180 x.throw_dimension_incompatible("is_disjoint_from(y)", y); 01181 01182 // If any of `x' or `y' is marked empty, then they are disjoint. 01183 // Note: no need to use `is_empty', as the following loop is anyway correct. 01184 if (x.marked_empty() || y.marked_empty()) 01185 return true; 01186 01187 for (dimension_type k = x.seq.size(); k-- > 0; ) 01188 // FIXME: fix this name qualification issue. 01189 if (x.seq[k].is_disjoint_from(y.seq[k])) 01190 return true; 01191 return false; 01192 }
| bool Parma_Polyhedra_Library::Box< ITV >::is_empty | ( | ) | const [inline] |
Returns true if and only if *this is an empty box.
Definition at line 175 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::check_empty(), and Parma_Polyhedra_Library::Box< ITV >::marked_empty().
Referenced by Parma_Polyhedra_Library::Box< ITV >::affine_dimension(), Parma_Polyhedra_Library::Box< ITV >::affine_image(), Parma_Polyhedra_Library::Box< ITV >::affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::Box< ITV >::bounds(), Parma_Polyhedra_Library::Box< ITV >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Box< ITV >::check_empty(), Parma_Polyhedra_Library::Box< ITV >::congruences(), Parma_Polyhedra_Library::Box< ITV >::constrains(), Parma_Polyhedra_Library::Box< ITV >::contains(), Parma_Polyhedra_Library::Box< ITV >::difference_assign(), Parma_Polyhedra_Library::Box< ITV >::fold_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::frequency(), Parma_Polyhedra_Library::Box< ITV >::get_interval(), Parma_Polyhedra_Library::Grid::Grid(), Parma_Polyhedra_Library::Box< ITV >::is_bounded(), Parma_Polyhedra_Library::Box< ITV >::is_discrete(), Parma_Polyhedra_Library::Box< ITV >::is_topologically_closed(), Parma_Polyhedra_Library::Box< ITV >::l_m_distance_assign(), Parma_Polyhedra_Library::Box< ITV >::map_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::max_min(), Parma_Polyhedra_Library::Box< ITV >::minimized_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::operator==(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::Pointset_Powerset(), Parma_Polyhedra_Library::Polyhedron::Polyhedron(), Parma_Polyhedra_Library::Box< ITV >::relation_with(), Parma_Polyhedra_Library::Box< ITV >::remove_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::set_interval(), Parma_Polyhedra_Library::Box< ITV >::simplify_using_context_assign(), Parma_Polyhedra_Library::Box< ITV >::time_elapse_assign(), Parma_Polyhedra_Library::Box< ITV >::topological_closure_assign(), and Parma_Polyhedra_Library::Box< ITV >::wrap_assign().
00175 { 00176 return marked_empty() || check_empty(); 00177 }
| bool Parma_Polyhedra_Library::Box< ITV >::is_topologically_closed | ( | ) | const [inline] |
Returns true if and only if *this is a topologically closed subset of the vector space.
Definition at line 1314 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::is_empty(), and Parma_Polyhedra_Library::Box< ITV >::seq.
01314 { 01315 if (ITV::is_always_topologically_closed() || is_empty()) 01316 return true; 01317 01318 for (dimension_type k = seq.size(); k-- > 0; ) 01319 if (!seq[k].is_topologically_closed()) 01320 return false; 01321 return true; 01322 }
| bool Parma_Polyhedra_Library::Box< ITV >::is_universe | ( | ) | const [inline] |
Returns true if and only if *this is a universe box.
Definition at line 1303 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), and Parma_Polyhedra_Library::Box< ITV >::seq.
Referenced by Parma_Polyhedra_Library::Box< ITV >::constrains().
01303 { 01304 if (marked_empty()) 01305 return false; 01306 for (dimension_type k = seq.size(); k-- > 0; ) 01307 if (!seq[k].is_universe()) 01308 return false; 01309 return true; 01310 }
| void Parma_Polyhedra_Library::Box< ITV >::limited_CC76_extrapolation_assign | ( | const Box< ITV > & | 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 | A box that must be contained in *this. | |
| cs | The system of constraints used to improve the widened box. | |
| 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 3668 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::CC76_widening_assign(), Parma_Polyhedra_Library::Box< ITV >::contains(), Parma_Polyhedra_Library::Box< ITV >::get_limiting_box(), Parma_Polyhedra_Library::Box< ITV >::intersection_assign(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::throw_constraint_incompatible(), Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::UNIVERSE.
03670 { 03671 Box& x = *this; 03672 const dimension_type space_dim = x.space_dimension(); 03673 03674 // Dimension-compatibility check. 03675 if (space_dim != y.space_dimension()) 03676 throw_dimension_incompatible("limited_CC76_extrapolation_assign(y, cs)", 03677 y); 03678 // `cs' must be dimension-compatible with the two boxes. 03679 const dimension_type cs_space_dim = cs.space_dimension(); 03680 if (space_dim < cs_space_dim) 03681 throw_constraint_incompatible("limited_CC76_extrapolation_assign(y, cs)"); 03682 03683 // The limited CC76-extrapolation between two boxes in a 03684 // zero-dimensional space is also a zero-dimensional box 03685 if (space_dim == 0) 03686 return; 03687 03688 #ifndef NDEBUG 03689 { 03690 // We assume that `y' is contained in or equal to `*this'. 03691 const Box x_copy = *this; 03692 const Box y_copy = y; 03693 PPL_ASSERT(x_copy.contains(y_copy)); 03694 } 03695 #endif 03696 03697 // If `*this' is empty, since `*this' contains `y', `y' is empty too. 03698 if (marked_empty()) 03699 return; 03700 // If `y' is empty, we return. 03701 if (y.marked_empty()) 03702 return; 03703 03704 // Build a limiting box using all the constraints in cs 03705 // that are satisfied by *this. 03706 Box limiting_box(space_dim, UNIVERSE); 03707 get_limiting_box(cs, limiting_box); 03708 03709 x.CC76_widening_assign(y, tp); 03710 03711 // Intersect the widened box with the limiting box. 03712 intersection_assign(limiting_box); 03713 }
| void Parma_Polyhedra_Library::Box< ITV >::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 co-domain (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 co-domain 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 2053 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::swap().
02053 { 02054 const dimension_type space_dim = space_dimension(); 02055 if (space_dim == 0) 02056 return; 02057 02058 if (pfunc.has_empty_codomain()) { 02059 // All dimensions vanish: the box becomes zero_dimensional. 02060 remove_higher_space_dimensions(0); 02061 return; 02062 } 02063 02064 const dimension_type new_space_dim = pfunc.max_in_codomain() + 1; 02065 // If the box is empty, then simply adjust the space dimension. 02066 if (is_empty()) { 02067 remove_higher_space_dimensions(new_space_dim); 02068 return; 02069 } 02070 02071 // We create a new Box with the new space dimension. 02072 Box<ITV> tmp(new_space_dim); 02073 // Map the intervals, exchanging the indexes. 02074 for (dimension_type i = 0; i < space_dim; ++i) { 02075 dimension_type new_i; 02076 if (pfunc.maps(i, new_i)) 02077 seq[i].swap(tmp.seq[new_i]); 02078 } 02079 swap(tmp); 02080 PPL_ASSERT(OK()); 02081 }
| bool Parma_Polyhedra_Library::Box< ITV >::marked_empty | ( | ) | const [inline, private] |
Returns true if and only if the box is known to be empty.
The return value false does not necessarily implies that *this is non-empty.
Definition at line 38 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::status, Parma_Polyhedra_Library::Box< ITV >::Status::test_empty(), and Parma_Polyhedra_Library::Box< ITV >::Status::test_empty_up_to_date().
Referenced by Parma_Polyhedra_Library::Box< ITV >::add_congruence_no_check(), Parma_Polyhedra_Library::Box< ITV >::add_constraint_no_check(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Box< ITV >::check_empty(), Parma_Polyhedra_Library::Box< ITV >::concatenate_assign(), Parma_Polyhedra_Library::Box< ITV >::congruences(), Parma_Polyhedra_Library::Box< ITV >::constrains(), Parma_Polyhedra_Library::Box< ITV >::constraints(), Parma_Polyhedra_Library::Box< ITV >::contains_integer_point(), Parma_Polyhedra_Library::Box< ITV >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Box< ITV >::generalized_affine_preimage(), Parma_Polyhedra_Library::Box< ITV >::intersection_assign(), Parma_Polyhedra_Library::Box< ITV >::is_disjoint_from(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::is_universe(), Parma_Polyhedra_Library::Box< ITV >::l_m_distance_assign(), Parma_Polyhedra_Library::Box< ITV >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::Box< ITV >::max_min(), Parma_Polyhedra_Library::Box< ITV >::minimized_constraints(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::propagate_constraint(), Parma_Polyhedra_Library::Box< ITV >::propagate_constraints(), Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::refine_with_congruence(), Parma_Polyhedra_Library::Box< ITV >::refine_with_congruences(), Parma_Polyhedra_Library::Box< ITV >::refine_with_constraint(), Parma_Polyhedra_Library::Box< ITV >::refine_with_constraints(), Parma_Polyhedra_Library::Box< ITV >::simplify_using_context_assign(), Parma_Polyhedra_Library::Box< ITV >::time_elapse_assign(), Parma_Polyhedra_Library::Box< ITV >::unconstrain(), Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign(), and Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign_if_exact().
00038 { 00039 return status.test_empty_up_to_date() && status.test_empty(); 00040 }
| bool Parma_Polyhedra_Library::Box< ITV >::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, included and point are left untouched.
Definition at line 1003 of file Box.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_canonical(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
01006 { 01007 // `expr' should be dimension-compatible with `*this'. 01008 const dimension_type space_dim = space_dimension(); 01009 const dimension_type expr_space_dim = expr.space_dimension(); 01010 if (space_dim < expr_space_dim) 01011 throw_dimension_incompatible((maximize 01012 ? "maximize(e, ...)" 01013 : "minimize(e, ...)"), "e", expr); 01014 // Deal with zero-dim Box first. 01015 if (space_dim == 0) { 01016 if (marked_empty()) 01017 return false; 01018 else { 01019 ext_n = expr.inhomogeneous_term(); 01020 ext_d = 1; 01021 included = true; 01022 return true; 01023 } 01024 } 01025 01026 // For an empty Box we simply return false. 01027 if (is_empty()) 01028 return false; 01029 01030 PPL_DIRTY_TEMP0(mpq_class, result); 01031 assign_r(result, expr.inhomogeneous_term(), ROUND_NOT_NEEDED); 01032 bool is_included = true; 01033 const int maximize_sign = maximize ? 1 : -1; 01034 PPL_DIRTY_TEMP0(mpq_class, bound_i); 01035 PPL_DIRTY_TEMP0(mpq_class, expr_i); 01036 for (dimension_type i = expr_space_dim; i-- > 0; ) { 01037 const ITV& seq_i = seq[i]; 01038 assign_r(expr_i, expr.coefficient(Variable(i)), ROUND_NOT_NEEDED); 01039 switch (sgn(expr_i) * maximize_sign) { 01040 case 1: 01041 if (seq_i.upper_is_boundary_infinity()) 01042 return false; 01043 assign_r(bound_i, seq_i.upper(), ROUND_NOT_NEEDED); 01044 add_mul_assign_r(result, bound_i, expr_i, ROUND_NOT_NEEDED); 01045 if (seq_i.upper_is_open()) 01046 is_included = false; 01047 break; 01048 case 0: 01049 // Nothing to do. 01050 break; 01051 case -1: 01052 if (seq_i.lower_is_boundary_infinity()) 01053 return false; 01054 assign_r(bound_i, seq_i.lower(), ROUND_NOT_NEEDED); 01055 add_mul_assign_r(result, bound_i, expr_i, ROUND_NOT_NEEDED); 01056 if (seq_i.lower_is_open()) 01057 is_included = false; 01058 break; 01059 } 01060 } 01061 // Extract output info. 01062 PPL_ASSERT(is_canonical(result)); 01063 ext_n = result.get_num(); 01064 ext_d = result.get_den(); 01065 included = is_included; 01066 return true; 01067 }
| bool Parma_Polyhedra_Library::Box< ITV >::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 1071 of file Box.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::lcm_assign(), Parma_Polyhedra_Library::Generator::point(), Parma_Polyhedra_Library::Box< ITV >::seq, and Parma_Polyhedra_Library::Box< ITV >::space_dimension().
Referenced by Parma_Polyhedra_Library::Box< ITV >::maximize(), and Parma_Polyhedra_Library::Box< ITV >::minimize().
01075 { 01076 if (!max_min(expr, maximize, ext_n, ext_d, included)) 01077 return false; 01078 01079 // Compute generator `g'. 01080 Linear_Expression g_expr; 01081 PPL_DIRTY_TEMP(Coefficient, g_divisor); 01082 g_divisor = 1; 01083 const int maximize_sign = maximize ? 1 : -1; 01084 PPL_DIRTY_TEMP0(mpq_class, g_coord); 01085 PPL_DIRTY_TEMP(Coefficient, num); 01086 PPL_DIRTY_TEMP(Coefficient, den); 01087 PPL_DIRTY_TEMP(Coefficient, lcm); 01088 PPL_DIRTY_TEMP(Coefficient, factor); 01089 for (dimension_type i = space_dimension(); i-- > 0; ) { 01090 const ITV& seq_i = seq[i]; 01091 switch (sgn(expr.coefficient(Variable(i))) * maximize_sign) { 01092 case 1: 01093 assign_r(g_coord, seq_i.upper(), ROUND_NOT_NEEDED); 01094 break; 01095 case 0: 01096 // If 0 belongs to the interval, choose it 01097 // (and directly proceed to the next iteration). 01098 // FIXME: name qualification issue. 01099 if (seq_i.contains(0)) 01100 continue; 01101 if (!seq_i.lower_is_boundary_infinity()) 01102 if (seq_i.lower_is_open()) 01103 if (!seq_i.upper_is_boundary_infinity()) 01104 if (seq_i.upper_is_open()) { 01105 // Bounded and open interval: compute middle point. 01106 assign_r(g_coord, seq_i.lower(), ROUND_NOT_NEEDED); 01107 PPL_DIRTY_TEMP0(mpq_class, q_seq_i_upper); 01108 assign_r(q_seq_i_upper, seq_i.upper(), ROUND_NOT_NEEDED); 01109 g_coord += q_seq_i_upper; 01110 g_coord /= 2; 01111 } 01112 else 01113 // The upper bound is in the interval. 01114 assign_r(g_coord, seq_i.upper(), ROUND_NOT_NEEDED); 01115 else { 01116 // Lower is open, upper is unbounded. 01117 assign_r(g_coord, seq_i.lower(), ROUND_NOT_NEEDED); 01118 ++g_coord; 01119 } 01120 else 01121 // The lower bound is in the interval. 01122 assign_r(g_coord, seq_i.lower(), ROUND_NOT_NEEDED); 01123 else { 01124 // Lower is unbounded, hence upper is bounded 01125 // (since we know that 0 does not belong to the interval). 01126 PPL_ASSERT(!seq_i.upper_is_boundary_infinity()); 01127 assign_r(g_coord, seq_i.upper(), ROUND_NOT_NEEDED); 01128 if (seq_i.upper_is_open()) 01129 --g_coord; 01130 } 01131 break; 01132 case -1: 01133 assign_r(g_coord, seq_i.lower(), ROUND_NOT_NEEDED); 01134 break; 01135 } 01136 // Add g_coord * Variable(i) to the generator. 01137 assign_r(den, g_coord.get_den(), ROUND_NOT_NEEDED); 01138 lcm_assign(lcm, g_divisor, den); 01139 exact_div_assign(factor, lcm, g_divisor); 01140 g_expr *= factor; 01141 exact_div_assign(factor, lcm, den); 01142 assign_r(num, g_coord.get_num(), ROUND_NOT_NEEDED); 01143 num *= factor; 01144 g_expr += num * Variable(i); 01145 g_divisor = lcm; 01146 } 01147 g = Generator::point(g_expr, g_divisor); 01148 return true; 01149 }
| dimension_type Parma_Polyhedra_Library::Box< ITV >::max_space_dimension | ( | ) | [inline, static] |
Returns the maximum space dimension that a Box can handle.
Definition at line 128 of file Box.inlines.hh.
Referenced by Parma_Polyhedra_Library::Box< ITV >::Box(), and Parma_Polyhedra_Library::Box< ITV >::expand_space_dimension().
00128 { 00129 // One dimension is reserved to have a value of type dimension_type 00130 // that does not represent a legal dimension. 00131 return Sequence().max_size() - 1; 00132 }
| bool Parma_Polyhedra_Library::Box< ITV >::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 201 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::max_min().
00203 { 00204 return max_min(expr, true, sup_n, sup_d, maximum, g); 00205 }
| bool Parma_Polyhedra_Library::Box< ITV >::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 193 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::max_min().
00195 { 00196 return max_min(expr, true, sup_n, sup_d, maximum); 00197 }
| bool Parma_Polyhedra_Library::Box< ITV >::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 217 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::max_min().
00219 { 00220 return max_min(expr, false, inf_n, inf_d, minimum, g); 00221 }
| bool Parma_Polyhedra_Library::Box< ITV >::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 209 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::max_min().
00211 { 00212 return max_min(expr, false, inf_n, inf_d, minimum); 00213 }
| Congruence_System Parma_Polyhedra_Library::Box< ITV >::minimized_congruences | ( | ) | const [inline] |
Returns a minimized system of congruences approximating *this.
Definition at line 370 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::congruences().
00370 { 00371 // Only equalities can be congruences and these are already minimized. 00372 return congruences(); 00373 }
| Constraint_System Parma_Polyhedra_Library::Box< ITV >::minimized_constraints | ( | ) | const [inline] |
Returns a minimized system of constraints defining *this.
Definition at line 3804 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::get_lower_bound(), Parma_Polyhedra_Library::Box< ITV >::get_upper_bound(), Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Constraint_System::zero_dim_empty().
03804 { 03805 Constraint_System cs; 03806 const dimension_type space_dim = space_dimension(); 03807 if (space_dim == 0) { 03808 if (marked_empty()) 03809 cs = Constraint_System::zero_dim_empty(); 03810 } 03811 // Make sure emptiness is detected. 03812 else if (is_empty()) 03813 cs.insert(0*Variable(space_dim-1) <= -1); 03814 else { 03815 // KLUDGE: in the future `cs' will be constructed of the right dimension. 03816 // For the time being, we force the dimension with the following line. 03817 cs.insert(0*Variable(space_dim-1) <= 0); 03818 03819 for (dimension_type k = 0; k < space_dim; ++k) { 03820 bool closed = false; 03821 PPL_DIRTY_TEMP(Coefficient, n); 03822 PPL_DIRTY_TEMP(Coefficient, d); 03823 if (get_lower_bound(k, closed, n, d)) { 03824 if (closed) 03825 // Make sure equality constraints are detected. 03826 if (seq[k].is_singleton()) { 03827 cs.insert(d*Variable(k) == n); 03828 continue; 03829 } 03830 else 03831 cs.insert(d*Variable(k) >= n); 03832 else 03833 cs.insert(d*Variable(k) > n); 03834 } 03835 if (get_upper_bound(k, closed, n, d)) { 03836 if (closed) 03837 cs.insert(d*Variable(k) <= n); 03838 else 03839 cs.insert(d*Variable(k) < n); 03840 } 03841 } 03842 } 03843 return cs; 03844 }
| bool Parma_Polyhedra_Library::Box< ITV >::OK | ( | ) | const [inline] |
Returns true if and only if *this satisfies all its invariants.
Definition at line 1245 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::check_empty(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::reset_empty_up_to_date(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::status, Parma_Polyhedra_Library::Box< ITV >::Status::test_empty(), and Parma_Polyhedra_Library::Box< ITV >::Status::test_empty_up_to_date().
Referenced by Parma_Polyhedra_Library::Box< ITV >::add_congruences_no_check(), Parma_Polyhedra_Library::Box< ITV >::add_constraints_no_check(), Parma_Polyhedra_Library::Box< ITV >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Box< ITV >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::Box< ITV >::affine_image(), Parma_Polyhedra_Library::Box< ITV >::affine_preimage(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Box< ITV >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Box< ITV >::CC76_widening_assign(), Parma_Polyhedra_Library::Box< ITV >::concatenate_assign(), Parma_Polyhedra_Library::Box< ITV >::difference_assign(), Parma_Polyhedra_Library::Box< ITV >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Box< ITV >::expand_space_dimension(), Parma_Polyhedra_Library::Box< ITV >::generalized_affine_preimage(), Parma_Polyhedra_Library::Box< ITV >::intersection_assign(), Parma_Polyhedra_Library::Box< ITV >::map_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::remove_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::set_interval(), Parma_Polyhedra_Library::Box< ITV >::simplify_using_context_assign(), Parma_Polyhedra_Library::Box< ITV >::time_elapse_assign(), Parma_Polyhedra_Library::Box< ITV >::unconstrain(), Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign(), and Parma_Polyhedra_Library::Box< ITV >::wrap_assign().
01245 { 01246 if (status.test_empty_up_to_date() && !status.test_empty()) { 01247 Box tmp = *this; 01248 tmp.reset_empty_up_to_date(); 01249 if (tmp.check_empty()) { 01250 #ifndef NDEBUG 01251 std::cerr << "The box is empty, but it is marked as non-empty." 01252 << std::endl; 01253 #endif // NDEBUG 01254 return false; 01255 } 01256 } 01257 01258 // A box that is not marked empty must have meaningful intervals. 01259 if (!marked_empty()) { 01260 for (dimension_type k = seq.size(); k-- > 0; ) 01261 if (!seq[k].OK()) 01262 return false; 01263 } 01264 01265 return true; 01266 }
| Box< ITV > & Parma_Polyhedra_Library::Box< ITV >::operator= | ( | const Box< ITV > & | y | ) | [inline] |
The assignment operator (*this and y can be dimension-incompatible).
Definition at line 76 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::seq, and Parma_Polyhedra_Library::Box< ITV >::status.
| const ITV & Parma_Polyhedra_Library::Box< ITV >::operator[] | ( | dimension_type | k | ) | const [inline, private] |
Returns a reference the interval that bounds the box on the k-th space dimension.
Definition at line 136 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::seq.
| void Parma_Polyhedra_Library::Box< ITV >::print | ( | ) | const |
Prints *this to std::cerr using operator<<.
| void Parma_Polyhedra_Library::Box< ITV >::propagate_constraint | ( | const Constraint & | c | ) | [inline] |
Use the constraint c for constraint propagation on *this.
| c | The constraint to be used for constraint propagation. |
| std::invalid_argument | Thrown if *this and c are dimension-incompatible. |
Definition at line 496 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::propagate_constraint_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
00496 { 00497 const dimension_type c_space_dim = c.space_dimension(); 00498 // Dimension-compatibility check. 00499 if (c_space_dim > space_dimension()) 00500 throw_dimension_incompatible("propagate_constraint(c)", c); 00501 00502 // If the box is already empty, there is nothing left to do. 00503 if (marked_empty()) 00504 return; 00505 00506 propagate_constraint_no_check(c); 00507 }
| void Parma_Polyhedra_Library::Box< ITV >::propagate_constraint_no_check | ( | const Constraint & | c | ) | [inline, private] |
Propagates the constraint c to refine *this.
| c | The constraint to be propagated. |
c and *this are dimension-incompatible, the behavior is undefined.For any expression
, we denote by
(resp.,
) the result of any computation that is guaranteed to yield an upper (resp., lower) approximation of
. So there exists
with
such that
. If
we say that the computation of
is exact; we say it is inexact otherwise. Similarly for
.
Consider a constraint of the general form
where
,
is a set of indices,
with
for each
, and
. The set
is subdivided into the disjoint sets
and
such that, for each
,
if
and
if
. Suppose that, for each
a variation interval
is known for
and that the infimum and the supremum of
are denoted, respectively, by
and
, where
.
For each
, we have
Thus, if
for each
and
for each
, we have
and, if
,
for each
and
for each
,
In the first inequality, the relation is strict if
, or if
for some
, or if
for some
, or if the computation is inexact. In the second inequality, the relation is strict if
for some
, or if
for some
, or if the computation is inexact.
For each
, we have
Thus, if
for each
and
for each
, we have
and, if
,
for each
and
for each
,
In the first inequality, the relation is strict if
, or if
for some
, or if
for some
, or if the computation is inexact. In the second inequality, the relation is strict if
for some
, or if
for some
, or if the computation is inexact.
Definition at line 2327 of file Box.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::Constraint::NONSTRICT_INEQUALITY, Parma_Polyhedra_Library::Box< ITV >::reset_empty_up_to_date(), Parma_Polyhedra_Library::Checked::Result, Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Constraint::STRICT_INEQUALITY, Parma_Polyhedra_Library::T_MAYBE, Parma_Polyhedra_Library::T_NO, Parma_Polyhedra_Library::T_YES, and Parma_Polyhedra_Library::Constraint::type().
Referenced by Parma_Polyhedra_Library::Box< ITV >::propagate_constraint(), and Parma_Polyhedra_Library::Box< ITV >::refine_no_check().
02327 { 02328 PPL_ASSERT(c.space_dimension() <= space_dimension()); 02329 02330 typedef 02331 typename Select_Temp_Boundary_Type<typename ITV::boundary_type>::type 02332 Temp_Boundary_Type; 02333 02334 const dimension_type c_space_dim = c.space_dimension(); 02335 const Constraint::Type c_type = c.type(); 02336 const Coefficient& c_inhomogeneous_term = c.inhomogeneous_term(); 02337 02338 // Find a space dimension having a non-zero coefficient (if any). 02339 dimension_type last_k = c_space_dim; 02340 for (dimension_type k = c_space_dim; k-- > 0; ) { 02341 if (c.coefficient(Variable(k)) != 0) { 02342 last_k = k; 02343 break; 02344 } 02345 } 02346 if (last_k == c_space_dim) { 02347 // Constraint c is trivial: check if it is inconsistent. 02348 if (c_inhomogeneous_term < 0 02349 || (c_inhomogeneous_term == 0 02350 && c_type != Constraint::NONSTRICT_INEQUALITY)) 02351 set_empty(); 02352 return; 02353 } 02354 02355 // Here constraint c is non-trivial. 02356 PPL_ASSERT(last_k < c_space_dim); 02357 Result r; 02358 Temp_Boundary_Type t_bound; 02359 Temp_Boundary_Type t_a; 02360 Temp_Boundary_Type t_x; 02361 Ternary open; 02362 for (dimension_type k = last_k+1; k-- > 0; ) { 02363 const Coefficient& a_k = c.coefficient(Variable(k)); 02364 int sgn_a_k = sgn(a_k); 02365 if (sgn_a_k == 0) 02366 continue; 02367 if (sgn_a_k > 0) { 02368 open = (c_type == Constraint::STRICT_INEQUALITY) ? T_YES : T_NO; 02369 if (open == T_NO) 02370 maybe_reset_fpu_inexact<Temp_Boundary_Type>(); 02371 r = assign_r(t_bound, c_inhomogeneous_term, ROUND_UP); 02372 if (propagate_constraint_check_result(r, open)) 02373 goto maybe_refine_upper_1; 02374 r = neg_assign_r(t_bound, t_bound, ROUND_DOWN); 02375 if (propagate_constraint_check_result(r, open)) 02376 goto maybe_refine_upper_1; 02377 for (dimension_type i = last_k+1; i-- > 0; ) { 02378 if (i == k) 02379 continue; 02380 const Coefficient& a_i = c.coefficient(Variable(i)); 02381 int sgn_a_i = sgn(a_i); 02382 if (sgn_a_i == 0) 02383 continue; 02384 ITV& x_i = seq[i]; 02385 if (sgn_a_i < 0) { 02386 if (x_i.lower_is_boundary_infinity()) 02387 goto maybe_refine_upper_1; 02388 r = assign_r(t_a, a_i, ROUND_DOWN); 02389 if (propagate_constraint_check_result(r, open)) 02390 goto maybe_refine_upper_1; 02391 r = assign_r(t_x, x_i.lower(), ROUND_DOWN); 02392 if (propagate_constraint_check_result(r, open)) 02393 goto maybe_refine_upper_1; 02394 if (x_i.lower_is_open()) 02395 open = T_YES; 02396 r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_DOWN); 02397 if (propagate_constraint_check_result(r, open)) 02398 goto maybe_refine_upper_1; 02399 } 02400 else { 02401 PPL_ASSERT(sgn_a_i > 0); 02402 if (x_i.upper_is_boundary_infinity()) 02403 goto maybe_refine_upper_1; 02404 r = assign_r(t_a, a_i, ROUND_UP); 02405 if (propagate_constraint_check_result(r, open)) 02406 goto maybe_refine_upper_1; 02407 r = assign_r(t_x, x_i.upper(), ROUND_UP); 02408 if (propagate_constraint_check_result(r, open)) 02409 goto maybe_refine_upper_1; 02410 if (x_i.upper_is_open()) 02411 open = T_YES; 02412 r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_DOWN); 02413 if (propagate_constraint_check_result(r, open)) 02414 goto maybe_refine_upper_1; 02415 } 02416 } 02417 r = assign_r(t_a, a_k, ROUND_UP); 02418 if (propagate_constraint_check_result(r, open)) 02419 goto maybe_refine_upper_1; 02420 r = div_assign_r(t_bound, t_bound, t_a, ROUND_DOWN); 02421 if (propagate_constraint_check_result(r, open)) 02422 goto maybe_refine_upper_1; 02423 02424 // Refine the lower bound of `seq[k]' with `t_bound'. 02425 if (open == T_MAYBE 02426 && maybe_check_fpu_inexact<Temp_Boundary_Type>() == 1) 02427 open = T_YES; 02428 seq[k].add_constraint(i_constraint(open == T_YES ? GREATER_THAN : GREATER_OR_EQUAL, t_bound)); 02429 reset_empty_up_to_date(); 02430 maybe_refine_upper_1: 02431 if (c_type != Constraint::EQUALITY) 02432 continue; 02433 open = T_NO; 02434 maybe_reset_fpu_inexact<Temp_Boundary_Type>(); 02435 r = assign_r(t_bound, c_inhomogeneous_term, ROUND_DOWN); 02436 if (propagate_constraint_check_result(r, open)) 02437 goto next_k; 02438 r = neg_assign_r(t_bound, t_bound, ROUND_UP); 02439 if (propagate_constraint_check_result(r, open)) 02440 goto next_k; 02441 for (dimension_type i = c_space_dim; i-- > 0; ) { 02442 if (i == k) 02443 continue; 02444 const Coefficient& a_i = c.coefficient(Variable(i)); 02445 int sgn_a_i = sgn(a_i); 02446 if (sgn_a_i == 0) 02447 continue; 02448 ITV& x_i = seq[i]; 02449 if (sgn_a_i < 0) { 02450 if (x_i.upper_is_boundary_infinity()) 02451 goto next_k; 02452 r = assign_r(t_a, a_i, ROUND_UP); 02453 if (propagate_constraint_check_result(r, open)) 02454 goto next_k; 02455 r = assign_r(t_x, x_i.upper(), ROUND_UP); 02456 if (propagate_constraint_check_result(r, open)) 02457 goto next_k; 02458 if (x_i.upper_is_open()) 02459 open = T_YES; 02460 r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_UP); 02461 if (propagate_constraint_check_result(r, open)) 02462 goto next_k; 02463 } 02464 else { 02465 PPL_ASSERT(sgn_a_i > 0); 02466 if (x_i.lower_is_boundary_infinity()) 02467 goto next_k; 02468 r = assign_r(t_a, a_i, ROUND_DOWN); 02469 if (propagate_constraint_check_result(r, open)) 02470 goto next_k; 02471 r = assign_r(t_x, x_i.lower(), ROUND_DOWN); 02472 if (propagate_constraint_check_result(r, open)) 02473 goto next_k; 02474 if (x_i.lower_is_open()) 02475 open = T_YES; 02476 r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_UP); 02477 if (propagate_constraint_check_result(r, open)) 02478 goto next_k; 02479 } 02480 } 02481 r = assign_r(t_a, a_k, ROUND_DOWN); 02482 if (propagate_constraint_check_result(r, open)) 02483 goto next_k; 02484 r = div_assign_r(t_bound, t_bound, t_a, ROUND_UP); 02485 if (propagate_constraint_check_result(r, open)) 02486 goto next_k; 02487 02488 // Refine the upper bound of seq[k] with t_bound. 02489 if (open == T_MAYBE 02490 && maybe_check_fpu_inexact<Temp_Boundary_Type>() == 1) 02491 open = T_YES; 02492 seq[k].add_constraint(i_constraint(open == T_YES ? LESS_THAN : LESS_OR_EQUAL, t_bound)); 02493 reset_empty_up_to_date(); 02494 } 02495 else { 02496 PPL_ASSERT(sgn_a_k < 0); 02497 open = (c_type == Constraint::STRICT_INEQUALITY) ? T_YES : T_NO; 02498 if (open == T_NO) 02499 maybe_reset_fpu_inexact<Temp_Boundary_Type>(); 02500 r = assign_r(t_bound, c_inhomogeneous_term, ROUND_UP); 02501 if (propagate_constraint_check_result(r, open)) 02502 goto maybe_refine_upper_2; 02503 r = neg_assign_r(t_bound, t_bound, ROUND_DOWN); 02504 if (propagate_constraint_check_result(r, open)) 02505 goto maybe_refine_upper_2; 02506 for (dimension_type i = c_space_dim; i-- > 0; ) { 02507 if (i == k) 02508 continue; 02509 const Coefficient& a_i = c.coefficient(Variable(i)); 02510 int sgn_a_i = sgn(a_i); 02511 if (sgn_a_i == 0) 02512 continue; 02513 ITV& x_i = seq[i]; 02514 if (sgn_a_i < 0) { 02515 if (x_i.lower_is_boundary_infinity()) 02516 goto maybe_refine_upper_2; 02517 r = assign_r(t_a, a_i, ROUND_DOWN); 02518 if (propagate_constraint_check_result(r, open)) 02519 goto maybe_refine_upper_2; 02520 r = assign_r(t_x, x_i.lower(), ROUND_DOWN); 02521 if (propagate_constraint_check_result(r, open)) 02522 goto maybe_refine_upper_2; 02523 if (x_i.lower_is_open()) 02524 open = T_YES; 02525 r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_UP); 02526 if (propagate_constraint_check_result(r, open)) 02527 goto maybe_refine_upper_2; 02528 } 02529 else { 02530 PPL_ASSERT(sgn_a_i > 0); 02531 if (x_i.upper_is_boundary_infinity()) 02532 goto maybe_refine_upper_2; 02533 r = assign_r(t_a, a_i, ROUND_UP); 02534 if (propagate_constraint_check_result(r, open)) 02535 goto maybe_refine_upper_2; 02536 r = assign_r(t_x, x_i.upper(), ROUND_UP); 02537 if (propagate_constraint_check_result(r, open)) 02538 goto maybe_refine_upper_2; 02539 if (x_i.upper_is_open()) 02540 open = T_YES; 02541 r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_DOWN); 02542 if (propagate_constraint_check_result(r, open)) 02543 goto maybe_refine_upper_2; 02544 } 02545 } 02546 r = assign_r(t_a, a_k, ROUND_UP); 02547 if (propagate_constraint_check_result(r, open)) 02548 goto maybe_refine_upper_2; 02549 r = div_assign_r(t_bound, t_bound, t_a, ROUND_UP); 02550 if (propagate_constraint_check_result(r, open)) 02551 goto maybe_refine_upper_2; 02552 02553 // Refine the upper bound of seq[k] with t_bound. 02554 if (open == T_MAYBE 02555 && maybe_check_fpu_inexact<Temp_Boundary_Type>() == 1) 02556 open = T_YES; 02557 seq[k].add_constraint(i_constraint(open == T_YES ? LESS_THAN : LESS_OR_EQUAL, t_bound)); 02558 reset_empty_up_to_date(); 02559 maybe_refine_upper_2: 02560 if (c_type != Constraint::EQUALITY) 02561 continue; 02562 open = T_NO; 02563 maybe_reset_fpu_inexact<Temp_Boundary_Type>(); 02564 r = assign_r(t_bound, c_inhomogeneous_term, ROUND_DOWN); 02565 if (propagate_constraint_check_result(r, open)) 02566 goto next_k; 02567 r = neg_assign_r(t_bound, t_bound, ROUND_UP); 02568 if (propagate_constraint_check_result(r, open)) 02569 goto next_k; 02570 for (dimension_type i = c_space_dim; i-- > 0; ) { 02571 if (i == k) 02572 continue; 02573 const Coefficient& a_i = c.coefficient(Variable(i)); 02574 int sgn_a_i = sgn(a_i); 02575 if (sgn_a_i == 0) 02576 continue; 02577 ITV& x_i = seq[i]; 02578 if (sgn_a_i < 0) { 02579 if (x_i.upper_is_boundary_infinity()) 02580 goto next_k; 02581 r = assign_r(t_a, a_i, ROUND_UP); 02582 if (propagate_constraint_check_result(r, open)) 02583 goto next_k; 02584 r = assign_r(t_x, x_i.upper(), ROUND_UP); 02585 if (propagate_constraint_check_result(r, open)) 02586 goto next_k; 02587 if (x_i.upper_is_open()) 02588 open = T_YES; 02589 r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_UP); 02590 if (propagate_constraint_check_result(r, open)) 02591 goto next_k; 02592 } 02593 else { 02594 PPL_ASSERT(sgn_a_i > 0); 02595 if (x_i.lower_is_boundary_infinity()) 02596 goto next_k; 02597 r = assign_r(t_a, a_i, ROUND_DOWN); 02598 if (propagate_constraint_check_result(r, open)) 02599 goto next_k; 02600 r = assign_r(t_x, x_i.lower(), ROUND_DOWN); 02601 if (propagate_constraint_check_result(r, open)) 02602 goto next_k; 02603 if (x_i.lower_is_open()) 02604 open = T_YES; 02605 r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_UP); 02606 if (propagate_constraint_check_result(r, open)) 02607 goto next_k; 02608 } 02609 } 02610 r = assign_r(t_a, a_k, ROUND_DOWN); 02611 if (propagate_constraint_check_result(r, open)) 02612 goto next_k; 02613 r = div_assign_r(t_bound, t_bound, t_a, ROUND_DOWN); 02614 if (propagate_constraint_check_result(r, open)) 02615 goto next_k; 02616 02617 // Refine the lower bound of seq[k] with t_bound. 02618 if (open == T_MAYBE 02619 && maybe_check_fpu_inexact<Temp_Boundary_Type>() == 1) 02620 open = T_YES; 02621 seq[k].add_constraint(i_constraint(open == T_YES ? GREATER_THAN : GREATER_OR_EQUAL, t_bound)); 02622 reset_empty_up_to_date(); 02623 } 02624 next_k: 02625 ; 02626 } 02627 }
| void Parma_Polyhedra_Library::Box< ITV >::propagate_constraints | ( | const Constraint_System & | cs, | |
| dimension_type | max_iterations = 0 | |||
| ) | [inline] |
Use the constraints in cs for constraint propagagion on *this.
| cs | The constraints to be used for constraint propagation. | |
| max_iterations | The maximum number of propagation steps for each constraint in cs. If zero (the default), the number of propagations will be unbounded, possibly resulting in an infinite loop. |
| std::invalid_argument | Thrown if *this and cs are dimension-incompatible. |
max_iterations is 0. Definition at line 511 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::propagate_constraints_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
00512 { 00513 // Dimension-compatibility check. 00514 if (cs.space_dimension() > space_dimension()) 00515 throw_dimension_incompatible("propagate_constraints(cs)", cs); 00516 00517 // If the box is already empty, there is nothing left to do. 00518 if (marked_empty()) 00519 return; 00520 00521 propagate_constraints_no_check(cs, max_iterations); 00522 }
| void Parma_Polyhedra_Library::Box< ITV >::propagate_constraints_no_check | ( | const Constraint_System & | cs, | |
| dimension_type | max_iterations | |||
| ) | [inline, private] |
Propagates the constraints in cs to refine *this.
| cs | The constraints to be propagated. | |
| max_iterations | The maximum number of propagation steps for each constraint in cs. If zero, the number of propagations will be unbounded, possibly resulting in an infinite loop. |
cs and *this are dimension-incompatible, the behavior is undefined.max_iterations is 0. Definition at line 2690 of file Box.templates.hh.
References Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::maybe_abandon(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), WEIGHT_ADD_MUL, and WEIGHT_BEGIN.
Referenced by Parma_Polyhedra_Library::Box< ITV >::Box(), and Parma_Polyhedra_Library::Box< ITV >::propagate_constraints().
02691 { 02692 const dimension_type space_dim = space_dimension(); 02693 PPL_ASSERT(cs.space_dimension() <= space_dim); 02694 02695 const Constraint_System::const_iterator cs_begin = cs.begin(); 02696 const Constraint_System::const_iterator cs_end = cs.end(); 02697 const dimension_type cs_size = std::distance(cs_begin, cs_end); 02698 const dimension_type propagation_weight = cs_size * space_dim; 02699 02700 Sequence copy; 02701 bool changed; 02702 dimension_type num_iterations = 0; 02703 do { 02704 WEIGHT_BEGIN(); 02705 ++num_iterations; 02706 copy = seq; 02707 for (Constraint_System::const_iterator i = cs_begin; i != cs_end; ++i) 02708 propagate_constraint_no_check(*i); 02709 02710 WEIGHT_ADD_MUL(40, propagation_weight); 02711 // Check if the client has requested abandoning all expensive 02712 // computations. If so, the exception specified by the client 02713 // is thrown now. 02714 maybe_abandon(); 02715 02716 // NOTE: if max_iterations == 0 (i.e., no iteration limit is set) 02717 // the following test will anyway trigger on wrap around. 02718 if (num_iterations == max_iterations) 02719 break; 02720 02721 changed = (copy != seq); 02722 } while (changed); 02723 }
| I_Result Parma_Polyhedra_Library::Box< ITV >::refine_interval_no_check | ( | ITV & | itv, | |
| Constraint::Type | type, | |||
| Coefficient_traits::const_reference | num, | |||
| Coefficient_traits::const_reference | den | |||
| ) | [inline, static, private] |
WRITE ME.
Definition at line 377 of file Box.inlines.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::Constraint::NONSTRICT_INEQUALITY, and Parma_Polyhedra_Library::Constraint::STRICT_INEQUALITY.
Referenced by Parma_Polyhedra_Library::Box< ITV >::wrap_assign().
00380 { 00381 PPL_ASSERT(den != 0); 00382 // The interval constraint is of the form 00383 // `var + num / den rel 0', 00384 // where `rel' is either the relation `==', `>=', or `>'. 00385 // For the purpose of refining the interval, this is 00386 // (morally) turned into `var rel -num/den'. 00387 PPL_DIRTY_TEMP0(mpq_class, q); 00388 assign_r(q.get_num(), num, ROUND_NOT_NEEDED); 00389 assign_r(q.get_den(), den, ROUND_NOT_NEEDED); 00390 q.canonicalize(); 00391 // Turn `num/den' into `-num/den'. 00392 q = -q; 00393 00394 I_Result res; 00395 switch (type) { 00396 case Constraint::EQUALITY: 00397 res = itv.add_constraint(i_constraint(EQUAL, q)); 00398 break; 00399 case Constraint::NONSTRICT_INEQUALITY: 00400 res = itv.add_constraint(i_constraint(den > 0 00401 ? GREATER_OR_EQUAL 00402 : LESS_OR_EQUAL, q)); 00403 break; 00404 case Constraint::STRICT_INEQUALITY: 00405 res = itv.add_constraint(i_constraint(den > 0 00406 ? GREATER_THAN 00407 : LESS_THAN, q)); 00408 break; 00409 default: 00410 // Silence an annoying GCC warning (should never reach this point). 00411 PPL_ASSERT(false); 00412 res = I_ANY; 00413 } 00414 PPL_ASSERT(itv.OK()); 00415 return res; 00416 }
| void Parma_Polyhedra_Library::Box< ITV >::refine_no_check | ( | const Congruence_System & | cgs | ) | [inline, private] |
Uses the congruences in cgs to refine *this.
| cgs | The congruences to be added. Nontrivial proper congruences are ignored. |
cgs and *this are dimension-incompatible, the behavior is undefined. Definition at line 2288 of file Box.templates.hh.
References Parma_Polyhedra_Library::Congruence_System::begin(), Parma_Polyhedra_Library::Congruence_System::end(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Congruence_System::space_dimension().
02288 { 02289 PPL_ASSERT(cgs.space_dimension() <= space_dimension()); 02290 for (Congruence_System::const_iterator i = cgs.begin(), 02291 cgs_end = cgs.end(); !marked_empty() && i != cgs_end; ++i) 02292 refine_no_check(*i); 02293 PPL_ASSERT(OK()); 02294 }
| void Parma_Polyhedra_Library::Box< ITV >::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. |
cg and *this are dimension-incompatible, the behavior is undefined. Definition at line 2267 of file Box.templates.hh.
References Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Congruence::is_proper_congruence(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Congruence::space_dimension().
02267 { 02268 PPL_ASSERT(!marked_empty()); 02269 02270 PPL_ASSERT(cg.space_dimension() <= space_dimension()); 02271 02272 if (cg.is_proper_congruence()) { 02273 // FIXME: also deal with the case of interval with restrictions. 02274 // A proper congruences is also an interval constraint 02275 // if and only if it is trivial. 02276 if (cg.is_inconsistent()) 02277 set_empty(); 02278 return; 02279 } 02280 02281 PPL_ASSERT(cg.is_equality()); 02282 Constraint c(cg); 02283 refine_no_check(c); 02284 }
| void Parma_Polyhedra_Library::Box< ITV >::refine_no_check | ( | const Constraint_System & | cs | ) | [inline, private] |
Uses the constraints in cs to refine *this.
| cs | The constraints to be used for the refinement. To avoid termination problems, each constraint in cs will be used for a single refinement step. |
cs and *this are dimension-incompatible, the behavior is undefined. Definition at line 2257 of file Box.templates.hh.
References Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Constraint_System::space_dimension().
02257 { 02258 PPL_ASSERT(cs.space_dimension() <= space_dimension()); 02259 for (Constraint_System::const_iterator i = cs.begin(), 02260 cs_end = cs.end(); !marked_empty() && i != cs_end; ++i) 02261 refine_no_check(*i); 02262 PPL_ASSERT(OK()); 02263 }
| void Parma_Polyhedra_Library::Box< ITV >::refine_no_check | ( | const Constraint & | c | ) | [inline, private] |
Uses the constraint c to refine *this.
| c | The constraint to be used for the refinement. |
c and *this are dimension-incompatible, the behavior is undefined. Definition at line 2227 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::add_interval_constraint_no_check(), Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Box< ITV >::extract_interval_constraint(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::propagate_constraint_no_check(), Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), and Parma_Polyhedra_Library::Constraint::type().
Referenced by Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::refine_with_congruence(), Parma_Polyhedra_Library::Box< ITV >::refine_with_congruences(), Parma_Polyhedra_Library::Box< ITV >::refine_with_constraint(), and Parma_Polyhedra_Library::Box< ITV >::refine_with_constraints().
02227 { 02228 const dimension_type c_space_dim = c.space_dimension(); 02229 PPL_ASSERT(c.space_dimension() <= space_dimension()); 02230 PPL_ASSERT(!marked_empty()); 02231 02232 dimension_type c_num_vars = 0; 02233 dimension_type c_only_var = 0; 02234 // Non-interval constraints are approximated. 02235 if (!extract_interval_constraint(c, c_space_dim, c_num_vars, c_only_var)) { 02236 propagate_constraint_no_check(c); 02237 return; 02238 } 02239 02240 const Coefficient& n = c.inhomogeneous_term(); 02241 if (c_num_vars == 0) { 02242 // Dealing with a trivial constraint. 02243 if (n < 0 02244 || (c.is_equality() && n != 0) 02245 || (c.is_strict_inequality() && n == 0)) 02246 set_empty(); 02247 return; 02248 } 02249 02250 PPL_ASSERT(c_num_vars == 1); 02251 const Coefficient& d = c.coefficient(Variable(c_only_var)); 02252 add_interval_constraint_no_check(c_only_var, c.type(), n, d); 02253 }
| void Parma_Polyhedra_Library::Box< ITV >::refine_with_congruence | ( | const Congruence & | cg | ) | [inline] |
Use the congruence cg to refine *this.
| cg | The congruence to be used for refinement. |
| std::invalid_argument | Thrown if *this and cg are dimension-incompatible. |
Definition at line 467 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Congruence::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
00467 { 00468 const dimension_type cg_space_dim = cg.space_dimension(); 00469 // Dimension-compatibility check. 00470 if (cg_space_dim > space_dimension()) 00471 throw_dimension_incompatible("refine_with_congruence(cg)", cg); 00472 00473 // If the box is already empty, there is nothing left to do. 00474 if (marked_empty()) 00475 return; 00476 00477 refine_no_check(cg); 00478 }
| void Parma_Polyhedra_Library::Box< ITV >::refine_with_congruences | ( | const Congruence_System & | cgs | ) | [inline] |
Use the congruences in cgs to refine *this.
| cgs | The congruences to be used for refinement. |
| std::invalid_argument | Thrown if *this and cgs are dimension-incompatible. |
Definition at line 482 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Congruence_System::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
00482 { 00483 // Dimension-compatibility check. 00484 if (cgs.space_dimension() > space_dimension()) 00485 throw_dimension_incompatible("refine_with_congruences(cgs)", cgs); 00486 00487 // If the box is already empty, there is nothing left to do. 00488 if (marked_empty()) 00489 return; 00490 00491 refine_no_check(cgs); 00492 }
| void Parma_Polyhedra_Library::Box< ITV >::refine_with_constraint | ( | const Constraint & | c | ) | [inline] |
Use the constraint c to refine *this.
| c | The constraint to be used for refinement. |
| std::invalid_argument | Thrown if *this and c are dimension-incompatible. |
Definition at line 438 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
00438 { 00439 const dimension_type c_space_dim = c.space_dimension(); 00440 // Dimension-compatibility check. 00441 if (c_space_dim > space_dimension()) 00442 throw_dimension_incompatible("refine_with_constraint(c)", c); 00443 00444 // If the box is already empty, there is nothing left to do. 00445 if (marked_empty()) 00446 return; 00447 00448 refine_no_check(c); 00449 }
| void Parma_Polyhedra_Library::Box< ITV >::refine_with_constraints | ( | const Constraint_System & | cs | ) | [inline] |
Use the constraints in cs to refine *this.
| cs | The constraints to be used for refinement. To avoid termination problems, each constraint in cs will be used for a single refinement step. |
| std::invalid_argument | Thrown if *this and cs are dimension-incompatible. |
cs, which is in general unpredictable. If a fine control on such an order is needed, the user should consider calling the method refine_with_constraint(const Constraint& c) inside an appropriate looping construct. Definition at line 453 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Box< ITV >::wrap_assign().
00453 { 00454 // Dimension-compatibility check. 00455 if (cs.space_dimension() > space_dimension()) 00456 throw_dimension_incompatible("refine_with_constraints(cs)", cs); 00457 00458 // If the box is already empty, there is nothing left to do. 00459 if (marked_empty()) 00460 return; 00461 00462 refine_no_check(cs); 00463 }
| Poly_Gen_Relation Parma_Polyhedra_Library::Box< ITV >::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 918 of file Box.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Generator::coefficient(), Parma_Polyhedra_Library::Generator::divisor(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Generator::is_line(), Parma_Polyhedra_Library::Generator::is_line_or_ray(), Parma_Polyhedra_Library::Generator::is_point(), Parma_Polyhedra_Library::Generator::is_ray(), Parma_Polyhedra_Library::Poly_Gen_Relation::nothing(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Generator::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Poly_Gen_Relation::subsumes(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
00918 { 00919 const dimension_type space_dim = space_dimension(); 00920 const dimension_type g_space_dim = g.space_dimension(); 00921 00922 // Dimension-compatibility check. 00923 if (space_dim < g_space_dim) 00924 throw_dimension_incompatible("relation_with(g)", g); 00925 00926 // The empty box cannot subsume a generator. 00927 if (is_empty()) 00928 return Poly_Gen_Relation::nothing(); 00929 00930 // A universe box in a zero-dimensional space subsumes 00931 // all the generators of a zero-dimensional space. 00932 if (space_dim == 0) 00933 return Poly_Gen_Relation::subsumes(); 00934 00935 if (g.is_line_or_ray()) { 00936 if (g.is_line()) { 00937 for (dimension_type i = g_space_dim; i-- > 0; ) 00938 if (g.coefficient(Variable(i)) != 0 && !seq[i].is_universe()) 00939 return Poly_Gen_Relation::nothing(); 00940 return Poly_Gen_Relation::subsumes(); 00941 } 00942 else { 00943 PPL_ASSERT(g.is_ray()); 00944 for (dimension_type i = g_space_dim; i-- > 0; ) 00945 switch (sgn(g.coefficient(Variable(i)))) { 00946 case 1: 00947 if (!seq[i].upper_is_boundary_infinity()) 00948 return Poly_Gen_Relation::nothing(); 00949 break; 00950 case 0: 00951 break; 00952 case -1: 00953 if (!seq[i].lower_is_boundary_infinity()) 00954 return Poly_Gen_Relation::nothing(); 00955 break; 00956 } 00957 return Poly_Gen_Relation::subsumes(); 00958 } 00959 } 00960 00961 // Here `g' is a point or closure point. 00962 const Coefficient& g_divisor = g.divisor(); 00963 PPL_DIRTY_TEMP0(mpq_class, g_coord); 00964 PPL_DIRTY_TEMP0(mpq_class, bound); 00965 for (dimension_type i = g_space_dim; i-- > 0; ) { 00966 const ITV& seq_i = seq[i]; 00967 if (seq_i.is_universe()) 00968 continue; 00969 assign_r(g_coord.get_num(), g.coefficient(Variable(i)), ROUND_NOT_NEEDED); 00970 assign_r(g_coord.get_den(), g_divisor, ROUND_NOT_NEEDED); 00971 g_coord.canonicalize(); 00972 // Check lower bound. 00973 if (!seq_i.lower_is_boundary_infinity()) { 00974 assign_r(bound, seq_i.lower(), ROUND_NOT_NEEDED); 00975 if (g_coord <= bound) { 00976 if (seq_i.lower_is_open()) { 00977 if (g.is_point() || g_coord != bound) 00978 return Poly_Gen_Relation::nothing(); 00979 } 00980 else if (g_coord != bound) 00981 return Poly_Gen_Relation::nothing(); 00982 } 00983 } 00984 // Check upper bound. 00985 if (!seq_i.upper_is_boundary_infinity()) { 00986 assign_r(bound, seq_i.upper(), ROUND_NOT_NEEDED); 00987 if (g_coord >= bound) { 00988 if (seq_i.upper_is_open()) { 00989 if (g.is_point() || g_coord != bound) 00990 return Poly_Gen_Relation::nothing(); 00991 } 00992 else if (g_coord != bound) 00993 return Poly_Gen_Relation::nothing(); 00994 } 00995 } 00996 } 00997 return Poly_Gen_Relation::subsumes(); 00998 }
| Poly_Con_Relation Parma_Polyhedra_Library::Box< ITV >::relation_with | ( | const Congruence & | cg | ) | const [inline] |
Returns the relations holding between *this and the congruence cg.
| std::invalid_argument | Thrown if *this and constraint cg are dimension-incompatible. |
Definition at line 771 of file Box.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Congruence::coefficient(), Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::Congruence::inhomogeneous_term(), Parma_Polyhedra_Library::interval_relation(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Congruence::modulus(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Box< ITV >::relation_with(), Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Congruence::space_dimension(), Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
00771 { 00772 const dimension_type cg_space_dim = cg.space_dimension(); 00773 const dimension_type space_dim = space_dimension(); 00774 00775 // Dimension-compatibility check. 00776 if (cg_space_dim > space_dim) 00777 throw_dimension_incompatible("relation_with(cg)", cg); 00778 00779 if (is_empty()) 00780 return Poly_Con_Relation::saturates() 00781 && Poly_Con_Relation::is_included() 00782 && Poly_Con_Relation::is_disjoint(); 00783 00784 if (space_dim == 0) { 00785 if (cg.is_inconsistent()) 00786 return Poly_Con_Relation::is_disjoint(); 00787 else 00788 return Poly_Con_Relation::saturates() 00789 && Poly_Con_Relation::is_included(); 00790 } 00791 00792 if (cg.is_equality()) { 00793 const Constraint c(cg); 00794 return relation_with(c); 00795 } 00796 00797 PPL_DIRTY_TEMP0(Rational_Interval, r); 00798 PPL_DIRTY_TEMP0(Rational_Interval, t); 00799 PPL_DIRTY_TEMP0(mpq_class, m); 00800 r = 0; 00801 for (dimension_type i = cg.space_dimension(); i-- > 0; ) { 00802 const Coefficient& cg_i = cg.coefficient(Variable(i)); 00803 if (sgn(cg_i) != 0) { 00804 assign_r(m, cg_i, ROUND_NOT_NEEDED); 00805 // FIXME: an add_mul_assign() method would come handy here. 00806 t.build(seq[i].lower_constraint(), seq[i].upper_constraint()); 00807 t *= m; 00808 r += t; 00809 } 00810 } 00811 00812 if (r.lower_is_boundary_infinity() || r.upper_is_boundary_infinity()) 00813 return Poly_Con_Relation::strictly_intersects(); 00814 00815 00816 // Find the value that satisfies the congruence and is 00817 // nearest to the lower bound such that the point lies on or above it. 00818 00819 PPL_DIRTY_TEMP_COEFFICIENT(lower); 00820 PPL_DIRTY_TEMP_COEFFICIENT(mod); 00821 PPL_DIRTY_TEMP_COEFFICIENT(v); 00822 mod = cg.modulus(); 00823 v = cg.inhomogeneous_term() % mod; 00824 assign_r(lower, r.lower(), ROUND_DOWN); 00825 v -= ((lower / mod) * mod); 00826 if (v + lower > 0) 00827 v -= mod; 00828 return interval_relation(r, Constraint::EQUALITY, v); 00829 }
| Poly_Con_Relation Parma_Polyhedra_Library::Box< ITV >::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 833 of file Box.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Box< ITV >::extract_interval_constraint(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::interval_relation(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), 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_strict_inequality(), Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Constraint::type().
Referenced by Parma_Polyhedra_Library::Box< ITV >::relation_with().
00833 { 00834 const dimension_type c_space_dim = c.space_dimension(); 00835 const dimension_type space_dim = space_dimension(); 00836 00837 // Dimension-compatibility check. 00838 if (c_space_dim > space_dim) 00839 throw_dimension_incompatible("relation_with(c)", c); 00840 00841 if (is_empty()) 00842 return Poly_Con_Relation::saturates() 00843 && Poly_Con_Relation::is_included() 00844 && Poly_Con_Relation::is_disjoint(); 00845 00846 if (space_dim == 0) { 00847 if ((c.is_equality() && c.inhomogeneous_term() != 0) 00848 || (c.is_inequality() && c.inhomogeneous_term() < 0)) 00849 return Poly_Con_Relation::is_disjoint(); 00850 else if (c.is_strict_inequality() && c.inhomogeneous_term() == 0) 00851 // The constraint 0 > 0 implicitly defines the hyperplane 0 = 0; 00852 // thus, the zero-dimensional point also saturates it. 00853 return Poly_Con_Relation::saturates() 00854 && Poly_Con_Relation::is_disjoint(); 00855 else if (c.is_equality() || c.inhomogeneous_term() == 0) 00856 return Poly_Con_Relation::saturates() 00857 && Poly_Con_Relation::is_included(); 00858 else 00859 // The zero-dimensional point saturates 00860 // neither the positivity constraint 1 >= 0, 00861 // nor the strict positivity constraint 1 > 0. 00862 return Poly_Con_Relation::is_included(); 00863 } 00864 00865 dimension_type c_num_vars = 0; 00866 dimension_type c_only_var = 0; 00867 00868 if (extract_interval_constraint(c, c_space_dim, c_num_vars, c_only_var)) 00869 if (c_num_vars == 0) 00870 // c is a trivial constraint. 00871 switch (sgn(c.inhomogeneous_term())) { 00872 case -1: 00873 return Poly_Con_Relation::is_disjoint(); 00874 case 0: 00875 if (c.is_strict_inequality()) 00876 return Poly_Con_Relation::saturates() 00877 && Poly_Con_Relation::is_disjoint(); 00878 else 00879 return Poly_Con_Relation::saturates() 00880 && Poly_Con_Relation::is_included(); 00881 case 1: 00882 return Poly_Con_Relation::is_included(); 00883 } 00884 else { 00885 // c is an interval constraint. 00886 return interval_relation(seq[c_only_var], 00887 c.type(), 00888 c.inhomogeneous_term(), 00889 c.coefficient(Variable(c_only_var))); 00890 } 00891 else { 00892 // Deal with a non-trivial and non-interval constraint. 00893 PPL_DIRTY_TEMP0(Rational_Interval, r); 00894 PPL_DIRTY_TEMP0(Rational_Interval, t); 00895 PPL_DIRTY_TEMP0(mpq_class, m); 00896 r = 0; 00897 for (dimension_type i = c.space_dimension(); i-- > 0; ) { 00898 const Coefficient& c_i = c.coefficient(Variable(i)); 00899 if (sgn(c_i) != 0) { 00900 assign_r(m, c_i, ROUND_NOT_NEEDED); 00901 // FIXME: an add_mul_assign() method would come handy here. 00902 t.build(seq[i].lower_constraint(), seq[i].upper_constraint()); 00903 t *= m; 00904 r += t; 00905 } 00906 } 00907 return interval_relation(r, 00908 c.type(), 00909 c.inhomogeneous_term()); 00910 } 00911 00912 // Quiet a compiler warning: this program point is unreachable. 00913 throw std::runtime_error("PPL internal error"); 00914 }
| void Parma_Polyhedra_Library::Box< ITV >::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 2030 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Box< ITV >::map_space_dimensions().
02030 { 02031 // Dimension-compatibility check: the variable having 02032 // maximum index is the one occurring last in the set. 02033 const dimension_type old_dim = space_dimension(); 02034 if (new_dim > old_dim) 02035 throw_dimension_incompatible("remove_higher_space_dimensions(nd)", 02036 new_dim); 02037 02038 // The removal of no dimensions from any box is a no-op. 02039 // Note that this case also captures the only legal removal of 02040 // dimensions from a zero-dim space box. 02041 if (new_dim == old_dim) { 02042 PPL_ASSERT(OK()); 02043 return; 02044 } 02045 02046 seq.erase(seq.begin() + new_dim, seq.end()); 02047 PPL_ASSERT(OK()); 02048 }
| void Parma_Polyhedra_Library::Box< ITV >::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 1977 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Box< ITV >::fold_space_dimensions().
01977 { 01978 // The removal of no dimensions from any box is a no-op. 01979 // Note that this case also captures the only legal removal of 01980 // space dimensions from a box in a zero-dimensional space. 01981 if (vars.empty()) { 01982 PPL_ASSERT(OK()); 01983 return; 01984 } 01985 01986 const dimension_type old_space_dim = space_dimension(); 01987 01988 // Dimension-compatibility check. 01989 const dimension_type vsi_space_dim = vars.space_dimension(); 01990 if (old_space_dim < vsi_space_dim) 01991 throw_dimension_incompatible("remove_space_dimensions(vs)", 01992 vsi_space_dim); 01993 01994 const dimension_type new_space_dim = old_space_dim - vars.size(); 01995 01996 // If the box is empty (this must be detected), then resizing is all 01997 // what is needed. If it is not empty and we are removing _all_ the 01998 // dimensions then, again, resizing suffices. 01999 if (is_empty() || new_space_dim == 0) { 02000 seq.resize(new_space_dim); 02001 PPL_ASSERT(OK()); 02002 return; 02003 } 02004 02005 // For each variable to be removed, we fill the corresponding interval 02006 // by shifting left those intervals that will not be removed. 02007 Variables_Set::const_iterator vsi = vars.begin(); 02008 Variables_Set::const_iterator vsi_end = vars.end(); 02009 dimension_type dst = *vsi; 02010 dimension_type src = dst + 1; 02011 for (++vsi; vsi != vsi_end; ++vsi) { 02012 const dimension_type vsi_next = *vsi; 02013 // All intervals in between are moved to the left. 02014 while (src < vsi_next) 02015 seq[dst++].swap(seq[src++]); 02016 ++src; 02017 } 02018 // Moving the remaining intervals. 02019 while (src < old_space_dim) 02020 seq[dst++].swap(seq[src++]); 02021 02022 PPL_ASSERT(dst == new_space_dim); 02023 seq.resize(new_space_dim); 02024 02025 PPL_ASSERT(OK()); 02026 }
| void Parma_Polyhedra_Library::Box< ITV >::reset_empty_up_to_date | ( | ) | [inline, private] |
Invalidates empty flag of *this.
Definition at line 64 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::Status::reset_empty_up_to_date(), and Parma_Polyhedra_Library::Box< ITV >::status.
Referenced by Parma_Polyhedra_Library::Box< ITV >::concatenate_assign(), Parma_Polyhedra_Library::Box< ITV >::intersection_assign(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::propagate_constraint_no_check(), Parma_Polyhedra_Library::Box< ITV >::set_interval(), and Parma_Polyhedra_Library::Box< ITV >::wrap_assign().
00064 { 00065 return status.reset_empty_up_to_date(); 00066 }
| void Parma_Polyhedra_Library::Box< ITV >::set_empty | ( | ) | [inline] |
Causes the box to become empty, i.e., to represent the empty set.
Definition at line 44 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::Status::set_empty(), Parma_Polyhedra_Library::Box< ITV >::Status::set_empty_up_to_date(), and Parma_Polyhedra_Library::Box< ITV >::status.
Referenced by Parma_Polyhedra_Library::Box< ITV >::add_congruence_no_check(), Parma_Polyhedra_Library::Box< ITV >::add_constraint_no_check(), Parma_Polyhedra_Library::Box< ITV >::affine_preimage(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Box< ITV >::check_empty(), Parma_Polyhedra_Library::Box< ITV >::concatenate_assign(), Parma_Polyhedra_Library::Box< ITV >::difference_assign(), Parma_Polyhedra_Library::Box< ITV >::intersection_assign(), Parma_Polyhedra_Library::Box< ITV >::propagate_constraint_no_check(), Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::time_elapse_assign(), Parma_Polyhedra_Library::Box< ITV >::unconstrain(), and Parma_Polyhedra_Library::Box< ITV >::wrap_assign().
00044 { 00045 status.set_empty(); 00046 status.set_empty_up_to_date(); 00047 }
| void Parma_Polyhedra_Library::Box< ITV >::set_empty_up_to_date | ( | ) | [inline, private] |
Asserts the validity of the empty flag of *this.
Definition at line 58 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::Status::set_empty_up_to_date(), and Parma_Polyhedra_Library::Box< ITV >::status.
Referenced by Parma_Polyhedra_Library::Box< ITV >::Box().
00058 { 00059 status.set_empty_up_to_date(); 00060 }
| void Parma_Polyhedra_Library::Box< ITV >::set_interval | ( | Variable | var, | |
| const ITV & | i | |||
| ) | [inline] |
Sets to i the interval that bounds var.
| std::invalid_argument | Thrown if var is not a space dimension of *this. |
Definition at line 157 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::reset_empty_up_to_date(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
00157 { 00158 const dimension_type space_dim = space_dimension(); 00159 if (space_dim < var.space_dimension()) 00160 throw_dimension_incompatible("set_interval(v, i)", "v", var); 00161 00162 if (is_empty() && space_dim >= 2) 00163 // If the box is empty, and has dimension >= 2, setting only one 00164 // interval will not make it non-empty. 00165 return; 00166 00167 seq[var.id()] = i; 00168 reset_empty_up_to_date(); 00169 00170 PPL_ASSERT(OK()); 00171 }
| void Parma_Polyhedra_Library::Box< ITV >::set_nonempty | ( | ) | [inline, private] |
Marks *this as definitely not empty.
Definition at line 51 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::Status::reset_empty(), Parma_Polyhedra_Library::Box< ITV >::Status::set_empty_up_to_date(), and Parma_Polyhedra_Library::Box< ITV >::status.
Referenced by Parma_Polyhedra_Library::Box< ITV >::check_empty(), and Parma_Polyhedra_Library::Box< ITV >::simplify_using_context_assign().
00051 { 00052 status.reset_empty(); 00053 status.set_empty_up_to_date(); 00054 }
| bool Parma_Polyhedra_Library::Box< ITV >::simplify_using_context_assign | ( | const Box< ITV > & | 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 dimension-incompatible. |
Definition at line 1863 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_nonempty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::UNIVERSE.
01863 { 01864 Box& x = *this; 01865 const dimension_type num_dims = x.space_dimension(); 01866 // Dimension-compatibility check. 01867 if (num_dims != y.space_dimension()) 01868 x.throw_dimension_incompatible("simplify_using_context_assign(y)", y); 01869 01870 // Filter away the zero-dimensional case. 01871 if (num_dims == 0) { 01872 if (y.marked_empty()) { 01873 x.set_nonempty(); 01874 return false; 01875 } 01876 else 01877 return !x.marked_empty(); 01878 } 01879 01880 // Filter away the case when `y' is empty. 01881 if (y.is_empty()) { 01882 for (dimension_type i = num_dims; i-- > 0; ) 01883 x.seq[i].assign(UNIVERSE); 01884 x.set_nonempty(); 01885 return false; 01886 } 01887 01888 if (x.is_empty()) { 01889 // Find in `y' a non-universe interval, if any. 01890 for (dimension_type i = 0; i < num_dims; ++i) { 01891 if (y.seq[i].is_universe()) 01892 x.seq[i].assign(UNIVERSE); 01893 else { 01894 // Set x.seq[i] so as to contradict y.seq[i], if possible. 01895 ITV& seq_i = x.seq[i]; 01896 seq_i.empty_intersection_assign(y.seq[i]); 01897 if (seq_i.is_empty()) { 01898 // We were not able to assign to `seq_i' a non-empty interval: 01899 // reset `seq_i' to the universe interval and keep searching. 01900 seq_i.assign(UNIVERSE); 01901 continue; 01902 } 01903 // We assigned to `seq_i' a non-empty interval: 01904 // set the other intervals to universe and return. 01905 for (++i; i < num_dims; ++i) 01906 x.seq[i].assign(UNIVERSE); 01907 x.set_nonempty(); 01908 PPL_ASSERT(x.OK()); 01909 return false; 01910 } 01911 } 01912 // All intervals in `y' are universe or could not be contradicted: 01913 // simplification can leave the empty box `x' as is. 01914 PPL_ASSERT(x.OK() && x.is_empty()); 01915 return false; 01916 } 01917 01918 // Loop index `i' is intentionally going upwards. 01919 dimension_type i = 0; 01920 for ( ; i < num_dims; ++i) { 01921 if (!x.seq[i].simplify_using_context_assign(y.seq[i])) { 01922 PPL_ASSERT(!x.seq[i].is_empty()); 01923 // The intersection of `x' and `y' is empty due to the i-th interval: 01924 // reset other intervals to UNIVERSE. 01925 for (dimension_type j = num_dims; j-- > i; ) 01926 x.seq[j].assign(UNIVERSE); 01927 for (dimension_type j = i; j-- > 0; ) 01928 x.seq[j].assign(UNIVERSE); 01929 PPL_ASSERT(x.OK()); 01930 return false; 01931 } 01932 } 01933 PPL_ASSERT(x.OK()); 01934 return true; 01935 }
| dimension_type Parma_Polyhedra_Library::Box< ITV >::space_dimension | ( | ) | const [inline] |
Returns the dimension of the vector space enclosing *this.
Definition at line 122 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::seq.
Referenced by Parma_Polyhedra_Library::Box< ITV >::add_congruence(), Parma_Polyhedra_Library::Box< ITV >::add_congruence_no_check(), Parma_Polyhedra_Library::Box< ITV >::add_congruences(), Parma_Polyhedra_Library::Box< ITV >::add_congruences_no_check(), Parma_Polyhedra_Library::Box< ITV >::add_constraint(), Parma_Polyhedra_Library::Box< ITV >::add_constraint_no_check(), Parma_Polyhedra_Library::Box< ITV >::add_constraints(), Parma_Polyhedra_Library::Box< ITV >::add_constraints_no_check(), Parma_Polyhedra_Library::Box< ITV >::affine_dimension(), Parma_Polyhedra_Library::Box< ITV >::affine_image(), Parma_Polyhedra_Library::Box< ITV >::affine_preimage(), Parma_Polyhedra_Library::Box< ITV >::ascii_dump(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::Box< ITV >::bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Box< ITV >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Box< ITV >::concatenate_assign(), Parma_Polyhedra_Library::Box< ITV >::congruences(), Parma_Polyhedra_Library::Box< ITV >::constrains(), Parma_Polyhedra_Library::Box< ITV >::constraints(), Parma_Polyhedra_Library::Box< ITV >::contains(), Parma_Polyhedra_Library::Box< ITV >::difference_assign(), Parma_Polyhedra_Library::Box< ITV >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Box< ITV >::expand_space_dimension(), Parma_Polyhedra_Library::Box< ITV >::fold_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::frequency(), Parma_Polyhedra_Library::Box< ITV >::generalized_affine_preimage(), Parma_Polyhedra_Library::Box< ITV >::get_interval(), Parma_Polyhedra_Library::Box< ITV >::get_limiting_box(), Parma_Polyhedra_Library::Grid::Grid(), Parma_Polyhedra_Library::Box< ITV >::intersection_assign(), Parma_Polyhedra_Library::Box< ITV >::is_disjoint_from(), Parma_Polyhedra_Library::Box< ITV >::l_m_distance_assign(), Parma_Polyhedra_Library::Box< ITV >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::Box< ITV >::map_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::max_min(), Parma_Polyhedra_Library::Box< ITV >::minimized_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::operator==(), Parma_Polyhedra_Library::Polyhedron::Polyhedron(), Parma_Polyhedra_Library::Box< ITV >::propagate_constraint(), Parma_Polyhedra_Library::Box< ITV >::propagate_constraint_no_check(), Parma_Polyhedra_Library::Box< ITV >::propagate_constraints(), Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::refine_with_congruence(), Parma_Polyhedra_Library::Box< ITV >::refine_with_congruences(), Parma_Polyhedra_Library::Box< ITV >::refine_with_constraint(), Parma_Polyhedra_Library::Box< ITV >::refine_with_constraints(), Parma_Polyhedra_Library::Box< ITV >::relation_with(), Parma_Polyhedra_Library::Box< ITV >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::remove_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::set_interval(), Parma_Polyhedra_Library::Box< ITV >::simplify_using_context_assign(), Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible(), Parma_Polyhedra_Library::Box< ITV >::time_elapse_assign(), Parma_Polyhedra_Library::Box< ITV >::unconstrain(), Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign(), Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign_if_exact(), and Parma_Polyhedra_Library::Box< ITV >::wrap_assign().
00122 { 00123 return seq.size(); 00124 }
| bool Parma_Polyhedra_Library::Box< ITV >::strictly_contains | ( | const Box< ITV > & | y | ) | const [inline] |
Returns true if and only if *this strictly contains y.
| std::invalid_argument | Thrown if x and y are dimension-incompatible. |
Definition at line 225 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::contains().
00225 { 00226 const Box& x = *this; 00227 return x.contains(y) && !y.contains(x); 00228 }
| void Parma_Polyhedra_Library::Box< ITV >::swap | ( | Box< ITV > & | y | ) | [inline] |
Swaps *this with y (*this and y can be dimension-incompatible).
Definition at line 84 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::seq, and Parma_Polyhedra_Library::Box< ITV >::status.
Referenced by Parma_Polyhedra_Library::Box< ITV >::Box(), and Parma_Polyhedra_Library::Box< ITV >::map_space_dimensions().
| void Parma_Polyhedra_Library::Box< ITV >::throw_constraint_incompatible | ( | const char * | method | ) | [inline, static, private] |
Definition at line 4027 of file Box.templates.hh.
Referenced by Parma_Polyhedra_Library::Box< ITV >::limited_CC76_extrapolation_assign().
| void Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | name_row, | |||
| const Linear_Expression & | y | |||
| ) | const [inline, private] |
Definition at line 4047 of file Box.templates.hh.
References Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::space_dimension().
04049 { 04050 std::ostringstream s; 04051 s << "PPL::Box::" << method << ":" << std::endl 04052 << "this->space_dimension() == " << space_dimension() 04053 << ", " << name_row << "->space_dimension() == " 04054 << e.space_dimension() << "."; 04055 throw std::invalid_argument(s.str()); 04056 }
| void Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible | ( | const char * | method, | |
| const Generator & | g | |||
| ) | const [inline, private] |
Definition at line 4016 of file Box.templates.hh.
References Parma_Polyhedra_Library::Generator::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::space_dimension().
04017 { 04018 std::ostringstream s; 04019 s << "PPL::Box::" << method << ":" << std::endl 04020 << "this->space_dimension() == " << space_dimension() 04021 << ", g->space_dimension == " << g.space_dimension() << "."; 04022 throw std::invalid_argument(s.str()); 04023 }
| void Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible | ( | const char * | method, | |
| const Congruence_System & | cgs | |||
| ) | const [inline, private] |
Definition at line 4005 of file Box.templates.hh.
References Parma_Polyhedra_Library::Congruence_System::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::space_dimension().
04006 { 04007 std::ostringstream s; 04008 s << "PPL::Box::" << method << ":" << std::endl 04009 << "this->space_dimension() == " << space_dimension() 04010 << ", cgs->space_dimension == " << cgs.space_dimension() << "."; 04011 throw std::invalid_argument(s.str()); 04012 }
| void Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible | ( | const char * | method, | |
| const Constraint_System & | cs | |||
| ) | const [inline, private] |
Definition at line 3994 of file Box.templates.hh.
References Parma_Polyhedra_Library::Constraint_System::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::space_dimension().
03995 { 03996 std::ostringstream s; 03997 s << "PPL::Box::" << method << ":" << std::endl 03998 << "this->space_dimension() == " << space_dimension() 03999 << ", cs->space_dimension == " << cs.space_dimension() << "."; 04000 throw std::invalid_argument(s.str()); 04001 }
| void Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible | ( | const char * | method, | |
| const Congruence & | cg | |||
| ) | const [inline, private] |
Definition at line 3983 of file Box.templates.hh.
References Parma_Polyhedra_Library::Congruence::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::space_dimension().
03984 { 03985 std::ostringstream s; 03986 s << "PPL::Box::" << method << ":" << std::endl 03987 << "this->space_dimension() == " << space_dimension() 03988 << ", cg->space_dimension == " << cg.space_dimension() << "."; 03989 throw std::invalid_argument(s.str()); 03990 }
| void Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible | ( | const char * | method, | |
| const Constraint & | c | |||
| ) | const [inline, private] |
Definition at line 3972 of file Box.templates.hh.
References Parma_Polyhedra_Library::Constraint::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::space_dimension().
03973 { 03974 std::ostringstream s; 03975 s << "PPL::Box::" << method << ":" << std::endl 03976 << "this->space_dimension() == " << space_dimension() 03977 << ", c->space_dimension == " << c.space_dimension() << "."; 03978 throw std::invalid_argument(s.str()); 03979 }
| void Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible | ( | const char * | method, | |
| dimension_type | required_dim | |||
| ) | const [inline, private] |
Definition at line 3961 of file Box.templates.hh.
03962 { 03963 std::ostringstream s; 03964 s << "PPL::Box::" << method << ":" << std::endl 03965 << "this->space_dimension() == " << space_dimension() 03966 << ", required dimension == " << required_dim << "."; 03967 throw std::invalid_argument(s.str()); 03968 }
| void Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible | ( | const char * | method, | |
| const Box< ITV > & | x | |||
| ) | const [inline, private] |
Definition at line 3949 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::space_dimension().
Referenced by Parma_Polyhedra_Library::Box< ITV >::add_congruence(), Parma_Polyhedra_Library::Box< ITV >::add_congruences(), Parma_Polyhedra_Library::Box< ITV >::add_constraint(), Parma_Polyhedra_Library::Box< ITV >::add_constraints(), Parma_Polyhedra_Library::Box< ITV >::affine_image(), Parma_Polyhedra_Library::Box< ITV >::affine_preimage(), Parma_Polyhedra_Library::Box< ITV >::bounds(), Parma_Polyhedra_Library::Box< ITV >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Box< ITV >::constrains(), Parma_Polyhedra_Library::Box< ITV >::contains(), Parma_Polyhedra_Library::Box< ITV >::difference_assign(), Parma_Polyhedra_Library::Box< ITV >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Box< ITV >::expand_space_dimension(), Parma_Polyhedra_Library::Box< ITV >::fold_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::frequency(), Parma_Polyhedra_Library::Box< ITV >::generalized_affine_preimage(), Parma_Polyhedra_Library::Box< ITV >::get_interval(), Parma_Polyhedra_Library::Box< ITV >::intersection_assign(), Parma_Polyhedra_Library::Box< ITV >::is_disjoint_from(), Parma_Polyhedra_Library::Box< ITV >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::Box< ITV >::max_min(), Parma_Polyhedra_Library::Box< ITV >::propagate_constraint(), Parma_Polyhedra_Library::Box< ITV >::propagate_constraints(), Parma_Polyhedra_Library::Box< ITV >::refine_with_congruence(), Parma_Polyhedra_Library::Box< ITV >::refine_with_congruences(), Parma_Polyhedra_Library::Box< ITV >::refine_with_constraint(), Parma_Polyhedra_Library::Box< ITV >::refine_with_constraints(), Parma_Polyhedra_Library::Box< ITV >::relation_with(), Parma_Polyhedra_Library::Box< ITV >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::remove_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::set_interval(), Parma_Polyhedra_Library::Box< ITV >::simplify_using_context_assign(), Parma_Polyhedra_Library::Box< ITV >::time_elapse_assign(), Parma_Polyhedra_Library::Box< ITV >::unconstrain(), Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign(), and Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign_if_exact().
03950 { 03951 std::ostringstream s; 03952 s << "PPL::Box::" << method << ":" << std::endl 03953 << "this->space_dimension() == " << this->space_dimension() 03954 << ", y->space_dimension() == " << y.space_dimension() << "."; 03955 throw std::invalid_argument(s.str()); 03956 }
| void Parma_Polyhedra_Library::Box< ITV >::throw_expression_too_complex | ( | const char * | method, | |
| const Linear_Expression & | e | |||
| ) | [inline, static, private] |
Definition at line 4036 of file Box.templates.hh.
| void Parma_Polyhedra_Library::Box< ITV >::throw_generic | ( | const char * | method, | |
| const char * | reason | |||
| ) | [inline, static, private] |
Definition at line 4060 of file Box.templates.hh.
Referenced by Parma_Polyhedra_Library::Box< ITV >::add_congruence_no_check(), Parma_Polyhedra_Library::Box< ITV >::add_constraint_no_check(), Parma_Polyhedra_Library::Box< ITV >::affine_image(), Parma_Polyhedra_Library::Box< ITV >::affine_preimage(), Parma_Polyhedra_Library::Box< ITV >::expand_space_dimension(), Parma_Polyhedra_Library::Box< ITV >::fold_space_dimensions(), and Parma_Polyhedra_Library::Box< ITV >::generalized_affine_preimage().
| void Parma_Polyhedra_Library::Box< ITV >::throw_space_dimension_overflow | ( | const char * | method, | |
| const char * | reason | |||
| ) | [inline, static, private] |
Definition at line 4069 of file Box.templates.hh.
Referenced by Parma_Polyhedra_Library::Box< ITV >::Box().
| void Parma_Polyhedra_Library::Box< ITV >::time_elapse_assign | ( | const Box< ITV > & | 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 1939 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
01939 { 01940 Box& x = *this; 01941 const dimension_type x_space_dim = x.space_dimension(); 01942 01943 // Dimension-compatibility check. 01944 if (x_space_dim != y.space_dimension()) 01945 x.throw_dimension_incompatible("time_elapse_assign(y)", y); 01946 01947 // Dealing with the zero-dimensional case. 01948 if (x_space_dim == 0) { 01949 if (y.marked_empty()) 01950 x.set_empty(); 01951 return; 01952 } 01953 01954 // If either one of `x' or `y' is empty, the result is empty too. 01955 // Note: if possible, avoid cost of checking for emptiness. 01956 if (x.marked_empty() || y.marked_empty() 01957 || x.is_empty() || y.is_empty()) { 01958 x.set_empty(); 01959 return; 01960 } 01961 01962 for (dimension_type i = x_space_dim; i-- > 0; ) { 01963 ITV& x_seq_i = x.seq[i]; 01964 const ITV& y_seq_i = y.seq[i]; 01965 if (!x_seq_i.lower_is_boundary_infinity()) 01966 if (y_seq_i.lower_is_boundary_infinity() || y_seq_i.lower() < 0) 01967 x_seq_i.lower_extend(); 01968 if (!x_seq_i.upper_is_boundary_infinity()) 01969 if (y_seq_i.upper_is_boundary_infinity() || y_seq_i.upper() > 0) 01970 x_seq_i.upper_extend(); 01971 } 01972 PPL_ASSERT(x.OK()); 01973 }
| void Parma_Polyhedra_Library::Box< ITV >::topological_closure_assign | ( | ) | [inline] |
Assigns to *this its topological closure.
Definition at line 1481 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::is_empty(), and Parma_Polyhedra_Library::Box< ITV >::seq.
01481 { 01482 if (ITV::is_always_topologically_closed() || is_empty()) 01483 return; 01484 01485 for (dimension_type k = seq.size(); k-- > 0; ) 01486 seq[k].topological_closure_assign(); 01487 }
| memory_size_type Parma_Polyhedra_Library::Box< ITV >::total_memory_in_bytes | ( | ) | const [inline] |
Returns the total size in bytes of the memory occupied by *this.
Definition at line 116 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::external_memory_in_bytes().
00116 { 00117 return sizeof(*this) + external_memory_in_bytes(); 00118 }
| void Parma_Polyhedra_Library::Box< ITV >::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 1447 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::UNIVERSE.
01447 { 01448 // The cylindrification wrt no dimensions is a no-op. 01449 // This case also captures the only legal cylindrification 01450 // of a box in a 0-dim space. 01451 if (vars.empty()) 01452 return; 01453 01454 // Dimension-compatibility check. 01455 const dimension_type min_space_dim = vars.space_dimension(); 01456 if (space_dimension() < min_space_dim) 01457 throw_dimension_incompatible("unconstrain(vs)", min_space_dim); 01458 01459 // If the box is already empty, there is nothing left to do. 01460 if (marked_empty()) 01461 return; 01462 01463 // Here the box might still be empty (but we haven't detected it yet): 01464 // check emptiness of the interval for each of the variables in 01465 // `vars' before cylindrification. 01466 for (Variables_Set::const_iterator vsi = vars.begin(), 01467 vsi_end = vars.end(); vsi != vsi_end; ++vsi) { 01468 ITV& seq_vsi = seq[*vsi]; 01469 if (!seq_vsi.is_empty()) 01470 seq_vsi.assign(UNIVERSE); 01471 else { 01472 set_empty(); 01473 break; 01474 } 01475 } 01476 PPL_ASSERT(OK()); 01477 }
| void Parma_Polyhedra_Library::Box< ITV >::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 526 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::UNIVERSE.
00526 { 00527 const dimension_type var_id = var.id(); 00528 // Dimension-compatibility check. 00529 if (space_dimension() < var_id + 1) 00530 throw_dimension_incompatible("unconstrain(var)", var_id + 1); 00531 00532 // If the box is already empty, there is nothing left to do. 00533 if (marked_empty()) 00534 return; 00535 00536 // Here the box might still be empty (but we haven't detected it yet): 00537 // check emptiness of the interval for `var' before cylindrification. 00538 ITV& seq_var = seq[var_id]; 00539 if (seq_var.is_empty()) 00540 set_empty(); 00541 else 00542 seq_var.assign(UNIVERSE); 00543 00544 PPL_ASSERT(OK()); 00545 }
| void Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign | ( | const Box< ITV > & | y | ) | [inline] |
Assigns to *this the smallest box containing the union of *this and y.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 1744 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
01744 { 01745 Box& x = *this; 01746 01747 // Dimension-compatibility check. 01748 if (x.space_dimension() != y.space_dimension()) 01749 x.throw_dimension_incompatible("upper_bound_assign(y)", y); 01750 01751 // The lub of a box with an empty box is equal to the first box. 01752 if (y.marked_empty()) 01753 return; 01754 if (x.marked_empty()) { 01755 x = y; 01756 return; 01757 } 01758 01759 for (dimension_type k = x.seq.size(); k-- > 0; ) 01760 x.seq[k].join_assign(y.seq[k]); 01761 01762 PPL_ASSERT(x.OK()); 01763 }
| bool Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign_if_exact | ( | const Box< ITV > & | 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. |
Definition at line 1196 of file Box.templates.hh.
References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().
01196 { 01197 Box& x = *this; 01198 01199 // Dimension-compatibility check. 01200 if (x.space_dimension() != y.space_dimension()) 01201 x.throw_dimension_incompatible("upper_bound_assign_if_exact(y)", y); 01202 01203 // The lub of a box with an empty box is equal to the first box. 01204 if (y.marked_empty()) 01205 return true; 01206 if (x.marked_empty()) { 01207 x = y; 01208 return true; 01209 } 01210 01211 bool x_j_does_not_contain_y_j = false; 01212 bool y_j_does_not_contain_x_j = false; 01213 01214 for (dimension_type i = x.seq.size(); i-- > 0; ) { 01215 const ITV& x_seq_i = x.seq[i]; 01216 const ITV& y_seq_i = y.seq[i]; 01217 01218 if (!x_seq_i.can_be_exactly_joined_to(y_seq_i)) 01219 return false; 01220 01221 // Note: the use of `y_i_does_not_contain_x_i' is needed 01222 // because we want to temporarily preserve the old value 01223 // of `y_j_does_not_contain_x_j'. 01224 bool y_i_does_not_contain_x_i = !y_seq_i.contains(x_seq_i); 01225 if (y_i_does_not_contain_x_i && x_j_does_not_contain_y_j) 01226 return false; 01227 if (!x_seq_i.contains(y_seq_i)) { 01228 if (y_j_does_not_contain_x_j) 01229 return false; 01230 else 01231 x_j_does_not_contain_y_j = true; 01232 } 01233 if (y_i_does_not_contain_x_i) 01234 y_j_does_not_contain_x_j = true; 01235 } 01236 01237 // The upper bound is exact: compute it into *this. 01238 for (dimension_type k = x.seq.size(); k-- > 0; ) 01239 x.seq[k].join_assign(y.seq[k]); 01240 return true; 01241 }
| void Parma_Polyhedra_Library::Box< T >::widening_assign | ( | const Box< ITV > & | y, | |
| unsigned * | tp = 0 | |||
| ) | [inline] |
Same as CC76_widening_assign(y, tp).
Definition at line 364 of file Box.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::CC76_widening_assign().
00364 { 00365 CC76_widening_assign(y, tp); 00366 }
| void Parma_Polyhedra_Library::Box< ITV >::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. 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 which is ignored for the Box domain. | |
| wrap_individually | A precision parameter which is ignored for the Box domain. |
| std::invalid_argument | Thrown if *this is dimension-incompatible with one of the Variable objects contained in vars or with *pcs. |
Definition at line 1491 of file Box.templates.hh.
References Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Coefficient_one(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Box< ITV >::extract_interval_constraint(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Constraint::is_inconsistent(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::mul_2exp_assign(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::OVERFLOW_IMPOSSIBLE, Parma_Polyhedra_Library::OVERFLOW_UNDEFINED, Parma_Polyhedra_Library::OVERFLOW_WRAPS, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Box< ITV >::refine_interval_no_check(), Parma_Polyhedra_Library::Box< ITV >::refine_with_constraints(), Parma_Polyhedra_Library::Box< ITV >::reset_empty_up_to_date(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::SIGNED_2_COMPLEMENT, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::Constraint::type(), Parma_Polyhedra_Library::UNIVERSE, and Parma_Polyhedra_Library::UNSIGNED.
01497 { 01498 #if 0 // Generic implementation commented out. 01499 Implementation::wrap_assign(*this, 01500 vars, w, r, o, pcs, 01501 complexity_threshold, wrap_individually, 01502 "Box"); 01503 #else // Specialized implementation. 01504 used(wrap_individually); 01505 used(complexity_threshold); 01506 Box& x = *this; 01507 01508 // Dimension-compatibility check for `*pcs', if any. 01509 const dimension_type vars_space_dim = vars.space_dimension(); 01510 if (pcs != 0 && pcs->space_dimension() > vars_space_dim) { 01511 std::ostringstream s; 01512 s << "PPL::Box<ITV>::wrap_assign(vars, w, r, o, pcs, ...):" 01513 << std::endl 01514 << "vars.space_dimension() == " << vars_space_dim 01515 << ", pcs->space_dimension() == " << pcs->space_dimension() << "."; 01516 throw std::invalid_argument(s.str()); 01517 } 01518 01519 // Wrapping no variable only requires refining with *pcs, if any. 01520 if (vars.empty()) { 01521 if (pcs != 0) 01522 refine_with_constraints(*pcs); 01523 return; 01524 } 01525 01526 // Dimension-compatibility check for `vars'. 01527 const dimension_type space_dim = x.space_dimension(); 01528 if (space_dim < vars_space_dim) { 01529 std::ostringstream s; 01530 s << "PPL::Box<ITV>::wrap_assign(vars, ...):" 01531 << std::endl 01532 << "this->space_dimension() == " << space_dim 01533 << ", required space dimension == " << vars_space_dim << "."; 01534 throw std::invalid_argument(s.str()); 01535 } 01536 01537 // Wrapping an empty polyhedron is a no-op. 01538 if (x.is_empty()) 01539 return; 01540 01541 // FIXME: temporarily (ab-) using Coefficient. 01542 // Set `min_value' and `max_value' to the minimum and maximum values 01543 // a variable of width `w' and signedness `s' can take. 01544 PPL_DIRTY_TEMP_COEFFICIENT(min_value); 01545 PPL_DIRTY_TEMP_COEFFICIENT(max_value); 01546 if (r == UNSIGNED) { 01547 min_value = 0; 01548 mul_2exp_assign(max_value, Coefficient_one(), w); 01549 --max_value; 01550 } 01551 else { 01552 PPL_ASSERT(r == SIGNED_2_COMPLEMENT); 01553 mul_2exp_assign(max_value, Coefficient_one(), w-1); 01554 neg_assign(min_value, max_value); 01555 --max_value; 01556 } 01557 01558 // FIXME: Build the (integer) quadrant interval. 01559 PPL_DIRTY_TEMP(ITV, integer_quadrant_itv); 01560 PPL_DIRTY_TEMP(ITV, rational_quadrant_itv); 01561 { 01562 I_Constraint<Coefficient> lower = i_constraint(GREATER_OR_EQUAL, min_value); 01563 I_Constraint<Coefficient> upper = i_constraint(LESS_OR_EQUAL, max_value); 01564 integer_quadrant_itv.build(lower, upper); 01565 // The rational quadrant is only needed if overflow is undefined. 01566 if (o == OVERFLOW_UNDEFINED) { 01567 ++max_value; 01568 upper = i_constraint(LESS_THAN, max_value); 01569 rational_quadrant_itv.build(lower, upper); 01570 } 01571 } 01572 01573 const Variables_Set::const_iterator vs_end = vars.end(); 01574 01575 if (pcs == 0) { 01576 // No constraint refinement is needed here. 01577 switch (o) { 01578 case OVERFLOW_WRAPS: 01579 for (Variables_Set::const_iterator i = vars.begin(); i != vs_end; ++i) 01580 x.seq[*i].wrap_assign(w, r, integer_quadrant_itv); 01581 reset_empty_up_to_date(); 01582 break; 01583 case OVERFLOW_UNDEFINED: 01584 for (Variables_Set::const_iterator i = vars.begin(); i != vs_end; ++i) { 01585 ITV& x_seq_v = x.seq[*i]; 01586 if (!rational_quadrant_itv.contains(x_seq_v)) { 01587 x_seq_v.assign(integer_quadrant_itv); 01588 } 01589 } 01590 break; 01591 case OVERFLOW_IMPOSSIBLE: 01592 for (Variables_Set::const_iterator i = vars.begin(); i != vs_end; ++i) 01593 x.seq[*i].intersect_assign(integer_quadrant_itv); 01594 reset_empty_up_to_date(); 01595 break; 01596 } 01597 PPL_ASSERT(x.OK()); 01598 return; 01599 } 01600 01601 PPL_ASSERT(pcs != 0); 01602 const Constraint_System& cs = *pcs; 01603 const dimension_type cs_space_dim = cs.space_dimension(); 01604 // A map associating interval constraints to variable indexes. 01605 typedef std::map<dimension_type, std::vector<const Constraint*> > map_type; 01606 map_type var_cs_map; 01607 for (Constraint_System::const_iterator i = cs.begin(), 01608 i_end = cs.end(); i != i_end; ++i) { 01609 const Constraint& c = *i; 01610 dimension_type c_num_vars = 0; 01611 dimension_type c_only_var = 0; 01612 if (extract_interval_constraint(c, cs_space_dim, 01613 c_num_vars, c_only_var)) { 01614 if (c_num_vars == 1) { 01615 // An interval constraint on variable index `c_only_var'. 01616 PPL_ASSERT(c_only_var < space_dim); 01617 // We do care about c if c_only_var is going to be wrapped. 01618 if (vars.find(c_only_var) != vs_end) 01619 var_cs_map[c_only_var].push_back(&c); 01620 } 01621 else { 01622 PPL_ASSERT(c_num_vars == 0); 01623 // Note: tautologies have been filtered out by iterators. 01624 PPL_ASSERT(c.is_inconsistent()); 01625 x.set_empty(); 01626 return; 01627 } 01628 } 01629 } 01630 01631 PPL_DIRTY_TEMP(ITV, refinement_itv); 01632 const map_type::const_iterator var_cs_map_end = var_cs_map.end(); 01633 // Loop through the variable indexes in `vars'. 01634 for (Variables_Set::const_iterator i = vars.begin(); i != vs_end; ++i) { 01635 const dimension_type v = *i; 01636 refinement_itv = integer_quadrant_itv; 01637 // Look for the refinement constraints for space dimension index `v'. 01638 map_type::const_iterator var_cs_map_iter = var_cs_map.find(v); 01639 if (var_cs_map_iter != var_cs_map_end) { 01640 // Refine interval for variable `v'. 01641 const map_type::mapped_type& var_cs = var_cs_map_iter->second; 01642 for (dimension_type j = var_cs.size(); j-- > 0; ) { 01643 const Constraint& c = *var_cs[j]; 01644 refine_interval_no_check(refinement_itv, 01645 c.type(), 01646 c.inhomogeneous_term(), 01647 c.coefficient(Variable(v))); 01648 } 01649 } 01650 // Wrap space dimension index `v'. 01651 ITV& x_seq_v = x.seq[v]; 01652 switch (o) { 01653 case OVERFLOW_WRAPS: 01654 x_seq_v.wrap_assign(w, r, refinement_itv); 01655 break; 01656 case OVERFLOW_UNDEFINED: 01657 if (!rational_quadrant_itv.contains(x_seq_v)) 01658 x_seq_v.assign(UNIVERSE); 01659 break; 01660 case OVERFLOW_IMPOSSIBLE: 01661 x_seq_v.intersect_assign(refinement_itv); 01662 break; 01663 } 01664 } 01665 PPL_ASSERT(x.OK()); 01666 #endif 01667 }
| bool euclidean_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Box< ITV > & | x, | |||
| const Box< ITV > & | 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 591 of file Box.inlines.hh.
| bool euclidean_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Box< ITV > & | x, | |||
| const Box< ITV > & | 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 605 of file Box.inlines.hh.
00608 { 00609 typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp; 00610 PPL_DIRTY_TEMP(Checked_Temp, tmp0); 00611 PPL_DIRTY_TEMP(Checked_Temp, tmp1); 00612 PPL_DIRTY_TEMP(Checked_Temp, tmp2); 00613 return euclidean_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2); 00614 }
| bool extract_interval_constraint | ( | const Constraint & | c, | |
| dimension_type | c_space_dim, | |||
| dimension_type & | c_num_vars, | |||
| dimension_type & | c_only_var | |||
| ) | [related] |
Decodes the constraint c as an interval constraint.
true if the constraint c is an interval constraint; 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 and 1. | |
| c_only_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 only variable having a non-zero coefficient in c. |
Definition at line 33 of file Box.cc.
References Parma_Polyhedra_Library::Constraint::coefficient(), and Parma_Polyhedra_Library::Constraint::space_dimension().
Referenced by Parma_Polyhedra_Library::Box< ITV >::add_constraint_no_check(), Parma_Polyhedra_Library::Box< ITV >::get_limiting_box(), Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::relation_with(), and Parma_Polyhedra_Library::Box< ITV >::wrap_assign().
00036 { 00037 // Check for preconditions. 00038 PPL_ASSERT(c.space_dimension() == c_space_dim); 00039 PPL_ASSERT(c_num_vars == 0 && c_only_var == 0); 00040 // Collect the non-zero components of `c'. 00041 for (dimension_type i = c_space_dim; i-- > 0; ) 00042 if (c.coefficient(Variable(i)) != 0) { 00043 if (c_num_vars == 0) { 00044 c_only_var = i; 00045 ++c_num_vars; 00046 } 00047 else 00048 // Constraint `c' is not an interval constraint. 00049 return false; 00050 } 00051 return true; 00052 }
| bool l_infinity_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Box< ITV > & | x, | |||
| const Box< ITV > & | 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 632 of file Box.inlines.hh.
| bool l_infinity_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Box< ITV > & | x, | |||
| const Box< ITV > & | 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 646 of file Box.inlines.hh.
00649 { 00650 typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp; 00651 PPL_DIRTY_TEMP(Checked_Temp, tmp0); 00652 PPL_DIRTY_TEMP(Checked_Temp, tmp1); 00653 PPL_DIRTY_TEMP(Checked_Temp, tmp2); 00654 return l_infinity_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2); 00655 }
| bool l_m_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Box< ITV > & | x, | |||
| const Box< ITV > & | y, | |||
| Rounding_Dir | dir, | |||
| Temp & | tmp0, | |||
| Temp & | tmp1, | |||
| Temp & | tmp2 | |||
| ) | [related] |
Helper function for computing distances.
Definition at line 4083 of file Box.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::combine(), Parma_Polyhedra_Library::finalize(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::maybe_assign(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::Box< ITV >::seq, and Parma_Polyhedra_Library::Box< ITV >::space_dimension().
04086 { 04087 const dimension_type x_space_dim = x.space_dimension(); 04088 // Dimension-compatibility check. 04089 if (x_space_dim != y.space_dimension()) 04090 return false; 04091 04092 // Zero-dim boxes are equal if and only if they are both empty or universe. 04093 if (x_space_dim == 0) { 04094 if (x.marked_empty() == y.marked_empty()) 04095 assign_r(r, 0, ROUND_NOT_NEEDED); 04096 else 04097 assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED); 04098 return true; 04099 } 04100 04101 // The distance computation requires a check for emptiness. 04102 (void) x.is_empty(); 04103 (void) y.is_empty(); 04104 // If one of two boxes is empty, then they are equal if and only if 04105 // the other box is empty too. 04106 if (x.marked_empty() || y.marked_empty()) { 04107 if (x.marked_empty() == y.marked_empty()) { 04108 assign_r(r, 0, ROUND_NOT_NEEDED); 04109 return true; 04110 } 04111 else 04112 goto pinf; 04113 } 04114 04115 assign_r(tmp0, 0, ROUND_NOT_NEEDED); 04116 for (dimension_type i = x_space_dim; i-- > 0; ) { 04117 const ITV& x_i = x.seq[i]; 04118 const ITV& y_i = y.seq[i]; 04119 // Dealing with the lower bounds. 04120 if (x_i.lower_is_boundary_infinity()) { 04121 if (!y_i.lower_is_boundary_infinity()) 04122 goto pinf; 04123 } 04124 else if (y_i.lower_is_boundary_infinity()) 04125 goto pinf; 04126 else { 04127 const Temp* tmp1p; 04128 const Temp* tmp2p; 04129 if (x_i.lower() > y_i.lower()) { 04130 maybe_assign(tmp1p, tmp1, x_i.lower(), dir); 04131 maybe_assign(tmp2p, tmp2, y_i.lower(), inverse(dir)); 04132 } 04133 else { 04134 maybe_assign(tmp1p, tmp1, y_i.lower(), dir); 04135 maybe_assign(tmp2p, tmp2, x_i.lower(), inverse(dir)); 04136 } 04137 sub_assign_r(tmp1, *tmp1p, *tmp2p, dir); 04138 PPL_ASSERT(sgn(tmp1) >= 0); 04139 Specialization::combine(tmp0, tmp1, dir); 04140 } 04141 // Dealing with the lower bounds. 04142 if (x_i.upper_is_boundary_infinity()) 04143 if (y_i.upper_is_boundary_infinity()) 04144 continue; 04145 else 04146 goto pinf; 04147 else if (y_i.upper_is_boundary_infinity()) 04148 goto pinf; 04149 else { 04150 const Temp* tmp1p; 04151 const Temp* tmp2p; 04152 if (x_i.upper() > y_i.upper()) { 04153 maybe_assign(tmp1p, tmp1, x_i.upper(), dir); 04154 maybe_assign(tmp2p, tmp2, y_i.upper(), inverse(dir)); 04155 } 04156 else { 04157 maybe_assign(tmp1p, tmp1, y_i.upper(), dir); 04158 maybe_assign(tmp2p, tmp2, x_i.upper(), inverse(dir)); 04159 } 04160 sub_assign_r(tmp1, *tmp1p, *tmp2p, dir); 04161 PPL_ASSERT(sgn(tmp1) >= 0); 04162 Specialization::combine(tmp0, tmp1, dir); 04163 } 04164 } 04165 Specialization::finalize(tmp0, dir); 04166 assign_r(r, tmp0, dir); 04167 return true; 04168 04169 pinf: 04170 assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED); 04171 return true; 04172 }
Returns true if and only if x and y aren't the same box.
Note that x and y may be dimension-incompatible boxes: in this case, the value true is returned.
Definition at line 254 of file Box.inlines.hh.
| std::ostream & operator<< | ( | std::ostream & | s, | |
| const Box< ITV > & | box | |||
| ) | [related] |
Output operator.
Definition at line 3888 of file Box.templates.hh.
03888 { 03889 if (box.is_empty()) 03890 s << "false"; 03891 else if (box.is_universe()) 03892 s << "true"; 03893 else 03894 for (dimension_type k = 0, 03895 space_dim = box.space_dimension(); k < space_dim; ) { 03896 s << Variable(k) << " in " << box[k]; 03897 ++k; 03898 if (k < space_dim) 03899 s << ", "; 03900 else 03901 break; 03902 } 03903 return s; 03904 }
Returns true if and only if x and y are the same box.
Note that x and y may be dimension-incompatible boxes: in this case, the value false is returned.
Definition at line 533 of file Box.templates.hh.
00533 { 00534 const dimension_type x_space_dim = x.space_dimension(); 00535 if (x_space_dim != y.space_dimension()) 00536 return false; 00537 00538 if (x.is_empty()) 00539 return y.is_empty(); 00540 00541 if (y.is_empty()) 00542 return x.is_empty(); 00543 00544 for (dimension_type k = x_space_dim; k-- > 0; ) 00545 if (x.seq[k] != y.seq[k]) 00546 return false; 00547 return true; 00548 }
friend class Parma_Polyhedra_Library::Box [friend] |
Definition at line 1677 of file Box.defs.hh.
| std::ostream& Parma_Polyhedra_Library::IO_Operators::operator<< | ( | std::ostream & | s, | |
| const Box< ITV > & | box | |||
| ) | [friend] |
| bool Parma_Polyhedra_Library::l_m_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Box< I > & | x, | |||
| const Box< I > & | y, | |||
| const Rounding_Dir | dir, | |||
| Temp & | tmp0, | |||
| Temp & | tmp1, | |||
| Temp & | tmp2 | |||
| ) | [friend] |
| bool rectilinear_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Box< ITV > & | x, | |||
| const Box< ITV > & | 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 550 of file Box.inlines.hh.
| bool rectilinear_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Box< ITV > & | x, | |||
| const Box< ITV > & | 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 564 of file Box.inlines.hh.
00567 { 00568 typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp; 00569 PPL_DIRTY_TEMP(Checked_Temp, tmp0); 00570 PPL_DIRTY_TEMP(Checked_Temp, tmp1); 00571 PPL_DIRTY_TEMP(Checked_Temp, tmp2); 00572 return rectilinear_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2); 00573 }
Sequence Parma_Polyhedra_Library::Box< ITV >::seq [private] |
A sequence of intervals, one for each dimension of the vector space.
Definition at line 1702 of file Box.defs.hh.
Referenced by Parma_Polyhedra_Library::Box< ITV >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Box< ITV >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::Box< ITV >::affine_dimension(), Parma_Polyhedra_Library::Box< ITV >::affine_image(), Parma_Polyhedra_Library::Box< ITV >::affine_preimage(), Parma_Polyhedra_Library::Box< ITV >::ascii_dump(), Parma_Polyhedra_Library::Box< ITV >::bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Box< ITV >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Box< ITV >::CC76_widening_assign(), Parma_Polyhedra_Library::Box< ITV >::check_empty(), Parma_Polyhedra_Library::Box< ITV >::concatenate_assign(), Parma_Polyhedra_Library::Box< ITV >::congruences(), Parma_Polyhedra_Library::Box< ITV >::constrains(), Parma_Polyhedra_Library::Box< ITV >::contains(), Parma_Polyhedra_Library::Box< ITV >::contains_integer_point(), Parma_Polyhedra_Library::Box< ITV >::difference_assign(), Parma_Polyhedra_Library::Box< ITV >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Box< ITV >::expand_space_dimension(), Parma_Polyhedra_Library::Box< ITV >::external_memory_in_bytes(), Parma_Polyhedra_Library::Box< ITV >::fold_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::frequency(), Parma_Polyhedra_Library::Box< ITV >::get_interval(), Parma_Polyhedra_Library::Box< ITV >::get_limiting_box(), Parma_Polyhedra_Library::Box< ITV >::get_lower_bound(), Parma_Polyhedra_Library::Box< ITV >::get_upper_bound(), Parma_Polyhedra_Library::Box< ITV >::intersection_assign(), Parma_Polyhedra_Library::Box< ITV >::is_bounded(), Parma_Polyhedra_Library::Box< ITV >::is_discrete(), Parma_Polyhedra_Library::Box< ITV >::is_disjoint_from(), Parma_Polyhedra_Library::Box< ITV >::is_topologically_closed(), Parma_Polyhedra_Library::Box< ITV >::is_universe(), Parma_Polyhedra_Library::Box< ITV >::l_m_distance_assign(), Parma_Polyhedra_Library::Box< ITV >::map_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::max_min(), Parma_Polyhedra_Library::Box< ITV >::minimized_constraints(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::operator=(), Parma_Polyhedra_Library::operator==(), Parma_Polyhedra_Library::Box< ITV >::operator[](), Parma_Polyhedra_Library::Box< ITV >::propagate_constraint_no_check(), Parma_Polyhedra_Library::Box< ITV >::relation_with(), Parma_Polyhedra_Library::Box< ITV >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::remove_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::set_interval(), Parma_Polyhedra_Library::Box< ITV >::simplify_using_context_assign(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::swap(), Parma_Polyhedra_Library::Box< ITV >::time_elapse_assign(), Parma_Polyhedra_Library::Box< ITV >::topological_closure_assign(), Parma_Polyhedra_Library::Box< ITV >::unconstrain(), Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign(), Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign_if_exact(), and Parma_Polyhedra_Library::Box< ITV >::wrap_assign().
Status Parma_Polyhedra_Library::Box< ITV >::status [private] |
The status flags to keep track of the internal state.
Definition at line 1709 of file Box.defs.hh.
Referenced by Parma_Polyhedra_Library::Box< ITV >::ascii_dump(), Parma_Polyhedra_Library::Box< ITV >::concatenate_assign(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::operator=(), Parma_Polyhedra_Library::Box< ITV >::reset_empty_up_to_date(), Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::set_empty_up_to_date(), Parma_Polyhedra_Library::Box< ITV >::set_nonempty(), and Parma_Polyhedra_Library::Box< ITV >::swap().
1.6.3