1 /*
2 * Copyright 2010 INRIA Saclay
3 * Copyright 2013 Ecole Normale Superieure
4 * Copyright 2015 Sven Verdoolaege
5 * Copyright 2019 Cerebras Systems
6 *
7 * Use of this software is governed by the MIT license
8 *
9 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
10 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
11 * 91893 Orsay, France
12 * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
13 * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
14 */
15
16 #include <isl_map_private.h>
17 #include <isl_point_private.h>
18 #include <isl/set.h>
19 #include <isl/union_set.h>
20 #include <isl_sample.h>
21 #include <isl_scan.h>
22 #include <isl_seq.h>
23 #include <isl_space_private.h>
24 #include <isl_local_private.h>
25 #include <isl_val_private.h>
26 #include <isl_vec_private.h>
27 #include <isl_output_private.h>
28
29 #include <set_to_map.c>
30
isl_point_get_ctx(__isl_keep isl_point * pnt)31 isl_ctx *isl_point_get_ctx(__isl_keep isl_point *pnt)
32 {
33 return pnt ? isl_space_get_ctx(pnt->dim) : NULL;
34 }
35
36 /* Return the space of "pnt".
37 */
isl_point_peek_space(__isl_keep isl_point * pnt)38 __isl_keep isl_space *isl_point_peek_space(__isl_keep isl_point *pnt)
39 {
40 return pnt ? pnt->dim : NULL;
41 }
42
isl_point_get_space(__isl_keep isl_point * pnt)43 __isl_give isl_space *isl_point_get_space(__isl_keep isl_point *pnt)
44 {
45 return isl_space_copy(isl_point_peek_space(pnt));
46 }
47
48 #undef TYPE1
49 #define TYPE1 isl_basic_map
50 #undef TYPE2
51 #define TYPE2 isl_point
52 #undef TYPE_PAIR
53 #define TYPE_PAIR isl_basic_map_point
54
55 static
56 #include "isl_type_has_equal_space_templ.c"
57 static
58 #include "isl_type_check_equal_space_templ.c"
59
isl_point_alloc(__isl_take isl_space * space,__isl_take isl_vec * vec)60 __isl_give isl_point *isl_point_alloc(__isl_take isl_space *space,
61 __isl_take isl_vec *vec)
62 {
63 struct isl_point *pnt;
64 isl_size dim;
65
66 dim = isl_space_dim(space, isl_dim_all);
67 if (dim < 0 || !vec)
68 goto error;
69
70 if (vec->size > 1 + dim) {
71 vec = isl_vec_cow(vec);
72 if (!vec)
73 goto error;
74 vec->size = 1 + dim;
75 }
76
77 pnt = isl_alloc_type(space->ctx, struct isl_point);
78 if (!pnt)
79 goto error;
80
81 pnt->ref = 1;
82 pnt->dim = space;
83 pnt->vec = vec;
84
85 return pnt;
86 error:
87 isl_space_free(space);
88 isl_vec_free(vec);
89 return NULL;
90 }
91
isl_point_zero(__isl_take isl_space * space)92 __isl_give isl_point *isl_point_zero(__isl_take isl_space *space)
93 {
94 isl_vec *vec;
95 isl_size dim;
96
97 dim = isl_space_dim(space, isl_dim_all);
98 if (dim < 0)
99 goto error;
100 vec = isl_vec_alloc(space->ctx, 1 + dim);
101 if (!vec)
102 goto error;
103 isl_int_set_si(vec->el[0], 1);
104 isl_seq_clr(vec->el + 1, vec->size - 1);
105 return isl_point_alloc(space, vec);
106 error:
107 isl_space_free(space);
108 return NULL;
109 }
110
isl_point_dup(__isl_keep isl_point * pnt)111 __isl_give isl_point *isl_point_dup(__isl_keep isl_point *pnt)
112 {
113 struct isl_point *pnt2;
114
115 if (!pnt)
116 return NULL;
117 pnt2 = isl_point_alloc(isl_space_copy(pnt->dim), isl_vec_copy(pnt->vec));
118 return pnt2;
119 }
120
isl_point_cow(__isl_take isl_point * pnt)121 __isl_give isl_point *isl_point_cow(__isl_take isl_point *pnt)
122 {
123 struct isl_point *pnt2;
124 if (!pnt)
125 return NULL;
126
127 if (pnt->ref == 1)
128 return pnt;
129
130 pnt2 = isl_point_dup(pnt);
131 isl_point_free(pnt);
132 return pnt2;
133 }
134
isl_point_copy(__isl_keep isl_point * pnt)135 __isl_give isl_point *isl_point_copy(__isl_keep isl_point *pnt)
136 {
137 if (!pnt)
138 return NULL;
139
140 pnt->ref++;
141 return pnt;
142 }
143
isl_point_free(__isl_take isl_point * pnt)144 __isl_null isl_point *isl_point_free(__isl_take isl_point *pnt)
145 {
146 if (!pnt)
147 return NULL;
148
149 if (--pnt->ref > 0)
150 return NULL;
151
152 isl_space_free(pnt->dim);
153 isl_vec_free(pnt->vec);
154 free(pnt);
155 return NULL;
156 }
157
isl_point_void(__isl_take isl_space * space)158 __isl_give isl_point *isl_point_void(__isl_take isl_space *space)
159 {
160 if (!space)
161 return NULL;
162
163 return isl_point_alloc(space, isl_vec_alloc(space->ctx, 0));
164 }
165
isl_point_is_void(__isl_keep isl_point * pnt)166 isl_bool isl_point_is_void(__isl_keep isl_point *pnt)
167 {
168 if (!pnt)
169 return isl_bool_error;
170
171 return isl_bool_ok(pnt->vec->size == 0);
172 }
173
174 /* Return the space of "pnt".
175 * This may be either a copy or the space itself
176 * if there is only one reference to "pnt".
177 * This allows the space to be modified inplace
178 * if both the point and its space have only a single reference.
179 * The caller is not allowed to modify "pnt" between this call and
180 * a subsequent call to isl_point_restore_space.
181 * The only exception is that isl_point_free can be called instead.
182 */
isl_point_take_space(__isl_keep isl_point * pnt)183 __isl_give isl_space *isl_point_take_space(__isl_keep isl_point *pnt)
184 {
185 isl_space *space;
186
187 if (!pnt)
188 return NULL;
189 if (pnt->ref != 1)
190 return isl_point_get_space(pnt);
191 space = pnt->dim;
192 pnt->dim = NULL;
193 return space;
194 }
195
196 /* Set the space of "pnt" to "space", where the space of "pnt" may be missing
197 * due to a preceding call to isl_point_take_space.
198 * However, in this case, "pnt" only has a single reference and
199 * then the call to isl_point_cow has no effect.
200 */
isl_point_restore_space(__isl_take isl_point * pnt,__isl_take isl_space * space)201 __isl_give isl_point *isl_point_restore_space(__isl_take isl_point *pnt,
202 __isl_take isl_space *space)
203 {
204 if (!pnt || !space)
205 goto error;
206
207 if (pnt->dim == space) {
208 isl_space_free(space);
209 return pnt;
210 }
211
212 pnt = isl_point_cow(pnt);
213 if (!pnt)
214 goto error;
215 isl_space_free(pnt->dim);
216 pnt->dim = space;
217
218 return pnt;
219 error:
220 isl_point_free(pnt);
221 isl_space_free(space);
222 return NULL;
223 }
224
225 /* Return the coordinate vector of "pnt".
226 */
isl_point_peek_vec(__isl_keep isl_point * pnt)227 __isl_keep isl_vec *isl_point_peek_vec(__isl_keep isl_point *pnt)
228 {
229 return pnt ? pnt->vec : NULL;
230 }
231
232 /* Return a copy of the coordinate vector of "pnt".
233 */
isl_point_get_vec(__isl_keep isl_point * pnt)234 __isl_give isl_vec *isl_point_get_vec(__isl_keep isl_point *pnt)
235 {
236 return isl_vec_copy(isl_point_peek_vec(pnt));
237 }
238
239 /* Return the coordinate vector of "pnt".
240 * This may be either a copy or the coordinate vector itself
241 * if there is only one reference to "pnt".
242 * This allows the coordinate vector to be modified inplace
243 * if both the point and its coordinate vector have only a single reference.
244 * The caller is not allowed to modify "pnt" between this call and
245 * a subsequent call to isl_point_restore_vec.
246 * The only exception is that isl_point_free can be called instead.
247 */
isl_point_take_vec(__isl_keep isl_point * pnt)248 __isl_give isl_vec *isl_point_take_vec(__isl_keep isl_point *pnt)
249 {
250 isl_vec *vec;
251
252 if (!pnt)
253 return NULL;
254 if (pnt->ref != 1)
255 return isl_point_get_vec(pnt);
256 vec = pnt->vec;
257 pnt->vec = NULL;
258 return vec;
259 }
260
261 /* Set the coordinate vector of "pnt" to "vec",
262 * where the coordinate vector of "pnt" may be missing
263 * due to a preceding call to isl_point_take_vec.
264 * However, in this case, "pnt" only has a single reference and
265 * then the call to isl_point_cow has no effect.
266 */
isl_point_restore_vec(__isl_take isl_point * pnt,__isl_take isl_vec * vec)267 __isl_give isl_point *isl_point_restore_vec(__isl_take isl_point *pnt,
268 __isl_take isl_vec *vec)
269 {
270 if (!pnt || !vec)
271 goto error;
272
273 if (pnt->vec == vec) {
274 isl_vec_free(vec);
275 return pnt;
276 }
277
278 pnt = isl_point_cow(pnt);
279 if (!pnt)
280 goto error;
281 isl_vec_free(pnt->vec);
282 pnt->vec = vec;
283
284 return pnt;
285 error:
286 isl_point_free(pnt);
287 isl_vec_free(vec);
288 return NULL;
289 }
290
291 /* Return the number of variables of the given type.
292 */
isl_point_dim(__isl_keep isl_point * pnt,enum isl_dim_type type)293 static isl_size isl_point_dim(__isl_keep isl_point *pnt, enum isl_dim_type type)
294 {
295 return isl_space_dim(isl_point_peek_space(pnt), type);
296 }
297
298 /* Return the position of the coordinates of the given type
299 * within the sequence of coordinates of "pnt".
300 */
isl_point_var_offset(__isl_keep isl_point * pnt,enum isl_dim_type type)301 static isl_size isl_point_var_offset(__isl_keep isl_point *pnt,
302 enum isl_dim_type type)
303 {
304 return pnt ? isl_space_offset(pnt->dim, type) : isl_size_error;
305 }
306
307 #undef TYPE
308 #define TYPE isl_point
309 static
310 #include "check_type_range_templ.c"
311
312 /* Return the value of coordinate "pos" of type "type" of "pnt".
313 */
isl_point_get_coordinate_val(__isl_keep isl_point * pnt,enum isl_dim_type type,int pos)314 __isl_give isl_val *isl_point_get_coordinate_val(__isl_keep isl_point *pnt,
315 enum isl_dim_type type, int pos)
316 {
317 isl_ctx *ctx;
318 isl_val *v;
319 isl_size off;
320
321 if (!pnt)
322 return NULL;
323
324 ctx = isl_point_get_ctx(pnt);
325 if (isl_point_is_void(pnt))
326 isl_die(ctx, isl_error_invalid,
327 "void point does not have coordinates", return NULL);
328 if (isl_point_check_range(pnt, type, pos, 1) < 0)
329 return NULL;
330
331 off = isl_point_var_offset(pnt, type);
332 if (off < 0)
333 return NULL;
334 pos += off;
335
336 v = isl_val_rat_from_isl_int(ctx, pnt->vec->el[1 + pos],
337 pnt->vec->el[0]);
338 return isl_val_normalize(v);
339 }
340
341 /* Set all entries of "mv" to NaN.
342 */
set_nan(__isl_take isl_multi_val * mv)343 static __isl_give isl_multi_val *set_nan(__isl_take isl_multi_val *mv)
344 {
345 int i;
346 isl_size n;
347 isl_val *v;
348
349 n = isl_multi_val_size(mv);
350 if (n < 0)
351 return isl_multi_val_free(mv);
352 v = isl_val_nan(isl_multi_val_get_ctx(mv));
353 for (i = 0; i < n; ++i)
354 mv = isl_multi_val_set_at(mv, i, isl_val_copy(v));
355 isl_val_free(v);
356
357 return mv;
358 }
359
360 /* Return the values of the set dimensions of "pnt".
361 * Return a sequence of NaNs in case of a void point.
362 */
isl_point_get_multi_val(__isl_keep isl_point * pnt)363 __isl_give isl_multi_val *isl_point_get_multi_val(__isl_keep isl_point *pnt)
364 {
365 int i;
366 isl_bool is_void;
367 isl_size n;
368 isl_multi_val *mv;
369
370 is_void = isl_point_is_void(pnt);
371 if (is_void < 0)
372 return NULL;
373
374 mv = isl_multi_val_alloc(isl_point_get_space(pnt));
375 if (is_void)
376 return set_nan(mv);
377 n = isl_multi_val_size(mv);
378 if (n < 0)
379 return isl_multi_val_free(mv);
380 for (i = 0; i < n; ++i) {
381 isl_val *v;
382
383 v = isl_point_get_coordinate_val(pnt, isl_dim_set, i);
384 mv = isl_multi_val_set_at(mv, i, v);
385 }
386
387 return mv;
388 }
389
390 /* Replace coordinate "pos" of type "type" of "pnt" by "v".
391 */
isl_point_set_coordinate_val(__isl_take isl_point * pnt,enum isl_dim_type type,int pos,__isl_take isl_val * v)392 __isl_give isl_point *isl_point_set_coordinate_val(__isl_take isl_point *pnt,
393 enum isl_dim_type type, int pos, __isl_take isl_val *v)
394 {
395 if (!pnt || !v)
396 goto error;
397 if (isl_point_is_void(pnt))
398 isl_die(isl_point_get_ctx(pnt), isl_error_invalid,
399 "void point does not have coordinates", goto error);
400 if (isl_point_check_range(pnt, type, pos, 1) < 0)
401 goto error;
402 if (!isl_val_is_rat(v))
403 isl_die(isl_point_get_ctx(pnt), isl_error_invalid,
404 "expecting rational value", goto error);
405
406 pos += isl_space_offset(isl_point_peek_space(pnt), type);
407 if (isl_int_eq(pnt->vec->el[1 + pos], v->n) &&
408 isl_int_eq(pnt->vec->el[0], v->d)) {
409 isl_val_free(v);
410 return pnt;
411 }
412
413 pnt = isl_point_cow(pnt);
414 if (!pnt)
415 goto error;
416 pnt->vec = isl_vec_cow(pnt->vec);
417 if (!pnt->vec)
418 goto error;
419
420 if (isl_int_eq(pnt->vec->el[0], v->d)) {
421 isl_int_set(pnt->vec->el[1 + pos], v->n);
422 } else if (isl_int_is_one(v->d)) {
423 isl_int_mul(pnt->vec->el[1 + pos], pnt->vec->el[0], v->n);
424 } else {
425 isl_seq_scale(pnt->vec->el + 1,
426 pnt->vec->el + 1, v->d, pnt->vec->size - 1);
427 isl_int_mul(pnt->vec->el[1 + pos], pnt->vec->el[0], v->n);
428 isl_int_mul(pnt->vec->el[0], pnt->vec->el[0], v->d);
429 pnt->vec = isl_vec_normalize(pnt->vec);
430 if (!pnt->vec)
431 goto error;
432 }
433
434 isl_val_free(v);
435 return pnt;
436 error:
437 isl_val_free(v);
438 isl_point_free(pnt);
439 return NULL;
440 }
441
isl_point_add_ui(__isl_take isl_point * pnt,enum isl_dim_type type,int pos,unsigned val)442 __isl_give isl_point *isl_point_add_ui(__isl_take isl_point *pnt,
443 enum isl_dim_type type, int pos, unsigned val)
444 {
445 isl_size off;
446
447 if (!pnt || isl_point_is_void(pnt))
448 return pnt;
449
450 pnt = isl_point_cow(pnt);
451 if (!pnt)
452 return NULL;
453 pnt->vec = isl_vec_cow(pnt->vec);
454 if (!pnt->vec)
455 goto error;
456
457 off = isl_point_var_offset(pnt, type);
458 if (off < 0)
459 goto error;
460 pos += off;
461
462 isl_int_add_ui(pnt->vec->el[1 + pos], pnt->vec->el[1 + pos], val);
463
464 return pnt;
465 error:
466 isl_point_free(pnt);
467 return NULL;
468 }
469
isl_point_sub_ui(__isl_take isl_point * pnt,enum isl_dim_type type,int pos,unsigned val)470 __isl_give isl_point *isl_point_sub_ui(__isl_take isl_point *pnt,
471 enum isl_dim_type type, int pos, unsigned val)
472 {
473 isl_size off;
474
475 if (!pnt || isl_point_is_void(pnt))
476 return pnt;
477
478 pnt = isl_point_cow(pnt);
479 if (!pnt)
480 return NULL;
481 pnt->vec = isl_vec_cow(pnt->vec);
482 if (!pnt->vec)
483 goto error;
484
485 off = isl_point_var_offset(pnt, type);
486 if (off < 0)
487 goto error;
488 pos += off;
489
490 isl_int_sub_ui(pnt->vec->el[1 + pos], pnt->vec->el[1 + pos], val);
491
492 return pnt;
493 error:
494 isl_point_free(pnt);
495 return NULL;
496 }
497
498 struct isl_foreach_point {
499 struct isl_scan_callback callback;
500 isl_stat (*fn)(__isl_take isl_point *pnt, void *user);
501 void *user;
502 isl_space *dim;
503 };
504
foreach_point(struct isl_scan_callback * cb,__isl_take isl_vec * sample)505 static isl_stat foreach_point(struct isl_scan_callback *cb,
506 __isl_take isl_vec *sample)
507 {
508 struct isl_foreach_point *fp = (struct isl_foreach_point *)cb;
509 isl_point *pnt;
510
511 pnt = isl_point_alloc(isl_space_copy(fp->dim), sample);
512
513 return fp->fn(pnt, fp->user);
514 }
515
isl_set_foreach_point(__isl_keep isl_set * set,isl_stat (* fn)(__isl_take isl_point * pnt,void * user),void * user)516 isl_stat isl_set_foreach_point(__isl_keep isl_set *set,
517 isl_stat (*fn)(__isl_take isl_point *pnt, void *user), void *user)
518 {
519 struct isl_foreach_point fp = { { &foreach_point }, fn, user };
520 int i;
521
522 if (!set)
523 return isl_stat_error;
524
525 fp.dim = isl_set_get_space(set);
526 if (!fp.dim)
527 return isl_stat_error;
528
529 set = isl_set_copy(set);
530 set = isl_set_cow(set);
531 set = isl_set_make_disjoint(set);
532 set = isl_set_compute_divs(set);
533 if (!set)
534 goto error;
535
536 for (i = 0; i < set->n; ++i)
537 if (isl_basic_set_scan(isl_basic_set_copy(set->p[i]),
538 &fp.callback) < 0)
539 goto error;
540
541 isl_set_free(set);
542 isl_space_free(fp.dim);
543
544 return isl_stat_ok;
545 error:
546 isl_set_free(set);
547 isl_space_free(fp.dim);
548 return isl_stat_error;
549 }
550
551 /* Return 1 if "bmap" contains the point "point".
552 * "bmap" is assumed to have known divs.
553 * The point is first extended with the divs and then passed
554 * to basic_map_contains.
555 */
isl_basic_map_contains_point(__isl_keep isl_basic_map * bmap,__isl_keep isl_point * point)556 isl_bool isl_basic_map_contains_point(__isl_keep isl_basic_map *bmap,
557 __isl_keep isl_point *point)
558 {
559 isl_local *local;
560 isl_vec *vec;
561 isl_bool contains;
562
563 if (isl_basic_map_point_check_equal_space(bmap, point) < 0)
564 return isl_bool_error;
565 if (bmap->n_div == 0)
566 return isl_basic_map_contains(bmap, point->vec);
567
568 local = isl_local_alloc_from_mat(isl_basic_map_get_divs(bmap));
569 vec = isl_point_get_vec(point);
570 vec = isl_local_extend_point_vec(local, vec);
571 isl_local_free(local);
572
573 contains = isl_basic_map_contains(bmap, vec);
574
575 isl_vec_free(vec);
576 return contains;
577 }
578
isl_map_contains_point(__isl_keep isl_map * map,__isl_keep isl_point * point)579 isl_bool isl_map_contains_point(__isl_keep isl_map *map,
580 __isl_keep isl_point *point)
581 {
582 int i;
583 isl_bool found = isl_bool_false;
584
585 if (!map || !point)
586 return isl_bool_error;
587
588 map = isl_map_copy(map);
589 map = isl_map_compute_divs(map);
590 if (!map)
591 return isl_bool_error;
592
593 for (i = 0; i < map->n; ++i) {
594 found = isl_basic_map_contains_point(map->p[i], point);
595 if (found < 0)
596 goto error;
597 if (found)
598 break;
599 }
600 isl_map_free(map);
601
602 return found;
603 error:
604 isl_map_free(map);
605 return isl_bool_error;
606 }
607
isl_set_contains_point(__isl_keep isl_set * set,__isl_keep isl_point * point)608 isl_bool isl_set_contains_point(__isl_keep isl_set *set,
609 __isl_keep isl_point *point)
610 {
611 return isl_map_contains_point(set_to_map(set), point);
612 }
613
isl_basic_set_from_point(__isl_take isl_point * pnt)614 __isl_give isl_basic_set *isl_basic_set_from_point(__isl_take isl_point *pnt)
615 {
616 isl_basic_set *bset;
617 isl_basic_set *model;
618
619 if (!pnt)
620 return NULL;
621
622 model = isl_basic_set_empty(isl_space_copy(pnt->dim));
623 bset = isl_basic_set_from_vec(isl_vec_copy(pnt->vec));
624 bset = isl_basic_set_from_underlying_set(bset, model);
625 isl_point_free(pnt);
626
627 return bset;
628 }
629
isl_set_from_point(__isl_take isl_point * pnt)630 __isl_give isl_set *isl_set_from_point(__isl_take isl_point *pnt)
631 {
632 isl_basic_set *bset;
633 bset = isl_basic_set_from_point(pnt);
634 return isl_set_from_basic_set(bset);
635 }
636
637 /* Construct a union set, containing the single element "pnt".
638 * If "pnt" is void, then return an empty union set.
639 */
isl_union_set_from_point(__isl_take isl_point * pnt)640 __isl_give isl_union_set *isl_union_set_from_point(__isl_take isl_point *pnt)
641 {
642 if (!pnt)
643 return NULL;
644 if (isl_point_is_void(pnt)) {
645 isl_space *space;
646
647 space = isl_point_get_space(pnt);
648 isl_point_free(pnt);
649 return isl_union_set_empty(space);
650 }
651
652 return isl_union_set_from_set(isl_set_from_point(pnt));
653 }
654
isl_basic_set_box_from_points(__isl_take isl_point * pnt1,__isl_take isl_point * pnt2)655 __isl_give isl_basic_set *isl_basic_set_box_from_points(
656 __isl_take isl_point *pnt1, __isl_take isl_point *pnt2)
657 {
658 isl_basic_set *bset = NULL;
659 isl_size total;
660 int i;
661 int k;
662 isl_int t;
663
664 isl_int_init(t);
665
666 if (!pnt1 || !pnt2)
667 goto error;
668
669 isl_assert(pnt1->dim->ctx,
670 isl_space_is_equal(pnt1->dim, pnt2->dim), goto error);
671
672 if (isl_point_is_void(pnt1) && isl_point_is_void(pnt2)) {
673 isl_space *space = isl_space_copy(pnt1->dim);
674 isl_point_free(pnt1);
675 isl_point_free(pnt2);
676 isl_int_clear(t);
677 return isl_basic_set_empty(space);
678 }
679 if (isl_point_is_void(pnt1)) {
680 isl_point_free(pnt1);
681 isl_int_clear(t);
682 return isl_basic_set_from_point(pnt2);
683 }
684 if (isl_point_is_void(pnt2)) {
685 isl_point_free(pnt2);
686 isl_int_clear(t);
687 return isl_basic_set_from_point(pnt1);
688 }
689
690 total = isl_point_dim(pnt1, isl_dim_all);
691 if (total < 0)
692 goto error;
693 bset = isl_basic_set_alloc_space(isl_space_copy(pnt1->dim), 0, 0, 2 * total);
694
695 for (i = 0; i < total; ++i) {
696 isl_int_mul(t, pnt1->vec->el[1 + i], pnt2->vec->el[0]);
697 isl_int_submul(t, pnt2->vec->el[1 + i], pnt1->vec->el[0]);
698
699 k = isl_basic_set_alloc_inequality(bset);
700 if (k < 0)
701 goto error;
702 isl_seq_clr(bset->ineq[k] + 1, total);
703 if (isl_int_is_pos(t)) {
704 isl_int_set_si(bset->ineq[k][1 + i], -1);
705 isl_int_set(bset->ineq[k][0], pnt1->vec->el[1 + i]);
706 } else {
707 isl_int_set_si(bset->ineq[k][1 + i], 1);
708 isl_int_neg(bset->ineq[k][0], pnt1->vec->el[1 + i]);
709 }
710 isl_int_fdiv_q(bset->ineq[k][0], bset->ineq[k][0], pnt1->vec->el[0]);
711
712 k = isl_basic_set_alloc_inequality(bset);
713 if (k < 0)
714 goto error;
715 isl_seq_clr(bset->ineq[k] + 1, total);
716 if (isl_int_is_pos(t)) {
717 isl_int_set_si(bset->ineq[k][1 + i], 1);
718 isl_int_neg(bset->ineq[k][0], pnt2->vec->el[1 + i]);
719 } else {
720 isl_int_set_si(bset->ineq[k][1 + i], -1);
721 isl_int_set(bset->ineq[k][0], pnt2->vec->el[1 + i]);
722 }
723 isl_int_fdiv_q(bset->ineq[k][0], bset->ineq[k][0], pnt2->vec->el[0]);
724 }
725
726 bset = isl_basic_set_finalize(bset);
727
728 isl_point_free(pnt1);
729 isl_point_free(pnt2);
730
731 isl_int_clear(t);
732
733 return bset;
734 error:
735 isl_point_free(pnt1);
736 isl_point_free(pnt2);
737 isl_int_clear(t);
738 isl_basic_set_free(bset);
739 return NULL;
740 }
741
isl_set_box_from_points(__isl_take isl_point * pnt1,__isl_take isl_point * pnt2)742 __isl_give isl_set *isl_set_box_from_points(__isl_take isl_point *pnt1,
743 __isl_take isl_point *pnt2)
744 {
745 isl_basic_set *bset;
746 bset = isl_basic_set_box_from_points(pnt1, pnt2);
747 return isl_set_from_basic_set(bset);
748 }
749
750 /* Print the coordinate at position "pos" of the point "pnt".
751 */
print_coordinate(__isl_take isl_printer * p,struct isl_print_space_data * data,unsigned pos)752 static __isl_give isl_printer *print_coordinate(__isl_take isl_printer *p,
753 struct isl_print_space_data *data, unsigned pos)
754 {
755 isl_point *pnt = data->user;
756
757 pos += isl_space_offset(data->space, data->type);
758 p = isl_printer_print_isl_int(p, pnt->vec->el[1 + pos]);
759 if (!isl_int_is_one(pnt->vec->el[0])) {
760 p = isl_printer_print_str(p, "/");
761 p = isl_printer_print_isl_int(p, pnt->vec->el[0]);
762 }
763
764 return p;
765 }
766
isl_printer_print_point(__isl_take isl_printer * p,__isl_keep isl_point * pnt)767 __isl_give isl_printer *isl_printer_print_point(
768 __isl_take isl_printer *p, __isl_keep isl_point *pnt)
769 {
770 struct isl_print_space_data data = { 0 };
771 int i;
772 isl_size nparam;
773
774 if (!pnt)
775 return p;
776 if (isl_point_is_void(pnt)) {
777 p = isl_printer_print_str(p, "void");
778 return p;
779 }
780
781 nparam = isl_point_dim(pnt, isl_dim_param);
782 if (nparam < 0)
783 return isl_printer_free(p);
784 if (nparam > 0) {
785 p = isl_printer_print_str(p, "[");
786 for (i = 0; i < nparam; ++i) {
787 const char *name;
788 if (i)
789 p = isl_printer_print_str(p, ", ");
790 name = isl_space_get_dim_name(pnt->dim, isl_dim_param, i);
791 if (name) {
792 p = isl_printer_print_str(p, name);
793 p = isl_printer_print_str(p, " = ");
794 }
795 p = isl_printer_print_isl_int(p, pnt->vec->el[1 + i]);
796 if (!isl_int_is_one(pnt->vec->el[0])) {
797 p = isl_printer_print_str(p, "/");
798 p = isl_printer_print_isl_int(p, pnt->vec->el[0]);
799 }
800 }
801 p = isl_printer_print_str(p, "]");
802 p = isl_printer_print_str(p, " -> ");
803 }
804 data.print_dim = &print_coordinate;
805 data.user = pnt;
806 p = isl_printer_print_str(p, "{ ");
807 p = isl_print_space(pnt->dim, p, 0, &data);
808 p = isl_printer_print_str(p, " }");
809 return p;
810 }
811