Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 32fdb81

Browse files
feat(data/zsqrtd/to_real): Add to_real (#5640)
Also adds `norm_eq_zero`, and replaces some calls to simp with direct lemma applications Co-authored-by: Johan Commelin <johan@commelin.net>
1 parent 1011601 commit 32fdb81

File tree

3 files changed

+99
-7
lines changed

3 files changed

+99
-7
lines changed

src/data/zsqrtd/basic.lean

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ by simp [ext]
145145
@[simp] theorem muld_val (x y : ℤ) : sqrtd * ⟨x, y⟩ = ⟨d * y, x⟩ :=
146146
by simp [ext]
147147

148+
@[simp] theorem dmuld : sqrtd * sqrtd = d :=
149+
by simp [ext]
150+
148151
@[simp] theorem smuld_val (n x y : ℤ) : sqrtd * (n : ℤ√d) * ⟨x, y⟩ = ⟨d * n * y, n * x⟩ :=
149152
by simp [ext]
150153

@@ -157,9 +160,12 @@ by simp [ext, sub_eq_add_neg, mul_comm]
157160
theorem conj_mul {a b : ℤ√d} : conj (a * b) = conj a * conj b :=
158161
by { simp [ext], ring }
159162

160-
protected lemma coe_int_add (m n : ℤ) : (↑(m + n) : ℤ√d) = ↑m + ↑n := by simp [ext]
161-
protected lemma coe_int_sub (m n : ℤ) : (↑(m - n) : ℤ√d) = ↑m - ↑n := by simp [ext, sub_eq_add_neg]
162-
protected lemma coe_int_mul (m n : ℤ) : (↑(m * n) : ℤ√d) = ↑m * ↑n := by simp [ext]
163+
protected lemma coe_int_add (m n : ℤ) : (↑(m + n) : ℤ√d) = ↑m + ↑n :=
164+
(int.cast_ring_hom _).map_add _ _
165+
protected lemma coe_int_sub (m n : ℤ) : (↑(m - n) : ℤ√d) = ↑m - ↑n :=
166+
(int.cast_ring_hom _).map_sub _ _
167+
protected lemma coe_int_mul (m n : ℤ) : (↑(m * n) : ℤ√d) = ↑m * ↑n :=
168+
(int.cast_ring_hom _).map_mul _ _
163169
protected lemma coe_int_inj {m n : ℤ} (h : (↑m : ℤ√d) = ↑n) : m = n :=
164170
by simpa using congr_arg re h
165171

@@ -571,4 +577,64 @@ instance : linear_ordered_semiring ℤ√d := by apply_instance
571577
instance : ordered_semiring ℤ√d := by apply_instance
572578

573579
end
580+
581+
lemma norm_eq_zero {d : ℤ} (h_nonsquare : ∀ n : ℤ, d ≠ n*n) (a : ℤ√d) :
582+
norm a = 0 ↔ a = 0 :=
583+
begin
584+
refine ⟨λ ha, ext.mpr _, λ h, by rw [h, norm_zero]⟩,
585+
delta norm at ha,
586+
rw sub_eq_zero at ha,
587+
by_cases h : 0 ≤ d,
588+
{ obtain ⟨d', rfl⟩ := int.eq_coe_of_zero_le h,
589+
haveI : nonsquare d' := ⟨λ n h, h_nonsquare n $ by exact_mod_cast h⟩,
590+
exact divides_sq_eq_zero_z ha, },
591+
{ push_neg at h,
592+
suffices : a.re * a.re = 0,
593+
{ rw eq_zero_of_mul_self_eq_zero this at ha ⊢,
594+
simpa only [true_and, or_self_right, zero_re, zero_im, eq_self_iff_true,
595+
zero_eq_mul, mul_zero, mul_eq_zero, h.ne, false_or, or_self] using ha },
596+
apply _root_.le_antisymm _ (mul_self_nonneg _),
597+
rw [ha, mul_assoc],
598+
exact mul_nonpos_of_nonpos_of_nonneg h.le (mul_self_nonneg _) }
599+
end
600+
601+
variables {R : Type} [comm_ring R]
602+
603+
@[ext] lemma hom_ext {d : ℤ} (f g : ℤ√d →+* R) (h : f sqrtd = g sqrtd) : f = g :=
604+
begin
605+
ext ⟨x_re, x_im⟩,
606+
simp [decompose, h],
607+
end
608+
609+
/-- The unique `ring_hom` from `ℤ√d` to a ring `R`, constructed by replacing `√d` with the provided
610+
root. Conversely, this associates to every mapping `ℤ√d →+* R` a value of `√d` in `R`. -/
611+
@[simps]
612+
def lift {d : ℤ} : {r : R // r * r = ↑d} ≃ (ℤ√d →+* R) :=
613+
{ to_fun := λ r,
614+
{ to_fun := λ a, a.1 + a.2*(r : R),
615+
map_zero' := by simp,
616+
map_add' := λ a b, by { simp, ring, },
617+
map_one' := by simp,
618+
map_mul' := λ a b, by {
619+
have : (a.re + a.im * r : R) * (b.re + b.im * r) =
620+
a.re * b.re + (a.re * b.im + a.im * b.re) * r + a.im * b.im * (r * r) := by ring,
621+
simp [this, r.prop],
622+
ring, } },
623+
inv_fun := λ f, ⟨f sqrtd, by rw [←f.map_mul, dmuld, ring_hom.map_int_cast]⟩,
624+
left_inv := λ r, by { ext, simp },
625+
right_inv := λ f, by { ext, simp } }
626+
627+
/-- `lift r` is injective if `d` is non-square, and R has characteristic zero (that is, the map from
628+
`ℤ` into `R` is injective). -/
629+
lemma lift_injective [char_zero R] {d : ℤ} (r : {r : R // r * r = ↑d}) (hd : ∀ n : ℤ, d ≠ n*n) :
630+
function.injective (lift r) :=
631+
(lift r).injective_iff.mpr $ λ a ha,
632+
begin
633+
have h_inj : function.injective (coe : ℤ → R) := int.cast_injective,
634+
suffices : lift r a.norm = 0,
635+
{ simp only [coe_int_re, add_zero, lift_apply_apply, coe_int_im, int.cast_zero, zero_mul] at this,
636+
rwa [← int.cast_zero, h_inj.eq_iff, norm_eq_zero hd] at this },
637+
rw [norm_eq_mul_conj, ring_hom.map_mul, ha, zero_mul]
638+
end
639+
574640
end zsqrtd

src/data/zsqrtd/gaussian_int.lean

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,7 @@ local attribute [-instance] complex.field -- Avoid making things noncomputable u
5252

5353
/-- The embedding of the Gaussian integers into the complex numbers, as a ring homomorphism. -/
5454
def to_complex : ℤ[i] →+* ℂ :=
55-
begin
56-
refine_struct { to_fun := λ x : ℤ[i], (x.re + x.im * I : ℂ), .. };
57-
intros; apply complex.ext; dsimp; norm_cast; simp; abel
58-
end
55+
zsqrtd.lift ⟨I, by simp⟩
5956
end
6057

6158
instance : has_coe (ℤ[i]) ℂ := ⟨to_complex⟩

src/data/zsqrtd/to_real.lean

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/-
2+
Copyright (c) 2021 Eric Wieser. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Eric Wieser
5+
-/
6+
import data.real.sqrt
7+
import data.zsqrtd.basic
8+
9+
/-!
10+
# Image of `zsqrtd` in `ℝ`
11+
12+
This file defines `zsqrtd.to_real` and related lemmas.
13+
It is in a separate file to avoid pulling in all of `data.real` into `data.zsqrtd`.
14+
-/
15+
16+
namespace zsqrtd
17+
18+
/-- The image of `zsqrtd` in `ℝ`, using `real.sqrt` which takes the positive root of `d`.
19+
20+
If the negative root is desired, use `to_real h a.conj`. -/
21+
@[simps]
22+
noncomputable def to_real {d : ℤ} (h : 0 ≤ d) : ℤ√d →+* ℝ :=
23+
lift ⟨real.sqrt d, real.mul_self_sqrt (int.cast_nonneg.mpr h)⟩
24+
25+
lemma to_real_injective {d : ℤ} (h0d : 0 ≤ d) (hd : ∀ n : ℤ, d ≠ n*n) :
26+
function.injective (to_real h0d) :=
27+
lift_injective _ hd
28+
29+
end zsqrtd

0 commit comments

Comments
 (0)