add isl_set_sample_point
[isl.git] / isl_scan.c
blobd8936459e967f484114ca11088cc5d41f102d49d
1 /*
2 * Copyright 2008-2009 Katholieke Universiteit Leuven
4 * Use of this software is governed by the GNU LGPLv2.1 license
6 * Written by Sven Verdoolaege, K.U.Leuven, Departement
7 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
8 */
10 #include "isl_basis_reduction.h"
11 #include "isl_scan.h"
12 #include "isl_seq.h"
13 #include "isl_tab.h"
15 /* Call callback->add with the current sample value of the tableau "tab".
17 static int add_solution(struct isl_tab *tab, struct isl_scan_callback *callback)
19 struct isl_vec *sample;
21 if (!tab)
22 return -1;
23 sample = isl_tab_get_sample_value(tab);
24 if (!sample)
25 return -1;
27 return callback->add(callback, sample);
30 static int scan_0D(struct isl_basic_set *bset,
31 struct isl_scan_callback *callback)
33 struct isl_vec *sample;
35 sample = isl_vec_alloc(bset->ctx, 1);
36 isl_basic_set_free(bset);
38 if (!sample)
39 return -1;
41 isl_int_set_si(sample->el[0], 1);
43 return callback->add(callback, sample);
46 /* Look for all integer points in "bset", which is assumed to be unbounded,
47 * and call callback->add on each of them.
49 * We first compute a reduced basis for the set and then scan
50 * the set in the directions of this basis.
51 * We basically perform a depth first search, where in each level i
52 * we compute the range in the i-th basis vector direction, given
53 * fixed values in the directions of the previous basis vector.
54 * We then add an equality to the tableau fixing the value in the
55 * direction of the current basis vector to each value in the range
56 * in turn and then continue to the next level.
58 * The search is implemented iteratively. "level" identifies the current
59 * basis vector. "init" is true if we want the first value at the current
60 * level and false if we want the next value.
61 * Solutions are added in the leaves of the search tree, i.e., after
62 * we have fixed a value in each direction of the basis.
64 int isl_basic_set_scan(struct isl_basic_set *bset,
65 struct isl_scan_callback *callback)
67 unsigned dim;
68 struct isl_mat *B = NULL;
69 struct isl_tab *tab = NULL;
70 struct isl_vec *min;
71 struct isl_vec *max;
72 struct isl_tab_undo **snap;
73 int level;
74 int init;
75 enum isl_lp_result res;
77 if (!bset)
78 return -1;
80 dim = isl_basic_set_total_dim(bset);
81 if (dim == 0)
82 return scan_0D(bset, callback);
84 min = isl_vec_alloc(bset->ctx, dim);
85 max = isl_vec_alloc(bset->ctx, dim);
86 snap = isl_alloc_array(bset->ctx, struct isl_tab_undo *, dim);
88 if (!min || !max || !snap)
89 goto error;
91 tab = isl_tab_from_basic_set(bset);
92 if (!tab)
93 goto error;
94 if (isl_tab_extend_cons(tab, dim + 1) < 0)
95 goto error;
97 tab->basis = isl_mat_identity(bset->ctx, 1 + dim);
98 if (1)
99 tab = isl_tab_compute_reduced_basis(tab);
100 if (!tab)
101 goto error;
102 B = isl_mat_copy(tab->basis);
103 if (!B)
104 goto error;
106 level = 0;
107 init = 1;
109 while (level >= 0) {
110 int empty = 0;
111 if (init) {
112 res = isl_tab_min(tab, B->row[1 + level],
113 bset->ctx->one, &min->el[level], NULL, 0);
114 if (res == isl_lp_empty)
115 empty = 1;
116 if (res == isl_lp_error || res == isl_lp_unbounded)
117 goto error;
118 isl_seq_neg(B->row[1 + level] + 1,
119 B->row[1 + level] + 1, dim);
120 res = isl_tab_min(tab, B->row[1 + level],
121 bset->ctx->one, &max->el[level], NULL, 0);
122 isl_seq_neg(B->row[1 + level] + 1,
123 B->row[1 + level] + 1, dim);
124 isl_int_neg(max->el[level], max->el[level]);
125 if (res == isl_lp_empty)
126 empty = 1;
127 if (res == isl_lp_error || res == isl_lp_unbounded)
128 goto error;
129 snap[level] = isl_tab_snap(tab);
130 } else
131 isl_int_add_ui(min->el[level], min->el[level], 1);
133 if (empty || isl_int_gt(min->el[level], max->el[level])) {
134 level--;
135 init = 0;
136 if (level >= 0)
137 if (isl_tab_rollback(tab, snap[level]) < 0)
138 goto error;
139 continue;
141 isl_int_neg(B->row[1 + level][0], min->el[level]);
142 tab = isl_tab_add_valid_eq(tab, B->row[1 + level]);
143 isl_int_set_si(B->row[1 + level][0], 0);
144 if (level < dim - 1) {
145 ++level;
146 init = 1;
147 continue;
149 if (add_solution(tab, callback) < 0)
150 goto error;
151 init = 0;
152 if (isl_tab_rollback(tab, snap[level]) < 0)
153 goto error;
156 isl_tab_free(tab);
157 free(snap);
158 isl_vec_free(min);
159 isl_vec_free(max);
160 isl_basic_set_free(bset);
161 isl_mat_free(B);
162 return 0;
163 error:
164 isl_tab_free(tab);
165 free(snap);
166 isl_vec_free(min);
167 isl_vec_free(max);
168 isl_basic_set_free(bset);
169 isl_mat_free(B);
170 return -1;