@@ -5,7 +5,7 @@ Authors: Jeremy Avigad
5
5
6
6
The integers, with addition, multiplication, and subtraction.
7
7
-/
8
- import data.nat.basic algebra.char_zero algebra.order_functions
8
+ import data.nat.prime algebra.char_zero algebra.order_functions
9
9
open nat
10
10
11
11
namespace int
@@ -100,6 +100,37 @@ begin
100
100
exact this (i + 1 ) }
101
101
end
102
102
103
+ /- nat abs -/
104
+
105
+ attribute [simp] nat_abs nat_abs_of_nat nat_abs_zero nat_abs_one
106
+
107
+ theorem nat_abs_add_le (a b : ℤ) : nat_abs (a + b) ≤ nat_abs a + nat_abs b :=
108
+ begin
109
+ have , {
110
+ refine (λ a b : ℕ, sub_nat_nat_elim a b.succ
111
+ (λ m n i, n = b.succ → nat_abs i ≤ (m + b).succ) _ _ rfl);
112
+ intros i n e,
113
+ { subst e, rw [add_comm _ i, add_assoc],
114
+ exact nat.le_add_right i (b.succ + b).succ },
115
+ { apply succ_le_succ,
116
+ rw [← succ_inj e, ← add_assoc, add_comm],
117
+ apply nat.le_add_right } },
118
+ cases a; cases b with b b; simp [nat_abs, nat.succ_add];
119
+ try {refl}; [skip, rw add_comm a b]; apply this
120
+ end
121
+
122
+ theorem nat_abs_neg_of_nat (n : nat) : nat_abs (neg_of_nat n) = n :=
123
+ by cases n; refl
124
+
125
+ theorem nat_abs_mul (a b : ℤ) : nat_abs (a * b) = (nat_abs a) * (nat_abs b) :=
126
+ by cases a; cases b; simp [(*), int.mul, nat_abs_neg_of_nat]
127
+
128
+ theorem neg_succ_of_nat_eq' (m : ℕ) : -[1 + m] = -m - 1 :=
129
+ by simp [neg_succ_of_nat_eq]
130
+
131
+ lemma nat_abs_ne_zero_of_ne_zero {z : ℤ} (hz : z ≠ 0 ) : z.nat_abs ≠ 0 :=
132
+ λ h, hz $ int.eq_zero_of_nat_abs_eq_zero h
133
+
103
134
/- / -/
104
135
105
136
@[simp] theorem of_nat_div (m n : ℕ) : of_nat (m / n) = (of_nat m) / (of_nat n) := rfl
@@ -416,6 +447,12 @@ theorem coe_nat_dvd {m n : ℕ} : (↑m : ℤ) ∣ ↑n ↔ m ∣ n :=
416
447
subst a, exact ⟨k, int.coe_nat_inj ae⟩ }),
417
448
λ ⟨k, e⟩, dvd.intro k $ by rw [e, int.coe_nat_mul]⟩
418
449
450
+ theorem coe_nat_dvd_left {n : ℕ} {z : ℤ} : (↑n : ℤ) ∣ z ↔ n ∣ z.nat_abs :=
451
+ by rcases nat_abs_eq z with eq | eq; rw eq; simp [coe_nat_dvd]
452
+
453
+ theorem coe_nat_dvd_right {n : ℕ} {z : ℤ} : z ∣ (↑n : ℤ) ↔ z.nat_abs ∣ n :=
454
+ by rcases nat_abs_eq z with eq | eq; rw eq; simp [coe_nat_dvd]
455
+
419
456
theorem dvd_antisymm {a b : ℤ} (H1 : a ≥ 0 ) (H2 : b ≥ 0 ) : a ∣ b → b ∣ a → a = b :=
420
457
begin
421
458
rw [← abs_of_nonneg H1, ← abs_of_nonneg H2, abs_eq_nat_abs, abs_eq_nat_abs],
@@ -530,20 +567,20 @@ eq_one_of_mul_eq_one_right H (by rw [mul_comm, H'])
530
567
lemma of_nat_dvd_of_dvd_nat_abs {a : ℕ} : ∀ {z : ℤ} (haz : a ∣ z.nat_abs), ↑a ∣ z
531
568
| (int.of_nat _) haz := int.coe_nat_dvd.2 haz
532
569
| -[1 +k] haz :=
533
- begin
534
- change ↑a ∣ -(k+1 : ℤ),
535
- apply dvd_neg_of_dvd,
570
+ begin
571
+ change ↑a ∣ -(k+1 : ℤ),
572
+ apply dvd_neg_of_dvd,
536
573
apply int.coe_nat_dvd.2 ,
537
- exact haz
538
- end
574
+ exact haz
575
+ end
539
576
540
- lemma dvd_nat_abs_of_of_nat_dvd {a : ℕ} : ∀ {z : ℤ} (haz : ↑a ∣ z), a ∣ z.nat_abs
577
+ lemma dvd_nat_abs_of_of_nat_dvd {a : ℕ} : ∀ {z : ℤ} (haz : ↑a ∣ z), a ∣ z.nat_abs
541
578
| (int.of_nat _) haz := int.coe_nat_dvd.1 (int.dvd_nat_abs.2 haz)
542
- | -[1 +k] haz :=
579
+ | -[1 +k] haz :=
543
580
have haz' : (↑a:ℤ) ∣ (↑(k+1 ):ℤ), from dvd_of_dvd_neg haz,
544
- int.coe_nat_dvd.1 haz'
581
+ int.coe_nat_dvd.1 haz'
545
582
546
- lemma pow_div_of_le_of_pow_div_int {p m n : ℕ} {k : ℤ} (hmn : m ≤ n) (hdiv : ↑(p ^ n) ∣ k) :
583
+ lemma pow_div_of_le_of_pow_div_int {p m n : ℕ} {k : ℤ} (hmn : m ≤ n) (hdiv : ↑(p ^ n) ∣ k) :
547
584
↑(p ^ m) ∣ k :=
548
585
begin
549
586
induction k,
@@ -556,8 +593,20 @@ begin
556
593
apply pow_div_of_le_of_pow_div hmn,
557
594
apply int.coe_nat_dvd.1 ,
558
595
apply dvd_of_dvd_neg,
559
- exact hdiv }
560
- end
596
+ exact hdiv }
597
+ end
598
+
599
+ lemma succ_dvd_or_succ_dvd_of_succ_sum_dvd_mul {p : ℕ} (p_prime : nat.prime p) {m n : ℤ} {k l : ℕ}
600
+ (hpm : ↑(p ^ k) ∣ m)
601
+ (hpn : ↑(p ^ l) ∣ n) (hpmn : ↑(p ^ (k+l+1 )) ∣ m*n) : ↑(p ^ (k+1 )) ∣ m ∨ ↑(p ^ (l+1 )) ∣ n :=
602
+ have hpm' : p ^ k ∣ m.nat_abs, from int.coe_nat_dvd.1 $ int.dvd_nat_abs.2 hpm,
603
+ have hpn' : p ^ l ∣ n.nat_abs, from int.coe_nat_dvd.1 $ int.dvd_nat_abs.2 hpn,
604
+ have hpmn' : (p ^ (k+l+1 )) ∣ m.nat_abs*n.nat_abs,
605
+ by rw ←int.nat_abs_mul; apply (int.coe_nat_dvd.1 $ int.dvd_nat_abs.2 hpmn),
606
+ let hsd := nat.succ_dvd_or_succ_dvd_of_succ_sum_dvd_mul p_prime hpm' hpn' hpmn' in
607
+ hsd.elim
608
+ (λ hsd1, or.inl begin apply int.dvd_nat_abs.1 , apply int.coe_nat_dvd.2 hsd1 end )
609
+ (λ hsd2, or.inr begin apply int.dvd_nat_abs.1 , apply int.coe_nat_dvd.2 hsd2 end )
561
610
562
611
/- / and ordering -/
563
612
@@ -616,13 +665,13 @@ by rw [← int.mul_div_assoc _ H2]; exact
616
665
617
666
theorem eq_mul_div_of_mul_eq_mul_of_dvd_left {a b c d : ℤ} (hb : b ≠ 0 ) (hd : d ≠ 0 ) (hbc : b ∣ c)
618
667
(h : b * a = c * d) : a = c / b * d :=
619
- begin
668
+ begin
620
669
cases hbc with k hk,
621
670
subst hk,
622
671
rw int.mul_div_cancel_left, rw mul_assoc at h,
623
672
apply _root_.eq_of_mul_eq_mul_left _ h,
624
673
repeat {assumption}
625
- end
674
+ end
626
675
627
676
theorem of_nat_add_neg_succ_of_nat_of_lt {m n : ℕ}
628
677
(h : m < n.succ) : of_nat m + -[1 +n] = -[1 + n - m] :=
645
694
646
695
@[simp] theorem neg_add_neg (m n : ℕ) : -[1 +m] + -[1 +n] = -[1 +nat.succ(m+n)] := rfl
647
696
648
- /- nat abs -/
649
-
650
- attribute [simp] nat_abs nat_abs_of_nat nat_abs_zero nat_abs_one
651
-
652
- theorem nat_abs_add_le (a b : ℤ) : nat_abs (a + b) ≤ nat_abs a + nat_abs b :=
653
- begin
654
- have , {
655
- refine (λ a b : ℕ, sub_nat_nat_elim a b.succ
656
- (λ m n i, n = b.succ → nat_abs i ≤ (m + b).succ) _ _ rfl);
657
- intros i n e,
658
- { subst e, rw [add_comm _ i, add_assoc],
659
- exact nat.le_add_right i (b.succ + b).succ },
660
- { apply succ_le_succ,
661
- rw [← succ_inj e, ← add_assoc, add_comm],
662
- apply nat.le_add_right } },
663
- cases a; cases b with b b; simp [nat_abs, nat.succ_add];
664
- try {refl}; [skip, rw add_comm a b]; apply this
665
- end
666
-
667
- theorem nat_abs_neg_of_nat (n : nat) : nat_abs (neg_of_nat n) = n :=
668
- by cases n; refl
669
-
670
- theorem nat_abs_mul (a b : ℤ) : nat_abs (a * b) = (nat_abs a) * (nat_abs b) :=
671
- by cases a; cases b; simp [(*), int.mul, nat_abs_neg_of_nat]
672
-
673
- theorem neg_succ_of_nat_eq' (m : ℕ) : -[1 + m] = -m - 1 :=
674
- by simp [neg_succ_of_nat_eq]
675
-
676
- lemma nat_abs_ne_zero_of_ne_zero {z : ℤ} (hz : z ≠ 0 ) : z.nat_abs ≠ 0 :=
677
- λ h, hz $ int.eq_zero_of_nat_abs_eq_zero h
678
-
679
697
/- to_nat -/
680
698
681
699
theorem to_nat_eq_max : ∀ (a : ℤ), (to_nat a : ℤ) = max a 0
@@ -1101,3 +1119,57 @@ by simp [abs]
1101
1119
end cast
1102
1120
1103
1121
end int
1122
+
1123
+ /- extended euclidean algorithm -/
1124
+ namespace nat
1125
+
1126
+ def xgcd_aux : ℕ → ℤ → ℤ → ℕ → ℤ → ℤ → ℕ × ℤ × ℤ
1127
+ | 0 s t r' s' t' := (r', s', t')
1128
+ | r@(succ _) s t r' s' t' :=
1129
+ have r' % r < r, from mod_lt _ $ succ_pos _,
1130
+ let q := r' / r in xgcd_aux (r' % r) (s' - q * s) (t' - q * t) r s t
1131
+
1132
+ @[simp] theorem xgcd_zero_left {s t r' s' t'} : xgcd_aux 0 s t r' s' t' = (r', s', t') :=
1133
+ by simp [xgcd_aux]
1134
+
1135
+ @[simp] theorem xgcd_aux_rec {r s t r' s' t'} (h : 0 < r) : xgcd_aux r s t r' s' t' = xgcd_aux (r' % r) (s' - (r' / r) * s) (t' - (r' / r) * t) r s t :=
1136
+ by cases r; [exact absurd h (lt_irrefl _), {simp only [xgcd_aux], refl}]
1137
+
1138
+ /-- Use the extended GCD algorithm to generate the `a` and `b` values
1139
+ satisfying `gcd x y = x * a + y * b`. -/
1140
+ def xgcd (x y : ℕ) : ℤ × ℤ := (xgcd_aux x 1 0 y 0 1 ).2
1141
+
1142
+ /-- The extended GCD `a` value in the equation `gcd x y = x * a + y * b`. -/
1143
+ def gcd_a (x y : ℕ) : ℤ := (xgcd x y).1
1144
+
1145
+ /-- The extended GCD `b` value in the equation `gcd x y = x * a + y * b`. -/
1146
+ def gcd_b (x y : ℕ) : ℤ := (xgcd x y).2
1147
+
1148
+ @[simp] theorem xgcd_aux_fst (x y) : ∀ s t s' t',
1149
+ (xgcd_aux x s t y s' t').1 = gcd x y :=
1150
+ gcd.induction x y (by simp) (λ x y h IH s t s' t', by simp [h, IH]; rw ← gcd_rec)
1151
+
1152
+ theorem xgcd_aux_val (x y) : xgcd_aux x 1 0 y 0 1 = (gcd x y, xgcd x y) :=
1153
+ by rw [xgcd, ← xgcd_aux_fst x y 1 0 0 1 ]; cases xgcd_aux x 1 0 y 0 1 ; refl
1154
+
1155
+ theorem xgcd_val (x y) : xgcd x y = (gcd_a x y, gcd_b x y) :=
1156
+ by unfold gcd_a gcd_b; cases xgcd x y; refl
1157
+
1158
+ section
1159
+ parameters (a b : ℕ)
1160
+
1161
+ private def P : ℕ × ℤ × ℤ → Prop | (r, s, t) := (r : ℤ) = a * s + b * t
1162
+
1163
+ theorem xgcd_aux_P {r r'} : ∀ {s t s' t'}, P (r, s, t) → P (r', s', t') → P (xgcd_aux r s t r' s' t') :=
1164
+ gcd.induction r r' (by simp) $ λ x y h IH s t s' t' p p', begin
1165
+ rw [xgcd_aux_rec h], refine IH _ p, dsimp [P] at *,
1166
+ rw [int.mod_def], generalize : (y / x : ℤ) = k,
1167
+ rw [p, p'], simp [mul_add, mul_comm, mul_left_comm]
1168
+ end
1169
+
1170
+ theorem gcd_eq_gcd_ab : (gcd a b : ℤ) = a * gcd_a a b + b * gcd_b a b :=
1171
+ by have := @xgcd_aux_P a b a b 1 0 0 1 (by simp [P]) (by simp [P]);
1172
+ rwa [xgcd_aux_val, xgcd_val] at this
1173
+ end
1174
+
1175
+ end nat
0 commit comments