Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/tools/polly/lib/External/isl/isl_fold.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
#define ISL_DIM_H
12
#include <isl_map_private.h>
13
#include <isl_union_map_private.h>
14
#include <isl_polynomial_private.h>
15
#include <isl_point_private.h>
16
#include <isl_space_private.h>
17
#include <isl_lp_private.h>
18
#include <isl_seq.h>
19
#include <isl_mat_private.h>
20
#include <isl_val_private.h>
21
#include <isl_vec_private.h>
22
#include <isl_config.h>
23
#include <isl/deprecated/polynomial_int.h>
24
25
enum isl_fold isl_fold_type_negate(enum isl_fold type)
26
0
{
27
0
  switch (type) {
28
0
  case isl_fold_min:
29
0
    return isl_fold_max;
30
0
  case isl_fold_max:
31
0
    return isl_fold_min;
32
0
  case isl_fold_list:
33
0
    return isl_fold_list;
34
0
  }
35
0
36
0
  
isl_die0
(NULL, isl_error_internal, "unhandled isl_fold type", abort());
37
0
}
38
39
static __isl_give isl_qpolynomial_fold *qpolynomial_fold_alloc(
40
  enum isl_fold type, __isl_take isl_space *dim, int n)
41
19
{
42
19
  isl_qpolynomial_fold *fold;
43
19
44
19
  if (!dim)
45
0
    goto error;
46
19
47
19
  
isl_assert19
(dim->ctx, n >= 0, goto error);
48
19
  
fold = 19
isl_calloc19
(dim->ctx, struct isl_qpolynomial_fold,
49
19
      sizeof(struct isl_qpolynomial_fold) +
50
19
      (n - 1) * sizeof(struct isl_qpolynomial *));
51
19
  if (!fold)
52
0
    goto error;
53
19
54
19
  fold->ref = 1;
55
19
  fold->size = n;
56
19
  fold->n = 0;
57
19
  fold->type = type;
58
19
  fold->dim = dim;
59
19
60
19
  return fold;
61
0
error:
62
0
  isl_space_free(dim);
63
0
  return NULL;
64
19
}
65
66
isl_ctx *isl_qpolynomial_fold_get_ctx(__isl_keep isl_qpolynomial_fold *fold)
67
0
{
68
0
  return fold ? fold->dim->ctx : NULL;
69
0
}
70
71
__isl_give isl_space *isl_qpolynomial_fold_get_domain_space(
72
  __isl_keep isl_qpolynomial_fold *fold)
73
0
{
74
0
  return fold ? isl_space_copy(fold->dim) : NULL;
75
0
}
76
77
__isl_give isl_space *isl_qpolynomial_fold_get_space(
78
  __isl_keep isl_qpolynomial_fold *fold)
79
30
{
80
30
  isl_space *space;
81
30
  if (!fold)
82
0
    return NULL;
83
30
  space = isl_space_copy(fold->dim);
84
30
  space = isl_space_from_domain(space);
85
30
  space = isl_space_add_dims(space, isl_dim_out, 1);
86
30
  return space;
87
30
}
88
89
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_reset_domain_space(
90
  __isl_take isl_qpolynomial_fold *fold, __isl_take isl_space *dim)
91
3
{
92
3
  int i;
93
3
94
3
  fold = isl_qpolynomial_fold_cow(fold);
95
3
  if (
!fold || 3
!dim3
)
96
0
    goto error;
97
3
98
6
  
for (i = 0; 3
i < fold->n6
;
++i3
) {
99
3
    fold->qp[i] = isl_qpolynomial_reset_domain_space(fold->qp[i],
100
3
              isl_space_copy(dim));
101
3
    if (!fold->qp[i])
102
0
      goto error;
103
3
  }
104
3
105
3
  isl_space_free(fold->dim);
106
3
  fold->dim = dim;
107
3
108
3
  return fold;
109
0
error:
110
0
  isl_qpolynomial_fold_free(fold);
111
0
  isl_space_free(dim);
112
0
  return NULL;
113
3
}
114
115
/* Reset the space of "fold".  This function is called from isl_pw_templ.c
116
 * and doesn't know if the space of an element object is represented
117
 * directly or through its domain.  It therefore passes along both.
118
 */
119
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_reset_space_and_domain(
120
  __isl_take isl_qpolynomial_fold *fold, __isl_take isl_space *space,
121
  __isl_take isl_space *domain)
122
3
{
123
3
  isl_space_free(space);
124
3
  return isl_qpolynomial_fold_reset_domain_space(fold, domain);
125
3
}
126
127
int isl_qpolynomial_fold_involves_dims(__isl_keep isl_qpolynomial_fold *fold,
128
  enum isl_dim_type type, unsigned first, unsigned n)
129
0
{
130
0
  int i;
131
0
132
0
  if (!fold)
133
0
    return -1;
134
0
  
if (0
fold->n == 0 || 0
n == 00
)
135
0
    return 0;
136
0
137
0
  
for (i = 0; 0
i < fold->n0
;
++i0
) {
138
0
    int involves = isl_qpolynomial_involves_dims(fold->qp[i],
139
0
                  type, first, n);
140
0
    if (
involves < 0 || 0
involves0
)
141
0
      return involves;
142
0
  }
143
0
  return 0;
144
0
}
145
146
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_set_dim_name(
147
  __isl_take isl_qpolynomial_fold *fold,
148
  enum isl_dim_type type, unsigned pos, const char *s)
149
0
{
150
0
  int i;
151
0
152
0
  fold = isl_qpolynomial_fold_cow(fold);
153
0
  if (!fold)
154
0
    return NULL;
155
0
  fold->dim = isl_space_set_dim_name(fold->dim, type, pos, s);
156
0
  if (!fold->dim)
157
0
    goto error;
158
0
159
0
  
for (i = 0; 0
i < fold->n0
;
++i0
) {
160
0
    fold->qp[i] = isl_qpolynomial_set_dim_name(fold->qp[i],
161
0
                  type, pos, s);
162
0
    if (!fold->qp[i])
163
0
      goto error;
164
0
  }
165
0
166
0
  return fold;
167
0
error:
168
0
  isl_qpolynomial_fold_free(fold);
169
0
  return NULL;
170
0
}
171
172
/* Given a dimension type for an isl_qpolynomial_fold,
173
 * return the corresponding type for the domain.
174
 */
175
static enum isl_dim_type domain_type(enum isl_dim_type type)
176
0
{
177
0
  if (type == isl_dim_in)
178
0
    return isl_dim_set;
179
0
  return type;
180
0
}
181
182
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_drop_dims(
183
  __isl_take isl_qpolynomial_fold *fold,
184
  enum isl_dim_type type, unsigned first, unsigned n)
185
1
{
186
1
  int i;
187
1
  enum isl_dim_type set_type;
188
1
189
1
  if (!fold)
190
0
    return NULL;
191
1
  
if (1
n == 01
)
192
1
    return fold;
193
0
194
0
  set_type = domain_type(type);
195
0
196
0
  fold = isl_qpolynomial_fold_cow(fold);
197
0
  if (!fold)
198
0
    return NULL;
199
0
  fold->dim = isl_space_drop_dims(fold->dim, set_type, first, n);
200
0
  if (!fold->dim)
201
0
    goto error;
202
0
203
0
  
for (i = 0; 0
i < fold->n0
;
++i0
) {
204
0
    fold->qp[i] = isl_qpolynomial_drop_dims(fold->qp[i],
205
0
                  type, first, n);
206
0
    if (!fold->qp[i])
207
0
      goto error;
208
0
  }
209
0
210
0
  return fold;
211
0
error:
212
0
  isl_qpolynomial_fold_free(fold);
213
0
  return NULL;
214
1
}
215
216
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_insert_dims(
217
  __isl_take isl_qpolynomial_fold *fold,
218
  enum isl_dim_type type, unsigned first, unsigned n)
219
0
{
220
0
  int i;
221
0
222
0
  if (!fold)
223
0
    return NULL;
224
0
  
if (0
n == 0 && 0
!isl_space_is_named_or_nested(fold->dim, type)0
)
225
0
    return fold;
226
0
227
0
  fold = isl_qpolynomial_fold_cow(fold);
228
0
  if (!fold)
229
0
    return NULL;
230
0
  fold->dim = isl_space_insert_dims(fold->dim, type, first, n);
231
0
  if (!fold->dim)
232
0
    goto error;
233
0
234
0
  
for (i = 0; 0
i < fold->n0
;
++i0
) {
235
0
    fold->qp[i] = isl_qpolynomial_insert_dims(fold->qp[i],
236
0
                  type, first, n);
237
0
    if (!fold->qp[i])
238
0
      goto error;
239
0
  }
240
0
241
0
  return fold;
242
0
error:
243
0
  isl_qpolynomial_fold_free(fold);
244
0
  return NULL;
245
0
}
246
247
/* Determine the sign of the constant quasipolynomial "qp".
248
 *
249
 * Return
250
 *  -1 if qp <= 0
251
 *   1 if qp >= 0
252
 *   0 if unknown
253
 *
254
 * For qp == 0, we can return either -1 or 1.  In practice, we return 1.
255
 * For qp == NaN, the sign is undefined, so we return 0.
256
 */
257
static int isl_qpolynomial_cst_sign(__isl_keep isl_qpolynomial *qp)
258
2
{
259
2
  struct isl_upoly_cst *cst;
260
2
261
2
  if (isl_qpolynomial_is_nan(qp))
262
0
    return 0;
263
2
264
2
  cst = isl_upoly_as_cst(qp->upoly);
265
2
  if (!cst)
266
0
    return 0;
267
2
268
2
  
return 2
isl_int_sgn2
(cst->n) < 0 ?
-11
:
11
;
269
2
}
270
271
static int isl_qpolynomial_aff_sign(__isl_keep isl_set *set,
272
  __isl_keep isl_qpolynomial *qp)
273
0
{
274
0
  enum isl_lp_result res;
275
0
  isl_vec *aff;
276
0
  isl_int opt;
277
0
  int sgn = 0;
278
0
279
0
  aff = isl_qpolynomial_extract_affine(qp);
280
0
  if (!aff)
281
0
    return 0;
282
0
283
0
  
isl_int_init0
(opt);
284
0
285
0
  res = isl_set_solve_lp(set, 0, aff->el + 1, aff->el[0],
286
0
        &opt, NULL, NULL);
287
0
  if (res == isl_lp_error)
288
0
    goto done;
289
0
  
if (0
res == isl_lp_empty ||
290
0
      
(res == isl_lp_ok && 0
!0
isl_int_is_neg0
(opt))) {
291
0
    sgn = 1;
292
0
    goto done;
293
0
  }
294
0
295
0
  res = isl_set_solve_lp(set, 1, aff->el + 1, aff->el[0],
296
0
        &opt, NULL, NULL);
297
0
  if (
res == isl_lp_ok && 0
!0
isl_int_is_pos0
(opt))
298
0
    sgn = -1;
299
0
300
0
done:
301
0
  isl_int_clear(opt);
302
0
  isl_vec_free(aff);
303
0
  return sgn;
304
0
}
305
306
/* Determine, if possible, the sign of the quasipolynomial "qp" on
307
 * the domain "set".
308
 *
309
 * If qp is a constant, then the problem is trivial.
310
 * If qp is linear, then we check if the minimum of the corresponding
311
 * affine constraint is non-negative or if the maximum is non-positive.
312
 *
313
 * Otherwise, we check if the outermost variable "v" has a lower bound "l"
314
 * in "set".  If so, we write qp(v,v') as
315
 *
316
 *  q(v,v') * (v - l) + r(v')
317
 *
318
 * if q(v,v') and r(v') have the same known sign, then the original
319
 * quasipolynomial has the same sign as well.
320
 *
321
 * Return
322
 *  -1 if qp <= 0
323
 *   1 if qp >= 0
324
 *   0 if unknown
325
 */
326
static int isl_qpolynomial_sign(__isl_keep isl_set *set,
327
  __isl_keep isl_qpolynomial *qp)
328
2
{
329
2
  int d;
330
2
  int i;
331
2
  int is;
332
2
  struct isl_upoly_rec *rec;
333
2
  isl_vec *v;
334
2
  isl_int l;
335
2
  enum isl_lp_result res;
336
2
  int sgn = 0;
337
2
338
2
  is = isl_qpolynomial_is_cst(qp, NULL, NULL);
339
2
  if (is < 0)
340
0
    return 0;
341
2
  
if (2
is2
)
342
2
    return isl_qpolynomial_cst_sign(qp);
343
0
344
0
  is = isl_qpolynomial_is_affine(qp);
345
0
  if (is < 0)
346
0
    return 0;
347
0
  
if (0
is0
)
348
0
    return isl_qpolynomial_aff_sign(set, qp);
349
0
350
0
  
if (0
qp->div->n_row > 00
)
351
0
    return 0;
352
0
353
0
  rec = isl_upoly_as_rec(qp->upoly);
354
0
  if (!rec)
355
0
    return 0;
356
0
357
0
  d = isl_space_dim(qp->dim, isl_dim_all);
358
0
  v = isl_vec_alloc(set->ctx, 2 + d);
359
0
  if (!v)
360
0
    return 0;
361
0
362
0
  isl_seq_clr(v->el + 1, 1 + d);
363
0
  isl_int_set_si(v->el[0], 1);
364
0
  isl_int_set_si(v->el[2 + qp->upoly->var], 1);
365
0
366
0
  isl_int_init(l);
367
0
368
0
  res = isl_set_solve_lp(set, 0, v->el + 1, v->el[0], &l, NULL, NULL);
369
0
  if (
res == isl_lp_ok0
) {
370
0
    isl_qpolynomial *min;
371
0
    isl_qpolynomial *base;
372
0
    isl_qpolynomial *r, *q;
373
0
    isl_qpolynomial *t;
374
0
375
0
    min = isl_qpolynomial_cst_on_domain(isl_space_copy(qp->dim), l);
376
0
    base = isl_qpolynomial_var_pow_on_domain(isl_space_copy(qp->dim),
377
0
            qp->upoly->var, 1);
378
0
379
0
    r = isl_qpolynomial_alloc(isl_space_copy(qp->dim), 0,
380
0
            isl_upoly_copy(rec->p[rec->n - 1]));
381
0
    q = isl_qpolynomial_copy(r);
382
0
383
0
    for (i = rec->n - 2; 
i >= 00
;
--i0
) {
384
0
      r = isl_qpolynomial_mul(r, isl_qpolynomial_copy(min));
385
0
      t = isl_qpolynomial_alloc(isl_space_copy(qp->dim), 0,
386
0
              isl_upoly_copy(rec->p[i]));
387
0
      r = isl_qpolynomial_add(r, t);
388
0
      if (i == 0)
389
0
        break;
390
0
      q = isl_qpolynomial_mul(q, isl_qpolynomial_copy(base));
391
0
      q = isl_qpolynomial_add(q, isl_qpolynomial_copy(r));
392
0
    }
393
0
394
0
    if (isl_qpolynomial_is_zero(q))
395
0
      sgn = isl_qpolynomial_sign(set, r);
396
0
    else 
if (0
isl_qpolynomial_is_zero(r)0
)
397
0
      sgn = isl_qpolynomial_sign(set, q);
398
0
    else {
399
0
      int sgn_q, sgn_r;
400
0
      sgn_r = isl_qpolynomial_sign(set, r);
401
0
      sgn_q = isl_qpolynomial_sign(set, q);
402
0
      if (sgn_r == sgn_q)
403
0
        sgn = sgn_r;
404
0
    }
405
0
406
0
    isl_qpolynomial_free(min);
407
0
    isl_qpolynomial_free(base);
408
0
    isl_qpolynomial_free(q);
409
0
    isl_qpolynomial_free(r);
410
0
  }
411
0
412
0
  isl_int_clear(l);
413
2
414
2
  isl_vec_free(v);
415
2
416
2
  return sgn;
417
2
}
418
419
/* Combine "fold1" and "fold2" into a single reduction, eliminating
420
 * those elements of one reduction that are already covered by the other
421
 * reduction on "set".
422
 *
423
 * If "fold1" or "fold2" is an empty reduction, then return
424
 * the other reduction.
425
 * If "fold1" or "fold2" is a NaN, then return this NaN.
426
 */
427
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_fold_on_domain(
428
  __isl_keep isl_set *set,
429
  __isl_take isl_qpolynomial_fold *fold1,
430
  __isl_take isl_qpolynomial_fold *fold2)
431
3
{
432
3
  int i, j;
433
3
  int n1;
434
3
  struct isl_qpolynomial_fold *res = NULL;
435
3
  int better;
436
3
437
3
  if (
!fold1 || 3
!fold23
)
438
0
    goto error;
439
3
440
3
  
isl_assert3
(fold1->dim->ctx, fold1->type == fold2->type, goto error);
441
3
  
isl_assert3
(fold1->dim->ctx, isl_space_is_equal(fold1->dim, fold2->dim),
442
3
      goto error);
443
3
444
3
  
better = fold1->type == isl_fold_max ? 3
-13
:
10
;
445
3
446
3
  if (isl_qpolynomial_fold_is_empty(fold1) ||
447
3
      
isl_qpolynomial_fold_is_nan(fold2)3
) {
448
0
    isl_qpolynomial_fold_free(fold1);
449
0
    return fold2;
450
0
  }
451
3
452
3
  
if (3
isl_qpolynomial_fold_is_empty(fold2) ||
453
3
      
isl_qpolynomial_fold_is_nan(fold1)3
) {
454
0
    isl_qpolynomial_fold_free(fold2);
455
0
    return fold1;
456
0
  }
457
3
458
3
  res = qpolynomial_fold_alloc(fold1->type, isl_space_copy(fold1->dim),
459
3
          fold1->n + fold2->n);
460
3
  if (!res)
461
0
    goto error;
462
3
463
6
  
for (i = 0; 3
i < fold1->n6
;
++i3
) {
464
3
    res->qp[res->n] = isl_qpolynomial_copy(fold1->qp[i]);
465
3
    if (!res->qp[res->n])
466
0
      goto error;
467
3
    res->n++;
468
3
  }
469
3
  n1 = res->n;
470
3
471
6
  for (i = 0; 
i < fold2->n6
;
++i3
) {
472
4
    for (j = n1 - 1; 
j >= 04
;
--j1
) {
473
3
      isl_qpolynomial *d;
474
3
      int sgn, equal;
475
3
      equal = isl_qpolynomial_plain_is_equal(res->qp[j],
476
3
                fold2->qp[i]);
477
3
      if (equal < 0)
478
0
        goto error;
479
3
      
if (3
equal3
)
480
1
        break;
481
2
      d = isl_qpolynomial_sub(
482
2
        isl_qpolynomial_copy(res->qp[j]),
483
2
        isl_qpolynomial_copy(fold2->qp[i]));
484
2
      sgn = isl_qpolynomial_sign(set, d);
485
2
      isl_qpolynomial_free(d);
486
2
      if (sgn == 0)
487
0
        continue;
488
2
      
if (2
sgn != better2
)
489
1
        break;
490
1
      isl_qpolynomial_free(res->qp[j]);
491
1
      if (j != n1 - 1)
492
0
        res->qp[j] = res->qp[n1 - 1];
493
1
      n1--;
494
1
      if (n1 != res->n - 1)
495
0
        res->qp[n1] = res->qp[res->n - 1];
496
3
      res->n--;
497
3
    }
498
3
    
if (3
j >= 03
)
499
2
      continue;
500
1
    res->qp[res->n] = isl_qpolynomial_copy(fold2->qp[i]);
501
1
    if (!res->qp[res->n])
502
0
      goto error;
503
1
    res->n++;
504
1
  }
505
3
506
3
  isl_qpolynomial_fold_free(fold1);
507
3
  isl_qpolynomial_fold_free(fold2);
508
3
509
3
  return res;
510
0
error:
511
0
  isl_qpolynomial_fold_free(res);
512
0
  isl_qpolynomial_fold_free(fold1);
513
0
  isl_qpolynomial_fold_free(fold2);
514
0
  return NULL;
515
3
}
516
517
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_add_qpolynomial(
518
  __isl_take isl_qpolynomial_fold *fold, __isl_take isl_qpolynomial *qp)
519
0
{
520
0
  int i;
521
0
522
0
  if (
!fold || 0
!qp0
)
523
0
    goto error;
524
0
525
0
  
if (0
isl_qpolynomial_is_zero(qp)0
) {
526
0
    isl_qpolynomial_free(qp);
527
0
    return fold;
528
0
  }
529
0
530
0
  fold = isl_qpolynomial_fold_cow(fold);
531
0
  if (!fold)
532
0
    goto error;
533
0
534
0
  
for (i = 0; 0
i < fold->n0
;
++i0
) {
535
0
    fold->qp[i] = isl_qpolynomial_add(fold->qp[i],
536
0
            isl_qpolynomial_copy(qp));
537
0
    if (!fold->qp[i])
538
0
      goto error;
539
0
  }
540
0
541
0
  isl_qpolynomial_free(qp);
542
0
  return fold;
543
0
error:
544
0
  isl_qpolynomial_fold_free(fold);
545
0
  isl_qpolynomial_free(qp);
546
0
  return NULL;
547
0
}
548
549
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_add_on_domain(
550
  __isl_keep isl_set *dom,
551
  __isl_take isl_qpolynomial_fold *fold1,
552
  __isl_take isl_qpolynomial_fold *fold2)
553
0
{
554
0
  int i;
555
0
  isl_qpolynomial_fold *res = NULL;
556
0
557
0
  if (
!fold1 || 0
!fold20
)
558
0
    goto error;
559
0
560
0
  
if (0
isl_qpolynomial_fold_is_empty(fold1)0
) {
561
0
    isl_qpolynomial_fold_free(fold1);
562
0
    return fold2;
563
0
  }
564
0
565
0
  
if (0
isl_qpolynomial_fold_is_empty(fold2)0
) {
566
0
    isl_qpolynomial_fold_free(fold2);
567
0
    return fold1;
568
0
  }
569
0
570
0
  
if (0
fold1->n == 1 && 0
fold2->n != 10
)
571
0
    return isl_qpolynomial_fold_add_on_domain(dom, fold2, fold1);
572
0
573
0
  
if (0
fold2->n == 10
) {
574
0
    res = isl_qpolynomial_fold_add_qpolynomial(fold1,
575
0
          isl_qpolynomial_copy(fold2->qp[0]));
576
0
    isl_qpolynomial_fold_free(fold2);
577
0
    return res;
578
0
  }
579
0
580
0
  res = isl_qpolynomial_fold_add_qpolynomial(
581
0
        isl_qpolynomial_fold_copy(fold1),
582
0
        isl_qpolynomial_copy(fold2->qp[0]));
583
0
584
0
  for (i = 1; 
i < fold2->n0
;
++i0
) {
585
0
    isl_qpolynomial_fold *res_i;
586
0
    res_i = isl_qpolynomial_fold_add_qpolynomial(
587
0
          isl_qpolynomial_fold_copy(fold1),
588
0
          isl_qpolynomial_copy(fold2->qp[i]));
589
0
    res = isl_qpolynomial_fold_fold_on_domain(dom, res, res_i);
590
0
  }
591
0
592
0
  isl_qpolynomial_fold_free(fold1);
593
0
  isl_qpolynomial_fold_free(fold2);
594
0
  return res;
595
0
error:
596
0
  isl_qpolynomial_fold_free(res);
597
0
  isl_qpolynomial_fold_free(fold1);
598
0
  isl_qpolynomial_fold_free(fold2);
599
0
  return NULL;
600
0
}
601
602
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_substitute_equalities(
603
  __isl_take isl_qpolynomial_fold *fold, __isl_take isl_basic_set *eq)
604
0
{
605
0
  int i;
606
0
607
0
  if (
!fold || 0
!eq0
)
608
0
    goto error;
609
0
610
0
  fold = isl_qpolynomial_fold_cow(fold);
611
0
  if (!fold)
612
0
    return NULL;
613
0
614
0
  
for (i = 0; 0
i < fold->n0
;
++i0
) {
615
0
    fold->qp[i] = isl_qpolynomial_substitute_equalities(fold->qp[i],
616
0
              isl_basic_set_copy(eq));
617
0
    if (!fold->qp[i])
618
0
      goto error;
619
0
  }
620
0
621
0
  isl_basic_set_free(eq);
622
0
  return fold;
623
0
error:
624
0
  isl_basic_set_free(eq);
625
0
  isl_qpolynomial_fold_free(fold);
626
0
  return NULL;
627
0
}
628
629
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_gist(
630
  __isl_take isl_qpolynomial_fold *fold, __isl_take isl_set *context)
631
0
{
632
0
  int i;
633
0
634
0
  if (
!fold || 0
!context0
)
635
0
    goto error;
636
0
637
0
  fold = isl_qpolynomial_fold_cow(fold);
638
0
  if (!fold)
639
0
    return NULL;
640
0
641
0
  
for (i = 0; 0
i < fold->n0
;
++i0
) {
642
0
    fold->qp[i] = isl_qpolynomial_gist(fold->qp[i],
643
0
              isl_set_copy(context));
644
0
    if (!fold->qp[i])
645
0
      goto error;
646
0
  }
647
0
648
0
  isl_set_free(context);
649
0
  return fold;
650
0
error:
651
0
  isl_set_free(context);
652
0
  isl_qpolynomial_fold_free(fold);
653
0
  return NULL;
654
0
}
655
656
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_gist_params(
657
  __isl_take isl_qpolynomial_fold *fold, __isl_take isl_set *context)
658
0
{
659
0
  isl_space *space = isl_qpolynomial_fold_get_domain_space(fold);
660
0
  isl_set *dom_context = isl_set_universe(space);
661
0
  dom_context = isl_set_intersect_params(dom_context, context);
662
0
  return isl_qpolynomial_fold_gist(fold, dom_context);
663
0
}
664
665
2
#define isl_qpolynomial_fold_involves_nan isl_qpolynomial_fold_is_nan
666
667
#define HAS_TYPE
668
669
#undef PW
670
12
#define PW isl_pw_qpolynomial_fold
671
#undef EL
672
3
#define EL isl_qpolynomial_fold
673
#undef EL_IS_ZERO
674
#define EL_IS_ZERO is_empty
675
#undef ZERO
676
#define ZERO zero
677
#undef IS_ZERO
678
#define IS_ZERO is_zero
679
#undef FIELD
680
64
#define FIELD fold
681
#undef DEFAULT_IS_ZERO
682
0
#define DEFAULT_IS_ZERO 1
683
684
#define NO_NEG
685
#define NO_SUB
686
#define NO_PULLBACK
687
688
#include <isl_pw_templ.c>
689
690
#undef UNION
691
0
#define UNION isl_union_pw_qpolynomial_fold
692
#undef PART
693
0
#define PART isl_pw_qpolynomial_fold
694
#undef PARTS
695
#define PARTS pw_qpolynomial_fold
696
697
#define NO_SUB
698
699
#include <isl_union_single.c>
700
#include <isl_union_eval.c>
701
702
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_empty(enum isl_fold type,
703
  __isl_take isl_space *dim)
704
0
{
705
0
  return qpolynomial_fold_alloc(type, dim, 0);
706
0
}
707
708
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_alloc(
709
  enum isl_fold type, __isl_take isl_qpolynomial *qp)
710
15
{
711
15
  isl_qpolynomial_fold *fold;
712
15
713
15
  if (!qp)
714
0
    return NULL;
715
15
716
15
  fold = qpolynomial_fold_alloc(type, isl_space_copy(qp->dim), 1);
717
15
  if (!fold)
718
0
    goto error;
719
15
720
15
  fold->qp[0] = qp;
721
15
  fold->n++;
722
15
723
15
  return fold;
724
0
error:
725
0
  isl_qpolynomial_fold_free(fold);
726
0
  isl_qpolynomial_free(qp);
727
0
  return NULL;
728
15
}
729
730
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_copy(
731
  __isl_keep isl_qpolynomial_fold *fold)
732
22
{
733
22
  if (!fold)
734
0
    return NULL;
735
22
736
22
  fold->ref++;
737
22
  return fold;
738
22
}
739
740
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_dup(
741
  __isl_keep isl_qpolynomial_fold *fold)
742
1
{
743
1
  int i;
744
1
  isl_qpolynomial_fold *dup;
745
1
746
1
  if (!fold)
747
0
    return NULL;
748
1
  dup = qpolynomial_fold_alloc(fold->type,
749
1
          isl_space_copy(fold->dim), fold->n);
750
1
  if (!dup)
751
0
    return NULL;
752
1
  
753
1
  dup->n = fold->n;
754
2
  for (i = 0; 
i < fold->n2
;
++i1
) {
755
1
    dup->qp[i] = isl_qpolynomial_copy(fold->qp[i]);
756
1
    if (!dup->qp[i])
757
0
      goto error;
758
1
  }
759
1
760
1
  return dup;
761
0
error:
762
0
  isl_qpolynomial_fold_free(dup);
763
0
  return NULL;
764
1
}
765
766
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_cow(
767
  __isl_take isl_qpolynomial_fold *fold)
768
5
{
769
5
  if (!fold)
770
0
    return NULL;
771
5
772
5
  
if (5
fold->ref == 15
)
773
4
    return fold;
774
1
  fold->ref--;
775
1
  return isl_qpolynomial_fold_dup(fold);
776
1
}
777
778
void isl_qpolynomial_fold_free(__isl_take isl_qpolynomial_fold *fold)
779
40
{
780
40
  int i;
781
40
782
40
  if (!fold)
783
0
    return;
784
40
  
if (40
--fold->ref > 040
)
785
21
    return;
786
19
787
38
  
for (i = 0; 19
i < fold->n38
;
++i19
)
788
19
    isl_qpolynomial_free(fold->qp[i]);
789
40
  isl_space_free(fold->dim);
790
40
  free(fold);
791
40
}
792
793
int isl_qpolynomial_fold_is_empty(__isl_keep isl_qpolynomial_fold *fold)
794
24
{
795
24
  if (!fold)
796
0
    return -1;
797
24
798
24
  return fold->n == 0;
799
24
}
800
801
/* Does "fold" represent max(NaN) or min(NaN)?
802
 */
803
isl_bool isl_qpolynomial_fold_is_nan(__isl_keep isl_qpolynomial_fold *fold)
804
8
{
805
8
  if (!fold)
806
0
    return isl_bool_error;
807
8
  
if (8
fold->n != 18
)
808
0
    return isl_bool_false;
809
8
  return isl_qpolynomial_is_nan(fold->qp[0]);
810
8
}
811
812
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_fold(
813
  __isl_take isl_qpolynomial_fold *fold1,
814
  __isl_take isl_qpolynomial_fold *fold2)
815
0
{
816
0
  int i;
817
0
  struct isl_qpolynomial_fold *res = NULL;
818
0
819
0
  if (
!fold1 || 0
!fold20
)
820
0
    goto error;
821
0
822
0
  
isl_assert0
(fold1->dim->ctx, fold1->type == fold2->type, goto error);
823
0
  
isl_assert0
(fold1->dim->ctx, isl_space_is_equal(fold1->dim, fold2->dim),
824
0
      goto error);
825
0
826
0
  
if (0
isl_qpolynomial_fold_is_empty(fold1)0
) {
827
0
    isl_qpolynomial_fold_free(fold1);
828
0
    return fold2;
829
0
  }
830
0
831
0
  
if (0
isl_qpolynomial_fold_is_empty(fold2)0
) {
832
0
    isl_qpolynomial_fold_free(fold2);
833
0
    return fold1;
834
0
  }
835
0
836
0
  res = qpolynomial_fold_alloc(fold1->type, isl_space_copy(fold1->dim),
837
0
          fold1->n + fold2->n);
838
0
  if (!res)
839
0
    goto error;
840
0
841
0
  
for (i = 0; 0
i < fold1->n0
;
++i0
) {
842
0
    res->qp[res->n] = isl_qpolynomial_copy(fold1->qp[i]);
843
0
    if (!res->qp[res->n])
844
0
      goto error;
845
0
    res->n++;
846
0
  }
847
0
848
0
  
for (i = 0; 0
i < fold2->n0
;
++i0
) {
849
0
    res->qp[res->n] = isl_qpolynomial_copy(fold2->qp[i]);
850
0
    if (!res->qp[res->n])
851
0
      goto error;
852
0
    res->n++;
853
0
  }
854
0
855
0
  isl_qpolynomial_fold_free(fold1);
856
0
  isl_qpolynomial_fold_free(fold2);
857
0
858
0
  return res;
859
0
error:
860
0
  isl_qpolynomial_fold_free(res);
861
0
  isl_qpolynomial_fold_free(fold1);
862
0
  isl_qpolynomial_fold_free(fold2);
863
0
  return NULL;
864
0
}
865
866
__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_fold(
867
  __isl_take isl_pw_qpolynomial_fold *pw1,
868
  __isl_take isl_pw_qpolynomial_fold *pw2)
869
18
{
870
18
  int i, j, n;
871
18
  struct isl_pw_qpolynomial_fold *res;
872
18
  isl_set *set;
873
18
874
18
  if (
!pw1 || 18
!pw218
)
875
0
    goto error;
876
18
877
18
  
isl_assert18
(pw1->dim->ctx, isl_space_is_equal(pw1->dim, pw2->dim), goto error);
878
18
879
18
  
if (18
isl_pw_qpolynomial_fold_is_zero(pw1)18
) {
880
13
    isl_pw_qpolynomial_fold_free(pw1);
881
13
    return pw2;
882
13
  }
883
5
884
5
  
if (5
isl_pw_qpolynomial_fold_is_zero(pw2)5
) {
885
2
    isl_pw_qpolynomial_fold_free(pw2);
886
2
    return pw1;
887
2
  }
888
3
889
3
  
if (3
pw1->type != pw2->type3
)
890
0
    isl_die(pw1->dim->ctx, isl_error_invalid,
891
3
      "fold types don't match", goto error);
892
3
893
3
  n = (pw1->n + 1) * (pw2->n + 1);
894
3
  res = isl_pw_qpolynomial_fold_alloc_size(isl_space_copy(pw1->dim),
895
3
            pw1->type, n);
896
3
897
6
  for (i = 0; 
i < pw1->n6
;
++i3
) {
898
3
    set = isl_set_copy(pw1->p[i].set);
899
6
    for (j = 0; 
j < pw2->n6
;
++j3
) {
900
3
      struct isl_set *common;
901
3
      isl_qpolynomial_fold *sum;
902
3
      set = isl_set_subtract(set,
903
3
          isl_set_copy(pw2->p[j].set));
904
3
      common = isl_set_intersect(isl_set_copy(pw1->p[i].set),
905
3
            isl_set_copy(pw2->p[j].set));
906
3
      if (
isl_set_plain_is_empty(common)3
) {
907
0
        isl_set_free(common);
908
0
        continue;
909
0
      }
910
3
911
3
      sum = isl_qpolynomial_fold_fold_on_domain(common,
912
3
             isl_qpolynomial_fold_copy(pw1->p[i].fold),
913
3
             isl_qpolynomial_fold_copy(pw2->p[j].fold));
914
3
915
3
      res = isl_pw_qpolynomial_fold_add_piece(res, common, sum);
916
3
    }
917
3
    res = isl_pw_qpolynomial_fold_add_piece(res, set,
918
3
      isl_qpolynomial_fold_copy(pw1->p[i].fold));
919
3
  }
920
3
921
6
  for (j = 0; 
j < pw2->n6
;
++j3
) {
922
3
    set = isl_set_copy(pw2->p[j].set);
923
6
    for (i = 0; 
i < pw1->n6
;
++i3
)
924
3
      set = isl_set_subtract(set, isl_set_copy(pw1->p[i].set));
925
3
    res = isl_pw_qpolynomial_fold_add_piece(res, set,
926
3
            isl_qpolynomial_fold_copy(pw2->p[j].fold));
927
3
  }
928
3
929
3
  isl_pw_qpolynomial_fold_free(pw1);
930
3
  isl_pw_qpolynomial_fold_free(pw2);
931
3
932
3
  return res;
933
0
error:
934
0
  isl_pw_qpolynomial_fold_free(pw1);
935
0
  isl_pw_qpolynomial_fold_free(pw2);
936
0
  return NULL;
937
18
}
938
939
__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_fold_pw_qpolynomial_fold(
940
  __isl_take isl_union_pw_qpolynomial_fold *u,
941
  __isl_take isl_pw_qpolynomial_fold *part)
942
0
{
943
0
  struct isl_hash_table_entry *entry;
944
0
945
0
  u = isl_union_pw_qpolynomial_fold_cow(u);
946
0
947
0
  if (
!part || 0
!u0
)
948
0
    goto error;
949
0
  
if (0
isl_space_check_equal_params(part->dim, u->space) < 00
)
950
0
    goto error;
951
0
952
0
  entry = isl_union_pw_qpolynomial_fold_find_part_entry(u, part->dim, 1);
953
0
  if (!entry)
954
0
    goto error;
955
0
956
0
  
if (0
!entry->data0
)
957
0
    entry->data = part;
958
0
  else {
959
0
    entry->data = isl_pw_qpolynomial_fold_fold(entry->data,
960
0
              isl_pw_qpolynomial_fold_copy(part));
961
0
    if (!entry->data)
962
0
      goto error;
963
0
    isl_pw_qpolynomial_fold_free(part);
964
0
  }
965
0
966
0
  return u;
967
0
error:
968
0
  isl_pw_qpolynomial_fold_free(part);
969
0
  isl_union_pw_qpolynomial_fold_free(u);
970
0
  return NULL;
971
0
}
972
973
static isl_stat fold_part(__isl_take isl_pw_qpolynomial_fold *part, void *user)
974
0
{
975
0
  isl_union_pw_qpolynomial_fold **u;
976
0
  u = (isl_union_pw_qpolynomial_fold **)user;
977
0
978
0
  *u = isl_union_pw_qpolynomial_fold_fold_pw_qpolynomial_fold(*u, part);
979
0
980
0
  return isl_stat_ok;
981
0
}
982
983
__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_fold(
984
  __isl_take isl_union_pw_qpolynomial_fold *u1,
985
  __isl_take isl_union_pw_qpolynomial_fold *u2)
986
0
{
987
0
  u1 = isl_union_pw_qpolynomial_fold_cow(u1);
988
0
989
0
  if (
!u1 || 0
!u20
)
990
0
    goto error;
991
0
992
0
  
if (0
isl_union_pw_qpolynomial_fold_foreach_pw_qpolynomial_fold(u2,
993
0
              &fold_part, &u1) < 0)
994
0
    goto error;
995
0
996
0
  isl_union_pw_qpolynomial_fold_free(u2);
997
0
998
0
  return u1;
999
0
error:
1000
0
  isl_union_pw_qpolynomial_fold_free(u1);
1001
0
  isl_union_pw_qpolynomial_fold_free(u2);
1002
0
  return NULL;
1003
0
}
1004
1005
__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_from_pw_qpolynomial(
1006
  enum isl_fold type, __isl_take isl_pw_qpolynomial *pwqp)
1007
4
{
1008
4
  int i;
1009
4
  isl_pw_qpolynomial_fold *pwf;
1010
4
1011
4
  if (!pwqp)
1012
0
    return NULL;
1013
4
  
1014
4
  pwf = isl_pw_qpolynomial_fold_alloc_size(isl_space_copy(pwqp->dim),
1015
4
            type, pwqp->n);
1016
4
1017
7
  for (i = 0; 
i < pwqp->n7
;
++i3
)
1018
3
    pwf = isl_pw_qpolynomial_fold_add_piece(pwf,
1019
3
      isl_set_copy(pwqp->p[i].set),
1020
3
      isl_qpolynomial_fold_alloc(type,
1021
3
        isl_qpolynomial_copy(pwqp->p[i].qp)));
1022
4
1023
4
  isl_pw_qpolynomial_free(pwqp);
1024
4
1025
4
  return pwf;
1026
4
}
1027
1028
__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_add(
1029
  __isl_take isl_pw_qpolynomial_fold *pwf1,
1030
  __isl_take isl_pw_qpolynomial_fold *pwf2)
1031
0
{
1032
0
  return isl_pw_qpolynomial_fold_union_add_(pwf1, pwf2);
1033
0
}
1034
1035
/* Compare two quasi-polynomial reductions.
1036
 *
1037
 * Return -1 if "fold1" is "smaller" than "fold2", 1 if "fold1" is "greater"
1038
 * than "fold2" and 0 if they are equal.
1039
 */
1040
int isl_qpolynomial_fold_plain_cmp(__isl_keep isl_qpolynomial_fold *fold1,
1041
  __isl_keep isl_qpolynomial_fold *fold2)
1042
0
{
1043
0
  int i;
1044
0
1045
0
  if (fold1 == fold2)
1046
0
    return 0;
1047
0
  
if (0
!fold10
)
1048
0
    return -1;
1049
0
  
if (0
!fold20
)
1050
0
    return 1;
1051
0
1052
0
  
if (0
fold1->n != fold2->n0
)
1053
0
    return fold1->n - fold2->n;
1054
0
1055
0
  
for (i = 0; 0
i < fold1->n0
;
++i0
) {
1056
0
    int cmp;
1057
0
1058
0
    cmp = isl_qpolynomial_plain_cmp(fold1->qp[i], fold2->qp[i]);
1059
0
    if (cmp != 0)
1060
0
      return cmp;
1061
0
  }
1062
0
1063
0
  return 0;
1064
0
}
1065
1066
int isl_qpolynomial_fold_plain_is_equal(__isl_keep isl_qpolynomial_fold *fold1,
1067
  __isl_keep isl_qpolynomial_fold *fold2)
1068
1
{
1069
1
  int i;
1070
1
1071
1
  if (
!fold1 || 1
!fold21
)
1072
0
    return -1;
1073
1
1074
1
  
if (1
fold1->n != fold2->n1
)
1075
0
    return 0;
1076
1
1077
1
  /* We probably want to sort the qps first... */
1078
2
  
for (i = 0; 1
i < fold1->n2
;
++i1
) {
1079
1
    int eq = isl_qpolynomial_plain_is_equal(fold1->qp[i], fold2->qp[i]);
1080
1
    if (
eq < 0 || 1
!eq1
)
1081
0
      return eq;
1082
1
  }
1083
1
1084
1
  return 1;
1085
1
}
1086
1087
__isl_give isl_val *isl_qpolynomial_fold_eval(
1088
  __isl_take isl_qpolynomial_fold *fold, __isl_take isl_point *pnt)
1089
0
{
1090
0
  isl_ctx *ctx;
1091
0
  isl_val *v;
1092
0
1093
0
  if (
!fold || 0
!pnt0
)
1094
0
    goto error;
1095
0
  ctx = isl_point_get_ctx(pnt);
1096
0
  isl_assert(pnt->dim->ctx, isl_space_is_equal(pnt->dim, fold->dim), goto error);
1097
0
  
isl_assert0
(pnt->dim->ctx,
1098
0
    fold->type == isl_fold_max || fold->type == isl_fold_min,
1099
0
    goto error);
1100
0
1101
0
  
if (0
fold->n == 00
)
1102
0
    v = isl_val_zero(ctx);
1103
0
  else {
1104
0
    int i;
1105
0
    v = isl_qpolynomial_eval(isl_qpolynomial_copy(fold->qp[0]),
1106
0
            isl_point_copy(pnt));
1107
0
    for (i = 1; 
i < fold->n0
;
++i0
) {
1108
0
      isl_val *v_i;
1109
0
      v_i = isl_qpolynomial_eval(
1110
0
              isl_qpolynomial_copy(fold->qp[i]),
1111
0
              isl_point_copy(pnt));
1112
0
      if (fold->type == isl_fold_max)
1113
0
        v = isl_val_max(v, v_i);
1114
0
      else
1115
0
        v = isl_val_min(v, v_i);
1116
0
    }
1117
0
  }
1118
0
  isl_qpolynomial_fold_free(fold);
1119
0
  isl_point_free(pnt);
1120
0
1121
0
  return v;
1122
0
error:
1123
0
  isl_qpolynomial_fold_free(fold);
1124
0
  isl_point_free(pnt);
1125
0
  return NULL;
1126
0
}
1127
1128
size_t isl_pw_qpolynomial_fold_size(__isl_keep isl_pw_qpolynomial_fold *pwf)
1129
0
{
1130
0
  int i;
1131
0
  size_t n = 0;
1132
0
1133
0
  for (i = 0; 
i < pwf->n0
;
++i0
)
1134
0
    n += pwf->p[i].fold->n;
1135
0
1136
0
  return n;
1137
0
}
1138
1139
__isl_give isl_val *isl_qpolynomial_fold_opt_on_domain(
1140
  __isl_take isl_qpolynomial_fold *fold, __isl_take isl_set *set, int max)
1141
7
{
1142
7
  int i;
1143
7
  isl_val *opt;
1144
7
1145
7
  if (
!set || 7
!fold7
)
1146
0
    goto error;
1147
7
1148
7
  
if (7
fold->n == 07
) {
1149
0
    opt = isl_val_zero(isl_set_get_ctx(set));
1150
0
    isl_set_free(set);
1151
0
    isl_qpolynomial_fold_free(fold);
1152
0
    return opt;
1153
0
  }
1154
7
1155
7
  opt = isl_qpolynomial_opt_on_domain(isl_qpolynomial_copy(fold->qp[0]),
1156
7
            isl_set_copy(set), max);
1157
7
  for (i = 1; 
i < fold->n7
;
++i0
) {
1158
0
    isl_val *opt_i;
1159
0
    opt_i = isl_qpolynomial_opt_on_domain(
1160
0
        isl_qpolynomial_copy(fold->qp[i]),
1161
0
        isl_set_copy(set), max);
1162
0
    if (max)
1163
0
      opt = isl_val_max(opt, opt_i);
1164
0
    else
1165
0
      opt = isl_val_min(opt, opt_i);
1166
0
  }
1167
7
1168
7
  isl_set_free(set);
1169
7
  isl_qpolynomial_fold_free(fold);
1170
7
1171
7
  return opt;
1172
0
error:
1173
0
  isl_set_free(set);
1174
0
  isl_qpolynomial_fold_free(fold);
1175
0
  return NULL;
1176
7
}
1177
1178
/* Check whether for each quasi-polynomial in "fold2" there is
1179
 * a quasi-polynomial in "fold1" that dominates it on "set".
1180
 */
1181
static int qpolynomial_fold_covers_on_domain(__isl_keep isl_set *set,
1182
  __isl_keep isl_qpolynomial_fold *fold1,
1183
  __isl_keep isl_qpolynomial_fold *fold2)
1184
0
{
1185
0
  int i, j;
1186
0
  int covers;
1187
0
1188
0
  if (
!set || 0
!fold10
||
!fold20
)
1189
0
    return -1;
1190
0
1191
0
  
covers = fold1->type == isl_fold_max ? 0
10
:
-10
;
1192
0
1193
0
  for (i = 0; 
i < fold2->n0
;
++i0
) {
1194
0
    for (j = 0; 
j < fold1->n0
;
++j0
) {
1195
0
      isl_qpolynomial *d;
1196
0
      int sgn;
1197
0
1198
0
      d = isl_qpolynomial_sub(
1199
0
        isl_qpolynomial_copy(fold1->qp[j]),
1200
0
        isl_qpolynomial_copy(fold2->qp[i]));
1201
0
      sgn = isl_qpolynomial_sign(set, d);
1202
0
      isl_qpolynomial_free(d);
1203
0
      if (sgn == covers)
1204
0
        break;
1205
0
    }
1206
0
    if (j >= fold1->n)
1207
0
      return 0;
1208
0
  }
1209
0
1210
0
  return 1;
1211
0
}
1212
1213
/* Check whether "pwf1" dominated "pwf2", i.e., the domain of "pwf1" contains
1214
 * that of "pwf2" and on each cell, the corresponding fold from pwf1 dominates
1215
 * that of pwf2.
1216
 */
1217
int isl_pw_qpolynomial_fold_covers(__isl_keep isl_pw_qpolynomial_fold *pwf1,
1218
  __isl_keep isl_pw_qpolynomial_fold *pwf2)
1219
2
{
1220
2
  int i, j;
1221
2
  isl_set *dom1, *dom2;
1222
2
  int is_subset;
1223
2
1224
2
  if (
!pwf1 || 2
!pwf22
)
1225
0
    return -1;
1226
2
1227
2
  
if (2
pwf2->n == 02
)
1228
0
    return 1;
1229
2
  
if (2
pwf1->n == 02
)
1230
2
    return 0;
1231
0
1232
0
  dom1 = isl_pw_qpolynomial_fold_domain(isl_pw_qpolynomial_fold_copy(pwf1));
1233
0
  dom2 = isl_pw_qpolynomial_fold_domain(isl_pw_qpolynomial_fold_copy(pwf2));
1234
0
  is_subset = isl_set_is_subset(dom2, dom1);
1235
0
  isl_set_free(dom1);
1236
0
  isl_set_free(dom2);
1237
0
1238
0
  if (
is_subset < 0 || 0
!is_subset0
)
1239
0
    return is_subset;
1240
0
1241
0
  
for (i = 0; 0
i < pwf2->n0
;
++i0
) {
1242
0
    for (j = 0; 
j < pwf1->n0
;
++j0
) {
1243
0
      int is_empty;
1244
0
      isl_set *common;
1245
0
      int covers;
1246
0
1247
0
      common = isl_set_intersect(isl_set_copy(pwf1->p[j].set),
1248
0
               isl_set_copy(pwf2->p[i].set));
1249
0
      is_empty = isl_set_is_empty(common);
1250
0
      if (
is_empty < 0 || 0
is_empty0
) {
1251
0
        isl_set_free(common);
1252
0
        if (is_empty < 0)
1253
0
          return -1;
1254
0
        continue;
1255
0
      }
1256
0
      covers = qpolynomial_fold_covers_on_domain(common,
1257
0
          pwf1->p[j].fold, pwf2->p[i].fold);
1258
0
      isl_set_free(common);
1259
0
      if (
covers < 0 || 0
!covers0
)
1260
0
        return covers;
1261
0
    }
1262
0
  }
1263
0
1264
0
  return 1;
1265
2
}
1266
1267
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_morph_domain(
1268
  __isl_take isl_qpolynomial_fold *fold, __isl_take isl_morph *morph)
1269
1
{
1270
1
  int i;
1271
1
  isl_ctx *ctx;
1272
1
1273
1
  if (
!fold || 1
!morph1
)
1274
0
    goto error;
1275
1
1276
1
  ctx = fold->dim->ctx;
1277
1
  isl_assert(ctx, isl_space_is_equal(fold->dim, morph->dom->dim), goto error);
1278
1
1279
1
  fold = isl_qpolynomial_fold_cow(fold);
1280
1
  if (!fold)
1281
0
    goto error;
1282
1
1283
1
  isl_space_free(fold->dim);
1284
1
  fold->dim = isl_space_copy(morph->ran->dim);
1285
1
  if (!fold->dim)
1286
0
    goto error;
1287
1
1288
2
  
for (i = 0; 1
i < fold->n2
;
++i1
) {
1289
1
    fold->qp[i] = isl_qpolynomial_morph_domain(fold->qp[i],
1290
1
            isl_morph_copy(morph));
1291
1
    if (!fold->qp[i])
1292
0
      goto error;
1293
1
  }
1294
1
1295
1
  isl_morph_free(morph);
1296
1
1297
1
  return fold;
1298
0
error:
1299
0
  isl_qpolynomial_fold_free(fold);
1300
0
  isl_morph_free(morph);
1301
0
  return NULL;
1302
1
}
1303
1304
enum isl_fold isl_qpolynomial_fold_get_type(__isl_keep isl_qpolynomial_fold *fold)
1305
2
{
1306
2
  if (!fold)
1307
0
    return isl_fold_list;
1308
2
  return fold->type;
1309
2
}
1310
1311
enum isl_fold isl_union_pw_qpolynomial_fold_get_type(
1312
  __isl_keep isl_union_pw_qpolynomial_fold *upwf)
1313
0
{
1314
0
  if (!upwf)
1315
0
    return isl_fold_list;
1316
0
  return upwf->type;
1317
0
}
1318
1319
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_lift(
1320
  __isl_take isl_qpolynomial_fold *fold, __isl_take isl_space *dim)
1321
1
{
1322
1
  int i;
1323
1
1324
1
  if (
!fold || 1
!dim1
)
1325
0
    goto error;
1326
1
1327
1
  
if (1
isl_space_is_equal(fold->dim, dim)1
) {
1328
0
    isl_space_free(dim);
1329
0
    return fold;
1330
0
  }
1331
1
1332
1
  fold = isl_qpolynomial_fold_cow(fold);
1333
1
  if (!fold)
1334
0
    goto error;
1335
1
1336
1
  isl_space_free(fold->dim);
1337
1
  fold->dim = isl_space_copy(dim);
1338
1
  if (!fold->dim)
1339
0
    goto error;
1340
1
1341
2
  
for (i = 0; 1
i < fold->n2
;
++i1
) {
1342
1
    fold->qp[i] = isl_qpolynomial_lift(fold->qp[i],
1343
1
            isl_space_copy(dim));
1344
1
    if (!fold->qp[i])
1345
0
      goto error;
1346
1
  }
1347
1
1348
1
  isl_space_free(dim);
1349
1
1350
1
  return fold;
1351
0
error:
1352
0
  isl_qpolynomial_fold_free(fold);
1353
0
  isl_space_free(dim);
1354
0
  return NULL;
1355
1
}
1356
1357
isl_stat isl_qpolynomial_fold_foreach_qpolynomial(
1358
  __isl_keep isl_qpolynomial_fold *fold,
1359
  isl_stat (*fn)(__isl_take isl_qpolynomial *qp, void *user), void *user)
1360
2
{
1361
2
  int i;
1362
2
1363
2
  if (!fold)
1364
0
    return isl_stat_error;
1365
2
1366
4
  
for (i = 0; 2
i < fold->n4
;
++i2
)
1367
2
    
if (2
fn(isl_qpolynomial_copy(fold->qp[i]), user) < 02
)
1368
0
      return isl_stat_error;
1369
2
1370
2
  return isl_stat_ok;
1371
2
}
1372
1373
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_move_dims(
1374
  __isl_take isl_qpolynomial_fold *fold,
1375
  enum isl_dim_type dst_type, unsigned dst_pos,
1376
  enum isl_dim_type src_type, unsigned src_pos, unsigned n)
1377
0
{
1378
0
  int i;
1379
0
  enum isl_dim_type set_src_type, set_dst_type;
1380
0
1381
0
  if (n == 0)
1382
0
    return fold;
1383
0
1384
0
  fold = isl_qpolynomial_fold_cow(fold);
1385
0
  if (!fold)
1386
0
    return NULL;
1387
0
1388
0
  set_src_type = domain_type(src_type);
1389
0
  set_dst_type = domain_type(dst_type);
1390
0
1391
0
  fold->dim = isl_space_move_dims(fold->dim, set_dst_type, dst_pos,
1392
0
            set_src_type, src_pos, n);
1393
0
  if (!fold->dim)
1394
0
    goto error;
1395
0
1396
0
  
for (i = 0; 0
i < fold->n0
;
++i0
) {
1397
0
    fold->qp[i] = isl_qpolynomial_move_dims(fold->qp[i],
1398
0
        dst_type, dst_pos, src_type, src_pos, n);
1399
0
    if (!fold->qp[i])
1400
0
      goto error;
1401
0
  }
1402
0
1403
0
  return fold;
1404
0
error:
1405
0
  isl_qpolynomial_fold_free(fold);
1406
0
  return NULL;
1407
0
}
1408
1409
/* For each 0 <= i < "n", replace variable "first" + i of type "type"
1410
 * in fold->qp[k] by subs[i].
1411
 */
1412
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_substitute(
1413
  __isl_take isl_qpolynomial_fold *fold,
1414
  enum isl_dim_type type, unsigned first, unsigned n,
1415
  __isl_keep isl_qpolynomial **subs)
1416
0
{
1417
0
  int i;
1418
0
1419
0
  if (n == 0)
1420
0
    return fold;
1421
0
1422
0
  fold = isl_qpolynomial_fold_cow(fold);
1423
0
  if (!fold)
1424
0
    return NULL;
1425
0
1426
0
  
for (i = 0; 0
i < fold->n0
;
++i0
) {
1427
0
    fold->qp[i] = isl_qpolynomial_substitute(fold->qp[i],
1428
0
        type, first, n, subs);
1429
0
    if (!fold->qp[i])
1430
0
      goto error;
1431
0
  }
1432
0
1433
0
  return fold;
1434
0
error:
1435
0
  isl_qpolynomial_fold_free(fold);
1436
0
  return NULL;
1437
0
}
1438
1439
static isl_stat add_pwqp(__isl_take isl_pw_qpolynomial *pwqp, void *user)
1440
0
{
1441
0
  isl_pw_qpolynomial_fold *pwf;
1442
0
  isl_union_pw_qpolynomial_fold **upwf;
1443
0
  struct isl_hash_table_entry *entry;
1444
0
1445
0
  upwf = (isl_union_pw_qpolynomial_fold **)user;
1446
0
1447
0
  entry = isl_union_pw_qpolynomial_fold_find_part_entry(*upwf,
1448
0
       pwqp->dim, 1);
1449
0
  if (!entry)
1450
0
    goto error;
1451
0
1452
0
  pwf = isl_pw_qpolynomial_fold_from_pw_qpolynomial((*upwf)->type, pwqp);
1453
0
  if (!entry->data)
1454
0
    entry->data = pwf;
1455
0
  else {
1456
0
    entry->data = isl_pw_qpolynomial_fold_add(entry->data, pwf);
1457
0
    if (!entry->data)
1458
0
      return isl_stat_error;
1459
0
    
if (0
isl_pw_qpolynomial_fold_is_zero(entry->data)0
)
1460
0
      *upwf = isl_union_pw_qpolynomial_fold_remove_part_entry(
1461
0
                *upwf, entry);
1462
0
  }
1463
0
1464
0
  return isl_stat_ok;
1465
0
error:
1466
0
  isl_pw_qpolynomial_free(pwqp);
1467
0
  return isl_stat_error;
1468
0
}
1469
1470
__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial(
1471
  __isl_take isl_union_pw_qpolynomial_fold *upwf,
1472
  __isl_take isl_union_pw_qpolynomial *upwqp)
1473
0
{
1474
0
  upwf = isl_union_pw_qpolynomial_fold_align_params(upwf,
1475
0
        isl_union_pw_qpolynomial_get_space(upwqp));
1476
0
  upwqp = isl_union_pw_qpolynomial_align_params(upwqp,
1477
0
        isl_union_pw_qpolynomial_fold_get_space(upwf));
1478
0
1479
0
  upwf = isl_union_pw_qpolynomial_fold_cow(upwf);
1480
0
  if (
!upwf || 0
!upwqp0
)
1481
0
    goto error;
1482
0
1483
0
  
if (0
isl_union_pw_qpolynomial_foreach_pw_qpolynomial(upwqp, &add_pwqp,
1484
0
               &upwf) < 0)
1485
0
    goto error;
1486
0
1487
0
  isl_union_pw_qpolynomial_free(upwqp);
1488
0
1489
0
  return upwf;
1490
0
error:
1491
0
  isl_union_pw_qpolynomial_fold_free(upwf);
1492
0
  isl_union_pw_qpolynomial_free(upwqp);
1493
0
  return NULL;
1494
0
}
1495
1496
static isl_bool join_compatible(__isl_keep isl_space *space1,
1497
  __isl_keep isl_space *space2)
1498
0
{
1499
0
  isl_bool m;
1500
0
  m = isl_space_has_equal_params(space1, space2);
1501
0
  if (
m < 0 || 0
!m0
)
1502
0
    return m;
1503
0
  return isl_space_tuple_is_equal(space1, isl_dim_out,
1504
0
          space2, isl_dim_in);
1505
0
}
1506
1507
/* Compute the intersection of the range of the map and the domain
1508
 * of the piecewise quasipolynomial reduction and then compute a bound
1509
 * on the associated quasipolynomial reduction over all elements
1510
 * in this intersection.
1511
 *
1512
 * We first introduce some unconstrained dimensions in the
1513
 * piecewise quasipolynomial, intersect the resulting domain
1514
 * with the wrapped map and the compute the sum.
1515
 */
1516
__isl_give isl_pw_qpolynomial_fold *isl_map_apply_pw_qpolynomial_fold(
1517
  __isl_take isl_map *map, __isl_take isl_pw_qpolynomial_fold *pwf,
1518
  int *tight)
1519
0
{
1520
0
  isl_ctx *ctx;
1521
0
  isl_set *dom;
1522
0
  isl_space *map_dim;
1523
0
  isl_space *pwf_dim;
1524
0
  unsigned n_in;
1525
0
  isl_bool ok;
1526
0
1527
0
  ctx = isl_map_get_ctx(map);
1528
0
  if (!ctx)
1529
0
    goto error;
1530
0
1531
0
  map_dim = isl_map_get_space(map);
1532
0
  pwf_dim = isl_pw_qpolynomial_fold_get_space(pwf);
1533
0
  ok = join_compatible(map_dim, pwf_dim);
1534
0
  isl_space_free(map_dim);
1535
0
  isl_space_free(pwf_dim);
1536
0
  if (ok < 0)
1537
0
    goto error;
1538
0
  
if (0
!ok0
)
1539
0
    isl_die(ctx, isl_error_invalid, "incompatible dimensions",
1540
0
      goto error);
1541
0
1542
0
  n_in = isl_map_dim(map, isl_dim_in);
1543
0
  pwf = isl_pw_qpolynomial_fold_insert_dims(pwf, isl_dim_in, 0, n_in);
1544
0
1545
0
  dom = isl_map_wrap(map);
1546
0
  pwf = isl_pw_qpolynomial_fold_reset_domain_space(pwf,
1547
0
            isl_set_get_space(dom));
1548
0
1549
0
  pwf = isl_pw_qpolynomial_fold_intersect_domain(pwf, dom);
1550
0
  pwf = isl_pw_qpolynomial_fold_bound(pwf, tight);
1551
0
  
1552
0
  return pwf;
1553
0
error:
1554
0
  isl_map_free(map);
1555
0
  isl_pw_qpolynomial_fold_free(pwf);
1556
0
  return NULL;
1557
0
}
1558
1559
__isl_give isl_pw_qpolynomial_fold *isl_set_apply_pw_qpolynomial_fold(
1560
  __isl_take isl_set *set, __isl_take isl_pw_qpolynomial_fold *pwf,
1561
  int *tight)
1562
0
{
1563
0
  return isl_map_apply_pw_qpolynomial_fold(set, pwf, tight);
1564
0
}
1565
1566
struct isl_apply_fold_data {
1567
  isl_union_pw_qpolynomial_fold *upwf;
1568
  isl_union_pw_qpolynomial_fold *res;
1569
  isl_map *map;
1570
  int tight;
1571
};
1572
1573
static isl_stat pw_qpolynomial_fold_apply(
1574
  __isl_take isl_pw_qpolynomial_fold *pwf, void *user)
1575
0
{
1576
0
  isl_space *map_dim;
1577
0
  isl_space *pwf_dim;
1578
0
  struct isl_apply_fold_data *data = user;
1579
0
  isl_bool ok;
1580
0
1581
0
  map_dim = isl_map_get_space(data->map);
1582
0
  pwf_dim = isl_pw_qpolynomial_fold_get_space(pwf);
1583
0
  ok = join_compatible(map_dim, pwf_dim);
1584
0
  isl_space_free(map_dim);
1585
0
  isl_space_free(pwf_dim);
1586
0
1587
0
  if (ok < 0)
1588
0
    return isl_stat_error;
1589
0
  
if (0
ok0
) {
1590
0
    pwf = isl_map_apply_pw_qpolynomial_fold(isl_map_copy(data->map),
1591
0
            pwf, data->tight ? &data->tight : NULL);
1592
0
    data->res = isl_union_pw_qpolynomial_fold_fold_pw_qpolynomial_fold(
1593
0
              data->res, pwf);
1594
0
  } else
1595
0
    isl_pw_qpolynomial_fold_free(pwf);
1596
0
1597
0
  return isl_stat_ok;
1598
0
}
1599
1600
static isl_stat map_apply(__isl_take isl_map *map, void *user)
1601
0
{
1602
0
  struct isl_apply_fold_data *data = user;
1603
0
  isl_stat r;
1604
0
1605
0
  data->map = map;
1606
0
  r = isl_union_pw_qpolynomial_fold_foreach_pw_qpolynomial_fold(
1607
0
        data->upwf, &pw_qpolynomial_fold_apply, data);
1608
0
1609
0
  isl_map_free(map);
1610
0
  return r;
1611
0
}
1612
1613
__isl_give isl_union_pw_qpolynomial_fold *isl_union_map_apply_union_pw_qpolynomial_fold(
1614
  __isl_take isl_union_map *umap,
1615
  __isl_take isl_union_pw_qpolynomial_fold *upwf, int *tight)
1616
0
{
1617
0
  isl_space *dim;
1618
0
  enum isl_fold type;
1619
0
  struct isl_apply_fold_data data;
1620
0
1621
0
  upwf = isl_union_pw_qpolynomial_fold_align_params(upwf,
1622
0
        isl_union_map_get_space(umap));
1623
0
  umap = isl_union_map_align_params(umap,
1624
0
        isl_union_pw_qpolynomial_fold_get_space(upwf));
1625
0
1626
0
  data.upwf = upwf;
1627
0
  data.tight = tight ? 
10
:
00
;
1628
0
  dim = isl_union_pw_qpolynomial_fold_get_space(upwf);
1629
0
  type = isl_union_pw_qpolynomial_fold_get_type(upwf);
1630
0
  data.res = isl_union_pw_qpolynomial_fold_zero(dim, type);
1631
0
  if (isl_union_map_foreach_map(umap, &map_apply, &data) < 0)
1632
0
    goto error;
1633
0
1634
0
  isl_union_map_free(umap);
1635
0
  isl_union_pw_qpolynomial_fold_free(upwf);
1636
0
1637
0
  if (tight)
1638
0
    *tight = data.tight;
1639
0
1640
0
  return data.res;
1641
0
error:
1642
0
  isl_union_map_free(umap);
1643
0
  isl_union_pw_qpolynomial_fold_free(upwf);
1644
0
  isl_union_pw_qpolynomial_fold_free(data.res);
1645
0
  return NULL;
1646
0
}
1647
1648
__isl_give isl_union_pw_qpolynomial_fold *isl_union_set_apply_union_pw_qpolynomial_fold(
1649
  __isl_take isl_union_set *uset,
1650
  __isl_take isl_union_pw_qpolynomial_fold *upwf, int *tight)
1651
0
{
1652
0
  return isl_union_map_apply_union_pw_qpolynomial_fold(uset, upwf, tight);
1653
0
}
1654
1655
/* Reorder the dimension of "fold" according to the given reordering.
1656
 */
1657
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_realign_domain(
1658
  __isl_take isl_qpolynomial_fold *fold, __isl_take isl_reordering *r)
1659
0
{
1660
0
  int i;
1661
0
1662
0
  fold = isl_qpolynomial_fold_cow(fold);
1663
0
  if (
!fold || 0
!r0
)
1664
0
    goto error;
1665
0
1666
0
  
for (i = 0; 0
i < fold->n0
;
++i0
) {
1667
0
    fold->qp[i] = isl_qpolynomial_realign_domain(fold->qp[i],
1668
0
                isl_reordering_copy(r));
1669
0
    if (!fold->qp[i])
1670
0
      goto error;
1671
0
  }
1672
0
1673
0
  fold = isl_qpolynomial_fold_reset_domain_space(fold,
1674
0
                isl_space_copy(r->dim));
1675
0
1676
0
  isl_reordering_free(r);
1677
0
1678
0
  return fold;
1679
0
error:
1680
0
  isl_qpolynomial_fold_free(fold);
1681
0
  isl_reordering_free(r);
1682
0
  return NULL;
1683
0
}
1684
1685
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_mul_isl_int(
1686
  __isl_take isl_qpolynomial_fold *fold, isl_int v)
1687
0
{
1688
0
  int i;
1689
0
1690
0
  if (isl_int_is_one(v))
1691
0
    return fold;
1692
0
  
if (0
fold && 0
isl_int_is_zero0
(v)) {
1693
0
    isl_qpolynomial_fold *zero;
1694
0
    isl_space *dim = isl_space_copy(fold->dim);
1695
0
    zero = isl_qpolynomial_fold_empty(fold->type, dim);
1696
0
    isl_qpolynomial_fold_free(fold);
1697
0
    return zero;
1698
0
  }
1699
0
1700
0
  fold = isl_qpolynomial_fold_cow(fold);
1701
0
  if (!fold)
1702
0
    return NULL;
1703
0
1704
0
  
if (0
isl_int_is_neg0
(v))
1705
0
    fold->type = isl_fold_type_negate(fold->type);
1706
0
  for (i = 0; 
i < fold->n0
;
++i0
) {
1707
0
    fold->qp[i] = isl_qpolynomial_mul_isl_int(fold->qp[i], v);
1708
0
    if (!fold->qp[i])
1709
0
      goto error;
1710
0
  }
1711
0
1712
0
  return fold;
1713
0
error:
1714
0
  isl_qpolynomial_fold_free(fold);
1715
0
  return NULL;
1716
0
}
1717
1718
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_scale(
1719
  __isl_take isl_qpolynomial_fold *fold, isl_int v)
1720
0
{
1721
0
  return isl_qpolynomial_fold_mul_isl_int(fold, v);
1722
0
}
1723
1724
/* Multiply "fold" by "v".
1725
 */
1726
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_scale_val(
1727
  __isl_take isl_qpolynomial_fold *fold, __isl_take isl_val *v)
1728
0
{
1729
0
  int i;
1730
0
1731
0
  if (
!fold || 0
!v0
)
1732
0
    goto error;
1733
0
1734
0
  
if (0
isl_val_is_one(v)0
) {
1735
0
    isl_val_free(v);
1736
0
    return fold;
1737
0
  }
1738
0
  
if (0
isl_val_is_zero(v)0
) {
1739
0
    isl_qpolynomial_fold *zero;
1740
0
    isl_space *space = isl_qpolynomial_fold_get_domain_space(fold);
1741
0
    zero = isl_qpolynomial_fold_empty(fold->type, space);
1742
0
    isl_qpolynomial_fold_free(fold);
1743
0
    isl_val_free(v);
1744
0
    return zero;
1745
0
  }
1746
0
  
if (0
!isl_val_is_rat(v)0
)
1747
0
    isl_die(isl_qpolynomial_fold_get_ctx(fold), isl_error_invalid,
1748
0
      "expecting rational factor", goto error);
1749
0
1750
0
  fold = isl_qpolynomial_fold_cow(fold);
1751
0
  if (!fold)
1752
0
    goto error;
1753
0
1754
0
  
if (0
isl_val_is_neg(v)0
)
1755
0
    fold->type = isl_fold_type_negate(fold->type);
1756
0
  for (i = 0; 
i < fold->n0
;
++i0
) {
1757
0
    fold->qp[i] = isl_qpolynomial_scale_val(fold->qp[i],
1758
0
              isl_val_copy(v));
1759
0
    if (!fold->qp[i])
1760
0
      goto error;
1761
0
  }
1762
0
1763
0
  isl_val_free(v);
1764
0
  return fold;
1765
0
error:
1766
0
  isl_val_free(v);
1767
0
  isl_qpolynomial_fold_free(fold);
1768
0
  return NULL;
1769
0
}
1770
1771
/* Divide "fold" by "v".
1772
 */
1773
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_scale_down_val(
1774
  __isl_take isl_qpolynomial_fold *fold, __isl_take isl_val *v)
1775
0
{
1776
0
  if (
!fold || 0
!v0
)
1777
0
    goto error;
1778
0
1779
0
  
if (0
isl_val_is_one(v)0
) {
1780
0
    isl_val_free(v);
1781
0
    return fold;
1782
0
  }
1783
0
  
if (0
!isl_val_is_rat(v)0
)
1784
0
    isl_die(isl_qpolynomial_fold_get_ctx(fold), isl_error_invalid,
1785
0
      "expecting rational factor", goto error);
1786
0
  
if (0
isl_val_is_zero(v)0
)
1787
0
    isl_die(isl_val_get_ctx(v), isl_error_invalid,
1788
0
      "cannot scale down by zero", goto error);
1789
0
1790
0
  return isl_qpolynomial_fold_scale_val(fold, isl_val_inv(v));
1791
0
error:
1792
0
  isl_val_free(v);
1793
0
  isl_qpolynomial_fold_free(fold);
1794
0
  return NULL;
1795
0
}