1 /* 2 * Copyright 2008-2009 Katholieke Universiteit Leuven 3 * Copyright 2010 INRIA Saclay 4 * 5 * Use of this software is governed by the MIT license 6 * 7 * Written by Sven Verdoolaege, K.U.Leuven, Departement 8 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium 9 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite, 10 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France 11 */ 12 13 #include <isl_mat_private.h> 14 #include <isl_vec_private.h> 15 #include <isl_seq.h> 16 #include "isl_map_private.h" 17 #include "isl_equalities.h" 18 #include <isl_val_private.h> 19 20 /* Given a set of modulo constraints 21 * 22 * c + A y = 0 mod d 23 * 24 * this function computes a particular solution y_0 25 * 26 * The input is given as a matrix B = [ c A ] and a vector d. 27 * 28 * The output is matrix containing the solution y_0 or 29 * a zero-column matrix if the constraints admit no integer solution. 30 * 31 * The given set of constrains is equivalent to 32 * 33 * c + A y = -D x 34 * 35 * with D = diag d and x a fresh set of variables. 36 * Reducing both c and A modulo d does not change the 37 * value of y in the solution and may lead to smaller coefficients. 38 * Let M = [ D A ] and [ H 0 ] = M U, the Hermite normal form of M. 39 * Then 40 * [ x ] 41 * M [ y ] = - c 42 * and so 43 * [ x ] 44 * [ H 0 ] U^{-1} [ y ] = - c 45 * Let 46 * [ A ] [ x ] 47 * [ B ] = U^{-1} [ y ] 48 * then 49 * H A + 0 B = -c 50 * 51 * so B may be chosen arbitrarily, e.g., B = 0, and then 52 * 53 * [ x ] = [ -c ] 54 * U^{-1} [ y ] = [ 0 ] 55 * or 56 * [ x ] [ -c ] 57 * [ y ] = U [ 0 ] 58 * specifically, 59 * 60 * y = U_{2,1} (-c) 61 * 62 * If any of the coordinates of this y are non-integer 63 * then the constraints admit no integer solution and 64 * a zero-column matrix is returned. 65 */ 66 static __isl_give isl_mat *particular_solution(__isl_keep isl_mat *B, 67 __isl_keep isl_vec *d) 68 { 69 int i, j; 70 struct isl_mat *M = NULL; 71 struct isl_mat *C = NULL; 72 struct isl_mat *U = NULL; 73 struct isl_mat *H = NULL; 74 struct isl_mat *cst = NULL; 75 struct isl_mat *T = NULL; 76 77 M = isl_mat_alloc(B->ctx, B->n_row, B->n_row + B->n_col - 1); 78 C = isl_mat_alloc(B->ctx, 1 + B->n_row, 1); 79 if (!M || !C) 80 goto error; 81 isl_int_set_si(C->row[0][0], 1); 82 for (i = 0; i < B->n_row; ++i) { 83 isl_seq_clr(M->row[i], B->n_row); 84 isl_int_set(M->row[i][i], d->block.data[i]); 85 isl_int_neg(C->row[1 + i][0], B->row[i][0]); 86 isl_int_fdiv_r(C->row[1+i][0], C->row[1+i][0], M->row[i][i]); 87 for (j = 0; j < B->n_col - 1; ++j) 88 isl_int_fdiv_r(M->row[i][B->n_row + j], 89 B->row[i][1 + j], M->row[i][i]); 90 } 91 M = isl_mat_left_hermite(M, 0, &U, NULL); 92 if (!M || !U) 93 goto error; 94 H = isl_mat_sub_alloc(M, 0, B->n_row, 0, B->n_row); 95 H = isl_mat_lin_to_aff(H); 96 C = isl_mat_inverse_product(H, C); 97 if (!C) 98 goto error; 99 for (i = 0; i < B->n_row; ++i) { 100 if (!isl_int_is_divisible_by(C->row[1+i][0], C->row[0][0])) 101 break; 102 isl_int_divexact(C->row[1+i][0], C->row[1+i][0], C->row[0][0]); 103 } 104 if (i < B->n_row) 105 cst = isl_mat_alloc(B->ctx, B->n_row, 0); 106 else 107 cst = isl_mat_sub_alloc(C, 1, B->n_row, 0, 1); 108 T = isl_mat_sub_alloc(U, B->n_row, B->n_col - 1, 0, B->n_row); 109 cst = isl_mat_product(T, cst); 110 isl_mat_free(M); 111 isl_mat_free(C); 112 isl_mat_free(U); 113 return cst; 114 error: 115 isl_mat_free(M); 116 isl_mat_free(C); 117 isl_mat_free(U); 118 return NULL; 119 } 120 121 /* Compute and return the matrix 122 * 123 * U_1^{-1} diag(d_1, 1, ..., 1) 124 * 125 * with U_1 the unimodular completion of the first (and only) row of B. 126 * The columns of this matrix generate the lattice that satisfies 127 * the single (linear) modulo constraint. 128 */ 129 static __isl_take isl_mat *parameter_compression_1(__isl_keep isl_mat *B, 130 __isl_keep isl_vec *d) 131 { 132 struct isl_mat *U; 133 134 U = isl_mat_alloc(B->ctx, B->n_col - 1, B->n_col - 1); 135 if (!U) 136 return NULL; 137 isl_seq_cpy(U->row[0], B->row[0] + 1, B->n_col - 1); 138 U = isl_mat_unimodular_complete(U, 1); 139 U = isl_mat_right_inverse(U); 140 if (!U) 141 return NULL; 142 isl_mat_col_mul(U, 0, d->block.data[0], 0); 143 U = isl_mat_lin_to_aff(U); 144 return U; 145 } 146 147 /* Compute a common lattice of solutions to the linear modulo 148 * constraints specified by B and d. 149 * See also the documentation of isl_mat_parameter_compression. 150 * We put the matrix 151 * 152 * A = [ L_1^{-T} L_2^{-T} ... L_k^{-T} ] 153 * 154 * on a common denominator. This denominator D is the lcm of modulos d. 155 * Since L_i = U_i^{-1} diag(d_i, 1, ... 1), we have 156 * L_i^{-T} = U_i^T diag(d_i, 1, ... 1)^{-T} = U_i^T diag(1/d_i, 1, ..., 1). 157 * Putting this on the common denominator, we have 158 * D * L_i^{-T} = U_i^T diag(D/d_i, D, ..., D). 159 */ 160 static __isl_give isl_mat *parameter_compression_multi(__isl_keep isl_mat *B, 161 __isl_keep isl_vec *d) 162 { 163 int i, j, k; 164 isl_int D; 165 struct isl_mat *A = NULL, *U = NULL; 166 struct isl_mat *T; 167 unsigned size; 168 169 isl_int_init(D); 170 171 isl_vec_lcm(d, &D); 172 173 size = B->n_col - 1; 174 A = isl_mat_alloc(B->ctx, size, B->n_row * size); 175 U = isl_mat_alloc(B->ctx, size, size); 176 if (!U || !A) 177 goto error; 178 for (i = 0; i < B->n_row; ++i) { 179 isl_seq_cpy(U->row[0], B->row[i] + 1, size); 180 U = isl_mat_unimodular_complete(U, 1); 181 if (!U) 182 goto error; 183 isl_int_divexact(D, D, d->block.data[i]); 184 for (k = 0; k < U->n_col; ++k) 185 isl_int_mul(A->row[k][i*size+0], D, U->row[0][k]); 186 isl_int_mul(D, D, d->block.data[i]); 187 for (j = 1; j < U->n_row; ++j) 188 for (k = 0; k < U->n_col; ++k) 189 isl_int_mul(A->row[k][i*size+j], 190 D, U->row[j][k]); 191 } 192 A = isl_mat_left_hermite(A, 0, NULL, NULL); 193 T = isl_mat_sub_alloc(A, 0, A->n_row, 0, A->n_row); 194 T = isl_mat_lin_to_aff(T); 195 if (!T) 196 goto error; 197 isl_int_set(T->row[0][0], D); 198 T = isl_mat_right_inverse(T); 199 if (!T) 200 goto error; 201 isl_assert(T->ctx, isl_int_is_one(T->row[0][0]), goto error); 202 T = isl_mat_transpose(T); 203 isl_mat_free(A); 204 isl_mat_free(U); 205 206 isl_int_clear(D); 207 return T; 208 error: 209 isl_mat_free(A); 210 isl_mat_free(U); 211 isl_int_clear(D); 212 return NULL; 213 } 214 215 /* Given a set of modulo constraints 216 * 217 * c + A y = 0 mod d 218 * 219 * this function returns an affine transformation T, 220 * 221 * y = T y' 222 * 223 * that bijectively maps the integer vectors y' to integer 224 * vectors y that satisfy the modulo constraints. 225 * 226 * This function is inspired by Section 2.5.3 227 * of B. Meister, "Stating and Manipulating Periodicity in the Polytope 228 * Model. Applications to Program Analysis and Optimization". 229 * However, the implementation only follows the algorithm of that 230 * section for computing a particular solution and not for computing 231 * a general homogeneous solution. The latter is incomplete and 232 * may remove some valid solutions. 233 * Instead, we use an adaptation of the algorithm in Section 7 of 234 * B. Meister, S. Verdoolaege, "Polynomial Approximations in the Polytope 235 * Model: Bringing the Power of Quasi-Polynomials to the Masses". 236 * 237 * The input is given as a matrix B = [ c A ] and a vector d. 238 * Each element of the vector d corresponds to a row in B. 239 * The output is a lower triangular matrix. 240 * If no integer vector y satisfies the given constraints then 241 * a matrix with zero columns is returned. 242 * 243 * We first compute a particular solution y_0 to the given set of 244 * modulo constraints in particular_solution. If no such solution 245 * exists, then we return a zero-columned transformation matrix. 246 * Otherwise, we compute the generic solution to 247 * 248 * A y = 0 mod d 249 * 250 * That is we want to compute G such that 251 * 252 * y = G y'' 253 * 254 * with y'' integer, describes the set of solutions. 255 * 256 * We first remove the common factors of each row. 257 * In particular if gcd(A_i,d_i) != 1, then we divide the whole 258 * row i (including d_i) by this common factor. If afterwards gcd(A_i) != 1, 259 * then we divide this row of A by the common factor, unless gcd(A_i) = 0. 260 * In the later case, we simply drop the row (in both A and d). 261 * 262 * If there are no rows left in A, then G is the identity matrix. Otherwise, 263 * for each row i, we now determine the lattice of integer vectors 264 * that satisfies this row. Let U_i be the unimodular extension of the 265 * row A_i. This unimodular extension exists because gcd(A_i) = 1. 266 * The first component of 267 * 268 * y' = U_i y 269 * 270 * needs to be a multiple of d_i. Let y' = diag(d_i, 1, ..., 1) y''. 271 * Then, 272 * 273 * y = U_i^{-1} diag(d_i, 1, ..., 1) y'' 274 * 275 * for arbitrary integer vectors y''. That is, y belongs to the lattice 276 * generated by the columns of L_i = U_i^{-1} diag(d_i, 1, ..., 1). 277 * If there is only one row, then G = L_1. 278 * 279 * If there is more than one row left, we need to compute the intersection 280 * of the lattices. That is, we need to compute an L such that 281 * 282 * L = L_i L_i' for all i 283 * 284 * with L_i' some integer matrices. Let A be constructed as follows 285 * 286 * A = [ L_1^{-T} L_2^{-T} ... L_k^{-T} ] 287 * 288 * and computed the Hermite Normal Form of A = [ H 0 ] U 289 * Then, 290 * 291 * L_i^{-T} = H U_{1,i} 292 * 293 * or 294 * 295 * H^{-T} = L_i U_{1,i}^T 296 * 297 * In other words G = L = H^{-T}. 298 * To ensure that G is lower triangular, we compute and use its Hermite 299 * normal form. 300 * 301 * The affine transformation matrix returned is then 302 * 303 * [ 1 0 ] 304 * [ y_0 G ] 305 * 306 * as any y = y_0 + G y' with y' integer is a solution to the original 307 * modulo constraints. 308 */ 309 __isl_give isl_mat *isl_mat_parameter_compression(__isl_take isl_mat *B, 310 __isl_take isl_vec *d) 311 { 312 int i; 313 struct isl_mat *cst = NULL; 314 struct isl_mat *T = NULL; 315 isl_int D; 316 317 if (!B || !d) 318 goto error; 319 isl_assert(B->ctx, B->n_row == d->size, goto error); 320 cst = particular_solution(B, d); 321 if (!cst) 322 goto error; 323 if (cst->n_col == 0) { 324 T = isl_mat_alloc(B->ctx, B->n_col, 0); 325 isl_mat_free(cst); 326 isl_mat_free(B); 327 isl_vec_free(d); 328 return T; 329 } 330 isl_int_init(D); 331 /* Replace a*g*row = 0 mod g*m by row = 0 mod m */ 332 for (i = 0; i < B->n_row; ++i) { 333 isl_seq_gcd(B->row[i] + 1, B->n_col - 1, &D); 334 if (isl_int_is_one(D)) 335 continue; 336 if (isl_int_is_zero(D)) { 337 B = isl_mat_drop_rows(B, i, 1); 338 d = isl_vec_cow(d); 339 if (!B || !d) 340 goto error2; 341 isl_seq_cpy(d->block.data+i, d->block.data+i+1, 342 d->size - (i+1)); 343 d->size--; 344 i--; 345 continue; 346 } 347 B = isl_mat_cow(B); 348 if (!B) 349 goto error2; 350 isl_seq_scale_down(B->row[i] + 1, B->row[i] + 1, D, B->n_col-1); 351 isl_int_gcd(D, D, d->block.data[i]); 352 d = isl_vec_cow(d); 353 if (!d) 354 goto error2; 355 isl_int_divexact(d->block.data[i], d->block.data[i], D); 356 } 357 isl_int_clear(D); 358 if (B->n_row == 0) 359 T = isl_mat_identity(B->ctx, B->n_col); 360 else if (B->n_row == 1) 361 T = parameter_compression_1(B, d); 362 else 363 T = parameter_compression_multi(B, d); 364 T = isl_mat_left_hermite(T, 0, NULL, NULL); 365 if (!T) 366 goto error; 367 isl_mat_sub_copy(T->ctx, T->row + 1, cst->row, cst->n_row, 0, 0, 1); 368 isl_mat_free(cst); 369 isl_mat_free(B); 370 isl_vec_free(d); 371 return T; 372 error2: 373 isl_int_clear(D); 374 error: 375 isl_mat_free(cst); 376 isl_mat_free(B); 377 isl_vec_free(d); 378 return NULL; 379 } 380 381 /* Given a set of equalities 382 * 383 * B(y) + A x = 0 (*) 384 * 385 * compute and return an affine transformation T, 386 * 387 * y = T y' 388 * 389 * that bijectively maps the integer vectors y' to integer 390 * vectors y that satisfy the modulo constraints for some value of x. 391 * 392 * Let [H 0] be the Hermite Normal Form of A, i.e., 393 * 394 * A = [H 0] Q 395 * 396 * Then y is a solution of (*) iff 397 * 398 * H^-1 B(y) (= - [I 0] Q x) 399 * 400 * is an integer vector. Let d be the common denominator of H^-1. 401 * We impose 402 * 403 * d H^-1 B(y) = 0 mod d 404 * 405 * and compute the solution using isl_mat_parameter_compression. 406 */ 407 __isl_give isl_mat *isl_mat_parameter_compression_ext(__isl_take isl_mat *B, 408 __isl_take isl_mat *A) 409 { 410 isl_ctx *ctx; 411 isl_vec *d; 412 int n_row, n_col; 413 414 if (!A) 415 return isl_mat_free(B); 416 417 ctx = isl_mat_get_ctx(A); 418 n_row = A->n_row; 419 n_col = A->n_col; 420 A = isl_mat_left_hermite(A, 0, NULL, NULL); 421 A = isl_mat_drop_cols(A, n_row, n_col - n_row); 422 A = isl_mat_lin_to_aff(A); 423 A = isl_mat_right_inverse(A); 424 d = isl_vec_alloc(ctx, n_row); 425 if (A) 426 d = isl_vec_set(d, A->row[0][0]); 427 A = isl_mat_drop_rows(A, 0, 1); 428 A = isl_mat_drop_cols(A, 0, 1); 429 B = isl_mat_product(A, B); 430 431 return isl_mat_parameter_compression(B, d); 432 } 433 434 /* Return a compression matrix that indicates that there are no solutions 435 * to the original constraints. In particular, return a zero-column 436 * matrix with 1 + dim rows. If "T2" is not NULL, then assign *T2 437 * the inverse of this matrix. *T2 may already have been assigned 438 * matrix, so free it first. 439 * "free1", "free2" and "free3" are temporary matrices that are 440 * not useful when an empty compression is returned. They are 441 * simply freed. 442 */ 443 static __isl_give isl_mat *empty_compression(isl_ctx *ctx, unsigned dim, 444 __isl_give isl_mat **T2, __isl_take isl_mat *free1, 445 __isl_take isl_mat *free2, __isl_take isl_mat *free3) 446 { 447 isl_mat_free(free1); 448 isl_mat_free(free2); 449 isl_mat_free(free3); 450 if (T2) { 451 isl_mat_free(*T2); 452 *T2 = isl_mat_alloc(ctx, 0, 1 + dim); 453 } 454 return isl_mat_alloc(ctx, 1 + dim, 0); 455 } 456 457 /* Given a matrix that maps a (possibly) parametric domain to 458 * a parametric domain, add in rows that map the "nparam" parameters onto 459 * themselves. 460 */ 461 static __isl_give isl_mat *insert_parameter_rows(__isl_take isl_mat *mat, 462 unsigned nparam) 463 { 464 int i; 465 466 if (nparam == 0) 467 return mat; 468 if (!mat) 469 return NULL; 470 471 mat = isl_mat_insert_rows(mat, 1, nparam); 472 if (!mat) 473 return NULL; 474 475 for (i = 0; i < nparam; ++i) { 476 isl_seq_clr(mat->row[1 + i], mat->n_col); 477 isl_int_set(mat->row[1 + i][1 + i], mat->row[0][0]); 478 } 479 480 return mat; 481 } 482 483 /* Given a set of equalities 484 * 485 * -C(y) + M x = 0 486 * 487 * this function computes a unimodular transformation from a lower-dimensional 488 * space to the original space that bijectively maps the integer points x' 489 * in the lower-dimensional space to the integer points x in the original 490 * space that satisfy the equalities. 491 * 492 * The input is given as a matrix B = [ -C M ] and the output is a 493 * matrix that maps [1 x'] to [1 x]. 494 * The number of equality constraints in B is assumed to be smaller than 495 * or equal to the number of variables x. 496 * "first" is the position of the first x variable. 497 * The preceding variables are considered to be y-variables. 498 * If T2 is not NULL, then *T2 is set to a matrix mapping [1 x] to [1 x']. 499 * 500 * First compute the (left) Hermite normal form of M, 501 * 502 * M [U1 U2] = M U = H = [H1 0] 503 * or 504 * M = H Q = [H1 0] [Q1] 505 * [Q2] 506 * 507 * with U, Q unimodular, Q = U^{-1} (and H lower triangular). 508 * Define the transformed variables as 509 * 510 * x = [U1 U2] [ x1' ] = [U1 U2] [Q1] x 511 * [ x2' ] [Q2] 512 * 513 * The equalities then become 514 * 515 * -C(y) + H1 x1' = 0 or x1' = H1^{-1} C(y) = C'(y) 516 * 517 * If the denominator of the constant term does not divide the 518 * the common denominator of the coefficients of y, then every 519 * integer point is mapped to a non-integer point and then the original set 520 * has no integer solutions (since the x' are a unimodular transformation 521 * of the x). In this case, a zero-column matrix is returned. 522 * Otherwise, the transformation is given by 523 * 524 * x = U1 H1^{-1} C(y) + U2 x2' 525 * 526 * The inverse transformation is simply 527 * 528 * x2' = Q2 x 529 */ 530 __isl_give isl_mat *isl_mat_final_variable_compression(__isl_take isl_mat *B, 531 int first, __isl_give isl_mat **T2) 532 { 533 int i, n; 534 isl_ctx *ctx; 535 isl_mat *H = NULL, *C, *H1, *U = NULL, *U1, *U2; 536 unsigned dim; 537 538 if (T2) 539 *T2 = NULL; 540 if (!B) 541 goto error; 542 543 ctx = isl_mat_get_ctx(B); 544 dim = B->n_col - 1; 545 n = dim - first; 546 if (n < B->n_row) 547 isl_die(ctx, isl_error_invalid, "too many equality constraints", 548 goto error); 549 H = isl_mat_sub_alloc(B, 0, B->n_row, 1 + first, n); 550 H = isl_mat_left_hermite(H, 0, &U, T2); 551 if (!H || !U || (T2 && !*T2)) 552 goto error; 553 if (T2) { 554 *T2 = isl_mat_drop_rows(*T2, 0, B->n_row); 555 *T2 = isl_mat_diagonal(isl_mat_identity(ctx, 1 + first), *T2); 556 if (!*T2) 557 goto error; 558 } 559 C = isl_mat_alloc(ctx, 1 + B->n_row, 1 + first); 560 if (!C) 561 goto error; 562 isl_int_set_si(C->row[0][0], 1); 563 isl_seq_clr(C->row[0] + 1, first); 564 isl_mat_sub_neg(ctx, C->row + 1, B->row, B->n_row, 0, 0, 1 + first); 565 H1 = isl_mat_sub_alloc(H, 0, H->n_row, 0, H->n_row); 566 H1 = isl_mat_lin_to_aff(H1); 567 C = isl_mat_inverse_product(H1, C); 568 if (!C) 569 goto error; 570 isl_mat_free(H); 571 if (!isl_int_is_one(C->row[0][0])) { 572 isl_int g; 573 574 isl_int_init(g); 575 for (i = 0; i < B->n_row; ++i) { 576 isl_seq_gcd(C->row[1 + i] + 1, first, &g); 577 isl_int_gcd(g, g, C->row[0][0]); 578 if (!isl_int_is_divisible_by(C->row[1 + i][0], g)) 579 break; 580 } 581 isl_int_clear(g); 582 583 if (i < B->n_row) 584 return empty_compression(ctx, dim, T2, B, C, U); 585 C = isl_mat_normalize(C); 586 } 587 U1 = isl_mat_sub_alloc(U, 0, U->n_row, 0, B->n_row); 588 U1 = isl_mat_lin_to_aff(U1); 589 U2 = isl_mat_sub_alloc(U, 0, U->n_row, B->n_row, U->n_row - B->n_row); 590 U2 = isl_mat_lin_to_aff(U2); 591 isl_mat_free(U); 592 C = isl_mat_product(U1, C); 593 C = isl_mat_aff_direct_sum(C, U2); 594 C = insert_parameter_rows(C, first); 595 596 isl_mat_free(B); 597 598 return C; 599 error: 600 isl_mat_free(B); 601 isl_mat_free(H); 602 isl_mat_free(U); 603 if (T2) { 604 isl_mat_free(*T2); 605 *T2 = NULL; 606 } 607 return NULL; 608 } 609 610 /* Given a set of equalities 611 * 612 * M x - c = 0 613 * 614 * this function computes a unimodular transformation from a lower-dimensional 615 * space to the original space that bijectively maps the integer points x' 616 * in the lower-dimensional space to the integer points x in the original 617 * space that satisfy the equalities. 618 * 619 * The input is given as a matrix B = [ -c M ] and the output is a 620 * matrix that maps [1 x'] to [1 x]. 621 * The number of equality constraints in B is assumed to be smaller than 622 * or equal to the number of variables x. 623 * If T2 is not NULL, then *T2 is set to a matrix mapping [1 x] to [1 x']. 624 */ 625 __isl_give isl_mat *isl_mat_variable_compression(__isl_take isl_mat *B, 626 __isl_give isl_mat **T2) 627 { 628 return isl_mat_final_variable_compression(B, 0, T2); 629 } 630 631 /* Return "bset" and set *T and *T2 to the identity transformation 632 * on "bset" (provided T and T2 are not NULL). 633 */ 634 static __isl_give isl_basic_set *return_with_identity( 635 __isl_take isl_basic_set *bset, __isl_give isl_mat **T, 636 __isl_give isl_mat **T2) 637 { 638 isl_size dim; 639 isl_mat *id; 640 641 dim = isl_basic_set_dim(bset, isl_dim_set); 642 if (dim < 0) 643 return isl_basic_set_free(bset); 644 if (!T && !T2) 645 return bset; 646 647 id = isl_mat_identity(isl_basic_map_get_ctx(bset), 1 + dim); 648 if (T) 649 *T = isl_mat_copy(id); 650 if (T2) 651 *T2 = isl_mat_copy(id); 652 isl_mat_free(id); 653 654 return bset; 655 } 656 657 /* Use the n equalities of bset to unimodularly transform the 658 * variables x such that n transformed variables x1' have a constant value 659 * and rewrite the constraints of bset in terms of the remaining 660 * transformed variables x2'. The matrix pointed to by T maps 661 * the new variables x2' back to the original variables x, while T2 662 * maps the original variables to the new variables. 663 */ 664 static __isl_give isl_basic_set *compress_variables( 665 __isl_take isl_basic_set *bset, 666 __isl_give isl_mat **T, __isl_give isl_mat **T2) 667 { 668 struct isl_mat *B, *TC; 669 isl_size dim; 670 671 if (T) 672 *T = NULL; 673 if (T2) 674 *T2 = NULL; 675 if (isl_basic_set_check_no_params(bset) < 0 || 676 isl_basic_set_check_no_locals(bset) < 0) 677 return isl_basic_set_free(bset); 678 dim = isl_basic_set_dim(bset, isl_dim_set); 679 if (dim < 0) 680 return isl_basic_set_free(bset); 681 isl_assert(bset->ctx, bset->n_eq <= dim, goto error); 682 if (bset->n_eq == 0) 683 return return_with_identity(bset, T, T2); 684 685 B = isl_mat_sub_alloc6(bset->ctx, bset->eq, 0, bset->n_eq, 0, 1 + dim); 686 TC = isl_mat_variable_compression(B, T2); 687 if (!TC) 688 goto error; 689 if (TC->n_col == 0) { 690 isl_mat_free(TC); 691 if (T2) { 692 isl_mat_free(*T2); 693 *T2 = NULL; 694 } 695 bset = isl_basic_set_set_to_empty(bset); 696 return return_with_identity(bset, T, T2); 697 } 698 699 bset = isl_basic_set_preimage(bset, T ? isl_mat_copy(TC) : TC); 700 if (T) 701 *T = TC; 702 return bset; 703 error: 704 isl_basic_set_free(bset); 705 return NULL; 706 } 707 708 __isl_give isl_basic_set *isl_basic_set_remove_equalities( 709 __isl_take isl_basic_set *bset, __isl_give isl_mat **T, 710 __isl_give isl_mat **T2) 711 { 712 if (T) 713 *T = NULL; 714 if (T2) 715 *T2 = NULL; 716 if (isl_basic_set_check_no_params(bset) < 0) 717 return isl_basic_set_free(bset); 718 bset = isl_basic_set_gauss(bset, NULL); 719 if (ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY)) 720 return return_with_identity(bset, T, T2); 721 bset = compress_variables(bset, T, T2); 722 return bset; 723 } 724 725 /* Check if dimension dim belongs to a residue class 726 * i_dim \equiv r mod m 727 * with m != 1 and if so return m in *modulo and r in *residue. 728 * As a special case, when i_dim has a fixed value v, then 729 * *modulo is set to 0 and *residue to v. 730 * 731 * If i_dim does not belong to such a residue class, then *modulo 732 * is set to 1 and *residue is set to 0. 733 */ 734 isl_stat isl_basic_set_dim_residue_class(__isl_keep isl_basic_set *bset, 735 int pos, isl_int *modulo, isl_int *residue) 736 { 737 isl_bool fixed; 738 struct isl_ctx *ctx; 739 struct isl_mat *H = NULL, *U = NULL, *C, *H1, *U1; 740 isl_size total; 741 isl_size nparam; 742 743 if (!bset || !modulo || !residue) 744 return isl_stat_error; 745 746 fixed = isl_basic_set_plain_dim_is_fixed(bset, pos, residue); 747 if (fixed < 0) 748 return isl_stat_error; 749 if (fixed) { 750 isl_int_set_si(*modulo, 0); 751 return isl_stat_ok; 752 } 753 754 ctx = isl_basic_set_get_ctx(bset); 755 total = isl_basic_set_dim(bset, isl_dim_all); 756 nparam = isl_basic_set_dim(bset, isl_dim_param); 757 if (total < 0 || nparam < 0) 758 return isl_stat_error; 759 H = isl_mat_sub_alloc6(ctx, bset->eq, 0, bset->n_eq, 1, total); 760 H = isl_mat_left_hermite(H, 0, &U, NULL); 761 if (!H) 762 return isl_stat_error; 763 764 isl_seq_gcd(U->row[nparam + pos]+bset->n_eq, 765 total-bset->n_eq, modulo); 766 if (isl_int_is_zero(*modulo)) 767 isl_int_set_si(*modulo, 1); 768 if (isl_int_is_one(*modulo)) { 769 isl_int_set_si(*residue, 0); 770 isl_mat_free(H); 771 isl_mat_free(U); 772 return isl_stat_ok; 773 } 774 775 C = isl_mat_alloc(ctx, 1 + bset->n_eq, 1); 776 if (!C) 777 goto error; 778 isl_int_set_si(C->row[0][0], 1); 779 isl_mat_sub_neg(ctx, C->row + 1, bset->eq, bset->n_eq, 0, 0, 1); 780 H1 = isl_mat_sub_alloc(H, 0, H->n_row, 0, H->n_row); 781 H1 = isl_mat_lin_to_aff(H1); 782 C = isl_mat_inverse_product(H1, C); 783 isl_mat_free(H); 784 U1 = isl_mat_sub_alloc(U, nparam+pos, 1, 0, bset->n_eq); 785 U1 = isl_mat_lin_to_aff(U1); 786 isl_mat_free(U); 787 C = isl_mat_product(U1, C); 788 if (!C) 789 return isl_stat_error; 790 if (!isl_int_is_divisible_by(C->row[1][0], C->row[0][0])) { 791 bset = isl_basic_set_copy(bset); 792 bset = isl_basic_set_set_to_empty(bset); 793 isl_basic_set_free(bset); 794 isl_int_set_si(*modulo, 1); 795 isl_int_set_si(*residue, 0); 796 return isl_stat_ok; 797 } 798 isl_int_divexact(*residue, C->row[1][0], C->row[0][0]); 799 isl_int_fdiv_r(*residue, *residue, *modulo); 800 isl_mat_free(C); 801 return isl_stat_ok; 802 error: 803 isl_mat_free(H); 804 isl_mat_free(U); 805 return isl_stat_error; 806 } 807 808 /* Check if dimension dim belongs to a residue class 809 * i_dim \equiv r mod m 810 * with m != 1 and if so return m in *modulo and r in *residue. 811 * As a special case, when i_dim has a fixed value v, then 812 * *modulo is set to 0 and *residue to v. 813 * 814 * If i_dim does not belong to such a residue class, then *modulo 815 * is set to 1 and *residue is set to 0. 816 */ 817 isl_stat isl_set_dim_residue_class(__isl_keep isl_set *set, 818 int pos, isl_int *modulo, isl_int *residue) 819 { 820 isl_int m; 821 isl_int r; 822 int i; 823 824 if (!set || !modulo || !residue) 825 return isl_stat_error; 826 827 if (set->n == 0) { 828 isl_int_set_si(*modulo, 0); 829 isl_int_set_si(*residue, 0); 830 return isl_stat_ok; 831 } 832 833 if (isl_basic_set_dim_residue_class(set->p[0], pos, modulo, residue)<0) 834 return isl_stat_error; 835 836 if (set->n == 1) 837 return isl_stat_ok; 838 839 if (isl_int_is_one(*modulo)) 840 return isl_stat_ok; 841 842 isl_int_init(m); 843 isl_int_init(r); 844 845 for (i = 1; i < set->n; ++i) { 846 if (isl_basic_set_dim_residue_class(set->p[i], pos, &m, &r) < 0) 847 goto error; 848 isl_int_gcd(*modulo, *modulo, m); 849 isl_int_sub(m, *residue, r); 850 isl_int_gcd(*modulo, *modulo, m); 851 if (!isl_int_is_zero(*modulo)) 852 isl_int_fdiv_r(*residue, *residue, *modulo); 853 if (isl_int_is_one(*modulo)) 854 break; 855 } 856 857 isl_int_clear(m); 858 isl_int_clear(r); 859 860 return isl_stat_ok; 861 error: 862 isl_int_clear(m); 863 isl_int_clear(r); 864 return isl_stat_error; 865 } 866 867 /* Check if dimension "dim" belongs to a residue class 868 * i_dim \equiv r mod m 869 * with m != 1 and if so return m in *modulo and r in *residue. 870 * As a special case, when i_dim has a fixed value v, then 871 * *modulo is set to 0 and *residue to v. 872 * 873 * If i_dim does not belong to such a residue class, then *modulo 874 * is set to 1 and *residue is set to 0. 875 */ 876 isl_stat isl_set_dim_residue_class_val(__isl_keep isl_set *set, 877 int pos, __isl_give isl_val **modulo, __isl_give isl_val **residue) 878 { 879 *modulo = NULL; 880 *residue = NULL; 881 if (!set) 882 return isl_stat_error; 883 *modulo = isl_val_alloc(isl_set_get_ctx(set)); 884 *residue = isl_val_alloc(isl_set_get_ctx(set)); 885 if (!*modulo || !*residue) 886 goto error; 887 if (isl_set_dim_residue_class(set, pos, 888 &(*modulo)->n, &(*residue)->n) < 0) 889 goto error; 890 isl_int_set_si((*modulo)->d, 1); 891 isl_int_set_si((*residue)->d, 1); 892 return isl_stat_ok; 893 error: 894 isl_val_free(*modulo); 895 isl_val_free(*residue); 896 return isl_stat_error; 897 } 898