PPL  1.2
Parma_Polyhedra_Library::Box< ITV > Class Template Reference

A not necessarily closed, iso-oriented hyperrectangle. More...

#include <Box_defs.hh>

Collaboration diagram for Parma_Polyhedra_Library::Box< ITV >:

Classes

class  Status
 

Public Types

typedef ITV interval_type
 The type of intervals used to implement the box. More...
 

Public Member Functions

const ITV & get_interval (Variable var) const
 Returns a reference the interval that bounds var. More...
 
void set_interval (Variable var, const ITV &i)
 Sets to i the interval that bounds var. More...
 
bool has_lower_bound (Variable var, Coefficient &n, Coefficient &d, bool &closed) const
 If the space dimension of var is unbounded below, return false. Otherwise return true and set n, d and closed accordingly. More...
 
bool has_upper_bound (Variable var, Coefficient &n, Coefficient &d, bool &closed) const
 If the space dimension of var is unbounded above, return false. Otherwise return true and set n, d and closed accordingly. More...
 
Constraint_System constraints () const
 Returns a system of constraints defining *this. More...
 
Constraint_System minimized_constraints () const
 Returns a minimized system of constraints defining *this. More...
 
Congruence_System congruences () const
 Returns a system of congruences approximating *this. More...
 
Congruence_System minimized_congruences () const
 Returns a minimized system of congruences approximating *this. More...
 
memory_size_type total_memory_in_bytes () const
 Returns the total size in bytes of the memory occupied by *this. More...
 
memory_size_type external_memory_in_bytes () const
 Returns the size in bytes of the memory managed by *this. More...
 
int32_t hash_code () const
 Returns a 32-bit hash code for *this. More...
 
void ascii_dump () const
 Writes to std::cerr an ASCII representation of *this. More...
 
void ascii_dump (std::ostream &s) const
 Writes to s an ASCII representation of *this. More...
 
void print () const
 Prints *this to std::cerr using operator<<. More...
 
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. More...
 
void set_empty ()
 Causes the box to become empty, i.e., to represent the empty set. More...
 
template<typename T , typename Iterator >
Enable_If< Is_Same< T, Box< ITV > >::value &&Is_Same_Or_Derived< Interval_Base, ITV >::value, void >::type CC76_widening_assign (const T &y, Iterator first, Iterator last)
 
template<typename T >
Enable_If< Is_Same< T, Box< ITV > >::value &&Is_Same_Or_Derived< Interval_Base, ITV >::value, void >::type CC76_widening_assign (const T &y, unsigned *tp)
 
template<typename T >
Enable_If< Is_Same< T, Box< ITV > >::value &&Is_Same_Or_Derived< Interval_Base, ITV >::value, void >::type CC76_narrowing_assign (const T &y)
 
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. More...
 
 Box (const Box &y, Complexity_Class complexity=ANY_COMPLEXITY)
 Ordinary copy constructor. More...
 
template<typename Other_ITV >
 Box (const Box< Other_ITV > &y, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds a conservative, upward approximation of y. More...
 
 Box (const Constraint_System &cs)
 Builds a box from the system of constraints cs. More...
 
 Box (const Constraint_System &cs, Recycle_Input dummy)
 Builds a box recycling a system of constraints cs. More...
 
 Box (const Generator_System &gs)
 Builds a box from the system of generators gs. More...
 
 Box (const Generator_System &gs, Recycle_Input dummy)
 Builds a box recycling the system of generators gs. More...
 
 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. More...
 
template<typename T >
 Box (const Octagonal_Shape< T > &oct, Complexity_Class complexity=POLYNOMIAL_COMPLEXITY)
 Builds a box containing the octagonal shape oct. More...
 
 Box (const Polyhedron &ph, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds a box containing the polyhedron ph. More...
 
 Box (const Grid &gr, Complexity_Class complexity=POLYNOMIAL_COMPLEXITY)
 Builds a box containing the grid gr. More...
 
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. More...
 
Boxoperator= (const Box &y)
 The assignment operator (*this and y can be dimension-incompatible). More...
 
void m_swap (Box &y)
 Swaps *this with y (*this and y can be dimension-incompatible). More...
 
Member Functions that Do Not Modify the Box
dimension_type space_dimension () const
 Returns the dimension of the vector space enclosing *this. More...
 
dimension_type affine_dimension () const
 Returns $0$, if *this is empty; otherwise, returns the affine dimension of *this. More...
 
bool is_empty () const
 Returns true if and only if *this is an empty box. More...
 
bool is_universe () const
 Returns true if and only if *this is a universe box. More...
 
bool is_topologically_closed () const
 Returns true if and only if *this is a topologically closed subset of the vector space. More...
 
bool is_discrete () const
 Returns true if and only if *this is discrete. More...
 
bool is_bounded () const
 Returns true if and only if *this is a bounded box. More...
 
bool contains_integer_point () const
 Returns true if and only if *this contains at least one integer point. More...
 
bool constrains (Variable var) const
 Returns true if and only if var is constrained in *this. More...
 
Poly_Con_Relation relation_with (const Constraint &c) const
 Returns the relations holding between *this and the constraint c. More...
 
Poly_Con_Relation relation_with (const Congruence &cg) const
 Returns the relations holding between *this and the congruence cg. More...
 
Poly_Gen_Relation relation_with (const Generator &g) const
 Returns the relations holding between *this and the generator g. More...
 
bool bounds_from_above (const Linear_Expression &expr) const
 Returns true if and only if expr is bounded from above in *this. More...
 
bool bounds_from_below (const Linear_Expression &expr) const
 Returns true if and only if expr is bounded from below in *this. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
bool contains (const Box &y) const
 Returns true if and only if *this contains y. More...
 
bool strictly_contains (const Box &y) const
 Returns true if and only if *this strictly contains y. More...
 
bool is_disjoint_from (const Box &y) const
 Returns true if and only if *this and y are disjoint. More...
 
bool OK () const
 Returns true if and only if *this satisfies all its invariants. More...
 
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. More...
 
void add_constraints (const Constraint_System &cs)
 Adds the constraints in cs to the system of constraints defining *this. More...
 
void add_recycled_constraints (Constraint_System &cs)
 Adds the constraints in cs to the system of constraints defining *this. More...
 
void add_congruence (const Congruence &cg)
 Adds to *this a constraint equivalent to the congruence cg. More...
 
void add_congruences (const Congruence_System &cgs)
 Adds to *this constraints equivalent to the congruences in cgs. More...
 
void add_recycled_congruences (Congruence_System &cgs)
 Adds to *this constraints equivalent to the congruences in cgs. More...
 
void refine_with_constraint (const Constraint &c)
 Use the constraint c to refine *this. More...
 
void refine_with_constraints (const Constraint_System &cs)
 Use the constraints in cs to refine *this. More...
 
void refine_with_congruence (const Congruence &cg)
 Use the congruence cg to refine *this. More...
 
void refine_with_congruences (const Congruence_System &cgs)
 Use the congruences in cgs to refine *this. More...
 
void propagate_constraint (const Constraint &c)
 Use the constraint c for constraint propagation on *this. More...
 
void propagate_constraints (const Constraint_System &cs, dimension_type max_iterations=0)
 Use the constraints in cs for constraint propagation on *this. More...
 
void unconstrain (Variable var)
 Computes the cylindrification of *this with respect to space dimension var, assigning the result to *this. More...
 
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. More...
 
void intersection_assign (const Box &y)
 Assigns to *this the intersection of *this and y. More...
 
void upper_bound_assign (const Box &y)
 Assigns to *this the smallest box containing the union of *this and y. More...
 
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. More...
 
void difference_assign (const Box &y)
 Assigns to *this the difference of *this and y. More...
 
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. More...
 
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. More...
 
void affine_form_image (Variable var, const Linear_Form< ITV > &lf)
 Assigns to *this the affine form image of *this under the function mapping variable var into the affine expression(s) specified by lf. More...
 
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. More...
 
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 $\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym. More...
 
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 $\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym. More...
 
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 $\mathrm{lhs}' \relsym \mathrm{rhs}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym. More...
 
void generalized_affine_preimage (const Linear_Expression &lhs, Relation_Symbol relsym, const Linear_Expression &rhs)
 Assigns to *this the preimage of *this with respect to the generalized affine relation $\mathrm{lhs}' \relsym \mathrm{rhs}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym. More...
 
void bounded_affine_image (Variable var, const Linear_Expression &lb_expr, const Linear_Expression &ub_expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the image of *this with respect to the bounded affine relation $\frac{\mathrm{lb\_expr}}{\mathrm{denominator}} \leq \mathrm{var}' \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}$. More...
 
void bounded_affine_preimage (Variable var, const Linear_Expression &lb_expr, const Linear_Expression &ub_expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the preimage of *this with respect to the bounded affine relation $\frac{\mathrm{lb\_expr}}{\mathrm{denominator}} \leq \mathrm{var}' \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}$. More...
 
void time_elapse_assign (const Box &y)
 Assigns to *this the result of computing the time-elapse between *this and y. More...
 
void topological_closure_assign ()
 Assigns to *this its topological closure. More...
 
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 *cs_p=0, unsigned complexity_threshold=16, bool wrap_individually=true)
 Wraps the specified dimensions of the vector space. More...
 
void drop_some_non_integer_points (Complexity_Class complexity=ANY_COMPLEXITY)
 Possibly tightens *this by dropping some points with non-integer coordinates. More...
 
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. More...
 
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. More...
 
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. More...
 
void widening_assign (const Box &y, unsigned *tp=0)
 Same as CC76_widening_assign(y, tp). More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
void remove_space_dimensions (const Variables_Set &vars)
 Removes all the specified dimensions. More...
 
void remove_higher_space_dimensions (dimension_type new_dimension)
 Removes the higher dimensions so that the resulting space will have dimension new_dimension. More...
 
template<typename Partial_Function >
void map_space_dimensions (const Partial_Function &pfunc)
 Remaps the dimensions of the vector space according to a partial function. More...
 
void expand_space_dimension (Variable var, dimension_type m)
 Creates m copies of the space dimension corresponding to var. More...
 
void fold_space_dimensions (const Variables_Set &vars, Variable dest)
 Folds the space dimensions in vars into dest. More...
 

Static Public Member Functions

static dimension_type max_space_dimension ()
 Returns the maximum space dimension that a Box can handle. More...
 
static bool can_recycle_constraint_systems ()
 Returns false indicating that this domain does not recycle constraints. More...
 
static bool can_recycle_congruence_systems ()
 Returns false indicating that this domain does not recycle congruences. More...
 

Private Types

typedef std::vector< ITV > Sequence
 The type of sequence used to implement the box. More...
 
typedef ITV Tmp_Interval_Type
 The type of intervals used by inner computations when trying to limit the cumulative effect of approximation errors. More...
 

Private Member Functions

bool marked_empty () const
 Returns true if and only if the box is known to be empty. More...
 
void set_nonempty ()
 Marks *this as definitely not empty. More...
 
void set_empty_up_to_date ()
 Asserts the validity of the empty flag of *this. More...
 
void reset_empty_up_to_date ()
 Invalidates empty flag of *this. More...
 
bool check_empty () const
 Checks the hard way whether *this is an empty box: returns true if and only if it is so. More...
 
const ITV & operator[] (dimension_type k) const
 Returns a reference the interval that bounds the box on the k-th space dimension. More...
 
void add_interval_constraint_no_check (dimension_type var_id, Constraint::Type type, Coefficient_traits::const_reference numer, Coefficient_traits::const_reference denom)
 WRITE ME. More...
 
void add_constraint_no_check (const Constraint &c)
 WRITE ME. More...
 
void add_constraints_no_check (const Constraint_System &cs)
 WRITE ME. More...
 
void add_congruence_no_check (const Congruence &cg)
 WRITE ME. More...
 
void add_congruences_no_check (const Congruence_System &cgs)
 WRITE ME. More...
 
void refine_no_check (const Constraint &c)
 Uses the constraint c to refine *this. More...
 
void refine_no_check (const Constraint_System &cs)
 Uses the constraints in cs to refine *this. More...
 
void refine_no_check (const Congruence &cg)
 Uses the congruence cg to refine *this. More...
 
void refine_no_check (const Congruence_System &cgs)
 Uses the congruences in cgs to refine *this. More...
 
void propagate_constraint_no_check (const Constraint &c)
 Propagates the constraint c to refine *this. More...
 
void propagate_constraints_no_check (const Constraint_System &cs, dimension_type max_iterations)
 Propagates the constraints in cs to refine *this. More...
 
bool bounds (const Linear_Expression &expr, bool from_above) const
 Checks if and how expr is bounded in *this. More...
 
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. More...
 
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. More...
 
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. More...
 

Static Private Member Functions

static I_Result refine_interval_no_check (ITV &itv, Constraint::Type type, Coefficient_traits::const_reference numer, Coefficient_traits::const_reference denom)
 WRITE ME. More...
 

Private Attributes

Sequence seq
 A sequence of intervals, one for each dimension of the vector space. More...
 
Status status
 The status flags to keep track of the internal state. More...
 

Friends

template<typename Other_ITV >
class Parma_Polyhedra_Library::Box
 
bool operator== (const Box< ITV > &x, const Box< ITV > &y)
 
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 >
void swap (Box< ITV > &x, Box< ITV > &y)
 Swaps x with y. More...
 
template<typename ITV >
bool operator== (const Box< ITV > &x, const Box< ITV > &y)
 Returns true if and only if x and y are the same box. More...
 
template<typename ITV >
bool operator!= (const Box< ITV > &x, const Box< ITV > &y)
 Returns true if and only if x and y are not the same box. More...
 
template<typename ITV >
std::ostream & operator<< (std::ostream &s, const Box< ITV > &box)
 Output operator. More...
 
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. More...
 
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)
 Computes the rectilinear (or Manhattan) distance between x and y. More...
 
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. More...
 
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. More...
 
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)
 Computes the euclidean distance between x and y. More...
 
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. More...
 
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 $L_\infty$ distance between x and y. More...
 
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)
 Computes the $L_\infty$ distance between x and y. More...
 
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 $L_\infty$ distance between x and y. More...
 
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)
 
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, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
 
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, const Rounding_Dir dir)
 
template<typename To , typename ITV >
bool rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Box< ITV > &x, const Box< ITV > &y, const Rounding_Dir dir)
 
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, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
 
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, const Rounding_Dir dir)
 
template<typename To , typename ITV >
bool euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Box< ITV > &x, const Box< ITV > &y, const Rounding_Dir dir)
 
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, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
 
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, const Rounding_Dir dir)
 
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, const Rounding_Dir dir)
 
template<typename ITV >
void swap (Box< ITV > &x, Box< ITV > &y)
 
template<typename ITV >
std::ostream & operator<< (std::ostream &s, const Box< ITV > &box)
 
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, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
 

Exception Throwers

void throw_dimension_incompatible (const char *method, const Box &y) 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 *le_name, const Linear_Expression &le) const
 
template<typename C >
void throw_dimension_incompatible (const char *method, const char *lf_name, const Linear_Form< C > &lf) const
 
static void throw_constraint_incompatible (const char *method)
 
static void throw_expression_too_complex (const char *method, const Linear_Expression &le)
 
static void throw_invalid_argument (const char *method, const char *reason)
 

Detailed Description

template<typename ITV>
class Parma_Polyhedra_Library::Box< ITV >

A not necessarily closed, iso-oriented hyperrectangle.

A Box object represents the smash product of $n$ not necessarily closed and possibly unbounded intervals represented by objects of class ITV, where $n$ 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:

  • tautological and inconsistent constraints and congruences;
  • the interval constraints that are optimally supported by the template argument class ITV;
  • the interval congruences that are optimally supported by the template argument class 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 299 of file Box_defs.hh.

Member Typedef Documentation

template<typename ITV>
typedef ITV Parma_Polyhedra_Library::Box< ITV >::interval_type

The type of intervals used to implement the box.

Definition at line 302 of file Box_defs.hh.

template<typename ITV>
typedef std::vector<ITV> Parma_Polyhedra_Library::Box< ITV >::Sequence
private

The type of sequence used to implement the box.

Definition at line 1756 of file Box_defs.hh.

template<typename ITV>
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 1762 of file Box_defs.hh.

Constructor & Destructor Documentation

template<typename ITV >
Parma_Polyhedra_Library::Box< ITV >::Box ( dimension_type  num_dimensions = 0,
Degenerate_Element  kind = UNIVERSE 
)
inlineexplicit

Builds a universe or empty box of the specified space dimension.

Parameters
num_dimensionsThe number of dimensions of the vector space enclosing the box;
kindSpecifies whether the universe or the empty box has to be built.

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

51  : seq(check_space_dimension_overflow(num_dimensions,
53  "PPL::Box::",
54  "Box(n, k)",
55  "n exceeds the maximum "
56  "allowed space dimension")),
57  status() {
58  // In a box that is marked empty the intervals are completely
59  // meaningless: we exploit this by avoiding their initialization.
60  if (kind == UNIVERSE) {
61  for (dimension_type i = num_dimensions; i-- > 0; ) {
62  seq[i].assign(UNIVERSE);
63  }
65  }
66  else {
67  set_empty();
68  }
69  PPL_ASSERT(OK());
70 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Status status
The status flags to keep track of the internal state.
Definition: Box_defs.hh:1772
dimension_type check_space_dimension_overflow(const dimension_type dim, const dimension_type max, const char *domain, const char *method, const char *reason)
Definition: globals.cc:48
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
static dimension_type max_space_dimension()
Returns the maximum space dimension that a Box can handle.
Definition: Box_inlines.hh:129
The universe element, i.e., the whole vector space.
void set_empty_up_to_date()
Asserts the validity of the empty flag of *this.
Definition: Box_inlines.hh:58
bool OK() const
Returns true if and only if *this satisfies all its invariants.
void set_empty()
Causes the box to become empty, i.e., to represent the empty set.
Definition: Box_inlines.hh:44
template<typename ITV >
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.

71  : seq(y.seq), status(y.status) {
72 }
Status status
The status flags to keep track of the internal state.
Definition: Box_defs.hh:1772
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
template<typename ITV >
template<typename Other_ITV >
Parma_Polyhedra_Library::Box< ITV >::Box ( const Box< Other_ITV > &  y,
Complexity_Class  complexity = ANY_COMPLEXITY 
)
inlineexplicit

Builds a conservative, upward approximation of y.

The complexity argument is ignored.

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

110  : seq(y.space_dimension()),
111  // FIXME: why the following does not work?
112  // status(y.status) {
113  status() {
114  // FIXME: remove when the above is fixed.
115  if (y.marked_empty()) {
116  set_empty();
117  }
118 
119  if (!y.marked_empty()) {
120  for (dimension_type k = y.space_dimension(); k-- > 0; ) {
121  seq[k].assign(y.seq[k]);
122  }
123  }
124  PPL_ASSERT(OK());
125 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Status status
The status flags to keep track of the internal state.
Definition: Box_defs.hh:1772
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
bool OK() const
Returns true if and only if *this satisfies all its invariants.
void set_empty()
Causes the box to become empty, i.e., to represent the empty set.
Definition: Box_inlines.hh:44
template<typename ITV >
Parma_Polyhedra_Library::Box< ITV >::Box ( const Constraint_System cs)
inlineexplicit

Builds a box from the system of constraints cs.

The box inherits the space dimension of cs.

Parameters
csA system of constraints: constraints that are not interval constraints are ignored (even though they may have contributed to the space dimension).

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

75  : seq(check_space_dimension_overflow(cs.space_dimension(),
77  "PPL::Box::",
78  "Box(cs)",
79  "cs exceeds the maximum "
80  "allowed space dimension")),
81  status() {
82  // FIXME: check whether we can avoid the double initialization.
83  for (dimension_type i = cs.space_dimension(); i-- > 0; ) {
84  seq[i].assign(UNIVERSE);
85  }
87 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Status status
The status flags to keep track of the internal state.
Definition: Box_defs.hh:1772
void add_constraints_no_check(const Constraint_System &cs)
WRITE ME.
dimension_type check_space_dimension_overflow(const dimension_type dim, const dimension_type max, const char *domain, const char *method, const char *reason)
Definition: globals.cc:48
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
static dimension_type max_space_dimension()
Returns the maximum space dimension that a Box can handle.
Definition: Box_inlines.hh:129
The universe element, i.e., the whole vector space.
template<typename ITV >
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.

Parameters
csA system of constraints: constraints that are not interval constraints are ignored (even though they may have contributed to the space dimension).
dummyA dummy tag to syntactically differentiate this one from the other constructors.

Definition at line 93 of file Box_inlines.hh.

93  {
94  // Recycling is useless: just delegate.
95  Box<ITV> tmp(cs);
96  this->m_swap(tmp);
97 }
void m_swap(Box &y)
Swaps *this with y (*this and y can be dimension-incompatible).
Definition: Box_inlines.hh:84
template<typename ITV >
Parma_Polyhedra_Library::Box< ITV >::Box ( const Generator_System gs)
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.

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

Definition at line 128 of file Box_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Expression_Adapter< T >::begin(), 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::Expression_Hide_Last< T >::end(), Parma_Polyhedra_Library::Generator_System::end(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::Generator::expression(), Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::i_constraint(), Parma_Polyhedra_Library::Generator::is_point(), Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::Generator::LINE, Parma_Polyhedra_Library::Box< ITV >::OK(), PPL_DIRTY_TEMP, Parma_Polyhedra_Library::Generator::RAY, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, 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::Boundary_NS::sgn(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Generator::type(), and Parma_Polyhedra_Library::UNIVERSE.

129  : seq(check_space_dimension_overflow(gs.space_dimension(),
131  "PPL::Box::",
132  "Box(gs)",
133  "gs exceeds the maximum "
134  "allowed space dimension")),
135  status() {
136  const Generator_System::const_iterator gs_begin = gs.begin();
137  const Generator_System::const_iterator gs_end = gs.end();
138  if (gs_begin == gs_end) {
139  // An empty generator system defines the empty box.
140  set_empty();
141  return;
142  }
143 
144  // The empty flag will be meaningful, whatever happens from now on.
146 
147  const dimension_type space_dim = space_dimension();
148  PPL_DIRTY_TEMP(mpq_class, q);
149  bool point_seen = false;
150  // Going through all the points.
152  gs_i = gs_begin; gs_i != gs_end; ++gs_i) {
153  const Generator& g = *gs_i;
154  if (g.is_point()) {
155  const Coefficient& d = g.divisor();
156  if (point_seen) {
157  // This is not the first point: `seq' already contains valid values.
158  // TODO: If the variables in the expression that have coefficient 0
159  // have no effect on seq[i], this loop can be optimized using
160  // Generator::expr_type::const_iterator.
161  for (dimension_type i = space_dim; i-- > 0; ) {
162  assign_r(q.get_num(), g.coefficient(Variable(i)), ROUND_NOT_NEEDED);
163  assign_r(q.get_den(), d, ROUND_NOT_NEEDED);
164  q.canonicalize();
165  PPL_DIRTY_TEMP(ITV, iq);
166  iq.build(i_constraint(EQUAL, q));
167  seq[i].join_assign(iq);
168  }
169  }
170  else {
171  // This is the first point seen: initialize `seq'.
172  point_seen = true;
173  // TODO: If the variables in the expression that have coefficient 0
174  // have no effect on seq[i], this loop can be optimized using
175  // Generator::expr_type::const_iterator.
176  for (dimension_type i = space_dim; i-- > 0; ) {
177  assign_r(q.get_num(), g.coefficient(Variable(i)), ROUND_NOT_NEEDED);
178  assign_r(q.get_den(), d, ROUND_NOT_NEEDED);
179  q.canonicalize();
180  seq[i].build(i_constraint(EQUAL, q));
181  }
182  }
183  }
184  }
185 
186  if (!point_seen) {
187  // The generator system is not empty, but contains no points.
188  throw std::invalid_argument("PPL::Box<ITV>::Box(gs):\n"
189  "the non-empty generator system gs "
190  "contains no points.");
191  }
192 
193  // Going through all the lines, rays and closure points.
194  for (Generator_System::const_iterator gs_i = gs_begin;
195  gs_i != gs_end; ++gs_i) {
196  const Generator& g = *gs_i;
197  switch (g.type()) {
198  case Generator::LINE:
199  for (Generator::expr_type::const_iterator i = g.expression().begin(),
200  i_end = g.expression().end();
201  i != i_end; ++i) {
202  seq[i.variable().id()].assign(UNIVERSE);
203  }
204  break;
205  case Generator::RAY:
206  for (Generator::expr_type::const_iterator i = g.expression().begin(),
207  i_end = g.expression().end();
208  i != i_end; ++i) {
209  switch (sgn(*i)) {
210  case 1:
211  seq[i.variable().id()].upper_extend();
212  break;
213  case -1:
214  seq[i.variable().id()].lower_extend();
215  break;
216  default:
217  PPL_UNREACHABLE;
218  break;
219  }
220  }
221  break;
223  {
224  const Coefficient& d = g.divisor();
225  // TODO: If the variables in the expression that have coefficient 0
226  // have no effect on seq[i], this loop can be optimized using
227  // Generator::expr_type::const_iterator.
228  for (dimension_type i = space_dim; i-- > 0; ) {
229  assign_r(q.get_num(), g.coefficient(Variable(i)), ROUND_NOT_NEEDED);
230  assign_r(q.get_den(), d, ROUND_NOT_NEEDED);
231  q.canonicalize();
232  ITV& seq_i = seq[i];
233  seq_i.lower_extend(i_constraint(GREATER_THAN, q));
234  seq_i.upper_extend(i_constraint(LESS_THAN, q));
235  }
236  }
237  break;
238  default:
239  // Points already dealt with.
240  break;
241  }
242  }
243  PPL_ASSERT(OK());
244 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
I_Constraint< T > i_constraint(I_Constraint_Rel rel, const T &v)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
Status status
The status flags to keep track of the internal state.
Definition: Box_defs.hh:1772
dimension_type check_space_dimension_overflow(const dimension_type dim, const dimension_type max, const char *domain, const char *method, const char *reason)
Definition: globals.cc:48
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
static dimension_type max_space_dimension()
Returns the maximum space dimension that a Box can handle.
Definition: Box_inlines.hh:129
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
#define PPL_DIRTY_TEMP(T, id)
The universe element, i.e., the whole vector space.
Generator_System_const_iterator const_iterator
void set_empty_up_to_date()
Asserts the validity of the empty flag of *this.
Definition: Box_inlines.hh:58
base_type::const_iterator const_iterator
The type of const iterators on coefficients.
int sgn(Boundary_Type type, const T &x, const Info &info)
bool OK() const
Returns true if and only if *this satisfies all its invariants.
void set_empty()
Causes the box to become empty, i.e., to represent the empty set.
Definition: Box_inlines.hh:44
template<typename ITV >
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.

Parameters
gsThe generator system describing the polyhedron to be approximated.
dummyA dummy tag to syntactically differentiate this one from the other constructors.
Exceptions
std::invalid_argumentThrown if the system of generators is not empty but has no points.

Definition at line 101 of file Box_inlines.hh.

101  {
102  // Recycling is useless: just delegate.
103  Box<ITV> tmp(gs);
104  this->m_swap(tmp);
105 }
void m_swap(Box &y)
Swaps *this with y (*this and y can be dimension-incompatible).
Definition: Box_inlines.hh:84
template<typename ITV >
Parma_Polyhedra_Library::Box< ITV >::Box ( const Congruence_System cgs)
inlineexplicit

Builds the smallest box containing the grid defined by a system of congruences cgs. The box inherits the space dimension of cgs.

Parameters
cgsA 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 91 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.

92  : seq(check_space_dimension_overflow(cgs.space_dimension(),
94  "PPL::Box::",
95  "Box(cgs)",
96  "cgs exceeds the maximum "
97  "allowed space dimension")),
98  status() {
99  // FIXME: check whether we can avoid the double initialization.
100  for (dimension_type i = cgs.space_dimension(); i-- > 0; ) {
101  seq[i].assign(UNIVERSE);
102  }
104 }
void add_congruences_no_check(const Congruence_System &cgs)
WRITE ME.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Status status
The status flags to keep track of the internal state.
Definition: Box_defs.hh:1772
dimension_type check_space_dimension_overflow(const dimension_type dim, const dimension_type max, const char *domain, const char *method, const char *reason)
Definition: globals.cc:48
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
static dimension_type max_space_dimension()
Returns the maximum space dimension that a Box can handle.
Definition: Box_inlines.hh:129
The universe element, i.e., the whole vector space.
template<typename ITV >
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.

Parameters
cgsA system of congruences: congruences that are not non-relational equality constraints are ignored (though they will contribute to the space dimension).
dummyA dummy tag to syntactically differentiate this one from the other constructors.

Definition at line 109 of file Box_inlines.hh.

109  {
110  // Recycling is useless: just delegate.
111  Box<ITV> tmp(cgs);
112  this->m_swap(tmp);
113 }
void m_swap(Box &y)
Swaps *this with y (*this and y can be dimension-incompatible).
Definition: Box_inlines.hh:84
template<typename ITV >
template<typename T >
Parma_Polyhedra_Library::Box< ITV >::Box ( const BD_Shape< T > &  bds,
Complexity_Class  complexity = POLYNOMIAL_COMPLEXITY 
)
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 248 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(), PPL_DIRTY_TEMP, Parma_Polyhedra_Library::ROUND_DOWN, Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::I_Constraint< T, Val_Or_Ref_Criteria, extended >::set(), 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().

249  : seq(check_space_dimension_overflow(bds.space_dimension(),
251  "PPL::Box::",
252  "Box(bds)",
253  "bds exceeds the maximum "
254  "allowed space dimension")),
255  status() {
256  // Expose all the interval constraints.
257  bds.shortest_path_closure_assign();
258  if (bds.marked_empty()) {
259  set_empty();
260  PPL_ASSERT(OK());
261  return;
262  }
263 
264  // The empty flag will be meaningful, whatever happens from now on.
266 
267  const dimension_type space_dim = space_dimension();
268  if (space_dim == 0) {
269  PPL_ASSERT(OK());
270  return;
271  }
272 
273  typedef typename BD_Shape<T>::coefficient_type Coeff;
274  PPL_DIRTY_TEMP(Coeff, tmp);
275  const DB_Row<Coeff>& dbm_0 = bds.dbm[0];
276  for (dimension_type i = space_dim; i-- > 0; ) {
277  I_Constraint<Coeff> lower;
278  I_Constraint<Coeff> upper;
279  ITV& seq_i = seq[i];
280 
281  // Set the upper bound.
282  const Coeff& u = dbm_0[i+1];
283  if (!is_plus_infinity(u)) {
284  upper.set(LESS_OR_EQUAL, u, true);
285  }
286 
287  // Set the lower bound.
288  const Coeff& negated_l = bds.dbm[i+1][0];
289  if (!is_plus_infinity(negated_l)) {
290  neg_assign_r(tmp, negated_l, ROUND_DOWN);
291  lower.set(GREATER_OR_EQUAL, tmp);
292  }
293 
294  seq_i.build(lower, upper);
295  }
296  PPL_ASSERT(OK());
297 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
Status status
The status flags to keep track of the internal state.
Definition: Box_defs.hh:1772
dimension_type check_space_dimension_overflow(const dimension_type dim, const dimension_type max, const char *domain, const char *method, const char *reason)
Definition: globals.cc:48
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
static dimension_type max_space_dimension()
Returns the maximum space dimension that a Box can handle.
Definition: Box_inlines.hh:129
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
#define PPL_DIRTY_TEMP(T, id)
void set_empty_up_to_date()
Asserts the validity of the empty flag of *this.
Definition: Box_inlines.hh:58
bool OK() const
Returns true if and only if *this satisfies all its invariants.
void set_empty()
Causes the box to become empty, i.e., to represent the empty set.
Definition: Box_inlines.hh:44
template<typename ITV >
template<typename T >
Parma_Polyhedra_Library::Box< ITV >::Box ( const Octagonal_Shape< T > &  oct,
Complexity_Class  complexity = POLYNOMIAL_COMPLEXITY 
)
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 301 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, PPL_DIRTY_TEMP, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::I_Constraint< T, Val_Or_Ref_Criteria, extended >::set(), 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().

302  : seq(check_space_dimension_overflow(oct.space_dimension(),
304  "PPL::Box::",
305  "Box(oct)",
306  "oct exceeds the maximum "
307  "allowed space dimension")),
308  status() {
309  // Expose all the interval constraints.
310  oct.strong_closure_assign();
311  if (oct.marked_empty()) {
312  set_empty();
313  return;
314  }
315 
316  // The empty flag will be meaningful, whatever happens from now on.
318 
319  const dimension_type space_dim = space_dimension();
320  if (space_dim == 0) {
321  return;
322  }
323 
324  PPL_DIRTY_TEMP(mpq_class, lower_bound);
325  PPL_DIRTY_TEMP(mpq_class, upper_bound);
326  for (dimension_type i = space_dim; i-- > 0; ) {
327  typedef typename Octagonal_Shape<T>::coefficient_type Coeff;
328  I_Constraint<mpq_class> lower;
329  I_Constraint<mpq_class> upper;
330  ITV& seq_i = seq[i];
331  const dimension_type ii = 2*i;
332  const dimension_type cii = ii + 1;
333 
334  // Set the upper bound.
335  const Coeff& twice_ub = oct.matrix[cii][ii];
336  if (!is_plus_infinity(twice_ub)) {
337  assign_r(upper_bound, twice_ub, ROUND_NOT_NEEDED);
338  div_2exp_assign_r(upper_bound, upper_bound, 1, ROUND_NOT_NEEDED);
339  upper.set(LESS_OR_EQUAL, upper_bound);
340  }
341 
342  // Set the lower bound.
343  const Coeff& twice_lb = oct.matrix[ii][cii];
344  if (!is_plus_infinity(twice_lb)) {
345  assign_r(lower_bound, twice_lb, ROUND_NOT_NEEDED);
346  neg_assign_r(lower_bound, lower_bound, ROUND_NOT_NEEDED);
347  div_2exp_assign_r(lower_bound, lower_bound, 1, ROUND_NOT_NEEDED);
348  lower.set(GREATER_OR_EQUAL, lower_bound);
349  }
350  seq_i.build(lower, upper);
351  }
352 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
Status status
The status flags to keep track of the internal state.
Definition: Box_defs.hh:1772
dimension_type check_space_dimension_overflow(const dimension_type dim, const dimension_type max, const char *domain, const char *method, const char *reason)
Definition: globals.cc:48
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
static dimension_type max_space_dimension()
Returns the maximum space dimension that a Box can handle.
Definition: Box_inlines.hh:129
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
#define PPL_DIRTY_TEMP(T, id)
void set_empty_up_to_date()
Asserts the validity of the empty flag of *this.
Definition: Box_inlines.hh:58
void set_empty()
Causes the box to become empty, i.e., to represent the empty set.
Definition: Box_inlines.hh:44
template<typename ITV >
Parma_Polyhedra_Library::Box< ITV >::Box ( const Polyhedron ph,
Complexity_Class  complexity = ANY_COMPLEXITY 
)
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 355 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(), c, 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::Constraint::expression(), 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::Box< ITV >::m_swap(), 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, PPL_DIRTY_TEMP, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Box< ITV >::propagate_constraints_no_check(), Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::I_Constraint< T, Val_Or_Ref_Criteria, extended >::set(), 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(), and Parma_Polyhedra_Library::UNIVERSE.

356  : seq(check_space_dimension_overflow(ph.space_dimension(),
358  "PPL::Box::",
359  "Box(ph)",
360  "ph exceeds the maximum "
361  "allowed space dimension")),
362  status() {
363  // The empty flag will be meaningful, whatever happens from now on.
365 
366  // We do not need to bother about `complexity' if:
367  // a) the polyhedron is already marked empty; or ...
368  if (ph.marked_empty()) {
369  set_empty();
370  return;
371  }
372 
373  // b) the polyhedron is zero-dimensional; or ...
374  const dimension_type space_dim = ph.space_dimension();
375  if (space_dim == 0) {
376  return;
377  }
378 
379  // c) the polyhedron is already described by a generator system.
380  if (ph.generators_are_up_to_date() && !ph.has_pending_constraints()) {
381  Box tmp(ph.generators());
382  m_swap(tmp);
383  return;
384  }
385 
386  // Here generators are not up-to-date or there are pending constraints.
387  PPL_ASSERT(ph.constraints_are_up_to_date());
388 
389  if (complexity == POLYNOMIAL_COMPLEXITY) {
390  // FIXME: is there a way to avoid this initialization?
391  for (dimension_type i = space_dim; i-- > 0; ) {
392  seq[i].assign(UNIVERSE);
393  }
394  // Get a simplified version of the constraints.
395  const Constraint_System cs = ph.simplified_constraints();
396  // Propagate easy-to-find bounds from the constraints,
397  // allowing for a limited number of iterations.
398  // FIXME: 20 is just a wild guess.
399  const dimension_type max_iterations = 20;
400  propagate_constraints_no_check(cs, max_iterations);
401  }
402  else if (complexity == SIMPLEX_COMPLEXITY) {
403  MIP_Problem lp(space_dim);
404  const Constraint_System& ph_cs = ph.constraints();
405  if (!ph_cs.has_strict_inequalities()) {
406  lp.add_constraints(ph_cs);
407  }
408  else {
409  // Adding to `lp' a topologically closed version of `ph_cs'.
410  for (Constraint_System::const_iterator i = ph_cs.begin(),
411  ph_cs_end = ph_cs.end(); i != ph_cs_end; ++i) {
412  const Constraint& c = *i;
413  if (c.is_strict_inequality()) {
414  const Linear_Expression expr(c.expression());
415  lp.add_constraint(expr >= 0);
416  }
417  else {
418  lp.add_constraint(c);
419  }
420  }
421  }
422  // Check for unsatisfiability.
423  if (!lp.is_satisfiable()) {
424  set_empty();
425  return;
426  }
427  // Get all the bounds for the space dimensions.
428  Generator g(point());
429  PPL_DIRTY_TEMP(mpq_class, lower_bound);
430  PPL_DIRTY_TEMP(mpq_class, upper_bound);
431  PPL_DIRTY_TEMP_COEFFICIENT(bound_numer);
432  PPL_DIRTY_TEMP_COEFFICIENT(bound_denom);
433  for (dimension_type i = space_dim; i-- > 0; ) {
434  I_Constraint<mpq_class> lower;
435  I_Constraint<mpq_class> upper;
436  ITV& seq_i = seq[i];
437  lp.set_objective_function(Variable(i));
438  // Evaluate upper bound.
439  lp.set_optimization_mode(MAXIMIZATION);
440  if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
441  g = lp.optimizing_point();
442  lp.evaluate_objective_function(g, bound_numer, bound_denom);
443  assign_r(upper_bound.get_num(), bound_numer, ROUND_NOT_NEEDED);
444  assign_r(upper_bound.get_den(), bound_denom, ROUND_NOT_NEEDED);
445  PPL_ASSERT(is_canonical(upper_bound));
446  upper.set(LESS_OR_EQUAL, upper_bound);
447  }
448  // Evaluate optimal lower bound.
449  lp.set_optimization_mode(MINIMIZATION);
450  if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
451  g = lp.optimizing_point();
452  lp.evaluate_objective_function(g, bound_numer, bound_denom);
453  assign_r(lower_bound.get_num(), bound_numer, ROUND_NOT_NEEDED);
454  assign_r(lower_bound.get_den(), bound_denom, ROUND_NOT_NEEDED);
455  PPL_ASSERT(is_canonical(lower_bound));
456  lower.set(GREATER_OR_EQUAL, lower_bound);
457  }
458  seq_i.build(lower, upper);
459  }
460  }
461  else {
462  PPL_ASSERT(complexity == ANY_COMPLEXITY);
463  if (ph.is_empty()) {
464  set_empty();
465  }
466  else {
467  Box tmp(ph.generators());
468  m_swap(tmp);
469  }
470  }
471 }
Minimization is requested.
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
void m_swap(Box &y)
Swaps *this with y (*this and y can be dimension-incompatible).
Definition: Box_inlines.hh:84
size_t dimension_type
An unsigned integral type for representing space dimensions.
Box(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty box of the specified space dimension.
Status status
The status flags to keep track of the internal state.
Definition: Box_defs.hh:1772
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
void propagate_constraints_no_check(const Constraint_System &cs, dimension_type max_iterations)
Propagates the constraints in cs to refine *this.
Worst-case polynomial complexity.
Worst-case exponential complexity but typically polynomial behavior.
bool is_canonical(const mpq_class &x)
Returns true if and only if x is in canonical form.
dimension_type check_space_dimension_overflow(const dimension_type dim, const dimension_type max, const char *domain, const char *method, const char *reason)
Definition: globals.cc:48
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
static dimension_type max_space_dimension()
Returns the maximum space dimension that a Box can handle.
Definition: Box_inlines.hh:129
#define PPL_DIRTY_TEMP(T, id)
The universe element, i.e., the whole vector space.
Maximization is requested.
void set_empty_up_to_date()
Asserts the validity of the empty flag of *this.
Definition: Box_inlines.hh:58
Coefficient c
Definition: PIP_Tree.cc:64
The problem has an optimal solution.
Constraint_System_const_iterator const_iterator
void set_empty()
Causes the box to become empty, i.e., to represent the empty set.
Definition: Box_inlines.hh:44
template<typename ITV >
Parma_Polyhedra_Library::Box< ITV >::Box ( const Grid gr,
Complexity_Class  complexity = POLYNOMIAL_COMPLEXITY 
)
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 474 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::i_constraint(), Parma_Polyhedra_Library::Grid::marked_empty(), Parma_Polyhedra_Library::Grid::maximize(), PPL_DIRTY_TEMP, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, 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().

475  : seq(check_space_dimension_overflow(gr.space_dimension(),
477  "PPL::Box::",
478  "Box(gr)",
479  "gr exceeds the maximum "
480  "allowed space dimension")),
481  status() {
482 
483  if (gr.marked_empty()) {
484  set_empty();
485  return;
486  }
487 
488  // The empty flag will be meaningful, whatever happens from now on.
490 
491  const dimension_type space_dim = gr.space_dimension();
492 
493  if (space_dim == 0) {
494  return;
495  }
496 
497  if (!gr.generators_are_up_to_date() && !gr.update_generators()) {
498  // Updating found the grid empty.
499  set_empty();
500  return;
501  }
502 
503  PPL_ASSERT(!gr.gen_sys.empty());
504 
505  // For each dimension that is bounded by the grid, set both bounds
506  // of the interval to the value of the associated coefficient in a
507  // generator point.
508  PPL_DIRTY_TEMP(mpq_class, bound);
509  PPL_DIRTY_TEMP_COEFFICIENT(bound_numer);
510  PPL_DIRTY_TEMP_COEFFICIENT(bound_denom);
511  for (dimension_type i = space_dim; i-- > 0; ) {
512  ITV& seq_i = seq[i];
513  Variable var(i);
514  bool max;
515  if (gr.maximize(var, bound_numer, bound_denom, max)) {
516  assign_r(bound.get_num(), bound_numer, ROUND_NOT_NEEDED);
517  assign_r(bound.get_den(), bound_denom, ROUND_NOT_NEEDED);
518  bound.canonicalize();
519  seq_i.build(i_constraint(EQUAL, bound));
520  }
521  else {
522  seq_i.assign(UNIVERSE);
523  }
524  }
525 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
I_Constraint< T > i_constraint(I_Constraint_Rel rel, const T &v)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Status status
The status flags to keep track of the internal state.
Definition: Box_defs.hh:1772
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
dimension_type check_space_dimension_overflow(const dimension_type dim, const dimension_type max, const char *domain, const char *method, const char *reason)
Definition: globals.cc:48
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
static dimension_type max_space_dimension()
Returns the maximum space dimension that a Box can handle.
Definition: Box_inlines.hh:129
#define PPL_DIRTY_TEMP(T, id)
The universe element, i.e., the whole vector space.
void set_empty_up_to_date()
Asserts the validity of the empty flag of *this.
Definition: Box_inlines.hh:58
void set_empty()
Causes the box to become empty, i.e., to represent the empty set.
Definition: Box_inlines.hh:44
template<typename ITV >
template<typename D1 , typename D2 , typename R >
Parma_Polyhedra_Library::Box< ITV >::Box ( const Partially_Reduced_Product< D1, D2, R > &  dp,
Complexity_Class  complexity = ANY_COMPLEXITY 
)
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 529 of file Box_templates.hh.

References Parma_Polyhedra_Library::check_space_dimension_overflow(), 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 >::intersection_assign(), Parma_Polyhedra_Library::Box< ITV >::m_swap(), Parma_Polyhedra_Library::Box< ITV >::max_space_dimension(), and Parma_Polyhedra_Library::Partially_Reduced_Product< D1, D2, R >::space_dimension().

531  : seq(), status() {
532  check_space_dimension_overflow(dp.space_dimension(),
534  "PPL::Box::",
535  "Box(dp)",
536  "dp exceeds the maximum "
537  "allowed space dimension");
538  Box tmp1(dp.domain1(), complexity);
539  Box tmp2(dp.domain2(), complexity);
540  tmp1.intersection_assign(tmp2);
541  m_swap(tmp1);
542 }
void m_swap(Box &y)
Swaps *this with y (*this and y can be dimension-incompatible).
Definition: Box_inlines.hh:84
Box(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty box of the specified space dimension.
Status status
The status flags to keep track of the internal state.
Definition: Box_defs.hh:1772
dimension_type check_space_dimension_overflow(const dimension_type dim, const dimension_type max, const char *domain, const char *method, const char *reason)
Definition: globals.cc:48
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
static dimension_type max_space_dimension()
Returns the maximum space dimension that a Box can handle.
Definition: Box_inlines.hh:129

Member Function Documentation

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::add_congruence ( const Congruence cg)
inline

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

Parameters
cgThe congruence to be added.
Exceptions
std::invalid_argumentThrown if *this and congruence cg are dimension-incompatible, or cg is not optimally supported by the box domain.

Definition at line 348 of file Box_inlines.hh.

References Parma_Polyhedra_Library::Congruence::space_dimension().

348  {
349  const dimension_type cg_space_dim = cg.space_dimension();
350  // Dimension-compatibility check.
351  if (cg_space_dim > space_dimension()) {
352  throw_dimension_incompatible("add_congruence(cg)", cg);
353  }
354 
356 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
void add_congruence_no_check(const Congruence &cg)
WRITE ME.
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::add_congruence_no_check ( const Congruence cg)
private

WRITE ME.

Definition at line 2411 of file Box_templates.hh.

References Parma_Polyhedra_Library::Congruence::coefficient(), Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::Box_Helpers::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(), and Parma_Polyhedra_Library::Congruence::space_dimension().

2411  {
2412  PPL_ASSERT(cg.space_dimension() <= space_dimension());
2413 
2414  // Set aside the case of proper congruences.
2415  if (cg.is_proper_congruence()) {
2416  if (cg.is_inconsistent()) {
2417  set_empty();
2418  return;
2419  }
2420  else if (cg.is_tautological()) {
2421  return;
2422  }
2423  else {
2424  throw_invalid_argument("add_congruence(cg)",
2425  "cg is a nontrivial proper congruence");
2426  }
2427  }
2428 
2429  PPL_ASSERT(cg.is_equality());
2430  dimension_type cg_num_vars = 0;
2431  dimension_type cg_only_var = 0;
2432  // Throw an exception if c is not an interval congruence.
2433  if (!Box_Helpers::extract_interval_congruence(cg, cg_num_vars, cg_only_var)) {
2434  throw_invalid_argument("add_congruence(cg)",
2435  "cg is not an interval congruence");
2436  }
2437 
2438  // Avoid doing useless work if the box is known to be empty.
2439  if (marked_empty()) {
2440  return;
2441  }
2442 
2443  const Coefficient& n = cg.inhomogeneous_term();
2444  if (cg_num_vars == 0) {
2445  // Dealing with a trivial equality congruence.
2446  if (n != 0) {
2447  set_empty();
2448  }
2449  return;
2450  }
2451 
2452  PPL_ASSERT(cg_num_vars == 1);
2453  const Coefficient& d = cg.coefficient(Variable(cg_only_var));
2455 }
static bool extract_interval_congruence(const Congruence &cg, dimension_type &cg_num_vars, dimension_type &cg_only_var)
Definition: Box.cc:48
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
static void throw_invalid_argument(const char *method, const char *reason)
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
void add_interval_constraint_no_check(dimension_type var_id, Constraint::Type type, Coefficient_traits::const_reference numer, Coefficient_traits::const_reference denom)
WRITE ME.
Definition: Box_inlines.hh:442
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
void set_empty()
Causes the box to become empty, i.e., to represent the empty set.
Definition: Box_inlines.hh:44
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::add_congruences ( const Congruence_System cgs)
inline

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

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

Definition at line 360 of file Box_inlines.hh.

References Parma_Polyhedra_Library::Congruence_System::space_dimension().

360  {
361  if (cgs.space_dimension() > space_dimension()) {
362  throw_dimension_incompatible("add_congruences(cgs)", cgs);
363  }
365 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
void add_congruences_no_check(const Congruence_System &cgs)
WRITE ME.
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::add_congruences_no_check ( const Congruence_System cgs)
private

WRITE ME.

Definition at line 2459 of file Box_templates.hh.

References Parma_Polyhedra_Library::Congruence_System::begin(), Parma_Polyhedra_Library::Congruence_System::end(), and Parma_Polyhedra_Library::Congruence_System::space_dimension().

Referenced by Parma_Polyhedra_Library::Box< ITV >::Box().

2459  {
2460  PPL_ASSERT(cgs.space_dimension() <= space_dimension());
2461  // Note: even when the box is known to be empty, we need to go
2462  // through all the congruences to fulfill the method's contract
2463  // for what concerns exception throwing.
2464  for (Congruence_System::const_iterator i = cgs.begin(),
2465  cgs_end = cgs.end(); i != cgs_end; ++i) {
2467  }
2468  PPL_ASSERT(OK());
2469 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
void add_congruence_no_check(const Congruence &cg)
WRITE ME.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
template<typename ITV >
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.

Parameters
cThe constraint to be added.
Exceptions
std::invalid_argumentThrown if *this and constraint c are dimension-incompatible, or c is not optimally supported by the Box domain.

Definition at line 319 of file Box_inlines.hh.

References Parma_Polyhedra_Library::Constraint::space_dimension().

319  {
320  const dimension_type c_space_dim = c.space_dimension();
321  // Dimension-compatibility check.
322  if (c_space_dim > space_dimension()) {
323  throw_dimension_incompatible("add_constraint(c)", c);
324  }
325 
327 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
void add_constraint_no_check(const Constraint &c)
WRITE ME.
Coefficient c
Definition: PIP_Tree.cc:64
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::add_constraint_no_check ( const Constraint c)
private

WRITE ME.

Definition at line 2355 of file Box_templates.hh.

References Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Box_Helpers::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::Constraint::space_dimension(), and Parma_Polyhedra_Library::Constraint::type().

2355  {
2356  PPL_ASSERT(c.space_dimension() <= space_dimension());
2357 
2358  dimension_type c_num_vars = 0;
2359  dimension_type c_only_var = 0;
2360  // Throw an exception if c is not an interval constraints.
2361  if (!Box_Helpers::extract_interval_constraint(c, c_num_vars, c_only_var)) {
2362  throw_invalid_argument("add_constraint(c)",
2363  "c is not an interval constraint");
2364  }
2365 
2366  // Throw an exception if c is a nontrivial strict constraint
2367  // and ITV does not support open boundaries.
2368  if (c.is_strict_inequality() && c_num_vars != 0
2369  && ITV::is_always_topologically_closed()) {
2370  throw_invalid_argument("add_constraint(c)",
2371  "c is a nontrivial strict constraint");
2372  }
2373 
2374  // Avoid doing useless work if the box is known to be empty.
2375  if (marked_empty()) {
2376  return;
2377  }
2378 
2379  const Coefficient& n = c.inhomogeneous_term();
2380  if (c_num_vars == 0) {
2381  // Dealing with a trivial constraint.
2382  if (n < 0
2383  || (c.is_equality() && n != 0)
2384  || (c.is_strict_inequality() && n == 0)) {
2385  set_empty();
2386  }
2387  return;
2388  }
2389 
2390  PPL_ASSERT(c_num_vars == 1);
2391  const Coefficient& d = c.coefficient(Variable(c_only_var));
2392  add_interval_constraint_no_check(c_only_var, c.type(), n, d);
2393 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
static bool extract_interval_constraint(const Constraint &c, dimension_type &c_num_vars, dimension_type &c_only_var)
Decodes the constraint c as an interval constraint.
Definition: Box.cc:30
static void throw_invalid_argument(const char *method, const char *reason)
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
Coefficient c
Definition: PIP_Tree.cc:64
void add_interval_constraint_no_check(dimension_type var_id, Constraint::Type type, Coefficient_traits::const_reference numer, Coefficient_traits::const_reference denom)
WRITE ME.
Definition: Box_inlines.hh:442
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
void set_empty()
Causes the box to become empty, i.e., to represent the empty set.
Definition: Box_inlines.hh:44
template<typename ITV >
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.

Parameters
csThe constraints to be added.
Exceptions
std::invalid_argumentThrown if *this and cs are dimension-incompatible, or cs contains a constraint which is not optimally supported by the box domain.

Definition at line 331 of file Box_inlines.hh.

References Parma_Polyhedra_Library::Constraint_System::space_dimension().

331  {
332  // Dimension-compatibility check.
333  if (cs.space_dimension() > space_dimension()) {
334  throw_dimension_incompatible("add_constraints(cs)", cs);
335  }
336 
338 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
void add_constraints_no_check(const Constraint_System &cs)
WRITE ME.
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::add_constraints_no_check ( const Constraint_System cs)
private

WRITE ME.

Definition at line 2397 of file Box_templates.hh.

References Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint_System::end(), and Parma_Polyhedra_Library::Constraint_System::space_dimension().

Referenced by Parma_Polyhedra_Library::Box< ITV >::Box().

2397  {
2398  PPL_ASSERT(cs.space_dimension() <= space_dimension());
2399  // Note: even when the box is known to be empty, we need to go
2400  // through all the constraints to fulfill the method's contract
2401  // for what concerns exception throwing.
2402  for (Constraint_System::const_iterator i = cs.begin(),
2403  cs_end = cs.end(); i != cs_end; ++i) {
2405  }
2406  PPL_ASSERT(OK());
2407 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
void add_constraint_no_check(const Constraint &c)
WRITE ME.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
Constraint_System_const_iterator const_iterator
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::add_interval_constraint_no_check ( dimension_type  var_id,
Constraint::Type  type,
Coefficient_traits::const_reference  numer,
Coefficient_traits::const_reference  denom 
)
inlineprivate

WRITE ME.

Definition at line 442 of file Box_inlines.hh.

Referenced by Parma_Polyhedra_Library::Box< ITV >::get_limiting_box().

445  {
446  PPL_ASSERT(!marked_empty());
447  PPL_ASSERT(var_id < space_dimension());
448  PPL_ASSERT(denom != 0);
449  refine_interval_no_check(seq[var_id], type, numer, denom);
450  // FIXME: do check the value returned and set `empty' and
451  // `empty_up_to_date' as appropriate.
452  // This has to be done after reimplementation of intervals.
454  PPL_ASSERT(OK());
455 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
void reset_empty_up_to_date()
Invalidates empty flag of *this.
Definition: Box_inlines.hh:64
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
static I_Result refine_interval_no_check(ITV &itv, Constraint::Type type, Coefficient_traits::const_reference numer, Coefficient_traits::const_reference denom)
WRITE ME.
Definition: Box_inlines.hh:401
bool OK() const
Returns true if and only if *this satisfies all its invariants.
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename T >
void Parma_Polyhedra_Library::Box< T >::add_recycled_congruences ( Congruence_System cgs)
inline

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

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

Definition at line 369 of file Box_inlines.hh.

369  {
370  add_congruences(cgs);
371 }
void add_congruences(const Congruence_System &cgs)
Adds to *this constraints equivalent to the congruences in cgs.
Definition: Box_inlines.hh:360
template<typename T >
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.

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

Definition at line 342 of file Box_inlines.hh.

342  {
343  add_constraints(cs);
344 }
void add_constraints(const Constraint_System &cs)
Adds the constraints in cs to the system of constraints defining *this.
Definition: Box_inlines.hh:331
template<typename ITV >
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.

Parameters
mThe 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 $\cB \sseq \Rset^2$ and adding a third dimension, the result will be the box

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

Definition at line 546 of file Box_templates.hh.

References Parma_Polyhedra_Library::check_space_dimension_overflow(), Parma_Polyhedra_Library::max_space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.

546  {
547  // Adding no dimensions is a no-op.
548  if (m == 0) {
549  return;
550  }
552  "PPL::Box::",
553  "add_space_dimensions_and_embed(m)",
554  "adding m new space dimensions exceeds "
555  "the maximum allowed space dimension");
556  // To embed an n-dimension space box in a (n+m)-dimension space,
557  // we just add `m' new universe elements to the sequence.
558  seq.insert(seq.end(), m, ITV(UNIVERSE));
559  PPL_ASSERT(OK());
560 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
dimension_type check_space_dimension_overflow(const dimension_type dim, const dimension_type max, const char *domain, const char *method, const char *reason)
Definition: globals.cc:48
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
static dimension_type max_space_dimension()
Returns the maximum space dimension that a Box can handle.
Definition: Box_inlines.hh:129
The universe element, i.e., the whole vector space.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
template<typename ITV >
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.

Parameters
mThe 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 $\cB \sseq \Rset^2$ and adding a third dimension, the result will be the box

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

Definition at line 564 of file Box_templates.hh.

References Parma_Polyhedra_Library::check_space_dimension_overflow(), and Parma_Polyhedra_Library::max_space_dimension().

564  {
565  // Adding no dimensions is a no-op.
566  if (m == 0) {
567  return;
568  }
570  "PPL::Box::",
571  "add_space_dimensions_and_project(m)",
572  "adding m new space dimensions exceeds "
573  "the maximum allowed space dimension");
574  // Add `m' new zero elements to the sequence.
575  seq.insert(seq.end(), m, ITV(0));
576  PPL_ASSERT(OK());
577 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
dimension_type check_space_dimension_overflow(const dimension_type dim, const dimension_type max, const char *domain, const char *method, const char *reason)
Definition: globals.cc:48
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
static dimension_type max_space_dimension()
Returns the maximum space dimension that a Box can handle.
Definition: Box_inlines.hh:129
bool OK() const
Returns true if and only if *this satisfies all its invariants.
template<typename ITV >
dimension_type Parma_Polyhedra_Library::Box< ITV >::affine_dimension ( ) const

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

Definition at line 1427 of file Box_templates.hh.

1427  {
1429  // A zero-space-dim box always has affine dimension zero.
1430  if (d == 0) {
1431  return 0;
1432  }
1433 
1434  // An empty box has affine dimension zero.
1435  if (is_empty()) {
1436  return 0;
1437  }
1438 
1439  for (dimension_type k = d; k-- > 0; ) {
1440  if (seq[k].is_singleton()) {
1441  --d;
1442  }
1443  }
1444 
1445  return d;
1446 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::affine_form_image ( Variable  var,
const Linear_Form< ITV > &  lf 
)

Assigns to *this the affine form image of *this under the function mapping variable var into the affine expression(s) specified by lf.

Parameters
varThe variable to which the affine expression is assigned.
lfThe linear form on intervals with floating point boundaries that defines the affine expression(s). ALL of its coefficients MUST be bounded.
Exceptions
std::invalid_argumentThrown if lf and *this are dimension-incompatible or if var is not a dimension of *this.

This function is used in abstract interpretation to model an assignment of a value that is correctly overapproximated by lf to the floating point variable represented by var.

Definition at line 3115 of file Box_templates.hh.

References Parma_Polyhedra_Library::Linear_Form< C >::coefficient(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Form< C >::inhomogeneous_term(), PPL_COMPILE_TIME_CHECK, Parma_Polyhedra_Library::Variable::space_dimension(), and Parma_Polyhedra_Library::Linear_Form< C >::space_dimension().

3116  {
3117 
3118  // Check that ITV has a floating point boundary type.
3119  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<typename ITV::boundary_type>
3120  ::is_exact, "Box<ITV>::affine_form_image(Variable, Linear_Form):"
3121  "ITV has not a floating point boundary type.");
3122 
3123  // Dimension-compatibility checks.
3124  const dimension_type space_dim = space_dimension();
3125  const dimension_type lf_space_dim = lf.space_dimension();
3126  if (space_dim < lf_space_dim) {
3127  throw_dimension_incompatible("affine_form_image(var, lf)", "lf", lf);
3128  }
3129 
3130  // `var' should be one of the dimensions of the polyhedron.
3131  const dimension_type var_space_dim = var.space_dimension();
3132  if (space_dim < var_space_dim) {
3133  throw_dimension_incompatible("affine_form_image(var, lf)", "var", var);
3134  }
3135 
3136  if (is_empty()) {
3137  return;
3138  }
3139 
3140  // Intervalization of 'lf'.
3141  ITV result = lf.inhomogeneous_term();
3142  for (dimension_type i = 0; i < lf_space_dim; ++i) {
3143  ITV current_addend = lf.coefficient(Variable(i));
3144  const ITV& curr_int = seq[i];
3145  current_addend *= curr_int;
3146  result += current_addend;
3147  }
3148 
3149  seq[var.id()].assign(result);
3150  PPL_ASSERT(OK());
3151 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
#define PPL_COMPILE_TIME_CHECK(e, msg)
Produces a compilation error if the compile-time constant e does not evaluate to true ...
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
bool OK() const
Returns true if and only if *this satisfies all its invariants.
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::affine_image ( Variable  var,
const Linear_Expression expr,
Coefficient_traits::const_reference  denominator = Coefficient_one() 
)

Assigns to *this the affine image of *this under the function mapping variable var to the affine expression specified by expr and denominator.

Parameters
varThe variable to which the affine expression is assigned;
exprThe numerator of the affine expression;
denominatorThe denominator of the affine expression (optional argument with default value 1).
Exceptions
std::invalid_argumentThrown 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 3069 of file Box_templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::begin(), Parma_Polyhedra_Library::Linear_Expression::end(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Variable::space_dimension(), and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

3071  {
3072  // The denominator cannot be zero.
3073  if (denominator == 0) {
3074  throw_invalid_argument("affine_image(v, e, d)", "d == 0");
3075  }
3076 
3077  // Dimension-compatibility checks.
3078  const dimension_type space_dim = space_dimension();
3079  const dimension_type expr_space_dim = expr.space_dimension();
3080  if (space_dim < expr_space_dim) {
3081  throw_dimension_incompatible("affine_image(v, e, d)", "e", expr);
3082  }
3083  // `var' should be one of the dimensions of the polyhedron.
3084  const dimension_type var_space_dim = var.space_dimension();
3085  if (space_dim < var_space_dim) {
3086  throw_dimension_incompatible("affine_image(v, e, d)", "v", var);
3087  }
3088 
3089  if (is_empty()) {
3090  return;
3091  }
3092 
3093  Tmp_Interval_Type expr_value;
3094  Tmp_Interval_Type temp0;
3095  Tmp_Interval_Type temp1;
3096  expr_value.assign(expr.inhomogeneous_term());
3097  for (Linear_Expression::const_iterator i = expr.begin(),
3098  i_end = expr.end(); i != i_end; ++i) {
3099  temp0.assign(*i);
3100  temp1.assign(seq[i.variable().id()]);
3101  temp0.mul_assign(temp0, temp1);
3102  expr_value.add_assign(expr_value, temp0);
3103  }
3104  if (denominator != 1) {
3105  temp0.assign(denominator);
3106  expr_value.div_assign(expr_value, temp0);
3107  }
3108  seq[var.id()].assign(expr_value);
3109 
3110  PPL_ASSERT(OK());
3111 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
ITV Tmp_Interval_Type
The type of intervals used by inner computations when trying to limit the cumulative effect of approx...
Definition: Box_defs.hh:1762
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
static void throw_invalid_argument(const char *method, const char *reason)
bool OK() const
Returns true if and only if *this satisfies all its invariants.
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::affine_preimage ( Variable  var,
const Linear_Expression expr,
Coefficient_traits::const_reference  denominator = Coefficient_one() 
)

Assigns to *this the affine preimage of *this under the function mapping variable var to the affine expression specified by expr and denominator.

Parameters
varThe variable to which the affine expression is substituted;
exprThe numerator of the affine expression;
denominatorThe denominator of the affine expression (optional argument with default value 1).
Exceptions
std::invalid_argumentThrown 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 3155 of file Box_templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::begin(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Linear_Expression::end(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::inverse(), Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.

3158  {
3159  // The denominator cannot be zero.
3160  if (denominator == 0) {
3161  throw_invalid_argument("affine_preimage(v, e, d)", "d == 0");
3162  }
3163 
3164  // Dimension-compatibility checks.
3165  const dimension_type x_space_dim = space_dimension();
3166  const dimension_type expr_space_dim = expr.space_dimension();
3167  if (x_space_dim < expr_space_dim) {
3168  throw_dimension_incompatible("affine_preimage(v, e, d)", "e", expr);
3169  }
3170  // `var' should be one of the dimensions of the polyhedron.
3171  const dimension_type var_space_dim = var.space_dimension();
3172  if (x_space_dim < var_space_dim) {
3173  throw_dimension_incompatible("affine_preimage(v, e, d)", "v", var);
3174  }
3175 
3176  if (is_empty()) {
3177  return;
3178  }
3179 
3180  const Coefficient& expr_v = expr.coefficient(var);
3181  const bool invertible = (expr_v != 0);
3182  if (!invertible) {
3183  Tmp_Interval_Type expr_value;
3184  Tmp_Interval_Type temp0;
3185  Tmp_Interval_Type temp1;
3186  expr_value.assign(expr.inhomogeneous_term());
3187  for (Linear_Expression::const_iterator i = expr.begin(),
3188  i_end = expr.end(); i != i_end; ++i) {
3189  temp0.assign(*i);
3190  temp1.assign(seq[i.variable().id()]);
3191  temp0.mul_assign(temp0, temp1);
3192  expr_value.add_assign(expr_value, temp0);
3193  }
3194  if (denominator != 1) {
3195  temp0.assign(denominator);
3196  expr_value.div_assign(expr_value, temp0);
3197  }
3198  ITV& x_seq_v = seq[var.id()];
3199  expr_value.intersect_assign(x_seq_v);
3200  if (expr_value.is_empty()) {
3201  set_empty();
3202  }
3203  else {
3204  x_seq_v.assign(UNIVERSE);
3205  }
3206  }
3207  else {
3208  // The affine transformation is invertible.
3209  // CHECKME: for efficiency, would it be meaningful to avoid
3210  // the computation of inverse by partially evaluating the call
3211  // to affine_image?
3212  Linear_Expression inverse;
3213  inverse -= expr;
3214  inverse += (expr_v + denominator) * var;
3215  affine_image(var, inverse, expr_v);
3216  }
3217  PPL_ASSERT(OK());
3218 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
ITV Tmp_Interval_Type
The type of intervals used by inner computations when trying to limit the cumulative effect of approx...
Definition: Box_defs.hh:1762
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
Rounding_Dir inverse(Rounding_Dir dir)
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
static void throw_invalid_argument(const char *method, const char *reason)
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
The universe element, i.e., the whole vector space.
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 expr...
bool OK() const
Returns true if and only if *this satisfies all its invariants.
void set_empty()
Causes the box to become empty, i.e., to represent the empty set.
Definition: Box_inlines.hh:44
template<typename ITV>
void Parma_Polyhedra_Library::Box< ITV >::ascii_dump ( ) const

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

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::ascii_dump ( std::ostream &  s) const

Writes to s an ASCII representation of *this.

Definition at line 4414 of file Box_templates.hh.

References Parma_Polyhedra_Library::Implementation::BD_Shapes::separator.

4414  {
4415  const char separator = ' ';
4416  status.ascii_dump(s);
4417  const dimension_type space_dim = space_dimension();
4418  s << "space_dim" << separator << space_dim;
4419  s << "\n";
4420  for (dimension_type i = 0; i < space_dim; ++i) {
4421  seq[i].ascii_dump(s);
4422  }
4423 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
Status status
The status flags to keep track of the internal state.
Definition: Box_defs.hh:1772
void ascii_dump() const
Writes to std::cerr an ASCII representation of *this.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::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.

Definition at line 4429 of file Box_templates.hh.

4429  {
4430  if (!status.ascii_load(s)) {
4431  return false;
4432  }
4433  std::string str;
4434  dimension_type space_dim;
4435  if (!(s >> str) || str != "space_dim") {
4436  return false;
4437  }
4438  if (!(s >> space_dim)) {
4439  return false;
4440  }
4441  seq.clear();
4442  ITV seq_i;
4443  for (dimension_type i = 0; i < space_dim; ++i) {
4444  if (seq_i.ascii_load(s)) {
4445  seq.push_back(seq_i);
4446  }
4447  else {
4448  return false;
4449  }
4450  }
4451 
4452  // Check invariants.
4453  PPL_ASSERT(OK());
4454  return true;
4455 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Status status
The status flags to keep track of the internal state.
Definition: Box_defs.hh:1772
bool ascii_load(std::istream &s)
Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this ...
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
bool OK() const
Returns true if and only if *this satisfies all its invariants.
template<typename ITV >
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() 
)

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

Parameters
varThe variable updated by the affine relation;
lb_exprThe numerator of the lower bounding affine expression;
ub_exprThe numerator of the upper bounding affine expression;
denominatorThe (common) denominator for the lower and upper bounding affine expressions (optional argument with default value 1).
Exceptions
std::invalid_argumentThrown 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 3223 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::i_constraint(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, PPL_DIRTY_TEMP, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.

3226  {
3227  // The denominator cannot be zero.
3228  if (denominator == 0) {
3229  throw_invalid_argument("bounded_affine_image(v, lb, ub, d)", "d == 0");
3230  }
3231 
3232  // Dimension-compatibility checks.
3233  const dimension_type space_dim = space_dimension();
3234  // The dimension of `lb_expr' and `ub_expr' should not be
3235  // greater than the dimension of `*this'.
3236  const dimension_type lb_space_dim = lb_expr.space_dimension();
3237  if (space_dim < lb_space_dim) {
3238  throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
3239  "lb", lb_expr);
3240  }
3241  const dimension_type ub_space_dim = ub_expr.space_dimension();
3242  if (space_dim < ub_space_dim) {
3243  throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
3244  "ub", ub_expr);
3245  }
3246  // `var' should be one of the dimensions of the box.
3247  const dimension_type var_space_dim = var.space_dimension();
3248  if (space_dim < var_space_dim) {
3249  throw_dimension_incompatible("affine_image(v, e, d)", "v", var);
3250  }
3251  // Any image of an empty box is empty.
3252  if (is_empty()) {
3253  return;
3254  }
3255  // Add the constraint implied by the `lb_expr' and `ub_expr'.
3256  if (denominator > 0) {
3257  refine_with_constraint(lb_expr <= ub_expr);
3258  }
3259  else {
3260  refine_with_constraint(lb_expr >= ub_expr);
3261  }
3262 
3263  // Check whether `var' occurs in `lb_expr' and/or `ub_expr'.
3264  if (lb_expr.coefficient(var) == 0) {
3265  // Here `var' can only occur in `ub_expr'.
3267  LESS_OR_EQUAL,
3268  ub_expr,
3269  denominator);
3270  if (denominator > 0) {
3271  refine_with_constraint(lb_expr <= denominator*var);
3272  }
3273  else {
3274  refine_with_constraint(denominator*var <= lb_expr);
3275  }
3276  }
3277  else if (ub_expr.coefficient(var) == 0) {
3278  // Here `var' can only occur in `lb_expr'.
3281  lb_expr,
3282  denominator);
3283  if (denominator > 0) {
3284  refine_with_constraint(denominator*var <= ub_expr);
3285  }
3286  else {
3287  refine_with_constraint(ub_expr <= denominator*var);
3288  }
3289  }
3290  else {
3291  // Here `var' occurs in both `lb_expr' and `ub_expr'. As boxes
3292  // can only use the non-relational constraints, we find the
3293  // maximum/minimum values `ub_expr' and `lb_expr' obtain with the
3294  // box and use these instead of the `ub-expr' and `lb-expr'.
3295  PPL_DIRTY_TEMP_COEFFICIENT(max_numer);
3296  PPL_DIRTY_TEMP_COEFFICIENT(max_denom);
3297  bool max_included;
3298  PPL_DIRTY_TEMP_COEFFICIENT(min_numer);
3299  PPL_DIRTY_TEMP_COEFFICIENT(min_denom);
3300  bool min_included;
3301  ITV& seq_v = seq[var.id()];
3302  if (maximize(ub_expr, max_numer, max_denom, max_included)) {
3303  if (minimize(lb_expr, min_numer, min_denom, min_included)) {
3304  // The `ub_expr' has a maximum value and the `lb_expr'
3305  // has a minimum value for the box.
3306  // Set the bounds for `var' using the minimum for `lb_expr'.
3307  min_denom *= denominator;
3308  PPL_DIRTY_TEMP(mpq_class, q1);
3309  PPL_DIRTY_TEMP(mpq_class, q2);
3310  assign_r(q1.get_num(), min_numer, ROUND_NOT_NEEDED);
3311  assign_r(q1.get_den(), min_denom, ROUND_NOT_NEEDED);
3312  q1.canonicalize();
3313  // Now make the maximum of lb_expr the upper bound. If the
3314  // maximum is not at a box point, then inequality is strict.
3315  max_denom *= denominator;
3316  assign_r(q2.get_num(), max_numer, ROUND_NOT_NEEDED);
3317  assign_r(q2.get_den(), max_denom, ROUND_NOT_NEEDED);
3318  q2.canonicalize();
3319 
3320  if (denominator > 0) {
3321  Relation_Symbol gr = min_included ? GREATER_OR_EQUAL : GREATER_THAN;
3322  Relation_Symbol lr = max_included ? LESS_OR_EQUAL : LESS_THAN;
3323  seq_v.build(i_constraint(gr, q1), i_constraint(lr, q2));
3324  }
3325  else {
3326  Relation_Symbol gr = max_included ? GREATER_OR_EQUAL : GREATER_THAN;
3327  Relation_Symbol lr = min_included ? LESS_OR_EQUAL : LESS_THAN;
3328  seq_v.build(i_constraint(gr, q2), i_constraint(lr, q1));
3329  }
3330  }
3331  else {
3332  // The `ub_expr' has a maximum value but the `lb_expr'
3333  // has no minimum value for the box.
3334  // Set the bounds for `var' using the maximum for `lb_expr'.
3335  PPL_DIRTY_TEMP(mpq_class, q);
3336  max_denom *= denominator;
3337  assign_r(q.get_num(), max_numer, ROUND_NOT_NEEDED);
3338  assign_r(q.get_den(), max_denom, ROUND_NOT_NEEDED);
3339  q.canonicalize();
3340  Relation_Symbol rel = (denominator > 0)
3341  ? (max_included ? LESS_OR_EQUAL : LESS_THAN)
3342  : (max_included ? GREATER_OR_EQUAL : GREATER_THAN);
3343  seq_v.build(i_constraint(rel, q));
3344  }
3345  }
3346  else if (minimize(lb_expr, min_numer, min_denom, min_included)) {
3347  // The `ub_expr' has no maximum value but the `lb_expr'
3348  // has a minimum value for the box.
3349  // Set the bounds for `var' using the minimum for `lb_expr'.
3350  min_denom *= denominator;
3351  PPL_DIRTY_TEMP(mpq_class, q);
3352  assign_r(q.get_num(), min_numer, ROUND_NOT_NEEDED);
3353  assign_r(q.get_den(), min_denom, ROUND_NOT_NEEDED);
3354  q.canonicalize();
3355 
3356  Relation_Symbol rel = (denominator > 0)
3357  ? (min_included ? GREATER_OR_EQUAL : GREATER_THAN)
3358  : (min_included ? LESS_OR_EQUAL : LESS_THAN);
3359  seq_v.build(i_constraint(rel, q));
3360  }
3361  else {
3362  // The `ub_expr' has no maximum value and the `lb_expr'
3363  // has no minimum value for the box.
3364  // So we set the bounds to be unbounded.
3365  seq_v.assign(UNIVERSE);
3366  }
3367  }
3368  PPL_ASSERT(OK());
3369 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
I_Constraint< T > i_constraint(I_Constraint_Rel rel, const T &v)
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
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 ...
void refine_with_constraint(const Constraint &c)
Use the constraint c to refine *this.
Definition: Box_inlines.hh:459
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
Relation_Symbol
Relation symbols.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
static void throw_invalid_argument(const char *method, const char *reason)
#define PPL_DIRTY_TEMP(T, id)
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.
Definition: Box_inlines.hh:217
The universe element, i.e., the whole vector space.
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.
Definition: Box_inlines.hh:201
bool OK() const
Returns true if and only if *this satisfies all its invariants.
template<typename ITV >
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() 
)

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

Parameters
varThe variable updated by the affine relation;
lb_exprThe numerator of the lower bounding affine expression;
ub_exprThe numerator of the upper bounding affine expression;
denominatorThe (common) denominator for the lower and upper bounding affine expressions (optional argument with default value 1).
Exceptions
std::invalid_argumentThrown 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 3374 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::i_constraint(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::neg_assign(), PPL_DIRTY_TEMP, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::Variable::space_dimension(), and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

3377  {
3378  // The denominator cannot be zero.
3379  const dimension_type space_dim = space_dimension();
3380  if (denominator == 0) {
3381  throw_invalid_argument("bounded_affine_preimage(v, lb, ub, d)", "d == 0");
3382  }
3383 
3384  // Dimension-compatibility checks.
3385  // `var' should be one of the dimensions of the polyhedron.
3386  const dimension_type var_space_dim = var.space_dimension();
3387  if (space_dim < var_space_dim) {
3388  throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
3389  "v", var);
3390  }
3391  // The dimension of `lb_expr' and `ub_expr' should not be
3392  // greater than the dimension of `*this'.
3393  const dimension_type lb_space_dim = lb_expr.space_dimension();
3394  if (space_dim < lb_space_dim) {
3395  throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
3396  "lb", lb_expr);
3397  }
3398  const dimension_type ub_space_dim = ub_expr.space_dimension();
3399  if (space_dim < ub_space_dim) {
3400  throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
3401  "ub", ub_expr);
3402  }
3403 
3404  // Any preimage of an empty polyhedron is empty.
3405  if (marked_empty()) {
3406  return;
3407  }
3408 
3409  const bool negative_denom = (denominator < 0);
3410  const Coefficient& lb_var_coeff = lb_expr.coefficient(var);
3411  const Coefficient& ub_var_coeff = ub_expr.coefficient(var);
3412 
3413  // If the implied constraint between `ub_expr and `lb_expr' is
3414  // independent of `var', then impose it now.
3415  if (lb_var_coeff == ub_var_coeff) {
3416  if (negative_denom) {
3417  refine_with_constraint(lb_expr >= ub_expr);
3418  }
3419  else {
3420  refine_with_constraint(lb_expr <= ub_expr);
3421  }
3422  }
3423 
3424  ITV& seq_var = seq[var.id()];
3425  if (!seq_var.is_universe()) {
3426  // We want to work with a positive denominator,
3427  // so the sign and its (unsigned) value are separated.
3428  PPL_DIRTY_TEMP_COEFFICIENT(pos_denominator);
3429  pos_denominator = denominator;
3430  if (negative_denom) {
3431  neg_assign(pos_denominator, pos_denominator);
3432  }
3433  // Store all the information about the upper and lower bounds
3434  // for `var' before making this interval unbounded.
3435  bool open_lower = seq_var.lower_is_open();
3436  bool unbounded_lower = seq_var.lower_is_boundary_infinity();
3437  PPL_DIRTY_TEMP(mpq_class, q_seq_var_lower);
3438  PPL_DIRTY_TEMP_COEFFICIENT(numer_lower);
3439  PPL_DIRTY_TEMP_COEFFICIENT(denom_lower);
3440  if (!unbounded_lower) {
3441  assign_r(q_seq_var_lower, seq_var.lower(), ROUND_NOT_NEEDED);
3442  assign_r(numer_lower, q_seq_var_lower.get_num(), ROUND_NOT_NEEDED);
3443  assign_r(denom_lower, q_seq_var_lower.get_den(), ROUND_NOT_NEEDED);
3444  if (negative_denom) {
3445  neg_assign(denom_lower, denom_lower);
3446  }
3447  numer_lower *= pos_denominator;
3448  seq_var.lower_extend();
3449  }
3450  bool open_upper = seq_var.upper_is_open();
3451  bool unbounded_upper = seq_var.upper_is_boundary_infinity();
3452  PPL_DIRTY_TEMP(mpq_class, q_seq_var_upper);
3453  PPL_DIRTY_TEMP_COEFFICIENT(numer_upper);
3454  PPL_DIRTY_TEMP_COEFFICIENT(denom_upper);
3455  if (!unbounded_upper) {
3456  assign_r(q_seq_var_upper, seq_var.upper(), ROUND_NOT_NEEDED);
3457  assign_r(numer_upper, q_seq_var_upper.get_num(), ROUND_NOT_NEEDED);
3458  assign_r(denom_upper, q_seq_var_upper.get_den(), ROUND_NOT_NEEDED);
3459  if (negative_denom) {
3460  neg_assign(denom_upper, denom_upper);
3461  }
3462  numer_upper *= pos_denominator;
3463  seq_var.upper_extend();
3464  }
3465 
3466  if (!unbounded_lower) {
3467  // `lb_expr' is revised by removing the `var' component,
3468  // multiplying by `-' denominator of the lower bound for `var',
3469  // and adding the lower bound for `var' to the inhomogeneous term.
3470  Linear_Expression revised_lb_expr(ub_expr);
3471  revised_lb_expr -= ub_var_coeff * var;
3473  neg_assign(d, denom_lower);
3474  revised_lb_expr *= d;
3475  revised_lb_expr += numer_lower;
3476 
3477  // Find the minimum value for the revised lower bound expression
3478  // and use this to refine the appropriate bound.
3479  bool included;
3481  if (minimize(revised_lb_expr, numer_lower, denom, included)) {
3482  denom_lower *= (denom * ub_var_coeff);
3483  PPL_DIRTY_TEMP(mpq_class, q);
3484  assign_r(q.get_num(), numer_lower, ROUND_NOT_NEEDED);
3485  assign_r(q.get_den(), denom_lower, ROUND_NOT_NEEDED);
3486  q.canonicalize();
3487  if (!included) {
3488  open_lower = true;
3489  }
3490  Relation_Symbol rel;
3491  if ((ub_var_coeff >= 0) ? !negative_denom : negative_denom) {
3492  rel = open_lower ? GREATER_THAN : GREATER_OR_EQUAL;
3493  }
3494  else {
3495  rel = open_lower ? LESS_THAN : LESS_OR_EQUAL;
3496  }
3497  seq_var.add_constraint(i_constraint(rel, q));
3498  if (seq_var.is_empty()) {
3499  set_empty();
3500  return;
3501  }
3502  }
3503  }
3504 
3505  if (!unbounded_upper) {
3506  // `ub_expr' is revised by removing the `var' component,
3507  // multiplying by `-' denominator of the upper bound for `var',
3508  // and adding the upper bound for `var' to the inhomogeneous term.
3509  Linear_Expression revised_ub_expr(lb_expr);
3510  revised_ub_expr -= lb_var_coeff * var;
3512  neg_assign(d, denom_upper);
3513  revised_ub_expr *= d;
3514  revised_ub_expr += numer_upper;
3515 
3516  // Find the maximum value for the revised upper bound expression
3517  // and use this to refine the appropriate bound.
3518  bool included;
3520  if (maximize(revised_ub_expr, numer_upper, denom, included)) {
3521  denom_upper *= (denom * lb_var_coeff);
3522  PPL_DIRTY_TEMP(mpq_class, q);
3523  assign_r(q.get_num(), numer_upper, ROUND_NOT_NEEDED);
3524  assign_r(q.get_den(), denom_upper, ROUND_NOT_NEEDED);
3525  q.canonicalize();
3526  if (!included) {
3527  open_upper = true;
3528  }
3529  Relation_Symbol rel;
3530  if ((lb_var_coeff >= 0) ? !negative_denom : negative_denom) {
3531  rel = open_upper ? LESS_THAN : LESS_OR_EQUAL;
3532  }
3533  else {
3534  rel = open_upper ? GREATER_THAN : GREATER_OR_EQUAL;
3535  }
3536  seq_var.add_constraint(i_constraint(rel, q));
3537  if (seq_var.is_empty()) {
3538  set_empty();
3539  return;
3540  }
3541  }
3542  }
3543  }
3544 
3545  // If the implied constraint between `ub_expr and `lb_expr' is
3546  // dependent on `var', then impose on the new box.
3547  if (lb_var_coeff != ub_var_coeff) {
3548  if (denominator > 0) {
3549  refine_with_constraint(lb_expr <= ub_expr);
3550  }
3551  else {
3552  refine_with_constraint(lb_expr >= ub_expr);
3553  }
3554  }
3555 
3556  PPL_ASSERT(OK());
3557 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
I_Constraint< T > i_constraint(I_Constraint_Rel rel, const T &v)
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
void refine_with_constraint(const Constraint &c)
Use the constraint c to refine *this.
Definition: Box_inlines.hh:459
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
Relation_Symbol
Relation symbols.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
static void throw_invalid_argument(const char *method, const char *reason)
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
#define PPL_DIRTY_TEMP(T, id)
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.
Definition: Box_inlines.hh:217
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.
Definition: Box_inlines.hh:201
void neg_assign(GMP_Integer &x)
bool OK() const
Returns true if and only if *this satisfies all its invariants.
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
void set_empty()
Causes the box to become empty, i.e., to represent the empty set.
Definition: Box_inlines.hh:44
template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::bounds ( const Linear_Expression expr,
bool  from_above 
) const
private

Checks if and how expr is bounded in *this.

Returns true if and only if from_above is true and expr is bounded from above in *this, or from_above is false and expr is bounded from below in *this.

Parameters
exprThe linear expression to test;
from_abovetrue if and only if the boundedness of interest is "from above".
Exceptions
std::invalid_argumentThrown if expr and *this are dimension-incompatible.

Definition at line 605 of file Box_templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::begin(), Parma_Polyhedra_Library::Linear_Expression::end(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Boundary_NS::sgn(), and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

605  {
606  // `expr' should be dimension-compatible with `*this'.
607  const dimension_type expr_space_dim = expr.space_dimension();
608  const dimension_type space_dim = space_dimension();
609  if (space_dim < expr_space_dim) {
610  throw_dimension_incompatible((from_above
611  ? "bounds_from_above(e)"
612  : "bounds_from_below(e)"), "e", expr);
613  }
614  // A zero-dimensional or empty Box bounds everything.
615  if (space_dim == 0 || is_empty()) {
616  return true;
617  }
618  const int from_above_sign = from_above ? 1 : -1;
619  // TODO: This loop can be optimized more, if needed, exploiting the
620  // (possible) sparseness of expr.
621  for (Linear_Expression::const_iterator i = expr.begin(),
622  i_end = expr.end(); i != i_end; ++i) {
623  const Variable v = i.variable();
624  switch (sgn(*i) * from_above_sign) {
625  case 1:
626  if (seq[v.id()].upper_is_boundary_infinity()) {
627  return false;
628  }
629  break;
630  case 0:
631  PPL_UNREACHABLE;
632  break;
633  case -1:
634  if (seq[v.id()].lower_is_boundary_infinity()) {
635  return false;
636  }
637  break;
638  }
639  }
640  return true;
641 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
int sgn(Boundary_Type type, const T &x, const Info &info)
template<typename ITV >
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.

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

Definition at line 189 of file Box_inlines.hh.

189  {
190  return bounds(expr, true);
191 }
bool bounds(const Linear_Expression &expr, bool from_above) const
Checks if and how expr is bounded in *this.
template<typename ITV >
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.

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

Definition at line 195 of file Box_inlines.hh.

195  {
196  return bounds(expr, false);
197 }
bool bounds(const Linear_Expression &expr, bool from_above) const
Checks if and how expr is bounded in *this.
template<typename T >
bool Parma_Polyhedra_Library::Box< T >::can_recycle_congruence_systems ( )
inlinestatic

Returns false indicating that this domain does not recycle congruences.

Definition at line 381 of file Box_inlines.hh.

381  {
382  return false;
383 }
template<typename T >
bool Parma_Polyhedra_Library::Box< T >::can_recycle_constraint_systems ( )
inlinestatic

Returns false indicating that this domain does not recycle constraints.

Definition at line 375 of file Box_inlines.hh.

375  {
376  return false;
377 }
template<typename ITV>
template<typename T >
Enable_If<Is_Same<T, Box>::value && Is_Same_Or_Derived<Interval_Base, ITV>::value, void>::type Parma_Polyhedra_Library::Box< ITV >::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.

Parameters
yA Box that must contain *this.
Exceptions
std::invalid_argumentThrown if *this and y are dimension-incompatible.
Note
As was the case for widening operators, the argument 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 $\mathtt{y} \Delta \mathtt{x}$.
template<typename ITV>
template<typename T >
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)

Definition at line 4203 of file Box_templates.hh.

4203  {
4204  const dimension_type space_dim = space_dimension();
4205 
4206  // Dimension-compatibility check.
4207  if (space_dim != y.space_dimension()) {
4208  throw_dimension_incompatible("CC76_narrowing_assign(y)", y);
4209  }
4210 
4211  // Assume `*this' is contained in or equal to `y'.
4212  PPL_EXPECT_HEAVY(copy_contains(y, *this));
4213 
4214  // If both boxes are zero-dimensional,
4215  // since `y' contains `*this', we simply return `*this'.
4216  if (space_dim == 0) {
4217  return;
4218  }
4219  // If `y' is empty, since `y' contains `this', `*this' is empty too.
4220  if (y.is_empty()) {
4221  return;
4222  }
4223  // If `*this' is empty, we return.
4224  if (is_empty()) {
4225  return;
4226  }
4227  // Replace each constraint in `*this' by the corresponding constraint
4228  // in `y' if the corresponding inhomogeneous terms are both finite.
4229  for (dimension_type i = space_dim; i-- > 0; ) {
4230  ITV& x_i = seq[i];
4231  const ITV& y_i = y.seq[i];
4232  if (!x_i.lower_is_boundary_infinity()
4233  && !y_i.lower_is_boundary_infinity()
4234  && x_i.lower() != y_i.lower()) {
4235  x_i.lower() = y_i.lower();
4236  }
4237  if (!x_i.upper_is_boundary_infinity()
4238  && !y_i.upper_is_boundary_infinity()
4239  && x_i.upper() != y_i.upper()) {
4240  x_i.upper() = y_i.upper();
4241  }
4242  }
4243  PPL_ASSERT(OK());
4244 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
bool OK() const
Returns true if and only if *this satisfies all its invariants.
template<typename ITV>
template<typename T >
Enable_If<Is_Same<T, Box>::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 
)

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

Parameters
yA box that must be contained in *this.
tpAn optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique).
Exceptions
std::invalid_argumentThrown if *this and y are dimension-incompatible.

Referenced by Parma_Polyhedra_Library::Polyhedron::bounded_BHRZ03_extrapolation_assign(), Parma_Polyhedra_Library::Polyhedron::bounded_H79_extrapolation_assign(), Parma_Polyhedra_Library::Box< ITV >::CC76_widening_assign(), and Parma_Polyhedra_Library::Box< ITV >::limited_CC76_extrapolation_assign().

template<typename ITV>
template<typename T , typename Iterator >
Enable_If<Is_Same<T, Box>::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 
)

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

Parameters
yA box that must be contained in *this.
firstAn iterator that points to the first stop-point.
lastAn iterator that points one past the last stop-point.
Exceptions
std::invalid_argumentThrown if *this and y are dimension-incompatible.
template<typename ITV>
template<typename T , typename Iterator >
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 
)

Definition at line 4080 of file Box_templates.hh.

4080  {
4081  if (y.is_empty()) {
4082  return;
4083  }
4084  for (dimension_type i = seq.size(); i-- > 0; ) {
4085  seq[i].CC76_widening_assign(y.seq[i], first, last);
4086  }
4087 
4088  PPL_ASSERT(OK());
4089 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
bool OK() const
Returns true if and only if *this satisfies all its invariants.
template<typename ITV>
template<typename T >
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 
)

Definition at line 4096 of file Box_templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::CC76_widening_assign(), and Parma_Polyhedra_Library::Box< ITV >::contains().

4096  {
4097  static typename ITV::boundary_type stop_points[] = {
4098  typename ITV::boundary_type(-2),
4099  typename ITV::boundary_type(-1),
4100  typename ITV::boundary_type(0),
4101  typename ITV::boundary_type(1),
4102  typename ITV::boundary_type(2)
4103  };
4104 
4105  Box& x = *this;
4106  // If there are tokens available, work on a temporary copy.
4107  if (tp != 0 && *tp > 0) {
4108  Box<ITV> x_tmp(x);
4109  x_tmp.CC76_widening_assign(y, 0);
4110  // If the widening was not precise, use one of the available tokens.
4111  if (!x.contains(x_tmp)) {
4112  --(*tp);
4113  }
4114  return;
4115  }
4116  x.CC76_widening_assign(y,
4117  stop_points,
4118  stop_points
4119  + sizeof(stop_points)/sizeof(stop_points[0]));
4120 }
Box(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty box of the specified space dimension.
template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::check_empty ( ) const
private

Checks the hard way whether *this is an empty box: returns true if and only if it is so.

Definition at line 1450 of file Box_templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::set_empty(), and Parma_Polyhedra_Library::Box< ITV >::set_nonempty().

Referenced by Parma_Polyhedra_Library::Box< ITV >::OK().

1450  {
1451  PPL_ASSERT(!marked_empty());
1452  Box<ITV>& x = const_cast<Box<ITV>&>(*this);
1453  for (dimension_type k = seq.size(); k-- > 0; ) {
1454  if (seq[k].is_empty()) {
1455  x.set_empty();
1456  return true;
1457  }
1458  }
1459  x.set_nonempty();
1460  return false;
1461 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::concatenate_assign ( const Box< ITV > &  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.

Let $B \sseq \Rset^n$ and $D \sseq \Rset^m$ be the boxes corresponding, on entry, to *this and y, respectively. Upon successful completion, *this will represent the box $R \sseq \Rset^{n+m}$ such that

\[ R \defeq \Bigl\{\, (x_1, \ldots, x_n, y_1, \ldots, y_m)^\transpose \Bigm| (x_1, \ldots, x_n)^\transpose \in B, (y_1, \ldots, y_m)^\transpose \in D \,\Bigl\}. \]

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 1964 of file Box_templates.hh.

References Parma_Polyhedra_Library::check_space_dimension_overflow(), Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::max_space_dimension(), 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 >::status, and Parma_Polyhedra_Library::Box< ITV >::Status::test_empty_up_to_date().

1964  {
1965  Box& x = *this;
1966  const dimension_type x_space_dim = x.space_dimension();
1967  const dimension_type y_space_dim = y.space_dimension();
1968 
1969  // If `y' is marked empty, the result will be empty too.
1970  if (y.marked_empty()) {
1971  x.set_empty();
1972  }
1973 
1974  // If `y' is a 0-dim space box, there is nothing left to do.
1975  if (y_space_dim == 0) {
1976  return;
1977  }
1978  // The resulting space dimension must be at most the maximum.
1979  check_space_dimension_overflow(y.space_dimension(),
1981  "PPL::Box::",
1982  "concatenate_assign(y)",
1983  "concatenation exceeds the maximum "
1984  "allowed space dimension");
1985  // Here `y_space_dim > 0', so that a non-trivial concatenation will occur:
1986  // make sure that reallocation will occur once at most.
1987  x.seq.reserve(x_space_dim + y_space_dim);
1988 
1989  // If `x' is marked empty, then it is sufficient to adjust
1990  // the dimension of the vector space.
1991  if (x.marked_empty()) {
1992  x.seq.insert(x.seq.end(), y_space_dim, ITV(EMPTY));
1993  PPL_ASSERT(x.OK());
1994  return;
1995  }
1996 
1997  // Here neither `x' nor `y' are marked empty: concatenate them.
1998  std::copy(y.seq.begin(), y.seq.end(),
1999  std::back_insert_iterator<Sequence>(x.seq));
2000  // Update the `empty_up_to_date' flag.
2001  if (!y.status.test_empty_up_to_date()) {
2003  }
2004 
2005  PPL_ASSERT(x.OK());
2006 }
The empty element, i.e., the empty set.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
Box(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty box of the specified space dimension.
dimension_type check_space_dimension_overflow(const dimension_type dim, const dimension_type max, const char *domain, const char *method, const char *reason)
Definition: globals.cc:48
void reset_empty_up_to_date()
Invalidates empty flag of *this.
Definition: Box_inlines.hh:64
static dimension_type max_space_dimension()
Returns the maximum space dimension that a Box can handle.
Definition: Box_inlines.hh:129
template<typename ITV >
Congruence_System Parma_Polyhedra_Library::Box< ITV >::congruences ( ) const

Returns a system of congruences approximating *this.

Definition at line 4344 of file Box_templates.hh.

References Parma_Polyhedra_Library::Congruence_System::insert(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Congruence_System::zero_dim_empty(), and Parma_Polyhedra_Library::Congruence::zero_dim_false().

4344  {
4345  const dimension_type space_dim = space_dimension();
4346  Congruence_System cgs(space_dim);
4347 
4348  if (space_dim == 0) {
4349  if (marked_empty()) {
4351  }
4352  return cgs;
4353  }
4354 
4355  // Make sure emptiness is detected.
4356  if (is_empty()) {
4357  cgs.insert(Congruence::zero_dim_false());
4358  return cgs;
4359  }
4360 
4361  for (dimension_type k = 0; k < space_dim; ++k) {
4362  const Variable v_k = Variable(k);
4365  bool closed = false;
4366  if (has_lower_bound(v_k, n, d, closed) && closed) {
4367  // Make sure equality congruences are detected.
4368  if (seq[k].is_singleton()) {
4369  cgs.insert((d * v_k %= n) / 0);
4370  }
4371  }
4372  }
4373  return cgs;
4374 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
static const Congruence_System & zero_dim_empty()
Returns the system containing only Congruence::zero_dim_false().
static const Congruence & zero_dim_false()
Returns a reference to the false (zero-dimension space) congruence .
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
bool has_lower_bound(Variable var, Coefficient &n, Coefficient &d, bool &closed) const
If the space dimension of var is unbounded below, return false. Otherwise return true and set n...
Definition: Box_inlines.hh:270
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::constrains ( Variable  var) const

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

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

Definition at line 1606 of file Box_templates.hh.

References Parma_Polyhedra_Library::Variable::space_dimension().

1606  {
1607  // `var' should be one of the dimensions of the polyhedron.
1608  const dimension_type var_space_dim = var.space_dimension();
1609  if (space_dimension() < var_space_dim) {
1610  throw_dimension_incompatible("constrains(v)", "v", var);
1611  }
1612 
1613  if (marked_empty() || !seq[var_space_dim-1].is_universe()) {
1614  return true;
1615  }
1616  // Now force an emptiness check.
1617  return is_empty();
1618 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
bool is_universe() const
Returns true if and only if *this is a universe box.
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
Constraint_System Parma_Polyhedra_Library::Box< ITV >::constraints ( ) const

Returns a system of constraints defining *this.

Definition at line 4248 of file Box_templates.hh.

References Parma_Polyhedra_Library::Constraint_System::insert(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Constraint_System::set_space_dimension(), Parma_Polyhedra_Library::Constraint_System::zero_dim_empty(), and Parma_Polyhedra_Library::Constraint::zero_dim_false().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::Polyhedron::bounded_BHRZ03_extrapolation_assign(), Parma_Polyhedra_Library::Polyhedron::bounded_H79_extrapolation_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape().

4248  {
4249  const dimension_type space_dim = space_dimension();
4250  Constraint_System cs;
4251  cs.set_space_dimension(space_dim);
4252 
4253  if (space_dim == 0) {
4254  if (marked_empty()) {
4256  }
4257  return cs;
4258  }
4259 
4260  if (marked_empty()) {
4261  cs.insert(Constraint::zero_dim_false());
4262  return cs;
4263  }
4264 
4265  for (dimension_type k = 0; k < space_dim; ++k) {
4266  const Variable v_k = Variable(k);
4269  bool closed = false;
4270  if (has_lower_bound(v_k, n, d, closed)) {
4271  if (closed) {
4272  cs.insert(d * v_k >= n);
4273  }
4274  else {
4275  cs.insert(d * v_k > n);
4276  }
4277  }
4278  if (has_upper_bound(v_k, n, d, closed)) {
4279  if (closed) {
4280  cs.insert(d * v_k <= n);
4281  }
4282  else {
4283  cs.insert(d * v_k < n);
4284  }
4285  }
4286  }
4287  return cs;
4288 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
static const Constraint_System & zero_dim_empty()
Returns the singleton system containing only Constraint::zero_dim_false().
static const Constraint & zero_dim_false()
The unsatisfiable (zero-dimension space) constraint .
bool has_upper_bound(Variable var, Coefficient &n, Coefficient &d, bool &closed) const
If the space dimension of var is unbounded above, return false. Otherwise return true and set n...
Definition: Box_inlines.hh:294
bool has_lower_bound(Variable var, Coefficient &n, Coefficient &d, bool &closed) const
If the space dimension of var is unbounded below, return false. Otherwise return true and set n...
Definition: Box_inlines.hh:270
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::contains ( const Box< ITV > &  y) const

Returns true if and only if *this contains y.

Exceptions
std::invalid_argumentThrown if x and y are dimension-incompatible.

Definition at line 1291 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_widening_assign(), and Parma_Polyhedra_Library::Box< ITV >::strictly_contains().

1291  {
1292  const Box& x = *this;
1293  // Dimension-compatibility check.
1294  if (x.space_dimension() != y.space_dimension()) {
1295  x.throw_dimension_incompatible("contains(y)", y);
1296  }
1297 
1298  // If `y' is empty, then `x' contains `y'.
1299  if (y.is_empty()) {
1300  return true;
1301  }
1302 
1303  // If `x' is empty, then `x' cannot contain `y'.
1304  if (x.is_empty()) {
1305  return false;
1306  }
1307 
1308  for (dimension_type k = x.seq.size(); k-- > 0; ) {
1309  // FIXME: fix this name qualification issue.
1310  if (!x.seq[k].contains(y.seq[k])) {
1311  return false;
1312  }
1313  }
1314  return true;
1315 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Box(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty box of the specified space dimension.
template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::contains_integer_point ( ) const

Returns true if and only if *this contains at least one integer point.

Definition at line 1522 of file Box_templates.hh.

1522  {
1523  if (marked_empty()) {
1524  return false;
1525  }
1526  for (dimension_type k = seq.size(); k-- > 0; ) {
1527  if (!seq[k].contains_integer_point()) {
1528  return false;
1529  }
1530  }
1531  return true;
1532 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool contains_integer_point() const
Returns true if and only if *this contains at least one integer point.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::difference_assign ( const Box< ITV > &  y)

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

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

Definition at line 2010 of file Box_templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), and Parma_Polyhedra_Library::Box< ITV >::space_dimension().

2010  {
2011  const dimension_type space_dim = space_dimension();
2012 
2013  // Dimension-compatibility check.
2014  if (space_dim != y.space_dimension()) {
2015  throw_dimension_incompatible("difference_assign(y)", y);
2016  }
2017 
2018  Box& x = *this;
2019  if (x.is_empty() || y.is_empty()) {
2020  return;
2021  }
2022  switch (space_dim) {
2023  case 0:
2024  // If `x' is zero-dimensional, then at this point both `x' and `y'
2025  // are the universe box, so that their difference is empty.
2026  x.set_empty();
2027  break;
2028 
2029  case 1:
2030  x.seq[0].difference_assign(y.seq[0]);
2031  if (x.seq[0].is_empty()) {
2032  x.set_empty();
2033  }
2034  break;
2035 
2036  default:
2037  {
2038  dimension_type index_non_contained = space_dim;
2039  dimension_type number_non_contained = 0;
2040  for (dimension_type i = space_dim; i-- > 0; ) {
2041  if (!y.seq[i].contains(x.seq[i])) {
2042  if (++number_non_contained == 1) {
2043  index_non_contained = i;
2044  }
2045  else {
2046  break;
2047  }
2048  }
2049  }
2050 
2051  switch (number_non_contained) {
2052  case 0:
2053  // `y' covers `x': the difference is empty.
2054  x.set_empty();
2055  break;
2056  case 1:
2057  x.seq[index_non_contained]
2058  .difference_assign(y.seq[index_non_contained]);
2059  if (x.seq[index_non_contained].is_empty()) {
2060  x.set_empty();
2061  }
2062  break;
2063  default:
2064  // Nothing to do: the difference is `x'.
2065  break;
2066  }
2067  }
2068  break;
2069  }
2070  PPL_ASSERT(OK());
2071 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
Box(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty box of the specified space dimension.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::drop_some_non_integer_points ( Complexity_Class  complexity = ANY_COMPLEXITY)

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

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

Definition at line 1855 of file Box_templates.hh.

References Parma_Polyhedra_Library::is_integer().

1855  {
1857  && !ITV::info_type::store_open) {
1858  return;
1859  }
1860 
1861  if (marked_empty()) {
1862  return;
1863  }
1864 
1865  for (dimension_type k = seq.size(); k-- > 0; ) {
1866  seq[k].drop_some_non_integer_points();
1867  }
1868 
1869  PPL_ASSERT(OK());
1870 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_integer(const T &x)
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
bool OK() const
Returns true if and only if *this satisfies all its invariants.
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::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.

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

Definition at line 1874 of file Box_templates.hh.

References Parma_Polyhedra_Library::is_integer(), and Parma_Polyhedra_Library::Variables_Set::space_dimension().

1875  {
1876  // Dimension-compatibility check.
1877  const dimension_type min_space_dim = vars.space_dimension();
1878  if (space_dimension() < min_space_dim) {
1879  throw_dimension_incompatible("drop_some_non_integer_points(vs, cmpl)",
1880  min_space_dim);
1881  }
1883  && !ITV::info_type::store_open) {
1884  return;
1885  }
1886 
1887  if (marked_empty()) {
1888  return;
1889  }
1890 
1891  for (Variables_Set::const_iterator v_i = vars.begin(),
1892  v_end = vars.end(); v_i != v_end; ++v_i) {
1893  seq[*v_i].drop_some_non_integer_points();
1894  }
1895 
1896  PPL_ASSERT(OK());
1897 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_integer(const T &x)
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
bool OK() const
Returns true if and only if *this satisfies all its invariants.
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
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.

Parameters
varThe variable corresponding to the space dimension to be replicated;
mThe number of replicas to be created.
Exceptions
std::invalid_argumentThrown if var does not correspond to a dimension of the vector space.
std::length_errorThrown if adding m new space dimensions would cause the vector space to exceed dimension max_space_dimension().

If *this has space dimension $n$, with $n > 0$, and var has space dimension $k \leq n$, then the $k$-th space dimension is expanded to m new space dimensions $n$, $n+1$, $\dots$, $n+m-1$.

Definition at line 240 of file Box_inlines.hh.

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

241  {
242  const dimension_type space_dim = space_dimension();
243  // `var' should be one of the dimensions of the vector space.
244  if (var.space_dimension() > space_dim) {
245  throw_dimension_incompatible("expand_space_dimension(v, m)", "v", var);
246  }
247 
248  // The space dimension of the resulting Box should not
249  // overflow the maximum allowed space dimension.
250  if (m > max_space_dimension() - space_dim) {
251  throw_invalid_argument("expand_dimension(v, m)",
252  "adding m new space dimensions exceeds "
253  "the maximum allowed space dimension");
254  }
255 
256  // To expand the space dimension corresponding to variable `var',
257  // we append to the box `m' copies of the corresponding interval.
258  seq.insert(seq.end(), m, seq[var.id()]);
259  PPL_ASSERT(OK());
260 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
static dimension_type max_space_dimension()
Returns the maximum space dimension that a Box can handle.
Definition: Box_inlines.hh:129
static void throw_invalid_argument(const char *method, const char *reason)
bool OK() const
Returns true if and only if *this satisfies all its invariants.
template<typename ITV >
memory_size_type Parma_Polyhedra_Library::Box< ITV >::external_memory_in_bytes ( ) const

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

Definition at line 4378 of file Box_templates.hh.

4378  {
4379  memory_size_type n = seq.capacity() * sizeof(ITV);
4380  for (dimension_type k = seq.size(); k-- > 0; ) {
4381  n += seq[k].external_memory_in_bytes();
4382  }
4383  return n;
4384 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
size_t memory_size_type
An unsigned integral type for representing memory size in bytes.
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::fold_space_dimensions ( const Variables_Set vars,
Variable  dest 
)

Folds the space dimensions in vars into dest.

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

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

Definition at line 2316 of file Box_templates.hh.

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

2317  {
2318  const dimension_type space_dim = space_dimension();
2319  // `dest' should be one of the dimensions of the box.
2320  if (dest.space_dimension() > space_dim) {
2321  throw_dimension_incompatible("fold_space_dimensions(vs, v)", "v", dest);
2322  }
2323 
2324  // The folding of no dimensions is a no-op.
2325  if (vars.empty()) {
2326  return;
2327  }
2328 
2329  // All variables in `vars' should be dimensions of the box.
2330  if (vars.space_dimension() > space_dim) {
2331  throw_dimension_incompatible("fold_space_dimensions(vs, v)",
2332  vars.space_dimension());
2333  }
2334  // Moreover, `dest.id()' should not occur in `vars'.
2335  if (vars.find(dest.id()) != vars.end()) {
2336  throw_invalid_argument("fold_space_dimensions(vs, v)",
2337  "v should not occur in vs");
2338  }
2339 
2340  // Note: the check for emptiness is needed for correctness.
2341  if (!is_empty()) {
2342  // Join the interval corresponding to variable `dest' with the intervals
2343  // corresponding to the variables in `vars'.
2344  ITV& seq_v = seq[dest.id()];
2345  for (Variables_Set::const_iterator i = vars.begin(),
2346  vs_end = vars.end(); i != vs_end; ++i) {
2347  seq_v.join_assign(seq[*i]);
2348  }
2349  }
2351 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
static void throw_invalid_argument(const char *method, const char *reason)
void remove_space_dimensions(const Variables_Set &vars)
Removes all the specified dimensions.
template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::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.

Parameters
exprThe linear expression for which the frequency is needed;
freq_nIf true is returned, the value is set to $0$; Present for interface compatibility with class Grid, where the frequency can have a non-zero value;
freq_dIf true is returned, the value is set to $1$;
val_nThe numerator of val;
val_dThe denominator of val;
Exceptions
std::invalid_argumentThrown 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 1536 of file Box_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::begin(), c, Parma_Polyhedra_Library::Linear_Expression::end(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::normalize2(), PPL_DIRTY_TEMP, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

1538  {
1539  dimension_type space_dim = space_dimension();
1540  // The dimension of `expr' must be at most the dimension of *this.
1541  if (space_dim < expr.space_dimension()) {
1542  throw_dimension_incompatible("frequency(e, ...)", "e", expr);
1543  }
1544 
1545  // Check if `expr' has a constant value.
1546  // If it is constant, set the frequency `freq_n' to 0
1547  // and return true. Otherwise the values for \p expr
1548  // are not discrete so return false.
1549 
1550  // Space dimension is 0: if empty, then return false;
1551  // otherwise the frequency is 0 and the value is the inhomogeneous term.
1552  if (space_dim == 0) {
1553  if (is_empty()) {
1554  return false;
1555  }
1556  freq_n = 0;
1557  freq_d = 1;
1558  val_n = expr.inhomogeneous_term();
1559  val_d = 1;
1560  return true;
1561  }
1562 
1563  // For an empty Box, we simply return false.
1564  if (is_empty()) {
1565  return false;
1566  }
1567 
1568  // The Box has at least 1 dimension and is not empty.
1571  PPL_DIRTY_TEMP(mpq_class, tmp);
1572  Coefficient c = expr.inhomogeneous_term();
1573 
1574  PPL_DIRTY_TEMP_COEFFICIENT(val_denom);
1575  val_denom = 1;
1576 
1577  for (Linear_Expression::const_iterator i = expr.begin(), i_end = expr.end();
1578  i != i_end; ++i) {
1579  const ITV& seq_i = seq[i.variable().id()];
1580  // Check if `v' is constant in the BD shape.
1581  if (seq_i.is_singleton()) {
1582  // If `v' is constant, replace it in `le' by the value.
1583  assign_r(tmp, seq_i.lower(), ROUND_NOT_NEEDED);
1584  numer = tmp.get_num();
1585  denom = tmp.get_den();
1586  c *= denom;
1587  c += numer * val_denom * (*i);
1588  val_denom *= denom;
1589  continue;
1590  }
1591  // The expression `expr' is not constant.
1592  return false;
1593  }
1594 
1595  // The expression `expr' is constant.
1596  freq_n = 0;
1597  freq_d = 1;
1598 
1599  // Reduce `val_n' and `val_d'.
1600  normalize2(c, val_denom, val_n, val_d);
1601  return true;
1602 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
#define PPL_DIRTY_TEMP(T, id)
void normalize2(Coefficient_traits::const_reference x, Coefficient_traits::const_reference y, Coefficient &n_x, Coefficient &n_y)
If is the GCD of x and y, the values of x and y divided by are assigned to n_x and n_y...
Coefficient c
Definition: PIP_Tree.cc:64
template<typename ITV >
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() 
)

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

Parameters
varThe left hand side variable of the generalized affine relation;
relsymThe relation symbol;
exprThe numerator of the right hand side affine expression;
denominatorThe denominator of the right hand side affine expression (optional argument with default value 1).
Exceptions
std::invalid_argumentThrown 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 3562 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().

3565  {
3566  // The denominator cannot be zero.
3567  if (denominator == 0) {
3568  throw_invalid_argument("generalized_affine_image(v, r, e, d)", "d == 0");
3569  }
3570 
3571  // Dimension-compatibility checks.
3572  const dimension_type space_dim = space_dimension();
3573  // The dimension of `expr' should not be greater than the dimension
3574  // of `*this'.
3575  if (space_dim < expr.space_dimension()) {
3576  throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
3577  "e", expr);
3578  }
3579  // `var' should be one of the dimensions of the box.
3580  const dimension_type var_space_dim = var.space_dimension();
3581  if (space_dim < var_space_dim) {
3582  throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
3583  "v", var);
3584  }
3585 
3586  // The relation symbol cannot be a disequality.
3587  if (relsym == NOT_EQUAL) {
3588  throw_invalid_argument("generalized_affine_image(v, r, e, d)",
3589  "r is the disequality relation symbol");
3590  }
3591 
3592  // First compute the affine image.
3593  affine_image(var, expr, denominator);
3594 
3595  if (relsym == EQUAL) {
3596  // The affine relation is indeed an affine function.
3597  return;
3598  }
3599  // Any image of an empty box is empty.
3600  if (is_empty()) {
3601  return;
3602  }
3603 
3604  ITV& seq_var = seq[var.id()];
3605  switch (relsym) {
3606  case LESS_OR_EQUAL:
3607  seq_var.lower_extend();
3608  break;
3609  case LESS_THAN:
3610  seq_var.lower_extend();
3611  if (!seq_var.upper_is_boundary_infinity()) {
3612  seq_var.remove_sup();
3613  }
3614  break;
3615  case GREATER_OR_EQUAL:
3616  seq_var.upper_extend();
3617  break;
3618  case GREATER_THAN:
3619  seq_var.upper_extend();
3620  if (!seq_var.lower_is_boundary_infinity()) {
3621  seq_var.remove_inf();
3622  }
3623  break;
3624  default:
3625  // The EQUAL and NOT_EQUAL cases have been already dealt with.
3626  PPL_UNREACHABLE;
3627  break;
3628  }
3629  PPL_ASSERT(OK());
3630 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
static void throw_invalid_argument(const char *method, const char *reason)
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 expr...
bool OK() const
Returns true if and only if *this satisfies all its invariants.
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::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 $\mathrm{lhs}' \relsym \mathrm{rhs}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym.

Parameters
lhsThe left hand side affine expression;
relsymThe relation symbol;
rhsThe right hand side affine expression.
Exceptions
std::invalid_argumentThrown if *this is dimension-incompatible with lhs or rhs.

Definition at line 3788 of file Box_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::Linear_Expression::first_nonzero(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::i_constraint(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Linear_Expression::last_nonzero(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::NOT_EQUAL, PPL_DIRTY_TEMP, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::I_Constraint< T, Val_Or_Ref_Criteria, extended >::set(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.

3790  {
3791  // Dimension-compatibility checks.
3792  // The dimension of `lhs' should not be greater than the dimension
3793  // of `*this'.
3794  dimension_type lhs_space_dim = lhs.space_dimension();
3795  const dimension_type space_dim = space_dimension();
3796  if (space_dim < lhs_space_dim) {
3797  throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
3798  "e1", lhs);
3799  }
3800  // The dimension of `rhs' should not be greater than the dimension
3801  // of `*this'.
3802  const dimension_type rhs_space_dim = rhs.space_dimension();
3803  if (space_dim < rhs_space_dim) {
3804  throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
3805  "e2", rhs);
3806  }
3807 
3808  // The relation symbol cannot be a disequality.
3809  if (relsym == NOT_EQUAL) {
3810  throw_invalid_argument("generalized_affine_image(e1, r, e2)",
3811  "r is the disequality relation symbol");
3812  }
3813 
3814  // Any image of an empty box is empty.
3815  if (marked_empty()) {
3816  return;
3817  }
3818 
3819  // Compute the maximum and minimum value reached by the rhs on the box.
3820  PPL_DIRTY_TEMP_COEFFICIENT(max_numer);
3821  PPL_DIRTY_TEMP_COEFFICIENT(max_denom);
3822  bool max_included;
3823  bool max_rhs = maximize(rhs, max_numer, max_denom, max_included);
3824  PPL_DIRTY_TEMP_COEFFICIENT(min_numer);
3825  PPL_DIRTY_TEMP_COEFFICIENT(min_denom);
3826  bool min_included;
3827  bool min_rhs = minimize(rhs, min_numer, min_denom, min_included);
3828 
3829  // Check whether there is 0, 1 or more than one variable in the lhs
3830  // and record the variable with the highest dimension; set the box
3831  // intervals to be unbounded for all other dimensions with non-zero
3832  // coefficients in the lhs.
3833  bool has_var = false;
3834  dimension_type has_var_id = lhs.last_nonzero();
3835 
3836  if (has_var_id != 0) {
3837  has_var = true;
3838  --has_var_id;
3839  dimension_type other_var = lhs.first_nonzero(1, has_var_id + 1);
3840  --other_var;
3841  if (other_var != has_var_id) {
3842  // There is more than one dimension with non-zero coefficient, so
3843  // we cannot have any information about the dimensions in the lhs.
3844  ITV& seq_var = seq[has_var_id];
3845  seq_var.assign(UNIVERSE);
3846  // Since all but the highest dimension with non-zero coefficient
3847  // in the lhs have been set unbounded, it remains to set the
3848  // highest dimension in the lhs unbounded.
3849  ITV& seq_i = seq[other_var];
3850  seq_i.assign(UNIVERSE);
3851  PPL_ASSERT(OK());
3852  return;
3853  }
3854  }
3855 
3856  if (has_var) {
3857  // There is exactly one dimension with non-zero coefficient.
3858  ITV& seq_var = seq[has_var_id];
3859 
3860  // Compute the new bounds for this dimension defined by the rhs
3861  // expression.
3862  const Coefficient& inhomo = lhs.inhomogeneous_term();
3863  const Coefficient& coeff = lhs.coefficient(Variable(has_var_id));
3864  PPL_DIRTY_TEMP(mpq_class, q_max);
3865  PPL_DIRTY_TEMP(mpq_class, q_min);
3866  if (max_rhs) {
3867  max_numer -= inhomo * max_denom;
3868  max_denom *= coeff;
3869  assign_r(q_max.get_num(), max_numer, ROUND_NOT_NEEDED);
3870  assign_r(q_max.get_den(), max_denom, ROUND_NOT_NEEDED);
3871  q_max.canonicalize();
3872  }
3873  if (min_rhs) {
3874  min_numer -= inhomo * min_denom;
3875  min_denom *= coeff;
3876  assign_r(q_min.get_num(), min_numer, ROUND_NOT_NEEDED);
3877  assign_r(q_min.get_den(), min_denom, ROUND_NOT_NEEDED);
3878  q_min.canonicalize();
3879  }
3880 
3881  // The choice as to which bounds should be set depends on the sign
3882  // of the coefficient of the dimension `has_var_id' in the lhs.
3883  if (coeff > 0) {
3884  // The coefficient of the dimension in the lhs is positive.
3885  switch (relsym) {
3886  case LESS_OR_EQUAL:
3887  if (max_rhs) {
3888  Relation_Symbol rel = max_included ? LESS_OR_EQUAL : LESS_THAN;
3889  seq_var.build(i_constraint(rel, q_max));
3890  }
3891  else {
3892  seq_var.assign(UNIVERSE);
3893  }
3894  break;
3895  case LESS_THAN:
3896  if (max_rhs) {
3897  seq_var.build(i_constraint(LESS_THAN, q_max));
3898  }
3899  else {
3900  seq_var.assign(UNIVERSE);
3901  }
3902  break;
3903  case EQUAL:
3904  {
3905  I_Constraint<mpq_class> l;
3906  I_Constraint<mpq_class> u;
3907  if (max_rhs) {
3908  u.set(max_included ? LESS_OR_EQUAL : LESS_THAN, q_max);
3909  }
3910  if (min_rhs) {
3911  l.set(min_included ? GREATER_OR_EQUAL : GREATER_THAN, q_min);
3912  }
3913  seq_var.build(l, u);
3914  break;
3915  }
3916  case GREATER_OR_EQUAL:
3917  if (min_rhs) {
3918  Relation_Symbol rel = min_included ? GREATER_OR_EQUAL : GREATER_THAN;
3919  seq_var.build(i_constraint(rel, q_min));
3920  }
3921  else {
3922  seq_var.assign(UNIVERSE);
3923  }
3924  break;
3925  case GREATER_THAN:
3926  if (min_rhs) {
3927  seq_var.build(i_constraint(GREATER_THAN, q_min));
3928  }
3929  else {
3930  seq_var.assign(UNIVERSE);
3931  }
3932  break;
3933  default:
3934  // The NOT_EQUAL case has been already dealt with.
3935  PPL_UNREACHABLE;
3936  break;
3937  }
3938  }
3939  else {
3940  // The coefficient of the dimension in the lhs is negative.
3941  switch (relsym) {
3942  case GREATER_OR_EQUAL:
3943  if (min_rhs) {
3944  Relation_Symbol rel = min_included ? LESS_OR_EQUAL : LESS_THAN;
3945  seq_var.build(i_constraint(rel, q_min));
3946  }
3947  else {
3948  seq_var.assign(UNIVERSE);
3949  }
3950  break;
3951  case GREATER_THAN:
3952  if (min_rhs) {
3953  seq_var.build(i_constraint(LESS_THAN, q_min));
3954  }
3955  else {
3956  seq_var.assign(UNIVERSE);
3957  }
3958  break;
3959  case EQUAL:
3960  {
3961  I_Constraint<mpq_class> l;
3962  I_Constraint<mpq_class> u;
3963  if (max_rhs) {
3964  l.set(max_included ? GREATER_OR_EQUAL : GREATER_THAN, q_max);
3965  }
3966  if (min_rhs) {
3967  u.set(min_included ? LESS_OR_EQUAL : LESS_THAN, q_min);
3968  }
3969  seq_var.build(l, u);
3970  break;
3971  }
3972  case LESS_OR_EQUAL:
3973  if (max_rhs) {
3974  Relation_Symbol rel = max_included ? GREATER_OR_EQUAL : GREATER_THAN;
3975  seq_var.build(i_constraint(rel, q_max));
3976  }
3977  else {
3978  seq_var.assign(UNIVERSE);
3979  }
3980  break;
3981  case LESS_THAN:
3982  if (max_rhs) {
3983  seq_var.build(i_constraint(GREATER_THAN, q_max));
3984  }
3985  else {
3986  seq_var.assign(UNIVERSE);
3987  }
3988  break;
3989  default:
3990  // The NOT_EQUAL case has been already dealt with.
3991  PPL_UNREACHABLE;
3992  break;
3993  }
3994  }
3995  }
3996 
3997  else {
3998  // The lhs is a constant value, so we just need to add the
3999  // appropriate constraint.
4000  const Coefficient& inhomo = lhs.inhomogeneous_term();
4001  switch (relsym) {
4002  case LESS_THAN:
4003  refine_with_constraint(inhomo < rhs);
4004  break;
4005  case LESS_OR_EQUAL:
4006  refine_with_constraint(inhomo <= rhs);
4007  break;
4008  case EQUAL:
4009  refine_with_constraint(inhomo == rhs);
4010  break;
4011  case GREATER_OR_EQUAL:
4012  refine_with_constraint(inhomo >= rhs);
4013  break;
4014  case GREATER_THAN:
4015  refine_with_constraint(inhomo > rhs);
4016  break;
4017  default:
4018  // The NOT_EQUAL case has been already dealt with.
4019  PPL_UNREACHABLE;
4020  break;
4021  }
4022  }
4023  PPL_ASSERT(OK());
4024 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
I_Constraint< T > i_constraint(I_Constraint_Rel rel, const T &v)
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
void refine_with_constraint(const Constraint &c)
Use the constraint c to refine *this.
Definition: Box_inlines.hh:459
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
Relation_Symbol
Relation symbols.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
static void throw_invalid_argument(const char *method, const char *reason)
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
#define PPL_DIRTY_TEMP(T, id)
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.
Definition: Box_inlines.hh:217
The universe element, i.e., the whole vector space.
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.
Definition: Box_inlines.hh:201
bool OK() const
Returns true if and only if *this satisfies all its invariants.
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
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() 
)

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

Parameters
varThe left hand side variable of the generalized affine relation;
relsymThe relation symbol;
exprThe numerator of the right hand side affine expression;
denominatorThe denominator of the right hand side affine expression (optional argument with default value 1).
Exceptions
std::invalid_argumentThrown 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 3635 of file Box_templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Coefficient_zero(), 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::Linear_Expression::set_inhomogeneous_term(), Parma_Polyhedra_Library::Boundary_NS::sgn(), Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.

3639 {
3640  // The denominator cannot be zero.
3641  if (denominator == 0) {
3642  throw_invalid_argument("generalized_affine_preimage(v, r, e, d)",
3643  "d == 0");
3644  }
3645  // Dimension-compatibility checks.
3646  const dimension_type space_dim = space_dimension();
3647  // The dimension of `expr' should not be greater than the dimension
3648  // of `*this'.
3649  if (space_dim < expr.space_dimension()) {
3650  throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
3651  "e", expr);
3652  }
3653  // `var' should be one of the dimensions of the box.
3654  const dimension_type var_space_dim = var.space_dimension();
3655  if (space_dim < var_space_dim) {
3656  throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
3657  "v", var);
3658  }
3659  // The relation symbol cannot be a disequality.
3660  if (relsym == NOT_EQUAL) {
3661  throw_invalid_argument("generalized_affine_preimage(v, r, e, d)",
3662  "r is the disequality relation symbol");
3663  }
3664 
3665  // Check whether the affine relation is indeed an affine function.
3666  if (relsym == EQUAL) {
3667  affine_preimage(var, expr, denominator);
3668  return;
3669  }
3670 
3671  // Compute the reversed relation symbol to simplify later coding.
3672  Relation_Symbol reversed_relsym;
3673  switch (relsym) {
3674  case LESS_THAN:
3675  reversed_relsym = GREATER_THAN;
3676  break;
3677  case LESS_OR_EQUAL:
3678  reversed_relsym = GREATER_OR_EQUAL;
3679  break;
3680  case GREATER_OR_EQUAL:
3681  reversed_relsym = LESS_OR_EQUAL;
3682  break;
3683  case GREATER_THAN:
3684  reversed_relsym = LESS_THAN;
3685  break;
3686  default:
3687  // The EQUAL and NOT_EQUAL cases have been already dealt with.
3688  PPL_UNREACHABLE;
3689  break;
3690  }
3691 
3692  // Check whether the preimage of this affine relation can be easily
3693  // computed as the image of its inverse relation.
3694  const Coefficient& var_coefficient = expr.coefficient(var);
3695  if (var_coefficient != 0) {
3696  Linear_Expression inverse_expr
3697  = expr - (denominator + var_coefficient) * var;
3698  PPL_DIRTY_TEMP_COEFFICIENT(inverse_denominator);
3699  neg_assign(inverse_denominator, var_coefficient);
3700  Relation_Symbol inverse_relsym
3701  = (sgn(denominator) == sgn(inverse_denominator))
3702  ? relsym
3703  : reversed_relsym;
3704  generalized_affine_image(var, inverse_relsym, inverse_expr,
3705  inverse_denominator);
3706  return;
3707  }
3708 
3709  // Here `var_coefficient == 0', so that the preimage cannot
3710  // be easily computed by inverting the affine relation.
3711  // Shrink the box by adding the constraint induced
3712  // by the affine relation.
3713  // First, compute the maximum and minimum value reached by
3714  // `denominator*var' on the box as we need to use non-relational
3715  // expressions.
3716  PPL_DIRTY_TEMP_COEFFICIENT(max_numer);
3717  PPL_DIRTY_TEMP_COEFFICIENT(max_denom);
3718  bool max_included;
3719  bool bound_above = maximize(denominator*var, max_numer, max_denom, max_included);
3720  PPL_DIRTY_TEMP_COEFFICIENT(min_numer);
3721  PPL_DIRTY_TEMP_COEFFICIENT(min_denom);
3722  bool min_included;
3723  bool bound_below = minimize(denominator*var, min_numer, min_denom, min_included);
3724  // Use the correct relation symbol
3725  const Relation_Symbol corrected_relsym
3726  = (denominator > 0) ? relsym : reversed_relsym;
3727  // Revise the expression to take into account the denominator of the
3728  // maximum/minimum value for `var'.
3729  Linear_Expression revised_expr;
3731  if (corrected_relsym == LESS_THAN || corrected_relsym == LESS_OR_EQUAL) {
3732  if (bound_below) {
3733  revised_expr = expr;
3734  revised_expr.set_inhomogeneous_term(Coefficient_zero());
3735  revised_expr *= d;
3736  }
3737  }
3738  else {
3739  if (bound_above) {
3740  revised_expr = expr;
3741  revised_expr.set_inhomogeneous_term(Coefficient_zero());
3742  revised_expr *= max_denom;
3743  }
3744  }
3745 
3746  switch (corrected_relsym) {
3747  case LESS_THAN:
3748  if (bound_below) {
3749  refine_with_constraint(min_numer < revised_expr);
3750  }
3751  break;
3752  case LESS_OR_EQUAL:
3753  if (bound_below) {
3754  (min_included)
3755  ? refine_with_constraint(min_numer <= revised_expr)
3756  : refine_with_constraint(min_numer < revised_expr);
3757  }
3758  break;
3759  case GREATER_OR_EQUAL:
3760  if (bound_above) {
3761  (max_included)
3762  ? refine_with_constraint(max_numer >= revised_expr)
3763  : refine_with_constraint(max_numer > revised_expr);
3764  }
3765  break;
3766  case GREATER_THAN:
3767  if (bound_above) {
3768  refine_with_constraint(max_numer > revised_expr);
3769  }
3770  break;
3771  default:
3772  // The EQUAL and NOT_EQUAL cases have been already dealt with.
3773  PPL_UNREACHABLE;
3774  break;
3775  }
3776  // If the shrunk box is empty, its preimage is empty too.
3777  if (is_empty()) {
3778  return;
3779  }
3780  ITV& seq_v = seq[var.id()];
3781  seq_v.assign(UNIVERSE);
3782  PPL_ASSERT(OK());
3783 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
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 ...
void refine_with_constraint(const Constraint &c)
Use the constraint c to refine *this.
Definition: Box_inlines.hh:459
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
Relation_Symbol
Relation symbols.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
static void throw_invalid_argument(const char *method, const char *reason)
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
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.
Definition: Box_inlines.hh:217
The universe element, i.e., the whole vector space.
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.
Definition: Box_inlines.hh:201
void neg_assign(GMP_Integer &x)
Coefficient_traits::const_reference Coefficient_zero()
Returns a const reference to a Coefficient with value 0.
int sgn(Boundary_Type type, const T &x, const Info &info)
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 e...
bool OK() const
Returns true if and only if *this satisfies all its invariants.
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::generalized_affine_preimage ( const Linear_Expression lhs,
Relation_Symbol  relsym,
const Linear_Expression rhs 
)

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

Parameters
lhsThe left hand side affine expression;
relsymThe relation symbol;
rhsThe right hand side affine expression.
Exceptions
std::invalid_argumentThrown if *this is dimension-incompatible with lhs or rhs.

Definition at line 4028 of file Box_templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::begin(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Linear_Expression::end(), Parma_Polyhedra_Library::NOT_EQUAL, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and Parma_Polyhedra_Library::sub_mul_assign().

4030  {
4031  // Dimension-compatibility checks.
4032  // The dimension of `lhs' should not be greater than the dimension
4033  // of `*this'.
4034  dimension_type lhs_space_dim = lhs.space_dimension();
4035  const dimension_type space_dim = space_dimension();
4036  if (space_dim < lhs_space_dim) {
4037  throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
4038  "e1", lhs);
4039  }
4040  // The dimension of `rhs' should not be greater than the dimension
4041  // of `*this'.
4042  const dimension_type rhs_space_dim = rhs.space_dimension();
4043  if (space_dim < rhs_space_dim) {
4044  throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
4045  "e2", rhs);
4046  }
4047 
4048  // The relation symbol cannot be a disequality.
4049  if (relsym == NOT_EQUAL) {
4050  throw_invalid_argument("generalized_affine_image(e1, r, e2)",
4051  "r is the disequality relation symbol");
4052  }
4053  // Any image of an empty box is empty.
4054  if (marked_empty()) {
4055  return;
4056  }
4057  // For any dimension occurring in the lhs, swap and change the sign
4058  // of this component for the rhs and lhs. Then use these in a call
4059  // to generalized_affine_image/3.
4060  Linear_Expression revised_lhs = lhs;
4061  Linear_Expression revised_rhs = rhs;
4062  for (Linear_Expression::const_iterator i = lhs.begin(),
4063  i_end = lhs.end(); i != i_end; ++i) {
4064  const Variable var = i.variable();
4066  tmp = *i;
4067  tmp += rhs.coefficient(var);
4068  sub_mul_assign(revised_rhs, tmp, var);
4069  sub_mul_assign(revised_lhs, tmp, var);
4070  }
4071  generalized_affine_image(revised_lhs, relsym, revised_rhs);
4072  PPL_ASSERT(OK());
4073 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
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 ...
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
static void throw_invalid_argument(const char *method, const char *reason)
void sub_mul_assign(GMP_Integer &x, const GMP_Integer &y, const GMP_Integer &z)
bool OK() const
Returns true if and only if *this satisfies all its invariants.
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
const ITV & Parma_Polyhedra_Library::Box< ITV >::get_interval ( Variable  var) const
inline

Returns a reference the interval that bounds var.

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

Definition at line 150 of file Box_inlines.hh.

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

Referenced by Parma_Polyhedra_Library::Floating_Point_Expression< FP_Interval_Type, FP_Format >::intervalize(), and Parma_Polyhedra_Library::Polyhedron::overapproximate_linear_form().

150  {
151  if (space_dimension() < var.space_dimension()) {
152  throw_dimension_incompatible("get_interval(v)", "v", var);
153  }
154  if (is_empty()) {
155  static ITV empty_interval(EMPTY);
156  return empty_interval;
157  }
158 
159  return seq[var.id()];
160 }
The empty element, i.e., the empty set.
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::get_limiting_box ( const Constraint_System cs,
Box< ITV > &  limiting_box 
) const
private

Adds to limiting_box the interval constraints in cs that are satisfied by *this.

Definition at line 4124 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_Helpers::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::Constraint_System::space_dimension(), and Parma_Polyhedra_Library::Constraint::type().

4125  {
4126  // Private method: the caller has to ensure the following.
4127  PPL_ASSERT(cs.space_dimension() <= space_dimension());
4128 
4129  for (Constraint_System::const_iterator cs_i = cs.begin(),
4130  cs_end = cs.end(); cs_i != cs_end; ++cs_i) {
4131  const Constraint& c = *cs_i;
4132  dimension_type c_num_vars = 0;
4133  dimension_type c_only_var = 0;
4134  // Constraints that are not interval constraints are ignored.
4135  if (!Box_Helpers::extract_interval_constraint(c, c_num_vars, c_only_var)) {
4136  continue;
4137  }
4138  // Trivial constraints are ignored.
4139  if (c_num_vars != 0) {
4140  // c is a non-trivial interval constraint.
4141  // add interval constraint to limiting box
4142  const Coefficient& n = c.inhomogeneous_term();
4143  const Coefficient& d = c.coefficient(Variable(c_only_var));
4144  if (interval_relation(seq[c_only_var], c.type(), n, d)
4146  limiting_box.add_interval_constraint_no_check(c_only_var, c.type(),
4147  n, d);
4148  }
4149  }
4150  }
4151 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
static Poly_Con_Relation is_included()
The polyhedron is included in the set of points satisfying the constraint.
static bool extract_interval_constraint(const Constraint &c, dimension_type &c_num_vars, dimension_type &c_only_var)
Decodes the constraint c as an interval constraint.
Definition: Box.cc:30
Poly_Con_Relation interval_relation(const ITV &i, const Constraint::Type constraint_type, Coefficient_traits::const_reference numer, Coefficient_traits::const_reference denom=Coefficient_one())
Returns the relations holding between an interval and an interval constraint.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
Coefficient c
Definition: PIP_Tree.cc:64
Constraint_System_const_iterator const_iterator
template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::has_lower_bound ( Variable  var,
Coefficient n,
Coefficient d,
bool &  closed 
) const
inline

If the space dimension of var is unbounded below, return false. Otherwise return true and set n, d and closed accordingly.

Note
It is assumed that *this is a non-empty box having space dimension greater than or equal to that of var. An undefined behavior is obtained if this assumption is not met. To be more precise, if *this is an empty box (having space dimension greater than or equal to that of var) such that !marked_empty() holds, then the method can be called without incurring in undefined behavior: it will return unspecified boundary values that, if queried systematically on all space dimensions, will encode the box emptiness.

Let $I$ be the interval corresponding to variable var in the non-empty box *this. If $I$ is not bounded from below, simply return false (leaving all other parameters unchanged). Otherwise, set n, d and closed as follows:

  • n and d are assigned the integers $n$ and $d$ such that the fraction $n/d$ corresponds to the greatest lower bound of $I$. The fraction $n/d$ is in canonical form, meaning that $n$ and $d$ have no common factors, $d$ is positive, and if $n$ is zero then $d$ is one;
  • closed is set to true if and only if the lower boundary of $I$ is closed (i.e., it is included in the interval).

Definition at line 270 of file Box_inlines.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Variable::id(), PPL_DIRTY_TEMP, and Parma_Polyhedra_Library::ROUND_NOT_NEEDED.

Referenced by Parma_Polyhedra_Library::Grid::Grid(), and Parma_Polyhedra_Library::Polyhedron::Polyhedron().

271  {
272  // NOTE: assertion !is_empty() would be wrong;
273  // see the calls in method Box<ITV>::constraints().
274  PPL_ASSERT(!marked_empty());
275  const dimension_type k = var.id();
276  PPL_ASSERT(k < seq.size());
277  const ITV& seq_k = seq[k];
278 
279  if (seq_k.lower_is_boundary_infinity()) {
280  return false;
281  }
282  closed = !seq_k.lower_is_open();
283 
284  PPL_DIRTY_TEMP(mpq_class, lr);
285  assign_r(lr, seq_k.lower(), ROUND_NOT_NEEDED);
286  n = lr.get_num();
287  d = lr.get_den();
288 
289  return true;
290 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
#define PPL_DIRTY_TEMP(T, id)
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::has_upper_bound ( Variable  var,
Coefficient n,
Coefficient d,
bool &  closed 
) const
inline

If the space dimension of var is unbounded above, return false. Otherwise return true and set n, d and closed accordingly.

Note
It is assumed that *this is a non-empty box having space dimension greater than or equal to that of var. An undefined behavior is obtained if this assumption is not met. To be more precise, if *this is an empty box (having space dimension greater than or equal to that of var) such that !marked_empty() holds, then the method can be called without incurring in undefined behavior: it will return unspecified boundary values that, if queried systematically on all space dimensions, will encode the box emptiness.

Let $I$ be the interval corresponding to variable var in the non-empty box *this. If $I$ is not bounded from above, simply return false (leaving all other parameters unchanged). Otherwise, set n, d and closed as follows:

  • n and d are assigned the integers $n$ and $d$ such that the fraction $n/d$ corresponds to the least upper bound of $I$. The fraction $n/d$ is in canonical form, meaning that $n$ and $d$ have no common factors, $d$ is positive, and if $n$ is zero then $d$ is one;
  • closed is set to true if and only if the upper boundary of $I$ is closed (i.e., it is included in the interval).

Definition at line 294 of file Box_inlines.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Variable::id(), PPL_DIRTY_TEMP, and Parma_Polyhedra_Library::ROUND_NOT_NEEDED.

Referenced by Parma_Polyhedra_Library::Grid::Grid(), and Parma_Polyhedra_Library::Polyhedron::Polyhedron().

295  {
296  // NOTE: assertion !is_empty() would be wrong;
297  // see the calls in method Box<ITV>::constraints().
298  PPL_ASSERT(!marked_empty());
299  const dimension_type k = var.id();
300  PPL_ASSERT(k < seq.size());
301  const ITV& seq_k = seq[k];
302 
303  if (seq_k.upper_is_boundary_infinity()) {
304  return false;
305  }
306 
307  closed = !seq_k.upper_is_open();
308 
309  PPL_DIRTY_TEMP(mpq_class, ur);
310  assign_r(ur, seq_k.upper(), ROUND_NOT_NEEDED);
311  n = ur.get_num();
312  d = ur.get_den();
313 
314  return true;
315 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
#define PPL_DIRTY_TEMP(T, id)
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
int32_t Parma_Polyhedra_Library::Box< ITV >::hash_code ( ) const
inline

Returns a 32-bit hash code for *this.

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

Definition at line 137 of file Box_inlines.hh.

References Parma_Polyhedra_Library::hash_code_from_dimension().

137  {
139 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
int32_t hash_code_from_dimension(dimension_type dim)
Returns the hash code for space dimension dim.
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::intersection_assign ( const Box< ITV > &  y)

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

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

Definition at line 1901 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(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

Referenced by Parma_Polyhedra_Library::Box< ITV >::Box().

1901  {
1902  Box& x = *this;
1903  const dimension_type space_dim = space_dimension();
1904 
1905  // Dimension-compatibility check.
1906  if (space_dim != y.space_dimension()) {
1907  x.throw_dimension_incompatible("intersection_assign(y)", y);
1908  }
1909 
1910  // If one of the two boxes is empty, the intersection is empty.
1911  if (x.marked_empty()) {
1912  return;
1913  }
1914  if (y.marked_empty()) {
1915  x.set_empty();
1916  return;
1917  }
1918 
1919  // If both boxes are zero-dimensional, then at this point they are
1920  // necessarily non-empty, so that their intersection is non-empty too.
1921  if (space_dim == 0) {
1922  return;
1923  }
1924 
1925  // FIXME: here we may conditionally exploit a capability of the
1926  // underlying interval to eagerly detect empty results.
1928 
1929  for (dimension_type k = space_dim; k-- > 0; ) {
1930  x.seq[k].intersect_assign(y.seq[k]);
1931  }
1932 
1933  PPL_ASSERT(x.OK());
1934 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
Box(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty box of the specified space dimension.
void reset_empty_up_to_date()
Invalidates empty flag of *this.
Definition: Box_inlines.hh:64
template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::is_bounded ( ) const

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

Definition at line 1508 of file Box_templates.hh.

1508  {
1509  if (is_empty()) {
1510  return true;
1511  }
1512  for (dimension_type k = seq.size(); k-- > 0; ) {
1513  if (!seq[k].is_bounded()) {
1514  return false;
1515  }
1516  }
1517  return true;
1518 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
bool is_bounded() const
Returns true if and only if *this is a bounded box.
template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::is_discrete ( ) const

Returns true if and only if *this is discrete.

Definition at line 1494 of file Box_templates.hh.

1494  {
1495  if (is_empty()) {
1496  return true;
1497  }
1498  for (dimension_type k = seq.size(); k-- > 0; ) {
1499  if (!seq[k].is_singleton()) {
1500  return false;
1501  }
1502  }
1503  return true;
1504 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::is_disjoint_from ( const Box< ITV > &  y) const

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

Exceptions
std::invalid_argumentThrown if x and y are dimension-incompatible.

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

1319  {
1320  const Box& x = *this;
1321  // Dimension-compatibility check.
1322  if (x.space_dimension() != y.space_dimension()) {
1323  x.throw_dimension_incompatible("is_disjoint_from(y)", y);
1324  }
1325 
1326  // If any of `x' or `y' is marked empty, then they are disjoint.
1327  // Note: no need to use `is_empty', as the following loop is anyway correct.
1328  if (x.marked_empty() || y.marked_empty()) {
1329  return true;
1330  }
1331 
1332  for (dimension_type k = x.seq.size(); k-- > 0; ) {
1333  // FIXME: fix this name qualification issue.
1334  if (x.seq[k].is_disjoint_from(y.seq[k])) {
1335  return true;
1336  }
1337  }
1338  return false;
1339 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Box(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty box of the specified space dimension.
template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::is_topologically_closed ( ) const

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

Definition at line 1479 of file Box_templates.hh.

1479  {
1480  if (ITV::is_always_topologically_closed() || is_empty()) {
1481  return true;
1482  }
1483 
1484  for (dimension_type k = seq.size(); k-- > 0; ) {
1485  if (!seq[k].is_topologically_closed()) {
1486  return false;
1487  }
1488  }
1489  return true;
1490 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool is_topologically_closed() const
Returns true if and only if *this is a topologically closed subset of the vector space.
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::is_universe ( ) const

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

Definition at line 1465 of file Box_templates.hh.

1465  {
1466  if (marked_empty()) {
1467  return false;
1468  }
1469  for (dimension_type k = seq.size(); k-- > 0; ) {
1470  if (!seq[k].is_universe()) {
1471  return false;
1472  }
1473  }
1474  return true;
1475 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
bool is_universe() const
Returns true if and only if *this is a universe box.
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::limited_CC76_extrapolation_assign ( const Box< ITV > &  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.

Parameters
yA box that must be contained in *this.
csThe system of constraints used to improve the widened box.
tpAn optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique).
Exceptions
std::invalid_argumentThrown if *this, y and cs are dimension-incompatible or if cs contains a strict inequality.

Definition at line 4155 of file Box_templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::CC76_widening_assign(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.

4157  {
4158  Box& x = *this;
4159  const dimension_type space_dim = x.space_dimension();
4160 
4161  // Dimension-compatibility check.
4162  if (space_dim != y.space_dimension()) {
4163  throw_dimension_incompatible("limited_CC76_extrapolation_assign(y, cs)",
4164  y);
4165  }
4166  // `cs' must be dimension-compatible with the two boxes.
4167  const dimension_type cs_space_dim = cs.space_dimension();
4168  if (space_dim < cs_space_dim) {
4169  throw_constraint_incompatible("limited_CC76_extrapolation_assign(y, cs)");
4170  }
4171  // The limited CC76-extrapolation between two boxes in a
4172  // zero-dimensional space is also a zero-dimensional box
4173  if (space_dim == 0) {
4174  return;
4175  }
4176  // Assume `y' is contained in or equal to `*this'.
4177  PPL_EXPECT_HEAVY(copy_contains(*this, y));
4178 
4179  // If `*this' is empty, since `*this' contains `y', `y' is empty too.
4180  if (marked_empty()) {
4181  return;
4182  }
4183  // If `y' is empty, we return.
4184  if (y.marked_empty()) {
4185  return;
4186  }
4187  // Build a limiting box using all the constraints in cs
4188  // that are satisfied by *this.
4189  Box limiting_box(space_dim, UNIVERSE);
4190  get_limiting_box(cs, limiting_box);
4191 
4192  x.CC76_widening_assign(y, tp);
4193 
4194  // Intersect the widened box with the limiting box.
4195  intersection_assign(limiting_box);
4196 }
void throw_dimension_incompatible(const char *method, const Box &y) const
size_t dimension_type
An unsigned integral type for representing space dimensions.
Box(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty box of the specified space dimension.
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.
void intersection_assign(const Box &y)
Assigns to *this the intersection of *this and y.
static void throw_constraint_incompatible(const char *method)
The universe element, i.e., the whole vector space.
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::m_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, Parma_Polyhedra_Library::Box< ITV >::status, and Parma_Polyhedra_Library::swap().

Referenced by Parma_Polyhedra_Library::Box< ITV >::Box(), and Parma_Polyhedra_Library::Box< ITV >::swap().

84  {
85  Box& x = *this;
86  using std::swap;
87  swap(x.seq, y.seq);
88  swap(x.status, y.status);
89 }
void swap(CO_Tree &x, CO_Tree &y)
Box(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty box of the specified space dimension.
void swap(Box< ITV > &x, Box< ITV > &y)
Swaps x with y.
template<typename ITV >
template<typename Partial_Function >
void Parma_Polyhedra_Library::Box< ITV >::map_space_dimensions ( const Partial_Function pfunc)

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

Parameters
pfuncThe 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 $f$ be the represented function and $k$ be the value of i. If $f$ is defined in $k$, then $f(k)$ is assigned to j and true is returned. If $f$ is undefined in $k$, then false is returned.

The result is undefined if pfunc does not encode a partial function with the properties described in the specification of the mapping operator.

Definition at line 2282 of file Box_templates.hh.

References Parma_Polyhedra_Library::Partial_Function::has_empty_codomain(), Parma_Polyhedra_Library::Partial_Function::maps(), Parma_Polyhedra_Library::Partial_Function::max_in_codomain(), Parma_Polyhedra_Library::Box< ITV >::seq, and Parma_Polyhedra_Library::swap().

2282  {
2283  const dimension_type space_dim = space_dimension();
2284  if (space_dim == 0) {
2285  return;
2286  }
2287 
2288  if (pfunc.has_empty_codomain()) {
2289  // All dimensions vanish: the box becomes zero_dimensional.
2291  return;
2292  }
2293 
2294  const dimension_type new_space_dim = pfunc.max_in_codomain() + 1;
2295  // If the box is empty, then simply adjust the space dimension.
2296  if (is_empty()) {
2297  remove_higher_space_dimensions(new_space_dim);
2298  return;
2299  }
2300 
2301  // We create a new Box with the new space dimension.
2302  Box<ITV> tmp(new_space_dim);
2303  // Map the intervals, exchanging the indexes.
2304  for (dimension_type i = 0; i < space_dim; ++i) {
2305  dimension_type new_i;
2306  if (pfunc.maps(i, new_i)) {
2307  swap(seq[i], tmp.seq[new_i]);
2308  }
2309  }
2310  m_swap(tmp);
2311  PPL_ASSERT(OK());
2312 }
void m_swap(Box &y)
Swaps *this with y (*this and y can be dimension-incompatible).
Definition: Box_inlines.hh:84
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
void remove_higher_space_dimensions(dimension_type new_dimension)
Removes the higher dimensions so that the resulting space will have dimension new_dimension.
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
void swap(Box< ITV > &x, Box< ITV > &y)
Swaps x with y.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
bool OK() const
Returns true if and only if *this satisfies all its invariants.
template<typename ITV >
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
private

Maximizes or minimizes expr subject to *this.

Parameters
exprThe linear expression to be maximized or minimized subject to *this;
maximizetrue if maximization is what is wanted;
ext_nThe numerator of the extremum value;
ext_dThe denominator of the extremum value;
includedtrue if and only if the extremum of expr can actually be reached in *this;
gWhen maximization or minimization succeeds, will be assigned a point or closure point where expr reaches the corresponding extremum value.
Exceptions
std::invalid_argumentThrown 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 1200 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(), PPL_DIRTY_TEMP, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, and Parma_Polyhedra_Library::Boundary_NS::sgn().

1204  {
1205  if (!max_min(expr, maximize, ext_n, ext_d, included)) {
1206  return false;
1207  }
1208  // Compute generator `g'.
1209  Linear_Expression g_expr;
1210  PPL_DIRTY_TEMP_COEFFICIENT(g_divisor);
1211  g_divisor = 1;
1212  const int maximize_sign = maximize ? 1 : -1;
1213  PPL_DIRTY_TEMP(mpq_class, g_coord);
1218  // TODO: Check if the following loop can be optimized to exploit the
1219  // (possible) sparseness of expr.
1220  for (dimension_type i = space_dimension(); i-- > 0; ) {
1221  const ITV& seq_i = seq[i];
1222  switch (sgn(expr.coefficient(Variable(i))) * maximize_sign) {
1223  case 1:
1224  assign_r(g_coord, seq_i.upper(), ROUND_NOT_NEEDED);
1225  break;
1226  case 0:
1227  // If 0 belongs to the interval, choose it
1228  // (and directly proceed to the next iteration).
1229  // FIXME: name qualification issue.
1230  if (seq_i.contains(0)) {
1231  continue;
1232  }
1233  if (!seq_i.lower_is_boundary_infinity()) {
1234  if (seq_i.lower_is_open()) {
1235  if (!seq_i.upper_is_boundary_infinity()) {
1236  if (seq_i.upper_is_open()) {
1237  // Bounded and open interval: compute middle point.
1238  assign_r(g_coord, seq_i.lower(), ROUND_NOT_NEEDED);
1239  PPL_DIRTY_TEMP(mpq_class, q_seq_i_upper);
1240  assign_r(q_seq_i_upper, seq_i.upper(), ROUND_NOT_NEEDED);
1241  g_coord += q_seq_i_upper;
1242  g_coord /= 2;
1243  }
1244  else {
1245  // The upper bound is in the interval.
1246  assign_r(g_coord, seq_i.upper(), ROUND_NOT_NEEDED);
1247  }
1248  }
1249  else {
1250  // Lower is open, upper is unbounded.
1251  assign_r(g_coord, seq_i.lower(), ROUND_NOT_NEEDED);
1252  ++g_coord;
1253  }
1254  }
1255  else {
1256  // The lower bound is in the interval.
1257  assign_r(g_coord, seq_i.lower(), ROUND_NOT_NEEDED);
1258  }
1259  }
1260  else {
1261  // Lower is unbounded, hence upper is bounded
1262  // (since we know that 0 does not belong to the interval).
1263  PPL_ASSERT(!seq_i.upper_is_boundary_infinity());
1264  assign_r(g_coord, seq_i.upper(), ROUND_NOT_NEEDED);
1265  if (seq_i.upper_is_open()) {
1266  --g_coord;
1267  }
1268  }
1269  break;
1270  case -1:
1271  assign_r(g_coord, seq_i.lower(), ROUND_NOT_NEEDED);
1272  break;
1273  }
1274  // Add g_coord * Variable(i) to the generator.
1275  assign_r(denom, g_coord.get_den(), ROUND_NOT_NEEDED);
1276  lcm_assign(lcm, g_divisor, denom);
1277  exact_div_assign(factor, lcm, g_divisor);
1278  g_expr *= factor;
1279  exact_div_assign(factor, lcm, denom);
1280  assign_r(numer, g_coord.get_num(), ROUND_NOT_NEEDED);
1281  numer *= factor;
1282  g_expr += numer * Variable(i);
1283  g_divisor = lcm;
1284  }
1285  g = Generator::point(g_expr, g_divisor);
1286  return true;
1287 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
void lcm_assign(GMP_Integer &x, const GMP_Integer &y, const GMP_Integer &z)
void exact_div_assign(Checked_Number< T, Policy > &x, const Checked_Number< T, Policy > &y, const Checked_Number< T, Policy > &z)
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
#define PPL_DIRTY_TEMP(T, id)
static Generator point(const Linear_Expression &e=Linear_Expression::zero(), Coefficient_traits::const_reference d=Coefficient_one(), Representation r=default_representation)
Returns the point at e / d.
Definition: Generator.cc:57
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.
Definition: Box_inlines.hh:201
int sgn(Boundary_Type type, const T &x, const Info &info)
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.
template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::max_min ( const Linear_Expression expr,
bool  maximize,
Coefficient ext_n,
Coefficient ext_d,
bool &  included 
) const
private

Maximizes or minimizes expr subject to *this.

Parameters
exprThe linear expression to be maximized or minimized subject to *this;
maximizetrue if maximization is what is wanted;
ext_nThe numerator of the extremum value;
ext_dThe denominator of the extremum value;
includedtrue if and only if the extremum of expr can actually be reached in * this;
Exceptions
std::invalid_argumentThrown 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 1123 of file Box_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::begin(), Parma_Polyhedra_Library::Linear_Expression::end(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_canonical(), PPL_DIRTY_TEMP, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::Boundary_NS::sgn(), and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

1126  {
1127  // `expr' should be dimension-compatible with `*this'.
1128  const dimension_type space_dim = space_dimension();
1129  const dimension_type expr_space_dim = expr.space_dimension();
1130  if (space_dim < expr_space_dim) {
1132  ? "maximize(e, ...)"
1133  : "minimize(e, ...)"), "e", expr);
1134  }
1135 
1136  // Deal with zero-dim Box first.
1137  if (space_dim == 0) {
1138  if (marked_empty()) {
1139  return false;
1140  }
1141  else {
1142  ext_n = expr.inhomogeneous_term();
1143  ext_d = 1;
1144  included = true;
1145  return true;
1146  }
1147  }
1148 
1149  // For an empty Box we simply return false.
1150  if (is_empty()) {
1151  return false;
1152  }
1153 
1154  PPL_DIRTY_TEMP(mpq_class, result);
1155  assign_r(result, expr.inhomogeneous_term(), ROUND_NOT_NEEDED);
1156  bool is_included = true;
1157  const int maximize_sign = maximize ? 1 : -1;
1158  PPL_DIRTY_TEMP(mpq_class, bound_i);
1159  PPL_DIRTY_TEMP(mpq_class, expr_i);
1160  for (Linear_Expression::const_iterator i = expr.begin(),
1161  i_end = expr.end(); i != i_end; ++i) {
1162  const ITV& seq_i = seq[i.variable().id()];
1163  assign_r(expr_i, *i, ROUND_NOT_NEEDED);
1164  switch (sgn(expr_i) * maximize_sign) {
1165  case 1:
1166  if (seq_i.upper_is_boundary_infinity()) {
1167  return false;
1168  }
1169  assign_r(bound_i, seq_i.upper(), ROUND_NOT_NEEDED);
1170  add_mul_assign_r(result, bound_i, expr_i, ROUND_NOT_NEEDED);
1171  if (seq_i.upper_is_open()) {
1172  is_included = false;
1173  }
1174  break;
1175  case 0:
1176  PPL_UNREACHABLE;
1177  break;
1178  case -1:
1179  if (seq_i.lower_is_boundary_infinity()) {
1180  return false;
1181  }
1182  assign_r(bound_i, seq_i.lower(), ROUND_NOT_NEEDED);
1183  add_mul_assign_r(result, bound_i, expr_i, ROUND_NOT_NEEDED);
1184  if (seq_i.lower_is_open()) {
1185  is_included = false;
1186  }
1187  break;
1188  }
1189  }
1190  // Extract output info.
1191  PPL_ASSERT(is_canonical(result));
1192  ext_n = result.get_num();
1193  ext_d = result.get_den();
1194  included = is_included;
1195  return true;
1196 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
bool is_canonical(const mpq_class &x)
Returns true if and only if x is in canonical form.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
#define PPL_DIRTY_TEMP(T, id)
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.
Definition: Box_inlines.hh:201
int sgn(Boundary_Type type, const T &x, const Info &info)
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
dimension_type Parma_Polyhedra_Library::Box< ITV >::max_space_dimension ( )
inlinestatic

Returns the maximum space dimension that a Box can handle.

Definition at line 129 of file Box_inlines.hh.

Referenced by Parma_Polyhedra_Library::Box< ITV >::Box(), and Parma_Polyhedra_Library::max_space_dimension().

129  {
130  // One dimension is reserved to have a value of type dimension_type
131  // that does not represent a legal dimension.
132  return Sequence().max_size() - 1;
133 }
std::vector< ITV > Sequence
The type of sequence used to implement the box.
Definition: Box_defs.hh:1756
template<typename ITV >
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.

Parameters
exprThe linear expression to be maximized subject to *this;
sup_nThe numerator of the supremum value;
sup_dThe denominator of the supremum value;
maximumtrue if and only if the supremum is also the maximum value.
Exceptions
std::invalid_argumentThrown 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 201 of file Box_inlines.hh.

203  {
204  return max_min(expr, true, sup_n, sup_d, maximum);
205 }
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.
template<typename ITV >
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.

Parameters
exprThe linear expression to be maximized subject to *this;
sup_nThe numerator of the supremum value;
sup_dThe denominator of the supremum value;
maximumtrue if and only if the supremum is also the maximum value;
gWhen maximization succeeds, will be assigned the point or closure point where expr reaches its supremum value.
Exceptions
std::invalid_argumentThrown 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 209 of file Box_inlines.hh.

211  {
212  return max_min(expr, true, sup_n, sup_d, maximum, g);
213 }
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.
template<typename ITV >
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.

Parameters
exprThe linear expression to be minimized subject to *this;
inf_nThe numerator of the infimum value;
inf_dThe denominator of the infimum value;
minimumtrue if and only if the infimum is also the minimum value.
Exceptions
std::invalid_argumentThrown 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 217 of file Box_inlines.hh.

219  {
220  return max_min(expr, false, inf_n, inf_d, minimum);
221 }
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.
template<typename ITV >
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.

Parameters
exprThe linear expression to be minimized subject to *this;
inf_nThe numerator of the infimum value;
inf_dThe denominator of the infimum value;
minimumtrue if and only if the infimum is also the minimum value;
gWhen minimization succeeds, will be assigned a point or closure point where expr reaches its infimum value.
Exceptions
std::invalid_argumentThrown 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 225 of file Box_inlines.hh.

227  {
228  return max_min(expr, false, inf_n, inf_d, minimum, g);
229 }
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.
template<typename ITV >
Congruence_System Parma_Polyhedra_Library::Box< ITV >::minimized_congruences ( ) const
inline

Returns a minimized system of congruences approximating *this.

Definition at line 393 of file Box_inlines.hh.

393  {
394  // Only equalities can be congruences and these are already minimized.
395  return congruences();
396 }
Congruence_System congruences() const
Returns a system of congruences approximating *this.
template<typename ITV >
Constraint_System Parma_Polyhedra_Library::Box< ITV >::minimized_constraints ( ) const

Returns a minimized system of constraints defining *this.

Definition at line 4292 of file Box_templates.hh.

References Parma_Polyhedra_Library::Constraint_System::insert(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Constraint_System::set_space_dimension(), Parma_Polyhedra_Library::Constraint_System::zero_dim_empty(), and Parma_Polyhedra_Library::Constraint::zero_dim_false().

4292  {
4293  const dimension_type space_dim = space_dimension();
4294  Constraint_System cs;
4295  cs.set_space_dimension(space_dim);
4296 
4297  if (space_dim == 0) {
4298  if (marked_empty()) {
4300  }
4301  return cs;
4302  }
4303 
4304  // Make sure emptiness is detected.
4305  if (is_empty()) {
4306  cs.insert(Constraint::zero_dim_false());
4307  return cs;
4308  }
4309 
4310  for (dimension_type k = 0; k < space_dim; ++k) {
4311  const Variable v_k = Variable(k);
4314  bool closed = false;
4315  if (has_lower_bound(v_k, n, d, closed)) {
4316  if (closed) {
4317  // Make sure equality constraints are detected.
4318  if (seq[k].is_singleton()) {
4319  cs.insert(d * v_k == n);
4320  continue;
4321  }
4322  else {
4323  cs.insert(d * v_k >= n);
4324  }
4325  }
4326  else {
4327  cs.insert(d * v_k > n);
4328  }
4329  }
4330  if (has_upper_bound(v_k, n, d, closed)) {
4331  if (closed) {
4332  cs.insert(d * v_k <= n);
4333  }
4334  else {
4335  cs.insert(d * v_k < n);
4336  }
4337  }
4338  }
4339  return cs;
4340 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
static const Constraint_System & zero_dim_empty()
Returns the singleton system containing only Constraint::zero_dim_false().
static const Constraint & zero_dim_false()
The unsatisfiable (zero-dimension space) constraint .
bool has_upper_bound(Variable var, Coefficient &n, Coefficient &d, bool &closed) const
If the space dimension of var is unbounded above, return false. Otherwise return true and set n...
Definition: Box_inlines.hh:294
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
bool has_lower_bound(Variable var, Coefficient &n, Coefficient &d, bool &closed) const
If the space dimension of var is unbounded below, return false. Otherwise return true and set n...
Definition: Box_inlines.hh:270
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::OK ( ) const

Returns true if and only if *this satisfies all its invariants.

Definition at line 1400 of file Box_templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::check_empty(), and Parma_Polyhedra_Library::Box< ITV >::reset_empty_up_to_date().

Referenced by Parma_Polyhedra_Library::Box< ITV >::Status::ascii_load(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Box< ITV >::concatenate_assign(), Parma_Polyhedra_Library::Box< ITV >::intersection_assign(), Parma_Polyhedra_Library::Box< ITV >::simplify_using_context_assign(), Parma_Polyhedra_Library::Box< ITV >::time_elapse_assign(), Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign(), and Parma_Polyhedra_Library::Box< ITV >::wrap_assign().

1400  {
1402  Box tmp = *this;
1403  tmp.reset_empty_up_to_date();
1404  if (tmp.check_empty()) {
1405 #ifndef NDEBUG
1406  std::cerr << "The box is empty, but it is marked as non-empty."
1407  << std::endl;
1408 #endif // NDEBUG
1409  return false;
1410  }
1411  }
1412 
1413  // A box that is not marked empty must have meaningful intervals.
1414  if (!marked_empty()) {
1415  for (dimension_type k = seq.size(); k-- > 0; ) {
1416  if (!seq[k].OK()) {
1417  return false;
1418  }
1419  }
1420  }
1421 
1422  return true;
1423 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Box(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty box of the specified space dimension.
Status status
The status flags to keep track of the internal state.
Definition: Box_defs.hh:1772
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
bool OK() const
Returns true if and only if *this satisfies all its invariants.
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
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.

76  {
77  seq = y.seq;
78  status = y.status;
79  return *this;
80 }
Status status
The status flags to keep track of the internal state.
Definition: Box_defs.hh:1772
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
template<typename ITV >
const ITV & Parma_Polyhedra_Library::Box< ITV >::operator[] ( dimension_type  k) const
inlineprivate

Returns a reference the interval that bounds the box on the k-th space dimension.

Definition at line 143 of file Box_inlines.hh.

143  {
144  PPL_ASSERT(k < seq.size());
145  return seq[k];
146 }
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
template<typename ITV>
void Parma_Polyhedra_Library::Box< ITV >::print ( ) const

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

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::propagate_constraint ( const Constraint c)
inline

Use the constraint c for constraint propagation on *this.

Parameters
cThe constraint to be used for constraint propagation.
Exceptions
std::invalid_argumentThrown if *this and c are dimension-incompatible.

Definition at line 522 of file Box_inlines.hh.

References Parma_Polyhedra_Library::Constraint::space_dimension().

522  {
523  const dimension_type c_space_dim = c.space_dimension();
524  // Dimension-compatibility check.
525  if (c_space_dim > space_dimension()) {
526  throw_dimension_incompatible("propagate_constraint(c)", c);
527  }
528 
529  // If the box is already empty, there is nothing left to do.
530  if (marked_empty()) {
531  return;
532  }
534 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
void propagate_constraint_no_check(const Constraint &c)
Propagates the constraint c to refine *this.
Coefficient c
Definition: PIP_Tree.cc:64
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::propagate_constraint_no_check ( const Constraint c)
private

Propagates the constraint c to refine *this.

Parameters
cThe constraint to be propagated.
Warning
If c and *this are dimension-incompatible, the behavior is undefined.
This method may lead to non-termination.

For any expression $e$, we denote by $\left\uparrow e \right\uparrow$ (resp., $\left\downarrow e \right\downarrow$) the result of any computation that is guaranteed to yield an upper (resp., lower) approximation of $e$. So there exists $\epsilon \in \Rset$ with $\epsilon \geq 0$ such that $\left\uparrow e \right\uparrow = e + \epsilon$. If $\epsilon = 0$ we say that the computation of $\left\uparrow e \right\uparrow$ is exact; we say it is inexact otherwise. Similarly for $\left\downarrow e \right\downarrow$.

Consider a constraint of the general form

\[ z + \sum_{i \in I}{a_ix_i} \relsym 0, \]

where $z \in \Zset$, $I$ is a set of indices, $a_i \in \Zset$ with $a_i \neq 0$ for each $i \in I$, and $\mathord{\relsym} \in \{ \mathord{\geq}, \mathord{>}, \mathord{=} \}$. The set $I$ is subdivided into the disjoint sets $P$ and $N$ such that, for each $i \in I$, $a_i > 0$ if $i \in P$ and $a_i < 0$ if $i \in N$. Suppose that, for each $i \in P \union N$ a variation interval $\chi_i \sseq \Rset$ is known for $x_i$ and that the infimum and the supremum of $\chi_i$ are denoted, respectively, by $\chi_i^\mathrm{l}$ and $\chi_i^\mathrm{u}$, where $\chi_i^\mathrm{l}, \chi_i^\mathrm{u} \in \Rset \union \{ -\infty, +\infty \}$.

For each $k \in P$, we have

\[ x_k \relsym \frac{1}{a_k} \Biggl( - z - \sum_{i \in N}{a_ix_i} - \sum_{\genfrac{}{}{0pt}{} {\scriptstyle i \in P} {\scriptstyle i \neq k}}{a_ix_i} \Biggr). \]

Thus, if $\chi_i^\mathrm{l} \in \Rset$ for each $i \in N$ and $\chi_i^\mathrm{u} \in \Rset$ for each $i \in P \setdiff \{ k \}$, we have

\[ x_k \geq \Biggl\downarrow \frac{1}{a_k} \Biggl( - z - \sum_{i \in N}{a_i\chi_i^\mathrm{l}} - \sum_{\genfrac{}{}{0pt}{} {\scriptstyle i \in P} {\scriptstyle i \neq k}}{a_i\chi_i^\mathrm{u}} \Biggr) \Biggr\downarrow \]

and, if $\mathord{\relsym} \in \{ \mathord{=} \}$, $\chi_i^\mathrm{u} \in \Rset$ for each $i \in N$ and $\chi_i^\mathrm{l} \in \Rset$ for each $P \setdiff \{ k \}$,

\[ x_k \leq \Biggl\uparrow \frac{1}{a_k} \Biggl( - z - \sum_{i \in N}{a_i\chi_i^\mathrm{u}} - \sum_{\genfrac{}{}{0pt}{} {\scriptstyle i \in P} {\scriptstyle i \neq k}}{a_i\chi_i^\mathrm{l}} \Biggr) \Biggl\uparrow. \]

In the first inequality, the relation is strict if $\mathord{\relsym} \in \{ \mathord{>} \}$, or if $\chi_i^\mathrm{l} \notin \chi_i$ for some $i \in N$, or if $\chi_i^\mathrm{u} \notin \chi_i$ for some $i \in P \setdiff \{ k \}$, or if the computation is inexact. In the second inequality, the relation is strict if $\chi_i^\mathrm{u} \notin \chi_i$ for some $i \in N$, or if $\chi_i^\mathrm{l} \notin \chi_i$ for some $i \in P \setdiff \{ k \}$, or if the computation is inexact.

For each $k \in N$, we have

\[ \frac{1}{a_k} \Biggl( - z - \sum_{\genfrac{}{}{0pt}{} {\scriptstyle i \in N} {\scriptstyle i \neq k}}{a_ix_i} - \sum_{i \in P}{a_ix_i} \Biggr) \relsym x_k. \]

Thus, if $\chi_i^\mathrm{l} \in \Rset$ for each $i \in N \setdiff \{ k \}$ and $\chi_i^\mathrm{u} \in \Rset$ for each $i \in P$, we have

\[ \Biggl\uparrow \frac{1}{a_k} \Biggl( - z - \sum_{\genfrac{}{}{0pt}{} {\scriptstyle i \in N} {\scriptstyle i \neq k}}{a_i\chi_i^\mathrm{l}} - \sum_{i \in P}{a_i\chi_i^\mathrm{u}} \Biggr) \Biggl\uparrow \geq x_k \]

and, if $\mathord{\relsym} \in \{ \mathord{=} \}$, $\chi_i^\mathrm{u} \in \Rset$ for each $i \in N \setdiff \{ k \}$ and $\chi_i^\mathrm{l} \in \Rset$ for each $i \in P$,

\[ \Biggl\downarrow \frac{1}{a_k} \Biggl( - z - \sum_{\genfrac{}{}{0pt}{} {\scriptstyle i \in N} {\scriptstyle i \neq k}}{a_i\chi_i^\mathrm{u}} - \sum_{i \in P}{a_i\chi_i^\mathrm{l}} \Biggr) \Biggl\downarrow \leq x_k. \]

In the first inequality, the relation is strict if $\mathord{\relsym} \in \{ \mathord{>} \}$, or if $\chi_i^\mathrm{u} \notin \chi_i$ for some $i \in P$, or if $\chi_i^\mathrm{l} \notin \chi_i$ for some $i \in N \setdiff \{ k \}$, or if the computation is inexact. In the second inequality, the relation is strict if $\chi_i^\mathrm{l} \notin \chi_i$ for some $i \in P$, or if $\chi_i^\mathrm{u} \notin \chi_i$ for some $i \in N \setdiff \{ k \}$, or if the computation is inexact.

Definition at line 2581 of file Box_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Expression_Adapter< T >::begin(), Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::Constraint::expression(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::i_constraint(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Expression_Hide_Last< T >::last_nonzero(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::Expression_Hide_Last< T >::lower_bound(), Parma_Polyhedra_Library::Constraint::NONSTRICT_INEQUALITY, Parma_Polyhedra_Library::Implementation::Boxes::propagate_constraint_check_result(), Parma_Polyhedra_Library::ROUND_DOWN, Parma_Polyhedra_Library::ROUND_UP, Parma_Polyhedra_Library::Boundary_NS::sgn(), 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().

2581  {
2582  using namespace Implementation::Boxes;
2583 
2584  PPL_ASSERT(c.space_dimension() <= space_dimension());
2585 
2586  typedef
2587  typename Select_Temp_Boundary_Type<typename ITV::boundary_type>::type
2588  Temp_Boundary_Type;
2589 
2590  const dimension_type c_space_dim = c.space_dimension();
2591  const Constraint::Type c_type = c.type();
2592  const Coefficient& c_inhomogeneous_term = c.inhomogeneous_term();
2593 
2594  // Find a space dimension having a non-zero coefficient (if any).
2595  const dimension_type last_k
2596  = c.expression().last_nonzero(1, c_space_dim + 1);
2597  if (last_k == c_space_dim + 1) {
2598  // Constraint c is trivial: check if it is inconsistent.
2599  if (c_inhomogeneous_term < 0
2600  || (c_inhomogeneous_term == 0
2601  && c_type != Constraint::NONSTRICT_INEQUALITY)) {
2602  set_empty();
2603  }
2604  return;
2605  }
2606 
2607  // Here constraint c is non-trivial.
2608  PPL_ASSERT(last_k <= c_space_dim);
2609  Temp_Boundary_Type t_bound;
2610  Temp_Boundary_Type t_a;
2611  Temp_Boundary_Type t_x;
2612  Ternary open;
2613  const Constraint::expr_type c_e = c.expression();
2614  for (Constraint::expr_type::const_iterator k = c_e.begin(),
2615  k_end = c_e.lower_bound(Variable(last_k)); k != k_end; ++k) {
2616  const Coefficient& a_k = *k;
2617  const Variable k_var = k.variable();
2618  const int sgn_a_k = sgn(a_k);
2619  if (sgn_a_k == 0) {
2620  continue;
2621  }
2622  Result r;
2623  if (sgn_a_k > 0) {
2624  open = (c_type == Constraint::STRICT_INEQUALITY) ? T_YES : T_NO;
2625  if (open == T_NO) {
2626  maybe_reset_fpu_inexact<Temp_Boundary_Type>();
2627  }
2628  r = assign_r(t_bound, c_inhomogeneous_term, ROUND_UP);
2629  if (propagate_constraint_check_result(r, open)) {
2630  goto maybe_refine_upper_1;
2631  }
2632  r = neg_assign_r(t_bound, t_bound, ROUND_DOWN);
2633  if (propagate_constraint_check_result(r, open)) {
2634  goto maybe_refine_upper_1;
2635  }
2636  for (Constraint::expr_type::const_iterator i = c_e.begin(),
2637  i_end = c_e.lower_bound(Variable(last_k)); i != i_end; ++i) {
2638  const Variable i_var = i.variable();
2639  if (i_var.id() == k_var.id()) {
2640  continue;
2641  }
2642  const Coefficient& a_i = *i;
2643  const int sgn_a_i = sgn(a_i);
2644  ITV& x_i = seq[i_var.id()];
2645  if (sgn_a_i < 0) {
2646  if (x_i.lower_is_boundary_infinity()) {
2647  goto maybe_refine_upper_1;
2648  }
2649  r = assign_r(t_a, a_i, ROUND_DOWN);
2650  if (propagate_constraint_check_result(r, open)) {
2651  goto maybe_refine_upper_1;
2652  }
2653  r = assign_r(t_x, x_i.lower(), ROUND_DOWN);
2654  if (propagate_constraint_check_result(r, open)) {
2655  goto maybe_refine_upper_1;
2656  }
2657  if (x_i.lower_is_open()) {
2658  open = T_YES;
2659  }
2660  r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_DOWN);
2661  if (propagate_constraint_check_result(r, open)) {
2662  goto maybe_refine_upper_1;
2663  }
2664  }
2665  else {
2666  PPL_ASSERT(sgn_a_i > 0);
2667  if (x_i.upper_is_boundary_infinity()) {
2668  goto maybe_refine_upper_1;
2669  }
2670  r = assign_r(t_a, a_i, ROUND_UP);
2671  if (propagate_constraint_check_result(r, open)) {
2672  goto maybe_refine_upper_1;
2673  }
2674  r = assign_r(t_x, x_i.upper(), ROUND_UP);
2675  if (propagate_constraint_check_result(r, open)) {
2676  goto maybe_refine_upper_1;
2677  }
2678  if (x_i.upper_is_open()) {
2679  open = T_YES;
2680  }
2681  r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_DOWN);
2682  if (propagate_constraint_check_result(r, open)) {
2683  goto maybe_refine_upper_1;
2684  }
2685  }
2686  }
2687  r = assign_r(t_a, a_k, ROUND_UP);
2688  if (propagate_constraint_check_result(r, open)) {
2689  goto maybe_refine_upper_1;
2690  }
2691  r = div_assign_r(t_bound, t_bound, t_a, ROUND_DOWN);
2692  if (propagate_constraint_check_result(r, open)) {
2693  goto maybe_refine_upper_1;
2694  }
2695 
2696  // Refine the lower bound of `seq[k]' with `t_bound'.
2697  if (open == T_MAYBE
2698  && maybe_check_fpu_inexact<Temp_Boundary_Type>() == 1) {
2699  open = T_YES;
2700  }
2701  {
2702  const Relation_Symbol rel
2703  = (open == T_YES) ? GREATER_THAN : GREATER_OR_EQUAL;
2704  seq[k_var.id()].add_constraint(i_constraint(rel, t_bound));
2705  }
2707  maybe_refine_upper_1:
2708  if (c_type != Constraint::EQUALITY) {
2709  continue;
2710  }
2711  open = T_NO;
2712  maybe_reset_fpu_inexact<Temp_Boundary_Type>();
2713  r = assign_r(t_bound, c_inhomogeneous_term, ROUND_DOWN);
2714  if (propagate_constraint_check_result(r, open)) {
2715  goto next_k;
2716  }
2717  r = neg_assign_r(t_bound, t_bound, ROUND_UP);
2718  if (propagate_constraint_check_result(r, open)) {
2719  goto next_k;
2720  }
2721  for (Constraint::expr_type::const_iterator i = c_e.begin(),
2722  i_end = c_e.lower_bound(Variable(c_space_dim)); i != i_end; ++i) {
2723  const Variable i_var = i.variable();
2724  if (i_var.id() == k_var.id()) {
2725  continue;
2726  }
2727  const Coefficient& a_i = *i;
2728  const int sgn_a_i = sgn(a_i);
2729  ITV& x_i = seq[i_var.id()];
2730  if (sgn_a_i < 0) {
2731  if (x_i.upper_is_boundary_infinity()) {
2732  goto next_k;
2733  }
2734  r = assign_r(t_a, a_i, ROUND_UP);
2735  if (propagate_constraint_check_result(r, open)) {
2736  goto next_k;
2737  }
2738  r = assign_r(t_x, x_i.upper(), ROUND_UP);
2739  if (propagate_constraint_check_result(r, open)) {
2740  goto next_k;
2741  }
2742  if (x_i.upper_is_open()) {
2743  open = T_YES;
2744  }
2745  r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_UP);
2746  if (propagate_constraint_check_result(r, open)) {
2747  goto next_k;
2748  }
2749  }
2750  else {
2751  PPL_ASSERT(sgn_a_i > 0);
2752  if (x_i.lower_is_boundary_infinity()) {
2753  goto next_k;
2754  }
2755  r = assign_r(t_a, a_i, ROUND_DOWN);
2756  if (propagate_constraint_check_result(r, open)) {
2757  goto next_k;
2758  }
2759  r = assign_r(t_x, x_i.lower(), ROUND_DOWN);
2760  if (propagate_constraint_check_result(r, open)) {
2761  goto next_k;
2762  }
2763  if (x_i.lower_is_open()) {
2764  open = T_YES;
2765  }
2766  r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_UP);
2767  if (propagate_constraint_check_result(r, open)) {
2768  goto next_k;
2769  }
2770  }
2771  }
2772  r = assign_r(t_a, a_k, ROUND_DOWN);
2773  if (propagate_constraint_check_result(r, open)) {
2774  goto next_k;
2775  }
2776  r = div_assign_r(t_bound, t_bound, t_a, ROUND_UP);
2777  if (propagate_constraint_check_result(r, open)) {
2778  goto next_k;
2779  }
2780 
2781  // Refine the upper bound of seq[k] with t_bound.
2782  if (open == T_MAYBE
2783  && maybe_check_fpu_inexact<Temp_Boundary_Type>() == 1) {
2784  open = T_YES;
2785  }
2786  const Relation_Symbol rel
2787  = (open == T_YES) ? LESS_THAN : LESS_OR_EQUAL;
2788  seq[k_var.id()].add_constraint(i_constraint(rel, t_bound));
2790  }
2791  else {
2792  PPL_ASSERT(sgn_a_k < 0);
2793  open = (c_type == Constraint::STRICT_INEQUALITY) ? T_YES : T_NO;
2794  if (open == T_NO) {
2795  maybe_reset_fpu_inexact<Temp_Boundary_Type>();
2796  }
2797  r = assign_r(t_bound, c_inhomogeneous_term, ROUND_UP);
2798  if (propagate_constraint_check_result(r, open)) {
2799  goto maybe_refine_upper_2;
2800  }
2801  r = neg_assign_r(t_bound, t_bound, ROUND_DOWN);
2802  if (propagate_constraint_check_result(r, open)) {
2803  goto maybe_refine_upper_2;
2804  }
2805  for (Constraint::expr_type::const_iterator i = c_e.begin(),
2806  i_end = c_e.lower_bound(Variable(c_space_dim)); i != i_end; ++i) {
2807  const Variable i_var = i.variable();
2808  if (i_var.id() == k_var.id()) {
2809  continue;
2810  }
2811  const Coefficient& a_i = *i;
2812  const int sgn_a_i = sgn(a_i);
2813  ITV& x_i = seq[i_var.id()];
2814  if (sgn_a_i < 0) {
2815  if (x_i.lower_is_boundary_infinity()) {
2816  goto maybe_refine_upper_2;
2817  }
2818  r = assign_r(t_a, a_i, ROUND_DOWN);
2819  if (propagate_constraint_check_result(r, open)) {
2820  goto maybe_refine_upper_2;
2821  }
2822  r = assign_r(t_x, x_i.lower(), ROUND_DOWN);
2823  if (propagate_constraint_check_result(r, open)) {
2824  goto maybe_refine_upper_2;
2825  }
2826  if (x_i.lower_is_open()) {
2827  open = T_YES;
2828  }
2829  r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_UP);
2830  if (propagate_constraint_check_result(r, open)) {
2831  goto maybe_refine_upper_2;
2832  }
2833  }
2834  else {
2835  PPL_ASSERT(sgn_a_i > 0);
2836  if (x_i.upper_is_boundary_infinity()) {
2837  goto maybe_refine_upper_2;
2838  }
2839  r = assign_r(t_a, a_i, ROUND_UP);
2840  if (propagate_constraint_check_result(r, open)) {
2841  goto maybe_refine_upper_2;
2842  }
2843  r = assign_r(t_x, x_i.upper(), ROUND_UP);
2844  if (propagate_constraint_check_result(r, open)) {
2845  goto maybe_refine_upper_2;
2846  }
2847  if (x_i.upper_is_open()) {
2848  open = T_YES;
2849  }
2850  r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_DOWN);
2851  if (propagate_constraint_check_result(r, open)) {
2852  goto maybe_refine_upper_2;
2853  }
2854  }
2855  }
2856  r = assign_r(t_a, a_k, ROUND_UP);
2857  if (propagate_constraint_check_result(r, open)) {
2858  goto maybe_refine_upper_2;
2859  }
2860  r = div_assign_r(t_bound, t_bound, t_a, ROUND_UP);
2861  if (propagate_constraint_check_result(r, open)) {
2862  goto maybe_refine_upper_2;
2863  }
2864  // Refine the upper bound of seq[k] with t_bound.
2865  if (open == T_MAYBE
2866  && maybe_check_fpu_inexact<Temp_Boundary_Type>() == 1) {
2867  open = T_YES;
2868  }
2869  {
2870  const Relation_Symbol rel
2871  = (open == T_YES) ? LESS_THAN : LESS_OR_EQUAL;
2872  seq[k_var.id()].add_constraint(i_constraint(rel, t_bound));
2873  }
2875  maybe_refine_upper_2:
2876  if (c_type != Constraint::EQUALITY) {
2877  continue;
2878  }
2879  open = T_NO;
2880  maybe_reset_fpu_inexact<Temp_Boundary_Type>();
2881  r = assign_r(t_bound, c_inhomogeneous_term, ROUND_DOWN);
2882  if (propagate_constraint_check_result(r, open)) {
2883  goto next_k;
2884  }
2885  r = neg_assign_r(t_bound, t_bound, ROUND_UP);
2886  if (propagate_constraint_check_result(r, open)) {
2887  goto next_k;
2888  }
2889  for (Constraint::expr_type::const_iterator i = c_e.begin(),
2890  i_end = c_e.lower_bound(Variable(c_space_dim)); i != i_end; ++i) {
2891  const Variable i_var = i.variable();
2892  if (i_var.id() == k_var.id()) {
2893  continue;
2894  }
2895  const Coefficient& a_i = *i;
2896  const int sgn_a_i = sgn(a_i);
2897  ITV& x_i = seq[i_var.id()];
2898  if (sgn_a_i < 0) {
2899  if (x_i.upper_is_boundary_infinity()) {
2900  goto next_k;
2901  }
2902  r = assign_r(t_a, a_i, ROUND_UP);
2903  if (propagate_constraint_check_result(r, open)) {
2904  goto next_k;
2905  }
2906  r = assign_r(t_x, x_i.upper(), ROUND_UP);
2907  if (propagate_constraint_check_result(r, open)) {
2908  goto next_k;
2909  }
2910  if (x_i.upper_is_open()) {
2911  open = T_YES;
2912  }
2913  r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_UP);
2914  if (propagate_constraint_check_result(r, open)) {
2915  goto next_k;
2916  }
2917  }
2918  else {
2919  PPL_ASSERT(sgn_a_i > 0);
2920  if (x_i.lower_is_boundary_infinity()) {
2921  goto next_k;
2922  }
2923  r = assign_r(t_a, a_i, ROUND_DOWN);
2924  if (propagate_constraint_check_result(r, open)) {
2925  goto next_k;
2926  }
2927  r = assign_r(t_x, x_i.lower(), ROUND_DOWN);
2928  if (propagate_constraint_check_result(r, open)) {
2929  goto next_k;
2930  }
2931  if (x_i.lower_is_open()) {
2932  open = T_YES;
2933  }
2934  r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_UP);
2935  if (propagate_constraint_check_result(r, open)) {
2936  goto next_k;
2937  }
2938  }
2939  }
2940  r = assign_r(t_a, a_k, ROUND_DOWN);
2941  if (propagate_constraint_check_result(r, open)) {
2942  goto next_k;
2943  }
2944  r = div_assign_r(t_bound, t_bound, t_a, ROUND_DOWN);
2945  if (propagate_constraint_check_result(r, open)) {
2946  goto next_k;
2947  }
2948 
2949  // Refine the lower bound of seq[k] with t_bound.
2950  if (open == T_MAYBE
2951  && maybe_check_fpu_inexact<Temp_Boundary_Type>() == 1) {
2952  open = T_YES;
2953  }
2954  const Relation_Symbol rel
2955  = (open == T_YES) ? GREATER_THAN : GREATER_OR_EQUAL;
2956  seq[k_var.id()].add_constraint(i_constraint(rel, t_bound));
2958  }
2959  next_k:
2960  ;
2961  }
2962 }
Expression_Hide_Last< Linear_Expression > expr_type
The type of the (adapted) internal expression.
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
I_Constraint< T > i_constraint(I_Constraint_Rel rel, const T &v)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
Result
Possible outcomes of a checked arithmetic computation.
Definition: Result_defs.hh:76
Relation_Symbol
Relation symbols.
void reset_empty_up_to_date()
Invalidates empty flag of *this.
Definition: Box_inlines.hh:64
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
bool propagate_constraint_check_result(Result r, Ternary &open)
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
base_type::const_iterator const_iterator
The type of const iterators on coefficients.
int sgn(Boundary_Type type, const T &x, const Info &info)
Coefficient c
Definition: PIP_Tree.cc:64
void set_empty()
Causes the box to become empty, i.e., to represent the empty set.
Definition: Box_inlines.hh:44
template<typename ITV >
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 propagation on *this.

Parameters
csThe constraints to be used for constraint propagation.
max_iterationsThe maximum number of propagation steps for each constraint in cs. If zero (the default), the number of propagation steps will be unbounded, possibly resulting in an infinite loop.
Exceptions
std::invalid_argumentThrown if *this and cs are dimension-incompatible.
Warning
This method may lead to non-termination if max_iterations is 0.

Definition at line 538 of file Box_inlines.hh.

References Parma_Polyhedra_Library::Constraint_System::space_dimension().

539  {
540  // Dimension-compatibility check.
541  if (cs.space_dimension() > space_dimension()) {
542  throw_dimension_incompatible("propagate_constraints(cs)", cs);
543  }
544 
545  // If the box is already empty, there is nothing left to do.
546  if (marked_empty()) {
547  return;
548  }
549 
550  propagate_constraints_no_check(cs, max_iterations);
551 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
void propagate_constraints_no_check(const Constraint_System &cs, dimension_type max_iterations)
Propagates the constraints in cs to refine *this.
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::propagate_constraints_no_check ( const Constraint_System cs,
dimension_type  max_iterations 
)
private

Propagates the constraints in cs to refine *this.

Parameters
csThe constraints to be propagated.
max_iterationsThe maximum number of propagation steps for each constraint in cs. If zero, the number of propagation steps will be unbounded, possibly resulting in an infinite loop.
Warning
If cs and *this are dimension-incompatible, the behavior is undefined.
This method may lead to non-termination if max_iterations is 0.

Definition at line 3030 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::Implementation::num_constraints(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), WEIGHT_ADD_MUL, and WEIGHT_BEGIN.

Referenced by Parma_Polyhedra_Library::Box< ITV >::Box().

3031  {
3032  const dimension_type space_dim = space_dimension();
3033  PPL_ASSERT(cs.space_dimension() <= space_dim);
3034 
3035  const Constraint_System::const_iterator cs_begin = cs.begin();
3036  const Constraint_System::const_iterator cs_end = cs.end();
3037  const dimension_type propagation_weight
3038  = Implementation::num_constraints(cs) * space_dim;
3039 
3040  Sequence copy;
3041  bool changed;
3042  dimension_type num_iterations = 0;
3043  do {
3044  WEIGHT_BEGIN();
3045  ++num_iterations;
3046  copy = seq;
3047  for (Constraint_System::const_iterator i = cs_begin; i != cs_end; ++i) {
3049  }
3050 
3051  WEIGHT_ADD_MUL(40, propagation_weight);
3052  // Check if the client has requested abandoning all expensive
3053  // computations. If so, the exception specified by the client
3054  // is thrown now.
3055  maybe_abandon();
3056 
3057  // NOTE: if max_iterations == 0 (i.e., no iteration limit is set)
3058  // the following test will anyway trigger on wrap around.
3059  if (num_iterations == max_iterations) {
3060  break;
3061  }
3062 
3063  changed = (copy != seq);
3064  } while (changed);
3065 }
std::vector< ITV > Sequence
The type of sequence used to implement the box.
Definition: Box_defs.hh:1756
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
dimension_type num_constraints(const Constraint_System &cs)
Helper returning number of constraints in system.
void propagate_constraint_no_check(const Constraint &c)
Propagates the constraint c to refine *this.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
#define WEIGHT_ADD_MUL(delta, factor)
Definition: globals_defs.hh:90
#define WEIGHT_BEGIN()
Definition: globals_defs.hh:81
Constraint_System_const_iterator const_iterator
template<typename ITV >
I_Result Parma_Polyhedra_Library::Box< ITV >::refine_interval_no_check ( ITV &  itv,
Constraint::Type  type,
Coefficient_traits::const_reference  numer,
Coefficient_traits::const_reference  denom 
)
inlinestaticprivate

WRITE ME.

Definition at line 401 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::I_ANY, Parma_Polyhedra_Library::i_constraint(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::Constraint::NONSTRICT_INEQUALITY, PPL_DIRTY_TEMP, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, and Parma_Polyhedra_Library::Constraint::STRICT_INEQUALITY.

404  {
405  PPL_ASSERT(denom != 0);
406  // The interval constraint is of the form
407  // `var + numer / denom rel 0',
408  // where `rel' is either the relation `==', `>=', or `>'.
409  // For the purpose of refining the interval, this is
410  // (morally) turned into `var rel -numer/denom'.
411  PPL_DIRTY_TEMP(mpq_class, q);
412  assign_r(q.get_num(), numer, ROUND_NOT_NEEDED);
413  assign_r(q.get_den(), denom, ROUND_NOT_NEEDED);
414  q.canonicalize();
415  // Turn `numer/denom' into `-numer/denom'.
416  q = -q;
417 
418  Relation_Symbol rel_sym;
419  switch (type) {
421  rel_sym = EQUAL;
422  break;
424  rel_sym = (denom > 0) ? GREATER_OR_EQUAL : LESS_OR_EQUAL;
425  break;
427  rel_sym = (denom > 0) ? GREATER_THAN : LESS_THAN;
428  break;
429  default:
430  // Silence compiler warning.
431  PPL_UNREACHABLE;
432  return I_ANY;
433  }
434  I_Result res = itv.add_constraint(i_constraint(rel_sym, q));
435  PPL_ASSERT(itv.OK());
436  return res;
437 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
I_Constraint< T > i_constraint(I_Constraint_Rel rel, const T &v)
I_Result
The result of an operation on intervals.
Result may be empty or not empty.
Relation_Symbol
Relation symbols.
#define PPL_DIRTY_TEMP(T, id)
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::refine_no_check ( const Constraint c)
private

Uses the constraint c to refine *this.

Parameters
cThe constraint to be used for the refinement.
Warning
If c and *this are dimension-incompatible, the behavior is undefined.

Definition at line 2473 of file Box_templates.hh.

References Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Box_Helpers::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::Constraint::space_dimension(), and Parma_Polyhedra_Library::Constraint::type().

2473  {
2474  PPL_ASSERT(c.space_dimension() <= space_dimension());
2475  PPL_ASSERT(!marked_empty());
2476 
2477  dimension_type c_num_vars = 0;
2478  dimension_type c_only_var = 0;
2479  // Non-interval constraints are approximated.
2480  if (!Box_Helpers::extract_interval_constraint(c, c_num_vars, c_only_var)) {
2482  return;
2483  }
2484 
2485  const Coefficient& n = c.inhomogeneous_term();
2486  if (c_num_vars == 0) {
2487  // Dealing with a trivial constraint.
2488  if (n < 0
2489  || (c.is_equality() && n != 0)
2490  || (c.is_strict_inequality() && n == 0)) {
2491  set_empty();
2492  }
2493  return;
2494  }
2495 
2496  PPL_ASSERT(c_num_vars == 1);
2497  const Coefficient& d = c.coefficient(Variable(c_only_var));
2498  add_interval_constraint_no_check(c_only_var, c.type(), n, d);
2499 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
static bool extract_interval_constraint(const Constraint &c, dimension_type &c_num_vars, dimension_type &c_only_var)
Decodes the constraint c as an interval constraint.
Definition: Box.cc:30
void propagate_constraint_no_check(const Constraint &c)
Propagates the constraint c to refine *this.
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
Coefficient c
Definition: PIP_Tree.cc:64
void add_interval_constraint_no_check(dimension_type var_id, Constraint::Type type, Coefficient_traits::const_reference numer, Coefficient_traits::const_reference denom)
WRITE ME.
Definition: Box_inlines.hh:442
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
void set_empty()
Causes the box to become empty, i.e., to represent the empty set.
Definition: Box_inlines.hh:44
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::refine_no_check ( const Constraint_System cs)
private

Uses the constraints in cs to refine *this.

Parameters
csThe constraints to be used for the refinement. To avoid termination problems, each constraint in cs will be used for a single refinement step.
Warning
If cs and *this are dimension-incompatible, the behavior is undefined.

Definition at line 2503 of file Box_templates.hh.

References Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint_System::end(), and Parma_Polyhedra_Library::Constraint_System::space_dimension().

2503  {
2504  PPL_ASSERT(cs.space_dimension() <= space_dimension());
2505  for (Constraint_System::const_iterator i = cs.begin(),
2506  cs_end = cs.end(); !marked_empty() && i != cs_end; ++i) {
2507  refine_no_check(*i);
2508  }
2509  PPL_ASSERT(OK());
2510 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
void refine_no_check(const Constraint &c)
Uses the constraint c to refine *this.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
Constraint_System_const_iterator const_iterator
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::refine_no_check ( const Congruence cg)
private

Uses the congruence cg to refine *this.

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

Definition at line 2514 of file Box_templates.hh.

References c, Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Congruence::is_proper_congruence(), and Parma_Polyhedra_Library::Congruence::space_dimension().

2514  {
2515  PPL_ASSERT(!marked_empty());
2516 
2517  PPL_ASSERT(cg.space_dimension() <= space_dimension());
2518 
2519  if (cg.is_proper_congruence()) {
2520  // A proper congruences is also an interval constraint
2521  // if and only if it is trivial.
2522  if (cg.is_inconsistent()) {
2523  set_empty();
2524  }
2525  return;
2526  }
2527 
2528  PPL_ASSERT(cg.is_equality());
2529  Constraint c(cg);
2530  refine_no_check(c);
2531 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
void refine_no_check(const Constraint &c)
Uses the constraint c to refine *this.
Coefficient c
Definition: PIP_Tree.cc:64
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
void set_empty()
Causes the box to become empty, i.e., to represent the empty set.
Definition: Box_inlines.hh:44
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::refine_no_check ( const Congruence_System cgs)
private

Uses the congruences in cgs to refine *this.

Parameters
cgsThe congruences to be added. Nontrivial proper congruences are ignored.
Warning
If cgs and *this are dimension-incompatible, the behavior is undefined.

Definition at line 2535 of file Box_templates.hh.

References Parma_Polyhedra_Library::Congruence_System::begin(), Parma_Polyhedra_Library::Congruence_System::end(), and Parma_Polyhedra_Library::Congruence_System::space_dimension().

2535  {
2536  PPL_ASSERT(cgs.space_dimension() <= space_dimension());
2537  for (Congruence_System::const_iterator i = cgs.begin(),
2538  cgs_end = cgs.end(); !marked_empty() && i != cgs_end; ++i) {
2539  refine_no_check(*i);
2540  }
2541  PPL_ASSERT(OK());
2542 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
void refine_no_check(const Constraint &c)
Uses the constraint c to refine *this.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::refine_with_congruence ( const Congruence cg)
inline

Use the congruence cg to refine *this.

Parameters
cgThe congruence to be used for refinement.
Exceptions
std::invalid_argumentThrown if *this and cg are dimension-incompatible.

Definition at line 491 of file Box_inlines.hh.

References Parma_Polyhedra_Library::Congruence::space_dimension().

491  {
492  const dimension_type cg_space_dim = cg.space_dimension();
493  // Dimension-compatibility check.
494  if (cg_space_dim > space_dimension()) {
495  throw_dimension_incompatible("refine_with_congruence(cg)", cg);
496  }
497  // If the box is already empty, there is nothing left to do.
498  if (marked_empty()) {
499  return;
500  }
501  refine_no_check(cg);
502 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
void refine_no_check(const Constraint &c)
Uses the constraint c to refine *this.
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::refine_with_congruences ( const Congruence_System cgs)
inline

Use the congruences in cgs to refine *this.

Parameters
cgsThe congruences to be used for refinement.
Exceptions
std::invalid_argumentThrown if *this and cgs are dimension-incompatible.

Definition at line 506 of file Box_inlines.hh.

References Parma_Polyhedra_Library::Congruence_System::space_dimension().

506  {
507  // Dimension-compatibility check.
508  if (cgs.space_dimension() > space_dimension()) {
509  throw_dimension_incompatible("refine_with_congruences(cgs)", cgs);
510  }
511 
512  // If the box is already empty, there is nothing left to do.
513  if (marked_empty()) {
514  return;
515  }
516 
517  refine_no_check(cgs);
518 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
void refine_no_check(const Constraint &c)
Uses the constraint c to refine *this.
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::refine_with_constraint ( const Constraint c)
inline

Use the constraint c to refine *this.

Parameters
cThe constraint to be used for refinement.
Exceptions
std::invalid_argumentThrown if *this and c are dimension-incompatible.

Definition at line 459 of file Box_inlines.hh.

References Parma_Polyhedra_Library::Constraint::space_dimension().

459  {
460  const dimension_type c_space_dim = c.space_dimension();
461  // Dimension-compatibility check.
462  if (c_space_dim > space_dimension()) {
463  throw_dimension_incompatible("refine_with_constraint(c)", c);
464  }
465 
466  // If the box is already empty, there is nothing left to do.
467  if (marked_empty()) {
468  return;
469  }
470 
472 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
void refine_no_check(const Constraint &c)
Uses the constraint c to refine *this.
Coefficient c
Definition: PIP_Tree.cc:64
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::refine_with_constraints ( const Constraint_System cs)
inline

Use the constraints in cs to refine *this.

Parameters
csThe constraints to be used for refinement. To avoid termination problems, each constraint in cs will be used for a single refinement step.
Exceptions
std::invalid_argumentThrown if *this and cs are dimension-incompatible.
Note
The user is warned that the accuracy of this refinement operator depends on the order of evaluation of the constraints in 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 476 of file Box_inlines.hh.

References Parma_Polyhedra_Library::Constraint_System::space_dimension().

476  {
477  // Dimension-compatibility check.
478  if (cs.space_dimension() > space_dimension()) {
479  throw_dimension_incompatible("refine_with_constraints(cs)", cs);
480  }
481 
482  // If the box is already empty, there is nothing left to do.
483  if (marked_empty()) {
484  return;
485  }
486  refine_no_check(cs);
487 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
void refine_no_check(const Constraint &c)
Uses the constraint c to refine *this.
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
template<typename ITV >
Poly_Con_Relation Parma_Polyhedra_Library::Box< ITV >::relation_with ( const Constraint c) const

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

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

Definition at line 920 of file Box_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Expression_Adapter< T >::begin(), Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Expression_Hide_Last< T >::end(), Parma_Polyhedra_Library::Constraint::expression(), Parma_Polyhedra_Library::Box_Helpers::extract_interval_constraint(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::interval_relation(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Constraint::is_inequality(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Poly_Con_Relation::nothing(), PPL_DIRTY_TEMP, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), Parma_Polyhedra_Library::Boundary_NS::sgn(), Parma_Polyhedra_Library::Constraint::space_dimension(), and Parma_Polyhedra_Library::Constraint::type().

920  {
921  const dimension_type c_space_dim = c.space_dimension();
922  const dimension_type space_dim = space_dimension();
923 
924  // Dimension-compatibility check.
925  if (c_space_dim > space_dim) {
926  throw_dimension_incompatible("relation_with(c)", c);
927  }
928 
929  if (is_empty()) {
933  }
934 
935  if (space_dim == 0) {
936  if ((c.is_equality() && c.inhomogeneous_term() != 0)
937  || (c.is_inequality() && c.inhomogeneous_term() < 0)) {
939  }
940  else if (c.is_strict_inequality() && c.inhomogeneous_term() == 0) {
941  // The constraint 0 > 0 implicitly defines the hyperplane 0 = 0;
942  // thus, the zero-dimensional point also saturates it.
945  }
946  else if (c.is_equality() || c.inhomogeneous_term() == 0) {
949  }
950  else {
951  // The zero-dimensional point saturates
952  // neither the positivity constraint 1 >= 0,
953  // nor the strict positivity constraint 1 > 0.
955  }
956  }
957 
958  dimension_type c_num_vars = 0;
959  dimension_type c_only_var = 0;
960 
961  if (Box_Helpers::extract_interval_constraint(c, c_num_vars, c_only_var)) {
962  if (c_num_vars == 0) {
963  // c is a trivial constraint.
964  switch (sgn(c.inhomogeneous_term())) {
965  case -1:
967  case 0:
968  if (c.is_strict_inequality()) {
971  }
972  else {
975  }
976  case 1:
978  }
979  }
980  else {
981  // c is an interval constraint.
982  return interval_relation(seq[c_only_var],
983  c.type(),
984  c.inhomogeneous_term(),
985  c.coefficient(Variable(c_only_var)));
986  }
987  }
988  else {
989  // Deal with a non-trivial and non-interval constraint.
992  PPL_DIRTY_TEMP(mpq_class, m);
993  r = 0;
994  const Constraint::expr_type& e = c.expression();
995  for (Constraint::expr_type::const_iterator i = e.begin(), i_end = e.end();
996  i != i_end; ++i) {
997  assign_r(m, *i, ROUND_NOT_NEEDED);
998  const Variable v = i.variable();
999  // FIXME: an add_mul_assign() method would come handy here.
1000  t.build(seq[v.id()].lower_constraint(), seq[v.id()].upper_constraint());
1001  t *= m;
1002  r += t;
1003  }
1004  return interval_relation(r,
1005  c.type(),
1006  c.inhomogeneous_term());
1007  }
1008 
1009  // Quiet a compiler warning: this program point is unreachable.
1010  PPL_UNREACHABLE;
1011  return Poly_Con_Relation::nothing();
1012 }
Expression_Hide_Last< Linear_Expression > expr_type
The type of the (adapted) internal expression.
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
static Poly_Con_Relation is_disjoint()
The polyhedron and the set of points satisfying the constraint are disjoint.
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
static Poly_Con_Relation is_included()
The polyhedron is included in the set of points satisfying the constraint.
static Poly_Con_Relation saturates()
The polyhedron is included in the set of points saturating the constraint.
static bool extract_interval_constraint(const Constraint &c, dimension_type &c_num_vars, dimension_type &c_only_var)
Decodes the constraint c as an interval constraint.
Definition: Box.cc:30
Interval< mpq_class, Rational_Interval_Info > Rational_Interval
An interval with rational, possibly open boundaries.
Poly_Con_Relation interval_relation(const ITV &i, const Constraint::Type constraint_type, Coefficient_traits::const_reference numer, Coefficient_traits::const_reference denom=Coefficient_one())
Returns the relations holding between an interval and an interval constraint.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
#define PPL_DIRTY_TEMP(T, id)
base_type::const_iterator const_iterator
The type of const iterators on coefficients.
int sgn(Boundary_Type type, const T &x, const Info &info)
Coefficient c
Definition: PIP_Tree.cc:64
static Poly_Con_Relation nothing()
The assertion that says nothing.
template<typename ITV >
Poly_Con_Relation Parma_Polyhedra_Library::Box< ITV >::relation_with ( const Congruence cg) const

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

Exceptions
std::invalid_argumentThrown if *this and constraint cg are dimension-incompatible.

Definition at line 854 of file Box_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Expression_Adapter< T >::begin(), c, Parma_Polyhedra_Library::Expression_Adapter< T >::end(), Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::Congruence::expression(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Congruence::inhomogeneous_term(), Parma_Polyhedra_Library::interval_relation(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Congruence::modulus(), PPL_DIRTY_TEMP, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::ROUND_DOWN, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), Parma_Polyhedra_Library::Congruence::space_dimension(), and Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects().

854  {
855  const dimension_type cg_space_dim = cg.space_dimension();
856  const dimension_type space_dim = space_dimension();
857 
858  // Dimension-compatibility check.
859  if (cg_space_dim > space_dim) {
860  throw_dimension_incompatible("relation_with(cg)", cg);
861  }
862  if (is_empty()) {
866  }
867 
868  if (space_dim == 0) {
869  if (cg.is_inconsistent()) {
871  }
872  else {
875  }
876  }
877 
878  if (cg.is_equality()) {
879  const Constraint c(cg);
880  return relation_with(c);
881  }
882 
885  PPL_DIRTY_TEMP(mpq_class, m);
886  r = 0;
887  for (Congruence::expr_type::const_iterator i = cg.expression().begin(),
888  i_end = cg.expression().end(); i != i_end; ++i) {
889  const Coefficient& cg_i = *i;
890  const Variable v = i.variable();
891  assign_r(m, cg_i, ROUND_NOT_NEEDED);
892  // FIXME: an add_mul_assign() method would come handy here.
893  t.build(seq[v.id()].lower_constraint(), seq[v.id()].upper_constraint());
894  t *= m;
895  r += t;
896  }
897 
898  if (r.lower_is_boundary_infinity() || r.upper_is_boundary_infinity()) {
900  }
901 
902  // Find the value that satisfies the congruence and is
903  // nearest to the lower bound such that the point lies on or above it.
904 
908  mod = cg.modulus();
909  v = cg.inhomogeneous_term() % mod;
910  assign_r(lower, r.lower(), ROUND_DOWN);
911  v -= ((lower / mod) * mod);
912  if (v + lower > 0) {
913  v -= mod;
914  }
916 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
static Poly_Con_Relation is_disjoint()
The polyhedron and the set of points satisfying the constraint are disjoint.
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
static Poly_Con_Relation is_included()
The polyhedron is included in the set of points satisfying the constraint.
static Poly_Con_Relation saturates()
The polyhedron is included in the set of points saturating the constraint.
Interval< mpq_class, Rational_Interval_Info > Rational_Interval
An interval with rational, possibly open boundaries.
Poly_Con_Relation interval_relation(const ITV &i, const Constraint::Type constraint_type, Coefficient_traits::const_reference numer, Coefficient_traits::const_reference denom=Coefficient_one())
Returns the relations holding between an interval and an interval constraint.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
#define PPL_DIRTY_TEMP(T, id)
base_type::const_iterator const_iterator
The type of const iterators on coefficients.
Coefficient c
Definition: PIP_Tree.cc:64
Poly_Con_Relation relation_with(const Constraint &c) const
Returns the relations holding between *this and the constraint c.
static Poly_Con_Relation strictly_intersects()
The polyhedron intersects the set of points satisfying the constraint, but it is not included in it...
template<typename ITV >
Poly_Gen_Relation Parma_Polyhedra_Library::Box< ITV >::relation_with ( const Generator g) const

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

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

Definition at line 1016 of file Box_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Expression_Adapter< T >::begin(), Parma_Polyhedra_Library::Generator::coefficient(), Parma_Polyhedra_Library::Generator::divisor(), Parma_Polyhedra_Library::Expression_Hide_Last< T >::end(), Parma_Polyhedra_Library::Generator::expression(), Parma_Polyhedra_Library::Variable::id(), 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(), PPL_DIRTY_TEMP, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::Boundary_NS::sgn(), Parma_Polyhedra_Library::Generator::space_dimension(), and Parma_Polyhedra_Library::Poly_Gen_Relation::subsumes().

1016  {
1017  const dimension_type space_dim = space_dimension();
1018  const dimension_type g_space_dim = g.space_dimension();
1019 
1020  // Dimension-compatibility check.
1021  if (space_dim < g_space_dim) {
1022  throw_dimension_incompatible("relation_with(g)", g);
1023  }
1024 
1025  // The empty box cannot subsume a generator.
1026  if (is_empty()) {
1027  return Poly_Gen_Relation::nothing();
1028  }
1029 
1030  // A universe box in a zero-dimensional space subsumes
1031  // all the generators of a zero-dimensional space.
1032  if (space_dim == 0) {
1033  return Poly_Gen_Relation::subsumes();
1034  }
1035 
1036  if (g.is_line_or_ray()) {
1037  if (g.is_line()) {
1038  const Generator::expr_type& e = g.expression();
1039  for (Generator::expr_type::const_iterator i = e.begin(), i_end = e.end();
1040  i != i_end; ++i) {
1041  if (!seq[i.variable().id()].is_universe()) {
1042  return Poly_Gen_Relation::nothing();
1043  }
1044  }
1045  return Poly_Gen_Relation::subsumes();
1046  }
1047  else {
1048  PPL_ASSERT(g.is_ray());
1049  const Generator::expr_type& e = g.expression();
1050  for (Generator::expr_type::const_iterator i = e.begin(), i_end = e.end();
1051  i != i_end; ++i) {
1052  const Variable v = i.variable();
1053  switch (sgn(*i)) {
1054  case 1:
1055  if (!seq[v.id()].upper_is_boundary_infinity()) {
1056  return Poly_Gen_Relation::nothing();
1057  }
1058  break;
1059  case 0:
1060  PPL_UNREACHABLE;
1061  break;
1062  case -1:
1063  if (!seq[v.id()].lower_is_boundary_infinity()) {
1064  return Poly_Gen_Relation::nothing();
1065  }
1066  break;
1067  }
1068  }
1069  return Poly_Gen_Relation::subsumes();
1070  }
1071  }
1072 
1073  // Here `g' is a point or closure point.
1074  const Coefficient& g_divisor = g.divisor();
1075  PPL_DIRTY_TEMP(mpq_class, g_coord);
1076  PPL_DIRTY_TEMP(mpq_class, bound);
1077  // TODO: If the variables in the expression that have coefficient 0
1078  // have no effect on seq[i], this loop can be optimized using
1079  // Generator::expr_type::const_iterator.
1080  for (dimension_type i = g_space_dim; i-- > 0; ) {
1081  const ITV& seq_i = seq[i];
1082  if (seq_i.is_universe()) {
1083  continue;
1084  }
1085  assign_r(g_coord.get_num(), g.coefficient(Variable(i)), ROUND_NOT_NEEDED);
1086  assign_r(g_coord.get_den(), g_divisor, ROUND_NOT_NEEDED);
1087  g_coord.canonicalize();
1088  // Check lower bound.
1089  if (!seq_i.lower_is_boundary_infinity()) {
1090  assign_r(bound, seq_i.lower(), ROUND_NOT_NEEDED);
1091  if (g_coord <= bound) {
1092  if (seq_i.lower_is_open()) {
1093  if (g.is_point() || g_coord != bound) {
1094  return Poly_Gen_Relation::nothing();
1095  }
1096  }
1097  else if (g_coord != bound) {
1098  return Poly_Gen_Relation::nothing();
1099  }
1100  }
1101  }
1102  // Check upper bound.
1103  if (!seq_i.upper_is_boundary_infinity()) {
1104  assign_r(bound, seq_i.upper(), ROUND_NOT_NEEDED);
1105  if (g_coord >= bound) {
1106  if (seq_i.upper_is_open()) {
1107  if (g.is_point() || g_coord != bound) {
1108  return Poly_Gen_Relation::nothing();
1109  }
1110  }
1111  else if (g_coord != bound) {
1112  return Poly_Gen_Relation::nothing();
1113  }
1114  }
1115  }
1116  }
1117  return Poly_Gen_Relation::subsumes();
1118 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
static Poly_Gen_Relation subsumes()
Adding the generator would not change the polyhedron.
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
Expression_Hide_Last< Expression_Hide_Inhomo< Linear_Expression > > expr_type
The type of the (adapted) internal expression.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
#define PPL_DIRTY_TEMP(T, id)
base_type::const_iterator const_iterator
The type of const iterators on coefficients.
int sgn(Boundary_Type type, const T &x, const Info &info)
static Poly_Gen_Relation nothing()
The assertion that says nothing.
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::remove_higher_space_dimensions ( dimension_type  new_dimension)

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

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

Definition at line 2258 of file Box_templates.hh.

2258  {
2259  // Dimension-compatibility check: the variable having
2260  // maximum index is the one occurring last in the set.
2261  const dimension_type space_dim = space_dimension();
2262  if (new_dimension > space_dim) {
2263  throw_dimension_incompatible("remove_higher_space_dimensions(nd)",
2264  new_dimension);
2265  }
2266 
2267  // The removal of no dimensions from any box is a no-op.
2268  // Note that this case also captures the only legal removal of
2269  // dimensions from a zero-dim space box.
2270  if (new_dimension == space_dim) {
2271  PPL_ASSERT(OK());
2272  return;
2273  }
2274 
2275  seq.resize(new_dimension);
2276  PPL_ASSERT(OK());
2277 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
bool OK() const
Returns true if and only if *this satisfies all its invariants.
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::remove_space_dimensions ( const Variables_Set vars)
inline

Removes all the specified dimensions.

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

Definition at line 2201 of file Box_templates.hh.

References Parma_Polyhedra_Library::Variables_Set::space_dimension(), and Parma_Polyhedra_Library::swap().

2201  {
2202  // The removal of no dimensions from any box is a no-op.
2203  // Note that this case also captures the only legal removal of
2204  // space dimensions from a box in a zero-dimensional space.
2205  if (vars.empty()) {
2206  PPL_ASSERT(OK());
2207  return;
2208  }
2209 
2210  const dimension_type old_space_dim = space_dimension();
2211 
2212  // Dimension-compatibility check.
2213  const dimension_type vsi_space_dim = vars.space_dimension();
2214  if (old_space_dim < vsi_space_dim) {
2215  throw_dimension_incompatible("remove_space_dimensions(vs)",
2216  vsi_space_dim);
2217  }
2218 
2219  const dimension_type new_space_dim = old_space_dim - vars.size();
2220 
2221  // If the box is empty (this must be detected), then resizing is all
2222  // what is needed. If it is not empty and we are removing _all_ the
2223  // dimensions then, again, resizing suffices.
2224  if (is_empty() || new_space_dim == 0) {
2225  seq.resize(new_space_dim);
2226  PPL_ASSERT(OK());
2227  return;
2228  }
2229 
2230  // For each variable to be removed, we fill the corresponding interval
2231  // by shifting left those intervals that will not be removed.
2232  Variables_Set::const_iterator vsi = vars.begin();
2233  Variables_Set::const_iterator vsi_end = vars.end();
2234  dimension_type dst = *vsi;
2235  dimension_type src = dst + 1;
2236  for (++vsi; vsi != vsi_end; ++vsi) {
2237  const dimension_type vsi_next = *vsi;
2238  // All intervals in between are moved to the left.
2239  while (src < vsi_next) {
2240  swap(seq[dst++], seq[src++]);
2241  }
2242  ++src;
2243  }
2244 
2245  // Moving the remaining intervals.
2246  while (src < old_space_dim) {
2247  swap(seq[dst++], seq[src++]);
2248  }
2249 
2250  PPL_ASSERT(dst == new_space_dim);
2251  seq.resize(new_space_dim);
2252 
2253  PPL_ASSERT(OK());
2254 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
void swap(Box< ITV > &x, Box< ITV > &y)
Swaps x with y.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
bool OK() const
Returns true if and only if *this satisfies all its invariants.
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::reset_empty_up_to_date ( )
inlineprivate

Invalidates empty flag of *this.

Definition at line 64 of file Box_inlines.hh.

Referenced by Parma_Polyhedra_Library::Box< ITV >::OK().

64  {
66 }
Status status
The status flags to keep track of the internal state.
Definition: Box_defs.hh:1772
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::set_empty_up_to_date ( )
inlineprivate

Asserts the validity of the empty flag of *this.

Definition at line 58 of file Box_inlines.hh.

Referenced by Parma_Polyhedra_Library::Box< ITV >::Status::ascii_load(), and Parma_Polyhedra_Library::Box< ITV >::Box().

58  {
60 }
Status status
The status flags to keep track of the internal state.
Definition: Box_defs.hh:1772
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::set_interval ( Variable  var,
const ITV &  i 
)
inline

Sets to i the interval that bounds var.

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

Definition at line 164 of file Box_inlines.hh.

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

164  {
165  const dimension_type space_dim = space_dimension();
166  if (space_dim < var.space_dimension()) {
167  throw_dimension_incompatible("set_interval(v, i)", "v", var);
168  }
169 
170  if (is_empty() && space_dim >= 2) {
171  // If the box is empty, and has dimension >= 2, setting only one
172  // interval will not make it non-empty.
173  return;
174  }
175  seq[var.id()] = i;
177 
178  PPL_ASSERT(OK());
179 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
void reset_empty_up_to_date()
Invalidates empty flag of *this.
Definition: Box_inlines.hh:64
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
bool OK() const
Returns true if and only if *this satisfies all its invariants.
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::set_nonempty ( )
inlineprivate

Marks *this as definitely not empty.

Definition at line 51 of file Box_inlines.hh.

Referenced by Parma_Polyhedra_Library::Box< ITV >::check_empty(), and Parma_Polyhedra_Library::Box< ITV >::simplify_using_context_assign().

51  {
54 }
Status status
The status flags to keep track of the internal state.
Definition: Box_defs.hh:1772
template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::simplify_using_context_assign ( const Box< ITV > &  y)

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

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

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

2075  {
2076  Box& x = *this;
2077  const dimension_type num_dims = x.space_dimension();
2078  // Dimension-compatibility check.
2079  if (num_dims != y.space_dimension()) {
2080  x.throw_dimension_incompatible("simplify_using_context_assign(y)", y);
2081  }
2082 
2083  // Filter away the zero-dimensional case.
2084  if (num_dims == 0) {
2085  if (y.marked_empty()) {
2086  x.set_nonempty();
2087  return false;
2088  }
2089  else {
2090  return !x.marked_empty();
2091  }
2092  }
2093 
2094  // Filter away the case when `y' is empty.
2095  if (y.is_empty()) {
2096  for (dimension_type i = num_dims; i-- > 0; ) {
2097  x.seq[i].assign(UNIVERSE);
2098  }
2099  x.set_nonempty();
2100  return false;
2101  }
2102 
2103  if (x.is_empty()) {
2104  // Find in `y' a non-universe interval, if any.
2105  for (dimension_type i = 0; i < num_dims; ++i) {
2106  if (y.seq[i].is_universe()) {
2107  x.seq[i].assign(UNIVERSE);
2108  }
2109  else {
2110  // Set x.seq[i] so as to contradict y.seq[i], if possible.
2111  ITV& seq_i = x.seq[i];
2112  seq_i.empty_intersection_assign(y.seq[i]);
2113  if (seq_i.is_empty()) {
2114  // We were not able to assign to `seq_i' a non-empty interval:
2115  // reset `seq_i' to the universe interval and keep searching.
2116  seq_i.assign(UNIVERSE);
2117  continue;
2118  }
2119  // We assigned to `seq_i' a non-empty interval:
2120  // set the other intervals to universe and return.
2121  for (++i; i < num_dims; ++i) {
2122  x.seq[i].assign(UNIVERSE);
2123  }
2124  x.set_nonempty();
2125  PPL_ASSERT(x.OK());
2126  return false;
2127  }
2128  }
2129  // All intervals in `y' are universe or could not be contradicted:
2130  // simplification can leave the empty box `x' as is.
2131  PPL_ASSERT(x.OK() && x.is_empty());
2132  return false;
2133  }
2134 
2135  // Loop index `i' is intentionally going upwards.
2136  for (dimension_type i = 0; i < num_dims; ++i) {
2137  if (!x.seq[i].simplify_using_context_assign(y.seq[i])) {
2138  PPL_ASSERT(!x.seq[i].is_empty());
2139  // The intersection of `x' and `y' is empty due to the i-th interval:
2140  // reset other intervals to UNIVERSE.
2141  for (dimension_type j = num_dims; j-- > i; ) {
2142  x.seq[j].assign(UNIVERSE);
2143  }
2144  for (dimension_type j = i; j-- > 0; ) {
2145  x.seq[j].assign(UNIVERSE);
2146  }
2147  PPL_ASSERT(x.OK());
2148  return false;
2149  }
2150  }
2151  PPL_ASSERT(x.OK());
2152  return true;
2153 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Box(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty box of the specified space dimension.
The universe element, i.e., the whole vector space.
template<typename ITV >
dimension_type Parma_Polyhedra_Library::Box< ITV >::space_dimension ( ) const
inline
template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::strictly_contains ( const Box< ITV > &  y) const
inline

Returns true if and only if *this strictly contains y.

Exceptions
std::invalid_argumentThrown if x and y are dimension-incompatible.

Definition at line 233 of file Box_inlines.hh.

References Parma_Polyhedra_Library::Box< ITV >::contains().

233  {
234  const Box& x = *this;
235  return x.contains(y) && !y.contains(x);
236 }
Box(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty box of the specified space dimension.
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::throw_constraint_incompatible ( const char *  method)
staticprivate

Definition at line 4537 of file Box_templates.hh.

4537  {
4538  std::ostringstream s;
4539  s << "PPL::Box::" << method << ":" << std::endl
4540  << "the constraint is incompatible.";
4541  throw std::invalid_argument(s.str());
4542 }
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible ( const char *  method,
const Box< ITV > &  y 
) const
private

Definition at line 4459 of file Box_templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::space_dimension().

Referenced by Parma_Polyhedra_Library::Box< ITV >::contains(), Parma_Polyhedra_Library::Box< ITV >::intersection_assign(), Parma_Polyhedra_Library::Box< ITV >::is_disjoint_from(), Parma_Polyhedra_Library::Box< ITV >::simplify_using_context_assign(), Parma_Polyhedra_Library::Box< ITV >::time_elapse_assign(), Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign(), and Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign_if_exact().

4460  {
4461  std::ostringstream s;
4462  s << "PPL::Box::" << method << ":" << std::endl
4463  << "this->space_dimension() == " << this->space_dimension()
4464  << ", y->space_dimension() == " << y.space_dimension() << ".";
4465  throw std::invalid_argument(s.str());
4466 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible ( const char *  method,
dimension_type  required_dim 
) const
private

Definition at line 4471 of file Box_templates.hh.

4472  {
4473  std::ostringstream s;
4474  s << "PPL::Box::" << method << ":" << std::endl
4475  << "this->space_dimension() == " << space_dimension()
4476  << ", required dimension == " << required_dim << ".";
4477  throw std::invalid_argument(s.str());
4478 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible ( const char *  method,
const Constraint c 
) const
private

Definition at line 4482 of file Box_templates.hh.

References Parma_Polyhedra_Library::Constraint::space_dimension().

4483  {
4484  std::ostringstream s;
4485  s << "PPL::Box::" << method << ":" << std::endl
4486  << "this->space_dimension() == " << space_dimension()
4487  << ", c->space_dimension == " << c.space_dimension() << ".";
4488  throw std::invalid_argument(s.str());
4489 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
Coefficient c
Definition: PIP_Tree.cc:64
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible ( const char *  method,
const Congruence cg 
) const
private

Definition at line 4493 of file Box_templates.hh.

References Parma_Polyhedra_Library::Congruence::space_dimension().

4494  {
4495  std::ostringstream s;
4496  s << "PPL::Box::" << method << ":" << std::endl
4497  << "this->space_dimension() == " << space_dimension()
4498  << ", cg->space_dimension == " << cg.space_dimension() << ".";
4499  throw std::invalid_argument(s.str());
4500 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible ( const char *  method,
const Constraint_System cs 
) const
private

Definition at line 4504 of file Box_templates.hh.

References Parma_Polyhedra_Library::Constraint_System::space_dimension().

4505  {
4506  std::ostringstream s;
4507  s << "PPL::Box::" << method << ":" << std::endl
4508  << "this->space_dimension() == " << space_dimension()
4509  << ", cs->space_dimension == " << cs.space_dimension() << ".";
4510  throw std::invalid_argument(s.str());
4511 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible ( const char *  method,
const Congruence_System cgs 
) const
private

Definition at line 4515 of file Box_templates.hh.

References Parma_Polyhedra_Library::Congruence_System::space_dimension().

4516  {
4517  std::ostringstream s;
4518  s << "PPL::Box::" << method << ":" << std::endl
4519  << "this->space_dimension() == " << space_dimension()
4520  << ", cgs->space_dimension == " << cgs.space_dimension() << ".";
4521  throw std::invalid_argument(s.str());
4522 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible ( const char *  method,
const Generator g 
) const
private

Definition at line 4526 of file Box_templates.hh.

References Parma_Polyhedra_Library::Generator::space_dimension().

4527  {
4528  std::ostringstream s;
4529  s << "PPL::Box::" << method << ":" << std::endl
4530  << "this->space_dimension() == " << space_dimension()
4531  << ", g->space_dimension == " << g.space_dimension() << ".";
4532  throw std::invalid_argument(s.str());
4533 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible ( const char *  method,
const char *  le_name,
const Linear_Expression le 
) const
private

Definition at line 4557 of file Box_templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::space_dimension().

4559  {
4560  std::ostringstream s;
4561  s << "PPL::Box::" << method << ":" << std::endl
4562  << "this->space_dimension() == " << space_dimension()
4563  << ", " << le_name << "->space_dimension() == "
4564  << le.space_dimension() << ".";
4565  throw std::invalid_argument(s.str());
4566 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
bool le(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
template<typename ITV >
template<typename C >
void Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible ( const char *  method,
const char *  lf_name,
const Linear_Form< C > &  lf 
) const
private

Definition at line 4571 of file Box_templates.hh.

References Parma_Polyhedra_Library::Linear_Form< C >::space_dimension().

4573  {
4574  std::ostringstream s;
4575  s << "PPL::Box::" << method << ":\n"
4576  << "this->space_dimension() == " << space_dimension()
4577  << ", " << lf_name << "->space_dimension() == "
4578  << lf.space_dimension() << ".";
4579  throw std::invalid_argument(s.str());
4580 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::throw_expression_too_complex ( const char *  method,
const Linear_Expression le 
)
staticprivate

Definition at line 4546 of file Box_templates.hh.

4547  {
4548  using namespace IO_Operators;
4549  std::ostringstream s;
4550  s << "PPL::Box::" << method << ":" << std::endl
4551  << le << " is too complex.";
4552  throw std::invalid_argument(s.str());
4553 }
bool le(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::throw_invalid_argument ( const char *  method,
const char *  reason 
)
staticprivate

Definition at line 4584 of file Box_templates.hh.

4584  {
4585  std::ostringstream s;
4586  s << "PPL::Box::" << method << ":" << std::endl
4587  << reason;
4588  throw std::invalid_argument(s.str());
4589 }
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::time_elapse_assign ( const Box< ITV > &  y)

Assigns to *this the result of computing the time-elapse between *this and y.

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

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

2157  {
2158  Box& x = *this;
2159  const dimension_type x_space_dim = x.space_dimension();
2160 
2161  // Dimension-compatibility check.
2162  if (x_space_dim != y.space_dimension()) {
2163  x.throw_dimension_incompatible("time_elapse_assign(y)", y);
2164  }
2165 
2166  // Dealing with the zero-dimensional case.
2167  if (x_space_dim == 0) {
2168  if (y.marked_empty()) {
2169  x.set_empty();
2170  }
2171  return;
2172  }
2173 
2174  // If either one of `x' or `y' is empty, the result is empty too.
2175  // Note: if possible, avoid cost of checking for emptiness.
2176  if (x.marked_empty() || y.marked_empty()
2177  || x.is_empty() || y.is_empty()) {
2178  x.set_empty();
2179  return;
2180  }
2181 
2182  for (dimension_type i = x_space_dim; i-- > 0; ) {
2183  ITV& x_seq_i = x.seq[i];
2184  const ITV& y_seq_i = y.seq[i];
2185  if (!x_seq_i.lower_is_boundary_infinity()) {
2186  if (y_seq_i.lower_is_boundary_infinity() || y_seq_i.lower() < 0) {
2187  x_seq_i.lower_extend();
2188  }
2189  }
2190  if (!x_seq_i.upper_is_boundary_infinity()) {
2191  if (y_seq_i.upper_is_boundary_infinity() || y_seq_i.upper() > 0) {
2192  x_seq_i.upper_extend();
2193  }
2194  }
2195  }
2196  PPL_ASSERT(x.OK());
2197 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Box(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty box of the specified space dimension.
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::topological_closure_assign ( )

Assigns to *this its topological closure.

Definition at line 1659 of file Box_templates.hh.

1659  {
1660  if (ITV::is_always_topologically_closed() || is_empty()) {
1661  return;
1662  }
1663 
1664  for (dimension_type k = seq.size(); k-- > 0; ) {
1665  seq[k].topological_closure_assign();
1666  }
1667 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool is_empty() const
Returns true if and only if *this is an empty box.
Definition: Box_inlines.hh:183
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
template<typename ITV >
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 117 of file Box_inlines.hh.

References Parma_Polyhedra_Library::external_memory_in_bytes().

117  {
118  return sizeof(*this) + external_memory_in_bytes();
119 }
memory_size_type external_memory_in_bytes() const
Returns the size in bytes of the memory managed by *this.
template<typename ITV >
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.

Parameters
varThe space dimension that will be unconstrained.
Exceptions
std::invalid_argumentThrown if var is not a space dimension of *this.

Definition at line 555 of file Box_inlines.hh.

References Parma_Polyhedra_Library::Variable::id(), and Parma_Polyhedra_Library::UNIVERSE.

555  {
556  const dimension_type var_id = var.id();
557  // Dimension-compatibility check.
558  if (space_dimension() < var_id + 1) {
559  throw_dimension_incompatible("unconstrain(var)", var_id + 1);
560  }
561 
562  // If the box is already empty, there is nothing left to do.
563  if (marked_empty()) {
564  return;
565  }
566 
567  // Here the box might still be empty (but we haven't detected it yet):
568  // check emptiness of the interval for `var' before cylindrification.
569  ITV& seq_var = seq[var_id];
570  if (seq_var.is_empty()) {
571  set_empty();
572  }
573  else {
574  seq_var.assign(UNIVERSE);
575  }
576 
577  PPL_ASSERT(OK());
578 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
The universe element, i.e., the whole vector space.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
void set_empty()
Causes the box to become empty, i.e., to represent the empty set.
Definition: Box_inlines.hh:44
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::unconstrain ( const Variables_Set vars)

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

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

Definition at line 1622 of file Box_templates.hh.

References Parma_Polyhedra_Library::Variables_Set::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.

1622  {
1623  // The cylindrification with respect to no dimensions is a no-op.
1624  // This case also captures the only legal cylindrification
1625  // of a box in a 0-dim space.
1626  if (vars.empty()) {
1627  return;
1628  }
1629 
1630  // Dimension-compatibility check.
1631  const dimension_type min_space_dim = vars.space_dimension();
1632  if (space_dimension() < min_space_dim) {
1633  throw_dimension_incompatible("unconstrain(vs)", min_space_dim);
1634  }
1635  // If the box is already empty, there is nothing left to do.
1636  if (marked_empty()) {
1637  return;
1638  }
1639 
1640  // Here the box might still be empty (but we haven't detected it yet):
1641  // check emptiness of the interval for each of the variables in
1642  // `vars' before cylindrification.
1643  for (Variables_Set::const_iterator vsi = vars.begin(),
1644  vsi_end = vars.end(); vsi != vsi_end; ++vsi) {
1645  ITV& seq_vsi = seq[*vsi];
1646  if (!seq_vsi.is_empty()) {
1647  seq_vsi.assign(UNIVERSE);
1648  }
1649  else {
1650  set_empty();
1651  break;
1652  }
1653  }
1654  PPL_ASSERT(OK());
1655 }
void throw_dimension_incompatible(const char *method, const Box &y) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Definition: Box_inlines.hh:123
size_t dimension_type
An unsigned integral type for representing space dimensions.
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
Definition: Box_defs.hh:1765
The universe element, i.e., the whole vector space.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
bool marked_empty() const
Returns true if and only if the box is known to be empty.
Definition: Box_inlines.hh:38
void set_empty()
Causes the box to become empty, i.e., to represent the empty set.
Definition: Box_inlines.hh:44
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign ( const Box< ITV > &  y)

Assigns to *this the smallest box containing the union of *this and y.

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

Definition at line 1938 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 >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

1938  {
1939  Box& x = *this;
1940 
1941  // Dimension-compatibility check.
1942  if (x.space_dimension() != y.space_dimension()) {
1943  x.throw_dimension_incompatible("upper_bound_assign(y)", y);
1944  }
1945 
1946  // The lub of a box with an empty box is equal to the first box.
1947  if (y.is_empty()) {
1948  return;
1949  }
1950  if (x.is_empty()) {
1951  x = y;
1952  return;
1953  }
1954 
1955  for (dimension_type k = x.seq.size(); k-- > 0; ) {
1956  x.seq[k].join_assign(y.seq[k]);
1957  }
1958 
1959  PPL_ASSERT(x.OK());
1960 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Box(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty box of the specified space dimension.
template<typename ITV >
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.

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

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

1343  {
1344  Box& x = *this;
1345 
1346  // Dimension-compatibility check.
1347  if (x.space_dimension() != y.space_dimension()) {
1348  x.throw_dimension_incompatible("upper_bound_assign_if_exact(y)", y);
1349  }
1350 
1351  // The lub of a box with an empty box is equal to the first box.
1352  if (y.is_empty()) {
1353  return true;
1354  }
1355  if (x.is_empty()) {
1356  x = y;
1357  return true;
1358  }
1359 
1360  bool x_j_does_not_contain_y_j = false;
1361  bool y_j_does_not_contain_x_j = false;
1362 
1363  for (dimension_type i = x.seq.size(); i-- > 0; ) {
1364  const ITV& x_seq_i = x.seq[i];
1365  const ITV& y_seq_i = y.seq[i];
1366 
1367  if (!x_seq_i.can_be_exactly_joined_to(y_seq_i)) {
1368  return false;
1369  }
1370 
1371  // Note: the use of `y_i_does_not_contain_x_i' is needed
1372  // because we want to temporarily preserve the old value
1373  // of `y_j_does_not_contain_x_j'.
1374  bool y_i_does_not_contain_x_i = !y_seq_i.contains(x_seq_i);
1375  if (y_i_does_not_contain_x_i && x_j_does_not_contain_y_j) {
1376  return false;
1377  }
1378  if (!x_seq_i.contains(y_seq_i)) {
1379  if (y_j_does_not_contain_x_j) {
1380  return false;
1381  }
1382  else {
1383  x_j_does_not_contain_y_j = true;
1384  }
1385  }
1386  if (y_i_does_not_contain_x_i) {
1387  y_j_does_not_contain_x_j = true;
1388  }
1389  }
1390 
1391  // The upper bound is exact: compute it into *this.
1392  for (dimension_type k = x.seq.size(); k-- > 0; ) {
1393  x.seq[k].join_assign(y.seq[k]);
1394  }
1395  return true;
1396 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Box(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty box of the specified space dimension.
template<typename T >
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 387 of file Box_inlines.hh.

387  {
388  CC76_widening_assign(y, tp);
389 }
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 ITV >
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 cs_p = 0,
unsigned  complexity_threshold = 16,
bool  wrap_individually = true 
)

Wraps the specified dimensions of the vector space.

Parameters
varsThe set of Variable objects corresponding to the space dimensions to be wrapped.
wThe width of the bounded integer type corresponding to all the dimensions to be wrapped.
rThe representation of the bounded integer type corresponding to all the dimensions to be wrapped.
oThe overflow behavior of the bounded integer type corresponding to all the dimensions to be wrapped.
cs_pPossibly 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 *cs_p.
complexity_thresholdA precision parameter which is ignored for the Box domain.
wrap_individuallyA precision parameter which is ignored for the Box domain.
Exceptions
std::invalid_argumentThrown if *this is dimension-incompatible with one of the Variable objects contained in vars or with *cs_p.

Definition at line 1671 of file Box_templates.hh.

References Parma_Polyhedra_Library::Constraint_System::begin(), c, Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Coefficient_one(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Box_Helpers::extract_interval_constraint(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::i_constraint(), 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, PPL_DIRTY_TEMP_COEFFICIENT, PPL_USED, Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::SIGNED_2_COMPLEMENT, Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint::type(), Parma_Polyhedra_Library::UNIVERSE, Parma_Polyhedra_Library::UNSIGNED, and Parma_Polyhedra_Library::Implementation::wrap_assign().

1677  {
1678 #if 0 // Generic implementation commented out.
1680  vars, w, r, o, cs_p,
1681  complexity_threshold, wrap_individually,
1682  "Box");
1683 #else // Specialized implementation.
1684  PPL_USED(wrap_individually);
1685  PPL_USED(complexity_threshold);
1686  Box& x = *this;
1687 
1688  // Dimension-compatibility check for `*cs_p', if any.
1689  const dimension_type vars_space_dim = vars.space_dimension();
1690  if (cs_p != 0 && cs_p->space_dimension() > vars_space_dim) {
1691  std::ostringstream s;
1692  s << "PPL::Box<ITV>::wrap_assign(vars, w, r, o, cs_p, ...):"
1693  << std::endl
1694  << "vars.space_dimension() == " << vars_space_dim
1695  << ", cs_p->space_dimension() == " << cs_p->space_dimension() << ".";
1696  throw std::invalid_argument(s.str());
1697  }
1698 
1699  // Wrapping no variable only requires refining with *cs_p, if any.
1700  if (vars.empty()) {
1701  if (cs_p != 0) {
1702  refine_with_constraints(*cs_p);
1703  }
1704  return;
1705  }
1706 
1707  // Dimension-compatibility check for `vars'.
1708  const dimension_type space_dim = x.space_dimension();
1709  if (space_dim < vars_space_dim) {
1710  std::ostringstream s;
1711  s << "PPL::Box<ITV>::wrap_assign(vars, ...):"
1712  << std::endl
1713  << "this->space_dimension() == " << space_dim
1714  << ", required space dimension == " << vars_space_dim << ".";
1715  throw std::invalid_argument(s.str());
1716  }
1717 
1718  // Wrapping an empty polyhedron is a no-op.
1719  if (x.is_empty()) {
1720  return;
1721  }
1722 
1723  // FIXME: temporarily (ab-) using Coefficient.
1724  // Set `min_value' and `max_value' to the minimum and maximum values
1725  // a variable of width `w' and signedness `s' can take.
1726  PPL_DIRTY_TEMP_COEFFICIENT(min_value);
1727  PPL_DIRTY_TEMP_COEFFICIENT(max_value);
1728  if (r == UNSIGNED) {
1729  min_value = 0;
1730  mul_2exp_assign(max_value, Coefficient_one(), w);
1731  --max_value;
1732  }
1733  else {
1734  PPL_ASSERT(r == SIGNED_2_COMPLEMENT);
1735  mul_2exp_assign(max_value, Coefficient_one(), w-1);
1736  neg_assign(min_value, max_value);
1737  --max_value;
1738  }
1739 
1740  // FIXME: Build the (integer) quadrant interval.
1741  PPL_DIRTY_TEMP(ITV, integer_quadrant_itv);
1742  PPL_DIRTY_TEMP(ITV, rational_quadrant_itv);
1743  {
1744  I_Constraint<Coefficient> lower = i_constraint(GREATER_OR_EQUAL, min_value);
1745  I_Constraint<Coefficient> upper = i_constraint(LESS_OR_EQUAL, max_value);
1746  integer_quadrant_itv.build(lower, upper);
1747  // The rational quadrant is only needed if overflow is undefined.
1748  if (o == OVERFLOW_UNDEFINED) {
1749  ++max_value;
1750  upper = i_constraint(LESS_THAN, max_value);
1751  rational_quadrant_itv.build(lower, upper);
1752  }
1753  }
1754 
1755  const Variables_Set::const_iterator vs_end = vars.end();
1756 
1757  if (cs_p == 0) {
1758  // No constraint refinement is needed here.
1759  switch (o) {
1760  case OVERFLOW_WRAPS:
1761  for (Variables_Set::const_iterator i = vars.begin(); i != vs_end; ++i) {
1762  x.seq[*i].wrap_assign(w, r, integer_quadrant_itv);
1763  }
1765  break;
1766  case OVERFLOW_UNDEFINED:
1767  for (Variables_Set::const_iterator i = vars.begin(); i != vs_end; ++i) {
1768  ITV& x_seq_v = x.seq[*i];
1769  if (!rational_quadrant_itv.contains(x_seq_v)) {
1770  x_seq_v.assign(integer_quadrant_itv);
1771  }
1772  }
1773  break;
1774  case OVERFLOW_IMPOSSIBLE:
1775  for (Variables_Set::const_iterator i = vars.begin(); i != vs_end; ++i) {
1776  x.seq[*i].intersect_assign(integer_quadrant_itv);
1777  }
1779  break;
1780  }
1781  PPL_ASSERT(x.OK());
1782  return;
1783  }
1784 
1785  PPL_ASSERT(cs_p != 0);
1786  const Constraint_System& cs = *cs_p;
1787  // A map associating interval constraints to variable indexes.
1788  typedef std::map<dimension_type, std::vector<const Constraint*> > map_type;
1789  map_type var_cs_map;
1790  for (Constraint_System::const_iterator i = cs.begin(),
1791  i_end = cs.end(); i != i_end; ++i) {
1792  const Constraint& c = *i;
1793  dimension_type c_num_vars = 0;
1794  dimension_type c_only_var = 0;
1795  if (Box_Helpers::extract_interval_constraint(c, c_num_vars, c_only_var)) {
1796  if (c_num_vars == 1) {
1797  // An interval constraint on variable index `c_only_var'.
1798  PPL_ASSERT(c_only_var < space_dim);
1799  // We do care about c if c_only_var is going to be wrapped.
1800  if (vars.find(c_only_var) != vs_end) {
1801  var_cs_map[c_only_var].push_back(&c);
1802  }
1803  }
1804  else {
1805  PPL_ASSERT(c_num_vars == 0);
1806  // Note: tautologies have been filtered out by iterators.
1807  PPL_ASSERT(c.is_inconsistent());
1808  x.set_empty();
1809  return;
1810  }
1811  }
1812  }
1813 
1814  PPL_DIRTY_TEMP(ITV, refinement_itv);
1815  const map_type::const_iterator var_cs_map_end = var_cs_map.end();
1816  // Loop through the variable indexes in `vars'.
1817  for (Variables_Set::const_iterator i = vars.begin(); i != vs_end; ++i) {
1818  const dimension_type v = *i;
1819  refinement_itv = integer_quadrant_itv;
1820  // Look for the refinement constraints for space dimension index `v'.
1821  map_type::const_iterator var_cs_map_iter = var_cs_map.find(v);
1822  if (var_cs_map_iter != var_cs_map_end) {
1823  // Refine interval for variable `v'.
1824  const map_type::mapped_type& var_cs = var_cs_map_iter->second;
1825  for (dimension_type j = var_cs.size(); j-- > 0; ) {
1826  const Constraint& c = *var_cs[j];
1827  refine_interval_no_check(refinement_itv,
1828  c.type(),
1829  c.inhomogeneous_term(),
1830  c.coefficient(Variable(v)));
1831  }
1832  }
1833  // Wrap space dimension index `v'.
1834  ITV& x_seq_v = x.seq[v];
1835  switch (o) {
1836  case OVERFLOW_WRAPS:
1837  x_seq_v.wrap_assign(w, r, refinement_itv);
1838  break;
1839  case OVERFLOW_UNDEFINED:
1840  if (!rational_quadrant_itv.contains(x_seq_v)) {
1841  x_seq_v.assign(UNIVERSE);
1842  }
1843  break;
1844  case OVERFLOW_IMPOSSIBLE:
1845  x_seq_v.intersect_assign(refinement_itv);
1846  break;
1847  }
1848  }
1849  PPL_ASSERT(x.OK());
1850 #endif
1851 }
I_Constraint< T > i_constraint(I_Constraint_Rel rel, const T &v)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Box(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty box of the specified space dimension.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
void refine_with_constraints(const Constraint_System &cs)
Use the constraints in cs to refine *this.
Definition: Box_inlines.hh:476
On overflow, wrapping takes place.
static bool extract_interval_constraint(const Constraint &c, dimension_type &c_num_vars, dimension_type &c_only_var)
Decodes the constraint c as an interval constraint.
Definition: Box.cc:30
On overflow, the result is undefined.
void reset_empty_up_to_date()
Invalidates empty flag of *this.
Definition: Box_inlines.hh:64
static I_Result refine_interval_no_check(ITV &itv, Constraint::Type type, Coefficient_traits::const_reference numer, Coefficient_traits::const_reference denom)
WRITE ME.
Definition: Box_inlines.hh:401
void wrap_assign(PSET &pointset, const Variables_Set &vars, const Bounded_Integer_Type_Width w, const Bounded_Integer_Type_Representation r, const Bounded_Integer_Type_Overflow o, const Constraint_System *cs_p, const unsigned complexity_threshold, const bool wrap_individually, const char *class_name)
Definition: wrap_assign.hh:152
void mul_2exp_assign(GMP_Integer &x, const GMP_Integer &y, unsigned int exp)
#define PPL_DIRTY_TEMP(T, id)
The universe element, i.e., the whole vector space.
void neg_assign(GMP_Integer &x)
Signed binary where negative values are represented by the two's complement of the absolute value...
#define PPL_USED(v)
No-op macro that allows to avoid unused variable warnings from the compiler.
Definition: compiler.hh:39
Coefficient c
Definition: PIP_Tree.cc:64
Coefficient_traits::const_reference Coefficient_one()
Returns a const reference to a Coefficient with value 1.
Constraint_System_const_iterator const_iterator

Friends And Related Function Documentation

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

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 
)
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<Temp, Extended_Number_Policy>.

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

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,
const Rounding_Dir  dir,
Temp &  tmp0,
Temp &  tmp1,
Temp &  tmp2 
)
related

Definition at line 624 of file Box_inlines.hh.

630  {
631  return l_m_distance_assign<Euclidean_Distance_Specialization<Temp> >
632  (r, x, y, dir, tmp0, tmp1, tmp2);
633 }
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,
const Rounding_Dir  dir 
)
related

Definition at line 638 of file Box_inlines.hh.

References PPL_DIRTY_TEMP.

641  {
642  typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
643  PPL_DIRTY_TEMP(Checked_Temp, tmp0);
644  PPL_DIRTY_TEMP(Checked_Temp, tmp1);
645  PPL_DIRTY_TEMP(Checked_Temp, tmp2);
646  return euclidean_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
647 }
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.
#define PPL_DIRTY_TEMP(T, id)
template<typename To , typename ITV >
bool euclidean_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const Box< ITV > &  x,
const Box< ITV > &  y,
const Rounding_Dir  dir 
)
related

Definition at line 652 of file Box_inlines.hh.

655  {
656  // FIXME: the following qualification is only to work around a bug
657  // in the Intel C/C++ compiler version 10.1.x.
658  return Parma_Polyhedra_Library
659  ::euclidean_distance_assign<To, To, ITV>(r, x, y, dir);
660 }
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 
)
related

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

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

The direction of the approximation is specified by dir.

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

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 
)
related

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

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

The direction of the approximation is specified by dir.

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

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 
)
related

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

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

The direction of the approximation is specified by dir.

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

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,
const Rounding_Dir  dir,
Temp &  tmp0,
Temp &  tmp1,
Temp &  tmp2 
)
related

Definition at line 665 of file Box_inlines.hh.

671  {
672  return l_m_distance_assign<L_Infinity_Distance_Specialization<Temp> >
673  (r, x, y, dir, tmp0, tmp1, tmp2);
674 }
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,
const Rounding_Dir  dir 
)
related

Definition at line 679 of file Box_inlines.hh.

References PPL_DIRTY_TEMP.

682  {
683  typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
684  PPL_DIRTY_TEMP(Checked_Temp, tmp0);
685  PPL_DIRTY_TEMP(Checked_Temp, tmp1);
686  PPL_DIRTY_TEMP(Checked_Temp, tmp2);
687  return l_infinity_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
688 }
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.
#define PPL_DIRTY_TEMP(T, id)
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,
const Rounding_Dir  dir 
)
related

Definition at line 693 of file Box_inlines.hh.

696  {
697  // FIXME: the following qualification is only to work around a bug
698  // in the Intel C/C++ compiler version 10.1.x.
699  return Parma_Polyhedra_Library
700  ::l_infinity_distance_assign<To, To, ITV>(r, x, y, dir);
701 }
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 
)
related

Helper function for computing distances.

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,
const Rounding_Dir  dir,
Temp &  tmp0,
Temp &  tmp1,
Temp &  tmp2 
)
related

Definition at line 4597 of file Box_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::combine(), Parma_Polyhedra_Library::finalize(), Parma_Polyhedra_Library::inverse(), 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::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Boundary_NS::sgn(), and Parma_Polyhedra_Library::Box< ITV >::space_dimension().

4600  {
4601  const dimension_type x_space_dim = x.space_dimension();
4602  // Dimension-compatibility check.
4603  if (x_space_dim != y.space_dimension()) {
4604  return false;
4605  }
4606  // Zero-dim boxes are equal if and only if they are both empty or universe.
4607  if (x_space_dim == 0) {
4608  if (x.marked_empty() == y.marked_empty()) {
4609  assign_r(r, 0, ROUND_NOT_NEEDED);
4610  }
4611  else {
4613  }
4614  return true;
4615  }
4616 
4617  // The distance computation requires a check for emptiness.
4618  (void) x.is_empty();
4619  (void) y.is_empty();
4620  // If one of two boxes is empty, then they are equal if and only if
4621  // the other box is empty too.
4622  if (x.marked_empty() || y.marked_empty()) {
4623  if (x.marked_empty() == y.marked_empty()) {
4624  assign_r(r, 0, ROUND_NOT_NEEDED);
4625  return true;
4626  }
4627  else {
4628  goto pinf;
4629  }
4630  }
4631 
4632  assign_r(tmp0, 0, ROUND_NOT_NEEDED);
4633  for (dimension_type i = x_space_dim; i-- > 0; ) {
4634  const ITV& x_i = x.seq[i];
4635  const ITV& y_i = y.seq[i];
4636  // Dealing with the lower bounds.
4637  if (x_i.lower_is_boundary_infinity()) {
4638  if (!y_i.lower_is_boundary_infinity()) {
4639  goto pinf;
4640  }
4641  }
4642  else if (y_i.lower_is_boundary_infinity()) {
4643  goto pinf;
4644  }
4645  else {
4646  const Temp* tmp1p;
4647  const Temp* tmp2p;
4648  if (x_i.lower() > y_i.lower()) {
4649  maybe_assign(tmp1p, tmp1, x_i.lower(), dir);
4650  maybe_assign(tmp2p, tmp2, y_i.lower(), inverse(dir));
4651  }
4652  else {
4653  maybe_assign(tmp1p, tmp1, y_i.lower(), dir);
4654  maybe_assign(tmp2p, tmp2, x_i.lower(), inverse(dir));
4655  }
4656  sub_assign_r(tmp1, *tmp1p, *tmp2p, dir);
4657  PPL_ASSERT(sgn(tmp1) >= 0);
4658  Specialization::combine(tmp0, tmp1, dir);
4659  }
4660  // Dealing with the lower bounds.
4661  if (x_i.upper_is_boundary_infinity()) {
4662  if (y_i.upper_is_boundary_infinity()) {
4663  continue;
4664  }
4665  else {
4666  goto pinf;
4667  }
4668  }
4669  else if (y_i.upper_is_boundary_infinity()) {
4670  goto pinf;
4671  }
4672  else {
4673  const Temp* tmp1p;
4674  const Temp* tmp2p;
4675  if (x_i.upper() > y_i.upper()) {
4676  maybe_assign(tmp1p, tmp1, x_i.upper(), dir);
4677  maybe_assign(tmp2p, tmp2, y_i.upper(), inverse(dir));
4678  }
4679  else {
4680  maybe_assign(tmp1p, tmp1, y_i.upper(), dir);
4681  maybe_assign(tmp2p, tmp2, x_i.upper(), inverse(dir));
4682  }
4683  sub_assign_r(tmp1, *tmp1p, *tmp2p, dir);
4684  PPL_ASSERT(sgn(tmp1) >= 0);
4685  Specialization::combine(tmp0, tmp1, dir);
4686  }
4687  }
4688  Specialization::finalize(tmp0, dir);
4689  assign_r(r, tmp0, dir);
4690  return true;
4691 
4692  pinf:
4694  return true;
4695 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Rounding_Dir inverse(Rounding_Dir dir)
void finalize()
Finalizes the library.
Definition: initializer.hh:60
Plus_Infinity PLUS_INFINITY
Definition: checked.cc:31
I_Result combine(Result l, Result u)
int sgn(Boundary_Type type, const T &x, const Info &info)
Result maybe_assign(const To *&top, To &tmp, const From &from, Rounding_Dir dir)
Assigns to top a pointer to a location that holds the conversion, according to dir, of from to type To. When necessary, and only when necessary, the variable tmp is used to hold the result of conversion.
template<typename ITV >
bool operator!= ( const Box< ITV > &  x,
const Box< ITV > &  y 
)
related

Returns true if and only if x and y are not the same box.

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

Definition at line 264 of file Box_inlines.hh.

264  {
265  return !(x == y);
266 }
template<typename ITV >
std::ostream & operator<< ( std::ostream &  s,
const Box< ITV > &  box 
)
related

Output operator.

template<typename ITV >
std::ostream & operator<< ( std::ostream &  s,
const Box< ITV > &  box 
)
related

Definition at line 4389 of file Box_templates.hh.

4389  {
4390  if (box.is_empty()) {
4391  s << "false";
4392  }
4393  else if (box.is_universe()) {
4394  s << "true";
4395  }
4396  else {
4397  for (dimension_type k = 0,
4398  space_dim = box.space_dimension(); k < space_dim; ) {
4399  s << Variable(k) << " in " << box[k];
4400  ++k;
4401  if (k < space_dim) {
4402  s << ", ";
4403  }
4404  else {
4405  break;
4406  }
4407  }
4408  }
4409  return s;
4410 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
template<typename ITV >
bool operator== ( const Box< ITV > &  x,
const Box< ITV > &  y 
)
related

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 581 of file Box_templates.hh.

581  {
582  const dimension_type x_space_dim = x.space_dimension();
583  if (x_space_dim != y.space_dimension()) {
584  return false;
585  }
586 
587  if (x.is_empty()) {
588  return y.is_empty();
589  }
590 
591  if (y.is_empty()) {
592  return x.is_empty();
593  }
594 
595  for (dimension_type k = x_space_dim; k-- > 0; ) {
596  if (x.seq[k] != y.seq[k]) {
597  return false;
598  }
599  }
600  return true;
601 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
template<typename ITV>
bool operator== ( const Box< ITV > &  x,
const Box< ITV > &  y 
)
friend

Definition at line 581 of file Box_templates.hh.

581  {
582  const dimension_type x_space_dim = x.space_dimension();
583  if (x_space_dim != y.space_dimension()) {
584  return false;
585  }
586 
587  if (x.is_empty()) {
588  return y.is_empty();
589  }
590 
591  if (y.is_empty()) {
592  return x.is_empty();
593  }
594 
595  for (dimension_type k = x_space_dim; k-- > 0; ) {
596  if (x.seq[k] != y.seq[k]) {
597  return false;
598  }
599  }
600  return true;
601 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
template<typename ITV>
template<typename Other_ITV >
friend class Parma_Polyhedra_Library::Box
friend

Definition at line 1739 of file Box_defs.hh.

template<typename ITV>
std::ostream& Parma_Polyhedra_Library::IO_Operators::operator<< ( std::ostream &  s,
const Box< ITV > &  box 
)
friend
template<typename ITV>
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 
)
friend
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 
)
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>.

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 
)
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<Temp, Extended_Number_Policy>.

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

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,
const Rounding_Dir  dir,
Temp &  tmp0,
Temp &  tmp1,
Temp &  tmp2 
)
related

Definition at line 583 of file Box_inlines.hh.

589  {
590  return l_m_distance_assign<Rectilinear_Distance_Specialization<Temp> >
591  (r, x, y, dir, tmp0, tmp1, tmp2);
592 }
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,
const Rounding_Dir  dir 
)
related

Definition at line 597 of file Box_inlines.hh.

References PPL_DIRTY_TEMP.

600  {
601  typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
602  PPL_DIRTY_TEMP(Checked_Temp, tmp0);
603  PPL_DIRTY_TEMP(Checked_Temp, tmp1);
604  PPL_DIRTY_TEMP(Checked_Temp, tmp2);
605  return rectilinear_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
606 }
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.
#define PPL_DIRTY_TEMP(T, id)
template<typename To , typename ITV >
bool rectilinear_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const Box< ITV > &  x,
const Box< ITV > &  y,
const Rounding_Dir  dir 
)
related

Definition at line 611 of file Box_inlines.hh.

614  {
615  // FIXME: the following qualification is only to work around a bug
616  // in the Intel C/C++ compiler version 10.1.x.
617  return Parma_Polyhedra_Library
618  ::rectilinear_distance_assign<To, To, ITV>(r, x, y, dir);
619 }
template<typename ITV >
void swap ( Box< ITV > &  x,
Box< ITV > &  y 
)
related

Swaps x with y.

template<typename ITV >
void swap ( Box< ITV > &  x,
Box< ITV > &  y 
)
related

Definition at line 706 of file Box_inlines.hh.

References Parma_Polyhedra_Library::Box< ITV >::m_swap().

706  {
707  x.m_swap(y);
708 }

Member Data Documentation

template<typename ITV>
Status Parma_Polyhedra_Library::Box< ITV >::status
private

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