[inferbo] More physical equalities for Bounds

Reviewed By: skcho

Differential Revision: D13176079

fbshipit-source-id: e09ebd176
master
Mehdi Bouaziz 6 years ago committed by Facebook Github Bot
parent 03d3a85f45
commit bdbf39aaa3

@ -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))

Loading…
Cancel
Save