/* * Copyright 2010 INRIA Saclay * Copyright 2013 Ecole Normale Superieure * * Use of this software is governed by the MIT license * * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France, * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod, * 91893 Orsay, France * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France */ #undef TYPE #define TYPE … static #include "has_single_reference_templ.c" __isl_give UNION *FN(UNION,cow)(__isl_take UNION *u); isl_ctx *FN(UNION,get_ctx)(__isl_keep UNION *u) { … } /* Return the space of "u". */ static __isl_keep isl_space *FN(UNION,peek_space)(__isl_keep UNION *u) { … } /* Return a copy of the space of "u". */ __isl_give isl_space *FN(UNION,get_space)(__isl_keep UNION *u) { … } /* Return the number of parameters of "u", where "type" * is required to be set to isl_dim_param. */ isl_size FN(UNION,dim)(__isl_keep UNION *u, enum isl_dim_type type) { … } /* Return the position of the parameter with the given name * in "u". * Return -1 if no such dimension can be found. */ int FN(UNION,find_dim_by_name)(__isl_keep UNION *u, enum isl_dim_type type, const char *name) { … } #include "opt_type.h" static __isl_give UNION *FN(UNION,alloc)(__isl_take isl_space *space OPT_TYPE_PARAM, int size) { … } /* Create an empty/zero union without specifying any parameters. */ __isl_give UNION *FN(FN(UNION,ZERO),ctx)(isl_ctx *ctx OPT_TYPE_PARAM) { … } __isl_give UNION *FN(FN(UNION,ZERO),space)(__isl_take isl_space *space OPT_TYPE_PARAM) { … } /* This is an alternative name for the function above. */ __isl_give UNION *FN(UNION,ZERO)(__isl_take isl_space *space OPT_TYPE_PARAM) { … } __isl_give UNION *FN(UNION,copy)(__isl_keep UNION *u) { … } /* Do the tuples of "space" correspond to those of the domain of "part"? * That is, is the domain space of "part" equal to "space", ignoring parameters? */ static isl_bool FN(PART,has_domain_space_tuples)(__isl_keep PART *part, __isl_keep isl_space *space) { … } /* Extract the element of "u" living in "space" (ignoring parameters). * * Return the ZERO element if "u" does not contain any element * living in "space". */ __isl_give PART *FN(FN(UNION,extract),BASE)(__isl_keep UNION *u, __isl_take isl_space *space) { … } /* Add "part" to "u". * If "disjoint" is set, then "u" is not allowed to already have * a part that is defined over a domain that overlaps with the domain * of "part". * Otherwise, compute the union sum of "part" and the part in "u" * defined on the same space. */ static __isl_give UNION *FN(UNION,add_part_generic)(__isl_take UNION *u, __isl_take PART *part, int disjoint) { … } /* Add "part" to "u", where "u" is assumed not to already have * a part that is defined on the same space as "part". */ __isl_give UNION *FN(FN(UNION,add),BASE)(__isl_take UNION *u, __isl_take PART *part) { … } /* Allocate a UNION with the same type (if any) and the same size as "u" and * with space "space". */ static __isl_give UNION *FN(UNION,alloc_same_size_on_space)(__isl_keep UNION *u, __isl_take isl_space *space) { … } /* Allocate a UNION with the same space, the same type (if any) and * the same size as "u". */ static __isl_give UNION *FN(UNION,alloc_same_size)(__isl_keep UNION *u) { … } /* Data structure that specifies how isl_union_*_transform * should modify the base expressions in the union expression. * * If "inplace" is set, then the base expression in the input union * are modified in place. This means that "fn" should not * change the meaning of the union or that the union only * has a single reference. * If "space" is not NULL, then a new union is created in this space. * If "filter" is not NULL, then only the base expressions that satisfy "filter" * are taken into account. * "filter_user" is passed as the second argument to "filter". * If "fn" it not NULL, then it is applied to each entry in the input. * "fn_user" is passed as the second argument to "fn". */ S(UNION,transform_control) { … }; /* Internal data structure for isl_union_*_transform_space. * "control" specifies how the base expressions should be modified. * "res" collects the results (if control->inplace is not set). */ S(UNION,transform_data) { … }; /* Apply control->fn to "part" and add the result to data->res or * place it back into the input union if control->inplace is set. */ static isl_stat FN(UNION,transform_entry)(void **entry, void *user) { … } /* Return a UNION that is obtained by modifying "u" according to "control". */ static __isl_give UNION *FN(UNION,transform)(__isl_take UNION *u, S(UNION,transform_control) *control) { … } /* Return a UNION living in "space" that is otherwise obtained by modifying "u" * according to "control". */ static __isl_give UNION *FN(UNION,transform_space)(__isl_take UNION *u, __isl_take isl_space *space, S(UNION,transform_control) *control) { … } /* Update "u" by applying "fn" to each entry. * This operation is assumed not to change the number of entries nor * the spaces of the entries. * * If there is only one reference to "u", then change "u" inplace. * Otherwise, create a new UNION from "u" and discard the original. */ static __isl_give UNION *FN(UNION,transform_inplace)(__isl_take UNION *u, __isl_give PART *(*fn)(__isl_take PART *part, void *user), void *user) { … } /* An isl_union_*_transform callback for use in isl_union_*_dup * that simply returns "part". */ static __isl_give PART *FN(UNION,copy_part)(__isl_take PART *part, void *user) { … } __isl_give UNION *FN(UNION,dup)(__isl_keep UNION *u) { … } __isl_give UNION *FN(UNION,cow)(__isl_take UNION *u) { … } __isl_null UNION *FN(UNION,free)(__isl_take UNION *u) { … } static __isl_give PART *FN(UNION,align_entry)(__isl_take PART *part, void *user) { … } /* Reorder the parameters of "u" according to the given reordering. */ static __isl_give UNION *FN(UNION,realign_domain)(__isl_take UNION *u, __isl_take isl_reordering *r) { … } /* Align the parameters of "u" to those of "model". */ __isl_give UNION *FN(UNION,align_params)(__isl_take UNION *u, __isl_take isl_space *model) { … } /* Add "part" to *u, taking the union sum if "u" already has * a part defined on the same space as "part". */ static isl_stat FN(UNION,union_add_part)(__isl_take PART *part, void *user) { … } /* Compute the sum of "u1" and "u2" on the union of their domains, * with the actual sum on the shared domain and * the defined expression on the symmetric difference of the domains. * * This is an internal function that is exposed under different * names depending on whether the base expressions have a zero default * value. * If they do, then this function is called "add". * Otherwise, it is called "union_add". */ static __isl_give UNION *FN(UNION,union_add_)(__isl_take UNION *u1, __isl_take UNION *u2) { … } #if !DEFAULT_IS_ZERO /* Compute the sum of "u1" and "u2" on the union of their domains, * with the actual sum on the shared domain and * the defined expression on the symmetric difference of the domains. */ __isl_give UNION *FN(UNION,union_add)(__isl_take UNION *u1, __isl_take UNION *u2) { … } #endif __isl_give UNION *FN(FN(UNION,from),BASE)(__isl_take PART *part) { … } /* This function performs the same operation as isl_union_pw_*_from_pw_*, * but is considered as a function on an isl_pw_* when exported. */ __isl_give UNION *FN(FN(PART,to_union),BASE)(__isl_take PART *part) { … } S(UNION,match_bin_data) { … }; /* Check if data->u2 has an element living in the same space as "part". * If so, call data->fn on the two elements and add the result to * data->res. */ static isl_stat FN(UNION,match_bin_entry)(__isl_take PART *part, void *user) { … } /* This function is currently only used from isl_polynomial.c * and not from isl_fold.c. */ static __isl_give UNION *FN(UNION,match_bin_op)(__isl_take UNION *u1, __isl_take UNION *u2, __isl_give PART *(*fn)(__isl_take PART *, __isl_take PART *)) __attribute__ ((unused)); /* For each pair of elements in "u1" and "u2" living in the same space, * call "fn" and collect the results. */ static __isl_give UNION *FN(UNION,match_bin_op)(__isl_take UNION *u1, __isl_take UNION *u2, __isl_give PART *(*fn)(__isl_take PART *, __isl_take PART *)) { … } /* Compute the sum of "u1" and "u2". * * If the base expressions have a default zero value, then the sum * is computed on the union of the domains of "u1" and "u2". * Otherwise, it is computed on their shared domains. */ __isl_give UNION *FN(UNION,add)(__isl_take UNION *u1, __isl_take UNION *u2) { … } S(UNION,any_set_data) { … }; static __isl_give PART *FN(UNION,any_set_entry)(__isl_take PART *part, void *user) { … } /* Update each element of "u" by calling "fn" on the element and "set". */ static __isl_give UNION *FN(UNION,any_set_op)(__isl_take UNION *u, __isl_take isl_set *set, __isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*)) { … } /* Intersect the domain of "u" with the parameter domain "context". */ __isl_give UNION *FN(UNION,intersect_params)(__isl_take UNION *u, __isl_take isl_set *set) { … } /* Compute the gist of the domain of "u" with respect to * the parameter domain "context". */ __isl_give UNION *FN(UNION,gist_params)(__isl_take UNION *u, __isl_take isl_set *set) { … } /* Data structure that specifies how isl_union_*_match_domain_op * should combine its arguments. * * If "filter" is not NULL, then only parts that pass the given * filter are considered for matching. * "fn" is applied to each part in the union and each corresponding * set in the union set, i.e., such that the set lives in the same space * as the domain of the part. * If "match_space" is not NULL, then the set extracted from the union set * does not live in the same space as the domain of the part, * but rather in the space that results from calling "match_space" * on this domain space. */ S(UNION,match_domain_control) { … }; S(UNION,match_domain_data) { … }; /* Find the set in data->uset that lives in the same space as the domain * of "part" (ignoring parameters), apply data->fn to *entry and this set * (if any), and add the result to data->res. */ static isl_stat FN(UNION,match_domain_entry)(__isl_take PART *part, void *user) { … } /* Combine "u" and "uset" according to "control" * and collect the results. */ static __isl_give UNION *FN(UNION,match_domain_op)(__isl_take UNION *u, __isl_take isl_union_set *uset, S(UNION,match_domain_control) *control) { … } /* Intersect the domain of "u" with "uset". * If "uset" is a parameters domain, then intersect the parameter * domain of "u" with this set. */ __isl_give UNION *FN(UNION,intersect_domain_union_set)(__isl_take UNION *u, __isl_take isl_union_set *uset) { … } /* This is an alternative name for the function above. */ __isl_give UNION *FN(UNION,intersect_domain)(__isl_take UNION *u, __isl_take isl_union_set *uset) { … } /* Return true if this part should be kept. * * In particular, it should be kept if its domain space * corresponds to "space". */ static isl_bool FN(UNION,select_entry)(__isl_keep PART *part, void *user) { … } /* Remove any not element in "space" from the domain of "u". * * In particular, select any part of the function defined * on this domain space. */ __isl_give UNION *FN(UNION,intersect_domain_space)(__isl_take UNION *u, __isl_take isl_space *space) { … } /* Is the domain of "pw" a wrapped relation? */ static isl_bool FN(PW,domain_is_wrapping)(__isl_keep PW *pw) { … } /* Intersect the domain of the wrapped relation inside the domain of "u" * with "uset". */ __isl_give UNION *FN(UNION,intersect_domain_wrapped_domain)(__isl_take UNION *u, __isl_take isl_union_set *uset) { … } /* Intersect the range of the wrapped relation inside the domain of "u" * with "uset". */ __isl_give UNION *FN(UNION,intersect_domain_wrapped_range)(__isl_take UNION *u, __isl_take isl_union_set *uset) { … } /* Take the set (which may be empty) in data->uset that lives * in the same space as the domain of "pw", subtract it from the domain * of "part" and return the result. */ static __isl_give PART *FN(UNION,subtract_domain_entry)(__isl_take PART *part, void *user) { … } /* Subtract "uset" from the domain of "u". */ __isl_give UNION *FN(UNION,subtract_domain_union_set)(__isl_take UNION *u, __isl_take isl_union_set *uset) { … } /* This is an alternative name for the function above. */ __isl_give UNION *FN(UNION,subtract_domain)(__isl_take UNION *u, __isl_take isl_union_set *uset) { … } /* Return true if this part should be kept. * * In particular, it should be kept if its domain space * does not correspond to "space". */ static isl_bool FN(UNION,filter_out_entry)(__isl_keep PART *part, void *user) { … } /* Remove any element in "space" from the domain of "u". * * In particular, filter out any part of the function defined * on this domain space. */ __isl_give UNION *FN(UNION,subtract_domain_space)(__isl_take UNION *u, __isl_take isl_space *space) { … } __isl_give UNION *FN(UNION,gist)(__isl_take UNION *u, __isl_take isl_union_set *uset) { … } /* Coalesce an entry in a UNION. Coalescing is performed in-place. * Since the UNION may have several references, the entry is only * replaced if the coalescing is successful. */ static isl_stat FN(UNION,coalesce_entry)(void **entry, void *user) { … } __isl_give UNION *FN(UNION,coalesce)(__isl_take UNION *u) { … } static isl_stat FN(UNION,domain_entry)(__isl_take PART *part, void *user) { … } __isl_give isl_union_set *FN(UNION,domain)(__isl_take UNION *u) { … } #ifdef HAS_TYPE /* Negate the type of "u". */ static __isl_give UNION *FN(UNION,negate_type)(__isl_take UNION *u) { u = FN(UNION,cow)(u); if (!u) return NULL; u->type = isl_fold_type_negate(u->type); return u; } #else /* Negate the type of "u". * Since "u" does not have a type, do nothing. */ static __isl_give UNION *FN(UNION,negate_type)(__isl_take UNION *u) { … } #endif /* Multiply "part" by the isl_val "user" and return the result. */ static __isl_give PART *FN(UNION,scale_val_entry)(__isl_take PART *part, void *user) { … } /* Multiply "u" by "v" and return the result. */ __isl_give UNION *FN(UNION,scale_val)(__isl_take UNION *u, __isl_take isl_val *v) { … } /* Divide "part" by the isl_val "user" and return the result. */ static __isl_give PART *FN(UNION,scale_down_val_entry)(__isl_take PART *part, void *user) { … } /* Divide "u" by "v" and return the result. */ __isl_give UNION *FN(UNION,scale_down_val)(__isl_take UNION *u, __isl_take isl_val *v) { … } /* Internal data structure for isl_union_*_every_*. * * "test" is the user-specified callback function. * "user" is the user-specified callback function argument. * * "res" is the final result, initialized to isl_bool_true. */ S(UNION,every_data) { … }; /* Call data->test on the piecewise expression at *entry, * updating the result in data->res. * Abort if this result is no longer isl_bool_true. */ static isl_stat FN(UNION,every_entry)(void **entry, void *user) { … } /* Does "test" succeed on every piecewise expression in "u"? */ isl_bool FN(FN(UNION,every),BASE)(__isl_keep UNION *u, isl_bool (*test)(__isl_keep PW *pw, void *user), void *user) { … } S(UNION,plain_is_equal_data) { … }; static isl_bool FN(UNION,plain_is_equal_el)(__isl_keep PW *pw, void *user) { … } isl_bool FN(UNION,plain_is_equal)(__isl_keep UNION *u1, __isl_keep UNION *u2) { … } /* An isl_union_*_every_* callback that checks whether "pw" * does not involve any NaNs. */ static isl_bool FN(UNION,no_nan_el)(__isl_keep PW *pw, void *user) { … } /* Does "u" involve any NaNs? */ isl_bool FN(UNION,involves_nan)(__isl_keep UNION *u) { … } /* Internal data structure for isl_union_*_drop_dims. * type, first and n are passed to isl_*_drop_dims. */ S(UNION,drop_dims_data) { … }; /* Drop the parameters specified by "data" from "part" and return the result. */ static __isl_give PART *FN(UNION,drop_dims_entry)(__isl_take PART *part, void *user) { … } /* Drop the specified parameters from "u". * That is, type is required to be isl_dim_param. */ __isl_give UNION *FN(UNION,drop_dims)( __isl_take UNION *u, enum isl_dim_type type, unsigned first, unsigned n) { … } /* Internal data structure for isl_union_*_set_dim_name. * pos is the position of the parameter that needs to be renamed. * s is the new name. */ S(UNION,set_dim_name_data) { … }; /* Change the name of the parameter at position data->pos of "part" to data->s * and return the result. */ static __isl_give PART *FN(UNION,set_dim_name_entry)(__isl_take PART *part, void *user) { … } /* Change the name of the parameter at position "pos" to "s". * That is, type is required to be isl_dim_param. */ __isl_give UNION *FN(UNION,set_dim_name)(__isl_take UNION *u, enum isl_dim_type type, unsigned pos, const char *s) { … } /* Reset the user pointer on all identifiers of parameters and tuples * of the space of "part" and return the result. */ static __isl_give PART *FN(UNION,reset_user_entry)(__isl_take PART *part, void *user) { … } /* Reset the user pointer on all identifiers of parameters and tuples * of the spaces of "u". */ __isl_give UNION *FN(UNION,reset_user)(__isl_take UNION *u) { … } /* Add the base expression held by "entry" to "list". */ static isl_stat FN(UNION,add_to_list)(void **entry, void *user) { … } /* Return a list containing all the base expressions in "u". * * First construct a list of the appropriate size and * then add all the elements. */ __isl_give LIST(PART) *FN(FN(UNION,get),LIST(BASE))(__isl_keep UNION *u) { … }