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_nums.
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_nums.
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_nums, 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 znums.
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 znums.
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 znums.
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}