Пример #1
0
        public static double[] RealFastFourierTransform(Complex[] src, double amplitude = 1.0)
        {
            int n4 = 1 << (Mt.Log2Int(src.Length) - 1);
            int n = n4 * 4, n2 = n4 * 2, n3 = n4 * 3;
            int n2mask = n2 - 1;

            Complex[]       Data     = new Complex[n2];
            TriangularTable Triangle = TriangularTable.Get(n);

            for (int i = n4; i >= 0; --i)
            {
                int     j  = n2 - i;
                Complex g1 = src[i];
                Complex g2 = Complex.Conjugate(src[j]);
                Complex h1 = (g1 + g2);
                Complex h2 = (g1 - g2) * Triangle.Complex(n4 + i);
                Data[i]          = (h1 + h2);
                Data[j & n2mask] = Complex.Conjugate(h1 - h2);
            }
            Data = FastFourierTransform_(Data, false);
            LetMul(Data, amplitude / n);
            double[] Dst = New.Array(n, i => (i & 1) == 0 ? Data[i / 2].Real : Data[i / 2].Imaginary);
            return(Dst);
        }
Пример #2
0
        //---------------------------------------------------------------------------
        #region Numerical optimization functions
        public static double[] ArgminSimplex(double[] arguments, double[] delta, Func <double[], double> func, double tolerance)
        {
            int EstimationCountMax = 5000;
            int EstimationCount = 0;
            int D = arguments.Length, D1 = D + 1;

            double[][] Args   = New.Array(D + 1, j => New.Array(D, i => arguments[i] + (i == j ? delta[i] : 0.0)));
            double[]   ArgSum = New.Array(D, i => Ex.Range(D + 1).Sum(j => Args[j][i]));
            double[]   ArgTry = new double[D];
            double[]   Values = Args.Select(arg => func(arg)).ToArray();

            Func <int, double, double> tryfunc = (int i, double fac) =>
            {
                double[] arg  = Args[i];
                double   fac1 = (1 - fac) / D;
                double   fac2 = fac1 - fac;
                for (int j = D; --j >= 0;)
                {
                    ArgTry[j] = ArgSum[j] * fac1 - arg[j] * fac2;
                }

                double y = func(ArgTry);
                if (Values[i] > y)
                {
                    Values[i] = y;
                    for (int j = D; --j >= 0;)
                    {
                        ArgSum[j] += ArgTry[j] - arg[j];
                        arg[j]     = ArgTry[j];
                    }
                }
                return(y);
            };

            while (true)
            {
                int iMin  = 0;
                int iMax  = Values[0] > Values[1] ? 0 : 1;
                int iMax2 = 1 - iMax;
                for (int i = 0; i < D1; i++)
                {
                    double v = Values[i];
                    if (v <= Values[iMin])
                    {
                        iMin = i;
                    }
                    if (v > Values[iMax])
                    {
                        iMax2 = iMax; iMax = i;
                    }
                    else if (v > Values[iMax2] && i != iMax)
                    {
                        iMax2 = i;
                    }
                }

                double d = 2.0 * Math.Abs(Values[iMax] - Values[iMin])
                           / (Math.Abs(Values[iMax]) + Math.Abs(Values[iMin]) + Mt.DoubleEps);
                if (d < tolerance)
                {
                    break;
                }
                if (EstimationCount >= EstimationCountMax)
                {
                    ThrowException.WriteLine("ArgminSimplex: too many function estimations.");
                    break;
                }

                EstimationCount += 2;
                double vTry = tryfunc(iMax, -1);
                if (vTry <= Values[iMin])
                {
                    tryfunc(iMax, 2); continue;
                }
                if (vTry < Values[iMax2])
                {
                    EstimationCount--; continue;
                }

                double vTryPrev = Values[iMax];
                vTry = tryfunc(iMax, 0.5);
                if (vTry < vTryPrev)
                {
                    continue;
                }

                EstimationCount += D;
                for (int i = 0; i < D1; i++)
                {
                    if (i == iMin)
                    {
                        continue;
                    }
                    for (int j = 0; j < D; j++)
                    {
                        Args[i][j] = (Args[i][j] + Args[iMin][j]) / 2;
                    }
                    Values[i] = func(Args[i]);
                }
                for (int i = D; --i >= 0;)
                {
                    ArgSum[i] = Ex.Range(D + 1).Sum(j => Args[j][i]);
                }
            }
            return(New.Array(D, i => Ex.Range(D1).Average(j => Args[j][i])));
        }