docs: def sieve_of_eratosthenes(p_min=2, p_max=None):
  
      """ Generator of prime numbers using the sieve of Eratosthenes.
  
      Note:
          Adapted from http://code.activestate.com/recipes/117119/
  
      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")
  
      sieve = {}
      q = 2
  
      while p_max is None or q <= p_max:
          if q not in sieve:
              if q >= p_min:
                  yield q
              sieve[q * q] = [q]
          else:
              for p in sieve[q]:
                  sieve.setdefault(p + q, []).append(p)
              del sieve[q]
  
          q += 1