xref: /netbsd-src/external/mit/isl/dist/isl_power_templ.c (revision 5971e316fdea024efff6be8f03536623db06833e)
1 #include <isl_val_private.h>
2 
3 #define xFN(TYPE,NAME) TYPE ## _ ## NAME
4 #define FN(TYPE,NAME) xFN(TYPE,NAME)
5 
6 /* Helper function for isl_*_fixed_power that applies (a copy of) "map2"
7  * to the range of "map1" and returns the result.
8  *
9  * The result is coalesced in an attempt to reduce the number of disjuncts
10  * that result from repeated applications.
11  * Similarly, look for implicit equality constraints in an attempt
12  * to reduce the number of local variables that get introduced
13  * during the repeated applications.
14  */
FN(TYPE,fixed_power_apply)15 static __isl_give TYPE *FN(TYPE,fixed_power_apply)(__isl_take TYPE *map1,
16 	__isl_keep TYPE *map2)
17 {
18 	TYPE *res;
19 
20 	res = FN(TYPE,apply_range)(map1, FN(TYPE,copy)(map2));
21 	res = FN(TYPE,detect_equalities)(res);
22 	res = FN(TYPE,coalesce)(res);
23 
24 	return res;
25 }
26 
27 /* Compute the given non-zero power of "map" and return the result.
28  * If the exponent "exp" is negative, then the -exp th power of the inverse
29  * relation is computed.
30  */
FN(TYPE,fixed_power)31 __isl_give TYPE *FN(TYPE,fixed_power)(__isl_take TYPE *map, isl_int exp)
32 {
33 	isl_ctx *ctx;
34 	TYPE *res = NULL;
35 	isl_int r;
36 
37 	if (!map)
38 		return NULL;
39 
40 	ctx = FN(TYPE,get_ctx)(map);
41 	if (isl_int_is_zero(exp))
42 		isl_die(ctx, isl_error_invalid,
43 			"expecting non-zero exponent", goto error);
44 
45 	if (isl_int_is_neg(exp)) {
46 		isl_int_neg(exp, exp);
47 		map = FN(TYPE,reverse)(map);
48 		return FN(TYPE,fixed_power)(map, exp);
49 	}
50 
51 	isl_int_init(r);
52 	for (;;) {
53 		isl_int_fdiv_r(r, exp, ctx->two);
54 
55 		if (!isl_int_is_zero(r)) {
56 			if (!res)
57 				res = FN(TYPE,copy)(map);
58 			else
59 				res = FN(TYPE,fixed_power_apply)(res, map);
60 			if (!res)
61 				break;
62 		}
63 
64 		isl_int_fdiv_q(exp, exp, ctx->two);
65 		if (isl_int_is_zero(exp))
66 			break;
67 
68 		map = FN(TYPE,fixed_power_apply)(map, map);
69 	}
70 	isl_int_clear(r);
71 
72 	FN(TYPE,free)(map);
73 	return res;
74 error:
75 	FN(TYPE,free)(map);
76 	return NULL;
77 }
78 
79 /* Compute the given non-zero power of "map" and return the result.
80  * If the exponent "exp" is negative, then the -exp th power of the inverse
81  * relation is computed.
82  */
FN(TYPE,fixed_power_val)83 __isl_give TYPE *FN(TYPE,fixed_power_val)(__isl_take TYPE *map,
84 	__isl_take isl_val *exp)
85 {
86 	if (!map || !exp)
87 		goto error;
88 	if (!isl_val_is_int(exp))
89 		isl_die(FN(TYPE,get_ctx)(map), isl_error_invalid,
90 			"expecting integer exponent", goto error);
91 	map = FN(TYPE,fixed_power)(map, exp->n);
92 	isl_val_free(exp);
93 	return map;
94 error:
95 	FN(TYPE,free)(map);
96 	isl_val_free(exp);
97 	return NULL;
98 }
99