Parma_Polyhedra_Library::Box< ITV > Class Template Reference
[C++ Language Interface]

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

#include <Box.defs.hh>

Collaboration diagram for Parma_Polyhedra_Library::Box< ITV >:
Collaboration graph
[legend]

List of all members.

Classes

class  Status

Public Types

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

Public Member Functions

const ITV & get_interval (Variable var) const
 Returns a reference the interval that bounds var.
void set_interval (Variable var, const ITV &i)
 Sets to i the interval that bounds var.
bool get_lower_bound (dimension_type k, bool &closed, Coefficient &n, Coefficient &d) const
 If the k-th space dimension is unbounded below, returns false. Otherwise returns true and set closed, n and d accordingly.
bool get_upper_bound (dimension_type k, bool &closed, Coefficient &n, Coefficient &d) const
 If the k-th space dimension is unbounded above, returns false. Otherwise returns true and set closed, n and d accordingly.
Constraint_System constraints () const
 Returns a system of constraints defining *this.
Constraint_System minimized_constraints () const
 Returns a minimized system of constraints defining *this.
Congruence_System congruences () const
 Returns a system of congruences approximating *this.
Congruence_System minimized_congruences () const
 Returns a minimized system of congruences approximating *this.
memory_size_type total_memory_in_bytes () const
 Returns the total size in bytes of the memory occupied by *this.
memory_size_type external_memory_in_bytes () const
 Returns the size in bytes of the memory managed by *this.
void ascii_dump () const
 Writes to std::cerr an ASCII representation of *this.
void ascii_dump (std::ostream &s) const
 Writes to s an ASCII representation of *this.
void print () const
 Prints *this to std::cerr using operator<<.
bool ascii_load (std::istream &s)
 Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this accordingly. Returns true if successful, false otherwise.
void set_empty ()
 Causes the box to become empty, i.e., to represent the empty set.
Constructors, Assignment, Swap and Destructor

 Box (dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
 Builds a universe or empty box of the specified space dimension.
 Box (const Box &y, Complexity_Class complexity=ANY_COMPLEXITY)
 Ordinary copy constructor.
template<typename Other_ITV >
 Box (const Box< Other_ITV > &y, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds a conservative, upward approximation of y.
 Box (const Constraint_System &cs)
 Builds a box from the system of constraints cs.
 Box (const Constraint_System &cs, Recycle_Input dummy)
 Builds a box recycling a system of constraints cs.
 Box (const Generator_System &gs)
 Builds a box from the system of generators gs.
 Box (const Generator_System &gs, Recycle_Input dummy)
 Builds a box recycling the system of generators gs.
 Box (const Congruence_System &cgs)
 Box (const Congruence_System &cgs, Recycle_Input dummy)
template<typename T >
 Box (const BD_Shape< T > &bds, Complexity_Class complexity=POLYNOMIAL_COMPLEXITY)
 Builds a box containing the BDS bds.
template<typename T >
 Box (const Octagonal_Shape< T > &oct, Complexity_Class complexity=POLYNOMIAL_COMPLEXITY)
 Builds a box containing the octagonal shape oct.
 Box (const Polyhedron &ph, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds a box containing the polyhedron ph.
 Box (const Grid &ph, Complexity_Class complexity=POLYNOMIAL_COMPLEXITY)
 Builds a box containing the grid gr.
template<typename D1 , typename D2 , typename R >
 Box (const Partially_Reduced_Product< D1, D2, R > &dp, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds a box containing the partially reduced product dp.
Boxoperator= (const Box &y)
 The assignment operator (*this and y can be dimension-incompatible).
void swap (Box &y)
 Swaps *this with y (*this and y can be dimension-incompatible).
Member Functions that Do Not Modify the Box

dimension_type space_dimension () const
 Returns the dimension of the vector space enclosing *this.
dimension_type affine_dimension () const
 Returns $0$, if *this is empty; otherwise, returns the affine dimension of *this.
bool is_empty () const
 Returns true if and only if *this is an empty box.
bool is_universe () const
 Returns true if and only if *this is a universe box.
bool is_topologically_closed () const
 Returns true if and only if *this is a topologically closed subset of the vector space.
bool is_discrete () const
 Returns true if and only if *this is discrete.
bool is_bounded () const
 Returns true if and only if *this is a bounded box.
bool contains_integer_point () const
 Returns true if and only if *this contains at least one integer point.
bool constrains (Variable var) const
 Returns true if and only if var is constrained in *this.
Poly_Con_Relation relation_with (const Constraint &c) const
 Returns the relations holding between *this and the constraint c.
Poly_Con_Relation relation_with (const Congruence &cg) const
 Returns the relations holding between *this and the congruence cg.
Poly_Gen_Relation relation_with (const Generator &g) const
 Returns the relations holding between *this and the generator g.
bool bounds_from_above (const Linear_Expression &expr) const
 Returns true if and only if expr is bounded from above in *this.
bool bounds_from_below (const Linear_Expression &expr) const
 Returns true if and only if expr is bounded from below in *this.
bool maximize (const Linear_Expression &expr, Coefficient &sup_n, Coefficient &sup_d, bool &maximum) const
 Returns true if and only if *this is not empty and expr is bounded from above in *this, in which case the supremum value is computed.
bool maximize (const Linear_Expression &expr, Coefficient &sup_n, Coefficient &sup_d, bool &maximum, Generator &g) const
 Returns true if and only if *this is not empty and expr is bounded from above in *this, in which case the supremum value and a point where expr reaches it are computed.
bool minimize (const Linear_Expression &expr, Coefficient &inf_n, Coefficient &inf_d, bool &minimum) const
 Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value is computed.
bool minimize (const Linear_Expression &expr, Coefficient &inf_n, Coefficient &inf_d, bool &minimum, Generator &g) const
 Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value and a point where expr reaches it are computed.
bool frequency (const Linear_Expression &expr, Coefficient &freq_n, Coefficient &freq_d, Coefficient &val_n, Coefficient &val_d) const
 Returns true if and only if there exist a unique value val such that *this saturates the equality expr = val.
bool contains (const Box &y) const
 Returns true if and only if *this contains y.
bool strictly_contains (const Box &y) const
 Returns true if and only if *this strictly contains y.
bool is_disjoint_from (const Box &y) const
 Returns true if and only if *this and y are disjoint.
bool OK () const
 Returns true if and only if *this satisfies all its invariants.
Space-Dimension Preserving Member Functions that May Modify the Box

void add_constraint (const Constraint &c)
 Adds a copy of constraint c to the system of constraints defining *this.
void add_constraints (const Constraint_System &cs)
 Adds the constraints in cs to the system of constraints defining *this.
void add_recycled_constraints (Constraint_System &cs)
 Adds the constraints in cs to the system of constraints defining *this.
void add_congruence (const Congruence &cg)
 Adds to *this a constraint equivalent to the congruence cg.
void add_congruences (const Congruence_System &cgs)
 Adds to *this constraints equivalent to the congruences in cgs.
void add_recycled_congruences (Congruence_System &cgs)
 Adds to *this constraints equivalent to the congruences in cgs.
void refine_with_constraint (const Constraint &c)
 Use the constraint c to refine *this.
void refine_with_constraints (const Constraint_System &cs)
 Use the constraints in cs to refine *this.
void refine_with_congruence (const Congruence &cg)
 Use the congruence cg to refine *this.
void refine_with_congruences (const Congruence_System &cgs)
 Use the congruences in cgs to refine *this.
void propagate_constraint (const Constraint &c)
 Use the constraint c for constraint propagation on *this.
void propagate_constraints (const Constraint_System &cs, dimension_type max_iterations=0)
 Use the constraints in cs for constraint propagagion on *this.
void unconstrain (Variable var)
 Computes the cylindrification of *this with respect to space dimension var, assigning the result to *this.
void unconstrain (const Variables_Set &vars)
 Computes the cylindrification of *this with respect to the set of space dimensions vars, assigning the result to *this.
void intersection_assign (const Box &y)
 Assigns to *this the intersection of *this and y.
void upper_bound_assign (const Box &y)
 Assigns to *this the smallest box containing the union of *this and y.
bool upper_bound_assign_if_exact (const Box &y)
 If the upper bound of *this and y is exact, it is assigned to *this and true is returned, otherwise false is returned.
void difference_assign (const Box &y)
 Assigns to *this the difference of *this and y.
bool simplify_using_context_assign (const Box &y)
 Assigns to *this a meet-preserving simplification of *this with respect to y. If false is returned, then the intersection is empty.
void affine_image (Variable var, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the affine image of *this under the function mapping variable var to the affine expression specified by expr and denominator.
void affine_preimage (Variable var, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the affine preimage of *this under the function mapping variable var to the affine expression specified by expr and denominator.
void generalized_affine_image (Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the image of *this with respect to the generalized affine relation $\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym.
void generalized_affine_preimage (Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the preimage of *this with respect to the generalized affine relation $\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym.
void generalized_affine_image (const Linear_Expression &lhs, Relation_Symbol relsym, const Linear_Expression &rhs)
 Assigns to *this the image of *this with respect to the generalized affine relation $\mathrm{lhs}' \relsym \mathrm{rhs}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym.
void generalized_affine_preimage (const Linear_Expression &lhs, Relation_Symbol relsym, const Linear_Expression &rhs)
 Assigns to *this the preimage of *this with respect to the generalized affine relation $\mathrm{lhs}' \relsym \mathrm{rhs}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym.
void bounded_affine_image (Variable var, const Linear_Expression &lb_expr, const Linear_Expression &ub_expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the image of *this with respect to the bounded affine relation $\frac{\mathrm{lb\_expr}}{\mathrm{denominator}} \leq \mathrm{var}' \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}$.
void bounded_affine_preimage (Variable var, const Linear_Expression &lb_expr, const Linear_Expression &ub_expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the preimage of *this with respect to the bounded affine relation $\frac{\mathrm{lb\_expr}}{\mathrm{denominator}} \leq \mathrm{var}' \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}$.
void time_elapse_assign (const Box &y)
 Assigns to *this the result of computing the time-elapse between *this and y.
void topological_closure_assign ()
 Assigns to *this its topological closure.
void wrap_assign (const Variables_Set &vars, Bounded_Integer_Type_Width w, Bounded_Integer_Type_Representation r, Bounded_Integer_Type_Overflow o, const Constraint_System *pcs=0, unsigned complexity_threshold=16, bool wrap_individually=true)
 Wraps the specified dimensions of the vector space.
void drop_some_non_integer_points (Complexity_Class complexity=ANY_COMPLEXITY)
 Possibly tightens *this by dropping some points with non-integer coordinates.
void drop_some_non_integer_points (const Variables_Set &vars, Complexity_Class complexity=ANY_COMPLEXITY)
 Possibly tightens *this by dropping some points with non-integer coordinates for the space dimensions corresponding to vars.
template<typename T >
Enable_If< Is_Same< T, Box >
::value &&Is_Same_Or_Derived
< Interval_Base, ITV >::value,
void >::type 
CC76_widening_assign (const T &y, unsigned *tp=0)
 Assigns to *this the result of computing the CC76-widening between *this and y.
template<typename T , typename Iterator >
Enable_If< Is_Same< T, Box >
::value &&Is_Same_Or_Derived
< Interval_Base, ITV >::value,
void >::type 
CC76_widening_assign (const T &y, Iterator first, Iterator last)
 Assigns to *this the result of computing the CC76-widening between *this and y.
void widening_assign (const Box &y, unsigned *tp=0)
 Same as CC76_widening_assign(y, tp).
void limited_CC76_extrapolation_assign (const Box &y, const Constraint_System &cs, unsigned *tp=0)
 Improves the result of the CC76-extrapolation computation by also enforcing those constraints in cs that are satisfied by all the points of *this.
template<typename T >
Enable_If< Is_Same< T, Box >
::value &&Is_Same_Or_Derived
< Interval_Base, ITV >::value,
void >::type 
CC76_narrowing_assign (const T &y)
 Assigns to *this the result of restoring in y the constraints of *this that were lost by CC76-extrapolation applications.
Member Functions that May Modify the Dimension of the Vector Space

void add_space_dimensions_and_embed (dimension_type m)
 Adds m new dimensions and embeds the old box into the new space.
void add_space_dimensions_and_project (dimension_type m)
 Adds m new dimensions to the box and does not embed it in the new vector space.
void concatenate_assign (const Box &y)
 Seeing a box as a set of tuples (its points), assigns to *this all the tuples that can be obtained by concatenating, in the order given, a tuple of *this with a tuple of y.
void remove_space_dimensions (const Variables_Set &vars)
 Removes all the specified dimensions.
void remove_higher_space_dimensions (dimension_type new_dimension)
 Removes the higher dimensions so that the resulting space will have dimension new_dimension.
template<typename Partial_Function >
void map_space_dimensions (const Partial_Function &pfunc)
 Remaps the dimensions of the vector space according to a partial function.
void expand_space_dimension (Variable var, dimension_type m)
 Creates m copies of the space dimension corresponding to var.
void fold_space_dimensions (const Variables_Set &vars, Variable dest)
 Folds the space dimensions in vars into dest.

Static Public Member Functions

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

Private Types

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

Private Member Functions

bool marked_empty () const
 Returns true if and only if the box is known to be empty.
void set_nonempty ()
 Marks *this as definitely not empty.
void set_empty_up_to_date ()
 Asserts the validity of the empty flag of *this.
void reset_empty_up_to_date ()
 Invalidates empty flag of *this.
bool check_empty () const
 Checks the hard way whether *this is an empty box: returns true if and only if it is so.
const ITV & operator[] (dimension_type k) const
 Returns a reference the interval that bounds the box on the k-th space dimension.
void add_interval_constraint_no_check (dimension_type var_id, Constraint::Type type, Coefficient_traits::const_reference num, Coefficient_traits::const_reference den)
 WRITE ME.
void add_constraint_no_check (const Constraint &c)
 WRITE ME.
void add_constraints_no_check (const Constraint_System &cs)
 WRITE ME.
void add_congruence_no_check (const Congruence &cg)
 WRITE ME.
void add_congruences_no_check (const Congruence_System &cgs)
 WRITE ME.
void refine_no_check (const Constraint &c)
 Uses the constraint c to refine *this.
void refine_no_check (const Constraint_System &cs)
 Uses the constraints in cs to refine *this.
void refine_no_check (const Congruence &cg)
 Uses the congruence cg to refine *this.
void refine_no_check (const Congruence_System &cgs)
 Uses the congruences in cgs to refine *this.
void propagate_constraint_no_check (const Constraint &c)
 Propagates the constraint c to refine *this.
void propagate_constraints_no_check (const Constraint_System &cs, dimension_type max_iterations)
 Propagates the constraints in cs to refine *this.
bool bounds (const Linear_Expression &expr, bool from_above) const
 Checks if and how expr is bounded in *this.
bool max_min (const Linear_Expression &expr, bool maximize, Coefficient &ext_n, Coefficient &ext_d, bool &included, Generator &g) const
 Maximizes or minimizes expr subject to *this.
bool max_min (const Linear_Expression &expr, bool maximize, Coefficient &ext_n, Coefficient &ext_d, bool &included) const
 Maximizes or minimizes expr subject to *this.
void get_limiting_box (const Constraint_System &cs, Box &limiting_box) const
 Adds to limiting_box the interval constraints in cs that are satisfied by *this.

Static Private Member Functions

static I_Result refine_interval_no_check (ITV &itv, Constraint::Type type, Coefficient_traits::const_reference num, Coefficient_traits::const_reference den)
 WRITE ME.

Private Attributes

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

Friends

class Parma_Polyhedra_Library::Box
bool operator== (const Box< ITV > &x, const Box< ITV > &y)
 Returns true if and only if x and y are the same box.
std::ostream & Parma_Polyhedra_Library::IO_Operators::operator<< (std::ostream &s, const Box< ITV > &box)
template<typename Specialization , typename Temp , typename To , typename I >
bool Parma_Polyhedra_Library::l_m_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Box< I > &x, const Box< I > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)

Related Functions

(Note that these are not member functions.)



template<typename ITV >
bool operator!= (const Box< ITV > &x, const Box< ITV > &y)
 Returns true if and only if x and y aren't the same box.
template<typename ITV >
std::ostream & operator<< (std::ostream &s, const Box< ITV > &box)
 Output operator.
template<typename To , typename ITV >
bool rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Box< ITV > &x, const Box< ITV > &y, Rounding_Dir dir)
 Computes the rectilinear (or Manhattan) distance between x and y.
template<typename Temp , typename To , typename ITV >
bool rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Box< ITV > &x, const Box< ITV > &y, Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
 Computes the rectilinear (or Manhattan) distance between x and y.
template<typename To , typename ITV >
bool euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Box< ITV > &x, const Box< ITV > &y, Rounding_Dir dir)
 Computes the euclidean distance between x and y.
template<typename Temp , typename To , typename ITV >
bool euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Box< ITV > &x, const Box< ITV > &y, Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
 Computes the euclidean distance between x and y.
template<typename To , typename ITV >
bool l_infinity_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Box< ITV > &x, const Box< ITV > &y, Rounding_Dir dir)
 Computes the $L_\infty$ distance between x and y.
template<typename Temp , typename To , typename ITV >
bool l_infinity_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Box< ITV > &x, const Box< ITV > &y, Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
 Computes the $L_\infty$ distance between x and y.
template<typename Specialization , typename Temp , typename To , typename ITV >
bool l_m_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Box< ITV > &x, const Box< ITV > &y, Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
bool extract_interval_constraint (const Constraint &c, dimension_type c_space_dim, dimension_type &c_num_vars, dimension_type &c_only_var)
 Decodes the constraint c as an interval constraint.

Exception Throwers



void throw_dimension_incompatible (const char *method, const Box &x) const
void throw_dimension_incompatible (const char *method, dimension_type required_dim) const
void throw_dimension_incompatible (const char *method, const Constraint &c) const
void throw_dimension_incompatible (const char *method, const Congruence &cg) const
void throw_dimension_incompatible (const char *method, const Constraint_System &cs) const
void throw_dimension_incompatible (const char *method, const Congruence_System &cgs) const
void throw_dimension_incompatible (const char *method, const Generator &g) const
void throw_dimension_incompatible (const char *method, const char *name_row, const Linear_Expression &y) const
static void throw_space_dimension_overflow (const char *method, const char *reason)
static void throw_constraint_incompatible (const char *method)
static void throw_expression_too_complex (const char *method, const Linear_Expression &e)
static void throw_generic (const char *method, const char *reason)

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:

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

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

Definition at line 292 of file Box.defs.hh.


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 295 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 1693 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 1699 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 
) [inline, explicit]

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

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

Definition at line 48 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::set_empty_up_to_date(), and Parma_Polyhedra_Library::UNIVERSE.

00049   : seq(num_dimensions <= max_space_dimension()
00050         ? num_dimensions
00051         : (throw_space_dimension_overflow("Box(n, k)",
00052                                           "n exceeds the maximum "
00053                                           "allowed space dimension"),
00054            num_dimensions)),
00055     status() {
00056   // In a box that is marked empty the intervals are completely
00057   // meaningless: we exploit this by avoiding their initialization.
00058   if (kind == UNIVERSE) {
00059     for (dimension_type i = num_dimensions; i-- > 0; )
00060       seq[i].assign(UNIVERSE);
00061     set_empty_up_to_date();
00062   }
00063   else
00064     set_empty();
00065   PPL_ASSERT(OK());
00066 }

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.

00071   : seq(y.seq), status(y.status) {
00072 }

template<typename ITV >
template<typename Other_ITV >
Parma_Polyhedra_Library::Box< ITV >::Box ( const Box< Other_ITV > &  y,
Complexity_Class  complexity = ANY_COMPLEXITY 
) [inline, explicit]

Builds a conservative, upward approximation of y.

The complexity argument is ignored.

Definition at line 103 of file Box.templates.hh.

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

00104   : seq(y.space_dimension()),
00105     // FIXME: why the following does not work?
00106     // status(y.status) {
00107     status() {
00108   // FIXME: remove when the above is fixed.
00109   if (y.marked_empty())
00110     set_empty();
00111 
00112   if (!y.marked_empty())
00113     for (dimension_type k = y.space_dimension(); k-- > 0; )
00114       seq[k].assign(y.seq[k]);
00115   PPL_ASSERT(OK());
00116 }

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

Builds a box from the system of constraints cs.

The box inherits the space dimension of cs.

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

Definition at line 70 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::add_constraints_no_check(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Constraint_System::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.

00071   : seq(cs.space_dimension() <= max_space_dimension()
00072         ? cs.space_dimension()
00073         : (throw_space_dimension_overflow("Box(cs)",
00074                                           "cs exceeds the maximum "
00075                                           "allowed space dimension"),
00076            cs.space_dimension())),
00077     status() {
00078   // FIXME: check whether we can avoid the double initialization.
00079   for (dimension_type i = cs.space_dimension(); i-- > 0; )
00080     seq[i].assign(UNIVERSE);
00081   add_constraints_no_check(cs);
00082 }

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:
cs A system of constraints: constraints that are not interval constraints are ignored (even though they may have contributed to the space dimension).
dummy A dummy tag to syntactically differentiate this one from the other constructors.

Definition at line 92 of file Box.inlines.hh.

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

00092                                                         {
00093   // Recycling is useless: just delegate.
00094   Box<ITV> tmp(cs);
00095   this->swap(tmp);
00096 }

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

Builds a box from the system of generators gs.

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

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

Definition at line 119 of file Box.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Generator_System::begin(), Parma_Polyhedra_Library::Generator::CLOSURE_POINT, Parma_Polyhedra_Library::Generator::coefficient(), Parma_Polyhedra_Library::Generator::divisor(), Parma_Polyhedra_Library::Generator_System::end(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Generator::is_point(), Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::Generator::LINE, Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Generator::RAY, Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::set_empty_up_to_date(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Generator::type(), and Parma_Polyhedra_Library::UNIVERSE.

00120   : seq(gs.space_dimension() <= max_space_dimension()
00121         ? gs.space_dimension()
00122         : (throw_space_dimension_overflow("Box(gs)",
00123                                           "gs exceeds the maximum "
00124                                           "allowed space dimension"),
00125            gs.space_dimension())),
00126     status() {
00127   const Generator_System::const_iterator gs_begin = gs.begin();
00128   const Generator_System::const_iterator gs_end = gs.end();
00129   if (gs_begin == gs_end) {
00130     // An empty generator system defines the empty box.
00131     set_empty();
00132     return;
00133   }
00134 
00135   // The empty flag will be meaningful, whatever happens from now on.
00136   set_empty_up_to_date();
00137 
00138   const dimension_type space_dim = space_dimension();
00139   PPL_DIRTY_TEMP(mpq_class, q);
00140   bool point_seen = false;
00141   // Going through all the points.
00142   for (Generator_System::const_iterator
00143          gs_i = gs_begin; gs_i != gs_end; ++gs_i) {
00144     const Generator& g = *gs_i;
00145     if (g.is_point()) {
00146       const Coefficient& d = g.divisor();
00147       if (point_seen) {
00148         // This is not the first point: `seq' already contains valid values.
00149         for (dimension_type i = space_dim; i-- > 0; ) {
00150           assign_r(q.get_num(), g.coefficient(Variable(i)), ROUND_NOT_NEEDED);
00151           assign_r(q.get_den(), d, ROUND_NOT_NEEDED);
00152           q.canonicalize();
00153           PPL_DIRTY_TEMP(ITV, iq);
00154           iq.build(i_constraint(EQUAL, q));
00155           seq[i].join_assign(iq);
00156         }
00157       }
00158       else {
00159         // This is the first point seen: initialize `seq'.
00160         point_seen = true;
00161         for (dimension_type i = space_dim; i-- > 0; ) {
00162           assign_r(q.get_num(), g.coefficient(Variable(i)), ROUND_NOT_NEEDED);
00163           assign_r(q.get_den(), d, ROUND_NOT_NEEDED);
00164           q.canonicalize();
00165           seq[i].build(i_constraint(EQUAL, q));
00166         }
00167       }
00168     }
00169   }
00170 
00171   if (!point_seen)
00172     // The generator system is not empty, but contains no points.
00173     throw std::invalid_argument("PPL::Box<ITV>::Box(gs):\n"
00174                                 "the non-empty generator system gs "
00175                                 "contains no points.");
00176 
00177   // Going through all the lines, rays and closure points.
00178   ITV q_interval;
00179   for (Generator_System::const_iterator gs_i = gs_begin;
00180        gs_i != gs_end; ++gs_i) {
00181     const Generator& g = *gs_i;
00182     switch (g.type()) {
00183     case Generator::LINE:
00184       for (dimension_type i = space_dim; i-- > 0; )
00185         if (g.coefficient(Variable(i)) != 0)
00186           seq[i].assign(UNIVERSE);
00187       break;
00188     case Generator::RAY:
00189       for (dimension_type i = space_dim; i-- > 0; )
00190         switch (sgn(g.coefficient(Variable(i)))) {
00191         case 1:
00192           seq[i].upper_extend();
00193           break;
00194         case -1:
00195           seq[i].lower_extend();
00196           break;
00197         default:
00198           break;
00199         }
00200       break;
00201     case Generator::CLOSURE_POINT:
00202       {
00203         const Coefficient& d = g.divisor();
00204         for (dimension_type i = space_dim; i-- > 0; ) {
00205           assign_r(q.get_num(), g.coefficient(Variable(i)), ROUND_NOT_NEEDED);
00206           assign_r(q.get_den(), d, ROUND_NOT_NEEDED);
00207           q.canonicalize();
00208           ITV& seq_i = seq[i];
00209           seq_i.lower_extend(i_constraint(GREATER_THAN, q));
00210           seq_i.upper_extend(i_constraint(LESS_THAN, q));
00211         }
00212       }
00213       break;
00214     default:
00215       // Points already dealt with.
00216       break;
00217     }
00218   }
00219   PPL_ASSERT(OK());
00220 }

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:
gs The generator system describing the polyhedron to be approximated.
dummy A dummy tag to syntactically differentiate this one from the other constructors.
Exceptions:
std::invalid_argument Thrown if the system of generators is not empty but has no points.

Definition at line 100 of file Box.inlines.hh.

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

00100                                                        {
00101   // Recycling is useless: just delegate.
00102   Box<ITV> tmp(gs);
00103   this->swap(tmp);
00104 }

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

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

Parameters:
cgs A system of congruences: congruences that are not non-relational equality constraints are ignored (though they may have contributed to the space dimension).

Definition at line 86 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::add_congruences_no_check(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Congruence_System::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.

00087   : seq(cgs.space_dimension() <= max_space_dimension()
00088         ? cgs.space_dimension()
00089         : (throw_space_dimension_overflow("Box(cgs)",
00090                                           "cgs exceeds the maximum "
00091                                           "allowed space dimension"),
00092            cgs.space_dimension())),
00093     status() {
00094   // FIXME: check whether we can avoid the double initialization.
00095   for (dimension_type i = cgs.space_dimension(); i-- > 0; )
00096     seq[i].assign(UNIVERSE);
00097   add_congruences_no_check(cgs);
00098 }

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:
cgs A system of congruences: congruences that are not non-relational equality constraints are ignored (though they will contribute to the space dimension).
dummy A dummy tag to syntactically differentiate this one from the other constructors.

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

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

00108                                                          {
00109   // Recycling is useless: just delegate.
00110   Box<ITV> tmp(cgs);
00111   this->swap(tmp);
00112 }

template<typename ITV >
template<typename T >
Parma_Polyhedra_Library::Box< ITV >::Box ( const BD_Shape< T > &  bds,
Complexity_Class  complexity = POLYNOMIAL_COMPLEXITY 
) [inline, explicit]

Builds a box containing the BDS bds.

Builds the smallest box containing bds using a polynomial algorithm. The complexity argument is ignored.

Definition at line 224 of file Box.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::set_empty_up_to_date(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), and Parma_Polyhedra_Library::Box< ITV >::space_dimension().

00225   : seq(bds.space_dimension() <= max_space_dimension()
00226         ? bds.space_dimension()
00227         : (throw_space_dimension_overflow("Box(bds)",
00228                                           "bds exceeds the maximum "
00229                                           "allowed space dimension"),
00230            bds.space_dimension())),
00231     status() {
00232   // Expose all the interval constraints.
00233   bds.shortest_path_closure_assign();
00234   if (bds.marked_empty()) {
00235     set_empty();
00236     PPL_ASSERT(OK());
00237     return;
00238   }
00239 
00240   // The empty flag will be meaningful, whatever happens from now on.
00241   set_empty_up_to_date();
00242 
00243   const dimension_type space_dim = space_dimension();
00244   if (space_dim == 0) {
00245     PPL_ASSERT(OK());
00246     return;
00247   }
00248 
00249   typedef typename BD_Shape<T>::coefficient_type Coeff;
00250   PPL_DIRTY_TEMP(Coeff, tmp);
00251   const DB_Row<Coeff>& dbm_0 = bds.dbm[0];
00252   for (dimension_type i = space_dim; i-- > 0; ) {
00253     I_Constraint<Coeff> lower;
00254     I_Constraint<Coeff> upper;
00255     ITV& seq_i = seq[i];
00256 
00257     // Set the upper bound.
00258     const Coeff& u = dbm_0[i+1];
00259     if (!is_plus_infinity(u))
00260       upper.set(LESS_OR_EQUAL, u, true);
00261 
00262     // Set the lower bound.
00263     const Coeff& negated_l = bds.dbm[i+1][0];
00264     if (!is_plus_infinity(negated_l)) {
00265       neg_assign_r(tmp, negated_l, ROUND_DOWN);
00266       lower.set(GREATER_OR_EQUAL, tmp);
00267     }
00268 
00269     seq_i.build(lower, upper);
00270   }
00271   PPL_ASSERT(OK());
00272 }

template<typename ITV >
template<typename T >
Parma_Polyhedra_Library::Box< ITV >::Box ( const Octagonal_Shape< T > &  oct,
Complexity_Class  complexity = POLYNOMIAL_COMPLEXITY 
) [inline, explicit]

Builds a box containing the octagonal shape oct.

Builds the smallest box containing oct using a polynomial algorithm. The complexity argument is ignored.

Definition at line 276 of file Box.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::set_empty_up_to_date(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().

00277   : seq(oct.space_dimension() <= max_space_dimension()
00278         ? oct.space_dimension()
00279         : (throw_space_dimension_overflow("Box(oct)",
00280                                           "oct exceeds the maximum "
00281                                           "allowed space dimension"),
00282            oct.space_dimension())),
00283     status() {
00284   // Expose all the interval constraints.
00285   oct.strong_closure_assign();
00286   if (oct.marked_empty()) {
00287     set_empty();
00288     return;
00289   }
00290 
00291   // The empty flag will be meaningful, whatever happens from now on.
00292   set_empty_up_to_date();
00293 
00294   const dimension_type space_dim = space_dimension();
00295   if (space_dim == 0)
00296     return;
00297 
00298   PPL_DIRTY_TEMP0(mpq_class, lbound);
00299   PPL_DIRTY_TEMP0(mpq_class, ubound);
00300   for (dimension_type i = space_dim; i-- > 0; ) {
00301     typedef typename Octagonal_Shape<T>::coefficient_type Coeff;
00302     I_Constraint<mpq_class> lower;
00303     I_Constraint<mpq_class> upper;
00304     ITV& seq_i = seq[i];
00305     const dimension_type ii = 2*i;
00306     const dimension_type cii = ii + 1;
00307 
00308     // Set the upper bound.
00309     const Coeff& twice_ub = oct.matrix[cii][ii];
00310     if (!is_plus_infinity(twice_ub)) {
00311       assign_r(ubound, twice_ub, ROUND_NOT_NEEDED);
00312       div_2exp_assign_r(ubound, ubound, 1, ROUND_NOT_NEEDED);
00313       upper.set(LESS_OR_EQUAL, ubound);
00314     }
00315 
00316     // Set the lower bound.
00317     const Coeff& twice_lb = oct.matrix[ii][cii];
00318     if (!is_plus_infinity(twice_lb)) {
00319       assign_r(lbound, twice_lb, ROUND_NOT_NEEDED);
00320       neg_assign_r(lbound, lbound, ROUND_NOT_NEEDED);
00321       div_2exp_assign_r(lbound, lbound, 1, ROUND_NOT_NEEDED);
00322       lower.set(GREATER_OR_EQUAL, lbound);
00323     }
00324     seq_i.build(lower, upper);
00325   }
00326 }

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

Builds a box containing the polyhedron ph.

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

Definition at line 329 of file Box.templates.hh.

References Parma_Polyhedra_Library::MIP_Problem::add_constraint(), Parma_Polyhedra_Library::MIP_Problem::add_constraints(), Parma_Polyhedra_Library::ANY_COMPLEXITY, Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Polyhedron::constraints(), Parma_Polyhedra_Library::Polyhedron::constraints_are_up_to_date(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::MIP_Problem::evaluate_objective_function(), Parma_Polyhedra_Library::Polyhedron::generators(), Parma_Polyhedra_Library::Polyhedron::generators_are_up_to_date(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::Polyhedron::has_pending_constraints(), Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::is_canonical(), Parma_Polyhedra_Library::Polyhedron::is_empty(), Parma_Polyhedra_Library::MIP_Problem::is_satisfiable(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::Polyhedron::marked_empty(), Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::MINIMIZATION, Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, Parma_Polyhedra_Library::MIP_Problem::optimizing_point(), Parma_Polyhedra_Library::POLYNOMIAL_COMPLEXITY, Parma_Polyhedra_Library::Box< ITV >::propagate_constraints_no_check(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::set_empty_up_to_date(), Parma_Polyhedra_Library::MIP_Problem::set_objective_function(), Parma_Polyhedra_Library::MIP_Problem::set_optimization_mode(), Parma_Polyhedra_Library::SIMPLEX_COMPLEXITY, Parma_Polyhedra_Library::Polyhedron::simplified_constraints(), Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::Polyhedron::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::swap(), and Parma_Polyhedra_Library::UNIVERSE.

00330   : seq(ph.space_dimension() <= max_space_dimension()
00331         ? ph.space_dimension()
00332         : (throw_space_dimension_overflow("Box(ph)",
00333                                           "ph exceeds the maximum "
00334                                           "allowed space dimension"),
00335            ph.space_dimension())),
00336     status() {
00337   // The empty flag will be meaningful, whatever happens from now on.
00338   set_empty_up_to_date();
00339 
00340   // We do not need to bother about `complexity' if:
00341   // a) the polyhedron is already marked empty; or ...
00342   if (ph.marked_empty()) {
00343     set_empty();
00344     return;
00345   }
00346 
00347   // b) the polyhedron is zero-dimensional; or ...
00348   const dimension_type space_dim = ph.space_dimension();
00349   if (space_dim == 0)
00350     return;
00351 
00352   // c) the polyhedron is already described by a generator system.
00353   if (ph.generators_are_up_to_date() && !ph.has_pending_constraints()) {
00354     Box tmp(ph.generators());
00355     swap(tmp);
00356     return;
00357   }
00358 
00359   // Here generators are not up-to-date or there are pending constraints.
00360   PPL_ASSERT(ph.constraints_are_up_to_date());
00361 
00362   if (complexity == POLYNOMIAL_COMPLEXITY) {
00363     // FIXME: is there a way to avoid this initialization?
00364     for (dimension_type i = space_dim; i-- > 0; )
00365       seq[i].assign(UNIVERSE);
00366     // Get a simplified version of the constraints.
00367     Constraint_System cs = ph.simplified_constraints();
00368     // Propagate easy-to-find bounds from the constraints,
00369     // allowing for a limited number of iterations.
00370     // FIXME: 20 is just a wild guess.
00371     const dimension_type max_iterations = 20;
00372     propagate_constraints_no_check(cs, max_iterations);
00373   }
00374   else if (complexity == SIMPLEX_COMPLEXITY) {
00375     MIP_Problem lp(space_dim);
00376     const Constraint_System& ph_cs = ph.constraints();
00377     if (!ph_cs.has_strict_inequalities())
00378       lp.add_constraints(ph_cs);
00379     else
00380       // Adding to `lp' a topologically closed version of `ph_cs'.
00381       for (Constraint_System::const_iterator i = ph_cs.begin(),
00382              ph_cs_end = ph_cs.end(); i != ph_cs_end; ++i) {
00383         const Constraint& c = *i;
00384         if (c.is_strict_inequality())
00385           lp.add_constraint(Linear_Expression(c) >= 0);
00386         else
00387           lp.add_constraint(c);
00388       }
00389     // Check for unsatisfiability.
00390     if (!lp.is_satisfiable()) {
00391       set_empty();
00392       return;
00393     }
00394     // Get all the bounds for the space dimensions.
00395     Generator g(point());
00396     PPL_DIRTY_TEMP0(mpq_class, lbound);
00397     PPL_DIRTY_TEMP0(mpq_class, ubound);
00398     PPL_DIRTY_TEMP(Coefficient, bound_num);
00399     PPL_DIRTY_TEMP(Coefficient, bound_den);
00400     for (dimension_type i = space_dim; i-- > 0; ) {
00401       I_Constraint<mpq_class> lower;
00402       I_Constraint<mpq_class> upper;
00403       ITV& seq_i = seq[i];
00404       lp.set_objective_function(Variable(i));
00405       // Evaluate upper bound.
00406       lp.set_optimization_mode(MAXIMIZATION);
00407       if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
00408         g = lp.optimizing_point();
00409         lp.evaluate_objective_function(g, bound_num, bound_den);
00410         assign_r(ubound.get_num(), bound_num, ROUND_NOT_NEEDED);
00411         assign_r(ubound.get_den(), bound_den, ROUND_NOT_NEEDED);
00412         PPL_ASSERT(is_canonical(ubound));
00413         upper.set(LESS_OR_EQUAL, ubound);
00414       }
00415       // Evaluate optimal lower bound.
00416       lp.set_optimization_mode(MINIMIZATION);
00417       if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
00418         g = lp.optimizing_point();
00419         lp.evaluate_objective_function(g, bound_num, bound_den);
00420         assign_r(lbound.get_num(), bound_num, ROUND_NOT_NEEDED);
00421         assign_r(lbound.get_den(), bound_den, ROUND_NOT_NEEDED);
00422         PPL_ASSERT(is_canonical(lbound));
00423         lower.set(GREATER_OR_EQUAL, lbound);
00424       }
00425       seq_i.build(lower, upper);
00426     }
00427   }
00428   else {
00429     PPL_ASSERT(complexity == ANY_COMPLEXITY);
00430     if (ph.is_empty())
00431       set_empty();
00432     else {
00433       Box tmp(ph.generators());
00434       swap(tmp);
00435     }
00436   }
00437 }

template<typename ITV >
Parma_Polyhedra_Library::Box< ITV >::Box ( const Grid ph,
Complexity_Class  complexity = POLYNOMIAL_COMPLEXITY 
) [inline, explicit]

Builds a box containing the grid gr.

Builds the smallest box containing gr using a polynomial algorithm. The complexity argument is ignored.

Definition at line 440 of file Box.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Grid_Generator_System::empty(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::Grid::gen_sys, Parma_Polyhedra_Library::Grid::generators_are_up_to_date(), Parma_Polyhedra_Library::Grid::marked_empty(), Parma_Polyhedra_Library::Grid::maximize(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::set_empty_up_to_date(), Parma_Polyhedra_Library::Grid::space_dimension(), Parma_Polyhedra_Library::UNIVERSE, and Parma_Polyhedra_Library::Grid::update_generators().

00441   : seq(gr.space_dimension() <= max_space_dimension()
00442         ? gr.space_dimension()
00443         : (throw_space_dimension_overflow("Box(gr)",
00444                                           "gr exceeds the maximum "
00445                                           "allowed space dimension"),
00446            gr.space_dimension())),
00447     status() {
00448 
00449   // FIXME: here we are not taking advantage of intervals with restrictions!
00450 
00451   if (gr.marked_empty()) {
00452     set_empty();
00453     return;
00454   }
00455 
00456   // The empty flag will be meaningful, whatever happens from now on.
00457   set_empty_up_to_date();
00458 
00459   const dimension_type space_dim = gr.space_dimension();
00460 
00461   if (space_dim == 0)
00462     return;
00463 
00464   if (!gr.generators_are_up_to_date() && !gr.update_generators()) {
00465     // Updating found the grid empty.
00466     set_empty();
00467     return;
00468   }
00469 
00470   PPL_ASSERT(!gr.gen_sys.empty());
00471 
00472   // For each dimension that is bounded by the grid, set both bounds
00473   // of the interval to the value of the associated coefficient in a
00474   // generator point.
00475   PPL_DIRTY_TEMP0(mpq_class, bound);
00476   PPL_DIRTY_TEMP(Coefficient, bound_num);
00477   PPL_DIRTY_TEMP(Coefficient, bound_den);
00478   for (dimension_type i = space_dim; i-- > 0; ) {
00479     ITV& seq_i = seq[i];
00480     Variable var(i);
00481     bool max;
00482     if (gr.maximize(var, bound_num, bound_den, max)) {
00483       assign_r(bound.get_num(), bound_num, ROUND_NOT_NEEDED);
00484       assign_r(bound.get_den(), bound_den, ROUND_NOT_NEEDED);
00485       bound.canonicalize();
00486       seq_i.build(i_constraint(EQUAL, bound));
00487     }
00488     else
00489       seq_i.assign(UNIVERSE);
00490   }
00491 }

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 
) [inline, explicit]

Builds a box containing the partially reduced product dp.

Builds a box containing ph using algorithms whose complexity does not exceed the one specified by complexity.

Definition at line 495 of file Box.templates.hh.

References Parma_Polyhedra_Library::Partially_Reduced_Product< D1, D2, R >::domain1(), Parma_Polyhedra_Library::Partially_Reduced_Product< D1, D2, R >::domain2(), Parma_Polyhedra_Library::Box< ITV >::max_space_dimension(), Parma_Polyhedra_Library::Partially_Reduced_Product< D1, D2, R >::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::swap(), and Parma_Polyhedra_Library::Box< ITV >::throw_space_dimension_overflow().

00497   : seq(), status() {
00498   if (dp.space_dimension() > max_space_dimension())
00499     throw_space_dimension_overflow("Box(dp)",
00500                                    "dp exceeds the maximum "
00501                                    "allowed space dimension");
00502   Box tmp1(dp.domain1(), complexity);
00503   Box tmp2(dp.domain2(), complexity);
00504   tmp1.intersection_assign(tmp2);
00505   swap(tmp1);
00506 }


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:
cg The congruence to be added.
Exceptions:
std::invalid_argument Thrown if *this and congruence cg are dimension-incompatible, or cg is not optimally supported by the box domain.

Definition at line 327 of file Box.inlines.hh.

References Parma_Polyhedra_Library::Box< ITV >::add_congruence_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Congruence::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

00327                                              {
00328   const dimension_type cg_space_dim = cg.space_dimension();
00329   // Dimension-compatibility check.
00330   if (cg_space_dim > space_dimension())
00331     throw_dimension_incompatible("add_congruence(cg)", cg);
00332 
00333   add_congruence_no_check(cg);
00334 }

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::add_congruence_no_check ( const Congruence cg  )  [inline, private]

WRITE ME.

Definition at line 2170 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::add_interval_constraint_no_check(), Parma_Polyhedra_Library::Congruence::coefficient(), Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::extract_interval_congruence(), Parma_Polyhedra_Library::Congruence::inhomogeneous_term(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Congruence::is_proper_congruence(), Parma_Polyhedra_Library::Congruence::is_tautological(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Congruence::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_generic().

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

02170                                                       {
02171   const dimension_type cg_space_dim = cg.space_dimension();
02172   PPL_ASSERT(cg_space_dim <= space_dimension());
02173 
02174   // Set aside the case of proper congruences.
02175   if (cg.is_proper_congruence()) {
02176     if (cg.is_inconsistent()) {
02177       set_empty();
02178       return;
02179     }
02180     else if (cg.is_tautological())
02181       return;
02182     else
02183       // FIXME: what about intervals with restrictions?
02184       throw_generic("add_congruence(cg)",
02185                     "cg is a nontrivial proper congruence");
02186   }
02187 
02188   PPL_ASSERT(cg.is_equality());
02189   dimension_type cg_num_vars = 0;
02190   dimension_type cg_only_var = 0;
02191   // Throw an exception if c is not an interval congruence.
02192   if (!extract_interval_congruence(cg, cg_space_dim, cg_num_vars, cg_only_var))
02193     throw_generic("add_congruence(cg)", "cg is not an interval congruence");
02194 
02195   // Avoid doing useless work if the box is known to be empty.
02196   if (marked_empty())
02197     return;
02198 
02199   const Coefficient& n = cg.inhomogeneous_term();
02200   if (cg_num_vars == 0) {
02201     // Dealing with a trivial equality congruence.
02202     if (n != 0)
02203       set_empty();
02204     return;
02205   }
02206 
02207   PPL_ASSERT(cg_num_vars == 1);
02208   const Coefficient& d = cg.coefficient(Variable(cg_only_var));
02209   add_interval_constraint_no_check(cg_only_var, Constraint::EQUALITY, n, d);
02210 }

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:
cgs The congruences to be added.
Exceptions:
std::invalid_argument Thrown if *this and cgs are dimension-incompatible, or cgs contains a congruence which is not optimally supported by the box domain.

Definition at line 338 of file Box.inlines.hh.

References Parma_Polyhedra_Library::Box< ITV >::add_congruences_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Congruence_System::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

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

00338                                                       {
00339   if (cgs.space_dimension() > space_dimension())
00340     throw_dimension_incompatible("add_congruences(cgs)", cgs);
00341   add_congruences_no_check(cgs);
00342 }

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::add_congruences_no_check ( const Congruence_System cgs  )  [inline, private]

WRITE ME.

Definition at line 2214 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::add_congruence_no_check(), Parma_Polyhedra_Library::Congruence_System::begin(), Parma_Polyhedra_Library::Congruence_System::end(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Congruence_System::space_dimension().

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

02214                                                                {
02215   PPL_ASSERT(cgs.space_dimension() <= space_dimension());
02216   // Note: even when the box is known to be empty, we need to go
02217   // through all the congruences to fulfill the method's contract
02218   // for what concerns exception throwing.
02219   for (Congruence_System::const_iterator i = cgs.begin(),
02220          cgs_end = cgs.end(); i != cgs_end; ++i)
02221     add_congruence_no_check(*i);
02222   PPL_ASSERT(OK());
02223 }

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:
c The constraint to be added.
Exceptions:
std::invalid_argument Thrown if *this and constraint c are dimension-incompatible, or c is not optimally supported by the Box domain.

Definition at line 300 of file Box.inlines.hh.

References Parma_Polyhedra_Library::Box< ITV >::add_constraint_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

00300                                             {
00301   const dimension_type c_space_dim = c.space_dimension();
00302   // Dimension-compatibility check.
00303   if (c_space_dim > space_dimension())
00304     throw_dimension_incompatible("add_constraint(c)", c);
00305 
00306   add_constraint_no_check(c);
00307 }

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::add_constraint_no_check ( const Constraint c  )  [inline, private]

WRITE ME.

Definition at line 2120 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::add_interval_constraint_no_check(), Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Box< ITV >::extract_interval_constraint(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::throw_generic(), and Parma_Polyhedra_Library::Constraint::type().

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

02120                                                      {
02121   const dimension_type c_space_dim = c.space_dimension();
02122   PPL_ASSERT(c_space_dim <= space_dimension());
02123 
02124   dimension_type c_num_vars = 0;
02125   dimension_type c_only_var = 0;
02126   // Throw an exception if c is not an interval constraints.
02127   if (!extract_interval_constraint(c, c_space_dim, c_num_vars, c_only_var))
02128     throw_generic("add_constraint(c)", "c is not an interval constraint");
02129 
02130   // Throw an exception if c is a nontrivial strict constraint
02131   // and ITV does not support open boundaries.
02132   if (c.is_strict_inequality() && c_num_vars != 0
02133       && ITV::is_always_topologically_closed())
02134     throw_generic("add_constraint(c)", "c is a nontrivial strict constraint");
02135 
02136   // Avoid doing useless work if the box is known to be empty.
02137   if (marked_empty())
02138     return;
02139 
02140   const Coefficient& n = c.inhomogeneous_term();
02141   if (c_num_vars == 0) {
02142     // Dealing with a trivial constraint.
02143     if (n < 0
02144         || (c.is_equality() && n != 0)
02145         || (c.is_strict_inequality() && n == 0))
02146       set_empty();
02147     return;
02148   }
02149 
02150   PPL_ASSERT(c_num_vars == 1);
02151   const Coefficient& d = c.coefficient(Variable(c_only_var));
02152   add_interval_constraint_no_check(c_only_var, c.type(), n, d);
02153 }

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:
cs The constraints to be added.
Exceptions:
std::invalid_argument Thrown if *this and cs are dimension-incompatible, or cs contains a constraint which is not optimally supported by the box domain.

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

References Parma_Polyhedra_Library::Box< ITV >::add_constraints_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

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

00311                                                      {
00312   // Dimension-compatibility check.
00313   if (cs.space_dimension() > space_dimension())
00314     throw_dimension_incompatible("add_constraints(cs)", cs);
00315 
00316   add_constraints_no_check(cs);
00317 }

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::add_constraints_no_check ( const Constraint_System cs  )  [inline, private]

WRITE ME.

Definition at line 2157 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::add_constraint_no_check(), Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Constraint_System::space_dimension().

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

02157                                                               {
02158   PPL_ASSERT(cs.space_dimension() <= space_dimension());
02159   // Note: even when the box is known to be empty, we need to go
02160   // through all the constraints to fulfill the method's contract
02161   // for what concerns exception throwing.
02162   for (Constraint_System::const_iterator i = cs.begin(),
02163          cs_end = cs.end(); i != cs_end; ++i)
02164     add_constraint_no_check(*i);
02165   PPL_ASSERT(OK());
02166 }

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  num,
Coefficient_traits::const_reference  den 
) [inline, private]

WRITE ME.

Definition at line 421 of file Box.inlines.hh.

Referenced by Parma_Polyhedra_Library::Box< ITV >::add_congruence_no_check(), Parma_Polyhedra_Library::Box< ITV >::add_constraint_no_check(), Parma_Polyhedra_Library::Box< ITV >::get_limiting_box(), and Parma_Polyhedra_Library::Box< ITV >::refine_no_check().

00424                                                                           {
00425   PPL_ASSERT(!marked_empty());
00426   PPL_ASSERT(var_id < space_dimension());
00427   PPL_ASSERT(den != 0);
00428   refine_interval_no_check(seq[var_id], type, num, den);
00429   // FIXME: do check the value returned and set `empty' and
00430   // `empty_up_to_date' as appropriate.
00431   // This has to be done after reimplementation of intervals.
00432   reset_empty_up_to_date();
00433   PPL_ASSERT(OK());
00434 }

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:
cgs The congruence system to be added to *this. The congruences in cgs may be recycled.
Exceptions:
std::invalid_argument Thrown if *this and cgs are dimension-incompatible, or cgs contains a congruence which is not optimally supported by the 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 346 of file Box.inlines.hh.

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

00346                                                        {
00347   add_congruences(cgs);
00348 }

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:
cs The constraints to be added. They may be recycled.
Exceptions:
std::invalid_argument Thrown if *this and cs are dimension-incompatible, or cs contains a constraint which is not optimally supported by the 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 321 of file Box.inlines.hh.

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

00321                                                       {
00322   add_constraints(cs);
00323 }

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:
m The number of dimensions to add.

The new dimensions will be those having the highest indexes in the new box, which is defined by a system of interval constraints in which the variables running through the new dimensions are unconstrained. For instance, when starting from the box $\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 510 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, and Parma_Polyhedra_Library::UNIVERSE.

00510                                                                {
00511   // Adding no dimensions is a no-op.
00512   if (m == 0)
00513     return;
00514   // To embed an n-dimension space box in a (n+m)-dimension space,
00515   // we just add `m' new universe elements to the sequence.
00516   seq.insert(seq.end(), m, ITV(UNIVERSE));
00517   PPL_ASSERT(OK());
00518 }

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:
m The number of dimensions to add.

The new dimensions will be those having the highest indexes in the new box, which is defined by a system of bounded differences in which the variables running through the new dimensions are all constrained to be equal to 0. For instance, when starting from the box $\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 522 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::OK(), and Parma_Polyhedra_Library::Box< ITV >::seq.

00522                                                                  {
00523   // Adding no dimensions is a no-op.
00524   if (m == 0)
00525     return;
00526   // Add `m' new zero elements to the sequence.
00527   seq.insert(seq.end(), m, ITV(0));
00528   PPL_ASSERT(OK());
00529 }

template<typename ITV >
dimension_type Parma_Polyhedra_Library::Box< ITV >::affine_dimension (  )  const [inline]

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

Definition at line 1270 of file Box.templates.hh.

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

01270                                  {
01271   dimension_type d = space_dimension();
01272   // A zero-space-dim box always has affine dimension zero.
01273   if (d == 0)
01274     return 0;
01275 
01276   // An empty box has affine dimension zero.
01277   if (is_empty())
01278     return 0;
01279 
01280   for (dimension_type k = d; k-- > 0; )
01281     if (seq[k].is_singleton())
01282       --d;
01283 
01284   return d;
01285 }

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

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

Parameters:
var The variable to which the affine expression is assigned;
expr The numerator of the affine expression;
denominator The denominator of the affine expression (optional argument with default value 1).
Exceptions:
std::invalid_argument Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of *this.

Definition at line 2727 of file Box.templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Box< ITV >::throw_generic().

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

02729                                                                       {
02730   // The denominator cannot be zero.
02731   if (denominator == 0)
02732     throw_generic("affine_image(v, e, d)", "d == 0");
02733 
02734   // Dimension-compatibility checks.
02735   const dimension_type space_dim = space_dimension();
02736   const dimension_type expr_space_dim = expr.space_dimension();
02737   if (space_dim < expr_space_dim)
02738     throw_dimension_incompatible("affine_image(v, e, d)", "e", expr);
02739   // `var' should be one of the dimensions of the polyhedron.
02740   const dimension_type var_space_dim = var.space_dimension();
02741   if (space_dim < var_space_dim)
02742     throw_dimension_incompatible("affine_image(v, e, d)", "v", var);
02743 
02744   if (is_empty())
02745     return;
02746 
02747   Tmp_Interval_Type expr_value, temp0, temp1;
02748   expr_value.assign(expr.inhomogeneous_term());
02749   for (dimension_type i = expr_space_dim; i-- > 0; ) {
02750     const Coefficient& coeff = expr.coefficient(Variable(i));
02751     if (coeff != 0) {
02752       temp0.assign(coeff);
02753       temp1.assign(seq[i]);
02754       temp0.mul_assign(temp0, temp1);
02755       expr_value.add_assign(expr_value, temp0);
02756     }
02757   }
02758   if (denominator != 1) {
02759     temp0.assign(denominator);
02760     expr_value.div_assign(expr_value, temp0);
02761   }
02762   seq[var.id()].assign(expr_value);
02763 
02764   PPL_ASSERT(OK());
02765 }

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

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

Parameters:
var The variable to which the affine expression is substituted;
expr The numerator of the affine expression;
denominator The denominator of the affine expression (optional argument with default value 1).
Exceptions:
std::invalid_argument Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of *this.

Definition at line 2769 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::affine_image(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible(), Parma_Polyhedra_Library::Box< ITV >::throw_generic(), and Parma_Polyhedra_Library::UNIVERSE.

02772                                        {
02773   // The denominator cannot be zero.
02774   if (denominator == 0)
02775     throw_generic("affine_preimage(v, e, d)", "d == 0");
02776 
02777   // Dimension-compatibility checks.
02778   const dimension_type x_space_dim = space_dimension();
02779   const dimension_type expr_space_dim = expr.space_dimension();
02780   if (x_space_dim < expr_space_dim)
02781     throw_dimension_incompatible("affine_preimage(v, e, d)", "e", expr);
02782   // `var' should be one of the dimensions of the polyhedron.
02783   const dimension_type var_space_dim = var.space_dimension();
02784   if (x_space_dim < var_space_dim)
02785     throw_dimension_incompatible("affine_preimage(v, e, d)", "v", var);
02786 
02787   if (is_empty())
02788     return;
02789 
02790   const Coefficient& expr_v = expr.coefficient(var);
02791   const bool invertible = (expr_v != 0);
02792   if (!invertible) {
02793     Tmp_Interval_Type expr_value, temp0, temp1;
02794     expr_value.assign(expr.inhomogeneous_term());
02795     for (dimension_type i = expr_space_dim; i-- > 0; ) {
02796       const Coefficient& coeff = expr.coefficient(Variable(i));
02797       if (coeff != 0) {
02798         temp0.assign(coeff);
02799         temp1.assign(seq[i]);
02800         temp0.mul_assign(temp0, temp1);
02801         expr_value.add_assign(expr_value, temp0);
02802       }
02803     }
02804     if (denominator != 1) {
02805       temp0.assign(denominator);
02806       expr_value.div_assign(expr_value, temp0);
02807     }
02808     ITV& x_seq_v = seq[var.id()];
02809     expr_value.intersect_assign(x_seq_v);
02810     if (expr_value.is_empty())
02811       set_empty();
02812     else
02813       x_seq_v.assign(UNIVERSE);
02814   }
02815   else {
02816     // The affine transformation is invertible.
02817     // CHECKME: for efficiency, would it be meaningful to avoid
02818     // the computation of inverse by partially evaluating the call
02819     // to affine_image?
02820     Linear_Expression inverse;
02821     inverse -= expr;
02822     inverse += (expr_v + denominator) * var;
02823     affine_image(var, inverse, expr_v);
02824   }
02825   PPL_ASSERT(OK());
02826 }

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

Writes to s an ASCII representation of *this.

Definition at line 3908 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::ascii_dump(), Parma_Polyhedra_Library::Box< ITV >::Status::ascii_dump(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::status.

03908                                         {
03909   const char separator = ' ';
03910   status.ascii_dump(s);
03911   const dimension_type space_dim = space_dimension();
03912   s << "space_dim" << separator << space_dim;
03913   s << "\n";
03914   for (dimension_type i = 0; i < space_dim;  ++i)
03915     seq[i].ascii_dump(s);
03916 }

template<typename ITV>
void Parma_Polyhedra_Library::Box< ITV >::ascii_dump (  )  const

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

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

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

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

Definition at line 3922 of file Box.templates.hh.

03922                                   {
03923   if (!status.ascii_load(s))
03924     return false;
03925 
03926   std::string str;
03927   dimension_type space_dim;
03928   if (!(s >> str) || str != "space_dim")
03929     return false;
03930   if (!(s >> space_dim))
03931     return false;
03932 
03933   seq.clear();
03934   ITV seq_i;
03935   for (dimension_type i = 0; i < space_dim;  ++i) {
03936     if (seq_i.ascii_load(s))
03937       seq.push_back(seq_i);
03938     else
03939       return false;
03940   }
03941 
03942   // Check invariants.
03943   PPL_ASSERT(OK());
03944   return true;
03945 }

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

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

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

Definition at line 2831 of file Box.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.

02834                                                                       {
02835   // The denominator cannot be zero.
02836   if (denominator == 0)
02837     throw_generic("bounded_affine_image(v, lb, ub, d)", "d == 0");
02838 
02839   // Dimension-compatibility checks.
02840   const dimension_type space_dim = space_dimension();
02841   // The dimension of `lb_expr' and `ub_expr' should not be
02842   // greater than the dimension of `*this'.
02843   const dimension_type lb_space_dim = lb_expr.space_dimension();
02844   if (space_dim < lb_space_dim)
02845     throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
02846                                  "lb", lb_expr);
02847   const dimension_type ub_space_dim = ub_expr.space_dimension();
02848   if (space_dim < ub_space_dim)
02849     throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
02850                                  "ub", ub_expr);
02851     // `var' should be one of the dimensions of the box.
02852   const dimension_type var_space_dim = var.space_dimension();
02853   if (space_dim < var_space_dim)
02854     throw_dimension_incompatible("affine_image(v, e, d)", "v", var);
02855 
02856   // Any image of an empty box is empty.
02857   if (is_empty())
02858     return;
02859 
02860   // Add the constraint implied by the `lb_expr' and `ub_expr'.
02861   if (denominator > 0)
02862     refine_with_constraint(lb_expr <= ub_expr);
02863   else
02864     refine_with_constraint(lb_expr >= ub_expr);
02865 
02866   // Check whether `var' occurs in `lb_expr' and/or `ub_expr'.
02867   if (lb_expr.coefficient(var) == 0) {
02868     // Here `var' can only occur in `ub_expr'.
02869     generalized_affine_image(var,
02870                              LESS_OR_EQUAL,
02871                              ub_expr,
02872                              denominator);
02873     if (denominator > 0)
02874       refine_with_constraint(lb_expr <= denominator*var);
02875     else
02876       refine_with_constraint(denominator*var <= lb_expr);
02877   }
02878   else if (ub_expr.coefficient(var) == 0) {
02879     // Here `var' can only occur in `lb_expr'.
02880     generalized_affine_image(var,
02881                              GREATER_OR_EQUAL,
02882                              lb_expr,
02883                              denominator);
02884     if (denominator > 0)
02885       refine_with_constraint(denominator*var <= ub_expr);
02886     else
02887       refine_with_constraint(ub_expr <= denominator*var);
02888   }
02889   else {
02890     // Here `var' occurs in both `lb_expr' and `ub_expr'.  As boxes
02891     // can only use the non-relational constraints, we find the
02892     // maximum/minimum values `ub_expr' and `lb_expr' obtain with the
02893     // box and use these instead of the `ub-expr' and `lb-expr'.
02894     PPL_DIRTY_TEMP(Coefficient, max_num);
02895     PPL_DIRTY_TEMP(Coefficient, max_den);
02896     bool max_included;
02897     PPL_DIRTY_TEMP(Coefficient, min_num);
02898     PPL_DIRTY_TEMP(Coefficient, min_den);
02899     bool min_included;
02900     ITV& seq_v = seq[var.id()];
02901     if (maximize(ub_expr, max_num, max_den, max_included)) {
02902       if (minimize(lb_expr, min_num, min_den, min_included)) {
02903         // The `ub_expr' has a maximum value and the `lb_expr'
02904         // has a minimum value for the box.
02905         // Set the bounds for `var' using the minimum for `lb_expr'.
02906         min_den *= denominator;
02907         PPL_DIRTY_TEMP0(mpq_class, q1);
02908         PPL_DIRTY_TEMP0(mpq_class, q2);
02909         assign_r(q1.get_num(), min_num, ROUND_NOT_NEEDED);
02910         assign_r(q1.get_den(), min_den, ROUND_NOT_NEEDED);
02911         q1.canonicalize();
02912         // Now make the maximum of lb_expr the upper bound.  If the
02913         // maximum is not at a box point, then inequality is strict.
02914         max_den *= denominator;
02915         assign_r(q2.get_num(), max_num, ROUND_NOT_NEEDED);
02916         assign_r(q2.get_den(), max_den, ROUND_NOT_NEEDED);
02917         q2.canonicalize();
02918         if (denominator > 0)
02919           seq_v.build(i_constraint(min_included ? GREATER_OR_EQUAL : GREATER_THAN, q1),
02920                       i_constraint(max_included ? LESS_OR_EQUAL : LESS_THAN, q2));
02921         else
02922           seq_v.build(i_constraint(max_included ? GREATER_OR_EQUAL : GREATER_THAN, q2),
02923                        i_constraint(min_included ? LESS_OR_EQUAL : LESS_THAN, q1));
02924       }
02925       else {
02926         // The `ub_expr' has a maximum value but the `lb_expr'
02927         // has no minimum value for the box.
02928         // Set the bounds for `var' using the maximum for `lb_expr'.
02929         PPL_DIRTY_TEMP0(mpq_class, q);
02930         max_den *= denominator;
02931         assign_r(q.get_num(), max_num, ROUND_NOT_NEEDED);
02932         assign_r(q.get_den(), max_den, ROUND_NOT_NEEDED);
02933         q.canonicalize();
02934         if (denominator > 0)
02935           seq_v.build(i_constraint(max_included ? LESS_OR_EQUAL : LESS_THAN, q));
02936         else
02937           seq_v.build(i_constraint(max_included ? GREATER_OR_EQUAL : GREATER_THAN, q));
02938       }
02939     }
02940     else if (minimize(lb_expr, min_num, min_den, min_included)) {
02941         // The `ub_expr' has no maximum value but the `lb_expr'
02942         // has a minimum value for the box.
02943         // Set the bounds for `var' using the minimum for `lb_expr'.
02944         min_den *= denominator;
02945         PPL_DIRTY_TEMP0(mpq_class, q);
02946         assign_r(q.get_num(), min_num, ROUND_NOT_NEEDED);
02947         assign_r(q.get_den(), min_den, ROUND_NOT_NEEDED);
02948         q.canonicalize();
02949         if (denominator > 0)
02950           seq_v.build(i_constraint(min_included ? GREATER_OR_EQUAL : GREATER_THAN, q));
02951         else
02952           seq_v.build(i_constraint(min_included ? LESS_OR_EQUAL : LESS_THAN, q));
02953     }
02954     else {
02955       // The `ub_expr' has no maximum value and the `lb_expr'
02956       // has no minimum value for the box.
02957       // So we set the bounds to be unbounded.
02958       seq_v.assign(UNIVERSE);
02959     }
02960   }
02961   PPL_ASSERT(OK());
02962 }

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

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

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

Definition at line 2967 of file Box.templates.hh.

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

02970                                                                          {
02971   // The denominator cannot be zero.
02972   const dimension_type space_dim = space_dimension();
02973   if (denominator == 0)
02974     throw_generic("bounded_affine_preimage(v, lb, ub, d)", "d == 0");
02975 
02976   // Dimension-compatibility checks.
02977   // `var' should be one of the dimensions of the polyhedron.
02978   const dimension_type var_space_dim = var.space_dimension();
02979   if (space_dim < var_space_dim)
02980     throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
02981                                  "v", var);
02982   // The dimension of `lb_expr' and `ub_expr' should not be
02983   // greater than the dimension of `*this'.
02984   const dimension_type lb_space_dim = lb_expr.space_dimension();
02985   if (space_dim < lb_space_dim)
02986     throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)",
02987                                  "lb", lb_expr);
02988   const dimension_type ub_space_dim = ub_expr.space_dimension();
02989   if (space_dim < ub_space_dim)
02990     throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)",
02991                                  "ub", ub_expr);
02992 
02993   // Any preimage of an empty polyhedron is empty.
02994   if (marked_empty())
02995     return;
02996 
02997   const bool negative_denom = (denominator < 0);
02998   const Coefficient& lb_var_coeff = lb_expr.coefficient(var);
02999   const Coefficient& ub_var_coeff = ub_expr.coefficient(var);
03000 
03001   // If the implied constraint between `ub_expr and `lb_expr' is
03002   // independent of `var', then impose it now.
03003   if (lb_var_coeff == ub_var_coeff) {
03004     if (negative_denom)
03005       refine_with_constraint(lb_expr >= ub_expr);
03006     else
03007       refine_with_constraint(lb_expr <= ub_expr);
03008   }
03009 
03010   ITV& seq_var = seq[var.id()];
03011   if (!seq_var.is_universe()) {
03012     // We want to work with a positive denominator,
03013     // so the sign and its (unsigned) value are separated.
03014     PPL_DIRTY_TEMP_COEFFICIENT(pos_denominator);
03015     pos_denominator = denominator;
03016     if (negative_denom)
03017       neg_assign(pos_denominator, pos_denominator);
03018     // Store all the information about the upper and lower bounds
03019     // for `var' before making this interval unbounded.
03020     bool open_lower = seq_var.lower_is_open();
03021     bool unbounded_lower = seq_var.lower_is_boundary_infinity();
03022     PPL_DIRTY_TEMP0(mpq_class, q_seq_var_lower);
03023     PPL_DIRTY_TEMP(Coefficient, num_lower);
03024     PPL_DIRTY_TEMP(Coefficient, den_lower);
03025     if (!unbounded_lower) {
03026       assign_r(q_seq_var_lower, seq_var.lower(), ROUND_NOT_NEEDED);
03027       assign_r(num_lower, q_seq_var_lower.get_num(), ROUND_NOT_NEEDED);
03028       assign_r(den_lower, q_seq_var_lower.get_den(), ROUND_NOT_NEEDED);
03029       if (negative_denom)
03030         neg_assign(den_lower, den_lower);
03031       num_lower *= pos_denominator;
03032       seq_var.lower_extend();
03033     }
03034     bool open_upper = seq_var.upper_is_open();
03035     bool unbounded_upper = seq_var.upper_is_boundary_infinity();
03036     PPL_DIRTY_TEMP0(mpq_class, q_seq_var_upper);
03037     PPL_DIRTY_TEMP(Coefficient, num_upper);
03038     PPL_DIRTY_TEMP(Coefficient, den_upper);
03039     if (!unbounded_upper) {
03040       assign_r(q_seq_var_upper, seq_var.upper(), ROUND_NOT_NEEDED);
03041       assign_r(num_upper, q_seq_var_upper.get_num(), ROUND_NOT_NEEDED);
03042       assign_r(den_upper, q_seq_var_upper.get_den(), ROUND_NOT_NEEDED);
03043       if (negative_denom)
03044         neg_assign(den_upper, den_upper);
03045       num_upper *= pos_denominator;
03046       seq_var.upper_extend();
03047     }
03048 
03049     if (!unbounded_lower) {
03050       // `lb_expr' is revised by removing the `var' component,
03051       // multiplying by `-' denominator of the lower bound for `var',
03052       // and adding the lower bound for `var' to the inhomogeneous term.
03053       Linear_Expression revised_lb_expr(ub_expr);
03054       revised_lb_expr -= ub_var_coeff * var;
03055       PPL_DIRTY_TEMP(Coefficient, d);
03056       neg_assign(d, den_lower);
03057       revised_lb_expr *= d;
03058       revised_lb_expr += num_lower;
03059 
03060       // Find the minimum value for the revised lower bound expression
03061       // and use this to refine the appropriate bound.
03062       bool included;
03063       PPL_DIRTY_TEMP(Coefficient, den);
03064       if (minimize(revised_lb_expr, num_lower, den, included)) {
03065         den_lower *= (den * ub_var_coeff);
03066         PPL_DIRTY_TEMP0(mpq_class, q);
03067         assign_r(q.get_num(), num_lower, ROUND_NOT_NEEDED);
03068         assign_r(q.get_den(), den_lower, ROUND_NOT_NEEDED);
03069         q.canonicalize();
03070         open_lower |= !included;
03071         if ((ub_var_coeff >= 0) ? !negative_denom : negative_denom)
03072           seq_var.add_constraint(i_constraint(open_lower ? GREATER_THAN : GREATER_OR_EQUAL, q));
03073         else
03074           seq_var.add_constraint(i_constraint(open_lower ? LESS_THAN : LESS_OR_EQUAL, q));
03075         if (seq_var.is_empty()) {
03076           set_empty();
03077           return;
03078         }
03079       }
03080     }
03081 
03082     if (!unbounded_upper) {
03083       // `ub_expr' is revised by removing the `var' component,
03084       // multiplying by `-' denominator of the upper bound for `var',
03085       // and adding the upper bound for `var' to the inhomogeneous term.
03086       Linear_Expression revised_ub_expr(lb_expr);
03087       revised_ub_expr -= lb_var_coeff * var;
03088       PPL_DIRTY_TEMP(Coefficient, d);
03089       neg_assign(d, den_upper);
03090       revised_ub_expr *= d;
03091       revised_ub_expr += num_upper;
03092 
03093       // Find the maximum value for the revised upper bound expression
03094       // and use this to refine the appropriate bound.
03095       bool included;
03096       PPL_DIRTY_TEMP(Coefficient, den);
03097       if (maximize(revised_ub_expr, num_upper, den, included)) {
03098         den_upper *= (den * lb_var_coeff);
03099         PPL_DIRTY_TEMP0(mpq_class, q);
03100         assign_r(q.get_num(), num_upper, ROUND_NOT_NEEDED);
03101         assign_r(q.get_den(), den_upper, ROUND_NOT_NEEDED);
03102         q.canonicalize();
03103         open_upper |= !included;
03104         if ((lb_var_coeff >= 0) ? !negative_denom : negative_denom)
03105           seq_var.add_constraint(i_constraint(open_upper ? LESS_THAN : LESS_OR_EQUAL, q));
03106         else
03107           seq_var.add_constraint(i_constraint(open_upper ? GREATER_THAN : GREATER_OR_EQUAL, q));
03108         if (seq_var.is_empty()) {
03109           set_empty();
03110           return;
03111         }
03112       }
03113     }
03114   }
03115 
03116   // If the implied constraint between `ub_expr and `lb_expr' is
03117   // dependent on `var', then impose on the new box.
03118   if (lb_var_coeff != ub_var_coeff) {
03119     if (denominator > 0)
03120       refine_with_constraint(lb_expr <= ub_expr);
03121     else
03122       refine_with_constraint(lb_expr >= ub_expr);
03123   }
03124 
03125   PPL_ASSERT(OK());
03126 }

template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::bounds ( const Linear_Expression expr,
bool  from_above 
) const [inline, private]

Checks if and how expr is bounded in *this.

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

Parameters:
expr The linear expression to test;
from_above true if and only if the boundedness of interest is "from above".
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

Definition at line 552 of file Box.templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

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

00552                                                                            {
00553   // `expr' should be dimension-compatible with `*this'.
00554   const dimension_type expr_space_dim = expr.space_dimension();
00555   const dimension_type space_dim = space_dimension();
00556   if (space_dim < expr_space_dim)
00557     throw_dimension_incompatible((from_above
00558                                   ? "bounds_from_above(e)"
00559                                   : "bounds_from_below(e)"), "e", expr);
00560   // A zero-dimensional or empty Box bounds everything.
00561   if (space_dim == 0 || is_empty())
00562     return true;
00563 
00564   const int from_above_sign = from_above ? 1 : -1;
00565   for (dimension_type i = expr_space_dim; i-- > 0; )
00566     switch (sgn(expr.coefficient(Variable(i))) * from_above_sign) {
00567     case 1:
00568       if (seq[i].upper_is_boundary_infinity())
00569         return false;
00570       break;
00571     case 0:
00572       // Nothing to do.
00573       break;
00574     case -1:
00575       if (seq[i].lower_is_boundary_infinity())
00576         return false;
00577       break;
00578     }
00579   return true;
00580 }

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_argument Thrown if expr and *this are dimension-incompatible.

Definition at line 181 of file Box.inlines.hh.

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

00181                                                                {
00182   return bounds(expr, true);
00183 }

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_argument Thrown if expr and *this are dimension-incompatible.

Definition at line 187 of file Box.inlines.hh.

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

00187                                                                {
00188   return bounds(expr, false);
00189 }

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

Returns false indicating that this domain does not recycle congruences.

Definition at line 358 of file Box.inlines.hh.

00358                                        {
00359   return false;
00360 }

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

Returns false indicating that this domain does not recycle constraints.

Definition at line 352 of file Box.inlines.hh.

00352                                        {
00353   return false;
00354 }

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

Assigns to *this the result of restoring in y the constraints of *this that were lost by CC76-extrapolation applications.

Parameters:
y A Box that must contain *this.
Exceptions:
std::invalid_argument Thrown 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}$.

Definition at line 3720 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::contains(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

03720                                           {
03721   const dimension_type space_dim = space_dimension();
03722 
03723   // Dimension-compatibility check.
03724   if (space_dim != y.space_dimension())
03725     throw_dimension_incompatible("CC76_narrowing_assign(y)", y);
03726 
03727 #ifndef NDEBUG
03728   {
03729     // We assume that `*this' is contained in or equal to `y'.
03730     const Box x_copy = *this;
03731     const Box y_copy = y;
03732     PPL_ASSERT(y_copy.contains(x_copy));
03733   }
03734 #endif
03735 
03736   // If both boxes are zero-dimensional,
03737   // since `y' contains `*this', we simply return `*this'.
03738   if (space_dim == 0)
03739     return;
03740 
03741   // If `y' is empty, since `y' contains `this', `*this' is empty too.
03742   if (y.is_empty())
03743     return;
03744   // If `*this' is empty, we return.
03745   if (is_empty())
03746     return;
03747 
03748   // Replace each constraint in `*this' by the corresponding constraint
03749   // in `y' if the corresponding inhomogeneous terms are both finite.
03750   for (dimension_type i = space_dim; i-- > 0; ) {
03751     ITV& x_i = seq[i];
03752     const ITV& y_i = y.seq[i];
03753     if (!x_i.lower_is_boundary_infinity()
03754         && !y_i.lower_is_boundary_infinity()
03755         && x_i.lower() != y_i.lower())
03756       x_i.lower() = y_i.lower();
03757     if (!x_i.upper_is_boundary_infinity()
03758         && !y_i.upper_is_boundary_infinity()
03759         && x_i.upper() != y_i.upper())
03760       x_i.upper() = y_i.upper();
03761   }
03762   PPL_ASSERT(OK());
03763 }

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

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

Parameters:
y A box that must be contained in *this.
first An iterator that points to the first stop-point.
last An iterator that points one past the last stop-point.
Exceptions:
std::invalid_argument Thrown if *this and y are dimension-incompatible.

Definition at line 3596 of file Box.templates.hh.

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

03596                                                                         {
03597   if (y.is_empty())
03598     return;
03599 
03600   for (dimension_type i = seq.size(); i-- > 0; )
03601     seq[i].CC76_widening_assign(y.seq[i], first, last);
03602 
03603   PPL_ASSERT(OK());
03604 }

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 = 0 
) [inline]

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

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

Definition at line 3611 of file Box.templates.hh.

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

Referenced by Parma_Polyhedra_Library::Box< ITV >::CC76_widening_assign(), Parma_Polyhedra_Library::Box< ITV >::limited_CC76_extrapolation_assign(), and Parma_Polyhedra_Library::Box< ITV >::widening_assign().

03611                                                        {
03612   static typename ITV::boundary_type stop_points[] = {
03613     typename ITV::boundary_type(-2),
03614     typename ITV::boundary_type(-1),
03615     typename ITV::boundary_type(0),
03616     typename ITV::boundary_type(1),
03617     typename ITV::boundary_type(2)
03618   };
03619 
03620   Box& x = *this;
03621   // If there are tokens available, work on a temporary copy.
03622   if (tp != 0 && *tp > 0) {
03623     Box<ITV> x_tmp(x);
03624     x_tmp.CC76_widening_assign(y, 0);
03625     // If the widening was not precise, use one of the available tokens.
03626     if (!x.contains(x_tmp))
03627       --(*tp);
03628     return;
03629   }
03630   x.CC76_widening_assign(y,
03631                          stop_points,
03632                          stop_points
03633                          + sizeof(stop_points)/sizeof(stop_points[0]));
03634 }

template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::check_empty (  )  const [inline, private]

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

Definition at line 1289 of file Box.templates.hh.

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

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

01289                             {
01290   PPL_ASSERT(!marked_empty());
01291   Box<ITV>& x = const_cast<Box<ITV>&>(*this);
01292   for (dimension_type k = seq.size(); k-- > 0; )
01293     if (seq[k].is_empty()) {
01294       x.set_empty();
01295       return true;
01296     }
01297   x.set_nonempty();;
01298   return false;
01299 }

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

Seeing a box as a set of tuples (its points), assigns to *this all the tuples that can be obtained by concatenating, in the order given, a tuple of *this with a tuple of y.

Let $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 1767 of file Box.templates.hh.

References Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::reset_empty_up_to_date(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::status, and Parma_Polyhedra_Library::Box< ITV >::Status::test_empty_up_to_date().

01767                                          {
01768   Box& x = *this;
01769   const dimension_type x_space_dim = x.space_dimension();
01770   const dimension_type y_space_dim = y.space_dimension();
01771 
01772   // If `y' is marked empty, the result will be empty too.
01773   if (y.marked_empty())
01774     x.set_empty();
01775 
01776   // If `y' is a 0-dim space box, there is nothing left to do.
01777   if (y_space_dim == 0)
01778     return;
01779 
01780   // Here `y_space_dim > 0', so that a non-trivial concatenation will occur:
01781   // make sure that reallocation will occur once at most.
01782   x.seq.reserve(x_space_dim + y_space_dim);
01783 
01784   // If `x' is marked empty, then it is sufficient to adjust
01785   // the dimension of the vector space.
01786   if (x.marked_empty()) {
01787     x.seq.insert(x.seq.end(), y_space_dim, ITV(EMPTY));
01788     PPL_ASSERT(x.OK());
01789     return;
01790   }
01791 
01792   // Here neither `x' nor `y' are marked empty: concatenate them.
01793   std::copy(y.seq.begin(), y.seq.end(),
01794             std::back_insert_iterator<Sequence>(x.seq));
01795   // Update the `empty_up_to_date' flag.
01796   if (!y.status.test_empty_up_to_date())
01797     reset_empty_up_to_date();
01798 
01799   PPL_ASSERT(x.OK());
01800 }

template<typename ITV >
Congruence_System Parma_Polyhedra_Library::Box< ITV >::congruences (  )  const [inline]

Returns a system of congruences approximating *this.

Definition at line 3848 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::get_lower_bound(), Parma_Polyhedra_Library::Congruence_System::insert(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Congruence_System::zero_dim_empty().

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

03848                             {
03849   Congruence_System cgs;
03850   const dimension_type space_dim = space_dimension();
03851   if (space_dim == 0) {
03852     if (marked_empty())
03853       cgs = Congruence_System::zero_dim_empty();
03854   }
03855   // Make sure emptiness is detected.
03856   else if (is_empty())
03857     cgs.insert((0*Variable(space_dim-1) %= -1) / 0);
03858   else {
03859     // KLUDGE: in the future `cgs' will be constructed of the right dimension.
03860     // For the time being, we force the dimension with the following line.
03861     cgs.insert(0*Variable(space_dim-1) %= 0);
03862 
03863     for (dimension_type k = 0; k < space_dim; ++k) {
03864       bool closed = false;
03865       PPL_DIRTY_TEMP(Coefficient, n);
03866       PPL_DIRTY_TEMP(Coefficient, d);
03867       if (get_lower_bound(k, closed, n, d) && closed)
03868           // Make sure equality congruences are detected.
03869           if (seq[k].is_singleton())
03870             cgs.insert((d*Variable(k) %= n) / 0);
03871     }
03872   }
03873   return cgs;
03874 }

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

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

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

Definition at line 1433 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::is_universe(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

01433                                        {
01434   // `var' should be one of the dimensions of the polyhedron.
01435   const dimension_type var_space_dim = var.space_dimension();
01436   if (space_dimension() < var_space_dim)
01437     throw_dimension_incompatible("constrains(v)", "v", var);
01438 
01439   if (marked_empty() || !seq[var_space_dim-1].is_universe())
01440     return true;
01441   // Now force an emptiness check.
01442   return is_empty();
01443 }

template<typename ITV >
Constraint_System Parma_Polyhedra_Library::Box< ITV >::constraints (  )  const [inline]

Returns a system of constraints defining *this.

Definition at line 3767 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::get_lower_bound(), Parma_Polyhedra_Library::Box< ITV >::get_upper_bound(), Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Constraint_System::zero_dim_empty().

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

03767                             {
03768   Constraint_System cs;
03769   const dimension_type space_dim = space_dimension();
03770   if (space_dim == 0) {
03771     if (marked_empty())
03772       cs = Constraint_System::zero_dim_empty();
03773   }
03774   else if (marked_empty())
03775     cs.insert(0*Variable(space_dim-1) <= -1);
03776   else {
03777     // KLUDGE: in the future `cs' will be constructed of the right dimension.
03778     // For the time being, we force the dimension with the following line.
03779     cs.insert(0*Variable(space_dim-1) <= 0);
03780 
03781     for (dimension_type k = 0; k < space_dim; ++k) {
03782       bool closed = false;
03783       PPL_DIRTY_TEMP(Coefficient, n);
03784       PPL_DIRTY_TEMP(Coefficient, d);
03785       if (get_lower_bound(k, closed, n, d)) {
03786         if (closed)
03787           cs.insert(d*Variable(k) >= n);
03788         else
03789           cs.insert(d*Variable(k) > n);
03790       }
03791       if (get_upper_bound(k, closed, n, d)) {
03792         if (closed)
03793           cs.insert(d*Variable(k) <= n);
03794         else
03795           cs.insert(d*Variable(k) < n);
03796       }
03797     }
03798   }
03799   return cs;
03800 }

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

Returns true if and only if *this contains y.

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

Definition at line 1153 of file Box.templates.hh.

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

Referenced by Parma_Polyhedra_Library::Box< ITV >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Box< ITV >::CC76_widening_assign(), Parma_Polyhedra_Library::Box< ITV >::limited_CC76_extrapolation_assign(), and Parma_Polyhedra_Library::Box< ITV >::strictly_contains().

01153                                      {
01154   const Box& x = *this;
01155   // Dimension-compatibility check.
01156   if (x.space_dimension() != y.space_dimension())
01157     x.throw_dimension_incompatible("contains(y)", y);
01158 
01159   // If `y' is empty, then `x' contains `y'.
01160   if (y.is_empty())
01161     return true;
01162 
01163   // If `x' is empty, then `x' cannot contain `y'.
01164   if (x.is_empty())
01165     return false;
01166 
01167   for (dimension_type k = x.seq.size(); k-- > 0; )
01168     // FIXME: fix this name qualification issue.
01169     if (!x.seq[k].contains(y.seq[k]))
01170       return false;
01171   return true;
01172 }

template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::contains_integer_point (  )  const [inline]

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

Definition at line 1348 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), and Parma_Polyhedra_Library::Box< ITV >::seq.

01348                                        {
01349   if (marked_empty())
01350     return false;
01351   for (dimension_type k = seq.size(); k-- > 0; )
01352     if (!seq[k].contains_integer_point())
01353       return false;
01354   return true;
01355 }

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

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

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

Definition at line 1804 of file Box.templates.hh.

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

01804                                         {
01805   const dimension_type space_dim = space_dimension();
01806 
01807   // Dimension-compatibility check.
01808   if (space_dim != y.space_dimension())
01809     throw_dimension_incompatible("difference_assign(y)", y);
01810 
01811   Box& x = *this;
01812   if (x.is_empty() || y.is_empty())
01813     return;
01814 
01815   switch (space_dim) {
01816   case 0:
01817     // If `x' is zero-dimensional, then at this point both `x' and `y'
01818     // are the universe box, so that their difference is empty.
01819     x.set_empty();
01820     break;
01821 
01822   case 1:
01823     x.seq[0].difference_assign(y.seq[0]);
01824     if (x.seq[0].is_empty())
01825       x.set_empty();
01826     break;
01827 
01828   default:
01829     {
01830       dimension_type index_non_contained = space_dim;
01831       dimension_type number_non_contained = 0;
01832       for (dimension_type i = space_dim; i-- > 0; )
01833         if (!y.seq[i].contains(x.seq[i])) {
01834           if (++number_non_contained == 1)
01835             index_non_contained = i;
01836           else
01837             break;
01838         }
01839 
01840       switch (number_non_contained) {
01841       case 0:
01842         // `y' covers `x': the difference is empty.
01843         x.set_empty();
01844         break;
01845       case 1:
01846         x.seq[index_non_contained]
01847           .difference_assign(y.seq[index_non_contained]);
01848         if (x.seq[index_non_contained].is_empty())
01849           x.set_empty();
01850         break;
01851       default:
01852         // Nothing to do: the difference is `x'.
01853         break;
01854       }
01855     }
01856     break;
01857   }
01858   PPL_ASSERT(OK());
01859 }

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

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

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

Definition at line 1687 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::drop_some_non_integer_points(), Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Variables_Set::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

01688                                                          {
01689   // Dimension-compatibility check.
01690   const dimension_type min_space_dim = vars.space_dimension();
01691   if (space_dimension() < min_space_dim)
01692     throw_dimension_incompatible("drop_some_non_integer_points(vs, cmpl)",
01693                                  min_space_dim);
01694 
01695   if (std::numeric_limits<typename ITV::boundary_type>::is_integer
01696       && !ITV::info_type::store_open)
01697     return;
01698 
01699   if (marked_empty())
01700     return;
01701 
01702   for (Variables_Set::const_iterator v_i = vars.begin(),
01703          v_end = vars.end(); v_i != v_end; ++v_i)
01704     seq[*v_i].drop_some_non_integer_points();
01705 
01706   PPL_ASSERT(OK());
01707 }

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

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

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

Definition at line 1671 of file Box.templates.hh.

References Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), and Parma_Polyhedra_Library::Box< ITV >::seq.

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

01671                                                        {
01672   if (std::numeric_limits<typename ITV::boundary_type>::is_integer
01673       && !ITV::info_type::store_open)
01674     return;
01675 
01676   if (marked_empty())
01677     return;
01678 
01679   for (dimension_type k = seq.size(); k-- > 0; )
01680     seq[k].drop_some_non_integer_points();
01681 
01682   PPL_ASSERT(OK());
01683 }

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:
var The variable corresponding to the space dimension to be replicated;
m The number of replicas to be created.
Exceptions:
std::invalid_argument Thrown if var does not correspond to a dimension of the vector space.
std::length_error Thrown if adding m new space dimensions would cause the vector space to exceed dimension max_space_dimension().

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

Definition at line 232 of file Box.inlines.hh.

References Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Box< ITV >::max_space_dimension(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Box< ITV >::throw_generic().

00233                                                          {
00234   const dimension_type space_dim = space_dimension();
00235   // `var' should be one of the dimensions of the vector space.
00236   if (var.space_dimension() > space_dim)
00237     throw_dimension_incompatible("expand_space_dimension(v, m)", "v", var);
00238 
00239   // The space dimension of the resulting Box should not
00240   // overflow the maximum allowed space dimension.
00241   if (m > max_space_dimension() - space_dim)
00242     throw_generic("expand_dimension(v, m)",
00243                   "adding m new space dimensions exceeds "
00244                   "the maximum allowed space dimension");
00245 
00246   // To expand the space dimension corresponding to variable `var',
00247   // we append to the box `m' copies of the corresponding interval.
00248   seq.insert(seq.end(), m, seq[var.id()]);
00249   PPL_ASSERT(OK());
00250 }

template<typename ITV >
memory_size_type Parma_Polyhedra_Library::Box< ITV >::external_memory_in_bytes (  )  const [inline]

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

Definition at line 3878 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::seq.

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

03878                                          {
03879   memory_size_type n = seq.capacity() * sizeof(ITV);
03880   for (dimension_type k = seq.size(); k-- > 0; )
03881     n += seq[k].external_memory_in_bytes();
03882   return n;
03883 }

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

Folds the space dimensions in vars into dest.

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

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

Definition at line 2085 of file Box.templates.hh.

References Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::remove_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Box< ITV >::throw_generic().

02086                                                      {
02087   const dimension_type space_dim = space_dimension();
02088   // `dest' should be one of the dimensions of the box.
02089   if (dest.space_dimension() > space_dim)
02090     throw_dimension_incompatible("fold_space_dimensions(vs, v)", "v", dest);
02091 
02092   // The folding of no dimensions is a no-op.
02093   if (vars.empty())
02094     return;
02095 
02096   // All variables in `vars' should be dimensions of the box.
02097   if (vars.space_dimension() > space_dim)
02098     throw_dimension_incompatible("fold_space_dimensions(vs, v)",
02099                                  vars.space_dimension());
02100 
02101   // Moreover, `dest.id()' should not occur in `vars'.
02102   if (vars.find(dest.id()) != vars.end())
02103     throw_generic("fold_space_dimensions(vs, v)",
02104                   "v should not occur in vs");
02105 
02106   // Note: the check for emptiness is needed for correctness.
02107   if (!is_empty()) {
02108     // Join the interval corresponding to variable `dest' with the intervals
02109     // corresponding to the variables in `vars'.
02110     ITV& seq_v = seq[dest.id()];
02111     for (Variables_Set::const_iterator i = vars.begin(),
02112            vs_end = vars.end(); i != vs_end; ++i)
02113       seq_v.join_assign(seq[*i]);
02114   }
02115   remove_space_dimensions(vars);
02116 }

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 [inline]

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

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

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

Definition at line 1359 of file Box.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Checked::le, Parma_Polyhedra_Library::normalize2(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

01361                                                                 {
01362   dimension_type space_dim = space_dimension();
01363   // The dimension of `expr' must be at most the dimension of *this.
01364   if (space_dim < expr.space_dimension())
01365     throw_dimension_incompatible("frequency(e, ...)", "e", expr);
01366 
01367   // Check if `expr' has a constant value.
01368   // If it is constant, set the frequency `freq_n' to 0
01369   // and return true. Otherwise the values for \p expr
01370   // are not discrete so return false.
01371 
01372   // Space dimension = 0: if empty, then return false;
01373   // otherwise the frequency is 0 and the value is the inhomogeneous term.
01374   if (space_dim == 0) {
01375     if (is_empty())
01376       return false;
01377     freq_n = 0;
01378     freq_d = 1;
01379     val_n = expr.inhomogeneous_term();
01380     val_d = 1;
01381     return true;
01382   }
01383 
01384   // For an empty Box, we simply return false.
01385   if (is_empty())
01386     return false;
01387 
01388   // The Box has at least 1 dimension and is not empty.
01389   PPL_DIRTY_TEMP_COEFFICIENT(coeff);
01390   PPL_DIRTY_TEMP_COEFFICIENT(num);
01391   PPL_DIRTY_TEMP_COEFFICIENT(den);
01392   PPL_DIRTY_TEMP0(mpq_class, tmp);
01393   Linear_Expression le = expr;
01394 
01395   PPL_DIRTY_TEMP_COEFFICIENT(val_den);
01396   val_den = 1;
01397 
01398   for (dimension_type i = space_dim; i-- > 0; ) {
01399     const Variable v(i);
01400     coeff = le.coefficient(v);
01401     if (coeff == 0) {
01402       continue;
01403     }
01404 
01405     const ITV& seq_i = seq[i];
01406     // Check if `v' is constant in the BD shape.
01407     if (seq_i.is_singleton()) {
01408       // If `v' is constant, replace it in `le' by the value.
01409       assign_r(tmp, seq_i.lower(), ROUND_NOT_NEEDED);
01410       num = tmp.get_num();
01411       den = tmp.get_den();
01412       le -= coeff*v;
01413       le *= den;
01414       le += num*coeff;
01415       val_den *= den;
01416       continue;
01417     }
01418     // The expression `expr' is not constant.
01419     return false;
01420   }
01421 
01422   // The expression `expr' is constant.
01423   freq_n = 0;
01424   freq_d = 1;
01425 
01426   // Reduce `val_n' and `val_d'.
01427   normalize2(le.inhomogeneous_term(), val_den, val_n, val_d);
01428   return true;
01429 }

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

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

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

Definition at line 3341 of file Box.templates.hh.

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

03343                                                          {
03344   // Dimension-compatibility checks.
03345   // The dimension of `lhs' should not be greater than the dimension
03346   // of `*this'.
03347   dimension_type lhs_space_dim = lhs.space_dimension();
03348   const dimension_type space_dim = space_dimension();
03349   if (space_dim < lhs_space_dim)
03350     throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
03351                                  "e1", lhs);
03352   // The dimension of `rhs' should not be greater than the dimension
03353   // of `*this'.
03354   const dimension_type rhs_space_dim = rhs.space_dimension();
03355   if (space_dim < rhs_space_dim)
03356     throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
03357                                  "e2", rhs);
03358 
03359   // The relation symbol cannot be a disequality.
03360   if (relsym == NOT_EQUAL)
03361     throw_generic("generalized_affine_image(e1, r, e2)",
03362                   "r is the disequality relation symbol");
03363 
03364   // Any image of an empty box is empty.
03365   if (marked_empty())
03366     return;
03367 
03368   // Compute the maximum and minimum value reached by the rhs on the box.
03369   PPL_DIRTY_TEMP(Coefficient, max_num);
03370   PPL_DIRTY_TEMP(Coefficient, max_den);
03371   bool max_included;
03372   bool max_rhs = maximize(rhs, max_num, max_den, max_included);
03373   PPL_DIRTY_TEMP(Coefficient, min_num);
03374   PPL_DIRTY_TEMP(Coefficient, min_den);
03375   bool min_included;
03376   bool min_rhs = minimize(rhs, min_num, min_den, min_included);
03377 
03378   // Check whether there is 0, 1 or more than one variable in the lhs
03379   // and record the variable with the highest dimension; set the box
03380   // intervals to be unbounded for all other dimensions with non-zero
03381   // coefficients in the lhs.
03382   bool has_var = false;
03383   bool has_more_than_one_var = false;
03384   // Initialization is just to avoid an annoying warning.
03385   dimension_type has_var_id = 0;
03386   for ( ; lhs_space_dim > 0; --lhs_space_dim)
03387     if (lhs.coefficient(Variable(lhs_space_dim - 1)) != 0) {
03388       if (has_var) {
03389         ITV& seq_i = seq[lhs_space_dim - 1];
03390         seq_i.assign(UNIVERSE);
03391         has_more_than_one_var = true;
03392       }
03393       else {
03394         has_var = true;
03395         has_var_id = lhs_space_dim - 1;
03396       }
03397     }
03398 
03399   if (has_more_than_one_var) {
03400     // There is more than one dimension with non-zero coefficient, so
03401     // we cannot have any information about the dimensions in the lhs.
03402     // Since all but the highest dimension with non-zero coefficient
03403     // in the lhs have been set unbounded, it remains to set the
03404     // highest dimension in the lhs unbounded.
03405     ITV& seq_var = seq[has_var_id];
03406     seq_var.assign(UNIVERSE);
03407     PPL_ASSERT(OK());
03408     return;
03409   }
03410 
03411   if (has_var) {
03412     // There is exactly one dimension with non-zero coefficient.
03413     ITV& seq_var = seq[has_var_id];
03414 
03415     // Compute the new bounds for this dimension defined by the rhs
03416     // expression.
03417     const Coefficient& inhomo = lhs.inhomogeneous_term();
03418     const Coefficient& coeff = lhs.coefficient(Variable(has_var_id));
03419     PPL_DIRTY_TEMP0(mpq_class, q_max);
03420     PPL_DIRTY_TEMP0(mpq_class, q_min);
03421     if (max_rhs) {
03422       max_num -= inhomo * max_den;
03423       max_den *= coeff;
03424       assign_r(q_max.get_num(), max_num, ROUND_NOT_NEEDED);
03425       assign_r(q_max.get_den(), max_den, ROUND_NOT_NEEDED);
03426       q_max.canonicalize();
03427     }
03428     if (min_rhs) {
03429       min_num -= inhomo * min_den;
03430       min_den *= coeff;
03431       assign_r(q_min.get_num(), min_num, ROUND_NOT_NEEDED);
03432       assign_r(q_min.get_den(), min_den, ROUND_NOT_NEEDED);
03433       q_min.canonicalize();
03434     }
03435 
03436     // The choice as to which bounds should be set depends on the sign
03437     // of the coefficient of the dimension `has_var_id' in the lhs.
03438     if (coeff > 0)
03439       // The coefficient of the dimension in the lhs is +ve.
03440       switch (relsym) {
03441       case LESS_OR_EQUAL:
03442         max_rhs
03443           ? seq_var.build(i_constraint(max_included ? LESS_OR_EQUAL : LESS_THAN, q_max))
03444           : seq_var.assign(UNIVERSE);
03445         break;
03446       case LESS_THAN:
03447         max_rhs
03448           ? seq_var.build(i_constraint(LESS_THAN, q_max))
03449           : seq_var.assign(UNIVERSE);
03450         break;
03451       case EQUAL:
03452         {
03453           I_Constraint<mpq_class> l;
03454           I_Constraint<mpq_class> u;
03455           if (max_rhs)
03456             u.set(max_included ? LESS_OR_EQUAL : LESS_THAN, q_max);
03457           if (min_rhs)
03458             l.set(min_included ? GREATER_OR_EQUAL : GREATER_THAN, q_min);
03459           seq_var.build(l, u);
03460           break;
03461         }
03462       case GREATER_OR_EQUAL:
03463         min_rhs
03464           ? seq_var.build(i_constraint(min_included ? GREATER_OR_EQUAL : GREATER_THAN, q_min))
03465           : seq_var.assign(UNIVERSE);
03466         break;
03467       case GREATER_THAN:
03468         min_rhs
03469           ? seq_var.build(i_constraint(GREATER_THAN, q_min))
03470           : seq_var.assign(UNIVERSE);
03471         break;
03472       default:
03473         // The NOT_EQUAL case has been already dealt with.
03474         throw std::runtime_error("PPL internal error");
03475       }
03476     else
03477       // The coefficient of the dimension in the lhs is -ve.
03478       switch (relsym) {
03479       case GREATER_OR_EQUAL:
03480         min_rhs
03481           ? seq_var.build(i_constraint(min_included ? LESS_OR_EQUAL : LESS_THAN, q_min))
03482           : seq_var.assign(UNIVERSE);
03483         break;
03484       case GREATER_THAN:
03485         min_rhs
03486           ? seq_var.build(i_constraint(LESS_THAN, q_min))
03487           : seq_var.assign(UNIVERSE);
03488         break;
03489       case EQUAL:
03490         {
03491           I_Constraint<mpq_class> l;
03492           I_Constraint<mpq_class> u;
03493           if (max_rhs)
03494             l.set(max_included ? GREATER_OR_EQUAL : GREATER_THAN, q_max);
03495           if (min_rhs)
03496             u.set(min_included ? LESS_OR_EQUAL : LESS_THAN, q_min);
03497           seq_var.build(l, u);
03498           break;
03499         }
03500       case LESS_OR_EQUAL:
03501         max_rhs
03502           ? seq_var.build(i_constraint(max_included ? GREATER_OR_EQUAL : GREATER_THAN, q_max))
03503           : seq_var.assign(UNIVERSE);
03504         break;
03505       case LESS_THAN:
03506         max_rhs
03507           ? seq_var.build(i_constraint(GREATER_THAN, q_max))
03508           : seq_var.assign(UNIVERSE);
03509         break;
03510       default:
03511         // The NOT_EQUAL case has been already dealt with.
03512         throw std::runtime_error("PPL internal error");
03513       }
03514   }
03515 
03516   else {
03517     // The lhs is a constant value, so we just need to add the
03518     // appropriate constraint.
03519     const Coefficient& inhomo = lhs.inhomogeneous_term();
03520     switch (relsym) {
03521     case LESS_THAN:
03522       refine_with_constraint(inhomo < rhs);
03523       break;
03524     case LESS_OR_EQUAL:
03525       refine_with_constraint(inhomo <= rhs);
03526       break;
03527     case EQUAL:
03528       refine_with_constraint(inhomo == rhs);
03529       break;
03530     case GREATER_OR_EQUAL:
03531       refine_with_constraint(inhomo >= rhs);
03532       break;
03533     case GREATER_THAN:
03534       refine_with_constraint(inhomo > rhs);
03535       break;
03536     default:
03537       // The NOT_EQUAL case has been already dealt with.
03538       throw std::runtime_error("PPL internal error");
03539     }
03540   }
03541   PPL_ASSERT(OK());
03542 }

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

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:
var The left hand side variable of the generalized affine relation;
relsym The relation symbol;
expr The numerator of the right hand side affine expression;
denominator The denominator of the right hand side affine expression (optional argument with default value 1).
Exceptions:
std::invalid_argument Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of *this.

Definition at line 3131 of file Box.templates.hh.

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

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

03134                                                                           {
03135   // The denominator cannot be zero.
03136   if (denominator == 0)
03137     throw_generic("generalized_affine_image(v, r, e, d)", "d == 0");
03138 
03139   // Dimension-compatibility checks.
03140   const dimension_type space_dim = space_dimension();
03141   // The dimension of `expr' should not be greater than the dimension
03142   // of `*this'.
03143   if (space_dim < expr.space_dimension())
03144     throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
03145                                  "e", expr);
03146   // `var' should be one of the dimensions of the box.
03147   const dimension_type var_space_dim = var.space_dimension();
03148   if (space_dim < var_space_dim)
03149     throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
03150                                  "v", var);
03151 
03152   // The relation symbol cannot be a disequality.
03153   if (relsym == NOT_EQUAL)
03154     throw_generic("generalized_affine_image(v, r, e, d)",
03155                   "r is the disequality relation symbol");
03156 
03157   // First compute the affine image.
03158   affine_image(var, expr, denominator);
03159 
03160   if (relsym == EQUAL)
03161     // The affine relation is indeed an affine function.
03162     return;
03163 
03164   // Any image of an empty box is empty.
03165   if (is_empty())
03166     return;
03167 
03168   ITV& seq_var = seq[var.id()];
03169   switch (relsym) {
03170   case LESS_OR_EQUAL:
03171     seq_var.lower_extend();
03172     break;
03173   case LESS_THAN:
03174     seq_var.lower_extend();
03175     if (!seq_var.upper_is_boundary_infinity())
03176       seq_var.remove_sup();
03177     break;
03178   case GREATER_OR_EQUAL:
03179     seq_var.upper_extend();
03180     break;
03181   case GREATER_THAN:
03182     seq_var.upper_extend();
03183     if (!seq_var.lower_is_boundary_infinity())
03184       seq_var.remove_inf();
03185     break;
03186   default:
03187     // The EQUAL and NOT_EQUAL cases have been already dealt with.
03188     throw std::runtime_error("PPL internal error");
03189   }
03190   PPL_ASSERT(OK());
03191 }

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

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

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

Definition at line 3546 of file Box.templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Box< ITV >::generalized_affine_image(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::NOT_EQUAL, Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Box< ITV >::throw_generic().

03548                                                                     {
03549   // Dimension-compatibility checks.
03550   // The dimension of `lhs' should not be greater than the dimension
03551   // of `*this'.
03552   dimension_type lhs_space_dim = lhs.space_dimension();
03553   const dimension_type space_dim = space_dimension();
03554   if (space_dim < lhs_space_dim)
03555     throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
03556                                  "e1", lhs);
03557   // The dimension of `rhs' should not be greater than the dimension
03558   // of `*this'.
03559   const dimension_type rhs_space_dim = rhs.space_dimension();
03560   if (space_dim < rhs_space_dim)
03561     throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
03562                                  "e2", rhs);
03563 
03564   // The relation symbol cannot be a disequality.
03565   if (relsym == NOT_EQUAL)
03566     throw_generic("generalized_affine_image(e1, r, e2)",
03567                   "r is the disequality relation symbol");
03568 
03569   // Any image of an empty box is empty.
03570   if (marked_empty())
03571     return;
03572 
03573   // For any dimension occurring in the lhs, swap and change the sign
03574   // of this component for the rhs and lhs.  Then use these in a call
03575   // to generalized_affine_image/3.
03576   Linear_Expression revised_lhs = lhs;
03577   Linear_Expression revised_rhs = rhs;
03578   for (dimension_type d = lhs_space_dim; d-- > 0; ) {
03579     const Variable& var = Variable(d);
03580     if (lhs.coefficient(var) != 0) {
03581       PPL_DIRTY_TEMP(Coefficient, temp);
03582       temp = rhs.coefficient(var) + lhs.coefficient(var);
03583       revised_rhs -= temp * var;
03584       revised_lhs -= temp * var;
03585     }
03586   }
03587   generalized_affine_image(revised_lhs, relsym, revised_rhs);
03588   PPL_ASSERT(OK());
03589 }

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

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:
var The left hand side variable of the generalized affine relation;
relsym The relation symbol;
expr The numerator of the right hand side affine expression;
denominator The denominator of the right hand side affine expression (optional argument with default value 1).
Exceptions:
std::invalid_argument Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of *this.

Definition at line 3196 of file Box.templates.hh.

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

03200 {
03201   // The denominator cannot be zero.
03202   if (denominator == 0)
03203     throw_generic("generalized_affine_preimage(v, r, e, d)",
03204                            "d == 0");
03205 
03206   // Dimension-compatibility checks.
03207   const dimension_type space_dim = space_dimension();
03208   // The dimension of `expr' should not be greater than the dimension
03209   // of `*this'.
03210   if (space_dim < expr.space_dimension())
03211     throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
03212                                  "e", expr);
03213   // `var' should be one of the dimensions of the box.
03214   const dimension_type var_space_dim = var.space_dimension();
03215   if (space_dim < var_space_dim)
03216     throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
03217                                  "v", var);
03218   // The relation symbol cannot be a disequality.
03219   if (relsym == NOT_EQUAL)
03220     throw_generic("generalized_affine_preimage(v, r, e, d)",
03221                   "r is the disequality relation symbol");
03222 
03223   // Check whether the affine relation is indeed an affine function.
03224   if (relsym == EQUAL) {
03225     affine_preimage(var, expr, denominator);
03226     return;
03227   }
03228 
03229   // Compute the reversed relation symbol to simplify later coding.
03230   Relation_Symbol reversed_relsym;
03231   switch (relsym) {
03232   case LESS_THAN:
03233     reversed_relsym = GREATER_THAN;
03234     break;
03235   case LESS_OR_EQUAL:
03236     reversed_relsym = GREATER_OR_EQUAL;
03237     break;
03238   case GREATER_OR_EQUAL:
03239     reversed_relsym = LESS_OR_EQUAL;
03240     break;
03241   case GREATER_THAN:
03242     reversed_relsym = LESS_THAN;
03243     break;
03244   default:
03245     // The EQUAL and NOT_EQUAL cases have been already dealt with.
03246     throw std::runtime_error("PPL internal error");
03247   }
03248 
03249   // Check whether the preimage of this affine relation can be easily
03250   // computed as the image of its inverse relation.
03251   const Coefficient& var_coefficient = expr.coefficient(var);
03252   if (var_coefficient != 0) {
03253     Linear_Expression inverse_expr
03254       = expr - (denominator + var_coefficient) * var;
03255     PPL_DIRTY_TEMP_COEFFICIENT(inverse_denominator);
03256     neg_assign(inverse_denominator, var_coefficient);
03257     Relation_Symbol inverse_relsym
03258       = (sgn(denominator) == sgn(inverse_denominator))
03259       ? relsym : reversed_relsym;
03260     generalized_affine_image(var, inverse_relsym, inverse_expr,
03261                              inverse_denominator);
03262     return;
03263   }
03264 
03265   // Here `var_coefficient == 0', so that the preimage cannot
03266   // be easily computed by inverting the affine relation.
03267   // Shrink the box by adding the constraint induced
03268   // by the affine relation.
03269   // First, compute the maximum and minimum value reached by
03270   // `denominator*var' on the box as we need to use non-relational
03271   // expressions.
03272   PPL_DIRTY_TEMP(Coefficient, max_num);
03273   PPL_DIRTY_TEMP(Coefficient, max_den);
03274   bool max_included;
03275   bool bound_above = maximize(denominator*var, max_num, max_den, max_included);
03276   PPL_DIRTY_TEMP(Coefficient, min_num);
03277   PPL_DIRTY_TEMP(Coefficient, min_den);
03278   bool min_included;
03279   bool bound_below = minimize(denominator*var, min_num, min_den, min_included);
03280   // Use the correct relation symbol
03281   const Relation_Symbol corrected_relsym
03282     = (denominator > 0) ? relsym : reversed_relsym;
03283   // Revise the expression to take into account the denominator of the
03284   // maximum/minimim value for `var'.
03285   PPL_DIRTY_TEMP(Linear_Expression, revised_expr);
03286   dimension_type dim = space_dim;
03287   PPL_DIRTY_TEMP_COEFFICIENT(d);
03288   if (corrected_relsym == LESS_THAN || corrected_relsym == LESS_OR_EQUAL) {
03289     if (bound_below) {
03290       for ( ; dim > 0; dim--) {
03291         d = min_den * expr.coefficient(Variable(dim - 1));
03292         revised_expr += d * Variable(dim - 1);
03293       }
03294     }
03295   }
03296   else {
03297     if (bound_above) {
03298       for ( ; dim > 0; dim--) {
03299         d = max_den * expr.coefficient(Variable(dim - 1));
03300         revised_expr += d * Variable(dim - 1);
03301       }
03302     }
03303   }
03304 
03305   switch (corrected_relsym) {
03306   case LESS_THAN:
03307     if (bound_below)
03308       refine_with_constraint(min_num < revised_expr);
03309     break;
03310   case LESS_OR_EQUAL:
03311     if (bound_below)
03312       (min_included)
03313         ? refine_with_constraint(min_num <= revised_expr)
03314         : refine_with_constraint(min_num < revised_expr);
03315     break;
03316   case GREATER_OR_EQUAL:
03317     if (bound_above)
03318       (max_included)
03319         ? refine_with_constraint(max_num >= revised_expr)
03320         : refine_with_constraint(max_num > revised_expr);
03321     break;
03322   case GREATER_THAN:
03323     if (bound_above)
03324       refine_with_constraint(max_num > revised_expr);
03325     break;
03326   default:
03327     // The EQUAL and NOT_EQUAL cases have been already dealt with.
03328     throw std::runtime_error("PPL internal error");
03329   }
03330   // If the shrunk box is empty, its preimage is empty too.
03331   if (is_empty())
03332     return;
03333   ITV& seq_v = seq[var.id()];
03334   seq_v.assign(UNIVERSE);
03335   PPL_ASSERT(OK());
03336 }

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_argument Thrown if var is not a space dimension of *this.

Definition at line 143 of file Box.inlines.hh.

References Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

00143                                                {
00144   if (space_dimension() < var.space_dimension())
00145     throw_dimension_incompatible("get_interval(v)", "v", var);
00146 
00147   if (is_empty()) {
00148     static ITV empty_interval(EMPTY);
00149     return empty_interval;
00150   }
00151 
00152   return seq[var.id()];
00153 }

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::get_limiting_box ( const Constraint_System cs,
Box< ITV > &  limiting_box 
) const [inline, private]

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

Definition at line 3638 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::add_interval_constraint_no_check(), Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Box< ITV >::extract_interval_constraint(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::interval_relation(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), and Parma_Polyhedra_Library::Constraint::type().

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

03639                                                     {
03640   const dimension_type cs_space_dim = cs.space_dimension();
03641   // Private method: the caller has to ensure the following.
03642   PPL_ASSERT(cs_space_dim <= space_dimension());
03643 
03644   for (Constraint_System::const_iterator cs_i = cs.begin(),
03645          cs_end = cs.end(); cs_i != cs_end; ++cs_i) {
03646     const Constraint& c = *cs_i;
03647     dimension_type c_num_vars = 0;
03648     dimension_type c_only_var = 0;
03649     // Constraints that are not interval constraints are ignored.
03650     if (!extract_interval_constraint(c, cs_space_dim, c_num_vars, c_only_var))
03651       continue;
03652     // Trivial constraints are ignored.
03653     if (c_num_vars != 0) {
03654       // c is a non-trivial interval constraint.
03655       // add interval constraint to limiting box
03656       const Coefficient& n = c.inhomogeneous_term();
03657       const Coefficient& d = c.coefficient(Variable(c_only_var));
03658       if (interval_relation(seq[c_only_var], c.type(), n, d)
03659           == Poly_Con_Relation::is_included())
03660         limiting_box.add_interval_constraint_no_check(c_only_var, c.type(),
03661                                                       n, d);
03662     }
03663   }
03664 }

template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::get_lower_bound ( dimension_type  k,
bool &  closed,
Coefficient n,
Coefficient d 
) const [inline]

If the k-th space dimension is unbounded below, returns false. Otherwise returns true and set closed, n and d accordingly.

Let $I$ the interval corresponding to the k-th space dimension. If $I$ is not bounded from below, simply return false. Otherwise, set closed, n and d as follows: closed is set to true if the the lower boundary of $I$ is closed and is set to false otherwise; n and d are assigned the integers $n$ and $d$ such that the canonical fraction $n/d$ corresponds to the greatest lower bound of $I$. The fraction $n/d$ is in canonical form if and only if $n$ and $d$ have no common factors and $d$ is positive, $0/1$ being the unique representation for zero.

An undefined behavior is obtained if k is greater than or equal to the space dimension of *this.

Definition at line 260 of file Box.inlines.hh.

References Parma_Polyhedra_Library::assign_r(), and Parma_Polyhedra_Library::Box< ITV >::seq.

Referenced by Parma_Polyhedra_Library::Box< ITV >::congruences(), Parma_Polyhedra_Library::Box< ITV >::constraints(), Parma_Polyhedra_Library::Grid::Grid(), Parma_Polyhedra_Library::Box< ITV >::minimized_constraints(), and Parma_Polyhedra_Library::Polyhedron::Polyhedron().

00261                                                                 {
00262   PPL_ASSERT(k < seq.size());
00263   const ITV& seq_k = seq[k];
00264 
00265   if (seq_k.lower_is_boundary_infinity())
00266     return false;
00267 
00268   closed = !seq_k.lower_is_open();
00269 
00270   PPL_DIRTY_TEMP0(mpq_class, lr);
00271   assign_r(lr, seq_k.lower(), ROUND_NOT_NEEDED);
00272   n = lr.get_num();
00273   d = lr.get_den();
00274 
00275   return true;
00276 }

template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::get_upper_bound ( dimension_type  k,
bool &  closed,
Coefficient n,
Coefficient d 
) const [inline]

If the k-th space dimension is unbounded above, returns false. Otherwise returns true and set closed, n and d accordingly.

Let $I$ the interval corresponding to the k-th space dimension. If $I$ is not bounded from above, simply return false. Otherwise, set closed, n and d as follows: closed is set to true if the the upper boundary of $I$ is closed and is set to false otherwise; n and d are assigned the integers $n$ and $d$ such that the canonical fraction $n/d$ corresponds to the least upper bound of $I$.

An undefined behavior is obtained if k is greater than or equal to the space dimension of *this.

Definition at line 280 of file Box.inlines.hh.

References Parma_Polyhedra_Library::assign_r(), and Parma_Polyhedra_Library::Box< ITV >::seq.

Referenced by Parma_Polyhedra_Library::Box< ITV >::constraints(), Parma_Polyhedra_Library::Grid::Grid(), Parma_Polyhedra_Library::Box< ITV >::minimized_constraints(), and Parma_Polyhedra_Library::Polyhedron::Polyhedron().

00281                                                                 {
00282   PPL_ASSERT(k < seq.size());
00283   const ITV& seq_k = seq[k];
00284 
00285   if (seq_k.upper_is_boundary_infinity())
00286     return false;
00287 
00288   closed = !seq_k.upper_is_open();
00289 
00290   PPL_DIRTY_TEMP0(mpq_class, ur);
00291   assign_r(ur, seq_k.upper(), ROUND_NOT_NEEDED);
00292   n = ur.get_num();
00293   d = ur.get_den();
00294 
00295   return true;
00296 }

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

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

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

Definition at line 1711 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::reset_empty_up_to_date(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

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

01711                                           {
01712   Box& x = *this;
01713   const dimension_type space_dim = space_dimension();
01714 
01715   // Dimension-compatibility check.
01716   if (space_dim != y.space_dimension())
01717     x.throw_dimension_incompatible("intersection_assign(y)", y);
01718 
01719   // If one of the two boxes is empty, the intersection is empty.
01720   if (x.marked_empty())
01721     return;
01722   if (y.marked_empty()) {
01723     x.set_empty();
01724     return;
01725   }
01726 
01727   // If both boxes are zero-dimensional, then at this point they are
01728   // necessarily non-empty, so that their intersection is non-empty too.
01729   if (space_dim == 0)
01730     return;
01731 
01732   // FIXME: here we may conditionally exploit a capability of the
01733   // underlying interval to eagerly detect empty results.
01734   reset_empty_up_to_date();
01735 
01736   for (dimension_type k = space_dim; k-- > 0; )
01737     x.seq[k].intersect_assign(y.seq[k]);
01738 
01739   PPL_ASSERT(x.OK());
01740 }

template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::is_bounded (  )  const [inline]

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

Definition at line 1337 of file Box.templates.hh.

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

01337                            {
01338   if (is_empty())
01339     return true;
01340   for (dimension_type k = seq.size(); k-- > 0; )
01341     if (!seq[k].is_bounded())
01342       return false;
01343   return true;
01344 }

template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::is_discrete (  )  const [inline]

Returns true if and only if *this is discrete.

Definition at line 1326 of file Box.templates.hh.

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

01326                             {
01327   if (is_empty())
01328     return true;
01329   for (dimension_type k = seq.size(); k-- > 0; )
01330     if (!seq[k].is_singleton())
01331       return false;
01332   return true;
01333 }

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

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

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

Definition at line 1176 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

01176                                              {
01177   const Box& x = *this;
01178   // Dimension-compatibility check.
01179   if (x.space_dimension() != y.space_dimension())
01180     x.throw_dimension_incompatible("is_disjoint_from(y)", y);
01181 
01182   // If any of `x' or `y' is marked empty, then they are disjoint.
01183   // Note: no need to use `is_empty', as the following loop is anyway correct.
01184   if (x.marked_empty() || y.marked_empty())
01185     return true;
01186 
01187   for (dimension_type k = x.seq.size(); k-- > 0; )
01188     // FIXME: fix this name qualification issue.
01189     if (x.seq[k].is_disjoint_from(y.seq[k]))
01190       return true;
01191   return false;
01192 }

template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::is_empty (  )  const [inline]

Returns true if and only if *this is an empty box.

Definition at line 175 of file Box.inlines.hh.

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

Referenced by Parma_Polyhedra_Library::Box< ITV >::affine_dimension(), Parma_Polyhedra_Library::Box< ITV >::affine_image(), Parma_Polyhedra_Library::Box< ITV >::affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::Box< ITV >::bounds(), Parma_Polyhedra_Library::Box< ITV >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Box< ITV >::check_empty(), Parma_Polyhedra_Library::Box< ITV >::congruences(), Parma_Polyhedra_Library::Box< ITV >::constrains(), Parma_Polyhedra_Library::Box< ITV >::contains(), Parma_Polyhedra_Library::Box< ITV >::difference_assign(), Parma_Polyhedra_Library::Box< ITV >::fold_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::frequency(), Parma_Polyhedra_Library::Box< ITV >::get_interval(), Parma_Polyhedra_Library::Grid::Grid(), Parma_Polyhedra_Library::Box< ITV >::is_bounded(), Parma_Polyhedra_Library::Box< ITV >::is_discrete(), Parma_Polyhedra_Library::Box< ITV >::is_topologically_closed(), Parma_Polyhedra_Library::Box< ITV >::l_m_distance_assign(), Parma_Polyhedra_Library::Box< ITV >::map_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::max_min(), Parma_Polyhedra_Library::Box< ITV >::minimized_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::operator==(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::Pointset_Powerset(), Parma_Polyhedra_Library::Polyhedron::Polyhedron(), Parma_Polyhedra_Library::Box< ITV >::relation_with(), Parma_Polyhedra_Library::Box< ITV >::remove_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::set_interval(), Parma_Polyhedra_Library::Box< ITV >::simplify_using_context_assign(), Parma_Polyhedra_Library::Box< ITV >::time_elapse_assign(), Parma_Polyhedra_Library::Box< ITV >::topological_closure_assign(), and Parma_Polyhedra_Library::Box< ITV >::wrap_assign().

00175                          {
00176   return marked_empty() || check_empty();
00177 }

template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::is_topologically_closed (  )  const [inline]

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

Definition at line 1314 of file Box.templates.hh.

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

01314                                         {
01315   if (ITV::is_always_topologically_closed() || is_empty())
01316     return true;
01317 
01318   for (dimension_type k = seq.size(); k-- > 0; )
01319     if (!seq[k].is_topologically_closed())
01320       return false;
01321   return true;
01322 }

template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::is_universe (  )  const [inline]

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

Definition at line 1303 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), and Parma_Polyhedra_Library::Box< ITV >::seq.

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

01303                             {
01304   if (marked_empty())
01305     return false;
01306   for (dimension_type k = seq.size(); k-- > 0; )
01307     if (!seq[k].is_universe())
01308       return false;
01309   return true;
01310 }

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

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

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

Definition at line 3668 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::CC76_widening_assign(), Parma_Polyhedra_Library::Box< ITV >::contains(), Parma_Polyhedra_Library::Box< ITV >::get_limiting_box(), Parma_Polyhedra_Library::Box< ITV >::intersection_assign(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::throw_constraint_incompatible(), Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::UNIVERSE.

03670                                                           {
03671   Box& x = *this;
03672   const dimension_type space_dim = x.space_dimension();
03673 
03674   // Dimension-compatibility check.
03675   if (space_dim != y.space_dimension())
03676     throw_dimension_incompatible("limited_CC76_extrapolation_assign(y, cs)",
03677                                  y);
03678   // `cs' must be dimension-compatible with the two boxes.
03679   const dimension_type cs_space_dim = cs.space_dimension();
03680   if (space_dim < cs_space_dim)
03681     throw_constraint_incompatible("limited_CC76_extrapolation_assign(y, cs)");
03682 
03683   // The limited CC76-extrapolation between two boxes in a
03684   // zero-dimensional space is also a zero-dimensional box
03685   if (space_dim == 0)
03686     return;
03687 
03688 #ifndef NDEBUG
03689   {
03690     // We assume that `y' is contained in or equal to `*this'.
03691     const Box x_copy = *this;
03692     const Box y_copy = y;
03693     PPL_ASSERT(x_copy.contains(y_copy));
03694   }
03695 #endif
03696 
03697   // If `*this' is empty, since `*this' contains `y', `y' is empty too.
03698   if (marked_empty())
03699     return;
03700   // If `y' is empty, we return.
03701   if (y.marked_empty())
03702     return;
03703 
03704   // Build a limiting box using all the constraints in cs
03705   // that are satisfied by *this.
03706   Box limiting_box(space_dim, UNIVERSE);
03707   get_limiting_box(cs, limiting_box);
03708 
03709   x.CC76_widening_assign(y, tp);
03710 
03711   // Intersect the widened box with the limiting box.
03712   intersection_assign(limiting_box);
03713 }

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

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

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

The template type parameter Partial_Function must provide the following methods.

      bool has_empty_codomain() const

returns true if and only if the represented partial function has an empty 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 2053 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::swap().

02053                                                             {
02054   const dimension_type space_dim = space_dimension();
02055   if (space_dim == 0)
02056     return;
02057 
02058   if (pfunc.has_empty_codomain()) {
02059     // All dimensions vanish: the box becomes zero_dimensional.
02060     remove_higher_space_dimensions(0);
02061     return;
02062   }
02063 
02064   const dimension_type new_space_dim = pfunc.max_in_codomain() + 1;
02065   // If the box is empty, then simply adjust the space dimension.
02066   if (is_empty()) {
02067     remove_higher_space_dimensions(new_space_dim);
02068     return;
02069   }
02070 
02071   // We create a new Box with the new space dimension.
02072   Box<ITV> tmp(new_space_dim);
02073   // Map the intervals, exchanging the indexes.
02074   for (dimension_type i = 0; i < space_dim; ++i) {
02075     dimension_type new_i;
02076     if (pfunc.maps(i, new_i))
02077       seq[i].swap(tmp.seq[new_i]);
02078   }
02079   swap(tmp);
02080   PPL_ASSERT(OK());
02081 }

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

Returns true if and only if the box is known to be empty.

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

Definition at line 38 of file Box.inlines.hh.

References Parma_Polyhedra_Library::Box< ITV >::status, Parma_Polyhedra_Library::Box< ITV >::Status::test_empty(), and Parma_Polyhedra_Library::Box< ITV >::Status::test_empty_up_to_date().

Referenced by Parma_Polyhedra_Library::Box< ITV >::add_congruence_no_check(), Parma_Polyhedra_Library::Box< ITV >::add_constraint_no_check(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Box< ITV >::check_empty(), Parma_Polyhedra_Library::Box< ITV >::concatenate_assign(), Parma_Polyhedra_Library::Box< ITV >::congruences(), Parma_Polyhedra_Library::Box< ITV >::constrains(), Parma_Polyhedra_Library::Box< ITV >::constraints(), Parma_Polyhedra_Library::Box< ITV >::contains_integer_point(), Parma_Polyhedra_Library::Box< ITV >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Box< ITV >::generalized_affine_preimage(), Parma_Polyhedra_Library::Box< ITV >::intersection_assign(), Parma_Polyhedra_Library::Box< ITV >::is_disjoint_from(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::is_universe(), Parma_Polyhedra_Library::Box< ITV >::l_m_distance_assign(), Parma_Polyhedra_Library::Box< ITV >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::Box< ITV >::max_min(), Parma_Polyhedra_Library::Box< ITV >::minimized_constraints(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::propagate_constraint(), Parma_Polyhedra_Library::Box< ITV >::propagate_constraints(), Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::refine_with_congruence(), Parma_Polyhedra_Library::Box< ITV >::refine_with_congruences(), Parma_Polyhedra_Library::Box< ITV >::refine_with_constraint(), Parma_Polyhedra_Library::Box< ITV >::refine_with_constraints(), Parma_Polyhedra_Library::Box< ITV >::simplify_using_context_assign(), Parma_Polyhedra_Library::Box< ITV >::time_elapse_assign(), Parma_Polyhedra_Library::Box< ITV >::unconstrain(), Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign(), and Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign_if_exact().

00038                              {
00039   return status.test_empty_up_to_date() && status.test_empty();
00040 }

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 [inline, private]

Maximizes or minimizes expr subject to *this.

Parameters:
expr The linear expression to be maximized or minimized subject to *this;
maximize true if maximization is what is wanted;
ext_n The numerator of the extremum value;
ext_d The denominator of the extremum value;
included true if and only if the extremum of expr can actually be reached in * this;
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

If *this is empty or expr is not bounded in the appropriate direction, false is returned and ext_n, ext_d, included and point are left untouched.

Definition at line 1003 of file Box.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_canonical(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

01006                                         {
01007   // `expr' should be dimension-compatible with `*this'.
01008   const dimension_type space_dim = space_dimension();
01009   const dimension_type expr_space_dim = expr.space_dimension();
01010   if (space_dim < expr_space_dim)
01011     throw_dimension_incompatible((maximize
01012                                   ? "maximize(e, ...)"
01013                                   : "minimize(e, ...)"), "e", expr);
01014   // Deal with zero-dim Box first.
01015   if (space_dim == 0) {
01016     if (marked_empty())
01017       return false;
01018     else {
01019       ext_n = expr.inhomogeneous_term();
01020       ext_d = 1;
01021       included = true;
01022       return true;
01023     }
01024   }
01025 
01026   // For an empty Box we simply return false.
01027   if (is_empty())
01028     return false;
01029 
01030   PPL_DIRTY_TEMP0(mpq_class, result);
01031   assign_r(result, expr.inhomogeneous_term(), ROUND_NOT_NEEDED);
01032   bool is_included = true;
01033   const int maximize_sign = maximize ? 1 : -1;
01034   PPL_DIRTY_TEMP0(mpq_class, bound_i);
01035   PPL_DIRTY_TEMP0(mpq_class, expr_i);
01036   for (dimension_type i = expr_space_dim; i-- > 0; ) {
01037     const ITV& seq_i = seq[i];
01038     assign_r(expr_i, expr.coefficient(Variable(i)), ROUND_NOT_NEEDED);
01039     switch (sgn(expr_i) * maximize_sign) {
01040     case 1:
01041       if (seq_i.upper_is_boundary_infinity())
01042         return false;
01043       assign_r(bound_i, seq_i.upper(), ROUND_NOT_NEEDED);
01044       add_mul_assign_r(result, bound_i, expr_i, ROUND_NOT_NEEDED);
01045       if (seq_i.upper_is_open())
01046         is_included = false;
01047       break;
01048     case 0:
01049       // Nothing to do.
01050       break;
01051     case -1:
01052       if (seq_i.lower_is_boundary_infinity())
01053         return false;
01054       assign_r(bound_i, seq_i.lower(), ROUND_NOT_NEEDED);
01055       add_mul_assign_r(result, bound_i, expr_i, ROUND_NOT_NEEDED);
01056       if (seq_i.lower_is_open())
01057         is_included = false;
01058       break;
01059     }
01060   }
01061   // Extract output info.
01062   PPL_ASSERT(is_canonical(result));
01063   ext_n = result.get_num();
01064   ext_d = result.get_den();
01065   included = is_included;
01066   return true;
01067 }

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 [inline, private]

Maximizes or minimizes expr subject to *this.

Parameters:
expr The linear expression to be maximized or minimized subject to *this;
maximize true if maximization is what is wanted;
ext_n The numerator of the extremum value;
ext_d The denominator of the extremum value;
included true if and only if the extremum of expr can actually be reached in *this;
g When maximization or minimization succeeds, will be assigned a point or closure point where expr reaches the corresponding extremum value.
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

If *this is empty or expr is not bounded in the appropriate direction, false is returned and ext_n, ext_d, included and g are left untouched.

Definition at line 1071 of file Box.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::lcm_assign(), Parma_Polyhedra_Library::Generator::point(), Parma_Polyhedra_Library::Box< ITV >::seq, and Parma_Polyhedra_Library::Box< ITV >::space_dimension().

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

01075                                       {
01076   if (!max_min(expr, maximize, ext_n, ext_d, included))
01077     return false;
01078 
01079   // Compute generator `g'.
01080   Linear_Expression g_expr;
01081   PPL_DIRTY_TEMP(Coefficient, g_divisor);
01082   g_divisor = 1;
01083   const int maximize_sign = maximize ? 1 : -1;
01084   PPL_DIRTY_TEMP0(mpq_class, g_coord);
01085   PPL_DIRTY_TEMP(Coefficient, num);
01086   PPL_DIRTY_TEMP(Coefficient, den);
01087   PPL_DIRTY_TEMP(Coefficient, lcm);
01088   PPL_DIRTY_TEMP(Coefficient, factor);
01089   for (dimension_type i = space_dimension(); i-- > 0; ) {
01090     const ITV& seq_i = seq[i];
01091     switch (sgn(expr.coefficient(Variable(i))) * maximize_sign) {
01092     case 1:
01093       assign_r(g_coord, seq_i.upper(), ROUND_NOT_NEEDED);
01094       break;
01095     case 0:
01096       // If 0 belongs to the interval, choose it
01097       // (and directly proceed to the next iteration).
01098       // FIXME: name qualification issue.
01099       if (seq_i.contains(0))
01100         continue;
01101       if (!seq_i.lower_is_boundary_infinity())
01102         if (seq_i.lower_is_open())
01103           if (!seq_i.upper_is_boundary_infinity())
01104             if (seq_i.upper_is_open()) {
01105               // Bounded and open interval: compute middle point.
01106               assign_r(g_coord, seq_i.lower(), ROUND_NOT_NEEDED);
01107               PPL_DIRTY_TEMP0(mpq_class, q_seq_i_upper);
01108               assign_r(q_seq_i_upper, seq_i.upper(), ROUND_NOT_NEEDED);
01109               g_coord += q_seq_i_upper;
01110               g_coord /= 2;
01111             }
01112             else
01113               // The upper bound is in the interval.
01114               assign_r(g_coord, seq_i.upper(), ROUND_NOT_NEEDED);
01115           else {
01116             // Lower is open, upper is unbounded.
01117             assign_r(g_coord, seq_i.lower(), ROUND_NOT_NEEDED);
01118             ++g_coord;
01119           }
01120         else
01121           // The lower bound is in the interval.
01122           assign_r(g_coord, seq_i.lower(), ROUND_NOT_NEEDED);
01123       else {
01124         // Lower is unbounded, hence upper is bounded
01125         // (since we know that 0 does not belong to the interval).
01126         PPL_ASSERT(!seq_i.upper_is_boundary_infinity());
01127         assign_r(g_coord, seq_i.upper(), ROUND_NOT_NEEDED);
01128         if (seq_i.upper_is_open())
01129           --g_coord;
01130       }
01131       break;
01132     case -1:
01133       assign_r(g_coord, seq_i.lower(), ROUND_NOT_NEEDED);
01134       break;
01135     }
01136     // Add g_coord * Variable(i) to the generator.
01137     assign_r(den, g_coord.get_den(), ROUND_NOT_NEEDED);
01138     lcm_assign(lcm, g_divisor, den);
01139     exact_div_assign(factor, lcm, g_divisor);
01140     g_expr *= factor;
01141     exact_div_assign(factor, lcm, den);
01142     assign_r(num, g_coord.get_num(), ROUND_NOT_NEEDED);
01143     num *= factor;
01144     g_expr += num * Variable(i);
01145     g_divisor = lcm;
01146   }
01147   g = Generator::point(g_expr, g_divisor);
01148   return true;
01149 }

template<typename ITV >
dimension_type Parma_Polyhedra_Library::Box< ITV >::max_space_dimension (  )  [inline, static]

Returns the maximum space dimension that a Box can handle.

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

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

00128                               {
00129   // One dimension is reserved to have a value of type dimension_type
00130   // that does not represent a legal dimension.
00131   return Sequence().max_size() - 1;
00132 }

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:
expr The linear expression to be maximized subject to *this;
sup_n The numerator of the supremum value;
sup_d The denominator of the supremum value;
maximum true if and only if the supremum is also the maximum value;
g When maximization succeeds, will be assigned the point or closure point where expr reaches its supremum value.
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

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

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

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

00203                                        {
00204   return max_min(expr, true, sup_n, sup_d, maximum, g);
00205 }

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:
expr The linear expression to be maximized subject to *this;
sup_n The numerator of the supremum value;
sup_d The denominator of the supremum value;
maximum true if and only if the supremum is also the maximum value.
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

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

Definition at line 193 of file Box.inlines.hh.

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

00195                                         {
00196   return max_min(expr, true, sup_n, sup_d, maximum);
00197 }

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:
expr The linear expression to be minimized subject to *this;
inf_n The numerator of the infimum value;
inf_d The denominator of the infimum value;
minimum true if and only if the infimum is also the minimum value;
g When minimization succeeds, will be assigned a point or closure point where expr reaches its infimum value.
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

If *this is empty or expr is not bounded from below, false is returned and inf_n, inf_d, minimum and g are left untouched.

Definition at line 217 of file Box.inlines.hh.

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

00219                                        {
00220   return max_min(expr, false, inf_n, inf_d, minimum, g);
00221 }

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:
expr The linear expression to be minimized subject to *this;
inf_n The numerator of the infimum value;
inf_d The denominator of the infimum value;
minimum true if and only if the infimum is also the minimum value.
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

If *this is empty or expr is not bounded from below, false is returned and inf_n, inf_d and minimum are left untouched.

Definition at line 209 of file Box.inlines.hh.

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

00211                                         {
00212   return max_min(expr, false, inf_n, inf_d, minimum);
00213 }

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 370 of file Box.inlines.hh.

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

00370                                       {
00371   // Only equalities can be congruences and these are already minimized.
00372   return congruences();
00373 }

template<typename ITV >
Constraint_System Parma_Polyhedra_Library::Box< ITV >::minimized_constraints (  )  const [inline]

Returns a minimized system of constraints defining *this.

Definition at line 3804 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::get_lower_bound(), Parma_Polyhedra_Library::Box< ITV >::get_upper_bound(), Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Constraint_System::zero_dim_empty().

03804                                       {
03805   Constraint_System cs;
03806   const dimension_type space_dim = space_dimension();
03807   if (space_dim == 0) {
03808     if (marked_empty())
03809       cs = Constraint_System::zero_dim_empty();
03810   }
03811   // Make sure emptiness is detected.
03812   else if (is_empty())
03813     cs.insert(0*Variable(space_dim-1) <= -1);
03814   else {
03815     // KLUDGE: in the future `cs' will be constructed of the right dimension.
03816     // For the time being, we force the dimension with the following line.
03817     cs.insert(0*Variable(space_dim-1) <= 0);
03818 
03819     for (dimension_type k = 0; k < space_dim; ++k) {
03820       bool closed = false;
03821       PPL_DIRTY_TEMP(Coefficient, n);
03822       PPL_DIRTY_TEMP(Coefficient, d);
03823       if (get_lower_bound(k, closed, n, d)) {
03824         if (closed)
03825           // Make sure equality constraints are detected.
03826           if (seq[k].is_singleton()) {
03827             cs.insert(d*Variable(k) == n);
03828             continue;
03829           }
03830           else
03831             cs.insert(d*Variable(k) >= n);
03832         else
03833           cs.insert(d*Variable(k) > n);
03834       }
03835       if (get_upper_bound(k, closed, n, d)) {
03836         if (closed)
03837           cs.insert(d*Variable(k) <= n);
03838         else
03839           cs.insert(d*Variable(k) < n);
03840       }
03841     }
03842   }
03843   return cs;
03844 }

template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::OK (  )  const [inline]

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

Definition at line 1245 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::check_empty(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::reset_empty_up_to_date(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::status, Parma_Polyhedra_Library::Box< ITV >::Status::test_empty(), and Parma_Polyhedra_Library::Box< ITV >::Status::test_empty_up_to_date().

Referenced by Parma_Polyhedra_Library::Box< ITV >::add_congruences_no_check(), Parma_Polyhedra_Library::Box< ITV >::add_constraints_no_check(), Parma_Polyhedra_Library::Box< ITV >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Box< ITV >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::Box< ITV >::affine_image(), Parma_Polyhedra_Library::Box< ITV >::affine_preimage(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Box< ITV >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Box< ITV >::CC76_widening_assign(), Parma_Polyhedra_Library::Box< ITV >::concatenate_assign(), Parma_Polyhedra_Library::Box< ITV >::difference_assign(), Parma_Polyhedra_Library::Box< ITV >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Box< ITV >::expand_space_dimension(), Parma_Polyhedra_Library::Box< ITV >::generalized_affine_preimage(), Parma_Polyhedra_Library::Box< ITV >::intersection_assign(), Parma_Polyhedra_Library::Box< ITV >::map_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::remove_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::set_interval(), Parma_Polyhedra_Library::Box< ITV >::simplify_using_context_assign(), Parma_Polyhedra_Library::Box< ITV >::time_elapse_assign(), Parma_Polyhedra_Library::Box< ITV >::unconstrain(), Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign(), and Parma_Polyhedra_Library::Box< ITV >::wrap_assign().

01245                    {
01246   if (status.test_empty_up_to_date() && !status.test_empty()) {
01247     Box tmp = *this;
01248     tmp.reset_empty_up_to_date();
01249     if (tmp.check_empty()) {
01250 #ifndef NDEBUG
01251       std::cerr << "The box is empty, but it is marked as non-empty."
01252                 << std::endl;
01253 #endif // NDEBUG
01254       return false;
01255     }
01256   }
01257 
01258   // A box that is not marked empty must have meaningful intervals.
01259   if (!marked_empty()) {
01260     for (dimension_type k = seq.size(); k-- > 0; )
01261       if (!seq[k].OK())
01262         return false;
01263   }
01264 
01265   return true;
01266 }

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.

00076                                 {
00077   seq = y.seq;
00078   status = y.status;
00079   return *this;
00080 }

template<typename ITV >
const ITV & Parma_Polyhedra_Library::Box< ITV >::operator[] ( dimension_type  k  )  const [inline, private]

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

Definition at line 136 of file Box.inlines.hh.

References Parma_Polyhedra_Library::Box< ITV >::seq.

00136                                                  {
00137   PPL_ASSERT(k < seq.size());
00138   return seq[k];
00139 }

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:
c The constraint to be used for constraint propagation.
Exceptions:
std::invalid_argument Thrown if *this and c are dimension-incompatible.

Definition at line 496 of file Box.inlines.hh.

References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::propagate_constraint_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

00496                                                   {
00497   const dimension_type c_space_dim = c.space_dimension();
00498   // Dimension-compatibility check.
00499   if (c_space_dim > space_dimension())
00500     throw_dimension_incompatible("propagate_constraint(c)", c);
00501 
00502   // If the box is already empty, there is nothing left to do.
00503   if (marked_empty())
00504     return;
00505 
00506   propagate_constraint_no_check(c);
00507 }

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::propagate_constraint_no_check ( const Constraint c  )  [inline, private]

Propagates the constraint c to refine *this.

Parameters:
c The 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 2327 of file Box.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::Constraint::NONSTRICT_INEQUALITY, Parma_Polyhedra_Library::Box< ITV >::reset_empty_up_to_date(), Parma_Polyhedra_Library::Checked::Result, Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Constraint::STRICT_INEQUALITY, Parma_Polyhedra_Library::T_MAYBE, Parma_Polyhedra_Library::T_NO, Parma_Polyhedra_Library::T_YES, and Parma_Polyhedra_Library::Constraint::type().

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

02327                                                            {
02328   PPL_ASSERT(c.space_dimension() <= space_dimension());
02329 
02330   typedef
02331     typename Select_Temp_Boundary_Type<typename ITV::boundary_type>::type
02332     Temp_Boundary_Type;
02333 
02334   const dimension_type c_space_dim = c.space_dimension();
02335   const Constraint::Type c_type = c.type();
02336   const Coefficient& c_inhomogeneous_term = c.inhomogeneous_term();
02337 
02338   // Find a space dimension having a non-zero coefficient (if any).
02339   dimension_type last_k = c_space_dim;
02340   for (dimension_type k = c_space_dim; k-- > 0; ) {
02341     if (c.coefficient(Variable(k)) != 0) {
02342       last_k = k;
02343       break;
02344     }
02345   }
02346   if (last_k == c_space_dim) {
02347     // Constraint c is trivial: check if it is inconsistent.
02348     if (c_inhomogeneous_term < 0
02349         || (c_inhomogeneous_term == 0
02350             && c_type != Constraint::NONSTRICT_INEQUALITY))
02351       set_empty();
02352     return;
02353   }
02354 
02355   // Here constraint c is non-trivial.
02356   PPL_ASSERT(last_k < c_space_dim);
02357   Result r;
02358   Temp_Boundary_Type t_bound;
02359   Temp_Boundary_Type t_a;
02360   Temp_Boundary_Type t_x;
02361   Ternary open;
02362   for (dimension_type k = last_k+1; k-- > 0; ) {
02363     const Coefficient& a_k = c.coefficient(Variable(k));
02364     int sgn_a_k = sgn(a_k);
02365     if (sgn_a_k == 0)
02366       continue;
02367     if (sgn_a_k > 0) {
02368       open = (c_type == Constraint::STRICT_INEQUALITY) ? T_YES : T_NO;
02369       if (open == T_NO)
02370         maybe_reset_fpu_inexact<Temp_Boundary_Type>();
02371       r = assign_r(t_bound, c_inhomogeneous_term, ROUND_UP);
02372       if (propagate_constraint_check_result(r, open))
02373         goto maybe_refine_upper_1;
02374       r = neg_assign_r(t_bound, t_bound, ROUND_DOWN);
02375       if (propagate_constraint_check_result(r, open))
02376         goto maybe_refine_upper_1;
02377       for (dimension_type i = last_k+1; i-- > 0; ) {
02378         if (i == k)
02379           continue;
02380         const Coefficient& a_i = c.coefficient(Variable(i));
02381         int sgn_a_i = sgn(a_i);
02382         if (sgn_a_i == 0)
02383           continue;
02384         ITV& x_i = seq[i];
02385         if (sgn_a_i < 0) {
02386           if (x_i.lower_is_boundary_infinity())
02387             goto maybe_refine_upper_1;
02388           r = assign_r(t_a, a_i, ROUND_DOWN);
02389           if (propagate_constraint_check_result(r, open))
02390             goto maybe_refine_upper_1;
02391           r = assign_r(t_x, x_i.lower(), ROUND_DOWN);
02392           if (propagate_constraint_check_result(r, open))
02393             goto maybe_refine_upper_1;
02394           if (x_i.lower_is_open())
02395             open = T_YES;
02396           r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_DOWN);
02397           if (propagate_constraint_check_result(r, open))
02398             goto maybe_refine_upper_1;
02399         }
02400         else {
02401           PPL_ASSERT(sgn_a_i > 0);
02402           if (x_i.upper_is_boundary_infinity())
02403             goto maybe_refine_upper_1;
02404           r = assign_r(t_a, a_i, ROUND_UP);
02405           if (propagate_constraint_check_result(r, open))
02406             goto maybe_refine_upper_1;
02407           r = assign_r(t_x, x_i.upper(), ROUND_UP);
02408           if (propagate_constraint_check_result(r, open))
02409             goto maybe_refine_upper_1;
02410           if (x_i.upper_is_open())
02411             open = T_YES;
02412           r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_DOWN);
02413           if (propagate_constraint_check_result(r, open))
02414             goto maybe_refine_upper_1;
02415         }
02416       }
02417       r = assign_r(t_a, a_k, ROUND_UP);
02418       if (propagate_constraint_check_result(r, open))
02419         goto maybe_refine_upper_1;
02420       r = div_assign_r(t_bound, t_bound, t_a, ROUND_DOWN);
02421       if (propagate_constraint_check_result(r, open))
02422         goto maybe_refine_upper_1;
02423 
02424       // Refine the lower bound of `seq[k]' with `t_bound'.
02425       if (open == T_MAYBE
02426           && maybe_check_fpu_inexact<Temp_Boundary_Type>() == 1)
02427         open = T_YES;
02428       seq[k].add_constraint(i_constraint(open == T_YES ? GREATER_THAN : GREATER_OR_EQUAL, t_bound));
02429       reset_empty_up_to_date();
02430     maybe_refine_upper_1:
02431       if (c_type != Constraint::EQUALITY)
02432         continue;
02433       open = T_NO;
02434       maybe_reset_fpu_inexact<Temp_Boundary_Type>();
02435       r = assign_r(t_bound, c_inhomogeneous_term, ROUND_DOWN);
02436       if (propagate_constraint_check_result(r, open))
02437         goto next_k;
02438       r = neg_assign_r(t_bound, t_bound, ROUND_UP);
02439       if (propagate_constraint_check_result(r, open))
02440         goto next_k;
02441       for (dimension_type i = c_space_dim; i-- > 0; ) {
02442         if (i == k)
02443           continue;
02444         const Coefficient& a_i = c.coefficient(Variable(i));
02445         int sgn_a_i = sgn(a_i);
02446         if (sgn_a_i == 0)
02447           continue;
02448         ITV& x_i = seq[i];
02449         if (sgn_a_i < 0) {
02450           if (x_i.upper_is_boundary_infinity())
02451             goto next_k;
02452           r = assign_r(t_a, a_i, ROUND_UP);
02453           if (propagate_constraint_check_result(r, open))
02454             goto next_k;
02455           r = assign_r(t_x, x_i.upper(), ROUND_UP);
02456           if (propagate_constraint_check_result(r, open))
02457             goto next_k;
02458           if (x_i.upper_is_open())
02459             open = T_YES;
02460           r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_UP);
02461           if (propagate_constraint_check_result(r, open))
02462             goto next_k;
02463         }
02464         else {
02465           PPL_ASSERT(sgn_a_i > 0);
02466           if (x_i.lower_is_boundary_infinity())
02467             goto next_k;
02468           r = assign_r(t_a, a_i, ROUND_DOWN);
02469           if (propagate_constraint_check_result(r, open))
02470             goto next_k;
02471           r = assign_r(t_x, x_i.lower(), ROUND_DOWN);
02472           if (propagate_constraint_check_result(r, open))
02473             goto next_k;
02474           if (x_i.lower_is_open())
02475             open = T_YES;
02476           r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_UP);
02477           if (propagate_constraint_check_result(r, open))
02478             goto next_k;
02479         }
02480       }
02481       r = assign_r(t_a, a_k, ROUND_DOWN);
02482       if (propagate_constraint_check_result(r, open))
02483         goto next_k;
02484       r = div_assign_r(t_bound, t_bound, t_a, ROUND_UP);
02485       if (propagate_constraint_check_result(r, open))
02486         goto next_k;
02487 
02488       // Refine the upper bound of seq[k] with t_bound.
02489       if (open == T_MAYBE
02490           && maybe_check_fpu_inexact<Temp_Boundary_Type>() == 1)
02491         open = T_YES;
02492       seq[k].add_constraint(i_constraint(open == T_YES ? LESS_THAN : LESS_OR_EQUAL, t_bound));
02493       reset_empty_up_to_date();
02494     }
02495     else {
02496       PPL_ASSERT(sgn_a_k < 0);
02497       open = (c_type == Constraint::STRICT_INEQUALITY) ? T_YES : T_NO;
02498       if (open == T_NO)
02499         maybe_reset_fpu_inexact<Temp_Boundary_Type>();
02500       r = assign_r(t_bound, c_inhomogeneous_term, ROUND_UP);
02501       if (propagate_constraint_check_result(r, open))
02502         goto maybe_refine_upper_2;
02503       r = neg_assign_r(t_bound, t_bound, ROUND_DOWN);
02504       if (propagate_constraint_check_result(r, open))
02505         goto maybe_refine_upper_2;
02506       for (dimension_type i = c_space_dim; i-- > 0; ) {
02507         if (i == k)
02508           continue;
02509         const Coefficient& a_i = c.coefficient(Variable(i));
02510         int sgn_a_i = sgn(a_i);
02511         if (sgn_a_i == 0)
02512           continue;
02513         ITV& x_i = seq[i];
02514         if (sgn_a_i < 0) {
02515           if (x_i.lower_is_boundary_infinity())
02516             goto maybe_refine_upper_2;
02517           r = assign_r(t_a, a_i, ROUND_DOWN);
02518           if (propagate_constraint_check_result(r, open))
02519             goto maybe_refine_upper_2;
02520           r = assign_r(t_x, x_i.lower(), ROUND_DOWN);
02521           if (propagate_constraint_check_result(r, open))
02522             goto maybe_refine_upper_2;
02523           if (x_i.lower_is_open())
02524             open = T_YES;
02525           r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_UP);
02526           if (propagate_constraint_check_result(r, open))
02527             goto maybe_refine_upper_2;
02528         }
02529         else {
02530           PPL_ASSERT(sgn_a_i > 0);
02531           if (x_i.upper_is_boundary_infinity())
02532             goto maybe_refine_upper_2;
02533           r = assign_r(t_a, a_i, ROUND_UP);
02534           if (propagate_constraint_check_result(r, open))
02535             goto maybe_refine_upper_2;
02536           r = assign_r(t_x, x_i.upper(), ROUND_UP);
02537           if (propagate_constraint_check_result(r, open))
02538             goto maybe_refine_upper_2;
02539           if (x_i.upper_is_open())
02540             open = T_YES;
02541           r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_DOWN);
02542           if (propagate_constraint_check_result(r, open))
02543             goto maybe_refine_upper_2;
02544         }
02545       }
02546       r = assign_r(t_a, a_k, ROUND_UP);
02547       if (propagate_constraint_check_result(r, open))
02548         goto maybe_refine_upper_2;
02549       r = div_assign_r(t_bound, t_bound, t_a, ROUND_UP);
02550       if (propagate_constraint_check_result(r, open))
02551         goto maybe_refine_upper_2;
02552 
02553       // Refine the upper bound of seq[k] with t_bound.
02554       if (open == T_MAYBE
02555           && maybe_check_fpu_inexact<Temp_Boundary_Type>() == 1)
02556         open = T_YES;
02557       seq[k].add_constraint(i_constraint(open == T_YES ? LESS_THAN : LESS_OR_EQUAL, t_bound));
02558       reset_empty_up_to_date();
02559     maybe_refine_upper_2:
02560       if (c_type != Constraint::EQUALITY)
02561         continue;
02562       open = T_NO;
02563       maybe_reset_fpu_inexact<Temp_Boundary_Type>();
02564       r = assign_r(t_bound, c_inhomogeneous_term, ROUND_DOWN);
02565       if (propagate_constraint_check_result(r, open))
02566         goto next_k;
02567       r = neg_assign_r(t_bound, t_bound, ROUND_UP);
02568       if (propagate_constraint_check_result(r, open))
02569         goto next_k;
02570       for (dimension_type i = c_space_dim; i-- > 0; ) {
02571         if (i == k)
02572           continue;
02573         const Coefficient& a_i = c.coefficient(Variable(i));
02574         int sgn_a_i = sgn(a_i);
02575         if (sgn_a_i == 0)
02576           continue;
02577         ITV& x_i = seq[i];
02578         if (sgn_a_i < 0) {
02579           if (x_i.upper_is_boundary_infinity())
02580             goto next_k;
02581           r = assign_r(t_a, a_i, ROUND_UP);
02582           if (propagate_constraint_check_result(r, open))
02583             goto next_k;
02584           r = assign_r(t_x, x_i.upper(), ROUND_UP);
02585           if (propagate_constraint_check_result(r, open))
02586             goto next_k;
02587           if (x_i.upper_is_open())
02588             open = T_YES;
02589           r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_UP);
02590           if (propagate_constraint_check_result(r, open))
02591             goto next_k;
02592         }
02593         else {
02594           PPL_ASSERT(sgn_a_i > 0);
02595           if (x_i.lower_is_boundary_infinity())
02596             goto next_k;
02597           r = assign_r(t_a, a_i, ROUND_DOWN);
02598           if (propagate_constraint_check_result(r, open))
02599             goto next_k;
02600           r = assign_r(t_x, x_i.lower(), ROUND_DOWN);
02601           if (propagate_constraint_check_result(r, open))
02602             goto next_k;
02603           if (x_i.lower_is_open())
02604             open = T_YES;
02605           r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_UP);
02606           if (propagate_constraint_check_result(r, open))
02607             goto next_k;
02608         }
02609       }
02610       r = assign_r(t_a, a_k, ROUND_DOWN);
02611       if (propagate_constraint_check_result(r, open))
02612         goto next_k;
02613       r = div_assign_r(t_bound, t_bound, t_a, ROUND_DOWN);
02614       if (propagate_constraint_check_result(r, open))
02615         goto next_k;
02616 
02617       // Refine the lower bound of seq[k] with t_bound.
02618       if (open == T_MAYBE
02619           && maybe_check_fpu_inexact<Temp_Boundary_Type>() == 1)
02620         open = T_YES;
02621       seq[k].add_constraint(i_constraint(open == T_YES ? GREATER_THAN : GREATER_OR_EQUAL, t_bound));
02622       reset_empty_up_to_date();
02623     }
02624   next_k:
02625     ;
02626   }
02627 }

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 propagagion on *this.

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

Definition at line 511 of file Box.inlines.hh.

References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::propagate_constraints_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

00512                                                                      {
00513   // Dimension-compatibility check.
00514   if (cs.space_dimension() > space_dimension())
00515     throw_dimension_incompatible("propagate_constraints(cs)", cs);
00516 
00517   // If the box is already empty, there is nothing left to do.
00518   if (marked_empty())
00519     return;
00520 
00521   propagate_constraints_no_check(cs, max_iterations);
00522 }

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::propagate_constraints_no_check ( const Constraint_System cs,
dimension_type  max_iterations 
) [inline, private]

Propagates the constraints in cs to refine *this.

Parameters:
cs The constraints to be propagated.
max_iterations The maximum number of propagation steps for each constraint in cs. If zero, the number of propagations will be unbounded, possibly resulting in an infinite loop.
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 2690 of file Box.templates.hh.

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

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

02691                                                                       {
02692   const dimension_type space_dim = space_dimension();
02693   PPL_ASSERT(cs.space_dimension() <= space_dim);
02694 
02695   const Constraint_System::const_iterator cs_begin = cs.begin();
02696   const Constraint_System::const_iterator cs_end = cs.end();
02697   const dimension_type cs_size = std::distance(cs_begin, cs_end);
02698   const dimension_type propagation_weight = cs_size * space_dim;
02699 
02700   Sequence copy;
02701   bool changed;
02702   dimension_type num_iterations = 0;
02703   do {
02704     WEIGHT_BEGIN();
02705     ++num_iterations;
02706     copy = seq;
02707     for (Constraint_System::const_iterator i = cs_begin; i != cs_end; ++i)
02708       propagate_constraint_no_check(*i);
02709 
02710     WEIGHT_ADD_MUL(40, propagation_weight);
02711     // Check if the client has requested abandoning all expensive
02712     // computations.  If so, the exception specified by the client
02713     // is thrown now.
02714     maybe_abandon();
02715 
02716     // NOTE: if max_iterations == 0 (i.e., no iteration limit is set)
02717     // the following test will anyway trigger on wrap around.
02718     if (num_iterations == max_iterations)
02719       break;
02720 
02721     changed = (copy != seq);
02722   } while (changed);
02723 }

template<typename ITV >
I_Result Parma_Polyhedra_Library::Box< ITV >::refine_interval_no_check ( ITV &  itv,
Constraint::Type  type,
Coefficient_traits::const_reference  num,
Coefficient_traits::const_reference  den 
) [inline, static, private]

WRITE ME.

Definition at line 377 of file Box.inlines.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::Constraint::NONSTRICT_INEQUALITY, and Parma_Polyhedra_Library::Constraint::STRICT_INEQUALITY.

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

00380                                                                           {
00381   PPL_ASSERT(den != 0);
00382   // The interval constraint is of the form
00383   // `var + num / den rel 0',
00384   // where `rel' is either the relation `==', `>=', or `>'.
00385   // For the purpose of refining the interval, this is
00386   // (morally) turned into `var rel -num/den'.
00387   PPL_DIRTY_TEMP0(mpq_class, q);
00388   assign_r(q.get_num(), num, ROUND_NOT_NEEDED);
00389   assign_r(q.get_den(), den, ROUND_NOT_NEEDED);
00390   q.canonicalize();
00391   // Turn `num/den' into `-num/den'.
00392   q = -q;
00393 
00394   I_Result res;
00395   switch (type) {
00396   case Constraint::EQUALITY:
00397     res = itv.add_constraint(i_constraint(EQUAL, q));
00398     break;
00399   case Constraint::NONSTRICT_INEQUALITY:
00400     res = itv.add_constraint(i_constraint(den > 0
00401                                           ? GREATER_OR_EQUAL
00402                                           : LESS_OR_EQUAL, q));
00403     break;
00404   case Constraint::STRICT_INEQUALITY:
00405     res = itv.add_constraint(i_constraint(den > 0
00406                                           ? GREATER_THAN
00407                                           : LESS_THAN, q));
00408     break;
00409   default:
00410     // Silence an annoying GCC warning (should never reach this point).
00411     PPL_ASSERT(false);
00412     res = I_ANY;
00413   }
00414   PPL_ASSERT(itv.OK());
00415   return res;
00416 }

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::refine_no_check ( const Congruence_System cgs  )  [inline, private]

Uses the congruences in cgs to refine *this.

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

Definition at line 2288 of file Box.templates.hh.

References Parma_Polyhedra_Library::Congruence_System::begin(), Parma_Polyhedra_Library::Congruence_System::end(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Congruence_System::space_dimension().

02288                                                       {
02289   PPL_ASSERT(cgs.space_dimension() <= space_dimension());
02290   for (Congruence_System::const_iterator i = cgs.begin(),
02291          cgs_end = cgs.end(); !marked_empty() && i != cgs_end; ++i)
02292     refine_no_check(*i);
02293   PPL_ASSERT(OK());
02294 }

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::refine_no_check ( const Congruence cg  )  [inline, private]

Uses the congruence cg to refine *this.

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

Definition at line 2267 of file Box.templates.hh.

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

02267                                               {
02268   PPL_ASSERT(!marked_empty());
02269 
02270   PPL_ASSERT(cg.space_dimension() <= space_dimension());
02271 
02272   if (cg.is_proper_congruence()) {
02273     // FIXME: also deal with the case of interval with restrictions.
02274     // A proper congruences is also an interval constraint
02275     // if and only if it is trivial.
02276     if (cg.is_inconsistent())
02277       set_empty();
02278     return;
02279   }
02280 
02281   PPL_ASSERT(cg.is_equality());
02282   Constraint c(cg);
02283   refine_no_check(c);
02284 }

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::refine_no_check ( const Constraint_System cs  )  [inline, private]

Uses the constraints in cs to refine *this.

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

Definition at line 2257 of file Box.templates.hh.

References Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Constraint_System::space_dimension().

02257                                                      {
02258   PPL_ASSERT(cs.space_dimension() <= space_dimension());
02259   for (Constraint_System::const_iterator i = cs.begin(),
02260          cs_end = cs.end(); !marked_empty() && i != cs_end; ++i)
02261     refine_no_check(*i);
02262   PPL_ASSERT(OK());
02263 }

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

Uses the constraint c to refine *this.

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

Definition at line 2227 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::add_interval_constraint_no_check(), Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Box< ITV >::extract_interval_constraint(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::propagate_constraint_no_check(), Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), and Parma_Polyhedra_Library::Constraint::type().

Referenced by Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::refine_with_congruence(), Parma_Polyhedra_Library::Box< ITV >::refine_with_congruences(), Parma_Polyhedra_Library::Box< ITV >::refine_with_constraint(), and Parma_Polyhedra_Library::Box< ITV >::refine_with_constraints().

02227                                              {
02228   const dimension_type c_space_dim = c.space_dimension();
02229   PPL_ASSERT(c.space_dimension() <= space_dimension());
02230   PPL_ASSERT(!marked_empty());
02231 
02232   dimension_type c_num_vars = 0;
02233   dimension_type c_only_var = 0;
02234   // Non-interval constraints are approximated.
02235   if (!extract_interval_constraint(c, c_space_dim, c_num_vars, c_only_var)) {
02236     propagate_constraint_no_check(c);
02237     return;
02238   }
02239 
02240   const Coefficient& n = c.inhomogeneous_term();
02241   if (c_num_vars == 0) {
02242     // Dealing with a trivial constraint.
02243     if (n < 0
02244         || (c.is_equality() && n != 0)
02245         || (c.is_strict_inequality() && n == 0))
02246       set_empty();
02247     return;
02248   }
02249 
02250   PPL_ASSERT(c_num_vars == 1);
02251   const Coefficient& d = c.coefficient(Variable(c_only_var));
02252   add_interval_constraint_no_check(c_only_var, c.type(), n, d);
02253 }

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

Use the congruence cg to refine *this.

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

Definition at line 467 of file Box.inlines.hh.

References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Congruence::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

00467                                                      {
00468   const dimension_type cg_space_dim = cg.space_dimension();
00469   // Dimension-compatibility check.
00470   if (cg_space_dim > space_dimension())
00471     throw_dimension_incompatible("refine_with_congruence(cg)", cg);
00472 
00473   // If the box is already empty, there is nothing left to do.
00474   if (marked_empty())
00475     return;
00476 
00477   refine_no_check(cg);
00478 }

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:
cgs The congruences to be used for refinement.
Exceptions:
std::invalid_argument Thrown if *this and cgs are dimension-incompatible.

Definition at line 482 of file Box.inlines.hh.

References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Congruence_System::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

00482                                                               {
00483   // Dimension-compatibility check.
00484   if (cgs.space_dimension() > space_dimension())
00485     throw_dimension_incompatible("refine_with_congruences(cgs)", cgs);
00486 
00487   // If the box is already empty, there is nothing left to do.
00488   if (marked_empty())
00489     return;
00490 
00491   refine_no_check(cgs);
00492 }

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

Use the constraint c to refine *this.

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

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

References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

00438                                                     {
00439   const dimension_type c_space_dim = c.space_dimension();
00440   // Dimension-compatibility check.
00441   if (c_space_dim > space_dimension())
00442     throw_dimension_incompatible("refine_with_constraint(c)", c);
00443 
00444   // If the box is already empty, there is nothing left to do.
00445   if (marked_empty())
00446     return;
00447 
00448   refine_no_check(c);
00449 }

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:
cs The 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_argument Thrown 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 453 of file Box.inlines.hh.

References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

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

00453                                                              {
00454   // Dimension-compatibility check.
00455   if (cs.space_dimension() > space_dimension())
00456     throw_dimension_incompatible("refine_with_constraints(cs)", cs);
00457 
00458   // If the box is already empty, there is nothing left to do.
00459   if (marked_empty())
00460     return;
00461 
00462   refine_no_check(cs);
00463 }

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

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

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

Definition at line 918 of file Box.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Generator::coefficient(), Parma_Polyhedra_Library::Generator::divisor(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Generator::is_line(), Parma_Polyhedra_Library::Generator::is_line_or_ray(), Parma_Polyhedra_Library::Generator::is_point(), Parma_Polyhedra_Library::Generator::is_ray(), Parma_Polyhedra_Library::Poly_Gen_Relation::nothing(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Generator::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Poly_Gen_Relation::subsumes(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

00918                                                 {
00919   const dimension_type space_dim = space_dimension();
00920   const dimension_type g_space_dim = g.space_dimension();
00921 
00922   // Dimension-compatibility check.
00923   if (space_dim < g_space_dim)
00924     throw_dimension_incompatible("relation_with(g)", g);
00925 
00926   // The empty box cannot subsume a generator.
00927   if (is_empty())
00928     return Poly_Gen_Relation::nothing();
00929 
00930   // A universe box in a zero-dimensional space subsumes
00931   // all the generators of a zero-dimensional space.
00932   if (space_dim == 0)
00933     return Poly_Gen_Relation::subsumes();
00934 
00935   if (g.is_line_or_ray()) {
00936     if (g.is_line()) {
00937       for (dimension_type i = g_space_dim; i-- > 0; )
00938         if (g.coefficient(Variable(i)) != 0 && !seq[i].is_universe())
00939           return Poly_Gen_Relation::nothing();
00940       return Poly_Gen_Relation::subsumes();
00941     }
00942     else {
00943       PPL_ASSERT(g.is_ray());
00944       for (dimension_type i = g_space_dim; i-- > 0; )
00945         switch (sgn(g.coefficient(Variable(i)))) {
00946         case 1:
00947           if (!seq[i].upper_is_boundary_infinity())
00948             return Poly_Gen_Relation::nothing();
00949           break;
00950         case 0:
00951           break;
00952         case -1:
00953           if (!seq[i].lower_is_boundary_infinity())
00954             return Poly_Gen_Relation::nothing();
00955           break;
00956         }
00957       return Poly_Gen_Relation::subsumes();
00958     }
00959   }
00960 
00961   // Here `g' is a point or closure point.
00962   const Coefficient& g_divisor = g.divisor();
00963   PPL_DIRTY_TEMP0(mpq_class, g_coord);
00964   PPL_DIRTY_TEMP0(mpq_class, bound);
00965   for (dimension_type i = g_space_dim; i-- > 0; ) {
00966     const ITV& seq_i = seq[i];
00967     if (seq_i.is_universe())
00968       continue;
00969     assign_r(g_coord.get_num(), g.coefficient(Variable(i)), ROUND_NOT_NEEDED);
00970     assign_r(g_coord.get_den(), g_divisor, ROUND_NOT_NEEDED);
00971     g_coord.canonicalize();
00972     // Check lower bound.
00973     if (!seq_i.lower_is_boundary_infinity()) {
00974       assign_r(bound, seq_i.lower(), ROUND_NOT_NEEDED);
00975       if (g_coord <= bound) {
00976         if (seq_i.lower_is_open()) {
00977           if (g.is_point() || g_coord != bound)
00978             return Poly_Gen_Relation::nothing();
00979         }
00980         else if (g_coord != bound)
00981           return Poly_Gen_Relation::nothing();
00982       }
00983     }
00984     // Check upper bound.
00985     if (!seq_i.upper_is_boundary_infinity()) {
00986       assign_r(bound, seq_i.upper(), ROUND_NOT_NEEDED);
00987       if (g_coord >= bound) {
00988         if (seq_i.upper_is_open()) {
00989           if (g.is_point() || g_coord != bound)
00990             return Poly_Gen_Relation::nothing();
00991         }
00992         else if (g_coord != bound)
00993           return Poly_Gen_Relation::nothing();
00994       }
00995     }
00996   }
00997   return Poly_Gen_Relation::subsumes();
00998 }

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

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

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

Definition at line 771 of file Box.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Congruence::coefficient(), Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::Congruence::inhomogeneous_term(), Parma_Polyhedra_Library::interval_relation(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Congruence::modulus(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Box< ITV >::relation_with(), Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Congruence::space_dimension(), Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

00771                                                   {
00772   const dimension_type cg_space_dim = cg.space_dimension();
00773   const dimension_type space_dim = space_dimension();
00774 
00775   // Dimension-compatibility check.
00776   if (cg_space_dim > space_dim)
00777     throw_dimension_incompatible("relation_with(cg)", cg);
00778 
00779   if (is_empty())
00780     return Poly_Con_Relation::saturates()
00781       && Poly_Con_Relation::is_included()
00782       && Poly_Con_Relation::is_disjoint();
00783 
00784    if (space_dim == 0) {
00785     if (cg.is_inconsistent())
00786       return Poly_Con_Relation::is_disjoint();
00787     else
00788       return Poly_Con_Relation::saturates()
00789         && Poly_Con_Relation::is_included();
00790   }
00791 
00792   if (cg.is_equality()) {
00793     const Constraint c(cg);
00794     return relation_with(c);
00795   }
00796 
00797   PPL_DIRTY_TEMP0(Rational_Interval, r);
00798   PPL_DIRTY_TEMP0(Rational_Interval, t);
00799   PPL_DIRTY_TEMP0(mpq_class, m);
00800   r = 0;
00801   for (dimension_type i = cg.space_dimension(); i-- > 0; ) {
00802     const Coefficient& cg_i = cg.coefficient(Variable(i));
00803     if (sgn(cg_i) != 0) {
00804       assign_r(m, cg_i, ROUND_NOT_NEEDED);
00805       // FIXME: an add_mul_assign() method would come handy here.
00806       t.build(seq[i].lower_constraint(), seq[i].upper_constraint());
00807       t *= m;
00808       r += t;
00809     }
00810   }
00811 
00812   if (r.lower_is_boundary_infinity() || r.upper_is_boundary_infinity())
00813     return Poly_Con_Relation::strictly_intersects();
00814 
00815 
00816   // Find the value that satisfies the congruence and is
00817   // nearest to the lower bound such that the point lies on or above it.
00818 
00819   PPL_DIRTY_TEMP_COEFFICIENT(lower);
00820   PPL_DIRTY_TEMP_COEFFICIENT(mod);
00821   PPL_DIRTY_TEMP_COEFFICIENT(v);
00822   mod = cg.modulus();
00823   v = cg.inhomogeneous_term() % mod;
00824   assign_r(lower, r.lower(), ROUND_DOWN);
00825   v -= ((lower / mod) * mod);
00826   if (v + lower > 0)
00827     v -= mod;
00828   return interval_relation(r, Constraint::EQUALITY, v);
00829 }

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

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

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

Definition at line 833 of file Box.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Box< ITV >::extract_interval_constraint(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::interval_relation(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Constraint::is_inequality(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Constraint::type().

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

00833                                                  {
00834   const dimension_type c_space_dim = c.space_dimension();
00835   const dimension_type space_dim = space_dimension();
00836 
00837   // Dimension-compatibility check.
00838   if (c_space_dim > space_dim)
00839     throw_dimension_incompatible("relation_with(c)", c);
00840 
00841   if (is_empty())
00842     return Poly_Con_Relation::saturates()
00843       && Poly_Con_Relation::is_included()
00844       && Poly_Con_Relation::is_disjoint();
00845 
00846   if (space_dim == 0) {
00847     if ((c.is_equality() && c.inhomogeneous_term() != 0)
00848         || (c.is_inequality() && c.inhomogeneous_term() < 0))
00849       return Poly_Con_Relation::is_disjoint();
00850     else if (c.is_strict_inequality() && c.inhomogeneous_term() == 0)
00851       // The constraint 0 > 0 implicitly defines the hyperplane 0 = 0;
00852       // thus, the zero-dimensional point also saturates it.
00853       return Poly_Con_Relation::saturates()
00854         && Poly_Con_Relation::is_disjoint();
00855     else if (c.is_equality() || c.inhomogeneous_term() == 0)
00856       return Poly_Con_Relation::saturates()
00857         && Poly_Con_Relation::is_included();
00858     else
00859       // The zero-dimensional point saturates
00860       // neither the positivity constraint 1 >= 0,
00861       // nor the strict positivity constraint 1 > 0.
00862       return Poly_Con_Relation::is_included();
00863   }
00864 
00865   dimension_type c_num_vars = 0;
00866   dimension_type c_only_var = 0;
00867 
00868   if (extract_interval_constraint(c, c_space_dim, c_num_vars, c_only_var))
00869     if (c_num_vars == 0)
00870       // c is a trivial constraint.
00871       switch (sgn(c.inhomogeneous_term())) {
00872       case -1:
00873         return Poly_Con_Relation::is_disjoint();
00874       case 0:
00875         if (c.is_strict_inequality())
00876           return Poly_Con_Relation::saturates()
00877             && Poly_Con_Relation::is_disjoint();
00878         else
00879           return Poly_Con_Relation::saturates()
00880             && Poly_Con_Relation::is_included();
00881       case 1:
00882         return Poly_Con_Relation::is_included();
00883       }
00884     else {
00885       // c is an interval constraint.
00886       return interval_relation(seq[c_only_var],
00887                                c.type(),
00888                                c.inhomogeneous_term(),
00889                                c.coefficient(Variable(c_only_var)));
00890     }
00891   else {
00892     // Deal with a non-trivial and non-interval constraint.
00893     PPL_DIRTY_TEMP0(Rational_Interval, r);
00894     PPL_DIRTY_TEMP0(Rational_Interval, t);
00895     PPL_DIRTY_TEMP0(mpq_class, m);
00896     r = 0;
00897     for (dimension_type i = c.space_dimension(); i-- > 0; ) {
00898       const Coefficient& c_i = c.coefficient(Variable(i));
00899       if (sgn(c_i) != 0) {
00900         assign_r(m, c_i, ROUND_NOT_NEEDED);
00901         // FIXME: an add_mul_assign() method would come handy here.
00902         t.build(seq[i].lower_constraint(), seq[i].upper_constraint());
00903         t *= m;
00904         r += t;
00905       }
00906     }
00907     return interval_relation(r,
00908                              c.type(),
00909                              c.inhomogeneous_term());
00910   }
00911 
00912   // Quiet a compiler warning: this program point is unreachable.
00913   throw std::runtime_error("PPL internal error");
00914 }

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::remove_higher_space_dimensions ( dimension_type  new_dimension  )  [inline]

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

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

Definition at line 2030 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

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

02030                                                                      {
02031   // Dimension-compatibility check: the variable having
02032   // maximum index is the one occurring last in the set.
02033   const dimension_type old_dim = space_dimension();
02034   if (new_dim > old_dim)
02035     throw_dimension_incompatible("remove_higher_space_dimensions(nd)",
02036                                  new_dim);
02037 
02038   // The removal of no dimensions from any box is a no-op.
02039   // Note that this case also captures the only legal removal of
02040   // dimensions from a zero-dim space box.
02041   if (new_dim == old_dim) {
02042     PPL_ASSERT(OK());
02043     return;
02044   }
02045 
02046   seq.erase(seq.begin() + new_dim, seq.end());
02047   PPL_ASSERT(OK());
02048 }

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

Removes all the specified dimensions.

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

Definition at line 1977 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

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

01977                                                            {
01978   // The removal of no dimensions from any box is a no-op.
01979   // Note that this case also captures the only legal removal of
01980   // space dimensions from a box in a zero-dimensional space.
01981   if (vars.empty()) {
01982     PPL_ASSERT(OK());
01983     return;
01984   }
01985 
01986   const dimension_type old_space_dim = space_dimension();
01987 
01988   // Dimension-compatibility check.
01989   const dimension_type vsi_space_dim = vars.space_dimension();
01990   if (old_space_dim < vsi_space_dim)
01991     throw_dimension_incompatible("remove_space_dimensions(vs)",
01992                                  vsi_space_dim);
01993 
01994   const dimension_type new_space_dim = old_space_dim - vars.size();
01995 
01996   // If the box is empty (this must be detected), then resizing is all
01997   // what is needed.  If it is not empty and we are removing _all_ the
01998   // dimensions then, again, resizing suffices.
01999   if (is_empty() || new_space_dim == 0) {
02000     seq.resize(new_space_dim);
02001     PPL_ASSERT(OK());
02002     return;
02003   }
02004 
02005   // For each variable to be removed, we fill the corresponding interval
02006   // by shifting left those intervals that will not be removed.
02007   Variables_Set::const_iterator vsi = vars.begin();
02008   Variables_Set::const_iterator vsi_end = vars.end();
02009   dimension_type dst = *vsi;
02010   dimension_type src = dst + 1;
02011   for (++vsi; vsi != vsi_end; ++vsi) {
02012     const dimension_type vsi_next = *vsi;
02013     // All intervals in between are moved to the left.
02014     while (src < vsi_next)
02015       seq[dst++].swap(seq[src++]);
02016     ++src;
02017   }
02018   // Moving the remaining intervals.
02019   while (src < old_space_dim)
02020     seq[dst++].swap(seq[src++]);
02021 
02022   PPL_ASSERT(dst == new_space_dim);
02023   seq.resize(new_space_dim);
02024 
02025   PPL_ASSERT(OK());
02026 }

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::reset_empty_up_to_date (  )  [inline, private]
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::set_empty (  )  [inline]
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::set_empty_up_to_date (  )  [inline, private]

Asserts the validity of the empty flag of *this.

Definition at line 58 of file Box.inlines.hh.

References Parma_Polyhedra_Library::Box< ITV >::Status::set_empty_up_to_date(), and Parma_Polyhedra_Library::Box< ITV >::status.

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

00058                                {
00059   status.set_empty_up_to_date();
00060 }

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_argument Thrown if var is not a space dimension of *this.

Definition at line 157 of file Box.inlines.hh.

References Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::reset_empty_up_to_date(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

00157                                                        {
00158   const dimension_type space_dim = space_dimension();
00159   if (space_dim < var.space_dimension())
00160     throw_dimension_incompatible("set_interval(v, i)", "v", var);
00161 
00162   if (is_empty() && space_dim >= 2)
00163     // If the box is empty, and has dimension >= 2, setting only one
00164     // interval will not make it non-empty.
00165     return;
00166 
00167   seq[var.id()] = i;
00168   reset_empty_up_to_date();
00169 
00170   PPL_ASSERT(OK());
00171 }

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::set_nonempty (  )  [inline, private]
template<typename ITV >
bool Parma_Polyhedra_Library::Box< ITV >::simplify_using_context_assign ( const Box< ITV > &  y  )  [inline]

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

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

Definition at line 1863 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_nonempty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::UNIVERSE.

01863                                                     {
01864   Box& x = *this;
01865   const dimension_type num_dims = x.space_dimension();
01866   // Dimension-compatibility check.
01867   if (num_dims != y.space_dimension())
01868     x.throw_dimension_incompatible("simplify_using_context_assign(y)", y);
01869 
01870   // Filter away the zero-dimensional case.
01871   if (num_dims == 0) {
01872     if (y.marked_empty()) {
01873       x.set_nonempty();
01874       return false;
01875     }
01876     else
01877       return !x.marked_empty();
01878   }
01879 
01880   // Filter away the case when `y' is empty.
01881   if (y.is_empty()) {
01882     for (dimension_type i = num_dims; i-- > 0; )
01883       x.seq[i].assign(UNIVERSE);
01884     x.set_nonempty();
01885     return false;
01886   }
01887 
01888   if (x.is_empty()) {
01889     // Find in `y' a non-universe interval, if any.
01890     for (dimension_type i = 0; i < num_dims; ++i) {
01891       if (y.seq[i].is_universe())
01892         x.seq[i].assign(UNIVERSE);
01893       else {
01894         // Set x.seq[i] so as to contradict y.seq[i], if possible.
01895         ITV& seq_i = x.seq[i];
01896         seq_i.empty_intersection_assign(y.seq[i]);
01897         if (seq_i.is_empty()) {
01898           // We were not able to assign to `seq_i' a non-empty interval:
01899           // reset `seq_i' to the universe interval and keep searching.
01900           seq_i.assign(UNIVERSE);
01901           continue;
01902         }
01903         // We assigned to `seq_i' a non-empty interval:
01904         // set the other intervals to universe and return.
01905         for (++i; i < num_dims; ++i)
01906           x.seq[i].assign(UNIVERSE);
01907         x.set_nonempty();
01908         PPL_ASSERT(x.OK());
01909         return false;
01910       }
01911     }
01912     // All intervals in `y' are universe or could not be contradicted:
01913     // simplification can leave the empty box `x' as is.
01914     PPL_ASSERT(x.OK() && x.is_empty());
01915     return false;
01916   }
01917 
01918   // Loop index `i' is intentionally going upwards.
01919   dimension_type i = 0;
01920   for ( ; i < num_dims; ++i) {
01921     if (!x.seq[i].simplify_using_context_assign(y.seq[i])) {
01922       PPL_ASSERT(!x.seq[i].is_empty());
01923       // The intersection of `x' and `y' is empty due to the i-th interval:
01924       // reset other intervals to UNIVERSE.
01925       for (dimension_type j = num_dims; j-- > i; )
01926         x.seq[j].assign(UNIVERSE);
01927       for (dimension_type j = i; j-- > 0; )
01928         x.seq[j].assign(UNIVERSE);
01929       PPL_ASSERT(x.OK());
01930       return false;
01931     }
01932   }
01933   PPL_ASSERT(x.OK());
01934   return true;
01935 }

template<typename ITV >
dimension_type Parma_Polyhedra_Library::Box< ITV >::space_dimension (  )  const [inline]

Returns the dimension of the vector space enclosing *this.

Definition at line 122 of file Box.inlines.hh.

References Parma_Polyhedra_Library::Box< ITV >::seq.

Referenced by Parma_Polyhedra_Library::Box< ITV >::add_congruence(), Parma_Polyhedra_Library::Box< ITV >::add_congruence_no_check(), Parma_Polyhedra_Library::Box< ITV >::add_congruences(), Parma_Polyhedra_Library::Box< ITV >::add_congruences_no_check(), Parma_Polyhedra_Library::Box< ITV >::add_constraint(), Parma_Polyhedra_Library::Box< ITV >::add_constraint_no_check(), Parma_Polyhedra_Library::Box< ITV >::add_constraints(), Parma_Polyhedra_Library::Box< ITV >::add_constraints_no_check(), Parma_Polyhedra_Library::Box< ITV >::affine_dimension(), Parma_Polyhedra_Library::Box< ITV >::affine_image(), Parma_Polyhedra_Library::Box< ITV >::affine_preimage(), Parma_Polyhedra_Library::Box< ITV >::ascii_dump(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::Box< ITV >::bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Box< ITV >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Box< ITV >::concatenate_assign(), Parma_Polyhedra_Library::Box< ITV >::congruences(), Parma_Polyhedra_Library::Box< ITV >::constrains(), Parma_Polyhedra_Library::Box< ITV >::constraints(), Parma_Polyhedra_Library::Box< ITV >::contains(), Parma_Polyhedra_Library::Box< ITV >::difference_assign(), Parma_Polyhedra_Library::Box< ITV >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Box< ITV >::expand_space_dimension(), Parma_Polyhedra_Library::Box< ITV >::fold_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::frequency(), Parma_Polyhedra_Library::Box< ITV >::generalized_affine_preimage(), Parma_Polyhedra_Library::Box< ITV >::get_interval(), Parma_Polyhedra_Library::Box< ITV >::get_limiting_box(), Parma_Polyhedra_Library::Grid::Grid(), Parma_Polyhedra_Library::Box< ITV >::intersection_assign(), Parma_Polyhedra_Library::Box< ITV >::is_disjoint_from(), Parma_Polyhedra_Library::Box< ITV >::l_m_distance_assign(), Parma_Polyhedra_Library::Box< ITV >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::Box< ITV >::map_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::max_min(), Parma_Polyhedra_Library::Box< ITV >::minimized_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::operator==(), Parma_Polyhedra_Library::Polyhedron::Polyhedron(), Parma_Polyhedra_Library::Box< ITV >::propagate_constraint(), Parma_Polyhedra_Library::Box< ITV >::propagate_constraint_no_check(), Parma_Polyhedra_Library::Box< ITV >::propagate_constraints(), Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::refine_with_congruence(), Parma_Polyhedra_Library::Box< ITV >::refine_with_congruences(), Parma_Polyhedra_Library::Box< ITV >::refine_with_constraint(), Parma_Polyhedra_Library::Box< ITV >::refine_with_constraints(), Parma_Polyhedra_Library::Box< ITV >::relation_with(), Parma_Polyhedra_Library::Box< ITV >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::remove_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::set_interval(), Parma_Polyhedra_Library::Box< ITV >::simplify_using_context_assign(), Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible(), Parma_Polyhedra_Library::Box< ITV >::time_elapse_assign(), Parma_Polyhedra_Library::Box< ITV >::unconstrain(), Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign(), Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign_if_exact(), and Parma_Polyhedra_Library::Box< ITV >::wrap_assign().

00122                                 {
00123   return seq.size();
00124 }

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_argument Thrown if x and y are dimension-incompatible.

Definition at line 225 of file Box.inlines.hh.

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

00225                                               {
00226   const Box& x = *this;
00227   return x.contains(y) && !y.contains(x);
00228 }

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::swap ( Box< ITV > &  y  )  [inline]

Swaps *this with y (*this and y can be dimension-incompatible).

Definition at line 84 of file Box.inlines.hh.

References Parma_Polyhedra_Library::Box< ITV >::seq, and Parma_Polyhedra_Library::Box< ITV >::status.

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

00084                      {
00085   Box& x = *this;
00086   std::swap(x.seq, y.seq);
00087   std::swap(x.status, y.status);
00088 }

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::throw_constraint_incompatible ( const char *  method  )  [inline, static, private]

Definition at line 4027 of file Box.templates.hh.

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

04027                                                           {
04028   std::ostringstream s;
04029   s << "PPL::Box::" << method << ":" << std::endl
04030     << "the constraint is incompatible.";
04031   throw std::invalid_argument(s.str());
04032 }

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

Definition at line 4047 of file Box.templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::space_dimension().

04049                                                                          {
04050   std::ostringstream s;
04051   s << "PPL::Box::" << method << ":" << std::endl
04052     << "this->space_dimension() == " << space_dimension()
04053     << ", " << name_row << "->space_dimension() == "
04054     << e.space_dimension() << ".";
04055   throw std::invalid_argument(s.str());
04056 }

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

Definition at line 4016 of file Box.templates.hh.

References Parma_Polyhedra_Library::Generator::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::space_dimension().

04017                                                                  {
04018   std::ostringstream s;
04019   s << "PPL::Box::" << method << ":" << std::endl
04020     << "this->space_dimension() == " << space_dimension()
04021     << ", g->space_dimension == " << g.space_dimension() << ".";
04022   throw std::invalid_argument(s.str());
04023 }

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible ( const char *  method,
const Congruence_System cgs 
) const [inline, private]

Definition at line 4005 of file Box.templates.hh.

References Parma_Polyhedra_Library::Congruence_System::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::space_dimension().

04006                                                                            {
04007   std::ostringstream s;
04008   s << "PPL::Box::" << method << ":" << std::endl
04009     << "this->space_dimension() == " << space_dimension()
04010     << ", cgs->space_dimension == " << cgs.space_dimension() << ".";
04011   throw std::invalid_argument(s.str());
04012 }

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible ( const char *  method,
const Constraint_System cs 
) const [inline, private]

Definition at line 3994 of file Box.templates.hh.

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

03995                                                                           {
03996   std::ostringstream s;
03997   s << "PPL::Box::" << method << ":" << std::endl
03998     << "this->space_dimension() == " << space_dimension()
03999     << ", cs->space_dimension == " << cs.space_dimension() << ".";
04000   throw std::invalid_argument(s.str());
04001 }

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

Definition at line 3983 of file Box.templates.hh.

References Parma_Polyhedra_Library::Congruence::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::space_dimension().

03984                                                                    {
03985   std::ostringstream s;
03986   s << "PPL::Box::" << method << ":" << std::endl
03987     << "this->space_dimension() == " << space_dimension()
03988     << ", cg->space_dimension == " << cg.space_dimension() << ".";
03989   throw std::invalid_argument(s.str());
03990 }

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

Definition at line 3972 of file Box.templates.hh.

References Parma_Polyhedra_Library::Constraint::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::space_dimension().

03973                                                                   {
03974   std::ostringstream s;
03975   s << "PPL::Box::" << method << ":" << std::endl
03976     << "this->space_dimension() == " << space_dimension()
03977     << ", c->space_dimension == " << c.space_dimension() << ".";
03978   throw std::invalid_argument(s.str());
03979 }

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

Definition at line 3961 of file Box.templates.hh.

03962                                                                   {
03963   std::ostringstream s;
03964   s << "PPL::Box::" << method << ":" << std::endl
03965     << "this->space_dimension() == " << space_dimension()
03966     << ", required dimension == " << required_dim << ".";
03967   throw std::invalid_argument(s.str());
03968 }

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

Definition at line 3949 of file Box.templates.hh.

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

Referenced by Parma_Polyhedra_Library::Box< ITV >::add_congruence(), Parma_Polyhedra_Library::Box< ITV >::add_congruences(), Parma_Polyhedra_Library::Box< ITV >::add_constraint(), Parma_Polyhedra_Library::Box< ITV >::add_constraints(), Parma_Polyhedra_Library::Box< ITV >::affine_image(), Parma_Polyhedra_Library::Box< ITV >::affine_preimage(), Parma_Polyhedra_Library::Box< ITV >::bounds(), Parma_Polyhedra_Library::Box< ITV >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Box< ITV >::constrains(), Parma_Polyhedra_Library::Box< ITV >::contains(), Parma_Polyhedra_Library::Box< ITV >::difference_assign(), Parma_Polyhedra_Library::Box< ITV >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Box< ITV >::expand_space_dimension(), Parma_Polyhedra_Library::Box< ITV >::fold_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::frequency(), Parma_Polyhedra_Library::Box< ITV >::generalized_affine_preimage(), Parma_Polyhedra_Library::Box< ITV >::get_interval(), Parma_Polyhedra_Library::Box< ITV >::intersection_assign(), Parma_Polyhedra_Library::Box< ITV >::is_disjoint_from(), Parma_Polyhedra_Library::Box< ITV >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::Box< ITV >::max_min(), Parma_Polyhedra_Library::Box< ITV >::propagate_constraint(), Parma_Polyhedra_Library::Box< ITV >::propagate_constraints(), Parma_Polyhedra_Library::Box< ITV >::refine_with_congruence(), Parma_Polyhedra_Library::Box< ITV >::refine_with_congruences(), Parma_Polyhedra_Library::Box< ITV >::refine_with_constraint(), Parma_Polyhedra_Library::Box< ITV >::refine_with_constraints(), Parma_Polyhedra_Library::Box< ITV >::relation_with(), Parma_Polyhedra_Library::Box< ITV >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::remove_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::set_interval(), Parma_Polyhedra_Library::Box< ITV >::simplify_using_context_assign(), Parma_Polyhedra_Library::Box< ITV >::time_elapse_assign(), Parma_Polyhedra_Library::Box< ITV >::unconstrain(), Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign(), and Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign_if_exact().

03950                                                            {
03951   std::ostringstream s;
03952   s << "PPL::Box::" << method << ":" << std::endl
03953     << "this->space_dimension() == " << this->space_dimension()
03954     << ", y->space_dimension() == " << y.space_dimension() << ".";
03955   throw std::invalid_argument(s.str());
03956 }

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

Definition at line 4036 of file Box.templates.hh.

04037                                                                    {
04038   using namespace IO_Operators;
04039   std::ostringstream s;
04040   s << "PPL::Box::" << method << ":" << std::endl
04041     << e << " is too complex.";
04042   throw std::invalid_argument(s.str());
04043 }

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::throw_generic ( const char *  method,
const char *  reason 
) [inline, static, private]
template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::throw_space_dimension_overflow ( const char *  method,
const char *  reason 
) [inline, static, private]

Definition at line 4069 of file Box.templates.hh.

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

04070                                                              {
04071   std::ostringstream s;
04072   s << "PPL::Box::" << method << ":" << std::endl
04073     << reason;
04074   throw std::length_error(s.str());
04075 }

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::time_elapse_assign ( const Box< ITV > &  y  )  [inline]

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

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

Definition at line 1939 of file Box.templates.hh.

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

01939                                          {
01940   Box& x = *this;
01941   const dimension_type x_space_dim = x.space_dimension();
01942 
01943   // Dimension-compatibility check.
01944   if (x_space_dim != y.space_dimension())
01945     x.throw_dimension_incompatible("time_elapse_assign(y)", y);
01946 
01947   // Dealing with the zero-dimensional case.
01948   if (x_space_dim == 0) {
01949     if (y.marked_empty())
01950       x.set_empty();
01951     return;
01952   }
01953 
01954   // If either one of `x' or `y' is empty, the result is empty too.
01955   // Note: if possible, avoid cost of checking for emptiness.
01956   if (x.marked_empty() || y.marked_empty()
01957       || x.is_empty() || y.is_empty()) {
01958     x.set_empty();
01959     return;
01960   }
01961 
01962   for (dimension_type i = x_space_dim; i-- > 0; ) {
01963     ITV& x_seq_i = x.seq[i];
01964     const ITV& y_seq_i = y.seq[i];
01965     if (!x_seq_i.lower_is_boundary_infinity())
01966       if (y_seq_i.lower_is_boundary_infinity() || y_seq_i.lower() < 0)
01967         x_seq_i.lower_extend();
01968     if (!x_seq_i.upper_is_boundary_infinity())
01969       if (y_seq_i.upper_is_boundary_infinity() || y_seq_i.upper() > 0)
01970         x_seq_i.upper_extend();
01971   }
01972   PPL_ASSERT(x.OK());
01973 }

template<typename ITV >
void Parma_Polyhedra_Library::Box< ITV >::topological_closure_assign (  )  [inline]

Assigns to *this its topological closure.

Definition at line 1481 of file Box.templates.hh.

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

01481                                      {
01482   if (ITV::is_always_topologically_closed() || is_empty())
01483     return;
01484 
01485   for (dimension_type k = seq.size(); k-- > 0; )
01486     seq[k].topological_closure_assign();
01487 }

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 116 of file Box.inlines.hh.

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

00116                                       {
00117   return sizeof(*this) + external_memory_in_bytes();
00118 }

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

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

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

Definition at line 1447 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::UNIVERSE.

01447                                                {
01448   // The cylindrification wrt no dimensions is a no-op.
01449   // This case also captures the only legal cylindrification
01450   // of a box in a 0-dim space.
01451   if (vars.empty())
01452     return;
01453 
01454   // Dimension-compatibility check.
01455   const dimension_type min_space_dim = vars.space_dimension();
01456   if (space_dimension() < min_space_dim)
01457     throw_dimension_incompatible("unconstrain(vs)", min_space_dim);
01458 
01459   // If the box is already empty, there is nothing left to do.
01460   if (marked_empty())
01461     return;
01462 
01463   // Here the box might still be empty (but we haven't detected it yet):
01464   // check emptiness of the interval for each of the variables in
01465   // `vars' before cylindrification.
01466   for (Variables_Set::const_iterator vsi = vars.begin(),
01467          vsi_end = vars.end(); vsi != vsi_end; ++vsi) {
01468     ITV& seq_vsi = seq[*vsi];
01469     if (!seq_vsi.is_empty())
01470       seq_vsi.assign(UNIVERSE);
01471     else {
01472       set_empty();
01473       break;
01474     }
01475   }
01476   PPL_ASSERT(OK());
01477 }

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:
var The space dimension that will be unconstrained.
Exceptions:
std::invalid_argument Thrown if var is not a space dimension of *this.

Definition at line 526 of file Box.inlines.hh.

References Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::UNIVERSE.

00526                                         {
00527   const dimension_type var_id = var.id();
00528   // Dimension-compatibility check.
00529   if (space_dimension() < var_id + 1)
00530     throw_dimension_incompatible("unconstrain(var)", var_id + 1);
00531 
00532   // If the box is already empty, there is nothing left to do.
00533   if (marked_empty())
00534     return;
00535 
00536   // Here the box might still be empty (but we haven't detected it yet):
00537   // check emptiness of the interval for `var' before cylindrification.
00538   ITV& seq_var = seq[var_id];
00539   if (seq_var.is_empty())
00540     set_empty();
00541   else
00542     seq_var.assign(UNIVERSE);
00543 
00544   PPL_ASSERT(OK());
00545 }

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

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

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

Definition at line 1744 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

01744                                          {
01745   Box& x = *this;
01746 
01747   // Dimension-compatibility check.
01748   if (x.space_dimension() != y.space_dimension())
01749     x.throw_dimension_incompatible("upper_bound_assign(y)", y);
01750 
01751   // The lub of a box with an empty box is equal to the first box.
01752   if (y.marked_empty())
01753     return;
01754   if (x.marked_empty()) {
01755     x = y;
01756     return;
01757   }
01758 
01759   for (dimension_type k = x.seq.size(); k-- > 0; )
01760     x.seq[k].join_assign(y.seq[k]);
01761 
01762   PPL_ASSERT(x.OK());
01763 }

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_argument Thrown if *this and y are dimension-incompatible.

Definition at line 1196 of file Box.templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), and Parma_Polyhedra_Library::Box< ITV >::throw_dimension_incompatible().

01196                                                   {
01197   Box& x = *this;
01198 
01199   // Dimension-compatibility check.
01200   if (x.space_dimension() != y.space_dimension())
01201     x.throw_dimension_incompatible("upper_bound_assign_if_exact(y)", y);
01202 
01203   // The lub of a box with an empty box is equal to the first box.
01204   if (y.marked_empty())
01205     return true;
01206   if (x.marked_empty()) {
01207     x = y;
01208     return true;
01209   }
01210 
01211   bool x_j_does_not_contain_y_j = false;
01212   bool y_j_does_not_contain_x_j = false;
01213 
01214   for (dimension_type i = x.seq.size(); i-- > 0; ) {
01215     const ITV& x_seq_i = x.seq[i];
01216     const ITV& y_seq_i = y.seq[i];
01217 
01218     if (!x_seq_i.can_be_exactly_joined_to(y_seq_i))
01219       return false;
01220 
01221     // Note: the use of `y_i_does_not_contain_x_i' is needed
01222     // because we want to temporarily preserve the old value
01223     // of `y_j_does_not_contain_x_j'.
01224     bool y_i_does_not_contain_x_i = !y_seq_i.contains(x_seq_i);
01225     if (y_i_does_not_contain_x_i && x_j_does_not_contain_y_j)
01226       return false;
01227     if (!x_seq_i.contains(y_seq_i)) {
01228       if (y_j_does_not_contain_x_j)
01229         return false;
01230       else
01231         x_j_does_not_contain_y_j = true;
01232     }
01233     if (y_i_does_not_contain_x_i)
01234       y_j_does_not_contain_x_j = true;
01235   }
01236 
01237   // The upper bound is exact: compute it into *this.
01238   for (dimension_type k = x.seq.size(); k-- > 0; )
01239     x.seq[k].join_assign(y.seq[k]);
01240   return true;
01241 }

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 364 of file Box.inlines.hh.

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

00364                                                   {
00365   CC76_widening_assign(y, tp);
00366 }

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 pcs = 0,
unsigned  complexity_threshold = 16,
bool  wrap_individually = true 
) [inline]

Wraps the specified dimensions of the vector space.

Parameters:
vars The set of Variable objects corresponding to the space dimensions to be wrapped.
w The width of the bounded integer type corresponding to all the dimensions to be wrapped.
r The representation of the bounded integer type corresponding to all the dimensions to be wrapped.
o The overflow behavior of the bounded integer type corresponding to all the dimensions to be wrapped.
pcs Possibly null pointer to a constraint system. When non-null, the pointed-to constraint system is assumed to represent the conditional or looping construct guard with respect to which wrapping is performed. Since wrapping requires the computation of upper bounds and due to non-distributivity of constraint refinement over upper bounds, passing a constraint system in this way can be more precise than refining the result of the wrapping operation with the constraints in *pcs.
complexity_threshold A precision parameter which is ignored for the Box domain.
wrap_individually A precision parameter which is ignored for the Box domain.
Exceptions:
std::invalid_argument Thrown if *this is dimension-incompatible with one of the Variable objects contained in vars or with *pcs.

Definition at line 1491 of file Box.templates.hh.

References Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Coefficient_one(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Box< ITV >::extract_interval_constraint(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Constraint::is_inconsistent(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::mul_2exp_assign(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::OVERFLOW_IMPOSSIBLE, Parma_Polyhedra_Library::OVERFLOW_UNDEFINED, Parma_Polyhedra_Library::OVERFLOW_WRAPS, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Box< ITV >::refine_interval_no_check(), Parma_Polyhedra_Library::Box< ITV >::refine_with_constraints(), Parma_Polyhedra_Library::Box< ITV >::reset_empty_up_to_date(), Parma_Polyhedra_Library::Box< ITV >::seq, Parma_Polyhedra_Library::Box< ITV >::set_empty(), Parma_Polyhedra_Library::SIGNED_2_COMPLEMENT, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::Constraint::type(), Parma_Polyhedra_Library::UNIVERSE, and Parma_Polyhedra_Library::UNSIGNED.

01497                                               {
01498 #if 0 // Generic implementation commented out.
01499   Implementation::wrap_assign(*this,
01500                               vars, w, r, o, pcs,
01501                               complexity_threshold, wrap_individually,
01502                               "Box");
01503 #else // Specialized implementation.
01504   used(wrap_individually);
01505   used(complexity_threshold);
01506   Box& x = *this;
01507 
01508   // Dimension-compatibility check for `*pcs', if any.
01509   const dimension_type vars_space_dim = vars.space_dimension();
01510   if (pcs != 0 && pcs->space_dimension() > vars_space_dim) {
01511     std::ostringstream s;
01512     s << "PPL::Box<ITV>::wrap_assign(vars, w, r, o, pcs, ...):"
01513       << std::endl
01514       << "vars.space_dimension() == " << vars_space_dim
01515       << ", pcs->space_dimension() == " << pcs->space_dimension() << ".";
01516     throw std::invalid_argument(s.str());
01517   }
01518 
01519   // Wrapping no variable only requires refining with *pcs, if any.
01520   if (vars.empty()) {
01521     if (pcs != 0)
01522       refine_with_constraints(*pcs);
01523     return;
01524   }
01525 
01526   // Dimension-compatibility check for `vars'.
01527   const dimension_type space_dim = x.space_dimension();
01528   if (space_dim < vars_space_dim) {
01529     std::ostringstream s;
01530     s << "PPL::Box<ITV>::wrap_assign(vars, ...):"
01531       << std::endl
01532       << "this->space_dimension() == " << space_dim
01533       << ", required space dimension == " << vars_space_dim << ".";
01534     throw std::invalid_argument(s.str());
01535   }
01536 
01537   // Wrapping an empty polyhedron is a no-op.
01538   if (x.is_empty())
01539     return;
01540 
01541   // FIXME: temporarily (ab-) using Coefficient.
01542   // Set `min_value' and `max_value' to the minimum and maximum values
01543   // a variable of width `w' and signedness `s' can take.
01544   PPL_DIRTY_TEMP_COEFFICIENT(min_value);
01545   PPL_DIRTY_TEMP_COEFFICIENT(max_value);
01546   if (r == UNSIGNED) {
01547     min_value = 0;
01548     mul_2exp_assign(max_value, Coefficient_one(), w);
01549     --max_value;
01550   }
01551   else {
01552     PPL_ASSERT(r == SIGNED_2_COMPLEMENT);
01553     mul_2exp_assign(max_value, Coefficient_one(), w-1);
01554     neg_assign(min_value, max_value);
01555     --max_value;
01556   }
01557 
01558   // FIXME: Build the (integer) quadrant interval.
01559   PPL_DIRTY_TEMP(ITV, integer_quadrant_itv);
01560   PPL_DIRTY_TEMP(ITV, rational_quadrant_itv);
01561   {
01562     I_Constraint<Coefficient> lower = i_constraint(GREATER_OR_EQUAL, min_value);
01563     I_Constraint<Coefficient> upper = i_constraint(LESS_OR_EQUAL, max_value);
01564     integer_quadrant_itv.build(lower, upper);
01565     // The rational quadrant is only needed if overflow is undefined.
01566     if (o == OVERFLOW_UNDEFINED) {
01567       ++max_value;
01568       upper = i_constraint(LESS_THAN, max_value);
01569       rational_quadrant_itv.build(lower, upper);
01570     }
01571   }
01572 
01573   const Variables_Set::const_iterator vs_end = vars.end();
01574 
01575   if (pcs == 0) {
01576     // No constraint refinement is needed here.
01577     switch (o) {
01578     case OVERFLOW_WRAPS:
01579       for (Variables_Set::const_iterator i = vars.begin(); i != vs_end; ++i)
01580         x.seq[*i].wrap_assign(w, r, integer_quadrant_itv);
01581       reset_empty_up_to_date();
01582       break;
01583     case OVERFLOW_UNDEFINED:
01584       for (Variables_Set::const_iterator i = vars.begin(); i != vs_end; ++i) {
01585         ITV& x_seq_v = x.seq[*i];
01586         if (!rational_quadrant_itv.contains(x_seq_v)) {
01587           x_seq_v.assign(integer_quadrant_itv);
01588         }
01589       }
01590       break;
01591     case OVERFLOW_IMPOSSIBLE:
01592       for (Variables_Set::const_iterator i = vars.begin(); i != vs_end; ++i)
01593         x.seq[*i].intersect_assign(integer_quadrant_itv);
01594       reset_empty_up_to_date();
01595       break;
01596     }
01597     PPL_ASSERT(x.OK());
01598     return;
01599   }
01600 
01601   PPL_ASSERT(pcs != 0);
01602   const Constraint_System& cs = *pcs;
01603   const dimension_type cs_space_dim = cs.space_dimension();
01604   // A map associating interval constraints to variable indexes.
01605   typedef std::map<dimension_type, std::vector<const Constraint*> > map_type;
01606   map_type var_cs_map;
01607   for (Constraint_System::const_iterator i = cs.begin(),
01608          i_end = cs.end(); i != i_end; ++i) {
01609     const Constraint& c = *i;
01610     dimension_type c_num_vars = 0;
01611     dimension_type c_only_var = 0;
01612     if (extract_interval_constraint(c, cs_space_dim,
01613                                     c_num_vars, c_only_var)) {
01614       if (c_num_vars == 1) {
01615         // An interval constraint on variable index `c_only_var'.
01616         PPL_ASSERT(c_only_var < space_dim);
01617         // We do care about c if c_only_var is going to be wrapped.
01618         if (vars.find(c_only_var) != vs_end)
01619           var_cs_map[c_only_var].push_back(&c);
01620       }
01621       else {
01622         PPL_ASSERT(c_num_vars == 0);
01623         // Note: tautologies have been filtered out by iterators.
01624         PPL_ASSERT(c.is_inconsistent());
01625         x.set_empty();
01626         return;
01627       }
01628     }
01629   }
01630 
01631   PPL_DIRTY_TEMP(ITV, refinement_itv);
01632   const map_type::const_iterator var_cs_map_end = var_cs_map.end();
01633   // Loop through the variable indexes in `vars'.
01634   for (Variables_Set::const_iterator i = vars.begin(); i != vs_end; ++i) {
01635     const dimension_type v = *i;
01636     refinement_itv = integer_quadrant_itv;
01637     // Look for the refinement constraints for space dimension index `v'.
01638     map_type::const_iterator var_cs_map_iter = var_cs_map.find(v);
01639     if (var_cs_map_iter != var_cs_map_end) {
01640       // Refine interval for variable `v'.
01641       const map_type::mapped_type& var_cs = var_cs_map_iter->second;
01642       for (dimension_type j = var_cs.size(); j-- > 0; ) {
01643         const Constraint& c = *var_cs[j];
01644         refine_interval_no_check(refinement_itv,
01645                                  c.type(),
01646                                  c.inhomogeneous_term(),
01647                                  c.coefficient(Variable(v)));
01648       }
01649     }
01650     // Wrap space dimension index `v'.
01651     ITV& x_seq_v = x.seq[v];
01652     switch (o) {
01653     case OVERFLOW_WRAPS:
01654       x_seq_v.wrap_assign(w, r, refinement_itv);
01655       break;
01656     case OVERFLOW_UNDEFINED:
01657       if (!rational_quadrant_itv.contains(x_seq_v))
01658         x_seq_v.assign(UNIVERSE);
01659       break;
01660     case OVERFLOW_IMPOSSIBLE:
01661       x_seq_v.intersect_assign(refinement_itv);
01662       break;
01663     }
01664   }
01665   PPL_ASSERT(x.OK());
01666 #endif
01667 }


Friends And Related Function Documentation

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.

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

00597                                       {
00598   return l_m_distance_assign<Euclidean_Distance_Specialization<Temp> >
00599     (r, x, y, dir, tmp0, tmp1, tmp2);
00600 }

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

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

The direction of the approximation is specified by dir.

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

Definition at line 605 of file Box.inlines.hh.

00608                                                   {
00609   typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
00610   PPL_DIRTY_TEMP(Checked_Temp, tmp0);
00611   PPL_DIRTY_TEMP(Checked_Temp, tmp1);
00612   PPL_DIRTY_TEMP(Checked_Temp, tmp2);
00613   return euclidean_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
00614 }

template<typename ITV>
bool extract_interval_constraint ( const Constraint c,
dimension_type  c_space_dim,
dimension_type c_num_vars,
dimension_type c_only_var 
) [related]

Decodes the constraint c as an interval constraint.

Returns:
true if the constraint c is an interval constraint; false otherwise.
Parameters:
c The constraint to be decoded.
c_space_dim The space dimension of the constraint c (it is assumed to match the actual space dimension of c).
c_num_vars If true is returned, then it will be set to the number of variables having a non-zero coefficient. The only legal values will therefore be 0 and 1.
c_only_var If true is returned and if c_num_vars is not set to 0, then it will be set to the index of the only variable having a non-zero coefficient in c.

Definition at line 33 of file Box.cc.

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

Referenced by Parma_Polyhedra_Library::Box< ITV >::add_constraint_no_check(), Parma_Polyhedra_Library::Box< ITV >::get_limiting_box(), Parma_Polyhedra_Library::Box< ITV >::refine_no_check(), Parma_Polyhedra_Library::Box< ITV >::relation_with(), and Parma_Polyhedra_Library::Box< ITV >::wrap_assign().

00036                                                              {
00037   // Check for preconditions.
00038   PPL_ASSERT(c.space_dimension() == c_space_dim);
00039   PPL_ASSERT(c_num_vars == 0 && c_only_var == 0);
00040   // Collect the non-zero components of `c'.
00041   for (dimension_type i = c_space_dim; i-- > 0; )
00042     if (c.coefficient(Variable(i)) != 0) {
00043       if (c_num_vars == 0) {
00044         c_only_var = i;
00045         ++c_num_vars;
00046       }
00047       else
00048         // Constraint `c' is not an interval constraint.
00049         return false;
00050     }
00051   return true;
00052 }

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.

Definition at line 632 of file Box.inlines.hh.

00638                                        {
00639   return l_m_distance_assign<L_Infinity_Distance_Specialization<Temp> >
00640     (r, x, y, dir, tmp0, tmp1, tmp2);
00641 }

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

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

The direction of the approximation is specified by dir.

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

Definition at line 646 of file Box.inlines.hh.

00649                                                    {
00650   typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
00651   PPL_DIRTY_TEMP(Checked_Temp, tmp0);
00652   PPL_DIRTY_TEMP(Checked_Temp, tmp1);
00653   PPL_DIRTY_TEMP(Checked_Temp, tmp2);
00654   return l_infinity_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
00655 }

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.

Definition at line 4083 of file Box.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::combine(), Parma_Polyhedra_Library::finalize(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Box< ITV >::marked_empty(), Parma_Polyhedra_Library::maybe_assign(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::Box< ITV >::seq, and Parma_Polyhedra_Library::Box< ITV >::space_dimension().

04086                                                         {
04087   const dimension_type x_space_dim = x.space_dimension();
04088   // Dimension-compatibility check.
04089   if (x_space_dim != y.space_dimension())
04090     return false;
04091 
04092   // Zero-dim boxes are equal if and only if they are both empty or universe.
04093   if (x_space_dim == 0) {
04094     if (x.marked_empty() == y.marked_empty())
04095       assign_r(r, 0, ROUND_NOT_NEEDED);
04096     else
04097       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
04098     return true;
04099   }
04100 
04101   // The distance computation requires a check for emptiness.
04102   (void) x.is_empty();
04103   (void) y.is_empty();
04104   // If one of two boxes is empty, then they are equal if and only if
04105   // the other box is empty too.
04106   if (x.marked_empty() || y.marked_empty()) {
04107     if (x.marked_empty() == y.marked_empty()) {
04108       assign_r(r, 0, ROUND_NOT_NEEDED);
04109       return true;
04110     }
04111     else
04112       goto pinf;
04113   }
04114 
04115   assign_r(tmp0, 0, ROUND_NOT_NEEDED);
04116   for (dimension_type i = x_space_dim; i-- > 0; ) {
04117     const ITV& x_i = x.seq[i];
04118     const ITV& y_i = y.seq[i];
04119     // Dealing with the lower bounds.
04120     if (x_i.lower_is_boundary_infinity()) {
04121       if (!y_i.lower_is_boundary_infinity())
04122         goto pinf;
04123     }
04124     else if (y_i.lower_is_boundary_infinity())
04125       goto pinf;
04126     else {
04127       const Temp* tmp1p;
04128       const Temp* tmp2p;
04129       if (x_i.lower() > y_i.lower()) {
04130         maybe_assign(tmp1p, tmp1, x_i.lower(), dir);
04131         maybe_assign(tmp2p, tmp2, y_i.lower(), inverse(dir));
04132       }
04133       else {
04134         maybe_assign(tmp1p, tmp1, y_i.lower(), dir);
04135         maybe_assign(tmp2p, tmp2, x_i.lower(), inverse(dir));
04136       }
04137       sub_assign_r(tmp1, *tmp1p, *tmp2p, dir);
04138       PPL_ASSERT(sgn(tmp1) >= 0);
04139       Specialization::combine(tmp0, tmp1, dir);
04140     }
04141     // Dealing with the lower bounds.
04142     if (x_i.upper_is_boundary_infinity())
04143       if (y_i.upper_is_boundary_infinity())
04144         continue;
04145       else
04146         goto pinf;
04147     else if (y_i.upper_is_boundary_infinity())
04148       goto pinf;
04149     else {
04150       const Temp* tmp1p;
04151       const Temp* tmp2p;
04152       if (x_i.upper() > y_i.upper()) {
04153         maybe_assign(tmp1p, tmp1, x_i.upper(), dir);
04154         maybe_assign(tmp2p, tmp2, y_i.upper(), inverse(dir));
04155       }
04156       else {
04157         maybe_assign(tmp1p, tmp1, y_i.upper(), dir);
04158         maybe_assign(tmp2p, tmp2, x_i.upper(), inverse(dir));
04159       }
04160       sub_assign_r(tmp1, *tmp1p, *tmp2p, dir);
04161       PPL_ASSERT(sgn(tmp1) >= 0);
04162       Specialization::combine(tmp0, tmp1, dir);
04163     }
04164   }
04165   Specialization::finalize(tmp0, dir);
04166   assign_r(r, tmp0, dir);
04167   return true;
04168 
04169  pinf:
04170   assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
04171   return true;
04172 }

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

Returns true if and only if x and y aren't the same box.

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

Definition at line 254 of file Box.inlines.hh.

00254                                                  {
00255   return !(x == y);
00256 }

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

Output operator.

Definition at line 3888 of file Box.templates.hh.

03888                                                            {
03889   if (box.is_empty())
03890     s << "false";
03891   else if (box.is_universe())
03892     s << "true";
03893   else
03894     for (dimension_type k = 0,
03895            space_dim = box.space_dimension(); k < space_dim; ) {
03896       s << Variable(k) << " in " << box[k];
03897       ++k;
03898       if (k < space_dim)
03899         s << ", ";
03900       else
03901         break;
03902     }
03903   return s;
03904 }

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

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

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

Definition at line 533 of file Box.templates.hh.

00533                                                  {
00534   const dimension_type x_space_dim = x.space_dimension();
00535   if (x_space_dim != y.space_dimension())
00536     return false;
00537 
00538   if (x.is_empty())
00539     return y.is_empty();
00540 
00541   if (y.is_empty())
00542     return x.is_empty();
00543 
00544   for (dimension_type k = x_space_dim; k-- > 0; )
00545     if (x.seq[k] != y.seq[k])
00546       return false;
00547   return true;
00548 }

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

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

Definition at line 550 of file Box.inlines.hh.

00556                                         {
00557   return l_m_distance_assign<Rectilinear_Distance_Specialization<Temp> >
00558     (r, x, y, dir, tmp0, tmp1, tmp2);
00559 }

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

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

The direction of the approximation is specified by dir.

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

Definition at line 564 of file Box.inlines.hh.

00567                                                     {
00568   typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
00569   PPL_DIRTY_TEMP(Checked_Temp, tmp0);
00570   PPL_DIRTY_TEMP(Checked_Temp, tmp1);
00571   PPL_DIRTY_TEMP(Checked_Temp, tmp2);
00572   return rectilinear_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
00573 }


Member Data Documentation

template<typename ITV>
Sequence Parma_Polyhedra_Library::Box< ITV >::seq [private]

A sequence of intervals, one for each dimension of the vector space.

Definition at line 1702 of file Box.defs.hh.

Referenced by Parma_Polyhedra_Library::Box< ITV >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Box< ITV >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::Box< ITV >::affine_dimension(), Parma_Polyhedra_Library::Box< ITV >::affine_image(), Parma_Polyhedra_Library::Box< ITV >::affine_preimage(), Parma_Polyhedra_Library::Box< ITV >::ascii_dump(), Parma_Polyhedra_Library::Box< ITV >::bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Box< ITV >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Box< ITV >::CC76_widening_assign(), Parma_Polyhedra_Library::Box< ITV >::check_empty(), Parma_Polyhedra_Library::Box< ITV >::concatenate_assign(), Parma_Polyhedra_Library::Box< ITV >::congruences(), Parma_Polyhedra_Library::Box< ITV >::constrains(), Parma_Polyhedra_Library::Box< ITV >::contains(), Parma_Polyhedra_Library::Box< ITV >::contains_integer_point(), Parma_Polyhedra_Library::Box< ITV >::difference_assign(), Parma_Polyhedra_Library::Box< ITV >::drop_some_non_integer_points(), Parma_Polyhedra_Library::Box< ITV >::expand_space_dimension(), Parma_Polyhedra_Library::Box< ITV >::external_memory_in_bytes(), Parma_Polyhedra_Library::Box< ITV >::fold_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::frequency(), Parma_Polyhedra_Library::Box< ITV >::get_interval(), Parma_Polyhedra_Library::Box< ITV >::get_limiting_box(), Parma_Polyhedra_Library::Box< ITV >::get_lower_bound(), Parma_Polyhedra_Library::Box< ITV >::get_upper_bound(), Parma_Polyhedra_Library::Box< ITV >::intersection_assign(), Parma_Polyhedra_Library::Box< ITV >::is_bounded(), Parma_Polyhedra_Library::Box< ITV >::is_discrete(), Parma_Polyhedra_Library::Box< ITV >::is_disjoint_from(), Parma_Polyhedra_Library::Box< ITV >::is_topologically_closed(), Parma_Polyhedra_Library::Box< ITV >::is_universe(), Parma_Polyhedra_Library::Box< ITV >::l_m_distance_assign(), Parma_Polyhedra_Library::Box< ITV >::map_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::max_min(), Parma_Polyhedra_Library::Box< ITV >::minimized_constraints(), Parma_Polyhedra_Library::Box< ITV >::OK(), Parma_Polyhedra_Library::Box< ITV >::operator=(), Parma_Polyhedra_Library::operator==(), Parma_Polyhedra_Library::Box< ITV >::operator[](), Parma_Polyhedra_Library::Box< ITV >::propagate_constraint_no_check(), Parma_Polyhedra_Library::Box< ITV >::relation_with(), Parma_Polyhedra_Library::Box< ITV >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::remove_space_dimensions(), Parma_Polyhedra_Library::Box< ITV >::set_interval(), Parma_Polyhedra_Library::Box< ITV >::simplify_using_context_assign(), Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Box< ITV >::swap(), Parma_Polyhedra_Library::Box< ITV >::time_elapse_assign(), Parma_Polyhedra_Library::Box< ITV >::topological_closure_assign(), Parma_Polyhedra_Library::Box< ITV >::unconstrain(), Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign(), Parma_Polyhedra_Library::Box< ITV >::upper_bound_assign_if_exact(), and Parma_Polyhedra_Library::Box< ITV >::wrap_assign().

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

The documentation for this class was generated from the following files:
Generated on Sun Feb 27 16:20:29 2011 for PPL by  doxygen 1.6.3