Skip to content

Commit

Permalink
Add dichotomic symbolic ctz
Browse files Browse the repository at this point in the history
  • Loading branch information
krtab committed Feb 27, 2024
1 parent 782291f commit 7f248d6
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 13 deletions.
5 changes: 4 additions & 1 deletion src/int32.ml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ let clz =
Some
(fun n -> Stdlib.Int32.of_int (Ocaml_intrinsics.Int32.count_leading_zeros n))

let ctz n = Stdlib.Int32.of_int (Ocaml_intrinsics.Int32.count_trailing_zeros n)
let ctz =
Some
(fun n ->
Stdlib.Int32.of_int (Ocaml_intrinsics.Int32.count_trailing_zeros n) )

(* Taken from Base https://github.com/janestreet/base *)
let popcnt =
Expand Down
2 changes: 1 addition & 1 deletion src/int32.mli
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ val unsigned_to_int : t -> int option

val clz : (t -> t) option

val ctz : t -> t
val ctz : (t -> t) option

val popcnt : t -> t

Expand Down
5 changes: 4 additions & 1 deletion src/int64.ml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ let clz =
Some
(fun n -> Stdlib.Int64.of_int (Ocaml_intrinsics.Int64.count_leading_zeros n))

let ctz n = Stdlib.Int64.of_int (Ocaml_intrinsics.Int64.count_trailing_zeros n)
let ctz =
Some
(fun n ->
Stdlib.Int64.of_int (Ocaml_intrinsics.Int64.count_trailing_zeros n) )

(* Taken from Base: https://github.com/janestreet/base *)
let popcnt =
Expand Down
2 changes: 1 addition & 1 deletion src/int64.mli
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ val abs : t -> t

val clz : (t -> t) option

val ctz : t -> t
val ctz : (t -> t) option

val popcnt : t -> t

Expand Down
34 changes: 32 additions & 2 deletions src/interpret.ml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,32 @@ module Make (P : Interpret_intf.P) :
let> cond = I64.(eqz n) in
if cond then return @@ const_i64 64L else aux 0 64

let ctz_impl_32 n =
let rec aux (lb : int) ub =
if ub = lb + 1 then return (const_i32 (Int32.of_int lb))
else begin
let mid = (lb + ub) / 2 in
let two_pow_mid = Int32.shl 1l (Int32.of_int mid) in
let> cond = I32.(eqz @@ rem n (const_i32 two_pow_mid)) in
if cond then aux mid ub else aux lb mid
end
in
let> cond = I32.(eqz n) in
if cond then return @@ const_i32 32l else aux 0 32

let ctz_impl_64 n =
let rec aux (lb : int) ub =
if ub = lb + 1 then return (const_i64 (Int64.of_int lb))
else begin
let mid = (lb + ub) / 2 in
let two_pow_mid = Int64.shl 1L (Int64.of_int mid) in
let> cond = I64.(eqz @@ rem n (const_i64 two_pow_mid)) in
if cond then aux mid ub else aux lb mid
end
in
let> cond = I64.(eqz n) in
if cond then return @@ const_i64 64L else aux 0 64

let with_choosing_default_impl f ch_f =
match f with
| Some f -> fun n -> Choice.return (f n)
Expand All @@ -141,7 +167,9 @@ module Make (P : Interpret_intf.P) :
| Clz ->
let clz = with_choosing_default_impl clz clz_impl_32 in
clz n
| Ctz -> Choice.return @@ ctz n
| Ctz ->
let ctz = with_choosing_default_impl ctz ctz_impl_32 in
ctz n
| Popcnt -> Choice.return @@ popcnt n
in
Stack.push_i32 stack res
Expand All @@ -153,7 +181,9 @@ module Make (P : Interpret_intf.P) :
| Clz ->
let clz = with_choosing_default_impl clz clz_impl_64 in
clz n
| Ctz -> Choice.return @@ ctz n
| Ctz ->
let ctz = with_choosing_default_impl ctz ctz_impl_64 in
ctz n
| Popcnt -> Choice.return @@ popcnt n
in
Stack.push_i64 stack res
Expand Down
8 changes: 2 additions & 6 deletions src/symbolic_value.ml
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,7 @@ module I32 = struct

let clz = None

let ctz _ =
(* TODO *)
assert false
let ctz = None

let popcnt _ =
(* TODO *)
Expand Down Expand Up @@ -283,9 +281,7 @@ module I64 = struct

let clz = None

let ctz _ =
(* TODO *)
assert false
let ctz = None

let popcnt _ =
(* TODO *)
Expand Down
2 changes: 1 addition & 1 deletion src/value_intf.ml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ module type Iop = sig

val clz : (num -> num) option

val ctz : num -> num
val ctz : (num -> num) option

val popcnt : num -> num

Expand Down
13 changes: 13 additions & 0 deletions test/sym/clz_32.wat
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,19 @@
(call $countLeadingZeros (local.get $n))
(i32.clz (local.get $n))
))

(call $assert (i32.eq
(i32.ctz (local.get $n))
;; Implem of ctz using clz
;; from hacker's delight p107
(i32.sub
(i32.const 32)
(i32.clz ( i32.and
(i32.xor (local.get $n) (i32.const -1))
(i32.sub (local.get $n) (i32.const 1))
))
)
))
)


Expand Down
13 changes: 13 additions & 0 deletions test/sym/clz_64.wat
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,19 @@
(call $countLeadingZeros (local.get $n))
(i64.clz (local.get $n))
))

(call $assert (i64.eq
(i64.ctz (local.get $n))
;; Implem of ctz using clz
;; from hacker's delight p107
(i64.sub
(i64.const 64)
(i64.clz ( i64.and
(i64.xor (local.get $n) (i64.const -1))
(i64.sub (local.get $n) (i64.const 1))
))
)
))
)


Expand Down

0 comments on commit 7f248d6

Please sign in to comment.