number_theory.number_field.unitsMathlib.NumberTheory.NumberField.Units

This file has been ported!

Changes since the initial port

The following section lists changes to this file in mathlib3 and mathlib4 that occured after the initial port. Most recent changes are shown first. Hovering over a commit will show all commits associated with the same mathlib3 commit.

Changes in mathlib3

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(last sync)

Changes in mathlib3port

mathlib3
mathlib3port
Diff
@@ -36,7 +36,7 @@ section Rat
 theorem Rat.RingOfIntegers.isUnit_iff {x : 𝓞 ℚ} : IsUnit x ↔ (x : ℚ) = 1 ∨ (x : ℚ) = -1 := by
   simp_rw [(isUnit_map_iff (Rat.ringOfIntegersEquiv : 𝓞 ℚ →+* ℤ) x).symm, Int.isUnit_iff,
     RingEquiv.coe_toRingHom, RingEquiv.map_eq_one_iff, RingEquiv.map_eq_neg_one_iff, ←
-    subtype.coe_injective.eq_iff, AddSubgroupClass.coe_neg, algebraMap.coe_one]
+    subtype.coe_injective.eq_iff, NegMemClass.coe_neg, algebraMap.coe_one]
 #align rat.ring_of_integers.is_unit_iff Rat.RingOfIntegers.isUnit_iff
 -/
 
Diff
@@ -50,13 +50,13 @@ attribute [local instance] NumberField.inst_ringOfIntegersAlgebra
 
 variable {K}
 
-#print isUnit_iff_norm /-
-theorem isUnit_iff_norm [NumberField K] (x : 𝓞 K) :
+#print NumberField.isUnit_iff_norm /-
+theorem NumberField.isUnit_iff_norm [NumberField K] (x : 𝓞 K) :
     IsUnit x ↔ |(RingOfIntegers.norm ℚ x : ℚ)| = 1 :=
   by
   convert (RingOfIntegers.isUnit_norm ℚ).symm
   rw [← abs_one, abs_eq_abs, ← Rat.RingOfIntegers.isUnit_iff]
-#align is_unit_iff_norm isUnit_iff_norm
+#align is_unit_iff_norm NumberField.isUnit_iff_norm
 -/
 
 end IsUnit
Diff
@@ -3,7 +3,7 @@ Copyright (c) 2023 Xavier Roblot. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Xavier Roblot
 -/
-import Mathbin.NumberTheory.NumberField.Norm
+import NumberTheory.NumberField.Norm
 
 #align_import number_theory.number_field.units from "leanprover-community/mathlib"@"5d0c76894ada7940957143163d7b921345474cbc"
 
Diff
@@ -46,7 +46,7 @@ variable (K : Type _) [Field K]
 
 section IsUnit
 
-attribute [local instance] NumberField.ringOfIntegersAlgebra
+attribute [local instance] NumberField.inst_ringOfIntegersAlgebra
 
 variable {K}
 
Diff
@@ -2,14 +2,11 @@
 Copyright (c) 2023 Xavier Roblot. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Xavier Roblot
-
-! This file was ported from Lean 3 source module number_theory.number_field.units
-! leanprover-community/mathlib commit 5d0c76894ada7940957143163d7b921345474cbc
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
 -/
 import Mathbin.NumberTheory.NumberField.Norm
 
+#align_import number_theory.number_field.units from "leanprover-community/mathlib"@"5d0c76894ada7940957143163d7b921345474cbc"
+
 /-!
 # Units of a number field
 
Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Xavier Roblot
 
 ! This file was ported from Lean 3 source module number_theory.number_field.units
-! leanprover-community/mathlib commit 00f91228655eecdcd3ac97a7fd8dbcb139fe990a
+! leanprover-community/mathlib commit 5d0c76894ada7940957143163d7b921345474cbc
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -12,6 +12,9 @@ import Mathbin.NumberTheory.NumberField.Norm
 
 /-!
 # Units of a number field
+
+> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
+> Any changes to this file require a corresponding PR to mathlib4.
 We prove results about the group `(𝓞 K)ˣ` of units of the ring of integers `𝓞 K` of a number
 field `K`.
 
Diff
@@ -32,11 +32,13 @@ open NumberField Units
 
 section Rat
 
+#print Rat.RingOfIntegers.isUnit_iff /-
 theorem Rat.RingOfIntegers.isUnit_iff {x : 𝓞 ℚ} : IsUnit x ↔ (x : ℚ) = 1 ∨ (x : ℚ) = -1 := by
   simp_rw [(isUnit_map_iff (Rat.ringOfIntegersEquiv : 𝓞 ℚ →+* ℤ) x).symm, Int.isUnit_iff,
     RingEquiv.coe_toRingHom, RingEquiv.map_eq_one_iff, RingEquiv.map_eq_neg_one_iff, ←
     subtype.coe_injective.eq_iff, AddSubgroupClass.coe_neg, algebraMap.coe_one]
 #align rat.ring_of_integers.is_unit_iff Rat.RingOfIntegers.isUnit_iff
+-/
 
 end Rat
 
@@ -48,12 +50,14 @@ attribute [local instance] NumberField.ringOfIntegersAlgebra
 
 variable {K}
 
+#print isUnit_iff_norm /-
 theorem isUnit_iff_norm [NumberField K] (x : 𝓞 K) :
     IsUnit x ↔ |(RingOfIntegers.norm ℚ x : ℚ)| = 1 :=
   by
   convert (RingOfIntegers.isUnit_norm ℚ).symm
   rw [← abs_one, abs_eq_abs, ← Rat.RingOfIntegers.isUnit_iff]
 #align is_unit_iff_norm isUnit_iff_norm
+-/
 
 end IsUnit
 
Diff
@@ -51,7 +51,7 @@ variable {K}
 theorem isUnit_iff_norm [NumberField K] (x : 𝓞 K) :
     IsUnit x ↔ |(RingOfIntegers.norm ℚ x : ℚ)| = 1 :=
   by
-  convert(RingOfIntegers.isUnit_norm ℚ).symm
+  convert (RingOfIntegers.isUnit_norm ℚ).symm
   rw [← abs_one, abs_eq_abs, ← Rat.RingOfIntegers.isUnit_iff]
 #align is_unit_iff_norm isUnit_iff_norm
 
Diff
@@ -24,7 +24,7 @@ number field, units
  -/
 
 
-open NumberField
+open scoped NumberField
 
 noncomputable section
 

Changes in mathlib4

mathlib3
mathlib4
chore(NumberField/Units): split into two files (#12509)

This PR splits the file NumberField/Units.lean into two files placed into a new folder NumberField/Units:

  • Units/Basic.lean contains the basic definitions and results about the unit group and its torsion subgroup,
  • Units/DirichletTheorem.lean contains the proof of Dirichlet unit theorem and results about the structure of the unit group and its rank.
Diff
@@ -5,15 +5,16 @@ Authors: Xavier Roblot
 -/
 import Mathlib.LinearAlgebra.Matrix.Gershgorin
 import Mathlib.NumberTheory.NumberField.CanonicalEmbedding.ConvexBody
-import Mathlib.NumberTheory.NumberField.Norm
+import Mathlib.NumberTheory.NumberField.Units.Basic
 import Mathlib.RingTheory.RootsOfUnity.Basic
 
 #align_import number_theory.number_field.units from "leanprover-community/mathlib"@"00f91228655eecdcd3ac97a7fd8dbcb139fe990a"
 
 /-!
-# Units of a number field
-We prove results about the group `(𝓞 K)ˣ` of units of the ring of integers `𝓞 K` of a number
-field `K`.
+# Dirichlet theorem on the group of units of a number field
+This file is devoted to the proof of Dirichlet unit theorem that states that the group of
+units `(𝓞 K)ˣ` of units of the ring of integers `𝓞 K` of a number field `K` modulo its torsion
+subgroup is a free `ℤ`-module of rank `card (InfinitePlace K) - 1`.
 
 ## Main definitions
 
@@ -26,147 +27,29 @@ as an additive `ℤ`-module.
 
 ## Main results
 
-* `NumberField.isUnit_iff_norm`: an algebraic integer `x : 𝓞 K` is a unit if and only if
-`|norm ℚ x| = 1`.
-
-* `NumberField.Units.mem_torsion`: a unit `x : (𝓞 K)ˣ` is torsion iff `w x = 1` for all infinite
-places `w` of `K`.
+* `NumberField.Units.rank_modTorsion`: the `ℤ`-rank of `(𝓞 K)ˣ ⧸ (torsion K)` is equal to
+`card (InfinitePlace K) - 1`.
 
 * `NumberField.Units.exist_unique_eq_mul_prod`: **Dirichlet Unit Theorem**. Any unit of `𝓞 K`
 can be written uniquely as the product of a root of unity and powers of the units of the
 fundamental system `fundSystem`.
 
 ## Tags
-number field, units
+number field, units, Dirichlet unit theorem
  -/
 
 open scoped NumberField
 
 noncomputable section
 
-open NumberField Units BigOperators
-
-section Rat
-
-theorem Rat.RingOfIntegers.isUnit_iff {x : 𝓞 ℚ} : IsUnit x ↔ (x : ℚ) = 1 ∨ (x : ℚ) = -1 := by
-  simp_rw [(isUnit_map_iff (Rat.ringOfIntegersEquiv : 𝓞 ℚ →+* ℤ) x).symm, Int.isUnit_iff,
-    RingEquiv.coe_toRingHom, RingEquiv.map_eq_one_iff, RingEquiv.map_eq_neg_one_iff, ←
-    Subtype.coe_injective.eq_iff]; rfl
-#align rat.ring_of_integers.is_unit_iff Rat.RingOfIntegers.isUnit_iff
-
-end Rat
-
-variable (K : Type*) [Field K]
-
-section IsUnit
-
-variable {K}
-
-theorem NumberField.isUnit_iff_norm [NumberField K] {x : 𝓞 K} :
-    IsUnit x ↔ |(RingOfIntegers.norm ℚ x : ℚ)| = 1 := by
-  convert (RingOfIntegers.isUnit_norm ℚ (F := K)).symm
-  rw [← abs_one, abs_eq_abs, ← Rat.RingOfIntegers.isUnit_iff]
-#align is_unit_iff_norm NumberField.isUnit_iff_norm
-
-end IsUnit
-
-namespace NumberField.Units
-
-section coe
-
-theorem coe_injective : Function.Injective ((↑) : (𝓞 K)ˣ → K) :=
-  fun _ _ h => by rwa [SetLike.coe_eq_coe, Units.eq_iff] at h
-
-variable {K}
-
-theorem coe_mul (x y : (𝓞 K)ˣ) : ((x * y : (𝓞 K)ˣ) : K) = (x : K) * (y : K) := rfl
-
-theorem coe_pow (x : (𝓞 K)ˣ) (n : ℕ) : (↑(x ^ n) : K) = (x : K) ^ n := by
-  rw [← SubmonoidClass.coe_pow, ← val_pow_eq_pow_val]
+open NumberField NumberField.InfinitePlace NumberField.Units BigOperators
 
-theorem coe_zpow (x : (𝓞 K)ˣ) (n : ℤ) : (↑(x ^ n) : K) = (x : K) ^ n := by
-  change ((Units.coeHom K).comp (map (algebraMap (𝓞 K) K))) (x ^ n) = _
-  exact map_zpow _ x n
+variable (K : Type*) [Field K] [NumberField K]
 
-theorem coe_one : ((1 : (𝓞 K)ˣ) : K) = (1 : K) := rfl
-
-theorem coe_neg_one : ((-1 : (𝓞 K)ˣ) : K) = (-1 : K) := rfl
-
-theorem coe_ne_zero (x : (𝓞 K)ˣ) : (x : K) ≠ 0 :=
-  Subtype.coe_injective.ne_iff.mpr (_root_.Units.ne_zero x)
-
-end coe
-
-open NumberField.InfinitePlace
-
-section torsion
-
-/-- The torsion subgroup of the group of units. -/
-def torsion : Subgroup (𝓞 K)ˣ := CommGroup.torsion (𝓞 K)ˣ
-
-theorem mem_torsion {x : (𝓞 K)ˣ} [NumberField K] :
-    x ∈ torsion K ↔ ∀ w : InfinitePlace K, w x = 1 := by
-  rw [eq_iff_eq (x : K) 1, torsion, CommGroup.mem_torsion]
-  refine ⟨fun hx φ ↦ (((φ.comp $ algebraMap (𝓞 K) K).toMonoidHom.comp $
-    Units.coeHom _).isOfFinOrder hx).norm_eq_one, fun h ↦ isOfFinOrder_iff_pow_eq_one.2 ?_⟩
-  obtain ⟨n, hn, hx⟩ := Embeddings.pow_eq_one_of_norm_eq_one K ℂ x.val.prop h
-  exact ⟨n, hn, by ext; rw [coe_pow, hx, coe_one]⟩
-
-/-- Shortcut instance because Lean tends to time out before finding the general instance. -/
-instance : Nonempty (torsion K) := One.instNonempty
-
-/-- The torsion subgroup is finite. -/
-instance [NumberField K] : Fintype (torsion K) := by
-  refine @Fintype.ofFinite _ (Set.finite_coe_iff.mpr ?_)
-  refine Set.Finite.of_finite_image ?_ ((coe_injective K).injOn _)
-  refine (Embeddings.finite_of_norm_le K ℂ 1).subset
-    (fun a ⟨u, ⟨h_tors, h_ua⟩⟩ => ⟨?_, fun φ => ?_⟩)
-  · rw [← h_ua]
-    exact u.val.prop
-  · rw [← h_ua]
-    exact le_of_eq ((eq_iff_eq _ 1).mp ((mem_torsion K).mp h_tors) φ)
-
--- a shortcut instance to stop the next instance from timing out
-instance [NumberField K] : Finite (torsion K) := inferInstance
-
-/-- The torsion subgroup is cylic. -/
-instance [NumberField K] : IsCyclic (torsion K) := subgroup_units_cyclic _
-
-/-- The order of the torsion subgroup as a positive integer. -/
-def torsionOrder [NumberField K] : ℕ+ := ⟨Fintype.card (torsion K), Fintype.card_pos⟩
-
-/-- If `k` does not divide `torsionOrder` then there are no nontrivial roots of unity of
-  order dividing `k`. -/
-theorem rootsOfUnity_eq_one [NumberField K] {k : ℕ+} (hc : Nat.Coprime k (torsionOrder K))
-    {ζ : (𝓞 K)ˣ} : ζ ∈ rootsOfUnity k (𝓞 K) ↔ ζ = 1 := by
-  rw [mem_rootsOfUnity]
-  refine ⟨fun h => ?_, fun h => by rw [h, one_pow]⟩
-  refine orderOf_eq_one_iff.mp (Nat.eq_one_of_dvd_coprimes hc ?_ ?_)
-  · exact orderOf_dvd_of_pow_eq_one h
-  · have hζ : ζ ∈ torsion K := by
-      rw [torsion, CommGroup.mem_torsion, isOfFinOrder_iff_pow_eq_one]
-      exact ⟨k, k.prop, h⟩
-    rw [orderOf_submonoid (⟨ζ, hζ⟩ : torsion K)]
-    exact orderOf_dvd_card
-
-/-- The group of roots of unity of order dividing `torsionOrder` is equal to the torsion
-group. -/
-theorem rootsOfUnity_eq_torsion [NumberField K] :
-    rootsOfUnity (torsionOrder K) (𝓞 K) = torsion K := by
-  ext ζ
-  rw [torsion, mem_rootsOfUnity]
-  refine ⟨fun h => ?_, fun h => ?_⟩
-  · rw [CommGroup.mem_torsion, isOfFinOrder_iff_pow_eq_one]
-    exact ⟨↑(torsionOrder K), (torsionOrder K).prop, h⟩
-  · exact Subtype.ext_iff.mp (@pow_card_eq_one (torsion K) _ _ ⟨ζ, h⟩)
-
-end torsion
-
-namespace dirichletUnitTheorem
+namespace NumberField.Units.dirichletUnitTheorem
 
 /-!
 ### Dirichlet Unit Theorem
-This section is devoted to the proof of Dirichlet's unit theorem.
 
 We define a group morphism from `(𝓞 K)ˣ` to `{w : InfinitePlace K // w ≠ w₀} → ℝ` where `w₀` is a
 distinguished (arbitrary) infinite place, prove that its kernel is the torsion subgroup (see
@@ -181,7 +64,6 @@ see the section `span_top` below for more details.
 open scoped Classical
 open Finset
 
-variable [NumberField K]
 variable {K}
 
 /-- The distinguished infinite place. -/
@@ -404,7 +286,7 @@ theorem exists_unit (w₁ : InfinitePlace K) :
       (Ideal.span ({ (seq K w₁ hB n : 𝓞 K) }) = Ideal.span ({ (seq K w₁ hB m : 𝓞 K) }))
   · have hu := Ideal.span_singleton_eq_span_singleton.mp h
     refine ⟨hu.choose, fun w hw => Real.log_neg ?_ ?_⟩
-    · simp only [pos_iff, ne_eq, ZeroMemClass.coe_eq_zero, ne_zero, not_false_eq_true]
+    · simp only [pos_iff, ne_eq, ZeroMemClass.coe_eq_zero, Units.ne_zero, not_false_eq_true]
     · calc
         _ = w ((seq K w₁ hB m : K) * (seq K w₁ hB n : K)⁻¹) := by
           rw [← congr_arg ((↑) : (𝓞 K) → K) hu.choose_spec, mul_comm, Submonoid.coe_mul,
chore(NumberField/Units): split into two files (#12509)

This PR splits the file NumberField/Units.lean into two files placed into a new folder NumberField/Units:

  • Units/Basic.lean contains the basic definitions and results about the unit group and its torsion subgroup,
  • Units/DirichletTheorem.lean contains the proof of Dirichlet unit theorem and results about the structure of the unit group and its rank.
chore: adapt to multiple goal linter 1 (#12338)

A PR accompanying #12339.

Zulip discussion

Diff
@@ -442,12 +442,12 @@ theorem unitLattice_span_eq_top :
   simp_rw [Real.norm_eq_abs, B, Basis.coePiBasisFun.toMatrix_eq_transpose, Matrix.transpose_apply]
   rw [← sub_pos, sum_congr rfl (fun x hx => abs_of_neg ?_), sum_neg_distrib, sub_neg_eq_add,
     sum_erase_eq_sub (mem_univ _), ← add_comm_sub]
-  refine add_pos_of_nonneg_of_pos ?_ ?_
-  · rw [sub_nonneg]
-    exact le_abs_self _
-  · rw [sum_logEmbedding_component (exists_unit K w).choose]
-    refine mul_pos_of_neg_of_neg ?_ ((exists_unit K w).choose_spec _ w.prop.symm)
-    rw [mult]; split_ifs <;> norm_num
+  · refine add_pos_of_nonneg_of_pos ?_ ?_
+    · rw [sub_nonneg]
+      exact le_abs_self _
+    · rw [sum_logEmbedding_component (exists_unit K w).choose]
+      refine mul_pos_of_neg_of_neg ?_ ((exists_unit K w).choose_spec _ w.prop.symm)
+      rw [mult]; split_ifs <;> norm_num
   · refine mul_neg_of_pos_of_neg ?_ ((exists_unit K w).choose_spec x ?_)
     · rw [mult]; split_ifs <;> norm_num
     · exact Subtype.ext_iff_val.not.mp (ne_of_mem_erase hx)
fix: strengthen Dirichlet Unit Theorem (#12240)

The theorem NumberField.Units.exist_unique_eq_mul_prod was using nested ∃!'s rather than a single ∃!.

Diff
@@ -567,8 +567,8 @@ theorem fun_eq_repr {x ζ : (𝓞 K)ˣ} {f : Fin (rank K) → ℤ} (hζ : ζ ∈
 
 /-- **Dirichlet Unit Theorem**. Any unit `x` of `𝓞 K` can be written uniquely as the product of
 a root of unity and powers of the units of the fundamental system `fundSystem`. -/
-theorem exist_unique_eq_mul_prod (x : (𝓞 K)ˣ) : ∃! (ζ : torsion K), ∃! (e : Fin (rank K) → ℤ),
-    x = ζ * ∏ i, (fundSystem K i) ^ (e i) := by
+theorem exist_unique_eq_mul_prod (x : (𝓞 K)ˣ) : ∃! ζe : torsion K × (Fin (rank K) → ℤ),
+    x = ζe.1 * ∏ i, (fundSystem K i) ^ (ζe.2 i) := by
   let ζ := x * (∏ i, (fundSystem K i) ^ ((basisModTorsion K).repr (Additive.ofMul ↑x) i))⁻¹
   have h_tors : ζ ∈ torsion K := by
     rw [← QuotientGroup.eq_one_iff, QuotientGroup.mk_mul, QuotientGroup.mk_inv, ← ofMul_eq_zero,
@@ -576,13 +576,10 @@ theorem exist_unique_eq_mul_prod (x : (𝓞 K)ˣ) : ∃! (ζ : torsion K), ∃!
     simp_rw [QuotientGroup.mk_zpow, ofMul_zpow, fundSystem, QuotientGroup.out_eq']
     rw [add_eq_zero_iff_eq_neg, neg_neg]
     exact ((basisModTorsion K).sum_repr (Additive.ofMul ↑x)).symm
-  refine ⟨⟨ζ, h_tors⟩, ?_, ?_⟩
-  · refine ⟨((basisModTorsion K).repr (Additive.ofMul ↑x) : Fin (rank K) → ℤ), ?_, ?_⟩
-    · simp only [ζ, _root_.inv_mul_cancel_right]
-    · exact fun _ hf => fun_eq_repr K h_tors hf
-  · rintro η ⟨_, hf, _⟩
-    simp_rw [fun_eq_repr K η.prop hf] at hf
-    ext1; dsimp only [ζ]
+  refine ⟨⟨⟨ζ, h_tors⟩, ((basisModTorsion K).repr (Additive.ofMul ↑x) : Fin (rank K) → ℤ)⟩, ?_, ?_⟩
+  · simp only [ζ, _root_.inv_mul_cancel_right]
+  · rintro ⟨⟨ζ', h_tors'⟩, η⟩ hf
+    simp only [ζ, ← fun_eq_repr K h_tors' hf, Prod.mk.injEq, Subtype.mk.injEq, and_true]
     nth_rewrite 1 [hf]
     rw [_root_.mul_inv_cancel_right]
 
feat: make ExistsUnique notation throw an error when used with more than one binder (#12218)

Zulip discussion

Diff
@@ -567,7 +567,7 @@ theorem fun_eq_repr {x ζ : (𝓞 K)ˣ} {f : Fin (rank K) → ℤ} (hζ : ζ ∈
 
 /-- **Dirichlet Unit Theorem**. Any unit `x` of `𝓞 K` can be written uniquely as the product of
 a root of unity and powers of the units of the fundamental system `fundSystem`. -/
-theorem exist_unique_eq_mul_prod (x : (𝓞 K)ˣ) : ∃! (ζ : torsion K) (e : Fin (rank K) → ℤ),
+theorem exist_unique_eq_mul_prod (x : (𝓞 K)ˣ) : ∃! (ζ : torsion K), ∃! (e : Fin (rank K) → ℤ),
     x = ζ * ∏ i, (fundSystem K i) ^ (e i) := by
   let ζ := x * (∏ i, (fundSystem K i) ^ ((basisModTorsion K).repr (Additive.ofMul ↑x) i))⁻¹
   have h_tors : ζ ∈ torsion K := by
chore: superfluous parentheses (#12116)

Co-authored-by: Moritz Firsching <firsching@google.com>

Diff
@@ -425,7 +425,7 @@ theorem exists_unit (w₁ : InfinitePlace K) :
 
 theorem unitLattice_span_eq_top :
     Submodule.span ℝ (unitLattice K : Set ({w : InfinitePlace K // w ≠ w₀} → ℝ)) = ⊤ := by
-  refine le_antisymm (le_top) ?_
+  refine le_antisymm le_top ?_
   -- The standard basis
   let B := Pi.basisFun ℝ {w : InfinitePlace K // w ≠ w₀}
   -- The image by log_embedding of the family of units constructed above
chore: Slightly modify the split of CanonicalEmbedding (#11917)

Create a new directory for the split of CanonicalEmbedding since more material is coming.

Also add some docstrings.

Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Xavier Roblot
 -/
 import Mathlib.LinearAlgebra.Matrix.Gershgorin
-import Mathlib.NumberTheory.NumberField.ConvexBody
+import Mathlib.NumberTheory.NumberField.CanonicalEmbedding.ConvexBody
 import Mathlib.NumberTheory.NumberField.Norm
 import Mathlib.RingTheory.RootsOfUnity.Basic
 
chore: split NumberTheory.NumberField.CanonicalEmbedding (#11873)

#8361 indicates that this is the most compute-intensive file on the longest pole for compiling Mathlib. It's bottlenecked dependency is Mathlib.MeasureTheory.Measure.Lebesgue.VolumeOfBalls, and this import isn't used until the second half of the file, in the sections regarding convex bodies. I am therefore splitting the file at that point, from the context of the file it seems to me that this is a sensible split anyway.

Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Xavier Roblot
 -/
 import Mathlib.LinearAlgebra.Matrix.Gershgorin
-import Mathlib.NumberTheory.NumberField.CanonicalEmbedding
+import Mathlib.NumberTheory.NumberField.ConvexBody
 import Mathlib.NumberTheory.NumberField.Norm
 import Mathlib.RingTheory.RootsOfUnity.Basic
 
chore: Delete Init.Data.Subtype.Basic (#11887)

The few useful lemmas can go to Data.Subtype.Basic and the other ones can be deleted.

Diff
@@ -327,7 +327,7 @@ theorem seq_next {x : 𝓞 K} (hx : x ≠ 0) :
     obtain ⟨g, h_geqf, h_gprod⟩ := adjust_f K B this
     obtain ⟨y, hy, h_ynz, h_yle⟩ := exists_ne_zero_mem_ringOfIntegers_lt (f := g)
       (by rw [convexBodyLT_volume]; convert hB; exact congr_arg ((↑): NNReal → ENNReal) h_gprod)
-    refine ⟨⟨y, hy⟩, Subtype.ne_of_val_ne h_ynz, fun w hw => (h_geqf w hw ▸ h_yle w).trans ?_, ?_⟩
+    refine ⟨⟨y, hy⟩, Subtype.coe_ne_coe.1 h_ynz, fun w hw => (h_geqf w hw ▸ h_yle w).trans ?_, ?_⟩
     · rw [← Rat.cast_le (K := ℝ), Rat.cast_natCast]
       calc
         _ = ∏ w : InfinitePlace K, w y ^ mult w := (prod_eq_abs_norm (y : K)).symm
@@ -360,7 +360,7 @@ theorem seq_ne_zero (n : ℕ) : (seq K w₁ hB n : K) ≠ 0 := by
 
 /-- The terms of the sequence have nonzero norm. -/
 theorem seq_norm_ne_zero (n : ℕ) : Algebra.norm ℤ (seq K w₁ hB n : 𝓞 K) ≠ 0 :=
-  Algebra.norm_ne_zero_iff.mpr (Subtype.ne_of_val_ne (seq_ne_zero K w₁ hB n))
+  Algebra.norm_ne_zero_iff.mpr (Subtype.coe_ne_coe.1 (seq_ne_zero K w₁ hB n))
 
 /-- The sequence is strictly decreasing at infinite places distinct from `w₁`. -/
 theorem seq_decreasing {n m : ℕ} (h : n < m) (w : InfinitePlace K) (hw : w ≠ w₁) :
chore: Rename cat_coe_nat/cast_coe_int to cast_natCast/cast_intCast (#11552)

Reduce the diff of #11499

Diff
@@ -328,7 +328,7 @@ theorem seq_next {x : 𝓞 K} (hx : x ≠ 0) :
     obtain ⟨y, hy, h_ynz, h_yle⟩ := exists_ne_zero_mem_ringOfIntegers_lt (f := g)
       (by rw [convexBodyLT_volume]; convert hB; exact congr_arg ((↑): NNReal → ENNReal) h_gprod)
     refine ⟨⟨y, hy⟩, Subtype.ne_of_val_ne h_ynz, fun w hw => (h_geqf w hw ▸ h_yle w).trans ?_, ?_⟩
-    · rw [← Rat.cast_le (K := ℝ), Rat.cast_coe_nat]
+    · rw [← Rat.cast_le (K := ℝ), Rat.cast_natCast]
       calc
         _ = ∏ w : InfinitePlace K, w y ^ mult w := (prod_eq_abs_norm (y : K)).symm
         _ ≤ ∏ w : InfinitePlace K, (g w : ℝ) ^ mult w := by
chore(*): remove empty lines between variable statements (#11418)

Empty lines were removed by executing the following Python script twice

import os
import re


# Loop through each file in the repository
for dir_path, dirs, files in os.walk('.'):
  for filename in files:
    if filename.endswith('.lean'):
      file_path = os.path.join(dir_path, filename)

      # Open the file and read its contents
      with open(file_path, 'r') as file:
        content = file.read()

      # Use a regular expression to replace sequences of "variable" lines separated by empty lines
      # with sequences without empty lines
      modified_content = re.sub(r'(variable.*\n)\n(variable(?! .* in))', r'\1\2', content)

      # Write the modified content back to the file
      with open(file_path, 'w') as file:
        file.write(modified_content)
Diff
@@ -182,7 +182,6 @@ open scoped Classical
 open Finset
 
 variable [NumberField K]
-
 variable {K}
 
 /-- The distinguished infinite place. -/
chore: Define the class IsZlattice (#11356)

See the Zulip thread

Diff
@@ -478,22 +478,18 @@ instance instDiscrete_unitLattice : DiscreteTopology (unitLattice K) := by
     rintro ⟨x, hx, rfl⟩
     exact ⟨Subtype.mem x, hx⟩
 
+instance instZlattice_unitLattice : IsZlattice ℝ (unitLattice K) where
+  span_top := unitLattice_span_eq_top K
+
 protected theorem finrank_eq_rank :
     finrank ℝ ({w : InfinitePlace K // w ≠ w₀} → ℝ) = Units.rank K := by
   simp only [finrank_fintype_fun_eq_card, Fintype.card_subtype_compl,
     Fintype.card_ofSubsingleton, rank]
 
-instance instModuleFree_unitLattice : Module.Free ℤ (unitLattice K) :=
-  Zlattice.module_free ℝ (unitLattice_span_eq_top K)
-
-instance instModuleFinite_unitLattice : Module.Finite ℤ (unitLattice K) :=
-  Zlattice.module_finite ℝ (unitLattice_span_eq_top K)
-
 @[simp]
 theorem unitLattice_rank :
     finrank ℤ (unitLattice K) = Units.rank K := by
-  rw [← Units.finrank_eq_rank]
-  exact Zlattice.rank ℝ (unitLattice_span_eq_top K)
+  rw [← Units.finrank_eq_rank, Zlattice.rank ℝ]
 
 /-- The linear equivalence between `unitLattice` and `(𝓞 K)ˣ ⧸ (torsion K)` as an additive
 `ℤ`-module. -/
@@ -514,7 +510,7 @@ def unitLatticeEquiv : (unitLattice K) ≃ₗ[ℤ] Additive ((𝓞 K)ˣ ⧸ (tor
     rfl
 
 instance : Module.Free ℤ (Additive ((𝓞 K)ˣ ⧸ (torsion K))) :=
-  (instModuleFree_unitLattice K).of_equiv' (unitLatticeEquiv K)
+  Module.Free.of_equiv (unitLatticeEquiv K)
 
 instance : Module.Finite ℤ (Additive ((𝓞 K)ˣ ⧸ (torsion K))) :=
   Module.Finite.equiv (unitLatticeEquiv K)
chore: scope open Classical (#11199)

We remove all but one open Classicals, instead preferring to use open scoped Classical. The only real side-effect this led to is moving a couple declarations to use Exists.choose instead of Classical.choose.

The first few commits are explicitly labelled regex replaces for ease of review.

Diff
@@ -178,7 +178,8 @@ spans the full space over `ℝ` (see `unitLattice_span_eq_top`); this is the mai
 see the section `span_top` below for more details.
 -/
 
-open Classical Finset
+open scoped Classical
+open Finset
 
 variable [NumberField K]
 
@@ -460,7 +461,8 @@ section statements
 
 variable [NumberField K]
 
-open dirichletUnitTheorem FiniteDimensional Classical
+open scoped Classical
+open dirichletUnitTheorem FiniteDimensional
 
 /-- The unit rank of the number field `K`, it is equal to `card (InfinitePlace K) - 1`. -/
 def rank : ℕ := Fintype.card (InfinitePlace K) - 1
chore: move Mathlib to v4.7.0-rc1 (#11162)

This is a very large PR, but it has been reviewed piecemeal already in PRs to the bump/v4.7.0 branch as we update to intermediate nightlies.

Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Kyle Miller <kmill31415@gmail.com> Co-authored-by: damiano <adomani@gmail.com>

Diff
@@ -439,7 +439,7 @@ theorem unitLattice_span_eq_top :
   rw [Basis.det_apply]
   -- We use a specific lemma to prove that this determinant is nonzero
   refine det_ne_zero_of_sum_col_lt_diag (fun w => ?_)
-  simp_rw [Real.norm_eq_abs, Basis.coePiBasisFun.toMatrix_eq_transpose, Matrix.transpose_apply]
+  simp_rw [Real.norm_eq_abs, B, Basis.coePiBasisFun.toMatrix_eq_transpose, Matrix.transpose_apply]
   rw [← sub_pos, sum_congr rfl (fun x hx => abs_of_neg ?_), sum_neg_distrib, sub_neg_eq_add,
     sum_erase_eq_sub (mem_univ _), ← add_comm_sub]
   refine add_pos_of_nonneg_of_pos ?_ ?_
@@ -581,11 +581,11 @@ theorem exist_unique_eq_mul_prod (x : (𝓞 K)ˣ) : ∃! (ζ : torsion K) (e : F
     exact ((basisModTorsion K).sum_repr (Additive.ofMul ↑x)).symm
   refine ⟨⟨ζ, h_tors⟩, ?_, ?_⟩
   · refine ⟨((basisModTorsion K).repr (Additive.ofMul ↑x) : Fin (rank K) → ℤ), ?_, ?_⟩
-    · simp only [_root_.inv_mul_cancel_right]
+    · simp only [ζ, _root_.inv_mul_cancel_right]
     · exact fun _ hf => fun_eq_repr K h_tors hf
   · rintro η ⟨_, hf, _⟩
     simp_rw [fun_eq_repr K η.prop hf] at hf
-    ext1; dsimp only
+    ext1; dsimp only [ζ]
     nth_rewrite 1 [hf]
     rw [_root_.mul_inv_cancel_right]
 
perf: Use spread notation in ring transfer definitions (#10131)

Make sure that Function.Injective.somethingRing looks like

def ... : SomethingRing β where
  toA := hf.a f ...
  __ := hf.b f ...
  __ := hf.c f ...

if SomethingRing α extends A α, B α, C α.

This should hopefully give a performance boost in applications.

Incidentally, there were a few missing transfer definitions, so I added them as I needed them.

Co-authored-by: Matthew Ballard <matt@mrb.email> Co-authored-by: Johan Commelin <johan@commelin.net>

Diff
@@ -314,6 +314,8 @@ sequence defining the same ideal and their quotient is the desired unit `u_w₁`
 
 open NumberField.mixedEmbedding NNReal
 
+/- TODO: Remove!. Necessary to prevent a timeout that ends at here. #10131 -/
+attribute [-instance] FractionalIdeal.commSemiring
 variable (w₁ : InfinitePlace K) {B : ℕ} (hB : minkowskiBound K 1 < (convexBodyLTFactor K) * B)
 
 /-- This result shows that there always exists a next term in the sequence. -/
chore: Some constants in CanonicalEmbedding should be NNReal and not ENNReal (#10032)

Co-authored-by: Yury G. Kudryashov <urkud@urkud.name>

Diff
@@ -325,7 +325,7 @@ theorem seq_next {x : 𝓞 K} (hx : x ≠ 0) :
     obtain ⟨g, h_geqf, h_gprod⟩ := adjust_f K B this
     obtain ⟨y, hy, h_ynz, h_yle⟩ := exists_ne_zero_mem_ringOfIntegers_lt (f := g)
       (by rw [convexBodyLT_volume]; convert hB; exact congr_arg ((↑): NNReal → ENNReal) h_gprod)
-    refine ⟨⟨y, hy⟩,  Subtype.ne_of_val_ne h_ynz, fun w hw => (h_geqf w hw ▸ h_yle w).trans ?_, ?_⟩
+    refine ⟨⟨y, hy⟩, Subtype.ne_of_val_ne h_ynz, fun w hw => (h_geqf w hw ▸ h_yle w).trans ?_, ?_⟩
     · rw [← Rat.cast_le (K := ℝ), Rat.cast_coe_nat]
       calc
         _ = ∏ w : InfinitePlace K, w y ^ mult w := (prod_eq_abs_norm (y : K)).symm
@@ -396,7 +396,7 @@ theorem exists_unit (w₁ : InfinitePlace K) :
     ∃ u : (𝓞 K)ˣ, ∀ w : InfinitePlace K, w ≠ w₁ → Real.log (w u) < 0 := by
   obtain ⟨B, hB⟩ : ∃ B : ℕ, minkowskiBound K 1 < (convexBodyLTFactor K) * B := by
     conv => congr; ext; rw [mul_comm]
-    exact ENNReal.exists_nat_mul_gt (ne_of_gt (convexBodyLTFactor_pos K))
+    exact ENNReal.exists_nat_mul_gt (ENNReal.coe_ne_zero.mpr (convexBodyLTFactor_ne_zero K))
       (ne_of_lt (minkowskiBound_lt_top K 1))
   rsuffices ⟨n, m, hnm, h⟩ : ∃ n m, n < m ∧
       (Ideal.span ({ (seq K w₁ hB n : 𝓞 K) }) = Ideal.span ({ (seq K w₁ hB m : 𝓞 K) }))
chore(NonnegHomClass): rename map_nonneg to apply_nonneg (#10507)

... to avoid conflict with _root_.map_nonneg, see Zulip.

Diff
@@ -218,7 +218,7 @@ theorem sum_logEmbedding_component (x : (𝓞 K)ˣ) :
 theorem mult_log_place_eq_zero {x : (𝓞 K)ˣ} {w : InfinitePlace K} :
     mult w * Real.log (w x) = 0 ↔ w x = 1 := by
   rw [mul_eq_zero, or_iff_right, Real.log_eq_zero, or_iff_right, or_iff_left]
-  · linarith [(map_nonneg _ _ : 0 ≤ w x)]
+  · linarith [(apply_nonneg _ _ : 0 ≤ w x)]
   · simp only [ne_eq, map_eq_zero, coe_ne_zero x, not_false_eq_true]
   · refine (ne_of_gt ?_)
     rw [mult]; split_ifs <;> norm_num
feat: Generalize results of CanonicalEmbedding to fractional ideals (#9837)

The main results of NumberTheory.NumberField.CanonicalEmbedding, that is exists_ne_zero_mem_ringOfIntegers_lt and exists_ne_zero_mem_ringOfIntegers_of_norm_le about the existence of algebraic integers satisfying special properties, are generalized from the ring of integers to fractional ideals.

Diff
@@ -6,7 +6,6 @@ Authors: Xavier Roblot
 import Mathlib.LinearAlgebra.Matrix.Gershgorin
 import Mathlib.NumberTheory.NumberField.CanonicalEmbedding
 import Mathlib.NumberTheory.NumberField.Norm
-import Mathlib.RingTheory.Ideal.Norm
 import Mathlib.RingTheory.RootsOfUnity.Basic
 
 #align_import number_theory.number_field.units from "leanprover-community/mathlib"@"00f91228655eecdcd3ac97a7fd8dbcb139fe990a"
@@ -33,7 +32,7 @@ as an additive `ℤ`-module.
 * `NumberField.Units.mem_torsion`: a unit `x : (𝓞 K)ˣ` is torsion iff `w x = 1` for all infinite
 places `w` of `K`.
 
-* `NumberField.Units.exist_unique_eq_mul_prod`: **Dirichlet Unit Theorem**. Any unit `x` of `𝓞 K`
+* `NumberField.Units.exist_unique_eq_mul_prod`: **Dirichlet Unit Theorem**. Any unit of `𝓞 K`
 can be written uniquely as the product of a root of unity and powers of the units of the
 fundamental system `fundSystem`.
 
@@ -315,7 +314,7 @@ sequence defining the same ideal and their quotient is the desired unit `u_w₁`
 
 open NumberField.mixedEmbedding NNReal
 
-variable (w₁ : InfinitePlace K) {B : ℕ} (hB : minkowskiBound K < (convexBodyLTFactor K) * B)
+variable (w₁ : InfinitePlace K) {B : ℕ} (hB : minkowskiBound K 1 < (convexBodyLTFactor K) * B)
 
 /-- This result shows that there always exists a next term in the sequence. -/
 theorem seq_next {x : 𝓞 K} (hx : x ≠ 0) :
@@ -324,9 +323,9 @@ theorem seq_next {x : 𝓞 K} (hx : x ≠ 0) :
     fun w => ⟨(w x) / 2, div_nonneg (AbsoluteValue.nonneg _ _) (by norm_num)⟩
   suffices ∀ w, w ≠ w₁ → f w ≠ 0 by
     obtain ⟨g, h_geqf, h_gprod⟩ := adjust_f K B this
-    obtain ⟨y, h_ynz, h_yle⟩ := exists_ne_zero_mem_ringOfIntegers_lt (f := g)
+    obtain ⟨y, hy, h_ynz, h_yle⟩ := exists_ne_zero_mem_ringOfIntegers_lt (f := g)
       (by rw [convexBodyLT_volume]; convert hB; exact congr_arg ((↑): NNReal → ENNReal) h_gprod)
-    refine ⟨y, h_ynz, fun w hw => (h_geqf w hw ▸ h_yle w).trans ?_, ?_⟩
+    refine ⟨⟨y, hy⟩,  Subtype.ne_of_val_ne h_ynz, fun w hw => (h_geqf w hw ▸ h_yle w).trans ?_, ?_⟩
     · rw [← Rat.cast_le (K := ℝ), Rat.cast_coe_nat]
       calc
         _ = ∏ w : InfinitePlace K, w y ^ mult w := (prod_eq_abs_norm (y : K)).symm
@@ -395,10 +394,10 @@ image by the `logEmbedding` of these units is `ℝ`-linearly independent, see
 `unitLattice_span_eq_top`. -/
 theorem exists_unit (w₁ : InfinitePlace K) :
     ∃ u : (𝓞 K)ˣ, ∀ w : InfinitePlace K, w ≠ w₁ → Real.log (w u) < 0 := by
-  obtain ⟨B, hB⟩ : ∃ B : ℕ, minkowskiBound K < (convexBodyLTFactor K) * B := by
+  obtain ⟨B, hB⟩ : ∃ B : ℕ, minkowskiBound K 1 < (convexBodyLTFactor K) * B := by
     conv => congr; ext; rw [mul_comm]
     exact ENNReal.exists_nat_mul_gt (ne_of_gt (convexBodyLTFactor_pos K))
-      (ne_of_lt (minkowskiBound_lt_top K))
+      (ne_of_lt (minkowskiBound_lt_top K 1))
   rsuffices ⟨n, m, hnm, h⟩ : ∃ n m, n < m ∧
       (Ideal.span ({ (seq K w₁ hB n : 𝓞 K) }) = Ideal.span ({ (seq K w₁ hB m : 𝓞 K) }))
   · have hu := Ideal.span_singleton_eq_span_singleton.mp h
chore: tidy various files (#9903)
Diff
@@ -114,7 +114,7 @@ theorem mem_torsion {x : (𝓞 K)ˣ} [NumberField K] :
   exact ⟨n, hn, by ext; rw [coe_pow, hx, coe_one]⟩
 
 /-- Shortcut instance because Lean tends to time out before finding the general instance. -/
-instance : Nonempty (torsion K) := One.nonempty
+instance : Nonempty (torsion K) := One.instNonempty
 
 /-- The torsion subgroup is finite. -/
 instance [NumberField K] : Fintype (torsion K) := by
chore: replace Infinite assumption by Nontrivial in Ideal.absNorm (#9684)

Also fix a typo and remove a now useless maxHeartbeats in Mathlib.NumberTheory.NumberField.Units.

Diff
@@ -34,7 +34,7 @@ as an additive `ℤ`-module.
 places `w` of `K`.
 
 * `NumberField.Units.exist_unique_eq_mul_prod`: **Dirichlet Unit Theorem**. Any unit `x` of `𝓞 K`
-can be written uniquely as the product of a root of unity and powers of the units of of the
+can be written uniquely as the product of a root of unity and powers of the units of the
 fundamental system `fundSystem`.
 
 ## Tags
@@ -492,7 +492,6 @@ theorem unitLattice_rank :
   rw [← Units.finrank_eq_rank]
   exact Zlattice.rank ℝ (unitLattice_span_eq_top K)
 
-set_option synthInstance.maxHeartbeats 27000 in
 /-- The linear equivalence between `unitLattice` and `(𝓞 K)ˣ ⧸ (torsion K)` as an additive
 `ℤ`-module. -/
 def unitLatticeEquiv : (unitLattice K) ≃ₗ[ℤ] Additive ((𝓞 K)ˣ ⧸ (torsion K)) := by
feat: Finite order elements have norm one (#9516)

This lemma already existed, but with an impractical spelling.

From LeanAPAP

Diff
@@ -107,12 +107,11 @@ def torsion : Subgroup (𝓞 K)ˣ := CommGroup.torsion (𝓞 K)ˣ
 
 theorem mem_torsion {x : (𝓞 K)ˣ} [NumberField K] :
     x ∈ torsion K ↔ ∀ w : InfinitePlace K, w x = 1 := by
-  rw [eq_iff_eq (x : K) 1, torsion, CommGroup.mem_torsion, isOfFinOrder_iff_pow_eq_one]
-  refine ⟨fun ⟨n, h_pos, h_eq⟩ φ => ?_, fun h => ?_⟩
-  · refine norm_map_one_of_pow_eq_one φ.toMonoidHom (k := ⟨n, h_pos⟩) ?_
-    rw [PNat.mk_coe, ← coe_pow, h_eq, coe_one]
-  · obtain ⟨n, hn, hx⟩ := Embeddings.pow_eq_one_of_norm_eq_one K ℂ x.val.prop h
-    exact ⟨n, hn, by ext; rw [coe_pow, hx, coe_one]⟩
+  rw [eq_iff_eq (x : K) 1, torsion, CommGroup.mem_torsion]
+  refine ⟨fun hx φ ↦ (((φ.comp $ algebraMap (𝓞 K) K).toMonoidHom.comp $
+    Units.coeHom _).isOfFinOrder hx).norm_eq_one, fun h ↦ isOfFinOrder_iff_pow_eq_one.2 ?_⟩
+  obtain ⟨n, hn, hx⟩ := Embeddings.pow_eq_one_of_norm_eq_one K ℂ x.val.prop h
+  exact ⟨n, hn, by ext; rw [coe_pow, hx, coe_one]⟩
 
 /-- Shortcut instance because Lean tends to time out before finding the general instance. -/
 instance : Nonempty (torsion K) := One.nonempty
chore: Rename pow monotonicity lemmas (#9095)

The names for lemmas about monotonicity of (a ^ ·) and (· ^ n) were a mess. This PR tidies up everything related by following the naming convention for (a * ·) and (· * b). Namely, (a ^ ·) is pow_right and (· ^ n) is pow_left in lemma names. All lemma renames follow the corresponding multiplication lemma names closely.

Renames

Algebra.GroupPower.Order

  • pow_monopow_right_mono
  • pow_le_powpow_le_pow_right
  • pow_le_pow_of_le_leftpow_le_pow_left
  • pow_lt_pow_of_lt_leftpow_lt_pow_left
  • strictMonoOn_powpow_left_strictMonoOn
  • pow_strictMono_rightpow_right_strictMono
  • pow_lt_powpow_lt_pow_right
  • pow_lt_pow_iffpow_lt_pow_iff_right
  • pow_le_pow_iffpow_le_pow_iff_right
  • self_lt_powlt_self_pow
  • strictAnti_powpow_right_strictAnti
  • pow_lt_pow_iff_of_lt_onepow_lt_pow_iff_right_of_lt_one
  • pow_lt_pow_of_lt_onepow_lt_pow_right_of_lt_one
  • lt_of_pow_lt_powlt_of_pow_lt_pow_left
  • le_of_pow_le_powle_of_pow_le_pow_left
  • pow_lt_pow₀pow_lt_pow_right₀

Algebra.GroupPower.CovariantClass

  • pow_le_pow_of_le_left'pow_le_pow_left'
  • nsmul_le_nsmul_of_le_rightnsmul_le_nsmul_right
  • pow_lt_pow'pow_lt_pow_right'
  • nsmul_lt_nsmulnsmul_lt_nsmul_left
  • pow_strictMono_leftpow_right_strictMono'
  • nsmul_strictMono_rightnsmul_left_strictMono
  • StrictMono.pow_right'StrictMono.pow_const
  • StrictMono.nsmul_leftStrictMono.const_nsmul
  • pow_strictMono_right'pow_left_strictMono
  • nsmul_strictMono_leftnsmul_right_strictMono
  • Monotone.pow_rightMonotone.pow_const
  • Monotone.nsmul_leftMonotone.const_nsmul
  • lt_of_pow_lt_pow'lt_of_pow_lt_pow_left'
  • lt_of_nsmul_lt_nsmullt_of_nsmul_lt_nsmul_right
  • pow_le_pow'pow_le_pow_right'
  • nsmul_le_nsmulnsmul_le_nsmul_left
  • pow_le_pow_of_le_one'pow_le_pow_right_of_le_one'
  • nsmul_le_nsmul_of_nonposnsmul_le_nsmul_left_of_nonpos
  • le_of_pow_le_pow'le_of_pow_le_pow_left'
  • le_of_nsmul_le_nsmul'le_of_nsmul_le_nsmul_right'
  • pow_le_pow_iff'pow_le_pow_iff_right'
  • nsmul_le_nsmul_iffnsmul_le_nsmul_iff_left
  • pow_lt_pow_iff'pow_lt_pow_iff_right'
  • nsmul_lt_nsmul_iffnsmul_lt_nsmul_iff_left

Data.Nat.Pow

  • Nat.pow_lt_pow_of_lt_leftNat.pow_lt_pow_left
  • Nat.pow_le_iff_le_leftNat.pow_le_pow_iff_left
  • Nat.pow_lt_iff_lt_leftNat.pow_lt_pow_iff_left

Lemmas added

  • pow_le_pow_iff_left
  • pow_lt_pow_iff_left
  • pow_right_injective
  • pow_right_inj
  • Nat.pow_le_pow_left to have the correct name since Nat.pow_le_pow_of_le_left is in Std.
  • Nat.pow_le_pow_right to have the correct name since Nat.pow_le_pow_of_le_right is in Std.

Lemmas removed

  • self_le_pow was a duplicate of le_self_pow.
  • Nat.pow_lt_pow_of_lt_right is defeq to pow_lt_pow_right.
  • Nat.pow_right_strictMono is defeq to pow_right_strictMono.
  • Nat.pow_le_iff_le_right is defeq to pow_le_pow_iff_right.
  • Nat.pow_lt_iff_lt_right is defeq to pow_lt_pow_iff_right.

Other changes

  • A bunch of proofs have been golfed.
  • Some lemma assumptions have been turned from 0 < n or 1 ≤ n to n ≠ 0.
  • A few Nat lemmas have been protected.
  • One docstring has been fixed.
Diff
@@ -334,7 +334,7 @@ theorem seq_next {x : 𝓞 K} (hx : x ≠ 0) :
         _ ≤ ∏ w : InfinitePlace K, (g w : ℝ) ^ mult w := by
           refine prod_le_prod ?_ ?_
           · exact fun _ _ => pow_nonneg (by positivity) _
-          · exact fun w _ => pow_le_pow_of_le_left (by positivity) (le_of_lt (h_yle w)) (mult w)
+          · exact fun w _ => pow_le_pow_left (by positivity) (le_of_lt (h_yle w)) (mult w)
         _ ≤ (B : ℝ) := by
           simp_rw [← NNReal.coe_pow, ← NNReal.coe_prod]
           exact le_of_eq (congr_arg toReal h_gprod)
chore: tidy various files (#8880)
Diff
@@ -248,9 +248,9 @@ theorem logEmbedding_component_le {r : ℝ} {x : (𝓞 K)ˣ} (hr : 0 ≤ r) (h :
 theorem log_le_of_logEmbedding_le {r : ℝ} {x : (𝓞 K)ˣ} (hr : 0 ≤ r) (h : ‖logEmbedding K x‖ ≤ r)
     (w : InfinitePlace K) : |Real.log (w x)| ≤ (Fintype.card (InfinitePlace K)) * r := by
   have tool : ∀ x : ℝ, 0 ≤ x → x ≤ mult w * x := fun x hx => by
-      nth_rw 1 [← one_mul x]
-      refine mul_le_mul ?_ le_rfl hx ?_
-      all_goals { rw [mult]; split_ifs <;> norm_num }
+    nth_rw 1 [← one_mul x]
+    refine mul_le_mul ?_ le_rfl hx ?_
+    all_goals { rw [mult]; split_ifs <;> norm_num }
   by_cases hw : w = w₀
   · have hyp := congr_arg (‖·‖) (sum_logEmbedding_component x).symm
     replace hyp := (le_of_eq hyp).trans (norm_sum_le _ _)
@@ -316,7 +316,7 @@ sequence defining the same ideal and their quotient is the desired unit `u_w₁`
 
 open NumberField.mixedEmbedding NNReal
 
-variable (w₁ : InfinitePlace K) {B : ℕ} (hB : minkowskiBound K < (convexBodyLtFactor K) * B)
+variable (w₁ : InfinitePlace K) {B : ℕ} (hB : minkowskiBound K < (convexBodyLTFactor K) * B)
 
 /-- This result shows that there always exists a next term in the sequence. -/
 theorem seq_next {x : 𝓞 K} (hx : x ≠ 0) :
@@ -326,7 +326,7 @@ theorem seq_next {x : 𝓞 K} (hx : x ≠ 0) :
   suffices ∀ w, w ≠ w₁ → f w ≠ 0 by
     obtain ⟨g, h_geqf, h_gprod⟩ := adjust_f K B this
     obtain ⟨y, h_ynz, h_yle⟩ := exists_ne_zero_mem_ringOfIntegers_lt (f := g)
-      (by rw [convexBodyLt_volume]; convert hB; exact congr_arg ((↑): NNReal → ENNReal) h_gprod)
+      (by rw [convexBodyLT_volume]; convert hB; exact congr_arg ((↑): NNReal → ENNReal) h_gprod)
     refine ⟨y, h_ynz, fun w hw => (h_geqf w hw ▸ h_yle w).trans ?_, ?_⟩
     · rw [← Rat.cast_le (K := ℝ), Rat.cast_coe_nat]
       calc
@@ -396,9 +396,9 @@ image by the `logEmbedding` of these units is `ℝ`-linearly independent, see
 `unitLattice_span_eq_top`. -/
 theorem exists_unit (w₁ : InfinitePlace K) :
     ∃ u : (𝓞 K)ˣ, ∀ w : InfinitePlace K, w ≠ w₁ → Real.log (w u) < 0 := by
-  obtain ⟨B, hB⟩ : ∃ B : ℕ, minkowskiBound K < (convexBodyLtFactor K) * B := by
+  obtain ⟨B, hB⟩ : ∃ B : ℕ, minkowskiBound K < (convexBodyLTFactor K) * B := by
     conv => congr; ext; rw [mul_comm]
-    exact ENNReal.exists_nat_mul_gt (ne_of_gt (convexBodyLtFactor_pos K))
+    exact ENNReal.exists_nat_mul_gt (ne_of_gt (convexBodyLTFactor_pos K))
       (ne_of_lt (minkowskiBound_lt_top K))
   rsuffices ⟨n, m, hnm, h⟩ : ∃ n m, n < m ∧
       (Ideal.span ({ (seq K w₁ hB n : 𝓞 K) }) = Ideal.span ({ (seq K w₁ hB m : 𝓞 K) }))
@@ -562,11 +562,12 @@ theorem fun_eq_repr {x ζ : (𝓞 K)ˣ} {f : Fin (rank K) → ℤ} (hζ : ζ ∈
   suffices Additive.ofMul ↑x = ∑ i, (f i) • (basisModTorsion K i) by
     rw [← (basisModTorsion K).repr_sum_self f, ← this]
   calc
-    Additive.ofMul ↑x = ∑ i, (f i) • Additive.ofMul ↑(fundSystem K i) := by
-                      rw [h, QuotientGroup.mk_mul, (QuotientGroup.eq_one_iff _).mpr hζ, one_mul,
-                        QuotientGroup.mk_prod, ofMul_prod]; rfl
-                    _ = ∑ i, (f i) • (basisModTorsion K i) := by
-                      simp_rw [fundSystem, QuotientGroup.out_eq', ofMul_toMul]
+    Additive.ofMul ↑x
+    _ = ∑ i, (f i) • Additive.ofMul ↑(fundSystem K i) := by
+          rw [h, QuotientGroup.mk_mul, (QuotientGroup.eq_one_iff _).mpr hζ, one_mul,
+            QuotientGroup.mk_prod, ofMul_prod]; rfl
+    _ = ∑ i, (f i) • (basisModTorsion K i) := by
+          simp_rw [fundSystem, QuotientGroup.out_eq', ofMul_toMul]
 
 /-- **Dirichlet Unit Theorem**. Any unit `x` of `𝓞 K` can be written uniquely as the product of
 a root of unity and powers of the units of the fundamental system `fundSystem`. -/
refactor(Algebra/Group/Defs): Separate commutative and associative multiplication (addition) (#7060)

Currently in Mathlib there is no class for magma that are commutative but not associative - Field extends CommRing and DivisionRing, CommRing extends Ring and CommMonoid, CommGroup extends Group and CommMonoid and CommMonoid extends CommSemigroup and Monoid. CommSemigroup currently extends only Semigroup and has mul_comm as a property.

This PR moves mul_comm into a new CommMagma (AddCommMagma) class which extends Mul (Add). CommSemigroup now extends Semigroup and CommMagma.

The rest of Mathlib4 compiles as before, except with the need to increase synthInstance.maxHeartbeats for lift_of_splits.

(Update: The linter is objecting to an unused argument in what seems to be a completely unrelated bit of code (AddEquiv.lpPiLp). Trying a nolint for now.)

Also referenced in https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/.60add_comm.60.20without.20.60add_assoc.60

Co-authored-by: Jireh Loreaux <loreaujy@gmail.com> Co-authored-by: Christopher Hoskin <mans0954@users.noreply.github.com> Co-authored-by: Christopher Hoskin <christopher.hoskin@overleaf.com> Co-authored-by: Mario Carneiro <di.gama@gmail.com>

Diff
@@ -493,6 +493,7 @@ theorem unitLattice_rank :
   rw [← Units.finrank_eq_rank]
   exact Zlattice.rank ℝ (unitLattice_span_eq_top K)
 
+set_option synthInstance.maxHeartbeats 27000 in
 /-- The linear equivalence between `unitLattice` and `(𝓞 K)ˣ ⧸ (torsion K)` as an additive
 `ℤ`-module. -/
 def unitLatticeEquiv : (unitLattice K) ≃ₗ[ℤ] Additive ((𝓞 K)ˣ ⧸ (torsion K)) := by
chore: rename lemmas containing "of_open" to match the naming convention (#8229)

Mostly, this means replacing "of_open" by "of_isOpen". A few lemmas names were misleading and are corrected differently. Zulip discussion.

Diff
@@ -466,7 +466,7 @@ open dirichletUnitTheorem FiniteDimensional Classical
 def rank : ℕ := Fintype.card (InfinitePlace K) - 1
 
 instance instDiscrete_unitLattice : DiscreteTopology (unitLattice K) := by
-  refine discreteTopology_of_open_singleton_zero ?_
+  refine discreteTopology_of_isOpen_singleton_zero ?_
   refine isOpen_singleton_of_finite_mem_nhds 0 (s := Metric.closedBall 0 1) ?_ ?_
   · exact Metric.closedBall_mem_nhds _ (by norm_num)
   · refine Set.Finite.of_finite_image ?_ (Set.injOn_of_injective Subtype.val_injective _)
feat: move the lemma Algebra.coe_norm_int (#8481)

The following lemma:

theorem Algebra.coe_norm_int {K : Type*} [Field K] [NumberField K] (x : 𝓞 K) :
    Algebra.norm ℤ x = Algebra.norm ℚ (x : K)

is currently in NumberField.Units but it belongs to NumberField.Norm

Diff
@@ -55,10 +55,6 @@ theorem Rat.RingOfIntegers.isUnit_iff {x : 𝓞 ℚ} : IsUnit x ↔ (x : ℚ) =
     Subtype.coe_injective.eq_iff]; rfl
 #align rat.ring_of_integers.is_unit_iff Rat.RingOfIntegers.isUnit_iff
 
-theorem Algebra.coe_norm_int {K : Type*} [Field K] [NumberField K] (x : 𝓞 K) :
-    Algebra.norm ℤ x = Algebra.norm ℚ (x : K) :=
-  (Algebra.norm_localization (R := ℤ) (Rₘ := ℚ) (S := 𝓞 K) (Sₘ := K) (nonZeroDivisors ℤ) x).symm
-
 end Rat
 
 variable (K : Type*) [Field K]
fix: remove remaining ^ fixes (#8463)
Diff
@@ -41,8 +41,6 @@ fundamental system `fundSystem`.
 number field, units
  -/
 
-local macro_rules | `($x ^ $y) => `(HPow.hPow $x $y) -- Porting note: See issue lean4#2220
-
 open scoped NumberField
 
 noncomputable section
chore: bump to v4.3.0-rc2 (#8366)

PR contents

This is the supremum of

along with some minor fixes from failures on nightly-testing as Mathlib master is merged into it.

Note that some PRs for changes that are already compatible with the current toolchain and will be necessary have already been split out: #8380.

I am hopeful that in future we will be able to progressively merge adaptation PRs into a bump/v4.X.0 branch, so we never end up with a "big merge" like this. However one of these adaptation PRs (#8056) predates my new scheme for combined CI, and it wasn't possible to keep that PR viable in the meantime.

Lean PRs involved in this bump

In particular this includes adjustments for the Lean PRs

leanprover/lean4#2778

We can get rid of all the

local macro_rules | `($x ^ $y) => `(HPow.hPow $x $y) -- Porting note: See issue [lean4#2220](https://github.com/leanprover/lean4/pull/2220)

macros across Mathlib (and in any projects that want to write natural number powers of reals).

leanprover/lean4#2722

Changes the default behaviour of simp to (config := {decide := false}). This makes simp (and consequentially norm_num) less powerful, but also more consistent, and less likely to blow up in long failures. This requires a variety of changes: changing some previously by simp or norm_num to decide or rfl, or adding (config := {decide := true}).

leanprover/lean4#2783

This changed the behaviour of simp so that simp [f] will only unfold "fully applied" occurrences of f. The old behaviour can be recovered with simp (config := { unfoldPartialApp := true }). We may in future add a syntax for this, e.g. simp [!f]; please provide feedback! In the meantime, we have made the following changes:

  • switching to using explicit lemmas that have the intended level of application
  • (config := { unfoldPartialApp := true }) in some places, to recover the old behaviour
  • Using @[eqns] to manually adjust the equation lemmas for a particular definition, recovering the old behaviour just for that definition. See #8371, where we do this for Function.comp and Function.flip.

This change in Lean may require further changes down the line (e.g. adding the !f syntax, and/or upstreaming the special treatment for Function.comp and Function.flip, and/or removing this special treatment). Please keep an open and skeptical mind about these changes!

Co-authored-by: leanprover-community-mathlib4-bot <leanprover-community-mathlib4-bot@users.noreply.github.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Mauricio Collares <mauricio@collares.org>

Diff
@@ -88,10 +88,10 @@ variable {K}
 
 theorem coe_mul (x y : (𝓞 K)ˣ) : ((x * y : (𝓞 K)ˣ) : K) = (x : K) * (y : K) := rfl
 
-theorem coe_pow (x : (𝓞 K)ˣ) (n : ℕ) : (x ^ n : K) = (x : K) ^ n := by
+theorem coe_pow (x : (𝓞 K)ˣ) (n : ℕ) : (↑(x ^ n) : K) = (x : K) ^ n := by
   rw [← SubmonoidClass.coe_pow, ← val_pow_eq_pow_val]
 
-theorem coe_zpow (x : (𝓞 K)ˣ) (n : ℤ) : (x ^ n : K) = (x : K) ^ n := by
+theorem coe_zpow (x : (𝓞 K)ˣ) (n : ℤ) : (↑(x ^ n) : K) = (x : K) ^ n := by
   change ((Units.coeHom K).comp (map (algebraMap (𝓞 K) K))) (x ^ n) = _
   exact map_zpow _ x n
 
@@ -227,7 +227,7 @@ theorem mult_log_place_eq_zero {x : (𝓞 K)ˣ} {w : InfinitePlace K} :
     mult w * Real.log (w x) = 0 ↔ w x = 1 := by
   rw [mul_eq_zero, or_iff_right, Real.log_eq_zero, or_iff_right, or_iff_left]
   · linarith [(map_nonneg _ _ : 0 ≤ w x)]
-  · simp only [ne_eq, map_eq_zero, coe_ne_zero x]
+  · simp only [ne_eq, map_eq_zero, coe_ne_zero x, not_false_eq_true]
   · refine (ne_of_gt ?_)
     rw [mult]; split_ifs <;> norm_num
 
@@ -345,7 +345,7 @@ theorem seq_next {x : 𝓞 K} (hx : x ≠ 0) :
           simp_rw [← NNReal.coe_pow, ← NNReal.coe_prod]
           exact le_of_eq (congr_arg toReal h_gprod)
     · refine div_lt_self ?_ (by norm_num)
-      simp only [pos_iff, ne_eq, ZeroMemClass.coe_eq_zero, hx]
+      simp only [pos_iff, ne_eq, ZeroMemClass.coe_eq_zero, hx, not_false_eq_true]
   intro _ _
   rw [ne_eq, Nonneg.mk_eq_zero, div_eq_zero_iff, map_eq_zero, not_or, ZeroMemClass.coe_eq_zero]
   exact ⟨hx, by norm_num⟩
@@ -410,7 +410,7 @@ theorem exists_unit (w₁ : InfinitePlace K) :
       (Ideal.span ({ (seq K w₁ hB n : 𝓞 K) }) = Ideal.span ({ (seq K w₁ hB m : 𝓞 K) }))
   · have hu := Ideal.span_singleton_eq_span_singleton.mp h
     refine ⟨hu.choose, fun w hw => Real.log_neg ?_ ?_⟩
-    · simp only [pos_iff, ne_eq, ZeroMemClass.coe_eq_zero, ne_zero]
+    · simp only [pos_iff, ne_eq, ZeroMemClass.coe_eq_zero, ne_zero, not_false_eq_true]
     · calc
         _ = w ((seq K w₁ hB m : K) * (seq K w₁ hB n : K)⁻¹) := by
           rw [← congr_arg ((↑) : (𝓞 K) → K) hu.choose_spec, mul_comm, Submonoid.coe_mul,
perf(FunLike.Basic): beta reduce CoeFun.coe (#7905)

This eliminates (fun a ↦ β) α in the type when applying a FunLike.

Co-authored-by: Matthew Ballard <matt@mrb.email> Co-authored-by: Eric Wieser <wieser.eric@gmail.com>

Diff
@@ -199,7 +199,7 @@ variable (K)
 
 /-- The logarithmic embedding of the units (seen as an `Additive` group). -/
 def logEmbedding : Additive ((𝓞 K)ˣ) →+ ({w : InfinitePlace K // w ≠ w₀} → ℝ) :=
-{ toFun := fun x w => mult w.val * Real.log (w.val (Additive.toMul x))
+{ toFun := fun x w => mult w.val * Real.log (w.val ↑(Additive.toMul x))
   map_zero' := by simp; rfl
   map_add' := fun _ _ => by simp [Real.log_mul, mul_add]; rfl }
 
@@ -555,7 +555,8 @@ def basisModTorsion : Basis (Fin (rank K)) ℤ (Additive ((𝓞 K)ˣ ⧸ (torsio
 /-- A fundamental system of units of `K`. The units of `fundSystem` are arbitrary lifts of the
 units in `basisModTorsion`. -/
 def fundSystem : Fin (rank K) → (𝓞 K)ˣ :=
-  fun i => Quotient.out' (Additive.toMul (basisModTorsion K i))
+  -- `:)` prevents the `⧸` decaying to a quotient by `leftRel` when we unfold this later
+  fun i => Quotient.out' (Additive.toMul (basisModTorsion K i) :)
 
 /-- The exponents that appear in the unique decomposition of a unit as the product of
 a root of unity and powers of the units of the fundamental system `fundSystem` (see
@@ -580,7 +581,7 @@ theorem exist_unique_eq_mul_prod (x : (𝓞 K)ˣ) : ∃! (ζ : torsion K) (e : F
   have h_tors : ζ ∈ torsion K := by
     rw [← QuotientGroup.eq_one_iff, QuotientGroup.mk_mul, QuotientGroup.mk_inv, ← ofMul_eq_zero,
       ofMul_mul, ofMul_inv, QuotientGroup.mk_prod, ofMul_prod]
-    simp_rw [QuotientGroup.mk_zpow, ofMul_zpow, fundSystem, QuotientGroup.out_eq', ofMul_toMul]
+    simp_rw [QuotientGroup.mk_zpow, ofMul_zpow, fundSystem, QuotientGroup.out_eq']
     rw [add_eq_zero_iff_eq_neg, neg_neg]
     exact ((basisModTorsion K).sum_repr (Additive.ofMul ↑x)).symm
   refine ⟨⟨ζ, h_tors⟩, ?_, ?_⟩
feat: Order of elements of a subgroup (#8385)

The cardinality of a subgroup is greater than the order of any of its elements.

Rename

  • order_eq_card_zpowersFintype.card_zpowers
  • order_eq_card_zpowers'Nat.card_zpowers (and turn it around to match Nat.card_subgroupPowers)
  • Submonoid.powers_subsetSubmonoid.powers_le
  • orderOf_dvd_card_univorderOf_dvd_card
  • orderOf_subgroupSubgroup.orderOf
  • Subgroup.nonemptySubgroup.coe_nonempty
Diff
@@ -155,7 +155,7 @@ theorem rootsOfUnity_eq_one [NumberField K] {k : ℕ+} (hc : Nat.Coprime k (tors
       rw [torsion, CommGroup.mem_torsion, isOfFinOrder_iff_pow_eq_one]
       exact ⟨k, k.prop, h⟩
     rw [orderOf_submonoid (⟨ζ, hζ⟩ : torsion K)]
-    exact orderOf_dvd_card_univ
+    exact orderOf_dvd_card
 
 /-- The group of roots of unity of order dividing `torsionOrder` is equal to the torsion
 group. -/
chore: Generalise lemmas from finite groups to torsion elements (#8342)

Many lemmas in GroupTheory.OrderOfElement were stated for elements of finite groups even though they work more generally for torsion elements of possibly infinite groups. This PR generalises those lemmas (and leaves convenience lemmas stated for finite groups), and fixes a bunch of names to use dot notation.

Renames

  • Function.eq_of_lt_minimalPeriod_of_iterate_eqFunction.iterate_injOn_Iio_minimalPeriod
  • Function.eq_iff_lt_minimalPeriod_of_iterate_eqFunction.iterate_eq_iterate_iff_of_lt_minimalPeriod
  • isOfFinOrder_iff_coeSubmonoid.isOfFinOrder_coe
  • orderOf_pos'IsOfFinOrder.orderOf_pos
  • pow_eq_mod_orderOfpow_mod_orderOf (and turned around)
  • pow_injective_of_lt_orderOfpow_injOn_Iio_orderOf
  • mem_powers_iff_mem_range_order_of'IsOfFinOrder.mem_powers_iff_mem_range_orderOf
  • orderOf_pow''IsOfFinOrder.orderOf_pow
  • orderOf_pow_coprimeNat.Coprime.orderOf_pow
  • zpow_eq_mod_orderOfzpow_mod_orderOf (and turned around)
  • exists_pow_eq_oneisOfFinOrder_of_finite
  • pow_apply_eq_pow_mod_orderOf_cycleOf_applypow_mod_orderOf_cycleOf_apply

New lemmas

  • IsOfFinOrder.powers_eq_image_range_orderOf
  • IsOfFinOrder.natCard_powers_le_orderOf
  • IsOfFinOrder.finite_powers
  • finite_powers
  • infinite_powers
  • Nat.card_submonoidPowers
  • IsOfFinOrder.mem_powers_iff_mem_zpowers
  • IsOfFinOrder.powers_eq_zpowers
  • IsOfFinOrder.mem_zpowers_iff_mem_range_orderOf
  • IsOfFinOrder.exists_pow_eq_one

Other changes

  • Move decidableMemPowers/fintypePowers to GroupTheory.Submonoid.Membership and decidableMemZpowers/fintypeZpowers to GroupTheory.Subgroup.ZPowers.
  • finEquivPowers, finEquivZpowers, powersEquivPowers and zpowersEquivZpowers now assume IsOfFinTorsion x instead of Finite G.
  • isOfFinOrder_iff_pow_eq_one now takes one less explicit argument.
  • Delete Equiv.Perm.IsCycle.exists_pow_eq_one since it was saying that a permutation over a finite type is torsion, but this is trivial since the group of permutation is itself finite, so we can use isOfFinOrder_of_finite instead.
Diff
@@ -166,7 +166,7 @@ theorem rootsOfUnity_eq_torsion [NumberField K] :
   refine ⟨fun h => ?_, fun h => ?_⟩
   · rw [CommGroup.mem_torsion, isOfFinOrder_iff_pow_eq_one]
     exact ⟨↑(torsionOrder K), (torsionOrder K).prop, h⟩
-  · exact Subtype.ext_iff.mp (@pow_card_eq_one (torsion K) _ ⟨ζ, h⟩ _)
+  · exact Subtype.ext_iff.mp (@pow_card_eq_one (torsion K) _ _ ⟨ζ, h⟩)
 
 end torsion
 
feat: explicit volume computations in NumberTheory.NumberField.CanonicalEmbedding (#6886)

We compute the values of the volumes used in CanonicalEmbedding. In particular, we prove that

volume (fundamentalDomain (latticeBasis K)) =
       (2 : ℝ≥0∞)⁻¹ ^ (NrComplexPlaces K) * NNReal.sqrt ‖discr K‖₊

This will be useful later on to prove Hermite and Hermite-Minkowski theorems.

Diff
@@ -41,6 +41,7 @@ fundamental system `fundSystem`.
 number field, units
  -/
 
+local macro_rules | `($x ^ $y) => `(HPow.hPow $x $y) -- Porting note: See issue lean4#2220
 
 open scoped NumberField
 
@@ -321,9 +322,6 @@ sequence defining the same ideal and their quotient is the desired unit `u_w₁`
 
 open NumberField.mixedEmbedding NNReal
 
--- See: https://github.com/leanprover/lean4/issues/2220
-local macro_rules | `($x ^ $y) => `(HPow.hPow $x $y)
-
 variable (w₁ : InfinitePlace K) {B : ℕ} (hB : minkowskiBound K < (convexBodyLtFactor K) * B)
 
 /-- This result shows that there always exists a next term in the sequence. -/
@@ -405,10 +403,9 @@ image by the `logEmbedding` of these units is `ℝ`-linearly independent, see
 theorem exists_unit (w₁ : InfinitePlace K) :
     ∃ u : (𝓞 K)ˣ, ∀ w : InfinitePlace K, w ≠ w₁ → Real.log (w u) < 0 := by
   obtain ⟨B, hB⟩ : ∃ B : ℕ, minkowskiBound K < (convexBodyLtFactor K) * B := by
-    simp_rw [mul_comm]
-    refine ENNReal.exists_nat_mul_gt ?_ ?_
-    exact ne_of_gt (convexBodyLtFactor_pos K)
-    exact ne_of_lt (minkowskiBound_lt_top K)
+    conv => congr; ext; rw [mul_comm]
+    exact ENNReal.exists_nat_mul_gt (ne_of_gt (convexBodyLtFactor_pos K))
+      (ne_of_lt (minkowskiBound_lt_top K))
   rsuffices ⟨n, m, hnm, h⟩ : ∃ n m, n < m ∧
       (Ideal.span ({ (seq K w₁ hB n : 𝓞 K) }) = Ideal.span ({ (seq K w₁ hB m : 𝓞 K) }))
   · have hu := Ideal.span_singleton_eq_span_singleton.mp h
chore: remove some double spaces (#7983)

Co-authored-by: Moritz Firsching <firsching@google.com>

Diff
@@ -263,7 +263,7 @@ theorem log_le_of_logEmbedding_le {r : ℝ} {x : (𝓞 K)ˣ} (hr : 0 ≤ r) (h :
     refine (le_trans ?_ hyp).trans ?_
     · rw [← hw]
       exact tool _ (abs_nonneg _)
-    · refine (sum_le_card_nsmul univ _  _
+    · refine (sum_le_card_nsmul univ _ _
         (fun w _ => logEmbedding_component_le hr h w)).trans ?_
       rw [nsmul_eq_mul]
       refine mul_le_mul ?_ le_rfl hr (Fintype.card (InfinitePlace K)).cast_nonneg
@@ -400,9 +400,9 @@ theorem seq_norm_le (n : ℕ) :
       exact (seq_next K w₁ hB (seq K w₁ hB n).prop).choose_spec.2.2
 
 /-- Construct a unit associated to the place `w₁`. The family, for `w₁ ≠ w₀`, formed by the
-image by the `logEmbedding` of these units  is `ℝ`-linearly independent, see
+image by the `logEmbedding` of these units is `ℝ`-linearly independent, see
 `unitLattice_span_eq_top`. -/
-theorem exists_unit (w₁ : InfinitePlace K ) :
+theorem exists_unit (w₁ : InfinitePlace K) :
     ∃ u : (𝓞 K)ˣ, ∀ w : InfinitePlace K, w ≠ w₁ → Real.log (w u) < 0 := by
   obtain ⟨B, hB⟩ : ∃ B : ℕ, minkowskiBound K < (convexBodyLtFactor K) * B := by
     simp_rw [mul_comm]
@@ -427,7 +427,7 @@ theorem exists_unit (w₁ : InfinitePlace K ) :
     (fun n => ?_) ?_
   · rw [Set.mem_setOf_eq, Ideal.absNorm_span_singleton]
     refine ⟨?_, seq_norm_le K w₁ hB n⟩
-    exact  Nat.one_le_iff_ne_zero.mpr (Int.natAbs_ne_zero.mpr (seq_norm_ne_zero K w₁ hB n))
+    exact Nat.one_le_iff_ne_zero.mpr (Int.natAbs_ne_zero.mpr (seq_norm_ne_zero K w₁ hB n))
   · rw [show { I : Ideal (𝓞 K) | 1 ≤ Ideal.absNorm I ∧ Ideal.absNorm I ≤ B } =
           (⋃ n ∈ Set.Icc 1 B, { I : Ideal (𝓞 K) | Ideal.absNorm I = n }) by ext; simp]
     exact Set.Finite.biUnion (Set.finite_Icc _ _) (fun n hn => Ideal.finite_setOf_absNorm_eq hn.1)
feat: add a Module.Finite instance for units of number field (#7412)

Add the following instance

instance : Module.Finite ℤ (Additive (𝓞 K)ˣ) 

To prove this instance, it is helpful to add some rfl lemmas about Additive and AddMonoidHom.toIntLinearMap

This PR also fixes a couple of typo in the docstring

Diff
@@ -139,7 +139,7 @@ instance [NumberField K] : Finite (torsion K) := inferInstance
 /-- The torsion subgroup is cylic. -/
 instance [NumberField K] : IsCyclic (torsion K) := subgroup_units_cyclic _
 
-/-- The order of the torsion subgroup as positive integer. -/
+/-- The order of the torsion subgroup as a positive integer. -/
 def torsionOrder [NumberField K] : ℕ+ := ⟨Fintype.card (torsion K), Fintype.card_pos⟩
 
 /-- If `k` does not divide `torsionOrder` then there are no nontrivial roots of unity of
@@ -178,7 +178,7 @@ This section is devoted to the proof of Dirichlet's unit theorem.
 We define a group morphism from `(𝓞 K)ˣ` to `{w : InfinitePlace K // w ≠ w₀} → ℝ` where `w₀` is a
 distinguished (arbitrary) infinite place, prove that its kernel is the torsion subgroup (see
 `logEmbedding_eq_zero_iff`) and that its image, called `unitLattice`, is a full `ℤ`-lattice. It
-follows that `unitLattice` is a free `ℤ`-module (see `unitLattice_moduleFree `) of rank
+follows that `unitLattice` is a free `ℤ`-module (see `instModuleFree_unitLattice`) of rank
 `card (InfinitePlaces K) - 1` (see `unitLattice_rank`). To prove that the `unitLattice` is a full
 `ℤ`-lattice, we need to prove that it is discrete (see `unitLattice_inter_ball_finite`) and that it
 spans the full space over `ℝ` (see `unitLattice_span_eq_top`); this is the main part of the proof,
@@ -401,8 +401,8 @@ theorem seq_norm_le (n : ℕ) :
 
 /-- Construct a unit associated to the place `w₁`. The family, for `w₁ ≠ w₀`, formed by the
 image by the `logEmbedding` of these units  is `ℝ`-linearly independent, see
-`unit_lattice_span_eq_top`. -/
-theorem exists_unit (w₁ : InfinitePlace K) :
+`unitLattice_span_eq_top`. -/
+theorem exists_unit (w₁ : InfinitePlace K ) :
     ∃ u : (𝓞 K)ˣ, ∀ w : InfinitePlace K, w ≠ w₁ → Real.log (w u) < 0 := by
   obtain ⟨B, hB⟩ : ∃ B : ℕ, minkowskiBound K < (convexBodyLtFactor K) * B := by
     simp_rw [mul_comm]
@@ -512,9 +512,8 @@ def unitLatticeEquiv : (unitLattice K) ≃ₗ[ℤ] Additive ((𝓞 K)ˣ ⧸ (tor
     (QuotientAddGroup.quotientKerEquivOfSurjective
       (MonoidHom.toAdditive (QuotientGroup.mk' (torsion K))) (fun x => ?_))
   · ext
-    rw [AddMonoidHom.mem_ker, AddMonoidHom.mem_ker, logEmbedding_eq_zero_iff,
-      MonoidHom.toAdditive_apply_apply, ofMul_eq_zero, QuotientGroup.mk'_apply,
-      QuotientGroup.eq_one_iff]
+    rw [MonoidHom.coe_toAdditive_ker, QuotientGroup.ker_mk', AddMonoidHom.mem_ker,
+      logEmbedding_eq_zero_iff]
     rfl
   · refine ⟨Additive.ofMul x.out', ?_⟩
     simp only [MonoidHom.toAdditive_apply_apply, toMul_ofMul, QuotientGroup.mk'_apply,
@@ -527,6 +526,26 @@ instance : Module.Free ℤ (Additive ((𝓞 K)ˣ ⧸ (torsion K))) :=
 instance : Module.Finite ℤ (Additive ((𝓞 K)ˣ ⧸ (torsion K))) :=
   Module.Finite.equiv (unitLatticeEquiv K)
 
+-- Note that we prove this instance first and then deduce from it the instance
+-- `Monoid.FG (𝓞 K)ˣ`, and not the other way around, due to no `Subgroup` version
+-- of `Submodule.fg_of_fg_map_of_fg_inf_ker` existing.
+instance : Module.Finite ℤ (Additive (𝓞 K)ˣ) := by
+  rw [Module.finite_def]
+  refine Submodule.fg_of_fg_map_of_fg_inf_ker
+    (MonoidHom.toAdditive (QuotientGroup.mk' (torsion K))).toIntLinearMap ?_ ?_
+  · rw [Submodule.map_top, LinearMap.range_eq_top.mpr
+      (by exact QuotientGroup.mk'_surjective (torsion K)), ← Module.finite_def]
+    infer_instance
+  · rw [inf_of_le_right le_top, AddMonoidHom.coe_toIntLinearMap_ker, MonoidHom.coe_toAdditive_ker,
+      QuotientGroup.ker_mk', Submodule.fg_iff_add_subgroup_fg,
+      AddSubgroup.toIntSubmodule_toAddSubgroup, ← AddGroup.fg_iff_addSubgroup_fg]
+    have : Finite (Subgroup.toAddSubgroup (torsion K)) := (inferInstance : Finite (torsion K))
+    exact AddGroup.fg_of_finite
+
+instance : Monoid.FG (𝓞 K)ˣ := by
+  rw [Monoid.fg_iff_add_fg, ← AddGroup.fg_iff_addMonoid_fg, ← Module.Finite.iff_addGroup_fg]
+  infer_instance
+
 theorem rank_modTorsion :
     FiniteDimensional.finrank ℤ (Additive ((𝓞 K)ˣ ⧸ (torsion K))) = rank K := by
   rw [← LinearEquiv.finrank_eq (unitLatticeEquiv K), unitLattice_rank]
@@ -543,7 +562,7 @@ def fundSystem : Fin (rank K) → (𝓞 K)ˣ :=
 
 /-- The exponents that appear in the unique decomposition of a unit as the product of
 a root of unity and powers of the units of the fundamental system `fundSystem` (see
-`exist_unique_eq_mul_prod`) are given by the representation of the unit of `basisModTorsion`. -/
+`exist_unique_eq_mul_prod`) are given by the representation of the unit on `basisModTorsion`. -/
 theorem fun_eq_repr {x ζ : (𝓞 K)ˣ} {f : Fin (rank K) → ℤ} (hζ : ζ ∈ torsion K)
     (h : x = ζ * ∏ i, (fundSystem K i) ^ (f i)) :
     f = (basisModTorsion K).repr (Additive.ofMul ↑x) := by
chore: remove trailing space in backticks (#7617)

This will improve spaces in the mathlib4 docs.

Diff
@@ -181,7 +181,7 @@ distinguished (arbitrary) infinite place, prove that its kernel is the torsion s
 follows that `unitLattice` is a free `ℤ`-module (see `unitLattice_moduleFree `) of rank
 `card (InfinitePlaces K) - 1` (see `unitLattice_rank`). To prove that the `unitLattice` is a full
 `ℤ`-lattice, we need to prove that it is discrete (see `unitLattice_inter_ball_finite`) and that it
-spans the full space over `ℝ` (see ` unitLattice_span_eq_top`); this is the main part of the proof,
+spans the full space over `ℝ` (see `unitLattice_span_eq_top`); this is the main part of the proof,
 see the section `span_top` below for more details.
 -/
 
chore: cleanup some spaces (#7484)

Purely cosmetic PR.

Diff
@@ -402,7 +402,7 @@ theorem seq_norm_le (n : ℕ) :
 /-- Construct a unit associated to the place `w₁`. The family, for `w₁ ≠ w₀`, formed by the
 image by the `logEmbedding` of these units  is `ℝ`-linearly independent, see
 `unit_lattice_span_eq_top`. -/
-theorem exists_unit (w₁ : InfinitePlace K ) :
+theorem exists_unit (w₁ : InfinitePlace K) :
     ∃ u : (𝓞 K)ˣ, ∀ w : InfinitePlace K, w ≠ w₁ → Real.log (w u) < 0 := by
   obtain ⟨B, hB⟩ : ∃ B : ℕ, minkowskiBound K < (convexBodyLtFactor K) * B := by
     simp_rw [mul_comm]
feat: add Algebra.coe_norm_int (#7463)

From flt-regular.

Co-authored-by: Andrew Yang <the.erd.one@gmail.com>

Diff
@@ -56,6 +56,10 @@ theorem Rat.RingOfIntegers.isUnit_iff {x : 𝓞 ℚ} : IsUnit x ↔ (x : ℚ) =
     Subtype.coe_injective.eq_iff]; rfl
 #align rat.ring_of_integers.is_unit_iff Rat.RingOfIntegers.isUnit_iff
 
+theorem Algebra.coe_norm_int {K : Type*} [Field K] [NumberField K] (x : 𝓞 K) :
+    Algebra.norm ℤ x = Algebra.norm ℚ (x : K) :=
+  (Algebra.norm_localization (R := ℤ) (Rₘ := ℚ) (S := 𝓞 K) (Sₘ := K) (nonZeroDivisors ℤ) x).symm
+
 end Rat
 
 variable (K : Type*) [Field K]
@@ -392,9 +396,7 @@ theorem seq_norm_le (n : ℕ) :
         simp only [Nat.lt_one_iff.mp hB, CharP.cast_eq_zero, mul_zero, zero_le]
       simp only [ne_eq, seq, map_one, Int.natAbs_one, this]
   | succ n =>
-      rw [← Nat.cast_le (α := ℚ), Int.cast_natAbs, Int.cast_abs]
-      change |algebraMap ℤ ℚ _| ≤ _
-      rw [← Algebra.norm_localization ℤ (Sₘ := K) (nonZeroDivisors ℤ)]
+      rw [← Nat.cast_le (α := ℚ), Int.cast_natAbs, Int.cast_abs, Algebra.coe_norm_int]
       exact (seq_next K w₁ hB (seq K w₁ hB n).prop).choose_spec.2.2
 
 /-- Construct a unit associated to the place `w₁`. The family, for `w₁ ≠ w₀`, formed by the
style: a linter for four spaces (#7283)

Includes an auto-fix feature with the --fix flag so that spacing suggestions will be automatically applied in review also.

Co-authored-by: Moritz Firsching <firsching@google.com>

Diff
@@ -368,7 +368,7 @@ theorem seq_norm_ne_zero (n : ℕ) : Algebra.norm ℤ (seq K w₁ hB n : 𝓞 K)
 
 /-- The sequence is strictly decreasing at infinite places distinct from `w₁`. -/
 theorem seq_decreasing {n m : ℕ} (h : n < m) (w : InfinitePlace K) (hw : w ≠ w₁) :
-     w (seq K w₁ hB m) < w (seq K w₁ hB n) := by
+    w (seq K w₁ hB m) < w (seq K w₁ hB n) := by
   induction m with
   | zero =>
       exfalso
feat(NumberTheory.NumberField.Units): proof of Dirichlet's unit theorem (#5960)

We prove Dirichlet's unit theorem. More precisely, the main results are:

def basisModTorsion : Basis (Fin (Units.rank K)) ℤ (Additive ((𝓞 K)ˣ ⧸ (torsion K)))

where Units.rank := Fintype.card (InfinitePlace K) - 1 and

theorem exist_unique_eq_mul_prod (x : (𝓞 K)ˣ) : ∃! (ζ : torsion K) (e : Fin (Units.rank K) → ℤ),
    x = ζ * ∏ i, (fundSystem K i) ^ (e i)

where fundSystem : Fin (rank K) → (𝓞 K)ˣ is a fundamental system of units.

The exponents in exist_unique_eq_mul_prod can be computed via the following result:

theorem fun_eq_repr {x ζ : (𝓞 K)ˣ} {f : Fin (rank K) → ℤ} (hζ : ζ ∈ torsion K) 
    (h : x = ζ * ∏ i, (fundSystem K i) ^ (f i)) : f = (basisModTorsion K).repr (Additive.ofMul ↑x)
Diff
@@ -3,9 +3,10 @@ Copyright (c) 2023 Xavier Roblot. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Xavier Roblot
 -/
-import Mathlib.GroupTheory.Torsion
-import Mathlib.NumberTheory.NumberField.Embeddings
+import Mathlib.LinearAlgebra.Matrix.Gershgorin
+import Mathlib.NumberTheory.NumberField.CanonicalEmbedding
 import Mathlib.NumberTheory.NumberField.Norm
+import Mathlib.RingTheory.Ideal.Norm
 import Mathlib.RingTheory.RootsOfUnity.Basic
 
 #align_import number_theory.number_field.units from "leanprover-community/mathlib"@"00f91228655eecdcd3ac97a7fd8dbcb139fe990a"
@@ -15,22 +16,37 @@ import Mathlib.RingTheory.RootsOfUnity.Basic
 We prove results about the group `(𝓞 K)ˣ` of units of the ring of integers `𝓞 K` of a number
 field `K`.
 
+## Main definitions
+
+* `NumberField.Units.rank`: the unit rank of the number field `K`.
+
+* `NumberField.Units.fundSystem`: a fundamental system of units of `K`.
+
+* `NumberField.Units.basisModTorsion`: a `ℤ`-basis of `(𝓞 K)ˣ ⧸ (torsion K)`
+as an additive `ℤ`-module.
+
 ## Main results
-* `isUnit_iff_norm`: an algebraic integer `x : 𝓞 K` is a unit if and only if `|norm ℚ x| = 1`.
-* `mem_torsion`: a unit `x : (𝓞 K)ˣ` is torsion iff `w x = 1` for all infinite places of `K`.
+
+* `NumberField.isUnit_iff_norm`: an algebraic integer `x : 𝓞 K` is a unit if and only if
+`|norm ℚ x| = 1`.
+
+* `NumberField.Units.mem_torsion`: a unit `x : (𝓞 K)ˣ` is torsion iff `w x = 1` for all infinite
+places `w` of `K`.
+
+* `NumberField.Units.exist_unique_eq_mul_prod`: **Dirichlet Unit Theorem**. Any unit `x` of `𝓞 K`
+can be written uniquely as the product of a root of unity and powers of the units of of the
+fundamental system `fundSystem`.
 
 ## Tags
 number field, units
  -/
 
-set_option autoImplicit true
-
 
 open scoped NumberField
 
 noncomputable section
 
-open NumberField Units
+open NumberField Units BigOperators
 
 section Rat
 
@@ -48,11 +64,11 @@ section IsUnit
 
 variable {K}
 
-theorem isUnit_iff_norm [NumberField K] {x : 𝓞 K} :
+theorem NumberField.isUnit_iff_norm [NumberField K] {x : 𝓞 K} :
     IsUnit x ↔ |(RingOfIntegers.norm ℚ x : ℚ)| = 1 := by
   convert (RingOfIntegers.isUnit_norm ℚ (F := K)).symm
   rw [← abs_one, abs_eq_abs, ← Rat.RingOfIntegers.isUnit_iff]
-#align is_unit_iff_norm isUnit_iff_norm
+#align is_unit_iff_norm NumberField.isUnit_iff_norm
 
 end IsUnit
 
@@ -124,8 +140,8 @@ def torsionOrder [NumberField K] : ℕ+ := ⟨Fintype.card (torsion K), Fintype.
 
 /-- If `k` does not divide `torsionOrder` then there are no nontrivial roots of unity of
   order dividing `k`. -/
-theorem rootsOfUnity_eq_one [NumberField K] {k : ℕ+} (hc : Nat.Coprime k (torsionOrder K)) :
-    ζ ∈ rootsOfUnity k (𝓞 K) ↔ ζ = 1 := by
+theorem rootsOfUnity_eq_one [NumberField K] {k : ℕ+} (hc : Nat.Coprime k (torsionOrder K))
+    {ζ : (𝓞 K)ˣ} : ζ ∈ rootsOfUnity k (𝓞 K) ↔ ζ = 1 := by
   rw [mem_rootsOfUnity]
   refine ⟨fun h => ?_, fun h => by rw [h, one_pow]⟩
   refine orderOf_eq_one_iff.mp (Nat.eq_one_of_dvd_coprimes hc ?_ ?_)
@@ -149,4 +165,416 @@ theorem rootsOfUnity_eq_torsion [NumberField K] :
 
 end torsion
 
+namespace dirichletUnitTheorem
+
+/-!
+### Dirichlet Unit Theorem
+This section is devoted to the proof of Dirichlet's unit theorem.
+
+We define a group morphism from `(𝓞 K)ˣ` to `{w : InfinitePlace K // w ≠ w₀} → ℝ` where `w₀` is a
+distinguished (arbitrary) infinite place, prove that its kernel is the torsion subgroup (see
+`logEmbedding_eq_zero_iff`) and that its image, called `unitLattice`, is a full `ℤ`-lattice. It
+follows that `unitLattice` is a free `ℤ`-module (see `unitLattice_moduleFree `) of rank
+`card (InfinitePlaces K) - 1` (see `unitLattice_rank`). To prove that the `unitLattice` is a full
+`ℤ`-lattice, we need to prove that it is discrete (see `unitLattice_inter_ball_finite`) and that it
+spans the full space over `ℝ` (see ` unitLattice_span_eq_top`); this is the main part of the proof,
+see the section `span_top` below for more details.
+-/
+
+open Classical Finset
+
+variable [NumberField K]
+
+variable {K}
+
+/-- The distinguished infinite place. -/
+def w₀ : InfinitePlace K := (inferInstance : Nonempty (InfinitePlace K)).some
+
+variable (K)
+
+/-- The logarithmic embedding of the units (seen as an `Additive` group). -/
+def logEmbedding : Additive ((𝓞 K)ˣ) →+ ({w : InfinitePlace K // w ≠ w₀} → ℝ) :=
+{ toFun := fun x w => mult w.val * Real.log (w.val (Additive.toMul x))
+  map_zero' := by simp; rfl
+  map_add' := fun _ _ => by simp [Real.log_mul, mul_add]; rfl }
+
+variable {K}
+
+@[simp]
+theorem logEmbedding_component (x : (𝓞 K)ˣ) (w : {w : InfinitePlace K // w ≠ w₀}) :
+    (logEmbedding K x) w = mult w.val * Real.log (w.val x) := rfl
+
+theorem sum_logEmbedding_component (x : (𝓞 K)ˣ) :
+    ∑ w, logEmbedding K x w = - mult (w₀ : InfinitePlace K) * Real.log (w₀ (x : K)) := by
+  have h := congr_arg Real.log (prod_eq_abs_norm (x : K))
+  rw [show |(Algebra.norm ℚ) (x : K)| = 1 from isUnit_iff_norm.mp x.isUnit, Rat.cast_one,
+    Real.log_one, Real.log_prod] at h
+  · simp_rw [Real.log_pow] at h
+    rw [← insert_erase (mem_univ w₀), sum_insert (not_mem_erase w₀ univ), add_comm,
+      add_eq_zero_iff_eq_neg] at h
+    convert h using 1
+    · refine (sum_subtype _ (fun w => ?_) (fun w => (mult w) * (Real.log (w (x : K))))).symm
+      exact ⟨ne_of_mem_erase, fun h => mem_erase_of_ne_of_mem h (mem_univ w)⟩
+    · norm_num
+  · exact fun w _ => pow_ne_zero _ (AbsoluteValue.ne_zero _ (coe_ne_zero x))
+
+theorem mult_log_place_eq_zero {x : (𝓞 K)ˣ} {w : InfinitePlace K} :
+    mult w * Real.log (w x) = 0 ↔ w x = 1 := by
+  rw [mul_eq_zero, or_iff_right, Real.log_eq_zero, or_iff_right, or_iff_left]
+  · linarith [(map_nonneg _ _ : 0 ≤ w x)]
+  · simp only [ne_eq, map_eq_zero, coe_ne_zero x]
+  · refine (ne_of_gt ?_)
+    rw [mult]; split_ifs <;> norm_num
+
+theorem logEmbedding_eq_zero_iff {x : (𝓞 K)ˣ} :
+    logEmbedding K x = 0 ↔ x ∈ torsion K := by
+  rw [mem_torsion]
+  refine ⟨fun h w => ?_, fun h => ?_⟩
+  · by_cases hw : w = w₀
+    · suffices -mult w₀ * Real.log (w₀ (x : K)) = 0 by
+        rw [neg_mul, neg_eq_zero, ← hw] at this
+        exact mult_log_place_eq_zero.mp this
+      rw [← sum_logEmbedding_component, sum_eq_zero]
+      exact fun w _ => congrFun h w
+    · exact mult_log_place_eq_zero.mp (congrFun h ⟨w, hw⟩)
+  · ext w
+    rw [logEmbedding_component, h w.val, Real.log_one, mul_zero, Pi.zero_apply]
+
+theorem logEmbedding_component_le {r : ℝ} {x : (𝓞 K)ˣ} (hr : 0 ≤ r) (h : ‖logEmbedding K x‖ ≤ r)
+    (w : {w : InfinitePlace K // w ≠ w₀}) : |logEmbedding K x w| ≤ r := by
+  lift r to NNReal using hr
+  simp_rw [Pi.norm_def, NNReal.coe_le_coe, Finset.sup_le_iff, ← NNReal.coe_le_coe] at h
+  exact h w (mem_univ _)
+
+theorem log_le_of_logEmbedding_le {r : ℝ} {x : (𝓞 K)ˣ} (hr : 0 ≤ r) (h : ‖logEmbedding K x‖ ≤ r)
+    (w : InfinitePlace K) : |Real.log (w x)| ≤ (Fintype.card (InfinitePlace K)) * r := by
+  have tool : ∀ x : ℝ, 0 ≤ x → x ≤ mult w * x := fun x hx => by
+      nth_rw 1 [← one_mul x]
+      refine mul_le_mul ?_ le_rfl hx ?_
+      all_goals { rw [mult]; split_ifs <;> norm_num }
+  by_cases hw : w = w₀
+  · have hyp := congr_arg (‖·‖) (sum_logEmbedding_component x).symm
+    replace hyp := (le_of_eq hyp).trans (norm_sum_le _ _)
+    simp_rw [norm_mul, norm_neg, Real.norm_eq_abs, Nat.abs_cast] at hyp
+    refine (le_trans ?_ hyp).trans ?_
+    · rw [← hw]
+      exact tool _ (abs_nonneg _)
+    · refine (sum_le_card_nsmul univ _  _
+        (fun w _ => logEmbedding_component_le hr h w)).trans ?_
+      rw [nsmul_eq_mul]
+      refine mul_le_mul ?_ le_rfl hr (Fintype.card (InfinitePlace K)).cast_nonneg
+      simp [card_univ]
+  · have hyp := logEmbedding_component_le hr h ⟨w, hw⟩
+    rw [logEmbedding_component, abs_mul, Nat.abs_cast] at hyp
+    refine (le_trans ?_ hyp).trans ?_
+    · exact tool _ (abs_nonneg _)
+    · nth_rw 1 [← one_mul r]
+      exact mul_le_mul (Nat.one_le_cast.mpr Fintype.card_pos) (le_of_eq rfl) hr (Nat.cast_nonneg _)
+
+variable (K)
+
+/-- The lattice formed by the image of the logarithmic embedding. -/
+noncomputable def _root_.NumberField.Units.unitLattice :
+    AddSubgroup ({w : InfinitePlace K // w ≠ w₀} → ℝ) :=
+  AddSubgroup.map (logEmbedding K) ⊤
+
+theorem unitLattice_inter_ball_finite (r : ℝ) :
+    ((unitLattice K : Set ({ w : InfinitePlace K // w ≠ w₀} → ℝ)) ∩
+      Metric.closedBall 0 r).Finite := by
+  obtain hr | hr := lt_or_le r 0
+  · convert Set.finite_empty
+    rw [Metric.closedBall_eq_empty.mpr hr]
+    exact Set.inter_empty _
+  · suffices {x : (𝓞 K)ˣ | IsIntegral ℤ (x : K) ∧
+        ∀ (φ : K →+* ℂ), ‖φ x‖ ≤ Real.exp ((Fintype.card (InfinitePlace K)) * r)}.Finite by
+      refine (Set.Finite.image (logEmbedding K) this).subset ?_
+      rintro _ ⟨⟨x, ⟨_, rfl⟩⟩, hx⟩
+      refine ⟨x, ⟨x.val.prop, (le_iff_le _ _).mp (fun w => (Real.log_le_iff_le_exp ?_).mp ?_)⟩, rfl⟩
+      · exact pos_iff.mpr (coe_ne_zero x)
+      · rw [mem_closedBall_zero_iff] at hx
+        exact (le_abs_self _).trans (log_le_of_logEmbedding_le hr hx w)
+    refine Set.Finite.of_finite_image ?_ ((coe_injective K).injOn _)
+    refine (Embeddings.finite_of_norm_le K ℂ
+        (Real.exp ((Fintype.card (InfinitePlace K)) * r))).subset ?_
+    rintro _ ⟨x, ⟨⟨h_int, h_le⟩, rfl⟩⟩
+    exact ⟨h_int, h_le⟩
+
+section span_top
+
+/-!
+#### Section `span_top`
+
+In this section, we prove that the span over `ℝ` of the `unitLattice` is equal to the full space.
+For this, we construct for each infinite place `w₁ ≠ w₀` a unit `u_w₁` of `K` such that, for all
+infinite places `w` such that `w ≠ w₁`, we have `Real.log w (u_w₁) < 0`
+(and thus `Real.log w₁ (u_w₁) > 0`). It follows then from a determinant computation
+(using `Matrix.det_ne_zero_of_sum_col_lt_diag`) that the image by `logEmbedding` of these units is
+a `ℝ`-linearly independent family. The unit `u_w₁` is obtained by constructing a sequence `seq n`
+of nonzero algebraic integers that is strictly decreasing at infinite places distinct from `w₁` and
+of norm `≤ B`. Since there are finitely many ideals of norm `≤ B`, there exists two term in the
+sequence defining the same ideal and their quotient is the desired unit `u_w₁` (see `exists_unit`).
+-/
+
+open NumberField.mixedEmbedding NNReal
+
+-- See: https://github.com/leanprover/lean4/issues/2220
+local macro_rules | `($x ^ $y) => `(HPow.hPow $x $y)
+
+variable (w₁ : InfinitePlace K) {B : ℕ} (hB : minkowskiBound K < (convexBodyLtFactor K) * B)
+
+/-- This result shows that there always exists a next term in the sequence. -/
+theorem seq_next {x : 𝓞 K} (hx : x ≠ 0) :
+    ∃ y : 𝓞 K, y ≠ 0 ∧ (∀ w, w ≠ w₁ → w y < w x) ∧ |Algebra.norm ℚ (y : K)| ≤ B := by
+  let f : InfinitePlace K → ℝ≥0 :=
+    fun w => ⟨(w x) / 2, div_nonneg (AbsoluteValue.nonneg _ _) (by norm_num)⟩
+  suffices ∀ w, w ≠ w₁ → f w ≠ 0 by
+    obtain ⟨g, h_geqf, h_gprod⟩ := adjust_f K B this
+    obtain ⟨y, h_ynz, h_yle⟩ := exists_ne_zero_mem_ringOfIntegers_lt (f := g)
+      (by rw [convexBodyLt_volume]; convert hB; exact congr_arg ((↑): NNReal → ENNReal) h_gprod)
+    refine ⟨y, h_ynz, fun w hw => (h_geqf w hw ▸ h_yle w).trans ?_, ?_⟩
+    · rw [← Rat.cast_le (K := ℝ), Rat.cast_coe_nat]
+      calc
+        _ = ∏ w : InfinitePlace K, w y ^ mult w := (prod_eq_abs_norm (y : K)).symm
+        _ ≤ ∏ w : InfinitePlace K, (g w : ℝ) ^ mult w := by
+          refine prod_le_prod ?_ ?_
+          · exact fun _ _ => pow_nonneg (by positivity) _
+          · exact fun w _ => pow_le_pow_of_le_left (by positivity) (le_of_lt (h_yle w)) (mult w)
+        _ ≤ (B : ℝ) := by
+          simp_rw [← NNReal.coe_pow, ← NNReal.coe_prod]
+          exact le_of_eq (congr_arg toReal h_gprod)
+    · refine div_lt_self ?_ (by norm_num)
+      simp only [pos_iff, ne_eq, ZeroMemClass.coe_eq_zero, hx]
+  intro _ _
+  rw [ne_eq, Nonneg.mk_eq_zero, div_eq_zero_iff, map_eq_zero, not_or, ZeroMemClass.coe_eq_zero]
+  exact ⟨hx, by norm_num⟩
+
+/-- An infinite sequence of nonzero algebraic integers of `K` satisfying the following properties:
+• `seq n` is nonzero;
+• for `w : InfinitePlace K`, `w ≠ w₁ → w (seq n+1) < w (seq n)`;
+• `∣norm (seq n)∣ ≤ B`. -/
+def seq : ℕ → { x : 𝓞 K // x ≠ 0 }
+  | 0 => ⟨1, by norm_num⟩
+  | n + 1 =>
+    ⟨(seq_next K w₁ hB (seq n).prop).choose, (seq_next K w₁ hB (seq n).prop).choose_spec.1⟩
+
+/-- The terms of the sequence are nonzero. -/
+theorem seq_ne_zero (n : ℕ) : (seq K w₁ hB n : K) ≠ 0 := by
+  refine (map_ne_zero_iff (algebraMap (𝓞 K) K) ?_).mpr (seq K w₁ hB n).prop
+  exact IsFractionRing.injective { x // x ∈ 𝓞 K } K
+
+/-- The terms of the sequence have nonzero norm. -/
+theorem seq_norm_ne_zero (n : ℕ) : Algebra.norm ℤ (seq K w₁ hB n : 𝓞 K) ≠ 0 :=
+  Algebra.norm_ne_zero_iff.mpr (Subtype.ne_of_val_ne (seq_ne_zero K w₁ hB n))
+
+/-- The sequence is strictly decreasing at infinite places distinct from `w₁`. -/
+theorem seq_decreasing {n m : ℕ} (h : n < m) (w : InfinitePlace K) (hw : w ≠ w₁) :
+     w (seq K w₁ hB m) < w (seq K w₁ hB n) := by
+  induction m with
+  | zero =>
+      exfalso
+      exact Nat.not_succ_le_zero n h
+  | succ m m_ih =>
+      cases eq_or_lt_of_le (Nat.le_of_lt_succ h) with
+      | inl hr =>
+          rw [hr]
+          exact (seq_next K w₁ hB (seq K w₁ hB m).prop).choose_spec.2.1 w hw
+      | inr hr =>
+          refine lt_trans ?_ (m_ih hr)
+          exact (seq_next K w₁ hB (seq K w₁ hB m).prop).choose_spec.2.1 w hw
+
+/-- The terms of the sequence have norm bounded by `B`. -/
+theorem seq_norm_le (n : ℕ) :
+    Int.natAbs (Algebra.norm ℤ (seq K w₁ hB n : 𝓞 K)) ≤ B := by
+  cases n with
+  | zero =>
+      have : 1 ≤ B := by
+        contrapose! hB
+        simp only [Nat.lt_one_iff.mp hB, CharP.cast_eq_zero, mul_zero, zero_le]
+      simp only [ne_eq, seq, map_one, Int.natAbs_one, this]
+  | succ n =>
+      rw [← Nat.cast_le (α := ℚ), Int.cast_natAbs, Int.cast_abs]
+      change |algebraMap ℤ ℚ _| ≤ _
+      rw [← Algebra.norm_localization ℤ (Sₘ := K) (nonZeroDivisors ℤ)]
+      exact (seq_next K w₁ hB (seq K w₁ hB n).prop).choose_spec.2.2
+
+/-- Construct a unit associated to the place `w₁`. The family, for `w₁ ≠ w₀`, formed by the
+image by the `logEmbedding` of these units  is `ℝ`-linearly independent, see
+`unit_lattice_span_eq_top`. -/
+theorem exists_unit (w₁ : InfinitePlace K ) :
+    ∃ u : (𝓞 K)ˣ, ∀ w : InfinitePlace K, w ≠ w₁ → Real.log (w u) < 0 := by
+  obtain ⟨B, hB⟩ : ∃ B : ℕ, minkowskiBound K < (convexBodyLtFactor K) * B := by
+    simp_rw [mul_comm]
+    refine ENNReal.exists_nat_mul_gt ?_ ?_
+    exact ne_of_gt (convexBodyLtFactor_pos K)
+    exact ne_of_lt (minkowskiBound_lt_top K)
+  rsuffices ⟨n, m, hnm, h⟩ : ∃ n m, n < m ∧
+      (Ideal.span ({ (seq K w₁ hB n : 𝓞 K) }) = Ideal.span ({ (seq K w₁ hB m : 𝓞 K) }))
+  · have hu := Ideal.span_singleton_eq_span_singleton.mp h
+    refine ⟨hu.choose, fun w hw => Real.log_neg ?_ ?_⟩
+    · simp only [pos_iff, ne_eq, ZeroMemClass.coe_eq_zero, ne_zero]
+    · calc
+        _ = w ((seq K w₁ hB m : K) * (seq K w₁ hB n : K)⁻¹) := by
+          rw [← congr_arg ((↑) : (𝓞 K) → K) hu.choose_spec, mul_comm, Submonoid.coe_mul,
+            ← mul_assoc, inv_mul_cancel (seq_ne_zero K w₁ hB n), one_mul]
+        _ = w (seq K w₁ hB m) * w (seq K w₁ hB n)⁻¹ := _root_.map_mul _ _ _
+        _ < 1 := by
+          rw [map_inv₀, mul_inv_lt_iff (pos_iff.mpr (seq_ne_zero K w₁ hB n)), mul_one]
+          exact seq_decreasing K w₁ hB hnm w hw
+  refine Set.Finite.exists_lt_map_eq_of_forall_mem
+    (t := { I : Ideal (𝓞 K) | 1 ≤ Ideal.absNorm I ∧ Ideal.absNorm I ≤ B })
+    (fun n => ?_) ?_
+  · rw [Set.mem_setOf_eq, Ideal.absNorm_span_singleton]
+    refine ⟨?_, seq_norm_le K w₁ hB n⟩
+    exact  Nat.one_le_iff_ne_zero.mpr (Int.natAbs_ne_zero.mpr (seq_norm_ne_zero K w₁ hB n))
+  · rw [show { I : Ideal (𝓞 K) | 1 ≤ Ideal.absNorm I ∧ Ideal.absNorm I ≤ B } =
+          (⋃ n ∈ Set.Icc 1 B, { I : Ideal (𝓞 K) | Ideal.absNorm I = n }) by ext; simp]
+    exact Set.Finite.biUnion (Set.finite_Icc _ _) (fun n hn => Ideal.finite_setOf_absNorm_eq hn.1)
+
+theorem unitLattice_span_eq_top :
+    Submodule.span ℝ (unitLattice K : Set ({w : InfinitePlace K // w ≠ w₀} → ℝ)) = ⊤ := by
+  refine le_antisymm (le_top) ?_
+  -- The standard basis
+  let B := Pi.basisFun ℝ {w : InfinitePlace K // w ≠ w₀}
+  -- The image by log_embedding of the family of units constructed above
+  let v := fun w : { w : InfinitePlace K // w ≠ w₀ } => logEmbedding K (exists_unit K w).choose
+  -- To prove the result, it is enough to prove that the family `v` is linearly independent
+  suffices B.det v ≠ 0 by
+    rw [← isUnit_iff_ne_zero, ← is_basis_iff_det] at this
+    rw [← this.2]
+    exact Submodule.span_monotone (fun _ ⟨w, hw⟩ =>
+      ⟨(exists_unit K w).choose, trivial, by rw [← hw]⟩)
+  rw [Basis.det_apply]
+  -- We use a specific lemma to prove that this determinant is nonzero
+  refine det_ne_zero_of_sum_col_lt_diag (fun w => ?_)
+  simp_rw [Real.norm_eq_abs, Basis.coePiBasisFun.toMatrix_eq_transpose, Matrix.transpose_apply]
+  rw [← sub_pos, sum_congr rfl (fun x hx => abs_of_neg ?_), sum_neg_distrib, sub_neg_eq_add,
+    sum_erase_eq_sub (mem_univ _), ← add_comm_sub]
+  refine add_pos_of_nonneg_of_pos ?_ ?_
+  · rw [sub_nonneg]
+    exact le_abs_self _
+  · rw [sum_logEmbedding_component (exists_unit K w).choose]
+    refine mul_pos_of_neg_of_neg ?_ ((exists_unit K w).choose_spec _ w.prop.symm)
+    rw [mult]; split_ifs <;> norm_num
+  · refine mul_neg_of_pos_of_neg ?_ ((exists_unit K w).choose_spec x ?_)
+    · rw [mult]; split_ifs <;> norm_num
+    · exact Subtype.ext_iff_val.not.mp (ne_of_mem_erase hx)
+
+end span_top
+
+end dirichletUnitTheorem
+
+section statements
+
+variable [NumberField K]
+
+open dirichletUnitTheorem FiniteDimensional Classical
+
+/-- The unit rank of the number field `K`, it is equal to `card (InfinitePlace K) - 1`. -/
+def rank : ℕ := Fintype.card (InfinitePlace K) - 1
+
+instance instDiscrete_unitLattice : DiscreteTopology (unitLattice K) := by
+  refine discreteTopology_of_open_singleton_zero ?_
+  refine isOpen_singleton_of_finite_mem_nhds 0 (s := Metric.closedBall 0 1) ?_ ?_
+  · exact Metric.closedBall_mem_nhds _ (by norm_num)
+  · refine Set.Finite.of_finite_image ?_ (Set.injOn_of_injective Subtype.val_injective _)
+    convert unitLattice_inter_ball_finite K 1
+    ext x
+    refine ⟨?_, fun ⟨hx1, hx2⟩ => ⟨⟨x, hx1⟩, hx2, rfl⟩⟩
+    rintro ⟨x, hx, rfl⟩
+    exact ⟨Subtype.mem x, hx⟩
+
+protected theorem finrank_eq_rank :
+    finrank ℝ ({w : InfinitePlace K // w ≠ w₀} → ℝ) = Units.rank K := by
+  simp only [finrank_fintype_fun_eq_card, Fintype.card_subtype_compl,
+    Fintype.card_ofSubsingleton, rank]
+
+instance instModuleFree_unitLattice : Module.Free ℤ (unitLattice K) :=
+  Zlattice.module_free ℝ (unitLattice_span_eq_top K)
+
+instance instModuleFinite_unitLattice : Module.Finite ℤ (unitLattice K) :=
+  Zlattice.module_finite ℝ (unitLattice_span_eq_top K)
+
+@[simp]
+theorem unitLattice_rank :
+    finrank ℤ (unitLattice K) = Units.rank K := by
+  rw [← Units.finrank_eq_rank]
+  exact Zlattice.rank ℝ (unitLattice_span_eq_top K)
+
+/-- The linear equivalence between `unitLattice` and `(𝓞 K)ˣ ⧸ (torsion K)` as an additive
+`ℤ`-module. -/
+def unitLatticeEquiv : (unitLattice K) ≃ₗ[ℤ] Additive ((𝓞 K)ˣ ⧸ (torsion K)) := by
+  refine AddEquiv.toIntLinearEquiv ?_
+  rw [unitLattice, ← AddMonoidHom.range_eq_map (logEmbedding K)]
+  refine (QuotientAddGroup.quotientKerEquivRange (logEmbedding K)).symm.trans ?_
+  refine (QuotientAddGroup.quotientAddEquivOfEq ?_).trans
+    (QuotientAddGroup.quotientKerEquivOfSurjective
+      (MonoidHom.toAdditive (QuotientGroup.mk' (torsion K))) (fun x => ?_))
+  · ext
+    rw [AddMonoidHom.mem_ker, AddMonoidHom.mem_ker, logEmbedding_eq_zero_iff,
+      MonoidHom.toAdditive_apply_apply, ofMul_eq_zero, QuotientGroup.mk'_apply,
+      QuotientGroup.eq_one_iff]
+    rfl
+  · refine ⟨Additive.ofMul x.out', ?_⟩
+    simp only [MonoidHom.toAdditive_apply_apply, toMul_ofMul, QuotientGroup.mk'_apply,
+      QuotientGroup.out_eq']
+    rfl
+
+instance : Module.Free ℤ (Additive ((𝓞 K)ˣ ⧸ (torsion K))) :=
+  (instModuleFree_unitLattice K).of_equiv' (unitLatticeEquiv K)
+
+instance : Module.Finite ℤ (Additive ((𝓞 K)ˣ ⧸ (torsion K))) :=
+  Module.Finite.equiv (unitLatticeEquiv K)
+
+theorem rank_modTorsion :
+    FiniteDimensional.finrank ℤ (Additive ((𝓞 K)ˣ ⧸ (torsion K))) = rank K := by
+  rw [← LinearEquiv.finrank_eq (unitLatticeEquiv K), unitLattice_rank]
+
+/-- A basis of the quotient `(𝓞 K)ˣ ⧸ (torsion K)` seen as an additive ℤ-module. -/
+def basisModTorsion : Basis (Fin (rank K)) ℤ (Additive ((𝓞 K)ˣ ⧸ (torsion K))) :=
+  Basis.reindex (Module.Free.chooseBasis ℤ _) (Fintype.equivOfCardEq <| by
+    rw [← FiniteDimensional.finrank_eq_card_chooseBasisIndex, rank_modTorsion, Fintype.card_fin])
+
+/-- A fundamental system of units of `K`. The units of `fundSystem` are arbitrary lifts of the
+units in `basisModTorsion`. -/
+def fundSystem : Fin (rank K) → (𝓞 K)ˣ :=
+  fun i => Quotient.out' (Additive.toMul (basisModTorsion K i))
+
+/-- The exponents that appear in the unique decomposition of a unit as the product of
+a root of unity and powers of the units of the fundamental system `fundSystem` (see
+`exist_unique_eq_mul_prod`) are given by the representation of the unit of `basisModTorsion`. -/
+theorem fun_eq_repr {x ζ : (𝓞 K)ˣ} {f : Fin (rank K) → ℤ} (hζ : ζ ∈ torsion K)
+    (h : x = ζ * ∏ i, (fundSystem K i) ^ (f i)) :
+    f = (basisModTorsion K).repr (Additive.ofMul ↑x) := by
+  suffices Additive.ofMul ↑x = ∑ i, (f i) • (basisModTorsion K i) by
+    rw [← (basisModTorsion K).repr_sum_self f, ← this]
+  calc
+    Additive.ofMul ↑x = ∑ i, (f i) • Additive.ofMul ↑(fundSystem K i) := by
+                      rw [h, QuotientGroup.mk_mul, (QuotientGroup.eq_one_iff _).mpr hζ, one_mul,
+                        QuotientGroup.mk_prod, ofMul_prod]; rfl
+                    _ = ∑ i, (f i) • (basisModTorsion K i) := by
+                      simp_rw [fundSystem, QuotientGroup.out_eq', ofMul_toMul]
+
+/-- **Dirichlet Unit Theorem**. Any unit `x` of `𝓞 K` can be written uniquely as the product of
+a root of unity and powers of the units of the fundamental system `fundSystem`. -/
+theorem exist_unique_eq_mul_prod (x : (𝓞 K)ˣ) : ∃! (ζ : torsion K) (e : Fin (rank K) → ℤ),
+    x = ζ * ∏ i, (fundSystem K i) ^ (e i) := by
+  let ζ := x * (∏ i, (fundSystem K i) ^ ((basisModTorsion K).repr (Additive.ofMul ↑x) i))⁻¹
+  have h_tors : ζ ∈ torsion K := by
+    rw [← QuotientGroup.eq_one_iff, QuotientGroup.mk_mul, QuotientGroup.mk_inv, ← ofMul_eq_zero,
+      ofMul_mul, ofMul_inv, QuotientGroup.mk_prod, ofMul_prod]
+    simp_rw [QuotientGroup.mk_zpow, ofMul_zpow, fundSystem, QuotientGroup.out_eq', ofMul_toMul]
+    rw [add_eq_zero_iff_eq_neg, neg_neg]
+    exact ((basisModTorsion K).sum_repr (Additive.ofMul ↑x)).symm
+  refine ⟨⟨ζ, h_tors⟩, ?_, ?_⟩
+  · refine ⟨((basisModTorsion K).repr (Additive.ofMul ↑x) : Fin (rank K) → ℤ), ?_, ?_⟩
+    · simp only [_root_.inv_mul_cancel_right]
+    · exact fun _ hf => fun_eq_repr K h_tors hf
+  · rintro η ⟨_, hf, _⟩
+    simp_rw [fun_eq_repr K η.prop hf] at hf
+    ext1; dsimp only
+    nth_rewrite 1 [hf]
+    rw [_root_.mul_inv_cancel_right]
+
+end statements
+
 end NumberField.Units
chore: bump to v4.1.0-rc1 (2nd attempt) (#7216)

Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -124,7 +124,7 @@ def torsionOrder [NumberField K] : ℕ+ := ⟨Fintype.card (torsion K), Fintype.
 
 /-- If `k` does not divide `torsionOrder` then there are no nontrivial roots of unity of
   order dividing `k`. -/
-theorem rootsOfUnity_eq_one [NumberField K] {k : ℕ+} (hc : Nat.coprime k (torsionOrder K)) :
+theorem rootsOfUnity_eq_one [NumberField K] {k : ℕ+} (hc : Nat.Coprime k (torsionOrder K)) :
     ζ ∈ rootsOfUnity k (𝓞 K) ↔ ζ = 1 := by
   rw [mem_rootsOfUnity]
   refine ⟨fun h => ?_, fun h => by rw [h, one_pow]⟩
Revert "chore: bump to v4.1.0-rc1 (#7174)" (#7198)

This reverts commit 6f8e8104. Unfortunately this bump was not linted correctly, as CI did not run runLinter Mathlib.

We can unrevert once that's fixed.

Diff
@@ -124,7 +124,7 @@ def torsionOrder [NumberField K] : ℕ+ := ⟨Fintype.card (torsion K), Fintype.
 
 /-- If `k` does not divide `torsionOrder` then there are no nontrivial roots of unity of
   order dividing `k`. -/
-theorem rootsOfUnity_eq_one [NumberField K] {k : ℕ+} (hc : Nat.Coprime k (torsionOrder K)) :
+theorem rootsOfUnity_eq_one [NumberField K] {k : ℕ+} (hc : Nat.coprime k (torsionOrder K)) :
     ζ ∈ rootsOfUnity k (𝓞 K) ↔ ζ = 1 := by
   rw [mem_rootsOfUnity]
   refine ⟨fun h => ?_, fun h => by rw [h, one_pow]⟩
chore: bump to v4.1.0-rc1 (#7174)

Some changes have already been review and delegated in #6910 and #7148.

The diff that needs looking at is https://github.com/leanprover-community/mathlib4/pull/7174/commits/64d6d07ee18163627c8f517eb31455411921c5ac

The std bump PR was insta-merged already!

Co-authored-by: leanprover-community-mathlib4-bot <leanprover-community-mathlib4-bot@users.noreply.github.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -124,7 +124,7 @@ def torsionOrder [NumberField K] : ℕ+ := ⟨Fintype.card (torsion K), Fintype.
 
 /-- If `k` does not divide `torsionOrder` then there are no nontrivial roots of unity of
   order dividing `k`. -/
-theorem rootsOfUnity_eq_one [NumberField K] {k : ℕ+} (hc : Nat.coprime k (torsionOrder K)) :
+theorem rootsOfUnity_eq_one [NumberField K] {k : ℕ+} (hc : Nat.Coprime k (torsionOrder K)) :
     ζ ∈ rootsOfUnity k (𝓞 K) ↔ ζ = 1 := by
   rw [mem_rootsOfUnity]
   refine ⟨fun h => ?_, fun h => by rw [h, one_pow]⟩
chore: tidy various files (#7132)
Diff
@@ -120,11 +120,11 @@ instance [NumberField K] : Finite (torsion K) := inferInstance
 instance [NumberField K] : IsCyclic (torsion K) := subgroup_units_cyclic _
 
 /-- The order of the torsion subgroup as positive integer. -/
-def torsion_order [NumberField K] : ℕ+ := ⟨Fintype.card (torsion K), Fintype.card_pos⟩
+def torsionOrder [NumberField K] : ℕ+ := ⟨Fintype.card (torsion K), Fintype.card_pos⟩
 
-/-- If `k` does not divide `torsion_order` then there are no nontrivial roots of unity of
+/-- If `k` does not divide `torsionOrder` then there are no nontrivial roots of unity of
   order dividing `k`. -/
-theorem rootsOfUnity_eq_one [NumberField K] {k : ℕ+} (hc : Nat.coprime k (torsion_order K)) :
+theorem rootsOfUnity_eq_one [NumberField K] {k : ℕ+} (hc : Nat.coprime k (torsionOrder K)) :
     ζ ∈ rootsOfUnity k (𝓞 K) ↔ ζ = 1 := by
   rw [mem_rootsOfUnity]
   refine ⟨fun h => ?_, fun h => by rw [h, one_pow]⟩
@@ -136,15 +136,15 @@ theorem rootsOfUnity_eq_one [NumberField K] {k : ℕ+} (hc : Nat.coprime k (tors
     rw [orderOf_submonoid (⟨ζ, hζ⟩ : torsion K)]
     exact orderOf_dvd_card_univ
 
-/-- The group of roots of unity of order dividing `torsion_order` is equal to the torsion
+/-- The group of roots of unity of order dividing `torsionOrder` is equal to the torsion
 group. -/
 theorem rootsOfUnity_eq_torsion [NumberField K] :
-    rootsOfUnity (torsion_order K) (𝓞 K) = torsion K := by
+    rootsOfUnity (torsionOrder K) (𝓞 K) = torsion K := by
   ext ζ
   rw [torsion, mem_rootsOfUnity]
   refine ⟨fun h => ?_, fun h => ?_⟩
   · rw [CommGroup.mem_torsion, isOfFinOrder_iff_pow_eq_one]
-    exact ⟨↑(torsion_order K), (torsion_order K).prop, h⟩
+    exact ⟨↑(torsionOrder K), (torsionOrder K).prop, h⟩
   · exact Subtype.ext_iff.mp (@pow_card_eq_one (torsion K) _ ⟨ζ, h⟩ _)
 
 end torsion
fix: disable autoImplicit globally (#6528)

Autoimplicits are highly controversial and also defeat the performance-improving work in #6474.

The intent of this PR is to make autoImplicit opt-in on a per-file basis, by disabling it in the lakefile and enabling it again with set_option autoImplicit true in the few files that rely on it.

That also keeps this PR small, as opposed to attempting to "fix" files to not need it any more.

I claim that many of the uses of autoImplicit in these files are accidental; situations such as:

  • Assuming variables are in scope, but pasting the lemma in the wrong section
  • Pasting in a lemma from a scratch file without checking to see if the variable names are consistent with the rest of the file
  • Making a copy-paste error between lemmas and forgetting to add an explicit arguments.

Having set_option autoImplicit false as the default prevents these types of mistake being made in the 90% of files where autoImplicits are not used at all, and causes them to be caught by CI during review.

I think there were various points during the port where we encouraged porters to delete the universes u v lines; I think having autoparams for universe variables only would cover a lot of the cases we actually use them, while avoiding any real shortcomings.

A Zulip poll (after combining overlapping votes accordingly) was in favor of this change with 5:5:18 as the no:dontcare:yes vote ratio.

While this PR was being reviewed, a handful of files gained some more likely-accidental autoImplicits. In these places, set_option autoImplicit true has been placed locally within a section, rather than at the top of the file.

Diff
@@ -23,6 +23,8 @@ field `K`.
 number field, units
  -/
 
+set_option autoImplicit true
+
 
 open scoped NumberField
 
perf: add instance shortcut to remove heartbeat bump (#6410)

This removes a maxHeartbeats bump (the only one in the file).

Diff
@@ -111,7 +111,9 @@ instance [NumberField K] : Fintype (torsion K) := by
   · rw [← h_ua]
     exact le_of_eq ((eq_iff_eq _ 1).mp ((mem_torsion K).mp h_tors) φ)
 
-set_option synthInstance.maxHeartbeats 30000 in
+-- a shortcut instance to stop the next instance from timing out
+instance [NumberField K] : Finite (torsion K) := inferInstance
+
 /-- The torsion subgroup is cylic. -/
 instance [NumberField K] : IsCyclic (torsion K) := subgroup_units_cyclic _
 
chore: banish Type _ and Sort _ (#6499)

We remove all possible occurences of Type _ and Sort _ in favor of Type* and Sort*.

This has nice performance benefits.

Diff
@@ -40,7 +40,7 @@ theorem Rat.RingOfIntegers.isUnit_iff {x : 𝓞 ℚ} : IsUnit x ↔ (x : ℚ) =
 
 end Rat
 
-variable (K : Type _) [Field K]
+variable (K : Type*) [Field K]
 
 section IsUnit
 
feat: add instances for intervals (#5957)

Don't mind at all if anyone would like to push refactors or golfs. My main requirement from this PR is that

import Mathlib

example : WellFoundedLT { x : ℕ // x ≤ 37 }ᵒᵈ := inferInstance

works out of the box.

Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Matthew Robert Ballard <matt@mrb.email> Co-authored-by: Xavier Roblot <46200072+xroblot@users.noreply.github.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Jz Pan <acme_pjz@hotmail.com> Co-authored-by: Thomas Browning <tb65536@uw.edu> Co-authored-by: Oliver Nash <github@olivernash.org> Co-authored-by: Christopher Hoskin <christopher.hoskin@gmail.com> Co-authored-by: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> Co-authored-by: Anatole Dedecker <anatolededecker@gmail.com> Co-authored-by: Matthew Robert Ballard <k.buzzard@imperial.ac.uk> Co-authored-by: Peter Nelson <71660771+apnelson1@users.noreply.github.com> Co-authored-by: Rémy Degenne <remydegenne@gmail.com> Co-authored-by: MohanadAhmed <m.a.m.elhassan@gmail.com> Co-authored-by: Mario Carneiro <di.gama@gmail.com> Co-authored-by: damiano <adomani@gmail.com> Co-authored-by: Chris Hughes <chrishughes24@gmail.com> Co-authored-by: Rémy Degenne <Remydegenne@gmail.com> Co-authored-by: Jon Eugster <eugster.jon@gmail.com> Co-authored-by: Kevin Buzzard <k.buzzard@imperial.ac.uk>

Diff
@@ -111,6 +111,7 @@ instance [NumberField K] : Fintype (torsion K) := by
   · rw [← h_ua]
     exact le_of_eq ((eq_iff_eq _ 1).mp ((mem_torsion K).mp h_tors) φ)
 
+set_option synthInstance.maxHeartbeats 30000 in
 /-- The torsion subgroup is cylic. -/
 instance [NumberField K] : IsCyclic (torsion K) := subgroup_units_cyclic _
 
feat(NumberTheory.NumberField.Units): add torsion subgroup (#5748)

We define the torsion subgroup of the units of a number field and prove some results about it, mostly: it is finite, cyclic and an unit is torsion iff its value is 1 at all infinite places. Some results linking to rootsOfUnity are also proved.

This PR also includes a direct coercion from (𝓞 K)ˣ to K that is very convenient, although I am not sure it's done properly.

Diff
@@ -3,7 +3,10 @@ Copyright (c) 2023 Xavier Roblot. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Xavier Roblot
 -/
+import Mathlib.GroupTheory.Torsion
+import Mathlib.NumberTheory.NumberField.Embeddings
 import Mathlib.NumberTheory.NumberField.Norm
+import Mathlib.RingTheory.RootsOfUnity.Basic
 
 #align_import number_theory.number_field.units from "leanprover-community/mathlib"@"00f91228655eecdcd3ac97a7fd8dbcb139fe990a"
 
@@ -13,7 +16,8 @@ We prove results about the group `(𝓞 K)ˣ` of units of the ring of integers `
 field `K`.
 
 ## Main results
-* `isUnit_iff_norm`: an algebraic integer `x : 𝓞 K` is a unit if and only if `|norm ℚ x| = 1`
+* `isUnit_iff_norm`: an algebraic integer `x : 𝓞 K` is a unit if and only if `|norm ℚ x| = 1`.
+* `mem_torsion`: a unit `x : (𝓞 K)ˣ` is torsion iff `w x = 1` for all infinite places of `K`.
 
 ## Tags
 number field, units
@@ -42,10 +46,102 @@ section IsUnit
 
 variable {K}
 
-theorem isUnit_iff_norm [NumberField K] (x : 𝓞 K) :
+theorem isUnit_iff_norm [NumberField K] {x : 𝓞 K} :
     IsUnit x ↔ |(RingOfIntegers.norm ℚ x : ℚ)| = 1 := by
   convert (RingOfIntegers.isUnit_norm ℚ (F := K)).symm
   rw [← abs_one, abs_eq_abs, ← Rat.RingOfIntegers.isUnit_iff]
 #align is_unit_iff_norm isUnit_iff_norm
 
 end IsUnit
+
+namespace NumberField.Units
+
+section coe
+
+theorem coe_injective : Function.Injective ((↑) : (𝓞 K)ˣ → K) :=
+  fun _ _ h => by rwa [SetLike.coe_eq_coe, Units.eq_iff] at h
+
+variable {K}
+
+theorem coe_mul (x y : (𝓞 K)ˣ) : ((x * y : (𝓞 K)ˣ) : K) = (x : K) * (y : K) := rfl
+
+theorem coe_pow (x : (𝓞 K)ˣ) (n : ℕ) : (x ^ n : K) = (x : K) ^ n := by
+  rw [← SubmonoidClass.coe_pow, ← val_pow_eq_pow_val]
+
+theorem coe_zpow (x : (𝓞 K)ˣ) (n : ℤ) : (x ^ n : K) = (x : K) ^ n := by
+  change ((Units.coeHom K).comp (map (algebraMap (𝓞 K) K))) (x ^ n) = _
+  exact map_zpow _ x n
+
+theorem coe_one : ((1 : (𝓞 K)ˣ) : K) = (1 : K) := rfl
+
+theorem coe_neg_one : ((-1 : (𝓞 K)ˣ) : K) = (-1 : K) := rfl
+
+theorem coe_ne_zero (x : (𝓞 K)ˣ) : (x : K) ≠ 0 :=
+  Subtype.coe_injective.ne_iff.mpr (_root_.Units.ne_zero x)
+
+end coe
+
+open NumberField.InfinitePlace
+
+section torsion
+
+/-- The torsion subgroup of the group of units. -/
+def torsion : Subgroup (𝓞 K)ˣ := CommGroup.torsion (𝓞 K)ˣ
+
+theorem mem_torsion {x : (𝓞 K)ˣ} [NumberField K] :
+    x ∈ torsion K ↔ ∀ w : InfinitePlace K, w x = 1 := by
+  rw [eq_iff_eq (x : K) 1, torsion, CommGroup.mem_torsion, isOfFinOrder_iff_pow_eq_one]
+  refine ⟨fun ⟨n, h_pos, h_eq⟩ φ => ?_, fun h => ?_⟩
+  · refine norm_map_one_of_pow_eq_one φ.toMonoidHom (k := ⟨n, h_pos⟩) ?_
+    rw [PNat.mk_coe, ← coe_pow, h_eq, coe_one]
+  · obtain ⟨n, hn, hx⟩ := Embeddings.pow_eq_one_of_norm_eq_one K ℂ x.val.prop h
+    exact ⟨n, hn, by ext; rw [coe_pow, hx, coe_one]⟩
+
+/-- Shortcut instance because Lean tends to time out before finding the general instance. -/
+instance : Nonempty (torsion K) := One.nonempty
+
+/-- The torsion subgroup is finite. -/
+instance [NumberField K] : Fintype (torsion K) := by
+  refine @Fintype.ofFinite _ (Set.finite_coe_iff.mpr ?_)
+  refine Set.Finite.of_finite_image ?_ ((coe_injective K).injOn _)
+  refine (Embeddings.finite_of_norm_le K ℂ 1).subset
+    (fun a ⟨u, ⟨h_tors, h_ua⟩⟩ => ⟨?_, fun φ => ?_⟩)
+  · rw [← h_ua]
+    exact u.val.prop
+  · rw [← h_ua]
+    exact le_of_eq ((eq_iff_eq _ 1).mp ((mem_torsion K).mp h_tors) φ)
+
+/-- The torsion subgroup is cylic. -/
+instance [NumberField K] : IsCyclic (torsion K) := subgroup_units_cyclic _
+
+/-- The order of the torsion subgroup as positive integer. -/
+def torsion_order [NumberField K] : ℕ+ := ⟨Fintype.card (torsion K), Fintype.card_pos⟩
+
+/-- If `k` does not divide `torsion_order` then there are no nontrivial roots of unity of
+  order dividing `k`. -/
+theorem rootsOfUnity_eq_one [NumberField K] {k : ℕ+} (hc : Nat.coprime k (torsion_order K)) :
+    ζ ∈ rootsOfUnity k (𝓞 K) ↔ ζ = 1 := by
+  rw [mem_rootsOfUnity]
+  refine ⟨fun h => ?_, fun h => by rw [h, one_pow]⟩
+  refine orderOf_eq_one_iff.mp (Nat.eq_one_of_dvd_coprimes hc ?_ ?_)
+  · exact orderOf_dvd_of_pow_eq_one h
+  · have hζ : ζ ∈ torsion K := by
+      rw [torsion, CommGroup.mem_torsion, isOfFinOrder_iff_pow_eq_one]
+      exact ⟨k, k.prop, h⟩
+    rw [orderOf_submonoid (⟨ζ, hζ⟩ : torsion K)]
+    exact orderOf_dvd_card_univ
+
+/-- The group of roots of unity of order dividing `torsion_order` is equal to the torsion
+group. -/
+theorem rootsOfUnity_eq_torsion [NumberField K] :
+    rootsOfUnity (torsion_order K) (𝓞 K) = torsion K := by
+  ext ζ
+  rw [torsion, mem_rootsOfUnity]
+  refine ⟨fun h => ?_, fun h => ?_⟩
+  · rw [CommGroup.mem_torsion, isOfFinOrder_iff_pow_eq_one]
+    exact ⟨↑(torsion_order K), (torsion_order K).prop, h⟩
+  · exact Subtype.ext_iff.mp (@pow_card_eq_one (torsion K) _ ⟨ζ, h⟩ _)
+
+end torsion
+
+end NumberField.Units
chore: make ringOfIntegersAlgebra an instance (#6244)

Co-authored-by: Eric Wieser <wieser.eric@gmail.com>

Diff
@@ -40,8 +40,6 @@ variable (K : Type _) [Field K]
 
 section IsUnit
 
-attribute [local instance] NumberField.ringOfIntegersAlgebra
-
 variable {K}
 
 theorem isUnit_iff_norm [NumberField K] (x : 𝓞 K) :
chore: script to replace headers with #align_import statements (#5979)

Open in Gitpod

Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -2,14 +2,11 @@
 Copyright (c) 2023 Xavier Roblot. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Xavier Roblot
-
-! This file was ported from Lean 3 source module number_theory.number_field.units
-! leanprover-community/mathlib commit 00f91228655eecdcd3ac97a7fd8dbcb139fe990a
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
 -/
 import Mathlib.NumberTheory.NumberField.Norm
 
+#align_import number_theory.number_field.units from "leanprover-community/mathlib"@"00f91228655eecdcd3ac97a7fd8dbcb139fe990a"
+
 /-!
 # Units of a number field
 We prove results about the group `(𝓞 K)ˣ` of units of the ring of integers `𝓞 K` of a number
feat: port NumberTheory.NumberField.Units (#5359)

Dependencies 10 + 734

735 files ported (98.7%)
299561 lines ported (98.9%)
Show graph

The unported dependencies are