Frama-C API - Fval
Floating-point intervals, used to construct arithmetic lattices. The interfaces of this module may change between Frama-C versions. Contact us if you need stable APIs.
type kind = Float_sig.prec =
val pretty_kind : Stdlib.Format.formatter -> kind -> unit
module F : sig ... end
include Float_interval_sig.S with type float := F.t
type widen_hint = Datatype.Float.Set.t
Hints for the widening: set of relevant thresholds.
val packed_descr : Structural_descr.pack
val pretty : Stdlib.Format.formatter -> t -> unit
val hash : t -> int
Returns the bounds of the float interval, (or None if the argument is exactly NaN), and a boolean indicating the possibility that the value may be NaN.
val nan : t
The NaN singleton
val pos_infinity : Float_interval_sig.prec -> t
The infinities singleton
val neg_infinity : Float_interval_sig.prec -> t
val top_finite : Float_interval_sig.prec -> t
The interval of all finite values in the given precision.
Lattice operators.
val widen : ?hint:widen_hint -> Float_interval_sig.prec -> t -> t -> t
val narrow : t -> t -> t Lattice_bounds.or_bottom
val contains_a_zero : t -> bool
val contains_pos_zero : t -> bool
val contains_neg_zero : t -> bool
val contains_non_zero : t -> bool
val contains_pos_infinity : t -> bool
val contains_neg_infinity : t -> bool
val contains_nan : t -> bool
val is_negative : t -> Abstract_interp.Comp.result
is_negative f
returns True
iff all values in f
are negative; False
iff all values are positive; and Unknown
otherwise. Note that we do not keep sign information for NaN, so if f
may contain NaN, the result is always Unknown
.
val is_finite : t -> Abstract_interp.Comp.result
val is_infinite : t -> Abstract_interp.Comp.result
val is_not_nan : t -> Abstract_interp.Comp.result
val backward_is_finite : positive:bool -> Float_interval_sig.prec -> t -> t Lattice_bounds.or_bottom
val backward_is_infinite : positive:bool -> Float_interval_sig.prec -> t -> t Lattice_bounds.or_bottom
val backward_is_nan : positive:bool -> t -> t Lattice_bounds.or_bottom
has_greater_min_bound f1 f2
returns 1 if the interval f1
has a better minimum bound (i.e. greater) than the interval f2
.
has_smaller_max_bound f1 f2
returns 1 if the interval f1
has a better maximum bound (i.e. lower) than the interval f2
.
val forward_comp : Abstract_interp.Comp.t -> t -> t -> Abstract_interp.Comp.result
val backward_comp_left_true : Abstract_interp.Comp.t -> Float_interval_sig.prec -> t -> t -> t Lattice_bounds.or_bottom
backward_comp_left_true op prec f1 f2
attempts to reduce f1
into f1'
so that the relation f1' op f2
holds. prec
is the precision of f1
and f1'
, but not necessarily of f2
.
val backward_comp_left_false : Abstract_interp.Comp.t -> Float_interval_sig.prec -> t -> t -> t Lattice_bounds.or_bottom
backward_comp_left_false op prec f1 f2
attempts to reduce f1
into f1'
so that the relation f1' op f2
doesn't holds. prec
is the precision of f1
and f1'
, but not necessarily of f2
.
val abs : Float_interval_sig.prec -> t -> t
val add : Float_interval_sig.prec -> t -> t -> t
val sub : Float_interval_sig.prec -> t -> t -> t
val mul : Float_interval_sig.prec -> t -> t -> t
val div : Float_interval_sig.prec -> t -> t -> t
val sqrt : Float_interval_sig.prec -> t -> t
val pow : Float_interval_sig.prec -> t -> t -> t
val fmod : Float_interval_sig.prec -> t -> t -> t
val cos : Float_interval_sig.prec -> t -> t
val sin : Float_interval_sig.prec -> t -> t
val acos : Float_interval_sig.prec -> t -> t
val asin : Float_interval_sig.prec -> t -> t
val atan : Float_interval_sig.prec -> t -> t
val atan2 : Float_interval_sig.prec -> t -> t -> t
val backward_add : Float_interval_sig.prec -> left:t -> right:t -> result:t -> (t * t) Lattice_bounds.or_bottom
val backward_sub : Float_interval_sig.prec -> left:t -> right:t -> result:t -> (t * t) Lattice_bounds.or_bottom
val forward_cast : dst:Float_interval_sig.prec -> t -> t
val backward_cast : src:Float_interval_sig.prec -> t -> t Lattice_bounds.or_bottom
val cast_int_to_float : Float_interval_sig.prec -> Integer.t option -> Integer.t option -> t
Bitwise reinterpretation of a floating-point interval of double precision into consecutive ranges of integers.
Bitwise reinterpretation of a floating-point interval of single precision into consecutive ranges of integers.
val subdivide : Float_interval_sig.prec -> t -> t * t
Subdivides an interval of a given precision into two intervals. Raises Abstract_interp.Can_not_subdiv
if it can't be subdivided. prec
must be Single
or Double
.
inject
creates an abstract float interval. It handles infinities, flush-to-zero (rounding subnormals if needed) and NaN. Inputs must be compatible with float_kind
. Raises no exceptions (unless values are not compatible with float_kind
, in which case execution is aborted). The two floating point numbers must be ordered (so not NaN). ~nan
indicates if NaN is present.
val top : t
val plus_zero : t
val minus_zero : t
val zeros : t
Both positive and negative zero
val pi : t
Real representation of \pi.
val e : t
Real representation of \e.
val contains_plus_zero : t -> bool
val meet : t -> t -> t Lattice_bounds.or_bottom
val is_singleton : t -> bool
Returns true
on NaN. We expect this function to be e.g. to perform subdivisions/enumerations. The size of the concretization is less interesting to us. (And it is also possible to consider that there is only one NaN value in the concrete anyway.)
Discussion regarding kind
and the 3 functions below.
Support for fesetround(FE_UPWARD) and fesetround(FE_DOWNWARD) seems to be especially poor, including in not-so-old versions of Glibc (https://sourceware.org/bugzilla/show_bug.cgi?id=3976). The code for exp
, log
and log10
is correct wrt. kind=Reak
ONLY if the C implementation of these functions is correct in directed rounding modes. Otherwise, anything could happen, including crashes. For now, unless the Libc is known to be reliable, these functions should be called with rounding_mode=Nearest_Even
only. Also note that there the Glibc does not guarantee that f(FE_DOWNWARD) <= f(FE_TONEAREST) <= f(FE_UPWARD), which implies that using different rounding modes to bound the final result does not ensure correct bounds. Here's an example where it does not hold (glibc 2.21): log10f(3, FE_TONEAREST) < log10f(3, FE_DOWNWARD).
Also, we have observed bugs in powf
, which is called when kind=Float32
.
val backward_cast_float_to_double : t -> t Lattice_bounds.or_bottom
backward_cast_float_to_double d
return all possible float32 f
such that (double)f = d
. The double of d
that have no float32 equivalent are discarded.
val kind : Cil_types.fkind -> kind
Classify a Cil_types.fkind
as either a 32 or 64 floating-point type. Long double are over approximated by Reals