Binary representation of integers using inductive types #
Note: Unlike in Coq, where this representation is preferred because of
the reliance on kernel reduction, in Lean this representation is discouraged
in favor of the "Peano" natural numbers Nat
, and the purpose of this
collection of theorems is to show the equivalence of the different approaches.
Equations
bit b n
appends the bit b
to the end of n
, where bit tt x = x1
and bit ff x = x0
.
Equations
- PosNum.bit b = bif b then PosNum.bit1 else PosNum.bit0
Instances For
Returns a boolean for whether the PosNum
is one
.
Equations
- PosNum.isOne x = match x with | PosNum.one => true | x => false
Instances For
Addition of two PosNum
s.
Equations
- PosNum.add PosNum.one x = PosNum.succ x
- PosNum.add x PosNum.one = PosNum.succ x
- PosNum.add (PosNum.bit0 a) (PosNum.bit0 b) = PosNum.bit0 (PosNum.add a b)
- PosNum.add (PosNum.bit1 a) (PosNum.bit1 b) = PosNum.bit0 (PosNum.succ (PosNum.add a b))
- PosNum.add (PosNum.bit0 a) (PosNum.bit1 b) = PosNum.bit1 (PosNum.add a b)
- PosNum.add (PosNum.bit1 a) (PosNum.bit0 b) = PosNum.bit1 (PosNum.add a b)
Instances For
Equations
- PosNum.instAddPosNum = { add := PosNum.add }
The predecessor of a PosNum
as a Num
.
Equations
- PosNum.pred' PosNum.one = 0
- PosNum.pred' (PosNum.bit0 n) = Num.pos (Num.casesOn (PosNum.pred' n) 1 PosNum.bit1)
- PosNum.pred' (PosNum.bit1 n) = Num.pos (PosNum.bit0 n)
Instances For
The predecessor of a PosNum
as a PosNum
. This means that pred 1 = 1
.
Equations
- PosNum.pred a = Num.casesOn (PosNum.pred' a) 1 id
Instances For
The number of bits of a PosNum
, as a PosNum
.
Equations
- PosNum.size PosNum.one = 1
- PosNum.size (PosNum.bit0 n) = PosNum.succ (PosNum.size n)
- PosNum.size (PosNum.bit1 n) = PosNum.succ (PosNum.size n)
Instances For
Multiplication of two PosNum
s.
Equations
- PosNum.mul a PosNum.one = a
- PosNum.mul a (PosNum.bit0 n) = PosNum.bit0 (PosNum.mul a n)
- PosNum.mul a (PosNum.bit1 n) = PosNum.bit0 (PosNum.mul a n) + a
Instances For
Equations
- PosNum.instMulPosNum = { mul := PosNum.mul }
Equations
- PosNum.instOfNatPosNumHAddNatInstHAddInstAddNatOfNat = { ofNat := PosNum.ofNat (n + 1) }
Ordering of PosNum
s.
Equations
- PosNum.cmp PosNum.one PosNum.one = Ordering.eq
- PosNum.cmp x PosNum.one = Ordering.gt
- PosNum.cmp PosNum.one x = Ordering.lt
- PosNum.cmp (PosNum.bit0 a) (PosNum.bit0 b) = PosNum.cmp a b
- PosNum.cmp (PosNum.bit0 a) (PosNum.bit1 b) = Ordering.casesOn (PosNum.cmp a b) Ordering.lt Ordering.lt Ordering.gt
- PosNum.cmp (PosNum.bit1 a) (PosNum.bit0 b) = Ordering.casesOn (PosNum.cmp a b) Ordering.lt Ordering.gt Ordering.gt
- PosNum.cmp (PosNum.bit1 a) (PosNum.bit1 b) = PosNum.cmp a b
Instances For
Equations
- PosNum.instLTPosNum = { lt := fun a b => PosNum.cmp a b = Ordering.lt }
Equations
- PosNum.instLEPosNum = { le := fun a b => ¬b < a }
Equations
- PosNum.decidableLT x x = match x, x with | a, b => id inferInstance
Equations
- PosNum.decidableLE x x = match x, x with | a, b => id inferInstance
castPosNum
casts a PosNum
into any type which has 1
and +
.
Equations
- ↑PosNum.one = 1
- ↑(PosNum.bit0 n) = bit0 ↑n
- ↑(PosNum.bit1 n) = bit1 ↑n
Instances For
Equations
- instReprPosNum = { reprPrec := fun n x => repr ↑n }
The number of bits required to represent a Num
, as a Nat
. size 0
is defined to be 0
.
Equations
- Num.natSize x = match x with | Num.zero => 0 | Num.pos n => PosNum.natSize n
Instances For
Ordering of Num
s.
Equations
- Num.cmp x x = match x, x with | Num.zero, Num.zero => Ordering.eq | x, Num.zero => Ordering.gt | Num.zero, x => Ordering.lt | Num.pos a, Num.pos b => PosNum.cmp a b
Instances For
Equations
- Num.instLTNum = { lt := fun a b => Num.cmp a b = Ordering.lt }
Equations
- Num.decidableLT x x = match x, x with | a, b => id inferInstance
Equations
- Num.decidableLE x x = match x, x with | a, b => id inferInstance
Equations
- Num.toZNum x = match x with | Num.zero => 0 | Num.pos a => ZNum.pos a
Instances For
Equations
- Num.ofNat' = Nat.binaryRec 0 fun b x => bif b then Num.bit1 else Num.bit0
Instances For
The successor of a ZNum
.
Equations
- ZNum.succ x = match x with | ZNum.zero => 1 | ZNum.pos a => ZNum.pos (PosNum.succ a) | ZNum.neg a => Num.toZNumNeg (PosNum.pred' a)
Instances For
The predecessor of a ZNum
.
Equations
- ZNum.pred x = match x with | ZNum.zero => ZNum.neg 1 | ZNum.pos a => Num.toZNum (PosNum.pred' a) | ZNum.neg a => ZNum.neg (PosNum.succ a)
Instances For
bit1 x
appends a 1
to the end of x
, mapping x
to 2 * x + 1
.
Equations
- ZNum.bit1 x = match x with | ZNum.zero => 1 | ZNum.pos n => ZNum.pos (PosNum.bit1 n) | ZNum.neg n => ZNum.neg (Num.casesOn (PosNum.pred' n) 1 PosNum.bit1)
Instances For
bitm1 x
appends a 1
to the end of x
, mapping x
to 2 * x - 1
.
Equations
- ZNum.bitm1 x = match x with | ZNum.zero => ZNum.neg 1 | ZNum.pos n => ZNum.pos (Num.casesOn (PosNum.pred' n) 1 PosNum.bit1) | ZNum.neg n => ZNum.neg (PosNum.bit1 n)
Instances For
Equations
- ZNum.ofInt' x = match x with | Int.ofNat n => Num.toZNum (Num.ofNat' n) | Int.negSucc n => Num.toZNumNeg (Num.ofNat' (n + 1))
Instances For
Subtraction of two PosNum
s, producing a ZNum
.
Equations
- PosNum.sub' x PosNum.one = Num.toZNum (PosNum.pred' x)
- PosNum.sub' PosNum.one x = Num.toZNumNeg (PosNum.pred' x)
- PosNum.sub' (PosNum.bit0 a) (PosNum.bit0 b) = ZNum.bit0 (PosNum.sub' a b)
- PosNum.sub' (PosNum.bit0 a) (PosNum.bit1 b) = ZNum.bitm1 (PosNum.sub' a b)
- PosNum.sub' (PosNum.bit1 a) (PosNum.bit0 b) = ZNum.bit1 (PosNum.sub' a b)
- PosNum.sub' (PosNum.bit1 a) (PosNum.bit1 b) = ZNum.bit0 (PosNum.sub' a b)
Instances For
Converts a ZNum
to a PosNum
, mapping all out of range values to 1
.
Equations
- PosNum.ofZNum x = match x with | ZNum.pos p => p | x => 1
Instances For
Subtraction of PosNum
s, where if a < b
, then a - b = 1
.
Equations
- PosNum.sub a b = match PosNum.sub' a b with | ZNum.pos p => p | x => 1
Instances For
Equations
- PosNum.instSubPosNum = { sub := PosNum.sub }
Equations
- ZNum.instLTZNum = { lt := fun a b => ZNum.cmp a b = Ordering.lt }
Equations
- ZNum.decidableLT x x = match x, x with | a, b => id inferInstance
Equations
- ZNum.decidableLE x x = match x, x with | a, b => id inferInstance
Auxiliary definition for PosNum.divMod
.
Equations
- PosNum.divModAux d q r = match Num.ofZNum' (Num.sub' r (Num.pos d)) with | some r' => (Num.bit1 q, r') | none => (Num.bit0 q, r)
Instances For
divMod x y = (y / x, y % x)
.
Equations
- PosNum.divMod d (PosNum.bit0 n) = match PosNum.divMod d n with | (q, r₁) => PosNum.divModAux d q (Num.bit0 r₁)
- PosNum.divMod d (PosNum.bit1 n) = match PosNum.divMod d n with | (q, r₁) => PosNum.divModAux d q (Num.bit1 r₁)
- PosNum.divMod d PosNum.one = PosNum.divModAux d 0 1
Instances For
Auxiliary definition for Num.gcd
.
Equations
- Num.gcdAux 0 x x = x
- Num.gcdAux (Nat.succ n) Num.zero x = x
- Num.gcdAux (Nat.succ n) x x = Num.gcdAux n (x % x) x
Instances For
Greatest Common Divisor (GCD) of two Num
s.
Equations
- Num.gcd a b = if a ≤ b then Num.gcdAux (Num.natSize a + Num.natSize b) a b else Num.gcdAux (Num.natSize b + Num.natSize a) b a