1 (* ========================================================================= *)
2 (* Integer congruences. *)
3 (* ========================================================================= *)
7 (* ------------------------------------------------------------------------- *)
8 (* Combined rewrite, for later proofs. *)
9 (* ------------------------------------------------------------------------- *)
12 (`(x == y) (mod n) <=> ?q. x - y = q * n`,
13 REWRITE_TAC[int_congruent; int_divides] THEN MESON_TAC[INT_MUL_SYM]);;
15 (* ------------------------------------------------------------------------- *)
16 (* Trivial consequences. *)
17 (* ------------------------------------------------------------------------- *)
19 let CONG_MOD_0 = prove
20 (`(x == y) (mod (&0)) <=> (x = y)`,
23 let CONG_MOD_1 = prove
24 (`(x == y) (mod (&1))`,
27 (* ------------------------------------------------------------------------- *)
28 (* Congruence is an equivalence relation. *)
29 (* ------------------------------------------------------------------------- *)
32 (`!n x. (x == x) (mod n)`,
36 (`!n x y. (x == y) (mod n) ==> (y == x) (mod n)`,
39 let CONG_TRANS = prove
40 (`!n x y z. (x == y) (mod n) /\ (y == z) (mod n) ==> (x == z) (mod n)`,
43 (* ------------------------------------------------------------------------- *)
44 (* Congruences are indeed congruences. *)
45 (* ------------------------------------------------------------------------- *)
49 (x1 == x2) (mod n) /\ (y1 == y2) (mod n) ==> (x1 + y1 == x2 + y2) (mod n)`,
53 (`!n x1 x2. (x1 == x2) (mod n) ==> (--x1 == --x2) (mod n)`,
58 (x1 == x2) (mod n) /\ (y1 == y2) (mod n) ==> (x1 - y1 == x2 - y2) (mod n)`,
63 (x1 == x2) (mod n) /\ (y1 == y2) (mod n) ==> (x1 * y1 == x2 * y2) (mod n)`,
66 (* ------------------------------------------------------------------------- *)
67 (* Various other trivial properties of congruences. *)
68 (* ------------------------------------------------------------------------- *)
70 let CONG_MOD_NEG = prove
71 (`!x y n. (x == y) (mod (--n)) <=> (x == y) (mod n)`,
74 let CONG_MOD_ABS = prove
75 (`!x y n. (x == y) (mod (abs n)) <=> (x == y) (mod n)`,
76 REPEAT GEN_TAC THEN REWRITE_TAC[INT_ABS] THEN
77 COND_CASES_TAC THEN ASM_REWRITE_TAC[CONG_MOD_NEG]);;
79 let CONG_MULTIPLE = prove
80 (`!m n. (m * n == &0) (mod n)`,
84 (`!n. (n == &0) (mod n)`,
87 let CONG_SELF_ABS = prove
88 (`!n. (abs(n) == &0) (mod n)`,
89 ONCE_REWRITE_TAC[GSYM CONG_MOD_ABS] THEN REWRITE_TAC[CONG_SELF]);;
91 let CONG_MOD_1 = prove
95 (* ------------------------------------------------------------------------- *)
96 (* Can choose a representative, either positive or with minimal magnitude. *)
97 (* ------------------------------------------------------------------------- *)
99 let CONG_REP_POS_POS = prove
100 (`!n x. &0 <= x /\ ~(n = &0)
101 ==> ?y. &0 <= y /\ y < abs(n) /\ (x == y) (mod n)`,
102 REWRITE_TAC[IMP_CONJ] THEN
103 REWRITE_TAC[GSYM INT_FORALL_POS] THEN
104 MAP_EVERY X_GEN_TAC [`n:int`; `k:num`] THEN
105 ONCE_REWRITE_TAC[GSYM CONG_MOD_ABS] THEN
106 MP_TAC(SPEC `n:int` INT_ABS_POS) THEN
107 ONCE_REWRITE_TAC[INT_ARITH `(n = &0) <=> (abs n = &0)`] THEN
108 SPEC_TAC(`abs n`,`n:int`) THEN REWRITE_TAC[GSYM INT_FORALL_POS] THEN
109 X_GEN_TAC `n:num` THEN REWRITE_TAC[INT_OF_NUM_EQ] THEN DISCH_TAC THEN
110 EXISTS_TAC `&(k MOD n)` THEN
111 REWRITE_TAC[CONG; INT_OF_NUM_LE; INT_OF_NUM_LT] THEN
112 ASM_SIMP_TAC[DIVISION; LE_0] THEN EXISTS_TAC `&(k DIV n)` THEN
113 REWRITE_TAC[INT_ARITH `(x - y = z) <=> (x = z + y)`] THEN
114 REWRITE_TAC[INT_OF_NUM_MUL; INT_OF_NUM_ADD; INT_OF_NUM_EQ] THEN
115 ASM_SIMP_TAC[DIVISION]);;
117 let CONG_REP_POS = prove
118 (`!n x. ~(n = &0) ==> ?y. &0 <= y /\ y < abs(n) /\ (x == y) (mod n)`,
119 REPEAT STRIP_TAC THEN
120 DISJ_CASES_TAC(INT_ARITH `&0 <= x \/ &0 <= --x`) THEN
121 ASM_SIMP_TAC[CONG_REP_POS_POS] THEN
122 MP_TAC(SPECL [`n:int`; `--x`] CONG_REP_POS_POS) THEN
123 ASM_REWRITE_TAC[] THEN
124 DISCH_THEN(X_CHOOSE_THEN `y:int` STRIP_ASSUME_TAC) THEN
125 ASM_CASES_TAC `y = &0` THENL
126 [EXISTS_TAC `y:int` THEN
127 FIRST_ASSUM(MP_TAC o MATCH_MP CONG_NEG) THEN
128 ASM_REWRITE_TAC[INT_NEG_0; INT_NEG_NEG];
130 EXISTS_TAC `abs(n) - y` THEN
131 ASM_SIMP_TAC[INT_ARITH `y < abs(n) ==> &0 <= abs(n) - y`;
132 INT_ARITH `&0 <= y /\ ~(y = &0) ==> abs(n) - y < abs(n)`] THEN
133 FIRST_ASSUM(MP_TAC o MATCH_MP CONG_NEG) THEN
134 DISCH_THEN(MP_TAC o MATCH_MP CONG_SYM) THEN
135 DISCH_THEN(MP_TAC o CONJ (SPEC `abs n` CONG_SELF)) THEN
136 REWRITE_TAC[CONG_MOD_ABS] THEN
137 DISCH_THEN(MP_TAC o MATCH_MP CONG_ADD) THEN
138 REWRITE_TAC[INT_NEG_NEG; INT_ADD_LID] THEN
139 MESON_TAC[INT_ARITH `x + --y = x - y`; CONG_SYM]);;
141 let CONG_REP_MIN = prove
143 ==> ?y. --(abs n) <= &2 * y /\ &2 * y < abs n /\ (x == y) (mod n)`,
144 REPEAT STRIP_TAC THEN FIRST_ASSUM(MP_TAC o MATCH_MP CONG_REP_POS) THEN
145 DISCH_THEN(X_CHOOSE_THEN `y:int` STRIP_ASSUME_TAC o SPEC `x:int`) THEN
147 `&0 <= y /\ y < abs n
148 ==> --(abs n) <= &2 * y /\ &2 * y < abs(n) \/
149 --(abs n) <= &2 * (y - abs(n)) /\ &2 * (y - abs(n)) < abs(n)`) THEN
150 ASM_REWRITE_TAC[] THEN STRIP_TAC THENL
151 [ASM_MESON_TAC[CONG_REP_POS; INT_LT_IMP_LE]; ALL_TAC] THEN
152 EXISTS_TAC `y - abs(n)` THEN ASM_REWRITE_TAC[] THEN
153 MP_TAC(SPEC `n:int` CONG_SELF_ABS) THEN
154 DISCH_THEN(MP_TAC o MATCH_MP CONG_SYM) THEN
155 UNDISCH_TAC `(x == y) (mod n)` THEN
156 REWRITE_TAC[IMP_IMP] THEN
157 DISCH_THEN(MP_TAC o MATCH_MP CONG_SUB) THEN
158 REWRITE_TAC[INT_ARITH `x - &0 = x`]);;
160 let CONG_REP_MIN_ABS = prove
161 (`!n x. ~(n = &0) ==> ?y. &2 * abs(y) <= abs(n) /\ (x == y) (mod n)`,
162 REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP CONG_REP_MIN) THEN
163 DISCH_THEN(MP_TAC o SPEC `x:int`) THEN MATCH_MP_TAC MONO_EXISTS THEN
164 SIMP_TAC[] THEN INT_ARITH_TAC);;