Coverage Report

Created: 2019-07-24 05:18

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