diff --git a/farith2/.ocamlformat b/farith2/.ocamlformat
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/farith2/dune b/farith2/dune
index d5e22754d91cf47e52cc5c78df0148c1aba5cd07..8d6039c4896b8c3bb7a07b07443a80919ec0498b 100644
--- a/farith2/dune
+++ b/farith2/dune
@@ -1,7 +1,9 @@
 (library
  (name farith2)
  (public_name farith2)
- (libraries zarith)
+ (libraries zarith base)
+ (preprocess
+  (pps ppx_deriving.std ppx_hash))
  (flags "-w" "-33"))
 
 (copy_files# extracted/*.ml*)
diff --git a/farith2/extract/dune b/farith2/extract/dune
index 86a346fe2db88f1efe868a267c119af7ae075995..5645e69840044ec826f60b4b819cc8ae87c3c75a 100644
--- a/farith2/extract/dune
+++ b/farith2/extract/dune
@@ -1,5 +1,5 @@
 (coq.extraction
  (prelude extraction)
- (extracted_modules B32 BinNums Bool Qextended Utils Binary BinPosDef Datatypes Round Zaux BinarySingleNaN
-                    BinPos Interval SpecFloat Zbool BinInt Bits Intv32 Specif Zpower Assert GenericFloat)
+ (extracted_modules BinNums Bool Qextended Utils Binary BinPosDef Datatypes Round Zaux BinarySingleNaN
+                    BinPos Interval SpecFloat Zbool BinInt Bits Specif Zpower Assert GenericFloat Version)
  (theories Farith2))
diff --git a/farith2/extract/extraction.v b/farith2/extract/extraction.v
index 136f563fb14a6a90e9316d6b8a717cdf853fcf0f..0a05276a59ac9d81ea4e3936bc30d489a3af32e0 100644
--- a/farith2/extract/extraction.v
+++ b/farith2/extract/extraction.v
@@ -1,18 +1,18 @@
-From Flocq Require Import Core.Zaux IEEE754.BinarySingleNaN IEEE754.Bits.
-From Farith2 Require Import Qextended B32 Intv32 GenericFloat.
+From Flocq Require Import Core.Zaux IEEE754.BinarySingleNaN IEEE754.Bits Version.
+From Farith2 Require Import Qextended GenericFloat.
 From Coq Require Import Extraction Lia Arith.Wf_nat ZArith.
 
-Goal (Beqb (B32.add mode_NE (B32.of_q mode_NE Qx_half) (B32.of_q mode_NE Qx_half)) (B32.of_q mode_NE Qx_one) = true).
-Proof.
-  cbn.
-  reflexivity.
-Qed.
+(* Goal (Beqb (B32.add mode_NE (B32.of_q mode_NE Qx_half) (B32.of_q mode_NE Qx_half)) (B32.of_q mode_NE Qx_one) = true). *)
+(* Proof. *)
+(*   cbn. *)
+(*   reflexivity. *)
+(* Qed. *)
 
-Goal (Beqb (B32.div mode_NE (B32.of_q mode_NE Qx_one) (B32.of_q mode_NE Qx_two)) (B32.of_q mode_NE Qx_half) = true).
-Proof.
-  cbn.
-  reflexivity.
-Qed.
+(* Goal (Beqb (B32.div mode_NE (B32.of_q mode_NE Qx_one) (B32.of_q mode_NE Qx_two)) (B32.of_q mode_NE Qx_half) = true). *)
+(* Proof. *)
+(*   cbn. *)
+(*   reflexivity. *)
+(* Qed. *)
 
 Require Import Sumbool.
 
@@ -269,4 +269,4 @@ Extract Inductive mode => "Farith_Big.mode" [
   "Farith_Big.NE" "Farith_Big.ZR" "Farith_Big.DN" "Farith_Big.UP" "Farith_Big.NA"
 ].
 
-Separate Extraction B32.B32 Intv32 GenericFloat GenericInterval.
+Separate Extraction GenericFloat GenericInterval Flocq.Version.
diff --git a/farith2/extract/farith_Big.ml b/farith2/extract/farith_Big.ml
index 8ed2ad80c7f2fe17020e800bee1fabd883aae142..3ba55d18b0d35b4687e6acccade4b8aebcc8e0aa 100644
--- a/farith2/extract/farith_Big.ml
+++ b/farith2/extract/farith_Big.ml
@@ -14,10 +14,13 @@
 open Big_int_Z
 
 type big_int = Big_int_Z.big_int
+
 (* The type of big integers. *)
 let zero = zero_big_int
+
 (* The big integer [0]. *)
 let one = unit_big_int
+
 (* The big integer [1]. *)
 let two = big_int_of_int 2
 (* The big integer [2]. *)
@@ -25,30 +28,42 @@ let two = big_int_of_int 2
 (* {6 Arithmetic operations} *)
 
 let opp = minus_big_int
+
 (* Unary negation. *)
 let abs = abs_big_int
+
 (* Absolute value. *)
 let add = add_big_int
+
 (* Addition. *)
 let succ = succ_big_int
+
 (* Successor (add 1). *)
 let add_int = add_int_big_int
+
 (* Addition of a small integer to a big integer. *)
 let sub = sub_big_int
+
 (* Subtraction. *)
 let pred = pred_big_int
+
 (* Predecessor (subtract 1). *)
 let mult = mult_big_int
+
 (* Multiplication of two big integers. *)
 let mult_int = mult_int_big_int
+
 (* Multiplication of a big integer by a small integer *)
 let _square = square_big_int
+
 (* Return the square of the given big integer *)
 let sqrt = sqrt_big_int
+
 (* [sqrt_big_int a] returns the integer square root of [a],
     that is, the largest big integer [r] such that [r * r <= a].
     Raise [Invalid_argument] if [a] is negative. *)
 let quomod = quomod_big_int
+
 (* Euclidean division of two big integers.
     The first part of the result is the quotient,
     the second part is the remainder.
@@ -56,12 +71,15 @@ let quomod = quomod_big_int
     [a = q * b + r] and [0 <= r < |b|].
     Raise [Division_by_zero] if the divisor is zero. *)
 let div = div_big_int
+
 (* Euclidean quotient of two big integers.
     This is the first result [q] of [quomod_big_int] (see above). *)
 let modulo = mod_big_int
+
 (* Euclidean modulus of two big integers.
     This is the second result [r] of [quomod_big_int] (see above). *)
 let gcd = gcd_big_int
+
 (* Greatest common divisor of two big integers. *)
 let power = power_big_int_positive_big_int
 (* Exponentiation functions.  Return the big integer
@@ -73,25 +91,35 @@ let power = power_big_int_positive_big_int
 (* {6 Comparisons and tests} *)
 
 let sign = sign_big_int
+
 (* Return [0] if the given big integer is zero,
     [1] if it is positive, and [-1] if it is negative. *)
 let compare = compare_big_int
+
 (* [compare_big_int a b] returns [0] if [a] and [b] are equal,
     [1] if [a] is greater than [b], and [-1] if [a] is smaller
     than [b]. *)
 let eq = eq_big_int
+
 let le = le_big_int
+
 let ge = ge_big_int
+
 let lt = lt_big_int
+
 let gt = gt_big_int
+
 (* Usual boolean comparisons between two big integers. *)
 let max = max_big_int
+
 (* Return the greater of its two arguments. *)
 let min = min_big_int
+
 (* Return the smaller of its two arguments. *)
 (* {6 Conversions to and from strings} *)
 
 let to_string = string_of_big_int
+
 (* Return the string representation of the given big integer,
     in decimal (base 10). *)
 let of_string = big_int_of_string
@@ -102,8 +130,10 @@ let of_string = big_int_of_string
 (* {6 Conversions to and from other numerical types} *)
 
 let of_int = big_int_of_int
+
 (* Convert a small integer to a big integer. *)
 let is_int = is_int_big_int
+
 (* Test whether the given big integer is small enough to
     be representable as a small integer (type [int])
     without loss of precision.  On a 32-bit platform,
@@ -118,15 +148,19 @@ let to_int = int_of_big_int
 
 (* Functions used by extraction *)
 
-let double n = (Z.shift_left n 1)
+let double n = Z.shift_left n 1
+
 let succ_double n = Z.succ (Z.shift_left n 1)
+
 let pred_double n = Z.pred (Z.shift_left n 1)
 
 let nat_case fO fS n = if sign n <= 0 then fO () else fS (pred n)
 
 let positive_case f2p1 f2p f1 p =
-  if le p one then f1 () else
-    let (q,r) = quomod p two in if eq r zero then f2p q else f2p1 q
+  if le p one then f1 ()
+  else
+    let q, r = quomod p two in
+    if eq r zero then f2p q else f2p1 q
 
 let n_case fO fp n = if sign n <= 0 then fO () else fp n
 
@@ -137,20 +171,21 @@ let z_case fO fp fn z =
 let sgn z = Z.of_int (Z.sign z)
 
 let compare_case e l g x y =
-  let s = compare x y in if s = 0 then e else if s<0 then l else g
+  let s = compare x y in
+  if s = 0 then e else if s < 0 then l else g
 
 let nat_rec fO fS =
-  let rec loop acc n =
-    if sign n <= 0 then acc else loop (fS acc) (pred n)
-  in loop fO
+  let rec loop acc n = if sign n <= 0 then acc else loop (fS acc) (pred n) in
+  loop fO
 
 let positive_rec f2p1 f2p f1 =
   let rec loop n =
     if le n one then f1
     else
-      let (q,r) = quomod n two in
+      let q, r = quomod n two in
       if eq r zero then f2p (loop q) else f2p1 (loop q)
-  in loop
+  in
+  loop
 
 let z_rec fO fp fn = z_case (fun _ -> fO) fp fn
 
@@ -160,7 +195,7 @@ let rec nat_rect acc f n =
 let rec iter_nat f n acc =
   if sign n <= 0 then acc else iter_nat f (pred n) (f acc)
 
-external identity: 'a -> 'a = "%identity"
+external identity : 'a -> 'a = "%identity"
 
 let shiftl_pos a p = Z.shift_left a (Z.to_int p)
 
@@ -176,24 +211,23 @@ let div_pos a b =
 
 let square a = Z.mul a a
 
-let pow_pos a p =
-  Z.pow a (Z.to_int p)
+let pow_pos a p = Z.pow a (Z.to_int p)
 
 let div2_trunc n = Z.shift_right_trunc n 1
 
 let div_floor = Z.fdiv
+
 let div2_floor n = Z.shift_right n 1
+
 let mod_floor a b =
   let r = Z.rem a b in
-  if (Stdlib.(lxor) (Z.sign a) (Z.sign b) >= 0) || Z.equal r Z.zero
-  then r
+  if Stdlib.( lxor ) (Z.sign a) (Z.sign b) >= 0 || Z.equal r Z.zero then r
   else Z.add b r
 
 let div_mod_floor a b =
-  let p,r as pr = Z.div_rem a b in
-  if ((Stdlib.(lxor) (Z.sign a) (Z.sign b)) >= 0) || Z.equal r Z.zero
-  then pr
-  else Z.pred p, Z.add b r
+  let ((p, r) as pr) = Z.div_rem a b in
+  if Stdlib.( lxor ) (Z.sign a) (Z.sign b) >= 0 || Z.equal r Z.zero then pr
+  else (Z.pred p, Z.add b r)
 
 let pos_div_eucl a b =
   assert (sign a >= 0);
@@ -202,37 +236,32 @@ let pos_div_eucl a b =
 
 let shiftl a n =
   let n = Z.to_int n in
-  if n < 0 then Z.shift_right a (-n)
-  else Z.shift_left a n
+  if n < 0 then Z.shift_right a (-n) else Z.shift_left a n
 
 let shiftr a n =
   let n = Z.to_int n in
-  if n < 0 then Z.shift_left a (-n)
-  else Z.shift_right a n
+  if n < 0 then Z.shift_left a (-n) else Z.shift_right a n
 
 let ldiff a b = Z.logand a (Z.lognot b)
 
 module Z = Z (* zarith *)
 
-
 (* Q *)
 (* must be already normalize *)
-let q_mk (den,num) = {Q.den; Q.num}
+let q_mk (den, num) = { Q.den; Q.num }
+
 let q_case f q = f q.Q.den q.Q.num
+
 let q_den q = q.Q.den
+
 let q_num q = q.Q.num
 
-type mode =
-  | NE
-  | ZR
-  | DN
-  | UP
-  | NA
+type mode = NE | ZR | DN | UP | NA
 
 type classify =
   | Zero of bool
   | Infinity of bool
-  | NaN of bool * Z.t
+  | NaN
   | Finite of bool * Z.t * Z.t
 
-let combine_hash acc n = n * 65599 + acc
+let combine_hash acc n = (n * 65599) + acc
diff --git a/farith2/extracted/B32.ml b/farith2/extracted/B32.ml
deleted file mode 100644
index 59a32b73f87cfe42b566455c13a4dc3f12353bef..0000000000000000000000000000000000000000
--- a/farith2/extracted/B32.ml
+++ /dev/null
@@ -1,143 +0,0 @@
-open BinInt
-open Binary
-open BinarySingleNaN
-open Bits
-open Datatypes
-open SpecFloat
-
-module B32 =
- struct
-  (** val prec : Farith_Big.big_int **)
-
-  let prec =
-    (Farith_Big.double (Farith_Big.double (Farith_Big.double
-      (Farith_Big.succ_double Farith_Big.one))))
-
-  (** val emax : Farith_Big.big_int **)
-
-  let emax =
-    (Farith_Big.double (Farith_Big.double (Farith_Big.double
-      (Farith_Big.double (Farith_Big.double (Farith_Big.double
-      (Farith_Big.double Farith_Big.one)))))))
-
-  (** val mw : Farith_Big.big_int **)
-
-  let mw =
-    (Farith_Big.succ_double (Farith_Big.succ_double (Farith_Big.succ_double
-      (Farith_Big.double Farith_Big.one))))
-
-  (** val ew : Farith_Big.big_int **)
-
-  let ew =
-    (Farith_Big.double (Farith_Big.double (Farith_Big.double Farith_Big.one)))
-
-  type t = binary_float
-
-  (** val add : Farith_Big.mode -> t -> t -> t **)
-
-  let add =
-    coq_Bplus prec emax
-
-  (** val sub : Farith_Big.mode -> t -> t -> t **)
-
-  let sub =
-    coq_Bminus prec emax
-
-  (** val mult : Farith_Big.mode -> t -> t -> t **)
-
-  let mult =
-    coq_Bmult prec emax
-
-  (** val div : Farith_Big.mode -> t -> t -> t **)
-
-  let div =
-    coq_Bdiv prec emax
-
-  (** val sqrt : Farith_Big.mode -> t -> t **)
-
-  let sqrt =
-    coq_Bsqrt prec emax
-
-  (** val abs : t -> t **)
-
-  let abs =
-    coq_Babs prec emax
-
-  (** val le : t -> t -> bool **)
-
-  let le =
-    coq_Bleb prec emax
-
-  (** val lt : t -> t -> bool **)
-
-  let lt =
-    coq_Bltb prec emax
-
-  (** val eq : t -> t -> bool **)
-
-  let eq =
-    coq_Beqb prec emax
-
-  (** val ge : t -> t -> bool **)
-
-  let ge x y =
-    coq_Bleb prec emax y x
-
-  (** val gt : t -> t -> bool **)
-
-  let gt x y =
-    coq_Bltb prec emax y x
-
-  (** val of_bits : Farith_Big.big_int -> t **)
-
-  let of_bits b =
-    match binary_float_of_bits mw ew b with
-    | Binary.B754_zero s -> B754_zero s
-    | Binary.B754_infinity s -> B754_infinity s
-    | Binary.B754_nan (_, _) -> B754_nan
-    | Binary.B754_finite (s, m, e) -> B754_finite (s, m, e)
-
-  (** val pl_cst : Farith_Big.big_int **)
-
-  let pl_cst =
-    Farith_Big.iter_nat (fun x -> Farith_Big.double x)
-      (Z.to_nat (Farith_Big.pred mw)) Farith_Big.one
-
-  (** val to_bits : t -> Farith_Big.big_int **)
-
-  let to_bits = function
-  | B754_zero s -> bits_of_binary_float mw ew (Binary.B754_zero s)
-  | B754_infinity s -> bits_of_binary_float mw ew (Binary.B754_infinity s)
-  | B754_nan -> bits_of_binary_float mw ew (Binary.B754_nan (true, pl_cst))
-  | B754_finite (s, m, e) ->
-    bits_of_binary_float mw ew (Binary.B754_finite (s, m, e))
-
-  (** val of_q : Farith_Big.mode -> Q.t -> t **)
-
-  let of_q m q =
-    match Q.classify q with
-    | Q.INF -> B754_infinity false
-    | Q.MINF -> B754_infinity true
-    | Q.UNDEF -> B754_nan
-    | Q.ZERO -> B754_zero false
-    | Q.NZERO ->
-      (Farith_Big.z_case
-         (fun _ -> B754_nan)
-         (fun pn ->
-         coq_SF2B prec emax
-           (let (p, lz) =
-              coq_SFdiv_core_binary prec emax pn Farith_Big.zero
-                (Z.to_pos (Farith_Big.q_den q)) Farith_Big.zero
-            in
-            let (mz, ez) = p in
-            binary_round_aux prec emax m (xorb false false) mz ez lz))
-         (fun nn ->
-         coq_SF2B prec emax
-           (let (p, lz) =
-              coq_SFdiv_core_binary prec emax nn Farith_Big.zero
-                (Z.to_pos (Farith_Big.q_den q)) Farith_Big.zero
-            in
-            let (mz, ez) = p in
-            binary_round_aux prec emax m (xorb true false) mz ez lz))
-         (Farith_Big.q_num q))
- end
diff --git a/farith2/extracted/B32.mli b/farith2/extracted/B32.mli
deleted file mode 100644
index e20ce0b7e88057374bc5023cf1911de183703639..0000000000000000000000000000000000000000
--- a/farith2/extracted/B32.mli
+++ /dev/null
@@ -1,49 +0,0 @@
-open BinInt
-open Binary
-open BinarySingleNaN
-open Bits
-open Datatypes
-open SpecFloat
-
-module B32 :
- sig
-  val prec : Farith_Big.big_int
-
-  val emax : Farith_Big.big_int
-
-  val mw : Farith_Big.big_int
-
-  val ew : Farith_Big.big_int
-
-  type t = binary_float
-
-  val add : Farith_Big.mode -> t -> t -> t
-
-  val sub : Farith_Big.mode -> t -> t -> t
-
-  val mult : Farith_Big.mode -> t -> t -> t
-
-  val div : Farith_Big.mode -> t -> t -> t
-
-  val sqrt : Farith_Big.mode -> t -> t
-
-  val abs : t -> t
-
-  val le : t -> t -> bool
-
-  val lt : t -> t -> bool
-
-  val eq : t -> t -> bool
-
-  val ge : t -> t -> bool
-
-  val gt : t -> t -> bool
-
-  val of_bits : Farith_Big.big_int -> t
-
-  val pl_cst : Farith_Big.big_int
-
-  val to_bits : t -> Farith_Big.big_int
-
-  val of_q : Farith_Big.mode -> Q.t -> t
- end
diff --git a/farith2/extracted/GenericFloat.ml b/farith2/extracted/GenericFloat.ml
index c74fcbdfd35eeb098b5cee94487cd6e3874ee6b3..6e801d44faf57e305949d315e692c6dc16b8ba4a 100644
--- a/farith2/extracted/GenericFloat.ml
+++ b/farith2/extracted/GenericFloat.ml
@@ -1,11 +1,54 @@
+open BinInt
+open Binary
 open BinarySingleNaN
+open Bits
+open Datatypes
 open Interval
+open SpecFloat
 
 type __ = Obj.t
+let __ = let rec f _ = Obj.repr f in Obj.repr f
 
-type 'v coq_Generic = { prec : Farith_Big.big_int; emax : Farith_Big.big_int;
+(** val cprec : Farith_Big.big_int -> Farith_Big.big_int **)
+
+let cprec =
+  Farith_Big.succ
+
+(** val cemax : Farith_Big.big_int -> Farith_Big.big_int **)
+
+let cemax ew0 =
+  Z.pow (Farith_Big.double Farith_Big.one) (Farith_Big.sub ew0 Farith_Big.one)
+
+(** val check_param : Farith_Big.big_int -> Farith_Big.big_int -> bool **)
+
+let check_param mw0 ew0 =
+  (&&)
+    ((&&) (Farith_Big.lt Farith_Big.zero mw0)
+      (Farith_Big.lt Farith_Big.zero ew0))
+    (Farith_Big.lt (cprec mw0) (cemax ew0))
+
+type 'v coq_Generic = { mw : Farith_Big.big_int; ew : Farith_Big.big_int;
                         value : 'v }
 
+(** val prec : 'a1 coq_Generic -> Farith_Big.big_int **)
+
+let prec f =
+  cprec f.mw
+
+(** val emax : 'a1 coq_Generic -> Farith_Big.big_int **)
+
+let emax f =
+  cemax f.ew
+
+(** val mk_generic :
+    Farith_Big.big_int -> Farith_Big.big_int -> (Farith_Big.big_int ->
+    Farith_Big.big_int -> __ -> __ -> 'a1) -> 'a1 coq_Generic **)
+
+let mk_generic mw0 ew0 x =
+  let prec0 = cprec mw0 in
+  let emax0 = cemax ew0 in
+  { mw = mw0; ew = ew0; value = (x prec0 emax0 __ __) }
+
 (** val same_format_cast :
     Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int ->
     Farith_Big.big_int -> 'a1 -> 'a1 **)
@@ -16,26 +59,35 @@ let same_format_cast _ _ _ _ f =
 (** val same_format : 'a1 coq_Generic -> 'a2 coq_Generic -> bool **)
 
 let same_format x y =
-  (&&) (Farith_Big.eq x.prec y.prec) (Farith_Big.eq x.emax y.emax)
+  (&&) (Farith_Big.eq (prec x) (prec y)) (Farith_Big.eq (emax x) (emax y))
 
 (** val mk_with : 'a1 coq_Generic -> 'a2 -> 'a2 coq_Generic **)
 
 let mk_with x y =
-  { prec = x.prec; emax = x.emax; value = y }
+  { mw = x.mw; ew = x.ew; value = y }
+
+(** val mk_witho : 'a1 coq_Generic -> 'a2 option -> 'a2 coq_Generic option **)
+
+let mk_witho x = function
+| Some r -> Some (mk_with x r)
+| None -> None
 
 module GenericFloat =
  struct
-  type coq_F = binary_float coq_Generic
+  module Coq__1 = struct
+   type t = binary_float coq_Generic
+  end
+  include Coq__1
 
   module F_inhab =
    struct
-    type t = coq_F
+    type t = Coq__1.t
 
     (** val dummy : binary_float coq_Generic **)
 
     let dummy =
-      { prec = (Farith_Big.double (Farith_Big.double (Farith_Big.double
-        (Farith_Big.succ_double Farith_Big.one)))); emax = (Farith_Big.double
+      { mw = (Farith_Big.double (Farith_Big.double (Farith_Big.double
+        (Farith_Big.succ_double Farith_Big.one)))); ew = (Farith_Big.double
         (Farith_Big.double (Farith_Big.double (Farith_Big.double
         (Farith_Big.double (Farith_Big.double (Farith_Big.double
         Farith_Big.one))))))); value = B754_nan }
@@ -55,53 +107,194 @@ module GenericFloat =
 
   module AssertB = Assert.Assert(B_inhab)
 
-  (** val add :
-      Farith_Big.mode -> coq_F -> coq_F -> binary_float coq_Generic option **)
+  (** val of_q' :
+      Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> Q.t ->
+      binary_float **)
+
+  let of_q' prec0 emax0 m q =
+    match Q.classify q with
+    | Q.INF -> B754_infinity false
+    | Q.MINF -> B754_infinity true
+    | Q.UNDEF -> B754_nan
+    | Q.ZERO -> B754_zero false
+    | Q.NZERO ->
+      (Farith_Big.z_case
+         (fun _ -> B754_nan)
+         (fun pn ->
+         coq_SF2B prec0 emax0
+           (let (p, lz) =
+              coq_SFdiv_core_binary prec0 emax0 pn Farith_Big.zero
+                (Z.to_pos (Farith_Big.q_den q)) Farith_Big.zero
+            in
+            let (mz, ez) = p in
+            binary_round_aux prec0 emax0 m (xorb false false) mz ez lz))
+         (fun nn ->
+         coq_SF2B prec0 emax0
+           (let (p, lz) =
+              coq_SFdiv_core_binary prec0 emax0 nn Farith_Big.zero
+                (Z.to_pos (Farith_Big.q_den q)) Farith_Big.zero
+            in
+            let (mz, ez) = p in
+            binary_round_aux prec0 emax0 m (xorb true false) mz ez lz))
+         (Farith_Big.q_num q))
+
+  (** val of_q :
+      Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> Q.t -> t **)
+
+  let of_q mw0 ew0 m q =
+    (fun x f -> assert x; f ()) (check_param mw0 ew0) (fun _ ->
+      mk_generic mw0 ew0 (fun prec0 emax0 _ _ -> of_q' prec0 emax0 m q))
+
+  (** val add : Farith_Big.mode -> t -> t -> t **)
 
   let add m x y =
-    let filtered_var = same_format x y in
-    if filtered_var
-    then Some { prec = x.prec; emax = x.emax; value =
-           (coq_Bplus x.prec x.emax m x.value
-             (same_format_cast x.prec x.emax y.prec y.emax y.value)) }
-    else None
+    (fun x f -> assert x; f ()) (same_format x y) (fun _ ->
+      mk_with x
+        (coq_Bplus (cprec x.mw) (cemax x.ew) m x.value
+          (same_format_cast (prec x) (emax x) (prec y) (emax y) y.value)))
 
-  (** val coq_Fadd : Farith_Big.mode -> coq_F -> coq_F -> coq_F **)
+  (** val sub : Farith_Big.mode -> t -> t -> t **)
 
-  let coq_Fadd m x y =
+  let sub m x y =
     (fun x f -> assert x; f ()) (same_format x y) (fun _ ->
       mk_with x
-        (coq_Bplus x.prec x.emax m x.value
-          (same_format_cast x.prec x.emax y.prec y.emax y.value)))
+        (coq_Bminus (cprec x.mw) (cemax x.ew) m x.value
+          (same_format_cast (prec x) (emax x) (prec y) (emax y) y.value)))
+
+  (** val mul : Farith_Big.mode -> t -> t -> t **)
+
+  let mul m x y =
+    (fun x f -> assert x; f ()) (same_format x y) (fun _ ->
+      mk_with x
+        (coq_Bmult (cprec x.mw) (cemax x.ew) m x.value
+          (same_format_cast (prec x) (emax x) (prec y) (emax y) y.value)))
+
+  (** val div : Farith_Big.mode -> t -> t -> t **)
+
+  let div m x y =
+    (fun x f -> assert x; f ()) (same_format x y) (fun _ ->
+      mk_with x
+        (coq_Bdiv (cprec x.mw) (cemax x.ew) m x.value
+          (same_format_cast (prec x) (emax x) (prec y) (emax y) y.value)))
+
+  (** val sqrt : Farith_Big.mode -> t -> t **)
+
+  let sqrt m x =
+    mk_with x (coq_Bsqrt (cprec x.mw) (cemax x.ew) m x.value)
+
+  (** val abs : t -> t **)
+
+  let abs x =
+    mk_with x (coq_Babs (cprec x.mw) (cemax x.ew) x.value)
+
+  (** val le : t -> t -> bool **)
+
+  let le x y =
+    (fun x f -> assert x; f ()) (same_format x y) (fun _ ->
+      coq_Bleb (cprec x.mw) (cemax x.ew) x.value
+        (same_format_cast (prec x) (emax x) (prec y) (emax y) y.value))
+
+  (** val lt : t -> t -> bool **)
+
+  let lt x y =
+    (fun x f -> assert x; f ()) (same_format x y) (fun _ ->
+      coq_Bltb (cprec x.mw) (cemax x.ew) x.value
+        (same_format_cast (prec x) (emax x) (prec y) (emax y) y.value))
+
+  (** val eq : t -> t -> bool **)
+
+  let eq x y =
+    (fun x f -> assert x; f ()) (same_format x y) (fun _ ->
+      coq_Beqb (cprec x.mw) (cemax x.ew) x.value
+        (same_format_cast (prec x) (emax x) (prec y) (emax y) y.value))
 
-  (** val coq_Fsub : Farith_Big.mode -> coq_F -> coq_F -> coq_F **)
+  (** val ge : t -> t -> bool **)
 
-  let coq_Fsub m x y =
-    (fun x f -> assert x; f ()) (same_format x y) (fun _ -> { prec = x.prec;
-      emax = x.emax; value =
-      (coq_Bminus x.prec x.emax m x.value
-        (same_format_cast x.prec x.emax y.prec y.emax y.value)) })
+  let ge x y =
+    (fun x f -> assert x; f ()) (same_format x y) (fun _ ->
+      coq_Bleb (cprec x.mw) (cemax x.ew)
+        (same_format_cast (prec x) (emax x) (prec y) (emax y) y.value) x.value)
+
+  (** val gt : t -> t -> bool **)
+
+  let gt x y =
+    (fun x f -> assert x; f ()) (same_format x y) (fun _ ->
+      coq_Bltb (cprec x.mw) (cemax x.ew)
+        (same_format_cast (prec x) (emax x) (prec y) (emax y) y.value) x.value)
+
+  (** val of_bits' :
+      Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int ->
+      binary_float **)
+
+  let of_bits' mw0 ew0 b =
+    let filtered_var = binary_float_of_bits mw0 ew0 b in
+    (match filtered_var with
+     | Binary.B754_zero s -> B754_zero s
+     | Binary.B754_infinity s -> B754_infinity s
+     | Binary.B754_nan (_, _) -> B754_nan
+     | Binary.B754_finite (s, m, e) -> B754_finite (s, m, e))
+
+  (** val of_bits : Farith_Big.big_int -> Farith_Big.big_int -> Z.t -> t **)
+
+  let of_bits mw0 ew0 z =
+    (fun x f -> assert x; f ()) (check_param mw0 ew0) (fun _ -> { mw = mw0;
+      ew = ew0; value = (of_bits' mw0 ew0 z) })
+
+  (** val pl_cst : Farith_Big.big_int -> Farith_Big.big_int **)
+
+  let pl_cst mw0 =
+    Farith_Big.iter_nat (fun x -> Farith_Big.double x)
+      (Z.to_nat (Farith_Big.pred mw0)) Farith_Big.one
+
+  (** val to_bits : t -> Farith_Big.big_int **)
+
+  let to_bits f =
+    match f.value with
+    | B754_zero s -> bits_of_binary_float f.mw f.ew (Binary.B754_zero s)
+    | B754_infinity s ->
+      bits_of_binary_float f.mw f.ew (Binary.B754_infinity s)
+    | B754_nan ->
+      bits_of_binary_float f.mw f.ew (Binary.B754_nan (true, (pl_cst f.mw)))
+    | B754_finite (s, m, e) ->
+      bits_of_binary_float f.mw f.ew (Binary.B754_finite (s, m, e))
+
+  (** val nan : Farith_Big.big_int -> Farith_Big.big_int -> t **)
+
+  let nan mw0 ew0 =
+    (fun x f -> assert x; f ()) (check_param mw0 ew0) (fun _ ->
+      mk_generic mw0 ew0 (fun _ _ _ _ -> B754_nan))
+
+  (** val zero : Farith_Big.big_int -> Farith_Big.big_int -> bool -> t **)
+
+  let zero mw0 ew0 b =
+    (fun x f -> assert x; f ()) (check_param mw0 ew0) (fun _ ->
+      mk_generic mw0 ew0 (fun _ _ _ _ -> B754_zero b))
+
+  (** val inf : Farith_Big.big_int -> Farith_Big.big_int -> bool -> t **)
+
+  let inf mw0 ew0 b =
+    (fun x f -> assert x; f ()) (check_param mw0 ew0) (fun _ ->
+      mk_generic mw0 ew0 (fun _ _ _ _ -> B754_infinity b))
  end
 
 module GenericInterval =
  struct
-  module Coq__1 = struct
+  module Coq__2 = struct
    type t = coq_Interval coq_Generic
   end
-  include Coq__1
+  include Coq__2
 
   module I_inhab =
    struct
-    type t = Coq__1.t
+    type t = Coq__2.t
 
     (** val dummy : t **)
 
     let dummy =
-      { prec = (Farith_Big.double (Farith_Big.double (Farith_Big.double
-        (Farith_Big.succ_double Farith_Big.one)))); emax = (Farith_Big.double
+      { mw = (Farith_Big.succ_double (Farith_Big.succ_double
+        (Farith_Big.succ_double (Farith_Big.double Farith_Big.one)))); ew =
         (Farith_Big.double (Farith_Big.double (Farith_Big.double
-        (Farith_Big.double (Farith_Big.double (Farith_Big.double
-        Farith_Big.one))))))); value = (Intv ((B754_infinity true),
+        Farith_Big.one))); value = (Intv ((B754_infinity true),
         (B754_infinity false), true)) }
    end
 
@@ -109,7 +302,7 @@ module GenericInterval =
 
   module O_inhab =
    struct
-    type t = Coq__1.t option
+    type t = Coq__2.t option
 
     (** val dummy : t **)
 
@@ -124,10 +317,54 @@ module GenericInterval =
   let inter x y =
     (fun x f -> assert x; f ()) (same_format x y) (fun _ ->
       let r =
-        inter x.prec x.emax x.value
-          (same_format_cast x.prec x.emax y.prec y.emax y.value)
+        inter (prec x) (emax x) x.value
+          (same_format_cast (prec x) (emax x) (prec y) (emax y) y.value)
       in
       (match r with
        | Some r0 -> Some (mk_with x r0)
        | None -> None))
+
+  (** val add : Farith_Big.mode -> t -> t -> t **)
+
+  let add m x y =
+    (fun x f -> assert x; f ()) (same_format x y) (fun _ ->
+      mk_with x
+        (coq_Iadd (prec x) (emax x) m x.value
+          (same_format_cast (prec x) (emax x) (prec y) (emax y) y.value)))
+
+  (** val ge : t -> t option **)
+
+  let ge x =
+    mk_witho x (coq_Ige (prec x) (emax x) x.value)
+
+  (** val gt : t -> t option **)
+
+  let gt x =
+    mk_witho x (coq_Igt (prec x) (emax x) x.value)
+
+  (** val le : t -> t option **)
+
+  let le x =
+    mk_witho x (coq_Ile (prec x) (emax x) x.value)
+
+  (** val lt : t -> t option **)
+
+  let lt x =
+    mk_witho x (coq_Ilt (prec x) (emax x) x.value)
+
+  (** val singleton : GenericFloat.t -> t **)
+
+  let singleton x =
+    mk_with x (singleton (cprec x.mw) (cemax x.ew) x.value)
+
+  (** val is_singleton : t -> GenericFloat.t option **)
+
+  let is_singleton x =
+    mk_witho x (is_singleton (cprec x.mw) (cemax x.ew) x.value)
+
+  (** val top : Farith_Big.big_int -> Farith_Big.big_int -> t **)
+
+  let top mw0 ew0 =
+    (fun x f -> assert x; f ()) (check_param mw0 ew0) (fun _ ->
+      mk_generic mw0 ew0 (fun prec0 emax0 _ _ -> top prec0 emax0))
  end
diff --git a/farith2/extracted/GenericFloat.mli b/farith2/extracted/GenericFloat.mli
index 3472c3a41b25d176b23f795d345c45691bea28ed..b0387b2118363e7f80a2a773e0bf88b4c082fc91 100644
--- a/farith2/extracted/GenericFloat.mli
+++ b/farith2/extracted/GenericFloat.mli
@@ -1,11 +1,30 @@
+open BinInt
+open Binary
 open BinarySingleNaN
+open Bits
+open Datatypes
 open Interval
+open SpecFloat
 
 type __ = Obj.t
 
-type 'v coq_Generic = { prec : Farith_Big.big_int; emax : Farith_Big.big_int;
+val cprec : Farith_Big.big_int -> Farith_Big.big_int
+
+val cemax : Farith_Big.big_int -> Farith_Big.big_int
+
+val check_param : Farith_Big.big_int -> Farith_Big.big_int -> bool
+
+type 'v coq_Generic = { mw : Farith_Big.big_int; ew : Farith_Big.big_int;
                         value : 'v }
 
+val prec : 'a1 coq_Generic -> Farith_Big.big_int
+
+val emax : 'a1 coq_Generic -> Farith_Big.big_int
+
+val mk_generic :
+  Farith_Big.big_int -> Farith_Big.big_int -> (Farith_Big.big_int ->
+  Farith_Big.big_int -> __ -> __ -> 'a1) -> 'a1 coq_Generic
+
 val same_format_cast :
   Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int ->
   Farith_Big.big_int -> 'a1 -> 'a1
@@ -14,13 +33,18 @@ val same_format : 'a1 coq_Generic -> 'a2 coq_Generic -> bool
 
 val mk_with : 'a1 coq_Generic -> 'a2 -> 'a2 coq_Generic
 
+val mk_witho : 'a1 coq_Generic -> 'a2 option -> 'a2 coq_Generic option
+
 module GenericFloat :
  sig
-  type coq_F = binary_float coq_Generic
+  module Coq__1 : sig
+   type t = binary_float coq_Generic
+  end
+  include module type of struct include Coq__1 end
 
   module F_inhab :
    sig
-    type t = coq_F
+    type t = Coq__1.t
 
     val dummy : binary_float coq_Generic
    end
@@ -40,24 +64,62 @@ module GenericFloat :
    sig
    end
 
-  val add :
-    Farith_Big.mode -> coq_F -> coq_F -> binary_float coq_Generic option
+  val of_q' :
+    Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> Q.t ->
+    binary_float
+
+  val of_q :
+    Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> Q.t -> t
+
+  val add : Farith_Big.mode -> t -> t -> t
+
+  val sub : Farith_Big.mode -> t -> t -> t
+
+  val mul : Farith_Big.mode -> t -> t -> t
+
+  val div : Farith_Big.mode -> t -> t -> t
+
+  val sqrt : Farith_Big.mode -> t -> t
+
+  val abs : t -> t
+
+  val le : t -> t -> bool
+
+  val lt : t -> t -> bool
 
-  val coq_Fadd : Farith_Big.mode -> coq_F -> coq_F -> coq_F
+  val eq : t -> t -> bool
 
-  val coq_Fsub : Farith_Big.mode -> coq_F -> coq_F -> coq_F
+  val ge : t -> t -> bool
+
+  val gt : t -> t -> bool
+
+  val of_bits' :
+    Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int ->
+    binary_float
+
+  val of_bits : Farith_Big.big_int -> Farith_Big.big_int -> Z.t -> t
+
+  val pl_cst : Farith_Big.big_int -> Farith_Big.big_int
+
+  val to_bits : t -> Farith_Big.big_int
+
+  val nan : Farith_Big.big_int -> Farith_Big.big_int -> t
+
+  val zero : Farith_Big.big_int -> Farith_Big.big_int -> bool -> t
+
+  val inf : Farith_Big.big_int -> Farith_Big.big_int -> bool -> t
  end
 
 module GenericInterval :
  sig
-  module Coq__1 : sig
+  module Coq__2 : sig
    type t = coq_Interval coq_Generic
   end
-  include module type of struct include Coq__1 end
+  include module type of struct include Coq__2 end
 
   module I_inhab :
    sig
-    type t = Coq__1.t
+    type t = Coq__2.t
 
     val dummy : t
    end
@@ -68,7 +130,7 @@ module GenericInterval :
 
   module O_inhab :
    sig
-    type t = Coq__1.t option
+    type t = Coq__2.t option
 
     val dummy : t
    end
@@ -78,4 +140,20 @@ module GenericInterval :
    end
 
   val inter : t -> t -> t option
+
+  val add : Farith_Big.mode -> t -> t -> t
+
+  val ge : t -> t option
+
+  val gt : t -> t option
+
+  val le : t -> t option
+
+  val lt : t -> t option
+
+  val singleton : GenericFloat.t -> t
+
+  val is_singleton : t -> GenericFloat.t option
+
+  val top : Farith_Big.big_int -> Farith_Big.big_int -> t
  end
diff --git a/farith2/extracted/Interval.ml b/farith2/extracted/Interval.ml
index a252a5c302c5de76d2c3b9f0e68e7a16ba241f25..8f35f75cb22cd83b1ef028429048e49635fefef1 100644
--- a/farith2/extracted/Interval.ml
+++ b/farith2/extracted/Interval.ml
@@ -19,6 +19,31 @@ let to_Interval_opt _ _ = function
 | Some j -> Some j
 | None -> None
 
+(** val top : Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval **)
+
+let top _ _ =
+  Intv ((B754_infinity true), (B754_infinity false), true)
+
+(** val is_singleton :
+    Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> float option **)
+
+let is_singleton prec emax = function
+| Inan -> Some B754_nan
+| Intv (a, b, n) ->
+  if (&&)
+       ((&&) (coq_Beqb prec emax a b)
+         (Pervasives.not (coq_Beqb prec emax a (B754_zero false))))
+       (Pervasives.not n)
+  then Some a
+  else None
+
+(** val singleton :
+    Farith_Big.big_int -> Farith_Big.big_int -> float -> coq_Interval **)
+
+let singleton _ _ x = match x with
+| B754_nan -> Inan
+| _ -> Intv (x, x, false)
+
 (** val inter' :
     Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval' ->
     coq_Interval' -> coq_Interval' option **)
@@ -110,61 +135,3 @@ let coq_Ige _ _ = function
 let coq_Igt _ _ = function
 | Inan -> None
 | Intv (a, _, n) -> Some (Intv (a, (B754_infinity false), n))
-
-(** val inter_opt :
-    Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval_opt ->
-    coq_Interval_opt -> coq_Interval_opt **)
-
-let inter_opt prec emax i1 i2 =
-  match i1 with
-  | Some i3 -> (match i2 with
-                | Some i4 -> inter prec emax i3 i4
-                | None -> None)
-  | None -> None
-
-(** val to_opt :
-    Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval ->
-    coq_Interval_opt **)
-
-let to_opt _ _ i =
-  Some i
-
-(** val coq_Ige_inv :
-    Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> coq_Interval
-    -> coq_Interval_opt * coq_Interval_opt **)
-
-let coq_Ige_inv prec emax i1 i2 =
-  ((inter_opt prec emax (coq_Ige prec emax i2) (to_opt prec emax i1)),
-    (inter_opt prec emax (coq_Ile prec emax i1) (to_opt prec emax i2)))
-
-(** val coq_Igt_inv :
-    Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> coq_Interval
-    -> coq_Interval_opt * coq_Interval_opt **)
-
-let coq_Igt_inv prec emax i1 i2 =
-  ((inter_opt prec emax (coq_Igt prec emax i2) (to_opt prec emax i1)),
-    (inter_opt prec emax (coq_Ilt prec emax i1) (to_opt prec emax i2)))
-
-(** val coq_Ilt_inv :
-    Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> coq_Interval
-    -> coq_Interval_opt * coq_Interval_opt **)
-
-let coq_Ilt_inv prec emax i1 i2 =
-  ((inter_opt prec emax (coq_Ilt prec emax i2) (to_opt prec emax i1)),
-    (inter_opt prec emax (coq_Igt prec emax i1) (to_opt prec emax i2)))
-
-(** val coq_Ile_inv :
-    Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> coq_Interval
-    -> coq_Interval_opt * coq_Interval_opt **)
-
-let coq_Ile_inv prec emax i1 i2 =
-  ((inter_opt prec emax (coq_Ile prec emax i2) (to_opt prec emax i1)),
-    (inter_opt prec emax (coq_Ige prec emax i1) (to_opt prec emax i2)))
-
-(** val coq_Ieq_inv :
-    Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> coq_Interval
-    -> coq_Interval_opt * coq_Interval_opt **)
-
-let coq_Ieq_inv prec emax i1 i2 =
-  ((inter_opt prec emax (to_opt prec emax i1) (to_opt prec emax i2)),
-    (inter_opt prec emax (to_opt prec emax i1) (to_opt prec emax i2)))
diff --git a/farith2/extracted/Interval.mli b/farith2/extracted/Interval.mli
index 18d3461764c02fec9548452c12ee35bda43b014a..6a873c01a4e5a53de46a8318891cbbb65dbd7440 100644
--- a/farith2/extracted/Interval.mli
+++ b/farith2/extracted/Interval.mli
@@ -15,6 +15,14 @@ val to_Interval_opt :
   Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval' option ->
   coq_Interval_opt
 
+val top : Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval
+
+val is_singleton :
+  Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> float option
+
+val singleton :
+  Farith_Big.big_int -> Farith_Big.big_int -> float -> coq_Interval
+
 val inter' :
   Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval' -> coq_Interval'
   -> coq_Interval' option
@@ -42,30 +50,3 @@ val coq_Ige :
 
 val coq_Igt :
   Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> coq_Interval_opt
-
-val inter_opt :
-  Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval_opt ->
-  coq_Interval_opt -> coq_Interval_opt
-
-val to_opt :
-  Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> coq_Interval_opt
-
-val coq_Ige_inv :
-  Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> coq_Interval ->
-  coq_Interval_opt * coq_Interval_opt
-
-val coq_Igt_inv :
-  Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> coq_Interval ->
-  coq_Interval_opt * coq_Interval_opt
-
-val coq_Ilt_inv :
-  Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> coq_Interval ->
-  coq_Interval_opt * coq_Interval_opt
-
-val coq_Ile_inv :
-  Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> coq_Interval ->
-  coq_Interval_opt * coq_Interval_opt
-
-val coq_Ieq_inv :
-  Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> coq_Interval ->
-  coq_Interval_opt * coq_Interval_opt
diff --git a/farith2/extracted/Intv32.ml b/farith2/extracted/Intv32.ml
deleted file mode 100644
index 88fa1f17c182039bdb041ba882dc9e36480c42c1..0000000000000000000000000000000000000000
--- a/farith2/extracted/Intv32.ml
+++ /dev/null
@@ -1,132 +0,0 @@
-open BinarySingleNaN
-open Interval
-
-module Intv32 =
- struct
-  (** val prec : Farith_Big.big_int **)
-
-  let prec =
-    (Farith_Big.double (Farith_Big.double (Farith_Big.double
-      (Farith_Big.succ_double Farith_Big.one))))
-
-  (** val emax : Farith_Big.big_int **)
-
-  let emax =
-    (Farith_Big.double (Farith_Big.double (Farith_Big.double
-      (Farith_Big.double (Farith_Big.double (Farith_Big.double
-      (Farith_Big.double Farith_Big.one)))))))
-
-  type float32 = B32.B32.t
-
-  type t = coq_Interval
-
-  type t_opt = coq_Interval_opt
-
-  (** val inter : t -> t -> t_opt **)
-
-  let inter x y =
-    inter prec emax x y
-
-  (** val add : Farith_Big.mode -> t -> t -> t **)
-
-  let add =
-    coq_Iadd prec emax
-
-  (** val top : t **)
-
-  let top =
-    Intv ((B754_infinity true), (B754_infinity false), true)
-
-  (** val bot : t_opt **)
-
-  let bot =
-    None
-
-  (** val is_singleton : t -> float32 option **)
-
-  let is_singleton = function
-  | Inan -> Some B754_nan
-  | Intv (a, b, n) ->
-    if (&&)
-         ((&&) (coq_Beqb prec emax a b)
-           (Pervasives.not (coq_Beqb prec emax a (B754_zero false))))
-         (Pervasives.not n)
-    then Some a
-    else None
-
-  (** val s0 : coq_Interval **)
-
-  let s0 =
-    Intv ((B754_zero false), (B754_zero true), false)
-
-  (** val singleton : float32 -> t **)
-
-  let singleton x = match x with
-  | B754_nan -> Inan
-  | _ -> Intv (x, x, false)
-
-  (** val s00 : t **)
-
-  let s00 =
-    Intv ((B754_zero false), (B754_zero false), false)
-
-  (** val s01 : t **)
-
-  let s01 =
-    Intv ((B754_zero false), (B754_zero true), false)
-
-  (** val s10 : t **)
-
-  let s10 =
-    Intv ((B754_zero true), (B754_zero false), false)
-
-  (** val s11 : t **)
-
-  let s11 =
-    Intv ((B754_zero true), (B754_zero true), false)
-
-  (** val ge : t -> t_opt **)
-
-  let ge =
-    coq_Ige prec emax
-
-  (** val le : t -> t_opt **)
-
-  let le =
-    coq_Ile prec emax
-
-  (** val lt : t -> t_opt **)
-
-  let lt =
-    coq_Ilt prec emax
-
-  (** val gt : t -> t_opt **)
-
-  let gt =
-    coq_Igt prec emax
-
-  (** val le_inv : t -> t -> t_opt * t_opt **)
-
-  let le_inv =
-    coq_Ile_inv prec emax
-
-  (** val ge_inv : t -> t -> t_opt * t_opt **)
-
-  let ge_inv =
-    coq_Ige_inv prec emax
-
-  (** val lt_inv : t -> t -> t_opt * t_opt **)
-
-  let lt_inv =
-    coq_Ilt_inv prec emax
-
-  (** val gt_inv : t -> t -> t_opt * t_opt **)
-
-  let gt_inv =
-    coq_Igt_inv prec emax
-
-  (** val eq_inv : t -> t -> t_opt * t_opt **)
-
-  let eq_inv =
-    coq_Ieq_inv prec emax
- end
diff --git a/farith2/extracted/Intv32.mli b/farith2/extracted/Intv32.mli
deleted file mode 100644
index e44a79c2c97c9a60debfad6f846bb4e0a9c4fe4c..0000000000000000000000000000000000000000
--- a/farith2/extracted/Intv32.mli
+++ /dev/null
@@ -1,55 +0,0 @@
-open BinarySingleNaN
-open Interval
-
-module Intv32 :
- sig
-  val prec : Farith_Big.big_int
-
-  val emax : Farith_Big.big_int
-
-  type float32 = B32.B32.t
-
-  type t = coq_Interval
-
-  type t_opt = coq_Interval_opt
-
-  val inter : t -> t -> t_opt
-
-  val add : Farith_Big.mode -> t -> t -> t
-
-  val top : t
-
-  val bot : t_opt
-
-  val is_singleton : t -> float32 option
-
-  val s0 : coq_Interval
-
-  val singleton : float32 -> t
-
-  val s00 : t
-
-  val s01 : t
-
-  val s10 : t
-
-  val s11 : t
-
-  val ge : t -> t_opt
-
-  val le : t -> t_opt
-
-  val lt : t -> t_opt
-
-  val gt : t -> t_opt
-
-  val le_inv : t -> t -> t_opt * t_opt
-
-  val ge_inv : t -> t -> t_opt * t_opt
-
-  val lt_inv : t -> t -> t_opt * t_opt
-
-  val gt_inv : t -> t -> t_opt * t_opt
-
-  val eq_inv : t -> t -> t_opt * t_opt
- end
diff --git a/farith2/extracted/Version.ml b/farith2/extracted/Version.ml
new file mode 100644
index 0000000000000000000000000000000000000000..e77689aa7ec1fd0a14f5ba88308be87ef38a3763
--- /dev/null
+++ b/farith2/extracted/Version.ml
@@ -0,0 +1,10 @@
+
+(** val coq_Flocq_version : Farith_Big.big_int **)
+
+let coq_Flocq_version =
+  (Farith_Big.double (Farith_Big.succ_double (Farith_Big.double
+    (Farith_Big.double (Farith_Big.double (Farith_Big.double
+    (Farith_Big.succ_double (Farith_Big.succ_double (Farith_Big.double
+    (Farith_Big.succ_double (Farith_Big.succ_double (Farith_Big.double
+    (Farith_Big.succ_double (Farith_Big.succ_double
+    Farith_Big.one))))))))))))))
diff --git a/farith2/extracted/Version.mli b/farith2/extracted/Version.mli
new file mode 100644
index 0000000000000000000000000000000000000000..dce3905b89ac8474a768899a39c97e7c247937e8
--- /dev/null
+++ b/farith2/extracted/Version.mli
@@ -0,0 +1,2 @@
+
+val coq_Flocq_version : Farith_Big.big_int
diff --git a/farith2/extracted/dune b/farith2/extracted/dune
index cfadeed04bab40ab5d261ab1edbb83a7af611394..a607f0d77a5cc55152f1b3033d7dbe59c1dcb6b2 100644
--- a/farith2/extracted/dune
+++ b/farith2/extracted/dune
@@ -1,9 +1,7 @@
-(rule (action (copy ../extract/B32.ml B32.ml)) (mode promote))
 (rule (action (copy ../extract/BinNums.ml BinNums.ml)) (mode promote))
 (rule (action (copy ../extract/Bool.ml Bool.ml)) (mode promote))
 (rule (action (copy ../extract/Qextended.ml Qextended.ml)) (mode promote))
 (rule (action (copy ../extract/Utils.ml Utils.ml)) (mode promote))
-(rule (action (copy ../extract/B32.mli B32.mli)) (mode promote))
 (rule (action (copy ../extract/BinNums.mli BinNums.mli)) (mode promote))
 (rule (action (copy ../extract/Bool.mli Bool.mli)) (mode promote))
 (rule (action (copy ../extract/Qextended.mli Qextended.mli)) (mode promote))
@@ -30,15 +28,15 @@
 (rule (action (copy ../extract/Zbool.mli Zbool.mli)) (mode promote))
 (rule (action (copy ../extract/BinInt.ml BinInt.ml)) (mode promote))
 (rule (action (copy ../extract/Bits.ml Bits.ml)) (mode promote))
-(rule (action (copy ../extract/Intv32.ml Intv32.ml)) (mode promote))
 (rule (action (copy ../extract/Specif.ml Specif.ml)) (mode promote))
 (rule (action (copy ../extract/Zpower.ml Zpower.ml)) (mode promote))
 (rule (action (copy ../extract/BinInt.mli BinInt.mli)) (mode promote))
 (rule (action (copy ../extract/Bits.mli Bits.mli)) (mode promote))
-(rule (action (copy ../extract/Intv32.mli Intv32.mli)) (mode promote))
 (rule (action (copy ../extract/Specif.mli Specif.mli)) (mode promote))
 (rule (action (copy ../extract/Zpower.mli Zpower.mli)) (mode promote))
 (rule (action (copy ../extract/Assert.ml Assert.ml)) (mode promote))
 (rule (action (copy ../extract/Assert.mli Assert.mli)) (mode promote))
 (rule (action (copy ../extract/GenericFloat.ml GenericFloat.ml)) (mode promote))
 (rule (action (copy ../extract/GenericFloat.mli GenericFloat.mli)) (mode promote))
+(rule (action (copy ../extract/Version.ml Version.ml)) (mode promote))
+(rule (action (copy ../extract/Version.mli Version.mli)) (mode promote))
diff --git a/farith2/farith2.ml b/farith2/farith2.ml
new file mode 100644
index 0000000000000000000000000000000000000000..7573c9a302236956eb75b199d59db56b214cd934
--- /dev/null
+++ b/farith2/farith2.ml
@@ -0,0 +1,259 @@
+(**************************************************************************)
+(*  This file is part of FArith.                                          *)
+(*                                                                        *)
+(*  Copyright (C) 2015-2015                                               *)
+(*    CEA (Commissariat a l'energie atomique et aux energies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  (enclosed file LGPLv2.1).                                             *)
+(*                                                                        *)
+(**************************************************************************)
+open Base
+
+module Z = struct
+  include Z
+
+  let hash_fold_t s t = Base.Hash.fold_int s (hash t)
+end
+
+type mode = Farith_Big.mode = NE | ZR | DN | UP | NA
+[@@deriving eq, ord, hash]
+
+type classify = Farith_Big.classify =
+  | Zero of bool
+  | Infinity of bool
+  | NaN
+  | Finite of bool * Z.t * Z.t
+
+type 'v generic = 'v GenericFloat.coq_Generic = {
+  mw : Z.t;
+  ew : Z.t;
+  value : 'v;
+}
+[@@deriving eq, ord, hash]
+
+module F = struct
+  open GenericFloat
+  include GenericFloat
+
+  let mw t = Z.to_int t.mw
+
+  let ew t = Z.to_int t.ew
+
+  let pp_sign fmt b = Format.pp_print_string fmt (if b then "-" else "+")
+
+  type binary_float = BinarySingleNaN.binary_float =
+    | B754_zero of bool
+    | B754_infinity of bool
+    | B754_nan
+    | B754_finite of bool * Z.t * Z.t
+  [@@deriving eq, ord, hash]
+
+  type t = binary_float generic [@@deriving eq, ord, hash]
+
+  let pp_binary_float fmt (t : binary_float) =
+    match t with
+    | B754_zero b -> Format.fprintf fmt "%a0" pp_sign b
+    | B754_infinity b -> Format.fprintf fmt "%a∞" pp_sign b
+    | B754_nan -> Format.fprintf fmt "NaN"
+    | B754_finite (b, m, e) ->
+        let rec oddify a p =
+          if Z.equal (Z.logand a Z.one) Z.zero then
+            oddify (Z.shift_right_trunc a 1) (Z.succ p)
+          else if Z.equal a Z.zero then (Z.zero, Z.zero)
+          else (a, p)
+        in
+        let m, e = oddify m e in
+        Format.fprintf fmt "%a%ap%a" pp_sign b Z.pp_print m Z.pp_print e
+
+  let pp fmt t = pp_binary_float fmt t.value
+
+  (** lexer for finite float *)
+  let lex_float s =
+    match String.index s 'p' with
+    | Some k ->
+        let m = String.sub s ~pos:0 ~len:k in
+        let e = String.sub s (succ k) (String.length s - k - 1) in
+        (Z.of_string m, Z.of_string e)
+    | None -> (Z.of_string s, Z.zero)
+
+  let of_q ~mw ~ew ~mode q = of_q (Z.of_int mw) (Z.of_int ew) mode q
+
+  let of_bits ~mw ~ew z = of_bits (Z.of_int mw) (Z.of_int ew) z
+
+  let to_bits t = to_bits t
+
+  let nan ~mw ~ew = nan (Z.of_int mw) (Z.of_int ew)
+
+  let zero ~mw ~ew b = zero (Z.of_int mw) (Z.of_int ew) b
+
+  let inf ~mw ~ew b = inf (Z.of_int mw) (Z.of_int ew) b
+
+  let is_zero t = match t.value with B754_zero _ -> true | _ -> false
+end
+
+module I = struct
+  open GenericFloat
+  include GenericInterval
+
+  type interval = Interval.coq_Interval' =
+    | Inan
+    | Intv of F.binary_float * F.binary_float * bool
+  [@@deriving eq, ord, hash]
+
+  type t = interval generic [@@deriving eq, ord, hash]
+
+  let mw t = Z.to_int t.mw
+
+  let ew t = Z.to_int t.ew
+
+  let pp fmt (t : t) =
+    match t.value with
+    | Inan -> Format.fprintf fmt "{ NaN }"
+    | Intv (a, b, nan) ->
+        if nan then
+          Format.fprintf fmt "[%a, %a] + NaN" F.pp_binary_float a
+            F.pp_binary_float b
+        else
+          Format.fprintf fmt "[%a, %a]" F.pp_binary_float a F.pp_binary_float b
+
+  let top ~mw ~ew = top (Z.of_int mw) (Z.of_int ew)
+end
+
+(*
+module D = struct
+  type 't conf = 't Farith_F_aux.fconf
+  include Farith_F_aux.D
+  include Common
+
+  let mw conf = Z.to_int (Farith_F_aux.mw conf)
+  let ew conf = Z.to_int (Farith_F_aux.ew conf)
+
+  let roundq ~mw ~ew mode q = roundq (Z.of_int mw) (Z.of_int ew) mode q
+
+  let pp conf fmt x = pp fmt (cast_to_t conf x)
+
+  (* let of_string conf mode s =
+   *   let m,e = lex_float s in
+   *   finite conf mode m e *)
+end
+
+module type S = sig
+
+  type t
+  val conf : t D.conf
+
+  val compare: t -> t -> int
+  val equal: t -> t -> bool
+  val hash : t -> int
+
+  val opp : t -> t
+  val add : mode -> t -> t -> t
+  val sub : mode -> t -> t -> t
+  val mul : mode -> t -> t -> t
+  val div : mode -> t -> t -> t
+  val sqrt : mode -> t -> t
+  val abs : t -> t
+
+  val of_bits : Z.t -> t
+  val to_bits : t -> Z.t
+
+  val of_z : mode -> Z.t -> t (** Round. *)
+
+  val of_q : mode -> Q.t -> t (** Round. *)
+
+  val to_q : t -> Q.t (** Exact. *)
+
+  val conv : 't D.conf -> mode -> t -> 't
+
+  val infinity: bool -> t
+  val infp : t
+  val infm : t
+  val zero : bool -> t
+  val zerop: t
+  val nan: bool -> Z.t -> t
+  val default_nan: t
+  val finite: mode -> Z.t -> Z.t -> t
+  val classify: t -> classify
+
+  val le  : t -> t -> bool
+  val lt  : t -> t -> bool
+  val ge  : t -> t -> bool
+  val gt  : t -> t -> bool
+  val eq  : t -> t -> bool
+  val neq : t -> t -> bool
+
+  val fcompare : t -> t -> int option
+
+  val pp : Format.formatter -> t -> unit
+  val of_string: mode -> string -> t
+
+end
+
+module B32 = struct include Farith_F_aux.B32 include Common
+
+  let of_string mode s =
+    let m,e = lex_float s in
+    finite mode m e
+end
+
+module B64 = struct include Farith_F_aux.B64 include Common
+
+  (** unfortunately of_bits and to_bits wants positive argument (unsigned int64)
+      and Z.of_int64/Z.to_int64 wants signed argument (signed int64)
+  *)
+  let mask_one = Z.pred (Z.shift_left Z.one 64)
+  let of_float f =
+    let fb = (Big_int_Z.big_int_of_int64 (Int64.bits_of_float f)) in
+    let fb = Z.logand mask_one fb in
+    of_bits fb
+
+  let mask_63 = Z.shift_left Z.one 63
+  let intmask_63 = Int64.shift_left Int64.one 63
+  let to_float f =
+    let fb = to_bits f in
+    let i = if Z.logand mask_63 fb = Z.zero then Z.to_int64 fb
+      else Int64.logor intmask_63 (Z.to_int64 (Z.logxor mask_63 fb)) in
+    Int64.float_of_bits i
+
+  let of_string mode s =
+    let m,e = lex_float s in
+    finite mode m e
+
+end
+
+module type Size =
+sig
+  val mw : int (** mantissa size (in bits) *)
+
+  val ew : int (** exponent size (in bits) *)
+end
+
+module Make(Size : Size) =
+struct
+
+  include Farith_F_aux.Make
+      (struct
+        let mw = Z.of_int Size.mw
+        let ew = Z.of_int Size.ew
+      end)
+
+  include Common
+
+  let of_string mode s =
+    let m,e = lex_float s in
+    finite mode m e
+
+end
+*)
+let flocq_version = Version.coq_Flocq_version
diff --git a/farith2/farith2.mli b/farith2/farith2.mli
new file mode 100644
index 0000000000000000000000000000000000000000..c482549024e086896b99e676dfb2428e79f42fc0
--- /dev/null
+++ b/farith2/farith2.mli
@@ -0,0 +1,369 @@
+(**************************************************************************)
+(*  This file is part of FArith.                                          *)
+(*                                                                        *)
+(*  Copyright (C) 2015-2015                                               *)
+(*    CEA (Commissariat a l'energie atomique et aux energies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  (enclosed file LGPLv2.1).                                             *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** Float Arithmetics (based on [Flocq] extraction) *)
+
+(** Supported rounding modes *)
+type mode =
+  | NE  (** Nearest to even *)
+  | ZR  (** Toward zero *)
+  | DN  (** Toward minus infinity *)
+  | UP  (** Toward plus infinity *)
+  | NA  (** Nearest away from zero *)
+[@@deriving eq, ord, hash]
+
+(** Type used for classifying floating points *)
+type classify =
+  | Zero of bool
+  | Infinity of bool
+  | NaN
+  | Finite of bool * Z.t * Z.t
+
+module F : sig
+  type t [@@deriving eq, ord, hash]
+
+  val ew : t -> int
+
+  val mw : t -> int
+
+  val pp : Format.formatter -> t -> unit
+
+  val of_q : mw:int -> ew:int -> mode:mode -> Q.t -> t
+
+  val add : mode -> t -> t -> t
+
+  val sub : mode -> t -> t -> t
+
+  val mul : mode -> t -> t -> t
+
+  val div : mode -> t -> t -> t
+
+  val sqrt : mode -> t -> t
+
+  val abs : t -> t
+
+  val of_bits : mw:int -> ew:int -> Z.t -> t
+
+  val to_bits : t -> Z.t
+
+  val ge : t -> t -> bool
+
+  val gt : t -> t -> bool
+
+  val le : t -> t -> bool
+
+  val lt : t -> t -> bool
+
+  val eq : t -> t -> bool
+
+  val nan : mw:int -> ew:int -> t
+
+  val zero : mw:int -> ew:int -> bool -> t
+
+  val inf : mw:int -> ew:int -> bool -> t
+
+  val is_zero : t -> bool
+end
+
+module I : sig
+  type t [@@deriving eq, ord, hash]
+
+  val ew : t -> int
+
+  val mw : t -> int
+
+  val pp : Format.formatter -> t -> unit
+
+  val top : mw:int -> ew:int -> t
+
+  val inter : t -> t -> t option
+
+  val add : mode -> t -> t -> t
+
+  val ge : t -> t option
+
+  val gt : t -> t option
+
+  val le : t -> t option
+
+  val lt : t -> t option
+
+  val singleton : F.t -> t
+
+  val is_singleton : t -> F.t option
+end
+
+(* (\** {2 Generic Version } *\)
+ * 
+ * 
+ * module D : sig
+ * 
+ *   type 't conf
+ *   (\** A configuration links a mantissa and exponent size to a
+ *       type which is the set of representable floating point with these sizes.
+ *       A value of this type is obtained by application of {!Farith.Make}
+ *   *\)
+ * 
+ *   val mw : 't conf -> int
+ *   (\** mantissa size *\)
+ * 
+ *   val ew : 't conf -> int
+ *   (\** exponent size *\)
+ * 
+ *   (\** {2 Total operators} *\)
+ * 
+ *   val compare: 't conf -> 't -> 't -> int
+ *   val equal: 't conf -> 't -> 't -> bool
+ *   val hash : 't conf -> 't -> int
+ * 
+ *   (\** {2 Floating point operations} *\)
+ * 
+ *   val opp : 't conf -> 't -> 't
+ *   val add : 't conf -> mode -> 't -> 't -> 't
+ *   val sub : 't conf -> mode -> 't -> 't -> 't
+ *   val mul : 't conf -> mode -> 't -> 't -> 't
+ *   val div : 't conf -> mode -> 't -> 't -> 't
+ *   val sqrt : 't conf -> mode -> 't -> 't
+ *   val abs : 't conf -> 't -> 't
+ * 
+ *   (\** {2 Conversions} *\)
+ * 
+ *   val of_bits : 't conf -> Z.t -> 't
+ *   (\** Conversions from bitvector representation.
+ *       The given bitvector must be positive.
+ *   *\)
+ * 
+ *   val to_bits : 't conf -> 't -> Z.t
+ *   (\** Convert the floating point to its bitvector representation *\)
+ * 
+ *   val of_z : 't conf -> mode -> Z.t -> 't
+ *   (\** Convert the integer to the nearest representable integer *\)
+ * 
+ *   val of_q : 't conf -> mode -> Q.t -> 't
+ *   (\** Convert the rational to the nearest representable integer. *\)
+ * 
+ *   val to_q : 't conf -> 't -> Q.t
+ *   (\** Convert the floating-point to its rational representation. *\)
+ * 
+ *   val conv : 't1 conf -> 't2 conf -> mode -> 't1 -> 't2
+ *   (\** Convert the floating point to the nearest representable floating point
+ *       having another mantissa and exponent size. *\)
+ * 
+ *   val roundq : mw:int -> ew:int -> mode -> Q.t -> Q.t
+ *   (\** Round the given rational to the nearest representable floating
+ *       point with the mantissa width [mw] and exponent width [ew] using
+ *       the rounding mode [mode].
+ *   *\)
+ * 
+ *   (\** {2 Floating point constants} *\)
+ *   val infinity: 't conf -> bool -> 't
+ *   (\** create infinity floating point (true negative, false positive) *\)
+ * 
+ *   val infp : 't conf -> 't
+ *   (\** positive infinity *\)
+ * 
+ *   val infm : 't conf -> 't
+ *   (\** minus infinity *\)
+ * 
+ *   val zero : 't conf -> bool -> 't
+ *   (\** create zero floating point (true negative, false positive) *\)
+ * 
+ *   val zerop: 't conf -> 't
+ *   (\** positive zero *\)
+ * 
+ *   val nan: 't conf -> bool -> Z.t -> 't
+ *   (\** create a nan with the given payload. The payload must fit in the
+ *       mantissa *\)
+ * 
+ *   val default_nan: 't conf -> 't
+ * 
+ *   val finite: 't conf -> mode -> Z.t -> Z.t -> 't
+ *   (\** [finite conf mode m e] return the rounded floating point
+ *       corresponding to m*2^e. Beware of the result can be classified
+ *       not only as finite but also as infinite or zero because of the
+ *       rounding.
+ *   *\)
+ * 
+ *   val classify: 't conf -> 't -> classify
+ *   (\** Classify the floating point according to its kind *\)
+ * 
+ *   (\** {3 IEEE Comparison}
+ * 
+ *       Respect IEEE behavior for NaN
+ *   *\)
+ * 
+ *   val le  : 't conf -> 't -> 't -> bool
+ *   val lt  : 't conf -> 't -> 't -> bool
+ *   val ge  : 't conf -> 't -> 't -> bool
+ *   val gt  : 't conf -> 't -> 't -> bool
+ *   val eq  : 't conf -> 't -> 't -> bool
+ *   val neq : 't conf -> 't -> 't -> bool
+ * 
+ *   val fcompare : 't conf -> 't -> 't -> int option
+ *   (\** return None in the undefined cases (one of the argument is NaN) *\)
+ * 
+ *   (\** {3 Formatting}
+ * 
+ *       Format is [<m>[p<e>]] where [<m>] is a signed decimal integer
+ *       and [p<e>] an optional exponent in power of 2.
+ *       For instance [to_string (of_string "24p-1")] is ["3p2"].
+ *   *\)
+ * 
+ *   val pp : 't conf -> Format.formatter -> 't -> unit
+ * end
+ * 
+ * (\** {2 Functorized Version} *\)
+ * 
+ * 
+ * module type S = sig
+ *   type t
+ * 
+ *   val conf : t D.conf
+ *   (\** The configuration for this type of floating-point *\)
+ * 
+ *   (\** {2 Total operators} *\)
+ * 
+ *   val compare: t -> t -> int
+ *   val equal: t -> t -> bool
+ *   val hash : t -> int
+ * 
+ *   (\** {2 Floating point operations} *\)
+ * 
+ *   val opp : t -> t
+ *   val add : mode -> t -> t -> t
+ *   val sub : mode -> t -> t -> t
+ *   val mul : mode -> t -> t -> t
+ *   val div : mode -> t -> t -> t
+ *   val sqrt : mode -> t -> t
+ *   val abs : t -> t
+ * 
+ *   (\** {2 conversions} *\)
+ * 
+ *   val of_bits : Z.t -> t
+ *   (\** Conversions from bitvector representation.
+ *       The given bitvector must be positive.
+ *   *\)
+ * 
+ *   val to_bits : t -> Z.t
+ *   (\** Convert the floating point to its bitvector representation *\)
+ * 
+ *   val of_z : mode -> Z.t -> t
+ *   (\** Convert the integer to the nearest representable integer *\)
+ * 
+ *   val of_q : mode -> Q.t -> t
+ *   (\** Convert the rational to the nearest representable integer. *\)
+ * 
+ *   val to_q : t -> Q.t
+ *   (\** Convert the floating-point to its rational representation. *\)
+ * 
+ *   val conv : 't D.conf -> mode -> t -> 't
+ *   (\** Convert the floating point to the nearest representable floating point
+ *       having another mantissa and exponent size. *\)
+ * 
+ *   (\** {2 Floating point constants} *\)
+ *   val infinity: bool -> t
+ *   (\** create infinity floating point (true negative, false positive) *\)
+ * 
+ *   val infp : t
+ *   (\** positive infinity *\)
+ * 
+ *   val infm : t
+ *   (\** minus infinity *\)
+ * 
+ *   val zero : bool -> t
+ *   (\** create zero floating point (true negative, false positive) *\)
+ * 
+ *   val zerop: t
+ *   (\** positive zero *\)
+ * 
+ *   val nan: bool -> Z.t -> t
+ *   (\** create a nan with the given payload. The payload must fit in the
+ *       mantissa *\)
+ * 
+ *   val default_nan: t
+ * 
+ *   val finite: mode -> Z.t -> Z.t -> t
+ *   (\** [finite conf mode m e] return the rounded floating point
+ *       corresponding to m*2^e. Beware of the result can be classified
+ *       not only as finite but also as infinite or zero because of the
+ *       rounding. *\)
+ * 
+ *   val classify: t -> classify
+ *   (\** Classify the floating point according to its kind *\)
+ * 
+ *   (\** {3 IEEE Comparison}
+ * 
+ *       Respect IEEE behavior for NaN
+ *   *\)
+ * 
+ *   val le  : t -> t -> bool
+ *   val lt  : t -> t -> bool
+ *   val ge  : t -> t -> bool
+ *   val gt  : t -> t -> bool
+ *   val eq  : t -> t -> bool
+ *   val neq : t -> t -> bool
+ * 
+ *   val fcompare : t -> t -> int option
+ *   (\** return None in the undefined cases (one of the argument is NaN) *\)
+ * 
+ * 
+ *   (\** {3 Formatting}
+ * 
+ *       Format is [<m>[p<e>]] where [<m>] is a signed decimal integer
+ *       and [p<e>] an optional exponent in power of 2.
+ *       For instance [to_string (of_string "24p-1")] is ["3p2"].
+ *   *\)
+ * 
+ *   val pp : Format.formatter -> t -> unit
+ * 
+ * 
+ *   val of_string: mode -> string -> t
+ *   (\** convert string of the shape "[-+][0-9]+p[-+][0-9]+" or "[-+][0-9]+"
+ *       to a floating point using the given rounding *\)
+ * end
+ * 
+ * module type Size =
+ * sig
+ *   val mw : int
+ *   (\** mantissa size (in bits) *\)
+ * 
+ *   val ew : int
+ *   (\** exponent size (in bits) *\)
+ * end
+ * 
+ * module Make (Size : Size) : S
+ * 
+ * (\** {2 Already Applied Versions } *\)
+ * 
+ * (\** Simple  (mw = 23 ew = 8) *\)
+ * module B32 : S
+ * 
+ * (\** Double (mw = 52 ew = 11) *\)
+ * module B64 : sig
+ *   include S
+ * 
+ *   (\** {3 Exact conversion from/to OCaml floats} *\)
+ *   val of_float : float -> t
+ *   val to_float : t -> float
+ * 
+ * end
+ * 
+ * val flocq_version: Z.t *)
diff --git a/farith2/thry/B32.v b/farith2/thry/B32.v
index d3e811985799b915aa080cca6704658b9a029ff1..0c3f6367e504de1382e0a6b9f0babba8e09d1af4 100644
--- a/farith2/thry/B32.v
+++ b/farith2/thry/B32.v
@@ -8,7 +8,6 @@ Require Coq.Arith.Wf_nat.
 Require Import Extraction.
 Require Import Qextended Rextended.
 
-
 (** * An instanciation of Flocq's BinarySingleNan for 32 bits IEEE-754 floating points *)
 
 Module B32.
diff --git a/farith2/thry/GenericFloat.v b/farith2/thry/GenericFloat.v
index 98a473620ef0ca9a54a83f9df3db9d16085c1f6e..d8a92271a7ada9f64f68bbf599c30f0be7285486 100644
--- a/farith2/thry/GenericFloat.v
+++ b/farith2/thry/GenericFloat.v
@@ -1,15 +1,72 @@
-From Flocq Require Import IEEE754.BinarySingleNaN.
-From Coq Require Import Program ZArith Bool.
-Require Import Assert  Utils Interval B32.
+From Flocq Require Import Core.Core IEEE754.BinarySingleNaN IEEE754.Bits.
+From Coq Require Import Program ZArith Bool Lia Reals Qreals ZBits.
+Require Import Assert  Utils Interval Qextended Rextended.
+
+Definition cprec mw := (Z.succ mw)%Z.
+
+Definition cemax ew := Zpower 2 (ew - 1).
+  (* (if Z.eqb ew 1 then 1 else Z.pow_pos 2 (Z.to_pos (ew - 1)))%Z. *)
+
+Definition check_param mw ew :=
+  andb (andb (0 <? mw)%Z (0 <? ew)%Z) (cprec mw <? cemax ew)%Z.
 
 Record Generic { v } : Type := {
-    prec : Z;
-    emax : Z;
-    Hprec : FLX.Prec_gt_0 prec;
-    Hemax : Prec_lt_emax prec emax;
-    value : v prec emax;
+    mw : Z;
+    ew : Z;
+    HG: check_param mw ew = true;
+    value : v (cprec mw) (cemax ew);
   }.
 
+Lemma check_param_is_Hprec : forall mw ew, (check_param mw ew = true) -> FLX.Prec_gt_0 (cprec mw).
+Proof.
+  intros mw ew H.
+  unfold check_param in H.
+rewrite !Bool.andb_true_iff in H.
+rewrite <- !Zlt_is_lt_bool in H.
+intuition.
+unfold FLX.Prec_gt_0.
+unfold cprec.
+lia.
+Qed.
+
+Lemma check_param_is_Hw : forall mw ew, (check_param mw ew = true) -> FLX.Prec_gt_0 mw.
+Proof.
+  intros mw ew H.
+  unfold check_param in H.
+rewrite !Bool.andb_true_iff in H.
+rewrite <- !Zlt_is_lt_bool in H.
+intuition.
+Qed.
+
+Lemma check_param_is_Hemax : forall mw ew, (check_param mw ew = true) -> Prec_lt_emax (cprec mw) (cemax ew).
+Proof.
+  intros mw ew H.
+  unfold check_param in H.
+rewrite !Bool.andb_true_iff in H.
+rewrite <- !Zlt_is_lt_bool in H.
+intuition.
+Qed.
+
+Definition prec { v } (f: @Generic v) := cprec (mw f).
+
+Definition emax { v } (f: @Generic v) := cemax (ew f).
+
+Definition Hprec { v } (f: @Generic v) := check_param_is_Hprec (mw f) (ew f) (HG f).
+
+Definition Hemax { v } (f: @Generic v) := check_param_is_Hemax (mw f) (ew f) (HG f).
+
+Definition mk_generic { v } mw ew (H: check_param mw ew = true) (x: forall prec emax, FLX.Prec_gt_0 prec -> Prec_lt_emax prec emax -> v prec emax) : @Generic v :=
+  let prec := cprec mw in
+  let emax := cemax ew in
+  let Hprec : FLX.Prec_gt_0 prec := check_param_is_Hprec _ _ H in
+  let Hemax : Prec_lt_emax prec emax := check_param_is_Hemax _ _ H in
+    {|
+      mw := mw;
+      ew := ew;
+      HG := H;
+      value := x prec emax Hprec Hemax;
+    |}.
+
 Program Definition unify { v } (p e p' e' : Z) (f : v p' e') (Hp : p = p') (Hp : e = e') : v p e := f.
 
 Program Definition same_format_cast {v } {p e p' e' : Z} (H : ((p =? p') && (e =? e') = true)%Z) (f : v p' e') : v p e := f.
@@ -22,30 +79,37 @@ Next Obligation.
   now rewrite (proj1 (Z.eqb_eq _ _) B).
 Defined.
 
+
 Definition same_format { v1 v2 } (x : @Generic v1) (y : @Generic v2) : bool :=
   Z.eqb (prec x) (prec y) && Z.eqb (emax x) (emax y).
 
 Definition mk_with {v1 v2} (x : @Generic v1) (y:v2 (prec x) (emax x)) : @Generic v2 :=
    {|
-      prec := prec x;
-      emax := emax x;
-      Hprec := Hprec x;
-      Hemax := Hemax x;
+      mw := mw x;
+      ew := ew x;
+      HG := HG x;
       value := y;
    |}.
 
+
+Definition mk_witho {v1 v2 } (x:@Generic v1) (y:option (v2 (prec x) (emax x))) : option (@Generic v2) :=
+  match y with
+    | Some r => Some (mk_with x r)
+    | None => None
+  end.
+
+
 Module GenericFloat.
 
-  Definition F : Type := @Generic binary_float.
+  Definition t : Type := @Generic binary_float.
 
   Module F_inhab.
-    Definition t : Type := F.
+    Definition t : Type := t.
     Program Definition dummy := {|
-      prec := 24;
-      emax := 128;
+      mw := 24;
+      ew := 128;
       value := BinarySingleNaN.B754_nan;
-      Hprec := _;
-      Hemax := _;
+      HG := _;
     |}.
     Solve All Obligations with easy.
   End F_inhab.
@@ -60,29 +124,164 @@ Module GenericFloat.
 
   Module AssertB := Assert (B_inhab).
 
-  Program Definition add (m : mode) (x y : F) :=
-    match same_format x y with
-    | true => Some {|
-        prec := prec x;
-        emax := emax x;
-        Hprec := Hprec x;
-        Hemax := Hemax x;
-        value := @Bplus _ _ (Hprec x) (Hemax x) m (value x) (same_format_cast _ (value y))
-      |}
-    | false => None
-  end.
+  Definition of_q' prec emax Hprec Hemax (m : mode) (q : Qx) : binary_float prec emax :=
+    match Qx_classify q with
+    | Qx_ZERO _ _ _ _ => B754_zero false
+    | Qx_INF _ _ _ => B754_infinity false
+    | Qx_MINF _ _ _ => B754_infinity true
+    | Qx_UNDEF _ _ _ => B754_nan
+    | Qx_NZERO _ _ _ _ _ =>
+      match num q with
+      | Z0 => B754_nan (** absurd *)
+      | Z.pos pn =>
+        SF2B _ (proj1 (Bdiv_correct_aux prec emax Hprec Hemax m false pn 0%Z false (Z.to_pos (den q)) 0%Z))
+      | Z.neg nn =>
+        SF2B _ (proj1 (Bdiv_correct_aux prec emax Hprec Hemax m true nn 0%Z false (Z.to_pos (den q)) 0%Z))
+      end
+    end.
+
+  (* Lemma of_q_correct' : forall prec emax Hprec Hemax m q, Q2Rx q = B2Rx (of_q' prec emax Hprec Hemax m q). *)
+  (*   Proof. *)
+  (*     intros prec emax Hprec Hemax m q. *)
+  (*     unfold of_q', Q2Rx; destruct (Qx_classify q). *)
+  (*     - rewrite e, e0. reflexivity. *)
+  (*     - rewrite e, e0. reflexivity. *)
+  (*     - rewrite e, e0. reflexivity. *)
+  (*     - rewrite e, e0. *)
+  (*       destruct (Z.pos pq =? 0)%Z; try reflexivity. *)
+  (*       unfold Rdefinitions.Q2R; simpl. *)
+  (*       now rewrite Rmult_0_l. *)
+  (*     - rewrite e. destruct s; rewrite e0; simpl. *)
+  (*       * replace (Q2R (Z.pos nq # pq)) with *)
+  (*       ((F2R (Float radix2 (cond_Zopp false (Z.pos nq)) 0)) *)
+  (*          / (F2R (Float radix2 (cond_Zopp false (Z.pos pq)) 0)))%R. *)
+  (*       exact (Bdiv_correct_aux' mode false nq 0 false pq 0). *)
+  (*       compute [F2R cond_Zopp Q2R]; simpl. *)
+  (*       rewrite <- !P2R_INR. *)
+  (*       rewrite !Rmult_1_r. *)
+  (*       reflexivity. *)
+  (*     * replace (Q2R (Z.neg nq # pq)) with *)
+  (*       ((F2R (Float radix2 (cond_Zopp true (Z.pos nq)) 0)) *)
+  (*          / (F2R (Float radix2 (cond_Zopp false (Z.pos pq)) 0)))%R. *)
+  (*       exact (Bdiv_correct_aux' mode true nq 0 false pq 0). *)
+  (*       compute [F2R cond_Zopp Q2R]; simpl. *)
+  (*       rewrite <- !P2R_INR. *)
+  (*       rewrite !Rmult_1_r. *)
+  (*       reflexivity. *)
+  (*    Qed. *)
+
+  Definition of_q mw ew (m : mode) (q : Qx) : t :=
+    AssertF.assert (check_param mw ew)
+                   (fun H => mk_generic mw ew H (fun prec emax Hprec Hemax => of_q' prec emax Hprec Hemax m q)).
 
-  Definition Fadd (m : mode) (x y : F) : F :=
+  Definition add (m : mode) (x y : t) : t :=
     AssertF.assert (same_format x y) (fun H => mk_with x (@Bplus _ _ (Hprec x) (Hemax x) m (value x) (same_format_cast H (value y)))).
 
-  Definition Fsub (m : mode) (x y : F) : F :=
-    AssertF.assert (same_format x y) (fun H => {|
-      prec := prec x;
-      emax := emax x;
-      Hprec := Hprec x;
-      Hemax := Hemax x;
-      value := @Bminus _ _ (Hprec x) (Hemax x) m (value x) (same_format_cast H (value y));
-    |}).
+  Definition sub (m : mode) (x y : t) : t :=
+    AssertF.assert (same_format x y) (fun H => mk_with x (@Bminus _ _ (Hprec x) (Hemax x) m (value x) (same_format_cast H (value y)))).
+
+  Definition mul (m : mode) (x y : t) : t :=
+    AssertF.assert (same_format x y) (fun H => mk_with x (@Bmult _ _ (Hprec x) (Hemax x) m (value x) (same_format_cast H (value y)))).
+
+  Definition div (m : mode) (x y : t) : t :=
+    AssertF.assert (same_format x y) (fun H => mk_with x (@Bdiv _ _ (Hprec x) (Hemax x) m (value x) (same_format_cast H (value y)))).
+
+  Definition sqrt (m : mode) (x : t) : t :=
+    mk_with x (@Bsqrt _ _ (Hprec x) (Hemax x) m (value x)).
+
+  Definition abs (x : t) : t :=
+    mk_with x (@Babs _ _ (value x)).
+
+  Definition le (x y : t) : bool :=
+    AssertB.assert (same_format x y) (fun H => (@Bleb _ _ (value x) (same_format_cast H (value y)))).
+
+  Definition lt (x y : t) : bool :=
+    AssertB.assert (same_format x y) (fun H => (@Bltb _ _ (value x) (same_format_cast H (value y)))).
+
+  Definition eq (x y : t) : bool :=
+    AssertB.assert (same_format x y) (fun H => (@Beqb _ _ (value x) (same_format_cast H (value y)))).
+
+  Definition ge (x y : t) : bool :=
+    AssertB.assert (same_format x y) (fun H => (@Bleb _ _ (same_format_cast H (value y)) (value x))).
+
+  Definition gt (x y : t) : bool :=
+    AssertB.assert (same_format x y) (fun H => (@Bltb _ _ (same_format_cast H (value y)) (value x))).
+
+(** ** 4. convertions to and from [Z] and [Q]*)
+
+   Program Definition of_bits' mw ew (H:check_param mw ew = true) (b : Z) : binary_float (cprec mw) (cemax ew) :=
+     match Bits.binary_float_of_bits mw ew _ _ _ b with
+     | Binary.B754_nan _ _ _ _ _ => B754_nan
+     | Binary.B754_zero _ _ s => B754_zero s
+     | Binary.B754_infinity _ _ s => B754_infinity s
+     | Binary.B754_finite _ _ s m e H => B754_finite s m e H
+     end.
+   Next Obligation.
+   unfold check_param in H.
+   rewrite !Bool.andb_true_iff in H.
+   rewrite <- !Zlt_is_lt_bool in H.
+   intuition.
+   Defined.
+   Next Obligation.
+   unfold check_param in H.
+   rewrite !Bool.andb_true_iff in H.
+   rewrite <- !Zlt_is_lt_bool in H.
+   intuition.
+   Defined.
+   Next Obligation.
+   unfold check_param in H.
+   rewrite !Bool.andb_true_iff in H.
+   rewrite <- !Zlt_is_lt_bool in H.
+   intuition.
+   Defined.
+
+   Definition of_bits mw ew (z : Z.t) : t :=
+    AssertF.assert (check_param mw ew)
+                   (fun H =>
+    {|
+      mw := mw;
+      ew := ew;
+      HG := H;
+      value := of_bits' mw ew H z;
+    |}
+).
+
+   Definition pl_cst mw := (Zaux.iter_nat xO (Z.to_nat (Z.pred mw)) xH)%Z.
+
+   Lemma pl_valid mw (Hw:Prec_gt_0 mw) : (Z.pos (Digits.digits2_pos (pl_cst mw)) <? (cprec mw))%Z = true.
+   Proof.
+     assert (G:forall n, Digits.digits2_Pnat (Zaux.iter_nat xO n xH)%Z = n).
+     - induction n.
+       * reflexivity.
+       * rewrite iter_nat_S; simpl.
+         rewrite IHn; reflexivity.
+     - rewrite Digits.Zpos_digits2_pos.
+       rewrite <- Digits.Z_of_nat_S_digits2_Pnat.
+       unfold pl_cst, cprec.  unfold Prec_gt_0 in Hw.
+       rewrite G;clear G.
+       rewrite Nat2Z.inj_succ.
+       rewrite Z2Nat.id; [rewrite Z.ltb_lt | ]; lia.
+   Qed.
+
+   Definition to_bits (f : t) : Z :=
+     match value f with
+     | B754_nan =>
+       Bits.bits_of_binary_float (mw f) (ew f) (Binary.B754_nan (prec f) (emax f) true (pl_cst (mw f)) (pl_valid (mw f) (check_param_is_Hw _ _ (HG f))))
+     | B754_zero s => Bits.bits_of_binary_float (mw f) (ew f) (Binary.B754_zero (prec f) (emax f) s)
+     | B754_infinity s => Bits.bits_of_binary_float (mw f) (ew f) (Binary.B754_infinity (prec f) (emax f) s)
+     | B754_finite s m e H => Bits.bits_of_binary_float (mw f) (ew f) (Binary.B754_finite (prec f) (emax f) s m e H)
+     end.
+
+   Definition nan mw ew : t :=
+    AssertF.assert (check_param mw ew) (fun H =>  mk_generic mw ew H (fun _ _ _ _ => B754_nan)).
+
+   Definition zero mw ew b : t :=
+    AssertF.assert (check_param mw ew) (fun H =>  mk_generic mw ew H (fun _ _ _ _ => B754_zero b)).
+
+   Definition inf mw ew b : t :=
+    AssertF.assert (check_param mw ew) (fun H =>  mk_generic mw ew H (fun _ _ _ _ => B754_infinity b)).
+
+   
 End GenericFloat.
 
 Module GenericInterval.
@@ -92,11 +291,10 @@ Module GenericInterval.
   Module I_inhab.
     Definition t : Type := t.
     Program Definition dummy : t := {|
-      prec := 24;
-      emax := 128;
+      mw := 23;
+      ew := 8;
       value := Intv 24 128 -oo +oo true;
-      Hprec := _;
-      Hemax := _;
+      HG := _;
     |}.
     Solve All Obligations with easy.
   End I_inhab.
@@ -119,4 +317,24 @@ Module GenericInterval.
        | None => None
       end                                                                                                          ).
 
+  Definition add (m:mode) (x:t) (y:t) : t :=
+    AssertI.assert (same_format x y) (fun H =>
+       mk_with x (Iadd (prec x) (emax x) (Hprec x) (Hemax x) m (value x) (same_format_cast H (value y)))
+  ).
+
+  Definition ge (x:t) : option t :=
+    mk_witho x (Ige (prec x) (emax x) (value x)).
+  Definition gt (x:t) : option t :=
+    mk_witho x (Igt (prec x) (emax x) (value x)).
+  Definition le (x:t) : option t :=
+    mk_witho x (Ile (prec x) (emax x) (value x)).
+  Definition lt (x:t) : option t :=
+    mk_witho x (Ilt (prec x) (emax x) (value x)).
+  Definition singleton (x:GenericFloat.t) : t :=
+    mk_with x (singleton _ _ (value x)).
+  Definition is_singleton (x:t) : option GenericFloat.t :=
+    mk_witho x (is_singleton _ _ (value x)).
+  Definition top (mw:Z) (ew:Z) : t :=
+    AssertI.assert (check_param mw ew) (fun H => @mk_generic Interval mw ew H (fun prec emax _ _ => top prec emax)).
+
 End GenericInterval.
diff --git a/farith2/thry/Interval.v b/farith2/thry/Interval.v
index 10e0b29d695363b02b3ba35f0ba76d94a3184ae6..28dd3c8d6883942f7555eda89f9f7682fea70cbd 100644
--- a/farith2/thry/Interval.v
+++ b/farith2/thry/Interval.v
@@ -67,7 +67,67 @@ Proof.
   destruct I;reflexivity.
 Qed.
 
-  
+
+  Program Definition top : Interval := Intv -oo +oo true.
+
+  Program Definition bot : Interval_opt := None.
+
+  Lemma top_correct :
+    forall (x : float), contains (proj1_sig top) x.
+  Proof with auto.
+    unfold top, contains; fdestruct x; simpl...
+  Qed.
+
+  Lemma bot_correct :
+    forall (x : float), contains_opt bot x -> False.
+  Proof with auto.
+    unfold bot, contains; fdestruct x.
+  Qed.
+
+  Program Definition is_singleton (I : Interval) : option float :=
+    match proj1_sig I with
+    | Inan => Some NaN
+    | Intv a b n =>
+      if Beqb a b && (negb (Beqb a (B754_zero false))) && negb n then Some a
+      else None
+    end.
+
+  Program Definition s0 : Interval := Intv (B754_zero false) (B754_zero true) false.
+
+  Program Theorem is_singleton_correct :
+    forall (I : Interval) (x : float), (is_singleton I = Some x) -> (forall y, contains I y -> x = y).
+  Proof.
+    intros [[| a b n] H] x; cbn.
+    - intros H1; inversion H1; fdestruct y.
+    - intros H' y [[H1 H2] | H2].
+      + destruct (Beqb a b) eqn:?E, (negb n) eqn:?E,    (negb (Beqb a (B754_zero false))) eqn:?; try  easy; simpl in *.
+        assert (a <= y <= a) by eauto using E, Beqb_symm, Beqb_Bleb, Bleb_trans.
+        apply Bleb_antisymm_strict in H0.
+        * inversion H'; subst; reflexivity.
+        * now apply Bool.negb_true_iff in Heqb0.
+      + destruct (Beqb a b) eqn:?E, (negb n) eqn:?E,    (negb (Beqb a (B754_zero false))) eqn:?; try  easy; simpl in *.
+        destruct n; try easy.
+        fdestruct y.
+  Qed.
+
+  Program Definition singleton (x : float) : Interval :=
+    match x with
+    | B754_nan => Inan
+    | _ => Intv x x false
+    end.
+  Next Obligation.
+    apply Bleb_refl.
+    fdestruct x.
+  Defined.
+
+  Program Theorem singleton_correct :
+    forall (x : float), Beqb x (B754_zero true) = false -> is_singleton (singleton x) = Some x.
+  Proof.
+    intros [ [ ] | [ ] | | [ ] ] H; try easy; cbn.
+    - rewrite Z.compare_refl, Pcompare_refl; reflexivity.
+    - rewrite Z.compare_refl, Pcompare_refl; reflexivity.
+  Qed.
+
 Program Definition inter' (I1 I2 : Interval') : option Interval' :=
   match I1, I2 with
   | Inan, Inan => Some Inan
diff --git a/src_colibri2/theories/FP/.ocamlformat b/src_colibri2/theories/FP/.ocamlformat
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src_colibri2/theories/FP/dom_interval.ml b/src_colibri2/theories/FP/dom_interval.ml
index 7c14b026c2471385a06a017f2f33485ebef30c1b..2623343aca7bddc98b657988e0678ec316ea5d1d 100644
--- a/src_colibri2/theories/FP/dom_interval.ml
+++ b/src_colibri2/theories/FP/dom_interval.ml
@@ -22,31 +22,65 @@ open Colibri2_popop_lib
 open Colibri2_core
 (* open Colibri2_stdlib.Std *)
 
-let debug = Debug.register_info_flag
-  ~desc:"for intervals for the arithmetic theory"
-  "FP.interval"
+let debug =
+  Debug.register_info_flag ~desc:"for intervals for the arithmetic theory"
+    "FP.interval"
 
-module D = Interval32
+module D = Farith2.I
 
-let dom = Dom.Kind.create (module struct type t = D.t let name = "FP_ARITH" end)
+let dom =
+  Dom.Kind.create
+    (module struct
+      type t = D.t
 
-include (Dom.Lattice(struct
-    include D
-    let equal (x : t) (y : t) = Stdlib.(=) x y
-    let pp fmt x = Format.fprintf fmt "%s" (D.to_string x)
-    let key = dom
-    let inter _ d1 d2 = inter d1 d2
-    let is_singleton _ d =
-      Option.map (fun x -> Float32.nodevalue @@ Float32.index x) (D.is_singleton d)
-  end
-))
+      let name = "FP_ARITH"
+    end)
 
-let (!<) e = function
-  | Some x -> x
-  | None -> Egraph.contradiction e
+include Dom.Lattice (struct
+  include D
+
+  let key = dom
+
+  let inter _ d1 d2 = inter d1 d2
+
+  let is_singleton _ d =
+    Option.map
+      (fun x -> Fp_value.nodevalue @@ Fp_value.index x)
+      (D.is_singleton d)
+end)
+
+let ( !< ) e = function Some x -> x | None -> Egraph.contradiction e
+
+let neg_cmp = function
+  | `Lt -> `Ge
+  | `Le -> `Gt
+  | `Ge -> `Lt
+  | `Gt -> `Le
+  | `Eq -> `Ne
+  | `Ne -> `Ne
+
+let com_cmp = function
+  | `Lt -> `Gt
+  | `Le -> `Ge
+  | `Ge -> `Le
+  | `Gt -> `Lt
+  | `Eq -> `Eq
+  | `Ne -> `Ne
+
+let backward d c x =
+  let r =
+    match c with
+    | `Lt -> D.lt x
+    | `Gt -> D.gt x
+    | `Le -> D.le x
+    | `Ge -> D.ge x
+    | `Eq -> Some D.(top ~ew:(ew x) ~mw:(mw x))
+    | `Ne -> Some D.(top ~ew:(ew x) ~mw:(mw x))
+  in
+  match r with None -> Egraph.contradiction d | Some r -> r
 
 (** {2 Initialization} *)
-let converter d (f:Ground.t) =
+let converter d (f : Ground.t) =
   let r = Ground.node f in
   let reg n = Egraph.register d n in
   let open Monad in
@@ -55,62 +89,98 @@ let converter d (f:Ground.t) =
   let set = updd upd_dom in
   let get = getd dom in
   let getm = getv Rounding_mode.key in
+
   (* let fget x = CCOpt.get_exn_or "bad" (Egraph.get_dom d dom x) in *)
-  let propagate prop a b =
-    reg a; reg b;
-    (match Egraph.get_dom d dom a with
-    | Some _ -> ()
-    | None -> Egraph.set_dom d dom a (D.top));
-    (match Egraph.get_dom d dom b with
-    | Some _ -> ()
-    | None -> Egraph.set_dom d dom b (D.top));
-    attach d (
-      (* set a (let+ vr = getb r in Debug.dprintf2 debug "[FP] set top %a" Format.pp_print_bool vr; D.top) && *)
-      (* set b (let+ vr = getb r in Debug.dprintf2 debug "[FP] set top %a" Format.pp_print_bool vr; D.top) && *)
-      (* setb r (let+ vr = getb r in Debug.dprintf4 debug "[FP] domains : a = %a, b = %a" D.pp (fget a) D.pp (fget b); vr) && *)
-      set a (let+ vr = getb r and+ va = get a and+ vb = get b in
-        Debug.dprintf4 debug "[FP] domains : a = %a, b = %a" D.pp va D.pp vb;
-        if vr then !< d (fst (prop va vb)) else va) &&
-      set b (let+ vr = getb r and+ va = get a and+ vb = get b in
-        Debug.dprintf4 debug "[FP] domains : a = %a, b = %a" D.pp va D.pp vb;
-        if vr then !< d (snd (prop va vb)) else vb)
-    )
+  (* let propagate ~mw ~ew prop a b =
+   *   reg a; reg b;
+   *   (match Egraph.get_dom d dom a with
+   *   | Some _ -> ()
+   *   | None -> Egraph.set_dom d dom a (D.top ~mw ~ew));
+   *   (match Egraph.get_dom d dom b with
+   *   | Some _ -> ()
+   *   | None -> Egraph.set_dom d dom b (D.top ~mw ~ew));
+   *   attach d (
+   *     (\* set a (let+ vr = getb r in Debug.dprintf2 debug "[FP] set top %a" Format.pp_print_bool vr; D.top) && *\)
+   *     (\* set b (let+ vr = getb r in Debug.dprintf2 debug "[FP] set top %a" Format.pp_print_bool vr; D.top) && *\)
+   *     (\* setb r (let+ vr = getb r in Debug.dprintf4 debug "[FP] domains : a = %a, b = %a" D.pp (fget a) D.pp (fget b); vr) && *\)
+   *     set a (let+ vr = getb r and+ va = get a and+ vb = get b in
+   *       Debug.dprintf4 debug "[FP] domains : a = %a, b = %a" D.pp va D.pp vb;
+   *       if vr then !< d (fst (prop va vb)) else va) &&
+   *     set b (let+ vr = getb r and+ va = get a and+ vb = get b in
+   *       Debug.dprintf4 debug "[FP] domains : a = %a, b = %a" D.pp va D.pp vb;
+   *       if vr then !< d (snd (prop va vb)) else vb)
+   *   )
+   * in *)
+  let cmp d cmp ~r ~a ~b =
+    let reg n = Egraph.register d n in
+    (* let test c =
+     *   match c with
+     *   | D.Uncomparable -> None
+     *   | Le -> (
+     *       match cmp with
+     *       | `Le -> Some true
+     *       | `Gt -> Some false
+     *       | `Lt | `Ge -> None)
+     *   | Lt -> (
+     *       match cmp with `Le | `Lt -> Some true | `Ge | `Gt -> Some false)
+     *   | Eq -> (
+     *       match cmp with `Le | `Ge -> Some true | `Lt | `Gt -> Some false)
+     *   | Ge -> (
+     *       match cmp with
+     *       | `Ge -> Some true
+     *       | `Lt -> Some false
+     *       | `Gt | `Le -> None)
+     *   | Gt -> (
+     *       match cmp with `Gt | `Ge -> Some true | `Lt | `Le -> Some false)
+     * in *)
+    reg a;
+    reg b;
+    attach d
+      ((* setb r
+          *    (let* va = get a and+ vb = get b in
+          *     test (D.is_comparable va vb))
+          * && *)
+       set b
+         (let+ va = get a and+ vr = getb r in
+          backward d (if vr then com_cmp cmp else com_cmp (neg_cmp cmp)) va)
+      && set a
+           (let+ vb = get b and+ vr = getb r in
+            backward d (if vr then cmp else neg_cmp cmp) vb))
   in
   match Ground.sem f with
-  | { app = {builtin = Expr.Fp_add (8, 24); _}; args; _} ->
-    let m, a, b = IArray.extract3_exn args in
-    reg m; reg a; reg b;
-    attach d (
-      set r (let+ vm = getm m and+ va = get a and+ vb = get b in D.add (D.to_mode vm) va vb)
-    )
-  | { app = {builtin = Expr.Fp_eq (8, 24); _}; args; _} ->
-    let a, b = IArray.extract2_exn args in
-    propagate D.eq_inv a b
-  | { app = {builtin = Expr.Fp_leq (8, 24); _}; args; _} ->
-    let a, b = IArray.extract2_exn args in
-    propagate D.le_inv a b
-  | { app = {builtin = Expr.Fp_lt (8, 24); _}; args; _} ->
-    let a, b = IArray.extract2_exn args in
-    propagate D.lt_inv a b
-  | { app = {builtin = Expr.Fp_geq (8, 24); _}; args; _} ->
-    let a, b = IArray.extract2_exn args in
-    propagate D.ge_inv a b
-  | { app = {builtin = Expr.Fp_gt (8, 24); _}; args; _} ->
-    let a, b = IArray.extract2_exn args in
-    propagate D.gt_inv a b
+  | { app = { builtin = Expr.Fp_add (8, 24); _ }; args; _ } ->
+      let m, a, b = IArray.extract3_exn args in
+      reg m;
+      reg a;
+      reg b;
+      attach d
+        (set r
+           (let+ vm = getm m and+ va = get a and+ vb = get b in
+            D.add vm va vb))
+  | { app = { builtin = Expr.Fp_eq (8, 24); _ }; args; _ } ->
+      let a, b = IArray.extract2_exn args in
+      cmp d `Eq ~r ~a ~b
+  | { app = { builtin = Expr.Fp_leq (8, 24); _ }; args; _ } ->
+      let a, b = IArray.extract2_exn args in
+      cmp d `Le ~r ~a ~b
+  | { app = { builtin = Expr.Fp_lt (8, 24); _ }; args; _ } ->
+      let a, b = IArray.extract2_exn args in
+      cmp d `Lt ~r ~a ~b
+  | { app = { builtin = Expr.Fp_geq (8, 24); _ }; args; _ } ->
+      let a, b = IArray.extract2_exn args in
+      cmp d `Ge ~r ~a ~b
+  | { app = { builtin = Expr.Fp_gt (8, 24); _ }; args; _ } ->
+      let a, b = IArray.extract2_exn args in
+      cmp d `Gt ~r ~a ~b
   | _ -> ()
 
 let init env =
   Ground.register_converter env converter;
-  Daemon.attach_reg_value env
-    Float32.key
-    (fun d value ->
-       let v = Float32.value value in
-        if not Farith.B32.(eq v (zero true) || eq v (zero false)) then begin
-          (** An ugly way to fix a bug with the singleton {0} *)
-          let s = D.singleton (D.float32_of_B32 v) in
-          Debug.dprintf4 debug "[FP] set dom %a for %a" D.pp s Node.pp (Float32.node value);
-          Egraph.set_dom d dom (Float32.node value) s
-        end
-    )
-  
+  Daemon.attach_reg_value env Fp_value.key (fun d value ->
+      let v = Fp_value.value value in
+      if not (Farith2.F.is_zero v) then (
+        (* An ugly way to fix a bug with the singleton {0} *)
+        let s = D.singleton v in
+        Debug.dprintf4 debug "[FP] set dom %a for %a" D.pp s Node.pp
+          (Fp_value.node value);
+        Egraph.set_dom d dom (Fp_value.node value) s))
diff --git a/src_colibri2/theories/FP/dune b/src_colibri2/theories/FP/dune
index 09f9db029f87ace159cb599eaecaa0f73d3533cb..30caa47cd9b4b4b5a3c73a853565de84b3882aca 100644
--- a/src_colibri2/theories/FP/dune
+++ b/src_colibri2/theories/FP/dune
@@ -4,7 +4,6 @@
  (synopsis "theory of floatting points for colibri2")
  (libraries
   containers
-  farith
   farith2
   colibri2.stdlib
   colibri2.popop_lib
diff --git a/src_colibri2/theories/FP/float32.ml b/src_colibri2/theories/FP/float32.ml
deleted file mode 100644
index 16ffe354cf2c1e2b872f999b2d3e6433f40fcabd..0000000000000000000000000000000000000000
--- a/src_colibri2/theories/FP/float32.ml
+++ /dev/null
@@ -1,225 +0,0 @@
-(*************************************************************************)
-(*  This file is part of Colibri2.                                       *)
-(*                                                                       *)
-(*  Copyright (C) 2014-2021                                              *)
-(*    CEA   (Commissariat à l'énergie atomique et aux énergies           *)
-(*           alternatives)                                               *)
-(*                                                                       *)
-(*  you can redistribute it and/or modify it under the terms of the GNU  *)
-(*  Lesser General Public License as published by the Free Software      *)
-(*  Foundation, version 2.1.                                             *)
-(*                                                                       *)
-(*  It is distributed in the hope that it will be useful,                *)
-(*  but WITHOUT ANY WARRANTY; without even the implied warranty of       *)
-(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *)
-(*  GNU Lesser General Public License for more details.                  *)
-(*                                                                       *)
-(*  See the GNU Lesser General Public License version 2.1                *)
-(*  for more details (enclosed in the file licenses/LGPLv2.1).           *)
-(*************************************************************************)
-
-open Fp_value
-open Colibri2_theories_LRA
-open Colibri2_popop_lib
-
-
-module N32 = struct let name = "Float32" end
-module Float32 = Value.Register(MakeFloat(Farith.B32)(N32))
-
-include Float32
-
-let cst' c = index c
-
-let cst c = node (cst' c)
-
-let debug = Debug.register_info_flag
-  ~desc:"for float32 for the FP theory"
-  "FP.float32"
-
-(** Initialise type interpretation
-    TODO : fix bounds (there is a finite set of 32 bits floats)
-*)
-let init_ty d =
-  let specials =
-    let open Base.Sequence.Generator in
-    let (let*) = (>>=) in
-    run (
-      let* _ = yield (Farith.B32.default_nan) in
-      let* _ = yield (Farith.B32.zero true) in
-      let* _ = yield (Farith.B32.zero false) in
-      let* _ = yield (Farith.B32.infm) in
-      yield (Farith.B32.infp))
-  in
-  let open Base.Sequence in
-  let finites = posint_sequence >>| Farith.B32.of_bits in
-  let fp_seq = append specials finites in
-  let fp_values = fp_seq >>| Float32.of_value in
-  Interp.Register.ty d (fun d ty ->
-      match ty with
-      | {app={builtin = Builtin.Float(8, 24);_};_} ->
-        let open Interp.SeqLim in
-        Some (of_seq d fp_values)
-      | _ -> None)
-
-let interp d n = Opt.get_exn Impossible (Egraph.get_value d n)
-
-let compute_ground d t =
-  let (!>>>) t = RealValue.coerce_value (interp d t) in
-  let (!>>) t = Rounding_mode.coerce_value (interp d t) in
-  let (!>) t = Float32.coerce_value (interp d t) in
-  let (!<) v = `Some (Float32.nodevalue (Float32.index v)) in
-  let (!<<) v = `Some (Boolean.BoolValue.nodevalue (Boolean.BoolValue.index v)) in
-  match Ground.sem t with
-  | { app = {builtin = Expr.Real_to_fp (8, 24); _}; args; _} ->
-    let m, r = IArray.extract2_exn args in
-    !< (Farith.B32.of_q !>>m !>>>r)
-  | { app = {builtin = Expr.Plus_infinity (8, 24); _}; args; _} ->
-    assert (IArray.is_empty args);
-    !< (Farith.B32.infp)
-  | { app = {builtin = Expr.Minus_infinity (8, 24); _}; args; _} ->
-    assert (IArray.is_empty args);
-    !< (Farith.B32.infm)
-  | { app = {builtin = Expr.NaN (8, 24); _}; args; _} ->
-    assert (IArray.is_empty args);
-    !< (Farith.B32.(nan true Z.one))
-  | { app = {builtin = Expr.Plus_zero (8, 24); _}; args; _} ->
-    assert (IArray.is_empty args);
-    !< (Farith.B32.zerop)
-  | { app = {builtin = Expr.Minus_zero (8, 24); _}; args; _} ->
-    assert (IArray.is_empty args);
-    !< (Farith.B32.zero true)
-  | { app = {builtin = Expr.Fp_add (8, 24); _}; args; _} ->
-    let m, a, b = IArray.extract3_exn args in
-    !< (Farith.B32.add !>>m !>a !>b)
-  | { app = {builtin = Expr.Fp_sub (8, 24); _}; args; _} ->
-    let m, a, b = IArray.extract3_exn args in
-    !< (Farith.B32.sub !>>m !>a !>b)
-  | { app = {builtin = Expr.Fp_mul (8, 24); _}; args; _} ->
-    let m, a, b = IArray.extract3_exn args in
-    !< (Farith.B32.mul !>>m !>a !>b)
-  | { app = {builtin = Expr.Fp_abs (8, 24); _}; args; _} ->
-    let a = IArray.extract1_exn args in
-    !< (Farith.B32.abs !>a)
-  | { app = {builtin = Expr.Fp_div (8, 24); _}; args; _} ->
-    let m, a, b = IArray.extract3_exn args in
-    if Farith.B32.(eq !>b (zero true) || eq !>b (zero false)) then `Uninterp
-    else !< (Farith.B32.div !>>m !>a !>b)
-  | { app = {builtin = Expr.Fp_eq (8, 24); _}; args; _} ->
-    let a, b = IArray.extract2_exn args in
-    !<< (Farith.B32.eq !>a !>b)
-  | { app = {builtin = Expr.Fp_leq (8, 24); _}; args; _} ->
-    let a, b = IArray.extract2_exn args in
-    !<< (Farith.B32.le !>a !>b)
-  | { app = {builtin = Expr.Fp_lt (8, 24); _}; args; _} ->
-    let a, b = IArray.extract2_exn args in
-    !<< (Farith.B32.lt !>a !>b)
-  | { app = {builtin = Expr.Fp_geq (8, 24); _}; args; _} ->
-    let a, b = IArray.extract2_exn args in
-    !<< (Farith.B32.ge !>a !>b)
-  | { app = {builtin = Expr.Fp_gt (8, 24); _}; args; _} ->
-    let a, b = IArray.extract2_exn args in
-    !<< (Farith.B32.gt !>a !>b)
-  | _ -> `None
-
-let init_check d = Interp.Register.check d (fun d t ->
-    let check r =
-      Value.equal r (interp d (Ground.node t))
-    in
-    match compute_ground d t with
-    | `None -> NA
-    | `Some v -> Interp.check_of_bool (check v)
-    | `Uninterp ->
-      Interp.check_of_bool (Uninterp.On_uninterpreted_domain.check d t)
-  )
-
-let attach_interp d g =
-  let f d g =
-    match compute_ground d g with
-    | `None -> raise Impossible
-    | `Some v -> Egraph.set_value d (Ground.node g) v
-    | `Uninterp -> Uninterp.On_uninterpreted_domain.propagate d g
-  in
-  Interp.WatchArgs.create d f g
-
-let converter d (f:Ground.t) =
-  let r = Ground.node f in
-  let reg n = Egraph.register d n in
-  let merge n = Egraph.register d n; Egraph.merge d r n in
-  let open Monad in
-  let get a = Monad.getv Float32.key a in
-  let getq a = Monad.getv RealValue.key a in
-  let set a = Monad.setv Float32.key a in
-  let _getb a = Monad.getv Boolean.BoolValue.key a in
-  let setb a = Monad.setv Boolean.BoolValue.key a in
-  let (!>>) t = Rounding_mode.value (Rounding_mode.coerce_nodevalue (interp d t )) in
-  (* let (!>>>) t = RealValue.value (RealValue.coerce_nodevalue (interp d t )) in *)
-  let is_zero v = Farith.B32.(eq v (zero true) || eq v (zero false)) in
-  let cmp cmp a b =
-    reg a; reg b;
-    attach d (setb r (let+ va = get a and+ vb = get b in cmp va vb));
-  in
-  match Ground.sem f with
-  | {app={builtin=Expr.Real_to_fp (8, 24); _}; args; _} ->
-    let m, a = IArray.extract2_exn args in
-    reg m; reg a;
-    Debug.dprintf2 debug "[FP] assign a value to %a" Node.pp a;
-    attach d (set r (let+ va = getq a in Farith.B32.of_q !>>m va));
-  | {app={builtin=Expr.NaN (8, 24); _}; args; _} ->
-    assert (IArray.is_empty args);
-    merge (cst (Farith.B32.nan true Z.one))
-  | {app={builtin=Expr.Plus_infinity (8, 24); _}; args; _} ->
-    assert (IArray.is_empty args);
-    merge (cst (Farith.B32.infp))
-  | {app={builtin=Expr.Minus_infinity (8, 24); _}; args; _} ->
-    assert (IArray.is_empty args);
-    merge (cst (Farith.B32.infm))
-  | {app={builtin=Expr.Plus_zero (8, 24); _}; args; _} ->
-    assert (IArray.is_empty args);
-    merge (cst (Farith.B32.zerop))
-  | {app={builtin=Expr.Minus_zero (8, 24); _}; args; _} ->
-    assert (IArray.is_empty args);
-    merge (cst (Farith.B32.zero true))
-  | {app={builtin=Expr.Fp_abs (8, 24); _}; args; _} ->
-    let a = IArray.extract1_exn args in
-    reg a; attach_interp d f;
-    attach d (set r (let+ va = get a in Farith.B32.abs va));
-  | {app={builtin=Expr.Fp_add (8, 24); _}; args; _} ->
-    let m, a, b = IArray.extract3_exn args in
-    reg m; reg a; reg b; attach_interp d f;
-    attach d (set r (let+ va = get a and+ vb = get b in Farith.B32.add !>>m va vb));
-  | {app={builtin=Expr.Fp_sub (8, 24); _}; args; _} ->
-    let m, a, b = IArray.extract3_exn args in
-    reg m; reg a; reg b; attach_interp d f;
-    attach d (set r (let+ va = get a and+ vb = get b in Farith.B32.sub !>>m va vb));
-  | {app={builtin=Expr.Fp_mul (8, 24); _}; args; _} ->
-    let m, a, b = IArray.extract3_exn args in
-    reg m; reg a; reg b; attach_interp d f;
-    attach d (
-      set r (let* va = get a and+ vb = get b in
-             if is_zero vb then None else Some (Farith.B32.mul !>>m va vb))
-    );
-  | {app={builtin=Expr.Fp_div (8, 24); _}; args; _} ->
-    let m, a, b = IArray.extract3_exn args in
-    reg m; reg a; reg b; attach_interp d f;
-    attach d (
-      set r (let* va = get a and+ vb = get b in
-             if is_zero vb then None else Some (Farith.B32.div !>>m va vb))
-    );
-  | {app={builtin=Expr.Fp_leq (8, 24); _}; args; _} ->
-    let a, b = IArray.extract2_exn args in
-    cmp Farith.B32.le a b; attach_interp d f;
-  | {app={builtin=Expr.Fp_gt (8, 24); _}; args; _} ->
-    let a, b = IArray.extract2_exn args in
-    cmp Farith.B32.gt a b; attach_interp d f;
-  | {app={builtin=Expr.Fp_geq (8, 24); _}; args; _} ->
-    let a, b = IArray.extract2_exn args in
-    cmp Farith.B32.ge a b; attach_interp d f;
-  | {app={builtin=Expr.Fp_eq (8, 24); _}; args; _} ->
-    let a, b = IArray.extract2_exn args in
-    cmp Farith.B32.eq a b; attach_interp d f;
-  | _ -> ()
-
-let init env =
-  Ground.register_converter env converter;
-  init_ty env;
-  init_check env
diff --git a/src_colibri2/theories/FP/float32.mli b/src_colibri2/theories/FP/float32.mli
deleted file mode 100644
index 9f3efaae6112d8fd67db119080a51a67bd97f858..0000000000000000000000000000000000000000
--- a/src_colibri2/theories/FP/float32.mli
+++ /dev/null
@@ -1,27 +0,0 @@
-(*************************************************************************)
-(*  This file is part of Colibri2.                                       *)
-(*                                                                       *)
-(*  Copyright (C) 2014-2021                                              *)
-(*    CEA   (Commissariat à l'énergie atomique et aux énergies           *)
-(*           alternatives)                                               *)
-(*                                                                       *)
-(*  you can redistribute it and/or modify it under the terms of the GNU  *)
-(*  Lesser General Public License as published by the Free Software      *)
-(*  Foundation, version 2.1.                                             *)
-(*                                                                       *)
-(*  It is distributed in the hope that it will be useful,                *)
-(*  but WITHOUT ANY WARRANTY; without even the implied warranty of       *)
-(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *)
-(*  GNU Lesser General Public License for more details.                  *)
-(*                                                                       *)
-(*  See the GNU Lesser General Public License version 2.1                *)
-(*  for more details (enclosed in the file licenses/LGPLv2.1).           *)
-(*************************************************************************)
-
-include Value.S with type s = Farith.B32.t
-
-val cst': Farith.B32.t -> t
-
-val cst:  Farith.B32.t -> Node.t
-
-val init : Egraph.wt -> unit
diff --git a/src_colibri2/theories/FP/fp.ml b/src_colibri2/theories/FP/fp.ml
index cdee9a24e8412d4a20c0fa92862ef8269b595902..051ba09be7be0718ed8902ff23510cf60b145197 100644
--- a/src_colibri2/theories/FP/fp.ml
+++ b/src_colibri2/theories/FP/fp.ml
@@ -21,8 +21,7 @@
 let th_register env =
   Rounding_mode.init env;
   Dom_interval.init env;
-  Float32.init env
+  Fp_value.init env
 
 (* Add the theory to defaults *)
-let () =
-  Init.add_default_theory th_register
+let () = Init.add_default_theory th_register
diff --git a/src_colibri2/theories/FP/fp_value.ml b/src_colibri2/theories/FP/fp_value.ml
index a40c709cb78884624f70a3a98f9876919677afe0..2f78529956cec2354ec47f9efc3d3d997c012610 100644
--- a/src_colibri2/theories/FP/fp_value.ml
+++ b/src_colibri2/theories/FP/fp_value.ml
@@ -21,35 +21,258 @@
 open Colibri2_popop_lib
 open Popop_stdlib
 
-module type FloatName = sig val name : string end
+module F = struct
+  include Farith2.F
+  include MkDatatype (Farith2.F)
 
-(** Extends a module of type [Farith.S] to be of type [Value.Kind.Value] *)
-module MakeFloat (F : Farith.S) (N : FloatName) = struct
+  let name = "Fp_value"
+end
 
-  (** Extends a module of type [Farith.S] with [hash_fold_t] and [sexp_of_t] *)
-  module HF = struct
-    include F
-    let hash_fold_t s t = Base.Hash.fold_int s (hash t)
-    let sexp_of_t = sexp_of_t_of_pp F.pp
-  end
+module N = struct
+  let name = "Float"
+end
 
-  include HF
-  module M = Map.Make(HF)
-  module S = Extset.MakeOfMap(M)
-  module H = XHashtbl.Make(HF)
+module Float = Value.Register (F)
+include Float
 
-  let name = N.name
+let cst' c = index c
 
-end
+let cst c = node (cst' c)
+
+let debug =
+  Debug.register_info_flag ~desc:"for value for the FP theory" "FP.fp_value"
 
 (** Generate the sequence of all positive integers (without 0) *)
 let posint_sequence_without_zero =
   let open Base.Sequence.Generator in
-  let rec loop i =
-    yield i >>= (fun () -> loop (Z.succ i))
-  in
+  let rec loop i = yield i >>= fun () -> loop (Z.succ i) in
   run (loop Z.one)
 
 (** Generate the sequence of positive integers (without 0) *)
 let posint_sequence =
   Base.Sequence.shift_right posint_sequence_without_zero Z.zero
+
+(** Initialise type interpretation
+    TODO : fix bounds (there is a finite set of 32 bits floats)
+*)
+let init_ty d =
+  let specials ~mw ~ew =
+    let open Base.Sequence.Generator in
+    let ( let* ) = ( >>= ) in
+    run
+      (let* () = yield (F.nan ~mw ~ew) in
+       let* () = yield (F.zero ~mw ~ew true) in
+       let* () = yield (F.zero ~mw ~ew false) in
+       let* () = yield (F.inf ~mw ~ew false) in
+       yield (F.inf ~mw ~ew true))
+  in
+  let open Base.Sequence in
+  let finites ~mw ~ew = posint_sequence >>| F.of_bits ~mw ~ew in
+  let fp_seq ~mw ~ew = append (specials ~mw ~ew) (finites ~mw ~ew) in
+  let fp_values ~mw ~ew = fp_seq ~mw ~ew >>| of_value in
+  Interp.Register.ty d (fun d ty ->
+      match ty with
+      | { app = { builtin = Builtin.Float (ew, prec); _ }; _ } ->
+          let open Interp.SeqLim in
+          Some (of_seq d (fp_values ~ew ~mw:(prec - 1)))
+      | _ -> None)
+
+let interp d n = Opt.get_exn Impossible (Egraph.get_value d n)
+
+let compute_ground d t =
+  let ( !>>> ) t = Colibri2_theories_LRA.RealValue.coerce_value (interp d t) in
+  let ( !>> ) t = Rounding_mode.coerce_value (interp d t) in
+  let ( !> ) t = coerce_value (interp d t) in
+  let ( !< ) v = `Some (nodevalue (index v)) in
+  let ( !<< ) v =
+    `Some (Boolean.BoolValue.nodevalue (Boolean.BoolValue.index v))
+  in
+  match Ground.sem t with
+  | { app = { builtin = Expr.Real_to_fp (ew, prec); _ }; args; _ } ->
+      let m, r = IArray.extract2_exn args in
+      !<(F.of_q ~ew ~mw:(prec - 1) ~mode:!>>m !>>>r)
+  | { app = { builtin = Expr.Plus_infinity (ew, prec); _ }; args; _ } ->
+      assert (IArray.is_empty args);
+      !<(F.inf ~ew ~mw:(prec - 1) false)
+  | { app = { builtin = Expr.Minus_infinity (ew, prec); _ }; args; _ } ->
+      assert (IArray.is_empty args);
+      !<(F.inf ~ew ~mw:(prec - 1) true)
+  | { app = { builtin = Expr.NaN (ew, prec); _ }; args; _ } ->
+      assert (IArray.is_empty args);
+      !<(F.nan ~ew ~mw:(prec - 1))
+  | { app = { builtin = Expr.Plus_zero (ew, prec); _ }; args; _ } ->
+      assert (IArray.is_empty args);
+      !<(F.zero ~ew ~mw:(prec - 1) false)
+  | { app = { builtin = Expr.Minus_zero (ew, prec); _ }; args; _ } ->
+      assert (IArray.is_empty args);
+      !<(F.zero ~ew ~mw:(prec - 1) true)
+  | { app = { builtin = Expr.Fp_add (_ew, _prec); _ }; args; _ } ->
+      let m, a, b = IArray.extract3_exn args in
+      !<(F.add !>>m !>a !>b)
+  | { app = { builtin = Expr.Fp_sub (_ew, _prec); _ }; args; _ } ->
+      let m, a, b = IArray.extract3_exn args in
+      !<(F.sub !>>m !>a !>b)
+  | { app = { builtin = Expr.Fp_mul (_ew, _prec); _ }; args; _ } ->
+      let m, a, b = IArray.extract3_exn args in
+      !<(F.mul !>>m !>a !>b)
+  | { app = { builtin = Expr.Fp_abs (_ew, _prec); _ }; args; _ } ->
+      let a = IArray.extract1_exn args in
+      !<(F.abs !>a)
+  | { app = { builtin = Expr.Fp_div (_ew, _prec); _ }; args; _ } ->
+      let m, a, b = IArray.extract3_exn args in
+      !<(F.div !>>m !>a !>b)
+  | { app = { builtin = Expr.Fp_eq (_ew, _prec); _ }; args; _ } ->
+      let a, b = IArray.extract2_exn args in
+      !<<(F.eq !>a !>b)
+  | { app = { builtin = Expr.Fp_leq (_ew, _prec); _ }; args; _ } ->
+      let a, b = IArray.extract2_exn args in
+      !<<(F.le !>a !>b)
+  | { app = { builtin = Expr.Fp_lt (_ew, _prec); _ }; args; _ } ->
+      let a, b = IArray.extract2_exn args in
+      !<<(F.lt !>a !>b)
+  | { app = { builtin = Expr.Fp_geq (_ew, _prec); _ }; args; _ } ->
+      let a, b = IArray.extract2_exn args in
+      !<<(F.ge !>a !>b)
+  | { app = { builtin = Expr.Fp_gt (_ew, _prec); _ }; args; _ } ->
+      let a, b = IArray.extract2_exn args in
+      !<<(F.gt !>a !>b)
+  | _ -> `None
+
+let init_check d =
+  Interp.Register.check d (fun d t ->
+      let check r = Value.equal r (interp d (Ground.node t)) in
+      match compute_ground d t with
+      | `None -> NA
+      | `Some v -> Interp.check_of_bool (check v)
+      | `Uninterp ->
+          Interp.check_of_bool (Uninterp.On_uninterpreted_domain.check d t))
+
+let attach_interp d g =
+  let f d g =
+    match compute_ground d g with
+    | `None -> raise Impossible
+    | `Some v -> Egraph.set_value d (Ground.node g) v
+    | `Uninterp -> Uninterp.On_uninterpreted_domain.propagate d g
+  in
+  Interp.WatchArgs.create d f g
+
+let converter d (f : Ground.t) =
+  let r = Ground.node f in
+  let reg n = Egraph.register d n in
+  let merge n =
+    Egraph.register d n;
+    Egraph.merge d r n
+  in
+  let open Monad in
+  let get a = Monad.getv key a in
+  let getq a = Monad.getv Colibri2_theories_LRA.RealValue.key a in
+  let set a = Monad.setv key a in
+  let _getb a = Monad.getv Boolean.BoolValue.key a in
+  let setb a = Monad.setv Boolean.BoolValue.key a in
+  let ( !>> ) t =
+    Rounding_mode.value (Rounding_mode.coerce_nodevalue (interp d t))
+  in
+  (* let (!>>>) t = RealValue.value (RealValue.coerce_nodevalue (interp d t )) in *)
+  let cmp cmp a b =
+    reg a;
+    reg b;
+    attach d
+      (setb r
+         (let+ va = get a and+ vb = get b in
+          cmp va vb))
+  in
+  match Ground.sem f with
+  | { app = { builtin = Expr.Real_to_fp (ew, prec); _ }; args; _ } ->
+      let m, a = IArray.extract2_exn args in
+      reg m;
+      reg a;
+      Debug.dprintf2 debug "[FP] assign a value to %a" Node.pp a;
+      attach d
+        (set r
+           (let+ va = getq a in
+            F.of_q ~ew ~mw:(prec - 1) ~mode:!>>m va))
+  | { app = { builtin = Expr.NaN (ew, prec); _ }; args; _ } ->
+      assert (IArray.is_empty args);
+      merge (cst (F.nan ~ew ~mw:(prec - 1)))
+  | { app = { builtin = Expr.Plus_infinity (ew, prec); _ }; args; _ } ->
+      assert (IArray.is_empty args);
+      merge (cst (F.inf ~ew ~mw:(prec - 1) false))
+  | { app = { builtin = Expr.Minus_infinity (ew, prec); _ }; args; _ } ->
+      assert (IArray.is_empty args);
+      merge (cst (F.inf ~ew ~mw:(prec - 1) true))
+  | { app = { builtin = Expr.Plus_zero (ew, prec); _ }; args; _ } ->
+      assert (IArray.is_empty args);
+      merge (cst (F.zero ~ew ~mw:(prec - 1) false))
+  | { app = { builtin = Expr.Minus_zero (ew, prec); _ }; args; _ } ->
+      assert (IArray.is_empty args);
+      merge (cst (F.zero ~ew ~mw:(prec - 1) true))
+  | { app = { builtin = Expr.Fp_abs (_ew, _prec); _ }; args; _ } ->
+      let a = IArray.extract1_exn args in
+      reg a;
+      attach_interp d f;
+      attach d
+        (set r
+           (let+ va = get a in
+            F.abs va))
+  | { app = { builtin = Expr.Fp_add (_ew, _prec); _ }; args; _ } ->
+      let m, a, b = IArray.extract3_exn args in
+      reg m;
+      reg a;
+      reg b;
+      attach_interp d f;
+      attach d
+        (set r
+           (let+ va = get a and+ vb = get b in
+            F.add !>>m va vb))
+  | { app = { builtin = Expr.Fp_sub (_ew, _prec); _ }; args; _ } ->
+      let m, a, b = IArray.extract3_exn args in
+      reg m;
+      reg a;
+      reg b;
+      attach_interp d f;
+      attach d
+        (set r
+           (let+ va = get a and+ vb = get b in
+            F.sub !>>m va vb))
+  | { app = { builtin = Expr.Fp_mul (_ew, _prec); _ }; args; _ } ->
+      let m, a, b = IArray.extract3_exn args in
+      reg m;
+      reg a;
+      reg b;
+      attach_interp d f;
+      attach d
+        (set r
+           (let* va = get a and+ vb = get b in
+            if F.is_zero vb then None else Some (F.mul !>>m va vb)))
+  | { app = { builtin = Expr.Fp_div (_ew, _prec); _ }; args; _ } ->
+      let m, a, b = IArray.extract3_exn args in
+      reg m;
+      reg a;
+      reg b;
+      attach_interp d f;
+      attach d
+        (set r
+           (let* va = get a and+ vb = get b in
+            if F.is_zero vb then None else Some (F.div !>>m va vb)))
+  | { app = { builtin = Expr.Fp_leq (_ew, _prec); _ }; args; _ } ->
+      let a, b = IArray.extract2_exn args in
+      cmp F.le a b;
+      attach_interp d f
+  | { app = { builtin = Expr.Fp_gt (_ew, _prec); _ }; args; _ } ->
+      let a, b = IArray.extract2_exn args in
+      cmp F.gt a b;
+      attach_interp d f
+  | { app = { builtin = Expr.Fp_geq (_ew, _prec); _ }; args; _ } ->
+      let a, b = IArray.extract2_exn args in
+      cmp Farith2.F.ge a b;
+      attach_interp d f
+  | { app = { builtin = Expr.Fp_eq (_ew, _prec); _ }; args; _ } ->
+      let a, b = IArray.extract2_exn args in
+      cmp Farith2.F.eq a b;
+      attach_interp d f
+  | _ -> ()
+
+let init env =
+  Ground.register_converter env converter;
+  init_ty env;
+  init_check env
diff --git a/src_colibri2/theories/FP/fp_value.mli b/src_colibri2/theories/FP/fp_value.mli
index 6c759aa446a375910404bdaba4f48383a5ed0b12..04557f872a38ee1cffb4588f8caaeb8f3d4d21e4 100644
--- a/src_colibri2/theories/FP/fp_value.mli
+++ b/src_colibri2/theories/FP/fp_value.mli
@@ -18,16 +18,7 @@
 (*  for more details (enclosed in the file licenses/LGPLv2.1).           *)
 (*************************************************************************)
 
-(** Helpers to generate new interpretations of floating points *)
+include Value.S with type s = Farith2.F.t
+(** Foating points values *)
 
-(** Sequence of all positive integers *)
-val posint_sequence : Z.t Base.Sequence.t
-
-(** Names (string) wrapped in a module *)
-module type FloatName = sig val name : string end
-
-(**
-   Helper to extend a module of type [Farith.S] into a module of
-   type [Value.Kind.Value]
-*)
-module MakeFloat (F : Farith.S) (_ : FloatName) : Colibri2_popop_lib.Popop_stdlib.NamedDatatype with type t = F.t
+val init : Egraph.wt -> unit
diff --git a/src_colibri2/theories/FP/interval32.ml b/src_colibri2/theories/FP/interval32.ml
deleted file mode 100644
index a23adc11371f513e416325fc5e3ea5c81ecb2d13..0000000000000000000000000000000000000000
--- a/src_colibri2/theories/FP/interval32.ml
+++ /dev/null
@@ -1,54 +0,0 @@
-include Farith2.Intv32.Intv32
-
-let float32_to_B32 f =
-  (Farith.B32.of_bits (Farith2.B32.B32.to_bits f))
-
-let float32_of_B32 f =
-  (Farith2.B32.B32.of_bits (Farith.B32.to_bits f))
-
-let to_mode (m : Farith.mode) : Farith2.Farith_Big.mode =
-  match m with
-  | Farith.NE -> Farith2.Farith_Big.NE
-  | Farith.ZR -> Farith2.Farith_Big.ZR
-  | Farith.DN -> Farith2.Farith_Big.DN
-  | Farith.UP -> Farith2.Farith_Big.UP
-  | Farith.NA -> Farith2.Farith_Big.NA
-
-(* let is_singleton = function
-  | Farith2.Interval.Inan -> Some Farith.B32.default_nan
-  | Intv (a, b, n) ->
-    if (&&) (Farith2.BinarySingleNaN.coq_Beqb prec emax a b) (not n)
-    then Some (float32_to_B32 a)
-    else None *)
-
-let to_string = function
-  | Farith2.Interval.Inan -> "{ NaN }"
-  | Intv (a, b, nan) ->
-    if nan then
-      Format.sprintf "[%a, %a] + NaN"
-        Farith.B32.pp (float32_to_B32 a)
-        Farith.B32.pp (float32_to_B32 b)
-    else
-      Format.sprintf "[%a, %a]"
-        Farith.B32.pp (float32_to_B32 a)
-        Farith.B32.pp (float32_to_B32 b)
-
-let debug = Debug.register_info_flag
-  ~desc:"trash"
-  "FP.trash"
-
-let pp fmt x = Format.fprintf fmt "%s" (to_string x)
-
-let inter a b =
-  let r = inter a b in
-  match r with
-  | Some x -> Debug.dprintf6 debug "INTER %a %a = %a" pp a pp b pp x; r
-  | None -> Debug.dprintf4 debug "INTER %a %a = BOT" pp a pp b; r
-  
-let is_singleton d =
-  match is_singleton d with
-  | None -> None
-  | Some x ->
-    if Farith2.B32.B32.eq x (Farith2.B32.B32.of_q NE Q.zero) then
-      None
-    else None (** todo *)
diff --git a/src_colibri2/theories/FP/rounding_mode.ml b/src_colibri2/theories/FP/rounding_mode.ml
index d86092b0eaf0cf28568f3dc4eecb9903f108ecdf..55775b37c90506a61690e3fd89a9b2657a70bac5 100644
--- a/src_colibri2/theories/FP/rounding_mode.ml
+++ b/src_colibri2/theories/FP/rounding_mode.ml
@@ -23,13 +23,13 @@ open Popop_stdlib
 
 module FarithModes = struct
   let string_of_mode = function
-    | Farith.NE -> "RoundNearestTiesToEven"
-    | Farith.NA -> "RoundNearestTiesToAway"
-    | Farith.UP -> "RoundTowardPositive"
-    | Farith.DN -> "RoundTowardNegative"
-    | Farith.ZR -> "RoundTowardZero"
+    | Farith2.NE -> "RoundNearestTiesToEven"
+    | Farith2.NA -> "RoundNearestTiesToAway"
+    | Farith2.UP -> "RoundTowardPositive"
+    | Farith2.DN -> "RoundTowardNegative"
+    | Farith2.ZR -> "RoundTowardZero"
 
-  type t = Farith.mode
+  type t = Farith2.mode
 
   let hash = Hashtbl.hash
 
@@ -57,11 +57,11 @@ include Modes
 let rounding_mode_sequence =
   let open Base.Sequence.Generator in
   (
-    yield Farith.NE >>= fun () ->
-    yield Farith.NA >>= fun () ->
-    yield Farith.UP >>= fun () ->
-    yield Farith.DN >>= fun () ->
-    yield Farith.ZR
+    yield Farith2.NE >>= fun () ->
+    yield Farith2.NA >>= fun () ->
+    yield Farith2.UP >>= fun () ->
+    yield Farith2.DN >>= fun () ->
+    yield Farith2.ZR
   ) |> run
 
 let init_ty d =
@@ -83,15 +83,15 @@ let compute_cst t =
   let (!<) v = `Some (Modes.nodevalue (Modes.index v)) in
   match Ground.sem t with
   | { app = {builtin = Expr.RoundNearestTiesToEven; _}; _} ->
-    !< Farith.NE
+    !< Farith2.NE
   | { app = {builtin = Expr.RoundNearestTiesToAway; _}; _} ->
-    !< Farith.NA
+    !< Farith2.NA
   | { app = {builtin = Expr.RoundTowardNegative; _}; _} ->
-    !< Farith.DN
+    !< Farith2.DN
   | { app = {builtin = Expr.RoundTowardPositive; _}; _} ->
-    !< Farith.UP
+    !< Farith2.UP
   | { app = {builtin = Expr.RoundTowardZero; _}; _} ->
-    !< Farith.ZR
+    !< Farith2.ZR
   | _ -> `None
 
 let converter d f =
@@ -100,15 +100,15 @@ let converter d f =
   let merge n = Egraph.register d n; Egraph.merge d r n in
   match Ground.sem f with
   | { app = {builtin = Expr.RoundNearestTiesToEven; _}; _} ->
-    merge (cst Farith.NE)
+    merge (cst Farith2.NE)
   | { app = {builtin = Expr.RoundNearestTiesToAway; _}; _} ->
-    merge (cst Farith.NA)
+    merge (cst Farith2.NA)
   | { app = {builtin = Expr.RoundTowardNegative; _}; _} ->
-    merge (cst Farith.DN)
+    merge (cst Farith2.DN)
   | { app = {builtin = Expr.RoundTowardPositive; _}; _} ->
-    merge (cst Farith.UP)
+    merge (cst Farith2.UP)
   | { app = {builtin = Expr.RoundTowardZero; _}; _} ->
-    merge (cst Farith.ZR)
+    merge (cst Farith2.ZR)
   | _ -> ()
 
 let init_check d = Interp.Register.check d (fun d t ->
diff --git a/src_colibri2/theories/FP/rounding_mode.mli b/src_colibri2/theories/FP/rounding_mode.mli
index 07d44840f8cd6f6e13c76968fe8c592c546f77e1..047ea2a1cc05ca046dd153e809df279e9ecb929b 100644
--- a/src_colibri2/theories/FP/rounding_mode.mli
+++ b/src_colibri2/theories/FP/rounding_mode.mli
@@ -18,6 +18,6 @@
 (*  for more details (enclosed in the file licenses/LGPLv2.1).           *)
 (*************************************************************************)
 
-include Value.S with type s = Farith.mode
+include Value.S with type s = Farith2.mode
 
 val init : Egraph.wt -> unit