From d48aabe4c7fd104f22190d375fd1201c9771322a Mon Sep 17 00:00:00 2001 From: Maxime Jacquemin <maxime.jacquemin@cea.fr> Date: Wed, 31 Jan 2024 11:28:41 +0100 Subject: [PATCH] [Kernel] Add two unit tests for linear filter invariant computation --- .../analysis/filter/linear_filter_test.ml | 129 ++++++++++++++++++ .../analysis/filter/linear_filter_test.mli | 23 ++++ tests/float/linear_filter_test.ml | 5 +- .../oracle/linear_filter_test.res.oracle | 2 + 4 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 src/kernel_services/analysis/filter/linear_filter_test.ml create mode 100644 src/kernel_services/analysis/filter/linear_filter_test.mli diff --git a/src/kernel_services/analysis/filter/linear_filter_test.ml b/src/kernel_services/analysis/filter/linear_filter_test.ml new file mode 100644 index 00000000000..43e0564ca21 --- /dev/null +++ b/src/kernel_services/analysis/filter/linear_filter_test.ml @@ -0,0 +1,129 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2023 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + + + +module Rational = struct + + type scalar = Q.t + + module Type = struct + include Datatype.Serializable_undefined + type t = scalar + let name = "Linear.Filter.Test.Rational" + let reprs = [ Q.zero ] + let compare = Q.compare + let equal = Q.equal + let hash q = Z.hash (Q.num q) + 11 * Z.hash (Q.den q) + end + + include Datatype.Make_with_collections (Type) + + let pretty fmt n = + let ten = Z.of_int 10 in + let sign = if Q.sign n >= 0 then "" else "-" in + let num = Q.num n |> Z.abs and den = Q.den n |> Z.abs in + let finish n = Z.Compare.(n >= den || n == Z.zero) in + let rec f e n = if finish n then (n, e) else f (e + 1) Z.(n * ten) in + let num, exponent = f 0 num in + let default fmt n = Format.fprintf fmt "%1.7f" (Q.to_float n) in + if exponent > 0 then + let number = Q.make num den in + Format.fprintf fmt "%s%aE-%d" sign default number exponent + else default fmt n + + include Q + let infinity = Q.inf + let ( == ) = Q.equal + +end + + + +module Filter = Linear_filter.Make (Rational) +module Linear = Filter.Linear + +let max_exponent = 200 +let fin size n = Finite.of_int size n |> Option.get +let set row col i j n = Linear.Matrix.set (fin row i) (fin col j) n + +let pretty_invariant fmt = function + | None -> Format.fprintf fmt "%s" (Unicode.top_string ()) + | Some invariant -> Format.fprintf fmt "%a" Rational.pretty invariant + + + +module Circle = struct + + let order = Nat.(succ one) + + let state = + Linear.Matrix.zero order order + |> set order order 0 0 Rational.(of_float 0.68) + |> set order order 0 1 Rational.(of_float ~-.0.68) + |> set order order 1 0 Rational.(of_float 0.68) + |> set order order 1 1 Rational.(of_float 0.68) + + let input = Linear.Matrix.id order + + let measure = Linear.Vector.repeat Rational.one order + + let compute () = + let filter = Filter.create state input measure in + let invariant = Filter.invariant filter max_exponent in + Kernel.result "Circle : %a@." pretty_invariant invariant + +end + + + +module Simple = struct + + let order = Nat.(succ one) + let delay = Nat.one + + let state = + Linear.Matrix.zero order order + |> set order order 0 0 Rational.(of_float 1.5) + |> set order order 0 1 Rational.(of_float ~-.0.7) + |> set order order 1 0 Rational.(of_float 1.) + |> set order order 1 1 Rational.(of_float 0.) + + let input = + Linear.Matrix.zero order delay + |> set order delay 0 0 Rational.one + |> set order delay 1 0 Rational.zero + + let measure = Linear.Vector.repeat (Rational.of_float 0.1) delay + + let compute () = + let filter = Filter.create state input measure in + let invariant = Filter.invariant filter max_exponent in + Kernel.result "Simple : %a@." pretty_invariant invariant + +end + + + +let run () = + Circle.compute () ; + Simple.compute () diff --git a/src/kernel_services/analysis/filter/linear_filter_test.mli b/src/kernel_services/analysis/filter/linear_filter_test.mli new file mode 100644 index 00000000000..cc9eb1f5468 --- /dev/null +++ b/src/kernel_services/analysis/filter/linear_filter_test.mli @@ -0,0 +1,23 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2023 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +val run : unit -> unit diff --git a/tests/float/linear_filter_test.ml b/tests/float/linear_filter_test.ml index 6a356eaf372..420df28ae1e 100644 --- a/tests/float/linear_filter_test.ml +++ b/tests/float/linear_filter_test.ml @@ -1,7 +1,4 @@ (* Programmatic tests of the invariant computation of linear filters by the module Linear_filter. Run by linear_filter_test.i. *) -let main _ = - () - -let () = Db.Main.extend main +let () = Boot.Main.extend Linear_filter_test.run diff --git a/tests/float/oracle/linear_filter_test.res.oracle b/tests/float/oracle/linear_filter_test.res.oracle index 9fb7d2ecaff..27e5f9d3051 100644 --- a/tests/float/oracle/linear_filter_test.res.oracle +++ b/tests/float/oracle/linear_filter_test.res.oracle @@ -1 +1,3 @@ [kernel] Parsing linear_filter_test.i (no preprocessing) +[kernel] Circle : 31.3829787 +[kernel] Simple : 9.2732747E-1 -- GitLab