PPL  1.2
Linear_Expression_Impl_templates.hh
Go to the documentation of this file.
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>
42  construct(e);
43 }
44 
45 template <typename Row>
46 template <typename Row2>
49  construct(e);
50 }
51 
52 template <typename Row>
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>
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
92  PPL_ASSERT(space_dimension() == y.space_dimension());
93  PPL_ASSERT(i.space_dimension() <= space_dimension());
95 }
96 
97 template <typename Row>
98 template <typename Row2>
99 void
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
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
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
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>
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
238  return row == x.row;
239 }
240 
241 template <typename Row>
242 void
244  r = this->row;
245 }
246 
247 template <typename Row>
248 void
250  r = this->row;
251 }
252 
253 template <typename Row>
254 void
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 {
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>
289  return *this;
290 }
291 
293 template <typename Row>
296  const dimension_type v_space_dim = v.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 
315 template <typename Row>
316 template <typename Row2>
319  linear_combine(e2, Coefficient_one(), -1);
320  return *this;
321 }
322 
324 template <typename Row>
327  const dimension_type v_space_dim = v.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 
346 template <typename Row>
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 
363 template <typename Row>
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 
382 template <typename Row>
383 void
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 
393 template <typename Row>
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();
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 
419 template <typename Row>
422 ::sub_mul_assign(Coefficient_traits::const_reference n,
423  const Variable v) {
424  const dimension_type v_space_dim = v.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
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
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
469 Linear_Expression_Impl<Row>::print(std::ostream& s) const {
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.
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
526  return row.get(i);
527 }
528 
529 template <typename Row>
530 void
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
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) {
553  }
554  PPL_ASSERT(OK());
555 }
556 
557 template <typename Row>
558 void
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
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
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
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
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
710  row = e.row;
711  PPL_ASSERT(OK());
712 }
713 
714 template <typename Row>
715 template <typename Row2>
716 void
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
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
768  dimension_type start, dimension_type end) const {
770  scalar_product_assign(result, y, start, end);
771  return sgn(result);
772 }
773 
774 template <typename Row>
775 template <typename Row2>
776 bool
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
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
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
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
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
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>
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>
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
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
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
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
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
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
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
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
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
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
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
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
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
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>
1268  return new const_iterator(row, 1);
1269 }
1270 
1271 template <typename Row>
1274  return new const_iterator(row, row.size());
1275 }
1276 
1277 template <typename Row>
1280  return new const_iterator(row, v.space_dimension());
1281 }
1282 
1283 template <typename Row>
1286  : row(&r), itr(r.lower_bound(i)) {
1288 }
1289 
1290 template <typename Row>
1293 ::clone() const {
1294  return new const_iterator(*this);
1295 }
1296 
1297 template <typename Row>
1298 void
1301  ++itr;
1302  skip_zeroes_forward();
1303 }
1304 
1305 template <typename Row>
1306 void
1309  --itr;
1310  skip_zeroes_backward();
1311 }
1312 
1313 template <typename Row>
1316 ::operator*() const {
1317  return *itr;
1318 }
1319 
1320 template <typename Row>
1321 Variable
1323 ::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
1332 ::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
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
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 
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
1390  return row.OK();
1391 }
1392 
1393 } // namespace Parma_Polyhedra_Library
1394 
1395 #endif // !defined(PPL_Linear_Expression_Impl_templates_hh)
virtual Linear_Expression_Impl & operator+=(Coefficient_traits::const_reference n)
dimension_type max_space_dimension()
Returns the maximum space dimension this library can handle.
void swap(CO_Tree &x, CO_Tree &y)
A finite sequence of coefficients.
virtual void linear_combine(const Linear_Expression_Interface &y, Variable v)
size_t dimension_type
An unsigned integral type for representing space dimensions.
void linear_combine(Dense_Row &x, const Dense_Row &y, Coefficient_traits::const_reference coeff1, Coefficient_traits::const_reference coeff2)
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
virtual bool have_a_common_variable(const Linear_Expression_Interface &x, Variable first, Variable last) const
void add_mul_assign(GMP_Integer &x, const GMP_Integer &y, const GMP_Integer &z)
virtual bool OK() const
Checks if all the invariants are satisfied.
std::ostream & operator<<(std::ostream &s, const Ask_Tell< D > &x)
A finite sparse sequence of coefficients.
void exact_div_assign(Checked_Number< T, Policy > &x, const Checked_Number< T, Policy > &y, const Checked_Number< T, Policy > &z)
virtual Linear_Expression_Impl & operator-=(Coefficient_traits::const_reference n)
virtual Variable variable() const
Returns the variable of the coefficient pointed to by *this.
virtual void exact_div_assign(Coefficient_traits::const_reference c, dimension_type start, dimension_type end)
A dimension of the vector space.
virtual int compare(const Linear_Expression_Interface &y) const
The basic comparison function.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
virtual Linear_Expression_Impl & operator*=(Coefficient_traits::const_reference n)
virtual void get_row(Dense_Row &r) const
Sets r to a copy of the row that implements *this.
virtual Linear_Expression_Impl & add_mul_assign(Coefficient_traits::const_reference n, const Variable v)
virtual bool ascii_load(std::istream &s)
Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this ...
virtual int scalar_product_sign(const Linear_Expression_Interface &y, dimension_type start, dimension_type end) const
Computes the sign of the sum of (*this)[i]*y[i], for each i in [start,end).
virtual bool is_equal_to(const Linear_Expression_Interface &x) const
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
int compare(const Linear_Expression &x, const Linear_Expression &y)
virtual void set(dimension_type i, Coefficient_traits::const_reference n)
Sets the i-th coefficient to n.
Linear_Expression_Impl()
Default constructor: returns a copy of Linear_Expression_Impl::zero().
virtual void ascii_dump(std::ostream &s) const
Writes to s an ASCII representation of *this.
void neg_assign(GMP_Integer &x)
Coefficient_traits::const_reference Coefficient_zero()
Returns a const reference to a Coefficient with value 0.
The entire library is confined to this namespace.
Definition: version.hh:61
virtual Linear_Expression_Impl & operator/=(Coefficient_traits::const_reference n)
virtual dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
virtual void mul_assign(Coefficient_traits::const_reference n, dimension_type start, dimension_type end)
Equivalent to (*this)[i] *= n, for each i in [start, end).
virtual Coefficient_traits::const_reference get(dimension_type i) const
Returns the i-th coefficient.
virtual bool operator==(const const_iterator_interface &x) const
Compares *this with x .
int cmp(const GMP_Integer &x, const GMP_Integer &y)
int sgn(Boundary_Type type, const T &x, const Info &info)
void sub_mul_assign(GMP_Integer &x, const GMP_Integer &y, const GMP_Integer &z)
void normalize2(Coefficient_traits::const_reference x, Coefficient_traits::const_reference y, Coefficient &n_x, Coefficient &n_y)
If is the GCD of x and y, the values of x and y divided by are assigned to n_x and n_y...
virtual Linear_Expression_Impl & sub_mul_assign(Coefficient_traits::const_reference n, const Variable v)
virtual void linear_combine_lax(const Linear_Expression_Interface &y, Coefficient_traits::const_reference c1, Coefficient_traits::const_reference c2)
virtual void scalar_product_assign(Coefficient &result, const Linear_Expression_Interface &y, dimension_type start, dimension_type end) const
Sets results to the sum of (*this)[i]*y[i], for each i in [start,end).
Coefficient c
Definition: PIP_Tree.cc:64
virtual bool all_zeroes(const Variables_Set &vars) const
Returns true if the coefficient of each variable in vars[i] is .
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type construct(To &to, const From &, Rounding_Dir dir)
Coefficient_traits::const_reference Coefficient_one()
Returns a const reference to a Coefficient with value 1.
virtual const_iterator_interface * lower_bound(Variable v) const
virtual void permute_space_dimensions(const std::vector< Variable > &cycle)
Permutes the space dimensions of the expression.
virtual reference operator*() const
Returns the current element.