整数区间的逻辑计算

时间:2014-11-04 14:46:44

标签: math intervals

计算逻辑操作的规则是什么。两个整数区间的(AND OR XOR)?

给定两个区间[a,b] [c,d]我想计算[a,b] xor [c,d]

我假设结果是多个范围

我查看了filib ++并阅读了WIKI,但发现只是算术运算。支撑

任何人都可以教育我

1 个答案:

答案 0 :(得分:0)

您可以在文件src / ai / ival.ml中找到Frama-C的最新版本中的间隔之间的“按位和”,“按位xor”和“按位或”的实现。实际上,这些函数对Ival.t类型的值进行操作,它们表示一小组整数值,一个带有同余信息的间隔或一个浮点间隔。您只对Top _, Top _的情况感兴趣(对应于具有同余信息的整数区间)。该函数将结果计算为Ival.t,可能过度近似,但其中包含x第一个区间中x和第二个区间中y的所有值。

正如评论所说,pos_max_land的算法对于精度是最佳的,但是对于整数的位数没有最佳复杂度。在完成函数编写之后我才理解这一点,对于这个用例,整数的宽度不超过64,所以我没有打算写更快的版本。

文件src / ai / ival.ml是根据LGPL 2.1获得许可的。如果你用它做一些很酷的事情,我会很高兴听到它。

(* [different_bits min max] returns an overapproximation of the mask
   of the bits that can be different for different numbers
   in the interval [min]..[max] *)
let different_bits min max =
  let x = Int.logxor min max in
  next_pred_power_of_two x

(* [pos_max_land min1 max1 min2 max2] computes an upper bound for
   [x1 land x2] where [x1] is in [min1]..[max1] and [x2] is in [min2]..[max2].
   Precondition : [min1], [max1], [min2], [max2] must all have the
   same sign.
   Note: the algorithm below is optimal for the problem as stated.
   It is possible to compute this optimal solution faster but it does not
   seem worth the time necessary to think about it as long as integers
   are at most 64-bit. *)
let pos_max_land min1 max1 min2 max2 =
  let x1 = different_bits min1 max1 in
  let x2 = different_bits min2 max2 in
(*      Format.printf "pos_max_land %a %a -> %a |  %a %a -> %a@."
        Int.pretty min1 Int.pretty max1 Int.pretty x1
        Int.pretty min2 Int.pretty max2 Int.pretty x2; *)
  let fold_maxs max1 p f acc =
    let rec aux p acc =
      let p = Int.shift_right p Int.one in
      if Int.is_zero p
      then f max1 acc
      else if Int.is_zero (Int.logand p max1) 
      then aux p acc
      else 
        let c = Int.logor (Int.sub max1 p) (Int.pred p) in
        aux p (f c acc)
    in aux p acc
  in
  let sx1 = Int.succ x1 in
  let n1 = fold_maxs max1 sx1 (fun _ y -> succ y) 0 in
  let maxs1 = Array.make n1 sx1 in
  let _ = fold_maxs max1 sx1 (fun x i -> Array.set maxs1 i x; succ i) 0 in
  fold_maxs max2 (Int.succ x2)
    (fun max2 acc -> 
      Array.fold_left
        (fun acc max1 -> Int.max (Int.logand max1 max2) acc)
        acc
        maxs1)
    (Int.logand max1 max2)

let bitwise_or v1 v2 =
  if is_bottom v1 || is_bottom v2
  then bottom
  else
    match v1, v2 with
      Float _, _ | _, Float _ -> top
     | Set s1, Set s2 ->
        apply2_v Int.logor s1 s2
     | Set s, v | v, Set s when Array.length s = 1 && Int.is_zero s.(0) -> v
     | Top _, _ | _, Top _ ->
         ( match min_and_max v1 with
           Some mn1, Some mx1 when Int.ge mn1 Int.zero ->
             ( match min_and_max v2 with
               Some mn2, Some mx2 when Int.ge mn2 Int.zero ->
                 let new_max = next_pred_power_of_two (Int.logor mx1 mx2) in
                 let new_min = Int.max mn1 mn2 in (* Or can only add bits *)
                 inject_range (Some new_min) (Some new_max)
             | _ -> top )
         | _ -> top )

let bitwise_xor v1 v2 =
  if is_bottom v1 || is_bottom v2
  then bottom
  else
    match v1, v2 with
     | Float _, _ | _, Float _ -> top
     | Set s1, Set s2 -> apply2_v Int.logxor s1 s2
     | Top _, _ | _, Top _ ->
       (match min_and_max v1 with
         | Some mn1, Some mx1 when Int.ge mn1 Int.zero ->
           (match min_and_max v2 with
             | Some mn2, Some mx2 when Int.ge mn2 Int.zero ->
               let new_max = next_pred_power_of_two (Int.logor mx1 mx2) in
               let new_min = Int.zero in
               inject_range (Some new_min) (Some new_max)
             | _ -> top )
         | _ -> top )