2 * Copyright 2010 INRIA Saclay
4 * Use of this software is governed by the GNU LGPLv2.1 license
6 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
7 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
11 #include <isl_polynomial_private.h>
12 #include <isl_point_private.h>
14 #include <isl_map_private.h>
18 static __isl_give isl_qpolynomial_fold
*qpolynomial_fold_alloc(
19 enum isl_fold type
, __isl_take isl_dim
*dim
, int n
)
21 isl_qpolynomial_fold
*fold
;
26 isl_assert(dim
->ctx
, n
>= 0, goto error
);
27 fold
= isl_alloc(dim
->ctx
, struct isl_qpolynomial_fold
,
28 sizeof(struct isl_qpolynomial_fold
) +
29 (n
- 1) * sizeof(struct isl_qpolynomial
*));
45 int isl_qpolynomial_fold_involves_dims(__isl_keep isl_qpolynomial_fold
*fold
,
46 enum isl_dim_type type
, unsigned first
, unsigned n
)
52 if (fold
->n
== 0 || n
== 0)
55 for (i
= 0; i
< fold
->n
; ++i
) {
56 int involves
= isl_qpolynomial_involves_dims(fold
->qp
[i
],
58 if (involves
< 0 || involves
)
64 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_drop_dims(
65 __isl_take isl_qpolynomial_fold
*fold
,
66 enum isl_dim_type type
, unsigned first
, unsigned n
)
75 fold
= isl_qpolynomial_fold_cow(fold
);
78 fold
->dim
= isl_dim_drop(fold
->dim
, type
, first
, n
);
82 for (i
= 0; i
< fold
->n
; ++i
) {
83 fold
->qp
[i
] = isl_qpolynomial_drop_dims(fold
->qp
[i
],
91 isl_qpolynomial_fold_free(fold
);
95 static int isl_qpolynomial_cst_sign(__isl_keep isl_qpolynomial
*qp
)
97 struct isl_upoly_cst
*cst
;
99 cst
= isl_upoly_as_cst(qp
->upoly
);
103 return isl_int_sgn(cst
->n
) < 0 ? -1 : 1;
106 static int isl_qpolynomial_aff_sign(__isl_keep isl_set
*set
,
107 __isl_keep isl_qpolynomial
*qp
)
109 enum isl_lp_result res
;
114 aff
= isl_qpolynomial_extract_affine(qp
);
120 res
= isl_set_solve_lp(set
, 0, aff
->el
+ 1, aff
->el
[0],
122 if (res
== isl_lp_error
)
124 if (res
== isl_lp_empty
||
125 (res
== isl_lp_ok
&& !isl_int_is_neg(opt
))) {
130 res
= isl_set_solve_lp(set
, 1, aff
->el
+ 1, aff
->el
[0],
132 if (res
== isl_lp_ok
&& !isl_int_is_pos(opt
))
141 /* Determine, if possible, the sign of the quasipolynomial "qp" on
144 * If qp is a constant, then the problem is trivial.
145 * If qp is linear, then we check if the minimum of the corresponding
146 * affine constraint is non-negative or if the maximum is non-positive.
148 * Otherwise, we check if the outermost variable "v" has a lower bound "l"
149 * in "set". If so, we write qp(v,v') as
151 * q(v,v') * (v - l) + r(v')
153 * if q(v,v') and r(v') have the same known sign, then the original
154 * quasipolynomial has the same sign as well.
161 static int isl_qpolynomial_sign(__isl_keep isl_set
*set
,
162 __isl_keep isl_qpolynomial
*qp
)
167 struct isl_upoly_rec
*rec
;
170 enum isl_lp_result res
;
173 is
= isl_qpolynomial_is_cst(qp
, NULL
, NULL
);
177 return isl_qpolynomial_cst_sign(qp
);
179 is
= isl_qpolynomial_is_affine(qp
);
183 return isl_qpolynomial_aff_sign(set
, qp
);
185 if (qp
->div
->n_row
> 0)
188 rec
= isl_upoly_as_rec(qp
->upoly
);
192 d
= isl_dim_total(qp
->dim
);
193 v
= isl_vec_alloc(set
->ctx
, 2 + d
);
197 isl_seq_clr(v
->el
+ 1, 1 + d
);
198 isl_int_set_si(v
->el
[0], 1);
199 isl_int_set_si(v
->el
[2 + qp
->upoly
->var
], 1);
203 res
= isl_set_solve_lp(set
, 0, v
->el
+ 1, v
->el
[0], &l
, NULL
, NULL
);
204 if (res
== isl_lp_ok
) {
205 isl_qpolynomial
*min
;
206 isl_qpolynomial
*base
;
207 isl_qpolynomial
*r
, *q
;
210 min
= isl_qpolynomial_cst(isl_dim_copy(qp
->dim
), l
);
211 base
= isl_qpolynomial_pow(isl_dim_copy(qp
->dim
),
214 r
= isl_qpolynomial_alloc(isl_dim_copy(qp
->dim
), 0,
215 isl_upoly_copy(rec
->p
[rec
->n
- 1]));
216 q
= isl_qpolynomial_copy(r
);
218 for (i
= rec
->n
- 2; i
>= 0; --i
) {
219 r
= isl_qpolynomial_mul(r
, isl_qpolynomial_copy(min
));
220 t
= isl_qpolynomial_alloc(isl_dim_copy(qp
->dim
), 0,
221 isl_upoly_copy(rec
->p
[i
]));
222 r
= isl_qpolynomial_add(r
, t
);
225 q
= isl_qpolynomial_mul(q
, isl_qpolynomial_copy(base
));
226 q
= isl_qpolynomial_add(q
, isl_qpolynomial_copy(r
));
229 if (isl_qpolynomial_is_zero(q
))
230 sgn
= isl_qpolynomial_sign(set
, r
);
231 else if (isl_qpolynomial_is_zero(r
))
232 sgn
= isl_qpolynomial_sign(set
, q
);
235 sgn_r
= isl_qpolynomial_sign(set
, r
);
236 sgn_q
= isl_qpolynomial_sign(set
, q
);
241 isl_qpolynomial_free(min
);
242 isl_qpolynomial_free(base
);
243 isl_qpolynomial_free(q
);
244 isl_qpolynomial_free(r
);
254 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_fold_on_domain(
255 __isl_keep isl_set
*set
,
256 __isl_take isl_qpolynomial_fold
*fold1
,
257 __isl_take isl_qpolynomial_fold
*fold2
)
261 struct isl_qpolynomial_fold
*res
= NULL
;
264 if (!fold1
|| !fold2
)
267 isl_assert(fold1
->dim
->ctx
, fold1
->type
== fold2
->type
, goto error
);
268 isl_assert(fold1
->dim
->ctx
, isl_dim_equal(fold1
->dim
, fold2
->dim
),
271 better
= fold1
->type
== isl_fold_max
? -1 : 1;
273 if (isl_qpolynomial_fold_is_empty(fold1
)) {
274 isl_qpolynomial_fold_free(fold1
);
278 if (isl_qpolynomial_fold_is_empty(fold2
)) {
279 isl_qpolynomial_fold_free(fold2
);
283 res
= qpolynomial_fold_alloc(fold1
->type
, isl_dim_copy(fold1
->dim
),
284 fold1
->n
+ fold2
->n
);
288 for (i
= 0; i
< fold1
->n
; ++i
) {
289 res
->qp
[res
->n
] = isl_qpolynomial_copy(fold1
->qp
[i
]);
290 if (!res
->qp
[res
->n
])
296 for (i
= 0; i
< fold2
->n
; ++i
) {
297 for (j
= n1
- 1; j
>= 0; --j
) {
300 d
= isl_qpolynomial_sub(
301 isl_qpolynomial_copy(res
->qp
[j
]),
302 isl_qpolynomial_copy(fold2
->qp
[i
]));
303 sgn
= isl_qpolynomial_sign(set
, d
);
304 isl_qpolynomial_free(d
);
309 isl_qpolynomial_free(res
->qp
[j
]);
311 res
->qp
[j
] = res
->qp
[n1
- 1];
313 if (n1
!= res
->n
- 1)
314 res
->qp
[n1
] = res
->qp
[res
->n
- 1];
319 res
->qp
[res
->n
] = isl_qpolynomial_copy(fold2
->qp
[i
]);
320 if (!res
->qp
[res
->n
])
325 isl_qpolynomial_fold_free(fold1
);
326 isl_qpolynomial_fold_free(fold2
);
330 isl_qpolynomial_fold_free(res
);
331 isl_qpolynomial_fold_free(fold1
);
332 isl_qpolynomial_fold_free(fold2
);
337 #define PW isl_pw_qpolynomial_fold
339 #define EL isl_qpolynomial_fold
341 #define IS_ZERO is_empty
345 #define ADD(d,e1,e2) isl_qpolynomial_fold_fold_on_domain(d,e1,e2)
347 #include <isl_pw_templ.c>
349 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_empty(enum isl_fold type
,
350 __isl_take isl_dim
*dim
)
352 return qpolynomial_fold_alloc(type
, dim
, 0);
355 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_alloc(
356 enum isl_fold type
, __isl_take isl_qpolynomial
*qp
)
358 isl_qpolynomial_fold
*fold
;
363 fold
= qpolynomial_fold_alloc(type
, isl_dim_copy(qp
->dim
), 1);
372 isl_qpolynomial_fold_free(fold
);
373 isl_qpolynomial_free(qp
);
377 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_copy(
378 __isl_keep isl_qpolynomial_fold
*fold
)
387 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_dup(
388 __isl_keep isl_qpolynomial_fold
*fold
)
391 isl_qpolynomial_fold
*dup
;
395 dup
= qpolynomial_fold_alloc(fold
->type
,
396 isl_dim_copy(fold
->dim
), fold
->n
);
400 for (i
= 0; i
< fold
->n
; ++i
) {
401 dup
->qp
[i
] = isl_qpolynomial_copy(fold
->qp
[i
]);
408 isl_qpolynomial_fold_free(dup
);
412 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_cow(
413 __isl_take isl_qpolynomial_fold
*fold
)
421 return isl_qpolynomial_fold_dup(fold
);
424 void isl_qpolynomial_fold_free(__isl_take isl_qpolynomial_fold
*fold
)
433 for (i
= 0; i
< fold
->n
; ++i
)
434 isl_qpolynomial_free(fold
->qp
[i
]);
435 isl_dim_free(fold
->dim
);
439 int isl_qpolynomial_fold_is_empty(__isl_keep isl_qpolynomial_fold
*fold
)
447 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_fold(
448 __isl_take isl_qpolynomial_fold
*fold1
,
449 __isl_take isl_qpolynomial_fold
*fold2
)
452 struct isl_qpolynomial_fold
*res
= NULL
;
454 if (!fold1
|| !fold2
)
457 isl_assert(fold1
->dim
->ctx
, fold1
->type
== fold2
->type
, goto error
);
458 isl_assert(fold1
->dim
->ctx
, isl_dim_equal(fold1
->dim
, fold2
->dim
),
461 if (isl_qpolynomial_fold_is_empty(fold1
)) {
462 isl_qpolynomial_fold_free(fold1
);
466 if (isl_qpolynomial_fold_is_empty(fold2
)) {
467 isl_qpolynomial_fold_free(fold2
);
471 res
= qpolynomial_fold_alloc(fold1
->type
, isl_dim_copy(fold1
->dim
),
472 fold1
->n
+ fold2
->n
);
476 for (i
= 0; i
< fold1
->n
; ++i
) {
477 res
->qp
[res
->n
] = isl_qpolynomial_copy(fold1
->qp
[i
]);
478 if (!res
->qp
[res
->n
])
483 for (i
= 0; i
< fold2
->n
; ++i
) {
484 res
->qp
[res
->n
] = isl_qpolynomial_copy(fold2
->qp
[i
]);
485 if (!res
->qp
[res
->n
])
490 isl_qpolynomial_fold_free(fold1
);
491 isl_qpolynomial_fold_free(fold2
);
495 isl_qpolynomial_fold_free(res
);
496 isl_qpolynomial_fold_free(fold1
);
497 isl_qpolynomial_fold_free(fold2
);
501 __isl_give isl_pw_qpolynomial_fold
*isl_pw_qpolynomial_fold_from_pw_qpolynomial(
502 enum isl_fold type
, __isl_take isl_pw_qpolynomial
*pwqp
)
505 isl_pw_qpolynomial_fold
*pwf
;
510 pwf
= isl_pw_qpolynomial_fold_alloc_(isl_dim_copy(pwqp
->dim
), pwqp
->n
);
512 for (i
= 0; i
< pwqp
->n
; ++i
)
513 pwf
= isl_pw_qpolynomial_fold_add_piece(pwf
,
514 isl_set_copy(pwqp
->p
[i
].set
),
515 isl_qpolynomial_fold_alloc(type
,
516 isl_qpolynomial_copy(pwqp
->p
[i
].qp
)));
518 isl_pw_qpolynomial_free(pwqp
);
523 int isl_qpolynomial_fold_is_equal(__isl_keep isl_qpolynomial_fold
*fold1
,
524 __isl_keep isl_qpolynomial_fold
*fold2
)
528 if (!fold1
|| !fold2
)
531 if (fold1
->n
!= fold2
->n
)
534 /* We probably want to sort the qps first... */
535 for (i
= 0; i
< fold1
->n
; ++i
) {
536 int eq
= isl_qpolynomial_is_equal(fold1
->qp
[i
], fold2
->qp
[i
]);
544 __isl_give isl_qpolynomial
*isl_qpolynomial_fold_eval(
545 __isl_take isl_qpolynomial_fold
*fold
, __isl_take isl_point
*pnt
)
551 isl_assert(pnt
->dim
->ctx
, isl_dim_equal(pnt
->dim
, fold
->dim
), goto error
);
552 isl_assert(pnt
->dim
->ctx
,
553 fold
->type
== isl_fold_max
|| fold
->type
== isl_fold_min
,
557 qp
= isl_qpolynomial_zero(isl_dim_copy(fold
->dim
));
560 qp
= isl_qpolynomial_eval(isl_qpolynomial_copy(fold
->qp
[0]),
561 isl_point_copy(pnt
));
562 for (i
= 1; i
< fold
->n
; ++i
) {
563 isl_qpolynomial
*qp_i
;
564 qp_i
= isl_qpolynomial_eval(
565 isl_qpolynomial_copy(fold
->qp
[i
]),
566 isl_point_copy(pnt
));
567 if (fold
->type
== isl_fold_max
)
568 qp
= isl_qpolynomial_max_cst(qp
, qp_i
);
570 qp
= isl_qpolynomial_min_cst(qp
, qp_i
);
573 isl_qpolynomial_fold_free(fold
);
578 isl_qpolynomial_fold_free(fold
);
583 size_t isl_pw_qpolynomial_fold_size(__isl_keep isl_pw_qpolynomial_fold
*pwf
)
588 for (i
= 0; i
< pwf
->n
; ++i
)
589 n
+= pwf
->p
[i
].fold
->n
;
594 __isl_give isl_qpolynomial
*isl_qpolynomial_fold_opt_on_domain(
595 __isl_take isl_qpolynomial_fold
*fold
, __isl_take isl_set
*set
, int max
)
598 isl_qpolynomial
*opt
;
604 isl_dim
*dim
= isl_dim_copy(fold
->dim
);
606 isl_qpolynomial_fold_free(fold
);
607 return isl_qpolynomial_zero(dim
);
610 opt
= isl_qpolynomial_opt_on_domain(isl_qpolynomial_copy(fold
->qp
[0]),
611 isl_set_copy(set
), max
);
612 for (i
= 1; i
< fold
->n
; ++i
) {
613 isl_qpolynomial
*opt_i
;
614 opt_i
= isl_qpolynomial_opt_on_domain(
615 isl_qpolynomial_copy(fold
->qp
[i
]),
616 isl_set_copy(set
), max
);
618 opt
= isl_qpolynomial_max_cst(opt
, opt_i
);
620 opt
= isl_qpolynomial_min_cst(opt
, opt_i
);
624 isl_qpolynomial_fold_free(fold
);
629 isl_qpolynomial_fold_free(fold
);