10 static int lex_cmp(vec_ZZ
& a
, vec_ZZ
& b
)
12 assert(a
.length() == b
.length());
14 for (int j
= 0; j
< a
.length(); ++j
)
16 return a
[j
] < b
[j
] ? -1 : 1;
20 static int lex_cmp(mat_ZZ
& a
, mat_ZZ
& b
)
22 assert(a
.NumCols() == b
.NumCols());
23 int alen
= a
.NumRows();
24 int blen
= b
.NumRows();
25 int len
= alen
< blen
? alen
: blen
;
27 for (int i
= 0; i
< len
; ++i
) {
28 int s
= lex_cmp(a
[i
], b
[i
]);
35 void gen_fun::add(const ZZ
& cn
, const ZZ
& cd
, const vec_ZZ
& num
,
41 short_rat
* r
= new short_rat
;
42 r
->n
.coeff
.SetDims(1, 2);
43 r
->n
.coeff
[0][0] = cn
;
44 r
->n
.coeff
[0][1] = cd
;
45 r
->n
.power
.SetDims(1, num
.length());
49 /* Make all powers in denominator lexico-positive */
50 for (int i
= 0; i
< r
->d
.power
.NumRows(); ++i
) {
52 for (j
= 0; j
< r
->d
.power
.NumCols(); ++j
)
53 if (r
->d
.power
[i
][j
] != 0)
55 if (r
->d
.power
[i
][j
] < 0) {
56 r
->d
.power
[i
] = -r
->d
.power
[i
];
57 r
->n
.coeff
[0][0] = -r
->n
.coeff
[0][0];
58 r
->n
.power
[0] += r
->d
.power
[i
];
62 /* Order powers in denominator */
63 for (int i
= 0; i
< r
->d
.power
.NumRows(); ++i
) {
65 for (int j
= i
+1; j
< r
->d
.power
.NumRows(); ++j
)
66 if (lex_cmp(r
->d
.power
[j
], r
->d
.power
[m
]) < 0)
69 vec_ZZ tmp
= r
->d
.power
[m
];
70 r
->d
.power
[m
] = r
->d
.power
[i
];
75 for (int i
= 0; i
< term
.size(); ++i
)
76 if (lex_cmp(term
[i
]->d
.power
, r
->d
.power
) == 0) {
77 int len
= term
[i
]->n
.coeff
.NumRows();
79 for (j
= 0; j
< len
; ++j
)
80 if (r
->n
.power
[0] == term
[i
]->n
.power
[j
])
83 ZZ g
= GCD(r
->n
.coeff
[0][1], term
[i
]->n
.coeff
[j
][1]);
84 ZZ n
= term
[i
]->n
.coeff
[j
][0] * (r
->n
.coeff
[0][1] / g
) +
85 (term
[i
]->n
.coeff
[j
][1] / g
) * r
->n
.coeff
[0][0];
86 ZZ d
= term
[i
]->n
.coeff
[j
][1] / g
* r
->n
.coeff
[0][1];
88 term
[i
]->n
.coeff
[j
][0] = n
;
89 term
[i
]->n
.coeff
[j
][1] = d
;
93 term
[i
]->n
.power
[j
] = term
[i
]->n
.power
[len
-1];
94 term
[i
]->n
.coeff
[j
] = term
[i
]->n
.coeff
[len
-1];
96 int dim
= term
[i
]->n
.power
.NumCols();
97 term
[i
]->n
.coeff
.SetDims(len
-1, 2);
98 term
[i
]->n
.power
.SetDims(len
-1, dim
);
101 if (i
!= term
.size()-1)
102 term
[i
] = term
[term
.size()-1];
107 int dim
= term
[i
]->n
.power
.NumCols();
108 term
[i
]->n
.coeff
.SetDims(len
+1, 2);
109 term
[i
]->n
.power
.SetDims(len
+1, dim
);
110 term
[i
]->n
.coeff
[len
] = r
->n
.coeff
[0];
111 term
[i
]->n
.power
[len
] = r
->n
.power
[0];
120 static void print_power(vec_ZZ
& c
, vec_ZZ
& p
,
121 unsigned int nparam
, char **param_name
)
125 for (int i
= 0; i
< p
.length(); ++i
) {
129 if (c
[0] == -1 && c
[1] == 1)
131 else if (c
[0] != 1 || c
[1] != 1) {
134 cout
<< " / " << c
[1];
141 cout
<< param_name
[i
];
147 cout
<< "^(" << p
[i
] << ")";
154 cout
<< " / " << c
[1];
158 void gen_fun::print(unsigned int nparam
, char **param_name
) const
164 for (int i
= 0; i
< term
.size(); ++i
) {
168 for (int j
= 0; j
< term
[i
]->n
.coeff
.NumRows(); ++j
) {
169 if (j
!= 0 && term
[i
]->n
.coeff
[j
][0] > 0)
171 print_power(term
[i
]->n
.coeff
[j
], term
[i
]->n
.power
[j
],
175 for (int j
= 0; j
< term
[i
]->d
.power
.NumRows(); ++j
) {
179 print_power(mone
, term
[i
]->d
.power
[j
],
187 gen_fun::operator evalue
*() const
191 value_init(factor
.d
);
192 value_init(factor
.x
.n
);
193 for (int i
= 0; i
< term
.size(); ++i
) {
194 unsigned nvar
= term
[i
]->d
.power
.NumRows();
195 unsigned nparam
= term
[i
]->d
.power
.NumCols();
196 Matrix
*C
= Matrix_Alloc(nparam
+ nvar
, 1 + nvar
+ nparam
+ 1);
197 mat_ZZ
& d
= term
[i
]->d
.power
;
198 Polyhedron
*U
= context
? context
: Universe_Polyhedron(nparam
);
200 for (int j
= 0; j
< term
[i
]->n
.coeff
.NumRows(); ++j
) {
201 for (int r
= 0; r
< nparam
; ++r
) {
202 value_set_si(C
->p
[r
][0], 0);
203 for (int c
= 0; c
< nvar
; ++c
) {
204 zz2value(d
[c
][r
], C
->p
[r
][1+c
]);
206 Vector_Set(&C
->p
[r
][1+nvar
], 0, nparam
);
207 value_set_si(C
->p
[r
][1+nvar
+r
], -1);
208 zz2value(term
[i
]->n
.power
[j
][r
], C
->p
[r
][1+nvar
+nparam
]);
210 for (int r
= 0; r
< nvar
; ++r
) {
211 value_set_si(C
->p
[nparam
+r
][0], 1);
212 Vector_Set(&C
->p
[nparam
+r
][1], 0, nvar
+ nparam
+ 1);
213 value_set_si(C
->p
[nparam
+r
][1+r
], 1);
215 Polyhedron
*P
= Constraints2Polyhedron(C
, 0);
216 evalue
*E
= barvinok_enumerate_ev(P
, U
, 0);
218 if (EVALUE_IS_ZERO(*E
))
220 zz2value(term
[i
]->n
.coeff
[j
][0], factor
.x
.n
);
221 zz2value(term
[i
]->n
.coeff
[j
][1], factor
.d
);
224 Matrix_Print(stdout, P_VALUE_FMT, C);
225 char *test[] = { "A", "B", "C", "D", "E", "F", "G" };
226 print_evalue(stdout, E, test);
239 value_clear(factor
.d
);
240 value_clear(factor
.x
.n
);
244 void gen_fun::coefficient(Value
* params
, Value
* c
) const
246 if (context
&& !in_domain(context
, params
)) {
253 value_init(part
.x
.n
);
256 evalue_set_si(&sum
, 0, 1);
260 for (int i
= 0; i
< term
.size(); ++i
) {
261 unsigned nvar
= term
[i
]->d
.power
.NumRows();
262 unsigned nparam
= term
[i
]->d
.power
.NumCols();
263 Matrix
*C
= Matrix_Alloc(nparam
+ nvar
, 1 + nvar
+ 1);
264 mat_ZZ
& d
= term
[i
]->d
.power
;
266 for (int j
= 0; j
< term
[i
]->n
.coeff
.NumRows(); ++j
) {
267 for (int r
= 0; r
< nparam
; ++r
) {
268 value_set_si(C
->p
[r
][0], 0);
269 for (int c
= 0; c
< nvar
; ++c
) {
270 zz2value(d
[c
][r
], C
->p
[r
][1+c
]);
272 zz2value(term
[i
]->n
.power
[j
][r
], C
->p
[r
][1+nvar
]);
273 value_subtract(C
->p
[r
][1+nvar
], C
->p
[r
][1+nvar
], params
[r
]);
275 for (int r
= 0; r
< nvar
; ++r
) {
276 value_set_si(C
->p
[nparam
+r
][0], 1);
277 Vector_Set(&C
->p
[nparam
+r
][1], 0, nvar
+ 1);
278 value_set_si(C
->p
[nparam
+r
][1+r
], 1);
280 Polyhedron
*P
= Constraints2Polyhedron(C
, 0);
285 barvinok_count(P
, &tmp
, 0);
287 if (value_zero_p(tmp
))
289 zz2value(term
[i
]->n
.coeff
[j
][0], part
.x
.n
);
290 zz2value(term
[i
]->n
.coeff
[j
][1], part
.d
);
291 value_multiply(part
.x
.n
, part
.x
.n
, tmp
);
297 assert(value_one_p(sum
.d
));
298 value_assign(*c
, sum
.x
.n
);
302 value_clear(part
.x
.n
);
304 value_clear(sum
.x
.n
);