add isl_aff_mod_val
[platform/upstream/isl.git] / isl_output.c
index c2541cf..a1feb7f 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright 2008-2009 Katholieke Universiteit Leuven
  * Copyright 2010      INRIA Saclay
  *
- * Use of this software is governed by the GNU LGPLv2.1 license
+ * Use of this software is governed by the MIT license
  *
  * Written by Sven Verdoolaege, K.U.Leuven, Departement
  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
@@ -24,6 +24,7 @@
 #include <isl/constraint.h>
 #include <isl_local_space_private.h>
 #include <isl_aff_private.h>
+#include <isl_ast_build_expr.h>
 
 static const char *s_to[2] = { " -> ", " \\to " };
 static const char *s_and[2] = { " and ", " \\wedge " };
@@ -315,12 +316,16 @@ static int defining_equality(__isl_keep isl_basic_map *eq,
        return -1;
 }
 
+static __isl_give isl_printer *print_aff_body(__isl_take isl_printer *p,
+       __isl_keep isl_aff *aff);
+
 /* offset is the offset of local_dim inside global_type of global_dim.
  */
 static __isl_give isl_printer *print_nested_var_list(__isl_take isl_printer *p,
        __isl_keep isl_space *global_dim, enum isl_dim_type global_type,
        __isl_keep isl_space *local_dim, enum isl_dim_type local_type,
-       int latex, __isl_keep isl_basic_map *eq, int offset)
+       int latex, __isl_keep isl_basic_map *eq,
+       __isl_keep isl_multi_aff *maff, int offset)
 {
        int i, j;
 
@@ -330,6 +335,10 @@ static __isl_give isl_printer *print_nested_var_list(__isl_take isl_printer *p,
        for (i = 0; i < isl_space_dim(local_dim, local_type); ++i) {
                if (i)
                        p = isl_printer_print_str(p, ", ");
+               if (maff && global_type == isl_dim_out) {
+                       p = print_aff_body(p, maff->p[offset + i]);
+                       continue;
+               }
                j = defining_equality(eq, global_dim, global_type, offset + i);
                if (j >= 0) {
                        int pos = 1 + isl_space_offset(global_dim, global_type)
@@ -346,20 +355,23 @@ static __isl_give isl_printer *print_nested_var_list(__isl_take isl_printer *p,
 
 static __isl_give isl_printer *print_var_list(__isl_keep isl_space *dim,
        __isl_take isl_printer *p, enum isl_dim_type type,
-       int latex, __isl_keep isl_basic_map *eq)
+       int latex, __isl_keep isl_basic_map *eq, __isl_keep isl_multi_aff *maff)
 {
-       return print_nested_var_list(p, dim, type, dim, type, latex, eq, 0);
+       return print_nested_var_list(p, dim, type, dim, type, latex,
+                                       eq, maff, 0);
 }
 
 static __isl_give isl_printer *print_nested_map_dim(__isl_take isl_printer *p,
        __isl_keep isl_space *global_dim, enum isl_dim_type global_type,
        __isl_keep isl_space *local_dim,
-       int latex, __isl_keep isl_basic_map *eq, int offset);
+       int latex, __isl_keep isl_basic_map *eq,
+       __isl_keep isl_multi_aff *maff, int offset);
 
 static __isl_give isl_printer *print_nested_tuple(__isl_take isl_printer *p,
        __isl_keep isl_space *global_dim, enum isl_dim_type global_type,
        __isl_keep isl_space *local_dim, enum isl_dim_type local_type,
-       int latex, __isl_keep isl_basic_map *eq, int offset)
+       int latex, __isl_keep isl_basic_map *eq,
+       __isl_keep isl_multi_aff *maff, int offset)
 {
        const char *name = NULL;
        unsigned n = isl_space_dim(local_dim, local_type);
@@ -381,10 +393,11 @@ static __isl_give isl_printer *print_nested_tuple(__isl_take isl_printer *p,
                        offset += local_dim->n_in;
                p = print_nested_map_dim(p, global_dim, global_type,
                                local_dim->nested[local_type - isl_dim_in],
-                               latex, eq, offset);
+                               latex, eq, maff, offset);
        } else
                p = print_nested_var_list(p, global_dim, global_type,
-                                local_dim, local_type, latex, eq, offset);
+                                         local_dim, local_type, latex,
+                                         eq, maff, offset);
        if (!latex || n != 1 || name)
                p = isl_printer_print_str(p, s_close_list[latex]);
        return p;
@@ -392,39 +405,40 @@ static __isl_give isl_printer *print_nested_tuple(__isl_take isl_printer *p,
 
 static __isl_give isl_printer *print_tuple(__isl_keep isl_space *dim,
        __isl_take isl_printer *p, enum isl_dim_type type,
-       int latex, __isl_keep isl_basic_map *eq)
+       int latex, __isl_keep isl_basic_map *eq, __isl_keep isl_multi_aff *maff)
 {
-       return print_nested_tuple(p, dim, type, dim, type, latex, eq, 0);
+       return print_nested_tuple(p, dim, type, dim, type, latex, eq, maff, 0);
 }
 
 static __isl_give isl_printer *print_nested_map_dim(__isl_take isl_printer *p,
        __isl_keep isl_space *global_dim, enum isl_dim_type global_type,
        __isl_keep isl_space *local_dim,
-       int latex, __isl_keep isl_basic_map *eq, int offset)
+       int latex, __isl_keep isl_basic_map *eq,
+       __isl_keep isl_multi_aff *maff, int offset)
 {
        p = print_nested_tuple(p, global_dim, global_type,
-                       local_dim, isl_dim_in, latex, eq, offset);
+                       local_dim, isl_dim_in, latex, eq, maff, offset);
        p = isl_printer_print_str(p, s_to[latex]);
        p = print_nested_tuple(p, global_dim, global_type,
-                       local_dim, isl_dim_out, latex, eq, offset);
+                       local_dim, isl_dim_out, latex, eq, maff, offset);
 
        return p;
 }
 
 static __isl_give isl_printer *print_space(__isl_keep isl_space *dim,
        __isl_take isl_printer *p, int latex, int rational,
-       __isl_keep isl_basic_map *eq)
+       __isl_keep isl_basic_map *eq, __isl_keep isl_multi_aff *maff)
 {
        if (rational && !latex)
                p = isl_printer_print_str(p, "rat: ");
        if (isl_space_is_params(dim))
                ;
        else if (isl_space_is_set(dim))
-               p = print_tuple(dim, p, isl_dim_set, latex, eq);
+               p = print_tuple(dim, p, isl_dim_set, latex, eq, maff);
        else {
-               p = print_tuple(dim, p, isl_dim_in, latex, eq);
+               p = print_tuple(dim, p, isl_dim_in, latex, eq, maff);
                p = isl_printer_print_str(p, s_to[latex]);
-               p = print_tuple(dim, p, isl_dim_out, latex, eq);
+               p = print_tuple(dim, p, isl_dim_out, latex, eq, maff);
        }
 
        return p;
@@ -438,7 +452,7 @@ static __isl_give isl_printer *print_omega_parameters(__isl_keep isl_space *dim,
 
        p = isl_printer_start_line(p);
        p = isl_printer_print_str(p, "symbolic ");
-       p = print_var_list(dim, p, isl_dim_param, 0, NULL);
+       p = print_var_list(dim, p, isl_dim_param, 0, NULL, NULL);
        p = isl_printer_print_str(p, ";");
        p = isl_printer_end_line(p);
        return p;
@@ -543,62 +557,36 @@ static __isl_give isl_printer *basic_map_print_omega(
        __isl_keep isl_basic_map *bmap, __isl_take isl_printer *p)
 {
        p = isl_printer_print_str(p, "{ [");
-       p = print_var_list(bmap->dim, p, isl_dim_in, 0, NULL);
+       p = print_var_list(bmap->dim, p, isl_dim_in, 0, NULL, NULL);
        p = isl_printer_print_str(p, "] -> [");
-       p = print_var_list(bmap->dim, p, isl_dim_out, 0, NULL);
+       p = print_var_list(bmap->dim, p, isl_dim_out, 0, NULL, NULL);
        p = isl_printer_print_str(p, "] ");
        p = print_omega_constraints(bmap, p);
        p = isl_printer_print_str(p, " }");
        return p;
 }
 
-static __isl_give isl_printer *isl_basic_map_print_omega(
-       __isl_keep isl_basic_map *bmap, __isl_take isl_printer *p)
-{
-       p = print_omega_parameters(bmap->dim, p);
-
-       p = isl_printer_start_line(p);
-       p = basic_map_print_omega(bmap, p);
-       p = isl_printer_end_line(p);
-       return p;
-}
-
 static __isl_give isl_printer *basic_set_print_omega(
        __isl_keep isl_basic_set *bset, __isl_take isl_printer *p)
 {
        p = isl_printer_print_str(p, "{ [");
-       p = print_var_list(bset->dim, p, isl_dim_set, 0, NULL);
+       p = print_var_list(bset->dim, p, isl_dim_set, 0, NULL, NULL);
        p = isl_printer_print_str(p, "] ");
        p = print_omega_constraints((isl_basic_map *)bset, p);
        p = isl_printer_print_str(p, " }");
        return p;
 }
 
-static __isl_give isl_printer *isl_basic_set_print_omega(
-       __isl_keep isl_basic_set *bset, __isl_take isl_printer *p)
-{
-       p = print_omega_parameters(bset->dim, p);
-
-       p = isl_printer_start_line(p);
-       p = basic_set_print_omega(bset, p);
-       p = isl_printer_end_line(p);
-       return p;
-}
-
 static __isl_give isl_printer *isl_map_print_omega(__isl_keep isl_map *map,
        __isl_take isl_printer *p)
 {
        int i;
 
-       p = print_omega_parameters(map->dim, p);
-
-       p = isl_printer_start_line(p);
        for (i = 0; i < map->n; ++i) {
                if (i)
                        p = isl_printer_print_str(p, " union ");
                p = basic_map_print_omega(map->p[i], p);
        }
-       p = isl_printer_end_line(p);
        return p;
 }
 
@@ -607,15 +595,11 @@ static __isl_give isl_printer *isl_set_print_omega(__isl_keep isl_set *set,
 {
        int i;
 
-       p = print_omega_parameters(set->dim, p);
-
-       p = isl_printer_start_line(p);
        for (i = 0; i < set->n; ++i) {
                if (i)
                        p = isl_printer_print_str(p, " union ");
                p = basic_set_print_omega(set->p[i], p);
        }
-       p = isl_printer_end_line(p);
        return p;
 }
 
@@ -653,11 +637,11 @@ static __isl_give isl_printer *isl_basic_map_print_isl(
 {
        int rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
        if (isl_basic_map_dim(bmap, isl_dim_param) > 0) {
-               p = print_tuple(bmap->dim, p, isl_dim_param, latex, NULL);
+               p = print_tuple(bmap->dim, p, isl_dim_param, latex, NULL, NULL);
                p = isl_printer_print_str(p, " -> ");
        }
        p = isl_printer_print_str(p, "{ ");
-       p = print_space(bmap->dim, p, latex, rational, NULL);
+       p = print_space(bmap->dim, p, latex, rational, NULL, NULL);
        p = isl_printer_print_str(p, " : ");
        p = print_disjunct(bmap, bmap->dim, p, latex);
        p = isl_printer_print_str(p, " }");
@@ -855,7 +839,7 @@ static __isl_give isl_printer *print_split_map(__isl_take isl_printer *p,
                    ISL_F_ISSET(split[i].map->p[0], ISL_BASIC_MAP_RATIONAL);
                if (i)
                        p = isl_printer_print_str(p, "; ");
-               p = print_space(dim, p, 0, rational, split[i].aff);
+               p = print_space(dim, p, 0, rational, split[i].aff, NULL);
                p = print_disjuncts_map(split[i].map, p, 0);
        }
 
@@ -875,7 +859,7 @@ static __isl_give isl_printer *isl_map_print_isl_body(__isl_keep isl_map *map,
        } else {
                rational = map->n > 0 &&
                    ISL_F_ISSET(map->p[0], ISL_BASIC_MAP_RATIONAL);
-               p = print_space(map->dim, p, 0, rational, NULL);
+               p = print_space(map->dim, p, 0, rational, NULL, NULL);
                p = print_disjuncts_map(map, p, 0);
        }
        free_split(split, map->n);
@@ -886,7 +870,7 @@ static __isl_give isl_printer *isl_map_print_isl(__isl_keep isl_map *map,
        __isl_take isl_printer *p)
 {
        if (isl_map_dim(map, isl_dim_param) > 0) {
-               p = print_tuple(map->dim, p, isl_dim_param, 0, NULL);
+               p = print_tuple(map->dim, p, isl_dim_param, 0, NULL, NULL);
                p = isl_printer_print_str(p, s_to[0]);
        }
        p = isl_printer_print_str(p, s_open_set[0]);
@@ -899,11 +883,11 @@ static __isl_give isl_printer *print_latex_map(__isl_keep isl_map *map,
        __isl_take isl_printer *p, __isl_keep isl_basic_map *aff)
 {
        if (isl_map_dim(map, isl_dim_param) > 0) {
-               p = print_tuple(map->dim, p, isl_dim_param, 1, NULL);
+               p = print_tuple(map->dim, p, isl_dim_param, 1, NULL, NULL);
                p = isl_printer_print_str(p, s_to[1]);
        }
        p = isl_printer_print_str(p, s_open_set[1]);
-       p = print_space(map->dim, p, 1, 0, aff);
+       p = print_space(map->dim, p, 1, 0, aff, NULL);
        p = print_disjuncts_map(map, p, 1);
        p = isl_printer_print_str(p, s_close_set[1]);
 
@@ -942,7 +926,7 @@ __isl_give isl_printer *isl_printer_print_basic_map(__isl_take isl_printer *p,
        if (p->output_format == ISL_FORMAT_ISL)
                return isl_basic_map_print_isl(bmap, p, 0);
        else if (p->output_format == ISL_FORMAT_OMEGA)
-               return isl_basic_map_print_omega(bmap, p);
+               return basic_map_print_omega(bmap, p);
        isl_assert(bmap->ctx, 0, goto error);
 error:
        isl_printer_free(p);
@@ -982,7 +966,7 @@ __isl_give isl_printer *isl_printer_print_basic_set(__isl_take isl_printer *p,
        else if (p->output_format == ISL_FORMAT_POLYLIB_CONSTRAINTS)
                return bset_print_constraints_polylib(bset, p);
        else if (p->output_format == ISL_FORMAT_OMEGA)
-               return isl_basic_set_print_omega(bset, p);
+               return basic_set_print_omega(bset, p);
        isl_assert(p->ctx, 0, goto error);
 error:
        isl_printer_free(p);
@@ -1093,7 +1077,7 @@ static __isl_give isl_printer *isl_union_map_print_isl(
        isl_space *dim;
        dim = isl_union_map_get_space(umap);
        if (isl_space_dim(dim, isl_dim_param) > 0) {
-               p = print_tuple(dim, p, isl_dim_param, 0, NULL);
+               p = print_tuple(dim, p, isl_dim_param, 0, NULL, NULL);
                p = isl_printer_print_str(p, s_to[0]);
        }
        isl_space_free(dim);
@@ -1344,12 +1328,12 @@ static __isl_give isl_printer *print_qpolynomial_isl(__isl_take isl_printer *p,
                goto error;
 
        if (isl_space_dim(qp->dim, isl_dim_param) > 0) {
-               p = print_tuple(qp->dim, p, isl_dim_param, 0, NULL);
+               p = print_tuple(qp->dim, p, isl_dim_param, 0, NULL, NULL);
                p = isl_printer_print_str(p, " -> ");
        }
        p = isl_printer_print_str(p, "{ ");
        if (!isl_space_is_params(qp->dim)) {
-               p = print_space(qp->dim, p, 0, 0, NULL);
+               p = print_space(qp->dim, p, 0, 0, NULL, NULL);
                p = isl_printer_print_str(p, " -> ");
        }
        p = print_qpolynomial(p, qp);
@@ -1463,7 +1447,7 @@ static __isl_give isl_printer *isl_pwqp_print_isl_body(
                if (i)
                        p = isl_printer_print_str(p, "; ");
                if (!isl_space_is_params(pwqp->p[i].set->dim)) {
-                       p = print_space(pwqp->p[i].set->dim, p, 0, 0, NULL);
+                       p = print_space(pwqp->p[i].set->dim, p, 0, 0, NULL, NULL);
                        p = isl_printer_print_str(p, " -> ");
                }
                p = print_qpolynomial(p, pwqp->p[i].qp);
@@ -1480,13 +1464,13 @@ static __isl_give isl_printer *print_pw_qpolynomial_isl(
                goto error;
 
        if (isl_space_dim(pwqp->dim, isl_dim_param) > 0) {
-               p = print_tuple(pwqp->dim, p, isl_dim_param, 0, NULL);
+               p = print_tuple(pwqp->dim, p, isl_dim_param, 0, NULL, NULL);
                p = isl_printer_print_str(p, " -> ");
        }
        p = isl_printer_print_str(p, "{ ");
        if (pwqp->n == 0) {
                if (!isl_space_is_set(pwqp->dim)) {
-                       p = print_tuple(pwqp->dim, p, isl_dim_in, 0, NULL);
+                       p = print_tuple(pwqp->dim, p, isl_dim_in, 0, NULL, NULL);
                        p = isl_printer_print_str(p, " -> ");
                }
                p = isl_printer_print_str(p, "0");
@@ -1523,7 +1507,7 @@ static __isl_give isl_printer *isl_pwf_print_isl_body(
                if (i)
                        p = isl_printer_print_str(p, "; ");
                if (!isl_space_is_params(pwf->p[i].set->dim)) {
-                       p = print_space(pwf->p[i].set->dim, p, 0, 0, NULL);
+                       p = print_space(pwf->p[i].set->dim, p, 0, 0, NULL, NULL);
                        p = isl_printer_print_str(p, " -> ");
                }
                p = qpolynomial_fold_print(pwf->p[i].fold, p);
@@ -1537,13 +1521,13 @@ static __isl_give isl_printer *print_pw_qpolynomial_fold_isl(
        __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf)
 {
        if (isl_space_dim(pwf->dim, isl_dim_param) > 0) {
-               p = print_tuple(pwf->dim, p, isl_dim_param, 0, NULL);
+               p = print_tuple(pwf->dim, p, isl_dim_param, 0, NULL, NULL);
                p = isl_printer_print_str(p, " -> ");
        }
        p = isl_printer_print_str(p, "{ ");
        if (pwf->n == 0) {
                if (!isl_space_is_set(pwf->dim)) {
-                       p = print_tuple(pwf->dim, p, isl_dim_in, 0, NULL);
+                       p = print_tuple(pwf->dim, p, isl_dim_in, 0, NULL, NULL);
                        p = isl_printer_print_str(p, " -> ");
                }
                p = isl_printer_print_str(p, "0");
@@ -1635,10 +1619,22 @@ static __isl_give isl_printer *print_affine_c(__isl_take isl_printer *p,
        return print_partial_affine_c(p, dim, bset, c, len);
 }
 
+/* We skip the constraint if it is implied by the div expression.
+ */
 static __isl_give isl_printer *print_constraint_c(__isl_take isl_printer *p,
        __isl_keep isl_space *dim,
        __isl_keep isl_basic_set *bset, isl_int *c, const char *op, int first)
 {
+       unsigned o_div;
+       unsigned n_div;
+       int div;
+
+       o_div = isl_basic_set_offset(bset, isl_dim_div);
+       n_div = isl_basic_set_dim(bset, isl_dim_div);
+       div = isl_seq_last_non_zero(c + o_div, n_div);
+       if (div >= 0 && isl_basic_set_is_div_constraint(bset, c, div))
+               return p;
+
        if (!first)
                p = isl_printer_print_str(p, " && ");
 
@@ -1684,6 +1680,9 @@ static __isl_give isl_printer *print_set_c(__isl_take isl_printer *p,
 {
        int i;
 
+       if (!set)
+               return isl_printer_free(p);
+
        if (set->n == 0)
                p = isl_printer_print_str(p, "0");
 
@@ -1757,7 +1756,7 @@ static __isl_give isl_printer *print_union_pw_qpolynomial_isl(
        isl_space *dim;
        dim = isl_union_pw_qpolynomial_get_space(upwqp);
        if (isl_space_dim(dim, isl_dim_param) > 0) {
-               p = print_tuple(dim, p, isl_dim_param, 0, NULL);
+               p = print_tuple(dim, p, isl_dim_param, 0, NULL, NULL);
                p = isl_printer_print_str(p, " -> ");
        }
        isl_space_free(dim);
@@ -1897,7 +1896,7 @@ static __isl_give isl_printer *print_union_pw_qpolynomial_fold_isl(
        isl_space *dim;
        dim = isl_union_pw_qpolynomial_fold_get_space(upwf);
        if (isl_space_dim(dim, isl_dim_param) > 0) {
-               p = print_tuple(dim, p, isl_dim_param, 0, NULL);
+               p = print_tuple(dim, p, isl_dim_param, 0, NULL, NULL);
                p = isl_printer_print_str(p, " -> ");
        }
        isl_space_free(dim);
@@ -1943,14 +1942,14 @@ error:
        return NULL;
 }
 
-__isl_give isl_printer *isl_printer_print_space(__isl_take isl_printer *p,
-       __isl_keep isl_space *dim)
+static __isl_give isl_printer *isl_printer_print_space_isl(
+       __isl_take isl_printer *p, __isl_keep isl_space *dim)
 {
        if (!dim)
                goto error;
 
        if (isl_space_dim(dim, isl_dim_param) > 0) {
-               p = print_tuple(dim, p, isl_dim_param, 0, NULL);
+               p = print_tuple(dim, p, isl_dim_param, 0, NULL, NULL);
                p = isl_printer_print_str(p, " -> ");
        }
 
@@ -1958,7 +1957,7 @@ __isl_give isl_printer *isl_printer_print_space(__isl_take isl_printer *p,
        if (isl_space_is_params(dim))
                p = isl_printer_print_str(p, s_such_that[0]);
        else
-               p = print_space(dim, p, 0, 0, NULL);
+               p = print_space(dim, p, 0, 0, NULL, NULL);
        p = isl_printer_print_str(p, " }");
 
        return p;
@@ -1967,6 +1966,21 @@ error:
        return NULL;
 }
 
+__isl_give isl_printer *isl_printer_print_space(__isl_take isl_printer *p,
+       __isl_keep isl_space *space)
+{
+       if (!p || !space)
+               return isl_printer_free(p);
+       if (p->output_format == ISL_FORMAT_ISL)
+               return isl_printer_print_space_isl(p, space);
+       else if (p->output_format == ISL_FORMAT_OMEGA)
+               return print_omega_parameters(space, p);
+
+       isl_die(isl_space_get_ctx(space), isl_error_unsupported,
+               "output format not supported for space",
+               return isl_printer_free(p));
+}
+
 __isl_give isl_printer *isl_printer_print_local_space(__isl_take isl_printer *p,
        __isl_keep isl_local_space *ls)
 {
@@ -1978,11 +1992,11 @@ __isl_give isl_printer *isl_printer_print_local_space(__isl_take isl_printer *p,
 
        total = isl_local_space_dim(ls, isl_dim_all);
        if (isl_local_space_dim(ls, isl_dim_param) > 0) {
-               p = print_tuple(ls->dim, p, isl_dim_param, 0, NULL);
+               p = print_tuple(ls->dim, p, isl_dim_param, 0, NULL, NULL);
                p = isl_printer_print_str(p, " -> ");
        }
        p = isl_printer_print_str(p, "{ ");
-       p = print_space(ls->dim, p, 0, 0, NULL);
+       p = print_space(ls->dim, p, 0, 0, NULL, NULL);
        n_div = isl_local_space_dim(ls, isl_dim_div);
        if (n_div > 0) {
                int i;
@@ -2010,19 +2024,12 @@ error:
        return NULL;
 }
 
-static __isl_give isl_printer *print_aff(__isl_take isl_printer *p,
+static __isl_give isl_printer *print_aff_body(__isl_take isl_printer *p,
        __isl_keep isl_aff *aff)
 {
        unsigned total;
 
        total = isl_local_space_dim(aff->ls, isl_dim_all);
-       if (isl_space_is_params(aff->ls->dim))
-               ;
-       else {
-               p = print_tuple(aff->ls->dim, p, isl_dim_set, 0, NULL);
-               p = isl_printer_print_str(p, " -> ");
-       }
-       p = isl_printer_print_str(p, "[");
        p = isl_printer_print_str(p, "(");
        p = print_affine_of_len(aff->ls->dim, aff->ls->div, p,
                                aff->v->el + 1, 1 + total);
@@ -2032,6 +2039,21 @@ static __isl_give isl_printer *print_aff(__isl_take isl_printer *p,
                p = isl_printer_print_str(p, ")/");
                p = isl_printer_print_isl_int(p, aff->v->el[0]);
        }
+
+       return p;
+}
+
+static __isl_give isl_printer *print_aff(__isl_take isl_printer *p,
+       __isl_keep isl_aff *aff)
+{
+       if (isl_space_is_params(aff->ls->dim))
+               ;
+       else {
+               p = print_tuple(aff->ls->dim, p, isl_dim_set, 0, NULL, NULL);
+               p = isl_printer_print_str(p, " -> ");
+       }
+       p = isl_printer_print_str(p, "[");
+       p = print_aff_body(p, aff);
        p = isl_printer_print_str(p, "]");
 
        return p;
@@ -2044,7 +2066,7 @@ static __isl_give isl_printer *print_aff_isl(__isl_take isl_printer *p,
                goto error;
 
        if (isl_local_space_dim(aff->ls, isl_dim_param) > 0) {
-               p = print_tuple(aff->ls->dim, p, isl_dim_param, 0, NULL);
+               p = print_tuple(aff->ls->dim, p, isl_dim_param, 0, NULL, NULL);
                p = isl_printer_print_str(p, " -> ");
        }
        p = isl_printer_print_str(p, "{ ");
@@ -2065,7 +2087,7 @@ static __isl_give isl_printer *print_pw_aff_isl(__isl_take isl_printer *p,
                goto error;
 
        if (isl_space_dim(pwaff->dim, isl_dim_param) > 0) {
-               p = print_tuple(pwaff->dim, p, isl_dim_param, 0, NULL);
+               p = print_tuple(pwaff->dim, p, isl_dim_param, 0, NULL, NULL);
                p = isl_printer_print_str(p, " -> ");
        }
        p = isl_printer_print_str(p, "{ ");
@@ -2168,35 +2190,82 @@ static __isl_give isl_printer *print_aff_c(__isl_take isl_printer *p,
        unsigned total;
 
        total = isl_local_space_dim(aff->ls, isl_dim_all);
-       p = isl_printer_print_str(p, "(");
+       if (!isl_int_is_one(aff->v->el[0]))
+               p = isl_printer_print_str(p, "(");
        p = print_ls_partial_affine_c(p, aff->ls, aff->v->el + 1, 1 + total);
-       if (isl_int_is_one(aff->v->el[0]))
-               p = isl_printer_print_str(p, ")");
-       else {
+       if (!isl_int_is_one(aff->v->el[0])) {
                p = isl_printer_print_str(p, ")/");
                p = isl_printer_print_isl_int(p, aff->v->el[0]);
        }
        return p;
 }
 
+/* Print the affine expression "aff" in C format to "p".
+ * The dimension names are taken from "space"
+ * "set" represents the domain of the affine expression.
+ */
+static __isl_give isl_printer *print_aff_on_domain_c(__isl_take isl_printer *p,
+       __isl_keep isl_space *space, __isl_keep isl_aff *aff,
+       __isl_keep isl_set *set)
+{
+       isl_set *u;
+       isl_ast_build *build;
+       isl_ast_expr *expr;
+
+       u = isl_set_universe(isl_space_copy(space));
+       build = isl_ast_build_from_context(u);
+       build = isl_ast_build_restrict(build, isl_set_copy(set));
+       expr = isl_ast_expr_from_aff(isl_aff_copy(aff), build);
+       p = isl_printer_print_ast_expr(p, expr);
+       isl_ast_expr_free(expr);
+       isl_ast_build_free(build);
+
+       return p;
+}
+
+/* In the C format, we cannot express that "pwaff" may be undefined
+ * on parts of the domain space.  We therefore assume that the expression
+ * will only be evaluated on its definition domain and compute the gist
+ * of each cell with respect to this domain.
+ */
 static __isl_give isl_printer *print_pw_aff_c(__isl_take isl_printer *p,
        __isl_keep isl_pw_aff *pwaff)
 {
        int i;
+       isl_set *domain;
+       isl_space *space;
 
        if (pwaff->n < 1)
                isl_die(p->ctx, isl_error_unsupported,
                        "cannot print empty isl_pw_aff in C format", goto error);
+       space = isl_pw_aff_get_domain_space(pwaff);
+       if (!space)
+               goto error;
+
+       domain = isl_pw_aff_domain(isl_pw_aff_copy(pwaff));
 
        for (i = 0; i < pwaff->n - 1; ++i) {
+               isl_set *set_i;
+
                p = isl_printer_print_str(p, "(");
-               p = print_set_c(p, pwaff->dim, pwaff->p[i].set);
+
+               set_i = isl_set_copy(pwaff->p[i].set);
+               set_i = isl_set_gist(set_i, isl_set_copy(domain));
+               p = print_set_c(p, space, set_i);
+               isl_set_free(set_i);
+
                p = isl_printer_print_str(p, ") ? (");
-               p = print_aff_c(p, pwaff->p[i].aff);
+               p = print_aff_on_domain_c(p, space,
+                                       pwaff->p[i].aff, pwaff->p[i].set);
                p = isl_printer_print_str(p, ") : ");
        }
 
-       return print_aff_c(p, pwaff->p[pwaff->n - 1].aff);
+       isl_set_free(domain);
+
+       p = print_aff_on_domain_c(p, space, pwaff->p[pwaff->n - 1].aff,
+                                       pwaff->p[pwaff->n - 1].set);
+       isl_space_free(space);
+       return p;
 error:
        isl_printer_free(p);
        return NULL;
@@ -2235,3 +2304,228 @@ error:
        isl_printer_free(p);
        return NULL;
 }
+
+static __isl_give isl_printer *print_multi_aff(__isl_take isl_printer *p,
+       __isl_keep isl_multi_aff *maff)
+{
+       return print_space(maff->space, p, 0, 0, NULL, maff);
+}
+
+static __isl_give isl_printer *print_multi_aff_isl(__isl_take isl_printer *p,
+       __isl_keep isl_multi_aff *maff)
+{
+       if (!maff)
+               goto error;
+
+       if (isl_space_dim(maff->space, isl_dim_param) > 0) {
+               p = print_tuple(maff->space, p, isl_dim_param, 0, NULL, NULL);
+               p = isl_printer_print_str(p, " -> ");
+       }
+       p = isl_printer_print_str(p, "{ ");
+       p = print_multi_aff(p, maff);
+       p = isl_printer_print_str(p, " }");
+       return p;
+error:
+       isl_printer_free(p);
+       return NULL;
+}
+
+__isl_give isl_printer *isl_printer_print_multi_aff(__isl_take isl_printer *p,
+       __isl_keep isl_multi_aff *maff)
+{
+       if (!p || !maff)
+               goto error;
+
+       if (p->output_format == ISL_FORMAT_ISL)
+               return print_multi_aff_isl(p, maff);
+       isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
+               goto error);
+error:
+       isl_printer_free(p);
+       return NULL;
+}
+
+static __isl_give isl_printer *print_pw_multi_aff_body(
+       __isl_take isl_printer *p, __isl_keep isl_pw_multi_aff *pma)
+{
+       int i;
+
+       if (!pma)
+               goto error;
+
+       for (i = 0; i < pma->n; ++i) {
+               if (i)
+                       p = isl_printer_print_str(p, "; ");
+               p = print_multi_aff(p, pma->p[i].maff);
+               p = print_disjuncts((isl_map *)pma->p[i].set, p, 0);
+       }
+       return p;
+error:
+       isl_printer_free(p);
+       return NULL;
+}
+
+static __isl_give isl_printer *print_pw_multi_aff_isl(__isl_take isl_printer *p,
+       __isl_keep isl_pw_multi_aff *pma)
+{
+       if (!pma)
+               goto error;
+
+       if (isl_space_dim(pma->dim, isl_dim_param) > 0) {
+               p = print_tuple(pma->dim, p, isl_dim_param, 0, NULL, NULL);
+               p = isl_printer_print_str(p, " -> ");
+       }
+       p = isl_printer_print_str(p, "{ ");
+       p = print_pw_multi_aff_body(p, pma);
+       p = isl_printer_print_str(p, " }");
+       return p;
+error:
+       isl_printer_free(p);
+       return NULL;
+}
+
+static __isl_give isl_printer *print_unnamed_pw_multi_aff_c(
+       __isl_take isl_printer *p, __isl_keep isl_pw_multi_aff *pma)
+{
+       int i;
+
+       for (i = 0; i < pma->n - 1; ++i) {
+               p = isl_printer_print_str(p, "(");
+               p = print_set_c(p, pma->dim, pma->p[i].set);
+               p = isl_printer_print_str(p, ") ? (");
+               p = print_aff_c(p, pma->p[i].maff->p[0]);
+               p = isl_printer_print_str(p, ") : ");
+       }
+
+       return print_aff_c(p, pma->p[pma->n - 1].maff->p[0]);
+}
+
+static __isl_give isl_printer *print_pw_multi_aff_c(__isl_take isl_printer *p,
+       __isl_keep isl_pw_multi_aff *pma)
+{
+       int n;
+       const char *name;
+
+       if (!pma)
+               goto error;
+       if (pma->n < 1)
+               isl_die(p->ctx, isl_error_unsupported,
+                       "cannot print empty isl_pw_multi_aff in C format",
+                       goto error);
+       name = isl_pw_multi_aff_get_tuple_name(pma, isl_dim_out);
+       if (!name && isl_pw_multi_aff_dim(pma, isl_dim_out) == 1)
+               return print_unnamed_pw_multi_aff_c(p, pma);
+       if (!name)
+               isl_die(p->ctx, isl_error_unsupported,
+                       "cannot print unnamed isl_pw_multi_aff in C format",
+                       goto error);
+
+       p = isl_printer_print_str(p, name);
+       n = isl_pw_multi_aff_dim(pma, isl_dim_out);
+       if (n != 0)
+               isl_die(p->ctx, isl_error_unsupported,
+                       "not supported yet", goto error);
+
+       return p;
+error:
+       isl_printer_free(p);
+       return NULL;
+}
+
+__isl_give isl_printer *isl_printer_print_pw_multi_aff(
+       __isl_take isl_printer *p, __isl_keep isl_pw_multi_aff *pma)
+{
+       if (!p || !pma)
+               goto error;
+
+       if (p->output_format == ISL_FORMAT_ISL)
+               return print_pw_multi_aff_isl(p, pma);
+       if (p->output_format == ISL_FORMAT_C)
+               return print_pw_multi_aff_c(p, pma);
+       isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
+               goto error);
+error:
+       isl_printer_free(p);
+       return NULL;
+}
+
+static int print_pw_multi_aff_body_wrap(__isl_take isl_pw_multi_aff *pma,
+       void *user)
+{
+       struct isl_union_print_data *data;
+       data = (struct isl_union_print_data *) user;
+
+       if (!data->first)
+               data->p = isl_printer_print_str(data->p, "; ");
+       data->first = 0;
+
+       data->p = print_pw_multi_aff_body(data->p, pma);
+       isl_pw_multi_aff_free(pma);
+
+       return 0;
+}
+
+static __isl_give isl_printer *print_union_pw_multi_aff_isl(
+       __isl_take isl_printer *p, __isl_keep isl_union_pw_multi_aff *upma)
+{
+       struct isl_union_print_data data = { p, 1 };
+       isl_space *space;
+
+       space = isl_union_pw_multi_aff_get_space(upma);
+       if (isl_space_dim(space, isl_dim_param) > 0) {
+               p = print_tuple(space, p, isl_dim_param, 0, NULL, NULL);
+               p = isl_printer_print_str(p, s_to[0]);
+       }
+       isl_space_free(space);
+       p = isl_printer_print_str(p, s_open_set[0]);
+       isl_union_pw_multi_aff_foreach_pw_multi_aff(upma,
+                                       &print_pw_multi_aff_body_wrap, &data);
+       p = data.p;
+       p = isl_printer_print_str(p, s_close_set[0]);
+       return p;
+}
+
+__isl_give isl_printer *isl_printer_print_union_pw_multi_aff(
+       __isl_take isl_printer *p, __isl_keep isl_union_pw_multi_aff *upma)
+{
+       if (!p || !upma)
+               goto error;
+
+       if (p->output_format == ISL_FORMAT_ISL)
+               return print_union_pw_multi_aff_isl(p, upma);
+       isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
+               goto error);
+error:
+       isl_printer_free(p);
+       return NULL;
+}
+
+static __isl_give isl_printer *print_multi_pw_aff_isl(__isl_take isl_printer *p,
+       __isl_keep isl_multi_pw_aff *mpa)
+{
+       int i;
+
+       if (!mpa)
+               return isl_printer_free(p);
+
+       p = isl_printer_print_str(p, "(");
+       for (i = 0; i < mpa->n; ++i) {
+               if (i)
+                       p = isl_printer_print_str(p, ",");
+               p = isl_printer_print_pw_aff(p, mpa->p[i]);
+       }
+       p = isl_printer_print_str(p, ")");
+       return p;
+}
+
+__isl_give isl_printer *isl_printer_print_multi_pw_aff(
+       __isl_take isl_printer *p, __isl_keep isl_multi_pw_aff *mpa)
+{
+       if (!p || !mpa)
+               return isl_printer_free(p);
+
+       if (p->output_format == ISL_FORMAT_ISL)
+               return print_multi_pw_aff_isl(p, mpa);
+       isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
+               return isl_printer_free(p));
+}