From e945d78dc65718de6bb63efd00173e6954d77997 Mon Sep 17 00:00:00 2001
From: Julien Signoles <julien.signoles@cea.fr>
Date: Sat, 14 Aug 2021 17:05:23 +0200
Subject: [PATCH] [e-acsl:interval] simplify the case of \sum

---
 src/plugins/e-acsl/src/analyses/interval.ml | 59 +++++++++++----------
 1 file changed, 32 insertions(+), 27 deletions(-)

diff --git a/src/plugins/e-acsl/src/analyses/interval.ml b/src/plugins/e-acsl/src/analyses/interval.ml
index 5b5927ab5c7..91807d502aa 100644
--- a/src/plugins/e-acsl/src/analyses/interval.ml
+++ b/src/plugins/e-acsl/src/analyses/interval.ml
@@ -351,36 +351,41 @@ let extended_interv_of_typ ty = match interv_of_typ ty with
    of the lower (resp. upper) bound and [name] is the identifier of the extended
    quantifier (\sum, \product or \numof). The returned ival is the interval of
    the extended quantifier. *)
-let interv_of_extended_quantifier lambda i j name =
-  match lambda, i, j, name.lv_name with
-  | Ival lbd_iv, Ival i_iv, Ival j_iv, "\\sum" ->
+let interv_of_extended_quantifier lambda lb up name =
+  match lambda, lb, up, name.lv_name with
+  | Ival lbd_iv, Ival lb_iv, Ival ub_iv, "\\sum" ->
     (try
        let min_lambda, max_lambda = Ival.min_and_max lbd_iv in
-       let i_lb, i_ub = Ival.min_and_max i_iv in
-       let j_lb, j_ub = Ival.min_and_max j_iv in
-       let compute_bound bound_lambda is_lower_bound =
-         let cond = match bound_lambda with
-           | Some lambda ->
-             (is_lower_bound && Z.compare lambda Z.zero = 1) ||
-             (not is_lower_bound && Z.compare lambda Z.zero = -1)
-           | None -> false
-         in
-         match bound_lambda, i_lb, i_ub, j_lb, j_ub with
-         | Some lambda, _, Some i_ub, Some j_lb, _  when cond->
-           Some (Z.mul lambda (Z.max (Z.sub j_lb i_ub) Z.zero))
-         | _, _, _, _, _ when cond -> Some Z.zero
-         | Some lambda,  Some i_lb, _, _, Some j_ub ->
-           Some (Z.mul lambda (Z.max (Z.sub j_ub i_lb) Z.zero))
-         | Some lambda, _, _ , _, _ when Z.compare lambda Z.zero = 0 ->
-           Some Z.zero
-         | None, Some i_lb, _, _, Some j_ub when Z.compare j_ub i_lb = 0 ->
-           Some Z.zero
-         |  _, _, _, _, _ -> None
+       let min_lb, min_ub = Ival.min_and_max lb_iv in
+       let max_lb, max_ub = Ival.min_and_max ub_iv in
+       (* the number of iterations is the distance between the upper bound and
+          the lower bound, or 0 if it is negative. *)
+       let delta a b = Z.max Z.zero (Z.sub a b) in
+       let min_iteration_number =
+         (* the minimum number of iterations is the distance between the
+            smallest upper bound and the biggest lower bound. *)
+         match min_ub, max_lb with
+         | Some mub, Some mlb -> delta mub mlb
+         | _, None | None, _ -> Z.zero
+       in
+       let max_iteration_number =
+         (* the maximum number of iterations is the distance between the
+              biggest upper bound and the smallest lower bound. *)
+         match max_ub, min_lb with
+         | Some mub, Some mlb -> Some (delta mub mlb)
+         | _, None | None, _ -> None
        in
-       Ival
-         (Ival.inject_range
-            (compute_bound min_lambda true)
-            (compute_bound max_lambda false))
+       (* the lower (resp. upper) bound is the min (resp. max) value of
+          the lambda term times the min (resp. max) number of iterations *)
+       let lower_bound = match min_lambda with
+         | None -> None
+         | Some z -> Some (Z.mul z min_iteration_number)
+         in
+         let upper_bound = match max_lambda, max_iteration_number with
+           | None, _ | _, None -> None
+           | Some z, Some n -> Some (Z.mul z n)
+         in
+         Ival (Ival.inject_range lower_bound upper_bound)
      with Abstract_interp.Error_Bottom ->
        bottom)
   | _, _, _, "\\product" ->  Error.not_yet "product"
-- 
GitLab