PPL  1.2
Congruence.cc
Go to the documentation of this file.
1 /* Congruence class implementation (non-inline functions).
2  Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3  Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4 
5 This file is part of the Parma Polyhedra Library (PPL).
6 
7 The PPL is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 The PPL is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20 
21 For the most up-to-date information see the Parma Polyhedra Library
22 site: http://bugseng.com/products/ppl/ . */
23 
24 #include "ppl-config.h"
25 #include "Congruence_defs.hh"
26 #include "Variable_defs.hh"
27 #include "Constraint_defs.hh"
28 #include "assertions.hh"
29 #include <iostream>
30 #include <sstream>
31 #include <stdexcept>
32 #include <string>
33 
34 namespace PPL = Parma_Polyhedra_Library;
35 
37  : expr(c.expression(), c.space_dimension(), r),
38  modulus_(0) {
39  if (!c.is_equality()) {
40  throw_invalid_argument("Congruence(c, r)",
41  "constraint c must be an equality.");
42  }
43 }
44 
46  dimension_type new_space_dimension,
48  : expr(c.expression(), new_space_dimension, r),
49  modulus_(0) {
50  if (!c.is_equality()) {
51  throw_invalid_argument("Congruence(c, space_dim, r)",
52  "constraint c must be an equality.");
53  }
54 }
55 
56 void
58  expr.sign_normalize();
59 }
60 
61 void
63  PPL_ASSERT(OK());
64  sign_normalize();
65 
66  if (modulus_ == 0) {
67  return;
68  }
69 
71  c = expr.inhomogeneous_term();
72  // Factor the modulus out of the inhomogeneous term.
73  c %= modulus_;
74  if (c < 0) {
75  // Make inhomogeneous term positive.
76  c += modulus_;
77  }
78  expr.set_inhomogeneous_term(c);
79 
80  PPL_ASSERT(OK());
81 }
82 
83 void
85  normalize();
86 
87  Coefficient gcd = expr.gcd(0, expr.space_dimension() + 1);
88  if (gcd == 0) {
89  gcd = modulus_;
90  }
91  else {
92  gcd_assign(gcd, modulus_, gcd);
93  }
94 
95  if (gcd != 0 && gcd != 1) {
96  expr /= gcd;
97  modulus_ /= gcd;
98  }
99  PPL_ASSERT(OK());
100 }
101 
102 void
103 PPL::Congruence::scale(Coefficient_traits::const_reference factor) {
104  if (factor == 1) {
105  // Nothing to do.
106  return;
107  }
108 
109  expr *= factor;
110  modulus_ *= factor;
111 }
112 
113 void
116  Coefficient_traits::const_reference denominator) {
118  c = expr.get(v);
119 
120  if (c == 0) {
121  return;
122  }
123 
124  scale(denominator);
125 
126  expr.linear_combine(e, 1, c, 0, e.space_dimension() + 1);
127 
128  if (v.space_dimension() > e.space_dimension() || e.get(v) == 0) {
129  // Not invertible
130  expr.set(v, Coefficient_zero());
131  }
132  else {
133  c *= e.get(v);
134  expr.set(v, c);
135  }
136 }
137 
140  const Linear_Expression& e2,
141  Representation r) {
142  Linear_Expression e(e1,
143  std::max(e1.space_dimension(), e2.space_dimension()),
144  r);
145  e -= e2;
146  return Congruence(e, 1, Recycle_Input());
147 }
148 
149 void
151  const char* message) const {
152  std::ostringstream s;
153  s << "PPL::Congruence::" << method << ":" << std::endl
154  << message;
155  throw std::invalid_argument(s.str());
156 }
157 
158 void
160  const char* v_name,
161  const Variable v) const {
162  std::ostringstream s;
163  s << "this->space_dimension() == " << space_dimension() << ", "
164  << v_name << ".space_dimension() == " << v.space_dimension() << ".";
165  const std::string str = s.str();
166  throw_invalid_argument(method, str.c_str());
167 }
168 
170 std::ostream&
171 PPL::IO_Operators::operator<<(std::ostream& s, const Congruence& c) {
172  const dimension_type num_variables = c.space_dimension();
174  bool first = true;
175  const Congruence::expr_type c_e = c.expression();
177  i_end = c_e.lower_bound(Variable(num_variables)); i != i_end; ++i) {
178  cv = *i;
179  if (!first) {
180  if (cv > 0) {
181  s << " + ";
182  }
183  else {
184  s << " - ";
185  neg_assign(cv);
186  }
187  }
188  else {
189  first = false;
190  }
191  if (cv == -1) {
192  s << "-";
193  }
194  else if (cv != 1) {
195  s << cv << "*";
196  }
197  s << i.variable();
198  }
199  if (first) {
200  s << Coefficient_zero();
201  }
202  s << " = " << -c.inhomogeneous_term();
203  if (c.is_proper_congruence()) {
204  s << " (mod " << c.modulus() << ")";
205  }
206  return s;
207 }
208 
209 bool
211  if (is_equality()) {
212  return (inhomogeneous_term() == 0) && expr.all_homogeneous_terms_are_zero();
213  }
214  return (inhomogeneous_term() % modulus() == 0) && expr.all_homogeneous_terms_are_zero();
215 }
216 
217 bool
219  if (is_equality()) {
220  return (inhomogeneous_term() != 0) && expr.all_homogeneous_terms_are_zero();
221  }
222 
223  return (inhomogeneous_term() % modulus() != 0) && expr.all_homogeneous_terms_are_zero();
224 }
225 
226 void
227 PPL::Congruence::ascii_dump(std::ostream& s) const {
228  expr.ascii_dump(s);
229  s << " m " << modulus_ << std::endl;
230 }
231 
233 
234 bool
235 PPL::Congruence::ascii_load(std::istream& s) {
236  expr.ascii_load(s);
237 
238  std::string str;
239  if (!(s >> str) || str != "m") {
240  return false;
241  }
242 
243  if (!(s >> modulus_)) {
244  return false;
245  }
246 
247  PPL_ASSERT(OK());
248  return true;
249 }
250 
251 bool
253  // Modulus check.
254  if (modulus() < 0) {
255 #ifndef NDEBUG
256  std::cerr << "Congruence has a negative modulus " << modulus() << "."
257  << std::endl;
258 #endif
259  return false;
260  }
261 
262  // All tests passed.
263  return true;
264 }
265 
268 
269 void
271  PPL_ASSERT(zero_dim_false_p == 0);
272  zero_dim_false_p
273  = new Congruence((Linear_Expression::zero() %= Coefficient(-1)) / 0);
274 
275  PPL_ASSERT(zero_dim_integrality_p == 0);
276  zero_dim_integrality_p
278 }
279 
280 void
282  PPL_ASSERT(zero_dim_false_p != 0);
283  delete zero_dim_false_p;
284  zero_dim_false_p = 0;
285 
286  PPL_ASSERT(zero_dim_integrality_p != 0);
287  delete zero_dim_integrality_p;
288  zero_dim_integrality_p = 0;
289 }
A transparent adapter for Linear_Expression objects.
Coefficient_traits::const_reference modulus() const
Returns a const reference to the modulus of *this.
void sign_normalize()
Normalizes the signs.
Definition: Congruence.cc:57
A linear equality or inequality.
void affine_preimage(Variable v, const Linear_Expression &expr, Coefficient_traits::const_reference denominator)
Definition: Congruence.cc:115
bool is_equality() const
Returns true if and only if *this is an equality constraint.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Coefficient_traits::const_reference get(dimension_type i) const
Returns the i-th coefficient.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
bool is_inconsistent() const
Returns true if and only if *this is inconsistent (i.e., an always false congruence).
Definition: Congruence.cc:218
void strong_normalize()
Calls normalize, then divides out common factors.
Definition: Congruence.cc:84
static void initialize()
Initializes the class.
Definition: Congruence.cc:270
std::ostream & operator<<(std::ostream &s, const Ask_Tell< D > &x)
The standard C++ namespace.
expr_type expression() const
Partial read access to the (adapted) internal expression.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void ascii_dump() const
Writes to std::cerr an ASCII representation of *this.
Coefficient_traits::const_reference inhomogeneous_term() const
Returns the inhomogeneous term of *this.
bool is_proper_congruence() const
Returns true if the modulus is greater than zero.
A dimension of the vector space.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void normalize()
Normalizes signs and the inhomogeneous term.
Definition: Congruence.cc:62
static Congruence create(const Linear_Expression &e1, const Linear_Expression &e2, Representation r=default_representation)
Returns the congruence .
Definition: Congruence.cc:139
bool OK() const
Checks if all the invariants are satisfied.
Definition: Congruence.cc:252
static const Congruence * zero_dim_false_p
Holds (between class initialization and finalization) a pointer to the false (zero-dimension space) c...
Congruence(Representation r=default_representation)
Constructs the 0 = 0 congruence with space dimension 0 .
void throw_dimension_incompatible(const char *method, const char *v_name, Variable v) const
Throws a std::invalid_argument exception containing the appropriate error message.
Definition: Congruence.cc:159
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type ascii_load(std::istream &s, T &t)
void throw_invalid_argument(const char *method, const char *message) const
Throws a std::invalid_argument exception containing error message message.
Definition: Congruence.cc:150
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
bool is_tautological() const
Returns true if and only if *this is a tautology (i.e., an always true congruence).
Definition: Congruence.cc:210
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
static void finalize()
Finalizes the class.
Definition: Congruence.cc:281
void neg_assign(GMP_Integer &x)
Coefficient_traits::const_reference Coefficient_zero()
Returns a const reference to a Coefficient with value 0.
#define PPL_OUTPUT_DEFINITIONS(class_name)
The entire library is confined to this namespace.
Definition: version.hh:61
void gcd_assign(GMP_Integer &x, const GMP_Integer &y, const GMP_Integer &z)
base_type::const_iterator const_iterator
The type of const iterators on coefficients.
Coefficient c
Definition: PIP_Tree.cc:64
static const Linear_Expression & zero()
Returns the (zero-dimension space) constant 0.
const_iterator begin() const
Iterator pointing to the first nonzero variable coefficient.
void scale(Coefficient_traits::const_reference factor)
Multiplies all the coefficients, including the modulus, by factor .
Definition: Congruence.cc:103
static const Congruence * zero_dim_integrality_p
Holds (between class initialization and finalization) a pointer to the true (zero-dimension space) co...