4 #include <barvinok/genfun.h>
5 #include <barvinok/barvinok.h>
9 static int lex_cmp(vec_ZZ
& a
, vec_ZZ
& b
)
11 assert(a
.length() == b
.length());
13 for (int j
= 0; j
< a
.length(); ++j
)
15 return a
[j
] < b
[j
] ? -1 : 1;
19 static int lex_cmp(mat_ZZ
& a
, mat_ZZ
& b
)
21 assert(a
.NumCols() == b
.NumCols());
22 int alen
= a
.NumRows();
23 int blen
= b
.NumRows();
24 int len
= alen
< blen
? alen
: blen
;
26 for (int i
= 0; i
< len
; ++i
) {
27 int s
= lex_cmp(a
[i
], b
[i
]);
34 void gen_fun::add(const ZZ
& cn
, const ZZ
& cd
, const vec_ZZ
& num
,
40 short_rat
* r
= new short_rat
;
41 r
->n
.coeff
.SetDims(1, 2);
42 r
->n
.coeff
[0][0] = cn
;
43 r
->n
.coeff
[0][1] = cd
;
44 r
->n
.power
.SetDims(1, num
.length());
48 /* Make all powers in denominator lexico-positive */
49 for (int i
= 0; i
< r
->d
.power
.NumRows(); ++i
) {
51 for (j
= 0; j
< r
->d
.power
.NumCols(); ++j
)
52 if (r
->d
.power
[i
][j
] != 0)
54 if (r
->d
.power
[i
][j
] < 0) {
55 r
->d
.power
[i
] = -r
->d
.power
[i
];
56 r
->n
.coeff
[0][0] = -r
->n
.coeff
[0][0];
57 r
->n
.power
[0] += r
->d
.power
[i
];
61 /* Order powers in denominator */
62 for (int i
= 0; i
< r
->d
.power
.NumRows(); ++i
) {
64 for (int j
= i
+1; j
< r
->d
.power
.NumRows(); ++j
)
65 if (lex_cmp(r
->d
.power
[j
], r
->d
.power
[m
]) < 0)
68 vec_ZZ tmp
= r
->d
.power
[m
];
69 r
->d
.power
[m
] = r
->d
.power
[i
];
74 for (int i
= 0; i
< term
.size(); ++i
)
75 if (lex_cmp(term
[i
]->d
.power
, r
->d
.power
) == 0) {
76 int len
= term
[i
]->n
.coeff
.NumRows();
78 for (j
= 0; j
< len
; ++j
)
79 if (r
->n
.power
[0] == term
[i
]->n
.power
[j
])
82 ZZ g
= GCD(r
->n
.coeff
[0][1], term
[i
]->n
.coeff
[j
][1]);
83 ZZ n
= term
[i
]->n
.coeff
[j
][0] * (r
->n
.coeff
[0][1] / g
) +
84 (term
[i
]->n
.coeff
[j
][1] / g
) * r
->n
.coeff
[0][0];
85 ZZ d
= term
[i
]->n
.coeff
[j
][1] / g
* r
->n
.coeff
[0][1];
87 term
[i
]->n
.coeff
[j
][0] = n
;
88 term
[i
]->n
.coeff
[j
][1] = d
;
92 term
[i
]->n
.power
[j
] = term
[i
]->n
.power
[len
-1];
93 term
[i
]->n
.coeff
[j
] = term
[i
]->n
.coeff
[len
-1];
95 int dim
= term
[i
]->n
.power
.NumCols();
96 term
[i
]->n
.coeff
.SetDims(len
-1, 2);
97 term
[i
]->n
.power
.SetDims(len
-1, dim
);
100 if (i
!= term
.size()-1)
101 term
[i
] = term
[term
.size()-1];
106 int dim
= term
[i
]->n
.power
.NumCols();
107 term
[i
]->n
.coeff
.SetDims(len
+1, 2);
108 term
[i
]->n
.power
.SetDims(len
+1, dim
);
109 term
[i
]->n
.coeff
[len
] = r
->n
.coeff
[0];
110 term
[i
]->n
.power
[len
] = r
->n
.power
[0];
119 static void print_power(vec_ZZ
& c
, vec_ZZ
& p
,
120 unsigned int nparam
, char **param_name
)
124 for (int i
= 0; i
< p
.length(); ++i
) {
128 if (c
[0] == -1 && c
[1] == 1)
130 else if (c
[0] != 1 || c
[1] != 1) {
133 cout
<< " / " << c
[1];
140 cout
<< param_name
[i
];
146 cout
<< "^(" << p
[i
] << ")";
153 cout
<< " / " << c
[1];
157 void gen_fun::print(unsigned int nparam
, char **param_name
) const
163 for (int i
= 0; i
< term
.size(); ++i
) {
167 for (int j
= 0; j
< term
[i
]->n
.coeff
.NumRows(); ++j
) {
168 if (j
!= 0 && term
[i
]->n
.coeff
[j
][0] > 0)
170 print_power(term
[i
]->n
.coeff
[j
], term
[i
]->n
.power
[j
],
174 for (int j
= 0; j
< term
[i
]->d
.power
.NumRows(); ++j
) {
178 print_power(mone
, term
[i
]->d
.power
[j
],
186 gen_fun::operator evalue
*() const
190 value_init(factor
.d
);
191 value_init(factor
.x
.n
);
192 for (int i
= 0; i
< term
.size(); ++i
) {
193 unsigned nvar
= term
[i
]->d
.power
.NumRows();
194 unsigned nparam
= term
[i
]->d
.power
.NumCols();
195 Matrix
*C
= Matrix_Alloc(nparam
+ nvar
, 1 + nvar
+ nparam
+ 1);
196 mat_ZZ
& d
= term
[i
]->d
.power
;
197 Polyhedron
*U
= context
? context
: Universe_Polyhedron(nparam
);
199 for (int j
= 0; j
< term
[i
]->n
.coeff
.NumRows(); ++j
) {
200 for (int r
= 0; r
< nparam
; ++r
) {
201 value_set_si(C
->p
[r
][0], 0);
202 for (int c
= 0; c
< nvar
; ++c
) {
203 zz2value(d
[c
][r
], C
->p
[r
][1+c
]);
205 Vector_Set(&C
->p
[r
][1+nvar
], 0, nparam
);
206 value_set_si(C
->p
[r
][1+nvar
+r
], -1);
207 zz2value(term
[i
]->n
.power
[j
][r
], C
->p
[r
][1+nvar
+nparam
]);
209 for (int r
= 0; r
< nvar
; ++r
) {
210 value_set_si(C
->p
[nparam
+r
][0], 1);
211 Vector_Set(&C
->p
[nparam
+r
][1], 0, nvar
+ nparam
+ 1);
212 value_set_si(C
->p
[nparam
+r
][1+r
], 1);
214 Polyhedron
*P
= Constraints2Polyhedron(C
, 0);
215 evalue
*E
= barvinok_enumerate_ev(P
, U
, 0);
217 if (EVALUE_IS_ZERO(*E
))
219 zz2value(term
[i
]->n
.coeff
[j
][0], factor
.x
.n
);
220 zz2value(term
[i
]->n
.coeff
[j
][1], factor
.d
);
223 Matrix_Print(stdout, P_VALUE_FMT, C);
224 char *test[] = { "A", "B", "C", "D", "E", "F", "G" };
225 print_evalue(stdout, E, test);
238 value_clear(factor
.d
);
239 value_clear(factor
.x
.n
);
243 void gen_fun::coefficient(Value
* params
, Value
* c
) const
245 if (context
&& !in_domain(context
, params
)) {
252 value_init(part
.x
.n
);
255 evalue_set_si(&sum
, 0, 1);
259 for (int i
= 0; i
< term
.size(); ++i
) {
260 unsigned nvar
= term
[i
]->d
.power
.NumRows();
261 unsigned nparam
= term
[i
]->d
.power
.NumCols();
262 Matrix
*C
= Matrix_Alloc(nparam
+ nvar
, 1 + nvar
+ 1);
263 mat_ZZ
& d
= term
[i
]->d
.power
;
265 for (int j
= 0; j
< term
[i
]->n
.coeff
.NumRows(); ++j
) {
266 for (int r
= 0; r
< nparam
; ++r
) {
267 value_set_si(C
->p
[r
][0], 0);
268 for (int c
= 0; c
< nvar
; ++c
) {
269 zz2value(d
[c
][r
], C
->p
[r
][1+c
]);
271 zz2value(term
[i
]->n
.power
[j
][r
], C
->p
[r
][1+nvar
]);
272 value_subtract(C
->p
[r
][1+nvar
], C
->p
[r
][1+nvar
], params
[r
]);
274 for (int r
= 0; r
< nvar
; ++r
) {
275 value_set_si(C
->p
[nparam
+r
][0], 1);
276 Vector_Set(&C
->p
[nparam
+r
][1], 0, nvar
+ 1);
277 value_set_si(C
->p
[nparam
+r
][1+r
], 1);
279 Polyhedron
*P
= Constraints2Polyhedron(C
, 0);
284 barvinok_count(P
, &tmp
, 0);
286 if (value_zero_p(tmp
))
288 zz2value(term
[i
]->n
.coeff
[j
][0], part
.x
.n
);
289 zz2value(term
[i
]->n
.coeff
[j
][1], part
.d
);
290 value_multiply(part
.x
.n
, part
.x
.n
, tmp
);
296 assert(value_one_p(sum
.d
));
297 value_assign(*c
, sum
.x
.n
);
301 value_clear(part
.x
.n
);
303 value_clear(sum
.x
.n
);