docs: def ask_geno(self, number=None, xmean=None, sigma_fac=1):
          """get new candidate solutions in genotyp, sampled from a
          multi-variate normal distribution.
  
          Arguments are
              `number`
                  number of returned solutions, by default the
                  population size `popsize` (AKA lambda).
              `xmean`
                  distribution mean
              `sigma_fac`
                  multiplier for internal sample width (standard
                  deviation)
  
          `ask_geno` returns a list of N-dimensional candidate solutions
          in genotyp representation and is called by `ask`.
  
          Details: updates the sample distribution and might change
          the geno-pheno transformation during this update.
  
          :See: `ask`, `ask_and_eval`
  
          """
  
          if number is None or number < 1:
              number = self.sp.popsize
  
          # update distribution, might change self.mean
          if self.sp.CMA_on and (
                  (self.opts['updatecovwait'] is None and
                   self.countiter >=
                       self.itereigenupdated + 1. / (self.sp.c1 + self.sp.cmu) / self.N / 10
                   ) or
                  (self.opts['updatecovwait'] is not None and
                   self.countiter > self.itereigenupdated + self.opts['updatecovwait']
                   ) or
                  (self.sp.neg.cmuexp * (self.countiter - self.itereigenupdated) > 0.5
                  )  # TODO (minor): not sure whether this is "the right" criterion
              ):
              self.updateBD()
          if xmean is None:
              xmean = self.mean
          else:
              try:
                  xmean = self.archive[xmean]['geno']
                  # noise handling after call of tell
              except KeyError:
                  try:
                      xmean = self.sent_solutions[xmean]['geno']
                      # noise handling before calling tell
                  except KeyError:
                      pass
  
          if self.countiter == 0:
              self.tic = time.clock()  # backward compatible
              self.elapsed_time = ElapsedTime()
  
          sigma = sigma_fac * self.sigma
  
          # update parameters for sampling the distribution
          #        fac  0      1      10
          # 150-D cigar:
          #           50749  50464   50787
          # 200-D elli:               == 6.9
          #                  99900   101160
          #                 100995   103275 == 2% loss
          # 100-D elli:               == 6.9
          #                 363052   369325  < 2% loss
          #                 365075   365755
  
          # sample distribution
          if self._flgtelldone:  # could be done in tell()!?
              self._flgtelldone = False
              self.ary = []
  
          # check injections from pop_injection_directions
          arinj = []
          if hasattr(self, 'pop_injection_directions'):
              if self.countiter < 4 and \
                      len(self.pop_injection_directions) > self.popsize - 2:
                  _print_warning('  %d special injected samples with popsize %d, '
                                    % (len(self.pop_injection_directions), self.popsize)
                                 + "popsize %d will be used" % (len(self.pop_injection_directions) + 2)
                                 + (" and the warning is suppressed in the following" if self.countiter == 3 else ""))
              while self.pop_injection_directions:
                  y = self.pop_injection_directions.pop(0)
                  if self.opts['CMA_sample_on_sphere_surface']:
                      y *= (self.N**0.5 if self.opts['CSA_squared'] else
                            self.const.chiN) / self.mahalanobis_norm(y)
                      arinj.append(y)
                  else:
                      y *= self.random_rescaling_factor_to_mahalanobis_size(y) / self.sigma
                      arinj.append(y)
          # each row is a solution
          # the 1 is a small safeguard which needs to be removed to implement "pure" adaptive encoding
          arz = self.randn((max([1, (number - len(arinj))]), self.N))
          if self.opts['CMA_sample_on_sphere_surface']:  # normalize the length to chiN
              for i in rglen((arz)):
                  ss = sum(arz[i]**2)
                  if 1 < 3 or ss > self.N + 10.1:
                      arz[i] *= (self.N**0.5 if self.opts['CSA_squared']
                                             else self.const.chiN) / ss**0.5
              # or to average
              # arz *= 1 * self.const.chiN / np.mean([sum(z**2)**0.5 for z in arz])
  
          # fac = np.mean(sum(arz**2, 1)**0.5)
          # print fac
          # arz *= self.const.chiN / fac
  
          # compute ary from arz
          if len(arz):  # should always be true
              # apply unconditional mirroring, is pretty obsolete
              if new_injections and self.sp.lam_mirr and self.opts['CMA_mirrormethod'] == 0:
                  for i in xrange(self.sp.lam_mirr):
                      if 2 * (i + 1) > len(arz):
                          if self.countiter < 4:
                              _print_warning("fewer mirrors generated than given in parameter setting (%d<%d)"
                                              % (i, self.sp.lam_mirr))
                          break
                      arz[-1 - 2 * i] = -arz[-2 - 2 * i]
              ary = self.sigma_vec * np.dot(self.B, (self.D * arz).T).T
              if len(arinj):
                  ary = np.vstack((arinj, ary))
          else:
              ary = array(arinj)
  
          # TODO: subject to removal in future
          if not new_injections and number > 2 and self.countiter > 2:
              if (isinstance(self.adapt_sigma, CMAAdaptSigmaTPA) or
                  self.opts['mean_shift_line_samples'] or
                  self.opts['pc_line_samples']):
                  ys = []
                  if self.opts['pc_line_samples']:
                      ys.append(self.pc[:])  # now TPA is with pc_line_samples
                  if self.opts['mean_shift_line_samples']:
                      ys.append(self.mean - self.mean_old)
                  if not len(ys):
                      ys.append(self.mean - self.mean_old)
                  # assign a mirrored pair from each element of ys into ary
                  for i, y in enumerate(ys):
                      if len(arz) > 2 * i + 1:  # at least two more samples
                          assert y is not self.pc
                          # y *= sum(self.randn(self.N)**2)**0.5 / self.mahalanobis_norm(y)
                          y *= self.random_rescaling_factor_to_mahalanobis_size(y)
                          # TODO: rescale y depending on some parameter?
                          ary[2*i] = y / self.sigma
                          ary[2*i + 1] = y / -self.sigma
                      else:
                          _print_warning('line samples omitted due to small popsize',
                              method_name='ask_geno', iteration=self.countiter)
  
          # print(xmean[0])
          pop = xmean + sigma * ary
          self.evaluations_per_f_value = 1
          self.ary = ary
          return pop