00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef PPL_Generator_inlines_hh
00025 #define PPL_Generator_inlines_hh 1
00026
00027 namespace Parma_Polyhedra_Library {
00028
00029 inline
00030 Generator::Generator(Linear_Expression& e, Type type, Topology topology) {
00031 PPL_ASSERT(type != CLOSURE_POINT || topology == NOT_NECESSARILY_CLOSED);
00032 Linear_Row::swap(e);
00033 flags() = Flags(topology, (type == LINE
00034 ? LINE_OR_EQUALITY
00035 : RAY_OR_POINT_OR_INEQUALITY));
00036 }
00037
00038 inline
00039 Generator::Generator(const Generator& g)
00040 : Linear_Row(g) {
00041 }
00042
00043 inline
00044 Generator::Generator(const Generator& g, dimension_type dimension)
00045 : Linear_Row(g, dimension, dimension) {
00046 }
00047
00048 inline
00049 Generator::~Generator() {
00050 }
00051
00052 inline Generator&
00053 Generator::operator=(const Generator& g) {
00054 Linear_Row::operator=(g);
00055 return *this;
00056 }
00057
00058 inline dimension_type
00059 Generator::max_space_dimension() {
00060 return Linear_Row::max_space_dimension();
00061 }
00062
00063 inline dimension_type
00064 Generator::space_dimension() const {
00065 return Linear_Row::space_dimension();
00066 }
00067
00068 inline bool
00069 Generator::is_line() const {
00070 return is_line_or_equality();
00071 }
00072
00073 inline bool
00074 Generator::is_ray_or_point() const {
00075 return is_ray_or_point_or_inequality();
00076 }
00077
00078 inline bool
00079 Generator::is_line_or_ray() const {
00080 return (*this)[0] == 0;
00081 }
00082
00083 inline bool
00084 Generator::is_ray() const {
00085 return is_ray_or_point() && is_line_or_ray();
00086 }
00087
00088 inline Generator::Type
00089 Generator::type() const {
00090 if (is_line())
00091 return LINE;
00092 if (is_line_or_ray())
00093 return RAY;
00094 if (is_necessarily_closed())
00095 return POINT;
00096 else {
00097
00098 const Generator& g = *this;
00099 return (g[size() - 1] == 0) ? CLOSURE_POINT : POINT;
00100 }
00101 }
00102
00103 inline bool
00104 Generator::is_point() const {
00105 return type() == POINT;
00106 }
00107
00108 inline bool
00109 Generator::is_closure_point() const {
00110 return type() == CLOSURE_POINT;
00111 }
00112
00113 inline void
00114 Generator::set_is_line() {
00115 set_is_line_or_equality();
00116 }
00117
00118 inline void
00119 Generator::set_is_ray_or_point() {
00120 set_is_ray_or_point_or_inequality();
00121 }
00122
00123 inline Coefficient_traits::const_reference
00124 Generator::coefficient(const Variable v) const {
00125 if (v.space_dimension() > space_dimension())
00126 throw_dimension_incompatible("coefficient(v)", "v", v);
00127 return Linear_Row::coefficient(v.id());
00128 }
00129
00130 inline Coefficient_traits::const_reference
00131 Generator::divisor() const {
00132 Coefficient_traits::const_reference d = Linear_Row::inhomogeneous_term();
00133 if (!is_ray_or_point() || d == 0)
00134 throw_invalid_argument("divisor()",
00135 "*this is neither a point nor a closure point");
00136 return d;
00137 }
00138
00139 inline memory_size_type
00140 Generator::external_memory_in_bytes() const {
00141 return Linear_Row::external_memory_in_bytes();
00142 }
00143
00144 inline memory_size_type
00145 Generator::total_memory_in_bytes() const {
00146 return Linear_Row::total_memory_in_bytes();
00147 }
00148
00149 inline const Generator&
00150 Generator::zero_dim_point() {
00151 PPL_ASSERT(zero_dim_point_p != 0);
00152 return *zero_dim_point_p;
00153 }
00154
00155 inline const Generator&
00156 Generator::zero_dim_closure_point() {
00157 PPL_ASSERT(zero_dim_closure_point_p != 0);
00158 return *zero_dim_closure_point_p;
00159 }
00160
00162 inline Generator
00163 line(const Linear_Expression& e) {
00164 return Generator::line(e);
00165 }
00166
00168 inline Generator
00169 ray(const Linear_Expression& e) {
00170 return Generator::ray(e);
00171 }
00172
00174 inline Generator
00175 point(const Linear_Expression& e, Coefficient_traits::const_reference d) {
00176 return Generator::point(e, d);
00177 }
00178
00180 inline Generator
00181 closure_point(const Linear_Expression& e,
00182 Coefficient_traits::const_reference d) {
00183 return Generator::closure_point(e, d);
00184 }
00185
00187 inline bool
00188 operator==(const Generator& x, const Generator& y) {
00189 return x.is_equivalent_to(y);
00190 }
00191
00193 inline bool
00194 operator!=(const Generator& x, const Generator& y) {
00195 return !x.is_equivalent_to(y);
00196 }
00197
00198 inline void
00199 Generator::ascii_dump(std::ostream& s) const {
00200 Linear_Row::ascii_dump(s);
00201 }
00202
00203 inline bool
00204 Generator::ascii_load(std::istream& s) {
00205 return Linear_Row::ascii_load(s);
00206 }
00207
00208 inline void
00209 Generator::swap(Generator& y) {
00210 Linear_Row::swap(y);
00211 }
00212
00213 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
00214
00215 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
00216 template <typename Specialization, typename Temp, typename To>
00217 inline bool
00218 l_m_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00219 const Generator& x,
00220 const Generator& y,
00221 const Rounding_Dir dir,
00222 Temp& tmp0,
00223 Temp& tmp1,
00224 Temp& tmp2) {
00225
00226
00227 if (x.is_line_or_ray() || y.is_line_or_ray())
00228 return false;
00229 const dimension_type x_space_dim = x.space_dimension();
00230
00231 if (x_space_dim != y.space_dimension())
00232 return false;
00233
00234
00235 if (x_space_dim == 0) {
00236 assign_r(r, 0, ROUND_NOT_NEEDED);
00237 return true;
00238 }
00239
00240 PPL_DIRTY_TEMP0(mpq_class, x_coord);
00241 PPL_DIRTY_TEMP0(mpq_class, y_coord);
00242 PPL_DIRTY_TEMP0(mpq_class, x_div);
00243 PPL_DIRTY_TEMP0(mpq_class, y_div);
00244 assign_r(x_div, x.divisor(), ROUND_NOT_NEEDED);
00245 assign_r(y_div, y.divisor(), ROUND_NOT_NEEDED);
00246
00247 assign_r(tmp0, 0, ROUND_NOT_NEEDED);
00248 for (dimension_type i = x_space_dim; i-- > 0; ) {
00249 assign_r(x_coord, x.coefficient(Variable(i)), ROUND_NOT_NEEDED);
00250 div_assign_r(x_coord, x_coord, x_div, ROUND_NOT_NEEDED);
00251 assign_r(y_coord, y.coefficient(Variable(i)), ROUND_NOT_NEEDED);
00252 div_assign_r(y_coord, y_coord, y_div, ROUND_NOT_NEEDED);
00253 const Temp* tmp1p;
00254 const Temp* tmp2p;
00255
00256 if (x_coord > y_coord) {
00257 maybe_assign(tmp1p, tmp1, x_coord, dir);
00258 maybe_assign(tmp2p, tmp2, y_coord, inverse(dir));
00259 }
00260 else {
00261 maybe_assign(tmp1p, tmp1, y_coord, dir);
00262 maybe_assign(tmp2p, tmp2, x_coord, inverse(dir));
00263 }
00264 sub_assign_r(tmp1, *tmp1p, *tmp2p, dir);
00265 PPL_ASSERT(sgn(tmp1) >= 0);
00266 Specialization::combine(tmp0, tmp1, dir);
00267 }
00268 Specialization::finalize(tmp0, dir);
00269 assign_r(r, tmp0, dir);
00270 return true;
00271 }
00272
00274 template <typename Temp, typename To>
00275 inline bool
00276 rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00277 const Generator& x,
00278 const Generator& y,
00279 const Rounding_Dir dir,
00280 Temp& tmp0,
00281 Temp& tmp1,
00282 Temp& tmp2) {
00283 return l_m_distance_assign<Rectilinear_Distance_Specialization<Temp> >
00284 (r, x, y, dir, tmp0, tmp1, tmp2);
00285 }
00286
00288 template <typename Temp, typename To>
00289 inline bool
00290 rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00291 const Generator& x,
00292 const Generator& y,
00293 const Rounding_Dir dir) {
00294 typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
00295 PPL_DIRTY_TEMP(Checked_Temp, tmp0);
00296 PPL_DIRTY_TEMP(Checked_Temp, tmp1);
00297 PPL_DIRTY_TEMP(Checked_Temp, tmp2);
00298 return rectilinear_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
00299 }
00300
00302 template <typename To>
00303 inline bool
00304 rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00305 const Generator& x,
00306 const Generator& y,
00307 const Rounding_Dir dir) {
00308 return rectilinear_distance_assign<To, To>(r, x, y, dir);
00309 }
00310
00312 template <typename Temp, typename To>
00313 inline bool
00314 euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00315 const Generator& x,
00316 const Generator& y,
00317 const Rounding_Dir dir,
00318 Temp& tmp0,
00319 Temp& tmp1,
00320 Temp& tmp2) {
00321 return l_m_distance_assign<Euclidean_Distance_Specialization<Temp> >
00322 (r, x, y, dir, tmp0, tmp1, tmp2);
00323 }
00324
00326 template <typename Temp, typename To>
00327 inline bool
00328 euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00329 const Generator& x,
00330 const Generator& y,
00331 const Rounding_Dir dir) {
00332 typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
00333 PPL_DIRTY_TEMP(Checked_Temp, tmp0);
00334 PPL_DIRTY_TEMP(Checked_Temp, tmp1);
00335 PPL_DIRTY_TEMP(Checked_Temp, tmp2);
00336 return euclidean_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
00337 }
00338
00340 template <typename To>
00341 inline bool
00342 euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00343 const Generator& x,
00344 const Generator& y,
00345 const Rounding_Dir dir) {
00346 return euclidean_distance_assign<To, To>(r, x, y, dir);
00347 }
00348
00350 template <typename Temp, typename To>
00351 inline bool
00352 l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00353 const Generator& x,
00354 const Generator& y,
00355 const Rounding_Dir dir,
00356 Temp& tmp0,
00357 Temp& tmp1,
00358 Temp& tmp2) {
00359 return l_m_distance_assign<L_Infinity_Distance_Specialization<Temp> >
00360 (r, x, y, dir, tmp0, tmp1, tmp2);
00361 }
00362
00364 template <typename Temp, typename To>
00365 inline bool
00366 l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00367 const Generator& x,
00368 const Generator& y,
00369 const Rounding_Dir dir) {
00370 typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
00371 PPL_DIRTY_TEMP(Checked_Temp, tmp0);
00372 PPL_DIRTY_TEMP(Checked_Temp, tmp1);
00373 PPL_DIRTY_TEMP(Checked_Temp, tmp2);
00374 return l_infinity_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
00375 }
00376
00378 template <typename To>
00379 inline bool
00380 l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00381 const Generator& x,
00382 const Generator& y,
00383 const Rounding_Dir dir) {
00384 return l_infinity_distance_assign<To, To>(r, x, y, dir);
00385 }
00386
00387 }
00388
00389 namespace std {
00390
00392 inline void
00393 swap(Parma_Polyhedra_Library::Generator& x,
00394 Parma_Polyhedra_Library::Generator& y) {
00395 x.swap(y);
00396 }
00397
00398 }
00399
00400 #endif // !defined(PPL_Generator_inlines_hh)