\input texinfo
@c -*-texinfo-*-
@c %**start of header
@setfilename apron.info
@settitle APRON 0.9.10
@c @setcontentsaftertitlepage
@c include version.texi
@iftex
@afourpaper
@end iftex
@comment %**end of header

@c This file is part of the APRON Library, released under LGPL
@c license. Please read the COPYING file packaged in the distribution

@setcontentsaftertitlepage

@tex
\global\parskip=0.5ex
\global\baselineskip=3ex
\global\mag=1000
@end tex

@direntry
* apron: (apron).  APRON library for Abstract Interpretation of
numerical variables.
@end direntry

@iftex
@finalout
@end iftex

@ifnottex
@node Top, Copying, (dir), (dir)
@top APRON
@end ifnottex

@setchapternewpage odd

@c Texinfo version 4 or up will be needed to process this into .info files.
@c
@c The edition number is in three places and the month/year in one, all
@c taken from version.texi.  version.texi is created when you configure with
@c --enable-maintainer-mode, and is included in a distribution made with
@c "make dist".

@titlepage
@c  use the new format for titles

@title APRON
@subtitle The APRON library
@subtitle Edition 0.9.8, October 2007

@author by Bertrand Jeannet and the APRON team
@c Include the Distribution inside the titlepage so
@c that headings are turned off.
@end titlepage

@iftex
@page
@vskip 0pt plus 1filll
@end iftex


@ifnothtml
@contents
@end ifnothtml

@menu
* Copying::
* Introduction to APRON::
* APRON Rationale and Functionalities::
* APRON Guidelines::
* Managers and Abstract Domains::
* Scalars & Intervals & Coefficients::
* Level 1 of the interface::
* Level 0 of the interface::
* Functions for implementors::
* Examples::
* Appendices::
@end menu

@c *******************************************************************
@node Copying, Introduction to APRON, Top, Top
@chapter APRON Copying Conditions (LGPL)
@c *******************************************************************

The APRON library is copyright @copyright{} by the
@uref{http://www.cri.ensmp.fr/apron/,APRON project}, and its partners.

This license applies to all files distributed in the APRON library,
including all source code, libraries, binaries, and documentation.

@include lgpl.texi

@c *******************************************************************
@node Introduction to APRON, APRON Rationale and Functionalities, Copying, Top
@chapter Introduction to APRON
@c *******************************************************************

The APRON library provides a common interface for @emph{abstract
domains of invariants} for numerical variables, in the sense of the
Abstract Interpretation theory. It includes a few domains, and
provides interfaces to libraries implemented by other teams.

@c The APRON library is dedicated to the static analysis of the numerical
@c variables of a program by Abstract Interpretation. The aim of such an
@c analysis is to infer invariants about these variables, like
@c @math{1<=x+y<=z}, which holds during any execution of the program.
@c Such an analysis works by computing iteratively the solution of
@c fixpoint equations on an @emph{abstract domain} of invariants. The
@c result is a overapproximation of the least inductive invariant of the
@c program.

Several libraries already exists, wich implement various abstract domains of
invariants.  One can cite intervals, linear equalities, octagons,
octahedra, convex polyhedra, polynomial equalities, polynomial
inequalities. Although they offer a kernel of common functionalities,
their API may differ greatly, and some functionalities may lack in some
libraries. The aim of the APRON library is to offer a common interface to these
libraries. Such a standardized interface offers several advantages: it allows
@itemize
@item to easily
substitute a library/abstract domain by another in the same analysis
tool; this is useful to compare the efficiency of 2 implementations of
the same abstract domain, or the precision of 2 different abstract
domains.
@item
to factorize services which are mostly independant of the abstract
domain (variables management, linearization of non-linear expressions,
etc...);
@item
to make easier the combination of abstract domains: the abstract
domains to be combined are used through the same interface, as the
resulting combination;
@end itemize

@subsubheading As a user, why should I use APRON ?
@enumerate
@item
it makes very easy to switch the abstract domain (for numerical
variables) in use in an analyzer;
@item
it already offers the most used abstract domains, ranging from
intervals, octagons, convex polyhedra to linear congruences;
@item
its interface should satisfy most needs, as it already satisfies the
members of the APRON project working in different contexts
(verification of high-level specifications/programs with exact
arithmetics for INRIA \& Verimag, static analysis of runtime errors
with floating-point arithmetics for ENS Paris, automatic
parallelization of programs for ENSMP).
@item
the interface, at the level 1, already provides slightly higher-level
functionalities than most existing and publicy available abstract
domains libraries (with the manipulation of environments); this
statement should be reinforced in the near future with the planned
addition of a generic non-linear expressions layer and a
floating-point arithmetic layer.
@end enumerate

@subsubheading As a domain implementor, why should I interface my abstract domain/library to APRON ?
@enumerate
@item to incite existing users of the APRON interface to try your library;
@item to make your users, including yourself, benefit from previous points 1 and 4;
@item
to not waste your time implementing environments, variables renaming,
OCaml interfaces, and so on; the effort to connect your library to the
interface should at minimum be counterbalanced by such gains;
@end enumerate


@c The contributions of the project are
@c @itemize
@c @item
@c The identification of the basic functionalities that an implementation
@c should provide, and which cannot be factorized at a higher level;
@c @item
@c The design of a detailed API (datatypes, functions signatures)
@c @item
@c The implementation of functions that will be needed for most implementations
@c @item
@c The design and implementation of higher level services that are built on
@c top of the basic interface and that factorizes services that can be
@c shared between the underlying implementations.
@c @end itemize

@c *******************************************************************
@node APRON Rationale and Functionalities, APRON Guidelines, Introduction to APRON, Top
@chapter APRON Rationale and Functionalities
@c *******************************************************************

@include rationale.texi

@c *******************************************************************
@node APRON Guidelines, Managers and Abstract Domains, APRON Rationale and Functionalities, Top
@chapter APRON Guidelines
@c *******************************************************************
@menu
* Installing APRON::
* C Programming Guidelines::
* OCaml Programming Guidelines::
* MakingLibrary::         How to make an existing library conformant to APRON ?
@end menu

@c *******************************************************************
@node Installing APRON, C Programming Guidelines, APRON Guidelines, APRON Guidelines
@section Installing APRON
@c *******************************************************************

You should look at @file{../README}, @file{../Makefile.config.model}
and @file{../Makefile} files.

@c ===================================================================
@node C Programming Guidelines, OCaml Programming Guidelines, Installing APRON, APRON Guidelines
@section C Programming Guidelines
@c ===================================================================

@c -------------------------------------------------------------------

@menu
* C Headers and Libraries::
* C Naming conventions::
* Allocating managers and setting options::
* Sequel of the small example::
* Typing issue in C::
@end menu

@node C Headers and Libraries, C Naming conventions, C Programming Guidelines, C Programming Guidelines
@subsection C Headers and Libraries
@c -------------------------------------------------------------------

Declarations needed to use an underlying library via APRON are
collected in the C include files @file{ap_global0.h} and
@file{ap_global1.h}. They respectively refer to the level 0 and the
level 1 of the interface. One can also refer to single APRON modules
with their corresponding include files @file{ap_dimension.h},
@file{ap_lincons0.h}, ... Header files @file{<stdio.h>},
@file{stdlib.h} and @file{<stdarg.h>} will be required.

Then, you should also include the header files of the underlying
libraries you want to use it via APRON (for instance, @file{box.h},
@file{pk.h}, @file{ap_ppl.h}).

All programs using APRON must link against the @file{libapron},
@file{libmpfr} and @file{libgmp} libraries, and the underlying
libraries you want to use it via APRON:
@enumerate
@item
If some file @file{test.c} uses the POLKA library via APRON, the
compilation command should look like @samp{gcc -I$ITV/include
-I$MPFR/include -I$GMP/include -I$APRON/include -L$MPFR/lib
-L$GMP/lib -L$APRON/lib -o test test.c -lpolkaMPQ -lapron -lmpfr -lgmp},
assuming that the POLKA library is used in
its 'MPQ' version (internal number representation is GMP rationals) and
resides in @file{$APRON/include} and @file{$APRON/lib} directories.

The @file{libpolkaMPQ.a} library is of course needed,
@file{libapron.a} contains all the code common to all APRON library
(manipulation of expressions, environments, ...), as well as ITV
functions (quasi)linearisation facilities of APRON,...), last the
libraries @code{libmpfr.a} and @code{libgmp.a} are required both by
@sc{NewPolka} and @sc{APRON} .
@item
If some file @file{test.c} uses the PPL library via APRON, the
compilation command should look like @samp{g++ -I$ITV/include
-I$MPFR/include -I$GMP/include -I$APRON/include -I$PPL/include
-L$ITV/lib -L$MPFR/lib -L$GMP/lib -L$APRON/lib -L$PPL/lib -o test
test.c -la_ppl -lppl -lgmpxx -lapron -lmpfr
-lgmp}, assuming that PPL resides in $PPL and PPL APRON interface in
@file{$APRON/include} and @file{$APRON/lib} directories.

Notice that the PPL library (@file{libppl.a}) is a C++ library, you
need to use @samp{g++} instead of @samp{gcc} for linking. You also
need the C++ layer on top of GMP (@file{libgmpxx.a}). The
@file{libap_ppl.a} library contains the layer on top of PPL which
implements the APRON interface.
@end enumerate
You should look at the specific documentation of the libraries for
more details.

@c -------------------------------------------------------------------
@node C Naming conventions, Allocating managers and setting options, C Headers and Libraries, C Programming Guidelines
@subsection Naming conventions and Allocation/Deallocation schemes
@c -------------------------------------------------------------------

The general rule is that all type and function names defined by the
library are prefixed with @code{ap_}, in order to prevent name
conflicts with other libraries. Moreover, functions operating on
objects of type @code{ap_typ_t} are usually prefixed with
@code{ap_typ_op}.

Given an object of datatype @code{ap_typ_t*}, two kinds of allocation/deallocation pairs of functions may be defined:

@enumerate
@item
variable declaration: @code{ap_typ_t obj;}
@itemize
@item Initialization:
@code{void typ_init(ap_typ_t* arg, ...)} or @code{ap_typ_t ap_typ_make(...)}
@item Finalization:
@code{void ap_typ_clear(ap_typ_t* arg)}
@end itemize
this pair of functions follows the semantics used in the GMP
library. The first function initializes the object of type
@code{ap_typ_t} pointed to by @var{arg}, and fills it with a valid
content. The second function deallocates the memory possibly pointed
to by fields of the object @code{*arg}, but do not attempt to
deallocate the memory pointed by @var{arg}.
@item
variable declaration: @code{ap_typ_t* obj;}
@itemize
@item Allocation
@code{ap_typ_t* ap_typ_alloc(...)}
@item Deallocation
@code{void ap_typ_free(ap_typ_t* arg)}
@end itemize
the first function allocates an object of type @code{typ_t} and then
calls a @code{ap_typ_init}-like function on the result; the second
functions first call a @code{ap_typ_clear}-like function and then
deallocate the memory pointed by @var{arg}.
@end enumerate

@c -------------------------------------------------------------------
@node Allocating managers and setting options, Sequel of the small example, C Naming conventions, C Programming Guidelines
@subsection Allocating managers and setting options
@c -------------------------------------------------------------------

From the user point of view, the benefit of using the APRON interface
is to restrict the place where the user is aware of the real library
in use to the code initializing the manager, as illustrated by the
following example:
@example
#include "ap_global1.h"
#include "pk.h"

/* Allocating a Polka manager, for polyhedra with strict constraints */
manager_t* man = pk_manager_alloc(true);
/* Setting options offered by the common interface,
   but with meaning possibly specific to the library */
manager_set_abort_if_exception(man,EXC_OVERFLOW,true);
@{
  funopt_t funopt;
  funopt_init(&funopt);
  funopt.algorithm = 1; /* default value is 0 */
  manager_set_funopt(man,fun_widening,&funopt); /* Setting options for widening */
@}
@{
  funopt_t funopt = manager_get_funopt(man,fun_widening);
  funopt.timeout = 30;
  manager_set_funopt(man,fun_widening,&funopt);
@}
/* Obtaining the internal part of the manager and setting specific options */
pk_internal_t* pk = manager_get_internal(man);
pk_set_max_coeff_size(pk,size);
@end example
The standard operations can then be used and will have the
semantics defined in the interface. Notice however that some
generic functions are not formally generic: @code{abstract_fprint},
@code{abstract_fdump}, @code{abstract_approximate}.
At any point, options may be modified in the same way as during
the initialization.

@c -------------------------------------------------------------------
@node Sequel of the small example, Typing issue in C, Allocating managers and setting options, C Programming Guidelines
@subsection Sequel of the small example
@c -------------------------------------------------------------------
An environment can be created as follows:

@smallexample
/* Create an environment with 6 real variables */
ap_var_t name_of_dim[6] = @{
  "x","y","z","u","w","v"
@};
ap_environment_t* env = ap_environment_alloc(NULL,0,name_of_dim,6);
@end smallexample

Then, we build an array of constraints. At level 1, an array of
constraints is an abstract datatype, which requires careful
manipulation w.r.t. memory management.

@smallexample
/* Create an array of constraints of size 2 */
ap_lincons1_array_t array = ap_lincons1_array_make(env,2);

/* 1.a Creation of an inequality constraint */
ap_linexpr1_t expr = ap_linexpr1_make(env,AP_LINEXPR_SPARSE,1);
ap_lincons1_t cons = ap_lincons1_make(AP_CONS_SUP,&expr,NULL);
    /* Now expr is memory-managed by cons */
/* 1.b Fill the constraint */
ap_lincons1_set_list(&cons,
		     AP_COEFF_S_INT,"x",
		     AP_CST_S_FRAC,1,2,
		     AP_END);
/* 1.c Put in the array */
ap_lincons1_array_set(&array,0,&cons);
    /* Now cons is memory-managed by array */

/* 2.a Creation of an inequality constraint */
expr = ap_linexpr1_make(env,AP_LINEXPR_SPARSE,2);
cons = ap_lincons1_make(AP_CONS_SUPEQ,&expr,NULL);
    /* The old cons is not lost, because it is stored in the array.
       It would be an error to clear it (same for expr). */
/* 2.b Fill the constraint */
ap_lincons1_set_list(&cons,
		     AP_COEFF_S_INT,1,"x",
		     AP_COEFF_S_INT,1,"y",
		     AP_COEFF_S_INT,1,"z",
		     AP_END);
/* 2.c Put in the array */
ap_lincons1_array_set(&array,1,&cons);
@end smallexample

Last we can build an abstract value.

@smallexample
/* Creation of an abstract value defined by the array of constraints */
ap_abstract1_t abs = ap_abstract1_of_lincons_array(man,env,&array);

fprintf(stdout,"Abstract value:\n");
ap_abstract1_fprint(stdout,man,&abs);
@end smallexample

We  now deallocate everything:

@smallexample
/* deallocation */
ap_lincons1_array_clear(&array);
ap_abstract1_clear(&abs);
ap_environment_free(env);
ap_manager_free(man);
@end smallexample

@c -------------------------------------------------------------------
@node Typing issue in C,  , Sequel of the small example, C Programming Guidelines
@subsection Typing issue in C
@c -------------------------------------------------------------------

The use of several libraries at the same time via the common
interface and the managers associated to each library raises the
problem of typing. Look at the following code:

@example
ap_manager_t* manpk = pk_manager_alloc(true); /* manager for Polka */
ap_manager_t* manoct = oct_manager_alloc();    /* manager for octagon */

ap_abstract0_t* abs1 = ap_abstract_top(manpk,3,3);
ap_abstract0_t* abs2 = ap_abstract_top(manoct,3,3);
bool b = ap_abstract0_is_eq(manoct,abs1,abs2);
  /* Problem: the effective function called (octagon_is_eq) expects
     abs1 to be an octagon, and not a polyhedron ! */

ap_abstract0_t* abs3 = ap_abstract_top(manoct,3,3);
abstract0_meet_with(manpk,abs2,abs3);
  /* Problem: the effective function called (pk_meet_with) expects
     abs2 and abs3 to be polyhedra, but they are octagons */
@end example

There is actually no static typing, as @code{abstract0_t*}
and @code{manager_t} are abstract types shared by the different
libraries. Types are thus dynamically checked by the interface.
Notice that the use of @emph{C++} and inheritance would not solve
directly the problem, if functions of the interface are methods of
the manager; one would have:

@example
ap_manager_t* manpk = pk_manager_alloc(true);
  /* manager for Polka, effective type pk_manager_t* */
ap_manager_t* manoct = oct_manager_alloc();
  /* manager for octagon, effective type oct_manager_t* */

ap_abstract0_t* abs1 = manpk->abstract_top(3,3);
  /* effective type: poly_t */
ap_abstract0_t* abs2 = manoct->abstract_top(3,3);
  /* effective type: oct_t */
bool b = manoct->abstract0_is_eq(abs1,abs2);
  /* No static typing possible:
     manpk->abstract0_is_eq and manoct->abstract0_is_eq should have the same
     signature (otherwise one cannot interchange manpk and manoct in the code),
     which means that abs1 and abs2 are supposed to be of type abstract0_t* */
*/
@end example

Currently, only the OCaml polymorphic type system allows to solve
elegantly this problem.

@c ===================================================================
@node OCaml Programming Guidelines, MakingLibrary, C Programming Guidelines, APRON Guidelines
@section OCaml Programming Guidelines
@c ===================================================================

All modules belonging to the APRON interface itself (@code{Scalar},
@code{Interval}, ..., @code{Manager}, @code{Linexpr0},
... @code{Abstract1}) are included in a big encapsulating module named
@code{Apron}. In addition, there are modules like @code{Box}
(intervals), @code{Oct} (octagons), @code{Polka} (linear equalities
and convex polyhedra) and @code{Ppl} (convex polyhedra and linear
congruences) not included in @code{Apron}.

Generic abstract values have the type @code{'a Abstract1.t}, generic
managers the type @code{'a Manager.t}. A typical operation like the
emptiness test has the type @code{val is_bottom : 'a Manager.t -> 'a
Abstract1.t -> bool}.

Octagons of @sc{Octagon} have the type @code{Oct.t
Apron.Abstract1.t}. The corresponding managers have thus the type
@code{Oct.t Manager.t}.

See @uref{../mlapronidl/index.html,OCaml interface} for the
documentation.

@c ===================================================================
@node MakingLibrary,  , OCaml Programming Guidelines, APRON Guidelines
@section How to make an existing library conformant to APRON ?
@c ===================================================================

We briefly describe here how to connect an existing library to the
common interface.

First, the library has to expose an interface which conforms to the
level 0 of the interface (module @code{abstract0}).  All the functions
described in this module should be defined. If a function is not
really implemented, at least it shoulld contain the code raising the
exception @code{EXC_NOT_IMPLEMENTED}.  The implementor may use any
functions of the files @file{ap_coeff.h}, @file{ap_linexpr0.h},
@file{ap_lincons0.h}, @file{ap_generator0.h} and @file{ap_manager.h}
to help the job of converting datatypes of the interface to internal
datatypes used inside the library.

Second and last, the library should expose an initialization
function that allocates and initializes properly an object of type
@code{manager_t}. For this purpose, the module @code{manager} offers the
utility functions @code{manager_alloc}. As an example, we give the
definition of the function allocating a manager as implemented in
the @emph{NewPolka}.

@enumerate
@item Header of the function:
@example
manager_t* pk_manager_alloc(
  bool strict /* specific parameter: do we allow strict constaints ? */
)
@end example
@item Allocation and initialisation of global data specific to @emph{NewPolka}:
@example
@{
  pk_internal_t* pk = pk_internal_alloc(strict); /* allocation */
  pk_set_approximate_max_coeff_size(pk, 1);
    /* initialization of specific functions
       (not offered in the common interface) */
@}
@end example
@item Allocation of the manager itself:
@example
  manager_t* man = ap_manager_alloc("polka","2.0",
				    pk, (void (*)(void*))pk_internal_free);
@end example
We provide resp. name, version, internal specific manager, and the
function to free it.

The function @code{manager_alloc} sets the options of the
common interface to their default value (see documentation).
@item Initialization of the ``virtual'' table: we need to connect
  the generic functions of the interface (eg, @code{abstract_meet},
  \ldots) to the actual functions of the library.
@example
  funptr = man->funptr;

  funptr[fun_minimize] = &poly_minimize;
  funptr[fun_canonicalize] = &poly_canonicalize;
  funptr[fun_hash] = &poly_hash;
  funptr[fun_approximate] = &poly_approximate;
  funptr[fun_fprint] = &poly_fprint;
  funptr[fun_fprintdiff] = &poly_fprintdiff;
  funptr[fun_fdump] = &poly_fdump;
  ...
@end example
@item Last, we return the allocated manager:
@example
  return man;
@}
@end example
@end enumerate
That's all for the implementor side.

@c *******************************************************************
@node Managers and Abstract Domains, Scalars & Intervals & Coefficients, APRON Guidelines, Top
@chapter Managers and Abstract Domains
@c *******************************************************************

APRON makes use of a global manager for:

@itemize
@item
selecting an effective underlying library/abstract domain;
@item
controlling various options;
@item
managing exceptions and flags;
@item
and also managing internal workspace needed for some library.
@end itemize

In a multithreaded program, both managers and abstract values should
not be shared between threads (make copies to transmit information).

Managers are allocated by the underlying libraries/abstract domains, but are freed via an APRON function.

@menu
* Managers::
* Box::
* Oct::
* NewPolka::
* PPL::
* pkgrid::
@end menu

@c ===================================================================
@node Managers, Box, Managers and Abstract Domains, Managers and Abstract Domains
@section Managers (@file{ap_manager.h})
@c ===================================================================

@menu
* APRON Global Datatypes::
* Functions related to managers::
@end menu

@c -------------------------------------------------------------------
@node APRON Global Datatypes, Functions related to managers, Managers, Managers
@subsection Datatypes
@c -------------------------------------------------------------------

@deftp datatype tbool_t
@example
typedef enum tbool_t @{
  tbool_false=0,
  tbool_true=1,
  tbool_top=2,   /* don't know */
@} tbool_t;
static inline tbool_t tbool_of_bool(bool a);
static inline tbool_t tbool_or(tbool_t a, tbool_t b);
static inline tbool_t tbool_and(tbool_t a, tbool_t b);
@end example
Booleans with a third unknown value.
@end deftp

@deftp datatype ap_membuf_t
@example
typedef struct ap_membuf_t @{
  void* ptr;
  size_t size;
@} ap_membuf_t;
@end example
For serialization.
@end deftp

@deftp datatype ap_manager_t
APRON managers (opaque type).
@end deftp

@deftp datatype ap_funid_t
For identifying functions in excpetions, and when reading/setting
options attached to them.
@example
typedef enum ap_funid_t @{
  AP_FUNID_UNKNOWN,
  AP_FUNID_COPY,
  AP_FUNID_FREE,
  AP_FUNID_ASIZE, /* For avoiding name conflict with AP_FUNID_SIZE */
  AP_FUNID_MINIMIZE,
  AP_FUNID_CANONICALIZE,
  AP_FUNID_HASH,
  AP_FUNID_APPROXIMATE,
  AP_FUNID_FPRINT,
  AP_FUNID_FPRINTDIFF,
  AP_FUNID_FDUMP,
  AP_FUNID_SERIALIZE_RAW,
  AP_FUNID_DESERIALIZE_RAW,
  AP_FUNID_BOTTOM,
  AP_FUNID_TOP,
  AP_FUNID_OF_BOX,
  AP_FUNID_DIMENSION,
  AP_FUNID_IS_BOTTOM,
  AP_FUNID_IS_TOP,
  AP_FUNID_IS_LEQ,
  AP_FUNID_IS_EQ,
  AP_FUNID_IS_DIMENSION_UNCONSTRAINED,
  AP_FUNID_SAT_INTERVAL,
  AP_FUNID_SAT_LINCONS,
  AP_FUNID_SAT_TCONS,
  AP_FUNID_BOUND_DIMENSION,
  AP_FUNID_BOUND_LINEXPR,
  AP_FUNID_BOUND_TEXPR,
  AP_FUNID_TO_BOX,
  AP_FUNID_TO_LINCONS_ARRAY,
  AP_FUNID_TO_TCONS_ARRAY,
  AP_FUNID_TO_GENERATOR_ARRAY,
  AP_FUNID_MEET,
  AP_FUNID_MEET_ARRAY,
  AP_FUNID_MEET_LINCONS_ARRAY,
  AP_FUNID_MEET_TCONS_ARRAY,
  AP_FUNID_JOIN,
  AP_FUNID_JOIN_ARRAY,
  AP_FUNID_ADD_RAY_ARRAY,
  AP_FUNID_ASSIGN_LINEXPR_ARRAY,
  AP_FUNID_SUBSTITUTE_LINEXPR_ARRAY,
  AP_FUNID_ASSIGN_TEXPR_ARRAY,
  AP_FUNID_SUBSTITUTE_TEXPR_ARRAY,
  AP_FUNID_ADD_DIMENSIONS,
  AP_FUNID_REMOVE_DIMENSIONS,
  AP_FUNID_PERMUTE_DIMENSIONS,
  AP_FUNID_FORGET_ARRAY,
  AP_FUNID_EXPAND,
  AP_FUNID_FOLD,
  AP_FUNID_WIDENING,
  AP_FUNID_CLOSURE,
  AP_FUNID_SIZE,
  AP_FUNID_CHANGE_ENVIRONMENT,
  AP_FUNID_RENAME_ARRAY,
  AP_FUNID_SIZE2
@} ap_funid_t;

extern const char* ap_name_of_funid[AP_FUNID_SIZE2];
/* give the name of a function identifier */
@end example
@end deftp

@deftp datatype ap_exc_t
@deftpx datatype ap_exc_log_t
Exceptions and exception logs (chained in a list, the first one being
the last one).
@example
typedef enum ap_exc_t @{
  AP_EXC_NONE,           /* no exception detected */
  AP_EXC_TIMEOUT,        /* timeout detected */
  AP_EXC_OUT_OF_SPACE,   /* out of space detected */
  AP_EXC_OVERFLOW,        /* magnitude overflow detected */
  AP_EXC_INVALID_ARGUMENT, /* invalid arguments */
  AP_EXC_NOT_IMPLEMENTED, /* not implemented */
  AP_EXC_SIZE
@} ap_exc_t;
extern const char* ap_name_of_exception[AP_EXC_SIZE];
typedef struct ap_exclog_t @{
  ap_exc_t exn;
  ap_funid_t funid;
  char* msg;                   /* dynamically allocated */
  struct ap_exclog_t* tail;
@} ap_exclog_t;
@end example
@end deftp

@anchor{ap_funopt_t}
@deftp datatype ap_funopt_t
Options attached to functions.
@example
typedef struct ap_funopt_t @{
  int algorithm;
  /* Algorithm selection:
     - 0 is default algorithm;
     - MAX_INT is most accurate available;
     - MIN_INT is most efficient available;
     - otherwise, no accuracy or speed meaning
  */
  size_t timeout; /* unit !? */
  /* Above the given computation time, the function may abort with the
     exception flag flag_time_out on.
  */
  size_t max_object_size; /* in abstract object size unit. */
  /* If during the computation, the size of some object reach this limit, the
     function may abort with the exception flag flag_out_of_space on.
  */
  bool flag_exact_wanted;
  /* return information about exactitude if possible
  */
  bool flag_best_wanted;
  /* return information about best correct approximation if possible
  */
@} ap_funopt_t;
@end example
@end deftp

@c -------------------------------------------------------------------
@node Functions related to managers,  , APRON Global Datatypes, Managers
@subsection Functions related to managers
@c -------------------------------------------------------------------

@deftypefun void ap_manager_free (ap_manager_t* @var{man})
Free a manager (dereference a counter, and possibly deallocate).
@end deftypefun

@deftypefun const char* ap_manager_get_library (ap_manager_t* @var{man})
@deftypefunx const char* ap_manager_get_version (ap_manager_t* @var{man})
Reading the name and the version of the attached underlying library.
@end deftypefun

@deftypefun bool ap_manager_get_flag_exact (ap_manager_t* @var{man})
@deftypefunx bool ap_manager_get_flag_best (ap_manager_t* @var{man})
Return @code{true} if the last called APRON function returned an
exact (resp. a best approximation) result.
@end deftypefun

@anchor{Manager options}
@subheading Options
@xref{ap_funopt_t}.
@deftypefun ap_funopt_t ap_manager_get_funopt (ap_manager_t* @var{man}, ap_funid_t @var{funid})
Getting the option attached to the specified function in the
manager. @var{funid} should be less than @code{AP_FUNID_SIZE} (no
option associated to other identifiers). Otherwise, abort with a
message.
@end deftypefun
@deftypefun void ap_manager_set_funopt (ap_manager_t* @var{man}, ap_funid_t @var{funid}, ap_funopt_t* @var{fopt})
Setting the option attached to the specified function in the
manager. @var{fopt} is copied (and not only referenced). @var{funid}
should be less than @code{AP_FUNID_SIZE} (no option associated to
other identifiers). Otherwise, do nothing.
@end deftypefun
@deftypefun void ap_funopt_init (ap_funopt_t* @var{fopt})
Initialize @var{fopt} with default values.
@end deftypefun

@subheading Exceptions

@deftypefun bool ap_manager_get_abort_if_exception (ap_manager_t* @var{man}, ap_exc_t @var{exn})
Return true if the program abort when the exception @var{exn} is
raised by some function. Otherwise, in such a case, a valid (but
dummy) value should be returned by the function that raises the exception.
@end deftypefun
@deftypefun void ap_manager_set_abort_if_exception (ap_manager_t* @var{man}, ap_exc_t @var{exn}, bool @var{flag})
Position the above-described option.
@end deftypefun

@deftypefun ap_exc_t ap_manager_get_exception (ap_manager_t* @var{man})
Get the last exception raised.
@end deftypefun
@deftypefun ap_exclog_t ap_manager_get_exclog (ap_manager_t* @var{man})
Get the full log of exceptions. The first one in the list is the last
raised one.
@end deftypefun

@c ===================================================================
@node Box, Oct, Managers, Managers and Abstract Domains
@section Box (@file{box.h}): intervals abstract domain
@c ===================================================================

@include box.texi

@c ===================================================================
@node Oct, NewPolka, Box, Managers and Abstract Domains
@section Oct: octagon abstract domain
@c ===================================================================

@uref{oct_doc.html}

@c ===================================================================
@node NewPolka, PPL, Oct, Managers and Abstract Domains
@section NewPolka (@file{pk.h}): convex polyhedra and linear equalities abstract domains
@c ===================================================================

@include newpolka.texi

@c ===================================================================
@node PPL, pkgrid, NewPolka, Managers and Abstract Domains
@section PPL (@file{ap_ppl.h}): convex polyhedra and linear congruences abstract domains
@c ===================================================================

@include ap_ppl.texi

@c ===================================================================
@node pkgrid,  , PPL, Managers and Abstract Domains
@section pkgrid (@file{ap_pkgrid.h}): reduced product of NewPolka convex polyhedra and PPL linear congruences abstract domains
@c ===================================================================

@include ap_pkgrid.texi

@c *******************************************************************
@node Scalars & Intervals & Coefficients, Level 1 of the interface, Managers and Abstract Domains, Top
@chapter Scalars & Intervals & coefficients
@c *******************************************************************

@emph{Scalars} are scalar numbers, implemented either as an (inexact)
floating point type or an (exact) rational type.  @emph{Intervals} are
intervals built on scalars.  @emph{Coefficients} are either scalars or
intervals.

@menu
* Scalars::
* Intervals::
* Coefficients::
@end menu

@ifnothtml
We sum up the involved types below (numbers denotes sizes in bytes
on a typical 32 bits computer.
@verbatim
    ap_scalar_t     12       ap_interval_t  8
|-----------------|        |--------------|
| ap_scalar_discr |  4     | ap_scalar_t* | 4
|-----------------|        |--------------|
| double | mpq_t* |  8     | ap_scalar_t* | 4
|-----------------|        |--------------|

		ap_coeff_t             8
     |-------------------------------|
     |        ap_coeff_discr         | 4
     |-------------------------------|
     | ap_scalar_t* | ap_interval_t* | 4
     |-------------------------------|
@end verbatim

These types are manipulated using pointers, with creator
@code{X_t* X_alloc()} and destructors @code{void X_free(X_t*)}.
@end ifnothtml



@c ===================================================================
@node Scalars, Intervals, Scalars & Intervals & Coefficients, Scalars & Intervals & Coefficients
@section Scalars (@file{ap_scalar.h})
@c ===================================================================

@deftp datatype ap_scalar_discr_t
@example
typedef enum ap_scalar_discr_t @{
  AP_SCALAR_DOUBLE, /* floating-point with double */
  AP_SCALAR_MPQ     /* rational with multi-precision GMP */
@} ap_scalar_discr_t;
@end example
Discriminant indicating the underlying type of a scalar number.
@end deftp

@deftp datatype ap_scalar_t
@example
typedef struct ap_scalar_t @{
  ap_scalar_discr_t discr;
  union @{
    double dbl;
    mpq_ptr mpq; /* +infty coded by 1/0, -infty coded by -1/0 */
  @} val;
@} ap_scalar_t;
@end example
A scalar number is either a double, or a multi-precision rational, as
implemented by GMP.
@end deftp

@menu
* Initializing scalars::
* Assigning scalars::
* Converting scalars::
* Comparing scalars::
* Other operations on scalars::
@end menu


@c -------------------------------------------------------------------
@node Initializing scalars, Assigning scalars, Scalars, Scalars
@subsection Initializing scalars
@c -------------------------------------------------------------------
@deftypefun ap_scalar_t* ap_scalar_alloc ()
Allocate a scalar, of default type DOUBLE (the most economical)
@end deftypefun

@deftypefun void ap_scalar_free (ap_scalar_t* @var{op})
Deallocate a scalar.
@end deftypefun

@deftypefun void ap_scalar_reinit (ap_scalar_t* @var{op}, ap_scalar_discr_t @var{discr})
Change the type of an already allocated scalar (mainly for internal
use)
@end deftypefun

@deftypefun void ap_scalar_init (ap_scalar_t* @var{op}, ap_scalar_discr_t @var{discr})
@deftypefunx void ap_scalar_clear (ap_scalar_t* @var{op})
Initialize and clear a scalar \`a la GMP (internal use).
@end deftypefun

@c -------------------------------------------------------------------
@node Assigning scalars, Converting scalars, Initializing scalars, Scalars
@subsection Assigning scalars
@c -------------------------------------------------------------------
@deftypefun void ap_scalar_set (ap_scalar_t* @var{rop}, ap_scalar_t* @var{op})
Set the value of @var{rop} from @var{op}.
@end deftypefun

@deftypefun void ap_scalar_set_mpq (ap_scalar_t* @var{rop}, mpq_t @var{mpq})
@deftypefunx void ap_scalar_set_int (ap_scalar_t* @var{rop}, long int @var{i})

@deftypefunx void ap_scalar_set_frac (ap_scalar_t* @var{rop}, long int @var{i}, unsigned long int @var{j})
Change the type of @var{rop} to MPQ and set its value to
resp. @var{mpq}, @var{i}, and @var{i}/@var{j}.
@end deftypefun

@deftypefun void ap_scalar_set_double (ap_scalar_t* @var{rop}, double @var{k})
Change the type of @var{rop} to DOUBLE and set its value to @var{k}.
@end deftypefun

@deftypefun void ap_scalar_set_infty (ap_scalar_t* @var{rop}, int @var{sgn})
Set the value of @var{rop} to @var{sgn}*infinity. Keep the type of the
@var{rop}.
@end deftypefun

@deftypefun ap_scalar_t* ap_scalar_alloc_set (ap_scalar_t* @var{op})
@deftypefunx ap_scalar_t* ap_scalar_alloc_set_mpq (mpq_t @var{mpq})
@deftypefunx ap_scalar_t* ap_scalar_alloc_set_double (double @var{k})
Combined allocation and assignement.
@end deftypefun

@c -------------------------------------------------------------------
@node Converting scalars, Comparing scalars, Assigning scalars, Scalars
@subsection Converting scalars
@c -------------------------------------------------------------------
@deftypefun void ap_mpq_set_scalar (mpq_t @var{mpq}, ap_scalar_t* @var{op}, int @var{round})
Set @var{mpq} with the value of @var{op}, possibly converting from
DOUBLE type.

@var{round} currently unused.
@end deftypefun

@deftypefun double ap_scalar_get_double (ap_scalar_t* @var{op}, int @var{round})
Return the value of @var{op} in DOUBLE type, possibly converting from
MPQ type.

Conversion may be not exact. @var{round} currently unused.
@end deftypefun

@c -------------------------------------------------------------------
@node Comparing scalars, Other operations on scalars, Converting scalars, Scalars
@subsection Comparing scalars
@c -------------------------------------------------------------------
@deftypefun int ap_scalar_infty (ap_scalar_t* @var{op})
Return @code{-1} if @var{op} is set to +infty, @code{-1} if set to
-infty, and @code{0} otherwise.
@end deftypefun

@deftypefun int ap_scalar_sgn (ap_scalar_t* @var{op})
Return the sign of @var{op} (@code{+1}, @code{0} or @code{-1}).
@end deftypefun

@deftypefun int ap_scalar_cmp (ap_scalar_t* @var{op1}, ap_scalar_t* @var{op2})
@deftypefunx int ap_scalar_cmp_int (ap_scalar_t* @var{op1}, int @var{op2})
Exact comparison between two scalars (resp. a scalar and an integer).

Return @code{-1} if @var{op1} is less than @var{op2}, @code{0} if they
are equal, and @code{+1} if @code{op1} is greater than @var{op2}.
@end deftypefun

@deftypefun bool ap_scalar_equal (ap_scalar_t* @var{op1}, ap_scalar_t* @var{op2});
@deftypefunx bool ap_scalar_equal_int (ap_scalar_t* @var{op1}, int @var{op2});
Equality test between two scalars (resp. a scalar and an integer).

Return @code{true} if equality.
@end deftypefun

@c -------------------------------------------------------------------
@node Other operations on scalars,  , Comparing scalars, Scalars
@subsection Other operations on scalars
@c -------------------------------------------------------------------

@deftypefun void ap_scalar_neg (ap_scalar_t* @var{rop}, ap_scalar_t* @var{op})
Negation.
@end deftypefun

@deftypefun void ap_scalar_inv (ap_scalar_t* @var{rop}, ap_scalar_t* @var{op})
Inversion. Not exact for DOUBLE type.
@end deftypefun

@deftypefun void ap_scalar_swap (ap_scalar_t* @var{op1}, ap_scalar_t* @var{op2})
Exchange the values of @var{op1} and @var{op2}.
@end deftypefun

@deftypefun int ap_scalar_hash (ap_scalar_t* @var{op})
Return an hash code (for instance for OCaml interface).
@end deftypefun

@deftypefun void ap_scalar_fprint (FILE* @var{stream}, ap_scalar_t* @var{op})
Print @var{op} on the stream @var{stream}.
@end deftypefun

@c ===================================================================
@node Intervals, Coefficients, Scalars, Scalars & Intervals & Coefficients
@section Intervals (@file{ap_interval.h})
@c ===================================================================

@deftp datatype ap_interval_t
@example
typedef struct ap_interval_t @{
  ap_scalar_t* inf;
  ap_scalar_t* sup;
@} ap_interval_t;
@end example
Intervals on scalars.
@end deftp

@menu
* Initializing intervals::
* Assigning intervals::
* Comparing intervals::
* Other operations on intervals::
* Array of intervals::
@end menu


@c -------------------------------------------------------------------
@node Initializing intervals, Assigning intervals, Intervals, Intervals
@subsection Initializing intervals
@c -------------------------------------------------------------------
@deftypefun void ap_interval_alloc ()
Allocate an interval (with scalars of default type DOUBLE, the most
economical).
@end deftypefun

@deftypefun void ap_interval_free (ap_interval_t* @var{op})
Deallocate an interval.
@end deftypefun

@deftypefun void ap_interval_reinit (ap_interval_t* @var{op}, ap_scalar_discr_t @var{discr})
Change the type of the bounds of the interval (mainly for internal
use).
@end deftypefun

@c -------------------------------------------------------------------
@node Assigning intervals, Comparing intervals, Initializing intervals, Intervals
@subsection Assigning intervals
@c -------------------------------------------------------------------
@deftypefun void ap_interval_set (ap_interval_t* @var{rop}, ap_interval_t* @var{op})
Set the value of @var{rop} from @var{op}.
@end deftypefun

@deftypefun void ap_interval_set_scalar (ap_interval_t* @var{rop}, ap_scalar_t* @var{inf}, ap_scalar_t* @var{sup})
Set the value of @var{rop} from the interval [@var{inf},@var{sup}].
@end deftypefun

@deftypefun void ap_interval_set_mpq (ap_interval_t* @var{rop}, mpq_t @var{inf}, mpq_t @var{sup})
@deftypefunx void ap_interval_set_int (ap_interval_t* @var{rop}, int @var{inf}, int @var{sup})
@deftypefunx void ap_interval_set_frac (ap_interval_t* @var{rop}, int @var{numinf}, int @var{deninf}, int @var{numsup}, int @var{densup})
Set the value of @var{rop} from the interval [@var{inf},@var{sup}] or
[@var{numinf}/@var{deninf},@var{numsup}/@var{densup}]. The scalars are
of type MPQ.
@end deftypefun

@deftypefun void ap_interval_set_double (ap_interval_t* @var{rop}, double @var{inf}, double @var{sup})
Set the value of @var{rop} from the interval [@var{inf},@var{sup}].
The scalars are of type DOUBLE.
@end deftypefun

@deftypefun void ap_interval_set_top (ap_interval_t* @var{op})
@deftypefunx void ap_interval_set_bottom (ap_interval_t* @var{op})
Set the value of @var{rop} resp. to the top interval [-oo,+oo] or to
the empty interval [+1,-1].
@end deftypefun

@deftypefun ap_interval_t* ap_interval_alloc_set (ap_interval_t* @var{op})
Combined allocation and assignement.
@end deftypefun

@c -------------------------------------------------------------------
@node Comparing intervals, Other operations on intervals, Assigning intervals, Intervals
@subsection Comparing intervals
@c -------------------------------------------------------------------
@deftypefun bool ap_interval_is_top (ap_interval_t* @var{op})
@deftypefunx bool ap_interval_is_bottom (ap_interval_t* @var{op})
Return @code{true} if the interval is resp. the universe interval
([-oo,+oo]) or an empty interval.
@end deftypefun

@deftypefun bool ap_interval_is_leq (ap_interval_t* @var{op1}, ap_interval_t* @var{op2})
Inclusion test.

Return true if the interval @var{op1} is included in @var{op2}.
@end deftypefun

@deftypefun bool ap_interval_equal (ap_interval_t* @var{op1}, ap_interval_t* @var{op2})
Equality test.

Return true if the interval @var{op1} is included in @var{op2}.
@end deftypefun

@deftypefun int ap_interval_cmp (ap_interval_t* @var{op1}, ap_interval_t* @var{op2})
Non-total comparison.
@table @code
@item 0 equality
@item -1 @var{op1} included in @var{op2}
@item +1 @var{op2} included in @var{op1}
@item -2 @var{op1.inf} less than @var{op2.inf}
@item +2 @var{op1.inf} greater than @var{op2.inf}
@end table
@end deftypefun

@c -------------------------------------------------------------------
@node Other operations on intervals, Array of intervals, Comparing intervals, Intervals
@subsection Other operations on intervals
@c -------------------------------------------------------------------

@deftypefun void ap_interval_neg (ap_interval_t* @var{rop}, ap_interval_t* @var{op})
Negation.
@end deftypefun

@deftypefun void ap_interval_swap (ap_interval_t* @var{op1}, ap_interval_t* @var{op2})
Exchange the values of @var{op1} and @var{op2}.
@end deftypefun

@deftypefun int ap_interval_hash (ap_interval_t* @var{op})
Return an hash code (for instance for OCaml interface).
@end deftypefun

@deftypefun void ap_interval_fprint (FILE* @var{stream}, ap_interval_t* @var{op})
Print @var{op} on the stream @var{stream}.
@end deftypefun

@c -------------------------------------------------------------------
@node Array of intervals,  , Other operations on intervals, Intervals
@subsection Array of intervals
@c -------------------------------------------------------------------
@deftypefun ap_interval_t** ap_interval_array_alloc (size_t @var{size})
Allocate an array of intervals, initialized with [0,0] values.
@end deftypefun

@deftypefun void ap_interval_array_free (ap_interval_t** @var{array}, size_t @var{size})
Clearing and deallocating an array of intervals.
@end deftypefun

@c ===================================================================
@node Coefficients,  , Intervals, Scalars & Intervals & Coefficients
@section Coefficients (@file{ap_coeff.h})
@c ===================================================================
@deftp datatype ap_coeff_discr_t
@example
typedef enum ap_coeff_discr_t @{ AP_COEFF_SCALAR, AP_COEFF_INTERVAL @}
ap_coeff_discr_t;
@end example
Discriminant indicating the underlying type of a coefficient.
@end deftp

@deftp datatype ap_coeff_t
@example
typedef struct ap_coeff_t @{
  ap_coeff_discr_t discr;
  union @{
    ap_scalar_t* scalar;
    ap_interval_t* interval;
  @} val;
@} ap_coeff_t;
@end example
A coefficient is either a scalar or an interval.
@end deftp

@menu
* Initializing coefficients::
* Assigning coefficients::
* Comparing coefficients::
* Other operations on coefficients::
@end menu


@c -------------------------------------------------------------------
@node Initializing coefficients, Assigning coefficients, Coefficients, Coefficients
@subsection Initializing coefficients
@c -------------------------------------------------------------------

@deftypefun void ap_coeff_alloc (ap_coeff_discr_t @var{discr})
Allocate a coefficient, using @var{discr} to specify the type of
coefficient (scalar or interval).
@end deftypefun

@deftypefun void ap_coeff_free (ap_coeff_t* @var{op})
Deallocate a coefficient.
@end deftypefun

@deftypefun void ap_coeff_reinit (ap_coeff_t* @var{op}, ap_coeff_discr_t @var{discr1}, ap_scalar_discr_t @var{discr2})
Changing the type of the coefficient and also the type of the
underlting scalar(s).
@end deftypefun

@deftypefun void ap_coeff_reduce (ap_coeff_t* @var{op})
If the coefficient is an interval [a;a], convert it to a scalar. */
@end deftypefun

@deftypefun void ap_coeff_init (ap_coeff_t* @var{rop}, ap_coeff_discr_t @var{discr})
@deftypefunx void ap_coeff_init_set (ap_coeff_t* @var{rop}, ap_coeff_t* @var{op})
@deftypefunx void ap_coeff_clear (ap_coeff_t* @var{rop})
Initialize, initialize and assign, and clear a scalar \`a la GMP (internal use).
@end deftypefun

@c -------------------------------------------------------------------
@node Assigning coefficients, Comparing coefficients, Initializing coefficients, Coefficients
@subsection Assigning coefficients
@c -------------------------------------------------------------------
@deftypefun void ap_coeff_set (ap_coeff_t* @var{rop}, ap_coeff_t* @var{op})
Set the value of @var{rop} from @var{op}.
@end deftypefun

@deftypefun void ap_coeff_set_scalar (ap_coeff_t* @var{rop}, ap_scalar_t* @var{op})
@deftypefunx void ap_coeff_set_scalar_mpq (ap_coeff_t* @var{rop}, mpq_t @var{mpq})
@deftypefunx void ap_coeff_set_scalar_int (ap_coeff_t* @var{rop}, long int @var{i})
@deftypefunx void ap_coeff_set_scalar_frac (ap_coeff_t* @var{rop}, long int @var{i}, unsigned long int @var{j})
@deftypefunx void ap_coeff_set_scalar_double (ap_coeff_t* @var{rop}, double @var{k})
Set the type of @var{rop} to scalar, and sets its value as the
functions @code{ap_scalar_set_XXX}.
@end deftypefun

@deftypefun void ap_coeff_set_interval (ap_coeff_t* @var{rop}, ap_interval_t* @var{op})
@deftypefunx void ap_coeff_set_interval_scalar (ap_coeff_t* @var{rop}, ap_scalar_t* @var{inf}, ap_scalar_t* @var{sup})
@deftypefunx void ap_coeff_set_interval_mpq (ap_coeff_t* @var{rop}, mpq_t @var{inf}, mpq_t @var{sup})
@deftypefunx void ap_coeff_set_interval_int (ap_coeff_t* @var{rop}, int @var{inf}, int @var{sup})
@deftypefunx void ap_coeff_set_interval_frac (ap_coeff_t* @var{rop}, int @var{numinf}, int @var{deninf}, int @var{numsup}, int @var{densup})
@deftypefunx void ap_coeff_set_interval_double (ap_coeff_t* @var{rop}, double @var{inf}, double @var{sup})
Set the type of @var{rop} to interval, and sets its value as the
functions @code{ap_interval_set_XXX}.
@end deftypefun

@deftypefun ap_coeff_t* ap_coeff_alloc_set (ap_coeff_t* @var{op})

@deftypefunx ap_coeff_t* ap_coeff_alloc_set_scalar (ap_scalar_t* @var{scalar})
@deftypefunx ap_coeff_t* ap_coeff_alloc_set_interval (ap_interval_t* @var{interval})
Combined allocation and assignement.
@end deftypefun

@c -------------------------------------------------------------------
@node Comparing coefficients, Other operations on coefficients, Assigning coefficients, Coefficients
@subsection Comparing coefficients
@c -------------------------------------------------------------------

@deftypefun int ap_coeff_cmp (ap_coeff_t* @var{op1}, ap_coeff_t* @var{op2})
Non-total comparison.
@itemize
@item If @var{op1} and @var{op2} are scalars, corresponds to @code{ap_scalar_cmp}.
@item If @var{op1} and @var{op2} are intervals, corresponds to @code{ap_interval_cmp}.
@item otherwise, -3 if the first is a scalar, 3 otherwise
@end itemize
@end deftypefun

@deftypefun bool ap_coeff_equal (ap_coeff_t* @var{op1}, ap_coeff_t* @var{op2})
Equality test.
@end deftypefun

@deftypefun bool ap_coeff_zero (ap_coeff_t* @var{op})
Return true iff coeff is a zero scalar or an interval with zero
bounds.
@end deftypefun


@c -------------------------------------------------------------------
@node Other operations on coefficients,  , Comparing coefficients, Coefficients
@subsection Other operations on coefficients
@c -------------------------------------------------------------------

@deftypefun void ap_coeff_neg (ap_coeff_t* @var{rop}, ap_coeff_t* @var{op})
Negation.
@end deftypefun

@deftypefun void ap_coeff_swap (ap_coeff_t* @var{op1}, ap_coeff_t* @var{op2})
Exchange the values of @var{op1} and @var{op2}.
@end deftypefun

@deftypefun int ap_coeff_hash (ap_coeff_t* @var{op})
Return an hash code (for instance for OCaml interface).
@end deftypefun

@deftypefun void ap_coeff_fprint (FILE* @var{stream}, ap_coeff_t* @var{op})
Print @var{op} on the stream @var{stream}.
@end deftypefun

@c *******************************************************************
@node Level 1 of the interface, Level 0 of the interface, Scalars & Intervals & Coefficients, Top
@chapter Level 1 of the interface
@c *******************************************************************

This interface of level 1 is defined in @file{ap_global1.h}.

@menu
* Variables and related operations::
* Environments::
* Linear expressions of level 1::
* Linear constraints of level 1::
* Generators of level 1::
* Tree expressions of level 1::
* Tree constraints of level 1::
* Abstract values and operations of level 1::
@end menu

@noindent
The main functions brought by level 1 are

@itemize
@item
to convert variables to dimensions, thanks to the addition of
environments to objects;
@item
to redimension (abstract values), expressions, constraints and
generators defined on different environments.
@end itemize

The policy for redimensioning is the following one:

@itemize
@item
For functions taking one abstract value and one expression (or
constraint or generator, or array of ...), the environment of the
expression should be a sub-environment of the environment of the
abstract value. The environment of the result is the environment of
the argument abstract value.
@item
For functions taking several abstract values, their environments
should be the same. Otherwise, it is up to the user to move them
to a common super-environment (see @ref{Environments} and
@ref{Change of environments of abstract values of level 1}).
@end itemize

@ifnothtml
For information only (as these types are considered as abstract),
we sum up the involved types below.
@verbatim
 ap_var_t             ap_var_t      ap_environment_t
|-------|            |-------|   |----------------------|
| void* | by default | char* |   | ap_var_t* var_of_dim |
|-------|            |-------|   | size_t    intdim     |
				 | size_t    realdim    |
				 | size_t    count      |
				 |----------------------|
   ap_linexpr1_t
|-------------------|
| ap_linexpr0_t*    |
| ap_environment_t* |
|-------------------|

   ap_lincons1_t         ap_lincons1_array_t
|-------------------|  |----------------------|
| ap_lincons0_t*    |  | ap_lincons0_array_t* |
| ap_environment_t* |  | ap_environment_t*    |
|-------------------|  |----------------------|

   ap_generator1_t       ap_generator1_array_t
|-------------------|  |------------------------|
| ap_generator0_t*  |  | ap_generator0_array_t* |
| ap_environment_t* |  | ap_environment_t*      |
|-------------------|  |------------------------|

   ap_texpr1_t
|-------------------|
| ap_texpr0_t*      |
| ap_environment_t* |
|-------------------|

   ap_tcons1_t           ap_tcons1_array_t
|-------------------|  |----------------------|
| ap_tcons0_t*      |  | ap_tcons0_array_t*   |
| ap_environment_t* |  | ap_environment_t*    |
|-------------------|  |----------------------|

   ap_abstract1_t
|-------------------|
| ap_abstract0_t*   |
| ap_environment_t* |
|-------------------|
@end verbatim
@end ifnothtml

@c ===================================================================
@node Variables and related operations, Environments, Level 1 of the interface, Level 1 of the interface
@section Variables and related operations (@file{ap_var.h})
@c ===================================================================

A variable is not necessarily a name, it can be a more complex
structured datatype, depending on the application. That is the
motivation to make it a parameter of the interface.

The abstract type @code{ap_var_t} is equipped with a total ordering
function, a hashing function, a copy function, and a free function.
The parametrization of the interface is performed via a global
variable pointing to a @code{ap_var_operations_t} structure,
containing the above-mentione doperations on @code{ap_var_t} objects.
This means that this type should be fixed once, and that in a
multitreaded application all threads should share the same
@code{ap_var_t} type.

By default, @code{ap_var_t} is a C string (@code{char*}), and the
global variable @code{ap_var_operations} is properly initialized.

@deftp datatype ap_var_t
@example
typedef void* ap_var_t;
@end example
Datatype for ``variables''. It is assumed to be of size
@code{sizeof(void*)}.
@end deftp

@deftp datatype ap_var_operations_t
@example
typedef struct ap_var_operations_t @{
  int (*compare)(ap_var_t v1, ap_var_t v2); /* Total ordering function */
  int (*hash)(ap_var_t v);                  /* Hash function */
  ap_var_t (*copy)(ap_var_t var);           /* Duplication function */
  void (*free)(ap_var_t var);               /* Deallocation function */
  char* (*to_string)(ap_var_t var); /* Conversion to a dynamically allocated string,
				       which should be deallocated with free after use */
@} ap_var_operations_t;
@end example
Datatype for defining the operations on ``variables''.
@end deftp

@deftypevar ap_var_operations_t var_operations_default
Default manager, where @code{ap_var_t} is assumed to be @code{char*}.
@end deftypevar

@deftypevar ap_var_operations_t* var_operations
Global pointer to the manager in use, by default points to @code{ap_var_operations_default}.
@end deftypevar

@c ===================================================================
@node Environments, Linear expressions of level 1, Variables and related operations, Level 1 of the interface
@section Environments (@file{ap_environment.h})
@c ===================================================================

Environments bind variables (of level 1) to dimensions (of level 0).

@deftp datatype ap_environment_t
Internal datatype for environments.

For information, the definition is:
@example
typedef struct ap_environment_t @{
  ap_var_t* var_of_dim;
  /*
    Array of size intdim+realdim, indexed by dimensions.
    - It should not contain identical strings..
    - Slice [0..intdim-1] is lexicographically sorted,
      and denotes integer variables.
    - Slice [intdim..intdim+realdim-1] is lexicographically sorted,
      and denotes real variables.
    - The memory allocated for the variables are attached to the structure
      (they are freed when the structure is no longer in use)
  */
  size_t intdim; /* Number of integer variables */
  size_t realdim;/* Number of real variables */
  size_t count; /* For reference counting */
@} ap_environment_t;
@end example
@end deftp

@deftypefun void ap_environment_free (ap_environment_t* @var{env})
@deftypefunx ap_environment_t* ap_environment_copy (ap_environment_t* @var{env})
Respectively free and duplicate an environment.

(@code{copy} is cheap, as environments are managed with reference
counters).
@end deftypefun

@deftypefun void ap_environment_fdump (FILE* @var{stream}, ap_environment_t* @var{env})
Print an environment under the form:
@example
  environment: dim = (..,..), count = ..
  0: name0
  1: name1
  ...
@end example
@end deftypefun

@deftypefun ap_environment_t* ap_environment_alloc_empty ()
Build an empty environment.
@end deftypefun

@deftypefun ap_environment_t* ap_environment_alloc (ap_var_t* @var{var_of_intdim}, size_t @var{intdim}, ap_var_t* @var{var_of_realdim}, size_t @var{realdim})
Build an environment from an array of integer and an array of real variables.

@var{var_of_intdim} is an array of variables of size @var{intdim},
@var{var_of_realdim} is an array of variables of size
@var{realdim}. Pointers to arrays may be @code{NULL} if their size is
0.

Variables are duplicated in the result, so it is the responsability of
the user to free the variables he provides.

If some variables are duplicated, return @code{NULL}.
@end deftypefun

@deftypefun ap_environment_t* ap_environment_add (ap_environment_t* @var{env}, ap_var_t* @var{var_of_intdim}, size_t @var{intdim}, ap_var_t* @var{var_of_realdim}, size_t @var{realdim})
@deftypefunx ap_environment_t* ap_environment_remove (ap_environment_t* @var{env}, ap_var_t* @var{tvar}, size_t @var{size})
Resp. add or remove new variables to an existing environment, with
a functional semantics. Same conventions as for
@code{ap_environment_alloc} function apply. If the result is
non-sense (or in case of attempt to remove an unknwon variable),
return @code{NULL}.
@end deftypefun

@deftypefun ap_dim_t ap_environment_dim_of_var (ap_environment_t* @var{env}, ap_var_t @var{var})
Convert a variable in its corresponding dimension in the environment @var{env}. If @var{var} is unknown in @var{env}, return @code{AP_DIM_MAX}.
@end deftypefun
@deftypefun ap_dim_t ap_environment_var_of_dim (ap_environment_t* @var{env}, ap_dim_t @var{dim})
Return the variable associated to the dimension @var{dim} in the environment @var{env}. There is no bound check here.
@end deftypefun

The remaining functions are much less useful for normal user.

@deftypefun bool ap_environment_is_eq (ap_environment_t* @var{env1}, ap_environment_t* @var{env2})
@deftypefunx bool ap_environment_is_leq (ap_environment_t* @var{env1}, ap_environment_t* @var{env2})
Resp. test the equality and the inclusion of two environments.
@end deftypefun
@deftypefun int ap_environment_compare (ap_environment_t* @var{env1}, ap_environment_t* @var{env2})
Return:
@table @code
@item -2
if the environments are not compatible (a variable has a different
type in the 2 environments);
@item -1
if @var{env1} is a subset of (included in) @var{env2};
@item 0
if they are equal;
@item +1
if @var{env1} is a superset of @var{env2};
@item +2
otherwise: the least common environment exists and is a strict
superset of both environments.
@end table
@end deftypefun
@deftypefun int ap_environment_hash (ap_environment_t* @var{env})
Return an hash code for an environment.
@end deftypefun

@deftypefun ap_dimchange_t* ap_environment_dimchange (ap_environment_t* @var{env1}, ap_environment_t* @var{env})
Compute the transformation for converting from an environment
@var{env1} to a superenvironment @var{env}.  Return NULL if @var{env}
is not a superenvironment.
@end deftypefun

@deftypefun ap_dimchange2_t* ap_environment_dimchange2 (ap_environment_t* @var{env1}, ap_environment_t* @var{env2})
Compute the transformation for switching from an environment
@var{env1} to an @var{env2}, by first adding (some) variables of
@var{env2}, and then removing (some) variables of @var{env1}.  Return
NULL if @var{env1} and @var{env2} ar enot compatible environments.
@end deftypefun

@deftypefun ap_environment_t* ap_environment_lce (ap_environment_t* @var{env1}, ap_environment_t* @var{env2}, ap_dimchange_t** @var{dimchange1}, ap_dimchange_t** @var{dimchange2})
Least common environment to two enviroenments.
@itemize
@item
Assume @code{ap_environment_is_eq(env1,env2)==false}
@item
If environments are not compatible (a variable has different types in
the 2 environments), return NULL
@item
Compute also in @var{dimchange1} and @var{dimchange2} the conversion transformations to the lce.
@item
If no dimensions to add to @var{env1}, this implies that @var{env} is
actually @var{env1}. In this case,
@code{*dimchange1==NULL}. Otherwise, the function allocates the
@code{*dimchange1} with @code{ap_dimchange_alloc}.
@end itemize
@end deftypefun

@deftypefun ap_environment_t* ap_environment_lce_array (ap_environment_t** @var{tenv}, size_t @var{size}, ap_dimchange_t*** @var{ptdimchange})
Least common environment to an array of environments.
@itemize
@item
Assume the size @var{size} of the array @var{tenv} is at least one;
@item
If all input environments are the same, @code{*ptdimchange==NULL}.
Otherwise, compute in @code{*ptdimchange} the conversion permutations
@item
If no dimensions to add to @code{tenv[i]}, this implies that the
result is actually @code{tenv[i]}. In this case,
@code{(*ptdimchange)[i]==NULL}. Otherwise, the function allocates the
@code{(*ptdimchange)[i]} with @code{ap_dimchange_alloc}.
@end itemize
@end deftypefun

@deftypefun ap_environment_t* ap_environment_rename (ap_environment_t* @var{env}, ap_var_t* @var{tvar1}, ap_var_t* @var{tvar2}, size_t @var{size}, ap_dimperm_t* @var{perm})
Rename the variables in the environment.  @var{size} is the common
size of arrays @var{tvar1} and @var{tvar2}, and @var{perm} is a
result-parameter pointing to an @emph{existing but not initialized}
object of type @code{ap_dimperm_t}.

The function applies the variable substitution @code{tvar1[i]->tvar2[i]}
to the environment, and returns the resulting environment and the
allocated transformation permutation in @code{*perm}.

If the parameters are not valid, return @code{NULL} with
@code{perm->dim==NULL}.
@end deftypefun

@c ===================================================================
@node Linear expressions of level 1, Linear constraints of level 1, Environments, Level 1 of the interface
@section Linear expressions of level 1 (@file{ap_linexpr1.h})
@c ===================================================================

We manipulate here expressions of the form
@quotation
@math{a_0.x_0 + ... + a_n.x_n + b}
@end quotation
where the coefficients @math{a_0, ..., a_n, b} are of
@code{ap_coeff_t} type (either scalars or intervals) and the variables
@math{x_0, ... , x_n} are of type @code{ap_var_t}.

The semantics of linear expressions is exact, in the sense that the
arithmetic operations are interpreted in the real (or rational)
numbers. However, abstract domains are free to overapproximate this
exact semantics (this may occur when converting rational scalars to
@code{double} type for instance).

A special remark concerns integer variables. Abstract domains are
assumed to perform the operations involving linear expressions using a
real/rational semantics, and then possibly to reduce the result using
the knowledge that integer variables may only take integer
values.
@quotation
This semantics @emph{coincides} with the natural integer semantics of
expressions involving only integer variables @emph{only if} the
involved coefficients are all integers.
@end quotation
@quotation
A typical counter-example to this is an assignement @math{y := 1/3 x} where
@math{x} and @math{y} are integer variables. If this assignement is
applied to the @sc{Box} abstract domain value @math{x in [1;1]}, it
may lead to the bottom value, because one will first obtain @math{y in
[1/3;1/3]} by real/rational computations, and this may be reduced to
the empty interval because @math{y} is integer and the interval
contains no integer values.
@end quotation

If you need expressions with a less simple semantics (mixing integer,
real/rational and floating-point semantics with casts), you should use
tree expressions (@pxref{Tree expressions of level 1}).

@deftp datatype ap_linexpr1_t
(Internal) type of interval linear expressions.

Linear expressions of level 1 are created as objects of type
@code{ap_linexpr1_t}, not as pointers of type @code{ap_linexpr1_t*}.

For information:
@example
typedef struct ap_linexpr1_t @{
  ap_linexpr0_t* linexpr0;
  ap_environment_t* env;
@} ap_linexpr1_t;
@end example
@end deftp

@menu
* Allocating linear expressions of level 1::
* Tests on linear expressions of level 1::
* Access to linear expressions of level 1::
* Change of dimensions and permutations of linear expressions of level 1::
@end menu

@c -------------------------------------------------------------------
@node Allocating linear expressions of level 1, Tests on linear expressions of level 1, Linear expressions of level 1, Linear expressions of level 1
@subsection Allocating linear expressions of level 1
@c -------------------------------------------------------------------

@deftypefun ap_linexpr1_t ap_linexpr1_make (ap_environment_t* @var{env}, ap_linexpr_discr_t @var{lin_discr}, size_t @var{size})
Build a linear expressions on the environment @var{env}, with by
default coefficients of type SCALAR and DOUBLE.

If @var{lin_discr} selects a dense representation, the size of the
expression is the size of the environment. Otherwise, the initial
size is given by @var{size} and the expression may be resized lazily.
@end deftypefun

@deftypefun void ap_linexpr1_minimize (ap_linexpr1_t* @var{expr})
Reduce the coefficients (transform intervals into scalars when
possible).  In case of sparse representation, also remove zero
coefficients.
@end deftypefun

@deftypefun ap_linexpr1_t ap_linexpr1_copy (ap_linexpr1_t* @var{expr})
Duplication.
@end deftypefun

@deftypefun void ap_linexpr1_clear (ap_linexpr1_t @var{expr})
Clear the linear expression.
@end deftypefun

@deftypefun void ap_linexpr1_fprint (FILE* @var{stream}, ap_linexpr1_t* @var{expr})
Print the linear expression on stream @var{stream}.
@end deftypefun

@c -------------------------------------------------------------------
@node Tests on linear expressions of level 1, Access to linear expressions of level 1, Allocating linear expressions of level 1, Linear expressions of level 1
@subsection Tests on linear expressions of level 1
@c -------------------------------------------------------------------

@deftypefun bool ap_linexpr1_is_integer (ap_linexpr1_t* @var{expr})
Does the expression depends only on integer variables ?
@end deftypefun

@deftypefun bool ap_linexpr1_is_real (ap_linexpr1_t* @var{expr})
Does the expression depends only on real variables ?
@end deftypefun

@deftypefun bool ap_linexpr1_is_linear (ap_linexpr1_t* @var{expr})
Return true iff all involved coefficients are scalars.
@end deftypefun

@deftypefun bool ap_linexpr1_is_quasilinear (ap_linexpr1_t* @var{expr})
Return true iff all involved coefficients but the constant are scalars.
@end deftypefun

@c -------------------------------------------------------------------
@node Access to linear expressions of level 1, Change of dimensions and permutations of linear expressions of level 1, Tests on linear expressions of level 1, Linear expressions of level 1
@subsection Access to linear expressions of level 1
@c -------------------------------------------------------------------

@deftypefun ap_environment_t* ap_linexpr1_envref (ap_linexpr1_t* @var{expr})
Get a reference to the underlying environment. Do not free it.
@end deftypefun
@deftypefun size_t ap_linexpr1_linexpr0ref (ap_linexpr1_t* @var{expr})
Get a reference to the underlying linear expression of level 0. Do not
free it.
@end deftypefun

@c -------------------------------------------------------------------
@subsubsection Getting references

@deftypefun ap_coefft* ap_linexpr1_cstref (ap_linexpr1_t* @var{e})
Get a reference to the constant. Do not free it.
@end deftypefun

@deftypefun ap_coefft* ap_linexpr1_coeffref (ap_linexpr1_t* @var{e}, ap_var_t @var{var})
Get a reference to the coefficient associated to the variable
@var{var} in expression @var{e}.

Do not free it. In case of sparse representation, possibly induce the
addition of a new linear term.

Return NULL if @var{var} is unknown in the environment of @var{e}.
@end deftypefun

@c -------------------------------------------------------------------
@subsubsection Getting values

@deftypefun void ap_linexpr1_get_cst (ap_coefft* @var{coeff}, ap_linexpr1_t* @var{e})
Assign to @var{coeff} the constant coefficient of @var{e}.
@end deftypefun

@deftypefun bool ap_linexpr1_get_coeff (ap_coefft* @var{coeff}, ap_linexpr1_t* @var{e}, ap_var_t @var{var})
Assign to @var{coeff} the coefficient of variable @var{var} in the expression @var{e}.

Return true in case @code{ap_linexpr1_coeffref(e,dim)} returns NULL.
@end deftypefun

@defmac ap_linexpr1_ForeachLinterm (ap_linexpr1_t* @var{e}, size_t @var{i}, ap_ap_var_t @var{var}, ap_coeff_t* @var{coeff})
Iterator on the coefficients associated to variables.

@code{ap_linexpr1_ForeachLinterm(E,I,VAR,COEFF)@{ body @}}
executes the body for each pair (@var{coeff},@var{var}) in the
expression @var{e}. @var{coeff} is a reference to the coefficient
associated to variable @var{var} in @var{e}. @var{i} is an
auxiliary variable used internally by the macro.
@end defmac

@c -------------------------------------------------------------------
@subsubsection Assigning values with a list of arguments

@deftypefun bool ap_linexpr1_set_list (ap_linexpr1_t* @var{e}, ...)
This function assign the linear expression @var{e} from a list of tags
of type @code{ap_coefftag_t}, each followed by a number of arguments
as specified in the definition of the type @code{ap_coefftag_t}
(@pxref{Access to linear expressions of level 0}). The list should end
with the tag @code{AP_COEFF_END}. The only difference with level 0 is that variables replace dimensions in the list.

Return @code{true} in case @code{ap_linexpr1_coeffref (e,dim)}
returns NULL for one of the variables involved.

Here is a typical example, in the case where @code{ap_var_t} is actually @code{char*} (the default):
@example
ap_linexpr1_set_list(e,
		     AP_COEFF_S_INT, 3, "x",
		     AP_COEFF_S_FRAC, 3,2, "y",
		     AP_COEFF_S_DOUBLE, 4.1, "z",
		     AP_CST_I_DOUBLE, -2.4, 3.6,
		     AP_END); /* Do not forget the last tatg ! */
@end example
which transforms an null expression into @code{3 x + 3/2 y + 4.1 z + [-2.4,3.6]}
and is equivalent to:
@example
ap_linexpr1_set_coeff_scalar_int(e, "x", 3);
ap_linexpr1_set_coeff_scalar_frac(e, "y", 3,2);
ap_linexpr1_set_coeff_scalar_double(e, "z", 4.1);
ap_linexpr1_set_cst_interval_double(e, -2.4, 3.6);
@end example
@end deftypefun

@c -------------------------------------------------------------------
@subsubsection Assigning values

@deftypefun void ap_linexpr1_set_cst (ap_linexpr1_t* @var{e}, ap_coefft* @var{coeff})
@deftypefunx void ap_linexpr1_set_cst_scalar (ap_linexpr1_t* @var{e}, ap_scalar_t* @var{scalar})
@deftypefunx void ap_linexpr1_set_cst_scalar_int (ap_linexpr1_t* @var{e}, int @var{num})
@deftypefunx void ap_linexpr1_set_cst_scalar_frac (ap_linexpr1_t* @var{e}, int @var{num}, unsigned int @var{den})
@deftypefunx void ap_linexpr1_set_cst_scalar_double (ap_linexpr1_t* @var{e}, double @var{num})
@deftypefunx void ap_linexpr1_set_cst_interval (ap_linexpr1_t* @var{e}, ap_interval_t* @var{itv})
@deftypefunx void ap_linexpr1_set_cst_interval_scalar (ap_linexpr1_t* @var{e}, ap_scalar_t* @var{inf}, ap_scalar_t* @var{sup})
@deftypefunx void ap_linexpr1_set_cst_interval_int (ap_linexpr1_t* @var{e}, int @var{inf}, int @var{sup})
@deftypefunx void ap_linexpr1_set_cst_interval_frac (ap_linexpr1_t* @var{e}, int @var{numinf}, unsigned int @var{deninf}, int @var{numsup}, unsigned int @var{densup})
@deftypefunx void ap_linexpr1_set_cst_interval_double (ap_linexpr1_t* @var{e}, double @var{inf}, double @var{sup})
Set the constant coefficient of expression @var{e}.
@end deftypefun

@deftypefun bool ap_linexpr1_set_coeff (ap_linexpr1_t* @var{e}, ap_var_t @var{var}, ap_coefft* @var{coeff})
@deftypefunx bool ap_linexpr1_set_coeff_scalar (ap_linexpr1_t* @var{e}, ap_var_t @var{var}, ap_scalar_t* @var{scalar})
@deftypefunx bool ap_linexpr1_set_coeff_scalar_int (ap_linexpr1_t* @var{e}, ap_var_t @var{var}, int @var{num})
@deftypefunx bool ap_linexpr1_set_coeff_scalar_frac (ap_linexpr1_t* @var{e}, ap_var_t @var{var}, int @var{num}, unsigned int @var{den})
@deftypefunx bool ap_linexpr1_set_coeff_scalar_double (ap_linexpr1_t* @var{e}, ap_var_t @var{var}, double @var{num})
@deftypefunx bool ap_linexpr1_set_coeff_interval (ap_linexpr1_t* @var{e}, ap_var_t @var{var}, ap_interval_t* @var{itv})
@deftypefunx bool ap_linexpr1_set_coeff_interval_scalar (ap_linexpr1_t* @var{e}, ap_var_t @var{var}, ap_scalar_t* @var{inf}, ap_scalar_t* @var{sup})
@deftypefunx bool ap_linexpr1_set_coeff_interval_int (ap_linexpr1_t* @var{e}, ap_var_t @var{var}, int @var{inf}, int @var{sup})
@deftypefunx bool ap_linexpr1_set_coeff_interval_frac (ap_linexpr1_t* @var{e}, ap_var_t @var{var},int @var{numinf}, unsigned int @var{deninf}, int @var{numsup}, unsigned int @var{densup})
@deftypefunx void ap_linexpr1_set_coeff_interval_double (ap_linexpr1_t* @var{e}, ap_var_t @var{var}, double @var{inf}, double @var{sup})
Set the coefficient of the variable @var{var} of expression @var{e}.

Return @code{true} in case @code{ap_linexpr1_coeffref(e,var)} returns NULL.
@end deftypefun

@c -------------------------------------------------------------------
@node Change of dimensions and permutations of linear expressions of level 1,  , Access to linear expressions of level 1, Linear expressions of level 1
@subsection Change of dimensions and permutations of linear expressions of level 1
@c -------------------------------------------------------------------

@deftypefun bool ap_linexpr1_extend_environment (ap_linexpr1_t* @var{nexpr}, ap_linexpr1_t* @var{expr}, ap_environment_t* @var{nenv})
@deftypefunx bool ap_linexpr1_extend_environment_with (ap_linexpr1_t* @var{expr}, ap_environment_t* @var{nenv})
Change the current environment of the expression @var{expr} with a
super-environment @var{nenv}.  Return @code{true} if @var{nenv} is not
a superenvironment.

The first version store the result in the uninitialized @code{*nexpr}, the second one updates in-place its argument.
@end deftypefun

@c ===================================================================
@node Linear constraints of level 1, Generators of level 1, Linear expressions of level 1, Level 1 of the interface
@section Linear constraints of level 1 (@file{ap_lincons1.h})
@c ===================================================================

@deftp datatype ap_lincons1_t
Datatype for constraints.

For information:
@example
typedef struct ap_lincons1_t @{
  ap_lincons0_t lincons0;
  ap_environment_t* env;
@} ap_lincons1_t;
@end example

Constraints are meant to be manipulated freely via their
components. Creating the constraint @code{[1,2]x + 5/2 y >=0} and then
freeing it can be done with
@example
ap_lincons1_t cons = ap_lincons1_make(AP_CONS_SUPEQ,
				      ap_linexpr1_alloc(env,AP_LINEXPR_SPARSE,2),
                                      NULL);
ap_lincons1_set_list(&cons,
		     AP_COEFF_I_INT, 1,2, "x",
		     AP_COEFF_S_FRAC, 5,2, "y",
		     AP_END);
ap_lincons1_clear(&cons);
@end example
@end deftp


@deftp datatype ap_lincons1_array_t
@example
typedef struct ap_lincons1_array_t @{
  ap_lincons0_array_t lincons0_array;
  ap_environment_t* env;
@} ap_lincons1_array_t;
@end example
Datatype for arrays of constraints.

Arrays at level 1 cannot be accessed directly, for example by writing
@code{array->p[i]}, but should instead be accessed with functions
@code{ap_lincons1_array_get} and @code{ap_lincons1_array_set}.
@end deftp

@menu
* Allocating linear constraints of level 1::
* Tests on linear constraints of level 1::
* Access to linear constraints of level 1::
* Change of dimensions and permutations of linear constraints of level 1::
* Arrays of linear constraints of level 1::
@end menu

@c -------------------------------------------------------------------
@node Allocating linear constraints of level 1, Tests on linear constraints of level 1, Linear constraints of level 1, Linear constraints of level 1
@subsection Allocating linear constraints of level 1
@c -------------------------------------------------------------------

@deftypefun ap_lincons1_t ap_lincons1_make (ap_constyp_t @var{constyp}, ap_linexpr1_t* @var{linexpr}, ap_scalar_t* mod)
Create a constraint of type @var{constyp} with the expression
@var{linexpr}, and the modulo @var{mod} in case of a congruence
constraint (@code{constyp==AP_CONS_EQMOD}).

The expression is not duplicated, just pointed to, so it becomes
managed via the constraint.
@end deftypefun

@deftypefun ap_lincons1_t ap_lincons1_make_unsat (ap_environment_t* @var{env})
Create the constraint @code{-1>=0}.
@end deftypefun

@deftypefun ap_lincons1_t ap_lincons1_copy (ap_lincons1_t* @var{cons})
Duplication
@end deftypefun

@deftypefun void ap_lincons1_clear (ap_lincons1_t* @var{cons})
Clear the constraint and set pointers to NULL.
@end deftypefun

@deftypefun void ap_lincons1_fprint (FILE* @var{stream}, ap_lincons1_t* @var{cons});
Print the linear constraint on stream @var{stream}.
@end deftypefun

@c -------------------------------------------------------------------
@node Tests on linear constraints of level 1, Access to linear constraints of level 1, Allocating linear constraints of level 1, Linear constraints of level 1
@subsection Tests on linear constraints of level 1
@c -------------------------------------------------------------------

@deftypefun bool ap_lincons1_is_unsat (ap_lincons1_t* @var{cons})
Return @code{true} if the constraint is not satisfiable (@code{b>=0}
or @code{[a,b]>=0} with b negative).
@end deftypefun

@c -------------------------------------------------------------------
@node Access to linear constraints of level 1, Change of dimensions and permutations of linear constraints of level 1, Tests on linear constraints of level 1, Linear constraints of level 1
@subsection Access to linear constraints of level 1
@c -------------------------------------------------------------------

@deftypefun ap_environment_t* ap_lincons1_envref (ap_lincons1_t* @var{cons})
Get a reference to the environment. Do not free it.
@end deftypefun

@deftypefun ap_constyp_t* ap_lincons1_constypref (ap_lincons1_t* @var{cons})
Get a reference to the type of constraint. You may use the reference
to modify the constraint type.
@end deftypefun

@deftypefun ap_linexpr1_t ap_lincons1_linexpr1ref (ap_lincons1_t* @var{cons})
Get a reference to the underlying expression of the constraint.  Do
not free it: nothing is duplicated.  Modifying the argument or the
result is equivalent, except for change of dimensions/environment.
@end deftypefun

@deftypefun void ap_lincons1_get_cst (ap_coeff_t* @var{coeff}, ap_lincons1_t* @var{cons})
@deftypefunx void ap_lincons1_set_cst (ap_lincons1_t* @var{cons}, ap_coeff_t* cst)
@deftypefunx bool ap_lincons1_get_coeff (ap_coeff_t* @var{coeff}, ap_lincons1_t* cons, ap_var_t @var{var})
@deftypefunx bool ap_lincons1_set_coeff (ap_lincons1_t* @var{cons}, ap_var_t @var{var}, ap_coeff_t* @var{coeff})
@deftypefunx bool ap_lincons1_set_list (ap_lincons1_t* @var{cons}, ...)
@deftypefunx ap_coeff_t* ap_lincons1_cstref (ap_lincons1_t* @var{cons})
@deftypefunx ap_coeff_t* ap_lincons1_coeffref (ap_lincons1_t* @var{cons}, ap_var_t @var{var})
Identical to corresponding @code{ap_linexpr1_XXX} functions
(@pxref{Access to linear expressions of level 1}).
@end deftypefun

@deftypefun ap_lincons0_t* ap_lincons1_lincons0ref (ap_lincons1_t* @var{cons})
Return underlying constraint of level 0.
Do not free it: nothing is duplicated.
Modifying the argument or the result is equivalent, except for
change of dimensions/envionment.
@end deftypefun

@c -------------------------------------------------------------------
@node Change of dimensions and permutations of linear constraints of level 1, Arrays of linear constraints of level 1, Access to linear constraints of level 1, Linear constraints of level 1
@subsection Change of dimensions and permutations of linear constraints of level 1
@c -------------------------------------------------------------------

@deftypefun bool ap_lincons1_extend_environment (ap_lincons1_t* @var{ncons}, ap_lincons1_t* @var{cons}, ap_environment_t* @var{nenv})
@deftypefunx bool ap_lincons1_extend_environment_with (ap_lincons1_t* @var{cons}, ap_environment_t* @var{nenv})
Identical to corresponding @code{ap_linexpr1_XXX} functions (@pxref{Change of dimensions and permutations of linear expressions of level 1}).
@end deftypefun

@c -------------------------------------------------------------------
@node Arrays of linear constraints of level 1,  , Change of dimensions and permutations of linear constraints of level 1, Linear constraints of level 1
@subsection Arrays of linear constraints of level 1
@c -------------------------------------------------------------------

@deftypefun ap_lincons1_array_t ap_lincons1_array_make (ap_environment_t* @var{env}, size_t @var{size})
Allocate an array of constraints of size @var{size}, defined on the
environment @var{env}.

The constraints are initialized with NULL pointers for underlying
expressions.
@end deftypefun

@deftypefun void ap_lincons1_array_clear (ap_lincons1_array_t* @var{array})
Clear the constraints of the array, and then the array itself.
@end deftypefun

@deftypefun void ap_lincons1_array_fprint (FILE* @var{stream}, ap_lincons1_array_t* @var{array})
Print the array on the stream.
@end deftypefun

@deftypefun size_t ap_lincons1_array_size (ap_lincons1_array_t* @var{array})
Return the size of the array.
@end deftypefun

@deftypefun ap_environment_t* ap_lincons1_array_envref (ap_lincons1_array_t* @var{array})
Get a reference to the environment. Do not free it.
@end deftypefun

@deftypefun ap_lincons1_t ap_lincons1_array_get (ap_lincons1_array_t* @var{array}, size_t @var{index})
Return the linear constraint of the given index. Nothing is duplicated,
and the result should never be cleared.  Modifying the argument or the
result is equivalent, except for change of environments
@end deftypefun

@deftypefun bool ap_lincons1_array_set (ap_lincons1_array_t* @var{array}, size_t @var{index}, ap_lincons1_t* @var{cons})
Fill the index of the array with the constraint.  Assumes
@code{ap_environment_is_eq(array->env,cons->env)}. Nothing is
duplicated.  The argument should never be cleared (its environment is
dereferenced).  If a constraint was already stored, it is first
cleared.  Return true iff problem (index or
@code{array->env!=cons->env})
@end deftypefun

@deftypefun void ap_lincons1_array_clear_index (ap_lincons1_array_t* @var{array}, size_t @var{index})
Clear the constraint at index index.
@end deftypefun

@deftypefun bool ap_lincons1_array_extend_environment_with (ap_lincons1_array_t* @var{array}, ap_environment_t* @var{nenv})
@deftypefunx bool ap_lincons1_array_extend_environment (ap_lincons1_array_t* narray, ap_lincons1_array_t* @var{array}, ap_environment_t* @var{nenv})
Identical to corresponding @code{ap_linexpr1_XXX} functions (@pxref{Change of dimensions and permutations of linear expressions of level 1}).
@end deftypefun

@c ===================================================================
@node Generators of level 1, Tree expressions of level 1, Linear constraints of level 1, Level 1 of the interface
@section generators of level 1 (@file{ap_generator1.h})
@c ===================================================================

@deftp datatype ap_generator1_t
Datatype for generators.

For information:
@example
typedef struct ap_generator1_t @{
  ap_generator0_t generator0;
  ap_environment_t* env;
@} ap_generator1_t;
@end example

Generators are meant to be manipulated freely via their components. Creating the ray generator @code{x+2/3y} and then freeing it can be done with
@example
ap_generator1_t gen = ap_generator1_make(AP_GEN_RAY,
				      ap_linexpr1_alloc(env,AP_LINEXPR_SPARSE,2));
ap_generator1_set_list(&gen,
		     AP_COEFF_S_INT, 1, "x",
		     AP_COEFF_S_FRAC, 2,3, "y",
		     AP_END);
ap_generator1_clear(&gen);
@end example
@end deftp


@deftp datatype ap_generator1_array_t
@example
typedef struct ap_generator1_array_t @{
  ap_generator0_array_t generator0_array;
  ap_environment_t* env;
@} ap_generator1_array_t;
@end example
Datatype for arrays of generators.

Arrays at level 1 cannot be accessed directly, for example by writing
@code{array->p[i]}, but should instead be accessed with functions
@code{ap_generator1_array_get} and @code{ap_generator1_array_set}.
@end deftp

@menu
* Allocating generators of level 1::
* Access to generators of level 1::
* Change of dimensions and permutations of generators of level 1::
* Arrays of generators of level 1::
@end menu

@c -------------------------------------------------------------------
@node Allocating generators of level 1, Access to generators of level 1, Generators of level 1, Generators of level 1
@subsection Allocating generators of level 1
@c -------------------------------------------------------------------

@deftypefun ap_generator1_t ap_generator1_make (ap_gentyp_t @var{gentyp}, ap_linexpr1_t* @var{linexpr})
Create a generator of type @var{gentyp} with the expression @var{linexpr}.

The expression is not duplicated, just pointed to, so it becomes
managed via the generator.
@end deftypefun

@deftypefun ap_generator1_t ap_generator1_copy (ap_generator1_t* @var{gen})
Duplication
@end deftypefun

@deftypefun void ap_generator1_clear (ap_generator1_t* @var{gen})
Clear the generator and set pointers to NULL.
@end deftypefun

@deftypefun void ap_generator1_fprint (FILE* @var{stream}, ap_generator1_t* @var{gen});
Print the linear generator on stream @var{stream}.
@end deftypefun

@c -------------------------------------------------------------------
@node Access to generators of level 1, Change of dimensions and permutations of generators of level 1, Allocating generators of level 1, Generators of level 1
@subsection Access to generators of level 1
@c -------------------------------------------------------------------

@deftypefun ap_environment_t* ap_generator1_envref (ap_generator1_t* @var{gen})
Get a reference to the environment. Do not free it.
@end deftypefun

@deftypefun ap_gentyp_t* ap_generator1_gentypref (ap_generator1_t* @var{gen})
Get a reference to the type of generator. You may use the reference
to modify the generator type.
@end deftypefun

@deftypefun ap_linexpr1_t ap_generator1_linexpr1ref (ap_generator1_t* @var{gen})
Get a reference to the underlying expression of the generator.  Do
not free it: nothing is duplicated.  Modifying the argument or the
result is equivalent, except for change of dimensions/environment.
@end deftypefun

@deftypefun void ap_generator1_get_cst (ap_coeff_t* @var{coeff}, ap_generator1_t* @var{gen})
@deftypefunx void ap_generator1_set_cst (ap_generator1_t* @var{gen}, ap_coeff_t* cst)
@deftypefunx bool ap_generator1_get_coeff (ap_coeff_t* @var{coeff}, ap_generator1_t* gen, ap_var_t @var{var})
@deftypefunx bool ap_generator1_set_coeff (ap_generator1_t* @var{gen}, ap_var_t @var{var}, ap_coeff_t* @var{coeff})
@deftypefunx bool ap_generator1_set_list (ap_generator1_t* @var{gen}, ...)
@deftypefunx ap_coeff_t* ap_generator1_cstref (ap_generator1_t* @var{gen})
@deftypefunx ap_coeff_t* ap_generator1_coeffref (ap_generator1_t* @var{gen}, ap_var_t @var{var})
Identical to corresponding @code{ap_linexpr1_XXX} functions
(@pxref{Access to linear expressions of level 1}).
@end deftypefun

@deftypefun ap_generator0_t* ap_generator1_generator0ref (ap_generator1_t* @var{gen})
Return underlying generator of level 0.
Do not free it: nothing is duplicated.
Modifying the argument or the result is equivalent, except for
change of dimensions/envionment.
@end deftypefun

@c -------------------------------------------------------------------
@node Change of dimensions and permutations of generators of level 1, Arrays of generators of level 1, Access to generators of level 1, Generators of level 1
@subsection Change of dimensions and permutations of generators of level 1
@c -------------------------------------------------------------------

@deftypefun bool ap_generator1_extend_environment (ap_generator1_t* @var{ngen}, ap_generator1_t* @var{gen}, ap_environment_t* @var{nenv})
@deftypefunx bool ap_generator1_extend_environment_with (ap_generator1_t* @var{gen}, ap_environment_t* @var{nenv})
Identical to corresponding @code{ap_linexpr1_XXX} functions
(@pxref{Change of dimensions and permutations of linear expressions of level 1}).
@end deftypefun

@c -------------------------------------------------------------------
@node Arrays of generators of level 1,  , Change of dimensions and permutations of generators of level 1, Generators of level 1
@subsection Arrays of generators of level 1
@c -------------------------------------------------------------------

@deftypefun ap_generator1_array_t ap_generator1_array_make (ap_environment_t* @var{env}, size_t @var{size})
Allocate an array of generators of size @var{size}, defined on the
environment @var{env}.

The generators are initialized with NULL pointers for underlying
expressions.
@end deftypefun

@deftypefun void ap_generator1_array_clear (ap_generator1_array_t* @var{array})
Clear the generators of the array, and then the array itself.
@end deftypefun

@deftypefun void ap_generator1_array_fprint (FILE* @var{stream}, ap_generator1_array_t* @var{array})
Print the array on the stream.
@end deftypefun

@deftypefun size_t ap_generator1_array_size (ap_generator1_array_t* @var{array})
Return the size of the array.
@end deftypefun

@deftypefun ap_environment_t* ap_generator1_array_envref (ap_generator1_array_t* @var{array})
Get a reference to the environment. Do not free it.
@end deftypefun

@deftypefun ap_generator1_t ap_generator1_array_get (ap_generator1_array_t* @var{array}, size_t @var{index})
Return the linear generator of the given index Nothing is duplicated,
and the result should never be cleared.  Modifying the argument or the
result is equivalent, except for change of environments
@end deftypefun

@deftypefun bool ap_generator1_array_set (ap_generator1_array_t* @var{array}, size_t @var{index}, ap_generator1_t* @var{gen})
Fill the index of the array with the generator.  Assumes
@code{array->env==gen->env}.  Nothing is duplicated.  The argument should
never be cleared. (its environment is dereferenced).  If a generator
was already stored, it is first cleared.  Return true iff problem
(index or @code{array->env!=gen->env})
@end deftypefun

@deftypefun void ap_generator1_array_clear_index (ap_generator1_array_t* @var{array}, size_t @var{index})
Clear the generator at index index.
@end deftypefun

@deftypefun bool ap_generator1_array_extend_environment_with (ap_generator1_array_t* @var{array}, ap_environment_t* @var{nenv})
@deftypefunx bool ap_generator1_array_extend_environment (ap_generator1_array_t* narray, ap_generator1_array_t* @var{array}, ap_environment_t* @var{nenv})
Identical to corresponding @code{ap_linexpr1_XXX} functions (@pxref{Change of dimensions and permutations of linear expressions of level 1}).
@end deftypefun

@c ===================================================================
@node Tree expressions of level 1, Tree constraints of level 1, Generators of level 1, Level 1 of the interface
@section Tree expressions of level 1 (@file{ap_texpr1.h})
@c ===================================================================

We manipulate here general expressions described by the grammar
@quotation
@math{expr ::= cst | var | unop e | e1 binop e2}
@end quotation
Such tree expressions generalize linear expressions(@pxref{Linear
expressions of level 1}) in two ways:
@itemize
@item Non-linear operations are possible (multiplication, division, casts, ...)
@item
Semantics of operators is no longer restricted to real/rational
semantics. Each operation is parameterized by two parameters:
@itemize
@item
a rounding type parameter,
which indicates the destination type of the operation, and influences
how the rounding is performed;
@item
a rounding direction parameter, which defines the rounding mode.
@end itemize
@end itemize

@menu
* Datatypes for tree expressions of level 1::
* Constructors/Destructors for tree expressions of level 1::
* Tests on tree expressions of level 1::
* Operations on tree expressions of level 1::
@end menu

@c -------------------------------------------------------------------
@node Datatypes for tree expressions of level 1, Constructors/Destructors for tree expressions of level 1, Tree expressions of level 1, Tree expressions of level 1
@subsection Datatypes for tree expressions of level 1
@c -------------------------------------------------------------------

@deftp datatype ap_texpr1_t
Type of tree expressions.

Tree expressions of level 1 are created as objects of type
@code{ap_texpr1_t*}. They are manipulated in a functional way (except
a few operations), unlike linear expressions on which most operations
acts by side-effects.
@end deftp

@deftp datatype ap_texpr_op_t
Operators (actually defined in @file{ap_texpr0.h})
@example
typedef enum ap_texpr_op_t @{
  /* Binary operators */
  AP_TEXPR_ADD, AP_TEXPR_SUB, AP_TEXPR_MUL, AP_TEXPR_DIV,
  AP_TEXPR_MOD,  /* either integer or real, no rounding */
  /* Unary operators */
  AP_TEXPR_NEG   /* no rounding */,
  AP_TEXPR_CAST, AP_TEXPR_SQRT,
@} ap_texpr_op_t;
@end example
@end deftp

@deftp datatype ap_texpr_rtype_t
Destination type of the operation for rounding (actually defined in @file{ap_texpr0.h})
@example
typedef enum ap_texpr_rtype_t @{
  AP_RTYPE_REAL,     /* real (no rounding) */
  AP_RTYPE_INT,      /* integer */
  AP_RTYPE_SINGLE,   /* IEEE 754 32-bit single precision, e.g.: C's float */
  AP_RTYPE_DOUBLE,   /* IEEE 754 64-bit double precision, e.g.: C's double */
  AP_RTYPE_EXTENDED, /* non-standard 80-bit double extended, e.g.: Intel's long double */
  AP_RTYPE_QUAD,     /* non-standard 128-bit quadruple precision, e.g.: Motorola's long double */
@} ap_texpr_rtype_t;
@end example
@end deftp

@deftp datatype ap_texpr_rdir_t
Rounding mode (actually defined in @file{ap_texpr0.h})
@example
typedef enum ap_texpr_rdir_t @{
  AP_RDIR_NEAREST /* Nearest */
  AP_RDIR_ZERO    /* Zero (truncation for integers) */
  AP_RDIR_UP      /* + Infinity */
  AP_RDIR_DOWN    /* - Infinity */
  AP_RDIR_RND,    /* All possible mode, non deterministically */
  AP_RDIR_SIZE    /* Not to be used ! */
@} ap_texpr_rdir_t;
@end example
@end deftp

@c -------------------------------------------------------------------
@node Constructors/Destructors for tree expressions of level 1, Tests on tree expressions of level 1, Datatypes for tree expressions of level 1, Tree expressions of level 1
@subsection Constructors/Destructors for tree expressions of level 1
@c -------------------------------------------------------------------

Parameters of constructors are not memory-managed by the constructed
expression, with the important exception of expressions parameters
(type @code{ap_texpr1.h}) are, which means that they should not be
freed afterwards.

@deftypefun  ap_texpr1_t* ap_texpr1_cst                 (ap_environment_t* @var{env}, ap_coeff_t* @var{coeff})
@deftypefunx ap_texpr1_t* ap_texpr1_cst_scalar          (ap_environment_t* @var{env}, ap_scalar_t* @var{scalar})
@deftypefunx ap_texpr1_t* ap_texpr1_cst_scalar_mpq      (ap_environment_t* @var{env}, mpq_t @var{mpq})
@deftypefunx ap_texpr1_t* ap_texpr1_cst_scalar_int      (ap_environment_t* @var{env}, long int @var{num})
@deftypefunx ap_texpr1_t* ap_texpr1_cst_scalar_frac     (ap_environment_t* @var{env}, long int @var{num}, unsigned long int @var{den})
@deftypefunx ap_texpr1_t* ap_texpr1_cst_scalar_double   (ap_environment_t* @var{env}, double @var{num})
@deftypefunx ap_texpr1_t* ap_texpr1_cst_interval        (ap_environment_t* @var{env}, ap_interval_t* @var{itv})
@deftypefunx ap_texpr1_t* ap_texpr1_cst_interval_scalar (ap_environment_t* @var{env}, ap_scalar_t* @var{inf}, ap_scalar_t* @var{sup})
@deftypefunx ap_texpr1_t* ap_texpr1_cst_interval_mpq    (ap_environment_t* @var{env}, mpq_t @var{inf}, mpq_t @var{sup})
@deftypefunx ap_texpr1_t* ap_texpr1_cst_interval_int    (ap_environment_t* @var{env}, long int @var{inf}, long int @var{sup})
@deftypefunx ap_texpr1_t* ap_texpr1_cst_interval_frac   (ap_environment_t* @var{env}, long int @var{numinf}, unsigned long int @var{deninf}, long int @var{numsup}, unsigned long int @var{densup})
@deftypefunx ap_texpr1_t* ap_texpr1_cst_interval_double (ap_environment_t* @var{env}, double @var{inf}, double @var{sup})
@deftypefunx ap_texpr1_t* ap_texpr1_cst_top             (ap_environment_t* @var{env})
Create a constant expression, on the environment @var{env}.
@end deftypefun

@deftypefun ap_texpr1_t* ap_texpr1_var (ap_environment_t* @var{env}, ap_var_t @var{var})
Create a variable expression. Return @code{NULL} in the case @var{var}
is unknown in @var{env}.
@end deftypefun

@deftypefun ap_texpr1_t* ap_texpr1_unop (ap_texpr_op_t @var{op}, ap_texpr1_t* @var{opA}, ap_texpr_rtype_t @var{type}, ap_texpr_rdir_t @var{dir})
@deftypefunx ap_texpr1_t* ap_texpr1_binop (ap_texpr_op_t @var{op}, ap_texpr1_t* @var{opA}, ap_texpr1_t* @var{opB}, ap_texpr_rtype_t @var{type}, ap_texpr_rdir_t @var{dir})
Create an expression from an operator and expression operand(s). Be
aware that @var{opA} and @var{opB} are memroy-managed by the result
upon return.
@end deftypefun

@deftypefun ap_texpr1_t* ap_texpr1_copy (ap_texpr1_t* @var{expr})
(Deep) copy of a tree expression.
@end deftypefun

@deftypefun ap_texpr1_t* ap_texpr1_from_linexpr1 (ap_linexpr1_t* @var{linexpr})
Creation from a linear expression.
@end deftypefun

@deftypefun void ap_texpr1_free (ap_texpr1_t* @var{expr})
Free (recursively) a tree expression.
@end deftypefun

@deftypefun void ap_texpr1_fprint (FILE* @var{stream}, ap_texpr1_t* @var{e})
@deftypefunx void ap_texpr1_print (ap_texpr1_t* @var{e})
Print the expression
@end deftypefun

@c -------------------------------------------------------------------
@node Tests on tree expressions of level 1, Operations on tree expressions of level 1, Constructors/Destructors for tree expressions of level 1, Tree expressions of level 1
@subsection Tests on tree expressions of level 1
@c -------------------------------------------------------------------

@deftypefun bool ap_texpr1_equal (ap_texpr1_t* @var{e1}, ap_texpr1_t* @var{e2})
Structural (recursive) equality
@end deftypefun

@deftypefun bool ap_texpr1_has_var (ap_texpr1_t* @var{e}, ap_var_t @var{var})
Return true if variable @var{var} appears in the expression.
@end deftypefun

The next functions classifies tree expressions.
@deftypefun bool ap_texpr1_is_interval_cst (ap_texpr1_t* @var{e})
No variable, only constant leaves
@end deftypefun

@deftypefun bool ap_texpr1_is_interval_linear (ap_texpr1_t* @var{e})
Linear with possibly interval coefficients, no rounding
@end deftypefun

@deftypefun bool ap_texpr1_is_interval_polynomial (ap_texpr1_t* @var{e})
Polynomial with possibly interval coefficients, no rounding
@end deftypefun

@deftypefun bool ap_texpr1_is_interval_polyfrac (ap_texpr1_t* @var{e})
Polynomial fraction with possibly interval coefficients, no rounding
@end deftypefun

@deftypefun bool ap_texpr1_is_scalar (ap_texpr1_t* @var{e})
All coefficients are scalar (non-interval)@end deftypefun

@c -------------------------------------------------------------------
@node Operations on tree expressions of level 1,  , Tests on tree expressions of level 1, Tree expressions of level 1
@subsection Operations on tree expressions of level 1
@c -------------------------------------------------------------------

@deftypefun ap_texpr1_t* ap_texpr1_substitute (ap_texpr1_t* @var{e}, ap_var_t @var{var}, ap_texpr1_t* @var{dst})
Substitute every occurence of variable var with a copy of dst.  Return
NULL in case of incorrect argument (w.r.t. var and/or environment
compatibility).
@end deftypefun

@deftypefun ap_texpr1_t* ap_texpr1_extend_environment (ap_texpr1_t* @var{e}, ap_environment_t* @var{nenv})
Change current environment with a super-environment.  Return NULL if
@var{nenv} is not a superenvironment of @code{e->env}.
@end deftypefun

@deftypefun bool ap_texpr1_substitute_with (ap_texpr1_t* @var{e}, ap_var_t @var{var}, ap_texpr1_t* @var{dst})
@deftypefunx bool ap_texpr1_extend_environment_with (ap_texpr1_t* @var{e}, ap_environment_t* @var{nenv})
Side-effect versions of the previous functions. Return @code{true}
instead of @code{NULL} in case of problem.
@end deftypefun

@c ===================================================================
@node Tree constraints of level 1, Abstract values and operations of level 1, Tree expressions of level 1, Level 1 of the interface
@section Tree constraints of level 1 (@file{ap_tcons1.h})
@c ===================================================================

Tree constraints are constraints built on tree expressions.

@menu
* Datatypes for tree constraints of level 1::
* Constructors/Destructors for tree constraints of level 1::
* Operations on tree constraints of level 1::
* Arrays of tree constraints of level 1::
@end menu

@c -------------------------------------------------------------------
@node Datatypes for tree constraints of level 1, Constructors/Destructors for tree constraints of level 1, Tree constraints of level 1, Tree constraints of level 1
@subsection Datatypes for tree constraints of level 1
@c -------------------------------------------------------------------

@deftp datatype ap_tcons1_t
Datatype for constraints.

For information:
@example
typedef struct ap_tcons1_t @{
  ap_tcons0_t tcons0;
  ap_environment_t* env;
@} ap_tcons1_t;
@end example
@end deftp

@deftp datatype ap_tcons1_array_t
@example
typedef struct ap_tcons1_array_t @{
  ap_tcons0_array_t tcons0_array;
  ap_environment_t* env;
@} ap_tcons1_array_t;
@end example
Datatype for arrays of constraints.

Arrays at level 1 cannot be accessed directly, for example by writing
@code{array->p[i]}, but should instead be accessed with functions
@code{ap_tcons1_array_get} and @code{ap_tcons1_array_set}.
@end deftp

@c -------------------------------------------------------------------
@node Constructors/Destructors for tree constraints of level 1, Operations on tree constraints of level 1, Datatypes for tree constraints of level 1, Tree constraints of level 1
@subsection Constructors/Destructors for tree constraints of level 1
@c -------------------------------------------------------------------

@deftypefun ap_tcons1_t ap_tcons1_make (ap_constyp_t @var{constyp}, ap_texpr1_t*  @var{expr}, ap_scalar_t*  @var{scalar})
Create a constraint of given type with the given expression.  The
expression and the optional coefficient are not duplicated, just
pointed to.
@end deftypefun

@deftypefun ap_tcons1_t ap_tcons1_from_lincons1 (ap_tcons1_t* @var{cons})
Create a tree constraint from a linear constraint.
@end deftypefun

@deftypefun ap_tcons1_t ap_tcons1_copy (ap_tcons1_t* @var{cons})
Duplication.
@end deftypefun

@deftypefun void ap_tcons1_clear (ap_tcons1_t* @var{cons})
Clear the constraint and set pointers to NULL.
@end deftypefun

@deftypefun void ap_tcons1_fprint (FILE* @var{stream}, ap_tcons1_t* @var{cons})
@deftypefunx void ap_tcons1_print (ap_tcons1_t* @var{cons})
Printing
@end deftypefun

@deftypefun ap_environment_t* ap_tcons1_envref (ap_tcons1_t* @var{cons})
Get a reference to the environment. Do not free it.
@end deftypefun

@deftypefun ap_constyp_t* ap_tcons1_constypref (ap_tcons1_t* @var{cons})
Get a reference to the type of constraint.
@end deftypefun

@deftypefun ap_scalar_t* ap_tcons1_scalarref (ap_tcons1_t* @var{cons})
Get a reference to the auxiliary coefficient of the constraint.
@end deftypefun

@deftypefun ap_texpr1_t ap_tcons1_texpr1ref (ap_tcons1_t* @var{cons})
Get a reference to the underlying expression of the constraint.  Do
not free it: nothing is duplicated.  Modifying the argument or the
result is equivalent, except for change of dimensions/environment.
@end deftypefun

@deftypefun ap_tcons0_t* ap_tcons1_tcons0ref (ap_tcons1_t* @var{cons})
Return underlying constraint of level 0.  Do not free it: nothing is
duplicated.  Modifying the argument or the result is equivalent,
except for change of dimensions/envionment.
@end deftypefun

@c -------------------------------------------------------------------
@node Operations on tree constraints of level 1, Arrays of tree constraints of level 1, Constructors/Destructors for tree constraints of level 1, Tree constraints of level 1
@subsection Operations on tree constraints of level 1
@c -------------------------------------------------------------------

@deftypefun bool ap_tcons1_extend_environment (ap_tcons1_t* @var{ncons}, ap_tcons1_t* @var{cons}, ap_environment_t* @var{nenv})
@deftypefunx bool ap_tcons1_extend_environment_with (ap_tcons1_t* @var{cons}, ap_environment_t* @var{nenv})
Change current environment with a super-environment.  Return
@code{true} if @var{nenv} is not a superenvironment of @code{e->env}.
@end deftypefun

@c -------------------------------------------------------------------
@node Arrays of tree constraints of level 1,  , Operations on tree constraints of level 1, Tree constraints of level 1
@subsection Arrays of tree constraints of level 1
@c -------------------------------------------------------------------

@deftypefun ap_tcons1_array_t ap_tcons1_array_make (ap_environment_t* @var{env}, size_t @var{size})
Allocate an array of size constraints.  The constraints are
initialized with NULL pointers, so that @code{ap_tcons1_array_free}
may be safely called.
@end deftypefun
@deftypefun void ap_tcons1_array_clear (ap_tcons1_array_t* @var{array})
Clear the constraints of the array, and then the array itself.
@end deftypefun
@deftypefun void ap_tcons1_array_fprint (FILE* stream, ap_tcons1_array_t* @var{array})
@deftypefunx void ap_tcons1_array_print (ap_tcons1_array_t* @var{array})
Printing.
@end deftypefun

@deftypefun size_t ap_tcons1_array_size (ap_tcons1_array_t* @var{array})
Return the size of the array.
@end deftypefun

@deftypefun ap_environment_t* ap_tcons1_array_envref (ap_tcons1_array_t* @var{array})
Return a reference to the environment of the array. Do not free it.
@end deftypefun

@deftypefun void ap_tcons1_array_clear_index (ap_tcons1_array_t* @var{array}, size_t @var{index})
Clear the constraint at index index and set pointers to @code{NULL}.
@end deftypefun

@deftypefun ap_tcons1_t ap_tcons1_array_get (ap_tcons1_array_t* @var{array}, size_t @var{index})
Return the linear constraint of the given index Nothing is duplicated,
and the result should never be cleared.  Modifying the argument or the
result is equivalent, except for change of environments.
@end deftypefun

@deftypefun bool ap_tcons1_array_set (ap_tcons1_array_t* @var{array}, size_t @var{index}, ap_tcons1_t* @var{cons})
Fill the index of the array with the constraint.  Assumes
@code{ap_environment_is_eq(array->env,cons->env)}. Nothing is
duplicated.  The argument should never be cleared (its environment
is dereferenced).  If a constraint was already stored, it is first
cleared.  Return @code{true} iff problem (index or @code{array->env!=cons->env})
@end deftypefun

@deftypefun bool ap_tcons1_array_extend_environment_with (ap_tcons1_array_t* @var{array}, ap_environment_t* @var{nenv})
@deftypefunx bool ap_tcons1_array_extend_environment (ap_tcons1_array_t* narray, ap_tcons1_array_t* @var{array}, ap_environment_t* @var{nenv})
Change current environment with a super-environment.  Return
@code{true} if @var{nenv} is not a superenvironment of
@code{array->env}.
@end deftypefun

@c ===================================================================
@node Abstract values and operations of level 1,  , Tree constraints of level 1, Level 1 of the interface
@section Abstract values and operations of level 1 (@file{ap_abstract1.h})
@c ===================================================================

@deftp datatype ap_abstract1_t
Datatype for abstract values at level 1.

For information:
@example
typedef struct ap_abstract1_t @{
  ap_abstract0_t* abstract0;
  ap_environment_t* env;
@} ap_abstract1_t;
  /* data structure invariant:
     ap_abstract0_integer_dimension(man,abstract0)== env->intdim &&
     ap_abstract0_real_dimension(man,abstract0)== env->realdim */
@end example
@end deftp

@deftp datatype ap_box1_t
@example
typedef struct ap_box1_t @{
  ap_interval_t** p;
  ap_environment_t* env;
@} ap_box1_t;
void ap_box1_fprint(FILE* stream, ap_box1_t* box);
void ap_box1_clear(ap_box1_t* box);
@end example
@end deftp

Most operations are offered in 2 versions: @emph{functional} or
@emph{destructive} @xref{Abstract values and operations of level 0}.

We remind the policy for redimensioning (@pxref{Level 1 of the interface}):

@itemize
@item
For functions taking one abstract value and one expression (or
constraint or generator, or array of ...), the environment of the
expression should be a sub-environment of the environment of the
abstract value. The environment of the result is the environment of
the argument abstract value.
@item
For functions taking several abstract values, their environments
should be the same. Otherwise, it is up to the user to move them to a
common super-environment (@pxref{Environments}).
@end itemize

@menu
* Allocating abstract values of level 1::
* Control of internal representation of abstract values of level 1::
* Printing abstract values of level 1::
* Serialization of abstract values of level 1::

Constructors, Accessors, Tests and Extraction of properties
* Constructors for abstract values of level 1::
* Accessors for abstract values of level 1::
* Tests on abstract values of level 1::
* Extraction of properties of abstract values of level 1::

Operations
* Meet and Join of abstract values of level 1::
* Assignements and Substitutions of abstract values of level 1::
* Existential quantification of abstract values of level 1::
* Change of environments of abstract values of level 1::
* Expansion and Folding of dimensions in abstract values of level 1::
* Widening of abstract values of level 1::
* Topological closure of abstract values of level 1::

Additional functions
* Additional functions on abstract values of level 1::
@end menu

@c -------------------------------------------------------------------
@node Allocating abstract values of level 1, Control of internal representation of abstract values of level 1, Abstract values and operations of level 1, Abstract values and operations of level 1
@subsection Allocating abstract values of level 1
@c -------------------------------------------------------------------

@deftypefun ap_abstract1_t ap_abstract1_copy (ap_manager_t* @var{man}, ap_abstract1_t* @var{a})
Return a copy of @var{a}, on which destructive update does not
affect @var{a}.
@end deftypefun

@deftypefun void ap_abstract1_clear (ap_manager_t* @var{man}, ap_abstract1_t* @var{a})
Free all the memory used by @var{a}.
@end deftypefun

@deftypefun size_t ap_abstract1_size (ap_manager_t* @var{man}, ap_abstract1_t* @var{a})
Return the abstract size of @var{a}.
@end deftypefun

@c -------------------------------------------------------------------
@node Control of internal representation of abstract values of level 1, Printing abstract values of level 1, Allocating abstract values of level 1, Abstract values and operations of level 1
@subsection Control of internal representation of abstract values of level 1
@c -------------------------------------------------------------------

@deftypefun void ap_abstract1_minimize (ap_manager_t* @var{man}, ap_abstract1_t* @var{a})
Minimize the size of the representation of @var{a}.  This may result in
a later recomputation of internal information.
@end deftypefun

@deftypefun void ap_abstract1_canonicalize (ap_manager_t* @var{man}, ap_abstract1_t* @var{a})
Put @var{a} in canonical form. (not yet clear definition).
@end deftypefun

@deftypefun int ap_abstract1_hash (ap_manager_t* @var{man}, ap_abstract1_t* @var{a})
Return an hash value for @var{a}.  Two abstract values in canonical
from (according to @code{ap_abstract1_canonicalize}) and considered as
equal by the function @code{ap_abstract1_is_eq} are given the
same hash value.
@end deftypefun

@deftypefun void ap_abstract1_approximate (ap_manager_t* @var{man}, ap_abstract1_t* @var{a}, int @var{algorithm})
Perform some transformation on @var{a}, guided by the field
algorithm.

The transformation may lose information.  The argument
@var{algorithm} overrides the field algorithm of the structure of
type @code{ap_funopt_t} associated to
@code{ap_abstract1_approximate}.
@end deftypefun

@c -------------------------------------------------------------------
@node Printing abstract values of level 1, Serialization of abstract values of level 1, Control of internal representation of abstract values of level 1, Abstract values and operations of level 1
@subsection Printing abstract values of level 1
@c -------------------------------------------------------------------

@deftypefun void ap_abstract1_fprint (FILE* @var{stream}, ap_manager_t* @var{man}, ap_abstract1_t* @var{a})
Print @var{a} in a pretty way on the stream.
@end deftypefun

@deftypefun void ap_abstract1_fprintdiff (FILE* @var{stream}, ap_manager_t* @var{man}, ap_abstract1_t* @var{a1}, ap_abstract1_t* @var{a2})
Print the difference between @var{a1} (old value) and @var{a2} (new
value). The meaning of difference is library dependent.
@end deftypefun

@deftypefun void ap_abstract1_fdump (FILE* @var{stream}, ap_manager_t* @var{man}, ap_abstract1_t* @var{a})
Dump the internal representation of @var{a} for debugging
purposes.
@end deftypefun

@c -------------------------------------------------------------------
@node Serialization of abstract values of level 1, Constructors for abstract values of level 1, Printing abstract values of level 1, Abstract values and operations of level 1
@subsection Serialization of abstract values of level 1
@c -------------------------------------------------------------------
@deftypefun ap_membuf_t ap_abstract1_serialize_raw (ap_manager_t* @var{man}, ap_abstract1_t* @var{a})
Allocate a memory buffer (with @code{malloc}), output @var{a}
in raw binary format to it and return a pointer on the memory
buffer and the number of bytes written.  It is the user
responsability to free the memory afterwards (with @code{free}).
@end deftypefun

@deftypefun ap_abstract1_t ap_abstract1_deserialize_raw (ap_manager_t* @var{man}, void* @var{ptr}, size_t* @var{size})
Return the abstract value read in raw binary format from the
buffer pointed by @var{ptr} and store in size the number of bytes
read.
@end deftypefun

@c -------------------------------------------------------------------
@node Constructors for abstract values of level 1, Accessors for abstract values of level 1, Serialization of abstract values of level 1, Abstract values and operations of level 1
@subsection Constructors for abstract values of level 1
@c -------------------------------------------------------------------

@deftypefun ap_abstract1_t ap_abstract1_bottom (ap_manager_t* @var{man}, ap_environment_t* @var{env})
@deftypefunx ap_abstract1_t ap_abstract1_top (ap_manager_t* @var{man}, ap_environment_t* @var{env})
Create resp. a bottom (empty) value and a top (universe) value defined
on the environment @var{env}.
@end deftypefun

@deftypefun ap_abstract1_t ap_abstract1_of_box (ap_manager_t* @var{man}, ap_environment_t* @var{env}, ap_var_t* @var{tvar}, ap_interval_t** @var{tinterval}, size_t @var{size})
Abstract an hypercube defined by the arrays @var{tvar} and
@var{tintnerval} of size @var{size}.

If no inclusion is specified for a variable in the environment, its
value is no constrained in the resulting abstract value.
@end deftypefun

@c -------------------------------------------------------------------
@node Accessors for abstract values of level 1, Tests on abstract values of level 1, Constructors for abstract values of level 1, Abstract values and operations of level 1
@subsection Accessors for abstract values of level 1
@c -------------------------------------------------------------------

@deftypefun ap_dimension_t ap_abstract1_environment (ap_manager_t* @var{man}, ap_abstract1_t* @var{a})
Get a reference to the environment of @var{a}. Do not free it.
@end deftypefun

@deftypefun ap_manager_t* ap_abstract1_manager (ap_abstract1_t* @var{a})
Get a reference to the manager contained in @var{a}.
Do not free it.
@end deftypefun

@deftypefun ap_dimension_t ap_abstract1_abstract0 (ap_manager_t* @var{man}, ap_abstract1_t* @var{a})
Get a reference to the underlying abstract value of level 0 in
@var{a}. Do not free it.
@end deftypefun

@c -------------------------------------------------------------------
@node Tests on abstract values of level 1, Extraction of properties of abstract values of level 1, Accessors for abstract values of level 1, Abstract values and operations of level 1
@subsection Tests on abstract values of level 1
@c -------------------------------------------------------------------

In abstract tests,
@itemize
@item 
true means that the predicate is certainly true;
@item 
false means false @emph{or} don't know (an exception has occurred, or
the exact computation was considered too expensive to be performed,
according to the options).
@end itemize

@deftypefun bool ap_abstract1_is_bottom (ap_manager_t* @var{man}, ap_abstract1_t* @var{a})
@deftypefunx bool ap_abstract1_is_top (ap_manager_t* @var{man}, ap_abstract1_t* @var{a})
Emtpiness and universality tests.
@end deftypefun

@deftypefun bool ap_abstract1_is_leq (ap_manager_t* @var{man}, ap_abstract1_t* @var{a1}, ap_abstract1_t* @var{a2})
@deftypefunx bool ap_abstract1_is_eq (ap_manager_t* @var{man}, ap_abstract1_t* @var{a1}, ap_abstract1_t* @var{a2})
Inclusion and equality tests.
@end deftypefun

@deftypefun bool ap_abstract1_sat_interval (ap_manager_t* @var{man}, ap_abstract1_t* @var{a}, ap_var_t @var{var}, ap_interval_t* @var{interval})
Is the variable @var{var} included in the interval @var{interval} in the abstract value @var{a} ?
@end deftypefun

@deftypefun bool ap_abstract1_sat_lincons (ap_manager_t* @var{man}, ap_abstract1_t* @var{a}, ap_lincons1_t* @var{cons})
@deftypefunx bool ap_abstract1_sat_tcons (ap_manager_t* @var{man}, ap_abstract1_t* @var{a}, ap_tcons1_t* @var{cons})
Does the abstract value @var{a} satisfy the constraint @var{cons} ?
@end deftypefun

@deftypefun bool ap_abstract1_is_variable_unconstrained (ap_manager_t* @var{man}, ap_abstract1_t* @var{a}, ap_var_t @var{var})
Is the dimension @var{dim} unconstrained in the abstract value @var{a} ?
If it is the case, we have @code{forget(man,a,dim) == a}.
@end deftypefun

@c -------------------------------------------------------------------
@node Extraction of properties of abstract values of level 1, Meet and Join of abstract values of level 1, Tests on abstract values of level 1, Abstract values and operations of level 1
@subsection Extraction of properties of abstract values of level 1
@c -------------------------------------------------------------------

@deftypefun ap_interval_t* ap_abstract1_bound_variable (ap_manager_t* @var{man}, ap_abstract1_t* @var{a}, ap_var_t @var{var})
Return the interval taken by the variable @var{var} over the abstract
value @var{a}.
@end deftypefun

@deftypefun ap_interval_t* ap_abstract1_bound_linexpr (ap_manager_t* @var{man}, ap_abstract1_t* @var{a}, ap_linexpr1_t* @var{expr})
@deftypefunx ap_interval_t* ap_abstract1_bound_texpr (ap_manager_t* @var{man}, ap_abstract1_t* @var{a}, ap_texpr1_t* @var{expr})
Return the interval taken by the expression @var{expr} over
the abstract value @var{a}.

In the case of truly linear expression, this function allows to solve
a Linear Programming (LP) problem, but depending on the underlying
domain the solution may be not optimal.
@end deftypefun

@deftypefun ap_box1_t ap_abstract1_to_box (ap_manager_t* @var{man}, ap_abstract1_t* @var{a})
Convert @var{a} to an interval/hypercube.
@end deftypefun

@deftypefun ap_lincons1_array_t ap_abstract1_to_lincons_array (ap_manager_t* @var{man}, ap_abstract1_t* @var{a})
@deftypefunx ap_tcons1_array_t ap_abstract1_to_tcons_array (ap_manager_t* @var{man}, ap_abstract1_t* @var{a})
Convert @var{a} to a conjunction of linear (resp. tree)
constraints.

The constraints are normally guaranteed to be without intervals.
@end deftypefun

@deftypefun ap_generator1_array_t ap_abstract1_to_generator_array (ap_manager_t* @var{man}, ap_abstract1_t* @var{a})
Convert @var{a} to an array of generators.
@end deftypefun

@c -------------------------------------------------------------------
@node Meet and Join of abstract values of level 1, Assignements and Substitutions of abstract values of level 1, Extraction of properties of abstract values of level 1, Abstract values and operations of level 1
@subsection Meet and Join of abstract values of level 1
@c -------------------------------------------------------------------

@deftypefun ap_abstract1_t ap_abstract1_meet (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract1_t* @var{a1}, ap_abstract1_t* @var{a2})

@deftypefunx ap_abstract1_t ap_abstract1_join (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract1_t* @var{a1}, ap_abstract1_t* @var{a2})
Meet and Join of 2 abstract values
@end deftypefun


@deftypefun ap_abstract1_t ap_abstract1_meet_array (ap_manager_t* @var{man}, ap_abstract1_t* @var{array}, size_t @var{size})

@deftypefunx ap_abstract1_t ap_abstract1_join_array (ap_manager_t* @var{man}, ap_abstract1_t* @var{array}, size_t @var{size})
Meet and Join of the array @var{array} of abstract values of size
@var{size}.

Raise an @code{AP_EXC_INVALID_ARGUMENT} exception if
@code{size==1} (no way to define the environment of the result
in such a case).
@end deftypefun

@deftypefun ap_abstract1_t ap_abstract1_meet_lincons_array (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract1_t* @var{a}, ap_lincons1_array_t* @var{array})
@deftypefunx ap_abstract1_t ap_abstract1_meet_tcons_array (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract1_t* @var{a}, ap_tcons1_array_t* @var{array})
Meet of the abstract value @var{a} with the set of constraints
@var{array}.
@end deftypefun

@deftypefun ap_abstract1_t ap_abstract1_add_ray_array (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract1_t* @var{a}, ap_generator1_array_t* @var{array})
Generalized time elapse operator.

@var{array} is supposed to contain only rays or lines, no vertices.
@end deftypefun

@c -------------------------------------------------------------------
@node Assignements and Substitutions of abstract values of level 1, Existential quantification of abstract values of level 1, Meet and Join of abstract values of level 1, Abstract values and operations of level 1
@subsection Assignements and Substitutions of abstract values of level 1
@c -------------------------------------------------------------------

@deftypefun ap_abstract1_t ap_abstract1_assign_linexpr_array (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract1_t* @var{org}, ap_var_t* @var{tvar}, ap_linexpr1_t* @var{texpr}, size_t @var{size}, ap_abstract1_t* @var{dest})
@deftypefunx ap_abstract1_t ap_abstract1_substitute_linexpr_array (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract1_t* @var{org}, ap_var_t* @var{tvar}, ap_linexpr1_t* @var{texpr}, size_t @var{size}, ap_abstract1_t* @var{dest})
@deftypefunx ap_abstract1_t ap_abstract1_assign_texpr_array (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract1_t* @var{org}, ap_var_t* @var{tvar}, ap_texpr1_t* @var{texpr}, size_t @var{size}, ap_abstract1_t* @var{dest})
@deftypefunx ap_abstract1_t ap_abstract1_substitute_texpr_array (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract1_t* @var{org}, ap_var_t* @var{tvar}, ap_texpr1_t* @var{texpr}, size_t @var{size}, ap_abstract1_t* @var{dest})
Parallel Assignement and Substitution of several variables by
expressions in abstract value @var{org}.

@var{dest} is an optional argument. If not NULL, semantically speaking,
the result of the transformation is intersected with @var{dest}. This is
useful for precise backward transformations in lattices like intervals or
octagons.
@end deftypefun

@c -------------------------------------------------------------------
@node Existential quantification of abstract values of level 1, Change of environments of abstract values of level 1, Assignements and Substitutions of abstract values of level 1, Abstract values and operations of level 1
@subsection Existential quantification of abstract values of level 1
@c -------------------------------------------------------------------

@deftypefun ap_abstract1_t ap_abstract1_forget_array (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract1_t* @var{a}, ap_var_t* @var{tvar}, size_t @var{size}, bool @var{project})
Forget (@code{project=false}) or Project (@code{project=true}) the
array of variables @var{tvar} of size @var{size} in the abstract
value @var{a}.
@end deftypefun

@c -------------------------------------------------------------------
@node Change of environments of abstract values of level 1, Expansion and Folding of dimensions in abstract values of level 1, Existential quantification of abstract values of level 1, Abstract values and operations of level 1
@subsection Change of environments of abstract values of level 1
@c -------------------------------------------------------------------

@deftypefun ap_abstract1_t ap_abstract1_change_environment (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract1_t* @var{a}, ap_environment_t* @var{nenv}, bool @var{project})
Change the environment of the abstract values.  Variables that are
removed are first existentially quantified, and variables that are
introduced are either unconstrained (@code{project==false}) or
initialized to 0 (@code{project==false}).
@end deftypefun

@deftypefun ap_abstract1_t ap_abstract1_minimize_environment (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract1_t* @var{a})
Remove from the environment of the abstract value and from the
abstract value itself variables that are unconstrained in it.
@end deftypefun

@deftypefun ap_abstract1_t ap_abstract1_rename_array (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract1_t* @var{a}, ap_var_t* @var{tvar}, ap_var_t* @var{ntvar}, size_t @var{size})
Parallel renaming of the environment of the abstract value. The new
variables should not interfere with the variables that are not
renamed.
@end deftypefun

@c -------------------------------------------------------------------
@node Expansion and Folding of dimensions in abstract values of level 1, Widening of abstract values of level 1, Change of environments of abstract values of level 1, Abstract values and operations of level 1
@subsection Expansion and Folding of dimensions of abstract values of level 1
@c -------------------------------------------------------------------

Formally, expanding @code{z} into @code{z} and @code{w} in
abstract value (predicate) @code{P} is defined by
@math{expand(P(x,y,z),z,w) = P(x,y,z) and P(x,y,w)}.

Conversely, folding @code{z} and @code{w} into @code{z} in
abstract value (predicate) @code{Q} is defined by
@math{fold(Q(x,y,z,w),z,w) = (exists w: Q(x,y,z,w)) or (exists z:Q(x,y,z,w)[z<-w])}.

@deftypefun ap_abstract1_t ap_abstract1_expand (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract1_t* @var{a}, ap_var_t @var{var}, ap_var_t* @var{tvar}, size_t @var{size})
Expand the variable @var{var} into itself + the @var{size} additional
variables of the array @var{tvar}, which are given the same type as
@var{var}.  The additional variables are added to the environment of
the argument for making the environment of the result, so they should
not belong to the initial environment.

It results in @code{size+1} unrelated variables having same relations
with other dimensions.
@end deftypefun

@deftypefun ap_abstract1_t ap_abstract1_fold (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract1_t* @var{a}, ap_var_t* @var{tvar}, size_t @var{size})
Fold the variables in the array @var{tvar} of size @var{size}>=1 and
put the result in the first variable in the array. The other variables
of the array are then forgot and removed from the environment.
@end deftypefun

@c -------------------------------------------------------------------
@node Widening of abstract values of level 1, Topological closure of abstract values of level 1, Expansion and Folding of dimensions in abstract values of level 1, Abstract values and operations of level 1
@subsection Widening of abstract values of level 1
@c -------------------------------------------------------------------

@deftypefun ap_abstract1_t ap_abstract1_widening (ap_manager_t* @var{man}, ap_abstract1_t* @var{a1}, ap_abstract1_t* @var{a2})
Widening of @var{a1} with @var{a2}. @var{a1} is supposed to be
included in @var{a2}.
@end deftypefun

@deftypefun ap_abstract1_t ap_abstract1_widening_threshold (ap_manager_t* @var{man}, ap_abstract1_t* @var{a1}, ap_abstract1_t* @var{a2}, ap_lincons1_array_t* @var{array})
Widening with threshold.

Intersect the result of the standard widening with all the
constraints in @var{array} that are satisfied by both @var{a1} and
@var{a2}.
@end deftypefun

@c -------------------------------------------------------------------
@node Topological closure of abstract values of level 1, Additional functions on abstract values of level 1, Widening of abstract values of level 1, Abstract values and operations of level 1
@subsection Topological closure of abstract values of level 1
@c -------------------------------------------------------------------

@deftypefun ap_abstract1_t* ap_abstract1_closure (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract1_t* @var{a})
Relax strict constraints into non strict constraints.
@end deftypefun

@c -------------------------------------------------------------------
@node Additional functions on abstract values of level 1,  , Topological closure of abstract values of level 1, Abstract values and operations of level 1
@subsection Additional functions on abstract values of level 1
@c -------------------------------------------------------------------

@deftypefun ap_abstract1_t ap_abstract1_of_lincons_array (ap_manager_t* @var{man}, ap_environment_t* @var{env}, ap_lincons1_array_t* @var{array})
@deftypefunx ap_abstract1_t ap_abstract1_of_tcons_array (ap_manager_t* @var{man}, ap_environment_t* @var{env}, ap_tcons1_array_t* @var{array})
Abstract a conjunction of constraints. The environment of the array should be
a subset of the environment @var{env}.
@end deftypefun

@deftypefun ap_abstract1_t ap_abstract1_assign_linexpr (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract1_t* @var{org}, ap_var_t @var{var}, ap_linexpr1_t* @var{expr}, ap_abstract1_t* @var{dest})
@deftypefunx ap_abstract1_t ap_abstract1_substitute_linexpr (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract1_t* @var{org}, ap_var_t @var{var}, ap_linexpr1_t* @var{expr}, ap_abstract1_t* @var{dest})
@deftypefunx ap_abstract1_t ap_abstract1_assign_texpr (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract1_t* @var{org}, ap_var_t @var{var}, ap_texpr1_t* @var{expr}, ap_abstract1_t* @var{dest})
@deftypefunx ap_abstract1_t ap_abstract1_substitute_texpr (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract1_t* @var{org}, ap_var_t @var{var}, ap_texpr1_t* @var{expr}, ap_abstract1_t* @var{dest})
Assignement and Substitution of the dimension @var{dim} by the
expression @var{expr} in abstract value @var{org}.

@var{dest} is an optional argument. If not NULL, semantically
speaking, the result of the transformation is intersected with
@var{dest}. This is useful for precise backward transformations in
lattices like intervals or octagons.
@end deftypefun

@deftypefun ap_abstract1_t ap_abstract1_unify (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract1_t* @var{a1}, ap_abstract1_t* @var{a2})
Unify two abstract values on their common variables, that is,
embed them on the least common environment and then compute their
meet. The result is defined on the least common environment.

For instance, the unification of @code{1<=x<=3 and x=y} defined on
@code{@{ x, y @}} and @code{2<=z<=4 and z=y} defined on 
@code{@{y,z @}} results in @code{2<=x<=3 and x=y=z} defined on
@code{@{x,y,z@}}.
@end deftypefun


@deftypefun ap_linexpr1_t ap_abstract1_quasilinear_of_intlinear (ap_manager_t* @var{man}, ap_abstract1_t* @var{a}, ap_linexpr1_t* @var{expr})
Evaluate the interval linear expression @var{expr} on the abstract
value @var{a} and approximate it by a quasilinear expression.

This implies calls to @code{ap_abstract0_bound_dimension}.
@end deftypefun

@deftypefun ap_linexpr1_t ap_abstract1_intlinear_of_tree (ap_manager_t* @var{man}, ap_abstract1_t* @var{a}, ap_texpr1_t* @var{expr}, bool quasilinear)
Evaluate the tree expression @var{expr} on the abstract value @var{a}
and approximate it by an interval linear (resp. quasilinear if
@var{quasilinear} is true) expression.

This implies calls to @code{ap_abstract0_bound_dimension}.
@end deftypefun

@c *******************************************************************
@node Level 0 of the interface, Functions for implementors, Level 1 of the interface, Top
@chapter Level 0 of the interface
@c *******************************************************************

This interface of level 0 is defined in @file{ap_global0.h}.

Unless there exists specific reasons for not doing so, we advise the
user to use the level 1 of the interface (@pxref{Level 1 of the interface}).
The level 0 is intented for implementors who wants to connect a
new library/abstract domain, or who want to build a composite domain
from existing ones.

@menu
* Dimensions and related operations::  
* Linear expressions of level 0::  
* Linear constraints of level 0::  
* Generators of level 0::       
* Tree expressions of level 0::  
* Tree constraints of level 0::  
* Abstract values and operations of level 0::  
@end menu

@ifnothtml
For information only (as most of these types are considered as
abstract) and for implementors, we sum up the involved types
below.
@verbatim
    ap_dim_t         ap_dimension_t
|--------------|   |----------------|
| unsigned int |   | size_t intdim  |
|--------------|   | size_t realdim |
		   |----------------|

  ap_dimchange_t      ap_dimperm_t
|----------------|   |-----------|
| ap_dim_t* dim  |   | ap_dim_t* |
| size_t intdim  |   | size_t    |
| size_t realdim |   |-----------|
|----------------|

	ap_linexpr0_t              ap_linterm_t
|-----------------------------|   |------------|
|      ap_coeff_t       cst   |   | ap_dim_t   |
|      ap_linexpr_discr discr |   | ap_coeff_t |
|      size_t           size  |   |------------|
|-----------------------------|
| ap_coeff_t* | ap_linterm_t* |
|-----------------------------|

   ap_lincons0_t         ap_generator0_t
|------------------|   |----------------|
| ap_linexpr0_t*   |   | ap_linexpr0_t* |
| ap_constyp_t     |   | ap_gentyp_t    |
| ap_scalar_t* mod |   |----------------|
|------------------|

 ap_abstract0_t
|---------------|
| void*         |
| ap_manager_t* |
|---------------|
@end verbatim
@end ifnothtml

@c ===================================================================
@node Dimensions and related operations, Linear expressions of level 0, Level 0 of the interface, Level 0 of the interface
@section Dimensions and related operations (@file{ap_dimension.h})
@c ===================================================================

@deftp datatype ap_dim_t
@example
typedef unsigned int ap_dim_t;
@end example
Datatype for dimensions.
@end deftp

@defmac AP_DIM_MAX
Special value used for sparse representations, means: "to be
ignored". Also used as a result when an error occurs.
@end defmac

@deftp datatype ap_dimension_t
@example
typedef struct ap_dimension_t @{
  size_t intdim;  /* Number of integer dimensions */
  size_t realdim; /* Number of real dimensions */
@} ap_dimension_t;
@end example
Datatype for specifying the dimensionality of an abstract value.
@end deftp

@deftp datatype ap_dimchange_t
@example
typedef struct ap_dimchange_t @{
  ap_dim_t* dim;  /* Assumed to be an array of size intdim+realdim */
  size_t intdim ; /* Number of integer dimensions to add/remove */
  size_t realdim; /* Number of real dimensions to add/remove */
@} ap_dimchange_t;
@end example
Datatype for specifying change of dimension.

The semantics is the following:
@table @strong
@item Addition of dimensions

@code{dimchange.dim[k]} means: add one dimension at dimension k
and shift the already existing dimensions greater than or equal to
@code{k} one step on the right (or increment them).

if @code{k} is equal to the size of the vector, then it means: add
a dimension at the end.

Repetion are allowed, and means that one inserts more than one dimensions.

Example: @code{linexpr0_add_dimensions([i0 i1 r0 r1], @{ [0 1 2 2
4],3,1 @})} returns @code{[0 i0 0 i1 0 0 r0 r1 0]}, considered as
a vector with 5 integer dimensions and 4 real dimensions.

@item Removal of dimensions

@code{dimchange.dim[k]}: remove the dimension @code{k} and shift
the dimensions greater than @code{k} one step on the left (or
decrement them).

Repetitions are meaningless (and are not correct specification).

Example: @code{linexpr0_remove_dimensions([i0 i1 i2 r0 r1 r2], @{
[0 2 4],2,1 @})} returns @code{[i1 r0 r2]}, considered as a vector with 1
integer dimensions and 2 real dimensions.
@end table
@end deftp

@deftp datatype ap_dimchange2_t
@example
typedef struct ap_dimchange_2t @{
  ap_dimchange_t* add;    /* If not NULL, specifies the adding new dimensions */
  ap_dimchange_t* remove; /* If not NULL, specifies the removal of dimensions */
@} ap_dimchange2_t;
@end example
Datatype for specifying a transformation composed of the addition and
the removal of dimensions. Used by functions
@code{ap_abstract0_apply_dimchange2},
@code{ap_environment_dimchange2}, and
@code{ap_abstract1_change_environment.}.
@end deftp

@deftp datatype ap_dimperm_t
@example
typedef struct ap_dimperm_t @{
  ap_dim_t* dim; /* Array assumed to be of size size */
  size_t size;
@} ap_dimperm_t;
@end example
Datatype for permutations.

Represents the permutation @code{i -> dimperm.p[i]} for
@code{0<=i<dimperm.size}.
@end deftp

@menu
* Manipulating changes of dimensions::
* Manipulating permutations of dimensions::
@end menu

@c -------------------------------------------------------------------
@node Manipulating changes of dimensions, Manipulating permutations of dimensions, Dimensions and related operations, Dimensions and related operations
@subsection Manipulating changes of dimensions
@c -------------------------------------------------------------------

@deftypefun void ap_dimchange_init (ap_dimchange_t* @var{dimchange}, size_t @var{intdim}, size_t @var{realdim})
@deftypefunx void ap_dimchange_clear (ap_dimchange_t* @var{dimchange})
Initialize and clear a dimchange structure.
@end deftypefun

@deftypefun ap_dimchange_t* ap_dimchange_alloc (size_t @var{intdim}, size_t @var{realdim})
@deftypefunx void ap_dimchange_free (ap_dimchange_t* @var{dimchange})
Allocate and free a dimchange structure.
@end deftypefun

@deftypefun void ap_dimchange_fprint (FILE* @var{stream}, ap_dimchange_t* @var{dimchange})
Print the change of dimension.
@end deftypefun

@deftypefun void ap_dimchange_add_invert (ap_dimchange_t*  @var{dimchange})
Assuming that dimchange is a transformation for the addition of dimensions,
invert it to obtain the inverse transformation for removing dimensions.
@end deftypefun

@deftypefun void ap_dimchange2_init (ap_dimchange2_t* @var{dimchange2}, ap_dimchange_t* @var{add}, ap_dimchange_t* @var{remove})
@deftypefunx void ap_dimchange2_clear (ap_dimchange2_t* @var{dimchange2})
Initialize (with @var{add} and @var{remove}) and clear a dimchange2
structure.
@end deftypefun
@deftypefun ap_dimchange2_t* ap_dimchange2_alloc (ap_dimchange_t* @var{add}, ap_dimchange_t* @var{remove})
@deftypefunx void ap_dimchange2_free (ap_dimchange2_t* @var{dimchange2})
Allocate and free a dimchange2 structure.
@end deftypefun
@deftypefun void ap_dimchange2_fprint (FILE* @var{stream}, ap_dimchange2_t* @var{dimchange2})
Print the change of dimension.
@end deftypefun


@c -------------------------------------------------------------------
@node Manipulating permutations of dimensions,  , Manipulating changes of dimensions, Dimensions and related operations
@subsection Manipulating permutations of dimensions
@c -------------------------------------------------------------------

@deftypefun void ap_dimperm_init (ap_dimperm_t* @var{perm}, size_t @var{size})
@deftypefunx void ap_dimperm_clear (ap_dimperm_t* @var{perm})
Initialize and clear a dimperm structure.
@end deftypefun

@deftypefun ap_dimperm_t* ap_dimperm_alloc (size_t @var{size})
@deftypefunx void ap_dimperm_free (ap_dimperm_t* @var{perm})
Allocate and free a dimperm structure.
@end deftypefun

@deftypefun void ap_dimperm_fprint (FILE* @var{stream}, ap_dimperm_t* @var{perm})
Print the permutation.
@end deftypefun

@deftypefun void ap_dimperm_set_id (ap_dimperm_t* @var{perm})
Fill the already allocated @var{perm} with the identity permutation.
@end deftypefun

@deftypefun void ap_dimperm_compose (ap_dimperm_t* @var{perm}, ap_dimperm_t* @var{perm1}, ap_dimperm_t* @var{perm2})
Compose the 2 permutations @var{perm1} and @var{perm2} (in this order)
and store the result the already allocated perm.
The sizes of permutations are supposed to be equal.
At exit, we have @code{perm.dim[i] = perm2.dim[perm1.dim[i]]}.
@end deftypefun

@deftypefun void ap_dimperm_invert (ap_dimperm_t* @var{nperm}, ap_dimperm_t* @var{perm})
Invert the permutation @var{perm} and store it in the already
allocated @var{nperm}. The sizes of permutations are supposed to
be equal.
@end deftypefun

@c ===================================================================
@node Linear expressions of level 0, Linear constraints of level 0, Dimensions and related operations, Level 0 of the interface
@section Linear expressions of level 0 (@file{ap_linexpr0.h})
@c ===================================================================

@deftp datatype ap_linexpr_discr_t
@example
typedef enum ap_linexpr_discr_t @{
  LINEXPR_DENSE,
  LINEXPR_SPARSE
@} ap_linexpr_discr_t;
@end example
Type of representation of linear expressions: either dense or sparse.
@end deftp

@deftp datatype ap_linexpr0_t
Type of interval linear expressions. Coefficients in such expressions
are of type @code{coeff_t}.
@end deftp

@menu
* Allocating linear expressions of level 0::
* Tests on linear expressions of level 0::
* Access to linear expressions of level 0::
* Change of dimensions and permutations of linear expressions of level 0::
* Other functions on linear expressions of level 0::
@end menu

@c -------------------------------------------------------------------
@node Allocating linear expressions of level 0, Tests on linear expressions of level 0, Linear expressions of level 0, Linear expressions of level 0
@subsection Allocating linear expressions of level 0
@c -------------------------------------------------------------------

@deftypefun ap_linexpr0_t* ap_linexpr0_alloc (ap_linexpr_discr_t @var{lin_discr}, size_t @var{size});
Allocate a linear expressions with coefficients by default of type
SCALAR and DOUBLE. If sparse representation, corresponding new
dimensions are initialized with @code{AP_DIM_MAX}.
@end deftypefun

@deftypefun void ap_linexpr0_realloc (ap_linexpr0_t* @var{e}, size_t @var{size})
Change the dimensions of the array in @var{e}.  If new coefficients
are added, their type is of type SCALAR and DOUBLE.  If sparse
representation, corresponding new dimensions are initialized with
@code{AP_DIM_MAX}.
@end deftypefun

@deftypefun void ap_linexpr0_minimize (ap_linexpr0_t* @var{e})
Reduce the coefficients (transform intervals into scalars when
possible).  In case of sparse representation, also remove zero
coefficients.
@end deftypefun

@deftypefun void ap_linexpr0_free (ap_linexpr0_t* @var{e});
Deallocate the linear expression.
@end deftypefun

@deftypefun ap_linexpr0_t* ap_linexpr0_copy (ap_linexpr0_t* @var{e})
Duplication.
@end deftypefun

@deftypefun void ap_linexpr0_fprint (FILE* @var{stream}, ap_linexpr0_t* @var{e}, char** @var{name_of_dim});
Print the linear expression on stream @var{stream}, using the array
@var{name_of_dim} to convert dimensions to variable names. If
@var{name_of_dim} is @code{NULL}, the dimensions are named
@code{x0,x1,...}.
@end deftypefun

@c -------------------------------------------------------------------
@node Tests on linear expressions of level 0, Access to linear expressions of level 0, Allocating linear expressions of level 0, Linear expressions of level 0
@subsection Tests on linear expressions of level 0
@c -------------------------------------------------------------------

@deftypefun bool ap_linexpr0_is_integer (ap_linexpr0_t* @var{e}, size_t @var{intdim})
Does the expression depends only on integer variables ? assuming that
the first intdim dimensions are integer.
@end deftypefun

@deftypefun bool ap_linexpr0_is_real (ap_linexpr0_t* @var{e}, size_t @var{intdim})
Does the expression depends only on real variables ? assuming that
the first intdim dimensions are integer .
@end deftypefun

@deftypefun bool ap_linexpr0_is_linear (ap_linexpr0_t* @var{e})
Return true iff all involved coefficients are scalars.
@end deftypefun

@deftypefun bool ap_linexpr0_is_quasilinear (ap_linexpr0_t* @var{e})
Return true iff all involved coefficients but the constant are scalars.
@end deftypefun

@c -------------------------------------------------------------------
@node Access to linear expressions of level 0, Change of dimensions and permutations of linear expressions of level 0, Tests on linear expressions of level 0, Linear expressions of level 0
@subsection Access to linear expressions of level 0
@c -------------------------------------------------------------------

@deftypefun size_t ap_linexpr0_size (ap_linexpr0_t* @var{e})
Get the size of the linear expression
@end deftypefun

@c -------------------------------------------------------------------
@subsubsection Getting references

@deftypefun ap_coefft* ap_linexpr0_cstref (ap_linexpr0_t* @var{e})
Get a reference to the constant. Do not free it.
@end deftypefun

@deftypefun ap_coefft* ap_linexpr0_coeffref (ap_linexpr0_t* @var{e}, ap_dim_t @var{dim})
Get a reference to the coefficient associated to the dimension
@var{dim} in expression @var{e}.

Do not free it. In case of sparse representation, possibly induce the
addition of a new linear term.

Return NULL if:
@itemize
@item In case of dense representation, @code{dim>=e->size}.
@item In case of sparse representation,  @code{dim==AP_DIM_MAX}.
@end itemize
@end deftypefun

@c -------------------------------------------------------------------
@subsubsection Getting values

@deftypefun void ap_linexpr0_get_cst (ap_coefft* @var{coeff}, ap_linexpr0_t* @var{e})
Assign to @var{coeff} the constant coefficient of @var{e}.
@end deftypefun

@deftypefun bool ap_linexpr0_get_coeff (ap_coefft* coeff, ap_linexpr0_t* @var{e}, ap_dim_t @var{dim})
Assign to @var{coeff} the coefficient of dimension @var{dim} in the expression @var{e}.

Return true in case @code{ap_linexpr0_coeffref(e,dim)} returns NULL.
@end deftypefun

@defmac ap_linexpr0_ForeachLinterm (ap_linexpr0_t* @var{e}, size_t @var{i}, ap_dim_t @var{dim}, ap_coeff_t* @var{coeff})
Iterator on the coefficients associated to dimensions.

@code{ap_linexpr0_ForeachLinterm(E,I,DIM,COEFF)@{ body @}}
executes the body for each pair (@var{coeff},@var{dim}) in the
expression @var{e}. @var{coeff} is a reference to the coefficient
associated to dimension @var{dim} in @var{e}. @var{i} is an
auxiliary variable used internally by the macro.
@end defmac

@c -------------------------------------------------------------------
@subsubsection Assigning values with a list of arguments

@deftp datatype ap_coefftag_t
@example
typedef enum ap_coefftag_t @{
  AP_COEFF,          /* waiting for a coeff_t* object and a dimension */
  AP_COEFF_S,        /* waiting for a scalar_t* object and a dimension */
  AP_COEFF_S_MPQ,    /* waiting for a mpq_t object and a dimension */
  AP_COEFF_S_INT,    /* waiting for a int object and a dimension */
  AP_COEFF_S_FRAC,   /* waiting for 2 int objects and a dimension */
  AP_COEFF_S_DOUBLE, /* waiting for a double object and a dimension */
  AP_COEFF_I,        /* waiting for a interval_t* object and a dimension */
  AP_COEFF_I_SCALAR, /* waiting for 2 scalar_t* objects and a dimension */
  AP_COEFF_I_MPQ,    /* waiting for 2 mpq_t objects and a dimension */
  AP_COEFF_I_INT,    /* waiting for 2 int objects and a dimension */
  AP_COEFF_I_FRAC,   /* waiting for 4 int objects and a dimension */
  AP_COEFF_I_DOUBLE, /* waiting for 2 double objects and a dimension */
  AP_CST,            /* waiting for a coeff_t* object */
  AP_CST_S,          /* waiting for a scalar_t* object */
  AP_CST_S_MPQ,      /* waiting for a mpq_t object */
  AP_CST_S_INT,      /* waiting for a int object */
  AP_CST_S_FRAC,     /* waiting for 2 int objects */
  AP_CST_S_DOUBLE,   /* waiting for a double object */
  AP_CST_I,          /* waiting for a interval_t* object */
  AP_CST_I_SCALAR,   /* waiting for 2 scalar_t* objects */
  AP_CST_I_MPQ,      /* waiting for 2 mpq_t objects */
  AP_CST_I_INT,      /* waiting for 2 int objects */
  AP_CST_I_FRAC,     /* waiting for 4 int objects */
  AP_CST_I_DOUBLE,   /* waiting for 2 double objects */
  AP_END             /* indicating end of the list */
@} ap_coefftag_t;
@end example
Tags for @code{ap_linexpr0_set_list} function.
@end deftp

@deftypefun bool ap_linexpr0_set_list (ap_linexpr0_t* @var{e}, ...)
This function assign the linear expression @var{E} from a list of
tags of type @code{ap_coefftag_t}, each followed by a number of
arguments as specified in the definition of the tye
@code{ap_coefftag_t}. The list should end with the tag
@code{AP_COEFF_END}.

Return @code{true} in case @code{ap_linexpr0_coeffref(e,dim)}
returns NULL for one of the dimensions involved.

Here is a typical example:
@example
ap_linexpr0_set_list(e,
		     AP_COEFF_S_INT, 3, 0,
		     AP_COEFF_S_FRAC, 3,2, 1,
		     AP_COEFF_S_DOUBLE, 4.1, 2,
		     AP_CST_I_DOUBLE, -2.4, 3.6,
		     AP_END); /* Do not forget the last tatg ! */
@end example
which transforms an null expression into @code{3 x0 + 3/2 x1 + 4.1 x2 + [-2.4,3.6]}
and is equivalent to:
@example
ap_linexpr0_set_coeff_scalar_int(e,0, 3);
ap_linexpr0_set_coeff_scalar_frac(e,1, 3,2);
ap_linexpr0_set_coeff_scalar_double(e,2, 4.1);
ap_linexpr0_set_cst_interval_double(e, -2.4, 3.6);
@end example
@end deftypefun

@c -------------------------------------------------------------------
@subsubsection Assigning values

@deftypefun void ap_linexpr0_set_cst (ap_linexpr0_t* @var{e}, ap_coefft* @var{coeff})
@deftypefunx void ap_linexpr0_set_cst_scalar (ap_linexpr0_t* @var{e}, ap_scalar_t* @var{scalar})
@deftypefunx void ap_linexpr0_set_cst_scalar_int (ap_linexpr0_t* @var{e}, int @var{num})
@deftypefunx void ap_linexpr0_set_cst_scalar_frac (ap_linexpr0_t* @var{e}, int @var{num}, unsigned int @var{den})
@deftypefunx void ap_linexpr0_set_cst_scalar_double (ap_linexpr0_t* @var{e}, double @var{num})
@deftypefunx void ap_linexpr0_set_cst_interval (ap_linexpr0_t* @var{e}, ap_interval_t* @var{itv})
@deftypefunx void ap_linexpr0_set_cst_interval_scalar (ap_linexpr0_t* @var{e}, ap_scalar_t* @var{inf}, ap_scalar_t* @var{sup})
@deftypefunx void ap_linexpr0_set_cst_interval_int (ap_linexpr0_t* @var{e}, int @var{inf}, int @var{sup})
@deftypefunx void ap_linexpr0_set_cst_interval_frac (ap_linexpr0_t* @var{e}, int @var{numinf}, unsigned int @var{deninf}, int @var{numsup}, unsigned int @var{densup})
@deftypefunx void ap_linexpr0_set_cst_interval_double (ap_linexpr0_t* @var{e}, double @var{inf}, double @var{sup})
Set the constant coefficient of expression @var{e}.
@end deftypefun

@deftypefun bool ap_linexpr0_set_coeff (ap_linexpr0_t* @var{e}, ap_dim_t @var{dim}, ap_coefft* @var{coeff})
@deftypefunx bool ap_linexpr0_set_coeff_scalar (ap_linexpr0_t* @var{e}, ap_dim_t @var{dim}, ap_scalar_t* @var{scalar})
@deftypefunx bool ap_linexpr0_set_coeff_scalar_int (ap_linexpr0_t* @var{e}, ap_dim_t @var{dim}, int @var{num})
@deftypefunx bool ap_linexpr0_set_coeff_scalar_frac (ap_linexpr0_t* @var{e}, ap_dim_t @var{dim}, int @var{num}, unsigned int @var{den})
@deftypefunx bool ap_linexpr0_set_coeff_scalar_double (ap_linexpr0_t* @var{e}, ap_dim_t @var{dim}, double @var{num})
@deftypefunx bool ap_linexpr0_set_coeff_interval (ap_linexpr0_t* @var{e}, ap_dim_t @var{dim}, ap_interval_t* @var{itv})
@deftypefunx bool ap_linexpr0_set_coeff_interval_scalar (ap_linexpr0_t* @var{e}, ap_dim_t @var{dim}, ap_scalar_t* @var{inf}, ap_scalar_t* @var{sup})
@deftypefunx bool ap_linexpr0_set_coeff_interval_int (ap_linexpr0_t* @var{e}, ap_dim_t @var{dim}, int @var{inf}, int @var{sup})
@deftypefunx bool ap_linexpr0_set_coeff_interval_frac (ap_linexpr0_t* @var{e}, ap_dim_t @var{dim}, int @var{numinf}, unsigned int @var{deninf}, int @var{numsup}, unsigned int @var{densup})
@deftypefunx void ap_linexpr0_set_coeff_interval_double (ap_linexpr0_t* @var{e}, ap_dim_t @var{dim}, double @var{inf}, double @var{sup})
Set the coefficient of the dimension @var{dim} of expression @var{e}.

Return @code{true} in case @code{ap_linexpr0_coeffref(e,dim)} returns NULL.
@end deftypefun

@c -------------------------------------------------------------------
@node Change of dimensions and permutations of linear expressions of level 0, Other functions on linear expressions of level 0, Access to linear expressions of level 0, Linear expressions of level 0
@subsection Change of dimensions and permutations of linear expressions of level 0
@c -------------------------------------------------------------------

@deftypefun void ap_linexpr0_add_dimensions_with (ap_linexpr0_t* @var{e}, ap_dimchange_t* @var{dimchange})
@deftypefunx ap_linexpr0_t* ap_linexpr0_add_dimensions (ap_linexpr0_t* @var{e}, ap_dimchange_t* @var{dimchange})
These two functions add dimensions to the expressions, following
the semantics of dimchange (see the type definition of @code{ap_dimchange_t}).
@end deftypefun

@deftypefun void ap_linexpr0_permute_dimensions_with (ap_linexpr0_t* @var{e}, ap_dimperm_t* @var{perm})
@deftypefunx ap_linexpr0_t*  ap_linexpr0_permute_dimensions (ap_linexpr0_t* @var{e}, ap_dimperm_t* @var{perm})
These two functions apply the given permutation to the dimensions
of @var{e}. If dense representation, the size of the permutation
should be @code{e->size}. If sparse representation, the
dimensions present in the expression should just be less
than the size of the permutation.
@end deftypefun

@c -------------------------------------------------------------------
@node Other functions on linear expressions of level 0,  , Change of dimensions and permutations of linear expressions of level 0, Linear expressions of level 0
@subsection Other functions on linear expressions of level 0
@c -------------------------------------------------------------------

All these functions induces a reduction of the coefficients of the
linear expression.

@deftypefun int ap_linexpr0_hash (ap_linexpr0_t* @var{e})
Return a hash code.
@end deftypefun

@deftypefun bool ap_linexpr0_equal (ap_linexpr0_t* @var{e1}, ap_linexpr0_t* @var{e2})
Equality test.
@end deftypefun

@deftypefun int ap_linexpr0_compare (ap_linexpr0_t* @var{e1}, ap_linexpr0_t* @var{e2})
Lexicographic ordering, terminating by constant coefficients.

Use the (partial order) comparison function on coefficients
@code{coeff_cmp}.
@end deftypefun


@c ===================================================================
@node Linear constraints of level 0, Generators of level 0, Linear expressions of level 0, Level 0 of the interface
@section Linear constraints of level 0 (@file{ap_lincons0.h})
@c ===================================================================

@deftp datatype ap_constyp_t
@example
typedef enum ap_constyp_t @{
  AP_CONS_EQ,    /* equality constraint */
  AP_CONS_SUPEQ, /* >= constraint */
  AP_CONS_SUP,   /* > constraint */
  AP_CONS_EQMOD, /* congruence equality constraint */
  AP_CONS_DISEQ  /* disequality constraint */
@} ap_constyp_t;
@end example
Datatype for type of constraints.
@end deftp

@deftp datatype ap_lincons0_t
@example
typedef struct ap_lincons0_t @{
  ap_linexpr0_t* linexpr0;   /* expression */
  ap_constyp_t constyp;      /* type of constraint */
  ap_scalar_t* scalar;       /* maybe NULL.

				For EQMOD constraint, indicates the
				modulo */
@} ap_lincons0_t;
@end example
Datatype for constraints.

Constraints are meant to be manipulated freely via their components. Creating the constraint @code{[1,2]x0 + 5/2x1 >=0} and then freeing it can be done with
@example
ap_lincons0_t cons = ap_lincons0_make(AP_CONS_SUPEQ,
				      ap_linexpr0_alloc(AP_LINEXPR_SPARSE,2),
                                      NULL);
ap_linexpr0_set_list(cons.linexpr0,
		     AP_COEFF_I_INT, 1,2, 0,
		     AP_COEFF_S_FRAC, 5,2, 1,
		     AP_END);
ap_lincons0_clear(&cons);
@end example
@end deftp

@deftp datatype ap_lincons0_array_t
@example
typedef struct ap_lincons0_array_t @{
  ap_lincons0_t* p;
  size_t size;
@} ap_lincons0_array_t;
@end example
Datatype for arrays of constraints.

Arrays are accessed directly, for example by writing
@code{array->p[i]} (of type @code{ap_lincons0_t}),
@code{array->p[i].constyp} and @code{array->p[i].linexpr0}.

One can assign a constraint to the index @var{index} by writing:
@code{array->p[index] = ap_lincons0_make(constyp,expr)}.
@end deftp

@menu
* Allocating linear constraints of level 0::
* Tests on linear constraints of level 0::
* Arrays of linear constraints of level 0::
* Change of dimensions and permutations of linear constraints of level 0::
@end menu

@c -------------------------------------------------------------------
@node Allocating linear constraints of level 0, Tests on linear constraints of level 0, Linear constraints of level 0, Linear constraints of level 0
@subsection Allocating linear constraints of level 0
@c -------------------------------------------------------------------

@deftypefun ap_lincons0_t ap_lincons0_make (ap_constyp_t @var{constyp}, ap_linexpr0_t* @var{linexpr}, ap_scalar_t* @var{mod})
Create a constraint of type @var{constyp} with the expression
@var{linexpr}, and the modulo @var{mod} in case of a congruence
constraint (@code{constyp==AP_CONS_EQMOD}).

The expression is not duplicated, just pointed to, so it becomes
managed via the constraint.
@end deftypefun

@deftypefun ap_lincons0_t ap_lincons0_make_unsat ()
Create the constraint @code{-1>=0}.
@end deftypefun

@deftypefun ap_lincons0_t ap_lincons0_copy (ap_lincons0_t* @var{cons})
Duplication
@end deftypefun

@deftypefun void ap_lincons0_clear (ap_lincons0_t* @var{cons})
Clear the constraint.
@end deftypefun

@deftypefun void ap_lincons0_fprint (FILE* @var{stream}, ap_lincons0_t* @var{cons}, char** @var{name_of_dim});
Print the linear constraint on stream @var{stream}, using the array
@var{name_of_dim} to convert dimensions to variable names. If
@var{name_of_dim} is @code{NULL}, the dimensions are named
@code{x0,x1,...}.
@end deftypefun

@c -------------------------------------------------------------------
@node Tests on linear constraints of level 0, Arrays of linear constraints of level 0, Allocating linear constraints of level 0, Linear constraints of level 0
@subsection Tests on linear constraints of level 0
@c -------------------------------------------------------------------

@deftypefun bool ap_lincons0_is_unsat (ap_lincons0_t* @var{cons})
Return @code{true} if the constraint is not satisfiable.
@end deftypefun


@c -------------------------------------------------------------------
@node Arrays of linear constraints of level 0, Change of dimensions and permutations of linear constraints of level 0, Tests on linear constraints of level 0, Linear constraints of level 0
@subsection Arrays of linear constraints of level 0
@c -------------------------------------------------------------------

@deftypefun ap_lincons0_array_t ap_lincons0_array_make (size_t @var{size})
Allocate an array of size constraints.

The constraints are initialized with NULL pointers for underlying
expressions.
@end deftypefun

@deftypefun void ap_lincons0_array_clear (ap_lincons0_array_t* @var{array})
Clear the constraints of the array, and then the array itself.
@end deftypefun

@deftypefun void ap_lincons0_array_fprint (FILE* @var{stream}, ap_lincons0_array_t* @var{array}, char** @var{name_of_dim})
Print the array on the stream.
@end deftypefun

@c -------------------------------------------------------------------
@node Change of dimensions and permutations of linear constraints of level 0,  , Arrays of linear constraints of level 0, Linear constraints of level 0
@subsection Change of dimensions and permutations of linear constraints of level 0
@c -------------------------------------------------------------------

@deftypefun void ap_lincons0_add_dimensions_with (ap_lincons0_t* @var{cons}, ap_dimchange_t* @var{dimchange})
@deftypefunx ap_lincons0_t ap_lincons0_add_dimensions (ap_lincons0_t* @var{cons}, ap_dimchange_t* @var{dimchange})
These two functions add dimensions to the constraint, following
the semantics of dimchange (see the type definition of @code{ap_dimchange_t}).
@end deftypefun

@deftypefun void ap_lincons0_permute_dimensions_with (ap_lincons0_t* @var{cons}, ap_dimperm_t* @var{perm})
@deftypefunx ap_lincons0_t ap_lincons0_permute_dimensions (ap_lincons0_t* @var{cons}, ap_dimperm_t* @var{perm})
These two functions apply the given permutation to the dimensions
of @var{cons}.
@end deftypefun

@deftypefun void ap_lincons0_array_add_dimensions_with (ap_lincons0_array_t* @var{cons}, ap_dimchange_t* @var{dimchange})
@deftypefunx ap_lincons0_array_t ap_lincons0_array_add_dimensions (ap_lincons0_array_t* @var{cons}, ap_dimchange_t* @var{dimchange})
@deftypefunx void ap_lincons0_array_permute_dimensions_with (ap_lincons0_array_t* @var{cons}, ap_dimperm_t* @var{perm})
@deftypefunx ap_lincons0_array_t ap_lincons0_array_permute_dimensions (ap_lincons0_array_t* @var{cons}, ap_dimperm_t* @var{perm})
Extension to arrays of the corresponding functions on constraints.
@end deftypefun

@c ===================================================================
@node Generators of level 0, Tree expressions of level 0, Linear constraints of level 0, Level 0 of the interface
@section Generators of level 0 (@file{ap_generator0.h})
@c ===================================================================

Datatypes and functions are almost isomorphic to datatypes and
functions for linear constraints.

@deftp datatype ap_gentyp_t
@example
typedef enum ap_gentyp_t @{
  AP_GEN_LINE,
  AP_GEN_RAY,
  AP_GEN_VERTEX,
  AP_GEN_LINEMOD,
  AP_GEN_RAYMOD
@} ap_gentyp_t;
@end example
Datatype for type of generators.
@end deftp

@deftp datatype ap_generator0_t
@example
typedef struct ap_generator0_t @{
  ap_linexpr0_t* linexpr0; /* underlying expression.  */
  ap_gentyp_t gentyp;      /* type of generator */
@} ap_generator0_t;
@end example
Datatype for generators.

The constant of the expression is ignored, and the expression is
assumed to be truly linear (without intervals).
@end deftp

@deftp datatype ap_generator0_array_t
@example
typedef struct ap_generator0_array_t @{
  ap_generator0_t* p;
  size_t size;
@} ap_generator0_array_t;
@end example
Datatype for arrays of generators.
@end deftp

@menu
* Allocating generators of level 0::
* Arrays of generators of level 0::
* Change of dimensions and permutations of generators of level 0::
@end menu

@c -------------------------------------------------------------------
@node Allocating generators of level 0, Arrays of generators of level 0, Generators of level 0, Generators of level 0
@subsection Allocating generators of level 0
@c -------------------------------------------------------------------

@deftypefun ap_generator0_t ap_generator0_make (ap_gentyp_t @var{gentyp}, ap_linexpr0_t* @var{linexpr})
Create a generator of type @var{gentyp} with the expression
@var{linexpr}.

The expression is not duplicated, just pointed to, so it becomes
managed via the generator.
@end deftypefun

@deftypefun ap_generator0_t ap_generator0_copy (gent ap_generator0_t* @var{gen})
Duplication
@end deftypefun

@deftypefun void ap_generator0_clear (ap_generator0_t* @var{gen})
Clear the generator.
@end deftypefun

@deftypefun void ap_generator0_fprint (FILE* @var{stream}, gent ap_generator0_t* @var{gen}, char** @var{name_of_dim});
Print the linear generator on stream @var{stream}, using the array
@var{name_of_dim} to convert dimensions to variable names. If
@var{name_of_dim} is @code{NULL}, the dimensions are named
@code{x0,x1,...}.
@end deftypefun

@c -------------------------------------------------------------------
@node Arrays of generators of level 0, Change of dimensions and permutations of generators of level 0, Allocating generators of level 0, Generators of level 0
@subsection Arrays of generators of level 0
@c -------------------------------------------------------------------

Arrays are accessed directly, for example by writing
@code{array->p[i]} (of type @code{ap_generator0_t}),
@code{array->p[i].gentyp} and @code{array->p[i].linexpr0}.

One can assign a generator to the index @var{index} by writing:
@code{array->p[index] = ap_generator0_make(gentyp,expr)}.

@deftypefun ap_generator0_array_t ap_generator0_array_make (size_t @var{size})
Allocate an array of size generators.  The generators are
initialized with NULL pointers for underlying expressions.
@end deftypefun

@deftypefun void ap_generator0_array_clear (ap_generator0_array_t* @var{array})
Clear the generators of the array, and then the array itself.
@end deftypefun

@deftypefun void ap_generator0_array_fprint (FILE* @var{stream}, gent ap_generator0_array_t* @var{array}, char** @var{name_of_dim})
Print the array on the stream.
@end deftypefun

@c -------------------------------------------------------------------
@node Change of dimensions and permutations of generators of level 0,  , Arrays of generators of level 0, Generators of level 0
@subsection Change of dimensions and permutations of generators of level 0
@c -------------------------------------------------------------------

@deftypefun void ap_generator0_add_dimensions_with (ap_generator0_t* @var{gen}, gent ap_dimchange_t* @var{dimchange})
@deftypefunx ap_generator0_t ap_generator0_add_dimensions (gent ap_generator0_t* @var{gen}, gent ap_dimchange_t* @var{dimchange})
These two functions add dimensions to the generator, following
the semantics of dimchange (see the type definition of @code{ap_dimchange_t}).
@end deftypefun

@deftypefun void ap_generator0_permute_dimensions_with (ap_generator0_t* @var{gen}, gent ap_dimperm_t* @var{perm})
@deftypefunx ap_generator0_t ap_generator0_permute_dimensions (gent ap_generator0_t* @var{gen}, gent ap_dimperm_t* @var{perm})
These two functions apply the given permutation to the dimensions
of @var{gen}.
@end deftypefun

@deftypefun void ap_generator0_array_add_dimensions_with (ap_generator0_array_t* @var{gen}, gent ap_dimchange_t* @var{dimchange})
@deftypefunx ap_generator0_array_t ap_generator0_array_add_dimensions (gent ap_generator0_array_t* @var{gen}, gent ap_dimchange_t* @var{dimchange})
@deftypefunx void ap_generator0_array_permute_dimensions_with (ap_generator0_array_t* @var{gen}, gent ap_dimperm_t* @var{perm})
@deftypefunx ap_generator0_array_t ap_generator0_array_permute_dimensions (gent ap_generator0_array_t* @var{gen}, gent ap_dimperm_t* @var{perm})
Extension to arrays of the corresponding functions on generators.
@end deftypefun

@c ===================================================================
@node Tree expressions of level 0, Tree constraints of level 0, Generators of level 0, Level 0 of the interface
@section Tree expressions of level 0 (@file{ap_texpr0.h})
@c ===================================================================

@c ===================================================================
@node Tree constraints of level 0, Abstract values and operations of level 0, Tree expressions of level 0, Level 0 of the interface
@section Tree constraints of level 0 (@file{ap_tcons0.h})
@c ===================================================================

@c ===================================================================
@node Abstract values and operations of level 0,  , Tree constraints of level 0, Level 0 of the interface
@section Abstract values and operations of level 0 (@file{ap_abstract0.h})
@c ===================================================================

@deftp datatype ap_abstract0_t
Datatype for abstract values at level 0.
@end deftp


Most operations are offered in 2 versions: @emph{functional} or
@emph{destructive}. In such a case, the Boolean argument
@var{destructive} controls the behaviour of the functionn:

@itemize
@item
In the @emph{destructive semantics}, after the call the
first abstract value in the arguments of the function is destroyed and
should not be referenced any more. Although the returned value might
actually be equal to the (destroyed) argument, the user just
manipulates the returned value and never refers directly to the
(destroyed) argument.
@item
In the @emph{functional semantics}, the first abstract value in the
arguments is neither (semantically) modified nor deallocated.
@end itemize

@menu
* Allocating abstract values of level 0::
* Control of internal representation of abstract values of level 0::
* Printing abstract values of level 0::
* Serialization of abstract values of level 0::

Constructors, Accessors, Tests and Extraction of properties
* Constructors for abstract values of level 0::
* Accessors for abstract values of level 0::
* Tests on abstract values of level 0::
* Extraction of properties of abstract values of level 0::

Operations
* Meet and Join of abstract values of level 0::
* Assignements and Substitutions of abstract values of level 0::
* Existential quantification of abstract values of level 0::
* Change and permutation of dimensions of abstract values of level 0::
* Expansion and Folding of dimensions in abstract values of level 0::
* Widening of abstract values of level 0::
* Topological closure of abstract values of level 0::

Additional functions
* Additional functions on abstract values of level 0::
@end menu

@c -------------------------------------------------------------------
@node Allocating abstract values of level 0, Control of internal representation of abstract values of level 0, Abstract values and operations of level 0, Abstract values and operations of level 0
@subsection Allocating abstract values of level 0
@c -------------------------------------------------------------------

@deftypefun ap_abstract0_t* ap_abstract0_copy (ap_manager_t* @var{man}, ap_abstract0_t* @var{a})
Return a copy of @var{a}, on which destructive update does not
affect @var{a}.
@end deftypefun

@deftypefun void ap_abstract0_free (ap_manager_t* @var{man}, ap_abstract0_t* @var{a})
Free all the memory used by @var{a}.
@end deftypefun

@deftypefun size_t ap_abstract0_size (ap_manager_t* @var{man}, ap_abstract0_t* @var{a})
Return the abstract size of @var{a}.
@end deftypefun

@c -------------------------------------------------------------------
@node Control of internal representation of abstract values of level 0, Printing abstract values of level 0, Allocating abstract values of level 0, Abstract values and operations of level 0
@subsection Control of internal representation of level 0
@c -------------------------------------------------------------------

@deftypefun void ap_abstract0_minimize (ap_manager_t* @var{man}, ap_abstract0_t* @var{a})
Minimize the size of the representation of @var{a}.  This may result in
a later recomputation of internal information.
@end deftypefun

@deftypefun void ap_abstract0_canonicalize (ap_manager_t* @var{man}, ap_abstract0_t* @var{a})
Put @var{a} in canonical form. (not yet clear definition)
@end deftypefun

@deftypefun int ap_abstract0_hash (ap_manager_t* @var{man}, ap_abstract0_t* @var{a})
Return an hash value for @var{a}.  Two abstract values in canonical
from (according to @code{ap_abstract0_canonicalize}) and considered as
equal by the function @code{ap_abstract0_is_eq} should be given the
same hash value (this implies more or less a canonical form).
@end deftypefun

@deftypefun void ap_abstract0_approximate (ap_manager_t* @var{man}, ap_abstract0_t* @var{a}, int @var{algorithm})
Perform some transformation on @var{a}, guided by the field
algorithm.

The transformation may lose information.  The argument
@var{algorithm} overrides the field algorithm of the structure of
type @code{ap_funopt_t} associated to
@code{ap_abstract0_approximate}.
@end deftypefun

@c -------------------------------------------------------------------
@node Printing abstract values of level 0, Serialization of abstract values of level 0, Control of internal representation of abstract values of level 0, Abstract values and operations of level 0
@subsection Printing abstract values of level 0
@c -------------------------------------------------------------------

@deftypefun void ap_abstract0_fprint (FILE* @var{stream}, ap_manager_t* @var{man}, ap_abstract0_t* @var{a}, char** @var{name_of_dim})
Print @var{a} in a pretty way, using array @var{name_of_dim} to
name dimensions.. If @var{name_of_dim} is @code{NULL}, use the
default names @code{x0, x1, ...}.
@end deftypefun

@deftypefun void ap_abstract0_fprintdiff (FILE* @var{stream}, ap_manager_t* @var{man}, ap_abstract0_t* @var{a1}, ap_abstract0_t* @var{a2}, char** @var{name_of_dim})
Print the difference between @var{a1} (old value) and @var{a2}
(new value), using array @var{name_of_dim} to name dimensions.
The meaning of difference is library dependent.
@end deftypefun

@deftypefun void ap_abstract0_fdump (FILE* @var{stream}, ap_manager_t* @var{man}, ap_abstract0_t* @var{a})
Dump the internal representation of @var{a} for debugging
purposes.
@end deftypefun

@c -------------------------------------------------------------------
@node Serialization of abstract values of level 0, Constructors for abstract values of level 0, Printing abstract values of level 0, Abstract values and operations of level 0
@subsection Serialization of abstract values of level 0
@c -------------------------------------------------------------------
@deftypefun ap_membuf_t ap_abstract0_serialize_raw (ap_manager_t* @var{man}, ap_abstract0_t* @var{a})
Allocate a memory buffer (with @code{malloc}), output @var{a}
in raw binary format to it and return a pointer on the memory
buffer and the number of bytes written.  It is the user
responsability to free the memory afterwards (with free).
@end deftypefun

@deftypefun ap_abstract0_t* ap_abstract0_deserialize_raw (ap_manager_t* @var{man}, void* @var{ptr}, size_t* @var{size})
Return the abstract value read in raw binary format from the
buffer pointed by @var{ptr} and store in size the number of bytes
read.
@end deftypefun

@c -------------------------------------------------------------------
@node Constructors for abstract values of level 0, Accessors for abstract values of level 0, Serialization of abstract values of level 0, Abstract values and operations of level 0
@subsection Constructors for abstract values of level 0
@c -------------------------------------------------------------------

@deftypefun ap_abstract0_t* ap_abstract0_bottom (ap_manager_t* @var{man}, size_t @var{intdim}, size_t @var{realdim})
@deftypefunx ap_abstract0_t* ap_abstract0_top (ap_manager_t* @var{man}, size_t @var{intdim}, size_t @var{realdim})
Create resp. a bottom (empty) value and a top (universe) value
with @var{intdim} integer dimensions and @var{realdim} real
dimensions.
@end deftypefun

@deftypefun ap_abstract0_t* ap_abstract0_of_box (ap_manager_t* @var{man}, size_t @var{intdim}, size_t @var{realdim}, ap_interval_t** @var{array})
Abstract an hypercube defined by the array of intervals
@var{array} of size @var{intdim}+@var{realdim}.
@end deftypefun

@c -------------------------------------------------------------------
@node Accessors for abstract values of level 0, Tests on abstract values of level 0, Constructors for abstract values of level 0, Abstract values and operations of level 0
@subsection Accessors for abstract values of level 0
@c -------------------------------------------------------------------

@deftypefun ap_dimension_t ap_abstract0_dimension (ap_manager_t* @var{man}, ap_abstract0_t* @var{a})
Return the dimensionality of @var{a}.
@end deftypefun

@c -------------------------------------------------------------------
@node Tests on abstract values of level 0, Extraction of properties of abstract values of level 0, Accessors for abstract values of level 0, Abstract values and operations of level 0
@subsection Tests on abstract values of level 0
@c -------------------------------------------------------------------

In abstract tests,
@itemize
@item 
true means that the predicate is certainly true;
@item 
false means false @emph{or} don't know (an exception has occurred, or
the exact computation was considered too expensive to be performed,
according to the options).
@end itemize

@deftypefun bool ap_abstract0_is_bottom (ap_manager_t* @var{man}, ap_abstract0_t* @var{a})
@deftypefunx bool ap_abstract0_is_top (ap_manager_t* @var{man}, ap_abstract0_t* @var{a})
Emtpiness and universality tests.
@end deftypefun

@deftypefun bool ap_abstract0_is_leq (ap_manager_t* @var{man}, ap_abstract0_t* @var{a1}, ap_abstract0_t* @var{a2})
@deftypefunx bool ap_abstract0_is_eq (ap_manager_t* @var{man}, ap_abstract0_t* @var{a1}, ap_abstract0_t* @var{a2})
Inclusion and equality tests.
@end deftypefun

@deftypefun bool ap_abstract0_sat_interval (ap_manager_t* @var{man}, ap_abstract0_t* @var{a}, ap_dim_t @var{dim}, ap_interval_t* @var{interval})
Is the dimension @var{dim} included in the interval @var{interval} in the abstract value @var{a} ?
@end deftypefun

@deftypefun bool ap_abstract0_sat_lincons (ap_manager_t* @var{man}, ap_abstract0_t* @var{a}, ap_lincons0_t* @var{cons})
@deftypefunx bool ap_abstract0_sat_tcons (ap_manager_t* @var{man}, ap_abstract0_t* @var{a}, ap_tcons0_t* @var{cons})
Does the abstract value @var{a} satisfy the constraint @var{cons} ?
@end deftypefun

@deftypefun bool ap_abstract0_is_dimension_unconstrained (ap_manager_t* @var{man}, ap_abstract0_t* @var{a}, ap_dim_t @var{dim})
Is the dimension @var{dim} unconstrained in the abstract value @var{a} ?
If it is the case, we have @code{forget(man,a,dim) == a}.
@end deftypefun

@c -------------------------------------------------------------------
@node Extraction of properties of abstract values of level 0, Meet and Join of abstract values of level 0, Tests on abstract values of level 0, Abstract values and operations of level 0
@subsection Extraction of properties of abstract values of level 0
@c -------------------------------------------------------------------

@deftypefun ap_interval_t* ap_abstract0_bound_dimension (ap_manager_t* @var{man}, ap_abstract0_t* @var{a}, ap_dim_t @var{dim})
Return the interval taken by the dimension @var{dim} over the
abstract value@var{a}
@end deftypefun

@deftypefun ap_interval_t* ap_abstract0_bound_linexpr (ap_manager_t* @var{man}, ap_abstract0_t* @var{a}, ap_linexpr0_t* @var{expr})
@deftypefunx ap_interval_t* ap_abstract0_bound_texpr (ap_manager_t* @var{man}, ap_abstract0_t* @var{a}, ap_texpr0_t* @var{expr})
Return the interval taken by a linear expression @var{expr} over
the abstract value @var{a}.

This function allows to solve a Linear Programming (LP) problem, but
depending on the underlying domain the solution may be not optimal.
@end deftypefun

@deftypefun ap_interval_t** ap_abstract0_to_box (ap_manager_t* @var{man}, ap_abstract0_t* @var{a})
Convert @var{a} to an interval/hypercube.
The size of the resulting array is ap_abstract0_dimension(man,a).
@end deftypefun

@deftypefun ap_lincons0_array_t ap_abstract0_to_lincons_array (ap_manager_t* @var{man}, ap_abstract0_t* @var{a})
@deftypefunx ap_tcons0_array_t ap_abstract0_to_tcons_array (ap_manager_t* @var{man}, ap_abstract0_t* @var{a})
Convert @var{a} to a conjunction of constraints.

The constraints are normally guaranteed to be scalar (without
intervals)
@end deftypefun

@deftypefun ap_generator0_array_t ap_abstract0_to_generator_array (ap_manager_t* @var{man}, ap_abstract0_t* @var{a})
Convert @var{a} to an array of generators.
@end deftypefun

@c -------------------------------------------------------------------
@node Meet and Join of abstract values of level 0, Assignements and Substitutions of abstract values of level 0, Extraction of properties of abstract values of level 0, Abstract values and operations of level 0
@subsection Meet and Join of abstract values of level 0
@c -------------------------------------------------------------------

@deftypefun ap_abstract0_t* ap_abstract0_meet (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract0_t* @var{a1}, ap_abstract0_t* @var{a2})

@deftypefunx ap_abstract0_t* ap_abstract0_join (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract0_t* @var{a1}, ap_abstract0_t* @var{a2})
Meet and Join of 2 abstract values
@end deftypefun


@deftypefun ap_abstract0_t* ap_abstract0_meet_array (ap_manager_t* @var{man}, ap_abstract0_t** @var{array}, size_t @var{size})

@deftypefunx ap_abstract0_t* ap_abstract0_join_array (ap_manager_t* @var{man}, ap_abstract0_t** @var{array}, size_t @var{size})
Meet and Join of the array @var{array} of abstract values of size
@var{size}.

Raise an @code{AP_EXC_INVALID_ARGUMENT} exception if
@code{size==0} (no way to define the dimensionality of the result
in such a case).
@end deftypefun


@deftypefun ap_abstract0_t* ap_abstract0_meet_lincons_array (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract0_t* @var{a}, ap_lincons0_array_t* @var{array})
@deftypefunx ap_abstract0_t* ap_abstract0_meet_tcons_array (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract0_t* @var{a}, ap_tcons0_array_t* @var{array})
Meet of the abstract value @var{a} with the set of constraints
@var{array}.

@var{array} should have exactly the same dimensionality as
@var{a}.
@end deftypefun

@deftypefun ap_abstract0_t* ap_abstract0_add_ray_array (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract0_t* @var{a}, ap_generator0_array_t* @var{array})
Generalized time elapse operator.

@var{array} is supposed to contain only rays or lines, no vertices.

@var{array} should have exactly the same dimensionality as
@var{a}.
@end deftypefun

@c -------------------------------------------------------------------
@node Assignements and Substitutions of abstract values of level 0, Existential quantification of abstract values of level 0, Meet and Join of abstract values of level 0, Abstract values and operations of level 0
@subsection Assignements and Substitutions of abstract values of level 0
@c -------------------------------------------------------------------

@deftypefun ap_abstract0_t* ap_abstract0_assign_linexpr_array (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract0_t* @var{org}, ap_dim_t* @var{tdim}, ap_linexpr0_t** @var{texpr}, size_t @var{size}, ap_abstract0_t* @var{dest})
@deftypefunx ap_abstract0_t* ap_abstract0_substitute_linexpr_array (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract0_t* @var{org}, ap_dim_t* @var{tdim}, ap_linexpr0_t** @var{texpr}, size_t @var{size}, ap_abstract0_t* @var{dest})
@deftypefunx ap_abstract0_t* ap_abstract0_assign_texpr_array (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract0_t* @var{org}, ap_dim_t* @var{tdim}, ap_texpr0_t** @var{texpr}, size_t @var{size}, ap_abstract0_t* @var{dest})
@deftypefunx ap_abstract0_t* ap_abstract0_substitute_texpr_array (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract0_t* @var{org}, ap_dim_t* @var{tdim}, ap_texpr0_t** @var{texpr}, size_t @var{size}, ap_abstract0_t* @var{dest})
Parallel Assignement and Substitution of several dimensions by
expressions in abstract value @var{org}.

@var{dest} is an optional argument. If not NULL, semantically speaking,
the result of the transformation is intersected with @var{dest}. This is
useful for precise backward transformations in lattices like intervals or
octagons.
@end deftypefun

@c -------------------------------------------------------------------
@node Existential quantification of abstract values of level 0, Change and permutation of dimensions of abstract values of level 0, Assignements and Substitutions of abstract values of level 0, Abstract values and operations of level 0
@subsection Existential quantification of abstract values of level 0
@c -------------------------------------------------------------------

@deftypefun ap_abstract0_t* ap_abstract0_forget_array (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract0_t* @var{a}, ap_dim_t* @var{tdim}, size_t @var{size}, bool @var{project})
Forget (@code{project=false}) or Project (@code{project=true}) the
array of dimensions @var{tdim} of size @var{size} in the abstract
value @var{a}.
@end deftypefun

@c -------------------------------------------------------------------
@node Change and permutation of dimensions of abstract values of level 0, Expansion and Folding of dimensions in abstract values of level 0, Existential quantification of abstract values of level 0, Abstract values and operations of level 0
@subsection Change and permutation of dimensions of abstract values of level 0
@c -------------------------------------------------------------------

@deftypefun ap_abstract0_t* ap_abstract0_add_dimensions (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract0_t* @var{a}, ap_dimchange_t* @var{dimchange}, bool @var{project})
@deftypefunx ap_abstract0_t* ap_abstract0_remove_dimensions (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract0_t* @var{a}, ap_dimchange_t* @var{dimchange})
Addition and Removal of dimensions in @var{a} according to
@var{dimchange}. In the case of addition, new dimensions are either
unconstrained (@code{project==false}) or initialized to 0
((@code{project==true}).
@end deftypefun

@deftypefun ap_abstract0_t* ap_abstract0_apply_dimchange2 (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract0_t* @var{a}, ap_dimchange2_t* @var{dimchange2}, bool @var{project})
Apply the transformation specified by @var{dimchange2}. New dimensions
are either unconstrained (@code{project==false}) or initialized to 0
((@code{project==true}).
@end deftypefun

@deftypefun ap_abstract0_t* ap_abstract0_permute_dimensions (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract0_t* @var{a}, ap_dimperm_t* @var{perm})
Permute the dimensions of @var{a} according to the permutation @var{perm}.

The size of the permutation is supposed to be large enough w.r.t. @var{a}.
@end deftypefun

@c -------------------------------------------------------------------
@node Expansion and Folding of dimensions in abstract values of level 0, Widening of abstract values of level 0, Change and permutation of dimensions of abstract values of level 0, Abstract values and operations of level 0
@subsection Expansion and Folding of dimensions of abstract values of level 0
@c -------------------------------------------------------------------

Formally, expanding @code{z} into @code{z} and @code{w} in
abstract value (predicate) @code{P} is defined by
@math{expand(P(x,y,z),z,w) = P(x,y,z) and P(x,y,w)}.

Conversely, folding @code{z} and @code{w} into @code{z} in
abstract value (predicate) @code{Q} is defined by
@math{fold(Q(x,y,z,w),z,w) = (exists w: Q(x,y,z,w)) or (exists z:Q(x,y,z,w)[z<-w])}.

@deftypefun ap_abstract0_t* ap_abstract0_expand (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract0_t* @var{a}, ap_dim_t @var{dim}, size_t @var{n})
Expand the dimension @var{dim} into itself + @var{n} additional dimensions.

It results in @code{n+1} unrelated dimensions having same
relations with other dimensions. The @var{n+1} dimensions are put as follows:
@itemize
@item original dimension @var{dim};
@item if @var{dim} is integer, the @var{n} additional dimensions are put at the
end of integer dimensions; if it is real, at the end of the real
dimensions.
@end itemize
@end deftypefun

@deftypefun ap_abstract0_t* ap_abstract0_fold (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract0_t* @var{a}, ap_dim_t* @var{tdim}, size_t @var{size})
Fold the dimensions in the array @var{tdim} of size @var{size}>=1 and
put the result in the first dimension in the array @emph{assumed to be
sorted}. The other dimensions of the array are then removed.
@end deftypefun

@c -------------------------------------------------------------------
@node Widening of abstract values of level 0, Topological closure of abstract values of level 0, Expansion and Folding of dimensions in abstract values of level 0, Abstract values and operations of level 0
@subsection Widening of abstract values of level 0
@c -------------------------------------------------------------------

@deftypefun ap_abstract0_t* ap_abstract0_widening (ap_manager_t* @var{man}, ap_abstract0_t* @var{a1}, ap_abstract0_t* @var{a2})
Widening of @var{a1} with @var{a2}. @var{a1} is supposed to be
included in @var{a2}.
@end deftypefun

@c -------------------------------------------------------------------
@node Topological closure of abstract values of level 0, Additional functions on abstract values of level 0, Widening of abstract values of level 0, Abstract values and operations of level 0
@subsection Topological closure of abstract values of level 0
@c -------------------------------------------------------------------

@deftypefun ap_abstract0_t* ap_abstract0_closure (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract0_t* @var{a})
Relax strict constraints into non strict constraints.
@end deftypefun

@c -------------------------------------------------------------------
@node Additional functions on abstract values of level 0,  , Topological closure of abstract values of level 0, Abstract values and operations of level 0
@subsection Additional functions on abstract values of level 0
@c -------------------------------------------------------------------

These functions do not have corresponding functions into underlying libraries.

@deftypefun ap_manager_t* ap_abstract0_manager (ap_abstract0_t* @var{a})
Return a reference to the manager contained in @var{a}.

The reference should not be freed.
@end deftypefun

@deftypefun ap_abstract0_t* ap_abstract0_of_lincons_array (ap_manager_t* @var{man}, size_t @var{intdim}, size_t @var{realdim}, ap_lincons0_array_t* @var{array})
@deftypefunx ap_abstract0_t* ap_abstract0_of_tcons_array (ap_manager_t* @var{man}, size_t @var{intdim}, size_t @var{realdim}, ap_tcons0_array_t* @var{array})
Abstract a conjunction of constraints. The constraints in the array should
have exactly the dimensions (@var{intdim},@var{realdim}).
@end deftypefun

@deftypefun ap_abstract0_t* ap_abstract0_assign_linexpr (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract0_t* @var{org}, ap_dim_t @var{dim}, ap_linexpr0_t* @var{expr}, ap_abstract0_t* @var{dest})
@deftypefunx ap_abstract0_t* ap_abstract0_substitute_linexpr (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract0_t* @var{org}, ap_dim_t @var{dim}, ap_linexpr0_t* @var{expr}, ap_abstract0_t* @var{dest})
@deftypefunx ap_abstract0_t* ap_abstract0_assign_texpr (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract0_t* @var{org}, ap_dim_t @var{dim}, ap_texpr0_t* @var{expr}, ap_abstract0_t* @var{dest})
@deftypefunx ap_abstract0_t* ap_abstract0_substitute_texpr (ap_manager_t* @var{man}, bool @var{destructive}, ap_abstract0_t* @var{org}, ap_dim_t @var{dim}, ap_texpr0_t* @var{expr}, ap_abstract0_t* @var{dest})
Assignement and Substitution of the dimension @var{dim} by the
expression @var{expr} in abstract value @var{org}.

@var{dest} is an optional argument. If not NULL, semantically
speaking, the result of the transformation is intersected with
@var{dest}. This is useful for precise backward transformations in
lattices like intervals or octagons.
@end deftypefun


@deftypefun ap_abstract0_t* ap_abstract0_widening_threshold (ap_manager_t* @var{man}, ap_abstract0_t* @var{a1}, ap_abstract0_t* @var{a2}, ap_lincons0_array_t* @var{array})
Widening with threshold.

Intersect the result of the standard widening with all the
constraints in @var{array} that are satisfied by both @var{a1} and
@var{a2}.
@end deftypefun

@c *******************************************************************
@node Functions for implementors, Examples, Level 0 of the interface, Top
@chapter Functions for implementors
@c *******************************************************************

The signatures and documentation of these functions are
provided by the files @file{ap_generic.h},
@file{ap_linearize.h} and @file{ap_reducedproduct.h}.

These functions are dedicated to implementors of underlying
libraries. They offer generic default implementations for some of
the operations required by the APRON API, when there is no more
specific and efficient implementation for the domain being
implemented.

To use one of these, the function allocating manager, which is
specific to the domain, should put the corresponding pointer in
the virtual table to such a generic implementation.

They manipulated "unboxed" abstract values, which are native to
the underlying library: they are not yet boxed with the manager in
the type @code{ap_abstract0_t}.

@c *******************************************************************
@node Examples, Appendices, Functions for implementors, Top
@chapter Examples
@c *******************************************************************

Look at the examples in the @samp{example} subdirectoy of the full
distribution, or click on the links below:

@ifhtml
@uref{example1.c}

@uref{mlexample1.ml}
@uref{mlexample2.ml}
@uref{mlexample3.ml}
@end ifhtml

@c *******************************************************************
@node Appendices,  , Examples, Top
@appendix Appendices
@c *******************************************************************

@menu
* C Datatype Index::
* C Variable Index::
* C Function Index::
@end menu

@c ===================================================================
@node C Datatype Index, C Variable Index, Appendices, Appendices
@appendixsec C Datatype Index
@printindex tp
@c ===================================================================
@page
@c ===================================================================
@node C Variable Index, C Function Index, C Datatype Index, Appendices
@appendixsec C Variable Index
@c ===================================================================
@printindex vr
@page

@c ===================================================================
@node C Function Index,  , C Variable Index, Appendices
@appendixsec C Function Index
@c ===================================================================
@printindex fn
@page

@bye
