/- 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 -/ #align_import data.num.basic from "leanprover-community/mathlib"@"448144f7ae193a8990cb7473c9e9a01990f64ac7" /-! # 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. -/ #print PosNum /- /-- The type of positive binary numbers. 13 = 1101(base 2) = bit1 (bit0 (bit1 one)) -/ inductive PosNum : Type | one : PosNum | bit1 : PosNum → PosNum | bit0 : PosNum → PosNum deriving has_reflect, DecidableEq #align pos_num PosNum -/ instance : One PosNum := ⟨PosNum.one⟩ instance : Inhabited PosNum := ⟨1⟩ #print Num /- /-- The type of nonnegative binary numbers, using `pos_num`. 13 = 1101(base 2) = pos (bit1 (bit0 (bit1 one))) -/ inductive Num : Type | zero : Num | Pos : PosNum → Num deriving has_reflect, DecidableEq #align num Num -/ instance : Zero Num := ⟨Num.zero⟩ instance : One Num := ⟨Num.pos 1⟩ instance : Inhabited Num := ⟨0⟩ #print ZNum /- /-- 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))) -/ inductive ZNum : Type | zero : ZNum | Pos : PosNum → ZNum | neg : PosNum → ZNum deriving has_reflect, DecidableEq #align znum ZNum -/ instance : Zero ZNum := ⟨ZNum.zero⟩ instance : One ZNum := ⟨ZNum.pos 1⟩ instance : Inhabited ZNum := ⟨0⟩ namespace PosNum #print PosNum.bit /- /-- `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) : PosNum → PosNum := cond b bit1 bit0 #align pos_num.bit PosNum.bit -/ #print PosNum.succ /- /-- The successor of a `pos_num`. -/ def succ : PosNum → PosNum | 1 => bit0 one | bit1 n => bit0 (succ n) | bit0 n => bit1 n #align pos_num.succ PosNum.succ -/ #print PosNum.isOne /- /-- Returns a boolean for whether the `pos_num` is `one`. -/ def isOne : PosNum → Bool | 1 => true | _ => false #align pos_num.is_one PosNum.isOne -/ #print PosNum.add /- /-- Addition of two `pos_num`s. -/ protected def add : PosNum → PosNum → PosNum | 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) #align pos_num.add PosNum.add -/ instance : Add PosNum := ⟨PosNum.add⟩ #print PosNum.pred' /- /-- The predecessor of a `pos_num` as a `num`. -/ def pred' : PosNum → Num | 1 => 0 | bit0 n => Num.pos (Num.casesOn (pred' n) 1 bit1) | bit1 n => Num.pos (bit0 n) #align pos_num.pred' PosNum.pred' -/ #print PosNum.pred /- /-- The predecessor of a `pos_num` as a `pos_num`. This means that `pred 1 = 1`. -/ def pred (a : PosNum) : PosNum := Num.casesOn (pred' a) 1 id #align pos_num.pred PosNum.pred -/ #print PosNum.size /- /-- The number of bits of a `pos_num`, as a `pos_num`. -/ def size : PosNum → PosNum | 1 => 1 | bit0 n => succ (size n) | bit1 n => succ (size n) #align pos_num.size PosNum.size -/ #print PosNum.natSize /- /-- The number of bits of a `pos_num`, as a `nat`. -/ def natSize : PosNum → Nat | 1 => 1 | bit0 n => Nat.succ (nat_size n) | bit1 n => Nat.succ (nat_size n) #align pos_num.nat_size PosNum.natSize -/ #print PosNum.mul /- /-- Multiplication of two `pos_num`s. -/ protected def mul (a : PosNum) : PosNum → PosNum | 1 => a | bit0 b => bit0 (mul b) | bit1 b => bit0 (mul b) + a #align pos_num.mul PosNum.mul -/ instance : Mul PosNum := ⟨PosNum.mul⟩ #print PosNum.ofNatSucc /- /-- `of_nat_succ n` is the `pos_num` corresponding to `n + 1`. -/ def ofNatSucc : ℕ → PosNum | 0 => 1 | Nat.succ n => succ (of_nat_succ n) #align pos_num.of_nat_succ PosNum.ofNatSucc -/ #print PosNum.ofNat /- /-- `of_nat n` is the `pos_num` corresponding to `n`, except for `of_nat 0 = 1`. -/ def ofNat (n : ℕ) : PosNum := ofNatSucc (Nat.pred n) #align pos_num.of_nat PosNum.ofNat -/ open Ordering #print PosNum.cmp /- /-- Ordering of `pos_num`s. -/ def cmp : PosNum → PosNum → Ordering | 1, 1 => Eq | _, 1 => GT.gt | 1, _ => lt | bit0 a, bit0 b => cmp a b | bit0 a, bit1 b => Ordering.casesOn (cmp a b) lt lt GT.gt | bit1 a, bit0 b => Ordering.casesOn (cmp a b) lt GT.gt GT.gt | bit1 a, bit1 b => cmp a b #align pos_num.cmp PosNum.cmp -/ instance : LT PosNum := ⟨fun a b => cmp a b = Ordering.lt⟩ instance : LE PosNum := ⟨fun a b => ¬b < a⟩ #print PosNum.decidableLT /- instance decidableLT : @DecidableRel PosNum (· < ·) | a, b => by dsimp [(· < ·)] <;> infer_instance #align pos_num.decidable_lt PosNum.decidableLT -/ #print PosNum.decidableLE /- instance decidableLE : @DecidableRel PosNum (· ≤ ·) | a, b => by dsimp [(· ≤ ·)] <;> infer_instance #align pos_num.decidable_le PosNum.decidableLE -/ end PosNum section variable {α : Type _} [One α] [Add α] #print castPosNum /- /-- `cast_pos_num` casts a `pos_num` into any type which has `1` and `+`. -/ def castPosNum : PosNum → α | 1 => 1 | PosNum.bit0 a => bit0 (castPosNum a) | PosNum.bit1 a => bit1 (castPosNum a) #align cast_pos_num castPosNum -/ #print castNum /- /-- `cast_num` casts a `num` into any type which has `0`, `1` and `+`. -/ def castNum [z : Zero α] : Num → α | 0 => 0 | Num.pos p => castPosNum p #align cast_num castNum -/ #print posNumCoe /- -- see Note [coercion into rings] instance (priority := 900) posNumCoe : CoeTC PosNum α := ⟨castPosNum⟩ #align pos_num_coe posNumCoe -/ #print numNatCoe /- -- see Note [coercion into rings] instance (priority := 900) numNatCoe [z : Zero α] : CoeTC Num α := ⟨castNum⟩ #align num_nat_coe numNatCoe -/ instance : Repr PosNum := ⟨fun n => repr (n : ℕ)⟩ instance : Repr Num := ⟨fun n => repr (n : ℕ)⟩ end namespace Num open PosNum #print Num.succ' /- /-- The successor of a `num` as a `pos_num`. -/ def succ' : Num → PosNum | 0 => 1 | Pos p => succ p #align num.succ' Num.succ' -/ #print Num.succ /- /-- The successor of a `num` as a `num`. -/ def succ (n : Num) : Num := pos (succ' n) #align num.succ Num.succ -/ #print Num.add /- /-- Addition of two `num`s. -/ protected def add : Num → Num → Num | 0, a => a | b, 0 => b | Pos a, Pos b => pos (a + b) #align num.add Num.add -/ instance : Add Num := ⟨Num.add⟩ #print Num.bit0 /- /-- `bit0 n` appends a `0` to the end of `n`, where `bit0 n = n0`. -/ protected def bit0 : Num → Num | 0 => 0 | Pos n => pos (PosNum.bit0 n) #align num.bit0 Num.bit0 -/ #print Num.bit1 /- /-- `bit1 n` appends a `1` to the end of `n`, where `bit1 n = n1`. -/ protected def bit1 : Num → Num | 0 => 1 | Pos n => pos (PosNum.bit1 n) #align num.bit1 Num.bit1 -/ #print Num.bit /- /-- `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 #align num.bit Num.bit -/ #print Num.size /- /-- 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 (PosNum.size n) #align num.size Num.size -/ #print Num.natSize /- /-- The number of bits required to represent a `num`, as a `nat`. `size 0` is defined to be `0`. -/ def natSize : Num → Nat | 0 => 0 | Pos n => PosNum.natSize n #align num.nat_size Num.natSize -/ #print Num.mul /- /-- Multiplication of two `num`s. -/ protected def mul : Num → Num → Num | 0, _ => 0 | _, 0 => 0 | Pos a, Pos b => pos (a * b) #align num.mul Num.mul -/ instance : Mul Num := ⟨Num.mul⟩ open Ordering #print Num.cmp /- /-- Ordering of `num`s. -/ def cmp : Num → Num → Ordering | 0, 0 => Eq | _, 0 => GT.gt | 0, _ => lt | Pos a, Pos b => PosNum.cmp a b #align num.cmp Num.cmp -/ instance : LT Num := ⟨fun a b => cmp a b = Ordering.lt⟩ instance : LE Num := ⟨fun a b => ¬b < a⟩ #print Num.decidableLT /- instance decidableLT : @DecidableRel Num (· < ·) | a, b => by dsimp [(· < ·)] <;> infer_instance #align num.decidable_lt Num.decidableLT -/ #print Num.decidableLE /- instance decidableLE : @DecidableRel Num (· ≤ ·) | a, b => by dsimp [(· ≤ ·)] <;> infer_instance #align num.decidable_le Num.decidableLE -/ #print Num.toZNum /- /-- Converts a `num` to a `znum`. -/ def toZNum : Num → ZNum | 0 => 0 | Pos a => ZNum.pos a #align num.to_znum Num.toZNum -/ #print Num.toZNumNeg /- /-- Converts `x : num` to `-x : znum`. -/ def toZNumNeg : Num → ZNum | 0 => 0 | Pos a => ZNum.neg a #align num.to_znum_neg Num.toZNumNeg -/ #print Num.ofNat' /- /-- Converts a `nat` to a `num`. -/ def ofNat' : ℕ → Num := Nat.binaryRec 0 fun b n => cond b Num.bit1 Num.bit0 #align num.of_nat' Num.ofNat' -/ end Num namespace ZNum open PosNum #print ZNum.zNeg /- /-- The negation of a `znum`. -/ def zNeg : ZNum → ZNum | 0 => 0 | Pos a => neg a | neg a => pos a #align znum.zneg ZNum.zNeg -/ instance : Neg ZNum := ⟨zNeg⟩ #print ZNum.abs /- /-- 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 #align znum.abs ZNum.abs -/ #print ZNum.succ /- /-- The successor of a `znum`. -/ def succ : ZNum → ZNum | 0 => 1 | Pos a => pos (PosNum.succ a) | neg a => (PosNum.pred' a).toZNumNeg #align znum.succ ZNum.succ -/ #print ZNum.pred /- /-- The predecessor of a `znum`. -/ def pred : ZNum → ZNum | 0 => neg 1 | Pos a => (PosNum.pred' a).toZNum | neg a => neg (PosNum.succ a) #align znum.pred ZNum.pred -/ #print ZNum.bit0 /- /-- `bit0 n` appends a `0` to the end of `n`, where `bit0 n = n0`. -/ protected def bit0 : ZNum → ZNum | 0 => 0 | Pos n => pos (PosNum.bit0 n) | neg n => neg (PosNum.bit0 n) #align znum.bit0 ZNum.bit0 -/ #print ZNum.bit1 /- /-- `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 (PosNum.bit1 n) | neg n => neg (Num.casesOn (pred' n) 1 PosNum.bit1) #align znum.bit1 ZNum.bit1 -/ #print ZNum.bitm1 /- /-- `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.casesOn (pred' n) 1 PosNum.bit1) | neg n => neg (PosNum.bit1 n) #align znum.bitm1 ZNum.bitm1 -/ #print ZNum.ofInt' /- /-- Converts an `int` to a `znum`. -/ def ofInt' : ℤ → ZNum | (n : ℕ) => Num.toZNum (Num.ofNat' n) | -[n+1] => Num.toZNumNeg (Num.ofNat' (n + 1)) #align znum.of_int' ZNum.ofInt' -/ end ZNum namespace PosNum open ZNum #print PosNum.sub' /- /-- Subtraction of two `pos_num`s, producing a `znum`. -/ def sub' : PosNum → PosNum → ZNum | a, 1 => (pred' a).toZNum | 1, b => (pred' b).toZNumNeg | 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 #align pos_num.sub' PosNum.sub' -/ #print PosNum.ofZNum' /- /-- Converts a `znum` to `option pos_num`, where it is `some` if the `znum` was positive and `none` otherwise. -/ def ofZNum' : ZNum → Option PosNum | ZNum.pos p => some p | _ => none #align pos_num.of_znum' PosNum.ofZNum' -/ #print PosNum.ofZNum /- /-- Converts a `znum` to a `pos_num`, mapping all out of range values to `1`. -/ def ofZNum : ZNum → PosNum | ZNum.pos p => p | _ => 1 #align pos_num.of_znum PosNum.ofZNum -/ #print PosNum.sub /- /-- Subtraction of `pos_num`s, where if `a < b`, then `a - b = 1`. -/ protected def sub (a b : PosNum) : PosNum := match sub' a b with | ZNum.pos p => p | _ => 1 #align pos_num.sub PosNum.sub -/ instance : Sub PosNum := ⟨PosNum.sub⟩ end PosNum namespace Num #print Num.ppred /- /-- 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' #align num.ppred Num.ppred -/ #print Num.pred /- /-- The predecessor of a `num` as a `num`, where `pred 0 = 0`. -/ def pred : Num → Num | 0 => 0 | Pos p => p.pred' #align num.pred Num.pred -/ #print Num.div2 /- /-- Divides a `num` by `2` -/ def div2 : Num → Num | 0 => 0 | 1 => 0 | Pos (PosNum.bit0 p) => pos p | Pos (PosNum.bit1 p) => pos p #align num.div2 Num.div2 -/ #print Num.ofZNum' /- /-- Converts a `znum` to an `option num`, where `of_znum' p = none` if `p < 0`. -/ def ofZNum' : ZNum → Option Num | 0 => some 0 | ZNum.pos p => some (pos p) | ZNum.neg p => none #align num.of_znum' Num.ofZNum' -/ #print Num.ofZNum /- /-- Converts a `znum` to an `option num`, where `of_znum p = 0` if `p < 0`. -/ def ofZNum : ZNum → Num | ZNum.pos p => pos p | _ => 0 #align num.of_znum Num.ofZNum -/ #print Num.sub' /- /-- 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 #align num.sub' Num.sub' -/ #print Num.psub /- /-- Subtraction of two `num`s, producing an `option num`. -/ def psub (a b : Num) : Option Num := ofZNum' (sub' a b) #align num.psub Num.psub -/ #print Num.sub /- /-- Subtraction of two `num`s, where if `a < b`, `a - b = 0`. -/ protected def sub (a b : Num) : Num := ofZNum (sub' a b) #align num.sub Num.sub -/ instance : Sub Num := ⟨Num.sub⟩ end Num namespace ZNum open PosNum #print ZNum.add /- /-- 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) #align znum.add ZNum.add -/ instance : Add ZNum := ⟨ZNum.add⟩ #print ZNum.mul /- /-- 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) #align znum.mul ZNum.mul -/ instance : Mul ZNum := ⟨ZNum.mul⟩ open Ordering #print ZNum.cmp /- /-- Ordering on `znum`s. -/ def cmp : ZNum → ZNum → Ordering | 0, 0 => Eq | Pos a, Pos b => PosNum.cmp a b | neg a, neg b => PosNum.cmp b a | Pos _, _ => GT.gt | neg _, _ => lt | _, Pos _ => lt | _, neg _ => GT.gt #align znum.cmp ZNum.cmp -/ instance : LT ZNum := ⟨fun a b => cmp a b = Ordering.lt⟩ instance : LE ZNum := ⟨fun a b => ¬b < a⟩ #print ZNum.decidableLT /- instance decidableLT : @DecidableRel ZNum (· < ·) | a, b => by dsimp [(· < ·)] <;> infer_instance #align znum.decidable_lt ZNum.decidableLT -/ #print ZNum.decidableLE /- instance decidableLE : @DecidableRel ZNum (· ≤ ·) | a, b => by dsimp [(· ≤ ·)] <;> infer_instance #align znum.decidable_le ZNum.decidableLE -/ end ZNum namespace PosNum #print PosNum.divModAux /- /-- Auxiliary definition for `pos_num.divmod`. -/ def divModAux (d : PosNum) (q r : Num) : Num × Num := match Num.ofZNum' (Num.sub' r (Num.pos d)) with | some r' => (Num.bit1 q, r') | none => (Num.bit0 q, r) #align pos_num.divmod_aux PosNum.divModAux -/ #print PosNum.divMod /- /-- `divmod x y = (y / x, y % x)`. -/ def divMod (d : PosNum) : PosNum → Num × Num | bit0 n => let (q, r₁) := divmod n divModAux d q (Num.bit0 r₁) | bit1 n => let (q, r₁) := divmod n divModAux d q (Num.bit1 r₁) | 1 => divModAux d 0 1 #align pos_num.divmod PosNum.divMod -/ #print PosNum.div' /- /-- Division of `pos_num`, -/ def div' (n d : PosNum) : Num := (divMod d n).1 #align pos_num.div' PosNum.div' -/ #print PosNum.mod' /- /-- Modulus of `pos_num`s. -/ def mod' (n d : PosNum) : Num := (divMod d n).2 #align pos_num.mod' PosNum.mod' -/ /- 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 PosNum namespace Num #print Num.div /- /-- Division of `num`s, where `x / 0 = 0`. -/ def div : Num → Num → Num | 0, _ => 0 | _, 0 => 0 | Pos n, Pos d => PosNum.div' n d #align num.div Num.div -/ #print Num.mod /- /-- Modulus of `num`s. -/ def mod : Num → Num → Num | 0, _ => 0 | n, 0 => n | Pos n, Pos d => PosNum.mod' n d #align num.mod Num.mod -/ instance : Div Num := ⟨Num.div⟩ instance : Mod Num := ⟨Num.mod⟩ #print Num.gcdAux /- /-- Auxiliary definition for `num.gcd`. -/ def gcdAux : 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 #align num.gcd_aux Num.gcdAux -/ #print Num.gcd /- /-- Greatest Common Divisor (GCD) of two `num`s. -/ def gcd (a b : Num) : Num := if a ≤ b then gcdAux (a.natSize + b.natSize) a b else gcdAux (b.natSize + a.natSize) b a #align num.gcd Num.gcd -/ end Num namespace ZNum #print ZNum.div /- /-- Division of `znum`, where `x / 0 = 0`. -/ def div : ZNum → ZNum → ZNum | 0, _ => 0 | _, 0 => 0 | Pos n, Pos d => Num.toZNum (PosNum.div' n d) | Pos n, neg d => Num.toZNumNeg (PosNum.div' n d) | neg n, Pos d => neg (PosNum.pred' n / Num.pos d).succ' | neg n, neg d => pos (PosNum.pred' n / Num.pos d).succ' #align znum.div ZNum.div -/ #print ZNum.mod /- /-- Modulus of `znum`s. -/ def mod : ZNum → ZNum → ZNum | 0, d => 0 | Pos n, d => Num.toZNum (Num.pos n % d.abs) | neg n, d => d.abs.sub' (PosNum.pred' n % d.abs).succ #align znum.mod ZNum.mod -/ instance : Div ZNum := ⟨ZNum.div⟩ instance : Mod ZNum := ⟨ZNum.mod⟩ #print ZNum.gcd /- /-- Greatest Common Divisor (GCD) of two `znum`s. -/ def gcd (a b : ZNum) : Num := a.abs.gcd b.abs #align znum.gcd ZNum.gcd -/ end ZNum section variable {α : Type _} [Zero α] [One α] [Add α] [Neg α] #print castZNum /- /-- `cast_znum` casts a `znum` into any type which has `0`, `1`, `+` and `neg` -/ def castZNum : ZNum → α | 0 => 0 | ZNum.pos p => p | ZNum.neg p => -p #align cast_znum castZNum -/ #print znumCoe /- -- see Note [coercion into rings] instance (priority := 900) znumCoe : CoeTC ZNum α := ⟨castZNum⟩ #align znum_coe znumCoe -/ instance : Repr ZNum := ⟨fun n => repr (n : ℤ)⟩ end