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
Equations
- pos_num.inhabited = {default := 1}
Equations
- num.has_zero = {zero := num.zero}
Equations
- num.has_one = {one := num.pos 1}
Equations
- num.inhabited = {default := 0}
Equations
- znum.has_zero = {zero := znum.zero}
Equations
- znum.has_one = {one := znum.pos 1}
Equations
- znum.inhabited = {default := 0}
bit b n
appends the bit b
to the end of n
, where bit tt x = x1
and bit ff x = x0
.
Equations
Addition of two pos_num
s.
Equations
Equations
of_nat_succ n
is the pos_num
corresponding to n + 1
.
Equations
of_nat n
is the pos_num
corresponding to n
, except for of_nat 0 = 1
.
Equations
Ordering of pos_num
s.
Equations
- a.bit0.cmp b.bit0 = a.cmp b
- a.bit0.cmp b.bit1 = (a.cmp b).cases_on ordering.lt ordering.lt ordering.gt
- ᾰ.bit0.cmp 1 = ordering.gt
- a.bit1.cmp b.bit0 = (a.cmp b).cases_on ordering.lt ordering.gt ordering.gt
- a.bit1.cmp b.bit1 = a.cmp b
- ᾰ.bit1.cmp 1 = ordering.gt
- 1.cmp ᾰ.bit0 = ordering.lt
- 1.cmp ᾰ.bit1 = ordering.lt
- 1.cmp 1 = ordering.eq
Equations
- pos_num.has_lt = {lt := λ (a b : pos_num), a.cmp b = ordering.lt}
Equations
- pos_num.decidable_lt a b = id (ordering.decidable_eq (a.cmp b) ordering.lt)
Equations
- pos_num.decidable_le a b = id (ne.decidable (b.cmp a) ordering.lt)
cast_pos_num
casts a pos_num
into any type which has 1
and +
.
Equations
- cast_pos_num a.bit0 = bit0 (cast_pos_num a)
- cast_pos_num a.bit1 = bit1 (cast_pos_num a)
- cast_pos_num 1 = 1
Equations
- pos_num_coe = {coe := cast_pos_num _inst_2}
Equations
- num.has_add = {add := num.add}
Equations
- num.has_mul = {mul := num.mul}
Equations
- num.has_lt = {lt := λ (a b : num), a.cmp b = ordering.lt}
Equations
- num.decidable_lt a b = id (ordering.decidable_eq (a.cmp b) ordering.lt)
Equations
- num.decidable_le a b = id (ne.decidable (b.cmp a) ordering.lt)
Converts x : num
to -x : znum
.
Equations
- (num.pos a).to_znum_neg = znum.neg a
- 0.to_znum_neg = 0
Equations
- num.of_nat' = nat.binary_rec 0 (λ (b : bool) (n : ℕ), cond b num.bit1 num.bit0)
Equations
- znum.has_neg = {neg := znum.zneg}
Equations
- znum.of_int' -[1+ n] = (num.of_nat' (n + 1)).to_znum_neg
- znum.of_int' ↑n = (num.of_nat' n).to_znum
Subtraction of two pos_num
s, producing a znum
.
Equations
- a.bit0.sub' b.bit0 = (a.sub' b).bit0
- a.bit0.sub' b.bit1 = (a.sub' b).bitm1
- ᾰ.bit0.sub' 1 = ᾰ.bit0.pred'.to_znum
- a.bit1.sub' b.bit0 = (a.sub' b).bit1
- a.bit1.sub' b.bit1 = (a.sub' b).bit0
- ᾰ.bit1.sub' 1 = ᾰ.bit1.pred'.to_znum
- 1.sub' ᾰ.bit0 = ᾰ.bit0.pred'.to_znum_neg
- 1.sub' ᾰ.bit1 = ᾰ.bit1.pred'.to_znum_neg
- pos_num.one.sub' 1 = pos_num.one.pred'.to_znum
Converts a znum
to a pos_num
, mapping all out of range values to 1
.
Equations
- pos_num.of_znum (znum.neg ᾰ) = 1
- pos_num.of_znum (znum.pos p) = p
- pos_num.of_znum znum.zero = 1
Equations
Converts a znum
to an option num
, where of_znum' p = none
if p < 0
.
Equations
- num.of_znum' (znum.neg p) = none
- num.of_znum' (znum.pos p) = some (num.pos p)
- num.of_znum' 0 = some 0
Converts a znum
to an option num
, where of_znum p = 0
if p < 0
.
Equations
- num.of_znum (znum.neg ᾰ) = 0
- num.of_znum (znum.pos p) = num.pos p
- num.of_znum znum.zero = 0
Equations
- num.has_sub = {sub := num.sub}
Addition of znum
s.
Equations
- (znum.neg a).add (znum.neg b) = znum.neg (a + b)
- (znum.neg a).add (znum.pos b) = b.sub' a
- (znum.neg ᾰ).add 0 = znum.neg ᾰ
- (znum.pos a).add (znum.neg b) = a.sub' b
- (znum.pos a).add (znum.pos b) = znum.pos (a + b)
- (znum.pos ᾰ).add 0 = znum.pos ᾰ
- 0.add (znum.neg ᾰ) = znum.neg ᾰ
- 0.add (znum.pos ᾰ) = znum.pos ᾰ
- 0.add znum.zero = znum.zero
Equations
- znum.has_add = {add := znum.add}
Multiplication of znum
s.
Equations
- (znum.neg a).mul (znum.neg b) = znum.pos (a * b)
- (znum.neg a).mul (znum.pos b) = znum.neg (a * b)
- (znum.neg ᾰ).mul 0 = 0
- (znum.pos a).mul (znum.neg b) = znum.neg (a * b)
- (znum.pos a).mul (znum.pos b) = znum.pos (a * b)
- (znum.pos ᾰ).mul 0 = 0
- 0.mul (znum.neg ᾰ) = 0
- 0.mul (znum.pos ᾰ) = 0
- 0.mul znum.zero = 0
Equations
- znum.has_mul = {mul := znum.mul}
Ordering on znum
s.
Equations
- (znum.neg a).cmp (znum.neg b) = b.cmp a
- (znum.neg _x).cmp (znum.pos ᾰ) = ordering.lt
- (znum.neg _x).cmp znum.zero = ordering.lt
- (znum.pos _x).cmp (znum.neg ᾰ) = ordering.gt
- (znum.pos a).cmp (znum.pos b) = a.cmp b
- (znum.pos _x).cmp znum.zero = ordering.gt
- znum.zero.cmp (znum.neg _x) = ordering.gt
- znum.zero.cmp (znum.pos _x) = ordering.lt
- 0.cmp 0 = ordering.eq
Equations
- znum.has_lt = {lt := λ (a b : znum), a.cmp b = ordering.lt}
Equations
- znum.decidable_lt a b = id (ordering.decidable_eq (a.cmp b) ordering.lt)
Equations
- znum.decidable_le a b = id (ne.decidable (b.cmp a) ordering.lt)
Auxiliary definition for pos_num.divmod
.
divmod x y = (y / x, y % x)
.
Equations
- num.has_div = {div := num.div}
Equations
- num.has_mod = {mod := num.mod}
Auxiliary definition for num.gcd
.
Equations
- num.gcd_aux n.succ (num.pos ᾰ) b = num.gcd_aux n (b % num.pos ᾰ) (num.pos ᾰ)
- num.gcd_aux n.succ 0 b = b
- num.gcd_aux 0 a b = b
Division of znum
, where x / 0 = 0
.
Equations
- (znum.neg n).div (znum.neg d) = znum.pos (n.pred' / num.pos d).succ'
- (znum.neg n).div (znum.pos d) = znum.neg (n.pred' / num.pos d).succ'
- (znum.neg ᾰ).div 0 = 0
- (znum.pos n).div (znum.neg d) = (n.div' d).to_znum_neg
- (znum.pos n).div (znum.pos d) = (n.div' d).to_znum
- (znum.pos ᾰ).div 0 = 0
- 0.div (znum.neg ᾰ) = 0
- 0.div (znum.pos ᾰ) = 0
- 0.div znum.zero = 0
Equations
- znum.has_div = {div := znum.div}
Equations
- znum.has_mod = {mod := znum.mod}