@ -16,6 +16,8 @@ module L = Logging
let sym_size = ref 0
exception Not_one_symbol
module Symbol = struct
type t = Typ . Procname . t * int [ @@ deriving compare ]
@ -58,6 +60,8 @@ module SymLinear = struct
let initial : t = empty
let singleton : Symbol . t -> int -> t = M . singleton
let find : Symbol . t -> t -> int =
fun s x ->
try M . find s x
@ -132,34 +136,63 @@ module SymLinear = struct
let div_const : t -> int -> t = fun x n -> M . map ( ( / ) n ) x
(* Returns a symbol when the map contains only one symbol s with the
coefficient 1 . * )
let one_symbol : t -> Symbol . t option =
fun x ->
(* Returns a symbol when the map contains only one symbol s with a
given coefficient. * )
let one_symbol _of_coeff : int -> t -> Symbol . t option =
fun coeff x ->
let x = M . filter ( fun _ v -> v < > 0 ) x in
if Int . equal ( M . cardinal x ) 1 then
let k , v = M . min_binding x in
if Int . equal v 1 then Some k else None
if Int . equal v coeff then Some k else None
else None
let is_one_symbol : t -> bool = fun x -> match one_symbol x with Some _ -> true | None -> false
let get_one_symbol_opt : t -> Symbol . t option = one_symbol_of_coeff 1
let get_mone_symbol_opt : t -> Symbol . t option = one_symbol_of_coeff ( - 1 )
let get_one_symbol : t -> Symbol . t =
fun x -> match get_one_symbol_opt x with Some s -> s | None -> raise Not_one_symbol
let get_mone_symbol : t -> Symbol . t =
fun x -> match get_mone_symbol_opt x with Some s -> s | None -> raise Not_one_symbol
let is_one_symbol : t -> bool =
fun x -> match get_one_symbol_opt x with Some _ -> true | None -> false
let is_mone_symbol : t -> bool =
fun x -> match get_mone_symbol_opt x with Some _ -> true | None -> false
let get_symbols : t -> Symbol . t list = fun x -> List . map ~ f : fst ( M . bindings x )
end
module Bound = struct
type sign_t = Plus | Minus [ @@ deriving compare ]
let sign_equal = [ % compare . equal : sign_t ]
let neg_sign = function Plus -> Minus | Minus -> Plus
type min_max_t = Min | Max [ @@ deriving compare ]
let min_max_equal = [ % compare . equal : min_max_t ]
let neg_min_max = function Min -> Max | Max -> Min
(* MinMax constructs a bound that is in the "int [+|-] [min|max] ( int, symbol ) " format.
e . g . ` MinMax ( 1 , Minus , Max , 2 , s ) ` means " 1 - max (2, s) " . * )
type t =
| MInf
| Linear of int * SymLinear . t
| MinMax of min_max_t * int * Symbol . t
| MinMax of int * sign_t * min_max_t * int * Symbol . t
| PInf
| Bot
[ @@ deriving compare ]
and min_max_t = Min | Max
let equal = [ % compare . equal : t ]
let pp_sign ~ need_plus : F . formatter -> sign_t -> unit =
fun fmt -> function Plus -> if need_plus then F . fprintf fmt " + " | Minus -> F . fprintf fmt " - "
let pp_min_max : F . formatter -> min_max_t -> unit =
fun fmt -> function Min -> F . fprintf fmt " min " | Max -> F . fprintf fmt " max "
@ -176,8 +209,10 @@ module Bound = struct
-> if SymLinear . le x SymLinear . empty then F . fprintf fmt " %d " c
else if Int . equal c 0 then F . fprintf fmt " %a " SymLinear . pp x
else F . fprintf fmt " %a + %d " SymLinear . pp x c
| MinMax ( m , c , x )
-> F . fprintf fmt " %a(%d, %a) " pp_min_max m c Symbol . pp x
| MinMax ( c , sign , m , d , x )
-> if Int . equal c 0 then F . fprintf fmt " %a " ( pp_sign ~ need_plus : false ) sign
else F . fprintf fmt " %d%a " c ( pp_sign ~ need_plus : true ) sign ;
F . fprintf fmt " %a(%d, %a) " pp_min_max m d Symbol . pp x
let of_int : int -> t = fun n -> Linear ( n , SymLinear . empty )
@ -203,17 +238,27 @@ module Bound = struct
fun s ->
function
| Linear ( c , se )
-> Int . equal c 0 && opt_lift Symbol . eq ( SymLinear . one_symbol se ) ( Some s )
-> Int . equal c 0 && opt_lift Symbol . eq ( SymLinear . get_ one_symbol_opt se ) ( Some s )
| _
-> false
let one_symbol : t -> Symbol . t option = function
| Linear ( c , se ) when Int . equal c 0
-> SymLinear . one_symbol se
| _
-> None
let lift_get_one_symbol : ( SymLinear . t -> Symbol . t option ) -> t -> Symbol . t option =
fun f -> function Linear ( c , se ) when Int . equal c 0 -> f se | _ -> None
let get_one_symbol_opt : t -> Symbol . t option = lift_get_one_symbol SymLinear . get_one_symbol_opt
let get_mone_symbol_opt : t -> Symbol . t option =
lift_get_one_symbol SymLinear . get_mone_symbol_opt
let get_one_symbol : t -> Symbol . t =
fun x -> match get_one_symbol_opt x with Some s -> s | None -> raise Not_one_symbol
let is_one_symbol : t -> bool = fun x -> one_symbol x < > None
let get_mone_symbol : t -> Symbol . t =
fun x -> match get_mone_symbol_opt x with Some s -> s | None -> raise Not_one_symbol
let is_one_symbol : t -> bool = fun x -> get_one_symbol_opt x < > None
let is_mone_symbol : t -> bool = fun x -> get_mone_symbol_opt x < > None
let use_symbol : Symbol . t -> t -> bool =
fun s ->
@ -222,7 +267,7 @@ module Bound = struct
-> false
| Linear ( _ , se )
-> SymLinear . find s se < > 0
| MinMax ( _ , _ , s' )
| MinMax ( _ , _ , _ , _ , s' )
-> Symbol . eq s s'
let subst1 : t -> t -> Symbol . t -> t -> t =
@ -238,24 +283,50 @@ module Bound = struct
let se1 = SymLinear . add s 0 se1 in
let se' = SymLinear . plus se1 ( SymLinear . mult_const se2 coeff ) in
Linear ( c' , se' )
| MinMax ( Min , _ , s' ) , MInf when Symbol . eq s s'
| MinMax ( _ , Plus , Min , _ , _ ) , MInf
-> MInf
| MinMax ( Max , c , s' ) , MInf when Symbol . eq s s'
-> Linear ( c , SymLinear . zero )
| MinMax ( Max , _ , s' ) , PInf when Symbol . eq s s'
| MinMax ( _ , Minus , Min , _ , _ ) , MInf
-> PInf
| MinMax ( Min , c , s' ) , PInf when Symbol . eq s s'
-> Linear ( c , SymLinear . zero )
| MinMax ( Min , c1 , s' ) , Linear ( c2 , se ) when Symbol . eq s s' && SymLinear . is_zero se
-> Linear ( min c1 c2 , SymLinear . zero )
| MinMax ( Max , c1 , s' ) , Linear ( c2 , se ) when Symbol . eq s s' && SymLinear . is_zero se
-> Linear ( max c1 c2 , SymLinear . zero )
| MinMax ( m , c , s' ) , _ when Symbol . eq s s' && is_one_symbol y -> (
match one_symbol y with Some s'' -> MinMax ( m , c , s'' ) | _ -> assert false )
| MinMax ( Min , c1 , s' ) , MinMax ( Min , c2 , s'' ) when Symbol . eq s s'
-> MinMax ( Min , min c1 c2 , s'' )
| MinMax ( Max , c1 , s' ) , MinMax ( Max , c2 , s'' ) when Symbol . eq s s'
-> MinMax ( Max , max c1 c2 , s'' )
| MinMax ( _ , Plus , Max , _ , _ ) , PInf
-> PInf
| MinMax ( _ , Minus , Max , _ , _ ) , PInf
-> MInf
| MinMax ( c , Plus , Min , d , _ ) , PInf
-> Linear ( c + d , SymLinear . zero )
| MinMax ( c , Minus , Min , d , _ ) , PInf
-> Linear ( c - d , SymLinear . zero )
| MinMax ( c , Plus , Max , d , _ ) , MInf
-> Linear ( c + d , SymLinear . zero )
| MinMax ( c , Minus , Max , d , _ ) , MInf
-> Linear ( c - d , SymLinear . zero )
| MinMax ( c1 , Plus , Min , d1 , _ ) , Linear ( c2 , se ) when SymLinear . is_zero se
-> Linear ( c1 + min d1 c2 , SymLinear . zero )
| MinMax ( c1 , Minus , Min , d1 , _ ) , Linear ( c2 , se ) when SymLinear . is_zero se
-> Linear ( c1 - min d1 c2 , SymLinear . zero )
| MinMax ( c1 , Plus , Max , d1 , _ ) , Linear ( c2 , se ) when SymLinear . is_zero se
-> Linear ( c1 + max d1 c2 , SymLinear . zero )
| MinMax ( c1 , Minus , Max , d1 , _ ) , Linear ( c2 , se ) when SymLinear . is_zero se
-> Linear ( c1 - max d1 c2 , SymLinear . zero )
| MinMax ( c , sign , m , d , _ ) , _ when is_one_symbol y
-> MinMax ( c , sign , m , d , get_one_symbol y )
| MinMax ( c , sign , m , d , _ ) , _ when is_mone_symbol y
-> MinMax ( c , neg_sign sign , neg_min_max m , - d , get_mone_symbol y )
| MinMax ( c1 , Plus , Min , d1 , _ ) , MinMax ( c2 , Plus , Min , d2 , s' )
-> MinMax ( c1 + c2 , Plus , Min , min ( d1 - c2 ) d2 , s' )
| MinMax ( c1 , Plus , Max , d1 , _ ) , MinMax ( c2 , Plus , Max , d2 , s' )
-> MinMax ( c1 + c2 , Plus , Max , max ( d1 - c2 ) d2 , s' )
| MinMax ( c1 , Minus , Min , d1 , _ ) , MinMax ( c2 , Plus , Min , d2 , s' )
-> MinMax ( c1 - c2 , Minus , Min , min ( d1 - c2 ) d2 , s' )
| MinMax ( c1 , Minus , Max , d1 , _ ) , MinMax ( c2 , Plus , Max , d2 , s' )
-> MinMax ( c1 - c2 , Minus , Max , max ( d1 - c2 ) d2 , s' )
| MinMax ( c1 , Plus , Min , d1 , _ ) , MinMax ( c2 , Minus , Max , d2 , s' )
-> MinMax ( c1 + c2 , Minus , Max , max ( - d1 + c2 ) d2 , s' )
| MinMax ( c1 , Plus , Max , d1 , _ ) , MinMax ( c2 , Minus , Min , d2 , s' )
-> MinMax ( c1 + c2 , Minus , Min , min ( - d1 + c2 ) d2 , s' )
| MinMax ( c1 , Minus , Min , d1 , _ ) , MinMax ( c2 , Minus , Max , d2 , s' )
-> MinMax ( c1 - c2 , Minus , Max , max ( - d1 + c2 ) d2 , s' )
| MinMax ( c1 , Minus , Max , d1 , _ ) , MinMax ( c2 , Minus , Min , d2 , s' )
-> MinMax ( c1 - c2 , Minus , Min , min ( - d1 + c2 ) d2 , s' )
| _
-> default
@ -263,7 +334,54 @@ module Bound = struct
let subst : t -> t -> t SubstMap . t -> t =
fun default x map -> SubstMap . fold ( fun s y x -> subst1 default x s y ) map x
let le : t -> t -> bool =
let int_ub_of_minmax = function
| MinMax ( c , Plus , Min , d , _ )
-> Some ( c + d )
| MinMax ( c , Minus , Max , d , _ )
-> Some ( c - d )
| MinMax _
-> None
| MInf | PInf | Linear _ | Bot
-> assert false
let int_lb_of_minmax = function
| MinMax ( c , Plus , Max , d , _ )
-> Some ( c + d )
| MinMax ( c , Minus , Min , d , _ )
-> Some ( c - d )
| MinMax _
-> None
| MInf | PInf | Linear _ | Bot
-> assert false
let linear_ub_of_minmax = function
| MinMax ( c , Plus , Min , _ , x )
-> Some ( Linear ( c , SymLinear . singleton x 1 ) )
| MinMax ( c , Minus , Max , _ , x )
-> Some ( Linear ( c , SymLinear . singleton x ( - 1 ) ) )
| MinMax _
-> None
| MInf | PInf | Linear _ | Bot
-> assert false
let linear_lb_of_minmax = function
| MinMax ( c , Plus , Max , _ , x )
-> Some ( Linear ( c , SymLinear . singleton x 1 ) )
| MinMax ( c , Minus , Min , _ , x )
-> Some ( Linear ( c , SymLinear . singleton x ( - 1 ) ) )
| MinMax _
-> None
| MInf | PInf | Linear _ | Bot
-> assert false
let le_minmax_by_int x y =
match ( int_ub_of_minmax x , int_lb_of_minmax y ) with Some n , Some m -> n < = m | _ , _ -> false
let le_opt1 le opt_n m = Option . value_map opt_n ~ default : false ~ f : ( fun n -> le n m )
let le_opt2 le n opt_m = Option . value_map opt_m ~ default : false ~ f : ( fun m -> le n m )
let rec le : t -> t -> bool =
fun x y ->
assert ( x < > Bot && y < > Bot ) ;
match ( x , y ) with
@ -273,16 +391,22 @@ module Bound = struct
-> false
| Linear ( c0 , x0 ) , Linear ( c1 , x1 )
-> c0 < = c1 && SymLinear . eq x0 x1
| MinMax ( Min , c0 , x0 ) , MinMax ( Min , c1 , x1 ) | MinMax ( Max , c0 , x0 ) , MinMax ( Max , c1 , x1 )
-> c0 < = c1 && Symbol . eq x0 x1
| MinMax ( Min , c0 , x0 ) , Linear ( c1 , x1 )
-> c0 < = c1 && SymLinear . is_zero x1
| | Int . equal c1 0 && opt_lift Symbol . eq ( SymLinear . one_symbol x1 ) ( Some x0 )
| Linear ( c1 , x1 ) , MinMax ( Max , c0 , x0 )
-> c1 < = c0 && SymLinear . is_zero x1
| | Int . equal c1 0 && opt_lift Symbol . eq ( SymLinear . one_symbol x1 ) ( Some x0 )
| MinMax ( Min , c0 , x0 ) , MinMax ( Max , c1 , x1 )
-> c0 < = c1 | | Symbol . eq x0 x1
| MinMax ( c1 , sign1 , m1 , d1 , x1 ) , MinMax ( c2 , sign2 , m2 , d2 , x2 )
when sign_equal sign1 sign2 && min_max_equal m1 m2
-> c1 < = c2 && Int . equal d1 d2 && Symbol . eq x1 x2
| MinMax _ , MinMax _ when le_minmax_by_int x y
-> true
| MinMax ( c1 , Plus , Min , _ , x1 ) , MinMax ( c2 , Plus , Max , _ , x2 )
| MinMax ( c1 , Minus , Max , _ , x1 ) , MinMax ( c2 , Minus , Min , _ , x2 )
-> c1 < = c2 && Symbol . eq x1 x2
| MinMax _ , Linear ( c , se ) when SymLinear . is_zero se
-> le_opt1 ( < = ) ( int_ub_of_minmax x ) c
| MinMax _ , Linear _
-> le_opt1 le ( linear_ub_of_minmax x ) y
| Linear ( c , se ) , MinMax _ when SymLinear . is_zero se
-> le_opt2 ( < = ) c ( int_lb_of_minmax y )
| Linear _ , MinMax _
-> le_opt2 le x ( linear_lb_of_minmax y )
| _ , _
-> false
@ -292,14 +416,10 @@ module Bound = struct
match ( x , y ) with
| MInf , Linear _ | MInf , MinMax _ | MInf , PInf | Linear _ , PInf | MinMax _ , PInf
-> true
| Linear ( c0 , x0 ) , Linear ( c1 , x1 )
-> c0 < c1 && SymLinear . eq x0 x1
| MinMax ( Min , c0 , _ ) , Linear ( c1 , x1 )
-> c0 < c1 && SymLinear . is_zero x1
| Linear ( c1 , x1 ) , MinMax ( Max , c0 , _ )
-> c1 < c0 && SymLinear . is_zero x1
| MinMax ( Min , c0 , _ ) , MinMax ( Max , c1 , _ )
-> c0 < c1
| Linear ( c , x ) , _
-> le ( Linear ( c + 1 , x ) ) y
| MinMax ( c , sign , min_max , d , x ) , _
-> le ( MinMax ( c + 1 , sign , min_max , d , x ) ) y
| _ , _
-> false
@ -311,59 +431,77 @@ module Bound = struct
else if equal x Bot | | equal y Bot then false
else le x y && le y x
let min : t -> t -> t =
fun x y ->
let remove_max_int : t -> t =
fun x ->
match x with
| MinMax ( c , Plus , Max , _ , s )
-> Linear ( c , SymLinear . singleton s 1 )
| MinMax ( c , Minus , Min , _ , s )
-> Linear ( c , SymLinear . singleton s ( - 1 ) )
| _
-> x
let rec lb : ? default : t -> t -> t -> t =
fun ? ( default = MInf ) x y ->
assert ( x < > Bot && y < > Bot ) ;
if le x y then x
else if le y x then y
else
match ( x , y ) with
| Linear ( c0 , x0 ) , Linear ( c1 , x1 )
when SymLinear . is_zero x0 && Int . equal c1 0 && SymLinear . is_one_symbol x1 -> (
match SymLinear . one_symbol x1 with
| Some x'
-> MinMax ( Min , c0 , x' )
| None
-> assert false )
| Linear ( c0 , x0 ) , Linear ( c1 , x1 )
when SymLinear . is_zero x1 && Int . equal c0 0 && SymLinear . is_one_symbol x0 -> (
match SymLinear . one_symbol x0 with
| Some x'
-> MinMax ( Min , c1 , x' )
| None
-> assert false )
| MinMax ( Max , c0 , _ ) , Linear ( c1 , x1 )
| Linear ( c1 , x1 ) , MinMax ( Max , c0 , _ )
when SymLinear . is_zero x1 && c0 < c1
-> Linear ( c0 , x1 )
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_zero x1 && SymLinear . is_one_symbol x2
-> MinMax ( c2 , Plus , Min , c1 - c2 , SymLinear . get_one_symbol x2 )
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_one_symbol x1 && SymLinear . is_zero x2
-> MinMax ( c1 , Plus , Min , c2 - c1 , SymLinear . get_one_symbol x1 )
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_zero x1 && SymLinear . is_mone_symbol x2
-> MinMax ( c2 , Minus , Max , c2 - c1 , SymLinear . get_mone_symbol x2 )
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_mone_symbol x1 && SymLinear . is_zero x2
-> MinMax ( c1 , Minus , Max , c1 - c2 , SymLinear . get_mone_symbol x1 )
| MinMax ( c1 , Plus , Min , d1 , s ) , Linear ( c2 , se )
| Linear ( c2 , se ) , MinMax ( c1 , Plus , Min , d1 , s )
when SymLinear . is_zero se
-> MinMax ( c1 , Plus , Min , min d1 ( c2 - c1 ) , s )
| MinMax ( c1 , Plus , Max , _ , s ) , Linear ( c2 , se )
| Linear ( c2 , se ) , MinMax ( c1 , Plus , Max , _ , s )
when SymLinear . is_zero se
-> MinMax ( c1 , Plus , Min , c2 - c1 , s )
| MinMax ( c1 , Minus , Min , _ , s ) , Linear ( c2 , se )
| Linear ( c2 , se ) , MinMax ( c1 , Minus , Min , _ , s )
when SymLinear . is_zero se
-> MinMax ( c1 , Minus , Max , c1 - c2 , s )
| MinMax ( c1 , Minus , Max , d1 , s ) , Linear ( c2 , se )
| Linear ( c2 , se ) , MinMax ( c1 , Minus , Max , d1 , s )
when SymLinear . is_zero se
-> MinMax ( c1 , Minus , Max , max d1 ( c1 - c2 ) , s )
| MinMax ( _ , Plus , Min , _ , _ ) , MinMax ( _ , Plus , Max , _ , _ )
| MinMax ( _ , Plus , Min , _ , _ ) , MinMax ( _ , Minus , Min , _ , _ )
| MinMax ( _ , Minus , Max , _ , _ ) , MinMax ( _ , Plus , Max , _ , _ )
| MinMax ( _ , Minus , Max , _ , _ ) , MinMax ( _ , Minus , Min , _ , _ )
-> lb ~ default x ( remove_max_int y )
| MinMax ( _ , Plus , Max , _ , _ ) , MinMax ( _ , Plus , Min , _ , _ )
| MinMax ( _ , Minus , Min , _ , _ ) , MinMax ( _ , Plus , Min , _ , _ )
| MinMax ( _ , Plus , Max , _ , _ ) , MinMax ( _ , Minus , Max , _ , _ )
| MinMax ( _ , Minus , Min , _ , _ ) , MinMax ( _ , Minus , Max , _ , _ )
-> lb ~ default ( remove_max_int x ) y
| MinMax ( c1 , Plus , Max , d1 , _ ) , MinMax ( c2 , Plus , Max , d2 , _ )
-> Linear ( min ( c1 + d1 ) ( c2 + d2 ) , SymLinear . zero )
| _ , _
-> MInf
-> default
let max : t -> t -> t =
let ub : t -> t -> t =
fun x y ->
assert ( x < > Bot && y < > Bot ) ;
if le x y then y
else if le y x then x
else
match ( x , y ) with
| Linear ( c0 , x0 ) , Linear ( c1 , x1 )
when SymLinear . is_zero x0 && Int . equal c1 0 && SymLinear . is_one_symbol x1 -> (
match SymLinear . one_symbol x1 with
| Some x'
-> MinMax ( Max , c0 , x' )
| None
-> assert false )
| Linear ( c0 , x0 ) , Linear ( c1 , x1 )
when SymLinear . is_zero x1 && Int . equal c0 0 && SymLinear . is_one_symbol x0 -> (
match SymLinear . one_symbol x0 with
| Some x'
-> MinMax ( Max , c1 , x' )
| None
-> assert false )
| MinMax ( Min , c0 , _ ) , Linear ( c1 , x1 )
| Linear ( c1 , x1 ) , MinMax ( Min , c0 , _ )
when SymLinear . is_zero x1 && c0 > c1
-> Linear ( c0 , x1 )
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_zero x1 && SymLinear . is_one_symbol x2
-> MinMax ( c2 , Plus , Max , c1 - c2 , SymLinear . get_one_symbol x2 )
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_one_symbol x1 && SymLinear . is_zero x2
-> MinMax ( c1 , Plus , Max , c2 - c1 , SymLinear . get_one_symbol x1 )
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_zero x1 && SymLinear . is_mone_symbol x2
-> MinMax ( c2 , Minus , Min , c2 - c1 , SymLinear . get_mone_symbol x2 )
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_mone_symbol x1 && SymLinear . is_zero x2
-> MinMax ( c1 , Minus , Min , c1 - c2 , SymLinear . get_mone_symbol x1 )
| _ , _
-> PInf
@ -409,8 +547,16 @@ module Bound = struct
-> x
| Linear ( c1 , x1 ) , Linear ( c2 , x2 )
-> Linear ( c1 + c2 , SymLinear . plus x1 x2 )
| MinMax ( Max , c1 , _ ) , Linear ( c2 , x2 ) | Linear ( c2 , x2 ) , MinMax ( Max , c1 , _ )
-> Linear ( c1 + c2 , x2 )
| MinMax ( c1 , sign , min_max , d1 , x1 ) , Linear ( c2 , x2 )
| Linear ( c2 , x2 ) , MinMax ( c1 , sign , min_max , d1 , x1 )
when SymLinear . is_zero x2
-> MinMax ( c1 + c2 , sign , min_max , d1 , x1 )
| MinMax ( c1 , Plus , Max , d1 , _ ) , Linear ( c2 , x2 )
| Linear ( c2 , x2 ) , MinMax ( c1 , Plus , Max , d1 , _ )
-> Linear ( c1 + d1 + c2 , x2 )
| MinMax ( c1 , Minus , Min , d1 , _ ) , Linear ( c2 , x2 )
| Linear ( c2 , x2 ) , MinMax ( c1 , Minus , Min , d1 , _ )
-> Linear ( c1 - d1 + c2 , x2 )
| _ , _
-> MInf
@ -424,8 +570,16 @@ module Bound = struct
-> x
| Linear ( c1 , x1 ) , Linear ( c2 , x2 )
-> Linear ( c1 + c2 , SymLinear . plus x1 x2 )
| MinMax ( Min , c1 , _ ) , Linear ( c2 , x2 ) | Linear ( c2 , x2 ) , MinMax ( Min , c1 , _ )
-> Linear ( c1 + c2 , x2 )
| MinMax ( c1 , sign , min_max , d1 , x1 ) , Linear ( c2 , x2 )
| Linear ( c2 , x2 ) , MinMax ( c1 , sign , min_max , d1 , x1 )
when SymLinear . is_zero x2
-> MinMax ( c1 + c2 , sign , min_max , d1 , x1 )
| MinMax ( c1 , Plus , Min , d1 , _ ) , Linear ( c2 , x2 )
| Linear ( c2 , x2 ) , MinMax ( c1 , Plus , Min , d1 , _ )
-> Linear ( c1 + d1 + c2 , x2 )
| MinMax ( c1 , Minus , Max , d1 , _ ) , Linear ( c2 , x2 )
| Linear ( c2 , x2 ) , MinMax ( c1 , Minus , Max , d1 , _ )
-> Linear ( c1 - d1 + c2 , x2 )
| _ , _
-> PInf
@ -467,34 +621,17 @@ module Bound = struct
-> Some MInf
| Linear ( c , x )
-> Some ( Linear ( - c , SymLinear . neg x ) )
| MinMax _
-> None
| MinMax (c , sign , min _max, d , x )
-> Some ( MinMax ( - c , neg_sign sign , min_max , d , x ) )
| Bot
-> assert false
let make_min_max : min_max_t -> t -> t -> t option =
fun m x y ->
assert ( x < > Bot && y < > Bot ) ;
match ( x , y ) with
| Linear ( cx , x' ) , Linear ( cy , y' )
when Int . equal cy 0 && SymLinear . is_zero x' && SymLinear . is_one_symbol y' -> (
match SymLinear . one_symbol y' with Some s -> Some ( MinMax ( m , cx , s ) ) | None -> None )
| Linear ( cx , x' ) , Linear ( cy , y' )
when Int . equal cx 0 && SymLinear . is_zero y' && SymLinear . is_one_symbol x' -> (
match SymLinear . one_symbol x' with Some s -> Some ( MinMax ( m , cy , s ) ) | None -> None )
| _ , _
-> None
let make_min : t -> t -> t option = make_min_max Min
let make_max : t -> t -> t option = make_min_max Max
let get_symbols : t -> Symbol . t list = function
| MInf | PInf
-> []
| Linear ( _ , se )
-> SymLinear . get_symbols se
| MinMax ( _ , _ , s )
| MinMax ( _ , _ , _ , _ , s )
-> [ s ]
| Bot
-> assert false
@ -525,7 +662,7 @@ module ItvPure = struct
let ( < = ) : lhs : t -> rhs : t -> bool =
fun ~ lhs : ( l1 , u1 ) ~ rhs : ( l2 , u2 ) -> Bound . le l2 l1 && Bound . le u1 u2
let join : t -> t -> t = fun ( l1 , u1 ) ( l2 , u2 ) -> ( Bound . min l1 l2 , Bound . max u1 u2 )
let join : t -> t -> t = fun ( l1 , u1 ) ( l2 , u2 ) -> ( Bound . lb l1 l2 , Bound . ub u1 u2 )
let widen : prev : t -> next : t -> num_iters : int -> t =
fun ~ prev : ( l1 , u1 ) ~ next : ( l2 , u2 ) ~ num_iters : _ -> ( Bound . widen_l l1 l2 , Bound . widen_u u1 u2 )
@ -549,7 +686,8 @@ module ItvPure = struct
let make_sym : unsigned : bool -> Typ . Procname . t -> ( unit -> int ) -> t =
fun ~ unsigned pname new_sym_num ->
let lower =
if unsigned then Bound . MinMax ( Bound . Max , 0 , Symbol . make pname ( new_sym_num () ) )
if unsigned then
Bound . MinMax ( 0 , Bound . Plus , Bound . Max , 0 , Symbol . make pname ( new_sym_num () ) )
else Bound . of_sym ( SymLinear . make pname ( new_sym_num () ) )
in
let upper = Bound . of_sym ( SymLinear . make pname ( new_sym_num () ) ) in
@ -712,6 +850,8 @@ module ItvPure = struct
else if is_false x && is_false y then false _ sem
else unknown_bool
let min_sem : t -> t -> t = fun ( l1 , u1 ) ( l2 , u2 ) -> ( Bound . lb l1 l2 , Bound . lb ~ default : u1 u1 u2 )
let invalid : t -> bool =
fun ( l , u ) ->
Bound . equal l Bound . Bot | | Bound . equal u Bound . Bot | | Bound . eq l Bound . PInf
@ -724,25 +864,22 @@ module ItvPure = struct
-> ( l1 , u2 )
| ( l1 , Bound . Linear ( c1 , s1 ) ) , ( _ , Bound . Linear ( c2 , s2 ) ) when SymLinear . eq s1 s2
-> ( l1 , Bound . Linear ( min c1 c2 , s1 ) )
| ( l1 , Bound . Linear ( c , se ) ) , ( _ , u ) when SymLinear . is_zero se && Bound . is_one_symbol u -> (
match Bound . one_symbol u with
| Some s
-> ( l1 , Bound . MinMax ( Bound . Min , c , s ) )
| None
-> assert false )
| ( l1 , u ) , ( _ , Bound . Linear ( c , se ) ) when SymLinear . is_zero se && Bound . is_one_symbol u -> (
match Bound . one_symbol u with
| Some s
-> ( l1 , Bound . MinMax ( Bound . Min , c , s ) )
| None
-> assert false )
| ( l1 , Bound . Linear ( c1 , se ) ) , ( _ , Bound . MinMax ( Bound . Min , c2 , se' ) )
| ( l1 , Bound . MinMax ( Bound . Min , c1 , se' ) ) , ( _ , Bound . Linear ( c2 , se ) )
| ( l1 , Bound . Linear ( c , se ) ) , ( _ , u ) when SymLinear . is_zero se && Bound . is_one_symbol u
-> ( l1 , Bound . MinMax ( 0 , Bound . Plus , Bound . Min , c , Bound . get_one_symbol u ) )
| ( l1 , u ) , ( _ , Bound . Linear ( c , se ) ) when SymLinear . is_zero se && Bound . is_one_symbol u
-> ( l1 , Bound . MinMax ( 0 , Bound . Plus , Bound . Min , c , Bound . get_one_symbol u ) )
| ( l1 , Bound . Linear ( c , se ) ) , ( _ , u ) when SymLinear . is_zero se && Bound . is_mone_symbol u
-> ( l1 , Bound . MinMax ( 0 , Bound . Minus , Bound . Max , - c , Bound . get_mone_symbol u ) )
| ( l1 , u ) , ( _ , Bound . Linear ( c , se ) ) when SymLinear . is_zero se && Bound . is_mone_symbol u
-> ( l1 , Bound . MinMax ( 0 , Bound . Minus , Bound . Max , - c , Bound . get_mone_symbol u ) )
| ( l1 , Bound . Linear ( c1 , se ) ) , ( _ , Bound . MinMax ( c2 , Bound . Plus , Bound . Min , d2 , se' ) )
| ( l1 , Bound . MinMax ( c2 , Bound . Plus , Bound . Min , d2 , se' ) ) , ( _ , Bound . Linear ( c1 , se ) )
when SymLinear . is_zero se
-> ( l1 , Bound . MinMax ( Bound . Min , min c1 c2 , se' ) )
| ( l1 , Bound . MinMax ( Bound . Min , c1 , se1 ) ) , ( _ , Bound . MinMax ( Bound . Min , c2 , se2 ) )
when Symbol . eq se1 se2
-> ( l1 , Bound . MinMax ( Bound . Min , min c1 c2 , se1 ) )
-> ( l1 , Bound . MinMax ( c2 , Bound . Plus , Bound . Min , min ( c1 - c2 ) d2 , se' ) )
| ( ( l1 , Bound . MinMax ( c1 , Bound . Plus , Bound . Min , d1 , se1 ) )
, ( _ , Bound . MinMax ( c2 , Bound . Plus , Bound . Min , d2 , se2 ) ) )
when Int . equal c1 c2 && Symbol . eq se1 se2
-> ( l1 , Bound . MinMax ( c1 , Bound . Plus , Bound . Min , min d1 d2 , se1 ) )
| _
-> x
@ -753,25 +890,22 @@ module ItvPure = struct
-> ( l2 , u1 )
| ( Bound . Linear ( c1 , s1 ) , u1 ) , ( Bound . Linear ( c2 , s2 ) , _ ) when SymLinear . eq s1 s2
-> ( Bound . Linear ( max c1 c2 , s1 ) , u1 )
| ( Bound . Linear ( c , se ) , u1 ) , ( l , _ ) when SymLinear . is_zero se && Bound . is_one_symbol l -> (
match Bound . one_symbol l with
| Some s
-> ( Bound . MinMax ( Bound . Max , c , s ) , u1 )
| None
-> assert false )
| ( l , u1 ) , ( Bound . Linear ( c , se ) , _ ) when SymLinear . is_zero se && Bound . is_one_symbol l -> (
match Bound . one_symbol l with
| Some s
-> ( Bound . MinMax ( Bound . Max , c , s ) , u1 )
| None
-> assert false )
| ( Bound . Linear ( c1 , se ) , u1 ) , ( Bound . MinMax ( Bound . Max , c2 , se' ) , _ )
| ( Bound . MinMax ( Bound . Max , c1 , se' ) , u1 ) , ( Bound . Linear ( c2 , se ) , _ )
| ( Bound . Linear ( c , se ) , u1 ) , ( l , _ ) when SymLinear . is_zero se && Bound . is_one_symbol l
-> ( Bound . MinMax ( 0 , Bound . Plus , Bound . Max , c , Bound . get_one_symbol l ) , u1 )
| ( l , u1 ) , ( Bound . Linear ( c , se ) , _ ) when SymLinear . is_zero se && Bound . is_one_symbol l
-> ( Bound . MinMax ( 0 , Bound . Plus , Bound . Max , c , Bound . get_one_symbol l ) , u1 )
| ( Bound . Linear ( c , se ) , u1 ) , ( l , _ ) when SymLinear . is_zero se && Bound . is_mone_symbol l
-> ( Bound . MinMax ( 0 , Bound . Minus , Bound . Min , c , Bound . get_mone_symbol l ) , u1 )
| ( l , u1 ) , ( Bound . Linear ( c , se ) , _ ) when SymLinear . is_zero se && Bound . is_mone_symbol l
-> ( Bound . MinMax ( 0 , Bound . Minus , Bound . Min , c , Bound . get_mone_symbol l ) , u1 )
| ( Bound . Linear ( c1 , se ) , u1 ) , ( Bound . MinMax ( c2 , Bound . Plus , Bound . Max , d2 , se' ) , _ )
| ( Bound . MinMax ( c2 , Bound . Plus , Bound . Max , d2 , se' ) , u1 ) , ( Bound . Linear ( c1 , se ) , _ )
when SymLinear . is_zero se
-> ( Bound . MinMax ( Bound . Max , max c1 c2 , se' ) , u1 )
| ( Bound . MinMax ( Bound . Max , c1 , se1 ) , u1 ) , ( Bound . MinMax ( Bound . Max , c2 , se2 ) , _ )
when Symbol . eq se1 se2
-> ( Bound . MinMax ( Bound . Max , max c1 c2 , se1 ) , u1 )
-> ( Bound . MinMax ( c2 , Bound . Plus , Bound . Max , max ( c1 - c2 ) d2 , se' ) , u1 )
| ( ( Bound . MinMax ( c1 , Bound . Plus , Bound . Max , d1 , se1 ) , u1 )
, ( Bound . MinMax ( c2 , Bound . Plus , Bound . Max , d2 , se2 ) , _ ) )
when Int . equal c1 c2 && Symbol . eq se1 se2
-> ( Bound . MinMax ( c1 , Bound . Plus , Bound . Max , max d1 d2 , se1 ) , u1 )
| _
-> x
@ -964,6 +1098,8 @@ let land_sem : t -> t -> t = lift2 ItvPure.land_sem
let lor_sem : t -> t -> t = lift2 ItvPure . lor_sem
let min_sem : t -> t -> t = lift2 ItvPure . min_sem
let prune_zero : t -> t = lift1 ItvPure . prune_zero
let prune_comp : Binop . t -> t -> t -> t = fun comp -> lift2_opt ( ItvPure . prune_comp comp )