add isl_aff_mod_val
[platform/upstream/isl.git] / isl_power_templ.c
1 #define xFN(TYPE,NAME) TYPE ## _ ## NAME
2 #define FN(TYPE,NAME) xFN(TYPE,NAME)
3
4 /* Compute the given non-zero power of "map" and return the result.
5  * If the exponent "exp" is negative, then the -exp th power of the inverse
6  * relation is computed.
7  */
8 __isl_give TYPE *FN(TYPE,fixed_power)(__isl_take TYPE *map, isl_int exp)
9 {
10         isl_ctx *ctx;
11         TYPE *res = NULL;
12         isl_int r;
13
14         if (!map)
15                 return NULL;
16
17         ctx = FN(TYPE,get_ctx)(map);
18         if (isl_int_is_zero(exp))
19                 isl_die(ctx, isl_error_invalid,
20                         "expecting non-zero exponent", goto error);
21
22         if (isl_int_is_neg(exp)) {
23                 isl_int_neg(exp, exp);
24                 map = FN(TYPE,reverse)(map);
25                 return FN(TYPE,fixed_power)(map, exp);
26         }
27
28         isl_int_init(r);
29         for (;;) {
30                 isl_int_fdiv_r(r, exp, ctx->two);
31
32                 if (!isl_int_is_zero(r)) {
33                         if (!res)
34                                 res = FN(TYPE,copy)(map);
35                         else {
36                                 res = FN(TYPE,apply_range)(res,
37                                                           FN(TYPE,copy)(map));
38                                 res = FN(TYPE,coalesce)(res);
39                         }
40                         if (!res)
41                                 break;
42                 }
43
44                 isl_int_fdiv_q(exp, exp, ctx->two);
45                 if (isl_int_is_zero(exp))
46                         break;
47
48                 map = FN(TYPE,apply_range)(map, FN(TYPE,copy)(map));
49                 map = FN(TYPE,coalesce)(map);
50         }
51         isl_int_clear(r);
52
53         FN(TYPE,free)(map);
54         return res;
55 error:
56         FN(TYPE,free)(map);
57         return NULL;
58 }