/- Copyright (c) 2014 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura, Mario Carneiro -/ /-! # Binary representation of integers using inductive types > THIS FILE IS SYNCHRONIZED WITH MATHLIB4. > Any changes to this file require a corresponding PR to mathlib4. 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. -/ /-- The type of positive binary numbers. 13 = 1101(base 2) = bit1 (bit0 (bit1 one)) -/ @[derive has_reflect, derive decidable_eq] inductive pos_num : Type | one : pos_num | bit1 : pos_num → pos_num | bit0 : pos_num → pos_num instance : has_one pos_num := ⟨pos_num.one⟩ instance : inhabited pos_num := ⟨1⟩ /-- The type of nonnegative binary numbers, using `pos_num`. 13 = 1101(base 2) = pos (bit1 (bit0 (bit1 one))) -/ @[derive has_reflect, derive decidable_eq] inductive num : Type | zero : num | pos : pos_num → num instance : has_zero num := ⟨num.zero⟩ instance : has_one num := ⟨num.pos 1⟩ instance : inhabited num := ⟨0⟩ /-- Representation of integers using trichotomy around zero. 13 = 1101(base 2) = pos (bit1 (bit0 (bit1 one))) -13 = -1101(base 2) = neg (bit1 (bit0 (bit1 one))) -/ @[derive has_reflect, derive decidable_eq] inductive znum : Type | zero : znum | pos : pos_num → znum | neg : pos_num → znum instance : has_zero znum := ⟨znum.zero⟩ instance : has_one znum := ⟨znum.pos 1⟩ instance : inhabited znum := ⟨0⟩ namespace pos_num /-- `bit b n` appends the bit `b` to the end of `n`, where `bit tt x = x1` and `bit ff x = x0`. -/ def bit (b : bool) : pos_num → pos_num := cond b bit1 bit0 /-- The successor of a `pos_num`. -/ def succ : pos_num → pos_num | 1 := bit0 one | (bit1 n) := bit0 (succ n) | (bit0 n) := bit1 n /-- Returns a boolean for whether the `pos_num` is `one`. -/ def is_one : pos_num → bool | 1 := tt | _ := ff /-- Addition of two `pos_num`s. -/ protected def add : pos_num → pos_num → pos_num | 1 b := succ b | a 1 := succ a | (bit0 a) (bit0 b) := bit0 (add a b) | (bit1 a) (bit1 b) := bit0 (succ (add a b)) | (bit0 a) (bit1 b) := bit1 (add a b) | (bit1 a) (bit0 b) := bit1 (add a b) instance : has_add pos_num := ⟨pos_num.add⟩ /-- The predecessor of a `pos_num` as a `num`. -/ def pred' : pos_num → num | 1 := 0 | (bit0 n) := num.pos (num.cases_on (pred' n) 1 bit1) | (bit1 n) := num.pos (bit0 n) /-- The predecessor of a `pos_num` as a `pos_num`. This means that `pred 1 = 1`. -/ def pred (a : pos_num) : pos_num := num.cases_on (pred' a) 1 id /-- The number of bits of a `pos_num`, as a `pos_num`. -/ def size : pos_num → pos_num | 1 := 1 | (bit0 n) := succ (size n) | (bit1 n) := succ (size n) /-- The number of bits of a `pos_num`, as a `nat`. -/ def nat_size : pos_num → nat | 1 := 1 | (bit0 n) := nat.succ (nat_size n) | (bit1 n) := nat.succ (nat_size n) /-- Multiplication of two `pos_num`s. -/ protected def mul (a : pos_num) : pos_num → pos_num | 1 := a | (bit0 b) := bit0 (mul b) | (bit1 b) := bit0 (mul b) + a instance : has_mul pos_num := ⟨pos_num.mul⟩ /-- `of_nat_succ n` is the `pos_num` corresponding to `n + 1`. -/ def of_nat_succ : ℕ → pos_num | 0 := 1 | (nat.succ n) := succ (of_nat_succ n) /-- `of_nat n` is the `pos_num` corresponding to `n`, except for `of_nat 0 = 1`. -/ def of_nat (n : ℕ) : pos_num := of_nat_succ (nat.pred n) open ordering /-- Ordering of `pos_num`s. -/ def cmp : pos_num → pos_num → ordering | 1 1 := eq | _ 1 := gt | 1 _ := lt | (bit0 a) (bit0 b) := cmp a b | (bit0 a) (bit1 b) := ordering.cases_on (cmp a b) lt lt gt | (bit1 a) (bit0 b) := ordering.cases_on (cmp a b) lt gt gt | (bit1 a) (bit1 b) := cmp a b instance : has_lt pos_num := ⟨λa b, cmp a b = ordering.lt⟩ instance : has_le pos_num := ⟨λa b, ¬ b < a⟩ instance decidable_lt : @decidable_rel pos_num (<) | a b := by dsimp [(<)]; apply_instance instance decidable_le : @decidable_rel pos_num (≤) | a b := by dsimp [(≤)]; apply_instance end pos_num section variables {α : Type*} [has_one α] [has_add α] /-- `cast_pos_num` casts a `pos_num` into any type which has `1` and `+`. -/ def cast_pos_num : pos_num → α | 1 := 1 | (pos_num.bit0 a) := bit0 (cast_pos_num a) | (pos_num.bit1 a) := bit1 (cast_pos_num a) /-- `cast_num` casts a `num` into any type which has `0`, `1` and `+`. -/ def cast_num [z : has_zero α] : num → α | 0 := 0 | (num.pos p) := cast_pos_num p -- see Note [coercion into rings] @[priority 900] instance pos_num_coe : has_coe_t pos_num α := ⟨cast_pos_num⟩ -- see Note [coercion into rings] @[priority 900] instance num_nat_coe [z : has_zero α] : has_coe_t num α := ⟨cast_num⟩ instance : has_repr pos_num := ⟨λ n, repr (n : ℕ)⟩ instance : has_repr num := ⟨λ n, repr (n : ℕ)⟩ end namespace num open pos_num /-- The successor of a `num` as a `pos_num`. -/ def succ' : num → pos_num | 0 := 1 | (pos p) := succ p /-- The successor of a `num` as a `num`. -/ def succ (n : num) : num := pos (succ' n) /-- Addition of two `num`s. -/ protected def add : num → num → num | 0 a := a | b 0 := b | (pos a) (pos b) := pos (a + b) instance : has_add num := ⟨num.add⟩ /-- `bit0 n` appends a `0` to the end of `n`, where `bit0 n = n0`. -/ protected def bit0 : num → num | 0 := 0 | (pos n) := pos (pos_num.bit0 n) /-- `bit1 n` appends a `1` to the end of `n`, where `bit1 n = n1`. -/ protected def bit1 : num → num | 0 := 1 | (pos n) := pos (pos_num.bit1 n) /-- `bit b n` appends the bit `b` to the end of `n`, where `bit tt x = x1` and `bit ff x = x0`. -/ def bit (b : bool) : num → num := cond b num.bit1 num.bit0 /-- The number of bits required to represent a `num`, as a `num`. `size 0` is defined to be `0`. -/ def size : num → num | 0 := 0 | (pos n) := pos (pos_num.size n) /-- The number of bits required to represent a `num`, as a `nat`. `size 0` is defined to be `0`. -/ def nat_size : num → nat | 0 := 0 | (pos n) := pos_num.nat_size n /-- Multiplication of two `num`s. -/ protected def mul : num → num → num | 0 _ := 0 | _ 0 := 0 | (pos a) (pos b) := pos (a * b) instance : has_mul num := ⟨num.mul⟩ open ordering /-- Ordering of `num`s. -/ def cmp : num → num → ordering | 0 0 := eq | _ 0 := gt | 0 _ := lt | (pos a) (pos b) := pos_num.cmp a b instance : has_lt num := ⟨λa b, cmp a b = ordering.lt⟩ instance : has_le num := ⟨λa b, ¬ b < a⟩ instance decidable_lt : @decidable_rel num (<) | a b := by dsimp [(<)]; apply_instance instance decidable_le : @decidable_rel num (≤) | a b := by dsimp [(≤)]; apply_instance /-- Converts a `num` to a `znum`. -/ def to_znum : num → znum | 0 := 0 | (pos a) := znum.pos a /-- Converts `x : num` to `-x : znum`. -/ def to_znum_neg : num → znum | 0 := 0 | (pos a) := znum.neg a /-- Converts a `nat` to a `num`. -/ def of_nat' : ℕ → num := nat.binary_rec 0 (λ b n, cond b num.bit1 num.bit0) end num namespace znum open pos_num /-- The negation of a `znum`. -/ def zneg : znum → znum | 0 := 0 | (pos a) := neg a | (neg a) := pos a instance : has_neg znum := ⟨zneg⟩ /-- The absolute value of a `znum` as a `num`. -/ def abs : znum → num | 0 := 0 | (pos a) := num.pos a | (neg a) := num.pos a /-- The successor of a `znum`. -/ def succ : znum → znum | 0 := 1 | (pos a) := pos (pos_num.succ a) | (neg a) := (pos_num.pred' a).to_znum_neg /-- The predecessor of a `znum`. -/ def pred : znum → znum | 0 := neg 1 | (pos a) := (pos_num.pred' a).to_znum | (neg a) := neg (pos_num.succ a) /-- `bit0 n` appends a `0` to the end of `n`, where `bit0 n = n0`. -/ protected def bit0 : znum → znum | 0 := 0 | (pos n) := pos (pos_num.bit0 n) | (neg n) := neg (pos_num.bit0 n) /-- `bit1 x` appends a `1` to the end of `x`, mapping `x` to `2 * x + 1`. -/ protected def bit1 : znum → znum | 0 := 1 | (pos n) := pos (pos_num.bit1 n) | (neg n) := neg (num.cases_on (pred' n) 1 pos_num.bit1) /-- `bitm1 x` appends a `1` to the end of `x`, mapping `x` to `2 * x - 1`. -/ protected def bitm1 : znum → znum | 0 := neg 1 | (pos n) := pos (num.cases_on (pred' n) 1 pos_num.bit1) | (neg n) := neg (pos_num.bit1 n) /-- Converts an `int` to a `znum`. -/ def of_int' : ℤ → znum | (n : ℕ) := num.to_znum (num.of_nat' n) | -[1+ n] := num.to_znum_neg (num.of_nat' (n+1)) end znum namespace pos_num open znum /-- Subtraction of two `pos_num`s, producing a `znum`. -/ def sub' : pos_num → pos_num → znum | a 1 := (pred' a).to_znum | 1 b := (pred' b).to_znum_neg | (bit0 a) (bit0 b) := (sub' a b).bit0 | (bit0 a) (bit1 b) := (sub' a b).bitm1 | (bit1 a) (bit0 b) := (sub' a b).bit1 | (bit1 a) (bit1 b) := (sub' a b).bit0 /-- Converts a `znum` to `option pos_num`, where it is `some` if the `znum` was positive and `none` otherwise. -/ def of_znum' : znum → option pos_num | (znum.pos p) := some p | _ := none /-- Converts a `znum` to a `pos_num`, mapping all out of range values to `1`. -/ def of_znum : znum → pos_num | (znum.pos p) := p | _ := 1 /-- Subtraction of `pos_num`s, where if `a < b`, then `a - b = 1`. -/ protected def sub (a b : pos_num) : pos_num := match sub' a b with | (znum.pos p) := p | _ := 1 end instance : has_sub pos_num := ⟨pos_num.sub⟩ end pos_num namespace num /-- The predecessor of a `num` as an `option num`, where `ppred 0 = none` -/ def ppred : num → option num | 0 := none | (pos p) := some p.pred' /-- The predecessor of a `num` as a `num`, where `pred 0 = 0`. -/ def pred : num → num | 0 := 0 | (pos p) := p.pred' /-- Divides a `num` by `2` -/ def div2 : num → num | 0 := 0 | 1 := 0 | (pos (pos_num.bit0 p)) := pos p | (pos (pos_num.bit1 p)) := pos p /-- Converts a `znum` to an `option num`, where `of_znum' p = none` if `p < 0`. -/ def of_znum' : znum → option num | 0 := some 0 | (znum.pos p) := some (pos p) | (znum.neg p) := none /-- Converts a `znum` to an `option num`, where `of_znum p = 0` if `p < 0`. -/ def of_znum : znum → num | (znum.pos p) := pos p | _ := 0 /-- Subtraction of two `num`s, producing a `znum`. -/ def sub' : num → num → znum | 0 0 := 0 | (pos a) 0 := znum.pos a | 0 (pos b) := znum.neg b | (pos a) (pos b) := a.sub' b /-- Subtraction of two `num`s, producing an `option num`. -/ def psub (a b : num) : option num := of_znum' (sub' a b) /-- Subtraction of two `num`s, where if `a < b`, `a - b = 0`. -/ protected def sub (a b : num) : num := of_znum (sub' a b) instance : has_sub num := ⟨num.sub⟩ end num namespace znum open pos_num /-- Addition of `znum`s. -/ protected def add : znum → znum → znum | 0 a := a | b 0 := b | (pos a) (pos b) := pos (a + b) | (pos a) (neg b) := sub' a b | (neg a) (pos b) := sub' b a | (neg a) (neg b) := neg (a + b) instance : has_add znum := ⟨znum.add⟩ /-- Multiplication of `znum`s. -/ protected def mul : znum → znum → znum | 0 a := 0 | b 0 := 0 | (pos a) (pos b) := pos (a * b) | (pos a) (neg b) := neg (a * b) | (neg a) (pos b) := neg (a * b) | (neg a) (neg b) := pos (a * b) instance : has_mul znum := ⟨znum.mul⟩ open ordering /-- Ordering on `znum`s. -/ def cmp : znum → znum → ordering | 0 0 := eq | (pos a) (pos b) := pos_num.cmp a b | (neg a) (neg b) := pos_num.cmp b a | (pos _) _ := gt | (neg _) _ := lt | _ (pos _) := lt | _ (neg _) := gt instance : has_lt znum := ⟨λa b, cmp a b = ordering.lt⟩ instance : has_le znum := ⟨λa b, ¬ b < a⟩ instance decidable_lt : @decidable_rel znum (<) | a b := by dsimp [(<)]; apply_instance instance decidable_le : @decidable_rel znum (≤) | a b := by dsimp [(≤)]; apply_instance end znum namespace pos_num /-- Auxiliary definition for `pos_num.divmod`. -/ def divmod_aux (d : pos_num) (q r : num) : num × num := match num.of_znum' (num.sub' r (num.pos d)) with | some r' := (num.bit1 q, r') | none := (num.bit0 q, r) end /-- `divmod x y = (y / x, y % x)`. -/ def divmod (d : pos_num) : pos_num → num × num | (bit0 n) := let (q, r₁) := divmod n in divmod_aux d q (num.bit0 r₁) | (bit1 n) := let (q, r₁) := divmod n in divmod_aux d q (num.bit1 r₁) | 1 := divmod_aux d 0 1 /-- Division of `pos_num`, -/ def div' (n d : pos_num) : num := (divmod d n).1 /-- Modulus of `pos_num`s. -/ def mod' (n d : pos_num) : num := (divmod d n).2 /- private def sqrt_aux1 (b : pos_num) (r n : num) : num × num := match num.of_znum' (n.sub' (r + num.pos b)) with | some n' := (r.div2 + num.pos b, n') | none := (r.div2, n) end private def sqrt_aux : pos_num → num → num → num | b@(bit0 b') r n := let (r', n') := sqrt_aux1 b r n in sqrt_aux b' r' n' | b@(bit1 b') r n := let (r', n') := sqrt_aux1 b r n in sqrt_aux b' r' n' | 1 r n := (sqrt_aux1 1 r n).1 -/ /- def sqrt_aux : ℕ → ℕ → ℕ → ℕ | b r n := if b0 : b = 0 then r else let b' := shiftr b 2 in have b' < b, from sqrt_aux_dec b0, match (n - (r + b : ℕ) : ℤ) with | (n' : ℕ) := sqrt_aux b' (div2 r + b) n' | _ := sqrt_aux b' (div2 r) n end /-- `sqrt n` is the square root of a natural number `n`. If `n` is not a perfect square, it returns the largest `k:ℕ` such that `k*k ≤ n`. -/ def sqrt (n : ℕ) : ℕ := match size n with | 0 := 0 | succ s := sqrt_aux (shiftl 1 (bit0 (div2 s))) 0 n end -/ end pos_num namespace num /-- Division of `num`s, where `x / 0 = 0`. -/ def div : num → num → num | 0 _ := 0 | _ 0 := 0 | (pos n) (pos d) := pos_num.div' n d /-- Modulus of `num`s. -/ def mod : num → num → num | 0 _ := 0 | n 0 := n | (pos n) (pos d) := pos_num.mod' n d instance : has_div num := ⟨num.div⟩ instance : has_mod num := ⟨num.mod⟩ /-- Auxiliary definition for `num.gcd`. -/ def gcd_aux : nat → num → num → num | 0 a b := b | (nat.succ n) 0 b := b | (nat.succ n) a b := gcd_aux n (b % a) a /-- Greatest Common Divisor (GCD) of two `num`s. -/ def gcd (a b : num) : num := if a ≤ b then gcd_aux (a.nat_size + b.nat_size) a b else gcd_aux (b.nat_size + a.nat_size) b a end num namespace znum /-- Division of `znum`, where `x / 0 = 0`. -/ def div : znum → znum → znum | 0 _ := 0 | _ 0 := 0 | (pos n) (pos d) := num.to_znum (pos_num.div' n d) | (pos n) (neg d) := num.to_znum_neg (pos_num.div' n d) | (neg n) (pos d) := neg (pos_num.pred' n / num.pos d).succ' | (neg n) (neg d) := pos (pos_num.pred' n / num.pos d).succ' /-- Modulus of `znum`s. -/ def mod : znum → znum → znum | 0 d := 0 | (pos n) d := num.to_znum (num.pos n % d.abs) | (neg n) d := d.abs.sub' (pos_num.pred' n % d.abs).succ instance : has_div znum := ⟨znum.div⟩ instance : has_mod znum := ⟨znum.mod⟩ /-- Greatest Common Divisor (GCD) of two `znum`s. -/ def gcd (a b : znum) : num := a.abs.gcd b.abs end znum section variables {α : Type*} [has_zero α] [has_one α] [has_add α] [has_neg α] /-- `cast_znum` casts a `znum` into any type which has `0`, `1`, `+` and `neg` -/ def cast_znum : znum → α | 0 := 0 | (znum.pos p) := p | (znum.neg p) := -p -- see Note [coercion into rings] @[priority 900] instance znum_coe : has_coe_t znum α := ⟨cast_znum⟩ instance : has_repr znum := ⟨λ n, repr (n : ℤ)⟩ end