|
|
@ -41,6 +41,8 @@ module SymLinear = struct
|
|
|
|
|
|
|
|
|
|
|
|
let le : t -> t -> bool =
|
|
|
|
let le : t -> t -> bool =
|
|
|
|
fun x y ->
|
|
|
|
fun x y ->
|
|
|
|
|
|
|
|
phys_equal x y
|
|
|
|
|
|
|
|
||
|
|
|
|
let le_one_pair s v1_opt v2_opt =
|
|
|
|
let le_one_pair s v1_opt v2_opt =
|
|
|
|
let v1 = NonZeroInt.opt_to_big_int v1_opt in
|
|
|
|
let v1 = NonZeroInt.opt_to_big_int v1_opt in
|
|
|
|
let v2 = NonZeroInt.opt_to_big_int v2_opt in
|
|
|
|
let v2 = NonZeroInt.opt_to_big_int v2_opt in
|
|
|
@ -82,13 +84,15 @@ module SymLinear = struct
|
|
|
|
let plus : t -> t -> t =
|
|
|
|
let plus : t -> t -> t =
|
|
|
|
fun x y ->
|
|
|
|
fun x y ->
|
|
|
|
let plus_coeff _ c1 c2 = NonZeroInt.plus c1 c2 in
|
|
|
|
let plus_coeff _ c1 c2 = NonZeroInt.plus c1 c2 in
|
|
|
|
M.union plus_coeff x y
|
|
|
|
PhysEqual.optim2 x y ~res:(M.union plus_coeff x y)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mult_const : NonZeroInt.t -> t -> t = fun n x -> M.map (NonZeroInt.( * ) n) x
|
|
|
|
let mult_const : NonZeroInt.t -> t -> t =
|
|
|
|
|
|
|
|
fun n x -> if NonZeroInt.is_one n then x else M.map (NonZeroInt.( * ) n) x
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let exact_div_const_exn : t -> NonZeroInt.t -> t =
|
|
|
|
let exact_div_const_exn : t -> NonZeroInt.t -> t =
|
|
|
|
fun x n -> M.map (fun c -> NonZeroInt.exact_div_exn c n) x
|
|
|
|
fun x n -> if NonZeroInt.is_one n then x else M.map (fun c -> NonZeroInt.exact_div_exn c n) x
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(* Returns a symbol when the map contains only one symbol s with a
|
|
|
|
(* Returns a symbol when the map contains only one symbol s with a
|
|
|
@ -445,8 +449,8 @@ module Bound = struct
|
|
|
|
PInf
|
|
|
|
PInf
|
|
|
|
| PInf ->
|
|
|
|
| PInf ->
|
|
|
|
MInf
|
|
|
|
MInf
|
|
|
|
| Linear (c, x) ->
|
|
|
|
| Linear (c, x) as b ->
|
|
|
|
Linear (Z.neg c, SymLinear.neg x)
|
|
|
|
if Z.(equal c zero) && SymLinear.is_zero x then b else Linear (Z.neg c, SymLinear.neg x)
|
|
|
|
| MinMax (c, sign, min_max, d, x) ->
|
|
|
|
| MinMax (c, sign, min_max, d, x) ->
|
|
|
|
mk_MinMax (Z.neg c, Sign.neg sign, min_max, d, x)
|
|
|
|
mk_MinMax (Z.neg c, Sign.neg sign, min_max, d, x)
|
|
|
|
|
|
|
|
|
|
|
@ -619,9 +623,15 @@ module Bound = struct
|
|
|
|
overapprox_min original_b1 b2
|
|
|
|
overapprox_min original_b1 b2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let underapprox_max b1 b2 = neg (overapprox_min (neg b1) (neg b2))
|
|
|
|
let underapprox_max b1 b2 =
|
|
|
|
|
|
|
|
let res = neg (overapprox_min (neg b1) (neg b2)) in
|
|
|
|
|
|
|
|
if equal res b1 then b1 else if equal res b2 then b2 else res
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let overapprox_max b1 b2 =
|
|
|
|
|
|
|
|
let res = neg (underapprox_min (neg b1) (neg b2)) in
|
|
|
|
|
|
|
|
if equal res b1 then b1 else if equal res b2 then b2 else res
|
|
|
|
|
|
|
|
|
|
|
|
let overapprox_max b1 b2 = neg (underapprox_min (neg b1) (neg b2))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let approx_max = function
|
|
|
|
let approx_max = function
|
|
|
|
| Symb.BoundEnd.LowerBound ->
|
|
|
|
| Symb.BoundEnd.LowerBound ->
|
|
|
@ -678,11 +688,10 @@ module Bound = struct
|
|
|
|
|
|
|
|
|
|
|
|
let plus_common : f:(t -> t -> t) -> t -> t -> t =
|
|
|
|
let plus_common : f:(t -> t -> t) -> t -> t -> t =
|
|
|
|
fun ~f x y ->
|
|
|
|
fun ~f x y ->
|
|
|
|
|
|
|
|
if is_zero x then y
|
|
|
|
|
|
|
|
else if is_zero y then x
|
|
|
|
|
|
|
|
else
|
|
|
|
match (x, y) with
|
|
|
|
match (x, y) with
|
|
|
|
| _, _ when is_zero x ->
|
|
|
|
|
|
|
|
y
|
|
|
|
|
|
|
|
| _, _ when is_zero y ->
|
|
|
|
|
|
|
|
x
|
|
|
|
|
|
|
|
| Linear (c1, x1), Linear (c2, x2) ->
|
|
|
|
| Linear (c1, x1), Linear (c2, x2) ->
|
|
|
|
Linear (Z.(c1 + c2), SymLinear.plus x1 x2)
|
|
|
|
Linear (Z.(c1 + c2), SymLinear.plus x1 x2)
|
|
|
|
| MinMax (c1, sign, min_max, d1, x1), Linear (c2, x2)
|
|
|
|
| MinMax (c1, sign, min_max, d1, x1), Linear (c2, x2)
|
|
|
@ -723,6 +732,8 @@ module Bound = struct
|
|
|
|
|
|
|
|
|
|
|
|
let mult_const : Symb.BoundEnd.t -> NonZeroInt.t -> t -> t =
|
|
|
|
let mult_const : Symb.BoundEnd.t -> NonZeroInt.t -> t -> t =
|
|
|
|
fun bound_end n x ->
|
|
|
|
fun bound_end n x ->
|
|
|
|
|
|
|
|
if NonZeroInt.is_one n then x
|
|
|
|
|
|
|
|
else
|
|
|
|
match x with
|
|
|
|
match x with
|
|
|
|
| MInf ->
|
|
|
|
| MInf ->
|
|
|
|
if NonZeroInt.is_positive n then MInf else PInf
|
|
|
|
if NonZeroInt.is_positive n then MInf else PInf
|
|
|
@ -760,6 +771,8 @@ module Bound = struct
|
|
|
|
|
|
|
|
|
|
|
|
let div_const : Symb.BoundEnd.t -> t -> NonZeroInt.t -> t option =
|
|
|
|
let div_const : Symb.BoundEnd.t -> t -> NonZeroInt.t -> t option =
|
|
|
|
fun bound_end x n ->
|
|
|
|
fun bound_end x n ->
|
|
|
|
|
|
|
|
if NonZeroInt.is_one n then Some x
|
|
|
|
|
|
|
|
else
|
|
|
|
match x with
|
|
|
|
match x with
|
|
|
|
| MInf ->
|
|
|
|
| MInf ->
|
|
|
|
Some (if NonZeroInt.is_positive n then MInf else PInf)
|
|
|
|
Some (if NonZeroInt.is_positive n then MInf else PInf)
|
|
|
@ -803,10 +816,11 @@ module Bound = struct
|
|
|
|
|
|
|
|
|
|
|
|
let is_not_infty : t -> bool = function MInf | PInf -> false | _ -> true
|
|
|
|
let is_not_infty : t -> bool = function MInf | PInf -> false | _ -> true
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(** Substitutes ALL symbols in [x] with respect to [eval_sym]. Under/over-Approximate as good as possible according to [subst_pos]. *)
|
|
|
|
|
|
|
|
let subst : subst_pos:Symb.BoundEnd.t -> t -> eval_sym -> t bottom_lifted =
|
|
|
|
let lift1 : (t -> t) -> t bottom_lifted -> t bottom_lifted =
|
|
|
|
let lift1 : (t -> t) -> t bottom_lifted -> t bottom_lifted =
|
|
|
|
fun f x -> match x with Bottom -> Bottom | NonBottom x -> NonBottom (f x)
|
|
|
|
fun f x -> match x with Bottom -> Bottom | NonBottom x -> NonBottom (f x)
|
|
|
|
|
|
|
|
in
|
|
|
|
|
|
|
|
|
|
|
|
let lift2 : (t -> t -> t) -> t bottom_lifted -> t bottom_lifted -> t bottom_lifted =
|
|
|
|
let lift2 : (t -> t -> t) -> t bottom_lifted -> t bottom_lifted -> t bottom_lifted =
|
|
|
|
fun f x y ->
|
|
|
|
fun f x y ->
|
|
|
|
match (x, y) with
|
|
|
|
match (x, y) with
|
|
|
@ -814,10 +828,7 @@ module Bound = struct
|
|
|
|
Bottom
|
|
|
|
Bottom
|
|
|
|
| NonBottom x, NonBottom y ->
|
|
|
|
| NonBottom x, NonBottom y ->
|
|
|
|
NonBottom (f x y)
|
|
|
|
NonBottom (f x y)
|
|
|
|
|
|
|
|
in
|
|
|
|
|
|
|
|
|
|
|
|
(** Substitutes ALL symbols in [x] with respect to [eval_sym]. Under/over-Approximate as good as possible according to [subst_pos]. *)
|
|
|
|
|
|
|
|
let subst : subst_pos:Symb.BoundEnd.t -> t -> eval_sym -> t bottom_lifted =
|
|
|
|
|
|
|
|
fun ~subst_pos x eval_sym ->
|
|
|
|
fun ~subst_pos x eval_sym ->
|
|
|
|
let get s =
|
|
|
|
let get s =
|
|
|
|
match eval_sym s with
|
|
|
|
match eval_sym s with
|
|
|
@ -847,6 +858,8 @@ module Bound = struct
|
|
|
|
| MInf | PInf ->
|
|
|
|
| MInf | PInf ->
|
|
|
|
NonBottom x
|
|
|
|
NonBottom x
|
|
|
|
| Linear (c, se) ->
|
|
|
|
| Linear (c, se) ->
|
|
|
|
|
|
|
|
if SymLinear.is_empty se then NonBottom x
|
|
|
|
|
|
|
|
else
|
|
|
|
SymLinear.fold se
|
|
|
|
SymLinear.fold se
|
|
|
|
~init:(NonBottom (of_big_int c))
|
|
|
|
~init:(NonBottom (of_big_int c))
|
|
|
|
~f:(fun acc s coeff -> lift2 (plus subst_pos) acc (get_mult_const s coeff))
|
|
|
|
~f:(fun acc s coeff -> lift2 (plus subst_pos) acc (get_mult_const s coeff))
|
|
|
|