1-- Multiplication and the order of the integers: signs of products,2-- cancellation, and squares3-- Part of Cumulus, the Grace17 mathematics library.4-- Copyright (c) 2026 Grant Passmore.5-- Released under the Apache License 2.0. See LICENSE in the repository root.6-- Authors: Grant Passmore78module Grace.Cumulus.Int.OrderMul9import Order1011theorem integerLe.mul_nonneg (x y : Integer)12requires first : 0≤ x13requires second : 0≤ y14shows0≤ x * y15proof16have xNonnegative := integerLe.zero_iff.forward with first17have yNonnegative := integerLe.zero_iff.forward with second18apply integerLe.zero_iff.backward19exact IntegerNonnegative.mul with xNonnegative, yNonnegative2021theorem integerLess.mul_positive (x y : Integer)22requires first : 0 < x23requires second : 0 < y24shows0 < x * y25proof26have xPositive := integerLess.zero_iff_positive.forward with first27have yPositive := integerLess.zero_iff_positive.forward with second28apply integerLess.zero_iff_positive.backward29exact IntegerPositive.mul with xPositive, yPositive3031theorem integerLe.mul_left (x y k : Integer)32requires nonnegative : 0≤ k33requires below : x ≤ y34shows k * x ≤ k * y35proof36have difference := integerLe.sub_nonneg_iff.forward with below37have product := integerLe.mul_nonneg with nonnegative, difference38have shape : k * y - k * x = k * (y - x) byring39apply integerLe.sub_nonneg_iff.backward40rw shape41exact product4243theorem integerLe.mul_right (x y k : Integer)44requires nonnegative : 0≤ k45requires below : x ≤ y46shows x * k ≤ y * k47proof48have scaled := integerLe.mul_left with nonnegative, below49haveleft : k * x = x * k byring50haveright : k * y = y * k byring51rw [left, right] at scaled52exact scaled5354theorem integerLess.mul_left (x y k : Integer)55requires positive : 0 < k56requires below : x < y57shows k * x < k * y58proof59have difference := integerLess.sub_positive_iff.forward with below60have product := integerLess.mul_positive with positive, difference61have shape : k * y - k * x = k * (y - x) byring62apply integerLess.sub_positive_iff.backward63rw shape64exact product6566theorem integerLess.mul_right (x y k : Integer)67requires positive : 0 < k68requires below : x < y69shows x * k < y * k70proof71have scaled := integerLess.mul_left with positive, below72haveleft : k * x = x * k byring73haveright : k * y = y * k byring74rw [left, right] at scaled75exact scaled7677theorem integerLe.mul (a b c d : Integer)78requires aNonnegative : 0≤ a79requires first : a ≤ b80requires cNonnegative : 0≤ c81requires second : c ≤ d82shows a * c ≤ b * d83proof84have dNonnegative := integerLe.transitive with cNonnegative, second85haveleft:= integerLe.mul_left at c, d, a with aNonnegative, second86haveright:= integerLe.mul_right at a, b, d with dNonnegative, first87exact integerLe.transitive withleft, right8889theorem integerLe.mul_nonpos (x y : Integer)90requires nonpositive : x ≤091requires nonnegative : 0≤ y92shows x * y ≤093proof94have negated := integerLe.neg_nonneg_iff.backward with nonpositive95have product := integerLe.mul_nonneg with negated, nonnegative96have shape : (-x) * y = -(x * y) byring97rw shape at product98exact integerLe.neg_nonneg_iff.forward with product99100theorem integerLe.mul_nonpos_right (x y : Integer)101requires nonnegative : 0≤ x102requires nonpositive : y ≤0103shows x * y ≤0104proof105have swapped := integerLe.mul_nonpos with nonpositive, nonnegative106have shape : y * x = x * y byring107rw shape at swapped108exact swapped109110theorem integerLe.mul_nonpos_nonpos (x y : Integer)111requires first : x ≤0112requires second : y ≤0113shows0≤ x * y114proof115have xNegated := integerLe.neg_nonneg_iff.backward with first116have yNegated := integerLe.neg_nonneg_iff.backward with second117have product := integerLe.mul_nonneg with xNegated, yNegated118have shape : (-x) * (-y) = x * y byring119rw shape at product120exact product121122theorem integerLess.mul_negative (x y : Integer)123requires positive : 0 < x124requires negative : y < 0125shows x * y < 0126proof127have negated := integerLess.neg.forward with negative128have zero : -integerZero =0129ring130rw zero at negated131have product := integerLess.mul_positive with positive, negated132have shape : x * (-y) = -(x * y) byring133rw shape at product134have flipped := integerLess.neg at x * y, integerZero135rw zero at flipped136exact flipped.backward with product137138theorem integerLess.mul_negative_negative (x y : Integer)139requires first : x < 0140requires second : y < 0141shows0 < x * y142proof143have zero : -integerZero =0byring144have xNegated := integerLess.neg.forward with first145have yNegated := integerLess.neg.forward with second146rw zero at xNegated147rw zero at yNegated148have product := integerLess.mul_positive with xNegated, yNegated149have shape : (-x) * (-y) = x * y byring150rw shape at product151exact product152153theorem integerLe.square_nonneg (x : Integer)154shows0≤ x * x155proof156havesplit:= integerLe.cases_sign at x157casessplitwith nonnegative | nonpositive158 . exact integerLe.mul_nonneg with nonnegative, nonnegative159 . exact integerLe.mul_nonpos_nonpos with nonpositive, nonpositive160161theorem integerMulValue.eq_zero (x y : Integer)162requires zero : x * y =0163shows x =0∨ y =0164proof165have xNat := integerNatAbs.natural at x166have yNat := integerNatAbs.natural at y167have magnitudes := integerNatAbs.mul at x, y168rw zero at magnitudes169have vanish := integerNatAbs.zero170rw vanish at magnitudes171 symm at magnitudes172havesplit:= mul.eq_zero_iff.forward with magnitudes173casessplitwith xZero | yZero174 . left175exact integerNatAbs.zero_iff.forward with xZero176 . right177exact integerNatAbs.zero_iff.forward with yZero178179theorem integerMulValue.eq_zero_iff (x y : Integer)180shows x * y =0↔ x =0∨ y =0181proof182constructor183 . intro zero184exact integerMulValue.eq_zero with zero185 . introsplit186casessplitwith xZero | yZero187 . rw xZero188ring189 . rw yZero190ring191192theorem integerMulValue.nonzero (x y : Integer)193requires first : x ≠0194requires second : y ≠0195shows x * y ≠0196proof197intro zero198havesplit:= integerMulValue.eq_zero with zero199casessplitwith xZero | yZero200 . exact first with xZero201 . exact second with yZero202203theorem integerMulValue.square_eq_zero (x : Integer)204requires zero : x * x =0205shows x =0206proof207havesplit:= integerMulValue.eq_zero with zero208casessplitwith first | second209 . exact first210 . exact second211212theorem integerMulValue.square_eq_zero_iff (x : Integer)213shows x * x =0↔ x =0214proof215constructor216 . intro zero217exact integerMulValue.square_eq_zero with zero218 . intro zero219rw zero220ring221222theorem integerLess.square_positive (x : Integer)223requires nonzero : x ≠0224shows0 < x * x225proof226have nonnegative := integerLe.square_nonneg at x227have distinct : 0≠ x * x228intro zero229 symm at zero230have same := integerMulValue.square_eq_zero with zero231exact nonzero with same232exact integerLess.of_le_ne with nonnegative, distinct233234theorem integerMulValue.left_cancel (x y k : Integer)235requires nonzero : k ≠0236requires same : k * x = k * y237shows x = y238proof239have product : k * (x - y) =0240have shape : k * (x - y) = k * x - k * y byring241rw [shape, same]242ring243havesplit:= integerMulValue.eq_zero with product244casessplitwith kZero | difference245 . exfalso246exact nonzero with kZero247 . linear_combination difference248249theorem integerMulValue.right_cancel (x y k : Integer)250requires nonzero : k ≠0251requires same : x * k = y * k252shows x = y253proof254haveleft : x * k = k * x byring255haveright : y * k = k * y byring256rw [left, right] at same257exact integerMulValue.left_cancel with nonzero, same258259theorem integerLe.mul_left_cancel (x y k : Integer)260requires positive : 0 < k261requires below : k * x ≤ k * y262shows x ≤ y263proof264apply integerLe.of_not_less265intro above266have scaled := integerLess.mul_left at y, x, k with positive, above267exact integerLe.not_less with below, scaled268269theorem integerLe.mul_right_cancel (x y k : Integer)270requires positive : 0 < k271requires below : x * k ≤ y * k272shows x ≤ y273proof274haveleft : x * k = k * x byring275haveright : y * k = k * y byring276rw [left, right] at below277exact integerLe.mul_left_cancel with positive, below278279theorem integerLess.mul_left_cancel (x y k : Integer)280requires positive : 0 < k281requires below : k * x < k * y282shows x < y283proof284apply integerLess.of_not_le285intro above286have weak := integerLess.implies_le with positive287have scaled := integerLe.mul_left at y, x, k with weak, above288exact integerLess.not_le with below, scaled289290theorem integerLess.mul_right_cancel (x y k : Integer)291requires positive : 0 < k292requires below : x * k < y * k293shows x < y294proof295haveleft : x * k = k * x byring296haveright : y * k = k * y byring297rw [left, right] at below298exact integerLess.mul_left_cancel with positive, below299300theorem integerLe.sum_squares_eq_zero (x y : Integer)301requires zero : x * x + y * y =0302shows x =0∧ y =0303proof304have xSquare := integerLe.square_nonneg at x305have ySquare := integerLe.square_nonneg at y306have xZero : x * x =0307have upper : x * x ≤0308have shape : x * x =0 - y * y bylinear_combination zero309rw shape310have flipped := integerLe.neg_nonneg_iff.forward at y * y311have negShape : -(y * y) =0 - y * y byring312rw negShape at flipped313have negated := integerLe.neg.forward with ySquare314have zeroNeg : -integerZero =0byring315rw [zeroNeg, negShape] at negated316exact negated317exact integerLe.antisymmetric with upper, xSquare318have yZero : y * y =0bylinear_combination zero - xZero319constructor320 . exact integerMulValue.square_eq_zero with xZero321 . exact integerMulValue.square_eq_zero with yZero322323theorem integerLe.le_square (x : Integer)324shows x ≤ x * x325proof326havesplit:= integerLe.cases_sign at x327casessplitwith nonnegative | nonpositive328 . havecases:= integerLe.cases with nonnegative329casescaseswith positive | zero330 . have one := integerLess.one_le_of_positive with positive331have scaled :=332 integerLe.mul_left at integerOne, x, x with nonnegative, one333have unit : x *1= x byring334rw unit at scaled335exact scaled336 . rw← zero337have vanish : integerZero *0=0byring338rw vanish339exact integerLe.reflexive with*340 . have square := integerLe.square_nonneg at x341exact integerLe.transitive with nonpositive, square342343theorem integerLess.of_one_le (x : Integer)344requires one : 1≤ x345shows0 < x346proof347unfold integerLess348have shape : integerZero +1= integerOne byring349rw shape350exact one351352theorem integerLess.positive_iff_one_le (x : Integer)353shows0 < x ↔1≤ x354proof355constructor356 . intro positive357exact integerLess.one_le_of_positive with positive358 . intro one359exact integerLess.of_one_le with one360