summaryrefslogtreecommitdiff
path: root/src/Helium/Data/BitVec.agda
blob: 3d409ca4835e0fb27c461f139a2da5ae79f50cb7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
{-# OPTIONS --safe --without-K #-}

module Helium.Data.BitVec where

open import Algebra.Core
open import Data.Bool as B using () renaming (Bool to Bit; false to 0#; true to 1#)
open import Data.Fin hiding (_+_; _-_)
open import Data.Fin.Properties using (toℕ-fromℕ)
open import Data.Nat as N hiding (_+_)
open import Data.Product
open import Data.Vec hiding (map; replicate)
open import Relation.Binary.PropositionalEquality using (cong)

private
  variable
    l m n : ℕ

infixr 6 _∧_ _+_ _-_
infixr 5 _∨_ _xor_


-- Type

BitVec : ℕ → Set
BitVec = Vec Bit


-- Constants

replicate : Bit → BitVec n
replicate {zero}  b = []
replicate {suc n} b = b ∷ replicate b

zeroes : BitVec n
zeroes = replicate 0#

ones : BitVec n
ones = replicate 1#

one : BitVec (suc n)
one {zero}  = 1# ∷ []
one {suc n} = 0# ∷ one


-- Bitwise operations

bitwise : Op₁ Bit → Op₁ (BitVec n)
bitwise f [] = []
bitwise f (x ∷ xs) = f x ∷ bitwise f xs

bitwise₂ : Op₂ Bit → Op₂ (BitVec n)
bitwise₂ _∙_ []       []       = []
bitwise₂ _∙_ (x ∷ xs) (y ∷ ys) = x ∙ y ∷ bitwise₂ _∙_ xs ys

not : BitVec n → BitVec n
not = bitwise B.not

_∧_ : BitVec n → BitVec n → BitVec n
_∧_ = bitwise₂ B._∧_

_∨_ : BitVec n → BitVec n → BitVec n
_∨_ = bitwise₂ B._∨_

_xor_ : BitVec n → BitVec n → BitVec n
_xor_ = bitwise₂ B._xor_


-- Arithmetic operations

add-carry : Bit → BitVec n → BitVec n → Bit
add-carry c  []       []      = c
add-carry c (x ∷ xs) (y ∷ ys) = add-carry c xs ys B.∧ (x B.xor y) B.xor (x B.∧ y)

add-rem : Bit → BitVec n → BitVec n → BitVec n
add-rem c []       []       = []
add-rem c (x ∷ xs) (y ∷ ys) = (add-carry c xs ys B.xor x B.xor y) ∷ add-rem c xs ys

add : Bit → BitVec n → BitVec n → BitVec (suc n)
add c xs ys = add-carry c xs ys ∷ add-rem c xs ys

_+_ : BitVec n → BitVec n → BitVec n
xs + ys = add-rem 0# xs ys

_-_ : BitVec n → BitVec n → BitVec n
xs - ys = add-rem 1# xs (not ys)


-- Conversions

bitToFin : Bit → Fin 2
bitToFin 0# = zero
bitToFin 1# = suc zero

finToBit : Fin 2 → Bit
finToBit zero       = 0#
finToBit (suc zero) = 1#

toFin : BitVec n → Fin (2 ^ n)
toFin         []       = zero
toFin         (b ∷ bs) = combine (bitToFin b) (toFin bs)

fromFin : Fin (2 ^ n) → BitVec n
fromFin {zero}  x = []
fromFin {suc n} x = uncurry (_∷_) (map finToBit fromFin (remQuot (2 ^ n) x))