docs: def prime_generator(p_min=2, p_max=None):
  
      """ Generator of prime numbers using the sieve of Eratosthenes.
  
      Args:
          p_min (int): prime numbers lower than p_min will not be in the resulting primes
          p_max (int): the generator will stop when this value is reached, it means that there
              will be no prime bigger than this number in the resulting primes. If p_max
              is None, there will not be any upper limit
  
      Returns:
          A generator of all the consecutive primes between p_min and p_max
  
      Raises:
          TypeError: if p_min or p_max is not an integer
  
      """
  
      if not isinstance(p_min, int):
          raise TypeError("Expecting an integer")
      if p_max is not None and not isinstance(p_max, int):
          raise TypeError("Expecting an integer")
  
      q = max(p_min, 3)
      if q % 2 == 0:
          q += 1
      if p_min <= 2 and (p_max is None or p_max >= 2):
          yield 2  # outside the while block to make the double increment optimization work
  
      while p_max is None or q <= p_max:
          if is_prime(q):
              yield q
          q += 2