1/*
2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 * Copyright 2010      INRIA Saclay
4 * Copyright 2012-2013 Ecole Normale Superieure
5 *
6 * Use of this software is governed by the MIT license
7 *
8 * Written by Sven Verdoolaege, K.U.Leuven, Departement
9 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
10 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
11 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
12 * and Ecole Normale Superieure, 45 rue d���Ulm, 75230 Paris, France
13 */
14
15#include <string.h>
16#include <isl_ctx_private.h>
17#include <isl_map_private.h>
18#include <isl/blk.h>
19#include "isl_space_private.h"
20#include "isl_equalities.h"
21#include <isl/lp.h>
22#include <isl/seq.h>
23#include <isl/set.h>
24#include <isl/map.h>
25#include "isl_map_piplib.h"
26#include <isl_reordering.h>
27#include "isl_sample.h"
28#include "isl_tab.h"
29#include <isl/vec.h>
30#include <isl_mat_private.h>
31#include <isl_dim_map.h>
32#include <isl_local_space_private.h>
33#include <isl_aff_private.h>
34#include <isl_options_private.h>
35#include <isl_morph.h>
36#include <isl_val_private.h>
37
38static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type)
39{
40	switch (type) {
41	case isl_dim_param:	return dim->nparam;
42	case isl_dim_in:	return dim->n_in;
43	case isl_dim_out:	return dim->n_out;
44	case isl_dim_all:	return dim->nparam + dim->n_in + dim->n_out;
45	default:		return 0;
46	}
47}
48
49static unsigned pos(__isl_keep isl_space *dim, enum isl_dim_type type)
50{
51	switch (type) {
52	case isl_dim_param:	return 1;
53	case isl_dim_in:	return 1 + dim->nparam;
54	case isl_dim_out:	return 1 + dim->nparam + dim->n_in;
55	default:		return 0;
56	}
57}
58
59unsigned isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
60				enum isl_dim_type type)
61{
62	if (!bmap)
63		return 0;
64	switch (type) {
65	case isl_dim_cst:	return 1;
66	case isl_dim_param:
67	case isl_dim_in:
68	case isl_dim_out:	return isl_space_dim(bmap->dim, type);
69	case isl_dim_div:	return bmap->n_div;
70	case isl_dim_all:	return isl_basic_map_total_dim(bmap);
71	default:		return 0;
72	}
73}
74
75unsigned isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type)
76{
77	return map ? n(map->dim, type) : 0;
78}
79
80unsigned isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)
81{
82	return set ? n(set->dim, type) : 0;
83}
84
85unsigned isl_basic_map_offset(struct isl_basic_map *bmap,
86					enum isl_dim_type type)
87{
88	isl_space *dim = bmap->dim;
89	switch (type) {
90	case isl_dim_cst:	return 0;
91	case isl_dim_param:	return 1;
92	case isl_dim_in:	return 1 + dim->nparam;
93	case isl_dim_out:	return 1 + dim->nparam + dim->n_in;
94	case isl_dim_div:	return 1 + dim->nparam + dim->n_in + dim->n_out;
95	default:		return 0;
96	}
97}
98
99unsigned isl_basic_set_offset(struct isl_basic_set *bset,
100					enum isl_dim_type type)
101{
102	return isl_basic_map_offset(bset, type);
103}
104
105static unsigned map_offset(struct isl_map *map, enum isl_dim_type type)
106{
107	return pos(map->dim, type);
108}
109
110unsigned isl_basic_set_dim(__isl_keep isl_basic_set *bset,
111				enum isl_dim_type type)
112{
113	return isl_basic_map_dim(bset, type);
114}
115
116unsigned isl_basic_set_n_dim(__isl_keep isl_basic_set *bset)
117{
118	return isl_basic_set_dim(bset, isl_dim_set);
119}
120
121unsigned isl_basic_set_n_param(__isl_keep isl_basic_set *bset)
122{
123	return isl_basic_set_dim(bset, isl_dim_param);
124}
125
126unsigned isl_basic_set_total_dim(const struct isl_basic_set *bset)
127{
128	if (!bset)
129		return 0;
130	return isl_space_dim(bset->dim, isl_dim_all) + bset->n_div;
131}
132
133unsigned isl_set_n_dim(__isl_keep isl_set *set)
134{
135	return isl_set_dim(set, isl_dim_set);
136}
137
138unsigned isl_set_n_param(__isl_keep isl_set *set)
139{
140	return isl_set_dim(set, isl_dim_param);
141}
142
143unsigned isl_basic_map_n_in(const struct isl_basic_map *bmap)
144{
145	return bmap ? bmap->dim->n_in : 0;
146}
147
148unsigned isl_basic_map_n_out(const struct isl_basic_map *bmap)
149{
150	return bmap ? bmap->dim->n_out : 0;
151}
152
153unsigned isl_basic_map_n_param(const struct isl_basic_map *bmap)
154{
155	return bmap ? bmap->dim->nparam : 0;
156}
157
158unsigned isl_basic_map_n_div(const struct isl_basic_map *bmap)
159{
160	return bmap ? bmap->n_div : 0;
161}
162
163unsigned isl_basic_map_total_dim(const struct isl_basic_map *bmap)
164{
165	return bmap ? isl_space_dim(bmap->dim, isl_dim_all) + bmap->n_div : 0;
166}
167
168unsigned isl_map_n_in(const struct isl_map *map)
169{
170	return map ? map->dim->n_in : 0;
171}
172
173unsigned isl_map_n_out(const struct isl_map *map)
174{
175	return map ? map->dim->n_out : 0;
176}
177
178unsigned isl_map_n_param(const struct isl_map *map)
179{
180	return map ? map->dim->nparam : 0;
181}
182
183int isl_map_compatible_domain(struct isl_map *map, struct isl_set *set)
184{
185	int m;
186	if (!map || !set)
187		return -1;
188	m = isl_space_match(map->dim, isl_dim_param, set->dim, isl_dim_param);
189	if (m < 0 || !m)
190		return m;
191	return isl_space_tuple_match(map->dim, isl_dim_in, set->dim, isl_dim_set);
192}
193
194int isl_basic_map_compatible_domain(struct isl_basic_map *bmap,
195		struct isl_basic_set *bset)
196{
197	int m;
198	if (!bmap || !bset)
199		return -1;
200	m = isl_space_match(bmap->dim, isl_dim_param, bset->dim, isl_dim_param);
201	if (m < 0 || !m)
202		return m;
203	return isl_space_tuple_match(bmap->dim, isl_dim_in, bset->dim, isl_dim_set);
204}
205
206int isl_map_compatible_range(__isl_keep isl_map *map, __isl_keep isl_set *set)
207{
208	int m;
209	if (!map || !set)
210		return -1;
211	m = isl_space_match(map->dim, isl_dim_param, set->dim, isl_dim_param);
212	if (m < 0 || !m)
213		return m;
214	return isl_space_tuple_match(map->dim, isl_dim_out, set->dim, isl_dim_set);
215}
216
217int isl_basic_map_compatible_range(struct isl_basic_map *bmap,
218		struct isl_basic_set *bset)
219{
220	int m;
221	if (!bmap || !bset)
222		return -1;
223	m = isl_space_match(bmap->dim, isl_dim_param, bset->dim, isl_dim_param);
224	if (m < 0 || !m)
225		return m;
226	return isl_space_tuple_match(bmap->dim, isl_dim_out, bset->dim, isl_dim_set);
227}
228
229isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap)
230{
231	return bmap ? bmap->ctx : NULL;
232}
233
234isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset)
235{
236	return bset ? bset->ctx : NULL;
237}
238
239isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map)
240{
241	return map ? map->ctx : NULL;
242}
243
244isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set)
245{
246	return set ? set->ctx : NULL;
247}
248
249__isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap)
250{
251	if (!bmap)
252		return NULL;
253	return isl_space_copy(bmap->dim);
254}
255
256__isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset)
257{
258	if (!bset)
259		return NULL;
260	return isl_space_copy(bset->dim);
261}
262
263/* Extract the divs in "bmap" as a matrix.
264 */
265__isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap)
266{
267	int i;
268	isl_ctx *ctx;
269	isl_mat *div;
270	unsigned total;
271	unsigned cols;
272
273	if (!bmap)
274		return NULL;
275
276	ctx = isl_basic_map_get_ctx(bmap);
277	total = isl_space_dim(bmap->dim, isl_dim_all);
278	cols = 1 + 1 + total + bmap->n_div;
279	div = isl_mat_alloc(ctx, bmap->n_div, cols);
280	if (!div)
281		return NULL;
282
283	for (i = 0; i < bmap->n_div; ++i)
284		isl_seq_cpy(div->row[i], bmap->div[i], cols);
285
286	return div;
287}
288
289/* Extract the divs in "bset" as a matrix.
290 */
291__isl_give isl_mat *isl_basic_set_get_divs(__isl_keep isl_basic_set *bset)
292{
293	return isl_basic_map_get_divs(bset);
294}
295
296__isl_give isl_local_space *isl_basic_map_get_local_space(
297	__isl_keep isl_basic_map *bmap)
298{
299	isl_mat *div;
300
301	if (!bmap)
302		return NULL;
303
304	div = isl_basic_map_get_divs(bmap);
305	return isl_local_space_alloc_div(isl_space_copy(bmap->dim), div);
306}
307
308__isl_give isl_local_space *isl_basic_set_get_local_space(
309	__isl_keep isl_basic_set *bset)
310{
311	return isl_basic_map_get_local_space(bset);
312}
313
314__isl_give isl_basic_map *isl_basic_map_from_local_space(
315	__isl_take isl_local_space *ls)
316{
317	int i;
318	int n_div;
319	isl_basic_map *bmap;
320
321	if (!ls)
322		return NULL;
323
324	n_div = isl_local_space_dim(ls, isl_dim_div);
325	bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls),
326					n_div, 0, 2 * n_div);
327
328	for (i = 0; i < n_div; ++i)
329		if (isl_basic_map_alloc_div(bmap) < 0)
330			goto error;
331
332	for (i = 0; i < n_div; ++i) {
333		isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
334		if (isl_basic_map_add_div_constraints(bmap, i) < 0)
335			goto error;
336	}
337
338	isl_local_space_free(ls);
339	return bmap;
340error:
341	isl_local_space_free(ls);
342	isl_basic_map_free(bmap);
343	return NULL;
344}
345
346__isl_give isl_basic_set *isl_basic_set_from_local_space(
347	__isl_take isl_local_space *ls)
348{
349	return isl_basic_map_from_local_space(ls);
350}
351
352__isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map)
353{
354	if (!map)
355		return NULL;
356	return isl_space_copy(map->dim);
357}
358
359__isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set)
360{
361	if (!set)
362		return NULL;
363	return isl_space_copy(set->dim);
364}
365
366__isl_give isl_basic_map *isl_basic_map_set_tuple_name(
367	__isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s)
368{
369	bmap = isl_basic_map_cow(bmap);
370	if (!bmap)
371		return NULL;
372	bmap->dim = isl_space_set_tuple_name(bmap->dim, type, s);
373	if (!bmap->dim)
374		goto error;
375	bmap = isl_basic_map_finalize(bmap);
376	return bmap;
377error:
378	isl_basic_map_free(bmap);
379	return NULL;
380}
381
382__isl_give isl_basic_set *isl_basic_set_set_tuple_name(
383	__isl_take isl_basic_set *bset, const char *s)
384{
385	return isl_basic_map_set_tuple_name(bset, isl_dim_set, s);
386}
387
388const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap,
389	enum isl_dim_type type)
390{
391	return bmap ? isl_space_get_tuple_name(bmap->dim, type) : NULL;
392}
393
394__isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,
395	enum isl_dim_type type, const char *s)
396{
397	int i;
398
399	map = isl_map_cow(map);
400	if (!map)
401		return NULL;
402
403	map->dim = isl_space_set_tuple_name(map->dim, type, s);
404	if (!map->dim)
405		goto error;
406
407	for (i = 0; i < map->n; ++i) {
408		map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s);
409		if (!map->p[i])
410			goto error;
411	}
412
413	return map;
414error:
415	isl_map_free(map);
416	return NULL;
417}
418
419/* Does the input or output tuple have a name?
420 */
421int isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type)
422{
423	return map ? isl_space_has_tuple_name(map->dim, type) : -1;
424}
425
426const char *isl_map_get_tuple_name(__isl_keep isl_map *map,
427	enum isl_dim_type type)
428{
429	return map ? isl_space_get_tuple_name(map->dim, type) : NULL;
430}
431
432__isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,
433	const char *s)
434{
435	return (isl_set *)isl_map_set_tuple_name((isl_map *)set, isl_dim_set, s);
436}
437
438__isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,
439	enum isl_dim_type type, __isl_take isl_id *id)
440{
441	map = isl_map_cow(map);
442	if (!map)
443		return isl_id_free(id);
444
445	map->dim = isl_space_set_tuple_id(map->dim, type, id);
446
447	return isl_map_reset_space(map, isl_space_copy(map->dim));
448}
449
450__isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
451	__isl_take isl_id *id)
452{
453	return isl_map_set_tuple_id(set, isl_dim_set, id);
454}
455
456__isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,
457	enum isl_dim_type type)
458{
459	map = isl_map_cow(map);
460	if (!map)
461		return NULL;
462
463	map->dim = isl_space_reset_tuple_id(map->dim, type);
464
465	return isl_map_reset_space(map, isl_space_copy(map->dim));
466}
467
468__isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set)
469{
470	return isl_map_reset_tuple_id(set, isl_dim_set);
471}
472
473int isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type)
474{
475	return map ? isl_space_has_tuple_id(map->dim, type) : -1;
476}
477
478__isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map,
479	enum isl_dim_type type)
480{
481	return map ? isl_space_get_tuple_id(map->dim, type) : NULL;
482}
483
484int isl_set_has_tuple_id(__isl_keep isl_set *set)
485{
486	return isl_map_has_tuple_id(set, isl_dim_set);
487}
488
489__isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set)
490{
491	return isl_map_get_tuple_id(set, isl_dim_set);
492}
493
494/* Does the set tuple have a name?
495 */
496int isl_set_has_tuple_name(__isl_keep isl_set *set)
497{
498	return set ? isl_space_has_tuple_name(set->dim, isl_dim_set) : -1;
499}
500
501
502const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset)
503{
504	return bset ? isl_space_get_tuple_name(bset->dim, isl_dim_set) : NULL;
505}
506
507const char *isl_set_get_tuple_name(__isl_keep isl_set *set)
508{
509	return set ? isl_space_get_tuple_name(set->dim, isl_dim_set) : NULL;
510}
511
512const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap,
513	enum isl_dim_type type, unsigned pos)
514{
515	return bmap ? isl_space_get_dim_name(bmap->dim, type, pos) : NULL;
516}
517
518const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset,
519	enum isl_dim_type type, unsigned pos)
520{
521	return bset ? isl_space_get_dim_name(bset->dim, type, pos) : NULL;
522}
523
524/* Does the given dimension have a name?
525 */
526int isl_map_has_dim_name(__isl_keep isl_map *map,
527	enum isl_dim_type type, unsigned pos)
528{
529	return map ? isl_space_has_dim_name(map->dim, type, pos) : -1;
530}
531
532const char *isl_map_get_dim_name(__isl_keep isl_map *map,
533	enum isl_dim_type type, unsigned pos)
534{
535	return map ? isl_space_get_dim_name(map->dim, type, pos) : NULL;
536}
537
538const char *isl_set_get_dim_name(__isl_keep isl_set *set,
539	enum isl_dim_type type, unsigned pos)
540{
541	return set ? isl_space_get_dim_name(set->dim, type, pos) : NULL;
542}
543
544/* Does the given dimension have a name?
545 */
546int isl_set_has_dim_name(__isl_keep isl_set *set,
547	enum isl_dim_type type, unsigned pos)
548{
549	return set ? isl_space_has_dim_name(set->dim, type, pos) : -1;
550}
551
552__isl_give isl_basic_map *isl_basic_map_set_dim_name(
553	__isl_take isl_basic_map *bmap,
554	enum isl_dim_type type, unsigned pos, const char *s)
555{
556	bmap = isl_basic_map_cow(bmap);
557	if (!bmap)
558		return NULL;
559	bmap->dim = isl_space_set_dim_name(bmap->dim, type, pos, s);
560	if (!bmap->dim)
561		goto error;
562	return isl_basic_map_finalize(bmap);
563error:
564	isl_basic_map_free(bmap);
565	return NULL;
566}
567
568__isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,
569	enum isl_dim_type type, unsigned pos, const char *s)
570{
571	int i;
572
573	map = isl_map_cow(map);
574	if (!map)
575		return NULL;
576
577	map->dim = isl_space_set_dim_name(map->dim, type, pos, s);
578	if (!map->dim)
579		goto error;
580
581	for (i = 0; i < map->n; ++i) {
582		map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s);
583		if (!map->p[i])
584			goto error;
585	}
586
587	return map;
588error:
589	isl_map_free(map);
590	return NULL;
591}
592
593__isl_give isl_basic_set *isl_basic_set_set_dim_name(
594	__isl_take isl_basic_set *bset,
595	enum isl_dim_type type, unsigned pos, const char *s)
596{
597	return (isl_basic_set *)isl_basic_map_set_dim_name(
598		(isl_basic_map *)bset, type, pos, s);
599}
600
601__isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set,
602	enum isl_dim_type type, unsigned pos, const char *s)
603{
604	return (isl_set *)isl_map_set_dim_name((isl_map *)set, type, pos, s);
605}
606
607int isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap,
608	enum isl_dim_type type, unsigned pos)
609{
610	return bmap ? isl_space_has_dim_id(bmap->dim, type, pos) : -1;
611}
612
613__isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset,
614	enum isl_dim_type type, unsigned pos)
615{
616	return bset ? isl_space_get_dim_id(bset->dim, type, pos) : NULL;
617}
618
619int isl_map_has_dim_id(__isl_keep isl_map *map,
620	enum isl_dim_type type, unsigned pos)
621{
622	return map ? isl_space_has_dim_id(map->dim, type, pos) : -1;
623}
624
625__isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map,
626	enum isl_dim_type type, unsigned pos)
627{
628	return map ? isl_space_get_dim_id(map->dim, type, pos) : NULL;
629}
630
631int isl_set_has_dim_id(__isl_keep isl_set *set,
632	enum isl_dim_type type, unsigned pos)
633{
634	return isl_map_has_dim_id(set, type, pos);
635}
636
637__isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,
638	enum isl_dim_type type, unsigned pos)
639{
640	return isl_map_get_dim_id(set, type, pos);
641}
642
643__isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map,
644	enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
645{
646	map = isl_map_cow(map);
647	if (!map)
648		return isl_id_free(id);
649
650	map->dim = isl_space_set_dim_id(map->dim, type, pos, id);
651
652	return isl_map_reset_space(map, isl_space_copy(map->dim));
653}
654
655__isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,
656	enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
657{
658	return isl_map_set_dim_id(set, type, pos, id);
659}
660
661int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type,
662	__isl_keep isl_id *id)
663{
664	if (!map)
665		return -1;
666	return isl_space_find_dim_by_id(map->dim, type, id);
667}
668
669int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type,
670	__isl_keep isl_id *id)
671{
672	return isl_map_find_dim_by_id(set, type, id);
673}
674
675int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,
676	const char *name)
677{
678	if (!map)
679		return -1;
680	return isl_space_find_dim_by_name(map->dim, type, name);
681}
682
683int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,
684	const char *name)
685{
686	return isl_map_find_dim_by_name(set, type, name);
687}
688
689int isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap)
690{
691	if (!bmap)
692		return -1;
693	return ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
694}
695
696int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset)
697{
698	return isl_basic_map_is_rational(bset);
699}
700
701/* Does "bmap" contain any rational points?
702 *
703 * If "bmap" has an equality for each dimension, equating the dimension
704 * to an integer constant, then it has no rational points, even if it
705 * is marked as rational.
706 */
707int isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap)
708{
709	int has_rational = 1;
710	unsigned total;
711
712	if (!bmap)
713		return -1;
714	if (isl_basic_map_plain_is_empty(bmap))
715		return 0;
716	if (!isl_basic_map_is_rational(bmap))
717		return 0;
718	bmap = isl_basic_map_copy(bmap);
719	bmap = isl_basic_map_implicit_equalities(bmap);
720	if (!bmap)
721		return -1;
722	total = isl_basic_map_total_dim(bmap);
723	if (bmap->n_eq == total) {
724		int i, j;
725		for (i = 0; i < bmap->n_eq; ++i) {
726			j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);
727			if (j < 0)
728				break;
729			if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
730			    !isl_int_is_negone(bmap->eq[i][1 + j]))
731				break;
732			j = isl_seq_first_non_zero(bmap->eq[i] + 1 + j + 1,
733						    total - j - 1);
734			if (j >= 0)
735				break;
736		}
737		if (i == bmap->n_eq)
738			has_rational = 0;
739	}
740	isl_basic_map_free(bmap);
741
742	return has_rational;
743}
744
745/* Does "map" contain any rational points?
746 */
747int isl_map_has_rational(__isl_keep isl_map *map)
748{
749	int i;
750	int has_rational;
751
752	if (!map)
753		return -1;
754	for (i = 0; i < map->n; ++i) {
755		has_rational = isl_basic_map_has_rational(map->p[i]);
756		if (has_rational < 0)
757			return -1;
758		if (has_rational)
759			return 1;
760	}
761	return 0;
762}
763
764/* Does "set" contain any rational points?
765 */
766int isl_set_has_rational(__isl_keep isl_set *set)
767{
768	return isl_map_has_rational(set);
769}
770
771/* Is this basic set a parameter domain?
772 */
773int isl_basic_set_is_params(__isl_keep isl_basic_set *bset)
774{
775	if (!bset)
776		return -1;
777	return isl_space_is_params(bset->dim);
778}
779
780/* Is this set a parameter domain?
781 */
782int isl_set_is_params(__isl_keep isl_set *set)
783{
784	if (!set)
785		return -1;
786	return isl_space_is_params(set->dim);
787}
788
789/* Is this map actually a parameter domain?
790 * Users should never call this function.  Outside of isl,
791 * a map can never be a parameter domain.
792 */
793int isl_map_is_params(__isl_keep isl_map *map)
794{
795	if (!map)
796		return -1;
797	return isl_space_is_params(map->dim);
798}
799
800static struct isl_basic_map *basic_map_init(struct isl_ctx *ctx,
801		struct isl_basic_map *bmap, unsigned extra,
802		unsigned n_eq, unsigned n_ineq)
803{
804	int i;
805	size_t row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + extra;
806
807	bmap->ctx = ctx;
808	isl_ctx_ref(ctx);
809
810	bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size);
811	if (isl_blk_is_error(bmap->block))
812		goto error;
813
814	bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq);
815	if ((n_ineq + n_eq) && !bmap->ineq)
816		goto error;
817
818	if (extra == 0) {
819		bmap->block2 = isl_blk_empty();
820		bmap->div = NULL;
821	} else {
822		bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size));
823		if (isl_blk_is_error(bmap->block2))
824			goto error;
825
826		bmap->div = isl_alloc_array(ctx, isl_int *, extra);
827		if (!bmap->div)
828			goto error;
829	}
830
831	for (i = 0; i < n_ineq + n_eq; ++i)
832		bmap->ineq[i] = bmap->block.data + i * row_size;
833
834	for (i = 0; i < extra; ++i)
835		bmap->div[i] = bmap->block2.data + i * (1 + row_size);
836
837	bmap->ref = 1;
838	bmap->flags = 0;
839	bmap->c_size = n_eq + n_ineq;
840	bmap->eq = bmap->ineq + n_ineq;
841	bmap->extra = extra;
842	bmap->n_eq = 0;
843	bmap->n_ineq = 0;
844	bmap->n_div = 0;
845	bmap->sample = NULL;
846
847	return bmap;
848error:
849	isl_basic_map_free(bmap);
850	return NULL;
851}
852
853struct isl_basic_set *isl_basic_set_alloc(struct isl_ctx *ctx,
854		unsigned nparam, unsigned dim, unsigned extra,
855		unsigned n_eq, unsigned n_ineq)
856{
857	struct isl_basic_map *bmap;
858	isl_space *space;
859
860	space = isl_space_set_alloc(ctx, nparam, dim);
861	if (!space)
862		return NULL;
863
864	bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
865	return (struct isl_basic_set *)bmap;
866}
867
868struct isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *dim,
869		unsigned extra, unsigned n_eq, unsigned n_ineq)
870{
871	struct isl_basic_map *bmap;
872	if (!dim)
873		return NULL;
874	isl_assert(dim->ctx, dim->n_in == 0, goto error);
875	bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
876	return (struct isl_basic_set *)bmap;
877error:
878	isl_space_free(dim);
879	return NULL;
880}
881
882struct isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *dim,
883		unsigned extra, unsigned n_eq, unsigned n_ineq)
884{
885	struct isl_basic_map *bmap;
886
887	if (!dim)
888		return NULL;
889	bmap = isl_calloc_type(dim->ctx, struct isl_basic_map);
890	if (!bmap)
891		goto error;
892	bmap->dim = dim;
893
894	return basic_map_init(dim->ctx, bmap, extra, n_eq, n_ineq);
895error:
896	isl_space_free(dim);
897	return NULL;
898}
899
900struct isl_basic_map *isl_basic_map_alloc(struct isl_ctx *ctx,
901		unsigned nparam, unsigned in, unsigned out, unsigned extra,
902		unsigned n_eq, unsigned n_ineq)
903{
904	struct isl_basic_map *bmap;
905	isl_space *dim;
906
907	dim = isl_space_alloc(ctx, nparam, in, out);
908	if (!dim)
909		return NULL;
910
911	bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
912	return bmap;
913}
914
915static void dup_constraints(
916		struct isl_basic_map *dst, struct isl_basic_map *src)
917{
918	int i;
919	unsigned total = isl_basic_map_total_dim(src);
920
921	for (i = 0; i < src->n_eq; ++i) {
922		int j = isl_basic_map_alloc_equality(dst);
923		isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);
924	}
925
926	for (i = 0; i < src->n_ineq; ++i) {
927		int j = isl_basic_map_alloc_inequality(dst);
928		isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);
929	}
930
931	for (i = 0; i < src->n_div; ++i) {
932		int j = isl_basic_map_alloc_div(dst);
933		isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
934	}
935	ISL_F_SET(dst, ISL_BASIC_SET_FINAL);
936}
937
938struct isl_basic_map *isl_basic_map_dup(struct isl_basic_map *bmap)
939{
940	struct isl_basic_map *dup;
941
942	if (!bmap)
943		return NULL;
944	dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
945			bmap->n_div, bmap->n_eq, bmap->n_ineq);
946	if (!dup)
947		return NULL;
948	dup_constraints(dup, bmap);
949	dup->flags = bmap->flags;
950	dup->sample = isl_vec_copy(bmap->sample);
951	return dup;
952}
953
954struct isl_basic_set *isl_basic_set_dup(struct isl_basic_set *bset)
955{
956	struct isl_basic_map *dup;
957
958	dup = isl_basic_map_dup((struct isl_basic_map *)bset);
959	return (struct isl_basic_set *)dup;
960}
961
962struct isl_basic_set *isl_basic_set_copy(struct isl_basic_set *bset)
963{
964	if (!bset)
965		return NULL;
966
967	if (ISL_F_ISSET(bset, ISL_BASIC_SET_FINAL)) {
968		bset->ref++;
969		return bset;
970	}
971	return isl_basic_set_dup(bset);
972}
973
974struct isl_set *isl_set_copy(struct isl_set *set)
975{
976	if (!set)
977		return NULL;
978
979	set->ref++;
980	return set;
981}
982
983struct isl_basic_map *isl_basic_map_copy(struct isl_basic_map *bmap)
984{
985	if (!bmap)
986		return NULL;
987
988	if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) {
989		bmap->ref++;
990		return bmap;
991	}
992	bmap = isl_basic_map_dup(bmap);
993	if (bmap)
994		ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
995	return bmap;
996}
997
998struct isl_map *isl_map_copy(struct isl_map *map)
999{
1000	if (!map)
1001		return NULL;
1002
1003	map->ref++;
1004	return map;
1005}
1006
1007void *isl_basic_map_free(__isl_take isl_basic_map *bmap)
1008{
1009	if (!bmap)
1010		return NULL;
1011
1012	if (--bmap->ref > 0)
1013		return NULL;
1014
1015	isl_ctx_deref(bmap->ctx);
1016	free(bmap->div);
1017	isl_blk_free(bmap->ctx, bmap->block2);
1018	free(bmap->ineq);
1019	isl_blk_free(bmap->ctx, bmap->block);
1020	isl_vec_free(bmap->sample);
1021	isl_space_free(bmap->dim);
1022	free(bmap);
1023
1024	return NULL;
1025}
1026
1027void *isl_basic_set_free(struct isl_basic_set *bset)
1028{
1029	return isl_basic_map_free((struct isl_basic_map *)bset);
1030}
1031
1032static int room_for_con(struct isl_basic_map *bmap, unsigned n)
1033{
1034	return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;
1035}
1036
1037__isl_give isl_map *isl_map_align_params_map_map_and(
1038	__isl_take isl_map *map1, __isl_take isl_map *map2,
1039	__isl_give isl_map *(*fn)(__isl_take isl_map *map1,
1040				    __isl_take isl_map *map2))
1041{
1042	if (!map1 || !map2)
1043		goto error;
1044	if (isl_space_match(map1->dim, isl_dim_param, map2->dim, isl_dim_param))
1045		return fn(map1, map2);
1046	if (!isl_space_has_named_params(map1->dim) ||
1047	    !isl_space_has_named_params(map2->dim))
1048		isl_die(map1->ctx, isl_error_invalid,
1049			"unaligned unnamed parameters", goto error);
1050	map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1051	map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1052	return fn(map1, map2);
1053error:
1054	isl_map_free(map1);
1055	isl_map_free(map2);
1056	return NULL;
1057}
1058
1059int isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
1060	__isl_keep isl_map *map2,
1061	int (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
1062{
1063	int r;
1064
1065	if (!map1 || !map2)
1066		return -1;
1067	if (isl_space_match(map1->dim, isl_dim_param, map2->dim, isl_dim_param))
1068		return fn(map1, map2);
1069	if (!isl_space_has_named_params(map1->dim) ||
1070	    !isl_space_has_named_params(map2->dim))
1071		isl_die(map1->ctx, isl_error_invalid,
1072			"unaligned unnamed parameters", return -1);
1073	map1 = isl_map_copy(map1);
1074	map2 = isl_map_copy(map2);
1075	map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1076	map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1077	r = fn(map1, map2);
1078	isl_map_free(map1);
1079	isl_map_free(map2);
1080	return r;
1081}
1082
1083int isl_basic_map_alloc_equality(struct isl_basic_map *bmap)
1084{
1085	struct isl_ctx *ctx;
1086	if (!bmap)
1087		return -1;
1088	ctx = bmap->ctx;
1089	isl_assert(ctx, room_for_con(bmap, 1), return -1);
1090	isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size,
1091			return -1);
1092	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1093	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1094	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1095	ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1096	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1097	if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) {
1098		isl_int *t;
1099		int j = isl_basic_map_alloc_inequality(bmap);
1100		if (j < 0)
1101			return -1;
1102		t = bmap->ineq[j];
1103		bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1];
1104		bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1105		bmap->eq[-1] = t;
1106		bmap->n_eq++;
1107		bmap->n_ineq--;
1108		bmap->eq--;
1109		return 0;
1110	}
1111	isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + isl_basic_map_total_dim(bmap),
1112		      bmap->extra - bmap->n_div);
1113	return bmap->n_eq++;
1114}
1115
1116int isl_basic_set_alloc_equality(struct isl_basic_set *bset)
1117{
1118	return isl_basic_map_alloc_equality((struct isl_basic_map *)bset);
1119}
1120
1121int isl_basic_map_free_equality(struct isl_basic_map *bmap, unsigned n)
1122{
1123	if (!bmap)
1124		return -1;
1125	isl_assert(bmap->ctx, n <= bmap->n_eq, return -1);
1126	bmap->n_eq -= n;
1127	return 0;
1128}
1129
1130int isl_basic_set_free_equality(struct isl_basic_set *bset, unsigned n)
1131{
1132	return isl_basic_map_free_equality((struct isl_basic_map *)bset, n);
1133}
1134
1135int isl_basic_map_drop_equality(struct isl_basic_map *bmap, unsigned pos)
1136{
1137	isl_int *t;
1138	if (!bmap)
1139		return -1;
1140	isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);
1141
1142	if (pos != bmap->n_eq - 1) {
1143		t = bmap->eq[pos];
1144		bmap->eq[pos] = bmap->eq[bmap->n_eq - 1];
1145		bmap->eq[bmap->n_eq - 1] = t;
1146	}
1147	bmap->n_eq--;
1148	return 0;
1149}
1150
1151int isl_basic_set_drop_equality(struct isl_basic_set *bset, unsigned pos)
1152{
1153	return isl_basic_map_drop_equality((struct isl_basic_map *)bset, pos);
1154}
1155
1156/* Turn inequality "pos" of "bmap" into an equality.
1157 *
1158 * In particular, we move the inequality in front of the equalities
1159 * and move the last inequality in the position of the moved inequality.
1160 * Note that isl_tab_make_equalities_explicit depends on this particular
1161 * change in the ordering of the constraints.
1162 */
1163void isl_basic_map_inequality_to_equality(
1164		struct isl_basic_map *bmap, unsigned pos)
1165{
1166	isl_int *t;
1167
1168	t = bmap->ineq[pos];
1169	bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1170	bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1171	bmap->eq[-1] = t;
1172	bmap->n_eq++;
1173	bmap->n_ineq--;
1174	bmap->eq--;
1175	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1176	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1177	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1178	ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1179}
1180
1181static int room_for_ineq(struct isl_basic_map *bmap, unsigned n)
1182{
1183	return bmap->n_ineq + n <= bmap->eq - bmap->ineq;
1184}
1185
1186int isl_basic_map_alloc_inequality(struct isl_basic_map *bmap)
1187{
1188	struct isl_ctx *ctx;
1189	if (!bmap)
1190		return -1;
1191	ctx = bmap->ctx;
1192	isl_assert(ctx, room_for_ineq(bmap, 1), return -1);
1193	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1194	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1195	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1196	ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1197	isl_seq_clr(bmap->ineq[bmap->n_ineq] +
1198		      1 + isl_basic_map_total_dim(bmap),
1199		      bmap->extra - bmap->n_div);
1200	return bmap->n_ineq++;
1201}
1202
1203int isl_basic_set_alloc_inequality(struct isl_basic_set *bset)
1204{
1205	return isl_basic_map_alloc_inequality((struct isl_basic_map *)bset);
1206}
1207
1208int isl_basic_map_free_inequality(struct isl_basic_map *bmap, unsigned n)
1209{
1210	if (!bmap)
1211		return -1;
1212	isl_assert(bmap->ctx, n <= bmap->n_ineq, return -1);
1213	bmap->n_ineq -= n;
1214	return 0;
1215}
1216
1217int isl_basic_set_free_inequality(struct isl_basic_set *bset, unsigned n)
1218{
1219	return isl_basic_map_free_inequality((struct isl_basic_map *)bset, n);
1220}
1221
1222int isl_basic_map_drop_inequality(struct isl_basic_map *bmap, unsigned pos)
1223{
1224	isl_int *t;
1225	if (!bmap)
1226		return -1;
1227	isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
1228
1229	if (pos != bmap->n_ineq - 1) {
1230		t = bmap->ineq[pos];
1231		bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1232		bmap->ineq[bmap->n_ineq - 1] = t;
1233		ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1234	}
1235	bmap->n_ineq--;
1236	return 0;
1237}
1238
1239int isl_basic_set_drop_inequality(struct isl_basic_set *bset, unsigned pos)
1240{
1241	return isl_basic_map_drop_inequality((struct isl_basic_map *)bset, pos);
1242}
1243
1244__isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap,
1245	isl_int *eq)
1246{
1247	int k;
1248
1249	bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
1250	if (!bmap)
1251		return NULL;
1252	k = isl_basic_map_alloc_equality(bmap);
1253	if (k < 0)
1254		goto error;
1255	isl_seq_cpy(bmap->eq[k], eq, 1 + isl_basic_map_total_dim(bmap));
1256	return bmap;
1257error:
1258	isl_basic_map_free(bmap);
1259	return NULL;
1260}
1261
1262__isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,
1263	isl_int *eq)
1264{
1265	return (isl_basic_set *)
1266		isl_basic_map_add_eq((isl_basic_map *)bset, eq);
1267}
1268
1269__isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
1270	isl_int *ineq)
1271{
1272	int k;
1273
1274	bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
1275	if (!bmap)
1276		return NULL;
1277	k = isl_basic_map_alloc_inequality(bmap);
1278	if (k < 0)
1279		goto error;
1280	isl_seq_cpy(bmap->ineq[k], ineq, 1 + isl_basic_map_total_dim(bmap));
1281	return bmap;
1282error:
1283	isl_basic_map_free(bmap);
1284	return NULL;
1285}
1286
1287__isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset,
1288	isl_int *ineq)
1289{
1290	return (isl_basic_set *)
1291		isl_basic_map_add_ineq((isl_basic_map *)bset, ineq);
1292}
1293
1294int isl_basic_map_alloc_div(struct isl_basic_map *bmap)
1295{
1296	if (!bmap)
1297		return -1;
1298	isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);
1299	isl_seq_clr(bmap->div[bmap->n_div] +
1300		      1 + 1 + isl_basic_map_total_dim(bmap),
1301		      bmap->extra - bmap->n_div);
1302	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1303	return bmap->n_div++;
1304}
1305
1306int isl_basic_set_alloc_div(struct isl_basic_set *bset)
1307{
1308	return isl_basic_map_alloc_div((struct isl_basic_map *)bset);
1309}
1310
1311int isl_basic_map_free_div(struct isl_basic_map *bmap, unsigned n)
1312{
1313	if (!bmap)
1314		return -1;
1315	isl_assert(bmap->ctx, n <= bmap->n_div, return -1);
1316	bmap->n_div -= n;
1317	return 0;
1318}
1319
1320int isl_basic_set_free_div(struct isl_basic_set *bset, unsigned n)
1321{
1322	return isl_basic_map_free_div((struct isl_basic_map *)bset, n);
1323}
1324
1325/* Copy constraint from src to dst, putting the vars of src at offset
1326 * dim_off in dst and the divs of src at offset div_off in dst.
1327 * If both sets are actually map, then dim_off applies to the input
1328 * variables.
1329 */
1330static void copy_constraint(struct isl_basic_map *dst_map, isl_int *dst,
1331			    struct isl_basic_map *src_map, isl_int *src,
1332			    unsigned in_off, unsigned out_off, unsigned div_off)
1333{
1334	unsigned src_nparam = isl_basic_map_n_param(src_map);
1335	unsigned dst_nparam = isl_basic_map_n_param(dst_map);
1336	unsigned src_in = isl_basic_map_n_in(src_map);
1337	unsigned dst_in = isl_basic_map_n_in(dst_map);
1338	unsigned src_out = isl_basic_map_n_out(src_map);
1339	unsigned dst_out = isl_basic_map_n_out(dst_map);
1340	isl_int_set(dst[0], src[0]);
1341	isl_seq_cpy(dst+1, src+1, isl_min(dst_nparam, src_nparam));
1342	if (dst_nparam > src_nparam)
1343		isl_seq_clr(dst+1+src_nparam,
1344				dst_nparam - src_nparam);
1345	isl_seq_clr(dst+1+dst_nparam, in_off);
1346	isl_seq_cpy(dst+1+dst_nparam+in_off,
1347		    src+1+src_nparam,
1348		    isl_min(dst_in-in_off, src_in));
1349	if (dst_in-in_off > src_in)
1350		isl_seq_clr(dst+1+dst_nparam+in_off+src_in,
1351				dst_in - in_off - src_in);
1352	isl_seq_clr(dst+1+dst_nparam+dst_in, out_off);
1353	isl_seq_cpy(dst+1+dst_nparam+dst_in+out_off,
1354		    src+1+src_nparam+src_in,
1355		    isl_min(dst_out-out_off, src_out));
1356	if (dst_out-out_off > src_out)
1357		isl_seq_clr(dst+1+dst_nparam+dst_in+out_off+src_out,
1358				dst_out - out_off - src_out);
1359	isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out, div_off);
1360	isl_seq_cpy(dst+1+dst_nparam+dst_in+dst_out+div_off,
1361		    src+1+src_nparam+src_in+src_out,
1362		    isl_min(dst_map->extra-div_off, src_map->n_div));
1363	if (dst_map->n_div-div_off > src_map->n_div)
1364		isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out+
1365				div_off+src_map->n_div,
1366				dst_map->n_div - div_off - src_map->n_div);
1367}
1368
1369static void copy_div(struct isl_basic_map *dst_map, isl_int *dst,
1370		     struct isl_basic_map *src_map, isl_int *src,
1371		     unsigned in_off, unsigned out_off, unsigned div_off)
1372{
1373	isl_int_set(dst[0], src[0]);
1374	copy_constraint(dst_map, dst+1, src_map, src+1, in_off, out_off, div_off);
1375}
1376
1377static struct isl_basic_map *add_constraints(struct isl_basic_map *bmap1,
1378		struct isl_basic_map *bmap2, unsigned i_pos, unsigned o_pos)
1379{
1380	int i;
1381	unsigned div_off;
1382
1383	if (!bmap1 || !bmap2)
1384		goto error;
1385
1386	div_off = bmap1->n_div;
1387
1388	for (i = 0; i < bmap2->n_eq; ++i) {
1389		int i1 = isl_basic_map_alloc_equality(bmap1);
1390		if (i1 < 0)
1391			goto error;
1392		copy_constraint(bmap1, bmap1->eq[i1], bmap2, bmap2->eq[i],
1393				i_pos, o_pos, div_off);
1394	}
1395
1396	for (i = 0; i < bmap2->n_ineq; ++i) {
1397		int i1 = isl_basic_map_alloc_inequality(bmap1);
1398		if (i1 < 0)
1399			goto error;
1400		copy_constraint(bmap1, bmap1->ineq[i1], bmap2, bmap2->ineq[i],
1401				i_pos, o_pos, div_off);
1402	}
1403
1404	for (i = 0; i < bmap2->n_div; ++i) {
1405		int i1 = isl_basic_map_alloc_div(bmap1);
1406		if (i1 < 0)
1407			goto error;
1408		copy_div(bmap1, bmap1->div[i1], bmap2, bmap2->div[i],
1409			 i_pos, o_pos, div_off);
1410	}
1411
1412	isl_basic_map_free(bmap2);
1413
1414	return bmap1;
1415
1416error:
1417	isl_basic_map_free(bmap1);
1418	isl_basic_map_free(bmap2);
1419	return NULL;
1420}
1421
1422struct isl_basic_set *isl_basic_set_add_constraints(struct isl_basic_set *bset1,
1423		struct isl_basic_set *bset2, unsigned pos)
1424{
1425	return (struct isl_basic_set *)
1426		add_constraints((struct isl_basic_map *)bset1,
1427				(struct isl_basic_map *)bset2, 0, pos);
1428}
1429
1430struct isl_basic_map *isl_basic_map_extend_space(struct isl_basic_map *base,
1431		__isl_take isl_space *dim, unsigned extra,
1432		unsigned n_eq, unsigned n_ineq)
1433{
1434	struct isl_basic_map *ext;
1435	unsigned flags;
1436	int dims_ok;
1437
1438	if (!dim)
1439		goto error;
1440
1441	if (!base)
1442		goto error;
1443
1444	dims_ok = isl_space_is_equal(base->dim, dim) &&
1445		  base->extra >= base->n_div + extra;
1446
1447	if (dims_ok && room_for_con(base, n_eq + n_ineq) &&
1448		       room_for_ineq(base, n_ineq)) {
1449		isl_space_free(dim);
1450		return base;
1451	}
1452
1453	isl_assert(base->ctx, base->dim->nparam <= dim->nparam, goto error);
1454	isl_assert(base->ctx, base->dim->n_in <= dim->n_in, goto error);
1455	isl_assert(base->ctx, base->dim->n_out <= dim->n_out, goto error);
1456	extra += base->extra;
1457	n_eq += base->n_eq;
1458	n_ineq += base->n_ineq;
1459
1460	ext = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1461	dim = NULL;
1462	if (!ext)
1463		goto error;
1464
1465	if (dims_ok)
1466		ext->sample = isl_vec_copy(base->sample);
1467	flags = base->flags;
1468	ext = add_constraints(ext, base, 0, 0);
1469	if (ext) {
1470		ext->flags = flags;
1471		ISL_F_CLR(ext, ISL_BASIC_SET_FINAL);
1472	}
1473
1474	return ext;
1475
1476error:
1477	isl_space_free(dim);
1478	isl_basic_map_free(base);
1479	return NULL;
1480}
1481
1482struct isl_basic_set *isl_basic_set_extend_space(struct isl_basic_set *base,
1483		__isl_take isl_space *dim, unsigned extra,
1484		unsigned n_eq, unsigned n_ineq)
1485{
1486	return (struct isl_basic_set *)
1487		isl_basic_map_extend_space((struct isl_basic_map *)base, dim,
1488							extra, n_eq, n_ineq);
1489}
1490
1491struct isl_basic_map *isl_basic_map_extend_constraints(
1492		struct isl_basic_map *base, unsigned n_eq, unsigned n_ineq)
1493{
1494	if (!base)
1495		return NULL;
1496	return isl_basic_map_extend_space(base, isl_space_copy(base->dim),
1497					0, n_eq, n_ineq);
1498}
1499
1500struct isl_basic_map *isl_basic_map_extend(struct isl_basic_map *base,
1501		unsigned nparam, unsigned n_in, unsigned n_out, unsigned extra,
1502		unsigned n_eq, unsigned n_ineq)
1503{
1504	struct isl_basic_map *bmap;
1505	isl_space *dim;
1506
1507	if (!base)
1508		return NULL;
1509	dim = isl_space_alloc(base->ctx, nparam, n_in, n_out);
1510	if (!dim)
1511		goto error;
1512
1513	bmap = isl_basic_map_extend_space(base, dim, extra, n_eq, n_ineq);
1514	return bmap;
1515error:
1516	isl_basic_map_free(base);
1517	return NULL;
1518}
1519
1520struct isl_basic_set *isl_basic_set_extend(struct isl_basic_set *base,
1521		unsigned nparam, unsigned dim, unsigned extra,
1522		unsigned n_eq, unsigned n_ineq)
1523{
1524	return (struct isl_basic_set *)
1525		isl_basic_map_extend((struct isl_basic_map *)base,
1526					nparam, 0, dim, extra, n_eq, n_ineq);
1527}
1528
1529struct isl_basic_set *isl_basic_set_extend_constraints(
1530		struct isl_basic_set *base, unsigned n_eq, unsigned n_ineq)
1531{
1532	return (struct isl_basic_set *)
1533		isl_basic_map_extend_constraints((struct isl_basic_map *)base,
1534						    n_eq, n_ineq);
1535}
1536
1537struct isl_basic_set *isl_basic_set_cow(struct isl_basic_set *bset)
1538{
1539	return (struct isl_basic_set *)
1540		isl_basic_map_cow((struct isl_basic_map *)bset);
1541}
1542
1543struct isl_basic_map *isl_basic_map_cow(struct isl_basic_map *bmap)
1544{
1545	if (!bmap)
1546		return NULL;
1547
1548	if (bmap->ref > 1) {
1549		bmap->ref--;
1550		bmap = isl_basic_map_dup(bmap);
1551	}
1552	if (bmap)
1553		ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);
1554	return bmap;
1555}
1556
1557struct isl_set *isl_set_cow(struct isl_set *set)
1558{
1559	if (!set)
1560		return NULL;
1561
1562	if (set->ref == 1)
1563		return set;
1564	set->ref--;
1565	return isl_set_dup(set);
1566}
1567
1568struct isl_map *isl_map_cow(struct isl_map *map)
1569{
1570	if (!map)
1571		return NULL;
1572
1573	if (map->ref == 1)
1574		return map;
1575	map->ref--;
1576	return isl_map_dup(map);
1577}
1578
1579static void swap_vars(struct isl_blk blk, isl_int *a,
1580			unsigned a_len, unsigned b_len)
1581{
1582	isl_seq_cpy(blk.data, a+a_len, b_len);
1583	isl_seq_cpy(blk.data+b_len, a, a_len);
1584	isl_seq_cpy(a, blk.data, b_len+a_len);
1585}
1586
1587static __isl_give isl_basic_map *isl_basic_map_swap_vars(
1588	__isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2)
1589{
1590	int i;
1591	struct isl_blk blk;
1592
1593	if (!bmap)
1594		goto error;
1595
1596	isl_assert(bmap->ctx,
1597		pos + n1 + n2 <= 1 + isl_basic_map_total_dim(bmap), goto error);
1598
1599	if (n1 == 0 || n2 == 0)
1600		return bmap;
1601
1602	bmap = isl_basic_map_cow(bmap);
1603	if (!bmap)
1604		return NULL;
1605
1606	blk = isl_blk_alloc(bmap->ctx, n1 + n2);
1607	if (isl_blk_is_error(blk))
1608		goto error;
1609
1610	for (i = 0; i < bmap->n_eq; ++i)
1611		swap_vars(blk,
1612			  bmap->eq[i] + pos, n1, n2);
1613
1614	for (i = 0; i < bmap->n_ineq; ++i)
1615		swap_vars(blk,
1616			  bmap->ineq[i] + pos, n1, n2);
1617
1618	for (i = 0; i < bmap->n_div; ++i)
1619		swap_vars(blk,
1620			  bmap->div[i]+1 + pos, n1, n2);
1621
1622	isl_blk_free(bmap->ctx, blk);
1623
1624	ISL_F_CLR(bmap, ISL_BASIC_SET_NORMALIZED);
1625	bmap = isl_basic_map_gauss(bmap, NULL);
1626	return isl_basic_map_finalize(bmap);
1627error:
1628	isl_basic_map_free(bmap);
1629	return NULL;
1630}
1631
1632static __isl_give isl_basic_set *isl_basic_set_swap_vars(
1633	__isl_take isl_basic_set *bset, unsigned n)
1634{
1635	unsigned dim;
1636	unsigned nparam;
1637
1638	if (!bset)
1639		return NULL;
1640
1641	nparam = isl_basic_set_n_param(bset);
1642	dim = isl_basic_set_n_dim(bset);
1643	isl_assert(bset->ctx, n <= dim, goto error);
1644
1645	return isl_basic_map_swap_vars(bset, 1 + nparam, n, dim - n);
1646error:
1647	isl_basic_set_free(bset);
1648	return NULL;
1649}
1650
1651struct isl_basic_map *isl_basic_map_set_to_empty(struct isl_basic_map *bmap)
1652{
1653	int i = 0;
1654	unsigned total;
1655	if (!bmap)
1656		goto error;
1657	total = isl_basic_map_total_dim(bmap);
1658	isl_basic_map_free_div(bmap, bmap->n_div);
1659	isl_basic_map_free_inequality(bmap, bmap->n_ineq);
1660	if (bmap->n_eq > 0)
1661		isl_basic_map_free_equality(bmap, bmap->n_eq-1);
1662	else {
1663		i = isl_basic_map_alloc_equality(bmap);
1664		if (i < 0)
1665			goto error;
1666	}
1667	isl_int_set_si(bmap->eq[i][0], 1);
1668	isl_seq_clr(bmap->eq[i]+1, total);
1669	ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
1670	isl_vec_free(bmap->sample);
1671	bmap->sample = NULL;
1672	return isl_basic_map_finalize(bmap);
1673error:
1674	isl_basic_map_free(bmap);
1675	return NULL;
1676}
1677
1678struct isl_basic_set *isl_basic_set_set_to_empty(struct isl_basic_set *bset)
1679{
1680	return (struct isl_basic_set *)
1681		isl_basic_map_set_to_empty((struct isl_basic_map *)bset);
1682}
1683
1684/* Swap divs "a" and "b" in "bmap" (without modifying any of the constraints
1685 * of "bmap").
1686 */
1687static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b)
1688{
1689	isl_int *t = bmap->div[a];
1690	bmap->div[a] = bmap->div[b];
1691	bmap->div[b] = t;
1692}
1693
1694/* Swap divs "a" and "b" in "bmap" and adjust the constraints and
1695 * div definitions accordingly.
1696 */
1697void isl_basic_map_swap_div(struct isl_basic_map *bmap, int a, int b)
1698{
1699	int i;
1700	unsigned off = isl_space_dim(bmap->dim, isl_dim_all);
1701
1702	swap_div(bmap, a, b);
1703
1704	for (i = 0; i < bmap->n_eq; ++i)
1705		isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]);
1706
1707	for (i = 0; i < bmap->n_ineq; ++i)
1708		isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]);
1709
1710	for (i = 0; i < bmap->n_div; ++i)
1711		isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);
1712	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1713}
1714
1715/* Eliminate the specified n dimensions starting at first from the
1716 * constraints, without removing the dimensions from the space.
1717 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
1718 */
1719__isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
1720	enum isl_dim_type type, unsigned first, unsigned n)
1721{
1722	int i;
1723
1724	if (!map)
1725		return NULL;
1726	if (n == 0)
1727		return map;
1728
1729	if (first + n > isl_map_dim(map, type) || first + n < first)
1730		isl_die(map->ctx, isl_error_invalid,
1731			"index out of bounds", goto error);
1732
1733	map = isl_map_cow(map);
1734	if (!map)
1735		return NULL;
1736
1737	for (i = 0; i < map->n; ++i) {
1738		map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n);
1739		if (!map->p[i])
1740			goto error;
1741	}
1742	return map;
1743error:
1744	isl_map_free(map);
1745	return NULL;
1746}
1747
1748/* Eliminate the specified n dimensions starting at first from the
1749 * constraints, without removing the dimensions from the space.
1750 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
1751 */
1752__isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
1753	enum isl_dim_type type, unsigned first, unsigned n)
1754{
1755	return (isl_set *)isl_map_eliminate((isl_map *)set, type, first, n);
1756}
1757
1758/* Eliminate the specified n dimensions starting at first from the
1759 * constraints, without removing the dimensions from the space.
1760 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
1761 */
1762__isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,
1763	unsigned first, unsigned n)
1764{
1765	return isl_set_eliminate(set, isl_dim_set, first, n);
1766}
1767
1768__isl_give isl_basic_map *isl_basic_map_remove_divs(
1769	__isl_take isl_basic_map *bmap)
1770{
1771	if (!bmap)
1772		return NULL;
1773	bmap = isl_basic_map_eliminate_vars(bmap,
1774			    isl_space_dim(bmap->dim, isl_dim_all), bmap->n_div);
1775	if (!bmap)
1776		return NULL;
1777	bmap->n_div = 0;
1778	return isl_basic_map_finalize(bmap);
1779}
1780
1781__isl_give isl_basic_set *isl_basic_set_remove_divs(
1782	__isl_take isl_basic_set *bset)
1783{
1784	return (struct isl_basic_set *)isl_basic_map_remove_divs(
1785			(struct isl_basic_map *)bset);
1786}
1787
1788__isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map)
1789{
1790	int i;
1791
1792	if (!map)
1793		return NULL;
1794	if (map->n == 0)
1795		return map;
1796
1797	map = isl_map_cow(map);
1798	if (!map)
1799		return NULL;
1800
1801	for (i = 0; i < map->n; ++i) {
1802		map->p[i] = isl_basic_map_remove_divs(map->p[i]);
1803		if (!map->p[i])
1804			goto error;
1805	}
1806	return map;
1807error:
1808	isl_map_free(map);
1809	return NULL;
1810}
1811
1812__isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set)
1813{
1814	return isl_map_remove_divs(set);
1815}
1816
1817struct isl_basic_map *isl_basic_map_remove_dims(struct isl_basic_map *bmap,
1818	enum isl_dim_type type, unsigned first, unsigned n)
1819{
1820	if (!bmap)
1821		return NULL;
1822	isl_assert(bmap->ctx, first + n <= isl_basic_map_dim(bmap, type),
1823			goto error);
1824	if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
1825		return bmap;
1826	bmap = isl_basic_map_eliminate_vars(bmap,
1827			isl_basic_map_offset(bmap, type) - 1 + first, n);
1828	if (!bmap)
1829		return bmap;
1830	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div)
1831		return bmap;
1832	bmap = isl_basic_map_drop(bmap, type, first, n);
1833	return bmap;
1834error:
1835	isl_basic_map_free(bmap);
1836	return NULL;
1837}
1838
1839/* Return true if the definition of the given div (recursively) involves
1840 * any of the given variables.
1841 */
1842static int div_involves_vars(__isl_keep isl_basic_map *bmap, int div,
1843	unsigned first, unsigned n)
1844{
1845	int i;
1846	unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
1847
1848	if (isl_int_is_zero(bmap->div[div][0]))
1849		return 0;
1850	if (isl_seq_first_non_zero(bmap->div[div] + 1 + first, n) >= 0)
1851		return 1;
1852
1853	for (i = bmap->n_div - 1; i >= 0; --i) {
1854		if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
1855			continue;
1856		if (div_involves_vars(bmap, i, first, n))
1857			return 1;
1858	}
1859
1860	return 0;
1861}
1862
1863/* Try and add a lower and/or upper bound on "div" to "bmap"
1864 * based on inequality "i".
1865 * "total" is the total number of variables (excluding the divs).
1866 * "v" is a temporary object that can be used during the calculations.
1867 * If "lb" is set, then a lower bound should be constructed.
1868 * If "ub" is set, then an upper bound should be constructed.
1869 *
1870 * The calling function has already checked that the inequality does not
1871 * reference "div", but we still need to check that the inequality is
1872 * of the right form.  We'll consider the case where we want to construct
1873 * a lower bound.  The construction of upper bounds is similar.
1874 *
1875 * Let "div" be of the form
1876 *
1877 *	q = floor((a + f(x))/d)
1878 *
1879 * We essentially check if constraint "i" is of the form
1880 *
1881 *	b + f(x) >= 0
1882 *
1883 * so that we can use it to derive a lower bound on "div".
1884 * However, we allow a slightly more general form
1885 *
1886 *	b + g(x) >= 0
1887 *
1888 * with the condition that the coefficients of g(x) - f(x) are all
1889 * divisible by d.
1890 * Rewriting this constraint as
1891 *
1892 *	0 >= -b - g(x)
1893 *
1894 * adding a + f(x) to both sides and dividing by d, we obtain
1895 *
1896 *	(a + f(x))/d >= (a-b)/d + (f(x)-g(x))/d
1897 *
1898 * Taking the floor on both sides, we obtain
1899 *
1900 *	q >= floor((a-b)/d) + (f(x)-g(x))/d
1901 *
1902 * or
1903 *
1904 *	(g(x)-f(x))/d + ceil((b-a)/d) + q >= 0
1905 *
1906 * In the case of an upper bound, we construct the constraint
1907 *
1908 *	(g(x)+f(x))/d + floor((b+a)/d) - q >= 0
1909 *
1910 */
1911static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq(
1912	__isl_take isl_basic_map *bmap, int div, int i,
1913	unsigned total, isl_int v, int lb, int ub)
1914{
1915	int j;
1916
1917	for (j = 0; (lb || ub) && j < total + bmap->n_div; ++j) {
1918		if (lb) {
1919			isl_int_sub(v, bmap->ineq[i][1 + j],
1920					bmap->div[div][1 + 1 + j]);
1921			lb = isl_int_is_divisible_by(v, bmap->div[div][0]);
1922		}
1923		if (ub) {
1924			isl_int_add(v, bmap->ineq[i][1 + j],
1925					bmap->div[div][1 + 1 + j]);
1926			ub = isl_int_is_divisible_by(v, bmap->div[div][0]);
1927		}
1928	}
1929	if (!lb && !ub)
1930		return bmap;
1931
1932	bmap = isl_basic_map_extend_constraints(bmap, 0, lb + ub);
1933	if (lb) {
1934		int k = isl_basic_map_alloc_inequality(bmap);
1935		if (k < 0)
1936			goto error;
1937		for (j = 0; j < 1 + total + bmap->n_div; ++j) {
1938			isl_int_sub(bmap->ineq[k][j], bmap->ineq[i][j],
1939					bmap->div[div][1 + j]);
1940			isl_int_cdiv_q(bmap->ineq[k][j],
1941					bmap->ineq[k][j], bmap->div[div][0]);
1942		}
1943		isl_int_set_si(bmap->ineq[k][1 + total + div], 1);
1944	}
1945	if (ub) {
1946		int k = isl_basic_map_alloc_inequality(bmap);
1947		if (k < 0)
1948			goto error;
1949		for (j = 0; j < 1 + total + bmap->n_div; ++j) {
1950			isl_int_add(bmap->ineq[k][j], bmap->ineq[i][j],
1951					bmap->div[div][1 + j]);
1952			isl_int_fdiv_q(bmap->ineq[k][j],
1953					bmap->ineq[k][j], bmap->div[div][0]);
1954		}
1955		isl_int_set_si(bmap->ineq[k][1 + total + div], -1);
1956	}
1957
1958	return bmap;
1959error:
1960	isl_basic_map_free(bmap);
1961	return NULL;
1962}
1963
1964/* This function is called right before "div" is eliminated from "bmap"
1965 * using Fourier-Motzkin.
1966 * Look through the constraints of "bmap" for constraints on the argument
1967 * of the integer division and use them to construct constraints on the
1968 * integer division itself.  These constraints can then be combined
1969 * during the Fourier-Motzkin elimination.
1970 * Note that it is only useful to introduce lower bounds on "div"
1971 * if "bmap" already contains upper bounds on "div" as the newly
1972 * introduce lower bounds can then be combined with the pre-existing
1973 * upper bounds.  Similarly for upper bounds.
1974 * We therefore first check if "bmap" contains any lower and/or upper bounds
1975 * on "div".
1976 *
1977 * It is interesting to note that the introduction of these constraints
1978 * can indeed lead to more accurate results, even when compared to
1979 * deriving constraints on the argument of "div" from constraints on "div".
1980 * Consider, for example, the set
1981 *
1982 *	{ [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }
1983 *
1984 * The second constraint can be rewritten as
1985 *
1986 *	2 * [(-i-2j+3)/4] + k >= 0
1987 *
1988 * from which we can derive
1989 *
1990 *	-i - 2j + 3 >= -2k
1991 *
1992 * or
1993 *
1994 *	i + 2j <= 3 + 2k
1995 *
1996 * Combined with the first constraint, we obtain
1997 *
1998 *	-3 <= 3 + 2k	or	k >= -3
1999 *
2000 * If, on the other hand we derive a constraint on [(i+2j)/4] from
2001 * the first constraint, we obtain
2002 *
2003 *	[(i + 2j)/4] >= [-3/4] = -1
2004 *
2005 * Combining this constraint with the second constraint, we obtain
2006 *
2007 *	k >= -2
2008 */
2009static __isl_give isl_basic_map *insert_bounds_on_div(
2010	__isl_take isl_basic_map *bmap, int div)
2011{
2012	int i;
2013	int check_lb, check_ub;
2014	isl_int v;
2015	unsigned total;
2016
2017	if (!bmap)
2018		return NULL;
2019
2020	if (isl_int_is_zero(bmap->div[div][0]))
2021		return bmap;
2022
2023	total = isl_space_dim(bmap->dim, isl_dim_all);
2024
2025	check_lb = 0;
2026	check_ub = 0;
2027	for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) {
2028		int s = isl_int_sgn(bmap->ineq[i][1 + total + div]);
2029		if (s > 0)
2030			check_ub = 1;
2031		if (s < 0)
2032			check_lb = 1;
2033	}
2034
2035	if (!check_lb && !check_ub)
2036		return bmap;
2037
2038	isl_int_init(v);
2039
2040	for (i = 0; bmap && i < bmap->n_ineq; ++i) {
2041		if (!isl_int_is_zero(bmap->ineq[i][1 + total + div]))
2042			continue;
2043
2044		bmap = insert_bounds_on_div_from_ineq(bmap, div, i, total, v,
2045							check_lb, check_ub);
2046	}
2047
2048	isl_int_clear(v);
2049
2050	return bmap;
2051}
2052
2053/* Remove all divs (recursively) involving any of the given dimensions
2054 * in their definitions.
2055 */
2056__isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(
2057	__isl_take isl_basic_map *bmap,
2058	enum isl_dim_type type, unsigned first, unsigned n)
2059{
2060	int i;
2061
2062	if (!bmap)
2063		return NULL;
2064	isl_assert(bmap->ctx, first + n <= isl_basic_map_dim(bmap, type),
2065			goto error);
2066	first += isl_basic_map_offset(bmap, type);
2067
2068	for (i = bmap->n_div - 1; i >= 0; --i) {
2069		if (!div_involves_vars(bmap, i, first, n))
2070			continue;
2071		bmap = insert_bounds_on_div(bmap, i);
2072		bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
2073		if (!bmap)
2074			return NULL;
2075		i = bmap->n_div;
2076	}
2077
2078	return bmap;
2079error:
2080	isl_basic_map_free(bmap);
2081	return NULL;
2082}
2083
2084__isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(
2085	__isl_take isl_basic_set *bset,
2086	enum isl_dim_type type, unsigned first, unsigned n)
2087{
2088	return isl_basic_map_remove_divs_involving_dims(bset, type, first, n);
2089}
2090
2091__isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,
2092	enum isl_dim_type type, unsigned first, unsigned n)
2093{
2094	int i;
2095
2096	if (!map)
2097		return NULL;
2098	if (map->n == 0)
2099		return map;
2100
2101	map = isl_map_cow(map);
2102	if (!map)
2103		return NULL;
2104
2105	for (i = 0; i < map->n; ++i) {
2106		map->p[i] = isl_basic_map_remove_divs_involving_dims(map->p[i],
2107								type, first, n);
2108		if (!map->p[i])
2109			goto error;
2110	}
2111	return map;
2112error:
2113	isl_map_free(map);
2114	return NULL;
2115}
2116
2117__isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,
2118	enum isl_dim_type type, unsigned first, unsigned n)
2119{
2120	return (isl_set *)isl_map_remove_divs_involving_dims((isl_map *)set,
2121							      type, first, n);
2122}
2123
2124/* Does the desciption of "bmap" depend on the specified dimensions?
2125 * We also check whether the dimensions appear in any of the div definitions.
2126 * In principle there is no need for this check.  If the dimensions appear
2127 * in a div definition, they also appear in the defining constraints of that
2128 * div.
2129 */
2130int isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,
2131	enum isl_dim_type type, unsigned first, unsigned n)
2132{
2133	int i;
2134
2135	if (!bmap)
2136		return -1;
2137
2138	if (first + n > isl_basic_map_dim(bmap, type))
2139		isl_die(bmap->ctx, isl_error_invalid,
2140			"index out of bounds", return -1);
2141
2142	first += isl_basic_map_offset(bmap, type);
2143	for (i = 0; i < bmap->n_eq; ++i)
2144		if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0)
2145			return 1;
2146	for (i = 0; i < bmap->n_ineq; ++i)
2147		if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0)
2148			return 1;
2149	for (i = 0; i < bmap->n_div; ++i) {
2150		if (isl_int_is_zero(bmap->div[i][0]))
2151			continue;
2152		if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0)
2153			return 1;
2154	}
2155
2156	return 0;
2157}
2158
2159int isl_map_involves_dims(__isl_keep isl_map *map,
2160	enum isl_dim_type type, unsigned first, unsigned n)
2161{
2162	int i;
2163
2164	if (!map)
2165		return -1;
2166
2167	if (first + n > isl_map_dim(map, type))
2168		isl_die(map->ctx, isl_error_invalid,
2169			"index out of bounds", return -1);
2170
2171	for (i = 0; i < map->n; ++i) {
2172		int involves = isl_basic_map_involves_dims(map->p[i],
2173							    type, first, n);
2174		if (involves < 0 || involves)
2175			return involves;
2176	}
2177
2178	return 0;
2179}
2180
2181int isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,
2182	enum isl_dim_type type, unsigned first, unsigned n)
2183{
2184	return isl_basic_map_involves_dims(bset, type, first, n);
2185}
2186
2187int isl_set_involves_dims(__isl_keep isl_set *set,
2188	enum isl_dim_type type, unsigned first, unsigned n)
2189{
2190	return isl_map_involves_dims(set, type, first, n);
2191}
2192
2193/* Return true if the definition of the given div is unknown or depends
2194 * on unknown divs.
2195 */
2196static int div_is_unknown(__isl_keep isl_basic_map *bmap, int div)
2197{
2198	int i;
2199	unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
2200
2201	if (isl_int_is_zero(bmap->div[div][0]))
2202		return 1;
2203
2204	for (i = bmap->n_div - 1; i >= 0; --i) {
2205		if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
2206			continue;
2207		if (div_is_unknown(bmap, i))
2208			return 1;
2209	}
2210
2211	return 0;
2212}
2213
2214/* Remove all divs that are unknown or defined in terms of unknown divs.
2215 */
2216__isl_give isl_basic_map *isl_basic_map_remove_unknown_divs(
2217	__isl_take isl_basic_map *bmap)
2218{
2219	int i;
2220
2221	if (!bmap)
2222		return NULL;
2223
2224	for (i = bmap->n_div - 1; i >= 0; --i) {
2225		if (!div_is_unknown(bmap, i))
2226			continue;
2227		bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
2228		if (!bmap)
2229			return NULL;
2230		i = bmap->n_div;
2231	}
2232
2233	return bmap;
2234}
2235
2236/* Remove all divs that are unknown or defined in terms of unknown divs.
2237 */
2238__isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(
2239	__isl_take isl_basic_set *bset)
2240{
2241	return isl_basic_map_remove_unknown_divs(bset);
2242}
2243
2244__isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map)
2245{
2246	int i;
2247
2248	if (!map)
2249		return NULL;
2250	if (map->n == 0)
2251		return map;
2252
2253	map = isl_map_cow(map);
2254	if (!map)
2255		return NULL;
2256
2257	for (i = 0; i < map->n; ++i) {
2258		map->p[i] = isl_basic_map_remove_unknown_divs(map->p[i]);
2259		if (!map->p[i])
2260			goto error;
2261	}
2262	return map;
2263error:
2264	isl_map_free(map);
2265	return NULL;
2266}
2267
2268__isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set)
2269{
2270	return (isl_set *)isl_map_remove_unknown_divs((isl_map *)set);
2271}
2272
2273__isl_give isl_basic_set *isl_basic_set_remove_dims(
2274	__isl_take isl_basic_set *bset,
2275	enum isl_dim_type type, unsigned first, unsigned n)
2276{
2277	return (isl_basic_set *)
2278	    isl_basic_map_remove_dims((isl_basic_map *)bset, type, first, n);
2279}
2280
2281struct isl_map *isl_map_remove_dims(struct isl_map *map,
2282	enum isl_dim_type type, unsigned first, unsigned n)
2283{
2284	int i;
2285
2286	if (n == 0)
2287		return map;
2288
2289	map = isl_map_cow(map);
2290	if (!map)
2291		return NULL;
2292	isl_assert(map->ctx, first + n <= isl_map_dim(map, type), goto error);
2293
2294	for (i = 0; i < map->n; ++i) {
2295		map->p[i] = isl_basic_map_eliminate_vars(map->p[i],
2296			isl_basic_map_offset(map->p[i], type) - 1 + first, n);
2297		if (!map->p[i])
2298			goto error;
2299	}
2300	map = isl_map_drop(map, type, first, n);
2301	return map;
2302error:
2303	isl_map_free(map);
2304	return NULL;
2305}
2306
2307__isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,
2308	enum isl_dim_type type, unsigned first, unsigned n)
2309{
2310	return (isl_set *)isl_map_remove_dims((isl_map *)bset, type, first, n);
2311}
2312
2313/* Project out n inputs starting at first using Fourier-Motzkin */
2314struct isl_map *isl_map_remove_inputs(struct isl_map *map,
2315	unsigned first, unsigned n)
2316{
2317	return isl_map_remove_dims(map, isl_dim_in, first, n);
2318}
2319
2320static void dump_term(struct isl_basic_map *bmap,
2321			isl_int c, int pos, FILE *out)
2322{
2323	const char *name;
2324	unsigned in = isl_basic_map_n_in(bmap);
2325	unsigned dim = in + isl_basic_map_n_out(bmap);
2326	unsigned nparam = isl_basic_map_n_param(bmap);
2327	if (!pos)
2328		isl_int_print(out, c, 0);
2329	else {
2330		if (!isl_int_is_one(c))
2331			isl_int_print(out, c, 0);
2332		if (pos < 1 + nparam) {
2333			name = isl_space_get_dim_name(bmap->dim,
2334						isl_dim_param, pos - 1);
2335			if (name)
2336				fprintf(out, "%s", name);
2337			else
2338				fprintf(out, "p%d", pos - 1);
2339		} else if (pos < 1 + nparam + in)
2340			fprintf(out, "i%d", pos - 1 - nparam);
2341		else if (pos < 1 + nparam + dim)
2342			fprintf(out, "o%d", pos - 1 - nparam - in);
2343		else
2344			fprintf(out, "e%d", pos - 1 - nparam - dim);
2345	}
2346}
2347
2348static void dump_constraint_sign(struct isl_basic_map *bmap, isl_int *c,
2349				int sign, FILE *out)
2350{
2351	int i;
2352	int first;
2353	unsigned len = 1 + isl_basic_map_total_dim(bmap);
2354	isl_int v;
2355
2356	isl_int_init(v);
2357	for (i = 0, first = 1; i < len; ++i) {
2358		if (isl_int_sgn(c[i]) * sign <= 0)
2359			continue;
2360		if (!first)
2361			fprintf(out, " + ");
2362		first = 0;
2363		isl_int_abs(v, c[i]);
2364		dump_term(bmap, v, i, out);
2365	}
2366	isl_int_clear(v);
2367	if (first)
2368		fprintf(out, "0");
2369}
2370
2371static void dump_constraint(struct isl_basic_map *bmap, isl_int *c,
2372				const char *op, FILE *out, int indent)
2373{
2374	int i;
2375
2376	fprintf(out, "%*s", indent, "");
2377
2378	dump_constraint_sign(bmap, c, 1, out);
2379	fprintf(out, " %s ", op);
2380	dump_constraint_sign(bmap, c, -1, out);
2381
2382	fprintf(out, "\n");
2383
2384	for (i = bmap->n_div; i < bmap->extra; ++i) {
2385		if (isl_int_is_zero(c[1+isl_space_dim(bmap->dim, isl_dim_all)+i]))
2386			continue;
2387		fprintf(out, "%*s", indent, "");
2388		fprintf(out, "ERROR: unused div coefficient not zero\n");
2389		abort();
2390	}
2391}
2392
2393static void dump_constraints(struct isl_basic_map *bmap,
2394				isl_int **c, unsigned n,
2395				const char *op, FILE *out, int indent)
2396{
2397	int i;
2398
2399	for (i = 0; i < n; ++i)
2400		dump_constraint(bmap, c[i], op, out, indent);
2401}
2402
2403static void dump_affine(struct isl_basic_map *bmap, isl_int *exp, FILE *out)
2404{
2405	int j;
2406	int first = 1;
2407	unsigned total = isl_basic_map_total_dim(bmap);
2408
2409	for (j = 0; j < 1 + total; ++j) {
2410		if (isl_int_is_zero(exp[j]))
2411			continue;
2412		if (!first && isl_int_is_pos(exp[j]))
2413			fprintf(out, "+");
2414		dump_term(bmap, exp[j], j, out);
2415		first = 0;
2416	}
2417}
2418
2419static void dump(struct isl_basic_map *bmap, FILE *out, int indent)
2420{
2421	int i;
2422
2423	dump_constraints(bmap, bmap->eq, bmap->n_eq, "=", out, indent);
2424	dump_constraints(bmap, bmap->ineq, bmap->n_ineq, ">=", out, indent);
2425
2426	for (i = 0; i < bmap->n_div; ++i) {
2427		fprintf(out, "%*s", indent, "");
2428		fprintf(out, "e%d = [(", i);
2429		dump_affine(bmap, bmap->div[i]+1, out);
2430		fprintf(out, ")/");
2431		isl_int_print(out, bmap->div[i][0], 0);
2432		fprintf(out, "]\n");
2433	}
2434}
2435
2436void isl_basic_set_print_internal(struct isl_basic_set *bset,
2437	FILE *out, int indent)
2438{
2439	if (!bset) {
2440		fprintf(out, "null basic set\n");
2441		return;
2442	}
2443
2444	fprintf(out, "%*s", indent, "");
2445	fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",
2446			bset->ref, bset->dim->nparam, bset->dim->n_out,
2447			bset->extra, bset->flags);
2448	dump((struct isl_basic_map *)bset, out, indent);
2449}
2450
2451void isl_basic_map_print_internal(struct isl_basic_map *bmap,
2452	FILE *out, int indent)
2453{
2454	if (!bmap) {
2455		fprintf(out, "null basic map\n");
2456		return;
2457	}
2458
2459	fprintf(out, "%*s", indent, "");
2460	fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, "
2461			"flags: %x, n_name: %d\n",
2462		bmap->ref,
2463		bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out,
2464		bmap->extra, bmap->flags, bmap->dim->n_id);
2465	dump(bmap, out, indent);
2466}
2467
2468int isl_inequality_negate(struct isl_basic_map *bmap, unsigned pos)
2469{
2470	unsigned total;
2471	if (!bmap)
2472		return -1;
2473	total = isl_basic_map_total_dim(bmap);
2474	isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
2475	isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);
2476	isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);
2477	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
2478	return 0;
2479}
2480
2481__isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *dim, int n,
2482	unsigned flags)
2483{
2484	struct isl_set *set;
2485
2486	if (!dim)
2487		return NULL;
2488	isl_assert(dim->ctx, dim->n_in == 0, goto error);
2489	isl_assert(dim->ctx, n >= 0, goto error);
2490	set = isl_alloc(dim->ctx, struct isl_set,
2491			sizeof(struct isl_set) +
2492			(n - 1) * sizeof(struct isl_basic_set *));
2493	if (!set)
2494		goto error;
2495
2496	set->ctx = dim->ctx;
2497	isl_ctx_ref(set->ctx);
2498	set->ref = 1;
2499	set->size = n;
2500	set->n = 0;
2501	set->dim = dim;
2502	set->flags = flags;
2503	return set;
2504error:
2505	isl_space_free(dim);
2506	return NULL;
2507}
2508
2509struct isl_set *isl_set_alloc(struct isl_ctx *ctx,
2510		unsigned nparam, unsigned dim, int n, unsigned flags)
2511{
2512	struct isl_set *set;
2513	isl_space *dims;
2514
2515	dims = isl_space_alloc(ctx, nparam, 0, dim);
2516	if (!dims)
2517		return NULL;
2518
2519	set = isl_set_alloc_space(dims, n, flags);
2520	return set;
2521}
2522
2523/* Make sure "map" has room for at least "n" more basic maps.
2524 */
2525struct isl_map *isl_map_grow(struct isl_map *map, int n)
2526{
2527	int i;
2528	struct isl_map *grown = NULL;
2529
2530	if (!map)
2531		return NULL;
2532	isl_assert(map->ctx, n >= 0, goto error);
2533	if (map->n + n <= map->size)
2534		return map;
2535	grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags);
2536	if (!grown)
2537		goto error;
2538	for (i = 0; i < map->n; ++i) {
2539		grown->p[i] = isl_basic_map_copy(map->p[i]);
2540		if (!grown->p[i])
2541			goto error;
2542		grown->n++;
2543	}
2544	isl_map_free(map);
2545	return grown;
2546error:
2547	isl_map_free(grown);
2548	isl_map_free(map);
2549	return NULL;
2550}
2551
2552/* Make sure "set" has room for at least "n" more basic sets.
2553 */
2554struct isl_set *isl_set_grow(struct isl_set *set, int n)
2555{
2556	return (struct isl_set *)isl_map_grow((struct isl_map *)set, n);
2557}
2558
2559struct isl_set *isl_set_dup(struct isl_set *set)
2560{
2561	int i;
2562	struct isl_set *dup;
2563
2564	if (!set)
2565		return NULL;
2566
2567	dup = isl_set_alloc_space(isl_space_copy(set->dim), set->n, set->flags);
2568	if (!dup)
2569		return NULL;
2570	for (i = 0; i < set->n; ++i)
2571		dup = isl_set_add_basic_set(dup, isl_basic_set_copy(set->p[i]));
2572	return dup;
2573}
2574
2575struct isl_set *isl_set_from_basic_set(struct isl_basic_set *bset)
2576{
2577	return isl_map_from_basic_map(bset);
2578}
2579
2580struct isl_map *isl_map_from_basic_map(struct isl_basic_map *bmap)
2581{
2582	struct isl_map *map;
2583
2584	if (!bmap)
2585		return NULL;
2586
2587	map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT);
2588	return isl_map_add_basic_map(map, bmap);
2589}
2590
2591__isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,
2592						__isl_take isl_basic_set *bset)
2593{
2594	return (struct isl_set *)isl_map_add_basic_map((struct isl_map *)set,
2595						(struct isl_basic_map *)bset);
2596}
2597
2598void *isl_set_free(__isl_take isl_set *set)
2599{
2600	int i;
2601
2602	if (!set)
2603		return NULL;
2604
2605	if (--set->ref > 0)
2606		return NULL;
2607
2608	isl_ctx_deref(set->ctx);
2609	for (i = 0; i < set->n; ++i)
2610		isl_basic_set_free(set->p[i]);
2611	isl_space_free(set->dim);
2612	free(set);
2613
2614	return NULL;
2615}
2616
2617void isl_set_print_internal(struct isl_set *set, FILE *out, int indent)
2618{
2619	int i;
2620
2621	if (!set) {
2622		fprintf(out, "null set\n");
2623		return;
2624	}
2625
2626	fprintf(out, "%*s", indent, "");
2627	fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n",
2628			set->ref, set->n, set->dim->nparam, set->dim->n_out,
2629			set->flags);
2630	for (i = 0; i < set->n; ++i) {
2631		fprintf(out, "%*s", indent, "");
2632		fprintf(out, "basic set %d:\n", i);
2633		isl_basic_set_print_internal(set->p[i], out, indent+4);
2634	}
2635}
2636
2637void isl_map_print_internal(struct isl_map *map, FILE *out, int indent)
2638{
2639	int i;
2640
2641	if (!map) {
2642		fprintf(out, "null map\n");
2643		return;
2644	}
2645
2646	fprintf(out, "%*s", indent, "");
2647	fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, "
2648		     "flags: %x, n_name: %d\n",
2649			map->ref, map->n, map->dim->nparam, map->dim->n_in,
2650			map->dim->n_out, map->flags, map->dim->n_id);
2651	for (i = 0; i < map->n; ++i) {
2652		fprintf(out, "%*s", indent, "");
2653		fprintf(out, "basic map %d:\n", i);
2654		isl_basic_map_print_internal(map->p[i], out, indent+4);
2655	}
2656}
2657
2658struct isl_basic_map *isl_basic_map_intersect_domain(
2659		struct isl_basic_map *bmap, struct isl_basic_set *bset)
2660{
2661	struct isl_basic_map *bmap_domain;
2662
2663	if (!bmap || !bset)
2664		goto error;
2665
2666	isl_assert(bset->ctx, isl_space_match(bmap->dim, isl_dim_param,
2667					bset->dim, isl_dim_param), goto error);
2668
2669	if (isl_space_dim(bset->dim, isl_dim_set) != 0)
2670		isl_assert(bset->ctx,
2671		    isl_basic_map_compatible_domain(bmap, bset), goto error);
2672
2673	bmap = isl_basic_map_cow(bmap);
2674	if (!bmap)
2675		goto error;
2676	bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
2677			bset->n_div, bset->n_eq, bset->n_ineq);
2678	bmap_domain = isl_basic_map_from_domain(bset);
2679	bmap = add_constraints(bmap, bmap_domain, 0, 0);
2680
2681	bmap = isl_basic_map_simplify(bmap);
2682	return isl_basic_map_finalize(bmap);
2683error:
2684	isl_basic_map_free(bmap);
2685	isl_basic_set_free(bset);
2686	return NULL;
2687}
2688
2689struct isl_basic_map *isl_basic_map_intersect_range(
2690		struct isl_basic_map *bmap, struct isl_basic_set *bset)
2691{
2692	struct isl_basic_map *bmap_range;
2693
2694	if (!bmap || !bset)
2695		goto error;
2696
2697	isl_assert(bset->ctx, isl_space_match(bmap->dim, isl_dim_param,
2698					bset->dim, isl_dim_param), goto error);
2699
2700	if (isl_space_dim(bset->dim, isl_dim_set) != 0)
2701		isl_assert(bset->ctx,
2702		    isl_basic_map_compatible_range(bmap, bset), goto error);
2703
2704	if (isl_basic_set_is_universe(bset)) {
2705		isl_basic_set_free(bset);
2706		return bmap;
2707	}
2708
2709	bmap = isl_basic_map_cow(bmap);
2710	if (!bmap)
2711		goto error;
2712	bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
2713			bset->n_div, bset->n_eq, bset->n_ineq);
2714	bmap_range = isl_basic_map_from_basic_set(bset, isl_space_copy(bset->dim));
2715	bmap = add_constraints(bmap, bmap_range, 0, 0);
2716
2717	bmap = isl_basic_map_simplify(bmap);
2718	return isl_basic_map_finalize(bmap);
2719error:
2720	isl_basic_map_free(bmap);
2721	isl_basic_set_free(bset);
2722	return NULL;
2723}
2724
2725int isl_basic_map_contains(struct isl_basic_map *bmap, struct isl_vec *vec)
2726{
2727	int i;
2728	unsigned total;
2729	isl_int s;
2730
2731	if (!bmap || !vec)
2732		return -1;
2733
2734	total = 1 + isl_basic_map_total_dim(bmap);
2735	if (total != vec->size)
2736		return -1;
2737
2738	isl_int_init(s);
2739
2740	for (i = 0; i < bmap->n_eq; ++i) {
2741		isl_seq_inner_product(vec->el, bmap->eq[i], total, &s);
2742		if (!isl_int_is_zero(s)) {
2743			isl_int_clear(s);
2744			return 0;
2745		}
2746	}
2747
2748	for (i = 0; i < bmap->n_ineq; ++i) {
2749		isl_seq_inner_product(vec->el, bmap->ineq[i], total, &s);
2750		if (isl_int_is_neg(s)) {
2751			isl_int_clear(s);
2752			return 0;
2753		}
2754	}
2755
2756	isl_int_clear(s);
2757
2758	return 1;
2759}
2760
2761int isl_basic_set_contains(struct isl_basic_set *bset, struct isl_vec *vec)
2762{
2763	return isl_basic_map_contains((struct isl_basic_map *)bset, vec);
2764}
2765
2766struct isl_basic_map *isl_basic_map_intersect(
2767		struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
2768{
2769	struct isl_vec *sample = NULL;
2770
2771	if (!bmap1 || !bmap2)
2772		goto error;
2773
2774	isl_assert(bmap1->ctx, isl_space_match(bmap1->dim, isl_dim_param,
2775				     bmap2->dim, isl_dim_param), goto error);
2776	if (isl_space_dim(bmap1->dim, isl_dim_all) ==
2777				isl_space_dim(bmap1->dim, isl_dim_param) &&
2778	    isl_space_dim(bmap2->dim, isl_dim_all) !=
2779				isl_space_dim(bmap2->dim, isl_dim_param))
2780		return isl_basic_map_intersect(bmap2, bmap1);
2781
2782	if (isl_space_dim(bmap2->dim, isl_dim_all) !=
2783					isl_space_dim(bmap2->dim, isl_dim_param))
2784		isl_assert(bmap1->ctx,
2785			    isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
2786
2787	if (bmap1->sample &&
2788	    isl_basic_map_contains(bmap1, bmap1->sample) > 0 &&
2789	    isl_basic_map_contains(bmap2, bmap1->sample) > 0)
2790		sample = isl_vec_copy(bmap1->sample);
2791	else if (bmap2->sample &&
2792	    isl_basic_map_contains(bmap1, bmap2->sample) > 0 &&
2793	    isl_basic_map_contains(bmap2, bmap2->sample) > 0)
2794		sample = isl_vec_copy(bmap2->sample);
2795
2796	bmap1 = isl_basic_map_cow(bmap1);
2797	if (!bmap1)
2798		goto error;
2799	bmap1 = isl_basic_map_extend_space(bmap1, isl_space_copy(bmap1->dim),
2800			bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
2801	bmap1 = add_constraints(bmap1, bmap2, 0, 0);
2802
2803	if (!bmap1)
2804		isl_vec_free(sample);
2805	else if (sample) {
2806		isl_vec_free(bmap1->sample);
2807		bmap1->sample = sample;
2808	}
2809
2810	bmap1 = isl_basic_map_simplify(bmap1);
2811	return isl_basic_map_finalize(bmap1);
2812error:
2813	if (sample)
2814		isl_vec_free(sample);
2815	isl_basic_map_free(bmap1);
2816	isl_basic_map_free(bmap2);
2817	return NULL;
2818}
2819
2820struct isl_basic_set *isl_basic_set_intersect(
2821		struct isl_basic_set *bset1, struct isl_basic_set *bset2)
2822{
2823	return (struct isl_basic_set *)
2824		isl_basic_map_intersect(
2825			(struct isl_basic_map *)bset1,
2826			(struct isl_basic_map *)bset2);
2827}
2828
2829__isl_give isl_basic_set *isl_basic_set_intersect_params(
2830	__isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
2831{
2832	return isl_basic_set_intersect(bset1, bset2);
2833}
2834
2835/* Special case of isl_map_intersect, where both map1 and map2
2836 * are convex, without any divs and such that either map1 or map2
2837 * contains a single constraint.  This constraint is then simply
2838 * added to the other map.
2839 */
2840static __isl_give isl_map *map_intersect_add_constraint(
2841	__isl_take isl_map *map1, __isl_take isl_map *map2)
2842{
2843	isl_assert(map1->ctx, map1->n == 1, goto error);
2844	isl_assert(map2->ctx, map1->n == 1, goto error);
2845	isl_assert(map1->ctx, map1->p[0]->n_div == 0, goto error);
2846	isl_assert(map2->ctx, map1->p[0]->n_div == 0, goto error);
2847
2848	if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1)
2849		return isl_map_intersect(map2, map1);
2850
2851	isl_assert(map2->ctx,
2852		    map2->p[0]->n_eq + map2->p[0]->n_ineq == 1, goto error);
2853
2854	map1 = isl_map_cow(map1);
2855	if (!map1)
2856		goto error;
2857	if (isl_map_plain_is_empty(map1)) {
2858		isl_map_free(map2);
2859		return map1;
2860	}
2861	map1->p[0] = isl_basic_map_cow(map1->p[0]);
2862	if (map2->p[0]->n_eq == 1)
2863		map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]);
2864	else
2865		map1->p[0] = isl_basic_map_add_ineq(map1->p[0],
2866							map2->p[0]->ineq[0]);
2867
2868	map1->p[0] = isl_basic_map_simplify(map1->p[0]);
2869	map1->p[0] = isl_basic_map_finalize(map1->p[0]);
2870	if (!map1->p[0])
2871		goto error;
2872
2873	if (isl_basic_map_plain_is_empty(map1->p[0])) {
2874		isl_basic_map_free(map1->p[0]);
2875		map1->n = 0;
2876	}
2877
2878	isl_map_free(map2);
2879
2880	return map1;
2881error:
2882	isl_map_free(map1);
2883	isl_map_free(map2);
2884	return NULL;
2885}
2886
2887/* map2 may be either a parameter domain or a map living in the same
2888 * space as map1.
2889 */
2890static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
2891	__isl_take isl_map *map2)
2892{
2893	unsigned flags = 0;
2894	isl_map *result;
2895	int i, j;
2896
2897	if (!map1 || !map2)
2898		goto error;
2899
2900	if ((isl_map_plain_is_empty(map1) ||
2901	     isl_map_plain_is_universe(map2)) &&
2902	    isl_space_is_equal(map1->dim, map2->dim)) {
2903		isl_map_free(map2);
2904		return map1;
2905	}
2906	if ((isl_map_plain_is_empty(map2) ||
2907	     isl_map_plain_is_universe(map1)) &&
2908	    isl_space_is_equal(map1->dim, map2->dim)) {
2909		isl_map_free(map1);
2910		return map2;
2911	}
2912
2913	if (map1->n == 1 && map2->n == 1 &&
2914	    map1->p[0]->n_div == 0 && map2->p[0]->n_div == 0 &&
2915	    isl_space_is_equal(map1->dim, map2->dim) &&
2916	    (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 ||
2917	     map2->p[0]->n_eq + map2->p[0]->n_ineq == 1))
2918		return map_intersect_add_constraint(map1, map2);
2919
2920	if (isl_space_dim(map2->dim, isl_dim_all) !=
2921				isl_space_dim(map2->dim, isl_dim_param))
2922		isl_assert(map1->ctx,
2923			    isl_space_is_equal(map1->dim, map2->dim), goto error);
2924
2925	if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
2926	    ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
2927		ISL_FL_SET(flags, ISL_MAP_DISJOINT);
2928
2929	result = isl_map_alloc_space(isl_space_copy(map1->dim),
2930				map1->n * map2->n, flags);
2931	if (!result)
2932		goto error;
2933	for (i = 0; i < map1->n; ++i)
2934		for (j = 0; j < map2->n; ++j) {
2935			struct isl_basic_map *part;
2936			part = isl_basic_map_intersect(
2937				    isl_basic_map_copy(map1->p[i]),
2938				    isl_basic_map_copy(map2->p[j]));
2939			if (isl_basic_map_is_empty(part) < 0)
2940				part = isl_basic_map_free(part);
2941			result = isl_map_add_basic_map(result, part);
2942			if (!result)
2943				goto error;
2944		}
2945	isl_map_free(map1);
2946	isl_map_free(map2);
2947	return result;
2948error:
2949	isl_map_free(map1);
2950	isl_map_free(map2);
2951	return NULL;
2952}
2953
2954static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
2955	__isl_take isl_map *map2)
2956{
2957	if (!map1 || !map2)
2958		goto error;
2959	if (!isl_space_is_equal(map1->dim, map2->dim))
2960		isl_die(isl_map_get_ctx(map1), isl_error_invalid,
2961			"spaces don't match", goto error);
2962	return map_intersect_internal(map1, map2);
2963error:
2964	isl_map_free(map1);
2965	isl_map_free(map2);
2966	return NULL;
2967}
2968
2969__isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
2970	__isl_take isl_map *map2)
2971{
2972	return isl_map_align_params_map_map_and(map1, map2, &map_intersect);
2973}
2974
2975struct isl_set *isl_set_intersect(struct isl_set *set1, struct isl_set *set2)
2976{
2977	return (struct isl_set *)
2978		isl_map_intersect((struct isl_map *)set1,
2979				  (struct isl_map *)set2);
2980}
2981
2982/* map_intersect_internal accepts intersections
2983 * with parameter domains, so we can just call that function.
2984 */
2985static __isl_give isl_map *map_intersect_params(__isl_take isl_map *map,
2986		__isl_take isl_set *params)
2987{
2988	return map_intersect_internal(map, params);
2989}
2990
2991__isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map1,
2992	__isl_take isl_map *map2)
2993{
2994	return isl_map_align_params_map_map_and(map1, map2, &map_intersect_params);
2995}
2996
2997__isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
2998		__isl_take isl_set *params)
2999{
3000	return isl_map_intersect_params(set, params);
3001}
3002
3003struct isl_basic_map *isl_basic_map_reverse(struct isl_basic_map *bmap)
3004{
3005	isl_space *dim;
3006	struct isl_basic_set *bset;
3007	unsigned in;
3008
3009	if (!bmap)
3010		return NULL;
3011	bmap = isl_basic_map_cow(bmap);
3012	if (!bmap)
3013		return NULL;
3014	dim = isl_space_reverse(isl_space_copy(bmap->dim));
3015	in = isl_basic_map_n_in(bmap);
3016	bset = isl_basic_set_from_basic_map(bmap);
3017	bset = isl_basic_set_swap_vars(bset, in);
3018	return isl_basic_map_from_basic_set(bset, dim);
3019}
3020
3021static __isl_give isl_basic_map *basic_map_space_reset(
3022	__isl_take isl_basic_map *bmap, enum isl_dim_type type)
3023{
3024	isl_space *space;
3025
3026	if (!bmap)
3027		return NULL;
3028	if (!isl_space_is_named_or_nested(bmap->dim, type))
3029		return bmap;
3030
3031	space = isl_basic_map_get_space(bmap);
3032	space = isl_space_reset(space, type);
3033	bmap = isl_basic_map_reset_space(bmap, space);
3034	return bmap;
3035}
3036
3037__isl_give isl_basic_map *isl_basic_map_insert_dims(
3038	__isl_take isl_basic_map *bmap, enum isl_dim_type type,
3039	unsigned pos, unsigned n)
3040{
3041	isl_space *res_dim;
3042	struct isl_basic_map *res;
3043	struct isl_dim_map *dim_map;
3044	unsigned total, off;
3045	enum isl_dim_type t;
3046
3047	if (n == 0)
3048		return basic_map_space_reset(bmap, type);
3049
3050	if (!bmap)
3051		return NULL;
3052
3053	res_dim = isl_space_insert_dims(isl_basic_map_get_space(bmap), type, pos, n);
3054
3055	total = isl_basic_map_total_dim(bmap) + n;
3056	dim_map = isl_dim_map_alloc(bmap->ctx, total);
3057	off = 0;
3058	for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3059		if (t != type) {
3060			isl_dim_map_dim(dim_map, bmap->dim, t, off);
3061		} else {
3062			unsigned size = isl_basic_map_dim(bmap, t);
3063			isl_dim_map_dim_range(dim_map, bmap->dim, t,
3064						0, pos, off);
3065			isl_dim_map_dim_range(dim_map, bmap->dim, t,
3066						pos, size - pos, off + pos + n);
3067		}
3068		off += isl_space_dim(res_dim, t);
3069	}
3070	isl_dim_map_div(dim_map, bmap, off);
3071
3072	res = isl_basic_map_alloc_space(res_dim,
3073			bmap->n_div, bmap->n_eq, bmap->n_ineq);
3074	if (isl_basic_map_is_rational(bmap))
3075		res = isl_basic_map_set_rational(res);
3076	if (isl_basic_map_plain_is_empty(bmap)) {
3077		isl_basic_map_free(bmap);
3078		free(dim_map);
3079		return isl_basic_map_set_to_empty(res);
3080	}
3081	res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3082	return isl_basic_map_finalize(res);
3083}
3084
3085__isl_give isl_basic_set *isl_basic_set_insert_dims(
3086	__isl_take isl_basic_set *bset,
3087	enum isl_dim_type type, unsigned pos, unsigned n)
3088{
3089	return isl_basic_map_insert_dims(bset, type, pos, n);
3090}
3091
3092__isl_give isl_basic_map *isl_basic_map_add(__isl_take isl_basic_map *bmap,
3093		enum isl_dim_type type, unsigned n)
3094{
3095	if (!bmap)
3096		return NULL;
3097	return isl_basic_map_insert_dims(bmap, type,
3098					isl_basic_map_dim(bmap, type), n);
3099}
3100
3101__isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
3102		enum isl_dim_type type, unsigned n)
3103{
3104	if (!bset)
3105		return NULL;
3106	isl_assert(bset->ctx, type != isl_dim_in, goto error);
3107	return (isl_basic_set *)isl_basic_map_add((isl_basic_map *)bset, type, n);
3108error:
3109	isl_basic_set_free(bset);
3110	return NULL;
3111}
3112
3113static __isl_give isl_map *map_space_reset(__isl_take isl_map *map,
3114	enum isl_dim_type type)
3115{
3116	isl_space *space;
3117
3118	if (!map || !isl_space_is_named_or_nested(map->dim, type))
3119		return map;
3120
3121	space = isl_map_get_space(map);
3122	space = isl_space_reset(space, type);
3123	map = isl_map_reset_space(map, space);
3124	return map;
3125}
3126
3127__isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
3128		enum isl_dim_type type, unsigned pos, unsigned n)
3129{
3130	int i;
3131
3132	if (n == 0)
3133		return map_space_reset(map, type);
3134
3135	map = isl_map_cow(map);
3136	if (!map)
3137		return NULL;
3138
3139	map->dim = isl_space_insert_dims(map->dim, type, pos, n);
3140	if (!map->dim)
3141		goto error;
3142
3143	for (i = 0; i < map->n; ++i) {
3144		map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n);
3145		if (!map->p[i])
3146			goto error;
3147	}
3148
3149	return map;
3150error:
3151	isl_map_free(map);
3152	return NULL;
3153}
3154
3155__isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
3156		enum isl_dim_type type, unsigned pos, unsigned n)
3157{
3158	return isl_map_insert_dims(set, type, pos, n);
3159}
3160
3161__isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
3162		enum isl_dim_type type, unsigned n)
3163{
3164	if (!map)
3165		return NULL;
3166	return isl_map_insert_dims(map, type, isl_map_dim(map, type), n);
3167}
3168
3169__isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
3170		enum isl_dim_type type, unsigned n)
3171{
3172	if (!set)
3173		return NULL;
3174	isl_assert(set->ctx, type != isl_dim_in, goto error);
3175	return (isl_set *)isl_map_add_dims((isl_map *)set, type, n);
3176error:
3177	isl_set_free(set);
3178	return NULL;
3179}
3180
3181__isl_give isl_basic_map *isl_basic_map_move_dims(
3182	__isl_take isl_basic_map *bmap,
3183	enum isl_dim_type dst_type, unsigned dst_pos,
3184	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3185{
3186	struct isl_dim_map *dim_map;
3187	struct isl_basic_map *res;
3188	enum isl_dim_type t;
3189	unsigned total, off;
3190
3191	if (!bmap)
3192		return NULL;
3193	if (n == 0)
3194		return bmap;
3195
3196	isl_assert(bmap->ctx, src_pos + n <= isl_basic_map_dim(bmap, src_type),
3197		goto error);
3198
3199	if (dst_type == src_type && dst_pos == src_pos)
3200		return bmap;
3201
3202	isl_assert(bmap->ctx, dst_type != src_type, goto error);
3203
3204	if (pos(bmap->dim, dst_type) + dst_pos ==
3205	    pos(bmap->dim, src_type) + src_pos +
3206					    ((src_type < dst_type) ? n : 0)) {
3207		bmap = isl_basic_map_cow(bmap);
3208		if (!bmap)
3209			return NULL;
3210
3211		bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
3212						src_type, src_pos, n);
3213		if (!bmap->dim)
3214			goto error;
3215
3216		bmap = isl_basic_map_finalize(bmap);
3217
3218		return bmap;
3219	}
3220
3221	total = isl_basic_map_total_dim(bmap);
3222	dim_map = isl_dim_map_alloc(bmap->ctx, total);
3223
3224	off = 0;
3225	for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3226		unsigned size = isl_space_dim(bmap->dim, t);
3227		if (t == dst_type) {
3228			isl_dim_map_dim_range(dim_map, bmap->dim, t,
3229					    0, dst_pos, off);
3230			off += dst_pos;
3231			isl_dim_map_dim_range(dim_map, bmap->dim, src_type,
3232					    src_pos, n, off);
3233			off += n;
3234			isl_dim_map_dim_range(dim_map, bmap->dim, t,
3235					    dst_pos, size - dst_pos, off);
3236			off += size - dst_pos;
3237		} else if (t == src_type) {
3238			isl_dim_map_dim_range(dim_map, bmap->dim, t,
3239					    0, src_pos, off);
3240			off += src_pos;
3241			isl_dim_map_dim_range(dim_map, bmap->dim, t,
3242					src_pos + n, size - src_pos - n, off);
3243			off += size - src_pos - n;
3244		} else {
3245			isl_dim_map_dim(dim_map, bmap->dim, t, off);
3246			off += size;
3247		}
3248	}
3249	isl_dim_map_div(dim_map, bmap, off);
3250
3251	res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
3252			bmap->n_div, bmap->n_eq, bmap->n_ineq);
3253	bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3254	if (!bmap)
3255		goto error;
3256
3257	bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
3258					src_type, src_pos, n);
3259	if (!bmap->dim)
3260		goto error;
3261
3262	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
3263	bmap = isl_basic_map_gauss(bmap, NULL);
3264	bmap = isl_basic_map_finalize(bmap);
3265
3266	return bmap;
3267error:
3268	isl_basic_map_free(bmap);
3269	return NULL;
3270}
3271
3272__isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,
3273	enum isl_dim_type dst_type, unsigned dst_pos,
3274	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3275{
3276	return (isl_basic_set *)isl_basic_map_move_dims(
3277		(isl_basic_map *)bset, dst_type, dst_pos, src_type, src_pos, n);
3278}
3279
3280__isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
3281	enum isl_dim_type dst_type, unsigned dst_pos,
3282	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3283{
3284	if (!set)
3285		return NULL;
3286	isl_assert(set->ctx, dst_type != isl_dim_in, goto error);
3287	return (isl_set *)isl_map_move_dims((isl_map *)set, dst_type, dst_pos,
3288					src_type, src_pos, n);
3289error:
3290	isl_set_free(set);
3291	return NULL;
3292}
3293
3294__isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
3295	enum isl_dim_type dst_type, unsigned dst_pos,
3296	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3297{
3298	int i;
3299
3300	if (!map)
3301		return NULL;
3302	if (n == 0)
3303		return map;
3304
3305	isl_assert(map->ctx, src_pos + n <= isl_map_dim(map, src_type),
3306		goto error);
3307
3308	if (dst_type == src_type && dst_pos == src_pos)
3309		return map;
3310
3311	isl_assert(map->ctx, dst_type != src_type, goto error);
3312
3313	map = isl_map_cow(map);
3314	if (!map)
3315		return NULL;
3316
3317	map->dim = isl_space_move_dims(map->dim, dst_type, dst_pos, src_type, src_pos, n);
3318	if (!map->dim)
3319		goto error;
3320
3321	for (i = 0; i < map->n; ++i) {
3322		map->p[i] = isl_basic_map_move_dims(map->p[i],
3323						dst_type, dst_pos,
3324						src_type, src_pos, n);
3325		if (!map->p[i])
3326			goto error;
3327	}
3328
3329	return map;
3330error:
3331	isl_map_free(map);
3332	return NULL;
3333}
3334
3335/* Move the specified dimensions to the last columns right before
3336 * the divs.  Don't change the dimension specification of bmap.
3337 * That's the responsibility of the caller.
3338 */
3339static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap,
3340	enum isl_dim_type type, unsigned first, unsigned n)
3341{
3342	struct isl_dim_map *dim_map;
3343	struct isl_basic_map *res;
3344	enum isl_dim_type t;
3345	unsigned total, off;
3346
3347	if (!bmap)
3348		return NULL;
3349	if (pos(bmap->dim, type) + first + n ==
3350				1 + isl_space_dim(bmap->dim, isl_dim_all))
3351		return bmap;
3352
3353	total = isl_basic_map_total_dim(bmap);
3354	dim_map = isl_dim_map_alloc(bmap->ctx, total);
3355
3356	off = 0;
3357	for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3358		unsigned size = isl_space_dim(bmap->dim, t);
3359		if (t == type) {
3360			isl_dim_map_dim_range(dim_map, bmap->dim, t,
3361					    0, first, off);
3362			off += first;
3363			isl_dim_map_dim_range(dim_map, bmap->dim, t,
3364					    first, n, total - bmap->n_div - n);
3365			isl_dim_map_dim_range(dim_map, bmap->dim, t,
3366					    first + n, size - (first + n), off);
3367			off += size - (first + n);
3368		} else {
3369			isl_dim_map_dim(dim_map, bmap->dim, t, off);
3370			off += size;
3371		}
3372	}
3373	isl_dim_map_div(dim_map, bmap, off + n);
3374
3375	res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
3376			bmap->n_div, bmap->n_eq, bmap->n_ineq);
3377	res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3378	return res;
3379}
3380
3381/* Insert "n" rows in the divs of "bmap".
3382 *
3383 * The number of columns is not changed, which means that the last
3384 * dimensions of "bmap" are being reintepreted as the new divs.
3385 * The space of "bmap" is not adjusted, however, which means
3386 * that "bmap" is left in an inconsistent state.  Removing "n" dimensions
3387 * from the space of "bmap" is the responsibility of the caller.
3388 */
3389static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap,
3390	int n)
3391{
3392	int i;
3393	size_t row_size;
3394	isl_int **new_div;
3395	isl_int *old;
3396
3397	bmap = isl_basic_map_cow(bmap);
3398	if (!bmap)
3399		return NULL;
3400
3401	row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + bmap->extra;
3402	old = bmap->block2.data;
3403	bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2,
3404					(bmap->extra + n) * (1 + row_size));
3405	if (!bmap->block2.data)
3406		return isl_basic_map_free(bmap);
3407	new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n);
3408	if (!new_div)
3409		return isl_basic_map_free(bmap);
3410	for (i = 0; i < n; ++i) {
3411		new_div[i] = bmap->block2.data +
3412				(bmap->extra + i) * (1 + row_size);
3413		isl_seq_clr(new_div[i], 1 + row_size);
3414	}
3415	for (i = 0; i < bmap->extra; ++i)
3416		new_div[n + i] = bmap->block2.data + (bmap->div[i] - old);
3417	free(bmap->div);
3418	bmap->div = new_div;
3419	bmap->n_div += n;
3420	bmap->extra += n;
3421
3422	return bmap;
3423}
3424
3425/* Turn the n dimensions of type type, starting at first
3426 * into existentially quantified variables.
3427 */
3428__isl_give isl_basic_map *isl_basic_map_project_out(
3429		__isl_take isl_basic_map *bmap,
3430		enum isl_dim_type type, unsigned first, unsigned n)
3431{
3432	if (n == 0)
3433		return basic_map_space_reset(bmap, type);
3434
3435	if (!bmap)
3436		return NULL;
3437
3438	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
3439		return isl_basic_map_remove_dims(bmap, type, first, n);
3440
3441	isl_assert(bmap->ctx, first + n <= isl_basic_map_dim(bmap, type),
3442			goto error);
3443
3444	bmap = move_last(bmap, type, first, n);
3445	bmap = isl_basic_map_cow(bmap);
3446	bmap = insert_div_rows(bmap, n);
3447	if (!bmap)
3448		return NULL;
3449
3450	bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
3451	if (!bmap->dim)
3452		goto error;
3453	bmap = isl_basic_map_simplify(bmap);
3454	bmap = isl_basic_map_drop_redundant_divs(bmap);
3455	return isl_basic_map_finalize(bmap);
3456error:
3457	isl_basic_map_free(bmap);
3458	return NULL;
3459}
3460
3461/* Turn the n dimensions of type type, starting at first
3462 * into existentially quantified variables.
3463 */
3464struct isl_basic_set *isl_basic_set_project_out(struct isl_basic_set *bset,
3465		enum isl_dim_type type, unsigned first, unsigned n)
3466{
3467	return (isl_basic_set *)isl_basic_map_project_out(
3468			(isl_basic_map *)bset, type, first, n);
3469}
3470
3471/* Turn the n dimensions of type type, starting at first
3472 * into existentially quantified variables.
3473 */
3474__isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
3475		enum isl_dim_type type, unsigned first, unsigned n)
3476{
3477	int i;
3478
3479	if (!map)
3480		return NULL;
3481
3482	if (n == 0)
3483		return map_space_reset(map, type);
3484
3485	isl_assert(map->ctx, first + n <= isl_map_dim(map, type), goto error);
3486
3487	map = isl_map_cow(map);
3488	if (!map)
3489		return NULL;
3490
3491	map->dim = isl_space_drop_dims(map->dim, type, first, n);
3492	if (!map->dim)
3493		goto error;
3494
3495	for (i = 0; i < map->n; ++i) {
3496		map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n);
3497		if (!map->p[i])
3498			goto error;
3499	}
3500
3501	return map;
3502error:
3503	isl_map_free(map);
3504	return NULL;
3505}
3506
3507/* Turn the n dimensions of type type, starting at first
3508 * into existentially quantified variables.
3509 */
3510__isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
3511		enum isl_dim_type type, unsigned first, unsigned n)
3512{
3513	return (isl_set *)isl_map_project_out((isl_map *)set, type, first, n);
3514}
3515
3516static struct isl_basic_map *add_divs(struct isl_basic_map *bmap, unsigned n)
3517{
3518	int i, j;
3519
3520	for (i = 0; i < n; ++i) {
3521		j = isl_basic_map_alloc_div(bmap);
3522		if (j < 0)
3523			goto error;
3524		isl_seq_clr(bmap->div[j], 1+1+isl_basic_map_total_dim(bmap));
3525	}
3526	return bmap;
3527error:
3528	isl_basic_map_free(bmap);
3529	return NULL;
3530}
3531
3532struct isl_basic_map *isl_basic_map_apply_range(
3533		struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
3534{
3535	isl_space *dim_result = NULL;
3536	struct isl_basic_map *bmap;
3537	unsigned n_in, n_out, n, nparam, total, pos;
3538	struct isl_dim_map *dim_map1, *dim_map2;
3539
3540	if (!bmap1 || !bmap2)
3541		goto error;
3542	if (!isl_space_match(bmap1->dim, isl_dim_param,
3543				bmap2->dim, isl_dim_param))
3544		isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
3545			"parameters don't match", goto error);
3546	if (!isl_space_tuple_match(bmap1->dim, isl_dim_out,
3547				    bmap2->dim, isl_dim_in))
3548		isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
3549			"spaces don't match", goto error);
3550
3551	dim_result = isl_space_join(isl_space_copy(bmap1->dim),
3552				  isl_space_copy(bmap2->dim));
3553
3554	n_in = isl_basic_map_n_in(bmap1);
3555	n_out = isl_basic_map_n_out(bmap2);
3556	n = isl_basic_map_n_out(bmap1);
3557	nparam = isl_basic_map_n_param(bmap1);
3558
3559	total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n;
3560	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
3561	dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
3562	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
3563	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
3564	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
3565	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in);
3566	isl_dim_map_div(dim_map1, bmap1, pos += n_out);
3567	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
3568	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
3569	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
3570
3571	bmap = isl_basic_map_alloc_space(dim_result,
3572			bmap1->n_div + bmap2->n_div + n,
3573			bmap1->n_eq + bmap2->n_eq,
3574			bmap1->n_ineq + bmap2->n_ineq);
3575	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
3576	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
3577	bmap = add_divs(bmap, n);
3578	bmap = isl_basic_map_simplify(bmap);
3579	bmap = isl_basic_map_drop_redundant_divs(bmap);
3580	return isl_basic_map_finalize(bmap);
3581error:
3582	isl_basic_map_free(bmap1);
3583	isl_basic_map_free(bmap2);
3584	return NULL;
3585}
3586
3587struct isl_basic_set *isl_basic_set_apply(
3588		struct isl_basic_set *bset, struct isl_basic_map *bmap)
3589{
3590	if (!bset || !bmap)
3591		goto error;
3592
3593	isl_assert(bset->ctx, isl_basic_map_compatible_domain(bmap, bset),
3594		    goto error);
3595
3596	return (struct isl_basic_set *)
3597		isl_basic_map_apply_range((struct isl_basic_map *)bset, bmap);
3598error:
3599	isl_basic_set_free(bset);
3600	isl_basic_map_free(bmap);
3601	return NULL;
3602}
3603
3604struct isl_basic_map *isl_basic_map_apply_domain(
3605		struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
3606{
3607	if (!bmap1 || !bmap2)
3608		goto error;
3609
3610	isl_assert(bmap1->ctx,
3611	    isl_basic_map_n_in(bmap1) == isl_basic_map_n_in(bmap2), goto error);
3612	isl_assert(bmap1->ctx,
3613	    isl_basic_map_n_param(bmap1) == isl_basic_map_n_param(bmap2),
3614	    goto error);
3615
3616	bmap1 = isl_basic_map_reverse(bmap1);
3617	bmap1 = isl_basic_map_apply_range(bmap1, bmap2);
3618	return isl_basic_map_reverse(bmap1);
3619error:
3620	isl_basic_map_free(bmap1);
3621	isl_basic_map_free(bmap2);
3622	return NULL;
3623}
3624
3625/* Given two basic maps A -> f(A) and B -> g(B), construct a basic map
3626 * A \cap B -> f(A) + f(B)
3627 */
3628struct isl_basic_map *isl_basic_map_sum(
3629		struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
3630{
3631	unsigned n_in, n_out, nparam, total, pos;
3632	struct isl_basic_map *bmap = NULL;
3633	struct isl_dim_map *dim_map1, *dim_map2;
3634	int i;
3635
3636	if (!bmap1 || !bmap2)
3637		goto error;
3638
3639	isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim),
3640		goto error);
3641
3642	nparam = isl_basic_map_n_param(bmap1);
3643	n_in = isl_basic_map_n_in(bmap1);
3644	n_out = isl_basic_map_n_out(bmap1);
3645
3646	total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out;
3647	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
3648	dim_map2 = isl_dim_map_alloc(bmap2->ctx, total);
3649	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
3650	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos);
3651	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
3652	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
3653	isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out);
3654	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
3655	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
3656	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out);
3657
3658	bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim),
3659			bmap1->n_div + bmap2->n_div + 2 * n_out,
3660			bmap1->n_eq + bmap2->n_eq + n_out,
3661			bmap1->n_ineq + bmap2->n_ineq);
3662	for (i = 0; i < n_out; ++i) {
3663		int j = isl_basic_map_alloc_equality(bmap);
3664		if (j < 0)
3665			goto error;
3666		isl_seq_clr(bmap->eq[j], 1+total);
3667		isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1);
3668		isl_int_set_si(bmap->eq[j][1+pos+i], 1);
3669		isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1);
3670	}
3671	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
3672	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
3673	bmap = add_divs(bmap, 2 * n_out);
3674
3675	bmap = isl_basic_map_simplify(bmap);
3676	return isl_basic_map_finalize(bmap);
3677error:
3678	isl_basic_map_free(bmap);
3679	isl_basic_map_free(bmap1);
3680	isl_basic_map_free(bmap2);
3681	return NULL;
3682}
3683
3684/* Given two maps A -> f(A) and B -> g(B), construct a map
3685 * A \cap B -> f(A) + f(B)
3686 */
3687struct isl_map *isl_map_sum(struct isl_map *map1, struct isl_map *map2)
3688{
3689	struct isl_map *result;
3690	int i, j;
3691
3692	if (!map1 || !map2)
3693		goto error;
3694
3695	isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
3696
3697	result = isl_map_alloc_space(isl_space_copy(map1->dim),
3698				map1->n * map2->n, 0);
3699	if (!result)
3700		goto error;
3701	for (i = 0; i < map1->n; ++i)
3702		for (j = 0; j < map2->n; ++j) {
3703			struct isl_basic_map *part;
3704			part = isl_basic_map_sum(
3705				    isl_basic_map_copy(map1->p[i]),
3706				    isl_basic_map_copy(map2->p[j]));
3707			if (isl_basic_map_is_empty(part))
3708				isl_basic_map_free(part);
3709			else
3710				result = isl_map_add_basic_map(result, part);
3711			if (!result)
3712				goto error;
3713		}
3714	isl_map_free(map1);
3715	isl_map_free(map2);
3716	return result;
3717error:
3718	isl_map_free(map1);
3719	isl_map_free(map2);
3720	return NULL;
3721}
3722
3723__isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
3724	__isl_take isl_set *set2)
3725{
3726	return (isl_set *)isl_map_sum((isl_map *)set1, (isl_map *)set2);
3727}
3728
3729/* Given a basic map A -> f(A), construct A -> -f(A).
3730 */
3731struct isl_basic_map *isl_basic_map_neg(struct isl_basic_map *bmap)
3732{
3733	int i, j;
3734	unsigned off, n;
3735
3736	bmap = isl_basic_map_cow(bmap);
3737	if (!bmap)
3738		return NULL;
3739
3740	n = isl_basic_map_dim(bmap, isl_dim_out);
3741	off = isl_basic_map_offset(bmap, isl_dim_out);
3742	for (i = 0; i < bmap->n_eq; ++i)
3743		for (j = 0; j < n; ++j)
3744			isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]);
3745	for (i = 0; i < bmap->n_ineq; ++i)
3746		for (j = 0; j < n; ++j)
3747			isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]);
3748	for (i = 0; i < bmap->n_div; ++i)
3749		for (j = 0; j < n; ++j)
3750			isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]);
3751	bmap = isl_basic_map_gauss(bmap, NULL);
3752	return isl_basic_map_finalize(bmap);
3753}
3754
3755__isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset)
3756{
3757	return isl_basic_map_neg(bset);
3758}
3759
3760/* Given a map A -> f(A), construct A -> -f(A).
3761 */
3762struct isl_map *isl_map_neg(struct isl_map *map)
3763{
3764	int i;
3765
3766	map = isl_map_cow(map);
3767	if (!map)
3768		return NULL;
3769
3770	for (i = 0; i < map->n; ++i) {
3771		map->p[i] = isl_basic_map_neg(map->p[i]);
3772		if (!map->p[i])
3773			goto error;
3774	}
3775
3776	return map;
3777error:
3778	isl_map_free(map);
3779	return NULL;
3780}
3781
3782__isl_give isl_set *isl_set_neg(__isl_take isl_set *set)
3783{
3784	return (isl_set *)isl_map_neg((isl_map *)set);
3785}
3786
3787/* Given a basic map A -> f(A) and an integer d, construct a basic map
3788 * A -> floor(f(A)/d).
3789 */
3790struct isl_basic_map *isl_basic_map_floordiv(struct isl_basic_map *bmap,
3791		isl_int d)
3792{
3793	unsigned n_in, n_out, nparam, total, pos;
3794	struct isl_basic_map *result = NULL;
3795	struct isl_dim_map *dim_map;
3796	int i;
3797
3798	if (!bmap)
3799		return NULL;
3800
3801	nparam = isl_basic_map_n_param(bmap);
3802	n_in = isl_basic_map_n_in(bmap);
3803	n_out = isl_basic_map_n_out(bmap);
3804
3805	total = nparam + n_in + n_out + bmap->n_div + n_out;
3806	dim_map = isl_dim_map_alloc(bmap->ctx, total);
3807	isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0);
3808	isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam);
3809	isl_dim_map_div(dim_map, bmap, pos += n_in + n_out);
3810	isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div);
3811
3812	result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
3813			bmap->n_div + n_out,
3814			bmap->n_eq, bmap->n_ineq + 2 * n_out);
3815	result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map);
3816	result = add_divs(result, n_out);
3817	for (i = 0; i < n_out; ++i) {
3818		int j;
3819		j = isl_basic_map_alloc_inequality(result);
3820		if (j < 0)
3821			goto error;
3822		isl_seq_clr(result->ineq[j], 1+total);
3823		isl_int_neg(result->ineq[j][1+nparam+n_in+i], d);
3824		isl_int_set_si(result->ineq[j][1+pos+i], 1);
3825		j = isl_basic_map_alloc_inequality(result);
3826		if (j < 0)
3827			goto error;
3828		isl_seq_clr(result->ineq[j], 1+total);
3829		isl_int_set(result->ineq[j][1+nparam+n_in+i], d);
3830		isl_int_set_si(result->ineq[j][1+pos+i], -1);
3831		isl_int_sub_ui(result->ineq[j][0], d, 1);
3832	}
3833
3834	result = isl_basic_map_simplify(result);
3835	return isl_basic_map_finalize(result);
3836error:
3837	isl_basic_map_free(result);
3838	return NULL;
3839}
3840
3841/* Given a map A -> f(A) and an integer d, construct a map
3842 * A -> floor(f(A)/d).
3843 */
3844struct isl_map *isl_map_floordiv(struct isl_map *map, isl_int d)
3845{
3846	int i;
3847
3848	map = isl_map_cow(map);
3849	if (!map)
3850		return NULL;
3851
3852	ISL_F_CLR(map, ISL_MAP_DISJOINT);
3853	ISL_F_CLR(map, ISL_MAP_NORMALIZED);
3854	for (i = 0; i < map->n; ++i) {
3855		map->p[i] = isl_basic_map_floordiv(map->p[i], d);
3856		if (!map->p[i])
3857			goto error;
3858	}
3859
3860	return map;
3861error:
3862	isl_map_free(map);
3863	return NULL;
3864}
3865
3866/* Given a map A -> f(A) and an integer d, construct a map
3867 * A -> floor(f(A)/d).
3868 */
3869__isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,
3870	__isl_take isl_val *d)
3871{
3872	if (!map || !d)
3873		goto error;
3874	if (!isl_val_is_int(d))
3875		isl_die(isl_val_get_ctx(d), isl_error_invalid,
3876			"expecting integer denominator", goto error);
3877	map = isl_map_floordiv(map, d->n);
3878	isl_val_free(d);
3879	return map;
3880error:
3881	isl_map_free(map);
3882	isl_val_free(d);
3883	return NULL;
3884}
3885
3886static struct isl_basic_map *var_equal(struct isl_basic_map *bmap, unsigned pos)
3887{
3888	int i;
3889	unsigned nparam;
3890	unsigned n_in;
3891
3892	i = isl_basic_map_alloc_equality(bmap);
3893	if (i < 0)
3894		goto error;
3895	nparam = isl_basic_map_n_param(bmap);
3896	n_in = isl_basic_map_n_in(bmap);
3897	isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
3898	isl_int_set_si(bmap->eq[i][1+nparam+pos], -1);
3899	isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1);
3900	return isl_basic_map_finalize(bmap);
3901error:
3902	isl_basic_map_free(bmap);
3903	return NULL;
3904}
3905
3906/* Add a constraints to "bmap" expressing i_pos < o_pos
3907 */
3908static struct isl_basic_map *var_less(struct isl_basic_map *bmap, unsigned pos)
3909{
3910	int i;
3911	unsigned nparam;
3912	unsigned n_in;
3913
3914	i = isl_basic_map_alloc_inequality(bmap);
3915	if (i < 0)
3916		goto error;
3917	nparam = isl_basic_map_n_param(bmap);
3918	n_in = isl_basic_map_n_in(bmap);
3919	isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
3920	isl_int_set_si(bmap->ineq[i][0], -1);
3921	isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
3922	isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
3923	return isl_basic_map_finalize(bmap);
3924error:
3925	isl_basic_map_free(bmap);
3926	return NULL;
3927}
3928
3929/* Add a constraint to "bmap" expressing i_pos <= o_pos
3930 */
3931static __isl_give isl_basic_map *var_less_or_equal(
3932	__isl_take isl_basic_map *bmap, unsigned pos)
3933{
3934	int i;
3935	unsigned nparam;
3936	unsigned n_in;
3937
3938	i = isl_basic_map_alloc_inequality(bmap);
3939	if (i < 0)
3940		goto error;
3941	nparam = isl_basic_map_n_param(bmap);
3942	n_in = isl_basic_map_n_in(bmap);
3943	isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
3944	isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
3945	isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
3946	return isl_basic_map_finalize(bmap);
3947error:
3948	isl_basic_map_free(bmap);
3949	return NULL;
3950}
3951
3952/* Add a constraints to "bmap" expressing i_pos > o_pos
3953 */
3954static struct isl_basic_map *var_more(struct isl_basic_map *bmap, unsigned pos)
3955{
3956	int i;
3957	unsigned nparam;
3958	unsigned n_in;
3959
3960	i = isl_basic_map_alloc_inequality(bmap);
3961	if (i < 0)
3962		goto error;
3963	nparam = isl_basic_map_n_param(bmap);
3964	n_in = isl_basic_map_n_in(bmap);
3965	isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
3966	isl_int_set_si(bmap->ineq[i][0], -1);
3967	isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
3968	isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
3969	return isl_basic_map_finalize(bmap);
3970error:
3971	isl_basic_map_free(bmap);
3972	return NULL;
3973}
3974
3975/* Add a constraint to "bmap" expressing i_pos >= o_pos
3976 */
3977static __isl_give isl_basic_map *var_more_or_equal(
3978	__isl_take isl_basic_map *bmap, unsigned pos)
3979{
3980	int i;
3981	unsigned nparam;
3982	unsigned n_in;
3983
3984	i = isl_basic_map_alloc_inequality(bmap);
3985	if (i < 0)
3986		goto error;
3987	nparam = isl_basic_map_n_param(bmap);
3988	n_in = isl_basic_map_n_in(bmap);
3989	isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
3990	isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
3991	isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
3992	return isl_basic_map_finalize(bmap);
3993error:
3994	isl_basic_map_free(bmap);
3995	return NULL;
3996}
3997
3998__isl_give isl_basic_map *isl_basic_map_equal(
3999	__isl_take isl_space *dim, unsigned n_equal)
4000{
4001	int i;
4002	struct isl_basic_map *bmap;
4003	bmap = isl_basic_map_alloc_space(dim, 0, n_equal, 0);
4004	if (!bmap)
4005		return NULL;
4006	for (i = 0; i < n_equal && bmap; ++i)
4007		bmap = var_equal(bmap, i);
4008	return isl_basic_map_finalize(bmap);
4009}
4010
4011/* Return a relation on of dimension "dim" expressing i_[0..pos] << o_[0..pos]
4012 */
4013__isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *dim,
4014	unsigned pos)
4015{
4016	int i;
4017	struct isl_basic_map *bmap;
4018	bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4019	if (!bmap)
4020		return NULL;
4021	for (i = 0; i < pos && bmap; ++i)
4022		bmap = var_equal(bmap, i);
4023	if (bmap)
4024		bmap = var_less(bmap, pos);
4025	return isl_basic_map_finalize(bmap);
4026}
4027
4028/* Return a relation on of dimension "dim" expressing i_[0..pos] <<= o_[0..pos]
4029 */
4030__isl_give isl_basic_map *isl_basic_map_less_or_equal_at(
4031	__isl_take isl_space *dim, unsigned pos)
4032{
4033	int i;
4034	isl_basic_map *bmap;
4035
4036	bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4037	for (i = 0; i < pos; ++i)
4038		bmap = var_equal(bmap, i);
4039	bmap = var_less_or_equal(bmap, pos);
4040	return isl_basic_map_finalize(bmap);
4041}
4042
4043/* Return a relation on pairs of sets of dimension "dim" expressing i_pos > o_pos
4044 */
4045__isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *dim,
4046	unsigned pos)
4047{
4048	int i;
4049	struct isl_basic_map *bmap;
4050	bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4051	if (!bmap)
4052		return NULL;
4053	for (i = 0; i < pos && bmap; ++i)
4054		bmap = var_equal(bmap, i);
4055	if (bmap)
4056		bmap = var_more(bmap, pos);
4057	return isl_basic_map_finalize(bmap);
4058}
4059
4060/* Return a relation on of dimension "dim" expressing i_[0..pos] >>= o_[0..pos]
4061 */
4062__isl_give isl_basic_map *isl_basic_map_more_or_equal_at(
4063	__isl_take isl_space *dim, unsigned pos)
4064{
4065	int i;
4066	isl_basic_map *bmap;
4067
4068	bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4069	for (i = 0; i < pos; ++i)
4070		bmap = var_equal(bmap, i);
4071	bmap = var_more_or_equal(bmap, pos);
4072	return isl_basic_map_finalize(bmap);
4073}
4074
4075static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *dims,
4076	unsigned n, int equal)
4077{
4078	struct isl_map *map;
4079	int i;
4080
4081	if (n == 0 && equal)
4082		return isl_map_universe(dims);
4083
4084	map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT);
4085
4086	for (i = 0; i + 1 < n; ++i)
4087		map = isl_map_add_basic_map(map,
4088				  isl_basic_map_less_at(isl_space_copy(dims), i));
4089	if (n > 0) {
4090		if (equal)
4091			map = isl_map_add_basic_map(map,
4092			      isl_basic_map_less_or_equal_at(dims, n - 1));
4093		else
4094			map = isl_map_add_basic_map(map,
4095			      isl_basic_map_less_at(dims, n - 1));
4096	} else
4097		isl_space_free(dims);
4098
4099	return map;
4100}
4101
4102static __isl_give isl_map *map_lex_lte(__isl_take isl_space *dims, int equal)
4103{
4104	if (!dims)
4105		return NULL;
4106	return map_lex_lte_first(dims, dims->n_out, equal);
4107}
4108
4109__isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *dim, unsigned n)
4110{
4111	return map_lex_lte_first(dim, n, 0);
4112}
4113
4114__isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *dim, unsigned n)
4115{
4116	return map_lex_lte_first(dim, n, 1);
4117}
4118
4119__isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_dim)
4120{
4121	return map_lex_lte(isl_space_map_from_set(set_dim), 0);
4122}
4123
4124__isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_dim)
4125{
4126	return map_lex_lte(isl_space_map_from_set(set_dim), 1);
4127}
4128
4129static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *dims,
4130	unsigned n, int equal)
4131{
4132	struct isl_map *map;
4133	int i;
4134
4135	if (n == 0 && equal)
4136		return isl_map_universe(dims);
4137
4138	map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT);
4139
4140	for (i = 0; i + 1 < n; ++i)
4141		map = isl_map_add_basic_map(map,
4142				  isl_basic_map_more_at(isl_space_copy(dims), i));
4143	if (n > 0) {
4144		if (equal)
4145			map = isl_map_add_basic_map(map,
4146			      isl_basic_map_more_or_equal_at(dims, n - 1));
4147		else
4148			map = isl_map_add_basic_map(map,
4149			      isl_basic_map_more_at(dims, n - 1));
4150	} else
4151		isl_space_free(dims);
4152
4153	return map;
4154}
4155
4156static __isl_give isl_map *map_lex_gte(__isl_take isl_space *dims, int equal)
4157{
4158	if (!dims)
4159		return NULL;
4160	return map_lex_gte_first(dims, dims->n_out, equal);
4161}
4162
4163__isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *dim, unsigned n)
4164{
4165	return map_lex_gte_first(dim, n, 0);
4166}
4167
4168__isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *dim, unsigned n)
4169{
4170	return map_lex_gte_first(dim, n, 1);
4171}
4172
4173__isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_dim)
4174{
4175	return map_lex_gte(isl_space_map_from_set(set_dim), 0);
4176}
4177
4178__isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_dim)
4179{
4180	return map_lex_gte(isl_space_map_from_set(set_dim), 1);
4181}
4182
4183__isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,
4184	__isl_take isl_set *set2)
4185{
4186	isl_map *map;
4187	map = isl_map_lex_le(isl_set_get_space(set1));
4188	map = isl_map_intersect_domain(map, set1);
4189	map = isl_map_intersect_range(map, set2);
4190	return map;
4191}
4192
4193__isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,
4194	__isl_take isl_set *set2)
4195{
4196	isl_map *map;
4197	map = isl_map_lex_lt(isl_set_get_space(set1));
4198	map = isl_map_intersect_domain(map, set1);
4199	map = isl_map_intersect_range(map, set2);
4200	return map;
4201}
4202
4203__isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,
4204	__isl_take isl_set *set2)
4205{
4206	isl_map *map;
4207	map = isl_map_lex_ge(isl_set_get_space(set1));
4208	map = isl_map_intersect_domain(map, set1);
4209	map = isl_map_intersect_range(map, set2);
4210	return map;
4211}
4212
4213__isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,
4214	__isl_take isl_set *set2)
4215{
4216	isl_map *map;
4217	map = isl_map_lex_gt(isl_set_get_space(set1));
4218	map = isl_map_intersect_domain(map, set1);
4219	map = isl_map_intersect_range(map, set2);
4220	return map;
4221}
4222
4223__isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
4224	__isl_take isl_map *map2)
4225{
4226	isl_map *map;
4227	map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1)));
4228	map = isl_map_apply_domain(map, isl_map_reverse(map1));
4229	map = isl_map_apply_range(map, isl_map_reverse(map2));
4230	return map;
4231}
4232
4233__isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,
4234	__isl_take isl_map *map2)
4235{
4236	isl_map *map;
4237	map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1)));
4238	map = isl_map_apply_domain(map, isl_map_reverse(map1));
4239	map = isl_map_apply_range(map, isl_map_reverse(map2));
4240	return map;
4241}
4242
4243__isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,
4244	__isl_take isl_map *map2)
4245{
4246	isl_map *map;
4247	map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1)));
4248	map = isl_map_apply_domain(map, isl_map_reverse(map1));
4249	map = isl_map_apply_range(map, isl_map_reverse(map2));
4250	return map;
4251}
4252
4253__isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
4254	__isl_take isl_map *map2)
4255{
4256	isl_map *map;
4257	map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1)));
4258	map = isl_map_apply_domain(map, isl_map_reverse(map1));
4259	map = isl_map_apply_range(map, isl_map_reverse(map2));
4260	return map;
4261}
4262
4263__isl_give isl_basic_map *isl_basic_map_from_basic_set(
4264	__isl_take isl_basic_set *bset, __isl_take isl_space *dim)
4265{
4266	struct isl_basic_map *bmap;
4267
4268	bset = isl_basic_set_cow(bset);
4269	if (!bset || !dim)
4270		goto error;
4271
4272	isl_assert(bset->ctx, isl_space_compatible(bset->dim, dim), goto error);
4273	isl_space_free(bset->dim);
4274	bmap = (struct isl_basic_map *) bset;
4275	bmap->dim = dim;
4276	return isl_basic_map_finalize(bmap);
4277error:
4278	isl_basic_set_free(bset);
4279	isl_space_free(dim);
4280	return NULL;
4281}
4282
4283struct isl_basic_set *isl_basic_set_from_basic_map(struct isl_basic_map *bmap)
4284{
4285	if (!bmap)
4286		goto error;
4287	if (bmap->dim->n_in == 0)
4288		return (struct isl_basic_set *)bmap;
4289	bmap = isl_basic_map_cow(bmap);
4290	if (!bmap)
4291		goto error;
4292	bmap->dim = isl_space_as_set_space(bmap->dim);
4293	if (!bmap->dim)
4294		goto error;
4295	bmap = isl_basic_map_finalize(bmap);
4296	return (struct isl_basic_set *)bmap;
4297error:
4298	isl_basic_map_free(bmap);
4299	return NULL;
4300}
4301
4302/* For a div d = floor(f/m), add the constraint
4303 *
4304 *		f - m d >= 0
4305 */
4306static int add_upper_div_constraint(__isl_keep isl_basic_map *bmap,
4307	unsigned pos, isl_int *div)
4308{
4309	int i;
4310	unsigned total = isl_basic_map_total_dim(bmap);
4311
4312	i = isl_basic_map_alloc_inequality(bmap);
4313	if (i < 0)
4314		return -1;
4315	isl_seq_cpy(bmap->ineq[i], div + 1, 1 + total);
4316	isl_int_neg(bmap->ineq[i][1 + pos], div[0]);
4317
4318	return 0;
4319}
4320
4321/* For a div d = floor(f/m), add the constraint
4322 *
4323 *		-(f-(n-1)) + m d >= 0
4324 */
4325static int add_lower_div_constraint(__isl_keep isl_basic_map *bmap,
4326	unsigned pos, isl_int *div)
4327{
4328	int i;
4329	unsigned total = isl_basic_map_total_dim(bmap);
4330
4331	i = isl_basic_map_alloc_inequality(bmap);
4332	if (i < 0)
4333		return -1;
4334	isl_seq_neg(bmap->ineq[i], div + 1, 1 + total);
4335	isl_int_set(bmap->ineq[i][1 + pos], div[0]);
4336	isl_int_add(bmap->ineq[i][0], bmap->ineq[i][0], bmap->ineq[i][1 + pos]);
4337	isl_int_sub_ui(bmap->ineq[i][0], bmap->ineq[i][0], 1);
4338
4339	return 0;
4340}
4341
4342/* For a div d = floor(f/m), add the constraints
4343 *
4344 *		f - m d >= 0
4345 *		-(f-(n-1)) + m d >= 0
4346 *
4347 * Note that the second constraint is the negation of
4348 *
4349 *		f - m d >= n
4350 */
4351int isl_basic_map_add_div_constraints_var(__isl_keep isl_basic_map *bmap,
4352	unsigned pos, isl_int *div)
4353{
4354	if (add_upper_div_constraint(bmap, pos, div) < 0)
4355		return -1;
4356	if (add_lower_div_constraint(bmap, pos, div) < 0)
4357		return -1;
4358	return 0;
4359}
4360
4361int isl_basic_set_add_div_constraints_var(__isl_keep isl_basic_set *bset,
4362	unsigned pos, isl_int *div)
4363{
4364	return isl_basic_map_add_div_constraints_var((isl_basic_map *)bset,
4365							pos, div);
4366}
4367
4368int isl_basic_map_add_div_constraints(struct isl_basic_map *bmap, unsigned div)
4369{
4370	unsigned total = isl_basic_map_total_dim(bmap);
4371	unsigned div_pos = total - bmap->n_div + div;
4372
4373	return isl_basic_map_add_div_constraints_var(bmap, div_pos,
4374							bmap->div[div]);
4375}
4376
4377/* Add the div constraint of sign "sign" for div "div" of "bmap".
4378 *
4379 * In particular, if this div is of the form d = floor(f/m),
4380 * then add the constraint
4381 *
4382 *		f - m d >= 0
4383 *
4384 * if sign < 0 or the constraint
4385 *
4386 *		-(f-(n-1)) + m d >= 0
4387 *
4388 * if sign > 0.
4389 */
4390int isl_basic_map_add_div_constraint(__isl_keep isl_basic_map *bmap,
4391	unsigned div, int sign)
4392{
4393	unsigned total;
4394	unsigned div_pos;
4395
4396	if (!bmap)
4397		return -1;
4398
4399	total = isl_basic_map_total_dim(bmap);
4400	div_pos = total - bmap->n_div + div;
4401
4402	if (sign < 0)
4403		return add_upper_div_constraint(bmap, div_pos, bmap->div[div]);
4404	else
4405		return add_lower_div_constraint(bmap, div_pos, bmap->div[div]);
4406}
4407
4408int isl_basic_set_add_div_constraints(struct isl_basic_set *bset, unsigned div)
4409{
4410	return isl_basic_map_add_div_constraints(bset, div);
4411}
4412
4413struct isl_basic_set *isl_basic_map_underlying_set(
4414		struct isl_basic_map *bmap)
4415{
4416	if (!bmap)
4417		goto error;
4418	if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 &&
4419	    bmap->n_div == 0 &&
4420	    !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) &&
4421	    !isl_space_is_named_or_nested(bmap->dim, isl_dim_out))
4422		return (struct isl_basic_set *)bmap;
4423	bmap = isl_basic_map_cow(bmap);
4424	if (!bmap)
4425		goto error;
4426	bmap->dim = isl_space_underlying(bmap->dim, bmap->n_div);
4427	if (!bmap->dim)
4428		goto error;
4429	bmap->extra -= bmap->n_div;
4430	bmap->n_div = 0;
4431	bmap = isl_basic_map_finalize(bmap);
4432	return (struct isl_basic_set *)bmap;
4433error:
4434	isl_basic_map_free(bmap);
4435	return NULL;
4436}
4437
4438__isl_give isl_basic_set *isl_basic_set_underlying_set(
4439		__isl_take isl_basic_set *bset)
4440{
4441	return isl_basic_map_underlying_set((isl_basic_map *)bset);
4442}
4443
4444struct isl_basic_map *isl_basic_map_overlying_set(
4445	struct isl_basic_set *bset, struct isl_basic_map *like)
4446{
4447	struct isl_basic_map *bmap;
4448	struct isl_ctx *ctx;
4449	unsigned total;
4450	int i;
4451
4452	if (!bset || !like)
4453		goto error;
4454	ctx = bset->ctx;
4455	isl_assert(ctx, bset->n_div == 0, goto error);
4456	isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error);
4457	isl_assert(ctx, bset->dim->n_out == isl_basic_map_total_dim(like),
4458			goto error);
4459	if (isl_space_is_equal(bset->dim, like->dim) && like->n_div == 0) {
4460		isl_basic_map_free(like);
4461		return (struct isl_basic_map *)bset;
4462	}
4463	bset = isl_basic_set_cow(bset);
4464	if (!bset)
4465		goto error;
4466	total = bset->dim->n_out + bset->extra;
4467	bmap = (struct isl_basic_map *)bset;
4468	isl_space_free(bmap->dim);
4469	bmap->dim = isl_space_copy(like->dim);
4470	if (!bmap->dim)
4471		goto error;
4472	bmap->n_div = like->n_div;
4473	bmap->extra += like->n_div;
4474	if (bmap->extra) {
4475		unsigned ltotal;
4476		isl_int **div;
4477		ltotal = total - bmap->extra + like->extra;
4478		if (ltotal > total)
4479			ltotal = total;
4480		bmap->block2 = isl_blk_extend(ctx, bmap->block2,
4481					bmap->extra * (1 + 1 + total));
4482		if (isl_blk_is_error(bmap->block2))
4483			goto error;
4484		div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra);
4485		if (!div)
4486			goto error;
4487		bmap->div = div;
4488		for (i = 0; i < bmap->extra; ++i)
4489			bmap->div[i] = bmap->block2.data + i * (1 + 1 + total);
4490		for (i = 0; i < like->n_div; ++i) {
4491			isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal);
4492			isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal);
4493		}
4494		bmap = isl_basic_map_extend_constraints(bmap,
4495							0, 2 * like->n_div);
4496		for (i = 0; i < like->n_div; ++i) {
4497			if (!bmap)
4498				break;
4499			if (isl_int_is_zero(bmap->div[i][0]))
4500				continue;
4501			if (isl_basic_map_add_div_constraints(bmap, i) < 0)
4502				bmap = isl_basic_map_free(bmap);
4503		}
4504	}
4505	isl_basic_map_free(like);
4506	bmap = isl_basic_map_simplify(bmap);
4507	bmap = isl_basic_map_finalize(bmap);
4508	return bmap;
4509error:
4510	isl_basic_map_free(like);
4511	isl_basic_set_free(bset);
4512	return NULL;
4513}
4514
4515struct isl_basic_set *isl_basic_set_from_underlying_set(
4516	struct isl_basic_set *bset, struct isl_basic_set *like)
4517{
4518	return (struct isl_basic_set *)
4519		isl_basic_map_overlying_set(bset, (struct isl_basic_map *)like);
4520}
4521
4522struct isl_set *isl_set_from_underlying_set(
4523	struct isl_set *set, struct isl_basic_set *like)
4524{
4525	int i;
4526
4527	if (!set || !like)
4528		goto error;
4529	isl_assert(set->ctx, set->dim->n_out == isl_basic_set_total_dim(like),
4530		    goto error);
4531	if (isl_space_is_equal(set->dim, like->dim) && like->n_div == 0) {
4532		isl_basic_set_free(like);
4533		return set;
4534	}
4535	set = isl_set_cow(set);
4536	if (!set)
4537		goto error;
4538	for (i = 0; i < set->n; ++i) {
4539		set->p[i] = isl_basic_set_from_underlying_set(set->p[i],
4540						      isl_basic_set_copy(like));
4541		if (!set->p[i])
4542			goto error;
4543	}
4544	isl_space_free(set->dim);
4545	set->dim = isl_space_copy(like->dim);
4546	if (!set->dim)
4547		goto error;
4548	isl_basic_set_free(like);
4549	return set;
4550error:
4551	isl_basic_set_free(like);
4552	isl_set_free(set);
4553	return NULL;
4554}
4555
4556struct isl_set *isl_map_underlying_set(struct isl_map *map)
4557{
4558	int i;
4559
4560	map = isl_map_cow(map);
4561	if (!map)
4562		return NULL;
4563	map->dim = isl_space_cow(map->dim);
4564	if (!map->dim)
4565		goto error;
4566
4567	for (i = 1; i < map->n; ++i)
4568		isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div,
4569				goto error);
4570	for (i = 0; i < map->n; ++i) {
4571		map->p[i] = (struct isl_basic_map *)
4572				isl_basic_map_underlying_set(map->p[i]);
4573		if (!map->p[i])
4574			goto error;
4575	}
4576	if (map->n == 0)
4577		map->dim = isl_space_underlying(map->dim, 0);
4578	else {
4579		isl_space_free(map->dim);
4580		map->dim = isl_space_copy(map->p[0]->dim);
4581	}
4582	if (!map->dim)
4583		goto error;
4584	return (struct isl_set *)map;
4585error:
4586	isl_map_free(map);
4587	return NULL;
4588}
4589
4590struct isl_set *isl_set_to_underlying_set(struct isl_set *set)
4591{
4592	return (struct isl_set *)isl_map_underlying_set((struct isl_map *)set);
4593}
4594
4595__isl_give isl_basic_map *isl_basic_map_reset_space(
4596	__isl_take isl_basic_map *bmap, __isl_take isl_space *dim)
4597{
4598	bmap = isl_basic_map_cow(bmap);
4599	if (!bmap || !dim)
4600		goto error;
4601
4602	isl_space_free(bmap->dim);
4603	bmap->dim = dim;
4604
4605	bmap = isl_basic_map_finalize(bmap);
4606
4607	return bmap;
4608error:
4609	isl_basic_map_free(bmap);
4610	isl_space_free(dim);
4611	return NULL;
4612}
4613
4614__isl_give isl_basic_set *isl_basic_set_reset_space(
4615	__isl_take isl_basic_set *bset, __isl_take isl_space *dim)
4616{
4617	return (isl_basic_set *)isl_basic_map_reset_space((isl_basic_map *)bset,
4618							dim);
4619}
4620
4621__isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
4622	__isl_take isl_space *dim)
4623{
4624	int i;
4625
4626	map = isl_map_cow(map);
4627	if (!map || !dim)
4628		goto error;
4629
4630	for (i = 0; i < map->n; ++i) {
4631		map->p[i] = isl_basic_map_reset_space(map->p[i],
4632						    isl_space_copy(dim));
4633		if (!map->p[i])
4634			goto error;
4635	}
4636	isl_space_free(map->dim);
4637	map->dim = dim;
4638
4639	return map;
4640error:
4641	isl_map_free(map);
4642	isl_space_free(dim);
4643	return NULL;
4644}
4645
4646__isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,
4647	__isl_take isl_space *dim)
4648{
4649	return (struct isl_set *) isl_map_reset_space((struct isl_map *)set, dim);
4650}
4651
4652/* Compute the parameter domain of the given basic set.
4653 */
4654__isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)
4655{
4656	isl_space *space;
4657	unsigned n;
4658
4659	if (isl_basic_set_is_params(bset))
4660		return bset;
4661
4662	n = isl_basic_set_dim(bset, isl_dim_set);
4663	bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
4664	space = isl_basic_set_get_space(bset);
4665	space = isl_space_params(space);
4666	bset = isl_basic_set_reset_space(bset, space);
4667	return bset;
4668}
4669
4670/* Construct a zero-dimensional basic set with the given parameter domain.
4671 */
4672__isl_give isl_basic_set *isl_basic_set_from_params(
4673	__isl_take isl_basic_set *bset)
4674{
4675	isl_space *space;
4676	space = isl_basic_set_get_space(bset);
4677	space = isl_space_set_from_params(space);
4678	bset = isl_basic_set_reset_space(bset, space);
4679	return bset;
4680}
4681
4682/* Compute the parameter domain of the given set.
4683 */
4684__isl_give isl_set *isl_set_params(__isl_take isl_set *set)
4685{
4686	isl_space *space;
4687	unsigned n;
4688
4689	if (isl_set_is_params(set))
4690		return set;
4691
4692	n = isl_set_dim(set, isl_dim_set);
4693	set = isl_set_project_out(set, isl_dim_set, 0, n);
4694	space = isl_set_get_space(set);
4695	space = isl_space_params(space);
4696	set = isl_set_reset_space(set, space);
4697	return set;
4698}
4699
4700/* Construct a zero-dimensional set with the given parameter domain.
4701 */
4702__isl_give isl_set *isl_set_from_params(__isl_take isl_set *set)
4703{
4704	isl_space *space;
4705	space = isl_set_get_space(set);
4706	space = isl_space_set_from_params(space);
4707	set = isl_set_reset_space(set, space);
4708	return set;
4709}
4710
4711/* Compute the parameter domain of the given map.
4712 */
4713__isl_give isl_set *isl_map_params(__isl_take isl_map *map)
4714{
4715	isl_space *space;
4716	unsigned n;
4717
4718	n = isl_map_dim(map, isl_dim_in);
4719	map = isl_map_project_out(map, isl_dim_in, 0, n);
4720	n = isl_map_dim(map, isl_dim_out);
4721	map = isl_map_project_out(map, isl_dim_out, 0, n);
4722	space = isl_map_get_space(map);
4723	space = isl_space_params(space);
4724	map = isl_map_reset_space(map, space);
4725	return map;
4726}
4727
4728struct isl_basic_set *isl_basic_map_domain(struct isl_basic_map *bmap)
4729{
4730	isl_space *dim;
4731	struct isl_basic_set *domain;
4732	unsigned n_in;
4733	unsigned n_out;
4734
4735	if (!bmap)
4736		return NULL;
4737	dim = isl_space_domain(isl_basic_map_get_space(bmap));
4738
4739	n_in = isl_basic_map_n_in(bmap);
4740	n_out = isl_basic_map_n_out(bmap);
4741	domain = isl_basic_set_from_basic_map(bmap);
4742	domain = isl_basic_set_project_out(domain, isl_dim_set, n_in, n_out);
4743
4744	domain = isl_basic_set_reset_space(domain, dim);
4745
4746	return domain;
4747}
4748
4749int isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap)
4750{
4751	if (!bmap)
4752		return -1;
4753	return isl_space_may_be_set(bmap->dim);
4754}
4755
4756/* Is this basic map actually a set?
4757 * Users should never call this function.  Outside of isl,
4758 * the type should indicate whether something is a set or a map.
4759 */
4760int isl_basic_map_is_set(__isl_keep isl_basic_map *bmap)
4761{
4762	if (!bmap)
4763		return -1;
4764	return isl_space_is_set(bmap->dim);
4765}
4766
4767struct isl_basic_set *isl_basic_map_range(struct isl_basic_map *bmap)
4768{
4769	if (!bmap)
4770		return NULL;
4771	if (isl_basic_map_is_set(bmap))
4772		return bmap;
4773	return isl_basic_map_domain(isl_basic_map_reverse(bmap));
4774}
4775
4776__isl_give isl_basic_map *isl_basic_map_domain_map(
4777	__isl_take isl_basic_map *bmap)
4778{
4779	int i, k;
4780	isl_space *dim;
4781	isl_basic_map *domain;
4782	int nparam, n_in, n_out;
4783	unsigned total;
4784
4785	nparam = isl_basic_map_dim(bmap, isl_dim_param);
4786	n_in = isl_basic_map_dim(bmap, isl_dim_in);
4787	n_out = isl_basic_map_dim(bmap, isl_dim_out);
4788
4789	dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap)));
4790	domain = isl_basic_map_universe(dim);
4791
4792	bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
4793	bmap = isl_basic_map_apply_range(bmap, domain);
4794	bmap = isl_basic_map_extend_constraints(bmap, n_in, 0);
4795
4796	total = isl_basic_map_total_dim(bmap);
4797
4798	for (i = 0; i < n_in; ++i) {
4799		k = isl_basic_map_alloc_equality(bmap);
4800		if (k < 0)
4801			goto error;
4802		isl_seq_clr(bmap->eq[k], 1 + total);
4803		isl_int_set_si(bmap->eq[k][1 + nparam + i], -1);
4804		isl_int_set_si(bmap->eq[k][1 + nparam + n_in + n_out + i], 1);
4805	}
4806
4807	bmap = isl_basic_map_gauss(bmap, NULL);
4808	return isl_basic_map_finalize(bmap);
4809error:
4810	isl_basic_map_free(bmap);
4811	return NULL;
4812}
4813
4814__isl_give isl_basic_map *isl_basic_map_range_map(
4815	__isl_take isl_basic_map *bmap)
4816{
4817	int i, k;
4818	isl_space *dim;
4819	isl_basic_map *range;
4820	int nparam, n_in, n_out;
4821	unsigned total;
4822
4823	nparam = isl_basic_map_dim(bmap, isl_dim_param);
4824	n_in = isl_basic_map_dim(bmap, isl_dim_in);
4825	n_out = isl_basic_map_dim(bmap, isl_dim_out);
4826
4827	dim = isl_space_from_range(isl_space_range(isl_basic_map_get_space(bmap)));
4828	range = isl_basic_map_universe(dim);
4829
4830	bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
4831	bmap = isl_basic_map_apply_range(bmap, range);
4832	bmap = isl_basic_map_extend_constraints(bmap, n_out, 0);
4833
4834	total = isl_basic_map_total_dim(bmap);
4835
4836	for (i = 0; i < n_out; ++i) {
4837		k = isl_basic_map_alloc_equality(bmap);
4838		if (k < 0)
4839			goto error;
4840		isl_seq_clr(bmap->eq[k], 1 + total);
4841		isl_int_set_si(bmap->eq[k][1 + nparam + n_in + i], -1);
4842		isl_int_set_si(bmap->eq[k][1 + nparam + n_in + n_out + i], 1);
4843	}
4844
4845	bmap = isl_basic_map_gauss(bmap, NULL);
4846	return isl_basic_map_finalize(bmap);
4847error:
4848	isl_basic_map_free(bmap);
4849	return NULL;
4850}
4851
4852int isl_map_may_be_set(__isl_keep isl_map *map)
4853{
4854	if (!map)
4855		return -1;
4856	return isl_space_may_be_set(map->dim);
4857}
4858
4859/* Is this map actually a set?
4860 * Users should never call this function.  Outside of isl,
4861 * the type should indicate whether something is a set or a map.
4862 */
4863int isl_map_is_set(__isl_keep isl_map *map)
4864{
4865	if (!map)
4866		return -1;
4867	return isl_space_is_set(map->dim);
4868}
4869
4870struct isl_set *isl_map_range(struct isl_map *map)
4871{
4872	int i;
4873	struct isl_set *set;
4874
4875	if (!map)
4876		goto error;
4877	if (isl_map_is_set(map))
4878		return (isl_set *)map;
4879
4880	map = isl_map_cow(map);
4881	if (!map)
4882		goto error;
4883
4884	set = (struct isl_set *) map;
4885	set->dim = isl_space_range(set->dim);
4886	if (!set->dim)
4887		goto error;
4888	for (i = 0; i < map->n; ++i) {
4889		set->p[i] = isl_basic_map_range(map->p[i]);
4890		if (!set->p[i])
4891			goto error;
4892	}
4893	ISL_F_CLR(set, ISL_MAP_DISJOINT);
4894	ISL_F_CLR(set, ISL_SET_NORMALIZED);
4895	return set;
4896error:
4897	isl_map_free(map);
4898	return NULL;
4899}
4900
4901__isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)
4902{
4903	int i;
4904	isl_space *domain_dim;
4905
4906	map = isl_map_cow(map);
4907	if (!map)
4908		return NULL;
4909
4910	domain_dim = isl_space_from_range(isl_space_domain(isl_map_get_space(map)));
4911	map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
4912	map->dim = isl_space_join(map->dim, domain_dim);
4913	if (!map->dim)
4914		goto error;
4915	for (i = 0; i < map->n; ++i) {
4916		map->p[i] = isl_basic_map_domain_map(map->p[i]);
4917		if (!map->p[i])
4918			goto error;
4919	}
4920	ISL_F_CLR(map, ISL_MAP_DISJOINT);
4921	ISL_F_CLR(map, ISL_MAP_NORMALIZED);
4922	return map;
4923error:
4924	isl_map_free(map);
4925	return NULL;
4926}
4927
4928__isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)
4929{
4930	int i;
4931	isl_space *range_dim;
4932
4933	map = isl_map_cow(map);
4934	if (!map)
4935		return NULL;
4936
4937	range_dim = isl_space_range(isl_map_get_space(map));
4938	range_dim = isl_space_from_range(range_dim);
4939	map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
4940	map->dim = isl_space_join(map->dim, range_dim);
4941	if (!map->dim)
4942		goto error;
4943	for (i = 0; i < map->n; ++i) {
4944		map->p[i] = isl_basic_map_range_map(map->p[i]);
4945		if (!map->p[i])
4946			goto error;
4947	}
4948	ISL_F_CLR(map, ISL_MAP_DISJOINT);
4949	ISL_F_CLR(map, ISL_MAP_NORMALIZED);
4950	return map;
4951error:
4952	isl_map_free(map);
4953	return NULL;
4954}
4955
4956__isl_give isl_map *isl_map_from_set(__isl_take isl_set *set,
4957	__isl_take isl_space *dim)
4958{
4959	int i;
4960	struct isl_map *map = NULL;
4961
4962	set = isl_set_cow(set);
4963	if (!set || !dim)
4964		goto error;
4965	isl_assert(set->ctx, isl_space_compatible(set->dim, dim), goto error);
4966	map = (struct isl_map *)set;
4967	for (i = 0; i < set->n; ++i) {
4968		map->p[i] = isl_basic_map_from_basic_set(
4969				set->p[i], isl_space_copy(dim));
4970		if (!map->p[i])
4971			goto error;
4972	}
4973	isl_space_free(map->dim);
4974	map->dim = dim;
4975	return map;
4976error:
4977	isl_space_free(dim);
4978	isl_set_free(set);
4979	return NULL;
4980}
4981
4982__isl_give isl_basic_map *isl_basic_map_from_domain(
4983	__isl_take isl_basic_set *bset)
4984{
4985	return isl_basic_map_reverse(isl_basic_map_from_range(bset));
4986}
4987
4988__isl_give isl_basic_map *isl_basic_map_from_range(
4989	__isl_take isl_basic_set *bset)
4990{
4991	isl_space *space;
4992	space = isl_basic_set_get_space(bset);
4993	space = isl_space_from_range(space);
4994	bset = isl_basic_set_reset_space(bset, space);
4995	return (isl_basic_map *)bset;
4996}
4997
4998struct isl_map *isl_map_from_range(struct isl_set *set)
4999{
5000	isl_space *space;
5001	space = isl_set_get_space(set);
5002	space = isl_space_from_range(space);
5003	set = isl_set_reset_space(set, space);
5004	return (struct isl_map *)set;
5005}
5006
5007__isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set)
5008{
5009	return isl_map_reverse(isl_map_from_range(set));
5010}
5011
5012__isl_give isl_basic_map *isl_basic_map_from_domain_and_range(
5013	__isl_take isl_basic_set *domain, __isl_take isl_basic_set *range)
5014{
5015	return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range);
5016}
5017
5018__isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
5019	__isl_take isl_set *range)
5020{
5021	return isl_map_apply_range(isl_map_reverse(domain), range);
5022}
5023
5024struct isl_set *isl_set_from_map(struct isl_map *map)
5025{
5026	int i;
5027	struct isl_set *set = NULL;
5028
5029	if (!map)
5030		return NULL;
5031	map = isl_map_cow(map);
5032	if (!map)
5033		return NULL;
5034	map->dim = isl_space_as_set_space(map->dim);
5035	if (!map->dim)
5036		goto error;
5037	set = (struct isl_set *)map;
5038	for (i = 0; i < map->n; ++i) {
5039		set->p[i] = isl_basic_set_from_basic_map(map->p[i]);
5040		if (!set->p[i])
5041			goto error;
5042	}
5043	return set;
5044error:
5045	isl_map_free(map);
5046	return NULL;
5047}
5048
5049__isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *dim, int n,
5050	unsigned flags)
5051{
5052	struct isl_map *map;
5053
5054	if (!dim)
5055		return NULL;
5056	if (n < 0)
5057		isl_die(dim->ctx, isl_error_internal,
5058			"negative number of basic maps", goto error);
5059	map = isl_alloc(dim->ctx, struct isl_map,
5060			sizeof(struct isl_map) +
5061			(n - 1) * sizeof(struct isl_basic_map *));
5062	if (!map)
5063		goto error;
5064
5065	map->ctx = dim->ctx;
5066	isl_ctx_ref(map->ctx);
5067	map->ref = 1;
5068	map->size = n;
5069	map->n = 0;
5070	map->dim = dim;
5071	map->flags = flags;
5072	return map;
5073error:
5074	isl_space_free(dim);
5075	return NULL;
5076}
5077
5078struct isl_map *isl_map_alloc(struct isl_ctx *ctx,
5079		unsigned nparam, unsigned in, unsigned out, int n,
5080		unsigned flags)
5081{
5082	struct isl_map *map;
5083	isl_space *dims;
5084
5085	dims = isl_space_alloc(ctx, nparam, in, out);
5086	if (!dims)
5087		return NULL;
5088
5089	map = isl_map_alloc_space(dims, n, flags);
5090	return map;
5091}
5092
5093__isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *dim)
5094{
5095	struct isl_basic_map *bmap;
5096	bmap = isl_basic_map_alloc_space(dim, 0, 1, 0);
5097	bmap = isl_basic_map_set_to_empty(bmap);
5098	return bmap;
5099}
5100
5101__isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *dim)
5102{
5103	struct isl_basic_set *bset;
5104	bset = isl_basic_set_alloc_space(dim, 0, 1, 0);
5105	bset = isl_basic_set_set_to_empty(bset);
5106	return bset;
5107}
5108
5109struct isl_basic_map *isl_basic_map_empty_like(struct isl_basic_map *model)
5110{
5111	struct isl_basic_map *bmap;
5112	if (!model)
5113		return NULL;
5114	bmap = isl_basic_map_alloc_space(isl_space_copy(model->dim), 0, 1, 0);
5115	bmap = isl_basic_map_set_to_empty(bmap);
5116	return bmap;
5117}
5118
5119struct isl_basic_map *isl_basic_map_empty_like_map(struct isl_map *model)
5120{
5121	struct isl_basic_map *bmap;
5122	if (!model)
5123		return NULL;
5124	bmap = isl_basic_map_alloc_space(isl_space_copy(model->dim), 0, 1, 0);
5125	bmap = isl_basic_map_set_to_empty(bmap);
5126	return bmap;
5127}
5128
5129struct isl_basic_set *isl_basic_set_empty_like(struct isl_basic_set *model)
5130{
5131	struct isl_basic_set *bset;
5132	if (!model)
5133		return NULL;
5134	bset = isl_basic_set_alloc_space(isl_space_copy(model->dim), 0, 1, 0);
5135	bset = isl_basic_set_set_to_empty(bset);
5136	return bset;
5137}
5138
5139__isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *dim)
5140{
5141	struct isl_basic_map *bmap;
5142	bmap = isl_basic_map_alloc_space(dim, 0, 0, 0);
5143	bmap = isl_basic_map_finalize(bmap);
5144	return bmap;
5145}
5146
5147__isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *dim)
5148{
5149	struct isl_basic_set *bset;
5150	bset = isl_basic_set_alloc_space(dim, 0, 0, 0);
5151	bset = isl_basic_set_finalize(bset);
5152	return bset;
5153}
5154
5155__isl_give isl_basic_map *isl_basic_map_nat_universe(__isl_take isl_space *dim)
5156{
5157	int i;
5158	unsigned total = isl_space_dim(dim, isl_dim_all);
5159	isl_basic_map *bmap;
5160
5161	bmap= isl_basic_map_alloc_space(dim, 0, 0, total);
5162	for (i = 0; i < total; ++i) {
5163		int k = isl_basic_map_alloc_inequality(bmap);
5164		if (k < 0)
5165			goto error;
5166		isl_seq_clr(bmap->ineq[k], 1 + total);
5167		isl_int_set_si(bmap->ineq[k][1 + i], 1);
5168	}
5169	return bmap;
5170error:
5171	isl_basic_map_free(bmap);
5172	return NULL;
5173}
5174
5175__isl_give isl_basic_set *isl_basic_set_nat_universe(__isl_take isl_space *dim)
5176{
5177	return isl_basic_map_nat_universe(dim);
5178}
5179
5180__isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *dim)
5181{
5182	return isl_map_from_basic_map(isl_basic_map_nat_universe(dim));
5183}
5184
5185__isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *dim)
5186{
5187	return isl_map_nat_universe(dim);
5188}
5189
5190__isl_give isl_basic_map *isl_basic_map_universe_like(
5191		__isl_keep isl_basic_map *model)
5192{
5193	if (!model)
5194		return NULL;
5195	return isl_basic_map_alloc_space(isl_space_copy(model->dim), 0, 0, 0);
5196}
5197
5198struct isl_basic_set *isl_basic_set_universe_like(struct isl_basic_set *model)
5199{
5200	if (!model)
5201		return NULL;
5202	return isl_basic_set_alloc_space(isl_space_copy(model->dim), 0, 0, 0);
5203}
5204
5205__isl_give isl_basic_set *isl_basic_set_universe_like_set(
5206	__isl_keep isl_set *model)
5207{
5208	if (!model)
5209		return NULL;
5210	return isl_basic_set_alloc_space(isl_space_copy(model->dim), 0, 0, 0);
5211}
5212
5213__isl_give isl_map *isl_map_empty(__isl_take isl_space *dim)
5214{
5215	return isl_map_alloc_space(dim, 0, ISL_MAP_DISJOINT);
5216}
5217
5218struct isl_map *isl_map_empty_like(struct isl_map *model)
5219{
5220	if (!model)
5221		return NULL;
5222	return isl_map_alloc_space(isl_space_copy(model->dim), 0, ISL_MAP_DISJOINT);
5223}
5224
5225struct isl_map *isl_map_empty_like_basic_map(struct isl_basic_map *model)
5226{
5227	if (!model)
5228		return NULL;
5229	return isl_map_alloc_space(isl_space_copy(model->dim), 0, ISL_MAP_DISJOINT);
5230}
5231
5232__isl_give isl_set *isl_set_empty(__isl_take isl_space *dim)
5233{
5234	return isl_set_alloc_space(dim, 0, ISL_MAP_DISJOINT);
5235}
5236
5237struct isl_set *isl_set_empty_like(struct isl_set *model)
5238{
5239	if (!model)
5240		return NULL;
5241	return isl_set_empty(isl_space_copy(model->dim));
5242}
5243
5244__isl_give isl_map *isl_map_universe(__isl_take isl_space *dim)
5245{
5246	struct isl_map *map;
5247	if (!dim)
5248		return NULL;
5249	map = isl_map_alloc_space(isl_space_copy(dim), 1, ISL_MAP_DISJOINT);
5250	map = isl_map_add_basic_map(map, isl_basic_map_universe(dim));
5251	return map;
5252}
5253
5254__isl_give isl_set *isl_set_universe(__isl_take isl_space *dim)
5255{
5256	struct isl_set *set;
5257	if (!dim)
5258		return NULL;
5259	set = isl_set_alloc_space(isl_space_copy(dim), 1, ISL_MAP_DISJOINT);
5260	set = isl_set_add_basic_set(set, isl_basic_set_universe(dim));
5261	return set;
5262}
5263
5264__isl_give isl_set *isl_set_universe_like(__isl_keep isl_set *model)
5265{
5266	if (!model)
5267		return NULL;
5268	return isl_set_universe(isl_space_copy(model->dim));
5269}
5270
5271struct isl_map *isl_map_dup(struct isl_map *map)
5272{
5273	int i;
5274	struct isl_map *dup;
5275
5276	if (!map)
5277		return NULL;
5278	dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags);
5279	for (i = 0; i < map->n; ++i)
5280		dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i]));
5281	return dup;
5282}
5283
5284__isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
5285						__isl_take isl_basic_map *bmap)
5286{
5287	if (!bmap || !map)
5288		goto error;
5289	if (isl_basic_map_plain_is_empty(bmap)) {
5290		isl_basic_map_free(bmap);
5291		return map;
5292	}
5293	isl_assert(map->ctx, isl_space_is_equal(map->dim, bmap->dim), goto error);
5294	isl_assert(map->ctx, map->n < map->size, goto error);
5295	map->p[map->n] = bmap;
5296	map->n++;
5297	ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5298	return map;
5299error:
5300	if (map)
5301		isl_map_free(map);
5302	if (bmap)
5303		isl_basic_map_free(bmap);
5304	return NULL;
5305}
5306
5307void *isl_map_free(struct isl_map *map)
5308{
5309	int i;
5310
5311	if (!map)
5312		return NULL;
5313
5314	if (--map->ref > 0)
5315		return NULL;
5316
5317	isl_ctx_deref(map->ctx);
5318	for (i = 0; i < map->n; ++i)
5319		isl_basic_map_free(map->p[i]);
5320	isl_space_free(map->dim);
5321	free(map);
5322
5323	return NULL;
5324}
5325
5326struct isl_map *isl_map_extend(struct isl_map *base,
5327		unsigned nparam, unsigned n_in, unsigned n_out)
5328{
5329	int i;
5330
5331	base = isl_map_cow(base);
5332	if (!base)
5333		return NULL;
5334
5335	base->dim = isl_space_extend(base->dim, nparam, n_in, n_out);
5336	if (!base->dim)
5337		goto error;
5338	for (i = 0; i < base->n; ++i) {
5339		base->p[i] = isl_basic_map_extend_space(base->p[i],
5340				isl_space_copy(base->dim), 0, 0, 0);
5341		if (!base->p[i])
5342			goto error;
5343	}
5344	return base;
5345error:
5346	isl_map_free(base);
5347	return NULL;
5348}
5349
5350struct isl_set *isl_set_extend(struct isl_set *base,
5351		unsigned nparam, unsigned dim)
5352{
5353	return (struct isl_set *)isl_map_extend((struct isl_map *)base,
5354							nparam, 0, dim);
5355}
5356
5357static struct isl_basic_map *isl_basic_map_fix_pos_si(
5358	struct isl_basic_map *bmap, unsigned pos, int value)
5359{
5360	int j;
5361
5362	bmap = isl_basic_map_cow(bmap);
5363	bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
5364	j = isl_basic_map_alloc_equality(bmap);
5365	if (j < 0)
5366		goto error;
5367	isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
5368	isl_int_set_si(bmap->eq[j][pos], -1);
5369	isl_int_set_si(bmap->eq[j][0], value);
5370	bmap = isl_basic_map_simplify(bmap);
5371	return isl_basic_map_finalize(bmap);
5372error:
5373	isl_basic_map_free(bmap);
5374	return NULL;
5375}
5376
5377static __isl_give isl_basic_map *isl_basic_map_fix_pos(
5378	__isl_take isl_basic_map *bmap, unsigned pos, isl_int value)
5379{
5380	int j;
5381
5382	bmap = isl_basic_map_cow(bmap);
5383	bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
5384	j = isl_basic_map_alloc_equality(bmap);
5385	if (j < 0)
5386		goto error;
5387	isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
5388	isl_int_set_si(bmap->eq[j][pos], -1);
5389	isl_int_set(bmap->eq[j][0], value);
5390	bmap = isl_basic_map_simplify(bmap);
5391	return isl_basic_map_finalize(bmap);
5392error:
5393	isl_basic_map_free(bmap);
5394	return NULL;
5395}
5396
5397struct isl_basic_map *isl_basic_map_fix_si(struct isl_basic_map *bmap,
5398		enum isl_dim_type type, unsigned pos, int value)
5399{
5400	if (!bmap)
5401		return NULL;
5402	isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), goto error);
5403	return isl_basic_map_fix_pos_si(bmap,
5404		isl_basic_map_offset(bmap, type) + pos, value);
5405error:
5406	isl_basic_map_free(bmap);
5407	return NULL;
5408}
5409
5410__isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap,
5411		enum isl_dim_type type, unsigned pos, isl_int value)
5412{
5413	if (!bmap)
5414		return NULL;
5415	isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), goto error);
5416	return isl_basic_map_fix_pos(bmap,
5417		isl_basic_map_offset(bmap, type) + pos, value);
5418error:
5419	isl_basic_map_free(bmap);
5420	return NULL;
5421}
5422
5423/* Fix the value of the variable at position "pos" of type "type" of "bmap"
5424 * to be equal to "v".
5425 */
5426__isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,
5427	enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
5428{
5429	if (!bmap || !v)
5430		goto error;
5431	if (!isl_val_is_int(v))
5432		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
5433			"expecting integer value", goto error);
5434	if (pos >= isl_basic_map_dim(bmap, type))
5435		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
5436			"index out of bounds", goto error);
5437	pos += isl_basic_map_offset(bmap, type);
5438	bmap = isl_basic_map_fix_pos(bmap, pos, v->n);
5439	isl_val_free(v);
5440	return bmap;
5441error:
5442	isl_basic_map_free(bmap);
5443	isl_val_free(v);
5444	return NULL;
5445}
5446
5447/* Fix the value of the variable at position "pos" of type "type" of "bset"
5448 * to be equal to "v".
5449 */
5450__isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,
5451	enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
5452{
5453	return isl_basic_map_fix_val(bset, type, pos, v);
5454}
5455
5456struct isl_basic_set *isl_basic_set_fix_si(struct isl_basic_set *bset,
5457		enum isl_dim_type type, unsigned pos, int value)
5458{
5459	return (struct isl_basic_set *)
5460		isl_basic_map_fix_si((struct isl_basic_map *)bset,
5461					type, pos, value);
5462}
5463
5464__isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
5465		enum isl_dim_type type, unsigned pos, isl_int value)
5466{
5467	return (struct isl_basic_set *)
5468		isl_basic_map_fix((struct isl_basic_map *)bset,
5469					type, pos, value);
5470}
5471
5472struct isl_basic_map *isl_basic_map_fix_input_si(struct isl_basic_map *bmap,
5473		unsigned input, int value)
5474{
5475	return isl_basic_map_fix_si(bmap, isl_dim_in, input, value);
5476}
5477
5478struct isl_basic_set *isl_basic_set_fix_dim_si(struct isl_basic_set *bset,
5479		unsigned dim, int value)
5480{
5481	return (struct isl_basic_set *)
5482		isl_basic_map_fix_si((struct isl_basic_map *)bset,
5483					isl_dim_set, dim, value);
5484}
5485
5486static int remove_if_empty(__isl_keep isl_map *map, int i)
5487{
5488	int empty = isl_basic_map_plain_is_empty(map->p[i]);
5489
5490	if (empty < 0)
5491		return -1;
5492	if (!empty)
5493		return 0;
5494
5495	isl_basic_map_free(map->p[i]);
5496	if (i != map->n - 1) {
5497		ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5498		map->p[i] = map->p[map->n - 1];
5499	}
5500	map->n--;
5501
5502	return 0;
5503}
5504
5505/* Perform "fn" on each basic map of "map", where we may not be holding
5506 * the only reference to "map".
5507 * In particular, "fn" should be a semantics preserving operation
5508 * that we want to apply to all copies of "map".  We therefore need
5509 * to be careful not to modify "map" in a way that breaks "map"
5510 * in case anything goes wrong.
5511 */
5512__isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
5513	__isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap))
5514{
5515	struct isl_basic_map *bmap;
5516	int i;
5517
5518	if (!map)
5519		return NULL;
5520
5521	for (i = map->n - 1; i >= 0; --i) {
5522		bmap = isl_basic_map_copy(map->p[i]);
5523		bmap = fn(bmap);
5524		if (!bmap)
5525			goto error;
5526		isl_basic_map_free(map->p[i]);
5527		map->p[i] = bmap;
5528		if (remove_if_empty(map, i) < 0)
5529			goto error;
5530	}
5531
5532	return map;
5533error:
5534	isl_map_free(map);
5535	return NULL;
5536}
5537
5538struct isl_map *isl_map_fix_si(struct isl_map *map,
5539		enum isl_dim_type type, unsigned pos, int value)
5540{
5541	int i;
5542
5543	map = isl_map_cow(map);
5544	if (!map)
5545		return NULL;
5546
5547	isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
5548	for (i = map->n - 1; i >= 0; --i) {
5549		map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value);
5550		if (remove_if_empty(map, i) < 0)
5551			goto error;
5552	}
5553	ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5554	return map;
5555error:
5556	isl_map_free(map);
5557	return NULL;
5558}
5559
5560__isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
5561		enum isl_dim_type type, unsigned pos, int value)
5562{
5563	return (struct isl_set *)
5564		isl_map_fix_si((struct isl_map *)set, type, pos, value);
5565}
5566
5567__isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
5568		enum isl_dim_type type, unsigned pos, isl_int value)
5569{
5570	int i;
5571
5572	map = isl_map_cow(map);
5573	if (!map)
5574		return NULL;
5575
5576	isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
5577	for (i = 0; i < map->n; ++i) {
5578		map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value);
5579		if (!map->p[i])
5580			goto error;
5581	}
5582	ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5583	return map;
5584error:
5585	isl_map_free(map);
5586	return NULL;
5587}
5588
5589__isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
5590		enum isl_dim_type type, unsigned pos, isl_int value)
5591{
5592	return (struct isl_set *)isl_map_fix((isl_map *)set, type, pos, value);
5593}
5594
5595/* Fix the value of the variable at position "pos" of type "type" of "map"
5596 * to be equal to "v".
5597 */
5598__isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
5599	enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
5600{
5601	int i;
5602
5603	map = isl_map_cow(map);
5604	if (!map || !v)
5605		goto error;
5606
5607	if (!isl_val_is_int(v))
5608		isl_die(isl_map_get_ctx(map), isl_error_invalid,
5609			"expecting integer value", goto error);
5610	if (pos >= isl_map_dim(map, type))
5611		isl_die(isl_map_get_ctx(map), isl_error_invalid,
5612			"index out of bounds", goto error);
5613	for (i = map->n - 1; i >= 0; --i) {
5614		map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos,
5615							isl_val_copy(v));
5616		if (remove_if_empty(map, i) < 0)
5617			goto error;
5618	}
5619	ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5620	isl_val_free(v);
5621	return map;
5622error:
5623	isl_map_free(map);
5624	isl_val_free(v);
5625	return NULL;
5626}
5627
5628/* Fix the value of the variable at position "pos" of type "type" of "set"
5629 * to be equal to "v".
5630 */
5631__isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,
5632	enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
5633{
5634	return isl_map_fix_val(set, type, pos, v);
5635}
5636
5637struct isl_map *isl_map_fix_input_si(struct isl_map *map,
5638		unsigned input, int value)
5639{
5640	return isl_map_fix_si(map, isl_dim_in, input, value);
5641}
5642
5643struct isl_set *isl_set_fix_dim_si(struct isl_set *set, unsigned dim, int value)
5644{
5645	return (struct isl_set *)
5646		isl_map_fix_si((struct isl_map *)set, isl_dim_set, dim, value);
5647}
5648
5649static __isl_give isl_basic_map *basic_map_bound_si(
5650	__isl_take isl_basic_map *bmap,
5651	enum isl_dim_type type, unsigned pos, int value, int upper)
5652{
5653	int j;
5654
5655	if (!bmap)
5656		return NULL;
5657	isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), goto error);
5658	pos += isl_basic_map_offset(bmap, type);
5659	bmap = isl_basic_map_cow(bmap);
5660	bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
5661	j = isl_basic_map_alloc_inequality(bmap);
5662	if (j < 0)
5663		goto error;
5664	isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
5665	if (upper) {
5666		isl_int_set_si(bmap->ineq[j][pos], -1);
5667		isl_int_set_si(bmap->ineq[j][0], value);
5668	} else {
5669		isl_int_set_si(bmap->ineq[j][pos], 1);
5670		isl_int_set_si(bmap->ineq[j][0], -value);
5671	}
5672	bmap = isl_basic_map_simplify(bmap);
5673	return isl_basic_map_finalize(bmap);
5674error:
5675	isl_basic_map_free(bmap);
5676	return NULL;
5677}
5678
5679__isl_give isl_basic_map *isl_basic_map_lower_bound_si(
5680	__isl_take isl_basic_map *bmap,
5681	enum isl_dim_type type, unsigned pos, int value)
5682{
5683	return basic_map_bound_si(bmap, type, pos, value, 0);
5684}
5685
5686/* Constrain the values of the given dimension to be no greater than "value".
5687 */
5688__isl_give isl_basic_map *isl_basic_map_upper_bound_si(
5689	__isl_take isl_basic_map *bmap,
5690	enum isl_dim_type type, unsigned pos, int value)
5691{
5692	return basic_map_bound_si(bmap, type, pos, value, 1);
5693}
5694
5695struct isl_basic_set *isl_basic_set_lower_bound_dim(struct isl_basic_set *bset,
5696	unsigned dim, isl_int value)
5697{
5698	int j;
5699
5700	bset = isl_basic_set_cow(bset);
5701	bset = isl_basic_set_extend_constraints(bset, 0, 1);
5702	j = isl_basic_set_alloc_inequality(bset);
5703	if (j < 0)
5704		goto error;
5705	isl_seq_clr(bset->ineq[j], 1 + isl_basic_set_total_dim(bset));
5706	isl_int_set_si(bset->ineq[j][1 + isl_basic_set_n_param(bset) + dim], 1);
5707	isl_int_neg(bset->ineq[j][0], value);
5708	bset = isl_basic_set_simplify(bset);
5709	return isl_basic_set_finalize(bset);
5710error:
5711	isl_basic_set_free(bset);
5712	return NULL;
5713}
5714
5715static __isl_give isl_map *map_bound_si(__isl_take isl_map *map,
5716	enum isl_dim_type type, unsigned pos, int value, int upper)
5717{
5718	int i;
5719
5720	map = isl_map_cow(map);
5721	if (!map)
5722		return NULL;
5723
5724	isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
5725	for (i = 0; i < map->n; ++i) {
5726		map->p[i] = basic_map_bound_si(map->p[i],
5727						 type, pos, value, upper);
5728		if (!map->p[i])
5729			goto error;
5730	}
5731	ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5732	return map;
5733error:
5734	isl_map_free(map);
5735	return NULL;
5736}
5737
5738__isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,
5739	enum isl_dim_type type, unsigned pos, int value)
5740{
5741	return map_bound_si(map, type, pos, value, 0);
5742}
5743
5744__isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,
5745	enum isl_dim_type type, unsigned pos, int value)
5746{
5747	return map_bound_si(map, type, pos, value, 1);
5748}
5749
5750__isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,
5751		enum isl_dim_type type, unsigned pos, int value)
5752{
5753	return (struct isl_set *)
5754		isl_map_lower_bound_si((struct isl_map *)set, type, pos, value);
5755}
5756
5757__isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,
5758	enum isl_dim_type type, unsigned pos, int value)
5759{
5760	return isl_map_upper_bound_si(set, type, pos, value);
5761}
5762
5763/* Bound the given variable of "bmap" from below (or above is "upper"
5764 * is set) to "value".
5765 */
5766static __isl_give isl_basic_map *basic_map_bound(
5767	__isl_take isl_basic_map *bmap,
5768	enum isl_dim_type type, unsigned pos, isl_int value, int upper)
5769{
5770	int j;
5771
5772	if (!bmap)
5773		return NULL;
5774	if (pos >= isl_basic_map_dim(bmap, type))
5775		isl_die(bmap->ctx, isl_error_invalid,
5776			"index out of bounds", goto error);
5777	pos += isl_basic_map_offset(bmap, type);
5778	bmap = isl_basic_map_cow(bmap);
5779	bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
5780	j = isl_basic_map_alloc_inequality(bmap);
5781	if (j < 0)
5782		goto error;
5783	isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
5784	if (upper) {
5785		isl_int_set_si(bmap->ineq[j][pos], -1);
5786		isl_int_set(bmap->ineq[j][0], value);
5787	} else {
5788		isl_int_set_si(bmap->ineq[j][pos], 1);
5789		isl_int_neg(bmap->ineq[j][0], value);
5790	}
5791	bmap = isl_basic_map_simplify(bmap);
5792	return isl_basic_map_finalize(bmap);
5793error:
5794	isl_basic_map_free(bmap);
5795	return NULL;
5796}
5797
5798/* Bound the given variable of "map" from below (or above is "upper"
5799 * is set) to "value".
5800 */
5801static __isl_give isl_map *map_bound(__isl_take isl_map *map,
5802	enum isl_dim_type type, unsigned pos, isl_int value, int upper)
5803{
5804	int i;
5805
5806	map = isl_map_cow(map);
5807	if (!map)
5808		return NULL;
5809
5810	if (pos >= isl_map_dim(map, type))
5811		isl_die(map->ctx, isl_error_invalid,
5812			"index out of bounds", goto error);
5813	for (i = map->n - 1; i >= 0; --i) {
5814		map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper);
5815		if (remove_if_empty(map, i) < 0)
5816			goto error;
5817	}
5818	ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5819	return map;
5820error:
5821	isl_map_free(map);
5822	return NULL;
5823}
5824
5825__isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,
5826	enum isl_dim_type type, unsigned pos, isl_int value)
5827{
5828	return map_bound(map, type, pos, value, 0);
5829}
5830
5831__isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map,
5832	enum isl_dim_type type, unsigned pos, isl_int value)
5833{
5834	return map_bound(map, type, pos, value, 1);
5835}
5836
5837__isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
5838	enum isl_dim_type type, unsigned pos, isl_int value)
5839{
5840	return isl_map_lower_bound(set, type, pos, value);
5841}
5842
5843__isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
5844	enum isl_dim_type type, unsigned pos, isl_int value)
5845{
5846	return isl_map_upper_bound(set, type, pos, value);
5847}
5848
5849/* Force the values of the variable at position "pos" of type "type" of "set"
5850 * to be no smaller than "value".
5851 */
5852__isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,
5853	enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
5854{
5855	if (!value)
5856		goto error;
5857	if (!isl_val_is_int(value))
5858		isl_die(isl_set_get_ctx(set), isl_error_invalid,
5859			"expecting integer value", goto error);
5860	set = isl_set_lower_bound(set, type, pos, value->n);
5861	isl_val_free(value);
5862	return set;
5863error:
5864	isl_val_free(value);
5865	isl_set_free(set);
5866	return NULL;
5867}
5868
5869/* Force the values of the variable at position "pos" of type "type" of "set"
5870 * to be no greater than "value".
5871 */
5872__isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,
5873	enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
5874{
5875	if (!value)
5876		goto error;
5877	if (!isl_val_is_int(value))
5878		isl_die(isl_set_get_ctx(set), isl_error_invalid,
5879			"expecting integer value", goto error);
5880	set = isl_set_upper_bound(set, type, pos, value->n);
5881	isl_val_free(value);
5882	return set;
5883error:
5884	isl_val_free(value);
5885	isl_set_free(set);
5886	return NULL;
5887}
5888
5889struct isl_set *isl_set_lower_bound_dim(struct isl_set *set, unsigned dim,
5890					isl_int value)
5891{
5892	int i;
5893
5894	set = isl_set_cow(set);
5895	if (!set)
5896		return NULL;
5897
5898	isl_assert(set->ctx, dim < isl_set_n_dim(set), goto error);
5899	for (i = 0; i < set->n; ++i) {
5900		set->p[i] = isl_basic_set_lower_bound_dim(set->p[i], dim, value);
5901		if (!set->p[i])
5902			goto error;
5903	}
5904	return set;
5905error:
5906	isl_set_free(set);
5907	return NULL;
5908}
5909
5910struct isl_map *isl_map_reverse(struct isl_map *map)
5911{
5912	int i;
5913
5914	map = isl_map_cow(map);
5915	if (!map)
5916		return NULL;
5917
5918	map->dim = isl_space_reverse(map->dim);
5919	if (!map->dim)
5920		goto error;
5921	for (i = 0; i < map->n; ++i) {
5922		map->p[i] = isl_basic_map_reverse(map->p[i]);
5923		if (!map->p[i])
5924			goto error;
5925	}
5926	ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5927	return map;
5928error:
5929	isl_map_free(map);
5930	return NULL;
5931}
5932
5933static struct isl_map *isl_basic_map_partial_lexopt(
5934		struct isl_basic_map *bmap, struct isl_basic_set *dom,
5935		struct isl_set **empty, int max)
5936{
5937	if (!bmap)
5938		goto error;
5939	if (bmap->ctx->opt->pip == ISL_PIP_PIP)
5940		return isl_pip_basic_map_lexopt(bmap, dom, empty, max);
5941	else
5942		return isl_tab_basic_map_partial_lexopt(bmap, dom, empty, max);
5943error:
5944	isl_basic_map_free(bmap);
5945	isl_basic_set_free(dom);
5946	if (empty)
5947		*empty = NULL;
5948	return NULL;
5949}
5950
5951struct isl_map *isl_basic_map_partial_lexmax(
5952		struct isl_basic_map *bmap, struct isl_basic_set *dom,
5953		struct isl_set **empty)
5954{
5955	return isl_basic_map_partial_lexopt(bmap, dom, empty, 1);
5956}
5957
5958struct isl_map *isl_basic_map_partial_lexmin(
5959		struct isl_basic_map *bmap, struct isl_basic_set *dom,
5960		struct isl_set **empty)
5961{
5962	return isl_basic_map_partial_lexopt(bmap, dom, empty, 0);
5963}
5964
5965struct isl_set *isl_basic_set_partial_lexmin(
5966		struct isl_basic_set *bset, struct isl_basic_set *dom,
5967		struct isl_set **empty)
5968{
5969	return (struct isl_set *)
5970		isl_basic_map_partial_lexmin((struct isl_basic_map *)bset,
5971			dom, empty);
5972}
5973
5974struct isl_set *isl_basic_set_partial_lexmax(
5975		struct isl_basic_set *bset, struct isl_basic_set *dom,
5976		struct isl_set **empty)
5977{
5978	return (struct isl_set *)
5979		isl_basic_map_partial_lexmax((struct isl_basic_map *)bset,
5980			dom, empty);
5981}
5982
5983__isl_give isl_pw_multi_aff *isl_basic_map_partial_lexmin_pw_multi_aff(
5984	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
5985	__isl_give isl_set **empty)
5986{
5987	return isl_basic_map_partial_lexopt_pw_multi_aff(bmap, dom, empty, 0);
5988}
5989
5990__isl_give isl_pw_multi_aff *isl_basic_map_partial_lexmax_pw_multi_aff(
5991	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
5992	__isl_give isl_set **empty)
5993{
5994	return isl_basic_map_partial_lexopt_pw_multi_aff(bmap, dom, empty, 1);
5995}
5996
5997__isl_give isl_pw_multi_aff *isl_basic_set_partial_lexmin_pw_multi_aff(
5998	__isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom,
5999	__isl_give isl_set **empty)
6000{
6001	return isl_basic_map_partial_lexmin_pw_multi_aff(bset, dom, empty);
6002}
6003
6004__isl_give isl_pw_multi_aff *isl_basic_set_partial_lexmax_pw_multi_aff(
6005	__isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom,
6006	__isl_give isl_set **empty)
6007{
6008	return isl_basic_map_partial_lexmax_pw_multi_aff(bset, dom, empty);
6009}
6010
6011__isl_give isl_pw_multi_aff *isl_basic_map_lexopt_pw_multi_aff(
6012	__isl_take isl_basic_map *bmap, int max)
6013{
6014	isl_basic_set *dom = NULL;
6015	isl_space *dom_space;
6016
6017	if (!bmap)
6018		goto error;
6019	dom_space = isl_space_domain(isl_space_copy(bmap->dim));
6020	dom = isl_basic_set_universe(dom_space);
6021	return isl_basic_map_partial_lexopt_pw_multi_aff(bmap, dom, NULL, max);
6022error:
6023	isl_basic_map_free(bmap);
6024	return NULL;
6025}
6026
6027__isl_give isl_pw_multi_aff *isl_basic_map_lexmin_pw_multi_aff(
6028	__isl_take isl_basic_map *bmap)
6029{
6030	return isl_basic_map_lexopt_pw_multi_aff(bmap, 0);
6031}
6032
6033#undef TYPE
6034#define TYPE	isl_pw_multi_aff
6035#undef SUFFIX
6036#define SUFFIX	_pw_multi_aff
6037#undef EMPTY
6038#define EMPTY	isl_pw_multi_aff_empty
6039#undef ADD
6040#define ADD	isl_pw_multi_aff_union_add
6041#include "isl_map_lexopt_templ.c"
6042
6043/* Given a map "map", compute the lexicographically minimal
6044 * (or maximal) image element for each domain element in dom,
6045 * in the form of an isl_pw_multi_aff.
6046 * Set *empty to those elements in dom that do not have an image element.
6047 *
6048 * We first compute the lexicographically minimal or maximal element
6049 * in the first basic map.  This results in a partial solution "res"
6050 * and a subset "todo" of dom that still need to be handled.
6051 * We then consider each of the remaining maps in "map" and successively
6052 * update both "res" and "todo".
6053 */
6054static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
6055	__isl_take isl_map *map, __isl_take isl_set *dom,
6056	__isl_give isl_set **empty, int max)
6057{
6058	int i;
6059	isl_pw_multi_aff *res;
6060	isl_set *todo;
6061
6062	if (!map || !dom)
6063		goto error;
6064
6065	if (isl_map_plain_is_empty(map)) {
6066		if (empty)
6067			*empty = dom;
6068		else
6069			isl_set_free(dom);
6070		return isl_pw_multi_aff_from_map(map);
6071	}
6072
6073	res = basic_map_partial_lexopt_pw_multi_aff(
6074					    isl_basic_map_copy(map->p[0]),
6075					    isl_set_copy(dom), &todo, max);
6076
6077	for (i = 1; i < map->n; ++i) {
6078		isl_pw_multi_aff *res_i;
6079		isl_set *todo_i;
6080
6081		res_i = basic_map_partial_lexopt_pw_multi_aff(
6082					    isl_basic_map_copy(map->p[i]),
6083					    isl_set_copy(dom), &todo_i, max);
6084
6085		if (max)
6086			res = isl_pw_multi_aff_union_lexmax(res, res_i);
6087		else
6088			res = isl_pw_multi_aff_union_lexmin(res, res_i);
6089
6090		todo = isl_set_intersect(todo, todo_i);
6091	}
6092
6093	isl_set_free(dom);
6094	isl_map_free(map);
6095
6096	if (empty)
6097		*empty = todo;
6098	else
6099		isl_set_free(todo);
6100
6101	return res;
6102error:
6103	if (empty)
6104		*empty = NULL;
6105	isl_set_free(dom);
6106	isl_map_free(map);
6107	return NULL;
6108}
6109
6110#undef TYPE
6111#define TYPE	isl_map
6112#undef SUFFIX
6113#define SUFFIX
6114#undef EMPTY
6115#define EMPTY	isl_map_empty
6116#undef ADD
6117#define ADD	isl_map_union_disjoint
6118#include "isl_map_lexopt_templ.c"
6119
6120/* Given a map "map", compute the lexicographically minimal
6121 * (or maximal) image element for each domain element in dom.
6122 * Set *empty to those elements in dom that do not have an image element.
6123 *
6124 * We first compute the lexicographically minimal or maximal element
6125 * in the first basic map.  This results in a partial solution "res"
6126 * and a subset "todo" of dom that still need to be handled.
6127 * We then consider each of the remaining maps in "map" and successively
6128 * update both "res" and "todo".
6129 *
6130 * Let res^k and todo^k be the results after k steps and let i = k + 1.
6131 * Assume we are computing the lexicographical maximum.
6132 * We first compute the lexicographically maximal element in basic map i.
6133 * This results in a partial solution res_i and a subset todo_i.
6134 * Then we combine these results with those obtain for the first k basic maps
6135 * to obtain a result that is valid for the first k+1 basic maps.
6136 * In particular, the set where there is no solution is the set where
6137 * there is no solution for the first k basic maps and also no solution
6138 * for the ith basic map, i.e.,
6139 *
6140 *	todo^i = todo^k * todo_i
6141 *
6142 * On dom(res^k) * dom(res_i), we need to pick the larger of the two
6143 * solutions, arbitrarily breaking ties in favor of res^k.
6144 * That is, when res^k(a) >= res_i(a), we pick res^k and
6145 * when res^k(a) < res_i(a), we pick res_i.  (Here, ">=" and "<" denote
6146 * the lexicographic order.)
6147 * In practice, we compute
6148 *
6149 *	res^k * (res_i . "<=")
6150 *
6151 * and
6152 *
6153 *	res_i * (res^k . "<")
6154 *
6155 * Finally, we consider the symmetric difference of dom(res^k) and dom(res_i),
6156 * where only one of res^k and res_i provides a solution and we simply pick
6157 * that one, i.e.,
6158 *
6159 *	res^k * todo_i
6160 * and
6161 *	res_i * todo^k
6162 *
6163 * Note that we only compute these intersections when dom(res^k) intersects
6164 * dom(res_i).  Otherwise, the only effect of these intersections is to
6165 * potentially break up res^k and res_i into smaller pieces.
6166 * We want to avoid such splintering as much as possible.
6167 * In fact, an earlier implementation of this function would look for
6168 * better results in the domain of res^k and for extra results in todo^k,
6169 * but this would always result in a splintering according to todo^k,
6170 * even when the domain of basic map i is disjoint from the domains of
6171 * the previous basic maps.
6172 */
6173static __isl_give isl_map *isl_map_partial_lexopt_aligned(
6174		__isl_take isl_map *map, __isl_take isl_set *dom,
6175		__isl_give isl_set **empty, int max)
6176{
6177	int i;
6178	struct isl_map *res;
6179	struct isl_set *todo;
6180
6181	if (!map || !dom)
6182		goto error;
6183
6184	if (isl_map_plain_is_empty(map)) {
6185		if (empty)
6186			*empty = dom;
6187		else
6188			isl_set_free(dom);
6189		return map;
6190	}
6191
6192	res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
6193					isl_set_copy(dom), &todo, max);
6194
6195	for (i = 1; i < map->n; ++i) {
6196		isl_map *lt, *le;
6197		isl_map *res_i;
6198		isl_set *todo_i;
6199		isl_space *dim = isl_space_range(isl_map_get_space(res));
6200
6201		res_i = basic_map_partial_lexopt(isl_basic_map_copy(map->p[i]),
6202					isl_set_copy(dom), &todo_i, max);
6203
6204		if (max) {
6205			lt = isl_map_lex_lt(isl_space_copy(dim));
6206			le = isl_map_lex_le(dim);
6207		} else {
6208			lt = isl_map_lex_gt(isl_space_copy(dim));
6209			le = isl_map_lex_ge(dim);
6210		}
6211		lt = isl_map_apply_range(isl_map_copy(res), lt);
6212		lt = isl_map_intersect(lt, isl_map_copy(res_i));
6213		le = isl_map_apply_range(isl_map_copy(res_i), le);
6214		le = isl_map_intersect(le, isl_map_copy(res));
6215
6216		if (!isl_map_is_empty(lt) || !isl_map_is_empty(le)) {
6217			res = isl_map_intersect_domain(res,
6218							isl_set_copy(todo_i));
6219			res_i = isl_map_intersect_domain(res_i,
6220							isl_set_copy(todo));
6221		}
6222
6223		res = isl_map_union_disjoint(res, res_i);
6224		res = isl_map_union_disjoint(res, lt);
6225		res = isl_map_union_disjoint(res, le);
6226
6227		todo = isl_set_intersect(todo, todo_i);
6228	}
6229
6230	isl_set_free(dom);
6231	isl_map_free(map);
6232
6233	if (empty)
6234		*empty = todo;
6235	else
6236		isl_set_free(todo);
6237
6238	return res;
6239error:
6240	if (empty)
6241		*empty = NULL;
6242	isl_set_free(dom);
6243	isl_map_free(map);
6244	return NULL;
6245}
6246
6247__isl_give isl_map *isl_map_partial_lexmax(
6248		__isl_take isl_map *map, __isl_take isl_set *dom,
6249		__isl_give isl_set **empty)
6250{
6251	return isl_map_partial_lexopt(map, dom, empty, 1);
6252}
6253
6254__isl_give isl_map *isl_map_partial_lexmin(
6255		__isl_take isl_map *map, __isl_take isl_set *dom,
6256		__isl_give isl_set **empty)
6257{
6258	return isl_map_partial_lexopt(map, dom, empty, 0);
6259}
6260
6261__isl_give isl_set *isl_set_partial_lexmin(
6262		__isl_take isl_set *set, __isl_take isl_set *dom,
6263		__isl_give isl_set **empty)
6264{
6265	return (struct isl_set *)
6266		isl_map_partial_lexmin((struct isl_map *)set,
6267			dom, empty);
6268}
6269
6270__isl_give isl_set *isl_set_partial_lexmax(
6271		__isl_take isl_set *set, __isl_take isl_set *dom,
6272		__isl_give isl_set **empty)
6273{
6274	return (struct isl_set *)
6275		isl_map_partial_lexmax((struct isl_map *)set,
6276			dom, empty);
6277}
6278
6279/* Compute the lexicographic minimum (or maximum if "max" is set)
6280 * of "bmap" over its domain.
6281 *
6282 * Since we are not interested in the part of the domain space where
6283 * there is no solution, we initialize the domain to those constraints
6284 * of "bmap" that only involve the parameters and the input dimensions.
6285 * This relieves the parametric programming engine from detecting those
6286 * inequalities and transferring them to the context.  More importantly,
6287 * it ensures that those inequalities are transferred first and not
6288 * intermixed with inequalities that actually split the domain.
6289 */
6290__isl_give isl_map *isl_basic_map_lexopt(__isl_take isl_basic_map *bmap, int max)
6291{
6292	int n_div;
6293	int n_out;
6294	isl_basic_map *copy;
6295	isl_basic_set *dom;
6296
6297	n_div = isl_basic_map_dim(bmap, isl_dim_div);
6298	n_out = isl_basic_map_dim(bmap, isl_dim_out);
6299	copy = isl_basic_map_copy(bmap);
6300	copy = isl_basic_map_drop_constraints_involving_dims(copy,
6301							isl_dim_div, 0, n_div);
6302	copy = isl_basic_map_drop_constraints_involving_dims(copy,
6303							isl_dim_out, 0, n_out);
6304	dom = isl_basic_map_domain(copy);
6305	return isl_basic_map_partial_lexopt(bmap, dom, NULL, max);
6306}
6307
6308__isl_give isl_map *isl_basic_map_lexmin(__isl_take isl_basic_map *bmap)
6309{
6310	return isl_basic_map_lexopt(bmap, 0);
6311}
6312
6313__isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
6314{
6315	return isl_basic_map_lexopt(bmap, 1);
6316}
6317
6318__isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
6319{
6320	return (isl_set *)isl_basic_map_lexmin((isl_basic_map *)bset);
6321}
6322
6323__isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
6324{
6325	return (isl_set *)isl_basic_map_lexmax((isl_basic_map *)bset);
6326}
6327
6328/* Extract the first and only affine expression from list
6329 * and then add it to *pwaff with the given dom.
6330 * This domain is known to be disjoint from other domains
6331 * because of the way isl_basic_map_foreach_lexmax works.
6332 */
6333static int update_dim_opt(__isl_take isl_basic_set *dom,
6334	__isl_take isl_aff_list *list, void *user)
6335{
6336	isl_ctx *ctx = isl_basic_set_get_ctx(dom);
6337	isl_aff *aff;
6338	isl_pw_aff **pwaff = user;
6339	isl_pw_aff *pwaff_i;
6340
6341	if (!list)
6342		goto error;
6343	if (isl_aff_list_n_aff(list) != 1)
6344		isl_die(ctx, isl_error_internal,
6345			"expecting single element list", goto error);
6346
6347	aff = isl_aff_list_get_aff(list, 0);
6348	pwaff_i = isl_pw_aff_alloc(isl_set_from_basic_set(dom), aff);
6349
6350	*pwaff = isl_pw_aff_add_disjoint(*pwaff, pwaff_i);
6351
6352	isl_aff_list_free(list);
6353
6354	return 0;
6355error:
6356	isl_basic_set_free(dom);
6357	isl_aff_list_free(list);
6358	return -1;
6359}
6360
6361/* Given a basic map with one output dimension, compute the minimum or
6362 * maximum of that dimension as an isl_pw_aff.
6363 *
6364 * The isl_pw_aff is constructed by having isl_basic_map_foreach_lexopt
6365 * call update_dim_opt on each leaf of the result.
6366 */
6367static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,
6368	int max)
6369{
6370	isl_space *dim = isl_basic_map_get_space(bmap);
6371	isl_pw_aff *pwaff;
6372	int r;
6373
6374	dim = isl_space_from_domain(isl_space_domain(dim));
6375	dim = isl_space_add_dims(dim, isl_dim_out, 1);
6376	pwaff = isl_pw_aff_empty(dim);
6377
6378	r = isl_basic_map_foreach_lexopt(bmap, max, &update_dim_opt, &pwaff);
6379	if (r < 0)
6380		return isl_pw_aff_free(pwaff);
6381
6382	return pwaff;
6383}
6384
6385/* Compute the minimum or maximum of the given output dimension
6386 * as a function of the parameters and the input dimensions,
6387 * but independently of the other output dimensions.
6388 *
6389 * We first project out the other output dimension and then compute
6390 * the "lexicographic" maximum in each basic map, combining the results
6391 * using isl_pw_aff_union_max.
6392 */
6393static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
6394	int max)
6395{
6396	int i;
6397	isl_pw_aff *pwaff;
6398	unsigned n_out;
6399
6400	n_out = isl_map_dim(map, isl_dim_out);
6401	map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
6402	map = isl_map_project_out(map, isl_dim_out, 0, pos);
6403	if (!map)
6404		return NULL;
6405
6406	if (map->n == 0) {
6407		isl_space *dim = isl_map_get_space(map);
6408		dim = isl_space_domain(isl_space_from_range(dim));
6409		isl_map_free(map);
6410		return isl_pw_aff_empty(dim);
6411	}
6412
6413	pwaff = basic_map_dim_opt(map->p[0], max);
6414	for (i = 1; i < map->n; ++i) {
6415		isl_pw_aff *pwaff_i;
6416
6417		pwaff_i = basic_map_dim_opt(map->p[i], max);
6418		pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);
6419	}
6420
6421	isl_map_free(map);
6422
6423	return pwaff;
6424}
6425
6426/* Compute the maximum of the given output dimension as a function of the
6427 * parameters and input dimensions, but independently of
6428 * the other output dimensions.
6429 */
6430__isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)
6431{
6432	return map_dim_opt(map, pos, 1);
6433}
6434
6435/* Compute the minimum or maximum of the given set dimension
6436 * as a function of the parameters,
6437 * but independently of the other set dimensions.
6438 */
6439static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,
6440	int max)
6441{
6442	return map_dim_opt(set, pos, max);
6443}
6444
6445/* Compute the maximum of the given set dimension as a function of the
6446 * parameters, but independently of the other set dimensions.
6447 */
6448__isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)
6449{
6450	return set_dim_opt(set, pos, 1);
6451}
6452
6453/* Compute the minimum of the given set dimension as a function of the
6454 * parameters, but independently of the other set dimensions.
6455 */
6456__isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
6457{
6458	return set_dim_opt(set, pos, 0);
6459}
6460
6461/* Apply a preimage specified by "mat" on the parameters of "bset".
6462 * bset is assumed to have only parameters and divs.
6463 */
6464static struct isl_basic_set *basic_set_parameter_preimage(
6465	struct isl_basic_set *bset, struct isl_mat *mat)
6466{
6467	unsigned nparam;
6468
6469	if (!bset || !mat)
6470		goto error;
6471
6472	bset->dim = isl_space_cow(bset->dim);
6473	if (!bset->dim)
6474		goto error;
6475
6476	nparam = isl_basic_set_dim(bset, isl_dim_param);
6477
6478	isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
6479
6480	bset->dim->nparam = 0;
6481	bset->dim->n_out = nparam;
6482	bset = isl_basic_set_preimage(bset, mat);
6483	if (bset) {
6484		bset->dim->nparam = bset->dim->n_out;
6485		bset->dim->n_out = 0;
6486	}
6487	return bset;
6488error:
6489	isl_mat_free(mat);
6490	isl_basic_set_free(bset);
6491	return NULL;
6492}
6493
6494/* Apply a preimage specified by "mat" on the parameters of "set".
6495 * set is assumed to have only parameters and divs.
6496 */
6497static struct isl_set *set_parameter_preimage(
6498	struct isl_set *set, struct isl_mat *mat)
6499{
6500	isl_space *dim = NULL;
6501	unsigned nparam;
6502
6503	if (!set || !mat)
6504		goto error;
6505
6506	dim = isl_space_copy(set->dim);
6507	dim = isl_space_cow(dim);
6508	if (!dim)
6509		goto error;
6510
6511	nparam = isl_set_dim(set, isl_dim_param);
6512
6513	isl_assert(set->ctx, mat->n_row == 1 + nparam, goto error);
6514
6515	dim->nparam = 0;
6516	dim->n_out = nparam;
6517	isl_set_reset_space(set, dim);
6518	set = isl_set_preimage(set, mat);
6519	if (!set)
6520		goto error2;
6521	dim = isl_space_copy(set->dim);
6522	dim = isl_space_cow(dim);
6523	if (!dim)
6524		goto error2;
6525	dim->nparam = dim->n_out;
6526	dim->n_out = 0;
6527	isl_set_reset_space(set, dim);
6528	return set;
6529error:
6530	isl_space_free(dim);
6531	isl_mat_free(mat);
6532error2:
6533	isl_set_free(set);
6534	return NULL;
6535}
6536
6537/* Intersect the basic set "bset" with the affine space specified by the
6538 * equalities in "eq".
6539 */
6540static struct isl_basic_set *basic_set_append_equalities(
6541	struct isl_basic_set *bset, struct isl_mat *eq)
6542{
6543	int i, k;
6544	unsigned len;
6545
6546	if (!bset || !eq)
6547		goto error;
6548
6549	bset = isl_basic_set_extend_space(bset, isl_space_copy(bset->dim), 0,
6550					eq->n_row, 0);
6551	if (!bset)
6552		goto error;
6553
6554	len = 1 + isl_space_dim(bset->dim, isl_dim_all) + bset->extra;
6555	for (i = 0; i < eq->n_row; ++i) {
6556		k = isl_basic_set_alloc_equality(bset);
6557		if (k < 0)
6558			goto error;
6559		isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);
6560		isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);
6561	}
6562	isl_mat_free(eq);
6563
6564	bset = isl_basic_set_gauss(bset, NULL);
6565	bset = isl_basic_set_finalize(bset);
6566
6567	return bset;
6568error:
6569	isl_mat_free(eq);
6570	isl_basic_set_free(bset);
6571	return NULL;
6572}
6573
6574/* Intersect the set "set" with the affine space specified by the
6575 * equalities in "eq".
6576 */
6577static struct isl_set *set_append_equalities(struct isl_set *set,
6578	struct isl_mat *eq)
6579{
6580	int i;
6581
6582	if (!set || !eq)
6583		goto error;
6584
6585	for (i = 0; i < set->n; ++i) {
6586		set->p[i] = basic_set_append_equalities(set->p[i],
6587					isl_mat_copy(eq));
6588		if (!set->p[i])
6589			goto error;
6590	}
6591	isl_mat_free(eq);
6592	return set;
6593error:
6594	isl_mat_free(eq);
6595	isl_set_free(set);
6596	return NULL;
6597}
6598
6599/* Given a basic set "bset" that only involves parameters and existentially
6600 * quantified variables, return the index of the first equality
6601 * that only involves parameters.  If there is no such equality then
6602 * return bset->n_eq.
6603 *
6604 * This function assumes that isl_basic_set_gauss has been called on "bset".
6605 */
6606static int first_parameter_equality(__isl_keep isl_basic_set *bset)
6607{
6608	int i, j;
6609	unsigned nparam, n_div;
6610
6611	if (!bset)
6612		return -1;
6613
6614	nparam = isl_basic_set_dim(bset, isl_dim_param);
6615	n_div = isl_basic_set_dim(bset, isl_dim_div);
6616
6617	for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
6618		if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
6619			++i;
6620	}
6621
6622	return i;
6623}
6624
6625/* Compute an explicit representation for the existentially quantified
6626 * variables in "bset" by computing the "minimal value" of the set
6627 * variables.  Since there are no set variables, the computation of
6628 * the minimal value essentially computes an explicit representation
6629 * of the non-empty part(s) of "bset".
6630 *
6631 * The input only involves parameters and existentially quantified variables.
6632 * All equalities among parameters have been removed.
6633 *
6634 * Since the existentially quantified variables in the result are in general
6635 * going to be different from those in the input, we first replace
6636 * them by the minimal number of variables based on their equalities.
6637 * This should simplify the parametric integer programming.
6638 */
6639static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
6640{
6641	isl_morph *morph1, *morph2;
6642	isl_set *set;
6643	unsigned n;
6644
6645	if (!bset)
6646		return NULL;
6647	if (bset->n_eq == 0)
6648		return isl_basic_set_lexmin(bset);
6649
6650	morph1 = isl_basic_set_parameter_compression(bset);
6651	bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
6652	bset = isl_basic_set_lift(bset);
6653	morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
6654	bset = isl_morph_basic_set(morph2, bset);
6655	n = isl_basic_set_dim(bset, isl_dim_set);
6656	bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
6657
6658	set = isl_basic_set_lexmin(bset);
6659
6660	set = isl_morph_set(isl_morph_inverse(morph1), set);
6661
6662	return set;
6663}
6664
6665/* Project the given basic set onto its parameter domain, possibly introducing
6666 * new, explicit, existential variables in the constraints.
6667 * The input has parameters and (possibly implicit) existential variables.
6668 * The output has the same parameters, but only
6669 * explicit existentially quantified variables.
6670 *
6671 * The actual projection is performed by pip, but pip doesn't seem
6672 * to like equalities very much, so we first remove the equalities
6673 * among the parameters by performing a variable compression on
6674 * the parameters.  Afterward, an inverse transformation is performed
6675 * and the equalities among the parameters are inserted back in.
6676 *
6677 * The variable compression on the parameters may uncover additional
6678 * equalities that were only implicit before.  We therefore check
6679 * if there are any new parameter equalities in the result and
6680 * if so recurse.  The removal of parameter equalities is required
6681 * for the parameter compression performed by base_compute_divs.
6682 */
6683static struct isl_set *parameter_compute_divs(struct isl_basic_set *bset)
6684{
6685	int i;
6686	struct isl_mat *eq;
6687	struct isl_mat *T, *T2;
6688	struct isl_set *set;
6689	unsigned nparam;
6690
6691	bset = isl_basic_set_cow(bset);
6692	if (!bset)
6693		return NULL;
6694
6695	if (bset->n_eq == 0)
6696		return base_compute_divs(bset);
6697
6698	bset = isl_basic_set_gauss(bset, NULL);
6699	if (!bset)
6700		return NULL;
6701	if (isl_basic_set_plain_is_empty(bset))
6702		return isl_set_from_basic_set(bset);
6703
6704	i = first_parameter_equality(bset);
6705	if (i == bset->n_eq)
6706		return base_compute_divs(bset);
6707
6708	nparam = isl_basic_set_dim(bset, isl_dim_param);
6709	eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
6710		0, 1 + nparam);
6711	eq = isl_mat_cow(eq);
6712	T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);
6713	if (T && T->n_col == 0) {
6714		isl_mat_free(T);
6715		isl_mat_free(T2);
6716		isl_mat_free(eq);
6717		bset = isl_basic_set_set_to_empty(bset);
6718		return isl_set_from_basic_set(bset);
6719	}
6720	bset = basic_set_parameter_preimage(bset, T);
6721
6722	i = first_parameter_equality(bset);
6723	if (!bset)
6724		set = NULL;
6725	else if (i == bset->n_eq)
6726		set = base_compute_divs(bset);
6727	else
6728		set = parameter_compute_divs(bset);
6729	set = set_parameter_preimage(set, T2);
6730	set = set_append_equalities(set, eq);
6731	return set;
6732}
6733
6734/* Insert the divs from "ls" before those of "bmap".
6735 *
6736 * The number of columns is not changed, which means that the last
6737 * dimensions of "bmap" are being reintepreted as the divs from "ls".
6738 * The caller is responsible for removing the same number of dimensions
6739 * from the space of "bmap".
6740 */
6741static __isl_give isl_basic_map *insert_divs_from_local_space(
6742	__isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
6743{
6744	int i;
6745	int n_div;
6746	int old_n_div;
6747
6748	n_div = isl_local_space_dim(ls, isl_dim_div);
6749	if (n_div == 0)
6750		return bmap;
6751
6752	old_n_div = bmap->n_div;
6753	bmap = insert_div_rows(bmap, n_div);
6754	if (!bmap)
6755		return NULL;
6756
6757	for (i = 0; i < n_div; ++i) {
6758		isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
6759		isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);
6760	}
6761
6762	return bmap;
6763}
6764
6765/* Replace the space of "bmap" by the space and divs of "ls".
6766 *
6767 * If "ls" has any divs, then we simplify the result since we may
6768 * have discovered some additional equalities that could simplify
6769 * the div expressions.
6770 */
6771static __isl_give isl_basic_map *basic_replace_space_by_local_space(
6772	__isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
6773{
6774	int n_div;
6775
6776	bmap = isl_basic_map_cow(bmap);
6777	if (!bmap || !ls)
6778		goto error;
6779
6780	n_div = isl_local_space_dim(ls, isl_dim_div);
6781	bmap = insert_divs_from_local_space(bmap, ls);
6782	if (!bmap)
6783		goto error;
6784
6785	isl_space_free(bmap->dim);
6786	bmap->dim = isl_local_space_get_space(ls);
6787	if (!bmap->dim)
6788		goto error;
6789
6790	isl_local_space_free(ls);
6791	if (n_div > 0)
6792		bmap = isl_basic_map_simplify(bmap);
6793	bmap = isl_basic_map_finalize(bmap);
6794	return bmap;
6795error:
6796	isl_basic_map_free(bmap);
6797	isl_local_space_free(ls);
6798	return NULL;
6799}
6800
6801/* Replace the space of "map" by the space and divs of "ls".
6802 */
6803static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
6804	__isl_take isl_local_space *ls)
6805{
6806	int i;
6807
6808	map = isl_map_cow(map);
6809	if (!map || !ls)
6810		goto error;
6811
6812	for (i = 0; i < map->n; ++i) {
6813		map->p[i] = basic_replace_space_by_local_space(map->p[i],
6814						    isl_local_space_copy(ls));
6815		if (!map->p[i])
6816			goto error;
6817	}
6818	isl_space_free(map->dim);
6819	map->dim = isl_local_space_get_space(ls);
6820	if (!map->dim)
6821		goto error;
6822
6823	isl_local_space_free(ls);
6824	return map;
6825error:
6826	isl_local_space_free(ls);
6827	isl_map_free(map);
6828	return NULL;
6829}
6830
6831/* Compute an explicit representation for the existentially
6832 * quantified variables for which do not know any explicit representation yet.
6833 *
6834 * We first sort the existentially quantified variables so that the
6835 * existentially quantified variables for which we already have an explicit
6836 * representation are placed before those for which we do not.
6837 * The input dimensions, the output dimensions and the existentially
6838 * quantified variables for which we already have an explicit
6839 * representation are then turned into parameters.
6840 * compute_divs returns a map with the same parameters and
6841 * no input or output dimensions and the dimension specification
6842 * is reset to that of the input, including the existentially quantified
6843 * variables for which we already had an explicit representation.
6844 */
6845static struct isl_map *compute_divs(struct isl_basic_map *bmap)
6846{
6847	struct isl_basic_set *bset;
6848	struct isl_set *set;
6849	struct isl_map *map;
6850	isl_space *dim;
6851	isl_local_space *ls;
6852	unsigned	 nparam;
6853	unsigned	 n_in;
6854	unsigned	 n_out;
6855	unsigned n_known;
6856	int i;
6857
6858	bmap = isl_basic_map_sort_divs(bmap);
6859	bmap = isl_basic_map_cow(bmap);
6860	if (!bmap)
6861		return NULL;
6862
6863	for (n_known = 0; n_known < bmap->n_div; ++n_known)
6864		if (isl_int_is_zero(bmap->div[n_known][0]))
6865			break;
6866
6867	nparam = isl_basic_map_dim(bmap, isl_dim_param);
6868	n_in = isl_basic_map_dim(bmap, isl_dim_in);
6869	n_out = isl_basic_map_dim(bmap, isl_dim_out);
6870	dim = isl_space_set_alloc(bmap->ctx,
6871				    nparam + n_in + n_out + n_known, 0);
6872	if (!dim)
6873		goto error;
6874
6875	ls = isl_basic_map_get_local_space(bmap);
6876	ls = isl_local_space_drop_dims(ls, isl_dim_div,
6877					n_known, bmap->n_div - n_known);
6878	if (n_known > 0) {
6879		for (i = n_known; i < bmap->n_div; ++i)
6880			swap_div(bmap, i - n_known, i);
6881		bmap->n_div -= n_known;
6882		bmap->extra -= n_known;
6883	}
6884	bmap = isl_basic_map_reset_space(bmap, dim);
6885	bset = (struct isl_basic_set *)bmap;
6886
6887	set = parameter_compute_divs(bset);
6888	map = (struct isl_map *)set;
6889	map = replace_space_by_local_space(map, ls);
6890
6891	return map;
6892error:
6893	isl_basic_map_free(bmap);
6894	return NULL;
6895}
6896
6897int isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
6898{
6899	int i;
6900	unsigned off;
6901
6902	if (!bmap)
6903		return -1;
6904
6905	off = isl_space_dim(bmap->dim, isl_dim_all);
6906	for (i = 0; i < bmap->n_div; ++i) {
6907		if (isl_int_is_zero(bmap->div[i][0]))
6908			return 0;
6909		isl_assert(bmap->ctx, isl_int_is_zero(bmap->div[i][1+1+off+i]),
6910				return -1);
6911	}
6912	return 1;
6913}
6914
6915static int map_divs_known(__isl_keep isl_map *map)
6916{
6917	int i;
6918
6919	if (!map)
6920		return -1;
6921
6922	for (i = 0; i < map->n; ++i) {
6923		int known = isl_basic_map_divs_known(map->p[i]);
6924		if (known <= 0)
6925			return known;
6926	}
6927
6928	return 1;
6929}
6930
6931/* If bmap contains any unknown divs, then compute explicit
6932 * expressions for them.  However, this computation may be
6933 * quite expensive, so first try to remove divs that aren't
6934 * strictly needed.
6935 */
6936struct isl_map *isl_basic_map_compute_divs(struct isl_basic_map *bmap)
6937{
6938	int known;
6939	struct isl_map *map;
6940
6941	known = isl_basic_map_divs_known(bmap);
6942	if (known < 0)
6943		goto error;
6944	if (known)
6945		return isl_map_from_basic_map(bmap);
6946
6947	bmap = isl_basic_map_drop_redundant_divs(bmap);
6948
6949	known = isl_basic_map_divs_known(bmap);
6950	if (known < 0)
6951		goto error;
6952	if (known)
6953		return isl_map_from_basic_map(bmap);
6954
6955	map = compute_divs(bmap);
6956	return map;
6957error:
6958	isl_basic_map_free(bmap);
6959	return NULL;
6960}
6961
6962struct isl_map *isl_map_compute_divs(struct isl_map *map)
6963{
6964	int i;
6965	int known;
6966	struct isl_map *res;
6967
6968	if (!map)
6969		return NULL;
6970	if (map->n == 0)
6971		return map;
6972
6973	known = map_divs_known(map);
6974	if (known < 0) {
6975		isl_map_free(map);
6976		return NULL;
6977	}
6978	if (known)
6979		return map;
6980
6981	res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
6982	for (i = 1 ; i < map->n; ++i) {
6983		struct isl_map *r2;
6984		r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
6985		if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
6986			res = isl_map_union_disjoint(res, r2);
6987		else
6988			res = isl_map_union(res, r2);
6989	}
6990	isl_map_free(map);
6991
6992	return res;
6993}
6994
6995struct isl_set *isl_basic_set_compute_divs(struct isl_basic_set *bset)
6996{
6997	return (struct isl_set *)
6998		isl_basic_map_compute_divs((struct isl_basic_map *)bset);
6999}
7000
7001struct isl_set *isl_set_compute_divs(struct isl_set *set)
7002{
7003	return (struct isl_set *)
7004		isl_map_compute_divs((struct isl_map *)set);
7005}
7006
7007struct isl_set *isl_map_domain(struct isl_map *map)
7008{
7009	int i;
7010	struct isl_set *set;
7011
7012	if (!map)
7013		goto error;
7014
7015	map = isl_map_cow(map);
7016	if (!map)
7017		return NULL;
7018
7019	set = (struct isl_set *)map;
7020	set->dim = isl_space_domain(set->dim);
7021	if (!set->dim)
7022		goto error;
7023	for (i = 0; i < map->n; ++i) {
7024		set->p[i] = isl_basic_map_domain(map->p[i]);
7025		if (!set->p[i])
7026			goto error;
7027	}
7028	ISL_F_CLR(set, ISL_MAP_DISJOINT);
7029	ISL_F_CLR(set, ISL_SET_NORMALIZED);
7030	return set;
7031error:
7032	isl_map_free(map);
7033	return NULL;
7034}
7035
7036/* Return the union of "map1" and "map2", where we assume for now that
7037 * "map1" and "map2" are disjoint.  Note that the basic maps inside
7038 * "map1" or "map2" may not be disjoint from each other.
7039 * Also note that this function is also called from isl_map_union,
7040 * which takes care of handling the situation where "map1" and "map2"
7041 * may not be disjoint.
7042 *
7043 * If one of the inputs is empty, we can simply return the other input.
7044 * Similarly, if one of the inputs is universal, then it is equal to the union.
7045 */
7046static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
7047	__isl_take isl_map *map2)
7048{
7049	int i;
7050	unsigned flags = 0;
7051	struct isl_map *map = NULL;
7052	int is_universe;
7053
7054	if (!map1 || !map2)
7055		goto error;
7056
7057	if (map1->n == 0) {
7058		isl_map_free(map1);
7059		return map2;
7060	}
7061	if (map2->n == 0) {
7062		isl_map_free(map2);
7063		return map1;
7064	}
7065
7066	is_universe = isl_map_plain_is_universe(map1);
7067	if (is_universe < 0)
7068		goto error;
7069	if (is_universe) {
7070		isl_map_free(map2);
7071		return map1;
7072	}
7073
7074	is_universe = isl_map_plain_is_universe(map2);
7075	if (is_universe < 0)
7076		goto error;
7077	if (is_universe) {
7078		isl_map_free(map1);
7079		return map2;
7080	}
7081
7082	isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
7083
7084	if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
7085	    ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
7086		ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7087
7088	map = isl_map_alloc_space(isl_space_copy(map1->dim),
7089				map1->n + map2->n, flags);
7090	if (!map)
7091		goto error;
7092	for (i = 0; i < map1->n; ++i) {
7093		map = isl_map_add_basic_map(map,
7094				  isl_basic_map_copy(map1->p[i]));
7095		if (!map)
7096			goto error;
7097	}
7098	for (i = 0; i < map2->n; ++i) {
7099		map = isl_map_add_basic_map(map,
7100				  isl_basic_map_copy(map2->p[i]));
7101		if (!map)
7102			goto error;
7103	}
7104	isl_map_free(map1);
7105	isl_map_free(map2);
7106	return map;
7107error:
7108	isl_map_free(map);
7109	isl_map_free(map1);
7110	isl_map_free(map2);
7111	return NULL;
7112}
7113
7114__isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
7115	__isl_take isl_map *map2)
7116{
7117	return isl_map_align_params_map_map_and(map1, map2, &map_union_disjoint);
7118}
7119
7120struct isl_map *isl_map_union(struct isl_map *map1, struct isl_map *map2)
7121{
7122	map1 = isl_map_union_disjoint(map1, map2);
7123	if (!map1)
7124		return NULL;
7125	if (map1->n > 1)
7126		ISL_F_CLR(map1, ISL_MAP_DISJOINT);
7127	return map1;
7128}
7129
7130struct isl_set *isl_set_union_disjoint(
7131			struct isl_set *set1, struct isl_set *set2)
7132{
7133	return (struct isl_set *)
7134		isl_map_union_disjoint(
7135			(struct isl_map *)set1, (struct isl_map *)set2);
7136}
7137
7138struct isl_set *isl_set_union(struct isl_set *set1, struct isl_set *set2)
7139{
7140	return (struct isl_set *)
7141		isl_map_union((struct isl_map *)set1, (struct isl_map *)set2);
7142}
7143
7144/* Apply "fn" to pairs of elements from "map" and "set" and collect
7145 * the results.
7146 *
7147 * "map" and "set" are assumed to be compatible and non-NULL.
7148 */
7149static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
7150	__isl_take isl_set *set,
7151	__isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
7152		__isl_take isl_basic_set *bset))
7153{
7154	unsigned flags = 0;
7155	struct isl_map *result;
7156	int i, j;
7157
7158	if (isl_set_plain_is_universe(set)) {
7159		isl_set_free(set);
7160		return map;
7161	}
7162
7163	if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
7164	    ISL_F_ISSET(set, ISL_MAP_DISJOINT))
7165		ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7166
7167	result = isl_map_alloc_space(isl_space_copy(map->dim),
7168					map->n * set->n, flags);
7169	for (i = 0; result && i < map->n; ++i)
7170		for (j = 0; j < set->n; ++j) {
7171			result = isl_map_add_basic_map(result,
7172					fn(isl_basic_map_copy(map->p[i]),
7173					    isl_basic_set_copy(set->p[j])));
7174			if (!result)
7175				break;
7176		}
7177
7178	isl_map_free(map);
7179	isl_set_free(set);
7180	return result;
7181}
7182
7183static __isl_give isl_map *map_intersect_range(__isl_take isl_map *map,
7184	__isl_take isl_set *set)
7185{
7186	if (!map || !set)
7187		goto error;
7188
7189	if (!isl_map_compatible_range(map, set))
7190		isl_die(set->ctx, isl_error_invalid,
7191			"incompatible spaces", goto error);
7192
7193	return map_intersect_set(map, set, &isl_basic_map_intersect_range);
7194error:
7195	isl_map_free(map);
7196	isl_set_free(set);
7197	return NULL;
7198}
7199
7200__isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
7201	__isl_take isl_set *set)
7202{
7203	return isl_map_align_params_map_map_and(map, set, &map_intersect_range);
7204}
7205
7206static __isl_give isl_map *map_intersect_domain(__isl_take isl_map *map,
7207	__isl_take isl_set *set)
7208{
7209	if (!map || !set)
7210		goto error;
7211
7212	if (!isl_map_compatible_domain(map, set))
7213		isl_die(set->ctx, isl_error_invalid,
7214			"incompatible spaces", goto error);
7215
7216	return map_intersect_set(map, set, &isl_basic_map_intersect_domain);
7217error:
7218	isl_map_free(map);
7219	isl_set_free(set);
7220	return NULL;
7221}
7222
7223__isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
7224	__isl_take isl_set *set)
7225{
7226	return isl_map_align_params_map_map_and(map, set,
7227						&map_intersect_domain);
7228}
7229
7230static __isl_give isl_map *map_apply_domain(__isl_take isl_map *map1,
7231	__isl_take isl_map *map2)
7232{
7233	if (!map1 || !map2)
7234		goto error;
7235	map1 = isl_map_reverse(map1);
7236	map1 = isl_map_apply_range(map1, map2);
7237	return isl_map_reverse(map1);
7238error:
7239	isl_map_free(map1);
7240	isl_map_free(map2);
7241	return NULL;
7242}
7243
7244__isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
7245	__isl_take isl_map *map2)
7246{
7247	return isl_map_align_params_map_map_and(map1, map2, &map_apply_domain);
7248}
7249
7250static __isl_give isl_map *map_apply_range(__isl_take isl_map *map1,
7251	__isl_take isl_map *map2)
7252{
7253	isl_space *dim_result;
7254	struct isl_map *result;
7255	int i, j;
7256
7257	if (!map1 || !map2)
7258		goto error;
7259
7260	dim_result = isl_space_join(isl_space_copy(map1->dim),
7261				  isl_space_copy(map2->dim));
7262
7263	result = isl_map_alloc_space(dim_result, map1->n * map2->n, 0);
7264	if (!result)
7265		goto error;
7266	for (i = 0; i < map1->n; ++i)
7267		for (j = 0; j < map2->n; ++j) {
7268			result = isl_map_add_basic_map(result,
7269			    isl_basic_map_apply_range(
7270				isl_basic_map_copy(map1->p[i]),
7271				isl_basic_map_copy(map2->p[j])));
7272			if (!result)
7273				goto error;
7274		}
7275	isl_map_free(map1);
7276	isl_map_free(map2);
7277	if (result && result->n <= 1)
7278		ISL_F_SET(result, ISL_MAP_DISJOINT);
7279	return result;
7280error:
7281	isl_map_free(map1);
7282	isl_map_free(map2);
7283	return NULL;
7284}
7285
7286__isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
7287	__isl_take isl_map *map2)
7288{
7289	return isl_map_align_params_map_map_and(map1, map2, &map_apply_range);
7290}
7291
7292/*
7293 * returns range - domain
7294 */
7295struct isl_basic_set *isl_basic_map_deltas(struct isl_basic_map *bmap)
7296{
7297	isl_space *dims, *target_dim;
7298	struct isl_basic_set *bset;
7299	unsigned dim;
7300	unsigned nparam;
7301	int i;
7302
7303	if (!bmap)
7304		goto error;
7305	isl_assert(bmap->ctx, isl_space_tuple_match(bmap->dim, isl_dim_in,
7306						  bmap->dim, isl_dim_out),
7307		   goto error);
7308	target_dim = isl_space_domain(isl_basic_map_get_space(bmap));
7309	dim = isl_basic_map_n_in(bmap);
7310	nparam = isl_basic_map_n_param(bmap);
7311	bset = isl_basic_set_from_basic_map(bmap);
7312	bset = isl_basic_set_cow(bset);
7313	dims = isl_basic_set_get_space(bset);
7314	dims = isl_space_add_dims(dims, isl_dim_set, dim);
7315	bset = isl_basic_set_extend_space(bset, dims, 0, dim, 0);
7316	bset = isl_basic_set_swap_vars(bset, 2*dim);
7317	for (i = 0; i < dim; ++i) {
7318		int j = isl_basic_map_alloc_equality(
7319					    (struct isl_basic_map *)bset);
7320		if (j < 0) {
7321			bset = isl_basic_set_free(bset);
7322			break;
7323		}
7324		isl_seq_clr(bset->eq[j], 1 + isl_basic_set_total_dim(bset));
7325		isl_int_set_si(bset->eq[j][1+nparam+i], 1);
7326		isl_int_set_si(bset->eq[j][1+nparam+dim+i], 1);
7327		isl_int_set_si(bset->eq[j][1+nparam+2*dim+i], -1);
7328	}
7329	bset = isl_basic_set_project_out(bset, isl_dim_set, dim, 2*dim);
7330	bset = isl_basic_set_reset_space(bset, target_dim);
7331	return bset;
7332error:
7333	isl_basic_map_free(bmap);
7334	return NULL;
7335}
7336
7337/*
7338 * returns range - domain
7339 */
7340__isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)
7341{
7342	int i;
7343	isl_space *dim;
7344	struct isl_set *result;
7345
7346	if (!map)
7347		return NULL;
7348
7349	isl_assert(map->ctx, isl_space_tuple_match(map->dim, isl_dim_in,
7350						 map->dim, isl_dim_out),
7351		   goto error);
7352	dim = isl_map_get_space(map);
7353	dim = isl_space_domain(dim);
7354	result = isl_set_alloc_space(dim, map->n, 0);
7355	if (!result)
7356		goto error;
7357	for (i = 0; i < map->n; ++i)
7358		result = isl_set_add_basic_set(result,
7359			  isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
7360	isl_map_free(map);
7361	return result;
7362error:
7363	isl_map_free(map);
7364	return NULL;
7365}
7366
7367/*
7368 * returns [domain -> range] -> range - domain
7369 */
7370__isl_give isl_basic_map *isl_basic_map_deltas_map(
7371	__isl_take isl_basic_map *bmap)
7372{
7373	int i, k;
7374	isl_space *dim;
7375	isl_basic_map *domain;
7376	int nparam, n;
7377	unsigned total;
7378
7379	if (!isl_space_tuple_match(bmap->dim, isl_dim_in, bmap->dim, isl_dim_out))
7380		isl_die(bmap->ctx, isl_error_invalid,
7381			"domain and range don't match", goto error);
7382
7383	nparam = isl_basic_map_dim(bmap, isl_dim_param);
7384	n = isl_basic_map_dim(bmap, isl_dim_in);
7385
7386	dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap)));
7387	domain = isl_basic_map_universe(dim);
7388
7389	bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
7390	bmap = isl_basic_map_apply_range(bmap, domain);
7391	bmap = isl_basic_map_extend_constraints(bmap, n, 0);
7392
7393	total = isl_basic_map_total_dim(bmap);
7394
7395	for (i = 0; i < n; ++i) {
7396		k = isl_basic_map_alloc_equality(bmap);
7397		if (k < 0)
7398			goto error;
7399		isl_seq_clr(bmap->eq[k], 1 + total);
7400		isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
7401		isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
7402		isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
7403	}
7404
7405	bmap = isl_basic_map_gauss(bmap, NULL);
7406	return isl_basic_map_finalize(bmap);
7407error:
7408	isl_basic_map_free(bmap);
7409	return NULL;
7410}
7411
7412/*
7413 * returns [domain -> range] -> range - domain
7414 */
7415__isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
7416{
7417	int i;
7418	isl_space *domain_dim;
7419
7420	if (!map)
7421		return NULL;
7422
7423	if (!isl_space_tuple_match(map->dim, isl_dim_in, map->dim, isl_dim_out))
7424		isl_die(map->ctx, isl_error_invalid,
7425			"domain and range don't match", goto error);
7426
7427	map = isl_map_cow(map);
7428	if (!map)
7429		return NULL;
7430
7431	domain_dim = isl_space_from_range(isl_space_domain(isl_map_get_space(map)));
7432	map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
7433	map->dim = isl_space_join(map->dim, domain_dim);
7434	if (!map->dim)
7435		goto error;
7436	for (i = 0; i < map->n; ++i) {
7437		map->p[i] = isl_basic_map_deltas_map(map->p[i]);
7438		if (!map->p[i])
7439			goto error;
7440	}
7441	ISL_F_CLR(map, ISL_MAP_NORMALIZED);
7442	return map;
7443error:
7444	isl_map_free(map);
7445	return NULL;
7446}
7447
7448static __isl_give isl_basic_map *basic_map_identity(__isl_take isl_space *dims)
7449{
7450	struct isl_basic_map *bmap;
7451	unsigned nparam;
7452	unsigned dim;
7453	int i;
7454
7455	if (!dims)
7456		return NULL;
7457
7458	nparam = dims->nparam;
7459	dim = dims->n_out;
7460	bmap = isl_basic_map_alloc_space(dims, 0, dim, 0);
7461	if (!bmap)
7462		goto error;
7463
7464	for (i = 0; i < dim; ++i) {
7465		int j = isl_basic_map_alloc_equality(bmap);
7466		if (j < 0)
7467			goto error;
7468		isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap));
7469		isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
7470		isl_int_set_si(bmap->eq[j][1+nparam+dim+i], -1);
7471	}
7472	return isl_basic_map_finalize(bmap);
7473error:
7474	isl_basic_map_free(bmap);
7475	return NULL;
7476}
7477
7478__isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *dim)
7479{
7480	if (!dim)
7481		return NULL;
7482	if (dim->n_in != dim->n_out)
7483		isl_die(dim->ctx, isl_error_invalid,
7484			"number of input and output dimensions needs to be "
7485			"the same", goto error);
7486	return basic_map_identity(dim);
7487error:
7488	isl_space_free(dim);
7489	return NULL;
7490}
7491
7492struct isl_basic_map *isl_basic_map_identity_like(struct isl_basic_map *model)
7493{
7494	if (!model || !model->dim)
7495		return NULL;
7496	return isl_basic_map_identity(isl_space_copy(model->dim));
7497}
7498
7499__isl_give isl_map *isl_map_identity(__isl_take isl_space *dim)
7500{
7501	return isl_map_from_basic_map(isl_basic_map_identity(dim));
7502}
7503
7504struct isl_map *isl_map_identity_like(struct isl_map *model)
7505{
7506	if (!model || !model->dim)
7507		return NULL;
7508	return isl_map_identity(isl_space_copy(model->dim));
7509}
7510
7511struct isl_map *isl_map_identity_like_basic_map(struct isl_basic_map *model)
7512{
7513	if (!model || !model->dim)
7514		return NULL;
7515	return isl_map_identity(isl_space_copy(model->dim));
7516}
7517
7518__isl_give isl_map *isl_set_identity(__isl_take isl_set *set)
7519{
7520	isl_space *dim = isl_set_get_space(set);
7521	isl_map *id;
7522	id = isl_map_identity(isl_space_map_from_set(dim));
7523	return isl_map_intersect_range(id, set);
7524}
7525
7526/* Construct a basic set with all set dimensions having only non-negative
7527 * values.
7528 */
7529__isl_give isl_basic_set *isl_basic_set_positive_orthant(
7530	__isl_take isl_space *space)
7531{
7532	int i;
7533	unsigned nparam;
7534	unsigned dim;
7535	struct isl_basic_set *bset;
7536
7537	if (!space)
7538		return NULL;
7539	nparam = space->nparam;
7540	dim = space->n_out;
7541	bset = isl_basic_set_alloc_space(space, 0, 0, dim);
7542	if (!bset)
7543		return NULL;
7544	for (i = 0; i < dim; ++i) {
7545		int k = isl_basic_set_alloc_inequality(bset);
7546		if (k < 0)
7547			goto error;
7548		isl_seq_clr(bset->ineq[k], 1 + isl_basic_set_total_dim(bset));
7549		isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
7550	}
7551	return bset;
7552error:
7553	isl_basic_set_free(bset);
7554	return NULL;
7555}
7556
7557/* Construct the half-space x_pos >= 0.
7558 */
7559static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *dim,
7560	int pos)
7561{
7562	int k;
7563	isl_basic_set *nonneg;
7564
7565	nonneg = isl_basic_set_alloc_space(dim, 0, 0, 1);
7566	k = isl_basic_set_alloc_inequality(nonneg);
7567	if (k < 0)
7568		goto error;
7569	isl_seq_clr(nonneg->ineq[k], 1 + isl_basic_set_total_dim(nonneg));
7570	isl_int_set_si(nonneg->ineq[k][pos], 1);
7571
7572	return isl_basic_set_finalize(nonneg);
7573error:
7574	isl_basic_set_free(nonneg);
7575	return NULL;
7576}
7577
7578/* Construct the half-space x_pos <= -1.
7579 */
7580static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *dim, int pos)
7581{
7582	int k;
7583	isl_basic_set *neg;
7584
7585	neg = isl_basic_set_alloc_space(dim, 0, 0, 1);
7586	k = isl_basic_set_alloc_inequality(neg);
7587	if (k < 0)
7588		goto error;
7589	isl_seq_clr(neg->ineq[k], 1 + isl_basic_set_total_dim(neg));
7590	isl_int_set_si(neg->ineq[k][0], -1);
7591	isl_int_set_si(neg->ineq[k][pos], -1);
7592
7593	return isl_basic_set_finalize(neg);
7594error:
7595	isl_basic_set_free(neg);
7596	return NULL;
7597}
7598
7599__isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
7600	enum isl_dim_type type, unsigned first, unsigned n)
7601{
7602	int i;
7603	isl_basic_set *nonneg;
7604	isl_basic_set *neg;
7605
7606	if (!set)
7607		return NULL;
7608	if (n == 0)
7609		return set;
7610
7611	isl_assert(set->ctx, first + n <= isl_set_dim(set, type), goto error);
7612
7613	for (i = 0; i < n; ++i) {
7614		nonneg = nonneg_halfspace(isl_set_get_space(set),
7615					  pos(set->dim, type) + first + i);
7616		neg = neg_halfspace(isl_set_get_space(set),
7617					  pos(set->dim, type) + first + i);
7618
7619		set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
7620	}
7621
7622	return set;
7623error:
7624	isl_set_free(set);
7625	return NULL;
7626}
7627
7628static int foreach_orthant(__isl_take isl_set *set, int *signs, int first,
7629	int len, int (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
7630	void *user)
7631{
7632	isl_set *half;
7633
7634	if (!set)
7635		return -1;
7636	if (isl_set_plain_is_empty(set)) {
7637		isl_set_free(set);
7638		return 0;
7639	}
7640	if (first == len)
7641		return fn(set, signs, user);
7642
7643	signs[first] = 1;
7644	half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),
7645							1 + first));
7646	half = isl_set_intersect(half, isl_set_copy(set));
7647	if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)
7648		goto error;
7649
7650	signs[first] = -1;
7651	half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),
7652							1 + first));
7653	half = isl_set_intersect(half, set);
7654	return foreach_orthant(half, signs, first + 1, len, fn, user);
7655error:
7656	isl_set_free(set);
7657	return -1;
7658}
7659
7660/* Call "fn" on the intersections of "set" with each of the orthants
7661 * (except for obviously empty intersections).  The orthant is identified
7662 * by the signs array, with each entry having value 1 or -1 according
7663 * to the sign of the corresponding variable.
7664 */
7665int isl_set_foreach_orthant(__isl_keep isl_set *set,
7666	int (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
7667	void *user)
7668{
7669	unsigned nparam;
7670	unsigned nvar;
7671	int *signs;
7672	int r;
7673
7674	if (!set)
7675		return -1;
7676	if (isl_set_plain_is_empty(set))
7677		return 0;
7678
7679	nparam = isl_set_dim(set, isl_dim_param);
7680	nvar = isl_set_dim(set, isl_dim_set);
7681
7682	signs = isl_alloc_array(set->ctx, int, nparam + nvar);
7683
7684	r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,
7685			    fn, user);
7686
7687	free(signs);
7688
7689	return r;
7690}
7691
7692int isl_set_is_equal(struct isl_set *set1, struct isl_set *set2)
7693{
7694	return isl_map_is_equal((struct isl_map *)set1, (struct isl_map *)set2);
7695}
7696
7697int isl_basic_map_is_subset(
7698		struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
7699{
7700	int is_subset;
7701	struct isl_map *map1;
7702	struct isl_map *map2;
7703
7704	if (!bmap1 || !bmap2)
7705		return -1;
7706
7707	map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
7708	map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
7709
7710	is_subset = isl_map_is_subset(map1, map2);
7711
7712	isl_map_free(map1);
7713	isl_map_free(map2);
7714
7715	return is_subset;
7716}
7717
7718int isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
7719	__isl_keep isl_basic_set *bset2)
7720{
7721	return isl_basic_map_is_subset(bset1, bset2);
7722}
7723
7724int isl_basic_map_is_equal(
7725		struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
7726{
7727	int is_subset;
7728
7729	if (!bmap1 || !bmap2)
7730		return -1;
7731	is_subset = isl_basic_map_is_subset(bmap1, bmap2);
7732	if (is_subset != 1)
7733		return is_subset;
7734	is_subset = isl_basic_map_is_subset(bmap2, bmap1);
7735	return is_subset;
7736}
7737
7738int isl_basic_set_is_equal(
7739		struct isl_basic_set *bset1, struct isl_basic_set *bset2)
7740{
7741	return isl_basic_map_is_equal(
7742		(struct isl_basic_map *)bset1, (struct isl_basic_map *)bset2);
7743}
7744
7745int isl_map_is_empty(struct isl_map *map)
7746{
7747	int i;
7748	int is_empty;
7749
7750	if (!map)
7751		return -1;
7752	for (i = 0; i < map->n; ++i) {
7753		is_empty = isl_basic_map_is_empty(map->p[i]);
7754		if (is_empty < 0)
7755			return -1;
7756		if (!is_empty)
7757			return 0;
7758	}
7759	return 1;
7760}
7761
7762int isl_map_plain_is_empty(__isl_keep isl_map *map)
7763{
7764	return map ? map->n == 0 : -1;
7765}
7766
7767int isl_map_fast_is_empty(__isl_keep isl_map *map)
7768{
7769	return isl_map_plain_is_empty(map);
7770}
7771
7772int isl_set_plain_is_empty(struct isl_set *set)
7773{
7774	return set ? set->n == 0 : -1;
7775}
7776
7777int isl_set_fast_is_empty(__isl_keep isl_set *set)
7778{
7779	return isl_set_plain_is_empty(set);
7780}
7781
7782int isl_set_is_empty(struct isl_set *set)
7783{
7784	return isl_map_is_empty((struct isl_map *)set);
7785}
7786
7787int isl_map_has_equal_space(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
7788{
7789	if (!map1 || !map2)
7790		return -1;
7791
7792	return isl_space_is_equal(map1->dim, map2->dim);
7793}
7794
7795int isl_set_has_equal_space(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
7796{
7797	if (!set1 || !set2)
7798		return -1;
7799
7800	return isl_space_is_equal(set1->dim, set2->dim);
7801}
7802
7803static int map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
7804{
7805	int is_subset;
7806
7807	if (!map1 || !map2)
7808		return -1;
7809	is_subset = isl_map_is_subset(map1, map2);
7810	if (is_subset != 1)
7811		return is_subset;
7812	is_subset = isl_map_is_subset(map2, map1);
7813	return is_subset;
7814}
7815
7816int isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
7817{
7818	return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
7819}
7820
7821int isl_basic_map_is_strict_subset(
7822		struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
7823{
7824	int is_subset;
7825
7826	if (!bmap1 || !bmap2)
7827		return -1;
7828	is_subset = isl_basic_map_is_subset(bmap1, bmap2);
7829	if (is_subset != 1)
7830		return is_subset;
7831	is_subset = isl_basic_map_is_subset(bmap2, bmap1);
7832	if (is_subset == -1)
7833		return is_subset;
7834	return !is_subset;
7835}
7836
7837int isl_map_is_strict_subset(struct isl_map *map1, struct isl_map *map2)
7838{
7839	int is_subset;
7840
7841	if (!map1 || !map2)
7842		return -1;
7843	is_subset = isl_map_is_subset(map1, map2);
7844	if (is_subset != 1)
7845		return is_subset;
7846	is_subset = isl_map_is_subset(map2, map1);
7847	if (is_subset == -1)
7848		return is_subset;
7849	return !is_subset;
7850}
7851
7852int isl_set_is_strict_subset(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
7853{
7854	return isl_map_is_strict_subset((isl_map *)set1, (isl_map *)set2);
7855}
7856
7857int isl_basic_map_is_universe(struct isl_basic_map *bmap)
7858{
7859	if (!bmap)
7860		return -1;
7861	return bmap->n_eq == 0 && bmap->n_ineq == 0;
7862}
7863
7864int isl_basic_set_is_universe(struct isl_basic_set *bset)
7865{
7866	if (!bset)
7867		return -1;
7868	return bset->n_eq == 0 && bset->n_ineq == 0;
7869}
7870
7871int isl_map_plain_is_universe(__isl_keep isl_map *map)
7872{
7873	int i;
7874
7875	if (!map)
7876		return -1;
7877
7878	for (i = 0; i < map->n; ++i) {
7879		int r = isl_basic_map_is_universe(map->p[i]);
7880		if (r < 0 || r)
7881			return r;
7882	}
7883
7884	return 0;
7885}
7886
7887int isl_set_plain_is_universe(__isl_keep isl_set *set)
7888{
7889	return isl_map_plain_is_universe((isl_map *) set);
7890}
7891
7892int isl_set_fast_is_universe(__isl_keep isl_set *set)
7893{
7894	return isl_set_plain_is_universe(set);
7895}
7896
7897int isl_basic_map_is_empty(struct isl_basic_map *bmap)
7898{
7899	struct isl_basic_set *bset = NULL;
7900	struct isl_vec *sample = NULL;
7901	int empty;
7902	unsigned total;
7903
7904	if (!bmap)
7905		return -1;
7906
7907	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
7908		return 1;
7909
7910	if (isl_basic_map_is_universe(bmap))
7911		return 0;
7912
7913	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
7914		struct isl_basic_map *copy = isl_basic_map_copy(bmap);
7915		copy = isl_basic_map_remove_redundancies(copy);
7916		empty = isl_basic_map_plain_is_empty(copy);
7917		isl_basic_map_free(copy);
7918		return empty;
7919	}
7920
7921	total = 1 + isl_basic_map_total_dim(bmap);
7922	if (bmap->sample && bmap->sample->size == total) {
7923		int contains = isl_basic_map_contains(bmap, bmap->sample);
7924		if (contains < 0)
7925			return -1;
7926		if (contains)
7927			return 0;
7928	}
7929	isl_vec_free(bmap->sample);
7930	bmap->sample = NULL;
7931	bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
7932	if (!bset)
7933		return -1;
7934	sample = isl_basic_set_sample_vec(bset);
7935	if (!sample)
7936		return -1;
7937	empty = sample->size == 0;
7938	isl_vec_free(bmap->sample);
7939	bmap->sample = sample;
7940	if (empty)
7941		ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
7942
7943	return empty;
7944}
7945
7946int isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)
7947{
7948	if (!bmap)
7949		return -1;
7950	return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);
7951}
7952
7953int isl_basic_map_fast_is_empty(__isl_keep isl_basic_map *bmap)
7954{
7955	return isl_basic_map_plain_is_empty(bmap);
7956}
7957
7958int isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
7959{
7960	if (!bset)
7961		return -1;
7962	return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);
7963}
7964
7965int isl_basic_set_fast_is_empty(__isl_keep isl_basic_set *bset)
7966{
7967	return isl_basic_set_plain_is_empty(bset);
7968}
7969
7970int isl_basic_set_is_empty(struct isl_basic_set *bset)
7971{
7972	return isl_basic_map_is_empty((struct isl_basic_map *)bset);
7973}
7974
7975struct isl_map *isl_basic_map_union(
7976	struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
7977{
7978	struct isl_map *map;
7979	if (!bmap1 || !bmap2)
7980		goto error;
7981
7982	isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
7983
7984	map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
7985	if (!map)
7986		goto error;
7987	map = isl_map_add_basic_map(map, bmap1);
7988	map = isl_map_add_basic_map(map, bmap2);
7989	return map;
7990error:
7991	isl_basic_map_free(bmap1);
7992	isl_basic_map_free(bmap2);
7993	return NULL;
7994}
7995
7996struct isl_set *isl_basic_set_union(
7997		struct isl_basic_set *bset1, struct isl_basic_set *bset2)
7998{
7999	return (struct isl_set *)isl_basic_map_union(
8000					    (struct isl_basic_map *)bset1,
8001					    (struct isl_basic_map *)bset2);
8002}
8003
8004/* Order divs such that any div only depends on previous divs */
8005struct isl_basic_map *isl_basic_map_order_divs(struct isl_basic_map *bmap)
8006{
8007	int i;
8008	unsigned off;
8009
8010	if (!bmap)
8011		return NULL;
8012
8013	off = isl_space_dim(bmap->dim, isl_dim_all);
8014
8015	for (i = 0; i < bmap->n_div; ++i) {
8016		int pos;
8017		if (isl_int_is_zero(bmap->div[i][0]))
8018			continue;
8019		pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
8020							    bmap->n_div-i);
8021		if (pos == -1)
8022			continue;
8023		isl_basic_map_swap_div(bmap, i, i + pos);
8024		--i;
8025	}
8026	return bmap;
8027}
8028
8029struct isl_basic_set *isl_basic_set_order_divs(struct isl_basic_set *bset)
8030{
8031	return (struct isl_basic_set *)
8032		isl_basic_map_order_divs((struct isl_basic_map *)bset);
8033}
8034
8035__isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)
8036{
8037	int i;
8038
8039	if (!map)
8040		return 0;
8041
8042	for (i = 0; i < map->n; ++i) {
8043		map->p[i] = isl_basic_map_order_divs(map->p[i]);
8044		if (!map->p[i])
8045			goto error;
8046	}
8047
8048	return map;
8049error:
8050	isl_map_free(map);
8051	return NULL;
8052}
8053
8054/* Apply the expansion computed by isl_merge_divs.
8055 * The expansion itself is given by "exp" while the resulting
8056 * list of divs is given by "div".
8057 */
8058__isl_give isl_basic_set *isl_basic_set_expand_divs(
8059	__isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)
8060{
8061	int i, j;
8062	int n_div;
8063
8064	bset = isl_basic_set_cow(bset);
8065	if (!bset || !div)
8066		goto error;
8067
8068	if (div->n_row < bset->n_div)
8069		isl_die(isl_mat_get_ctx(div), isl_error_invalid,
8070			"not an expansion", goto error);
8071
8072	n_div = bset->n_div;
8073	bset = isl_basic_map_extend_space(bset, isl_space_copy(bset->dim),
8074					    div->n_row - n_div, 0,
8075					    2 * (div->n_row - n_div));
8076
8077	for (i = n_div; i < div->n_row; ++i)
8078		if (isl_basic_set_alloc_div(bset) < 0)
8079			goto error;
8080
8081	j = n_div - 1;
8082	for (i = div->n_row - 1; i >= 0; --i) {
8083		if (j >= 0 && exp[j] == i) {
8084			if (i != j)
8085				isl_basic_map_swap_div(bset, i, j);
8086			j--;
8087		} else {
8088			isl_seq_cpy(bset->div[i], div->row[i], div->n_col);
8089			if (isl_basic_map_add_div_constraints(bset, i) < 0)
8090				goto error;
8091		}
8092	}
8093
8094	isl_mat_free(div);
8095	return bset;
8096error:
8097	isl_basic_set_free(bset);
8098	isl_mat_free(div);
8099	return NULL;
8100}
8101
8102/* Look for a div in dst that corresponds to the div "div" in src.
8103 * The divs before "div" in src and dst are assumed to be the same.
8104 *
8105 * Returns -1 if no corresponding div was found and the position
8106 * of the corresponding div in dst otherwise.
8107 */
8108static int find_div(struct isl_basic_map *dst,
8109			struct isl_basic_map *src, unsigned div)
8110{
8111	int i;
8112
8113	unsigned total = isl_space_dim(src->dim, isl_dim_all);
8114
8115	isl_assert(dst->ctx, div <= dst->n_div, return -1);
8116	for (i = div; i < dst->n_div; ++i)
8117		if (isl_seq_eq(dst->div[i], src->div[div], 1+1+total+div) &&
8118		    isl_seq_first_non_zero(dst->div[i]+1+1+total+div,
8119						dst->n_div - div) == -1)
8120			return i;
8121	return -1;
8122}
8123
8124struct isl_basic_map *isl_basic_map_align_divs(
8125		struct isl_basic_map *dst, struct isl_basic_map *src)
8126{
8127	int i;
8128	unsigned total;
8129
8130	if (!dst || !src)
8131		goto error;
8132
8133	if (src->n_div == 0)
8134		return dst;
8135
8136	for (i = 0; i < src->n_div; ++i)
8137		isl_assert(src->ctx, !isl_int_is_zero(src->div[i][0]), goto error);
8138
8139	src = isl_basic_map_order_divs(src);
8140	dst = isl_basic_map_cow(dst);
8141	if (!dst)
8142		return NULL;
8143	dst = isl_basic_map_extend_space(dst, isl_space_copy(dst->dim),
8144			src->n_div, 0, 2 * src->n_div);
8145	if (!dst)
8146		return NULL;
8147	total = isl_space_dim(src->dim, isl_dim_all);
8148	for (i = 0; i < src->n_div; ++i) {
8149		int j = find_div(dst, src, i);
8150		if (j < 0) {
8151			j = isl_basic_map_alloc_div(dst);
8152			if (j < 0)
8153				goto error;
8154			isl_seq_cpy(dst->div[j], src->div[i], 1+1+total+i);
8155			isl_seq_clr(dst->div[j]+1+1+total+i, dst->n_div - i);
8156			if (isl_basic_map_add_div_constraints(dst, j) < 0)
8157				goto error;
8158		}
8159		if (j != i)
8160			isl_basic_map_swap_div(dst, i, j);
8161	}
8162	return dst;
8163error:
8164	isl_basic_map_free(dst);
8165	return NULL;
8166}
8167
8168struct isl_basic_set *isl_basic_set_align_divs(
8169		struct isl_basic_set *dst, struct isl_basic_set *src)
8170{
8171	return (struct isl_basic_set *)isl_basic_map_align_divs(
8172		(struct isl_basic_map *)dst, (struct isl_basic_map *)src);
8173}
8174
8175struct isl_map *isl_map_align_divs(struct isl_map *map)
8176{
8177	int i;
8178
8179	if (!map)
8180		return NULL;
8181	if (map->n == 0)
8182		return map;
8183	map = isl_map_compute_divs(map);
8184	map = isl_map_cow(map);
8185	if (!map)
8186		return NULL;
8187
8188	for (i = 1; i < map->n; ++i)
8189		map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
8190	for (i = 1; i < map->n; ++i) {
8191		map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
8192		if (!map->p[i])
8193			return isl_map_free(map);
8194	}
8195
8196	ISL_F_CLR(map, ISL_MAP_NORMALIZED);
8197	return map;
8198}
8199
8200struct isl_set *isl_set_align_divs(struct isl_set *set)
8201{
8202	return (struct isl_set *)isl_map_align_divs((struct isl_map *)set);
8203}
8204
8205static __isl_give isl_set *set_apply( __isl_take isl_set *set,
8206	__isl_take isl_map *map)
8207{
8208	if (!set || !map)
8209		goto error;
8210	isl_assert(set->ctx, isl_map_compatible_domain(map, set), goto error);
8211	map = isl_map_intersect_domain(map, set);
8212	set = isl_map_range(map);
8213	return set;
8214error:
8215	isl_set_free(set);
8216	isl_map_free(map);
8217	return NULL;
8218}
8219
8220__isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
8221	__isl_take isl_map *map)
8222{
8223	return isl_map_align_params_map_map_and(set, map, &set_apply);
8224}
8225
8226/* There is no need to cow as removing empty parts doesn't change
8227 * the meaning of the set.
8228 */
8229struct isl_map *isl_map_remove_empty_parts(struct isl_map *map)
8230{
8231	int i;
8232
8233	if (!map)
8234		return NULL;
8235
8236	for (i = map->n - 1; i >= 0; --i)
8237		remove_if_empty(map, i);
8238
8239	return map;
8240}
8241
8242struct isl_set *isl_set_remove_empty_parts(struct isl_set *set)
8243{
8244	return (struct isl_set *)
8245		isl_map_remove_empty_parts((struct isl_map *)set);
8246}
8247
8248struct isl_basic_map *isl_map_copy_basic_map(struct isl_map *map)
8249{
8250	struct isl_basic_map *bmap;
8251	if (!map || map->n == 0)
8252		return NULL;
8253	bmap = map->p[map->n-1];
8254	isl_assert(map->ctx, ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL), return NULL);
8255	return isl_basic_map_copy(bmap);
8256}
8257
8258struct isl_basic_set *isl_set_copy_basic_set(struct isl_set *set)
8259{
8260	return (struct isl_basic_set *)
8261		isl_map_copy_basic_map((struct isl_map *)set);
8262}
8263
8264__isl_give isl_map *isl_map_drop_basic_map(__isl_take isl_map *map,
8265						__isl_keep isl_basic_map *bmap)
8266{
8267	int i;
8268
8269	if (!map || !bmap)
8270		goto error;
8271	for (i = map->n-1; i >= 0; --i) {
8272		if (map->p[i] != bmap)
8273			continue;
8274		map = isl_map_cow(map);
8275		if (!map)
8276			goto error;
8277		isl_basic_map_free(map->p[i]);
8278		if (i != map->n-1) {
8279			ISL_F_CLR(map, ISL_SET_NORMALIZED);
8280			map->p[i] = map->p[map->n-1];
8281		}
8282		map->n--;
8283		return map;
8284	}
8285	return map;
8286error:
8287	isl_map_free(map);
8288	return NULL;
8289}
8290
8291struct isl_set *isl_set_drop_basic_set(struct isl_set *set,
8292						struct isl_basic_set *bset)
8293{
8294	return (struct isl_set *)isl_map_drop_basic_map((struct isl_map *)set,
8295						(struct isl_basic_map *)bset);
8296}
8297
8298/* Given two basic sets bset1 and bset2, compute the maximal difference
8299 * between the values of dimension pos in bset1 and those in bset2
8300 * for any common value of the parameters and dimensions preceding pos.
8301 */
8302static enum isl_lp_result basic_set_maximal_difference_at(
8303	__isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
8304	int pos, isl_int *opt)
8305{
8306	isl_space *dims;
8307	struct isl_basic_map *bmap1 = NULL;
8308	struct isl_basic_map *bmap2 = NULL;
8309	struct isl_ctx *ctx;
8310	struct isl_vec *obj;
8311	unsigned total;
8312	unsigned nparam;
8313	unsigned dim1, dim2;
8314	enum isl_lp_result res;
8315
8316	if (!bset1 || !bset2)
8317		return isl_lp_error;
8318
8319	nparam = isl_basic_set_n_param(bset1);
8320	dim1 = isl_basic_set_n_dim(bset1);
8321	dim2 = isl_basic_set_n_dim(bset2);
8322	dims = isl_space_alloc(bset1->ctx, nparam, pos, dim1 - pos);
8323	bmap1 = isl_basic_map_from_basic_set(isl_basic_set_copy(bset1), dims);
8324	dims = isl_space_alloc(bset2->ctx, nparam, pos, dim2 - pos);
8325	bmap2 = isl_basic_map_from_basic_set(isl_basic_set_copy(bset2), dims);
8326	if (!bmap1 || !bmap2)
8327		goto error;
8328	bmap1 = isl_basic_map_cow(bmap1);
8329	bmap1 = isl_basic_map_extend(bmap1, nparam,
8330			pos, (dim1 - pos) + (dim2 - pos),
8331			bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
8332	bmap1 = add_constraints(bmap1, bmap2, 0, dim1 - pos);
8333	if (!bmap1)
8334		goto error;
8335	total = isl_basic_map_total_dim(bmap1);
8336	ctx = bmap1->ctx;
8337	obj = isl_vec_alloc(ctx, 1 + total);
8338	if (!obj)
8339		goto error2;
8340	isl_seq_clr(obj->block.data, 1 + total);
8341	isl_int_set_si(obj->block.data[1+nparam+pos], 1);
8342	isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);
8343	res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,
8344					opt, NULL, NULL);
8345	isl_basic_map_free(bmap1);
8346	isl_vec_free(obj);
8347	return res;
8348error:
8349	isl_basic_map_free(bmap2);
8350error2:
8351	isl_basic_map_free(bmap1);
8352	return isl_lp_error;
8353}
8354
8355/* Given two _disjoint_ basic sets bset1 and bset2, check whether
8356 * for any common value of the parameters and dimensions preceding pos
8357 * in both basic sets, the values of dimension pos in bset1 are
8358 * smaller or larger than those in bset2.
8359 *
8360 * Returns
8361 *	 1 if bset1 follows bset2
8362 *	-1 if bset1 precedes bset2
8363 *	 0 if bset1 and bset2 are incomparable
8364 *	-2 if some error occurred.
8365 */
8366int isl_basic_set_compare_at(struct isl_basic_set *bset1,
8367	struct isl_basic_set *bset2, int pos)
8368{
8369	isl_int opt;
8370	enum isl_lp_result res;
8371	int cmp;
8372
8373	isl_int_init(opt);
8374
8375	res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
8376
8377	if (res == isl_lp_empty)
8378		cmp = 0;
8379	else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
8380		  res == isl_lp_unbounded)
8381		cmp = 1;
8382	else if (res == isl_lp_ok && isl_int_is_neg(opt))
8383		cmp = -1;
8384	else
8385		cmp = -2;
8386
8387	isl_int_clear(opt);
8388	return cmp;
8389}
8390
8391/* Given two basic sets bset1 and bset2, check whether
8392 * for any common value of the parameters and dimensions preceding pos
8393 * there is a value of dimension pos in bset1 that is larger
8394 * than a value of the same dimension in bset2.
8395 *
8396 * Return
8397 *	 1 if there exists such a pair
8398 *	 0 if there is no such pair, but there is a pair of equal values
8399 *	-1 otherwise
8400 *	-2 if some error occurred.
8401 */
8402int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
8403	__isl_keep isl_basic_set *bset2, int pos)
8404{
8405	isl_int opt;
8406	enum isl_lp_result res;
8407	int cmp;
8408
8409	isl_int_init(opt);
8410
8411	res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
8412
8413	if (res == isl_lp_empty)
8414		cmp = -1;
8415	else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
8416		  res == isl_lp_unbounded)
8417		cmp = 1;
8418	else if (res == isl_lp_ok && isl_int_is_neg(opt))
8419		cmp = -1;
8420	else if (res == isl_lp_ok)
8421		cmp = 0;
8422	else
8423		cmp = -2;
8424
8425	isl_int_clear(opt);
8426	return cmp;
8427}
8428
8429/* Given two sets set1 and set2, check whether
8430 * for any common value of the parameters and dimensions preceding pos
8431 * there is a value of dimension pos in set1 that is larger
8432 * than a value of the same dimension in set2.
8433 *
8434 * Return
8435 *	 1 if there exists such a pair
8436 *	 0 if there is no such pair, but there is a pair of equal values
8437 *	-1 otherwise
8438 *	-2 if some error occurred.
8439 */
8440int isl_set_follows_at(__isl_keep isl_set *set1,
8441	__isl_keep isl_set *set2, int pos)
8442{
8443	int i, j;
8444	int follows = -1;
8445
8446	if (!set1 || !set2)
8447		return -2;
8448
8449	for (i = 0; i < set1->n; ++i)
8450		for (j = 0; j < set2->n; ++j) {
8451			int f;
8452			f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);
8453			if (f == 1 || f == -2)
8454				return f;
8455			if (f > follows)
8456				follows = f;
8457		}
8458
8459	return follows;
8460}
8461
8462static int isl_basic_map_plain_has_fixed_var(__isl_keep isl_basic_map *bmap,
8463	unsigned pos, isl_int *val)
8464{
8465	int i;
8466	int d;
8467	unsigned total;
8468
8469	if (!bmap)
8470		return -1;
8471	total = isl_basic_map_total_dim(bmap);
8472	for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
8473		for (; d+1 > pos; --d)
8474			if (!isl_int_is_zero(bmap->eq[i][1+d]))
8475				break;
8476		if (d != pos)
8477			continue;
8478		if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
8479			return 0;
8480		if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
8481			return 0;
8482		if (!isl_int_is_one(bmap->eq[i][1+d]))
8483			return 0;
8484		if (val)
8485			isl_int_neg(*val, bmap->eq[i][0]);
8486		return 1;
8487	}
8488	return 0;
8489}
8490
8491static int isl_map_plain_has_fixed_var(__isl_keep isl_map *map,
8492	unsigned pos, isl_int *val)
8493{
8494	int i;
8495	isl_int v;
8496	isl_int tmp;
8497	int fixed;
8498
8499	if (!map)
8500		return -1;
8501	if (map->n == 0)
8502		return 0;
8503	if (map->n == 1)
8504		return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val);
8505	isl_int_init(v);
8506	isl_int_init(tmp);
8507	fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v);
8508	for (i = 1; fixed == 1 && i < map->n; ++i) {
8509		fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp);
8510		if (fixed == 1 && isl_int_ne(tmp, v))
8511			fixed = 0;
8512	}
8513	if (val)
8514		isl_int_set(*val, v);
8515	isl_int_clear(tmp);
8516	isl_int_clear(v);
8517	return fixed;
8518}
8519
8520static int isl_basic_set_plain_has_fixed_var(__isl_keep isl_basic_set *bset,
8521	unsigned pos, isl_int *val)
8522{
8523	return isl_basic_map_plain_has_fixed_var((struct isl_basic_map *)bset,
8524						pos, val);
8525}
8526
8527static int isl_set_plain_has_fixed_var(__isl_keep isl_set *set, unsigned pos,
8528	isl_int *val)
8529{
8530	return isl_map_plain_has_fixed_var((struct isl_map *)set, pos, val);
8531}
8532
8533int isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
8534	enum isl_dim_type type, unsigned pos, isl_int *val)
8535{
8536	if (pos >= isl_basic_map_dim(bmap, type))
8537		return -1;
8538	return isl_basic_map_plain_has_fixed_var(bmap,
8539		isl_basic_map_offset(bmap, type) - 1 + pos, val);
8540}
8541
8542/* If "bmap" obviously lies on a hyperplane where the given dimension
8543 * has a fixed value, then return that value.
8544 * Otherwise return NaN.
8545 */
8546__isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
8547	__isl_keep isl_basic_map *bmap,
8548	enum isl_dim_type type, unsigned pos)
8549{
8550	isl_ctx *ctx;
8551	isl_val *v;
8552	int fixed;
8553
8554	if (!bmap)
8555		return NULL;
8556	ctx = isl_basic_map_get_ctx(bmap);
8557	v = isl_val_alloc(ctx);
8558	if (!v)
8559		return NULL;
8560	fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);
8561	if (fixed < 0)
8562		return isl_val_free(v);
8563	if (fixed) {
8564		isl_int_set_si(v->d, 1);
8565		return v;
8566	}
8567	isl_val_free(v);
8568	return isl_val_nan(ctx);
8569}
8570
8571int isl_map_plain_is_fixed(__isl_keep isl_map *map,
8572	enum isl_dim_type type, unsigned pos, isl_int *val)
8573{
8574	if (pos >= isl_map_dim(map, type))
8575		return -1;
8576	return isl_map_plain_has_fixed_var(map,
8577		map_offset(map, type) - 1 + pos, val);
8578}
8579
8580/* If "map" obviously lies on a hyperplane where the given dimension
8581 * has a fixed value, then return that value.
8582 * Otherwise return NaN.
8583 */
8584__isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
8585	enum isl_dim_type type, unsigned pos)
8586{
8587	isl_ctx *ctx;
8588	isl_val *v;
8589	int fixed;
8590
8591	if (!map)
8592		return NULL;
8593	ctx = isl_map_get_ctx(map);
8594	v = isl_val_alloc(ctx);
8595	if (!v)
8596		return NULL;
8597	fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);
8598	if (fixed < 0)
8599		return isl_val_free(v);
8600	if (fixed) {
8601		isl_int_set_si(v->d, 1);
8602		return v;
8603	}
8604	isl_val_free(v);
8605	return isl_val_nan(ctx);
8606}
8607
8608/* If "set" obviously lies on a hyperplane where the given dimension
8609 * has a fixed value, then return that value.
8610 * Otherwise return NaN.
8611 */
8612__isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
8613	enum isl_dim_type type, unsigned pos)
8614{
8615	return isl_map_plain_get_val_if_fixed(set, type, pos);
8616}
8617
8618int isl_set_plain_is_fixed(__isl_keep isl_set *set,
8619	enum isl_dim_type type, unsigned pos, isl_int *val)
8620{
8621	return isl_map_plain_is_fixed(set, type, pos, val);
8622}
8623
8624int isl_map_fast_is_fixed(__isl_keep isl_map *map,
8625	enum isl_dim_type type, unsigned pos, isl_int *val)
8626{
8627	return isl_map_plain_is_fixed(map, type, pos, val);
8628}
8629
8630/* Check if dimension dim has fixed value and if so and if val is not NULL,
8631 * then return this fixed value in *val.
8632 */
8633int isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
8634	unsigned dim, isl_int *val)
8635{
8636	return isl_basic_set_plain_has_fixed_var(bset,
8637					isl_basic_set_n_param(bset) + dim, val);
8638}
8639
8640/* Check if dimension dim has fixed value and if so and if val is not NULL,
8641 * then return this fixed value in *val.
8642 */
8643int isl_set_plain_dim_is_fixed(__isl_keep isl_set *set,
8644	unsigned dim, isl_int *val)
8645{
8646	return isl_set_plain_has_fixed_var(set, isl_set_n_param(set) + dim, val);
8647}
8648
8649int isl_set_fast_dim_is_fixed(__isl_keep isl_set *set,
8650	unsigned dim, isl_int *val)
8651{
8652	return isl_set_plain_dim_is_fixed(set, dim, val);
8653}
8654
8655/* Check if input variable in has fixed value and if so and if val is not NULL,
8656 * then return this fixed value in *val.
8657 */
8658int isl_map_plain_input_is_fixed(__isl_keep isl_map *map,
8659	unsigned in, isl_int *val)
8660{
8661	return isl_map_plain_has_fixed_var(map, isl_map_n_param(map) + in, val);
8662}
8663
8664/* Check if dimension dim has an (obvious) fixed lower bound and if so
8665 * and if val is not NULL, then return this lower bound in *val.
8666 */
8667int isl_basic_set_plain_dim_has_fixed_lower_bound(
8668	__isl_keep isl_basic_set *bset, unsigned dim, isl_int *val)
8669{
8670	int i, i_eq = -1, i_ineq = -1;
8671	isl_int *c;
8672	unsigned total;
8673	unsigned nparam;
8674
8675	if (!bset)
8676		return -1;
8677	total = isl_basic_set_total_dim(bset);
8678	nparam = isl_basic_set_n_param(bset);
8679	for (i = 0; i < bset->n_eq; ++i) {
8680		if (isl_int_is_zero(bset->eq[i][1+nparam+dim]))
8681			continue;
8682		if (i_eq != -1)
8683			return 0;
8684		i_eq = i;
8685	}
8686	for (i = 0; i < bset->n_ineq; ++i) {
8687		if (!isl_int_is_pos(bset->ineq[i][1+nparam+dim]))
8688			continue;
8689		if (i_eq != -1 || i_ineq != -1)
8690			return 0;
8691		i_ineq = i;
8692	}
8693	if (i_eq == -1 && i_ineq == -1)
8694		return 0;
8695	c = i_eq != -1 ? bset->eq[i_eq] : bset->ineq[i_ineq];
8696	/* The coefficient should always be one due to normalization. */
8697	if (!isl_int_is_one(c[1+nparam+dim]))
8698		return 0;
8699	if (isl_seq_first_non_zero(c+1, nparam+dim) != -1)
8700		return 0;
8701	if (isl_seq_first_non_zero(c+1+nparam+dim+1,
8702					total - nparam - dim - 1) != -1)
8703		return 0;
8704	if (val)
8705		isl_int_neg(*val, c[0]);
8706	return 1;
8707}
8708
8709int isl_set_plain_dim_has_fixed_lower_bound(__isl_keep isl_set *set,
8710	unsigned dim, isl_int *val)
8711{
8712	int i;
8713	isl_int v;
8714	isl_int tmp;
8715	int fixed;
8716
8717	if (!set)
8718		return -1;
8719	if (set->n == 0)
8720		return 0;
8721	if (set->n == 1)
8722		return isl_basic_set_plain_dim_has_fixed_lower_bound(set->p[0],
8723								dim, val);
8724	isl_int_init(v);
8725	isl_int_init(tmp);
8726	fixed = isl_basic_set_plain_dim_has_fixed_lower_bound(set->p[0],
8727								dim, &v);
8728	for (i = 1; fixed == 1 && i < set->n; ++i) {
8729		fixed = isl_basic_set_plain_dim_has_fixed_lower_bound(set->p[i],
8730								dim, &tmp);
8731		if (fixed == 1 && isl_int_ne(tmp, v))
8732			fixed = 0;
8733	}
8734	if (val)
8735		isl_int_set(*val, v);
8736	isl_int_clear(tmp);
8737	isl_int_clear(v);
8738	return fixed;
8739}
8740
8741struct constraint {
8742	unsigned	size;
8743	isl_int		*c;
8744};
8745
8746/* uset_gist depends on constraints without existentially quantified
8747 * variables sorting first.
8748 */
8749static int qsort_constraint_cmp(const void *p1, const void *p2)
8750{
8751	const struct constraint *c1 = (const struct constraint *)p1;
8752	const struct constraint *c2 = (const struct constraint *)p2;
8753	int l1, l2;
8754	unsigned size = isl_min(c1->size, c2->size);
8755
8756	l1 = isl_seq_last_non_zero(c1->c + 1, size);
8757	l2 = isl_seq_last_non_zero(c2->c + 1, size);
8758
8759	if (l1 != l2)
8760		return l1 - l2;
8761
8762	return isl_seq_cmp(c1->c + 1, c2->c + 1, size);
8763}
8764
8765static struct isl_basic_map *isl_basic_map_sort_constraints(
8766	struct isl_basic_map *bmap)
8767{
8768	int i;
8769	struct constraint *c;
8770	unsigned total;
8771
8772	if (!bmap)
8773		return NULL;
8774	if (bmap->n_ineq == 0)
8775		return bmap;
8776	total = isl_basic_map_total_dim(bmap);
8777	c = isl_alloc_array(bmap->ctx, struct constraint, bmap->n_ineq);
8778	if (!c)
8779		goto error;
8780	for (i = 0; i < bmap->n_ineq; ++i) {
8781		c[i].size = total;
8782		c[i].c = bmap->ineq[i];
8783	}
8784	qsort(c, bmap->n_ineq, sizeof(struct constraint), qsort_constraint_cmp);
8785	for (i = 0; i < bmap->n_ineq; ++i)
8786		bmap->ineq[i] = c[i].c;
8787	free(c);
8788	return bmap;
8789error:
8790	isl_basic_map_free(bmap);
8791	return NULL;
8792}
8793
8794__isl_give isl_basic_set *isl_basic_set_sort_constraints(
8795	__isl_take isl_basic_set *bset)
8796{
8797	return (struct isl_basic_set *)isl_basic_map_sort_constraints(
8798						(struct isl_basic_map *)bset);
8799}
8800
8801struct isl_basic_map *isl_basic_map_normalize(struct isl_basic_map *bmap)
8802{
8803	if (!bmap)
8804		return NULL;
8805	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED))
8806		return bmap;
8807	bmap = isl_basic_map_remove_redundancies(bmap);
8808	bmap = isl_basic_map_sort_constraints(bmap);
8809	if (bmap)
8810		ISL_F_SET(bmap, ISL_BASIC_MAP_NORMALIZED);
8811	return bmap;
8812}
8813
8814struct isl_basic_set *isl_basic_set_normalize(struct isl_basic_set *bset)
8815{
8816	return (struct isl_basic_set *)isl_basic_map_normalize(
8817						(struct isl_basic_map *)bset);
8818}
8819
8820int isl_basic_map_plain_cmp(const __isl_keep isl_basic_map *bmap1,
8821	const __isl_keep isl_basic_map *bmap2)
8822{
8823	int i, cmp;
8824	unsigned total;
8825
8826	if (bmap1 == bmap2)
8827		return 0;
8828	if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=
8829	    ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))
8830		return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;
8831	if (isl_basic_map_n_param(bmap1) != isl_basic_map_n_param(bmap2))
8832		return isl_basic_map_n_param(bmap1) - isl_basic_map_n_param(bmap2);
8833	if (isl_basic_map_n_in(bmap1) != isl_basic_map_n_in(bmap2))
8834		return isl_basic_map_n_out(bmap1) - isl_basic_map_n_out(bmap2);
8835	if (isl_basic_map_n_out(bmap1) != isl_basic_map_n_out(bmap2))
8836		return isl_basic_map_n_out(bmap1) - isl_basic_map_n_out(bmap2);
8837	if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&
8838	    ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
8839		return 0;
8840	if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))
8841		return 1;
8842	if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
8843		return -1;
8844	if (bmap1->n_eq != bmap2->n_eq)
8845		return bmap1->n_eq - bmap2->n_eq;
8846	if (bmap1->n_ineq != bmap2->n_ineq)
8847		return bmap1->n_ineq - bmap2->n_ineq;
8848	if (bmap1->n_div != bmap2->n_div)
8849		return bmap1->n_div - bmap2->n_div;
8850	total = isl_basic_map_total_dim(bmap1);
8851	for (i = 0; i < bmap1->n_eq; ++i) {
8852		cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
8853		if (cmp)
8854			return cmp;
8855	}
8856	for (i = 0; i < bmap1->n_ineq; ++i) {
8857		cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);
8858		if (cmp)
8859			return cmp;
8860	}
8861	for (i = 0; i < bmap1->n_div; ++i) {
8862		cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
8863		if (cmp)
8864			return cmp;
8865	}
8866	return 0;
8867}
8868
8869int isl_basic_set_plain_cmp(const __isl_keep isl_basic_set *bset1,
8870	const __isl_keep isl_basic_set *bset2)
8871{
8872	return isl_basic_map_plain_cmp(bset1, bset2);
8873}
8874
8875int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
8876{
8877	int i, cmp;
8878
8879	if (set1 == set2)
8880		return 0;
8881	if (set1->n != set2->n)
8882		return set1->n - set2->n;
8883
8884	for (i = 0; i < set1->n; ++i) {
8885		cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);
8886		if (cmp)
8887			return cmp;
8888	}
8889
8890	return 0;
8891}
8892
8893int isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
8894	__isl_keep isl_basic_map *bmap2)
8895{
8896	return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;
8897}
8898
8899int isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
8900	__isl_keep isl_basic_set *bset2)
8901{
8902	return isl_basic_map_plain_is_equal((isl_basic_map *)bset1,
8903					    (isl_basic_map *)bset2);
8904}
8905
8906static int qsort_bmap_cmp(const void *p1, const void *p2)
8907{
8908	const struct isl_basic_map *bmap1 = *(const struct isl_basic_map **)p1;
8909	const struct isl_basic_map *bmap2 = *(const struct isl_basic_map **)p2;
8910
8911	return isl_basic_map_plain_cmp(bmap1, bmap2);
8912}
8913
8914/* We normalize in place, but if anything goes wrong we need
8915 * to return NULL, so we need to make sure we don't change the
8916 * meaning of any possible other copies of map.
8917 */
8918struct isl_map *isl_map_normalize(struct isl_map *map)
8919{
8920	int i, j;
8921	struct isl_basic_map *bmap;
8922
8923	if (!map)
8924		return NULL;
8925	if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))
8926		return map;
8927	for (i = 0; i < map->n; ++i) {
8928		bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));
8929		if (!bmap)
8930			goto error;
8931		isl_basic_map_free(map->p[i]);
8932		map->p[i] = bmap;
8933	}
8934	qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);
8935	ISL_F_SET(map, ISL_MAP_NORMALIZED);
8936	map = isl_map_remove_empty_parts(map);
8937	if (!map)
8938		return NULL;
8939	for (i = map->n - 1; i >= 1; --i) {
8940		if (!isl_basic_map_plain_is_equal(map->p[i-1], map->p[i]))
8941			continue;
8942		isl_basic_map_free(map->p[i-1]);
8943		for (j = i; j < map->n; ++j)
8944			map->p[j-1] = map->p[j];
8945		map->n--;
8946	}
8947	return map;
8948error:
8949	isl_map_free(map);
8950	return NULL;
8951
8952}
8953
8954struct isl_set *isl_set_normalize(struct isl_set *set)
8955{
8956	return (struct isl_set *)isl_map_normalize((struct isl_map *)set);
8957}
8958
8959int isl_map_plain_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
8960{
8961	int i;
8962	int equal;
8963
8964	if (!map1 || !map2)
8965		return -1;
8966
8967	if (map1 == map2)
8968		return 1;
8969	if (!isl_space_is_equal(map1->dim, map2->dim))
8970		return 0;
8971
8972	map1 = isl_map_copy(map1);
8973	map2 = isl_map_copy(map2);
8974	map1 = isl_map_normalize(map1);
8975	map2 = isl_map_normalize(map2);
8976	if (!map1 || !map2)
8977		goto error;
8978	equal = map1->n == map2->n;
8979	for (i = 0; equal && i < map1->n; ++i) {
8980		equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);
8981		if (equal < 0)
8982			goto error;
8983	}
8984	isl_map_free(map1);
8985	isl_map_free(map2);
8986	return equal;
8987error:
8988	isl_map_free(map1);
8989	isl_map_free(map2);
8990	return -1;
8991}
8992
8993int isl_map_fast_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
8994{
8995	return isl_map_plain_is_equal(map1, map2);
8996}
8997
8998int isl_set_plain_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
8999{
9000	return isl_map_plain_is_equal((struct isl_map *)set1,
9001						(struct isl_map *)set2);
9002}
9003
9004int isl_set_fast_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
9005{
9006	return isl_set_plain_is_equal(set1, set2);
9007}
9008
9009/* Return an interval that ranges from min to max (inclusive)
9010 */
9011struct isl_basic_set *isl_basic_set_interval(struct isl_ctx *ctx,
9012	isl_int min, isl_int max)
9013{
9014	int k;
9015	struct isl_basic_set *bset = NULL;
9016
9017	bset = isl_basic_set_alloc(ctx, 0, 1, 0, 0, 2);
9018	if (!bset)
9019		goto error;
9020
9021	k = isl_basic_set_alloc_inequality(bset);
9022	if (k < 0)
9023		goto error;
9024	isl_int_set_si(bset->ineq[k][1], 1);
9025	isl_int_neg(bset->ineq[k][0], min);
9026
9027	k = isl_basic_set_alloc_inequality(bset);
9028	if (k < 0)
9029		goto error;
9030	isl_int_set_si(bset->ineq[k][1], -1);
9031	isl_int_set(bset->ineq[k][0], max);
9032
9033	return bset;
9034error:
9035	isl_basic_set_free(bset);
9036	return NULL;
9037}
9038
9039/* Return the Cartesian product of the basic sets in list (in the given order).
9040 */
9041__isl_give isl_basic_set *isl_basic_set_list_product(
9042	__isl_take struct isl_basic_set_list *list)
9043{
9044	int i;
9045	unsigned dim;
9046	unsigned nparam;
9047	unsigned extra;
9048	unsigned n_eq;
9049	unsigned n_ineq;
9050	struct isl_basic_set *product = NULL;
9051
9052	if (!list)
9053		goto error;
9054	isl_assert(list->ctx, list->n > 0, goto error);
9055	isl_assert(list->ctx, list->p[0], goto error);
9056	nparam = isl_basic_set_n_param(list->p[0]);
9057	dim = isl_basic_set_n_dim(list->p[0]);
9058	extra = list->p[0]->n_div;
9059	n_eq = list->p[0]->n_eq;
9060	n_ineq = list->p[0]->n_ineq;
9061	for (i = 1; i < list->n; ++i) {
9062		isl_assert(list->ctx, list->p[i], goto error);
9063		isl_assert(list->ctx,
9064		    nparam == isl_basic_set_n_param(list->p[i]), goto error);
9065		dim += isl_basic_set_n_dim(list->p[i]);
9066		extra += list->p[i]->n_div;
9067		n_eq += list->p[i]->n_eq;
9068		n_ineq += list->p[i]->n_ineq;
9069	}
9070	product = isl_basic_set_alloc(list->ctx, nparam, dim, extra,
9071					n_eq, n_ineq);
9072	if (!product)
9073		goto error;
9074	dim = 0;
9075	for (i = 0; i < list->n; ++i) {
9076		isl_basic_set_add_constraints(product,
9077					isl_basic_set_copy(list->p[i]), dim);
9078		dim += isl_basic_set_n_dim(list->p[i]);
9079	}
9080	isl_basic_set_list_free(list);
9081	return product;
9082error:
9083	isl_basic_set_free(product);
9084	isl_basic_set_list_free(list);
9085	return NULL;
9086}
9087
9088struct isl_basic_map *isl_basic_map_product(
9089		struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
9090{
9091	isl_space *dim_result = NULL;
9092	struct isl_basic_map *bmap;
9093	unsigned in1, in2, out1, out2, nparam, total, pos;
9094	struct isl_dim_map *dim_map1, *dim_map2;
9095
9096	if (!bmap1 || !bmap2)
9097		goto error;
9098
9099	isl_assert(bmap1->ctx, isl_space_match(bmap1->dim, isl_dim_param,
9100				     bmap2->dim, isl_dim_param), goto error);
9101	dim_result = isl_space_product(isl_space_copy(bmap1->dim),
9102						   isl_space_copy(bmap2->dim));
9103
9104	in1 = isl_basic_map_n_in(bmap1);
9105	in2 = isl_basic_map_n_in(bmap2);
9106	out1 = isl_basic_map_n_out(bmap1);
9107	out2 = isl_basic_map_n_out(bmap2);
9108	nparam = isl_basic_map_n_param(bmap1);
9109
9110	total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;
9111	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9112	dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9113	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9114	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9115	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9116	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
9117	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
9118	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
9119	isl_dim_map_div(dim_map1, bmap1, pos += out2);
9120	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9121
9122	bmap = isl_basic_map_alloc_space(dim_result,
9123			bmap1->n_div + bmap2->n_div,
9124			bmap1->n_eq + bmap2->n_eq,
9125			bmap1->n_ineq + bmap2->n_ineq);
9126	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9127	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9128	bmap = isl_basic_map_simplify(bmap);
9129	return isl_basic_map_finalize(bmap);
9130error:
9131	isl_basic_map_free(bmap1);
9132	isl_basic_map_free(bmap2);
9133	return NULL;
9134}
9135
9136__isl_give isl_basic_map *isl_basic_map_flat_product(
9137	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9138{
9139	isl_basic_map *prod;
9140
9141	prod = isl_basic_map_product(bmap1, bmap2);
9142	prod = isl_basic_map_flatten(prod);
9143	return prod;
9144}
9145
9146__isl_give isl_basic_set *isl_basic_set_flat_product(
9147	__isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
9148{
9149	return isl_basic_map_flat_range_product(bset1, bset2);
9150}
9151
9152__isl_give isl_basic_map *isl_basic_map_domain_product(
9153	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9154{
9155	isl_space *space_result = NULL;
9156	isl_basic_map *bmap;
9157	unsigned in1, in2, out, nparam, total, pos;
9158	struct isl_dim_map *dim_map1, *dim_map2;
9159
9160	if (!bmap1 || !bmap2)
9161		goto error;
9162
9163	space_result = isl_space_domain_product(isl_space_copy(bmap1->dim),
9164						isl_space_copy(bmap2->dim));
9165
9166	in1 = isl_basic_map_dim(bmap1, isl_dim_in);
9167	in2 = isl_basic_map_dim(bmap2, isl_dim_in);
9168	out = isl_basic_map_dim(bmap1, isl_dim_out);
9169	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
9170
9171	total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
9172	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9173	dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9174	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9175	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9176	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9177	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
9178	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
9179	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);
9180	isl_dim_map_div(dim_map1, bmap1, pos += out);
9181	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9182
9183	bmap = isl_basic_map_alloc_space(space_result,
9184			bmap1->n_div + bmap2->n_div,
9185			bmap1->n_eq + bmap2->n_eq,
9186			bmap1->n_ineq + bmap2->n_ineq);
9187	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9188	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9189	bmap = isl_basic_map_simplify(bmap);
9190	return isl_basic_map_finalize(bmap);
9191error:
9192	isl_basic_map_free(bmap1);
9193	isl_basic_map_free(bmap2);
9194	return NULL;
9195}
9196
9197__isl_give isl_basic_map *isl_basic_map_range_product(
9198	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9199{
9200	isl_space *dim_result = NULL;
9201	isl_basic_map *bmap;
9202	unsigned in, out1, out2, nparam, total, pos;
9203	struct isl_dim_map *dim_map1, *dim_map2;
9204
9205	if (!bmap1 || !bmap2)
9206		goto error;
9207
9208	if (!isl_space_match(bmap1->dim, isl_dim_param,
9209			    bmap2->dim, isl_dim_param))
9210		isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
9211			"parameters don't match", goto error);
9212
9213	dim_result = isl_space_range_product(isl_space_copy(bmap1->dim),
9214					   isl_space_copy(bmap2->dim));
9215
9216	in = isl_basic_map_dim(bmap1, isl_dim_in);
9217	out1 = isl_basic_map_n_out(bmap1);
9218	out2 = isl_basic_map_n_out(bmap2);
9219	nparam = isl_basic_map_n_param(bmap1);
9220
9221	total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
9222	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9223	dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9224	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9225	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9226	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9227	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
9228	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);
9229	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
9230	isl_dim_map_div(dim_map1, bmap1, pos += out2);
9231	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9232
9233	bmap = isl_basic_map_alloc_space(dim_result,
9234			bmap1->n_div + bmap2->n_div,
9235			bmap1->n_eq + bmap2->n_eq,
9236			bmap1->n_ineq + bmap2->n_ineq);
9237	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9238	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9239	bmap = isl_basic_map_simplify(bmap);
9240	return isl_basic_map_finalize(bmap);
9241error:
9242	isl_basic_map_free(bmap1);
9243	isl_basic_map_free(bmap2);
9244	return NULL;
9245}
9246
9247__isl_give isl_basic_map *isl_basic_map_flat_range_product(
9248	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9249{
9250	isl_basic_map *prod;
9251
9252	prod = isl_basic_map_range_product(bmap1, bmap2);
9253	prod = isl_basic_map_flatten_range(prod);
9254	return prod;
9255}
9256
9257static __isl_give isl_map *map_product(__isl_take isl_map *map1,
9258	__isl_take isl_map *map2,
9259	__isl_give isl_space *(*dim_product)(__isl_take isl_space *left,
9260					   __isl_take isl_space *right),
9261	__isl_give isl_basic_map *(*basic_map_product)(
9262		__isl_take isl_basic_map *left, __isl_take isl_basic_map *right))
9263{
9264	unsigned flags = 0;
9265	struct isl_map *result;
9266	int i, j;
9267
9268	if (!map1 || !map2)
9269		goto error;
9270
9271	isl_assert(map1->ctx, isl_space_match(map1->dim, isl_dim_param,
9272					 map2->dim, isl_dim_param), goto error);
9273
9274	if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
9275	    ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
9276		ISL_FL_SET(flags, ISL_MAP_DISJOINT);
9277
9278	result = isl_map_alloc_space(dim_product(isl_space_copy(map1->dim),
9279					       isl_space_copy(map2->dim)),
9280				map1->n * map2->n, flags);
9281	if (!result)
9282		goto error;
9283	for (i = 0; i < map1->n; ++i)
9284		for (j = 0; j < map2->n; ++j) {
9285			struct isl_basic_map *part;
9286			part = basic_map_product(isl_basic_map_copy(map1->p[i]),
9287						 isl_basic_map_copy(map2->p[j]));
9288			if (isl_basic_map_is_empty(part))
9289				isl_basic_map_free(part);
9290			else
9291				result = isl_map_add_basic_map(result, part);
9292			if (!result)
9293				goto error;
9294		}
9295	isl_map_free(map1);
9296	isl_map_free(map2);
9297	return result;
9298error:
9299	isl_map_free(map1);
9300	isl_map_free(map2);
9301	return NULL;
9302}
9303
9304/* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
9305 */
9306static __isl_give isl_map *map_product_aligned(__isl_take isl_map *map1,
9307	__isl_take isl_map *map2)
9308{
9309	return map_product(map1, map2, &isl_space_product, &isl_basic_map_product);
9310}
9311
9312__isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
9313	__isl_take isl_map *map2)
9314{
9315	return isl_map_align_params_map_map_and(map1, map2, &map_product_aligned);
9316}
9317
9318/* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
9319 */
9320__isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
9321	__isl_take isl_map *map2)
9322{
9323	isl_map *prod;
9324
9325	prod = isl_map_product(map1, map2);
9326	prod = isl_map_flatten(prod);
9327	return prod;
9328}
9329
9330/* Given two set A and B, construct its Cartesian product A x B.
9331 */
9332struct isl_set *isl_set_product(struct isl_set *set1, struct isl_set *set2)
9333{
9334	return isl_map_range_product(set1, set2);
9335}
9336
9337__isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
9338	__isl_take isl_set *set2)
9339{
9340	return isl_map_flat_range_product(set1, set2);
9341}
9342
9343/* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
9344 */
9345static __isl_give isl_map *map_domain_product_aligned(__isl_take isl_map *map1,
9346	__isl_take isl_map *map2)
9347{
9348	return map_product(map1, map2, &isl_space_domain_product,
9349				&isl_basic_map_domain_product);
9350}
9351
9352/* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
9353 */
9354static __isl_give isl_map *map_range_product_aligned(__isl_take isl_map *map1,
9355	__isl_take isl_map *map2)
9356{
9357	return map_product(map1, map2, &isl_space_range_product,
9358				&isl_basic_map_range_product);
9359}
9360
9361__isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
9362	__isl_take isl_map *map2)
9363{
9364	return isl_map_align_params_map_map_and(map1, map2,
9365						&map_domain_product_aligned);
9366}
9367
9368__isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
9369	__isl_take isl_map *map2)
9370{
9371	return isl_map_align_params_map_map_and(map1, map2,
9372						&map_range_product_aligned);
9373}
9374
9375/* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)
9376 */
9377__isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
9378	__isl_take isl_map *map2)
9379{
9380	isl_map *prod;
9381
9382	prod = isl_map_domain_product(map1, map2);
9383	prod = isl_map_flatten_domain(prod);
9384	return prod;
9385}
9386
9387/* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
9388 */
9389__isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
9390	__isl_take isl_map *map2)
9391{
9392	isl_map *prod;
9393
9394	prod = isl_map_range_product(map1, map2);
9395	prod = isl_map_flatten_range(prod);
9396	return prod;
9397}
9398
9399uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
9400{
9401	int i;
9402	uint32_t hash = isl_hash_init();
9403	unsigned total;
9404
9405	if (!bmap)
9406		return 0;
9407	bmap = isl_basic_map_copy(bmap);
9408	bmap = isl_basic_map_normalize(bmap);
9409	if (!bmap)
9410		return 0;
9411	total = isl_basic_map_total_dim(bmap);
9412	isl_hash_byte(hash, bmap->n_eq & 0xFF);
9413	for (i = 0; i < bmap->n_eq; ++i) {
9414		uint32_t c_hash;
9415		c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);
9416		isl_hash_hash(hash, c_hash);
9417	}
9418	isl_hash_byte(hash, bmap->n_ineq & 0xFF);
9419	for (i = 0; i < bmap->n_ineq; ++i) {
9420		uint32_t c_hash;
9421		c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);
9422		isl_hash_hash(hash, c_hash);
9423	}
9424	isl_hash_byte(hash, bmap->n_div & 0xFF);
9425	for (i = 0; i < bmap->n_div; ++i) {
9426		uint32_t c_hash;
9427		if (isl_int_is_zero(bmap->div[i][0]))
9428			continue;
9429		isl_hash_byte(hash, i & 0xFF);
9430		c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);
9431		isl_hash_hash(hash, c_hash);
9432	}
9433	isl_basic_map_free(bmap);
9434	return hash;
9435}
9436
9437uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)
9438{
9439	return isl_basic_map_get_hash((isl_basic_map *)bset);
9440}
9441
9442uint32_t isl_map_get_hash(__isl_keep isl_map *map)
9443{
9444	int i;
9445	uint32_t hash;
9446
9447	if (!map)
9448		return 0;
9449	map = isl_map_copy(map);
9450	map = isl_map_normalize(map);
9451	if (!map)
9452		return 0;
9453
9454	hash = isl_hash_init();
9455	for (i = 0; i < map->n; ++i) {
9456		uint32_t bmap_hash;
9457		bmap_hash = isl_basic_map_get_hash(map->p[i]);
9458		isl_hash_hash(hash, bmap_hash);
9459	}
9460
9461	isl_map_free(map);
9462
9463	return hash;
9464}
9465
9466uint32_t isl_set_get_hash(__isl_keep isl_set *set)
9467{
9468	return isl_map_get_hash((isl_map *)set);
9469}
9470
9471/* Check if the value for dimension dim is completely determined
9472 * by the values of the other parameters and variables.
9473 * That is, check if dimension dim is involved in an equality.
9474 */
9475int isl_basic_set_dim_is_unique(struct isl_basic_set *bset, unsigned dim)
9476{
9477	int i;
9478	unsigned nparam;
9479
9480	if (!bset)
9481		return -1;
9482	nparam = isl_basic_set_n_param(bset);
9483	for (i = 0; i < bset->n_eq; ++i)
9484		if (!isl_int_is_zero(bset->eq[i][1 + nparam + dim]))
9485			return 1;
9486	return 0;
9487}
9488
9489/* Check if the value for dimension dim is completely determined
9490 * by the values of the other parameters and variables.
9491 * That is, check if dimension dim is involved in an equality
9492 * for each of the subsets.
9493 */
9494int isl_set_dim_is_unique(struct isl_set *set, unsigned dim)
9495{
9496	int i;
9497
9498	if (!set)
9499		return -1;
9500	for (i = 0; i < set->n; ++i) {
9501		int unique;
9502		unique = isl_basic_set_dim_is_unique(set->p[i], dim);
9503		if (unique != 1)
9504			return unique;
9505	}
9506	return 1;
9507}
9508
9509int isl_set_n_basic_set(__isl_keep isl_set *set)
9510{
9511	return set ? set->n : 0;
9512}
9513
9514int isl_map_foreach_basic_map(__isl_keep isl_map *map,
9515	int (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)
9516{
9517	int i;
9518
9519	if (!map)
9520		return -1;
9521
9522	for (i = 0; i < map->n; ++i)
9523		if (fn(isl_basic_map_copy(map->p[i]), user) < 0)
9524			return -1;
9525
9526	return 0;
9527}
9528
9529int isl_set_foreach_basic_set(__isl_keep isl_set *set,
9530	int (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
9531{
9532	int i;
9533
9534	if (!set)
9535		return -1;
9536
9537	for (i = 0; i < set->n; ++i)
9538		if (fn(isl_basic_set_copy(set->p[i]), user) < 0)
9539			return -1;
9540
9541	return 0;
9542}
9543
9544__isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
9545{
9546	isl_space *dim;
9547
9548	if (!bset)
9549		return NULL;
9550
9551	bset = isl_basic_set_cow(bset);
9552	if (!bset)
9553		return NULL;
9554
9555	dim = isl_basic_set_get_space(bset);
9556	dim = isl_space_lift(dim, bset->n_div);
9557	if (!dim)
9558		goto error;
9559	isl_space_free(bset->dim);
9560	bset->dim = dim;
9561	bset->extra -= bset->n_div;
9562	bset->n_div = 0;
9563
9564	bset = isl_basic_set_finalize(bset);
9565
9566	return bset;
9567error:
9568	isl_basic_set_free(bset);
9569	return NULL;
9570}
9571
9572__isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
9573{
9574	int i;
9575	isl_space *dim;
9576	unsigned n_div;
9577
9578	set = isl_set_align_divs(set);
9579
9580	if (!set)
9581		return NULL;
9582
9583	set = isl_set_cow(set);
9584	if (!set)
9585		return NULL;
9586
9587	n_div = set->p[0]->n_div;
9588	dim = isl_set_get_space(set);
9589	dim = isl_space_lift(dim, n_div);
9590	if (!dim)
9591		goto error;
9592	isl_space_free(set->dim);
9593	set->dim = dim;
9594
9595	for (i = 0; i < set->n; ++i) {
9596		set->p[i] = isl_basic_set_lift(set->p[i]);
9597		if (!set->p[i])
9598			goto error;
9599	}
9600
9601	return set;
9602error:
9603	isl_set_free(set);
9604	return NULL;
9605}
9606
9607__isl_give isl_map *isl_set_lifting(__isl_take isl_set *set)
9608{
9609	isl_space *dim;
9610	struct isl_basic_map *bmap;
9611	unsigned n_set;
9612	unsigned n_div;
9613	unsigned n_param;
9614	unsigned total;
9615	int i, k, l;
9616
9617	set = isl_set_align_divs(set);
9618
9619	if (!set)
9620		return NULL;
9621
9622	dim = isl_set_get_space(set);
9623	if (set->n == 0 || set->p[0]->n_div == 0) {
9624		isl_set_free(set);
9625		return isl_map_identity(isl_space_map_from_set(dim));
9626	}
9627
9628	n_div = set->p[0]->n_div;
9629	dim = isl_space_map_from_set(dim);
9630	n_param = isl_space_dim(dim, isl_dim_param);
9631	n_set = isl_space_dim(dim, isl_dim_in);
9632	dim = isl_space_extend(dim, n_param, n_set, n_set + n_div);
9633	bmap = isl_basic_map_alloc_space(dim, 0, n_set, 2 * n_div);
9634	for (i = 0; i < n_set; ++i)
9635		bmap = var_equal(bmap, i);
9636
9637	total = n_param + n_set + n_set + n_div;
9638	for (i = 0; i < n_div; ++i) {
9639		k = isl_basic_map_alloc_inequality(bmap);
9640		if (k < 0)
9641			goto error;
9642		isl_seq_cpy(bmap->ineq[k], set->p[0]->div[i]+1, 1+n_param);
9643		isl_seq_clr(bmap->ineq[k]+1+n_param, n_set);
9644		isl_seq_cpy(bmap->ineq[k]+1+n_param+n_set,
9645			    set->p[0]->div[i]+1+1+n_param, n_set + n_div);
9646		isl_int_neg(bmap->ineq[k][1+n_param+n_set+n_set+i],
9647			    set->p[0]->div[i][0]);
9648
9649		l = isl_basic_map_alloc_inequality(bmap);
9650		if (l < 0)
9651			goto error;
9652		isl_seq_neg(bmap->ineq[l], bmap->ineq[k], 1 + total);
9653		isl_int_add(bmap->ineq[l][0], bmap->ineq[l][0],
9654			    set->p[0]->div[i][0]);
9655		isl_int_sub_ui(bmap->ineq[l][0], bmap->ineq[l][0], 1);
9656	}
9657
9658	isl_set_free(set);
9659	bmap = isl_basic_map_simplify(bmap);
9660	bmap = isl_basic_map_finalize(bmap);
9661	return isl_map_from_basic_map(bmap);
9662error:
9663	isl_set_free(set);
9664	isl_basic_map_free(bmap);
9665	return NULL;
9666}
9667
9668int isl_basic_set_size(__isl_keep isl_basic_set *bset)
9669{
9670	unsigned dim;
9671	int size = 0;
9672
9673	if (!bset)
9674		return -1;
9675
9676	dim = isl_basic_set_total_dim(bset);
9677	size += bset->n_eq * (1 + dim);
9678	size += bset->n_ineq * (1 + dim);
9679	size += bset->n_div * (2 + dim);
9680
9681	return size;
9682}
9683
9684int isl_set_size(__isl_keep isl_set *set)
9685{
9686	int i;
9687	int size = 0;
9688
9689	if (!set)
9690		return -1;
9691
9692	for (i = 0; i < set->n; ++i)
9693		size += isl_basic_set_size(set->p[i]);
9694
9695	return size;
9696}
9697
9698/* Check if there is any lower bound (if lower == 0) and/or upper
9699 * bound (if upper == 0) on the specified dim.
9700 */
9701static int basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
9702	enum isl_dim_type type, unsigned pos, int lower, int upper)
9703{
9704	int i;
9705
9706	if (!bmap)
9707		return -1;
9708
9709	isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), return -1);
9710
9711	pos += isl_basic_map_offset(bmap, type);
9712
9713	for (i = 0; i < bmap->n_div; ++i) {
9714		if (isl_int_is_zero(bmap->div[i][0]))
9715			continue;
9716		if (!isl_int_is_zero(bmap->div[i][1 + pos]))
9717			return 1;
9718	}
9719
9720	for (i = 0; i < bmap->n_eq; ++i)
9721		if (!isl_int_is_zero(bmap->eq[i][pos]))
9722			return 1;
9723
9724	for (i = 0; i < bmap->n_ineq; ++i) {
9725		int sgn = isl_int_sgn(bmap->ineq[i][pos]);
9726		if (sgn > 0)
9727			lower = 1;
9728		if (sgn < 0)
9729			upper = 1;
9730	}
9731
9732	return lower && upper;
9733}
9734
9735int isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
9736	enum isl_dim_type type, unsigned pos)
9737{
9738	return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);
9739}
9740
9741int isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,
9742	enum isl_dim_type type, unsigned pos)
9743{
9744	return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);
9745}
9746
9747int isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,
9748	enum isl_dim_type type, unsigned pos)
9749{
9750	return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);
9751}
9752
9753int isl_map_dim_is_bounded(__isl_keep isl_map *map,
9754	enum isl_dim_type type, unsigned pos)
9755{
9756	int i;
9757
9758	if (!map)
9759		return -1;
9760
9761	for (i = 0; i < map->n; ++i) {
9762		int bounded;
9763		bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);
9764		if (bounded < 0 || !bounded)
9765			return bounded;
9766	}
9767
9768	return 1;
9769}
9770
9771/* Return 1 if the specified dim is involved in both an upper bound
9772 * and a lower bound.
9773 */
9774int isl_set_dim_is_bounded(__isl_keep isl_set *set,
9775	enum isl_dim_type type, unsigned pos)
9776{
9777	return isl_map_dim_is_bounded((isl_map *)set, type, pos);
9778}
9779
9780/* Does "map" have a bound (according to "fn") for any of its basic maps?
9781 */
9782static int has_any_bound(__isl_keep isl_map *map,
9783	enum isl_dim_type type, unsigned pos,
9784	int (*fn)(__isl_keep isl_basic_map *bmap,
9785		  enum isl_dim_type type, unsigned pos))
9786{
9787	int i;
9788
9789	if (!map)
9790		return -1;
9791
9792	for (i = 0; i < map->n; ++i) {
9793		int bounded;
9794		bounded = fn(map->p[i], type, pos);
9795		if (bounded < 0 || bounded)
9796			return bounded;
9797	}
9798
9799	return 0;
9800}
9801
9802/* Return 1 if the specified dim is involved in any lower bound.
9803 */
9804int isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
9805	enum isl_dim_type type, unsigned pos)
9806{
9807	return has_any_bound(set, type, pos,
9808				&isl_basic_map_dim_has_lower_bound);
9809}
9810
9811/* Return 1 if the specified dim is involved in any upper bound.
9812 */
9813int isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
9814	enum isl_dim_type type, unsigned pos)
9815{
9816	return has_any_bound(set, type, pos,
9817				&isl_basic_map_dim_has_upper_bound);
9818}
9819
9820/* Does "map" have a bound (according to "fn") for all of its basic maps?
9821 */
9822static int has_bound(__isl_keep isl_map *map,
9823	enum isl_dim_type type, unsigned pos,
9824	int (*fn)(__isl_keep isl_basic_map *bmap,
9825		  enum isl_dim_type type, unsigned pos))
9826{
9827	int i;
9828
9829	if (!map)
9830		return -1;
9831
9832	for (i = 0; i < map->n; ++i) {
9833		int bounded;
9834		bounded = fn(map->p[i], type, pos);
9835		if (bounded < 0 || !bounded)
9836			return bounded;
9837	}
9838
9839	return 1;
9840}
9841
9842/* Return 1 if the specified dim has a lower bound (in each of its basic sets).
9843 */
9844int isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
9845	enum isl_dim_type type, unsigned pos)
9846{
9847	return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);
9848}
9849
9850/* Return 1 if the specified dim has an upper bound (in each of its basic sets).
9851 */
9852int isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
9853	enum isl_dim_type type, unsigned pos)
9854{
9855	return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);
9856}
9857
9858/* For each of the "n" variables starting at "first", determine
9859 * the sign of the variable and put the results in the first "n"
9860 * elements of the array "signs".
9861 * Sign
9862 *	1 means that the variable is non-negative
9863 *	-1 means that the variable is non-positive
9864 *	0 means the variable attains both positive and negative values.
9865 */
9866int isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
9867	unsigned first, unsigned n, int *signs)
9868{
9869	isl_vec *bound = NULL;
9870	struct isl_tab *tab = NULL;
9871	struct isl_tab_undo *snap;
9872	int i;
9873
9874	if (!bset || !signs)
9875		return -1;
9876
9877	bound = isl_vec_alloc(bset->ctx, 1 + isl_basic_set_total_dim(bset));
9878	tab = isl_tab_from_basic_set(bset, 0);
9879	if (!bound || !tab)
9880		goto error;
9881
9882	isl_seq_clr(bound->el, bound->size);
9883	isl_int_set_si(bound->el[0], -1);
9884
9885	snap = isl_tab_snap(tab);
9886	for (i = 0; i < n; ++i) {
9887		int empty;
9888
9889		isl_int_set_si(bound->el[1 + first + i], -1);
9890		if (isl_tab_add_ineq(tab, bound->el) < 0)
9891			goto error;
9892		empty = tab->empty;
9893		isl_int_set_si(bound->el[1 + first + i], 0);
9894		if (isl_tab_rollback(tab, snap) < 0)
9895			goto error;
9896
9897		if (empty) {
9898			signs[i] = 1;
9899			continue;
9900		}
9901
9902		isl_int_set_si(bound->el[1 + first + i], 1);
9903		if (isl_tab_add_ineq(tab, bound->el) < 0)
9904			goto error;
9905		empty = tab->empty;
9906		isl_int_set_si(bound->el[1 + first + i], 0);
9907		if (isl_tab_rollback(tab, snap) < 0)
9908			goto error;
9909
9910		signs[i] = empty ? -1 : 0;
9911	}
9912
9913	isl_tab_free(tab);
9914	isl_vec_free(bound);
9915	return 0;
9916error:
9917	isl_tab_free(tab);
9918	isl_vec_free(bound);
9919	return -1;
9920}
9921
9922int isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
9923	enum isl_dim_type type, unsigned first, unsigned n, int *signs)
9924{
9925	if (!bset || !signs)
9926		return -1;
9927	isl_assert(bset->ctx, first + n <= isl_basic_set_dim(bset, type),
9928		return -1);
9929
9930	first += pos(bset->dim, type) - 1;
9931	return isl_basic_set_vars_get_sign(bset, first, n, signs);
9932}
9933
9934/* Check if the given basic map is obviously single-valued.
9935 * In particular, for each output dimension, check that there is
9936 * an equality that defines the output dimension in terms of
9937 * earlier dimensions.
9938 */
9939int isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
9940{
9941	int i, j;
9942	unsigned total;
9943	unsigned n_out;
9944	unsigned o_out;
9945
9946	if (!bmap)
9947		return -1;
9948
9949	total = 1 + isl_basic_map_total_dim(bmap);
9950	n_out = isl_basic_map_dim(bmap, isl_dim_out);
9951	o_out = isl_basic_map_offset(bmap, isl_dim_out);
9952
9953	for (i = 0; i < n_out; ++i) {
9954		for (j = 0; j < bmap->n_eq; ++j) {
9955			if (isl_int_is_zero(bmap->eq[j][o_out + i]))
9956				continue;
9957			if (isl_seq_first_non_zero(bmap->eq[j] + o_out + i + 1,
9958						total - (o_out + i + 1)) == -1)
9959				break;
9960		}
9961		if (j >= bmap->n_eq)
9962			return 0;
9963	}
9964
9965	return 1;
9966}
9967
9968/* Check if the given basic map is single-valued.
9969 * We simply compute
9970 *
9971 *	M \circ M^-1
9972 *
9973 * and check if the result is a subset of the identity mapping.
9974 */
9975int isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)
9976{
9977	isl_space *space;
9978	isl_basic_map *test;
9979	isl_basic_map *id;
9980	int sv;
9981
9982	sv = isl_basic_map_plain_is_single_valued(bmap);
9983	if (sv < 0 || sv)
9984		return sv;
9985
9986	test = isl_basic_map_reverse(isl_basic_map_copy(bmap));
9987	test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));
9988
9989	space = isl_basic_map_get_space(bmap);
9990	space = isl_space_map_from_set(isl_space_range(space));
9991	id = isl_basic_map_identity(space);
9992
9993	sv = isl_basic_map_is_subset(test, id);
9994
9995	isl_basic_map_free(test);
9996	isl_basic_map_free(id);
9997
9998	return sv;
9999}
10000
10001/* Check if the given map is obviously single-valued.
10002 */
10003int isl_map_plain_is_single_valued(__isl_keep isl_map *map)
10004{
10005	if (!map)
10006		return -1;
10007	if (map->n == 0)
10008		return 1;
10009	if (map->n >= 2)
10010		return 0;
10011
10012	return isl_basic_map_plain_is_single_valued(map->p[0]);
10013}
10014
10015/* Check if the given map is single-valued.
10016 * We simply compute
10017 *
10018 *	M \circ M^-1
10019 *
10020 * and check if the result is a subset of the identity mapping.
10021 */
10022int isl_map_is_single_valued(__isl_keep isl_map *map)
10023{
10024	isl_space *dim;
10025	isl_map *test;
10026	isl_map *id;
10027	int sv;
10028
10029	sv = isl_map_plain_is_single_valued(map);
10030	if (sv < 0 || sv)
10031		return sv;
10032
10033	test = isl_map_reverse(isl_map_copy(map));
10034	test = isl_map_apply_range(test, isl_map_copy(map));
10035
10036	dim = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));
10037	id = isl_map_identity(dim);
10038
10039	sv = isl_map_is_subset(test, id);
10040
10041	isl_map_free(test);
10042	isl_map_free(id);
10043
10044	return sv;
10045}
10046
10047int isl_map_is_injective(__isl_keep isl_map *map)
10048{
10049	int in;
10050
10051	map = isl_map_copy(map);
10052	map = isl_map_reverse(map);
10053	in = isl_map_is_single_valued(map);
10054	isl_map_free(map);
10055
10056	return in;
10057}
10058
10059/* Check if the given map is obviously injective.
10060 */
10061int isl_map_plain_is_injective(__isl_keep isl_map *map)
10062{
10063	int in;
10064
10065	map = isl_map_copy(map);
10066	map = isl_map_reverse(map);
10067	in = isl_map_plain_is_single_valued(map);
10068	isl_map_free(map);
10069
10070	return in;
10071}
10072
10073int isl_map_is_bijective(__isl_keep isl_map *map)
10074{
10075	int sv;
10076
10077	sv = isl_map_is_single_valued(map);
10078	if (sv < 0 || !sv)
10079		return sv;
10080
10081	return isl_map_is_injective(map);
10082}
10083
10084int isl_set_is_singleton(__isl_keep isl_set *set)
10085{
10086	return isl_map_is_single_valued((isl_map *)set);
10087}
10088
10089int isl_map_is_translation(__isl_keep isl_map *map)
10090{
10091	int ok;
10092	isl_set *delta;
10093
10094	delta = isl_map_deltas(isl_map_copy(map));
10095	ok = isl_set_is_singleton(delta);
10096	isl_set_free(delta);
10097
10098	return ok;
10099}
10100
10101static int unique(isl_int *p, unsigned pos, unsigned len)
10102{
10103	if (isl_seq_first_non_zero(p, pos) != -1)
10104		return 0;
10105	if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)
10106		return 0;
10107	return 1;
10108}
10109
10110int isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
10111{
10112	int i, j;
10113	unsigned nvar;
10114	unsigned ovar;
10115
10116	if (!bset)
10117		return -1;
10118
10119	if (isl_basic_set_dim(bset, isl_dim_div) != 0)
10120		return 0;
10121
10122	nvar = isl_basic_set_dim(bset, isl_dim_set);
10123	ovar = isl_space_offset(bset->dim, isl_dim_set);
10124	for (j = 0; j < nvar; ++j) {
10125		int lower = 0, upper = 0;
10126		for (i = 0; i < bset->n_eq; ++i) {
10127			if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))
10128				continue;
10129			if (!unique(bset->eq[i] + 1 + ovar, j, nvar))
10130				return 0;
10131			break;
10132		}
10133		if (i < bset->n_eq)
10134			continue;
10135		for (i = 0; i < bset->n_ineq; ++i) {
10136			if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))
10137				continue;
10138			if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))
10139				return 0;
10140			if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))
10141				lower = 1;
10142			else
10143				upper = 1;
10144		}
10145		if (!lower || !upper)
10146			return 0;
10147	}
10148
10149	return 1;
10150}
10151
10152int isl_set_is_box(__isl_keep isl_set *set)
10153{
10154	if (!set)
10155		return -1;
10156	if (set->n != 1)
10157		return 0;
10158
10159	return isl_basic_set_is_box(set->p[0]);
10160}
10161
10162int isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)
10163{
10164	if (!bset)
10165		return -1;
10166
10167	return isl_space_is_wrapping(bset->dim);
10168}
10169
10170int isl_set_is_wrapping(__isl_keep isl_set *set)
10171{
10172	if (!set)
10173		return -1;
10174
10175	return isl_space_is_wrapping(set->dim);
10176}
10177
10178__isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
10179{
10180	bmap = isl_basic_map_cow(bmap);
10181	if (!bmap)
10182		return NULL;
10183
10184	bmap->dim = isl_space_wrap(bmap->dim);
10185	if (!bmap->dim)
10186		goto error;
10187
10188	bmap = isl_basic_map_finalize(bmap);
10189
10190	return (isl_basic_set *)bmap;
10191error:
10192	isl_basic_map_free(bmap);
10193	return NULL;
10194}
10195
10196__isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)
10197{
10198	int i;
10199
10200	map = isl_map_cow(map);
10201	if (!map)
10202		return NULL;
10203
10204	for (i = 0; i < map->n; ++i) {
10205		map->p[i] = (isl_basic_map *)isl_basic_map_wrap(map->p[i]);
10206		if (!map->p[i])
10207			goto error;
10208	}
10209	map->dim = isl_space_wrap(map->dim);
10210	if (!map->dim)
10211		goto error;
10212
10213	return (isl_set *)map;
10214error:
10215	isl_map_free(map);
10216	return NULL;
10217}
10218
10219__isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
10220{
10221	bset = isl_basic_set_cow(bset);
10222	if (!bset)
10223		return NULL;
10224
10225	bset->dim = isl_space_unwrap(bset->dim);
10226	if (!bset->dim)
10227		goto error;
10228
10229	bset = isl_basic_set_finalize(bset);
10230
10231	return (isl_basic_map *)bset;
10232error:
10233	isl_basic_set_free(bset);
10234	return NULL;
10235}
10236
10237__isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
10238{
10239	int i;
10240
10241	if (!set)
10242		return NULL;
10243
10244	if (!isl_set_is_wrapping(set))
10245		isl_die(set->ctx, isl_error_invalid, "not a wrapping set",
10246			goto error);
10247
10248	set = isl_set_cow(set);
10249	if (!set)
10250		return NULL;
10251
10252	for (i = 0; i < set->n; ++i) {
10253		set->p[i] = (isl_basic_set *)isl_basic_set_unwrap(set->p[i]);
10254		if (!set->p[i])
10255			goto error;
10256	}
10257
10258	set->dim = isl_space_unwrap(set->dim);
10259	if (!set->dim)
10260		goto error;
10261
10262	return (isl_map *)set;
10263error:
10264	isl_set_free(set);
10265	return NULL;
10266}
10267
10268__isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
10269	enum isl_dim_type type)
10270{
10271	if (!bmap)
10272		return NULL;
10273
10274	if (!isl_space_is_named_or_nested(bmap->dim, type))
10275		return bmap;
10276
10277	bmap = isl_basic_map_cow(bmap);
10278	if (!bmap)
10279		return NULL;
10280
10281	bmap->dim = isl_space_reset(bmap->dim, type);
10282	if (!bmap->dim)
10283		goto error;
10284
10285	bmap = isl_basic_map_finalize(bmap);
10286
10287	return bmap;
10288error:
10289	isl_basic_map_free(bmap);
10290	return NULL;
10291}
10292
10293__isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
10294	enum isl_dim_type type)
10295{
10296	int i;
10297
10298	if (!map)
10299		return NULL;
10300
10301	if (!isl_space_is_named_or_nested(map->dim, type))
10302		return map;
10303
10304	map = isl_map_cow(map);
10305	if (!map)
10306		return NULL;
10307
10308	for (i = 0; i < map->n; ++i) {
10309		map->p[i] = isl_basic_map_reset(map->p[i], type);
10310		if (!map->p[i])
10311			goto error;
10312	}
10313	map->dim = isl_space_reset(map->dim, type);
10314	if (!map->dim)
10315		goto error;
10316
10317	return map;
10318error:
10319	isl_map_free(map);
10320	return NULL;
10321}
10322
10323__isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
10324{
10325	if (!bmap)
10326		return NULL;
10327
10328	if (!bmap->dim->nested[0] && !bmap->dim->nested[1])
10329		return bmap;
10330
10331	bmap = isl_basic_map_cow(bmap);
10332	if (!bmap)
10333		return NULL;
10334
10335	bmap->dim = isl_space_flatten(bmap->dim);
10336	if (!bmap->dim)
10337		goto error;
10338
10339	bmap = isl_basic_map_finalize(bmap);
10340
10341	return bmap;
10342error:
10343	isl_basic_map_free(bmap);
10344	return NULL;
10345}
10346
10347__isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
10348{
10349	return (isl_basic_set *)isl_basic_map_flatten((isl_basic_map *)bset);
10350}
10351
10352__isl_give isl_basic_map *isl_basic_map_flatten_domain(
10353	__isl_take isl_basic_map *bmap)
10354{
10355	if (!bmap)
10356		return NULL;
10357
10358	if (!bmap->dim->nested[0])
10359		return bmap;
10360
10361	bmap = isl_basic_map_cow(bmap);
10362	if (!bmap)
10363		return NULL;
10364
10365	bmap->dim = isl_space_flatten_domain(bmap->dim);
10366	if (!bmap->dim)
10367		goto error;
10368
10369	bmap = isl_basic_map_finalize(bmap);
10370
10371	return bmap;
10372error:
10373	isl_basic_map_free(bmap);
10374	return NULL;
10375}
10376
10377__isl_give isl_basic_map *isl_basic_map_flatten_range(
10378	__isl_take isl_basic_map *bmap)
10379{
10380	if (!bmap)
10381		return NULL;
10382
10383	if (!bmap->dim->nested[1])
10384		return bmap;
10385
10386	bmap = isl_basic_map_cow(bmap);
10387	if (!bmap)
10388		return NULL;
10389
10390	bmap->dim = isl_space_flatten_range(bmap->dim);
10391	if (!bmap->dim)
10392		goto error;
10393
10394	bmap = isl_basic_map_finalize(bmap);
10395
10396	return bmap;
10397error:
10398	isl_basic_map_free(bmap);
10399	return NULL;
10400}
10401
10402__isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)
10403{
10404	int i;
10405
10406	if (!map)
10407		return NULL;
10408
10409	if (!map->dim->nested[0] && !map->dim->nested[1])
10410		return map;
10411
10412	map = isl_map_cow(map);
10413	if (!map)
10414		return NULL;
10415
10416	for (i = 0; i < map->n; ++i) {
10417		map->p[i] = isl_basic_map_flatten(map->p[i]);
10418		if (!map->p[i])
10419			goto error;
10420	}
10421	map->dim = isl_space_flatten(map->dim);
10422	if (!map->dim)
10423		goto error;
10424
10425	return map;
10426error:
10427	isl_map_free(map);
10428	return NULL;
10429}
10430
10431__isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
10432{
10433	return (isl_set *)isl_map_flatten((isl_map *)set);
10434}
10435
10436__isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
10437{
10438	isl_space *dim, *flat_dim;
10439	isl_map *map;
10440
10441	dim = isl_set_get_space(set);
10442	flat_dim = isl_space_flatten(isl_space_copy(dim));
10443	map = isl_map_identity(isl_space_join(isl_space_reverse(dim), flat_dim));
10444	map = isl_map_intersect_domain(map, set);
10445
10446	return map;
10447}
10448
10449__isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)
10450{
10451	int i;
10452
10453	if (!map)
10454		return NULL;
10455
10456	if (!map->dim->nested[0])
10457		return map;
10458
10459	map = isl_map_cow(map);
10460	if (!map)
10461		return NULL;
10462
10463	for (i = 0; i < map->n; ++i) {
10464		map->p[i] = isl_basic_map_flatten_domain(map->p[i]);
10465		if (!map->p[i])
10466			goto error;
10467	}
10468	map->dim = isl_space_flatten_domain(map->dim);
10469	if (!map->dim)
10470		goto error;
10471
10472	return map;
10473error:
10474	isl_map_free(map);
10475	return NULL;
10476}
10477
10478__isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)
10479{
10480	int i;
10481
10482	if (!map)
10483		return NULL;
10484
10485	if (!map->dim->nested[1])
10486		return map;
10487
10488	map = isl_map_cow(map);
10489	if (!map)
10490		return NULL;
10491
10492	for (i = 0; i < map->n; ++i) {
10493		map->p[i] = isl_basic_map_flatten_range(map->p[i]);
10494		if (!map->p[i])
10495			goto error;
10496	}
10497	map->dim = isl_space_flatten_range(map->dim);
10498	if (!map->dim)
10499		goto error;
10500
10501	return map;
10502error:
10503	isl_map_free(map);
10504	return NULL;
10505}
10506
10507/* Reorder the dimensions of "bmap" according to the given dim_map
10508 * and set the dimension specification to "dim".
10509 */
10510__isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
10511	__isl_take isl_space *dim, __isl_take struct isl_dim_map *dim_map)
10512{
10513	isl_basic_map *res;
10514	unsigned flags;
10515
10516	bmap = isl_basic_map_cow(bmap);
10517	if (!bmap || !dim || !dim_map)
10518		goto error;
10519
10520	flags = bmap->flags;
10521	ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
10522	ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED);
10523	ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
10524	res = isl_basic_map_alloc_space(dim,
10525			bmap->n_div, bmap->n_eq, bmap->n_ineq);
10526	res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
10527	if (res)
10528		res->flags = flags;
10529	res = isl_basic_map_finalize(res);
10530	return res;
10531error:
10532	free(dim_map);
10533	isl_basic_map_free(bmap);
10534	isl_space_free(dim);
10535	return NULL;
10536}
10537
10538/* Reorder the dimensions of "map" according to given reordering.
10539 */
10540__isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
10541	__isl_take isl_reordering *r)
10542{
10543	int i;
10544	struct isl_dim_map *dim_map;
10545
10546	map = isl_map_cow(map);
10547	dim_map = isl_dim_map_from_reordering(r);
10548	if (!map || !r || !dim_map)
10549		goto error;
10550
10551	for (i = 0; i < map->n; ++i) {
10552		struct isl_dim_map *dim_map_i;
10553
10554		dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);
10555
10556		map->p[i] = isl_basic_map_realign(map->p[i],
10557					    isl_space_copy(r->dim), dim_map_i);
10558
10559		if (!map->p[i])
10560			goto error;
10561	}
10562
10563	map = isl_map_reset_space(map, isl_space_copy(r->dim));
10564
10565	isl_reordering_free(r);
10566	free(dim_map);
10567	return map;
10568error:
10569	free(dim_map);
10570	isl_map_free(map);
10571	isl_reordering_free(r);
10572	return NULL;
10573}
10574
10575__isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
10576	__isl_take isl_reordering *r)
10577{
10578	return (isl_set *)isl_map_realign((isl_map *)set, r);
10579}
10580
10581__isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
10582	__isl_take isl_space *model)
10583{
10584	isl_ctx *ctx;
10585
10586	if (!map || !model)
10587		goto error;
10588
10589	ctx = isl_space_get_ctx(model);
10590	if (!isl_space_has_named_params(model))
10591		isl_die(ctx, isl_error_invalid,
10592			"model has unnamed parameters", goto error);
10593	if (!isl_space_has_named_params(map->dim))
10594		isl_die(ctx, isl_error_invalid,
10595			"relation has unnamed parameters", goto error);
10596	if (!isl_space_match(map->dim, isl_dim_param, model, isl_dim_param)) {
10597		isl_reordering *exp;
10598
10599		model = isl_space_drop_dims(model, isl_dim_in,
10600					0, isl_space_dim(model, isl_dim_in));
10601		model = isl_space_drop_dims(model, isl_dim_out,
10602					0, isl_space_dim(model, isl_dim_out));
10603		exp = isl_parameter_alignment_reordering(map->dim, model);
10604		exp = isl_reordering_extend_space(exp, isl_map_get_space(map));
10605		map = isl_map_realign(map, exp);
10606	}
10607
10608	isl_space_free(model);
10609	return map;
10610error:
10611	isl_space_free(model);
10612	isl_map_free(map);
10613	return NULL;
10614}
10615
10616__isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
10617	__isl_take isl_space *model)
10618{
10619	return isl_map_align_params(set, model);
10620}
10621
10622/* Align the parameters of "bmap" to those of "model", introducing
10623 * additional parameters if needed.
10624 */
10625__isl_give isl_basic_map *isl_basic_map_align_params(
10626	__isl_take isl_basic_map *bmap, __isl_take isl_space *model)
10627{
10628	isl_ctx *ctx;
10629
10630	if (!bmap || !model)
10631		goto error;
10632
10633	ctx = isl_space_get_ctx(model);
10634	if (!isl_space_has_named_params(model))
10635		isl_die(ctx, isl_error_invalid,
10636			"model has unnamed parameters", goto error);
10637	if (!isl_space_has_named_params(bmap->dim))
10638		isl_die(ctx, isl_error_invalid,
10639			"relation has unnamed parameters", goto error);
10640	if (!isl_space_match(bmap->dim, isl_dim_param, model, isl_dim_param)) {
10641		isl_reordering *exp;
10642		struct isl_dim_map *dim_map;
10643
10644		model = isl_space_drop_dims(model, isl_dim_in,
10645					0, isl_space_dim(model, isl_dim_in));
10646		model = isl_space_drop_dims(model, isl_dim_out,
10647					0, isl_space_dim(model, isl_dim_out));
10648		exp = isl_parameter_alignment_reordering(bmap->dim, model);
10649		exp = isl_reordering_extend_space(exp,
10650					isl_basic_map_get_space(bmap));
10651		dim_map = isl_dim_map_from_reordering(exp);
10652		bmap = isl_basic_map_realign(bmap,
10653				    exp ? isl_space_copy(exp->dim) : NULL,
10654				    isl_dim_map_extend(dim_map, bmap));
10655		isl_reordering_free(exp);
10656		free(dim_map);
10657	}
10658
10659	isl_space_free(model);
10660	return bmap;
10661error:
10662	isl_space_free(model);
10663	isl_basic_map_free(bmap);
10664	return NULL;
10665}
10666
10667/* Align the parameters of "bset" to those of "model", introducing
10668 * additional parameters if needed.
10669 */
10670__isl_give isl_basic_set *isl_basic_set_align_params(
10671	__isl_take isl_basic_set *bset, __isl_take isl_space *model)
10672{
10673	return isl_basic_map_align_params(bset, model);
10674}
10675
10676__isl_give isl_mat *isl_basic_map_equalities_matrix(
10677		__isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
10678		enum isl_dim_type c2, enum isl_dim_type c3,
10679		enum isl_dim_type c4, enum isl_dim_type c5)
10680{
10681	enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
10682	struct isl_mat *mat;
10683	int i, j, k;
10684	int pos;
10685
10686	if (!bmap)
10687		return NULL;
10688	mat = isl_mat_alloc(bmap->ctx, bmap->n_eq,
10689				isl_basic_map_total_dim(bmap) + 1);
10690	if (!mat)
10691		return NULL;
10692	for (i = 0; i < bmap->n_eq; ++i)
10693		for (j = 0, pos = 0; j < 5; ++j) {
10694			int off = isl_basic_map_offset(bmap, c[j]);
10695			for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
10696				isl_int_set(mat->row[i][pos],
10697					    bmap->eq[i][off + k]);
10698				++pos;
10699			}
10700		}
10701
10702	return mat;
10703}
10704
10705__isl_give isl_mat *isl_basic_map_inequalities_matrix(
10706		__isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
10707		enum isl_dim_type c2, enum isl_dim_type c3,
10708		enum isl_dim_type c4, enum isl_dim_type c5)
10709{
10710	enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
10711	struct isl_mat *mat;
10712	int i, j, k;
10713	int pos;
10714
10715	if (!bmap)
10716		return NULL;
10717	mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq,
10718				isl_basic_map_total_dim(bmap) + 1);
10719	if (!mat)
10720		return NULL;
10721	for (i = 0; i < bmap->n_ineq; ++i)
10722		for (j = 0, pos = 0; j < 5; ++j) {
10723			int off = isl_basic_map_offset(bmap, c[j]);
10724			for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
10725				isl_int_set(mat->row[i][pos],
10726					    bmap->ineq[i][off + k]);
10727				++pos;
10728			}
10729		}
10730
10731	return mat;
10732}
10733
10734__isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
10735	__isl_take isl_space *dim,
10736	__isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
10737	enum isl_dim_type c2, enum isl_dim_type c3,
10738	enum isl_dim_type c4, enum isl_dim_type c5)
10739{
10740	enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
10741	isl_basic_map *bmap;
10742	unsigned total;
10743	unsigned extra;
10744	int i, j, k, l;
10745	int pos;
10746
10747	if (!dim || !eq || !ineq)
10748		goto error;
10749
10750	if (eq->n_col != ineq->n_col)
10751		isl_die(dim->ctx, isl_error_invalid,
10752			"equalities and inequalities matrices should have "
10753			"same number of columns", goto error);
10754
10755	total = 1 + isl_space_dim(dim, isl_dim_all);
10756
10757	if (eq->n_col < total)
10758		isl_die(dim->ctx, isl_error_invalid,
10759			"number of columns too small", goto error);
10760
10761	extra = eq->n_col - total;
10762
10763	bmap = isl_basic_map_alloc_space(isl_space_copy(dim), extra,
10764				       eq->n_row, ineq->n_row);
10765	if (!bmap)
10766		goto error;
10767	for (i = 0; i < extra; ++i) {
10768		k = isl_basic_map_alloc_div(bmap);
10769		if (k < 0)
10770			goto error;
10771		isl_int_set_si(bmap->div[k][0], 0);
10772	}
10773	for (i = 0; i < eq->n_row; ++i) {
10774		l = isl_basic_map_alloc_equality(bmap);
10775		if (l < 0)
10776			goto error;
10777		for (j = 0, pos = 0; j < 5; ++j) {
10778			int off = isl_basic_map_offset(bmap, c[j]);
10779			for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
10780				isl_int_set(bmap->eq[l][off + k],
10781					    eq->row[i][pos]);
10782				++pos;
10783			}
10784		}
10785	}
10786	for (i = 0; i < ineq->n_row; ++i) {
10787		l = isl_basic_map_alloc_inequality(bmap);
10788		if (l < 0)
10789			goto error;
10790		for (j = 0, pos = 0; j < 5; ++j) {
10791			int off = isl_basic_map_offset(bmap, c[j]);
10792			for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
10793				isl_int_set(bmap->ineq[l][off + k],
10794					    ineq->row[i][pos]);
10795				++pos;
10796			}
10797		}
10798	}
10799
10800	isl_space_free(dim);
10801	isl_mat_free(eq);
10802	isl_mat_free(ineq);
10803
10804	bmap = isl_basic_map_simplify(bmap);
10805	return isl_basic_map_finalize(bmap);
10806error:
10807	isl_space_free(dim);
10808	isl_mat_free(eq);
10809	isl_mat_free(ineq);
10810	return NULL;
10811}
10812
10813__isl_give isl_mat *isl_basic_set_equalities_matrix(
10814	__isl_keep isl_basic_set *bset, enum isl_dim_type c1,
10815	enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
10816{
10817	return isl_basic_map_equalities_matrix((isl_basic_map *)bset,
10818						c1, c2, c3, c4, isl_dim_in);
10819}
10820
10821__isl_give isl_mat *isl_basic_set_inequalities_matrix(
10822	__isl_keep isl_basic_set *bset, enum isl_dim_type c1,
10823	enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
10824{
10825	return isl_basic_map_inequalities_matrix((isl_basic_map *)bset,
10826						 c1, c2, c3, c4, isl_dim_in);
10827}
10828
10829__isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
10830	__isl_take isl_space *dim,
10831	__isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
10832	enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
10833{
10834	return (isl_basic_set*)
10835	    isl_basic_map_from_constraint_matrices(dim, eq, ineq,
10836						   c1, c2, c3, c4, isl_dim_in);
10837}
10838
10839int isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)
10840{
10841	if (!bmap)
10842		return -1;
10843
10844	return isl_space_can_zip(bmap->dim);
10845}
10846
10847int isl_map_can_zip(__isl_keep isl_map *map)
10848{
10849	if (!map)
10850		return -1;
10851
10852	return isl_space_can_zip(map->dim);
10853}
10854
10855/* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map
10856 * (A -> C) -> (B -> D).
10857 */
10858__isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
10859{
10860	unsigned pos;
10861	unsigned n1;
10862	unsigned n2;
10863
10864	if (!bmap)
10865		return NULL;
10866
10867	if (!isl_basic_map_can_zip(bmap))
10868		isl_die(bmap->ctx, isl_error_invalid,
10869			"basic map cannot be zipped", goto error);
10870	pos = isl_basic_map_offset(bmap, isl_dim_in) +
10871		isl_space_dim(bmap->dim->nested[0], isl_dim_in);
10872	n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
10873	n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
10874	bmap = isl_basic_map_cow(bmap);
10875	bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
10876	if (!bmap)
10877		return NULL;
10878	bmap->dim = isl_space_zip(bmap->dim);
10879	if (!bmap->dim)
10880		goto error;
10881	return bmap;
10882error:
10883	isl_basic_map_free(bmap);
10884	return NULL;
10885}
10886
10887/* Given a map (A -> B) -> (C -> D), return the corresponding map
10888 * (A -> C) -> (B -> D).
10889 */
10890__isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
10891{
10892	int i;
10893
10894	if (!map)
10895		return NULL;
10896
10897	if (!isl_map_can_zip(map))
10898		isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
10899			goto error);
10900
10901	map = isl_map_cow(map);
10902	if (!map)
10903		return NULL;
10904
10905	for (i = 0; i < map->n; ++i) {
10906		map->p[i] = isl_basic_map_zip(map->p[i]);
10907		if (!map->p[i])
10908			goto error;
10909	}
10910
10911	map->dim = isl_space_zip(map->dim);
10912	if (!map->dim)
10913		goto error;
10914
10915	return map;
10916error:
10917	isl_map_free(map);
10918	return NULL;
10919}
10920
10921/* Can we apply isl_basic_map_curry to "bmap"?
10922 * That is, does it have a nested relation in its domain?
10923 */
10924int isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)
10925{
10926	if (!bmap)
10927		return -1;
10928
10929	return isl_space_can_curry(bmap->dim);
10930}
10931
10932/* Can we apply isl_map_curry to "map"?
10933 * That is, does it have a nested relation in its domain?
10934 */
10935int isl_map_can_curry(__isl_keep isl_map *map)
10936{
10937	if (!map)
10938		return -1;
10939
10940	return isl_space_can_curry(map->dim);
10941}
10942
10943/* Given a basic map (A -> B) -> C, return the corresponding basic map
10944 * A -> (B -> C).
10945 */
10946__isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
10947{
10948
10949	if (!bmap)
10950		return NULL;
10951
10952	if (!isl_basic_map_can_curry(bmap))
10953		isl_die(bmap->ctx, isl_error_invalid,
10954			"basic map cannot be curried", goto error);
10955	bmap = isl_basic_map_cow(bmap);
10956	if (!bmap)
10957		return NULL;
10958	bmap->dim = isl_space_curry(bmap->dim);
10959	if (!bmap->dim)
10960		goto error;
10961	return bmap;
10962error:
10963	isl_basic_map_free(bmap);
10964	return NULL;
10965}
10966
10967/* Given a map (A -> B) -> C, return the corresponding map
10968 * A -> (B -> C).
10969 */
10970__isl_give isl_map *isl_map_curry(__isl_take isl_map *map)
10971{
10972	int i;
10973
10974	if (!map)
10975		return NULL;
10976
10977	if (!isl_map_can_curry(map))
10978		isl_die(map->ctx, isl_error_invalid, "map cannot be curried",
10979			goto error);
10980
10981	map = isl_map_cow(map);
10982	if (!map)
10983		return NULL;
10984
10985	for (i = 0; i < map->n; ++i) {
10986		map->p[i] = isl_basic_map_curry(map->p[i]);
10987		if (!map->p[i])
10988			goto error;
10989	}
10990
10991	map->dim = isl_space_curry(map->dim);
10992	if (!map->dim)
10993		goto error;
10994
10995	return map;
10996error:
10997	isl_map_free(map);
10998	return NULL;
10999}
11000
11001/* Can we apply isl_basic_map_uncurry to "bmap"?
11002 * That is, does it have a nested relation in its domain?
11003 */
11004int isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)
11005{
11006	if (!bmap)
11007		return -1;
11008
11009	return isl_space_can_uncurry(bmap->dim);
11010}
11011
11012/* Can we apply isl_map_uncurry to "map"?
11013 * That is, does it have a nested relation in its domain?
11014 */
11015int isl_map_can_uncurry(__isl_keep isl_map *map)
11016{
11017	if (!map)
11018		return -1;
11019
11020	return isl_space_can_uncurry(map->dim);
11021}
11022
11023/* Given a basic map A -> (B -> C), return the corresponding basic map
11024 * (A -> B) -> C.
11025 */
11026__isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
11027{
11028
11029	if (!bmap)
11030		return NULL;
11031
11032	if (!isl_basic_map_can_uncurry(bmap))
11033		isl_die(bmap->ctx, isl_error_invalid,
11034			"basic map cannot be uncurried",
11035			return isl_basic_map_free(bmap));
11036	bmap = isl_basic_map_cow(bmap);
11037	if (!bmap)
11038		return NULL;
11039	bmap->dim = isl_space_uncurry(bmap->dim);
11040	if (!bmap->dim)
11041		return isl_basic_map_free(bmap);
11042	return bmap;
11043}
11044
11045/* Given a map A -> (B -> C), return the corresponding map
11046 * (A -> B) -> C.
11047 */
11048__isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)
11049{
11050	int i;
11051
11052	if (!map)
11053		return NULL;
11054
11055	if (!isl_map_can_uncurry(map))
11056		isl_die(map->ctx, isl_error_invalid, "map cannot be uncurried",
11057			return isl_map_free(map));
11058
11059	map = isl_map_cow(map);
11060	if (!map)
11061		return NULL;
11062
11063	for (i = 0; i < map->n; ++i) {
11064		map->p[i] = isl_basic_map_uncurry(map->p[i]);
11065		if (!map->p[i])
11066			return isl_map_free(map);
11067	}
11068
11069	map->dim = isl_space_uncurry(map->dim);
11070	if (!map->dim)
11071		return isl_map_free(map);
11072
11073	return map;
11074}
11075
11076/* Construct a basic map mapping the domain of the affine expression
11077 * to a one-dimensional range prescribed by the affine expression.
11078 */
11079__isl_give isl_basic_map *isl_basic_map_from_aff(__isl_take isl_aff *aff)
11080{
11081	int k;
11082	int pos;
11083	isl_local_space *ls;
11084	isl_basic_map *bmap;
11085
11086	if (!aff)
11087		return NULL;
11088
11089	ls = isl_aff_get_local_space(aff);
11090	bmap = isl_basic_map_from_local_space(ls);
11091	bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
11092	k = isl_basic_map_alloc_equality(bmap);
11093	if (k < 0)
11094		goto error;
11095
11096	pos = isl_basic_map_offset(bmap, isl_dim_out);
11097	isl_seq_cpy(bmap->eq[k], aff->v->el + 1, pos);
11098	isl_int_neg(bmap->eq[k][pos], aff->v->el[0]);
11099	isl_seq_cpy(bmap->eq[k] + pos + 1, aff->v->el + 1 + pos,
11100		    aff->v->size - (pos + 1));
11101
11102	isl_aff_free(aff);
11103	bmap = isl_basic_map_finalize(bmap);
11104	return bmap;
11105error:
11106	isl_aff_free(aff);
11107	isl_basic_map_free(bmap);
11108	return NULL;
11109}
11110
11111/* Construct a map mapping the domain of the affine expression
11112 * to a one-dimensional range prescribed by the affine expression.
11113 */
11114__isl_give isl_map *isl_map_from_aff(__isl_take isl_aff *aff)
11115{
11116	isl_basic_map *bmap;
11117
11118	bmap = isl_basic_map_from_aff(aff);
11119	return isl_map_from_basic_map(bmap);
11120}
11121
11122/* Construct a basic map mapping the domain the multi-affine expression
11123 * to its range, with each dimension in the range equated to the
11124 * corresponding affine expression.
11125 */
11126__isl_give isl_basic_map *isl_basic_map_from_multi_aff(
11127	__isl_take isl_multi_aff *maff)
11128{
11129	int i;
11130	isl_space *space;
11131	isl_basic_map *bmap;
11132
11133	if (!maff)
11134		return NULL;
11135
11136	if (isl_space_dim(maff->space, isl_dim_out) != maff->n)
11137		isl_die(isl_multi_aff_get_ctx(maff), isl_error_internal,
11138			"invalid space", return isl_multi_aff_free(maff));
11139
11140	space = isl_space_domain(isl_multi_aff_get_space(maff));
11141	bmap = isl_basic_map_universe(isl_space_from_domain(space));
11142
11143	for (i = 0; i < maff->n; ++i) {
11144		isl_aff *aff;
11145		isl_basic_map *bmap_i;
11146
11147		aff = isl_aff_copy(maff->p[i]);
11148		bmap_i = isl_basic_map_from_aff(aff);
11149
11150		bmap = isl_basic_map_flat_range_product(bmap, bmap_i);
11151	}
11152
11153	bmap = isl_basic_map_reset_space(bmap, isl_multi_aff_get_space(maff));
11154
11155	isl_multi_aff_free(maff);
11156	return bmap;
11157}
11158
11159/* Construct a map mapping the domain the multi-affine expression
11160 * to its range, with each dimension in the range equated to the
11161 * corresponding affine expression.
11162 */
11163__isl_give isl_map *isl_map_from_multi_aff(__isl_take isl_multi_aff *maff)
11164{
11165	isl_basic_map *bmap;
11166
11167	bmap = isl_basic_map_from_multi_aff(maff);
11168	return isl_map_from_basic_map(bmap);
11169}
11170
11171/* Construct a basic map mapping a domain in the given space to
11172 * to an n-dimensional range, with n the number of elements in the list,
11173 * where each coordinate in the range is prescribed by the
11174 * corresponding affine expression.
11175 * The domains of all affine expressions in the list are assumed to match
11176 * domain_dim.
11177 */
11178__isl_give isl_basic_map *isl_basic_map_from_aff_list(
11179	__isl_take isl_space *domain_dim, __isl_take isl_aff_list *list)
11180{
11181	int i;
11182	isl_space *dim;
11183	isl_basic_map *bmap;
11184
11185	if (!list)
11186		return NULL;
11187
11188	dim = isl_space_from_domain(domain_dim);
11189	bmap = isl_basic_map_universe(dim);
11190
11191	for (i = 0; i < list->n; ++i) {
11192		isl_aff *aff;
11193		isl_basic_map *bmap_i;
11194
11195		aff = isl_aff_copy(list->p[i]);
11196		bmap_i = isl_basic_map_from_aff(aff);
11197
11198		bmap = isl_basic_map_flat_range_product(bmap, bmap_i);
11199	}
11200
11201	isl_aff_list_free(list);
11202	return bmap;
11203}
11204
11205__isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
11206	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11207{
11208	return isl_map_equate(set, type1, pos1, type2, pos2);
11209}
11210
11211/* Construct a basic map where the given dimensions are equal to each other.
11212 */
11213static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
11214	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11215{
11216	isl_basic_map *bmap = NULL;
11217	int i;
11218
11219	if (!space)
11220		return NULL;
11221
11222	if (pos1 >= isl_space_dim(space, type1))
11223		isl_die(isl_space_get_ctx(space), isl_error_invalid,
11224			"index out of bounds", goto error);
11225	if (pos2 >= isl_space_dim(space, type2))
11226		isl_die(isl_space_get_ctx(space), isl_error_invalid,
11227			"index out of bounds", goto error);
11228
11229	if (type1 == type2 && pos1 == pos2)
11230		return isl_basic_map_universe(space);
11231
11232	bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);
11233	i = isl_basic_map_alloc_equality(bmap);
11234	if (i < 0)
11235		goto error;
11236	isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
11237	pos1 += isl_basic_map_offset(bmap, type1);
11238	pos2 += isl_basic_map_offset(bmap, type2);
11239	isl_int_set_si(bmap->eq[i][pos1], -1);
11240	isl_int_set_si(bmap->eq[i][pos2], 1);
11241	bmap = isl_basic_map_finalize(bmap);
11242	isl_space_free(space);
11243	return bmap;
11244error:
11245	isl_space_free(space);
11246	isl_basic_map_free(bmap);
11247	return NULL;
11248}
11249
11250/* Add a constraint imposing that the given two dimensions are equal.
11251 */
11252__isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
11253	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11254{
11255	isl_basic_map *eq;
11256
11257	eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
11258
11259	bmap = isl_basic_map_intersect(bmap, eq);
11260
11261	return bmap;
11262}
11263
11264/* Add a constraint imposing that the given two dimensions are equal.
11265 */
11266__isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
11267	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11268{
11269	isl_basic_map *bmap;
11270
11271	bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);
11272
11273	map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
11274
11275	return map;
11276}
11277
11278/* Add a constraint imposing that the given two dimensions have opposite values.
11279 */
11280__isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
11281	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11282{
11283	isl_basic_map *bmap = NULL;
11284	int i;
11285
11286	if (!map)
11287		return NULL;
11288
11289	if (pos1 >= isl_map_dim(map, type1))
11290		isl_die(map->ctx, isl_error_invalid,
11291			"index out of bounds", goto error);
11292	if (pos2 >= isl_map_dim(map, type2))
11293		isl_die(map->ctx, isl_error_invalid,
11294			"index out of bounds", goto error);
11295
11296	bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
11297	i = isl_basic_map_alloc_equality(bmap);
11298	if (i < 0)
11299		goto error;
11300	isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
11301	pos1 += isl_basic_map_offset(bmap, type1);
11302	pos2 += isl_basic_map_offset(bmap, type2);
11303	isl_int_set_si(bmap->eq[i][pos1], 1);
11304	isl_int_set_si(bmap->eq[i][pos2], 1);
11305	bmap = isl_basic_map_finalize(bmap);
11306
11307	map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
11308
11309	return map;
11310error:
11311	isl_basic_map_free(bmap);
11312	isl_map_free(map);
11313	return NULL;
11314}
11315
11316/* Add a constraint imposing that the value of the first dimension is
11317 * greater than or equal to that of the second.
11318 */
11319__isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
11320	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11321{
11322	isl_constraint *c;
11323	isl_local_space *ls;
11324
11325	if (!bmap)
11326		return NULL;
11327
11328	if (pos1 >= isl_basic_map_dim(bmap, type1))
11329		isl_die(bmap->ctx, isl_error_invalid,
11330			"index out of bounds", return isl_basic_map_free(bmap));
11331	if (pos2 >= isl_basic_map_dim(bmap, type2))
11332		isl_die(bmap->ctx, isl_error_invalid,
11333			"index out of bounds", return isl_basic_map_free(bmap));
11334
11335	if (type1 == type2 && pos1 == pos2)
11336		return bmap;
11337
11338	ls = isl_local_space_from_space(isl_basic_map_get_space(bmap));
11339	c = isl_inequality_alloc(ls);
11340	c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);
11341	c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);
11342	bmap = isl_basic_map_add_constraint(bmap, c);
11343
11344	return bmap;
11345}
11346
11347/* Construct a basic map where the value of the first dimension is
11348 * greater than that of the second.
11349 */
11350static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
11351	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11352{
11353	isl_basic_map *bmap = NULL;
11354	int i;
11355
11356	if (!space)
11357		return NULL;
11358
11359	if (pos1 >= isl_space_dim(space, type1))
11360		isl_die(isl_space_get_ctx(space), isl_error_invalid,
11361			"index out of bounds", goto error);
11362	if (pos2 >= isl_space_dim(space, type2))
11363		isl_die(isl_space_get_ctx(space), isl_error_invalid,
11364			"index out of bounds", goto error);
11365
11366	if (type1 == type2 && pos1 == pos2)
11367		return isl_basic_map_empty(space);
11368
11369	bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
11370	i = isl_basic_map_alloc_inequality(bmap);
11371	if (i < 0)
11372		goto error;
11373	isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
11374	pos1 += isl_basic_map_offset(bmap, type1);
11375	pos2 += isl_basic_map_offset(bmap, type2);
11376	isl_int_set_si(bmap->ineq[i][pos1], 1);
11377	isl_int_set_si(bmap->ineq[i][pos2], -1);
11378	isl_int_set_si(bmap->ineq[i][0], -1);
11379	bmap = isl_basic_map_finalize(bmap);
11380
11381	return bmap;
11382error:
11383	isl_space_free(space);
11384	isl_basic_map_free(bmap);
11385	return NULL;
11386}
11387
11388/* Add a constraint imposing that the value of the first dimension is
11389 * greater than that of the second.
11390 */
11391__isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
11392	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11393{
11394	isl_basic_map *gt;
11395
11396	gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
11397
11398	bmap = isl_basic_map_intersect(bmap, gt);
11399
11400	return bmap;
11401}
11402
11403/* Add a constraint imposing that the value of the first dimension is
11404 * greater than that of the second.
11405 */
11406__isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
11407	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11408{
11409	isl_basic_map *bmap;
11410
11411	bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);
11412
11413	map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
11414
11415	return map;
11416}
11417
11418/* Add a constraint imposing that the value of the first dimension is
11419 * smaller than that of the second.
11420 */
11421__isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
11422	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11423{
11424	return isl_map_order_gt(map, type2, pos2, type1, pos1);
11425}
11426
11427__isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
11428	int pos)
11429{
11430	isl_aff *div;
11431	isl_local_space *ls;
11432
11433	if (!bmap)
11434		return NULL;
11435
11436	if (!isl_basic_map_divs_known(bmap))
11437		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
11438			"some divs are unknown", return NULL);
11439
11440	ls = isl_basic_map_get_local_space(bmap);
11441	div = isl_local_space_get_div(ls, pos);
11442	isl_local_space_free(ls);
11443
11444	return div;
11445}
11446
11447__isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
11448	int pos)
11449{
11450	return isl_basic_map_get_div(bset, pos);
11451}
11452
11453/* Plug in "subs" for dimension "type", "pos" of "bset".
11454 *
11455 * Let i be the dimension to replace and let "subs" be of the form
11456 *
11457 *	f/d
11458 *
11459 * Any integer division with a non-zero coefficient for i,
11460 *
11461 *	floor((a i + g)/m)
11462 *
11463 * is replaced by
11464 *
11465 *	floor((a f + d g)/(m d))
11466 *
11467 * Constraints of the form
11468 *
11469 *	a i + g
11470 *
11471 * are replaced by
11472 *
11473 *	a f + d g
11474 *
11475 * We currently require that "subs" is an integral expression.
11476 * Handling rational expressions may require us to add stride constraints
11477 * as we do in isl_basic_set_preimage_multi_aff.
11478 */
11479__isl_give isl_basic_set *isl_basic_set_substitute(
11480	__isl_take isl_basic_set *bset,
11481	enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
11482{
11483	int i;
11484	isl_int v;
11485	isl_ctx *ctx;
11486
11487	if (bset && isl_basic_set_plain_is_empty(bset))
11488		return bset;
11489
11490	bset = isl_basic_set_cow(bset);
11491	if (!bset || !subs)
11492		goto error;
11493
11494	ctx = isl_basic_set_get_ctx(bset);
11495	if (!isl_space_is_equal(bset->dim, subs->ls->dim))
11496		isl_die(ctx, isl_error_invalid,
11497			"spaces don't match", goto error);
11498	if (isl_local_space_dim(subs->ls, isl_dim_div) != 0)
11499		isl_die(ctx, isl_error_unsupported,
11500			"cannot handle divs yet", goto error);
11501	if (!isl_int_is_one(subs->v->el[0]))
11502		isl_die(ctx, isl_error_invalid,
11503			"can only substitute integer expressions", goto error);
11504
11505	pos += isl_basic_set_offset(bset, type);
11506
11507	isl_int_init(v);
11508
11509	for (i = 0; i < bset->n_eq; ++i) {
11510		if (isl_int_is_zero(bset->eq[i][pos]))
11511			continue;
11512		isl_int_set(v, bset->eq[i][pos]);
11513		isl_int_set_si(bset->eq[i][pos], 0);
11514		isl_seq_combine(bset->eq[i], subs->v->el[0], bset->eq[i],
11515				v, subs->v->el + 1, subs->v->size - 1);
11516	}
11517
11518	for (i = 0; i < bset->n_ineq; ++i) {
11519		if (isl_int_is_zero(bset->ineq[i][pos]))
11520			continue;
11521		isl_int_set(v, bset->ineq[i][pos]);
11522		isl_int_set_si(bset->ineq[i][pos], 0);
11523		isl_seq_combine(bset->ineq[i], subs->v->el[0], bset->ineq[i],
11524				v, subs->v->el + 1, subs->v->size - 1);
11525	}
11526
11527	for (i = 0; i < bset->n_div; ++i) {
11528		if (isl_int_is_zero(bset->div[i][1 + pos]))
11529			continue;
11530		isl_int_set(v, bset->div[i][1 + pos]);
11531		isl_int_set_si(bset->div[i][1 + pos], 0);
11532		isl_seq_combine(bset->div[i] + 1,
11533				subs->v->el[0], bset->div[i] + 1,
11534				v, subs->v->el + 1, subs->v->size - 1);
11535		isl_int_mul(bset->div[i][0], bset->div[i][0], subs->v->el[0]);
11536	}
11537
11538	isl_int_clear(v);
11539
11540	bset = isl_basic_set_simplify(bset);
11541	return isl_basic_set_finalize(bset);
11542error:
11543	isl_basic_set_free(bset);
11544	return NULL;
11545}
11546
11547/* Plug in "subs" for dimension "type", "pos" of "set".
11548 */
11549__isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
11550	enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
11551{
11552	int i;
11553
11554	if (set && isl_set_plain_is_empty(set))
11555		return set;
11556
11557	set = isl_set_cow(set);
11558	if (!set || !subs)
11559		goto error;
11560
11561	for (i = set->n - 1; i >= 0; --i) {
11562		set->p[i] = isl_basic_set_substitute(set->p[i], type, pos, subs);
11563		if (remove_if_empty(set, i) < 0)
11564			goto error;
11565	}
11566
11567	return set;
11568error:
11569	isl_set_free(set);
11570	return NULL;
11571}
11572
11573/* Check if the range of "ma" is compatible with the domain or range
11574 * (depending on "type") of "bmap".
11575 * Return -1 if anything is wrong.
11576 */
11577static int check_basic_map_compatible_range_multi_aff(
11578	__isl_keep isl_basic_map *bmap, enum isl_dim_type type,
11579	__isl_keep isl_multi_aff *ma)
11580{
11581	int m;
11582	isl_space *ma_space;
11583
11584	ma_space = isl_multi_aff_get_space(ma);
11585	m = isl_space_tuple_match(bmap->dim, type, ma_space, isl_dim_out);
11586	isl_space_free(ma_space);
11587	if (m >= 0 && !m)
11588		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
11589			"spaces don't match", return -1);
11590	return m;
11591}
11592
11593/* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"
11594 * coefficients before the transformed range of dimensions,
11595 * the "n_after" coefficients after the transformed range of dimensions
11596 * and the coefficients of the other divs in "bmap".
11597 */
11598static int set_ma_divs(__isl_keep isl_basic_map *bmap,
11599	__isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
11600{
11601	int i;
11602	int n_param;
11603	int n_set;
11604	isl_local_space *ls;
11605
11606	if (n_div == 0)
11607		return 0;
11608
11609	ls = isl_aff_get_domain_local_space(ma->p[0]);
11610	if (!ls)
11611		return -1;
11612
11613	n_param = isl_local_space_dim(ls, isl_dim_param);
11614	n_set = isl_local_space_dim(ls, isl_dim_set);
11615	for (i = 0; i < n_div; ++i) {
11616		int o_bmap = 0, o_ls = 0;
11617
11618		isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);
11619		o_bmap += 1 + 1 + n_param;
11620		o_ls += 1 + 1 + n_param;
11621		isl_seq_clr(bmap->div[i] + o_bmap, n_before);
11622		o_bmap += n_before;
11623		isl_seq_cpy(bmap->div[i] + o_bmap,
11624			    ls->div->row[i] + o_ls, n_set);
11625		o_bmap += n_set;
11626		o_ls += n_set;
11627		isl_seq_clr(bmap->div[i] + o_bmap, n_after);
11628		o_bmap += n_after;
11629		isl_seq_cpy(bmap->div[i] + o_bmap,
11630			    ls->div->row[i] + o_ls, n_div);
11631		o_bmap += n_div;
11632		o_ls += n_div;
11633		isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
11634		if (isl_basic_set_add_div_constraints(bmap, i) < 0)
11635			goto error;
11636	}
11637
11638	isl_local_space_free(ls);
11639	return 0;
11640error:
11641	isl_local_space_free(ls);
11642	return -1;
11643}
11644
11645/* How many stride constraints does "ma" enforce?
11646 * That is, how many of the affine expressions have a denominator
11647 * different from one?
11648 */
11649static int multi_aff_strides(__isl_keep isl_multi_aff *ma)
11650{
11651	int i;
11652	int strides = 0;
11653
11654	for (i = 0; i < ma->n; ++i)
11655		if (!isl_int_is_one(ma->p[i]->v->el[0]))
11656			strides++;
11657
11658	return strides;
11659}
11660
11661/* For each affine expression in ma of the form
11662 *
11663 *	x_i = (f_i y + h_i)/m_i
11664 *
11665 * with m_i different from one, add a constraint to "bmap"
11666 * of the form
11667 *
11668 *	f_i y + h_i = m_i alpha_i
11669 *
11670 * with alpha_i an additional existentially quantified variable.
11671 */
11672static __isl_give isl_basic_map *add_ma_strides(
11673	__isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,
11674	int n_before, int n_after)
11675{
11676	int i, k;
11677	int div;
11678	int total;
11679	int n_param;
11680	int n_in;
11681	int n_div;
11682
11683	total = isl_basic_map_total_dim(bmap);
11684	n_param = isl_multi_aff_dim(ma, isl_dim_param);
11685	n_in = isl_multi_aff_dim(ma, isl_dim_in);
11686	n_div = isl_multi_aff_dim(ma, isl_dim_div);
11687	for (i = 0; i < ma->n; ++i) {
11688		int o_bmap = 0, o_ma = 1;
11689
11690		if (isl_int_is_one(ma->p[i]->v->el[0]))
11691			continue;
11692		div = isl_basic_map_alloc_div(bmap);
11693		k = isl_basic_map_alloc_equality(bmap);
11694		if (div < 0 || k < 0)
11695			goto error;
11696		isl_int_set_si(bmap->div[div][0], 0);
11697		isl_seq_cpy(bmap->eq[k] + o_bmap,
11698			    ma->p[i]->v->el + o_ma, 1 + n_param);
11699		o_bmap += 1 + n_param;
11700		o_ma += 1 + n_param;
11701		isl_seq_clr(bmap->eq[k] + o_bmap, n_before);
11702		o_bmap += n_before;
11703		isl_seq_cpy(bmap->eq[k] + o_bmap,
11704			    ma->p[i]->v->el + o_ma, n_in);
11705		o_bmap += n_in;
11706		o_ma += n_in;
11707		isl_seq_clr(bmap->eq[k] + o_bmap, n_after);
11708		o_bmap += n_after;
11709		isl_seq_cpy(bmap->eq[k] + o_bmap,
11710			    ma->p[i]->v->el + o_ma, n_div);
11711		o_bmap += n_div;
11712		o_ma += n_div;
11713		isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);
11714		isl_int_neg(bmap->eq[k][1 + total], ma->p[i]->v->el[0]);
11715		total++;
11716	}
11717
11718	return bmap;
11719error:
11720	isl_basic_map_free(bmap);
11721	return NULL;
11722}
11723
11724/* Replace the domain or range space (depending on "type) of "space" by "set".
11725 */
11726static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,
11727	enum isl_dim_type type, __isl_take isl_space *set)
11728{
11729	if (type == isl_dim_in) {
11730		space = isl_space_range(space);
11731		space = isl_space_map_from_domain_and_range(set, space);
11732	} else {
11733		space = isl_space_domain(space);
11734		space = isl_space_map_from_domain_and_range(space, set);
11735	}
11736
11737	return space;
11738}
11739
11740/* Compute the preimage of the domain or range (depending on "type")
11741 * of "bmap" under the function represented by "ma".
11742 * In other words, plug in "ma" in the domain or range of "bmap".
11743 * The result is a basic map that lives in the same space as "bmap"
11744 * except that the domain or range has been replaced by
11745 * the domain space of "ma".
11746 *
11747 * If bmap is represented by
11748 *
11749 *	A(p) + S u + B x + T v + C(divs) >= 0,
11750 *
11751 * where u and x are input and output dimensions if type == isl_dim_out
11752 * while x and v are input and output dimensions if type == isl_dim_in,
11753 * and ma is represented by
11754 *
11755 *	x = D(p) + F(y) + G(divs')
11756 *
11757 * then the result is
11758 *
11759 *	A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0
11760 *
11761 * The divs in the input set are similarly adjusted.
11762 * In particular
11763 *
11764 *	floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)
11765 *
11766 * becomes
11767 *
11768 *	floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +
11769 *		B_i G(divs') + c_i(divs))/n_i)
11770 *
11771 * If bmap is not a rational map and if F(y) involves any denominators
11772 *
11773 *	x_i = (f_i y + h_i)/m_i
11774 *
11775 * then additional constraints are added to ensure that we only
11776 * map back integer points.  That is we enforce
11777 *
11778 *	f_i y + h_i = m_i alpha_i
11779 *
11780 * with alpha_i an additional existentially quantified variable.
11781 *
11782 * We first copy over the divs from "ma".
11783 * Then we add the modified constraints and divs from "bmap".
11784 * Finally, we add the stride constraints, if needed.
11785 */
11786__isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
11787	__isl_take isl_basic_map *bmap, enum isl_dim_type type,
11788	__isl_take isl_multi_aff *ma)
11789{
11790	int i, k;
11791	isl_space *space;
11792	isl_basic_map *res = NULL;
11793	int n_before, n_after, n_div_bmap, n_div_ma;
11794	isl_int f, c1, c2, g;
11795	int rational, strides;
11796
11797	isl_int_init(f);
11798	isl_int_init(c1);
11799	isl_int_init(c2);
11800	isl_int_init(g);
11801
11802	ma = isl_multi_aff_align_divs(ma);
11803	if (!bmap || !ma)
11804		goto error;
11805	if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)
11806		goto error;
11807
11808	if (type == isl_dim_in) {
11809		n_before = 0;
11810		n_after = isl_basic_map_dim(bmap, isl_dim_out);
11811	} else {
11812		n_before = isl_basic_map_dim(bmap, isl_dim_in);
11813		n_after = 0;
11814	}
11815	n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
11816	n_div_ma = ma->n ? isl_aff_dim(ma->p[0], isl_dim_div) : 0;
11817
11818	space = isl_multi_aff_get_domain_space(ma);
11819	space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
11820	rational = isl_basic_map_is_rational(bmap);
11821	strides = rational ? 0 : multi_aff_strides(ma);
11822	res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,
11823			    bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);
11824	if (rational)
11825		res = isl_basic_map_set_rational(res);
11826
11827	for (i = 0; i < n_div_ma + n_div_bmap; ++i)
11828		if (isl_basic_map_alloc_div(res) < 0)
11829			goto error;
11830
11831	if (set_ma_divs(res, ma, n_before, n_after, n_div_ma) < 0)
11832		goto error;
11833
11834	for (i = 0; i < bmap->n_eq; ++i) {
11835		k = isl_basic_map_alloc_equality(res);
11836		if (k < 0)
11837			goto error;
11838		isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
11839				n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
11840	}
11841
11842	for (i = 0; i < bmap->n_ineq; ++i) {
11843		k = isl_basic_map_alloc_inequality(res);
11844		if (k < 0)
11845			goto error;
11846		isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
11847				n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
11848	}
11849
11850	for (i = 0; i < bmap->n_div; ++i) {
11851		if (isl_int_is_zero(bmap->div[i][0])) {
11852			isl_int_set_si(res->div[n_div_ma + i][0], 0);
11853			continue;
11854		}
11855		isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
11856				    n_before, n_after, n_div_ma, n_div_bmap,
11857				    f, c1, c2, g, 1);
11858	}
11859
11860	if (strides)
11861		res = add_ma_strides(res, ma, n_before, n_after);
11862
11863	isl_int_clear(f);
11864	isl_int_clear(c1);
11865	isl_int_clear(c2);
11866	isl_int_clear(g);
11867	isl_basic_map_free(bmap);
11868	isl_multi_aff_free(ma);
11869	res = isl_basic_set_simplify(res);
11870	return isl_basic_map_finalize(res);
11871error:
11872	isl_int_clear(f);
11873	isl_int_clear(c1);
11874	isl_int_clear(c2);
11875	isl_int_clear(g);
11876	isl_basic_map_free(bmap);
11877	isl_multi_aff_free(ma);
11878	isl_basic_map_free(res);
11879	return NULL;
11880}
11881
11882/* Compute the preimage of "bset" under the function represented by "ma".
11883 * In other words, plug in "ma" in "bset".  The result is a basic set
11884 * that lives in the domain space of "ma".
11885 */
11886__isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
11887	__isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)
11888{
11889	return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);
11890}
11891
11892/* Check if the range of "ma" is compatible with the domain or range
11893 * (depending on "type") of "map".
11894 * Return -1 if anything is wrong.
11895 */
11896static int check_map_compatible_range_multi_aff(
11897	__isl_keep isl_map *map, enum isl_dim_type type,
11898	__isl_keep isl_multi_aff *ma)
11899{
11900	int m;
11901	isl_space *ma_space;
11902
11903	ma_space = isl_multi_aff_get_space(ma);
11904	m = isl_space_tuple_match(map->dim, type, ma_space, isl_dim_out);
11905	isl_space_free(ma_space);
11906	if (m >= 0 && !m)
11907		isl_die(isl_map_get_ctx(map), isl_error_invalid,
11908			"spaces don't match", return -1);
11909	return m;
11910}
11911
11912/* Compute the preimage of the domain or range (depending on "type")
11913 * of "map" under the function represented by "ma".
11914 * In other words, plug in "ma" in the domain or range of "map".
11915 * The result is a map that lives in the same space as "map"
11916 * except that the domain or range has been replaced by
11917 * the domain space of "ma".
11918 *
11919 * The parameters are assumed to have been aligned.
11920 */
11921static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
11922	enum isl_dim_type type, __isl_take isl_multi_aff *ma)
11923{
11924	int i;
11925	isl_space *space;
11926
11927	map = isl_map_cow(map);
11928	ma = isl_multi_aff_align_divs(ma);
11929	if (!map || !ma)
11930		goto error;
11931	if (check_map_compatible_range_multi_aff(map, type, ma) < 0)
11932		goto error;
11933
11934	for (i = 0; i < map->n; ++i) {
11935		map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,
11936							isl_multi_aff_copy(ma));
11937		if (!map->p[i])
11938			goto error;
11939	}
11940
11941	space = isl_multi_aff_get_domain_space(ma);
11942	space = isl_space_set(isl_map_get_space(map), type, space);
11943
11944	isl_space_free(map->dim);
11945	map->dim = space;
11946	if (!map->dim)
11947		goto error;
11948
11949	isl_multi_aff_free(ma);
11950	if (map->n > 1)
11951		ISL_F_CLR(map, ISL_MAP_DISJOINT);
11952	ISL_F_CLR(map, ISL_SET_NORMALIZED);
11953	return map;
11954error:
11955	isl_multi_aff_free(ma);
11956	isl_map_free(map);
11957	return NULL;
11958}
11959
11960/* Compute the preimage of the domain or range (depending on "type")
11961 * of "map" under the function represented by "ma".
11962 * In other words, plug in "ma" in the domain or range of "map".
11963 * The result is a map that lives in the same space as "map"
11964 * except that the domain or range has been replaced by
11965 * the domain space of "ma".
11966 */
11967__isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,
11968	enum isl_dim_type type, __isl_take isl_multi_aff *ma)
11969{
11970	if (!map || !ma)
11971		goto error;
11972
11973	if (isl_space_match(map->dim, isl_dim_param, ma->space, isl_dim_param))
11974		return map_preimage_multi_aff(map, type, ma);
11975
11976	if (!isl_space_has_named_params(map->dim) ||
11977	    !isl_space_has_named_params(ma->space))
11978		isl_die(map->ctx, isl_error_invalid,
11979			"unaligned unnamed parameters", goto error);
11980	map = isl_map_align_params(map, isl_multi_aff_get_space(ma));
11981	ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));
11982
11983	return map_preimage_multi_aff(map, type, ma);
11984error:
11985	isl_multi_aff_free(ma);
11986	return isl_map_free(map);
11987}
11988
11989/* Compute the preimage of "set" under the function represented by "ma".
11990 * In other words, plug in "ma" "set".  The result is a set
11991 * that lives in the domain space of "ma".
11992 */
11993__isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
11994	__isl_take isl_multi_aff *ma)
11995{
11996	return isl_map_preimage_multi_aff(set, isl_dim_set, ma);
11997}
11998
11999/* Compute the preimage of the domain of "map" under the function
12000 * represented by "ma".
12001 * In other words, plug in "ma" in the domain of "map".
12002 * The result is a map that lives in the same space as "map"
12003 * except that the domain has been replaced by the domain space of "ma".
12004 */
12005__isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
12006	__isl_take isl_multi_aff *ma)
12007{
12008	return isl_map_preimage_multi_aff(map, isl_dim_in, ma);
12009}
12010
12011/* Compute the preimage of "set" under the function represented by "pma".
12012 * In other words, plug in "pma" in "set.  The result is a set
12013 * that lives in the domain space of "pma".
12014 */
12015static __isl_give isl_set *set_preimage_pw_multi_aff(__isl_take isl_set *set,
12016	__isl_take isl_pw_multi_aff *pma)
12017{
12018	int i;
12019	isl_set *res;
12020
12021	if (!pma)
12022		goto error;
12023
12024	if (pma->n == 0) {
12025		isl_pw_multi_aff_free(pma);
12026		res = isl_set_empty(isl_set_get_space(set));
12027		isl_set_free(set);
12028		return res;
12029	}
12030
12031	res = isl_set_preimage_multi_aff(isl_set_copy(set),
12032					isl_multi_aff_copy(pma->p[0].maff));
12033	res = isl_set_intersect(res, isl_set_copy(pma->p[0].set));
12034
12035	for (i = 1; i < pma->n; ++i) {
12036		isl_set *res_i;
12037
12038		res_i = isl_set_preimage_multi_aff(isl_set_copy(set),
12039					isl_multi_aff_copy(pma->p[i].maff));
12040		res_i = isl_set_intersect(res_i, isl_set_copy(pma->p[i].set));
12041		res = isl_set_union(res, res_i);
12042	}
12043
12044	isl_pw_multi_aff_free(pma);
12045	isl_set_free(set);
12046	return res;
12047error:
12048	isl_pw_multi_aff_free(pma);
12049	isl_set_free(set);
12050	return NULL;
12051}
12052
12053__isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
12054	__isl_take isl_pw_multi_aff *pma)
12055{
12056	if (!set || !pma)
12057		goto error;
12058
12059	if (isl_space_match(set->dim, isl_dim_param, pma->dim, isl_dim_param))
12060		return set_preimage_pw_multi_aff(set, pma);
12061
12062	if (!isl_space_has_named_params(set->dim) ||
12063	    !isl_space_has_named_params(pma->dim))
12064		isl_die(set->ctx, isl_error_invalid,
12065			"unaligned unnamed parameters", goto error);
12066	set = isl_set_align_params(set, isl_pw_multi_aff_get_space(pma));
12067	pma = isl_pw_multi_aff_align_params(pma, isl_set_get_space(set));
12068
12069	return set_preimage_pw_multi_aff(set, pma);
12070error:
12071	isl_pw_multi_aff_free(pma);
12072	return isl_set_free(set);
12073}
12074