diff --git a/.gitignore b/.gitignore index 9a29e7203869e1ecc46d5ff7d20d8bf5ac626a96..19cae1d82697e9c99de6c83af7113225881f0a66 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,18 @@ why3shapes.gz dolmen/ farith/ +# coq artifacts + +**/*.vo +**/*.vok +**/*.glob +**/*.lia.cache +**/*.aux +**/*.vk +**/.CoqMakefile.d +**/*.vos +**/CoqMakefile +**/CoqMakefile.conf # doc *.html @@ -27,3 +39,7 @@ farith/ # debug files *debug_graph.tmp/ + +# mac artifacts + +.DS_Store \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 93c4d178a6214e0d5fe2663ddeee85c6f376836c..f7e889a02cd5cbfd1f8e57192876a40edf57270d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,6 +1,5 @@ stages: - test - - deploy .build-matrix: parallel: @@ -41,8 +40,10 @@ tests: - opam pin --no-action --yes . - opam depext --yes colibri2 colibrics farith - opam install . --deps-only --locked --with-test --with-doc --yes - - opam depext --yes --install why3 core jingoo yojson logs core # For generation not done in release mode + - opam repo add coq-released https://coq.inria.fr/opam/released + - opam depext --yes --install why3 core jingoo yojson logs core coq-flocq # For generation not done in release mode - opam depext --yes --install ounit2 # For tests move to opam file? + - make -C farith2 - make - make test tags: @@ -69,40 +70,32 @@ generate-static: - opam depext --yes colibri2 colibrics farith - opam install . --dry-run --deps-only --locked --with-test --with-doc --yes | awk '/-> installed/{print $3}' | xargs opam depext --yes - opam install . --deps-only --locked --with-test --with-doc --yes - - opam depext --yes --install why3 core jingoo yojson logs core # For generation not done in release mode + - opam repo add coq-released https://coq.inria.fr/opam/released + - opam depext --yes --install why3 core jingoo yojson logs core coq-flocq coq-coq2html # For generation not done in release mode - opam depext --yes --install ounit2 # For tests move to opam file? + - echo -e "\e[31mCompile Farith2\e[0m" + - make -C farith2 + - make -C farith2 doc + - tar -cvf farith2_doc.tar.gz farith2/doc/ + - echo -e "\e[31mCompile Colibri2 static\e[0m" - make - make test - dune install --destdir=destdir --prefix=/ - cp destdir/bin/colibri2 colibri2 + - echo -e "\e[31mCreate Starexec archive\e[0m" + - mkdir bin + - mv colibri2 bin/ + - mv misc/starexec_run_default bin/ + - tar -cvf colibri2_starexec_$CI_COMMIT_SHORT_SHA.tar.gz bin/ tags: - docker rules: - - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH when: manual allow_failure: true - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH artifacts: - expose_as: 'Colibri2 binary' paths: - colibri2 - -starexec: - stage: deploy - # ocaml/opam:alpine-3.13-opam - image: ocaml/opam@sha256:db94e740f73340f00113f09e5da81fe93183f241ac5974393cc51dfbdcc17b2d - rules: - - when: manual - dependencies: - - generate-static - script: - - mkdir bin - - mv colibri2 bin/ - - mv misc/starexec_run_default bin/ - artifacts: - expose_as: 'Starexec' - name: 'colibri2_starexec_$CI_COMMIT_SHORT_SHA' - paths: - - bin/ - tags: - - docker + - farith2_doc.tar.gz + - colibri2_starexec_$CI_COMMIT_SHORT_SHA.tar.gz diff --git a/.lia.cache b/.lia.cache new file mode 100644 index 0000000000000000000000000000000000000000..76ef9efc0b944a7bc41557da47a648f617d36de3 Binary files /dev/null and b/.lia.cache differ diff --git a/doc/coq2html.js b/doc/coq2html.js new file mode 100644 index 0000000000000000000000000000000000000000..d869b602b1c5c440f89ef0198d6c1130eb2d9c88 --- /dev/null +++ b/doc/coq2html.js @@ -0,0 +1,25 @@ + +function toggleDisplay(id) +{ + var elt = document.getElementById(id); + if (elt.style.display == 'none') { + elt.style.display = 'block'; + } else { + elt.style.display = 'none'; + } +} + +function hideAll(cls) +{ + var testClass = new RegExp("(^|s)" + cls + "(s|$)"); + var tag = tag || "*"; + var elements = document.getElementsByTagName("div"); + var current; + var length = elements.length; + for(var i=0; i<length; i++){ + current = elements[i]; + if(testClass.test(current.className)) { + current.style.display = 'none'; + } + } +} diff --git a/dune b/dune index 0da6f6ffbb95d0e01b2d771ba974e6bf7b166b3b..9b7d214cb9666ef92a20b79f0c4c45d75c476175 100644 --- a/dune +++ b/dune @@ -1 +1 @@ -(vendored_dirs dolmen farith) +(vendored_dirs dolmen farith farith2) diff --git a/farith2/.gitignore b/farith2/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..a7d81f76f0912920a891a8325f5ffd2b6b603617 --- /dev/null +++ b/farith2/.gitignore @@ -0,0 +1,45 @@ +.*.aux +.*.d +*.a +*.cma +*.cmi +*.cmo +*.cmx +*.cmxa +*.cmxs +*.glob +*.ml.d +*.ml4.d +*.mlg.d +*.mli.d +*.mllib.d +*.mlpack.d +*.native +*.o +*.v.d +*.vio +*.vo +*.vok +*.vos +.coq-native +.csdp.cache +.lia.cache +.nia.cache +.nlia.cache +.nra.cache +csdp.cache +lia.cache +nia.cache +nlia.cache +nra.cache +native_compute_profile_*.data + +# generated timing files +*.timing.diff +*.v.after-timing +*.v.before-timing +*.v.timing +time-of-build-after.log +time-of-build-before.log +time-of-build-both.log +time-of-build-pretty.log \ No newline at end of file diff --git a/farith2/.nra.cache b/farith2/.nra.cache new file mode 100644 index 0000000000000000000000000000000000000000..d98ef9c4b6c6b430155da61742d938534ee28064 Binary files /dev/null and b/farith2/.nra.cache differ diff --git a/farith2/B32.ml b/farith2/B32.ml new file mode 100644 index 0000000000000000000000000000000000000000..59a32b73f87cfe42b566455c13a4dc3f12353bef --- /dev/null +++ b/farith2/B32.ml @@ -0,0 +1,143 @@ +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/B32.mli b/farith2/B32.mli new file mode 100644 index 0000000000000000000000000000000000000000..e20ce0b7e88057374bc5023cf1911de183703639 --- /dev/null +++ b/farith2/B32.mli @@ -0,0 +1,49 @@ +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/BinInt.ml b/farith2/BinInt.ml new file mode 100644 index 0000000000000000000000000000000000000000..fc758fddab7cfa584a13b8e4514dc0ff942589e9 --- /dev/null +++ b/farith2/BinInt.ml @@ -0,0 +1,83 @@ + +module Z = + struct + type t = Farith_Big.big_int + + (** val pow : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int **) + + let pow x y = + Farith_Big.z_case + (fun _ -> Farith_Big.one) + (fun p -> Farith_Big.pow_pos x p) + (fun _ -> Farith_Big.zero) + y + + (** val to_nat : Farith_Big.big_int -> Farith_Big.big_int **) + + let to_nat z = + Farith_Big.z_case + (fun _ -> Farith_Big.zero) + (fun p -> Farith_Big.identity p) + (fun _ -> Farith_Big.zero) + z + + (** val to_pos : Farith_Big.big_int -> Farith_Big.big_int **) + + let to_pos z = + Farith_Big.z_case + (fun _ -> Farith_Big.one) + (fun p -> p) + (fun _ -> Farith_Big.one) + z + + (** val pos_div_eucl : + Farith_Big.big_int -> Farith_Big.big_int -> + Farith_Big.big_int * Farith_Big.big_int **) + + let rec pos_div_eucl a b = + Farith_Big.positive_case + (fun a' -> + let (q, r) = pos_div_eucl a' b in + let r' = + Farith_Big.add (Farith_Big.mult (Farith_Big.double Farith_Big.one) r) + Farith_Big.one + in + if Farith_Big.lt r' b + then ((Farith_Big.mult (Farith_Big.double Farith_Big.one) q), r') + else ((Farith_Big.add + (Farith_Big.mult (Farith_Big.double Farith_Big.one) q) + Farith_Big.one), (Farith_Big.sub r' b))) + (fun a' -> + let (q, r) = pos_div_eucl a' b in + let r' = Farith_Big.mult (Farith_Big.double Farith_Big.one) r in + if Farith_Big.lt r' b + then ((Farith_Big.mult (Farith_Big.double Farith_Big.one) q), r') + else ((Farith_Big.add + (Farith_Big.mult (Farith_Big.double Farith_Big.one) q) + Farith_Big.one), (Farith_Big.sub r' b))) + (fun _ -> + if Farith_Big.le (Farith_Big.double Farith_Big.one) b + then (Farith_Big.zero, Farith_Big.one) + else (Farith_Big.one, Farith_Big.zero)) + a + + (** val even : Farith_Big.big_int -> bool **) + + let even z = + Farith_Big.z_case + (fun _ -> true) + (fun p -> + Farith_Big.positive_case + (fun _ -> false) + (fun _ -> true) + (fun _ -> false) + p) + (fun p -> + Farith_Big.positive_case + (fun _ -> false) + (fun _ -> true) + (fun _ -> false) + p) + z + end diff --git a/farith2/BinInt.mli b/farith2/BinInt.mli new file mode 100644 index 0000000000000000000000000000000000000000..c0985b8cd475d4d04c18e43ecd1062fde75095e9 --- /dev/null +++ b/farith2/BinInt.mli @@ -0,0 +1,17 @@ + +module Z : + sig + type t = Farith_Big.big_int + + val pow : Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int + + val to_nat : Farith_Big.big_int -> Farith_Big.big_int + + val to_pos : Farith_Big.big_int -> Farith_Big.big_int + + val pos_div_eucl : + Farith_Big.big_int -> Farith_Big.big_int -> + Farith_Big.big_int * Farith_Big.big_int + + val even : Farith_Big.big_int -> bool + end diff --git a/farith2/BinNums.ml b/farith2/BinNums.ml new file mode 100644 index 0000000000000000000000000000000000000000..139597f9cb07c5d48bed18984ec4747f4b4f3438 --- /dev/null +++ b/farith2/BinNums.ml @@ -0,0 +1,2 @@ + + diff --git a/farith2/BinNums.mli b/farith2/BinNums.mli new file mode 100644 index 0000000000000000000000000000000000000000..139597f9cb07c5d48bed18984ec4747f4b4f3438 --- /dev/null +++ b/farith2/BinNums.mli @@ -0,0 +1,2 @@ + + diff --git a/farith2/BinPos.ml b/farith2/BinPos.ml new file mode 100644 index 0000000000000000000000000000000000000000..36df342ec382f6fbc471c010adf71baa3d412a2c --- /dev/null +++ b/farith2/BinPos.ml @@ -0,0 +1,165 @@ +open BinPosDef + +module Pos = + struct + (** val add_carry : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int **) + + let rec add_carry = fun p q -> Farith_Big.succ (Farith_Big.add p q) + + type mask = Pos.mask = + | IsNul + | IsPos of Farith_Big.big_int + | IsNeg + + (** val succ_double_mask : mask -> mask **) + + let succ_double_mask = function + | IsNul -> IsPos Farith_Big.one + | IsPos p -> IsPos (Farith_Big.succ_double p) + | IsNeg -> IsNeg + + (** val double_mask : mask -> mask **) + + let double_mask = function + | IsPos p -> IsPos (Farith_Big.double p) + | x0 -> x0 + + (** val double_pred_mask : Farith_Big.big_int -> mask **) + + let double_pred_mask x = + Farith_Big.positive_case + (fun p -> IsPos (Farith_Big.double (Farith_Big.double p))) + (fun p -> IsPos (Farith_Big.double + (Farith_Big.pred_double p))) + (fun _ -> IsNul) + x + + (** val sub_mask : Farith_Big.big_int -> Farith_Big.big_int -> mask **) + + let rec sub_mask x y = + Farith_Big.positive_case + (fun p -> + Farith_Big.positive_case + (fun q -> double_mask (sub_mask p q)) + (fun q -> succ_double_mask (sub_mask p q)) + (fun _ -> IsPos (Farith_Big.double p)) + y) + (fun p -> + Farith_Big.positive_case + (fun q -> succ_double_mask (sub_mask_carry p q)) + (fun q -> double_mask (sub_mask p q)) + (fun _ -> IsPos (Farith_Big.pred_double p)) + y) + (fun _ -> + Farith_Big.positive_case + (fun _ -> IsNeg) + (fun _ -> IsNeg) + (fun _ -> IsNul) + y) + x + + (** val sub_mask_carry : + Farith_Big.big_int -> Farith_Big.big_int -> mask **) + + and sub_mask_carry x y = + Farith_Big.positive_case + (fun p -> + Farith_Big.positive_case + (fun q -> succ_double_mask (sub_mask_carry p q)) + (fun q -> double_mask (sub_mask p q)) + (fun _ -> IsPos (Farith_Big.pred_double p)) + y) + (fun p -> + Farith_Big.positive_case + (fun q -> double_mask (sub_mask_carry p q)) + (fun q -> succ_double_mask (sub_mask_carry p q)) + (fun _ -> double_pred_mask p) + y) + (fun _ -> IsNeg) + x + + (** val iter : ('a1 -> 'a1) -> 'a1 -> Farith_Big.big_int -> 'a1 **) + + let rec iter f x n = + Farith_Big.positive_case + (fun n' -> f (iter f (iter f x n') n')) + (fun n' -> iter f (iter f x n') n') + (fun _ -> f x) + n + + (** val div2 : Farith_Big.big_int -> Farith_Big.big_int **) + + let div2 p = + Farith_Big.positive_case + (fun p0 -> p0) + (fun p0 -> p0) + (fun _ -> Farith_Big.one) + p + + (** val div2_up : Farith_Big.big_int -> Farith_Big.big_int **) + + let div2_up p = + Farith_Big.positive_case + (fun p0 -> Farith_Big.succ p0) + (fun p0 -> p0) + (fun _ -> Farith_Big.one) + p + + (** val sqrtrem_step : + (Farith_Big.big_int -> Farith_Big.big_int) -> (Farith_Big.big_int -> + Farith_Big.big_int) -> (Farith_Big.big_int * mask) -> + Farith_Big.big_int * mask **) + + let sqrtrem_step f g = function + | (s, y) -> + (match y with + | IsPos r -> + let s' = Farith_Big.succ_double (Farith_Big.double s) in + let r' = g (f r) in + if Farith_Big.le s' r' + then ((Farith_Big.succ_double s), (sub_mask r' s')) + else ((Farith_Big.double s), (IsPos r')) + | _ -> + ((Farith_Big.double s), + (sub_mask (g (f Farith_Big.one)) (Farith_Big.double + (Farith_Big.double Farith_Big.one))))) + + (** val sqrtrem : Farith_Big.big_int -> Farith_Big.big_int * mask **) + + let rec sqrtrem p = + Farith_Big.positive_case + (fun p0 -> + Farith_Big.positive_case + (fun p1 -> + sqrtrem_step (fun x -> Farith_Big.succ_double x) (fun x -> + Farith_Big.succ_double x) (sqrtrem p1)) + (fun p1 -> + sqrtrem_step (fun x -> Farith_Big.double x) (fun x -> + Farith_Big.succ_double x) (sqrtrem p1)) + (fun _ -> (Farith_Big.one, (IsPos (Farith_Big.double + Farith_Big.one)))) + p0) + (fun p0 -> + Farith_Big.positive_case + (fun p1 -> + sqrtrem_step (fun x -> Farith_Big.succ_double x) (fun x -> + Farith_Big.double x) (sqrtrem p1)) + (fun p1 -> + sqrtrem_step (fun x -> Farith_Big.double x) (fun x -> + Farith_Big.double x) (sqrtrem p1)) + (fun _ -> (Farith_Big.one, (IsPos Farith_Big.one))) + p0) + (fun _ -> (Farith_Big.one, IsNul)) + p + + (** val iter_op : + ('a1 -> 'a1 -> 'a1) -> Farith_Big.big_int -> 'a1 -> 'a1 **) + + let rec iter_op op p a = + Farith_Big.positive_case + (fun p0 -> op a (iter_op op p0 (op a a))) + (fun p0 -> iter_op op p0 (op a a)) + (fun _ -> a) + p + end diff --git a/farith2/BinPos.mli b/farith2/BinPos.mli new file mode 100644 index 0000000000000000000000000000000000000000..00dbe4ffa8517199cf70622e0a701d540499afa4 --- /dev/null +++ b/farith2/BinPos.mli @@ -0,0 +1,37 @@ +open BinPosDef + +module Pos : + sig + val add_carry : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int + + type mask = Pos.mask = + | IsNul + | IsPos of Farith_Big.big_int + | IsNeg + + val succ_double_mask : mask -> mask + + val double_mask : mask -> mask + + val double_pred_mask : Farith_Big.big_int -> mask + + val sub_mask : Farith_Big.big_int -> Farith_Big.big_int -> mask + + val sub_mask_carry : Farith_Big.big_int -> Farith_Big.big_int -> mask + + val iter : ('a1 -> 'a1) -> 'a1 -> Farith_Big.big_int -> 'a1 + + val div2 : Farith_Big.big_int -> Farith_Big.big_int + + val div2_up : Farith_Big.big_int -> Farith_Big.big_int + + val sqrtrem_step : + (Farith_Big.big_int -> Farith_Big.big_int) -> (Farith_Big.big_int -> + Farith_Big.big_int) -> (Farith_Big.big_int * mask) -> + Farith_Big.big_int * mask + + val sqrtrem : Farith_Big.big_int -> Farith_Big.big_int * mask + + val iter_op : ('a1 -> 'a1 -> 'a1) -> Farith_Big.big_int -> 'a1 -> 'a1 + end diff --git a/farith2/BinPosDef.ml b/farith2/BinPosDef.ml new file mode 100644 index 0000000000000000000000000000000000000000..e1f8f253c83dbb38118366a179331bdd84bcee5e --- /dev/null +++ b/farith2/BinPosDef.ml @@ -0,0 +1,8 @@ + +module Pos = + struct + type mask = + | IsNul + | IsPos of Farith_Big.big_int + | IsNeg + end diff --git a/farith2/BinPosDef.mli b/farith2/BinPosDef.mli new file mode 100644 index 0000000000000000000000000000000000000000..ae03b859d41d6c6d966489dbfd57a4e72fc34104 --- /dev/null +++ b/farith2/BinPosDef.mli @@ -0,0 +1,8 @@ + +module Pos : + sig + type mask = + | IsNul + | IsPos of Farith_Big.big_int + | IsNeg + end diff --git a/farith2/Binary.ml b/farith2/Binary.ml new file mode 100644 index 0000000000000000000000000000000000000000..1fc1c209b69892ff1cd4f018bdba4e92e64982fd --- /dev/null +++ b/farith2/Binary.ml @@ -0,0 +1,21 @@ + +type full_float = +| F754_zero of bool +| F754_infinity of bool +| F754_nan of bool * Farith_Big.big_int +| F754_finite of bool * Farith_Big.big_int * Farith_Big.big_int + +type binary_float = +| B754_zero of bool +| B754_infinity of bool +| B754_nan of bool * Farith_Big.big_int +| B754_finite of bool * Farith_Big.big_int * Farith_Big.big_int + +(** val coq_FF2B : + Farith_Big.big_int -> Farith_Big.big_int -> full_float -> binary_float **) + +let coq_FF2B _ _ = function +| F754_zero s -> B754_zero s +| F754_infinity s -> B754_infinity s +| F754_nan (b, pl) -> B754_nan (b, pl) +| F754_finite (s, m, e) -> B754_finite (s, m, e) diff --git a/farith2/Binary.mli b/farith2/Binary.mli new file mode 100644 index 0000000000000000000000000000000000000000..a9eb82be8428482583b233c3cf204d316fd68cae --- /dev/null +++ b/farith2/Binary.mli @@ -0,0 +1,15 @@ + +type full_float = +| F754_zero of bool +| F754_infinity of bool +| F754_nan of bool * Farith_Big.big_int +| F754_finite of bool * Farith_Big.big_int * Farith_Big.big_int + +type binary_float = +| B754_zero of bool +| B754_infinity of bool +| B754_nan of bool * Farith_Big.big_int +| B754_finite of bool * Farith_Big.big_int * Farith_Big.big_int + +val coq_FF2B : + Farith_Big.big_int -> Farith_Big.big_int -> full_float -> binary_float diff --git a/farith2/BinarySingleNaN.ml b/farith2/BinarySingleNaN.ml new file mode 100644 index 0000000000000000000000000000000000000000..f3f6d10d7cf7e39663c172a24cfa549d08de13bf --- /dev/null +++ b/farith2/BinarySingleNaN.ml @@ -0,0 +1,295 @@ +open BinInt +open Bool +open Datatypes +open Round +open SpecFloat + +type binary_float = +| B754_zero of bool +| B754_infinity of bool +| B754_nan +| B754_finite of bool * Farith_Big.big_int * Farith_Big.big_int + +(** val coq_SF2B : + Farith_Big.big_int -> Farith_Big.big_int -> spec_float -> binary_float **) + +let coq_SF2B _ _ = function +| S754_zero s -> B754_zero s +| S754_infinity s -> B754_infinity s +| S754_nan -> B754_nan +| S754_finite (s, m, e) -> B754_finite (s, m, e) + +(** val coq_B2SF : + Farith_Big.big_int -> Farith_Big.big_int -> binary_float -> spec_float **) + +let coq_B2SF _ _ = function +| B754_zero s -> S754_zero s +| B754_infinity s -> S754_infinity s +| B754_nan -> S754_nan +| B754_finite (s, m, e) -> S754_finite (s, m, e) + +(** val is_nan : + Farith_Big.big_int -> Farith_Big.big_int -> binary_float -> bool **) + +let is_nan _ _ = function +| B754_nan -> true +| _ -> false + +(** val coq_Babs : + Farith_Big.big_int -> Farith_Big.big_int -> binary_float -> binary_float **) + +let coq_Babs _ _ x = match x with +| B754_zero _ -> B754_zero false +| B754_infinity _ -> B754_infinity false +| B754_nan -> x +| B754_finite (_, mx, ex) -> B754_finite (false, mx, ex) + +(** val coq_Beqb : + Farith_Big.big_int -> Farith_Big.big_int -> binary_float -> binary_float + -> bool **) + +let coq_Beqb prec emax f1 f2 = + coq_SFeqb (coq_B2SF prec emax f1) (coq_B2SF prec emax f2) + +(** val coq_Bltb : + Farith_Big.big_int -> Farith_Big.big_int -> binary_float -> binary_float + -> bool **) + +let coq_Bltb prec emax f1 f2 = + coq_SFltb (coq_B2SF prec emax f1) (coq_B2SF prec emax f2) + +(** val coq_Bleb : + Farith_Big.big_int -> Farith_Big.big_int -> binary_float -> binary_float + -> bool **) + +let coq_Bleb prec emax f1 f2 = + coq_SFleb (coq_B2SF prec emax f1) (coq_B2SF prec emax f2) + +(** val choice_mode : + Farith_Big.mode -> bool -> Farith_Big.big_int -> location -> + Farith_Big.big_int **) + +let choice_mode m sx mx lx = + match m with + | Farith_Big.NE -> cond_incr (round_N (Pervasives.not (Z.even mx)) lx) mx + | Farith_Big.ZR -> mx + | Farith_Big.DN -> cond_incr (round_sign_DN sx lx) mx + | Farith_Big.UP -> cond_incr (round_sign_UP sx lx) mx + | Farith_Big.NA -> cond_incr (round_N true lx) mx + +(** val overflow_to_inf : Farith_Big.mode -> bool -> bool **) + +let overflow_to_inf m s = + match m with + | Farith_Big.ZR -> false + | Farith_Big.DN -> s + | Farith_Big.UP -> Pervasives.not s + | _ -> true + +(** val binary_overflow : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> bool -> + spec_float **) + +let binary_overflow prec emax m s = + if overflow_to_inf m s + then S754_infinity s + else S754_finite (s, + (Z.to_pos + (Farith_Big.sub (Z.pow (Farith_Big.double Farith_Big.one) prec) + Farith_Big.one)), (Farith_Big.sub emax prec)) + +(** val binary_fit_aux : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> bool -> + Farith_Big.big_int -> Farith_Big.big_int -> spec_float **) + +let binary_fit_aux prec emax mode0 sx mx ex = + if Farith_Big.le ex (Farith_Big.sub emax prec) + then S754_finite (sx, mx, ex) + else binary_overflow prec emax mode0 sx + +(** val binary_round_aux : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> bool -> + Farith_Big.big_int -> Farith_Big.big_int -> location -> spec_float **) + +let binary_round_aux prec emax mode0 sx mx ex lx = + let (mrs', e') = shr_fexp prec emax mx ex lx in + let (mrs'', e'') = + shr_fexp prec emax + (choice_mode mode0 sx mrs'.shr_m (loc_of_shr_record mrs')) e' + Coq_loc_Exact + in + (Farith_Big.z_case + (fun _ -> S754_zero sx) + (fun m -> binary_fit_aux prec emax mode0 sx m e'') + (fun _ -> S754_nan) + mrs''.shr_m) + +(** val coq_Bmult : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> + binary_float -> binary_float -> binary_float **) + +let coq_Bmult prec emax m x y = + match x with + | B754_zero sx -> + (match y with + | B754_zero sy -> B754_zero (xorb sx sy) + | B754_finite (sy, _, _) -> B754_zero (xorb sx sy) + | _ -> B754_nan) + | B754_infinity sx -> + (match y with + | B754_infinity sy -> B754_infinity (xorb sx sy) + | B754_finite (sy, _, _) -> B754_infinity (xorb sx sy) + | _ -> B754_nan) + | B754_nan -> B754_nan + | B754_finite (sx, mx, ex) -> + (match y with + | B754_zero sy -> B754_zero (xorb sx sy) + | B754_infinity sy -> B754_infinity (xorb sx sy) + | B754_nan -> B754_nan + | B754_finite (sy, my, ey) -> + coq_SF2B prec emax + (binary_round_aux prec emax m (xorb sx sy) (Farith_Big.mult mx my) + (Farith_Big.add ex ey) Coq_loc_Exact)) + +(** val shl_align_fexp : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int -> + Farith_Big.big_int -> Farith_Big.big_int * Farith_Big.big_int **) + +let shl_align_fexp prec emax mx ex = + shl_align mx ex (fexp prec emax (Farith_Big.add (digits2_pos mx) ex)) + +(** val binary_round : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> bool -> + Farith_Big.big_int -> Farith_Big.big_int -> spec_float **) + +let binary_round prec emax m sx mx ex = + let (mz, ez) = shl_align_fexp prec emax mx ex in + binary_round_aux prec emax m sx mz ez Coq_loc_Exact + +(** val binary_normalize : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> + Farith_Big.big_int -> Farith_Big.big_int -> bool -> binary_float **) + +let binary_normalize prec emax mode0 m e szero = + Farith_Big.z_case + (fun _ -> B754_zero szero) + (fun m0 -> + coq_SF2B prec emax (binary_round prec emax mode0 false m0 e)) + (fun m0 -> coq_SF2B prec emax (binary_round prec emax mode0 true m0 e)) + m + +(** val coq_Bplus : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> + binary_float -> binary_float -> binary_float **) + +let coq_Bplus prec emax m x y = + match x with + | B754_zero sx -> + (match y with + | B754_zero sy -> + if eqb sx sy + then x + else (match m with + | Farith_Big.DN -> B754_zero true + | _ -> B754_zero false) + | B754_nan -> B754_nan + | _ -> y) + | B754_infinity sx -> + (match y with + | B754_infinity sy -> if eqb sx sy then x else B754_nan + | B754_nan -> B754_nan + | _ -> x) + | B754_nan -> B754_nan + | B754_finite (sx, mx, ex) -> + (match y with + | B754_zero _ -> x + | B754_infinity _ -> y + | B754_nan -> B754_nan + | B754_finite (sy, my, ey) -> + let ez = Farith_Big.min ex ey in + binary_normalize prec emax m + (Farith_Big.add (cond_Zopp sx (Pervasives.fst (shl_align mx ex ez))) + (cond_Zopp sy (Pervasives.fst (shl_align my ey ez)))) ez + (match m with + | Farith_Big.DN -> true + | _ -> false)) + +(** val coq_Bminus : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> + binary_float -> binary_float -> binary_float **) + +let coq_Bminus prec emax m x y = + match x with + | B754_zero sx -> + (match y with + | B754_zero sy -> + if eqb sx (Pervasives.not sy) + then x + else (match m with + | Farith_Big.DN -> B754_zero true + | _ -> B754_zero false) + | B754_infinity sy -> B754_infinity (Pervasives.not sy) + | B754_nan -> B754_nan + | B754_finite (sy, my, ey) -> B754_finite ((Pervasives.not sy), my, ey)) + | B754_infinity sx -> + (match y with + | B754_infinity sy -> if eqb sx (Pervasives.not sy) then x else B754_nan + | B754_nan -> B754_nan + | _ -> x) + | B754_nan -> B754_nan + | B754_finite (sx, mx, ex) -> + (match y with + | B754_zero _ -> x + | B754_infinity sy -> B754_infinity (Pervasives.not sy) + | B754_nan -> B754_nan + | B754_finite (sy, my, ey) -> + let ez = Farith_Big.min ex ey in + binary_normalize prec emax m + (Farith_Big.sub (cond_Zopp sx (Pervasives.fst (shl_align mx ex ez))) + (cond_Zopp sy (Pervasives.fst (shl_align my ey ez)))) ez + (match m with + | Farith_Big.DN -> true + | _ -> false)) + +(** val coq_Bdiv : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> + binary_float -> binary_float -> binary_float **) + +let coq_Bdiv prec emax m x y = + match x with + | B754_zero sx -> + (match y with + | B754_infinity sy -> B754_zero (xorb sx sy) + | B754_finite (sy, _, _) -> B754_zero (xorb sx sy) + | _ -> B754_nan) + | B754_infinity sx -> + (match y with + | B754_zero sy -> B754_infinity (xorb sx sy) + | B754_finite (sy, _, _) -> B754_infinity (xorb sx sy) + | _ -> B754_nan) + | B754_nan -> B754_nan + | B754_finite (sx, mx, ex) -> + (match y with + | B754_zero sy -> B754_infinity (xorb sx sy) + | B754_infinity sy -> B754_zero (xorb sx sy) + | B754_nan -> B754_nan + | B754_finite (sy, my, ey) -> + coq_SF2B prec emax + (let (p, lz) = coq_SFdiv_core_binary prec emax mx ex my ey in + let (mz, ez) = p in + binary_round_aux prec emax m (xorb sx sy) mz ez lz)) + +(** val coq_Bsqrt : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> + binary_float -> binary_float **) + +let coq_Bsqrt prec emax m x = match x with +| B754_zero _ -> x +| B754_infinity s -> if s then B754_nan else x +| B754_nan -> B754_nan +| B754_finite (sx, mx, ex) -> + if sx + then B754_nan + else coq_SF2B prec emax + (let (p, lz) = coq_SFsqrt_core_binary prec emax mx ex in + let (mz, ez) = p in binary_round_aux prec emax m false mz ez lz) diff --git a/farith2/BinarySingleNaN.mli b/farith2/BinarySingleNaN.mli new file mode 100644 index 0000000000000000000000000000000000000000..5a6d651e302909b2e7c9f2c191b1dd378ed9c7e8 --- /dev/null +++ b/farith2/BinarySingleNaN.mli @@ -0,0 +1,84 @@ +open BinInt +open Bool +open Datatypes +open Round +open SpecFloat + +type binary_float = +| B754_zero of bool +| B754_infinity of bool +| B754_nan +| B754_finite of bool * Farith_Big.big_int * Farith_Big.big_int + +val coq_SF2B : + Farith_Big.big_int -> Farith_Big.big_int -> spec_float -> binary_float + +val coq_B2SF : + Farith_Big.big_int -> Farith_Big.big_int -> binary_float -> spec_float + +val is_nan : Farith_Big.big_int -> Farith_Big.big_int -> binary_float -> bool + +val coq_Babs : + Farith_Big.big_int -> Farith_Big.big_int -> binary_float -> binary_float + +val coq_Beqb : + Farith_Big.big_int -> Farith_Big.big_int -> binary_float -> binary_float -> + bool + +val coq_Bltb : + Farith_Big.big_int -> Farith_Big.big_int -> binary_float -> binary_float -> + bool + +val coq_Bleb : + Farith_Big.big_int -> Farith_Big.big_int -> binary_float -> binary_float -> + bool + +val choice_mode : + Farith_Big.mode -> bool -> Farith_Big.big_int -> location -> + Farith_Big.big_int + +val overflow_to_inf : Farith_Big.mode -> bool -> bool + +val binary_overflow : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> bool -> + spec_float + +val binary_fit_aux : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> bool -> + Farith_Big.big_int -> Farith_Big.big_int -> spec_float + +val binary_round_aux : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> bool -> + Farith_Big.big_int -> Farith_Big.big_int -> location -> spec_float + +val coq_Bmult : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> binary_float + -> binary_float -> binary_float + +val shl_align_fexp : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int -> + Farith_Big.big_int -> Farith_Big.big_int * Farith_Big.big_int + +val binary_round : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> bool -> + Farith_Big.big_int -> Farith_Big.big_int -> spec_float + +val binary_normalize : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> + Farith_Big.big_int -> Farith_Big.big_int -> bool -> binary_float + +val coq_Bplus : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> binary_float + -> binary_float -> binary_float + +val coq_Bminus : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> binary_float + -> binary_float -> binary_float + +val coq_Bdiv : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> binary_float + -> binary_float -> binary_float + +val coq_Bsqrt : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> binary_float + -> binary_float diff --git a/farith2/Bits.ml b/farith2/Bits.ml new file mode 100644 index 0000000000000000000000000000000000000000..a842d4305f0164bb7ae55b4404c840d7d5d821b1 --- /dev/null +++ b/farith2/Bits.ml @@ -0,0 +1,108 @@ +open BinInt +open Binary + +(** val join_bits : + Farith_Big.big_int -> Farith_Big.big_int -> bool -> Farith_Big.big_int -> + Farith_Big.big_int -> Farith_Big.big_int **) + +let join_bits mw ew s m e = + Farith_Big.add + (Farith_Big.shiftl + (Farith_Big.add + (if s + then Z.pow (Farith_Big.double Farith_Big.one) ew + else Farith_Big.zero) e) mw) m + +(** val split_bits : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int -> + (bool * Farith_Big.big_int) * Farith_Big.big_int **) + +let split_bits mw ew x = + let mm = Z.pow (Farith_Big.double Farith_Big.one) mw in + let em = Z.pow (Farith_Big.double Farith_Big.one) ew in + (((Farith_Big.le (Farith_Big.mult mm em) x), (Farith_Big.mod_floor x mm)), + (Farith_Big.mod_floor (Farith_Big.div_floor x mm) em)) + +(** val bits_of_binary_float : + Farith_Big.big_int -> Farith_Big.big_int -> binary_float -> + Farith_Big.big_int **) + +let bits_of_binary_float mw ew = + let emax = + Z.pow (Farith_Big.double Farith_Big.one) + (Farith_Big.sub ew Farith_Big.one) + in + let prec = Farith_Big.add mw Farith_Big.one in + let emin = + Farith_Big.sub + (Farith_Big.sub (Farith_Big.succ_double Farith_Big.one) emax) prec + in + (fun x -> + match x with + | B754_zero sx -> join_bits mw ew sx Farith_Big.zero Farith_Big.zero + | B754_infinity sx -> + join_bits mw ew sx Farith_Big.zero + (Farith_Big.sub (Z.pow (Farith_Big.double Farith_Big.one) ew) + Farith_Big.one) + | B754_nan (sx, plx) -> + join_bits mw ew sx plx + (Farith_Big.sub (Z.pow (Farith_Big.double Farith_Big.one) ew) + Farith_Big.one) + | B754_finite (sx, mx, ex) -> + let m = Farith_Big.sub mx (Z.pow (Farith_Big.double Farith_Big.one) mw) in + if Farith_Big.le Farith_Big.zero m + then join_bits mw ew sx m + (Farith_Big.add (Farith_Big.sub ex emin) Farith_Big.one) + else join_bits mw ew sx mx Farith_Big.zero) + +(** val binary_float_of_bits_aux : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int -> + full_float **) + +let binary_float_of_bits_aux mw ew = + let emax = + Z.pow (Farith_Big.double Farith_Big.one) + (Farith_Big.sub ew Farith_Big.one) + in + let prec = Farith_Big.add mw Farith_Big.one in + let emin = + Farith_Big.sub + (Farith_Big.sub (Farith_Big.succ_double Farith_Big.one) emax) prec + in + (fun x -> + let (p, ex) = split_bits mw ew x in + let (sx, mx) = p in + if Farith_Big.eq ex Farith_Big.zero + then (Farith_Big.z_case + (fun _ -> F754_zero sx) + (fun px -> F754_finite (sx, px, emin)) + (fun _ -> F754_nan (false, Farith_Big.one)) + mx) + else if Farith_Big.eq ex + (Farith_Big.sub (Z.pow (Farith_Big.double Farith_Big.one) ew) + Farith_Big.one) + then (Farith_Big.z_case + (fun _ -> F754_infinity sx) + (fun plx -> F754_nan (sx, plx)) + (fun _ -> F754_nan (false, Farith_Big.one)) + mx) + else (Farith_Big.z_case + (fun _ -> F754_nan (false, Farith_Big.one)) + (fun px -> F754_finite (sx, px, + (Farith_Big.sub (Farith_Big.add ex emin) Farith_Big.one))) + (fun _ -> F754_nan (false, + Farith_Big.one)) + (Farith_Big.add mx + (Z.pow (Farith_Big.double Farith_Big.one) mw)))) + +(** val binary_float_of_bits : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int -> + binary_float **) + +let binary_float_of_bits mw ew x = + let emax = + Z.pow (Farith_Big.double Farith_Big.one) + (Farith_Big.sub ew Farith_Big.one) + in + let prec = Farith_Big.add mw Farith_Big.one in + coq_FF2B prec emax (binary_float_of_bits_aux mw ew x) diff --git a/farith2/Bits.mli b/farith2/Bits.mli new file mode 100644 index 0000000000000000000000000000000000000000..7fa47fa2f41e77fc088b4109978c45e8552ab7b2 --- /dev/null +++ b/farith2/Bits.mli @@ -0,0 +1,21 @@ +open BinInt +open Binary + +val join_bits : + Farith_Big.big_int -> Farith_Big.big_int -> bool -> Farith_Big.big_int -> + Farith_Big.big_int -> Farith_Big.big_int + +val split_bits : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int -> + (bool * Farith_Big.big_int) * Farith_Big.big_int + +val bits_of_binary_float : + Farith_Big.big_int -> Farith_Big.big_int -> binary_float -> + Farith_Big.big_int + +val binary_float_of_bits_aux : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int -> full_float + +val binary_float_of_bits : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int -> + binary_float diff --git a/farith2/Bool.ml b/farith2/Bool.ml new file mode 100644 index 0000000000000000000000000000000000000000..15e4eb09a33e0029bd22c6d0a3306dde660ca896 --- /dev/null +++ b/farith2/Bool.ml @@ -0,0 +1,5 @@ + +(** val eqb : bool -> bool -> bool **) + +let eqb b1 b2 = + if b1 then b2 else if b2 then false else true diff --git a/farith2/Bool.mli b/farith2/Bool.mli new file mode 100644 index 0000000000000000000000000000000000000000..2af28bedbbb20beba8789d1d04cc40b9586bcc67 --- /dev/null +++ b/farith2/Bool.mli @@ -0,0 +1,2 @@ + +val eqb : bool -> bool -> bool diff --git a/farith2/Datatypes.ml b/farith2/Datatypes.ml new file mode 100644 index 0000000000000000000000000000000000000000..d5c929229ea2573390a9d676a61a8985e4d0d4a1 --- /dev/null +++ b/farith2/Datatypes.ml @@ -0,0 +1,17 @@ + +(** val xorb : bool -> bool -> bool **) + +let xorb b1 b2 = + if b1 then if b2 then false else true else b2 + +type comparison = +| Eq +| Lt +| Gt + +(** val coq_CompOpp : comparison -> comparison **) + +let coq_CompOpp = function +| Eq -> Eq +| Lt -> Gt +| Gt -> Lt diff --git a/farith2/Datatypes.mli b/farith2/Datatypes.mli new file mode 100644 index 0000000000000000000000000000000000000000..32ae552786ef1a1097214521ec43849167e8491c --- /dev/null +++ b/farith2/Datatypes.mli @@ -0,0 +1,9 @@ + +val xorb : bool -> bool -> bool + +type comparison = +| Eq +| Lt +| Gt + +val coq_CompOpp : comparison -> comparison diff --git a/farith2/Interval.ml b/farith2/Interval.ml new file mode 100644 index 0000000000000000000000000000000000000000..f02e05cb3652f931bfb23055c7270e85ec0ca167 --- /dev/null +++ b/farith2/Interval.ml @@ -0,0 +1,162 @@ +open BinarySingleNaN +open Utils + +type float = binary_float + +type coq_Interval' = +| Inan +| Intv of float * float * bool + +type coq_Interval = coq_Interval' + +type coq_Interval_opt = coq_Interval' option + +(** val inter' : + Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval' -> + coq_Interval' -> coq_Interval' option **) + +let inter' prec emax i1 i2 = + match i1 with + | Inan -> + (match i2 with + | Inan -> Some Inan + | Intv (_, _, nan) -> if nan then Some Inan else None) + | Intv (lo1, hi1, nan1) -> + (match i2 with + | Inan -> if nan1 then Some Inan else None + | Intv (lo2, hi2, nan2) -> + if (||) (coq_Bltb prec emax hi1 lo2) (coq_Bltb prec emax hi2 lo1) + then if (&&) nan1 nan2 then Some Inan else None + else Some (Intv ((coq_Bmax prec emax lo1 lo2), + (coq_Bmin prec emax hi1 hi2), ((&&) nan1 nan2)))) + +(** val inter : + Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> coq_Interval + -> coq_Interval_opt **) + +let inter = + inter' + +(** val coq_Iadd' : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> + coq_Interval' -> coq_Interval' -> coq_Interval' **) + +let coq_Iadd' prec emax m i1 i2 = + match i1 with + | Inan -> Inan + | Intv (l, h, n) -> + (match i2 with + | Inan -> Inan + | Intv (l', h', n') -> + let sum1 = coq_Bplus prec emax m l l' in + let sum2 = coq_Bplus prec emax m h h' in + if is_nan prec emax sum1 + then if is_nan prec emax sum2 + then Inan + else Intv ((B754_infinity false), (B754_infinity false), true) + else if is_nan prec emax sum2 + then Intv ((B754_infinity true), (B754_infinity true), true) + else Intv (sum1, sum2, + ((||) + ((||) ((||) n n') + ((&&) (coq_Beqb prec emax h (B754_infinity false)) + (coq_Beqb prec emax l' (B754_infinity true)))) + ((&&) (coq_Beqb prec emax h' (B754_infinity false)) + (coq_Beqb prec emax l (B754_infinity true)))))) + +(** val coq_Iadd : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> + coq_Interval -> coq_Interval -> coq_Interval **) + +let coq_Iadd = + coq_Iadd' + +(** val coq_Ile : + Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> + coq_Interval_opt **) + +let coq_Ile _ _ = function +| Inan -> None +| Intv (_, b, n) -> Some (Intv ((B754_infinity true), b, n)) + +(** val coq_Ilt : + Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> + coq_Interval_opt **) + +let coq_Ilt _ _ = function +| Inan -> None +| Intv (_, b, n) -> Some (Intv ((B754_infinity true), b, n)) + +(** val coq_Ige : + Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> + coq_Interval_opt **) + +let coq_Ige _ _ = function +| Inan -> None +| Intv (a, _, n) -> Some (Intv (a, (B754_infinity false), n)) + +(** val coq_Igt : + Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> + coq_Interval_opt **) + +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/Interval.mli b/farith2/Interval.mli new file mode 100644 index 0000000000000000000000000000000000000000..19d9d78dcd85b7d1721b25081fe53bcd735900de --- /dev/null +++ b/farith2/Interval.mli @@ -0,0 +1,67 @@ +open BinarySingleNaN +open Utils + +type float = binary_float + +type coq_Interval' = +| Inan +| Intv of float * float * bool + +type coq_Interval = coq_Interval' + +type coq_Interval_opt = coq_Interval' option + +val inter' : + Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval' -> coq_Interval' + -> coq_Interval' option + +val inter : + Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> coq_Interval -> + coq_Interval_opt + +val coq_Iadd' : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> + coq_Interval' -> coq_Interval' -> coq_Interval' + +val coq_Iadd : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.mode -> coq_Interval + -> coq_Interval -> coq_Interval + +val coq_Ile : + Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> coq_Interval_opt + +val coq_Ilt : + Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> coq_Interval_opt + +val coq_Ige : + Farith_Big.big_int -> Farith_Big.big_int -> coq_Interval -> coq_Interval_opt + +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/Intv32.ml b/farith2/Intv32.ml new file mode 100644 index 0000000000000000000000000000000000000000..26467f98fcc8c8dfca5a11c7db1d70d075906abe --- /dev/null +++ b/farith2/Intv32.ml @@ -0,0 +1,112 @@ +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 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/Intv32.mli b/farith2/Intv32.mli new file mode 100644 index 0000000000000000000000000000000000000000..21914091a50561ac6f9139d062d6fe1a868f46d1 --- /dev/null +++ b/farith2/Intv32.mli @@ -0,0 +1,47 @@ +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 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/Makefile b/farith2/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a0ebd3b0eaa0108839a40817e86c469ef534f436 --- /dev/null +++ b/farith2/Makefile @@ -0,0 +1,13 @@ +include CoqMakefile + +CoqMakefile: + @ coq_makefile -f _CoqProject -o CoqMakefile + +.PHONY: cleandoc doc + +cleandoc: + @ rm -rf doc/ + +doc: + @ mkdir -p doc + @ cd thry && coq2html -base F -d ../doc *.v *.glob \ No newline at end of file diff --git a/farith2/Qextended.ml b/farith2/Qextended.ml new file mode 100644 index 0000000000000000000000000000000000000000..139597f9cb07c5d48bed18984ec4747f4b4f3438 --- /dev/null +++ b/farith2/Qextended.ml @@ -0,0 +1,2 @@ + + diff --git a/farith2/Qextended.mli b/farith2/Qextended.mli new file mode 100644 index 0000000000000000000000000000000000000000..139597f9cb07c5d48bed18984ec4747f4b4f3438 --- /dev/null +++ b/farith2/Qextended.mli @@ -0,0 +1,2 @@ + + diff --git a/farith2/Readme.md b/farith2/Readme.md new file mode 100644 index 0000000000000000000000000000000000000000..602106b02f647cf8e9dbacfc7cca80456b99c8eb --- /dev/null +++ b/farith2/Readme.md @@ -0,0 +1,18 @@ +# Farith2 + +Farith2 is an *under construction* Coq module formalizing floating points abstract domains based on [Flocq](http://flocq.gforge.inria.fr/). + +## Structure + +The structure of the sources may vary a lot over time. For now the structure is as follows : + ++ the folder `thry` contains all Coq modules ++ the folder `farith_big` contains OCaml modules used to provide a compatibility layer with Zarith for efficient extraction ++ the `extract.v` file drives the extraction to OCaml ++ the root contains `.ml(i)` files generated by extraction + +## Compilation + +The compilation of the Coq sources is handled with CoqMakefile. To compile everything, simply type `make` at Farith2's root. + +To generate the documentation, it is first required to build the sources using `make` and then `make doc` should fill the `doc` folder with the html documentation formatted using [coq2html](https://github.com/xavierleroy/coq2html). \ No newline at end of file diff --git a/farith2/Round.ml b/farith2/Round.ml new file mode 100644 index 0000000000000000000000000000000000000000..f6c4da1bd14072a85f5b3ef326d99257f841c0cf --- /dev/null +++ b/farith2/Round.ml @@ -0,0 +1,28 @@ +open Datatypes +open SpecFloat + +(** val cond_incr : bool -> Farith_Big.big_int -> Farith_Big.big_int **) + +let cond_incr b m = + if b then Farith_Big.add m Farith_Big.one else m + +(** val round_sign_DN : bool -> location -> bool **) + +let round_sign_DN s = function +| Coq_loc_Exact -> false +| Coq_loc_Inexact _ -> s + +(** val round_sign_UP : bool -> location -> bool **) + +let round_sign_UP s = function +| Coq_loc_Exact -> false +| Coq_loc_Inexact _ -> Pervasives.not s + +(** val round_N : bool -> location -> bool **) + +let round_N p = function +| Coq_loc_Exact -> false +| Coq_loc_Inexact c -> (match c with + | Eq -> p + | Lt -> false + | Gt -> true) diff --git a/farith2/Round.mli b/farith2/Round.mli new file mode 100644 index 0000000000000000000000000000000000000000..db97e992a08fb191f1a5a8117f0eec6d956df8ae --- /dev/null +++ b/farith2/Round.mli @@ -0,0 +1,10 @@ +open Datatypes +open SpecFloat + +val cond_incr : bool -> Farith_Big.big_int -> Farith_Big.big_int + +val round_sign_DN : bool -> location -> bool + +val round_sign_UP : bool -> location -> bool + +val round_N : bool -> location -> bool diff --git a/farith2/SpecFloat.ml b/farith2/SpecFloat.ml new file mode 100644 index 0000000000000000000000000000000000000000..7c315960cd7f3b2d8a1633fd4e90622501fa08fa --- /dev/null +++ b/farith2/SpecFloat.ml @@ -0,0 +1,290 @@ +open BinInt +open Datatypes +open Zpower + +type spec_float = +| S754_zero of bool +| S754_infinity of bool +| S754_nan +| S754_finite of bool * Farith_Big.big_int * Farith_Big.big_int + +(** val emin : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int **) + +let emin prec emax = + Farith_Big.sub + (Farith_Big.sub (Farith_Big.succ_double Farith_Big.one) emax) prec + +(** val fexp : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int -> + Farith_Big.big_int **) + +let fexp prec emax e = + Farith_Big.max (Farith_Big.sub e prec) (emin prec emax) + +(** val digits2_pos : Farith_Big.big_int -> Farith_Big.big_int **) + +let rec digits2_pos n = + Farith_Big.positive_case + (fun p -> Farith_Big.succ (digits2_pos p)) + (fun p -> Farith_Big.succ (digits2_pos p)) + (fun _ -> Farith_Big.one) + n + +(** val coq_Zdigits2 : Farith_Big.big_int -> Farith_Big.big_int **) + +let coq_Zdigits2 n = + Farith_Big.z_case + (fun _ -> n) + (fun p -> (digits2_pos p)) + (fun p -> (digits2_pos p)) + n + +(** val iter_pos : ('a1 -> 'a1) -> Farith_Big.big_int -> 'a1 -> 'a1 **) + +let rec iter_pos f n x = + Farith_Big.positive_case + (fun n' -> iter_pos f n' (iter_pos f n' (f x))) + (fun n' -> iter_pos f n' (iter_pos f n' x)) + (fun _ -> f x) + n + +type location = +| Coq_loc_Exact +| Coq_loc_Inexact of comparison + +type shr_record = { shr_m : Farith_Big.big_int; shr_r : bool; shr_s : bool } + +(** val shr_1 : shr_record -> shr_record **) + +let shr_1 mrs = + let { shr_m = m; shr_r = r; shr_s = s } = mrs in + let s0 = (||) r s in + (Farith_Big.z_case + (fun _ -> { shr_m = Farith_Big.zero; shr_r = false; shr_s = + s0 }) + (fun p0 -> + Farith_Big.positive_case + (fun p -> { shr_m = p; shr_r = true; shr_s = s0 }) + (fun p -> { shr_m = p; shr_r = false; shr_s = s0 }) + (fun _ -> { shr_m = Farith_Big.zero; shr_r = true; shr_s = s0 }) + p0) + (fun p0 -> + Farith_Big.positive_case + (fun p -> { shr_m = (Farith_Big.opp p); shr_r = true; shr_s = + s0 }) + (fun p -> { shr_m = (Farith_Big.opp p); shr_r = false; shr_s = + s0 }) + (fun _ -> { shr_m = Farith_Big.zero; shr_r = true; shr_s = s0 }) + p0) + m) + +(** val loc_of_shr_record : shr_record -> location **) + +let loc_of_shr_record mrs = + let { shr_m = _; shr_r = shr_r0; shr_s = shr_s0 } = mrs in + if shr_r0 + then if shr_s0 then Coq_loc_Inexact Gt else Coq_loc_Inexact Eq + else if shr_s0 then Coq_loc_Inexact Lt else Coq_loc_Exact + +(** val shr_record_of_loc : Farith_Big.big_int -> location -> shr_record **) + +let shr_record_of_loc m = function +| Coq_loc_Exact -> { shr_m = m; shr_r = false; shr_s = false } +| Coq_loc_Inexact c -> + (match c with + | Eq -> { shr_m = m; shr_r = true; shr_s = false } + | Lt -> { shr_m = m; shr_r = false; shr_s = true } + | Gt -> { shr_m = m; shr_r = true; shr_s = true }) + +(** val shr : + shr_record -> Farith_Big.big_int -> Farith_Big.big_int -> + shr_record * Farith_Big.big_int **) + +let shr mrs e n = + Farith_Big.z_case + (fun _ -> (mrs, e)) + (fun p -> ((iter_pos shr_1 p mrs), (Farith_Big.add e n))) + (fun _ -> (mrs, e)) + n + +(** val shr_fexp : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int -> + Farith_Big.big_int -> location -> shr_record * Farith_Big.big_int **) + +let shr_fexp prec emax m e l = + shr (shr_record_of_loc m l) e + (Farith_Big.sub (fexp prec emax (Farith_Big.add (coq_Zdigits2 m) e)) e) + +(** val shl_align : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int -> + Farith_Big.big_int * Farith_Big.big_int **) + +let shl_align mx ex ex' = + Farith_Big.z_case + (fun _ -> (mx, ex)) + (fun _ -> (mx, ex)) + (fun d -> ((shift_pos d mx), ex')) + (Farith_Big.sub ex' ex) + +(** val coq_SFcompare : spec_float -> spec_float -> comparison option **) + +let coq_SFcompare f1 f2 = + match f1 with + | S754_zero _ -> + (match f2 with + | S754_zero _ -> Some Eq + | S754_infinity s -> Some (if s then Gt else Lt) + | S754_nan -> None + | S754_finite (s, _, _) -> Some (if s then Gt else Lt)) + | S754_infinity s -> + (match f2 with + | S754_infinity s0 -> + Some (if s then if s0 then Eq else Lt else if s0 then Gt else Eq) + | S754_nan -> None + | _ -> Some (if s then Lt else Gt)) + | S754_nan -> None + | S754_finite (s1, m1, e1) -> + (match f2 with + | S754_zero _ -> Some (if s1 then Lt else Gt) + | S754_infinity s -> Some (if s then Gt else Lt) + | S754_nan -> None + | S754_finite (s2, m2, e2) -> + Some + (if s1 + then if s2 + then (match (Farith_Big.compare_case Eq Lt Gt) e1 e2 with + | Eq -> + coq_CompOpp + ((fun c x y -> Farith_Big.compare_case c Lt Gt x y) + Eq m1 m2) + | Lt -> Gt + | Gt -> Lt) + else Lt + else if s2 + then Gt + else (match (Farith_Big.compare_case Eq Lt Gt) e1 e2 with + | Eq -> + (fun c x y -> Farith_Big.compare_case c Lt Gt x y) Eq + m1 m2 + | x -> x))) + +(** val coq_SFeqb : spec_float -> spec_float -> bool **) + +let coq_SFeqb f1 f2 = + match coq_SFcompare f1 f2 with + | Some c -> (match c with + | Eq -> true + | _ -> false) + | None -> false + +(** val coq_SFltb : spec_float -> spec_float -> bool **) + +let coq_SFltb f1 f2 = + match coq_SFcompare f1 f2 with + | Some c -> (match c with + | Lt -> true + | _ -> false) + | None -> false + +(** val coq_SFleb : spec_float -> spec_float -> bool **) + +let coq_SFleb f1 f2 = + match coq_SFcompare f1 f2 with + | Some c -> (match c with + | Gt -> false + | _ -> true) + | None -> false + +(** val cond_Zopp : bool -> Farith_Big.big_int -> Farith_Big.big_int **) + +let cond_Zopp b m = + if b then Farith_Big.opp m else m + +(** val new_location_even : + Farith_Big.big_int -> Farith_Big.big_int -> location **) + +let new_location_even nb_steps k = + if Farith_Big.eq k Farith_Big.zero + then Coq_loc_Exact + else Coq_loc_Inexact + ((Farith_Big.compare_case Eq Lt Gt) + (Farith_Big.mult (Farith_Big.double Farith_Big.one) k) nb_steps) + +(** val new_location_odd : + Farith_Big.big_int -> Farith_Big.big_int -> location **) + +let new_location_odd nb_steps k = + if Farith_Big.eq k Farith_Big.zero + then Coq_loc_Exact + else Coq_loc_Inexact + (match (Farith_Big.compare_case Eq Lt Gt) + (Farith_Big.add + (Farith_Big.mult (Farith_Big.double Farith_Big.one) k) + Farith_Big.one) nb_steps with + | Eq -> Lt + | x -> x) + +(** val new_location : + Farith_Big.big_int -> Farith_Big.big_int -> location **) + +let new_location nb_steps = + if Z.even nb_steps + then new_location_even nb_steps + else new_location_odd nb_steps + +(** val coq_SFdiv_core_binary : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int -> + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int -> + (Farith_Big.big_int * Farith_Big.big_int) * location **) + +let coq_SFdiv_core_binary prec emax m1 e1 m2 e2 = + let d1 = coq_Zdigits2 m1 in + let d2 = coq_Zdigits2 m2 in + let e' = + Farith_Big.min + (fexp prec emax + (Farith_Big.sub (Farith_Big.add d1 e1) (Farith_Big.add d2 e2))) + (Farith_Big.sub e1 e2) + in + let s = Farith_Big.sub (Farith_Big.sub e1 e2) e' in + let m' = + Farith_Big.z_case + (fun _ -> m1) + (fun _ -> Farith_Big.shiftl m1 s) + (fun _ -> Farith_Big.zero) + s + in + let (q, r) = Farith_Big.div_mod_floor m' m2 in + ((q, e'), (new_location m2 r)) + +(** val coq_SFsqrt_core_binary : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int -> + Farith_Big.big_int -> (Farith_Big.big_int * Farith_Big.big_int) * location **) + +let coq_SFsqrt_core_binary prec emax m e = + let d = coq_Zdigits2 m in + let e' = + Farith_Big.min + (fexp prec emax + (Farith_Big.div2_floor + (Farith_Big.add (Farith_Big.add d e) Farith_Big.one))) + (Farith_Big.div2_floor e) + in + let s = + Farith_Big.sub e (Farith_Big.mult (Farith_Big.double Farith_Big.one) e') + in + let m' = + Farith_Big.z_case + (fun _ -> m) + (fun _ -> Farith_Big.shiftl m s) + (fun _ -> Farith_Big.zero) + s + in + let (q, r) = Farith_Big.Z.sqrt_rem m' in + let l = + if Farith_Big.eq r Farith_Big.zero + then Coq_loc_Exact + else Coq_loc_Inexact (if Farith_Big.le r q then Lt else Gt) + in + ((q, e'), l) diff --git a/farith2/SpecFloat.mli b/farith2/SpecFloat.mli new file mode 100644 index 0000000000000000000000000000000000000000..0523a53f16cbcff61a123e4627e21b58c9d3ef2c --- /dev/null +++ b/farith2/SpecFloat.mli @@ -0,0 +1,70 @@ +open BinInt +open Datatypes +open Zpower + +type spec_float = +| S754_zero of bool +| S754_infinity of bool +| S754_nan +| S754_finite of bool * Farith_Big.big_int * Farith_Big.big_int + +val emin : Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int + +val fexp : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int -> + Farith_Big.big_int + +val digits2_pos : Farith_Big.big_int -> Farith_Big.big_int + +val coq_Zdigits2 : Farith_Big.big_int -> Farith_Big.big_int + +val iter_pos : ('a1 -> 'a1) -> Farith_Big.big_int -> 'a1 -> 'a1 + +type location = +| Coq_loc_Exact +| Coq_loc_Inexact of comparison + +type shr_record = { shr_m : Farith_Big.big_int; shr_r : bool; shr_s : bool } + +val shr_1 : shr_record -> shr_record + +val loc_of_shr_record : shr_record -> location + +val shr_record_of_loc : Farith_Big.big_int -> location -> shr_record + +val shr : + shr_record -> Farith_Big.big_int -> Farith_Big.big_int -> + shr_record * Farith_Big.big_int + +val shr_fexp : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int -> + Farith_Big.big_int -> location -> shr_record * Farith_Big.big_int + +val shl_align : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int -> + Farith_Big.big_int * Farith_Big.big_int + +val coq_SFcompare : spec_float -> spec_float -> comparison option + +val coq_SFeqb : spec_float -> spec_float -> bool + +val coq_SFltb : spec_float -> spec_float -> bool + +val coq_SFleb : spec_float -> spec_float -> bool + +val cond_Zopp : bool -> Farith_Big.big_int -> Farith_Big.big_int + +val new_location_even : Farith_Big.big_int -> Farith_Big.big_int -> location + +val new_location_odd : Farith_Big.big_int -> Farith_Big.big_int -> location + +val new_location : Farith_Big.big_int -> Farith_Big.big_int -> location + +val coq_SFdiv_core_binary : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int -> + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int -> + (Farith_Big.big_int * Farith_Big.big_int) * location + +val coq_SFsqrt_core_binary : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int -> + Farith_Big.big_int -> (Farith_Big.big_int * Farith_Big.big_int) * location diff --git a/farith2/Specif.ml b/farith2/Specif.ml new file mode 100644 index 0000000000000000000000000000000000000000..c756f547f6bed7dabf5cd7d81e664b8d4dbe9e70 --- /dev/null +++ b/farith2/Specif.ml @@ -0,0 +1,3 @@ + +type 'a coq_sig = 'a + (* singleton inductive, whose constructor was exist *) diff --git a/farith2/Specif.mli b/farith2/Specif.mli new file mode 100644 index 0000000000000000000000000000000000000000..c756f547f6bed7dabf5cd7d81e664b8d4dbe9e70 --- /dev/null +++ b/farith2/Specif.mli @@ -0,0 +1,3 @@ + +type 'a coq_sig = 'a + (* singleton inductive, whose constructor was exist *) diff --git a/farith2/Utils.ml b/farith2/Utils.ml new file mode 100644 index 0000000000000000000000000000000000000000..ff1c2c78ec2d4d47eab07021d6b26b42d84198ec --- /dev/null +++ b/farith2/Utils.ml @@ -0,0 +1,19 @@ +open BinarySingleNaN + +type float = binary_float + +(** val coq_Bmax : + Farith_Big.big_int -> Farith_Big.big_int -> float -> float -> float **) + +let coq_Bmax prec emax f1 f2 = + if (||) (is_nan prec emax f1) (is_nan prec emax f2) + then B754_nan + else if coq_Bleb prec emax f1 f2 then f2 else f1 + +(** val coq_Bmin : + Farith_Big.big_int -> Farith_Big.big_int -> float -> float -> float **) + +let coq_Bmin prec emax f1 f2 = + if (||) (is_nan prec emax f1) (is_nan prec emax f2) + then B754_nan + else if coq_Bleb prec emax f1 f2 then f1 else f2 diff --git a/farith2/Utils.mli b/farith2/Utils.mli new file mode 100644 index 0000000000000000000000000000000000000000..5eb5b65c88744551c30b0850b19ea251cfc6cb2f --- /dev/null +++ b/farith2/Utils.mli @@ -0,0 +1,9 @@ +open BinarySingleNaN + +type float = binary_float + +val coq_Bmax : + Farith_Big.big_int -> Farith_Big.big_int -> float -> float -> float + +val coq_Bmin : + Farith_Big.big_int -> Farith_Big.big_int -> float -> float -> float diff --git a/farith2/Zaux.ml b/farith2/Zaux.ml new file mode 100644 index 0000000000000000000000000000000000000000..139597f9cb07c5d48bed18984ec4747f4b4f3438 --- /dev/null +++ b/farith2/Zaux.ml @@ -0,0 +1,2 @@ + + diff --git a/farith2/Zaux.mli b/farith2/Zaux.mli new file mode 100644 index 0000000000000000000000000000000000000000..139597f9cb07c5d48bed18984ec4747f4b4f3438 --- /dev/null +++ b/farith2/Zaux.mli @@ -0,0 +1,2 @@ + + diff --git a/farith2/Zbool.ml b/farith2/Zbool.ml new file mode 100644 index 0000000000000000000000000000000000000000..139597f9cb07c5d48bed18984ec4747f4b4f3438 --- /dev/null +++ b/farith2/Zbool.ml @@ -0,0 +1,2 @@ + + diff --git a/farith2/Zbool.mli b/farith2/Zbool.mli new file mode 100644 index 0000000000000000000000000000000000000000..139597f9cb07c5d48bed18984ec4747f4b4f3438 --- /dev/null +++ b/farith2/Zbool.mli @@ -0,0 +1,2 @@ + + diff --git a/farith2/Zpower.ml b/farith2/Zpower.ml new file mode 100644 index 0000000000000000000000000000000000000000..d7ddaef5cd096dac49935b076f994f6738fe1b08 --- /dev/null +++ b/farith2/Zpower.ml @@ -0,0 +1,7 @@ +open BinPos + +(** val shift_pos : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int **) + +let shift_pos n z = + Pos.iter (fun x -> Farith_Big.double x) z n diff --git a/farith2/Zpower.mli b/farith2/Zpower.mli new file mode 100644 index 0000000000000000000000000000000000000000..0887c39e52a58f7598409c912ba4f51569b0a7b2 --- /dev/null +++ b/farith2/Zpower.mli @@ -0,0 +1,4 @@ +open BinPos + +val shift_pos : + Farith_Big.big_int -> Farith_Big.big_int -> Farith_Big.big_int diff --git a/farith2/_CoqProject b/farith2/_CoqProject new file mode 100644 index 0000000000000000000000000000000000000000..e5fa34fb951bd2c04b133eb521811322d7941c65 --- /dev/null +++ b/farith2/_CoqProject @@ -0,0 +1,11 @@ +-R ./thry F +./thry/Interval.v +./thry/All.v +./thry/Intv32.v +./thry/Tactics.v +./thry/Rextended.v +./thry/Qextended.v +./thry/Utils.v +./thry/B32.v +./thry/Correction_thms.v +./extraction.v \ No newline at end of file diff --git a/farith2/doc/coq2html.js b/farith2/doc/coq2html.js new file mode 100644 index 0000000000000000000000000000000000000000..d869b602b1c5c440f89ef0198d6c1130eb2d9c88 --- /dev/null +++ b/farith2/doc/coq2html.js @@ -0,0 +1,25 @@ + +function toggleDisplay(id) +{ + var elt = document.getElementById(id); + if (elt.style.display == 'none') { + elt.style.display = 'block'; + } else { + elt.style.display = 'none'; + } +} + +function hideAll(cls) +{ + var testClass = new RegExp("(^|s)" + cls + "(s|$)"); + var tag = tag || "*"; + var elements = document.getElementsByTagName("div"); + var current; + var length = elements.length; + for(var i=0; i<length; i++){ + current = elements[i]; + if(testClass.test(current.className)) { + current.style.display = 'none'; + } + } +} diff --git a/farith2/dune b/farith2/dune new file mode 100644 index 0000000000000000000000000000000000000000..541a416dad12c7b413d290f5b2941b75dba419bc --- /dev/null +++ b/farith2/dune @@ -0,0 +1,7 @@ +(include_subdirs unqualified) + +(library + (name farith2) + (public_name farith2) + (libraries zarith) + (flags "-w" "-33")) diff --git a/farith2/dune-project b/farith2/dune-project new file mode 100644 index 0000000000000000000000000000000000000000..ab8113ad5e2aa636170feaa81ad55560556c0649 --- /dev/null +++ b/farith2/dune-project @@ -0,0 +1,7 @@ +(lang dune 2.8) + +(generate_opam_files true) + +(package + (name farith2) + (synopsis "formaly verified floating-points valuations based on Flocq")) diff --git a/farith2/extraction.v b/farith2/extraction.v new file mode 100644 index 0000000000000000000000000000000000000000..3ed0abac6151ba4395328d9857440096a1306336 --- /dev/null +++ b/farith2/extraction.v @@ -0,0 +1,273 @@ +From Flocq Require Import Core.Zaux IEEE754.BinarySingleNaN IEEE754.Bits. +From F Require Import Qextended B32 Intv32. +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.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. + +Extract Inlined Constant bool_of_sumbool => "Farith_Big.identity". +Extract Inlined Constant sumbool_of_bool => "Farith_Big.identity". + + +(** From ExtrOcamlNatBigInt of coq archive *) + +Require Import Arith Even Div2 EqNat Euclid. +Require Import ExtrOcamlBasic. + +Extract Inlined Constant Datatypes.negb => "Pervasives.not". +Extract Inlined Constant Datatypes.fst => "Pervasives.fst". +Extract Inlined Constant Datatypes.snd => "Pervasives.snd". + + +(** NB: The extracted code should be linked with [nums.cm(x)a] + from ocaml's stdlib and with the wrapper [big.ml] that + simplifies the use of [Big_int] (it can be found in the sources + of Coq). *) + +(** Disclaimer: trying to obtain efficient certified programs + by extracting [nat] into [big_int] isn't necessarily a good idea. + See comments in [ExtrOcamlNatInt.v]. +*) + + +(** Mapping of [nat] into [big_int]. The last string corresponds to + a [nat_case], see documentation of [Extract Inductive]. *) + +Extract Inductive nat => "Farith_Big.big_int" [ "Farith_Big.zero" "Farith_Big.succ" ] + "Farith_Big.nat_case". + +(** Efficient (but uncertified) versions for usual [nat] functions *) + +Extract Inlined Constant plus => "Farith_Big.add". +Extract Inlined Constant mult => "Farith_Big.mult". +Extract Constant pred => "fun n -> Farith_Big.max Farith_Big.zero (Farith_Big.pred n)". +Extract Constant minus => "fun n m -> Farith_Big.max Farith_Big.zero (Farith_Big.sub n m)". +Extract Inlined Constant max => "Farith_Big.max". +Extract Inlined Constant min => "Farith_Big.min". +(*Extract Constant nat_beq => "Farith_Big.eq".*) +Extract Constant EqNat.beq_nat => "Farith_Big.eq". +Extract Constant EqNat.eq_nat_decide => "Farith_Big.eq". + +Extract Constant Peano_dec.eq_nat_dec => "Farith_Big.eq". + +(* Extract Constant Compare_dec.nat_compare => + "Farith_Big.compare_case Eq Lt Gt". + +Extract Constant Compare_dec.leb => "Farith_Big.le". +Extract Constant Compare_dec.le_lt_dec => "Farith_Big.le". +Extract Constant Compare_dec.lt_eq_lt_dec => + "Farith_Big.compare_case (Some false) (Some true) None". *) + +Extract Constant Even.even_odd_dec => + "fun n -> Farith_Big.sign (Farith_Big.mod n Farith_Big.two) = 0". +Extract Constant Div2.div2 => "fun n -> Farith_Big.div n Farith_Big.two". + +Extract Inductive Euclid.diveucl => "(Farith_Big.big_int * Farith_Big.big_int)" [""]. +Extract Constant Euclid.eucl_dev => "fun n m -> Farith_Big.quomod m n". +Extract Constant Euclid.quotient => "fun n m -> Farith_Big.div m n". +Extract Constant Euclid.modulo => "fun n m -> Farith_Big.modulo m n". + + +(** From ExtrOcamlZBigInt of coq archive *) + +Require Import ZArith NArith. +Require Import ExtrOcamlBasic. + +(** NB: The extracted code should be linked with [nums.cm(x)a] + from ocaml's stdlib and with the wrapper [big.ml] that + simplifies the use of [Big_int] (it can be found in the sources + of Coq). *) + +(** Disclaimer: trying to obtain efficient certified programs + by extracting [Z] into [big_int] isn't necessarily a good idea. + See the Disclaimer in [ExtrOcamlNatInt]. *) + +(** Mapping of [positive], [Z], [N] into [big_int]. The last strings + emulate the matching, see documentation of [Extract Inductive]. *) + +Extract Inductive positive => "Farith_Big.big_int" + [ "Farith_Big.succ_double" "Farith_Big.double" "Farith_Big.one" ] "Farith_Big.positive_case". + +Extract Inductive Z => "Farith_Big.big_int" + [ "Farith_Big.zero" "" "Farith_Big.opp" ] "Farith_Big.z_case". + +Extract Inductive N => "Farith_Big.big_int" + [ "Farith_Big.zero" "" ] "Farith_Big.n_case". + +(** Nota: the "" above is used as an identity function "(fun p->p)" *) + +(** Efficient (but uncertified) versions for usual functions *) + +Extract Inlined Constant Pos.add => "Farith_Big.add". +Extract Inlined Constant Pos.succ => "Farith_Big.succ". +Extract Constant Pos.pred => "fun n -> Farith_Big.max Farith_Big.one (Farith_Big.pred n)". +Extract Constant Pos.sub => "fun n m -> Farith_Big.max Farith_Big.one (Farith_Big.sub n m)". +Extract Inlined Constant Pos.pred_double => "Farith_Big.pred_double". +Extract Inlined Constant Pos.mul => "Farith_Big.mult". +Extract Inlined Constant Pos.min => "Farith_Big.min". +Extract Inlined Constant Pos.max => "Farith_Big.max". +Extract Inlined Constant Pos.compare => "(Farith_Big.compare_case Eq Lt Gt)". +Extract Constant Pos.compare_cont => + "fun c x y -> Farith_Big.compare_case c Lt Gt x y". +Extract Inlined Constant Pos.eqb => "Farith_Big.eq". +Extract Inlined Constant Pos.leb => "Farith_Big.le". +Extract Inlined Constant Pos.ltb => "Farith_Big.lt". +Extract Inlined Constant Pos.to_nat => "Farith_Big.identity". +Extract Inlined Constant Pos.of_nat => "Farith_Big.identity". +Extract Inlined Constant Pos.of_succ_nat => "Farith_Big.succ". +Extract Constant Pos.add_carry => "fun p q -> Farith_Big.succ (Farith_Big.add p q)". +Extract Inlined Constant Pos.sqrt => "Farith_Big.Z.sqrt". +Extract Inlined Constant Pos.square => "Farith_Big.square". +Extract Inlined Constant Pos.eq_dec => "Farith_Big.Z.equal". +Extract Inlined Constant Pos.pow => "Farith_Big.pow_pos". +Extract Inlined Constant Pos.gcd => "Farith_Big.Z.gcd". +Extract Inlined Constant Pos.lor => "Farith_Big.Z.logor". +Extract Inlined Constant Pos.land => "Farith_Big.Z.logand". +Extract Inlined Constant Pos.lxor => "Farith_Big.Z.logxor". +Extract Inlined Constant Pos.ldiff => "Farith_Big.ldiff". +Extract Inlined Constant Pos.shiftl_nat => "Farith_Big.shiftl". +Extract Inlined Constant Pos.shiftr_nat => "Farith_Big.shiftr". +Extract Inlined Constant Pos.shiftl => "Farith_Big.shiftl". +Extract Inlined Constant Pos.shiftr => "Farith_Big.shiftr". + +Extract Inlined Constant BinPos.Pos.compare_cont => "(fun c x y -> Farith_Big.compare_case c Lt Gt x y)". + + +Extract Inlined Constant N.add => "Farith_Big.add". +Extract Inlined Constant N.succ => "Farith_Big.succ". +Extract Constant N.pred => "fun n -> Farith_Big.max Farith_Big.zero (Farith_Big.pred n)". +Extract Constant N.sub => "fun n m -> Farith_Big.max Farith_Big.zero (Farith_Big.sub n m)". +Extract Inlined Constant N.mul => "Farith_Big.mult". +Extract Inlined Constant N.min => "Farith_Big.min". +Extract Inlined Constant N.max => "Farith_Big.max". +Extract Constant N.div => + "fun a b -> if Farith_Big.eq b Farith_Big.zero then Farith_Big.zero else Farith_Big.div a b". +Extract Constant N.modulo => + "fun a b -> if Farith_Big.eq b Farith_Big.zero then Farith_Big.zero else Farith_Big.modulo a b". +Extract Constant N.compare => "Farith_Big.compare_case Eq Lt Gt". +Extract Inlined Constant N.succ_double => "Farith_Big.succ_double". +Extract Inlined Constant N.double => "Farith_Big.double". +Extract Inlined Constant Pos.Nsucc_double => "Farith_Big.succ_double". +Extract Inlined Constant Pos.Ndouble => "Farith_Big.double". + +Extract Inlined Constant Z.add => "Farith_Big.add". +Extract Inlined Constant Z.succ => "Farith_Big.succ". +Extract Inlined Constant Z.pred => "Farith_Big.pred". +Extract Inlined Constant Z.sub => "Farith_Big.sub". +Extract Inlined Constant Z.mul => "Farith_Big.mult". +Extract Inlined Constant Z.opp => "Farith_Big.opp". +Extract Inlined Constant Z.abs => "Farith_Big.abs". +Extract Inlined Constant Z.min => "Farith_Big.min". +Extract Inlined Constant Z.max => "Farith_Big.max". +Extract Inlined Constant Z.eqb => "Farith_Big.eq". +Extract Inlined Constant Z.leb => "Farith_Big.le". +Extract Inlined Constant Z.ltb => "Farith_Big.lt". +Extract Inlined Constant Z.geb => "Farith_Big.ge". +Extract Inlined Constant Z.gtb => "Farith_Big.gt". +Extract Inlined Constant Z.compare => "(Farith_Big.compare_case Eq Lt Gt)". +Extract Inlined Constant Z.double => "Farith_Big.double". +Extract Inlined Constant Z.succ_double => "Farith_Big.succ_double". +Extract Inlined Constant Z.pred_double => "Farith_Big.pred_double". +Extract Inlined Constant Z.pos_sub => "Farith_Big.sub". +Extract Inlined Constant Z.gcd => "Farith_Big.Z.gcd". +Extract Inlined Constant Z.sqrt => "Farith_Big.Z.sqrt". +Extract Inlined Constant Z.sqrtrem => "Farith_Big.Z.sqrt_rem". +Extract Inlined Constant Z.square => "Farith_Big.square". +Extract Inlined Constant Z.lnot => "Farith_Big.Z.lognot". +Extract Inlined Constant Z.lor => "Farith_Big.Z.logor". +Extract Inlined Constant Z.land => "Farith_Big.Z.logand". +Extract Inlined Constant Z.lxor => "Farith_Big.Z.logxor". +Extract Inlined Constant Z.ldiff => "Farith_Big.ldiff". +Extract Inlined Constant Z.eq_dec => "Farith_Big.Z.equal". +Extract Inlined Constant Z.shiftr => "Farith_Big.shiftr". +Extract Inlined Constant Z.shiftl => "Farith_Big.shiftl". +Extract Inlined Constant Z.sgn => "Farith_Big.sgn". + +Extract Inlined Constant Z.of_N => "Farith_Big.identity". +Extract Inlined Constant Z.of_nat => "Farith_Big.identity". + +Extract Inlined Constant Z.abs_N => "Farith_Big.abs". +Extract Inlined Constant Z.abs_nat => "Farith_Big.abs". + +Extract Inlined Constant Zeq_bool => "Farith_Big.eq". + +(** trunc convention *) +Extract Inlined Constant Z.rem => "Farith_Big.Z.rem". +Extract Inlined Constant Z.quot => "Farith_Big.Z.div". +Extract Inlined Constant Z.quot2 => "Farith_Big.div2_trunc". +Extract Inlined Constant Z.quotrem => "Farith_Big.Z.div_rem". + +(** floor convention *) +Extract Inlined Constant Z.modulo => "Farith_Big.mod_floor". +Extract Inlined Constant Z.div => "Farith_Big.div_floor". +Extract Inlined Constant Z.div_eucl => "Farith_Big.div_mod_floor". +Extract Inlined Constant Z.div2 => "Farith_Big.div2_floor". + +(** euclid convention *) +Require Import Zeuclid. +Extract Inlined Constant ZEuclid.modulo => "Farith_Big.Z.erem". +Extract Inlined Constant ZEuclid.div => "Farith_Big.Z.ediv". + +Extract Inlined Constant Z.pow_pos => "Farith_Big.pow_pos". + + + +Require Import Flocq.Core.Zaux. +Require Coq.Arith.Wf_nat. +(* Extract Inlined Constant shiftl_pos => "Farith_Big.shiftl_pos". *) +Extract Inlined Constant Core.Zaux.iter_nat => "Farith_Big.iter_nat". +Extract Inlined Constant nat_rect => "Farith_Big.nat_rect". + + +(** Some proofs used in function realization *) + +Definition div_mod_floor a b := + let (q,r) := Z.quotrem a b in + if orb (Z.lxor (Z.sgn a) (Z.sgn b) >=? 0)%Z (r =? 0)%Z + then (q,r) + else (Z.pred q,b+r)%Z. + +Lemma Floor_of_Trunc: + forall a b, (b <> 0)%Z -> Z.div_eucl a b = div_mod_floor a b. +Proof. + intros a' b' Hb. + unfold div_mod_floor. + assert (Lmod := Z.rem_mod a' b' Hb). + assert (Ldiv := Z.quot_div a' b' Hb). + replace (Z.quotrem a' b') with ((Z.quot a' b',Z.rem a' b')) by + (compute [Z.quot Z.rem]; destruct (Z.quotrem a' b'); trivial). + replace (Z.pred (Z.quot a' b'))%Z with (-(Z.opp (Z.quot a' b')+1))%Z by lia. + rewrite Lmod. rewrite Ldiv. + pose (a := a'). pose (b := b'). + destruct a'; destruct b'; unfold Z.modulo, Z.div; simpl; trivial; + destruct (Z.pos_div_eucl p (Z.pos p0)) as [[|pq|nq] [|pr|nr]]; trivial. +Qed. + +(* Avoid name clashes *) +Extraction Blacklist Big List String Int Z Q. + +Extract Inductive Qextended.Qx => "Q.t" [ "Farith_Big.q_mk" ] "Farith_Big.q_case". +Extract Inlined Constant Qextended.den => "Farith_Big.q_den". +Extract Inlined Constant Qextended.num => "Farith_Big.q_num". +Extract Inlined Constant Qextended.Qx_classify => "Q.classify". + +Extract Inductive Qx_kind => "Q.kind" [ "Q.INF" "Q.MINF" "Q.UNDEF" "Q.ZERO" "Q.NZERO" ]. +Extract Inlined Constant Qx_classify => "Q.classify". + +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. + diff --git a/farith2/farith_big/farith_Big.ml b/farith2/farith_big/farith_Big.ml new file mode 100644 index 0000000000000000000000000000000000000000..8ed2ad80c7f2fe17020e800bee1fabd883aae142 --- /dev/null +++ b/farith2/farith_big/farith_Big.ml @@ -0,0 +1,238 @@ +(************************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2015 *) +(* \VV/ **************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(************************************************************************) + +(** [Big] : a wrapper around ocaml [Big_int] with nicer names, + and a few extraction-specific constructions *) + +(** To be linked with [nums.(cma|cmxa)] *) + +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]. *) + +(* {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. + Writing [(q,r) = quomod_big_int a b], we have + [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 + representing the first argument [a] raised to the power [b] + (the second argument). Depending + on the function, [a] and [b] can be either small integers + or big integers. Raise [Invalid_argument] if [b] is negative. *) + +(* {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 +(* Convert a string to a big integer, in decimal. + The string consists of an optional [-] or [+] sign, + followed by one or several decimal digits. *) + +(* {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, + [is_int_big_int a] returns [true] if and only if + [a] is between 2{^30} and 2{^30}-1. On a 64-bit platform, + [is_int_big_int a] returns [true] if and only if + [a] is between -2{^62} and 2{^62}-1. *) +let to_int = int_of_big_int +(* Convert a big integer to a small integer (type [int]). + Raises [Failure "int_of_big_int"] if the big integer + is not representable as a small integer. *) + +(* Functions used by extraction *) + +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 + +let n_case fO fp n = if sign n <= 0 then fO () else fp n + +let z_case fO fp fn z = + let s = sign z in + if s = 0 then fO () else if s > 0 then fp z else fn (opp 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 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 positive_rec f2p1 f2p f1 = + let rec loop n = + if le n one then f1 + else + let (q,r) = quomod n two in + if eq r zero then f2p (loop q) else f2p1 (loop q) + in loop + +let z_rec fO fp fn = z_case (fun _ -> fO) fp fn + +let rec nat_rect acc f n = + if sign n <= 0 then acc else nat_rect (f () acc) f (pred 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" + +let shiftl_pos a p = Z.shift_left a (Z.to_int p) + +let modulo_pos a b = + assert (sign a >= 0); + assert (sign b >= 0); + modulo a b + +let div_pos a b = + assert (sign a >= 0); + assert (sign b > 0); + div a b + +let square a = Z.mul a a + +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 + 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 pos_div_eucl a b = + assert (sign a >= 0); + assert (sign b > 0); + Z.div_rem 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 + +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 + +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_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 classify = + | Zero of bool + | Infinity of bool + | NaN of bool * Z.t + | Finite of bool * Z.t * Z.t + +let combine_hash acc n = n * 65599 + acc diff --git a/farith2/thry/.gitignore b/farith2/thry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..cc786a9724d1c928c856bdcbef4ce2acdc6ede2d --- /dev/null +++ b/farith2/thry/.gitignore @@ -0,0 +1 @@ +doc/ \ No newline at end of file diff --git a/farith2/thry/.nra.cache b/farith2/thry/.nra.cache new file mode 100644 index 0000000000000000000000000000000000000000..d98ef9c4b6c6b430155da61742d938534ee28064 Binary files /dev/null and b/farith2/thry/.nra.cache differ diff --git a/farith2/thry/All.v b/farith2/thry/All.v new file mode 100644 index 0000000000000000000000000000000000000000..90ece08dd73b91e37aa7dcefd9ee4557c375ef92 --- /dev/null +++ b/farith2/thry/All.v @@ -0,0 +1,27 @@ +(** * A list of all submodules of Farith2 *) + +(** Usefull facts about floating points *) +From F Require Import Utils. + +(** An extension of [R] including infinite values + together with a new semantic for floating points +*) +From F Require Import Rextended. + +(** An extension of [Q] including infinite values + used to write the specifications of conversions from [Q] to [float] + and from [float] to [Q] +*) +From F Require Import Qextended. + +(** Correction lemmas associated to floating point binary operators *) +From F Require Import Utils. + +(** A 32 bits instanciation of Flocq's [BinarySingleNaN] *) +From F Require Import B32. + +(** Generic float intervals with verified propagators *) +From F Require Import Interval. + +(** A 32 bits instanciation of [Interval] *) +From F Require Import Intv32. \ No newline at end of file diff --git a/farith2/thry/B32.v b/farith2/thry/B32.v new file mode 100644 index 0000000000000000000000000000000000000000..3b42e90e6db5dec1dfb68aa50f953b2b3e0aa60e --- /dev/null +++ b/farith2/thry/B32.v @@ -0,0 +1,134 @@ +From Flocq Require Import Core.Core IEEE754.BinarySingleNaN IEEE754.Bits. +Require Import QArith. +Require Import Qreals. +Require Import Reals. +Require Import ZBits. +Require Import Lia Lra. +Require Coq.Arith.Wf_nat. +Require Import Extraction. +From F Require Import Qextended Rextended. + + +(** * An instanciation of Flocq's BinarySingleNan for 32 bits IEEE-754 floating points *) + +Module B32. + +(** ** 1. Precision, maximal exponent & their properties *) + +Definition prec : Z := 24. +Definition emax : Z := 128. +Definition mw : Z := 23. +Definition ew : Z := 8. +Definition t : Type := binary_float prec emax. + +Lemma Hprec : Prec_gt_0 prec. +Proof. + unfold Prec_gt_0, prec; lia. +Qed. + +Lemma Hemax : Prec_lt_emax prec emax. +Proof. + unfold Prec_lt_emax, prec, emax; lia. +Qed. + +Lemma Hmw : (0 < mw)%Z. +Proof. + unfold mw; lia. +Qed. + +Lemma Hew : (0 < ew)%Z. +Proof. + unfold ew; lia. +Qed. + +(** ** 2. Floating-points operators *) + +Definition add : mode -> t -> t -> t := @Bplus _ _ Hprec Hemax. +Definition sub : mode -> t -> t -> t := @Bminus _ _ Hprec Hemax. +Definition mult : mode -> t -> t -> t := @Bmult _ _ Hprec Hemax. +Definition div : mode -> t -> t -> t := @Bdiv _ _ Hprec Hemax. +Definition sqrt : mode -> t -> t := @Bsqrt _ _ Hprec Hemax. +Definition abs : t -> t := Babs. + +(** ** 3. Floating-points relations *) + +Definition le : t -> t -> bool := Bleb. +Definition lt : t -> t -> bool := Bltb. +Definition eq : t -> t -> bool := Beqb. +Definition ge : t -> t -> bool := fun x y => Bleb y x. +Definition gt : t -> t -> bool := fun x y => Bltb y x. + +(** ** 4. convertions to and from [Z] and [Q]*) + +Definition of_bits (b : Z) : t := + match Bits.binary_float_of_bits mw ew Hmw Hew Hemax 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. + +Definition pl_cst := (Zaux.iter_nat xO (Z.to_nat (Z.pred mw)) xH)%Z. + +Lemma pl_valid : (Z.pos (Digits.digits2_pos pl_cst) <? prec)%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, prec, mw. + rewrite G;clear G. + rewrite Nat2Z.inj_succ. + rewrite Z2Nat.id; [rewrite Z.ltb_lt | ]; lia. +Qed. + +Definition to_bits (f : t) : Z := + match f with + | B754_nan => + Bits.bits_of_binary_float mw ew (Binary.B754_nan prec emax true pl_cst pl_valid) + | B754_zero s => Bits.bits_of_binary_float mw ew (Binary.B754_zero prec emax s) + | B754_infinity s => Bits.bits_of_binary_float mw ew (Binary.B754_infinity prec emax s) + | B754_finite s m e H => Bits.bits_of_binary_float mw ew (Binary.B754_finite prec emax s m e H) + end. + +Definition of_q (m : mode) (q : Qx) : t := + 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 _ _ Hprec Hemax m false pn 0%Z false (Z.to_pos (den q)) 0%Z)) + | Z.neg nn => + SF2B _ (proj1 (Bdiv_correct_aux _ _ Hprec Hemax m true nn 0%Z false (Z.to_pos (den q)) 0%Z)) + end + end. + +Lemma of_q_correct : forall m q, Q2Rx q = B2Rx (of_q m q). +Proof. + intros 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 Q2R; simpl. + now rewrite Rmult_0_l. + - rewrite e. + destruct (Z.pos pq =? 0)%Z eqn:E1, (num q =? 0)%Z eqn:E2. + + rewrite Z.eqb_eq in E1; rewrite E1; + rewrite Z.eqb_eq in E2; rewrite E2. + reflexivity. + + admit. + + admit. + + admit. +Admitted. + +End B32. \ No newline at end of file diff --git a/farith2/thry/Correction_thms.v b/farith2/thry/Correction_thms.v new file mode 100644 index 0000000000000000000000000000000000000000..ae8eae891593325667706b4f48c757ee2e02e192 --- /dev/null +++ b/farith2/thry/Correction_thms.v @@ -0,0 +1,260 @@ +From Flocq Require Import IEEE754.BinarySingleNaN. +From Coq Require Import ZArith Lia Reals Psatz. +From F Require Import Utils Rextended. + +Section Correction. + +Variable prec : Z. +Variable emax : Z. +Context (Hprec : FLX.Prec_gt_0 prec). +Context (Hemax : Prec_lt_emax prec emax). + +Definition float : Type := binary_float prec emax. + + +Lemma B2SF_eq : + forall (x : float) y H, B2SF x = y -> x = SF2B y H. +Proof. + intros. + apply B2SF_inj. + rewrite H0. + symmetry. + apply B2SF_SF2B. +Qed. + +Lemma Bplus_correct : + forall (m : mode) (x y : float), + is_nan (Bplus m x y) = false -> + B2Rx (Bplus m x y) = round m (add (B2Rx x) (B2Rx y)). +Proof. + Ltac compute0 := + match goal with + | [ m : mode |- _ ] => + destruct m; simpl (B2Rx (B754_zero _)); (rewrite add_0_l || rewrite add_0_r); try apply round_id; apply round_0 + end. + intros m x y HnanS. + destruct (Bplus_not_nan_inv _ _ _ HnanS) as [HnanX HnanY]. + induction x as [ [ ] | [ ] | | ] eqn:Ex, y as [ [ ] | [ ] | | ] eqn:Ey; try easy; try compute0. + unfold add. + repeat rewrite (B2Rx_finite (B754_finite _ _ _ _)); auto. + unfold round. + assert (Fx : is_finite x = true) by (rewrite Ex; auto). + assert (Fy : is_finite y = true) by (rewrite Ey; auto). + pose proof (Bplus_correct _ _ _ _ m x y Fx Fy). + destruct (do_overflow _ _ _ _) eqn:Ho1. + - apply do_overflow_true in Ho1. + unfold dont_overflow in Ho1. + rewrite <- Ex, <- Ey in *. + unfold R_imax in Ho1. + rewrite Ho1 in H. + destruct H as [H1 H2]. + apply (B2SF_eq _ _ (binary_overflow_correct _ _ _ _ _ _)) in H1. + destruct m eqn:Em, (sign (B2R x + B2R y)) eqn:Hs. + + simpl in *. rewrite H1; simpl. + fdestruct x; fdestruct y. + destruct s1, s2; simpl in *; try easy. + unfold Defs.F2R in Hs; simpl in Hs. + apply sign_neg_inv in Hs. + pose proof (IZR_pos m2); pose proof (IZR_pos m3); + pose proof (Raux.bpow_gt_0 Zaux.radix2 e3); + pose proof (Raux.bpow_gt_0 Zaux.radix2 e5); nra. + + simpl in *. rewrite H1; simpl. + fdestruct x; fdestruct y. + destruct s1, s2; simpl in *; try easy. + unfold Defs.F2R in Hs; simpl in Hs. + apply sign_pos_inv in Hs. + pose proof (IZR_neg m2); pose proof (IZR_neg m3); + pose proof (Raux.bpow_gt_0 Zaux.radix2 e3); + pose proof (Raux.bpow_gt_0 Zaux.radix2 e5); nra. + + simpl in *. rewrite H1; simpl. + fdestruct x; fdestruct y. + destruct s1, s2; simpl in *; try easy. + unfold Defs.F2R in Hs; simpl in Hs. + apply sign_neg_inv in Hs. + pose proof (IZR_pos m2); pose proof (IZR_pos m3); + pose proof (Raux.bpow_gt_0 Zaux.radix2 e3); + pose proof (Raux.bpow_gt_0 Zaux.radix2 e5); nra. + + simpl in *. rewrite H1; simpl. + fdestruct x; fdestruct y. + destruct s1, s2; simpl in *; try easy. + unfold Defs.F2R in Hs; simpl in Hs. + apply sign_pos_inv in Hs. + change (Z.neg m2) with (- Z.pos m2)%Z in Hs. + change (Z.neg m3) with (- Z.pos m3)%Z in Hs. + repeat rewrite opp_IZR in Hs. + pose proof (IZR_pos m2); pose proof (IZR_pos m3); + pose proof (Raux.bpow_gt_0 Zaux.radix2 e3); + pose proof (Raux.bpow_gt_0 Zaux.radix2 e5); nra. + + simpl in *. rewrite H1; simpl. + fdestruct x; fdestruct y. + destruct s1, s2; simpl in *; try easy. + unfold Defs.F2R in Hs; simpl in Hs. + apply sign_neg_inv in Hs. + pose proof (IZR_pos m2); pose proof (IZR_pos m3); + pose proof (Raux.bpow_gt_0 Zaux.radix2 e3); + pose proof (Raux.bpow_gt_0 Zaux.radix2 e5); nra. + + simpl in *. rewrite H1; simpl. + fdestruct x; fdestruct y. + destruct s1, s2; simpl in *; try easy. + unfold Defs.F2R in Hs; simpl in Hs. + apply sign_pos_inv in Hs. + pose proof (IZR_neg m2); pose proof (IZR_neg m3); + pose proof (Raux.bpow_gt_0 Zaux.radix2 e5); + pose proof (Raux.bpow_gt_0 Zaux.radix2 e3); + nra. + + simpl in *. rewrite H1; simpl. + fdestruct x; fdestruct y. + destruct s1, s2; simpl in *; try easy. + unfold Defs.F2R in Hs; simpl in Hs. + apply sign_neg_inv in Hs. + pose proof (IZR_pos m2); pose proof (IZR_pos m3); + pose proof (Raux.bpow_gt_0 Zaux.radix2 e3); + pose proof (Raux.bpow_gt_0 Zaux.radix2 e5); nra. + + simpl in *. rewrite H1; simpl. + fdestruct x; fdestruct y. + destruct s1, s2; simpl in *; try easy. + unfold Defs.F2R in Hs; simpl in Hs. + apply sign_pos_inv in Hs. + pose proof (IZR_neg m2); pose proof (IZR_neg m3); + pose proof (Raux.bpow_gt_0 Zaux.radix2 e3); + pose proof (Raux.bpow_gt_0 Zaux.radix2 e5); nra. + + simpl in *. rewrite H1; simpl. + fdestruct x; fdestruct y. + destruct s1, s2; simpl in *; try easy. + unfold Defs.F2R in Hs; simpl in Hs. + apply sign_neg_inv in Hs. + pose proof (IZR_pos m2); pose proof (IZR_pos m3); + pose proof (Raux.bpow_gt_0 Zaux.radix2 e3); + pose proof (Raux.bpow_gt_0 Zaux.radix2 e5); nra. + + simpl in *. rewrite H1; simpl. + fdestruct x; fdestruct y. + destruct s1, s2; simpl in *; try easy. + unfold Defs.F2R in Hs; simpl in Hs. + apply sign_pos_inv in Hs. + pose proof (IZR_neg m2); pose proof (IZR_neg m3); + pose proof (Raux.bpow_gt_0 Zaux.radix2 e3); + pose proof (Raux.bpow_gt_0 Zaux.radix2 e5); nra. + - apply do_overflow_false in Ho1. + unfold dont_overflow in Ho1. + rewrite <- Ex, <- Ey in *. + unfold R_imax in Ho1. + rewrite Ho1 in H. + now destruct H as [<- [Hf _]], (Bplus _ _ _). +Qed. + +Theorem Bplus_le_compat: + forall m (a b c : float), + is_nan (Bplus m a c) = false -> + is_nan (Bplus m b c) = false -> + a <= b -> + Bplus m a c <= Bplus m b c. +Proof. + intros m a b c Hnan1 Hnan2 Hab. + apply B2Rx_le; try easy. + rewrite (Bplus_correct m a c Hnan1). + rewrite (Bplus_correct m b c Hnan2). + apply round_le. + apply add_leb_mono_l. + fdestruct a; fdestruct b; simpl. + - apply Raux.Rle_bool_true; lra. + - apply Raux.Rle_bool_true; lra. + - destruct s; simpl; try easy. + unfold Defs.F2R; simpl. + apply Raux.Rle_bool_true. + pose proof (IZR_pos m0). + pose proof (Raux.bpow_gt_0 Zaux.radix2 e). + nra. + - apply Raux.Rle_bool_true; lra. + - apply Raux.Rle_bool_true; lra. + - destruct s; simpl; try easy. + unfold Defs.F2R; simpl. + apply Raux.Rle_bool_true. + pose proof (IZR_pos m0). + pose proof (Raux.bpow_gt_0 Zaux.radix2 e). + nra. + - destruct s; simpl; try easy. + unfold Defs.F2R; simpl. + apply Raux.Rle_bool_true. + pose proof (IZR_neg m0). + pose proof (Raux.bpow_gt_0 Zaux.radix2 e). + nra. + - destruct s; simpl; try easy. + unfold Defs.F2R; simpl. + apply Raux.Rle_bool_true. + pose proof (IZR_neg m0). + pose proof (Raux.bpow_gt_0 Zaux.radix2 e). + nra. + - destruct s, s0; simpl; try easy; + apply Bleb_Rle in Hab; auto; + now apply Raux.Rle_bool_true. +Qed. + +Theorem Bplus_le_compat_l: + forall m (a b c : float), + is_nan (Bplus m c a) = false -> + is_nan (Bplus m c b) = false -> + a <= b -> + Bplus m c a <= Bplus m c b. +Proof. + intros m a b c Hnan1 Hnan2 Hab. + apply B2Rx_le; try easy. + rewrite (Bplus_correct m c a Hnan1). + rewrite (Bplus_correct m c b Hnan2). + apply round_le. + apply add_leb_mono_r. + fdestruct a; fdestruct b; simpl. + - apply Raux.Rle_bool_true; lra. + - apply Raux.Rle_bool_true; lra. + - destruct s; simpl; try easy. + unfold Defs.F2R; simpl. + apply Raux.Rle_bool_true. + pose proof (IZR_pos m0). + pose proof (Raux.bpow_gt_0 Zaux.radix2 e). + nra. + - apply Raux.Rle_bool_true; lra. + - apply Raux.Rle_bool_true; lra. + - destruct s; simpl; try easy. + unfold Defs.F2R; simpl. + apply Raux.Rle_bool_true. + pose proof (IZR_pos m0). + pose proof (Raux.bpow_gt_0 Zaux.radix2 e). + nra. + - destruct s; simpl; try easy. + unfold Defs.F2R; simpl. + apply Raux.Rle_bool_true. + pose proof (IZR_neg m0). + pose proof (Raux.bpow_gt_0 Zaux.radix2 e). + nra. + - destruct s; simpl; try easy. + unfold Defs.F2R; simpl. + apply Raux.Rle_bool_true. + pose proof (IZR_neg m0). + pose proof (Raux.bpow_gt_0 Zaux.radix2 e). + nra. + - destruct s, s0; simpl; try easy; + apply Bleb_Rle in Hab; auto; + now apply Raux.Rle_bool_true. +Qed. + +Theorem Bplus_le_compat': + forall m (a b c d : float), + is_nan (Bplus m a b) = false -> + is_nan (Bplus m c d) = false -> + a <= c -> + b <= d -> + Bplus m a b <= Bplus m c d. +Proof. + intros. + apply B2Rx_le; try easy. + rewrite (Bplus_correct m a b); auto. + rewrite (Bplus_correct m c d); auto. + eapply leb_trans. + - apply round_le. + apply add_leb_mono_l. + apply (le_B2Rx _ _ H1). + - apply round_le. + apply add_leb_mono_r. + apply (le_B2Rx _ _ H2). +Qed. + +End Correction. \ No newline at end of file diff --git a/farith2/thry/Interval.v b/farith2/thry/Interval.v new file mode 100644 index 0000000000000000000000000000000000000000..5279d9c0a412e8b62e6821db23b23de92cab5d4a --- /dev/null +++ b/farith2/thry/Interval.v @@ -0,0 +1,411 @@ +From Flocq Require Import IEEE754.BinarySingleNaN. +From Coq Require Import QArith Psatz Reals Extraction. +Require Import F.Utils F.Correction_thms F.Rextended. + +(********************************************************* + Interval arithmetic over floatting points +**********************************************************) + +Section Finterval. + +Variable prec : Z. +Variable emax : Z. +Context (Hprec : FLX.Prec_gt_0 prec). +Context (Hemax : Prec_lt_emax prec emax). + +Definition float := binary_float prec emax. + +Inductive Interval' := + | Inan : Interval' + | Intv : forall (lo hi : float) (nan : bool), Interval'. + +Definition valid (I : Interval') := + match I with + | Intv lo hi _ => lo <= hi + | _ => True + end. + +Definition valid_opt (I : option Interval') := + match I with + | Some (Intv lo hi _) => lo <= hi + | _ => True + end. + +Definition Interval := { I : Interval' | valid I }. + +Definition Interval_opt := { I : option Interval' | valid_opt I }. + +Program Definition contains (I : Interval') (x : float) : Prop := + match I with + | Inan => is_nan x = true + | Intv lo hi nan => + lo <= x <= hi \/ (is_nan x && nan = true) + end. + +Definition contains_opt (I : option Interval') (x : float) : Prop := + match I with + | None => False + | Some i => contains i x + end. + +Program Definition inter' (I1 I2 : Interval') : option Interval' := + match I1, I2 with + | Inan, Inan => Some Inan + | Inan, Intv _ _ nan => + if nan then Some Inan else None + | Intv _ _ nan, Inan => + if nan then Some (Inan) else None + | Intv lo1 hi1 nan1, Intv lo2 hi2 nan2 => + if Bltb hi1 lo2 || Bltb hi2 lo1 then + if nan1 && nan2 then Some Inan else None + else + Some (Intv (Bmax lo1 lo2) (Bmin hi1 hi2) (nan1 && nan2)) + end. + +Ltac ieasy := + simpl in *; try easy; try (intuition; fail). + +Ltac sdestruct x := + try destruct x; simpl; easy. + +Program Definition inter (I1 I2 : Interval) : Interval_opt := + inter' I1 I2. +Next Obligation. + destruct I1 as [[|lo1 hi1 nan1] H1], I2 as [[|lo2 hi2 nan2] H2]; ieasy; try (now destruct nan1 || now destruct nan2). + case (Bltb (hi1) (lo2)) eqn:?, (Bltb (hi2) (lo1)) eqn:?; simpl; try (destruct nan1, nan2; simpl; easy). + pose proof (le_not_nan_l _ _ H1). + pose proof (le_not_nan_r _ _ H2). + pose proof (le_not_nan_r _ _ H1). + pose proof (le_not_nan_l _ _ H2). + auto using Bmax_le, Bmin_le, Bltb_false_Bleb. +Defined. + +Program Lemma inter_precise_l : + forall I1 I2, forall x, contains_opt (inter I1 I2) x -> contains I1 x. +Proof with auto. + intros [[|lo1 hi1 nan1] H1] [[|lo2 hi2 nan2] H2] x Hx; simpl in *... + + destruct nan2; fdestruct x. + + right; destruct nan1; fdestruct x. + + case (Bltb hi1 lo2) eqn:?, (Bltb hi2 lo1) eqn:?; simpl in *; + try (right; destruct nan1, nan2; simpl in *; fdestruct x; fail). + destruct Hx as [[Hc1 Hc2] | H ]. + - left; split; [ apply (Bmax_le_inv _ _ _ _ _ Hc1) | apply (Bmin_le_inv _ _ _ _ _ Hc2) ]. + - repeat rewrite andb_true_iff in H; intuition. +Qed. + +Program Lemma inter_precise_r : + forall I1 I2, forall x, contains_opt (inter I1 I2) x -> contains I2 x. +Proof with auto. + intros [[|lo1 hi1 nan1] H1] [[|lo2 hi2 nan2] H2] x Hx; simpl in *... + + right; destruct nan2; fdestruct x. + + destruct nan1; fdestruct x. + + case (Bltb hi1 lo2) eqn:?, (Bltb hi2 lo1) eqn:?; simpl in *; + try (right; destruct nan1, nan2; simpl in *; fdestruct x; fail). + destruct Hx as [[Hc1 Hc2] | H ]. + - left; split; [ apply (Bmax_le_inv _ _ _ _ _ Hc1) | apply (Bmin_le_inv _ _ _ _ _ Hc2) ]. + - repeat rewrite andb_true_iff in H; intuition. +Qed. + +Program Lemma inter_correct : + forall (I1 I2 : Interval), forall x, contains I1 x -> contains I2 x -> contains_opt (inter I1 I2) x. +Proof with auto. + intros [[|lo1 hi1 nan1] H1] [[|lo2 hi2 nan2] H2] x Hx1 Hx2; simpl in *... + - fdestruct x; destruct nan2, Hx2; try easy. + - fdestruct x; destruct nan1, Hx1; try easy. + - pose proof (le_not_nan_l _ _ H1). + pose proof (le_not_nan_r _ _ H1). + pose proof (le_not_nan_l _ _ H2). + pose proof (le_not_nan_r _ _ H2). + destruct Hx1 as [[Hc1 Hc1'] |], Hx2 as [[Hc2 Hc2'] |]; try (fdestruct x ; fail). + + pose proof (Hlt1 := Bleb_trans _ _ _ Hc2 Hc1'). + apply Bleb_true_Bltb in Hlt1... + pose proof (Hlt2 := Bleb_trans _ _ _ Hc1 Hc2'). + apply Bleb_true_Bltb in Hlt2... + rewrite Hlt1, Hlt2; simpl; left; split; auto using Bmax_le, Bmin_le. + + fdestruct x; destruct nan2, nan1, (Bltb hi1 _), (Bltb hi2); simpl; try easy. + now right. +Qed. + +Definition Iadd' (m : mode) (I1 I2 : Interval') : Interval' := + match I1, I2 with + | Inan, _ => Inan + | _, Inan => Inan + | Intv l h n, Intv l' h' n' => + let sum1 := Bplus m l l' in + let sum2 := Bplus m h h' in + match is_nan sum1 with + | true => + match is_nan sum2 with + | true => Inan + | false => Intv +oo +oo true + end + | false => + match is_nan sum2 with + | true => Intv -oo -oo true + | false => Intv sum1 sum2 (n || n' || (Beqb h +oo && Beqb l' -oo) || (Beqb h' +oo && Beqb l -oo)) + end + end + end. + +Program Definition Iadd (m : mode) (I1 I2 : Interval) : Interval := + Iadd' m I1 I2. +Next Obligation. + destruct I1 as [[|l1 h1] H1], I2 as [[|l2 h2] H2]; simpl in *; auto. + destruct (is_nan (Bplus m l1 l2)) eqn:E1, (is_nan (Bplus m h1 h2)) eqn:E2; try easy; simpl. + apply B2Rx_le; auto. + repeat (rewrite Bplus_correct; auto). + apply round_le. + eapply leb_trans. + - apply (add_leb_mono_l _ _ _ (le_B2Rx _ _ H1)). + - apply (add_leb_mono_r _ _ _ (le_B2Rx _ _ H2)). +Qed. + +Program Lemma Iadd_correct : + forall m (I1 I2 : Interval) (x y : float), contains I1 x -> contains I2 y -> contains (Iadd m I1 I2) (Bplus m x y). +Proof with auto. + intros m [[|l1 h1] H1] [[|l2 h2] H2] x y Hx Hy; simpl in *; try (fdestruct x; fdestruct y; fail). + case (is_nan (Bplus m l1 l2)) eqn:E1, (is_nan (Bplus m h1 h2)) eqn:E2; intuition; simpl. + all: try (fdestruct x; fdestruct y; simpl; auto; fail). + - destruct (Bplus_nan_inv _ _ _ E1); intuition; subst; try easy. + * rewrite (infp_le_is_infp _ _ _ H0) in *. + rewrite (infp_le_is_infp _ _ _ H1) in *. + fdestruct h2. + rewrite (le_infm_is_infm _ _ _ H5) in *... + * rewrite (infp_le_is_infp _ _ _ H4) in *. + rewrite (infp_le_is_infp _ _ _ H2) in *. + fdestruct h1. + rewrite (le_infm_is_infm _ _ _ H3) in *... + - destruct (Bplus_nan_inv _ _ _ E1) as [[ -> -> ] | [ [ -> -> ] | [ -> | -> ]]]; try easy; + fdestruct x; fdestruct y; simpl... + - destruct (Bplus_nan_inv _ _ _ E2) as [[ -> -> ] | [ [ -> -> ] | [ -> | -> ]]]; try easy; + fdestruct x; fdestruct y; simpl... + - destruct (is_nan (Bplus m x y)) eqn:E. + + right. destruct (Bplus_nan_inv _ _ _ E) as [ [-> ->] | [ [ -> -> ] | ] ]. + * rewrite (infp_le_is_infp _ _ _ H3) in *. + rewrite (le_infm_is_infm _ _ _ H4) in *. + fdestruct l2; simpl; fdestruct h1; simpl; intuition. + * rewrite (infp_le_is_infp _ _ _ H5) in *. + rewrite (le_infm_is_infm _ _ _ H0) in *. + fdestruct h1; simpl; fdestruct l2; simpl; intuition. + * destruct H as [ -> | -> ]; fdestruct h1. + + left. split; now apply Bplus_le_compat'. + - right; fdestruct y; fdestruct x; destruct nan0; simpl; intuition. + - right; fdestruct y; fdestruct x; destruct nan; simpl; intuition. + - right; fdestruct y; fdestruct x; destruct nan; simpl; intuition. +Qed. + +Notation "'Interval+⊥'" := Interval_opt. + +Program Definition Ile (I : Interval) : Interval+⊥ := + match I with + | Inan => None + | Intv a b n => + Some (Intv -oo b n) + end. +Next Obligation. + destruct I as [[|l1 h1] H1]; simpl in *; fdestruct b. + inversion Heq_I; subst. + fdestruct l1. +Defined. + + +Program Theorem Ile_correct : + forall (I : Interval) (x y : float), contains I y -> x <= y -> contains_opt (Ile I) x. +Proof. + intros [[| l1 h1] H1] x y Hx Hxy; simpl in *. + - fdestruct y; fdestruct x. + - destruct (is_nan x), Hx as [ [H H'] | ]; + try (left ; idtac; split; [ fdestruct x | apply (Bleb_trans _ _ _ Hxy H')]); + try (right ; fdestruct y; fdestruct x). +Qed. + +Program Definition Ilt (I : Interval) : Interval+⊥ := + match I with + | Inan => None + | Intv a b n => + Some (Intv -oo b n) + end. +Next Obligation. + destruct I as [[|l1 h1] H1]; simpl in *; fdestruct b; + inversion Heq_I; subst; fdestruct l1. +Defined. + + +Program Theorem Ilt_correct : + forall (I : Interval) (x y : float), contains I y -> Bltb x y = true -> contains_opt (Ilt I) x. +Proof. + intros [[| l1 h1] H1] x y Hx Hxy; simpl in *. + - fdestruct y; fdestruct x. + - apply Bltb_Bleb in Hxy. + destruct (is_nan x), Hx as [ [H H'] | ]; + try (left ; idtac; split; [ fdestruct x | apply (Bleb_trans _ _ _ Hxy H')]); + try (right ; fdestruct y; fdestruct x). +Qed. + +Program Definition Ige (I : Interval) : Interval+⊥ := + match I with + | Inan => None + | Intv a b n => + Some (Intv a +oo n) + end. +Next Obligation. + destruct I as [[|l1 h1] H1]; simpl in *; fdestruct b; + inversion Heq_I; subst; fdestruct l1. +Defined. + +Program Theorem Ige_correct : + forall (I : Interval) (x y : float), contains I y -> Bleb y x = true -> contains_opt (Ige I) x. +Proof. + intros [[| l1 h1] H1] x y Hx Hxy; simpl in *. + - fdestruct y; fdestruct x. + - destruct (is_nan x), Hx as [ [H H'] | ]; + try (left ; idtac; split; [ apply (Bleb_trans _ _ _ H Hxy) | fdestruct x; fdestruct y ]); + try (right ; fdestruct y; fdestruct x). +Qed. + +Program Definition Igt (I : Interval) : Interval+⊥ := + match I with + | Inan => None + | Intv a b n => + Some (Intv a +oo n) + end. +Next Obligation. + destruct I as [[|l1 h1] H1]; simpl in *; fdestruct b; + inversion Heq_I; subst; fdestruct l1. +Defined. + +Program Theorem Igt_correct : + forall (I : Interval) (x y : float), contains I y -> Bltb y x = true -> contains_opt (Igt I) x. +Proof. + intros [[| l1 h1] H1] x y Hx Hxy; simpl in *. + - fdestruct y; fdestruct x. + - apply Bltb_Bleb in Hxy. + destruct (is_nan x), Hx as [ [H H'] | ]; + try (left ; idtac; split; [ apply (Bleb_trans _ _ _ H Hxy) | fdestruct x; fdestruct y ]); + try (right ; fdestruct y; fdestruct x). +Qed. + +Program Definition inter_opt (I1 I2 : Interval+⊥) : Interval+⊥ := + match I1, I2 with + | None, _ => None + | _, None => None + | Some i1, Some i2 => inter i1 i2 + end. +Next Obligation. + destruct I1 as [[[|l1 h1 n1]|] H1]; simpl in *; now inversion Heq_I1. +Defined. +Next Obligation. + destruct I2 as [[[|l1 h1 n1]|] H1]; simpl in *; now inversion Heq_I2. +Defined. + +Program Definition to_opt (I : Interval) : Interval+⊥ := + Some (I :>). +Next Obligation. + now destruct I as [[| l h n ] H]. +Defined. + +Coercion to_opt : Interval >-> Interval_opt. + +Ltac fall_cases x := + try (fdestruct x; fail). + +Ltac fall_cases2 x y := + try (fdestruct x; fdestruct y; fail). + + +Definition Ige_inv (I1 I2 : Interval) : Interval+⊥ * Interval+⊥ := + (inter_opt (Ige I2) I1, inter_opt (Ile I1) I2). + +Program Theorem Ige_inv_correct : + forall (I1 I2 : Interval) (x y : float), + contains I1 x -> contains I2 y -> + y <= x -> + contains_opt (fst (Ige_inv I1 I2)) x /\ + contains_opt (snd (Ige_inv I1 I2)) y. +Proof. + intros [[|l1 h1 n1] H1] [[|l2 h2 n2] H2] x y Hx Hy Hxy; fall_cases2 x y. + split; apply inter_correct; simpl in *; auto. + + destruct Hx as [[Hx Hx'] | Hx], Hy as [[Hy Hy'] | Hy]; fall_cases2 y x. + left; split; [ apply (Bleb_trans _ _ _ Hy Hxy) | fdestruct x ]. + + destruct Hx as [[Hx Hx'] | Hx], Hy as [[Hy Hy'] | Hy]; fall_cases2 y x. + left; split; [ fdestruct y; fdestruct x | apply (Bleb_trans _ _ _ Hxy Hx') ]. +Qed. + + +Definition Igt_inv (I1 I2 : Interval) : Interval+⊥ * Interval+⊥ := + (inter_opt (Igt I2) I1, inter_opt (Ilt I1) I2). + +Program Theorem Igt_inv_correct : + forall (I1 I2 : Interval) (x y : float), + contains I1 x -> contains I2 y -> + Bltb y x = true -> + contains_opt (fst (Igt_inv I1 I2)) x /\ + contains_opt (snd (Igt_inv I1 I2)) y. +Proof. + intros [[|l1 h1 n1] H1] [[|l2 h2 n2] H2] x y Hx Hy Hxy; fall_cases2 x y. + split; apply inter_correct; simpl in *; auto; destruct Hx as [[Hx Hx'] | Hx], Hy as [[Hy Hy'] | Hy]; auto; fall_cases2 x y. + + left; split. + * apply (Bleb_trans _ _ _ Hy (Bltb_Bleb _ _ _ _ Hxy)). + * fdestruct x. + + left; split. + * fdestruct y. + * apply (Bleb_trans _ _ _ (Bltb_Bleb _ _ _ _ Hxy) Hx'). +Qed. + +Definition Ilt_inv (I1 I2 : Interval) : Interval+⊥ * Interval+⊥ := + (inter_opt (Ilt I2) I1, inter_opt (Igt I1) I2). + +Program Theorem Ilt_inv_correct : + forall (I1 I2 : Interval) (x y : float), + contains I1 x -> contains I2 y -> + Bltb x y = true -> + contains_opt (fst (Ilt_inv I1 I2)) x /\ + contains_opt (snd (Ilt_inv I1 I2)) y. +Proof. + intros [[|l1 h1 n1] H1] [[|l2 h2 n2] H2] x y Hx Hy Hxy; fall_cases2 x y. + split; apply inter_correct; simpl in *; auto; destruct Hx as [[Hx Hx'] | Hx], Hy as [[Hy Hy'] | Hy]; auto; fall_cases2 x y. + + left; split; fall_cases x. + apply (Bleb_trans _ _ _ (Bltb_Bleb _ _ _ _ Hxy) Hy'). + + left; split; fall_cases y. + apply (Bleb_trans _ _ _ Hx (Bltb_Bleb _ _ _ _ Hxy)). +Qed. + +Definition Ile_inv (I1 I2 : Interval) : Interval+⊥ * Interval+⊥ := + (inter_opt (Ile I2) I1, inter_opt (Ige I1) I2). + +Program Theorem Ile_inv_correct : + forall (I1 I2 : Interval) (x y : float), + contains I1 x -> contains I2 y -> + x <= y -> + contains_opt (fst (Ile_inv I1 I2)) x /\ + contains_opt (snd (Ile_inv I1 I2)) y. +Proof. + intros [[|l1 h1 n1] H1] [[|l2 h2 n2] H2] x y Hx Hy Hxy; fall_cases2 x y. + split; apply inter_correct; simpl in *; auto; destruct Hx as [[Hx Hx'] | Hx], Hy as [[Hy Hy'] | Hy]; auto; fall_cases2 x y. + + left; split; fall_cases x. + apply (Bleb_trans _ _ _ Hxy Hy'). + + left; split; fall_cases y. + apply (Bleb_trans _ _ _ Hx Hxy). +Qed. + +Definition Ieq_inv (I1 I2 : Interval) : Interval+⊥ * Interval+⊥ := + (inter_opt I1 I2, inter_opt I1 I2). + +Program Theorem Ieq_inv_correct : + forall (I1 I2 : Interval) (x y : float), + contains I1 x -> contains I2 y -> + Beqb x y = true -> + contains_opt (fst (Ieq_inv I1 I2)) x /\ + contains_opt (snd (Ieq_inv I1 I2)) y. +Proof. + intros [[|l1 h1 n1] H1] [[|l2 h2 n2] H2] x y Hx Hy Hxy; fall_cases2 x y. + split; apply inter_correct; simpl in *; auto; destruct Hx as [[Hx Hx'] | Hx], Hy as [[Hy Hy'] | Hy]; auto; fall_cases2 x y. + + left; split. + * apply (Bleb_trans l2 y x Hy (Beqb_Bleb _ _ _ _ (Beqb_symm _ _ _ _ Hxy))). + * apply (Bleb_trans x y h2 (Beqb_Bleb _ _ _ _ Hxy) Hy'). + + left; split. + * apply (Bleb_trans l1 x y Hx (Beqb_Bleb _ _ _ _ Hxy)). + * apply (Bleb_trans y x h1 (Beqb_Bleb _ _ _ _ (Beqb_symm _ _ _ _ Hxy)) Hx'). +Qed. + +End Finterval. \ No newline at end of file diff --git a/farith2/thry/Intv32.v b/farith2/thry/Intv32.v new file mode 100644 index 0000000000000000000000000000000000000000..5c135e067d802817f17495dc2ebd952527d9078c --- /dev/null +++ b/farith2/thry/Intv32.v @@ -0,0 +1,170 @@ +From Coq Require Import ZArith Extraction Bool Psatz ExtrOcamlBasic. +From Flocq Require Import IEEE754.BinarySingleNaN FLX. +From F Require Import Utils Interval B32. + +Notation "x '+⊥'" := (option x) (at level 80). + +Module Intv32. + Definition prec := 24%Z. + Definition emax := 128%Z. + Definition float32 := B32.t. + + Lemma Hprec : Prec_gt_0 prec. + Proof. unfold Prec_gt_0, prec; lia. Qed. + + Lemma Hemax : Prec_lt_emax prec emax. + Proof. unfold Prec_lt_emax, prec, emax; lia. Qed. + + Definition t := Interval prec emax. + + Definition t_opt := Interval_opt prec emax. + + Program Definition contains : t -> float32 -> Prop := contains prec emax. + + Program Definition contains_opt : t_opt -> float32 -> Prop := contains_opt prec emax. + + Definition inter (x y : t) : t_opt := + @inter prec emax x y. + + Definition add : mode -> t -> t -> t := + @Iadd prec emax Hprec Hemax. + + Program Lemma inter_correct : + forall (i1 i2 : t) (x : float32), + contains i1 x -> contains i2 x -> contains_opt (inter i1 i2) x. + Proof. + apply (inter_correct prec emax). + Qed. + + Lemma inter_precise : + forall (i1 i2 : t) (x : float32), + contains_opt (inter i1 i2) x -> contains i1 x /\ contains i2 x. + Proof. + intros; split. + - apply (inter_precise_l prec emax _ _ _ H). + - apply (inter_precise_r prec emax _ _ _ H). + Qed. + + Lemma add_correct : + forall (m : mode) (i1 i2 : t) (x y : float32), + contains i1 x -> contains i2 y -> contains (add m i1 i2) (@Bplus prec emax Hprec Hemax m x y). + Proof. apply Iadd_correct. Qed. + + Program Definition top : t := Intv prec emax -oo +oo true. + + Program Definition bot : t_opt := None. + + Lemma top_correct : + forall (x : float32), contains top x. + Proof with auto. + unfold top, contains; fdestruct x; simpl... + Qed. + + Lemma bot_correct : + forall (x : float32), contains_opt bot x -> False. + Proof with auto. + unfold bot, contains; fdestruct x. + Qed. + + Program Definition is_singleton (I : t) : option float32 := + match 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 prec emax := Intv _ _ (B754_zero false) (B754_zero true) false. + + Program Theorem is_singleton_correct : + forall (I : t) (x : float32), (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 : float32) : t := + match x with + | B754_nan => Inan prec emax + | _ => Intv _ _ x x false + end. + Next Obligation. + apply Bleb_refl. + fdestruct x. + Defined. + + Program Theorem singleton_correct : + forall (x : float32), 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 ge : t -> t_opt := @Ige prec emax. + Program Definition le : t -> t_opt := @Ile prec emax. + Program Definition lt : t -> t_opt := @Ilt prec emax. + Program Definition gt : t -> t_opt := @Igt prec emax. + + Program Definition le_inv : t -> t -> (t_opt * t_opt) := @Ile_inv prec emax. + Program Definition ge_inv : t -> t -> (t_opt * t_opt) := @Ige_inv prec emax. + Program Definition lt_inv : t -> t -> (t_opt * t_opt) := @Ilt_inv prec emax. + Program Definition gt_inv : t -> t -> (t_opt * t_opt) := @Igt_inv prec emax. + Program Definition eq_inv : t -> t -> (t_opt * t_opt) := @Ieq_inv prec emax. + + Theorem le_inv_correct : + forall (I1 I2 : t) (x y : float32), + contains I1 x -> contains I2 y -> x <= y -> + contains_opt (fst (le_inv I1 I2)) x /\ contains_opt (snd (le_inv I1 I2)) y. + Proof. apply (@Ile_inv_correct prec emax). Qed. + + Theorem ge_inv_correct : + forall (I1 I2 : t) (x y : float32), + contains I1 x -> contains I2 y -> y <= x -> + contains_opt (fst (ge_inv I1 I2)) x /\ contains_opt (snd (ge_inv I1 I2)) y. + Proof. apply (@Ige_inv_correct prec emax). Qed. + + Theorem gt_inv_correct : + forall (I1 I2 : t) (x y : float32), + contains I1 x -> contains I2 y -> Bltb y x = true -> + contains_opt (fst (gt_inv I1 I2)) x /\ contains_opt (snd (gt_inv I1 I2)) y. + Proof. apply (@Igt_inv_correct prec emax). Qed. + + Theorem lt_inv_correct : + forall (I1 I2 : t) (x y : float32), + contains I1 x -> contains I2 y -> Bltb x y = true -> + contains_opt (fst (lt_inv I1 I2)) x /\ contains_opt (snd (lt_inv I1 I2)) y. + Proof. apply (@Ilt_inv_correct prec emax). Qed. + + Theorem eq_inv_correct : + forall (I1 I2 : t) (x y : float32), + contains I1 x -> contains I2 y -> Beqb x y = true -> + contains_opt (fst (eq_inv I1 I2)) x /\ contains_opt (snd (eq_inv I1 I2)) y. + Proof. apply (@Ieq_inv_correct prec emax). Qed. + + Theorem le_correct : + forall (I : t) (x y : float32), contains I y -> x <= y -> contains_opt (le I) x. + Proof. apply (@Ile_correct prec emax). Qed. + + Theorem lt_correct : + forall (I : t) (x y : float32), contains I y -> Bltb x y = true -> contains_opt (lt I) x. + Proof. apply (@Ilt_correct prec emax). Qed. + + Theorem ge_correct : + forall (I : t) (x y : float32), contains I y -> y <= x -> contains_opt (ge I) x. + Proof. apply (@Ige_correct prec emax). Qed. + + Theorem gt_correct : + forall (I : t) (x y : float32), contains I y -> Bltb y x = true -> contains_opt (gt I) x. + Proof. apply (@Igt_correct prec emax). Qed. + +End Intv32. \ No newline at end of file diff --git a/farith2/thry/Qextended.v b/farith2/thry/Qextended.v new file mode 100644 index 0000000000000000000000000000000000000000..e6fbf4afac0b73bc80c54753b7f194b40d504a1f --- /dev/null +++ b/farith2/thry/Qextended.v @@ -0,0 +1,68 @@ +From Coq Require Import ZArith Reals Qreals Extraction. +From F Require Import Rextended. + +(** * A type of rationals suitable for conversions from and to fp + and compatible with zarith Q +*) + +Record Qx := Qxmake { + num : Z.t; den : Z.t; + Hden1 : (0 <=? den)%Z = true; + Hden2 : (if den =? 0 then orb (orb (num =? -1) (num =? 0)) (num =? 1) else Z.gcd num den =? 1)%Z = true +}. + +Lemma Hden2' : + forall q, (den q = 0 -> num q = -1 \/ num q = 0 \/ num q = 1)%Z. +Proof. + intros q H. + rewrite <- !Z.eqb_eq in *. + assert (H2 := Hden2 q). + rewrite H in H2. + destruct (num q =? -1)%Z; destruct (num q =? 0)%Z; destruct (num q =? 1)%Z; + tauto. +Qed. + +Definition Qx_zero := Qxmake 0%Z 1%Z (refl_equal _) (refl_equal _). +Definition Qx_undef := Qxmake 0%Z 0%Z (refl_equal _) (refl_equal _). +Definition Qx_inf := Qxmake 1%Z 0%Z (refl_equal _) (refl_equal _). +Definition Qx_minus_inf := Qxmake (-1)%Z 0%Z (refl_equal _) (refl_equal _). +Definition Qx_half := Qxmake (1)%Z 2%Z (refl_equal _) (refl_equal _). +Definition Qx_one := Qxmake (1)%Z 1%Z (refl_equal _) (refl_equal _). +Definition Qx_two := Qxmake (2)%Z (1)%Z (refl_equal _) (refl_equal _). + +Inductive Qx_kind (q : Qx) := (* cf Q of Zarith *) + | Qx_INF: (num q = 1)%Z -> (den q = 0)%Z -> Qx_kind q + | Qx_MINF: (num q = -1)%Z -> (den q = 0)%Z -> Qx_kind q + | Qx_UNDEF: (num q = 0)%Z -> (den q = 0)%Z -> Qx_kind q + | Qx_ZERO: (num q = 0)%Z -> forall pq, (den q = Z.pos pq)%Z -> Qx_kind q + | Qx_NZERO: forall nq (s:{num q = Z.pos nq} + {num q = Z.neg nq}) pq, (den q = Z.pos pq)%Z -> Qx_kind q. + +Extraction Implicit Qx_ZERO [pq]. +Extraction Implicit Qx_NZERO [nq s pq]. + +Lemma Qx_classify (q: Qx) : Qx_kind q. +Proof. + intros. + case_eq (den q); [intros Hd | intros pd Hd| intros nd Hd]. + - case_eq (num q); [intros Hn | intros pn Hn| intros nn Hn]. + * exact (Qx_UNDEF q Hn Hd). + * assert (H: num q = ( 1)%Z) by (destruct (Hden2' q Hd) as [H|[H|H]]; rewrite Hn in *; + [discriminate H| discriminate H | assumption ]). + exact (Qx_INF q H Hd). + * assert (H: num q = (-1)%Z) by (destruct (Hden2' q Hd) as [H|[H|H]]; rewrite Hn in *; + [assumption| discriminate H | discriminate H]). + exact (Qx_MINF q H Hd). + - case_eq (num q); [intros Hn | intros nq Hn| intros nq Hn]. + * exact (Qx_ZERO q Hn pd Hd). + * exact (Qx_NZERO q nq (left Hn) pd Hd). + * exact (Qx_NZERO q nq (right Hn) pd Hd). + - assert (A := Hden1 q). + rewrite Hd in A. + discriminate A. +Defined. + +Definition Q2Rx q : Rx := + if (den q =? 0)%Z then + if (num q =? 0)%Z then Real (0%R) + else Inf (num q <? 0)%Z + else Real (Q2R (Qmake (num q) (Z.to_pos (den q)))). \ No newline at end of file diff --git a/farith2/thry/Rextended.v b/farith2/thry/Rextended.v new file mode 100644 index 0000000000000000000000000000000000000000..7444891bdfef9375f531dc9a9e73ede905ffcfa3 --- /dev/null +++ b/farith2/thry/Rextended.v @@ -0,0 +1,676 @@ +(********************************************************* + Extension of R with special values +oo, -oo +**********************************************************) + +From Flocq Require Import IEEE754.BinarySingleNaN. +From Coq Require Import ZArith Psatz Reals. +From F Require Import Utils. + +Set Implicit Arguments. + +(** + Inject BinarySingleNan in R extended with infinities +*) +Section Rextended. + +Variable prec : Z. +Variable emax : Z. +Context (Hprec : FLX.Prec_gt_0 prec). +Context (Hemax : Prec_lt_emax prec emax). + +Definition float := binary_float prec emax. + +(** Reals extended with +oo, -oo *) +Inductive Rx : Type := + | Real : R -> Rx + | Inf : bool -> Rx. + +Definition R_imax : R := Raux.bpow Zaux.radix2 emax. + +Definition R_fmax : R := Raux.bpow Zaux.radix2 emax - Raux.bpow Zaux.radix2 (emax - prec). + +Program Definition F_fmax : float := B754_finite false (Z.to_pos (Zpower 2 prec - 1)%Z) (emax - prec) _. +Next Obligation. + refine (binary_overflow_correct prec emax _ _ mode_ZR false). +Defined. + +Lemma R2F_fmax: + R_fmax = B2R (F_fmax). +Proof. + unfold FLX.Prec_gt_0 in Hprec. + unfold Prec_lt_emax in Hemax. + assert (0 < emax)%Z by lia. + unfold R_fmax, F_fmax, B2R, Defs.F2R; simpl. + destruct prec eqn:E; try easy. + rewrite Z2Pos.id. + - rewrite <- E, minus_IZR. + replace 2%Z with (Zaux.radix_val Zaux.radix2) by auto. + rewrite Raux.IZR_Zpower by lia. + rewrite Rmult_minus_distr_r. + rewrite <- Raux.bpow_plus. + replace (prec + (emax - prec))%Z with emax by lia. + lra. + - assert (1 < 2 ^ (Z.pos p))%Z. + + replace 2%Z with (Zaux.radix_val Zaux.radix2) by auto. + apply Zaux.Zpower_gt_1; lia. + + lia. +Qed. + +Lemma F_fmax_max : + forall (x : float), is_finite x = true -> Bleb x F_fmax = true. +Proof. + intros [ [ ] | [ ] | | [ ] m e Hbound'] Fx; auto. + apply Rle_Bleb; auto. + rewrite <- R2F_fmax. + now apply bounded_le_emax_minus_prec. +Qed. + +Lemma F_fmax_min : + forall (x : float), is_finite x = true -> Bleb (Bopp F_fmax) x = true. +Proof. + intros [ [ ] | [ ] | | [ ] m e Hbound'] Fx; auto. + apply Rle_Bleb; auto. + rewrite pos_Bopp_neg, B2R_Bopp, B2R_Bopp, <- R2F_fmax. + apply Ropp_le_contravar. + now apply bounded_le_emax_minus_prec. +Qed. + +Lemma Rimax_Rfmax : + (R_fmax < R_imax)%R. +Proof. + apply minus_pos_lt, Raux.bpow_gt_0. +Qed. + +Definition leb (x y : Rx) := + match x with + | Inf true => true + | Inf false => + match y with + | Inf s => negb s + | _ => false + end + | Real r1 => + match y with + | Inf b => negb b + | Real r2 => Raux.Rle_bool r1 r2 + end + end. + +Definition fexp := SpecFloat.fexp prec emax. + +Definition do_overflow (m : mode) (x : R) : bool := + let fexp := SpecFloat.fexp prec emax in + let rsum := Generic_fmt.round Zaux.radix2 fexp (round_mode m) x in + Raux.Rle_bool R_imax (Rabs rsum). + +Definition dont_overflow (m : mode) (x : R) : bool := + let fexp := SpecFloat.fexp prec emax in + let rsum := Generic_fmt.round Zaux.radix2 fexp (round_mode m) x in + Raux.Rlt_bool (Rabs rsum) R_imax. + +Lemma do_overflow_false : + forall m r, do_overflow m r = false -> dont_overflow m r = true. +Proof. + intros. unfold do_overflow, dont_overflow in *. + now rewrite <- Raux.negb_Rlt_bool, H. +Qed. + +Lemma do_overflow_true : + forall m r, do_overflow m r = true -> dont_overflow m r = false. +Proof. + intros. unfold do_overflow, dont_overflow in *. + now rewrite <- Raux.negb_Rlt_bool, H. +Qed. + +Lemma dont_overflow_true : + forall m r, dont_overflow m r = true -> do_overflow m r = false. +Proof. + intros. unfold do_overflow, dont_overflow in *. + now rewrite <- Raux.negb_Rle_bool, Bool.negb_false_iff. +Qed. + +Lemma dont_overflow_false : + forall m r, dont_overflow m r = false -> do_overflow m r = true. +Proof. + intros. unfold do_overflow, dont_overflow in *. + now rewrite <- Bool.negb_false_iff, Raux.negb_Rlt_bool. +Qed. + +Lemma F2R_congr : + forall m1 e1 m2 e2, m1 = m2 -> e1 = e2 -> + @Defs.F2R Zaux.radix2 {| Defs.Fnum := m1; Defs.Fexp := e1 |} = + @Defs.F2R Zaux.radix2 {| Defs.Fnum := m2; Defs.Fexp := e2 |}. +Proof. congruence. Qed. + +Definition round (m : mode) (r : Rx) : Rx := + match r with + | Real x => + if do_overflow m x then + if overflow_to_inf m (sign x) then Inf (sign x) + else Real (B2R (if sign x then Bopp F_fmax else F_fmax)) + else + Real (Generic_fmt.round Zaux.radix2 (SpecFloat.fexp prec emax) (round_mode m) x) + | _ => r + end. + +Lemma dont_overflow_inv : + forall m (r : R), + do_overflow m r = false -> + exists (f : float), Generic_fmt.round Zaux.radix2 (SpecFloat.fexp prec emax) (round_mode m) r = B2R f /\ is_finite f = true. +Proof. + intros mode r H. + apply do_overflow_false in H. + unfold dont_overflow in H. + apply Rltb_Rlt in H. + set (e := Generic_fmt.cexp Zaux.radix2 (SpecFloat.fexp prec emax) r). + set (m' := Generic_fmt.scaled_mantissa Zaux.radix2 (SpecFloat.fexp prec emax) r). + set (m := Z.to_pos (round_mode mode m')). + set (s := sign m'). + destruct (Rsign_split r) as [ | [ | ]]. + - admit. + - exists (B754_zero false); split; auto. + rewrite H0, Generic_fmt.round_0; simpl; intuition. + - eexists (B754_finite false m e _); split; auto. + unfold Generic_fmt.round; simpl. + apply F2R_congr; auto. + unfold m, m', SpecFloat.cond_Zopp. +Admitted. + +Lemma R_imax_gt_0: (R_imax > 0)%R. + apply Raux.bpow_gt_0. +Qed. + +Lemma F_fmax_ge_0: (B2R F_fmax >= 0)%R. + simpl. + unfold Defs.F2R; simpl. + apply Rle_ge, Rmult_le_pos. + + apply IZR_le; lia. + + left; apply Raux.bpow_gt_0. +Qed. + +Ltac fformat := + try intuition; try apply fexp_correct. + +Theorem generic_format_Rimax : + Generic_fmt.generic_format Zaux.radix2 fexp R_imax. +Proof. + intros. + red; unfold Defs.F2R, R_imax; simpl. + rewrite <- Generic_fmt.scaled_mantissa_generic. + + unfold Generic_fmt.scaled_mantissa. + rewrite Rmult_assoc, Rmult_comm. + rewrite <- Raux.bpow_plus. + rewrite (Zplus_comm)%R. + rewrite Zegal_left by lia; simpl; lra. + + apply (Generic_fmt.generic_format_bpow Zaux.radix2 fexp emax). + unfold fexp, SpecFloat.fexp, SpecFloat.emin. + unfold FLX.Prec_gt_0 in *. + unfold Prec_lt_emax in *. + lia. +Qed. + +Theorem round_Rimax : + forall m, Generic_fmt.round Zaux.radix2 fexp (round_mode m) R_imax = R_imax. +Proof. + intros. + apply Generic_fmt.round_generic; intuition. + apply generic_format_Rimax. +Qed. + +Lemma Rltb_lt : + forall x y, Raux.Rlt_bool x y = true -> (x < y)%R. +Proof. + intros. + pose proof (Hp := Raux.Rlt_bool_spec x y). + rewrite H in Hp. + now inversion Hp. +Qed. + +Lemma Rimax_float : + exists m e, R_imax = Defs.F2R (Defs.Float Zaux.radix2 m e). +Proof. + exists 1%Z. + unfold R_imax, Defs.F2R; simpl. + eexists. + symmetry. + apply Rmult_1_l. +Qed. + +Lemma incr_R_fmax_R_imax : + @Defs.F2R Zaux.radix2 {| Defs.Fnum := (Zpower 2 prec - 1 + 1)%Z ; Defs.Fexp := (emax - prec) |} = R_imax. +Proof. + unfold Defs.F2R, R_imax; simpl. + replace (2 ^ prec - 1 + 1)%Z with (2 ^ prec)%Z by lia. + rewrite (Raux.IZR_Zpower Zaux.radix2). + + rewrite <- Raux.bpow_plus. + replace (prec + (emax - prec))%Z with (emax) by lia. + reflexivity. + + unfold FLX.Prec_gt_0 in Hprec. + unfold Prec_lt_emax in Hemax. + lia. +Qed. + +Theorem do_overflow_iff: + forall m x, + let fexp := SpecFloat.fexp prec emax in + let rx := Generic_fmt.round Zaux.radix2 fexp (round_mode m) x in + do_overflow m x = true <-> (Raux.Rle_bool R_imax rx = true \/ Raux.Rle_bool rx (-R_imax)%R = true). +Proof. + intros; split; intros. + - unfold do_overflow in H. + unfold Rabs in H. + destruct Rcase_abs. + + apply Rleb_Rle in H. + right. apply Raux.Rle_bool_true. + apply Ropp_le_contravar in H. + replace (rx) with (--rx)%R by lra. + subst rx; auto. + + apply Rleb_Rle in H. + left. apply Raux.Rle_bool_true. + auto. + - destruct H; apply Raux.Rle_bool_true; apply Rleb_Rle in H. + + eauto using Rle_trans, H, Rle_abs. + + apply Ropp_le_contravar in H. + replace (--R_imax)%R with R_imax in H by lra. + pose proof R_imax_gt_0. + assert (0 <= -rx)%R by lra. + assert (0 > rx)%R by lra. + assert (-rx > rx)%R by lra. + assert (Rabs rx = - rx)%R by auto using Rabs_left. + rewrite <- H4 in H. + auto. +Qed. + +Lemma overflow_is_le : + forall m r1 r2, + (r1 <= r2)%R -> + (0 <= r1)%R -> + do_overflow m r1 = true -> + do_overflow m r2 = true. +Proof. + intros m r1 r2 Hle Hr1 Ho. + rewrite do_overflow_iff in Ho. destruct Ho as [H | H]. + - apply Rleb_Rle in H. + rewrite do_overflow_iff. left. + apply Raux.Rle_bool_true. + eapply Generic_fmt.round_le in Hle. + + eapply Rle_trans; [apply H | apply Hle]. + + now apply fexp_correct. + + intuition. + - apply Rleb_Rle in H. + assert (-R_imax < 0)%R. + { assert (R_imax > 0)%R by apply R_imax_gt_0. lra. } + pose proof H0. + apply Rlt_le in H1. + eapply Generic_fmt.round_le in Hr1. + + erewrite Generic_fmt.round_0 in Hr1. + assert (0 < 0)%R. + eapply Rle_lt_trans. + apply Hr1. + eapply Rle_lt_trans. + apply H. + apply H0. + lra. + intuition. + + now apply fexp_correct. + + intuition. +Qed. + +Lemma overflow_is_ge : + forall m r1 r2, + (r1 <= r2)%R -> + (r2 <= 0)%R -> + do_overflow m r2 = true -> + do_overflow m r1 = true. +Proof. + intros m r1 r2 Hle Hr1 Ho. + rewrite do_overflow_iff in Ho. destruct Ho as [H | H]. + - apply Rleb_Rle in H. + rewrite <- (round_Rimax m) in H. + eapply (Generic_fmt.round_le Zaux.radix2 fexp (round_mode m)) in Hr1; intuition. + rewrite Generic_fmt.round_0 in Hr1. + assert (Generic_fmt.round Zaux.radix2 fexp (round_mode m) R_imax <= 0)%R. + + eapply Rle_trans. + * apply H. + * apply Hr1. + + pose proof R_imax_gt_0. + rewrite (round_Rimax m) in H0. + lra. + + intuition. + - apply Rleb_Rle in H. + rewrite do_overflow_iff. right. + apply Raux.Rle_bool_true. + apply (Generic_fmt.round_le Zaux.radix2 fexp (round_mode m)) in Hle. + eapply Rle_trans. + + apply Hle. + + apply H. +Qed. + +Lemma round_0: + forall m, + Real 0 = round m (Real 0). +Proof. + intros m. + unfold round. + assert (H: do_overflow m 0 = false). + { unfold do_overflow, R_imax. + rewrite Generic_fmt.round_0 by fformat. + rewrite Rabs_R0. + apply Raux.Rle_bool_false. + apply Raux.bpow_gt_0. + } + rewrite H. + now rewrite Generic_fmt.round_0 by fformat. +Qed. + +Theorem round_le: + forall (m : mode) (r1 r2 : Rx), leb r1 r2 = true -> leb (round m r1) (round m r2) = true. +Proof. + intros m [ r1 | [] ] [r2 | []] H; try easy. + Ltac fbounded := + match goal with + | [ Ho1 : do_overflow _ _ = false |- _ ] => + apply Raux.Rle_bool_true; + destruct (dont_overflow_inv _ _ Ho1) as (f & [?Hreq ?Hf]); + rewrite ?Hreq; first [now apply Bleb_Rle, F_fmax_min | now apply Bleb_Rle, F_fmax_max ] + end. + Ltac freals := + match goal with + | [ H : Raux.Rle_bool _ _ = true |- _ ] => + apply Raux.Rle_bool_true; apply Rleb_Rle in H; + now apply Generic_fmt.round_le; fformat + end. + Ltac finfinites := + simpl; now destruct overflow_to_inf eqn:?, do_overflow eqn:?, sign eqn:?. + Ltac absurd_sign := + match goal with + | [ Hs2 : sign _ = true, Hs1 : sign _ = false, H : Raux.Rle_bool _ _ = true |- _ ] => + now rewrite (pos_Rleb_neg _ _ Hs1 Hs2) in H + end. + Ltac absurd_mode := + match goal with + | [ m : mode |- _] => now destruct m + end. + Ltac absurd_overflow := + match goal with + | [ H : Raux.Rle_bool _ _ = true, + Hs : sign _ = false, + Ho1 : do_overflow _ _ = true, + Ho2 : do_overflow _ _ = false + |- _ + ] => apply Rleb_Rle in H; now rewrite (overflow_is_le _ H (sign_pos_inv _ Hs) Ho1) in Ho2 + | [ H : Raux.Rle_bool _ _ = true, + Hs : sign _ = true, + Ho1 : do_overflow _ _ = false, + Ho2 : do_overflow _ _ = true + |- _ + ] => apply Rleb_Rle in H; now rewrite (overflow_is_ge _ H (sign_neg_inv _ Hs) Ho2) in Ho1 + | [ H : Raux.Rle_bool _ _ = false, + Hs : sign _ = true, + Ho1 : do_overflow _ _ = true, + Ho2 : do_overflow _ _ = false + |- _ + ] => apply Rleb_Rle in H; now rewrite (overflow_is_ge _ H (sign_neg_inv _ Hs) Ho2) in Ho1 + | [ H1 : overflow_to_inf _ _ = true, H2 : overflow_to_inf _ _ = false |- _ ] => + now rewrite H1 in H2 + end. + Ltac absurd_case := + match goal with + | [r1 : R, r2 : R |- _ ] => + try absurd_mode; try absurd_sign; absurd_overflow + end. + Ltac sign_analysis := + match goal with + | [r1 : R, r2 : R |- _ ] => + destruct (sign r1) eqn:Hs1, (sign r2) eqn:Hs2; auto + end. + - simpl in H. unfold round. + destruct (do_overflow m r1) eqn:Ho1; + destruct (do_overflow m r2) eqn:Ho2; + destruct (overflow_to_inf m (sign r1)) eqn:Hi1; + destruct (overflow_to_inf m (sign r2)) eqn:Hi2; + (try freals); sign_analysis; try absurd_case; try fbounded ; simpl. + + unfold Raux.Rle_bool. + destruct Raux.Rcompare eqn:E; try easy. + apply Raux.Rcompare_Gt_inv in E; lra. + + unfold Raux.Rle_bool. + destruct Raux.Rcompare eqn:E; try easy. + apply Raux.Rcompare_Gt_inv in E. + unfold Defs.F2R in E; simpl in E. + apply Rmult_lt_reg_r in E. + * apply lt_IZR in E; lia. + * apply Raux.bpow_gt_0. + + unfold Raux.Rle_bool. + destruct Raux.Rcompare eqn:E; try easy. + apply Raux.Rcompare_Gt_inv in E; lra. + (* + apply Raux.Rle_bool_true. + apply do_overflow_false in Ho2. + unfold dont_overflow in Ho2. + apply Rltb_Rlt in Ho2. + apply Raux.Rabs_lt_inv in Ho2. + destruct Ho2 as [Ho2 Ho2']. + Search () + assert (- R_imax) + assert (R_imax < (Generic_fmt.round Zaux.radix2 (SpecFloat.fexp prec emax) + (round_mode m) r2))%R. + + unfold R_imax in Ho2. + + destruct (dont_overflow_inv _ _ Ho2) as (f & [?Hreq ?Hf]). + unfold Generic_fmt.round, Defs.F2R; simpl. + Raux.bpow_simplify. + unfold FLX.Prec_gt_0 in Hprec. + unfold Prec_lt_emax in Hemax. + rewrite <- Raux.IZR_Zpower by lia. + rewrite <- mult_IZR. + rewrite <- Raux.IZR_Zpower. + unfold Generic_fmt.cexp. + rewrite <- mult_IZR. + apply IZR_le. + rewrite Hreq. + unfold Generic_fmt.round. apply F2R_congr. *) + - finfinites. +Qed. + +Lemma round_inf : + forall m b, round m (Inf b) = Inf b. +Proof. reflexivity. Qed. + + +Example leb_infp_true : + forall x, leb x (Inf false) = true. +Proof. now induction x as [ | [ ] ]. Qed. + +Example leb_infm_true : + forall x, leb (Inf true) x = true. +Proof. now induction x as [ | [ ] ]. Qed. + +Example leb_real : + forall r1 r2, leb (Real r1) (Real r2) = Raux.Rle_bool r1 r2. +Proof. reflexivity. Qed. + +Example leb_refl : + forall x, leb x x = true. +Proof. + induction x as [ | [ ] ]; auto. + apply Raux.Rle_bool_true; lra. +Qed. + +Definition add (x y : Rx) : Rx := + match x with + | Inf true => x + | Inf false => + match y with + | Inf true => Inf true + | _ => x + end + | Real r => + match y with + | Inf _ => y + | Real r' => Real (r + r')%R + end + end. + +Lemma leb_trans : + forall x y z : Rx, leb x y = true -> leb y z = true -> leb x z = true. +Proof. + intros [ rx | [ ] ] [ ry | [ ] ] [ rz | [ ] ] Hxy Hyz; simpl in *; try easy. + apply Rleb_Rle in Hxy. + apply Rleb_Rle in Hyz. + apply Raux.Rle_bool_true. + lra. +Qed. + +Lemma add_leb_mono_l : + forall x y z : Rx, + leb x y = true -> leb (add x z) (add y z) = true. +Proof. + intros [ ] [ ] [ ] H. + - simpl in *. + apply Rleb_Rle in H. + apply Raux.Rle_bool_true. + lra. + - now destruct b. + - now destruct b. + - now destruct b, b0. + - now destruct b. + - now destruct b, b0. + - now destruct b, b0. + - now destruct b, b0, b1. +Qed. + +Lemma add_leb_mono_r : + forall x y z : Rx, + leb x y = true -> leb (add z x) (add z y) = true. +Proof. + intros [ | [ ]] [ | [ ]] [ | [ ]] H; try easy. + simpl in *. + apply Rleb_Rle in H. + apply Raux.Rle_bool_true. + lra. +Qed. + +Lemma add_real : + forall (r1 r2 : R), add (Real r1) (Real r2) = Real (r1 + r2)%R. +Proof. reflexivity. Qed. + +Lemma add_0_l: + forall r : Rx, add (Real 0) r = r. +Proof. destruct r; simpl; intuition. Qed. + +Lemma add_0_r: + forall r : Rx, add r (Real 0) = r. +Proof. destruct r; try destruct b; simpl; intuition. Qed. + +Definition B2Rx (x : float) := + match x with + | B754_infinity b => Inf b + | _ => Real (B2R x) + end. + + +Lemma B2Rx_finite : + forall (f : float), + is_finite f = true -> B2Rx f = Real (B2R f). +Proof. now destruct f. Qed. + +Lemma bounded_dont_overflow : + forall mode s m e (H : SpecFloat.bounded prec emax m e = true), + dont_overflow mode (B2R (B754_finite s m e H)) = true. +Proof. + intros. + unfold dont_overflow. + apply Raux.Rlt_bool_true. + apply Raux.Rabs_lt; split. + + rewrite Generic_fmt.round_generic by (intuition; apply generic_format_B2R). + rewrite <- Ropp_involutive. + apply Ropp_lt_contravar. + rewrite <- B2R_Bopp; simpl (Bopp _). + apply (Rle_lt_trans _ R_fmax). + - rewrite R2F_fmax. auto using Bleb_Rle, F_fmax_max. + - apply Rimax_Rfmax. + + rewrite Generic_fmt.round_generic by (intuition; apply generic_format_B2R). + apply (Rle_lt_trans _ R_fmax). + - rewrite R2F_fmax. auto using Bleb_Rle, F_fmax_max. + - apply Rimax_Rfmax. +Qed. + +Lemma round_id : + forall m (f : float), + B2Rx f = round m (B2Rx f). +Proof. + intros m; destruct f as [ [ ] | [ ] | | ]; try easy. + + simpl (B2Rx _); apply round_0. + + simpl (B2Rx _); apply round_0. + + simpl (B2Rx _); apply round_0. + + unfold B2Rx, round. + rewrite (dont_overflow_true _ _ (bounded_dont_overflow m s m0 e e0)). + now rewrite Generic_fmt.round_generic by (intuition; apply generic_format_B2R). +Qed. + +Lemma B2Rx_le : + forall (x y : float), + is_nan x = false -> + is_nan y = false -> + leb (B2Rx x) (B2Rx y) = true -> + Bleb x y = true. +Proof. + intros. + destruct x as [[ ] | [ ] | | ] eqn:E1; destruct y as [ [ ] | [ ] | | ] eqn:E2; try easy; + rewrite <- E1, <- E2 in *; + rewrite B2Rx_finite in H1 by (rewrite E1; auto); + rewrite B2Rx_finite in H1 by (rewrite E2; auto); + unfold leb in H1; + unfold Bleb, SpecFloat.SFleb; + replace (SpecFloat.SFcompare (B2SF x) (B2SF y)) with (Bcompare x y) by auto; + assert (Fx: is_finite x = true) by (rewrite E1; auto); + assert (Fy: is_finite y = true) by (rewrite E2; auto); + rewrite (Bcompare_correct _ _ x y Fx Fy); + destruct Raux.Rcompare eqn:E; auto; + apply Raux.Rcompare_Gt_inv in E; + destruct (Raux.Rle_bool_spec (B2R x) (B2R y)); auto; lra. +Qed. + +Ltac fdestruct f := + destruct f as [ [ ] | [ ] | | ] eqn:?E; try easy. + +Lemma B2Rx_B2R : + forall (x : float), + is_finite x = true -> + B2Rx x = Real (B2R x). +Proof. now intros [ ] Fx. Qed. + +Lemma le_B2Rx : + forall (x y : float), + Bleb x y = true -> + leb (B2Rx x) (B2Rx y) = true. +Proof. + Ltac by_comparison := + match goal with + | [ x : _, y : _, E : _, E0 : _, H : _ |- _ ] => + rewrite <- E, <- E0 in H; + unfold Bleb, SpecFloat.SFleb in H; + replace (SpecFloat.SFcompare (B2SF _) (B2SF _)) with (Bcompare x y) in H by auto; + rewrite E, E0 in *; + rewrite Bcompare_correct in H by auto; + rewrite B2Rx_B2R by auto; + rewrite B2Rx_B2R, leb_real by auto; + destruct (Raux.Rcompare _) eqn:Cmp in H; try easy; + [ apply Raux.Rcompare_Eq_inv in Cmp | apply Raux.Rcompare_Lt_inv in Cmp ]; + apply Raux.Rle_bool_true; lra + end. + Ltac by_computation := + simpl; apply Raux.Rle_bool_true; lra. + intros. + fdestruct x; fdestruct y; try by_computation; by_comparison. +Qed. + +End Rextended. + +Arguments round {prec} {emax} {Hprec} {Hemax}. +Arguments round_le {prec} {emax} {Hprec} {Hemax}. +Arguments B2Rx {prec} {emax}. +Arguments B2Rx_le {prec} {emax}. +Arguments le_B2Rx {prec} {emax}. +Arguments B2Rx_B2R {prec} {emax}. +Arguments B2Rx_finite {prec} {emax}. diff --git a/farith2/thry/Tactics.v b/farith2/thry/Tactics.v new file mode 100644 index 0000000000000000000000000000000000000000..6a95779372fa1e22c3eed41a0383170da8068328 --- /dev/null +++ b/farith2/thry/Tactics.v @@ -0,0 +1,2 @@ +From Flocq Require Import IEEE754.BinarySingleNaN. +From Coq Require Import QArith Psatz Reals. diff --git a/farith2/thry/Utils.v b/farith2/thry/Utils.v new file mode 100644 index 0000000000000000000000000000000000000000..91aacfaee541db10fbfdc9ead83e73897b324513 --- /dev/null +++ b/farith2/thry/Utils.v @@ -0,0 +1,705 @@ +From Flocq Require Import IEEE754.BinarySingleNaN. +From Coq Require Import ZArith Lia Reals Psatz Bool. +(* From F Require Import Rextended. *) + +(** + Usefull facts & definitions about R +*) +Section Rutils. + +Definition sign (r : R) := + Raux.Rlt_bool r 0. + +Lemma sign_pos_inv : + forall r, sign r = false -> (0 <= r)%R. +Proof. + intros. + unfold sign in H. + now destruct (Raux.Rlt_bool_spec r 0). +Qed. + +Lemma sign_neg_inv : + forall r, sign r = true -> (r <= 0)%R. +Proof. + intros. + unfold sign in H. left. + now destruct (Raux.Rlt_bool_spec r 0). +Qed. + +Lemma sign_neg_inv_strict: + forall r, sign r = true -> (r < 0)%R. +Proof. + intros. + unfold sign in H. + now destruct (Raux.Rlt_bool_spec r 0). +Qed. + +Lemma minus_pos_lt : + forall r1 r2, (0 < r2)%R -> (r1 - r2 < r1)%R. +Proof. + intros; lra. +Qed. + +Lemma IZR_neg : + (forall x, IZR (Z.neg x) < 0)%R. +Proof. + induction x; try lra; + apply (Rgt_trans _ (IZR (Z.neg x))); auto; + apply IZR_lt; lia. +Qed. + +Lemma IZR_pos : + (forall x, IZR (Z.pos x) > 0)%R. +Proof. + induction x; try lra; + apply (Rgt_trans _ (IZR (Z.pos x))); auto; + apply IZR_lt; lia. +Qed. + +Lemma pos_Rleb_neg : + forall r1 r2, + sign r1 = false -> + sign r2 = true -> + Raux.Rle_bool r1 r2 = false. +Proof. + intros. unfold sign in *. + destruct (Raux.Rlt_bool_spec r1 0); try easy. + destruct (Raux.Rlt_bool_spec r2 0); try easy. + apply Raux.Rle_bool_false; lra. +Qed. + +Lemma Rleb_Rle : + forall r1 r2, Raux.Rle_bool r1 r2 = true -> (r1 <= r2)%R. +Proof. + intros. + now destruct (Raux.Rle_bool_spec r1 r2). +Qed. + +Lemma Reqb_Req : + forall r1 r2, Raux.Req_bool r1 r2 = true -> (r1 = r2)%R. +Proof. + intros. + now destruct (Raux.Req_bool_spec r1 r2). +Qed. + +Lemma Rltb_Rlt : + forall r1 r2, Raux.Rlt_bool r1 r2 = true -> (r1 < r2)%R. +Proof. + intros. + now destruct (Raux.Rlt_bool_spec r1 r2). +Qed. + +Lemma Rsign_split : + forall (r : R), (r < 0 \/ r = 0 \/ r > 0)%R. +Proof. + intros. lra. +Qed. + +End Rutils. + +(********************************************************* + Simple & usefull results on floats +**********************************************************) + +#[global] Notation "x <= y" := (Bleb x y = true). +#[global] Notation "x <= y <= z" := (Bleb x y = true /\ Bleb y z = true). +#[global] Notation "'+oo'" := (B754_infinity false). +#[global] Notation "'-oo'" := (B754_infinity true). +#[global] Notation "'NaN'" := (B754_nan). + +Ltac fdestruct f := + destruct f as [ [ ] | [ ] | | ]; try easy. + +Section Utils. + +Variable prec : Z. +Variable emax : Z. +Context (Hprec : FLX.Prec_gt_0 prec). +Context (Hemax : Prec_lt_emax prec emax). + +Definition float := binary_float prec emax. + +Definition is_inf (x : float) := + match x with + | B754_infinity _ => true + | _ => false + end. + +Definition is_infp (x : float) := + match x with + | B754_infinity s => negb s + | _ => false + end. + +Definition is_infm (x : float) := + match x with + | B754_infinity s => s + | _ => false + end. + +Lemma le_not_nan : + forall x y : float, Bleb x y = true -> is_nan x = false /\ is_nan y = false. +Proof. now intros [ ] [ ]. Qed. + +Lemma le_not_nan_l : + forall x y : float, Bleb x y = true -> is_nan x = false. +Proof. + intros. + exact (proj1 (le_not_nan x y H)). +Qed. + +Lemma le_not_nan_r : + forall x y : float, Bleb x y = true -> is_nan y = false. +Proof. + intros. + exact (proj2 (le_not_nan x y H)). +Qed. + +Lemma infm_min : + forall (x : float), is_nan x = false -> -oo <= x. +Proof. fdestruct x. Qed. + +Lemma infp_max : + forall (x : float), is_nan x = false -> x <= +oo. +Proof. fdestruct x. Qed. + +Lemma infp_le_is_infp : + forall x : float, +oo <= x -> x = +oo. +Proof. + now intros [ [ ] | [ ] | | ] H. +Qed. + +Lemma le_infm_is_infm : + forall x : float, x <= -oo -> x = -oo. +Proof. + now intros [ [ ] | [ ] | | ] H. +Qed. + +Lemma is_infm_inv: + forall x : float, is_infm x = true -> x = -oo. +Proof. now intros [ [ ] | [ ] | | ]. Qed. + +Lemma is_infp_inv: + forall x : float, is_infp x = true -> x = +oo. +Proof. now intros [ [ ] | [ ] | | ]. Qed. + +Lemma is_nan_inv: + forall x : float, is_nan x = true -> x = NaN. +Proof. now intros [ ]. Qed. + +Lemma le_infp_finite: + forall x : float, is_finite x = true -> +oo <= x -> False. +Proof. now intros [ ]. Qed. + +Lemma le_infm_finite: + forall x : float, is_finite x = true -> x <= -oo -> False. +Proof. now intros [ ]. Qed. + +Lemma Bplus_finites_not_nan : + forall m (x y : float), + is_finite x = true -> + is_finite y = true -> + is_nan (Bplus m x y) = false. +Proof. + intros m [[ ] | [ ] | | ] [ [ ] | [ ] | | ] Fx Fy; try easy. + - now destruct m. + - now destruct m. + - unfold Bplus. + auto using (is_nan_binary_normalize prec emax). +Qed. + +Lemma Bplus_nan_inv : + forall (m : mode) (x y:float), is_nan (Bplus m x y) = true -> + x = +oo /\ y = -oo \/ x = -oo /\ y = +oo \/ x = NaN \/ y = NaN. +Proof. + intros; fdestruct x; fdestruct y; auto. + - now destruct m. + - now destruct m. + - now rewrite Bplus_finites_not_nan in H. +Qed. + +Lemma Bplus_not_nan_inv : + forall (m : mode) (x y:float), is_nan (Bplus m x y) = false -> + ~(x = +oo /\ y = -oo) /\ ~(x = -oo /\ y = +oo) /\ (is_nan x = false) /\ (is_nan y = false). +Proof. + intros; repeat split; fdestruct x; fdestruct y. +Qed. + +(* Lemma Bplus_nan_if : + forall m (x y : float), + is_nan x = false -> + is_nan y = false -> + is_nan (Bplus m x y) = true -> + (x = +oo /\ y = -oo) \/ (x = -oo /\ y = +oo). +Proof. + intros. + fdestruct x; fdestruct y; try now destruct m; intuition. + assert (is_nan (Bplus m (B754_finite s m0 e e0) (B754_finite s0 m1 e1 e2)) = false) by auto using Bplus_finites_not_nan. + rewrite H1 in H2; discriminate. +Qed. *) + +Lemma Bplus_zero : + forall m b (x : float), + B2R (Bplus m (B754_zero b) x) = B2R x. +Proof. + intros ? [ ] [ [ ] | [ ] | | ]; try easy. + - simpl; destruct m; reflexivity. + - simpl; destruct m; reflexivity. +Qed. + +Lemma pos_Bopp_neg : + forall m e Hb, @B754_finite prec emax true m e Hb = Bopp (B754_finite false m e Hb). +Proof. reflexivity. Qed. + +Lemma neg_Bopp_pos : + forall m e Hb, @B754_finite prec emax false m e Hb = Bopp (B754_finite true m e Hb). +Proof. reflexivity. Qed. + +Lemma Rle_Bleb : + forall (x y : float), + is_finite x = true -> + is_finite y = true -> + (B2R x <= B2R y)%R -> + Bleb x y = true. +Proof. + intros x y Fx Fy Hxy. + unfold Bleb, SpecFloat.SFleb. + replace (SpecFloat.SFcompare (_ x) (_ y)) with (Bcompare x y) by auto. + rewrite (Bcompare_correct _ _ x y Fx Fy). + destruct Raux.Rcompare eqn:E; try easy. + apply Raux.Rcompare_Gt_inv in E; lra. +Qed. + +Lemma Rlt_Bltb : + forall (x y : float), + is_finite x = true -> + is_finite y = true -> + (B2R x < B2R y)%R -> + Bltb x y = true. +Proof. + intros x y Fx Fy Hxy. + unfold Bltb, SpecFloat.SFltb. + replace (SpecFloat.SFcompare (_ x) (_ y)) with (Bcompare x y) by auto. + rewrite (Bcompare_correct _ _ x y Fx Fy). + destruct Raux.Rcompare eqn:E; auto. + - apply Raux.Rcompare_Eq_inv in E; lra. + - apply Raux.Rcompare_Gt_inv in E; lra. +Qed. + +Lemma Bleb_Rle : + forall x y : float, is_finite x = true -> is_finite y = true -> + Bleb x y = true -> (B2R x <= B2R y)%R. +Proof. + intros x y Fx Fy H. + unfold Bleb, SpecFloat.SFleb in H. + replace (SpecFloat.SFcompare (_ x) (_ y)) with (Bcompare x y) in H by auto. + rewrite (Bcompare_correct _ _ x y Fx Fy) in H. + destruct (Raux.Rcompare) eqn:E in H; try easy. + + apply Raux.Rcompare_Eq_inv in E; lra. + + apply Raux.Rcompare_Lt_inv in E; lra. +Qed. + +Lemma Bltb_Rlt : + forall x y : float, is_finite x = true -> is_finite y = true -> + Bltb x y = true -> (B2R x < B2R y)%R. +Proof. + intros x y Fx Fy H. + unfold Bltb, SpecFloat.SFltb in H. + replace (SpecFloat.SFcompare (_ x) (_ y)) with (Bcompare x y) in H by auto. + rewrite (Bcompare_correct _ _ x y Fx Fy) in H. + destruct (Raux.Rcompare) eqn:E in H; try easy. + apply Raux.Rcompare_Lt_inv in E; lra. +Qed. + +Lemma Bleb_trans : + forall (x y z : float), x <= y -> y <= z -> x <= z. +Proof. + intros x y z Hxy Hyz. + fdestruct x; fdestruct y; fdestruct z; + apply Rle_Bleb; auto; + apply Bleb_Rle in Hxy; auto; + apply Bleb_Rle in Hyz; auto; + lra. +Qed. + +Lemma Bltb_trans : + forall (x y z : float), Bltb x y = true -> Bltb y z = true -> Bltb x z = true. +Proof. + intros x y z Hxy Hyz. + fdestruct x; fdestruct y; fdestruct z; + apply Rlt_Bltb; auto; + apply Bltb_Rlt in Hxy; auto; + apply Bltb_Rlt in Hyz; auto; + lra. +Qed. + +Lemma Bltb_Bleb_trans : + forall x y z : float, Bltb x y = true -> y <= z -> Bltb x z = true. +Proof. + intros x y z Hxy Hyz. + fdestruct x; fdestruct y; fdestruct z; + apply Rlt_Bltb; auto; + apply Bltb_Rlt in Hxy; auto; + apply Bleb_Rle in Hyz; auto; + lra. +Qed. + +Lemma Bleb_Bltb_trans : + forall x y z : float, Bleb x y = true -> Bltb y z = true -> Bltb x z = true. +Proof. + intros x y z Hxy Hyz. + fdestruct x; fdestruct y; fdestruct z; + apply Rlt_Bltb; auto; + apply Bleb_Rle in Hxy; auto; + apply Bltb_Rlt in Hyz; auto; + lra. +Qed. + +Lemma Beqb_refl : + forall x : float, is_nan x = false -> Beqb x x = true. +Proof. + intros; fdestruct x. + unfold Beqb; cbn. + destruct s; + rewrite (Zaux.Zcompare_Eq e e) by reflexivity; + now rewrite (Pcompare_refl m). +Qed. + +Lemma Beqb_nan_l : + forall (x : float), Beqb NaN x = false. +Proof. fdestruct x. Qed. + +Lemma Beqb_nan_r : + forall (x : float), Beqb x NaN = false. +Proof. fdestruct x. Qed. + +Lemma Beqb_Bleb : + forall x y : float, Beqb x y = true -> Bleb x y = true. +Proof. + intros x y Hxy. + fdestruct x; fdestruct y; rewrite Beqb_correct in Hxy; auto; + apply Rle_Bleb; auto; right; + now apply Reqb_Req in Hxy. +Qed. + + +Lemma Bleb_refl : + forall x:float, is_nan x = false -> Bleb x x = true. +Proof. + intros x Hx; fdestruct x. + apply Rle_Bleb; auto; lra. +Qed. + +Lemma Bltb_Bleb : + forall x y : float, Bltb x y = true -> Bleb x y = true. +Proof. + intros x y Hxy. + fdestruct x; fdestruct y; + apply Rle_Bleb; auto; + apply Bltb_Rlt in Hxy; auto; + lra. +Qed. + +Axiom proof_irr : + forall m e (H H' : SpecFloat.bounded prec emax m e = true), H = H'. + +Lemma Bleb_antisymm_strict : + forall x y : float, x <= y <= x -> Beqb x (B754_zero true) = false -> x = y. +Proof. + intros x y [H1 H2]. + fdestruct x; fdestruct y; + try (destruct s; try easy); + try (destruct s0; try easy). + - intros _. + cbn in H1, H2. + destruct (e ?= e1)%Z eqn:E1; rewrite (Z.compare_antisym _ _), E1 in H2; simpl in H2; try discriminate. + rewrite <- ZC4 in H1. + destruct (Pos.compare_cont Eq m0 m) eqn:E2; try easy. + apply (Pcompare_Eq_eq _ _) in E2; subst. + apply (Z.compare_eq) in E1; subst; cbn. + rewrite (proof_irr _ _ e0 e2). + reflexivity. + - intros _. + cbn in H1, H2. + rewrite ZC4 in H2. + destruct (e1 ?= e)%Z eqn:E1; rewrite (Z.compare_antisym _ _), E1 in H1; simpl in H2; try discriminate. + destruct (Pos.compare_cont Eq m m0) eqn:E2; try easy. + + apply (Pcompare_Eq_eq _ _) in E2; subst. + apply (Z.compare_eq) in E1; subst; cbn. + rewrite (proof_irr _ _ e0 e2). + reflexivity. +Qed. + + +Lemma Bleb_antisymm : + forall x y : float, x <= y <= x -> Beqb x y = true. +Proof. + intros x y [H1 H2]. + fdestruct x; fdestruct y; + try (destruct s; try easy); + try (destruct s0; try easy). + - cbn in H1, H2. + destruct (e ?= e1)%Z eqn:E1; rewrite (Z.compare_antisym _ _), E1 in H2; simpl in H2; try discriminate. + rewrite <- ZC4 in H1. + destruct (Pos.compare_cont Eq m0 m) eqn:E2; try easy. + apply (Pcompare_Eq_eq _ _) in E2; subst. + apply (Z.compare_eq) in E1; subst; cbn. + now rewrite Z.compare_refl, Pcompare_refl. + - cbn in H1, H2. + destruct (e ?= e1)%Z eqn:E1; rewrite (Z.compare_antisym _ _), E1 in H2; simpl in H2; try discriminate. + destruct (Pos.compare_cont Eq m m0) eqn:E2; try easy. + + apply (Pcompare_Eq_eq) in E2; subst. + apply (Z.compare_eq) in E1; subst; cbn. + now rewrite Z.compare_refl, Pcompare_refl. + + destruct (Pos.compare_cont Eq m0 m) eqn:E3; try easy. + * apply Pos.compare_nge_iff in E2. + apply Pos.compare_eq_iff in E3. + intuition. + * apply Pos.compare_nge_iff in E2. + apply Pos.compare_nge_iff in E3. + intuition. +Qed. + +Lemma Beqb_symm : + forall x y : float, Beqb x y = true -> Beqb y x = true. +Proof. + intros x y Hxy. + fdestruct x; fdestruct y; unfold Beqb in Hxy; simpl in *; try (now destruct s). + unfold SpecFloat.SFeqb in Hxy; simpl in *. + destruct s, s0; auto. + * rewrite <- ZC4 in Hxy. + destruct (e ?= e1)%Z eqn:E1, (Pos.compare_cont Eq m0 m) eqn:E2; simpl in *; try discriminate. + rewrite Z.compare_eq_iff in E1; subst. + apply Pcompare_Eq_eq in E2; subst. + rewrite Beqb_correct; auto; simpl. + unfold Raux.Req_bool. + rewrite Raux.Rcompare_Eq; reflexivity. + * destruct (e ?= e1)%Z eqn:E1, (Pos.compare_cont Eq m m0) eqn:E2; simpl in *; try discriminate. + rewrite Z.compare_eq_iff in E1; subst. + apply Pcompare_Eq_eq in E2; subst. + rewrite Beqb_correct; auto; simpl. + unfold Raux.Req_bool. + rewrite Raux.Rcompare_Eq; reflexivity. +Qed. + +Lemma Beqb_trans : + forall x y z : float, Beqb x y = true -> Beqb y z = true -> Beqb x z = true. +Proof. + intros x y z H1 H2. + apply Bleb_antisymm; split. + - apply (Bleb_trans _ _ _ (Beqb_Bleb _ _ H1) (Beqb_Bleb _ _ H2)). + - apply (Bleb_trans _ _ _ (Beqb_Bleb _ _ (Beqb_symm _ _ H2)) (Beqb_Bleb _ _ (Beqb_symm _ _ H1))). +Qed. + +Lemma Bleb_false_Bltb : + forall x y:float, is_nan x = false -> is_nan y = false -> Bleb x y = false -> Bltb y x = true. +Proof. + intros x y Hx Hy Hxy. + destruct x as [ | [ ] | | ] eqn:Ex, y as [ | [ ] | | ] eqn:Ey; try easy; rewrite <- Ex, <- Ey in *; + unfold Bleb, SpecFloat.SFleb in Hxy; + replace (SpecFloat.SFcompare (B2SF _) (B2SF _)) with (Bcompare x y) in Hxy by auto; + assert (Fx: is_finite x = true) by (rewrite Ex; auto); + assert (Fy: is_finite y = true) by (rewrite Ey; auto); + rewrite (Bcompare_correct _ _ x y Fx Fy) in Hxy; auto; + destruct (Raux.Rcompare _ _) eqn:E; try easy; + apply Raux.Rcompare_Gt_inv in E; + apply Rlt_Bltb; auto. +Qed. + +Lemma Bltb_false_Bleb : + forall x y:float, is_nan x = false -> is_nan y = false -> Bltb x y = false -> Bleb y x = true. +Proof. + intros x y Hx Hy Hxy. + destruct x as [ | [ ] | | ] eqn:Ex, y as [ | [ ] | | ] eqn:Ey; try easy; rewrite <- Ex, <- Ey in *; + unfold Bltb, SpecFloat.SFltb in Hxy; + replace (SpecFloat.SFcompare (B2SF _) (B2SF _)) with (Bcompare x y) in Hxy by auto; + assert (Fx: is_finite x = true) by (rewrite Ex; auto); + assert (Fy: is_finite y = true) by (rewrite Ey; auto); + rewrite (Bcompare_correct _ _ x y Fx Fy) in Hxy; auto; + destruct (Raux.Rcompare _ _) eqn:E; try easy; + (apply Raux.Rcompare_Eq_inv in E || apply Raux.Rcompare_Gt_inv in E); + apply Rle_Bleb; auto; lra. +Qed. + +Lemma Bltb_true_Bleb : + forall x y:float, is_nan x = false -> is_nan y = false -> Bltb x y = true -> Bleb y x = false. +Proof. + intros x y Hx Hy Hxy. + destruct x as [ | [ ] | | ] eqn:Ex, y as [ | [ ] | | ] eqn:Ey; try easy; rewrite <- Ex, <- Ey in *; + assert (Fx: is_finite x = true) by (rewrite Ex; auto); + assert (Fy: is_finite y = true) by (rewrite Ey; auto); + apply (Bltb_Rlt _ _ Fx Fy) in Hxy; + apply not_true_is_false; intros Hcontr; + apply (Bleb_Rle _ _ Fy Fx) in Hcontr; + lra. +Qed. + +Lemma Bleb_true_Bltb : + forall x y:float, is_nan x = false -> is_nan y = false -> Bleb x y = true -> Bltb y x = false. +Proof. + intros x y Hx Hy Hxy. + destruct x as [ | [ ] | | ] eqn:Ex, y as [ | [ ] | | ] eqn:Ey; try easy; rewrite <- Ex, <- Ey in *; + assert (Fx: is_finite x = true) by (rewrite Ex; auto); + assert (Fy: is_finite y = true) by (rewrite Ey; auto); + apply (Bleb_Rle _ _ Fx Fy) in Hxy; + apply not_true_is_false; intros Hcontr; + apply (Bltb_Rlt _ _ Fy Fx) in Hcontr; + lra. +Qed. + +Definition Bmax (f1 f2 : float) : float := + if is_nan f1 || is_nan f2 then NaN + else if Bleb f1 f2 then f2 + else f1. + +Definition Bmin (f1 f2 : float) : float := + if is_nan f1 || is_nan f2 then NaN + else if Bleb f1 f2 then f1 + else f2. + +Lemma Bmax_max_1 : + forall x y, (Bmax x y = x \/ Bmax x y = y). +Proof. + intros [ ] [ ]; unfold Bmax; destruct Bleb; intuition. +Qed. + +Lemma Bmax_max_2 : + forall x y, is_finite x = true -> is_finite y = true -> x <= Bmax x y /\ y <= Bmax x y. +Proof. + intros x y Fx Fy; unfold Bmax. + assert (HnanX: is_nan x = false) by fdestruct x. + assert (HnanY: is_nan y = false) by fdestruct y. + rewrite HnanX, HnanY; simpl. + split. + - destruct (Bleb x y) eqn:?; auto. + apply Bleb_refl; fdestruct x. + - destruct (Bleb x y) eqn:E. + + apply Bleb_refl; fdestruct y. + + apply Bleb_false_Bltb in E; auto. + now apply Bltb_Bleb in E. +Qed. + +Lemma Bmax_le : + forall x y z : float, x <= z -> y <= z -> Bmax x y <= z. +Proof. + intros x y z Hxz Hyz. + assert (HnanX: is_nan x = false) by fdestruct x. + assert (HnanY: is_nan y = false) by fdestruct y. + unfold Bmax. + rewrite HnanX, HnanY; simpl. + now destruct (Bleb x y). +Qed. + +Lemma Bmax_not_nan_inv : + forall x y, is_nan (Bmax x y) = false -> is_nan x = false /\ is_nan y = false. +Proof. + intros; split. + + fdestruct x. + + fdestruct x; fdestruct y. +Qed. + +Lemma Bmin_not_nan_inv : + forall x y, is_nan (Bmin x y) = false -> is_nan x = false /\ is_nan y = false. +Proof. + intros; split. + + fdestruct x. + + fdestruct x; fdestruct y. +Qed. + +Lemma Bmax_le_inv : + forall x y z : float, Bmax x y <= z -> x <= z /\ y <= z. +Proof. + intros x y z Hxyz. + assert (is_nan (Bmax x y) = false) by (fdestruct (Bmax x y)). + unfold Bmax in Hxyz. + apply Bmax_not_nan_inv in H. + destruct H as [H1 H2]. + rewrite H1, H2 in Hxyz. + simpl in *. + destruct (Bleb x y) eqn:E; split; auto. + - now apply (Bleb_trans x y z). + - apply Bleb_false_Bltb in E; auto. + apply Bltb_Bleb in E; auto. + now apply (Bleb_trans y x z). +Qed. + +Lemma Bmin_min_1 : + forall x y, (Bmin x y = x \/ Bmin x y = y). +Proof. + intros [ ] [ ]; unfold Bmin; destruct Bleb; intuition. +Qed. + +Lemma Bmin_min_2 : + forall x y, is_finite x = true -> is_finite y = true -> Bmin x y <= x /\ Bmin x y <= y. +Proof. + intros x y Fx Fy; unfold Bmin. + assert (HnanX: is_nan x = false) by fdestruct x. + assert (HnanY: is_nan y = false) by fdestruct y. + rewrite HnanX, HnanY; simpl. + split. + - destruct (Bleb x y) eqn:?. + + apply Bleb_refl; fdestruct x. + + assert (Hx : is_nan x = false) by (fdestruct x). + assert (Hy : is_nan y = false) by (fdestruct y). + apply Bleb_false_Bltb in Heqb; auto. + apply Bltb_Rlt in Heqb; auto. + apply Rle_Bleb; auto. + lra. + - destruct (Bleb x y) eqn:E; auto. + apply Bleb_refl; fdestruct y. +Qed. + +Lemma Bmin_le : + forall x y z : float, z <= x -> z <= y -> z <= Bmin x y. +Proof. + intros x y z Hxz Hyz. + assert (HnanX: is_nan x = false) by (fdestruct z; fdestruct x). + assert (HnanY: is_nan y = false) by (fdestruct z; fdestruct y). + unfold Bmin. + rewrite HnanX, HnanY; simpl. + now destruct (Bleb x y). +Qed. + +Lemma Bmin_le_inv : + forall x y z : float, z <= Bmin x y -> z <= x /\ z <= y. +Proof. + intros x y z Hxyz. + assert (is_nan (Bmin x y) = false) by (fdestruct (Bmin x y); fdestruct z). + unfold Bmin in Hxyz. + apply Bmin_not_nan_inv in H. + destruct H as [H1 H2]. + rewrite H1, H2 in Hxyz. + simpl in *. + destruct (Bleb x y) eqn:E; split; auto. + - now apply (Bleb_trans z x y). + - apply Bleb_false_Bltb in E; auto. + apply Bltb_Bleb in E. + now apply (Bleb_trans z y x). +Qed. + +Lemma Bpred_not_nan : + forall (x : float), is_nan x = false -> is_nan (Bpred x) = false. +Proof. + intros x <-. + apply is_nan_Bpred. +Qed. + +End Utils. + +Arguments le_not_nan {prec} {emax}. +Arguments le_not_nan_l {prec} {emax}. +Arguments le_not_nan_r {prec} {emax}. +Arguments is_nan_inv {prec} {emax}. +Arguments is_infm {prec} {emax}. +Arguments is_infp {prec} {emax}. +Arguments is_inf {prec} {emax}. +Arguments Bplus_not_nan_inv {prec} {emax} {Hprec} {Hemax}. +Arguments Bplus_nan_inv {prec} {emax} {Hprec} {Hemax}. +Arguments Bmin {prec} {emax}. +Arguments Bmax {prec} {emax}. +Arguments Bmax_max_1 {prec} {emax}. +Arguments Bmax_max_2 {prec} {emax}. +Arguments Bmin_min_1 {prec} {emax}. +Arguments Bmin_min_2 {prec} {emax}. +Arguments Bleb_trans {prec} {emax}. +Arguments Bltb_Bleb_trans {prec} {emax}. diff --git a/src_colibri2/tests/solve/smt_fp/sat/_head b/src_colibri2/tests/solve/smt_fp/sat/_head new file mode 100644 index 0000000000000000000000000000000000000000..96c0283fac14b3394a77cd8dba745eadd3f18f88 --- /dev/null +++ b/src_colibri2/tests/solve/smt_fp/sat/_head @@ -0,0 +1,2 @@ +\begin{figure}[h!] + \centering\begin{minted}{scheme} diff --git a/src_colibri2/tests/solve/smt_fp/sat/_tail b/src_colibri2/tests/solve/smt_fp/sat/_tail new file mode 100644 index 0000000000000000000000000000000000000000..026e1a6bee0be18ba149e5ad30b9f780a6868dce --- /dev/null +++ b/src_colibri2/tests/solve/smt_fp/sat/_tail @@ -0,0 +1,3 @@ + \end{minted} + \caption{Incompatibilité de l'égalité flottante avec l'égalité usuelle} +\end{figure} diff --git a/src_colibri2/tests/solve/smt_fp/sat/dune.inc b/src_colibri2/tests/solve/smt_fp/sat/dune.inc index 0a776eab81b6bd13f4f5a1c7a787873ac7be0bda..f0216026c8d36e97ea490cf09e2b42bc28de066b 100644 --- a/src_colibri2/tests/solve/smt_fp/sat/dune.inc +++ b/src_colibri2/tests/solve/smt_fp/sat/dune.inc @@ -17,9 +17,6 @@ --dont-print-result %{dep:recognize_float32.smt2}))) (rule (alias runtest-learning) (action (run %{bin:colibri2} --size=10M --time=30s --max-steps 3500 --check-status sat --learning --dont-print-result %{dep:recognize_float32.smt2}))) (rule (alias runtest) (action (run %{bin:colibri2} --size=10M --time=30s --max-steps 3500 --check-status sat ---dont-print-result %{dep:recognize_float64.smt2}))) -(rule (alias runtest-learning) (action (run %{bin:colibri2} --size=10M --time=30s --max-steps 3500 --check-status sat --learning --dont-print-result %{dep:recognize_float64.smt2}))) -(rule (alias runtest) (action (run %{bin:colibri2} --size=10M --time=30s --max-steps 3500 --check-status sat --dont-print-result %{dep:recognize_rounding_mode.smt2}))) (rule (alias runtest-learning) (action (run %{bin:colibri2} --size=10M --time=30s --max-steps 3500 --check-status sat --learning --dont-print-result %{dep:recognize_rounding_mode.smt2}))) (rule (alias runtest) (action (run %{bin:colibri2} --size=10M --time=30s --max-steps 3500 --check-status sat diff --git a/src_colibri2/tests/solve/smt_fp/sat/recognize_float64.smt2 b/src_colibri2/tests/solve/smt_fp/sat/recognize_float64.smt2 deleted file mode 100644 index 51b3b30b78cb09def79d66167969933518883501..0000000000000000000000000000000000000000 --- a/src_colibri2/tests/solve/smt_fp/sat/recognize_float64.smt2 +++ /dev/null @@ -1,5 +0,0 @@ -(set-logic ALL) -(declare-fun x () (_ FloatingPoint 11 53)) -(declare-fun y () (_ FloatingPoint 11 53)) -(assert (= x y)) -(check-sat) \ No newline at end of file diff --git a/src_colibri2/tests/solve/smt_fp/sat/rm_instanciation.smt2 b/src_colibri2/tests/solve/smt_fp/sat/rm_instanciation.smt2 index f881999439bff2f9f5f5ca1f62afe46b6336c187..0dbb523e8e067bef2968c69f1c45f8fc3ed1f79d 100644 --- a/src_colibri2/tests/solve/smt_fp/sat/rm_instanciation.smt2 +++ b/src_colibri2/tests/solve/smt_fp/sat/rm_instanciation.smt2 @@ -3,5 +3,5 @@ (declare-fun y () (_ FloatingPoint 8 24)) (declare-fun m () RoundingMode) (assert (not (= RNE m))) -(assert (= (fp.add m x y) x)) -(check-sat) \ No newline at end of file +(assert (fp.eq (fp.add m x y) x)) +(check-sat) diff --git a/src_colibri2/tests/solve/smt_fp/sat/simple_add_float32.smt2 b/src_colibri2/tests/solve/smt_fp/sat/simple_add_float32.smt2 index 6f0a55c4ef55157052764d0a2b7c12ed868ede9b..3f47b356d83306c7cd6936488b9c0ac5fbac61cb 100644 --- a/src_colibri2/tests/solve/smt_fp/sat/simple_add_float32.smt2 +++ b/src_colibri2/tests/solve/smt_fp/sat/simple_add_float32.smt2 @@ -1,5 +1,6 @@ (set-logic ALL) (declare-fun x () (_ FloatingPoint 8 24)) (declare-fun y () (_ FloatingPoint 8 24)) -(assert (= (fp.add RNE x y) x)) -(check-sat) \ No newline at end of file +(assert (= (fp.add RNE (_ NaN 8 24) y) (_ NaN 8 24))) +(assert (fp.eq (fp.add RNE x y) x)) +(check-sat) diff --git a/src_colibri2/tests/solve/smt_fp/sat/simple_mul_float32.smt2 b/src_colibri2/tests/solve/smt_fp/sat/simple_mul_float32.smt2 index e0e38f6736112c5a4924579cd4cfa9b4897845de..3fa2e8949b29f856d6533ffe93f1b2cf135bb910 100644 --- a/src_colibri2/tests/solve/smt_fp/sat/simple_mul_float32.smt2 +++ b/src_colibri2/tests/solve/smt_fp/sat/simple_mul_float32.smt2 @@ -1,5 +1,6 @@ (set-logic ALL) (declare-fun x () (_ FloatingPoint 8 24)) (declare-fun y () (_ FloatingPoint 8 24)) -(assert (= (fp.mul RNE x y) x)) -(check-sat) \ No newline at end of file +(assert (= (fp.mul RNE (_ NaN 8 24) y) (_ NaN 8 24))) +(assert (fp.eq (fp.mul RNE x y) x)) +(check-sat) diff --git a/src_colibri2/tests/solve/smt_fp/unsat/dune.inc b/src_colibri2/tests/solve/smt_fp/unsat/dune.inc index d6d0be9784a0b61dfd60878c8aed847242c0da22..5d8594119d983e5c74dfa5044d3723bcca6d6187 100644 --- a/src_colibri2/tests/solve/smt_fp/unsat/dune.inc +++ b/src_colibri2/tests/solve/smt_fp/unsat/dune.inc @@ -7,3 +7,6 @@ (rule (alias runtest) (action (run %{bin:colibri2} --size=10M --time=30s --max-steps 3500 --check-status unsat --dont-print-result %{dep:nan_neq_float32.smt2}))) (rule (alias runtest-learning) (action (run %{bin:colibri2} --size=10M --time=30s --max-steps 3500 --check-status unsat --learning --dont-print-result %{dep:nan_neq_float32.smt2}))) +(rule (alias runtest) (action (run %{bin:colibri2} --size=10M --time=30s --max-steps 3500 --check-status unsat +--dont-print-result %{dep:propagate_le_ge.smt2}))) +(rule (alias runtest-learning) (action (run %{bin:colibri2} --size=10M --time=30s --max-steps 3500 --check-status unsat --learning --dont-print-result %{dep:propagate_le_ge.smt2}))) diff --git a/src_colibri2/tests/solve/smt_fp/unsat/propagate_le_ge.smt2 b/src_colibri2/tests/solve/smt_fp/unsat/propagate_le_ge.smt2 new file mode 100644 index 0000000000000000000000000000000000000000..67a89a5d33987285dc5e6d5fab567a4aef0aa4bd --- /dev/null +++ b/src_colibri2/tests/solve/smt_fp/unsat/propagate_le_ge.smt2 @@ -0,0 +1,5 @@ +(set-logic ALL) +(declare-const x Float32) +(assert (fp.leq x ((_ to_fp 8 24) RNE 1.0))) +(assert (fp.geq x ((_ to_fp 8 24) RNE 3.0))) +(check-sat) \ No newline at end of file diff --git a/src_colibri2/theories/FP/dom_interval.ml b/src_colibri2/theories/FP/dom_interval.ml index c95cbb4d8ba547900962adbc80c4d82ed78cdcb0..0551468dd3241f2e8e59170cfaa87cbcebd5edf2 100644 --- a/src_colibri2/theories/FP/dom_interval.ml +++ b/src_colibri2/theories/FP/dom_interval.ml @@ -20,261 +20,97 @@ open Colibri2_popop_lib open Colibri2_core -open Colibri2_stdlib.Std +(* open Colibri2_stdlib.Std *) let debug = Debug.register_info_flag - ~desc:"for intervals for the floating points theory" - "FP.interval" + ~desc:"for intervals for the arithmetic theory" + "FP.interval" -module D = Colibri2_theories_LRA_stages.Interval_domain +module D = Interval32 let dom = Dom.Kind.create (module struct type t = D.t let name = "FP_ARITH" end) -let () = Dom.register(module struct +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 merged i1 i2 = - match i1, i2 with - | None, None -> true - | Some i1, Some i2 -> D.equal i1 i2 - | _ -> false + 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 merge d (i1,cl1) (i2,cl2) _ = - assert (not (Egraph.is_equal d cl1 cl2)); - match i1, cl1, i2, cl2 with - | Some i1,_, Some i2,_ -> - begin match D.inter i1 i2 with - | None -> - Debug.dprintf8 Debug.contradiction - "[FP/Dom] The intersection of %a and %a is empty when merging %a and %a" - D.pp i1 D.pp i2 - Node.pp cl1 - Node.pp cl2; - Egraph.contradiction d - | Some i -> - if not (D.equal i i1) then - Egraph.set_dom d dom cl1 i; - if not (D.equal i i2) then - Egraph.set_dom d dom cl2 i - end - | Some i1, _, _, cl2 | _, cl2, Some i1, _ -> - Egraph.set_dom d dom cl2 i1 - | None,_,None,_ -> raise Impossible - end) - -let is_zero_or_positive d n = - match Egraph.get_dom d dom n with - | None -> false - | Some p -> match D.is_comparable D.zero p with - | D.Le | D.Lt -> true - | D.Ge | D.Gt | D.Uncomparable -> false - -let is_not_zero d n = - match Egraph.get_dom d dom n with - | None -> false - | Some p -> D.absent Q.zero p - -let is_strictly_positive d n = - match Egraph.get_dom d dom n with - | None -> false - | Some p -> match D.is_comparable D.zero p with - | D.Lt -> true - | D.Le | D.Ge | D.Gt | D.Uncomparable -> false - -let is_strictly_negative d n = - match Egraph.get_dom d dom n with - | None -> false - | Some p -> match D.is_comparable D.zero p with - | D.Gt -> true - | D.Le | D.Ge | D.Lt | D.Uncomparable -> false - -let is_integer d n = - match Egraph.get_dom d dom n with - | None -> false - | Some p -> D.is_integer p - -let set_dom d node v = - match D.is_singleton v with - | Some q -> - let cst = Float32.cst' (Farith.B32.(of_q NE q)) in - Egraph.set_value d node (Float32.nodevalue cst) - | None -> - (** the pexp must be in the dom *) - Egraph.set_dom d dom node v - - -module ChoLRA = struct - let make_decision node v env = - Debug.dprintf4 Debug.decision - "[FP] decide %a on %a" D.pp v Node.pp node; - set_dom env node v - - let choose_decision node env = - let v = Opt.get_def D.reals (Egraph.get_dom env dom node) in - match D.split_heuristic v with - | Singleton _ -> Choice.DecNo - | Splitted (v1,v2) -> - DecTodo (List.map (make_decision node) (Shuffle.shufflel [v1;v2])) - | NotSplitted -> - DecTodo [make_decision node (D.singleton (D.choose v))] - - let choice n = { - Choice.prio = 1; - choice = choose_decision n; - print_cho = "FP.Dom_interval.ChoLRA"; - } - -end - -let choice = ChoLRA.choice - -let upd_dom d n' v' = - match Egraph.get_dom d dom n' with - | None -> Egraph.set_dom d dom n' v' - | Some old -> - match D.inter old v' with - | None -> - Debug.dprintf6 Debug.contradiction - "[FP/Dom] The intersection of %a with %a is empty when updating %a" - D.pp old D.pp v' - Node.pp n'; - Egraph.contradiction d - | Some d' -> - if not (D.equal old d') - then Egraph.set_dom d dom n' d' - -module Monad : sig - type 'a monad = Egraph.wt -> Node.t -> 'a - val get: Node.t -> D.t option monad - val set: Node.t -> D.t option monad -> unit monad - val getb: Node.t -> bool option monad - val setb: Node.t -> bool option option monad -> unit monad - val (let+): 'b option monad -> ('b -> 'c) -> 'c option monad - val (and+): 'b option monad -> 'c option monad -> ('b * 'c) option monad - val (&&): unit monad -> unit monad -> unit monad -end = struct - type 'a monad = Egraph.wt -> Node.t -> 'a - let [@ocaml.always inline] get_dom dom n' = fun d _ -> - Egraph.get_dom d dom n' - let [@ocaml.always inline] set_dom (type b) (dom:b Dom.Kind.t) n' v' d n = - if Node.equal n n' then () else - Option.iter - (fun (v':b) -> Egraph.set_dom d dom n' v') - (v' d n) - let [@ocaml.always inline] set n' v' d n = - if Node.equal n n' then () else - Option.iter - (fun v' -> upd_dom d n' v' ) - (v' d n) - let [@ocaml.always inline] get a = get_dom dom a - let [@ocaml.always inline] get_value key n' = fun d _ -> - let open CCOpt in - let* v = Egraph.get_value d n' in - Value.value key v - let [@ocaml.always inline] set_value (type b) - (value:(module Value.S with type s = b)) - n' (v':b option option monad) : unit monad = - fun d n -> - if Node.equal n n' then () else - let module V = (val value) in - Option.iter - (Option.iter (fun v' -> Egraph.set_value d n' (V.nodevalue (V.index v')))) - (v' d n) - let getb a = get_value Boolean.dom a - let setb a = set_value (module Boolean.BoolValue) a - let [@ocaml.always inline] (let+) a (f:'b -> 'a) = fun d n -> Option.map f (a d n) - let [@ocaml.always inline] (and+) a b = fun d n -> match a d n, b d n with - | Some a, Some b -> Some (a,b) | _ -> None - let [@ocaml.always inline] (&&) a b = fun d n -> a d n; b d n - -end - -let neg_cmp = function - | `Lt -> `Ge - | `Le -> `Gt - | `Ge -> `Lt - | `Gt -> `Le - -let com_cmp = function - | `Lt -> `Gt - | `Le -> `Ge - | `Ge -> `Le - | `Gt -> `Lt - -let backward = function - | `Lt -> D.lt' - | `Gt -> D.gt' - | `Le -> D.le' - | `Ge -> D.ge' +let (!<) e = function + | Some x -> x + | None -> Egraph.contradiction e (** {2 Initialization} *) let converter d (f:Ground.t) = let r = Ground.node f in let reg n = Egraph.register d n in let open Monad in - let cmp test cmp a b = + (* let setb = setv Boolean.dom in *) + let getb = getv Boolean.dom in + 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; - let wakeup = - 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 (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 (if vr then cmp else (neg_cmp cmp)) vb) - in - List.iter (fun n -> Daemon.attach_dom d n dom wakeup) [a;b]; - Daemon.attach_value d r Boolean.BoolValue.key (fun d n _ -> wakeup d n) + (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) + ) in match Ground.sem f with - | { app = {builtin = Expr.Base; _ }; tyargs = _; args = _; ty } - when Ground.Ty.equal ty Ground.Ty.real -> - (* Egraph.register_decision d (ChoLRA.choice r) *) (* not useful for now *) - () - | { app = {builtin = Expr.Base; _ }; tyargs = _; args = _; ty } - when Ground.Ty.equal ty Ground.Ty.int -> - upd_dom d r D.integers - | { app = {builtin = Expr.Add}; tyargs = []; args; _ } -> - let (a,b) = IArray.extract2_exn args in - reg a; reg b; - let wakeup = - set r (let+ va = get a and+ vb = get b in D.add va vb) - in - List.iter (fun n -> Daemon.attach_dom d n dom wakeup) [a; b; r] - | { app = {builtin = Expr.Sub}; tyargs = []; args; _ } -> - let (a,b) = IArray.extract2_exn args in - reg a; reg b; - let wakeup = - set r (let+ va = get a and+ vb = get b in D.minus va vb) - in - List.iter (fun n -> Daemon.attach_dom d n dom wakeup) [a; b; r] - | { app = {builtin = Expr.Minus}; tyargs = []; args; _ } -> - let a = IArray.extract1_exn args in - reg a; - let wakeup = - set r (let+ va = get a in D.mult_cst Q.minus_one va) && - set a (let+ vr = get r in D.mult_cst Q.minus_one vr) - in - List.iter (fun n -> Daemon.attach_dom d n dom wakeup) [a;r] - | { app = {builtin = Expr.Lt}; tyargs = []; args; _ } -> - let a,b = IArray.extract2_exn args in - cmp (function | Uncomparable | Le -> None | Lt -> Some true | Ge | Gt -> Some false) `Lt a b - | { app = {builtin = Expr.Leq}; tyargs = []; args; _ } -> - let a,b = IArray.extract2_exn args in - cmp (function | Uncomparable | Ge -> None | Lt | Le -> Some true | Gt -> Some false) `Le a b - | { app = {builtin = Expr.Geq}; tyargs = []; args; _ } -> - let a,b = IArray.extract2_exn args in - cmp (function | Uncomparable | Le -> None | Lt -> Some false | Ge | Gt -> Some true) `Ge a b - | { app = {builtin = Expr.Gt}; tyargs = []; args; _ } -> - let a,b = IArray.extract2_exn args in - cmp (function | Uncomparable | Ge -> None | Lt | Le -> Some false | Gt -> Some true) `Gt 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 (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 | _ -> () let init env = + Ground.register_converter env converter; Daemon.attach_reg_value env Float32.key (fun d value -> let v = Float32.value value in - let s = D.singleton (Farith.B32.to_q v) in - Egraph.set_dom d dom (Float32.node value) s - ); - Ground.register_converter env converter + 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 + ) + \ No newline at end of file diff --git a/src_colibri2/theories/FP/dune b/src_colibri2/theories/FP/dune index cbb3f787cb459924a1feec6571f6578d90eac56b..09f9db029f87ace159cb599eaecaa0f73d3533cb 100644 --- a/src_colibri2/theories/FP/dune +++ b/src_colibri2/theories/FP/dune @@ -5,6 +5,7 @@ (libraries containers farith + farith2 colibri2.stdlib colibri2.popop_lib colibri2.theories.bool diff --git a/src_colibri2/theories/FP/float32.ml b/src_colibri2/theories/FP/float32.ml index 9e42756c13cd597094b4a1ce907f7649a887edc0..16ffe354cf2c1e2b872f999b2d3e6433f40fcabd 100644 --- a/src_colibri2/theories/FP/float32.ml +++ b/src_colibri2/theories/FP/float32.ml @@ -32,6 +32,10 @@ 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) *) @@ -158,6 +162,7 @@ let converter d (f:Ground.t) = | {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); @@ -214,7 +219,6 @@ let converter d (f:Ground.t) = cmp Farith.B32.eq a b; attach_interp d f; | _ -> () - let init env = Ground.register_converter env converter; init_ty env; diff --git a/src_colibri2/theories/FP/float64.ml b/src_colibri2/theories/FP/float64.ml deleted file mode 100644 index 803b353b0fa34c8ce90c3ae5040c1bb11b9e871c..0000000000000000000000000000000000000000 --- a/src_colibri2/theories/FP/float64.ml +++ /dev/null @@ -1,46 +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 -module N64 = struct let name = "Float64" end -module Float64 = Value.Register(MakeFloat(Farith.B64)(N64)) - -include Float64 - -(** Initialise type interpretation - TODO : fix bounds (there is a finite set of 64 bits floats) -*) -let init_ty d = - Interp.Register.ty d (fun d ty -> - match ty with - | {app={builtin = Builtin.Float(11, 53);_};_} -> - let seq = - let open Interp.SeqLim in - let+ e = of_seq d posint_sequence in - (Farith.B64.of_bits e |> index |> nodevalue) - in - Some seq - | _ -> None) - -(* TO DO : Initialise check *) -(* let init_check d = Interp.Register.check d (...) *) - -let init env = - init_ty env diff --git a/src_colibri2/theories/FP/float64.mli b/src_colibri2/theories/FP/float64.mli deleted file mode 100644 index 908b52f61c02a6f79cab51f3bae8fa5156861146..0000000000000000000000000000000000000000 --- a/src_colibri2/theories/FP/float64.mli +++ /dev/null @@ -1,23 +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.B64.t - -val init : Egraph.wt -> unit diff --git a/src_colibri2/theories/FP/fp.ml b/src_colibri2/theories/FP/fp.ml index edd102b7cf47e01221870a9610de44a6e8a5ea3c..cdee9a24e8412d4a20c0fa92862ef8269b595902 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; - Float64.init env + Float32.init env (* Add the theory to defaults *) let () = diff --git a/src_colibri2/theories/FP/interval32.ml b/src_colibri2/theories/FP/interval32.ml new file mode 100644 index 0000000000000000000000000000000000000000..f0684baed16da75506f0cceff33b08199e8e1c3f --- /dev/null +++ b/src_colibri2/theories/FP/interval32.ml @@ -0,0 +1,54 @@ +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 failwith "assert false" (* failSome (float32_to_B32 x) *) \ No newline at end of file