From b9c9f7177b92b59ef942a26a6c0a83aef68089c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20B=C3=BChler?= <david.buhler@cea.fr> Date: Thu, 31 Jan 2019 17:02:00 +0100 Subject: [PATCH] [Ival] Comments int_set and int_interval. --- .../abstract_interp/int_interval.ml | 4 +- .../abstract_interp/int_interval.mli | 33 ++++++++--- .../abstract_interp/int_set.ml | 4 +- .../abstract_interp/int_set.mli | 55 +++++++++++++++---- .../abstract_interp/int_val.ml | 2 +- 5 files changed, 75 insertions(+), 23 deletions(-) diff --git a/src/kernel_services/abstract_interp/int_interval.ml b/src/kernel_services/abstract_interp/int_interval.ml index 0453c1260a7..cb8d0a9c2ba 100644 --- a/src/kernel_services/abstract_interp/int_interval.ml +++ b/src/kernel_services/abstract_interp/int_interval.ml @@ -412,8 +412,8 @@ let cardinal_zero_or_one t = | Some min, Some max -> Integer.equal min max (* TODO? *) -let diff _ _ = assert false -let diff_if_one _ _ = assert false +let diff v _ = `Value v +let diff_if_one v _ = `Value v let fold_int f t acc = match t.min, t.max with diff --git a/src/kernel_services/abstract_interp/int_interval.mli b/src/kernel_services/abstract_interp/int_interval.mli index 74cb8c36358..b3854e42dfb 100644 --- a/src/kernel_services/abstract_interp/int_interval.mli +++ b/src/kernel_services/abstract_interp/int_interval.mli @@ -20,6 +20,12 @@ (* *) (**************************************************************************) +(** Integer intervals with congruence. + An interval defined by [min, max, rem, modu] represents all integers + between the bounds [min] and [max] and congruent to [rem] modulo [modu]. + A value of [None] for [min] (resp. [max]) represents -infinity + (resp. +infinity). [modu] is > 0, and [0 <= rem < modu]. *) + open Bottom.Type include Datatype.S_with_collections @@ -28,31 +34,40 @@ include Eva_lattice_type.Full_AI_Lattice_with_cardinality with type t := t and type widen_hint = Integer.t * Datatype.Integer.Set.t +(** Makes the interval of all integers between [min] and [max] and congruent + to [rem] modulo [modu]. Fails if these conditions does not hold: + - min ≤ max + - 0 ≤ rem < modu + - min ≅ rem [modu] ∧ max ≅ rem [modu] *) val make: min:Integer.t option -> max:Integer.t option -> rem:Integer.t -> modu:Integer.t -> t +(** Makes the interval of all integers between [min] and [max]. *) val inject_range: Integer.t option -> Integer.t option -> t +(** Returns the bounds of the given interval. [None] means infinity. *) val min_and_max: t -> Integer.t option * Integer.t option +(** Returns the bounds and the modulo of the given interval. *) val min_max_rem_modu: t -> Integer.t option * Integer.t option * Integer.t * Integer.t +(** [mem i t] returns true iff the integer [i] is in the interval [t]. *) val mem: Integer.t -> t -> bool +(** Returns the number of integers represented by the given interval. + Returns [None] if the interval represents an infinite number of integers. *) val cardinal: t -> Integer.t option -val add : t -> t -> t -(** Addition of two integer (ie. not [Float]) ivals. *) -val add_under : t -> t -> t or_bottom -(** Underapproximation of the same operation *) -val add_singleton_int: Integer.t -> t -> t -(** Addition of an integer ival with an integer. Exact operation. *) +(** {2 Interval semantics.} *) -val neg : t -> t -(** Negation of an integer ival. Exact operation. *) +(** See {!Int_val} for more details. *) +val add_singleton_int: Integer.t -> t -> t +val add: t -> t -> t +val add_under: t -> t -> t or_bottom +val neg: t -> t val scale: Integer.t -> t -> t val scale_div: pos:bool -> Integer.t -> t -> t @@ -65,6 +80,8 @@ val c_rem: t -> t -> t or_bottom val cast: size:Integer.t -> signed:bool -> t -> t +(** {2 Misc.} *) + val subdivide: t -> t * t val reduce_sign: t -> bool -> t or_bottom diff --git a/src/kernel_services/abstract_interp/int_set.ml b/src/kernel_services/abstract_interp/int_set.ml index 5854fa30f8b..4f60e38cd03 100644 --- a/src/kernel_services/abstract_interp/int_set.ml +++ b/src/kernel_services/abstract_interp/int_set.ml @@ -61,6 +61,7 @@ let share_array_or_bottom a s = let inject_periodic ~from ~period ~number = let l = Int.to_int number in + assert (l > 0); let s = Array.make l Int.zero in let v = ref from in let i = ref 0 in @@ -208,7 +209,6 @@ type pre_set = let empty_ps = Pre_set (O.empty, 0) -(* TODO: share this code with ival2.make_itv_from_set? *) let make_top_from_set s = if debug_cardinal then assert (O.cardinal s >= 2); let min = O.min_elt s in @@ -651,3 +651,5 @@ let subdivide s = let min t = t.(0) let max t = t.(Array.length t - 1) + +let mem i t = mem i t >= 0 diff --git a/src/kernel_services/abstract_interp/int_set.mli b/src/kernel_services/abstract_interp/int_set.mli index b88c2cc4887..3743502d031 100644 --- a/src/kernel_services/abstract_interp/int_set.mli +++ b/src/kernel_services/abstract_interp/int_set.mli @@ -27,27 +27,50 @@ open Bottom.Type +(** Returns the limit above which integer sets are converted into intervals. *) +val get_small_cardinal: unit -> int + +(** Sets the limit above which integer sets are converted into intervals. + This is used by the Eva plugin according to the -eva-ilevel option. + Do not use. *) +val set_small_cardinal: int -> unit + include Datatype.S_with_collections +(** Creates the set containing only the given integer. *) val inject_singleton: Integer.t -> t + +(** Creates the set with integers [from + k*period] for [k] in {0 ... number-1}. + The resulting set contains [number] integers. There is no verification + about [number], but it should be stritly positive. *) val inject_periodic: from:Integer.t -> period:Integer.t -> number:Integer.t -> t + +(** Creates a set from an integer list. The list must not be empty, and the list + length must not exceed the small cardinal limit. *) val inject_list: Integer.t list -> t +(** Returns the set as an integer list. *) val to_list: t -> Integer.t list +(** Removes an integer from a set. + Returns Bottom if the resulting set is empty. *) val remove: t -> Integer.t -> t or_bottom +(** [mem i s] is true iff the set [s] contains the integer [i]. *) +val mem: Integer.t -> t -> bool + val one: t val zero: t val minus_one: t val zero_or_one: t -val min: t -> Integer.t -val max: t -> Integer.t +val min: t -> Integer.t (** Returns the smallest integer of a set. *) +val max: t -> Integer.t (** Returns the highest integer of a set. *) +(** Returns the number of integers in a set. *) val cardinal: t -> int -val mem: Integer.t -> t -> int +(** {2 Iterators on the integers of a set.} *) val for_all: (Integer.t -> bool) -> t -> bool val exists: (Integer.t -> bool) -> t -> bool @@ -57,9 +80,20 @@ val map: (Integer.t -> Integer.t) -> t -> t val filter: (Integer.t -> bool) -> t -> t or_bottom val map_reduce: (Integer.t -> 'a) -> ('a -> 'a -> 'a) -> t -> 'a -type set_or_top = [ `Set of t | `Top of Integer.t * Integer.t * Integer.t ] +(** Sets whose cardinal exceeds a certain limit must be converted into + intervals. Functions that make sets grow returns either a set small enough, + or the information needed to construct the corresponding interval: the + smallest and highest elements, and the periodicity of the integers of + the set. *) +type set_or_top = + [ `Set of t (** Small set. *) + | `Top of Integer.t * Integer.t * Integer.t (** Interval: min, max, modu *) + ] + type set_or_top_or_bottom = [ `Bottom | set_or_top ] +(** {2 Lattice structure.} *) + val is_included: t -> t -> bool val join: t -> t -> set_or_top val link: t -> t -> set_or_top @@ -68,6 +102,10 @@ val narrow: t -> t -> t or_bottom val intersects: t -> t -> bool val diff_if_one: t -> t -> t or_bottom +(** {2 Semantics.} *) + +(** See {!Int_val} for more details. *) + val add_singleton: Integer.t -> t -> t val add: t -> t -> set_or_top val add_under: t -> t -> set_or_top @@ -82,13 +120,8 @@ val scale_rem: pos:bool -> Integer.t -> t -> t val bitwise_signed_not: t -> t -val subdivide: t -> t * t - -(**/**) +(** {2 Misc} *) -val get_small_cardinal: unit -> int - -(* This is used by the Value plugin. Do not use. *) -val set_small_cardinal: int -> unit +val subdivide: t -> t * t val rehash: t -> t diff --git a/src/kernel_services/abstract_interp/int_val.ml b/src/kernel_services/abstract_interp/int_val.ml index 107bc49c1ee..f18a3834a50 100644 --- a/src/kernel_services/abstract_interp/int_val.ml +++ b/src/kernel_services/abstract_interp/int_val.ml @@ -231,7 +231,7 @@ let is_one = equal one let contains_zero = function | Itv i -> Int_interval.mem Int.zero i - | Set s -> Int_set.mem Int.zero s >= 0 + | Set s -> Int_set.mem Int.zero s let contains_non_zero = function | Itv _ -> true (* at least two values *) -- GitLab