Manual
manual
User Manual:
Open the PDF directly: View PDF .
Page Count: 251
Download | |
Open PDF In Browser | View PDF |
Integer Set Library: Manual Version: isl-0.20 Sven Verdoolaege July 28, 2018 Contents 1 User Manual 3 1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.1.1 Backward Incompatible Changes . . . . . . . . . . . . . . . 3 1.2 License . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.3 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.3.1 Installation from the git repository . . . . . . . . . . . . . . . 7 1.3.2 Common installation instructions . . . . . . . . . . . . . . . 8 1.4 Integer Set Library . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 1.4.1 Memory Management . . . . . . . . . . . . . . . . . . . . . 9 1.4.2 Initialization . . . . . . . . . . . . . . . . . . . . . . . . . . 10 1.4.3 Return Types . . . . . . . . . . . . . . . . . . . . . . . . . . 13 1.4.4 Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 1.4.5 Sets and Relations . . . . . . . . . . . . . . . . . . . . . . . 17 1.4.6 Error Handling . . . . . . . . . . . . . . . . . . . . . . . . . 17 1.4.7 Identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 1.4.8 Spaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 1.4.9 Local Spaces . . . . . . . . . . . . . . . . . . . . . . . . . . 36 1.4.10 Creating New Sets and Relations . . . . . . . . . . . . . . . . 37 1.4.11 Inspecting Sets and Relations . . . . . . . . . . . . . . . . . 43 1.4.12 Points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 1.4.13 Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 1.4.14 Input and Output . . . . . . . . . . . . . . . . . . . . . . . . 69 1.4.15 Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 1.4.16 Unary Operations . . . . . . . . . . . . . . . . . . . . . . . . 89 1.4.17 Binary Operations . . . . . . . . . . . . . . . . . . . . . . . 122 1.4.18 Ternary Operations . . . . . . . . . . . . . . . . . . . . . . . 157 1.4.19 Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 1.4.20 Associative arrays . . . . . . . . . . . . . . . . . . . . . . . 160 1.4.21 Vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 1.4.22 Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 1.4.23 Bounds on Piecewise Quasipolynomials and Piecewise Quasipolynomial Reductions . . . . . . . . . . . . . . . . . . . . . . . 163 1.4.24 Parametric Vertex Enumeration . . . . . . . . . . . . . . . . 164 1.5 Polyhedral Compilation Library . . . . . . . . . . . . . . . . . . . . 165 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 183 189 195 219 220 220 220 220 220 220 220 Implementation Details 2.1 Sets and Relations . . . . . . . . . . . . . . . . . . . . . . . 2.2 Simple Hull . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3 Parametric Integer Programming . . . . . . . . . . . . . . . 2.3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . 2.3.2 The Dual Simplex Method . . . . . . . . . . . . . . 2.3.3 Gomory Cuts . . . . . . . . . . . . . . . . . . . . . 2.3.4 Negative Unknowns and Maximization . . . . . . . 2.3.5 Preprocessing . . . . . . . . . . . . . . . . . . . . . 2.3.6 Postprocessing . . . . . . . . . . . . . . . . . . . . 2.3.7 Context Tableau . . . . . . . . . . . . . . . . . . . 2.3.8 Experiments . . . . . . . . . . . . . . . . . . . . . 2.3.9 Online Symmetry Detection . . . . . . . . . . . . . 2.4 Coalescing . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5 Transitive Closure . . . . . . . . . . . . . . . . . . . . . . . 2.5.1 Introduction . . . . . . . . . . . . . . . . . . . . . . 2.5.2 Computing an Approximation of Rk . . . . . . . . . 2.5.3 Checking Exactness . . . . . . . . . . . . . . . . . 2.5.4 Decomposing R into strongly connected components 2.5.5 Partitioning the domains and ranges of R . . . . . . 2.5.6 Incremental Computation . . . . . . . . . . . . . . . 2.5.7 An Omega-like implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 221 222 222 222 223 224 225 226 227 228 230 231 232 232 232 233 239 239 242 244 246 1.6 2 3 1.5.1 Schedule Trees . . . . . . . . 1.5.2 Dependence Analysis . . . . . 1.5.3 Scheduling . . . . . . . . . . 1.5.4 AST Generation . . . . . . . Applications . . . . . . . . . . . . . . 1.6.1 isl_polyhedron_sample . 1.6.2 isl_pip . . . . . . . . . . . 1.6.3 isl_polyhedron_minimize 1.6.4 isl_polytope_scan . . . . 1.6.5 isl_flow . . . . . . . . . . . 1.6.6 isl_codegen . . . . . . . . 1.6.7 isl_schedule . . . . . . . . Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247 2 Chapter 1 User Manual 1.1 Introduction isl is a thread-safe C library for manipulating sets and relations of integer points bounded by affine constraints. The descriptions of the sets and relations may involve both parameters and existentially quantified variables. All computations are performed in exact integer arithmetic using GMP or imath. The isl library offers functionality that is similar to that offered by the Omega and Omega+ libraries, but the underlying algorithms are in most cases completely different. The library is by no means complete and some fairly basic functionality is still missing. Still, even in its current form, the library has been successfully used as a backend polyhedral library for the polyhedral scanner CLooG and as part of an equivalence checker of static affine programs. For bug reports, feature requests and questions, visit the discussion group at http://groups.google.com/group/isl-development. 1.1.1 Backward Incompatible Changes Changes since isl-0.02 • The old printing functions have been deprecated and replaced by isl_printer functions, see Input and Output. • Most functions related to dependence analysis have acquired an extra must argument. To obtain the old behavior, this argument should be given the value 1. See Dependence Analysis. Changes since isl-0.03 • The function isl_pw_qpolynomial_fold_add has been renamed to isl_pw_qpolynomial_fold_fold. Similarly, isl_union_pw_qpolynomial_fold_add has been renamed to isl_union_pw_qpolynomial_fold_ 3 Changes since isl-0.04 • All header files have been renamed from isl_header.h to isl/header.h. Changes since isl-0.05 • The functions isl_printer_print_basic_set and isl_printer_print_basic_map no longer print a newline. • The functions isl_flow_get_no_source and isl_union_map_compute_flow now return the accesses for which no source could be found instead of the iterations where those accesses occur. • The functions isl_basic_map_identity and isl_map_identity now take a map space as input. An old call isl_map_identity(space) can be rewritten to isl_map_identity(isl_space_map_from_set(space)). • The function isl_map_power no longer takes a parameter position as input. Instead, the exponent is now expressed as the domain of the resulting relation. Changes since isl-0.06 • The format of isl_printer_print_qpolynomial’s ISL_FORMAT_ISL output has changed. Use ISL_FORMAT_C to obtain the old output. • The *_fast_* functions have been renamed to *_plain_*. Some of the old names have been kept for backward compatibility, but they will be removed in the future. Changes since isl-0.07 • The function isl_pw_aff_max has been renamed to isl_pw_aff_union_max. Similarly, the function isl_pw_aff_add has been renamed to isl_pw_aff_union_add. • The isl_dim type has been renamed to isl_space along with the associated functions. Some of the old names have been kept for backward compatibility, but they will be removed in the future. • Spaces of maps, sets and parameter domains are now treated differently. The distinction between map spaces and set spaces has always been made on a conceptual level, but proper use of such spaces was never checked. Furthermore, up until isl-0.07 there was no way of explicitly creating a parameter space. These can now be created directly using isl_space_params_alloc or from other spaces using isl_space_params. • The space in which isl_aff, isl_pw_aff, isl_qpolynomial, isl_pw_qpolynomial, isl_qpolynomial_fold and isl_pw_qpolynomial_fold objects live is now a map space instead of a set space. This means, for example, that the dimensions of the domain of an isl_aff are now considered to be of type isl_dim_in 4 instead of isl_dim_set. Extra functions have been added to obtain the domain space. Some of the constructors still take a domain space and have therefore been renamed. • The functions isl_equality_alloc and isl_inequality_alloc now take an isl_local_space instead of an isl_space. An isl_local_space can be created from an isl_space using isl_local_space_from_space. • The isl_div type has been removed. Functions that used to return an isl_div now return an isl_aff. Note that the space of an isl_aff is that of relation. When replacing a call to isl_div_get_coefficient by a call to isl_aff_get_coefficient any isl_dim_set argument needs to be replaced by isl_dim_in. A call to isl_aff_from_div can be replaced by a call to isl_aff_floor. A call to isl_qpolynomial_div(div) call be replaced by the nested call isl_qpolynomial_from_aff(isl_aff_floor(div)) The function isl_constraint_div has also been renamed to isl_constraint_get_div. • The nparam argument has been removed from isl_map_read_from_str and similar functions. When reading input in the original PolyLib format, the result will have no parameters. If parameters are expected, the caller may want to perform dimension manipulation on the result. Changes since isl-0.09 • The schedule_split_parallel option has been replaced by the schedule_split_scaled option. • The first argument of isl_pw_aff_cond is now an isl_pw_aff instead of an isl_set. A call isl_pw_aff_cond(a, b, c) can be replaced by isl_pw_aff_cond(isl_set_indicator_function(a), b, c) Changes since isl-0.10 • The functions isl_set_dim_has_lower_bound and isl_set_dim_has_upper_bound have been renamed to isl_set_dim_has_any_lower_bound and isl_set_dim_has_any_upper_bound. The new isl_set_dim_has_lower_bound and isl_set_dim_has_upper_bound have slightly different meanings. Changes since isl-0.12 • isl_int has been replaced by isl_val. Some of the old functions are still available in isl/deprecated/*.h but they will be removed in the future. • The functions isl_pw_qpolynomial_eval, isl_union_pw_qpolynomial_eval, isl_pw_qpolynomial_fold_eval and isl_union_pw_qpolynomial_fold_eval have been changed to return an isl_val instead of an isl_qpolynomial. 5 • The function isl_band_member_is_zero_distance has been removed. Essentially the same functionality is available through isl_band_member_is_coincident, except that it requires setting up coincidence constraints. The option schedule_outer_zero_distance has accordingly been replaced by the option schedule_outer_coincidence. • The function isl_vertex_get_expr has been changed to return an isl_multi_aff instead of a rational isl_basic_set. The function isl_vertex_get_domain has been changed to return a regular basic set, rather than a rational basic set. Changes since isl-0.14 • The function isl_union_pw_multi_aff_add now consistently computes the sum on the shared definition domain. The function isl_union_pw_multi_aff_union_add has been added to compute the sum on the union of definition domains. The original behavior of isl_union_pw_multi_aff_add was confused and is no longer available. • Band forests have been replaced by schedule trees. • The function isl_union_map_compute_flow has been replaced by the function isl_union_access_info_compute_flow. Note that the may dependence relation returned by isl_union_flow_get_may_dependence is the union of the two dependence relations returned by isl_union_map_compute_flow. Similarly for the no source relations. The function isl_union_map_compute_flow is still available for backward compatibility, but it will be removed in the future. • The function isl_basic_set_drop_constraint has been deprecated. • The function isl_ast_build_ast_from_schedule has been renamed to isl_ast_build_node_from_schedu The original name is still available for backward compatibility, but it will be removed in the future. • The separation_class AST generation option has been deprecated. • The functions isl_equality_alloc and isl_inequality_alloc have been renamed to isl_constraint_alloc_equality and isl_constraint_alloc_inequality. The original names have been kept for backward compatibility, but they will be removed in the future. • The schedule_fuse option has been replaced by the schedule_serialize_sccs option. The effect of setting the schedule_fuse option to ISL_SCHEDULE_FUSE_MIN is now obtained by turning on the schedule_serialize_sccs option. Changes since isl-0.17 • The function isl_printer_print_ast_expr no longer prints in C format by default. To print in C format, the output format of the printer needs to have been explicitly set to ISL_FORMAT_C. As a result, the function isl_ast_expr_to_str no longer prints the expression in C format. Use isl_ast_expr_to_C_str instead. 6 • The functions isl_set_align_divs and isl_map_align_divs have been deprecated. The function isl_set_lift has an effect that is similar to isl_set_align_divs and could in some cases be used as an alternative. Changes since isl-0.19 • Zero-dimensional objects of type isl_multi_pw_aff or isl_multi_union_pw_aff can now keep track of an explicit domain. This explicit domain, if present, is taken into account by various operations that take such objects as input. 1.2 License isl is released under the MIT license. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Note that by default isl requires GMP, which is released under the GNU Lesser General Public License (LGPL). This means that code linked against isl is also linked against LGPL code. When configuring with --with-int=imath or --with-int=imath-32, isl will link against imath, a library for exact integer arithmetic released under the MIT license. 1.3 Installation The source of isl can be obtained either as a tarball or from the git repository. Both are available from http://isl.gforge.inria.fr/. The installation process depends on how you obtained the source. 1.3.1 Installation from the git repository 1. Clone or update the repository 7 The first time the source is obtained, you need to clone the repository. git clone git://repo.or.cz/isl.git To obtain updates, you need to pull in the latest changes git pull 2. Optionally get imath submodule To build isl with imath, you need to obtain the imath submodule by running in the git source tree of isl git submodule init git submodule update This will fetch the required version of imath in a subdirectory of isl. 3. Generate configure ./autogen.sh After performing the above steps, continue with the Common installation instructions. 1.3.2 Common installation instructions 1. Obtain GMP By default, building isl requires GMP, including its headers files. Your distribution may not provide these header files by default and you may need to install a package called gmp-devel or something similar. Alternatively, GMP can be built from source, available from http://gmplib.org/. GMP is not needed if you build isl with imath. 2. Configure isl uses the standard autoconf configure script. To run it, just type ./configure optionally followed by some configure options. A complete list of options can be obtained by running ./configure --help Below we discuss some of the more common options. 8 --prefix Installation prefix for isl --with-int=[gmp|imath|imath-32] Select the integer library to be used by isl, the default is gmp. With imath-32, isl will use 32 bit integers, but fall back to imath for values out of the 32 bit range. In most applications, isl will run fastest with the imath-32 option, followed by gmp and imath, the slowest. --with-gmp-prefix Installation prefix for GMP (architecture-independent files). --with-gmp-exec-prefix Installation prefix for GMP (architecture-dependent files). 3. Compile make 4. Install (optional) make install 1.4 Integer Set Library 1.4.1 Memory Management Since a high-level operation on isl objects usually involves several substeps and since the user is usually not interested in the intermediate results, most functions that return a new object will also release all the objects passed as arguments. If the user still wants to use one or more of these arguments after the function call, she should pass along a copy of the object rather than the object itself. The user is then responsible for making sure that the original object gets used somewhere else or is explicitly freed. The arguments and return values of all documented functions are annotated to make clear which arguments are released and which arguments are preserved. In particular, the following annotations are used __isl_give __isl_give means that a new object is returned. The user should make sure that the returned pointer is used exactly once as a value for an __isl_take argument. In between, it can be used as a value for as many __isl_keep arguments as the user likes. There is one exception, and that is the case where the pointer returned is NULL. Is this case, the user is free to use it as an __isl_take argument or not. When applied to a char *, the returned pointer needs to be freed using free. __isl_null __isl_null means that a NULL value is returned. 9 __isl_take __isl_take means that the object the argument points to is taken over by the function and may no longer be used by the user as an argument to any other function. The pointer value must be one returned by a function returning an __isl_give pointer. If the user passes in a NULL value, then this will be treated as an error in the sense that the function will not perform its usual operation. However, it will still make sure that all the other __isl_take arguments are released. __isl_keep __isl_keep means that the function will only use the object temporarily. After the function has finished, the user can still use it as an argument to other functions. A NULL value will be treated in the same way as a NULL value for an __isl_take argument. This annotation may also be used on return values of type const char *, in which case the returned pointer should not be freed by the user and is only valid until the object from which it was derived is updated or freed. 1.4.2 Initialization All manipulations of integer sets and relations occur within the context of an isl_ctx. A given isl_ctx can only be used within a single thread. All arguments of a function are required to have been allocated within the same context. There are currently no functions available for moving an object from one isl_ctx to another isl_ctx. This means that there is currently no way of safely moving an object from one thread to another, unless the whole isl_ctx is moved. An isl_ctx can be allocated using isl_ctx_alloc and freed using isl_ctx_free. All objects allocated within an isl_ctx should be freed before the isl_ctx itself is freed. isl_ctx *isl_ctx_alloc(); void isl_ctx_free(isl_ctx *ctx); The user can impose a bound on the number of low-level operations that can be performed by an isl_ctx. This bound can be set and retrieved using the following functions. A bound of zero means that no bound is imposed. The number of operations performed can be reset using isl_ctx_reset_operations. Note that the number of low-level operations needed to perform a high-level computation may differ significantly across different versions of isl, but it should be the same across different platforms for the same version of isl. Warning: This feature is experimental. isl has good support to abort and bail out during the computation, but this feature may exercise error code paths that are normally not used that much. Consequently, it is not unlikely that hidden bugs will be exposed. void isl_ctx_set_max_operations(isl_ctx *ctx, unsigned long max_operations); 10 unsigned long isl_ctx_get_max_operations(isl_ctx *ctx); void isl_ctx_reset_operations(isl_ctx *ctx); In order to be able to create an object in the same context as another object, most object types (described later in this document) provide a function to obtain the context in which the object was created. #includeisl_ctx *isl_val_get_ctx(__isl_keep isl_val *val); isl_ctx *isl_multi_val_get_ctx( __isl_keep isl_multi_val *mv); #include isl_ctx *isl_id_get_ctx(__isl_keep isl_id *id); #include isl_ctx *isl_local_space_get_ctx( __isl_keep isl_local_space *ls); #include isl_ctx *isl_set_list_get_ctx( __isl_keep isl_set_list *list); #include isl_ctx *isl_aff_get_ctx(__isl_keep isl_aff *aff); isl_ctx *isl_multi_aff_get_ctx( __isl_keep isl_multi_aff *maff); isl_ctx *isl_pw_aff_get_ctx(__isl_keep isl_pw_aff *pa); isl_ctx *isl_pw_multi_aff_get_ctx( __isl_keep isl_pw_multi_aff *pma); isl_ctx *isl_multi_pw_aff_get_ctx( __isl_keep isl_multi_pw_aff *mpa); isl_ctx *isl_union_pw_aff_get_ctx( __isl_keep isl_union_pw_aff *upa); isl_ctx *isl_union_pw_multi_aff_get_ctx( __isl_keep isl_union_pw_multi_aff *upma); isl_ctx *isl_multi_union_pw_aff_get_ctx( __isl_keep isl_multi_union_pw_aff *mupa); #include isl_ctx *isl_id_to_ast_expr_get_ctx( __isl_keep isl_id_to_ast_expr *id2expr); #include isl_ctx *isl_point_get_ctx(__isl_keep isl_point *pnt); #include isl_ctx *isl_vec_get_ctx(__isl_keep isl_vec *vec); 11 #include isl_ctx *isl_mat_get_ctx(__isl_keep isl_mat *mat); #include isl_ctx *isl_vertices_get_ctx( __isl_keep isl_vertices *vertices); isl_ctx *isl_vertex_get_ctx(__isl_keep isl_vertex *vertex); isl_ctx *isl_cell_get_ctx(__isl_keep isl_cell *cell); #include isl_ctx *isl_restriction_get_ctx( __isl_keep isl_restriction *restr); isl_ctx *isl_union_access_info_get_ctx( __isl_keep isl_union_access_info *access); isl_ctx *isl_union_flow_get_ctx( __isl_keep isl_union_flow *flow); #include isl_ctx *isl_schedule_get_ctx( __isl_keep isl_schedule *sched); isl_ctx *isl_schedule_constraints_get_ctx( __isl_keep isl_schedule_constraints *sc); #include isl_ctx *isl_schedule_node_get_ctx( __isl_keep isl_schedule_node *node); #include isl_ctx *isl_ast_build_get_ctx( __isl_keep isl_ast_build *build); #include isl_ctx *isl_ast_expr_get_ctx( __isl_keep isl_ast_expr *expr); isl_ctx *isl_ast_node_get_ctx( __isl_keep isl_ast_node *node); #include isl_ctx *isl_stride_info_get_ctx( __isl_keep isl_stride_info *si); #include isl_ctx *isl_fixed_box_get_ctx( __isl_keep isl_fixed_box *box); 12 1.4.3 Return Types isl uses two special return types for functions that either return a boolean or that in principle do not return anything. In particular, the isl_bool type has three possible values: isl_bool_true (a positive integer value), indicating true or yes; isl_bool_false (the integer value zero), indicating false or no; and isl_bool_error (a negative integer value), indicating that something went wrong. The following function can be used to negate an isl_bool, where the negation of isl_bool_error is isl_bool_error again. #include isl_bool isl_bool_not(isl_bool b); The isl_stat type has two possible values: isl_stat_ok (the integer value zero), indicating a successful operation; and isl_stat_error (a negative integer value), indicating that something went wrong. See §1.4.6 for more information on isl_bool_error and isl_stat_error. 1.4.4 Values An isl_val represents an integer value, a rational value or one of three special values, infinity, negative infinity and NaN. Some predefined values can be created using the following functions. #include __isl_give isl_val *isl_val_zero(isl_ctx *ctx); __isl_give isl_val *isl_val_one(isl_ctx *ctx); __isl_give isl_val *isl_val_negone(isl_ctx *ctx); __isl_give isl_val *isl_val_nan(isl_ctx *ctx); __isl_give isl_val *isl_val_infty(isl_ctx *ctx); __isl_give isl_val *isl_val_neginfty(isl_ctx *ctx); Specific integer values can be created using the following functions. #include __isl_give isl_val *isl_val_int_from_si(isl_ctx *ctx, long i); __isl_give isl_val *isl_val_int_from_ui(isl_ctx *ctx, unsigned long u); __isl_give isl_val *isl_val_int_from_chunks(isl_ctx *ctx, size_t n, size_t size, const void *chunks); The function isl_val_int_from_chunks constructs an isl_val from the n digits, each consisting of size bytes, stored at chunks. The least significant digit is assumed to be stored first. Value objects can be copied and freed using the following functions. 13 #include __isl_give isl_val *isl_val_copy(__isl_keep isl_val *v); __isl_null isl_val *isl_val_free(__isl_take isl_val *v); They can be inspected using the following functions. #include long isl_val_get_num_si(__isl_keep isl_val *v); long isl_val_get_den_si(__isl_keep isl_val *v); __isl_give isl_val *isl_val_get_den_val( __isl_keep isl_val *v); double isl_val_get_d(__isl_keep isl_val *v); size_t isl_val_n_abs_num_chunks(__isl_keep isl_val *v, size_t size); int isl_val_get_abs_num_chunks(__isl_keep isl_val *v, size_t size, void *chunks); isl_val_n_abs_num_chunks returns the number of digits of size bytes needed to store the absolute value of the numerator of v. isl_val_get_abs_num_chunks stores these digits at chunks, which is assumed to have been preallocated by the caller. The least significant digit is stored first. Note that isl_val_get_num_si, isl_val_get_den_si, isl_val_get_d, isl_val_n_abs_num_chunks and isl_val_get_abs_num_chunks can only be applied to rational values. An isl_val can be modified using the following function. #include __isl_give isl_val *isl_val_set_si(__isl_take isl_val *v, long i); The following unary properties are defined on isl_vals. #include int isl_val_sgn(__isl_keep isl_val *v); isl_bool isl_val_is_zero(__isl_keep isl_val *v); isl_bool isl_val_is_one(__isl_keep isl_val *v); isl_bool isl_val_is_negone(__isl_keep isl_val *v); isl_bool isl_val_is_nonneg(__isl_keep isl_val *v); isl_bool isl_val_is_nonpos(__isl_keep isl_val *v); isl_bool isl_val_is_pos(__isl_keep isl_val *v); isl_bool isl_val_is_neg(__isl_keep isl_val *v); isl_bool isl_val_is_int(__isl_keep isl_val *v); isl_bool isl_val_is_rat(__isl_keep isl_val *v); isl_bool isl_val_is_nan(__isl_keep isl_val *v); isl_bool isl_val_is_infty(__isl_keep isl_val *v); isl_bool isl_val_is_neginfty(__isl_keep isl_val *v); Note that the sign of NaN is undefined. The following binary properties are defined on pairs of isl_vals. 14 #include isl_bool isl_val_lt(__isl_keep isl_val *v1, __isl_keep isl_val *v2); isl_bool isl_val_le(__isl_keep isl_val *v1, __isl_keep isl_val *v2); isl_bool isl_val_gt(__isl_keep isl_val *v1, __isl_keep isl_val *v2); isl_bool isl_val_ge(__isl_keep isl_val *v1, __isl_keep isl_val *v2); isl_bool isl_val_eq(__isl_keep isl_val *v1, __isl_keep isl_val *v2); isl_bool isl_val_ne(__isl_keep isl_val *v1, __isl_keep isl_val *v2); isl_bool isl_val_abs_eq(__isl_keep isl_val *v1, __isl_keep isl_val *v2); Comparisons to NaN always return false. That is, a NaN is not considered to hold any relative position with respect to any value. In particular, a NaN is neither considered to be equal to nor to be different from any value (including another NaN). The function isl_val_abs_eq checks whether its two arguments are equal in absolute value. For integer isl_vals we additionally have the following binary property. #include isl_bool isl_val_is_divisible_by(__isl_keep isl_val *v1, __isl_keep isl_val *v2); An isl_val can also be compared to an integer using the following functions. The result of isl_val_cmp_si undefined for NaN. #include isl_bool isl_val_gt_si(__isl_keep isl_val *v, long i); int isl_val_cmp_si(__isl_keep isl_val *v, long i); The following unary operations are available on isl_vals. #include __isl_give isl_val *isl_val_abs(__isl_take isl_val *v); __isl_give isl_val *isl_val_neg(__isl_take isl_val *v); __isl_give isl_val *isl_val_floor(__isl_take isl_val *v); __isl_give isl_val *isl_val_ceil(__isl_take isl_val *v); __isl_give isl_val *isl_val_trunc(__isl_take isl_val *v); __isl_give isl_val *isl_val_inv(__isl_take isl_val *v); __isl_give isl_val *isl_val_2exp(__isl_take isl_val *v); The following binary operations are available on isl_vals. 15 #include __isl_give isl_val *isl_val_min(__isl_take isl_val *v1, __isl_take isl_val *v2); __isl_give isl_val *isl_val_max(__isl_take isl_val *v1, __isl_take isl_val *v2); __isl_give isl_val *isl_val_add(__isl_take isl_val *v1, __isl_take isl_val *v2); __isl_give isl_val *isl_val_add_ui(__isl_take isl_val *v1, unsigned long v2); __isl_give isl_val *isl_val_sub(__isl_take isl_val *v1, __isl_take isl_val *v2); __isl_give isl_val *isl_val_sub_ui(__isl_take isl_val *v1, unsigned long v2); __isl_give isl_val *isl_val_mul(__isl_take isl_val *v1, __isl_take isl_val *v2); __isl_give isl_val *isl_val_mul_ui(__isl_take isl_val *v1, unsigned long v2); __isl_give isl_val *isl_val_div(__isl_take isl_val *v1, __isl_take isl_val *v2); __isl_give isl_val *isl_val_div_ui(__isl_take isl_val *v1, unsigned long v2); On integer values, we additionally have the following operations. #include __isl_give isl_val *isl_val_2exp(__isl_take isl_val *v); __isl_give isl_val *isl_val_mod(__isl_take isl_val *v1, __isl_take isl_val *v2); __isl_give isl_val *isl_val_gcd(__isl_take isl_val *v1, __isl_take isl_val *v2); __isl_give isl_val *isl_val_gcdext(__isl_take isl_val *v1, __isl_take isl_val *v2, __isl_give isl_val **x, __isl_give isl_val **y); The function isl_val_gcdext returns the greatest common divisor g of v1 and v2 as well as two integers *x and *y such that *x * v1 + *y * v2 = g. GMP specific functions These functions are only available if isl has been compiled with GMP support. Specific integer and rational values can be created from GMP values using the following functions. #include __isl_give isl_val *isl_val_int_from_gmp(isl_ctx *ctx, mpz_t z); __isl_give isl_val *isl_val_from_gmp(isl_ctx *ctx, const mpz_t n, const mpz_t d); 16 The numerator and denominator of a rational value can be extracted as GMP values using the following functions. #include int isl_val_get_num_gmp(__isl_keep isl_val *v, mpz_t z); int isl_val_get_den_gmp(__isl_keep isl_val *v, mpz_t z); 1.4.5 Sets and Relations isl uses six types of objects for representing sets and relations, isl_basic_set, isl_basic_map, isl_set, isl_map, isl_union_set and isl_union_map. isl_basic_set and isl_basic_map represent sets and relations that can be described as a conjunction of affine constraints, while isl_set and isl_map represent unions of isl_basic_sets and isl_basic_maps, respectively. However, all isl_basic_sets or isl_basic_maps in the union need to live in the same space. isl_union_sets and isl_union_maps represent unions of isl_sets or isl_maps in different spaces, where spaces are considered different if they have a different number of dimensions and/or different names (see §1.4.8). The difference between sets and relations (maps) is that sets have one set of variables, while relations have two sets of variables, input variables and output variables. 1.4.6 Error Handling isl supports different ways to react in case a runtime error is triggered. Runtime errors arise, e.g., if a function such as isl_map_intersect is called with two maps that have incompatible spaces. There are three possible ways to react on error: to warn, to continue or to abort. The default behavior is to warn. In this mode, isl prints a warning, stores the last error in the corresponding isl_ctx and the function in which the error was triggered returns a value indicating that some error has occurred. In case of functions returning a pointer, this value is NULL. In case of functions returning an isl_bool or an isl_stat, this value is isl_bool_error or isl_stat_error. An error does not corrupt internal state, such that isl can continue to be used. isl also provides functions to read the last error, including the specific error message, the isl source file where the error occurred and the line number, and to reset all information about the last error. The last error is only stored for information purposes. Its presence does not change the behavior of isl. Hence, resetting an error is not required to continue to use isl, but only to observe new errors. #include enum isl_error isl_ctx_last_error(isl_ctx *ctx); const char *isl_ctx_last_error_msg(isl_ctx *ctx); const char *isl_ctx_last_error_file(isl_ctx *ctx); int isl_ctx_last_error_line(isl_ctx *ctx); void isl_ctx_reset_error(isl_ctx *ctx); 17 If no error has occurred since the last call to isl_ctx_reset_error, then the functions isl_ctx_last_error_msg and isl_ctx_last_error_file return NULL. Another option is to continue on error. This is similar to warn on error mode, except that isl does not print any warning. This allows a program to implement its own error reporting. The last option is to directly abort the execution of the program from within the isl library. This makes it obviously impossible to recover from an error, but it allows to directly spot the error location. By aborting on error, debuggers break at the location the error occurred and can provide a stack trace. Other tools that automatically provide stack traces on abort or that do not want to continue execution after an error was triggered may also prefer to abort on error. The on error behavior of isl can be specified by calling isl_options_set_on_error or by setting the command line option --isl-on-error. Valid arguments for the function call are ISL_ON_ERROR_WARN, ISL_ON_ERROR_CONTINUE and ISL_ON_ERROR_ABORT. The choices for the command line option are warn, continue and abort. It is also possible to query the current error mode. #include isl_stat isl_options_set_on_error(isl_ctx *ctx, int val); int isl_options_get_on_error(isl_ctx *ctx); 1.4.7 Identifiers Identifiers are used to identify both individual dimensions and tuples of dimensions. They consist of an optional name and an optional user pointer. The name and the user pointer cannot both be NULL, however. Identifiers with the same name but different pointer values are considered to be distinct. Similarly, identifiers with different names but the same pointer value are also considered to be distinct. Equal identifiers are represented using the same object. Pairs of identifiers can therefore be tested for equality using the == operator. Identifiers can be constructed, copied, freed, inspected and printed using the following functions. #include __isl_give isl_id *isl_id_alloc(isl_ctx *ctx, __isl_keep const char *name, void *user); __isl_give isl_id *isl_id_set_free_user( __isl_take isl_id *id, void (*free_user)(void *user)); __isl_give isl_id *isl_id_copy(isl_id *id); __isl_null isl_id *isl_id_free(__isl_take isl_id *id); void *isl_id_get_user(__isl_keep isl_id *id); __isl_keep const char *isl_id_get_name(__isl_keep isl_id *id); __isl_give isl_printer *isl_printer_print_id( __isl_take isl_printer *p, __isl_keep isl_id *id); 18 The callback set by isl_id_set_free_user is called on the user pointer when the last reference to the isl_id is freed. Note that isl_id_get_name returns a pointer to some internal data structure, so the result can only be used while the corresponding isl_id is alive. 1.4.8 Spaces Whenever a new set, relation or similar object is created from scratch, the space in which it lives needs to be specified using an isl_space. Each space involves zero or more parameters and zero, one or two tuples of set or input/output dimensions. The parameters and dimensions are identified by an isl_dim_type and a position. The type isl_dim_param refers to parameters, the type isl_dim_set refers to set dimensions (for spaces with a single tuple of dimensions) and the types isl_dim_in and isl_dim_out refer to input and output dimensions (for spaces with two tuples of dimensions). Local spaces (see §1.4.9) also contain dimensions of type isl_dim_div. Note that parameters are only identified by their position within a given object. Across different objects, parameters are (usually) identified by their names or identifiers. Only unnamed parameters are identified by their positions across objects. The use of unnamed parameters is discouraged. #include __isl_give isl_space *isl_space_alloc(isl_ctx *ctx, unsigned nparam, unsigned n_in, unsigned n_out); __isl_give isl_space *isl_space_params_alloc(isl_ctx *ctx, unsigned nparam); __isl_give isl_space *isl_space_set_alloc(isl_ctx *ctx, unsigned nparam, unsigned dim); __isl_give isl_space *isl_space_copy(__isl_keep isl_space *space); __isl_null isl_space *isl_space_free(__isl_take isl_space *space); The space used for creating a parameter domain needs to be created using isl_space_params_alloc. For other sets, the space needs to be created using isl_space_set_alloc, while for a relation, the space needs to be created using isl_space_alloc. To check whether a given space is that of a set or a map or whether it is a parameter space, use these functions: #include isl_bool isl_bool isl_bool isl_space_is_params(__isl_keep isl_space *space); isl_space_is_set(__isl_keep isl_space *space); isl_space_is_map(__isl_keep isl_space *space); Spaces can be compared using the following functions: #include isl_bool isl_space_is_equal(__isl_keep isl_space *space1, __isl_keep isl_space *space2); isl_bool isl_space_has_equal_params( 19 __isl_keep isl_space *space1, __isl_keep isl_space *space2); isl_bool isl_space_has_equal_tuples( __isl_keep isl_space *space1, __isl_keep isl_space *space2); isl_bool isl_space_is_domain(__isl_keep isl_space *space1, __isl_keep isl_space *space2); isl_bool isl_space_is_range(__isl_keep isl_space *space1, __isl_keep isl_space *space2); isl_bool isl_space_tuple_is_equal( __isl_keep isl_space *space1, enum isl_dim_type type1, __isl_keep isl_space *space2, enum isl_dim_type type2); isl_space_is_domain checks whether the first argument is equal to the domain of the second argument. This requires in particular that the first argument is a set space and that the second argument is a map space. isl_space_tuple_is_equal checks whether the given tuples (isl_dim_in, isl_dim_out or isl_dim_set) of the given spaces are the same. That is, it checks if they have the same identifier (if any), the same dimension and the same internal structure (if any). The function isl_space_has_equal_params checks whether two spaces have the same parameters in the same order. isl_space_has_equal_tuples check whether two spaces have the same tuples. In contrast to isl_space_is_equal below, it does not check the parameters. This is useful because many isl functions align the parameters before they perform their operations, such that equivalence is not necessary. isl_space_is_equal checks whether two spaces are identical, meaning that they have the same parameters and the same tuples. That is, it checks whether both isl_space_has_equal_params and isl_space_has_equal_tuples hold. It is often useful to create objects that live in the same space as some other object. This can be accomplished by creating the new objects (see §1.4.10 or §1.4.13) based on the space of the original object. #include __isl_give isl_space *isl_basic_set_get_space( __isl_keep isl_basic_set *bset); __isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set); #include __isl_give isl_space *isl_union_set_get_space( __isl_keep isl_union_set *uset); #include __isl_give isl_space *isl_basic_map_get_space( __isl_keep isl_basic_map *bmap); __isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map); 20 #include __isl_give isl_space *isl_union_map_get_space( __isl_keep isl_union_map *umap); #include __isl_give isl_space *isl_constraint_get_space( __isl_keep isl_constraint *constraint); #include __isl_give isl_space *isl_qpolynomial_get_domain_space( __isl_keep isl_qpolynomial *qp); __isl_give isl_space *isl_qpolynomial_get_space( __isl_keep isl_qpolynomial *qp); __isl_give isl_space * isl_qpolynomial_fold_get_domain_space( __isl_keep isl_qpolynomial_fold *fold); __isl_give isl_space *isl_qpolynomial_fold_get_space( __isl_keep isl_qpolynomial_fold *fold); __isl_give isl_space *isl_pw_qpolynomial_get_domain_space( __isl_keep isl_pw_qpolynomial *pwqp); __isl_give isl_space *isl_pw_qpolynomial_get_space( __isl_keep isl_pw_qpolynomial *pwqp); __isl_give isl_space *isl_pw_qpolynomial_fold_get_domain_space( __isl_keep isl_pw_qpolynomial_fold *pwf); __isl_give isl_space *isl_pw_qpolynomial_fold_get_space( __isl_keep isl_pw_qpolynomial_fold *pwf); __isl_give isl_space *isl_union_pw_qpolynomial_get_space( __isl_keep isl_union_pw_qpolynomial *upwqp); __isl_give isl_space *isl_union_pw_qpolynomial_fold_get_space( __isl_keep isl_union_pw_qpolynomial_fold *upwf); #include __isl_give isl_space *isl_multi_val_get_space( __isl_keep isl_multi_val *mv); #include __isl_give isl_space *isl_aff_get_domain_space( __isl_keep isl_aff *aff); __isl_give isl_space *isl_aff_get_space( __isl_keep isl_aff *aff); __isl_give isl_space *isl_pw_aff_get_domain_space( __isl_keep isl_pw_aff *pwaff); __isl_give isl_space *isl_pw_aff_get_space( __isl_keep isl_pw_aff *pwaff); __isl_give isl_space *isl_multi_aff_get_domain_space( __isl_keep isl_multi_aff *maff); __isl_give isl_space *isl_multi_aff_get_space( 21 __isl_keep isl_multi_aff *maff); __isl_give isl_space *isl_pw_multi_aff_get_domain_space( __isl_keep isl_pw_multi_aff *pma); __isl_give isl_space *isl_pw_multi_aff_get_space( __isl_keep isl_pw_multi_aff *pma); __isl_give isl_space *isl_union_pw_aff_get_space( __isl_keep isl_union_pw_aff *upa); __isl_give isl_space *isl_union_pw_multi_aff_get_space( __isl_keep isl_union_pw_multi_aff *upma); __isl_give isl_space *isl_multi_pw_aff_get_domain_space( __isl_keep isl_multi_pw_aff *mpa); __isl_give isl_space *isl_multi_pw_aff_get_space( __isl_keep isl_multi_pw_aff *mpa); __isl_give isl_space * isl_multi_union_pw_aff_get_domain_space( __isl_keep isl_multi_union_pw_aff *mupa); __isl_give isl_space * isl_multi_union_pw_aff_get_space( __isl_keep isl_multi_union_pw_aff *mupa); #include __isl_give isl_space *isl_point_get_space( __isl_keep isl_point *pnt); #include __isl_give isl_space *isl_fixed_box_get_space( __isl_keep isl_fixed_box *box); The number of dimensions of a given type of space may be read off from a space or an object that lives in a space using the following functions. In case of isl_space_dim, type may be isl_dim_param, isl_dim_in (only for relations), isl_dim_out (only for relations), isl_dim_set (only for sets) or isl_dim_all. #include unsigned isl_space_dim(__isl_keep isl_space *space, enum isl_dim_type type); #include int isl_local_space_dim(__isl_keep isl_local_space *ls, enum isl_dim_type type); #include unsigned isl_basic_set_dim(__isl_keep isl_basic_set *bset, enum isl_dim_type type); unsigned isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type); 22 #include unsigned isl_union_set_dim(__isl_keep isl_union_set *uset, enum isl_dim_type type); #include unsigned isl_basic_map_dim(__isl_keep isl_basic_map *bmap, enum isl_dim_type type); unsigned isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type); #include unsigned isl_union_map_dim(__isl_keep isl_union_map *umap, enum isl_dim_type type); #include unsigned isl_multi_val_dim(__isl_keep isl_multi_val *mv, enum isl_dim_type type); #include int isl_aff_dim(__isl_keep isl_aff *aff, enum isl_dim_type type); unsigned isl_multi_aff_dim(__isl_keep isl_multi_aff *maff, enum isl_dim_type type); unsigned isl_pw_aff_dim(__isl_keep isl_pw_aff *pwaff, enum isl_dim_type type); unsigned isl_pw_multi_aff_dim( __isl_keep isl_pw_multi_aff *pma, enum isl_dim_type type); unsigned isl_multi_pw_aff_dim( __isl_keep isl_multi_pw_aff *mpa, enum isl_dim_type type); unsigned isl_union_pw_aff_dim( __isl_keep isl_union_pw_aff *upa, enum isl_dim_type type); unsigned isl_union_pw_multi_aff_dim( __isl_keep isl_union_pw_multi_aff *upma, enum isl_dim_type type); unsigned isl_multi_union_pw_aff_dim( __isl_keep isl_multi_union_pw_aff *mupa, enum isl_dim_type type); #include unsigned isl_union_pw_qpolynomial_dim( __isl_keep isl_union_pw_qpolynomial *upwqp, enum isl_dim_type type); unsigned isl_union_pw_qpolynomial_fold_dim( __isl_keep isl_union_pw_qpolynomial_fold *upwf, enum isl_dim_type type); 23 Note that an isl_union_set, an isl_union_map, an isl_union_pw_multi_aff, an isl_union_pw_qpolynomial and an isl_union_pw_qpolynomial_fold only have parameters. Additional parameters can be added to a space using the following function. #include __isl_give isl_space *isl_space_add_param_id( __isl_take isl_space *space, __isl_take isl_id *id); If a parameter with the given identifier already appears in the space, then it is not added again. The identifiers or names of the individual dimensions of spaces may be set or read off using the following functions on spaces or objects that live in spaces. These functions are mostly useful to obtain the identifiers, positions or names of the parameters. Identifiers of individual dimensions are essentially only useful for printing. They are ignored by all other operations and may not be preserved across those operations. #include __isl_give isl_space *isl_space_set_dim_id( __isl_take isl_space *space, enum isl_dim_type type, unsigned pos, __isl_take isl_id *id); isl_bool isl_space_has_dim_id(__isl_keep isl_space *space, enum isl_dim_type type, unsigned pos); __isl_give isl_id *isl_space_get_dim_id( __isl_keep isl_space *space, enum isl_dim_type type, unsigned pos); __isl_give isl_space *isl_space_set_dim_name( __isl_take isl_space *space, enum isl_dim_type type, unsigned pos, __isl_keep const char *name); isl_bool isl_space_has_dim_name(__isl_keep isl_space *space, enum isl_dim_type type, unsigned pos); __isl_keep const char *isl_space_get_dim_name( __isl_keep isl_space *space, enum isl_dim_type type, unsigned pos); #include __isl_give isl_local_space *isl_local_space_set_dim_id( __isl_take isl_local_space *ls, enum isl_dim_type type, unsigned pos, __isl_take isl_id *id); isl_bool isl_local_space_has_dim_id( __isl_keep isl_local_space *ls, enum isl_dim_type type, unsigned pos); __isl_give isl_id *isl_local_space_get_dim_id( 24 __isl_keep isl_local_space *ls, enum isl_dim_type type, unsigned pos); __isl_give isl_local_space *isl_local_space_set_dim_name( __isl_take isl_local_space *ls, enum isl_dim_type type, unsigned pos, const char *s); isl_bool isl_local_space_has_dim_name( __isl_keep isl_local_space *ls, enum isl_dim_type type, unsigned pos) const char *isl_local_space_get_dim_name( __isl_keep isl_local_space *ls, enum isl_dim_type type, unsigned pos); #include const char *isl_constraint_get_dim_name( __isl_keep isl_constraint *constraint, enum isl_dim_type type, unsigned pos); #include __isl_give isl_id *isl_basic_set_get_dim_id( __isl_keep isl_basic_set *bset, enum isl_dim_type type, unsigned pos); __isl_give isl_set *isl_set_set_dim_id( __isl_take isl_set *set, enum isl_dim_type type, unsigned pos, __isl_take isl_id *id); isl_bool isl_set_has_dim_id(__isl_keep isl_set *set, enum isl_dim_type type, unsigned pos); __isl_give isl_id *isl_set_get_dim_id( __isl_keep isl_set *set, enum isl_dim_type type, unsigned pos); const char *isl_basic_set_get_dim_name( __isl_keep isl_basic_set *bset, enum isl_dim_type type, unsigned pos); isl_bool isl_set_has_dim_name(__isl_keep isl_set *set, enum isl_dim_type type, unsigned pos); const char *isl_set_get_dim_name( __isl_keep isl_set *set, enum isl_dim_type type, unsigned pos); #include __isl_give isl_map *isl_map_set_dim_id( __isl_take isl_map *map, enum isl_dim_type type, unsigned pos, __isl_take isl_id *id); isl_bool isl_basic_map_has_dim_id( __isl_keep isl_basic_map *bmap, enum isl_dim_type type, unsigned pos); isl_bool isl_map_has_dim_id(__isl_keep isl_map *map, enum isl_dim_type type, unsigned pos); 25 __isl_give isl_id *isl_map_get_dim_id( __isl_keep isl_map *map, enum isl_dim_type type, unsigned pos); __isl_give isl_id *isl_union_map_get_dim_id( __isl_keep isl_union_map *umap, enum isl_dim_type type, unsigned pos); const char *isl_basic_map_get_dim_name( __isl_keep isl_basic_map *bmap, enum isl_dim_type type, unsigned pos); isl_bool isl_map_has_dim_name(__isl_keep isl_map *map, enum isl_dim_type type, unsigned pos); const char *isl_map_get_dim_name( __isl_keep isl_map *map, enum isl_dim_type type, unsigned pos); #include __isl_give isl_multi_val *isl_multi_val_set_dim_id( __isl_take isl_multi_val *mv, enum isl_dim_type type, unsigned pos, __isl_take isl_id *id); __isl_give isl_id *isl_multi_val_get_dim_id( __isl_keep isl_multi_val *mv, enum isl_dim_type type, unsigned pos); __isl_give isl_multi_val *isl_multi_val_set_dim_name( __isl_take isl_multi_val *mv, enum isl_dim_type type, unsigned pos, const char *s); #include __isl_give isl_aff *isl_aff_set_dim_id( __isl_take isl_aff *aff, enum isl_dim_type type, unsigned pos, __isl_take isl_id *id); __isl_give isl_multi_aff *isl_multi_aff_set_dim_id( __isl_take isl_multi_aff *maff, enum isl_dim_type type, unsigned pos, __isl_take isl_id *id); __isl_give isl_pw_aff *isl_pw_aff_set_dim_id( __isl_take isl_pw_aff *pma, enum isl_dim_type type, unsigned pos, __isl_take isl_id *id); __isl_give isl_multi_pw_aff * isl_multi_pw_aff_set_dim_id( __isl_take isl_multi_pw_aff *mpa, enum isl_dim_type type, unsigned pos, __isl_take isl_id *id); __isl_give isl_multi_union_pw_aff * isl_multi_union_pw_aff_set_dim_id( 26 __isl_take isl_multi_union_pw_aff *mupa, enum isl_dim_type type, unsigned pos, __isl_take isl_id *id); __isl_give isl_id *isl_multi_aff_get_dim_id( __isl_keep isl_multi_aff *ma, enum isl_dim_type type, unsigned pos); isl_bool isl_pw_aff_has_dim_id(__isl_keep isl_pw_aff *pa, enum isl_dim_type type, unsigned pos); __isl_give isl_id *isl_pw_aff_get_dim_id( __isl_keep isl_pw_aff *pa, enum isl_dim_type type, unsigned pos); __isl_give isl_id *isl_pw_multi_aff_get_dim_id( __isl_keep isl_pw_multi_aff *pma, enum isl_dim_type type, unsigned pos); __isl_give isl_id *isl_multi_pw_aff_get_dim_id( __isl_keep isl_multi_pw_aff *mpa, enum isl_dim_type type, unsigned pos); __isl_give isl_id *isl_multi_union_pw_aff_get_dim_id( __isl_keep isl_multi_union_pw_aff *mupa, enum isl_dim_type type, unsigned pos); __isl_give isl_aff *isl_aff_set_dim_name( __isl_take isl_aff *aff, enum isl_dim_type type, unsigned pos, const char *s); __isl_give isl_multi_aff *isl_multi_aff_set_dim_name( __isl_take isl_multi_aff *maff, enum isl_dim_type type, unsigned pos, const char *s); __isl_give isl_multi_pw_aff * isl_multi_pw_aff_set_dim_name( __isl_take isl_multi_pw_aff *mpa, enum isl_dim_type type, unsigned pos, const char *s); __isl_give isl_union_pw_aff * isl_union_pw_aff_set_dim_name( __isl_take isl_union_pw_aff *upa, enum isl_dim_type type, unsigned pos, const char *s); __isl_give isl_union_pw_multi_aff * isl_union_pw_multi_aff_set_dim_name( __isl_take isl_union_pw_multi_aff *upma, enum isl_dim_type type, unsigned pos, const char *s); __isl_give isl_multi_union_pw_aff * isl_multi_union_pw_aff_set_dim_name( __isl_take isl_multi_union_pw_aff *mupa, enum isl_dim_type type, unsigned pos, const char *isl_aff_get_dim_name(__isl_keep isl_aff *aff, enum isl_dim_type type, unsigned pos); 27 const char *isl_pw_aff_get_dim_name( __isl_keep isl_pw_aff *pa, enum isl_dim_type type, unsigned pos); const char *isl_pw_multi_aff_get_dim_name( __isl_keep isl_pw_multi_aff *pma, enum isl_dim_type type, unsigned pos); #include __isl_give isl_qpolynomial *isl_qpolynomial_set_dim_name( __isl_take isl_qpolynomial *qp, enum isl_dim_type type, unsigned pos, const char *s); __isl_give isl_pw_qpolynomial * isl_pw_qpolynomial_set_dim_name( __isl_take isl_pw_qpolynomial *pwqp, enum isl_dim_type type, unsigned pos, const char *s); __isl_give isl_pw_qpolynomial_fold * isl_pw_qpolynomial_fold_set_dim_name( __isl_take isl_pw_qpolynomial_fold *pwf, enum isl_dim_type type, unsigned pos, const char *s); __isl_give isl_union_pw_qpolynomial * isl_union_pw_qpolynomial_set_dim_name( __isl_take isl_union_pw_qpolynomial *upwqp, enum isl_dim_type type, unsigned pos, const char *s); __isl_give isl_union_pw_qpolynomial_fold * isl_union_pw_qpolynomial_fold_set_dim_name( __isl_take isl_union_pw_qpolynomial_fold *upwf, enum isl_dim_type type, unsigned pos, const char *s); Note that isl_space_get_name returns a pointer to some internal data structure, so the result can only be used while the corresponding isl_space is alive. Also note that every function that operates on two sets or relations requires that both arguments have the same parameters. This also means that if one of the arguments has named parameters, then the other needs to have named parameters too and the names need to match. Pairs of isl_set, isl_map, isl_union_set and/or isl_union_map arguments may have different parameters (as long as they are named), in which case the result will have as parameters the union of the parameters of the arguments. Given the identifier or name of a dimension (typically a parameter), its position can be obtained from the following functions. #include int isl_space_find_dim_by_id(__isl_keep isl_space *space, enum isl_dim_type type, __isl_keep isl_id *id); 28 int isl_space_find_dim_by_name(__isl_keep isl_space *space, enum isl_dim_type type, const char *name); #include int isl_local_space_find_dim_by_name( __isl_keep isl_local_space *ls, enum isl_dim_type type, const char *name); #include int isl_multi_val_find_dim_by_id( __isl_keep isl_multi_val *mv, enum isl_dim_type type, __isl_keep isl_id *id); int isl_multi_val_find_dim_by_name( __isl_keep isl_multi_val *mv, enum isl_dim_type type, const char *name); #include int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type, __isl_keep isl_id *id); int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type, const char *name); #include int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type, __isl_keep isl_id *id); int isl_basic_map_find_dim_by_name( __isl_keep isl_basic_map *bmap, enum isl_dim_type type, const char *name); int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type, const char *name); int isl_union_map_find_dim_by_name( __isl_keep isl_union_map *umap, enum isl_dim_type type, const char *name); #include int isl_multi_aff_find_dim_by_id( __isl_keep isl_multi_aff *ma, enum isl_dim_type type, __isl_keep isl_id *id); int isl_multi_pw_aff_find_dim_by_id( __isl_keep isl_multi_pw_aff *mpa, enum isl_dim_type type, __isl_keep isl_id *id); int isl_multi_union_pw_aff_find_dim_by_id( __isl_keep isl_union_multi_pw_aff *mupa, enum isl_dim_type type, __isl_keep isl_id *id); int isl_aff_find_dim_by_name(__isl_keep isl_aff *aff, enum isl_dim_type type, const char *name); int isl_multi_aff_find_dim_by_name( 29 int int int int int int __isl_keep isl_multi_aff *ma, enum isl_dim_type type, const char *name); isl_pw_aff_find_dim_by_name(__isl_keep isl_pw_aff *pa, enum isl_dim_type type, const char *name); isl_multi_pw_aff_find_dim_by_name( __isl_keep isl_multi_pw_aff *mpa, enum isl_dim_type type, const char *name); isl_pw_multi_aff_find_dim_by_name( __isl_keep isl_pw_multi_aff *pma, enum isl_dim_type type, const char *name); isl_union_pw_aff_find_dim_by_name( __isl_keep isl_union_pw_aff *upa, enum isl_dim_type type, const char *name); isl_union_pw_multi_aff_find_dim_by_name( __isl_keep isl_union_pw_multi_aff *upma, enum isl_dim_type type, const char *name); isl_multi_union_pw_aff_find_dim_by_name( __isl_keep isl_multi_union_pw_aff *mupa, enum isl_dim_type type, const char *name); #include int isl_pw_qpolynomial_find_dim_by_name( __isl_keep isl_pw_qpolynomial *pwqp, enum isl_dim_type type, const char *name); int isl_pw_qpolynomial_fold_find_dim_by_name( __isl_keep isl_pw_qpolynomial_fold *pwf, enum isl_dim_type type, const char *name); int isl_union_pw_qpolynomial_find_dim_by_name( __isl_keep isl_union_pw_qpolynomial *upwqp, enum isl_dim_type type, const char *name); int isl_union_pw_qpolynomial_fold_find_dim_by_name( __isl_keep isl_union_pw_qpolynomial_fold *upwf, enum isl_dim_type type, const char *name); The identifiers or names of entire spaces may be set or read off using the following functions. #include __isl_give isl_space *isl_space_set_tuple_id( __isl_take isl_space *space, enum isl_dim_type type, __isl_take isl_id *id); __isl_give isl_space *isl_space_reset_tuple_id( __isl_take isl_space *space, enum isl_dim_type type); isl_bool isl_space_has_tuple_id( __isl_keep isl_space *space, enum isl_dim_type type); __isl_give isl_id *isl_space_get_tuple_id( 30 __isl_keep isl_space *space, enum isl_dim_type type); __isl_give isl_space *isl_space_set_tuple_name( __isl_take isl_space *space, enum isl_dim_type type, const char *s); isl_bool isl_space_has_tuple_name( __isl_keep isl_space *space, enum isl_dim_type type); __isl_keep const char *isl_space_get_tuple_name( __isl_keep isl_space *space, enum isl_dim_type type); #include __isl_give isl_local_space *isl_local_space_set_tuple_id( __isl_take isl_local_space *ls, enum isl_dim_type type, __isl_take isl_id *id); #include __isl_give isl_basic_set *isl_basic_set_set_tuple_id( __isl_take isl_basic_set *bset, __isl_take isl_id *id); __isl_give isl_set *isl_set_set_tuple_id( __isl_take isl_set *set, __isl_take isl_id *id); __isl_give isl_set *isl_set_reset_tuple_id( __isl_take isl_set *set); isl_bool isl_set_has_tuple_id(__isl_keep isl_set *set); __isl_give isl_id *isl_set_get_tuple_id( __isl_keep isl_set *set); __isl_give isl_basic_set *isl_basic_set_set_tuple_name( __isl_take isl_basic_set *set, const char *s); __isl_give isl_set *isl_set_set_tuple_name( __isl_take isl_set *set, const char *s); const char *isl_basic_set_get_tuple_name( __isl_keep isl_basic_set *bset); isl_bool isl_set_has_tuple_name(__isl_keep isl_set *set); const char *isl_set_get_tuple_name( __isl_keep isl_set *set); #include __isl_give isl_basic_map *isl_basic_map_set_tuple_id( __isl_take isl_basic_map *bmap, enum isl_dim_type type, __isl_take isl_id *id); __isl_give isl_map *isl_map_set_tuple_id( __isl_take isl_map *map, enum isl_dim_type type, __isl_take isl_id *id); __isl_give isl_map *isl_map_reset_tuple_id( __isl_take isl_map *map, enum isl_dim_type type); isl_bool isl_map_has_tuple_id(__isl_keep isl_map *map, 31 enum isl_dim_type type); __isl_give isl_id *isl_map_get_tuple_id( __isl_keep isl_map *map, enum isl_dim_type type); __isl_give isl_map *isl_map_set_tuple_name( __isl_take isl_map *map, enum isl_dim_type type, const char *s); const char *isl_basic_map_get_tuple_name( __isl_keep isl_basic_map *bmap, enum isl_dim_type type); __isl_give isl_basic_map *isl_basic_map_set_tuple_name( __isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s); isl_bool isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type); const char *isl_map_get_tuple_name( __isl_keep isl_map *map, enum isl_dim_type type); #include __isl_give isl_multi_val *isl_multi_val_set_tuple_id( __isl_take isl_multi_val *mv, enum isl_dim_type type, __isl_take isl_id *id); __isl_give isl_multi_val *isl_multi_val_reset_tuple_id( __isl_take isl_multi_val *mv, enum isl_dim_type type); isl_bool isl_multi_val_has_tuple_id( __isl_keep isl_multi_val *mv, enum isl_dim_type type); __isl_give isl_id *isl_multi_val_get_tuple_id( __isl_keep isl_multi_val *mv, enum isl_dim_type type); __isl_give isl_multi_val *isl_multi_val_set_tuple_name( __isl_take isl_multi_val *mv, enum isl_dim_type type, const char *s); const char *isl_multi_val_get_tuple_name( __isl_keep isl_multi_val *mv, enum isl_dim_type type); #include __isl_give isl_aff *isl_aff_set_tuple_id( __isl_take isl_aff *aff, enum isl_dim_type type, __isl_take isl_id *id); __isl_give isl_multi_aff *isl_multi_aff_set_tuple_id( __isl_take isl_multi_aff *maff, enum isl_dim_type type, __isl_take isl_id *id); __isl_give isl_pw_aff *isl_pw_aff_set_tuple_id( 32 __isl_take isl_pw_aff *pwaff, enum isl_dim_type type, __isl_take isl_id *id); __isl_give isl_pw_multi_aff *isl_pw_multi_aff_set_tuple_id( __isl_take isl_pw_multi_aff *pma, enum isl_dim_type type, __isl_take isl_id *id); __isl_give isl_multi_union_pw_aff * isl_multi_union_pw_aff_set_tuple_id( __isl_take isl_multi_union_pw_aff *mupa, enum isl_dim_type type, __isl_take isl_id *id); __isl_give isl_multi_aff *isl_multi_aff_reset_tuple_id( __isl_take isl_multi_aff *ma, enum isl_dim_type type); __isl_give isl_pw_aff *isl_pw_aff_reset_tuple_id( __isl_take isl_pw_aff *pa, enum isl_dim_type type); __isl_give isl_multi_pw_aff * isl_multi_pw_aff_reset_tuple_id( __isl_take isl_multi_pw_aff *mpa, enum isl_dim_type type); __isl_give isl_pw_multi_aff * isl_pw_multi_aff_reset_tuple_id( __isl_take isl_pw_multi_aff *pma, enum isl_dim_type type); __isl_give isl_multi_union_pw_aff * isl_multi_union_pw_aff_reset_tuple_id( __isl_take isl_multi_union_pw_aff *mupa, enum isl_dim_type type); isl_bool isl_multi_aff_has_tuple_id( __isl_keep isl_multi_aff *ma, enum isl_dim_type type); __isl_give isl_id *isl_multi_aff_get_tuple_id( __isl_keep isl_multi_aff *ma, enum isl_dim_type type); isl_bool isl_pw_aff_has_tuple_id(__isl_keep isl_pw_aff *pa, enum isl_dim_type type); __isl_give isl_id *isl_pw_aff_get_tuple_id( __isl_keep isl_pw_aff *pa, enum isl_dim_type type); isl_bool isl_pw_multi_aff_has_tuple_id( __isl_keep isl_pw_multi_aff *pma, enum isl_dim_type type); __isl_give isl_id *isl_pw_multi_aff_get_tuple_id( __isl_keep isl_pw_multi_aff *pma, enum isl_dim_type type); isl_bool isl_multi_pw_aff_has_tuple_id( __isl_keep isl_multi_pw_aff *mpa, 33 enum isl_dim_type type); __isl_give isl_id *isl_multi_pw_aff_get_tuple_id( __isl_keep isl_multi_pw_aff *mpa, enum isl_dim_type type); isl_bool isl_multi_union_pw_aff_has_tuple_id( __isl_keep isl_multi_union_pw_aff *mupa, enum isl_dim_type type); __isl_give isl_id *isl_multi_union_pw_aff_get_tuple_id( __isl_keep isl_multi_union_pw_aff *mupa, enum isl_dim_type type); __isl_give isl_multi_aff *isl_multi_aff_set_tuple_name( __isl_take isl_multi_aff *maff, enum isl_dim_type type, const char *s); __isl_give isl_multi_pw_aff * isl_multi_pw_aff_set_tuple_name( __isl_take isl_multi_pw_aff *mpa, enum isl_dim_type type, const char *s); __isl_give isl_multi_union_pw_aff * isl_multi_union_pw_aff_set_tuple_name( __isl_take isl_multi_union_pw_aff *mupa, enum isl_dim_type type, const char *s); const char *isl_multi_aff_get_tuple_name( __isl_keep isl_multi_aff *multi, enum isl_dim_type type); isl_bool isl_pw_multi_aff_has_tuple_name( __isl_keep isl_pw_multi_aff *pma, enum isl_dim_type type); const char *isl_pw_multi_aff_get_tuple_name( __isl_keep isl_pw_multi_aff *pma, enum isl_dim_type type); const char *isl_multi_union_pw_aff_get_tuple_name( __isl_keep isl_multi_union_pw_aff *mupa, enum isl_dim_type type); The type argument needs to be one of isl_dim_in, isl_dim_out or isl_dim_set. As with isl_space_get_name, the isl_space_get_tuple_name function returns a pointer to some internal data structure. Binary operations require the corresponding spaces of their arguments to have the same name. To keep the names of all parameters and tuples, but reset the user pointers of all the corresponding identifiers, use the following function. #include __isl_give isl_space *isl_space_reset_user( __isl_take isl_space *space); #include __isl_give isl_set *isl_set_reset_user( 34 __isl_take isl_set *set); #include __isl_give isl_map *isl_map_reset_user( __isl_take isl_map *map); #include __isl_give isl_union_set *isl_union_set_reset_user( __isl_take isl_union_set *uset); #include __isl_give isl_union_map *isl_union_map_reset_user( __isl_take isl_union_map *umap); #include __isl_give isl_multi_val *isl_multi_val_reset_user( __isl_take isl_multi_val *mv); #include __isl_give isl_multi_aff *isl_multi_aff_reset_user( __isl_take isl_multi_aff *ma); __isl_give isl_pw_aff *isl_pw_aff_reset_user( __isl_take isl_pw_aff *pa); __isl_give isl_multi_pw_aff *isl_multi_pw_aff_reset_user( __isl_take isl_multi_pw_aff *mpa); __isl_give isl_pw_multi_aff *isl_pw_multi_aff_reset_user( __isl_take isl_pw_multi_aff *pma); __isl_give isl_union_pw_aff *isl_union_pw_aff_reset_user( __isl_take isl_union_pw_aff *upa); __isl_give isl_multi_union_pw_aff * isl_multi_union_pw_aff_reset_user( __isl_take isl_multi_union_pw_aff *mupa); __isl_give isl_union_pw_multi_aff * isl_union_pw_multi_aff_reset_user( __isl_take isl_union_pw_multi_aff *upma); #include __isl_give isl_pw_qpolynomial * isl_pw_qpolynomial_reset_user( __isl_take isl_pw_qpolynomial *pwqp); __isl_give isl_union_pw_qpolynomial * isl_union_pw_qpolynomial_reset_user( __isl_take isl_union_pw_qpolynomial *upwqp); __isl_give isl_pw_qpolynomial_fold * isl_pw_qpolynomial_fold_reset_user( __isl_take isl_pw_qpolynomial_fold *pwf); __isl_give isl_union_pw_qpolynomial_fold * isl_union_pw_qpolynomial_fold_reset_user( __isl_take isl_union_pw_qpolynomial_fold *upwf); 35 Spaces can be nested. In particular, the domain of a set or the domain or range of a relation can be a nested relation. This process is also called wrapping. The functions for detecting, constructing and deconstructing such nested spaces can be found in the wrapping properties of §1.4.15, the wrapping operations of §1.4.16 and the Cartesian product operations of §1.4.17. Spaces can be created from other spaces using the functions described in §1.4.16 and §1.4.17. 1.4.9 Local Spaces A local space is essentially a space with zero or more existentially quantified variables. The local space of various objects can be obtained using the following functions. #include __isl_give isl_local_space *isl_constraint_get_local_space( __isl_keep isl_constraint *constraint); #include __isl_give isl_local_space *isl_basic_set_get_local_space( __isl_keep isl_basic_set *bset); #include __isl_give isl_local_space *isl_basic_map_get_local_space( __isl_keep isl_basic_map *bmap); #include __isl_give isl_local_space __isl_keep isl_aff __isl_give isl_local_space __isl_keep isl_aff *isl_aff_get_domain_local_space( *aff); *isl_aff_get_local_space( *aff); A new local space can be created from a space using #include __isl_give isl_local_space *isl_local_space_from_space( __isl_take isl_space *space); They can be inspected, modified, copied and freed using the following functions. #include isl_bool isl_local_space_is_params( __isl_keep isl_local_space *ls); isl_bool isl_local_space_is_set( __isl_keep isl_local_space *ls); __isl_give isl_space *isl_local_space_get_space( __isl_keep isl_local_space *ls); __isl_give isl_aff *isl_local_space_get_div( 36 __isl_keep isl_local_space *ls, int pos); __isl_give isl_local_space *isl_local_space_copy( __isl_keep isl_local_space *ls); __isl_null isl_local_space *isl_local_space_free( __isl_take isl_local_space *ls); Note that isl_local_space_get_div can only be used on local spaces of sets. Two local spaces can be compared using isl_bool isl_local_space_is_equal( __isl_keep isl_local_space *ls1, __isl_keep isl_local_space *ls2); Local spaces can be created from other local spaces using the functions described in §1.4.16 and §1.4.17. 1.4.10 Creating New Sets and Relations isl has functions for creating some standard sets and relations. • Empty sets and relations __isl_give isl_basic_set *isl_basic_set_empty( __isl_take isl_space *space); __isl_give isl_basic_map *isl_basic_map_empty( __isl_take isl_space *space); __isl_give isl_set *isl_set_empty( __isl_take isl_space *space); __isl_give isl_map *isl_map_empty( __isl_take isl_space *space); __isl_give isl_union_set *isl_union_set_empty( __isl_take isl_space *space); __isl_give isl_union_map *isl_union_map_empty( __isl_take isl_space *space); For isl_union_sets and isl_union_maps, the space is only used to specify the parameters. • Universe sets and relations __isl_give isl_basic_set *isl_basic_set_universe( __isl_take isl_space *space); __isl_give isl_basic_map *isl_basic_map_universe( __isl_take isl_space *space); __isl_give isl_set *isl_set_universe( __isl_take isl_space *space); __isl_give isl_map *isl_map_universe( 37 __isl_take isl_space *space); __isl_give isl_union_set *isl_union_set_universe( __isl_take isl_union_set *uset); __isl_give isl_union_map *isl_union_map_universe( __isl_take isl_union_map *umap); The sets and relations constructed by the functions above contain all integer values, while those constructed by the functions below only contain non-negative values. __isl_give isl_basic_set *isl_basic_set_nat_universe( __isl_take isl_space *space); __isl_give isl_basic_map *isl_basic_map_nat_universe( __isl_take isl_space *space); __isl_give isl_set *isl_set_nat_universe( __isl_take isl_space *space); __isl_give isl_map *isl_map_nat_universe( __isl_take isl_space *space); • Identity relations __isl_give isl_basic_map *isl_basic_map_identity( __isl_take isl_space *space); __isl_give isl_map *isl_map_identity( __isl_take isl_space *space); The number of input and output dimensions in space needs to be the same. • Lexicographic order __isl_give isl_map __isl_take __isl_give isl_map __isl_take __isl_give isl_map __isl_take __isl_give isl_map __isl_take __isl_give isl_map __isl_take __isl_give isl_map __isl_take __isl_give isl_map __isl_take __isl_give isl_map __isl_take *isl_map_lex_lt( isl_space *set_space); *isl_map_lex_le( isl_space *set_space); *isl_map_lex_gt( isl_space *set_space); *isl_map_lex_ge( isl_space *set_space); *isl_map_lex_lt_first( isl_space *space, unsigned *isl_map_lex_le_first( isl_space *space, unsigned *isl_map_lex_gt_first( isl_space *space, unsigned *isl_map_lex_ge_first( isl_space *space, unsigned 38 n); n); n); n); The first four functions take a space for a set and return relations that express that the elements in the domain are lexicographically less (isl_map_lex_lt), less or equal (isl_map_lex_le), greater (isl_map_lex_gt) or greater or equal (isl_map_lex_ge) than the elements in the range. The last four functions take a space for a map and return relations that express that the first n dimensions in the domain are lexicographically less (isl_map_lex_lt_first), less or equal (isl_map_lex_le_first), greater (isl_map_lex_gt_first) or greater or equal (isl_map_lex_ge_first) than the first n dimensions in the range. A basic set or relation can be converted to a set or relation using the following functions. __isl_give isl_set __isl_take __isl_give isl_map __isl_take *isl_set_from_basic_set( isl_basic_set *bset); *isl_map_from_basic_map( isl_basic_map *bmap); Sets and relations can be converted to union sets and relations using the following functions. __isl_give isl_union_set *isl_union_set_from_basic_set( __isl_take isl_basic_set *bset); __isl_give isl_union_map *isl_union_map_from_basic_map( __isl_take isl_basic_map *bmap); __isl_give isl_union_set *isl_union_set_from_set( __isl_take isl_set *set); __isl_give isl_union_map *isl_union_map_from_map( __isl_take isl_map *map); The inverse conversions below can only be used if the input union set or relation is known to contain elements in exactly one space. __isl_give isl_set __isl_take __isl_give isl_map __isl_take *isl_set_from_union_set( isl_union_set *uset); *isl_map_from_union_map( isl_union_map *umap); Sets and relations can be copied and freed again using the following functions. __isl_give isl_basic_set *isl_basic_set_copy( __isl_keep isl_basic_set *bset); __isl_give isl_set *isl_set_copy(__isl_keep isl_set *set); __isl_give isl_union_set *isl_union_set_copy( __isl_keep isl_union_set *uset); __isl_give isl_basic_map *isl_basic_map_copy( __isl_keep isl_basic_map *bmap); __isl_give isl_map *isl_map_copy(__isl_keep isl_map *map); 39 __isl_give isl_union_map *isl_union_map_copy( __isl_keep isl_union_map *umap); __isl_null isl_basic_set *isl_basic_set_free( __isl_take isl_basic_set *bset); __isl_null isl_set *isl_set_free(__isl_take isl_set *set); __isl_null isl_union_set *isl_union_set_free( __isl_take isl_union_set *uset); __isl_null isl_basic_map *isl_basic_map_free( __isl_take isl_basic_map *bmap); __isl_null isl_map *isl_map_free(__isl_take isl_map *map); __isl_null isl_union_map *isl_union_map_free( __isl_take isl_union_map *umap); Other sets and relations can be constructed by starting from a universe set or relation, adding equality and/or inequality constraints and then projecting out the existentially quantified variables, if any. Constraints can be constructed, manipulated and added to (or removed from) (basic) sets and relations using the following functions. #include __isl_give isl_constraint *isl_constraint_alloc_equality( __isl_take isl_local_space *ls); __isl_give isl_constraint *isl_constraint_alloc_inequality( __isl_take isl_local_space *ls); __isl_give isl_constraint *isl_constraint_set_constant_si( __isl_take isl_constraint *constraint, int v); __isl_give isl_constraint *isl_constraint_set_constant_val( __isl_take isl_constraint *constraint, __isl_take isl_val *v); __isl_give isl_constraint *isl_constraint_set_coefficient_si( __isl_take isl_constraint *constraint, enum isl_dim_type type, int pos, int v); __isl_give isl_constraint * isl_constraint_set_coefficient_val( __isl_take isl_constraint *constraint, enum isl_dim_type type, int pos, __isl_take isl_val *v); __isl_give isl_basic_map *isl_basic_map_add_constraint( __isl_take isl_basic_map *bmap, __isl_take isl_constraint *constraint); __isl_give isl_basic_set *isl_basic_set_add_constraint( __isl_take isl_basic_set *bset, __isl_take isl_constraint *constraint); __isl_give isl_map *isl_map_add_constraint( __isl_take isl_map *map, __isl_take isl_constraint *constraint); __isl_give isl_set *isl_set_add_constraint( 40 __isl_take isl_set *set, __isl_take isl_constraint *constraint); For example, to create a set containing the even integers between 10 and 42, you would use the following code. isl_space *space; isl_local_space *ls; isl_constraint *c; isl_basic_set *bset; space = isl_space_set_alloc(ctx, 0, 2); bset = isl_basic_set_universe(isl_space_copy(space)); ls = isl_local_space_from_space(space); c = isl_constraint_alloc_equality(isl_local_space_copy(ls)); c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1); c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 2); bset = isl_basic_set_add_constraint(bset, c); c = isl_constraint_alloc_inequality(isl_local_space_copy(ls)); c = isl_constraint_set_constant_si(c, -10); c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1); bset = isl_basic_set_add_constraint(bset, c); c = isl_constraint_alloc_inequality(ls); c = isl_constraint_set_constant_si(c, 42); c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1); bset = isl_basic_set_add_constraint(bset, c); bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 1); Or, alternatively, isl_basic_set *bset; bset = isl_basic_set_read_from_str(ctx, "{[i] : exists (a : i = 2a and i >= 10 and i <= 42)}"); A basic set or relation can also be constructed from two matrices describing the equalities and the inequalities. __isl_give isl_basic_set *isl_basic_set_from_constraint_matrices( __isl_take isl_space *space, __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1, enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4); __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices( 41 __isl_take isl_space *space, __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1, enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4, enum isl_dim_type c5); The isl_dim_type arguments indicate the order in which different kinds of variables appear in the input matrices and should be a permutation of isl_dim_cst, isl_dim_param, isl_dim_set and isl_dim_div for sets and of isl_dim_cst, isl_dim_param, isl_dim_in, isl_dim_out and isl_dim_div for relations. A (basic or union) set or relation can also be constructed from a (union) (piecewise) (multiple) affine expression or a list of affine expressions (See §1.4.13), provided these affine expressions do not involve any NaN. #include __isl_give isl_basic_set *isl_basic_set_from_multi_aff( __isl_take isl_multi_aff *ma); __isl_give isl_set *isl_set_from_multi_aff( __isl_take isl_multi_aff *ma); #include __isl_give isl_basic_map *isl_basic_map_from_aff( __isl_take isl_aff *aff); __isl_give isl_map *isl_map_from_aff( __isl_take isl_aff *aff); __isl_give isl_basic_map *isl_basic_map_from_aff_list( __isl_take isl_space *domain_space, __isl_take isl_aff_list *list); __isl_give isl_basic_map *isl_basic_map_from_multi_aff( __isl_take isl_multi_aff *maff) __isl_give isl_map *isl_map_from_multi_aff( __isl_take isl_multi_aff *maff) #include __isl_give isl_set *isl_set_from_pw_aff( __isl_take isl_pw_aff *pwaff); __isl_give isl_map *isl_map_from_pw_aff( __isl_take isl_pw_aff *pwaff); __isl_give isl_set *isl_set_from_pw_multi_aff( __isl_take isl_pw_multi_aff *pma); __isl_give isl_map *isl_map_from_pw_multi_aff( __isl_take isl_pw_multi_aff *pma); __isl_give isl_set *isl_set_from_multi_pw_aff( __isl_take isl_multi_pw_aff *mpa); __isl_give isl_map *isl_map_from_multi_pw_aff( __isl_take isl_multi_pw_aff *mpa); __isl_give isl_union_map *isl_union_map_from_union_pw_aff( 42 __isl_take isl_union_pw_aff *upa); __isl_give isl_union_map * isl_union_map_from_union_pw_multi_aff( __isl_take isl_union_pw_multi_aff *upma); __isl_give isl_union_map * isl_union_map_from_multi_union_pw_aff( __isl_take isl_multi_union_pw_aff *mupa); The domain_space argument describes the domain of the resulting basic relation. It is required because the list may consist of zero affine expressions. The mupa passed to isl_union_map_from_multi_union_pw_aff is not allowed to be zerodimensional. The domain of the result is the shared domain of the union piecewise affine elements. 1.4.11 Inspecting Sets and Relations Usually, the user should not have to care about the actual constraints of the sets and maps, but should instead apply the abstract operations explained in the following sections. Occasionally, however, it may be required to inspect the individual coefficients of the constraints. This section explains how to do so. In these cases, it may also be useful to have isl compute an explicit representation of the existentially quantified variables. __isl_give isl_set *isl_set_compute_divs( __isl_take isl_set *set); __isl_give isl_map *isl_map_compute_divs( __isl_take isl_map *map); __isl_give isl_union_set *isl_union_set_compute_divs( __isl_take isl_union_set *uset); __isl_give isl_union_map *isl_union_map_compute_divs( __isl_take isl_union_map *umap); This explicit representation defines the existentially quantified variables as integer divisions of the other variables, possibly including earlier existentially quantified variables. An explicitly represented existentially quantified variable therefore has a unique value when the values of the other variables are known. Alternatively, the existentially quantified variables can be removed using the following functions, which compute an overapproximation. #include __isl_give isl_basic_set *isl_basic_set_remove_divs( __isl_take isl_basic_set *bset); __isl_give isl_set *isl_set_remove_divs( __isl_take isl_set *set); #include __isl_give isl_basic_map *isl_basic_map_remove_divs( 43 __isl_take isl_basic_map *bmap); __isl_give isl_map *isl_map_remove_divs( __isl_take isl_map *map); #include __isl_give isl_union_set *isl_union_set_remove_divs( __isl_take isl_union_set *bset); #include __isl_give isl_union_map *isl_union_map_remove_divs( __isl_take isl_union_map *bmap); It is also possible to only remove those divs that are defined in terms of a given range of dimensions or only those for which no explicit representation is known. __isl_give isl_basic_set * isl_basic_set_remove_divs_involving_dims( __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned first, unsigned n); __isl_give isl_basic_map * isl_basic_map_remove_divs_involving_dims( __isl_take isl_basic_map *bmap, enum isl_dim_type type, unsigned first, unsigned n); __isl_give isl_set *isl_set_remove_divs_involving_dims( __isl_take isl_set *set, enum isl_dim_type type, unsigned first, unsigned n); __isl_give isl_map *isl_map_remove_divs_involving_dims( __isl_take isl_map *map, enum isl_dim_type type, unsigned first, unsigned n); __isl_give isl_basic_set * isl_basic_set_remove_unknown_divs( __isl_take isl_basic_set *bset); __isl_give isl_set *isl_set_remove_unknown_divs( __isl_take isl_set *set); __isl_give isl_map *isl_map_remove_unknown_divs( __isl_take isl_map *map); To iterate over all the sets or maps in a union set or map, use #include isl_stat isl_union_set_foreach_set( __isl_keep isl_union_set *uset, isl_stat (*fn)(__isl_take isl_set *set, void *user), void *user); 44 #include isl_stat isl_union_map_foreach_map( __isl_keep isl_union_map *umap, isl_stat (*fn)(__isl_take isl_map *map, void *user), void *user); isl_bool isl_union_map_every_map( __isl_keep isl_union_map *umap, isl_bool (*test)(__isl_keep isl_map *map, void *user), void *user); These functions call the callback function once for each (pair of) space(s) for which there are elements in the input. The argument to the callback contains all elements in the input with that (pair of) space(s). The isl_union_map_every_map variant check whether each call to the callback returns true and stops checking as soon as one of these calls returns false. The number of sets or maps in a union set or map can be obtained from int isl_union_set_n_set(__isl_keep isl_union_set *uset); int isl_union_map_n_map(__isl_keep isl_union_map *umap); To extract the set or map in a given space from a union, use __isl_give isl_set __isl_keep __isl_take __isl_give isl_map __isl_keep __isl_take *isl_union_set_extract_set( isl_union_set *uset, isl_space *space); *isl_union_map_extract_map( isl_union_map *umap, isl_space *space); To iterate over all the basic sets or maps in a set or map, use isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set, isl_stat (*fn)(__isl_take isl_basic_set *bset, void *user), void *user); isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map, isl_stat (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user); The callback function fn should return isl_stat_ok if successful and isl_stat_error if an error occurs. In the latter case, or if any other error occurs, the above functions will return isl_stat_error. It should be noted that isl does not guarantee that the basic sets or maps passed to fn are disjoint. If this is required, then the user should call one of the following functions first. 45 __isl_give isl_set __isl_take __isl_give isl_map __isl_take *isl_set_make_disjoint( isl_set *set); *isl_map_make_disjoint( isl_map *map); The number of basic sets in a set can be obtained or the number of basic maps in a map can be obtained from #include int isl_set_n_basic_set(__isl_keep isl_set *set); #include int isl_map_n_basic_map(__isl_keep isl_map *map); It is also possible to obtain a list of (basic) sets from a set or union set, a list of basic maps from a map and a list of maps from a union map. #include __isl_give isl_basic_set_list *isl_set_get_basic_set_list( __isl_keep isl_set *set); #include __isl_give isl_basic_set_list * isl_union_set_get_basic_set_list( __isl_keep isl_union_set *uset); __isl_give isl_set_list *isl_union_set_get_set_list( __isl_keep isl_union_set *uset); #include __isl_give isl_basic_map_list *isl_map_get_basic_map_list( __isl_keep isl_map *map); #include __isl_give isl_map_list *isl_union_map_get_map_list( __isl_keep isl_union_map *umap); The returned list can be manipulated using the functions in §1.4.19. To iterate over the constraints of a basic set or map, use #include int isl_basic_set_n_constraint( __isl_keep isl_basic_set *bset); isl_stat isl_basic_set_foreach_constraint( __isl_keep isl_basic_set *bset, isl_stat (*fn)(__isl_take isl_constraint *c, void *user), void *user); 46 int isl_basic_map_n_constraint( __isl_keep isl_basic_map *bmap); isl_stat isl_basic_map_foreach_constraint( __isl_keep isl_basic_map *bmap, isl_stat (*fn)(__isl_take isl_constraint *c, void *user), void *user); __isl_null isl_constraint *isl_constraint_free( __isl_take isl_constraint *c); Again, the callback function fn should return isl_stat_ok if successful and isl_stat_error if an error occurs. In the latter case, or if any other error occurs, the above functions will return isl_stat_error. The constraint c represents either an equality or an inequality. Use the following function to find out whether a constraint represents an equality. If not, it represents an inequality. isl_bool isl_constraint_is_equality( __isl_keep isl_constraint *constraint); It is also possible to obtain a list of constraints from a basic map or set #include __isl_give isl_constraint_list * isl_basic_map_get_constraint_list( __isl_keep isl_basic_map *bmap); __isl_give isl_constraint_list * isl_basic_set_get_constraint_list( __isl_keep isl_basic_set *bset); These functions require that all existentially quantified variables have an explicit representation. The returned list can be manipulated using the functions in §1.4.19. The coefficients of the constraints can be inspected using the following functions. isl_bool isl_constraint_is_lower_bound( __isl_keep isl_constraint *constraint, enum isl_dim_type type, unsigned pos); isl_bool isl_constraint_is_upper_bound( __isl_keep isl_constraint *constraint, enum isl_dim_type type, unsigned pos); __isl_give isl_val *isl_constraint_get_constant_val( __isl_keep isl_constraint *constraint); __isl_give isl_val *isl_constraint_get_coefficient_val( __isl_keep isl_constraint *constraint, enum isl_dim_type type, int pos); The explicit representations of the existentially quantified variables can be inspected using the following function. Note that the user is only allowed to use this function if the inspected set or map is the result of a call to isl_set_compute_divs or 47 isl_map_compute_divs. The existentially quantified variable is equal to the floor of the returned affine expression. The affine expression itself can be inspected using the functions in §1.4.13. __isl_give isl_aff *isl_constraint_get_div( __isl_keep isl_constraint *constraint, int pos); To obtain the constraints of a basic set or map in matrix form, use the following functions. __isl_give isl_mat *isl_basic_set_equalities_matrix( __isl_keep isl_basic_set *bset, enum isl_dim_type c1, enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4); __isl_give isl_mat *isl_basic_set_inequalities_matrix( __isl_keep isl_basic_set *bset, enum isl_dim_type c1, enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4); __isl_give isl_mat *isl_basic_map_equalities_matrix( __isl_keep isl_basic_map *bmap, enum isl_dim_type c1, enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4, enum isl_dim_type c5); __isl_give isl_mat *isl_basic_map_inequalities_matrix( __isl_keep isl_basic_map *bmap, enum isl_dim_type c1, enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4, enum isl_dim_type c5); The isl_dim_type arguments dictate the order in which different kinds of variables appear in the resulting matrix. For set inputs, they should be a permutation of isl_dim_cst, isl_dim_param, isl_dim_set and isl_dim_div. For map inputs, they should be a permutation of isl_dim_cst, isl_dim_param, isl_dim_in, isl_dim_out and isl_dim_div. 1.4.12 Points Points are elements of a set. They can be used to construct simple sets (boxes) or they can be used to represent the individual elements of a set. The zero point (the origin) can be created using __isl_give isl_point *isl_point_zero(__isl_take isl_space *space); The coordinates of a point can be inspected, set and changed using __isl_give isl_val *isl_point_get_coordinate_val( __isl_keep isl_point *pnt, 48 enum isl_dim_type type, int pos); __isl_give isl_point *isl_point_set_coordinate_val( __isl_take isl_point *pnt, enum isl_dim_type type, int pos, __isl_take isl_val *v); __isl_give isl_point *isl_point_add_ui( __isl_take isl_point *pnt, enum isl_dim_type type, int pos, unsigned val); __isl_give isl_point *isl_point_sub_ui( __isl_take isl_point *pnt, enum isl_dim_type type, int pos, unsigned val); Points can be copied or freed using __isl_give isl_point *isl_point_copy( __isl_keep isl_point *pnt); __isl_null isl_point *isl_point_free( __isl_take isl_point *pnt); A singleton set can be created from a point using __isl_give isl_basic_set *isl_basic_set_from_point( __isl_take isl_point *pnt); __isl_give isl_set *isl_set_from_point( __isl_take isl_point *pnt); __isl_give isl_union_set *isl_union_set_from_point( __isl_take isl_point *pnt); and a box can be created from two opposite extremal points using __isl_give isl_basic_set *isl_basic_set_box_from_points( __isl_take isl_point *pnt1, __isl_take isl_point *pnt2); __isl_give isl_set *isl_set_box_from_points( __isl_take isl_point *pnt1, __isl_take isl_point *pnt2); All elements of a bounded (union) set can be enumerated using the following functions. isl_stat isl_set_foreach_point(__isl_keep isl_set *set, isl_stat (*fn)(__isl_take isl_point *pnt, void *user), void *user); isl_stat isl_union_set_foreach_point( __isl_keep isl_union_set *uset, isl_stat (*fn)(__isl_take isl_point *pnt, void *user), void *user); 49 The function fn is called for each integer point in set with as second argument the last argument of the isl_set_foreach_point call. The function fn should return isl_stat_ok on success and isl_stat_error on failure. In the latter case, isl_set_foreach_point will stop enumerating and return isl_stat_error as well. If the enumeration is performed successfully and to completion, then isl_set_foreach_point returns isl_stat_ok. To obtain a single point of a (basic or union) set, use __isl_give isl_point *isl_basic_set_sample_point( __isl_take isl_basic_set *bset); __isl_give isl_point *isl_set_sample_point( __isl_take isl_set *set); __isl_give isl_point *isl_union_set_sample_point( __isl_take isl_union_set *uset); If set does not contain any (integer) points, then the resulting point will be “void”, a property that can be tested using isl_bool isl_point_is_void(__isl_keep isl_point *pnt); 1.4.13 Functions Besides sets and relation, isl also supports various types of functions. Each of these types is derived from the value type (see §1.4.4) or from one of two primitive function types through the application of zero or more type constructors. We first describe the primitive type and then we describe the types derived from these primitive types. Primitive Functions isl support two primitive function types, quasi-affine expressions and quasipolynomials. A quasi-affine expression is defined either over a parameter space or over a set and is composed of integer constants, parameters and set variables, addition, subtraction and integer division by an integer constant. For example, the quasi-affine expression [n] -> { [x] -> [2*floor((4 n + x)/9)] } maps x to 2*floor((4 n + x)/9. A quasipolynomial is a polynomial expression in quasi-affine expression. That is, it additionally allows for multiplication. Note, though, that it is not allowed to construct an integer division of an expression involving multiplications. Here is an example of a quasipolynomial that is not quasi-affine expression [n] -> { [x] -> (n*floor((4 n + x)/9)) } Note that the external representations of quasi-affine expressions and quasipolynomials are different. Quasi-affine expressions use a notation with square brackets just like binary relations, while quasipolynomials do not. This might change at some point. 50 If a primitive function is defined over a parameter space, then the space of the function itself is that of a set. If it is defined over a set, then the space of the function is that of a relation. In both cases, the set space (or the output space) is single-dimensional, anonymous and unstructured. To create functions with multiple dimensions or with other kinds of set or output spaces, use multiple expressions (see §1.4.13). • Quasi-affine Expressions Besides the expressions described above, a quasi-affine expression can also be set to NaN. Such expressions typically represent a failure to represent a result as a quasi-affine expression. The zero quasi affine expression or the quasi affine expression that is equal to a given value, parameter or a specified dimension on a given domain can be created using #include __isl_give isl_aff *isl_aff_zero_on_domain( __isl_take isl_local_space *ls); __isl_give isl_aff *isl_aff_val_on_domain( __isl_take isl_local_space *ls, __isl_take isl_val *val); __isl_give isl_aff *isl_aff_param_on_domain_space_id( __isl_take isl_space *space, __isl_take isl_id *id); __isl_give isl_aff *isl_aff_var_on_domain( __isl_take isl_local_space *ls, enum isl_dim_type type, unsigned pos); __isl_give isl_aff *isl_aff_nan_on_domain( __isl_take isl_local_space *ls); The space passed to isl_aff_param_on_domain_space_id is required to have a parameter with the given identifier. Quasi affine expressions can be copied and freed using #include __isl_give isl_aff *isl_aff_copy( __isl_keep isl_aff *aff); __isl_null isl_aff *isl_aff_free( __isl_take isl_aff *aff); A (rational) bound on a dimension can be extracted from an isl_constraint using the following function. The constraint is required to have a non-zero coefficient for the specified dimension. #include 51 __isl_give isl_aff *isl_constraint_get_bound( __isl_keep isl_constraint *constraint, enum isl_dim_type type, int pos); The entire affine expression of the constraint can also be extracted using the following function. #include __isl_give isl_aff *isl_constraint_get_aff( __isl_keep isl_constraint *constraint); Conversely, an equality constraint equating the affine expression to zero or an inequality constraint enforcing the affine expression to be non-negative, can be constructed using __isl_give isl_constraint *isl_equality_from_aff( __isl_take isl_aff *aff); __isl_give isl_constraint *isl_inequality_from_aff( __isl_take isl_aff *aff); The coefficients and the integer divisions of an affine expression can be inspected using the following functions. #include __isl_give isl_val *isl_aff_get_constant_val( __isl_keep isl_aff *aff); __isl_give isl_val *isl_aff_get_coefficient_val( __isl_keep isl_aff *aff, enum isl_dim_type type, int pos); int isl_aff_coefficient_sgn(__isl_keep isl_aff *aff, enum isl_dim_type type, int pos); __isl_give isl_val *isl_aff_get_denominator_val( __isl_keep isl_aff *aff); __isl_give isl_aff *isl_aff_get_div( __isl_keep isl_aff *aff, int pos); They can be modified using the following functions. #include __isl_give isl_aff *isl_aff_set_constant_si( __isl_take isl_aff *aff, int v); __isl_give isl_aff *isl_aff_set_constant_val( __isl_take isl_aff *aff, __isl_take isl_val *v); __isl_give isl_aff *isl_aff_set_coefficient_si( __isl_take isl_aff *aff, 52 enum isl_dim_type type, int pos, int v); __isl_give isl_aff *isl_aff_set_coefficient_val( __isl_take isl_aff *aff, enum isl_dim_type type, int pos, __isl_take isl_val *v); __isl_give isl_aff *isl_aff_add_constant_si( __isl_take isl_aff *aff, int v); __isl_give isl_aff *isl_aff_add_constant_val( __isl_take isl_aff *aff, __isl_take isl_val *v); __isl_give isl_aff *isl_aff_add_constant_num_si( __isl_take isl_aff *aff, int v); __isl_give isl_aff *isl_aff_add_coefficient_si( __isl_take isl_aff *aff, enum isl_dim_type type, int pos, int v); __isl_give isl_aff *isl_aff_add_coefficient_val( __isl_take isl_aff *aff, enum isl_dim_type type, int pos, __isl_take isl_val *v); Note that isl_aff_set_constant_si and isl_aff_set_coefficient_si set the numerator of the constant or coefficient, while isl_aff_set_constant_val and isl_aff_set_coefficient_val set the constant or coefficient as a whole. The add_constant and add_coefficient functions add an integer or rational value to the possibly rational constant or coefficient. The add_constant_num functions add an integer value to the numerator. • Quasipolynomials Some simple quasipolynomials can be created using the following functions. #include __isl_give isl_qpolynomial *isl_qpolynomial_zero_on_domain( __isl_take isl_space *domain); __isl_give isl_qpolynomial *isl_qpolynomial_one_on_domain( __isl_take isl_space *domain); __isl_give isl_qpolynomial *isl_qpolynomial_infty_on_domain( __isl_take isl_space *domain); __isl_give isl_qpolynomial *isl_qpolynomial_neginfty_on_domain( __isl_take isl_space *domain); __isl_give isl_qpolynomial *isl_qpolynomial_nan_on_domain( __isl_take isl_space *domain); __isl_give isl_qpolynomial *isl_qpolynomial_val_on_domain( __isl_take isl_space *domain, __isl_take isl_val *val); __isl_give isl_qpolynomial *isl_qpolynomial_var_on_domain( __isl_take isl_space *domain, 53 enum isl_dim_type type, unsigned pos); __isl_give isl_qpolynomial *isl_qpolynomial_from_aff( __isl_take isl_aff *aff); Recall that the space in which a quasipolynomial lives is a map space with a one-dimensional range. The domain argument in some of the functions above corresponds to the domain of this map space. Quasipolynomials can be copied and freed again using the following functions. #include __isl_give isl_qpolynomial *isl_qpolynomial_copy( __isl_keep isl_qpolynomial *qp); __isl_null isl_qpolynomial *isl_qpolynomial_free( __isl_take isl_qpolynomial *qp); The constant term of a quasipolynomial can be extracted using __isl_give isl_val *isl_qpolynomial_get_constant_val( __isl_keep isl_qpolynomial *qp); To iterate over all terms in a quasipolynomial, use isl_stat isl_qpolynomial_foreach_term( __isl_keep isl_qpolynomial *qp, isl_stat (*fn)(__isl_take isl_term *term, void *user), void *user); The terms themselves can be inspected and freed using these functions unsigned isl_term_dim(__isl_keep isl_term *term, enum isl_dim_type type); __isl_give isl_val *isl_term_get_coefficient_val( __isl_keep isl_term *term); int isl_term_get_exp(__isl_keep isl_term *term, enum isl_dim_type type, unsigned pos); __isl_give isl_aff *isl_term_get_div( __isl_keep isl_term *term, unsigned pos); void isl_term_free(__isl_take isl_term *term); Each term is a product of parameters, set variables and integer divisions. The function isl_term_get_exp returns the exponent of a given dimensions in the given term. 54 Reductions A reduction represents a maximum or a minimum of its base expressions. The only reduction type defined by isl is isl_qpolynomial_fold. There are currently no functions to directly create such objects, but they do appear in the piecewise quasipolynomial reductions returned by the isl_pw_qpolynomial_bound function. See §1.4.23. Reductions can be copied and freed using the following functions. #include __isl_give isl_qpolynomial_fold * isl_qpolynomial_fold_copy( __isl_keep isl_qpolynomial_fold *fold); void isl_qpolynomial_fold_free( __isl_take isl_qpolynomial_fold *fold); To iterate over all quasipolynomials in a reduction, use isl_stat isl_qpolynomial_fold_foreach_qpolynomial( __isl_keep isl_qpolynomial_fold *fold, isl_stat (*fn)(__isl_take isl_qpolynomial *qp, void *user), void *user); Multiple Expressions A multiple expression represents a sequence of zero or more base expressions, all defined on the same domain space. The domain space of the multiple expression is the same as that of the base expressions, but the range space can be any space. In case the base expressions have a set space, the corresponding multiple expression also has a set space. Objects of the value type do not have an associated space. The space of a multiple value is therefore always a set space. Similarly, the space of a multiple union piecewise affine expression is always a set space. If the base expressions are not total, then a corresponding zero-dimensional multiple expression may have an explicit domain that keeps track of the domain outside of any base expressions. The multiple expression types defined by isl are isl_multi_val, isl_multi_aff, isl_multi_pw_aff, isl_multi_union_pw_aff. A multiple expression with the value zero for each output (or set) dimension can be created using the following functions. #include __isl_give isl_multi_val *isl_multi_val_zero( __isl_take isl_space *space); #include __isl_give isl_multi_aff *isl_multi_aff_zero( __isl_take isl_space *space); __isl_give isl_multi_pw_aff *isl_multi_pw_aff_zero( 55 __isl_take isl_space *space); __isl_give isl_multi_union_pw_aff * isl_multi_union_pw_aff_zero( __isl_take isl_space *space); Since there is no canonical way of representing a zero value of type isl_union_pw_aff, the space passed to isl_multi_union_pw_aff_zero needs to be zero-dimensional. An identity function can be created using the following functions. The space needs to be that of a relation with the same number of input and output dimensions. #include __isl_give isl_multi_aff *isl_multi_aff_identity( __isl_take isl_space *space); __isl_give isl_multi_pw_aff *isl_multi_pw_aff_identity( __isl_take isl_space *space); A function that performs a projection on a universe relation or set can be created using the following functions. See also the corresponding projection operations in §1.4.16. #include __isl_give isl_multi_aff *isl_multi_aff_domain_map( __isl_take isl_space *space); __isl_give isl_multi_aff *isl_multi_aff_range_map( __isl_take isl_space *space); __isl_give isl_multi_aff *isl_multi_aff_project_out_map( __isl_take isl_space *space, enum isl_dim_type type, unsigned first, unsigned n); A multiple expression can be created from a single base expression using the following functions. The space of the created multiple expression is the same as that of the base expression, except for isl_multi_union_pw_aff_from_union_pw_aff where the input lives in a parameter space and the output lives in a single-dimensional set space. #include __isl_give isl_multi_aff *isl_multi_aff_from_aff( __isl_take isl_aff *aff); __isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_pw_aff( __isl_take isl_pw_aff *pa); __isl_give isl_multi_union_pw_aff * isl_multi_union_pw_aff_from_union_pw_aff( __isl_take isl_union_pw_aff *upa); A multiple expression can be created from a list of base expression in a specified space. The domain of this space needs to be the same as the domains of the base expressions in the list. If the base expressions have a set space (or no associated space), then this space also needs to be a set space. 56 #include __isl_give isl_multi_val *isl_multi_val_from_val_list( __isl_take isl_space *space, __isl_take isl_val_list *list); #include __isl_give isl_multi_aff *isl_multi_aff_from_aff_list( __isl_take isl_space *space, __isl_take isl_aff_list *list); __isl_give isl_multi_pw_aff * isl_multi_pw_aff_from_pw_aff_list( __isl_take isl_space *space, __isl_take isl_pw_aff_list *list); __isl_give isl_multi_union_pw_aff * isl_multi_union_pw_aff_from_union_pw_aff_list( __isl_take isl_space *space, __isl_take isl_union_pw_aff_list *list); As a convenience, a multiple piecewise expression can also be created from a multiple expression. Each piecewise expression in the result has a single universe cell. #include __isl_give isl_multi_pw_aff * isl_multi_pw_aff_from_multi_aff( __isl_take isl_multi_aff *ma); Similarly, a multiple union expression can be created from a multiple expression. #include __isl_give isl_multi_union_pw_aff * isl_multi_union_pw_aff_from_multi_aff( __isl_take isl_multi_aff *ma); __isl_give isl_multi_union_pw_aff * isl_multi_union_pw_aff_from_multi_pw_aff( __isl_take isl_multi_pw_aff *mpa); A multiple quasi-affine expression can be created from a multiple value with a given domain space using the following function. #include __isl_give isl_multi_aff * isl_multi_aff_multi_val_on_space( __isl_take isl_space *space, __isl_take isl_multi_val *mv); Similarly, a multiple union piecewise affine expression can be created from a multiple value with a given domain or a (piecewise) multiple affine expression with a given domain using the following functions. 57 #include __isl_give isl_multi_union_pw_aff * isl_multi_union_pw_aff_multi_val_on_domain( __isl_take isl_union_set *domain, __isl_take isl_multi_val *mv); __isl_give isl_multi_union_pw_aff * isl_multi_union_pw_aff_multi_aff_on_domain( __isl_take isl_union_set *domain, __isl_take isl_multi_aff *ma); __isl_give isl_multi_union_pw_aff * isl_multi_union_pw_aff_pw_multi_aff_on_domain( __isl_take isl_union_set *domain, __isl_take isl_pw_multi_aff *pma); Multiple expressions can be copied and freed using the following functions. #include __isl_give isl_multi_val *isl_multi_val_copy( __isl_keep isl_multi_val *mv); __isl_null isl_multi_val *isl_multi_val_free( __isl_take isl_multi_val *mv); #include __isl_give isl_multi_aff *isl_multi_aff_copy( __isl_keep isl_multi_aff *maff); __isl_null isl_multi_aff *isl_multi_aff_free( __isl_take isl_multi_aff *maff); __isl_give isl_multi_pw_aff *isl_multi_pw_aff_copy( __isl_keep isl_multi_pw_aff *mpa); __isl_null isl_multi_pw_aff *isl_multi_pw_aff_free( __isl_take isl_multi_pw_aff *mpa); __isl_give isl_multi_union_pw_aff * isl_multi_union_pw_aff_copy( __isl_keep isl_multi_union_pw_aff *mupa); __isl_null isl_multi_union_pw_aff * isl_multi_union_pw_aff_free( __isl_take isl_multi_union_pw_aff *mupa); The base expression at a given position of a multiple expression can be extracted using the following functions. #include __isl_give isl_val *isl_multi_val_get_val( __isl_keep isl_multi_val *mv, int pos); #include __isl_give isl_aff *isl_multi_aff_get_aff( 58 __isl_keep isl_multi_aff *multi, int pos); __isl_give isl_pw_aff *isl_multi_pw_aff_get_pw_aff( __isl_keep isl_multi_pw_aff *mpa, int pos); __isl_give isl_union_pw_aff * isl_multi_union_pw_aff_get_union_pw_aff( __isl_keep isl_multi_union_pw_aff *mupa, int pos); It can be replaced using the following functions. #include __isl_give isl_multi_val *isl_multi_val_set_val( __isl_take isl_multi_val *mv, int pos, __isl_take isl_val *val); #include __isl_give isl_multi_aff *isl_multi_aff_set_aff( __isl_take isl_multi_aff *multi, int pos, __isl_take isl_aff *aff); __isl_give isl_multi_union_pw_aff * isl_multi_union_pw_aff_set_union_pw_aff( __isl_take isl_multi_union_pw_aff *mupa, int pos, __isl_take isl_union_pw_aff *upa); As a convenience, a sequence of base expressions that have their domains in a given space can be extracted from a sequence of union expressions using the following function. #include __isl_give isl_multi_pw_aff * isl_multi_union_pw_aff_extract_multi_pw_aff( __isl_keep isl_multi_union_pw_aff *mupa, __isl_take isl_space *space); Note that there is a difference between isl_multi_union_pw_aff and isl_union_pw_multi_aff objects. The first is a sequence of unions of piecewise expressions, while the second is a union of piecewise sequences. In particular, multiple affine expressions in an isl_union_pw_multi_aff may live in different spaces, while there is only a single multiple expression in an isl_multi_union_pw_aff, which can therefore only live in a single space. This means that not every isl_union_pw_multi_aff can be converted to an isl_multi_union_pw_aff. Conversely, the elements of an isl_multi_union_pw_aff may be defined over different domains, while each multiple expression inside an isl_union_pw_multi_aff has a single domain. The conversion of an isl_union_pw_multi_aff of dimension greater than one may therefore not be exact. The following functions can be used to perform these conversions when they are possible. #include 59 __isl_give isl_multi_union_pw_aff * isl_multi_union_pw_aff_from_union_pw_multi_aff( __isl_take isl_union_pw_multi_aff *upma); __isl_give isl_union_pw_multi_aff * isl_union_pw_multi_aff_from_multi_union_pw_aff( __isl_take isl_multi_union_pw_aff *mupa); Piecewise Expressions A piecewise expression is an expression that is described using zero or more base expression defined over the same number of cells in the domain space of the base expressions. All base expressions are defined over the same domain space and the cells are disjoint. The space of a piecewise expression is the same as that of the base expressions. If the union of the cells is a strict subset of the domain space, then the value of the piecewise expression outside this union is different for types derived from quasi-affine expressions and those derived from quasipolynomials. Piecewise expressions derived from quasi-affine expressions are considered to be undefined outside the union of their cells. Piecewise expressions derived from quasipolynomials are considered to be zero outside the union of their cells. Piecewise quasipolynomials are mainly used by the barvinok library for representing the number of elements in a parametric set or map. For example, the piecewise quasipolynomial [n] -> { [x] -> ((1 + n) - x) : x <= n and x >= 0 } represents the number of points in the map [n] -> { [x] -> [y] : x,y >= 0 and 0 <= x + y <= n } The piecewise expression types defined by isl are isl_pw_aff, isl_pw_multi_aff, isl_pw_qpolynomial and isl_pw_qpolynomial_fold. A piecewise expression with no cells can be created using the following functions. #include __isl_give isl_pw_aff *isl_pw_aff_empty( __isl_take isl_space *space); __isl_give isl_pw_multi_aff *isl_pw_multi_aff_empty( __isl_take isl_space *space); A piecewise expression with a single universe cell can be created using the following functions. #include __isl_give isl_pw_aff *isl_pw_aff_from_aff( __isl_take isl_aff *aff); __isl_give isl_pw_multi_aff * isl_pw_multi_aff_from_multi_aff( __isl_take isl_multi_aff *ma); 60 #include __isl_give isl_pw_qpolynomial * isl_pw_qpolynomial_from_qpolynomial( __isl_take isl_qpolynomial *qp); A piecewise expression with a single specified cell can be created using the following functions. #include __isl_give isl_pw_aff *isl_pw_aff_alloc( __isl_take isl_set *set, __isl_take isl_aff *aff); __isl_give isl_pw_multi_aff *isl_pw_multi_aff_alloc( __isl_take isl_set *set, __isl_take isl_multi_aff *maff); #include __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_alloc( __isl_take isl_set *set, __isl_take isl_qpolynomial *qp); The following convenience functions first create a base expression and then create a piecewise expression over a universe domain. #include __isl_give isl_pw_aff *isl_pw_aff_zero_on_domain( __isl_take isl_local_space *ls); __isl_give isl_pw_aff *isl_pw_aff_var_on_domain( __isl_take isl_local_space *ls, enum isl_dim_type type, unsigned pos); __isl_give isl_pw_aff *isl_pw_aff_nan_on_domain( __isl_take isl_local_space *ls); __isl_give isl_pw_multi_aff *isl_pw_multi_aff_zero( __isl_take isl_space *space); __isl_give isl_pw_multi_aff *isl_pw_multi_aff_identity( __isl_take isl_space *space); __isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_map( __isl_take isl_space *space); __isl_give isl_pw_multi_aff * isl_pw_multi_aff_project_out_map( __isl_take isl_space *space, enum isl_dim_type type, unsigned first, unsigned n); #include __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_zero( __isl_take isl_space *space); 61 The following convenience functions first create a base expression and then create a piecewise expression over a given domain. #include __isl_give isl_pw_aff *isl_pw_aff_val_on_domain( __isl_take isl_set *domain, __isl_take isl_val *v); __isl_give isl_pw_multi_aff * isl_pw_multi_aff_multi_val_on_domain( __isl_take isl_set *domain, __isl_take isl_multi_val *mv); As a convenience, a piecewise multiple expression can also be created from a piecewise expression. Each multiple expression in the result is derived from the corresponding base expression. #include __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_pw_aff( __isl_take isl_pw_aff *pa); Similarly, a piecewise quasipolynomial can be created from a piecewise quasiaffine expression using the following function. #include __isl_give isl_pw_qpolynomial * isl_pw_qpolynomial_from_pw_aff( __isl_take isl_pw_aff *pwaff); Piecewise expressions can be copied and freed using the following functions. #include __isl_give isl_pw_aff *isl_pw_aff_copy( __isl_keep isl_pw_aff *pwaff); __isl_null isl_pw_aff *isl_pw_aff_free( __isl_take isl_pw_aff *pwaff); __isl_give isl_pw_multi_aff *isl_pw_multi_aff_copy( __isl_keep isl_pw_multi_aff *pma); __isl_null isl_pw_multi_aff *isl_pw_multi_aff_free( __isl_take isl_pw_multi_aff *pma); #include __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_copy( __isl_keep isl_pw_qpolynomial *pwqp); __isl_null isl_pw_qpolynomial *isl_pw_qpolynomial_free( __isl_take isl_pw_qpolynomial *pwqp); __isl_give isl_pw_qpolynomial_fold * isl_pw_qpolynomial_fold_copy( 62 __isl_keep isl_pw_qpolynomial_fold *pwf); __isl_null isl_pw_qpolynomial_fold * isl_pw_qpolynomial_fold_free( __isl_take isl_pw_qpolynomial_fold *pwf); To iterate over the different cells of a piecewise expression, use the following functions. #include isl_bool isl_pw_aff_is_empty(__isl_keep isl_pw_aff *pwaff); int isl_pw_aff_n_piece(__isl_keep isl_pw_aff *pwaff); isl_stat isl_pw_aff_foreach_piece( __isl_keep isl_pw_aff *pwaff, isl_stat (*fn)(__isl_take isl_set *set, __isl_take isl_aff *aff, void *user), void *user); int isl_pw_multi_aff_n_piece( __isl_keep isl_pw_multi_aff *pma); isl_stat isl_pw_multi_aff_foreach_piece( __isl_keep isl_pw_multi_aff *pma, isl_stat (*fn)(__isl_take isl_set *set, __isl_take isl_multi_aff *maff, void *user), void *user); #include int isl_pw_qpolynomial_n_piece( __isl_keep isl_pw_qpolynomial *pwqp); isl_stat isl_pw_qpolynomial_foreach_piece( __isl_keep isl_pw_qpolynomial *pwqp, isl_stat (*fn)(__isl_take isl_set *set, __isl_take isl_qpolynomial *qp, void *user), void *user); isl_stat isl_pw_qpolynomial_foreach_lifted_piece( __isl_keep isl_pw_qpolynomial *pwqp, isl_stat (*fn)(__isl_take isl_set *set, __isl_take isl_qpolynomial *qp, void *user), void *user); int isl_pw_qpolynomial_fold_n_piece( __isl_keep isl_pw_qpolynomial_fold *pwf); isl_stat isl_pw_qpolynomial_fold_foreach_piece( __isl_keep isl_pw_qpolynomial_fold *pwf, isl_stat (*fn)(__isl_take isl_set *set, __isl_take isl_qpolynomial_fold *fold, void *user), void *user); isl_stat isl_pw_qpolynomial_fold_foreach_lifted_piece( __isl_keep isl_pw_qpolynomial_fold *pwf, isl_stat (*fn)(__isl_take isl_set *set, 63 __isl_take isl_qpolynomial_fold *fold, void *user), void *user); As usual, the function fn should return isl_stat_ok on success and isl_stat_error on failure. The difference between isl_pw_qpolynomial_foreach_piece and isl_pw_qpolynomial_foreach_lif is that isl_pw_qpolynomial_foreach_lifted_piece will first compute unique representations for all existentially quantified variables and then turn these existentially quantified variables into extra set variables, adapting the associated quasipolynomial accordingly. This means that the set passed to fn will not have any existentially quantified variables, but that the dimensions of the sets may be different for different invocations of fn. Similarly for isl_pw_qpolynomial_fold_foreach_piece and isl_pw_qpolynomial_fold_foreach_lifted_piece. A piecewise expression consisting of the expressions at a given position of a piecewise multiple expression can be extracted using the following function. #include __isl_give isl_pw_aff *isl_pw_multi_aff_get_pw_aff( __isl_keep isl_pw_multi_aff *pma, int pos); These expressions can be replaced using the following function. #include __isl_give isl_pw_multi_aff *isl_pw_multi_aff_set_pw_aff( __isl_take isl_pw_multi_aff *pma, unsigned pos, __isl_take isl_pw_aff *pa); Note that there is a difference between isl_multi_pw_aff and isl_pw_multi_aff objects. The first is a sequence of piecewise affine expressions, while the second is a piecewise sequence of affine expressions. In particular, each of the piecewise affine expressions in an isl_multi_pw_aff may have a different domain, while all multiple expressions associated to a cell in an isl_pw_multi_aff have the same domain. It is possible to convert between the two, but when converting an isl_multi_pw_aff to an isl_pw_multi_aff, the domain of the result is the intersection of the domains of the input. The reverse conversion is exact. #include __isl_give isl_pw_multi_aff * isl_pw_multi_aff_from_multi_pw_aff( __isl_take isl_multi_pw_aff *mpa); __isl_give isl_multi_pw_aff * isl_multi_pw_aff_from_pw_multi_aff( __isl_take isl_pw_multi_aff *pma); Union Expressions A union expression collects base expressions defined over different domains. The space of a union expression is that of the shared parameter space. 64 The union expression types defined by isl are isl_union_pw_aff, isl_union_pw_multi_aff, isl_union_pw_qpolynomial and isl_union_pw_qpolynomial_fold. In case of isl_union_pw_aff, isl_union_pw_qpolynomial and isl_union_pw_qpolynomial_fold, there can be at most one base expression for a given domain space. In case of isl_union_pw_multi_aff, there can be multiple such expressions for a given domain space, but the domains of these expressions need to be disjoint. An empty union expression can be created using the following functions. #include __isl_give isl_union_pw_aff *isl_union_pw_aff_empty( __isl_take isl_space *space); __isl_give isl_union_pw_multi_aff * isl_union_pw_multi_aff_empty( __isl_take isl_space *space); #include __isl_give isl_union_pw_qpolynomial * isl_union_pw_qpolynomial_zero( __isl_take isl_space *space); A union expression containing a single base expression can be created using the following functions. #include __isl_give isl_union_pw_aff * isl_union_pw_aff_from_pw_aff( __isl_take isl_pw_aff *pa); __isl_give isl_union_pw_multi_aff * isl_union_pw_multi_aff_from_aff( __isl_take isl_aff *aff); __isl_give isl_union_pw_multi_aff * isl_union_pw_multi_aff_from_pw_multi_aff( __isl_take isl_pw_multi_aff *pma); #include __isl_give isl_union_pw_qpolynomial * isl_union_pw_qpolynomial_from_pw_qpolynomial( __isl_take isl_pw_qpolynomial *pwqp); The following functions create a base expression on each of the sets in the union set and collect the results. #include __isl_give isl_union_pw_multi_aff * isl_union_pw_multi_aff_from_union_pw_aff( __isl_take isl_union_pw_aff *upa); __isl_give isl_union_pw_aff * 65 isl_union_pw_multi_aff_get_union_pw_aff( __isl_keep isl_union_pw_multi_aff *upma, int pos); __isl_give isl_union_pw_aff * isl_union_pw_aff_val_on_domain( __isl_take isl_union_set *domain, __isl_take isl_val *v); __isl_give isl_union_pw_multi_aff * isl_union_pw_multi_aff_multi_val_on_domain( __isl_take isl_union_set *domain, __isl_take isl_multi_val *mv); __isl_give isl_union_pw_aff * isl_union_pw_aff_param_on_domain_id( __isl_take isl_union_set *domain, __isl_take isl_id *id); The id argument of isl_union_pw_aff_param_on_domain_id is the identifier of a parameter that may or may not already be present in domain. An isl_union_pw_aff that is equal to a (parametric) affine or piecewise affine expression on a given domain can be created using the following functions. #include __isl_give isl_union_pw_aff * isl_union_pw_aff_aff_on_domain( __isl_take isl_union_set *domain, __isl_take isl_aff *aff); __isl_give isl_union_pw_aff * isl_union_pw_aff_pw_aff_on_domain( __isl_take isl_union_set *domain, __isl_take isl_pw_aff *pa); A base expression can be added to a union expression using the following functions. #include __isl_give isl_union_pw_aff * isl_union_pw_aff_add_pw_aff( __isl_take isl_union_pw_aff *upa, __isl_take isl_pw_aff *pa); __isl_give isl_union_pw_multi_aff * isl_union_pw_multi_aff_add_pw_multi_aff( __isl_take isl_union_pw_multi_aff *upma, __isl_take isl_pw_multi_aff *pma); #include __isl_give isl_union_pw_qpolynomial * isl_union_pw_qpolynomial_add_pw_qpolynomial( __isl_take isl_union_pw_qpolynomial *upwqp, __isl_take isl_pw_qpolynomial *pwqp); 66 Union expressions can be copied and freed using the following functions. #include __isl_give isl_union_pw_aff *isl_union_pw_aff_copy( __isl_keep isl_union_pw_aff *upa); __isl_null isl_union_pw_aff *isl_union_pw_aff_free( __isl_take isl_union_pw_aff *upa); __isl_give isl_union_pw_multi_aff * isl_union_pw_multi_aff_copy( __isl_keep isl_union_pw_multi_aff *upma); __isl_null isl_union_pw_multi_aff * isl_union_pw_multi_aff_free( __isl_take isl_union_pw_multi_aff *upma); #include __isl_give isl_union_pw_qpolynomial * isl_union_pw_qpolynomial_copy( __isl_keep isl_union_pw_qpolynomial *upwqp); __isl_null isl_union_pw_qpolynomial * isl_union_pw_qpolynomial_free( __isl_take isl_union_pw_qpolynomial *upwqp); __isl_give isl_union_pw_qpolynomial_fold * isl_union_pw_qpolynomial_fold_copy( __isl_keep isl_union_pw_qpolynomial_fold *upwf); __isl_null isl_union_pw_qpolynomial_fold * isl_union_pw_qpolynomial_fold_free( __isl_take isl_union_pw_qpolynomial_fold *upwf); To iterate over the base expressions in a union expression, use the following functions. #include int isl_union_pw_aff_n_pw_aff( __isl_keep isl_union_pw_aff *upa); isl_stat isl_union_pw_aff_foreach_pw_aff( __isl_keep isl_union_pw_aff *upa, isl_stat (*fn)(__isl_take isl_pw_aff *pa, void *user), void *user); int isl_union_pw_multi_aff_n_pw_multi_aff( __isl_keep isl_union_pw_multi_aff *upma); isl_stat isl_union_pw_multi_aff_foreach_pw_multi_aff( __isl_keep isl_union_pw_multi_aff *upma, isl_stat (*fn)(__isl_take isl_pw_multi_aff *pma, void *user), void *user); #include int isl_union_pw_qpolynomial_n_pw_qpolynomial( 67 __isl_keep isl_union_pw_qpolynomial *upwqp); isl_stat isl_union_pw_qpolynomial_foreach_pw_qpolynomial( __isl_keep isl_union_pw_qpolynomial *upwqp, isl_stat (*fn)(__isl_take isl_pw_qpolynomial *pwqp, void *user), void *user); int isl_union_pw_qpolynomial_fold_n_pw_qpolynomial_fold( __isl_keep isl_union_pw_qpolynomial_fold *upwf); isl_stat isl_union_pw_qpolynomial_fold_foreach_pw_qpolynomial_fold( __isl_keep isl_union_pw_qpolynomial_fold *upwf, isl_stat (*fn)(__isl_take isl_pw_qpolynomial_fold *pwf, void *user), void *user); To extract the base expression in a given space from a union, use the following functions. #include __isl_give isl_pw_aff *isl_union_pw_aff_extract_pw_aff( __isl_keep isl_union_pw_aff *upa, __isl_take isl_space *space); __isl_give isl_pw_multi_aff * isl_union_pw_multi_aff_extract_pw_multi_aff( __isl_keep isl_union_pw_multi_aff *upma, __isl_take isl_space *space); #include __isl_give isl_pw_qpolynomial * isl_union_pw_qpolynomial_extract_pw_qpolynomial( __isl_keep isl_union_pw_qpolynomial *upwqp, __isl_take isl_space *space); It is also possible to obtain a list of the base expressions using the following functions. #include __isl_give isl_pw_aff_list * isl_union_pw_aff_get_pw_aff_list( __isl_keep isl_union_pw_aff *upa); __isl_give isl_pw_multi_aff_list * isl_union_pw_multi_aff_get_pw_multi_aff_list( __isl_keep isl_union_pw_multi_aff *upma); #include __isl_give isl_pw_qpolynomial_list * isl_union_pw_qpolynomial_get_pw_qpolynomial_list( __isl_keep isl_union_pw_qpolynomial *upwqp); __isl_give isl_pw_qpolynomial_fold_list * isl_union_pw_qpolynomial_fold_get_pw_qpolynomial_fold_list( __isl_keep isl_union_pw_qpolynomial_fold *upwf); The returned list can be manipulated using the functions in §1.4.19. 68 1.4.14 Input and Output For set and relation, isl supports its own input/output format, which is similar to the Omega format, but also supports the PolyLib format in some cases. For other object types, typically only an isl format is supported. isl format The isl format is similar to that of Omega, but has a different syntax for describing the parameters and allows for the definition of an existentially quantified variable as the integer division of an affine expression. For example, the set of integers i between 0 and n such that i % 10 <= 6 can be described as [n] -> { [i] : exists (a = [i/10] : 0 <= i and i <= n and i - 10 a <= 6) } A set or relation can have several disjuncts, separated by the keyword or. Each disjunct is either a conjunction of constraints or a projection (exists) of a conjunction of constraints. The constraints are separated by the keyword and. PolyLib format If the represented set is a union, then the first line contains a single number representing the number of disjuncts. Otherwise, a line containing the number 1 is optional. Each disjunct is represented by a matrix of constraints. The first line contains two numbers representing the number of rows and columns, where the number of rows is equal to the number of constraints and the number of columns is equal to two plus the number of variables. The following lines contain the actual rows of the constraint matrix. In each row, the first column indicates whether the constraint is an equality (0) or inequality (1). The final column corresponds to the constant term. If the set is parametric, then the coefficients of the parameters appear in the last columns before the constant column. The coefficients of any existentially quantified variables appear between those of the set variables and those of the parameters. Extended PolyLib format The extended PolyLib format is nearly identical to the PolyLib format. The only difference is that the line containing the number of rows and columns of a constraint matrix also contains four additional numbers: the number of output dimensions, the number of input dimensions, the number of local dimensions (i.e., the number of existentially quantified variables) and the number of parameters. For sets, the number of “output” dimensions is equal to the number of set dimensions, while the number of “input” dimensions is zero. Input Objects can be read from input using the following functions. 69 #include __isl_give isl_val *isl_val_read_from_str(isl_ctx *ctx, const char *str); __isl_give isl_multi_val *isl_multi_val_read_from_str( isl_ctx *ctx, const char *str); #include __isl_give isl_basic_set *isl_basic_set_read_from_file( isl_ctx *ctx, FILE *input); __isl_give isl_basic_set *isl_basic_set_read_from_str( isl_ctx *ctx, const char *str); __isl_give isl_set *isl_set_read_from_file(isl_ctx *ctx, FILE *input); __isl_give isl_set *isl_set_read_from_str(isl_ctx *ctx, const char *str); #include __isl_give isl_basic_map *isl_basic_map_read_from_file( isl_ctx *ctx, FILE *input); __isl_give isl_basic_map *isl_basic_map_read_from_str( isl_ctx *ctx, const char *str); __isl_give isl_map *isl_map_read_from_file( isl_ctx *ctx, FILE *input); __isl_give isl_map *isl_map_read_from_str(isl_ctx *ctx, const char *str); #include __isl_give isl_union_set *isl_union_set_read_from_file( isl_ctx *ctx, FILE *input); __isl_give isl_union_set *isl_union_set_read_from_str( isl_ctx *ctx, const char *str); #include __isl_give isl_union_map *isl_union_map_read_from_file( isl_ctx *ctx, FILE *input); __isl_give isl_union_map *isl_union_map_read_from_str( isl_ctx *ctx, const char *str); #include __isl_give isl_aff *isl_aff_read_from_str( isl_ctx *ctx, const char *str); __isl_give isl_multi_aff *isl_multi_aff_read_from_str( isl_ctx *ctx, const char *str); __isl_give isl_pw_aff *isl_pw_aff_read_from_str( isl_ctx *ctx, const char *str); __isl_give isl_pw_multi_aff *isl_pw_multi_aff_read_from_str( isl_ctx *ctx, const char *str); 70 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_read_from_str( isl_ctx *ctx, const char *str); __isl_give isl_union_pw_aff * isl_union_pw_aff_read_from_str( isl_ctx *ctx, const char *str); __isl_give isl_union_pw_multi_aff * isl_union_pw_multi_aff_read_from_str( isl_ctx *ctx, const char *str); __isl_give isl_multi_union_pw_aff * isl_multi_union_pw_aff_read_from_str( isl_ctx *ctx, const char *str); #include __isl_give isl_union_pw_qpolynomial * isl_union_pw_qpolynomial_read_from_str( isl_ctx *ctx, const char *str); For sets and relations, the input format is autodetected and may be either the PolyLib format or the isl format. Output Before anything can be printed, an isl_printer needs to be created. __isl_give isl_printer *isl_printer_to_file(isl_ctx *ctx, FILE *file); __isl_give isl_printer *isl_printer_to_str(isl_ctx *ctx); __isl_null isl_printer *isl_printer_free( __isl_take isl_printer *printer); isl_printer_to_file prints to the given file, while isl_printer_to_str prints to a string that can be extracted using the following function. #include __isl_give char *isl_printer_get_str( __isl_keep isl_printer *printer); The printer can be inspected using the following functions. FILE *isl_printer_get_file( __isl_keep isl_printer *printer); int isl_printer_get_output_format( __isl_keep isl_printer *p); int isl_printer_get_yaml_style(__isl_keep isl_printer *p); The behavior of the printer can be modified in various ways 71 __isl_give isl_printer *isl_printer_set_output_format( __isl_take isl_printer *p, int output_format); __isl_give isl_printer *isl_printer_set_indent( __isl_take isl_printer *p, int indent); __isl_give isl_printer *isl_printer_set_indent_prefix( __isl_take isl_printer *p, const char *prefix); __isl_give isl_printer *isl_printer_indent( __isl_take isl_printer *p, int indent); __isl_give isl_printer *isl_printer_set_prefix( __isl_take isl_printer *p, const char *prefix); __isl_give isl_printer *isl_printer_set_suffix( __isl_take isl_printer *p, const char *suffix); __isl_give isl_printer *isl_printer_set_yaml_style( __isl_take isl_printer *p, int yaml_style); The output_format may be either ISL_FORMAT_ISL, ISL_FORMAT_OMEGA, ISL_FORMAT_POLYLIB, ISL_FORMAT_EXT_POLYLIB or ISL_FORMAT_LATEX and defaults to ISL_FORMAT_ISL. Each line in the output is prefixed by indent_prefix, indented by indent (set by isl_printer_set_indent) spaces (default: 0), prefixed by prefix and suffixed by suffix. In the PolyLib format output, the coefficients of the existentially quantified variables appear between those of the set variables and those of the parameters. The function isl_printer_indent increases the indentation by the specified amount (which may be negative). The YAML style may be either ISL_YAML_STYLE_BLOCK or ISL_YAML_STYLE_FLOW and when we are printing something in YAML format. To actually print something, use #include __isl_give isl_printer *isl_printer_print_double( __isl_take isl_printer *p, double d); #include __isl_give isl_printer *isl_printer_print_val( __isl_take isl_printer *p, __isl_keep isl_val *v); #include __isl_give isl_printer *isl_printer_print_basic_set( __isl_take isl_printer *printer, __isl_keep isl_basic_set *bset); __isl_give isl_printer *isl_printer_print_set( __isl_take isl_printer *printer, __isl_keep isl_set *set); #include __isl_give isl_printer *isl_printer_print_basic_map( __isl_take isl_printer *printer, __isl_keep isl_basic_map *bmap); __isl_give isl_printer *isl_printer_print_map( 72 __isl_take isl_printer *printer, __isl_keep isl_map *map); #include __isl_give isl_printer *isl_printer_print_union_set( __isl_take isl_printer *p, __isl_keep isl_union_set *uset); #include __isl_give isl_printer *isl_printer_print_union_map( __isl_take isl_printer *p, __isl_keep isl_union_map *umap); #include __isl_give isl_printer *isl_printer_print_multi_val( __isl_take isl_printer *p, __isl_keep isl_multi_val *mv); #include __isl_give isl_printer *isl_printer_print_aff( __isl_take isl_printer *p, __isl_keep isl_aff *aff); __isl_give isl_printer *isl_printer_print_multi_aff( __isl_take isl_printer *p, __isl_keep isl_multi_aff *maff); __isl_give isl_printer *isl_printer_print_pw_aff( __isl_take isl_printer *p, __isl_keep isl_pw_aff *pwaff); __isl_give isl_printer *isl_printer_print_pw_multi_aff( __isl_take isl_printer *p, __isl_keep isl_pw_multi_aff *pma); __isl_give isl_printer *isl_printer_print_multi_pw_aff( __isl_take isl_printer *p, __isl_keep isl_multi_pw_aff *mpa); __isl_give isl_printer *isl_printer_print_union_pw_aff( __isl_take isl_printer *p, __isl_keep isl_union_pw_aff *upa); __isl_give isl_printer *isl_printer_print_union_pw_multi_aff( __isl_take isl_printer *p, __isl_keep isl_union_pw_multi_aff *upma); __isl_give isl_printer * isl_printer_print_multi_union_pw_aff( __isl_take isl_printer *p, __isl_keep isl_multi_union_pw_aff *mupa); #include __isl_give isl_printer *isl_printer_print_qpolynomial( __isl_take isl_printer *p, 73 __isl_keep isl_qpolynomial *qp); __isl_give isl_printer *isl_printer_print_pw_qpolynomial( __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp); __isl_give isl_printer *isl_printer_print_union_pw_qpolynomial( __isl_take isl_printer *p, __isl_keep isl_union_pw_qpolynomial *upwqp); __isl_give isl_printer * isl_printer_print_pw_qpolynomial_fold( __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf); __isl_give isl_printer * isl_printer_print_union_pw_qpolynomial_fold( __isl_take isl_printer *p, __isl_keep isl_union_pw_qpolynomial_fold *upwf); For isl_printer_print_qpolynomial, isl_printer_print_pw_qpolynomial and isl_printer_print_pw_qpolynomial_fold, the output format of the printer needs to be set to either ISL_FORMAT_ISL or ISL_FORMAT_C. For isl_printer_print_union_pw_qpolynomial and isl_printer_print_union_pw_qpolynomial_fold, only ISL_FORMAT_ISL is supported. In case of printing in ISL_FORMAT_C, the user may want to set the names of all dimensions first. isl also provides limited support for printing YAML documents, just enough for the internal use for printing such documents. #include __isl_give isl_printer *isl_printer_yaml_start_mapping( __isl_take isl_printer *p); __isl_give isl_printer *isl_printer_yaml_end_mapping( __isl_take isl_printer *p); __isl_give isl_printer *isl_printer_yaml_start_sequence( __isl_take isl_printer *p); __isl_give isl_printer *isl_printer_yaml_end_sequence( __isl_take isl_printer *p); __isl_give isl_printer *isl_printer_yaml_next( __isl_take isl_printer *p); A document is started by a call to either isl_printer_yaml_start_mapping or isl_printer_yaml_start_sequence. Anything printed to the printer after such a call belong to the first key of the mapping or the first element in the sequence. The function isl_printer_yaml_next moves to the value if we are currently printing a mapping key, the next key if we are printing a value or the next element if we are printing an element in a sequence. Nested mappings and sequences are initiated by the same isl_printer_yaml_start_mapping or isl_printer_yaml_start_sequence. Each call to these functions needs to have a corresponding call to isl_printer_yaml_end_mapping or isl_printer_yaml_end_sequence. 74 When called on a file printer, the following function flushes the file. When called on a string printer, the buffer is cleared. __isl_give isl_printer *isl_printer_flush( __isl_take isl_printer *p); The following functions allow the user to attach notes to a printer in order to keep track of additional state. #include isl_bool isl_printer_has_note(__isl_keep isl_printer *p, __isl_keep isl_id *id); __isl_give isl_id *isl_printer_get_note( __isl_keep isl_printer *p, __isl_take isl_id *id); __isl_give isl_printer *isl_printer_set_note( __isl_take isl_printer *p, __isl_take isl_id *id, __isl_take isl_id *note); isl_printer_set_note associates the given note to the given identifier in the printer. isl_printer_get_note retrieves a note associated to an identifier, while isl_printer_has_note checks if there is such a note. isl_printer_get_note fails if the requested note does not exist. Alternatively, a string representation can be obtained directly using the following functions, which always print in isl format. #include __isl_give char *isl_id_to_str( __isl_keep isl_id *id); #include __isl_give char *isl_space_to_str( __isl_keep isl_space *space); #include __isl_give char *isl_val_to_str(__isl_keep isl_val *v); __isl_give char *isl_multi_val_to_str( __isl_keep isl_multi_val *mv); #include __isl_give char *isl_basic_set_to_str( __isl_keep isl_basic_set *bset); __isl_give char *isl_set_to_str( __isl_keep isl_set *set); #include __isl_give char *isl_union_set_to_str( __isl_keep isl_union_set *uset); 75 #include __isl_give char *isl_basic_map_to_str( __isl_keep isl_basic_map *bmap); __isl_give char *isl_map_to_str( __isl_keep isl_map *map); #include __isl_give char *isl_union_map_to_str( __isl_keep isl_union_map *umap); #include __isl_give char *isl_aff_to_str(__isl_keep isl_aff *aff); __isl_give char *isl_pw_aff_to_str( __isl_keep isl_pw_aff *pa); __isl_give char *isl_multi_aff_to_str( __isl_keep isl_multi_aff *ma); __isl_give char *isl_pw_multi_aff_to_str( __isl_keep isl_pw_multi_aff *pma); __isl_give char *isl_multi_pw_aff_to_str( __isl_keep isl_multi_pw_aff *mpa); __isl_give char *isl_union_pw_aff_to_str( __isl_keep isl_union_pw_aff *upa); __isl_give char *isl_union_pw_multi_aff_to_str( __isl_keep isl_union_pw_multi_aff *upma); __isl_give char *isl_multi_union_pw_aff_to_str( __isl_keep isl_multi_union_pw_aff *mupa); #include __isl_give char *isl_point_to_str( __isl_keep isl_point *pnt); #include __isl_give char *isl_pw_qpolynomial_to_str( __isl_keep isl_pw_qpolynomial *pwqp); __isl_give char *isl_union_pw_qpolynomial_to_str( __isl_keep isl_union_pw_qpolynomial *upwqp); 1.4.15 Properties Unary Properties • Emptiness The following functions test whether the given set or relation contains any integer points. The “plain” variants do not perform any computations, but simply check if the given set or relation is already known to be empty. #include 76 isl_bool isl_basic_set_plain_is_empty( __isl_keep isl_basic_set *bset); isl_bool isl_basic_set_is_empty( __isl_keep isl_basic_set *bset); isl_bool isl_set_plain_is_empty( __isl_keep isl_set *set); isl_bool isl_set_is_empty(__isl_keep isl_set *set); #include isl_bool isl_union_set_is_empty( __isl_keep isl_union_set *uset); #include isl_bool isl_basic_map_plain_is_empty( __isl_keep isl_basic_map *bmap); isl_bool isl_basic_map_is_empty( __isl_keep isl_basic_map *bmap); isl_bool isl_map_plain_is_empty( __isl_keep isl_map *map); isl_bool isl_map_is_empty(__isl_keep isl_map *map); #include isl_bool isl_union_map_plain_is_empty( __isl_keep isl_union_map *umap); isl_bool isl_union_map_is_empty( __isl_keep isl_union_map *umap); • Universality isl_bool isl_basic_set_plain_is_universe( __isl_keep isl_basic_set *bset); isl_bool isl_basic_set_is_universe( __isl_keep isl_basic_set *bset); isl_bool isl_basic_map_plain_is_universe( __isl_keep isl_basic_map *bmap); isl_bool isl_basic_map_is_universe( __isl_keep isl_basic_map *bmap); isl_bool isl_set_plain_is_universe( __isl_keep isl_set *set); isl_bool isl_map_plain_is_universe( __isl_keep isl_map *map); • Single-valuedness #include isl_bool isl_set_is_singleton(__isl_keep isl_set *set); 77 #include isl_bool isl_basic_map_is_single_valued( __isl_keep isl_basic_map *bmap); isl_bool isl_map_plain_is_single_valued( __isl_keep isl_map *map); isl_bool isl_map_is_single_valued(__isl_keep isl_map *map); #include isl_bool isl_union_map_is_single_valued( __isl_keep isl_union_map *umap); • Injectivity isl_bool isl_map_plain_is_injective( __isl_keep isl_map *map); isl_bool isl_map_is_injective( __isl_keep isl_map *map); isl_bool isl_union_map_plain_is_injective( __isl_keep isl_union_map *umap); isl_bool isl_union_map_is_injective( __isl_keep isl_union_map *umap); • Bijectivity isl_bool isl_map_is_bijective( __isl_keep isl_map *map); isl_bool isl_union_map_is_bijective( __isl_keep isl_union_map *umap); • Identity The following functions test whether the given relation only maps elements to themselves. #include isl_bool isl_map_is_identity( __isl_keep isl_map *map); #include isl_bool isl_union_map_is_identity( __isl_keep isl_union_map *umap); • Position 78 __isl_give isl_val * isl_basic_map_plain_get_val_if_fixed( __isl_keep isl_basic_map *bmap, enum isl_dim_type type, unsigned pos); __isl_give isl_val *isl_set_plain_get_val_if_fixed( __isl_keep isl_set *set, enum isl_dim_type type, unsigned pos); __isl_give isl_val *isl_map_plain_get_val_if_fixed( __isl_keep isl_map *map, enum isl_dim_type type, unsigned pos); If the set or relation obviously lies on a hyperplane where the given dimension has a fixed value, then return that value. Otherwise return NaN. • Stride isl_stat isl_set_dim_residue_class_val( __isl_keep isl_set *set, int pos, __isl_give isl_val **modulo, __isl_give isl_val **residue); Check if the values of the given set dimension are equal to a fixed value modulo some integer value. If so, assign the modulo to *modulo and the fixed value to *residue. If the given dimension attains only a single value, then assign 0 to *modulo and the fixed value to *residue. If the dimension does not attain only a single value and if no modulo can be found then assign 1 to *modulo and 1 to *residue. #include __isl_give isl_stride_info *isl_set_get_stride_info( __isl_keep isl_set *set, int pos); __isl_give isl_val *isl_set_get_stride( __isl_keep isl_set *set, int pos); #include __isl_give isl_stride_info * isl_map_get_range_stride_info( __isl_keep isl_map *map, int pos); Check if the values of the given set dimension are equal to some affine expression of the other dimensions (the offset) modulo some integer stride or check if the values of the given output dimensions are equal to some affine expression of the input dimensions (the offset) modulo some integer stride. If no more specific information can be found, then the stride is taken to be one and the offset is taken to be the zero expression. The function isl_set_get_stride performs the same computation as isl_set_get_stride_info but only returns the stride. For the other functions, the stride and offset can be extracted from the returned object using the following functions. 79 #include __isl_give isl_val *isl_stride_info_get_stride( __isl_keep isl_stride_info *si); __isl_give isl_aff *isl_stride_info_get_offset( __isl_keep isl_stride_info *si); The stride info object can be copied and released using the following functions. #include __isl_give isl_stride_info *isl_stride_info_copy( __isl_keep isl_stride_info *si); __isl_null isl_stride_info *isl_stride_info_free( __isl_take isl_stride_info *si); • Dependence To check whether the description of a set, relation or function depends on one or more given dimensions, the following functions can be used. #include isl_bool isl_constraint_involves_dims( __isl_keep isl_constraint *constraint, enum isl_dim_type type, unsigned first, unsigned n); #include isl_bool isl_basic_set_involves_dims( __isl_keep isl_basic_set *bset, enum isl_dim_type type, unsigned first, unsigned n); isl_bool isl_set_involves_dims(__isl_keep isl_set *set, enum isl_dim_type type, unsigned first, unsigned n); #include isl_bool isl_basic_map_involves_dims( __isl_keep isl_basic_map *bmap, enum isl_dim_type type, unsigned first, unsigned n); isl_bool isl_map_involves_dims(__isl_keep isl_map *map, enum isl_dim_type type, unsigned first, unsigned n); #include isl_bool isl_union_map_involves_dims( __isl_keep isl_union_map *umap, enum isl_dim_type type, unsigned first, unsigned n); #include isl_bool isl_aff_involves_dims(__isl_keep isl_aff *aff, enum isl_dim_type type, unsigned first, unsigned n); 80 isl_bool isl_pw_aff_involves_dims( __isl_keep isl_pw_aff *pwaff, enum isl_dim_type type, unsigned first, isl_bool isl_multi_aff_involves_dims( __isl_keep isl_multi_aff *ma, enum isl_dim_type type, unsigned first, isl_bool isl_pw_multi_aff_involves_dims( __isl_keep isl_pw_multi_aff *pma, enum isl_dim_type type, unsigned first, isl_bool isl_multi_pw_aff_involves_dims( __isl_keep isl_multi_pw_aff *mpa, enum isl_dim_type type, unsigned first, unsigned n); unsigned n); unsigned n); unsigned n); #include isl_bool isl_qpolynomial_involves_dims( __isl_keep isl_qpolynomial *qp, enum isl_dim_type type, unsigned first, unsigned n); Similarly, the following functions can be used to check whether a given dimension is involved in any lower or upper bound. #include isl_bool isl_set_dim_has_any_lower_bound( __isl_keep isl_set *set, enum isl_dim_type type, unsigned pos); isl_bool isl_set_dim_has_any_upper_bound( __isl_keep isl_set *set, enum isl_dim_type type, unsigned pos); Note that these functions return true even if there is a bound on the dimension on only some of the basic sets of set. To check if they have a bound for all of the basic sets in set, use the following functions instead. #include isl_bool isl_set_dim_has_lower_bound( __isl_keep isl_set *set, enum isl_dim_type type, unsigned pos); isl_bool isl_set_dim_has_upper_bound( __isl_keep isl_set *set, enum isl_dim_type type, unsigned pos); • Space To check whether a set is a parameter domain, use this function: 81 isl_bool isl_set_is_params(__isl_keep isl_set *set); isl_bool isl_union_set_is_params( __isl_keep isl_union_set *uset); • Wrapping The following functions check whether the space of the given (basic) set or relation domain and/or range is a wrapped relation. #include isl_bool isl_space_is_wrapping( __isl_keep isl_space *space); isl_bool isl_space_domain_is_wrapping( __isl_keep isl_space *space); isl_bool isl_space_range_is_wrapping( __isl_keep isl_space *space); isl_bool isl_space_is_product( __isl_keep isl_space *space); #include isl_bool isl_basic_set_is_wrapping( __isl_keep isl_basic_set *bset); isl_bool isl_set_is_wrapping(__isl_keep isl_set *set); #include isl_bool isl_map_domain_is_wrapping( __isl_keep isl_map *map); isl_bool isl_map_range_is_wrapping( __isl_keep isl_map *map); isl_bool isl_map_is_product(__isl_keep isl_map *map); #include isl_bool isl_multi_val_range_is_wrapping( __isl_keep isl_multi_val *mv); #include isl_bool isl_multi_aff_range_is_wrapping( __isl_keep isl_multi_aff *ma); isl_bool isl_multi_pw_aff_range_is_wrapping( __isl_keep isl_multi_pw_aff *mpa); isl_bool isl_multi_union_pw_aff_range_is_wrapping( __isl_keep isl_multi_union_pw_aff *mupa); The input to isl_space_is_wrapping should be the space of a set, while that of isl_space_domain_is_wrapping and isl_space_range_is_wrapping should be the space of a relation. The input to isl_space_is_product can be either the space of a set or that of a binary relation. In case the input is the space of a binary relation, it checks whether both domain and range are wrapping. 82 • Internal Product isl_bool isl_basic_map_can_zip( __isl_keep isl_basic_map *bmap); isl_bool isl_map_can_zip(__isl_keep isl_map *map); Check whether the product of domain and range of the given relation can be computed, i.e., whether both domain and range are nested relations. • Currying #include isl_bool isl_space_can_curry( __isl_keep isl_space *space); #include isl_bool isl_basic_map_can_curry( __isl_keep isl_basic_map *bmap); isl_bool isl_map_can_curry(__isl_keep isl_map *map); Check whether the domain of the (basic) relation is a wrapped relation. #include __isl_give isl_space *isl_space_uncurry( __isl_take isl_space *space); #include isl_bool isl_basic_map_can_uncurry( __isl_keep isl_basic_map *bmap); isl_bool isl_map_can_uncurry(__isl_keep isl_map *map); Check whether the range of the (basic) relation is a wrapped relation. #include isl_bool isl_space_can_range_curry( __isl_keep isl_space *space); #include isl_bool isl_map_can_range_curry( __isl_keep isl_map *map); Check whether the domain of the relation wrapped in the range of the input is itself a wrapped relation. • Special Values 83 #include isl_bool isl_bool isl_bool isl_aff_is_cst(__isl_keep isl_aff *aff); isl_pw_aff_is_cst(__isl_keep isl_pw_aff *pwaff); isl_multi_pw_aff_is_cst( __isl_keep isl_multi_pw_aff *mpa); Check whether the given expression is a constant. #include isl_bool isl_multi_val_involves_nan( __isl_keep isl_multi_val *mv); #include isl_bool isl_aff_is_nan(__isl_keep isl_aff *aff); isl_bool isl_multi_aff_involves_nan( __isl_keep isl_multi_aff *ma); isl_bool isl_pw_aff_involves_nan( __isl_keep isl_pw_aff *pa); isl_bool isl_pw_multi_aff_involves_nan( __isl_keep isl_pw_multi_aff *pma); isl_bool isl_multi_pw_aff_involves_nan( __isl_keep isl_multi_pw_aff *mpa); isl_bool isl_union_pw_aff_involves_nan( __isl_keep isl_union_pw_aff *upa); isl_bool isl_union_pw_multi_aff_involves_nan( __isl_keep isl_union_pw_multi_aff *upma); isl_bool isl_multi_union_pw_aff_involves_nan( __isl_keep isl_multi_union_pw_aff *mupa); #include isl_bool isl_qpolynomial_is_nan( __isl_keep isl_qpolynomial *qp); isl_bool isl_qpolynomial_fold_is_nan( __isl_keep isl_qpolynomial_fold *fold); isl_bool isl_pw_qpolynomial_involves_nan( __isl_keep isl_pw_qpolynomial *pwqp); isl_bool isl_pw_qpolynomial_fold_involves_nan( __isl_keep isl_pw_qpolynomial_fold *pwf); isl_bool isl_union_pw_qpolynomial_involves_nan( __isl_keep isl_union_pw_qpolynomial *upwqp); isl_bool isl_union_pw_qpolynomial_fold_involves_nan( __isl_keep isl_union_pw_qpolynomial_fold *upwf); Check whether the given expression is equal to or involves NaN. 84 #include isl_bool isl_aff_plain_is_zero( __isl_keep isl_aff *aff); Check whether the affine expression is obviously zero. Binary Properties • Equality The following functions check whether two objects represent the same set, relation or function. The plain variants only return true if the objects are obviously the same. That is, they may return false even if the objects are the same, but they will never return true if the objects are not the same. #include isl_bool isl_basic_set_plain_is_equal( __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2); isl_bool isl_basic_set_is_equal( __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2); isl_bool isl_set_plain_is_equal( __isl_keep isl_set *set1, __isl_keep isl_set *set2); isl_bool isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2); #include isl_bool isl_basic_map_is_equal( __isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2); isl_bool isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2); isl_bool isl_map_plain_is_equal( __isl_keep isl_map *map1, __isl_keep isl_map *map2); #include isl_bool isl_union_set_is_equal( __isl_keep isl_union_set *uset1, __isl_keep isl_union_set *uset2); #include isl_bool isl_union_map_is_equal( __isl_keep isl_union_map *umap1, __isl_keep isl_union_map *umap2); 85 #include isl_bool isl_multi_val_plain_is_equal( __isl_keep isl_multi_val *mv1, __isl_keep isl_multi_val *mv2); #include isl_bool isl_aff_plain_is_equal( __isl_keep isl_aff *aff1, __isl_keep isl_aff *aff2); isl_bool isl_multi_aff_plain_is_equal( __isl_keep isl_multi_aff *maff1, __isl_keep isl_multi_aff *maff2); isl_bool isl_pw_aff_plain_is_equal( __isl_keep isl_pw_aff *pwaff1, __isl_keep isl_pw_aff *pwaff2); isl_bool isl_pw_aff_is_equal( __isl_keep isl_pw_aff *pa1, __isl_keep isl_pw_aff *pa2); isl_bool isl_pw_multi_aff_plain_is_equal( __isl_keep isl_pw_multi_aff *pma1, __isl_keep isl_pw_multi_aff *pma2); isl_bool isl_pw_multi_aff_is_equal( __isl_keep isl_pw_multi_aff *pma1, __isl_keep isl_pw_multi_aff *pma2); isl_bool isl_multi_pw_aff_plain_is_equal( __isl_keep isl_multi_pw_aff *mpa1, __isl_keep isl_multi_pw_aff *mpa2); isl_bool isl_multi_pw_aff_is_equal( __isl_keep isl_multi_pw_aff *mpa1, __isl_keep isl_multi_pw_aff *mpa2); isl_bool isl_union_pw_aff_plain_is_equal( __isl_keep isl_union_pw_aff *upa1, __isl_keep isl_union_pw_aff *upa2); isl_bool isl_union_pw_multi_aff_plain_is_equal( __isl_keep isl_union_pw_multi_aff *upma1, __isl_keep isl_union_pw_multi_aff *upma2); isl_bool isl_multi_union_pw_aff_plain_is_equal( __isl_keep isl_multi_union_pw_aff *mupa1, __isl_keep isl_multi_union_pw_aff *mupa2); #include isl_bool isl_union_pw_qpolynomial_plain_is_equal( __isl_keep isl_union_pw_qpolynomial *upwqp1, __isl_keep isl_union_pw_qpolynomial *upwqp2); isl_bool isl_union_pw_qpolynomial_fold_plain_is_equal( __isl_keep isl_union_pw_qpolynomial_fold *upwf1, 86 __isl_keep isl_union_pw_qpolynomial_fold *upwf2); • Disjointness #include isl_bool isl_basic_set_is_disjoint( __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2); isl_bool isl_set_plain_is_disjoint( __isl_keep isl_set *set1, __isl_keep isl_set *set2); isl_bool isl_set_is_disjoint(__isl_keep isl_set *set1, __isl_keep isl_set *set2); #include isl_bool isl_basic_map_is_disjoint( __isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2); isl_bool isl_map_is_disjoint(__isl_keep isl_map *map1, __isl_keep isl_map *map2); #include isl_bool isl_union_set_is_disjoint( __isl_keep isl_union_set *uset1, __isl_keep isl_union_set *uset2); #include isl_bool isl_union_map_is_disjoint( __isl_keep isl_union_map *umap1, __isl_keep isl_union_map *umap2); • Subset isl_bool isl_basic_set_is_subset( __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2); isl_bool isl_set_is_subset(__isl_keep isl_set *set1, __isl_keep isl_set *set2); isl_bool isl_set_is_strict_subset( __isl_keep isl_set *set1, __isl_keep isl_set *set2); isl_bool isl_union_set_is_subset( __isl_keep isl_union_set *uset1, __isl_keep isl_union_set *uset2); isl_bool isl_union_set_is_strict_subset( 87 __isl_keep isl_union_set *uset1, __isl_keep isl_union_set *uset2); isl_bool isl_basic_map_is_subset( __isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2); isl_bool isl_basic_map_is_strict_subset( __isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2); isl_bool isl_map_is_subset( __isl_keep isl_map *map1, __isl_keep isl_map *map2); isl_bool isl_map_is_strict_subset( __isl_keep isl_map *map1, __isl_keep isl_map *map2); isl_bool isl_union_map_is_subset( __isl_keep isl_union_map *umap1, __isl_keep isl_union_map *umap2); isl_bool isl_union_map_is_strict_subset( __isl_keep isl_union_map *umap1, __isl_keep isl_union_map *umap2); Check whether the first argument is a (strict) subset of the second argument. • Order Every comparison function returns a negative value if the first argument is considered smaller than the second, a positive value if the first argument is considered greater and zero if the two constraints are considered the same by the comparison criterion. #include int isl_constraint_plain_cmp( __isl_keep isl_constraint *c1, __isl_keep isl_constraint *c2); This function is useful for sorting isl_constraints. The order depends on the internal representation of the inputs. The order is fixed over different calls to the function (assuming the internal representation of the inputs has not changed), but may change over different versions of isl. #include int isl_constraint_cmp_last_non_zero( __isl_keep isl_constraint *c1, __isl_keep isl_constraint *c2); This function can be used to sort constraints that live in the same local space. Constraints that involve “earlier” dimensions or that have a smaller coefficient 88 for the shared latest dimension are considered smaller than other constraints. This function only defines a partial order. #include