2 /***************************************************************************
3 ehrhartpolynom.h - description
5 begin : Fri 23 Nov 2001
6 copyright : (C) 2001 by Kristof Beyls
7 email : Kristof.Beyls@elis.rug.ac.be
8 ***************************************************************************/
10 #ifndef EHRHARTPOLYNOM_H
11 #define EHRHARTPOLYNOM_H
18 #define swap omega_swap
32 #include <polylib/polylibgmp.h>
33 #include <polylib/ehrhart.h>
37 /** class PeriodicNumber represents a multidimensional
38 * periodic number. For more definition and more details
39 * about periodic numbers: see "Counting Solutions to Linear
40 * and Nonlinear Constraints through Ehrhart Polynomials:
41 * Applications to Analyze and Transform Scientific Programs",
42 * By Philippe CLAUSS, in tenth ACM International Conference
43 * on Supercomputing, May 1996
45 class PeriodicNumber
{
46 friend class EhrhartPolynom
;
47 /// parameter_names contains the ordered names of the parameters
48 std::set
<string
> parameter_names
;
49 /// period is the period of the variable
50 map
<string
,int> period
;
51 /** data contains the multi-dimensional matrix containing
52 * the value's in the periodic number. The data
53 * is layed out column-major, with the dimensions
54 * of the matrix ordered with the alphabetical order
55 * of the corresponding parameter names.
58 /** stride contains the stride in the data array between
59 * 2 consecutive elements of parameter p.
60 * e.g. if the parameters are "a" and "b", and the strides
62 * stride["a"] = 1 and stride["b"] = 3.
64 map
<string
,unsigned long> stride
;
65 unsigned long datasize
;
68 /** @param parameter_names contains the names of the
70 * @param period contains the periods of the different
73 PeriodicNumber(const std::set
<string
>& _parameter_names
,
74 const map
<string
, int>& _period
)
75 : parameter_names(_parameter_names
), period(_period
)
77 unsigned long datasize
= 1;
78 for(map
<string
,int>::const_iterator i
=period
.begin();
79 i
!=period
.end(); i
++) {
80 stride
[(*i
).first
] = datasize
;
81 datasize
*=(*i
).second
;
83 data
= new Value
[datasize
];
84 for(unsigned i
=0;i
<datasize
;i
++) {
86 value_set_si(data
[i
] , 0);
88 this->datasize
= datasize
;
91 parameter_names
.insert("");
94 data
= new Value
[datasize
];
96 value_set_si(data
[0],0);
99 PeriodicNumber(const Value t
) {
100 parameter_names
.insert("");
103 data
= new Value
[datasize
];
105 value_assign(data
[0],t
);
108 PeriodicNumber(const PeriodicNumber
& pn
)
109 : parameter_names(pn
.parameter_names
), period(pn
.period
),
110 stride(pn
.stride
), datasize(pn
.datasize
)
112 data
= new Value
[datasize
];
113 for(unsigned i
=0;i
<datasize
; i
++) {
115 value_assign(data
[i
], pn
.data
[i
]);
118 memcpy(data, pn.data, sizeof(Value)*datasize);
121 PeriodicNumber
& operator=(const PeriodicNumber
& pn
) {
125 for(unsigned i
=0; i
<datasize
; i
++)
126 value_clear(data
[i
]);
129 parameter_names
=pn
.parameter_names
;
132 datasize
=pn
.datasize
;
134 data
= new Value
[datasize
];
135 for(unsigned i
=0;i
<datasize
; i
++) {
137 value_assign(data
[i
], pn
.data
[i
]);
139 /* memcpy(data, pn.data, sizeof(Value)*datasize); */
142 bool is_zero() const {
143 for(unsigned long i
=0;i
<datasize
;i
++)
144 if (value_notzero_p(data
[i
]))
148 bool operator==(const PeriodicNumber
& pn
) const {
149 bool t1
= (parameter_names
==pn
.parameter_names
&&
153 assert(stride
==pn
.stride
);
154 assert(datasize
==pn
.datasize
);
155 for(unsigned i
=0;i
<datasize
; i
++)
156 if (value_ne( data
[i
], pn
.data
[i
]))
160 return (0==memcmp(data, pn.data, datasize*sizeof(Value)));
163 inline bool operator!=(const PeriodicNumber
& pn
) const { return !((*this)==pn
); }
164 // PeriodicNumber() : data(0) {}
166 for(unsigned i
=0;i
<datasize
; i
++)
167 value_clear(data
[i
]);
171 assert(period
.size()==parameter_names
.size());
172 return period
.size();
174 /** operator[] returns the Value which correspends to the index
175 * @param index The index in the multidimensional matrix,
176 * representing the multi-periodic number.
178 Value
& operator[](const map
<string
, int>& index
);
179 const Value
& operator[](const map
<string
, int>& index
) const;
180 /** multiply all the values in the periodic number with v */
181 PeriodicNumber
operator*(const Value v
) const;
182 /** find the gcd of all the values in the periodic number */
183 void get_gcd(Value
& v
) const;
184 /** divide all the values in the periodic number by v.
185 * The gcd of all the values should be a multiple of v.*/
186 void divide_by(const Value v
);
187 /* Calculate the product of 2 periodic numbers.
188 * e.g. product of [1,2]_p and [5,6]_q
192 PeriodicNumber
operator*(const PeriodicNumber
& pn
) const;
193 PeriodicNumber
operator+(const PeriodicNumber
& pn
) const;
194 bool smaller_than(const PeriodicNumber
& pn
) const;
195 string
to_string() const;
196 double to_double() const;
197 inline operator string() const { return to_string(); }
198 ::evalue
to_evalue(const deque
<string
>& parameter_names
) const;
199 int get_period(const string
& name
) const {
200 map
<string
,int>::const_iterator i
=period
.find(name
);
201 assert(i
!=period
.end());
204 bool has_param(const string
& name
) const;
205 std::set
<string
> get_params() const {
206 std::set
<string
> result
;
207 for(map
<string
,int>::const_iterator i
=period
.begin();
208 i
!=period
.end(); i
++)
209 result
.insert((*i
).first
);
210 assert(result
== parameter_names
);
215 /** class EhrhartPolynom is PolyAst's own representation of
216 * an Ehrhart polynomial. The first reason to create this
217 * representation is to allow an easy algorithm to add up 2
218 * Ehrhart Polynomials, since the eadd-function in polylib4.19
219 * doesn't handle all cases.
221 class EhrhartPolynom
{
223 struct periodic_rational
{
224 PeriodicNumber first
;
226 periodic_rational(const PeriodicNumber
& pn
, const Value v
) {
229 value_assign(second
, v
);
231 periodic_rational() {
234 ~periodic_rational() {
237 periodic_rational(const periodic_rational
& pr
) {
240 value_assign(second
, pr
.second
);
242 periodic_rational
& operator=(const periodic_rational
& pr
) {
246 value_assign(second
, pr
.second
);
250 /** data represents the Ehrhart polynomial. The first part
251 * of the pair in the map represents the coefficients of the
252 * parameters. The second part represents the coefficient,
253 * which is a periodic number.
255 * \f$2x^2y+ 2/3 y^2-z\f$ is represented as
256 * ({(x,2),(y,1)},(2,1)), ({(y,2)},(2,3)), ({(z,1)},(-1,1)).
258 map
<map
<string
, int>, periodic_rational
> data
;
259 /** simplify removes the terms with coefficient 0
260 * and removes the exponents with power 0.
264 /** Initialization of EhrhartPolynom from a Polylib representation
265 of the Ehrhart Polynomial. */
266 EhrhartPolynom(const ::evalue
* e
, const deque
<string
>& parameter_names
);
267 /** Initialization to zero. */
271 value_set_si(val
, 0);
273 value_set_si(one
, 1);
274 map
<string
,int> exponent
;
275 PeriodicNumber
pn(val
);
276 periodic_rational
pr(pn
, one
);
281 /** Initialization to constant value. */
282 EhrhartPolynom(long cst
) {
285 value_set_si(val
, cst
);
287 value_set_si(one
, 1);
288 map
<string
,int> exponent
;
289 PeriodicNumber
pn(val
);
290 periodic_rational
pr(pn
, one
);
295 /** single-term polynomial. */
296 EhrhartPolynom(const map
<string
,int>& exponent
,
297 const periodic_rational
& coef
) {
298 data
[exponent
] = coef
;
301 /** single-term polynomial. */
302 EhrhartPolynom(const map
<string
,int>& exponent
,
303 const pair
<PeriodicNumber
, Value
>& coef
) {
304 data
[exponent
] = periodic_rational(coef
.first
, coef
.second
);
307 bool operator==(const EhrhartPolynom
& ep
) const;
308 inline bool operator!=(const EhrhartPolynom
& ep
) const { return !((*this)==ep
); }
309 bool smaller_than(const EhrhartPolynom
& ep
) const;
311 EhrhartPolynom
& operator=(const EhrhartPolynom
& e1
)
316 for(map<map<string, int>, periodic_rational >::iterator
317 i=data.begin(); i!=data.end(); i++)
318 value_clear((*i).second.second);
321 for(map
<map
<string
, int>, periodic_rational
>::const_iterator
322 i
=e1
.data
.begin(); i
!=e1
.data
.end(); i
++) {
326 value_assign(val, (*i).second.second);
327 pair<map<string, int>, pair<PeriodicNumber, Value> > new_record=(*i);
328 new_record.second.second = val;
329 data.insert(new_record);
331 data
[(*i
).first
] = (*i
).second
;
335 /** operator+ adds up the this polynomial and polynomial e1. */
336 EhrhartPolynom
operator+(const EhrhartPolynom
& e1
) const;
337 /** operator+= adds up the polynomial e1 to this polynomial. */
338 EhrhartPolynom
operator+=(const EhrhartPolynom
& e1
) {
340 data = ((*this) + e1).data;
342 EhrhartPolynom sum
= (*this) + e1
;
346 /** operator* multiplies the this polynomial and polynomial e1. */
347 EhrhartPolynom
operator*(const EhrhartPolynom
& e1
) const;
348 /** operator/ divides by constant. */
349 EhrhartPolynom
operator/(const Value v
) const;
350 /** operator*= multiplies this polynomial with polynomial e1. */
351 EhrhartPolynom
operator*=(const EhrhartPolynom
& e1
) {
352 EhrhartPolynom prod
= (*this) * e1
;
356 ::evalue
to_evalue(const deque
<string
>& parameter_names
) const;
357 double to_double() const;
358 string
to_string() const;
359 inline operator string() const { return to_string(); }
360 bool contains_parameters() const;
362 /** subst_var substitutes variable @a var in the polynomial
363 with the expression encoded in @a subtitution.
364 @param subtitution is a affine function of variables
365 occuring in the polynomial, minus the substituted variable
368 EhrhartPolynom
subst_var(const string
& var
,
369 const map
<string
, int>& substitution
,
370 const int divisor
=1) const;
373 * equal_in_domain tries to find out if this polynomial and ep2 are
374 * equal in the domain. e.g. (n-i in domain i=1) and (i-1 in domain
375 * i=n) are equal (they both evaluate to n-1).
376 * @param ep1 the first Ehrhart polynomial.
377 * @param ep2 the second Ehrhart polynomial.
378 * @param domain1 the domain corresponding to ep1.
379 * @param domain2 the domain corresponding to ep2.
380 * @return a null pointer if the polynomials are not equal in the
381 * domain, otherwise a pointer to a simplified EhrhartPolynomial
382 * is returned. In the example above, n-1 would be returned.
384 static EhrhartPolynom
* equal_in_domain
385 (const EhrhartPolynom
& ep1
,
386 const EhrhartPolynom
& ep2
,
387 const ::Relation
& domain1
,
388 const ::Relation
& domain2
);
391 /** struct affine represents an Ehrhart Polynomial as a std::set of
392 * affine functions, if possible. This is only possible if the
393 * polynomial is univariate, with maximum power 1.
396 /** period indicates the period of the different parameters in
397 the Ehrhart polynomial. */
398 map
<string
,int> period
;
399 /** @c offset[i] contains the constraints under which @c polynomial[i]
400 and @c denumerator[i] are legal. e.g. when @c offset[i] equals
401 {("a",2),("b",0)} then @c polynomial[i] and @c denumerator[i] are
404 a \textrm{ mod \tt\ period[}a\textrm{\tt ] } = 2 \wedge
405 b \textrm{ mod \tt\ period[}b\textrm{\tt ] } = 0
408 deque
<map
<string
,int> > offset
;
409 /** @c polynomial[i] indicates the polynomial */
410 deque
<map
<string
,int> > polynomial
;
411 /** @c denumerator[i] indicates the denumerator, the polynomial should
413 deque
<int> denumerator
;
414 unsigned size() const {
415 assert(offset
.size()==polynomial
.size());
416 assert(denumerator
.size()==offset
.size());
417 return offset
.size();
419 string
to_string() const;
423 * get_affine_polynomials returns the Ehrhart polynomials as a std::set
424 * of affine functions when possible. If not possible, it returns
427 struct affine
* get_affine_polynomials() const;
430 * get_AST_representation returns an PolyAstNode representation of
434 /* KB november 2003: only usefull in PolyAST */
435 polyast::Expression
* get_AST_representation() const;
438 evalue
translate_one_term(const deque
<string
>& parameter_names
,
439 const deque
<string
>& left_over_var_names
,
440 const std::set
<map
<string
, int> >& terms
) const;