lean4-htt/library/data/bitvec.lean
Joe Hendrix e6d964bef3 feat(library): Port subset of lean2 standard library needed for bitvectors.
This is a minimal port of lean2 libraries needed for the bitvector
library to lean3.
2016-11-15 12:15:49 -08:00

157 lines
4.8 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
Copyright (c) 2015 Joe Hendrix. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Joe Hendrix
Basic operations on bitvectors.
This is a work-in-progress, and contains additions to other theories.
-/
import data.tuple
definition bitvec (n : ) := tuple bool n
namespace bitvec
open nat
open tuple
-- Create a zero bitvector
definition zero { n : } : bitvec n := tuple.repeat ff
-- Create a bitvector with the constant one.
definition one {n : } : bitvec (succ n) := tuple.append (tuple.repeat ff : bitvec n) [ tt ]
section shift
-- shift left
definition shl {n:} : bitvec n → → bitvec n
| x i :=
if le : i ≤ n then
let eq := nat.sub_add_cancel le in
cast (congr_arg bitvec eq) (tuple.append (dropn i x) (zero : bitvec i))
else
zero
-- unsigned shift right
definition ushr {n:} : bitvec n → → bitvec n
| x i :=
if le : i ≤ n then
let y : bitvec (n-i) := @firstn _ _ _ (sub_le n i) x in
let eq := calc (i+(n-i)) = (n - i) + i : nat.add_comm i (n - i)
... = n : nat.sub_add_cancel le in
cast (congr_arg bitvec eq) (tuple.append zero y)
else
zero
-- signed shift right
definition sshr {m:} : bitvec (succ m) → → bitvec (succ m)
| x i :=
let n := succ m in
if le : i ≤ n then
let z : bitvec i := repeat (head x) in
let y : bitvec (n-i) := @firstn _ _ (n - i) (sub_le n i) x in
let eq := calc (i+(n-i)) = (n-i) + i : nat.add_comm i (n - i)
... = n : nat.sub_add_cancel le in
cast (congr_arg bitvec eq) (tuple.append z y)
else
zero
end shift
section bitwise
variable { n : }
definition not : bitvec n → bitvec n := map bnot
definition and : bitvec n → bitvec n → bitvec n := map₂ band
definition or : bitvec n → bitvec n → bitvec n := map₂ bor
definition xor : bitvec n → bitvec n → bitvec n := map₂ bxor
end bitwise
section arith
variable { n : }
protected definition xor3 (x:bool) (y:bool) (c:bool) := bxor (bxor x y) c
protected definition carry (x:bool) (y:bool) (c:bool) :=
x && y || x && c || y && c
definition neg : bitvec n → bitvec n
| x :=
let f := λy c, (y || c, bxor y c) in
prod.snd (mapAccumR f x ff)
-- Add with carry (no overflow)
definition adc : bitvec n → bitvec n → bool → bitvec (n+1)
| x y c :=
let f := λx y c, (bitvec.carry x y c, bitvec.xor3 x y c) in
let z := tuple.mapAccumR₂ f x y c in
prod.fst z :: prod.snd z
definition add : bitvec n → bitvec n → bitvec n
| x y := tail (adc x y ff)
protected definition borrow (x:bool) (y:bool) (b:bool) :=
bnot x && y || bnot x && b || y && b
-- Subtract with borrow
definition sbb : bitvec n → bitvec n → bool → bool × bitvec n
| x y b :=
let f := λx y c, (bitvec.borrow x y c, bitvec.xor3 x y c) in
tuple.mapAccumR₂ f x y b
definition sub : bitvec n → bitvec n → bitvec n
| x y := prod.snd (sbb x y ff)
instance : has_zero (bitvec n) := has_zero.mk zero
instance : has_one (bitvec (succ n)) := has_one.mk one
instance : has_add (bitvec n) := has_add.mk add
instance : has_sub (bitvec n) := has_sub.mk sub
instance : has_neg (bitvec n) := has_neg.mk neg
definition mul : bitvec n → bitvec n → bitvec n
| x y :=
let f := λr b, cond b (r + r + y) (r + r) in
list.foldl f 0 (to_list x)
instance : has_mul (bitvec n) := has_mul.mk mul
end arith
section comparison
variable {n : }
definition uborrow : bitvec n → bitvec n → bool := λx y, prod.fst (sbb x y ff)
definition ult (x y : bitvec n) : Prop := uborrow x y = tt
definition ugt (x y : bitvec n) : Prop := ult y x
definition ule (x y : bitvec n) : Prop := ¬ (ult y x)
definition uge : bitvec n → bitvec n → Prop := λx y, ule y x
definition sborrow : bitvec (succ n) → bitvec (succ n) → bool := λx y,
bool.cases_on
(head x)
(bool.cases_on (head y) (uborrow (tail x) (tail y)) tt)
(bool.cases_on (head y) ff (uborrow (tail x) (tail y)))
definition slt : bitvec (succ n) → bitvec (succ n) → Prop := λx y,
sborrow x y = tt
definition sgt : bitvec (succ n) → bitvec (succ n) → Prop := λx y, slt y x
definition sle : bitvec (succ n) → bitvec (succ n) → Prop := λx y, ¬ (slt y x)
definition sge : bitvec (succ n) → bitvec (succ n) → Prop := λx y, sle y x
end comparison
section from_bitvec
variable {A : Type}
-- Convert a bitvector to another number.
definition from_bitvec [p : has_add A] [q0 : has_zero A] [q1 : has_one A] {n:nat} (v:bitvec n) : A :=
let f : A → bool → A := λr b, cond b (r + r + 1) (r + r) in
list.foldl f (0 : A) (to_list v)
end from_bitvec
end bitvec