1 /* Linear_Expression_Impl class implementation: non-inline template 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_Linear_Expression_Impl_templates_hh
25 #define PPL_Linear_Expression_Impl_templates_hh 1
26 
27 #include "Dense_Row_defs.hh"
28 #include "Sparse_Row_defs.hh"
29 
30 #include "Constraint_defs.hh"
31 #include "Generator_defs.hh"
32 #include "Grid_Generator_defs.hh"
33 #include "Congruence_defs.hh"
34 #include <stdexcept>
35 #include <iostream>
36 
37 namespace Parma_Polyhedra_Library {
38 
39 template <typename Row>
40 Linear_Expression_Impl<Row>
Linear_Expression_Impl(const Linear_Expression_Impl & e)41 ::Linear_Expression_Impl(const Linear_Expression_Impl& e) {
42   construct(e);
43 }
44 
45 template <typename Row>
46 template <typename Row2>
47 Linear_Expression_Impl<Row>
Linear_Expression_Impl(const Linear_Expression_Impl<Row2> & e)48 ::Linear_Expression_Impl(const Linear_Expression_Impl<Row2>& e) {
49   construct(e);
50 }
51 
52 template <typename Row>
53 Linear_Expression_Impl<Row>
Linear_Expression_Impl(const Linear_Expression_Interface & e)54 ::Linear_Expression_Impl(const Linear_Expression_Interface& e) {
55   typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
56   typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
57   if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&e)) {
58     construct(*p);
59   }
60   else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&e)) {
61     construct(*p);
62   }
63   else {
64     // Add implementations for other derived classes here.
65     PPL_UNREACHABLE;
66   }
67 }
68 
69 template <typename Row>
70 Linear_Expression_Impl<Row>
Linear_Expression_Impl(const Linear_Expression_Interface & e,dimension_type space_dim)71 ::Linear_Expression_Impl(const Linear_Expression_Interface& e,
72                          dimension_type space_dim) {
73   typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
74   typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
75   if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&e)) {
76     construct(*p, space_dim);
77   }
78   else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&e)) {
79     construct(*p, space_dim);
80   }
81   else {
82     // Add implementations for other derived classes here.
83     PPL_UNREACHABLE;
84   }
85 }
86 
87 template <typename Row>
88 template <typename Row2>
89 void
90 Linear_Expression_Impl<Row>
linear_combine(const Linear_Expression_Impl<Row2> & y,Variable i)91 ::linear_combine(const Linear_Expression_Impl<Row2>& y, Variable i) {
92   PPL_ASSERT(space_dimension() == y.space_dimension());
93   PPL_ASSERT(i.space_dimension() <= space_dimension());
94   linear_combine(y, i.space_dimension());
95 }
96 
97 template <typename Row>
98 template <typename Row2>
99 void
100 Linear_Expression_Impl<Row>
linear_combine(const Linear_Expression_Impl<Row2> & y,dimension_type i)101 ::linear_combine(const Linear_Expression_Impl<Row2>& y, dimension_type i) {
102   const Linear_Expression_Impl& x = *this;
103   PPL_ASSERT(i < x.space_dimension() + 1);
104   PPL_ASSERT(x.space_dimension() == y.space_dimension());
105   Coefficient_traits::const_reference x_i = x.row.get(i);
106   Coefficient_traits::const_reference y_i = y.row.get(i);
107   PPL_ASSERT(x_i != 0);
108   PPL_ASSERT(y_i != 0);
109   PPL_DIRTY_TEMP_COEFFICIENT(normalized_x_v);
110   PPL_DIRTY_TEMP_COEFFICIENT(normalized_y_v);
111   normalize2(x_i, y_i, normalized_x_v, normalized_y_v);
112   neg_assign(normalized_x_v);
113   linear_combine(y, normalized_y_v, normalized_x_v);
114   // We cannot use x_i here because it may have been invalidated by
115   // linear_combine().
116   assert(x.row.get(i) == 0);
117   PPL_ASSERT(OK());
118 }
119 
120 template <typename Row>
121 template <typename Row2>
122 void
123 Linear_Expression_Impl<Row>
linear_combine(const Linear_Expression_Impl<Row2> & y,Coefficient_traits::const_reference c1,Coefficient_traits::const_reference c2)124 ::linear_combine(const Linear_Expression_Impl<Row2>& y,
125                  Coefficient_traits::const_reference c1,
126                  Coefficient_traits::const_reference c2) {
127   PPL_ASSERT(c1 != 0);
128   PPL_ASSERT(c2 != 0);
129   if (space_dimension() < y.space_dimension()) {
130     set_space_dimension(y.space_dimension());
131   }
132   linear_combine(y, c1, c2, 0, y.space_dimension() + 1);
133   PPL_ASSERT(OK());
134 }
135 
136 template <typename Row>
137 template <typename Row2>
138 void
139 Linear_Expression_Impl<Row>
linear_combine_lax(const Linear_Expression_Impl<Row2> & y,Coefficient_traits::const_reference c1,Coefficient_traits::const_reference c2)140 ::linear_combine_lax(const Linear_Expression_Impl<Row2>& y,
141                      Coefficient_traits::const_reference c1,
142                      Coefficient_traits::const_reference c2) {
143   if (space_dimension() < y.space_dimension()) {
144     set_space_dimension(y.space_dimension());
145   }
146   linear_combine_lax(y, c1, c2, 0, y.space_dimension() + 1);
147   PPL_ASSERT(OK());
148 }
149 
150 template <typename Row>
151 template <typename Row2>
152 int
153 Linear_Expression_Impl<Row>
compare(const Linear_Expression_Impl<Row2> & y) const154 ::compare(const Linear_Expression_Impl<Row2>& y) const {
155   const Linear_Expression_Impl& x = *this;
156   // Compare all the coefficients of the row starting from position 1.
157   // NOTE: x and y may be of different size.
158   typename Row::const_iterator i = x.row.lower_bound(1);
159   typename Row::const_iterator i_end = x.row.end();
160   typename Row2::const_iterator j = y.row.lower_bound(1);
161   typename Row2::const_iterator j_end = y.row.end();
162   while (i != i_end && j != j_end) {
163     if (i.index() < j.index()) {
164       const int s = sgn(*i);
165       if (s != 0) {
166         return 2*s;
167       }
168       ++i;
169       continue;
170     }
171     if (i.index() > j.index()) {
172       const int s = sgn(*j);
173       if (s != 0) {
174         return -2*s;
175       }
176       ++j;
177       continue;
178     }
179     PPL_ASSERT(i.index() == j.index());
180     const int s = cmp(*i, *j);
181     if (s < 0) {
182       return -2;
183     }
184     if (s > 0) {
185       return 2;
186     }
187     PPL_ASSERT(s == 0);
188     ++i;
189     ++j;
190   }
191   for ( ; i != i_end; ++i) {
192     const int s = sgn(*i);
193     if (s != 0) {
194       return 2*s;
195     }
196   }
197   for ( ; j != j_end; ++j) {
198     const int s = sgn(*j);
199     if (s != 0) {
200       return -2*s;
201     }
202   }
203 
204   // If all the coefficients in `x' equal all the coefficients in `y'
205   // (starting from position 1) we compare coefficients in position 0,
206   // i.e., inhomogeneous terms.
207   const int comp = cmp(x.row.get(0), y.row.get(0));
208   if (comp > 0) {
209     return 1;
210   }
211   if (comp < 0) {
212     return -1;
213   }
214   PPL_ASSERT(comp == 0);
215 
216   // `x' and `y' are equal.
217   return 0;
218 }
219 
220 template <typename Row>
Linear_Expression_Impl(const Variable v)221 Linear_Expression_Impl<Row>::Linear_Expression_Impl(const Variable v) {
222   if (v.space_dimension() > max_space_dimension()) {
223     throw std::length_error("Linear_Expression_Impl::"
224                             "Linear_Expression_Impl(v):\n"
225                             "v exceeds the maximum allowed "
226                             "space dimension.");
227   }
228   set_space_dimension(v.space_dimension());
229   (*this) += v;
230   PPL_ASSERT(OK());
231 }
232 
233 template <typename Row>
234 template <typename Row2>
235 bool
236 Linear_Expression_Impl<Row>
is_equal_to(const Linear_Expression_Impl<Row2> & x) const237 ::is_equal_to(const Linear_Expression_Impl<Row2>& x) const {
238   return row == x.row;
239 }
240 
241 template <typename Row>
242 void
get_row(Dense_Row & r) const243 Linear_Expression_Impl<Row>::get_row(Dense_Row& r) const {
244   r = this->row;
245 }
246 
247 template <typename Row>
248 void
get_row(Sparse_Row & r) const249 Linear_Expression_Impl<Row>::get_row(Sparse_Row& r) const {
250   r = this->row;
251 }
252 
253 template <typename Row>
254 void
255 Linear_Expression_Impl<Row>
permute_space_dimensions(const std::vector<Variable> & cycle)256 ::permute_space_dimensions(const std::vector<Variable>& cycle) {
257   const dimension_type n = cycle.size();
258   if (n < 2) {
259     return;
260   }
261 
262   if (n == 2) {
263     row.swap_coefficients(cycle[0].space_dimension(),
264                           cycle[1].space_dimension());
265   }
266   else {
267     PPL_DIRTY_TEMP_COEFFICIENT(tmp);
268     tmp = row.get(cycle.back().space_dimension());
269     for (dimension_type i = n - 1; i-- > 0; ) {
270       row.swap_coefficients(cycle[i + 1].space_dimension(),
271                             cycle[i].space_dimension());
272     }
273     if (tmp == 0) {
274       row.reset(cycle[0].space_dimension());
275     }
276     else {
277       using std::swap;
278       swap(tmp, row[cycle[0].space_dimension()]);
279     }
280   }
281   PPL_ASSERT(OK());
282 }
283 
284 template <typename Row>
285 template <typename Row2>
286 Linear_Expression_Impl<Row>&
operator +=(const Linear_Expression_Impl<Row2> & e)287 Linear_Expression_Impl<Row>::operator+=(const Linear_Expression_Impl<Row2>& e) {
288   linear_combine(e, Coefficient_one(), Coefficient_one());
289   return *this;
290 }
291 
292 /*! \relates Parma_Polyhedra_Library::Linear_Expression_Impl */
293 template <typename Row>
294 Linear_Expression_Impl<Row>&
operator +=(const Variable v)295 Linear_Expression_Impl<Row>::operator+=(const Variable v) {
296   const dimension_type v_space_dim = v.space_dimension();
297   if (v_space_dim > Linear_Expression_Impl<Row>::max_space_dimension()) {
298     throw std::length_error("Linear_Expression_Impl& "
299                             "operator+=(e, v):\n"
300                             "v exceeds the maximum allowed space dimension.");
301   }
302   if (space_dimension() < v_space_dim) {
303     set_space_dimension(v_space_dim);
304   }
305   typename Row::iterator itr = row.insert(v_space_dim);
306   ++(*itr);
307   if (*itr == 0) {
308     row.reset(itr);
309   }
310   PPL_ASSERT(OK());
311   return *this;
312 }
313 
314 /*! \relates Parma_Polyhedra_Library::Linear_Expression_Impl */
315 template <typename Row>
316 template <typename Row2>
317 Linear_Expression_Impl<Row>&
operator -=(const Linear_Expression_Impl<Row2> & e2)318 Linear_Expression_Impl<Row>::operator-=(const Linear_Expression_Impl<Row2>& e2) {
319   linear_combine(e2, Coefficient_one(), -1);
320   return *this;
321 }
322 
323 /*! \relates Parma_Polyhedra_Library::Linear_Expression_Impl */
324 template <typename Row>
325 Linear_Expression_Impl<Row>&
operator -=(const Variable v)326 Linear_Expression_Impl<Row>::operator-=(const Variable v) {
327   const dimension_type v_space_dim = v.space_dimension();
328   if (v_space_dim > Linear_Expression_Impl<Row>::max_space_dimension()) {
329     throw std::length_error("Linear_Expression_Impl& "
330                             "operator-=(e, v):\n"
331                             "v exceeds the maximum allowed space dimension.");
332   }
333   if (space_dimension() < v_space_dim) {
334     set_space_dimension(v_space_dim);
335   }
336   typename Row::iterator itr = row.insert(v_space_dim);
337   --(*itr);
338   if (*itr == 0) {
339     row.reset(itr);
340   }
341   PPL_ASSERT(OK());
342   return *this;
343 }
344 
345 /*! \relates Parma_Polyhedra_Library::Linear_Expression_Impl */
346 template <typename Row>
347 Linear_Expression_Impl<Row>&
operator *=(Coefficient_traits::const_reference n)348 Linear_Expression_Impl<Row>::operator*=(Coefficient_traits::const_reference n) {
349   if (n == 0) {
350     row.clear();
351     PPL_ASSERT(OK());
352     return *this;
353   }
354   for (typename Row::iterator i = row.begin(),
355          i_end = row.end(); i != i_end; ++i) {
356     (*i) *= n;
357   }
358   PPL_ASSERT(OK());
359   return *this;
360 }
361 
362 /*! \relates Parma_Polyhedra_Library::Linear_Expression_Impl */
363 template <typename Row>
364 Linear_Expression_Impl<Row>&
operator /=(Coefficient_traits::const_reference n)365 Linear_Expression_Impl<Row>::operator/=(Coefficient_traits::const_reference n) {
366   typename Row::iterator i = row.begin();
367   const typename Row::iterator& i_end = row.end();
368   while (i != i_end) {
369     (*i) /= n;
370     if (*i == 0) {
371       i = row.reset(i);
372     }
373     else {
374       ++i;
375     }
376   }
377   PPL_ASSERT(OK());
378   return *this;
379 }
380 
381 /*! \relates Parma_Polyhedra_Library::Linear_Expression_Impl */
382 template <typename Row>
383 void
negate()384 Linear_Expression_Impl<Row>::negate() {
385   for (typename Row::iterator i = row.begin(),
386          i_end = row.end(); i != i_end; ++i) {
387     neg_assign(*i);
388   }
389   PPL_ASSERT(OK());
390 }
391 
392 /*! \relates Parma_Polyhedra_Library::Linear_Expression_Impl */
393 template <typename Row>
394 Linear_Expression_Impl<Row>&
add_mul_assign(Coefficient_traits::const_reference n,const Variable v)395 Linear_Expression_Impl<Row>::add_mul_assign(Coefficient_traits::const_reference n,
396                                             const Variable v) {
397   const dimension_type v_space_dim = v.space_dimension();
398   if (v_space_dim > Linear_Expression_Impl<Row>::max_space_dimension()) {
399     throw std::length_error("Linear_Expression_Impl& "
400                             "add_mul_assign(e, n, v):\n"
401                             "v exceeds the maximum allowed space dimension.");
402   }
403   if (space_dimension() < v_space_dim) {
404     set_space_dimension(v_space_dim);
405   }
406   if (n == 0) {
407     return *this;
408   }
409   typename Row::iterator itr = row.insert(v_space_dim);
410   (*itr) += n;
411   if (*itr == 0) {
412     row.reset(itr);
413   }
414   PPL_ASSERT(OK());
415   return *this;
416 }
417 
418 /*! \relates Parma_Polyhedra_Library::Linear_Expression_Impl */
419 template <typename Row>
420 Linear_Expression_Impl<Row>&
421 Linear_Expression_Impl<Row>
sub_mul_assign(Coefficient_traits::const_reference n,const Variable v)422 ::sub_mul_assign(Coefficient_traits::const_reference n,
423                  const Variable v) {
424   const dimension_type v_space_dim = v.space_dimension();
425   if (v_space_dim > Linear_Expression_Impl<Row>::max_space_dimension()) {
426     throw std::length_error("Linear_Expression_Impl& "
427                             "sub_mul_assign(e, n, v):\n"
428                             "v exceeds the maximum allowed space dimension.");
429   }
430   if (space_dimension() < v_space_dim) {
431     set_space_dimension(v_space_dim);
432   }
433   if (n == 0) {
434     return *this;
435   }
436   typename Row::iterator itr = row.insert(v_space_dim);
437   (*itr) -= n;
438   if (*itr == 0) {
439     row.reset(itr);
440   }
441   PPL_ASSERT(OK());
442   return *this;
443 }
444 
445 template <typename Row>
446 template <typename Row2>
447 void
448 Linear_Expression_Impl<Row>
add_mul_assign(Coefficient_traits::const_reference factor,const Linear_Expression_Impl<Row2> & y)449 ::add_mul_assign(Coefficient_traits::const_reference factor,
450                  const Linear_Expression_Impl<Row2>& y) {
451   if (factor != 0) {
452     linear_combine(y, Coefficient_one(), factor);
453   }
454 }
455 
456 template <typename Row>
457 template <typename Row2>
458 void
459 Linear_Expression_Impl<Row>
sub_mul_assign(Coefficient_traits::const_reference factor,const Linear_Expression_Impl<Row2> & y)460 ::sub_mul_assign(Coefficient_traits::const_reference factor,
461                  const Linear_Expression_Impl<Row2>& y) {
462   if (factor != 0) {
463     linear_combine(y, Coefficient_one(), -factor);
464   }
465 }
466 
467 template <typename Row>
468 void
print(std::ostream & s) const469 Linear_Expression_Impl<Row>::print(std::ostream& s) const {
470   PPL_DIRTY_TEMP_COEFFICIENT(ev);
471   bool first = true;
472   for (typename Row::const_iterator i = row.lower_bound(1), i_end = row.end();
473        i != i_end; ++i) {
474     ev = *i;
475     if (ev == 0) {
476       continue;
477     }
478     if (!first) {
479       if (ev > 0) {
480         s << " + ";
481       }
482       else {
483         s << " - ";
484         neg_assign(ev);
485       }
486     }
487     else {
488       first = false;
489     }
490     if (ev == -1) {
491       s << "-";
492     }
493     else if (ev != 1) {
494       s << ev << "*";
495     }
496     IO_Operators::operator<<(s, Variable(i.index() - 1));
497   }
498   // Inhomogeneous term.
499   PPL_DIRTY_TEMP_COEFFICIENT(it);
500   it = row[0];
501   if (it != 0) {
502     if (!first) {
503       if (it > 0) {
504         s << " + ";
505       }
506       else {
507         s << " - ";
508         neg_assign(it);
509       }
510     }
511     else {
512       first = false;
513     }
514     s << it;
515   }
516 
517   if (first) {
518     // The null linear expression.
519     s << Coefficient_zero();
520   }
521 }
522 
523 template <typename Row>
524 Coefficient_traits::const_reference
get(dimension_type i) const525 Linear_Expression_Impl<Row>::get(dimension_type i) const {
526   return row.get(i);
527 }
528 
529 template <typename Row>
530 void
531 Linear_Expression_Impl<Row>
set(dimension_type i,Coefficient_traits::const_reference n)532 ::set(dimension_type i, Coefficient_traits::const_reference n) {
533   if (n == 0) {
534     row.reset(i);
535   }
536   else {
537     row.insert(i, n);
538   }
539   PPL_ASSERT(OK());
540 }
541 
542 template <typename Row>
543 void
544 Linear_Expression_Impl<Row>
exact_div_assign(Coefficient_traits::const_reference c,dimension_type start,dimension_type end)545 ::exact_div_assign(Coefficient_traits::const_reference c,
546                    dimension_type start, dimension_type end) {
547   // NOTE: Since all coefficients in [start,end) are multiple of c,
548   // each of the resulting coefficients will be nonzero iff the initial
549   // coefficient was.
550   for (typename Row::iterator i = row.lower_bound(start),
551          i_end = row.lower_bound(end); i != i_end; ++i) {
552     Parma_Polyhedra_Library::exact_div_assign(*i, *i, c);
553   }
554   PPL_ASSERT(OK());
555 }
556 
557 template <typename Row>
558 void
559 Linear_Expression_Impl<Row>
mul_assign(Coefficient_traits::const_reference c,dimension_type start,dimension_type end)560 ::mul_assign(Coefficient_traits::const_reference c,
561                    dimension_type start, dimension_type end) {
562   if (c == 0) {
563     typename Row::iterator i = row.lower_bound(start);
564     const typename Row::iterator& i_end = row.end();
565     while (i != i_end && i.index() < end) {
566       i = row.reset(i);
567     }
568   }
569   else {
570     for (typename Row::iterator
571       i = row.lower_bound(start), i_end = row.lower_bound(end);
572       i != i_end; ++i) {
573       (*i) *= c;
574     }
575   }
576   PPL_ASSERT(OK());
577 }
578 
579 template <typename Row>
580 template <typename Row2>
581 void
582 Linear_Expression_Impl<Row>
linear_combine(const Linear_Expression_Impl<Row2> & y,Coefficient_traits::const_reference c1,Coefficient_traits::const_reference c2,dimension_type start,dimension_type end)583 ::linear_combine(const Linear_Expression_Impl<Row2>& y,
584                  Coefficient_traits::const_reference c1,
585                  Coefficient_traits::const_reference c2,
586                  dimension_type start, dimension_type end) {
587   Parma_Polyhedra_Library::linear_combine(row, y.row, c1, c2, start, end);
588   PPL_ASSERT(OK());
589 }
590 
591 template <typename Row>
592 template <typename Row2>
593 void
594 Linear_Expression_Impl<Row>
linear_combine_lax(const Linear_Expression_Impl<Row2> & y,Coefficient_traits::const_reference c1,Coefficient_traits::const_reference c2,dimension_type start,dimension_type end)595 ::linear_combine_lax(const Linear_Expression_Impl<Row2>& y,
596                      Coefficient_traits::const_reference c1,
597                      Coefficient_traits::const_reference c2,
598                      dimension_type start, dimension_type end) {
599   PPL_ASSERT(start <= end);
600   PPL_ASSERT(end <= row.size());
601   PPL_ASSERT(end <= y.row.size());
602   if (c1 == 0) {
603     if (c2 == 0) {
604       PPL_ASSERT(c1 == 0);
605       PPL_ASSERT(c2 == 0);
606       typename Row::iterator i = row.lower_bound(start);
607       const typename Row::iterator& i_end = row.end();
608       while (i != i_end && i.index() < end) {
609         i = row.reset(i);
610       }
611     }
612     else {
613       PPL_ASSERT(c1 == 0);
614       PPL_ASSERT(c2 != 0);
615 
616       typename Row::iterator i = row.lower_bound(start);
617       const typename Row::iterator& i_end = row.end();
618       typename Row2::const_iterator j = y.row.lower_bound(start);
619       typename Row2::const_iterator j_last = y.row.lower_bound(end);
620 
621       while (i != i_end && i.index() < end && j != j_last) {
622         if (i.index() < j.index()) {
623           i = row.reset(i);
624           continue;
625         }
626         if (i.index() > j.index()) {
627           i = row.insert(i, j.index(), *j);
628           (*i) *= c2;
629           ++i;
630           ++j;
631           continue;
632         }
633         PPL_ASSERT(i.index() == j.index());
634         (*i) = (*j);
635         (*i) *= c2;
636         ++i;
637         ++j;
638       }
639       while (i != i_end && i.index() < end) {
640         i = row.reset(i);
641       }
642       while (j != j_last) {
643         i = row.insert(i, j.index(), *j);
644         (*i) *= c2;
645         // No need to increment i here.
646         ++j;
647       }
648     }
649   }
650   else {
651     if (c2 == 0) {
652       PPL_ASSERT(c1 != 0);
653       PPL_ASSERT(c2 == 0);
654       for (typename Row::iterator i = row.lower_bound(start),
655              i_end = row.lower_bound(end); i != i_end; ++i) {
656         (*i) *= c1;
657       }
658     }
659     else {
660       PPL_ASSERT(c1 != 0);
661       PPL_ASSERT(c2 != 0);
662       Parma_Polyhedra_Library::linear_combine(row, y.row, c1, c2, start, end);
663     }
664   }
665   PPL_ASSERT(OK());
666 }
667 
668 template <typename Row>
669 void
sign_normalize()670 Linear_Expression_Impl<Row>::sign_normalize() {
671   typename Row::iterator i = row.lower_bound(1);
672   typename Row::iterator i_end = row.end();
673 
674   for ( ; i != i_end; ++i) {
675     if (*i != 0) {
676       break;
677     }
678   }
679 
680   if (i != i_end && *i < 0) {
681     for ( ; i != i_end; ++i) {
682       neg_assign(*i);
683     }
684     // Negate the first coefficient, too.
685     typename Row::iterator first = row.begin();
686     if (first != row.end() && first.index() == 0) {
687       neg_assign(*first);
688     }
689   }
690   PPL_ASSERT(OK());
691 }
692 
693 template <typename Row>
694 void
negate(dimension_type first,dimension_type last)695 Linear_Expression_Impl<Row>::negate(dimension_type first, dimension_type last) {
696   PPL_ASSERT(first <= last);
697   PPL_ASSERT(last <= row.size());
698   typename Row::iterator i = row.lower_bound(first);
699   typename Row::iterator i_end = row.lower_bound(last);
700   for ( ; i != i_end; ++i) {
701     neg_assign(*i);
702   }
703   PPL_ASSERT(OK());
704 }
705 
706 template <typename Row>
707 template <typename Row2>
708 void
construct(const Linear_Expression_Impl<Row2> & e)709 Linear_Expression_Impl<Row>::construct(const Linear_Expression_Impl<Row2>& e) {
710   row = e.row;
711   PPL_ASSERT(OK());
712 }
713 
714 template <typename Row>
715 template <typename Row2>
716 void
construct(const Linear_Expression_Impl<Row2> & e,dimension_type space_dim)717 Linear_Expression_Impl<Row>::construct(const Linear_Expression_Impl<Row2>& e,
718                                        dimension_type space_dim) {
719   Row x(e.row, space_dim + 1, space_dim + 1);
720   swap(row, x);
721   PPL_ASSERT(OK());
722 }
723 
724 template <typename Row>
725 template <typename Row2>
726 void
727 Linear_Expression_Impl<Row>
scalar_product_assign(Coefficient & result,const Linear_Expression_Impl<Row2> & y,dimension_type start,dimension_type end) const728 ::scalar_product_assign(Coefficient& result,
729                         const Linear_Expression_Impl<Row2>& y,
730                         dimension_type start, dimension_type end) const {
731   const Linear_Expression_Impl<Row>& x = *this;
732   PPL_ASSERT(start <= end);
733   PPL_ASSERT(end <= x.row.size());
734   PPL_ASSERT(end <= y.row.size());
735   result = 0;
736   typename Row ::const_iterator x_i = x.row.lower_bound(start);
737   typename Row ::const_iterator x_end = x.row.lower_bound(end);
738   typename Row2::const_iterator y_i = y.row.lower_bound(start);
739   typename Row2::const_iterator y_end = y.row.lower_bound(end);
740   while (x_i != x_end && y_i != y_end) {
741     if (x_i.index() == y_i.index()) {
742       Parma_Polyhedra_Library::add_mul_assign(result, *x_i, *y_i);
743       ++x_i;
744       ++y_i;
745     }
746     else {
747       if (x_i.index() < y_i.index()) {
748         PPL_ASSERT(y.row.get(x_i.index()) == 0);
749         // (*x_i) * 0 == 0, nothing to do.
750         ++x_i;
751       }
752       else {
753         PPL_ASSERT(x.row.get(y_i.index()) == 0);
754         // 0 * (*y_i) == 0, nothing to do.
755         ++y_i;
756       }
757     }
758   }
759   // In the remaining positions (if any) at most one row is nonzero, so
760   // there's nothing left to do.
761 }
762 
763 template <typename Row>
764 template <typename Row2>
765 int
766 Linear_Expression_Impl<Row>
scalar_product_sign(const Linear_Expression_Impl<Row2> & y,dimension_type start,dimension_type end) const767 ::scalar_product_sign(const Linear_Expression_Impl<Row2>& y,
768                       dimension_type start, dimension_type end) const {
769   PPL_DIRTY_TEMP_COEFFICIENT(result);
770   scalar_product_assign(result, y, start, end);
771   return sgn(result);
772 }
773 
774 template <typename Row>
775 template <typename Row2>
776 bool
777 Linear_Expression_Impl<Row>
is_equal_to(const Linear_Expression_Impl<Row2> & y,dimension_type start,dimension_type end) const778 ::is_equal_to(const Linear_Expression_Impl<Row2>& y,
779               dimension_type start, dimension_type end) const {
780   const Linear_Expression_Impl<Row>& x = *this;
781   PPL_ASSERT(start <= end);
782   PPL_ASSERT(end <= x.row.size());
783   PPL_ASSERT(end <= y.row.size());
784 
785   typename Row::const_iterator i = x.row.lower_bound(start);
786   typename Row::const_iterator i_end = x.row.lower_bound(end);
787   typename Row2::const_iterator j = y.row.lower_bound(start);
788   typename Row2::const_iterator j_end = y.row.lower_bound(end);
789   while (i != i_end && j != j_end) {
790     if (i.index() == j.index()) {
791       if (*i != *j) {
792         return false;
793       }
794       ++i;
795       ++j;
796     }
797     else {
798       if (i.index() < j.index()) {
799         if (*i != 0) {
800           return false;
801         }
802         ++i;
803       }
804       else {
805         PPL_ASSERT(i.index() > j.index());
806         if (*j != 0) {
807           return false;
808         }
809         ++j;
810       }
811     }
812   }
813   for ( ; i != i_end; ++i) {
814     if (*i != 0) {
815       return false;
816     }
817   }
818   for ( ; j != j_end; ++j) {
819     if (*j != 0) {
820       return false;
821     }
822   }
823   return true;
824 }
825 
826 template <typename Row>
827 template <typename Row2>
828 bool
829 Linear_Expression_Impl<Row>
is_equal_to(const Linear_Expression_Impl<Row2> & y,Coefficient_traits::const_reference c1,Coefficient_traits::const_reference c2,dimension_type start,dimension_type end) const830 ::is_equal_to(const Linear_Expression_Impl<Row2>& y,
831               Coefficient_traits::const_reference c1,
832               Coefficient_traits::const_reference c2,
833               dimension_type start, dimension_type end) const {
834   const Linear_Expression_Impl<Row>& x = *this;
835   PPL_ASSERT(start <= end);
836   PPL_ASSERT(end <= x.row.size());
837   PPL_ASSERT(end <= y.row.size());
838 
839   // Deal with trivial cases.
840   if (c1 == 0) {
841     if (c2 == 0) {
842       return true;
843     }
844     else {
845       return y.all_zeroes(start, end);
846     }
847   }
848   if (c2 == 0) {
849     return x.all_zeroes(start, end);
850   }
851 
852   PPL_ASSERT(c1 != 0);
853   PPL_ASSERT(c2 != 0);
854   typename Row::const_iterator i = x.row.lower_bound(start);
855   typename Row::const_iterator i_end = x.row.lower_bound(end);
856   typename Row2::const_iterator j = y.row.lower_bound(start);
857   typename Row2::const_iterator j_end = y.row.lower_bound(end);
858   while (i != i_end && j != j_end) {
859     if (i.index() == j.index()) {
860       if ((*i) * c1 != (*j) * c2) {
861         return false;
862       }
863       ++i;
864       ++j;
865     }
866     else {
867       if (i.index() < j.index()) {
868         if (*i != 0) {
869           return false;
870         }
871         ++i;
872       }
873       else {
874         PPL_ASSERT(i.index() > j.index());
875         if (*j != 0) {
876           return false;
877         }
878         ++j;
879       }
880     }
881   }
882   for ( ; i != i_end; ++i) {
883     if (*i != 0) {
884       return false;
885     }
886   }
887   for ( ; j != j_end; ++j) {
888     if (*j != 0) {
889       return false;
890     }
891   }
892   return true;
893 }
894 
895 template <typename Row>
896 void
897 Linear_Expression_Impl<Row>
linear_combine(const Linear_Expression_Interface & y,Variable v)898 ::linear_combine(const Linear_Expression_Interface& y, Variable v) {
899   typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
900   typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
901   if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
902     linear_combine(*p, v);
903   }
904   else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
905     linear_combine(*p, v);
906   }
907   else {
908     // Add implementations for new derived classes here.
909     PPL_UNREACHABLE;
910   }
911 }
912 
913 template <typename Row>
914 void
915 Linear_Expression_Impl<Row>
linear_combine(const Linear_Expression_Interface & y,Coefficient_traits::const_reference c1,Coefficient_traits::const_reference c2)916 ::linear_combine(const Linear_Expression_Interface& y,
917                  Coefficient_traits::const_reference c1,
918                  Coefficient_traits::const_reference c2) {
919   typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
920   typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
921   if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
922     linear_combine(*p, c1, c2);
923   }
924   else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
925     linear_combine(*p, c1, c2);
926   }
927   else {
928     // Add implementations for new derived classes here.
929     PPL_UNREACHABLE;
930   }
931 }
932 
933 template <typename Row>
934 void
935 Linear_Expression_Impl<Row>
linear_combine_lax(const Linear_Expression_Interface & y,Coefficient_traits::const_reference c1,Coefficient_traits::const_reference c2)936 ::linear_combine_lax(const Linear_Expression_Interface& y,
937                      Coefficient_traits::const_reference c1,
938                      Coefficient_traits::const_reference c2) {
939   typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
940   typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
941   if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
942     linear_combine_lax(*p, c1, c2);
943   }
944   else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
945     linear_combine_lax(*p, c1, c2);
946   }
947   else {
948     // Add implementations for new derived classes here.
949     PPL_UNREACHABLE;
950   }
951 }
952 
953 template <typename Row>
954 bool
955 Linear_Expression_Impl<Row>
is_equal_to(const Linear_Expression_Interface & y) const956 ::is_equal_to(const Linear_Expression_Interface& y) const {
957   typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
958   typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
959   if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
960     return is_equal_to(*p);
961   }
962   else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
963     return is_equal_to(*p);
964   }
965   else {
966     // Add implementations for new derived classes here.
967     PPL_UNREACHABLE;
968     return false;
969   }
970 }
971 
972 template <typename Row>
973 Linear_Expression_Impl<Row>&
974 Linear_Expression_Impl<Row>
operator +=(const Linear_Expression_Interface & y)975 ::operator+=(const Linear_Expression_Interface& y) {
976   typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
977   typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
978   if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
979     return operator+=(*p);
980   }
981   else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
982     return operator+=(*p);
983   }
984   else {
985     // Add implementations for new derived classes here.
986     PPL_UNREACHABLE;
987     return *this;
988   }
989 }
990 
991 template <typename Row>
992 Linear_Expression_Impl<Row>&
993 Linear_Expression_Impl<Row>
operator -=(const Linear_Expression_Interface & y)994 ::operator-=(const Linear_Expression_Interface& y) {
995   typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
996   typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
997   if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
998     return operator-=(*p);
999   }
1000   else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
1001     return operator-=(*p);
1002   }
1003   else {
1004     // Add implementations for new derived classes here.
1005     PPL_UNREACHABLE;
1006     return *this;
1007   }
1008 }
1009 
1010 template <typename Row>
1011 void
1012 Linear_Expression_Impl<Row>
add_mul_assign(Coefficient_traits::const_reference factor,const Linear_Expression_Interface & y)1013 ::add_mul_assign(Coefficient_traits::const_reference factor,
1014                  const Linear_Expression_Interface& y) {
1015   typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
1016   typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
1017   if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
1018     add_mul_assign(factor, *p);
1019   }
1020   else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
1021     add_mul_assign(factor, *p);
1022   }
1023   else {
1024     // Add implementations for new derived classes here.
1025     PPL_UNREACHABLE;
1026   }
1027 }
1028 
1029 template <typename Row>
1030 void
1031 Linear_Expression_Impl<Row>
sub_mul_assign(Coefficient_traits::const_reference factor,const Linear_Expression_Interface & y)1032 ::sub_mul_assign(Coefficient_traits::const_reference factor,
1033                  const Linear_Expression_Interface& y) {
1034   typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
1035   typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
1036   if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
1037     sub_mul_assign(factor, *p);
1038   }
1039   else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
1040     sub_mul_assign(factor, *p);
1041   }
1042   else {
1043     // Add implementations for new derived classes here.
1044     PPL_UNREACHABLE;
1045   }
1046 }
1047 
1048 template <typename Row>
1049 void
1050 Linear_Expression_Impl<Row>
linear_combine(const Linear_Expression_Interface & y,dimension_type i)1051 ::linear_combine(const Linear_Expression_Interface& y, dimension_type i) {
1052   typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
1053   typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
1054   if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
1055     linear_combine(*p, i);
1056   }
1057   else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
1058     linear_combine(*p, i);
1059   }
1060   else {
1061     // Add implementations for new derived classes here.
1062     PPL_UNREACHABLE;
1063   }
1064 }
1065 
1066 template <typename Row>
1067 void
1068 Linear_Expression_Impl<Row>
linear_combine(const Linear_Expression_Interface & y,Coefficient_traits::const_reference c1,Coefficient_traits::const_reference c2,dimension_type start,dimension_type end)1069 ::linear_combine(const Linear_Expression_Interface& y,
1070                  Coefficient_traits::const_reference c1,
1071                  Coefficient_traits::const_reference c2,
1072                  dimension_type start, dimension_type end) {
1073   typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
1074   typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
1075   if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
1076     linear_combine(*p, c1, c2, start, end);
1077   }
1078   else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
1079     linear_combine(*p, c1, c2, start, end);
1080   }
1081   else {
1082     // Add implementations for new derived classes here.
1083     PPL_UNREACHABLE;
1084   }
1085 }
1086 
1087 template <typename Row>
1088 void
1089 Linear_Expression_Impl<Row>
linear_combine_lax(const Linear_Expression_Interface & y,Coefficient_traits::const_reference c1,Coefficient_traits::const_reference c2,dimension_type start,dimension_type end)1090 ::linear_combine_lax(const Linear_Expression_Interface& y,
1091                      Coefficient_traits::const_reference c1,
1092                      Coefficient_traits::const_reference c2,
1093                      dimension_type start, dimension_type end) {
1094   typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
1095   typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
1096   if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
1097     linear_combine_lax(*p, c1, c2, start, end);
1098   }
1099   else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
1100     linear_combine_lax(*p, c1, c2, start, end);
1101   }
1102   else {
1103     // Add implementations for new derived classes here.
1104     PPL_UNREACHABLE;
1105   }
1106 }
1107 
1108 template <typename Row>
1109 int
1110 Linear_Expression_Impl<Row>
compare(const Linear_Expression_Interface & y) const1111 ::compare(const Linear_Expression_Interface& y) const {
1112   typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
1113   typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
1114   if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
1115     return compare(*p);
1116   }
1117   else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
1118     return compare(*p);
1119   }
1120   else {
1121     // Add implementations for new derived classes here.
1122     PPL_UNREACHABLE;
1123     return 0;
1124   }
1125 }
1126 
1127 
1128 template <typename Row>
1129 void
construct(const Linear_Expression_Interface & y)1130 Linear_Expression_Impl<Row>::construct(const Linear_Expression_Interface& y) {
1131   typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
1132   typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
1133   if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
1134     return construct(*p);
1135   }
1136   else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
1137     return construct(*p);
1138   }
1139   else {
1140     // Add implementations for new derived classes here.
1141     PPL_UNREACHABLE;
1142   }
1143 }
1144 
1145 template <typename Row>
1146 void
construct(const Linear_Expression_Interface & y,dimension_type space_dim)1147 Linear_Expression_Impl<Row>::construct(const Linear_Expression_Interface& y,
1148                                        dimension_type space_dim) {
1149   typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
1150   typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
1151   if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
1152     return construct(*p, space_dim);
1153   }
1154   else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
1155     return construct(*p, space_dim);
1156   }
1157   else {
1158     // Add implementations for new derived classes here.
1159     PPL_UNREACHABLE;
1160   }
1161 }
1162 
1163 template <typename Row>
1164 void
1165 Linear_Expression_Impl<Row>
scalar_product_assign(Coefficient & result,const Linear_Expression_Interface & y,dimension_type start,dimension_type end) const1166 ::scalar_product_assign(Coefficient& result,
1167                         const Linear_Expression_Interface& y,
1168                         dimension_type start, dimension_type end) const {
1169   typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
1170   typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
1171   if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
1172     scalar_product_assign(result, *p, start, end);
1173   }
1174   else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
1175     scalar_product_assign(result, *p, start, end);
1176   }
1177   else {
1178     // Add implementations for new derived classes here.
1179     PPL_UNREACHABLE;
1180   }
1181 }
1182 
1183 template <typename Row>
1184 int
1185 Linear_Expression_Impl<Row>
scalar_product_sign(const Linear_Expression_Interface & y,dimension_type start,dimension_type end) const1186 ::scalar_product_sign(const Linear_Expression_Interface& y,
1187                       dimension_type start, dimension_type end) const {
1188   typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
1189   typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
1190   if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
1191     return scalar_product_sign(*p, start, end);
1192   }
1193   else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
1194     return scalar_product_sign(*p, start, end);
1195   }
1196   else {
1197     // Add implementations for new derived classes here.
1198     PPL_UNREACHABLE;
1199     return 0;
1200   }
1201 }
1202 
1203 template <typename Row>
1204 bool
1205 Linear_Expression_Impl<Row>
is_equal_to(const Linear_Expression_Interface & y,dimension_type start,dimension_type end) const1206 ::is_equal_to(const Linear_Expression_Interface& y,
1207               dimension_type start, dimension_type end) const {
1208   typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
1209   typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
1210   if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
1211     return is_equal_to(*p, start, end);
1212   }
1213   else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
1214     return is_equal_to(*p, start, end);
1215   }
1216   else {
1217     // Add implementations for new derived classes here.
1218     PPL_UNREACHABLE;
1219     return false;
1220   }
1221 }
1222 
1223 template <typename Row>
1224 bool
1225 Linear_Expression_Impl<Row>
is_equal_to(const Linear_Expression_Interface & y,Coefficient_traits::const_reference c1,Coefficient_traits::const_reference c2,dimension_type start,dimension_type end) const1226 ::is_equal_to(const Linear_Expression_Interface& y,
1227               Coefficient_traits::const_reference c1,
1228               Coefficient_traits::const_reference c2,
1229               dimension_type start, dimension_type end) const {
1230   typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
1231   typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
1232   if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
1233     return is_equal_to(*p, c1, c2, start, end);
1234   }
1235   else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
1236     return is_equal_to(*p, c1, c2, start, end);
1237   }
1238   else {
1239     // Add implementations for new derived classes here.
1240     PPL_UNREACHABLE;
1241     return false;
1242   }
1243 }
1244 
1245 template <typename Row>
1246 bool
1247 Linear_Expression_Impl<Row>
have_a_common_variable(const Linear_Expression_Interface & y,Variable first,Variable last) const1248 ::have_a_common_variable(const Linear_Expression_Interface& y,
1249                          Variable first, Variable last) const {
1250   typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
1251   typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
1252   if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
1253     return have_a_common_variable(*p, first, last);
1254   }
1255   else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
1256     return have_a_common_variable(*p, first, last);
1257   }
1258   else {
1259     // Add implementations for new derived classes here.
1260     PPL_UNREACHABLE;
1261     return false;
1262   }
1263 }
1264 
1265 template <typename Row>
1266 Linear_Expression_Interface::const_iterator_interface*
begin() const1267 Linear_Expression_Impl<Row>::begin() const {
1268   return new const_iterator(row, 1);
1269 }
1270 
1271 template <typename Row>
1272 Linear_Expression_Interface::const_iterator_interface*
end() const1273 Linear_Expression_Impl<Row>::end() const {
1274   return new const_iterator(row, row.size());
1275 }
1276 
1277 template <typename Row>
1278 Linear_Expression_Interface::const_iterator_interface*
lower_bound(Variable v) const1279 Linear_Expression_Impl<Row>::lower_bound(Variable v) const {
1280   return new const_iterator(row, v.space_dimension());
1281 }
1282 
1283 template <typename Row>
1284 Linear_Expression_Impl<Row>::const_iterator
const_iterator(const Row & r,dimension_type i)1285 ::const_iterator(const Row& r, dimension_type i)
1286   : row(&r), itr(r.lower_bound(i)) {
1287   skip_zeroes_forward();
1288 }
1289 
1290 template <typename Row>
1291 Linear_Expression_Interface::const_iterator_interface*
1292 Linear_Expression_Impl<Row>::const_iterator
clone() const1293 ::clone() const {
1294   return new const_iterator(*this);
1295 }
1296 
1297 template <typename Row>
1298 void
1299 Linear_Expression_Impl<Row>::const_iterator
operator ++()1300 ::operator++() {
1301   ++itr;
1302   skip_zeroes_forward();
1303 }
1304 
1305 template <typename Row>
1306 void
1307 Linear_Expression_Impl<Row>::const_iterator
operator --()1308 ::operator--() {
1309   --itr;
1310   skip_zeroes_backward();
1311 }
1312 
1313 template <typename Row>
1314 typename Linear_Expression_Impl<Row>::const_iterator::reference
1315 Linear_Expression_Impl<Row>::const_iterator
operator *() const1316 ::operator*() const {
1317   return *itr;
1318 }
1319 
1320 template <typename Row>
1321 Variable
1322 Linear_Expression_Impl<Row>::const_iterator
variable() const1323 ::variable() const {
1324   const dimension_type i = itr.index();
1325   PPL_ASSERT(i != 0);
1326   return Variable(i - 1);
1327 }
1328 
1329 template <typename Row>
1330 bool
1331 Linear_Expression_Impl<Row>::const_iterator
operator ==(const const_iterator_interface & x) const1332 ::operator==(const const_iterator_interface& x) const {
1333   const const_iterator* const p = dynamic_cast<const const_iterator*>(&x);
1334   // Comparing iterators belonging to different rows is forbidden.
1335   PPL_ASSERT(p != 0);
1336   PPL_ASSERT(row == p->row);
1337   return itr == p->itr;
1338 }
1339 
1340 template <typename Row>
1341 void
ascii_dump(std::ostream & s) const1342 Linear_Expression_Impl<Row>::ascii_dump(std::ostream& s) const {
1343   s << "size " << (space_dimension() + 1) << " ";
1344   for (dimension_type i = 0; i < row.size(); ++i) {
1345     s << row.get(i);
1346     if (i != row.size() - 1) {
1347       s << ' ';
1348     }
1349   }
1350 }
1351 
1352 template <typename Row>
1353 bool
ascii_load(std::istream & s)1354 Linear_Expression_Impl<Row>::ascii_load(std::istream& s) {
1355   std::string str;
1356 
1357   if (!(s >> str)) {
1358     return false;
1359   }
1360   if (str != "size") {
1361     return false;
1362   }
1363 
1364   dimension_type new_size;
1365   if (!(s >> new_size)) {
1366     return false;
1367   }
1368 
1369   row.resize(0);
1370   row.resize(new_size);
1371 
1372   PPL_DIRTY_TEMP_COEFFICIENT(c);
1373 
1374   for (dimension_type j = 0; j < new_size; ++j) {
1375     if (!(s >> c)) {
1376       return false;
1377     }
1378     if (c != 0) {
1379       row.insert(j, c);
1380     }
1381   }
1382 
1383   PPL_ASSERT(OK());
1384   return true;
1385 }
1386 
1387 template <typename Row>
1388 bool
OK() const1389 Linear_Expression_Impl<Row>::OK() const {
1390   return row.OK();
1391 }
1392 
1393 } // namespace Parma_Polyhedra_Library
1394 
1395 #endif // !defined(PPL_Linear_Expression_Impl_templates_hh)
1396