void GaussianMutation(IEvolutionState state, IMersenneTwister random, FloatVectorSpecies species, int index)
        {
            double val;
            double min   = species.GetMinGene(index);
            double max   = species.GetMaxGene(index);
            double stdev = species.GetGaussMutationStdev(index);
            int    outOfBoundsLeftOverTries = species.OutOfBoundsRetries;
            bool   givingUpAllowed          = species.OutOfBoundsRetries != 0;

            do
            {
                val = random.NextGaussian() * stdev + genome[index];
                outOfBoundsLeftOverTries--;
                if (species.GetMutationIsBounded(index) && (val > max || val < min))
                {
                    if (givingUpAllowed && (outOfBoundsLeftOverTries == 0))
                    {
                        val = min + random.NextFloat() * (max - min);
                        species.OutOfRangeRetryLimitReached(state);// it better get inlined
                        break;
                    }
                }
                else
                {
                    break;
                }
            }while (true);
            genome[index] = val;
        }
        void PolynomialMutation(IEvolutionState state, IMersenneTwister random, FloatVectorSpecies species, int index)
        {
            double eta_m = species.GetMutationDistributionIndex(index);
            bool   alternativePolynomialVersion = species.GetPolynomialIsAlternative(index);

            double rnd, delta1, delta2, mut_pow, deltaq;
            double y, yl, yu, val, xy;
            double y1;

            y1     = y = genome[index];         // ind[index];
            yl     = species.GetMinGene(index); // min_realvar[index];
            yu     = species.GetMaxGene(index); // max_realvar[index];
            delta1 = (y - yl) / (yu - yl);
            delta2 = (yu - y) / (yu - yl);

            int totalTries = species.OutOfBoundsRetries;
            int tries      = 0;

            for (tries = 0; tries < totalTries || totalTries == 0; tries++)  // keep trying until totalTries is reached if it's not zero.  If it's zero, go on forever.
            {
                rnd     = random.NextDouble();
                mut_pow = 1.0 / (eta_m + 1.0);
                if (rnd <= 0.5)
                {
                    xy     = 1.0 - delta1;
                    val    = 2.0 * rnd + (alternativePolynomialVersion ? (1.0 - 2.0 * rnd) * (Math.Pow(xy, (eta_m + 1.0))) : 0.0);
                    deltaq = Math.Pow(val, mut_pow) - 1.0;
                }
                else
                {
                    xy     = 1.0 - delta2;
                    val    = 2.0 * (1.0 - rnd) + (alternativePolynomialVersion ? 2.0 * (rnd - 0.5) * (Math.Pow(xy, (eta_m + 1.0))) : 0.0);
                    deltaq = 1.0 - (Math.Pow(val, mut_pow));
                }
                y1 = y + deltaq * (yu - yl);
                if (!species.GetMutationIsBounded(index) || (y1 >= yl && y1 <= yu))
                {
                    break;                                                                  // yay, found one
                }
            }

            // at this point, if tries is totalTries, we failed
            if (totalTries != 0 && tries == totalTries)
            {
                // just randomize
                y1 = (double)(species.GetMinGene(index) + random.NextDouble(true, true) * (species.GetMaxGene(index) - species.GetMinGene(index))); //(double)(min_realvar[index] + random.NextDouble() * (max_realvar[index] - min_realvar[index]));
                species.OutOfRangeRetryLimitReached(state);                                                                                         // it better get inlined
            }
            genome[index] = y1;                                                                                                                     // ind[index] = y1;
        }