brintos

brintos / llvm-project-archived public Read only

0
0
Text · 114.1 KiB · 7b4eae0 Raw
5232 lines · c
1/*2 * Copyright 2010      INRIA Saclay3 *4 * Use of this software is governed by the MIT license5 *6 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,7 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,8 * 91893 Orsay, France 9 */10 11#include <stdlib.h>12#include <isl_ctx_private.h>13#include <isl_map_private.h>14#include <isl_factorization.h>15#include <isl_lp_private.h>16#include <isl_seq.h>17#include <isl_union_map_private.h>18#include <isl_constraint_private.h>19#include <isl_polynomial_private.h>20#include <isl_point_private.h>21#include <isl_space_private.h>22#include <isl_mat_private.h>23#include <isl_vec_private.h>24#include <isl_range.h>25#include <isl_local.h>26#include <isl_local_space_private.h>27#include <isl_aff_private.h>28#include <isl_val_private.h>29#include <isl_config.h>30 31#undef EL_BASE32#define EL_BASE qpolynomial33 34#include <isl_list_templ.c>35 36#undef EL_BASE37#define EL_BASE pw_qpolynomial38 39#include <isl_list_templ.c>40 41static unsigned pos(__isl_keep isl_space *space, enum isl_dim_type type)42{43	switch (type) {44	case isl_dim_param:	return 0;45	case isl_dim_in:	return space->nparam;46	case isl_dim_out:	return space->nparam + space->n_in;47	default:		return 0;48	}49}50 51isl_bool isl_poly_is_cst(__isl_keep isl_poly *poly)52{53	if (!poly)54		return isl_bool_error;55 56	return isl_bool_ok(poly->var < 0);57}58 59__isl_keep isl_poly_cst *isl_poly_as_cst(__isl_keep isl_poly *poly)60{61	if (!poly)62		return NULL;63 64	isl_assert(poly->ctx, poly->var < 0, return NULL);65 66	return (isl_poly_cst *) poly;67}68 69__isl_keep isl_poly_rec *isl_poly_as_rec(__isl_keep isl_poly *poly)70{71	if (!poly)72		return NULL;73 74	isl_assert(poly->ctx, poly->var >= 0, return NULL);75 76	return (isl_poly_rec *) poly;77}78 79/* Compare two polynomials.80 *81 * Return -1 if "poly1" is "smaller" than "poly2", 1 if "poly1" is "greater"82 * than "poly2" and 0 if they are equal.83 */84static int isl_poly_plain_cmp(__isl_keep isl_poly *poly1,85	__isl_keep isl_poly *poly2)86{87	int i;88	isl_bool is_cst1;89	isl_poly_rec *rec1, *rec2;90 91	if (poly1 == poly2)92		return 0;93	is_cst1 = isl_poly_is_cst(poly1);94	if (is_cst1 < 0)95		return -1;96	if (!poly2)97		return 1;98	if (poly1->var != poly2->var)99		return poly1->var - poly2->var;100 101	if (is_cst1) {102		isl_poly_cst *cst1, *cst2;103		int cmp;104 105		cst1 = isl_poly_as_cst(poly1);106		cst2 = isl_poly_as_cst(poly2);107		if (!cst1 || !cst2)108			return 0;109		cmp = isl_int_cmp(cst1->n, cst2->n);110		if (cmp != 0)111			return cmp;112		return isl_int_cmp(cst1->d, cst2->d);113	}114 115	rec1 = isl_poly_as_rec(poly1);116	rec2 = isl_poly_as_rec(poly2);117	if (!rec1 || !rec2)118		return 0;119 120	if (rec1->n != rec2->n)121		return rec1->n - rec2->n;122 123	for (i = 0; i < rec1->n; ++i) {124		int cmp = isl_poly_plain_cmp(rec1->p[i], rec2->p[i]);125		if (cmp != 0)126			return cmp;127	}128 129	return 0;130}131 132isl_bool isl_poly_is_equal(__isl_keep isl_poly *poly1,133	__isl_keep isl_poly *poly2)134{135	int i;136	isl_bool is_cst1;137	isl_poly_rec *rec1, *rec2;138 139	is_cst1 = isl_poly_is_cst(poly1);140	if (is_cst1 < 0 || !poly2)141		return isl_bool_error;142	if (poly1 == poly2)143		return isl_bool_true;144	if (poly1->var != poly2->var)145		return isl_bool_false;146	if (is_cst1) {147		isl_poly_cst *cst1, *cst2;148		int r;149		cst1 = isl_poly_as_cst(poly1);150		cst2 = isl_poly_as_cst(poly2);151		if (!cst1 || !cst2)152			return isl_bool_error;153		r = isl_int_eq(cst1->n, cst2->n) &&154		    isl_int_eq(cst1->d, cst2->d);155		return isl_bool_ok(r);156	}157 158	rec1 = isl_poly_as_rec(poly1);159	rec2 = isl_poly_as_rec(poly2);160	if (!rec1 || !rec2)161		return isl_bool_error;162 163	if (rec1->n != rec2->n)164		return isl_bool_false;165 166	for (i = 0; i < rec1->n; ++i) {167		isl_bool eq = isl_poly_is_equal(rec1->p[i], rec2->p[i]);168		if (eq < 0 || !eq)169			return eq;170	}171 172	return isl_bool_true;173}174 175isl_bool isl_poly_is_zero(__isl_keep isl_poly *poly)176{177	isl_bool is_cst;178	isl_poly_cst *cst;179 180	is_cst = isl_poly_is_cst(poly);181	if (is_cst < 0 || !is_cst)182		return is_cst;183 184	cst = isl_poly_as_cst(poly);185	if (!cst)186		return isl_bool_error;187 188	return isl_bool_ok(isl_int_is_zero(cst->n) && isl_int_is_pos(cst->d));189}190 191int isl_poly_sgn(__isl_keep isl_poly *poly)192{193	isl_bool is_cst;194	isl_poly_cst *cst;195 196	is_cst = isl_poly_is_cst(poly);197	if (is_cst < 0 || !is_cst)198		return 0;199 200	cst = isl_poly_as_cst(poly);201	if (!cst)202		return 0;203 204	return isl_int_sgn(cst->n);205}206 207isl_bool isl_poly_is_nan(__isl_keep isl_poly *poly)208{209	isl_bool is_cst;210	isl_poly_cst *cst;211 212	is_cst = isl_poly_is_cst(poly);213	if (is_cst < 0 || !is_cst)214		return is_cst;215 216	cst = isl_poly_as_cst(poly);217	if (!cst)218		return isl_bool_error;219 220	return isl_bool_ok(isl_int_is_zero(cst->n) && isl_int_is_zero(cst->d));221}222 223isl_bool isl_poly_is_infty(__isl_keep isl_poly *poly)224{225	isl_bool is_cst;226	isl_poly_cst *cst;227 228	is_cst = isl_poly_is_cst(poly);229	if (is_cst < 0 || !is_cst)230		return is_cst;231 232	cst = isl_poly_as_cst(poly);233	if (!cst)234		return isl_bool_error;235 236	return isl_bool_ok(isl_int_is_pos(cst->n) && isl_int_is_zero(cst->d));237}238 239isl_bool isl_poly_is_neginfty(__isl_keep isl_poly *poly)240{241	isl_bool is_cst;242	isl_poly_cst *cst;243 244	is_cst = isl_poly_is_cst(poly);245	if (is_cst < 0 || !is_cst)246		return is_cst;247 248	cst = isl_poly_as_cst(poly);249	if (!cst)250		return isl_bool_error;251 252	return isl_bool_ok(isl_int_is_neg(cst->n) && isl_int_is_zero(cst->d));253}254 255isl_bool isl_poly_is_one(__isl_keep isl_poly *poly)256{257	isl_bool is_cst;258	isl_poly_cst *cst;259	int r;260 261	is_cst = isl_poly_is_cst(poly);262	if (is_cst < 0 || !is_cst)263		return is_cst;264 265	cst = isl_poly_as_cst(poly);266	if (!cst)267		return isl_bool_error;268 269	r = isl_int_eq(cst->n, cst->d) && isl_int_is_pos(cst->d);270	return isl_bool_ok(r);271}272 273isl_bool isl_poly_is_negone(__isl_keep isl_poly *poly)274{275	isl_bool is_cst;276	isl_poly_cst *cst;277 278	is_cst = isl_poly_is_cst(poly);279	if (is_cst < 0 || !is_cst)280		return is_cst;281 282	cst = isl_poly_as_cst(poly);283	if (!cst)284		return isl_bool_error;285 286	return isl_bool_ok(isl_int_is_negone(cst->n) && isl_int_is_one(cst->d));287}288 289__isl_give isl_poly_cst *isl_poly_cst_alloc(isl_ctx *ctx)290{291	isl_poly_cst *cst;292 293	cst = isl_alloc_type(ctx, struct isl_poly_cst);294	if (!cst)295		return NULL;296 297	cst->poly.ref = 1;298	cst->poly.ctx = ctx;299	isl_ctx_ref(ctx);300	cst->poly.var = -1;301 302	isl_int_init(cst->n);303	isl_int_init(cst->d);304 305	return cst;306}307 308__isl_give isl_poly *isl_poly_zero(isl_ctx *ctx)309{310	isl_poly_cst *cst;311 312	cst = isl_poly_cst_alloc(ctx);313	if (!cst)314		return NULL;315 316	isl_int_set_si(cst->n, 0);317	isl_int_set_si(cst->d, 1);318 319	return &cst->poly;320}321 322__isl_give isl_poly *isl_poly_one(isl_ctx *ctx)323{324	isl_poly_cst *cst;325 326	cst = isl_poly_cst_alloc(ctx);327	if (!cst)328		return NULL;329 330	isl_int_set_si(cst->n, 1);331	isl_int_set_si(cst->d, 1);332 333	return &cst->poly;334}335 336__isl_give isl_poly *isl_poly_infty(isl_ctx *ctx)337{338	isl_poly_cst *cst;339 340	cst = isl_poly_cst_alloc(ctx);341	if (!cst)342		return NULL;343 344	isl_int_set_si(cst->n, 1);345	isl_int_set_si(cst->d, 0);346 347	return &cst->poly;348}349 350__isl_give isl_poly *isl_poly_neginfty(isl_ctx *ctx)351{352	isl_poly_cst *cst;353 354	cst = isl_poly_cst_alloc(ctx);355	if (!cst)356		return NULL;357 358	isl_int_set_si(cst->n, -1);359	isl_int_set_si(cst->d, 0);360 361	return &cst->poly;362}363 364__isl_give isl_poly *isl_poly_nan(isl_ctx *ctx)365{366	isl_poly_cst *cst;367 368	cst = isl_poly_cst_alloc(ctx);369	if (!cst)370		return NULL;371 372	isl_int_set_si(cst->n, 0);373	isl_int_set_si(cst->d, 0);374 375	return &cst->poly;376}377 378__isl_give isl_poly *isl_poly_rat_cst(isl_ctx *ctx, isl_int n, isl_int d)379{380	isl_poly_cst *cst;381 382	cst = isl_poly_cst_alloc(ctx);383	if (!cst)384		return NULL;385 386	isl_int_set(cst->n, n);387	isl_int_set(cst->d, d);388 389	return &cst->poly;390}391 392__isl_give isl_poly_rec *isl_poly_alloc_rec(isl_ctx *ctx, int var, int size)393{394	isl_poly_rec *rec;395 396	isl_assert(ctx, var >= 0, return NULL);397	isl_assert(ctx, size >= 0, return NULL);398	rec = isl_calloc(ctx, struct isl_poly_rec,399			sizeof(struct isl_poly_rec) +400			size * sizeof(struct isl_poly *));401	if (!rec)402		return NULL;403 404	rec->poly.ref = 1;405	rec->poly.ctx = ctx;406	isl_ctx_ref(ctx);407	rec->poly.var = var;408 409	rec->n = 0;410	rec->size = size;411 412	return rec;413}414 415__isl_give isl_qpolynomial *isl_qpolynomial_reset_domain_space(416	__isl_take isl_qpolynomial *qp, __isl_take isl_space *space)417{418	qp = isl_qpolynomial_cow(qp);419	if (!qp || !space)420		goto error;421 422	isl_space_free(qp->dim);423	qp->dim = space;424 425	return qp;426error:427	isl_qpolynomial_free(qp);428	isl_space_free(space);429	return NULL;430}431 432/* Reset the space of "qp".  This function is called from isl_pw_templ.c433 * and doesn't know if the space of an element object is represented434 * directly or through its domain.  It therefore passes along both.435 */436__isl_give isl_qpolynomial *isl_qpolynomial_reset_space_and_domain(437	__isl_take isl_qpolynomial *qp, __isl_take isl_space *space,438	__isl_take isl_space *domain)439{440	isl_space_free(space);441	return isl_qpolynomial_reset_domain_space(qp, domain);442}443 444isl_ctx *isl_qpolynomial_get_ctx(__isl_keep isl_qpolynomial *qp)445{446	return qp ? qp->dim->ctx : NULL;447}448 449/* Return the domain space of "qp".450 */451static __isl_keep isl_space *isl_qpolynomial_peek_domain_space(452	__isl_keep isl_qpolynomial *qp)453{454	return qp ? qp->dim : NULL;455}456 457/* Return a copy of the domain space of "qp".458 */459__isl_give isl_space *isl_qpolynomial_get_domain_space(460	__isl_keep isl_qpolynomial *qp)461{462	return isl_space_copy(isl_qpolynomial_peek_domain_space(qp));463}464 465#undef TYPE466#define TYPE		isl_qpolynomial467#undef PEEK_SPACE468#define PEEK_SPACE	peek_domain_space469 470static471#include "isl_type_has_equal_space_bin_templ.c"472static473#include "isl_type_check_equal_space_templ.c"474 475#undef PEEK_SPACE476 477/* Return a copy of the local space on which "qp" is defined.478 */479static __isl_give isl_local_space *isl_qpolynomial_get_domain_local_space(480	__isl_keep isl_qpolynomial *qp)481{482	isl_space *space;483 484	if (!qp)485		return NULL;486 487	space = isl_qpolynomial_get_domain_space(qp);488	return isl_local_space_alloc_div(space, isl_mat_copy(qp->div));489}490 491__isl_give isl_space *isl_qpolynomial_get_space(__isl_keep isl_qpolynomial *qp)492{493	isl_space *space;494	if (!qp)495		return NULL;496	space = isl_space_copy(qp->dim);497	space = isl_space_from_domain(space);498	space = isl_space_add_dims(space, isl_dim_out, 1);499	return space;500}501 502/* Return the number of variables of the given type in the domain of "qp".503 */504isl_size isl_qpolynomial_domain_dim(__isl_keep isl_qpolynomial *qp,505	enum isl_dim_type type)506{507	isl_space *space;508	isl_size dim;509 510	space = isl_qpolynomial_peek_domain_space(qp);511 512	if (!space)513		return isl_size_error;514	if (type == isl_dim_div)515		return qp->div->n_row;516	dim = isl_space_dim(space, type);517	if (dim < 0)518		return isl_size_error;519	if (type == isl_dim_all) {520		isl_size n_div;521 522		n_div = isl_qpolynomial_domain_dim(qp, isl_dim_div);523		if (n_div < 0)524			return isl_size_error;525		dim += n_div;526	}527	return dim;528}529 530/* Given the type of a dimension of an isl_qpolynomial,531 * return the type of the corresponding dimension in its domain.532 * This function is only called for "type" equal to isl_dim_in or533 * isl_dim_param.534 */535static enum isl_dim_type domain_type(enum isl_dim_type type)536{537	return type == isl_dim_in ? isl_dim_set : type;538}539 540/* Externally, an isl_qpolynomial has a map space, but internally, the541 * ls field corresponds to the domain of that space.542 */543isl_size isl_qpolynomial_dim(__isl_keep isl_qpolynomial *qp,544	enum isl_dim_type type)545{546	if (!qp)547		return isl_size_error;548	if (type == isl_dim_out)549		return 1;550	type = domain_type(type);551	return isl_qpolynomial_domain_dim(qp, type);552}553 554/* Return the offset of the first variable of type "type" within555 * the variables of the domain of "qp".556 */557static isl_size isl_qpolynomial_domain_var_offset(558	__isl_keep isl_qpolynomial *qp, enum isl_dim_type type)559{560	isl_space *space;561 562	space = isl_qpolynomial_peek_domain_space(qp);563	if (!space)564		return isl_size_error;565 566	switch (type) {567	case isl_dim_param:568	case isl_dim_set:	return isl_space_offset(space, type);569	case isl_dim_div:	return isl_space_dim(space, isl_dim_all);570	case isl_dim_cst:571	default:572		isl_die(isl_qpolynomial_get_ctx(qp), isl_error_invalid,573			"invalid dimension type", return isl_size_error);574	}575}576 577/* Return the offset of the first coefficient of type "type" in578 * the domain of "qp".579 */580unsigned isl_qpolynomial_domain_offset(__isl_keep isl_qpolynomial *qp,581	enum isl_dim_type type)582{583	switch (type) {584	case isl_dim_cst:585		return 0;586	case isl_dim_param:587	case isl_dim_set:588	case isl_dim_div:589		return 1 + isl_qpolynomial_domain_var_offset(qp, type);590	default:591		return 0;592	}593}594 595isl_bool isl_qpolynomial_is_zero(__isl_keep isl_qpolynomial *qp)596{597	return qp ? isl_poly_is_zero(qp->poly) : isl_bool_error;598}599 600isl_bool isl_qpolynomial_is_one(__isl_keep isl_qpolynomial *qp)601{602	return qp ? isl_poly_is_one(qp->poly) : isl_bool_error;603}604 605isl_bool isl_qpolynomial_is_nan(__isl_keep isl_qpolynomial *qp)606{607	return qp ? isl_poly_is_nan(qp->poly) : isl_bool_error;608}609 610isl_bool isl_qpolynomial_is_infty(__isl_keep isl_qpolynomial *qp)611{612	return qp ? isl_poly_is_infty(qp->poly) : isl_bool_error;613}614 615isl_bool isl_qpolynomial_is_neginfty(__isl_keep isl_qpolynomial *qp)616{617	return qp ? isl_poly_is_neginfty(qp->poly) : isl_bool_error;618}619 620int isl_qpolynomial_sgn(__isl_keep isl_qpolynomial *qp)621{622	return qp ? isl_poly_sgn(qp->poly) : 0;623}624 625static void poly_free_cst(__isl_take isl_poly_cst *cst)626{627	isl_int_clear(cst->n);628	isl_int_clear(cst->d);629}630 631static void poly_free_rec(__isl_take isl_poly_rec *rec)632{633	int i;634 635	for (i = 0; i < rec->n; ++i)636		isl_poly_free(rec->p[i]);637}638 639__isl_give isl_poly *isl_poly_copy(__isl_keep isl_poly *poly)640{641	if (!poly)642		return NULL;643 644	poly->ref++;645	return poly;646}647 648__isl_give isl_poly *isl_poly_dup_cst(__isl_keep isl_poly *poly)649{650	isl_poly_cst *cst;651	isl_poly_cst *dup;652 653	cst = isl_poly_as_cst(poly);654	if (!cst)655		return NULL;656 657	dup = isl_poly_as_cst(isl_poly_zero(poly->ctx));658	if (!dup)659		return NULL;660	isl_int_set(dup->n, cst->n);661	isl_int_set(dup->d, cst->d);662 663	return &dup->poly;664}665 666__isl_give isl_poly *isl_poly_dup_rec(__isl_keep isl_poly *poly)667{668	int i;669	isl_poly_rec *rec;670	isl_poly_rec *dup;671 672	rec = isl_poly_as_rec(poly);673	if (!rec)674		return NULL;675 676	dup = isl_poly_alloc_rec(poly->ctx, poly->var, rec->n);677	if (!dup)678		return NULL;679 680	for (i = 0; i < rec->n; ++i) {681		dup->p[i] = isl_poly_copy(rec->p[i]);682		if (!dup->p[i])683			goto error;684		dup->n++;685	}686 687	return &dup->poly;688error:689	isl_poly_free(&dup->poly);690	return NULL;691}692 693__isl_give isl_poly *isl_poly_dup(__isl_keep isl_poly *poly)694{695	isl_bool is_cst;696 697	is_cst = isl_poly_is_cst(poly);698	if (is_cst < 0)699		return NULL;700	if (is_cst)701		return isl_poly_dup_cst(poly);702	else703		return isl_poly_dup_rec(poly);704}705 706__isl_give isl_poly *isl_poly_cow(__isl_take isl_poly *poly)707{708	if (!poly)709		return NULL;710 711	if (poly->ref == 1)712		return poly;713	poly->ref--;714	return isl_poly_dup(poly);715}716 717__isl_null isl_poly *isl_poly_free(__isl_take isl_poly *poly)718{719	if (!poly)720		return NULL;721 722	if (--poly->ref > 0)723		return NULL;724 725	if (poly->var < 0)726		poly_free_cst((isl_poly_cst *) poly);727	else728		poly_free_rec((isl_poly_rec *) poly);729 730	isl_ctx_deref(poly->ctx);731	free(poly);732	return NULL;733}734 735static void isl_poly_cst_reduce(__isl_keep isl_poly_cst *cst)736{737	isl_int gcd;738 739	isl_int_init(gcd);740	isl_int_gcd(gcd, cst->n, cst->d);741	if (!isl_int_is_zero(gcd) && !isl_int_is_one(gcd)) {742		isl_int_divexact(cst->n, cst->n, gcd);743		isl_int_divexact(cst->d, cst->d, gcd);744	}745	isl_int_clear(gcd);746}747 748__isl_give isl_poly *isl_poly_sum_cst(__isl_take isl_poly *poly1,749	__isl_take isl_poly *poly2)750{751	isl_poly_cst *cst1;752	isl_poly_cst *cst2;753 754	poly1 = isl_poly_cow(poly1);755	if (!poly1 || !poly2)756		goto error;757 758	cst1 = isl_poly_as_cst(poly1);759	cst2 = isl_poly_as_cst(poly2);760 761	if (isl_int_eq(cst1->d, cst2->d))762		isl_int_add(cst1->n, cst1->n, cst2->n);763	else {764		isl_int_mul(cst1->n, cst1->n, cst2->d);765		isl_int_addmul(cst1->n, cst2->n, cst1->d);766		isl_int_mul(cst1->d, cst1->d, cst2->d);767	}768 769	isl_poly_cst_reduce(cst1);770 771	isl_poly_free(poly2);772	return poly1;773error:774	isl_poly_free(poly1);775	isl_poly_free(poly2);776	return NULL;777}778 779static __isl_give isl_poly *replace_by_zero(__isl_take isl_poly *poly)780{781	struct isl_ctx *ctx;782 783	if (!poly)784		return NULL;785	ctx = poly->ctx;786	isl_poly_free(poly);787	return isl_poly_zero(ctx);788}789 790static __isl_give isl_poly *replace_by_constant_term(__isl_take isl_poly *poly)791{792	isl_poly_rec *rec;793	isl_poly *cst;794 795	if (!poly)796		return NULL;797 798	rec = isl_poly_as_rec(poly);799	if (!rec)800		goto error;801	cst = isl_poly_copy(rec->p[0]);802	isl_poly_free(poly);803	return cst;804error:805	isl_poly_free(poly);806	return NULL;807}808 809__isl_give isl_poly *isl_poly_sum(__isl_take isl_poly *poly1,810	__isl_take isl_poly *poly2)811{812	int i;813	isl_bool is_zero, is_nan, is_cst;814	isl_poly_rec *rec1, *rec2;815 816	if (!poly1 || !poly2)817		goto error;818 819	is_nan = isl_poly_is_nan(poly1);820	if (is_nan < 0)821		goto error;822	if (is_nan) {823		isl_poly_free(poly2);824		return poly1;825	}826 827	is_nan = isl_poly_is_nan(poly2);828	if (is_nan < 0)829		goto error;830	if (is_nan) {831		isl_poly_free(poly1);832		return poly2;833	}834 835	is_zero = isl_poly_is_zero(poly1);836	if (is_zero < 0)837		goto error;838	if (is_zero) {839		isl_poly_free(poly1);840		return poly2;841	}842 843	is_zero = isl_poly_is_zero(poly2);844	if (is_zero < 0)845		goto error;846	if (is_zero) {847		isl_poly_free(poly2);848		return poly1;849	}850 851	if (poly1->var < poly2->var)852		return isl_poly_sum(poly2, poly1);853 854	if (poly2->var < poly1->var) {855		isl_poly_rec *rec;856		isl_bool is_infty;857 858		is_infty = isl_poly_is_infty(poly2);859		if (is_infty >= 0 && !is_infty)860			is_infty = isl_poly_is_neginfty(poly2);861		if (is_infty < 0)862			goto error;863		if (is_infty) {864			isl_poly_free(poly1);865			return poly2;866		}867		poly1 = isl_poly_cow(poly1);868		rec = isl_poly_as_rec(poly1);869		if (!rec)870			goto error;871		rec->p[0] = isl_poly_sum(rec->p[0], poly2);872		if (rec->n == 1)873			poly1 = replace_by_constant_term(poly1);874		return poly1;875	}876 877	is_cst = isl_poly_is_cst(poly1);878	if (is_cst < 0)879		goto error;880	if (is_cst)881		return isl_poly_sum_cst(poly1, poly2);882 883	rec1 = isl_poly_as_rec(poly1);884	rec2 = isl_poly_as_rec(poly2);885	if (!rec1 || !rec2)886		goto error;887 888	if (rec1->n < rec2->n)889		return isl_poly_sum(poly2, poly1);890 891	poly1 = isl_poly_cow(poly1);892	rec1 = isl_poly_as_rec(poly1);893	if (!rec1)894		goto error;895 896	for (i = rec2->n - 1; i >= 0; --i) {897		isl_bool is_zero;898 899		rec1->p[i] = isl_poly_sum(rec1->p[i],900					    isl_poly_copy(rec2->p[i]));901		if (!rec1->p[i])902			goto error;903		if (i != rec1->n - 1)904			continue;905		is_zero = isl_poly_is_zero(rec1->p[i]);906		if (is_zero < 0)907			goto error;908		if (is_zero) {909			isl_poly_free(rec1->p[i]);910			rec1->n--;911		}912	}913 914	if (rec1->n == 0)915		poly1 = replace_by_zero(poly1);916	else if (rec1->n == 1)917		poly1 = replace_by_constant_term(poly1);918 919	isl_poly_free(poly2);920 921	return poly1;922error:923	isl_poly_free(poly1);924	isl_poly_free(poly2);925	return NULL;926}927 928__isl_give isl_poly *isl_poly_cst_add_isl_int(__isl_take isl_poly *poly,929	isl_int v)930{931	isl_poly_cst *cst;932 933	poly = isl_poly_cow(poly);934	if (!poly)935		return NULL;936 937	cst = isl_poly_as_cst(poly);938 939	isl_int_addmul(cst->n, cst->d, v);940 941	return poly;942}943 944__isl_give isl_poly *isl_poly_add_isl_int(__isl_take isl_poly *poly, isl_int v)945{946	isl_bool is_cst;947	isl_poly_rec *rec;948 949	is_cst = isl_poly_is_cst(poly);950	if (is_cst < 0)951		return isl_poly_free(poly);952	if (is_cst)953		return isl_poly_cst_add_isl_int(poly, v);954 955	poly = isl_poly_cow(poly);956	rec = isl_poly_as_rec(poly);957	if (!rec)958		goto error;959 960	rec->p[0] = isl_poly_add_isl_int(rec->p[0], v);961	if (!rec->p[0])962		goto error;963 964	return poly;965error:966	isl_poly_free(poly);967	return NULL;968}969 970__isl_give isl_poly *isl_poly_cst_mul_isl_int(__isl_take isl_poly *poly,971	isl_int v)972{973	isl_bool is_zero;974	isl_poly_cst *cst;975 976	is_zero = isl_poly_is_zero(poly);977	if (is_zero < 0)978		return isl_poly_free(poly);979	if (is_zero)980		return poly;981 982	poly = isl_poly_cow(poly);983	if (!poly)984		return NULL;985 986	cst = isl_poly_as_cst(poly);987 988	isl_int_mul(cst->n, cst->n, v);989 990	return poly;991}992 993__isl_give isl_poly *isl_poly_mul_isl_int(__isl_take isl_poly *poly, isl_int v)994{995	int i;996	isl_bool is_cst;997	isl_poly_rec *rec;998 999	is_cst = isl_poly_is_cst(poly);1000	if (is_cst < 0)1001		return isl_poly_free(poly);1002	if (is_cst)1003		return isl_poly_cst_mul_isl_int(poly, v);1004 1005	poly = isl_poly_cow(poly);1006	rec = isl_poly_as_rec(poly);1007	if (!rec)1008		goto error;1009 1010	for (i = 0; i < rec->n; ++i) {1011		rec->p[i] = isl_poly_mul_isl_int(rec->p[i], v);1012		if (!rec->p[i])1013			goto error;1014	}1015 1016	return poly;1017error:1018	isl_poly_free(poly);1019	return NULL;1020}1021 1022/* Multiply the constant polynomial "poly" by "v".1023 */1024static __isl_give isl_poly *isl_poly_cst_scale_val(__isl_take isl_poly *poly,1025	__isl_keep isl_val *v)1026{1027	isl_bool is_zero;1028	isl_poly_cst *cst;1029 1030	is_zero = isl_poly_is_zero(poly);1031	if (is_zero < 0)1032		return isl_poly_free(poly);1033	if (is_zero)1034		return poly;1035 1036	poly = isl_poly_cow(poly);1037	if (!poly)1038		return NULL;1039 1040	cst = isl_poly_as_cst(poly);1041 1042	isl_int_mul(cst->n, cst->n, v->n);1043	isl_int_mul(cst->d, cst->d, v->d);1044	isl_poly_cst_reduce(cst);1045 1046	return poly;1047}1048 1049/* Multiply the polynomial "poly" by "v".1050 */1051static __isl_give isl_poly *isl_poly_scale_val(__isl_take isl_poly *poly,1052	__isl_keep isl_val *v)1053{1054	int i;1055	isl_bool is_cst;1056	isl_poly_rec *rec;1057 1058	is_cst = isl_poly_is_cst(poly);1059	if (is_cst < 0)1060		return isl_poly_free(poly);1061	if (is_cst)1062		return isl_poly_cst_scale_val(poly, v);1063 1064	poly = isl_poly_cow(poly);1065	rec = isl_poly_as_rec(poly);1066	if (!rec)1067		goto error;1068 1069	for (i = 0; i < rec->n; ++i) {1070		rec->p[i] = isl_poly_scale_val(rec->p[i], v);1071		if (!rec->p[i])1072			goto error;1073	}1074 1075	return poly;1076error:1077	isl_poly_free(poly);1078	return NULL;1079}1080 1081__isl_give isl_poly *isl_poly_mul_cst(__isl_take isl_poly *poly1,1082	__isl_take isl_poly *poly2)1083{1084	isl_poly_cst *cst1;1085	isl_poly_cst *cst2;1086 1087	poly1 = isl_poly_cow(poly1);1088	if (!poly1 || !poly2)1089		goto error;1090 1091	cst1 = isl_poly_as_cst(poly1);1092	cst2 = isl_poly_as_cst(poly2);1093 1094	isl_int_mul(cst1->n, cst1->n, cst2->n);1095	isl_int_mul(cst1->d, cst1->d, cst2->d);1096 1097	isl_poly_cst_reduce(cst1);1098 1099	isl_poly_free(poly2);1100	return poly1;1101error:1102	isl_poly_free(poly1);1103	isl_poly_free(poly2);1104	return NULL;1105}1106 1107__isl_give isl_poly *isl_poly_mul_rec(__isl_take isl_poly *poly1,1108	__isl_take isl_poly *poly2)1109{1110	isl_poly_rec *rec1;1111	isl_poly_rec *rec2;1112	isl_poly_rec *res = NULL;1113	int i, j;1114	int size;1115 1116	rec1 = isl_poly_as_rec(poly1);1117	rec2 = isl_poly_as_rec(poly2);1118	if (!rec1 || !rec2)1119		goto error;1120	size = rec1->n + rec2->n - 1;1121	res = isl_poly_alloc_rec(poly1->ctx, poly1->var, size);1122	if (!res)1123		goto error;1124 1125	for (i = 0; i < rec1->n; ++i) {1126		res->p[i] = isl_poly_mul(isl_poly_copy(rec2->p[0]),1127					    isl_poly_copy(rec1->p[i]));1128		if (!res->p[i])1129			goto error;1130		res->n++;1131	}1132	for (; i < size; ++i) {1133		res->p[i] = isl_poly_zero(poly1->ctx);1134		if (!res->p[i])1135			goto error;1136		res->n++;1137	}1138	for (i = 0; i < rec1->n; ++i) {1139		for (j = 1; j < rec2->n; ++j) {1140			isl_poly *poly;1141			poly = isl_poly_mul(isl_poly_copy(rec2->p[j]),1142					    isl_poly_copy(rec1->p[i]));1143			res->p[i + j] = isl_poly_sum(res->p[i + j], poly);1144			if (!res->p[i + j])1145				goto error;1146		}1147	}1148 1149	isl_poly_free(poly1);1150	isl_poly_free(poly2);1151 1152	return &res->poly;1153error:1154	isl_poly_free(poly1);1155	isl_poly_free(poly2);1156	isl_poly_free(&res->poly);1157	return NULL;1158}1159 1160__isl_give isl_poly *isl_poly_mul(__isl_take isl_poly *poly1,1161	__isl_take isl_poly *poly2)1162{1163	isl_bool is_zero, is_nan, is_one, is_cst;1164 1165	if (!poly1 || !poly2)1166		goto error;1167 1168	is_nan = isl_poly_is_nan(poly1);1169	if (is_nan < 0)1170		goto error;1171	if (is_nan) {1172		isl_poly_free(poly2);1173		return poly1;1174	}1175 1176	is_nan = isl_poly_is_nan(poly2);1177	if (is_nan < 0)1178		goto error;1179	if (is_nan) {1180		isl_poly_free(poly1);1181		return poly2;1182	}1183 1184	is_zero = isl_poly_is_zero(poly1);1185	if (is_zero < 0)1186		goto error;1187	if (is_zero) {1188		isl_poly_free(poly2);1189		return poly1;1190	}1191 1192	is_zero = isl_poly_is_zero(poly2);1193	if (is_zero < 0)1194		goto error;1195	if (is_zero) {1196		isl_poly_free(poly1);1197		return poly2;1198	}1199 1200	is_one = isl_poly_is_one(poly1);1201	if (is_one < 0)1202		goto error;1203	if (is_one) {1204		isl_poly_free(poly1);1205		return poly2;1206	}1207 1208	is_one = isl_poly_is_one(poly2);1209	if (is_one < 0)1210		goto error;1211	if (is_one) {1212		isl_poly_free(poly2);1213		return poly1;1214	}1215 1216	if (poly1->var < poly2->var)1217		return isl_poly_mul(poly2, poly1);1218 1219	if (poly2->var < poly1->var) {1220		int i;1221		isl_poly_rec *rec;1222		isl_bool is_infty;1223 1224		is_infty = isl_poly_is_infty(poly2);1225		if (is_infty >= 0 && !is_infty)1226			is_infty = isl_poly_is_neginfty(poly2);1227		if (is_infty < 0)1228			goto error;1229		if (is_infty) {1230			isl_ctx *ctx = poly1->ctx;1231			isl_poly_free(poly1);1232			isl_poly_free(poly2);1233			return isl_poly_nan(ctx);1234		}1235		poly1 = isl_poly_cow(poly1);1236		rec = isl_poly_as_rec(poly1);1237		if (!rec)1238			goto error;1239 1240		for (i = 0; i < rec->n; ++i) {1241			rec->p[i] = isl_poly_mul(rec->p[i],1242						isl_poly_copy(poly2));1243			if (!rec->p[i])1244				goto error;1245		}1246		isl_poly_free(poly2);1247		return poly1;1248	}1249 1250	is_cst = isl_poly_is_cst(poly1);1251	if (is_cst < 0)1252		goto error;1253	if (is_cst)1254		return isl_poly_mul_cst(poly1, poly2);1255 1256	return isl_poly_mul_rec(poly1, poly2);1257error:1258	isl_poly_free(poly1);1259	isl_poly_free(poly2);1260	return NULL;1261}1262 1263__isl_give isl_poly *isl_poly_pow(__isl_take isl_poly *poly, unsigned power)1264{1265	isl_poly *res;1266 1267	if (!poly)1268		return NULL;1269	if (power == 1)1270		return poly;1271 1272	if (power % 2)1273		res = isl_poly_copy(poly);1274	else1275		res = isl_poly_one(poly->ctx);1276 1277	while (power >>= 1) {1278		poly = isl_poly_mul(poly, isl_poly_copy(poly));1279		if (power % 2)1280			res = isl_poly_mul(res, isl_poly_copy(poly));1281	}1282 1283	isl_poly_free(poly);1284	return res;1285}1286 1287__isl_give isl_qpolynomial *isl_qpolynomial_alloc(__isl_take isl_space *space,1288	unsigned n_div, __isl_take isl_poly *poly)1289{1290	struct isl_qpolynomial *qp = NULL;1291	isl_size total;1292 1293	total = isl_space_dim(space, isl_dim_all);1294	if (total < 0 || !poly)1295		goto error;1296 1297	if (!isl_space_is_set(space))1298		isl_die(isl_space_get_ctx(space), isl_error_invalid,1299			"domain of polynomial should be a set", goto error);1300 1301	qp = isl_calloc_type(space->ctx, struct isl_qpolynomial);1302	if (!qp)1303		goto error;1304 1305	qp->ref = 1;1306	qp->div = isl_mat_alloc(space->ctx, n_div, 1 + 1 + total + n_div);1307	if (!qp->div)1308		goto error;1309 1310	qp->dim = space;1311	qp->poly = poly;1312 1313	return qp;1314error:1315	isl_space_free(space);1316	isl_poly_free(poly);1317	isl_qpolynomial_free(qp);1318	return NULL;1319}1320 1321__isl_give isl_qpolynomial *isl_qpolynomial_copy(__isl_keep isl_qpolynomial *qp)1322{1323	if (!qp)1324		return NULL;1325 1326	qp->ref++;1327	return qp;1328}1329 1330__isl_give isl_qpolynomial *isl_qpolynomial_dup(__isl_keep isl_qpolynomial *qp)1331{1332	struct isl_qpolynomial *dup;1333 1334	if (!qp)1335		return NULL;1336 1337	dup = isl_qpolynomial_alloc(isl_space_copy(qp->dim), qp->div->n_row,1338				    isl_poly_copy(qp->poly));1339	if (!dup)1340		return NULL;1341	isl_mat_free(dup->div);1342	dup->div = isl_mat_copy(qp->div);1343	if (!dup->div)1344		goto error;1345 1346	return dup;1347error:1348	isl_qpolynomial_free(dup);1349	return NULL;1350}1351 1352__isl_give isl_qpolynomial *isl_qpolynomial_cow(__isl_take isl_qpolynomial *qp)1353{1354	if (!qp)1355		return NULL;1356 1357	if (qp->ref == 1)1358		return qp;1359	qp->ref--;1360	return isl_qpolynomial_dup(qp);1361}1362 1363__isl_null isl_qpolynomial *isl_qpolynomial_free(1364	__isl_take isl_qpolynomial *qp)1365{1366	if (!qp)1367		return NULL;1368 1369	if (--qp->ref > 0)1370		return NULL;1371 1372	isl_space_free(qp->dim);1373	isl_mat_free(qp->div);1374	isl_poly_free(qp->poly);1375 1376	free(qp);1377	return NULL;1378}1379 1380__isl_give isl_poly *isl_poly_var_pow(isl_ctx *ctx, int pos, int power)1381{1382	int i;1383	isl_poly_rec *rec;1384	isl_poly_cst *cst;1385 1386	rec = isl_poly_alloc_rec(ctx, pos, 1 + power);1387	if (!rec)1388		return NULL;1389	for (i = 0; i < 1 + power; ++i) {1390		rec->p[i] = isl_poly_zero(ctx);1391		if (!rec->p[i])1392			goto error;1393		rec->n++;1394	}1395	cst = isl_poly_as_cst(rec->p[power]);1396	isl_int_set_si(cst->n, 1);1397 1398	return &rec->poly;1399error:1400	isl_poly_free(&rec->poly);1401	return NULL;1402}1403 1404/* r array maps original positions to new positions.1405 */1406static __isl_give isl_poly *reorder(__isl_take isl_poly *poly, int *r)1407{1408	int i;1409	isl_bool is_cst;1410	isl_poly_rec *rec;1411	isl_poly *base;1412	isl_poly *res;1413 1414	is_cst = isl_poly_is_cst(poly);1415	if (is_cst < 0)1416		return isl_poly_free(poly);1417	if (is_cst)1418		return poly;1419 1420	rec = isl_poly_as_rec(poly);1421	if (!rec)1422		goto error;1423 1424	isl_assert(poly->ctx, rec->n >= 1, goto error);1425 1426	base = isl_poly_var_pow(poly->ctx, r[poly->var], 1);1427	res = reorder(isl_poly_copy(rec->p[rec->n - 1]), r);1428 1429	for (i = rec->n - 2; i >= 0; --i) {1430		res = isl_poly_mul(res, isl_poly_copy(base));1431		res = isl_poly_sum(res, reorder(isl_poly_copy(rec->p[i]), r));1432	}1433 1434	isl_poly_free(base);1435	isl_poly_free(poly);1436 1437	return res;1438error:1439	isl_poly_free(poly);1440	return NULL;1441}1442 1443static isl_bool compatible_divs(__isl_keep isl_mat *div1,1444	__isl_keep isl_mat *div2)1445{1446	int n_row, n_col;1447	isl_bool equal;1448 1449	isl_assert(div1->ctx, div1->n_row >= div2->n_row &&1450				div1->n_col >= div2->n_col,1451		    return isl_bool_error);1452 1453	if (div1->n_row == div2->n_row)1454		return isl_mat_is_equal(div1, div2);1455 1456	n_row = div1->n_row;1457	n_col = div1->n_col;1458	div1->n_row = div2->n_row;1459	div1->n_col = div2->n_col;1460 1461	equal = isl_mat_is_equal(div1, div2);1462 1463	div1->n_row = n_row;1464	div1->n_col = n_col;1465 1466	return equal;1467}1468 1469static int cmp_row(__isl_keep isl_mat *div, int i, int j)1470{1471	int li, lj;1472 1473	li = isl_seq_last_non_zero(div->row[i], div->n_col);1474	lj = isl_seq_last_non_zero(div->row[j], div->n_col);1475 1476	if (li != lj)1477		return li - lj;1478 1479	return isl_seq_cmp(div->row[i], div->row[j], div->n_col);1480}1481 1482struct isl_div_sort_info {1483	isl_mat	*div;1484	int	 row;1485};1486 1487static int div_sort_cmp(const void *p1, const void *p2)1488{1489	const struct isl_div_sort_info *i1, *i2;1490	i1 = (const struct isl_div_sort_info *) p1;1491	i2 = (const struct isl_div_sort_info *) p2;1492 1493	return cmp_row(i1->div, i1->row, i2->row);1494}1495 1496/* Sort divs and remove duplicates.1497 */1498static __isl_give isl_qpolynomial *sort_divs(__isl_take isl_qpolynomial *qp)1499{1500	int i;1501	int skip;1502	int len;1503	struct isl_div_sort_info *array = NULL;1504	int *pos = NULL, *at = NULL;1505	int *reordering = NULL;1506	isl_size div_pos;1507 1508	if (!qp)1509		return NULL;1510	if (qp->div->n_row <= 1)1511		return qp;1512 1513	div_pos = isl_qpolynomial_domain_var_offset(qp, isl_dim_div);1514	if (div_pos < 0)1515		return isl_qpolynomial_free(qp);1516 1517	array = isl_alloc_array(qp->div->ctx, struct isl_div_sort_info,1518				qp->div->n_row);1519	pos = isl_alloc_array(qp->div->ctx, int, qp->div->n_row);1520	at = isl_alloc_array(qp->div->ctx, int, qp->div->n_row);1521	len = qp->div->n_col - 2;1522	reordering = isl_alloc_array(qp->div->ctx, int, len);1523	if (!array || !pos || !at || !reordering)1524		goto error;1525 1526	for (i = 0; i < qp->div->n_row; ++i) {1527		array[i].div = qp->div;1528		array[i].row = i;1529		pos[i] = i;1530		at[i] = i;1531	}1532 1533	qsort(array, qp->div->n_row, sizeof(struct isl_div_sort_info),1534		div_sort_cmp);1535 1536	for (i = 0; i < div_pos; ++i)1537		reordering[i] = i;1538 1539	for (i = 0; i < qp->div->n_row; ++i) {1540		if (pos[array[i].row] == i)1541			continue;1542		qp->div = isl_mat_swap_rows(qp->div, i, pos[array[i].row]);1543		pos[at[i]] = pos[array[i].row];1544		at[pos[array[i].row]] = at[i];1545		at[i] = array[i].row;1546		pos[array[i].row] = i;1547	}1548 1549	skip = 0;1550	for (i = 0; i < len - div_pos; ++i) {1551		if (i > 0 &&1552		    isl_seq_eq(qp->div->row[i - skip - 1],1553			       qp->div->row[i - skip], qp->div->n_col)) {1554			qp->div = isl_mat_drop_rows(qp->div, i - skip, 1);1555			isl_mat_col_add(qp->div, 2 + div_pos + i - skip - 1,1556						 2 + div_pos + i - skip);1557			qp->div = isl_mat_drop_cols(qp->div,1558						    2 + div_pos + i - skip, 1);1559			skip++;1560		}1561		reordering[div_pos + array[i].row] = div_pos + i - skip;1562	}1563 1564	qp->poly = reorder(qp->poly, reordering);1565 1566	if (!qp->poly || !qp->div)1567		goto error;1568 1569	free(at);1570	free(pos);1571	free(array);1572	free(reordering);1573 1574	return qp;1575error:1576	free(at);1577	free(pos);1578	free(array);1579	free(reordering);1580	isl_qpolynomial_free(qp);1581	return NULL;1582}1583 1584static __isl_give isl_poly *expand(__isl_take isl_poly *poly, int *exp,1585	int first)1586{1587	int i;1588	isl_bool is_cst;1589	isl_poly_rec *rec;1590 1591	is_cst = isl_poly_is_cst(poly);1592	if (is_cst < 0)1593		return isl_poly_free(poly);1594	if (is_cst)1595		return poly;1596 1597	if (poly->var < first)1598		return poly;1599 1600	if (exp[poly->var - first] == poly->var - first)1601		return poly;1602 1603	poly = isl_poly_cow(poly);1604	if (!poly)1605		goto error;1606 1607	poly->var = exp[poly->var - first] + first;1608 1609	rec = isl_poly_as_rec(poly);1610	if (!rec)1611		goto error;1612 1613	for (i = 0; i < rec->n; ++i) {1614		rec->p[i] = expand(rec->p[i], exp, first);1615		if (!rec->p[i])1616			goto error;1617	}1618 1619	return poly;1620error:1621	isl_poly_free(poly);1622	return NULL;1623}1624 1625static __isl_give isl_qpolynomial *with_merged_divs(1626	__isl_give isl_qpolynomial *(*fn)(__isl_take isl_qpolynomial *qp1,1627					  __isl_take isl_qpolynomial *qp2),1628	__isl_take isl_qpolynomial *qp1, __isl_take isl_qpolynomial *qp2)1629{1630	int *exp1 = NULL;1631	int *exp2 = NULL;1632	isl_mat *div = NULL;1633	int n_div1, n_div2;1634 1635	qp1 = isl_qpolynomial_cow(qp1);1636	qp2 = isl_qpolynomial_cow(qp2);1637 1638	if (!qp1 || !qp2)1639		goto error;1640 1641	isl_assert(qp1->div->ctx, qp1->div->n_row >= qp2->div->n_row &&1642				qp1->div->n_col >= qp2->div->n_col, goto error);1643 1644	n_div1 = qp1->div->n_row;1645	n_div2 = qp2->div->n_row;1646	exp1 = isl_alloc_array(qp1->div->ctx, int, n_div1);1647	exp2 = isl_alloc_array(qp2->div->ctx, int, n_div2);1648	if ((n_div1 && !exp1) || (n_div2 && !exp2))1649		goto error;1650 1651	div = isl_merge_divs(qp1->div, qp2->div, exp1, exp2);1652	if (!div)1653		goto error;1654 1655	isl_mat_free(qp1->div);1656	qp1->div = isl_mat_copy(div);1657	isl_mat_free(qp2->div);1658	qp2->div = isl_mat_copy(div);1659 1660	qp1->poly = expand(qp1->poly, exp1, div->n_col - div->n_row - 2);1661	qp2->poly = expand(qp2->poly, exp2, div->n_col - div->n_row - 2);1662 1663	if (!qp1->poly || !qp2->poly)1664		goto error;1665 1666	isl_mat_free(div);1667	free(exp1);1668	free(exp2);1669 1670	return fn(qp1, qp2);1671error:1672	isl_mat_free(div);1673	free(exp1);1674	free(exp2);1675	isl_qpolynomial_free(qp1);1676	isl_qpolynomial_free(qp2);1677	return NULL;1678}1679 1680__isl_give isl_qpolynomial *isl_qpolynomial_add(__isl_take isl_qpolynomial *qp1,1681	__isl_take isl_qpolynomial *qp2)1682{1683	isl_bool compatible;1684 1685	qp1 = isl_qpolynomial_cow(qp1);1686 1687	if (isl_qpolynomial_check_equal_space(qp1, qp2) < 0)1688		goto error;1689 1690	if (qp1->div->n_row < qp2->div->n_row)1691		return isl_qpolynomial_add(qp2, qp1);1692 1693	compatible = compatible_divs(qp1->div, qp2->div);1694	if (compatible < 0)1695		goto error;1696	if (!compatible)1697		return with_merged_divs(isl_qpolynomial_add, qp1, qp2);1698 1699	qp1->poly = isl_poly_sum(qp1->poly, isl_poly_copy(qp2->poly));1700	if (!qp1->poly)1701		goto error;1702 1703	isl_qpolynomial_free(qp2);1704 1705	return qp1;1706error:1707	isl_qpolynomial_free(qp1);1708	isl_qpolynomial_free(qp2);1709	return NULL;1710}1711 1712__isl_give isl_qpolynomial *isl_qpolynomial_add_on_domain(1713	__isl_keep isl_set *dom,1714	__isl_take isl_qpolynomial *qp1,1715	__isl_take isl_qpolynomial *qp2)1716{1717	qp1 = isl_qpolynomial_add(qp1, qp2);1718	qp1 = isl_qpolynomial_gist(qp1, isl_set_copy(dom));1719	return qp1;1720}1721 1722__isl_give isl_qpolynomial *isl_qpolynomial_sub(__isl_take isl_qpolynomial *qp1,1723	__isl_take isl_qpolynomial *qp2)1724{1725	return isl_qpolynomial_add(qp1, isl_qpolynomial_neg(qp2));1726}1727 1728__isl_give isl_qpolynomial *isl_qpolynomial_add_isl_int(1729	__isl_take isl_qpolynomial *qp, isl_int v)1730{1731	if (isl_int_is_zero(v))1732		return qp;1733 1734	qp = isl_qpolynomial_cow(qp);1735	if (!qp)1736		return NULL;1737 1738	qp->poly = isl_poly_add_isl_int(qp->poly, v);1739	if (!qp->poly)1740		goto error;1741 1742	return qp;1743error:1744	isl_qpolynomial_free(qp);1745	return NULL;1746 1747}1748 1749__isl_give isl_qpolynomial *isl_qpolynomial_neg(__isl_take isl_qpolynomial *qp)1750{1751	if (!qp)1752		return NULL;1753 1754	return isl_qpolynomial_mul_isl_int(qp, qp->dim->ctx->negone);1755}1756 1757__isl_give isl_qpolynomial *isl_qpolynomial_mul_isl_int(1758	__isl_take isl_qpolynomial *qp, isl_int v)1759{1760	if (isl_int_is_one(v))1761		return qp;1762 1763	if (qp && isl_int_is_zero(v)) {1764		isl_qpolynomial *zero;1765		zero = isl_qpolynomial_zero_on_domain(isl_space_copy(qp->dim));1766		isl_qpolynomial_free(qp);1767		return zero;1768	}1769	1770	qp = isl_qpolynomial_cow(qp);1771	if (!qp)1772		return NULL;1773 1774	qp->poly = isl_poly_mul_isl_int(qp->poly, v);1775	if (!qp->poly)1776		goto error;1777 1778	return qp;1779error:1780	isl_qpolynomial_free(qp);1781	return NULL;1782}1783 1784__isl_give isl_qpolynomial *isl_qpolynomial_scale(1785	__isl_take isl_qpolynomial *qp, isl_int v)1786{1787	return isl_qpolynomial_mul_isl_int(qp, v);1788}1789 1790/* Multiply "qp" by "v".1791 */1792__isl_give isl_qpolynomial *isl_qpolynomial_scale_val(1793	__isl_take isl_qpolynomial *qp, __isl_take isl_val *v)1794{1795	if (!qp || !v)1796		goto error;1797 1798	if (!isl_val_is_rat(v))1799		isl_die(isl_qpolynomial_get_ctx(qp), isl_error_invalid,1800			"expecting rational factor", goto error);1801 1802	if (isl_val_is_one(v)) {1803		isl_val_free(v);1804		return qp;1805	}1806 1807	if (isl_val_is_zero(v)) {1808		isl_space *space;1809 1810		space = isl_qpolynomial_get_domain_space(qp);1811		isl_qpolynomial_free(qp);1812		isl_val_free(v);1813		return isl_qpolynomial_zero_on_domain(space);1814	}1815 1816	qp = isl_qpolynomial_cow(qp);1817	if (!qp)1818		goto error;1819 1820	qp->poly = isl_poly_scale_val(qp->poly, v);1821	if (!qp->poly)1822		qp = isl_qpolynomial_free(qp);1823 1824	isl_val_free(v);1825	return qp;1826error:1827	isl_val_free(v);1828	isl_qpolynomial_free(qp);1829	return NULL;1830}1831 1832/* Divide "qp" by "v".1833 */1834__isl_give isl_qpolynomial *isl_qpolynomial_scale_down_val(1835	__isl_take isl_qpolynomial *qp, __isl_take isl_val *v)1836{1837	if (!qp || !v)1838		goto error;1839 1840	if (!isl_val_is_rat(v))1841		isl_die(isl_qpolynomial_get_ctx(qp), isl_error_invalid,1842			"expecting rational factor", goto error);1843	if (isl_val_is_zero(v))1844		isl_die(isl_val_get_ctx(v), isl_error_invalid,1845			"cannot scale down by zero", goto error);1846 1847	return isl_qpolynomial_scale_val(qp, isl_val_inv(v));1848error:1849	isl_val_free(v);1850	isl_qpolynomial_free(qp);1851	return NULL;1852}1853 1854__isl_give isl_qpolynomial *isl_qpolynomial_mul(__isl_take isl_qpolynomial *qp1,1855	__isl_take isl_qpolynomial *qp2)1856{1857	isl_bool compatible;1858 1859	qp1 = isl_qpolynomial_cow(qp1);1860 1861	if (isl_qpolynomial_check_equal_space(qp1, qp2) < 0)1862		goto error;1863 1864	if (qp1->div->n_row < qp2->div->n_row)1865		return isl_qpolynomial_mul(qp2, qp1);1866 1867	compatible = compatible_divs(qp1->div, qp2->div);1868	if (compatible < 0)1869		goto error;1870	if (!compatible)1871		return with_merged_divs(isl_qpolynomial_mul, qp1, qp2);1872 1873	qp1->poly = isl_poly_mul(qp1->poly, isl_poly_copy(qp2->poly));1874	if (!qp1->poly)1875		goto error;1876 1877	isl_qpolynomial_free(qp2);1878 1879	return qp1;1880error:1881	isl_qpolynomial_free(qp1);1882	isl_qpolynomial_free(qp2);1883	return NULL;1884}1885 1886__isl_give isl_qpolynomial *isl_qpolynomial_pow(__isl_take isl_qpolynomial *qp,1887	unsigned power)1888{1889	qp = isl_qpolynomial_cow(qp);1890 1891	if (!qp)1892		return NULL;1893 1894	qp->poly = isl_poly_pow(qp->poly, power);1895	if (!qp->poly)1896		goto error;1897 1898	return qp;1899error:1900	isl_qpolynomial_free(qp);1901	return NULL;1902}1903 1904__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_pow(1905	__isl_take isl_pw_qpolynomial *pwqp, unsigned power)1906{1907	int i;1908 1909	if (power == 1)1910		return pwqp;1911 1912	pwqp = isl_pw_qpolynomial_cow(pwqp);1913	if (!pwqp)1914		return NULL;1915 1916	for (i = 0; i < pwqp->n; ++i) {1917		pwqp->p[i].qp = isl_qpolynomial_pow(pwqp->p[i].qp, power);1918		if (!pwqp->p[i].qp)1919			return isl_pw_qpolynomial_free(pwqp);1920	}1921 1922	return pwqp;1923}1924 1925__isl_give isl_qpolynomial *isl_qpolynomial_zero_on_domain(1926	__isl_take isl_space *domain)1927{1928	if (!domain)1929		return NULL;1930	return isl_qpolynomial_alloc(domain, 0, isl_poly_zero(domain->ctx));1931}1932 1933__isl_give isl_qpolynomial *isl_qpolynomial_one_on_domain(1934	__isl_take isl_space *domain)1935{1936	if (!domain)1937		return NULL;1938	return isl_qpolynomial_alloc(domain, 0, isl_poly_one(domain->ctx));1939}1940 1941__isl_give isl_qpolynomial *isl_qpolynomial_infty_on_domain(1942	__isl_take isl_space *domain)1943{1944	if (!domain)1945		return NULL;1946	return isl_qpolynomial_alloc(domain, 0, isl_poly_infty(domain->ctx));1947}1948 1949__isl_give isl_qpolynomial *isl_qpolynomial_neginfty_on_domain(1950	__isl_take isl_space *domain)1951{1952	if (!domain)1953		return NULL;1954	return isl_qpolynomial_alloc(domain, 0, isl_poly_neginfty(domain->ctx));1955}1956 1957__isl_give isl_qpolynomial *isl_qpolynomial_nan_on_domain(1958	__isl_take isl_space *domain)1959{1960	if (!domain)1961		return NULL;1962	return isl_qpolynomial_alloc(domain, 0, isl_poly_nan(domain->ctx));1963}1964 1965__isl_give isl_qpolynomial *isl_qpolynomial_cst_on_domain(1966	__isl_take isl_space *domain,1967	isl_int v)1968{1969	struct isl_qpolynomial *qp;1970	isl_poly_cst *cst;1971 1972	qp = isl_qpolynomial_zero_on_domain(domain);1973	if (!qp)1974		return NULL;1975 1976	cst = isl_poly_as_cst(qp->poly);1977	isl_int_set(cst->n, v);1978 1979	return qp;1980}1981 1982isl_bool isl_qpolynomial_is_cst(__isl_keep isl_qpolynomial *qp,1983	isl_int *n, isl_int *d)1984{1985	isl_bool is_cst;1986	isl_poly_cst *cst;1987 1988	if (!qp)1989		return isl_bool_error;1990 1991	is_cst = isl_poly_is_cst(qp->poly);1992	if (is_cst < 0 || !is_cst)1993		return is_cst;1994 1995	cst = isl_poly_as_cst(qp->poly);1996	if (!cst)1997		return isl_bool_error;1998 1999	if (n)2000		isl_int_set(*n, cst->n);2001	if (d)2002		isl_int_set(*d, cst->d);2003 2004	return isl_bool_true;2005}2006 2007/* Return the constant term of "poly".2008 */2009static __isl_give isl_val *isl_poly_get_constant_val(__isl_keep isl_poly *poly)2010{2011	isl_bool is_cst;2012	isl_poly_cst *cst;2013 2014	if (!poly)2015		return NULL;2016 2017	while ((is_cst = isl_poly_is_cst(poly)) == isl_bool_false) {2018		isl_poly_rec *rec;2019 2020		rec = isl_poly_as_rec(poly);2021		if (!rec)2022			return NULL;2023		poly = rec->p[0];2024	}2025	if (is_cst < 0)2026		return NULL;2027 2028	cst = isl_poly_as_cst(poly);2029	if (!cst)2030		return NULL;2031	return isl_val_rat_from_isl_int(cst->poly.ctx, cst->n, cst->d);2032}2033 2034/* Return the constant term of "qp".2035 */2036__isl_give isl_val *isl_qpolynomial_get_constant_val(2037	__isl_keep isl_qpolynomial *qp)2038{2039	if (!qp)2040		return NULL;2041 2042	return isl_poly_get_constant_val(qp->poly);2043}2044 2045isl_bool isl_poly_is_affine(__isl_keep isl_poly *poly)2046{2047	isl_bool is_cst;2048	isl_poly_rec *rec;2049 2050	if (!poly)2051		return isl_bool_error;2052 2053	if (poly->var < 0)2054		return isl_bool_true;2055 2056	rec = isl_poly_as_rec(poly);2057	if (!rec)2058		return isl_bool_error;2059 2060	if (rec->n > 2)2061		return isl_bool_false;2062 2063	isl_assert(poly->ctx, rec->n > 1, return isl_bool_error);2064 2065	is_cst = isl_poly_is_cst(rec->p[1]);2066	if (is_cst < 0 || !is_cst)2067		return is_cst;2068 2069	return isl_poly_is_affine(rec->p[0]);2070}2071 2072isl_bool isl_qpolynomial_is_affine(__isl_keep isl_qpolynomial *qp)2073{2074	if (!qp)2075		return isl_bool_error;2076 2077	if (qp->div->n_row > 0)2078		return isl_bool_false;2079 2080	return isl_poly_is_affine(qp->poly);2081}2082 2083static void update_coeff(__isl_keep isl_vec *aff,2084	__isl_keep isl_poly_cst *cst, int pos)2085{2086	isl_int gcd;2087	isl_int f;2088 2089	if (isl_int_is_zero(cst->n))2090		return;2091 2092	isl_int_init(gcd);2093	isl_int_init(f);2094	isl_int_gcd(gcd, cst->d, aff->el[0]);2095	isl_int_divexact(f, cst->d, gcd);2096	isl_int_divexact(gcd, aff->el[0], gcd);2097	isl_seq_scale(aff->el, aff->el, f, aff->size);2098	isl_int_mul(aff->el[1 + pos], gcd, cst->n);2099	isl_int_clear(gcd);2100	isl_int_clear(f);2101}2102 2103int isl_poly_update_affine(__isl_keep isl_poly *poly, __isl_keep isl_vec *aff)2104{2105	isl_poly_cst *cst;2106	isl_poly_rec *rec;2107 2108	if (!poly || !aff)2109		return -1;2110 2111	if (poly->var < 0) {2112		isl_poly_cst *cst;2113 2114		cst = isl_poly_as_cst(poly);2115		if (!cst)2116			return -1;2117		update_coeff(aff, cst, 0);2118		return 0;2119	}2120 2121	rec = isl_poly_as_rec(poly);2122	if (!rec)2123		return -1;2124	isl_assert(poly->ctx, rec->n == 2, return -1);2125 2126	cst = isl_poly_as_cst(rec->p[1]);2127	if (!cst)2128		return -1;2129	update_coeff(aff, cst, 1 + poly->var);2130 2131	return isl_poly_update_affine(rec->p[0], aff);2132}2133 2134__isl_give isl_vec *isl_qpolynomial_extract_affine(2135	__isl_keep isl_qpolynomial *qp)2136{2137	isl_vec *aff;2138	isl_size d;2139 2140	d = isl_qpolynomial_domain_dim(qp, isl_dim_all);2141	if (d < 0)2142		return NULL;2143 2144	aff = isl_vec_alloc(qp->div->ctx, 2 + d);2145	if (!aff)2146		return NULL;2147 2148	isl_seq_clr(aff->el + 1, 1 + d);2149	isl_int_set_si(aff->el[0], 1);2150 2151	if (isl_poly_update_affine(qp->poly, aff) < 0)2152		goto error;2153 2154	return aff;2155error:2156	isl_vec_free(aff);2157	return NULL;2158}2159 2160/* Compare two quasi-polynomials.2161 *2162 * Return -1 if "qp1" is "smaller" than "qp2", 1 if "qp1" is "greater"2163 * than "qp2" and 0 if they are equal.2164 */2165int isl_qpolynomial_plain_cmp(__isl_keep isl_qpolynomial *qp1,2166	__isl_keep isl_qpolynomial *qp2)2167{2168	int cmp;2169 2170	if (qp1 == qp2)2171		return 0;2172	if (!qp1)2173		return -1;2174	if (!qp2)2175		return 1;2176 2177	cmp = isl_space_cmp(qp1->dim, qp2->dim);2178	if (cmp != 0)2179		return cmp;2180 2181	cmp = isl_local_cmp(qp1->div, qp2->div);2182	if (cmp != 0)2183		return cmp;2184 2185	return isl_poly_plain_cmp(qp1->poly, qp2->poly);2186}2187 2188/* Is "qp1" obviously equal to "qp2"?2189 *2190 * NaN is not equal to anything, not even to another NaN.2191 */2192isl_bool isl_qpolynomial_plain_is_equal(__isl_keep isl_qpolynomial *qp1,2193	__isl_keep isl_qpolynomial *qp2)2194{2195	isl_bool equal;2196 2197	if (!qp1 || !qp2)2198		return isl_bool_error;2199 2200	if (isl_qpolynomial_is_nan(qp1) || isl_qpolynomial_is_nan(qp2))2201		return isl_bool_false;2202 2203	equal = isl_space_is_equal(qp1->dim, qp2->dim);2204	if (equal < 0 || !equal)2205		return equal;2206 2207	equal = isl_mat_is_equal(qp1->div, qp2->div);2208	if (equal < 0 || !equal)2209		return equal;2210 2211	return isl_poly_is_equal(qp1->poly, qp2->poly);2212}2213 2214static isl_stat poly_update_den(__isl_keep isl_poly *poly, isl_int *d)2215{2216	int i;2217	isl_bool is_cst;2218	isl_poly_rec *rec;2219 2220	is_cst = isl_poly_is_cst(poly);2221	if (is_cst < 0)2222		return isl_stat_error;2223	if (is_cst) {2224		isl_poly_cst *cst;2225		cst = isl_poly_as_cst(poly);2226		if (!cst)2227			return isl_stat_error;2228		isl_int_lcm(*d, *d, cst->d);2229		return isl_stat_ok;2230	}2231 2232	rec = isl_poly_as_rec(poly);2233	if (!rec)2234		return isl_stat_error;2235 2236	for (i = 0; i < rec->n; ++i)2237		poly_update_den(rec->p[i], d);2238 2239	return isl_stat_ok;2240}2241 2242__isl_give isl_val *isl_qpolynomial_get_den(__isl_keep isl_qpolynomial *qp)2243{2244	isl_val *d;2245 2246	if (!qp)2247		return NULL;2248	d = isl_val_one(isl_qpolynomial_get_ctx(qp));2249	if (!d)2250		return NULL;2251	if (poly_update_den(qp->poly, &d->n) < 0)2252		return isl_val_free(d);2253	return d;2254}2255 2256__isl_give isl_qpolynomial *isl_qpolynomial_var_pow_on_domain(2257	__isl_take isl_space *domain, int pos, int power)2258{2259	struct isl_ctx *ctx;2260 2261	if (!domain)2262		return NULL;2263 2264	ctx = domain->ctx;2265 2266	return isl_qpolynomial_alloc(domain, 0,2267					isl_poly_var_pow(ctx, pos, power));2268}2269 2270__isl_give isl_qpolynomial *isl_qpolynomial_var_on_domain(2271	__isl_take isl_space *domain, enum isl_dim_type type, unsigned pos)2272{2273	if (isl_space_check_is_set(domain ) < 0)2274		goto error;2275	if (isl_space_check_range(domain, type, pos, 1) < 0)2276		goto error;2277 2278	pos += isl_space_offset(domain, type);2279 2280	return isl_qpolynomial_var_pow_on_domain(domain, pos, 1);2281error:2282	isl_space_free(domain);2283	return NULL;2284}2285 2286__isl_give isl_poly *isl_poly_subs(__isl_take isl_poly *poly,2287	unsigned first, unsigned n, __isl_keep isl_poly **subs)2288{2289	int i;2290	isl_bool is_cst;2291	isl_poly_rec *rec;2292	isl_poly *base, *res;2293 2294	is_cst = isl_poly_is_cst(poly);2295	if (is_cst < 0)2296		return isl_poly_free(poly);2297	if (is_cst)2298		return poly;2299 2300	if (poly->var < first)2301		return poly;2302 2303	rec = isl_poly_as_rec(poly);2304	if (!rec)2305		goto error;2306 2307	isl_assert(poly->ctx, rec->n >= 1, goto error);2308 2309	if (poly->var >= first + n)2310		base = isl_poly_var_pow(poly->ctx, poly->var, 1);2311	else2312		base = isl_poly_copy(subs[poly->var - first]);2313 2314	res = isl_poly_subs(isl_poly_copy(rec->p[rec->n - 1]), first, n, subs);2315	for (i = rec->n - 2; i >= 0; --i) {2316		isl_poly *t;2317		t = isl_poly_subs(isl_poly_copy(rec->p[i]), first, n, subs);2318		res = isl_poly_mul(res, isl_poly_copy(base));2319		res = isl_poly_sum(res, t);2320	}2321 2322	isl_poly_free(base);2323	isl_poly_free(poly);2324				2325	return res;2326error:2327	isl_poly_free(poly);2328	return NULL;2329}	2330 2331__isl_give isl_poly *isl_poly_from_affine(isl_ctx *ctx, isl_int *f,2332	isl_int denom, unsigned len)2333{2334	int i;2335	isl_poly *poly;2336 2337	isl_assert(ctx, len >= 1, return NULL);2338 2339	poly = isl_poly_rat_cst(ctx, f[0], denom);2340	for (i = 0; i < len - 1; ++i) {2341		isl_poly *t;2342		isl_poly *c;2343 2344		if (isl_int_is_zero(f[1 + i]))2345			continue;2346 2347		c = isl_poly_rat_cst(ctx, f[1 + i], denom);2348		t = isl_poly_var_pow(ctx, i, 1);2349		t = isl_poly_mul(c, t);2350		poly = isl_poly_sum(poly, t);2351	}2352 2353	return poly;2354}2355 2356/* Remove common factor of non-constant terms and denominator.2357 */2358static void normalize_div(__isl_keep isl_qpolynomial *qp, int div)2359{2360	isl_ctx *ctx = qp->div->ctx;2361	unsigned total = qp->div->n_col - 2;2362 2363	isl_seq_gcd(qp->div->row[div] + 2, total, &ctx->normalize_gcd);2364	isl_int_gcd(ctx->normalize_gcd,2365		    ctx->normalize_gcd, qp->div->row[div][0]);2366	if (isl_int_is_one(ctx->normalize_gcd))2367		return;2368 2369	isl_seq_scale_down(qp->div->row[div] + 2, qp->div->row[div] + 2,2370			    ctx->normalize_gcd, total);2371	isl_int_divexact(qp->div->row[div][0], qp->div->row[div][0],2372			    ctx->normalize_gcd);2373	isl_int_fdiv_q(qp->div->row[div][1], qp->div->row[div][1],2374			    ctx->normalize_gcd);2375}2376 2377/* Replace the integer division identified by "div" by the polynomial "s".2378 * The integer division is assumed not to appear in the definition2379 * of any other integer divisions.2380 */2381static __isl_give isl_qpolynomial *substitute_div(2382	__isl_take isl_qpolynomial *qp, int div, __isl_take isl_poly *s)2383{2384	int i;2385	isl_size div_pos;2386	int *reordering;2387	isl_ctx *ctx;2388 2389	if (!qp || !s)2390		goto error;2391 2392	qp = isl_qpolynomial_cow(qp);2393	if (!qp)2394		goto error;2395 2396	div_pos = isl_qpolynomial_domain_var_offset(qp, isl_dim_div);2397	if (div_pos < 0)2398		goto error;2399	qp->poly = isl_poly_subs(qp->poly, div_pos + div, 1, &s);2400	if (!qp->poly)2401		goto error;2402 2403	ctx = isl_qpolynomial_get_ctx(qp);2404	reordering = isl_alloc_array(ctx, int, div_pos + qp->div->n_row);2405	if (!reordering)2406		goto error;2407	for (i = 0; i < div_pos + div; ++i)2408		reordering[i] = i;2409	for (i = div_pos + div + 1; i < div_pos + qp->div->n_row; ++i)2410		reordering[i] = i - 1;2411	qp->div = isl_mat_drop_rows(qp->div, div, 1);2412	qp->div = isl_mat_drop_cols(qp->div, 2 + div_pos + div, 1);2413	qp->poly = reorder(qp->poly, reordering);2414	free(reordering);2415 2416	if (!qp->poly || !qp->div)2417		goto error;2418 2419	isl_poly_free(s);2420	return qp;2421error:2422	isl_qpolynomial_free(qp);2423	isl_poly_free(s);2424	return NULL;2425}2426 2427/* Replace all integer divisions [e/d] that turn out to not actually be integer2428 * divisions because d is equal to 1 by their definition, i.e., e.2429 */2430static __isl_give isl_qpolynomial *substitute_non_divs(2431	__isl_take isl_qpolynomial *qp)2432{2433	int i, j;2434	isl_size div_pos;2435	isl_poly *s;2436 2437	div_pos = isl_qpolynomial_domain_var_offset(qp, isl_dim_div);2438	if (div_pos < 0)2439		return isl_qpolynomial_free(qp);2440 2441	for (i = 0; qp && i < qp->div->n_row; ++i) {2442		if (!isl_int_is_one(qp->div->row[i][0]))2443			continue;2444		for (j = i + 1; j < qp->div->n_row; ++j) {2445			if (isl_int_is_zero(qp->div->row[j][2 + div_pos + i]))2446				continue;2447			isl_seq_combine(qp->div->row[j] + 1,2448				qp->div->ctx->one, qp->div->row[j] + 1,2449				qp->div->row[j][2 + div_pos + i],2450				qp->div->row[i] + 1, 1 + div_pos + i);2451			isl_int_set_si(qp->div->row[j][2 + div_pos + i], 0);2452			normalize_div(qp, j);2453		}2454		s = isl_poly_from_affine(qp->dim->ctx, qp->div->row[i] + 1,2455					qp->div->row[i][0], qp->div->n_col - 1);2456		qp = substitute_div(qp, i, s);2457		--i;2458	}2459 2460	return qp;2461}2462 2463/* Reduce the coefficients of div "div" to lie in the interval [0, d-1],2464 * with d the denominator.  When replacing the coefficient e of x by2465 * d * frac(e/d) = e - d * floor(e/d), we are subtracting d * floor(e/d) * x2466 * inside the division, so we need to add floor(e/d) * x outside.2467 * That is, we replace q by q' + floor(e/d) * x and we therefore need2468 * to adjust the coefficient of x in each later div that depends on the2469 * current div "div" and also in the affine expressions in the rows of "mat"2470 * (if they too depend on "div").2471 */2472static void reduce_div(__isl_keep isl_qpolynomial *qp, int div,2473	__isl_keep isl_mat **mat)2474{2475	int i, j;2476	isl_int v;2477	unsigned total = qp->div->n_col - qp->div->n_row - 2;2478 2479	isl_int_init(v);2480	for (i = 0; i < 1 + total + div; ++i) {2481		if (isl_int_is_nonneg(qp->div->row[div][1 + i]) &&2482		    isl_int_lt(qp->div->row[div][1 + i], qp->div->row[div][0]))2483			continue;2484		isl_int_fdiv_q(v, qp->div->row[div][1 + i], qp->div->row[div][0]);2485		isl_int_fdiv_r(qp->div->row[div][1 + i],2486				qp->div->row[div][1 + i], qp->div->row[div][0]);2487		*mat = isl_mat_col_addmul(*mat, i, v, 1 + total + div);2488		for (j = div + 1; j < qp->div->n_row; ++j) {2489			if (isl_int_is_zero(qp->div->row[j][2 + total + div]))2490				continue;2491			isl_int_addmul(qp->div->row[j][1 + i],2492					v, qp->div->row[j][2 + total + div]);2493		}2494	}2495	isl_int_clear(v);2496}2497 2498/* Check if the last non-zero coefficient is bigger that half of the2499 * denominator.  If so, we will invert the div to further reduce the number2500 * of distinct divs that may appear.2501 * If the last non-zero coefficient is exactly half the denominator,2502 * then we continue looking for earlier coefficients that are bigger2503 * than half the denominator.2504 */2505static int needs_invert(__isl_keep isl_mat *div, int row)2506{2507	int i;2508	int cmp;2509 2510	for (i = div->n_col - 1; i >= 1; --i) {2511		if (isl_int_is_zero(div->row[row][i]))2512			continue;2513		isl_int_mul_ui(div->row[row][i], div->row[row][i], 2);2514		cmp = isl_int_cmp(div->row[row][i], div->row[row][0]);2515		isl_int_divexact_ui(div->row[row][i], div->row[row][i], 2);2516		if (cmp)2517			return cmp > 0;2518		if (i == 1)2519			return 1;2520	}2521 2522	return 0;2523}2524 2525/* Replace div "div" q = [e/d] by -[(-e+(d-1))/d].2526 * We only invert the coefficients of e (and the coefficient of q in2527 * later divs and in the rows of "mat").  After calling this function, the2528 * coefficients of e should be reduced again.2529 */2530static void invert_div(__isl_keep isl_qpolynomial *qp, int div,2531	__isl_keep isl_mat **mat)2532{2533	unsigned total = qp->div->n_col - qp->div->n_row - 2;2534 2535	isl_seq_neg(qp->div->row[div] + 1,2536		    qp->div->row[div] + 1, qp->div->n_col - 1);2537	isl_int_sub_ui(qp->div->row[div][1], qp->div->row[div][1], 1);2538	isl_int_add(qp->div->row[div][1],2539		    qp->div->row[div][1], qp->div->row[div][0]);2540	*mat = isl_mat_col_neg(*mat, 1 + total + div);2541	isl_mat_col_mul(qp->div, 2 + total + div,2542			qp->div->ctx->negone, 2 + total + div);2543}2544 2545/* Reduce all divs of "qp" to have coefficients2546 * in the interval [0, d-1], with d the denominator and such that the2547 * last non-zero coefficient that is not equal to d/2 is smaller than d/2.2548 * The modifications to the integer divisions need to be reflected2549 * in the factors of the polynomial that refer to the original2550 * integer divisions.  To this end, the modifications are collected2551 * as a set of affine expressions and then plugged into the polynomial.2552 *2553 * After the reduction, some divs may have become redundant or identical,2554 * so we call substitute_non_divs and sort_divs.  If these functions2555 * eliminate divs or merge two or more divs into one, the coefficients2556 * of the enclosing divs may have to be reduced again, so we call2557 * ourselves recursively if the number of divs decreases.2558 */2559static __isl_give isl_qpolynomial *reduce_divs(__isl_take isl_qpolynomial *qp)2560{2561	int i;2562	isl_ctx *ctx;2563	isl_mat *mat;2564	isl_poly **s;2565	unsigned o_div;2566	isl_size n_div, total, new_n_div;2567 2568	total = isl_qpolynomial_domain_dim(qp, isl_dim_all);2569	n_div = isl_qpolynomial_domain_dim(qp, isl_dim_div);2570	o_div = isl_qpolynomial_domain_offset(qp, isl_dim_div);2571	if (total < 0 || n_div < 0)2572		return isl_qpolynomial_free(qp);2573	ctx = isl_qpolynomial_get_ctx(qp);2574	mat = isl_mat_zero(ctx, n_div, 1 + total);2575 2576	for (i = 0; i < n_div; ++i)2577		mat = isl_mat_set_element_si(mat, i, o_div + i, 1);2578 2579	for (i = 0; i < qp->div->n_row; ++i) {2580		normalize_div(qp, i);2581		reduce_div(qp, i, &mat);2582		if (needs_invert(qp->div, i)) {2583			invert_div(qp, i, &mat);2584			reduce_div(qp, i, &mat);2585		}2586	}2587	if (!mat)2588		goto error;2589 2590	s = isl_alloc_array(ctx, struct isl_poly *, n_div);2591	if (n_div && !s)2592		goto error;2593	for (i = 0; i < n_div; ++i)2594		s[i] = isl_poly_from_affine(ctx, mat->row[i], ctx->one,2595					    1 + total);2596	qp->poly = isl_poly_subs(qp->poly, o_div - 1, n_div, s);2597	for (i = 0; i < n_div; ++i)2598		isl_poly_free(s[i]);2599	free(s);2600	if (!qp->poly)2601		goto error;2602 2603	isl_mat_free(mat);2604 2605	qp = substitute_non_divs(qp);2606	qp = sort_divs(qp);2607	new_n_div = isl_qpolynomial_domain_dim(qp, isl_dim_div);2608	if (new_n_div < 0)2609		return isl_qpolynomial_free(qp);2610	if (new_n_div < n_div)2611		return reduce_divs(qp);2612 2613	return qp;2614error:2615	isl_qpolynomial_free(qp);2616	isl_mat_free(mat);2617	return NULL;2618}2619 2620__isl_give isl_qpolynomial *isl_qpolynomial_rat_cst_on_domain(2621	__isl_take isl_space *domain, const isl_int n, const isl_int d)2622{2623	struct isl_qpolynomial *qp;2624	isl_poly_cst *cst;2625 2626	qp = isl_qpolynomial_zero_on_domain(domain);2627	if (!qp)2628		return NULL;2629 2630	cst = isl_poly_as_cst(qp->poly);2631	isl_int_set(cst->n, n);2632	isl_int_set(cst->d, d);2633 2634	return qp;2635}2636 2637/* Return an isl_qpolynomial that is equal to "val" on domain space "domain".2638 */2639__isl_give isl_qpolynomial *isl_qpolynomial_val_on_domain(2640	__isl_take isl_space *domain, __isl_take isl_val *val)2641{2642	isl_qpolynomial *qp;2643	isl_poly_cst *cst;2644 2645	qp = isl_qpolynomial_zero_on_domain(domain);2646	if (!qp || !val)2647		goto error;2648 2649	cst = isl_poly_as_cst(qp->poly);2650	isl_int_set(cst->n, val->n);2651	isl_int_set(cst->d, val->d);2652 2653	isl_val_free(val);2654	return qp;2655error:2656	isl_val_free(val);2657	isl_qpolynomial_free(qp);2658	return NULL;2659}2660 2661static isl_stat poly_set_active(__isl_keep isl_poly *poly, int *active, int d)2662{2663	isl_bool is_cst;2664	isl_poly_rec *rec;2665	int i;2666 2667	is_cst = isl_poly_is_cst(poly);2668	if (is_cst < 0)2669		return isl_stat_error;2670	if (is_cst)2671		return isl_stat_ok;2672 2673	if (poly->var < d)2674		active[poly->var] = 1;2675 2676	rec = isl_poly_as_rec(poly);2677	for (i = 0; i < rec->n; ++i)2678		if (poly_set_active(rec->p[i], active, d) < 0)2679			return isl_stat_error;2680 2681	return isl_stat_ok;2682}2683 2684static isl_stat set_active(__isl_keep isl_qpolynomial *qp, int *active)2685{2686	int i, j;2687	isl_size d;2688	isl_space *space;2689 2690	space = isl_qpolynomial_peek_domain_space(qp);2691	d = isl_space_dim(space, isl_dim_all);2692	if (d < 0 || !active)2693		return isl_stat_error;2694 2695	for (i = 0; i < d; ++i)2696		for (j = 0; j < qp->div->n_row; ++j) {2697			if (isl_int_is_zero(qp->div->row[j][2 + i]))2698				continue;2699			active[i] = 1;2700			break;2701		}2702 2703	return poly_set_active(qp->poly, active, d);2704}2705 2706#undef TYPE2707#define TYPE	isl_qpolynomial2708static2709#include "check_type_range_templ.c"2710 2711isl_bool isl_qpolynomial_involves_dims(__isl_keep isl_qpolynomial *qp,2712	enum isl_dim_type type, unsigned first, unsigned n)2713{2714	int i;2715	int *active = NULL;2716	isl_bool involves = isl_bool_false;2717	isl_size offset;2718	isl_size d;2719	isl_space *space;2720 2721	if (!qp)2722		return isl_bool_error;2723	if (n == 0)2724		return isl_bool_false;2725 2726	if (isl_qpolynomial_check_range(qp, type, first, n) < 0)2727		return isl_bool_error;2728	isl_assert(qp->dim->ctx, type == isl_dim_param ||2729				 type == isl_dim_in, return isl_bool_error);2730 2731	space = isl_qpolynomial_peek_domain_space(qp);2732	d = isl_space_dim(space, isl_dim_all);2733	if (d < 0)2734		return isl_bool_error;2735	active = isl_calloc_array(qp->dim->ctx, int, d);2736	if (set_active(qp, active) < 0)2737		goto error;2738 2739	offset = isl_qpolynomial_domain_var_offset(qp, domain_type(type));2740	if (offset < 0)2741		goto error;2742	first += offset;2743	for (i = 0; i < n; ++i)2744		if (active[first + i]) {2745			involves = isl_bool_true;2746			break;2747		}2748 2749	free(active);2750 2751	return involves;2752error:2753	free(active);2754	return isl_bool_error;2755}2756 2757/* Remove divs that do not appear in the quasi-polynomial, nor in any2758 * of the divs that do appear in the quasi-polynomial.2759 */2760static __isl_give isl_qpolynomial *remove_redundant_divs(2761	__isl_take isl_qpolynomial *qp)2762{2763	int i, j;2764	isl_size div_pos;2765	int len;2766	int skip;2767	int *active = NULL;2768	int *reordering = NULL;2769	int redundant = 0;2770	int n_div;2771	isl_ctx *ctx;2772 2773	if (!qp)2774		return NULL;2775	if (qp->div->n_row == 0)2776		return qp;2777 2778	div_pos = isl_qpolynomial_domain_var_offset(qp, isl_dim_div);2779	if (div_pos < 0)2780		return isl_qpolynomial_free(qp);2781	len = qp->div->n_col - 2;2782	ctx = isl_qpolynomial_get_ctx(qp);2783	active = isl_calloc_array(ctx, int, len);2784	if (!active)2785		goto error;2786 2787	if (poly_set_active(qp->poly, active, len) < 0)2788		goto error;2789 2790	for (i = qp->div->n_row - 1; i >= 0; --i) {2791		if (!active[div_pos + i]) {2792			redundant = 1;2793			continue;2794		}2795		for (j = 0; j < i; ++j) {2796			if (isl_int_is_zero(qp->div->row[i][2 + div_pos + j]))2797				continue;2798			active[div_pos + j] = 1;2799			break;2800		}2801	}2802 2803	if (!redundant) {2804		free(active);2805		return qp;2806	}2807 2808	reordering = isl_alloc_array(qp->div->ctx, int, len);2809	if (!reordering)2810		goto error;2811 2812	for (i = 0; i < div_pos; ++i)2813		reordering[i] = i;2814 2815	skip = 0;2816	n_div = qp->div->n_row;2817	for (i = 0; i < n_div; ++i) {2818		if (!active[div_pos + i]) {2819			qp->div = isl_mat_drop_rows(qp->div, i - skip, 1);2820			qp->div = isl_mat_drop_cols(qp->div,2821						    2 + div_pos + i - skip, 1);2822			skip++;2823		}2824		reordering[div_pos + i] = div_pos + i - skip;2825	}2826 2827	qp->poly = reorder(qp->poly, reordering);2828 2829	if (!qp->poly || !qp->div)2830		goto error;2831 2832	free(active);2833	free(reordering);2834 2835	return qp;2836error:2837	free(active);2838	free(reordering);2839	isl_qpolynomial_free(qp);2840	return NULL;2841}2842 2843__isl_give isl_poly *isl_poly_drop(__isl_take isl_poly *poly,2844	unsigned first, unsigned n)2845{2846	int i;2847	isl_poly_rec *rec;2848 2849	if (!poly)2850		return NULL;2851	if (n == 0 || poly->var < 0 || poly->var < first)2852		return poly;2853	if (poly->var < first + n) {2854		poly = replace_by_constant_term(poly);2855		return isl_poly_drop(poly, first, n);2856	}2857	poly = isl_poly_cow(poly);2858	if (!poly)2859		return NULL;2860	poly->var -= n;2861	rec = isl_poly_as_rec(poly);2862	if (!rec)2863		goto error;2864 2865	for (i = 0; i < rec->n; ++i) {2866		rec->p[i] = isl_poly_drop(rec->p[i], first, n);2867		if (!rec->p[i])2868			goto error;2869	}2870 2871	return poly;2872error:2873	isl_poly_free(poly);2874	return NULL;2875}2876 2877__isl_give isl_qpolynomial *isl_qpolynomial_set_dim_name(2878	__isl_take isl_qpolynomial *qp,2879	enum isl_dim_type type, unsigned pos, const char *s)2880{2881	qp = isl_qpolynomial_cow(qp);2882	if (!qp)2883		return NULL;2884	if (type == isl_dim_out)2885		isl_die(isl_qpolynomial_get_ctx(qp), isl_error_invalid,2886			"cannot set name of output/set dimension",2887			return isl_qpolynomial_free(qp));2888	type = domain_type(type);2889	qp->dim = isl_space_set_dim_name(qp->dim, type, pos, s);2890	if (!qp->dim)2891		goto error;2892	return qp;2893error:2894	isl_qpolynomial_free(qp);2895	return NULL;2896}2897 2898__isl_give isl_qpolynomial *isl_qpolynomial_drop_dims(2899	__isl_take isl_qpolynomial *qp,2900	enum isl_dim_type type, unsigned first, unsigned n)2901{2902	isl_size offset;2903 2904	if (!qp)2905		return NULL;2906	if (type == isl_dim_out)2907		isl_die(qp->dim->ctx, isl_error_invalid,2908			"cannot drop output/set dimension",2909			goto error);2910	if (isl_qpolynomial_check_range(qp, type, first, n) < 0)2911		return isl_qpolynomial_free(qp);2912	type = domain_type(type);2913	if (n == 0 && !isl_space_is_named_or_nested(qp->dim, type))2914		return qp;2915 2916	qp = isl_qpolynomial_cow(qp);2917	if (!qp)2918		return NULL;2919 2920	isl_assert(qp->dim->ctx, type == isl_dim_param ||2921				 type == isl_dim_set, goto error);2922 2923	qp->dim = isl_space_drop_dims(qp->dim, type, first, n);2924	if (!qp->dim)2925		goto error;2926 2927	offset = isl_qpolynomial_domain_var_offset(qp, type);2928	if (offset < 0)2929		goto error;2930	first += offset;2931 2932	qp->div = isl_mat_drop_cols(qp->div, 2 + first, n);2933	if (!qp->div)2934		goto error;2935 2936	qp->poly = isl_poly_drop(qp->poly, first, n);2937	if (!qp->poly)2938		goto error;2939 2940	return qp;2941error:2942	isl_qpolynomial_free(qp);2943	return NULL;2944}2945 2946/* Project the domain of the quasi-polynomial onto its parameter space.2947 * The quasi-polynomial may not involve any of the domain dimensions.2948 */2949__isl_give isl_qpolynomial *isl_qpolynomial_project_domain_on_params(2950	__isl_take isl_qpolynomial *qp)2951{2952	isl_space *space;2953	isl_size n;2954	isl_bool involves;2955 2956	n = isl_qpolynomial_dim(qp, isl_dim_in);2957	if (n < 0)2958		return isl_qpolynomial_free(qp);2959	involves = isl_qpolynomial_involves_dims(qp, isl_dim_in, 0, n);2960	if (involves < 0)2961		return isl_qpolynomial_free(qp);2962	if (involves)2963		isl_die(isl_qpolynomial_get_ctx(qp), isl_error_invalid,2964			"polynomial involves some of the domain dimensions",2965			return isl_qpolynomial_free(qp));2966	qp = isl_qpolynomial_drop_dims(qp, isl_dim_in, 0, n);2967	space = isl_qpolynomial_get_domain_space(qp);2968	space = isl_space_params(space);2969	qp = isl_qpolynomial_reset_domain_space(qp, space);2970	return qp;2971}2972 2973static __isl_give isl_qpolynomial *isl_qpolynomial_substitute_equalities_lifted(2974	__isl_take isl_qpolynomial *qp, __isl_take isl_basic_set *eq)2975{2976	int i, j, k;2977	isl_int denom;2978	unsigned total;2979	unsigned n_div;2980	isl_poly *poly;2981 2982	if (!eq)2983		goto error;2984	if (eq->n_eq == 0) {2985		isl_basic_set_free(eq);2986		return qp;2987	}2988 2989	qp = isl_qpolynomial_cow(qp);2990	if (!qp)2991		goto error;2992	qp->div = isl_mat_cow(qp->div);2993	if (!qp->div)2994		goto error;2995 2996	total = isl_basic_set_offset(eq, isl_dim_div);2997	n_div = eq->n_div;2998	isl_int_init(denom);2999	for (i = 0; i < eq->n_eq; ++i) {3000		j = isl_seq_last_non_zero(eq->eq[i], total + n_div);3001		if (j < 0 || j == 0 || j >= total)3002			continue;3003 3004		for (k = 0; k < qp->div->n_row; ++k) {3005			if (isl_int_is_zero(qp->div->row[k][1 + j]))3006				continue;3007			isl_seq_elim(qp->div->row[k] + 1, eq->eq[i], j, total,3008					&qp->div->row[k][0]);3009			normalize_div(qp, k);3010		}3011 3012		if (isl_int_is_pos(eq->eq[i][j]))3013			isl_seq_neg(eq->eq[i], eq->eq[i], total);3014		isl_int_abs(denom, eq->eq[i][j]);3015		isl_int_set_si(eq->eq[i][j], 0);3016 3017		poly = isl_poly_from_affine(qp->dim->ctx,3018						   eq->eq[i], denom, total);3019		qp->poly = isl_poly_subs(qp->poly, j - 1, 1, &poly);3020		isl_poly_free(poly);3021	}3022	isl_int_clear(denom);3023 3024	if (!qp->poly)3025		goto error;3026 3027	isl_basic_set_free(eq);3028 3029	qp = substitute_non_divs(qp);3030	qp = sort_divs(qp);3031 3032	return qp;3033error:3034	isl_basic_set_free(eq);3035	isl_qpolynomial_free(qp);3036	return NULL;3037}3038 3039/* Exploit the equalities in "eq" to simplify the quasi-polynomial.3040 */3041__isl_give isl_qpolynomial *isl_qpolynomial_substitute_equalities(3042	__isl_take isl_qpolynomial *qp, __isl_take isl_basic_set *eq)3043{3044	if (!qp || !eq)3045		goto error;3046	if (qp->div->n_row > 0)3047		eq = isl_basic_set_add_dims(eq, isl_dim_set, qp->div->n_row);3048	return isl_qpolynomial_substitute_equalities_lifted(qp, eq);3049error:3050	isl_basic_set_free(eq);3051	isl_qpolynomial_free(qp);3052	return NULL;3053}3054 3055/* Look for equalities among the variables shared by context and qp3056 * and the integer divisions of qp, if any.3057 * The equalities are then used to eliminate variables and/or integer3058 * divisions from qp.3059 */3060__isl_give isl_qpolynomial *isl_qpolynomial_gist(3061	__isl_take isl_qpolynomial *qp, __isl_take isl_set *context)3062{3063	isl_local_space *ls;3064	isl_basic_set *aff;3065 3066	ls = isl_qpolynomial_get_domain_local_space(qp);3067	context = isl_local_space_lift_set(ls, context);3068 3069	aff = isl_set_affine_hull(context);3070	return isl_qpolynomial_substitute_equalities_lifted(qp, aff);3071}3072 3073__isl_give isl_qpolynomial *isl_qpolynomial_gist_params(3074	__isl_take isl_qpolynomial *qp, __isl_take isl_set *context)3075{3076	isl_space *space = isl_qpolynomial_get_domain_space(qp);3077	isl_set *dom_context = isl_set_universe(space);3078	dom_context = isl_set_intersect_params(dom_context, context);3079	return isl_qpolynomial_gist(qp, dom_context);3080}3081 3082/* Return a zero isl_qpolynomial in the given space.3083 *3084 * This is a helper function for isl_pw_*_as_* that ensures a uniform3085 * interface over all piecewise types.3086 */3087static __isl_give isl_qpolynomial *isl_qpolynomial_zero_in_space(3088	__isl_take isl_space *space)3089{3090	return isl_qpolynomial_zero_on_domain(isl_space_domain(space));3091}3092 3093#define isl_qpolynomial_involves_nan isl_qpolynomial_is_nan3094 3095#undef PW3096#define PW isl_pw_qpolynomial3097#undef BASE3098#define BASE qpolynomial3099#undef EL_IS_ZERO3100#define EL_IS_ZERO is_zero3101#undef ZERO3102#define ZERO zero3103#undef IS_ZERO3104#define IS_ZERO is_zero3105#undef FIELD3106#define FIELD qp3107#undef DEFAULT_IS_ZERO3108#define DEFAULT_IS_ZERO 13109 3110#include <isl_pw_templ.c>3111#include <isl_pw_un_op_templ.c>3112#include <isl_pw_add_disjoint_templ.c>3113#include <isl_pw_eval.c>3114#include <isl_pw_fix_templ.c>3115#include <isl_pw_from_range_templ.c>3116#include <isl_pw_insert_dims_templ.c>3117#include <isl_pw_lift_templ.c>3118#include <isl_pw_morph_templ.c>3119#include <isl_pw_move_dims_templ.c>3120#include <isl_pw_neg_templ.c>3121#include <isl_pw_opt_templ.c>3122#include <isl_pw_split_dims_templ.c>3123#include <isl_pw_sub_templ.c>3124 3125#undef BASE3126#define BASE pw_qpolynomial3127 3128#include <isl_union_single.c>3129#include <isl_union_eval.c>3130#include <isl_union_neg.c>3131#include <isl_union_sub_templ.c>3132 3133int isl_pw_qpolynomial_is_one(__isl_keep isl_pw_qpolynomial *pwqp)3134{3135	if (!pwqp)3136		return -1;3137 3138	if (pwqp->n != -1)3139		return 0;3140 3141	if (!isl_set_plain_is_universe(pwqp->p[0].set))3142		return 0;3143 3144	return isl_qpolynomial_is_one(pwqp->p[0].qp);3145}3146 3147__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_add(3148	__isl_take isl_pw_qpolynomial *pwqp1,3149	__isl_take isl_pw_qpolynomial *pwqp2)3150{3151	return isl_pw_qpolynomial_union_add_(pwqp1, pwqp2);3152}3153 3154__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_mul(3155	__isl_take isl_pw_qpolynomial *pwqp1,3156	__isl_take isl_pw_qpolynomial *pwqp2)3157{3158	int i, j, n;3159	struct isl_pw_qpolynomial *res;3160 3161	if (!pwqp1 || !pwqp2)3162		goto error;3163 3164	isl_assert(pwqp1->dim->ctx, isl_space_is_equal(pwqp1->dim, pwqp2->dim),3165			goto error);3166 3167	if (isl_pw_qpolynomial_is_zero(pwqp1)) {3168		isl_pw_qpolynomial_free(pwqp2);3169		return pwqp1;3170	}3171 3172	if (isl_pw_qpolynomial_is_zero(pwqp2)) {3173		isl_pw_qpolynomial_free(pwqp1);3174		return pwqp2;3175	}3176 3177	if (isl_pw_qpolynomial_is_one(pwqp1)) {3178		isl_pw_qpolynomial_free(pwqp1);3179		return pwqp2;3180	}3181 3182	if (isl_pw_qpolynomial_is_one(pwqp2)) {3183		isl_pw_qpolynomial_free(pwqp2);3184		return pwqp1;3185	}3186 3187	n = pwqp1->n * pwqp2->n;3188	res = isl_pw_qpolynomial_alloc_size(isl_space_copy(pwqp1->dim), n);3189 3190	for (i = 0; i < pwqp1->n; ++i) {3191		for (j = 0; j < pwqp2->n; ++j) {3192			struct isl_set *common;3193			struct isl_qpolynomial *prod;3194			common = isl_set_intersect(isl_set_copy(pwqp1->p[i].set),3195						isl_set_copy(pwqp2->p[j].set));3196			if (isl_set_plain_is_empty(common)) {3197				isl_set_free(common);3198				continue;3199			}3200 3201			prod = isl_qpolynomial_mul(3202				isl_qpolynomial_copy(pwqp1->p[i].qp),3203				isl_qpolynomial_copy(pwqp2->p[j].qp));3204 3205			res = isl_pw_qpolynomial_add_piece(res, common, prod);3206		}3207	}3208 3209	isl_pw_qpolynomial_free(pwqp1);3210	isl_pw_qpolynomial_free(pwqp2);3211 3212	return res;3213error:3214	isl_pw_qpolynomial_free(pwqp1);3215	isl_pw_qpolynomial_free(pwqp2);3216	return NULL;3217}3218 3219__isl_give isl_val *isl_poly_eval(__isl_take isl_poly *poly,3220	__isl_take isl_vec *vec)3221{3222	int i;3223	isl_bool is_cst;3224	isl_poly_rec *rec;3225	isl_val *res;3226	isl_val *base;3227 3228	is_cst = isl_poly_is_cst(poly);3229	if (is_cst < 0)3230		goto error;3231	if (is_cst) {3232		isl_vec_free(vec);3233		res = isl_poly_get_constant_val(poly);3234		isl_poly_free(poly);3235		return res;3236	}3237 3238	rec = isl_poly_as_rec(poly);3239	if (!rec || !vec)3240		goto error;3241 3242	isl_assert(poly->ctx, rec->n >= 1, goto error);3243 3244	base = isl_val_rat_from_isl_int(poly->ctx,3245					vec->el[1 + poly->var], vec->el[0]);3246 3247	res = isl_poly_eval(isl_poly_copy(rec->p[rec->n - 1]),3248				isl_vec_copy(vec));3249 3250	for (i = rec->n - 2; i >= 0; --i) {3251		res = isl_val_mul(res, isl_val_copy(base));3252		res = isl_val_add(res, isl_poly_eval(isl_poly_copy(rec->p[i]),3253							    isl_vec_copy(vec)));3254	}3255 3256	isl_val_free(base);3257	isl_poly_free(poly);3258	isl_vec_free(vec);3259	return res;3260error:3261	isl_poly_free(poly);3262	isl_vec_free(vec);3263	return NULL;3264}3265 3266/* Evaluate "qp" in the void point "pnt".3267 * In particular, return the value NaN.3268 */3269static __isl_give isl_val *eval_void(__isl_take isl_qpolynomial *qp,3270	__isl_take isl_point *pnt)3271{3272	isl_ctx *ctx;3273 3274	ctx = isl_point_get_ctx(pnt);3275	isl_qpolynomial_free(qp);3276	isl_point_free(pnt);3277	return isl_val_nan(ctx);3278}3279 3280__isl_give isl_val *isl_qpolynomial_eval(__isl_take isl_qpolynomial *qp,3281	__isl_take isl_point *pnt)3282{3283	isl_bool is_void;3284	isl_vec *ext;3285	isl_val *v;3286 3287	if (!qp || !pnt)3288		goto error;3289	isl_assert(pnt->dim->ctx, isl_space_is_equal(pnt->dim, qp->dim), goto error);3290	is_void = isl_point_is_void(pnt);3291	if (is_void < 0)3292		goto error;3293	if (is_void)3294		return eval_void(qp, pnt);3295 3296	ext = isl_local_extend_point_vec(qp->div, isl_vec_copy(pnt->vec));3297 3298	v = isl_poly_eval(isl_poly_copy(qp->poly), ext);3299 3300	isl_qpolynomial_free(qp);3301	isl_point_free(pnt);3302 3303	return v;3304error:3305	isl_qpolynomial_free(qp);3306	isl_point_free(pnt);3307	return NULL;3308}3309 3310int isl_poly_cmp(__isl_keep isl_poly_cst *cst1, __isl_keep isl_poly_cst *cst2)3311{3312	int cmp;3313	isl_int t;3314	isl_int_init(t);3315	isl_int_mul(t, cst1->n, cst2->d);3316	isl_int_submul(t, cst2->n, cst1->d);3317	cmp = isl_int_sgn(t);3318	isl_int_clear(t);3319	return cmp;3320}3321 3322__isl_give isl_qpolynomial *isl_qpolynomial_insert_dims(3323	__isl_take isl_qpolynomial *qp, enum isl_dim_type type,3324	unsigned first, unsigned n)3325{3326	unsigned total;3327	unsigned g_pos;3328	int *exp;3329 3330	if (!qp)3331		return NULL;3332	if (type == isl_dim_out)3333		isl_die(qp->div->ctx, isl_error_invalid,3334			"cannot insert output/set dimensions",3335			goto error);3336	if (isl_qpolynomial_check_range(qp, type, first, 0) < 0)3337		return isl_qpolynomial_free(qp);3338	type = domain_type(type);3339	if (n == 0 && !isl_space_is_named_or_nested(qp->dim, type))3340		return qp;3341 3342	qp = isl_qpolynomial_cow(qp);3343	if (!qp)3344		return NULL;3345 3346	g_pos = pos(qp->dim, type) + first;3347 3348	qp->div = isl_mat_insert_zero_cols(qp->div, 2 + g_pos, n);3349	if (!qp->div)3350		goto error;3351 3352	total = qp->div->n_col - 2;3353	if (total > g_pos) {3354		int i;3355		exp = isl_alloc_array(qp->div->ctx, int, total - g_pos);3356		if (!exp)3357			goto error;3358		for (i = 0; i < total - g_pos; ++i)3359			exp[i] = i + n;3360		qp->poly = expand(qp->poly, exp, g_pos);3361		free(exp);3362		if (!qp->poly)3363			goto error;3364	}3365 3366	qp->dim = isl_space_insert_dims(qp->dim, type, first, n);3367	if (!qp->dim)3368		goto error;3369 3370	return qp;3371error:3372	isl_qpolynomial_free(qp);3373	return NULL;3374}3375 3376__isl_give isl_qpolynomial *isl_qpolynomial_add_dims(3377	__isl_take isl_qpolynomial *qp, enum isl_dim_type type, unsigned n)3378{3379	isl_size pos;3380 3381	pos = isl_qpolynomial_dim(qp, type);3382	if (pos < 0)3383		return isl_qpolynomial_free(qp);3384 3385	return isl_qpolynomial_insert_dims(qp, type, pos, n);3386}3387 3388static int *reordering_move(isl_ctx *ctx,3389	unsigned len, unsigned dst, unsigned src, unsigned n)3390{3391	int i;3392	int *reordering;3393 3394	reordering = isl_alloc_array(ctx, int, len);3395	if (!reordering)3396		return NULL;3397 3398	if (dst <= src) {3399		for (i = 0; i < dst; ++i)3400			reordering[i] = i;3401		for (i = 0; i < n; ++i)3402			reordering[src + i] = dst + i;3403		for (i = 0; i < src - dst; ++i)3404			reordering[dst + i] = dst + n + i;3405		for (i = 0; i < len - src - n; ++i)3406			reordering[src + n + i] = src + n + i;3407	} else {3408		for (i = 0; i < src; ++i)3409			reordering[i] = i;3410		for (i = 0; i < n; ++i)3411			reordering[src + i] = dst + i;3412		for (i = 0; i < dst - src; ++i)3413			reordering[src + n + i] = src + i;3414		for (i = 0; i < len - dst - n; ++i)3415			reordering[dst + n + i] = dst + n + i;3416	}3417 3418	return reordering;3419}3420 3421__isl_give isl_qpolynomial *isl_qpolynomial_move_dims(3422	__isl_take isl_qpolynomial *qp,3423	enum isl_dim_type dst_type, unsigned dst_pos,3424	enum isl_dim_type src_type, unsigned src_pos, unsigned n)3425{3426	unsigned g_dst_pos;3427	unsigned g_src_pos;3428	int *reordering;3429 3430	if (!qp)3431		return NULL;3432 3433	if (dst_type == isl_dim_out || src_type == isl_dim_out)3434		isl_die(qp->dim->ctx, isl_error_invalid,3435			"cannot move output/set dimension",3436			goto error);3437	if (isl_qpolynomial_check_range(qp, src_type, src_pos, n) < 0)3438		return isl_qpolynomial_free(qp);3439	if (dst_type == isl_dim_in)3440		dst_type = isl_dim_set;3441	if (src_type == isl_dim_in)3442		src_type = isl_dim_set;3443 3444	if (n == 0 &&3445	    !isl_space_is_named_or_nested(qp->dim, src_type) &&3446	    !isl_space_is_named_or_nested(qp->dim, dst_type))3447		return qp;3448 3449	qp = isl_qpolynomial_cow(qp);3450	if (!qp)3451		return NULL;3452 3453	g_dst_pos = pos(qp->dim, dst_type) + dst_pos;3454	g_src_pos = pos(qp->dim, src_type) + src_pos;3455	if (dst_type > src_type)3456		g_dst_pos -= n;3457 3458	qp->div = isl_mat_move_cols(qp->div, 2 + g_dst_pos, 2 + g_src_pos, n);3459	if (!qp->div)3460		goto error;3461	qp = sort_divs(qp);3462	if (!qp)3463		goto error;3464 3465	reordering = reordering_move(qp->dim->ctx,3466				qp->div->n_col - 2, g_dst_pos, g_src_pos, n);3467	if (!reordering)3468		goto error;3469 3470	qp->poly = reorder(qp->poly, reordering);3471	free(reordering);3472	if (!qp->poly)3473		goto error;3474 3475	qp->dim = isl_space_move_dims(qp->dim, dst_type, dst_pos, src_type, src_pos, n);3476	if (!qp->dim)3477		goto error;3478 3479	return qp;3480error:3481	isl_qpolynomial_free(qp);3482	return NULL;3483}3484 3485__isl_give isl_qpolynomial *isl_qpolynomial_from_affine(3486	__isl_take isl_space *space, isl_int *f, isl_int denom)3487{3488	isl_size d;3489	isl_poly *poly;3490 3491	space = isl_space_domain(space);3492	if (!space)3493		return NULL;3494 3495	d = isl_space_dim(space, isl_dim_all);3496	poly = d < 0 ? NULL : isl_poly_from_affine(space->ctx, f, denom, 1 + d);3497 3498	return isl_qpolynomial_alloc(space, 0, poly);3499}3500 3501__isl_give isl_qpolynomial *isl_qpolynomial_from_aff(__isl_take isl_aff *aff)3502{3503	isl_ctx *ctx;3504	isl_poly *poly;3505	isl_qpolynomial *qp;3506 3507	if (!aff)3508		return NULL;3509 3510	ctx = isl_aff_get_ctx(aff);3511	poly = isl_poly_from_affine(ctx, aff->v->el + 1, aff->v->el[0],3512				    aff->v->size - 1);3513 3514	qp = isl_qpolynomial_alloc(isl_aff_get_domain_space(aff),3515				    aff->ls->div->n_row, poly);3516	if (!qp)3517		goto error;3518 3519	isl_mat_free(qp->div);3520	qp->div = isl_mat_copy(aff->ls->div);3521	qp->div = isl_mat_cow(qp->div);3522	if (!qp->div)3523		goto error;3524 3525	isl_aff_free(aff);3526	qp = reduce_divs(qp);3527	qp = remove_redundant_divs(qp);3528	return qp;3529error:3530	isl_aff_free(aff);3531	return isl_qpolynomial_free(qp);3532}3533 3534__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_from_pw_aff(3535	__isl_take isl_pw_aff *pwaff)3536{3537	int i;3538	isl_pw_qpolynomial *pwqp;3539 3540	if (!pwaff)3541		return NULL;3542 3543	pwqp = isl_pw_qpolynomial_alloc_size(isl_pw_aff_get_space(pwaff),3544						pwaff->n);3545 3546	for (i = 0; i < pwaff->n; ++i) {3547		isl_set *dom;3548		isl_qpolynomial *qp;3549 3550		dom = isl_set_copy(pwaff->p[i].set);3551		qp = isl_qpolynomial_from_aff(isl_aff_copy(pwaff->p[i].aff));3552		pwqp = isl_pw_qpolynomial_add_piece(pwqp,  dom, qp);3553	}3554 3555	isl_pw_aff_free(pwaff);3556	return pwqp;3557}3558 3559__isl_give isl_qpolynomial *isl_qpolynomial_from_constraint(3560	__isl_take isl_constraint *c, enum isl_dim_type type, unsigned pos)3561{3562	isl_aff *aff;3563 3564	aff = isl_constraint_get_bound(c, type, pos);3565	isl_constraint_free(c);3566	return isl_qpolynomial_from_aff(aff);3567}3568 3569/* For each 0 <= i < "n", replace variable "first" + i of type "type"3570 * in "qp" by subs[i].3571 */3572__isl_give isl_qpolynomial *isl_qpolynomial_substitute(3573	__isl_take isl_qpolynomial *qp,3574	enum isl_dim_type type, unsigned first, unsigned n,3575	__isl_keep isl_qpolynomial **subs)3576{3577	int i;3578	isl_poly **polys;3579 3580	if (n == 0)3581		return qp;3582 3583	qp = isl_qpolynomial_cow(qp);3584	if (!qp)3585		return NULL;3586 3587	if (type == isl_dim_out)3588		isl_die(qp->dim->ctx, isl_error_invalid,3589			"cannot substitute output/set dimension",3590			goto error);3591	if (isl_qpolynomial_check_range(qp, type, first, n) < 0)3592		return isl_qpolynomial_free(qp);3593	type = domain_type(type);3594 3595	for (i = 0; i < n; ++i)3596		if (!subs[i])3597			goto error;3598 3599	for (i = 0; i < n; ++i)3600		if (isl_qpolynomial_check_equal_space(qp, subs[i]) < 0)3601			goto error;3602 3603	isl_assert(qp->dim->ctx, qp->div->n_row == 0, goto error);3604	for (i = 0; i < n; ++i)3605		isl_assert(qp->dim->ctx, subs[i]->div->n_row == 0, goto error);3606 3607	first += pos(qp->dim, type);3608 3609	polys = isl_alloc_array(qp->dim->ctx, struct isl_poly *, n);3610	if (!polys)3611		goto error;3612	for (i = 0; i < n; ++i)3613		polys[i] = subs[i]->poly;3614 3615	qp->poly = isl_poly_subs(qp->poly, first, n, polys);3616 3617	free(polys);3618 3619	if (!qp->poly)3620		goto error;3621 3622	return qp;3623error:3624	isl_qpolynomial_free(qp);3625	return NULL;3626}3627 3628/* Extend "bset" with extra set dimensions for each integer division3629 * in "qp" and then call "fn" with the extended bset and the polynomial3630 * that results from replacing each of the integer divisions by the3631 * corresponding extra set dimension.3632 */3633isl_stat isl_qpolynomial_as_polynomial_on_domain(__isl_keep isl_qpolynomial *qp,3634	__isl_keep isl_basic_set *bset,3635	isl_stat (*fn)(__isl_take isl_basic_set *bset,3636		  __isl_take isl_qpolynomial *poly, void *user), void *user)3637{3638	isl_space *space;3639	isl_local_space *ls;3640	isl_qpolynomial *poly;3641 3642	if (!qp || !bset)3643		return isl_stat_error;3644	if (qp->div->n_row == 0)3645		return fn(isl_basic_set_copy(bset), isl_qpolynomial_copy(qp),3646			  user);3647 3648	space = isl_space_copy(qp->dim);3649	space = isl_space_add_dims(space, isl_dim_set, qp->div->n_row);3650	poly = isl_qpolynomial_alloc(space, 0, isl_poly_copy(qp->poly));3651	bset = isl_basic_set_copy(bset);3652	ls = isl_qpolynomial_get_domain_local_space(qp);3653	bset = isl_local_space_lift_basic_set(ls, bset);3654 3655	return fn(bset, poly, user);3656}3657 3658/* Return total degree in variables first (inclusive) up to last (exclusive).3659 */3660int isl_poly_degree(__isl_keep isl_poly *poly, int first, int last)3661{3662	int deg = -1;3663	int i;3664	isl_bool is_zero, is_cst;3665	isl_poly_rec *rec;3666 3667	is_zero = isl_poly_is_zero(poly);3668	if (is_zero < 0)3669		return -2;3670	if (is_zero)3671		return -1;3672	is_cst = isl_poly_is_cst(poly);3673	if (is_cst < 0)3674		return -2;3675	if (is_cst || poly->var < first)3676		return 0;3677 3678	rec = isl_poly_as_rec(poly);3679	if (!rec)3680		return -2;3681 3682	for (i = 0; i < rec->n; ++i) {3683		int d;3684 3685		is_zero = isl_poly_is_zero(rec->p[i]);3686		if (is_zero < 0)3687			return -2;3688		if (is_zero)3689			continue;3690		d = isl_poly_degree(rec->p[i], first, last);3691		if (poly->var < last)3692			d += i;3693		if (d > deg)3694			deg = d;3695	}3696 3697	return deg;3698}3699 3700/* Return total degree in set variables.3701 */3702int isl_qpolynomial_degree(__isl_keep isl_qpolynomial *poly)3703{3704	unsigned ovar;3705	isl_size nvar;3706 3707	if (!poly)3708		return -2;3709 3710	ovar = isl_space_offset(poly->dim, isl_dim_set);3711	nvar = isl_space_dim(poly->dim, isl_dim_set);3712	if (nvar < 0)3713		return -2;3714	return isl_poly_degree(poly->poly, ovar, ovar + nvar);3715}3716 3717__isl_give isl_poly *isl_poly_coeff(__isl_keep isl_poly *poly,3718	unsigned pos, int deg)3719{3720	int i;3721	isl_bool is_cst;3722	isl_poly_rec *rec;3723 3724	is_cst = isl_poly_is_cst(poly);3725	if (is_cst < 0)3726		return NULL;3727	if (is_cst || poly->var < pos) {3728		if (deg == 0)3729			return isl_poly_copy(poly);3730		else3731			return isl_poly_zero(poly->ctx);3732	}3733 3734	rec = isl_poly_as_rec(poly);3735	if (!rec)3736		return NULL;3737 3738	if (poly->var == pos) {3739		if (deg < rec->n)3740			return isl_poly_copy(rec->p[deg]);3741		else3742			return isl_poly_zero(poly->ctx);3743	}3744 3745	poly = isl_poly_copy(poly);3746	poly = isl_poly_cow(poly);3747	rec = isl_poly_as_rec(poly);3748	if (!rec)3749		goto error;3750 3751	for (i = 0; i < rec->n; ++i) {3752		isl_poly *t;3753		t = isl_poly_coeff(rec->p[i], pos, deg);3754		if (!t)3755			goto error;3756		isl_poly_free(rec->p[i]);3757		rec->p[i] = t;3758	}3759 3760	return poly;3761error:3762	isl_poly_free(poly);3763	return NULL;3764}3765 3766/* Return coefficient of power "deg" of variable "t_pos" of type "type".3767 */3768__isl_give isl_qpolynomial *isl_qpolynomial_coeff(3769	__isl_keep isl_qpolynomial *qp,3770	enum isl_dim_type type, unsigned t_pos, int deg)3771{3772	unsigned g_pos;3773	isl_poly *poly;3774	isl_qpolynomial *c;3775 3776	if (!qp)3777		return NULL;3778 3779	if (type == isl_dim_out)3780		isl_die(qp->div->ctx, isl_error_invalid,3781			"output/set dimension does not have a coefficient",3782			return NULL);3783	if (isl_qpolynomial_check_range(qp, type, t_pos, 1) < 0)3784		return NULL;3785	type = domain_type(type);3786 3787	g_pos = pos(qp->dim, type) + t_pos;3788	poly = isl_poly_coeff(qp->poly, g_pos, deg);3789 3790	c = isl_qpolynomial_alloc(isl_space_copy(qp->dim),3791				qp->div->n_row, poly);3792	if (!c)3793		return NULL;3794	isl_mat_free(c->div);3795	c->div = isl_mat_copy(qp->div);3796	if (!c->div)3797		goto error;3798	return c;3799error:3800	isl_qpolynomial_free(c);3801	return NULL;3802}3803 3804/* Homogenize the polynomial in the variables first (inclusive) up to3805 * last (exclusive) by inserting powers of variable first.3806 * Variable first is assumed not to appear in the input.3807 */3808__isl_give isl_poly *isl_poly_homogenize(__isl_take isl_poly *poly, int deg,3809	int target, int first, int last)3810{3811	int i;3812	isl_bool is_zero, is_cst;3813	isl_poly_rec *rec;3814 3815	is_zero = isl_poly_is_zero(poly);3816	if (is_zero < 0)3817		return isl_poly_free(poly);3818	if (is_zero)3819		return poly;3820	if (deg == target)3821		return poly;3822	is_cst = isl_poly_is_cst(poly);3823	if (is_cst < 0)3824		return isl_poly_free(poly);3825	if (is_cst || poly->var < first) {3826		isl_poly *hom;3827 3828		hom = isl_poly_var_pow(poly->ctx, first, target - deg);3829		if (!hom)3830			goto error;3831		rec = isl_poly_as_rec(hom);3832		rec->p[target - deg] = isl_poly_mul(rec->p[target - deg], poly);3833 3834		return hom;3835	}3836 3837	poly = isl_poly_cow(poly);3838	rec = isl_poly_as_rec(poly);3839	if (!rec)3840		goto error;3841 3842	for (i = 0; i < rec->n; ++i) {3843		is_zero = isl_poly_is_zero(rec->p[i]);3844		if (is_zero < 0)3845			return isl_poly_free(poly);3846		if (is_zero)3847			continue;3848		rec->p[i] = isl_poly_homogenize(rec->p[i],3849				poly->var < last ? deg + i : i, target,3850				first, last);3851		if (!rec->p[i])3852			goto error;3853	}3854 3855	return poly;3856error:3857	isl_poly_free(poly);3858	return NULL;3859}3860 3861/* Homogenize the polynomial in the set variables by introducing3862 * powers of an extra set variable at position 0.3863 */3864__isl_give isl_qpolynomial *isl_qpolynomial_homogenize(3865	__isl_take isl_qpolynomial *poly)3866{3867	unsigned ovar;3868	isl_size nvar;3869	int deg = isl_qpolynomial_degree(poly);3870 3871	if (deg < -1)3872		goto error;3873 3874	poly = isl_qpolynomial_insert_dims(poly, isl_dim_in, 0, 1);3875	poly = isl_qpolynomial_cow(poly);3876	if (!poly)3877		goto error;3878 3879	ovar = isl_space_offset(poly->dim, isl_dim_set);3880	nvar = isl_space_dim(poly->dim, isl_dim_set);3881	if (nvar < 0)3882		return isl_qpolynomial_free(poly);3883	poly->poly = isl_poly_homogenize(poly->poly, 0, deg, ovar, ovar + nvar);3884	if (!poly->poly)3885		goto error;3886 3887	return poly;3888error:3889	isl_qpolynomial_free(poly);3890	return NULL;3891}3892 3893__isl_give isl_term *isl_term_alloc(__isl_take isl_space *space,3894	__isl_take isl_mat *div)3895{3896	isl_term *term;3897	isl_size d;3898	int n;3899 3900	d = isl_space_dim(space, isl_dim_all);3901	if (d < 0 || !div)3902		goto error;3903 3904	n = d + div->n_row;3905 3906	term = isl_calloc(space->ctx, struct isl_term,3907			sizeof(struct isl_term) + (n - 1) * sizeof(int));3908	if (!term)3909		goto error;3910 3911	term->ref = 1;3912	term->dim = space;3913	term->div = div;3914	isl_int_init(term->n);3915	isl_int_init(term->d);3916	3917	return term;3918error:3919	isl_space_free(space);3920	isl_mat_free(div);3921	return NULL;3922}3923 3924__isl_give isl_term *isl_term_copy(__isl_keep isl_term *term)3925{3926	if (!term)3927		return NULL;3928 3929	term->ref++;3930	return term;3931}3932 3933__isl_give isl_term *isl_term_dup(__isl_keep isl_term *term)3934{3935	int i;3936	isl_term *dup;3937	isl_size total;3938 3939	total = isl_term_dim(term, isl_dim_all);3940	if (total < 0)3941		return NULL;3942 3943	dup = isl_term_alloc(isl_space_copy(term->dim), isl_mat_copy(term->div));3944	if (!dup)3945		return NULL;3946 3947	isl_int_set(dup->n, term->n);3948	isl_int_set(dup->d, term->d);3949 3950	for (i = 0; i < total; ++i)3951		dup->pow[i] = term->pow[i];3952 3953	return dup;3954}3955 3956__isl_give isl_term *isl_term_cow(__isl_take isl_term *term)3957{3958	if (!term)3959		return NULL;3960 3961	if (term->ref == 1)3962		return term;3963	term->ref--;3964	return isl_term_dup(term);3965}3966 3967__isl_null isl_term *isl_term_free(__isl_take isl_term *term)3968{3969	if (!term)3970		return NULL;3971 3972	if (--term->ref > 0)3973		return NULL;3974 3975	isl_space_free(term->dim);3976	isl_mat_free(term->div);3977	isl_int_clear(term->n);3978	isl_int_clear(term->d);3979	free(term);3980 3981	return NULL;3982}3983 3984isl_size isl_term_dim(__isl_keep isl_term *term, enum isl_dim_type type)3985{3986	isl_size dim;3987 3988	if (!term)3989		return isl_size_error;3990 3991	switch (type) {3992	case isl_dim_param:3993	case isl_dim_in:3994	case isl_dim_out:	return isl_space_dim(term->dim, type);3995	case isl_dim_div:	return term->div->n_row;3996	case isl_dim_all:	dim = isl_space_dim(term->dim, isl_dim_all);3997				if (dim < 0)3998					return isl_size_error;3999				return dim + term->div->n_row;4000	default:		return isl_size_error;4001	}4002}4003 4004/* Return the space of "term".4005 */4006static __isl_keep isl_space *isl_term_peek_space(__isl_keep isl_term *term)4007{4008	return term ? term->dim : NULL;4009}4010 4011/* Return the offset of the first variable of type "type" within4012 * the variables of "term".4013 */4014static isl_size isl_term_offset(__isl_keep isl_term *term,4015	enum isl_dim_type type)4016{4017	isl_space *space;4018 4019	space = isl_term_peek_space(term);4020	if (!space)4021		return isl_size_error;4022 4023	switch (type) {4024	case isl_dim_param:4025	case isl_dim_set:	return isl_space_offset(space, type);4026	case isl_dim_div:	return isl_space_dim(space, isl_dim_all);4027	default:4028		isl_die(isl_term_get_ctx(term), isl_error_invalid,4029			"invalid dimension type", return isl_size_error);4030	}4031}4032 4033isl_ctx *isl_term_get_ctx(__isl_keep isl_term *term)4034{4035	return term ? term->dim->ctx : NULL;4036}4037 4038void isl_term_get_num(__isl_keep isl_term *term, isl_int *n)4039{4040	if (!term)4041		return;4042	isl_int_set(*n, term->n);4043}4044 4045/* Return the coefficient of the term "term".4046 */4047__isl_give isl_val *isl_term_get_coefficient_val(__isl_keep isl_term *term)4048{4049	if (!term)4050		return NULL;4051 4052	return isl_val_rat_from_isl_int(isl_term_get_ctx(term),4053					term->n, term->d);4054}4055 4056#undef TYPE4057#define TYPE	isl_term4058static4059#include "check_type_range_templ.c"4060 4061isl_size isl_term_get_exp(__isl_keep isl_term *term,4062	enum isl_dim_type type, unsigned pos)4063{4064	isl_size offset;4065 4066	if (isl_term_check_range(term, type, pos, 1) < 0)4067		return isl_size_error;4068	offset = isl_term_offset(term, type);4069	if (offset < 0)4070		return isl_size_error;4071 4072	return term->pow[offset + pos];4073}4074 4075__isl_give isl_aff *isl_term_get_div(__isl_keep isl_term *term, unsigned pos)4076{4077	isl_local_space *ls;4078	isl_aff *aff;4079 4080	if (isl_term_check_range(term, isl_dim_div, pos, 1) < 0)4081		return NULL;4082 4083	ls = isl_local_space_alloc_div(isl_space_copy(term->dim),4084					isl_mat_copy(term->div));4085	aff = isl_aff_alloc(ls);4086	if (!aff)4087		return NULL;4088 4089	isl_seq_cpy(aff->v->el, term->div->row[pos], aff->v->size);4090 4091	aff = isl_aff_normalize(aff);4092 4093	return aff;4094}4095 4096__isl_give isl_term *isl_poly_foreach_term(__isl_keep isl_poly *poly,4097	isl_stat (*fn)(__isl_take isl_term *term, void *user),4098	__isl_take isl_term *term, void *user)4099{4100	int i;4101	isl_bool is_zero, is_bad, is_cst;4102	isl_poly_rec *rec;4103 4104	is_zero = isl_poly_is_zero(poly);4105	if (is_zero < 0 || !term)4106		goto error;4107 4108	if (is_zero)4109		return term;4110 4111	is_cst = isl_poly_is_cst(poly);4112	is_bad = isl_poly_is_nan(poly);4113	if (is_bad >= 0 && !is_bad)4114		is_bad = isl_poly_is_infty(poly);4115	if (is_bad >= 0 && !is_bad)4116		is_bad = isl_poly_is_neginfty(poly);4117	if (is_cst < 0 || is_bad < 0)4118		return isl_term_free(term);4119	if (is_bad)4120		isl_die(isl_term_get_ctx(term), isl_error_invalid,4121			"cannot handle NaN/infty polynomial",4122			return isl_term_free(term));4123 4124	if (is_cst) {4125		isl_poly_cst *cst;4126		cst = isl_poly_as_cst(poly);4127		if (!cst)4128			goto error;4129		term = isl_term_cow(term);4130		if (!term)4131			goto error;4132		isl_int_set(term->n, cst->n);4133		isl_int_set(term->d, cst->d);4134		if (fn(isl_term_copy(term), user) < 0)4135			goto error;4136		return term;4137	}4138 4139	rec = isl_poly_as_rec(poly);4140	if (!rec)4141		goto error;4142 4143	for (i = 0; i < rec->n; ++i) {4144		term = isl_term_cow(term);4145		if (!term)4146			goto error;4147		term->pow[poly->var] = i;4148		term = isl_poly_foreach_term(rec->p[i], fn, term, user);4149		if (!term)4150			goto error;4151	}4152	term = isl_term_cow(term);4153	if (!term)4154		return NULL;4155	term->pow[poly->var] = 0;4156 4157	return term;4158error:4159	isl_term_free(term);4160	return NULL;4161}4162 4163isl_stat isl_qpolynomial_foreach_term(__isl_keep isl_qpolynomial *qp,4164	isl_stat (*fn)(__isl_take isl_term *term, void *user), void *user)4165{4166	isl_term *term;4167 4168	if (!qp)4169		return isl_stat_error;4170 4171	term = isl_term_alloc(isl_space_copy(qp->dim), isl_mat_copy(qp->div));4172	if (!term)4173		return isl_stat_error;4174 4175	term = isl_poly_foreach_term(qp->poly, fn, term, user);4176 4177	isl_term_free(term);4178 4179	return term ? isl_stat_ok : isl_stat_error;4180}4181 4182__isl_give isl_qpolynomial *isl_qpolynomial_from_term(__isl_take isl_term *term)4183{4184	isl_poly *poly;4185	isl_qpolynomial *qp;4186	int i;4187	isl_size n;4188 4189	n = isl_term_dim(term, isl_dim_all);4190	if (n < 0)4191		term = isl_term_free(term);4192	if (!term)4193		return NULL;4194 4195	poly = isl_poly_rat_cst(term->dim->ctx, term->n, term->d);4196	for (i = 0; i < n; ++i) {4197		if (!term->pow[i])4198			continue;4199		poly = isl_poly_mul(poly,4200			    isl_poly_var_pow(term->dim->ctx, i, term->pow[i]));4201	}4202 4203	qp = isl_qpolynomial_alloc(isl_space_copy(term->dim),4204				    term->div->n_row, poly);4205	if (!qp)4206		goto error;4207	isl_mat_free(qp->div);4208	qp->div = isl_mat_copy(term->div);4209	if (!qp->div)4210		goto error;4211 4212	isl_term_free(term);4213	return qp;4214error:4215	isl_qpolynomial_free(qp);4216	isl_term_free(term);4217	return NULL;4218}4219 4220__isl_give isl_qpolynomial *isl_qpolynomial_lift(__isl_take isl_qpolynomial *qp,4221	__isl_take isl_space *space)4222{4223	int i;4224	int extra;4225	isl_size total, d_set, d_qp;4226 4227	if (!qp || !space)4228		goto error;4229 4230	if (isl_space_is_equal(qp->dim, space)) {4231		isl_space_free(space);4232		return qp;4233	}4234 4235	qp = isl_qpolynomial_cow(qp);4236	if (!qp)4237		goto error;4238 4239	d_set = isl_space_dim(space, isl_dim_set);4240	d_qp = isl_qpolynomial_domain_dim(qp, isl_dim_set);4241	extra = d_set - d_qp;4242	total = isl_space_dim(qp->dim, isl_dim_all);4243	if (d_set < 0 || d_qp < 0 || total < 0)4244		goto error;4245	if (qp->div->n_row) {4246		int *exp;4247 4248		exp = isl_alloc_array(qp->div->ctx, int, qp->div->n_row);4249		if (!exp)4250			goto error;4251		for (i = 0; i < qp->div->n_row; ++i)4252			exp[i] = extra + i;4253		qp->poly = expand(qp->poly, exp, total);4254		free(exp);4255		if (!qp->poly)4256			goto error;4257	}4258	qp->div = isl_mat_insert_cols(qp->div, 2 + total, extra);4259	if (!qp->div)4260		goto error;4261	for (i = 0; i < qp->div->n_row; ++i)4262		isl_seq_clr(qp->div->row[i] + 2 + total, extra);4263 4264	isl_space_free(qp->dim);4265	qp->dim = space;4266 4267	return qp;4268error:4269	isl_space_free(space);4270	isl_qpolynomial_free(qp);4271	return NULL;4272}4273 4274/* For each parameter or variable that does not appear in qp,4275 * first eliminate the variable from all constraints and then set it to zero.4276 */4277static __isl_give isl_set *fix_inactive(__isl_take isl_set *set,4278	__isl_keep isl_qpolynomial *qp)4279{4280	int *active = NULL;4281	int i;4282	isl_size d;4283	isl_size nparam;4284	isl_size nvar;4285 4286	d = isl_set_dim(set, isl_dim_all);4287	if (d < 0 || !qp)4288		goto error;4289 4290	active = isl_calloc_array(set->ctx, int, d);4291	if (set_active(qp, active) < 0)4292		goto error;4293 4294	for (i = 0; i < d; ++i)4295		if (!active[i])4296			break;4297 4298	if (i == d) {4299		free(active);4300		return set;4301	}4302 4303	nparam = isl_set_dim(set, isl_dim_param);4304	nvar = isl_set_dim(set, isl_dim_set);4305	if (nparam < 0 || nvar < 0)4306		goto error;4307	for (i = 0; i < nparam; ++i) {4308		if (active[i])4309			continue;4310		set = isl_set_eliminate(set, isl_dim_param, i, 1);4311		set = isl_set_fix_si(set, isl_dim_param, i, 0);4312	}4313	for (i = 0; i < nvar; ++i) {4314		if (active[nparam + i])4315			continue;4316		set = isl_set_eliminate(set, isl_dim_set, i, 1);4317		set = isl_set_fix_si(set, isl_dim_set, i, 0);4318	}4319 4320	free(active);4321 4322	return set;4323error:4324	free(active);4325	isl_set_free(set);4326	return NULL;4327}4328 4329struct isl_opt_data {4330	isl_qpolynomial *qp;4331	int first;4332	isl_val *opt;4333	int max;4334};4335 4336static isl_stat opt_fn(__isl_take isl_point *pnt, void *user)4337{4338	struct isl_opt_data *data = (struct isl_opt_data *)user;4339	isl_val *val;4340 4341	val = isl_qpolynomial_eval(isl_qpolynomial_copy(data->qp), pnt);4342	if (data->first) {4343		data->first = 0;4344		data->opt = val;4345	} else if (data->max) {4346		data->opt = isl_val_max(data->opt, val);4347	} else {4348		data->opt = isl_val_min(data->opt, val);4349	}4350 4351	return isl_stat_ok;4352}4353 4354__isl_give isl_val *isl_qpolynomial_opt_on_domain(4355	__isl_take isl_qpolynomial *qp, __isl_take isl_set *set, int max)4356{4357	struct isl_opt_data data = { NULL, 1, NULL, max };4358	isl_bool is_cst;4359 4360	if (!set || !qp)4361		goto error;4362 4363	is_cst = isl_poly_is_cst(qp->poly);4364	if (is_cst < 0)4365		goto error;4366	if (is_cst) {4367		isl_set_free(set);4368		data.opt = isl_qpolynomial_get_constant_val(qp);4369		isl_qpolynomial_free(qp);4370		return data.opt;4371	}4372 4373	set = fix_inactive(set, qp);4374 4375	data.qp = qp;4376	if (isl_set_foreach_point(set, opt_fn, &data) < 0)4377		goto error;4378 4379	if (data.first)4380		data.opt = isl_val_zero(isl_set_get_ctx(set));4381 4382	isl_set_free(set);4383	isl_qpolynomial_free(qp);4384	return data.opt;4385error:4386	isl_set_free(set);4387	isl_qpolynomial_free(qp);4388	isl_val_free(data.opt);4389	return NULL;4390}4391 4392__isl_give isl_qpolynomial *isl_qpolynomial_morph_domain(4393	__isl_take isl_qpolynomial *qp, __isl_take isl_morph *morph)4394{4395	int i;4396	int n_sub;4397	isl_ctx *ctx;4398	isl_space *space;4399	isl_poly **subs;4400	isl_mat *mat, *diag;4401 4402	qp = isl_qpolynomial_cow(qp);4403 4404	space = isl_qpolynomial_peek_domain_space(qp);4405	if (isl_morph_check_applies(morph, space) < 0)4406		goto error;4407 4408	ctx = isl_qpolynomial_get_ctx(qp);4409	n_sub = morph->inv->n_row - 1;4410	if (morph->inv->n_row != morph->inv->n_col)4411		n_sub += qp->div->n_row;4412	subs = isl_calloc_array(ctx, struct isl_poly *, n_sub);4413	if (n_sub && !subs)4414		goto error;4415 4416	for (i = 0; 1 + i < morph->inv->n_row; ++i)4417		subs[i] = isl_poly_from_affine(ctx, morph->inv->row[1 + i],4418					morph->inv->row[0][0], morph->inv->n_col);4419	if (morph->inv->n_row != morph->inv->n_col)4420		for (i = 0; i < qp->div->n_row; ++i)4421			subs[morph->inv->n_row - 1 + i] =4422			    isl_poly_var_pow(ctx, morph->inv->n_col - 1 + i, 1);4423 4424	qp->poly = isl_poly_subs(qp->poly, 0, n_sub, subs);4425 4426	for (i = 0; i < n_sub; ++i)4427		isl_poly_free(subs[i]);4428	free(subs);4429 4430	diag = isl_mat_diag(ctx, 1, morph->inv->row[0][0]);4431	mat = isl_mat_diagonal(diag, isl_mat_copy(morph->inv));4432	diag = isl_mat_diag(ctx, qp->div->n_row, morph->inv->row[0][0]);4433	mat = isl_mat_diagonal(mat, diag);4434	qp->div = isl_mat_product(qp->div, mat);4435	isl_space_free(qp->dim);4436	qp->dim = isl_space_copy(morph->ran->dim);4437 4438	if (!qp->poly || !qp->div || !qp->dim)4439		goto error;4440 4441	isl_morph_free(morph);4442 4443	return qp;4444error:4445	isl_qpolynomial_free(qp);4446	isl_morph_free(morph);4447	return NULL;4448}4449 4450__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_mul(4451	__isl_take isl_union_pw_qpolynomial *upwqp1,4452	__isl_take isl_union_pw_qpolynomial *upwqp2)4453{4454	return isl_union_pw_qpolynomial_match_bin_op(upwqp1, upwqp2,4455						&isl_pw_qpolynomial_mul);4456}4457 4458/* Reorder the dimension of "qp" according to the given reordering.4459 */4460__isl_give isl_qpolynomial *isl_qpolynomial_realign_domain(4461	__isl_take isl_qpolynomial *qp, __isl_take isl_reordering *r)4462{4463	isl_space *space;4464 4465	qp = isl_qpolynomial_cow(qp);4466	if (!qp)4467		goto error;4468 4469	r = isl_reordering_extend(r, qp->div->n_row);4470	if (!r)4471		goto error;4472 4473	qp->div = isl_local_reorder(qp->div, isl_reordering_copy(r));4474	if (!qp->div)4475		goto error;4476 4477	qp->poly = reorder(qp->poly, r->pos);4478	if (!qp->poly)4479		goto error;4480 4481	space = isl_reordering_get_space(r);4482	qp = isl_qpolynomial_reset_domain_space(qp, space);4483 4484	isl_reordering_free(r);4485	return qp;4486error:4487	isl_qpolynomial_free(qp);4488	isl_reordering_free(r);4489	return NULL;4490}4491 4492__isl_give isl_qpolynomial *isl_qpolynomial_align_params(4493	__isl_take isl_qpolynomial *qp, __isl_take isl_space *model)4494{4495	isl_space *domain_space;4496	isl_bool equal_params;4497 4498	domain_space = isl_qpolynomial_peek_domain_space(qp);4499	equal_params = isl_space_has_equal_params(domain_space, model);4500	if (equal_params < 0)4501		goto error;4502	if (!equal_params) {4503		isl_reordering *exp;4504 4505		exp = isl_parameter_alignment_reordering(domain_space, model);4506		qp = isl_qpolynomial_realign_domain(qp, exp);4507	}4508 4509	isl_space_free(model);4510	return qp;4511error:4512	isl_space_free(model);4513	isl_qpolynomial_free(qp);4514	return NULL;4515}4516 4517struct isl_split_periods_data {4518	int max_periods;4519	isl_pw_qpolynomial *res;4520};4521 4522/* Create a slice where the integer division "div" has the fixed value "v".4523 * In particular, if "div" refers to floor(f/m), then create a slice4524 *4525 *	m v <= f <= m v + (m - 1)4526 *4527 * or4528 *4529 *	f - m v >= 04530 *	-f + m v + (m - 1) >= 04531 */4532static __isl_give isl_set *set_div_slice(__isl_take isl_space *space,4533	__isl_keep isl_qpolynomial *qp, int div, isl_int v)4534{4535	isl_size total;4536	isl_basic_set *bset = NULL;4537	int k;4538 4539	total = isl_space_dim(space, isl_dim_all);4540	if (total < 0 || !qp)4541		goto error;4542 4543	bset = isl_basic_set_alloc_space(isl_space_copy(space), 0, 0, 2);4544 4545	k = isl_basic_set_alloc_inequality(bset);4546	if (k < 0)4547		goto error;4548	isl_seq_cpy(bset->ineq[k], qp->div->row[div] + 1, 1 + total);4549	isl_int_submul(bset->ineq[k][0], v, qp->div->row[div][0]);4550 4551	k = isl_basic_set_alloc_inequality(bset);4552	if (k < 0)4553		goto error;4554	isl_seq_neg(bset->ineq[k], qp->div->row[div] + 1, 1 + total);4555	isl_int_addmul(bset->ineq[k][0], v, qp->div->row[div][0]);4556	isl_int_add(bset->ineq[k][0], bset->ineq[k][0], qp->div->row[div][0]);4557	isl_int_sub_ui(bset->ineq[k][0], bset->ineq[k][0], 1);4558 4559	isl_space_free(space);4560	return isl_set_from_basic_set(bset);4561error:4562	isl_basic_set_free(bset);4563	isl_space_free(space);4564	return NULL;4565}4566 4567static isl_stat split_periods(__isl_take isl_set *set,4568	__isl_take isl_qpolynomial *qp, void *user);4569 4570/* Create a slice of the domain "set" such that integer division "div"4571 * has the fixed value "v" and add the results to data->res,4572 * replacing the integer division by "v" in "qp".4573 */4574static isl_stat set_div(__isl_take isl_set *set,4575	__isl_take isl_qpolynomial *qp, int div, isl_int v,4576	struct isl_split_periods_data *data)4577{4578	int i;4579	isl_size div_pos;4580	isl_set *slice;4581	isl_poly *cst;4582 4583	slice = set_div_slice(isl_set_get_space(set), qp, div, v);4584	set = isl_set_intersect(set, slice);4585 4586	div_pos = isl_qpolynomial_domain_var_offset(qp, isl_dim_div);4587	if (div_pos < 0)4588		goto error;4589 4590	for (i = div + 1; i < qp->div->n_row; ++i) {4591		if (isl_int_is_zero(qp->div->row[i][2 + div_pos + div]))4592			continue;4593		isl_int_addmul(qp->div->row[i][1],4594				qp->div->row[i][2 + div_pos + div], v);4595		isl_int_set_si(qp->div->row[i][2 + div_pos + div], 0);4596	}4597 4598	cst = isl_poly_rat_cst(qp->dim->ctx, v, qp->dim->ctx->one);4599	qp = substitute_div(qp, div, cst);4600 4601	return split_periods(set, qp, data);4602error:4603	isl_set_free(set);4604	isl_qpolynomial_free(qp);4605	return isl_stat_error;4606}4607 4608/* Split the domain "set" such that integer division "div"4609 * has a fixed value (ranging from "min" to "max") on each slice4610 * and add the results to data->res.4611 */4612static isl_stat split_div(__isl_take isl_set *set,4613	__isl_take isl_qpolynomial *qp, int div, isl_int min, isl_int max,4614	struct isl_split_periods_data *data)4615{4616	for (; isl_int_le(min, max); isl_int_add_ui(min, min, 1)) {4617		isl_set *set_i = isl_set_copy(set);4618		isl_qpolynomial *qp_i = isl_qpolynomial_copy(qp);4619 4620		if (set_div(set_i, qp_i, div, min, data) < 0)4621			goto error;4622	}4623	isl_set_free(set);4624	isl_qpolynomial_free(qp);4625	return isl_stat_ok;4626error:4627	isl_set_free(set);4628	isl_qpolynomial_free(qp);4629	return isl_stat_error;4630}4631 4632/* If "qp" refers to any integer division4633 * that can only attain "max_periods" distinct values on "set"4634 * then split the domain along those distinct values.4635 * Add the results (or the original if no splitting occurs)4636 * to data->res.4637 */4638static isl_stat split_periods(__isl_take isl_set *set,4639	__isl_take isl_qpolynomial *qp, void *user)4640{4641	int i;4642	isl_pw_qpolynomial *pwqp;4643	struct isl_split_periods_data *data;4644	isl_int min, max;4645	isl_size div_pos;4646	isl_stat r = isl_stat_ok;4647 4648	data = (struct isl_split_periods_data *)user;4649 4650	if (!set || !qp)4651		goto error;4652 4653	if (qp->div->n_row == 0) {4654		pwqp = isl_pw_qpolynomial_alloc(set, qp);4655		data->res = isl_pw_qpolynomial_add_disjoint(data->res, pwqp);4656		return isl_stat_ok;4657	}4658 4659	div_pos = isl_qpolynomial_domain_var_offset(qp, isl_dim_div);4660	if (div_pos < 0)4661		goto error;4662 4663	isl_int_init(min);4664	isl_int_init(max);4665	for (i = 0; i < qp->div->n_row; ++i) {4666		enum isl_lp_result lp_res;4667 4668		if (isl_seq_first_non_zero(qp->div->row[i] + 2 + div_pos,4669						qp->div->n_row) != -1)4670			continue;4671 4672		lp_res = isl_set_solve_lp(set, 0, qp->div->row[i] + 1,4673					  set->ctx->one, &min, NULL, NULL);4674		if (lp_res == isl_lp_error)4675			goto error2;4676		if (lp_res == isl_lp_unbounded || lp_res == isl_lp_empty)4677			continue;4678		isl_int_fdiv_q(min, min, qp->div->row[i][0]);4679 4680		lp_res = isl_set_solve_lp(set, 1, qp->div->row[i] + 1,4681					  set->ctx->one, &max, NULL, NULL);4682		if (lp_res == isl_lp_error)4683			goto error2;4684		if (lp_res == isl_lp_unbounded || lp_res == isl_lp_empty)4685			continue;4686		isl_int_fdiv_q(max, max, qp->div->row[i][0]);4687 4688		isl_int_sub(max, max, min);4689		if (isl_int_cmp_si(max, data->max_periods) < 0) {4690			isl_int_add(max, max, min);4691			break;4692		}4693	}4694 4695	if (i < qp->div->n_row) {4696		r = split_div(set, qp, i, min, max, data);4697	} else {4698		pwqp = isl_pw_qpolynomial_alloc(set, qp);4699		data->res = isl_pw_qpolynomial_add_disjoint(data->res, pwqp);4700	}4701 4702	isl_int_clear(max);4703	isl_int_clear(min);4704 4705	return r;4706error2:4707	isl_int_clear(max);4708	isl_int_clear(min);4709error:4710	isl_set_free(set);4711	isl_qpolynomial_free(qp);4712	return isl_stat_error;4713}4714 4715/* If any quasi-polynomial in pwqp refers to any integer division4716 * that can only attain "max_periods" distinct values on its domain4717 * then split the domain along those distinct values.4718 */4719__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_split_periods(4720	__isl_take isl_pw_qpolynomial *pwqp, int max_periods)4721{4722	struct isl_split_periods_data data;4723 4724	data.max_periods = max_periods;4725	data.res = isl_pw_qpolynomial_zero(isl_pw_qpolynomial_get_space(pwqp));4726 4727	if (isl_pw_qpolynomial_foreach_piece(pwqp, &split_periods, &data) < 0)4728		goto error;4729 4730	isl_pw_qpolynomial_free(pwqp);4731 4732	return data.res;4733error:4734	isl_pw_qpolynomial_free(data.res);4735	isl_pw_qpolynomial_free(pwqp);4736	return NULL;4737}4738 4739/* Construct a piecewise quasipolynomial that is constant on the given4740 * domain.  In particular, it is4741 *	0	if cst == 04742 *	1	if cst == 14743 *  infinity	if cst == -14744 *4745 * If cst == -1, then explicitly check whether the domain is empty and,4746 * if so, return 0 instead.4747 */4748static __isl_give isl_pw_qpolynomial *constant_on_domain(4749	__isl_take isl_basic_set *bset, int cst)4750{4751	isl_space *space;4752	isl_qpolynomial *qp;4753 4754	if (cst < 0 && isl_basic_set_is_empty(bset) == isl_bool_true)4755		cst = 0;4756	if (!bset)4757		return NULL;4758 4759	bset = isl_basic_set_params(bset);4760	space = isl_basic_set_get_space(bset);4761	if (cst < 0)4762		qp = isl_qpolynomial_infty_on_domain(space);4763	else if (cst == 0)4764		qp = isl_qpolynomial_zero_on_domain(space);4765	else4766		qp = isl_qpolynomial_one_on_domain(space);4767	return isl_pw_qpolynomial_alloc(isl_set_from_basic_set(bset), qp);4768}4769 4770/* Internal data structure for multiplicative_call_factor_pw_qpolynomial.4771 * "fn" is the function that is called on each factor.4772 * "pwpq" collects the results.4773 */4774struct isl_multiplicative_call_data_pw_qpolynomial {4775	__isl_give isl_pw_qpolynomial *(*fn)(__isl_take isl_basic_set *bset);4776	isl_pw_qpolynomial *pwqp;4777};4778 4779/* Call "fn" on "bset" and return the result,4780 * but first check if "bset" has any redundant constraints or4781 * implicit equality constraints.4782 * If so, there may be further opportunities for detecting factors or4783 * removing equality constraints, so recursively call4784 * the top-level isl_basic_set_multiplicative_call.4785 */4786static __isl_give isl_pw_qpolynomial *multiplicative_call_base(4787	__isl_take isl_basic_set *bset,4788	__isl_give isl_pw_qpolynomial *(*fn)(__isl_take isl_basic_set *bset))4789{4790	isl_size n1, n2, n_eq;4791 4792	n1 = isl_basic_set_n_constraint(bset);4793	if (n1 < 0)4794		bset = isl_basic_set_free(bset);4795	bset = isl_basic_set_remove_redundancies(bset);4796	bset = isl_basic_set_detect_equalities(bset);4797	n2 = isl_basic_set_n_constraint(bset);4798	n_eq = isl_basic_set_n_equality(bset);4799	if (n2 < 0 || n_eq < 0)4800		bset = isl_basic_set_free(bset);4801	else if (n2 < n1 || n_eq > 0)4802		return isl_basic_set_multiplicative_call(bset, fn);4803	return fn(bset);4804}4805 4806/* isl_factorizer_every_factor_basic_set callback that applies4807 * data->fn to the factor "bset" and multiplies in the result4808 * in data->pwqp.4809 */4810static isl_bool multiplicative_call_factor_pw_qpolynomial(4811	__isl_keep isl_basic_set *bset, void *user)4812{4813	struct isl_multiplicative_call_data_pw_qpolynomial *data = user;4814	isl_pw_qpolynomial *res;4815 4816	bset = isl_basic_set_copy(bset);4817	res = multiplicative_call_base(bset, data->fn);4818	data->pwqp = isl_pw_qpolynomial_mul(data->pwqp, res);4819	if (!data->pwqp)4820		return isl_bool_error;4821 4822	return isl_bool_true;4823}4824 4825/* Factor bset, call fn on each of the factors and return the product.4826 *4827 * If no factors can be found, simply call fn on the input.4828 * Otherwise, construct the factors based on the factorizer,4829 * call fn on each factor and compute the product.4830 */4831static __isl_give isl_pw_qpolynomial *compressed_multiplicative_call(4832	__isl_take isl_basic_set *bset,4833	__isl_give isl_pw_qpolynomial *(*fn)(__isl_take isl_basic_set *bset))4834{4835	struct isl_multiplicative_call_data_pw_qpolynomial data = { fn };4836	isl_space *space;4837	isl_set *set;4838	isl_factorizer *f;4839	isl_qpolynomial *qp;4840	isl_bool every;4841 4842	f = isl_basic_set_factorizer(bset);4843	if (!f)4844		goto error;4845	if (f->n_group == 0) {4846		isl_factorizer_free(f);4847		return multiplicative_call_base(bset, fn);4848	}4849 4850	space = isl_basic_set_get_space(bset);4851	space = isl_space_params(space);4852	set = isl_set_universe(isl_space_copy(space));4853	qp = isl_qpolynomial_one_on_domain(space);4854	data.pwqp = isl_pw_qpolynomial_alloc(set, qp);4855 4856	every = isl_factorizer_every_factor_basic_set(f,4857			&multiplicative_call_factor_pw_qpolynomial, &data);4858	if (every < 0)4859		data.pwqp = isl_pw_qpolynomial_free(data.pwqp);4860 4861	isl_basic_set_free(bset);4862	isl_factorizer_free(f);4863 4864	return data.pwqp;4865error:4866	isl_basic_set_free(bset);4867	return NULL;4868}4869 4870/* Factor bset, call fn on each of the factors and return the product.4871 * The function is assumed to evaluate to zero on empty domains,4872 * to one on zero-dimensional domains and to infinity on unbounded domains4873 * and will not be called explicitly on zero-dimensional or unbounded domains.4874 *4875 * We first check for some special cases and remove all equalities.4876 * Then we hand over control to compressed_multiplicative_call.4877 */4878__isl_give isl_pw_qpolynomial *isl_basic_set_multiplicative_call(4879	__isl_take isl_basic_set *bset,4880	__isl_give isl_pw_qpolynomial *(*fn)(__isl_take isl_basic_set *bset))4881{4882	isl_bool bounded;4883	isl_size dim;4884	isl_morph *morph;4885	isl_pw_qpolynomial *pwqp;4886 4887	if (!bset)4888		return NULL;4889 4890	if (isl_basic_set_plain_is_empty(bset))4891		return constant_on_domain(bset, 0);4892 4893	dim = isl_basic_set_dim(bset, isl_dim_set);4894	if (dim < 0)4895		goto error;4896	if (dim == 0)4897		return constant_on_domain(bset, 1);4898 4899	bounded = isl_basic_set_is_bounded(bset);4900	if (bounded < 0)4901		goto error;4902	if (!bounded)4903		return constant_on_domain(bset, -1);4904 4905	if (bset->n_eq == 0)4906		return compressed_multiplicative_call(bset, fn);4907 4908	morph = isl_basic_set_full_compression(bset);4909	bset = isl_morph_basic_set(isl_morph_copy(morph), bset);4910 4911	pwqp = compressed_multiplicative_call(bset, fn);4912 4913	morph = isl_morph_dom_params(morph);4914	morph = isl_morph_ran_params(morph);4915	morph = isl_morph_inverse(morph);4916 4917	pwqp = isl_pw_qpolynomial_morph_domain(pwqp, morph);4918 4919	return pwqp;4920error:4921	isl_basic_set_free(bset);4922	return NULL;4923}4924 4925/* Drop all floors in "qp", turning each integer division [a/m] into4926 * a rational division a/m.  If "down" is set, then the integer division4927 * is replaced by (a-(m-1))/m instead.4928 */4929static __isl_give isl_qpolynomial *qp_drop_floors(4930	__isl_take isl_qpolynomial *qp, int down)4931{4932	int i;4933	isl_poly *s;4934 4935	if (!qp)4936		return NULL;4937	if (qp->div->n_row == 0)4938		return qp;4939 4940	qp = isl_qpolynomial_cow(qp);4941	if (!qp)4942		return NULL;4943 4944	for (i = qp->div->n_row - 1; i >= 0; --i) {4945		if (down) {4946			isl_int_sub(qp->div->row[i][1],4947				    qp->div->row[i][1], qp->div->row[i][0]);4948			isl_int_add_ui(qp->div->row[i][1],4949				       qp->div->row[i][1], 1);4950		}4951		s = isl_poly_from_affine(qp->dim->ctx, qp->div->row[i] + 1,4952					qp->div->row[i][0], qp->div->n_col - 1);4953		qp = substitute_div(qp, i, s);4954		if (!qp)4955			return NULL;4956	}4957 4958	return qp;4959}4960 4961/* Drop all floors in "pwqp", turning each integer division [a/m] into4962 * a rational division a/m.4963 */4964static __isl_give isl_pw_qpolynomial *pwqp_drop_floors(4965	__isl_take isl_pw_qpolynomial *pwqp)4966{4967	int i;4968 4969	if (!pwqp)4970		return NULL;4971 4972	if (isl_pw_qpolynomial_is_zero(pwqp))4973		return pwqp;4974 4975	pwqp = isl_pw_qpolynomial_cow(pwqp);4976	if (!pwqp)4977		return NULL;4978 4979	for (i = 0; i < pwqp->n; ++i) {4980		pwqp->p[i].qp = qp_drop_floors(pwqp->p[i].qp, 0);4981		if (!pwqp->p[i].qp)4982			goto error;4983	}4984 4985	return pwqp;4986error:4987	isl_pw_qpolynomial_free(pwqp);4988	return NULL;4989}4990 4991/* Adjust all the integer divisions in "qp" such that they are at least4992 * one over the given orthant (identified by "signs").  This ensures4993 * that they will still be non-negative even after subtracting (m-1)/m.4994 *4995 * In particular, f is replaced by f' + v, changing f = [a/m]4996 * to f' = [(a - m v)/m].4997 * If the constant term k in a is smaller than m,4998 * the constant term of v is set to floor(k/m) - 1.4999 * For any other term, if the coefficient c and the variable x have5000 * the same sign, then no changes are needed.5001 * Otherwise, if the variable is positive (and c is negative),5002 * then the coefficient of x in v is set to floor(c/m).5003 * If the variable is negative (and c is positive),5004 * then the coefficient of x in v is set to ceil(c/m).5005 */5006static __isl_give isl_qpolynomial *make_divs_pos(__isl_take isl_qpolynomial *qp,5007	int *signs)5008{5009	int i, j;5010	isl_size div_pos;5011	isl_vec *v = NULL;5012	isl_poly *s;5013 5014	qp = isl_qpolynomial_cow(qp);5015	div_pos = isl_qpolynomial_domain_var_offset(qp, isl_dim_div);5016	if (div_pos < 0)5017		return isl_qpolynomial_free(qp);5018	qp->div = isl_mat_cow(qp->div);5019	if (!qp->div)5020		goto error;5021 5022	v = isl_vec_alloc(qp->div->ctx, qp->div->n_col - 1);5023 5024	for (i = 0; i < qp->div->n_row; ++i) {5025		isl_int *row = qp->div->row[i];5026		v = isl_vec_clr(v);5027		if (!v)5028			goto error;5029		if (isl_int_lt(row[1], row[0])) {5030			isl_int_fdiv_q(v->el[0], row[1], row[0]);5031			isl_int_sub_ui(v->el[0], v->el[0], 1);5032			isl_int_submul(row[1], row[0], v->el[0]);5033		}5034		for (j = 0; j < div_pos; ++j) {5035			if (isl_int_sgn(row[2 + j]) * signs[j] >= 0)5036				continue;5037			if (signs[j] < 0)5038				isl_int_cdiv_q(v->el[1 + j], row[2 + j], row[0]);5039			else5040				isl_int_fdiv_q(v->el[1 + j], row[2 + j], row[0]);5041			isl_int_submul(row[2 + j], row[0], v->el[1 + j]);5042		}5043		for (j = 0; j < i; ++j) {5044			if (isl_int_sgn(row[2 + div_pos + j]) >= 0)5045				continue;5046			isl_int_fdiv_q(v->el[1 + div_pos + j],5047					row[2 + div_pos + j], row[0]);5048			isl_int_submul(row[2 + div_pos + j],5049					row[0], v->el[1 + div_pos + j]);5050		}5051		for (j = i + 1; j < qp->div->n_row; ++j) {5052			if (isl_int_is_zero(qp->div->row[j][2 + div_pos + i]))5053				continue;5054			isl_seq_combine(qp->div->row[j] + 1,5055				qp->div->ctx->one, qp->div->row[j] + 1,5056				qp->div->row[j][2 + div_pos + i], v->el,5057				v->size);5058		}5059		isl_int_set_si(v->el[1 + div_pos + i], 1);5060		s = isl_poly_from_affine(qp->dim->ctx, v->el,5061					qp->div->ctx->one, v->size);5062		qp->poly = isl_poly_subs(qp->poly, div_pos + i, 1, &s);5063		isl_poly_free(s);5064		if (!qp->poly)5065			goto error;5066	}5067 5068	isl_vec_free(v);5069	return qp;5070error:5071	isl_vec_free(v);5072	isl_qpolynomial_free(qp);5073	return NULL;5074}5075 5076struct isl_to_poly_data {5077	int sign;5078	isl_pw_qpolynomial *res;5079	isl_qpolynomial *qp;5080};5081 5082/* Appoximate data->qp by a polynomial on the orthant identified by "signs".5083 * We first make all integer divisions positive and then split the5084 * quasipolynomials into terms with sign data->sign (the direction5085 * of the requested approximation) and terms with the opposite sign.5086 * In the first set of terms, each integer division [a/m] is5087 * overapproximated by a/m, while in the second it is underapproximated5088 * by (a-(m-1))/m.5089 */5090static isl_stat to_polynomial_on_orthant(__isl_take isl_set *orthant,5091	int *signs, void *user)5092{5093	struct isl_to_poly_data *data = user;5094	isl_pw_qpolynomial *t;5095	isl_qpolynomial *qp, *up, *down;5096 5097	qp = isl_qpolynomial_copy(data->qp);5098	qp = make_divs_pos(qp, signs);5099 5100	up = isl_qpolynomial_terms_of_sign(qp, signs, data->sign);5101	up = qp_drop_floors(up, 0);5102	down = isl_qpolynomial_terms_of_sign(qp, signs, -data->sign);5103	down = qp_drop_floors(down, 1);5104 5105	isl_qpolynomial_free(qp);5106	qp = isl_qpolynomial_add(up, down);5107 5108	t = isl_pw_qpolynomial_alloc(orthant, qp);5109	data->res = isl_pw_qpolynomial_add_disjoint(data->res, t);5110 5111	return isl_stat_ok;5112}5113 5114/* Approximate each quasipolynomial by a polynomial.  If "sign" is positive,5115 * the polynomial will be an overapproximation.  If "sign" is negative,5116 * it will be an underapproximation.  If "sign" is zero, the approximation5117 * will lie somewhere in between.5118 *5119 * In particular, is sign == 0, we simply drop the floors, turning5120 * the integer divisions into rational divisions.5121 * Otherwise, we split the domains into orthants, make all integer divisions5122 * positive and then approximate each [a/m] by either a/m or (a-(m-1))/m,5123 * depending on the requested sign and the sign of the term in which5124 * the integer division appears.5125 */5126__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_to_polynomial(5127	__isl_take isl_pw_qpolynomial *pwqp, int sign)5128{5129	int i;5130	struct isl_to_poly_data data;5131 5132	if (sign == 0)5133		return pwqp_drop_floors(pwqp);5134 5135	if (!pwqp)5136		return NULL;5137 5138	data.sign = sign;5139	data.res = isl_pw_qpolynomial_zero(isl_pw_qpolynomial_get_space(pwqp));5140 5141	for (i = 0; i < pwqp->n; ++i) {5142		if (pwqp->p[i].qp->div->n_row == 0) {5143			isl_pw_qpolynomial *t;5144			t = isl_pw_qpolynomial_alloc(5145					isl_set_copy(pwqp->p[i].set),5146					isl_qpolynomial_copy(pwqp->p[i].qp));5147			data.res = isl_pw_qpolynomial_add_disjoint(data.res, t);5148			continue;5149		}5150		data.qp = pwqp->p[i].qp;5151		if (isl_set_foreach_orthant(pwqp->p[i].set,5152					&to_polynomial_on_orthant, &data) < 0)5153			goto error;5154	}5155 5156	isl_pw_qpolynomial_free(pwqp);5157 5158	return data.res;5159error:5160	isl_pw_qpolynomial_free(pwqp);5161	isl_pw_qpolynomial_free(data.res);5162	return NULL;5163}5164 5165static __isl_give isl_pw_qpolynomial *poly_entry(5166	__isl_take isl_pw_qpolynomial *pwqp, void *user)5167{5168	int *sign = user;5169 5170	return isl_pw_qpolynomial_to_polynomial(pwqp, *sign);5171}5172 5173__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_to_polynomial(5174	__isl_take isl_union_pw_qpolynomial *upwqp, int sign)5175{5176	return isl_union_pw_qpolynomial_transform_inplace(upwqp,5177				   &poly_entry, &sign);5178}5179 5180__isl_give isl_basic_map *isl_basic_map_from_qpolynomial(5181	__isl_take isl_qpolynomial *qp)5182{5183	int i, k;5184	isl_space *space;5185	isl_vec *aff = NULL;5186	isl_basic_map *bmap = NULL;5187	isl_bool is_affine;5188	unsigned pos;5189	unsigned n_div;5190 5191	if (!qp)5192		return NULL;5193	is_affine = isl_poly_is_affine(qp->poly);5194	if (is_affine < 0)5195		goto error;5196	if (!is_affine)5197		isl_die(qp->dim->ctx, isl_error_invalid,5198			"input quasi-polynomial not affine", goto error);5199	aff = isl_qpolynomial_extract_affine(qp);5200	if (!aff)5201		goto error;5202	space = isl_qpolynomial_get_space(qp);5203	pos = 1 + isl_space_offset(space, isl_dim_out);5204	n_div = qp->div->n_row;5205	bmap = isl_basic_map_alloc_space(space, n_div, 1, 2 * n_div);5206 5207	for (i = 0; i < n_div; ++i) {5208		k = isl_basic_map_alloc_div(bmap);5209		if (k < 0)5210			goto error;5211		isl_seq_cpy(bmap->div[k], qp->div->row[i], qp->div->n_col);5212		isl_int_set_si(bmap->div[k][qp->div->n_col], 0);5213		bmap = isl_basic_map_add_div_constraints(bmap, k);5214	}5215	k = isl_basic_map_alloc_equality(bmap);5216	if (k < 0)5217		goto error;5218	isl_int_neg(bmap->eq[k][pos], aff->el[0]);5219	isl_seq_cpy(bmap->eq[k], aff->el + 1, pos);5220	isl_seq_cpy(bmap->eq[k] + pos + 1, aff->el + 1 + pos, n_div);5221 5222	isl_vec_free(aff);5223	isl_qpolynomial_free(qp);5224	bmap = isl_basic_map_finalize(bmap);5225	return bmap;5226error:5227	isl_vec_free(aff);5228	isl_qpolynomial_free(qp);5229	isl_basic_map_free(bmap);5230	return NULL;5231}5232