4.3 Bitvectors
Rosette extends Racket with a primitive bitvector datatype whose values are
fixed-size words—
> (bv 4 (bitvector 7)) ; A bitvector literal of size 7. (bv #b0000100 7)
> (bv 4 7) ; A shorthand for the same literal. (bv #b0000100 7)
> (define-symbolic x y (bitvector 7)) ; Symbolic bitvector constants. > (bvslt (bv 4 7) (bv -1 7)) ; Signed 7-bit < comparison of 4 and -1. #f
> (bvult (bv 4 7) (bv -1 7)) ; Unsigned 7-bit < comparison of 4 and -1. #t
> (define-symbolic b boolean?) > (bvadd x (if b y (bv 3 4))) ; This typechecks only when b is true, (bvadd x y)
> (vc) ; so Rosette emits a corresponding assertion. (vc #t b)
procedure
(bitvector size) → bitvector?
size : (and/c integer? positive? (not/c term?) (not/c union?))
> (define bv6? (bitvector 6)) > (bv6? 1) #f
> (bv6? (bv 3 6)) #t
> (bv6? (bv 3 5)) #f
> (define-symbolic b boolean?) > (bv6? (if b (bv 3 6) #t)) b
procedure
(bitvector? v) → boolean?
v : any/c
> (define bv6? (bitvector 6)) > (define bv7? (bitvector 7)) > (define-symbolic b boolean?) > (bitvector? bv6?) ; A concrete bitvector type. #t
> (bitvector? (if b bv6? bv7?)) ; Not a concrete type. #f
> (bitvector? integer?) ; Not a bitvector type. #f
> (bitvector? 3) ; Not a type. #f
procedure
val : (and/c integer? (not/c term?) (not/c union?))
size :
(and/c (or/c bitvector? (and/c integer? positive?)) (not/c term?) (not/c union?))
4.3.1 Comparison Operators
procedure
x : (bitvector n) y : (bitvector n) (bvslt x y) → boolean? x : (bitvector n) y : (bitvector n) (bvult x y) → boolean? x : (bitvector n) y : (bitvector n) (bvsle x y) → boolean? x : (bitvector n) y : (bitvector n) (bvule x y) → boolean? x : (bitvector n) y : (bitvector n) (bvsgt x y) → boolean? x : (bitvector n) y : (bitvector n) (bvugt x y) → boolean? x : (bitvector n) y : (bitvector n) (bvsge x y) → boolean? x : (bitvector n) y : (bitvector n) (bvuge x y) → boolean? x : (bitvector n) y : (bitvector n)
> (define-symbolic u v (bitvector 7)) ; Symbolic bitvector constants. > (bvslt (bv 4 7) (bv -1 7)) ; Signed 7-bit < comparison of 4 and -1. #f
> (bvult (bv 4 7) (bv -1 7)) ; Unsigned 7-bit < comparison of 4 and -1. #t
> (define-symbolic b boolean?) > (bvsge u (if b v (bv 3 4))) ; This typechecks only when b is true, (bvsle v u)
> (vc) ; so Rosette emits a corresponding assertion. (vc #t b)
4.3.2 Bitwise Operators
> (bvnot (bv -1 4)) (bv #x0 4)
> (bvnot (bv 0 4)) (bv #xf 4)
> (define-symbolic b boolean?) > (bvnot (if b 0 (bv 0 4))) ; This typechecks only when b is false, (bv #xf 4)
> (vc) ; so Rosette emits a corresponding assertion. (vc #t (! b))
procedure
x : (bitvector n) (bvor x ...+) → (bitvector n) x : (bitvector n) (bvxor x ...+) → (bitvector n) x : (bitvector n)
> (bvand (bv -1 4) (bv 2 4)) (bv #x2 4)
> (bvor (bv 0 3) (bv 1 3)) (bv #b001 3)
> (bvxor (bv -1 5) (bv 1 5)) (bv #b11110 5)
> (define-symbolic b boolean?)
> (bvand (bv -1 4) (if b 0 (bv 2 4))) ; This typechecks only when b is false, (bv #x2 4)
> (vc) ; so Rosette emits a corresponding assertion. (vc #t (! b))
procedure
x : (bitvector n) y : (bitvector n) (bvlshr x y) → (bitvector n) x : (bitvector n) y : (bitvector n) (bvashr x y) → (bitvector n) x : (bitvector n) y : (bitvector n)
> (bvshl (bv 1 4) (bv 2 4)) (bv #x4 4)
> (bvlshr (bv -1 3) (bv 1 3)) (bv #b011 3)
> (bvashr (bv -1 5) (bv 1 5)) (bv #b11111 5)
> (define-symbolic b boolean?)
> (bvshl (bv -1 4) (if b 0 (bv 2 4))) ; This typechecks only when b is false, (bv #xc 4)
> (vc) ; so Rosette emits a corresponding assertion. (vc #t (! b))
4.3.3 Arithmetic Operators
> (bvneg (bv -1 4)) (bv #x1 4)
> (bvneg (bv 0 4)) (bv #x0 4)
> (define-symbolic z (bitvector 3)) > (bvneg z) (bvneg z)
procedure
x : (bitvector n) (bvsub x ...+) → (bitvector n) x : (bitvector n) (bvmul x ...+) → (bitvector n) x : (bitvector n)
> (bvadd (bv -1 4) (bv 2 4)) (bv #x1 4)
> (bvsub (bv 0 3) (bv 1 3)) (bv #b111 3)
> (bvmul (bv -1 5) (bv 1 5)) (bv #b11111 5)
> (define-symbolic b boolean?) > (bvadd (bv -1 4) (bv 2 4) (if b (bv 1 4) "bad")) (bv #x2 4)
> (vc) (vc #t b)
procedure
x : (bitvector n) y : (bitvector n) (bvudiv x y) → (bitvector n) x : (bitvector n) y : (bitvector n) (bvsrem x y) → (bitvector n) x : (bitvector n) y : (bitvector n) (bvurem x y) → (bitvector n) x : (bitvector n) y : (bitvector n) (bvsmod x y) → (bitvector n) x : (bitvector n) y : (bitvector n)
> (bvsdiv (bv -3 4) (bv 2 4)) (bv #xf 4)
> (bvudiv (bv -3 3) (bv 2 3)) (bv #b010 3)
> (bvsmod (bv 1 5) (bv 0 5)) (bv #b00001 5)
> (define-symbolic b boolean?) > (bvsrem (bv -3 4) (if b (bv 2 4) "bad")) (bv #xf 4)
> (vc) (vc #t b)
4.3.4 Conversion Operators
> (concat (bv -1 4) (bv 0 1) (bv -1 3)) (bv #xf7 8)
> (define-symbolic b boolean?) > (concat (bv -1 4) (if b (bv 0 1) (bv 0 2)) (bv -1 3)) (union [b (bv #xf7 8)] [(! b) (bv #b111100111 9)])
> (extract 2 1 (bv -1 4)) (bv #b11 2)
> (extract 3 3 (bv 1 4)) (bv #b0 1)
> (define-symbolic i j integer?) > (extract i j (bv 1 2))
(union
[(&& (= 0 j) (= 1 i)) (bv #b01 2)]
[(|| (&& (= 0 i) (= 0 j)) (&& (= 1 i) (= 1 j)))
(ite* (⊢ (&& (= 0 i) (= 0 j)) (bv #b1 1)) (⊢ (&& (= 1 i) (= 1 j)) ...))])
> (vc) (vc #t (&& (&& (<= j i) (<= 0 j)) (< i 2)))
procedure
(sign-extend x t) → bv?
x : bv? t : (or/c bitvector? union?) (zero-extend x t) → bv? x : bv? t : (or/c bitvector? union?)
> (sign-extend (bv -3 4) (bitvector 6)) (bv #b111101 6)
> (zero-extend (bv -3 4) (bitvector 6)) (bv #b001101 6)
> (define-symbolic b c boolean?) > (zero-extend (bv -3 4) (if b (bitvector 5) (bitvector 6))) (union [b (bv #b01101 5)] [(! b) (bv #b001101 6)])
> (zero-extend (bv -3 4) (if b (bitvector 5) "bad")) (bv #b01101 5)
> (vc) (vc #t b)
> (zero-extend (bv -3 4) (if c (bitvector 5) (bitvector 1))) (bv #b01101 5)
> (vc) (vc #t (&& b c))
procedure
(bitvector->integer x) → integer?
x : bv? (bitvector->natural x) → integer? x : bv?
> (bitvector->integer (bv -1 4)) -1
> (bitvector->natural (bv -1 4)) 15
> (define-symbolic b boolean?) > (bitvector->integer (if b (bv -1 3) (bv -3 4))) (ite b -1 -3)
> (bitvector->integer (if b (bv -1 3) "bad")) -1
> (vc) (vc #t b)
procedure
(integer->bitvector i t) → bv?
i : integer? t : (or/c bitvector? union?)
> (integer->bitvector 4 (bitvector 2)) (bv #b00 2)
> (integer->bitvector 15 (bitvector 4)) (bv #xf 4)
> (define-symbolic b c boolean?) > (integer->bitvector (if b pi 3) (if c (bitvector 5) (bitvector 6))) (union [c (bv #b00011 5)] [(! c) (bv #b000011 6)])
> (vc) (vc #t (! b))
4.3.5 Additional Operators
> (bit 1 (bv 3 4)) (bv #b1 1)
> (bit 2 (bv 1 4)) (bv #b0 1)
> (define-symbolic i integer?) > (define-symbolic x (bitvector 4)) > (bit i x)
(ite*
(⊢ (= 0 i) (extract 0 0 x))
(⊢ (= 1 i) (extract 1 1 x))
(⊢ (= 2 i) (extract 2 2 x))
(⊢ (= 3 i) (extract 3 3 x)))
> (vc) (vc #t (&& (<= 0 i) (< i 4)))
> (lsb (bv 3 4)) (bv #b1 1)
> (msb (bv 3 4)) (bv #b0 1)
> (define-symbolic x (bitvector 4)) > (define-symbolic y (bitvector 8)) > (lsb (if b x y)) (ite b (extract 0 0 x) (extract 0 0 y))
> (msb (if b x y)) (ite b (extract 3 3 x) (extract 7 7 y))
> (define-symbolic x (bitvector 4)) > (bvzero? x) (bveq (bv #x0 4) x)
> (define-symbolic y (bitvector 8)) > (bvzero? y) (bveq (bv #x00 8) y)
> (define-symbolic b boolean?) > (bvzero? (if b x y)) (|| (&& (bveq (bv #x00 8) y) (! b)) (&& (bveq (bv #x0 4) x) b))
> (define-symbolic x (bitvector 4)) > (bvadd1 x) (bvadd (bv #x1 4) x)
> (define-symbolic y (bitvector 8)) > (bvsub1 y) (bvadd (bv #xff 8) y)
> (define-symbolic b boolean?) > (bvadd1 (if b x y)) (union [b (bvadd (bv #x1 4) x)] [(! b) (bvadd (bv #x01 8) y)])
> (bvsub1 (if b x y)) (union [b (bvadd (bv #xf 4) x)] [(! b) (bvadd (bv #xff 8) y)])
procedure
x : (bitvector n) (bvumin x ...+) → (bitvector n) x : (bitvector n) (bvsmax x ...+) → (bitvector n) x : (bitvector n) (bvumax x ...+) → (bitvector n) x : (bitvector n)
> (bvsmin (bv -1 4) (bv 2 4)) (bv #xf 4)
> (bvumin (bv -1 4) (bv 2 4)) (bv #x2 4)
> (bvsmax (bv -1 4) (bv 2 4)) (bv #x2 4)
> (bvumax (bv -1 4) (bv 2 4)) (bv #xf 4)
> (define-symbolic b boolean?) > (bvsmin (bv -1 4) (bv 2 4) (if b (bv 1 4) (bv 3 8))) (bv #xf 4)
> (vc) (vc #t b)
procedure
x : (bitvector n) y : (bitvector n) (bvror x y) → (bitvector n) x : (bitvector n) y : (bitvector n)
> (bvrol (bv 3 4) (bv 2 4)) (bv #xc 4)
> (bvrol (bv 3 4) (bv -2 4)) (bv #xc 4)
> (define-symbolic b boolean?)
> (bvror (bv 3 4) (if b 0 (bv 2 4))) ; This typechecks only when b is false, (bv #xc 4)
> (vc) ; so Rosette emits a corresponding assertion. (vc #t (! b))
procedure
(rotate-left i x) → (bitvector n)
i : integer? x : (bitvector n) (rotate-right i x) → (bitvector n) i : integer? x : (bitvector n)
> (rotate-left 3 (bv 3 4)) (bv #x9 4)
> (rotate-right 1 (bv 3 4)) (bv #x9 4)
> (define-symbolic i integer?) > (define-symbolic b boolean?) > (rotate-left i (if b (bv 3 4) (bv 7 8)))
(union
[b
(ite* (⊢ (= 0 i) (bv #x3 4)) (⊢ (= 1 i) (bv #x6 4)) (⊢ (= 2 i) ...) ...)]
[(! b)
(ite* (⊢ (= 0 i) (bv #x07 8)) (⊢ (= 1 i) (bv #x0e 8)) (⊢ (= 2 ...) ...) ...)])
> (vc)
(vc
#t
(&&
(<= 0 i)
(|| (! b) (&& (<= 0 i) (|| (< i 4) (! (|| b (! (<= 0 i)))))))
(|| b (&& (<= 0 i) (|| (< i 8) (! (|| (! b) (! (<= 0 i)))))))))
procedure
(bitvector->bits x) → (listof (bitvector 1))
x : (bitvector n)
> (bitvector->bits (bv 3 4)) (list (bv #b1 1) (bv #b1 1) (bv #b0 1) (bv #b0 1))
> (define-symbolic y (bitvector 2)) > (bitvector->bits y) (list (extract 0 0 y) (extract 1 1 y))
> (define-symbolic b boolean?) > (bitvector->bits (if b (bv 3 4) y))
(union
[b ((bv #b1 1) (bv #b1 1) (bv #b0 1) (bv #b0 1))]
[(! b) ((extract 0 0 y) (extract 1 1 y))])
procedure
(bitvector->bool x) → boolean?
x : (bitvector n)
procedure
(bool->bitvector b [t]) → bv?
b : any/c t : (or/c positive-integer? (bitvector n)) = (bitvector 1)
> (bool->bitvector #f 3) (bv #b000 3)
> (bool->bitvector "non-false-value") (bv #b1 1)
> (define-symbolic b boolean?) > (bool->bitvector b) (ite b (bv #b1 1) (bv #b0 1))