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