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