File: Mathlib/NumberTheory/SmoothNumbers.lean

full_name: Nat.primesBelow
code: /-- `primesBelow n` is the set of primes less than `n` as a `Finset`. -/
def primesBelow (n : ℕ) : Finset ℕ 
goal: Finset ℕ

full_name: Nat.primesBelow_zero
code: @[simp]
lemma primesBelow_zero : primesBelow 0 = ∅ 
goal: Nat.primesBelow 0 = ∅

full_name: Nat.mem_primesBelow
code: lemma mem_primesBelow {k n : ℕ} :
    n ∈ primesBelow k ↔ n < k ∧ n.Prime 
goal: n ∈ k.primesBelow ↔ n < k ∧ Nat.Prime n

full_name: Nat.prime_of_mem_primesBelow
code: lemma prime_of_mem_primesBelow {p n : ℕ} (h : p ∈ n.primesBelow) : p.Prime 
goal: Nat.Prime p

full_name: Nat.lt_of_mem_primesBelow
code: lemma lt_of_mem_primesBelow {p n : ℕ} (h : p ∈ n.primesBelow) : p < n 
goal: p < n

full_name: Nat.primesBelow_succ
code: lemma primesBelow_succ (n : ℕ) :
    primesBelow n.succ = if n.Prime then insert n (primesBelow n) else primesBelow n 
goal: n.succ.primesBelow = if Nat.Prime n then insert n n.primesBelow else n.primesBelow

full_name: Nat.not_mem_primesBelow
code: lemma not_mem_primesBelow (n : ℕ) : n ∉ primesBelow n 
goal: n ∉ n.primesBelow

full_name: Nat.factoredNumbers
code: /-- `factoredNumbers s`, for a finite set `s` of natural numbers, is the set of positive natural
numbers all of whose prime factors are in `s`. -/
def factoredNumbers (s : Finset ℕ) : Set ℕ 
goal: Set ℕ

full_name: Nat.mem_factoredNumbers
code: lemma mem_factoredNumbers {s : Finset ℕ} {m : ℕ} :
    m ∈ factoredNumbers s ↔ m ≠ 0 ∧ ∀ p ∈ primeFactorsList m, p ∈ s 
goal: m ∈ Nat.factoredNumbers s ↔ m ≠ 0 ∧ ∀ p ∈ m.primeFactorsList, p ∈ s

full_name: Nat.instDecidablePredMemSetFactoredNumbers
code: /-- Membership in `Nat.factoredNumbers n` is decidable. -/
instance (s : Finset ℕ) : DecidablePred (· ∈ factoredNumbers s) 
goal: DecidablePred fun x => x ∈ Nat.factoredNumbers s

full_name: Nat.mem_factoredNumbers_of_dvd
code: /-- A number that divides an `s`-factored number is itself `s`-factored. -/
lemma mem_factoredNumbers_of_dvd {s : Finset ℕ} {m k : ℕ} (h : m ∈ factoredNumbers s)
    (h' : k ∣ m) :
    k ∈ factoredNumbers s 
goal: k ∈ Nat.factoredNumbers s

full_name: Nat.mem_factoredNumbers_iff_forall_le
code: /-- `m` is `s`-factored if and only if `m` is nonzero and all prime divisors `≤ m` of `m`
are in `s`. -/
lemma mem_factoredNumbers_iff_forall_le {s : Finset ℕ} {m : ℕ} :
    m ∈ factoredNumbers s ↔ m ≠ 0 ∧ ∀ p ≤ m, p.Prime → p ∣ m → p ∈ s 
goal: m ∈ Nat.factoredNumbers s ↔ m ≠ 0 ∧ ∀ p ≤ m, Nat.Prime p → p ∣ m → p ∈ s

full_name: Nat.mem_factoredNumbers'
code: /-- `m` is `s`-factored if and only if all prime divisors of `m` are in `s`. -/
lemma mem_factoredNumbers' {s : Finset ℕ} {m : ℕ} :
    m ∈ factoredNumbers s ↔ ∀ p, p.Prime → p ∣ m → p ∈ s 
goal: m ∈ Nat.factoredNumbers s ↔ ∀ (p : ℕ), Nat.Prime p → p ∣ m → p ∈ s

full_name: Nat.ne_zero_of_mem_factoredNumbers
code: lemma ne_zero_of_mem_factoredNumbers {s : Finset ℕ} {m : ℕ} (h : m ∈ factoredNumbers s) : m ≠ 0 
goal: m ≠ 0

full_name: Nat.primeFactors_subset_of_mem_factoredNumbers
code: /-- The `Finset` of prime factors of an `s`-factored number is contained in `s`. -/
lemma primeFactors_subset_of_mem_factoredNumbers {s : Finset ℕ} {m : ℕ}
    (hm : m ∈ factoredNumbers s) :
    m.primeFactors ⊆ s 
goal: m.primeFactors ⊆ s

full_name: Nat.mem_factoredNumbers_of_primeFactors_subset
code: /-- If `m ≠ 0` and the `Finset` of prime factors of `m` is contained in `s`, then `m`
is `s`-factored. -/
lemma mem_factoredNumbers_of_primeFactors_subset {s : Finset ℕ} {m : ℕ} (hm : m ≠ 0)
    (hp : m.primeFactors ⊆ s) :
    m ∈ factoredNumbers s 
goal: m ∈ Nat.factoredNumbers s

full_name: Nat.mem_factoredNumbers_iff_primeFactors_subset
code: /-- `m` is `s`-factored if and only if `m ≠ 0` and its `Finset` of prime factors
is contained in `s`. -/
lemma mem_factoredNumbers_iff_primeFactors_subset {s : Finset ℕ} {m : ℕ} :
    m ∈ factoredNumbers s ↔ m ≠ 0 ∧ m.primeFactors ⊆ s 
goal: m ∈ Nat.factoredNumbers s ↔ m ≠ 0 ∧ m.primeFactors ⊆ s

full_name: Nat.factoredNumbers_empty
code: @[simp]
lemma factoredNumbers_empty : factoredNumbers ∅ = {1} 
goal: Nat.factoredNumbers ∅ = {1}

full_name: Nat.mul_mem_factoredNumbers
code: /-- The product of two `s`-factored numbers is again `s`-factored. -/
lemma mul_mem_factoredNumbers {s : Finset ℕ} {m n : ℕ} (hm : m ∈ factoredNumbers s)
    (hn : n ∈ factoredNumbers s) :
    m * n ∈ factoredNumbers s 
goal: m * n ∈ Nat.factoredNumbers s

full_name: Nat.prod_mem_factoredNumbers
code: /-- The product of the prime factors of `n` that are in `s` is an `s`-factored number. -/
lemma prod_mem_factoredNumbers (s : Finset ℕ) (n : ℕ) :
    (n.primeFactorsList.filter (· ∈ s)).prod ∈ factoredNumbers s 
goal: (List.filter (fun x => decide (x ∈ s)) n.primeFactorsList).prod ∈ Nat.factoredNumbers s

full_name: Nat.factoredNumbers_insert
code: /-- The sets of `s`-factored and of `s ∪ {N}`-factored numbers are the same when `N` is not prime.
See `Nat.equivProdNatFactoredNumbers` for when `N` is prime. -/
lemma factoredNumbers_insert (s : Finset ℕ) {N : ℕ} (hN : ¬ N.Prime) :
    factoredNumbers (insert N s) = factoredNumbers s 
goal: Nat.factoredNumbers (insert N s) = Nat.factoredNumbers s

full_name: Nat.factoredNumbers_mono
code: @[gcongr] lemma factoredNumbers_mono {s t : Finset ℕ} (hst : s ≤ t) :
    factoredNumbers s ⊆ factoredNumbers t 
goal: Nat.factoredNumbers s ⊆ Nat.factoredNumbers t

full_name: Nat.factoredNumbers_compl
code: /-- The non-zero non-`s`-factored numbers are `≥ N` when `s` contains all primes less than `N`. -/
lemma factoredNumbers_compl {N : ℕ} {s : Finset ℕ} (h : primesBelow N ≤ s) :
    (factoredNumbers s)ᶜ \ {0} ⊆ {n | N ≤ n} 
goal: (Nat.factoredNumbers s)ᶜ \ {0} ⊆ {n | N ≤ n}

full_name: Nat.pow_mul_mem_factoredNumbers
code: /-- If `p` is a prime and `n` is `s`-factored, then every product `p^e * n`
is `s ∪ {p}`-factored. -/
lemma pow_mul_mem_factoredNumbers {s : Finset ℕ} {p n : ℕ} (hp : p.Prime) (e : ℕ)
    (hn : n ∈ factoredNumbers s) :
    p ^ e * n ∈ factoredNumbers (insert p s) 
goal: p ^ e * n ∈ Nat.factoredNumbers (insert p s)

full_name: Nat.Prime.factoredNumbers_coprime
code: /-- If `p ∉ s` is a prime and `n` is `s`-factored, then `p` and `n` are coprime. -/
lemma Prime.factoredNumbers_coprime {s : Finset ℕ} {p n : ℕ} (hp : p.Prime) (hs : p ∉ s)
    (hn : n ∈ factoredNumbers s) :
    Nat.Coprime p n 
goal: p.Coprime n

full_name: Nat.factoredNumbers.map_prime_pow_mul
code: /-- If `f : ℕ → F` is multiplicative on coprime arguments, `p ∉ s` is a prime and `m`
is `s`-factored, then `f (p^e * m) = f (p^e) * f m`. -/
lemma factoredNumbers.map_prime_pow_mul {F : Type*} [CommSemiring F] {f : ℕ → F}
    (hmul : ∀ {m n}, Coprime m n → f (m * n) = f m * f n) {s : Finset ℕ} {p : ℕ}
    (hp : p.Prime) (hs : p ∉ s) (e : ℕ) {m : factoredNumbers s} :
    f (p ^ e * m) = f (p ^ e) * f m 
goal: f (p ^ e * ↑m) = f (p ^ e) * f ↑m

full_name: Nat.equivProdNatFactoredNumbers
code: /-- We establish the bijection from `ℕ × factoredNumbers s` to `factoredNumbers (s ∪ {p})`
given by `(e, n) ↦ p^e * n` when `p ∉ s` is a prime. See `Nat.factoredNumbers_insert` for
when `p` is not prime. -/
def equivProdNatFactoredNumbers {s : Finset ℕ} {p : ℕ} (hp : p.Prime) (hs : p ∉ s) :
    ℕ × factoredNumbers s ≃ factoredNumbers (insert p s) 
goal: ℕ × ↑(Nat.factoredNumbers s) ≃ ↑(Nat.factoredNumbers (insert p s))

full_name: Nat.equivProdNatFactoredNumbers_apply
code: @[simp]
lemma equivProdNatFactoredNumbers_apply {s : Finset ℕ} {p e m : ℕ} (hp : p.Prime) (hs : p ∉ s)
    (hm : m ∈ factoredNumbers s) :
    equivProdNatFactoredNumbers hp hs (e, ⟨m, hm⟩) = p ^ e * m 
goal: ↑((Nat.equivProdNatFactoredNumbers hp hs) (e, ⟨m, hm⟩)) = p ^ e * m

full_name: Nat.equivProdNatFactoredNumbers_apply'
code: @[simp]
lemma equivProdNatFactoredNumbers_apply' {s : Finset ℕ} {p : ℕ} (hp : p.Prime) (hs : p ∉ s)
    (x : ℕ × factoredNumbers s) :
    equivProdNatFactoredNumbers hp hs x = p ^ x.1 * x.2 
goal: ↑((Nat.equivProdNatFactoredNumbers hp hs) x) = p ^ x.1 * ↑x.2

full_name: Nat.smoothNumbers
code: /-- `smoothNumbers n` is the set of *`n`-smooth positive natural numbers*, i.e., the
positive natural numbers all of whose prime factors are less than `n`. -/
def smoothNumbers (n : ℕ) : Set ℕ 
goal: Set ℕ

full_name: Nat.mem_smoothNumbers
code: lemma mem_smoothNumbers {n m : ℕ} : m ∈ smoothNumbers n ↔ m ≠ 0 ∧ ∀ p ∈ primeFactorsList m, p < n 
goal: m ∈ n.smoothNumbers ↔ m ≠ 0 ∧ ∀ p ∈ m.primeFactorsList, p < n

full_name: Nat.smoothNumbers_eq_factoredNumbers
code: /-- The `n`-smooth numbers agree with the `Finset.range n`-factored numbers. -/
lemma smoothNumbers_eq_factoredNumbers (n : ℕ) :
    smoothNumbers n = factoredNumbers (Finset.range n) 
goal: n.smoothNumbers = Nat.factoredNumbers (Finset.range n)

full_name: Nat.smmoothNumbers_eq_factoredNumbers_primesBelow
code: /-- The `n`-smooth numbers agree with the `primesBelow n`-factored numbers. -/
lemma smmoothNumbers_eq_factoredNumbers_primesBelow (n : ℕ) :
    smoothNumbers n = factoredNumbers n.primesBelow 
goal: n.smoothNumbers = Nat.factoredNumbers n.primesBelow

full_name: Nat.instDecidablePredMemSetSmoothNumbers
code: /-- Membership in `Nat.smoothNumbers n` is decidable. -/
instance (n : ℕ) : DecidablePred (· ∈ smoothNumbers n) 
goal: DecidablePred fun x => x ∈ n.smoothNumbers

full_name: Nat.mem_smoothNumbers_of_dvd
code: /-- A number that divides an `n`-smooth number is itself `n`-smooth. -/
lemma mem_smoothNumbers_of_dvd {n m k : ℕ} (h : m ∈ smoothNumbers n) (h' : k ∣ m) :
    k ∈ smoothNumbers n 
goal: k ∈ n.smoothNumbers

full_name: Nat.mem_smoothNumbers_iff_forall_le
code: /-- `m` is `n`-smooth if and only if `m` is nonzero and all prime divisors `≤ m` of `m`
are less than `n`. -/
lemma mem_smoothNumbers_iff_forall_le {n m : ℕ} :
    m ∈ smoothNumbers n ↔ m ≠ 0 ∧ ∀ p ≤ m, p.Prime → p ∣ m → p < n 
goal: m ∈ n.smoothNumbers ↔ m ≠ 0 ∧ ∀ p ≤ m, Nat.Prime p → p ∣ m → p < n

full_name: Nat.mem_smoothNumbers'
code: /-- `m` is `n`-smooth if and only if all prime divisors of `m` are less than `n`. -/
lemma mem_smoothNumbers' {n m : ℕ} : m ∈ smoothNumbers n ↔ ∀ p, p.Prime → p ∣ m → p < n 
goal: m ∈ n.smoothNumbers ↔ ∀ (p : ℕ), Nat.Prime p → p ∣ m → p < n

full_name: Nat.primeFactors_subset_of_mem_smoothNumbers
code: /-- The `Finset` of prime factors of an `n`-smooth number is contained in the `Finset`
of primes below `n`. -/
lemma primeFactors_subset_of_mem_smoothNumbers {m n : ℕ} (hms : m ∈ n.smoothNumbers) :
    m.primeFactors ⊆ n.primesBelow 
goal: m.primeFactors ⊆ n.primesBelow

full_name: Nat.mem_smoothNumbers_of_primeFactors_subset
code: /-- `m` is an `n`-smooth number if the `Finset` of its prime factors consists of numbers `< n`. -/
lemma mem_smoothNumbers_of_primeFactors_subset {m n : ℕ} (hm : m ≠ 0)
    (hp : m.primeFactors ⊆ Finset.range n) : m ∈ n.smoothNumbers 
goal: m ∈ n.smoothNumbers

full_name: Nat.mem_smoothNumbers_iff_primeFactors_subset
code: /-- `m` is an `n`-smooth number if and only if `m ≠ 0` and the `Finset` of its prime factors
is contained in the `Finset` of primes below `n` -/
lemma mem_smoothNumbers_iff_primeFactors_subset {m n : ℕ} :
    m ∈ n.smoothNumbers ↔ m ≠ 0 ∧ m.primeFactors ⊆ n.primesBelow 
goal: m ∈ n.smoothNumbers ↔ m ≠ 0 ∧ m.primeFactors ⊆ n.primesBelow

full_name: Nat.ne_zero_of_mem_smoothNumbers
code: /-- Zero is never a smooth number -/
lemma ne_zero_of_mem_smoothNumbers {n m : ℕ} (h : m ∈ smoothNumbers n) : m ≠ 0 
goal: m ≠ 0

full_name: Nat.smoothNumbers_zero
code: @[simp]
lemma smoothNumbers_zero : smoothNumbers 0 = {1} 
goal: Nat.smoothNumbers 0 = {1}

full_name: Nat.mul_mem_smoothNumbers
code: /-- The product of two `n`-smooth numbers is an `n`-smooth number. -/
theorem mul_mem_smoothNumbers {m₁ m₂ n : ℕ}
    (hm1 : m₁ ∈ n.smoothNumbers) (hm2 : m₂ ∈ n.smoothNumbers) : m₁ * m₂ ∈ n.smoothNumbers 
goal: m₁ * m₂ ∈ n.smoothNumbers

full_name: Nat.prod_mem_smoothNumbers
code: /-- The product of the prime factors of `n` that are less than `N` is an `N`-smooth number. -/
lemma prod_mem_smoothNumbers (n N : ℕ) :
    (n.primeFactorsList.filter (· < N)).prod ∈ smoothNumbers N 
goal: (List.filter (fun x => decide (x < N)) n.primeFactorsList).prod ∈ N.smoothNumbers

full_name: Nat.smoothNumbers_succ
code: /-- The sets of `N`-smooth and of `(N+1)`-smooth numbers are the same when `N` is not prime.
See `Nat.equivProdNatSmoothNumbers` for when `N` is prime. -/
lemma smoothNumbers_succ {N : ℕ} (hN : ¬ N.Prime) : N.succ.smoothNumbers = N.smoothNumbers 
goal: N.succ.smoothNumbers = N.smoothNumbers

full_name: Nat.smoothNumbers_one
code: @[simp] lemma smoothNumbers_one : smoothNumbers 1 = {1} 
goal: Nat.smoothNumbers 1 = {1}

full_name: Nat.smoothNumbers_mono
code: @[gcongr] lemma smoothNumbers_mono {N M : ℕ} (hNM : N ≤ M) : N.smoothNumbers ⊆ M.smoothNumbers 
goal: N.smoothNumbers ⊆ M.smoothNumbers

full_name: Nat.mem_smoothNumbers_of_lt
code: /-- All `m`, `0 < m < n` are `n`-smooth numbers -/
lemma mem_smoothNumbers_of_lt {m n : ℕ} (hm : 0 < m) (hmn : m < n) : m ∈ n.smoothNumbers 
goal: m ∈ n.smoothNumbers

full_name: Nat.smoothNumbers_compl
code: /-- The non-zero non-`N`-smooth numbers are `≥ N`. -/
lemma smoothNumbers_compl (N : ℕ) : (N.smoothNumbers)ᶜ \ {0} ⊆ {n | N ≤ n} 
goal: N.smoothNumbersᶜ \ {0} ⊆ {n | N ≤ n}

full_name: Nat.pow_mul_mem_smoothNumbers
code: /-- If `p` is positive and `n` is `p`-smooth, then every product `p^e * n` is `(p+1)`-smooth. -/
lemma pow_mul_mem_smoothNumbers {p n : ℕ} (hp : p ≠ 0) (e : ℕ) (hn : n ∈ smoothNumbers p) :
    p ^ e * n ∈ smoothNumbers (succ p) 
goal: p ^ e * n ∈ p.succ.smoothNumbers

full_name: Nat.Prime.smoothNumbers_coprime
code: /-- If `p` is a prime and `n` is `p`-smooth, then `p` and `n` are coprime. -/
lemma Prime.smoothNumbers_coprime {p n : ℕ} (hp : p.Prime) (hn : n ∈ smoothNumbers p) :
    Nat.Coprime p n 
goal: p.Coprime n

full_name: Nat.map_prime_pow_mul
code: /-- If `f : ℕ → F` is multiplicative on coprime arguments, `p` is a prime and `m` is `p`-smooth,
then `f (p^e * m) = f (p^e) * f m`. -/
lemma map_prime_pow_mul {F : Type*} [CommSemiring F] {f : ℕ → F}
    (hmul : ∀ {m n}, Nat.Coprime m n → f (m * n) = f m * f n) {p : ℕ} (hp : p.Prime) (e : ℕ)
    {m : p.smoothNumbers} :
    f (p ^ e * m) = f (p ^ e) * f m 
goal: f (p ^ e * ↑m) = f (p ^ e) * f ↑m

full_name: Nat.equivProdNatSmoothNumbers
code: /-- We establish the bijection from `ℕ × smoothNumbers p` to `smoothNumbers (p+1)`
given by `(e, n) ↦ p^e * n` when `p` is a prime. See `Nat.smoothNumbers_succ` for
when `p` is not prime. -/
def equivProdNatSmoothNumbers {p : ℕ} (hp : p.Prime) :
    ℕ × smoothNumbers p ≃ smoothNumbers p.succ 
goal: ℕ × ↑p.smoothNumbers ≃ ↑p.succ.smoothNumbers

full_name: Nat.equivProdNatSmoothNumbers_apply
code: @[simp]
lemma equivProdNatSmoothNumbers_apply {p e m : ℕ} (hp : p.Prime) (hm : m ∈ p.smoothNumbers) :
    equivProdNatSmoothNumbers hp (e, ⟨m, hm⟩) = p ^ e * m 
goal: ↑((Nat.equivProdNatSmoothNumbers hp) (e, ⟨m, hm⟩)) = p ^ e * m

full_name: Nat.equivProdNatSmoothNumbers_apply'
code: @[simp]
lemma equivProdNatSmoothNumbers_apply' {p : ℕ} (hp : p.Prime) (x : ℕ × p.smoothNumbers) :
    equivProdNatSmoothNumbers hp x = p ^ x.1 * x.2 
goal: ↑((Nat.equivProdNatSmoothNumbers hp) x) = p ^ x.1 * ↑x.2

full_name: Nat.smoothNumbersUpTo
code: /-- The `k`-smooth numbers up to and including `N` as a `Finset` -/
def smoothNumbersUpTo (N k : ℕ) : Finset ℕ 
goal: Finset ℕ

full_name: Nat.mem_smoothNumbersUpTo
code: lemma mem_smoothNumbersUpTo {N k n : ℕ} :
    n ∈ smoothNumbersUpTo N k ↔ n ≤ N ∧ n ∈ smoothNumbers k 
goal: n ∈ N.smoothNumbersUpTo k ↔ n ≤ N ∧ n ∈ k.smoothNumbers

full_name: Nat.roughNumbersUpTo
code: /-- The positive non-`k`-smooth (so "`k`-rough") numbers up to and including `N` as a `Finset` -/
def roughNumbersUpTo (N k : ℕ) : Finset ℕ 
goal: Finset ℕ

full_name: Nat.smoothNumbersUpTo_card_add_roughNumbersUpTo_card
code: lemma smoothNumbersUpTo_card_add_roughNumbersUpTo_card (N k : ℕ) :
    (smoothNumbersUpTo N k).card + (roughNumbersUpTo N k).card = N 
goal: (N.smoothNumbersUpTo k).card + (N.roughNumbersUpTo k).card = N

full_name: Nat.eq_prod_primes_mul_sq_of_mem_smoothNumbers
code: /-- A `k`-smooth number can be written as a square times a product of distinct primes `< k`. -/
lemma eq_prod_primes_mul_sq_of_mem_smoothNumbers {n k : ℕ} (h : n ∈ smoothNumbers k) :
    ∃ s ∈ k.primesBelow.powerset, ∃ m, n = m ^ 2 * (s.prod id) 
goal: ∃ s ∈ k.primesBelow.powerset, ∃ m, n = m ^ 2 * s.prod id

full_name: Nat.smoothNumbersUpTo_subset_image
code: /-- The set of `k`-smooth numbers `≤ N` is contained in the set of numbers of the form `m^2 * P`,
where `m ≤ √N` and `P` is a product of distinct primes `< k`. -/
lemma smoothNumbersUpTo_subset_image (N k : ℕ) :
    smoothNumbersUpTo N k ⊆ Finset.image (fun (s, m) ↦ m ^ 2 * (s.prod id))
      (k.primesBelow.powerset ×ˢ (Finset.range N.sqrt.succ).erase 0) 
goal: N.smoothNumbersUpTo k ⊆
  Finset.image
    (fun x =>
      match x with
      | (s, m) => m ^ 2 * s.prod id)
    (k.primesBelow.powerset ×ˢ (Finset.range N.sqrt.succ).erase 0)

full_name: Nat.smoothNumbersUpTo_card_le
code: /-- The cardinality of the set of `k`-smooth numbers `≤ N` is bounded by `2^π(k-1) * √N`. -/
lemma smoothNumbersUpTo_card_le (N k : ℕ) :
    (smoothNumbersUpTo N k).card ≤ 2 ^ k.primesBelow.card * N.sqrt 
goal: (N.smoothNumbersUpTo k).card ≤ 2 ^ k.primesBelow.card * N.sqrt

full_name: Nat.roughNumbersUpTo_eq_biUnion
code: /-- The set of `k`-rough numbers `≤ N` can be written as the union of the sets of multiples `≤ N`
of primes `k ≤ p ≤ N`. -/
lemma roughNumbersUpTo_eq_biUnion (N k) :
    roughNumbersUpTo N k =
      (N.succ.primesBelow \ k.primesBelow).biUnion
        fun p ↦ (Finset.range N.succ).filter (fun m ↦ m ≠ 0 ∧ p ∣ m) 
goal: N.roughNumbersUpTo k =
  (N.succ.primesBelow \ k.primesBelow).biUnion fun p => Finset.filter (fun m => m ≠ 0 ∧ p ∣ m) (Finset.range N.succ)

full_name: Nat.roughNumbersUpTo_card_le
code: /-- The cardinality of the set of `k`-rough numbers `≤ N` is bounded by the sum of `⌊N/p⌋`
over the primes `k ≤ p ≤ N`. -/
lemma roughNumbersUpTo_card_le (N k : ℕ) :
    (roughNumbersUpTo N k).card ≤ (N.succ.primesBelow \ k.primesBelow).sum (fun p ↦ N / p) 
goal: (N.roughNumbersUpTo k).card ≤ ∑ p ∈ N.succ.primesBelow \ k.primesBelow, N / p