Skip to content

Commit d7833ec

Browse files
Merge pull request #1493 from goblint/issue_1328
make cil_exp_of_linexpr1 work with fractional expressions
2 parents 6d2654f + 44e9549 commit d7833ec

File tree

1 file changed

+40
-9
lines changed

1 file changed

+40
-9
lines changed

src/cdomains/apron/sharedFunctions.apron.ml

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ open GobApron
66

77
module M = Messages
88

9-
let int_of_scalar ?round (scalar: Scalar.t) =
9+
10+
let int_of_scalar ?(scalewith=Z.one) ?round (scalar: Scalar.t) =
1011
if Scalar.is_infty scalar <> 0 then (* infinity means unbounded *)
1112
None
1213
else
@@ -20,18 +21,21 @@ let int_of_scalar ?round (scalar: Scalar.t) =
2021
| None when Stdlib.Float.is_integer f -> Some f
2122
| None -> None
2223
in
23-
Z.of_float f
24+
Z.(of_float f * scalewith)
2425
| Mpqf scalar -> (* octMPQ, boxMPQ, polkaMPQ *)
2526
let n = Mpqf.get_num scalar in
2627
let d = Mpqf.get_den scalar in
28+
let scale = Z_mlgmpidl.mpz_of_z scalewith in
2729
let+ z =
2830
if Mpzf.cmp_int d 1 = 0 then (* exact integer (denominator 1) *)
29-
Some n
31+
Some (Mpzf.mul scale n)
3032
else
3133
begin match round with
32-
| Some `Floor -> Some (Mpzf.fdiv_q n d) (* floor division *)
33-
| Some `Ceil -> Some (Mpzf.cdiv_q n d) (* ceiling division *)
34-
| None -> None
34+
| Some `Floor -> Some (Mpzf.mul scale (Mpzf.fdiv_q n d)) (* floor division *)
35+
| Some `Ceil -> Some (Mpzf.mul scale (Mpzf.cdiv_q n d)) (* ceiling division *)
36+
| None -> let product = Mpzf.mul scale n in if Mpz.divisible_p product d then
37+
Some (Mpzf.divexact product d) (* scale, preferably with common denominator *)
38+
else None
3539
end
3640
in
3741
Z_mlgmpidl.z_of_mpzf z
@@ -245,11 +249,11 @@ module CilOfApron (V: SV) =
245249
struct
246250
exception Unsupported_Linexpr1
247251

248-
let cil_exp_of_linexpr1 (linexpr1:Linexpr1.t) =
252+
let cil_exp_of_linexpr1 ?scalewith (linexpr1:Linexpr1.t) =
249253
let longlong = TInt(ILongLong,[]) in
250254
let coeff_to_const consider_flip (c:Coeff.union_5) = match c with
251255
| Scalar c ->
252-
(match int_of_scalar c with
256+
(match int_of_scalar ?scalewith c with
253257
| Some i ->
254258
let ci,truncation = truncateCilint ILongLong i in
255259
if truncation = NoTruncation then
@@ -285,11 +289,38 @@ struct
285289
!expr
286290

287291

292+
let lcm_den linexpr1 =
293+
let exception UnsupportedScalar
294+
in
295+
let frac_of_scalar scalar =
296+
if Scalar.is_infty scalar <> 0 then (* infinity means unbounded *)
297+
None
298+
else match scalar with
299+
| Float f -> if Stdlib.Float.is_integer f then Some (Q.of_float f) else None
300+
| Mpqf f -> Some (Z_mlgmpidl.q_of_mpqf f)
301+
| _ -> raise UnsupportedScalar
302+
in
303+
let extract_den (c:Coeff.union_5) =
304+
match c with
305+
| Scalar c -> BatOption.map Q.den (frac_of_scalar c)
306+
| _ -> None
307+
in
308+
let lcm_denom = ref (BatOption.default Z.one (extract_den (Linexpr1.get_cst linexpr1))) in
309+
let lcm_coeff (c:Coeff.union_5) _ =
310+
match (extract_den c) with
311+
| Some z -> lcm_denom := Z.lcm z !lcm_denom
312+
| _ -> ()
313+
in
314+
try
315+
Linexpr1.iter lcm_coeff linexpr1; !lcm_denom
316+
with UnsupportedScalar -> Z.one
317+
288318
let cil_exp_of_lincons1 (lincons1:Lincons1.t) =
289319
let zero = Cil.kinteger ILongLong 0 in
290320
try
291321
let linexpr1 = Lincons1.get_linexpr1 lincons1 in
292-
let cilexp = cil_exp_of_linexpr1 linexpr1 in
322+
let common_denominator = lcm_den linexpr1 in
323+
let cilexp = cil_exp_of_linexpr1 ~scalewith:common_denominator linexpr1 in
293324
match Lincons1.get_typ lincons1 with
294325
| EQ -> Some (Cil.constFold false @@ BinOp(Eq, cilexp, zero, TInt(IInt,[])))
295326
| SUPEQ -> Some (Cil.constFold false @@ BinOp(Ge, cilexp, zero, TInt(IInt,[])))

0 commit comments

Comments
 (0)