add isl_set_from_point
[platform/upstream/isl.git] / doc / user.pod
index ce0ca45..3f9129d 100644 (file)
@@ -96,7 +96,7 @@ C<piplib> functionality is currently used by default.
 The C<--with-piplib> option can
 be used to specify which C<piplib>
 library to use, either an installed version (C<system>),
-an externally built version (C<build>), a bundled version (C<bundled>)
+an externally built version (C<build>)
 or no version (C<no>).  The option C<build> is mostly useful
 in C<configure> scripts of larger projects that bundle both C<isl>
 and C<piplib>.
@@ -117,9 +117,7 @@ Installation prefix for C<GMP> (architecture-dependent files).
 
 =item C<--with-piplib>
 
-Which copy of C<piplib> to use, either C<no> (default), C<system>, C<build>
-or C<bundled>.  Note that C<bundled> only works if you have obtained
-C<isl> and its submodules from the git repository.
+Which copy of C<piplib> to use, either C<no> (default), C<system> or C<build>.
 
 =item C<--with-piplib-prefix>
 
@@ -177,6 +175,12 @@ support fixed integer arithmetic, all calls to C<GMP>
 are wrapped inside C<isl> specific macros.
 The basic type is C<isl_int> and the following operations
 are available on this type.
+The meanings of these operations are essentially the same
+as their C<GMP> C<mpz_> counterparts.
+As always with C<GMP> types, C<isl_int>s need to be
+initialized with C<isl_int_init> before they can be used
+and they need to be released with C<isl_int_clear>
+after the last use.
 
 =over
 
@@ -471,21 +475,6 @@ the coefficients of the existentially quantified variables
 appear between those of the set variables and those
 of the parameters.
 
-=head3 Dumping the internal state
-
-For lack of proper output functions, the following functions
-can be used to dump the internal state of a set or relation.
-The user should not depend on the output format of these functions.
-
-       void isl_basic_set_dump(__isl_keep isl_basic_set *bset,
-               FILE *out, int indent);
-       void isl_basic_map_dump(__isl_keep isl_basic_map *bmap,
-               FILE *out, int indent);
-       void isl_set_dump(__isl_keep isl_set *set,
-               FILE *out, int indent);
-       void isl_map_dump(__isl_keep isl_map *map,
-               FILE *out, int indent);
-
 =head2 Creating New Sets and Relations
 
 C<isl> has functions for creating some standard sets and relations.
@@ -633,6 +622,97 @@ Or, alternatively,
        bset = isl_basic_set_read_from_str(ctx,
                "{[i] : exists (a : i = 2a and i >= 10 and i <= 42)}", -1);
 
+=head2 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 C<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);
+
+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.
+If, furthermore, the same existentials, i.e., existentials
+with the same explicit representations, should appear in the
+same order in each of the disjuncts of a set or map, then the user should call
+either of the following functions.
+
+       __isl_give isl_set *isl_set_align_divs(
+               __isl_take isl_set *set);
+       __isl_give isl_map *isl_map_align_divs(
+               __isl_take isl_map *map);
+
+To iterate over all the basic sets or maps in a set or map, use
+
+       int isl_set_foreach_basic_set(__isl_keep isl_set *set,
+               int (*fn)(__isl_take isl_basic_set *bset, void *user),
+               void *user);
+       int isl_map_foreach_basic_map(__isl_keep isl_map *map,
+               int (*fn)(__isl_take isl_basic_map *bmap, void *user),
+               void *user);
+
+The callback function C<fn> should return 0 if successful and
+-1 if an error occurs.  In the latter case, or if any other error
+occurs, the above functions will return -1.
+
+It should be noted that C<isl> does not guarantee that
+the basic sets or maps passed to C<fn> are disjoint.
+If this is required, then the user should call one of
+the following functions first.
+
+       __isl_give isl_set *isl_set_make_disjoint(
+               __isl_take isl_set *set);
+       __isl_give isl_map *isl_map_make_disjoint(
+               __isl_take isl_map *map);
+
+To iterate over the constraints of a basic set or map, use
+
+       #include <isl_constraint.h>
+
+       int isl_basic_map_foreach_constraint(
+               __isl_keep isl_basic_map *bmap,
+               int (*fn)(__isl_take isl_constraint *c, void *user),
+               void *user);
+       void isl_constraint_free(struct isl_constraint *c);
+
+Again, the callback function C<fn> should return 0 if successful and
+-1 if an error occurs.  In the latter case, or if any other error
+occurs, the above functions will return -1.
+
+The coefficients of the constraints can be inspected using
+the following functions.
+
+       void isl_constraint_get_constant(
+               __isl_keep isl_constraint *constraint, isl_int *v);
+       void isl_constraint_get_coefficient(
+               __isl_keep isl_constraint *constraint,
+               enum isl_dim_type type, int pos, isl_int *v);
+
+The explicit representations of the existentially quantified
+variables can be inspected using the following functions.
+Note that the user is only allowed to use these functions
+if the inspected set or map is the result of a call
+to C<isl_set_compute_divs> or C<isl_map_compute_divs>.
+
+       __isl_give isl_div *isl_constraint_div(
+               __isl_keep isl_constraint *constraint, int pos);
+       void isl_div_get_constant(__isl_keep isl_div *div,
+               isl_int *v);
+       void isl_div_get_denominator(__isl_keep isl_div *div,
+               isl_int *v);
+       void isl_div_get_coefficient(__isl_keep isl_div *div,
+               enum isl_dim_type type, int pos, isl_int *v);
+
 =head2 Properties
 
 =head3 Unary Properties
@@ -658,6 +738,7 @@ is already known to be empty.
 
        int isl_basic_set_is_universe(__isl_keep isl_basic_set *bset);
        int isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap);
+       int isl_set_fast_is_universe(__isl_keep isl_set *set);
 
 =back
 
@@ -710,13 +791,23 @@ is already known to be empty.
 
 =over
 
+=item * Complement
+
+       __isl_give isl_set *isl_set_complement(
+               __isl_take isl_set *set);
+
 =item * Projection
 
        __isl_give isl_basic_set *isl_basic_set_project_out(
                __isl_take isl_basic_set *bset,
                enum isl_dim_type type, unsigned first, unsigned n);
+       __isl_give isl_basic_map *isl_basic_map_project_out(
+               __isl_take isl_basic_map *bmap,
+               enum isl_dim_type type, unsigned first, unsigned n);
        __isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
                enum isl_dim_type type, unsigned first, unsigned n);
+       __isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
+               enum isl_dim_type type, unsigned first, unsigned n);
        __isl_give isl_basic_set *isl_basic_map_domain(
                __isl_take isl_basic_map *bmap);
        __isl_give isl_basic_set *isl_basic_map_range(
@@ -726,9 +817,6 @@ is already known to be empty.
        __isl_give isl_set *isl_map_range(
                __isl_take isl_map *map);
 
-C<isl_basic_set_project_out> currently only supports projecting
-out the final C<isl_dim_set> dimensions.
-
 =item * Coalescing
 
 Simplify the representation of a set or relation by trying
@@ -759,6 +847,29 @@ variables, then the result of these operations is currently undefined.
        __isl_give isl_basic_map *isl_map_affine_hull(
                __isl_take isl_map *map);
 
+=item * Power
+
+       __isl_give isl_map *isl_map_power(__isl_take isl_map *map,
+               unsigned param, int *exact);
+
+Compute a parametric representation for all positive powers I<k> of C<map>.
+The power I<k> is equated to the parameter at position C<param>.
+The result may be an overapproximation.  If the result is exact,
+then C<*exact> is set to C<1>.
+The current implementation only produces exact results for particular
+cases of piecewise translations (i.e., piecewise uniform dependences).
+
+=item * Transitive closure
+
+       __isl_give isl_map *isl_map_transitive_closure(
+               __isl_take isl_map *map, int *exact);
+
+Compute the transitive closure of C<map>.
+The result may be an overapproximation.  If the result is known to be exact,
+then C<*exact> is set to C<1>.
+The current implementation only produces exact results for particular
+cases of piecewise translations (i.e., piecewise uniform dependences).
+
 =back
 
 =head2 Binary Operations
@@ -847,13 +958,13 @@ the same (number of) parameters.
 
 =head3 Lexicographic Optimization
 
-Given a basic set C<bset> and a zero-dimensional domain C<dom>,
+Given a (basic) set C<set> (or C<bset>) and a zero-dimensional domain C<dom>,
 the following functions
 compute a set that contains the lexicographic minimum or maximum
-of the elements in C<bset> for those values of the parameters
+of the elements in C<set> (or C<bset>) for those values of the parameters
 that satisfy C<dom>.
 If C<empty> is not C<NULL>, then C<*empty> is assigned a set
-that contains the parameter values in C<dom> for which C<bset>
+that contains the parameter values in C<dom> for which C<set> (or C<bset>)
 has no elements.
 In other words, the union of the parameter values
 for which the result is non-empty and of C<*empty>
@@ -867,25 +978,35 @@ is equal to C<dom>.
                __isl_take isl_basic_set *bset,
                __isl_take isl_basic_set *dom,
                __isl_give isl_set **empty);
+       __isl_give isl_set *isl_set_partial_lexmin(
+               __isl_take isl_set *set, __isl_take isl_set *dom,
+               __isl_give isl_set **empty);
+       __isl_give isl_set *isl_set_partial_lexmax(
+               __isl_take isl_set *set, __isl_take isl_set *dom,
+               __isl_give isl_set **empty);
 
-Given a basic set C<bset>, the following functions simply
+Given a (basic) set C<set> (or C<bset>), the following functions simply
 return a set containing the lexicographic minimum or maximum
-of the elements in C<bset>.
+of the elements in C<set> (or C<bset>).
 
        __isl_give isl_set *isl_basic_set_lexmin(
                __isl_take isl_basic_set *bset);
        __isl_give isl_set *isl_basic_set_lexmax(
                __isl_take isl_basic_set *bset);
+       __isl_give isl_set *isl_set_lexmin(
+               __isl_take isl_set *set);
+       __isl_give isl_set *isl_set_lexmax(
+               __isl_take isl_set *set);
 
-Given a basic relation C<bmap> and a domain C<dom>,
+Given a (basic) relation C<map> (or C<bmap>) and a domain C<dom>,
 the following functions
 compute a relation that maps each element of C<dom>
 to the single lexicographic minimum or maximum
 of the elements that are associated to that same
-element in C<bmap>.
+element in C<map> (or C<bmap>).
 If C<empty> is not C<NULL>, then C<*empty> is assigned a set
 that contains the elements in C<dom> that do not map
-to any elements in C<bmap>.
+to any elements in C<map> (or C<bmap>).
 In other words, the union of the domain of the result and of C<*empty>
 is equal to C<dom>.
 
@@ -897,23 +1018,349 @@ is equal to C<dom>.
                __isl_take isl_basic_map *bmap,
                __isl_take isl_basic_set *dom,
                __isl_give isl_set **empty);
+       __isl_give isl_map *isl_map_partial_lexmax(
+               __isl_take isl_map *map, __isl_take isl_set *dom,
+               __isl_give isl_set **empty);
+       __isl_give isl_map *isl_map_partial_lexmin(
+               __isl_take isl_map *map, __isl_take isl_set *dom,
+               __isl_give isl_set **empty);
 
-Given a basic map C<bmap>, the following functions simply
+Given a (basic) map C<map> (or C<bmap>), the following functions simply
 return a map mapping each element in the domain of
-C<bmap> to the lexicographic minimum or maximum
+C<map> (or C<bmap>) to the lexicographic minimum or maximum
 of all elements associated to that element.
 
        __isl_give isl_map *isl_basic_map_lexmin(
                __isl_take isl_basic_map *bmap);
        __isl_give isl_map *isl_basic_map_lexmax(
                __isl_take isl_basic_map *bmap);
+       __isl_give isl_map *isl_map_lexmin(
+               __isl_take isl_map *map);
+       __isl_give isl_map *isl_map_lexmax(
+               __isl_take isl_map *map);
+
+=head2 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_dim *dim);
+
+The coordinates of a point can be inspected, set and changed
+using
+
+       void isl_point_get_coordinate(__isl_keep isl_point *pnt,
+               enum isl_dim_type type, int pos, isl_int *v);
+       __isl_give isl_point *isl_point_set_coordinate(
+               __isl_take isl_point *pnt,
+               enum isl_dim_type type, int pos, isl_int 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);
+       void isl_point_free(__isl_take isl_point *pnt);
+
+A singleton set can be created from a point using
+
+       __isl_give isl_set *isl_set_from_point(
+               __isl_take isl_point *pnt);
+
+and a box can be created from two opposite extremal points using
+
+       __isl_give isl_set *isl_set_box_from_points(
+               __isl_take isl_point *pnt1,
+               __isl_take isl_point *pnt2);
+
+All elements of a B<bounded> set can be enumerated using
+the following function.
+
+       int isl_set_foreach_point(__isl_keep isl_set *set,
+               int (*fn)(__isl_take isl_point *pnt, void *user),
+               void *user);
+
+The function C<fn> is called for each integer point in
+C<set> with as second argument the last argument of
+the C<isl_set_foreach_point> call.  The function C<fn>
+should return C<0> on success and C<-1> on failure.
+In the latter case, C<isl_set_foreach_point> will stop
+enumerating and return C<-1> as well.
+If the enumeration is performed successfully and to completion,
+then C<isl_set_foreach_point> returns C<0>.
+
+To obtain a single point of a set, use
+
+       __isl_give isl_point *isl_set_sample_point(
+               __isl_take isl_set *set);
+
+If C<set> does not contain any (integer) points, then the
+resulting point will be ``void'', a property that can be
+tested using
+
+       int isl_point_is_void(__isl_keep isl_point *pnt);
+
+=head2 Piecewise Quasipolynomials
+
+A piecewise quasipolynomial is a particular kind of function that maps
+a parametric point to a rational value.
+More specifically, a quasipolynomial is a polynomial expression in greatest
+integer parts of affine expressions of parameters and variables.
+A piecewise quasipolynomial is a subdivision of a given parametric
+domain into disjoint cells with a quasipolynomial associated to
+each cell.  The value of the piecewise quasipolynomial at a given
+point is the value of the quasipolynomial associated to the cell
+that contains the point.  Outside of the union of cells,
+the value is assumed to be zero.
+For example, the piecewise quasipolynomial
+
+       [n] -> { [x] -> ((1 + n) - x) : x <= n and x >= 0 }
+
+maps C<x> to C<1 + n - x> for values of C<x> between C<0> and C<n>.
+Piecewise quasipolynomials are mainly used by the C<barvinok>
+library for representing the number of elements in a parametric set or map.
+For example, the piecewise quasipolynomial above represents
+the number of point in the map
+
+       [n] -> { [x] -> [y] : x,y >= 0 and 0 <= x + y <= n }
+
+=head3 Printing (Piecewise) Quasipolynomials
+
+Quasipolynomials and piecewise quasipolynomials can be printed
+using the following functions.
+
+       void isl_qpolynomial_print(__isl_keep isl_qpolynomial *qp,
+               FILE *out, unsigned output_format);
+
+       void isl_pw_qpolynomial_print(
+               __isl_keep isl_pw_qpolynomial *pwqp, FILE *out,
+               unsigned output_format);
+
+=head3 Creating New (Piecewise) Quasipolynomials
+
+Some simple quasipolynomials can be created using the following functions.
+More complicated quasipolynomials can be created by applying
+operations such as addition and multiplication
+on the resulting quasipolynomials
+
+       __isl_give isl_qpolynomial *isl_qpolynomial_zero(
+               __isl_take isl_dim *dim);
+       __isl_give isl_qpolynomial *isl_qpolynomial_infty(
+               __isl_take isl_dim *dim);
+       __isl_give isl_qpolynomial *isl_qpolynomial_nan(
+               __isl_take isl_dim *dim);
+       __isl_give isl_qpolynomial *isl_qpolynomial_rat_cst(
+               __isl_take isl_dim *dim,
+               const isl_int n, const isl_int d);
+       __isl_give isl_qpolynomial *isl_qpolynomial_div(
+               __isl_take isl_div *div);
+       __isl_give isl_qpolynomial *isl_qpolynomial_var(
+               __isl_take isl_dim *dim,
+               enum isl_dim_type type, unsigned pos);
+
+The zero piecewise quasipolynomial or a piecewise quasipolynomial
+with a single cell can be created using the following functions.
+Multiple of these single cell piecewise quasipolynomials can
+be combined to create more complicated piecewise quasipolynomials.
+
+       __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_zero(
+               __isl_take isl_dim *dim);
+       __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_alloc(
+               __isl_take isl_set *set,
+               __isl_take isl_qpolynomial *qp);
+
+Quasipolynomials can be copied and freed again using the following
+functions.
+
+       __isl_give isl_qpolynomial *isl_qpolynomial_copy(
+               __isl_keep isl_qpolynomial *qp);
+       void isl_qpolynomial_free(__isl_take isl_qpolynomial *qp);
+
+       __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_copy(
+               __isl_keep isl_pw_qpolynomial *pwqp);
+       void isl_pw_qpolynomial_free(
+               __isl_take isl_pw_qpolynomial *pwqp);
+
+=head3 Inspecting (Piecewise) Quasipolynomials
+
+To iterate over the cells in a piecewise quasipolynomial,
+use the following function
+
+       int isl_pw_qpolynomial_foreach_piece(
+               __isl_keep isl_pw_qpolynomial *pwqp,
+               int (*fn)(__isl_take isl_set *set,
+                         __isl_take isl_qpolynomial *qp,
+                         void *user), void *user);
+
+As usual, the function C<fn> should return C<0> on success
+and C<-1> on failure.
+
+To iterate over all terms in a quasipolynomial,
+use
+
+       int isl_qpolynomial_foreach_term(
+               __isl_keep isl_qpolynomial *qp,
+               int (*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);
+       void isl_term_get_num(__isl_keep isl_term *term,
+               isl_int *n);
+       void isl_term_get_den(__isl_keep isl_term *term,
+               isl_int *d);
+       int isl_term_get_exp(__isl_keep isl_term *term,
+               enum isl_dim_type type, unsigned pos);
+       __isl_give isl_div *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 C<isl_term_get_exp>
+returns the exponent of a given dimensions in the given term.
+The C<isl_int>s in the arguments of C<isl_term_get_num>
+and C<isl_term_get_den> need to have been initialized
+using C<isl_int_init> before calling these functions.
+
+=head3 Properties of (Piecewise) Quasipolynomials
+
+To check whether a quasipolynomial is actually a constant,
+use the following function.
+
+       int isl_qpolynomial_is_cst(__isl_keep isl_qpolynomial *qp,
+               isl_int *n, isl_int *d);
+
+If C<qp> is a constant and if C<n> and C<d> are not C<NULL>
+then the numerator and denominator of the constant
+are returned in C<*n> and C<*d>, respectively.
+
+=head3 Operations on (Piecewise) Quasipolynomials
+
+       __isl_give isl_qpolynomial *isl_qpolynomial_neg(
+               __isl_take isl_qpolynomial *qp);
+       __isl_give isl_qpolynomial *isl_qpolynomial_add(
+               __isl_take isl_qpolynomial *qp1,
+               __isl_take isl_qpolynomial *qp2);
+       __isl_give isl_qpolynomial *isl_qpolynomial_mul(
+               __isl_take isl_qpolynomial *qp1,
+               __isl_take isl_qpolynomial *qp2);
+
+       __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_add(
+               __isl_take isl_pw_qpolynomial *pwqp1,
+               __isl_take isl_pw_qpolynomial *pwqp2);
+       __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_sub(
+               __isl_take isl_pw_qpolynomial *pwqp1,
+               __isl_take isl_pw_qpolynomial *pwqp2);
+       __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_add_disjoint(
+               __isl_take isl_pw_qpolynomial *pwqp1,
+               __isl_take isl_pw_qpolynomial *pwqp2);
+       __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_neg(
+               __isl_take isl_pw_qpolynomial *pwqp);
+       __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_mul(
+               __isl_take isl_pw_qpolynomial *pwqp1,
+               __isl_take isl_pw_qpolynomial *pwqp2);
+
+       __isl_give isl_qpolynomial *isl_pw_qpolynomial_eval(
+               __isl_take isl_pw_qpolynomial *pwqp,
+               __isl_take isl_point *pnt);
+
+=head2 Dependence Analysis
+
+C<isl> contains specialized functionality for performing
+array dataflow analysis.  That is, given a I<sink> access relation
+and a collection of possible I<source> access relations,
+C<isl> can compute relations that describe
+for each iteration of the sink access, which iteration
+of which of the source access relations was the last
+to access the same data element before the given iteration
+of the sink access.
+To compute standard flow dependences, the sink should be
+a read, while the sources should be writes.
+
+       #include <isl_flow.h>
+
+       __isl_give isl_access_info *isl_access_info_alloc(
+               __isl_take isl_map *sink,
+               void *sink_user, isl_access_level_before fn,
+               int max_source);
+       __isl_give isl_access_info *isl_access_info_add_source(
+               __isl_take isl_access_info *acc,
+               __isl_take isl_map *source, void *source_user);
+
+       __isl_give isl_flow *isl_access_info_compute_flow(
+               __isl_take isl_access_info *acc);
+
+       int isl_flow_foreach(__isl_keep isl_flow *deps,
+               int (*fn)(__isl_take isl_map *dep, void *dep_user,
+                         void *user),
+               void *user);
+       __isl_give isl_set *isl_flow_get_no_source(
+               __isl_keep isl_flow *deps);
+       void isl_flow_free(__isl_take isl_flow *deps);
+
+The function C<isl_access_info_compute_flow> performs the actual
+dependence analysis.  The other functions are used to construct
+the input for this function or to read off the output.
+
+The input is collected in an C<isl_access_info>, which can
+be created through a call to C<isl_access_info_alloc>.
+The arguments to this functions are the sink access relation
+C<sink>, a token C<sink_user> used to identify the sink
+access to the user, a callback function for specifying the
+relative order of source and sink accesses, and the number
+of source access relations that will be added.
+The callback function has type C<int (*)(void *first, void *second)>.
+The function is called with two user supplied tokens identifying
+either a source or the sink and it should return the shared nesting
+level and the relative order of the two accesses.
+In particular, let I<n> be the number of loops shared by
+the two accesses.  If C<first> precedes C<second> textually,
+then the function should return I<2 * n + 1>; otherwise,
+it should return I<2 * n>.
+The sources can be added to the C<isl_access_info> by performing
+(at most) C<max_source> calls to C<isl_access_info_add_source>.
+The C<source_user> token is again used to identify
+the source access.  The range of the source access relation
+C<source> should have the same dimension as the range
+of the sink access relation.
+
+The result of the dependence analysis is collected in an
+C<isl_flow>.  There may be elements in the domain of
+the sink access for which no preceding source access could be
+find.  The set of these elements can be obtained through
+a call to C<isl_flow_get_no_source>.
+In the case of standard flow dependence analysis,
+this set corresponds to the reads from uninitialized
+array elements.
+The actual flow dependences can be extracted using
+C<isl_flow_foreach>.  This function will call the user-specified
+callback function C<fn> for each B<non-empty> dependence between
+a source and the sink.  The callback function is called
+with three arguments, the actual flow dependence relation
+mapping source iterations to sink iterations, a token
+identifying the source and an additional C<void *> with value
+equal to the third argument of the C<isl_flow_foreach> call.
+
+After finishing with an C<isl_flow>, the user should call
+C<isl_flow_free> to free all associated memory.
 
 =head1 Applications
 
 Although C<isl> is mainly meant to be used as a library,
 it also contains some basic applications that use some
 of the functionality of C<isl>.
-The input may specified either in the L<isl format>
+The input may be specified in either the L<isl format>
 or the L<PolyLib format>.
 
 =head2 C<isl_polyhedron_sample>