/* * Copyright 2008-2009 Katholieke Universiteit Leuven * Copyright 2010 INRIA Saclay * Copyright 2012-2013 Ecole Normale Superieure * Copyright 2019,2022 Cerebras Systems * * 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 * and 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 * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA */ #include <ctype.h> #include <stdio.h> #include <string.h> #include <isl_ctx_private.h> #include <isl_map_private.h> #include <isl_id_private.h> #include <isl/set.h> #include <isl_seq.h> #include <isl_stream_private.h> #include <isl/obj.h> #include "isl_polynomial_private.h" #include <isl/union_set.h> #include <isl/union_map.h> #include <isl_mat_private.h> #include <isl_aff_private.h> #include <isl_vec_private.h> #include <isl/list.h> #include <isl_val_private.h> struct variable { … }; struct vars { … }; static struct vars *vars_new(struct isl_ctx *ctx) { … } static void variable_free(struct variable *var) { … } static void vars_free(struct vars *v) { … } static void vars_drop(struct vars *v, int n) { … } static struct variable *variable_new(struct vars *v, const char *name, int len, int pos) { … } static int vars_pos(struct vars *v, const char *s, int len) { … } static int vars_add_anon(struct vars *v) { … } /* Obtain next token, with some preprocessing. * In particular, evaluate expressions of the form x^y, * with x and y values. */ static struct isl_token *next_token(__isl_keep isl_stream *s) { … } /* Read an isl_val from "s". * * The following token sequences are recognized * * "infty" -> infty * "-" "infty" -> -infty * "NaN" -> NaN * n "/" d -> n/d * "-" n "/" d -> -n/d * v -> v * "-" v -> -v * * where n, d and v are integer constants. */ __isl_give isl_val *isl_stream_read_val(__isl_keep isl_stream *s) { … } #undef TYPE_BASE #define TYPE_BASE … #include "isl_read_from_str_templ.c" static isl_stat accept_cst_factor(__isl_keep isl_stream *s, isl_int *f) { … } /* Given an affine expression aff, return an affine expression * for aff % d, with d the next token on the stream, which is * assumed to be a constant. * * We introduce an integer division q = [aff/d] and the result * is set to aff - d q. */ static __isl_give isl_pw_aff *affine_mod(__isl_keep isl_stream *s, struct vars *v, __isl_take isl_pw_aff *aff) { … } static __isl_give isl_pw_aff *accept_affine(__isl_keep isl_stream *s, __isl_take isl_space *space, struct vars *v); static __isl_give isl_pw_aff_list *accept_affine_list(__isl_keep isl_stream *s, __isl_take isl_space *space, struct vars *v); static __isl_give isl_pw_aff *accept_minmax(__isl_keep isl_stream *s, __isl_take isl_space *space, struct vars *v) { … } /* Divide "pa" by an integer constant read from the stream. */ static __isl_give isl_pw_aff *pw_aff_div_by_cst(__isl_keep isl_stream *s, __isl_take isl_pw_aff *pa) { … } /* Return the (signed) value that is next on the stream, * using "next" to read the next token and printing "msg" in case of an error. */ static struct isl_token *next_signed_value_fn(__isl_keep isl_stream *s, struct isl_token *(*next)(__isl_keep isl_stream *s), char *msg) { … } /* Return the (signed) value that is next on the stream, * printing "msg" in case of an error. */ static struct isl_token *next_signed_value(__isl_keep isl_stream *s, char *msg) { … } /* Return the (signed) value that is next on the stream, * provided it is on the same line, * printing "msg" in case of an error. */ static struct isl_token *next_signed_value_on_same_line( __isl_keep isl_stream *s, char *msg) { … } /* Is "tok" the start of an integer division? */ static int is_start_of_div(struct isl_token *tok) { … } /* Read an integer division from "s" and return it as an isl_pw_aff. * * The integer division can be of the form * * [<affine expression>] * floor(<affine expression>) * ceil(<affine expression>) * floord(<affine expression>,<denominator>) * ceild(<affine expression>,<denominator>) */ static __isl_give isl_pw_aff *accept_div(__isl_keep isl_stream *s, __isl_take isl_space *space, struct vars *v) { … } static __isl_give isl_pw_aff *accept_affine_factor(__isl_keep isl_stream *s, __isl_take isl_space *space, struct vars *v) { … } /* Return a piecewise affine expression defined on the specified domain * that represents NaN. */ static __isl_give isl_pw_aff *nan_on_domain(__isl_keep isl_space *space) { … } static __isl_give isl_pw_aff *accept_affine(__isl_keep isl_stream *s, __isl_take isl_space *space, struct vars *v) { … } /* Is "type" the type of a comparison operator between lists * of affine expressions? */ static int is_list_comparator_type(int type) { … } static int is_comparator(struct isl_token *tok) { … } static __isl_give isl_map *read_formula(__isl_keep isl_stream *s, struct vars *v, __isl_take isl_map *map, int rational); static __isl_give isl_pw_aff *accept_extended_affine(__isl_keep isl_stream *s, __isl_take isl_space *space, struct vars *v, int rational); /* Accept a ternary operator, given the first argument. */ static __isl_give isl_pw_aff *accept_ternary(__isl_keep isl_stream *s, __isl_take isl_map *cond, struct vars *v, int rational) { … } /* Set *line and *col to those of the next token, if any. */ static void set_current_line_col(__isl_keep isl_stream *s, int *line, int *col) { … } /* Push a token encapsulating "pa" onto "s", with the given * line and column. */ static isl_stat push_aff(__isl_keep isl_stream *s, int line, int col, __isl_take isl_pw_aff *pa) { … } /* Is the next token a comparison operator? */ static int next_is_comparator(__isl_keep isl_stream *s) { … } /* Accept an affine expression that may involve ternary operators. * We first read an affine expression. * If it is not followed by a comparison operator, we simply return it. * Otherwise, we assume the affine expression is part of the first * argument of a ternary operator and try to parse that. */ static __isl_give isl_pw_aff *accept_extended_affine(__isl_keep isl_stream *s, __isl_take isl_space *space, struct vars *v, int rational) { … } static __isl_give isl_map *read_var_def(__isl_keep isl_stream *s, __isl_take isl_map *map, enum isl_dim_type type, struct vars *v, int rational) { … } static __isl_give isl_pw_aff_list *accept_affine_list(__isl_keep isl_stream *s, __isl_take isl_space *space, struct vars *v) { … } static __isl_give isl_map *read_defined_var_list(__isl_keep isl_stream *s, struct vars *v, __isl_take isl_map *map, int rational) { … } static int next_is_tuple(__isl_keep isl_stream *s) { … } /* Does the next token mark the end of a tuple element? */ static int next_is_end_tuple_element(__isl_keep isl_stream *s) { … } /* Is the next token one that necessarily forms the start of a condition? */ static int next_is_condition_start(__isl_keep isl_stream *s) { … } /* Is "pa" an expression in term of earlier dimensions? * The alternative is that the dimension is defined to be equal to itself, * meaning that it has a universe domain and an expression that depends * on itself. "i" is the position of the expression in a sequence * of "n" expressions. The final dimensions of "pa" correspond to * these "n" expressions. */ static isl_bool pw_aff_is_expr(__isl_keep isl_pw_aff *pa, int i, int n) { … } /* Does the tuple contain any dimensions that are defined * in terms of earlier dimensions? */ static isl_bool tuple_has_expr(__isl_keep isl_multi_pw_aff *tuple) { … } /* Set the name of dimension "pos" in "space" to "name". * During printing, we add primes if the same name appears more than once * to distinguish the occurrences. Here, we remove those primes from "name" * before setting the name of the dimension. */ static __isl_give isl_space *space_set_dim_name(__isl_take isl_space *space, int pos, char *name) { … } /* Set the name of the last (output) dimension of "space" to "name", * ignoring any primes in "name". */ static __isl_give isl_space *space_set_last_dim_name( __isl_take isl_space *space, char *name) { … } /* Construct an isl_pw_aff defined on a "space" (with v->n variables) * that is equal to the last of those variables. */ static __isl_give isl_pw_aff *identity_tuple_el_on_space( __isl_take isl_space *space, struct vars *v) { … } /* Construct an isl_pw_aff defined on the domain space of "pa" * that is equal to the last variable in "v". * * That is, if D is the domain space of "pa", then construct * * D[..., i] -> i. */ static __isl_give isl_pw_aff *init_range(__isl_keep isl_pw_aff *pa, struct vars *v) { … } /* Impose the lower bound "lower" on the variable represented by "range_pa". * * In particular, "range_pa" is of the form * * D[..., i] -> i : C * * with D also the domains space of "lower' and "C" some constraints. * * Return the expression * * D[..., i] -> i : C and i >= lower */ static __isl_give isl_pw_aff *set_lower(__isl_take isl_pw_aff *range_pa, __isl_take isl_pw_aff *lower) { … } /* Impose the upper bound "upper" on the variable represented by "range_pa". * * In particular, "range_pa" is of the form * * D[..., i] -> i : C * * with D also the domains space of "upper' and "C" some constraints. * * Return the expression * * D[..., i] -> i : C and i <= upper */ static __isl_give isl_pw_aff *set_upper(__isl_take isl_pw_aff *range_pa, __isl_take isl_pw_aff *upper) { … } /* Construct a piecewise affine expression corresponding * to the last variable in "v" that is greater than or equal to "pa". * * In particular, if D is the domain space of "pa", * then construct the expression * * D[..., i] -> i, * * impose lower bound "pa" and return * * D[..., i] -> i : i >= pa */ static __isl_give isl_pw_aff *construct_lower(__isl_take isl_pw_aff *pa, struct vars *v) { … } /* Construct a piecewise affine expression corresponding * to the last variable in "v" that is smaller than or equal to "pa". * * In particular, if D is the domain space of "pa", * then construct the expression * * D[..., i] -> i, * * impose lower bound "pa" and return * * D[..., i] -> i : i <= pa */ static __isl_give isl_pw_aff *construct_upper(__isl_take isl_pw_aff *pa, struct vars *v) { … } /* Construct a piecewise affine expression corresponding * to the last variable in "v" that ranges between "pa" and "pa2". * * In particular, if D is the domain space of "pa" (and "pa2"), * then construct the expression * * D[..., i] -> i, * * impose lower bound "pa" and upper bound "pa2" and return * * D[..., i] -> i : pa <= i <= pa2 */ static __isl_give isl_pw_aff *construct_range(__isl_take isl_pw_aff *pa, __isl_take isl_pw_aff *pa2, struct vars *v) { … } static int resolve_paren_expr(__isl_keep isl_stream *s, struct vars *v, __isl_take isl_map *map, int rational); /* Given that the (piecewise) affine expression "pa" * has just been parsed, followed by a colon, * continue parsing as part of a piecewise affine expression. * * In particular, check if the colon is followed by a condition. * If so, parse the conditions(a) on "pa" and include them in the domain. * Otherwise, if the colon is followed by another (piecewise) affine expression * then consider the two expressions as endpoints of a range of values and * return a piecewise affine expression that takes values in that range. * Note that an affine expression followed by a comparison operator * is considered to be part of a condition. * If the colon is not followed by anything (inside the tuple element), * then consider "pa" as a lower bound on a range of values without upper bound * and return a piecewise affine expression that takes values in that range. */ static __isl_give isl_pw_aff *update_piecewise_affine_colon( __isl_take isl_pw_aff *pa, __isl_keep isl_stream *s, struct vars *v, int rational) { … } /* Accept a piecewise affine expression. * * At the outer level, the piecewise affine expression may be of the form * * aff1 : condition1; aff2 : conditions2; ... * * or one of * * aff : * aff1 : aff2 * : aff * : * * or simply * * aff * * each of the affine expressions may in turn include ternary operators. * * If the first token is a colon, then the expression must be * ":" or ": aff2", depending on whether anything follows the colon * inside the tuple element. * The first is considered to represent an arbitrary value. * The second is considered to represent a range of values * with the given upper bound and no lower bound. * * There may be parentheses around some subexpression of "aff1" * around "aff1" itself, around "aff1 : condition1" and/or * around the entire piecewise affine expression. * We therefore remove the opening parenthesis (if any) from the stream * in case the closing parenthesis follows the colon, but if the closing * parenthesis is the first thing in the stream after the parsed affine * expression, we push the parsed expression onto the stream and parse * again in case the parentheses enclose some subexpression of "aff1". */ static __isl_give isl_pw_aff *accept_piecewise_affine(__isl_keep isl_stream *s, __isl_take isl_space *space, struct vars *v, int rational) { … } /* Read an affine expression from "s" for use in read_tuple. * * accept_extended_affine requires a wrapped space as input. * read_tuple on the other hand expects each isl_pw_aff * to have an anonymous space. We therefore adjust the space * of the isl_pw_aff before returning it. */ static __isl_give isl_pw_aff *read_tuple_var_def(__isl_keep isl_stream *s, struct vars *v, int rational) { … } /* Read a list of tuple elements by calling "read_el" on each of them and * return a space with the same number of set dimensions derived from * the parameter space "space" and possibly updated by "read_el". * The elements in the list are separated by either "," or "][". * If "comma" is set then only "," is allowed. */ static __isl_give isl_space *read_tuple_list(__isl_keep isl_stream *s, struct vars *v, __isl_take isl_space *space, int rational, int comma, __isl_give isl_space *(*read_el)(__isl_keep isl_stream *s, struct vars *v, __isl_take isl_space *space, int rational, void *user), void *user) { … } /* Read a tuple space from "s" derived from the parameter space "space". * Call "read_el" on each element in the tuples. */ static __isl_give isl_space *read_tuple_space(__isl_keep isl_stream *s, struct vars *v, __isl_take isl_space *space, int rational, int comma, __isl_give isl_space *(*read_el)(__isl_keep isl_stream *s, struct vars *v, __isl_take isl_space *space, int rational, void *user), void *user) { … } /* Construct an isl_pw_aff defined on a space with v->n variables * that is equal to the last of those variables. */ static __isl_give isl_pw_aff *identity_tuple_el(struct vars *v) { … } /* This function is called for each element in a tuple inside read_tuple. * Add a new variable to "v" and construct a corresponding isl_pw_aff defined * over a space containing all variables in "v" defined so far. * The isl_pw_aff expresses the new variable in terms of earlier variables * if a definition is provided. Otherwise, it is represented as being * equal to itself. * Add the isl_pw_aff to *list. * If the new variable was named, then adjust "space" accordingly and * return the updated space. */ static __isl_give isl_space *read_tuple_pw_aff_el(__isl_keep isl_stream *s, struct vars *v, __isl_take isl_space *space, int rational, void *user) { … } /* Read a tuple and represent it as an isl_multi_pw_aff. * The range space of the isl_multi_pw_aff is the space of the tuple. * The domain space is an anonymous space * with a dimension for each variable in the set of variables in "v", * including the variables in the range. * If a given dimension is not defined in terms of earlier dimensions in * the input, then the corresponding isl_pw_aff is set equal to one time * the variable corresponding to the dimension being defined. * * The elements in the tuple are collected in a list by read_tuple_pw_aff_el. * Each element in this list is defined over a space representing * the variables defined so far. We need to adjust the earlier * elements to have as many variables in the domain as the final * element in the list. */ static __isl_give isl_multi_pw_aff *read_tuple(__isl_keep isl_stream *s, struct vars *v, int rational, int comma) { … } /* Add the tuple represented by the isl_multi_pw_aff "tuple" to "map". * We first create the appropriate space in "map" based on the range * space of this isl_multi_pw_aff. Then, we add equalities based * on the affine expressions. These live in an anonymous space, * however, so we first need to reset the space to that of "map". */ static __isl_give isl_map *map_from_tuple(__isl_take isl_multi_pw_aff *tuple, __isl_take isl_map *map, enum isl_dim_type type, struct vars *v, int rational) { … } /* Read a tuple from "s" and add it to "map". * The tuple is initially represented as an isl_multi_pw_aff and * then added to "map". */ static __isl_give isl_map *read_map_tuple(__isl_keep isl_stream *s, __isl_take isl_map *map, enum isl_dim_type type, struct vars *v, int rational, int comma) { … } /* Read the parameter domain of an expression from "s" (if any) and * check that it does not involve any constraints. * "v" contains a description of the identifiers parsed so far * (of which there should not be any at this point) and is extended * by this function. */ static __isl_give isl_set *read_universe_params(__isl_keep isl_stream *s, struct vars *v) { … } /* Read the parameter domain of an expression from "s" (if any), * check that it does not involve any constraints and return its space. * "v" contains a description of the identifiers parsed so far * (of which there should not be any at this point) and is extended * by this function. */ static __isl_give isl_space *read_params(__isl_keep isl_stream *s, struct vars *v) { … } /* This function is called for each element in a tuple inside read_space_tuples. * Add a new variable to "v" and adjust "space" accordingly * if the variable has a name. */ static __isl_give isl_space *read_tuple_id(__isl_keep isl_stream *s, struct vars *v, __isl_take isl_space *space, int rational, void *user) { … } /* Given a parameter space "params", extend it with one or two tuples * read from "s". * "v" contains a description of the identifiers parsed so far and is extended * by this function. */ static __isl_give isl_space *read_space_tuples(__isl_keep isl_stream *s, struct vars *v, __isl_take isl_space *params) { … } /* Read an isl_space object from "s". * * First read the parameters (if any). * * Then check if the description is of the special form "{ : }", * in which case it represents a parameter space. * Otherwise, it has one or two tuples. */ __isl_give isl_space *isl_stream_read_space(__isl_keep isl_stream *s) { … } #undef TYPE_BASE #define TYPE_BASE … #include "isl_read_from_str_templ.c" /* Given two equal-length lists of piecewise affine expression with the space * of "set" as domain, construct a set in the same space that expresses * that "left" and "right" satisfy the comparison "type". * * A space is constructed of the same dimension as the number of elements * in the two lists. The comparison is then expressed in a map from * this space to itself and wrapped into a set. Finally the two lists * of piecewise affine expressions are plugged into this set. * * Let S be the space of "set" and T the constructed space. * The lists are first changed into two isl_multi_pw_affs in S -> T and * then combined into an isl_multi_pw_aff in S -> [T -> T], * while the comparison is first expressed in T -> T, then [T -> T] * and finally in S. */ static __isl_give isl_set *list_cmp(__isl_keep isl_set *set, int type, __isl_take isl_pw_aff_list *left, __isl_take isl_pw_aff_list *right) { … } /* Construct constraints of the form * * a op b * * where a is an element in "left", op is an operator of type "type" and * b is an element in "right", add the constraints to "set" and return * the result. * "rational" is set if the constraints should be treated as * a rational constraints. * * If "type" is the type of a comparison operator between lists * of affine expressions, then a single (compound) constraint * is constructed by list_cmp instead. */ static __isl_give isl_set *construct_constraints( __isl_take isl_set *set, int type, __isl_keep isl_pw_aff_list *left, __isl_keep isl_pw_aff_list *right, int rational) { … } /* Read a constraint from "s", add it to "map" and return the result. * "v" contains a description of the identifiers parsed so far. * "rational" is set if the constraint should be treated as * a rational constraint. * The constraint read from "s" may be applied to multiple pairs * of affine expressions and may be chained. * In particular, a list of affine expressions is read, followed * by a comparison operator and another list of affine expressions. * The comparison operator is then applied to each pair of elements * in the two lists and the results are added to "map". * However, if the operator expects two lists of affine expressions, * then it is applied directly to those lists and the two lists * are required to have the same length. * If the next token is another comparison operator, then another * list of affine expressions is read and the process repeats. * * The processing is performed on a wrapped copy of "map" because * an affine expression cannot have a binary relation as domain. */ static __isl_give isl_map *add_constraint(__isl_keep isl_stream *s, struct vars *v, __isl_take isl_map *map, int rational) { … } static __isl_give isl_map *read_exists(__isl_keep isl_stream *s, struct vars *v, __isl_take isl_map *map, int rational) { … } /* Parse an expression between parentheses and push the result * back on the stream. * * The parsed expression may be either an affine expression * or a condition. The first type is pushed onto the stream * as an isl_pw_aff, while the second is pushed as an isl_map. * * If the initial token indicates the start of a condition, * we parse it as such. * Otherwise, we first parse an affine expression and push * that onto the stream. If the affine expression covers the * entire expression between parentheses, we return. * Otherwise, we assume that the affine expression is the * start of a condition and continue parsing. */ static int resolve_paren_expr(__isl_keep isl_stream *s, struct vars *v, __isl_take isl_map *map, int rational) { … } static __isl_give isl_map *read_conjunct(__isl_keep isl_stream *s, struct vars *v, __isl_take isl_map *map, int rational) { … } static __isl_give isl_map *read_conjuncts(__isl_keep isl_stream *s, struct vars *v, __isl_take isl_map *map, int rational) { … } static __isl_give isl_map *read_disjuncts(__isl_keep isl_stream *s, struct vars *v, __isl_take isl_map *map, int rational) { … } /* Read a first order formula from "s", add the corresponding * constraints to "map" and return the result. * * In particular, read a formula of the form * * a * * or * * a implies b * * where a and b are disjunctions. * * In the first case, map is replaced by * * map \cap { [..] : a } * * In the second case, it is replaced by * * (map \setminus { [..] : a}) \cup (map \cap { [..] : b }) */ static __isl_give isl_map *read_formula(__isl_keep isl_stream *s, struct vars *v, __isl_take isl_map *map, int rational) { … } static isl_size polylib_pos_to_isl_pos(__isl_keep isl_basic_map *bmap, int pos) { … } static __isl_give isl_basic_map *basic_map_read_polylib_constraint( __isl_keep isl_stream *s, __isl_take isl_basic_map *bmap) { … } static __isl_give isl_basic_map *basic_map_read_polylib( __isl_keep isl_stream *s) { … } static __isl_give isl_map *map_read_polylib(__isl_keep isl_stream *s) { … } static int optional_power(__isl_keep isl_stream *s) { … } static __isl_give isl_pw_qpolynomial *read_term(__isl_keep isl_stream *s, __isl_keep isl_map *map, struct vars *v); static __isl_give isl_pw_qpolynomial *read_factor(__isl_keep isl_stream *s, __isl_keep isl_map *map, struct vars *v) { … } static __isl_give isl_pw_qpolynomial *read_term(__isl_keep isl_stream *s, __isl_keep isl_map *map, struct vars *v) { … } static __isl_give isl_map *read_optional_formula(__isl_keep isl_stream *s, __isl_take isl_map *map, struct vars *v, int rational) { … } static struct isl_obj obj_read_poly(__isl_keep isl_stream *s, __isl_take isl_map *map, struct vars *v, int n) { … } static struct isl_obj obj_read_poly_or_fold(__isl_keep isl_stream *s, __isl_take isl_set *set, struct vars *v, int n) { … } static int is_rational(__isl_keep isl_stream *s) { … } static struct isl_obj obj_read_body(__isl_keep isl_stream *s, __isl_take isl_map *map, struct vars *v) { … } static struct isl_obj to_union(isl_ctx *ctx, struct isl_obj obj) { … } static struct isl_obj obj_add(__isl_keep isl_stream *s, struct isl_obj obj1, struct isl_obj obj2) { … } /* Are the first two tokens on "s", "domain" (either as a string * or as an identifier) followed by ":"? */ static int next_is_domain_colon(__isl_keep isl_stream *s) { … } /* Do the first tokens on "s" look like a schedule? * * The root of a schedule is always a domain node, so the first thing * we expect in the stream is a domain key, i.e., "domain" followed * by ":". If the schedule was printed in YAML flow style, then * we additionally expect a "{" to open the outer mapping. */ static int next_is_schedule(__isl_keep isl_stream *s) { … } /* Read an isl_schedule from "s" and store it in an isl_obj. */ static struct isl_obj schedule_read(__isl_keep isl_stream *s) { … } /* Read a disjunction of object bodies from "s". * That is, read the inside of the braces, but not the braces themselves. * "v" contains a description of the identifiers parsed so far. * "map" contains information about the parameters. */ static struct isl_obj obj_read_disjuncts(__isl_keep isl_stream *s, struct vars *v, __isl_keep isl_map *map) { … } static struct isl_obj obj_read(__isl_keep isl_stream *s) { … } struct isl_obj isl_stream_read_obj(__isl_keep isl_stream *s) { … } __isl_give isl_map *isl_stream_read_map(__isl_keep isl_stream *s) { … } __isl_give isl_set *isl_stream_read_set(__isl_keep isl_stream *s) { … } __isl_give isl_union_map *isl_stream_read_union_map(__isl_keep isl_stream *s) { … } /* Extract an isl_union_set from "obj". * This only works if the object was detected as either a set * (in which case it is converted to a union set) or a union set. */ static __isl_give isl_union_set *extract_union_set(isl_ctx *ctx, struct isl_obj obj) { … } /* Read an isl_union_set from "s". * First read a generic object and then try and extract * an isl_union_set from that. */ __isl_give isl_union_set *isl_stream_read_union_set(__isl_keep isl_stream *s) { … } static __isl_give isl_basic_map *isl_stream_read_basic_map( __isl_keep isl_stream *s) { … } /* Read an isl_basic_set object from "s". */ __isl_give isl_basic_set *isl_stream_read_basic_set(__isl_keep isl_stream *s) { … } __isl_give isl_basic_map *isl_basic_map_read_from_file(isl_ctx *ctx, FILE *input) { … } __isl_give isl_basic_set *isl_basic_set_read_from_file(isl_ctx *ctx, FILE *input) { … } #undef TYPE_BASE #define TYPE_BASE … #include "isl_read_from_str_templ.c" #undef TYPE_BASE #define TYPE_BASE … #include "isl_read_from_str_templ.c" __isl_give isl_map *isl_map_read_from_file(struct isl_ctx *ctx, FILE *input) { … } #undef TYPE_BASE #define TYPE_BASE … #include "isl_read_from_str_templ.c" __isl_give isl_set *isl_set_read_from_file(struct isl_ctx *ctx, FILE *input) { … } #undef TYPE_BASE #define TYPE_BASE … #include "isl_read_from_str_templ.c" __isl_give isl_union_map *isl_union_map_read_from_file(isl_ctx *ctx, FILE *input) { … } #undef TYPE_BASE #define TYPE_BASE … #include "isl_read_from_str_templ.c" __isl_give isl_union_set *isl_union_set_read_from_file(isl_ctx *ctx, FILE *input) { … } #undef TYPE_BASE #define TYPE_BASE … #include "isl_read_from_str_templ.c" static __isl_give isl_vec *isl_vec_read_polylib(__isl_keep isl_stream *s) { … } static __isl_give isl_vec *vec_read(__isl_keep isl_stream *s) { … } __isl_give isl_vec *isl_vec_read_from_file(isl_ctx *ctx, FILE *input) { … } __isl_give isl_pw_qpolynomial *isl_stream_read_pw_qpolynomial( __isl_keep isl_stream *s) { … } #undef TYPE_BASE #define TYPE_BASE … #include "isl_read_from_str_templ.c" __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_read_from_file(isl_ctx *ctx, FILE *input) { … } /* Read an isl_pw_qpolynomial_fold from "s". * First read a generic object and * then check that it is an isl_pw_qpolynomial_fold. */ __isl_give isl_pw_qpolynomial_fold *isl_stream_read_pw_qpolynomial_fold( __isl_keep isl_stream *s) { … } #undef TYPE_BASE #define TYPE_BASE … #include "isl_read_from_str_templ.c" /* Is the next token an identifier not in "v"? */ static int next_is_fresh_ident(__isl_keep isl_stream *s, struct vars *v) { … } /* First read the domain of the affine expression, which may be * a parameter space or a set. * The tricky part is that we don't know if the domain is a set or not, * so when we are trying to read the domain, we may actually be reading * the affine expression itself (defined on a parameter domains) * If the tuple we are reading is named, we assume it's the domain. * Also, if inside the tuple, the first thing we find is a nested tuple * or a new identifier, we again assume it's the domain. * Finally, if the tuple is empty, then it must be the domain * since it does not contain an affine expression. * Otherwise, we assume we are reading an affine expression. */ static __isl_give isl_set *read_aff_domain(__isl_keep isl_stream *s, __isl_take isl_set *dom, struct vars *v) { … } /* Read an affine expression from "s". */ __isl_give isl_aff *isl_stream_read_aff(__isl_keep isl_stream *s) { … } /* Read a piecewise affine expression from "s" with domain (space) "dom". */ static __isl_give isl_pw_aff *read_pw_aff_with_dom(__isl_keep isl_stream *s, __isl_take isl_set *dom, struct vars *v) { … } /* Read an affine expression, together with optional constraints * on the domain from "s". "dom" represents the initial constraints * on the parameter domain. * "v" contains a description of the identifiers parsed so far. */ static __isl_give isl_pw_aff *read_conditional_aff(__isl_keep isl_stream *s, __isl_take isl_set *dom, struct vars *v) { … } #undef BASE #define BASE … #include "isl_stream_read_pw_with_params_templ.c" #undef TYPE_BASE #define TYPE_BASE … #include "isl_read_from_str_templ.c" #undef TYPE_BASE #define TYPE_BASE … #include "isl_stream_read_with_params_templ.c" #include "isl_read_from_str_templ.c" /* Given that "pa" is the element at position "pos" of a tuple * returned by read_tuple, check that it does not involve any * output/set dimensions (appearing at the "n" positions starting at "first"), * remove those from the domain and replace the domain space * with "domain_space". * * In particular, the result of read_tuple is of the form * [input, output] -> [output], with anonymous domain. * The function read_tuple accepts tuples where some output or * set dimensions are defined in terms of other output or set dimensions * since this function is also used to read maps. As a special case, * read_tuple also accepts dimensions that are defined in terms of themselves * (i.e., that are not defined). * These cases are not allowed here. */ static __isl_give isl_pw_aff *separate_tuple_entry(__isl_take isl_pw_aff *pa, int pos, unsigned first, unsigned n, __isl_take isl_space *domain_space) { … } /* Set entry "pos" of "mpa" to the corresponding entry in "tuple", * as obtained from read_tuple(). * The "n" output dimensions also appear among the input dimensions * at position "first". * * The entry is not allowed to depend on any (other) output dimensions. */ static __isl_give isl_multi_pw_aff *isl_multi_pw_aff_set_tuple_entry( __isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_aff *tuple_el, int pos, unsigned first, unsigned n) { … } #undef BASE #define BASE … #include <isl_multi_from_tuple_templ.c> /* Read a tuple of piecewise affine expressions, * including optional constraints on the domain from "s". * "dom" represents the initial constraints on the domain. * * The input format is similar to that of a map, except that any conditions * on the domains should be specified inside the tuple since each * piecewise affine expression may have a different domain. * However, additional, shared conditions can also be specified. * This is especially useful for setting the explicit domain * of a zero-dimensional isl_multi_pw_aff. * * The isl_multi_pw_aff may live in either a set or a map space. * First read the first tuple and check if it is followed by a "->". * If so, convert the tuple into the domain of the isl_multi_pw_aff and * read in the next tuple. This tuple (or the first tuple if it was * not followed by a "->") is then converted into an isl_multi_pw_aff * through a call to isl_multi_pw_aff_from_tuple. * The domain of the result is intersected with the domain. * * Note that the last tuple may introduce new identifiers, * but these cannot be referenced in the description of the domain. */ static __isl_give isl_multi_pw_aff *read_conditional_multi_pw_aff( __isl_keep isl_stream *s, __isl_take isl_set *dom, struct vars *v) { … } /* Read a tuple of affine expressions, together with optional constraints * on the domain from "s". "dom" represents the initial constraints * on the domain. * * Read a tuple of piecewise affine expressions with optional constraints and * convert the result to an isl_pw_multi_aff on the shared domain. */ static __isl_give isl_pw_multi_aff *read_conditional_multi_aff( __isl_keep isl_stream *s, __isl_take isl_set *dom, struct vars *v) { … } /* Read an isl_union_pw_multi_aff from "s" with parameter domain "dom". * "v" contains a description of the identifiers parsed so far. * * In particular, read a sequence * of zero or more tuples of affine expressions with optional conditions and * add them up. */ static __isl_give isl_union_pw_multi_aff * isl_stream_read_with_params_union_pw_multi_aff(__isl_keep isl_stream *s, __isl_keep isl_set *dom, struct vars *v) { … } #undef BASE #define BASE … #include "isl_stream_read_pw_with_params_templ.c" #undef TYPE_BASE #define TYPE_BASE … #include "isl_stream_read_with_params_templ.c" #include "isl_read_from_str_templ.c" #undef TYPE_BASE #define TYPE_BASE … #include "isl_stream_read_with_params_templ.c" #include "isl_read_from_str_templ.c" #undef BASE #define BASE … #include <isl_multi_read_no_explicit_domain_templ.c> #undef BASE #define BASE … #include <isl_multi_read_no_explicit_domain_templ.c> /* Set entry "pos" of "ma" to the corresponding entry in "tuple", * as obtained from read_tuple(). * The "n" output dimensions also appear among the input dimensions * at position "first". * * The entry is not allowed to depend on any (other) output dimensions. */ static __isl_give isl_multi_aff *isl_multi_aff_set_tuple_entry( __isl_take isl_multi_aff *ma, __isl_take isl_pw_aff *tuple_el, int pos, unsigned first, unsigned n) { … } #undef BASE #define BASE … #include <isl_multi_from_tuple_templ.c> /* Read a multi-affine expression from "s". * If the multi-affine expression has a domain, then the tuple * representing this domain cannot involve any affine expressions. * The tuple representing the actual expressions needs to consist * of only affine expressions. */ __isl_give isl_multi_aff *isl_stream_read_multi_aff(__isl_keep isl_stream *s) { … } #undef TYPE_BASE #define TYPE_BASE … #include "isl_read_from_str_templ.c" /* Read an isl_multi_pw_aff from "s" with parameter domain "dom".. * "v" contains a description of the identifiers parsed so far. */ static __isl_give isl_multi_pw_aff *isl_stream_read_with_params_multi_pw_aff( __isl_keep isl_stream *s, __isl_keep isl_set *dom, struct vars *v) { … } #undef TYPE_BASE #define TYPE_BASE … #include "isl_stream_read_with_params_templ.c" #include "isl_read_from_str_templ.c" /* Read the body of an isl_union_pw_aff from "s" with parameter domain "dom". */ static __isl_give isl_union_pw_aff *read_union_pw_aff_with_dom( __isl_keep isl_stream *s, __isl_take isl_set *dom, struct vars *v) { … } /* Read an isl_union_pw_aff from "s" with parameter domain "dom". * "v" contains a description of the identifiers parsed so far. */ static __isl_give isl_union_pw_aff *isl_stream_read_with_params_union_pw_aff( __isl_keep isl_stream *s, __isl_keep isl_set *dom, struct vars *v) { … } #undef TYPE_BASE #define TYPE_BASE … #include "isl_stream_read_with_params_templ.c" #include "isl_read_from_str_templ.c" /* This function is called for each element in a tuple inside * isl_stream_read_multi_union_pw_aff. * * Read a '{', the union piecewise affine expression body and a '}' and * add the isl_union_pw_aff to *list. */ static __isl_give isl_space *read_union_pw_aff_el(__isl_keep isl_stream *s, struct vars *v, __isl_take isl_space *space, int rational, void *user) { … } /* Do the next tokens in "s" correspond to an empty tuple? * In particular, does the stream start with a '[', followed by a ']', * not followed by a "->"? */ static int next_is_empty_tuple(__isl_keep isl_stream *s) { … } /* Do the next tokens in "s" correspond to a tuple of parameters? * In particular, does the stream start with a '[' that is not * followed by a '{' or a nested tuple? */ static int next_is_param_tuple(__isl_keep isl_stream *s) { … } /* Read the core of a body of an isl_multi_union_pw_aff from "s", * i.e., everything except the parameter specification and * without shared domain constraints. * "v" contains a description of the identifiers parsed so far. * The parameters, if any, are specified by "space". * * The body is of the form * * [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }] * * Read the tuple, collecting the individual isl_union_pw_aff * elements in a list and construct the result from the tuple space and * the list. */ static __isl_give isl_multi_union_pw_aff *read_multi_union_pw_aff_body_core( __isl_keep isl_stream *s, struct vars *v, __isl_take isl_space *space) { … } /* Read the body of an isl_union_set from "s", * i.e., everything except the parameter specification. * "v" contains a description of the identifiers parsed so far. * The parameters, if any, are specified by "space". * * First read a generic disjunction of object bodies and then try and extract * an isl_union_set from that. */ static __isl_give isl_union_set *read_union_set_body(__isl_keep isl_stream *s, struct vars *v, __isl_take isl_space *space) { … } /* Read the body of an isl_multi_union_pw_aff from "s", * i.e., everything except the parameter specification. * "v" contains a description of the identifiers parsed so far. * The parameters, if any, are specified by "space". * * In particular, handle the special case with shared domain constraints. * These are specified as * * ([...] : ...) * * and are especially useful for setting the explicit domain * of a zero-dimensional isl_multi_union_pw_aff. * The core isl_multi_union_pw_aff body ([...]) is read by * read_multi_union_pw_aff_body_core. */ static __isl_give isl_multi_union_pw_aff *read_multi_union_pw_aff_body( __isl_keep isl_stream *s, struct vars *v, __isl_take isl_space *space) { … } /* Read an isl_multi_union_pw_aff from "s". * * The input has the form * * [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }] * * or * * [..] -> [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }] * * Additionally, a shared domain may be specified as * * ([..] : ...) * * or * * [..] -> ([..] : ...) * * The first case is handled by the caller, the second case * is handled by read_multi_union_pw_aff_body. * * We first check for the special case of an empty tuple "[]". * Then we check if there are any parameters. * Finally, read the tuple and construct the result. */ static __isl_give isl_multi_union_pw_aff *read_multi_union_pw_aff_core( __isl_keep isl_stream *s) { … } /* Read an isl_multi_union_pw_aff from "s". * * In particular, handle the special case with shared domain constraints. * These are specified as * * ([...] : ...) * * and are especially useful for setting the explicit domain * of a zero-dimensional isl_multi_union_pw_aff. * The core isl_multi_union_pw_aff ([...]) is read by * read_multi_union_pw_aff_core. */ __isl_give isl_multi_union_pw_aff *isl_stream_read_multi_union_pw_aff( __isl_keep isl_stream *s) { … } #undef TYPE_BASE #define TYPE_BASE … #include "isl_read_from_str_templ.c" __isl_give isl_union_pw_qpolynomial *isl_stream_read_union_pw_qpolynomial( __isl_keep isl_stream *s) { … } #undef TYPE_BASE #define TYPE_BASE … #include "isl_read_from_str_templ.c"