1 #include <isl_map_private.h>
2 #include <isl_point_private.h>
4 #include <isl/union_set.h>
5 #include <isl_sample.h>
8 #include <isl_space_private.h>
9 #include <isl_local_private.h>
10 #include <isl_val_private.h>
11 #include <isl_vec_private.h>
12 #include <isl_output_private.h>
14 #include <set_to_map.c>
16 isl_ctx
*isl_point_get_ctx(__isl_keep isl_point
*pnt
)
18 return pnt
? isl_space_get_ctx(pnt
->dim
) : NULL
;
21 /* Return the space of "pnt".
23 __isl_keep isl_space
*isl_point_peek_space(__isl_keep isl_point
*pnt
)
25 return pnt
? pnt
->dim
: NULL
;
28 __isl_give isl_space
*isl_point_get_space(__isl_keep isl_point
*pnt
)
30 return isl_space_copy(isl_point_peek_space(pnt
));
33 __isl_give isl_point
*isl_point_alloc(__isl_take isl_space
*space
,
34 __isl_take isl_vec
*vec
)
36 struct isl_point
*pnt
;
39 dim
= isl_space_dim(space
, isl_dim_all
);
43 if (vec
->size
> 1 + dim
) {
44 vec
= isl_vec_cow(vec
);
50 pnt
= isl_alloc_type(space
->ctx
, struct isl_point
);
60 isl_space_free(space
);
65 __isl_give isl_point
*isl_point_zero(__isl_take isl_space
*space
)
70 dim
= isl_space_dim(space
, isl_dim_all
);
73 vec
= isl_vec_alloc(space
->ctx
, 1 + dim
);
76 isl_int_set_si(vec
->el
[0], 1);
77 isl_seq_clr(vec
->el
+ 1, vec
->size
- 1);
78 return isl_point_alloc(space
, vec
);
80 isl_space_free(space
);
84 __isl_give isl_point
*isl_point_dup(__isl_keep isl_point
*pnt
)
86 struct isl_point
*pnt2
;
90 pnt2
= isl_point_alloc(isl_space_copy(pnt
->dim
), isl_vec_copy(pnt
->vec
));
94 __isl_give isl_point
*isl_point_cow(__isl_take isl_point
*pnt
)
96 struct isl_point
*pnt2
;
103 pnt2
= isl_point_dup(pnt
);
108 __isl_give isl_point
*isl_point_copy(__isl_keep isl_point
*pnt
)
117 __isl_null isl_point
*isl_point_free(__isl_take isl_point
*pnt
)
125 isl_space_free(pnt
->dim
);
126 isl_vec_free(pnt
->vec
);
131 __isl_give isl_point
*isl_point_void(__isl_take isl_space
*space
)
136 return isl_point_alloc(space
, isl_vec_alloc(space
->ctx
, 0));
139 isl_bool
isl_point_is_void(__isl_keep isl_point
*pnt
)
142 return isl_bool_error
;
144 return isl_bool_ok(pnt
->vec
->size
== 0);
147 /* Return the space of "pnt".
148 * This may be either a copy or the space itself
149 * if there is only one reference to "pnt".
150 * This allows the space to be modified inplace
151 * if both the point and its space have only a single reference.
152 * The caller is not allowed to modify "pnt" between this call and
153 * a subsequent call to isl_point_restore_space.
154 * The only exception is that isl_point_free can be called instead.
156 __isl_give isl_space
*isl_point_take_space(__isl_keep isl_point
*pnt
)
163 return isl_point_get_space(pnt
);
169 /* Set the space of "pnt" to "space", where the space of "pnt" may be missing
170 * due to a preceding call to isl_point_take_space.
171 * However, in this case, "pnt" only has a single reference and
172 * then the call to isl_point_cow has no effect.
174 __isl_give isl_point
*isl_point_restore_space(__isl_take isl_point
*pnt
,
175 __isl_take isl_space
*space
)
180 if (pnt
->dim
== space
) {
181 isl_space_free(space
);
185 pnt
= isl_point_cow(pnt
);
188 isl_space_free(pnt
->dim
);
194 isl_space_free(space
);
198 /* Return the coordinate vector of "pnt".
200 __isl_keep isl_vec
*isl_point_peek_vec(__isl_keep isl_point
*pnt
)
202 return pnt
? pnt
->vec
: NULL
;
205 /* Return a copy of the coordinate vector of "pnt".
207 __isl_give isl_vec
*isl_point_get_vec(__isl_keep isl_point
*pnt
)
209 return isl_vec_copy(isl_point_peek_vec(pnt
));
212 /* Return the coordinate vector of "pnt".
213 * This may be either a copy or the coordinate vector itself
214 * if there is only one reference to "pnt".
215 * This allows the coordinate vector to be modified inplace
216 * if both the point and its coordinate vector have only a single reference.
217 * The caller is not allowed to modify "pnt" between this call and
218 * a subsequent call to isl_point_restore_vec.
219 * The only exception is that isl_point_free can be called instead.
221 __isl_give isl_vec
*isl_point_take_vec(__isl_keep isl_point
*pnt
)
228 return isl_point_get_vec(pnt
);
234 /* Set the coordinate vector of "pnt" to "vec",
235 * where the coordinate vector of "pnt" may be missing
236 * due to a preceding call to isl_point_take_vec.
237 * However, in this case, "pnt" only has a single reference and
238 * then the call to isl_point_cow has no effect.
240 __isl_give isl_point
*isl_point_restore_vec(__isl_take isl_point
*pnt
,
241 __isl_take isl_vec
*vec
)
246 if (pnt
->vec
== vec
) {
251 pnt
= isl_point_cow(pnt
);
254 isl_vec_free(pnt
->vec
);
264 /* Return the number of variables of the given type.
266 static isl_size
isl_point_dim(__isl_keep isl_point
*pnt
, enum isl_dim_type type
)
268 return isl_space_dim(isl_point_peek_space(pnt
), type
);
271 /* Return the position of the coordinates of the given type
272 * within the sequence of coordinates of "pnt".
274 static isl_size
isl_point_var_offset(__isl_keep isl_point
*pnt
,
275 enum isl_dim_type type
)
277 return pnt
? isl_space_offset(pnt
->dim
, type
) : isl_size_error
;
281 #define TYPE isl_point
283 #include "check_type_range_templ.c"
285 /* Return the value of coordinate "pos" of type "type" of "pnt".
287 __isl_give isl_val
*isl_point_get_coordinate_val(__isl_keep isl_point
*pnt
,
288 enum isl_dim_type type
, int pos
)
297 ctx
= isl_point_get_ctx(pnt
);
298 if (isl_point_is_void(pnt
))
299 isl_die(ctx
, isl_error_invalid
,
300 "void point does not have coordinates", return NULL
);
301 if (isl_point_check_range(pnt
, type
, pos
, 1) < 0)
304 off
= isl_point_var_offset(pnt
, type
);
309 v
= isl_val_rat_from_isl_int(ctx
, pnt
->vec
->el
[1 + pos
],
311 return isl_val_normalize(v
);
314 /* Replace coordinate "pos" of type "type" of "pnt" by "v".
316 __isl_give isl_point
*isl_point_set_coordinate_val(__isl_take isl_point
*pnt
,
317 enum isl_dim_type type
, int pos
, __isl_take isl_val
*v
)
321 if (isl_point_is_void(pnt
))
322 isl_die(isl_point_get_ctx(pnt
), isl_error_invalid
,
323 "void point does not have coordinates", goto error
);
324 if (isl_point_check_range(pnt
, type
, pos
, 1) < 0)
326 if (!isl_val_is_rat(v
))
327 isl_die(isl_point_get_ctx(pnt
), isl_error_invalid
,
328 "expecting rational value", goto error
);
330 pos
+= isl_space_offset(isl_point_peek_space(pnt
), type
);
331 if (isl_int_eq(pnt
->vec
->el
[1 + pos
], v
->n
) &&
332 isl_int_eq(pnt
->vec
->el
[0], v
->d
)) {
337 pnt
= isl_point_cow(pnt
);
340 pnt
->vec
= isl_vec_cow(pnt
->vec
);
344 if (isl_int_eq(pnt
->vec
->el
[0], v
->d
)) {
345 isl_int_set(pnt
->vec
->el
[1 + pos
], v
->n
);
346 } else if (isl_int_is_one(v
->d
)) {
347 isl_int_mul(pnt
->vec
->el
[1 + pos
], pnt
->vec
->el
[0], v
->n
);
349 isl_seq_scale(pnt
->vec
->el
+ 1,
350 pnt
->vec
->el
+ 1, v
->d
, pnt
->vec
->size
- 1);
351 isl_int_mul(pnt
->vec
->el
[1 + pos
], pnt
->vec
->el
[0], v
->n
);
352 isl_int_mul(pnt
->vec
->el
[0], pnt
->vec
->el
[0], v
->d
);
353 pnt
->vec
= isl_vec_normalize(pnt
->vec
);
366 __isl_give isl_point
*isl_point_add_ui(__isl_take isl_point
*pnt
,
367 enum isl_dim_type type
, int pos
, unsigned val
)
371 if (!pnt
|| isl_point_is_void(pnt
))
374 pnt
= isl_point_cow(pnt
);
377 pnt
->vec
= isl_vec_cow(pnt
->vec
);
381 off
= isl_point_var_offset(pnt
, type
);
386 isl_int_add_ui(pnt
->vec
->el
[1 + pos
], pnt
->vec
->el
[1 + pos
], val
);
394 __isl_give isl_point
*isl_point_sub_ui(__isl_take isl_point
*pnt
,
395 enum isl_dim_type type
, int pos
, unsigned val
)
399 if (!pnt
|| isl_point_is_void(pnt
))
402 pnt
= isl_point_cow(pnt
);
405 pnt
->vec
= isl_vec_cow(pnt
->vec
);
409 off
= isl_point_var_offset(pnt
, type
);
414 isl_int_sub_ui(pnt
->vec
->el
[1 + pos
], pnt
->vec
->el
[1 + pos
], val
);
422 struct isl_foreach_point
{
423 struct isl_scan_callback callback
;
424 isl_stat (*fn
)(__isl_take isl_point
*pnt
, void *user
);
429 static isl_stat
foreach_point(struct isl_scan_callback
*cb
,
430 __isl_take isl_vec
*sample
)
432 struct isl_foreach_point
*fp
= (struct isl_foreach_point
*)cb
;
435 pnt
= isl_point_alloc(isl_space_copy(fp
->dim
), sample
);
437 return fp
->fn(pnt
, fp
->user
);
440 isl_stat
isl_set_foreach_point(__isl_keep isl_set
*set
,
441 isl_stat (*fn
)(__isl_take isl_point
*pnt
, void *user
), void *user
)
443 struct isl_foreach_point fp
= { { &foreach_point
}, fn
, user
};
447 return isl_stat_error
;
449 fp
.dim
= isl_set_get_space(set
);
451 return isl_stat_error
;
453 set
= isl_set_copy(set
);
454 set
= isl_set_cow(set
);
455 set
= isl_set_make_disjoint(set
);
456 set
= isl_set_compute_divs(set
);
460 for (i
= 0; i
< set
->n
; ++i
)
461 if (isl_basic_set_scan(isl_basic_set_copy(set
->p
[i
]),
466 isl_space_free(fp
.dim
);
471 isl_space_free(fp
.dim
);
472 return isl_stat_error
;
475 /* Return 1 if "bmap" contains the point "point".
476 * "bmap" is assumed to have known divs.
477 * The point is first extended with the divs and then passed
478 * to basic_map_contains.
480 isl_bool
isl_basic_map_contains_point(__isl_keep isl_basic_map
*bmap
,
481 __isl_keep isl_point
*point
)
488 return isl_bool_error
;
489 isl_assert(bmap
->ctx
, isl_space_is_equal(bmap
->dim
, point
->dim
),
490 return isl_bool_error
);
491 if (bmap
->n_div
== 0)
492 return isl_basic_map_contains(bmap
, point
->vec
);
494 local
= isl_local_alloc_from_mat(isl_basic_map_get_divs(bmap
));
495 vec
= isl_point_get_vec(point
);
496 vec
= isl_local_extend_point_vec(local
, vec
);
497 isl_local_free(local
);
499 contains
= isl_basic_map_contains(bmap
, vec
);
505 isl_bool
isl_map_contains_point(__isl_keep isl_map
*map
,
506 __isl_keep isl_point
*point
)
509 isl_bool found
= isl_bool_false
;
512 return isl_bool_error
;
514 map
= isl_map_copy(map
);
515 map
= isl_map_compute_divs(map
);
517 return isl_bool_error
;
519 for (i
= 0; i
< map
->n
; ++i
) {
520 found
= isl_basic_map_contains_point(map
->p
[i
], point
);
531 return isl_bool_error
;
534 isl_bool
isl_set_contains_point(__isl_keep isl_set
*set
,
535 __isl_keep isl_point
*point
)
537 return isl_map_contains_point(set_to_map(set
), point
);
540 __isl_give isl_basic_set
*isl_basic_set_from_point(__isl_take isl_point
*pnt
)
543 isl_basic_set
*model
;
548 model
= isl_basic_set_empty(isl_space_copy(pnt
->dim
));
549 bset
= isl_basic_set_from_vec(isl_vec_copy(pnt
->vec
));
550 bset
= isl_basic_set_from_underlying_set(bset
, model
);
556 __isl_give isl_set
*isl_set_from_point(__isl_take isl_point
*pnt
)
559 bset
= isl_basic_set_from_point(pnt
);
560 return isl_set_from_basic_set(bset
);
563 /* Construct a union set, containing the single element "pnt".
564 * If "pnt" is void, then return an empty union set.
566 __isl_give isl_union_set
*isl_union_set_from_point(__isl_take isl_point
*pnt
)
570 if (isl_point_is_void(pnt
)) {
573 space
= isl_point_get_space(pnt
);
575 return isl_union_set_empty(space
);
578 return isl_union_set_from_set(isl_set_from_point(pnt
));
581 __isl_give isl_basic_set
*isl_basic_set_box_from_points(
582 __isl_take isl_point
*pnt1
, __isl_take isl_point
*pnt2
)
584 isl_basic_set
*bset
= NULL
;
595 isl_assert(pnt1
->dim
->ctx
,
596 isl_space_is_equal(pnt1
->dim
, pnt2
->dim
), goto error
);
598 if (isl_point_is_void(pnt1
) && isl_point_is_void(pnt2
)) {
599 isl_space
*dim
= isl_space_copy(pnt1
->dim
);
600 isl_point_free(pnt1
);
601 isl_point_free(pnt2
);
603 return isl_basic_set_empty(dim
);
605 if (isl_point_is_void(pnt1
)) {
606 isl_point_free(pnt1
);
608 return isl_basic_set_from_point(pnt2
);
610 if (isl_point_is_void(pnt2
)) {
611 isl_point_free(pnt2
);
613 return isl_basic_set_from_point(pnt1
);
616 total
= isl_point_dim(pnt1
, isl_dim_all
);
619 bset
= isl_basic_set_alloc_space(isl_space_copy(pnt1
->dim
), 0, 0, 2 * total
);
621 for (i
= 0; i
< total
; ++i
) {
622 isl_int_mul(t
, pnt1
->vec
->el
[1 + i
], pnt2
->vec
->el
[0]);
623 isl_int_submul(t
, pnt2
->vec
->el
[1 + i
], pnt1
->vec
->el
[0]);
625 k
= isl_basic_set_alloc_inequality(bset
);
628 isl_seq_clr(bset
->ineq
[k
] + 1, total
);
629 if (isl_int_is_pos(t
)) {
630 isl_int_set_si(bset
->ineq
[k
][1 + i
], -1);
631 isl_int_set(bset
->ineq
[k
][0], pnt1
->vec
->el
[1 + i
]);
633 isl_int_set_si(bset
->ineq
[k
][1 + i
], 1);
634 isl_int_neg(bset
->ineq
[k
][0], pnt1
->vec
->el
[1 + i
]);
636 isl_int_fdiv_q(bset
->ineq
[k
][0], bset
->ineq
[k
][0], pnt1
->vec
->el
[0]);
638 k
= isl_basic_set_alloc_inequality(bset
);
641 isl_seq_clr(bset
->ineq
[k
] + 1, total
);
642 if (isl_int_is_pos(t
)) {
643 isl_int_set_si(bset
->ineq
[k
][1 + i
], 1);
644 isl_int_neg(bset
->ineq
[k
][0], pnt2
->vec
->el
[1 + i
]);
646 isl_int_set_si(bset
->ineq
[k
][1 + i
], -1);
647 isl_int_set(bset
->ineq
[k
][0], pnt2
->vec
->el
[1 + i
]);
649 isl_int_fdiv_q(bset
->ineq
[k
][0], bset
->ineq
[k
][0], pnt2
->vec
->el
[0]);
652 bset
= isl_basic_set_finalize(bset
);
654 isl_point_free(pnt1
);
655 isl_point_free(pnt2
);
661 isl_point_free(pnt1
);
662 isl_point_free(pnt2
);
664 isl_basic_set_free(bset
);
668 __isl_give isl_set
*isl_set_box_from_points(__isl_take isl_point
*pnt1
,
669 __isl_take isl_point
*pnt2
)
672 bset
= isl_basic_set_box_from_points(pnt1
, pnt2
);
673 return isl_set_from_basic_set(bset
);
676 /* Print the coordinate at position "pos" of the point "pnt".
678 static __isl_give isl_printer
*print_coordinate(__isl_take isl_printer
*p
,
679 struct isl_print_space_data
*data
, unsigned pos
)
681 isl_point
*pnt
= data
->user
;
683 pos
+= isl_space_offset(data
->space
, data
->type
);
684 p
= isl_printer_print_isl_int(p
, pnt
->vec
->el
[1 + pos
]);
685 if (!isl_int_is_one(pnt
->vec
->el
[0])) {
686 p
= isl_printer_print_str(p
, "/");
687 p
= isl_printer_print_isl_int(p
, pnt
->vec
->el
[0]);
693 __isl_give isl_printer
*isl_printer_print_point(
694 __isl_take isl_printer
*p
, __isl_keep isl_point
*pnt
)
696 struct isl_print_space_data data
= { 0 };
702 if (isl_point_is_void(pnt
)) {
703 p
= isl_printer_print_str(p
, "void");
707 nparam
= isl_point_dim(pnt
, isl_dim_param
);
709 return isl_printer_free(p
);
711 p
= isl_printer_print_str(p
, "[");
712 for (i
= 0; i
< nparam
; ++i
) {
715 p
= isl_printer_print_str(p
, ", ");
716 name
= isl_space_get_dim_name(pnt
->dim
, isl_dim_param
, i
);
718 p
= isl_printer_print_str(p
, name
);
719 p
= isl_printer_print_str(p
, " = ");
721 p
= isl_printer_print_isl_int(p
, pnt
->vec
->el
[1 + i
]);
722 if (!isl_int_is_one(pnt
->vec
->el
[0])) {
723 p
= isl_printer_print_str(p
, "/");
724 p
= isl_printer_print_isl_int(p
, pnt
->vec
->el
[0]);
727 p
= isl_printer_print_str(p
, "]");
728 p
= isl_printer_print_str(p
, " -> ");
730 data
.print_dim
= &print_coordinate
;
732 p
= isl_printer_print_str(p
, "{ ");
733 p
= isl_print_space(pnt
->dim
, p
, 0, &data
);
734 p
= isl_printer_print_str(p
, " }");