1 /* Generator class implementation: inline functions.
2    Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3    Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4 
5 This file is part of the Parma Polyhedra Library (PPL).
6 
7 The PPL is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 The PPL is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20 
21 For the most up-to-date information see the Parma Polyhedra Library
22 site: http://bugseng.com/products/ppl/ . */
23 
24 #ifndef PPL_Generator_inlines_hh
25 #define PPL_Generator_inlines_hh 1
26 
27 namespace Parma_Polyhedra_Library {
28 
29 inline bool
is_necessarily_closed() const30 Generator::is_necessarily_closed() const {
31   return (topology() == NECESSARILY_CLOSED);
32 }
33 
34 inline bool
is_not_necessarily_closed() const35 Generator::is_not_necessarily_closed() const {
36   return (topology() == NOT_NECESSARILY_CLOSED);
37 }
38 
39 inline Generator::expr_type
expression() const40 Generator::expression() const {
41   return expr_type(expr, is_not_necessarily_closed());
42 }
43 
44 inline dimension_type
space_dimension() const45 Generator::space_dimension() const {
46   return expression().space_dimension();
47 }
48 
49 inline bool
is_line_or_equality() const50 Generator::is_line_or_equality() const {
51   return (kind_ == LINE_OR_EQUALITY);
52 }
53 
54 inline bool
is_ray_or_point_or_inequality() const55 Generator::is_ray_or_point_or_inequality() const {
56   return (kind_ == RAY_OR_POINT_OR_INEQUALITY);
57 }
58 
59 inline Topology
topology() const60 Generator::topology() const {
61   return topology_;
62 }
63 
64 inline void
set_is_line_or_equality()65 Generator::set_is_line_or_equality() {
66   kind_ = LINE_OR_EQUALITY;
67 }
68 
69 inline void
set_is_ray_or_point_or_inequality()70 Generator::set_is_ray_or_point_or_inequality() {
71   kind_ = RAY_OR_POINT_OR_INEQUALITY;
72 }
73 
74 inline void
set_topology(Topology x)75 Generator::set_topology(Topology x) {
76   if (topology() == x) {
77     return;
78   }
79   if (topology() == NECESSARILY_CLOSED) {
80     // Add a column for the epsilon dimension.
81     expr.set_space_dimension(expr.space_dimension() + 1);
82   }
83   else {
84     PPL_ASSERT(expr.space_dimension() > 0);
85     expr.set_space_dimension(expr.space_dimension() - 1);
86   }
87   topology_ = x;
88 }
89 
90 inline void
mark_as_necessarily_closed()91 Generator::mark_as_necessarily_closed() {
92   PPL_ASSERT(is_not_necessarily_closed());
93   topology_ = NECESSARILY_CLOSED;
94 }
95 
96 inline void
mark_as_not_necessarily_closed()97 Generator::mark_as_not_necessarily_closed() {
98   PPL_ASSERT(is_necessarily_closed());
99   topology_ = NOT_NECESSARILY_CLOSED;
100 }
101 
102 inline void
set_necessarily_closed()103 Generator::set_necessarily_closed() {
104   set_topology(NECESSARILY_CLOSED);
105 }
106 
107 inline void
set_not_necessarily_closed()108 Generator::set_not_necessarily_closed() {
109   set_topology(NOT_NECESSARILY_CLOSED);
110 }
111 
112 inline
Generator(Representation r)113 Generator::Generator(Representation r)
114   : expr(r),
115     kind_(RAY_OR_POINT_OR_INEQUALITY),
116     topology_(NECESSARILY_CLOSED) {
117   expr.set_inhomogeneous_term(Coefficient_one());
118   PPL_ASSERT(space_dimension() == 0);
119   PPL_ASSERT(OK());
120 }
121 
122 inline
Generator(dimension_type space_dim,Kind kind,Topology topology,Representation r)123 Generator::Generator(dimension_type space_dim, Kind kind, Topology topology,
124                      Representation r)
125   : expr(r),
126     kind_(kind),
127     topology_(topology) {
128   if (is_necessarily_closed()) {
129     expr.set_space_dimension(space_dim);
130   }
131   else {
132     expr.set_space_dimension(space_dim + 1);
133   }
134   PPL_ASSERT(space_dimension() == space_dim);
135   PPL_ASSERT(OK());
136 }
137 
138 inline
Generator(Linear_Expression & e,Type type,Topology topology)139 Generator::Generator(Linear_Expression& e, Type type, Topology topology)
140   : topology_(topology) {
141   PPL_ASSERT(type != CLOSURE_POINT || topology == NOT_NECESSARILY_CLOSED);
142   swap(expr, e);
143   if (topology == NOT_NECESSARILY_CLOSED) {
144     expr.set_space_dimension(expr.space_dimension() + 1);
145   }
146   if (type == LINE) {
147     kind_ = LINE_OR_EQUALITY;
148   }
149   else {
150     kind_ = RAY_OR_POINT_OR_INEQUALITY;
151   }
152   strong_normalize();
153 }
154 
155 inline
Generator(Linear_Expression & e,Kind kind,Topology topology)156 Generator::Generator(Linear_Expression& e, Kind kind, Topology topology)
157   : kind_(kind),
158     topology_(topology) {
159   swap(expr, e);
160   if (topology == NOT_NECESSARILY_CLOSED) {
161     expr.set_space_dimension(expr.space_dimension() + 1);
162   }
163   strong_normalize();
164 }
165 
166 inline
Generator(const Generator & g)167 Generator::Generator(const Generator& g)
168   : expr(g.expr),
169     kind_(g.kind_),
170     topology_(g.topology_) {
171 }
172 
173 inline
Generator(const Generator & g,Representation r)174 Generator::Generator(const Generator& g, Representation r)
175   : expr(g.expr, r),
176     kind_(g.kind_),
177     topology_(g.topology_) {
178   // This does not assert OK() because it's called by OK().
179   PPL_ASSERT(OK());
180 }
181 
182 inline
Generator(const Generator & g,dimension_type space_dim)183 Generator::Generator(const Generator& g, dimension_type space_dim)
184   : expr(g.expr, g.is_necessarily_closed() ? space_dim : (space_dim + 1)),
185     kind_(g.kind_),
186     topology_(g.topology_) {
187   PPL_ASSERT(OK());
188   PPL_ASSERT(space_dimension() == space_dim);
189 }
190 
191 inline
Generator(const Generator & g,dimension_type space_dim,Representation r)192 Generator::Generator(const Generator& g, dimension_type space_dim,
193                      Representation r)
194   : expr(g.expr, g.is_necessarily_closed() ? space_dim : (space_dim + 1), r),
195     kind_(g.kind_),
196     topology_(g.topology_) {
197   PPL_ASSERT(OK());
198   PPL_ASSERT(space_dimension() == space_dim);
199 }
200 
201 inline
~Generator()202 Generator::~Generator() {
203 }
204 
205 inline Generator&
operator =(const Generator & g)206 Generator::operator=(const Generator& g) {
207   Generator tmp = g;
208   swap(*this, tmp);
209 
210   return *this;
211 }
212 
213 inline Representation
representation() const214 Generator::representation() const {
215   return expr.representation();
216 }
217 
218 inline void
set_representation(Representation r)219 Generator::set_representation(Representation r) {
220   expr.set_representation(r);
221 }
222 
223 inline dimension_type
max_space_dimension()224 Generator::max_space_dimension() {
225   return Linear_Expression::max_space_dimension();
226 }
227 
228 inline void
set_space_dimension_no_ok(dimension_type space_dim)229 Generator::set_space_dimension_no_ok(dimension_type space_dim) {
230   const dimension_type old_expr_space_dim = expr.space_dimension();
231   if (topology() == NECESSARILY_CLOSED) {
232     expr.set_space_dimension(space_dim);
233   }
234   else {
235     const dimension_type old_space_dim = space_dimension();
236     if (space_dim > old_space_dim) {
237       expr.set_space_dimension(space_dim + 1);
238       expr.swap_space_dimensions(Variable(space_dim), Variable(old_space_dim));
239     }
240     else {
241       expr.swap_space_dimensions(Variable(space_dim), Variable(old_space_dim));
242       expr.set_space_dimension(space_dim + 1);
243     }
244   }
245   PPL_ASSERT(space_dimension() == space_dim);
246   if (expr.space_dimension() < old_expr_space_dim) {
247     strong_normalize();
248   }
249 }
250 
251 inline void
set_space_dimension(dimension_type space_dim)252 Generator::set_space_dimension(dimension_type space_dim) {
253   set_space_dimension_no_ok(space_dim);
254   PPL_ASSERT(OK());
255 }
256 
257 inline void
shift_space_dimensions(Variable v,dimension_type n)258 Generator::shift_space_dimensions(Variable v, dimension_type n) {
259   expr.shift_space_dimensions(v, n);
260 }
261 
262 inline bool
is_line() const263 Generator::is_line() const {
264   return is_line_or_equality();
265 }
266 
267 inline bool
is_ray_or_point() const268 Generator::is_ray_or_point() const {
269   return is_ray_or_point_or_inequality();
270 }
271 
272 inline bool
is_line_or_ray() const273 Generator::is_line_or_ray() const {
274   return expr.inhomogeneous_term() == 0;
275 }
276 
277 inline bool
is_ray() const278 Generator::is_ray() const {
279   return is_ray_or_point() && is_line_or_ray();
280 }
281 
282 inline Generator::Type
type() const283 Generator::type() const {
284   if (is_line()) {
285     return LINE;
286   }
287   if (is_line_or_ray()) {
288     return RAY;
289   }
290   if (is_necessarily_closed()) {
291     return POINT;
292   }
293   else {
294     // Checking the value of the epsilon coefficient.
295     if (epsilon_coefficient() == 0) {
296       return CLOSURE_POINT;
297     }
298     else {
299       return POINT;
300     }
301   }
302 }
303 
304 inline bool
is_point() const305 Generator::is_point() const {
306   return type() == POINT;
307 }
308 
309 inline bool
is_closure_point() const310 Generator::is_closure_point() const {
311   return type() == CLOSURE_POINT;
312 }
313 
314 inline void
set_is_line()315 Generator::set_is_line() {
316   set_is_line_or_equality();
317 }
318 
319 inline void
set_is_ray_or_point()320 Generator::set_is_ray_or_point() {
321   set_is_ray_or_point_or_inequality();
322 }
323 
324 inline Coefficient_traits::const_reference
coefficient(const Variable v) const325 Generator::coefficient(const Variable v) const {
326   if (v.space_dimension() > space_dimension()) {
327     throw_dimension_incompatible("coefficient(v)", "v", v);
328   }
329   return expr.coefficient(v);
330 }
331 
332 inline Coefficient_traits::const_reference
divisor() const333 Generator::divisor() const {
334   Coefficient_traits::const_reference d = expr.inhomogeneous_term();
335   if (!is_ray_or_point() || d == 0) {
336     throw_invalid_argument("divisor()",
337                            "*this is neither a point nor a closure point");
338   }
339   return d;
340 }
341 
342 inline Coefficient_traits::const_reference
epsilon_coefficient() const343 Generator::epsilon_coefficient() const {
344   PPL_ASSERT(is_not_necessarily_closed());
345   return expr.coefficient(Variable(expr.space_dimension() - 1));
346 }
347 
348 
349 inline void
set_epsilon_coefficient(Coefficient_traits::const_reference n)350 Generator::set_epsilon_coefficient(Coefficient_traits::const_reference n) {
351   PPL_ASSERT(is_not_necessarily_closed());
352   expr.set_coefficient(Variable(expr.space_dimension() - 1), n);
353 }
354 
355 
356 inline memory_size_type
external_memory_in_bytes() const357 Generator::external_memory_in_bytes() const {
358   return expr.external_memory_in_bytes();
359 }
360 
361 inline memory_size_type
total_memory_in_bytes() const362 Generator::total_memory_in_bytes() const {
363   return sizeof(*this) + external_memory_in_bytes();
364 }
365 
366 inline void
strong_normalize()367 Generator::strong_normalize() {
368   expr.normalize();
369   sign_normalize();
370 }
371 
372 inline const Generator&
zero_dim_point()373 Generator::zero_dim_point() {
374   PPL_ASSERT(zero_dim_point_p != 0);
375   return *zero_dim_point_p;
376 }
377 
378 inline const Generator&
zero_dim_closure_point()379 Generator::zero_dim_closure_point() {
380   PPL_ASSERT(zero_dim_closure_point_p != 0);
381   return *zero_dim_closure_point_p;
382 }
383 
384 /*! \relates Generator */
385 inline Generator
line(const Linear_Expression & e,Representation r)386 line(const Linear_Expression& e, Representation r) {
387   return Generator::line(e, r);
388 }
389 
390 /*! \relates Generator */
391 inline Generator
ray(const Linear_Expression & e,Representation r)392 ray(const Linear_Expression& e, Representation r) {
393   return Generator::ray(e, r);
394 }
395 
396 /*! \relates Generator */
397 inline Generator
point(const Linear_Expression & e,Coefficient_traits::const_reference d,Representation r)398 point(const Linear_Expression& e, Coefficient_traits::const_reference d,
399       Representation r) {
400   return Generator::point(e, d, r);
401 }
402 
403 /*! \relates Generator */
404 inline Generator
point(Representation r)405 point(Representation r) {
406   return Generator::point(r);
407 }
408 
409 /*! \relates Generator */
410 inline Generator
point(const Linear_Expression & e,Representation r)411 point(const Linear_Expression& e, Representation r) {
412   return Generator::point(e, r);
413 }
414 
415 /*! \relates Generator */
416 inline Generator
closure_point(const Linear_Expression & e,Coefficient_traits::const_reference d,Representation r)417 closure_point(const Linear_Expression& e,
418               Coefficient_traits::const_reference d,
419               Representation r) {
420   return Generator::closure_point(e, d, r);
421 }
422 
423 /*! \relates Generator */
424 inline Generator
closure_point(Representation r)425 closure_point(Representation r) {
426   return Generator::closure_point(r);
427 }
428 
429 /*! \relates Generator */
430 inline Generator
closure_point(const Linear_Expression & e,Representation r)431 closure_point(const Linear_Expression& e,
432               Representation r) {
433   return Generator::closure_point(e, r);
434 }
435 
436 /*! \relates Generator */
437 inline bool
operator ==(const Generator & x,const Generator & y)438 operator==(const Generator& x, const Generator& y) {
439   return x.is_equivalent_to(y);
440 }
441 
442 /*! \relates Generator */
443 inline bool
operator !=(const Generator & x,const Generator & y)444 operator!=(const Generator& x, const Generator& y) {
445   return !x.is_equivalent_to(y);
446 }
447 
448 inline void
ascii_dump(std::ostream & s) const449 Generator::ascii_dump(std::ostream& s) const {
450 
451   expr.ascii_dump(s);
452 
453   s << " ";
454 
455   switch (type()) {
456   case Generator::LINE:
457     s << "L ";
458     break;
459   case Generator::RAY:
460     s << "R ";
461     break;
462   case Generator::POINT:
463     s << "P ";
464     break;
465   case Generator::CLOSURE_POINT:
466     s << "C ";
467     break;
468   }
469   if (is_necessarily_closed()) {
470     s << "(C)";
471   }
472   else {
473     s << "(NNC)";
474   }
475   s << "\n";
476 }
477 
478 inline bool
ascii_load(std::istream & s)479 Generator::ascii_load(std::istream& s) {
480   std::string str;
481 
482   expr.ascii_load(s);
483 
484   if (!(s >> str)) {
485     return false;
486   }
487   if (str == "L") {
488     set_is_line();
489   }
490   else if (str == "R" || str == "P" || str == "C") {
491     set_is_ray_or_point();
492   }
493   else {
494     return false;
495   }
496 
497   std::string str2;
498 
499   if (!(s >> str2)) {
500     return false;
501   }
502   if (str2 == "(C)") {
503     if (is_not_necessarily_closed()) {
504       // TODO: Avoid using the mark_as_*() methods if possible.
505       mark_as_necessarily_closed();
506     }
507   }
508   else {
509     if (str2 == "(NNC)") {
510       if (is_necessarily_closed()) {
511         // TODO: Avoid using the mark_as_*() methods if possible.
512         mark_as_not_necessarily_closed();
513       }
514     }
515     else {
516       return false;
517     }
518   }
519 
520   // Checking for equality of actual and declared types.
521   switch (type()) {
522   case Generator::LINE:
523     if (str != "L") {
524       return false;
525     }
526     break;
527   case Generator::RAY:
528     if (str != "R") {
529       return false;
530     }
531     break;
532   case Generator::POINT:
533     if (str != "P") {
534       return false;
535     }
536     break;
537   case Generator::CLOSURE_POINT:
538     if (str != "C") {
539       return false;
540     }
541     break;
542   }
543 
544   return true;
545 }
546 
547 inline void
m_swap(Generator & y)548 Generator::m_swap(Generator& y) {
549   using std::swap;
550   swap(expr, y.expr);
551   swap(kind_, y.kind_);
552   swap(topology_, y.topology_);
553 }
554 
555 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
556 /*! \relates Generator */
557 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
558 template <typename Specialization, typename Temp, typename To>
559 inline bool
l_m_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const Generator & x,const Generator & y,const Rounding_Dir dir,Temp & tmp0,Temp & tmp1,Temp & tmp2)560 l_m_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
561                     const Generator& x,
562                     const Generator& y,
563                     const Rounding_Dir dir,
564                     Temp& tmp0,
565                     Temp& tmp1,
566                     Temp& tmp2) {
567   // Generator kind compatibility check: we only compute distances
568   // between (closure) points.
569   if (x.is_line_or_ray() || y.is_line_or_ray()) {
570     return false;
571   }
572   const dimension_type x_space_dim = x.space_dimension();
573   // Dimension-compatibility check.
574   if (x_space_dim != y.space_dimension()) {
575     return false;
576   }
577 
578   // All zero-dim generators have distance zero.
579   if (x_space_dim == 0) {
580     assign_r(r, 0, ROUND_NOT_NEEDED);
581     return true;
582   }
583 
584   PPL_DIRTY_TEMP(mpq_class, x_coord);
585   PPL_DIRTY_TEMP(mpq_class, y_coord);
586   PPL_DIRTY_TEMP(mpq_class, x_div);
587   PPL_DIRTY_TEMP(mpq_class, y_div);
588   assign_r(x_div, x.divisor(), ROUND_NOT_NEEDED);
589   assign_r(y_div, y.divisor(), ROUND_NOT_NEEDED);
590 
591   assign_r(tmp0, 0, ROUND_NOT_NEEDED);
592   // TODO: This loop can be optimized more, if needed.
593   for (dimension_type i = x_space_dim; i-- > 0; ) {
594     assign_r(x_coord, x.coefficient(Variable(i)), ROUND_NOT_NEEDED);
595     div_assign_r(x_coord, x_coord, x_div, ROUND_NOT_NEEDED);
596     assign_r(y_coord, y.coefficient(Variable(i)), ROUND_NOT_NEEDED);
597     div_assign_r(y_coord, y_coord, y_div, ROUND_NOT_NEEDED);
598     const Temp* tmp1p;
599     const Temp* tmp2p;
600 
601     if (x_coord > y_coord) {
602       maybe_assign(tmp1p, tmp1, x_coord, dir);
603       maybe_assign(tmp2p, tmp2, y_coord, inverse(dir));
604     }
605     else {
606       maybe_assign(tmp1p, tmp1, y_coord, dir);
607       maybe_assign(tmp2p, tmp2, x_coord, inverse(dir));
608     }
609     sub_assign_r(tmp1, *tmp1p, *tmp2p, dir);
610     PPL_ASSERT(sgn(tmp1) >= 0);
611     Specialization::combine(tmp0, tmp1, dir);
612   }
613   Specialization::finalize(tmp0, dir);
614   assign_r(r, tmp0, dir);
615   return true;
616 }
617 
618 /*! \relates Generator */
619 template <typename Temp, typename To>
620 inline bool
rectilinear_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const Generator & x,const Generator & y,const Rounding_Dir dir,Temp & tmp0,Temp & tmp1,Temp & tmp2)621 rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
622                             const Generator& x,
623                             const Generator& y,
624                             const Rounding_Dir dir,
625                             Temp& tmp0,
626                             Temp& tmp1,
627                             Temp& tmp2) {
628   return l_m_distance_assign<Rectilinear_Distance_Specialization<Temp> >
629     (r, x, y, dir, tmp0, tmp1, tmp2);
630 }
631 
632 /*! \relates Generator */
633 template <typename Temp, typename To>
634 inline bool
rectilinear_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const Generator & x,const Generator & y,const Rounding_Dir dir)635 rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
636                             const Generator& x,
637                             const Generator& y,
638                             const Rounding_Dir dir) {
639   typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
640   PPL_DIRTY_TEMP(Checked_Temp, tmp0);
641   PPL_DIRTY_TEMP(Checked_Temp, tmp1);
642   PPL_DIRTY_TEMP(Checked_Temp, tmp2);
643   return rectilinear_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
644 }
645 
646 /*! \relates Generator */
647 template <typename To>
648 inline bool
rectilinear_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const Generator & x,const Generator & y,const Rounding_Dir dir)649 rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
650                             const Generator& x,
651                             const Generator& y,
652                             const Rounding_Dir dir) {
653   return rectilinear_distance_assign<To, To>(r, x, y, dir);
654 }
655 
656 /*! \relates Generator */
657 template <typename Temp, typename To>
658 inline bool
euclidean_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const Generator & x,const Generator & y,const Rounding_Dir dir,Temp & tmp0,Temp & tmp1,Temp & tmp2)659 euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
660                           const Generator& x,
661                           const Generator& y,
662                           const Rounding_Dir dir,
663                           Temp& tmp0,
664                           Temp& tmp1,
665                           Temp& tmp2) {
666   return l_m_distance_assign<Euclidean_Distance_Specialization<Temp> >
667     (r, x, y, dir, tmp0, tmp1, tmp2);
668 }
669 
670 /*! \relates Generator */
671 template <typename Temp, typename To>
672 inline bool
euclidean_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const Generator & x,const Generator & y,const Rounding_Dir dir)673 euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
674                           const Generator& x,
675                           const Generator& y,
676                           const Rounding_Dir dir) {
677   typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
678   PPL_DIRTY_TEMP(Checked_Temp, tmp0);
679   PPL_DIRTY_TEMP(Checked_Temp, tmp1);
680   PPL_DIRTY_TEMP(Checked_Temp, tmp2);
681   return euclidean_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
682 }
683 
684 /*! \relates Generator */
685 template <typename To>
686 inline bool
euclidean_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const Generator & x,const Generator & y,const Rounding_Dir dir)687 euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
688                           const Generator& x,
689                           const Generator& y,
690                           const Rounding_Dir dir) {
691   return euclidean_distance_assign<To, To>(r, x, y, dir);
692 }
693 
694 /*! \relates Generator */
695 template <typename Temp, typename To>
696 inline bool
l_infinity_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const Generator & x,const Generator & y,const Rounding_Dir dir,Temp & tmp0,Temp & tmp1,Temp & tmp2)697 l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
698                            const Generator& x,
699                            const Generator& y,
700                            const Rounding_Dir dir,
701                            Temp& tmp0,
702                            Temp& tmp1,
703                            Temp& tmp2) {
704   return l_m_distance_assign<L_Infinity_Distance_Specialization<Temp> >
705     (r, x, y, dir, tmp0, tmp1, tmp2);
706 }
707 
708 /*! \relates Generator */
709 template <typename Temp, typename To>
710 inline bool
l_infinity_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const Generator & x,const Generator & y,const Rounding_Dir dir)711 l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
712                            const Generator& x,
713                            const Generator& y,
714                            const Rounding_Dir dir) {
715   typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
716   PPL_DIRTY_TEMP(Checked_Temp, tmp0);
717   PPL_DIRTY_TEMP(Checked_Temp, tmp1);
718   PPL_DIRTY_TEMP(Checked_Temp, tmp2);
719   return l_infinity_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
720 }
721 
722 /*! \relates Generator */
723 template <typename To>
724 inline bool
l_infinity_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const Generator & x,const Generator & y,const Rounding_Dir dir)725 l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
726                            const Generator& x,
727                            const Generator& y,
728                            const Rounding_Dir dir) {
729   return l_infinity_distance_assign<To, To>(r, x, y, dir);
730 }
731 
732 /*! \relates Generator */
733 inline void
swap(Generator & x,Generator & y)734 swap(Generator& x, Generator& y) {
735   x.m_swap(y);
736 }
737 
738 } // namespace Parma_Polyhedra_Library
739 
740 #endif // !defined(PPL_Generator_inlines_hh)
741