@ -42,9 +42,9 @@ module SymLinear = struct
let le : t -> t -> bool =
let le : t -> t -> bool =
fun x y ->
fun 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_ int v1_opt in
let v1 = NonZeroInt . opt_to_ big_ int v1_opt in
let v2 = NonZeroInt . opt_to_ int v2_opt in
let v2 = NonZeroInt . opt_to_ big_ int v2_opt in
Int. equal v1 v2 | | ( Symb . Symbol . is_unsigned s && v1 < = v2 )
Z. ( equal v1 v2 ) | | ( Symb . Symbol . is_unsigned s && v1 < = v2 )
in
in
M . for_all2 ~ f : le_one_pair x y
M . for_all2 ~ f : le_one_pair x y
@ -64,17 +64,17 @@ module SymLinear = struct
let eq : t -> t -> bool =
let eq : t -> t -> bool =
fun x y ->
fun x y ->
let eq_pair _ ( coeff1 : NonZeroInt . t option ) ( coeff2 : NonZeroInt . t option ) =
let eq_pair _ ( coeff1 : NonZeroInt . t option ) ( coeff2 : NonZeroInt . t option ) =
[ % compare . equal : int option ] ( coeff1 :> int option ) ( coeff2 :> in t option )
[ % compare . equal : Z . t option ] ( coeff1 :> Z . t option ) ( coeff2 :> Z . t option )
in
in
M . for_all2 ~ f : eq_pair x y
M . for_all2 ~ f : eq_pair x y
let pp1 : F . formatter -> Symb . Symbol . t * NonZeroInt . t -> unit =
let pp1 : F . formatter -> Symb . Symbol . t * NonZeroInt . t -> unit =
fun fmt ( s , c ) ->
fun fmt ( s , c ) ->
let c = ( c :> in t) in
let c = ( c :> Z . t) in
if Int. equal c 1 then Symb . Symbol . pp fmt s
if Z. ( equal c one ) then Symb . Symbol . pp fmt s
else if Int. equal c ( - 1 ) then F . fprintf fmt " -%a " Symb . Symbol . pp s
else if Z. ( equal c minus_one ) then F . fprintf fmt " -%a " Symb . Symbol . pp s
else F . fprintf fmt " % dx%a" c Symb . Symbol . pp s
else F . fprintf fmt " % ax%a" Z . pp_print c Symb . Symbol . pp s
let pp : F . formatter -> t -> unit =
let pp : F . formatter -> t -> unit =
@ -106,7 +106,7 @@ module SymLinear = struct
let one_symbol_of_coeff : NonZeroInt . t -> t -> Symb . Symbol . t option =
let one_symbol_of_coeff : NonZeroInt . t -> t -> Symb . Symbol . t option =
fun coeff x ->
fun coeff x ->
match M . is_singleton x with
match M . is_singleton x with
| Some ( k , v ) when Int. equal ( v :> int ) ( coeff :> in t) ->
| Some ( k , v ) when Z. equal ( v :> Z . t ) ( coeff :> Z . t) ->
Some k
Some k
| _ ->
| _ ->
None
None
@ -153,9 +153,9 @@ module SymLinear = struct
(* we can give integer bounds ( obviously 0 ) only when all symbols are unsigned *)
(* we can give integer bounds ( obviously 0 ) only when all symbols are unsigned *)
let int_lb x = if is_ge_zero x then Some 0 else None
let big_ int_lb x = if is_ge_zero x then Some Z . zero else None
let int_ub x = if is_le_zero x then Some 0 else None
let big_ int_ub x = if is_le_zero x then Some Z . zero else None
(* * When two following symbols are from the same path, simplify what would lead to a zero sum. E.g. 2 * x.lb - x.ub = x.lb *)
(* * When two following symbols are from the same path, simplify what would lead to a zero sum. E.g. 2 * x.lb - x.ub = x.lb *)
let simplify_bound_ends_from_paths : t -> t =
let simplify_bound_ends_from_paths : t -> t =
@ -198,7 +198,7 @@ module Bound = struct
let neg = function Plus -> Minus | Minus -> Plus
let neg = function Plus -> Minus | Minus -> Plus
let eval_ int x i1 i2 = match x with Plus -> i1 + i2 | Minus -> i1 - i2
let eval_ big_ int x i1 i2 = match x with Plus -> Z . ( i1 + i2 ) | Minus -> Z . ( i1 - i2 )
let pp ~ need_plus : F . formatter -> t -> unit =
let pp ~ need_plus : F . formatter -> t -> unit =
fun fmt -> function
fun fmt -> function
@ -217,7 +217,7 @@ module Bound = struct
let neg = function Min -> Max | Max -> Min
let neg = function Min -> Max | Max -> Min
let eval_ int x i1 i2 = match x with Min -> min i1 i2 | Max -> max i1 i2
let eval_ big_ int x i1 i2 = match x with Min -> Z . min i1 i2 | Max -> Z . max i1 i2
let pp : F . formatter -> t -> unit =
let pp : F . formatter -> t -> unit =
fun fmt -> function Min -> F . pp_print_string fmt " min " | Max -> F . pp_print_string fmt " max "
fun fmt -> function Min -> F . pp_print_string fmt " min " | Max -> F . pp_print_string fmt " max "
@ -227,8 +227,8 @@ module Bound = struct
e . g . ` MinMax ( 1 , Minus , Max , 2 , s ) ` means " 1 - max (2, s) " . * )
e . g . ` MinMax ( 1 , Minus , Max , 2 , s ) ` means " 1 - max (2, s) " . * )
type t =
type t =
| MInf
| MInf
| Linear of in t * SymLinear . t
| Linear of Z . t * SymLinear . t
| MinMax of in t * Sign . t * MinMax . t * in t * Symb . Symbol . t
| MinMax of Z . t * Sign . t * MinMax . t * Z . t * Symb . Symbol . t
| PInf
| PInf
[ @@ deriving compare ]
[ @@ deriving compare ]
@ -241,24 +241,26 @@ module Bound = struct
| PInf ->
| PInf ->
F . pp_print_string fmt " +oo "
F . pp_print_string fmt " +oo "
| Linear ( c , x ) ->
| Linear ( c , x ) ->
if SymLinear . is_zero x then F. pp_print_ int fmt c
if SymLinear . is_zero x then Z. pp_pr int fmt c
else if Int. equal c 0 then SymLinear . pp fmt x
else if Z. ( equal c zero ) then SymLinear . pp fmt x
else F . fprintf fmt " %a + % d " SymLinear . pp x c
else F . fprintf fmt " %a + % a " SymLinear . pp x Z . pp_print c
| MinMax ( c , sign , m , d , x ) ->
| MinMax ( c , sign , m , d , x ) ->
if Int. equal c 0 then ( Sign . pp ~ need_plus : false ) fmt sign
if Z. ( equal c zero ) then ( Sign . pp ~ need_plus : false ) fmt sign
else F . fprintf fmt " % d%a" c ( Sign . pp ~ need_plus : true ) sign ;
else F . fprintf fmt " % a%a" Z . pp_print c ( Sign . pp ~ need_plus : true ) sign ;
F . fprintf fmt " %a(% d , %a)" MinMax . pp m d Symb . Symbol . pp x
F . fprintf fmt " %a(% a , %a)" MinMax . pp m Z . pp_print d Symb . Symbol . pp x
let of_bound_end = function Symb . BoundEnd . LowerBound -> MInf | Symb . BoundEnd . UpperBound -> PInf
let of_bound_end = function Symb . BoundEnd . LowerBound -> MInf | Symb . BoundEnd . UpperBound -> PInf
let of_int : int -> t = fun n -> Linear ( n , SymLinear . empty )
let of_int : int -> t = fun n -> Linear ( Z . of_int n , SymLinear . empty )
let of_big_int : Z . t -> t = fun n -> Linear ( n , SymLinear . empty )
let minus_one = of_int ( - 1 )
let minus_one = of_int ( - 1 )
let _ 255 = of_int 255
let _ 255 = of_int 255
let of_sym : SymLinear . t -> t = fun s -> Linear ( 0 , s )
let of_sym : SymLinear . t -> t = fun s -> Linear ( Z . zero , s )
let is_symbolic : t -> bool = function
let is_symbolic : t -> bool = function
| MInf | PInf ->
| MInf | PInf ->
@ -270,7 +272,7 @@ module Bound = struct
let lift_symlinear : ( SymLinear . t -> ' a option ) -> t -> ' a option =
let lift_symlinear : ( SymLinear . t -> ' a option ) -> t -> ' a option =
fun f -> function Linear ( 0 , se ) -> f se | _ -> None
fun f -> function Linear ( n , se ) when Z . ( equal n zero ) -> f se | _ -> None
let get_one_symbol_opt : t -> Symb . Symbol . t option = lift_symlinear SymLinear . get_one_symbol_opt
let get_one_symbol_opt : t -> Symb . Symbol . t option = lift_symlinear SymLinear . get_one_symbol_opt
@ -292,10 +294,10 @@ module Bound = struct
let is_mone_symbol : t -> bool = fun x -> get_mone_symbol_opt x < > None
let is_mone_symbol : t -> bool = fun x -> get_mone_symbol_opt x < > None
let mk_MinMax ( c , sign , m , d , s ) =
let mk_MinMax ( c , sign , m , d , s ) =
if Symb . Symbol . is_unsigned s && d < = 0 then
if Symb . Symbol . is_unsigned s && Z . ( d < = zero ) then
match m with
match m with
| Min ->
| Min ->
of_ int ( Sign . eval _int sign c d )
of_ big_ int ( Sign . eval _big _int sign c d )
| Max -> (
| Max -> (
match sign with
match sign with
| Plus ->
| Plus ->
@ -305,59 +307,59 @@ module Bound = struct
else MinMax ( c , sign , m , d , s )
else MinMax ( c , sign , m , d , s )
let int_ub_of_minmax = function
let big_ int_ub_of_minmax = function
| MinMax ( c , Plus , Min , d , _ ) ->
| MinMax ( c , Plus , Min , d , _ ) ->
Some ( c + d )
Some Z . ( c + d )
| MinMax ( c , Minus , Max , d , s ) when Symb . Symbol . is_unsigned s ->
| MinMax ( c , Minus , Max , d , s ) when Symb . Symbol . is_unsigned s ->
Some ( min c ( c - d ) )
Some Z . ( min c ( c - d ) )
| MinMax ( c , Minus , Max , d , _ ) ->
| MinMax ( c , Minus , Max , d , _ ) ->
Some ( c - d )
Some Z . ( c - d )
| MinMax _ ->
| MinMax _ ->
None
None
| MInf | PInf | Linear _ ->
| MInf | PInf | Linear _ ->
assert false
assert false
let int_lb_of_minmax = function
let big_ int_lb_of_minmax = function
| MinMax ( c , Plus , Max , d , s ) when Symb . Symbol . is_unsigned s ->
| MinMax ( c , Plus , Max , d , s ) when Symb . Symbol . is_unsigned s ->
Some ( max c ( c + d ) )
Some Z . ( max c ( c + d ) )
| MinMax ( c , Plus , Max , d , _ ) ->
| MinMax ( c , Plus , Max , d , _ ) ->
Some ( c + d )
Some Z . ( c + d )
| MinMax ( c , Minus , Min , d , _ ) ->
| MinMax ( c , Minus , Min , d , _ ) ->
Some ( c - d )
Some Z . ( c - d )
| MinMax _ ->
| MinMax _ ->
None
None
| MInf | PInf | Linear _ ->
| MInf | PInf | Linear _ ->
assert false
assert false
let int_of_minmax = function
let big_ int_of_minmax = function
| Symb . BoundEnd . LowerBound ->
| Symb . BoundEnd . LowerBound ->
int_lb_of_minmax
big_ int_lb_of_minmax
| Symb . BoundEnd . UpperBound ->
| Symb . BoundEnd . UpperBound ->
int_ub_of_minmax
big_ int_ub_of_minmax
let int_lb = function
let big_ int_lb = function
| MInf ->
| MInf ->
None
None
| PInf ->
| PInf ->
assert false
assert false
| MinMax _ as b ->
| MinMax _ as b ->
int_lb_of_minmax b
big_ int_lb_of_minmax b
| Linear ( c , se ) ->
| Linear ( c , se ) ->
SymLinear . int_lb se | > Option . map ~ f : ( ( + ) c )
SymLinear . big_ int_lb se | > Option . map ~ f : ( Z . ( + ) c )
let int_ub = function
let big_ int_ub = function
| MInf ->
| MInf ->
assert false
assert false
| PInf ->
| PInf ->
None
None
| MinMax _ as b ->
| MinMax _ as b ->
int_ub_of_minmax b
big_ int_ub_of_minmax b
| Linear ( c , se ) ->
| Linear ( c , se ) ->
SymLinear . int_ub se | > Option . map ~ f : ( ( + ) c )
SymLinear . big_ int_ub se | > Option . map ~ f : ( Z . ( + ) c )
let linear_ub_of_minmax = function
let linear_ub_of_minmax = function
@ -383,7 +385,11 @@ module Bound = struct
let le_minmax_by_int x y =
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
match ( big_int_ub_of_minmax x , big_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_opt1 le opt_n m = Option . value_map opt_n ~ default : false ~ f : ( fun n -> le n m )
@ -401,17 +407,17 @@ module Bound = struct
c0 < = c1 && SymLinear . le x0 x1
c0 < = c1 && SymLinear . le x0 x1
| MinMax ( c1 , sign1 , m1 , d1 , x1 ) , MinMax ( c2 , sign2 , m2 , d2 , x2 )
| MinMax ( c1 , sign1 , m1 , d1 , x1 ) , MinMax ( c2 , sign2 , m2 , d2 , x2 )
when Sign . equal sign1 sign2 && MinMax . equal m1 m2 ->
when Sign . equal sign1 sign2 && MinMax . equal m1 m2 ->
c1 < = c2 && Int . equal d1 d2 && Symb . Symbol . equal x1 x2
c1 < = c2 && Z . equal d1 d2 && Symb . Symbol . equal x1 x2
| MinMax _ , MinMax _ when le_minmax_by_int x y ->
| MinMax _ , MinMax _ when le_minmax_by_int x y ->
true
true
| MinMax ( c1 , Plus , Min , _ , x1 ) , MinMax ( c2 , Plus , Max , _ , x2 )
| MinMax ( c1 , Plus , Min , _ , x1 ) , MinMax ( c2 , Plus , Max , _ , x2 )
| MinMax ( c1 , Minus , Max , _ , x1 ) , MinMax ( c2 , Minus , Min , _ , x2 ) ->
| MinMax ( c1 , Minus , Max , _ , x1 ) , MinMax ( c2 , Minus , Min , _ , x2 ) ->
c1 < = c2 && Symb . Symbol . equal x1 x2
c1 < = c2 && Symb . Symbol . equal x1 x2
| MinMax _ , Linear ( c , se ) ->
| MinMax _ , Linear ( c , se ) ->
( SymLinear . is_ge_zero se && le_opt1 Int. ( < = ) ( int_ub_of_minmax x ) c )
( SymLinear . is_ge_zero se && le_opt1 Z. leq ( big_ int_ub_of_minmax x ) c )
| | le_opt1 le ( linear_ub_of_minmax x ) y
| | le_opt1 le ( linear_ub_of_minmax x ) y
| Linear ( c , se ) , MinMax _ ->
| Linear ( c , se ) , MinMax _ ->
( SymLinear . is_le_zero se && le_opt2 Int. ( < = ) c ( int_lb_of_minmax y ) )
( SymLinear . is_le_zero se && le_opt2 Z. leq c ( big_ int_lb_of_minmax y ) )
| | le_opt2 le x ( linear_lb_of_minmax y )
| | le_opt2 le x ( linear_lb_of_minmax y )
| _ , _ ->
| _ , _ ->
false
false
@ -423,9 +429,9 @@ module Bound = struct
| MInf , Linear _ | MInf , MinMax _ | MInf , PInf | Linear _ , PInf | MinMax _ , PInf ->
| MInf , Linear _ | MInf , MinMax _ | MInf , PInf | Linear _ , PInf | MinMax _ , PInf ->
true
true
| Linear ( c , x ) , _ ->
| Linear ( c , x ) , _ ->
le ( Linear ( c + 1 , x ) ) y
le ( Linear ( Z . succ c , x ) ) y
| MinMax ( c , sign , min_max , d , x ) , _ ->
| MinMax ( c , sign , min_max , d , x ) , _ ->
le ( mk_MinMax ( c + 1 , sign , min_max , d , x ) ) y
le ( mk_MinMax ( Z . succ c , sign , min_max , d , x ) ) y
| _ , _ ->
| _ , _ ->
false
false
@ -454,31 +460,31 @@ module Bound = struct
else
else
match ( x , y ) with
match ( x , y ) with
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_zero x1 && SymLinear . is_one_symbol x2 ->
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_zero x1 && SymLinear . is_one_symbol x2 ->
mk_MinMax ( c2 , Plus , Min , c1 - c2 , SymLinear . get_one_symbol x2 )
mk_MinMax ( c2 , Plus , Min , Z . ( c1 - c2 ) , SymLinear . get_one_symbol x2 )
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_one_symbol x1 && SymLinear . is_zero x2 ->
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_one_symbol x1 && SymLinear . is_zero x2 ->
mk_MinMax ( c1 , Plus , Min , c2 - c1 , SymLinear . get_one_symbol x1 )
mk_MinMax ( c1 , Plus , Min , Z . ( c2 - c1 ) , SymLinear . get_one_symbol x1 )
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_zero x1 && SymLinear . is_mone_symbol x2
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_zero x1 && SymLinear . is_mone_symbol x2
->
->
mk_MinMax ( c2 , Minus , Max , c2 - c1 , SymLinear . get_mone_symbol x2 )
mk_MinMax ( c2 , Minus , Max , Z . ( c2 - c1 ) , SymLinear . get_mone_symbol x2 )
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_mone_symbol x1 && SymLinear . is_zero x2
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_mone_symbol x1 && SymLinear . is_zero x2
->
->
mk_MinMax ( c1 , Minus , Max , c1 - c2 , SymLinear . get_mone_symbol x1 )
mk_MinMax ( c1 , Minus , Max , Z . ( c1 - c2 ) , SymLinear . get_mone_symbol x1 )
| MinMax ( c1 , Plus , Min , d1 , s ) , Linear ( c2 , se )
| MinMax ( c1 , Plus , Min , d1 , s ) , Linear ( c2 , se )
| Linear ( c2 , se ) , MinMax ( c1 , Plus , Min , d1 , s )
| Linear ( c2 , se ) , MinMax ( c1 , Plus , Min , d1 , s )
when SymLinear . is_zero se ->
when SymLinear . is_zero se ->
mk_MinMax ( c1 , Plus , Min , min d1 ( c2 - c1 ) , s )
mk_MinMax ( c1 , Plus , Min , Z . ( min d1 ( c2 - c1 ) ) , s )
| MinMax ( c1 , Plus , Max , _ , s ) , Linear ( c2 , se )
| MinMax ( c1 , Plus , Max , _ , s ) , Linear ( c2 , se )
| Linear ( c2 , se ) , MinMax ( c1 , Plus , Max , _ , s )
| Linear ( c2 , se ) , MinMax ( c1 , Plus , Max , _ , s )
when SymLinear . is_zero se ->
when SymLinear . is_zero se ->
mk_MinMax ( c1 , Plus , Min , c2 - c1 , s )
mk_MinMax ( c1 , Plus , Min , Z . ( c2 - c1 ) , s )
| MinMax ( c1 , Minus , Min , _ , s ) , Linear ( c2 , se )
| MinMax ( c1 , Minus , Min , _ , s ) , Linear ( c2 , se )
| Linear ( c2 , se ) , MinMax ( c1 , Minus , Min , _ , s )
| Linear ( c2 , se ) , MinMax ( c1 , Minus , Min , _ , s )
when SymLinear . is_zero se ->
when SymLinear . is_zero se ->
mk_MinMax ( c1 , Minus , Max , c1 - c2 , s )
mk_MinMax ( c1 , Minus , Max , Z . ( c1 - c2 ) , s )
| MinMax ( c1 , Minus , Max , d1 , s ) , Linear ( c2 , se )
| MinMax ( c1 , Minus , Max , d1 , s ) , Linear ( c2 , se )
| Linear ( c2 , se ) , MinMax ( c1 , Minus , Max , d1 , s )
| Linear ( c2 , se ) , MinMax ( c1 , Minus , Max , d1 , s )
when SymLinear . is_zero se ->
when SymLinear . is_zero se ->
mk_MinMax ( c1 , Minus , Max , max d1 ( c1 - c2 ) , s )
mk_MinMax ( c1 , Minus , Max , Z . ( max d1 ( c1 - c2 ) ) , s )
| MinMax ( _ , Plus , Min , _ , _ ) , MinMax ( _ , Plus , Max , _ , _ )
| MinMax ( _ , Plus , Min , _ , _ ) , MinMax ( _ , Plus , Max , _ , _ )
| MinMax ( _ , Plus , Min , _ , _ ) , MinMax ( _ , Minus , Min , _ , _ )
| MinMax ( _ , Plus , Min , _ , _ ) , MinMax ( _ , Minus , Min , _ , _ )
| MinMax ( _ , Minus , Max , _ , _ ) , MinMax ( _ , Plus , Max , _ , _ )
| MinMax ( _ , Minus , Max , _ , _ ) , MinMax ( _ , Plus , Max , _ , _ )
@ -490,7 +496,7 @@ module Bound = struct
| MinMax ( _ , Minus , Min , _ , _ ) , MinMax ( _ , Minus , Max , _ , _ ) ->
| MinMax ( _ , Minus , Min , _ , _ ) , MinMax ( _ , Minus , Max , _ , _ ) ->
lb ~ default ( remove_max_int x ) y
lb ~ default ( remove_max_int x ) y
| MinMax ( c1 , Plus , Max , d1 , _ ) , MinMax ( c2 , Plus , Max , d2 , _ ) ->
| MinMax ( c1 , Plus , Max , d1 , _ ) , MinMax ( c2 , Plus , Max , d2 , _ ) ->
Linear ( min ( c1 + d1 ) ( c2 + d2 ) , SymLinear . zero )
Linear ( Z . ( min ( c1 + d1 ) ( c2 + d2 ) ) , SymLinear . zero )
| _ , _ ->
| _ , _ ->
default
default
@ -513,15 +519,15 @@ module Bound = struct
else
else
match ( x , y ) with
match ( x , y ) with
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_zero x1 && SymLinear . is_one_symbol x2 ->
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_zero x1 && SymLinear . is_one_symbol x2 ->
mk_MinMax ( c2 , Plus , Max , c1 - c2 , SymLinear . get_one_symbol x2 )
mk_MinMax ( c2 , Plus , Max , Z . ( c1 - c2 ) , SymLinear . get_one_symbol x2 )
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_one_symbol x1 && SymLinear . is_zero x2 ->
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_one_symbol x1 && SymLinear . is_zero x2 ->
mk_MinMax ( c1 , Plus , Max , c2 - c1 , SymLinear . get_one_symbol x1 )
mk_MinMax ( c1 , Plus , Max , Z . ( c2 - c1 ) , SymLinear . get_one_symbol x1 )
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_zero x1 && SymLinear . is_mone_symbol x2
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_zero x1 && SymLinear . is_mone_symbol x2
->
->
mk_MinMax ( c2 , Minus , Min , c2 - c1 , SymLinear . get_mone_symbol x2 )
mk_MinMax ( c2 , Minus , Min , Z . ( c2 - c1 ) , SymLinear . get_mone_symbol x2 )
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_mone_symbol x1 && SymLinear . is_zero x2
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) when SymLinear . is_mone_symbol x1 && SymLinear . is_zero x2
->
->
mk_MinMax ( c1 , Minus , Min , c1 - c2 , SymLinear . get_mone_symbol x1 )
mk_MinMax ( c1 , Minus , Min , Z . ( c1 - c2 ) , SymLinear . get_mone_symbol x1 )
| _ , _ ->
| _ , _ ->
default
default
@ -534,10 +540,10 @@ module Bound = struct
| PInf , _ | _ , PInf ->
| PInf , _ | _ , PInf ->
L . ( die InternalError ) " Lower bound cannot be +oo. "
L . ( die InternalError ) " Lower bound cannot be +oo. "
| MinMax ( n1 , Plus , Max , _ , s1 ) , Linear ( n2 , s2 )
| MinMax ( n1 , Plus , Max , _ , s1 ) , Linear ( n2 , s2 )
when Int . equal n1 n2 && SymLinear . is_one_symbol_of s1 s2 ->
when Z . equal n1 n2 && SymLinear . is_one_symbol_of s1 s2 ->
y
y
| MinMax ( n1 , Minus , Min , _ , s1 ) , Linear ( n2 , s2 )
| MinMax ( n1 , Minus , Min , _ , s1 ) , Linear ( n2 , s2 )
when Int . equal n1 n2 && SymLinear . is_mone_symbol_of s1 s2 ->
when Z . equal n1 n2 && SymLinear . is_mone_symbol_of s1 s2 ->
y
y
| _ ->
| _ ->
if le x y then x else MInf
if le x y then x else MInf
@ -549,28 +555,28 @@ module Bound = struct
| MInf , _ | _ , MInf ->
| MInf , _ | _ , MInf ->
L . ( die InternalError ) " Upper bound cannot be -oo. "
L . ( die InternalError ) " Upper bound cannot be -oo. "
| MinMax ( n1 , Plus , Min , _ , s1 ) , Linear ( n2 , s2 )
| MinMax ( n1 , Plus , Min , _ , s1 ) , Linear ( n2 , s2 )
when Int . equal n1 n2 && SymLinear . is_one_symbol_of s1 s2 ->
when Z . equal n1 n2 && SymLinear . is_one_symbol_of s1 s2 ->
y
y
| MinMax ( n1 , Minus , Max , _ , s1 ) , Linear ( n2 , s2 )
| MinMax ( n1 , Minus , Max , _ , s1 ) , Linear ( n2 , s2 )
when Int . equal n1 n2 && SymLinear . is_mone_symbol_of s1 s2 ->
when Z . equal n1 n2 && SymLinear . is_mone_symbol_of s1 s2 ->
y
y
| _ ->
| _ ->
if le y x then x else PInf
if le y x then x else PInf
let zero : t = Linear ( 0 , SymLinear . zero )
let zero : t = Linear ( Z . zero , SymLinear . zero )
let one : t = Linear ( 1 , SymLinear . zero )
let one : t = Linear ( Z . one , SymLinear . zero )
let mone : t = Linear ( - 1 , SymLinear . zero )
let mone : t = Linear ( Z . minus_one , SymLinear . zero )
let is_some_const : in t -> t -> bool =
let is_some_const : Z . t -> t -> bool =
fun c x -> match x with Linear ( c' , y ) -> Int . equal c c' && SymLinear . is_zero y | _ -> false
fun c x -> match x with Linear ( c' , y ) -> Z . equal c c' && SymLinear . is_zero y | _ -> false
let is_zero : t -> bool = is_some_const 0
let is_zero : t -> bool = is_some_const Z . zero
let is_const : t -> in t option =
let is_const : t -> Z . t option =
fun x -> match x with Linear ( c , y ) when SymLinear . is_zero y -> Some c | _ -> None
fun x -> match x with Linear ( c , y ) when SymLinear . is_zero y -> Some c | _ -> None
@ -582,11 +588,11 @@ module Bound = struct
| _ , _ when is_zero y ->
| _ , _ when is_zero y ->
x
x
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) ->
| Linear ( c1 , x1 ) , Linear ( c2 , x2 ) ->
Linear ( 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 )
| Linear ( c2 , x2 ) , MinMax ( c1 , sign , min_max , d1 , x1 )
| Linear ( c2 , x2 ) , MinMax ( c1 , sign , min_max , d1 , x1 )
when SymLinear . is_zero x2 ->
when SymLinear . is_zero x2 ->
mk_MinMax ( c1 + c2 , sign , min_max , d1 , x1 )
mk_MinMax ( Z . ( c1 + c2 ) , sign , min_max , d1 , x1 )
| _ ->
| _ ->
f x y
f x y
@ -596,10 +602,10 @@ module Bound = struct
match ( x , y ) with
match ( x , y ) with
| MinMax ( c1 , Plus , Max , d1 , _ ) , Linear ( c2 , x2 )
| MinMax ( c1 , Plus , Max , d1 , _ ) , Linear ( c2 , x2 )
| Linear ( c2 , x2 ) , MinMax ( c1 , Plus , Max , d1 , _ ) ->
| Linear ( c2 , x2 ) , MinMax ( c1 , Plus , Max , d1 , _ ) ->
Linear ( c1 + d1 + c2 , x2 )
Linear ( Z . ( c1 + d1 + c2 ) , x2 )
| MinMax ( c1 , Minus , Min , d1 , _ ) , Linear ( c2 , x2 )
| MinMax ( c1 , Minus , Min , d1 , _ ) , Linear ( c2 , x2 )
| Linear ( c2 , x2 ) , MinMax ( c1 , Minus , Min , d1 , _ ) ->
| Linear ( c2 , x2 ) , MinMax ( c1 , Minus , Min , d1 , _ ) ->
Linear ( c1 - d1 + c2 , x2 )
Linear ( Z . ( c1 - d1 + c2 ) , x2 )
| _ , _ ->
| _ , _ ->
MInf )
MInf )
@ -609,10 +615,10 @@ module Bound = struct
match ( x , y ) with
match ( x , y ) with
| MinMax ( c1 , Plus , Min , d1 , _ ) , Linear ( c2 , x2 )
| MinMax ( c1 , Plus , Min , d1 , _ ) , Linear ( c2 , x2 )
| Linear ( c2 , x2 ) , MinMax ( c1 , Plus , Min , d1 , _ ) ->
| Linear ( c2 , x2 ) , MinMax ( c1 , Plus , Min , d1 , _ ) ->
Linear ( c1 + d1 + c2 , x2 )
Linear ( Z . ( c1 + d1 + c2 ) , x2 )
| MinMax ( c1 , Minus , Max , d1 , _ ) , Linear ( c2 , x2 )
| MinMax ( c1 , Minus , Max , d1 , _ ) , Linear ( c2 , x2 )
| Linear ( c2 , x2 ) , MinMax ( c1 , Minus , Max , d1 , _ ) ->
| Linear ( c2 , x2 ) , MinMax ( c1 , Minus , Max , d1 , _ ) ->
Linear ( c1 - d1 + c2 , x2 )
Linear ( Z . ( c1 - d1 + c2 ) , x2 )
| _ , _ ->
| _ , _ ->
PInf )
PInf )
@ -627,15 +633,19 @@ module Bound = struct
| PInf ->
| PInf ->
if NonZeroInt . is_positive n then PInf else MInf
if NonZeroInt . is_positive n then PInf else MInf
| Linear ( c , x' ) ->
| Linear ( c , x' ) ->
Linear ( c * ( n :> int ) , SymLinear . mult_const n x' )
Linear ( Z . ( c * ( n :> Z . t ) ) , SymLinear . mult_const n x' )
| MinMax _ -> (
| MinMax _ -> (
let int_bound =
let int_bound =
let bound_end' =
let bound_end' =
if NonZeroInt . is_positive n then bound_end else Symb . BoundEnd . neg bound_end
if NonZeroInt . is_positive n then bound_end else Symb . BoundEnd . neg bound_end
in
in
int_of_minmax bound_end' x
big_ int_of_minmax bound_end' x
in
in
match int_bound with Some i -> of_int ( i * ( n :> int ) ) | None -> of_bound_end bound_end )
match int_bound with
| Some i ->
of_big_int Z . ( i * ( n :> Z . t ) )
| None ->
of_bound_end bound_end )
let mult_const_l = mult_const Symb . BoundEnd . LowerBound
let mult_const_l = mult_const Symb . BoundEnd . LowerBound
@ -648,9 +658,9 @@ module Bound = struct
| PInf ->
| PInf ->
MInf
MInf
| Linear ( c , x ) ->
| Linear ( c , x ) ->
Linear ( - c , SymLinear . neg x )
Linear ( Z . neg c , SymLinear . neg x )
| MinMax ( c , sign , min_max , d , x ) ->
| MinMax ( c , sign , min_max , d , x ) ->
mk_MinMax ( - c , Sign . neg sign , min_max , d , x )
mk_MinMax ( Z . neg c , Sign . neg sign , min_max , d , x )
let div_const : t -> NonZeroInt . t -> t option =
let div_const : t -> NonZeroInt . t -> t option =
@ -663,7 +673,7 @@ module Bound = struct
| Linear ( c , x' ) when NonZeroInt . is_multiple c n -> (
| Linear ( c , x' ) when NonZeroInt . is_multiple c n -> (
match SymLinear . exact_div_const_exn x' n with
match SymLinear . exact_div_const_exn x' n with
| x'' ->
| x'' ->
Some ( Linear ( c / ( n :> int ) , x'' ) )
Some ( Linear ( Z . ( c / ( n :> Z . t ) ) , x'' ) )
| exception NonZeroInt . DivisionNotExact ->
| exception NonZeroInt . DivisionNotExact ->
None )
None )
| _ ->
| _ ->
@ -738,13 +748,13 @@ module Bound = struct
NonBottom x
NonBottom x
| Linear ( c , se ) ->
| Linear ( c , se ) ->
SymLinear . fold se
SymLinear . fold se
~ init : ( NonBottom ( of_ 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 ) )
| MinMax ( c , sign , min_max , d , s ) -> (
| MinMax ( c , sign , min_max , d , s ) -> (
match get s with
match get s with
| Bottom ->
| Bottom ->
Option . value_map ( int_of_minmax subst_pos x ) ~ default : Bottom ~ f : ( fun i ->
Option . value_map ( big_ int_of_minmax subst_pos x ) ~ default : Bottom ~ f : ( fun i ->
NonBottom ( of_ int i ) )
NonBottom ( of_ big_ int i ) )
| NonBottom x' ->
| NonBottom x' ->
let res =
let res =
match ( sign , min_max , x' ) with
match ( sign , min_max , x' ) with
@ -753,44 +763,48 @@ module Bound = struct
| Plus , Max , PInf | Minus , Min , MInf ->
| Plus , Max , PInf | Minus , Min , MInf ->
PInf
PInf
| sign , Min , PInf | sign , Max , MInf ->
| sign , Min , PInf | sign , Max , MInf ->
of_ int ( Sign . eval _int sign c d )
of_ big_ int ( Sign . eval _big _int sign c d )
| _ , _ , Linear ( c2 , se ) -> (
| _ , _ , Linear ( c2 , se ) -> (
if SymLinear . is_zero se then
if SymLinear . is_zero se then
of_ int ( Sign . eval _int sign c ( MinMax . eval _int min_max d c2 ) )
of_ big_ int ( Sign . eval _big _int sign c ( MinMax . eval _big _int min_max d c2 ) )
else if SymLinear . is_one_symbol se then
else if SymLinear . is_one_symbol se then
mk_MinMax
mk_MinMax
( Sign . eval_int sign c c2 , sign , min_max , d - c2 , SymLinear . get_one_symbol se )
( Sign . eval_big_int sign c c2
, sign
, min_max
, Z . ( d - c2 )
, SymLinear . get_one_symbol se )
else if SymLinear . is_mone_symbol se then
else if SymLinear . is_mone_symbol se then
mk_MinMax
mk_MinMax
( Sign . eval_int sign c c2
( Sign . eval_ big_ int sign c c2
, Sign . neg sign
, Sign . neg sign
, MinMax . neg min_max
, MinMax . neg min_max
, c2 - d
, Z . ( c2 - d )
, SymLinear . get_mone_symbol se )
, SymLinear . get_mone_symbol se )
else
else
match int_of_minmax subst_pos x with
match big_ int_of_minmax subst_pos x with
| Some i ->
| Some i ->
of_ int i
of_ big_ int i
| None ->
| None ->
of_bound_end subst_pos )
of_bound_end subst_pos )
| _ , _ , MinMax ( c2 , sign2 , min_max2 , d2 , s2 ) -> (
| _ , _ , MinMax ( c2 , sign2 , min_max2 , d2 , s2 ) -> (
match ( min_max , sign2 , min_max2 ) with
match ( min_max , sign2 , min_max2 ) with
| Min , Plus , Min | Max , Plus , Max ->
| Min , Plus , Min | Max , Plus , Max ->
let c' = Sign . eval_ int sign c c2 in
let c' = Sign . eval_ big_ int sign c c2 in
let d' = MinMax . eval_ int min_max ( d - c2 ) d2 in
let d' = MinMax . eval_ big_ int min_max Z . ( d - c2 ) d2 in
mk_MinMax ( c' , sign , min_max , d' , s2 )
mk_MinMax ( c' , sign , min_max , d' , s2 )
| Min , Minus , Max | Max , Minus , Min ->
| Min , Minus , Max | Max , Minus , Min ->
let c' = Sign . eval_ int sign c c2 in
let c' = Sign . eval_ big_ int sign c c2 in
let d' = MinMax . eval_ int min_max2 ( c2 - d ) d2 in
let d' = MinMax . eval_ big_ int min_max2 Z . ( c2 - d ) d2 in
mk_MinMax ( c' , Sign . neg sign , min_max2 , d' , s2 )
mk_MinMax ( c' , Sign . neg sign , min_max2 , d' , s2 )
| _ ->
| _ ->
let bound_end =
let bound_end =
match sign with Plus -> subst_pos | Minus -> Symb . BoundEnd . neg subst_pos
match sign with Plus -> subst_pos | Minus -> Symb . BoundEnd . neg subst_pos
in
in
of_ int
of_ big_ int
( Sign . eval_ int sign c
( Sign . eval_ big_ int sign c
( MinMax . eval_ int min_max d
( MinMax . eval_ big_ int min_max d
( int_of_minmax bound_end x' | > Option . value ~ default : d ) ) ) )
( big_ int_of_minmax bound_end x' | > Option . value ~ default : d ) ) ) )
in
in
NonBottom res )
NonBottom res )
@ -810,7 +824,7 @@ module Bound = struct
let is_same_symbol b1 b2 =
let is_same_symbol b1 b2 =
match ( b1 , b2 ) with
match ( b1 , b2 ) with
| Linear ( 0 , se1 ) , Linear ( 0 , se2 ) ->
| Linear ( n1 , se1 ) , Linear ( n2 , se2 ) when Z . ( equal n1 zero ) && Z . ( equal n2 zero ) ->
SymLinear . is_same_symbol se1 se2
SymLinear . is_same_symbol se1 se2
| _ ->
| _ ->
None
None
@ -836,5 +850,5 @@ module NonNegativeBound = struct
| None ->
| None ->
Symbolic b
Symbolic b
| Some c ->
| Some c ->
Constant ( NonNegativeInt . of_ int_exn c ) )
Constant ( NonNegativeInt . of_ big_ int_exn c ) )
end
end