From 17c18752ffb61c793f88eee4255dd33d5bee2c07 Mon Sep 17 00:00:00 2001 From: Markus Himmel Date: Thu, 27 Mar 2025 16:17:56 +0100 Subject: [PATCH] feat: `IntX` operations and conversion theory (#7592) This PR adds theory about signed finite integers relating operations and conversion functions. --- src/Init/Data/SInt/Bitwise.lean | 712 ++++++- src/Init/Data/SInt/Lemmas.lean | 1802 ++++++++++++++++- src/Init/Data/UInt/Bitwise.lean | 902 ++++++++- src/Init/Data/UInt/Lemmas.lean | 1019 +++++++++- tests/lean/interactive/compNamespace.lean | 12 +- .../compNamespace.lean.expected.out | 12 +- tests/lean/run/simprocSInt.lean | 8 +- 7 files changed, 4403 insertions(+), 64 deletions(-) diff --git a/src/Init/Data/SInt/Bitwise.lean b/src/Init/Data/SInt/Bitwise.lean index 8e4f59dbfb..b5a6573130 100644 --- a/src/Init/Data/SInt/Bitwise.lean +++ b/src/Init/Data/SInt/Bitwise.lean @@ -12,11 +12,6 @@ macro "declare_bitwise_int_theorems" typeName:ident bits:term:arg : command => `( namespace $typeName -@[simp, int_toBitVec] protected theorem toBitVec_add {a b : $typeName} : (a + b).toBitVec = a.toBitVec + b.toBitVec := rfl -@[simp, int_toBitVec] protected theorem toBitVec_sub {a b : $typeName} : (a - b).toBitVec = a.toBitVec - b.toBitVec := rfl -@[simp, int_toBitVec] protected theorem toBitVec_mul {a b : $typeName} : (a * b).toBitVec = a.toBitVec * b.toBitVec := rfl -@[simp, int_toBitVec] protected theorem toBitVec_div {a b : $typeName} : (a / b).toBitVec = a.toBitVec.sdiv b.toBitVec := rfl -@[simp, int_toBitVec] protected theorem toBitVec_mod {a b : $typeName} : (a % b).toBitVec = a.toBitVec.srem b.toBitVec := rfl @[simp, int_toBitVec] protected theorem toBitVec_not {a : $typeName} : (~~~a).toBitVec = ~~~a.toBitVec := rfl @[simp, int_toBitVec] protected theorem toBitVec_and (a b : $typeName) : (a &&& b).toBitVec = a.toBitVec &&& b.toBitVec := rfl @[simp, int_toBitVec] protected theorem toBitVec_or (a b : $typeName) : (a ||| b).toBitVec = a.toBitVec ||| b.toBitVec := rfl @@ -57,30 +52,6 @@ theorem Bool.toBitVec_toISize {b : Bool} : · apply BitVec.eq_of_toNat_eq simp [toISize] -@[simp] theorem UInt8.toInt8_add (a b : UInt8) : (a + b).toInt8 = a.toInt8 + b.toInt8 := rfl -@[simp] theorem UInt16.toInt16_add (a b : UInt16) : (a + b).toInt16 = a.toInt16 + b.toInt16 := rfl -@[simp] theorem UInt32.toInt32_add (a b : UInt32) : (a + b).toInt32 = a.toInt32 + b.toInt32 := rfl -@[simp] theorem UInt64.toInt64_add (a b : UInt64) : (a + b).toInt64 = a.toInt64 + b.toInt64 := rfl -@[simp] theorem USize.toISize_add (a b : USize) : (a + b).toISize = a.toISize + b.toISize := rfl - -@[simp] theorem UInt8.toInt8_neg (a : UInt8) : (-a).toInt8 = -a.toInt8 := rfl -@[simp] theorem UInt16.toInt16_neg (a : UInt16) : (-a).toInt16 = -a.toInt16 := rfl -@[simp] theorem UInt32.toInt32_neg (a : UInt32) : (-a).toInt32 = -a.toInt32 := rfl -@[simp] theorem UInt64.toInt64_neg (a : UInt64) : (-a).toInt64 = -a.toInt64 := rfl -@[simp] theorem USize.toISize_neg (a : USize) : (-a).toISize = -a.toISize := rfl - -@[simp] theorem UInt8.toInt8_sub (a b : UInt8) : (a - b).toInt8 = a.toInt8 - b.toInt8 := rfl -@[simp] theorem UInt16.toInt16_sub (a b : UInt16) : (a - b).toInt16 = a.toInt16 - b.toInt16 := rfl -@[simp] theorem UInt32.toInt32_sub (a b : UInt32) : (a - b).toInt32 = a.toInt32 - b.toInt32 := rfl -@[simp] theorem UInt64.toInt64_sub (a b : UInt64) : (a - b).toInt64 = a.toInt64 - b.toInt64 := rfl -@[simp] theorem USize.toISize_sub (a b : USize) : (a - b).toISize = a.toISize - b.toISize := rfl - -@[simp] theorem UInt8.toInt8_mul (a b : UInt8) : (a * b).toInt8 = a.toInt8 * b.toInt8 := rfl -@[simp] theorem UInt16.toInt16_mul (a b : UInt16) : (a * b).toInt16 = a.toInt16 * b.toInt16 := rfl -@[simp] theorem UInt32.toInt32_mul (a b : UInt32) : (a * b).toInt32 = a.toInt32 * b.toInt32 := rfl -@[simp] theorem UInt64.toInt64_mul (a b : UInt64) : (a * b).toInt64 = a.toInt64 * b.toInt64 := rfl -@[simp] theorem USize.toISize_mul (a b : USize) : (a * b).toISize = a.toISize * b.toISize := rfl - @[simp] theorem UInt8.toInt8_and (a b : UInt8) : (a &&& b).toInt8 = a.toInt8 &&& b.toInt8 := rfl @[simp] theorem UInt16.toInt16_and (a b : UInt16) : (a &&& b).toInt16 = a.toInt16 &&& b.toInt16 := rfl @[simp] theorem UInt32.toInt32_and (a b : UInt32) : (a &&& b).toInt32 = a.toInt32 &&& b.toInt32 := rfl @@ -104,3 +75,686 @@ theorem Bool.toBitVec_toISize {b : Bool} : @[simp] theorem UInt32.toInt32_not (a : UInt32) : (~~~a).toInt32 = ~~~a.toInt32 := rfl @[simp] theorem UInt64.toInt64_not (a : UInt64) : (~~~a).toInt64 = ~~~a.toInt64 := rfl @[simp] theorem USize.toISize_not (a : USize) : (~~~a).toISize = ~~~a.toISize := rfl + +@[simp] theorem Int8.toUInt8_and (a b : Int8) : (a &&& b).toUInt8 = a.toUInt8 &&& b.toUInt8 := rfl +@[simp] theorem Int16.toUInt16_and (a b : Int16) : (a &&& b).toUInt16 = a.toUInt16 &&& b.toUInt16 := rfl +@[simp] theorem Int32.toUInt32_and (a b : Int32) : (a &&& b).toUInt32 = a.toUInt32 &&& b.toUInt32 := rfl +@[simp] theorem Int64.toUInt64_and (a b : Int64) : (a &&& b).toUInt64 = a.toUInt64 &&& b.toUInt64 := rfl +@[simp] theorem ISize.toUSize_and (a b : ISize) : (a &&& b).toUSize = a.toUSize &&& b.toUSize := rfl + +@[simp] theorem Int8.toUInt8_or (a b : Int8) : (a ||| b).toUInt8 = a.toUInt8 ||| b.toUInt8 := rfl +@[simp] theorem Int16.toUInt16_or (a b : Int16) : (a ||| b).toUInt16 = a.toUInt16 ||| b.toUInt16 := rfl +@[simp] theorem Int32.toUInt32_or (a b : Int32) : (a ||| b).toUInt32 = a.toUInt32 ||| b.toUInt32 := rfl +@[simp] theorem Int64.toUInt64_or (a b : Int64) : (a ||| b).toUInt64 = a.toUInt64 ||| b.toUInt64 := rfl +@[simp] theorem ISize.toUSize_or (a b : ISize) : (a ||| b).toUSize = a.toUSize ||| b.toUSize := rfl + +@[simp] theorem Int8.toUInt8_xor (a b : Int8) : (a ^^^ b).toUInt8 = a.toUInt8 ^^^ b.toUInt8 := rfl +@[simp] theorem Int16.toUInt16_xor (a b : Int16) : (a ^^^ b).toUInt16 = a.toUInt16 ^^^ b.toUInt16 := rfl +@[simp] theorem Int32.toUInt32_xor (a b : Int32) : (a ^^^ b).toUInt32 = a.toUInt32 ^^^ b.toUInt32 := rfl +@[simp] theorem Int64.toUInt64_xor (a b : Int64) : (a ^^^ b).toUInt64 = a.toUInt64 ^^^ b.toUInt64 := rfl +@[simp] theorem ISize.toUSize_xor (a b : ISize) : (a ^^^ b).toUSize = a.toUSize ^^^ b.toUSize := rfl + +@[simp] theorem Int8.toUInt8_not (a : Int8) : (~~~a).toUInt8 = ~~~a.toUInt8 := rfl +@[simp] theorem Int16.toUInt16_not (a : Int16) : (~~~a).toUInt16 = ~~~a.toUInt16 := rfl +@[simp] theorem Int32.toUInt32_not (a : Int32) : (~~~a).toUInt32 = ~~~a.toUInt32 := rfl +@[simp] theorem Int64.toUInt64_not (a : Int64) : (~~~a).toUInt64 = ~~~a.toUInt64 := rfl +@[simp] theorem ISize.toUSize_not (a : ISize) : (~~~a).toUSize = ~~~a.toUSize := rfl + +@[simp] theorem Int8.toInt16_and (a b : Int8) : (a &&& b).toInt16 = a.toInt16 &&& b.toInt16 := Int16.toBitVec_inj.1 (by simp) +@[simp] theorem Int8.toInt32_and (a b : Int8) : (a &&& b).toInt32 = a.toInt32 &&& b.toInt32 := Int32.toBitVec_inj.1 (by simp) +@[simp] theorem Int8.toInt64_and (a b : Int8) : (a &&& b).toInt64 = a.toInt64 &&& b.toInt64 := Int64.toBitVec_inj.1 (by simp) +@[simp] theorem Int8.toISize_and (a b : Int8) : (a &&& b).toISize = a.toISize &&& b.toISize := ISize.toBitVec_inj.1 (by simp) + +@[simp] theorem Int16.toInt8_and (a b : Int16) : (a &&& b).toInt8 = a.toInt8 &&& b.toInt8 := Int8.toBitVec_inj.1 (by simp) +@[simp] theorem Int16.toInt32_and (a b : Int16) : (a &&& b).toInt32 = a.toInt32 &&& b.toInt32 := Int32.toBitVec_inj.1 (by simp) +@[simp] theorem Int16.toInt64_and (a b : Int16) : (a &&& b).toInt64 = a.toInt64 &&& b.toInt64 := Int64.toBitVec_inj.1 (by simp) +@[simp] theorem Int16.toISize_and (a b : Int16) : (a &&& b).toISize = a.toISize &&& b.toISize := ISize.toBitVec_inj.1 (by simp) + +@[simp] theorem Int32.toInt8_and (a b : Int32) : (a &&& b).toInt8 = a.toInt8 &&& b.toInt8 := Int8.toBitVec_inj.1 (by simp) +@[simp] theorem Int32.toInt16_and (a b : Int32) : (a &&& b).toInt16 = a.toInt16 &&& b.toInt16 := Int16.toBitVec_inj.1 (by simp) +@[simp] theorem Int32.toInt64_and (a b : Int32) : (a &&& b).toInt64 = a.toInt64 &&& b.toInt64 := Int64.toBitVec_inj.1 (by simp) +@[simp] theorem Int32.toISize_and (a b : Int32) : (a &&& b).toISize = a.toISize &&& b.toISize := ISize.toBitVec_inj.1 (by simp) + +@[simp] theorem ISize.toInt8_and (a b : ISize) : (a &&& b).toInt8 = a.toInt8 &&& b.toInt8 := Int8.toBitVec_inj.1 (by simp) +@[simp] theorem ISize.toInt16_and (a b : ISize) : (a &&& b).toInt16 = a.toInt16 &&& b.toInt16 := Int16.toBitVec_inj.1 (by simp) +@[simp] theorem ISize.toInt32_and (a b : ISize) : (a &&& b).toInt32 = a.toInt32 &&& b.toInt32 := Int32.toBitVec_inj.1 (by simp) +@[simp] theorem ISize.toInt64_and (a b : ISize) : (a &&& b).toInt64 = a.toInt64 &&& b.toInt64 := Int64.toBitVec_inj.1 (by simp) + +@[simp] theorem Int64.toInt8_and (a b : Int64) : (a &&& b).toInt8 = a.toInt8 &&& b.toInt8 := Int8.toBitVec_inj.1 (by simp) +@[simp] theorem Int64.toInt16_and (a b : Int64) : (a &&& b).toInt16 = a.toInt16 &&& b.toInt16 := Int16.toBitVec_inj.1 (by simp) +@[simp] theorem Int64.toInt32_and (a b : Int64) : (a &&& b).toInt32 = a.toInt32 &&& b.toInt32 := Int32.toBitVec_inj.1 (by simp) +@[simp] theorem Int64.toISize_and (a b : Int64) : (a &&& b).toISize = a.toISize &&& b.toISize := ISize.toBitVec_inj.1 (by simp) + +@[simp] theorem Int8.toInt16_or (a b : Int8) : (a ||| b).toInt16 = a.toInt16 ||| b.toInt16 := Int16.toBitVec_inj.1 (by simp) +@[simp] theorem Int8.toInt32_or (a b : Int8) : (a ||| b).toInt32 = a.toInt32 ||| b.toInt32 := Int32.toBitVec_inj.1 (by simp) +@[simp] theorem Int8.toInt64_or (a b : Int8) : (a ||| b).toInt64 = a.toInt64 ||| b.toInt64 := Int64.toBitVec_inj.1 (by simp) +@[simp] theorem Int8.toISize_or (a b : Int8) : (a ||| b).toISize = a.toISize ||| b.toISize := ISize.toBitVec_inj.1 (by simp) + +@[simp] theorem Int16.toInt8_or (a b : Int16) : (a ||| b).toInt8 = a.toInt8 ||| b.toInt8 := Int8.toBitVec_inj.1 (by simp) +@[simp] theorem Int16.toInt32_or (a b : Int16) : (a ||| b).toInt32 = a.toInt32 ||| b.toInt32 := Int32.toBitVec_inj.1 (by simp) +@[simp] theorem Int16.toInt64_or (a b : Int16) : (a ||| b).toInt64 = a.toInt64 ||| b.toInt64 := Int64.toBitVec_inj.1 (by simp) +@[simp] theorem Int16.toISize_or (a b : Int16) : (a ||| b).toISize = a.toISize ||| b.toISize := ISize.toBitVec_inj.1 (by simp) + +@[simp] theorem Int32.toInt8_or (a b : Int32) : (a ||| b).toInt8 = a.toInt8 ||| b.toInt8 := Int8.toBitVec_inj.1 (by simp) +@[simp] theorem Int32.toInt16_or (a b : Int32) : (a ||| b).toInt16 = a.toInt16 ||| b.toInt16 := Int16.toBitVec_inj.1 (by simp) +@[simp] theorem Int32.toInt64_or (a b : Int32) : (a ||| b).toInt64 = a.toInt64 ||| b.toInt64 := Int64.toBitVec_inj.1 (by simp) +@[simp] theorem Int32.toISize_or (a b : Int32) : (a ||| b).toISize = a.toISize ||| b.toISize := ISize.toBitVec_inj.1 (by simp) + +@[simp] theorem ISize.toInt8_or (a b : ISize) : (a ||| b).toInt8 = a.toInt8 ||| b.toInt8 := Int8.toBitVec_inj.1 (by simp) +@[simp] theorem ISize.toInt16_or (a b : ISize) : (a ||| b).toInt16 = a.toInt16 ||| b.toInt16 := Int16.toBitVec_inj.1 (by simp) +@[simp] theorem ISize.toInt32_or (a b : ISize) : (a ||| b).toInt32 = a.toInt32 ||| b.toInt32 := Int32.toBitVec_inj.1 (by simp) +@[simp] theorem ISize.toInt64_or (a b : ISize) : (a ||| b).toInt64 = a.toInt64 ||| b.toInt64 := Int64.toBitVec_inj.1 (by simp) + +@[simp] theorem Int64.toInt8_or (a b : Int64) : (a ||| b).toInt8 = a.toInt8 ||| b.toInt8 := Int8.toBitVec_inj.1 (by simp) +@[simp] theorem Int64.toInt16_or (a b : Int64) : (a ||| b).toInt16 = a.toInt16 ||| b.toInt16 := Int16.toBitVec_inj.1 (by simp) +@[simp] theorem Int64.toInt32_or (a b : Int64) : (a ||| b).toInt32 = a.toInt32 ||| b.toInt32 := Int32.toBitVec_inj.1 (by simp) +@[simp] theorem Int64.toISize_or (a b : Int64) : (a ||| b).toISize = a.toISize ||| b.toISize := ISize.toBitVec_inj.1 (by simp) + +@[simp] theorem Int8.toInt16_xor (a b : Int8) : (a ^^^ b).toInt16 = a.toInt16 ^^^ b.toInt16 := Int16.toBitVec_inj.1 (by simp) +@[simp] theorem Int8.toInt32_xor (a b : Int8) : (a ^^^ b).toInt32 = a.toInt32 ^^^ b.toInt32 := Int32.toBitVec_inj.1 (by simp) +@[simp] theorem Int8.toInt64_xor (a b : Int8) : (a ^^^ b).toInt64 = a.toInt64 ^^^ b.toInt64 := Int64.toBitVec_inj.1 (by simp) +@[simp] theorem Int8.toISize_xor (a b : Int8) : (a ^^^ b).toISize = a.toISize ^^^ b.toISize := ISize.toBitVec_inj.1 (by simp) + +@[simp] theorem Int16.toInt8_xor (a b : Int16) : (a ^^^ b).toInt8 = a.toInt8 ^^^ b.toInt8 := Int8.toBitVec_inj.1 (by simp) +@[simp] theorem Int16.toInt32_xor (a b : Int16) : (a ^^^ b).toInt32 = a.toInt32 ^^^ b.toInt32 := Int32.toBitVec_inj.1 (by simp) +@[simp] theorem Int16.toInt64_xor (a b : Int16) : (a ^^^ b).toInt64 = a.toInt64 ^^^ b.toInt64 := Int64.toBitVec_inj.1 (by simp) +@[simp] theorem Int16.toISize_xor (a b : Int16) : (a ^^^ b).toISize = a.toISize ^^^ b.toISize := ISize.toBitVec_inj.1 (by simp) + +@[simp] theorem Int32.toInt8_xor (a b : Int32) : (a ^^^ b).toInt8 = a.toInt8 ^^^ b.toInt8 := Int8.toBitVec_inj.1 (by simp) +@[simp] theorem Int32.toInt16_xor (a b : Int32) : (a ^^^ b).toInt16 = a.toInt16 ^^^ b.toInt16 := Int16.toBitVec_inj.1 (by simp) +@[simp] theorem Int32.toInt64_xor (a b : Int32) : (a ^^^ b).toInt64 = a.toInt64 ^^^ b.toInt64 := Int64.toBitVec_inj.1 (by simp) +@[simp] theorem Int32.toISize_xor (a b : Int32) : (a ^^^ b).toISize = a.toISize ^^^ b.toISize := ISize.toBitVec_inj.1 (by simp) + +@[simp] theorem ISize.toInt8_xor (a b : ISize) : (a ^^^ b).toInt8 = a.toInt8 ^^^ b.toInt8 := Int8.toBitVec_inj.1 (by simp) +@[simp] theorem ISize.toInt16_xor (a b : ISize) : (a ^^^ b).toInt16 = a.toInt16 ^^^ b.toInt16 := Int16.toBitVec_inj.1 (by simp) +@[simp] theorem ISize.toInt32_xor (a b : ISize) : (a ^^^ b).toInt32 = a.toInt32 ^^^ b.toInt32 := Int32.toBitVec_inj.1 (by simp) +@[simp] theorem ISize.toInt64_xor (a b : ISize) : (a ^^^ b).toInt64 = a.toInt64 ^^^ b.toInt64 := Int64.toBitVec_inj.1 (by simp) + +@[simp] theorem Int64.toInt8_xor (a b : Int64) : (a ^^^ b).toInt8 = a.toInt8 ^^^ b.toInt8 := Int8.toBitVec_inj.1 (by simp) +@[simp] theorem Int64.toInt16_xor (a b : Int64) : (a ^^^ b).toInt16 = a.toInt16 ^^^ b.toInt16 := Int16.toBitVec_inj.1 (by simp) +@[simp] theorem Int64.toInt32_xor (a b : Int64) : (a ^^^ b).toInt32 = a.toInt32 ^^^ b.toInt32 := Int32.toBitVec_inj.1 (by simp) +@[simp] theorem Int64.toISize_xor (a b : Int64) : (a ^^^ b).toISize = a.toISize ^^^ b.toISize := ISize.toBitVec_inj.1 (by simp) + +theorem Int8.not_eq_neg_add (a : Int8) : ~~~a = -a - 1 := Int8.toBitVec_inj.1 (by simpa using BitVec.not_eq_neg_add _) +theorem Int16.not_eq_neg_add (a : Int16) : ~~~a = -a - 1 := Int16.toBitVec_inj.1 (by simpa using BitVec.not_eq_neg_add _) +theorem Int32.not_eq_neg_add (a : Int32) : ~~~a = -a - 1 := Int32.toBitVec_inj.1 (by simpa using BitVec.not_eq_neg_add _) +theorem Int64.not_eq_neg_add (a : Int64) : ~~~a = -a - 1 := Int64.toBitVec_inj.1 (by simpa using BitVec.not_eq_neg_add _) +theorem ISize.not_eq_neg_add (a : ISize) : ~~~a = -a - 1 := ISize.toBitVec_inj.1 (by simpa using BitVec.not_eq_neg_add _) + +@[simp] theorem Int8.toInt_not (a : Int8) : (~~~a).toInt = (-a.toInt - 1).bmod (2 ^ 8) := by simp [Int8.not_eq_neg_add] +@[simp] theorem Int16.toInt_not (a : Int16) : (~~~a).toInt = (-a.toInt - 1).bmod (2 ^ 16) := by simp [Int16.not_eq_neg_add] +@[simp] theorem Int32.toInt_not (a : Int32) : (~~~a).toInt = (-a.toInt - 1).bmod (2 ^ 32) := by simp [Int32.not_eq_neg_add] +@[simp] theorem Int64.toInt_not (a : Int64) : (~~~a).toInt = (-a.toInt - 1).bmod (2 ^ 64) := by simp [Int64.not_eq_neg_add] +@[simp] theorem ISize.toInt_not (a : ISize) : (~~~a).toInt = (-a.toInt - 1).bmod (2 ^ System.Platform.numBits) := by + simp [ISize.not_eq_neg_add, toInt_neg] + +@[simp] theorem Int16.toInt8_not (a : Int16) : (~~~a).toInt8 = ~~~a.toInt8 := Int8.toBitVec_inj.1 (by simp) +@[simp] theorem Int32.toInt8_not (a : Int32) : (~~~a).toInt8 = ~~~a.toInt8 := Int8.toBitVec_inj.1 (by simp) +@[simp] theorem Int64.toInt8_not (a : Int64) : (~~~a).toInt8 = ~~~a.toInt8 := Int8.toBitVec_inj.1 (by simp) +@[simp] theorem ISize.toInt8_not (a : ISize) : (~~~a).toInt8 = ~~~a.toInt8 := Int8.toBitVec_inj.1 (by simp [System.Platform.numBits_pos]) + +@[simp] theorem Int32.toInt16_not (a : Int32) : (~~~a).toInt16 = ~~~a.toInt16 := Int16.toBitVec_inj.1 (by simp) +@[simp] theorem Int64.toInt16_not (a : Int64) : (~~~a).toInt16 = ~~~a.toInt16 := Int16.toBitVec_inj.1 (by simp) +@[simp] theorem ISize.toInt16_not (a : ISize) : (~~~a).toInt16 = ~~~a.toInt16 := Int16.toBitVec_inj.1 (by simp [System.Platform.numBits_pos]) + +@[simp] theorem Int64.toInt32_not (a : Int64) : (~~~a).toInt32 = ~~~a.toInt32 := Int32.toBitVec_inj.1 (by simp) +@[simp] theorem ISize.toInt32_not (a : ISize) : (~~~a).toInt32 = ~~~a.toInt32 := Int32.toBitVec_inj.1 (by simp [System.Platform.numBits_pos]) + +@[simp] theorem Int64.toISize_not (a : Int64) : (~~~a).toISize = ~~~a.toISize := ISize.toBitVec_inj.1 (by simp) + +@[simp] theorem Int8.ofBitVec_and (a b : BitVec 8) : Int8.ofBitVec (a &&& b) = Int8.ofBitVec a &&& Int8.ofBitVec b := rfl +@[simp] theorem Int16.ofBitVec_and (a b : BitVec 16) : Int16.ofBitVec (a &&& b) = Int16.ofBitVec a &&& Int16.ofBitVec b := rfl +@[simp] theorem Int32.ofBitVec_and (a b : BitVec 32) : Int32.ofBitVec (a &&& b) = Int32.ofBitVec a &&& Int32.ofBitVec b := rfl +@[simp] theorem Int64.ofBitVec_and (a b : BitVec 64) : Int64.ofBitVec (a &&& b) = Int64.ofBitVec a &&& Int64.ofBitVec b := rfl +@[simp] theorem ISize.ofBitVec_and (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a &&& b) = ISize.ofBitVec a &&& ISize.ofBitVec b := rfl + +@[simp] theorem Int8.ofBitVec_or (a b : BitVec 8) : Int8.ofBitVec (a ||| b) = Int8.ofBitVec a ||| Int8.ofBitVec b := rfl +@[simp] theorem Int16.ofBitVec_or (a b : BitVec 16) : Int16.ofBitVec (a ||| b) = Int16.ofBitVec a ||| Int16.ofBitVec b := rfl +@[simp] theorem Int32.ofBitVec_or (a b : BitVec 32) : Int32.ofBitVec (a ||| b) = Int32.ofBitVec a ||| Int32.ofBitVec b := rfl +@[simp] theorem Int64.ofBitVec_or (a b : BitVec 64) : Int64.ofBitVec (a ||| b) = Int64.ofBitVec a ||| Int64.ofBitVec b := rfl +@[simp] theorem ISize.ofBitVec_or (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a ||| b) = ISize.ofBitVec a ||| ISize.ofBitVec b := rfl + +@[simp] theorem Int8.ofBitVec_xor (a b : BitVec 8) : Int8.ofBitVec (a ^^^ b) = Int8.ofBitVec a ^^^ Int8.ofBitVec b := rfl +@[simp] theorem Int16.ofBitVec_xor (a b : BitVec 16) : Int16.ofBitVec (a ^^^ b) = Int16.ofBitVec a ^^^ Int16.ofBitVec b := rfl +@[simp] theorem Int32.ofBitVec_xor (a b : BitVec 32) : Int32.ofBitVec (a ^^^ b) = Int32.ofBitVec a ^^^ Int32.ofBitVec b := rfl +@[simp] theorem Int64.ofBitVec_xor (a b : BitVec 64) : Int64.ofBitVec (a ^^^ b) = Int64.ofBitVec a ^^^ Int64.ofBitVec b := rfl +@[simp] theorem ISize.ofBitVec_xor (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a ^^^ b) = ISize.ofBitVec a ^^^ ISize.ofBitVec b := rfl + +@[simp] theorem Int8.ofBitVec_not (a : BitVec 8) : Int8.ofBitVec (~~~a) = ~~~Int8.ofBitVec a := rfl +@[simp] theorem Int16.ofBitVec_not (a : BitVec 16) : Int16.ofBitVec (~~~a) = ~~~Int16.ofBitVec a := rfl +@[simp] theorem Int32.ofBitVec_not (a : BitVec 32) : Int32.ofBitVec (~~~a) = ~~~Int32.ofBitVec a := rfl +@[simp] theorem Int64.ofBitVec_not (a : BitVec 64) : Int64.ofBitVec (~~~a) = ~~~Int64.ofBitVec a := rfl +@[simp] theorem ISize.ofBitVec_not (a : BitVec System.Platform.numBits) : ISize.ofBitVec (~~~a) = ~~~ISize.ofBitVec a := rfl + +@[simp] theorem Int8.ofBitVec_intMin : Int8.ofBitVec (BitVec.intMin 8) = Int8.minValue := rfl +@[simp] theorem Int16.ofBitVec_intMin : Int16.ofBitVec (BitVec.intMin 16) = Int16.minValue := rfl +@[simp] theorem Int32.ofBitVec_intMin : Int32.ofBitVec (BitVec.intMin 32) = Int32.minValue := rfl +@[simp] theorem Int64.ofBitVec_intMin : Int64.ofBitVec (BitVec.intMin 64) = Int64.minValue := rfl +@[simp] theorem ISize.ofBitVec_intMin : ISize.ofBitVec (BitVec.intMin System.Platform.numBits) = ISize.minValue := + ISize.toBitVec_inj.1 (by simp [BitVec.intMin_eq_neg_two_pow]) + +@[simp] theorem Int8.ofBitVec_intMax : Int8.ofBitVec (BitVec.intMax 8) = Int8.maxValue := rfl +@[simp] theorem Int16.ofBitVec_intMax : Int16.ofBitVec (BitVec.intMax 16) = Int16.maxValue := rfl +@[simp] theorem Int32.ofBitVec_intMax : Int32.ofBitVec (BitVec.intMax 32) = Int32.maxValue := rfl +@[simp] theorem Int64.ofBitVec_intMax : Int64.ofBitVec (BitVec.intMax 64) = Int64.maxValue := rfl +@[simp] theorem ISize.ofBitVec_intMax : ISize.ofBitVec (BitVec.intMax System.Platform.numBits) = ISize.maxValue := + ISize.toInt_inj.1 (by rw [toInt_ofBitVec, BitVec.toInt_intMax, toInt_maxValue]) + +theorem Int8.neg_eq_not_add (a : Int8) : -a = ~~~a + 1 := Int8.toBitVec_inj.1 (BitVec.neg_eq_not_add _) +theorem Int16.neg_eq_not_add (a : Int16) : -a = ~~~a + 1 := Int16.toBitVec_inj.1 (BitVec.neg_eq_not_add _) +theorem Int32.neg_eq_not_add (a : Int32) : -a = ~~~a + 1 := Int32.toBitVec_inj.1 (BitVec.neg_eq_not_add _) +theorem Int64.neg_eq_not_add (a : Int64) : -a = ~~~a + 1 := Int64.toBitVec_inj.1 (BitVec.neg_eq_not_add _) +theorem ISize.neg_eq_not_add (a : ISize) : -a = ~~~a + 1 := ISize.toBitVec_inj.1 (BitVec.neg_eq_not_add _) + +theorem Int8.not_eq_neg_sub (a : Int8) : ~~~a = -a - 1 := Int8.toBitVec_inj.1 (BitVec.not_eq_neg_add _) +theorem Int16.not_eq_neg_sub (a : Int16) : ~~~a = -a - 1 := Int16.toBitVec_inj.1 (BitVec.not_eq_neg_add _) +theorem Int32.not_eq_neg_sub (a : Int32) : ~~~a = -a - 1 := Int32.toBitVec_inj.1 (BitVec.not_eq_neg_add _) +theorem Int64.not_eq_neg_sub (a : Int64) : ~~~a = -a - 1 := Int64.toBitVec_inj.1 (BitVec.not_eq_neg_add _) +theorem ISize.not_eq_neg_sub (a : ISize) : ~~~a = -a - 1 := ISize.toBitVec_inj.1 (BitVec.not_eq_neg_add _) + +theorem Int8.or_assoc (a b c : Int8) : a ||| b ||| c = a ||| (b ||| c) := Int8.toBitVec_inj.1 (BitVec.or_assoc _ _ _) +theorem Int16.or_assoc (a b c : Int16) : a ||| b ||| c = a ||| (b ||| c) := Int16.toBitVec_inj.1 (BitVec.or_assoc _ _ _) +theorem Int32.or_assoc (a b c : Int32) : a ||| b ||| c = a ||| (b ||| c) := Int32.toBitVec_inj.1 (BitVec.or_assoc _ _ _) +theorem Int64.or_assoc (a b c : Int64) : a ||| b ||| c = a ||| (b ||| c) := Int64.toBitVec_inj.1 (BitVec.or_assoc _ _ _) +theorem ISize.or_assoc (a b c : ISize) : a ||| b ||| c = a ||| (b ||| c) := ISize.toBitVec_inj.1 (BitVec.or_assoc _ _ _) + +instance : Std.Associative (α := Int8) (· ||| ·) := ⟨Int8.or_assoc⟩ +instance : Std.Associative (α := Int16) (· ||| ·) := ⟨Int16.or_assoc⟩ +instance : Std.Associative (α := Int32) (· ||| ·) := ⟨Int32.or_assoc⟩ +instance : Std.Associative (α := Int64) (· ||| ·) := ⟨Int64.or_assoc⟩ +instance : Std.Associative (α := ISize) (· ||| ·) := ⟨ISize.or_assoc⟩ + +theorem Int8.or_comm (a b : Int8) : a ||| b = b ||| a := Int8.toBitVec_inj.1 (BitVec.or_comm _ _) +theorem Int16.or_comm (a b : Int16) : a ||| b = b ||| a := Int16.toBitVec_inj.1 (BitVec.or_comm _ _) +theorem Int32.or_comm (a b : Int32) : a ||| b = b ||| a := Int32.toBitVec_inj.1 (BitVec.or_comm _ _) +theorem Int64.or_comm (a b : Int64) : a ||| b = b ||| a := Int64.toBitVec_inj.1 (BitVec.or_comm _ _) +theorem ISize.or_comm (a b : ISize) : a ||| b = b ||| a := ISize.toBitVec_inj.1 (BitVec.or_comm _ _) + +instance : Std.Commutative (α := Int8) (· ||| ·) := ⟨Int8.or_comm⟩ +instance : Std.Commutative (α := Int16) (· ||| ·) := ⟨Int16.or_comm⟩ +instance : Std.Commutative (α := Int32) (· ||| ·) := ⟨Int32.or_comm⟩ +instance : Std.Commutative (α := Int64) (· ||| ·) := ⟨Int64.or_comm⟩ +instance : Std.Commutative (α := ISize) (· ||| ·) := ⟨ISize.or_comm⟩ + +@[simp] theorem Int8.or_self {a : Int8} : a ||| a = a := Int8.toBitVec_inj.1 BitVec.or_self +@[simp] theorem Int16.or_self {a : Int16} : a ||| a = a := Int16.toBitVec_inj.1 BitVec.or_self +@[simp] theorem Int32.or_self {a : Int32} : a ||| a = a := Int32.toBitVec_inj.1 BitVec.or_self +@[simp] theorem Int64.or_self {a : Int64} : a ||| a = a := Int64.toBitVec_inj.1 BitVec.or_self +@[simp] theorem ISize.or_self {a : ISize} : a ||| a = a := ISize.toBitVec_inj.1 BitVec.or_self + +instance : Std.IdempotentOp (α := Int8) (· ||| ·) := ⟨fun _ => Int8.or_self⟩ +instance : Std.IdempotentOp (α := Int16) (· ||| ·) := ⟨fun _ => Int16.or_self⟩ +instance : Std.IdempotentOp (α := Int32) (· ||| ·) := ⟨fun _ => Int32.or_self⟩ +instance : Std.IdempotentOp (α := Int64) (· ||| ·) := ⟨fun _ => Int64.or_self⟩ +instance : Std.IdempotentOp (α := ISize) (· ||| ·) := ⟨fun _ => ISize.or_self⟩ + +@[simp] theorem Int8.or_zero {a : Int8} : a ||| 0 = a := Int8.toBitVec_inj.1 BitVec.or_zero +@[simp] theorem Int16.or_zero {a : Int16} : a ||| 0 = a := Int16.toBitVec_inj.1 BitVec.or_zero +@[simp] theorem Int32.or_zero {a : Int32} : a ||| 0 = a := Int32.toBitVec_inj.1 BitVec.or_zero +@[simp] theorem Int64.or_zero {a : Int64} : a ||| 0 = a := Int64.toBitVec_inj.1 BitVec.or_zero +@[simp] theorem ISize.or_zero {a : ISize} : a ||| 0 = a := ISize.toBitVec_inj.1 BitVec.or_zero + +@[simp] theorem Int8.zero_or {a : Int8} : 0 ||| a = a := Int8.toBitVec_inj.1 BitVec.zero_or +@[simp] theorem Int16.zero_or {a : Int16} : 0 ||| a = a := Int16.toBitVec_inj.1 BitVec.zero_or +@[simp] theorem Int32.zero_or {a : Int32} : 0 ||| a = a := Int32.toBitVec_inj.1 BitVec.zero_or +@[simp] theorem Int64.zero_or {a : Int64} : 0 ||| a = a := Int64.toBitVec_inj.1 BitVec.zero_or +@[simp] theorem ISize.zero_or {a : ISize} : 0 ||| a = a := ISize.toBitVec_inj.1 BitVec.zero_or + +instance : Std.LawfulCommIdentity (α := Int8) (· ||| ·) 0 where + right_id _ := Int8.or_zero +instance : Std.LawfulCommIdentity (α := Int16) (· ||| ·) 0 where + right_id _ := Int16.or_zero +instance : Std.LawfulCommIdentity (α := Int32) (· ||| ·) 0 where + right_id _ := Int32.or_zero +instance : Std.LawfulCommIdentity (α := Int64) (· ||| ·) 0 where + right_id _ := Int64.or_zero +instance : Std.LawfulCommIdentity (α := ISize) (· ||| ·) 0 where + right_id _ := ISize.or_zero + +@[simp] theorem Int8.neg_one_or {a : Int8} : -1 ||| a = -1 := by + rw [← Int8.toBitVec_inj, Int8.toBitVec_or, Int8.toBitVec_neg, Int8.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_or] +@[simp] theorem Int16.neg_one_or {a : Int16} : -1 ||| a = -1 := by + rw [← Int16.toBitVec_inj, Int16.toBitVec_or, Int16.toBitVec_neg, Int16.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_or] +@[simp] theorem Int32.neg_one_or {a : Int32} : -1 ||| a = -1 := by + rw [← Int32.toBitVec_inj, Int32.toBitVec_or, Int32.toBitVec_neg, Int32.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_or] +@[simp] theorem Int64.neg_one_or {a : Int64} : -1 ||| a = -1 := by + rw [← Int64.toBitVec_inj, Int64.toBitVec_or, Int64.toBitVec_neg, Int64.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_or] +@[simp] theorem ISize.neg_one_or {a : ISize} : -1 ||| a = -1 := by + rw [← ISize.toBitVec_inj, ISize.toBitVec_or, ISize.toBitVec_neg, ISize.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_or] + +@[simp] theorem Int8.or_neg_one {a : Int8} : a ||| -1 = -1 := by rw [or_comm, neg_one_or] +@[simp] theorem Int16.or_neg_one {a : Int16} : a ||| -1 = -1 := by rw [or_comm, neg_one_or] +@[simp] theorem Int32.or_neg_one {a : Int32} : a ||| -1 = -1 := by rw [or_comm, neg_one_or] +@[simp] theorem Int64.or_neg_one {a : Int64} : a ||| -1 = -1 := by rw [or_comm, neg_one_or] +@[simp] theorem ISize.or_neg_one {a : ISize} : a ||| -1 = -1 := by rw [or_comm, neg_one_or] + +@[simp] theorem Int8.or_eq_zero_iff {a b : Int8} : a ||| b = 0 ↔ a = 0 ∧ b = 0 := by + simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.or_eq_zero_iff {a b : Int16} : a ||| b = 0 ↔ a = 0 ∧ b = 0 := by + simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.or_eq_zero_iff {a b : Int32} : a ||| b = 0 ↔ a = 0 ∧ b = 0 := by + simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.or_eq_zero_iff {a b : Int64} : a ||| b = 0 ↔ a = 0 ∧ b = 0 := by + simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.or_eq_zero_iff {a b : ISize} : a ||| b = 0 ↔ a = 0 ∧ b = 0 := by + simp [← ISize.toBitVec_inj] + +theorem Int8.and_assoc (a b c : Int8) : a &&& b &&& c = a &&& (b &&& c) := Int8.toBitVec_inj.1 (BitVec.and_assoc _ _ _) +theorem Int16.and_assoc (a b c : Int16) : a &&& b &&& c = a &&& (b &&& c) := Int16.toBitVec_inj.1 (BitVec.and_assoc _ _ _) +theorem Int32.and_assoc (a b c : Int32) : a &&& b &&& c = a &&& (b &&& c) := Int32.toBitVec_inj.1 (BitVec.and_assoc _ _ _) +theorem Int64.and_assoc (a b c : Int64) : a &&& b &&& c = a &&& (b &&& c) := Int64.toBitVec_inj.1 (BitVec.and_assoc _ _ _) +theorem ISize.and_assoc (a b c : ISize) : a &&& b &&& c = a &&& (b &&& c) := ISize.toBitVec_inj.1 (BitVec.and_assoc _ _ _) + +instance : Std.Associative (α := Int8) (· &&& ·) := ⟨Int8.and_assoc⟩ +instance : Std.Associative (α := Int16) (· &&& ·) := ⟨Int16.and_assoc⟩ +instance : Std.Associative (α := Int32) (· &&& ·) := ⟨Int32.and_assoc⟩ +instance : Std.Associative (α := Int64) (· &&& ·) := ⟨Int64.and_assoc⟩ +instance : Std.Associative (α := ISize) (· &&& ·) := ⟨ISize.and_assoc⟩ + +theorem Int8.and_comm (a b : Int8) : a &&& b = b &&& a := Int8.toBitVec_inj.1 (BitVec.and_comm _ _) +theorem Int16.and_comm (a b : Int16) : a &&& b = b &&& a := Int16.toBitVec_inj.1 (BitVec.and_comm _ _) +theorem Int32.and_comm (a b : Int32) : a &&& b = b &&& a := Int32.toBitVec_inj.1 (BitVec.and_comm _ _) +theorem Int64.and_comm (a b : Int64) : a &&& b = b &&& a := Int64.toBitVec_inj.1 (BitVec.and_comm _ _) +theorem ISize.and_comm (a b : ISize) : a &&& b = b &&& a := ISize.toBitVec_inj.1 (BitVec.and_comm _ _) + +instance : Std.Commutative (α := Int8) (· &&& ·) := ⟨Int8.and_comm⟩ +instance : Std.Commutative (α := Int16) (· &&& ·) := ⟨Int16.and_comm⟩ +instance : Std.Commutative (α := Int32) (· &&& ·) := ⟨Int32.and_comm⟩ +instance : Std.Commutative (α := Int64) (· &&& ·) := ⟨Int64.and_comm⟩ +instance : Std.Commutative (α := ISize) (· &&& ·) := ⟨ISize.and_comm⟩ + +@[simp] theorem Int8.and_self {a : Int8} : a &&& a = a := Int8.toBitVec_inj.1 BitVec.and_self +@[simp] theorem Int16.and_self {a : Int16} : a &&& a = a := Int16.toBitVec_inj.1 BitVec.and_self +@[simp] theorem Int32.and_self {a : Int32} : a &&& a = a := Int32.toBitVec_inj.1 BitVec.and_self +@[simp] theorem Int64.and_self {a : Int64} : a &&& a = a := Int64.toBitVec_inj.1 BitVec.and_self +@[simp] theorem ISize.and_self {a : ISize} : a &&& a = a := ISize.toBitVec_inj.1 BitVec.and_self + +instance : Std.IdempotentOp (α := Int8) (· &&& ·) := ⟨fun _ => Int8.and_self⟩ +instance : Std.IdempotentOp (α := Int16) (· &&& ·) := ⟨fun _ => Int16.and_self⟩ +instance : Std.IdempotentOp (α := Int32) (· &&& ·) := ⟨fun _ => Int32.and_self⟩ +instance : Std.IdempotentOp (α := Int64) (· &&& ·) := ⟨fun _ => Int64.and_self⟩ +instance : Std.IdempotentOp (α := ISize) (· &&& ·) := ⟨fun _ => ISize.and_self⟩ + +@[simp] theorem Int8.and_zero {a : Int8} : a &&& 0 = 0 := Int8.toBitVec_inj.1 BitVec.and_zero +@[simp] theorem Int16.and_zero {a : Int16} : a &&& 0 = 0 := Int16.toBitVec_inj.1 BitVec.and_zero +@[simp] theorem Int32.and_zero {a : Int32} : a &&& 0 = 0 := Int32.toBitVec_inj.1 BitVec.and_zero +@[simp] theorem Int64.and_zero {a : Int64} : a &&& 0 = 0 := Int64.toBitVec_inj.1 BitVec.and_zero +@[simp] theorem ISize.and_zero {a : ISize} : a &&& 0 = 0 := ISize.toBitVec_inj.1 BitVec.and_zero + +@[simp] theorem Int8.zero_and {a : Int8} : 0 &&& a = 0 := Int8.toBitVec_inj.1 BitVec.zero_and +@[simp] theorem Int16.zero_and {a : Int16} : 0 &&& a = 0 := Int16.toBitVec_inj.1 BitVec.zero_and +@[simp] theorem Int32.zero_and {a : Int32} : 0 &&& a = 0 := Int32.toBitVec_inj.1 BitVec.zero_and +@[simp] theorem Int64.zero_and {a : Int64} : 0 &&& a = 0 := Int64.toBitVec_inj.1 BitVec.zero_and +@[simp] theorem ISize.zero_and {a : ISize} : 0 &&& a = 0 := ISize.toBitVec_inj.1 BitVec.zero_and + +@[simp] theorem Int8.neg_one_and {a : Int8} : -1 &&& a = a := by + rw [← Int8.toBitVec_inj, Int8.toBitVec_and, Int8.toBitVec_neg, Int8.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_and] +@[simp] theorem Int16.neg_one_and {a : Int16} : -1 &&& a = a := by + rw [← Int16.toBitVec_inj, Int16.toBitVec_and, Int16.toBitVec_neg, Int16.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_and] +@[simp] theorem Int32.neg_one_and {a : Int32} : -1 &&& a = a := by + rw [← Int32.toBitVec_inj, Int32.toBitVec_and, Int32.toBitVec_neg, Int32.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_and] +@[simp] theorem Int64.neg_one_and {a : Int64} : -1 &&& a = a := by + rw [← Int64.toBitVec_inj, Int64.toBitVec_and, Int64.toBitVec_neg, Int64.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_and] +@[simp] theorem ISize.neg_one_and {a : ISize} : -1 &&& a = a := by + rw [← ISize.toBitVec_inj, ISize.toBitVec_and, ISize.toBitVec_neg, ISize.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_and] + +@[simp] theorem Int8.and_neg_one {a : Int8} : a &&& -1 = a := by rw [and_comm, neg_one_and] +@[simp] theorem Int16.and_neg_one {a : Int16} : a &&& -1 = a := by rw [and_comm, neg_one_and] +@[simp] theorem Int32.and_neg_one {a : Int32} : a &&& -1 = a := by rw [and_comm, neg_one_and] +@[simp] theorem Int64.and_neg_one {a : Int64} : a &&& -1 = a := by rw [and_comm, neg_one_and] +@[simp] theorem ISize.and_neg_one {a : ISize} : a &&& -1 = a := by rw [and_comm, neg_one_and] + +instance : Std.LawfulCommIdentity (α := Int8) (· &&& ·) (-1) where + right_id _ := Int8.and_neg_one +instance : Std.LawfulCommIdentity (α := Int16) (· &&& ·) (-1) where + right_id _ := Int16.and_neg_one +instance : Std.LawfulCommIdentity (α := Int32) (· &&& ·) (-1) where + right_id _ := Int32.and_neg_one +instance : Std.LawfulCommIdentity (α := Int64) (· &&& ·) (-1) where + right_id _ := Int64.and_neg_one +instance : Std.LawfulCommIdentity (α := ISize) (· &&& ·) (-1) where + right_id _ := ISize.and_neg_one + +@[simp] theorem Int8.and_eq_neg_one_iff {a b : Int8} : a &&& b = -1 ↔ a = -1 ∧ b = -1 := by + simp only [← Int8.toBitVec_inj, Int8.toBitVec_and, Int8.toBitVec_neg, Int8.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.and_eq_allOnes_iff] +@[simp] theorem Int16.and_eq_neg_one_iff {a b : Int16} : a &&& b = -1 ↔ a = -1 ∧ b = -1 := by + simp only [← Int16.toBitVec_inj, Int16.toBitVec_and, Int16.toBitVec_neg, Int16.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.and_eq_allOnes_iff] +@[simp] theorem Int32.and_eq_neg_one_iff {a b : Int32} : a &&& b = -1 ↔ a = -1 ∧ b = -1 := by + simp only [← Int32.toBitVec_inj, Int32.toBitVec_and, Int32.toBitVec_neg, Int32.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.and_eq_allOnes_iff] +@[simp] theorem Int64.and_eq_neg_one_iff {a b : Int64} : a &&& b = -1 ↔ a = -1 ∧ b = -1 := by + simp only [← Int64.toBitVec_inj, Int64.toBitVec_and, Int64.toBitVec_neg, Int64.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.and_eq_allOnes_iff] +@[simp] theorem ISize.and_eq_neg_one_iff {a b : ISize} : a &&& b = -1 ↔ a = -1 ∧ b = -1 := by + simp only [← ISize.toBitVec_inj, ISize.toBitVec_and, ISize.toBitVec_neg, ISize.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.and_eq_allOnes_iff] + +theorem Int8.xor_assoc (a b c : Int8) : a ^^^ b ^^^ c = a ^^^ (b ^^^ c) := Int8.toBitVec_inj.1 (BitVec.xor_assoc _ _ _) +theorem Int16.xor_assoc (a b c : Int16) : a ^^^ b ^^^ c = a ^^^ (b ^^^ c) := Int16.toBitVec_inj.1 (BitVec.xor_assoc _ _ _) +theorem Int32.xor_assoc (a b c : Int32) : a ^^^ b ^^^ c = a ^^^ (b ^^^ c) := Int32.toBitVec_inj.1 (BitVec.xor_assoc _ _ _) +theorem Int64.xor_assoc (a b c : Int64) : a ^^^ b ^^^ c = a ^^^ (b ^^^ c) := Int64.toBitVec_inj.1 (BitVec.xor_assoc _ _ _) +theorem ISize.xor_assoc (a b c : ISize) : a ^^^ b ^^^ c = a ^^^ (b ^^^ c) := ISize.toBitVec_inj.1 (BitVec.xor_assoc _ _ _) + +instance : Std.Associative (α := Int8) (· ^^^ ·) := ⟨Int8.xor_assoc⟩ +instance : Std.Associative (α := Int16) (· ^^^ ·) := ⟨Int16.xor_assoc⟩ +instance : Std.Associative (α := Int32) (· ^^^ ·) := ⟨Int32.xor_assoc⟩ +instance : Std.Associative (α := Int64) (· ^^^ ·) := ⟨Int64.xor_assoc⟩ +instance : Std.Associative (α := ISize) (· ^^^ ·) := ⟨ISize.xor_assoc⟩ + +theorem Int8.xor_comm (a b : Int8) : a ^^^ b = b ^^^ a := Int8.toBitVec_inj.1 (BitVec.xor_comm _ _) +theorem Int16.xor_comm (a b : Int16) : a ^^^ b = b ^^^ a := Int16.toBitVec_inj.1 (BitVec.xor_comm _ _) +theorem Int32.xor_comm (a b : Int32) : a ^^^ b = b ^^^ a := Int32.toBitVec_inj.1 (BitVec.xor_comm _ _) +theorem Int64.xor_comm (a b : Int64) : a ^^^ b = b ^^^ a := Int64.toBitVec_inj.1 (BitVec.xor_comm _ _) +theorem ISize.xor_comm (a b : ISize) : a ^^^ b = b ^^^ a := ISize.toBitVec_inj.1 (BitVec.xor_comm _ _) + +instance : Std.Commutative (α := Int8) (· ^^^ ·) := ⟨Int8.xor_comm⟩ +instance : Std.Commutative (α := Int16) (· ^^^ ·) := ⟨Int16.xor_comm⟩ +instance : Std.Commutative (α := Int32) (· ^^^ ·) := ⟨Int32.xor_comm⟩ +instance : Std.Commutative (α := Int64) (· ^^^ ·) := ⟨Int64.xor_comm⟩ +instance : Std.Commutative (α := ISize) (· ^^^ ·) := ⟨ISize.xor_comm⟩ + +@[simp] theorem Int8.xor_self {a : Int8} : a ^^^ a = 0 := Int8.toBitVec_inj.1 BitVec.xor_self +@[simp] theorem Int16.xor_self {a : Int16} : a ^^^ a = 0 := Int16.toBitVec_inj.1 BitVec.xor_self +@[simp] theorem Int32.xor_self {a : Int32} : a ^^^ a = 0 := Int32.toBitVec_inj.1 BitVec.xor_self +@[simp] theorem Int64.xor_self {a : Int64} : a ^^^ a = 0 := Int64.toBitVec_inj.1 BitVec.xor_self +@[simp] theorem ISize.xor_self {a : ISize} : a ^^^ a = 0 := ISize.toBitVec_inj.1 BitVec.xor_self + +@[simp] theorem Int8.xor_zero {a : Int8} : a ^^^ 0 = a := Int8.toBitVec_inj.1 BitVec.xor_zero +@[simp] theorem Int16.xor_zero {a : Int16} : a ^^^ 0 = a := Int16.toBitVec_inj.1 BitVec.xor_zero +@[simp] theorem Int32.xor_zero {a : Int32} : a ^^^ 0 = a := Int32.toBitVec_inj.1 BitVec.xor_zero +@[simp] theorem Int64.xor_zero {a : Int64} : a ^^^ 0 = a := Int64.toBitVec_inj.1 BitVec.xor_zero +@[simp] theorem ISize.xor_zero {a : ISize} : a ^^^ 0 = a := ISize.toBitVec_inj.1 BitVec.xor_zero + +@[simp] theorem Int8.zero_xor {a : Int8} : 0 ^^^ a = a := Int8.toBitVec_inj.1 BitVec.zero_xor +@[simp] theorem Int16.zero_xor {a : Int16} : 0 ^^^ a = a := Int16.toBitVec_inj.1 BitVec.zero_xor +@[simp] theorem Int32.zero_xor {a : Int32} : 0 ^^^ a = a := Int32.toBitVec_inj.1 BitVec.zero_xor +@[simp] theorem Int64.zero_xor {a : Int64} : 0 ^^^ a = a := Int64.toBitVec_inj.1 BitVec.zero_xor +@[simp] theorem ISize.zero_xor {a : ISize} : 0 ^^^ a = a := ISize.toBitVec_inj.1 BitVec.zero_xor + +@[simp] theorem Int8.neg_one_xor {a : Int8} : -1 ^^^ a = ~~~a := by + rw [← Int8.toBitVec_inj, Int8.toBitVec_xor, Int8.toBitVec_neg, Int8.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_xor, Int8.toBitVec_not] +@[simp] theorem Int16.neg_one_xor {a : Int16} : -1 ^^^ a = ~~~a := by + rw [← Int16.toBitVec_inj, Int16.toBitVec_xor, Int16.toBitVec_neg, Int16.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_xor, Int16.toBitVec_not] +@[simp] theorem Int32.neg_one_xor {a : Int32} : -1 ^^^ a = ~~~a := by + rw [← Int32.toBitVec_inj, Int32.toBitVec_xor, Int32.toBitVec_neg, Int32.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_xor, Int32.toBitVec_not] +@[simp] theorem Int64.neg_one_xor {a : Int64} : -1 ^^^ a = ~~~a := by + rw [← Int64.toBitVec_inj, Int64.toBitVec_xor, Int64.toBitVec_neg, Int64.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_xor, Int64.toBitVec_not] +@[simp] theorem ISize.neg_one_xor {a : ISize} : -1 ^^^ a = ~~~a := by + rw [← ISize.toBitVec_inj, ISize.toBitVec_xor, ISize.toBitVec_neg, ISize.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_xor, ISize.toBitVec_not] + +@[simp] theorem Int8.xor_neg_one {a : Int8} : a ^^^ -1 = ~~~a := by rw [xor_comm, neg_one_xor] +@[simp] theorem Int16.xor_neg_one {a : Int16} : a ^^^ -1 = ~~~a := by rw [xor_comm, neg_one_xor] +@[simp] theorem Int32.xor_neg_one {a : Int32} : a ^^^ -1 = ~~~a := by rw [xor_comm, neg_one_xor] +@[simp] theorem Int64.xor_neg_one {a : Int64} : a ^^^ -1 = ~~~a := by rw [xor_comm, neg_one_xor] +@[simp] theorem ISize.xor_neg_one {a : ISize} : a ^^^ -1 = ~~~a := by rw [xor_comm, neg_one_xor] + +instance : Std.LawfulCommIdentity (α := Int8) (· ^^^ ·) 0 where + right_id _ := Int8.xor_zero +instance : Std.LawfulCommIdentity (α := Int16) (· ^^^ ·) 0 where + right_id _ := Int16.xor_zero +instance : Std.LawfulCommIdentity (α := Int32) (· ^^^ ·) 0 where + right_id _ := Int32.xor_zero +instance : Std.LawfulCommIdentity (α := Int64) (· ^^^ ·) 0 where + right_id _ := Int64.xor_zero +instance : Std.LawfulCommIdentity (α := ISize) (· ^^^ ·) 0 where + right_id _ := ISize.xor_zero + +@[simp] theorem Int8.xor_eq_zero_iff {a b : Int8} : a ^^^ b = 0 ↔ a = b := by simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.xor_eq_zero_iff {a b : Int16} : a ^^^ b = 0 ↔ a = b := by simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.xor_eq_zero_iff {a b : Int32} : a ^^^ b = 0 ↔ a = b := by simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.xor_eq_zero_iff {a b : Int64} : a ^^^ b = 0 ↔ a = b := by simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.xor_eq_zero_iff {a b : ISize} : a ^^^ b = 0 ↔ a = b := by simp [← ISize.toBitVec_inj] + +@[simp] theorem Int8.xor_left_inj {a b : Int8} (c : Int8) : (a ^^^ c = b ^^^ c) ↔ a = b := by + simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.xor_left_inj {a b : Int16} (c : Int16) : (a ^^^ c = b ^^^ c) ↔ a = b := by + simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.xor_left_inj {a b : Int32} (c : Int32) : (a ^^^ c = b ^^^ c) ↔ a = b := by + simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.xor_left_inj {a b : Int64} (c : Int64) : (a ^^^ c = b ^^^ c) ↔ a = b := by + simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.xor_left_inj {a b : ISize} (c : ISize) : (a ^^^ c = b ^^^ c) ↔ a = b := by + simp [← ISize.toBitVec_inj] + +@[simp] theorem Int8.xor_right_inj {a b : Int8} (c : Int8) : (c ^^^ a = c ^^^ b) ↔ a = b := by + simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.xor_right_inj {a b : Int16} (c : Int16) : (c ^^^ a = c ^^^ b) ↔ a = b := by + simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.xor_right_inj {a b : Int32} (c : Int32) : (c ^^^ a = c ^^^ b) ↔ a = b := by + simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.xor_right_inj {a b : Int64} (c : Int64) : (c ^^^ a = c ^^^ b) ↔ a = b := by + simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.xor_right_inj {a b : ISize} (c : ISize) : (c ^^^ a = c ^^^ b) ↔ a = b := by + simp [← ISize.toBitVec_inj] + +@[simp] theorem Int8.not_zero : ~~~(0 : Int8) = -1 := rfl +@[simp] theorem Int16.not_zero : ~~~(0 : Int16) = -1 := rfl +@[simp] theorem Int32.not_zero : ~~~(0 : Int32) = -1 := rfl +@[simp] theorem Int64.not_zero : ~~~(0 : Int64) = -1 := rfl +@[simp] theorem ISize.not_zero : ~~~(0 : ISize) = -1 := by simp [ISize.not_eq_neg_sub] + +@[simp] theorem Int8.not_neg_one : ~~~(-1 : Int8) = 0 := rfl +@[simp] theorem Int16.not_neg_one : ~~~(-1 : Int16) = 0 := rfl +@[simp] theorem Int32.not_neg_one : ~~~(-1 : Int32) = 0 := rfl +@[simp] theorem Int64.not_neg_one : ~~~(-1 : Int64) = 0 := rfl +@[simp] theorem ISize.not_neg_one : ~~~(-1 : ISize) = 0 := by simp [ISize.not_eq_neg_sub] + +@[simp] theorem Int8.not_not {a : Int8} : ~~~(~~~a) = a := by simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.not_not {a : Int16} : ~~~(~~~a) = a := by simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.not_not {a : Int32} : ~~~(~~~a) = a := by simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.not_not {a : Int64} : ~~~(~~~a) = a := by simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.not_not {a : ISize} : ~~~(~~~a) = a := by simp [← ISize.toBitVec_inj] + +@[simp] theorem Int8.not_inj {a b : Int8} : ~~~a = ~~~b ↔ a = b := by simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.not_inj {a b : Int16} : ~~~a = ~~~b ↔ a = b := by simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.not_inj {a b : Int32} : ~~~a = ~~~b ↔ a = b := by simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.not_inj {a b : Int64} : ~~~a = ~~~b ↔ a = b := by simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.not_inj {a b : ISize} : ~~~a = ~~~b ↔ a = b := by simp [← ISize.toBitVec_inj] + +@[simp] theorem Int8.and_not_self {a : Int8} : a &&& ~~~a = 0 := by simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.and_not_self {a : Int16} : a &&& ~~~a = 0 := by simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.and_not_self {a : Int32} : a &&& ~~~a = 0 := by simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.and_not_self {a : Int64} : a &&& ~~~a = 0 := by simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.and_not_self {a : ISize} : a &&& ~~~a = 0 := by simp [← ISize.toBitVec_inj] + +@[simp] theorem Int8.not_and_self {a : Int8} : ~~~a &&& a = 0 := by simp [Int8.and_comm] +@[simp] theorem Int16.not_and_self {a : Int16} : ~~~a &&& a = 0 := by simp [Int16.and_comm] +@[simp] theorem Int32.not_and_self {a : Int32} : ~~~a &&& a = 0 := by simp [Int32.and_comm] +@[simp] theorem Int64.not_and_self {a : Int64} : ~~~a &&& a = 0 := by simp [Int64.and_comm] +@[simp] theorem ISize.not_and_self {a : ISize} : ~~~a &&& a = 0 := by simp [ISize.and_comm] + +@[simp] theorem Int8.or_not_self {a : Int8} : a ||| ~~~a = -1 := by + rw [← Int8.toBitVec_inj, Int8.toBitVec_or, Int8.toBitVec_not, BitVec.or_not_self, + Int8.toBitVec_neg, Int8.toBitVec_one, BitVec.negOne_eq_allOnes] +@[simp] theorem Int16.or_not_self {a : Int16} : a ||| ~~~a = -1 := by + rw [← Int16.toBitVec_inj, Int16.toBitVec_or, Int16.toBitVec_not, BitVec.or_not_self, + Int16.toBitVec_neg, Int16.toBitVec_one, BitVec.negOne_eq_allOnes] +@[simp] theorem Int32.or_not_self {a : Int32} : a ||| ~~~a = -1 := by + rw [← Int32.toBitVec_inj, Int32.toBitVec_or, Int32.toBitVec_not, BitVec.or_not_self, + Int32.toBitVec_neg, Int32.toBitVec_one, BitVec.negOne_eq_allOnes] +@[simp] theorem Int64.or_not_self {a : Int64} : a ||| ~~~a = -1 := by + rw [← Int64.toBitVec_inj, Int64.toBitVec_or, Int64.toBitVec_not, BitVec.or_not_self, + Int64.toBitVec_neg, Int64.toBitVec_one, BitVec.negOne_eq_allOnes] +@[simp] theorem ISize.or_not_self {a : ISize} : a ||| ~~~a = -1 := by + rw [← ISize.toBitVec_inj, ISize.toBitVec_or, ISize.toBitVec_not, BitVec.or_not_self, + ISize.toBitVec_neg, ISize.toBitVec_one, BitVec.negOne_eq_allOnes] + +@[simp] theorem Int8.not_or_self {a : Int8} : ~~~a ||| a = -1 := by simp [Int8.or_comm] +@[simp] theorem Int16.not_or_self {a : Int16} : ~~~a ||| a = -1 := by simp [Int16.or_comm] +@[simp] theorem Int32.not_or_self {a : Int32} : ~~~a ||| a = -1 := by simp [Int32.or_comm] +@[simp] theorem Int64.not_or_self {a : Int64} : ~~~a ||| a = -1 := by simp [Int64.or_comm] +@[simp] theorem ISize.not_or_self {a : ISize} : ~~~a ||| a = -1 := by simp [ISize.or_comm] + +theorem Int8.not_eq_comm {a b : Int8} : ~~~a = b ↔ a = ~~~b := by + simp [← Int8.toBitVec_inj, BitVec.not_eq_comm] +theorem Int16.not_eq_comm {a b : Int16} : ~~~a = b ↔ a = ~~~b := by + simp [← Int16.toBitVec_inj, BitVec.not_eq_comm] +theorem Int32.not_eq_comm {a b : Int32} : ~~~a = b ↔ a = ~~~b := by + simp [← Int32.toBitVec_inj, BitVec.not_eq_comm] +theorem Int64.not_eq_comm {a b : Int64} : ~~~a = b ↔ a = ~~~b := by + simp [← Int64.toBitVec_inj, BitVec.not_eq_comm] +theorem ISize.not_eq_comm {a b : ISize} : ~~~a = b ↔ a = ~~~b := by + simp [← ISize.toBitVec_inj, BitVec.not_eq_comm] + +@[simp] theorem Int8.ne_not_self {a : Int8} : a ≠ ~~~a := by simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.ne_not_self {a : Int16} : a ≠ ~~~a := by simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.ne_not_self {a : Int32} : a ≠ ~~~a := by simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.ne_not_self {a : Int64} : a ≠ ~~~a := by simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.ne_not_self {a : ISize} : a ≠ ~~~a := by simp [← ISize.toBitVec_inj] + +@[simp] theorem Int8.not_ne_self {a : Int8} : ~~~a ≠ a := by simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.not_ne_self {a : Int16} : ~~~a ≠ a := by simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.not_ne_self {a : Int32} : ~~~a ≠ a := by simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.not_ne_self {a : Int64} : ~~~a ≠ a := by simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.not_ne_self {a : ISize} : ~~~a ≠ a := by simp [← ISize.toBitVec_inj] + +theorem Int8.not_xor {a b : Int8} : ~~~a ^^^ b = ~~~(a ^^^ b) := by + simp [← Int8.toBitVec_inj, BitVec.not_xor_left] +theorem Int16.not_xor {a b : Int16} : ~~~a ^^^ b = ~~~(a ^^^ b) := by + simp [← Int16.toBitVec_inj, BitVec.not_xor_left] +theorem Int32.not_xor {a b : Int32} : ~~~a ^^^ b = ~~~(a ^^^ b) := by + simp [← Int32.toBitVec_inj, BitVec.not_xor_left] +theorem Int64.not_xor {a b : Int64} : ~~~a ^^^ b = ~~~(a ^^^ b) := by + simp [← Int64.toBitVec_inj, BitVec.not_xor_left] +theorem ISize.not_xor {a b : ISize} : ~~~a ^^^ b = ~~~(a ^^^ b) := by + simp [← ISize.toBitVec_inj, BitVec.not_xor_left] + +theorem Int8.xor_not {a b : Int8} : a ^^^ ~~~b = ~~~(a ^^^ b) := by + simp [← Int8.toBitVec_inj, BitVec.not_xor_right] +theorem Int16.xor_not {a b : Int16} : a ^^^ ~~~b = ~~~(a ^^^ b) := by + simp [← Int16.toBitVec_inj, BitVec.not_xor_right] +theorem Int32.xor_not {a b : Int32} : a ^^^ ~~~b = ~~~(a ^^^ b) := by + simp [← Int32.toBitVec_inj, BitVec.not_xor_right] +theorem Int64.xor_not {a b : Int64} : a ^^^ ~~~b = ~~~(a ^^^ b) := by + simp [← Int64.toBitVec_inj, BitVec.not_xor_right] +theorem ISize.xor_not {a b : ISize} : a ^^^ ~~~b = ~~~(a ^^^ b) := by + simp [← ISize.toBitVec_inj, BitVec.not_xor_right] + +@[simp] theorem Int8.shiftLeft_zero {a : Int8} : a <<< 0 = a := by simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.shiftLeft_zero {a : Int16} : a <<< 0 = a := by simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.shiftLeft_zero {a : Int32} : a <<< 0 = a := by simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.shiftLeft_zero {a : Int64} : a <<< 0 = a := by simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.shiftLeft_zero {a : ISize} : a <<< 0 = a := by simp [← ISize.toBitVec_inj] + +@[simp] theorem Int8.zero_shiftLeft {a : Int8} : 0 <<< a = 0 := by simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.zero_shiftLeft {a : Int16} : 0 <<< a = 0 := by simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.zero_shiftLeft {a : Int32} : 0 <<< a = 0 := by simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.zero_shiftLeft {a : Int64} : 0 <<< a = 0 := by simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.zero_shiftLeft {a : ISize} : 0 <<< a = 0 := by simp [← ISize.toBitVec_inj] + +theorem Int8.shiftLeft_xor {a b c : Int8} : (a ^^^ b) <<< c = (a <<< c) ^^^ (b <<< c) := by + simp [← Int8.toBitVec_inj, BitVec.shiftLeft_xor_distrib] +theorem Int16.shiftLeft_xor {a b c : Int16} : (a ^^^ b) <<< c = (a <<< c) ^^^ (b <<< c) := by + simp [← Int16.toBitVec_inj, BitVec.shiftLeft_xor_distrib] +theorem Int32.shiftLeft_xor {a b c : Int32} : (a ^^^ b) <<< c = (a <<< c) ^^^ (b <<< c) := by + simp [← Int32.toBitVec_inj, BitVec.shiftLeft_xor_distrib] +theorem Int64.shiftLeft_xor {a b c : Int64} : (a ^^^ b) <<< c = (a <<< c) ^^^ (b <<< c) := by + simp [← Int64.toBitVec_inj, BitVec.shiftLeft_xor_distrib] +theorem ISize.shiftLeft_xor {a b c : ISize} : (a ^^^ b) <<< c = (a <<< c) ^^^ (b <<< c) := by + simp [← ISize.toBitVec_inj, BitVec.shiftLeft_xor_distrib] + +theorem Int8.shiftLeft_and {a b c : Int8} : (a &&& b) <<< c = (a <<< c) &&& (b <<< c) := by + simp [← Int8.toBitVec_inj, BitVec.shiftLeft_and_distrib] +theorem Int16.shiftLeft_and {a b c : Int16} : (a &&& b) <<< c = (a <<< c) &&& (b <<< c) := by + simp [← Int16.toBitVec_inj, BitVec.shiftLeft_and_distrib] +theorem Int32.shiftLeft_and {a b c : Int32} : (a &&& b) <<< c = (a <<< c) &&& (b <<< c) := by + simp [← Int32.toBitVec_inj, BitVec.shiftLeft_and_distrib] +theorem Int64.shiftLeft_and {a b c : Int64} : (a &&& b) <<< c = (a <<< c) &&& (b <<< c) := by + simp [← Int64.toBitVec_inj, BitVec.shiftLeft_and_distrib] +theorem ISize.shiftLeft_and {a b c : ISize} : (a &&& b) <<< c = (a <<< c) &&& (b <<< c) := by + simp [← ISize.toBitVec_inj, BitVec.shiftLeft_and_distrib] + +theorem Int8.shiftLeft_or {a b c : Int8} : (a ||| b) <<< c = (a <<< c) ||| (b <<< c) := by + simp [← Int8.toBitVec_inj, BitVec.shiftLeft_or_distrib] +theorem Int16.shiftLeft_or {a b c : Int16} : (a ||| b) <<< c = (a <<< c) ||| (b <<< c) := by + simp [← Int16.toBitVec_inj, BitVec.shiftLeft_or_distrib] +theorem Int32.shiftLeft_or {a b c : Int32} : (a ||| b) <<< c = (a <<< c) ||| (b <<< c) := by + simp [← Int32.toBitVec_inj, BitVec.shiftLeft_or_distrib] +theorem Int64.shiftLeft_or {a b c : Int64} : (a ||| b) <<< c = (a <<< c) ||| (b <<< c) := by + simp [← Int64.toBitVec_inj, BitVec.shiftLeft_or_distrib] +theorem ISize.shiftLeft_or {a b c : ISize} : (a ||| b) <<< c = (a <<< c) ||| (b <<< c) := by + simp [← ISize.toBitVec_inj, BitVec.shiftLeft_or_distrib] + +@[simp] theorem Int8.neg_one_shiftLeft_and_shiftLeft {a b : Int8} : + (-1) <<< b &&& a <<< b = a <<< b := by simp [← Int8.shiftLeft_and] +@[simp] theorem Int16.neg_one_shiftLeft_and_shiftLeft {a b : Int16} : + (-1) <<< b &&& a <<< b = a <<< b := by simp [← Int16.shiftLeft_and] +@[simp] theorem Int32.neg_one_shiftLeft_and_shiftLeft {a b : Int32} : + (-1) <<< b &&& a <<< b = a <<< b := by simp [← Int32.shiftLeft_and] +@[simp] theorem Int64.neg_one_shiftLeft_and_shiftLeft {a b : Int64} : + (-1) <<< b &&& a <<< b = a <<< b := by simp [← Int64.shiftLeft_and] +@[simp] theorem ISize.neg_one_shiftLeft_and_shiftLeft {a b : ISize} : + (-1) <<< b &&& a <<< b = a <<< b := by simp [← ISize.shiftLeft_and] + +@[simp] theorem Int8.neg_one_shiftLeft_or_shiftLeft {a b : Int8} : + (-1) <<< b ||| a <<< b = (-1) <<< b := by simp [← Int8.shiftLeft_or] +@[simp] theorem Int16.neg_one_shiftLeft_or_shiftLeft {a b : Int16} : + (-1) <<< b ||| a <<< b = (-1) <<< b := by simp [← Int16.shiftLeft_or] +@[simp] theorem Int32.neg_one_shiftLeft_or_shiftLeft {a b : Int32} : + (-1) <<< b ||| a <<< b = (-1) <<< b := by simp [← Int32.shiftLeft_or] +@[simp] theorem Int64.neg_one_shiftLeft_or_shiftLeft {a b : Int8} : + (-1) <<< b ||| a <<< b = (-1) <<< b := by simp [← Int64.shiftLeft_or] +@[simp] theorem ISize.neg_one_shiftLeft_or_shiftLeft {a b : ISize} : + (-1) <<< b ||| a <<< b = (-1) <<< b := by simp [← ISize.shiftLeft_or] + +@[simp] theorem Int8.shiftRight_zero {a : Int8} : a >>> 0 = a := by simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.shiftRight_zero {a : Int16} : a >>> 0 = a := by simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.shiftRight_zero {a : Int32} : a >>> 0 = a := by simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.shiftRight_zero {a : Int64} : a >>> 0 = a := by simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.shiftRight_zero {a : ISize} : a >>> 0 = a := by simp [← ISize.toBitVec_inj] + +@[simp] theorem Int8.zero_shiftRight {a : Int8} : 0 >>> a = 0 := by simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.zero_shiftRight {a : Int16} : 0 >>> a = 0 := by simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.zero_shiftRight {a : Int32} : 0 >>> a = 0 := by simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.zero_shiftRight {a : Int64} : 0 >>> a = 0 := by simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.zero_shiftRight {a : ISize} : 0 >>> a = 0 := by simp [← ISize.toBitVec_inj] + +theorem Int8.shiftRight_xor {a b c : Int8} : (a ^^^ b) >>> c = (a >>> c) ^^^ (b >>> c) := by + simp [← Int8.toBitVec_inj, BitVec.sshiftRight_xor_distrib] +theorem Int16.shiftRight_xor {a b c : Int16} : (a ^^^ b) >>> c = (a >>> c) ^^^ (b >>> c) := by + simp [← Int16.toBitVec_inj, BitVec.sshiftRight_xor_distrib] +theorem Int32.shiftRight_xor {a b c : Int32} : (a ^^^ b) >>> c = (a >>> c) ^^^ (b >>> c) := by + simp [← Int32.toBitVec_inj, BitVec.sshiftRight_xor_distrib] +theorem Int64.shiftRight_xor {a b c : Int64} : (a ^^^ b) >>> c = (a >>> c) ^^^ (b >>> c) := by + simp [← Int64.toBitVec_inj, BitVec.sshiftRight_xor_distrib] +theorem ISize.shiftRight_xor {a b c : ISize} : (a ^^^ b) >>> c = (a >>> c) ^^^ (b >>> c) := by + simp [← ISize.toBitVec_inj, BitVec.sshiftRight_xor_distrib] + +theorem Int8.shiftRight_and {a b c : Int8} : (a &&& b) >>> c = (a >>> c) &&& (b >>> c) := by + simp [← Int8.toBitVec_inj, BitVec.sshiftRight_and_distrib] +theorem Int16.shiftRight_and {a b c : Int16} : (a &&& b) >>> c = (a >>> c) &&& (b >>> c) := by + simp [← Int16.toBitVec_inj, BitVec.sshiftRight_and_distrib] +theorem Int32.shiftRight_and {a b c : Int32} : (a &&& b) >>> c = (a >>> c) &&& (b >>> c) := by + simp [← Int32.toBitVec_inj, BitVec.sshiftRight_and_distrib] +theorem Int64.shiftRight_and {a b c : Int64} : (a &&& b) >>> c = (a >>> c) &&& (b >>> c) := by + simp [← Int64.toBitVec_inj, BitVec.sshiftRight_and_distrib] +theorem ISize.shiftRight_and {a b c : ISize} : (a &&& b) >>> c = (a >>> c) &&& (b >>> c) := by + simp [← ISize.toBitVec_inj, BitVec.sshiftRight_and_distrib] + +theorem Int8.shiftRight_or {a b c : Int8} : (a ||| b) >>> c = (a >>> c) ||| (b >>> c) := by + simp [← Int8.toBitVec_inj, BitVec.sshiftRight_or_distrib] +theorem Int16.shiftRight_or {a b c : Int16} : (a ||| b) >>> c = (a >>> c) ||| (b >>> c) := by + simp [← Int16.toBitVec_inj, BitVec.sshiftRight_or_distrib] +theorem Int32.shiftRight_or {a b c : Int32} : (a ||| b) >>> c = (a >>> c) ||| (b >>> c) := by + simp [← Int32.toBitVec_inj, BitVec.sshiftRight_or_distrib] +theorem Int64.shiftRight_or {a b c : Int64} : (a ||| b) >>> c = (a >>> c) ||| (b >>> c) := by + simp [← Int64.toBitVec_inj, BitVec.sshiftRight_or_distrib] +theorem ISize.shiftRight_or {a b c : ISize} : (a ||| b) >>> c = (a >>> c) ||| (b >>> c) := by + simp [← ISize.toBitVec_inj, BitVec.sshiftRight_or_distrib] diff --git a/src/Init/Data/SInt/Lemmas.lean b/src/Init/Data/SInt/Lemmas.lean index ae9cb28fe7..fdb2b68c0d 100644 --- a/src/Init/Data/SInt/Lemmas.lean +++ b/src/Init/Data/SInt/Lemmas.lean @@ -16,8 +16,9 @@ macro "declare_int_theorems" typeName:ident _bits:term:arg : command => do let mut cmds ← Syntax.getArgs <$> `( namespace $typeName - @[int_toBitVec] theorem le_def {a b : $typeName} : a ≤ b ↔ a.toBitVec.sle b.toBitVec := Iff.rfl - @[int_toBitVec] theorem lt_def {a b : $typeName} : a < b ↔ a.toBitVec.slt b.toBitVec := Iff.rfl + @[int_toBitVec] theorem le_iff_toBitVec_sle {a b : $typeName} : a ≤ b ↔ a.toBitVec.sle b.toBitVec := Iff.rfl + @[int_toBitVec] theorem lt_iff_toBitVec_slt {a b : $typeName} : a < b ↔ a.toBitVec.slt b.toBitVec := Iff.rfl + theorem toBitVec_inj {a b : $typeName} : a.toBitVec = b.toBitVec ↔ a = b := ⟨toBitVec.inj, (· ▸ rfl)⟩ @[int_toBitVec] theorem eq_iff_toBitVec_eq {a b : $typeName} : a = b ↔ a.toBitVec = b.toBitVec := @@ -27,6 +28,12 @@ macro "declare_int_theorems" typeName:ident _bits:term:arg : command => do @[simp] theorem toBitVec_ofNat' {n : Nat} : toBitVec (ofNat n) = BitVec.ofNat _ n := rfl @[simp, int_toBitVec] theorem toBitVec_ofNat {n : Nat} : toBitVec (no_index (OfNat.ofNat n)) = OfNat.ofNat n := rfl + @[simp, int_toBitVec] protected theorem toBitVec_add {a b : $typeName} : (a + b).toBitVec = a.toBitVec + b.toBitVec := rfl + @[simp, int_toBitVec] protected theorem toBitVec_sub {a b : $typeName} : (a - b).toBitVec = a.toBitVec - b.toBitVec := rfl + @[simp, int_toBitVec] protected theorem toBitVec_mul {a b : $typeName} : (a * b).toBitVec = a.toBitVec * b.toBitVec := rfl + @[simp, int_toBitVec] protected theorem toBitVec_div {a b : $typeName} : (a / b).toBitVec = a.toBitVec.sdiv b.toBitVec := rfl + @[simp, int_toBitVec] protected theorem toBitVec_mod {a b : $typeName} : (a % b).toBitVec = a.toBitVec.srem b.toBitVec := rfl + end $typeName ) return ⟨mkNullNode cmds⟩ @@ -37,6 +44,28 @@ declare_int_theorems Int32 32 declare_int_theorems Int64 64 declare_int_theorems ISize System.Platform.numBits +@[deprecated Int8.le_iff_toBitVec_sle (since := "2025-03-20")] +theorem Int8.le_def {a b : Int8} : a ≤ b ↔ a.toBitVec.sle b.toBitVec := Iff.rfl +@[deprecated Int16.le_iff_toBitVec_sle (since := "2025-03-20")] +theorem Int16.le_def {a b : Int16} : a ≤ b ↔ a.toBitVec.sle b.toBitVec := Iff.rfl +@[deprecated Int32.le_iff_toBitVec_sle (since := "2025-03-20")] +theorem Int32.le_def {a b : Int32} : a ≤ b ↔ a.toBitVec.sle b.toBitVec := Iff.rfl +@[deprecated Int64.le_iff_toBitVec_sle (since := "2025-03-20")] +theorem Int64.le_def {a b : Int64} : a ≤ b ↔ a.toBitVec.sle b.toBitVec := Iff.rfl +@[deprecated ISize.le_iff_toBitVec_sle (since := "2025-03-20")] +theorem ISize.le_def {a b : ISize} : a ≤ b ↔ a.toBitVec.sle b.toBitVec := Iff.rfl + +@[deprecated Int8.lt_iff_toBitVec_slt (since := "2025-03-20")] +theorem Int8.lt_def {a b : Int8} : a < b ↔ a.toBitVec.slt b.toBitVec := Iff.rfl +@[deprecated Int16.lt_iff_toBitVec_slt (since := "2025-03-20")] +theorem Int16.lt_def {a b : Int16} : a < b ↔ a.toBitVec.slt b.toBitVec := Iff.rfl +@[deprecated Int32.lt_iff_toBitVec_slt (since := "2025-03-20")] +theorem Int32.lt_def {a b : Int32} : a < b ↔ a.toBitVec.slt b.toBitVec := Iff.rfl +@[deprecated Int64.lt_iff_toBitVec_slt (since := "2025-03-20")] +theorem Int64.lt_def {a b : Int64} : a < b ↔ a.toBitVec.slt b.toBitVec := Iff.rfl +@[deprecated ISize.lt_iff_toBitVec_slt (since := "2025-03-20")] +theorem ISize.lt_def {a b : ISize} : a < b ↔ a.toBitVec.slt b.toBitVec := Iff.rfl + theorem Int8.toInt.inj {x y : Int8} (h : x.toInt = y.toInt) : x = y := Int8.toBitVec.inj (BitVec.eq_of_toInt_eq h) theorem Int8.toInt_inj {x y : Int8} : x.toInt = y.toInt ↔ x = y := ⟨Int8.toInt.inj, fun h => h ▸ rfl⟩ theorem Int16.toInt.inj {x y : Int16} (h : x.toInt = y.toInt) : x = y := Int16.toBitVec.inj (BitVec.eq_of_toInt_eq h) @@ -54,7 +83,17 @@ theorem ISize.toInt_inj {x y : ISize} : x.toInt = y.toInt ↔ x = y := ⟨ISize. @[simp] theorem Int64.toBitVec_neg (x : Int64) : (-x).toBitVec = -x.toBitVec := rfl @[simp] theorem ISize.toBitVec_neg (x : ISize) : (-x).toBitVec = -x.toBitVec := rfl -@[simp] theorem ISize.toBitVec_zero : (0 : ISize).toBitVec = 0 := rfl +@[simp] theorem Int8.toBitVec_zero : toBitVec 0 = 0#8 := rfl +@[simp] theorem Int16.toBitVec_zero : toBitVec 0 = 0#16 := rfl +@[simp] theorem Int32.toBitVec_zero : toBitVec 0 = 0#32 := rfl +@[simp] theorem Int64.toBitVec_zero : toBitVec 0 = 0#64 := rfl +@[simp] theorem ISize.toBitVec_zero : toBitVec 0 = 0#System.Platform.numBits := rfl + +theorem Int8.toBitVec_one : (1 : Int8).toBitVec = 1#8 := rfl +theorem Int16.toBitVec_one : (1 : Int16).toBitVec = 1#16 := rfl +theorem Int32.toBitVec_one : (1 : Int32).toBitVec = 1#32 := rfl +theorem Int64.toBitVec_one : (1 : Int64).toBitVec = 1#64 := rfl +theorem ISize.toBitVec_one : (1 : ISize).toBitVec = 1#System.Platform.numBits := rfl @[simp] theorem Int8.toBitVec_ofInt (i : Int) : (ofInt i).toBitVec = BitVec.ofInt _ i := rfl @[simp] theorem Int16.toBitVec_ofInt (i : Int) : (ofInt i).toBitVec = BitVec.ofInt _ i := rfl @@ -193,7 +232,7 @@ theorem Int8.toInt_minValue : Int8.minValue.toInt = -2^7 := rfl theorem Int16.toInt_minValue : Int16.minValue.toInt = -2^15 := rfl theorem Int32.toInt_minValue : Int32.minValue.toInt = -2^31 := rfl theorem Int64.toInt_minValue : Int64.minValue.toInt = -2^63 := rfl -@[simp] theorem ISize.toInt_minValue : ISize.minValue.toInt = -2^(System.Platform.numBits - 1) := by +theorem ISize.toInt_minValue : ISize.minValue.toInt = -2 ^ (System.Platform.numBits - 1) := by rw [minValue, toInt_ofInt_of_two_pow_numBits_le] <;> cases System.Platform.numBits_eq <;> simp_all @@ -201,7 +240,7 @@ theorem Int8.toInt_maxValue : Int8.maxValue.toInt = 2 ^ 7 - 1 := rfl theorem Int16.toInt_maxValue : Int16.maxValue.toInt = 2 ^ 15 - 1 := rfl theorem Int32.toInt_maxValue : Int32.maxValue.toInt = 2 ^ 31 - 1 := rfl theorem Int64.toInt_maxValue : Int64.maxValue.toInt = 2 ^ 63 - 1 := rfl -@[simp] theorem ISize.toInt_maxValue : ISize.maxValue.toInt = 2^(System.Platform.numBits - 1) - 1:= by +theorem ISize.toInt_maxValue : ISize.maxValue.toInt = 2 ^ (System.Platform.numBits - 1) - 1:= by rw [maxValue, toInt_ofInt_of_two_pow_numBits_le] <;> cases System.Platform.numBits_eq <;> simp_all @@ -526,15 +565,15 @@ theorem ISize.toFin_toBitVec (x : ISize) : x.toBitVec.toFin = x.toUSize.toFin := @[simp] theorem Int8.toInt_bmod_two_pow_numBits (x : Int8) : x.toInt.bmod (2 ^ System.Platform.numBits) = x.toInt := by refine Int.bmod_eq_self_of_le (Int.le_trans ?_ x.iSizeMinValue_le_toInt) (Int.lt_of_le_sub_one (Int.le_trans x.toInt_le_iSizeMaxValue ?_)) - all_goals cases System.Platform.numBits_eq <;> simp_all + all_goals cases System.Platform.numBits_eq <;> simp_all [ISize.toInt_minValue, ISize.toInt_maxValue] @[simp] theorem Int16.toInt_bmod_two_pow_numBits (x : Int16) : x.toInt.bmod (2 ^ System.Platform.numBits) = x.toInt := by refine Int.bmod_eq_self_of_le (Int.le_trans ?_ x.iSizeMinValue_le_toInt) (Int.lt_of_le_sub_one (Int.le_trans x.toInt_le_iSizeMaxValue ?_)) - all_goals cases System.Platform.numBits_eq <;> simp_all + all_goals cases System.Platform.numBits_eq <;> simp_all [ISize.toInt_minValue, ISize.toInt_maxValue] @[simp] theorem Int32.toInt_bmod_two_pow_numBits (x : Int32) : x.toInt.bmod (2 ^ System.Platform.numBits) = x.toInt := by refine Int.bmod_eq_self_of_le (Int.le_trans ?_ x.iSizeMinValue_le_toInt) (Int.lt_of_le_sub_one (Int.le_trans x.toInt_le_iSizeMaxValue ?_)) - all_goals cases System.Platform.numBits_eq <;> simp_all + all_goals cases System.Platform.numBits_eq <;> simp_all [ISize.toInt_minValue, ISize.toInt_maxValue] @[simp] theorem BitVec.ofInt_int8ToInt (x : Int8) : BitVec.ofInt 8 x.toInt = x.toBitVec := BitVec.eq_of_toInt_eq (by simp) @[simp] theorem BitVec.ofInt_int16ToInt (x : Int16) : BitVec.ofInt 16 x.toInt = x.toBitVec := BitVec.eq_of_toInt_eq (by simp) @@ -625,9 +664,9 @@ theorem ISize.ofIntLE_int64ToInt (x : Int64) {h₁ h₂} : ISize.ofIntLE x.toInt rw [ofIntLE, toInt_ofInt_of_le h₁ (Int.lt_of_le_sub_one h₂)] @[simp] theorem ISize.toInt_ofIntLE {x : Int} {h₁ h₂} : (ofIntLE x h₁ h₂).toInt = x := by rw [ofIntLE, toInt_ofInt_of_two_pow_numBits_le] - · simpa using h₁ + · simpa [ISize.toInt_minValue] using h₁ · apply Int.lt_of_le_sub_one - simpa using h₂ + simpa [ISize.toInt_maxValue] using h₂ theorem Int8.ofIntLE_eq_ofIntTruncate {x : Int} {h₁ h₂} : (ofIntLE x h₁ h₂) = ofIntTruncate x := by rw [ofIntTruncate, dif_pos h₁, dif_pos h₂] @@ -733,6 +772,12 @@ theorem Int32.le_iff_toInt_le {x y : Int32} : x ≤ y ↔ x.toInt ≤ y.toInt := theorem Int64.le_iff_toInt_le {x y : Int64} : x ≤ y ↔ x.toInt ≤ y.toInt := BitVec.sle_iff_toInt_le theorem ISize.le_iff_toInt_le {x y : ISize} : x ≤ y ↔ x.toInt ≤ y.toInt := BitVec.sle_iff_toInt_le +theorem Int8.lt_iff_toInt_lt {x y : Int8} : x < y ↔ x.toInt < y.toInt := BitVec.slt_iff_toInt_lt +theorem Int16.lt_iff_toInt_lt {x y : Int16} : x < y ↔ x.toInt < y.toInt := BitVec.slt_iff_toInt_lt +theorem Int32.lt_iff_toInt_lt {x y : Int32} : x < y ↔ x.toInt < y.toInt := BitVec.slt_iff_toInt_lt +theorem Int64.lt_iff_toInt_lt {x y : Int64} : x < y ↔ x.toInt < y.toInt := BitVec.slt_iff_toInt_lt +theorem ISize.lt_iff_toInt_lt {x y : ISize} : x < y ↔ x.toInt < y.toInt := BitVec.slt_iff_toInt_lt + theorem Int8.cast_toNatClampNeg (x : Int8) (hx : 0 ≤ x) : x.toNatClampNeg = x.toInt := by rw [toNatClampNeg, toInt, Int.toNat_of_nonneg (by simpa using le_iff_toInt_le.1 hx)] theorem Int16.cast_toNatClampNeg (x : Int16) (hx : 0 ≤ x) : x.toNatClampNeg = x.toInt := by @@ -1401,7 +1446,7 @@ theorem ISize.toInt64_ofIntLE {n : Int} (h₁ h₂) : (ISize.ofNat n).toInt64 = Int64.ofNat n := by rw [← ofInt_eq_ofNat, toInt64_ofInt _ h, Int64.ofInt_eq_ofNat] refine Int.le_trans ?_ (Int.zero_le_ofNat _) - cases System.Platform.numBits_eq <;> simp_all + cases System.Platform.numBits_eq <;> simp_all [ISize.toInt_minValue] @[simp] theorem ISize.toInt64_ofNat {n : Nat} (h : n ≤ 2147483647) : toInt64 (no_index (OfNat.ofNat n)) = OfNat.ofNat n := @@ -1480,3 +1525,1738 @@ theorem ISize.ofBitVec_ofNatLT (n : Nat) (hn) : ISize.ofBitVec (BitVec.ofNatLT n @[simp] theorem ISize.ofIntTruncate_bitVecToInt (n : BitVec System.Platform.numBits) : ISize.ofIntTruncate n.toInt = ISize.ofBitVec n := ISize.toBitVec.inj (by simp [toBitVec_ofIntTruncate (toInt_minValue ▸ n.le_toInt) (toInt_maxValue ▸ n.toInt_le) ]) + +@[simp] theorem Int8.toInt_neg (n : Int8) : (-n).toInt = (-n.toInt).bmod (2 ^ 8) := BitVec.toInt_neg +@[simp] theorem Int16.toInt_neg (n : Int16) : (-n).toInt = (-n.toInt).bmod (2 ^ 16) := BitVec.toInt_neg +@[simp] theorem Int32.toInt_neg (n : Int32) : (-n).toInt = (-n.toInt).bmod (2 ^ 32) := BitVec.toInt_neg +@[simp] theorem Int64.toInt_neg (n : Int64) : (-n).toInt = (-n.toInt).bmod (2 ^ 64) := BitVec.toInt_neg +-- Simp on this seems to do more harm than good when numeric literals are involved +theorem ISize.toInt_neg (n : ISize) : (-n).toInt = (-n.toInt).bmod (2 ^ System.Platform.numBits) := BitVec.toInt_neg + +@[simp] theorem Int8.toNatClampNeg_eq_zero_iff {n : Int8} : n.toNatClampNeg = 0 ↔ n ≤ 0 := by + rw [toNatClampNeg, Int.toNat_eq_zero, le_iff_toInt_le, toInt_zero] +@[simp] theorem Int16.toNatClampNeg_eq_zero_iff {n : Int16} : n.toNatClampNeg = 0 ↔ n ≤ 0 := by + rw [toNatClampNeg, Int.toNat_eq_zero, le_iff_toInt_le, toInt_zero] +@[simp] theorem Int32.toNatClampNeg_eq_zero_iff {n : Int32} : n.toNatClampNeg = 0 ↔ n ≤ 0 := by + rw [toNatClampNeg, Int.toNat_eq_zero, le_iff_toInt_le, toInt_zero] +@[simp] theorem Int64.toNatClampNeg_eq_zero_iff {n : Int64} : n.toNatClampNeg = 0 ↔ n ≤ 0 := by + rw [toNatClampNeg, Int.toNat_eq_zero, le_iff_toInt_le, toInt_zero] +@[simp] theorem ISize.toNatClampNeg_eq_zero_iff {n : ISize} : n.toNatClampNeg = 0 ↔ n ≤ 0 := by + rw [toNatClampNeg, Int.toNat_eq_zero, le_iff_toInt_le, toInt_zero] + +@[simp] theorem Int8.not_le (n m : Int8) : ¬n ≤ m ↔ m < n := by simp [le_iff_toInt_le, lt_iff_toInt_lt] +@[simp] theorem Int16.not_le (n m : Int16) : ¬n ≤ m ↔ m < n := by simp [le_iff_toInt_le, lt_iff_toInt_lt] +@[simp] theorem Int32.not_le (n m : Int32) : ¬n ≤ m ↔ m < n := by simp [le_iff_toInt_le, lt_iff_toInt_lt] +@[simp] theorem Int64.not_le (n m : Int64) : ¬n ≤ m ↔ m < n := by simp [le_iff_toInt_le, lt_iff_toInt_lt] +@[simp] theorem ISize.not_le (n m : ISize) : ¬n ≤ m ↔ m < n := by simp [le_iff_toInt_le, lt_iff_toInt_lt] + +@[simp] theorem Int8.neg_nonpos_iff (n : Int8) : -n ≤ 0 ↔ n = minValue ∨ 0 ≤ n := by + rw [le_iff_toBitVec_sle, toBitVec_zero, toBitVec_neg, BitVec.neg_sle_zero (by decide)] + simp [← toBitVec_inj, le_iff_toBitVec_sle, BitVec.intMin_eq_neg_two_pow] +@[simp] theorem Int16.neg_nonpos_iff (n : Int16) : -n ≤ 0 ↔ n = minValue ∨ 0 ≤ n := by + rw [le_iff_toBitVec_sle, toBitVec_zero, toBitVec_neg, BitVec.neg_sle_zero (by decide)] + simp [← toBitVec_inj, le_iff_toBitVec_sle, BitVec.intMin_eq_neg_two_pow] +@[simp] theorem Int32.neg_nonpos_iff (n : Int32) : -n ≤ 0 ↔ n = minValue ∨ 0 ≤ n := by + rw [le_iff_toBitVec_sle, toBitVec_zero, toBitVec_neg, BitVec.neg_sle_zero (by decide)] + simp [← toBitVec_inj, le_iff_toBitVec_sle, BitVec.intMin_eq_neg_two_pow] +@[simp] theorem Int64.neg_nonpos_iff (n : Int64) : -n ≤ 0 ↔ n = minValue ∨ 0 ≤ n := by + rw [le_iff_toBitVec_sle, toBitVec_zero, toBitVec_neg, BitVec.neg_sle_zero (by decide)] + simp [← toBitVec_inj, le_iff_toBitVec_sle, BitVec.intMin_eq_neg_two_pow] +@[simp] theorem ISize.neg_nonpos_iff (n : ISize) : -n ≤ 0 ↔ n = minValue ∨ 0 ≤ n := by + rw [le_iff_toBitVec_sle, toBitVec_zero, toBitVec_neg, BitVec.neg_sle_zero System.Platform.numBits_pos] + simp [← toBitVec_inj, le_iff_toBitVec_sle, BitVec.intMin_eq_neg_two_pow] + +@[simp] theorem Int8.toNatClampNeg_pos_iff (n : Int8) : 0 < n.toNatClampNeg ↔ 0 < n := by simp [Nat.pos_iff_ne_zero] +@[simp] theorem Int16.toNatClampNeg_pos_iff (n : Int16) : 0 < n.toNatClampNeg ↔ 0 < n := by simp [Nat.pos_iff_ne_zero] +@[simp] theorem Int32.toNatClampNeg_pos_iff (n : Int32) : 0 < n.toNatClampNeg ↔ 0 < n := by simp [Nat.pos_iff_ne_zero] +@[simp] theorem Int64.toNatClampNeg_pos_iff (n : Int64) : 0 < n.toNatClampNeg ↔ 0 < n := by simp [Nat.pos_iff_ne_zero] +@[simp] theorem ISize.toNatClampNeg_pos_iff (n : ISize) : 0 < n.toNatClampNeg ↔ 0 < n := by simp [Nat.pos_iff_ne_zero] + +@[simp] theorem Int8.toInt_div (a b : Int8) : (a / b).toInt = (a.toInt.tdiv b.toInt).bmod (2 ^ 8) := by + rw [← toInt_toBitVec, Int8.toBitVec_div, BitVec.toInt_sdiv, toInt_toBitVec, toInt_toBitVec] +@[simp] theorem Int16.toInt_div (a b : Int16) : (a / b).toInt = (a.toInt.tdiv b.toInt).bmod (2 ^ 16) := by + rw [← toInt_toBitVec, Int16.toBitVec_div, BitVec.toInt_sdiv, toInt_toBitVec, toInt_toBitVec] +@[simp] theorem Int32.toInt_div (a b : Int32) : (a / b).toInt = (a.toInt.tdiv b.toInt).bmod (2 ^ 32) := by + rw [← toInt_toBitVec, Int32.toBitVec_div, BitVec.toInt_sdiv, toInt_toBitVec, toInt_toBitVec] +@[simp] theorem Int64.toInt_div (a b : Int64) : (a / b).toInt = (a.toInt.tdiv b.toInt).bmod (2 ^ 64) := by + rw [← toInt_toBitVec, Int64.toBitVec_div, BitVec.toInt_sdiv, toInt_toBitVec, toInt_toBitVec] +@[simp] theorem ISize.toInt_div (a b : ISize) : (a / b).toInt = (a.toInt.tdiv b.toInt).bmod (2 ^ System.Platform.numBits) := by + rw [← toInt_toBitVec, ISize.toBitVec_div, BitVec.toInt_sdiv, toInt_toBitVec, toInt_toBitVec] + +theorem Int8.toInt_div_of_ne_left (a b : Int8) (h : a ≠ minValue) : (a / b).toInt = a.toInt.tdiv b.toInt := by + rw [← toInt_toBitVec, Int8.toBitVec_div, BitVec.toInt_sdiv_of_ne_or_ne, toInt_toBitVec, toInt_toBitVec] + exact Or.inl (by simpa [← toBitVec_inj] using h) +theorem Int16.toInt_div_of_ne_left (a b : Int16) (h : a ≠ minValue) : (a / b).toInt = a.toInt.tdiv b.toInt := by + rw [← toInt_toBitVec, Int16.toBitVec_div, BitVec.toInt_sdiv_of_ne_or_ne, toInt_toBitVec, toInt_toBitVec] + exact Or.inl (by simpa [← toBitVec_inj] using h) +theorem Int32.toInt_div_of_ne_left (a b : Int32) (h : a ≠ minValue) : (a / b).toInt = a.toInt.tdiv b.toInt := by + rw [← toInt_toBitVec, Int32.toBitVec_div, BitVec.toInt_sdiv_of_ne_or_ne, toInt_toBitVec, toInt_toBitVec] + exact Or.inl (by simpa [← toBitVec_inj] using h) +theorem Int64.toInt_div_of_ne_left (a b : Int64) (h : a ≠ minValue) : (a / b).toInt = a.toInt.tdiv b.toInt := by + rw [← toInt_toBitVec, Int64.toBitVec_div, BitVec.toInt_sdiv_of_ne_or_ne, toInt_toBitVec, toInt_toBitVec] + exact Or.inl (by simpa [← toBitVec_inj] using h) +theorem ISize.toInt_div_of_ne_left (a b : ISize) (h : a ≠ minValue) : (a / b).toInt = a.toInt.tdiv b.toInt := by + rw [← toInt_toBitVec, ISize.toBitVec_div, BitVec.toInt_sdiv_of_ne_or_ne, toInt_toBitVec, toInt_toBitVec] + exact Or.inl (by simpa [← toBitVec_inj, BitVec.intMin_eq_neg_two_pow] using h) + +theorem Int8.toInt_div_of_ne_right (a b : Int8) (h : b ≠ -1) : (a / b).toInt = a.toInt.tdiv b.toInt := by + rw [← toInt_toBitVec, Int8.toBitVec_div, BitVec.toInt_sdiv_of_ne_or_ne, toInt_toBitVec, toInt_toBitVec] + exact Or.inr (by simpa [← toBitVec_inj] using h) +theorem Int16.toInt_div_of_ne_right (a b : Int16) (h : b ≠ -1) : (a / b).toInt = a.toInt.tdiv b.toInt := by + rw [← toInt_toBitVec, Int16.toBitVec_div, BitVec.toInt_sdiv_of_ne_or_ne, toInt_toBitVec, toInt_toBitVec] + exact Or.inr (by simpa [← toBitVec_inj] using h) +theorem Int32.toInt_div_of_ne_right (a b : Int32) (h : b ≠ -1) : (a / b).toInt = a.toInt.tdiv b.toInt := by + rw [← toInt_toBitVec, Int32.toBitVec_div, BitVec.toInt_sdiv_of_ne_or_ne, toInt_toBitVec, toInt_toBitVec] + exact Or.inr (by simpa [← toBitVec_inj] using h) +theorem Int64.toInt_div_of_ne_right (a b : Int64) (h : b ≠ -1) : (a / b).toInt = a.toInt.tdiv b.toInt := by + rw [← toInt_toBitVec, Int64.toBitVec_div, BitVec.toInt_sdiv_of_ne_or_ne, toInt_toBitVec, toInt_toBitVec] + exact Or.inr (by simpa [← toBitVec_inj] using h) +theorem ISize.toInt_div_of_ne_right (a b : ISize) (h : b ≠ -1) : (a / b).toInt = a.toInt.tdiv b.toInt := by + rw [← toInt_toBitVec, ISize.toBitVec_div, BitVec.toInt_sdiv_of_ne_or_ne, toInt_toBitVec, toInt_toBitVec] + exact Or.inr (by simpa [← toBitVec_inj] using h) + +theorem Int8.toInt16_ne_minValue (a : Int8) : a.toInt16 ≠ Int16.minValue := + have := a.le_toInt; by simp [← Int16.toInt_inj, Int16.toInt_minValue]; omega +theorem Int8.toInt32_ne_minValue (a : Int8) : a.toInt32 ≠ Int32.minValue := + have := a.le_toInt; by simp [← Int32.toInt_inj, Int32.toInt_minValue]; omega +theorem Int8.toInt64_ne_minValue (a : Int8) : a.toInt64 ≠ Int64.minValue := + have := a.le_toInt; by simp [← Int64.toInt_inj, Int64.toInt_minValue]; omega +theorem Int8.toISize_ne_minValue (a : Int8) : a.toISize ≠ ISize.minValue := + have := a.le_toInt; have := ISize.toInt_minValue_le; by simp [← ISize.toInt_inj]; omega + +theorem Int16.toInt32_ne_minValue (a : Int16) : a.toInt32 ≠ Int32.minValue := + have := a.le_toInt; by simp [← Int32.toInt_inj, Int32.toInt_minValue]; omega +theorem Int16.toInt64_ne_minValue (a : Int16) : a.toInt64 ≠ Int64.minValue := + have := a.le_toInt; by simp [← Int64.toInt_inj, Int64.toInt_minValue]; omega +theorem Int16.toISize_ne_minValue (a : Int16) : a.toISize ≠ ISize.minValue := + have := a.le_toInt; have := ISize.toInt_minValue_le; by simp [← ISize.toInt_inj]; omega + +theorem Int32.toInt64_ne_minValue (a : Int32) : a.toInt64 ≠ Int64.minValue := + have := a.le_toInt; by simp [← Int64.toInt_inj, Int64.toInt_minValue]; omega +theorem Int32.toISize_ne_minValue (a : Int32) (ha : a ≠ minValue) : a.toISize ≠ ISize.minValue := by + have := a.le_toInt + have := ISize.toInt_minValue_le + simp [← ISize.toInt_inj, ← Int32.toInt_inj] at ⊢ ha; omega + +theorem ISize.toInt64_ne_minValue (a : ISize) (ha : a ≠ minValue) : a.toInt64 ≠ Int64.minValue := by + have := a.minValue_le_toInt + have : -2 ^ 63 ≤ minValue.toInt := minValue.le_toInt + simp [← Int64.toInt_inj, ← ISize.toInt_inj] at *; omega + +theorem Int8.toInt16_ne_neg_one (a : Int8) (ha : a ≠ -1) : a.toInt16 ≠ -1 := + ne_of_apply_ne Int16.toInt8 (by simpa using ha) +theorem Int8.toInt32_ne_neg_one (a : Int8) (ha : a ≠ -1) : a.toInt32 ≠ -1 := + ne_of_apply_ne Int32.toInt8 (by simpa using ha) +theorem Int8.toInt64_ne_neg_one (a : Int8) (ha : a ≠ -1) : a.toInt64 ≠ -1 := + ne_of_apply_ne Int64.toInt8 (by simpa using ha) +theorem Int8.toISize_ne_neg_one (a : Int8) (ha : a ≠ -1) : a.toISize ≠ -1 := + ne_of_apply_ne ISize.toInt8 (by simpa using ha) + +theorem Int16.toInt32_ne_neg_one (a : Int16) (ha : a ≠ -1) : a.toInt32 ≠ -1 := + ne_of_apply_ne Int32.toInt16 (by simpa using ha) +theorem Int16.toInt64_ne_neg_one (a : Int16) (ha : a ≠ -1) : a.toInt64 ≠ -1 := + ne_of_apply_ne Int64.toInt16 (by simpa using ha) +theorem Int16.toISize_ne_neg_one (a : Int16) (ha : a ≠ -1) : a.toISize ≠ -1 := + ne_of_apply_ne ISize.toInt16 (by simpa using ha) + +theorem Int32.toInt64_ne_neg_one (a : Int32) (ha : a ≠ -1) : a.toInt64 ≠ -1 := + ne_of_apply_ne Int64.toInt32 (by simpa using ha) +theorem Int32.toISize_ne_neg_one (a : Int32) (ha : a ≠ -1) : a.toISize ≠ -1 := + ne_of_apply_ne ISize.toInt32 (by simpa using ha) + +theorem ISize.toInt64_ne_neg_one (a : ISize) (ha : a ≠ -1) : a.toInt64 ≠ -1 := + ne_of_apply_ne Int64.toISize (by simpa using ha) + +theorem Int8.toInt16_div_of_ne_left (a b : Int8) (ha : a ≠ minValue) : (a / b).toInt16 = a.toInt16 / b.toInt16 := + Int16.toInt_inj.1 (by rw [toInt_toInt16, toInt_div_of_ne_left _ _ ha, + Int16.toInt_div_of_ne_left _ _ a.toInt16_ne_minValue, toInt_toInt16, toInt_toInt16]) +theorem Int8.toInt32_div_of_ne_left (a b : Int8) (ha : a ≠ minValue) : (a / b).toInt32 = a.toInt32 / b.toInt32 := + Int32.toInt_inj.1 (by rw [toInt_toInt32, toInt_div_of_ne_left _ _ ha, + Int32.toInt_div_of_ne_left _ _ a.toInt32_ne_minValue, toInt_toInt32, toInt_toInt32]) +theorem Int8.toInt64_div_of_ne_left (a b : Int8) (ha : a ≠ minValue) : (a / b).toInt64 = a.toInt64 / b.toInt64 := + Int64.toInt_inj.1 (by rw [toInt_toInt64, toInt_div_of_ne_left _ _ ha, + Int64.toInt_div_of_ne_left _ _ a.toInt64_ne_minValue, toInt_toInt64, toInt_toInt64]) +theorem Int8.toISize_div_of_ne_left (a b : Int8) (ha : a ≠ minValue) : (a / b).toISize = a.toISize / b.toISize := + ISize.toInt_inj.1 (by rw [toInt_toISize, toInt_div_of_ne_left _ _ ha, + ISize.toInt_div_of_ne_left _ _ a.toISize_ne_minValue, toInt_toISize, toInt_toISize]) + +theorem Int16.toInt32_div_of_ne_left (a b : Int16) (ha : a ≠ minValue) : (a / b).toInt32 = a.toInt32 / b.toInt32 := + Int32.toInt_inj.1 (by rw [toInt_toInt32, toInt_div_of_ne_left _ _ ha, + Int32.toInt_div_of_ne_left _ _ a.toInt32_ne_minValue, toInt_toInt32, toInt_toInt32]) +theorem Int16.toInt64_div_of_ne_left (a b : Int16) (ha : a ≠ minValue) : (a / b).toInt64 = a.toInt64 / b.toInt64 := + Int64.toInt_inj.1 (by rw [toInt_toInt64, toInt_div_of_ne_left _ _ ha, + Int64.toInt_div_of_ne_left _ _ a.toInt64_ne_minValue, toInt_toInt64, toInt_toInt64]) +theorem Int16.toISize_div_of_ne_left (a b : Int16) (ha : a ≠ minValue) : (a / b).toISize = a.toISize / b.toISize := + ISize.toInt_inj.1 (by rw [toInt_toISize, toInt_div_of_ne_left _ _ ha, + ISize.toInt_div_of_ne_left _ _ a.toISize_ne_minValue, toInt_toISize, toInt_toISize]) + +theorem Int32.toInt64_div_of_ne_left (a b : Int32) (ha : a ≠ minValue) : (a / b).toInt64 = a.toInt64 / b.toInt64 := + Int64.toInt_inj.1 (by rw [toInt_toInt64, toInt_div_of_ne_left _ _ ha, + Int64.toInt_div_of_ne_left _ _ a.toInt64_ne_minValue, toInt_toInt64, toInt_toInt64]) +theorem Int32.toISize_div_of_ne_left (a b : Int32) (ha : a ≠ minValue) : (a / b).toISize = a.toISize / b.toISize := + ISize.toInt_inj.1 (by rw [toInt_toISize, toInt_div_of_ne_left _ _ ha, + ISize.toInt_div_of_ne_left _ _ (a.toISize_ne_minValue ha), toInt_toISize, toInt_toISize]) + +theorem ISize.toInt64_div_of_ne_left (a b : ISize) (ha : a ≠ minValue) : (a / b).toInt64 = a.toInt64 / b.toInt64 := + Int64.toInt_inj.1 (by rw [toInt_toInt64, toInt_div_of_ne_left _ _ ha, + Int64.toInt_div_of_ne_left _ _ (a.toInt64_ne_minValue ha), toInt_toInt64, toInt_toInt64]) + +theorem Int8.toInt16_div_of_ne_right (a b : Int8) (hb : b ≠ -1) : (a / b).toInt16 = a.toInt16 / b.toInt16 := + Int16.toInt_inj.1 (by rw [toInt_toInt16, toInt_div_of_ne_right _ _ hb, + Int16.toInt_div_of_ne_right _ _ (b.toInt16_ne_neg_one hb), toInt_toInt16, toInt_toInt16]) +theorem Int8.toInt32_div_of_ne_right (a b : Int8) (hb : b ≠ -1) : (a / b).toInt32 = a.toInt32 / b.toInt32 := + Int32.toInt_inj.1 (by rw [toInt_toInt32, toInt_div_of_ne_right _ _ hb, + Int32.toInt_div_of_ne_right _ _ (b.toInt32_ne_neg_one hb), toInt_toInt32, toInt_toInt32]) +theorem Int8.toInt64_div_of_ne_right (a b : Int8) (hb : b ≠ -1) : (a / b).toInt64 = a.toInt64 / b.toInt64 := + Int64.toInt_inj.1 (by rw [toInt_toInt64, toInt_div_of_ne_right _ _ hb, + Int64.toInt_div_of_ne_right _ _ (b.toInt64_ne_neg_one hb), toInt_toInt64, toInt_toInt64]) +theorem Int8.toISize_div_of_ne_right (a b : Int8) (hb : b ≠ -1) : (a / b).toISize = a.toISize / b.toISize := + ISize.toInt_inj.1 (by rw [toInt_toISize, toInt_div_of_ne_right _ _ hb, + ISize.toInt_div_of_ne_right _ _ (b.toISize_ne_neg_one hb), toInt_toISize, toInt_toISize]) + +theorem Int16.toInt32_div_of_ne_right (a b : Int16) (hb : b ≠ -1) : (a / b).toInt32 = a.toInt32 / b.toInt32 := + Int32.toInt_inj.1 (by rw [toInt_toInt32, toInt_div_of_ne_right _ _ hb, + Int32.toInt_div_of_ne_right _ _ (b.toInt32_ne_neg_one hb), toInt_toInt32, toInt_toInt32]) +theorem Int16.toInt64_div_of_ne_right (a b : Int16) (hb : b ≠ -1) : (a / b).toInt64 = a.toInt64 / b.toInt64 := + Int64.toInt_inj.1 (by rw [toInt_toInt64, toInt_div_of_ne_right _ _ hb, + Int64.toInt_div_of_ne_right _ _ (b.toInt64_ne_neg_one hb), toInt_toInt64, toInt_toInt64]) +theorem Int16.toISize_div_of_ne_right (a b : Int16) (hb : b ≠ -1) : (a / b).toISize = a.toISize / b.toISize := + ISize.toInt_inj.1 (by rw [toInt_toISize, toInt_div_of_ne_right _ _ hb, + ISize.toInt_div_of_ne_right _ _ (b.toISize_ne_neg_one hb), toInt_toISize, toInt_toISize]) + +theorem Int32.toInt64_div_of_ne_right (a b : Int32) (hb : b ≠ -1) : (a / b).toInt64 = a.toInt64 / b.toInt64 := + Int64.toInt_inj.1 (by rw [toInt_toInt64, toInt_div_of_ne_right _ _ hb, + Int64.toInt_div_of_ne_right _ _ (b.toInt64_ne_neg_one hb), toInt_toInt64, toInt_toInt64]) +theorem Int32.toISize_div_of_ne_right (a b : Int32) (hb : b ≠ -1) : (a / b).toISize = a.toISize / b.toISize := + ISize.toInt_inj.1 (by rw [toInt_toISize, toInt_div_of_ne_right _ _ hb, + ISize.toInt_div_of_ne_right _ _ (b.toISize_ne_neg_one hb), toInt_toISize, toInt_toISize]) + +theorem ISize.toInt64_div_of_ne_right (a b : ISize) (hb : b ≠ -1) : (a / b).toInt64 = a.toInt64 / b.toInt64 := + Int64.toInt_inj.1 (by rw [toInt_toInt64, toInt_div_of_ne_right _ _ hb, + Int64.toInt_div_of_ne_right _ _ (b.toInt64_ne_neg_one hb), toInt_toInt64, toInt_toInt64]) + +@[simp] theorem Int8.minValue_div_neg_one : minValue / -1 = minValue := rfl +@[simp] theorem Int16.minValue_div_neg_one : minValue / -1 = minValue := rfl +@[simp] theorem Int32.minValue_div_neg_one : minValue / -1 = minValue := rfl +@[simp] theorem Int64.minValue_div_neg_one : minValue / -1 = minValue := rfl +@[simp] theorem ISize.minValue_div_neg_one : minValue / -1 = minValue := + ISize.toBitVec_inj.1 (by simpa [BitVec.intMin_eq_neg_two_pow] using BitVec.intMin_sdiv_neg_one) + +@[simp] theorem Int8.toInt_add (a b : Int8) : (a + b).toInt = (a.toInt + b.toInt).bmod (2 ^ 8) := by + rw [← toInt_toBitVec, Int8.toBitVec_add, BitVec.toInt_add, toInt_toBitVec, toInt_toBitVec] +@[simp] theorem Int16.toInt_add (a b : Int16) : (a + b).toInt = (a.toInt + b.toInt).bmod (2 ^ 16) := by + rw [← toInt_toBitVec, Int16.toBitVec_add, BitVec.toInt_add, toInt_toBitVec, toInt_toBitVec] +@[simp] theorem Int32.toInt_add (a b : Int32) : (a + b).toInt = (a.toInt + b.toInt).bmod (2 ^ 32) := by + rw [← toInt_toBitVec, Int32.toBitVec_add, BitVec.toInt_add, toInt_toBitVec, toInt_toBitVec] +@[simp] theorem Int64.toInt_add (a b : Int64) : (a + b).toInt = (a.toInt + b.toInt).bmod (2 ^ 64) := by + rw [← toInt_toBitVec, Int64.toBitVec_add, BitVec.toInt_add, toInt_toBitVec, toInt_toBitVec] +@[simp] theorem ISize.toInt_add (a b : ISize) : (a + b).toInt = (a.toInt + b.toInt).bmod (2 ^ System.Platform.numBits) := by + rw [← toInt_toBitVec, ISize.toBitVec_add, BitVec.toInt_add, toInt_toBitVec, toInt_toBitVec] + +@[simp] theorem Int16.toInt8_add (a b : Int16) : (a + b).toInt8 = a.toInt8 + b.toInt8 := + Int8.toBitVec_inj.1 (by simp [BitVec.signExtend_eq_setWidth_of_le, BitVec.setWidth_add]) + +@[simp] theorem Int32.toInt8_add (a b : Int32) : (a + b).toInt8 = a.toInt8 + b.toInt8 := + Int8.toBitVec_inj.1 (by simp [BitVec.signExtend_eq_setWidth_of_le, BitVec.setWidth_add]) +@[simp] theorem Int32.toInt16_add (a b : Int32) : (a + b).toInt16 = a.toInt16 + b.toInt16 := + Int16.toBitVec_inj.1 (by simp [BitVec.signExtend_eq_setWidth_of_le, BitVec.setWidth_add]) + +@[simp] theorem ISize.toInt8_add (a b : ISize) : (a + b).toInt8 = a.toInt8 + b.toInt8 := + Int8.toBitVec_inj.1 (by simp [BitVec.signExtend_eq_setWidth_of_le, BitVec.setWidth_add]) +@[simp] theorem ISize.toInt16_add (a b : ISize) : (a + b).toInt16 = a.toInt16 + b.toInt16 := + Int16.toBitVec_inj.1 (by simp [BitVec.signExtend_eq_setWidth_of_le, BitVec.setWidth_add]) +@[simp] theorem ISize.toInt32_add (a b : ISize) : (a + b).toInt32 = a.toInt32 + b.toInt32 := + Int32.toBitVec_inj.1 (by simp [BitVec.signExtend_eq_setWidth_of_le, BitVec.setWidth_add]) + +@[simp] theorem Int64.toInt8_add (a b : Int64) : (a + b).toInt8 = a.toInt8 + b.toInt8 := + Int8.toBitVec_inj.1 (by simp [BitVec.signExtend_eq_setWidth_of_le, BitVec.setWidth_add]) +@[simp] theorem Int64.toInt16_add (a b : Int64) : (a + b).toInt16 = a.toInt16 + b.toInt16 := + Int16.toBitVec_inj.1 (by simp [BitVec.signExtend_eq_setWidth_of_le, BitVec.setWidth_add]) +@[simp] theorem Int64.toInt32_add (a b : Int64) : (a + b).toInt32 = a.toInt32 + b.toInt32 := + Int32.toBitVec_inj.1 (by simp [BitVec.signExtend_eq_setWidth_of_le, BitVec.setWidth_add]) +@[simp] theorem Int64.toISize_add (a b : Int64) : (a + b).toISize = a.toISize + b.toISize := + ISize.toBitVec_inj.1 (by simp [BitVec.signExtend_eq_setWidth_of_le, BitVec.setWidth_add]) + +@[simp] theorem Int8.toInt_mul (a b : Int8) : (a * b).toInt = (a.toInt * b.toInt).bmod (2 ^ 8) := by + rw [← toInt_toBitVec, Int8.toBitVec_mul, BitVec.toInt_mul, toInt_toBitVec, toInt_toBitVec] +@[simp] theorem Int16.toInt_mul (a b : Int16) : (a * b).toInt = (a.toInt * b.toInt).bmod (2 ^ 16) := by + rw [← toInt_toBitVec, Int16.toBitVec_mul, BitVec.toInt_mul, toInt_toBitVec, toInt_toBitVec] +@[simp] theorem Int32.toInt_mul (a b : Int32) : (a * b).toInt = (a.toInt * b.toInt).bmod (2 ^ 32) := by + rw [← toInt_toBitVec, Int32.toBitVec_mul, BitVec.toInt_mul, toInt_toBitVec, toInt_toBitVec] +@[simp] theorem Int64.toInt_mul (a b : Int64) : (a * b).toInt = (a.toInt * b.toInt).bmod (2 ^ 64) := by + rw [← toInt_toBitVec, Int64.toBitVec_mul, BitVec.toInt_mul, toInt_toBitVec, toInt_toBitVec] +@[simp] theorem ISize.toInt_mul (a b : ISize) : (a * b).toInt = (a.toInt * b.toInt).bmod (2 ^ System.Platform.numBits) := by + rw [← toInt_toBitVec, ISize.toBitVec_mul, BitVec.toInt_mul, toInt_toBitVec, toInt_toBitVec] + +@[simp] theorem Int16.toInt8_mul (a b : Int16) : (a * b).toInt8 = a.toInt8 * b.toInt8 := + Int8.toBitVec_inj.1 (by simp [BitVec.signExtend_eq_setWidth_of_le, BitVec.setWidth_mul]) + +@[simp] theorem Int32.toInt8_mul (a b : Int32) : (a * b).toInt8 = a.toInt8 * b.toInt8 := + Int8.toBitVec_inj.1 (by simp [BitVec.signExtend_eq_setWidth_of_le, BitVec.setWidth_mul]) +@[simp] theorem Int32.toInt16_mul (a b : Int32) : (a * b).toInt16 = a.toInt16 * b.toInt16 := + Int16.toBitVec_inj.1 (by simp [BitVec.signExtend_eq_setWidth_of_le, BitVec.setWidth_mul]) + +@[simp] theorem ISize.toInt8_mul (a b : ISize) : (a * b).toInt8 = a.toInt8 * b.toInt8 := + Int8.toBitVec_inj.1 (by simp [BitVec.signExtend_eq_setWidth_of_le, BitVec.setWidth_mul]) +@[simp] theorem ISize.toInt16_mul (a b : ISize) : (a * b).toInt16 = a.toInt16 * b.toInt16 := + Int16.toBitVec_inj.1 (by simp [BitVec.signExtend_eq_setWidth_of_le, BitVec.setWidth_mul]) +@[simp] theorem ISize.toInt32_mul (a b : ISize) : (a * b).toInt32 = a.toInt32 * b.toInt32 := + Int32.toBitVec_inj.1 (by simp [BitVec.signExtend_eq_setWidth_of_le, BitVec.setWidth_mul]) + +@[simp] theorem Int64.toInt8_mul (a b : Int64) : (a * b).toInt8 = a.toInt8 * b.toInt8 := + Int8.toBitVec_inj.1 (by simp [BitVec.signExtend_eq_setWidth_of_le, BitVec.setWidth_mul]) +@[simp] theorem Int64.toInt16_mul (a b : Int64) : (a * b).toInt16 = a.toInt16 * b.toInt16 := + Int16.toBitVec_inj.1 (by simp [BitVec.signExtend_eq_setWidth_of_le, BitVec.setWidth_mul]) +@[simp] theorem Int64.toInt32_mul (a b : Int64) : (a * b).toInt32 = a.toInt32 * b.toInt32 := + Int32.toBitVec_inj.1 (by simp [BitVec.signExtend_eq_setWidth_of_le, BitVec.setWidth_mul]) +@[simp] theorem Int64.toISize_mul (a b : Int64) : (a * b).toISize = a.toISize * b.toISize := + ISize.toBitVec_inj.1 (by simp [BitVec.signExtend_eq_setWidth_of_le, BitVec.setWidth_mul]) + +theorem Int8.sub_eq_add_neg (a b : Int8) : a - b = a + -b := Int8.toBitVec.inj (by simp [BitVec.sub_toAdd]) +theorem Int16.sub_eq_add_neg (a b : Int16) : a - b = a + -b := Int16.toBitVec.inj (by simp [BitVec.sub_toAdd]) +theorem Int32.sub_eq_add_neg (a b : Int32) : a - b = a + -b := Int32.toBitVec.inj (by simp [BitVec.sub_toAdd]) +theorem Int64.sub_eq_add_neg (a b : Int64) : a - b = a + -b := Int64.toBitVec.inj (by simp [BitVec.sub_toAdd]) +theorem ISize.sub_eq_add_neg (a b : ISize) : a - b = a + -b := ISize.toBitVec.inj (by simp [BitVec.sub_toAdd]) + +@[simp] theorem Int8.toInt_sub (a b : Int8) : (a - b).toInt = (a.toInt - b.toInt).bmod (2 ^ 8) := by + simp [sub_eq_add_neg, Int.sub_eq_add_neg] +@[simp] theorem Int16.toInt_sub (a b : Int16) : (a - b).toInt = (a.toInt - b.toInt).bmod (2 ^ 16) := by + simp [sub_eq_add_neg, Int.sub_eq_add_neg] +@[simp] theorem Int32.toInt_sub (a b : Int32) : (a - b).toInt = (a.toInt - b.toInt).bmod (2 ^ 32) := by + simp [sub_eq_add_neg, Int.sub_eq_add_neg] +@[simp] theorem Int64.toInt_sub (a b : Int64) : (a - b).toInt = (a.toInt - b.toInt).bmod (2 ^ 64) := by + simp [sub_eq_add_neg, Int.sub_eq_add_neg] +@[simp] theorem ISize.toInt_sub (a b : ISize) : (a - b).toInt = (a.toInt - b.toInt).bmod (2 ^ System.Platform.numBits) := by + simp [sub_eq_add_neg, Int.sub_eq_add_neg, toInt_neg] + +@[simp] theorem Int16.toInt8_sub (a b : Int16) : (a - b).toInt8 = a.toInt8 - b.toInt8 := by + simp [sub_eq_add_neg, Int8.sub_eq_add_neg] + +@[simp] theorem Int32.toInt8_sub (a b : Int32) : (a - b).toInt8 = a.toInt8 - b.toInt8 := by + simp [sub_eq_add_neg, Int8.sub_eq_add_neg] +@[simp] theorem Int32.toInt16_sub (a b : Int32) : (a - b).toInt16 = a.toInt16 - b.toInt16 := by + simp [sub_eq_add_neg, Int16.sub_eq_add_neg] + +@[simp] theorem ISize.toInt8_sub (a b : ISize) : (a - b).toInt8 = a.toInt8 - b.toInt8 := by + simp [sub_eq_add_neg, Int8.sub_eq_add_neg] +@[simp] theorem ISize.toInt16_sub (a b : ISize) : (a - b).toInt16 = a.toInt16 - b.toInt16 := by + simp [sub_eq_add_neg, Int16.sub_eq_add_neg] +@[simp] theorem ISize.toInt32_sub (a b : ISize) : (a - b).toInt32 = a.toInt32 - b.toInt32 := by + simp [sub_eq_add_neg, Int32.sub_eq_add_neg] + +@[simp] theorem Int64.toInt8_sub (a b : Int64) : (a - b).toInt8 = a.toInt8 - b.toInt8 := by + simp [sub_eq_add_neg, Int8.sub_eq_add_neg] +@[simp] theorem Int64.toInt16_sub (a b : Int64) : (a - b).toInt16 = a.toInt16 - b.toInt16 := by + simp [sub_eq_add_neg, Int16.sub_eq_add_neg] +@[simp] theorem Int64.toInt32_sub (a b : Int64) : (a - b).toInt32 = a.toInt32 - b.toInt32 := by + simp [sub_eq_add_neg, Int32.sub_eq_add_neg] +@[simp] theorem Int64.toISize_sub (a b : Int64) : (a - b).toISize = a.toISize - b.toISize := by + simp [sub_eq_add_neg, ISize.sub_eq_add_neg] + +@[simp] theorem Int8.toInt16_lt {a b : Int8} : a.toInt16 < b.toInt16 ↔ a < b := by + simp [lt_iff_toInt_lt, Int16.lt_iff_toInt_lt] +@[simp] theorem Int8.toInt32_lt {a b : Int8} : a.toInt32 < b.toInt32 ↔ a < b := by + simp [lt_iff_toInt_lt, Int32.lt_iff_toInt_lt] +@[simp] theorem Int8.toInt64_lt {a b : Int8} : a.toInt64 < b.toInt64 ↔ a < b := by + simp [lt_iff_toInt_lt, Int64.lt_iff_toInt_lt] +@[simp] theorem Int8.toISize_lt {a b : Int8} : a.toISize < b.toISize ↔ a < b := by + simp [lt_iff_toInt_lt, ISize.lt_iff_toInt_lt] + +@[simp] theorem Int16.toInt32_lt {a b : Int16} : a.toInt32 < b.toInt32 ↔ a < b := by + simp [lt_iff_toInt_lt, Int32.lt_iff_toInt_lt] +@[simp] theorem Int16.toInt64_lt {a b : Int16} : a.toInt64 < b.toInt64 ↔ a < b := by + simp [lt_iff_toInt_lt, Int64.lt_iff_toInt_lt] +@[simp] theorem Int16.toISize_lt {a b : Int16} : a.toISize < b.toISize ↔ a < b := by + simp [lt_iff_toInt_lt, ISize.lt_iff_toInt_lt] + +@[simp] theorem Int32.toInt64_lt {a b : Int32} : a.toInt64 < b.toInt64 ↔ a < b := by + simp [lt_iff_toInt_lt, Int64.lt_iff_toInt_lt] +@[simp] theorem Int32.toISize_lt {a b : Int32} : a.toISize < b.toISize ↔ a < b := by + simp [lt_iff_toInt_lt, ISize.lt_iff_toInt_lt] + +@[simp] theorem ISize.toInt64_lt {a b : ISize} : a.toInt64 < b.toInt64 ↔ a < b := by + simp [lt_iff_toInt_lt, Int64.lt_iff_toInt_lt] + +@[simp] theorem Int8.toInt16_le {a b : Int8} : a.toInt16 ≤ b.toInt16 ↔ a ≤ b := by + simp [le_iff_toInt_le, Int16.le_iff_toInt_le] +@[simp] theorem Int8.toInt32_le {a b : Int8} : a.toInt32 ≤ b.toInt32 ↔ a ≤ b := by + simp [le_iff_toInt_le, Int32.le_iff_toInt_le] +@[simp] theorem Int8.toInt64_le {a b : Int8} : a.toInt64 ≤ b.toInt64 ↔ a ≤ b := by + simp [le_iff_toInt_le, Int64.le_iff_toInt_le] +@[simp] theorem Int8.toISize_le {a b : Int8} : a.toISize ≤ b.toISize ↔ a ≤ b := by + simp [le_iff_toInt_le, ISize.le_iff_toInt_le] + +@[simp] theorem Int16.toInt32_le {a b : Int16} : a.toInt32 ≤ b.toInt32 ↔ a ≤ b := by + simp [le_iff_toInt_le, Int32.le_iff_toInt_le] +@[simp] theorem Int16.toInt64_le {a b : Int16} : a.toInt64 ≤ b.toInt64 ↔ a ≤ b := by + simp [le_iff_toInt_le, Int64.le_iff_toInt_le] +@[simp] theorem Int16.toISize_le {a b : Int16} : a.toISize ≤ b.toISize ↔ a ≤ b := by + simp [le_iff_toInt_le, ISize.le_iff_toInt_le] + +@[simp] theorem Int32.toInt64_le {a b : Int32} : a.toInt64 ≤ b.toInt64 ↔ a ≤ b := by + simp [le_iff_toInt_le, Int64.le_iff_toInt_le] +@[simp] theorem Int32.toISize_le {a b : Int32} : a.toISize ≤ b.toISize ↔ a ≤ b := by + simp [le_iff_toInt_le, ISize.le_iff_toInt_le] + +@[simp] theorem ISize.toInt64_le {a b : ISize} : a.toInt64 ≤ b.toInt64 ↔ a ≤ b := by + simp [le_iff_toInt_le, Int64.le_iff_toInt_le] + +@[simp] theorem Int8.ofBitVec_neg (a : BitVec 8) : Int8.ofBitVec (-a) = -Int8.ofBitVec a := rfl +@[simp] theorem Int16.ofBitVec_neg (a : BitVec 16) : Int16.ofBitVec (-a) = -Int16.ofBitVec a := rfl +@[simp] theorem Int32.ofBitVec_neg (a : BitVec 32) : Int32.ofBitVec (-a) = -Int32.ofBitVec a := rfl +@[simp] theorem Int64.ofBitVec_neg (a : BitVec 64) : Int64.ofBitVec (-a) = -Int64.ofBitVec a := rfl +@[simp] theorem ISize.ofBitVec_neg (a : BitVec System.Platform.numBits) : ISize.ofBitVec (-a) = -ISize.ofBitVec a := rfl + +@[simp] theorem Int8.ofInt_neg (a : Int) : Int8.ofInt (-a) = -Int8.ofInt a := Int8.toInt_inj.1 (by simp) +@[simp] theorem Int16.ofInt_neg (a : Int) : Int16.ofInt (-a) = -Int16.ofInt a := Int16.toInt_inj.1 (by simp) +@[simp] theorem Int32.ofInt_neg (a : Int) : Int32.ofInt (-a) = -Int32.ofInt a := Int32.toInt_inj.1 (by simp) +@[simp] theorem Int64.ofInt_neg (a : Int) : Int64.ofInt (-a) = -Int64.ofInt a := Int64.toInt_inj.1 (by simp) +@[simp] theorem ISize.ofInt_neg (a : Int) : ISize.ofInt (-a) = -ISize.ofInt a := + ISize.toInt_inj.1 (by simp [ISize.toInt_ofInt, toInt_neg]) + +theorem Int8.ofInt_eq_iff_bmod_eq_toInt (a : Int) (b : Int8) : Int8.ofInt a = b ↔ a.bmod (2 ^ 8) = b.toInt := by + simp [← Int8.toInt_inj] +theorem Int16.ofInt_eq_iff_bmod_eq_toInt (a : Int) (b : Int16) : Int16.ofInt a = b ↔ a.bmod (2 ^ 16) = b.toInt := by + simp [← Int16.toInt_inj] +theorem Int32.ofInt_eq_iff_bmod_eq_toInt (a : Int) (b : Int32) : Int32.ofInt a = b ↔ a.bmod (2 ^ 32) = b.toInt := by + simp [← Int32.toInt_inj] +theorem Int64.ofInt_eq_iff_bmod_eq_toInt (a : Int) (b : Int64) : Int64.ofInt a = b ↔ a.bmod (2 ^ 64) = b.toInt := by + simp [← Int64.toInt_inj] +theorem ISize.ofInt_eq_iff_bmod_eq_toInt (a : Int) (b : ISize) : ISize.ofInt a = b ↔ a.bmod (2 ^ System.Platform.numBits) = b.toInt := by + simp [← ISize.toInt_inj, ISize.toInt_ofInt] + +@[simp] theorem Int8.ofBitVec_add (a b : BitVec 8) : Int8.ofBitVec (a + b) = Int8.ofBitVec a + Int8.ofBitVec b := rfl +@[simp] theorem Int16.ofBitVec_add (a b : BitVec 16) : Int16.ofBitVec (a + b) = Int16.ofBitVec a + Int16.ofBitVec b := rfl +@[simp] theorem Int32.ofBitVec_add (a b : BitVec 32) : Int32.ofBitVec (a + b) = Int32.ofBitVec a + Int32.ofBitVec b := rfl +@[simp] theorem Int64.ofBitVec_add (a b : BitVec 64) : Int64.ofBitVec (a + b) = Int64.ofBitVec a + Int64.ofBitVec b := rfl +@[simp] theorem ISize.ofBitVec_add (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a + b) = ISize.ofBitVec a + ISize.ofBitVec b := rfl + +@[simp] theorem Int8.ofInt_add (a b : Int) : Int8.ofInt (a + b) = Int8.ofInt a + Int8.ofInt b := by + simp [Int8.ofInt_eq_iff_bmod_eq_toInt] +@[simp] theorem Int16.ofInt_add (a b : Int) : Int16.ofInt (a + b) = Int16.ofInt a + Int16.ofInt b := by + simp [Int16.ofInt_eq_iff_bmod_eq_toInt] +@[simp] theorem Int32.ofInt_add (a b : Int) : Int32.ofInt (a + b) = Int32.ofInt a + Int32.ofInt b := by + simp [Int32.ofInt_eq_iff_bmod_eq_toInt] +@[simp] theorem Int64.ofInt_add (a b : Int) : Int64.ofInt (a + b) = Int64.ofInt a + Int64.ofInt b := by + simp [Int64.ofInt_eq_iff_bmod_eq_toInt] +@[simp] theorem ISize.ofInt_add (a b : Int) : ISize.ofInt (a + b) = ISize.ofInt a + ISize.ofInt b := by + simp [ISize.ofInt_eq_iff_bmod_eq_toInt, ISize.toInt_ofInt] + +@[simp] theorem Int8.ofNat_add (a b : Nat) : Int8.ofNat (a + b) = Int8.ofNat a + Int8.ofNat b := by + simp [← Int8.ofInt_eq_ofNat] +@[simp] theorem Int16.ofNat_add (a b : Nat) : Int16.ofNat (a + b) = Int16.ofNat a + Int16.ofNat b := by + simp [← Int16.ofInt_eq_ofNat] +@[simp] theorem Int32.ofNat_add (a b : Nat) : Int32.ofNat (a + b) = Int32.ofNat a + Int32.ofNat b := by + simp [← Int32.ofInt_eq_ofNat] +@[simp] theorem Int64.ofNat_add (a b : Nat) : Int64.ofNat (a + b) = Int64.ofNat a + Int64.ofNat b := by + simp [← Int64.ofInt_eq_ofNat] +@[simp] theorem ISize.ofNat_add (a b : Nat) : ISize.ofNat (a + b) = ISize.ofNat a + ISize.ofNat b := by + simp [← ISize.ofInt_eq_ofNat] + +theorem Int8.ofIntLE_add {a b : Int} {hab₁ hab₂} : Int8.ofIntLE (a + b) hab₁ hab₂ = Int8.ofInt a + Int8.ofInt b := by + simp [Int8.ofIntLE_eq_ofInt] +theorem Int16.ofIntLE_add {a b : Int} {hab₁ hab₂} : Int16.ofIntLE (a + b) hab₁ hab₂ = Int16.ofInt a + Int16.ofInt b := by + simp [Int16.ofIntLE_eq_ofInt] +theorem Int32.ofIntLE_add {a b : Int} {hab₁ hab₂} : Int32.ofIntLE (a + b) hab₁ hab₂ = Int32.ofInt a + Int32.ofInt b := by + simp [Int32.ofIntLE_eq_ofInt] +theorem Int64.ofIntLE_add {a b : Int} {hab₁ hab₂} : Int64.ofIntLE (a + b) hab₁ hab₂ = Int64.ofInt a + Int64.ofInt b := by + simp [Int64.ofIntLE_eq_ofInt] +theorem ISize.ofIntLE_add {a b : Int} {hab₁ hab₂} : ISize.ofIntLE (a + b) hab₁ hab₂ = ISize.ofInt a + ISize.ofInt b := by + simp [ISize.ofIntLE_eq_ofInt] + +@[simp] theorem Int8.ofBitVec_sub (a b : BitVec 8) : Int8.ofBitVec (a - b) = Int8.ofBitVec a - Int8.ofBitVec b := rfl +@[simp] theorem Int16.ofBitVec_sub (a b : BitVec 16) : Int16.ofBitVec (a - b) = Int16.ofBitVec a - Int16.ofBitVec b := rfl +@[simp] theorem Int32.ofBitVec_sub (a b : BitVec 32) : Int32.ofBitVec (a - b) = Int32.ofBitVec a - Int32.ofBitVec b := rfl +@[simp] theorem Int64.ofBitVec_sub (a b : BitVec 64) : Int64.ofBitVec (a - b) = Int64.ofBitVec a - Int64.ofBitVec b := rfl +@[simp] theorem ISize.ofBitVec_sub (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a - b) = ISize.ofBitVec a - ISize.ofBitVec b := rfl + +@[simp] theorem Int8.ofInt_sub (a b : Int) : Int8.ofInt (a - b) = Int8.ofInt a - Int8.ofInt b := by + simp [Int8.ofInt_eq_iff_bmod_eq_toInt] +@[simp] theorem Int16.ofInt_sub (a b : Int) : Int16.ofInt (a - b) = Int16.ofInt a - Int16.ofInt b := by + simp [Int16.ofInt_eq_iff_bmod_eq_toInt] +@[simp] theorem Int32.ofInt_sub (a b : Int) : Int32.ofInt (a - b) = Int32.ofInt a - Int32.ofInt b := by + simp [Int32.ofInt_eq_iff_bmod_eq_toInt] +@[simp] theorem Int64.ofInt_sub (a b : Int) : Int64.ofInt (a - b) = Int64.ofInt a - Int64.ofInt b := by + simp [Int64.ofInt_eq_iff_bmod_eq_toInt] +@[simp] theorem ISize.ofInt_sub (a b : Int) : ISize.ofInt (a - b) = ISize.ofInt a - ISize.ofInt b := by + simp [ISize.ofInt_eq_iff_bmod_eq_toInt, ISize.toInt_ofInt] + +@[simp] theorem Int8.ofNat_sub (a b : Nat) (hab : b ≤ a) : Int8.ofNat (a - b) = Int8.ofNat a - Int8.ofNat b := by + simp [← Int8.ofInt_eq_ofNat, Int.ofNat_sub hab] +@[simp] theorem Int16.ofNat_sub (a b : Nat) (hab : b ≤ a) : Int16.ofNat (a - b) = Int16.ofNat a - Int16.ofNat b := by + simp [← Int16.ofInt_eq_ofNat, Int.ofNat_sub hab] +@[simp] theorem Int32.ofNat_sub (a b : Nat) (hab : b ≤ a) : Int32.ofNat (a - b) = Int32.ofNat a - Int32.ofNat b := by + simp [← Int32.ofInt_eq_ofNat, Int.ofNat_sub hab] +@[simp] theorem Int64.ofNat_sub (a b : Nat) (hab : b ≤ a) : Int64.ofNat (a - b) = Int64.ofNat a - Int64.ofNat b := by + simp [← Int64.ofInt_eq_ofNat, Int.ofNat_sub hab] +@[simp] theorem ISize.ofNat_sub (a b : Nat) (hab : b ≤ a) : ISize.ofNat (a - b) = ISize.ofNat a - ISize.ofNat b := by + simp [← ISize.ofInt_eq_ofNat, Int.ofNat_sub hab] + +theorem Int8.ofIntLE_sub {a b : Int} {hab₁ hab₂} : Int8.ofIntLE (a - b) hab₁ hab₂ = Int8.ofInt a - Int8.ofInt b := by + simp [Int8.ofIntLE_eq_ofInt] +theorem Int16.ofIntLE_sub {a b : Int} {hab₁ hab₂} : Int16.ofIntLE (a - b) hab₁ hab₂ = Int16.ofInt a - Int16.ofInt b := by + simp [Int16.ofIntLE_eq_ofInt] +theorem Int32.ofIntLE_sub {a b : Int} {hab₁ hab₂} : Int32.ofIntLE (a - b) hab₁ hab₂ = Int32.ofInt a - Int32.ofInt b := by + simp [Int32.ofIntLE_eq_ofInt] +theorem Int64.ofIntLE_sub {a b : Int} {hab₁ hab₂} : Int64.ofIntLE (a - b) hab₁ hab₂ = Int64.ofInt a - Int64.ofInt b := by + simp [Int64.ofIntLE_eq_ofInt] +theorem ISize.ofIntLE_sub {a b : Int} {hab₁ hab₂} : ISize.ofIntLE (a - b) hab₁ hab₂ = ISize.ofInt a - ISize.ofInt b := by + simp [ISize.ofIntLE_eq_ofInt] + +@[simp] theorem Int8.ofBitVec_mul (a b : BitVec 8) : Int8.ofBitVec (a * b) = Int8.ofBitVec a * Int8.ofBitVec b := rfl +@[simp] theorem Int16.ofBitVec_mul (a b : BitVec 16) : Int16.ofBitVec (a * b) = Int16.ofBitVec a * Int16.ofBitVec b := rfl +@[simp] theorem Int32.ofBitVec_mul (a b : BitVec 32) : Int32.ofBitVec (a * b) = Int32.ofBitVec a * Int32.ofBitVec b := rfl +@[simp] theorem Int64.ofBitVec_mul (a b : BitVec 64) : Int64.ofBitVec (a * b) = Int64.ofBitVec a * Int64.ofBitVec b := rfl +@[simp] theorem ISize.ofBitVec_mul (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a * b) = ISize.ofBitVec a * ISize.ofBitVec b := rfl + +@[simp] theorem Int8.ofInt_mul (a b : Int) : Int8.ofInt (a * b) = Int8.ofInt a * Int8.ofInt b := by + simp [Int8.ofInt_eq_iff_bmod_eq_toInt] +@[simp] theorem Int16.ofInt_mul (a b : Int) : Int16.ofInt (a * b) = Int16.ofInt a * Int16.ofInt b := by + simp [Int16.ofInt_eq_iff_bmod_eq_toInt] +@[simp] theorem Int32.ofInt_mul (a b : Int) : Int32.ofInt (a * b) = Int32.ofInt a * Int32.ofInt b := by + simp [Int32.ofInt_eq_iff_bmod_eq_toInt] +@[simp] theorem Int64.ofInt_mul (a b : Int) : Int64.ofInt (a * b) = Int64.ofInt a * Int64.ofInt b := by + simp [Int64.ofInt_eq_iff_bmod_eq_toInt] +@[simp] theorem ISize.ofInt_mul (a b : Int) : ISize.ofInt (a * b) = ISize.ofInt a * ISize.ofInt b := by + simp [ISize.ofInt_eq_iff_bmod_eq_toInt, ISize.toInt_ofInt] + +@[simp] theorem Int8.ofNat_mul (a b : Nat) : Int8.ofNat (a * b) = Int8.ofNat a * Int8.ofNat b := by + simp [← Int8.ofInt_eq_ofNat] +@[simp] theorem Int16.ofNat_mul (a b : Nat) : Int16.ofNat (a * b) = Int16.ofNat a * Int16.ofNat b := by + simp [← Int16.ofInt_eq_ofNat] +@[simp] theorem Int32.ofNat_mul (a b : Nat) : Int32.ofNat (a * b) = Int32.ofNat a * Int32.ofNat b := by + simp [← Int32.ofInt_eq_ofNat] +@[simp] theorem Int64.ofNat_mul (a b : Nat) : Int64.ofNat (a * b) = Int64.ofNat a * Int64.ofNat b := by + simp [← Int64.ofInt_eq_ofNat] +@[simp] theorem ISize.ofNat_mul (a b : Nat) : ISize.ofNat (a * b) = ISize.ofNat a * ISize.ofNat b := by + simp [← ISize.ofInt_eq_ofNat] + +theorem Int8.ofIntLE_mul {a b : Int} {hab₁ hab₂} : Int8.ofIntLE (a * b) hab₁ hab₂ = Int8.ofInt a * Int8.ofInt b := by + simp [Int8.ofIntLE_eq_ofInt] +theorem Int16.ofIntLE_mul {a b : Int} {hab₁ hab₂} : Int16.ofIntLE (a * b) hab₁ hab₂ = Int16.ofInt a * Int16.ofInt b := by + simp [Int16.ofIntLE_eq_ofInt] +theorem Int32.ofIntLE_mul {a b : Int} {hab₁ hab₂} : Int32.ofIntLE (a * b) hab₁ hab₂ = Int32.ofInt a * Int32.ofInt b := by + simp [Int32.ofIntLE_eq_ofInt] +theorem Int64.ofIntLE_mul {a b : Int} {hab₁ hab₂} : Int64.ofIntLE (a * b) hab₁ hab₂ = Int64.ofInt a * Int64.ofInt b := by + simp [Int64.ofIntLE_eq_ofInt] +theorem ISize.ofIntLE_mul {a b : Int} {hab₁ hab₂} : ISize.ofIntLE (a * b) hab₁ hab₂ = ISize.ofInt a * ISize.ofInt b := by + simp [ISize.ofIntLE_eq_ofInt] + +theorem Int8.toInt_minValue_lt_zero : minValue.toInt < 0 := by decide +theorem Int16.toInt_minValue_lt_zero : minValue.toInt < 0 := by decide +theorem Int32.toInt_minValue_lt_zero : minValue.toInt < 0 := by decide +theorem Int64.toInt_minValue_lt_zero : minValue.toInt < 0 := by decide +theorem ISize.toInt_minValue_lt_zero : minValue.toInt < 0 := by + rw [toInt_minValue, Int.neg_lt_zero_iff] + exact Int.pow_pos (by decide) + +theorem Int8.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ 7 := rfl +theorem Int16.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ 15 := rfl +theorem Int32.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ 31 := rfl +theorem Int64.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ 63 := rfl +theorem ISize.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ (System.Platform.numBits - 1) := by + rw [toInt_maxValue, Int.sub_add_cancel] + +@[simp] theorem Int8.ofBitVec_sdiv (a b : BitVec 8) : Int8.ofBitVec (a.sdiv b) = Int8.ofBitVec a / Int8.ofBitVec b := rfl +@[simp] theorem Int16.ofBitVec_sdiv (a b : BitVec 16) : Int16.ofBitVec (a.sdiv b) = Int16.ofBitVec a / Int16.ofBitVec b := rfl +@[simp] theorem Int32.ofBitVec_sdiv (a b : BitVec 32) : Int32.ofBitVec (a.sdiv b) = Int32.ofBitVec a / Int32.ofBitVec b := rfl +@[simp] theorem Int64.ofBitVec_sdiv (a b : BitVec 64) : Int64.ofBitVec (a.sdiv b) = Int64.ofBitVec a / Int64.ofBitVec b := rfl +@[simp] theorem ISize.ofBitVec_sdiv (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a.sdiv b) = ISize.ofBitVec a / ISize.ofBitVec b := rfl + +theorem Int8.ofInt_tdiv {a b : Int} (ha₁ : minValue.toInt ≤ a) (ha₂ : a ≤ maxValue.toInt) + (hb₁ : minValue.toInt ≤ b) (hb₂ : b ≤ maxValue.toInt) : Int8.ofInt (a.tdiv b) = Int8.ofInt a / Int8.ofInt b := by + rw [Int8.ofInt_eq_iff_bmod_eq_toInt, toInt_div, toInt_ofInt, toInt_ofInt, + Int.bmod_eq_self_of_le (n := a), Int.bmod_eq_self_of_le (n := b)] + · exact hb₁ + · exact Int.lt_of_le_sub_one hb₂ + · exact ha₁ + · exact Int.lt_of_le_sub_one ha₂ +theorem Int16.ofInt_tdiv {a b : Int} (ha₁ : minValue.toInt ≤ a) (ha₂ : a ≤ maxValue.toInt) + (hb₁ : minValue.toInt ≤ b) (hb₂ : b ≤ maxValue.toInt) : Int16.ofInt (a.tdiv b) = Int16.ofInt a / Int16.ofInt b := by + rw [Int16.ofInt_eq_iff_bmod_eq_toInt, toInt_div, toInt_ofInt, toInt_ofInt, + Int.bmod_eq_self_of_le (n := a), Int.bmod_eq_self_of_le (n := b)] + · exact hb₁ + · exact Int.lt_of_le_sub_one hb₂ + · exact ha₁ + · exact Int.lt_of_le_sub_one ha₂ +theorem Int32.ofInt_tdiv {a b : Int} (ha₁ : minValue.toInt ≤ a) (ha₂ : a ≤ maxValue.toInt) + (hb₁ : minValue.toInt ≤ b) (hb₂ : b ≤ maxValue.toInt) : Int32.ofInt (a.tdiv b) = Int32.ofInt a / Int32.ofInt b := by + rw [Int32.ofInt_eq_iff_bmod_eq_toInt, toInt_div, toInt_ofInt, toInt_ofInt, + Int.bmod_eq_self_of_le (n := a), Int.bmod_eq_self_of_le (n := b)] + · exact hb₁ + · exact Int.lt_of_le_sub_one hb₂ + · exact ha₁ + · exact Int.lt_of_le_sub_one ha₂ +theorem Int64.ofInt_tdiv {a b : Int} (ha₁ : minValue.toInt ≤ a) (ha₂ : a ≤ maxValue.toInt) + (hb₁ : minValue.toInt ≤ b) (hb₂ : b ≤ maxValue.toInt) : Int64.ofInt (a.tdiv b) = Int64.ofInt a / Int64.ofInt b := by + rw [Int64.ofInt_eq_iff_bmod_eq_toInt, toInt_div, toInt_ofInt, toInt_ofInt, + Int.bmod_eq_self_of_le (n := a), Int.bmod_eq_self_of_le (n := b)] + · exact hb₁ + · exact Int.lt_of_le_sub_one hb₂ + · exact ha₁ + · exact Int.lt_of_le_sub_one ha₂ +theorem ISize.ofInt_tdiv {a b : Int} (ha₁ : minValue.toInt ≤ a) (ha₂ : a ≤ maxValue.toInt) + (hb₁ : minValue.toInt ≤ b) (hb₂ : b ≤ maxValue.toInt) : ISize.ofInt (a.tdiv b) = ISize.ofInt a / ISize.ofInt b := by + rw [ISize.ofInt_eq_iff_bmod_eq_toInt, toInt_div, toInt_ofInt, toInt_ofInt, + Int.bmod_eq_self_of_le (n := a), Int.bmod_eq_self_of_le (n := b)] + · exact le_of_eq_of_le (by cases System.Platform.numBits_eq <;> simp_all [size, toInt_ofInt, toInt_neg]) hb₁ + · refine Int.lt_of_le_sub_one (le_of_le_of_eq hb₂ ?_) + cases System.Platform.numBits_eq <;> simp_all [size, toInt_ofInt] + · exact le_of_eq_of_le (by cases System.Platform.numBits_eq <;> simp_all [size, toInt_ofInt, toInt_neg]) ha₁ + · refine Int.lt_of_le_sub_one (le_of_le_of_eq ha₂ ?_) + cases System.Platform.numBits_eq <;> simp_all [size, toInt_ofInt] + +theorem Int8.ofInt_eq_ofIntLE_div {a b : Int} (ha₁ ha₂ hb₁ hb₂) : + Int8.ofInt (a.tdiv b) = Int8.ofIntLE a ha₁ ha₂ / Int8.ofIntLE b hb₁ hb₂ := by + rw [ofIntLE_eq_ofInt, ofIntLE_eq_ofInt, ofInt_tdiv ha₁ ha₂ hb₁ hb₂] +theorem Int16.ofInt_eq_ofIntLE_div {a b : Int} (ha₁ ha₂ hb₁ hb₂) : + Int16.ofInt (a.tdiv b) = Int16.ofIntLE a ha₁ ha₂ / Int16.ofIntLE b hb₁ hb₂ := by + rw [ofIntLE_eq_ofInt, ofIntLE_eq_ofInt, ofInt_tdiv ha₁ ha₂ hb₁ hb₂] +theorem Int32.ofInt_eq_ofIntLE_div {a b : Int} (ha₁ ha₂ hb₁ hb₂) : + Int32.ofInt (a.tdiv b) = Int32.ofIntLE a ha₁ ha₂ / Int32.ofIntLE b hb₁ hb₂ := by + rw [ofIntLE_eq_ofInt, ofIntLE_eq_ofInt, ofInt_tdiv ha₁ ha₂ hb₁ hb₂] +theorem Int64.ofInt_eq_ofIntLE_div {a b : Int} (ha₁ ha₂ hb₁ hb₂) : + Int64.ofInt (a.tdiv b) = Int64.ofIntLE a ha₁ ha₂ / Int64.ofIntLE b hb₁ hb₂ := by + rw [ofIntLE_eq_ofInt, ofIntLE_eq_ofInt, ofInt_tdiv ha₁ ha₂ hb₁ hb₂] +theorem ISize.ofInt_eq_ofIntLE_div {a b : Int} (ha₁ ha₂ hb₁ hb₂) : + ISize.ofInt (a.tdiv b) = ISize.ofIntLE a ha₁ ha₂ / ISize.ofIntLE b hb₁ hb₂ := by + rw [ofIntLE_eq_ofInt, ofIntLE_eq_ofInt, ofInt_tdiv ha₁ ha₂ hb₁ hb₂] + +theorem Int8.ofNat_div {a b : Nat} (ha : a < 2 ^ 7) (hb : b < 2 ^ 7) : + Int8.ofNat (a / b) = Int8.ofNat a / Int8.ofNat b := by + rw [← ofInt_eq_ofNat, ← ofInt_eq_ofNat, ← ofInt_eq_ofNat, Int.ofNat_tdiv, + ofInt_tdiv (by simp) _ (by simp)] + · exact Int.le_of_lt_add_one (Int.ofNat_le.2 hb) + · exact Int.le_of_lt_add_one (Int.ofNat_le.2 ha) +theorem Int16.ofNat_div {a b : Nat} (ha : a < 2 ^ 15) (hb : b < 2 ^ 15) : + Int16.ofNat (a / b) = Int16.ofNat a / Int16.ofNat b := by + rw [← ofInt_eq_ofNat, ← ofInt_eq_ofNat, ← ofInt_eq_ofNat, Int.ofNat_tdiv, + ofInt_tdiv (by simp) _ (by simp)] + · exact Int.le_of_lt_add_one (Int.ofNat_le.2 hb) + · exact Int.le_of_lt_add_one (Int.ofNat_le.2 ha) +theorem Int32.ofNat_div {a b : Nat} (ha : a < 2 ^ 31) (hb : b < 2 ^ 31) : + Int32.ofNat (a / b) = Int32.ofNat a / Int32.ofNat b := by + rw [← ofInt_eq_ofNat, ← ofInt_eq_ofNat, ← ofInt_eq_ofNat, Int.ofNat_tdiv, + ofInt_tdiv (by simp) _ (by simp)] + · exact Int.le_of_lt_add_one (Int.ofNat_le.2 hb) + · exact Int.le_of_lt_add_one (Int.ofNat_le.2 ha) +theorem Int64.ofNat_div {a b : Nat} (ha : a < 2 ^ 63) (hb : b < 2 ^ 63) : + Int64.ofNat (a / b) = Int64.ofNat a / Int64.ofNat b := by + rw [← ofInt_eq_ofNat, ← ofInt_eq_ofNat, ← ofInt_eq_ofNat, Int.ofNat_tdiv, + ofInt_tdiv (by simp) _ (by simp)] + · exact Int.le_of_lt_add_one (Int.ofNat_le.2 hb) + · exact Int.le_of_lt_add_one (Int.ofNat_le.2 ha) +theorem ISize.ofNat_div {a b : Nat} (ha : a < 2 ^ (System.Platform.numBits - 1)) (hb : b < 2 ^ (System.Platform.numBits - 1)) : + ISize.ofNat (a / b) = ISize.ofNat a / ISize.ofNat b := by + rw [← ofInt_eq_ofNat, ← ofInt_eq_ofNat, ← ofInt_eq_ofNat, Int.ofNat_tdiv, ofInt_tdiv] + · exact Int.le_of_lt (Int.lt_of_lt_of_le ISize.toInt_minValue_lt_zero (Int.ofNat_zero_le _)) + · apply Int.le_of_lt_add_one + simpa only [toInt_maxValue_add_one, ← Int.ofNat_lt, Int.natCast_pow] using ha + · exact Int.le_of_lt (Int.lt_of_lt_of_le ISize.toInt_minValue_lt_zero (Int.ofNat_zero_le _)) + · apply Int.le_of_lt_add_one + simpa only [toInt_maxValue_add_one, ← Int.ofNat_lt, Int.natCast_pow] using hb + +@[simp] theorem Int8.ofBitVec_srem (a b : BitVec 8) : Int8.ofBitVec (a.srem b) = Int8.ofBitVec a % Int8.ofBitVec b := rfl +@[simp] theorem Int16.ofBitVec_srem (a b : BitVec 16) : Int16.ofBitVec (a.srem b) = Int16.ofBitVec a % Int16.ofBitVec b := rfl +@[simp] theorem Int32.ofBitVec_srem (a b : BitVec 32) : Int32.ofBitVec (a.srem b) = Int32.ofBitVec a % Int32.ofBitVec b := rfl +@[simp] theorem Int64.ofBitVec_srem (a b : BitVec 64) : Int64.ofBitVec (a.srem b) = Int64.ofBitVec a % Int64.ofBitVec b := rfl +@[simp] theorem ISize.ofBitVec_srem (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a.srem b) = ISize.ofBitVec a % ISize.ofBitVec b := rfl + +@[simp] theorem Int8.toInt_bmod_size (a : Int8) : a.toInt.bmod size = a.toInt := BitVec.toInt_bmod_cancel _ +@[simp] theorem Int16.toInt_bmod_size (a : Int16) : a.toInt.bmod size = a.toInt := BitVec.toInt_bmod_cancel _ +@[simp] theorem Int32.toInt_bmod_size (a : Int32) : a.toInt.bmod size = a.toInt := BitVec.toInt_bmod_cancel _ +@[simp] theorem Int64.toInt_bmod_size (a : Int64) : a.toInt.bmod size = a.toInt := BitVec.toInt_bmod_cancel _ +@[simp] theorem ISize.toInt_bmod_size (a : ISize) : a.toInt.bmod size = a.toInt := BitVec.toInt_bmod_cancel _ + +theorem Int8.ofIntLE_le_iff_le {a b : Int} (ha₁ ha₂ hb₁ hb₂) : + Int8.ofIntLE a ha₁ ha₂ ≤ Int8.ofIntLE b hb₁ hb₂ ↔ a ≤ b := by simp [le_iff_toInt_le] +theorem Int16.ofIntLE_le_iff_le {a b : Int} (ha₁ ha₂ hb₁ hb₂) : + Int16.ofIntLE a ha₁ ha₂ ≤ Int16.ofIntLE b hb₁ hb₂ ↔ a ≤ b := by simp [le_iff_toInt_le] +theorem Int32.ofIntLE_le_iff_le {a b : Int} (ha₁ ha₂ hb₁ hb₂) : + Int32.ofIntLE a ha₁ ha₂ ≤ Int32.ofIntLE b hb₁ hb₂ ↔ a ≤ b := by simp [le_iff_toInt_le] +theorem Int64.ofIntLE_le_iff_le {a b : Int} (ha₁ ha₂ hb₁ hb₂) : + Int64.ofIntLE a ha₁ ha₂ ≤ Int64.ofIntLE b hb₁ hb₂ ↔ a ≤ b := by simp [le_iff_toInt_le] +theorem ISize.ofIntLE_le_iff_le {a b : Int} (ha₁ ha₂ hb₁ hb₂) : + ISize.ofIntLE a ha₁ ha₂ ≤ ISize.ofIntLE b hb₁ hb₂ ↔ a ≤ b := by simp [le_iff_toInt_le] + +theorem Int8.ofInt_le_iff_le {a b : Int} (ha₁ : minValue.toInt ≤ a) (ha₂ : a ≤ maxValue.toInt) + (hb₁ : minValue.toInt ≤ b) (hb₂ : b ≤ maxValue.toInt) : Int8.ofInt a ≤ Int8.ofInt b ↔ a ≤ b := by + rw [← ofIntLE_eq_ofInt ha₁ ha₂, ← ofIntLE_eq_ofInt hb₁ hb₂, ofIntLE_le_iff_le] +theorem Int16.ofInt_le_iff_le {a b : Int} (ha₁ : minValue.toInt ≤ a) (ha₂ : a ≤ maxValue.toInt) + (hb₁ : minValue.toInt ≤ b) (hb₂ : b ≤ maxValue.toInt) : Int16.ofInt a ≤ Int16.ofInt b ↔ a ≤ b := by + rw [← ofIntLE_eq_ofInt ha₁ ha₂, ← ofIntLE_eq_ofInt hb₁ hb₂, ofIntLE_le_iff_le] +theorem Int32.ofInt_le_iff_le {a b : Int} (ha₁ : minValue.toInt ≤ a) (ha₂ : a ≤ maxValue.toInt) + (hb₁ : minValue.toInt ≤ b) (hb₂ : b ≤ maxValue.toInt) : Int32.ofInt a ≤ Int32.ofInt b ↔ a ≤ b := by + rw [← ofIntLE_eq_ofInt ha₁ ha₂, ← ofIntLE_eq_ofInt hb₁ hb₂, ofIntLE_le_iff_le] +theorem Int64.ofInt_le_iff_le {a b : Int} (ha₁ : minValue.toInt ≤ a) (ha₂ : a ≤ maxValue.toInt) + (hb₁ : minValue.toInt ≤ b) (hb₂ : b ≤ maxValue.toInt) : Int64.ofInt a ≤ Int64.ofInt b ↔ a ≤ b := by + rw [← ofIntLE_eq_ofInt ha₁ ha₂, ← ofIntLE_eq_ofInt hb₁ hb₂, ofIntLE_le_iff_le] +theorem ISize.ofInt_le_iff_le {a b : Int} (ha₁ : minValue.toInt ≤ a) (ha₂ : a ≤ maxValue.toInt) + (hb₁ : minValue.toInt ≤ b) (hb₂ : b ≤ maxValue.toInt) : ISize.ofInt a ≤ ISize.ofInt b ↔ a ≤ b := by + rw [← ofIntLE_eq_ofInt ha₁ ha₂, ← ofIntLE_eq_ofInt hb₁ hb₂, ofIntLE_le_iff_le] + +theorem Int8.ofNat_le_iff_le {a b : Nat} (ha : a < 2 ^ 7) (hb : b < 2 ^ 7) : + Int8.ofNat a ≤ Int8.ofNat b ↔ a ≤ b := by + rw [← ofInt_eq_ofNat, ← ofInt_eq_ofNat, ofInt_le_iff_le (by simp) _ (by simp), Int.ofNat_le] + · exact Int.le_of_lt_add_one (Int.ofNat_le.2 hb) + · exact Int.le_of_lt_add_one (Int.ofNat_le.2 ha) +theorem Int16.ofNat_le_iff_le {a b : Nat} (ha : a < 2 ^ 15) (hb : b < 2 ^ 15) : + Int16.ofNat a ≤ Int16.ofNat b ↔ a ≤ b := by + rw [← ofInt_eq_ofNat, ← ofInt_eq_ofNat, ofInt_le_iff_le (by simp) _ (by simp), Int.ofNat_le] + · exact Int.le_of_lt_add_one (Int.ofNat_le.2 hb) + · exact Int.le_of_lt_add_one (Int.ofNat_le.2 ha) +theorem Int32.ofNat_le_iff_le {a b : Nat} (ha : a < 2 ^ 31) (hb : b < 2 ^ 31) : + Int32.ofNat a ≤ Int32.ofNat b ↔ a ≤ b := by + rw [← ofInt_eq_ofNat, ← ofInt_eq_ofNat, ofInt_le_iff_le (by simp) _ (by simp), Int.ofNat_le] + · exact Int.le_of_lt_add_one (Int.ofNat_le.2 hb) + · exact Int.le_of_lt_add_one (Int.ofNat_le.2 ha) +theorem Int64.ofNat_le_iff_le {a b : Nat} (ha : a < 2 ^ 63) (hb : b < 2 ^ 63) : + Int64.ofNat a ≤ Int64.ofNat b ↔ a ≤ b := by + rw [← ofInt_eq_ofNat, ← ofInt_eq_ofNat, ofInt_le_iff_le (by simp) _ (by simp), Int.ofNat_le] + · exact Int.le_of_lt_add_one (Int.ofNat_le.2 hb) + · exact Int.le_of_lt_add_one (Int.ofNat_le.2 ha) +theorem ISize.ofNat_le_iff_le {a b : Nat} (ha : a < 2 ^ (System.Platform.numBits - 1)) (hb : b < 2 ^ (System.Platform.numBits - 1)) : + ISize.ofNat a ≤ ISize.ofNat b ↔ a ≤ b := by + rw [← ofInt_eq_ofNat, ← ofInt_eq_ofNat, ofInt_le_iff_le, Int.ofNat_le] + · exact Int.le_of_lt (Int.lt_of_lt_of_le ISize.toInt_minValue_lt_zero (Int.ofNat_zero_le _)) + · apply Int.le_of_lt_add_one + simpa only [toInt_maxValue_add_one, ← Int.ofNat_lt, Int.natCast_pow] using ha + · exact Int.le_of_lt (Int.lt_of_lt_of_le ISize.toInt_minValue_lt_zero (Int.ofNat_zero_le _)) + · apply Int.le_of_lt_add_one + simpa only [toInt_maxValue_add_one, ← Int.ofNat_lt, Int.natCast_pow] using hb + +theorem Int8.ofBitVec_le_iff_sle (a b : BitVec 8) : Int8.ofBitVec a ≤ Int8.ofBitVec b ↔ a.sle b := Iff.rfl +theorem Int16.ofBitVec_le_iff_sle (a b : BitVec 16) : Int16.ofBitVec a ≤ Int16.ofBitVec b ↔ a.sle b := Iff.rfl +theorem Int32.ofBitVec_le_iff_sle (a b : BitVec 32) : Int32.ofBitVec a ≤ Int32.ofBitVec b ↔ a.sle b := Iff.rfl +theorem Int64.ofBitVec_le_iff_sle (a b : BitVec 64) : Int64.ofBitVec a ≤ Int64.ofBitVec b ↔ a.sle b := Iff.rfl +theorem ISize.ofBitVec_le_iff_sle (a b : BitVec System.Platform.numBits) : ISize.ofBitVec a ≤ ISize.ofBitVec b ↔ a.sle b := Iff.rfl + +theorem Int8.ofIntLE_lt_iff_lt {a b : Int} (ha₁ ha₂ hb₁ hb₂) : + Int8.ofIntLE a ha₁ ha₂ < Int8.ofIntLE b hb₁ hb₂ ↔ a < b := by simp [lt_iff_toInt_lt] +theorem Int16.ofIntLE_lt_iff_lt {a b : Int} (ha₁ ha₂ hb₁ hb₂) : + Int16.ofIntLE a ha₁ ha₂ < Int16.ofIntLE b hb₁ hb₂ ↔ a < b := by simp [lt_iff_toInt_lt] +theorem Int32.ofIntLE_lt_iff_lt {a b : Int} (ha₁ ha₂ hb₁ hb₂) : + Int32.ofIntLE a ha₁ ha₂ < Int32.ofIntLE b hb₁ hb₂ ↔ a < b := by simp [lt_iff_toInt_lt] +theorem Int64.ofIntLE_lt_iff_lt {a b : Int} (ha₁ ha₂ hb₁ hb₂) : + Int64.ofIntLE a ha₁ ha₂ < Int64.ofIntLE b hb₁ hb₂ ↔ a < b := by simp [lt_iff_toInt_lt] +theorem ISize.ofIntLE_lt_iff_lt {a b : Int} (ha₁ ha₂ hb₁ hb₂) : + ISize.ofIntLE a ha₁ ha₂ < ISize.ofIntLE b hb₁ hb₂ ↔ a < b := by simp [lt_iff_toInt_lt] + +theorem Int8.ofInt_lt_iff_lt {a b : Int} (ha₁ : minValue.toInt ≤ a) (ha₂ : a ≤ maxValue.toInt) + (hb₁ : minValue.toInt ≤ b) (hb₂ : b ≤ maxValue.toInt) : Int8.ofInt a < Int8.ofInt b ↔ a < b := by + rw [← ofIntLE_eq_ofInt ha₁ ha₂, ← ofIntLE_eq_ofInt hb₁ hb₂, ofIntLE_lt_iff_lt] +theorem Int16.ofInt_lt_iff_lt {a b : Int} (ha₁ : minValue.toInt ≤ a) (ha₂ : a ≤ maxValue.toInt) + (hb₁ : minValue.toInt ≤ b) (hb₂ : b ≤ maxValue.toInt) : Int16.ofInt a < Int16.ofInt b ↔ a < b := by + rw [← ofIntLE_eq_ofInt ha₁ ha₂, ← ofIntLE_eq_ofInt hb₁ hb₂, ofIntLE_lt_iff_lt] +theorem Int32.ofInt_lt_iff_lt {a b : Int} (ha₁ : minValue.toInt ≤ a) (ha₂ : a ≤ maxValue.toInt) + (hb₁ : minValue.toInt ≤ b) (hb₂ : b ≤ maxValue.toInt) : Int32.ofInt a < Int32.ofInt b ↔ a < b := by + rw [← ofIntLE_eq_ofInt ha₁ ha₂, ← ofIntLE_eq_ofInt hb₁ hb₂, ofIntLE_lt_iff_lt] +theorem Int64.ofInt_lt_iff_lt {a b : Int} (ha₁ : minValue.toInt ≤ a) (ha₂ : a ≤ maxValue.toInt) + (hb₁ : minValue.toInt ≤ b) (hb₂ : b ≤ maxValue.toInt) : Int64.ofInt a < Int64.ofInt b ↔ a < b := by + rw [← ofIntLE_eq_ofInt ha₁ ha₂, ← ofIntLE_eq_ofInt hb₁ hb₂, ofIntLE_lt_iff_lt] +theorem ISize.ofInt_lt_iff_lt {a b : Int} (ha₁ : minValue.toInt ≤ a) (ha₂ : a ≤ maxValue.toInt) + (hb₁ : minValue.toInt ≤ b) (hb₂ : b ≤ maxValue.toInt) : ISize.ofInt a < ISize.ofInt b ↔ a < b := by + rw [← ofIntLE_eq_ofInt ha₁ ha₂, ← ofIntLE_eq_ofInt hb₁ hb₂, ofIntLE_lt_iff_lt] + +theorem Int8.ofNat_lt_iff_lt {a b : Nat} (ha : a < 2 ^ 7) (hb : b < 2 ^ 7) : + Int8.ofNat a < Int8.ofNat b ↔ a < b := by + rw [← ofInt_eq_ofNat, ← ofInt_eq_ofNat, ofInt_lt_iff_lt (by simp) _ (by simp), Int.ofNat_lt] + · exact Int.le_of_lt_add_one (Int.ofNat_lt.2 hb) + · exact Int.le_of_lt_add_one (Int.ofNat_lt.2 ha) +theorem Int16.ofNat_lt_iff_lt {a b : Nat} (ha : a < 2 ^ 15) (hb : b < 2 ^ 15) : + Int16.ofNat a < Int16.ofNat b ↔ a < b := by + rw [← ofInt_eq_ofNat, ← ofInt_eq_ofNat, ofInt_lt_iff_lt (by simp) _ (by simp), Int.ofNat_lt] + · exact Int.le_of_lt_add_one (Int.ofNat_lt.2 hb) + · exact Int.le_of_lt_add_one (Int.ofNat_lt.2 ha) +theorem Int32.ofNat_lt_iff_lt {a b : Nat} (ha : a < 2 ^ 31) (hb : b < 2 ^ 31) : + Int32.ofNat a < Int32.ofNat b ↔ a < b := by + rw [← ofInt_eq_ofNat, ← ofInt_eq_ofNat, ofInt_lt_iff_lt (by simp) _ (by simp), Int.ofNat_lt] + · exact Int.le_of_lt_add_one (Int.ofNat_lt.2 hb) + · exact Int.le_of_lt_add_one (Int.ofNat_lt.2 ha) +theorem Int64.ofNat_lt_iff_lt {a b : Nat} (ha : a < 2 ^ 63) (hb : b < 2 ^ 63) : + Int64.ofNat a < Int64.ofNat b ↔ a < b := by + rw [← ofInt_eq_ofNat, ← ofInt_eq_ofNat, ofInt_lt_iff_lt (by simp) _ (by simp), Int.ofNat_lt] + · exact Int.le_of_lt_add_one (Int.ofNat_lt.2 hb) + · exact Int.le_of_lt_add_one (Int.ofNat_lt.2 ha) +theorem ISize.ofNat_lt_iff_lt {a b : Nat} (ha : a < 2 ^ (System.Platform.numBits - 1)) (hb : b < 2 ^ (System.Platform.numBits - 1)) : + ISize.ofNat a < ISize.ofNat b ↔ a < b := by + rw [← ofInt_eq_ofNat, ← ofInt_eq_ofNat, ofInt_lt_iff_lt, Int.ofNat_lt] + · exact Int.le_of_lt (Int.lt_of_lt_of_le ISize.toInt_minValue_lt_zero (Int.ofNat_zero_le _)) + · apply Int.le_of_lt_add_one + simpa only [toInt_maxValue_add_one, ← Int.ofNat_lt, Int.natCast_pow] using ha + · exact Int.le_of_lt (Int.lt_of_lt_of_le ISize.toInt_minValue_lt_zero (Int.ofNat_zero_le _)) + · apply Int.le_of_lt_add_one + simpa only [toInt_maxValue_add_one, ← Int.ofNat_lt, Int.natCast_pow] using hb + +theorem Int8.ofBitVec_lt_iff_slt (a b : BitVec 8) : Int8.ofBitVec a < Int8.ofBitVec b ↔ a.slt b := Iff.rfl +theorem Int16.ofBitVec_lt_iff_slt (a b : BitVec 16) : Int16.ofBitVec a < Int16.ofBitVec b ↔ a.slt b := Iff.rfl +theorem Int32.ofBitVec_lt_iff_slt (a b : BitVec 32) : Int32.ofBitVec a < Int32.ofBitVec b ↔ a.slt b := Iff.rfl +theorem Int64.ofBitVec_lt_iff_slt (a b : BitVec 64) : Int64.ofBitVec a < Int64.ofBitVec b ↔ a.slt b := Iff.rfl +theorem ISize.ofBitVec_lt_iff_slt (a b : BitVec System.Platform.numBits) : ISize.ofBitVec a < ISize.ofBitVec b ↔ a.slt b := Iff.rfl + +theorem Int8.toNatClampNeg_one : (1 : Int8).toNatClampNeg = 1 := rfl +theorem Int16.toNatClampNeg_one : (1 : Int16).toNatClampNeg = 1 := rfl +theorem Int32.toNatClampNeg_one : (1 : Int32).toNatClampNeg = 1 := rfl +theorem Int64.toNatClampNeg_one : (1 : Int64).toNatClampNeg = 1 := rfl +theorem ISize.toNatClampNeg_one : (1 : ISize).toNatClampNeg = 1 := by simp + +theorem Int8.toInt_one : (1 : Int8).toInt = 1 := rfl +theorem Int16.toInt_one : (1 : Int16).toInt = 1 := rfl +theorem Int32.toInt_one : (1 : Int32).toInt = 1 := rfl +theorem Int64.toInt_one : (1 : Int64).toInt = 1 := rfl +theorem ISize.toInt_one : (1 : ISize).toInt = 1 := by simp + +theorem Int8.zero_lt_one : (0 : Int8) < 1 := by simp +theorem Int16.zero_lt_one : (0 : Int16) < 1 := by simp +theorem Int32.zero_lt_one : (0 : Int32) < 1 := by simp +theorem Int64.zero_lt_one : (0 : Int64) < 1 := by simp +theorem ISize.zero_lt_one : (0 : ISize) < 1 := by simp [lt_iff_toInt_lt] + +theorem Int8.zero_ne_one : (0 : Int8) ≠ 1 := by simp +theorem Int16.zero_ne_one : (0 : Int16) ≠ 1 := by simp +theorem Int32.zero_ne_one : (0 : Int32) ≠ 1 := by simp +theorem Int64.zero_ne_one : (0 : Int64) ≠ 1 := by simp +theorem ISize.zero_ne_one : (0 : ISize) ≠ 1 := by simp [← ISize.toInt_inj] + +theorem Int8.add_assoc (a b c : Int8) : a + b + c = a + (b + c) := + Int8.toBitVec_inj.1 (BitVec.add_assoc _ _ _) +theorem Int16.add_assoc (a b c : Int16) : a + b + c = a + (b + c) := + Int16.toBitVec_inj.1 (BitVec.add_assoc _ _ _) +theorem Int32.add_assoc (a b c : Int32) : a + b + c = a + (b + c) := + Int32.toBitVec_inj.1 (BitVec.add_assoc _ _ _) +theorem Int64.add_assoc (a b c : Int64) : a + b + c = a + (b + c) := + Int64.toBitVec_inj.1 (BitVec.add_assoc _ _ _) +theorem ISize.add_assoc (a b c : ISize) : a + b + c = a + (b + c) := + ISize.toBitVec_inj.1 (BitVec.add_assoc _ _ _) + +instance : Std.Associative (α := Int8) (· + ·) := ⟨Int8.add_assoc⟩ +instance : Std.Associative (α := Int16) (· + ·) := ⟨Int16.add_assoc⟩ +instance : Std.Associative (α := Int32) (· + ·) := ⟨Int32.add_assoc⟩ +instance : Std.Associative (α := Int64) (· + ·) := ⟨Int64.add_assoc⟩ +instance : Std.Associative (α := ISize) (· + ·) := ⟨ISize.add_assoc⟩ + +theorem Int8.add_comm (a b : Int8) : a + b = b + a := Int8.toBitVec_inj.1 (BitVec.add_comm _ _) +theorem Int16.add_comm (a b : Int16) : a + b = b + a := Int16.toBitVec_inj.1 (BitVec.add_comm _ _) +theorem Int32.add_comm (a b : Int32) : a + b = b + a := Int32.toBitVec_inj.1 (BitVec.add_comm _ _) +theorem Int64.add_comm (a b : Int64) : a + b = b + a := Int64.toBitVec_inj.1 (BitVec.add_comm _ _) +theorem ISize.add_comm (a b : ISize) : a + b = b + a := ISize.toBitVec_inj.1 (BitVec.add_comm _ _) + +instance : Std.Commutative (α := Int8) (· + ·) := ⟨Int8.add_comm⟩ +instance : Std.Commutative (α := Int16) (· + ·) := ⟨Int16.add_comm⟩ +instance : Std.Commutative (α := Int32) (· + ·) := ⟨Int32.add_comm⟩ +instance : Std.Commutative (α := Int64) (· + ·) := ⟨Int64.add_comm⟩ +instance : Std.Commutative (α := ISize) (· + ·) := ⟨ISize.add_comm⟩ + +@[simp] theorem Int8.add_zero (a : Int8) : a + 0 = a := Int8.toBitVec_inj.1 (BitVec.add_zero _) +@[simp] theorem Int16.add_zero (a : Int16) : a + 0 = a := Int16.toBitVec_inj.1 (BitVec.add_zero _) +@[simp] theorem Int32.add_zero (a : Int32) : a + 0 = a := Int32.toBitVec_inj.1 (BitVec.add_zero _) +@[simp] theorem Int64.add_zero (a : Int64) : a + 0 = a := Int64.toBitVec_inj.1 (BitVec.add_zero _) +@[simp] theorem ISize.add_zero (a : ISize) : a + 0 = a := ISize.toBitVec_inj.1 (BitVec.add_zero _) + +@[simp] theorem Int8.zero_add (a : Int8) : 0 + a = a := Int8.toBitVec_inj.1 (BitVec.zero_add _) +@[simp] theorem Int16.zero_add (a : Int16) : 0 + a = a := Int16.toBitVec_inj.1 (BitVec.zero_add _) +@[simp] theorem Int32.zero_add (a : Int32) : 0 + a = a := Int32.toBitVec_inj.1 (BitVec.zero_add _) +@[simp] theorem Int64.zero_add (a : Int64) : 0 + a = a := Int64.toBitVec_inj.1 (BitVec.zero_add _) +@[simp] theorem ISize.zero_add (a : ISize) : 0 + a = a := ISize.toBitVec_inj.1 (BitVec.zero_add _) + +instance : Std.LawfulIdentity (α := Int8) (· + ·) 0 where + left_id := Int8.zero_add + right_id := Int8.add_zero +instance : Std.LawfulIdentity (α := Int16) (· + ·) 0 where + left_id := Int16.zero_add + right_id := Int16.add_zero +instance : Std.LawfulIdentity (α := Int32) (· + ·) 0 where + left_id := Int32.zero_add + right_id := Int32.add_zero +instance : Std.LawfulIdentity (α := Int64) (· + ·) 0 where + left_id := Int64.zero_add + right_id := Int64.add_zero +instance : Std.LawfulIdentity (α := ISize) (· + ·) 0 where + left_id := ISize.zero_add + right_id := ISize.add_zero + +@[simp] theorem Int8.sub_zero (a : Int8) : a - 0 = a := Int8.toBitVec_inj.1 (BitVec.sub_zero _) +@[simp] theorem Int16.sub_zero (a : Int16) : a - 0 = a := Int16.toBitVec_inj.1 (BitVec.sub_zero _) +@[simp] theorem Int32.sub_zero (a : Int32) : a - 0 = a := Int32.toBitVec_inj.1 (BitVec.sub_zero _) +@[simp] theorem Int64.sub_zero (a : Int64) : a - 0 = a := Int64.toBitVec_inj.1 (BitVec.sub_zero _) +@[simp] theorem ISize.sub_zero (a : ISize) : a - 0 = a := ISize.toBitVec_inj.1 (BitVec.sub_zero _) + +@[simp] theorem Int8.zero_sub (a : Int8) : 0 - a = -a := Int8.toBitVec_inj.1 (BitVec.zero_sub _) +@[simp] theorem Int16.zero_sub (a : Int16) : 0 - a = -a := Int16.toBitVec_inj.1 (BitVec.zero_sub _) +@[simp] theorem Int32.zero_sub (a : Int32) : 0 - a = -a := Int32.toBitVec_inj.1 (BitVec.zero_sub _) +@[simp] theorem Int64.zero_sub (a : Int64) : 0 - a = -a := Int64.toBitVec_inj.1 (BitVec.zero_sub _) +@[simp] theorem ISize.zero_sub (a : ISize) : 0 - a = -a := ISize.toBitVec_inj.1 (BitVec.zero_sub _) + +@[simp] theorem Int8.sub_self (a : Int8) : a - a = 0 := Int8.toBitVec_inj.1 (BitVec.sub_self _) +@[simp] theorem Int16.sub_self (a : Int16) : a - a = 0 := Int16.toBitVec_inj.1 (BitVec.sub_self _) +@[simp] theorem Int32.sub_self (a : Int32) : a - a = 0 := Int32.toBitVec_inj.1 (BitVec.sub_self _) +@[simp] theorem Int64.sub_self (a : Int64) : a - a = 0 := Int64.toBitVec_inj.1 (BitVec.sub_self _) +@[simp] theorem ISize.sub_self (a : ISize) : a - a = 0 := ISize.toBitVec_inj.1 (BitVec.sub_self _) + +@[simp] theorem Int8.sub_add_cancel (a b : Int8) : a - b + b = a := + Int8.toBitVec_inj.1 (BitVec.sub_add_cancel _ _) +@[simp] theorem Int16.sub_add_cancel (a b : Int16) : a - b + b = a := + Int16.toBitVec_inj.1 (BitVec.sub_add_cancel _ _) +@[simp] theorem Int32.sub_add_cancel (a b : Int32) : a - b + b = a := + Int32.toBitVec_inj.1 (BitVec.sub_add_cancel _ _) +@[simp] theorem Int64.sub_add_cancel (a b : Int64) : a - b + b = a := + Int64.toBitVec_inj.1 (BitVec.sub_add_cancel _ _) +@[simp] theorem ISize.sub_add_cancel (a b : ISize) : a - b + b = a := + ISize.toBitVec_inj.1 (BitVec.sub_add_cancel _ _) + +theorem Int8.eq_sub_iff_add_eq {a b c : Int8} : a = c - b ↔ a + b = c := by + simpa [← Int8.toBitVec_inj] using BitVec.eq_sub_iff_add_eq +theorem Int16.eq_sub_iff_add_eq {a b c : Int16} : a = c - b ↔ a + b = c := by + simpa [← Int16.toBitVec_inj] using BitVec.eq_sub_iff_add_eq +theorem Int32.eq_sub_iff_add_eq {a b c : Int32} : a = c - b ↔ a + b = c := by + simpa [← Int32.toBitVec_inj] using BitVec.eq_sub_iff_add_eq +theorem Int64.eq_sub_iff_add_eq {a b c : Int64} : a = c - b ↔ a + b = c := by + simpa [← Int64.toBitVec_inj] using BitVec.eq_sub_iff_add_eq +theorem ISize.eq_sub_iff_add_eq {a b c : ISize} : a = c - b ↔ a + b = c := by + simpa [← ISize.toBitVec_inj] using BitVec.eq_sub_iff_add_eq + +theorem Int8.sub_eq_iff_eq_add {a b c : Int8} : a - b = c ↔ a = c + b := by + simpa [← Int8.toBitVec_inj] using BitVec.sub_eq_iff_eq_add +theorem Int16.sub_eq_iff_eq_add {a b c : Int16} : a - b = c ↔ a = c + b := by + simpa [← Int16.toBitVec_inj] using BitVec.sub_eq_iff_eq_add +theorem Int32.sub_eq_iff_eq_add {a b c : Int32} : a - b = c ↔ a = c + b := by + simpa [← Int32.toBitVec_inj] using BitVec.sub_eq_iff_eq_add +theorem Int64.sub_eq_iff_eq_add {a b c : Int64} : a - b = c ↔ a = c + b := by + simpa [← Int64.toBitVec_inj] using BitVec.sub_eq_iff_eq_add +theorem ISize.sub_eq_iff_eq_add {a b c : ISize} : a - b = c ↔ a = c + b := by + simpa [← ISize.toBitVec_inj] using BitVec.sub_eq_iff_eq_add + +@[simp] theorem Int8.neg_neg {a : Int8} : - -a = a := Int8.toBitVec_inj.1 BitVec.neg_neg +@[simp] theorem Int16.neg_neg {a : Int16} : - -a = a := Int16.toBitVec_inj.1 BitVec.neg_neg +@[simp] theorem Int32.neg_neg {a : Int32} : - -a = a := Int32.toBitVec_inj.1 BitVec.neg_neg +@[simp] theorem Int64.neg_neg {a : Int64} : - -a = a := Int64.toBitVec_inj.1 BitVec.neg_neg +@[simp] theorem ISize.neg_neg {a : ISize} : - -a = a := ISize.toBitVec_inj.1 BitVec.neg_neg + +@[simp] theorem Int8.neg_inj {a b : Int8} : -a = -b ↔ a = b := by simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.neg_inj {a b : Int16} : -a = -b ↔ a = b := by simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.neg_inj {a b : Int32} : -a = -b ↔ a = b := by simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.neg_inj {a b : Int64} : -a = -b ↔ a = b := by simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.neg_inj {a b : ISize} : -a = -b ↔ a = b := by simp [← ISize.toBitVec_inj] + +@[simp] theorem Int8.neg_ne_zero {a : Int8} : -a ≠ 0 ↔ a ≠ 0 := by simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.neg_ne_zero {a : Int16} : -a ≠ 0 ↔ a ≠ 0 := by simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.neg_ne_zero {a : Int32} : -a ≠ 0 ↔ a ≠ 0 := by simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.neg_ne_zero {a : Int64} : -a ≠ 0 ↔ a ≠ 0 := by simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.neg_ne_zero {a : ISize} : -a ≠ 0 ↔ a ≠ 0 := by simp [← ISize.toBitVec_inj] + +theorem Int8.neg_add {a b : Int8} : - (a + b) = -a - b := Int8.toBitVec_inj.1 BitVec.neg_add +theorem Int16.neg_add {a b : Int16} : - (a + b) = -a - b := Int16.toBitVec_inj.1 BitVec.neg_add +theorem Int32.neg_add {a b : Int32} : - (a + b) = -a - b := Int32.toBitVec_inj.1 BitVec.neg_add +theorem Int64.neg_add {a b : Int64} : - (a + b) = -a - b := Int64.toBitVec_inj.1 BitVec.neg_add +theorem ISize.neg_add {a b : ISize} : - (a + b) = -a - b := ISize.toBitVec_inj.1 BitVec.neg_add + +@[simp] theorem Int8.sub_neg {a b : Int8} : a - -b = a + b := Int8.toBitVec_inj.1 BitVec.sub_neg +@[simp] theorem Int16.sub_neg {a b : Int16} : a - -b = a + b := Int16.toBitVec_inj.1 BitVec.sub_neg +@[simp] theorem Int32.sub_neg {a b : Int32} : a - -b = a + b := Int32.toBitVec_inj.1 BitVec.sub_neg +@[simp] theorem Int64.sub_neg {a b : Int64} : a - -b = a + b := Int64.toBitVec_inj.1 BitVec.sub_neg +@[simp] theorem ISize.sub_neg {a b : ISize} : a - -b = a + b := ISize.toBitVec_inj.1 BitVec.sub_neg + +@[simp] theorem Int8.neg_sub {a b : Int8} : -(a - b) = b - a := by + rw [sub_eq_add_neg, neg_add, sub_neg, add_comm, ← sub_eq_add_neg] +@[simp] theorem Int16.neg_sub {a b : Int16} : -(a - b) = b - a := by + rw [sub_eq_add_neg, neg_add, sub_neg, add_comm, ← sub_eq_add_neg] +@[simp] theorem Int32.neg_sub {a b : Int32} : -(a - b) = b - a := by + rw [sub_eq_add_neg, neg_add, sub_neg, add_comm, ← sub_eq_add_neg] +@[simp] theorem Int64.neg_sub {a b : Int64} : -(a - b) = b - a := by + rw [sub_eq_add_neg, neg_add, sub_neg, add_comm, ← sub_eq_add_neg] +@[simp] theorem ISize.neg_sub {a b : ISize} : -(a - b) = b - a := by + rw [sub_eq_add_neg, neg_add, sub_neg, add_comm, ← sub_eq_add_neg] + +@[simp] theorem Int8.add_left_inj {a b : Int8} (c : Int8) : (a + c = b + c) ↔ a = b := by + simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.add_left_inj {a b : Int16} (c : Int16) : (a + c = b + c) ↔ a = b := by + simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.add_left_inj {a b : Int32} (c : Int32) : (a + c = b + c) ↔ a = b := by + simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.add_left_inj {a b : Int64} (c : Int64) : (a + c = b + c) ↔ a = b := by + simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.add_left_inj {a b : ISize} (c : ISize) : (a + c = b + c) ↔ a = b := by + simp [← ISize.toBitVec_inj] + +@[simp] theorem Int8.add_right_inj {a b : Int8} (c : Int8) : (c + a = c + b) ↔ a = b := by + simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.add_right_inj {a b : Int16} (c : Int16) : (c + a = c + b) ↔ a = b := by + simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.add_right_inj {a b : Int32} (c : Int32) : (c + a = c + b) ↔ a = b := by + simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.add_right_inj {a b : Int64} (c : Int64) : (c + a = c + b) ↔ a = b := by + simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.add_right_inj {a b : ISize} (c : ISize) : (c + a = c + b) ↔ a = b := by + simp [← ISize.toBitVec_inj] + +@[simp] theorem Int8.sub_left_inj {a b : Int8} (c : Int8) : (a - c = b - c) ↔ a = b := by + simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.sub_left_inj {a b : Int16} (c : Int16) : (a - c = b - c) ↔ a = b := by + simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.sub_left_inj {a b : Int32} (c : Int32) : (a - c = b - c) ↔ a = b := by + simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.sub_left_inj {a b : Int64} (c : Int64) : (a - c = b - c) ↔ a = b := by + simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.sub_left_inj {a b : ISize} (c : ISize) : (a - c = b - c) ↔ a = b := by + simp [← ISize.toBitVec_inj] + +@[simp] theorem Int8.sub_right_inj {a b : Int8} (c : Int8) : (c - a = c - b) ↔ a = b := by + simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.sub_right_inj {a b : Int16} (c : Int16) : (c - a = c - b) ↔ a = b := by + simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.sub_right_inj {a b : Int32} (c : Int32) : (c - a = c - b) ↔ a = b := by + simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.sub_right_inj {a b : Int64} (c : Int64) : (c - a = c - b) ↔ a = b := by + simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.sub_right_inj {a b : ISize} (c : ISize) : (c - a = c - b) ↔ a = b := by + simp [← ISize.toBitVec_inj] + +@[simp] theorem Int8.add_eq_right {a b : Int8} : a + b = b ↔ a = 0 := by + simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.add_eq_right {a b : Int16} : a + b = b ↔ a = 0 := by + simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.add_eq_right {a b : Int32} : a + b = b ↔ a = 0 := by + simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.add_eq_right {a b : Int64} : a + b = b ↔ a = 0 := by + simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.add_eq_right {a b : ISize} : a + b = b ↔ a = 0 := by + simp [← ISize.toBitVec_inj] + +@[simp] theorem Int8.add_eq_left {a b : Int8} : a + b = a ↔ b = 0 := by + simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.add_eq_left {a b : Int16} : a + b = a ↔ b = 0 := by + simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.add_eq_left {a b : Int32} : a + b = a ↔ b = 0 := by + simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.add_eq_left {a b : Int64} : a + b = a ↔ b = 0 := by + simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.add_eq_left {a b : ISize} : a + b = a ↔ b = 0 := by + simp [← ISize.toBitVec_inj] + +@[simp] theorem Int8.right_eq_add {a b : Int8} : b = a + b ↔ a = 0 := by + simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.right_eq_add {a b : Int16} : b = a + b ↔ a = 0 := by + simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.right_eq_add {a b : Int32} : b = a + b ↔ a = 0 := by + simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.right_eq_add {a b : Int64} : b = a + b ↔ a = 0 := by + simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.right_eq_add {a b : ISize} : b = a + b ↔ a = 0 := by + simp [← ISize.toBitVec_inj] + +@[simp] theorem Int8.left_eq_add {a b : Int8} : a = a + b ↔ b = 0 := by + simp [← Int8.toBitVec_inj] +@[simp] theorem Int16.left_eq_add {a b : Int16} : a = a + b ↔ b = 0 := by + simp [← Int16.toBitVec_inj] +@[simp] theorem Int32.left_eq_add {a b : Int32} : a = a + b ↔ b = 0 := by + simp [← Int32.toBitVec_inj] +@[simp] theorem Int64.left_eq_add {a b : Int64} : a = a + b ↔ b = 0 := by + simp [← Int64.toBitVec_inj] +@[simp] theorem ISize.left_eq_add {a b : ISize} : a = a + b ↔ b = 0 := by + simp [← ISize.toBitVec_inj] + +theorem Int8.mul_comm (a b : Int8) : a * b = b * a := Int8.toBitVec_inj.1 (BitVec.mul_comm _ _) +theorem Int16.mul_comm (a b : Int16) : a * b = b * a := Int16.toBitVec_inj.1 (BitVec.mul_comm _ _) +theorem Int32.mul_comm (a b : Int32) : a * b = b * a := Int32.toBitVec_inj.1 (BitVec.mul_comm _ _) +theorem Int64.mul_comm (a b : Int64) : a * b = b * a := Int64.toBitVec_inj.1 (BitVec.mul_comm _ _) +theorem ISize.mul_comm (a b : ISize) : a * b = b * a := ISize.toBitVec_inj.1 (BitVec.mul_comm _ _) + +instance : Std.Commutative (α := Int8) (· * ·) := ⟨Int8.mul_comm⟩ +instance : Std.Commutative (α := Int16) (· * ·) := ⟨Int16.mul_comm⟩ +instance : Std.Commutative (α := Int32) (· * ·) := ⟨Int32.mul_comm⟩ +instance : Std.Commutative (α := Int64) (· * ·) := ⟨Int64.mul_comm⟩ +instance : Std.Commutative (α := ISize) (· * ·) := ⟨ISize.mul_comm⟩ + +theorem Int8.mul_assoc (a b c : Int8) : a * b * c = a * (b * c) := Int8.toBitVec_inj.1 (BitVec.mul_assoc _ _ _) +theorem Int16.mul_assoc (a b c : Int16) : a * b * c = a * (b * c) := Int16.toBitVec_inj.1 (BitVec.mul_assoc _ _ _) +theorem Int32.mul_assoc (a b c : Int32) : a * b * c = a * (b * c) := Int32.toBitVec_inj.1 (BitVec.mul_assoc _ _ _) +theorem Int64.mul_assoc (a b c : Int64) : a * b * c = a * (b * c) := Int64.toBitVec_inj.1 (BitVec.mul_assoc _ _ _) +theorem ISize.mul_assoc (a b c : ISize) : a * b * c = a * (b * c) := ISize.toBitVec_inj.1 (BitVec.mul_assoc _ _ _) + +instance : Std.Associative (α := Int8) (· * ·) := ⟨Int8.mul_assoc⟩ +instance : Std.Associative (α := Int16) (· * ·) := ⟨Int16.mul_assoc⟩ +instance : Std.Associative (α := Int32) (· * ·) := ⟨Int32.mul_assoc⟩ +instance : Std.Associative (α := Int64) (· * ·) := ⟨Int64.mul_assoc⟩ +instance : Std.Associative (α := ISize) (· * ·) := ⟨ISize.mul_assoc⟩ + +@[simp] theorem Int8.mul_one (a : Int8) : a * 1 = a := Int8.toBitVec_inj.1 (BitVec.mul_one _) +@[simp] theorem Int16.mul_one (a : Int16) : a * 1 = a := Int16.toBitVec_inj.1 (BitVec.mul_one _) +@[simp] theorem Int32.mul_one (a : Int32) : a * 1 = a := Int32.toBitVec_inj.1 (BitVec.mul_one _) +@[simp] theorem Int64.mul_one (a : Int64) : a * 1 = a := Int64.toBitVec_inj.1 (BitVec.mul_one _) +@[simp] theorem ISize.mul_one (a : ISize) : a * 1 = a := ISize.toBitVec_inj.1 (BitVec.mul_one _) + +@[simp] theorem Int8.one_mul (a : Int8) : 1 * a = a := Int8.toBitVec_inj.1 (BitVec.one_mul _) +@[simp] theorem Int16.one_mul (a : Int16) : 1 * a = a := Int16.toBitVec_inj.1 (BitVec.one_mul _) +@[simp] theorem Int32.one_mul (a : Int32) : 1 * a = a := Int32.toBitVec_inj.1 (BitVec.one_mul _) +@[simp] theorem Int64.one_mul (a : Int64) : 1 * a = a := Int64.toBitVec_inj.1 (BitVec.one_mul _) +@[simp] theorem ISize.one_mul (a : ISize) : 1 * a = a := ISize.toBitVec_inj.1 (BitVec.one_mul _) + +instance : Std.LawfulCommIdentity (α := Int8) (· * ·) 1 where + right_id := Int8.mul_one +instance : Std.LawfulCommIdentity (α := Int16) (· * ·) 1 where + right_id := Int16.mul_one +instance : Std.LawfulCommIdentity (α := Int32) (· * ·) 1 where + right_id := Int32.mul_one +instance : Std.LawfulCommIdentity (α := Int64) (· * ·) 1 where + right_id := Int64.mul_one +instance : Std.LawfulCommIdentity (α := ISize) (· * ·) 1 where + right_id := ISize.mul_one + +@[simp] theorem Int8.mul_zero {a : Int8} : a * 0 = 0 := Int8.toBitVec_inj.1 BitVec.mul_zero +@[simp] theorem Int16.mul_zero {a : Int16} : a * 0 = 0 := Int16.toBitVec_inj.1 BitVec.mul_zero +@[simp] theorem Int32.mul_zero {a : Int32} : a * 0 = 0 := Int32.toBitVec_inj.1 BitVec.mul_zero +@[simp] theorem Int64.mul_zero {a : Int64} : a * 0 = 0 := Int64.toBitVec_inj.1 BitVec.mul_zero +@[simp] theorem ISize.mul_zero {a : ISize} : a * 0 = 0 := ISize.toBitVec_inj.1 BitVec.mul_zero + +@[simp] theorem Int8.zero_mul {a : Int8} : 0 * a = 0 := Int8.toBitVec_inj.1 BitVec.zero_mul +@[simp] theorem Int16.zero_mul {a : Int16} : 0 * a = 0 := Int16.toBitVec_inj.1 BitVec.zero_mul +@[simp] theorem Int32.zero_mul {a : Int32} : 0 * a = 0 := Int32.toBitVec_inj.1 BitVec.zero_mul +@[simp] theorem Int64.zero_mul {a : Int64} : 0 * a = 0 := Int64.toBitVec_inj.1 BitVec.zero_mul +@[simp] theorem ISize.zero_mul {a : ISize} : 0 * a = 0 := ISize.toBitVec_inj.1 BitVec.zero_mul + +theorem Int8.mul_add {a b c : Int8} : a * (b + c) = a * b + a * c := + Int8.toBitVec_inj.1 BitVec.mul_add +theorem Int16.mul_add {a b c : Int16} : a * (b + c) = a * b + a * c := + Int16.toBitVec_inj.1 BitVec.mul_add +theorem Int32.mul_add {a b c : Int32} : a * (b + c) = a * b + a * c := + Int32.toBitVec_inj.1 BitVec.mul_add +theorem Int64.mul_add {a b c : Int64} : a * (b + c) = a * b + a * c := + Int64.toBitVec_inj.1 BitVec.mul_add +theorem ISize.mul_add {a b c : ISize} : a * (b + c) = a * b + a * c := + ISize.toBitVec_inj.1 BitVec.mul_add + +theorem Int8.add_mul {a b c : Int8} : (a + b) * c = a * c + b * c := by + rw [mul_comm, mul_add, mul_comm a c, mul_comm c b] +theorem Int16.add_mul {a b c : Int16} : (a + b) * c = a * c + b * c := by + rw [mul_comm, mul_add, mul_comm a c, mul_comm c b] +theorem Int32.add_mul {a b c : Int32} : (a + b) * c = a * c + b * c := by + rw [mul_comm, mul_add, mul_comm a c, mul_comm c b] +theorem Int64.add_mul {a b c : Int64} : (a + b) * c = a * c + b * c := by + rw [mul_comm, mul_add, mul_comm a c, mul_comm c b] +theorem ISize.add_mul {a b c : ISize} : (a + b) * c = a * c + b * c := by + rw [mul_comm, mul_add, mul_comm a c, mul_comm c b] + +theorem Int8.mul_succ {a b : Int8} : a * (b + 1) = a * b + a := by simp [mul_add] +theorem Int16.mul_succ {a b : Int16} : a * (b + 1) = a * b + a := by simp [mul_add] +theorem Int32.mul_succ {a b : Int32} : a * (b + 1) = a * b + a := by simp [mul_add] +theorem Int64.mul_succ {a b : Int64} : a * (b + 1) = a * b + a := by simp [mul_add] +theorem ISize.mul_succ {a b : ISize} : a * (b + 1) = a * b + a := by simp [mul_add] + +theorem Int8.succ_mul {a b : Int8} : (a + 1) * b = a * b + b := by simp [add_mul] +theorem Int16.succ_mul {a b : Int16} : (a + 1) * b = a * b + b := by simp [add_mul] +theorem Int32.succ_mul {a b : Int32} : (a + 1) * b = a * b + b := by simp [add_mul] +theorem Int64.succ_mul {a b : Int64} : (a + 1) * b = a * b + b := by simp [add_mul] +theorem ISize.succ_mul {a b : ISize} : (a + 1) * b = a * b + b := by simp [add_mul] + +theorem Int8.two_mul {a : Int8} : 2 * a = a + a := Int8.toBitVec_inj.1 BitVec.two_mul +theorem Int16.two_mul {a : Int16} : 2 * a = a + a := Int16.toBitVec_inj.1 BitVec.two_mul +theorem Int32.two_mul {a : Int32} : 2 * a = a + a := Int32.toBitVec_inj.1 BitVec.two_mul +theorem Int64.two_mul {a : Int64} : 2 * a = a + a := Int64.toBitVec_inj.1 BitVec.two_mul +theorem ISize.two_mul {a : ISize} : 2 * a = a + a := ISize.toBitVec_inj.1 BitVec.two_mul + +theorem Int8.mul_two {a : Int8} : a * 2 = a + a := Int8.toBitVec_inj.1 BitVec.mul_two +theorem Int16.mul_two {a : Int16} : a * 2 = a + a := Int16.toBitVec_inj.1 BitVec.mul_two +theorem Int32.mul_two {a : Int32} : a * 2 = a + a := Int32.toBitVec_inj.1 BitVec.mul_two +theorem Int64.mul_two {a : Int64} : a * 2 = a + a := Int64.toBitVec_inj.1 BitVec.mul_two +theorem ISize.mul_two {a : ISize} : a * 2 = a + a := ISize.toBitVec_inj.1 BitVec.mul_two + +theorem Int8.neg_mul (a b : Int8) : -a * b = -(a * b) := Int8.toBitVec_inj.1 (BitVec.neg_mul _ _) +theorem Int16.neg_mul (a b : Int16) : -a * b = -(a * b) := Int16.toBitVec_inj.1 (BitVec.neg_mul _ _) +theorem Int32.neg_mul (a b : Int32) : -a * b = -(a * b) := Int32.toBitVec_inj.1 (BitVec.neg_mul _ _) +theorem Int64.neg_mul (a b : Int64) : -a * b = -(a * b) := Int64.toBitVec_inj.1 (BitVec.neg_mul _ _) +theorem ISize.neg_mul (a b : ISize) : -a * b = -(a * b) := ISize.toBitVec_inj.1 (BitVec.neg_mul _ _) + +theorem Int8.mul_neg (a b : Int8) : a * -b = -(a * b) := Int8.toBitVec_inj.1 (BitVec.mul_neg _ _) +theorem Int16.mul_neg (a b : Int16) : a * -b = -(a * b) := Int16.toBitVec_inj.1 (BitVec.mul_neg _ _) +theorem Int32.mul_neg (a b : Int32) : a * -b = -(a * b) := Int32.toBitVec_inj.1 (BitVec.mul_neg _ _) +theorem Int64.mul_neg (a b : Int64) : a * -b = -(a * b) := Int64.toBitVec_inj.1 (BitVec.mul_neg _ _) +theorem ISize.mul_neg (a b : ISize) : a * -b = -(a * b) := ISize.toBitVec_inj.1 (BitVec.mul_neg _ _) + +theorem Int8.neg_mul_neg (a b : Int8) : -a * -b = a * b := Int8.toBitVec_inj.1 (BitVec.neg_mul_neg _ _) +theorem Int16.neg_mul_neg (a b : Int16) : -a * -b = a * b := Int16.toBitVec_inj.1 (BitVec.neg_mul_neg _ _) +theorem Int32.neg_mul_neg (a b : Int32) : -a * -b = a * b := Int32.toBitVec_inj.1 (BitVec.neg_mul_neg _ _) +theorem Int64.neg_mul_neg (a b : Int64) : -a * -b = a * b := Int64.toBitVec_inj.1 (BitVec.neg_mul_neg _ _) +theorem ISize.neg_mul_neg (a b : ISize) : -a * -b = a * b := ISize.toBitVec_inj.1 (BitVec.neg_mul_neg _ _) + +theorem Int8.neg_mul_comm (a b : Int8) : -a * b = a * -b := Int8.toBitVec_inj.1 (BitVec.neg_mul_comm _ _) +theorem Int16.neg_mul_comm (a b : Int16) : -a * b = a * -b := Int16.toBitVec_inj.1 (BitVec.neg_mul_comm _ _) +theorem Int32.neg_mul_comm (a b : Int32) : -a * b = a * -b := Int32.toBitVec_inj.1 (BitVec.neg_mul_comm _ _) +theorem Int64.neg_mul_comm (a b : Int64) : -a * b = a * -b := Int64.toBitVec_inj.1 (BitVec.neg_mul_comm _ _) +theorem ISize.neg_mul_comm (a b : ISize) : -a * b = a * -b := ISize.toBitVec_inj.1 (BitVec.neg_mul_comm _ _) + +theorem Int8.mul_sub {a b c : Int8} : a * (b - c) = a * b - a * c := Int8.toBitVec_inj.1 BitVec.mul_sub +theorem Int16.mul_sub {a b c : Int16} : a * (b - c) = a * b - a * c := Int16.toBitVec_inj.1 BitVec.mul_sub +theorem Int32.mul_sub {a b c : Int32} : a * (b - c) = a * b - a * c := Int32.toBitVec_inj.1 BitVec.mul_sub +theorem Int64.mul_sub {a b c : Int64} : a * (b - c) = a * b - a * c := Int64.toBitVec_inj.1 BitVec.mul_sub +theorem ISize.mul_sub {a b c : ISize} : a * (b - c) = a * b - a * c := ISize.toBitVec_inj.1 BitVec.mul_sub + +theorem Int8.sub_mul {a b c : Int8} : (a - b) * c = a * c - b * c := by + rw [mul_comm, mul_sub, mul_comm, mul_comm c] +theorem Int16.sub_mul {a b c : Int16} : (a - b) * c = a * c - b * c := by + rw [mul_comm, mul_sub, mul_comm, mul_comm c] +theorem Int32.sub_mul {a b c : Int32} : (a - b) * c = a * c - b * c := by + rw [mul_comm, mul_sub, mul_comm, mul_comm c] +theorem Int64.sub_mul {a b c : Int64} : (a - b) * c = a * c - b * c := by + rw [mul_comm, mul_sub, mul_comm, mul_comm c] +theorem ISize.sub_mul {a b c : ISize} : (a - b) * c = a * c - b * c := by + rw [mul_comm, mul_sub, mul_comm, mul_comm c] + +theorem Int8.neg_add_mul_eq_mul_not {a b : Int8} : -(a + a * b) = a * ~~~b := + Int8.toBitVec_inj.1 BitVec.neg_add_mul_eq_mul_not +theorem Int16.neg_add_mul_eq_mul_not {a b : Int16} : -(a + a * b) = a * ~~~b := + Int16.toBitVec_inj.1 BitVec.neg_add_mul_eq_mul_not +theorem Int32.neg_add_mul_eq_mul_not {a b : Int32} : -(a + a * b) = a * ~~~b := + Int32.toBitVec_inj.1 BitVec.neg_add_mul_eq_mul_not +theorem Int64.neg_add_mul_eq_mul_not {a b : Int64} : -(a + a * b) = a * ~~~b := + Int64.toBitVec_inj.1 BitVec.neg_add_mul_eq_mul_not +theorem ISize.neg_add_mul_eq_mul_not {a b : ISize} : -(a + a * b) = a * ~~~b := + ISize.toBitVec_inj.1 BitVec.neg_add_mul_eq_mul_not + +theorem Int8.neg_mul_not_eq_add_mul {a b : Int8} : -(a * ~~~b) = a + a * b := + Int8.toBitVec_inj.1 BitVec.neg_mul_not_eq_add_mul +theorem Int16.neg_mul_not_eq_add_mul {a b : Int16} : -(a * ~~~b) = a + a * b := + Int16.toBitVec_inj.1 BitVec.neg_mul_not_eq_add_mul +theorem Int32.neg_mul_not_eq_add_mul {a b : Int32} : -(a * ~~~b) = a + a * b := + Int32.toBitVec_inj.1 BitVec.neg_mul_not_eq_add_mul +theorem Int64.neg_mul_not_eq_add_mul {a b : Int64} : -(a * ~~~b) = a + a * b := + Int64.toBitVec_inj.1 BitVec.neg_mul_not_eq_add_mul +theorem ISize.neg_mul_not_eq_add_mul {a b : ISize} : -(a * ~~~b) = a + a * b := + ISize.toBitVec_inj.1 BitVec.neg_mul_not_eq_add_mul + +theorem Int8.le_of_lt {a b : Int8} : a < b → a ≤ b := by + simpa [lt_iff_toInt_lt, le_iff_toInt_le] using Int.le_of_lt +theorem Int16.le_of_lt {a b : Int16} : a < b → a ≤ b := by + simpa [lt_iff_toInt_lt, le_iff_toInt_le] using Int.le_of_lt +theorem Int32.le_of_lt {a b : Int32} : a < b → a ≤ b := by + simpa [lt_iff_toInt_lt, le_iff_toInt_le] using Int.le_of_lt +theorem Int64.le_of_lt {a b : Int64} : a < b → a ≤ b := by + simpa [lt_iff_toInt_lt, le_iff_toInt_le] using Int.le_of_lt +theorem ISize.le_of_lt {a b : ISize} : a < b → a ≤ b := by + simpa [lt_iff_toInt_lt, le_iff_toInt_le] using Int.le_of_lt + +theorem Int8.lt_of_le_of_ne {a b : Int8} : a ≤ b → a ≠ b → a < b := by + simpa [lt_iff_toInt_lt, le_iff_toInt_le, ← Int8.toInt_inj] using (Int.lt_iff_le_and_ne.2 ⟨·, ·⟩) +theorem Int16.lt_of_le_of_ne {a b : Int16} : a ≤ b → a ≠ b → a < b := by + simpa [lt_iff_toInt_lt, le_iff_toInt_le, ← Int16.toInt_inj] using (Int.lt_iff_le_and_ne.2 ⟨·, ·⟩) +theorem Int32.lt_of_le_of_ne {a b : Int32} : a ≤ b → a ≠ b → a < b := by + simpa [lt_iff_toInt_lt, le_iff_toInt_le, ← Int32.toInt_inj] using (Int.lt_iff_le_and_ne.2 ⟨·, ·⟩) +theorem Int64.lt_of_le_of_ne {a b : Int64} : a ≤ b → a ≠ b → a < b := by + simpa [lt_iff_toInt_lt, le_iff_toInt_le, ← Int64.toInt_inj] using (Int.lt_iff_le_and_ne.2 ⟨·, ·⟩) +theorem ISize.lt_of_le_of_ne {a b : ISize} : a ≤ b → a ≠ b → a < b := by + simpa [lt_iff_toInt_lt, le_iff_toInt_le, ← ISize.toInt_inj] using (Int.lt_iff_le_and_ne.2 ⟨·, ·⟩) + +theorem Int8.lt_iff_le_and_ne {a b : Int8} : a < b ↔ a ≤ b ∧ a ≠ b := by + simpa [lt_iff_toInt_lt, le_iff_toInt_le, ← Int8.toInt_inj] using Int.lt_iff_le_and_ne +theorem Int16.lt_iff_le_and_ne {a b : Int16} : a < b ↔ a ≤ b ∧ a ≠ b := by + simpa [lt_iff_toInt_lt, le_iff_toInt_le, ← Int16.toInt_inj] using Int.lt_iff_le_and_ne +theorem Int32.lt_iff_le_and_ne {a b : Int32} : a < b ↔ a ≤ b ∧ a ≠ b := by + simpa [lt_iff_toInt_lt, le_iff_toInt_le, ← Int32.toInt_inj] using Int.lt_iff_le_and_ne +theorem Int64.lt_iff_le_and_ne {a b : Int64} : a < b ↔ a ≤ b ∧ a ≠ b := by + simpa [lt_iff_toInt_lt, le_iff_toInt_le, ← Int64.toInt_inj] using Int.lt_iff_le_and_ne +theorem ISize.lt_iff_le_and_ne {a b : ISize} : a < b ↔ a ≤ b ∧ a ≠ b := by + simpa [lt_iff_toInt_lt, le_iff_toInt_le, ← ISize.toInt_inj] using Int.lt_iff_le_and_ne + +@[simp] theorem Int8.lt_irrefl {a : Int8} : ¬a < a := by simp [lt_iff_toInt_lt] +@[simp] theorem Int16.lt_irrefl {a : Int16} : ¬a < a := by simp [lt_iff_toInt_lt] +@[simp] theorem Int32.lt_irrefl {a : Int32} : ¬a < a := by simp [lt_iff_toInt_lt] +@[simp] theorem Int64.lt_irrefl {a : Int64} : ¬a < a := by simp [lt_iff_toInt_lt] +@[simp] theorem ISize.lt_irrefl {a : ISize} : ¬a < a := by simp [lt_iff_toInt_lt] + +@[simp] theorem Int8.lt_of_le_of_lt {a b c : Int8} : a ≤ b → b < c → a < c := by + simpa [le_iff_toInt_le, lt_iff_toInt_lt] using Int.lt_of_le_of_lt +@[simp] theorem Int16.lt_of_le_of_lt {a b c : Int16} : a ≤ b → b < c → a < c := by + simpa [le_iff_toInt_le, lt_iff_toInt_lt] using Int.lt_of_le_of_lt +@[simp] theorem Int32.lt_of_le_of_lt {a b c : Int32} : a ≤ b → b < c → a < c := by + simpa [le_iff_toInt_le, lt_iff_toInt_lt] using Int.lt_of_le_of_lt +@[simp] theorem Int64.lt_of_le_of_lt {a b c : Int64} : a ≤ b → b < c → a < c := by + simpa [le_iff_toInt_le, lt_iff_toInt_lt] using Int.lt_of_le_of_lt +@[simp] theorem ISize.lt_of_le_of_lt {a b c : ISize} : a ≤ b → b < c → a < c := by + simpa [le_iff_toInt_le, lt_iff_toInt_lt] using Int.lt_of_le_of_lt + +@[simp] theorem Int8.lt_of_lt_of_le {a b c : Int8} : a < b → b ≤ c → a < c := by + simpa [le_iff_toInt_le, lt_iff_toInt_lt] using Int.lt_of_lt_of_le +@[simp] theorem Int16.lt_of_lt_of_le {a b c : Int16} : a < b → b ≤ c → a < c := by + simpa [le_iff_toInt_le, lt_iff_toInt_lt] using Int.lt_of_lt_of_le +@[simp] theorem Int32.lt_of_lt_of_le {a b c : Int32} : a < b → b ≤ c → a < c := by + simpa [le_iff_toInt_le, lt_iff_toInt_lt] using Int.lt_of_lt_of_le +@[simp] theorem Int64.lt_of_lt_of_le {a b c : Int64} : a < b → b ≤ c → a < c := by + simpa [le_iff_toInt_le, lt_iff_toInt_lt] using Int.lt_of_lt_of_le +@[simp] theorem ISize.lt_of_lt_of_le {a b c : ISize} : a < b → b ≤ c → a < c := by + simpa [le_iff_toInt_le, lt_iff_toInt_lt] using Int.lt_of_lt_of_le + +@[simp] theorem Int8.minValue_le (a : Int8) : minValue ≤ a := by simpa [le_iff_toInt_le] using a.minValue_le_toInt +@[simp] theorem Int16.minValue_le (a : Int16) : minValue ≤ a := by simpa [le_iff_toInt_le] using a.minValue_le_toInt +@[simp] theorem Int32.minValue_le (a : Int32) : minValue ≤ a := by simpa [le_iff_toInt_le] using a.minValue_le_toInt +@[simp] theorem Int64.minValue_le (a : Int64) : minValue ≤ a := by simpa [le_iff_toInt_le] using a.minValue_le_toInt +@[simp] theorem ISize.minValue_le (a : ISize) : minValue ≤ a := by simpa [le_iff_toInt_le] using a.minValue_le_toInt + +@[simp] theorem Int8.le_maxValue (a : Int8) : a ≤ maxValue := by simpa [le_iff_toInt_le] using a.toInt_le +@[simp] theorem Int16.le_maxValue (a : Int16) : a ≤ maxValue := by simpa [le_iff_toInt_le] using a.toInt_le +@[simp] theorem Int32.le_maxValue (a : Int32) : a ≤ maxValue := by simpa [le_iff_toInt_le] using a.toInt_le +@[simp] theorem Int64.le_maxValue (a : Int64) : a ≤ maxValue := by simpa [le_iff_toInt_le] using a.toInt_le +@[simp] theorem ISize.le_maxValue (a : ISize) : a ≤ maxValue := by simpa [le_iff_toInt_le] using a.toInt_le + +@[simp] theorem Int8.not_lt_minValue {a : Int8} : ¬a < minValue := + fun h => Int8.lt_irrefl (Int8.lt_of_le_of_lt a.minValue_le h) +@[simp] theorem Int16.not_lt_minValue {a : Int16} : ¬a < minValue := + fun h => Int16.lt_irrefl (Int16.lt_of_le_of_lt a.minValue_le h) +@[simp] theorem Int32.not_lt_minValue {a : Int32} : ¬a < minValue := + fun h => Int32.lt_irrefl (Int32.lt_of_le_of_lt a.minValue_le h) +@[simp] theorem Int64.not_lt_minValue {a : Int64} : ¬a < minValue := + fun h => Int64.lt_irrefl (Int64.lt_of_le_of_lt a.minValue_le h) +@[simp] theorem ISize.not_lt_minValue {a : ISize} : ¬a < minValue := + fun h => ISize.lt_irrefl (ISize.lt_of_le_of_lt a.minValue_le h) + +@[simp] theorem Int8.not_maxValue_lt {a : Int8} : ¬maxValue < a := + fun h => Int8.lt_irrefl (Int8.lt_of_lt_of_le h a.le_maxValue) +@[simp] theorem Int16.not_maxValue_lt {a : Int16} : ¬maxValue < a := + fun h => Int16.lt_irrefl (Int16.lt_of_lt_of_le h a.le_maxValue) +@[simp] theorem Int32.not_maxValue_lt {a : Int32} : ¬maxValue < a := + fun h => Int32.lt_irrefl (Int32.lt_of_lt_of_le h a.le_maxValue) +@[simp] theorem Int64.not_maxValue_lt {a : Int64} : ¬maxValue < a := + fun h => Int64.lt_irrefl (Int64.lt_of_lt_of_le h a.le_maxValue) +@[simp] theorem ISize.not_maxValue_lt {a : ISize} : ¬maxValue < a := + fun h => ISize.lt_irrefl (ISize.lt_of_lt_of_le h a.le_maxValue) + +@[simp] theorem Int8.le_refl (a : Int8) : a ≤ a := by simp [Int8.le_iff_toInt_le] +@[simp] theorem Int16.le_refl (a : Int16) : a ≤ a := by simp [Int16.le_iff_toInt_le] +@[simp] theorem Int32.le_refl (a : Int32) : a ≤ a := by simp [Int32.le_iff_toInt_le] +@[simp] theorem Int64.le_refl (a : Int64) : a ≤ a := by simp [Int64.le_iff_toInt_le] +@[simp] theorem ISize.le_refl (a : ISize) : a ≤ a := by simp [ISize.le_iff_toInt_le] + +theorem Int8.le_rfl {a : Int8} : a ≤ a := le_refl _ +theorem Int16.le_rfl {a : Int16} : a ≤ a := le_refl _ +theorem Int32.le_rfl {a : Int32} : a ≤ a := le_refl _ +theorem Int64.le_rfl {a : Int64} : a ≤ a := le_refl _ +theorem ISize.le_rfl {a : ISize} : a ≤ a := le_refl _ + +theorem Int8.le_antisymm_iff {a b : Int8} : a = b ↔ a ≤ b ∧ b ≤ a := + ⟨by rintro rfl; simp, by simpa [← Int8.toInt_inj, le_iff_toInt_le] using Int.le_antisymm⟩ +theorem Int16.le_antisymm_iff {a b : Int16} : a = b ↔ a ≤ b ∧ b ≤ a := + ⟨by rintro rfl; simp, by simpa [← Int16.toInt_inj, le_iff_toInt_le] using Int.le_antisymm⟩ +theorem Int32.le_antisymm_iff {a b : Int32} : a = b ↔ a ≤ b ∧ b ≤ a := + ⟨by rintro rfl; simp, by simpa [← Int32.toInt_inj, le_iff_toInt_le] using Int.le_antisymm⟩ +theorem Int64.le_antisymm_iff {a b : Int64} : a = b ↔ a ≤ b ∧ b ≤ a := + ⟨by rintro rfl; simp, by simpa [← Int64.toInt_inj, le_iff_toInt_le] using Int.le_antisymm⟩ +theorem ISize.le_antisymm_iff {a b : ISize} : a = b ↔ a ≤ b ∧ b ≤ a := + ⟨by rintro rfl; simp, by simpa [← ISize.toInt_inj, le_iff_toInt_le] using Int.le_antisymm⟩ + +theorem Int8.le_antisymm {a b : Int8} : a ≤ b → b ≤ a → a = b := by simpa using Int8.le_antisymm_iff.2 +theorem Int16.le_antisymm {a b : Int16} : a ≤ b → b ≤ a → a = b := by simpa using Int16.le_antisymm_iff.2 +theorem Int32.le_antisymm {a b : Int32} : a ≤ b → b ≤ a → a = b := by simpa using Int32.le_antisymm_iff.2 +theorem Int64.le_antisymm {a b : Int64} : a ≤ b → b ≤ a → a = b := by simpa using Int64.le_antisymm_iff.2 +theorem ISize.le_antisymm {a b : ISize} : a ≤ b → b ≤ a → a = b := by simpa using ISize.le_antisymm_iff.2 + +@[simp] theorem Int8.le_minValue_iff {a : Int8} : a ≤ minValue ↔ a = minValue := + ⟨fun h => Int8.le_antisymm h a.minValue_le, by rintro rfl; simp⟩ +@[simp] theorem Int16.le_minValue_iff {a : Int16} : a ≤ minValue ↔ a = minValue := + ⟨fun h => Int16.le_antisymm h a.minValue_le, by rintro rfl; simp⟩ +@[simp] theorem Int32.le_minValue_iff {a : Int32} : a ≤ minValue ↔ a = minValue := + ⟨fun h => Int32.le_antisymm h a.minValue_le, by rintro rfl; simp⟩ +@[simp] theorem Int64.le_minValue_iff {a : Int64} : a ≤ minValue ↔ a = minValue := + ⟨fun h => Int64.le_antisymm h a.minValue_le, by rintro rfl; simp⟩ +@[simp] theorem ISize.le_minValue_iff {a : ISize} : a ≤ minValue ↔ a = minValue := + ⟨fun h => ISize.le_antisymm h a.minValue_le, by rintro rfl; simp⟩ + +@[simp] theorem Int8.maxValue_le_iff {a : Int8} : maxValue ≤ a ↔ a = maxValue := + ⟨fun h => Int8.le_antisymm a.le_maxValue h, by rintro rfl; simp⟩ +@[simp] theorem Int16.maxValue_le_iff {a : Int16} : maxValue ≤ a ↔ a = maxValue := + ⟨fun h => Int16.le_antisymm a.le_maxValue h, by rintro rfl; simp⟩ +@[simp] theorem Int32.maxValue_le_iff {a : Int32} : maxValue ≤ a ↔ a = maxValue := + ⟨fun h => Int32.le_antisymm a.le_maxValue h, by rintro rfl; simp⟩ +@[simp] theorem Int64.maxValue_le_iff {a : Int64} : maxValue ≤ a ↔ a = maxValue := + ⟨fun h => Int64.le_antisymm a.le_maxValue h, by rintro rfl; simp⟩ +@[simp] theorem ISize.maxValue_le_iff {a : ISize} : maxValue ≤ a ↔ a = maxValue := + ⟨fun h => ISize.le_antisymm a.le_maxValue h, by rintro rfl; simp⟩ + +@[simp] theorem Int8.zero_div {a : Int8} : 0 / a = 0 := Int8.toBitVec_inj.1 BitVec.zero_sdiv +@[simp] theorem Int16.zero_div {a : Int16} : 0 / a = 0 := Int16.toBitVec_inj.1 BitVec.zero_sdiv +@[simp] theorem Int32.zero_div {a : Int32} : 0 / a = 0 := Int32.toBitVec_inj.1 BitVec.zero_sdiv +@[simp] theorem Int64.zero_div {a : Int64} : 0 / a = 0 := Int64.toBitVec_inj.1 BitVec.zero_sdiv +@[simp] theorem ISize.zero_div {a : ISize} : 0 / a = 0 := ISize.toBitVec_inj.1 BitVec.zero_sdiv + +@[simp] theorem Int8.div_zero {a : Int8} : a / 0 = 0 := Int8.toBitVec_inj.1 BitVec.sdiv_zero +@[simp] theorem Int16.div_zero {a : Int16} : a / 0 = 0 := Int16.toBitVec_inj.1 BitVec.sdiv_zero +@[simp] theorem Int32.div_zero {a : Int32} : a / 0 = 0 := Int32.toBitVec_inj.1 BitVec.sdiv_zero +@[simp] theorem Int64.div_zero {a : Int64} : a / 0 = 0 := Int64.toBitVec_inj.1 BitVec.sdiv_zero +@[simp] theorem ISize.div_zero {a : ISize} : a / 0 = 0 := ISize.toBitVec_inj.1 BitVec.sdiv_zero + +@[simp] theorem Int8.div_one {a : Int8} : a / 1 = a := Int8.toBitVec_inj.1 BitVec.sdiv_one +@[simp] theorem Int16.div_one {a : Int16} : a / 1 = a := Int16.toBitVec_inj.1 BitVec.sdiv_one +@[simp] theorem Int32.div_one {a : Int32} : a / 1 = a := Int32.toBitVec_inj.1 BitVec.sdiv_one +@[simp] theorem Int64.div_one {a : Int64} : a / 1 = a := Int64.toBitVec_inj.1 BitVec.sdiv_one +@[simp] theorem ISize.div_one {a : ISize} : a / 1 = a := ISize.toBitVec_inj.1 BitVec.sdiv_one + +theorem Int8.div_self {a : Int8} : a / a = if a = 0 then 0 else 1 := by + simp [← Int8.toBitVec_inj, apply_ite] +theorem Int16.div_self {a : Int16} : a / a = if a = 0 then 0 else 1 := by + simp [← Int16.toBitVec_inj, apply_ite] +theorem Int32.div_self {a : Int32} : a / a = if a = 0 then 0 else 1 := by + simp [← Int32.toBitVec_inj, apply_ite] +theorem Int64.div_self {a : Int64} : a / a = if a = 0 then 0 else 1 := by + simp [← Int64.toBitVec_inj, apply_ite] +theorem ISize.div_self {a : ISize} : a / a = if a = 0 then 0 else 1 := by + simp [← ISize.toInt_inj] + split + · simp_all + · rw [Int.tdiv_self, Int.bmod_eq_self_of_le] + · simp + · cases System.Platform.numBits_eq <;> simp_all + · cases System.Platform.numBits_eq <;> simp_all + · cases System.Platform.numBits_eq <;> simp_all + +@[simp] theorem Int8.mod_zero {a : Int8} : a % 0 = a := Int8.toBitVec_inj.1 BitVec.srem_zero +@[simp] theorem Int16.mod_zero {a : Int16} : a % 0 = a := Int16.toBitVec_inj.1 BitVec.srem_zero +@[simp] theorem Int32.mod_zero {a : Int32} : a % 0 = a := Int32.toBitVec_inj.1 BitVec.srem_zero +@[simp] theorem Int64.mod_zero {a : Int64} : a % 0 = a := Int64.toBitVec_inj.1 BitVec.srem_zero +@[simp] theorem ISize.mod_zero {a : ISize} : a % 0 = a := ISize.toBitVec_inj.1 BitVec.srem_zero + +@[simp] theorem Int8.zero_mod {a : Int8} : 0 % a = 0 := Int8.toBitVec_inj.1 BitVec.zero_srem +@[simp] theorem Int16.zero_mod {a : Int16} : 0 % a = 0 := Int16.toBitVec_inj.1 BitVec.zero_srem +@[simp] theorem Int32.zero_mod {a : Int32} : 0 % a = 0 := Int32.toBitVec_inj.1 BitVec.zero_srem +@[simp] theorem Int64.zero_mod {a : Int64} : 0 % a = 0 := Int64.toBitVec_inj.1 BitVec.zero_srem +@[simp] theorem ISize.zero_mod {a : ISize} : 0 % a = 0 := ISize.toBitVec_inj.1 BitVec.zero_srem + +@[simp] theorem Int8.mod_one {a : Int8} : a % 1 = 0 := Int8.toBitVec_inj.1 BitVec.srem_one +@[simp] theorem Int16.mod_one {a : Int16} : a % 1 = 0 := Int16.toBitVec_inj.1 BitVec.srem_one +@[simp] theorem Int32.mod_one {a : Int32} : a % 1 = 0 := Int32.toBitVec_inj.1 BitVec.srem_one +@[simp] theorem Int64.mod_one {a : Int64} : a % 1 = 0 := Int64.toBitVec_inj.1 BitVec.srem_one +@[simp] theorem ISize.mod_one {a : ISize} : a % 1 = 0 := ISize.toBitVec_inj.1 BitVec.srem_one + +@[simp] theorem Int8.mod_self {a : Int8} : a % a = 0 := Int8.toBitVec_inj.1 BitVec.srem_self +@[simp] theorem Int16.mod_self {a : Int16} : a % a = 0 := Int16.toBitVec_inj.1 BitVec.srem_self +@[simp] theorem Int32.mod_self {a : Int32} : a % a = 0 := Int32.toBitVec_inj.1 BitVec.srem_self +@[simp] theorem Int64.mod_self {a : Int64} : a % a = 0 := Int64.toBitVec_inj.1 BitVec.srem_self +@[simp] theorem ISize.mod_self {a : ISize} : a % a = 0 := ISize.toBitVec_inj.1 BitVec.srem_self + +@[simp] theorem Int8.not_lt {a b : Int8} : ¬ a < b ↔ b ≤ a := by + simp [lt_iff_toBitVec_slt, le_iff_toBitVec_sle, BitVec.sle_eq_not_slt] +@[simp] theorem Int16.not_lt {a b : Int16} : ¬ a < b ↔ b ≤ a := by + simp [lt_iff_toBitVec_slt, le_iff_toBitVec_sle, BitVec.sle_eq_not_slt] +@[simp] theorem Int32.not_lt {a b : Int32} : ¬ a < b ↔ b ≤ a := by + simp [lt_iff_toBitVec_slt, le_iff_toBitVec_sle, BitVec.sle_eq_not_slt] +@[simp] theorem Int64.not_lt {a b : Int64} : ¬ a < b ↔ b ≤ a := by + simp [lt_iff_toBitVec_slt, le_iff_toBitVec_sle, BitVec.sle_eq_not_slt] +@[simp] theorem ISize.not_lt {a b : ISize} : ¬ a < b ↔ b ≤ a := by + simp [lt_iff_toBitVec_slt, le_iff_toBitVec_sle, BitVec.sle_eq_not_slt] + +theorem Int8.le_trans {a b c : Int8} : a ≤ b → b ≤ c → a ≤ c := by + simpa [le_iff_toInt_le] using Int.le_trans +theorem Int16.le_trans {a b c : Int16} : a ≤ b → b ≤ c → a ≤ c := by + simpa [le_iff_toInt_le] using Int.le_trans +theorem Int32.le_trans {a b c : Int32} : a ≤ b → b ≤ c → a ≤ c := by + simpa [le_iff_toInt_le] using Int.le_trans +theorem Int64.le_trans {a b c : Int64} : a ≤ b → b ≤ c → a ≤ c := by + simpa [le_iff_toInt_le] using Int.le_trans +theorem ISize.le_trans {a b c : ISize} : a ≤ b → b ≤ c → a ≤ c := by + simpa [le_iff_toInt_le] using Int.le_trans + +theorem Int8.lt_trans {a b c : Int8} : a < b → b < c → a < c := by + simpa [lt_iff_toInt_lt] using Int.lt_trans +theorem Int16.lt_trans {a b c : Int16} : a < b → b < c → a < c := by + simpa [lt_iff_toInt_lt] using Int.lt_trans +theorem Int32.lt_trans {a b c : Int32} : a < b → b < c → a < c := by + simpa [lt_iff_toInt_lt] using Int.lt_trans +theorem Int64.lt_trans {a b c : Int64} : a < b → b < c → a < c := by + simpa [lt_iff_toInt_lt] using Int.lt_trans +theorem ISize.lt_trans {a b c : ISize} : a < b → b < c → a < c := by + simpa [lt_iff_toInt_lt] using Int.lt_trans + +theorem Int8.le_total (a b : Int8) : a ≤ b ∨ b ≤ a := by + simpa [le_iff_toInt_le] using Int.le_total _ _ +theorem Int16.le_total (a b : Int16) : a ≤ b ∨ b ≤ a := by + simpa [le_iff_toInt_le] using Int.le_total _ _ +theorem Int32.le_total (a b : Int32) : a ≤ b ∨ b ≤ a := by + simpa [le_iff_toInt_le] using Int.le_total _ _ +theorem Int64.le_total (a b : Int64) : a ≤ b ∨ b ≤ a := by + simpa [le_iff_toInt_le] using Int.le_total _ _ +theorem ISize.le_total (a b : ISize) : a ≤ b ∨ b ≤ a := by + simpa [le_iff_toInt_le] using Int.le_total _ _ + +theorem Int8.lt_asymm {a b : Int8} : a < b → ¬b < a := + fun hab hba => Int8.lt_irrefl (Int8.lt_trans hab hba) +theorem Int16.lt_asymm {a b : Int16} : a < b → ¬b < a := + fun hab hba => Int16.lt_irrefl (Int16.lt_trans hab hba) +theorem Int32.lt_asymm {a b : Int32} : a < b → ¬b < a := + fun hab hba => Int32.lt_irrefl (Int32.lt_trans hab hba) +theorem Int64.lt_asymm {a b : Int64} : a < b → ¬b < a := + fun hab hba => Int64.lt_irrefl (Int64.lt_trans hab hba) +theorem ISize.lt_asymm {a b : ISize} : a < b → ¬b < a := + fun hab hba => ISize.lt_irrefl (ISize.lt_trans hab hba) + +theorem Int8.add_neg_eq_sub {a b : Int8} : a + -b = a - b := Int8.toBitVec_inj.1 BitVec.add_neg_eq_sub +theorem Int16.add_neg_eq_sub {a b : Int16} : a + -b = a - b := Int16.toBitVec_inj.1 BitVec.add_neg_eq_sub +theorem Int32.add_neg_eq_sub {a b : Int32} : a + -b = a - b := Int32.toBitVec_inj.1 BitVec.add_neg_eq_sub +theorem Int64.add_neg_eq_sub {a b : Int64} : a + -b = a - b := Int64.toBitVec_inj.1 BitVec.add_neg_eq_sub +theorem ISize.add_neg_eq_sub {a b : ISize} : a + -b = a - b := ISize.toBitVec_inj.1 BitVec.add_neg_eq_sub + +theorem Int8.neg_eq_neg_one_mul (a : Int8) : -a = -1 * a := Int8.toInt_inj.1 (by simp) +theorem Int16.neg_eq_neg_one_mul (a : Int16) : -a = -1 * a := Int16.toInt_inj.1 (by simp) +theorem Int32.neg_eq_neg_one_mul (a : Int32) : -a = -1 * a := Int32.toInt_inj.1 (by simp) +theorem Int64.neg_eq_neg_one_mul (a : Int64) : -a = -1 * a := Int64.toInt_inj.1 (by simp) +theorem ISize.neg_eq_neg_one_mul (a : ISize) : -a = -1 * a := ISize.toInt_inj.1 (by simp [toInt_neg]) + +@[simp] theorem Int8.add_sub_cancel (a b : Int8) : a + b - b = a := Int8.toBitVec_inj.1 (BitVec.add_sub_cancel _ _) +@[simp] theorem Int16.add_sub_cancel (a b : Int16) : a + b - b = a := Int16.toBitVec_inj.1 (BitVec.add_sub_cancel _ _) +@[simp] theorem Int32.add_sub_cancel (a b : Int32) : a + b - b = a := Int32.toBitVec_inj.1 (BitVec.add_sub_cancel _ _) +@[simp] theorem Int64.add_sub_cancel (a b : Int64) : a + b - b = a := Int64.toBitVec_inj.1 (BitVec.add_sub_cancel _ _) +@[simp] theorem ISize.add_sub_cancel (a b : ISize) : a + b - b = a := ISize.toBitVec_inj.1 (BitVec.add_sub_cancel _ _) + +theorem Int8.lt_or_lt_of_ne {a b : Int8} : a ≠ b → a < b ∨ b < a := by + simp [lt_iff_toInt_lt, ← Int8.toInt_inj]; omega +theorem Int16.lt_or_lt_of_ne {a b : Int16} : a ≠ b → a < b ∨ b < a := by + simp [lt_iff_toInt_lt, ← Int16.toInt_inj]; omega +theorem Int32.lt_or_lt_of_ne {a b : Int32} : a ≠ b → a < b ∨ b < a := by + simp [lt_iff_toInt_lt, ← Int32.toInt_inj]; omega +theorem Int64.lt_or_lt_of_ne {a b : Int64} : a ≠ b → a < b ∨ b < a := by + simp [lt_iff_toInt_lt, ← Int64.toInt_inj]; omega +theorem ISize.lt_or_lt_of_ne {a b : ISize} : a ≠ b → a < b ∨ b < a := by + simp [lt_iff_toInt_lt, ← ISize.toInt_inj]; omega + +theorem Int8.lt_or_le (a b : Int8) : a < b ∨ b ≤ a := by + simp [lt_iff_toInt_lt, le_iff_toInt_le]; omega +theorem Int16.lt_or_le (a b : Int16) : a < b ∨ b ≤ a := by + simp [lt_iff_toInt_lt, le_iff_toInt_le]; omega +theorem Int32.lt_or_le (a b : Int32) : a < b ∨ b ≤ a := by + simp [lt_iff_toInt_lt, le_iff_toInt_le]; omega +theorem Int64.lt_or_le (a b : Int64) : a < b ∨ b ≤ a := by + simp [lt_iff_toInt_lt, le_iff_toInt_le]; omega +theorem ISize.lt_or_le (a b : ISize) : a < b ∨ b ≤ a := by + simp [lt_iff_toInt_lt, le_iff_toInt_le]; omega + +theorem Int8.le_or_lt (a b : Int8) : a ≤ b ∨ b < a := (b.lt_or_le a).symm +theorem Int16.le_or_lt (a b : Int16) : a ≤ b ∨ b < a := (b.lt_or_le a).symm +theorem Int32.le_or_lt (a b : Int32) : a ≤ b ∨ b < a := (b.lt_or_le a).symm +theorem Int64.le_or_lt (a b : Int64) : a ≤ b ∨ b < a := (b.lt_or_le a).symm +theorem ISize.le_or_lt (a b : ISize) : a ≤ b ∨ b < a := (b.lt_or_le a).symm + +theorem Int8.le_of_eq {a b : Int8} : a = b → a ≤ b := (· ▸ Int8.le_rfl) +theorem Int16.le_of_eq {a b : Int16} : a = b → a ≤ b := (· ▸ Int16.le_rfl) +theorem Int32.le_of_eq {a b : Int32} : a = b → a ≤ b := (· ▸ Int32.le_rfl) +theorem Int64.le_of_eq {a b : Int64} : a = b → a ≤ b := (· ▸ Int64.le_rfl) +theorem ISize.le_of_eq {a b : ISize} : a = b → a ≤ b := (· ▸ ISize.le_rfl) + +theorem Int8.le_iff_lt_or_eq {a b : Int8} : a ≤ b ↔ a < b ∨ a = b := by + simp [← Int8.toInt_inj, le_iff_toInt_le, lt_iff_toInt_lt]; omega +theorem Int16.le_iff_lt_or_eq {a b : Int16} : a ≤ b ↔ a < b ∨ a = b := by + simp [← Int16.toInt_inj, le_iff_toInt_le, lt_iff_toInt_lt]; omega +theorem Int32.le_iff_lt_or_eq {a b : Int32} : a ≤ b ↔ a < b ∨ a = b := by + simp [← Int32.toInt_inj, le_iff_toInt_le, lt_iff_toInt_lt]; omega +theorem Int64.le_iff_lt_or_eq {a b : Int64} : a ≤ b ↔ a < b ∨ a = b := by + simp [← Int64.toInt_inj, le_iff_toInt_le, lt_iff_toInt_lt]; omega +theorem ISize.le_iff_lt_or_eq {a b : ISize} : a ≤ b ↔ a < b ∨ a = b := by + simp [← ISize.toInt_inj, le_iff_toInt_le, lt_iff_toInt_lt]; omega + +theorem Int8.lt_or_eq_of_le {a b : Int8} : a ≤ b → a < b ∨ a = b := Int8.le_iff_lt_or_eq.mp +theorem Int16.lt_or_eq_of_le {a b : Int16} : a ≤ b → a < b ∨ a = b := Int16.le_iff_lt_or_eq.mp +theorem Int32.lt_or_eq_of_le {a b : Int32} : a ≤ b → a < b ∨ a = b := Int32.le_iff_lt_or_eq.mp +theorem Int64.lt_or_eq_of_le {a b : Int64} : a ≤ b → a < b ∨ a = b := Int64.le_iff_lt_or_eq.mp +theorem ISize.lt_or_eq_of_le {a b : ISize} : a ≤ b → a < b ∨ a = b := ISize.le_iff_lt_or_eq.mp + +theorem Int8.toInt_eq_toNatClampNeg {a : Int8} (ha : 0 ≤ a) : a.toInt = a.toNatClampNeg := by + simpa only [← toNat_toInt, Int.eq_ofNat_toNat, le_iff_toInt_le] using ha +theorem Int16.toInt_eq_toNatClampNeg {a : Int16} (ha : 0 ≤ a) : a.toInt = a.toNatClampNeg := by + simpa only [← toNat_toInt, Int.eq_ofNat_toNat, le_iff_toInt_le] using ha +theorem Int32.toInt_eq_toNatClampNeg {a : Int32} (ha : 0 ≤ a) : a.toInt = a.toNatClampNeg := by + simpa only [← toNat_toInt, Int.eq_ofNat_toNat, le_iff_toInt_le] using ha +theorem Int64.toInt_eq_toNatClampNeg {a : Int64} (ha : 0 ≤ a) : a.toInt = a.toNatClampNeg := by + simpa only [← toNat_toInt, Int.eq_ofNat_toNat, le_iff_toInt_le] using ha +theorem ISize.toInt_eq_toNatClampNeg {a : ISize} (ha : 0 ≤ a) : a.toInt = a.toNatClampNeg := by + simpa only [← toNat_toInt, Int.eq_ofNat_toNat, le_iff_toInt_le, toInt_zero] using ha + +@[simp] theorem UInt8.toInt8_add (a b : UInt8) : (a + b).toInt8 = a.toInt8 + b.toInt8 := rfl +@[simp] theorem UInt16.toInt16_add (a b : UInt16) : (a + b).toInt16 = a.toInt16 + b.toInt16 := rfl +@[simp] theorem UInt32.toInt32_add (a b : UInt32) : (a + b).toInt32 = a.toInt32 + b.toInt32 := rfl +@[simp] theorem UInt64.toInt64_add (a b : UInt64) : (a + b).toInt64 = a.toInt64 + b.toInt64 := rfl +@[simp] theorem USize.toISize_add (a b : USize) : (a + b).toISize = a.toISize + b.toISize := rfl + +@[simp] theorem UInt8.toInt8_neg (a : UInt8) : (-a).toInt8 = -a.toInt8 := rfl +@[simp] theorem UInt16.toInt16_neg (a : UInt16) : (-a).toInt16 = -a.toInt16 := rfl +@[simp] theorem UInt32.toInt32_neg (a : UInt32) : (-a).toInt32 = -a.toInt32 := rfl +@[simp] theorem UInt64.toInt64_neg (a : UInt64) : (-a).toInt64 = -a.toInt64 := rfl +@[simp] theorem USize.toISize_neg (a : USize) : (-a).toISize = -a.toISize := rfl + +@[simp] theorem UInt8.toInt8_sub (a b : UInt8) : (a - b).toInt8 = a.toInt8 - b.toInt8 := rfl +@[simp] theorem UInt16.toInt16_sub (a b : UInt16) : (a - b).toInt16 = a.toInt16 - b.toInt16 := rfl +@[simp] theorem UInt32.toInt32_sub (a b : UInt32) : (a - b).toInt32 = a.toInt32 - b.toInt32 := rfl +@[simp] theorem UInt64.toInt64_sub (a b : UInt64) : (a - b).toInt64 = a.toInt64 - b.toInt64 := rfl +@[simp] theorem USize.toISize_sub (a b : USize) : (a - b).toISize = a.toISize - b.toISize := rfl + +@[simp] theorem UInt8.toInt8_mul (a b : UInt8) : (a * b).toInt8 = a.toInt8 * b.toInt8 := rfl +@[simp] theorem UInt16.toInt16_mul (a b : UInt16) : (a * b).toInt16 = a.toInt16 * b.toInt16 := rfl +@[simp] theorem UInt32.toInt32_mul (a b : UInt32) : (a * b).toInt32 = a.toInt32 * b.toInt32 := rfl +@[simp] theorem UInt64.toInt64_mul (a b : UInt64) : (a * b).toInt64 = a.toInt64 * b.toInt64 := rfl +@[simp] theorem USize.toISize_mul (a b : USize) : (a * b).toISize = a.toISize * b.toISize := rfl + +@[simp] theorem Int8.toUInt8_add (a b : Int8) : (a + b).toUInt8 = a.toUInt8 + b.toUInt8 := rfl +@[simp] theorem Int16.toUInt16_add (a b : Int16) : (a + b).toUInt16 = a.toUInt16 + b.toUInt16 := rfl +@[simp] theorem Int32.toUInt32_add (a b : Int32) : (a + b).toUInt32 = a.toUInt32 + b.toUInt32 := rfl +@[simp] theorem Int64.toUInt64_add (a b : Int64) : (a + b).toUInt64 = a.toUInt64 + b.toUInt64 := rfl +@[simp] theorem ISize.toUSize_add (a b : ISize) : (a + b).toUSize = a.toUSize + b.toUSize := rfl + +@[simp] theorem Int8.toUInt8_neg (a : Int8) : (-a).toUInt8 = -a.toUInt8 := rfl +@[simp] theorem Int16.toUInt16_neg (a : Int16) : (-a).toUInt16 = -a.toUInt16 := rfl +@[simp] theorem Int32.toUInt32_neg (a : Int32) : (-a).toUInt32 = -a.toUInt32 := rfl +@[simp] theorem Int64.toUInt64_neg (a : Int64) : (-a).toUInt64 = -a.toUInt64 := rfl +@[simp] theorem ISize.toUSize_neg (a : ISize) : (-a).toUSize = -a.toUSize := rfl + +@[simp] theorem Int8.toUInt8_sub (a b : Int8) : (a - b).toUInt8 = a.toUInt8 - b.toUInt8 := rfl +@[simp] theorem Int16.toUInt16_sub (a b : Int16) : (a - b).toUInt16 = a.toUInt16 - b.toUInt16 := rfl +@[simp] theorem Int32.toUInt32_sub (a b : Int32) : (a - b).toUInt32 = a.toUInt32 - b.toUInt32 := rfl +@[simp] theorem Int64.toUInt64_sub (a b : Int64) : (a - b).toUInt64 = a.toUInt64 - b.toUInt64 := rfl +@[simp] theorem ISize.toUSize_sub (a b : ISize) : (a - b).toUSize = a.toUSize - b.toUSize := rfl + +@[simp] theorem Int8.toUInt8_mul (a b : Int8) : (a * b).toUInt8 = a.toUInt8 * b.toUInt8 := rfl +@[simp] theorem Int16.toUInt16_mul (a b : Int16) : (a * b).toUInt16 = a.toUInt16 * b.toUInt16 := rfl +@[simp] theorem Int32.toUInt32_mul (a b : Int32) : (a * b).toUInt32 = a.toUInt32 * b.toUInt32 := rfl +@[simp] theorem Int64.toUInt64_mul (a b : Int64) : (a * b).toUInt64 = a.toUInt64 * b.toUInt64 := rfl +@[simp] theorem ISize.toUSize_mul (a b : ISize) : (a * b).toUSize = a.toUSize * b.toUSize := rfl + +theorem Int8.toNatClampNeg_le {a b : Int8} (hab : a ≤ b) : a.toNatClampNeg ≤ b.toNatClampNeg := by + rw [← Int8.toNat_toInt, ← Int8.toNat_toInt] + exact Int.toNat_le_toNat (Int8.le_iff_toInt_le.1 hab) +theorem Int16.toNatClampNeg_le {a b : Int16} (hab : a ≤ b) : a.toNatClampNeg ≤ b.toNatClampNeg := by + rw [← Int16.toNat_toInt, ← Int16.toNat_toInt] + exact Int.toNat_le_toNat (Int16.le_iff_toInt_le.1 hab) +theorem Int32.toNatClampNeg_le {a b : Int32} (hab : a ≤ b) : a.toNatClampNeg ≤ b.toNatClampNeg := by + rw [← Int32.toNat_toInt, ← Int32.toNat_toInt] + exact Int.toNat_le_toNat (Int32.le_iff_toInt_le.1 hab) +theorem Int64.toNatClampNeg_le {a b : Int64} (hab : a ≤ b) : a.toNatClampNeg ≤ b.toNatClampNeg := by + rw [← Int64.toNat_toInt, ← Int64.toNat_toInt] + exact Int.toNat_le_toNat (Int64.le_iff_toInt_le.1 hab) +theorem ISize.toNatClampNeg_le {a b : ISize} (hab : a ≤ b) : a.toNatClampNeg ≤ b.toNatClampNeg := by + rw [← ISize.toNat_toInt, ← ISize.toNat_toInt] + exact Int.toNat_le_toNat (ISize.le_iff_toInt_le.1 hab) + +theorem Int8.toUInt8_le {a b : Int8} (ha : 0 ≤ a) (hab : a ≤ b) : a.toUInt8 ≤ b.toUInt8 := by + rw [UInt8.le_iff_toNat_le, toNat_toUInt8_of_le ha, toNat_toUInt8_of_le (Int8.le_trans ha hab)] + exact Int8.toNatClampNeg_le hab +theorem Int16.toUInt16_le {a b : Int16} (ha : 0 ≤ a) (hab : a ≤ b) : a.toUInt16 ≤ b.toUInt16 := by + rw [UInt16.le_iff_toNat_le, toNat_toUInt16_of_le ha, toNat_toUInt16_of_le (Int16.le_trans ha hab)] + exact Int16.toNatClampNeg_le hab +theorem Int32.toUInt32_le {a b : Int32} (ha : 0 ≤ a) (hab : a ≤ b) : a.toUInt32 ≤ b.toUInt32 := by + rw [UInt32.le_iff_toNat_le, toNat_toUInt32_of_le ha, toNat_toUInt32_of_le (Int32.le_trans ha hab)] + exact Int32.toNatClampNeg_le hab +theorem Int64.toUInt64_le {a b : Int64} (ha : 0 ≤ a) (hab : a ≤ b) : a.toUInt64 ≤ b.toUInt64 := by + rw [UInt64.le_iff_toNat_le, toNat_toUInt64_of_le ha, toNat_toUInt64_of_le (Int64.le_trans ha hab)] + exact Int64.toNatClampNeg_le hab +theorem ISize.toUSize_le {a b : ISize} (ha : 0 ≤ a) (hab : a ≤ b) : a.toUSize ≤ b.toUSize := by + rw [USize.le_iff_toNat_le, toNat_toUISize_of_le ha, toNat_toUISize_of_le (ISize.le_trans ha hab)] + exact ISize.toNatClampNeg_le hab + +theorem Int8.zero_le_ofNat_of_lt {a : Nat} (ha : a < 2 ^ 7) : 0 ≤ Int8.ofNat a := by + rw [le_iff_toInt_le, toInt_ofNat_of_lt ha, Int8.toInt_zero] + exact Int.ofNat_zero_le _ +theorem Int16.zero_le_ofNat_of_lt {a : Nat} (ha : a < 2 ^ 15) : 0 ≤ Int16.ofNat a := by + rw [le_iff_toInt_le, toInt_ofNat_of_lt ha, Int16.toInt_zero] + exact Int.ofNat_zero_le _ +theorem Int32.zero_le_ofNat_of_lt {a : Nat} (ha : a < 2 ^ 31) : 0 ≤ Int32.ofNat a := by + rw [le_iff_toInt_le, toInt_ofNat_of_lt ha, Int32.toInt_zero] + exact Int.ofNat_zero_le _ +theorem Int64.zero_le_ofNat_of_lt {a : Nat} (ha : a < 2 ^ 63) : 0 ≤ Int64.ofNat a := by + rw [le_iff_toInt_le, toInt_ofNat_of_lt ha, Int64.toInt_zero] + exact Int.ofNat_zero_le _ +theorem ISize.zero_le_ofNat_of_lt {a : Nat} (ha : a < 2 ^ (System.Platform.numBits - 1)) : + 0 ≤ ISize.ofNat a := by + rw [le_iff_toInt_le, toInt_ofNat_of_lt_two_pow_numBits ha, ISize.toInt_zero] + exact Int.ofNat_zero_le _ + +theorem Int8.sub_nonneg_of_le {a b : Int8} (hb : 0 ≤ b) (hab : b ≤ a) : 0 ≤ a - b := by + rw [← ofNat_toNatClampNeg _ hb, ← ofNat_toNatClampNeg _ (Int8.le_trans hb hab), + ← ofNat_sub _ _ (Int8.toNatClampNeg_le hab)] + exact Int8.zero_le_ofNat_of_lt (Nat.sub_lt_of_lt a.toNatClampNeg_lt) +theorem Int16.sub_nonneg_of_le {a b : Int16} (hb : 0 ≤ b) (hab : b ≤ a) : 0 ≤ a - b := by + rw [← ofNat_toNatClampNeg _ hb, ← ofNat_toNatClampNeg _ (Int16.le_trans hb hab), + ← ofNat_sub _ _ (Int16.toNatClampNeg_le hab)] + exact Int16.zero_le_ofNat_of_lt (Nat.sub_lt_of_lt a.toNatClampNeg_lt) +theorem Int32.sub_nonneg_of_le {a b : Int32} (hb : 0 ≤ b) (hab : b ≤ a) : 0 ≤ a - b := by + rw [← ofNat_toNatClampNeg _ hb, ← ofNat_toNatClampNeg _ (Int32.le_trans hb hab), + ← ofNat_sub _ _ (Int32.toNatClampNeg_le hab)] + exact Int32.zero_le_ofNat_of_lt (Nat.sub_lt_of_lt a.toNatClampNeg_lt) +theorem Int64.sub_nonneg_of_le {a b : Int64} (hb : 0 ≤ b) (hab : b ≤ a) : 0 ≤ a - b := by + rw [← ofNat_toNatClampNeg _ hb, ← ofNat_toNatClampNeg _ (Int64.le_trans hb hab), + ← ofNat_sub _ _ (Int64.toNatClampNeg_le hab)] + exact Int64.zero_le_ofNat_of_lt (Nat.sub_lt_of_lt a.toNatClampNeg_lt) +theorem ISize.sub_nonneg_of_le {a b : ISize} (hb : 0 ≤ b) (hab : b ≤ a) : 0 ≤ a - b := by + rw [← ofNat_toNatClampNeg _ hb, ← ofNat_toNatClampNeg _ (ISize.le_trans hb hab), + ← ofNat_sub _ _ (ISize.toNatClampNeg_le hab)] + exact ISize.zero_le_ofNat_of_lt (Nat.sub_lt_of_lt a.toNatClampNeg_lt_two_pow_numBits) + +theorem Int8.toNatClampNeg_sub_of_le {a b : Int8} (hb : 0 ≤ b) (hab : b ≤ a) : + (a - b).toNatClampNeg = a.toNatClampNeg - b.toNatClampNeg := by + rw [← toNat_toUInt8_of_le (Int8.sub_nonneg_of_le hb hab), toUInt8_sub, + UInt8.toNat_sub_of_le _ _ (Int8.toUInt8_le hb hab), + ← toNat_toUInt8_of_le (Int8.le_trans hb hab), ← toNat_toUInt8_of_le hb] +theorem Int16.toNatClampNeg_sub_of_le {a b : Int16} (hb : 0 ≤ b) (hab : b ≤ a) : + (a - b).toNatClampNeg = a.toNatClampNeg - b.toNatClampNeg := by + rw [← toNat_toUInt16_of_le (Int16.sub_nonneg_of_le hb hab), toUInt16_sub, + UInt16.toNat_sub_of_le _ _ (Int16.toUInt16_le hb hab), + ← toNat_toUInt16_of_le (Int16.le_trans hb hab), ← toNat_toUInt16_of_le hb] +theorem Int32.toNatClampNeg_sub_of_le {a b : Int32} (hb : 0 ≤ b) (hab : b ≤ a) : + (a - b).toNatClampNeg = a.toNatClampNeg - b.toNatClampNeg := by + rw [← toNat_toUInt32_of_le (Int32.sub_nonneg_of_le hb hab), toUInt32_sub, + UInt32.toNat_sub_of_le _ _ (Int32.toUInt32_le hb hab), + ← toNat_toUInt32_of_le (Int32.le_trans hb hab), ← toNat_toUInt32_of_le hb] +theorem Int64.toNatClampNeg_sub_of_le {a b : Int64} (hb : 0 ≤ b) (hab : b ≤ a) : + (a - b).toNatClampNeg = a.toNatClampNeg - b.toNatClampNeg := by + rw [← toNat_toUInt64_of_le (Int64.sub_nonneg_of_le hb hab), toUInt64_sub, + UInt64.toNat_sub_of_le _ _ (Int64.toUInt64_le hb hab), + ← toNat_toUInt64_of_le (Int64.le_trans hb hab), ← toNat_toUInt64_of_le hb] +theorem ISize.toNatClampNeg_sub_of_le {a b : ISize} (hb : 0 ≤ b) (hab : b ≤ a) : + (a - b).toNatClampNeg = a.toNatClampNeg - b.toNatClampNeg := by + rw [← toNat_toUISize_of_le (ISize.sub_nonneg_of_le hb hab), toUSize_sub, + USize.toNat_sub_of_le _ _ (ISize.toUSize_le hb hab), + ← toNat_toUISize_of_le (ISize.le_trans hb hab), ← toNat_toUISize_of_le hb] + +theorem Int8.toInt_sub_of_le (a b : Int8) (hb : 0 ≤ b) (h : b ≤ a) : + (a - b).toInt = a.toInt - b.toInt := by + rw [Int8.toInt_eq_toNatClampNeg (Int8.sub_nonneg_of_le hb h), + Int8.toInt_eq_toNatClampNeg (Int8.le_trans hb h), Int8.toInt_eq_toNatClampNeg hb, + Int8.toNatClampNeg_sub_of_le hb h, Int.ofNat_sub] + exact Int8.toNatClampNeg_le h +theorem Int16.toInt_sub_of_le (a b : Int16) (hb : 0 ≤ b) (h : b ≤ a) : + (a - b).toInt = a.toInt - b.toInt := by + rw [Int16.toInt_eq_toNatClampNeg (Int16.sub_nonneg_of_le hb h), + Int16.toInt_eq_toNatClampNeg (Int16.le_trans hb h), Int16.toInt_eq_toNatClampNeg hb, + Int16.toNatClampNeg_sub_of_le hb h, Int.ofNat_sub] + exact Int16.toNatClampNeg_le h +theorem Int32.toInt_sub_of_le (a b : Int32) (hb : 0 ≤ b) (h : b ≤ a) : + (a - b).toInt = a.toInt - b.toInt := by + rw [Int32.toInt_eq_toNatClampNeg (Int32.sub_nonneg_of_le hb h), + Int32.toInt_eq_toNatClampNeg (Int32.le_trans hb h), Int32.toInt_eq_toNatClampNeg hb, + Int32.toNatClampNeg_sub_of_le hb h, Int.ofNat_sub] + exact Int32.toNatClampNeg_le h +theorem Int64.toInt_sub_of_le (a b : Int64) (hb : 0 ≤ b) (h : b ≤ a) : + (a - b).toInt = a.toInt - b.toInt := by + rw [Int64.toInt_eq_toNatClampNeg (Int64.sub_nonneg_of_le hb h), + Int64.toInt_eq_toNatClampNeg (Int64.le_trans hb h), Int64.toInt_eq_toNatClampNeg hb, + Int64.toNatClampNeg_sub_of_le hb h, Int.ofNat_sub] + exact Int64.toNatClampNeg_le h +theorem ISize.toInt_sub_of_le (a b : ISize) (hb : 0 ≤ b) (h : b ≤ a) : + (a - b).toInt = a.toInt - b.toInt := by + rw [ISize.toInt_eq_toNatClampNeg (ISize.sub_nonneg_of_le hb h), + ISize.toInt_eq_toNatClampNeg (ISize.le_trans hb h), ISize.toInt_eq_toNatClampNeg hb, + ISize.toNatClampNeg_sub_of_le hb h, Int.ofNat_sub] + exact ISize.toNatClampNeg_le h + +theorem Int8.sub_le {a b : Int8} (hb : 0 ≤ b) (hab : b ≤ a) : a - b ≤ a := by + simp_all [le_iff_toInt_le, Int8.toInt_sub_of_le _ _ hb hab]; omega +theorem Int16.sub_le {a b : Int16} (hb : 0 ≤ b) (hab : b ≤ a) : a - b ≤ a := by + simp_all [le_iff_toInt_le, Int16.toInt_sub_of_le _ _ hb hab]; omega +theorem Int32.sub_le {a b : Int32} (hb : 0 ≤ b) (hab : b ≤ a) : a - b ≤ a := by + simp_all [le_iff_toInt_le, Int32.toInt_sub_of_le _ _ hb hab]; omega +theorem Int64.sub_le {a b : Int64} (hb : 0 ≤ b) (hab : b ≤ a) : a - b ≤ a := by + simp_all [le_iff_toInt_le, Int64.toInt_sub_of_le _ _ hb hab]; omega +theorem ISize.sub_le {a b : ISize} (hb : 0 ≤ b) (hab : b ≤ a) : a - b ≤ a := by + simp_all [le_iff_toInt_le, ISize.toInt_sub_of_le _ _ hb hab]; omega + +theorem Int8.sub_lt {a b : Int8} (hb : 0 < b) (hab : b ≤ a) : a - b < a := by + simp_all [lt_iff_toInt_lt, Int8.toInt_sub_of_le _ _ (Int8.le_of_lt hb) hab]; omega +theorem Int16.sub_lt {a b : Int16} (hb : 0 < b) (hab : b ≤ a) : a - b < a := by + simp_all [lt_iff_toInt_lt, Int16.toInt_sub_of_le _ _ (Int16.le_of_lt hb) hab]; omega +theorem Int32.sub_lt {a b : Int32} (hb : 0 < b) (hab : b ≤ a) : a - b < a := by + simp_all [lt_iff_toInt_lt, Int32.toInt_sub_of_le _ _ (Int32.le_of_lt hb) hab]; omega +theorem Int64.sub_lt {a b : Int64} (hb : 0 < b) (hab : b ≤ a) : a - b < a := by + simp_all [lt_iff_toInt_lt, Int64.toInt_sub_of_le _ _ (Int64.le_of_lt hb) hab]; omega +theorem ISize.sub_lt {a b : ISize} (hb : 0 < b) (hab : b ≤ a) : a - b < a := by + simp_all [lt_iff_toInt_lt, ISize.toInt_sub_of_le _ _ (ISize.le_of_lt hb) hab]; omega diff --git a/src/Init/Data/UInt/Bitwise.lean b/src/Init/Data/UInt/Bitwise.lean index 4875077e24..bcbe7da88d 100644 --- a/src/Init/Data/UInt/Bitwise.lean +++ b/src/Init/Data/UInt/Bitwise.lean @@ -229,7 +229,6 @@ theorem Bool.toBitVec_toUSize {b : Bool} : @[simp] theorem USize.toFin_shiftLeft (a b : USize) (hb : b.toNat < System.Platform.numBits) : (a <<< b).toFin = a.toFin <<< b.toFin := Fin.val_inj.1 (by simp [Nat.mod_eq_of_lt (a := b.toNat) (b := System.Platform.numBits) hb]) - theorem UInt8.shiftLeft_eq_shiftLeft_mod (a b : UInt8) : a <<< b = a <<< (b % 8) := UInt8.toBitVec_inj.1 (by simp) theorem UInt16.shiftLeft_eq_shiftLeft_mod (a b : UInt16) : a <<< b = a <<< (b % 16) := UInt16.toBitVec_inj.1 (by simp) theorem UInt32.shiftLeft_eq_shiftLeft_mod (a b : UInt32) : a <<< b = a <<< (b % 32) := UInt32.toBitVec_inj.1 (by simp) @@ -423,3 +422,904 @@ theorem USize.toUInt64_shiftLeft_of_lt (a b : USize) (hb : b.toNat < System.Plat There is no reasonable statement for`UInt16.toUInt8_shiftRight`; in fact for `a b : UInt16` the expression `(a >>> b).toUInt8` is not a function of `a.toUInt8` and `b.toUInt8`. -/ + +@[simp] theorem UInt8.ofFin_and (a b : Fin UInt8.size) : UInt8.ofFin (a &&& b) = UInt8.ofFin a &&& UInt8.ofFin b := UInt8.toFin_inj.1 (by simp) +@[simp] theorem UInt16.ofFin_and (a b : Fin UInt16.size) : UInt16.ofFin (a &&& b) = UInt16.ofFin a &&& UInt16.ofFin b := UInt16.toFin_inj.1 (by simp) +@[simp] theorem UInt32.ofFin_and (a b : Fin UInt32.size) : UInt32.ofFin (a &&& b) = UInt32.ofFin a &&& UInt32.ofFin b := UInt32.toFin_inj.1 (by simp) +@[simp] theorem UInt64.ofFin_and (a b : Fin UInt64.size) : UInt64.ofFin (a &&& b) = UInt64.ofFin a &&& UInt64.ofFin b := UInt64.toFin_inj.1 (by simp) +@[simp] theorem USize.ofFin_and (a b : Fin USize.size) : USize.ofFin (a &&& b) = USize.ofFin a &&& USize.ofFin b := USize.toFin_inj.1 (by simp) + +@[simp] theorem UInt8.ofBitVec_and (a b : BitVec 8) : UInt8.ofBitVec (a &&& b) = UInt8.ofBitVec a &&& UInt8.ofBitVec b := rfl +@[simp] theorem UInt16.ofBitVec_and (a b : BitVec 16) : UInt16.ofBitVec (a &&& b) = UInt16.ofBitVec a &&& UInt16.ofBitVec b := rfl +@[simp] theorem UInt32.ofBitVec_and (a b : BitVec 32) : UInt32.ofBitVec (a &&& b) = UInt32.ofBitVec a &&& UInt32.ofBitVec b := rfl +@[simp] theorem UInt64.ofBitVec_and (a b : BitVec 64) : UInt64.ofBitVec (a &&& b) = UInt64.ofBitVec a &&& UInt64.ofBitVec b := rfl +@[simp] theorem USize.ofBitVec_and (a b : BitVec System.Platform.numBits) : USize.ofBitVec (a &&& b) = USize.ofBitVec a &&& USize.ofBitVec b := rfl + +@[simp] theorem UInt8.ofNat_and (a b : Nat) : UInt8.ofNat (a &&& b) = UInt8.ofNat a &&& UInt8.ofNat b := + UInt8.toBitVec_inj.1 (by simp [UInt8.toBitVec_ofNat']) +@[simp] theorem UInt16.ofNat_and (a b : Nat) : UInt16.ofNat (a &&& b) = UInt16.ofNat a &&& UInt16.ofNat b := + UInt16.toBitVec_inj.1 (by simp [UInt16.toBitVec_ofNat']) +@[simp] theorem UInt32.ofNat_and (a b : Nat) : UInt32.ofNat (a &&& b) = UInt32.ofNat a &&& UInt32.ofNat b := + UInt32.toBitVec_inj.1 (by simp [UInt32.toBitVec_ofNat']) +@[simp] theorem UInt64.ofNat_and (a b : Nat) : UInt64.ofNat (a &&& b) = UInt64.ofNat a &&& UInt64.ofNat b := + UInt64.toBitVec_inj.1 (by simp [UInt64.toBitVec_ofNat']) +@[simp] theorem USize.ofNat_and (a b : Nat) : USize.ofNat (a &&& b) = USize.ofNat a &&& USize.ofNat b := + USize.toBitVec_inj.1 (by simp [USize.toBitVec_ofNat']) + +@[simp] theorem UInt8.ofNatLT_and (a b : Nat) (ha : a < 2 ^ 8) (hb : b < 2 ^ 8) : + UInt8.ofNatLT (a &&& b) (Nat.and_lt_two_pow _ hb) = UInt8.ofNatLT a ha &&& UInt8.ofNatLT b hb := by + simp [UInt8.ofNatLT_eq_ofNat] +@[simp] theorem UInt16.ofNatLT_and (a b : Nat) (ha : a < 2 ^ 16) (hb : b < 2 ^ 16) : + UInt16.ofNatLT (a &&& b) (Nat.and_lt_two_pow _ hb) = UInt16.ofNatLT a ha &&& UInt16.ofNatLT b hb := by + simp [UInt16.ofNatLT_eq_ofNat] +@[simp] theorem UInt32.ofNatLT_and (a b : Nat) (ha : a < 2 ^ 32) (hb : b < 2 ^ 32) : + UInt32.ofNatLT (a &&& b) (Nat.and_lt_two_pow _ hb) = UInt32.ofNatLT a ha &&& UInt32.ofNatLT b hb := by + simp [UInt32.ofNatLT_eq_ofNat] +@[simp] theorem UInt64.ofNatLT_and (a b : Nat) (ha : a < 2 ^ 64) (hb : b < 2 ^ 64) : + UInt64.ofNatLT (a &&& b) (Nat.and_lt_two_pow _ hb) = UInt64.ofNatLT a ha &&& UInt64.ofNatLT b hb := by + simp [UInt64.ofNatLT_eq_ofNat] + +@[simp] theorem UInt8.ofFin_or (a b : Fin UInt8.size) : UInt8.ofFin (a ||| b) = UInt8.ofFin a ||| UInt8.ofFin b := UInt8.toFin_inj.1 (by simp) +@[simp] theorem UInt16.ofFin_or (a b : Fin UInt16.size) : UInt16.ofFin (a ||| b) = UInt16.ofFin a ||| UInt16.ofFin b := UInt16.toFin_inj.1 (by simp) +@[simp] theorem UInt32.ofFin_or (a b : Fin UInt32.size) : UInt32.ofFin (a ||| b) = UInt32.ofFin a ||| UInt32.ofFin b := UInt32.toFin_inj.1 (by simp) +@[simp] theorem UInt64.ofFin_or (a b : Fin UInt64.size) : UInt64.ofFin (a ||| b) = UInt64.ofFin a ||| UInt64.ofFin b := UInt64.toFin_inj.1 (by simp) +@[simp] theorem USize.ofFin_or (a b : Fin USize.size) : USize.ofFin (a ||| b) = USize.ofFin a ||| USize.ofFin b := USize.toFin_inj.1 (by simp) + +@[simp] theorem UInt8.ofBitVec_or (a b : BitVec 8) : UInt8.ofBitVec (a ||| b) = UInt8.ofBitVec a ||| UInt8.ofBitVec b := rfl +@[simp] theorem UInt16.ofBitVec_or (a b : BitVec 16) : UInt16.ofBitVec (a ||| b) = UInt16.ofBitVec a ||| UInt16.ofBitVec b := rfl +@[simp] theorem UInt32.ofBitVec_or (a b : BitVec 32) : UInt32.ofBitVec (a ||| b) = UInt32.ofBitVec a ||| UInt32.ofBitVec b := rfl +@[simp] theorem UInt64.ofBitVec_or (a b : BitVec 64) : UInt64.ofBitVec (a ||| b) = UInt64.ofBitVec a ||| UInt64.ofBitVec b := rfl +@[simp] theorem USize.ofBitVec_or (a b : BitVec System.Platform.numBits) : USize.ofBitVec (a ||| b) = USize.ofBitVec a ||| USize.ofBitVec b := rfl + +@[simp] theorem UInt8.ofNat_or (a b : Nat) : UInt8.ofNat (a ||| b) = UInt8.ofNat a ||| UInt8.ofNat b := + UInt8.toBitVec_inj.1 (by simp [UInt8.toBitVec_ofNat']) +@[simp] theorem UInt16.ofNat_or (a b : Nat) : UInt16.ofNat (a ||| b) = UInt16.ofNat a ||| UInt16.ofNat b := + UInt16.toBitVec_inj.1 (by simp [UInt16.toBitVec_ofNat']) +@[simp] theorem UInt32.ofNat_or (a b : Nat) : UInt32.ofNat (a ||| b) = UInt32.ofNat a ||| UInt32.ofNat b := + UInt32.toBitVec_inj.1 (by simp [UInt32.toBitVec_ofNat']) +@[simp] theorem UInt64.ofNat_or (a b : Nat) : UInt64.ofNat (a ||| b) = UInt64.ofNat a ||| UInt64.ofNat b := + UInt64.toBitVec_inj.1 (by simp [UInt64.toBitVec_ofNat']) +@[simp] theorem USize.ofNat_or (a b : Nat) : USize.ofNat (a ||| b) = USize.ofNat a ||| USize.ofNat b := + USize.toBitVec_inj.1 (by simp [USize.toBitVec_ofNat']) + +@[simp] theorem UInt8.ofNatLT_or (a b : Nat) (ha : a < 2 ^ 8) (hb : b < 2 ^ 8) : + UInt8.ofNatLT (a ||| b) (Nat.or_lt_two_pow ha hb) = UInt8.ofNatLT a ha ||| UInt8.ofNatLT b hb := by + simp [UInt8.ofNatLT_eq_ofNat] +@[simp] theorem UInt16.ofNatLT_or (a b : Nat) (ha : a < 2 ^ 16) (hb : b < 2 ^ 16) : + UInt16.ofNatLT (a ||| b) (Nat.or_lt_two_pow ha hb) = UInt16.ofNatLT a ha ||| UInt16.ofNatLT b hb := by + simp [UInt16.ofNatLT_eq_ofNat] +@[simp] theorem UInt32.ofNatLT_or (a b : Nat) (ha : a < 2 ^ 32) (hb : b < 2 ^ 32) : + UInt32.ofNatLT (a ||| b) (Nat.or_lt_two_pow ha hb) = UInt32.ofNatLT a ha ||| UInt32.ofNatLT b hb := by + simp [UInt32.ofNatLT_eq_ofNat] +@[simp] theorem UInt64.ofNatLT_or (a b : Nat) (ha : a < 2 ^ 64) (hb : b < 2 ^ 64) : + UInt64.ofNatLT (a ||| b) (Nat.or_lt_two_pow ha hb) = UInt64.ofNatLT a ha ||| UInt64.ofNatLT b hb := by + simp [UInt64.ofNatLT_eq_ofNat] + +@[simp] theorem UInt8.ofFin_xor (a b : Fin UInt8.size) : UInt8.ofFin (a ^^^ b) = UInt8.ofFin a ^^^ UInt8.ofFin b := UInt8.toFin_inj.1 (by simp) +@[simp] theorem UInt16.ofFin_xor (a b : Fin UInt16.size) : UInt16.ofFin (a ^^^ b) = UInt16.ofFin a ^^^ UInt16.ofFin b := UInt16.toFin_inj.1 (by simp) +@[simp] theorem UInt32.ofFin_xor (a b : Fin UInt32.size) : UInt32.ofFin (a ^^^ b) = UInt32.ofFin a ^^^ UInt32.ofFin b := UInt32.toFin_inj.1 (by simp) +@[simp] theorem UInt64.ofFin_xor (a b : Fin UInt64.size) : UInt64.ofFin (a ^^^ b) = UInt64.ofFin a ^^^ UInt64.ofFin b := UInt64.toFin_inj.1 (by simp) +@[simp] theorem USize.ofFin_xor (a b : Fin USize.size) : USize.ofFin (a ^^^ b) = USize.ofFin a ^^^ USize.ofFin b := USize.toFin_inj.1 (by simp) + +@[simp] theorem UInt8.ofBitVec_xor (a b : BitVec 8) : UInt8.ofBitVec (a ^^^ b) = UInt8.ofBitVec a ^^^ UInt8.ofBitVec b := rfl +@[simp] theorem UInt16.ofBitVec_xor (a b : BitVec 16) : UInt16.ofBitVec (a ^^^ b) = UInt16.ofBitVec a ^^^ UInt16.ofBitVec b := rfl +@[simp] theorem UInt32.ofBitVec_xor (a b : BitVec 32) : UInt32.ofBitVec (a ^^^ b) = UInt32.ofBitVec a ^^^ UInt32.ofBitVec b := rfl +@[simp] theorem UInt64.ofBitVec_xor (a b : BitVec 64) : UInt64.ofBitVec (a ^^^ b) = UInt64.ofBitVec a ^^^ UInt64.ofBitVec b := rfl +@[simp] theorem USize.ofBitVec_xor (a b : BitVec System.Platform.numBits) : USize.ofBitVec (a ^^^ b) = USize.ofBitVec a ^^^ USize.ofBitVec b := rfl + +@[simp] theorem UInt8.ofNat_xor (a b : Nat) : UInt8.ofNat (a ^^^ b) = UInt8.ofNat a ^^^ UInt8.ofNat b := + UInt8.toBitVec_inj.1 (by simp [UInt8.toBitVec_ofNat']) +@[simp] theorem UInt16.ofNat_xor (a b : Nat) : UInt16.ofNat (a ^^^ b) = UInt16.ofNat a ^^^ UInt16.ofNat b := + UInt16.toBitVec_inj.1 (by simp [UInt16.toBitVec_ofNat']) +@[simp] theorem UInt32.ofNat_xor (a b : Nat) : UInt32.ofNat (a ^^^ b) = UInt32.ofNat a ^^^ UInt32.ofNat b := + UInt32.toBitVec_inj.1 (by simp [UInt32.toBitVec_ofNat']) +@[simp] theorem UInt64.ofNat_xor (a b : Nat) : UInt64.ofNat (a ^^^ b) = UInt64.ofNat a ^^^ UInt64.ofNat b := + UInt64.toBitVec_inj.1 (by simp [UInt64.toBitVec_ofNat']) +@[simp] theorem USize.ofNat_xor (a b : Nat) : USize.ofNat (a ^^^ b) = USize.ofNat a ^^^ USize.ofNat b := + USize.toBitVec_inj.1 (by simp [USize.toBitVec_ofNat']) + +@[simp] theorem UInt8.ofNatLT_xor (a b : Nat) (ha : a < 2 ^ 8) (hb : b < 2 ^ 8) : + UInt8.ofNatLT (a ^^^ b) (Nat.xor_lt_two_pow ha hb) = UInt8.ofNatLT a ha ^^^ UInt8.ofNatLT b hb := by + simp [UInt8.ofNatLT_eq_ofNat] +@[simp] theorem UInt16.ofNatLT_xor (a b : Nat) (ha : a < 2 ^ 16) (hb : b < 2 ^ 16) : + UInt16.ofNatLT (a ^^^ b) (Nat.xor_lt_two_pow ha hb) = UInt16.ofNatLT a ha ^^^ UInt16.ofNatLT b hb := by + simp [UInt16.ofNatLT_eq_ofNat] +@[simp] theorem UInt32.ofNatLT_xor (a b : Nat) (ha : a < 2 ^ 32) (hb : b < 2 ^ 32) : + UInt32.ofNatLT (a ^^^ b) (Nat.xor_lt_two_pow ha hb) = UInt32.ofNatLT a ha ^^^ UInt32.ofNatLT b hb := by + simp [UInt32.ofNatLT_eq_ofNat] +@[simp] theorem UInt64.ofNatLT_xor (a b : Nat) (ha : a < 2 ^ 64) (hb : b < 2 ^ 64) : + UInt64.ofNatLT (a ^^^ b) (Nat.xor_lt_two_pow ha hb) = UInt64.ofNatLT a ha ^^^ UInt64.ofNatLT b hb := by + simp [UInt64.ofNatLT_eq_ofNat] + +@[simp] theorem UInt8.ofBitVec_not (a : BitVec 8) : UInt8.ofBitVec (~~~a) = ~~~UInt8.ofBitVec a := rfl +@[simp] theorem UInt16.ofBitVec_not (a : BitVec 16) : UInt16.ofBitVec (~~~a) = ~~~UInt16.ofBitVec a := rfl +@[simp] theorem UInt32.ofBitVec_not (a : BitVec 32) : UInt32.ofBitVec (~~~a) = ~~~UInt32.ofBitVec a := rfl +@[simp] theorem UInt64.ofBitVec_not (a : BitVec 64) : UInt64.ofBitVec (~~~a) = ~~~UInt64.ofBitVec a := rfl +@[simp] theorem USize.ofBitVec_not (a : BitVec System.Platform.numBits) : USize.ofBitVec (~~~a) = ~~~USize.ofBitVec a := rfl + +@[simp] theorem UInt8.ofFin_rev (a : Fin UInt8.size) : UInt8.ofFin a.rev = ~~~UInt8.ofFin a := UInt8.toFin_inj.1 (by simp) +@[simp] theorem UInt16.ofFin_rev (a : Fin UInt16.size) : UInt16.ofFin a.rev = ~~~UInt16.ofFin a := UInt16.toFin_inj.1 (by simp) +@[simp] theorem UInt32.ofFin_rev (a : Fin UInt32.size) : UInt32.ofFin a.rev = ~~~UInt32.ofFin a := UInt32.toFin_inj.1 (by simp) +@[simp] theorem UInt64.ofFin_rev (a : Fin UInt64.size) : UInt64.ofFin a.rev = ~~~UInt64.ofFin a := UInt64.toFin_inj.1 (by simp) +@[simp] theorem USize.ofFin_rev (a : Fin USize.size) : USize.ofFin a.rev = ~~~USize.ofFin a := USize.toFin_inj.1 (by simp) + +@[simp] theorem UInt8.ofBitVec_shiftLeft (a : BitVec 8) (b : Nat) (hb : b < 8) : UInt8.ofBitVec (a <<< b) = UInt8.ofBitVec a <<< UInt8.ofNat b := + UInt8.toBitVec_inj.1 (by simp [Nat.mod_eq_of_lt hb]) +@[simp] theorem UInt16.ofBitVec_shiftLeft (a : BitVec 16) (b : Nat) (hb : b < 16) : UInt16.ofBitVec (a <<< b) = UInt16.ofBitVec a <<< UInt16.ofNat b := + UInt16.toBitVec_inj.1 (by simp [Nat.mod_eq_of_lt hb]) +@[simp] theorem UInt32.ofBitVec_shiftLeft (a : BitVec 32) (b : Nat) (hb : b < 32) : UInt32.ofBitVec (a <<< b) = UInt32.ofBitVec a <<< UInt32.ofNat b := + UInt32.toBitVec_inj.1 (by simp [Nat.mod_eq_of_lt hb]) +@[simp] theorem UInt64.ofBitVec_shiftLeft (a : BitVec 64) (b : Nat) (hb : b < 64) : UInt64.ofBitVec (a <<< b) = UInt64.ofBitVec a <<< UInt64.ofNat b := + UInt64.toBitVec_inj.1 (by simp [Nat.mod_eq_of_lt hb]) +@[simp] theorem USize.ofBitVec_shiftLeft (a : BitVec System.Platform.numBits) (b : Nat) (hb : b < System.Platform.numBits) : + USize.ofBitVec (a <<< b) = USize.ofBitVec a <<< USize.ofNat b := by + apply USize.toBitVec_inj.1 + simp only [USize.toBitVec_shiftLeft, BitVec.natCast_eq_ofNat, BitVec.shiftLeft_eq', + BitVec.toNat_umod, toNat_toBitVec, toNat_ofNat', BitVec.toNat_ofNat, Nat.mod_two_pow_self] + rw [Nat.mod_mod_of_dvd _ (by cases System.Platform.numBits_eq <;> simp_all), Nat.mod_eq_of_lt hb] + +@[simp] theorem UInt8.ofBitVec_shiftLeft_mod (a : BitVec 8) (b : Nat) : UInt8.ofBitVec (a <<< (b % 8)) = UInt8.ofBitVec a <<< UInt8.ofNat b := + UInt8.toBitVec_inj.1 (by simp) +@[simp] theorem UInt16.ofBitVec_shiftLeft_mod (a : BitVec 16) (b : Nat) : UInt16.ofBitVec (a <<< (b % 16)) = UInt16.ofBitVec a <<< UInt16.ofNat b := + UInt16.toBitVec_inj.1 (by simp) +@[simp] theorem UInt32.ofBitVec_shiftLeft_mod (a : BitVec 32) (b : Nat) : UInt32.ofBitVec (a <<< (b % 32)) = UInt32.ofBitVec a <<< UInt32.ofNat b := + UInt32.toBitVec_inj.1 (by simp) +@[simp] theorem UInt64.ofBitVec_shiftLeft_mod (a : BitVec 64) (b : Nat) : UInt64.ofBitVec (a <<< (b % 64)) = UInt64.ofBitVec a <<< UInt64.ofNat b := + UInt64.toBitVec_inj.1 (by simp) +@[simp] theorem USize.ofBitVec_shiftLeft_mod (a : BitVec System.Platform.numBits) (b : Nat) : + USize.ofBitVec (a <<< (b % System.Platform.numBits)) = USize.ofBitVec a <<< USize.ofNat b := by + apply USize.toBitVec_inj.1 + simp only [USize.toBitVec_shiftLeft, BitVec.natCast_eq_ofNat, BitVec.shiftLeft_eq', + BitVec.toNat_umod, toNat_toBitVec, toNat_ofNat', BitVec.toNat_ofNat, Nat.mod_two_pow_self] + rw [Nat.mod_mod_of_dvd _ (by cases System.Platform.numBits_eq <;> simp_all)] + +@[simp] theorem UInt8.ofFin_shiftLeft (a b : Fin UInt8.size) (hb : b < 8) : UInt8.ofFin (a <<< b) = UInt8.ofFin a <<< UInt8.ofFin b := + UInt8.toFin_inj.1 (by simp [UInt8.toFin_shiftLeft (ofFin a) (ofFin b) hb]) +@[simp] theorem UInt16.ofFin_shiftLeft (a b : Fin UInt16.size) (hb : b < 16) : UInt16.ofFin (a <<< b) = UInt16.ofFin a <<< UInt16.ofFin b := + UInt16.toFin_inj.1 (by simp [UInt16.toFin_shiftLeft (ofFin a) (ofFin b) hb]) +@[simp] theorem UInt32.ofFin_shiftLeft (a b : Fin UInt32.size) (hb : b < 32) : UInt32.ofFin (a <<< b) = UInt32.ofFin a <<< UInt32.ofFin b := + UInt32.toFin_inj.1 (by simp [UInt32.toFin_shiftLeft (ofFin a) (ofFin b) hb]) +@[simp] theorem UInt64.ofFin_shiftLeft (a b : Fin UInt64.size) (hb : b < 64) : UInt64.ofFin (a <<< b) = UInt64.ofFin a <<< UInt64.ofFin b := + UInt64.toFin_inj.1 (by simp [UInt64.toFin_shiftLeft (ofFin a) (ofFin b) hb]) +@[simp] theorem USize.ofFin_shiftLeft (a b : Fin USize.size) (hb : b < System.Platform.numBits) : USize.ofFin (a <<< b) = USize.ofFin a <<< USize.ofFin b := + USize.toFin_inj.1 (by simp [USize.toFin_shiftLeft (ofFin a) (ofFin b) hb]) + +@[simp] theorem UInt8.ofFin_shiftLeft_mod (a b : Fin UInt8.size) : UInt8.ofFin (a <<< (b % 8)) = UInt8.ofFin a <<< UInt8.ofFin b := + UInt8.toNat_inj.1 (by simp; rfl) +@[simp] theorem UInt16.ofFin_shiftLeft_mod (a b : Fin UInt16.size) : UInt16.ofFin (a <<< (b % 16)) = UInt16.ofFin a <<< UInt16.ofFin b := + UInt16.toNat_inj.1 (by simp; rfl) +@[simp] theorem UInt32.ofFin_shiftLeft_mod (a b : Fin UInt32.size) : UInt32.ofFin (a <<< (b % 32)) = UInt32.ofFin a <<< UInt32.ofFin b := + UInt32.toNat_inj.1 (by simp; rfl) +@[simp] theorem UInt64.ofFin_shiftLeft_mod (a b : Fin UInt64.size) : UInt64.ofFin (a <<< (b % 64)) = UInt64.ofFin a <<< UInt64.ofFin b := + UInt64.toNat_inj.1 (by simp; rfl) +@[simp] theorem USize.ofFin_shiftLeft_mod (a b : Fin USize.size) : + USize.ofFin (a <<< (b % ⟨System.Platform.numBits, by cases System.Platform.numBits_eq <;> simp_all [USize.size]⟩)) = USize.ofFin a <<< USize.ofFin b := by + apply USize.toFin_inj.1 + rw [toFin_ofFin, USize.shiftLeft_eq_shiftLeft_mod, USize.toFin_shiftLeft, toFin_ofFin, USize.toFin_mod, + toFin_ofFin, toFin_ofNat', ← Fin.ofNat'_val_eq_self ⟨System.Platform.numBits, _⟩] + rw [USize.toNat_mod, toNat_ofNat'] + cases System.Platform.numBits_eq <;> simpa [*] using Nat.mod_lt _ (by decide) + +@[simp] theorem UInt8.ofNat_shiftLeft (a b : Nat) (hb : b < 8) : + UInt8.ofNat (a <<< b) = UInt8.ofNat a <<< UInt8.ofNat b := by + rw [UInt8.ofNat_eq_iff_mod_eq_toNat, UInt8.toNat_shiftLeft, toNat_ofNat', toNat_ofNat', + Nat.mod_mod_of_dvd _ (by decide), Nat.mod_eq_of_lt hb, Nat.mod_two_pow_shiftLeft_mod_two_pow] +@[simp] theorem UInt16.ofNat_shiftLeft (a b : Nat) (hb : b < 16) : + UInt16.ofNat (a <<< b) = UInt16.ofNat a <<< UInt16.ofNat b := by + rw [UInt16.ofNat_eq_iff_mod_eq_toNat, UInt16.toNat_shiftLeft, toNat_ofNat', toNat_ofNat', + Nat.mod_mod_of_dvd _ (by decide), Nat.mod_eq_of_lt hb, Nat.mod_two_pow_shiftLeft_mod_two_pow] +@[simp] theorem UInt32.ofNat_shiftLeft (a b : Nat) (hb : b < 32) : + UInt32.ofNat (a <<< b) = UInt32.ofNat a <<< UInt32.ofNat b := by + rw [UInt32.ofNat_eq_iff_mod_eq_toNat, UInt32.toNat_shiftLeft, toNat_ofNat', toNat_ofNat', + Nat.mod_mod_of_dvd _ (by decide), Nat.mod_eq_of_lt hb, Nat.mod_two_pow_shiftLeft_mod_two_pow] +@[simp] theorem UInt64.ofNat_shiftLeft (a b : Nat) (hb : b < 64) : + UInt64.ofNat (a <<< b) = UInt64.ofNat a <<< UInt64.ofNat b := by + rw [UInt64.ofNat_eq_iff_mod_eq_toNat, UInt64.toNat_shiftLeft, toNat_ofNat', toNat_ofNat', + Nat.mod_mod_of_dvd _ (by decide), Nat.mod_eq_of_lt hb, Nat.mod_two_pow_shiftLeft_mod_two_pow] +@[simp] theorem USize.ofNat_shiftLeft (a b : Nat) (hb : b < System.Platform.numBits) : + USize.ofNat (a <<< b) = USize.ofNat a <<< USize.ofNat b := by + rw [USize.ofNat_eq_iff_mod_eq_toNat, USize.toNat_shiftLeft, toNat_ofNat', toNat_ofNat', + Nat.mod_mod_of_dvd _ _, Nat.mod_eq_of_lt hb, Nat.mod_two_pow_shiftLeft_mod_two_pow] + cases System.Platform.numBits_eq <;> simp_all + +@[simp] theorem UInt8.ofNatLT_shiftLeft {a b : Nat} (ha : a <<< b < UInt8.size) (hb : b < 8) : + UInt8.ofNatLT (a <<< b) ha = UInt8.ofNatLT a (Nat.lt_of_shiftLeft_lt ha) <<< UInt8.ofNatLT b (Nat.lt_trans hb (by decide)) := by + simp [UInt8.ofNatLT_eq_ofNat, UInt8.ofNat_shiftLeft a b hb] +@[simp] theorem UInt16.ofNatLT_shiftLeft {a b : Nat} (ha : a <<< b < UInt16.size) (hb : b < 16) : + UInt16.ofNatLT (a <<< b) ha = UInt16.ofNatLT a (Nat.lt_of_shiftLeft_lt ha) <<< UInt16.ofNatLT b (Nat.lt_trans hb (by decide)) := by + simp [UInt16.ofNatLT_eq_ofNat, UInt16.ofNat_shiftLeft a b hb] +@[simp] theorem UInt32.ofNatLT_shiftLeft {a b : Nat} (ha : a <<< b < UInt32.size) (hb : b < 32) : + UInt32.ofNatLT (a <<< b) ha = UInt32.ofNatLT a (Nat.lt_of_shiftLeft_lt ha) <<< UInt32.ofNatLT b (Nat.lt_trans hb (by decide)) := by + simp [UInt32.ofNatLT_eq_ofNat, UInt32.ofNat_shiftLeft a b hb] +@[simp] theorem UInt64.ofNatLT_shiftLeft {a b : Nat} (ha : a <<< b < UInt64.size) (hb : b < 64) : + UInt64.ofNatLT (a <<< b) ha = UInt64.ofNatLT a (Nat.lt_of_shiftLeft_lt ha) <<< UInt64.ofNatLT b (Nat.lt_trans hb (by decide)) := by + simp [UInt64.ofNatLT_eq_ofNat, UInt64.ofNat_shiftLeft a b hb] +@[simp] theorem USize.ofNatLT_shiftLeft {a b : Nat} (ha : a <<< b < USize.size) (hb : b < System.Platform.numBits) : + USize.ofNatLT (a <<< b) ha = USize.ofNatLT a (Nat.lt_of_shiftLeft_lt ha) <<< USize.ofNatLT b (Nat.lt_trans hb Nat.lt_two_pow_self) := by + simp [USize.ofNatLT_eq_ofNat, USize.ofNat_shiftLeft a b hb] + +@[simp] theorem UInt8.ofBitVec_shiftRight (a : BitVec 8) (b : Nat) (hb : b < 8) : UInt8.ofBitVec (a >>> b) = UInt8.ofBitVec a >>> UInt8.ofNat b := + UInt8.toBitVec_inj.1 (by simp [Nat.mod_eq_of_lt hb]) +@[simp] theorem UInt16.ofBitVec_shiftRight (a : BitVec 16) (b : Nat) (hb : b < 16) : UInt16.ofBitVec (a >>> b) = UInt16.ofBitVec a >>> UInt16.ofNat b := + UInt16.toBitVec_inj.1 (by simp [Nat.mod_eq_of_lt hb]) +@[simp] theorem UInt32.ofBitVec_shiftRight (a : BitVec 32) (b : Nat) (hb : b < 32) : UInt32.ofBitVec (a >>> b) = UInt32.ofBitVec a >>> UInt32.ofNat b := + UInt32.toBitVec_inj.1 (by simp [Nat.mod_eq_of_lt hb]) +@[simp] theorem UInt64.ofBitVec_shiftRight (a : BitVec 64) (b : Nat) (hb : b < 64) : UInt64.ofBitVec (a >>> b) = UInt64.ofBitVec a >>> UInt64.ofNat b := + UInt64.toBitVec_inj.1 (by simp [Nat.mod_eq_of_lt hb]) +@[simp] theorem USize.ofBitVec_shiftRight (a : BitVec System.Platform.numBits) (b : Nat) (hb : b < System.Platform.numBits) : + USize.ofBitVec (a >>> b) = USize.ofBitVec a >>> USize.ofNat b := by + apply USize.toBitVec_inj.1 + simp only [USize.toBitVec_shiftRight, BitVec.natCast_eq_ofNat, BitVec.ushiftRight_eq', + BitVec.toNat_umod, toNat_toBitVec, toNat_ofNat', BitVec.toNat_ofNat, Nat.mod_two_pow_self] + rw [Nat.mod_mod_of_dvd _ (by cases System.Platform.numBits_eq <;> simp_all), Nat.mod_eq_of_lt hb] + +@[simp] theorem UInt8.ofBitVec_shiftRight_mod (a : BitVec 8) (b : Nat) : UInt8.ofBitVec (a >>> (b % 8)) = UInt8.ofBitVec a >>> UInt8.ofNat b := + UInt8.toBitVec_inj.1 (by simp) +@[simp] theorem UInt16.ofBitVec_shiftRight_mod (a : BitVec 16) (b : Nat) : UInt16.ofBitVec (a >>> (b % 16)) = UInt16.ofBitVec a >>> UInt16.ofNat b := + UInt16.toBitVec_inj.1 (by simp) +@[simp] theorem UInt32.ofBitVec_shiftRight_mod (a : BitVec 32) (b : Nat) : UInt32.ofBitVec (a >>> (b % 32)) = UInt32.ofBitVec a >>> UInt32.ofNat b := + UInt32.toBitVec_inj.1 (by simp) +@[simp] theorem UInt64.ofBitVec_shiftRight_mod (a : BitVec 64) (b : Nat) : UInt64.ofBitVec (a >>> (b % 64)) = UInt64.ofBitVec a >>> UInt64.ofNat b := + UInt64.toBitVec_inj.1 (by simp) +@[simp] theorem USize.ofBitVec_shiftRight_mod (a : BitVec System.Platform.numBits) (b : Nat) : + USize.ofBitVec (a >>> (b % System.Platform.numBits)) = USize.ofBitVec a >>> USize.ofNat b := by + apply USize.toBitVec_inj.1 + simp only [USize.toBitVec_shiftRight, BitVec.natCast_eq_ofNat, BitVec.ushiftRight_eq', + BitVec.toNat_umod, toNat_toBitVec, toNat_ofNat', BitVec.toNat_ofNat, Nat.mod_two_pow_self] + rw [Nat.mod_mod_of_dvd _ (by cases System.Platform.numBits_eq <;> simp_all)] + +@[simp] theorem UInt8.ofFin_shiftRight (a b : Fin UInt8.size) (hb : b < 8) : UInt8.ofFin (a >>> b) = UInt8.ofFin a >>> UInt8.ofFin b := + UInt8.toFin_inj.1 (by simp [UInt8.toFin_shiftRight (ofFin a) (ofFin b) hb]) +@[simp] theorem UInt16.ofFin_shiftRight (a b : Fin UInt16.size) (hb : b < 16) : UInt16.ofFin (a >>> b) = UInt16.ofFin a >>> UInt16.ofFin b := + UInt16.toFin_inj.1 (by simp [UInt16.toFin_shiftRight (ofFin a) (ofFin b) hb]) +@[simp] theorem UInt32.ofFin_shiftRight (a b : Fin UInt32.size) (hb : b < 32) : UInt32.ofFin (a >>> b) = UInt32.ofFin a >>> UInt32.ofFin b := + UInt32.toFin_inj.1 (by simp [UInt32.toFin_shiftRight (ofFin a) (ofFin b) hb]) +@[simp] theorem UInt64.ofFin_shiftRight (a b : Fin UInt64.size) (hb : b < 64) : UInt64.ofFin (a >>> b) = UInt64.ofFin a >>> UInt64.ofFin b := + UInt64.toFin_inj.1 (by simp [UInt64.toFin_shiftRight (ofFin a) (ofFin b) hb]) +@[simp] theorem USize.ofFin_shiftRight (a b : Fin USize.size) (hb : b < System.Platform.numBits) : USize.ofFin (a >>> b) = USize.ofFin a >>> USize.ofFin b := + USize.toFin_inj.1 (by simp [USize.toFin_shiftRight (ofFin a) (ofFin b) hb]) + +@[simp] theorem UInt8.ofFin_shiftRight_mod (a b : Fin UInt8.size) : UInt8.ofFin (a >>> (b % 8)) = UInt8.ofFin a >>> UInt8.ofFin b := + UInt8.toNat_inj.1 (by simp; rfl) +@[simp] theorem UInt16.ofFin_shiftRight_mod (a b : Fin UInt16.size) : UInt16.ofFin (a >>> (b % 16)) = UInt16.ofFin a >>> UInt16.ofFin b := + UInt16.toNat_inj.1 (by simp; rfl) +@[simp] theorem UInt32.ofFin_shiftRight_mod (a b : Fin UInt32.size) : UInt32.ofFin (a >>> (b % 32)) = UInt32.ofFin a >>> UInt32.ofFin b := + UInt32.toNat_inj.1 (by simp; rfl) +@[simp] theorem UInt64.ofFin_shiftRight_mod (a b : Fin UInt64.size) : UInt64.ofFin (a >>> (b % 64)) = UInt64.ofFin a >>> UInt64.ofFin b := + UInt64.toNat_inj.1 (by simp; rfl) +@[simp] theorem USize.ofFin_shiftRight_mod (a b : Fin USize.size) : + USize.ofFin (a >>> (b % ⟨System.Platform.numBits, by cases System.Platform.numBits_eq <;> simp_all [USize.size]⟩)) = USize.ofFin a >>> USize.ofFin b := by + apply USize.toFin_inj.1 + rw [toFin_ofFin, USize.shiftRight_eq_shiftRight_mod, USize.toFin_shiftRight, toFin_ofFin, USize.toFin_mod, + toFin_ofFin, toFin_ofNat', ← Fin.ofNat'_val_eq_self ⟨System.Platform.numBits, _⟩] + rw [USize.toNat_mod, toNat_ofNat'] + cases System.Platform.numBits_eq <;> simpa [*] using Nat.mod_lt _ (by decide) + +theorem UInt8.neg_eq_not_add (a : UInt8) : -a = ~~~a + 1 := UInt8.toBitVec_inj.1 (BitVec.neg_eq_not_add _) +theorem UInt16.neg_eq_not_add (a : UInt16) : -a = ~~~a + 1 := UInt16.toBitVec_inj.1 (BitVec.neg_eq_not_add _) +theorem UInt32.neg_eq_not_add (a : UInt32) : -a = ~~~a + 1 := UInt32.toBitVec_inj.1 (BitVec.neg_eq_not_add _) +theorem UInt64.neg_eq_not_add (a : UInt64) : -a = ~~~a + 1 := UInt64.toBitVec_inj.1 (BitVec.neg_eq_not_add _) +theorem USize.neg_eq_not_add (a : USize) : -a = ~~~a + 1 := USize.toBitVec_inj.1 (BitVec.neg_eq_not_add _) + +theorem UInt8.not_eq_neg_sub (a : UInt8) : ~~~a = -a - 1 := UInt8.toBitVec_inj.1 (BitVec.not_eq_neg_add _) +theorem UInt16.not_eq_neg_sub (a : UInt16) : ~~~a = -a - 1 := UInt16.toBitVec_inj.1 (BitVec.not_eq_neg_add _) +theorem UInt32.not_eq_neg_sub (a : UInt32) : ~~~a = -a - 1 := UInt32.toBitVec_inj.1 (BitVec.not_eq_neg_add _) +theorem UInt64.not_eq_neg_sub (a : UInt64) : ~~~a = -a - 1 := UInt64.toBitVec_inj.1 (BitVec.not_eq_neg_add _) +theorem USize.not_eq_neg_sub (a : USize) : ~~~a = -a - 1 := USize.toBitVec_inj.1 (BitVec.not_eq_neg_add _) + +theorem UInt8.or_assoc (a b c : UInt8) : a ||| b ||| c = a ||| (b ||| c) := UInt8.toBitVec_inj.1 (BitVec.or_assoc _ _ _) +theorem UInt16.or_assoc (a b c : UInt16) : a ||| b ||| c = a ||| (b ||| c) := UInt16.toBitVec_inj.1 (BitVec.or_assoc _ _ _) +theorem UInt32.or_assoc (a b c : UInt32) : a ||| b ||| c = a ||| (b ||| c) := UInt32.toBitVec_inj.1 (BitVec.or_assoc _ _ _) +theorem UInt64.or_assoc (a b c : UInt64) : a ||| b ||| c = a ||| (b ||| c) := UInt64.toBitVec_inj.1 (BitVec.or_assoc _ _ _) +theorem USize.or_assoc (a b c : USize) : a ||| b ||| c = a ||| (b ||| c) := USize.toBitVec_inj.1 (BitVec.or_assoc _ _ _) + +instance : Std.Associative (α := UInt8) (· ||| ·) := ⟨UInt8.or_assoc⟩ +instance : Std.Associative (α := UInt16) (· ||| ·) := ⟨UInt16.or_assoc⟩ +instance : Std.Associative (α := UInt32) (· ||| ·) := ⟨UInt32.or_assoc⟩ +instance : Std.Associative (α := UInt64) (· ||| ·) := ⟨UInt64.or_assoc⟩ +instance : Std.Associative (α := USize) (· ||| ·) := ⟨USize.or_assoc⟩ + +theorem UInt8.or_comm (a b : UInt8) : a ||| b = b ||| a := UInt8.toBitVec_inj.1 (BitVec.or_comm _ _) +theorem UInt16.or_comm (a b : UInt16) : a ||| b = b ||| a := UInt16.toBitVec_inj.1 (BitVec.or_comm _ _) +theorem UInt32.or_comm (a b : UInt32) : a ||| b = b ||| a := UInt32.toBitVec_inj.1 (BitVec.or_comm _ _) +theorem UInt64.or_comm (a b : UInt64) : a ||| b = b ||| a := UInt64.toBitVec_inj.1 (BitVec.or_comm _ _) +theorem USize.or_comm (a b : USize) : a ||| b = b ||| a := USize.toBitVec_inj.1 (BitVec.or_comm _ _) + +instance : Std.Commutative (α := UInt8) (· ||| ·) := ⟨UInt8.or_comm⟩ +instance : Std.Commutative (α := UInt16) (· ||| ·) := ⟨UInt16.or_comm⟩ +instance : Std.Commutative (α := UInt32) (· ||| ·) := ⟨UInt32.or_comm⟩ +instance : Std.Commutative (α := UInt64) (· ||| ·) := ⟨UInt64.or_comm⟩ +instance : Std.Commutative (α := USize) (· ||| ·) := ⟨USize.or_comm⟩ + +@[simp] theorem UInt8.or_self {a : UInt8} : a ||| a = a := UInt8.toBitVec_inj.1 BitVec.or_self +@[simp] theorem UInt16.or_self {a : UInt16} : a ||| a = a := UInt16.toBitVec_inj.1 BitVec.or_self +@[simp] theorem UInt32.or_self {a : UInt32} : a ||| a = a := UInt32.toBitVec_inj.1 BitVec.or_self +@[simp] theorem UInt64.or_self {a : UInt64} : a ||| a = a := UInt64.toBitVec_inj.1 BitVec.or_self +@[simp] theorem USize.or_self {a : USize} : a ||| a = a := USize.toBitVec_inj.1 BitVec.or_self + +instance : Std.IdempotentOp (α := UInt8) (· ||| ·) := ⟨fun _ => UInt8.or_self⟩ +instance : Std.IdempotentOp (α := UInt16) (· ||| ·) := ⟨fun _ => UInt16.or_self⟩ +instance : Std.IdempotentOp (α := UInt32) (· ||| ·) := ⟨fun _ => UInt32.or_self⟩ +instance : Std.IdempotentOp (α := UInt64) (· ||| ·) := ⟨fun _ => UInt64.or_self⟩ +instance : Std.IdempotentOp (α := USize) (· ||| ·) := ⟨fun _ => USize.or_self⟩ + +@[simp] theorem UInt8.or_zero {a : UInt8} : a ||| 0 = a := UInt8.toBitVec_inj.1 BitVec.or_zero +@[simp] theorem UInt16.or_zero {a : UInt16} : a ||| 0 = a := UInt16.toBitVec_inj.1 BitVec.or_zero +@[simp] theorem UInt32.or_zero {a : UInt32} : a ||| 0 = a := UInt32.toBitVec_inj.1 BitVec.or_zero +@[simp] theorem UInt64.or_zero {a : UInt64} : a ||| 0 = a := UInt64.toBitVec_inj.1 BitVec.or_zero +@[simp] theorem USize.or_zero {a : USize} : a ||| 0 = a := USize.toBitVec_inj.1 BitVec.or_zero + +@[simp] theorem UInt8.zero_or {a : UInt8} : 0 ||| a = a := UInt8.toBitVec_inj.1 BitVec.zero_or +@[simp] theorem UInt16.zero_or {a : UInt16} : 0 ||| a = a := UInt16.toBitVec_inj.1 BitVec.zero_or +@[simp] theorem UInt32.zero_or {a : UInt32} : 0 ||| a = a := UInt32.toBitVec_inj.1 BitVec.zero_or +@[simp] theorem UInt64.zero_or {a : UInt64} : 0 ||| a = a := UInt64.toBitVec_inj.1 BitVec.zero_or +@[simp] theorem USize.zero_or {a : USize} : 0 ||| a = a := USize.toBitVec_inj.1 BitVec.zero_or + +instance : Std.LawfulCommIdentity (α := UInt8) (· ||| ·) 0 where + right_id _ := UInt8.or_zero +instance : Std.LawfulCommIdentity (α := UInt16) (· ||| ·) 0 where + right_id _ := UInt16.or_zero +instance : Std.LawfulCommIdentity (α := UInt32) (· ||| ·) 0 where + right_id _ := UInt32.or_zero +instance : Std.LawfulCommIdentity (α := UInt64) (· ||| ·) 0 where + right_id _ := UInt64.or_zero +instance : Std.LawfulCommIdentity (α := USize) (· ||| ·) 0 where + right_id _ := USize.or_zero + +@[simp] theorem UInt8.neg_one_or {a : UInt8} : -1 ||| a = -1 := by + rw [← UInt8.toBitVec_inj, UInt8.toBitVec_or, UInt8.toBitVec_neg, UInt8.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_or] +@[simp] theorem UInt16.neg_one_or {a : UInt16} : -1 ||| a = -1 := by + rw [← UInt16.toBitVec_inj, UInt16.toBitVec_or, UInt16.toBitVec_neg, UInt16.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_or] +@[simp] theorem UInt32.neg_one_or {a : UInt32} : -1 ||| a = -1 := by + rw [← UInt32.toBitVec_inj, UInt32.toBitVec_or, UInt32.toBitVec_neg, UInt32.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_or] +@[simp] theorem UInt64.neg_one_or {a : UInt64} : -1 ||| a = -1 := by + rw [← UInt64.toBitVec_inj, UInt64.toBitVec_or, UInt64.toBitVec_neg, UInt64.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_or] +@[simp] theorem USize.neg_one_or {a : USize} : -1 ||| a = -1 := by + rw [← USize.toBitVec_inj, USize.toBitVec_or, USize.toBitVec_neg, USize.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_or] + +@[simp] theorem UInt8.or_neg_one {a : UInt8} : a ||| -1 = -1 := by rw [or_comm, neg_one_or] +@[simp] theorem UInt16.or_neg_one {a : UInt16} : a ||| -1 = -1 := by rw [or_comm, neg_one_or] +@[simp] theorem UInt32.or_neg_one {a : UInt32} : a ||| -1 = -1 := by rw [or_comm, neg_one_or] +@[simp] theorem UInt64.or_neg_one {a : UInt64} : a ||| -1 = -1 := by rw [or_comm, neg_one_or] +@[simp] theorem USize.or_neg_one {a : USize} : a ||| -1 = -1 := by rw [or_comm, neg_one_or] + +@[simp] theorem UInt8.or_eq_zero_iff {a b : UInt8} : a ||| b = 0 ↔ a = 0 ∧ b = 0 := by + simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.or_eq_zero_iff {a b : UInt16} : a ||| b = 0 ↔ a = 0 ∧ b = 0 := by + simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.or_eq_zero_iff {a b : UInt32} : a ||| b = 0 ↔ a = 0 ∧ b = 0 := by + simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.or_eq_zero_iff {a b : UInt64} : a ||| b = 0 ↔ a = 0 ∧ b = 0 := by + simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.or_eq_zero_iff {a b : USize} : a ||| b = 0 ↔ a = 0 ∧ b = 0 := by + simp [← USize.toBitVec_inj] + +theorem UInt8.and_assoc (a b c : UInt8) : a &&& b &&& c = a &&& (b &&& c) := UInt8.toBitVec_inj.1 (BitVec.and_assoc _ _ _) +theorem UInt16.and_assoc (a b c : UInt16) : a &&& b &&& c = a &&& (b &&& c) := UInt16.toBitVec_inj.1 (BitVec.and_assoc _ _ _) +theorem UInt32.and_assoc (a b c : UInt32) : a &&& b &&& c = a &&& (b &&& c) := UInt32.toBitVec_inj.1 (BitVec.and_assoc _ _ _) +theorem UInt64.and_assoc (a b c : UInt64) : a &&& b &&& c = a &&& (b &&& c) := UInt64.toBitVec_inj.1 (BitVec.and_assoc _ _ _) +theorem USize.and_assoc (a b c : USize) : a &&& b &&& c = a &&& (b &&& c) := USize.toBitVec_inj.1 (BitVec.and_assoc _ _ _) + +instance : Std.Associative (α := UInt8) (· &&& ·) := ⟨UInt8.and_assoc⟩ +instance : Std.Associative (α := UInt16) (· &&& ·) := ⟨UInt16.and_assoc⟩ +instance : Std.Associative (α := UInt32) (· &&& ·) := ⟨UInt32.and_assoc⟩ +instance : Std.Associative (α := UInt64) (· &&& ·) := ⟨UInt64.and_assoc⟩ +instance : Std.Associative (α := USize) (· &&& ·) := ⟨USize.and_assoc⟩ + +theorem UInt8.and_comm (a b : UInt8) : a &&& b = b &&& a := UInt8.toBitVec_inj.1 (BitVec.and_comm _ _) +theorem UInt16.and_comm (a b : UInt16) : a &&& b = b &&& a := UInt16.toBitVec_inj.1 (BitVec.and_comm _ _) +theorem UInt32.and_comm (a b : UInt32) : a &&& b = b &&& a := UInt32.toBitVec_inj.1 (BitVec.and_comm _ _) +theorem UInt64.and_comm (a b : UInt64) : a &&& b = b &&& a := UInt64.toBitVec_inj.1 (BitVec.and_comm _ _) +theorem USize.and_comm (a b : USize) : a &&& b = b &&& a := USize.toBitVec_inj.1 (BitVec.and_comm _ _) + +instance : Std.Commutative (α := UInt8) (· &&& ·) := ⟨UInt8.and_comm⟩ +instance : Std.Commutative (α := UInt16) (· &&& ·) := ⟨UInt16.and_comm⟩ +instance : Std.Commutative (α := UInt32) (· &&& ·) := ⟨UInt32.and_comm⟩ +instance : Std.Commutative (α := UInt64) (· &&& ·) := ⟨UInt64.and_comm⟩ +instance : Std.Commutative (α := USize) (· &&& ·) := ⟨USize.and_comm⟩ + +@[simp] theorem UInt8.and_self {a : UInt8} : a &&& a = a := UInt8.toBitVec_inj.1 BitVec.and_self +@[simp] theorem UInt16.and_self {a : UInt16} : a &&& a = a := UInt16.toBitVec_inj.1 BitVec.and_self +@[simp] theorem UInt32.and_self {a : UInt32} : a &&& a = a := UInt32.toBitVec_inj.1 BitVec.and_self +@[simp] theorem UInt64.and_self {a : UInt64} : a &&& a = a := UInt64.toBitVec_inj.1 BitVec.and_self +@[simp] theorem USize.and_self {a : USize} : a &&& a = a := USize.toBitVec_inj.1 BitVec.and_self + +instance : Std.IdempotentOp (α := UInt8) (· &&& ·) := ⟨fun _ => UInt8.and_self⟩ +instance : Std.IdempotentOp (α := UInt16) (· &&& ·) := ⟨fun _ => UInt16.and_self⟩ +instance : Std.IdempotentOp (α := UInt32) (· &&& ·) := ⟨fun _ => UInt32.and_self⟩ +instance : Std.IdempotentOp (α := UInt64) (· &&& ·) := ⟨fun _ => UInt64.and_self⟩ +instance : Std.IdempotentOp (α := USize) (· &&& ·) := ⟨fun _ => USize.and_self⟩ + +@[simp] theorem UInt8.and_zero {a : UInt8} : a &&& 0 = 0 := UInt8.toBitVec_inj.1 BitVec.and_zero +@[simp] theorem UInt16.and_zero {a : UInt16} : a &&& 0 = 0 := UInt16.toBitVec_inj.1 BitVec.and_zero +@[simp] theorem UInt32.and_zero {a : UInt32} : a &&& 0 = 0 := UInt32.toBitVec_inj.1 BitVec.and_zero +@[simp] theorem UInt64.and_zero {a : UInt64} : a &&& 0 = 0 := UInt64.toBitVec_inj.1 BitVec.and_zero +@[simp] theorem USize.and_zero {a : USize} : a &&& 0 = 0 := USize.toBitVec_inj.1 BitVec.and_zero + +@[simp] theorem UInt8.zero_and {a : UInt8} : 0 &&& a = 0 := UInt8.toBitVec_inj.1 BitVec.zero_and +@[simp] theorem UInt16.zero_and {a : UInt16} : 0 &&& a = 0 := UInt16.toBitVec_inj.1 BitVec.zero_and +@[simp] theorem UInt32.zero_and {a : UInt32} : 0 &&& a = 0 := UInt32.toBitVec_inj.1 BitVec.zero_and +@[simp] theorem UInt64.zero_and {a : UInt64} : 0 &&& a = 0 := UInt64.toBitVec_inj.1 BitVec.zero_and +@[simp] theorem USize.zero_and {a : USize} : 0 &&& a = 0 := USize.toBitVec_inj.1 BitVec.zero_and + +@[simp] theorem UInt8.neg_one_and {a : UInt8} : -1 &&& a = a := by + rw [← UInt8.toBitVec_inj, UInt8.toBitVec_and, UInt8.toBitVec_neg, UInt8.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_and] +@[simp] theorem UInt16.neg_one_and {a : UInt16} : -1 &&& a = a := by + rw [← UInt16.toBitVec_inj, UInt16.toBitVec_and, UInt16.toBitVec_neg, UInt16.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_and] +@[simp] theorem UInt32.neg_one_and {a : UInt32} : -1 &&& a = a := by + rw [← UInt32.toBitVec_inj, UInt32.toBitVec_and, UInt32.toBitVec_neg, UInt32.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_and] +@[simp] theorem UInt64.neg_one_and {a : UInt64} : -1 &&& a = a := by + rw [← UInt64.toBitVec_inj, UInt64.toBitVec_and, UInt64.toBitVec_neg, UInt64.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_and] +@[simp] theorem USize.neg_one_and {a : USize} : -1 &&& a = a := by + rw [← USize.toBitVec_inj, USize.toBitVec_and, USize.toBitVec_neg, USize.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_and] + +@[simp] theorem UInt8.and_neg_one {a : UInt8} : a &&& -1 = a := by rw [and_comm, neg_one_and] +@[simp] theorem UInt16.and_neg_one {a : UInt16} : a &&& -1 = a := by rw [and_comm, neg_one_and] +@[simp] theorem UInt32.and_neg_one {a : UInt32} : a &&& -1 = a := by rw [and_comm, neg_one_and] +@[simp] theorem UInt64.and_neg_one {a : UInt64} : a &&& -1 = a := by rw [and_comm, neg_one_and] +@[simp] theorem USize.and_neg_one {a : USize} : a &&& -1 = a := by rw [and_comm, neg_one_and] + +instance : Std.LawfulCommIdentity (α := UInt8) (· &&& ·) (-1) where + right_id _ := UInt8.and_neg_one +instance : Std.LawfulCommIdentity (α := UInt16) (· &&& ·) (-1) where + right_id _ := UInt16.and_neg_one +instance : Std.LawfulCommIdentity (α := UInt32) (· &&& ·) (-1) where + right_id _ := UInt32.and_neg_one +instance : Std.LawfulCommIdentity (α := UInt64) (· &&& ·) (-1) where + right_id _ := UInt64.and_neg_one +instance : Std.LawfulCommIdentity (α := USize) (· &&& ·) (-1) where + right_id _ := USize.and_neg_one + +@[simp] theorem UInt8.and_eq_neg_one_iff {a b : UInt8} : a &&& b = -1 ↔ a = -1 ∧ b = -1 := by + simp only [← UInt8.toBitVec_inj, UInt8.toBitVec_and, UInt8.toBitVec_neg, UInt8.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.and_eq_allOnes_iff] +@[simp] theorem UInt16.and_eq_neg_one_iff {a b : UInt16} : a &&& b = -1 ↔ a = -1 ∧ b = -1 := by + simp only [← UInt16.toBitVec_inj, UInt16.toBitVec_and, UInt16.toBitVec_neg, UInt16.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.and_eq_allOnes_iff] +@[simp] theorem UInt32.and_eq_neg_one_iff {a b : UInt32} : a &&& b = -1 ↔ a = -1 ∧ b = -1 := by + simp only [← UInt32.toBitVec_inj, UInt32.toBitVec_and, UInt32.toBitVec_neg, UInt32.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.and_eq_allOnes_iff] +@[simp] theorem UInt64.and_eq_neg_one_iff {a b : UInt64} : a &&& b = -1 ↔ a = -1 ∧ b = -1 := by + simp only [← UInt64.toBitVec_inj, UInt64.toBitVec_and, UInt64.toBitVec_neg, UInt64.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.and_eq_allOnes_iff] +@[simp] theorem USize.and_eq_neg_one_iff {a b : USize} : a &&& b = -1 ↔ a = -1 ∧ b = -1 := by + simp only [← USize.toBitVec_inj, USize.toBitVec_and, USize.toBitVec_neg, USize.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.and_eq_allOnes_iff] + +theorem UInt8.xor_assoc (a b c : UInt8) : a ^^^ b ^^^ c = a ^^^ (b ^^^ c) := UInt8.toBitVec_inj.1 (BitVec.xor_assoc _ _ _) +theorem UInt16.xor_assoc (a b c : UInt16) : a ^^^ b ^^^ c = a ^^^ (b ^^^ c) := UInt16.toBitVec_inj.1 (BitVec.xor_assoc _ _ _) +theorem UInt32.xor_assoc (a b c : UInt32) : a ^^^ b ^^^ c = a ^^^ (b ^^^ c) := UInt32.toBitVec_inj.1 (BitVec.xor_assoc _ _ _) +theorem UInt64.xor_assoc (a b c : UInt64) : a ^^^ b ^^^ c = a ^^^ (b ^^^ c) := UInt64.toBitVec_inj.1 (BitVec.xor_assoc _ _ _) +theorem USize.xor_assoc (a b c : USize) : a ^^^ b ^^^ c = a ^^^ (b ^^^ c) := USize.toBitVec_inj.1 (BitVec.xor_assoc _ _ _) + +instance : Std.Associative (α := UInt8) (· ^^^ ·) := ⟨UInt8.xor_assoc⟩ +instance : Std.Associative (α := UInt16) (· ^^^ ·) := ⟨UInt16.xor_assoc⟩ +instance : Std.Associative (α := UInt32) (· ^^^ ·) := ⟨UInt32.xor_assoc⟩ +instance : Std.Associative (α := UInt64) (· ^^^ ·) := ⟨UInt64.xor_assoc⟩ +instance : Std.Associative (α := USize) (· ^^^ ·) := ⟨USize.xor_assoc⟩ + +theorem UInt8.xor_comm (a b : UInt8) : a ^^^ b = b ^^^ a := UInt8.toBitVec_inj.1 (BitVec.xor_comm _ _) +theorem UInt16.xor_comm (a b : UInt16) : a ^^^ b = b ^^^ a := UInt16.toBitVec_inj.1 (BitVec.xor_comm _ _) +theorem UInt32.xor_comm (a b : UInt32) : a ^^^ b = b ^^^ a := UInt32.toBitVec_inj.1 (BitVec.xor_comm _ _) +theorem UInt64.xor_comm (a b : UInt64) : a ^^^ b = b ^^^ a := UInt64.toBitVec_inj.1 (BitVec.xor_comm _ _) +theorem USize.xor_comm (a b : USize) : a ^^^ b = b ^^^ a := USize.toBitVec_inj.1 (BitVec.xor_comm _ _) + +instance : Std.Commutative (α := UInt8) (· ^^^ ·) := ⟨UInt8.xor_comm⟩ +instance : Std.Commutative (α := UInt16) (· ^^^ ·) := ⟨UInt16.xor_comm⟩ +instance : Std.Commutative (α := UInt32) (· ^^^ ·) := ⟨UInt32.xor_comm⟩ +instance : Std.Commutative (α := UInt64) (· ^^^ ·) := ⟨UInt64.xor_comm⟩ +instance : Std.Commutative (α := USize) (· ^^^ ·) := ⟨USize.xor_comm⟩ + +@[simp] theorem UInt8.xor_self {a : UInt8} : a ^^^ a = 0 := UInt8.toBitVec_inj.1 BitVec.xor_self +@[simp] theorem UInt16.xor_self {a : UInt16} : a ^^^ a = 0 := UInt16.toBitVec_inj.1 BitVec.xor_self +@[simp] theorem UInt32.xor_self {a : UInt32} : a ^^^ a = 0 := UInt32.toBitVec_inj.1 BitVec.xor_self +@[simp] theorem UInt64.xor_self {a : UInt64} : a ^^^ a = 0 := UInt64.toBitVec_inj.1 BitVec.xor_self +@[simp] theorem USize.xor_self {a : USize} : a ^^^ a = 0 := USize.toBitVec_inj.1 BitVec.xor_self + +@[simp] theorem UInt8.xor_zero {a : UInt8} : a ^^^ 0 = a := UInt8.toBitVec_inj.1 BitVec.xor_zero +@[simp] theorem UInt16.xor_zero {a : UInt16} : a ^^^ 0 = a := UInt16.toBitVec_inj.1 BitVec.xor_zero +@[simp] theorem UInt32.xor_zero {a : UInt32} : a ^^^ 0 = a := UInt32.toBitVec_inj.1 BitVec.xor_zero +@[simp] theorem UInt64.xor_zero {a : UInt64} : a ^^^ 0 = a := UInt64.toBitVec_inj.1 BitVec.xor_zero +@[simp] theorem USize.xor_zero {a : USize} : a ^^^ 0 = a := USize.toBitVec_inj.1 BitVec.xor_zero + +@[simp] theorem UInt8.zero_xor {a : UInt8} : 0 ^^^ a = a := UInt8.toBitVec_inj.1 BitVec.zero_xor +@[simp] theorem UInt16.zero_xor {a : UInt16} : 0 ^^^ a = a := UInt16.toBitVec_inj.1 BitVec.zero_xor +@[simp] theorem UInt32.zero_xor {a : UInt32} : 0 ^^^ a = a := UInt32.toBitVec_inj.1 BitVec.zero_xor +@[simp] theorem UInt64.zero_xor {a : UInt64} : 0 ^^^ a = a := UInt64.toBitVec_inj.1 BitVec.zero_xor +@[simp] theorem USize.zero_xor {a : USize} : 0 ^^^ a = a := USize.toBitVec_inj.1 BitVec.zero_xor + +@[simp] theorem UInt8.neg_one_xor {a : UInt8} : -1 ^^^ a = ~~~a := by + rw [← UInt8.toBitVec_inj, UInt8.toBitVec_xor, UInt8.toBitVec_neg, UInt8.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_xor, UInt8.toBitVec_not] +@[simp] theorem UInt16.neg_one_xor {a : UInt16} : -1 ^^^ a = ~~~a := by + rw [← UInt16.toBitVec_inj, UInt16.toBitVec_xor, UInt16.toBitVec_neg, UInt16.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_xor, UInt16.toBitVec_not] +@[simp] theorem UInt32.neg_one_xor {a : UInt32} : -1 ^^^ a = ~~~a := by + rw [← UInt32.toBitVec_inj, UInt32.toBitVec_xor, UInt32.toBitVec_neg, UInt32.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_xor, UInt32.toBitVec_not] +@[simp] theorem UInt64.neg_one_xor {a : UInt64} : -1 ^^^ a = ~~~a := by + rw [← UInt64.toBitVec_inj, UInt64.toBitVec_xor, UInt64.toBitVec_neg, UInt64.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_xor, UInt64.toBitVec_not] +@[simp] theorem USize.neg_one_xor {a : USize} : -1 ^^^ a = ~~~a := by + rw [← USize.toBitVec_inj, USize.toBitVec_xor, USize.toBitVec_neg, USize.toBitVec_one, + BitVec.negOne_eq_allOnes, BitVec.allOnes_xor, USize.toBitVec_not] + +@[simp] theorem UInt8.xor_neg_one {a : UInt8} : a ^^^ -1 = ~~~a := by rw [xor_comm, neg_one_xor] +@[simp] theorem UInt16.xor_neg_one {a : UInt16} : a ^^^ -1 = ~~~a := by rw [xor_comm, neg_one_xor] +@[simp] theorem UInt32.xor_neg_one {a : UInt32} : a ^^^ -1 = ~~~a := by rw [xor_comm, neg_one_xor] +@[simp] theorem UInt64.xor_neg_one {a : UInt64} : a ^^^ -1 = ~~~a := by rw [xor_comm, neg_one_xor] +@[simp] theorem USize.xor_neg_one {a : USize} : a ^^^ -1 = ~~~a := by rw [xor_comm, neg_one_xor] + +instance : Std.LawfulCommIdentity (α := UInt8) (· ^^^ ·) 0 where + right_id _ := UInt8.xor_zero +instance : Std.LawfulCommIdentity (α := UInt16) (· ^^^ ·) 0 where + right_id _ := UInt16.xor_zero +instance : Std.LawfulCommIdentity (α := UInt32) (· ^^^ ·) 0 where + right_id _ := UInt32.xor_zero +instance : Std.LawfulCommIdentity (α := UInt64) (· ^^^ ·) 0 where + right_id _ := UInt64.xor_zero +instance : Std.LawfulCommIdentity (α := USize) (· ^^^ ·) 0 where + right_id _ := USize.xor_zero + +@[simp] theorem UInt8.xor_eq_zero_iff {a b : UInt8} : a ^^^ b = 0 ↔ a = b := by simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.xor_eq_zero_iff {a b : UInt16} : a ^^^ b = 0 ↔ a = b := by simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.xor_eq_zero_iff {a b : UInt32} : a ^^^ b = 0 ↔ a = b := by simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.xor_eq_zero_iff {a b : UInt64} : a ^^^ b = 0 ↔ a = b := by simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.xor_eq_zero_iff {a b : USize} : a ^^^ b = 0 ↔ a = b := by simp [← USize.toBitVec_inj] + +@[simp] theorem UInt8.xor_left_inj {a b : UInt8} (c : UInt8) : (a ^^^ c = b ^^^ c) ↔ a = b := by + simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.xor_left_inj {a b : UInt16} (c : UInt16) : (a ^^^ c = b ^^^ c) ↔ a = b := by + simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.xor_left_inj {a b : UInt32} (c : UInt32) : (a ^^^ c = b ^^^ c) ↔ a = b := by + simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.xor_left_inj {a b : UInt64} (c : UInt64) : (a ^^^ c = b ^^^ c) ↔ a = b := by + simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.xor_left_inj {a b : USize} (c : USize) : (a ^^^ c = b ^^^ c) ↔ a = b := by + simp [← USize.toBitVec_inj] + +@[simp] theorem UInt8.xor_right_inj {a b : UInt8} (c : UInt8) : (c ^^^ a = c ^^^ b) ↔ a = b := by + simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.xor_right_inj {a b : UInt16} (c : UInt16) : (c ^^^ a = c ^^^ b) ↔ a = b := by + simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.xor_right_inj {a b : UInt32} (c : UInt32) : (c ^^^ a = c ^^^ b) ↔ a = b := by + simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.xor_right_inj {a b : UInt64} (c : UInt64) : (c ^^^ a = c ^^^ b) ↔ a = b := by + simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.xor_right_inj {a b : USize} (c : USize) : (c ^^^ a = c ^^^ b) ↔ a = b := by + simp [← USize.toBitVec_inj] + +@[simp] theorem UInt8.not_zero : ~~~(0 : UInt8) = -1 := rfl +@[simp] theorem UInt16.not_zero : ~~~(0 : UInt16) = -1 := rfl +@[simp] theorem UInt32.not_zero : ~~~(0 : UInt32) = -1 := rfl +@[simp] theorem UInt64.not_zero : ~~~(0 : UInt64) = -1 := rfl +@[simp] theorem USize.not_zero : ~~~(0 : USize) = -1 := by simp [USize.not_eq_neg_sub] + +@[simp] theorem UInt8.not_neg_one : ~~~(-1 : UInt8) = 0 := rfl +@[simp] theorem UInt16.not_neg_one : ~~~(-1 : UInt16) = 0 := rfl +@[simp] theorem UInt32.not_neg_one : ~~~(-1 : UInt32) = 0 := rfl +@[simp] theorem UInt64.not_neg_one : ~~~(-1 : UInt64) = 0 := rfl +@[simp] theorem USize.not_neg_one : ~~~(-1 : USize) = 0 := by simp [USize.not_eq_neg_sub] + +@[simp] theorem UInt8.not_not {a : UInt8} : ~~~(~~~a) = a := by simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.not_not {a : UInt16} : ~~~(~~~a) = a := by simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.not_not {a : UInt32} : ~~~(~~~a) = a := by simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.not_not {a : UInt64} : ~~~(~~~a) = a := by simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.not_not {a : USize} : ~~~(~~~a) = a := by simp [← USize.toBitVec_inj] + +@[simp] theorem UInt8.not_inj {a b : UInt8} : ~~~a = ~~~b ↔ a = b := by simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.not_inj {a b : UInt16} : ~~~a = ~~~b ↔ a = b := by simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.not_inj {a b : UInt32} : ~~~a = ~~~b ↔ a = b := by simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.not_inj {a b : UInt64} : ~~~a = ~~~b ↔ a = b := by simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.not_inj {a b : USize} : ~~~a = ~~~b ↔ a = b := by simp [← USize.toBitVec_inj] + +@[simp] theorem UInt8.and_not_self {a : UInt8} : a &&& ~~~a = 0 := by simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.and_not_self {a : UInt16} : a &&& ~~~a = 0 := by simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.and_not_self {a : UInt32} : a &&& ~~~a = 0 := by simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.and_not_self {a : UInt64} : a &&& ~~~a = 0 := by simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.and_not_self {a : USize} : a &&& ~~~a = 0 := by simp [← USize.toBitVec_inj] + +@[simp] theorem UInt8.not_and_self {a : UInt8} : ~~~a &&& a = 0 := by simp [UInt8.and_comm] +@[simp] theorem UInt16.not_and_self {a : UInt16} : ~~~a &&& a = 0 := by simp [UInt16.and_comm] +@[simp] theorem UInt32.not_and_self {a : UInt32} : ~~~a &&& a = 0 := by simp [UInt32.and_comm] +@[simp] theorem UInt64.not_and_self {a : UInt64} : ~~~a &&& a = 0 := by simp [UInt64.and_comm] +@[simp] theorem USize.not_and_self {a : USize} : ~~~a &&& a = 0 := by simp [USize.and_comm] + +@[simp] theorem UInt8.or_not_self {a : UInt8} : a ||| ~~~a = -1 := by + rw [← UInt8.toBitVec_inj, UInt8.toBitVec_or, UInt8.toBitVec_not, BitVec.or_not_self, + UInt8.toBitVec_neg, UInt8.toBitVec_one, BitVec.negOne_eq_allOnes] +@[simp] theorem UInt16.or_not_self {a : UInt16} : a ||| ~~~a = -1 := by + rw [← UInt16.toBitVec_inj, UInt16.toBitVec_or, UInt16.toBitVec_not, BitVec.or_not_self, + UInt16.toBitVec_neg, UInt16.toBitVec_one, BitVec.negOne_eq_allOnes] +@[simp] theorem UInt32.or_not_self {a : UInt32} : a ||| ~~~a = -1 := by + rw [← UInt32.toBitVec_inj, UInt32.toBitVec_or, UInt32.toBitVec_not, BitVec.or_not_self, + UInt32.toBitVec_neg, UInt32.toBitVec_one, BitVec.negOne_eq_allOnes] +@[simp] theorem UInt64.or_not_self {a : UInt64} : a ||| ~~~a = -1 := by + rw [← UInt64.toBitVec_inj, UInt64.toBitVec_or, UInt64.toBitVec_not, BitVec.or_not_self, + UInt64.toBitVec_neg, UInt64.toBitVec_one, BitVec.negOne_eq_allOnes] +@[simp] theorem USize.or_not_self {a : USize} : a ||| ~~~a = -1 := by + rw [← USize.toBitVec_inj, USize.toBitVec_or, USize.toBitVec_not, BitVec.or_not_self, + USize.toBitVec_neg, USize.toBitVec_one, BitVec.negOne_eq_allOnes] + +@[simp] theorem UInt8.not_or_self {a : UInt8} : ~~~a ||| a = -1 := by simp [UInt8.or_comm] +@[simp] theorem UInt16.not_or_self {a : UInt16} : ~~~a ||| a = -1 := by simp [UInt16.or_comm] +@[simp] theorem UInt32.not_or_self {a : UInt32} : ~~~a ||| a = -1 := by simp [UInt32.or_comm] +@[simp] theorem UInt64.not_or_self {a : UInt64} : ~~~a ||| a = -1 := by simp [UInt64.or_comm] +@[simp] theorem USize.not_or_self {a : USize} : ~~~a ||| a = -1 := by simp [USize.or_comm] + +theorem UInt8.not_eq_comm {a b : UInt8} : ~~~a = b ↔ a = ~~~b := by + simp [← UInt8.toBitVec_inj, BitVec.not_eq_comm] +theorem UInt16.not_eq_comm {a b : UInt16} : ~~~a = b ↔ a = ~~~b := by + simp [← UInt16.toBitVec_inj, BitVec.not_eq_comm] +theorem UInt32.not_eq_comm {a b : UInt32} : ~~~a = b ↔ a = ~~~b := by + simp [← UInt32.toBitVec_inj, BitVec.not_eq_comm] +theorem UInt64.not_eq_comm {a b : UInt64} : ~~~a = b ↔ a = ~~~b := by + simp [← UInt64.toBitVec_inj, BitVec.not_eq_comm] +theorem USize.not_eq_comm {a b : USize} : ~~~a = b ↔ a = ~~~b := by + simp [← USize.toBitVec_inj, BitVec.not_eq_comm] + +@[simp] theorem UInt8.ne_not_self {a : UInt8} : a ≠ ~~~a := by simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.ne_not_self {a : UInt16} : a ≠ ~~~a := by simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.ne_not_self {a : UInt32} : a ≠ ~~~a := by simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.ne_not_self {a : UInt64} : a ≠ ~~~a := by simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.ne_not_self {a : USize} : a ≠ ~~~a := by simp [← USize.toBitVec_inj] + +@[simp] theorem UInt8.not_ne_self {a : UInt8} : ~~~a ≠ a := by simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.not_ne_self {a : UInt16} : ~~~a ≠ a := by simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.not_ne_self {a : UInt32} : ~~~a ≠ a := by simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.not_ne_self {a : UInt64} : ~~~a ≠ a := by simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.not_ne_self {a : USize} : ~~~a ≠ a := by simp [← USize.toBitVec_inj] + +theorem UInt8.not_xor {a b : UInt8} : ~~~a ^^^ b = ~~~(a ^^^ b) := by + simp [← UInt8.toBitVec_inj, BitVec.not_xor_left] +theorem UInt16.not_xor {a b : UInt16} : ~~~a ^^^ b = ~~~(a ^^^ b) := by + simp [← UInt16.toBitVec_inj, BitVec.not_xor_left] +theorem UInt32.not_xor {a b : UInt32} : ~~~a ^^^ b = ~~~(a ^^^ b) := by + simp [← UInt32.toBitVec_inj, BitVec.not_xor_left] +theorem UInt64.not_xor {a b : UInt64} : ~~~a ^^^ b = ~~~(a ^^^ b) := by + simp [← UInt64.toBitVec_inj, BitVec.not_xor_left] +theorem USize.not_xor {a b : USize} : ~~~a ^^^ b = ~~~(a ^^^ b) := by + simp [← USize.toBitVec_inj, BitVec.not_xor_left] + +theorem UInt8.xor_not {a b : UInt8} : a ^^^ ~~~b = ~~~(a ^^^ b) := by + simp [← UInt8.toBitVec_inj, BitVec.not_xor_right] +theorem UInt16.xor_not {a b : UInt16} : a ^^^ ~~~b = ~~~(a ^^^ b) := by + simp [← UInt16.toBitVec_inj, BitVec.not_xor_right] +theorem UInt32.xor_not {a b : UInt32} : a ^^^ ~~~b = ~~~(a ^^^ b) := by + simp [← UInt32.toBitVec_inj, BitVec.not_xor_right] +theorem UInt64.xor_not {a b : UInt64} : a ^^^ ~~~b = ~~~(a ^^^ b) := by + simp [← UInt64.toBitVec_inj, BitVec.not_xor_right] +theorem USize.xor_not {a b : USize} : a ^^^ ~~~b = ~~~(a ^^^ b) := by + simp [← USize.toBitVec_inj, BitVec.not_xor_right] + +@[simp] theorem UInt8.shiftLeft_zero {a : UInt8} : a <<< 0 = a := by simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.shiftLeft_zero {a : UInt16} : a <<< 0 = a := by simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.shiftLeft_zero {a : UInt32} : a <<< 0 = a := by simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.shiftLeft_zero {a : UInt64} : a <<< 0 = a := by simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.shiftLeft_zero {a : USize} : a <<< 0 = a := by simp [← USize.toBitVec_inj] + +@[simp] theorem UInt8.zero_shiftLeft {a : UInt8} : 0 <<< a = 0 := by simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.zero_shiftLeft {a : UInt16} : 0 <<< a = 0 := by simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.zero_shiftLeft {a : UInt32} : 0 <<< a = 0 := by simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.zero_shiftLeft {a : UInt64} : 0 <<< a = 0 := by simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.zero_shiftLeft {a : USize} : 0 <<< a = 0 := by simp [← USize.toBitVec_inj] + +theorem UInt8.shiftLeft_xor {a b c : UInt8} : (a ^^^ b) <<< c = (a <<< c) ^^^ (b <<< c) := by + simp [← UInt8.toBitVec_inj, BitVec.shiftLeft_xor_distrib] +theorem UInt16.shiftLeft_xor {a b c : UInt16} : (a ^^^ b) <<< c = (a <<< c) ^^^ (b <<< c) := by + simp [← UInt16.toBitVec_inj, BitVec.shiftLeft_xor_distrib] +theorem UInt32.shiftLeft_xor {a b c : UInt32} : (a ^^^ b) <<< c = (a <<< c) ^^^ (b <<< c) := by + simp [← UInt32.toBitVec_inj, BitVec.shiftLeft_xor_distrib] +theorem UInt64.shiftLeft_xor {a b c : UInt64} : (a ^^^ b) <<< c = (a <<< c) ^^^ (b <<< c) := by + simp [← UInt64.toBitVec_inj, BitVec.shiftLeft_xor_distrib] +theorem USize.shiftLeft_xor {a b c : USize} : (a ^^^ b) <<< c = (a <<< c) ^^^ (b <<< c) := by + simp [← USize.toBitVec_inj, BitVec.shiftLeft_xor_distrib] + +theorem UInt8.shiftLeft_and {a b c : UInt8} : (a &&& b) <<< c = (a <<< c) &&& (b <<< c) := by + simp [← UInt8.toBitVec_inj, BitVec.shiftLeft_and_distrib] +theorem UInt16.shiftLeft_and {a b c : UInt16} : (a &&& b) <<< c = (a <<< c) &&& (b <<< c) := by + simp [← UInt16.toBitVec_inj, BitVec.shiftLeft_and_distrib] +theorem UInt32.shiftLeft_and {a b c : UInt32} : (a &&& b) <<< c = (a <<< c) &&& (b <<< c) := by + simp [← UInt32.toBitVec_inj, BitVec.shiftLeft_and_distrib] +theorem UInt64.shiftLeft_and {a b c : UInt64} : (a &&& b) <<< c = (a <<< c) &&& (b <<< c) := by + simp [← UInt64.toBitVec_inj, BitVec.shiftLeft_and_distrib] +theorem USize.shiftLeft_and {a b c : USize} : (a &&& b) <<< c = (a <<< c) &&& (b <<< c) := by + simp [← USize.toBitVec_inj, BitVec.shiftLeft_and_distrib] + +theorem UInt8.shiftLeft_or {a b c : UInt8} : (a ||| b) <<< c = (a <<< c) ||| (b <<< c) := by + simp [← UInt8.toBitVec_inj, BitVec.shiftLeft_or_distrib] +theorem UInt16.shiftLeft_or {a b c : UInt16} : (a ||| b) <<< c = (a <<< c) ||| (b <<< c) := by + simp [← UInt16.toBitVec_inj, BitVec.shiftLeft_or_distrib] +theorem UInt32.shiftLeft_or {a b c : UInt32} : (a ||| b) <<< c = (a <<< c) ||| (b <<< c) := by + simp [← UInt32.toBitVec_inj, BitVec.shiftLeft_or_distrib] +theorem UInt64.shiftLeft_or {a b c : UInt64} : (a ||| b) <<< c = (a <<< c) ||| (b <<< c) := by + simp [← UInt64.toBitVec_inj, BitVec.shiftLeft_or_distrib] +theorem USize.shiftLeft_or {a b c : USize} : (a ||| b) <<< c = (a <<< c) ||| (b <<< c) := by + simp [← USize.toBitVec_inj, BitVec.shiftLeft_or_distrib] + +theorem UInt8.shiftLeft_add_of_toNat_lt {a b c : UInt8} (h : b.toNat + c.toNat < 8) : + a <<< (b + c) = (a <<< b) <<< c := by + simp [← UInt8.toBitVec_inj, Nat.mod_eq_of_lt h, Nat.mod_eq_of_lt (show b.toNat < 8 by omega), + Nat.mod_eq_of_lt (show c.toNat < 8 by omega), BitVec.shiftLeft_add] +theorem UInt16.shiftLeft_add_of_toNat_lt {a b c : UInt16} (h : b.toNat + c.toNat < 16) : + a <<< (b + c) = (a <<< b) <<< c := by + simp [← UInt16.toBitVec_inj, Nat.mod_eq_of_lt h, Nat.mod_eq_of_lt (show b.toNat < 16 by omega), + Nat.mod_eq_of_lt (show c.toNat < 16 by omega), BitVec.shiftLeft_add] +theorem UInt32.shiftLeft_add_of_toNat_lt {a b c : UInt32} (h : b.toNat + c.toNat < 32) : + a <<< (b + c) = (a <<< b) <<< c := by + simp [← UInt32.toBitVec_inj, Nat.mod_eq_of_lt h, Nat.mod_eq_of_lt (show b.toNat < 32 by omega), + Nat.mod_eq_of_lt (show c.toNat < 32 by omega), BitVec.shiftLeft_add] +theorem UInt64.shiftLeft_add_of_toNat_lt {a b c : UInt64} (h : b.toNat + c.toNat < 64) : + a <<< (b + c) = (a <<< b) <<< c := by + simp [← UInt64.toBitVec_inj, Nat.mod_eq_of_lt h, Nat.mod_eq_of_lt (show b.toNat < 64 by omega), + Nat.mod_eq_of_lt (show c.toNat < 64 by omega), BitVec.shiftLeft_add] +theorem USize.shiftLeft_add_of_toNat_lt {a b c : USize} + (h : b.toNat + c.toNat < System.Platform.numBits) : + a <<< (b + c) = (a <<< b) <<< c := by + simp only [← USize.toBitVec_inj, USize.toBitVec_shiftLeft, USize.toBitVec_add, + BitVec.natCast_eq_ofNat, BitVec.shiftLeft_eq', BitVec.toNat_umod, BitVec.toNat_add, + toNat_toBitVec, BitVec.toNat_ofNat, Nat.mod_two_pow_self] + rw [Nat.mod_eq_of_lt, Nat.mod_eq_of_lt, Nat.mod_eq_of_lt, Nat.mod_eq_of_lt, BitVec.shiftLeft_add] + · omega + · omega + · exact Nat.lt_trans h Nat.lt_two_pow_self + · exact Nat.lt_of_le_of_lt (Nat.mod_le _ _) h + +theorem UInt8.shiftLeft_add {a b c : UInt8} (hb : b < 8) (hc : c < 8) (hbc : b + c < 8) : + a <<< (b + c) = (a <<< b) <<< c := by + apply UInt8.shiftLeft_add_of_toNat_lt + have hb : b.toNat < 8 := by simpa [lt_iff_toNat_lt] using hb + have hc : c.toNat < 8 := by simpa [lt_iff_toNat_lt] using hc + simp only [lt_iff_toNat_lt, UInt8.toNat_add, Nat.reducePow, UInt8.reduceToNat] at hbc + rwa [Nat.mod_eq_of_lt (by omega)] at hbc +theorem UInt16.shiftLeft_add {a b c : UInt16} (hb : b < 16) (hc : c < 16) (hbc : b + c < 16) : + a <<< (b + c) = (a <<< b) <<< c := by + apply UInt16.shiftLeft_add_of_toNat_lt + have hb : b.toNat < 16 := by simpa [lt_iff_toNat_lt] using hb + have hc : c.toNat < 16 := by simpa [lt_iff_toNat_lt] using hc + simp only [lt_iff_toNat_lt, UInt16.toNat_add, Nat.reducePow, UInt16.reduceToNat] at hbc + rwa [Nat.mod_eq_of_lt (by omega)] at hbc +theorem UInt32.shiftLeft_add {a b c : UInt32} (hb : b < 32) (hc : c < 32) (hbc : b + c < 32) : + a <<< (b + c) = (a <<< b) <<< c := by + apply UInt32.shiftLeft_add_of_toNat_lt + have hb : b.toNat < 32 := by simpa [lt_iff_toNat_lt] using hb + have hc : c.toNat < 32 := by simpa [lt_iff_toNat_lt] using hc + simp only [lt_iff_toNat_lt, UInt32.toNat_add, Nat.reducePow, UInt32.reduceToNat] at hbc + rwa [Nat.mod_eq_of_lt (by omega)] at hbc +theorem UInt64.shiftLeft_add {a b c : UInt64} (hb : b < 64) (hc : c < 64) (hbc : b + c < 64) : + a <<< (b + c) = (a <<< b) <<< c := by + apply UInt64.shiftLeft_add_of_toNat_lt + have hb : b.toNat < 64 := by simpa [lt_iff_toNat_lt] using hb + have hc : c.toNat < 64 := by simpa [lt_iff_toNat_lt] using hc + simp only [lt_iff_toNat_lt, UInt64.toNat_add, Nat.reducePow, UInt64.reduceToNat] at hbc + rwa [Nat.mod_eq_of_lt (by omega)] at hbc +theorem USize.shiftLeft_add {a b c : USize} (hb : b < USize.ofNat System.Platform.numBits) + (hc : c < USize.ofNat System.Platform.numBits) (hbc : b + c < USize.ofNat System.Platform.numBits) : + a <<< (b + c) = (a <<< b) <<< c := by + apply USize.shiftLeft_add_of_toNat_lt + have hb : b.toNat < System.Platform.numBits := by simpa [lt_iff_toNat_lt] using hb + have hc : c.toNat < System.Platform.numBits := by simpa [lt_iff_toNat_lt] using hc + simp only [lt_iff_toNat_lt, USize.toNat_add, toNat_ofNat', Nat.mod_two_pow_self] at hbc + rwa [Nat.mod_eq_of_lt] at hbc + cases System.Platform.numBits_eq <;> simp_all <;> omega + +@[simp] theorem UInt8.neg_one_shiftLeft_and_shiftLeft {a b : UInt8} : + (-1) <<< b &&& a <<< b = a <<< b := by simp [← UInt8.shiftLeft_and] +@[simp] theorem UInt16.neg_one_shiftLeft_and_shiftLeft {a b : UInt16} : + (-1) <<< b &&& a <<< b = a <<< b := by simp [← UInt16.shiftLeft_and] +@[simp] theorem UInt32.neg_one_shiftLeft_and_shiftLeft {a b : UInt32} : + (-1) <<< b &&& a <<< b = a <<< b := by simp [← UInt32.shiftLeft_and] +@[simp] theorem UInt64.neg_one_shiftLeft_and_shiftLeft {a b : UInt64} : + (-1) <<< b &&& a <<< b = a <<< b := by simp [← UInt64.shiftLeft_and] +@[simp] theorem USize.neg_one_shiftLeft_and_shiftLeft {a b : USize} : + (-1) <<< b &&& a <<< b = a <<< b := by simp [← USize.shiftLeft_and] + +@[simp] theorem UInt8.neg_one_shiftLeft_or_shiftLeft {a b : UInt8} : + (-1) <<< b ||| a <<< b = (-1) <<< b := by simp [← UInt8.shiftLeft_or] +@[simp] theorem UInt16.neg_one_shiftLeft_or_shiftLeft {a b : UInt16} : + (-1) <<< b ||| a <<< b = (-1) <<< b := by simp [← UInt16.shiftLeft_or] +@[simp] theorem UInt32.neg_one_shiftLeft_or_shiftLeft {a b : UInt32} : + (-1) <<< b ||| a <<< b = (-1) <<< b := by simp [← UInt32.shiftLeft_or] +@[simp] theorem UInt64.neg_one_shiftLeft_or_shiftLeft {a b : UInt8} : + (-1) <<< b ||| a <<< b = (-1) <<< b := by simp [← UInt64.shiftLeft_or] +@[simp] theorem USize.neg_one_shiftLeft_or_shiftLeft {a b : USize} : + (-1) <<< b ||| a <<< b = (-1) <<< b := by simp [← USize.shiftLeft_or] + +@[simp] theorem UInt8.shiftRight_zero {a : UInt8} : a >>> 0 = a := by simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.shiftRight_zero {a : UInt16} : a >>> 0 = a := by simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.shiftRight_zero {a : UInt32} : a >>> 0 = a := by simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.shiftRight_zero {a : UInt64} : a >>> 0 = a := by simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.shiftRight_zero {a : USize} : a >>> 0 = a := by simp [← USize.toBitVec_inj] + +@[simp] theorem UInt8.zero_shiftRight {a : UInt8} : 0 >>> a = 0 := by simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.zero_shiftRight {a : UInt16} : 0 >>> a = 0 := by simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.zero_shiftRight {a : UInt32} : 0 >>> a = 0 := by simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.zero_shiftRight {a : UInt64} : 0 >>> a = 0 := by simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.zero_shiftRight {a : USize} : 0 >>> a = 0 := by simp [← USize.toBitVec_inj] + +theorem UInt8.shiftRight_xor {a b c : UInt8} : (a ^^^ b) >>> c = (a >>> c) ^^^ (b >>> c) := by + simp [← UInt8.toBitVec_inj, BitVec.ushiftRight_xor_distrib] +theorem UInt16.shiftRight_xor {a b c : UInt16} : (a ^^^ b) >>> c = (a >>> c) ^^^ (b >>> c) := by + simp [← UInt16.toBitVec_inj, BitVec.ushiftRight_xor_distrib] +theorem UInt32.shiftRight_xor {a b c : UInt32} : (a ^^^ b) >>> c = (a >>> c) ^^^ (b >>> c) := by + simp [← UInt32.toBitVec_inj, BitVec.ushiftRight_xor_distrib] +theorem UInt64.shiftRight_xor {a b c : UInt64} : (a ^^^ b) >>> c = (a >>> c) ^^^ (b >>> c) := by + simp [← UInt64.toBitVec_inj, BitVec.ushiftRight_xor_distrib] +theorem USize.shiftRight_xor {a b c : USize} : (a ^^^ b) >>> c = (a >>> c) ^^^ (b >>> c) := by + simp [← USize.toBitVec_inj, BitVec.ushiftRight_xor_distrib] + +theorem UInt8.shiftRight_and {a b c : UInt8} : (a &&& b) >>> c = (a >>> c) &&& (b >>> c) := by + simp [← UInt8.toBitVec_inj, BitVec.ushiftRight_and_distrib] +theorem UInt16.shiftRight_and {a b c : UInt16} : (a &&& b) >>> c = (a >>> c) &&& (b >>> c) := by + simp [← UInt16.toBitVec_inj, BitVec.ushiftRight_and_distrib] +theorem UInt32.shiftRight_and {a b c : UInt32} : (a &&& b) >>> c = (a >>> c) &&& (b >>> c) := by + simp [← UInt32.toBitVec_inj, BitVec.ushiftRight_and_distrib] +theorem UInt64.shiftRight_and {a b c : UInt64} : (a &&& b) >>> c = (a >>> c) &&& (b >>> c) := by + simp [← UInt64.toBitVec_inj, BitVec.ushiftRight_and_distrib] +theorem USize.shiftRight_and {a b c : USize} : (a &&& b) >>> c = (a >>> c) &&& (b >>> c) := by + simp [← USize.toBitVec_inj, BitVec.ushiftRight_and_distrib] + +theorem UInt8.shiftRight_or {a b c : UInt8} : (a ||| b) >>> c = (a >>> c) ||| (b >>> c) := by + simp [← UInt8.toBitVec_inj, BitVec.ushiftRight_or_distrib] +theorem UInt16.shiftRight_or {a b c : UInt16} : (a ||| b) >>> c = (a >>> c) ||| (b >>> c) := by + simp [← UInt16.toBitVec_inj, BitVec.ushiftRight_or_distrib] +theorem UInt32.shiftRight_or {a b c : UInt32} : (a ||| b) >>> c = (a >>> c) ||| (b >>> c) := by + simp [← UInt32.toBitVec_inj, BitVec.ushiftRight_or_distrib] +theorem UInt64.shiftRight_or {a b c : UInt64} : (a ||| b) >>> c = (a >>> c) ||| (b >>> c) := by + simp [← UInt64.toBitVec_inj, BitVec.ushiftRight_or_distrib] +theorem USize.shiftRight_or {a b c : USize} : (a ||| b) >>> c = (a >>> c) ||| (b >>> c) := by + simp [← USize.toBitVec_inj, BitVec.ushiftRight_or_distrib] + +theorem UInt8.and_le_right {a b : UInt8} : a &&& b ≤ b := by + simpa [UInt8.le_iff_toNat_le] using Nat.and_le_right +theorem UInt16.and_le_right {a b : UInt16} : a &&& b ≤ b := by + simpa [UInt16.le_iff_toNat_le] using Nat.and_le_right +theorem UInt32.and_le_right {a b : UInt32} : a &&& b ≤ b := by + simpa [UInt32.le_iff_toNat_le] using Nat.and_le_right +theorem UInt64.and_le_right {a b : UInt64} : a &&& b ≤ b := by + simpa [UInt64.le_iff_toNat_le] using Nat.and_le_right +theorem USize.and_le_right {a b : USize} : a &&& b ≤ b := by + simpa [USize.le_iff_toNat_le] using Nat.and_le_right + +theorem UInt8.and_le_left {a b : UInt8} : a &&& b ≤ a := by + simpa [UInt8.le_iff_toNat_le] using Nat.and_le_left +theorem UInt16.and_le_left {a b : UInt16} : a &&& b ≤ a := by + simpa [UInt16.le_iff_toNat_le] using Nat.and_le_left +theorem UInt32.and_le_left {a b : UInt32} : a &&& b ≤ a := by + simpa [UInt32.le_iff_toNat_le] using Nat.and_le_left +theorem UInt64.and_le_left {a b : UInt64} : a &&& b ≤ a := by + simpa [UInt64.le_iff_toNat_le] using Nat.and_le_left +theorem USize.and_le_left {a b : USize} : a &&& b ≤ a := by + simpa [USize.le_iff_toNat_le] using Nat.and_le_left + +theorem UInt8.left_le_or {a b : UInt8} : a ≤ a ||| b := by + simpa [UInt8.le_iff_toNat_le] using Nat.left_le_or +theorem UInt16.left_le_or {a b : UInt16} : a ≤ a ||| b := by + simpa [UInt16.le_iff_toNat_le] using Nat.left_le_or +theorem UInt32.left_le_or {a b : UInt32} : a ≤ a ||| b := by + simpa [UInt32.le_iff_toNat_le] using Nat.left_le_or +theorem UInt64.left_le_or {a b : UInt64} : a ≤ a ||| b := by + simpa [UInt64.le_iff_toNat_le] using Nat.left_le_or +theorem USize.left_le_or {a b : USize} : a ≤ a ||| b := by + simpa [USize.le_iff_toNat_le] using Nat.left_le_or + +theorem UInt8.right_le_or {a b : UInt8} : b ≤ a ||| b := by + simpa [UInt8.le_iff_toNat_le] using Nat.right_le_or +theorem UInt16.right_le_or {a b : UInt16} : b ≤ a ||| b := by + simpa [UInt16.le_iff_toNat_le] using Nat.right_le_or +theorem UInt32.right_le_or {a b : UInt32} : b ≤ a ||| b := by + simpa [UInt32.le_iff_toNat_le] using Nat.right_le_or +theorem UInt64.right_le_or {a b : UInt64} : b ≤ a ||| b := by + simpa [UInt64.le_iff_toNat_le] using Nat.right_le_or +theorem USize.right_le_or {a b : USize} : b ≤ a ||| b := by + simpa [USize.le_iff_toNat_le] using Nat.right_le_or diff --git a/src/Init/Data/UInt/Lemmas.lean b/src/Init/Data/UInt/Lemmas.lean index 776ceb4cc4..d1bcf35224 100644 --- a/src/Init/Data/UInt/Lemmas.lean +++ b/src/Init/Data/UInt/Lemmas.lean @@ -72,19 +72,30 @@ macro "declare_uint_theorems" typeName:ident bits:term:arg : command => do theorem toNat_ofNat_of_lt {n : Nat} (h : n < size) : toNat (OfNat.ofNat n) = n := toNat_ofNat_of_lt' h - @[int_toBitVec] theorem le_def {a b : $typeName} : a ≤ b ↔ a.toBitVec ≤ b.toBitVec := .rfl + @[int_toBitVec] theorem le_iff_toBitVec_le {a b : $typeName} : a ≤ b ↔ a.toBitVec ≤ b.toBitVec := .rfl - @[int_toBitVec] theorem lt_def {a b : $typeName} : a < b ↔ a.toBitVec < b.toBitVec := .rfl + @[deprecated le_iff_toBitVec_le (since := "2025-03-20")] + theorem le_def {a b : $typeName} : a ≤ b ↔ a.toBitVec ≤ b.toBitVec := .rfl + + @[int_toBitVec] theorem lt_iff_toBitVec_lt {a b : $typeName} : a < b ↔ a.toBitVec < b.toBitVec := .rfl + + @[deprecated lt_iff_toBitVec_lt (since := "2025-03-20")] + theorem lt_def {a b : $typeName} : a < b ↔ a.toBitVec < b.toBitVec := .rfl theorem le_iff_toNat_le {a b : $typeName} : a ≤ b ↔ a.toNat ≤ b.toNat := .rfl theorem lt_iff_toNat_lt {a b : $typeName} : a < b ↔ a.toNat < b.toNat := .rfl - @[simp] protected theorem not_le {a b : $typeName} : ¬ a ≤ b ↔ b < a := by simp [le_def, lt_def] + @[simp] protected theorem not_le {a b : $typeName} : ¬ a ≤ b ↔ b < a := by + simp [le_iff_toBitVec_le, lt_iff_toBitVec_lt] - @[simp] protected theorem not_lt {a b : $typeName} : ¬ a < b ↔ b ≤ a := by simp [le_def, lt_def] + @[simp] protected theorem not_lt {a b : $typeName} : ¬ a < b ↔ b ≤ a := by + simp [le_iff_toBitVec_le, lt_iff_toBitVec_lt] - @[simp] protected theorem le_refl (a : $typeName) : a ≤ a := by simp [le_def] + @[simp] protected theorem le_refl (a : $typeName) : a ≤ a := by simp [le_iff_toBitVec_le] + + open $typeName (le_refl) in + protected theorem le_rfl {a : $typeName} : a ≤ a := le_refl _ @[simp] protected theorem lt_irrefl (a : $typeName) : ¬ a < a := by simp @@ -143,7 +154,7 @@ macro "declare_uint_theorems" typeName:ident bits:term:arg : command => do protected theorem ne_of_lt {a b : $typeName} (h : a < b) : a ≠ b := by apply ne_of_toBitVec_ne apply BitVec.ne_of_lt - simpa [lt_def] using h + simpa [lt_iff_toBitVec_lt] using h @[simp] protected theorem toNat_zero : (0 : $typeName).toNat = 0 := Nat.zero_mod _ @@ -186,7 +197,7 @@ macro "declare_uint_theorems" typeName:ident bits:term:arg : command => do · apply Fin.is_lt protected theorem mod_lt (a : $typeName) {b : $typeName} : 0 < b → a % b < b := by - simp only [lt_def, mod_def] + simp only [lt_iff_toBitVec_lt, mod_def] apply BitVec.umod_lt protected theorem toNat.inj : ∀ {a b : $typeName}, a.toNat = b.toNat → a = b @@ -537,6 +548,12 @@ theorem USize.ofNatLT_uInt64ToNat (n : UInt64) (h) : USize.ofNatLT n.toNat h = n @[simp] theorem UInt64.ofFin_toFin (n : UInt64) : UInt64.ofFin n.toFin = n := rfl @[simp] theorem USize.ofFin_toFin (n : USize) : USize.ofFin n.toFin = n := rfl +@[simp] theorem UInt8.toFin_ofFin (n : Fin UInt8.size) : (UInt8.ofFin n).toFin = n := rfl +@[simp] theorem UInt16.toFin_ofFin (n : Fin UInt16.size) : (UInt16.ofFin n).toFin = n := rfl +@[simp] theorem UInt32.toFin_ofFin (n : Fin UInt32.size) : (UInt32.ofFin n).toFin = n := rfl +@[simp] theorem UInt64.toFin_ofFin (n : Fin UInt64.size) : (UInt64.ofFin n).toFin = n := rfl +@[simp] theorem USize.toFin_ofFin (n : Fin USize.size) : (USize.ofFin n).toFin = n := rfl + @[simp] theorem UInt16.ofFin_uint8ToFin (n : UInt8) : UInt16.ofFin (n.toFin.castLE (by decide)) = n.toUInt16 := rfl @[simp] theorem UInt32.ofFin_uint8ToFin (n : UInt8) : UInt32.ofFin (n.toFin.castLE (by decide)) = n.toUInt32 := rfl @@ -1691,6 +1708,18 @@ theorem UInt32.toUSize_inj {a b : UInt32} : a.toUSize = b.toUSize ↔ a = b := theorem USize.toUInt64_inj {a b : USize} : a.toUInt64 = b.toUInt64 ↔ a = b := ⟨fun h => by rw [← toUSize_toUInt64 a, h, toUSize_toUInt64], by rintro rfl; rfl⟩ +theorem UInt8.lt_iff_toFin_lt {a b : UInt8} : a < b ↔ a.toFin < b.toFin := Iff.rfl +theorem UInt16.lt_iff_toFin_lt {a b : UInt16} : a < b ↔ a.toFin < b.toFin := Iff.rfl +theorem UInt32.lt_iff_toFin_lt {a b : UInt32} : a < b ↔ a.toFin < b.toFin := Iff.rfl +theorem UInt64.lt_iff_toFin_lt {a b : UInt64} : a < b ↔ a.toFin < b.toFin := Iff.rfl +theorem USize.lt_iff_toFin_lt {a b : USize} : a < b ↔ a.toFin < b.toFin := Iff.rfl + +theorem UInt8.le_iff_toFin_le {a b : UInt8} : a ≤ b ↔ a.toFin ≤ b.toFin := Iff.rfl +theorem UInt16.le_iff_toFin_le {a b : UInt16} : a ≤ b ↔ a.toFin ≤ b.toFin := Iff.rfl +theorem UInt32.le_iff_toFin_le {a b : UInt32} : a ≤ b ↔ a.toFin ≤ b.toFin := Iff.rfl +theorem UInt64.le_iff_toFin_le {a b : UInt64} : a ≤ b ↔ a.toFin ≤ b.toFin := Iff.rfl +theorem USize.le_iff_toFin_le {a b : USize} : a ≤ b ↔ a.toFin ≤ b.toFin := Iff.rfl + @[simp] theorem UInt8.toUInt16_lt {a b : UInt8} : a.toUInt16 < b.toUInt16 ↔ a < b := by simp [lt_iff_toNat_lt, UInt16.lt_iff_toNat_lt] @[simp] theorem UInt8.toUInt32_lt {a b : UInt8} : a.toUInt32 < b.toUInt32 ↔ a < b := by @@ -1841,6 +1870,12 @@ theorem UInt32.sub_eq_add_neg (a b : UInt32) : a - b = a + (-b) := UInt32.toBitV theorem UInt64.sub_eq_add_neg (a b : UInt64) : a - b = a + (-b) := UInt64.toBitVec_inj.1 (BitVec.sub_toAdd _ _) theorem USize.sub_eq_add_neg (a b : USize) : a - b = a + (-b) := USize.toBitVec_inj.1 (BitVec.sub_toAdd _ _) +theorem UInt8.add_neg_eq_sub {a b : UInt8} : a + -b = a - b := UInt8.toBitVec_inj.1 BitVec.add_neg_eq_sub +theorem UInt16.add_neg_eq_sub {a b : UInt16} : a + -b = a - b := UInt16.toBitVec_inj.1 BitVec.add_neg_eq_sub +theorem UInt32.add_neg_eq_sub {a b : UInt32} : a + -b = a - b := UInt32.toBitVec_inj.1 BitVec.add_neg_eq_sub +theorem UInt64.add_neg_eq_sub {a b : UInt64} : a + -b = a - b := UInt64.toBitVec_inj.1 BitVec.add_neg_eq_sub +theorem USize.add_neg_eq_sub {a b : USize} : a + -b = a - b := USize.toBitVec_inj.1 BitVec.add_neg_eq_sub + theorem UInt8.neg_one_eq : (-1 : UInt8) = 255 := rfl theorem UInt16.neg_one_eq : (-1 : UInt16) = 65535 := rfl theorem UInt32.neg_one_eq : (-1 : UInt32) = 4294967295 := rfl @@ -1940,3 +1975,973 @@ theorem USize.sub_eq_add_mul (a b : USize) : a - b = a + USize.ofNatLT (USize.si @[simp] theorem USize.toUInt64_sub (a b : USize) : (a - b).toUInt64 = (a.toUInt64 - b.toUInt64) % UInt64.ofNat USize.size := by simp [USize.toUInt64_eq_mod_usizeSize_iff] + +@[simp] theorem UInt8.ofBitVec_neg (b : BitVec 8) : UInt8.ofBitVec (-b) = -UInt8.ofBitVec b := rfl +@[simp] theorem UInt16.ofBitVec_neg (b : BitVec 16) : UInt16.ofBitVec (-b) = -UInt16.ofBitVec b := rfl +@[simp] theorem UInt32.ofBitVec_neg (b : BitVec 32) : UInt32.ofBitVec (-b) = -UInt32.ofBitVec b := rfl +@[simp] theorem UInt64.ofBitVec_neg (b : BitVec 64) : UInt64.ofBitVec (-b) = -UInt64.ofBitVec b := rfl +@[simp] theorem USize.ofBitVec_neg (b : BitVec System.Platform.numBits) : USize.ofBitVec (-b) = -USize.ofBitVec b := rfl + +@[simp] theorem UInt8.ofFin_div (a b : Fin UInt8.size) : UInt8.ofFin (a / b) = UInt8.ofFin a / UInt8.ofFin b := rfl +@[simp] theorem UInt16.ofFin_div (a b : Fin UInt16.size) : UInt16.ofFin (a / b) = UInt16.ofFin a / UInt16.ofFin b := rfl +@[simp] theorem UInt32.ofFin_div (a b : Fin UInt32.size) : UInt32.ofFin (a / b) = UInt32.ofFin a / UInt32.ofFin b := rfl +@[simp] theorem UInt64.ofFin_div (a b : Fin UInt64.size) : UInt64.ofFin (a / b) = UInt64.ofFin a / UInt64.ofFin b := rfl +@[simp] theorem USize.ofFin_div (a b : Fin USize.size) : USize.ofFin (a / b) = USize.ofFin a / USize.ofFin b := rfl + +@[simp] theorem UInt8.ofBitVec_div (a b : BitVec 8) : UInt8.ofBitVec (a / b) = UInt8.ofBitVec a / UInt8.ofBitVec b := rfl +@[simp] theorem UInt16.ofBitVec_div (a b : BitVec 16) : UInt16.ofBitVec (a / b) = UInt16.ofBitVec a / UInt16.ofBitVec b := rfl +@[simp] theorem UInt32.ofBitVec_div (a b : BitVec 32) : UInt32.ofBitVec (a / b) = UInt32.ofBitVec a / UInt32.ofBitVec b := rfl +@[simp] theorem UInt64.ofBitVec_div (a b : BitVec 64) : UInt64.ofBitVec (a / b) = UInt64.ofBitVec a / UInt64.ofBitVec b := rfl +@[simp] theorem USize.ofBitVec_div (a b : BitVec System.Platform.numBits) : USize.ofBitVec (a / b) = USize.ofBitVec a / USize.ofBitVec b := rfl + +@[simp] theorem UInt8.ofFin_mod (a b : Fin UInt8.size) : UInt8.ofFin (a % b) = UInt8.ofFin a % UInt8.ofFin b := rfl +@[simp] theorem UInt16.ofFin_mod (a b : Fin UInt16.size) : UInt16.ofFin (a % b) = UInt16.ofFin a % UInt16.ofFin b := rfl +@[simp] theorem UInt32.ofFin_mod (a b : Fin UInt32.size) : UInt32.ofFin (a % b) = UInt32.ofFin a % UInt32.ofFin b := rfl +@[simp] theorem UInt64.ofFin_mod (a b : Fin UInt64.size) : UInt64.ofFin (a % b) = UInt64.ofFin a % UInt64.ofFin b := rfl +@[simp] theorem USize.ofFin_mod (a b : Fin USize.size) : USize.ofFin (a % b) = USize.ofFin a % USize.ofFin b := rfl + +@[simp] theorem UInt8.ofBitVec_mod (a b : BitVec 8) : UInt8.ofBitVec (a % b) = UInt8.ofBitVec a % UInt8.ofBitVec b := rfl +@[simp] theorem UInt16.ofBitVec_mod (a b : BitVec 16) : UInt16.ofBitVec (a % b) = UInt16.ofBitVec a % UInt16.ofBitVec b := rfl +@[simp] theorem UInt32.ofBitVec_mod (a b : BitVec 32) : UInt32.ofBitVec (a % b) = UInt32.ofBitVec a % UInt32.ofBitVec b := rfl +@[simp] theorem UInt64.ofBitVec_mod (a b : BitVec 64) : UInt64.ofBitVec (a % b) = UInt64.ofBitVec a % UInt64.ofBitVec b := rfl +@[simp] theorem USize.ofBitVec_mod (a b : BitVec System.Platform.numBits) : USize.ofBitVec (a % b) = USize.ofBitVec a % USize.ofBitVec b := rfl + +theorem UInt8.ofNat_eq_iff_mod_eq_toNat (a : Nat) (b : UInt8) : UInt8.ofNat a = b ↔ a % 2 ^ 8 = b.toNat := by + simp [← UInt8.toNat_inj] +theorem UInt16.ofNat_eq_iff_mod_eq_toNat (a : Nat) (b : UInt16) : UInt16.ofNat a = b ↔ a % 2 ^ 16 = b.toNat := by + simp [← UInt16.toNat_inj] +theorem UInt32.ofNat_eq_iff_mod_eq_toNat (a : Nat) (b : UInt32) : UInt32.ofNat a = b ↔ a % 2 ^ 32 = b.toNat := by + simp [← UInt32.toNat_inj] +theorem UInt64.ofNat_eq_iff_mod_eq_toNat (a : Nat) (b : UInt64) : UInt64.ofNat a = b ↔ a % 2 ^ 64 = b.toNat := by + simp [← UInt64.toNat_inj] +theorem USize.ofNat_eq_iff_mod_eq_toNat (a : Nat) (b : USize) : USize.ofNat a = b ↔ a % 2 ^ System.Platform.numBits = b.toNat := by + simp [← USize.toNat_inj] + +@[simp] theorem UInt8.ofNat_div {a b : Nat} (ha : a < 2 ^ 8) (hb : b < 2 ^ 8) : + UInt8.ofNat (a / b) = UInt8.ofNat a / UInt8.ofNat b := by + simp [UInt8.ofNat_eq_iff_mod_eq_toNat, Nat.div_mod_eq_mod_div_mod ha hb] +@[simp] theorem UInt16.ofNat_div {a b : Nat} (ha : a < 2 ^ 16) (hb : b < 2 ^ 16) : + UInt16.ofNat (a / b) = UInt16.ofNat a / UInt16.ofNat b := by + simp [UInt16.ofNat_eq_iff_mod_eq_toNat, Nat.div_mod_eq_mod_div_mod ha hb] +@[simp] theorem UInt32.ofNat_div {a b : Nat} (ha : a < 2 ^ 32) (hb : b < 2 ^ 32) : + UInt32.ofNat (a / b) = UInt32.ofNat a / UInt32.ofNat b := by + simp [UInt32.ofNat_eq_iff_mod_eq_toNat, Nat.div_mod_eq_mod_div_mod ha hb] +@[simp] theorem UInt64.ofNat_div {a b : Nat} (ha : a < 2 ^ 64) (hb : b < 2 ^ 64) : + UInt64.ofNat (a / b) = UInt64.ofNat a / UInt64.ofNat b := by + simp [UInt64.ofNat_eq_iff_mod_eq_toNat, Nat.div_mod_eq_mod_div_mod ha hb] +@[simp] theorem USize.ofNat_div {a b : Nat} (ha : a < 2 ^ System.Platform.numBits) (hb : b < 2 ^ System.Platform.numBits) : + USize.ofNat (a / b) = USize.ofNat a / USize.ofNat b := by + simp [USize.ofNat_eq_iff_mod_eq_toNat, Nat.div_mod_eq_mod_div_mod ha hb] + +@[simp] theorem UInt8.ofNatLT_div {a b : Nat} (ha : a < 2 ^ 8) (hb : b < 2 ^ 8) : + UInt8.ofNatLT (a / b) (Nat.div_lt_of_lt ha) = UInt8.ofNatLT a ha / UInt8.ofNatLT b hb := by + simp [UInt8.ofNatLT_eq_ofNat, UInt8.ofNat_div ha hb] +@[simp] theorem UInt16.ofNatLT_div {a b : Nat} (ha : a < 2 ^ 16) (hb : b < 2 ^ 16) : + UInt16.ofNatLT (a / b) (Nat.div_lt_of_lt ha) = UInt16.ofNatLT a ha / UInt16.ofNatLT b hb := by + simp [UInt16.ofNatLT_eq_ofNat, UInt16.ofNat_div ha hb] +@[simp] theorem UInt32.ofNatLT_div {a b : Nat} (ha : a < 2 ^ 32) (hb : b < 2 ^ 32) : + UInt32.ofNatLT (a / b) (Nat.div_lt_of_lt ha) = UInt32.ofNatLT a ha / UInt32.ofNatLT b hb := by + simp [UInt32.ofNatLT_eq_ofNat, UInt32.ofNat_div ha hb] +@[simp] theorem UInt64.ofNatLT_div {a b : Nat} (ha : a < 2 ^ 64) (hb : b < 2 ^ 64) : + UInt64.ofNatLT (a / b) (Nat.div_lt_of_lt ha) = UInt64.ofNatLT a ha / UInt64.ofNatLT b hb := by + simp [UInt64.ofNatLT_eq_ofNat, UInt64.ofNat_div ha hb] +@[simp] theorem USize.ofNatLT_div {a b : Nat} (ha : a < 2 ^ System.Platform.numBits) (hb : b < 2 ^ System.Platform.numBits) : + USize.ofNatLT (a / b) (Nat.div_lt_of_lt ha) = USize.ofNatLT a ha / USize.ofNatLT b hb := by + simp [USize.ofNatLT_eq_ofNat, USize.ofNat_div ha hb] + +@[simp] theorem UInt8.ofNat_mod {a b : Nat} (ha : a < 2 ^ 8) (hb : b < 2 ^ 8) : + UInt8.ofNat (a % b) = UInt8.ofNat a % UInt8.ofNat b := by + simp [UInt8.ofNat_eq_iff_mod_eq_toNat, Nat.mod_mod_eq_mod_mod_mod ha hb] +@[simp] theorem UInt16.ofNat_mod {a b : Nat} (ha : a < 2 ^ 16) (hb : b < 2 ^ 16) : + UInt16.ofNat (a % b) = UInt16.ofNat a % UInt16.ofNat b := by + simp [UInt16.ofNat_eq_iff_mod_eq_toNat, Nat.mod_mod_eq_mod_mod_mod ha hb] +@[simp] theorem UInt32.ofNat_mod {a b : Nat} (ha : a < 2 ^ 32) (hb : b < 2 ^ 32) : + UInt32.ofNat (a % b) = UInt32.ofNat a % UInt32.ofNat b := by + simp [UInt32.ofNat_eq_iff_mod_eq_toNat, Nat.mod_mod_eq_mod_mod_mod ha hb] +@[simp] theorem UInt64.ofNat_mod {a b : Nat} (ha : a < 2 ^ 64) (hb : b < 2 ^ 64) : + UInt64.ofNat (a % b) = UInt64.ofNat a % UInt64.ofNat b := by + simp [UInt64.ofNat_eq_iff_mod_eq_toNat, Nat.mod_mod_eq_mod_mod_mod ha hb] +@[simp] theorem USize.ofNat_mod {a b : Nat} (ha : a < 2 ^ System.Platform.numBits) (hb : b < 2 ^ System.Platform.numBits) : + USize.ofNat (a % b) = USize.ofNat a % USize.ofNat b := by + simp [USize.ofNat_eq_iff_mod_eq_toNat, Nat.mod_mod_eq_mod_mod_mod ha hb] + +@[simp] theorem UInt8.ofNatLT_mod {a b : Nat} (ha : a < 2 ^ 8) (hb : b < 2 ^ 8) : + UInt8.ofNatLT (a % b) (Nat.mod_lt_of_lt ha) = UInt8.ofNatLT a ha % UInt8.ofNatLT b hb := by + simp [UInt8.ofNatLT_eq_ofNat, UInt8.ofNat_mod ha hb] +@[simp] theorem UInt16.ofNatLT_mod {a b : Nat} (ha : a < 2 ^ 16) (hb : b < 2 ^ 16) : + UInt16.ofNatLT (a % b) (Nat.mod_lt_of_lt ha) = UInt16.ofNatLT a ha % UInt16.ofNatLT b hb := by + simp [UInt16.ofNatLT_eq_ofNat, UInt16.ofNat_mod ha hb] +@[simp] theorem UInt32.ofNatLT_mod {a b : Nat} (ha : a < 2 ^ 32) (hb : b < 2 ^ 32) : + UInt32.ofNatLT (a % b) (Nat.mod_lt_of_lt ha) = UInt32.ofNatLT a ha % UInt32.ofNatLT b hb := by + simp [UInt32.ofNatLT_eq_ofNat, UInt32.ofNat_mod ha hb] +@[simp] theorem UInt64.ofNatLT_mod {a b : Nat} (ha : a < 2 ^ 64) (hb : b < 2 ^ 64) : + UInt64.ofNatLT (a % b) (Nat.mod_lt_of_lt ha) = UInt64.ofNatLT a ha % UInt64.ofNatLT b hb := by + simp [UInt64.ofNatLT_eq_ofNat, UInt64.ofNat_mod ha hb] +@[simp] theorem USize.ofNatLT_mod {a b : Nat} (ha : a < 2 ^ System.Platform.numBits) (hb : b < 2 ^ System.Platform.numBits) : + USize.ofNatLT (a % b) (Nat.mod_lt_of_lt ha) = USize.ofNatLT a ha % USize.ofNatLT b hb := by + simp [USize.ofNatLT_eq_ofNat, USize.ofNat_mod ha hb] + +@[simp] theorem UInt8.ofNat_add (a b : Nat) : UInt8.ofNat (a + b) = UInt8.ofNat a + UInt8.ofNat b := by + simp [UInt8.ofNat_eq_iff_mod_eq_toNat] +@[simp] theorem UInt16.ofNat_add (a b : Nat) : UInt16.ofNat (a + b) = UInt16.ofNat a + UInt16.ofNat b := by + simp [UInt16.ofNat_eq_iff_mod_eq_toNat] +@[simp] theorem UInt32.ofNat_add (a b : Nat) : UInt32.ofNat (a + b) = UInt32.ofNat a + UInt32.ofNat b := by + simp [UInt32.ofNat_eq_iff_mod_eq_toNat] +@[simp] theorem UInt64.ofNat_add (a b : Nat) : UInt64.ofNat (a + b) = UInt64.ofNat a + UInt64.ofNat b := by + simp [UInt64.ofNat_eq_iff_mod_eq_toNat] +@[simp] theorem USize.ofNat_add (a b : Nat) : USize.ofNat (a + b) = USize.ofNat a + USize.ofNat b := by + simp [USize.ofNat_eq_iff_mod_eq_toNat] + +@[simp] theorem UInt8.ofNatLT_add {a b : Nat} (hab : a + b < 2 ^ 8) : + UInt8.ofNatLT (a + b) hab = UInt8.ofNatLT a (Nat.lt_of_add_right_lt hab) + UInt8.ofNatLT b (Nat.lt_of_add_left_lt hab) := by + simp [UInt8.ofNatLT_eq_ofNat] +@[simp] theorem UInt16.ofNatLT_add {a b : Nat} (hab : a + b < 2 ^ 16) : + UInt16.ofNatLT (a + b) hab = UInt16.ofNatLT a (Nat.lt_of_add_right_lt hab) + UInt16.ofNatLT b (Nat.lt_of_add_left_lt hab) := by + simp [UInt16.ofNatLT_eq_ofNat] +@[simp] theorem UInt32.ofNatLT_add {a b : Nat} (hab : a + b < 2 ^ 32) : + UInt32.ofNatLT (a + b) hab = UInt32.ofNatLT a (Nat.lt_of_add_right_lt hab) + UInt32.ofNatLT b (Nat.lt_of_add_left_lt hab) := by + simp [UInt32.ofNatLT_eq_ofNat] +@[simp] theorem UInt64.ofNatLT_add {a b : Nat} (hab : a + b < 2 ^ 64) : + UInt64.ofNatLT (a + b) hab = UInt64.ofNatLT a (Nat.lt_of_add_right_lt hab) + UInt64.ofNatLT b (Nat.lt_of_add_left_lt hab) := by + simp [UInt64.ofNatLT_eq_ofNat] +@[simp] theorem USize.ofNatLT_add {a b : Nat} (hab : a + b < 2 ^ System.Platform.numBits) : + USize.ofNatLT (a + b) hab = USize.ofNatLT a (Nat.lt_of_add_right_lt hab) + USize.ofNatLT b (Nat.lt_of_add_left_lt hab) := by + simp [USize.ofNatLT_eq_ofNat] + +@[simp] theorem UInt8.ofFin_add (a b : Fin UInt8.size) : UInt8.ofFin (a + b) = UInt8.ofFin a + UInt8.ofFin b := rfl +@[simp] theorem UInt16.ofFin_add (a b : Fin UInt16.size) : UInt16.ofFin (a + b) = UInt16.ofFin a + UInt16.ofFin b := rfl +@[simp] theorem UInt32.ofFin_add (a b : Fin UInt32.size) : UInt32.ofFin (a + b) = UInt32.ofFin a + UInt32.ofFin b := rfl +@[simp] theorem UInt64.ofFin_add (a b : Fin UInt64.size) : UInt64.ofFin (a + b) = UInt64.ofFin a + UInt64.ofFin b := rfl +@[simp] theorem USize.ofFin_add (a b : Fin USize.size) : USize.ofFin (a + b) = USize.ofFin a + USize.ofFin b := rfl + +@[simp] theorem UInt8.ofBitVec_add (a b : BitVec 8) : UInt8.ofBitVec (a + b) = UInt8.ofBitVec a + UInt8.ofBitVec b := rfl +@[simp] theorem UInt16.ofBitVec_add (a b : BitVec 16) : UInt16.ofBitVec (a + b) = UInt16.ofBitVec a + UInt16.ofBitVec b := rfl +@[simp] theorem UInt32.ofBitVec_add (a b : BitVec 32) : UInt32.ofBitVec (a + b) = UInt32.ofBitVec a + UInt32.ofBitVec b := rfl +@[simp] theorem UInt64.ofBitVec_add (a b : BitVec 64) : UInt64.ofBitVec (a + b) = UInt64.ofBitVec a + UInt64.ofBitVec b := rfl +@[simp] theorem USize.ofBitVec_add (a b : BitVec System.Platform.numBits) : USize.ofBitVec (a + b) = USize.ofBitVec a + USize.ofBitVec b := rfl + +@[simp] theorem UInt8.ofFin_sub (a b : Fin UInt8.size) : UInt8.ofFin (a - b) = UInt8.ofFin a - UInt8.ofFin b := rfl +@[simp] theorem UInt16.ofFin_sub (a b : Fin UInt16.size) : UInt16.ofFin (a - b) = UInt16.ofFin a - UInt16.ofFin b := rfl +@[simp] theorem UInt32.ofFin_sub (a b : Fin UInt32.size) : UInt32.ofFin (a - b) = UInt32.ofFin a - UInt32.ofFin b := rfl +@[simp] theorem UInt64.ofFin_sub (a b : Fin UInt64.size) : UInt64.ofFin (a - b) = UInt64.ofFin a - UInt64.ofFin b := rfl +@[simp] theorem USize.ofFin_sub (a b : Fin USize.size) : USize.ofFin (a - b) = USize.ofFin a - USize.ofFin b := rfl + +@[simp] theorem UInt8.ofBitVec_sub (a b : BitVec 8) : UInt8.ofBitVec (a - b) = UInt8.ofBitVec a - UInt8.ofBitVec b := rfl +@[simp] theorem UInt16.ofBitVec_sub (a b : BitVec 16) : UInt16.ofBitVec (a - b) = UInt16.ofBitVec a - UInt16.ofBitVec b := rfl +@[simp] theorem UInt32.ofBitVec_sub (a b : BitVec 32) : UInt32.ofBitVec (a - b) = UInt32.ofBitVec a - UInt32.ofBitVec b := rfl +@[simp] theorem UInt64.ofBitVec_sub (a b : BitVec 64) : UInt64.ofBitVec (a - b) = UInt64.ofBitVec a - UInt64.ofBitVec b := rfl +@[simp] theorem USize.ofBitVec_sub (a b : BitVec System.Platform.numBits) : USize.ofBitVec (a - b) = USize.ofBitVec a - USize.ofBitVec b := rfl + +theorem UInt8.add_sub_cancel (a b : UInt8) : a + b - b = a := UInt8.toBitVec_inj.1 (BitVec.add_sub_cancel _ _) +theorem UInt16.add_sub_cancel (a b : UInt16) : a + b - b = a := UInt16.toBitVec_inj.1 (BitVec.add_sub_cancel _ _) +theorem UInt32.add_sub_cancel (a b : UInt32) : a + b - b = a := UInt32.toBitVec_inj.1 (BitVec.add_sub_cancel _ _) +theorem UInt64.add_sub_cancel (a b : UInt64) : a + b - b = a := UInt64.toBitVec_inj.1 (BitVec.add_sub_cancel _ _) +theorem USize.add_sub_cancel (a b : USize) : a + b - b = a := USize.toBitVec_inj.1 (BitVec.add_sub_cancel _ _) + +theorem UInt8.ofNat_sub {a b : Nat} (hab : b ≤ a) : UInt8.ofNat (a - b) = UInt8.ofNat a - UInt8.ofNat b := by + rw [(Nat.sub_add_cancel hab ▸ UInt8.ofNat_add (a - b) b :), UInt8.add_sub_cancel] +theorem UInt16.ofNat_sub {a b : Nat} (hab : b ≤ a) : UInt16.ofNat (a - b) = UInt16.ofNat a - UInt16.ofNat b := by + rw [(Nat.sub_add_cancel hab ▸ UInt16.ofNat_add (a - b) b :), UInt16.add_sub_cancel] +theorem UInt32.ofNat_sub {a b : Nat} (hab : b ≤ a) : UInt32.ofNat (a - b) = UInt32.ofNat a - UInt32.ofNat b := by + rw [(Nat.sub_add_cancel hab ▸ UInt32.ofNat_add (a - b) b :), UInt32.add_sub_cancel] +theorem UInt64.ofNat_sub {a b : Nat} (hab : b ≤ a) : UInt64.ofNat (a - b) = UInt64.ofNat a - UInt64.ofNat b := by + rw [(Nat.sub_add_cancel hab ▸ UInt64.ofNat_add (a - b) b :), UInt64.add_sub_cancel] +theorem USize.ofNat_sub {a b : Nat} (hab : b ≤ a) : USize.ofNat (a - b) = USize.ofNat a - USize.ofNat b := by + rw [(Nat.sub_add_cancel hab ▸ USize.ofNat_add (a - b) b :), USize.add_sub_cancel] + +theorem UInt8.ofNatLT_sub {a b : Nat} (ha : a < 2 ^ 8) (hab : b ≤ a) : + UInt8.ofNatLT (a - b) (Nat.sub_lt_of_lt ha) = UInt8.ofNatLT a ha - UInt8.ofNatLT b (Nat.lt_of_le_of_lt hab ha) := by + simp [UInt8.ofNatLT_eq_ofNat, UInt8.ofNat_sub hab] +theorem UInt16.ofNatLT_sub {a b : Nat} (ha : a < 2 ^ 16) (hab : b ≤ a) : + UInt16.ofNatLT (a - b) (Nat.sub_lt_of_lt ha) = UInt16.ofNatLT a ha - UInt16.ofNatLT b (Nat.lt_of_le_of_lt hab ha) := by + simp [UInt16.ofNatLT_eq_ofNat, UInt16.ofNat_sub hab] +theorem UInt32.ofNatLT_sub {a b : Nat} (ha : a < 2 ^ 32) (hab : b ≤ a) : + UInt32.ofNatLT (a - b) (Nat.sub_lt_of_lt ha) = UInt32.ofNatLT a ha - UInt32.ofNatLT b (Nat.lt_of_le_of_lt hab ha) := by + simp [UInt32.ofNatLT_eq_ofNat, UInt32.ofNat_sub hab] +theorem UInt64.ofNatLT_sub {a b : Nat} (ha : a < 2 ^ 64) (hab : b ≤ a) : + UInt64.ofNatLT (a - b) (Nat.sub_lt_of_lt ha) = UInt64.ofNatLT a ha - UInt64.ofNatLT b (Nat.lt_of_le_of_lt hab ha) := by + simp [UInt64.ofNatLT_eq_ofNat, UInt64.ofNat_sub hab] +theorem USize.ofNatLT_sub {a b : Nat} (ha : a < 2 ^ System.Platform.numBits) (hab : b ≤ a) : + USize.ofNatLT (a - b) (Nat.sub_lt_of_lt ha) = USize.ofNatLT a ha - USize.ofNatLT b (Nat.lt_of_le_of_lt hab ha) := by + simp [USize.ofNatLT_eq_ofNat, USize.ofNat_sub hab] + +@[simp] theorem UInt8.ofNat_mul (a b : Nat) : UInt8.ofNat (a * b) = UInt8.ofNat a * UInt8.ofNat b := by + simp [UInt8.ofNat_eq_iff_mod_eq_toNat] +@[simp] theorem UInt16.ofNat_mul (a b : Nat) : UInt16.ofNat (a * b) = UInt16.ofNat a * UInt16.ofNat b := by + simp [UInt16.ofNat_eq_iff_mod_eq_toNat] +@[simp] theorem UInt32.ofNat_mul (a b : Nat) : UInt32.ofNat (a * b) = UInt32.ofNat a * UInt32.ofNat b := by + simp [UInt32.ofNat_eq_iff_mod_eq_toNat] +@[simp] theorem UInt64.ofNat_mul (a b : Nat) : UInt64.ofNat (a * b) = UInt64.ofNat a * UInt64.ofNat b := by + simp [UInt64.ofNat_eq_iff_mod_eq_toNat] +@[simp] theorem USize.ofNat_mul (a b : Nat) : USize.ofNat (a * b) = USize.ofNat a * USize.ofNat b := by + simp [USize.ofNat_eq_iff_mod_eq_toNat] + +@[simp] theorem UInt8.ofNatLT_mul {a b : Nat} (ha : a < 2 ^ 8) (hb : b < 2 ^ 8) (hab : a * b < 2 ^ 8) : + UInt8.ofNatLT (a * b) hab = UInt8.ofNatLT a ha * UInt8.ofNatLT b hb := by + simp [UInt8.ofNatLT_eq_ofNat] +@[simp] theorem UInt16.ofNatLT_mul {a b : Nat} (ha : a < 2 ^ 16) (hb : b < 2 ^ 16) (hab : a * b < 2 ^ 16) : + UInt16.ofNatLT (a * b) hab = UInt16.ofNatLT a ha * UInt16.ofNatLT b hb := by + simp [UInt16.ofNatLT_eq_ofNat] +@[simp] theorem UInt32.ofNatLT_mul {a b : Nat} (ha : a < 2 ^ 32) (hb : b < 2 ^ 32) (hab : a * b < 2 ^ 32) : + UInt32.ofNatLT (a * b) hab = UInt32.ofNatLT a ha * UInt32.ofNatLT b hb := by + simp [UInt32.ofNatLT_eq_ofNat] +@[simp] theorem UInt64.ofNatLT_mul {a b : Nat} (ha : a < 2 ^ 64) (hb : b < 2 ^ 64) (hab : a * b < 2 ^ 64) : + UInt64.ofNatLT (a * b) hab = UInt64.ofNatLT a ha * UInt64.ofNatLT b hb := by + simp [UInt64.ofNatLT_eq_ofNat] +@[simp] theorem USize.ofNatLT_mul {a b : Nat} (ha : a < 2 ^ System.Platform.numBits) + (hb : b < 2 ^ System.Platform.numBits) (hab : a * b < 2 ^ System.Platform.numBits) : + USize.ofNatLT (a * b) hab = USize.ofNatLT a ha * USize.ofNatLT b hb := by + simp [USize.ofNatLT_eq_ofNat] + +@[simp] theorem UInt8.ofFin_mul (a b : Fin UInt8.size) : UInt8.ofFin (a * b) = UInt8.ofFin a * UInt8.ofFin b := rfl +@[simp] theorem UInt16.ofFin_mul (a b : Fin UInt16.size) : UInt16.ofFin (a * b) = UInt16.ofFin a * UInt16.ofFin b := rfl +@[simp] theorem UInt32.ofFin_mul (a b : Fin UInt32.size) : UInt32.ofFin (a * b) = UInt32.ofFin a * UInt32.ofFin b := rfl +@[simp] theorem UInt64.ofFin_mul (a b : Fin UInt64.size) : UInt64.ofFin (a * b) = UInt64.ofFin a * UInt64.ofFin b := rfl +@[simp] theorem USize.ofFin_mul (a b : Fin USize.size) : USize.ofFin (a * b) = USize.ofFin a * USize.ofFin b := rfl + +@[simp] theorem UInt8.ofBitVec_mul (a b : BitVec 8) : UInt8.ofBitVec (a * b) = UInt8.ofBitVec a * UInt8.ofBitVec b := rfl +@[simp] theorem UInt16.ofBitVec_mul (a b : BitVec 16) : UInt16.ofBitVec (a * b) = UInt16.ofBitVec a * UInt16.ofBitVec b := rfl +@[simp] theorem UInt32.ofBitVec_mul (a b : BitVec 32) : UInt32.ofBitVec (a * b) = UInt32.ofBitVec a * UInt32.ofBitVec b := rfl +@[simp] theorem UInt64.ofBitVec_mul (a b : BitVec 64) : UInt64.ofBitVec (a * b) = UInt64.ofBitVec a * UInt64.ofBitVec b := rfl +@[simp] theorem USize.ofBitVec_mul (a b : BitVec System.Platform.numBits) : USize.ofBitVec (a * b) = USize.ofBitVec a * USize.ofBitVec b := rfl + +theorem UInt8.ofFin_lt_iff_lt {a b : Fin UInt8.size} : UInt8.ofFin a < UInt8.ofFin b ↔ a < b := Iff.rfl +theorem UInt16.ofFin_lt_iff_lt {a b : Fin UInt16.size} : UInt16.ofFin a < UInt16.ofFin b ↔ a < b := Iff.rfl +theorem UInt32.ofFin_lt_iff_lt {a b : Fin UInt32.size} : UInt32.ofFin a < UInt32.ofFin b ↔ a < b := Iff.rfl +theorem UInt64.ofFin_lt_iff_lt {a b : Fin UInt64.size} : UInt64.ofFin a < UInt64.ofFin b ↔ a < b := Iff.rfl +theorem USize.ofFin_lt_iff_lt {a b : Fin USize.size} : USize.ofFin a < USize.ofFin b ↔ a < b := Iff.rfl + +theorem UInt8.ofFin_le_iff_le {a b : Fin UInt8.size} : UInt8.ofFin a ≤ UInt8.ofFin b ↔ a ≤ b := Iff.rfl +theorem UInt16.ofFin_le_iff_le {a b : Fin UInt16.size} : UInt16.ofFin a ≤ UInt16.ofFin b ↔ a ≤ b := Iff.rfl +theorem UInt32.ofFin_le_iff_le {a b : Fin UInt32.size} : UInt32.ofFin a ≤ UInt32.ofFin b ↔ a ≤ b := Iff.rfl +theorem UInt64.ofFin_le_iff_le {a b : Fin UInt64.size} : UInt64.ofFin a ≤ UInt64.ofFin b ↔ a ≤ b := Iff.rfl +theorem USize.ofFin_le_iff_le {a b : Fin USize.size} : USize.ofFin a ≤ USize.ofFin b ↔ a ≤ b := Iff.rfl + +theorem UInt8.ofBitVec_lt_iff_lt {a b : BitVec 8} : UInt8.ofBitVec a < UInt8.ofBitVec b ↔ a < b := Iff.rfl +theorem UInt16.ofBitVec_lt_iff_lt {a b : BitVec 16} : UInt16.ofBitVec a < UInt16.ofBitVec b ↔ a < b := Iff.rfl +theorem UInt32.ofBitVec_lt_iff_lt {a b : BitVec 32} : UInt32.ofBitVec a < UInt32.ofBitVec b ↔ a < b := Iff.rfl +theorem UInt64.ofBitVec_lt_iff_lt {a b : BitVec 64} : UInt64.ofBitVec a < UInt64.ofBitVec b ↔ a < b := Iff.rfl +theorem USize.ofBitVec_lt_iff_lt {a b : BitVec System.Platform.numBits} : USize.ofBitVec a < USize.ofBitVec b ↔ a < b := Iff.rfl + +theorem UInt8.ofBitVec_le_iff_le {a b : BitVec 8} : UInt8.ofBitVec a ≤ UInt8.ofBitVec b ↔ a ≤ b := Iff.rfl +theorem UInt16.ofBitVec_le_iff_le {a b : BitVec 16} : UInt16.ofBitVec a ≤ UInt16.ofBitVec b ↔ a ≤ b := Iff.rfl +theorem UInt32.ofBitVec_le_iff_le {a b : BitVec 32} : UInt32.ofBitVec a ≤ UInt32.ofBitVec b ↔ a ≤ b := Iff.rfl +theorem UInt64.ofBitVec_le_iff_le {a b : BitVec 64} : UInt64.ofBitVec a ≤ UInt64.ofBitVec b ↔ a ≤ b := Iff.rfl +theorem USize.ofBitVec_le_iff_le {a b : BitVec System.Platform.numBits} : USize.ofBitVec a ≤ USize.ofBitVec b ↔ a ≤ b := Iff.rfl + +theorem UInt8.ofNatLT_lt_iff_lt {a b : Nat} (ha : a < UInt8.size) (hb : b < UInt8.size) : + UInt8.ofNatLT a ha < UInt8.ofNatLT b hb ↔ a < b := Iff.rfl +theorem UInt16.ofNatLT_lt_iff_lt {a b : Nat} (ha : a < UInt16.size) (hb : b < UInt16.size) : + UInt16.ofNatLT a ha < UInt16.ofNatLT b hb ↔ a < b := Iff.rfl +theorem UInt32.ofNatLT_lt_iff_lt {a b : Nat} (ha : a < UInt32.size) (hb : b < UInt32.size) : + UInt32.ofNatLT a ha < UInt32.ofNatLT b hb ↔ a < b := Iff.rfl +theorem UInt64.ofNatLT_lt_iff_lt {a b : Nat} (ha : a < UInt64.size) (hb : b < UInt64.size) : + UInt64.ofNatLT a ha < UInt64.ofNatLT b hb ↔ a < b := Iff.rfl +theorem USize.ofNatLT_lt_iff_lt {a b : Nat} (ha : a < USize.size) (hb : b < USize.size) : + USize.ofNatLT a ha < USize.ofNatLT b hb ↔ a < b := Iff.rfl + +theorem UInt8.ofNatLT_le_iff_le {a b : Nat} (ha : a < UInt8.size) (hb : b < UInt8.size) : + UInt8.ofNatLT a ha ≤ UInt8.ofNatLT b hb ↔ a ≤ b := Iff.rfl +theorem UInt16.ofNatLT_le_iff_le {a b : Nat} (ha : a < UInt16.size) (hb : b < UInt16.size) : + UInt16.ofNatLT a ha ≤ UInt16.ofNatLT b hb ↔ a ≤ b := Iff.rfl +theorem UInt32.ofNatLT_le_iff_le {a b : Nat} (ha : a < UInt32.size) (hb : b < UInt32.size) : + UInt32.ofNatLT a ha ≤ UInt32.ofNatLT b hb ↔ a ≤ b := Iff.rfl +theorem UInt64.ofNatLT_le_iff_le {a b : Nat} (ha : a < UInt64.size) (hb : b < UInt64.size) : + UInt64.ofNatLT a ha ≤ UInt64.ofNatLT b hb ↔ a ≤ b := Iff.rfl +theorem USize.ofNatLT_le_iff_le {a b : Nat} (ha : a < USize.size) (hb : b < USize.size) : + USize.ofNatLT a ha ≤ USize.ofNatLT b hb ↔ a ≤ b := Iff.rfl + +theorem UInt8.ofNat_lt_iff_lt {a b : Nat} (ha : a < UInt8.size) (hb : b < UInt8.size) : + UInt8.ofNat a < UInt8.ofNat b ↔ a < b := by + rw [← ofNatLT_eq_ofNat (h := ha), ← ofNatLT_eq_ofNat (h := hb), ofNatLT_lt_iff_lt] +theorem UInt16.ofNat_lt_iff_lt {a b : Nat} (ha : a < UInt16.size) (hb : b < UInt16.size) : + UInt16.ofNat a < UInt16.ofNat b ↔ a < b := by + rw [← ofNatLT_eq_ofNat (h := ha), ← ofNatLT_eq_ofNat (h := hb), ofNatLT_lt_iff_lt] +theorem UInt32.ofNat_lt_iff_lt {a b : Nat} (ha : a < UInt32.size) (hb : b < UInt32.size) : + UInt32.ofNat a < UInt32.ofNat b ↔ a < b := by + rw [← ofNatLT_eq_ofNat (h := ha), ← ofNatLT_eq_ofNat (h := hb), ofNatLT_lt_iff_lt] +theorem UInt64.ofNat_lt_iff_lt {a b : Nat} (ha : a < UInt64.size) (hb : b < UInt64.size) : + UInt64.ofNat a < UInt64.ofNat b ↔ a < b := by + rw [← ofNatLT_eq_ofNat (h := ha), ← ofNatLT_eq_ofNat (h := hb), ofNatLT_lt_iff_lt] +theorem USize.ofNat_lt_iff_lt {a b : Nat} (ha : a < USize.size) (hb : b < USize.size) : + USize.ofNat a < USize.ofNat b ↔ a < b := by + rw [← ofNatLT_eq_ofNat (h := ha), ← ofNatLT_eq_ofNat (h := hb), ofNatLT_lt_iff_lt] + +theorem UInt8.ofNat_le_iff_le {a b : Nat} (ha : a < UInt8.size) (hb : b < UInt8.size) : + UInt8.ofNat a ≤ UInt8.ofNat b ↔ a ≤ b := by + rw [← ofNatLT_eq_ofNat (h := ha), ← ofNatLT_eq_ofNat (h := hb), ofNatLT_le_iff_le] +theorem UInt16.ofNat_le_iff_le {a b : Nat} (ha : a < UInt16.size) (hb : b < UInt16.size) : + UInt16.ofNat a ≤ UInt16.ofNat b ↔ a ≤ b := by + rw [← ofNatLT_eq_ofNat (h := ha), ← ofNatLT_eq_ofNat (h := hb), ofNatLT_le_iff_le] +theorem UInt32.ofNat_le_iff_le {a b : Nat} (ha : a < UInt32.size) (hb : b < UInt32.size) : + UInt32.ofNat a ≤ UInt32.ofNat b ↔ a ≤ b := by + rw [← ofNatLT_eq_ofNat (h := ha), ← ofNatLT_eq_ofNat (h := hb), ofNatLT_le_iff_le] +theorem UInt64.ofNat_le_iff_le {a b : Nat} (ha : a < UInt64.size) (hb : b < UInt64.size) : + UInt64.ofNat a ≤ UInt64.ofNat b ↔ a ≤ b := by + rw [← ofNatLT_eq_ofNat (h := ha), ← ofNatLT_eq_ofNat (h := hb), ofNatLT_le_iff_le] +theorem USize.ofNat_le_iff_le {a b : Nat} (ha : a < USize.size) (hb : b < USize.size) : + USize.ofNat a ≤ USize.ofNat b ↔ a ≤ b := by + rw [← ofNatLT_eq_ofNat (h := ha), ← ofNatLT_eq_ofNat (h := hb), ofNatLT_le_iff_le] + +theorem UInt8.toNat_one : (1 : UInt8).toNat = 1 := rfl +theorem UInt16.toNat_one : (1 : UInt16).toNat = 1 := rfl +theorem UInt32.toNat_one : (1 : UInt32).toNat = 1 := rfl +theorem UInt64.toNat_one : (1 : UInt64).toNat = 1 := rfl +theorem USize.toNat_one : (1 : USize).toNat = 1 := by simp + +theorem UInt8.zero_lt_one : (0 : UInt8) < 1 := by simp +theorem UInt16.zero_lt_one : (0 : UInt16) < 1 := by simp +theorem UInt32.zero_lt_one : (0 : UInt32) < 1 := by simp +theorem UInt64.zero_lt_one : (0 : UInt64) < 1 := by simp +theorem USize.zero_lt_one : (0 : USize) < 1 := by simp [lt_iff_toNat_lt] + +theorem UInt8.zero_ne_one : (0 : UInt8) ≠ 1 := by simp +theorem UInt16.zero_ne_one : (0 : UInt16) ≠ 1 := by simp +theorem UInt32.zero_ne_one : (0 : UInt32) ≠ 1 := by simp +theorem UInt64.zero_ne_one : (0 : UInt64) ≠ 1 := by simp +theorem USize.zero_ne_one : (0 : USize) ≠ 1 := by simp [← USize.toNat_inj] + +theorem UInt8.add_assoc (a b c : UInt8) : a + b + c = a + (b + c) := + UInt8.toBitVec_inj.1 (BitVec.add_assoc _ _ _) +theorem UInt16.add_assoc (a b c : UInt16) : a + b + c = a + (b + c) := + UInt16.toBitVec_inj.1 (BitVec.add_assoc _ _ _) +theorem UInt32.add_assoc (a b c : UInt32) : a + b + c = a + (b + c) := + UInt32.toBitVec_inj.1 (BitVec.add_assoc _ _ _) +theorem UInt64.add_assoc (a b c : UInt64) : a + b + c = a + (b + c) := + UInt64.toBitVec_inj.1 (BitVec.add_assoc _ _ _) +theorem USize.add_assoc (a b c : USize) : a + b + c = a + (b + c) := + USize.toBitVec_inj.1 (BitVec.add_assoc _ _ _) + +instance : Std.Associative (α := UInt8) (· + ·) := ⟨UInt8.add_assoc⟩ +instance : Std.Associative (α := UInt16) (· + ·) := ⟨UInt16.add_assoc⟩ +instance : Std.Associative (α := UInt32) (· + ·) := ⟨UInt32.add_assoc⟩ +instance : Std.Associative (α := UInt64) (· + ·) := ⟨UInt64.add_assoc⟩ +instance : Std.Associative (α := USize) (· + ·) := ⟨USize.add_assoc⟩ + +theorem UInt8.add_comm (a b : UInt8) : a + b = b + a := UInt8.toBitVec_inj.1 (BitVec.add_comm _ _) +theorem UInt16.add_comm (a b : UInt16) : a + b = b + a := UInt16.toBitVec_inj.1 (BitVec.add_comm _ _) +theorem UInt32.add_comm (a b : UInt32) : a + b = b + a := UInt32.toBitVec_inj.1 (BitVec.add_comm _ _) +theorem UInt64.add_comm (a b : UInt64) : a + b = b + a := UInt64.toBitVec_inj.1 (BitVec.add_comm _ _) +theorem USize.add_comm (a b : USize) : a + b = b + a := USize.toBitVec_inj.1 (BitVec.add_comm _ _) + +instance : Std.Commutative (α := UInt8) (· + ·) := ⟨UInt8.add_comm⟩ +instance : Std.Commutative (α := UInt16) (· + ·) := ⟨UInt16.add_comm⟩ +instance : Std.Commutative (α := UInt32) (· + ·) := ⟨UInt32.add_comm⟩ +instance : Std.Commutative (α := UInt64) (· + ·) := ⟨UInt64.add_comm⟩ +instance : Std.Commutative (α := USize) (· + ·) := ⟨USize.add_comm⟩ + +@[simp] theorem UInt8.add_zero (a : UInt8) : a + 0 = a := UInt8.toBitVec_inj.1 (BitVec.add_zero _) +@[simp] theorem UInt16.add_zero (a : UInt16) : a + 0 = a := UInt16.toBitVec_inj.1 (BitVec.add_zero _) +@[simp] theorem UInt32.add_zero (a : UInt32) : a + 0 = a := UInt32.toBitVec_inj.1 (BitVec.add_zero _) +@[simp] theorem UInt64.add_zero (a : UInt64) : a + 0 = a := UInt64.toBitVec_inj.1 (BitVec.add_zero _) +@[simp] theorem USize.add_zero (a : USize) : a + 0 = a := USize.toBitVec_inj.1 (BitVec.add_zero _) + +@[simp] theorem UInt8.zero_add (a : UInt8) : 0 + a = a := UInt8.toBitVec_inj.1 (BitVec.zero_add _) +@[simp] theorem UInt16.zero_add (a : UInt16) : 0 + a = a := UInt16.toBitVec_inj.1 (BitVec.zero_add _) +@[simp] theorem UInt32.zero_add (a : UInt32) : 0 + a = a := UInt32.toBitVec_inj.1 (BitVec.zero_add _) +@[simp] theorem UInt64.zero_add (a : UInt64) : 0 + a = a := UInt64.toBitVec_inj.1 (BitVec.zero_add _) +@[simp] theorem USize.zero_add (a : USize) : 0 + a = a := USize.toBitVec_inj.1 (BitVec.zero_add _) + +instance : Std.LawfulIdentity (α := UInt8) (· + ·) 0 where + left_id := UInt8.zero_add + right_id := UInt8.add_zero +instance : Std.LawfulIdentity (α := UInt16) (· + ·) 0 where + left_id := UInt16.zero_add + right_id := UInt16.add_zero +instance : Std.LawfulIdentity (α := UInt32) (· + ·) 0 where + left_id := UInt32.zero_add + right_id := UInt32.add_zero +instance : Std.LawfulIdentity (α := UInt64) (· + ·) 0 where + left_id := UInt64.zero_add + right_id := UInt64.add_zero +instance : Std.LawfulIdentity (α := USize) (· + ·) 0 where + left_id := USize.zero_add + right_id := USize.add_zero + +@[simp] theorem UInt8.sub_zero (a : UInt8) : a - 0 = a := UInt8.toBitVec_inj.1 (BitVec.sub_zero _) +@[simp] theorem UInt16.sub_zero (a : UInt16) : a - 0 = a := UInt16.toBitVec_inj.1 (BitVec.sub_zero _) +@[simp] theorem UInt32.sub_zero (a : UInt32) : a - 0 = a := UInt32.toBitVec_inj.1 (BitVec.sub_zero _) +@[simp] theorem UInt64.sub_zero (a : UInt64) : a - 0 = a := UInt64.toBitVec_inj.1 (BitVec.sub_zero _) +@[simp] theorem USize.sub_zero (a : USize) : a - 0 = a := USize.toBitVec_inj.1 (BitVec.sub_zero _) + +@[simp] theorem UInt8.zero_sub (a : UInt8) : 0 - a = -a := UInt8.toBitVec_inj.1 (BitVec.zero_sub _) +@[simp] theorem UInt16.zero_sub (a : UInt16) : 0 - a = -a := UInt16.toBitVec_inj.1 (BitVec.zero_sub _) +@[simp] theorem UInt32.zero_sub (a : UInt32) : 0 - a = -a := UInt32.toBitVec_inj.1 (BitVec.zero_sub _) +@[simp] theorem UInt64.zero_sub (a : UInt64) : 0 - a = -a := UInt64.toBitVec_inj.1 (BitVec.zero_sub _) +@[simp] theorem USize.zero_sub (a : USize) : 0 - a = -a := USize.toBitVec_inj.1 (BitVec.zero_sub _) + +@[simp] theorem UInt8.sub_self (a : UInt8) : a - a = 0 := UInt8.toBitVec_inj.1 (BitVec.sub_self _) +@[simp] theorem UInt16.sub_self (a : UInt16) : a - a = 0 := UInt16.toBitVec_inj.1 (BitVec.sub_self _) +@[simp] theorem UInt32.sub_self (a : UInt32) : a - a = 0 := UInt32.toBitVec_inj.1 (BitVec.sub_self _) +@[simp] theorem UInt64.sub_self (a : UInt64) : a - a = 0 := UInt64.toBitVec_inj.1 (BitVec.sub_self _) +@[simp] theorem USize.sub_self (a : USize) : a - a = 0 := USize.toBitVec_inj.1 (BitVec.sub_self _) + +@[simp] theorem UInt8.neg_zero : -(0 : UInt8) = 0 := rfl +@[simp] theorem UInt16.neg_zero : -(0 : UInt16) = 0 := rfl +@[simp] theorem UInt32.neg_zero : -(0 : UInt32) = 0 := rfl +@[simp] theorem UInt64.neg_zero : -(0 : UInt64) = 0 := rfl +@[simp] theorem USize.neg_zero : -(0 : USize) = 0 := USize.toBitVec_inj.1 (BitVec.neg_zero _) + +@[simp] theorem UInt8.sub_add_cancel (a b : UInt8) : a - b + b = a := + UInt8.toBitVec_inj.1 (BitVec.sub_add_cancel _ _) +@[simp] theorem UInt16.sub_add_cancel (a b : UInt16) : a - b + b = a := + UInt16.toBitVec_inj.1 (BitVec.sub_add_cancel _ _) +@[simp] theorem UInt32.sub_add_cancel (a b : UInt32) : a - b + b = a := + UInt32.toBitVec_inj.1 (BitVec.sub_add_cancel _ _) +@[simp] theorem UInt64.sub_add_cancel (a b : UInt64) : a - b + b = a := + UInt64.toBitVec_inj.1 (BitVec.sub_add_cancel _ _) +@[simp] theorem USize.sub_add_cancel (a b : USize) : a - b + b = a := + USize.toBitVec_inj.1 (BitVec.sub_add_cancel _ _) + +theorem UInt8.eq_sub_iff_add_eq {a b c : UInt8} : a = c - b ↔ a + b = c := by + simpa [← UInt8.toBitVec_inj] using BitVec.eq_sub_iff_add_eq +theorem UInt16.eq_sub_iff_add_eq {a b c : UInt16} : a = c - b ↔ a + b = c := by + simpa [← UInt16.toBitVec_inj] using BitVec.eq_sub_iff_add_eq +theorem UInt32.eq_sub_iff_add_eq {a b c : UInt32} : a = c - b ↔ a + b = c := by + simpa [← UInt32.toBitVec_inj] using BitVec.eq_sub_iff_add_eq +theorem UInt64.eq_sub_iff_add_eq {a b c : UInt64} : a = c - b ↔ a + b = c := by + simpa [← UInt64.toBitVec_inj] using BitVec.eq_sub_iff_add_eq +theorem USize.eq_sub_iff_add_eq {a b c : USize} : a = c - b ↔ a + b = c := by + simpa [← USize.toBitVec_inj] using BitVec.eq_sub_iff_add_eq + +theorem UInt8.sub_eq_iff_eq_add {a b c : UInt8} : a - b = c ↔ a = c + b := by + simpa [← UInt8.toBitVec_inj] using BitVec.sub_eq_iff_eq_add +theorem UInt16.sub_eq_iff_eq_add {a b c : UInt16} : a - b = c ↔ a = c + b := by + simpa [← UInt16.toBitVec_inj] using BitVec.sub_eq_iff_eq_add +theorem UInt32.sub_eq_iff_eq_add {a b c : UInt32} : a - b = c ↔ a = c + b := by + simpa [← UInt32.toBitVec_inj] using BitVec.sub_eq_iff_eq_add +theorem UInt64.sub_eq_iff_eq_add {a b c : UInt64} : a - b = c ↔ a = c + b := by + simpa [← UInt64.toBitVec_inj] using BitVec.sub_eq_iff_eq_add +theorem USize.sub_eq_iff_eq_add {a b c : USize} : a - b = c ↔ a = c + b := by + simpa [← USize.toBitVec_inj] using BitVec.sub_eq_iff_eq_add + +@[simp] theorem UInt8.neg_neg {a : UInt8} : - -a = a := UInt8.toBitVec_inj.1 BitVec.neg_neg +@[simp] theorem UInt16.neg_neg {a : UInt16} : - -a = a := UInt16.toBitVec_inj.1 BitVec.neg_neg +@[simp] theorem UInt32.neg_neg {a : UInt32} : - -a = a := UInt32.toBitVec_inj.1 BitVec.neg_neg +@[simp] theorem UInt64.neg_neg {a : UInt64} : - -a = a := UInt64.toBitVec_inj.1 BitVec.neg_neg +@[simp] theorem USize.neg_neg {a : USize} : - -a = a := USize.toBitVec_inj.1 BitVec.neg_neg + +@[simp] theorem UInt8.neg_inj {a b : UInt8} : -a = -b ↔ a = b := by simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.neg_inj {a b : UInt16} : -a = -b ↔ a = b := by simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.neg_inj {a b : UInt32} : -a = -b ↔ a = b := by simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.neg_inj {a b : UInt64} : -a = -b ↔ a = b := by simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.neg_inj {a b : USize} : -a = -b ↔ a = b := by simp [← USize.toBitVec_inj] + +@[simp] theorem UInt8.neg_ne_zero {a : UInt8} : -a ≠ 0 ↔ a ≠ 0 := by simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.neg_ne_zero {a : UInt16} : -a ≠ 0 ↔ a ≠ 0 := by simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.neg_ne_zero {a : UInt32} : -a ≠ 0 ↔ a ≠ 0 := by simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.neg_ne_zero {a : UInt64} : -a ≠ 0 ↔ a ≠ 0 := by simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.neg_ne_zero {a : USize} : -a ≠ 0 ↔ a ≠ 0 := by simp [← USize.toBitVec_inj] + +theorem UInt8.neg_add {a b : UInt8} : - (a + b) = -a - b := UInt8.toBitVec_inj.1 BitVec.neg_add +theorem UInt16.neg_add {a b : UInt16} : - (a + b) = -a - b := UInt16.toBitVec_inj.1 BitVec.neg_add +theorem UInt32.neg_add {a b : UInt32} : - (a + b) = -a - b := UInt32.toBitVec_inj.1 BitVec.neg_add +theorem UInt64.neg_add {a b : UInt64} : - (a + b) = -a - b := UInt64.toBitVec_inj.1 BitVec.neg_add +theorem USize.neg_add {a b : USize} : - (a + b) = -a - b := USize.toBitVec_inj.1 BitVec.neg_add + +@[simp] theorem UInt8.sub_neg {a b : UInt8} : a - -b = a + b := UInt8.toBitVec_inj.1 BitVec.sub_neg +@[simp] theorem UInt16.sub_neg {a b : UInt16} : a - -b = a + b := UInt16.toBitVec_inj.1 BitVec.sub_neg +@[simp] theorem UInt32.sub_neg {a b : UInt32} : a - -b = a + b := UInt32.toBitVec_inj.1 BitVec.sub_neg +@[simp] theorem UInt64.sub_neg {a b : UInt64} : a - -b = a + b := UInt64.toBitVec_inj.1 BitVec.sub_neg +@[simp] theorem USize.sub_neg {a b : USize} : a - -b = a + b := USize.toBitVec_inj.1 BitVec.sub_neg + +@[simp] theorem UInt8.neg_sub {a b : UInt8} : -(a - b) = b - a := by + rw [sub_eq_add_neg, neg_add, sub_neg, add_comm, ← sub_eq_add_neg] +@[simp] theorem UInt16.neg_sub {a b : UInt16} : -(a - b) = b - a := by + rw [sub_eq_add_neg, neg_add, sub_neg, add_comm, ← sub_eq_add_neg] +@[simp] theorem UInt32.neg_sub {a b : UInt32} : -(a - b) = b - a := by + rw [sub_eq_add_neg, neg_add, sub_neg, add_comm, ← sub_eq_add_neg] +@[simp] theorem UInt64.neg_sub {a b : UInt64} : -(a - b) = b - a := by + rw [sub_eq_add_neg, neg_add, sub_neg, add_comm, ← sub_eq_add_neg] +@[simp] theorem USize.neg_sub {a b : USize} : -(a - b) = b - a := by + rw [sub_eq_add_neg, neg_add, sub_neg, add_comm, ← sub_eq_add_neg] + +@[simp] theorem UInt8.add_left_inj {a b : UInt8} (c : UInt8) : (a + c = b + c) ↔ a = b := by + simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.add_left_inj {a b : UInt16} (c : UInt16) : (a + c = b + c) ↔ a = b := by + simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.add_left_inj {a b : UInt32} (c : UInt32) : (a + c = b + c) ↔ a = b := by + simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.add_left_inj {a b : UInt64} (c : UInt64) : (a + c = b + c) ↔ a = b := by + simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.add_left_inj {a b : USize} (c : USize) : (a + c = b + c) ↔ a = b := by + simp [← USize.toBitVec_inj] + +@[simp] theorem UInt8.add_right_inj {a b : UInt8} (c : UInt8) : (c + a = c + b) ↔ a = b := by + simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.add_right_inj {a b : UInt16} (c : UInt16) : (c + a = c + b) ↔ a = b := by + simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.add_right_inj {a b : UInt32} (c : UInt32) : (c + a = c + b) ↔ a = b := by + simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.add_right_inj {a b : UInt64} (c : UInt64) : (c + a = c + b) ↔ a = b := by + simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.add_right_inj {a b : USize} (c : USize) : (c + a = c + b) ↔ a = b := by + simp [← USize.toBitVec_inj] + +@[simp] theorem UInt8.sub_left_inj {a b : UInt8} (c : UInt8) : (a - c = b - c) ↔ a = b := by + simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.sub_left_inj {a b : UInt16} (c : UInt16) : (a - c = b - c) ↔ a = b := by + simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.sub_left_inj {a b : UInt32} (c : UInt32) : (a - c = b - c) ↔ a = b := by + simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.sub_left_inj {a b : UInt64} (c : UInt64) : (a - c = b - c) ↔ a = b := by + simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.sub_left_inj {a b : USize} (c : USize) : (a - c = b - c) ↔ a = b := by + simp [← USize.toBitVec_inj] + +@[simp] theorem UInt8.sub_right_inj {a b : UInt8} (c : UInt8) : (c - a = c - b) ↔ a = b := by + simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.sub_right_inj {a b : UInt16} (c : UInt16) : (c - a = c - b) ↔ a = b := by + simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.sub_right_inj {a b : UInt32} (c : UInt32) : (c - a = c - b) ↔ a = b := by + simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.sub_right_inj {a b : UInt64} (c : UInt64) : (c - a = c - b) ↔ a = b := by + simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.sub_right_inj {a b : USize} (c : USize) : (c - a = c - b) ↔ a = b := by + simp [← USize.toBitVec_inj] + +@[simp] theorem UInt8.add_eq_right {a b : UInt8} : a + b = b ↔ a = 0 := by + simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.add_eq_right {a b : UInt16} : a + b = b ↔ a = 0 := by + simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.add_eq_right {a b : UInt32} : a + b = b ↔ a = 0 := by + simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.add_eq_right {a b : UInt64} : a + b = b ↔ a = 0 := by + simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.add_eq_right {a b : USize} : a + b = b ↔ a = 0 := by + simp [← USize.toBitVec_inj] + +@[simp] theorem UInt8.add_eq_left {a b : UInt8} : a + b = a ↔ b = 0 := by + simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.add_eq_left {a b : UInt16} : a + b = a ↔ b = 0 := by + simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.add_eq_left {a b : UInt32} : a + b = a ↔ b = 0 := by + simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.add_eq_left {a b : UInt64} : a + b = a ↔ b = 0 := by + simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.add_eq_left {a b : USize} : a + b = a ↔ b = 0 := by + simp [← USize.toBitVec_inj] + +@[simp] theorem UInt8.right_eq_add {a b : UInt8} : b = a + b ↔ a = 0 := by + simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.right_eq_add {a b : UInt16} : b = a + b ↔ a = 0 := by + simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.right_eq_add {a b : UInt32} : b = a + b ↔ a = 0 := by + simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.right_eq_add {a b : UInt64} : b = a + b ↔ a = 0 := by + simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.right_eq_add {a b : USize} : b = a + b ↔ a = 0 := by + simp [← USize.toBitVec_inj] + +@[simp] theorem UInt8.left_eq_add {a b : UInt8} : a = a + b ↔ b = 0 := by + simp [← UInt8.toBitVec_inj] +@[simp] theorem UInt16.left_eq_add {a b : UInt16} : a = a + b ↔ b = 0 := by + simp [← UInt16.toBitVec_inj] +@[simp] theorem UInt32.left_eq_add {a b : UInt32} : a = a + b ↔ b = 0 := by + simp [← UInt32.toBitVec_inj] +@[simp] theorem UInt64.left_eq_add {a b : UInt64} : a = a + b ↔ b = 0 := by + simp [← UInt64.toBitVec_inj] +@[simp] theorem USize.left_eq_add {a b : USize} : a = a + b ↔ b = 0 := by + simp [← USize.toBitVec_inj] + +theorem UInt8.mul_comm (a b : UInt8) : a * b = b * a := UInt8.toBitVec_inj.1 (BitVec.mul_comm _ _) +theorem UInt16.mul_comm (a b : UInt16) : a * b = b * a := UInt16.toBitVec_inj.1 (BitVec.mul_comm _ _) +theorem UInt32.mul_comm (a b : UInt32) : a * b = b * a := UInt32.toBitVec_inj.1 (BitVec.mul_comm _ _) +theorem UInt64.mul_comm (a b : UInt64) : a * b = b * a := UInt64.toBitVec_inj.1 (BitVec.mul_comm _ _) +theorem USize.mul_comm (a b : USize) : a * b = b * a := USize.toBitVec_inj.1 (BitVec.mul_comm _ _) + +instance : Std.Commutative (α := UInt8) (· * ·) := ⟨UInt8.mul_comm⟩ +instance : Std.Commutative (α := UInt16) (· * ·) := ⟨UInt16.mul_comm⟩ +instance : Std.Commutative (α := UInt32) (· * ·) := ⟨UInt32.mul_comm⟩ +instance : Std.Commutative (α := UInt64) (· * ·) := ⟨UInt64.mul_comm⟩ +instance : Std.Commutative (α := USize) (· * ·) := ⟨USize.mul_comm⟩ + +theorem UInt8.mul_assoc (a b c : UInt8) : a * b * c = a * (b * c) := UInt8.toBitVec_inj.1 (BitVec.mul_assoc _ _ _) +theorem UInt16.mul_assoc (a b c : UInt16) : a * b * c = a * (b * c) := UInt16.toBitVec_inj.1 (BitVec.mul_assoc _ _ _) +theorem UInt32.mul_assoc (a b c : UInt32) : a * b * c = a * (b * c) := UInt32.toBitVec_inj.1 (BitVec.mul_assoc _ _ _) +theorem UInt64.mul_assoc (a b c : UInt64) : a * b * c = a * (b * c) := UInt64.toBitVec_inj.1 (BitVec.mul_assoc _ _ _) +theorem USize.mul_assoc (a b c : USize) : a * b * c = a * (b * c) := USize.toBitVec_inj.1 (BitVec.mul_assoc _ _ _) + +instance : Std.Associative (α := UInt8) (· * ·) := ⟨UInt8.mul_assoc⟩ +instance : Std.Associative (α := UInt16) (· * ·) := ⟨UInt16.mul_assoc⟩ +instance : Std.Associative (α := UInt32) (· * ·) := ⟨UInt32.mul_assoc⟩ +instance : Std.Associative (α := UInt64) (· * ·) := ⟨UInt64.mul_assoc⟩ +instance : Std.Associative (α := USize) (· * ·) := ⟨USize.mul_assoc⟩ + +@[simp] theorem UInt8.mul_one (a : UInt8) : a * 1 = a := UInt8.toBitVec_inj.1 (BitVec.mul_one _) +@[simp] theorem UInt16.mul_one (a : UInt16) : a * 1 = a := UInt16.toBitVec_inj.1 (BitVec.mul_one _) +@[simp] theorem UInt32.mul_one (a : UInt32) : a * 1 = a := UInt32.toBitVec_inj.1 (BitVec.mul_one _) +@[simp] theorem UInt64.mul_one (a : UInt64) : a * 1 = a := UInt64.toBitVec_inj.1 (BitVec.mul_one _) +@[simp] theorem USize.mul_one (a : USize) : a * 1 = a := USize.toBitVec_inj.1 (BitVec.mul_one _) + +@[simp] theorem UInt8.one_mul (a : UInt8) : 1 * a = a := UInt8.toBitVec_inj.1 (BitVec.one_mul _) +@[simp] theorem UInt16.one_mul (a : UInt16) : 1 * a = a := UInt16.toBitVec_inj.1 (BitVec.one_mul _) +@[simp] theorem UInt32.one_mul (a : UInt32) : 1 * a = a := UInt32.toBitVec_inj.1 (BitVec.one_mul _) +@[simp] theorem UInt64.one_mul (a : UInt64) : 1 * a = a := UInt64.toBitVec_inj.1 (BitVec.one_mul _) +@[simp] theorem USize.one_mul (a : USize) : 1 * a = a := USize.toBitVec_inj.1 (BitVec.one_mul _) + +instance : Std.LawfulCommIdentity (α := UInt8) (· * ·) 1 where + right_id := UInt8.mul_one +instance : Std.LawfulCommIdentity (α := UInt16) (· * ·) 1 where + right_id := UInt16.mul_one +instance : Std.LawfulCommIdentity (α := UInt32) (· * ·) 1 where + right_id := UInt32.mul_one +instance : Std.LawfulCommIdentity (α := UInt64) (· * ·) 1 where + right_id := UInt64.mul_one +instance : Std.LawfulCommIdentity (α := USize) (· * ·) 1 where + right_id := USize.mul_one + +@[simp] theorem UInt8.mul_zero {a : UInt8} : a * 0 = 0 := UInt8.toBitVec_inj.1 BitVec.mul_zero +@[simp] theorem UInt16.mul_zero {a : UInt16} : a * 0 = 0 := UInt16.toBitVec_inj.1 BitVec.mul_zero +@[simp] theorem UInt32.mul_zero {a : UInt32} : a * 0 = 0 := UInt32.toBitVec_inj.1 BitVec.mul_zero +@[simp] theorem UInt64.mul_zero {a : UInt64} : a * 0 = 0 := UInt64.toBitVec_inj.1 BitVec.mul_zero +@[simp] theorem USize.mul_zero {a : USize} : a * 0 = 0 := USize.toBitVec_inj.1 BitVec.mul_zero + +@[simp] theorem UInt8.zero_mul {a : UInt8} : 0 * a = 0 := UInt8.toBitVec_inj.1 BitVec.zero_mul +@[simp] theorem UInt16.zero_mul {a : UInt16} : 0 * a = 0 := UInt16.toBitVec_inj.1 BitVec.zero_mul +@[simp] theorem UInt32.zero_mul {a : UInt32} : 0 * a = 0 := UInt32.toBitVec_inj.1 BitVec.zero_mul +@[simp] theorem UInt64.zero_mul {a : UInt64} : 0 * a = 0 := UInt64.toBitVec_inj.1 BitVec.zero_mul +@[simp] theorem USize.zero_mul {a : USize} : 0 * a = 0 := USize.toBitVec_inj.1 BitVec.zero_mul + +theorem UInt8.mul_add {a b c : UInt8} : a * (b + c) = a * b + a * c := + UInt8.toBitVec_inj.1 BitVec.mul_add +theorem UInt16.mul_add {a b c : UInt16} : a * (b + c) = a * b + a * c := + UInt16.toBitVec_inj.1 BitVec.mul_add +theorem UInt32.mul_add {a b c : UInt32} : a * (b + c) = a * b + a * c := + UInt32.toBitVec_inj.1 BitVec.mul_add +theorem UInt64.mul_add {a b c : UInt64} : a * (b + c) = a * b + a * c := + UInt64.toBitVec_inj.1 BitVec.mul_add +theorem USize.mul_add {a b c : USize} : a * (b + c) = a * b + a * c := + USize.toBitVec_inj.1 BitVec.mul_add + +theorem UInt8.add_mul {a b c : UInt8} : (a + b) * c = a * c + b * c := by + rw [mul_comm, mul_add, mul_comm a c, mul_comm c b] +theorem UInt16.add_mul {a b c : UInt16} : (a + b) * c = a * c + b * c := by + rw [mul_comm, mul_add, mul_comm a c, mul_comm c b] +theorem UInt32.add_mul {a b c : UInt32} : (a + b) * c = a * c + b * c := by + rw [mul_comm, mul_add, mul_comm a c, mul_comm c b] +theorem UInt64.add_mul {a b c : UInt64} : (a + b) * c = a * c + b * c := by + rw [mul_comm, mul_add, mul_comm a c, mul_comm c b] +theorem USize.add_mul {a b c : USize} : (a + b) * c = a * c + b * c := by + rw [mul_comm, mul_add, mul_comm a c, mul_comm c b] + +theorem UInt8.mul_succ {a b : UInt8} : a * (b + 1) = a * b + a := by simp [mul_add] +theorem UInt16.mul_succ {a b : UInt16} : a * (b + 1) = a * b + a := by simp [mul_add] +theorem UInt32.mul_succ {a b : UInt32} : a * (b + 1) = a * b + a := by simp [mul_add] +theorem UInt64.mul_succ {a b : UInt64} : a * (b + 1) = a * b + a := by simp [mul_add] +theorem USize.mul_succ {a b : USize} : a * (b + 1) = a * b + a := by simp [mul_add] + +theorem UInt8.succ_mul {a b : UInt8} : (a + 1) * b = a * b + b := by simp [add_mul] +theorem UInt16.succ_mul {a b : UInt16} : (a + 1) * b = a * b + b := by simp [add_mul] +theorem UInt32.succ_mul {a b : UInt32} : (a + 1) * b = a * b + b := by simp [add_mul] +theorem UInt64.succ_mul {a b : UInt64} : (a + 1) * b = a * b + b := by simp [add_mul] +theorem USize.succ_mul {a b : USize} : (a + 1) * b = a * b + b := by simp [add_mul] + +theorem UInt8.two_mul {a : UInt8} : 2 * a = a + a := UInt8.toBitVec_inj.1 BitVec.two_mul +theorem UInt16.two_mul {a : UInt16} : 2 * a = a + a := UInt16.toBitVec_inj.1 BitVec.two_mul +theorem UInt32.two_mul {a : UInt32} : 2 * a = a + a := UInt32.toBitVec_inj.1 BitVec.two_mul +theorem UInt64.two_mul {a : UInt64} : 2 * a = a + a := UInt64.toBitVec_inj.1 BitVec.two_mul +theorem USize.two_mul {a : USize} : 2 * a = a + a := USize.toBitVec_inj.1 BitVec.two_mul + +theorem UInt8.mul_two {a : UInt8} : a * 2 = a + a := UInt8.toBitVec_inj.1 BitVec.mul_two +theorem UInt16.mul_two {a : UInt16} : a * 2 = a + a := UInt16.toBitVec_inj.1 BitVec.mul_two +theorem UInt32.mul_two {a : UInt32} : a * 2 = a + a := UInt32.toBitVec_inj.1 BitVec.mul_two +theorem UInt64.mul_two {a : UInt64} : a * 2 = a + a := UInt64.toBitVec_inj.1 BitVec.mul_two +theorem USize.mul_two {a : USize} : a * 2 = a + a := USize.toBitVec_inj.1 BitVec.mul_two + +theorem UInt8.neg_mul (a b : UInt8) : -a * b = -(a * b) := UInt8.toBitVec_inj.1 (BitVec.neg_mul _ _) +theorem UInt16.neg_mul (a b : UInt16) : -a * b = -(a * b) := UInt16.toBitVec_inj.1 (BitVec.neg_mul _ _) +theorem UInt32.neg_mul (a b : UInt32) : -a * b = -(a * b) := UInt32.toBitVec_inj.1 (BitVec.neg_mul _ _) +theorem UInt64.neg_mul (a b : UInt64) : -a * b = -(a * b) := UInt64.toBitVec_inj.1 (BitVec.neg_mul _ _) +theorem USize.neg_mul (a b : USize) : -a * b = -(a * b) := USize.toBitVec_inj.1 (BitVec.neg_mul _ _) + +theorem UInt8.mul_neg (a b : UInt8) : a * -b = -(a * b) := UInt8.toBitVec_inj.1 (BitVec.mul_neg _ _) +theorem UInt16.mul_neg (a b : UInt16) : a * -b = -(a * b) := UInt16.toBitVec_inj.1 (BitVec.mul_neg _ _) +theorem UInt32.mul_neg (a b : UInt32) : a * -b = -(a * b) := UInt32.toBitVec_inj.1 (BitVec.mul_neg _ _) +theorem UInt64.mul_neg (a b : UInt64) : a * -b = -(a * b) := UInt64.toBitVec_inj.1 (BitVec.mul_neg _ _) +theorem USize.mul_neg (a b : USize) : a * -b = -(a * b) := USize.toBitVec_inj.1 (BitVec.mul_neg _ _) + +theorem UInt8.neg_mul_neg (a b : UInt8) : -a * -b = a * b := UInt8.toBitVec_inj.1 (BitVec.neg_mul_neg _ _) +theorem UInt16.neg_mul_neg (a b : UInt16) : -a * -b = a * b := UInt16.toBitVec_inj.1 (BitVec.neg_mul_neg _ _) +theorem UInt32.neg_mul_neg (a b : UInt32) : -a * -b = a * b := UInt32.toBitVec_inj.1 (BitVec.neg_mul_neg _ _) +theorem UInt64.neg_mul_neg (a b : UInt64) : -a * -b = a * b := UInt64.toBitVec_inj.1 (BitVec.neg_mul_neg _ _) +theorem USize.neg_mul_neg (a b : USize) : -a * -b = a * b := USize.toBitVec_inj.1 (BitVec.neg_mul_neg _ _) + +theorem UInt8.neg_mul_comm (a b : UInt8) : -a * b = a * -b := UInt8.toBitVec_inj.1 (BitVec.neg_mul_comm _ _) +theorem UInt16.neg_mul_comm (a b : UInt16) : -a * b = a * -b := UInt16.toBitVec_inj.1 (BitVec.neg_mul_comm _ _) +theorem UInt32.neg_mul_comm (a b : UInt32) : -a * b = a * -b := UInt32.toBitVec_inj.1 (BitVec.neg_mul_comm _ _) +theorem UInt64.neg_mul_comm (a b : UInt64) : -a * b = a * -b := UInt64.toBitVec_inj.1 (BitVec.neg_mul_comm _ _) +theorem USize.neg_mul_comm (a b : USize) : -a * b = a * -b := USize.toBitVec_inj.1 (BitVec.neg_mul_comm _ _) + +theorem UInt8.mul_sub {a b c : UInt8} : a * (b - c) = a * b - a * c := UInt8.toBitVec_inj.1 BitVec.mul_sub +theorem UInt16.mul_sub {a b c : UInt16} : a * (b - c) = a * b - a * c := UInt16.toBitVec_inj.1 BitVec.mul_sub +theorem UInt32.mul_sub {a b c : UInt32} : a * (b - c) = a * b - a * c := UInt32.toBitVec_inj.1 BitVec.mul_sub +theorem UInt64.mul_sub {a b c : UInt64} : a * (b - c) = a * b - a * c := UInt64.toBitVec_inj.1 BitVec.mul_sub +theorem USize.mul_sub {a b c : USize} : a * (b - c) = a * b - a * c := USize.toBitVec_inj.1 BitVec.mul_sub + +theorem UInt8.sub_mul {a b c : UInt8} : (a - b) * c = a * c - b * c := by + rw [mul_comm, mul_sub, mul_comm, mul_comm c] +theorem UInt16.sub_mul {a b c : UInt16} : (a - b) * c = a * c - b * c := by + rw [mul_comm, mul_sub, mul_comm, mul_comm c] +theorem UInt32.sub_mul {a b c : UInt32} : (a - b) * c = a * c - b * c := by + rw [mul_comm, mul_sub, mul_comm, mul_comm c] +theorem UInt64.sub_mul {a b c : UInt64} : (a - b) * c = a * c - b * c := by + rw [mul_comm, mul_sub, mul_comm, mul_comm c] +theorem USize.sub_mul {a b c : USize} : (a - b) * c = a * c - b * c := by + rw [mul_comm, mul_sub, mul_comm, mul_comm c] + +theorem UInt8.neg_add_mul_eq_mul_not {a b : UInt8} : -(a + a * b) = a * ~~~b := + UInt8.toBitVec_inj.1 BitVec.neg_add_mul_eq_mul_not +theorem UInt16.neg_add_mul_eq_mul_not {a b : UInt16} : -(a + a * b) = a * ~~~b := + UInt16.toBitVec_inj.1 BitVec.neg_add_mul_eq_mul_not +theorem UInt32.neg_add_mul_eq_mul_not {a b : UInt32} : -(a + a * b) = a * ~~~b := + UInt32.toBitVec_inj.1 BitVec.neg_add_mul_eq_mul_not +theorem UInt64.neg_add_mul_eq_mul_not {a b : UInt64} : -(a + a * b) = a * ~~~b := + UInt64.toBitVec_inj.1 BitVec.neg_add_mul_eq_mul_not +theorem USize.neg_add_mul_eq_mul_not {a b : USize} : -(a + a * b) = a * ~~~b := + USize.toBitVec_inj.1 BitVec.neg_add_mul_eq_mul_not + +theorem UInt8.neg_mul_not_eq_add_mul {a b : UInt8} : -(a * ~~~b) = a + a * b := + UInt8.toBitVec_inj.1 BitVec.neg_mul_not_eq_add_mul +theorem UInt16.neg_mul_not_eq_add_mul {a b : UInt16} : -(a * ~~~b) = a + a * b := + UInt16.toBitVec_inj.1 BitVec.neg_mul_not_eq_add_mul +theorem UInt32.neg_mul_not_eq_add_mul {a b : UInt32} : -(a * ~~~b) = a + a * b := + UInt32.toBitVec_inj.1 BitVec.neg_mul_not_eq_add_mul +theorem UInt64.neg_mul_not_eq_add_mul {a b : UInt64} : -(a * ~~~b) = a + a * b := + UInt64.toBitVec_inj.1 BitVec.neg_mul_not_eq_add_mul +theorem USize.neg_mul_not_eq_add_mul {a b : USize} : -(a * ~~~b) = a + a * b := + USize.toBitVec_inj.1 BitVec.neg_mul_not_eq_add_mul + +theorem UInt8.le_of_lt {a b : UInt8} : a < b → a ≤ b := by + simpa [lt_iff_toNat_lt, le_iff_toNat_le] using Nat.le_of_lt +theorem UInt16.le_of_lt {a b : UInt16} : a < b → a ≤ b := by + simpa [lt_iff_toNat_lt, le_iff_toNat_le] using Nat.le_of_lt +theorem UInt32.le_of_lt {a b : UInt32} : a < b → a ≤ b := by + simpa [lt_iff_toNat_lt, le_iff_toNat_le] using Nat.le_of_lt +theorem UInt64.le_of_lt {a b : UInt64} : a < b → a ≤ b := by + simpa [lt_iff_toNat_lt, le_iff_toNat_le] using Nat.le_of_lt +theorem USize.le_of_lt {a b : USize} : a < b → a ≤ b := by + simpa [lt_iff_toNat_lt, le_iff_toNat_le] using Nat.le_of_lt + +theorem UInt8.lt_of_le_of_ne {a b : UInt8} : a ≤ b → a ≠ b → a < b := by + simpa [lt_iff_toNat_lt, le_iff_toNat_le, ← UInt8.toNat_inj] using Nat.lt_of_le_of_ne +theorem UInt16.lt_of_le_of_ne {a b : UInt16} : a ≤ b → a ≠ b → a < b := by + simpa [lt_iff_toNat_lt, le_iff_toNat_le, ← UInt16.toNat_inj] using Nat.lt_of_le_of_ne +theorem UInt32.lt_of_le_of_ne {a b : UInt32} : a ≤ b → a ≠ b → a < b := by + simpa [lt_iff_toNat_lt, le_iff_toNat_le, ← UInt32.toNat_inj] using Nat.lt_of_le_of_ne +theorem UInt64.lt_of_le_of_ne {a b : UInt64} : a ≤ b → a ≠ b → a < b := by + simpa [lt_iff_toNat_lt, le_iff_toNat_le, ← UInt64.toNat_inj] using Nat.lt_of_le_of_ne +theorem USize.lt_of_le_of_ne {a b : USize} : a ≤ b → a ≠ b → a < b := by + simpa [lt_iff_toNat_lt, le_iff_toNat_le, ← USize.toNat_inj] using Nat.lt_of_le_of_ne + +theorem UInt8.lt_iff_le_and_ne {a b : UInt8} : a < b ↔ a ≤ b ∧ a ≠ b := by + simpa [lt_iff_toNat_lt, le_iff_toNat_le, ← UInt8.toNat_inj] using Nat.lt_iff_le_and_ne +theorem UInt16.lt_iff_le_and_ne {a b : UInt16} : a < b ↔ a ≤ b ∧ a ≠ b := by + simpa [lt_iff_toNat_lt, le_iff_toNat_le, ← UInt16.toNat_inj] using Nat.lt_iff_le_and_ne +theorem UInt32.lt_iff_le_and_ne {a b : UInt32} : a < b ↔ a ≤ b ∧ a ≠ b := by + simpa [lt_iff_toNat_lt, le_iff_toNat_le, ← UInt32.toNat_inj] using Nat.lt_iff_le_and_ne +theorem UInt64.lt_iff_le_and_ne {a b : UInt64} : a < b ↔ a ≤ b ∧ a ≠ b := by + simpa [lt_iff_toNat_lt, le_iff_toNat_le, ← UInt64.toNat_inj] using Nat.lt_iff_le_and_ne +theorem USize.lt_iff_le_and_ne {a b : USize} : a < b ↔ a ≤ b ∧ a ≠ b := by + simpa [lt_iff_toNat_lt, le_iff_toNat_le, ← USize.toNat_inj] using Nat.lt_iff_le_and_ne + +@[simp] theorem UInt8.not_lt_zero {a : UInt8} : ¬a < 0 := by simp [UInt8.lt_iff_toBitVec_lt] +@[simp] theorem UInt16.not_lt_zero {a : UInt16} : ¬a < 0 := by simp [UInt16.lt_iff_toBitVec_lt] +@[simp] theorem UInt32.not_lt_zero {a : UInt32} : ¬a < 0 := by simp [UInt32.lt_iff_toBitVec_lt] +@[simp] theorem UInt64.not_lt_zero {a : UInt64} : ¬a < 0 := by simp [UInt64.lt_iff_toBitVec_lt] +@[simp] theorem USize.not_lt_zero {a : USize} : ¬a < 0 := by simp [USize.lt_iff_toBitVec_lt] + +@[simp] theorem UInt8.zero_le {a : UInt8} : 0 ≤ a := by simp [← UInt8.not_lt] +@[simp] theorem UInt16.zero_le {a : UInt16} : 0 ≤ a := by simp [← UInt16.not_lt] +@[simp] theorem UInt32.zero_le {a : UInt32} : 0 ≤ a := by simp [← UInt32.not_lt] +@[simp] theorem UInt64.zero_le {a : UInt64} : 0 ≤ a := by simp [← UInt64.not_lt] +@[simp] theorem USize.zero_le {a : USize} : 0 ≤ a := by simp [← USize.not_lt] + +@[simp] theorem UInt8.le_zero_iff {a : UInt8} : a ≤ 0 ↔ a = 0 := by + simp [UInt8.le_iff_toBitVec_le, ← UInt8.toBitVec_inj] +@[simp] theorem UInt16.le_zero_iff {a : UInt16} : a ≤ 0 ↔ a = 0 := by + simp [UInt16.le_iff_toBitVec_le, ← UInt16.toBitVec_inj] +@[simp] theorem UInt32.le_zero_iff {a : UInt32} : a ≤ 0 ↔ a = 0 := by + simp [UInt32.le_iff_toBitVec_le, ← UInt32.toBitVec_inj] +@[simp] theorem UInt64.le_zero_iff {a : UInt64} : a ≤ 0 ↔ a = 0 := by + simp [UInt64.le_iff_toBitVec_le, ← UInt64.toBitVec_inj] +@[simp] theorem USize.le_zero_iff {a : USize} : a ≤ 0 ↔ a = 0 := by + simp [USize.le_iff_toBitVec_le, ← USize.toBitVec_inj] + +@[simp] theorem UInt8.lt_one_iff {a : UInt8} : a < 1 ↔ a = 0 := by + simp [UInt8.lt_iff_toBitVec_lt, ← UInt8.toBitVec_inj] +@[simp] theorem UInt16.lt_one_iff {a : UInt16} : a < 1 ↔ a = 0 := by + simp [UInt16.lt_iff_toBitVec_lt, ← UInt16.toBitVec_inj] +@[simp] theorem UInt32.lt_one_iff {a : UInt32} : a < 1 ↔ a = 0 := by + simp [UInt32.lt_iff_toBitVec_lt, ← UInt32.toBitVec_inj] +@[simp] theorem UInt64.lt_one_iff {a : UInt64} : a < 1 ↔ a = 0 := by + simp [UInt64.lt_iff_toBitVec_lt, ← UInt64.toBitVec_inj] +@[simp] theorem USize.lt_one_iff {a : USize} : a < 1 ↔ a = 0 := by + simp [USize.lt_iff_toBitVec_lt, ← USize.toBitVec_inj] + +@[simp] theorem UInt8.zero_div {a : UInt8} : 0 / a = 0 := UInt8.toBitVec_inj.1 BitVec.zero_udiv +@[simp] theorem UInt16.zero_div {a : UInt16} : 0 / a = 0 := UInt16.toBitVec_inj.1 BitVec.zero_udiv +@[simp] theorem UInt32.zero_div {a : UInt32} : 0 / a = 0 := UInt32.toBitVec_inj.1 BitVec.zero_udiv +@[simp] theorem UInt64.zero_div {a : UInt64} : 0 / a = 0 := UInt64.toBitVec_inj.1 BitVec.zero_udiv +@[simp] theorem USize.zero_div {a : USize} : 0 / a = 0 := USize.toBitVec_inj.1 BitVec.zero_udiv + +@[simp] theorem UInt8.div_zero {a : UInt8} : a / 0 = 0 := UInt8.toBitVec_inj.1 BitVec.udiv_zero +@[simp] theorem UInt16.div_zero {a : UInt16} : a / 0 = 0 := UInt16.toBitVec_inj.1 BitVec.udiv_zero +@[simp] theorem UInt32.div_zero {a : UInt32} : a / 0 = 0 := UInt32.toBitVec_inj.1 BitVec.udiv_zero +@[simp] theorem UInt64.div_zero {a : UInt64} : a / 0 = 0 := UInt64.toBitVec_inj.1 BitVec.udiv_zero +@[simp] theorem USize.div_zero {a : USize} : a / 0 = 0 := USize.toBitVec_inj.1 BitVec.udiv_zero + +@[simp] theorem UInt8.div_one {a : UInt8} : a / 1 = a := UInt8.toBitVec_inj.1 BitVec.udiv_one +@[simp] theorem UInt16.div_one {a : UInt16} : a / 1 = a := UInt16.toBitVec_inj.1 BitVec.udiv_one +@[simp] theorem UInt32.div_one {a : UInt32} : a / 1 = a := UInt32.toBitVec_inj.1 BitVec.udiv_one +@[simp] theorem UInt64.div_one {a : UInt64} : a / 1 = a := UInt64.toBitVec_inj.1 BitVec.udiv_one +@[simp] theorem USize.div_one {a : USize} : a / 1 = a := USize.toBitVec_inj.1 BitVec.udiv_one + +theorem UInt8.div_self {a : UInt8} : a / a = if a = 0 then 0 else 1 := by + simp [← UInt8.toBitVec_inj, apply_ite] +theorem UInt16.div_self {a : UInt16} : a / a = if a = 0 then 0 else 1 := by + simp [← UInt16.toBitVec_inj, apply_ite] +theorem UInt32.div_self {a : UInt32} : a / a = if a = 0 then 0 else 1 := by + simp [← UInt32.toBitVec_inj, apply_ite] +theorem UInt64.div_self {a : UInt64} : a / a = if a = 0 then 0 else 1 := by + simp [← UInt64.toBitVec_inj, apply_ite] +theorem USize.div_self {a : USize} : a / a = if a = 0 then 0 else 1 := by + simp [← USize.toNat_inj] + split + · simp_all + · simpa using Nat.div_self (by omega) + +@[simp] theorem UInt8.mod_zero {a : UInt8} : a % 0 = a := UInt8.toBitVec_inj.1 BitVec.umod_zero +@[simp] theorem UInt16.mod_zero {a : UInt16} : a % 0 = a := UInt16.toBitVec_inj.1 BitVec.umod_zero +@[simp] theorem UInt32.mod_zero {a : UInt32} : a % 0 = a := UInt32.toBitVec_inj.1 BitVec.umod_zero +@[simp] theorem UInt64.mod_zero {a : UInt64} : a % 0 = a := UInt64.toBitVec_inj.1 BitVec.umod_zero +@[simp] theorem USize.mod_zero {a : USize} : a % 0 = a := USize.toBitVec_inj.1 BitVec.umod_zero + +@[simp] theorem UInt8.zero_mod {a : UInt8} : 0 % a = 0 := UInt8.toBitVec_inj.1 BitVec.zero_umod +@[simp] theorem UInt16.zero_mod {a : UInt16} : 0 % a = 0 := UInt16.toBitVec_inj.1 BitVec.zero_umod +@[simp] theorem UInt32.zero_mod {a : UInt32} : 0 % a = 0 := UInt32.toBitVec_inj.1 BitVec.zero_umod +@[simp] theorem UInt64.zero_mod {a : UInt64} : 0 % a = 0 := UInt64.toBitVec_inj.1 BitVec.zero_umod +@[simp] theorem USize.zero_mod {a : USize} : 0 % a = 0 := USize.toBitVec_inj.1 BitVec.zero_umod + +@[simp] theorem UInt8.mod_one {a : UInt8} : a % 1 = 0 := UInt8.toBitVec_inj.1 BitVec.umod_one +@[simp] theorem UInt16.mod_one {a : UInt16} : a % 1 = 0 := UInt16.toBitVec_inj.1 BitVec.umod_one +@[simp] theorem UInt32.mod_one {a : UInt32} : a % 1 = 0 := UInt32.toBitVec_inj.1 BitVec.umod_one +@[simp] theorem UInt64.mod_one {a : UInt64} : a % 1 = 0 := UInt64.toBitVec_inj.1 BitVec.umod_one +@[simp] theorem USize.mod_one {a : USize} : a % 1 = 0 := USize.toBitVec_inj.1 BitVec.umod_one + +@[simp] theorem UInt8.mod_self {a : UInt8} : a % a = 0 := UInt8.toBitVec_inj.1 BitVec.umod_self +@[simp] theorem UInt16.mod_self {a : UInt16} : a % a = 0 := UInt16.toBitVec_inj.1 BitVec.umod_self +@[simp] theorem UInt32.mod_self {a : UInt32} : a % a = 0 := UInt32.toBitVec_inj.1 BitVec.umod_self +@[simp] theorem UInt64.mod_self {a : UInt64} : a % a = 0 := UInt64.toBitVec_inj.1 BitVec.umod_self +@[simp] theorem USize.mod_self {a : USize} : a % a = 0 := USize.toBitVec_inj.1 BitVec.umod_self + +theorem UInt8.pos_iff_ne_zero {a : UInt8} : 0 < a ↔ a ≠ 0 := by simp [lt_iff_le_and_ne, Eq.comm] +theorem UInt16.pos_iff_ne_zero {a : UInt16} : 0 < a ↔ a ≠ 0 := by simp [lt_iff_le_and_ne, Eq.comm] +theorem UInt32.pos_iff_ne_zero {a : UInt32} : 0 < a ↔ a ≠ 0 := by simp [lt_iff_le_and_ne, Eq.comm] +theorem UInt64.pos_iff_ne_zero {a : UInt64} : 0 < a ↔ a ≠ 0 := by simp [lt_iff_le_and_ne, Eq.comm] +theorem USize.pos_iff_ne_zero {a : USize} : 0 < a ↔ a ≠ 0 := by simp [lt_iff_le_and_ne, Eq.comm] + +theorem UInt8.lt_of_le_of_lt {a b c : UInt8} : a ≤ b → b < c → a < c := by + simpa [le_iff_toNat_le, lt_iff_toNat_lt] using Nat.lt_of_le_of_lt +theorem UInt16.lt_of_le_of_lt {a b c : UInt16} : a ≤ b → b < c → a < c := by + simpa [le_iff_toNat_le, lt_iff_toNat_lt] using Nat.lt_of_le_of_lt +theorem UInt32.lt_of_le_of_lt {a b c : UInt32} : a ≤ b → b < c → a < c := by + simpa [le_iff_toNat_le, lt_iff_toNat_lt] using Nat.lt_of_le_of_lt +theorem UInt64.lt_of_le_of_lt {a b c : UInt64} : a ≤ b → b < c → a < c := by + simpa [le_iff_toNat_le, lt_iff_toNat_lt] using Nat.lt_of_le_of_lt +theorem USize.lt_of_le_of_lt {a b c : USize} : a ≤ b → b < c → a < c := by + simpa [le_iff_toNat_le, lt_iff_toNat_lt] using Nat.lt_of_le_of_lt + +theorem UInt8.lt_of_lt_of_le {a b c : UInt8} : a < b → b ≤ c → a < c := by + simpa [le_iff_toNat_le, lt_iff_toNat_lt] using Nat.lt_of_lt_of_le +theorem UInt16.lt_of_lt_of_le {a b c : UInt16} : a < b → b ≤ c → a < c := by + simpa [le_iff_toNat_le, lt_iff_toNat_lt] using Nat.lt_of_lt_of_le +theorem UInt32.lt_of_lt_of_le {a b c : UInt32} : a < b → b ≤ c → a < c := by + simpa [le_iff_toNat_le, lt_iff_toNat_lt] using Nat.lt_of_lt_of_le +theorem UInt64.lt_of_lt_of_le {a b c : UInt64} : a < b → b ≤ c → a < c := by + simpa [le_iff_toNat_le, lt_iff_toNat_lt] using Nat.lt_of_lt_of_le +theorem USize.lt_of_lt_of_le {a b c : USize} : a < b → b ≤ c → a < c := by + simpa [le_iff_toNat_le, lt_iff_toNat_lt] using Nat.lt_of_lt_of_le + +theorem UInt8.lt_or_lt_of_ne {a b : UInt8} : a ≠ b → a < b ∨ b < a := by + simpa [lt_iff_toNat_lt, ← UInt8.toNat_inj] using Nat.lt_or_lt_of_ne +theorem UInt16.lt_or_lt_of_ne {a b : UInt16} : a ≠ b → a < b ∨ b < a := by + simpa [lt_iff_toNat_lt, ← UInt16.toNat_inj] using Nat.lt_or_lt_of_ne +theorem UInt32.lt_or_lt_of_ne {a b : UInt32} : a ≠ b → a < b ∨ b < a := by + simpa [lt_iff_toNat_lt, ← UInt32.toNat_inj] using Nat.lt_or_lt_of_ne +theorem UInt64.lt_or_lt_of_ne {a b : UInt64} : a ≠ b → a < b ∨ b < a := by + simpa [lt_iff_toNat_lt, ← UInt64.toNat_inj] using Nat.lt_or_lt_of_ne +theorem USize.lt_or_lt_of_ne {a b : USize} : a ≠ b → a < b ∨ b < a := by + simpa [lt_iff_toNat_lt, ← USize.toNat_inj] using Nat.lt_or_lt_of_ne + +theorem UInt8.lt_or_le (a b : UInt8) : a < b ∨ b ≤ a := by + simp [lt_iff_toNat_lt, le_iff_toNat_le]; omega +theorem UInt16.lt_or_le (a b : UInt16) : a < b ∨ b ≤ a := by + simp [lt_iff_toNat_lt, le_iff_toNat_le]; omega +theorem UInt32.lt_or_le (a b : UInt32) : a < b ∨ b ≤ a := by + simp [lt_iff_toNat_lt, le_iff_toNat_le]; omega +theorem UInt64.lt_or_le (a b : UInt64) : a < b ∨ b ≤ a := by + simp [lt_iff_toNat_lt, le_iff_toNat_le]; omega +theorem USize.lt_or_le (a b : USize) : a < b ∨ b ≤ a := by + simp [lt_iff_toNat_lt, le_iff_toNat_le]; omega + +theorem UInt8.le_or_lt (a b : UInt8) : a ≤ b ∨ b < a := (b.lt_or_le a).symm +theorem UInt16.le_or_lt (a b : UInt16) : a ≤ b ∨ b < a := (b.lt_or_le a).symm +theorem UInt32.le_or_lt (a b : UInt32) : a ≤ b ∨ b < a := (b.lt_or_le a).symm +theorem UInt64.le_or_lt (a b : UInt64) : a ≤ b ∨ b < a := (b.lt_or_le a).symm +theorem USize.le_or_lt (a b : USize) : a ≤ b ∨ b < a := (b.lt_or_le a).symm + +theorem UInt8.le_of_eq {a b : UInt8} : a = b → a ≤ b := (· ▸ UInt8.le_rfl) +theorem UInt16.le_of_eq {a b : UInt16} : a = b → a ≤ b := (· ▸ UInt16.le_rfl) +theorem UInt32.le_of_eq {a b : UInt32} : a = b → a ≤ b := (· ▸ UInt32.le_rfl) +theorem UInt64.le_of_eq {a b : UInt64} : a = b → a ≤ b := (· ▸ UInt64.le_rfl) +theorem USize.le_of_eq {a b : USize} : a = b → a ≤ b := (· ▸ USize.le_rfl) + +theorem UInt8.le_iff_lt_or_eq {a b : UInt8} : a ≤ b ↔ a < b ∨ a = b := by + simpa [← UInt8.toNat_inj, le_iff_toNat_le, lt_iff_toNat_lt] using Nat.le_iff_lt_or_eq +theorem UInt16.le_iff_lt_or_eq {a b : UInt16} : a ≤ b ↔ a < b ∨ a = b := by + simpa [← UInt16.toNat_inj, le_iff_toNat_le, lt_iff_toNat_lt] using Nat.le_iff_lt_or_eq +theorem UInt32.le_iff_lt_or_eq {a b : UInt32} : a ≤ b ↔ a < b ∨ a = b := by + simpa [← UInt32.toNat_inj, le_iff_toNat_le, lt_iff_toNat_lt] using Nat.le_iff_lt_or_eq +theorem UInt64.le_iff_lt_or_eq {a b : UInt64} : a ≤ b ↔ a < b ∨ a = b := by + simpa [← UInt64.toNat_inj, le_iff_toNat_le, lt_iff_toNat_lt] using Nat.le_iff_lt_or_eq +theorem USize.le_iff_lt_or_eq {a b : USize} : a ≤ b ↔ a < b ∨ a = b := by + simpa [← USize.toNat_inj, le_iff_toNat_le, lt_iff_toNat_lt] using Nat.le_iff_lt_or_eq + +theorem UInt8.lt_or_eq_of_le {a b : UInt8} : a ≤ b → a < b ∨ a = b := UInt8.le_iff_lt_or_eq.mp +theorem UInt16.lt_or_eq_of_le {a b : UInt16} : a ≤ b → a < b ∨ a = b := UInt16.le_iff_lt_or_eq.mp +theorem UInt32.lt_or_eq_of_le {a b : UInt32} : a ≤ b → a < b ∨ a = b := UInt32.le_iff_lt_or_eq.mp +theorem UInt64.lt_or_eq_of_le {a b : UInt64} : a ≤ b → a < b ∨ a = b := UInt64.le_iff_lt_or_eq.mp +theorem USize.lt_or_eq_of_le {a b : USize} : a ≤ b → a < b ∨ a = b := USize.le_iff_lt_or_eq.mp + +theorem UInt8.sub_le {a b : UInt8} (hab : b ≤ a) : a - b ≤ a := by + simp [le_iff_toNat_le, UInt8.toNat_sub_of_le _ _ hab] +theorem UInt16.sub_le {a b : UInt16} (hab : b ≤ a) : a - b ≤ a := by + simp [le_iff_toNat_le, UInt16.toNat_sub_of_le _ _ hab] +theorem UInt32.sub_le {a b : UInt32} (hab : b ≤ a) : a - b ≤ a := by + simp [le_iff_toNat_le, UInt32.toNat_sub_of_le _ _ hab] +theorem UInt64.sub_le {a b : UInt64} (hab : b ≤ a) : a - b ≤ a := by + simp [le_iff_toNat_le, UInt64.toNat_sub_of_le _ _ hab] +theorem USize.sub_le {a b : USize} (hab : b ≤ a) : a - b ≤ a := by + simp [le_iff_toNat_le, USize.toNat_sub_of_le _ _ hab] + +theorem UInt8.sub_lt {a b : UInt8} (hb : 0 < b) (hab : b ≤ a) : a - b < a := by + rw [lt_iff_toNat_lt, UInt8.toNat_sub_of_le _ _ hab] + refine Nat.sub_lt ?_ (UInt8.lt_iff_toNat_lt.1 hb) + exact UInt8.lt_iff_toNat_lt.1 (UInt8.lt_of_lt_of_le hb hab) +theorem UInt16.sub_lt {a b : UInt16} (hb : 0 < b) (hab : b ≤ a) : a - b < a := by + rw [lt_iff_toNat_lt, UInt16.toNat_sub_of_le _ _ hab] + refine Nat.sub_lt ?_ (UInt16.lt_iff_toNat_lt.1 hb) + exact UInt16.lt_iff_toNat_lt.1 (UInt16.lt_of_lt_of_le hb hab) +theorem UInt32.sub_lt {a b : UInt32} (hb : 0 < b) (hab : b ≤ a) : a - b < a := by + rw [lt_iff_toNat_lt, UInt32.toNat_sub_of_le _ _ hab] + refine Nat.sub_lt ?_ (UInt32.lt_iff_toNat_lt.1 hb) + exact UInt32.lt_iff_toNat_lt.1 (UInt32.lt_of_lt_of_le hb hab) +theorem UInt64.sub_lt {a b : UInt64} (hb : 0 < b) (hab : b ≤ a) : a - b < a := by + rw [lt_iff_toNat_lt, UInt64.toNat_sub_of_le _ _ hab] + refine Nat.sub_lt ?_ (UInt64.lt_iff_toNat_lt.1 hb) + exact UInt64.lt_iff_toNat_lt.1 (UInt64.lt_of_lt_of_le hb hab) +theorem USize.sub_lt {a b : USize} (hb : 0 < b) (hab : b ≤ a) : a - b < a := by + rw [lt_iff_toNat_lt, USize.toNat_sub_of_le _ _ hab] + refine Nat.sub_lt ?_ (USize.lt_iff_toNat_lt.1 hb) + exact USize.lt_iff_toNat_lt.1 (USize.lt_of_lt_of_le hb hab) diff --git a/tests/lean/interactive/compNamespace.lean b/tests/lean/interactive/compNamespace.lean index 2879bb47bc..e640577281 100644 --- a/tests/lean/interactive/compNamespace.lean +++ b/tests/lean/interactive/compNamespace.lean @@ -3,12 +3,12 @@ namespace LongNamespaceExample def x := 10 -#check LongN - --^ textDocument/completion +#check LongNam + --^ textDocument/completion end LongNamespaceExample -#check LongN - --^ textDocument/completion +#check LongNam + --^ textDocument/completion end Foo #check Foo. @@ -18,5 +18,5 @@ end Foo --^ textDocument/completion open Foo -#check LongN - --^ textDocument/completion +#check LongNam + --^ textDocument/completion diff --git a/tests/lean/interactive/compNamespace.lean.expected.out b/tests/lean/interactive/compNamespace.lean.expected.out index f39e006aed..b7f37121bd 100644 --- a/tests/lean/interactive/compNamespace.lean.expected.out +++ b/tests/lean/interactive/compNamespace.lean.expected.out @@ -1,5 +1,5 @@ {"textDocument": {"uri": "file:///compNamespace.lean"}, - "position": {"line": 5, "character": 12}} + "position": {"line": 5, "character": 14}} {"items": [{"label": "LongNamespaceExample", "kind": 9, @@ -7,11 +7,11 @@ "data": {"params": {"textDocument": {"uri": "file:///compNamespace.lean"}, - "position": {"line": 5, "character": 12}}, + "position": {"line": 5, "character": 14}}, "cPos": 0}}], "isIncomplete": false} {"textDocument": {"uri": "file:///compNamespace.lean"}, - "position": {"line": 9, "character": 12}} + "position": {"line": 9, "character": 14}} {"items": [{"label": "LongNamespaceExample", "kind": 9, @@ -19,7 +19,7 @@ "data": {"params": {"textDocument": {"uri": "file:///compNamespace.lean"}, - "position": {"line": 9, "character": 12}}, + "position": {"line": 9, "character": 14}}, "cPos": 0}}], "isIncomplete": false} {"textDocument": {"uri": "file:///compNamespace.lean"}, @@ -47,7 +47,7 @@ "cPos": 0}}], "isIncomplete": false} {"textDocument": {"uri": "file:///compNamespace.lean"}, - "position": {"line": 20, "character": 12}} + "position": {"line": 20, "character": 14}} {"items": [{"label": "LongNamespaceExample", "kind": 9, @@ -55,6 +55,6 @@ "data": {"params": {"textDocument": {"uri": "file:///compNamespace.lean"}, - "position": {"line": 20, "character": 12}}, + "position": {"line": 20, "character": 14}}, "cPos": 0}}], "isIncomplete": false} diff --git a/tests/lean/run/simprocSInt.lean b/tests/lean/run/simprocSInt.lean index 6b0df5f5f5..d637539cef 100644 --- a/tests/lean/run/simprocSInt.lean +++ b/tests/lean/run/simprocSInt.lean @@ -39,7 +39,7 @@ example : Int8.toInt (-8) + 8 = 0 := by simp +ground only #check_simp x = - (-2) ~> x = 2 #check_simp x = -0 ~> x = 0 #check_simp x = - (-0) ~> x = 0 -#check_simp x = - (-128) ~> x = -128 +#check_simp x = - (-128) ~> x = 128 #check_simp x = - (-127) ~> x = 127 #check_simp x = 2 + 3 ~> x = 5 #check_simp x = -3 + 2 ~> x = -1 @@ -82,7 +82,7 @@ example : Int16.toInt (-16) + 16 = 0 := by simp +ground only #check_simp x = - (-2) ~> x = 2 #check_simp x = -0 ~> x = 0 #check_simp x = - (-0) ~> x = 0 -#check_simp x = - (-32768) ~> x = -32768 +#check_simp x = - (-32768) ~> x = 32768 #check_simp x = - (-32767) ~> x = 32767 #check_simp x = 2 + 3 ~> x = 5 #check_simp x = -3 + 2 ~> x = -1 @@ -120,7 +120,7 @@ example : Int32.toInt (-32) + 32 = 0 := by simp +ground only #check_simp x = - (-2) ~> x = 2 #check_simp x = -0 ~> x = 0 #check_simp x = - (-0) ~> x = 0 -#check_simp x = - (-2147483648) ~> x = -2147483648 +#check_simp x = - (-2147483648) ~> x = 2147483648 #check_simp x = - (-2147483647) ~> x = 2147483647 #check_simp x = 2 + 3 ~> x = 5 #check_simp x = -3 + 2 ~> x = -1 @@ -158,7 +158,7 @@ example : Int64.toInt (-64) + 64 = 0 := by simp +ground only #check_simp x = - (-2) ~> x = 2 #check_simp x = -0 ~> x = 0 #check_simp x = - (-0) ~> x = 0 -#check_simp x = - (-9223372036854775808) ~> x = -9223372036854775808 +#check_simp x = - (-9223372036854775808) ~> x = 9223372036854775808 #check_simp x = - (-9223372036854775807) ~> x = 9223372036854775807 #check_simp x = 2 + 3 ~> x = 5 #check_simp x = -3 + 2 ~> x = -1