@@ -6,7 +6,8 @@ open GobApron
6
6
7
7
module M = Messages
8
8
9
- let int_of_scalar ?round (scalar : Scalar.t ) =
9
+
10
+ let int_of_scalar ?(scalewith =Z. one) ?round (scalar : Scalar.t ) =
10
11
if Scalar. is_infty scalar <> 0 then (* infinity means unbounded *)
11
12
None
12
13
else
@@ -20,18 +21,21 @@ let int_of_scalar ?round (scalar: Scalar.t) =
20
21
| None when Stdlib.Float. is_integer f -> Some f
21
22
| None -> None
22
23
in
23
- Z. of_float f
24
+ Z. ( of_float f * scalewith)
24
25
| Mpqf scalar -> (* octMPQ, boxMPQ, polkaMPQ *)
25
26
let n = Mpqf. get_num scalar in
26
27
let d = Mpqf. get_den scalar in
28
+ let scale = Z_mlgmpidl. mpz_of_z scalewith in
27
29
let + z =
28
30
if Mpzf. cmp_int d 1 = 0 then (* exact integer (denominator 1) *)
29
- Some n
31
+ Some ( Mpzf. mul scale n)
30
32
else
31
33
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
35
39
end
36
40
in
37
41
Z_mlgmpidl. z_of_mpzf z
@@ -245,11 +249,11 @@ module CilOfApron (V: SV) =
245
249
struct
246
250
exception Unsupported_Linexpr1
247
251
248
- let cil_exp_of_linexpr1 (linexpr1 :Linexpr1.t ) =
252
+ let cil_exp_of_linexpr1 ? scalewith (linexpr1 :Linexpr1.t ) =
249
253
let longlong = TInt (ILongLong ,[] ) in
250
254
let coeff_to_const consider_flip (c :Coeff.union_5 ) = match c with
251
255
| Scalar c ->
252
- (match int_of_scalar c with
256
+ (match int_of_scalar ?scalewith c with
253
257
| Some i ->
254
258
let ci,truncation = truncateCilint ILongLong i in
255
259
if truncation = NoTruncation then
@@ -285,11 +289,38 @@ struct
285
289
! expr
286
290
287
291
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
+
288
318
let cil_exp_of_lincons1 (lincons1 :Lincons1.t ) =
289
319
let zero = Cil. kinteger ILongLong 0 in
290
320
try
291
321
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
293
324
match Lincons1. get_typ lincons1 with
294
325
| EQ -> Some (Cil. constFold false @@ BinOp (Eq , cilexp, zero, TInt (IInt ,[] )))
295
326
| SUPEQ -> Some (Cil. constFold false @@ BinOp (Ge , cilexp, zero, TInt (IInt ,[] )))
0 commit comments