module UInt
import Base
import Nat
import UIntDefs
import UIntToFrom
import UIntLess
import UIntAdd
theorem toNat_mult: all x:UInt, y:UInt.
toNat(x * y) = toNat(x) * toNat(y)
proof
induction UInt
case bzero {
arbitrary y:UInt
show toNat(bzero * y) = toNat(bzero) * toNat(y)
expand operator* | toNat
evaluate
}
case dub_inc(x') assume IH {
arbitrary y:UInt
show toNat(dub_inc(x') * y) = toNat(dub_inc(x')) * toNat(y)
switch y {
case bzero {
expand operator* | toNat
evaluate
}
case dub_inc(y') {
expand operator* | toNat
replace toNat_dub
expand toNat
replace toNat_add | toNat_add
replace IH[y']
replace nat_suc_one_add
replace dist_mult_add[(ℕ2 + ℕ2 * toNat(x')), ℕ2, ℕ2*toNat(y')]
replace mult_commute[toNat(x'), ℕ2]
replace dist_mult_add_right[ℕ4, ℕ4*toNat(x'), toNat(y')].
}
case inc_dub(y') {
expand operator* | toNat
replace toNat_add | toNat_dub | toNat_add
replace IH[y']
replace nat_suc_one_add | dist_mult_add[(ℕ2 + ℕ2 * toNat(x')), ℕ1, ℕ2*toNat(y')]
replace mult_commute[toNat(x'), ℕ2]
| dist_mult_add_right[ℕ4, ℕ4*toNat(x'), toNat(y')].
}
}
}
case inc_dub(x') assume IH {
arbitrary y:UInt
show toNat(inc_dub(x') * y) = toNat(inc_dub(x')) * toNat(y)
switch y {
case bzero {
expand operator* | toNat
evaluate
}
case dub_inc(y') {
expand operator* | toNat
replace toNat_add | toNat_add | toNat_dub
replace IH[y']
replace dist_mult_add[ℕ2 * toNat(x'), ℕ2, ℕ2 * toNat(y')]
replace mult_commute[toNat(x'), ℕ2]
replace add_commute[ℕ4 * toNat(x'), ℕ2 * toNat(y')].
}
case inc_dub(y') {
expand operator* | toNat
replace toNat_add | toNat_add | toNat_dub
replace IH[y']
replace nat_suc_one_add | nat_suc_one_add
replace dist_mult_add[ℕ2 * toNat(x'), ℕ1, ℕ2 * toNat(y')]
replace mult_commute[toNat(x'), ℕ2]
replace add_commute[ℕ2 * toNat(x'), ℕ2 * toNat(y')].
}
}
}
end
theorem uint_mult_commute: all m:UInt, n:UInt.
m * n = n * m
proof
arbitrary m:UInt, n:UInt
suffices toNat(m * n) = toNat(n * m) by uint_toNat_injective
replace toNat_mult
mult_commute
end
theorem uint_mult_assoc: all m:UInt, n:UInt, o:UInt.
(m * n) * o = m * (n * o)
proof
arbitrary m:UInt, n:UInt, o:UInt
suffices toNat((m * n) * o) = toNat(m * (n * o)) by uint_toNat_injective
replace toNat_mult | toNat_mult.
end
associative operator* in UInt
postulate fromNat_mult: all x:Nat, y:Nat. (fromNat(x * y) = fromNat(x) * fromNat(y))
theorem lit_mult_fromNat: all x:Nat, y:Nat.
fromNat(lit(x)) * fromNat(lit(y)) = fromNat(lit(x) * lit(y))
proof
arbitrary x:Nat, y:Nat
symmetric
fromNat_mult[lit(x), lit(y)]
end
auto lit_mult_fromNat
theorem uint_zero_mult: all n:UInt. 0 * n = 0
proof
arbitrary n:UInt
expand lit | fromNat | operator*.
end
auto uint_zero_mult
postulate uint_mult_zero: all n:UInt. n * 0 = 0
auto uint_mult_zero
theorem uint_one_mult: all n:UInt.
1 * n = n
proof
arbitrary n:UInt
suffices toNat(1 * n) = toNat(n) by uint_toNat_injective
replace toNat_mult
evaluate
end
auto uint_one_mult
theorem uint_mult_one: all n:UInt.
n * 1 = n
proof
arbitrary n:UInt
suffices toNat(n * 1) = toNat(n) by uint_toNat_injective
replace toNat_mult
evaluate
end
auto uint_mult_one
theorem uint_dist_mult_add:
all a:UInt, x:UInt, y:UInt.
a * (x + y) = a * x + a * y
proof
arbitrary a:UInt, x:UInt, y:UInt
suffices toNat(a * (x + y)) = toNat(a * x + a * y) by uint_toNat_injective
replace toNat_mult | toNat_add | toNat_mult
replace dist_mult_add.
end
postulate uint_dist_mult_add_right:
all x:UInt, y:UInt, a:UInt.
(x + y) * a = x * a + y * a
postulate uint_mult_to_zero: all n:UInt, m:UInt.
(if n * m = 0 then n = 0 or m = 0)
postulate uint_two_mult: all n:UInt. 2 * n = n + n
postulate uint_mult_mono_le: (all n:UInt, x:UInt, y:UInt. (if x ≤ y then n * x ≤ n * y))
postulate uint_mult_mono_le2 : all n : UInt, x : UInt, m:UInt, y : UInt. (if n ≤ m and x ≤ y then n * x ≤ m * y)
lemma inc_dub_add_mult2: all n:UInt. inc_dub(n) = 1 + 2 * n
proof
arbitrary n:UInt
suffices toNat(inc_dub(n)) = toNat(1 + 2 * n) by uint_toNat_injective
replace toNat_add | toNat_mult
expand toNat
replace uint_toNat_fromNat
replace nat_suc_one_add.
end
lemma dub_inc_mult2_add: all n:UInt. dub_inc(n) = 2 * (1 + n)
proof
arbitrary n:UInt
suffices toNat(dub_inc(n)) = toNat(2 * (1 + n)) by uint_toNat_injective
replace toNat_mult | toNat_add
expand toNat
replace uint_toNat_fromNat.
end
postulate uint_pos_mult_both_sides_of_less : all n : UInt, x : UInt, y : UInt.
(if 0 < n and x < y then n * x < n * y)