1/*
2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 * Copyright 2012      Ecole Normale Superieure
4 *
5 * Use of this software is governed by the MIT license
6 *
7 * Written by Sven Verdoolaege, K.U.Leuven, Departement
8 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
9 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
10 */
11
12#include <strings.h>
13#include <isl_ctx_private.h>
14#include <isl_map_private.h>
15#include "isl_equalities.h"
16#include <isl/map.h>
17#include <isl/seq.h>
18#include "isl_tab.h"
19#include <isl_space_private.h>
20#include <isl_mat_private.h>
21
22static void swap_equality(struct isl_basic_map *bmap, int a, int b)
23{
24	isl_int *t = bmap->eq[a];
25	bmap->eq[a] = bmap->eq[b];
26	bmap->eq[b] = t;
27}
28
29static void swap_inequality(struct isl_basic_map *bmap, int a, int b)
30{
31	if (a != b) {
32		isl_int *t = bmap->ineq[a];
33		bmap->ineq[a] = bmap->ineq[b];
34		bmap->ineq[b] = t;
35	}
36}
37
38static void constraint_drop_vars(isl_int *c, unsigned n, unsigned rem)
39{
40	isl_seq_cpy(c, c + n, rem);
41	isl_seq_clr(c + rem, n);
42}
43
44/* Drop n dimensions starting at first.
45 *
46 * In principle, this frees up some extra variables as the number
47 * of columns remains constant, but we would have to extend
48 * the div array too as the number of rows in this array is assumed
49 * to be equal to extra.
50 */
51struct isl_basic_set *isl_basic_set_drop_dims(
52		struct isl_basic_set *bset, unsigned first, unsigned n)
53{
54	int i;
55
56	if (!bset)
57		goto error;
58
59	isl_assert(bset->ctx, first + n <= bset->dim->n_out, goto error);
60
61	if (n == 0 && !isl_space_get_tuple_name(bset->dim, isl_dim_set))
62		return bset;
63
64	bset = isl_basic_set_cow(bset);
65	if (!bset)
66		return NULL;
67
68	for (i = 0; i < bset->n_eq; ++i)
69		constraint_drop_vars(bset->eq[i]+1+bset->dim->nparam+first, n,
70				     (bset->dim->n_out-first-n)+bset->extra);
71
72	for (i = 0; i < bset->n_ineq; ++i)
73		constraint_drop_vars(bset->ineq[i]+1+bset->dim->nparam+first, n,
74				     (bset->dim->n_out-first-n)+bset->extra);
75
76	for (i = 0; i < bset->n_div; ++i)
77		constraint_drop_vars(bset->div[i]+1+1+bset->dim->nparam+first, n,
78				     (bset->dim->n_out-first-n)+bset->extra);
79
80	bset->dim = isl_space_drop_outputs(bset->dim, first, n);
81	if (!bset->dim)
82		goto error;
83
84	ISL_F_CLR(bset, ISL_BASIC_SET_NORMALIZED);
85	bset = isl_basic_set_simplify(bset);
86	return isl_basic_set_finalize(bset);
87error:
88	isl_basic_set_free(bset);
89	return NULL;
90}
91
92struct isl_set *isl_set_drop_dims(
93		struct isl_set *set, unsigned first, unsigned n)
94{
95	int i;
96
97	if (!set)
98		goto error;
99
100	isl_assert(set->ctx, first + n <= set->dim->n_out, goto error);
101
102	if (n == 0 && !isl_space_get_tuple_name(set->dim, isl_dim_set))
103		return set;
104	set = isl_set_cow(set);
105	if (!set)
106		goto error;
107	set->dim = isl_space_drop_outputs(set->dim, first, n);
108	if (!set->dim)
109		goto error;
110
111	for (i = 0; i < set->n; ++i) {
112		set->p[i] = isl_basic_set_drop_dims(set->p[i], first, n);
113		if (!set->p[i])
114			goto error;
115	}
116
117	ISL_F_CLR(set, ISL_SET_NORMALIZED);
118	return set;
119error:
120	isl_set_free(set);
121	return NULL;
122}
123
124/* Move "n" divs starting at "first" to the end of the list of divs.
125 */
126static struct isl_basic_map *move_divs_last(struct isl_basic_map *bmap,
127	unsigned first, unsigned n)
128{
129	isl_int **div;
130	int i;
131
132	if (first + n == bmap->n_div)
133		return bmap;
134
135	div = isl_alloc_array(bmap->ctx, isl_int *, n);
136	if (!div)
137		goto error;
138	for (i = 0; i < n; ++i)
139		div[i] = bmap->div[first + i];
140	for (i = 0; i < bmap->n_div - first - n; ++i)
141		bmap->div[first + i] = bmap->div[first + n + i];
142	for (i = 0; i < n; ++i)
143		bmap->div[bmap->n_div - n + i] = div[i];
144	free(div);
145	return bmap;
146error:
147	isl_basic_map_free(bmap);
148	return NULL;
149}
150
151/* Drop "n" dimensions of type "type" starting at "first".
152 *
153 * In principle, this frees up some extra variables as the number
154 * of columns remains constant, but we would have to extend
155 * the div array too as the number of rows in this array is assumed
156 * to be equal to extra.
157 */
158struct isl_basic_map *isl_basic_map_drop(struct isl_basic_map *bmap,
159	enum isl_dim_type type, unsigned first, unsigned n)
160{
161	int i;
162	unsigned dim;
163	unsigned offset;
164	unsigned left;
165
166	if (!bmap)
167		goto error;
168
169	dim = isl_basic_map_dim(bmap, type);
170	isl_assert(bmap->ctx, first + n <= dim, goto error);
171
172	if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
173		return bmap;
174
175	bmap = isl_basic_map_cow(bmap);
176	if (!bmap)
177		return NULL;
178
179	offset = isl_basic_map_offset(bmap, type) + first;
180	left = isl_basic_map_total_dim(bmap) - (offset - 1) - n;
181	for (i = 0; i < bmap->n_eq; ++i)
182		constraint_drop_vars(bmap->eq[i]+offset, n, left);
183
184	for (i = 0; i < bmap->n_ineq; ++i)
185		constraint_drop_vars(bmap->ineq[i]+offset, n, left);
186
187	for (i = 0; i < bmap->n_div; ++i)
188		constraint_drop_vars(bmap->div[i]+1+offset, n, left);
189
190	if (type == isl_dim_div) {
191		bmap = move_divs_last(bmap, first, n);
192		if (!bmap)
193			goto error;
194		isl_basic_map_free_div(bmap, n);
195	} else
196		bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
197	if (!bmap->dim)
198		goto error;
199
200	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
201	bmap = isl_basic_map_simplify(bmap);
202	return isl_basic_map_finalize(bmap);
203error:
204	isl_basic_map_free(bmap);
205	return NULL;
206}
207
208__isl_give isl_basic_set *isl_basic_set_drop(__isl_take isl_basic_set *bset,
209	enum isl_dim_type type, unsigned first, unsigned n)
210{
211	return (isl_basic_set *)isl_basic_map_drop((isl_basic_map *)bset,
212							type, first, n);
213}
214
215struct isl_basic_map *isl_basic_map_drop_inputs(
216		struct isl_basic_map *bmap, unsigned first, unsigned n)
217{
218	return isl_basic_map_drop(bmap, isl_dim_in, first, n);
219}
220
221struct isl_map *isl_map_drop(struct isl_map *map,
222	enum isl_dim_type type, unsigned first, unsigned n)
223{
224	int i;
225
226	if (!map)
227		goto error;
228
229	isl_assert(map->ctx, first + n <= isl_map_dim(map, type), goto error);
230
231	if (n == 0 && !isl_space_get_tuple_name(map->dim, type))
232		return map;
233	map = isl_map_cow(map);
234	if (!map)
235		goto error;
236	map->dim = isl_space_drop_dims(map->dim, type, first, n);
237	if (!map->dim)
238		goto error;
239
240	for (i = 0; i < map->n; ++i) {
241		map->p[i] = isl_basic_map_drop(map->p[i], type, first, n);
242		if (!map->p[i])
243			goto error;
244	}
245	ISL_F_CLR(map, ISL_MAP_NORMALIZED);
246
247	return map;
248error:
249	isl_map_free(map);
250	return NULL;
251}
252
253struct isl_set *isl_set_drop(struct isl_set *set,
254	enum isl_dim_type type, unsigned first, unsigned n)
255{
256	return (isl_set *)isl_map_drop((isl_map *)set, type, first, n);
257}
258
259struct isl_map *isl_map_drop_inputs(
260		struct isl_map *map, unsigned first, unsigned n)
261{
262	return isl_map_drop(map, isl_dim_in, first, n);
263}
264
265/*
266 * We don't cow, as the div is assumed to be redundant.
267 */
268static struct isl_basic_map *isl_basic_map_drop_div(
269		struct isl_basic_map *bmap, unsigned div)
270{
271	int i;
272	unsigned pos;
273
274	if (!bmap)
275		goto error;
276
277	pos = 1 + isl_space_dim(bmap->dim, isl_dim_all) + div;
278
279	isl_assert(bmap->ctx, div < bmap->n_div, goto error);
280
281	for (i = 0; i < bmap->n_eq; ++i)
282		constraint_drop_vars(bmap->eq[i]+pos, 1, bmap->extra-div-1);
283
284	for (i = 0; i < bmap->n_ineq; ++i) {
285		if (!isl_int_is_zero(bmap->ineq[i][pos])) {
286			isl_basic_map_drop_inequality(bmap, i);
287			--i;
288			continue;
289		}
290		constraint_drop_vars(bmap->ineq[i]+pos, 1, bmap->extra-div-1);
291	}
292
293	for (i = 0; i < bmap->n_div; ++i)
294		constraint_drop_vars(bmap->div[i]+1+pos, 1, bmap->extra-div-1);
295
296	if (div != bmap->n_div - 1) {
297		int j;
298		isl_int *t = bmap->div[div];
299
300		for (j = div; j < bmap->n_div - 1; ++j)
301			bmap->div[j] = bmap->div[j+1];
302
303		bmap->div[bmap->n_div - 1] = t;
304	}
305	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
306	isl_basic_map_free_div(bmap, 1);
307
308	return bmap;
309error:
310	isl_basic_map_free(bmap);
311	return NULL;
312}
313
314struct isl_basic_map *isl_basic_map_normalize_constraints(
315	struct isl_basic_map *bmap)
316{
317	int i;
318	isl_int gcd;
319	unsigned total = isl_basic_map_total_dim(bmap);
320
321	if (!bmap)
322		return NULL;
323
324	isl_int_init(gcd);
325	for (i = bmap->n_eq - 1; i >= 0; --i) {
326		isl_seq_gcd(bmap->eq[i]+1, total, &gcd);
327		if (isl_int_is_zero(gcd)) {
328			if (!isl_int_is_zero(bmap->eq[i][0])) {
329				bmap = isl_basic_map_set_to_empty(bmap);
330				break;
331			}
332			isl_basic_map_drop_equality(bmap, i);
333			continue;
334		}
335		if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
336			isl_int_gcd(gcd, gcd, bmap->eq[i][0]);
337		if (isl_int_is_one(gcd))
338			continue;
339		if (!isl_int_is_divisible_by(bmap->eq[i][0], gcd)) {
340			bmap = isl_basic_map_set_to_empty(bmap);
341			break;
342		}
343		isl_seq_scale_down(bmap->eq[i], bmap->eq[i], gcd, 1+total);
344	}
345
346	for (i = bmap->n_ineq - 1; i >= 0; --i) {
347		isl_seq_gcd(bmap->ineq[i]+1, total, &gcd);
348		if (isl_int_is_zero(gcd)) {
349			if (isl_int_is_neg(bmap->ineq[i][0])) {
350				bmap = isl_basic_map_set_to_empty(bmap);
351				break;
352			}
353			isl_basic_map_drop_inequality(bmap, i);
354			continue;
355		}
356		if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
357			isl_int_gcd(gcd, gcd, bmap->ineq[i][0]);
358		if (isl_int_is_one(gcd))
359			continue;
360		isl_int_fdiv_q(bmap->ineq[i][0], bmap->ineq[i][0], gcd);
361		isl_seq_scale_down(bmap->ineq[i]+1, bmap->ineq[i]+1, gcd, total);
362	}
363	isl_int_clear(gcd);
364
365	return bmap;
366}
367
368struct isl_basic_set *isl_basic_set_normalize_constraints(
369	struct isl_basic_set *bset)
370{
371	return (struct isl_basic_set *)isl_basic_map_normalize_constraints(
372		(struct isl_basic_map *)bset);
373}
374
375/* Remove any common factor in numerator and denominator of the div expression,
376 * not taking into account the constant term.
377 * That is, if the div is of the form
378 *
379 *	floor((a + m f(x))/(m d))
380 *
381 * then replace it by
382 *
383 *	floor((floor(a/m) + f(x))/d)
384 *
385 * The difference {a/m}/d in the argument satisfies 0 <= {a/m}/d < 1/d
386 * and can therefore not influence the result of the floor.
387 */
388static void normalize_div_expression(__isl_keep isl_basic_map *bmap, int div)
389{
390	unsigned total = isl_basic_map_total_dim(bmap);
391	isl_ctx *ctx = bmap->ctx;
392
393	if (isl_int_is_zero(bmap->div[div][0]))
394		return;
395	isl_seq_gcd(bmap->div[div] + 2, total, &ctx->normalize_gcd);
396	isl_int_gcd(ctx->normalize_gcd, ctx->normalize_gcd, bmap->div[div][0]);
397	if (isl_int_is_one(ctx->normalize_gcd))
398		return;
399	isl_int_fdiv_q(bmap->div[div][1], bmap->div[div][1],
400			ctx->normalize_gcd);
401	isl_int_divexact(bmap->div[div][0], bmap->div[div][0],
402			ctx->normalize_gcd);
403	isl_seq_scale_down(bmap->div[div] + 2, bmap->div[div] + 2,
404			ctx->normalize_gcd, total);
405}
406
407/* Remove any common factor in numerator and denominator of a div expression,
408 * not taking into account the constant term.
409 * That is, look for any div of the form
410 *
411 *	floor((a + m f(x))/(m d))
412 *
413 * and replace it by
414 *
415 *	floor((floor(a/m) + f(x))/d)
416 *
417 * The difference {a/m}/d in the argument satisfies 0 <= {a/m}/d < 1/d
418 * and can therefore not influence the result of the floor.
419 */
420static __isl_give isl_basic_map *normalize_div_expressions(
421	__isl_take isl_basic_map *bmap)
422{
423	int i;
424
425	if (!bmap)
426		return NULL;
427	if (bmap->n_div == 0)
428		return bmap;
429
430	for (i = 0; i < bmap->n_div; ++i)
431		normalize_div_expression(bmap, i);
432
433	return bmap;
434}
435
436/* Assumes divs have been ordered if keep_divs is set.
437 */
438static void eliminate_var_using_equality(struct isl_basic_map *bmap,
439	unsigned pos, isl_int *eq, int keep_divs, int *progress)
440{
441	unsigned total;
442	unsigned space_total;
443	int k;
444	int last_div;
445
446	total = isl_basic_map_total_dim(bmap);
447	space_total = isl_space_dim(bmap->dim, isl_dim_all);
448	last_div = isl_seq_last_non_zero(eq + 1 + space_total, bmap->n_div);
449	for (k = 0; k < bmap->n_eq; ++k) {
450		if (bmap->eq[k] == eq)
451			continue;
452		if (isl_int_is_zero(bmap->eq[k][1+pos]))
453			continue;
454		if (progress)
455			*progress = 1;
456		isl_seq_elim(bmap->eq[k], eq, 1+pos, 1+total, NULL);
457		isl_seq_normalize(bmap->ctx, bmap->eq[k], 1 + total);
458	}
459
460	for (k = 0; k < bmap->n_ineq; ++k) {
461		if (isl_int_is_zero(bmap->ineq[k][1+pos]))
462			continue;
463		if (progress)
464			*progress = 1;
465		isl_seq_elim(bmap->ineq[k], eq, 1+pos, 1+total, NULL);
466		isl_seq_normalize(bmap->ctx, bmap->ineq[k], 1 + total);
467		ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
468	}
469
470	for (k = 0; k < bmap->n_div; ++k) {
471		if (isl_int_is_zero(bmap->div[k][0]))
472			continue;
473		if (isl_int_is_zero(bmap->div[k][1+1+pos]))
474			continue;
475		if (progress)
476			*progress = 1;
477		/* We need to be careful about circular definitions,
478		 * so for now we just remove the definition of div k
479		 * if the equality contains any divs.
480		 * If keep_divs is set, then the divs have been ordered
481		 * and we can keep the definition as long as the result
482		 * is still ordered.
483		 */
484		if (last_div == -1 || (keep_divs && last_div < k)) {
485			isl_seq_elim(bmap->div[k]+1, eq,
486					1+pos, 1+total, &bmap->div[k][0]);
487			normalize_div_expression(bmap, k);
488		} else
489			isl_seq_clr(bmap->div[k], 1 + total);
490		ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
491	}
492}
493
494/* Assumes divs have been ordered if keep_divs is set.
495 */
496static void eliminate_div(struct isl_basic_map *bmap, isl_int *eq,
497	unsigned div, int keep_divs)
498{
499	unsigned pos = isl_space_dim(bmap->dim, isl_dim_all) + div;
500
501	eliminate_var_using_equality(bmap, pos, eq, keep_divs, NULL);
502
503	isl_basic_map_drop_div(bmap, div);
504}
505
506/* Check if elimination of div "div" using equality "eq" would not
507 * result in a div depending on a later div.
508 */
509static int ok_to_eliminate_div(struct isl_basic_map *bmap, isl_int *eq,
510	unsigned div)
511{
512	int k;
513	int last_div;
514	unsigned space_total = isl_space_dim(bmap->dim, isl_dim_all);
515	unsigned pos = space_total + div;
516
517	last_div = isl_seq_last_non_zero(eq + 1 + space_total, bmap->n_div);
518	if (last_div < 0 || last_div <= div)
519		return 1;
520
521	for (k = 0; k <= last_div; ++k) {
522		if (isl_int_is_zero(bmap->div[k][0]))
523			return 1;
524		if (!isl_int_is_zero(bmap->div[k][1 + 1 + pos]))
525			return 0;
526	}
527
528	return 1;
529}
530
531/* Elimininate divs based on equalities
532 */
533static struct isl_basic_map *eliminate_divs_eq(
534		struct isl_basic_map *bmap, int *progress)
535{
536	int d;
537	int i;
538	int modified = 0;
539	unsigned off;
540
541	bmap = isl_basic_map_order_divs(bmap);
542
543	if (!bmap)
544		return NULL;
545
546	off = 1 + isl_space_dim(bmap->dim, isl_dim_all);
547
548	for (d = bmap->n_div - 1; d >= 0 ; --d) {
549		for (i = 0; i < bmap->n_eq; ++i) {
550			if (!isl_int_is_one(bmap->eq[i][off + d]) &&
551			    !isl_int_is_negone(bmap->eq[i][off + d]))
552				continue;
553			if (!ok_to_eliminate_div(bmap, bmap->eq[i], d))
554				continue;
555			modified = 1;
556			*progress = 1;
557			eliminate_div(bmap, bmap->eq[i], d, 1);
558			isl_basic_map_drop_equality(bmap, i);
559			break;
560		}
561	}
562	if (modified)
563		return eliminate_divs_eq(bmap, progress);
564	return bmap;
565}
566
567/* Elimininate divs based on inequalities
568 */
569static struct isl_basic_map *eliminate_divs_ineq(
570		struct isl_basic_map *bmap, int *progress)
571{
572	int d;
573	int i;
574	unsigned off;
575	struct isl_ctx *ctx;
576
577	if (!bmap)
578		return NULL;
579
580	ctx = bmap->ctx;
581	off = 1 + isl_space_dim(bmap->dim, isl_dim_all);
582
583	for (d = bmap->n_div - 1; d >= 0 ; --d) {
584		for (i = 0; i < bmap->n_eq; ++i)
585			if (!isl_int_is_zero(bmap->eq[i][off + d]))
586				break;
587		if (i < bmap->n_eq)
588			continue;
589		for (i = 0; i < bmap->n_ineq; ++i)
590			if (isl_int_abs_gt(bmap->ineq[i][off + d], ctx->one))
591				break;
592		if (i < bmap->n_ineq)
593			continue;
594		*progress = 1;
595		bmap = isl_basic_map_eliminate_vars(bmap, (off-1)+d, 1);
596		if (!bmap || ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
597			break;
598		bmap = isl_basic_map_drop_div(bmap, d);
599		if (!bmap)
600			break;
601	}
602	return bmap;
603}
604
605struct isl_basic_map *isl_basic_map_gauss(
606	struct isl_basic_map *bmap, int *progress)
607{
608	int k;
609	int done;
610	int last_var;
611	unsigned total_var;
612	unsigned total;
613
614	bmap = isl_basic_map_order_divs(bmap);
615
616	if (!bmap)
617		return NULL;
618
619	total = isl_basic_map_total_dim(bmap);
620	total_var = total - bmap->n_div;
621
622	last_var = total - 1;
623	for (done = 0; done < bmap->n_eq; ++done) {
624		for (; last_var >= 0; --last_var) {
625			for (k = done; k < bmap->n_eq; ++k)
626				if (!isl_int_is_zero(bmap->eq[k][1+last_var]))
627					break;
628			if (k < bmap->n_eq)
629				break;
630		}
631		if (last_var < 0)
632			break;
633		if (k != done)
634			swap_equality(bmap, k, done);
635		if (isl_int_is_neg(bmap->eq[done][1+last_var]))
636			isl_seq_neg(bmap->eq[done], bmap->eq[done], 1+total);
637
638		eliminate_var_using_equality(bmap, last_var, bmap->eq[done], 1,
639						progress);
640
641		if (last_var >= total_var &&
642		    isl_int_is_zero(bmap->div[last_var - total_var][0])) {
643			unsigned div = last_var - total_var;
644			isl_seq_neg(bmap->div[div]+1, bmap->eq[done], 1+total);
645			isl_int_set_si(bmap->div[div][1+1+last_var], 0);
646			isl_int_set(bmap->div[div][0],
647				    bmap->eq[done][1+last_var]);
648			if (progress)
649				*progress = 1;
650			ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
651		}
652	}
653	if (done == bmap->n_eq)
654		return bmap;
655	for (k = done; k < bmap->n_eq; ++k) {
656		if (isl_int_is_zero(bmap->eq[k][0]))
657			continue;
658		return isl_basic_map_set_to_empty(bmap);
659	}
660	isl_basic_map_free_equality(bmap, bmap->n_eq-done);
661	return bmap;
662}
663
664struct isl_basic_set *isl_basic_set_gauss(
665	struct isl_basic_set *bset, int *progress)
666{
667	return (struct isl_basic_set*)isl_basic_map_gauss(
668			(struct isl_basic_map *)bset, progress);
669}
670
671
672static unsigned int round_up(unsigned int v)
673{
674	int old_v = v;
675
676	while (v) {
677		old_v = v;
678		v ^= v & -v;
679	}
680	return old_v << 1;
681}
682
683static int hash_index(isl_int ***index, unsigned int size, int bits,
684			struct isl_basic_map *bmap, int k)
685{
686	int h;
687	unsigned total = isl_basic_map_total_dim(bmap);
688	uint32_t hash = isl_seq_get_hash_bits(bmap->ineq[k]+1, total, bits);
689	for (h = hash; index[h]; h = (h+1) % size)
690		if (&bmap->ineq[k] != index[h] &&
691		    isl_seq_eq(bmap->ineq[k]+1, index[h][0]+1, total))
692			break;
693	return h;
694}
695
696static int set_hash_index(isl_int ***index, unsigned int size, int bits,
697			  struct isl_basic_set *bset, int k)
698{
699	return hash_index(index, size, bits, (struct isl_basic_map *)bset, k);
700}
701
702/* If we can eliminate more than one div, then we need to make
703 * sure we do it from last div to first div, in order not to
704 * change the position of the other divs that still need to
705 * be removed.
706 */
707static struct isl_basic_map *remove_duplicate_divs(
708	struct isl_basic_map *bmap, int *progress)
709{
710	unsigned int size;
711	int *index;
712	int *elim_for;
713	int k, l, h;
714	int bits;
715	struct isl_blk eq;
716	unsigned total_var;
717	unsigned total;
718	struct isl_ctx *ctx;
719
720	bmap = isl_basic_map_order_divs(bmap);
721	if (!bmap || bmap->n_div <= 1)
722		return bmap;
723
724	total_var = isl_space_dim(bmap->dim, isl_dim_all);
725	total = total_var + bmap->n_div;
726
727	ctx = bmap->ctx;
728	for (k = bmap->n_div - 1; k >= 0; --k)
729		if (!isl_int_is_zero(bmap->div[k][0]))
730			break;
731	if (k <= 0)
732		return bmap;
733
734	elim_for = isl_calloc_array(ctx, int, bmap->n_div);
735	size = round_up(4 * bmap->n_div / 3 - 1);
736	bits = ffs(size) - 1;
737	index = isl_calloc_array(ctx, int, size);
738	if (!index)
739		return bmap;
740	eq = isl_blk_alloc(ctx, 1+total);
741	if (isl_blk_is_error(eq))
742		goto out;
743
744	isl_seq_clr(eq.data, 1+total);
745	index[isl_seq_get_hash_bits(bmap->div[k], 2+total, bits)] = k + 1;
746	for (--k; k >= 0; --k) {
747		uint32_t hash;
748
749		if (isl_int_is_zero(bmap->div[k][0]))
750			continue;
751
752		hash = isl_seq_get_hash_bits(bmap->div[k], 2+total, bits);
753		for (h = hash; index[h]; h = (h+1) % size)
754			if (isl_seq_eq(bmap->div[k],
755				       bmap->div[index[h]-1], 2+total))
756				break;
757		if (index[h]) {
758			*progress = 1;
759			l = index[h] - 1;
760			elim_for[l] = k + 1;
761		}
762		index[h] = k+1;
763	}
764	for (l = bmap->n_div - 1; l >= 0; --l) {
765		if (!elim_for[l])
766			continue;
767		k = elim_for[l] - 1;
768		isl_int_set_si(eq.data[1+total_var+k], -1);
769		isl_int_set_si(eq.data[1+total_var+l], 1);
770		eliminate_div(bmap, eq.data, l, 1);
771		isl_int_set_si(eq.data[1+total_var+k], 0);
772		isl_int_set_si(eq.data[1+total_var+l], 0);
773	}
774
775	isl_blk_free(ctx, eq);
776out:
777	free(index);
778	free(elim_for);
779	return bmap;
780}
781
782static int n_pure_div_eq(struct isl_basic_map *bmap)
783{
784	int i, j;
785	unsigned total;
786
787	total = isl_space_dim(bmap->dim, isl_dim_all);
788	for (i = 0, j = bmap->n_div-1; i < bmap->n_eq; ++i) {
789		while (j >= 0 && isl_int_is_zero(bmap->eq[i][1 + total + j]))
790			--j;
791		if (j < 0)
792			break;
793		if (isl_seq_first_non_zero(bmap->eq[i] + 1 + total, j) != -1)
794			return 0;
795	}
796	return i;
797}
798
799/* Normalize divs that appear in equalities.
800 *
801 * In particular, we assume that bmap contains some equalities
802 * of the form
803 *
804 *	a x = m * e_i
805 *
806 * and we want to replace the set of e_i by a minimal set and
807 * such that the new e_i have a canonical representation in terms
808 * of the vector x.
809 * If any of the equalities involves more than one divs, then
810 * we currently simply bail out.
811 *
812 * Let us first additionally assume that all equalities involve
813 * a div.  The equalities then express modulo constraints on the
814 * remaining variables and we can use "parameter compression"
815 * to find a minimal set of constraints.  The result is a transformation
816 *
817 *	x = T(x') = x_0 + G x'
818 *
819 * with G a lower-triangular matrix with all elements below the diagonal
820 * non-negative and smaller than the diagonal element on the same row.
821 * We first normalize x_0 by making the same property hold in the affine
822 * T matrix.
823 * The rows i of G with a 1 on the diagonal do not impose any modulo
824 * constraint and simply express x_i = x'_i.
825 * For each of the remaining rows i, we introduce a div and a corresponding
826 * equality.  In particular
827 *
828 *	g_ii e_j = x_i - g_i(x')
829 *
830 * where each x'_k is replaced either by x_k (if g_kk = 1) or the
831 * corresponding div (if g_kk != 1).
832 *
833 * If there are any equalities not involving any div, then we
834 * first apply a variable compression on the variables x:
835 *
836 *	x = C x''	x'' = C_2 x
837 *
838 * and perform the above parameter compression on A C instead of on A.
839 * The resulting compression is then of the form
840 *
841 *	x'' = T(x') = x_0 + G x'
842 *
843 * and in constructing the new divs and the corresponding equalities,
844 * we have to replace each x'', i.e., the x'_k with (g_kk = 1),
845 * by the corresponding row from C_2.
846 */
847static struct isl_basic_map *normalize_divs(
848	struct isl_basic_map *bmap, int *progress)
849{
850	int i, j, k;
851	int total;
852	int div_eq;
853	struct isl_mat *B;
854	struct isl_vec *d;
855	struct isl_mat *T = NULL;
856	struct isl_mat *C = NULL;
857	struct isl_mat *C2 = NULL;
858	isl_int v;
859	int *pos;
860	int dropped, needed;
861
862	if (!bmap)
863		return NULL;
864
865	if (bmap->n_div == 0)
866		return bmap;
867
868	if (bmap->n_eq == 0)
869		return bmap;
870
871	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS))
872		return bmap;
873
874	total = isl_space_dim(bmap->dim, isl_dim_all);
875	div_eq = n_pure_div_eq(bmap);
876	if (div_eq == 0)
877		return bmap;
878
879	if (div_eq < bmap->n_eq) {
880		B = isl_mat_sub_alloc6(bmap->ctx, bmap->eq, div_eq,
881					bmap->n_eq - div_eq, 0, 1 + total);
882		C = isl_mat_variable_compression(B, &C2);
883		if (!C || !C2)
884			goto error;
885		if (C->n_col == 0) {
886			bmap = isl_basic_map_set_to_empty(bmap);
887			isl_mat_free(C);
888			isl_mat_free(C2);
889			goto done;
890		}
891	}
892
893	d = isl_vec_alloc(bmap->ctx, div_eq);
894	if (!d)
895		goto error;
896	for (i = 0, j = bmap->n_div-1; i < div_eq; ++i) {
897		while (j >= 0 && isl_int_is_zero(bmap->eq[i][1 + total + j]))
898			--j;
899		isl_int_set(d->block.data[i], bmap->eq[i][1 + total + j]);
900	}
901	B = isl_mat_sub_alloc6(bmap->ctx, bmap->eq, 0, div_eq, 0, 1 + total);
902
903	if (C) {
904		B = isl_mat_product(B, C);
905		C = NULL;
906	}
907
908	T = isl_mat_parameter_compression(B, d);
909	if (!T)
910		goto error;
911	if (T->n_col == 0) {
912		bmap = isl_basic_map_set_to_empty(bmap);
913		isl_mat_free(C2);
914		isl_mat_free(T);
915		goto done;
916	}
917	isl_int_init(v);
918	for (i = 0; i < T->n_row - 1; ++i) {
919		isl_int_fdiv_q(v, T->row[1 + i][0], T->row[1 + i][1 + i]);
920		if (isl_int_is_zero(v))
921			continue;
922		isl_mat_col_submul(T, 0, v, 1 + i);
923	}
924	isl_int_clear(v);
925	pos = isl_alloc_array(bmap->ctx, int, T->n_row);
926	if (!pos)
927		goto error;
928	/* We have to be careful because dropping equalities may reorder them */
929	dropped = 0;
930	for (j = bmap->n_div - 1; j >= 0; --j) {
931		for (i = 0; i < bmap->n_eq; ++i)
932			if (!isl_int_is_zero(bmap->eq[i][1 + total + j]))
933				break;
934		if (i < bmap->n_eq) {
935			bmap = isl_basic_map_drop_div(bmap, j);
936			isl_basic_map_drop_equality(bmap, i);
937			++dropped;
938		}
939	}
940	pos[0] = 0;
941	needed = 0;
942	for (i = 1; i < T->n_row; ++i) {
943		if (isl_int_is_one(T->row[i][i]))
944			pos[i] = i;
945		else
946			needed++;
947	}
948	if (needed > dropped) {
949		bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
950				needed, needed, 0);
951		if (!bmap)
952			goto error;
953	}
954	for (i = 1; i < T->n_row; ++i) {
955		if (isl_int_is_one(T->row[i][i]))
956			continue;
957		k = isl_basic_map_alloc_div(bmap);
958		pos[i] = 1 + total + k;
959		isl_seq_clr(bmap->div[k] + 1, 1 + total + bmap->n_div);
960		isl_int_set(bmap->div[k][0], T->row[i][i]);
961		if (C2)
962			isl_seq_cpy(bmap->div[k] + 1, C2->row[i], 1 + total);
963		else
964			isl_int_set_si(bmap->div[k][1 + i], 1);
965		for (j = 0; j < i; ++j) {
966			if (isl_int_is_zero(T->row[i][j]))
967				continue;
968			if (pos[j] < T->n_row && C2)
969				isl_seq_submul(bmap->div[k] + 1, T->row[i][j],
970						C2->row[pos[j]], 1 + total);
971			else
972				isl_int_neg(bmap->div[k][1 + pos[j]],
973								T->row[i][j]);
974		}
975		j = isl_basic_map_alloc_equality(bmap);
976		isl_seq_neg(bmap->eq[j], bmap->div[k]+1, 1+total+bmap->n_div);
977		isl_int_set(bmap->eq[j][pos[i]], bmap->div[k][0]);
978	}
979	free(pos);
980	isl_mat_free(C2);
981	isl_mat_free(T);
982
983	if (progress)
984		*progress = 1;
985done:
986	ISL_F_SET(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
987
988	return bmap;
989error:
990	isl_mat_free(C);
991	isl_mat_free(C2);
992	isl_mat_free(T);
993	return bmap;
994}
995
996static struct isl_basic_map *set_div_from_lower_bound(
997	struct isl_basic_map *bmap, int div, int ineq)
998{
999	unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
1000
1001	isl_seq_neg(bmap->div[div] + 1, bmap->ineq[ineq], total + bmap->n_div);
1002	isl_int_set(bmap->div[div][0], bmap->ineq[ineq][total + div]);
1003	isl_int_add(bmap->div[div][1], bmap->div[div][1], bmap->div[div][0]);
1004	isl_int_sub_ui(bmap->div[div][1], bmap->div[div][1], 1);
1005	isl_int_set_si(bmap->div[div][1 + total + div], 0);
1006
1007	return bmap;
1008}
1009
1010/* Check whether it is ok to define a div based on an inequality.
1011 * To avoid the introduction of circular definitions of divs, we
1012 * do not allow such a definition if the resulting expression would refer to
1013 * any other undefined divs or if any known div is defined in
1014 * terms of the unknown div.
1015 */
1016static int ok_to_set_div_from_bound(struct isl_basic_map *bmap,
1017	int div, int ineq)
1018{
1019	int j;
1020	unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
1021
1022	/* Not defined in terms of unknown divs */
1023	for (j = 0; j < bmap->n_div; ++j) {
1024		if (div == j)
1025			continue;
1026		if (isl_int_is_zero(bmap->ineq[ineq][total + j]))
1027			continue;
1028		if (isl_int_is_zero(bmap->div[j][0]))
1029			return 0;
1030	}
1031
1032	/* No other div defined in terms of this one => avoid loops */
1033	for (j = 0; j < bmap->n_div; ++j) {
1034		if (div == j)
1035			continue;
1036		if (isl_int_is_zero(bmap->div[j][0]))
1037			continue;
1038		if (!isl_int_is_zero(bmap->div[j][1 + total + div]))
1039			return 0;
1040	}
1041
1042	return 1;
1043}
1044
1045/* Would an expression for div "div" based on inequality "ineq" of "bmap"
1046 * be a better expression than the current one?
1047 *
1048 * If we do not have any expression yet, then any expression would be better.
1049 * Otherwise we check if the last variable involved in the inequality
1050 * (disregarding the div that it would define) is in an earlier position
1051 * than the last variable involved in the current div expression.
1052 */
1053static int better_div_constraint(__isl_keep isl_basic_map *bmap,
1054	int div, int ineq)
1055{
1056	unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
1057	int last_div;
1058	int last_ineq;
1059
1060	if (isl_int_is_zero(bmap->div[div][0]))
1061		return 1;
1062
1063	if (isl_seq_last_non_zero(bmap->ineq[ineq] + total + div + 1,
1064				  bmap->n_div - (div + 1)) >= 0)
1065		return 0;
1066
1067	last_ineq = isl_seq_last_non_zero(bmap->ineq[ineq], total + div);
1068	last_div = isl_seq_last_non_zero(bmap->div[div] + 1,
1069					 total + bmap->n_div);
1070
1071	return last_ineq < last_div;
1072}
1073
1074/* Given two constraints "k" and "l" that are opposite to each other,
1075 * except for the constant term, check if we can use them
1076 * to obtain an expression for one of the hitherto unknown divs or
1077 * a "better" expression for a div for which we already have an expression.
1078 * "sum" is the sum of the constant terms of the constraints.
1079 * If this sum is strictly smaller than the coefficient of one
1080 * of the divs, then this pair can be used define the div.
1081 * To avoid the introduction of circular definitions of divs, we
1082 * do not use the pair if the resulting expression would refer to
1083 * any other undefined divs or if any known div is defined in
1084 * terms of the unknown div.
1085 */
1086static struct isl_basic_map *check_for_div_constraints(
1087	struct isl_basic_map *bmap, int k, int l, isl_int sum, int *progress)
1088{
1089	int i;
1090	unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
1091
1092	for (i = 0; i < bmap->n_div; ++i) {
1093		if (isl_int_is_zero(bmap->ineq[k][total + i]))
1094			continue;
1095		if (isl_int_abs_ge(sum, bmap->ineq[k][total + i]))
1096			continue;
1097		if (!better_div_constraint(bmap, i, k))
1098			continue;
1099		if (!ok_to_set_div_from_bound(bmap, i, k))
1100			break;
1101		if (isl_int_is_pos(bmap->ineq[k][total + i]))
1102			bmap = set_div_from_lower_bound(bmap, i, k);
1103		else
1104			bmap = set_div_from_lower_bound(bmap, i, l);
1105		if (progress)
1106			*progress = 1;
1107		break;
1108	}
1109	return bmap;
1110}
1111
1112static struct isl_basic_map *remove_duplicate_constraints(
1113	struct isl_basic_map *bmap, int *progress, int detect_divs)
1114{
1115	unsigned int size;
1116	isl_int ***index;
1117	int k, l, h;
1118	int bits;
1119	unsigned total = isl_basic_map_total_dim(bmap);
1120	isl_int sum;
1121	isl_ctx *ctx;
1122
1123	if (!bmap || bmap->n_ineq <= 1)
1124		return bmap;
1125
1126	size = round_up(4 * (bmap->n_ineq+1) / 3 - 1);
1127	bits = ffs(size) - 1;
1128	ctx = isl_basic_map_get_ctx(bmap);
1129	index = isl_calloc_array(ctx, isl_int **, size);
1130	if (!index)
1131		return bmap;
1132
1133	index[isl_seq_get_hash_bits(bmap->ineq[0]+1, total, bits)] = &bmap->ineq[0];
1134	for (k = 1; k < bmap->n_ineq; ++k) {
1135		h = hash_index(index, size, bits, bmap, k);
1136		if (!index[h]) {
1137			index[h] = &bmap->ineq[k];
1138			continue;
1139		}
1140		if (progress)
1141			*progress = 1;
1142		l = index[h] - &bmap->ineq[0];
1143		if (isl_int_lt(bmap->ineq[k][0], bmap->ineq[l][0]))
1144			swap_inequality(bmap, k, l);
1145		isl_basic_map_drop_inequality(bmap, k);
1146		--k;
1147	}
1148	isl_int_init(sum);
1149	for (k = 0; k < bmap->n_ineq-1; ++k) {
1150		isl_seq_neg(bmap->ineq[k]+1, bmap->ineq[k]+1, total);
1151		h = hash_index(index, size, bits, bmap, k);
1152		isl_seq_neg(bmap->ineq[k]+1, bmap->ineq[k]+1, total);
1153		if (!index[h])
1154			continue;
1155		l = index[h] - &bmap->ineq[0];
1156		isl_int_add(sum, bmap->ineq[k][0], bmap->ineq[l][0]);
1157		if (isl_int_is_pos(sum)) {
1158			if (detect_divs)
1159				bmap = check_for_div_constraints(bmap, k, l,
1160								 sum, progress);
1161			continue;
1162		}
1163		if (isl_int_is_zero(sum)) {
1164			/* We need to break out of the loop after these
1165			 * changes since the contents of the hash
1166			 * will no longer be valid.
1167			 * Plus, we probably we want to regauss first.
1168			 */
1169			if (progress)
1170				*progress = 1;
1171			isl_basic_map_drop_inequality(bmap, l);
1172			isl_basic_map_inequality_to_equality(bmap, k);
1173		} else
1174			bmap = isl_basic_map_set_to_empty(bmap);
1175		break;
1176	}
1177	isl_int_clear(sum);
1178
1179	free(index);
1180	return bmap;
1181}
1182
1183
1184/* Eliminate knowns divs from constraints where they appear with
1185 * a (positive or negative) unit coefficient.
1186 *
1187 * That is, replace
1188 *
1189 *	floor(e/m) + f >= 0
1190 *
1191 * by
1192 *
1193 *	e + m f >= 0
1194 *
1195 * and
1196 *
1197 *	-floor(e/m) + f >= 0
1198 *
1199 * by
1200 *
1201 *	-e + m f + m - 1 >= 0
1202 *
1203 * The first conversion is valid because floor(e/m) >= -f is equivalent
1204 * to e/m >= -f because -f is an integral expression.
1205 * The second conversion follows from the fact that
1206 *
1207 *	-floor(e/m) = ceil(-e/m) = floor((-e + m - 1)/m)
1208 *
1209 *
1210 * Note that one of the div constraints may have been eliminated
1211 * due to being redundant with respect to the constraint that is
1212 * being modified by this function.  The modified constraint may
1213 * no longer imply this div constraint, so we add it back to make
1214 * sure we do not lose any information.
1215 *
1216 * We skip integral divs, i.e., those with denominator 1, as we would
1217 * risk eliminating the div from the div constraints.  We do not need
1218 * to handle those divs here anyway since the div constraints will turn
1219 * out to form an equality and this equality can then be use to eliminate
1220 * the div from all constraints.
1221 */
1222static __isl_give isl_basic_map *eliminate_unit_divs(
1223	__isl_take isl_basic_map *bmap, int *progress)
1224{
1225	int i, j;
1226	isl_ctx *ctx;
1227	unsigned total;
1228
1229	if (!bmap)
1230		return NULL;
1231
1232	ctx = isl_basic_map_get_ctx(bmap);
1233	total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
1234
1235	for (i = 0; i < bmap->n_div; ++i) {
1236		if (isl_int_is_zero(bmap->div[i][0]))
1237			continue;
1238		if (isl_int_is_one(bmap->div[i][0]))
1239			continue;
1240		for (j = 0; j < bmap->n_ineq; ++j) {
1241			int s;
1242
1243			if (!isl_int_is_one(bmap->ineq[j][total + i]) &&
1244			    !isl_int_is_negone(bmap->ineq[j][total + i]))
1245				continue;
1246
1247			*progress = 1;
1248
1249			s = isl_int_sgn(bmap->ineq[j][total + i]);
1250			isl_int_set_si(bmap->ineq[j][total + i], 0);
1251			if (s < 0)
1252				isl_seq_combine(bmap->ineq[j],
1253					ctx->negone, bmap->div[i] + 1,
1254					bmap->div[i][0], bmap->ineq[j],
1255					total + bmap->n_div);
1256			else
1257				isl_seq_combine(bmap->ineq[j],
1258					ctx->one, bmap->div[i] + 1,
1259					bmap->div[i][0], bmap->ineq[j],
1260					total + bmap->n_div);
1261			if (s < 0) {
1262				isl_int_add(bmap->ineq[j][0],
1263					bmap->ineq[j][0], bmap->div[i][0]);
1264				isl_int_sub_ui(bmap->ineq[j][0],
1265					bmap->ineq[j][0], 1);
1266			}
1267
1268			bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
1269			if (isl_basic_map_add_div_constraint(bmap, i, s) < 0)
1270				return isl_basic_map_free(bmap);
1271		}
1272	}
1273
1274	return bmap;
1275}
1276
1277struct isl_basic_map *isl_basic_map_simplify(struct isl_basic_map *bmap)
1278{
1279	int progress = 1;
1280	if (!bmap)
1281		return NULL;
1282	while (progress) {
1283		progress = 0;
1284		if (!bmap)
1285			break;
1286		if (isl_basic_map_plain_is_empty(bmap))
1287			break;
1288		bmap = isl_basic_map_normalize_constraints(bmap);
1289		bmap = normalize_div_expressions(bmap);
1290		bmap = remove_duplicate_divs(bmap, &progress);
1291		bmap = eliminate_unit_divs(bmap, &progress);
1292		bmap = eliminate_divs_eq(bmap, &progress);
1293		bmap = eliminate_divs_ineq(bmap, &progress);
1294		bmap = isl_basic_map_gauss(bmap, &progress);
1295		/* requires equalities in normal form */
1296		bmap = normalize_divs(bmap, &progress);
1297		bmap = remove_duplicate_constraints(bmap, &progress, 1);
1298	}
1299	return bmap;
1300}
1301
1302struct isl_basic_set *isl_basic_set_simplify(struct isl_basic_set *bset)
1303{
1304	return (struct isl_basic_set *)
1305		isl_basic_map_simplify((struct isl_basic_map *)bset);
1306}
1307
1308
1309int isl_basic_map_is_div_constraint(__isl_keep isl_basic_map *bmap,
1310	isl_int *constraint, unsigned div)
1311{
1312	unsigned pos;
1313
1314	if (!bmap)
1315		return -1;
1316
1317	pos = 1 + isl_space_dim(bmap->dim, isl_dim_all) + div;
1318
1319	if (isl_int_eq(constraint[pos], bmap->div[div][0])) {
1320		int neg;
1321		isl_int_sub(bmap->div[div][1],
1322				bmap->div[div][1], bmap->div[div][0]);
1323		isl_int_add_ui(bmap->div[div][1], bmap->div[div][1], 1);
1324		neg = isl_seq_is_neg(constraint, bmap->div[div]+1, pos);
1325		isl_int_sub_ui(bmap->div[div][1], bmap->div[div][1], 1);
1326		isl_int_add(bmap->div[div][1],
1327				bmap->div[div][1], bmap->div[div][0]);
1328		if (!neg)
1329			return 0;
1330		if (isl_seq_first_non_zero(constraint+pos+1,
1331					    bmap->n_div-div-1) != -1)
1332			return 0;
1333	} else if (isl_int_abs_eq(constraint[pos], bmap->div[div][0])) {
1334		if (!isl_seq_eq(constraint, bmap->div[div]+1, pos))
1335			return 0;
1336		if (isl_seq_first_non_zero(constraint+pos+1,
1337					    bmap->n_div-div-1) != -1)
1338			return 0;
1339	} else
1340		return 0;
1341
1342	return 1;
1343}
1344
1345int isl_basic_set_is_div_constraint(__isl_keep isl_basic_set *bset,
1346	isl_int *constraint, unsigned div)
1347{
1348	return isl_basic_map_is_div_constraint(bset, constraint, div);
1349}
1350
1351
1352/* If the only constraints a div d=floor(f/m)
1353 * appears in are its two defining constraints
1354 *
1355 *	f - m d >=0
1356 *	-(f - (m - 1)) + m d >= 0
1357 *
1358 * then it can safely be removed.
1359 */
1360static int div_is_redundant(struct isl_basic_map *bmap, int div)
1361{
1362	int i;
1363	unsigned pos = 1 + isl_space_dim(bmap->dim, isl_dim_all) + div;
1364
1365	for (i = 0; i < bmap->n_eq; ++i)
1366		if (!isl_int_is_zero(bmap->eq[i][pos]))
1367			return 0;
1368
1369	for (i = 0; i < bmap->n_ineq; ++i) {
1370		if (isl_int_is_zero(bmap->ineq[i][pos]))
1371			continue;
1372		if (!isl_basic_map_is_div_constraint(bmap, bmap->ineq[i], div))
1373			return 0;
1374	}
1375
1376	for (i = 0; i < bmap->n_div; ++i) {
1377		if (isl_int_is_zero(bmap->div[i][0]))
1378			continue;
1379		if (!isl_int_is_zero(bmap->div[i][1+pos]))
1380			return 0;
1381	}
1382
1383	return 1;
1384}
1385
1386/*
1387 * Remove divs that don't occur in any of the constraints or other divs.
1388 * These can arise when dropping some of the variables in a quast
1389 * returned by piplib.
1390 */
1391static struct isl_basic_map *remove_redundant_divs(struct isl_basic_map *bmap)
1392{
1393	int i;
1394
1395	if (!bmap)
1396		return NULL;
1397
1398	for (i = bmap->n_div-1; i >= 0; --i) {
1399		if (!div_is_redundant(bmap, i))
1400			continue;
1401		bmap = isl_basic_map_drop_div(bmap, i);
1402	}
1403	return bmap;
1404}
1405
1406struct isl_basic_map *isl_basic_map_finalize(struct isl_basic_map *bmap)
1407{
1408	bmap = remove_redundant_divs(bmap);
1409	if (!bmap)
1410		return NULL;
1411	ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
1412	return bmap;
1413}
1414
1415struct isl_basic_set *isl_basic_set_finalize(struct isl_basic_set *bset)
1416{
1417	return (struct isl_basic_set *)
1418		isl_basic_map_finalize((struct isl_basic_map *)bset);
1419}
1420
1421struct isl_set *isl_set_finalize(struct isl_set *set)
1422{
1423	int i;
1424
1425	if (!set)
1426		return NULL;
1427	for (i = 0; i < set->n; ++i) {
1428		set->p[i] = isl_basic_set_finalize(set->p[i]);
1429		if (!set->p[i])
1430			goto error;
1431	}
1432	return set;
1433error:
1434	isl_set_free(set);
1435	return NULL;
1436}
1437
1438struct isl_map *isl_map_finalize(struct isl_map *map)
1439{
1440	int i;
1441
1442	if (!map)
1443		return NULL;
1444	for (i = 0; i < map->n; ++i) {
1445		map->p[i] = isl_basic_map_finalize(map->p[i]);
1446		if (!map->p[i])
1447			goto error;
1448	}
1449	ISL_F_CLR(map, ISL_MAP_NORMALIZED);
1450	return map;
1451error:
1452	isl_map_free(map);
1453	return NULL;
1454}
1455
1456
1457/* Remove definition of any div that is defined in terms of the given variable.
1458 * The div itself is not removed.  Functions such as
1459 * eliminate_divs_ineq depend on the other divs remaining in place.
1460 */
1461static struct isl_basic_map *remove_dependent_vars(struct isl_basic_map *bmap,
1462									int pos)
1463{
1464	int i;
1465
1466	if (!bmap)
1467		return NULL;
1468
1469	for (i = 0; i < bmap->n_div; ++i) {
1470		if (isl_int_is_zero(bmap->div[i][0]))
1471			continue;
1472		if (isl_int_is_zero(bmap->div[i][1+1+pos]))
1473			continue;
1474		isl_int_set_si(bmap->div[i][0], 0);
1475	}
1476	return bmap;
1477}
1478
1479/* Eliminate the specified variables from the constraints using
1480 * Fourier-Motzkin.  The variables themselves are not removed.
1481 */
1482struct isl_basic_map *isl_basic_map_eliminate_vars(
1483	struct isl_basic_map *bmap, unsigned pos, unsigned n)
1484{
1485	int d;
1486	int i, j, k;
1487	unsigned total;
1488	int need_gauss = 0;
1489
1490	if (n == 0)
1491		return bmap;
1492	if (!bmap)
1493		return NULL;
1494	total = isl_basic_map_total_dim(bmap);
1495
1496	bmap = isl_basic_map_cow(bmap);
1497	for (d = pos + n - 1; d >= 0 && d >= pos; --d)
1498		bmap = remove_dependent_vars(bmap, d);
1499	if (!bmap)
1500		return NULL;
1501
1502	for (d = pos + n - 1;
1503	     d >= 0 && d >= total - bmap->n_div && d >= pos; --d)
1504		isl_seq_clr(bmap->div[d-(total-bmap->n_div)], 2+total);
1505	for (d = pos + n - 1; d >= 0 && d >= pos; --d) {
1506		int n_lower, n_upper;
1507		if (!bmap)
1508			return NULL;
1509		for (i = 0; i < bmap->n_eq; ++i) {
1510			if (isl_int_is_zero(bmap->eq[i][1+d]))
1511				continue;
1512			eliminate_var_using_equality(bmap, d, bmap->eq[i], 0, NULL);
1513			isl_basic_map_drop_equality(bmap, i);
1514			need_gauss = 1;
1515			break;
1516		}
1517		if (i < bmap->n_eq)
1518			continue;
1519		n_lower = 0;
1520		n_upper = 0;
1521		for (i = 0; i < bmap->n_ineq; ++i) {
1522			if (isl_int_is_pos(bmap->ineq[i][1+d]))
1523				n_lower++;
1524			else if (isl_int_is_neg(bmap->ineq[i][1+d]))
1525				n_upper++;
1526		}
1527		bmap = isl_basic_map_extend_constraints(bmap,
1528				0, n_lower * n_upper);
1529		if (!bmap)
1530			goto error;
1531		for (i = bmap->n_ineq - 1; i >= 0; --i) {
1532			int last;
1533			if (isl_int_is_zero(bmap->ineq[i][1+d]))
1534				continue;
1535			last = -1;
1536			for (j = 0; j < i; ++j) {
1537				if (isl_int_is_zero(bmap->ineq[j][1+d]))
1538					continue;
1539				last = j;
1540				if (isl_int_sgn(bmap->ineq[i][1+d]) ==
1541				    isl_int_sgn(bmap->ineq[j][1+d]))
1542					continue;
1543				k = isl_basic_map_alloc_inequality(bmap);
1544				if (k < 0)
1545					goto error;
1546				isl_seq_cpy(bmap->ineq[k], bmap->ineq[i],
1547						1+total);
1548				isl_seq_elim(bmap->ineq[k], bmap->ineq[j],
1549						1+d, 1+total, NULL);
1550			}
1551			isl_basic_map_drop_inequality(bmap, i);
1552			i = last + 1;
1553		}
1554		if (n_lower > 0 && n_upper > 0) {
1555			bmap = isl_basic_map_normalize_constraints(bmap);
1556			bmap = remove_duplicate_constraints(bmap, NULL, 0);
1557			bmap = isl_basic_map_gauss(bmap, NULL);
1558			bmap = isl_basic_map_remove_redundancies(bmap);
1559			need_gauss = 0;
1560			if (!bmap)
1561				goto error;
1562			if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
1563				break;
1564		}
1565	}
1566	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1567	if (need_gauss)
1568		bmap = isl_basic_map_gauss(bmap, NULL);
1569	return bmap;
1570error:
1571	isl_basic_map_free(bmap);
1572	return NULL;
1573}
1574
1575struct isl_basic_set *isl_basic_set_eliminate_vars(
1576	struct isl_basic_set *bset, unsigned pos, unsigned n)
1577{
1578	return (struct isl_basic_set *)isl_basic_map_eliminate_vars(
1579			(struct isl_basic_map *)bset, pos, n);
1580}
1581
1582/* Eliminate the specified n dimensions starting at first from the
1583 * constraints, without removing the dimensions from the space.
1584 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
1585 * Otherwise, they are projected out and the original space is restored.
1586 */
1587__isl_give isl_basic_map *isl_basic_map_eliminate(
1588	__isl_take isl_basic_map *bmap,
1589	enum isl_dim_type type, unsigned first, unsigned n)
1590{
1591	isl_space *space;
1592
1593	if (!bmap)
1594		return NULL;
1595	if (n == 0)
1596		return bmap;
1597
1598	if (first + n > isl_basic_map_dim(bmap, type) || first + n < first)
1599		isl_die(bmap->ctx, isl_error_invalid,
1600			"index out of bounds", goto error);
1601
1602	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
1603		first += isl_basic_map_offset(bmap, type) - 1;
1604		bmap = isl_basic_map_eliminate_vars(bmap, first, n);
1605		return isl_basic_map_finalize(bmap);
1606	}
1607
1608	space = isl_basic_map_get_space(bmap);
1609	bmap = isl_basic_map_project_out(bmap, type, first, n);
1610	bmap = isl_basic_map_insert_dims(bmap, type, first, n);
1611	bmap = isl_basic_map_reset_space(bmap, space);
1612	return bmap;
1613error:
1614	isl_basic_map_free(bmap);
1615	return NULL;
1616}
1617
1618__isl_give isl_basic_set *isl_basic_set_eliminate(
1619	__isl_take isl_basic_set *bset,
1620	enum isl_dim_type type, unsigned first, unsigned n)
1621{
1622	return isl_basic_map_eliminate(bset, type, first, n);
1623}
1624
1625/* Don't assume equalities are in order, because align_divs
1626 * may have changed the order of the divs.
1627 */
1628static void compute_elimination_index(struct isl_basic_map *bmap, int *elim)
1629{
1630	int d, i;
1631	unsigned total;
1632
1633	total = isl_space_dim(bmap->dim, isl_dim_all);
1634	for (d = 0; d < total; ++d)
1635		elim[d] = -1;
1636	for (i = 0; i < bmap->n_eq; ++i) {
1637		for (d = total - 1; d >= 0; --d) {
1638			if (isl_int_is_zero(bmap->eq[i][1+d]))
1639				continue;
1640			elim[d] = i;
1641			break;
1642		}
1643	}
1644}
1645
1646static void set_compute_elimination_index(struct isl_basic_set *bset, int *elim)
1647{
1648	compute_elimination_index((struct isl_basic_map *)bset, elim);
1649}
1650
1651static int reduced_using_equalities(isl_int *dst, isl_int *src,
1652	struct isl_basic_map *bmap, int *elim)
1653{
1654	int d;
1655	int copied = 0;
1656	unsigned total;
1657
1658	total = isl_space_dim(bmap->dim, isl_dim_all);
1659	for (d = total - 1; d >= 0; --d) {
1660		if (isl_int_is_zero(src[1+d]))
1661			continue;
1662		if (elim[d] == -1)
1663			continue;
1664		if (!copied) {
1665			isl_seq_cpy(dst, src, 1 + total);
1666			copied = 1;
1667		}
1668		isl_seq_elim(dst, bmap->eq[elim[d]], 1 + d, 1 + total, NULL);
1669	}
1670	return copied;
1671}
1672
1673static int set_reduced_using_equalities(isl_int *dst, isl_int *src,
1674	struct isl_basic_set *bset, int *elim)
1675{
1676	return reduced_using_equalities(dst, src,
1677					(struct isl_basic_map *)bset, elim);
1678}
1679
1680static struct isl_basic_set *isl_basic_set_reduce_using_equalities(
1681	struct isl_basic_set *bset, struct isl_basic_set *context)
1682{
1683	int i;
1684	int *elim;
1685
1686	if (!bset || !context)
1687		goto error;
1688
1689	if (context->n_eq == 0) {
1690		isl_basic_set_free(context);
1691		return bset;
1692	}
1693
1694	bset = isl_basic_set_cow(bset);
1695	if (!bset)
1696		goto error;
1697
1698	elim = isl_alloc_array(bset->ctx, int, isl_basic_set_n_dim(bset));
1699	if (!elim)
1700		goto error;
1701	set_compute_elimination_index(context, elim);
1702	for (i = 0; i < bset->n_eq; ++i)
1703		set_reduced_using_equalities(bset->eq[i], bset->eq[i],
1704							context, elim);
1705	for (i = 0; i < bset->n_ineq; ++i)
1706		set_reduced_using_equalities(bset->ineq[i], bset->ineq[i],
1707							context, elim);
1708	isl_basic_set_free(context);
1709	free(elim);
1710	bset = isl_basic_set_simplify(bset);
1711	bset = isl_basic_set_finalize(bset);
1712	return bset;
1713error:
1714	isl_basic_set_free(bset);
1715	isl_basic_set_free(context);
1716	return NULL;
1717}
1718
1719static struct isl_basic_set *remove_shifted_constraints(
1720	struct isl_basic_set *bset, struct isl_basic_set *context)
1721{
1722	unsigned int size;
1723	isl_int ***index;
1724	int bits;
1725	int k, h, l;
1726	isl_ctx *ctx;
1727
1728	if (!bset)
1729		return NULL;
1730
1731	size = round_up(4 * (context->n_ineq+1) / 3 - 1);
1732	bits = ffs(size) - 1;
1733	ctx = isl_basic_set_get_ctx(bset);
1734	index = isl_calloc_array(ctx, isl_int **, size);
1735	if (!index)
1736		return bset;
1737
1738	for (k = 0; k < context->n_ineq; ++k) {
1739		h = set_hash_index(index, size, bits, context, k);
1740		index[h] = &context->ineq[k];
1741	}
1742	for (k = 0; k < bset->n_ineq; ++k) {
1743		h = set_hash_index(index, size, bits, bset, k);
1744		if (!index[h])
1745			continue;
1746		l = index[h] - &context->ineq[0];
1747		if (isl_int_lt(bset->ineq[k][0], context->ineq[l][0]))
1748			continue;
1749		bset = isl_basic_set_cow(bset);
1750		if (!bset)
1751			goto error;
1752		isl_basic_set_drop_inequality(bset, k);
1753		--k;
1754	}
1755	free(index);
1756	return bset;
1757error:
1758	free(index);
1759	return bset;
1760}
1761
1762/* Does the (linear part of a) constraint "c" involve any of the "len"
1763 * "relevant" dimensions?
1764 */
1765static int is_related(isl_int *c, int len, int *relevant)
1766{
1767	int i;
1768
1769	for (i = 0; i < len; ++i) {
1770		if (!relevant[i])
1771			continue;
1772		if (!isl_int_is_zero(c[i]))
1773			return 1;
1774	}
1775
1776	return 0;
1777}
1778
1779/* Drop constraints from "bset" that do not involve any of
1780 * the dimensions marked "relevant".
1781 */
1782static __isl_give isl_basic_set *drop_unrelated_constraints(
1783	__isl_take isl_basic_set *bset, int *relevant)
1784{
1785	int i, dim;
1786
1787	dim = isl_basic_set_dim(bset, isl_dim_set);
1788	for (i = 0; i < dim; ++i)
1789		if (!relevant[i])
1790			break;
1791	if (i >= dim)
1792		return bset;
1793
1794	for (i = bset->n_eq - 1; i >= 0; --i)
1795		if (!is_related(bset->eq[i] + 1, dim, relevant))
1796			isl_basic_set_drop_equality(bset, i);
1797
1798	for (i = bset->n_ineq - 1; i >= 0; --i)
1799		if (!is_related(bset->ineq[i] + 1, dim, relevant))
1800			isl_basic_set_drop_inequality(bset, i);
1801
1802	return bset;
1803}
1804
1805/* Update the groups in "group" based on the (linear part of a) constraint "c".
1806 *
1807 * In particular, for any variable involved in the constraint,
1808 * find the actual group id from before and replace the group
1809 * of the corresponding variable by the minimal group of all
1810 * the variables involved in the constraint considered so far
1811 * (if this minimum is smaller) or replace the minimum by this group
1812 * (if the minimum is larger).
1813 *
1814 * At the end, all the variables in "c" will (indirectly) point
1815 * to the minimal of the groups that they referred to originally.
1816 */
1817static void update_groups(int dim, int *group, isl_int *c)
1818{
1819	int j;
1820	int min = dim;
1821
1822	for (j = 0; j < dim; ++j) {
1823		if (isl_int_is_zero(c[j]))
1824			continue;
1825		while (group[j] >= 0 && group[group[j]] != group[j])
1826			group[j] = group[group[j]];
1827		if (group[j] == min)
1828			continue;
1829		if (group[j] < min) {
1830			if (min >= 0 && min < dim)
1831				group[min] = group[j];
1832			min = group[j];
1833		} else
1834			group[group[j]] = min;
1835	}
1836}
1837
1838/* Drop constraints from "context" that are irrelevant for computing
1839 * the gist of "bset".
1840 *
1841 * In particular, drop constraints in variables that are not related
1842 * to any of the variables involved in the constraints of "bset"
1843 * in the sense that there is no sequence of constraints that connects them.
1844 *
1845 * We construct groups of variables that collect variables that
1846 * (indirectly) appear in some common constraint of "context".
1847 * Each group is identified by the first variable in the group,
1848 * except for the special group of variables that appear in "bset"
1849 * (or are related to those variables), which is identified by -1.
1850 * If group[i] is equal to i (or -1), then the group of i is i (or -1),
1851 * otherwise the group of i is the group of group[i].
1852 *
1853 * We first initialize the -1 group with the variables that appear in "bset".
1854 * Then we initialize groups for the remaining variables.
1855 * Then we iterate over the constraints of "context" and update the
1856 * group of the variables in the constraint by the smallest group.
1857 * Finally, we resolve indirect references to groups by running over
1858 * the variables.
1859 *
1860 * After computing the groups, we drop constraints that do not involve
1861 * any variables in the -1 group.
1862 */
1863static __isl_give isl_basic_set *drop_irrelevant_constraints(
1864	__isl_take isl_basic_set *context, __isl_keep isl_basic_set *bset)
1865{
1866	isl_ctx *ctx;
1867	int *group;
1868	int dim;
1869	int i, j;
1870	int last;
1871
1872	if (!context || !bset)
1873		return isl_basic_set_free(context);
1874
1875	dim = isl_basic_set_dim(bset, isl_dim_set);
1876	ctx = isl_basic_set_get_ctx(bset);
1877	group = isl_calloc_array(ctx, int, dim);
1878
1879	if (!group)
1880		goto error;
1881
1882	for (i = 0; i < dim; ++i) {
1883		for (j = 0; j < bset->n_eq; ++j)
1884			if (!isl_int_is_zero(bset->eq[j][1 + i]))
1885				break;
1886		if (j < bset->n_eq) {
1887			group[i] = -1;
1888			continue;
1889		}
1890		for (j = 0; j < bset->n_ineq; ++j)
1891			if (!isl_int_is_zero(bset->ineq[j][1 + i]))
1892				break;
1893		if (j < bset->n_ineq)
1894			group[i] = -1;
1895	}
1896
1897	last = -1;
1898	for (i = 0; i < dim; ++i)
1899		if (group[i] >= 0)
1900			last = group[i] = i;
1901	if (last < 0) {
1902		free(group);
1903		return context;
1904	}
1905
1906	for (i = 0; i < context->n_eq; ++i)
1907		update_groups(dim, group, context->eq[i] + 1);
1908	for (i = 0; i < context->n_ineq; ++i)
1909		update_groups(dim, group, context->ineq[i] + 1);
1910
1911	for (i = 0; i < dim; ++i)
1912		if (group[i] >= 0)
1913			group[i] = group[group[i]];
1914
1915	for (i = 0; i < dim; ++i)
1916		group[i] = group[i] == -1;
1917
1918	context = drop_unrelated_constraints(context, group);
1919
1920	free(group);
1921	return context;
1922error:
1923	free(group);
1924	return isl_basic_set_free(context);
1925}
1926
1927/* Remove all information from bset that is redundant in the context
1928 * of context.  Both bset and context are assumed to be full-dimensional.
1929 *
1930 * We first remove the inequalities from "bset"
1931 * that are obviously redundant with respect to some inequality in "context".
1932 * Then we remove those constraints from "context" that have become
1933 * irrelevant for computing the gist of "bset".
1934 * Note that this removal of constraints cannot be replaced by
1935 * a factorization because factors in "bset" may still be connected
1936 * to each other through constraints in "context".
1937 *
1938 * If there are any inequalities left, we construct a tableau for
1939 * the context and then add the inequalities of "bset".
1940 * Before adding these inequalities, we freeze all constraints such that
1941 * they won't be considered redundant in terms of the constraints of "bset".
1942 * Then we detect all redundant constraints (among the
1943 * constraints that weren't frozen), first by checking for redundancy in the
1944 * the tableau and then by checking if replacing a constraint by its negation
1945 * would lead to an empty set.  This last step is fairly expensive
1946 * and could be optimized by more reuse of the tableau.
1947 * Finally, we update bset according to the results.
1948 */
1949static __isl_give isl_basic_set *uset_gist_full(__isl_take isl_basic_set *bset,
1950	__isl_take isl_basic_set *context)
1951{
1952	int i, k;
1953	isl_basic_set *combined = NULL;
1954	struct isl_tab *tab = NULL;
1955	unsigned context_ineq;
1956	unsigned total;
1957
1958	if (!bset || !context)
1959		goto error;
1960
1961	if (isl_basic_set_is_universe(bset)) {
1962		isl_basic_set_free(context);
1963		return bset;
1964	}
1965
1966	if (isl_basic_set_is_universe(context)) {
1967		isl_basic_set_free(context);
1968		return bset;
1969	}
1970
1971	bset = remove_shifted_constraints(bset, context);
1972	if (!bset)
1973		goto error;
1974	if (bset->n_ineq == 0)
1975		goto done;
1976
1977	context = drop_irrelevant_constraints(context, bset);
1978	if (!context)
1979		goto error;
1980	if (isl_basic_set_is_universe(context)) {
1981		isl_basic_set_free(context);
1982		return bset;
1983	}
1984
1985	context_ineq = context->n_ineq;
1986	combined = isl_basic_set_cow(isl_basic_set_copy(context));
1987	combined = isl_basic_set_extend_constraints(combined, 0, bset->n_ineq);
1988	tab = isl_tab_from_basic_set(combined, 0);
1989	for (i = 0; i < context_ineq; ++i)
1990		if (isl_tab_freeze_constraint(tab, i) < 0)
1991			goto error;
1992	tab = isl_tab_extend(tab, bset->n_ineq);
1993	for (i = 0; i < bset->n_ineq; ++i)
1994		if (isl_tab_add_ineq(tab, bset->ineq[i]) < 0)
1995			goto error;
1996	bset = isl_basic_set_add_constraints(combined, bset, 0);
1997	combined = NULL;
1998	if (!bset)
1999		goto error;
2000	if (isl_tab_detect_redundant(tab) < 0)
2001		goto error;
2002	total = isl_basic_set_total_dim(bset);
2003	for (i = context_ineq; i < bset->n_ineq; ++i) {
2004		int is_empty;
2005		if (tab->con[i].is_redundant)
2006			continue;
2007		tab->con[i].is_redundant = 1;
2008		combined = isl_basic_set_dup(bset);
2009		combined = isl_basic_set_update_from_tab(combined, tab);
2010		combined = isl_basic_set_extend_constraints(combined, 0, 1);
2011		k = isl_basic_set_alloc_inequality(combined);
2012		if (k < 0)
2013			goto error;
2014		isl_seq_neg(combined->ineq[k], bset->ineq[i], 1 + total);
2015		isl_int_sub_ui(combined->ineq[k][0], combined->ineq[k][0], 1);
2016		is_empty = isl_basic_set_is_empty(combined);
2017		if (is_empty < 0)
2018			goto error;
2019		isl_basic_set_free(combined);
2020		combined = NULL;
2021		if (!is_empty)
2022			tab->con[i].is_redundant = 0;
2023	}
2024	for (i = 0; i < context_ineq; ++i)
2025		tab->con[i].is_redundant = 1;
2026	bset = isl_basic_set_update_from_tab(bset, tab);
2027	if (bset) {
2028		ISL_F_SET(bset, ISL_BASIC_SET_NO_IMPLICIT);
2029		ISL_F_SET(bset, ISL_BASIC_SET_NO_REDUNDANT);
2030	}
2031
2032	isl_tab_free(tab);
2033done:
2034	bset = isl_basic_set_simplify(bset);
2035	bset = isl_basic_set_finalize(bset);
2036	isl_basic_set_free(context);
2037	return bset;
2038error:
2039	isl_tab_free(tab);
2040	isl_basic_set_free(combined);
2041	isl_basic_set_free(context);
2042	isl_basic_set_free(bset);
2043	return NULL;
2044}
2045
2046/* Remove all information from bset that is redundant in the context
2047 * of context.  In particular, equalities that are linear combinations
2048 * of those in context are removed.  Then the inequalities that are
2049 * redundant in the context of the equalities and inequalities of
2050 * context are removed.
2051 *
2052 * First of all, we drop those constraints from "context"
2053 * that are irrelevant for computing the gist of "bset".
2054 * Alternatively, we could factorize the intersection of "context" and "bset".
2055 *
2056 * We first compute the integer affine hull of the intersection,
2057 * compute the gist inside this affine hull and then add back
2058 * those equalities that are not implied by the context.
2059 *
2060 * If two constraints are mutually redundant, then uset_gist_full
2061 * will remove the second of those constraints.  We therefore first
2062 * sort the constraints so that constraints not involving existentially
2063 * quantified variables are given precedence over those that do.
2064 * We have to perform this sorting before the variable compression,
2065 * because that may effect the order of the variables.
2066 */
2067static __isl_give isl_basic_set *uset_gist(__isl_take isl_basic_set *bset,
2068	__isl_take isl_basic_set *context)
2069{
2070	isl_mat *eq;
2071	isl_mat *T, *T2;
2072	isl_basic_set *aff;
2073	isl_basic_set *aff_context;
2074	unsigned total;
2075
2076	if (!bset || !context)
2077		goto error;
2078
2079	context = drop_irrelevant_constraints(context, bset);
2080
2081	bset = isl_basic_set_intersect(bset, isl_basic_set_copy(context));
2082	if (isl_basic_set_plain_is_empty(bset)) {
2083		isl_basic_set_free(context);
2084		return bset;
2085	}
2086	bset = isl_basic_set_sort_constraints(bset);
2087	aff = isl_basic_set_affine_hull(isl_basic_set_copy(bset));
2088	if (!aff)
2089		goto error;
2090	if (isl_basic_set_plain_is_empty(aff)) {
2091		isl_basic_set_free(aff);
2092		isl_basic_set_free(context);
2093		return bset;
2094	}
2095	if (aff->n_eq == 0) {
2096		isl_basic_set_free(aff);
2097		return uset_gist_full(bset, context);
2098	}
2099	total = isl_basic_set_total_dim(bset);
2100	eq = isl_mat_sub_alloc6(bset->ctx, aff->eq, 0, aff->n_eq, 0, 1 + total);
2101	eq = isl_mat_cow(eq);
2102	T = isl_mat_variable_compression(eq, &T2);
2103	if (T && T->n_col == 0) {
2104		isl_mat_free(T);
2105		isl_mat_free(T2);
2106		isl_basic_set_free(context);
2107		isl_basic_set_free(aff);
2108		return isl_basic_set_set_to_empty(bset);
2109	}
2110
2111	aff_context = isl_basic_set_affine_hull(isl_basic_set_copy(context));
2112
2113	bset = isl_basic_set_preimage(bset, isl_mat_copy(T));
2114	context = isl_basic_set_preimage(context, T);
2115
2116	bset = uset_gist_full(bset, context);
2117	bset = isl_basic_set_preimage(bset, T2);
2118	bset = isl_basic_set_intersect(bset, aff);
2119	bset = isl_basic_set_reduce_using_equalities(bset, aff_context);
2120
2121	if (bset) {
2122		ISL_F_SET(bset, ISL_BASIC_SET_NO_IMPLICIT);
2123		ISL_F_SET(bset, ISL_BASIC_SET_NO_REDUNDANT);
2124	}
2125
2126	return bset;
2127error:
2128	isl_basic_set_free(bset);
2129	isl_basic_set_free(context);
2130	return NULL;
2131}
2132
2133/* Normalize the divs in "bmap" in the context of the equalities in "context".
2134 * We simply add the equalities in context to bmap and then do a regular
2135 * div normalizations.  Better results can be obtained by normalizing
2136 * only the divs in bmap than do not also appear in context.
2137 * We need to be careful to reduce the divs using the equalities
2138 * so that later calls to isl_basic_map_overlying_set wouldn't introduce
2139 * spurious constraints.
2140 */
2141static struct isl_basic_map *normalize_divs_in_context(
2142	struct isl_basic_map *bmap, struct isl_basic_map *context)
2143{
2144	int i;
2145	unsigned total_context;
2146	int div_eq;
2147
2148	div_eq = n_pure_div_eq(bmap);
2149	if (div_eq == 0)
2150		return bmap;
2151
2152	if (context->n_div > 0)
2153		bmap = isl_basic_map_align_divs(bmap, context);
2154
2155	total_context = isl_basic_map_total_dim(context);
2156	bmap = isl_basic_map_extend_constraints(bmap, context->n_eq, 0);
2157	for (i = 0; i < context->n_eq; ++i) {
2158		int k;
2159		k = isl_basic_map_alloc_equality(bmap);
2160		if (k < 0)
2161			return isl_basic_map_free(bmap);
2162		isl_seq_cpy(bmap->eq[k], context->eq[i], 1 + total_context);
2163		isl_seq_clr(bmap->eq[k] + 1 + total_context,
2164				isl_basic_map_total_dim(bmap) - total_context);
2165	}
2166	bmap = isl_basic_map_gauss(bmap, NULL);
2167	bmap = normalize_divs(bmap, NULL);
2168	bmap = isl_basic_map_gauss(bmap, NULL);
2169	return bmap;
2170}
2171
2172struct isl_basic_map *isl_basic_map_gist(struct isl_basic_map *bmap,
2173	struct isl_basic_map *context)
2174{
2175	struct isl_basic_set *bset;
2176
2177	if (!bmap || !context)
2178		goto error;
2179
2180	if (isl_basic_map_is_universe(bmap)) {
2181		isl_basic_map_free(context);
2182		return bmap;
2183	}
2184	if (isl_basic_map_plain_is_empty(context)) {
2185		isl_basic_map_free(bmap);
2186		return context;
2187	}
2188	if (isl_basic_map_plain_is_empty(bmap)) {
2189		isl_basic_map_free(context);
2190		return bmap;
2191	}
2192
2193	bmap = isl_basic_map_remove_redundancies(bmap);
2194	context = isl_basic_map_remove_redundancies(context);
2195	if (!context)
2196		goto error;
2197
2198	if (context->n_eq)
2199		bmap = normalize_divs_in_context(bmap, context);
2200
2201	context = isl_basic_map_align_divs(context, bmap);
2202	bmap = isl_basic_map_align_divs(bmap, context);
2203
2204	bset = uset_gist(isl_basic_map_underlying_set(isl_basic_map_copy(bmap)),
2205			 isl_basic_map_underlying_set(context));
2206
2207	return isl_basic_map_overlying_set(bset, bmap);
2208error:
2209	isl_basic_map_free(bmap);
2210	isl_basic_map_free(context);
2211	return NULL;
2212}
2213
2214/*
2215 * Assumes context has no implicit divs.
2216 */
2217__isl_give isl_map *isl_map_gist_basic_map(__isl_take isl_map *map,
2218	__isl_take isl_basic_map *context)
2219{
2220	int i;
2221
2222	if (!map || !context)
2223		goto error;;
2224
2225	if (isl_basic_map_plain_is_empty(context)) {
2226		isl_map_free(map);
2227		return isl_map_from_basic_map(context);
2228	}
2229
2230	context = isl_basic_map_remove_redundancies(context);
2231	map = isl_map_cow(map);
2232	if (!map || !context)
2233		goto error;;
2234	isl_assert(map->ctx, isl_space_is_equal(map->dim, context->dim), goto error);
2235	map = isl_map_compute_divs(map);
2236	if (!map)
2237		goto error;
2238	for (i = map->n - 1; i >= 0; --i) {
2239		map->p[i] = isl_basic_map_gist(map->p[i],
2240						isl_basic_map_copy(context));
2241		if (!map->p[i])
2242			goto error;
2243		if (isl_basic_map_plain_is_empty(map->p[i])) {
2244			isl_basic_map_free(map->p[i]);
2245			if (i != map->n - 1)
2246				map->p[i] = map->p[map->n - 1];
2247			map->n--;
2248		}
2249	}
2250	isl_basic_map_free(context);
2251	ISL_F_CLR(map, ISL_MAP_NORMALIZED);
2252	return map;
2253error:
2254	isl_map_free(map);
2255	isl_basic_map_free(context);
2256	return NULL;
2257}
2258
2259/* Return a map that has the same intersection with "context" as "map"
2260 * and that as "simple" as possible.
2261 *
2262 * If "map" is already the universe, then we cannot make it any simpler.
2263 * Similarly, if "context" is the universe, then we cannot exploit it
2264 * to simplify "map"
2265 * If "map" and "context" are identical to each other, then we can
2266 * return the corresponding universe.
2267 *
2268 * If none of these cases apply, we have to work a bit harder.
2269 */
2270static __isl_give isl_map *map_gist(__isl_take isl_map *map,
2271	__isl_take isl_map *context)
2272{
2273	int equal;
2274	int is_universe;
2275
2276	is_universe = isl_map_plain_is_universe(map);
2277	if (is_universe >= 0 && !is_universe)
2278		is_universe = isl_map_plain_is_universe(context);
2279	if (is_universe < 0)
2280		goto error;
2281	if (is_universe) {
2282		isl_map_free(context);
2283		return map;
2284	}
2285
2286	equal = isl_map_plain_is_equal(map, context);
2287	if (equal < 0)
2288		goto error;
2289	if (equal) {
2290		isl_map *res = isl_map_universe(isl_map_get_space(map));
2291		isl_map_free(map);
2292		isl_map_free(context);
2293		return res;
2294	}
2295
2296	context = isl_map_compute_divs(context);
2297	return isl_map_gist_basic_map(map, isl_map_simple_hull(context));
2298error:
2299	isl_map_free(map);
2300	isl_map_free(context);
2301	return NULL;
2302}
2303
2304__isl_give isl_map *isl_map_gist(__isl_take isl_map *map,
2305	__isl_take isl_map *context)
2306{
2307	return isl_map_align_params_map_map_and(map, context, &map_gist);
2308}
2309
2310struct isl_basic_set *isl_basic_set_gist(struct isl_basic_set *bset,
2311						struct isl_basic_set *context)
2312{
2313	return (struct isl_basic_set *)isl_basic_map_gist(
2314		(struct isl_basic_map *)bset, (struct isl_basic_map *)context);
2315}
2316
2317__isl_give isl_set *isl_set_gist_basic_set(__isl_take isl_set *set,
2318	__isl_take isl_basic_set *context)
2319{
2320	return (struct isl_set *)isl_map_gist_basic_map((struct isl_map *)set,
2321					(struct isl_basic_map *)context);
2322}
2323
2324__isl_give isl_set *isl_set_gist_params_basic_set(__isl_take isl_set *set,
2325	__isl_take isl_basic_set *context)
2326{
2327	isl_space *space = isl_set_get_space(set);
2328	isl_basic_set *dom_context = isl_basic_set_universe(space);
2329	dom_context = isl_basic_set_intersect_params(dom_context, context);
2330	return isl_set_gist_basic_set(set, dom_context);
2331}
2332
2333__isl_give isl_set *isl_set_gist(__isl_take isl_set *set,
2334	__isl_take isl_set *context)
2335{
2336	return (struct isl_set *)isl_map_gist((struct isl_map *)set,
2337					(struct isl_map *)context);
2338}
2339
2340__isl_give isl_map *isl_map_gist_domain(__isl_take isl_map *map,
2341	__isl_take isl_set *context)
2342{
2343	isl_map *map_context = isl_map_universe(isl_map_get_space(map));
2344	map_context = isl_map_intersect_domain(map_context, context);
2345	return isl_map_gist(map, map_context);
2346}
2347
2348__isl_give isl_map *isl_map_gist_range(__isl_take isl_map *map,
2349	__isl_take isl_set *context)
2350{
2351	isl_map *map_context = isl_map_universe(isl_map_get_space(map));
2352	map_context = isl_map_intersect_range(map_context, context);
2353	return isl_map_gist(map, map_context);
2354}
2355
2356__isl_give isl_map *isl_map_gist_params(__isl_take isl_map *map,
2357	__isl_take isl_set *context)
2358{
2359	isl_map *map_context = isl_map_universe(isl_map_get_space(map));
2360	map_context = isl_map_intersect_params(map_context, context);
2361	return isl_map_gist(map, map_context);
2362}
2363
2364__isl_give isl_set *isl_set_gist_params(__isl_take isl_set *set,
2365	__isl_take isl_set *context)
2366{
2367	return isl_map_gist_params(set, context);
2368}
2369
2370/* Quick check to see if two basic maps are disjoint.
2371 * In particular, we reduce the equalities and inequalities of
2372 * one basic map in the context of the equalities of the other
2373 * basic map and check if we get a contradiction.
2374 */
2375int isl_basic_map_plain_is_disjoint(__isl_keep isl_basic_map *bmap1,
2376	__isl_keep isl_basic_map *bmap2)
2377{
2378	struct isl_vec *v = NULL;
2379	int *elim = NULL;
2380	unsigned total;
2381	int i;
2382
2383	if (!bmap1 || !bmap2)
2384		return -1;
2385	isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim),
2386			return -1);
2387	if (bmap1->n_div || bmap2->n_div)
2388		return 0;
2389	if (!bmap1->n_eq && !bmap2->n_eq)
2390		return 0;
2391
2392	total = isl_space_dim(bmap1->dim, isl_dim_all);
2393	if (total == 0)
2394		return 0;
2395	v = isl_vec_alloc(bmap1->ctx, 1 + total);
2396	if (!v)
2397		goto error;
2398	elim = isl_alloc_array(bmap1->ctx, int, total);
2399	if (!elim)
2400		goto error;
2401	compute_elimination_index(bmap1, elim);
2402	for (i = 0; i < bmap2->n_eq; ++i) {
2403		int reduced;
2404		reduced = reduced_using_equalities(v->block.data, bmap2->eq[i],
2405							bmap1, elim);
2406		if (reduced && !isl_int_is_zero(v->block.data[0]) &&
2407		    isl_seq_first_non_zero(v->block.data + 1, total) == -1)
2408			goto disjoint;
2409	}
2410	for (i = 0; i < bmap2->n_ineq; ++i) {
2411		int reduced;
2412		reduced = reduced_using_equalities(v->block.data,
2413						bmap2->ineq[i], bmap1, elim);
2414		if (reduced && isl_int_is_neg(v->block.data[0]) &&
2415		    isl_seq_first_non_zero(v->block.data + 1, total) == -1)
2416			goto disjoint;
2417	}
2418	compute_elimination_index(bmap2, elim);
2419	for (i = 0; i < bmap1->n_ineq; ++i) {
2420		int reduced;
2421		reduced = reduced_using_equalities(v->block.data,
2422						bmap1->ineq[i], bmap2, elim);
2423		if (reduced && isl_int_is_neg(v->block.data[0]) &&
2424		    isl_seq_first_non_zero(v->block.data + 1, total) == -1)
2425			goto disjoint;
2426	}
2427	isl_vec_free(v);
2428	free(elim);
2429	return 0;
2430disjoint:
2431	isl_vec_free(v);
2432	free(elim);
2433	return 1;
2434error:
2435	isl_vec_free(v);
2436	free(elim);
2437	return -1;
2438}
2439
2440int isl_basic_set_plain_is_disjoint(__isl_keep isl_basic_set *bset1,
2441	__isl_keep isl_basic_set *bset2)
2442{
2443	return isl_basic_map_plain_is_disjoint((struct isl_basic_map *)bset1,
2444					      (struct isl_basic_map *)bset2);
2445}
2446
2447/* Are "map1" and "map2" obviously disjoint?
2448 *
2449 * If they have different parameters, then we skip any further tests.
2450 * In particular, the outcome of the subsequent calls to
2451 * isl_space_tuple_match may be affected by the different parameters
2452 * in nested spaces.
2453 *
2454 * If one of them is empty or if they live in different spaces (assuming
2455 * they have the same parameters), then they are clearly disjoint.
2456 *
2457 * If they are obviously equal, but not obviously empty, then we will
2458 * not be able to detect if they are disjoint.
2459 *
2460 * Otherwise we check if each basic map in "map1" is obviously disjoint
2461 * from each basic map in "map2".
2462 */
2463int isl_map_plain_is_disjoint(__isl_keep isl_map *map1,
2464	__isl_keep isl_map *map2)
2465{
2466	int i, j;
2467	int disjoint;
2468	int intersect;
2469	int match;
2470
2471	if (!map1 || !map2)
2472		return -1;
2473
2474	disjoint = isl_map_plain_is_empty(map1);
2475	if (disjoint < 0 || disjoint)
2476		return disjoint;
2477
2478	disjoint = isl_map_plain_is_empty(map2);
2479	if (disjoint < 0 || disjoint)
2480		return disjoint;
2481
2482	match = isl_space_match(map1->dim, isl_dim_param,
2483				map2->dim, isl_dim_param);
2484	if (match < 0 || !match)
2485		return match < 0 ? -1 : 0;
2486
2487	match = isl_space_tuple_match(map1->dim, isl_dim_in,
2488				map2->dim, isl_dim_in);
2489	if (match < 0 || !match)
2490		return match < 0 ? -1 : 1;
2491
2492	match = isl_space_tuple_match(map1->dim, isl_dim_out,
2493				map2->dim, isl_dim_out);
2494	if (match < 0 || !match)
2495		return match < 0 ? -1 : 1;
2496
2497	intersect = isl_map_plain_is_equal(map1, map2);
2498	if (intersect < 0 || intersect)
2499		return intersect < 0 ? -1 : 0;
2500
2501	for (i = 0; i < map1->n; ++i) {
2502		for (j = 0; j < map2->n; ++j) {
2503			int d = isl_basic_map_plain_is_disjoint(map1->p[i],
2504							       map2->p[j]);
2505			if (d != 1)
2506				return d;
2507		}
2508	}
2509	return 1;
2510}
2511
2512/* Are "map1" and "map2" disjoint?
2513 *
2514 * They are disjoint if they are "obviously disjoint" or if one of them
2515 * is empty.  Otherwise, they are not disjoint if one of them is universal.
2516 * If none of these cases apply, we compute the intersection and see if
2517 * the result is empty.
2518 */
2519int isl_map_is_disjoint(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
2520{
2521	int disjoint;
2522	int intersect;
2523	isl_map *test;
2524
2525	disjoint = isl_map_plain_is_disjoint(map1, map2);
2526	if (disjoint < 0 || disjoint)
2527		return disjoint;
2528
2529	disjoint = isl_map_is_empty(map1);
2530	if (disjoint < 0 || disjoint)
2531		return disjoint;
2532
2533	disjoint = isl_map_is_empty(map2);
2534	if (disjoint < 0 || disjoint)
2535		return disjoint;
2536
2537	intersect = isl_map_plain_is_universe(map1);
2538	if (intersect < 0 || intersect)
2539		return intersect < 0 ? -1 : 0;
2540
2541	intersect = isl_map_plain_is_universe(map2);
2542	if (intersect < 0 || intersect)
2543		return intersect < 0 ? -1 : 0;
2544
2545	test = isl_map_intersect(isl_map_copy(map1), isl_map_copy(map2));
2546	disjoint = isl_map_is_empty(test);
2547	isl_map_free(test);
2548
2549	return disjoint;
2550}
2551
2552int isl_set_plain_is_disjoint(__isl_keep isl_set *set1,
2553	__isl_keep isl_set *set2)
2554{
2555	return isl_map_plain_is_disjoint((struct isl_map *)set1,
2556					(struct isl_map *)set2);
2557}
2558
2559/* Are "set1" and "set2" disjoint?
2560 */
2561int isl_set_is_disjoint(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
2562{
2563	return isl_map_is_disjoint(set1, set2);
2564}
2565
2566int isl_set_fast_is_disjoint(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
2567{
2568	return isl_set_plain_is_disjoint(set1, set2);
2569}
2570
2571/* Check if we can combine a given div with lower bound l and upper
2572 * bound u with some other div and if so return that other div.
2573 * Otherwise return -1.
2574 *
2575 * We first check that
2576 *	- the bounds are opposites of each other (except for the constant
2577 *	  term)
2578 *	- the bounds do not reference any other div
2579 *	- no div is defined in terms of this div
2580 *
2581 * Let m be the size of the range allowed on the div by the bounds.
2582 * That is, the bounds are of the form
2583 *
2584 *	e <= a <= e + m - 1
2585 *
2586 * with e some expression in the other variables.
2587 * We look for another div b such that no third div is defined in terms
2588 * of this second div b and such that in any constraint that contains
2589 * a (except for the given lower and upper bound), also contains b
2590 * with a coefficient that is m times that of b.
2591 * That is, all constraints (execpt for the lower and upper bound)
2592 * are of the form
2593 *
2594 *	e + f (a + m b) >= 0
2595 *
2596 * If so, we return b so that "a + m b" can be replaced by
2597 * a single div "c = a + m b".
2598 */
2599static int div_find_coalesce(struct isl_basic_map *bmap, int *pairs,
2600	unsigned div, unsigned l, unsigned u)
2601{
2602	int i, j;
2603	unsigned dim;
2604	int coalesce = -1;
2605
2606	if (bmap->n_div <= 1)
2607		return -1;
2608	dim = isl_space_dim(bmap->dim, isl_dim_all);
2609	if (isl_seq_first_non_zero(bmap->ineq[l] + 1 + dim, div) != -1)
2610		return -1;
2611	if (isl_seq_first_non_zero(bmap->ineq[l] + 1 + dim + div + 1,
2612				   bmap->n_div - div - 1) != -1)
2613		return -1;
2614	if (!isl_seq_is_neg(bmap->ineq[l] + 1, bmap->ineq[u] + 1,
2615			    dim + bmap->n_div))
2616		return -1;
2617
2618	for (i = 0; i < bmap->n_div; ++i) {
2619		if (isl_int_is_zero(bmap->div[i][0]))
2620			continue;
2621		if (!isl_int_is_zero(bmap->div[i][1 + 1 + dim + div]))
2622			return -1;
2623	}
2624
2625	isl_int_add(bmap->ineq[l][0], bmap->ineq[l][0], bmap->ineq[u][0]);
2626	if (isl_int_is_neg(bmap->ineq[l][0])) {
2627		isl_int_sub(bmap->ineq[l][0],
2628			    bmap->ineq[l][0], bmap->ineq[u][0]);
2629		bmap = isl_basic_map_copy(bmap);
2630		bmap = isl_basic_map_set_to_empty(bmap);
2631		isl_basic_map_free(bmap);
2632		return -1;
2633	}
2634	isl_int_add_ui(bmap->ineq[l][0], bmap->ineq[l][0], 1);
2635	for (i = 0; i < bmap->n_div; ++i) {
2636		if (i == div)
2637			continue;
2638		if (!pairs[i])
2639			continue;
2640		for (j = 0; j < bmap->n_div; ++j) {
2641			if (isl_int_is_zero(bmap->div[j][0]))
2642				continue;
2643			if (!isl_int_is_zero(bmap->div[j][1 + 1 + dim + i]))
2644				break;
2645		}
2646		if (j < bmap->n_div)
2647			continue;
2648		for (j = 0; j < bmap->n_ineq; ++j) {
2649			int valid;
2650			if (j == l || j == u)
2651				continue;
2652			if (isl_int_is_zero(bmap->ineq[j][1 + dim + div]))
2653				continue;
2654			if (isl_int_is_zero(bmap->ineq[j][1 + dim + i]))
2655				break;
2656			isl_int_mul(bmap->ineq[j][1 + dim + div],
2657				    bmap->ineq[j][1 + dim + div],
2658				    bmap->ineq[l][0]);
2659			valid = isl_int_eq(bmap->ineq[j][1 + dim + div],
2660					   bmap->ineq[j][1 + dim + i]);
2661			isl_int_divexact(bmap->ineq[j][1 + dim + div],
2662					 bmap->ineq[j][1 + dim + div],
2663					 bmap->ineq[l][0]);
2664			if (!valid)
2665				break;
2666		}
2667		if (j < bmap->n_ineq)
2668			continue;
2669		coalesce = i;
2670		break;
2671	}
2672	isl_int_sub_ui(bmap->ineq[l][0], bmap->ineq[l][0], 1);
2673	isl_int_sub(bmap->ineq[l][0], bmap->ineq[l][0], bmap->ineq[u][0]);
2674	return coalesce;
2675}
2676
2677/* Given a lower and an upper bound on div i, construct an inequality
2678 * that when nonnegative ensures that this pair of bounds always allows
2679 * for an integer value of the given div.
2680 * The lower bound is inequality l, while the upper bound is inequality u.
2681 * The constructed inequality is stored in ineq.
2682 * g, fl, fu are temporary scalars.
2683 *
2684 * Let the upper bound be
2685 *
2686 *	-n_u a + e_u >= 0
2687 *
2688 * and the lower bound
2689 *
2690 *	n_l a + e_l >= 0
2691 *
2692 * Let n_u = f_u g and n_l = f_l g, with g = gcd(n_u, n_l).
2693 * We have
2694 *
2695 *	- f_u e_l <= f_u f_l g a <= f_l e_u
2696 *
2697 * Since all variables are integer valued, this is equivalent to
2698 *
2699 *	- f_u e_l - (f_u - 1) <= f_u f_l g a <= f_l e_u + (f_l - 1)
2700 *
2701 * If this interval is at least f_u f_l g, then it contains at least
2702 * one integer value for a.
2703 * That is, the test constraint is
2704 *
2705 *	f_l e_u + f_u e_l + f_l - 1 + f_u - 1 + 1 >= f_u f_l g
2706 */
2707static void construct_test_ineq(struct isl_basic_map *bmap, int i,
2708	int l, int u, isl_int *ineq, isl_int g, isl_int fl, isl_int fu)
2709{
2710	unsigned dim;
2711	dim = isl_space_dim(bmap->dim, isl_dim_all);
2712
2713	isl_int_gcd(g, bmap->ineq[l][1 + dim + i], bmap->ineq[u][1 + dim + i]);
2714	isl_int_divexact(fl, bmap->ineq[l][1 + dim + i], g);
2715	isl_int_divexact(fu, bmap->ineq[u][1 + dim + i], g);
2716	isl_int_neg(fu, fu);
2717	isl_seq_combine(ineq, fl, bmap->ineq[u], fu, bmap->ineq[l],
2718			1 + dim + bmap->n_div);
2719	isl_int_add(ineq[0], ineq[0], fl);
2720	isl_int_add(ineq[0], ineq[0], fu);
2721	isl_int_sub_ui(ineq[0], ineq[0], 1);
2722	isl_int_mul(g, g, fl);
2723	isl_int_mul(g, g, fu);
2724	isl_int_sub(ineq[0], ineq[0], g);
2725}
2726
2727/* Remove more kinds of divs that are not strictly needed.
2728 * In particular, if all pairs of lower and upper bounds on a div
2729 * are such that they allow at least one integer value of the div,
2730 * the we can eliminate the div using Fourier-Motzkin without
2731 * introducing any spurious solutions.
2732 */
2733static struct isl_basic_map *drop_more_redundant_divs(
2734	struct isl_basic_map *bmap, int *pairs, int n)
2735{
2736	struct isl_tab *tab = NULL;
2737	struct isl_vec *vec = NULL;
2738	unsigned dim;
2739	int remove = -1;
2740	isl_int g, fl, fu;
2741
2742	isl_int_init(g);
2743	isl_int_init(fl);
2744	isl_int_init(fu);
2745
2746	if (!bmap)
2747		goto error;
2748
2749	dim = isl_space_dim(bmap->dim, isl_dim_all);
2750	vec = isl_vec_alloc(bmap->ctx, 1 + dim + bmap->n_div);
2751	if (!vec)
2752		goto error;
2753
2754	tab = isl_tab_from_basic_map(bmap, 0);
2755
2756	while (n > 0) {
2757		int i, l, u;
2758		int best = -1;
2759		enum isl_lp_result res;
2760
2761		for (i = 0; i < bmap->n_div; ++i) {
2762			if (!pairs[i])
2763				continue;
2764			if (best >= 0 && pairs[best] <= pairs[i])
2765				continue;
2766			best = i;
2767		}
2768
2769		i = best;
2770		for (l = 0; l < bmap->n_ineq; ++l) {
2771			if (!isl_int_is_pos(bmap->ineq[l][1 + dim + i]))
2772				continue;
2773			for (u = 0; u < bmap->n_ineq; ++u) {
2774				if (!isl_int_is_neg(bmap->ineq[u][1 + dim + i]))
2775					continue;
2776				construct_test_ineq(bmap, i, l, u,
2777						    vec->el, g, fl, fu);
2778				res = isl_tab_min(tab, vec->el,
2779						  bmap->ctx->one, &g, NULL, 0);
2780				if (res == isl_lp_error)
2781					goto error;
2782				if (res == isl_lp_empty) {
2783					bmap = isl_basic_map_set_to_empty(bmap);
2784					break;
2785				}
2786				if (res != isl_lp_ok || isl_int_is_neg(g))
2787					break;
2788			}
2789			if (u < bmap->n_ineq)
2790				break;
2791		}
2792		if (l == bmap->n_ineq) {
2793			remove = i;
2794			break;
2795		}
2796		pairs[i] = 0;
2797		--n;
2798	}
2799
2800	isl_tab_free(tab);
2801	isl_vec_free(vec);
2802
2803	isl_int_clear(g);
2804	isl_int_clear(fl);
2805	isl_int_clear(fu);
2806
2807	free(pairs);
2808
2809	if (remove < 0)
2810		return bmap;
2811
2812	bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, remove, 1);
2813	return isl_basic_map_drop_redundant_divs(bmap);
2814error:
2815	free(pairs);
2816	isl_basic_map_free(bmap);
2817	isl_tab_free(tab);
2818	isl_vec_free(vec);
2819	isl_int_clear(g);
2820	isl_int_clear(fl);
2821	isl_int_clear(fu);
2822	return NULL;
2823}
2824
2825/* Given a pair of divs div1 and div2 such that, expect for the lower bound l
2826 * and the upper bound u, div1 always occurs together with div2 in the form
2827 * (div1 + m div2), where m is the constant range on the variable div1
2828 * allowed by l and u, replace the pair div1 and div2 by a single
2829 * div that is equal to div1 + m div2.
2830 *
2831 * The new div will appear in the location that contains div2.
2832 * We need to modify all constraints that contain
2833 * div2 = (div - div1) / m
2834 * (If a constraint does not contain div2, it will also not contain div1.)
2835 * If the constraint also contains div1, then we know they appear
2836 * as f (div1 + m div2) and we can simply replace (div1 + m div2) by div,
2837 * i.e., the coefficient of div is f.
2838 *
2839 * Otherwise, we first need to introduce div1 into the constraint.
2840 * Let the l be
2841 *
2842 *	div1 + f >=0
2843 *
2844 * and u
2845 *
2846 *	-div1 + f' >= 0
2847 *
2848 * A lower bound on div2
2849 *
2850 *	n div2 + t >= 0
2851 *
2852 * can be replaced by
2853 *
2854 *	(n * (m div 2 + div1) + m t + n f)/g >= 0
2855 *
2856 * with g = gcd(m,n).
2857 * An upper bound
2858 *
2859 *	-n div2 + t >= 0
2860 *
2861 * can be replaced by
2862 *
2863 *	(-n * (m div2 + div1) + m t + n f')/g >= 0
2864 *
2865 * These constraint are those that we would obtain from eliminating
2866 * div1 using Fourier-Motzkin.
2867 *
2868 * After all constraints have been modified, we drop the lower and upper
2869 * bound and then drop div1.
2870 */
2871static struct isl_basic_map *coalesce_divs(struct isl_basic_map *bmap,
2872	unsigned div1, unsigned div2, unsigned l, unsigned u)
2873{
2874	isl_int a;
2875	isl_int b;
2876	isl_int m;
2877	unsigned dim, total;
2878	int i;
2879
2880	dim = isl_space_dim(bmap->dim, isl_dim_all);
2881	total = 1 + dim + bmap->n_div;
2882
2883	isl_int_init(a);
2884	isl_int_init(b);
2885	isl_int_init(m);
2886	isl_int_add(m, bmap->ineq[l][0], bmap->ineq[u][0]);
2887	isl_int_add_ui(m, m, 1);
2888
2889	for (i = 0; i < bmap->n_ineq; ++i) {
2890		if (i == l || i == u)
2891			continue;
2892		if (isl_int_is_zero(bmap->ineq[i][1 + dim + div2]))
2893			continue;
2894		if (isl_int_is_zero(bmap->ineq[i][1 + dim + div1])) {
2895			isl_int_gcd(b, m, bmap->ineq[i][1 + dim + div2]);
2896			isl_int_divexact(a, m, b);
2897			isl_int_divexact(b, bmap->ineq[i][1 + dim + div2], b);
2898			if (isl_int_is_pos(b)) {
2899				isl_seq_combine(bmap->ineq[i], a, bmap->ineq[i],
2900						b, bmap->ineq[l], total);
2901			} else {
2902				isl_int_neg(b, b);
2903				isl_seq_combine(bmap->ineq[i], a, bmap->ineq[i],
2904						b, bmap->ineq[u], total);
2905			}
2906		}
2907		isl_int_set(bmap->ineq[i][1 + dim + div2],
2908			    bmap->ineq[i][1 + dim + div1]);
2909		isl_int_set_si(bmap->ineq[i][1 + dim + div1], 0);
2910	}
2911
2912	isl_int_clear(a);
2913	isl_int_clear(b);
2914	isl_int_clear(m);
2915	if (l > u) {
2916		isl_basic_map_drop_inequality(bmap, l);
2917		isl_basic_map_drop_inequality(bmap, u);
2918	} else {
2919		isl_basic_map_drop_inequality(bmap, u);
2920		isl_basic_map_drop_inequality(bmap, l);
2921	}
2922	bmap = isl_basic_map_drop_div(bmap, div1);
2923	return bmap;
2924}
2925
2926/* First check if we can coalesce any pair of divs and
2927 * then continue with dropping more redundant divs.
2928 *
2929 * We loop over all pairs of lower and upper bounds on a div
2930 * with coefficient 1 and -1, respectively, check if there
2931 * is any other div "c" with which we can coalesce the div
2932 * and if so, perform the coalescing.
2933 */
2934static struct isl_basic_map *coalesce_or_drop_more_redundant_divs(
2935	struct isl_basic_map *bmap, int *pairs, int n)
2936{
2937	int i, l, u;
2938	unsigned dim;
2939
2940	dim = isl_space_dim(bmap->dim, isl_dim_all);
2941
2942	for (i = 0; i < bmap->n_div; ++i) {
2943		if (!pairs[i])
2944			continue;
2945		for (l = 0; l < bmap->n_ineq; ++l) {
2946			if (!isl_int_is_one(bmap->ineq[l][1 + dim + i]))
2947				continue;
2948			for (u = 0; u < bmap->n_ineq; ++u) {
2949				int c;
2950
2951				if (!isl_int_is_negone(bmap->ineq[u][1+dim+i]))
2952					continue;
2953				c = div_find_coalesce(bmap, pairs, i, l, u);
2954				if (c < 0)
2955					continue;
2956				free(pairs);
2957				bmap = coalesce_divs(bmap, i, c, l, u);
2958				return isl_basic_map_drop_redundant_divs(bmap);
2959			}
2960		}
2961	}
2962
2963	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
2964		return bmap;
2965
2966	return drop_more_redundant_divs(bmap, pairs, n);
2967}
2968
2969/* Remove divs that are not strictly needed.
2970 * In particular, if a div only occurs positively (or negatively)
2971 * in constraints, then it can simply be dropped.
2972 * Also, if a div occurs in only two constraints and if moreover
2973 * those two constraints are opposite to each other, except for the constant
2974 * term and if the sum of the constant terms is such that for any value
2975 * of the other values, there is always at least one integer value of the
2976 * div, i.e., if one plus this sum is greater than or equal to
2977 * the (absolute value) of the coefficent of the div in the constraints,
2978 * then we can also simply drop the div.
2979 *
2980 * We skip divs that appear in equalities or in the definition of other divs.
2981 * Divs that appear in the definition of other divs usually occur in at least
2982 * 4 constraints, but the constraints may have been simplified.
2983 *
2984 * If any divs are left after these simple checks then we move on
2985 * to more complicated cases in drop_more_redundant_divs.
2986 */
2987struct isl_basic_map *isl_basic_map_drop_redundant_divs(
2988	struct isl_basic_map *bmap)
2989{
2990	int i, j;
2991	unsigned off;
2992	int *pairs = NULL;
2993	int n = 0;
2994
2995	if (!bmap)
2996		goto error;
2997	if (bmap->n_div == 0)
2998		return bmap;
2999
3000	off = isl_space_dim(bmap->dim, isl_dim_all);
3001	pairs = isl_calloc_array(bmap->ctx, int, bmap->n_div);
3002	if (!pairs)
3003		goto error;
3004
3005	for (i = 0; i < bmap->n_div; ++i) {
3006		int pos, neg;
3007		int last_pos, last_neg;
3008		int redundant;
3009		int defined;
3010
3011		defined = !isl_int_is_zero(bmap->div[i][0]);
3012		for (j = i; j < bmap->n_div; ++j)
3013			if (!isl_int_is_zero(bmap->div[j][1 + 1 + off + i]))
3014				break;
3015		if (j < bmap->n_div)
3016			continue;
3017		for (j = 0; j < bmap->n_eq; ++j)
3018			if (!isl_int_is_zero(bmap->eq[j][1 + off + i]))
3019				break;
3020		if (j < bmap->n_eq)
3021			continue;
3022		++n;
3023		pos = neg = 0;
3024		for (j = 0; j < bmap->n_ineq; ++j) {
3025			if (isl_int_is_pos(bmap->ineq[j][1 + off + i])) {
3026				last_pos = j;
3027				++pos;
3028			}
3029			if (isl_int_is_neg(bmap->ineq[j][1 + off + i])) {
3030				last_neg = j;
3031				++neg;
3032			}
3033		}
3034		pairs[i] = pos * neg;
3035		if (pairs[i] == 0) {
3036			for (j = bmap->n_ineq - 1; j >= 0; --j)
3037				if (!isl_int_is_zero(bmap->ineq[j][1+off+i]))
3038					isl_basic_map_drop_inequality(bmap, j);
3039			bmap = isl_basic_map_drop_div(bmap, i);
3040			free(pairs);
3041			return isl_basic_map_drop_redundant_divs(bmap);
3042		}
3043		if (pairs[i] != 1)
3044			continue;
3045		if (!isl_seq_is_neg(bmap->ineq[last_pos] + 1,
3046				    bmap->ineq[last_neg] + 1,
3047				    off + bmap->n_div))
3048			continue;
3049
3050		isl_int_add(bmap->ineq[last_pos][0],
3051			    bmap->ineq[last_pos][0], bmap->ineq[last_neg][0]);
3052		isl_int_add_ui(bmap->ineq[last_pos][0],
3053			       bmap->ineq[last_pos][0], 1);
3054		redundant = isl_int_ge(bmap->ineq[last_pos][0],
3055				bmap->ineq[last_pos][1+off+i]);
3056		isl_int_sub_ui(bmap->ineq[last_pos][0],
3057			       bmap->ineq[last_pos][0], 1);
3058		isl_int_sub(bmap->ineq[last_pos][0],
3059			    bmap->ineq[last_pos][0], bmap->ineq[last_neg][0]);
3060		if (!redundant) {
3061			if (defined ||
3062			    !ok_to_set_div_from_bound(bmap, i, last_pos)) {
3063				pairs[i] = 0;
3064				--n;
3065				continue;
3066			}
3067			bmap = set_div_from_lower_bound(bmap, i, last_pos);
3068			bmap = isl_basic_map_simplify(bmap);
3069			free(pairs);
3070			return isl_basic_map_drop_redundant_divs(bmap);
3071		}
3072		if (last_pos > last_neg) {
3073			isl_basic_map_drop_inequality(bmap, last_pos);
3074			isl_basic_map_drop_inequality(bmap, last_neg);
3075		} else {
3076			isl_basic_map_drop_inequality(bmap, last_neg);
3077			isl_basic_map_drop_inequality(bmap, last_pos);
3078		}
3079		bmap = isl_basic_map_drop_div(bmap, i);
3080		free(pairs);
3081		return isl_basic_map_drop_redundant_divs(bmap);
3082	}
3083
3084	if (n > 0)
3085		return coalesce_or_drop_more_redundant_divs(bmap, pairs, n);
3086
3087	free(pairs);
3088	return bmap;
3089error:
3090	free(pairs);
3091	isl_basic_map_free(bmap);
3092	return NULL;
3093}
3094
3095struct isl_basic_set *isl_basic_set_drop_redundant_divs(
3096	struct isl_basic_set *bset)
3097{
3098	return (struct isl_basic_set *)
3099	    isl_basic_map_drop_redundant_divs((struct isl_basic_map *)bset);
3100}
3101
3102struct isl_map *isl_map_drop_redundant_divs(struct isl_map *map)
3103{
3104	int i;
3105
3106	if (!map)
3107		return NULL;
3108	for (i = 0; i < map->n; ++i) {
3109		map->p[i] = isl_basic_map_drop_redundant_divs(map->p[i]);
3110		if (!map->p[i])
3111			goto error;
3112	}
3113	ISL_F_CLR(map, ISL_MAP_NORMALIZED);
3114	return map;
3115error:
3116	isl_map_free(map);
3117	return NULL;
3118}
3119
3120struct isl_set *isl_set_drop_redundant_divs(struct isl_set *set)
3121{
3122	return (struct isl_set *)
3123	    isl_map_drop_redundant_divs((struct isl_map *)set);
3124}
3125