/* -*- mode: c -*- */

quote(C,"#include \"ap_global0.h\"")
quote(C,"#include \"apron_caml.h\"")
quote(C,"#include \"ap_pkgrid.h\"")

import "manager.idl";
import "abstract0.idl";

quote(MLMLI,"(** Reduced product of NewPolka polyhedra and PPL grids *)")

quote(MLMLI,"
(** Type of abstract values, where ['a] is [Polka.loose] or [Polka.strict]. *)\n\
type 'a t
")

quote(MLI,"(** Create a PolkaGrid manager from a (loose or strict) polka manager, and a PPL grid manager *)")
ap_manager_ptr ap_pkgrid_manager_alloc(ap_manager_ptr manpk, ap_manager_ptr manpplgrid)
quote(call,"
_res = ap_pkgrid_manager_alloc(manpk,manpplgrid);
if (_res==NULL) caml_failwith(\"PolkaGrid.manager_alloc: the provided polka manager is most probably an equalities polka manager\");
{ ap_exc_t i;
for (i=1; i<AP_EXC_SIZE; i++){
ap_manager_set_abort_if_exception(_res,i,false);
}}
");

quote(MLI,"(** Decompose the manager *)")
void ap_pkgrid_manager_decompose(ap_manager_ptr man, [out]ap_manager_ptr manpk, [out]ap_manager_ptr manpplgrid)
quote(call,"
ap_reducedproduct_internal_t* intern = (ap_reducedproduct_internal_t*)man->internal;
manpk = ap_manager_copy(intern->tmanagers[0]);
manpplgrid = ap_manager_copy(intern->tmanagers[1]);
");

quote(MLI,"(** Decompose an abstract value *)")
void ap_pkgrid_decompose(ap_abstract0_ptr abs, [out]ap_abstract0_ptr abspk, [out]ap_abstract0_ptr abspplgrid)
quote(call,"
{
ap_reducedproduct_internal_t* intern = (ap_reducedproduct_internal_t*)abs->man->internal;
ap_manager_t* manpk = intern->tmanagers[0];
ap_manager_t* manpplgrid = intern->tmanagers[1];
void** res = ap_reducedproduct_decompose(abs->man,false,(ap_reducedproduct_t*)abs->value);
abspk = (ap_abstract0_t*)malloc(sizeof(ap_abstract0_t));
abspk->man = ap_manager_copy(manpk);
abspk->value = res[0];
abspplgrid = (ap_abstract0_t*)malloc(sizeof(ap_abstract0_t));
abspplgrid->man = ap_manager_copy(manpplgrid);
abspplgrid->value = res[1];
free(res);
}
")
quote(dealloc,"I0_CHECK_EXC(abs->man)");

quote(MLI,"(** Compose an abstract value *)")
ap_abstract0_ptr ap_pkgrid_compose(ap_manager_ptr man, ap_abstract0_ptr abspk, ap_abstract0_ptr abspplgrid)
quote(call,"
{
ap_reducedproduct_internal_t* intern = (ap_reducedproduct_internal_t*)man->internal;
ap_manager_t* manpk = intern->tmanagers[0];
ap_manager_t* manpplgrid = intern->tmanagers[1];
void* tabs[2];
tabs[0] = abspk->value;
tabs[1] = abspplgrid->value;
ap_reducedproduct_t* prod = ap_reducedproduct_compose(man,false,tabs);
_res = (ap_abstract0_t*)malloc(sizeof(ap_abstract0_t));
_res->man = ap_manager_copy(man);
_res->value = prod;
}
")
quote(dealloc,"I0_CHECK_EXC(man)");



quote(MLI,"(** {2 Type conversions} *)

val manager_is_polkagrid : 'a Apron.Manager.t -> bool
  (** Return [true] iff the argument manager is a polkagrid manager *)
val manager_of_polkagrid : 'a t Apron.Manager.t -> 'b Apron.Manager.t
  (** Makes a polkagrid manager generic *)
val manager_to_polkagrid : 'a Apron.Manager.t -> 'b t Apron.Manager.t
  (** Instanciate the type of a polkagrid manager. 
      Raises [Failure] if the argument manager is not a polkagrid manager *)

module Abstract0 : sig
  val is_polkagrid : 'a Apron.Abstract0.t -> bool
    (** Return [true] iff the argument manager is a polkagrid value *)
  val of_polkagrid : 'a t Apron.Abstract0.t -> 'b Apron.Abstract0.t
    (** Makes a polkagrid value generic *)
  val to_polkagrid : 'a Apron.Abstract0.t -> 'b t Apron.Abstract0.t
    (** Instanciate the type of a polkagrid value.
	Raises [Failure] if the argument manager is not a polkagrid manager *)
end

module Abstract1 : sig
  val is_polkagrid : 'a Apron.Abstract1.t -> bool
    (** Return [true] iff the argument manager is a polkagrid value *)
  val of_polkagrid : 'a t Apron.Abstract1.t -> 'b Apron.Abstract1.t
    (** Makes a polkagrid value generic *)
  val to_polkagrid : 'a Apron.Abstract1.t -> 'b t Apron.Abstract1.t
    (** Instanciate the type of a polkagrid value.
	Raises [Failure] if the argument manager is not a polkagrid manager *)
end
")

quote(ML,"
let manager_is_polkagrid man =
  let str = Apron.Manager.get_library man in
  let str =
    try String.sub str 0 9
    with Invalid_argument _ -> \"\"
  in
  (String.compare str \"polkagrid\")==0
let manager_of_polkagrid (man:'a t Apron.Manager.t) : 'b Apron.Manager.t = Obj.magic man
let manager_to_polkagrid (man:'a Apron.Manager.t) : 'b t Apron.Manager.t =
  if manager_is_polkagrid man then
    Obj.magic man
  else
    failwith \"PolkaGrid.to_polkagrid: the argument manager is not a polkagrid manager\"

module Abstract0 = struct
  let is_polkagrid abs =
    manager_is_polkagrid (Apron.Abstract0.manager abs)
  let of_polkagrid (abs: 'a t Apron.Abstract0.t) : 'b Apron.Abstract0.t = Obj.magic abs
  let to_polkagrid (abs:'a Apron.Abstract0.t) : 'b t Apron.Abstract0.t =
    if is_polkagrid abs then
      Obj.magic abs
    else
      failwith \"PolkaGrid.Abstract0.to_polkagrid: the argument value is not a polkagrid value\"
end

module Abstract1 = struct
  let is_polkagrid abs =
    manager_is_polkagrid (Apron.Abstract1.manager abs)
  let of_polkagrid (abs: 'a t Apron.Abstract1.t) : 'b Apron.Abstract1.t = Obj.magic abs
  let to_polkagrid (abs:'a Apron.Abstract1.t) : 'b t Apron.Abstract1.t =
    if is_polkagrid abs then
      Obj.magic abs
    else
      failwith \"PolkaGrid.Abstract1.to_polkagrid: the argument value is not a polkagrid value\"
end
")
quote(MLI,"\n(**

{2 Compilation information}

See {!Introduction.compilation} for complete explanations.
We just show examples with the file [mlexample.ml].

Do not forget the [-cc \"g++\"] option: PPL is a C++ library which requires
a C++ linker.

{3 Bytecode compilation}

{[ocamlc -cc \"g++\"-I $MLGMPIDL_PREFIX/lib -I $APRON_PREFIX/lib -o mlexample.byte \\
  bigarray.cma gmp.cma apron.cma polkaMPQ.cma ppl.cma polkaGrid.cma mlexample.ml]}

{[ocamlc -cc \"g++\" -I $MLGMPIDL_PREFIX/lib -I $APRON_PREFIX/lib -make-runtime -o myrun \\
  bigarray.cma gmp.cma apron.cma polkaMPQ.cma ppl.cma polkaGrid.cma 

ocamlc -cc \"g++\" -I $MLGMPIDL_PREFIX/lib -I $APRON_PREFIX/lib -use-runtime myrun -o mlexample.byte \\
  bigarray.cma gmp.cma apron.cma polkaMPQ.cma ppl.cma polkaGrid.cma mlexample.ml ]}

{3 Native-code compilation}

{[ocamlopt -cc \"g++\" -I $MLGMPIDL_PREFIX/lib -I $APRON_PREFIX/lib -o mlexample.opt \\
  bigarray.cmxa gmp.cmxa apron.cmxa polkaMPQ.cmxa ppl.cmxa polkaGrid.cmxa mlexample.ml ]}

{3 Without auto-linking feature}

{[ocamlopt -cc \"g++\" -I $MLGMPIDL_PREFIX/lib -I $APRON_PREFIX/lib -noautolink -o mlexample.opt \\
  bigarray.cmxa gmp.cmxa apron.cmxa polkaMPQ.cmxa ppl.cmxa polkaGrid.cmxa mlexample.ml \\
  -cclib \"-L$MLGMPIDL_PREFIX/lib -L$APRON_PREFIX/lib -L$PPL_PREFIX/lib \\
          -lpolkaGrid_caml_debug -lap_pkgrid_debug \\
          -lpolkaMPQ_caml_debug -lpolkaMPQ_debug \\
	  -lap_ppl_caml_debug -lap_ppl_debug -lppl -lgmpxx \\
	  -lapron_caml_debug -lapron_debug \\
	  -lgmp_caml -L$MPFR_PREFIX/lib -lmpfr -L$GMP_PREFIX/lib -lgmp \\
	  -L$CAMLIDL_PREFIX/lib/ocaml -lcamlidl \\
	  -lbigarray\" ]}
*)")
