add isl_point
authorSven Verdoolaege <skimo@kotnet.org>
Thu, 4 Mar 2010 11:38:31 +0000 (12:38 +0100)
committerSven Verdoolaege <skimo@kotnet.org>
Thu, 4 Mar 2010 16:02:00 +0000 (17:02 +0100)
Makefile.am
doc/user.pod
include/isl_point.h [new file with mode: 0644]
include/isl_set.h
isl_point.c [new file with mode: 0644]
isl_point_private.h [new file with mode: 0644]

index eaf3bec..1f313ea 100644 (file)
@@ -63,6 +63,8 @@ libisl_la_SOURCES = \
        isl_options.c \
        isl_output.c \
        isl_piplib.h \
+       isl_point_private.h \
+       isl_point.c \
        isl_sample.h \
        isl_sample.c \
        isl_scan.c \
@@ -154,6 +156,7 @@ pkginclude_HEADERS = \
        include/isl_mat.h \
        include/isl_map.h \
        include/isl_options.h \
+       include/isl_point.h \
        include/isl_seq.h \
        include/isl_set.h \
        include/isl_vec.h
index d266041..666637a 100644 (file)
@@ -1041,6 +1041,59 @@ of all elements associated to that element.
        __isl_give isl_map *isl_map_lexmax(
                __isl_take isl_map *map);
 
+=head2 Points
+
+Points are elements of a set.  They can be used to construct
+simple sets (boxes) or they can be used to represent the
+individual elements of a set.
+The zero point (the origin) can be created using
+
+       __isl_give isl_point *isl_point_zero(__isl_take isl_dim *dim);
+
+The coordinates of a point can be inspected, set and changed
+using
+
+       void isl_point_get_coordinate(__isl_keep isl_point *pnt,
+               enum isl_dim_type type, int pos, isl_int *v);
+       __isl_give isl_point *isl_point_set_coordinate(
+               __isl_take isl_point *pnt,
+               enum isl_dim_type type, int pos, isl_int v);
+
+       __isl_give isl_point *isl_point_add_ui(
+               __isl_take isl_point *pnt,
+               enum isl_dim_type type, int pos, unsigned val);
+       __isl_give isl_point *isl_point_sub_ui(
+               __isl_take isl_point *pnt,
+               enum isl_dim_type type, int pos, unsigned val);
+
+Points can be copied or freed using
+
+       __isl_give isl_point *isl_point_copy(
+               __isl_keep isl_point *pnt);
+       void isl_point_free(__isl_take isl_point *pnt);
+
+A box can be created from two opposite extremal points using
+
+       __isl_give isl_set *isl_set_box_from_points(
+               __isl_take isl_point *pnt1,
+               __isl_take isl_point *pnt2);
+
+All elements of a B<bounded> set can be enumerated using
+the following function.
+
+       int isl_set_foreach_point(__isl_keep isl_set *set,
+               int (*fn)(__isl_take isl_point *pnt, void *user),
+               void *user);
+
+The function C<fn> is called for each integer point in
+C<set> with as second argument the last argument of
+the C<isl_set_foreach_point> call.  The function C<fn>
+should return C<0> on success and C<-1> on failure.
+In the latter case, C<isl_set_foreach_point> will stop
+enumerating and return C<-1> as well.
+If the enumeration is performed successfully and to completion,
+then C<isl_set_foreach_point> returns C<0>.
+
 =head2 Dependence Analysis
 
 C<isl> contains specialized functionality for performing
diff --git a/include/isl_point.h b/include/isl_point.h
new file mode 100644 (file)
index 0000000..d0beba3
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef ISL_POINT_H
+#define ISL_POINT_H
+
+#include <stdio.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_point;
+typedef struct isl_point isl_point;
+
+__isl_give isl_point *isl_point_zero(__isl_take isl_dim *dim);
+__isl_give isl_point *isl_point_copy(__isl_keep isl_point *pnt);
+void isl_point_free(__isl_take isl_point *pnt);
+
+void isl_point_get_coordinate(__isl_keep isl_point *pnt,
+       enum isl_dim_type type, int pos, isl_int *v);
+__isl_give isl_point *isl_point_set_coordinate(__isl_take isl_point *pnt,
+       enum isl_dim_type type, int pos, isl_int v);
+
+__isl_give isl_point *isl_point_add_ui(__isl_take isl_point *pnt,
+       enum isl_dim_type type, int pos, unsigned val);
+__isl_give isl_point *isl_point_sub_ui(__isl_take isl_point *pnt,
+       enum isl_dim_type type, int pos, unsigned val);
+
+__isl_give isl_point *isl_point_void(__isl_take isl_dim *dim);
+int isl_point_is_void(__isl_keep isl_point *pnt);
+
+void isl_point_print(__isl_keep isl_point *pnt, FILE *out);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
index 483c524..146d99f 100644 (file)
@@ -12,6 +12,7 @@
 
 #include "isl_map.h"
 #include "isl_list.h"
+#include <isl_point.h>
 
 #if defined(__cplusplus)
 extern "C" {
@@ -299,6 +300,12 @@ int isl_set_dim_is_unique(struct isl_set *set, unsigned dim);
 int isl_set_foreach_basic_set(__isl_keep isl_set *set,
        int (*fn)(__isl_take isl_basic_set *bset, void *user), void *user);
 
+int isl_set_foreach_point(__isl_keep isl_set *set,
+       int (*fn)(__isl_take isl_point *pnt, void *user), void *user);
+
+__isl_give isl_set *isl_set_box_from_points(__isl_take isl_point *pnt1,
+       __isl_take isl_point *pnt2);
+
 int isl_set_size(__isl_keep isl_set *set);
 
 #if defined(__cplusplus)
diff --git a/isl_point.c b/isl_point.c
new file mode 100644 (file)
index 0000000..23dbb50
--- /dev/null
@@ -0,0 +1,388 @@
+#include <isl_point_private.h>
+#include <isl_set.h>
+#include <isl_map_private.h>
+#include <isl_sample.h>
+#include <isl_scan.h>
+#include <isl_seq.h>
+
+__isl_give isl_point *isl_point_alloc(__isl_take isl_dim *dim,
+       __isl_take isl_vec *vec)
+{
+       struct isl_point *pnt;
+
+       if (!dim || !vec)
+               goto error;
+
+       pnt = isl_alloc_type(dim->ctx, struct isl_point);
+       if (!pnt)
+               goto error;
+
+       if (vec->size > 1 + isl_dim_total(dim)) {
+               vec = isl_vec_cow(vec);
+               if (!vec)
+                       goto error;
+               vec->size = 1 + isl_dim_total(dim);
+       }
+
+       pnt->ref = 1;
+       pnt->dim = dim;
+       pnt->vec = vec;
+
+       return pnt;
+error:
+       isl_dim_free(dim);
+       isl_vec_free(vec);
+       return NULL;
+}
+
+__isl_give isl_point *isl_point_zero(__isl_take isl_dim *dim)
+{
+       isl_vec *vec;
+
+       if (!dim)
+               return NULL;
+       vec = isl_vec_alloc(dim->ctx, 1 + isl_dim_total(dim));
+       if (!vec)
+               goto error;
+       isl_int_set_si(vec->el[0], 1);
+       isl_seq_clr(vec->el + 1, vec->size - 1);
+       return isl_point_alloc(dim, vec);
+error:
+       isl_dim_free(dim);
+       return NULL;
+}
+
+__isl_give isl_point *isl_point_dup(__isl_keep isl_point *pnt)
+{
+       struct isl_point *pnt2;
+
+       if (!pnt)
+               return NULL;
+       pnt2 = isl_point_alloc(isl_dim_copy(pnt->dim), isl_vec_copy(pnt->vec));
+       return pnt2;
+}
+
+__isl_give isl_point *isl_point_cow(__isl_take isl_point *pnt)
+{
+       struct isl_point *pnt2;
+       if (!pnt)
+               return NULL;
+
+       if (pnt->ref == 1)
+               return pnt;
+
+       pnt2 = isl_point_dup(pnt);
+       isl_point_free(pnt);
+       return pnt2;
+}
+
+__isl_give isl_point *isl_point_copy(__isl_keep isl_point *pnt)
+{
+       if (!pnt)
+               return NULL;
+
+       pnt->ref++;
+       return pnt;
+}
+
+void isl_point_free(__isl_take isl_point *pnt)
+{
+       if (!pnt)
+               return;
+
+       if (--pnt->ref > 0)
+               return;
+
+       isl_dim_free(pnt->dim);
+       isl_vec_free(pnt->vec);
+       free(pnt);
+}
+
+__isl_give isl_point *isl_point_void(__isl_take isl_dim *dim)
+{
+       if (!dim)
+               return NULL;
+
+       return isl_point_alloc(dim, isl_vec_alloc(dim->ctx, 0));
+}
+
+int isl_point_is_void(__isl_keep isl_point *pnt)
+{
+       if (!pnt)
+               return -1;
+
+       return pnt->vec->size == 0;
+}
+
+void isl_point_get_coordinate(__isl_keep isl_point *pnt,
+       enum isl_dim_type type, int pos, isl_int *v)
+{
+       if (!pnt || isl_point_is_void(pnt))
+               return;
+       if (type == isl_dim_set)
+               pos += isl_dim_size(pnt->dim, isl_dim_param);
+       isl_int_set(*v, pnt->vec->el[1 + pos]);
+}
+
+__isl_give isl_point *isl_point_set_coordinate(__isl_take isl_point *pnt,
+       enum isl_dim_type type, int pos, isl_int v)
+{
+       if (!pnt || isl_point_is_void(pnt))
+               return pnt;
+
+       pnt = isl_point_cow(pnt);
+       if (!pnt)
+               return NULL;
+       pnt->vec = isl_vec_cow(pnt->vec);
+       if (!pnt->vec)
+               goto error;
+
+       if (type == isl_dim_set)
+               pos += isl_dim_size(pnt->dim, isl_dim_param);
+
+       isl_int_set(pnt->vec->el[1 + pos], v);
+
+       return pnt;
+error:
+       isl_point_free(pnt);
+       return NULL;
+}
+
+__isl_give isl_point *isl_point_add_ui(__isl_take isl_point *pnt,
+       enum isl_dim_type type, int pos, unsigned val)
+{
+       if (!pnt || isl_point_is_void(pnt))
+               return pnt;
+
+       pnt = isl_point_cow(pnt);
+       if (!pnt)
+               return NULL;
+       pnt->vec = isl_vec_cow(pnt->vec);
+       if (!pnt->vec)
+               goto error;
+
+       if (type == isl_dim_set)
+               pos += isl_dim_size(pnt->dim, isl_dim_param);
+
+       isl_int_add_ui(pnt->vec->el[1 + pos], pnt->vec->el[1 + pos], val);
+
+       return pnt;
+error:
+       isl_point_free(pnt);
+       return NULL;
+}
+
+__isl_give isl_point *isl_point_sub_ui(__isl_take isl_point *pnt,
+       enum isl_dim_type type, int pos, unsigned val)
+{
+       if (!pnt || isl_point_is_void(pnt))
+               return pnt;
+
+       pnt = isl_point_cow(pnt);
+       if (!pnt)
+               return NULL;
+       pnt->vec = isl_vec_cow(pnt->vec);
+       if (!pnt->vec)
+               goto error;
+
+       if (type == isl_dim_set)
+               pos += isl_dim_size(pnt->dim, isl_dim_param);
+
+       isl_int_sub_ui(pnt->vec->el[1 + pos], pnt->vec->el[1 + pos], val);
+
+       return pnt;
+error:
+       isl_point_free(pnt);
+       return NULL;
+}
+
+struct isl_foreach_point {
+       struct isl_scan_callback callback;
+       int (*fn)(__isl_take isl_point *pnt, void *user);
+       void *user;
+       isl_dim *dim;
+};
+
+static int foreach_point(struct isl_scan_callback *cb, __isl_take isl_vec *sample)
+{
+       struct isl_foreach_point *fp = (struct isl_foreach_point *)cb;
+       isl_point *pnt;
+
+       pnt = isl_point_alloc(isl_dim_copy(fp->dim), sample);
+
+       return fp->fn(pnt, fp->user);
+}
+
+int isl_set_foreach_point(__isl_keep isl_set *set,
+       int (*fn)(__isl_take isl_point *pnt, void *user), void *user)
+{
+       struct isl_foreach_point fp = { { &foreach_point }, fn, user };
+       int i;
+
+       if (!set)
+               return -1;
+
+       fp.dim = isl_set_get_dim(set);
+       if (!fp.dim)
+               return -1;
+
+       set = isl_set_copy(set);
+       set = isl_set_cow(set);
+       set = isl_set_make_disjoint(set);
+       set = isl_set_compute_divs(set);
+       if (!set)
+               goto error;
+
+       for (i = 0; i < set->n; ++i)
+               if (isl_basic_set_scan(isl_basic_set_copy(set->p[i]),
+                                       &fp.callback) < 0)
+                       goto error;
+
+       isl_set_free(set);
+       isl_dim_free(fp.dim);
+
+       return 0;
+error:
+       isl_set_free(set);
+       isl_dim_free(fp.dim);
+       return -1;
+}
+
+__isl_give isl_set *isl_set_box_from_points(__isl_take isl_point *pnt1,
+       __isl_take isl_point *pnt2)
+{
+       isl_basic_set *bset;
+       unsigned total;
+       int i;
+       int k;
+       isl_int t;
+
+       isl_int_init(t);
+
+       if (!pnt1 || !pnt2)
+               goto error;
+
+       isl_assert(pnt1->dim->ctx,
+                       isl_dim_equal(pnt1->dim, pnt2->dim), goto error);
+
+       if (isl_point_is_void(pnt1) && isl_point_is_void(pnt2)) {
+               isl_dim *dim = isl_dim_copy(pnt1->dim);
+               isl_point_free(pnt1);
+               isl_point_free(pnt2);
+               isl_int_clear(t);
+               return isl_set_empty(dim);
+       }
+       if (isl_point_is_void(pnt1)) {
+               isl_basic_set *model;
+               model = isl_basic_set_empty(isl_dim_copy(pnt2->dim));
+               bset = isl_basic_set_from_vec(isl_vec_copy(pnt2->vec));
+               bset = isl_basic_set_from_underlying_set(bset, model);
+               isl_point_free(pnt1);
+               isl_point_free(pnt2);
+               isl_int_clear(t);
+               return isl_set_from_basic_set(bset);
+       }
+       if (isl_point_is_void(pnt2)) {
+               isl_basic_set *model;
+               model = isl_basic_set_empty(isl_dim_copy(pnt1->dim));
+               bset = isl_basic_set_from_vec(isl_vec_copy(pnt1->vec));
+               bset = isl_basic_set_from_underlying_set(bset, model);
+               isl_point_free(pnt1);
+               isl_point_free(pnt2);
+               isl_int_clear(t);
+               return isl_set_from_basic_set(bset);
+       }
+
+       total = isl_dim_total(pnt1->dim);
+       bset = isl_basic_set_alloc_dim(isl_dim_copy(pnt1->dim), 0, 0, 2 * total);
+
+       for (i = 0; i < total; ++i) {
+               isl_int_mul(t, pnt1->vec->el[1 + i], pnt2->vec->el[0]);
+               isl_int_submul(t, pnt2->vec->el[1 + i], pnt1->vec->el[0]);
+
+               k = isl_basic_set_alloc_inequality(bset);
+               if (k < 0)
+                       goto error;
+               isl_seq_clr(bset->ineq[k] + 1, total);
+               if (isl_int_is_pos(t)) {
+                       isl_int_set_si(bset->ineq[k][1 + i], -1);
+                       isl_int_set(bset->ineq[k][0], pnt1->vec->el[1 + i]);
+               } else {
+                       isl_int_set_si(bset->ineq[k][1 + i], 1);
+                       isl_int_neg(bset->ineq[k][0], pnt1->vec->el[1 + i]);
+               }
+               isl_int_fdiv_q(bset->ineq[k][0], bset->ineq[k][0], pnt1->vec->el[0]);
+
+               k = isl_basic_set_alloc_inequality(bset);
+               if (k < 0)
+                       goto error;
+               isl_seq_clr(bset->ineq[k] + 1, total);
+               if (isl_int_is_pos(t)) {
+                       isl_int_set_si(bset->ineq[k][1 + i], 1);
+                       isl_int_neg(bset->ineq[k][0], pnt2->vec->el[1 + i]);
+               } else {
+                       isl_int_set_si(bset->ineq[k][1 + i], -1);
+                       isl_int_set(bset->ineq[k][0], pnt2->vec->el[1 + i]);
+               }
+               isl_int_fdiv_q(bset->ineq[k][0], bset->ineq[k][0], pnt2->vec->el[0]);
+       }
+
+       bset = isl_basic_set_finalize(bset);
+
+       isl_point_free(pnt1);
+       isl_point_free(pnt2);
+
+       isl_int_clear(t);
+
+       return isl_set_from_basic_set(bset);
+error:
+       isl_point_free(pnt1);
+       isl_point_free(pnt2);
+       isl_int_clear(t);
+       return NULL;
+}
+
+void isl_point_print(__isl_keep isl_point *pnt, FILE *out)
+{
+       int i;
+       unsigned nparam;
+       unsigned dim;
+
+       if (!pnt)
+               return;
+       if (isl_point_is_void(pnt)) {
+               fprintf(out, "void\n");
+               return;
+       }
+
+       nparam = isl_dim_size(pnt->dim, isl_dim_param);
+       dim = isl_dim_size(pnt->dim, isl_dim_set);
+       if (nparam > 0) {
+               fprintf(out, "[");
+               for (i = 0; i < nparam; ++i) {
+                       const char *name;
+                       if (i)
+                               fprintf(out, ", ");
+                       name = isl_dim_get_name(pnt->dim, isl_dim_param, i);
+                       if (name)
+                               fprintf(out, "%s = ", name);
+                       isl_int_print(out, pnt->vec->el[1 + i], 0);
+                       if (!isl_int_is_one(pnt->vec->el[0])) {
+                               fprintf(out, "/");
+                               isl_int_print(out, pnt->vec->el[0], 0);
+                       }
+               }
+               fprintf(out, "] -> ");
+       }
+       fprintf(out, "[");
+       for (i = 0; i < dim; ++i) {
+               if (i)
+                       fprintf(out, ", ");
+               isl_int_print(out, pnt->vec->el[1 + nparam + i], 0);
+               if (!isl_int_is_one(pnt->vec->el[0])) {
+                       fprintf(out, "/");
+                       isl_int_print(out, pnt->vec->el[0], 0);
+               }
+       }
+       fprintf(out, "]\n");
+}
diff --git a/isl_point_private.h b/isl_point_private.h
new file mode 100644 (file)
index 0000000..fbf1ee9
--- /dev/null
@@ -0,0 +1,12 @@
+#include <isl_dim.h>
+#include <isl_point.h>
+#include <isl_vec.h>
+
+struct isl_point {
+       int             ref;
+       struct isl_dim  *dim;
+       struct isl_vec  *vec;
+};
+
+__isl_give isl_point *isl_point_alloc(__isl_take isl_dim *dim,
+       __isl_take isl_vec *vec);