import UInt
import Base
import Nat
union Int {
pos(UInt)
negsuc(UInt)
}
fun abs(x : Int) {
switch x {
case pos(n) { n }
case negsuc(n) { 1 + n }
}
}
union Sign {
positive
negative
}
fun sign(n : Int) {
switch n {
case pos(n') { positive }
case negsuc(n') { negative }
}
}
private fun flip(s : Sign) {
switch s {
case positive { negative }
case negative { positive }
}
}
fun operator*(s1 : Sign, s2 : Sign) {
switch s1 {
case positive { s2 }
case negative { flip(s2) }
}
}
fun operator -(x : Int) {
switch x {
case pos(n) {
if n = 0 then pos(0)
else negsuc(n ∸ 1)
}
case negsuc(n){ pos(1 + n) }
}
}
fun operator -(n:UInt) {
- pos(n)
}
fun operator*(s : Sign, n : Int) {
switch s {
case positive { n }
case negative { -n }
}
}
fun operator*(s : Sign, n : UInt) { s * pos(n) }
fun operator ⊝(x:UInt, y:UInt) {
if x < y then
-(y ∸ x)
else
pos(x ∸ y)
}
fun operator +(x : Int, m :Int) {
switch x {
case pos(n) {
switch m {
case pos(n') { pos(n + n') }
case negsuc(n') { n ⊝ (1 + n') }
}
}
case negsuc(n) {
switch m {
case pos(n') { n' ⊝ (1 + n) }
case negsuc(n') { negsuc(1 + n + n') }
}
}
}
}
fun operator + (n:UInt, m:Int) { pos(n) + m }
fun operator + (n:Int, m:UInt) { n + pos(m) }
fun operator - (n:Int, m:Int) { n + (- m) }
fun operator - (n:UInt, m:Int) { pos(n) - m }
fun operator - (n:Int, m:UInt) { n - pos(m) }
fun operator -(x:UInt, y:UInt) { pos(x) - pos(y) }
fun operator *(x : Int, y : Int) {
(sign(x) * sign(y)) * (abs(x) * abs(y))
}
fun operator * (n:UInt, m:Int) { pos(n) * m }
fun operator * (n:Int, m:UInt) { n * pos(m) }
fun operator / (n:Int, m:Int) {
(sign(n) * sign(m)) * (abs(n) / abs(m))
}
fun operator / (n:Int, m:UInt) {
sign(n) * (abs(n) / m)
}
fun operator ≤(a : Int, y : Int) {
switch a {
case pos(x) {
switch y {
case pos(y') { x ≤ y' }
case negsuc(y') { false }
}
}
case negsuc(x) {
switch y {
case pos(y') { true }
case negsuc(y') { y' ≤ x }
}
}
}
}
lemma sign_pos: all n:UInt. sign(pos(n)) = positive
proof
arbitrary n:UInt
expand sign.
end
lemma sign_negsuc: all n:UInt. sign(negsuc(n)) = negative
proof
arbitrary n:UInt
expand sign.
end
lemma sign_neg_pos: all n:UInt. sign(-pos(1 + n)) = negative
proof
arbitrary n:UInt
expand operator- | sign
replace apply eq_false to uint_not_one_add_zero[n].
end
lemma sign_neg_negsuc: all n:UInt. sign(-negsuc(n)) = positive
proof
arbitrary n:UInt
expand operator - | sign.
end
lemma mult_pos_any: all s:Sign. positive * s = s
proof
arbitrary s:Sign
expand operator*.
end
lemma mult_any_pos: all s:Sign. s * positive = s
proof
arbitrary s:Sign
expand operator*
switch s {
case positive {
.
}
case negative {
expand flip.
}
}
end
lemma mult_pos_neg: positive * negative = negative
proof
expand operator*.
end
lemma mult_neg_pos: negative * positive = negative
proof
expand operator* | flip.
end
lemma mult_neg_neg: negative * negative = positive
proof
expand operator* | flip.
end
lemma mult_pos_uint: all n:UInt. positive * n = pos(n)
proof
arbitrary n:UInt
evaluate
end
lemma mult_pos_int: all n:Int. positive * n = n
proof
arbitrary n:Int
switch n {
case pos(n') {
expand operator*.
}
case negsuc(n') {
expand operator*.
}
}
end
lemma mult_neg_uint: all n:UInt. negative * n = - pos(n)
proof
arbitrary n:UInt
evaluate
end
lemma abs_pos: all n:UInt. abs(pos(n)) = n
proof
arbitrary n:UInt
expand abs.
end
lemma abs_negsuc: all n:UInt. abs(negsuc(n)) = 1 + n
proof
arbitrary n:UInt
expand abs.
end
theorem abs_neg: all n:Int. abs(- n) = abs(n)
proof
arbitrary n:Int
switch n {
case pos(n') {
have zp: n' = 0 or 0 < n' by uint_zero_or_positive[n']
cases zp
case n_z {
expand operator-
replace n_z.
}
case n_pos {
have n_z: not (n' = 0) by apply uint_pos_not_zero to n_pos
expand operator-
replace apply eq_false to n_z
replace abs_negsuc | abs_pos
have: 1 ≤ n' by apply uint_pos_implies_one_le to n_pos
conclude 1 + (n' ∸ 1) = n' by apply uint_monus_add_identity to recall 1 ≤ n'
}
}
case negsuc(n') {
expand operator- | abs.
}
}
end
theorem neg_zero: - +0 = +0
proof
evaluate
end
lemma neg_pos: all n:UInt.
- pos(1 + n) = negsuc(n)
proof
arbitrary n : UInt
expand operator-
replace apply eq_false to uint_not_one_add_zero[n]
have eq: (1 + n) ∸ 1 = n by uint_add_monus_identity
replace eq.
end
lemma neg_suc: all n:UInt.
- (1 + n) = negsuc(n)
proof
arbitrary n : UInt
expand 2* operator-
replace apply eq_false to uint_not_one_add_zero[n]
replace uint_add_monus_identity.
end
theorem neg_involutive: all n:Int. - - n = n
proof
arbitrary n:Int
switch n {
case pos(n') {
have zp: n' = 0 or 0 < n' by uint_zero_or_positive[n']
cases zp
case n_z {
expand operator- replace n_z.
}
case n_pos {
expand operator-
replace apply eq_false to (apply uint_pos_not_zero to n_pos)
replace apply uint_monus_add_identity to (apply uint_pos_implies_one_le to n_pos).
}
}
case negsuc(n') {
have zp: n' = 0 or 0 < n' by uint_zero_or_positive[n']
cases zp
case n_z {
expand operator- replace n_z evaluate
}
case n_pos {
expand operator-
replace apply eq_false to uint_not_one_add_zero[n']
replace uint_add_monus_identity.
}
}
}
end
theorem int_zero_add: all n:Int.
+0 + n = n
proof
arbitrary n:Int
switch n {
case pos(n') {
evaluate
}
case negsuc(n') {
expand operator+ | operator⊝
have A: 0 < 1 + n' by uint_zero_less_one_add
replace (apply eq_true to A)
replace uint_monus_zero
neg_suc
}
}
end
auto int_zero_add
theorem int_add_zero: all n:Int.
n + +0 = n
proof
arbitrary n:Int
switch n {
case pos(n') {
evaluate
}
case negsuc(n') {
expand operator+ | operator⊝
have A: 0 < 1 + n' by uint_zero_less_one_add
replace (apply eq_true to A)
replace uint_monus_zero
neg_suc
}
}
end
auto int_add_zero
theorem int_add_commute: all x:Int, y:Int. x + y = y + x
proof
arbitrary x:Int, y:Int
switch x {
case pos(x') {
switch y {
case pos(y') {
suffices pos(x' + y') = pos(y' + x') by expand operator+.
replace uint_add_commute[x',y'].
}
case negsuc(y') {
expand operator+.
}
}
}
case negsuc(x') {
switch y {
case pos(y') {
expand operator+.
}
case negsuc(y') {
expand operator+
replace uint_add_commute[x', y'].
}
}
}
}
end
lemma zero_monuso_neg: all n:UInt. 0 ⊝ (1 + n) = negsuc(n)
proof
arbitrary n:UInt
expand operator⊝
have A: 0 < 1 + n by uint_zero_less_one_add
replace (apply eq_true to A)
replace uint_monus_zero
neg_suc
end
lemma int_monuso_zero: all n:UInt. n ⊝ 0 = pos(n)
proof
arbitrary n:UInt
expand operator⊝
replace (apply eq_false to uint_not_less_zero[n])
replace uint_monus_zero.
end
lemma int_monuso_cancel: all n:UInt. n ⊝ n = +0
proof
arbitrary n:UInt
expand operator⊝
replace (apply eq_false to uint_less_irreflexive[n])
replace uint_monus_cancel.
end
lemma subo_monus: all x:UInt, y:UInt. x ⊝ y = pos(x) - pos(y)
proof
arbitrary x:UInt, y:UInt
expand operator⊝ | operator-
switch x < y {
case true assume x_y {
expand operator-
have yz_or_not: y = 0 or not (y = 0) by ex_mid[y = 0]
cases yz_or_not
case yz {
have xz: x < 0 by replace (replace yz in x_y).
conclude false by apply uint_not_less_zero to xz
}
case not_yz {
replace (apply eq_false to not_yz)
have xly: x < y by replace x_y.
have xy: x ≤ y by apply uint_less_implies_less_equal to xly
have pos_yx: 0 < y ∸ x by {
have A: x < x + (y ∸ x)
by replace (symmetric apply uint_monus_add_identity[y,x] to xy) in xly
have B: x + 0 < x + (y ∸ x) by A
apply uint_add_both_sides_of_less[x,0,y∸x] to B
}
have y_pos: 0 < y by apply uint_not_zero_pos to not_yz
have one_y: 1 ≤ y by apply uint_pos_implies_one_le to y_pos
have one_yx: 1 ≤ y ∸ x by apply uint_pos_implies_one_le to pos_yx
replace (apply eq_false to apply uint_pos_not_zero to pos_yx)
expand operator+
show negsuc((y ∸ x) ∸ 1) = x ⊝ (1 + (y ∸ 1))
replace (apply uint_monus_add_identity to one_y)
replace symmetric neg_suc[(y ∸ x) ∸ 1]
show - (1 + ((y ∸ x) ∸ 1)) = x ⊝ y
replace (apply uint_monus_add_identity to one_yx)
expand operator⊝
replace (apply eq_true to xly).
}
}
case false assume x_y_false {
expand operator- | operator+
have yz_or_not: y = 0 or not (y = 0) by ex_mid[y = 0]
cases yz_or_not
case yz {
replace yz
replace uint_monus_zero.
}
case ynz {
replace (apply eq_false to ynz)
show pos(x ∸ y) = x ⊝ (1 + (y ∸ 1))
have y_pos: 0 < y by apply uint_not_zero_pos to ynz
have one_y: 1 ≤ y by apply uint_pos_implies_one_le to y_pos
replace (apply uint_monus_add_identity to one_y)
expand operator⊝
replace x_y_false.
}
}
}
end
lemma suc_uint_monuso: all x:UInt, y:UInt. (1 + x) ⊝ (1 + y) = x ⊝ y
proof
arbitrary x:UInt, y:UInt
switch x < y for operator ⊝{
case true assume xy_true {
have x_y: x < y by replace xy_true.
have sx_sy: 1 + x < 1 + y by apply uint_add_both_sides_of_less[1,x,y] to x_y
expand operator-
replace apply eq_true to sx_sy
replace uint_add_both_monus[1,y,x].
}
case false assume xy_false {
have: not (1 + x < 1 + y) by {
assume xy1: 1 + x < 1 + y
have xy: x < y by apply uint_add_both_sides_of_less to xy1
conclude false by replace xy_false in xy
}
expand operator -
replace apply eq_false to recall (not (1 + x < 1 + y))
replace uint_add_both_monus[1,x,y].
}
}
end
lemma distrib_left_monus_add: all m:UInt, n:UInt, o:UInt.
(n ⊝ o) + pos(m) = (n + m) ⊝ o
proof
arbitrary m:UInt, n:UInt
define P = fun n':UInt { all o:UInt. (n' ⊝ o) + pos(m) = (n' + m) ⊝ o }
have P0: P(0) by {
expand P
arbitrary o:UInt
cases uint_zero_or_positive[o]
case oz {
replace oz
show (0 ⊝ 0) + pos(m) = m ⊝ 0
replace int_monuso_zero.
}
case o_pos {
obtain o' where os: o = 1 + o' from apply uint_positive_add_one to o_pos
replace os | zero_monuso_neg
conclude #negsuc(o') + pos(m)# = m ⊝ (1 + o')
by expand operator+.
}
}
have ind: all n':UInt. if P(n') then P(1 + n') by {
arbitrary n':UInt
assume IH
expand P
arbitrary o:UInt
cases uint_zero_or_positive[o]
case oz {
replace oz | int_monuso_zero
expand operator+.
}
case o_pos {
obtain o' where os: o = 1 + o' from apply uint_positive_add_one to o_pos
replace os | suc_uint_monuso
conclude (n' ⊝ o') + pos(m) = (n' + m) ⊝ o'
by expand P in IH
}
}
expand P in apply uint_induction[P, n] to P0, ind
end
lemma add_pos_pos: all n:UInt, m:UInt.
pos(n) + pos(m) = pos(n + m)
proof
arbitrary n:UInt, m:UInt
conclude #pos(n) + pos(m)# = pos(n + m)
by expand operator+.
end
lemma add_pos_negsuc: all n:UInt, m:UInt.
pos(n) + negsuc(m) = n ⊝ (1 + m)
proof
arbitrary n:UInt, m:UInt
conclude #pos(n) + negsuc(m)# = n ⊝ (1 + m)
by expand operator+.
end
lemma add_negsuc_pos: all n:UInt, m:UInt.
negsuc(n) + pos(m) = m ⊝ (1 + n)
proof
arbitrary n:UInt, m:UInt
conclude #negsuc(n) + pos(m)# = m ⊝ (1 + n) by expand operator+.
end
lemma add_negsuc_negsuc: all n:UInt, m:UInt.
negsuc(n) + negsuc(m) = negsuc(1 + n + m)
proof
arbitrary n:UInt, m:UInt
conclude #negsuc(n) + negsuc(m)# = negsuc(1 + n + m)
by expand operator+.
end
lemma distrib_left_monus_add_neg: all m:UInt, n:UInt, o:UInt.
(n ⊝ o) + negsuc(m) = n ⊝ ((1 + o) + m)
proof
arbitrary m:UInt, n:UInt
define P = fun n':UInt { all o:UInt. (n' ⊝ o) + negsuc(m) = n' ⊝ ((1 + o) + m)}
have P0: P(0) by {
expand P
arbitrary o:UInt
cases uint_zero_or_positive[o]
case oz {
replace oz
evaluate
}
case o_pos {
obtain o' where os: o = 1 + o' from apply uint_positive_add_one to o_pos
replace os | zero_monuso_neg
show #negsuc(o') + negsuc(m)# = negsuc((1 + o') + m)
expand operator+.
}
}
have ind: all n':UInt. if P(n') then P(1 + n') by {
arbitrary n':UInt
assume IH
expand P
arbitrary o:UInt
cases uint_zero_or_positive[o]
case oz {
replace oz | int_monuso_zero | suc_uint_monuso | add_pos_negsuc
replace suc_uint_monuso.
}
case o_pos {
obtain o' where os: o = 1 + o' from apply uint_positive_add_one to o_pos
replace os | suc_uint_monuso
expand P in IH
}
}
expand P in apply uint_induction[P, n] to P0, ind
end
theorem add_commute_uint_int: all x:UInt, y:Int.
x + y = y + x
proof
arbitrary x:UInt, y:Int
switch y {
case pos(y') {
expand 2* operator+ replace uint_add_commute[x,y'].
}
case negsuc(y') {
expand 2* operator+.
}
}
end
lemma distrib_right_monus_add: all m:UInt, n:UInt, o:UInt.
pos(m) + (n ⊝ o) = (m + n) ⊝ o
proof
arbitrary m:UInt, n:UInt, o:UInt
equations
pos(m) + (n ⊝ o)
= (n ⊝ o) + pos(m) by int_add_commute
... = (n + m) ⊝ o by distrib_left_monus_add
... = (m + n) ⊝ o by replace uint_add_commute.
end
lemma distrib_right_monus_add_neg: all m:UInt, n:UInt, o:UInt.
negsuc(m) + (n ⊝ o) = n ⊝ (1 + m + o)
proof
arbitrary m:UInt, n:UInt, o:UInt
equations
negsuc(m) + (n ⊝ o)
= (n ⊝ o) + negsuc(m) by int_add_commute
... = n ⊝ (1 + o + m) by distrib_left_monus_add_neg[m,n,o]
... = n ⊝ (1 + m + o) by replace uint_add_commute[o,m].
end
theorem int_add_assoc: all x:Int, y:Int, z:Int. (x + y) + z = x + (y + z)
proof
arbitrary x:Int, y:Int, z:Int
switch x {
case pos(x') {
switch y {
case pos(y') {
switch z {
case pos(z') {
expand operator+.
}
case negsuc(z') {
equations
(pos(x') + pos(y')) + negsuc(z')
= (x' + y') ⊝ (1 + z') by expand operator+.
... = pos(x') + (y' ⊝ (1 + z')) by symmetric distrib_right_monus_add
... = pos(x') + #pos(y') + negsuc(z')# by expand operator+.
}
}
}
case negsuc(y') {
switch z {
case pos(z') {
equations
(pos(x') + negsuc(y')) + pos(z')
= (x' ⊝ (1 + y')) + pos(z') by evaluate
... = (x' + z') ⊝ (1 + y') by distrib_left_monus_add
... = pos(x') + (z' ⊝ (1 + y')) by symmetric distrib_right_monus_add
... = pos(x') + #(negsuc(y') + pos(z'))# by expand operator+.
}
case negsuc(z') {
equations
(pos(x') + negsuc(y')) + negsuc(z')
= (x' ⊝ (1 + y')) + negsuc(z') by evaluate
... = negsuc(z') + (x' ⊝ (1 + y')) by int_add_commute
... = x' ⊝ (1 + z' + 1 + y') by distrib_right_monus_add_neg
... = x' ⊝ (1 + 1 + y' + z') by replace uint_add_commute[z',1]
| uint_add_commute[z',y'].
... = #pos(x') + (negsuc(y') + negsuc(z'))# by expand operator+.
}
}
}
}
}
case negsuc(x') {
switch y {
case pos(y') {
switch z {
case pos(z') {
equations
(negsuc(x') + pos(y')) + pos(z')
= (y' ⊝ (1 + x')) + pos(z') by evaluate
... = (y' + z') ⊝ (1 + x') by distrib_left_monus_add
... = #negsuc(x') + (pos(y') + pos(z'))# by expand operator+.
}
case negsuc(z') {
equations
(negsuc(x') + pos(y')) + negsuc(z')
= (y' ⊝ (1 + x')) + negsuc(z') by evaluate
... = y' ⊝ (1 + 1 + x' + z') by distrib_left_monus_add_neg[z',y',1+x']
... = y' ⊝ (1 + 1 + z' + x') by replace uint_add_commute[x'].
... = (y' ⊝ (1 + z')) + negsuc(x')
by symmetric distrib_left_monus_add_neg[x',y',1+z']
... = negsuc(x') + (y' ⊝ (1 + z')) by int_add_commute
... = negsuc(x') + #pos(y') + negsuc(z')# by expand operator+.
}
}
}
case negsuc(y') {
switch z {
case pos(z') {
equations
(negsuc(x') + negsuc(y')) + pos(z')
= z' ⊝ (1 + 1 + x' + y') by expand operator+.
... = z' ⊝ (1 + 1 + y' + x') by replace uint_add_commute[x'].
... = (z' ⊝ (1 + y')) + negsuc(x')
by symmetric distrib_left_monus_add_neg[x',z',1+y']
... = negsuc(x') + (z' ⊝ (1 + y')) by int_add_commute
... = negsuc(x') + #negsuc(y') + pos(z')# by expand operator+.
}
case negsuc(z') {
equations
(negsuc(x') + negsuc(y')) + negsuc(z')
= negsuc(1 + 1 + x' + y' + z') by expand operator+.
... = negsuc(1 + x' + 1 + y' + z') by replace uint_add_commute[1,x'].
... = #negsuc(x') + (negsuc(y') + negsuc(z'))# by expand operator+.
}
}
}
}
}
}
end
associative operator+ in Int
theorem int_add_inverse: all x:Int. x + -x = +0
proof
arbitrary x:Int
switch x {
case pos(x') {
cases uint_zero_or_positive[x']
case xpz {
replace xpz
evaluate
}
case xp_pos {
obtain x'' where xpps: x' = 1 + x'' from apply uint_positive_add_one to xp_pos
replace xpps
expand operator-
replace (apply eq_false to uint_not_one_add_zero[x'']) | add_pos_negsuc
replace uint_add_monus_identity | suc_uint_monuso | int_monuso_cancel.
}
}
case negsuc(x') {
expand operator-
replace add_negsuc_pos | suc_uint_monuso | int_monuso_cancel.
}
}
end
lemma neg_uint: all x:UInt. -x = -pos(x)
proof
arbitrary x:UInt
evaluate
end
lemma neg_monuso: all x:UInt, y:UInt. - (x ⊝ y) = y ⊝ x
proof
arbitrary x:UInt, y:UInt
cases uint_trichotomy[x,y]
case: x < y {
have: not (y < x) by apply uint_less_implies_not_greater to (recall x < y)
expand operator ⊝
replace (apply eq_true to recall x < y)
replace (apply eq_false to recall not (y < x))
show - (- (y ∸ x)) = pos(y ∸ x)
replace neg_uint | neg_involutive.
}
case: x = y {
suffices - (y ⊝ y) = y ⊝ y by replace recall x = y.
suffices - +0 = +0 by replace int_monuso_cancel.
expand operator-.
}
case: y < x {
have: not (x < y) by apply uint_less_implies_not_greater to recall y < x
suffices - pos(x ∸ y) = - (x ∸ y)
by expand operator⊝ replace (apply eq_true to recall y < x)
| (apply eq_false to recall not (x < y)).
expand 2* operator-.
}
end
theorem neg_distr_add: all x:Int, y:Int. -(x + y) = (- x) + (- y)
proof
arbitrary x:Int, y:Int
switch x {
case pos(x') {
cases uint_zero_or_positive[x']
case xpz {
replace xpz
conclude -(+0 + y) = #- +0# + -y by expand operator-.
}
case xp_pos {
have xnz: not (x' = 0) by apply uint_pos_not_zero to xp_pos
have: 1 ≤ x' by apply uint_pos_implies_one_le to xp_pos
switch y {
case pos(y') {
replace add_pos_pos
cases uint_zero_or_positive[y']
case ypz {
replace ypz | neg_zero.
}
case yp_pos {
have ypnz: not (y' = 0) by apply uint_pos_not_zero to yp_pos
expand operator-
replace (apply eq_false to xnz) | (apply eq_false to ypnz)
replace add_negsuc_negsuc
have A: not (x' + y' = 0) by {
assume xyz
have: x' = 0 by apply uint_add_to_zero to xyz
conclude false by apply xnz to recall x' = 0
}
replace (apply eq_false to A)
replace apply uint_monus_add_identity to recall 1 ≤ x'
have: 1 ≤ y' by apply uint_pos_implies_one_le to yp_pos
replace apply uint_monus_add_assoc[y',x',1] to recall 1 ≤ y'.
}
}
case negsuc(y') {
replace add_pos_negsuc
replace neg_monuso
expand operator-
replace (apply eq_false to xnz)
replace add_negsuc_pos
replace apply uint_monus_add_identity to recall 1 ≤ x'.
}
}
}
}
case negsuc(x') {
switch y {
case pos(y') {
suffices - (y' ⊝ (1 + x')) = - negsuc(x') + - pos(y') by evaluate
equations
- (y' ⊝ (1 + x'))
= (1 + x') ⊝ y' by neg_monuso
... = pos(1 + x') - pos(y') by subo_monus
... = pos(1 + x') + - pos(y') by expand operator-.
... = #- negsuc(x')# + - pos(y') by expand operator-.
}
case negsuc(y') {
expand operator+ | operator-
show pos(1 + #1 + x'# + y') = pos(1 + x' + 1 + y')
replace uint_add_commute.
}
}
}
}
end
theorem int_sub_cancel: all x:Int. x - x = +0
proof
arbitrary x:Int
expand operator-
show x + (- x) = +0
int_add_inverse
end
lemma mult_pos_pos: all x:UInt, y:UInt. pos(x) * pos(y) = pos(x * y)
proof
arbitrary x:UInt, y:UInt
evaluate
end
lemma mult_pos_negsuc: all x:UInt, y:UInt.
pos(x) * negsuc(y) = - pos(x + x * y)
proof
arbitrary x:UInt, y:UInt
show #pos(x) * negsuc(y)# = - pos(x + x * y)
expand operator*
expand sign | abs
replace mult_pos_neg | mult_neg_uint | uint_dist_mult_add.
end
theorem int_one_mult: all x:Int. +1 * x = x
proof
arbitrary x:Int
switch x {
case pos(x') {
replace mult_pos_pos.
}
case negsuc(x') {
replace mult_pos_negsuc | neg_pos.
}
}
end
auto int_one_mult
theorem int_zero_mult: all x:Int. +0 * x = +0
proof
arbitrary x:Int
switch x {
case pos(x') { evaluate }
case negsuc(x') { evaluate }
}
end
auto int_zero_mult
lemma sign_neg_flip: all x:Int.
if not (x = +0)
then sign(- x) = flip(sign(x))
proof
arbitrary x:Int
switch x {
case pos(x') {
assume prem
expand operator-
have xnz: not (x' = 0) by {
assume xz
conclude false by replace xz in prem
}
replace (apply eq_false to xnz)
expand sign | flip.
}
case negsuc(x') {
expand operator- | sign | flip.
}
}
end
theorem dist_neg_mult: all x:Int,y:Int.
-(x * y) = (-x) * y
proof
arbitrary x:Int, y:Int
switch x {
case pos(x') {
switch y {
case pos(y') {
expand operator*
replace sign_pos
replace mult_pos_any | abs_pos | mult_pos_uint
cases uint_zero_or_positive[x']
case xz {
replace xz | neg_zero
expand sign | abs
replace mult_pos_any | mult_pos_uint.
}
case xp_pos {
have xnz: not (x' = 0) by apply uint_pos_not_zero to xp_pos
expand operator-
replace (apply eq_false to xnz)
expand abs | sign
replace mult_neg_pos | mult_neg_uint
cases uint_zero_or_positive[y']
case yz {
replace yz
expand operator-.
}
case y_pos {
have ynz: not (y' = 0) by apply uint_pos_not_zero to y_pos
have nxyz: not (x' * y' = 0) by {
assume xyz
cases apply uint_mult_to_zero[x',y'] to xyz
case xz {
conclude false by apply xnz to xz
}
case yz {
conclude false by apply ynz to yz
}
}
replace (apply eq_false to nxyz)
have one_x: 1 ≤ x' by apply uint_pos_implies_one_le to xp_pos
replace (apply uint_monus_add_identity to one_x)
replace (symmetric neg_pos[(x' * y' ∸ 1)])
have one_xy: 1 ≤ x' * y' by {
obtain y'' where yp: y' = 1 + y'' from apply uint_positive_add_one to y_pos
replace yp | uint_dist_mult_add
have x_xy: x' ≤ x' + x' * y'' by uint_less_equal_add
apply uint_less_equal_trans to one_x, x_xy
}
replace (apply uint_monus_add_identity to one_xy).
}
}
}
case negsuc(y') {
expand operator*
replace sign_pos | sign_negsuc | mult_pos_any | mult_neg_uint | abs_negsuc | abs_pos
| neg_involutive | abs_neg | abs_pos
cases uint_zero_or_positive[x']
case xz {
replace xz
evaluate
}
case xp_pos {
have xnz: not (x' = 0) by apply uint_pos_not_zero to xp_pos
expand operator-
replace (apply eq_false to xnz) | sign_negsuc | mult_neg_neg | mult_pos_uint.
}
}
}
}
case negsuc(x') {
switch y {
case pos(y') {
expand operator*
replace sign_negsuc | sign_pos | abs_negsuc | abs_pos | mult_neg_pos | mult_neg_uint
replace sign_neg_negsuc | mult_pos_any | abs_neg | abs_negsuc | mult_pos_uint | neg_involutive.
}
case negsuc(y') {
expand operator*
replace sign_negsuc | abs_negsuc | sign_neg_negsuc | mult_pos_neg | abs_neg | abs_negsuc | mult_neg_uint
| mult_neg_neg | mult_pos_uint.
}
}
}
}
end
theorem int_mult_commute: all x:Int, y:Int. x * y = y * x
proof
arbitrary x:Int, y:Int
switch x {
case pos(x') {
switch y {
case pos(y') {
suffices pos(x' * y') = pos(y' * x') by evaluate
replace uint_mult_commute[x',y'].
}
case negsuc(y') {
suffices - (x' * (1 + y')) = - ((1 + y') * x') by evaluate
replace uint_mult_commute[x', 1 + y'].
}
}
}
case negsuc(x') {
switch y {
case pos(y') {
suffices - ((1 + x') * y') = - (y' * (1 + x')) by evaluate
replace uint_mult_commute[1 + x', y'].
}
case negsuc(y') {
suffices pos((1 + x') * (1 + y')) = pos((1 + y') * (1 + x')) by evaluate
replace uint_mult_commute[(1 + x'), (1 + y')].
}
}
}
}
end
theorem int_mult_one: all x:Int. x * +1 = x
proof
arbitrary x:Int
conclude x * +1 = x by int_mult_commute[x,+1]
end
auto int_mult_one
theorem int_mult_zero: all x:Int. x * +0 = +0
proof
arbitrary x:Int
conclude x * +0 = +0 by int_mult_commute[x,+0]
end
auto int_mult_zero
lemma mult_assoc_helper: all x:UInt, y:UInt, z:UInt.
z + (y + x * (1 + y)) * (1 + z)
= (z + y * (1 + z)) + x * (1 + z + y * (1 + z))
proof
arbitrary x:UInt, y:UInt, z:UInt
equations
z + (y + x * (1 + y)) * (1 + z)
= z + (y + x + x * y) * (1 + z)
by replace uint_dist_mult_add[x].
... = z + y + x + x * y + (y + x + x * y) * z
by replace uint_dist_mult_add.
... = z + y + x + x * y + y*z + x*z + x*y*z
by replace uint_dist_mult_add_right.
... = z + y + x + y*z + x*y + x*z + x*y*z
by replace uint_add_commute[x*y, y*z].
... = z + y + x + y*z + x*z + x*y + x*y*z
by replace uint_add_commute[x*y].
... = z + y + y*z + x + x*z + x*y + x*y*z
by replace uint_add_commute[x].
... = #(z + y * (1 + z)) + x * (1 + z + y * (1 + z))#
by replace uint_dist_mult_add.
end
theorem int_mult_assoc: all x:Int, y:Int, z:Int. (x * y) * z = x * (y * z)
proof
arbitrary x:Int, y:Int, z:Int
switch x {
case pos(x') {
cases uint_zero_or_positive[x']
case xpz: x' = 0 {
replace xpz.
}
case xp_pos: 0 < x' {
have xnz: not (x' = 0) by apply uint_pos_not_zero to xp_pos
obtain x'' where xp_eq: x' = 1 + x'' from apply uint_positive_add_one to xp_pos
switch y {
case pos(y') {
cases uint_zero_or_positive[y']
case ypz: y' = 0 {
replace ypz.
}
case yp_pos: 0 < y' {
have ynz: not (y' = 0) by apply uint_pos_not_zero to yp_pos
switch z {
case pos(z') {
replace mult_pos_pos | mult_pos_pos.
}
case negsuc(z') {
replace mult_pos_pos
replace mult_pos_negsuc
replace int_mult_commute[pos(x'), -pos(y'+y'*z')] | symmetric dist_neg_mult[pos(y'+y'*z'), pos(x')]
replace mult_pos_pos | uint_dist_mult_add_right | uint_mult_commute[y',x']
| uint_mult_commute[y'*z',x'].
}
}
}
}
case negsuc(y') {
switch z {
case pos(z') {
expand operator*
replace sign_pos | sign_negsuc | abs_pos | abs_negsuc | mult_pos_neg | mult_neg_uint
replace mult_neg_pos | mult_neg_uint | abs_neg | abs_pos | mult_any_pos | mult_pos_any
replace uint_dist_mult_add | uint_dist_mult_add_right
replace xp_eq | sign_neg_pos
cases uint_zero_or_positive[z']
case zpz: z' = 0 {
replace zpz
expand operator- | sign | 2*operator* | operator-.
}
case zp_pos: 0 < z' {
have znz: not (z' = 0) by apply uint_pos_not_zero to zp_pos
obtain z'' where zp_eq: z' = 1 + z'' from apply uint_positive_add_one to zp_pos
replace zp_eq
replace sign_neg_pos.
}
}
case negsuc(z') {
expand operator*
replace sign_pos | sign_negsuc | abs_pos | abs_negsuc
replace mult_pos_neg | mult_neg_uint | mult_pos_any | mult_neg_neg | mult_pos_uint | abs_pos | sign_pos
replace mult_pos_uint | uint_dist_mult_add | uint_dist_mult_add
replace xp_eq | sign_neg_pos | mult_neg_neg | abs_neg | abs_pos | mult_pos_uint.
}
}
}
}
}
}
case negsuc(x') {
switch y {
case pos(y') {
switch z {
case pos(z') {
expand operator*
replace sign_negsuc | sign_pos | abs_negsuc | abs_pos | mult_neg_pos | mult_neg_uint | mult_pos_any
| mult_pos_uint | uint_dist_mult_add_right | sign_pos | mult_neg_pos | abs_pos
| mult_neg_uint
cases uint_zero_or_positive[y']
case ypz: y' = 0 {
replace ypz
evaluate
}
case yp_pos: 0 < y' {
obtain y'' where yp_eq: y' = 1 + y'' from apply uint_positive_add_one to yp_pos
replace yp_eq
replace sign_neg_pos | mult_neg_pos | abs_neg | abs_pos | mult_neg_uint | uint_dist_mult_add_right
| uint_dist_mult_add | uint_dist_mult_add_right | uint_dist_mult_add_right.
}
}
case negsuc(z') {
expand operator*
replace sign_negsuc | sign_pos | abs_negsuc | abs_pos | mult_neg_pos | mult_neg_uint | mult_pos_neg
| mult_neg_uint | uint_dist_mult_add_right | uint_dist_mult_add
cases uint_zero_or_positive[y']
case ypz: y' = 0 {
replace ypz
expand operator-
expand sign | abs
evaluate
}
case yp_pos: 0 < y' {
obtain y'' where yp_eq: y' = 1 + y'' from apply uint_positive_add_one to yp_pos
replace yp_eq
replace sign_neg_pos | abs_neg | abs_pos | mult_neg_neg | uint_dist_mult_add
replace uint_dist_mult_add_right | mult_pos_uint
replace uint_add_commute[x'+x'*y'',z']
replace uint_add_commute[x'+x'*y'',y''*z'].
}
}
}
}
case negsuc(y') {
switch z {
case pos(z') {
cases uint_zero_or_positive[z']
case zpz: z' = 0 {
replace zpz
evaluate
}
case zp_pos: 0 < z' {
have znz: not (z' = 0) by apply uint_pos_not_zero to zp_pos
obtain z'' where zp_eq: z' = 1 + z'' from apply uint_positive_add_one to zp_pos
replace zp_eq
expand operator*
replace sign_negsuc | abs_negsuc | mult_neg_neg | sign_pos | mult_pos_uint | mult_neg_pos | abs_pos
| mult_neg_uint | sign_pos | mult_pos_any | uint_dist_mult_add
| uint_dist_mult_add_right
| uint_dist_mult_add_right
| uint_dist_mult_add
| sign_neg_pos | mult_neg_neg | mult_pos_uint | abs_neg | abs_pos
| uint_add_commute[z'' + x' + x' * z'', y']
| uint_add_commute[x' + x' * z'', y' * z'']
| uint_dist_mult_add
| uint_add_commute[x' * z'', x' * y'].
}
}
case negsuc(z'') {
suffices negsuc(z'' + (y' + x' * (1 + y')) * (1 + z''))
= negsuc((z'' + y' * (1 + z'')) + x' * (1 + z'' + y' * (1 + z'')))
by evaluate
replace mult_assoc_helper[x',y',z''].
}
}
}
}
}
}
end
associative operator* in Int
theorem int_less_equal_refl: all n:Int. n ≤ n
proof
arbitrary n:Int
switch n {
case pos(n') {
expand operator≤
uint_less_equal_refl
}
case negsuc(n') {
expand operator≤
uint_less_equal_refl
}
}
end
theorem int_less_equal_trans: all m:Int, n:Int, o:Int.
if m ≤ n and n ≤ o then m ≤ o
proof
arbitrary m:Int, n:Int, o:Int
switch m {
case pos(m') {
switch n {
case pos(n') {
switch o {
case pos(o') {
expand operator≤
uint_less_equal_trans
}
case negsuc(o') { expand operator≤. }
}
}
case negsuc(n') { expand operator≤. }
}
}
case negsuc(m') {
switch n {
case pos(n') {
switch o {
case pos(o') { expand operator≤. }
case negsuc(o') { expand operator≤. }
}
}
case negsuc(n') {
switch o {
case pos(o') { expand operator≤. }
case negsuc(o') {
expand operator≤
assume nm_n_on
apply uint_less_equal_trans[o',n',m'] to nm_n_on
}
}
}
}
}
}
end
theorem int_less_equal_antisymmetric:
all x:Int, y:Int.
if x ≤ y and y ≤ x
then x = y
proof
arbitrary x:Int, y:Int
assume xy_n_yx
switch x {
case pos(x') assume x_pos {
switch y {
case pos(y') assume y_pos {
have: x' ≤ y' and y' ≤ x' by expand operator≤ in replace x_pos | y_pos in xy_n_yx
have: x' = y' by apply uint_less_equal_antisymmetric to (recall x' ≤ y' and y' ≤ x')
conclude pos(x') = pos(y') by replace (recall x' = y').
}
case negsuc(y') assume y_neg {
conclude false by expand operator≤ in replace x_pos | y_neg in xy_n_yx
}
}
}
case negsuc(x') assume x_neg {
switch y {
case pos(y') assume y_pos {
conclude false by expand operator≤ in replace x_neg | y_pos in xy_n_yx
}
case negsuc(y') assume y_neg {
have: x' ≤ y' and y' ≤ x' by expand operator≤ in replace x_neg | y_neg in xy_n_yx
have: x' = y' by apply uint_less_equal_antisymmetric to (recall x' ≤ y' and y' ≤ x')
conclude negsuc(x') = negsuc(y') by replace (recall x' = y').
}
}
}
}
end