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
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`