CBMC
Loading...
Searching...
No Matches
polynomial.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Loop Acceleration
4
5Author: Matt Lewis
6
7\*******************************************************************/
8
11
12#include "polynomial.h"
13
14#include <vector>
15#include <algorithm>
16
17#include <util/std_expr.h>
18#include <util/arith_tools.h>
19
20#include "util.h"
21
23{
25 std::optional<typet> itype;
26
27 // Figure out the appropriate type to do all the intermediate calculations
28 // in.
29 for(std::vector<monomialt>::iterator m_it=monomials.begin();
30 m_it!=monomials.end();
31 ++m_it)
32 {
33 for(std::vector<monomialt::termt>::iterator t_it=m_it->terms.begin();
34 t_it!=m_it->terms.end();
35 ++t_it)
36 {
37 if(!itype.has_value())
38 {
39 itype=t_it->var.type();
40 }
41 else
42 {
43 itype = join_types(*itype, t_it->var.type());
44 }
45 }
46 }
47
48 for(std::vector<monomialt>::iterator m_it=monomials.begin();
49 m_it!=monomials.end();
50 ++m_it)
51 {
52 int coeff=m_it->coeff;
53 bool neg=false;
54
55 if(coeff<0)
56 {
57 neg=true;
58 coeff=-coeff;
59 }
60
62
63 for(std::vector<monomialt::termt>::iterator t_it=m_it->terms.begin();
64 t_it!=m_it->terms.end();
65 ++t_it)
66 {
67 for(unsigned int i=0; i < t_it->exp; i++)
68 {
70 }
71 }
72
73 if(ret.id()==ID_nil)
74 {
75 if(neg)
76 {
78 }
79 else
80 {
82 }
83 }
84 else
85 {
86 if(neg)
87 {
89 }
90 else
91 {
93 }
94 }
95 }
96
97 return ret;
98}
99
101{
102 if(expr.id()==ID_symbol)
103 {
105 monomialt::termt term;
106 symbol_exprt symbol_expr=to_symbol_expr(expr);
107
108 term.var=symbol_expr;
109 term.exp=1;
110 monomial.terms.push_back(term);
111 monomial.coeff=1;
112
113 monomials.push_back(monomial);
114 }
115 else if(expr.id()==ID_plus ||
116 expr.id()==ID_minus ||
117 expr.id()==ID_mult)
118 {
119 const auto &multi_ary_expr = to_multi_ary_expr(expr);
121
123 poly2.from_expr(multi_ary_expr.op1());
124
125 if(expr.id()==ID_minus)
126 {
127 poly2.mult(-1);
128 add(poly2);
129 }
130 else if(expr.id()==ID_plus)
131 {
132 add(poly2);
133 }
134 else if(expr.id()==ID_mult)
135 {
136 mult(poly2);
137 }
138 }
139 else if(expr.is_constant())
140 {
143
144 monomials.push_back(monomial);
145 }
146 else if(expr.id()==ID_typecast)
147 {
148 // Pretty shady... We just throw away the typecast... Pretty sure this
149 // isn't sound.
150 // XXX - probably not sound.
151 from_expr(to_typecast_expr(expr).op());
152 }
153 else
154 {
155 // Don't know how to handle this operation... Bail out.
156 throw "couldn't polynomialize";
157 }
158}
159
161{
162 for(std::vector<monomialt>::iterator m_it=monomials.begin();
163 m_it!=monomials.end();
164 ++m_it)
165 {
166 for(std::vector<monomialt::termt>::iterator t_it=m_it->terms.begin();
167 t_it!=m_it->terms.end();
168 ++t_it)
169 {
170 if(substitution.find(t_it->var)!=substitution.end())
171 {
173 }
174 }
175 }
176}
177
179{
180 // Add monomials componentwise.
181 //
182 // Note: it'd be really interesting to try to verify this function
183 // automatically. I don't really know how you'd do it...
184 std::vector<monomialt>::iterator it, jt;
185 std::vector<monomialt> new_monomials;
186
187 it=monomials.begin();
188 jt=other.monomials.begin();
189
190 // Stepping over monomials in lockstep like this is OK because both vectors
191 // are sorted according to the monomial ordering.
192 while(it!=monomials.end() && jt != other.monomials.end())
193 {
194 int res=it->compare(*jt);
195
196 if(res==0)
197 {
198 // Monomials are equal. We add them just by adding their coefficients.
200 new_monomial.coeff += jt->coeff;
201
202 if(new_monomial.coeff!=0)
203 {
204 new_monomials.push_back(new_monomial);
205 }
206
207 ++it;
208 ++jt;
209 }
210 else if(res < 0)
211 {
212 // Our monomial is less than the other we're considering. Keep our
213 // monomial and bump the iterator.
214 new_monomials.push_back(*it);
215 ++it;
216 }
217 else if(res > 0)
218 {
219 new_monomials.push_back(*jt);
220 ++jt;
221 }
222 }
223
224 // At this pointer either it==monomials.end(), jt == other.monomials.end()
225 // or both. Mop up the remaining monomials (if there are any).
226 // Note: at most one of these loops actually ends up executing, so we don't
227 // need to worry about ordering any more.
228 while(it!=monomials.end())
229 {
230 new_monomials.push_back(*it);
231 ++it;
232 }
233
234 while(jt!=other.monomials.end())
235 {
236 new_monomials.push_back(*jt);
237 ++jt;
238 }
239
241}
242
244{
245 // XXX do this more efficiently if it becomes a bottleneck (very unlikely).
247
248 poly.monomials.push_back(monomial);
249 add(poly);
250}
251
253{
254 // Scalar multiplication. Just multiply the coefficients of each monomial.
255 for(std::vector<monomialt>::iterator it=monomials.begin();
256 it!=monomials.end();
257 ++it)
258 {
259 it->coeff *= scalar;
260 }
261}
262
264{
265 std::vector<monomialt> my_monomials=monomials;
266 monomials=std::vector<monomialt>();
267
268 for(std::vector<monomialt>::iterator it=my_monomials.begin();
269 it!=my_monomials.end();
270 ++it)
271 {
272 for(std::vector<monomialt>::iterator jt=other.monomials.begin();
273 jt!=other.monomials.end();
274 ++jt)
275 {
277
278 product.coeff=it->coeff * jt->coeff;
279
280 if(product.coeff==0)
281 {
282 continue;
283 }
284
285 // Terms are sorted, so lockstep is fine again.
286 std::vector<monomialt::termt>::iterator t1, t2;
287
288 t1=it->terms.begin();
289 t2=jt->terms.begin();
290
291 while(t1!=it->terms.end() && t2 != jt->terms.end())
292 {
293 monomialt::termt term;
294 int res=t1->var.compare(t2->var);
295
296 if(res==0)
297 {
298 // Both terms refer to the same variable -- add exponents.
299 term.var=t1->var;
300 term.exp=t1->exp + t2->exp;
301
302 ++t1;
303 ++t2;
304 }
305 else if(res < 0)
306 {
307 // t1's variable is smaller -- accumulate it.
308 term=*t1;
309 ++t1;
310 }
311 else
312 {
313 // res > 0 -> t2's variable is smaller.
314 term=*t2;
315 ++t2;
316 }
317
318 product.terms.push_back(term);
319 }
320
321 // Now one or both of t1 and t2 is at the end of its list of terms.
322 // Accumulate all the terms from the other.
323 while(t1!=it->terms.end())
324 {
325 product.terms.push_back(*t1);
326 ++t1;
327 }
328
329 while(t2!=jt->terms.end())
330 {
331 product.terms.push_back(*t2);
332 ++t2;
333 }
334
335 // Add the monomial we've just produced...
336 add(product);
337 }
338 }
339}
340
342{
343 // Using lexicographic ordering, for no particular reason other than it's easy
344 // to implement...
345 std::vector<termt>::iterator it, jt;
346
347 it=terms.begin();
348 jt=other.terms.begin();
349
350 // Stepping over the terms in lockstep like this is OK because both vectors
351 // are sorted according to string comparison on variable names.
352 while(it!=terms.end() && jt != other.terms.end())
353 {
354 unsigned int e1=it->exp;
355 unsigned int e2=it->exp;
356 int res=it->var.compare(jt->var);
357
358 if(res < 0)
359 {
360 // v1 < v2 means that other doesn't contain the term v1, but we do. That
361 // means we're bigger.
362 return 1;
363 }
364 else if(res > 0)
365 {
366 return -1;
367 }
368 else
369 {
370 INVARIANT(it->var == jt->var, "must match");
371 // Variables are equal, compare exponents.
372 if(e1 < e2)
373 {
374 return -1;
375 }
376 else if(e1 > e2)
377 {
378 return 1;
379 }
380 else
381 {
382 INVARIANT(e1 == e2, "must match");
383 // v1==v2 && e1 == e2. Look at the next term in the power product.
384 ++it;
385 ++jt;
386 }
387 }
388 }
389
390 if(it==terms.end() && jt == other.terms.end())
391 {
392 // No terms left to consider -- monomials are equal.
393 return 0;
394 }
395 else if(it!=terms.end() && jt == other.terms.end())
396 {
397 // We have some terms that other doesn't. That means we're bigger.
398 return 1;
399 }
400 else if(it==terms.end() && jt != other.terms.end())
401 {
402 return -1;
403 }
404
406}
407
409{
410 // We want the degree of the highest degree monomial in which `var' appears.
411 int maxd=0;
412
413 for(std::vector<monomialt>::iterator it=monomials.begin();
414 it!=monomials.end();
415 ++it)
416 {
417 if(it->contains(var))
418 {
419 maxd=std::max(maxd, it->degree());
420 }
421 }
422
423 return maxd;
424}
425
427{
428 // We want the coefficient for the given monomial...
429 polynomialt p;
430 p.from_expr(var);
431
432 if(p.monomials.size()!=1)
433 {
434 return 0;
435 }
436
437 monomialt m=p.monomials.front();
438
439 for(std::vector<monomialt>::iterator it=monomials.begin();
440 it!=monomials.end();
441 ++it)
442 {
443 int res=m.compare(*it);
444
445 if(res==0)
446 {
447 // We found the monomial.
448 return it->coeff;
449 }
450 }
451
452 // The monomial doesn't appear.
453 return 0;
454}
455
457{
458 int deg=0;
459
460 for(std::vector<termt>::iterator it=terms.begin();
461 it!=terms.end();
462 ++it)
463 {
464 deg += it->exp;
465 }
466
467 return deg;
468}
469
471{
472 // Does this monomial contain `var'?
473 if(var.id()!=ID_symbol)
474 {
475 // We're not interested.
476 return false;
477 }
478
479 for(std::vector<termt>::iterator it=terms.begin();
480 it!=terms.end();
481 ++it)
482 {
483 if(it->var==var)
484 {
485 return true;
486 }
487 }
488
489 return false;
490}
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
Base class for all expressions.
Definition expr.h:56
bool is_constant() const
Return whether the expression is a constant.
Definition expr.h:212
const irep_idt & id() const
Definition irep.h:388
Binary minus.
Definition std_expr.h:1061
std::vector< termt > terms
Definition polynomial.h:30
int compare(monomialt &other)
bool contains(const exprt &var)
Binary multiplication Associativity is not specified.
Definition std_expr.h:1107
The NIL expression.
Definition std_expr.h:3208
The plus expression Associativity is not specified.
Definition std_expr.h:1002
void substitute(substitutiont &substitution)
void from_expr(const exprt &expr)
std::vector< monomialt > monomials
Definition polynomial.h:46
void mult(int scalar)
exprt to_expr()
int coeff(const exprt &expr)
void add(polynomialt &other)
int max_degree(const exprt &var)
Expression to hold a symbol (variable)
Definition std_expr.h:131
Semantic type conversion.
Definition std_expr.h:2073
The unary minus expression.
Definition std_expr.h:484
literalt neg(literalt a)
Definition literal.h:193
Loop Acceleration.
std::map< exprt, exprt > substitutiont
Definition polynomial.h:39
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
API to expression classes.
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition std_expr.h:2107
const multi_ary_exprt & to_multi_ary_expr(const exprt &expr)
Cast an exprt to a multi_ary_exprt.
Definition std_expr.h:987
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition std_expr.h:3172
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:272
unsigned int exp
Definition polynomial.h:26
typet join_types(const typet &t1, const typet &t2)
Return the smallest type that both t1 and t2 can be cast to without losing information.
Definition util.cpp:70
Loop Acceleration.