Пример #1
0
        }// InversBit

        //-----------------------------------------------------------------------------

        /// <summary>
        /// Wyznacznie wektora ExpW o elementach zespolonych ExpW[k]=Exp(znak*j*2*PI*k/N);
        /// </summary>
        /// <param name="znak">znak =-1 -transformacja prosta
        ///                    znak =+1 -transformacja odwrotna</param>
        /// <param name="N">liczba probek</param>
        /// <param name="ExpW">ExpW referencja do wektora o elementach zespolonych</param>
        /// <returns>funkcja zwraca 0 gdy błąd nie wystapil, w przeciwnym
        /// razie zwraca numer błędu</returns>
        public static int WekExp(int znak, int N, Complex.Complex[] ExpW)
        {
            int    k;
            double fi, s, c;

            Complex.Complex W, W1;
            W1 = new Complex.Complex(1.0, 0);
            if (ExpW.Length - 1 == N)
            {
                fi = 2 * Math.PI / N;  s = Math.Sin(fi); c = Math.Cos(fi);
                if (znak >= 0)
                {
                    W = new Complex.Complex(c, s);
                }
                else
                {
                    W = new Complex.Complex(c, -s);
                }
                ExpW[0] = W1;
                for (k = 1; k <= N - 1; k++)
                {
                    ExpW[k] = ExpW[k - 1] * W;
                }
                return(0);
            }
            else
            {
                return(2);
            }
        }// WekExpW
Пример #2
0
        }// WekExpW

        //---------------------------------------------------------------------------

        /// <summary>
        /// Metoda wg algorytmu FFT Cooleya-Tukeya
        /// </summary>
        /// <param name="znak">znak =-1 -transformacja prosta
        ///                    znak =+1 -transformacja odwrotna</param>
        /// <param name="p">wykładnik potęgi przy obliczaniu N dwa do potęgi p</param>
        /// <param name="X">wektor zespolony próbek wejściowych o elementach X[j]</param>
        /// <returns>funkcja zwraca 0 gdy błąd nie wystapil, w przeciwnym
        /// razie zwraca numer błędu</returns>
        public static int FFTCooleyTukey(int znak, int p, Complex.Complex[] X)
        {
            Complex.Complex   T;
            Complex.Complex[] ExpW;
            int i, l, k, m, r, s, N, MP = 0, MP1, Blad = 0;

            N = 1 << p; //dwa do potęgi p
            //InicjacjaWektora(ExpW,N);
            ExpW = new Complex.Complex[N + 1];
            if (p < 3 || p > 15)
            {
                Blad = 3;
            }
            else if (X.Length - 1 != N)
            {
                Blad = 5;
            }
            if (Blad == 0)
            {
                Blad = InversBit(p, X);
                if (Blad == 0)
                {
                    WekExp(znak, N, ExpW);
                    r = N;
                    for (m = 1; m <= p; m++)
                    {
                        if (m > 1)
                        {
                            MP = MP << 1;
                        }
                        else
                        {
                            MP = 2;                         //MP=MP<<1;  mnożenie przez dwa
                        }
                        MP1 = MP >> 1;    r = r >> 1;       //r=r>>1; dzielenie przez dwa
                        for (k = 0; k <= MP1 - 1; k++)
                        {
                            i = k; s = r * k;
                            while (i < N)
                            {
                                l    = i + MP1;
                                T    = X[l] * ExpW[s];
                                X[l] = X[i] - T;   X[i] += T;
                                i   += MP;
                            }
                        }
                    }
                    return(0);
                }
                else
                {
                    return(Blad);
                }
            }
            else
            {
                return(Blad);
            }
        }//FFTCooleyTukey
Пример #3
0
        }//DTFHorner

        //-------------------------------------------------------------------------

        /// <summary>
        /// Metoda do wyznaczanie zespolonych współczynników  szeregu Fouriera
        /// funkcji okresowej
        /// </summary>
        /// <param name="Metoda">Rodzaj algorytmu stosowanego do wyznaczania
        /// odwrotnej transformaty  1 - FFT Cooleya-Tukeya
        ///                         2 - FFT Sandego-Tukeya
        ///                         3 - DTF Hornera</param>
        /// <param name="p">wykładnik potęgi przy obliczaniu
        /// N dwa do potęgi p dla algorytmu</param>
        /// <param name="T0">Chwila początkowa całkowania po okresie T</param>
        /// <param name="T">Okres badanej funkcji</param>
        /// <param name="X">Wektor zespolony współczynników szeregu Fouriera X[j]</param>
        /// <param name="U">Egzemplarz delegata FunkcjaRealeReale funkcji okresowej </param>
        /// <returns>funkcja zwraca 0 gdy błąd nie wystapil, w przeciwnym
        /// razie zwraca numer błędu</returns>
        public static int WspolczynnikiSzereguFouriera(int Metoda,
                                                       int p, double T0, double T,
                                                       Complex.Complex[] X, FunkcjaRealeReale U)
        {
            int    k, N = 0, Blad = 0;
            double la, h, tt, aa;

            if (Metoda == 3)
            {
                N = p;
            }
            else
            {
                if (p < 3 || p > 15)
                {
                    Blad = 9;
                }
                else
                {
                    N = 1 << p;
                }
            }
            if (Blad == 0)
            {
                h = T / N; la = 2.0 / N;
                for (k = 0; k <= N - 1; k++)
                {
                    tt   = T0 + k * h;  aa = U(tt) * la;
                    X[k] = new Complex.Complex(aa, 0);
                }
                switch (Metoda)
                {
                case 1: Blad = FFTCooleyTukey(-1, p, X);
                    break;

                case 2:  Blad = FFTSandeTukey(-1, p, X);
                    break;

                case 3:       Blad = DTFHorner(-1, N, X);
                    break;

                default: Blad = 8; break;
                }
                if (Blad == 0)
                {
                    return(0);
                }
                else
                {
                    return(Blad);
                }
            }
            else
            {
                return(Blad);
            }
        }//WspolczynnikiSzereguFouriera
Пример #4
0
        }//FFTCooleyTukey

        //------------------------------------------------------------------------------

        /// <summary>
        /// Metoda wg algorytmu FFT Sandego-Tukeya
        /// </summary>
        /// <param name="znak">znak =-1 -transformacja prosta
        ///                    znak =+1 -transformacja odwrotna</param>
        /// <param name="p">wykładnik potęgi przy obliczaniu N dwa do potęgi p</param>
        /// <param name="X">wektor zespolony próbek wejściowych o elementach X[j]</param>
        /// <returns>funkcja zwraca 0 gdy błąd nie wystapil, w przeciwnym
        /// razie zwraca numer błędu</returns>
        public static int FFTSandeTukey(int znak, int p, Complex.Complex[] X)
        {
            Complex.Complex   T;
            Complex.Complex[] ExpW;
            int i, l, k, m, r = 0, s, N, MP = 0, MP1, Blad = 0;

            N = 1 << p; //dwa do potęgi p
            //InicjacjaWektora(ExpW,N);
            ExpW = new Complex.Complex[N + 1];
            if (p < 3 || p > 15)
            {
                Blad = 4;
            }
            else if (X.Length - 1 != N)
            {
                Blad = 6;
            }
            if (Blad == 0)
            {
                WekExp(znak, N, ExpW);
                MP1 = N;
                for (m = 1; m <= p; m++)
                {
                    MP1 = MP1 >> 1;   MP = MP1 << 1;
                    if (m == 1)
                    {
                        r = 1;
                    }
                    else
                    {
                        r = r << 1;      //r=r<<1;  mnożenie przez dwa
                    }
                    for (i = 0; i <= MP1 - 1; i++)
                    {
                        l = i;  s = i * r;
                        while (l < N)
                        {
                            k     = l + MP1;
                            T     = X[l] - X[k];
                            X[l] += X[k];
                            X[k]  = T * ExpW[s];
                            l    += MP;
                        }
                    } //i
                }     //m
                InversBit(p, X);   return(0);
            }
            else
            {
                return(Blad);
            }
        }//FFTSandeTukey
Пример #5
0
        }// RKW

        /// <summary>
        /// Metoda dokonuje podstawienia kolejnych pierwiastków
        ///wielomianu pod wektor zespolony FZ
        ///FZ.B[k] -k-ty pierwiastek wielomianu
        /// </summary>
        /// <param name="FZ">Wektor zespolony pierwiastków</param>
        /// <param name="FP">Pierwszy współczynik trójmianu X^2-FP*X+FQ</param>
        /// <param name="FQ">Drugi współczynik trójmianu X^2-FP*X+FQ</param>
        /// <param name="k">Numer k-tego pierwiastka wielomianu</param>
        private static void PRW2(Complex.Complex[] FZ, double FP, double FQ, ref int k)
        {
            double X = 0, Y = 0;
            bool   Re = false;

            RKW(FP, FQ, ref X, ref Y, ref Re);
            if (Re)
            {
                k++; FZ[k] = new Complex.Complex(X, 0);
                k++; FZ[k] = new Complex.Complex(Y, 0);
            }
            else
            {
                k++; FZ[k] = new Complex.Complex(X, Y);
                k++; FZ[k] = new Complex.Complex(X, -Y);
            }
        }// PRW2
Пример #6
0
        }//FFTSandeTukey

        //------------------------------------------------------------------------------

        /// <summary>
        /// Metoda wg algorytmu Hornera
        /// </summary>
        /// <param name="znak">znak =-1 -transformacja prosta
        ///                    znak =+1 -transformacja odwrotna</param>
        /// <param name="N">liczba elementów wektora X</param>
        /// <param name="X">wektor zespolony próbek wejściowych o elementach X[j]</param>
        /// <returns>funkcja zwraca 0 gdy błąd nie wystapil, w przeciwnym
        /// razie zwraca numer błędu</returns>
        public static int DTFHorner(int znak, int N, Complex.Complex[] X)
        {
            int i, k, Blad = 0;

            Complex.Complex   ZX, Wk;
            Complex.Complex[] ExpW = new Complex.Complex[N + 1];
            //InicjacjaWektora(ExpW,N);
            //vector<complex<Typ> > WekC(X);
            Complex.Complex[] WekC = new Complex.Complex[N + 1];
            for (k = 0; k <= N - 1; k++)
            {
                WekC[k] = X[k];
            }
            //WekC=X;
            if (X.Length - 1 != N)
            {
                Blad = 7;
            }
            if (Blad == 0)
            {
                //InicjacjaWektora(ExpW,N);
                WekExp(znak, N, ExpW);
                for (k = 0; k <= N - 1; k++)
                {
                    Wk = ExpW[k];  ZX = WekC[N - 1];
                    for (i = N - 1; i >= 1; i--)
                    {
                        ZX *= Wk;  ZX += WekC[i - 1];
                    }
                    X[k] = ZX;
                }
                return(0);
            }
            else
            {
                return(Blad);
            }
        }//DTFHorner
Пример #7
0
        }//PrzestawPierwiastki

        //-----------------------------------------------------------------------
        /// <summary>
        /// Metoda Bairstowa obliczania pierwiastków wielomianu (4.57) stopnia N
        /// </summary>
        /// <param name="FW">Wektor wpółczynników wielomianu inicjowany na zewnątrz klasy</param>
        /// <param name="ZZ">Wektor zespolony zer wielomianu inicjowany na zewnątrz klasy</param>
        /// <param name="P">Początkowe przybliżenie do dzielenia wielomianu przez
        ///      trójmian kwadratowy X^2-FP*X+FQ np. P:=1</param>
        /// <param name="Q">Początkowe przybliżenie do dzielenia wielomianu przez
        ///      trójmian kwadratowy X^2-FP*X+FQ np. Q:=1</param>
        /// <param name="eps">dokładność bezwzględna iteracji  np. eps=1E-16</param>
        /// <param name="mega">próg poszukiwania dzielnika np.mega:=1E+3</param>
        /// <param name="maxit">ustalona maksymalna liczba iteracji kończąca obliczenia</param>
        /// <returns>Funkcja zwraca numer błędu; wartość 0 - brak błędu</returns>
        public static int ZeraWielBairstow(double[] FW, Complex.Complex[] ZZ,
                                           double P, double Q, double eps, double mega, int maxit)
        {
            double FP, FQ;
            int    k, N, N1, Blad;

            Blad = 0;
            N    = FW.Length - 1;   N1 = N;
            //InicjacjaWektora(ZZ,N);
            FP = P; FQ = Q;
            if (FW[0] == 0)
            {
                return(1);
            }
            k = 0;
            while (N > 2)
            {
                Blad = Bairstow(FW, eps, mega, ref FP, ref FQ, N);
                if (Blad == 0)
                {
                    PRW2(ZZ, FP, FQ, ref k);
                    Div2(FW, FP, FQ, ref N);
                }
            }
            if (N == 2)
            {
                FP = -FW[1] / FW[0]; FQ = FW[2] / FW[0];
                PRW2(ZZ, FP, FQ, ref k);
            }
            else
            {
                k++; ZZ[k] = new Complex.Complex(-FW[1] / FW[0], 0);
            }
            PrzestawPierwiastki(ZZ, N1);
            return(Blad);
        }// ZeraWielBairstow
Пример #8
0
        }    //OdwMacC

        //--------------------------------------------------------------------
        /// <summary>
        /// // Metoda odwracanie macierzy metodą rozkładu LU wg algorytmu
        /// Crouta-Doolittle'a i zapisanie jej na miejscu oryginalnej
        /// </summary>
        /// <param name="A">Macierz kwadratowa rzędu NW=A.GetLength(0)-1</param>
        /// <param name="eps">dokładność określenia zerowego elementu przy
        ///     poszukiwaniu elementu głównego</param>
        /// <returns>return 0 brak błędu, inna wartość = numer błędu</returns>
        public static int OdwMacCroutDoolitta(Complex.Complex[,] A, double eps)
        {
            int    i, j, k, u, k1, NW, NK, Nu, Nj1, Nk1;
            double T, T1;

            Complex.Complex S, W;
            //NW=MacA.size()-1;  NK=MacA[NW].size()-1;
            NW = A.GetLength(0) - 1; NK = A.GetLength(1) - 1;
            //vector<Typ> X;  InicjacjaWektora(X,NW);
            //vector<int> M;  InicjacjaWektora(M,NW);
            int[]             M = new int[NW + 1];
            Complex.Complex[] X = new Complex.Complex[NW + 1];
            if (NK == NW)
            {     // Przekształcenie macierzy A do postaci  niezawierającej
                // elementów na głównej przekątnej
                for (i = 1; i <= NW; i++)
                {
                    T = Complex.ComplexMath.Abs(A[i, i]); k = i;
                    if (T < eps)
                    {
                        for (j = i + 1; j <= NW; j++)
                        {
                            T1 = Complex.ComplexMath.Abs(A[j, i]);
                            if (T1 > T)
                            {
                                T = T1; k = j;
                            }
                        }
                        if (T < eps)
                        {
                            return(15);
                        }
                        // Zamiana wiersza k-tego z i-tym
                        if (i != k)
                        {
                            //swap(A[k], A[i]);
                            for (j = 1; j <= NW; j++)
                            {
                                W = A[k, j]; A[i, j] = A[k, j]; A[k, j] = W;
                            }
                        }
                    }
                    M[i] = k;
                }    //i
                // Rozkład LU macierzy A wg algorytmu Doolittle'a  A=L*U
                for (k = 1; k <= NW - 1; k++)
                {
                    k1 = k + 1;
                    if (A[k, k] != 0)
                    {
                        for (i = k1; i <= NW; i++)
                        {
                            if (A[k, i] != 0)
                            {
                                A[k, i] /= A[k, k];
                            }
                        }
                    }
                    else
                    {
                        return(15);
                    }
                    for (i = k1; i <= NW; i++)
                    {
                        for (j = k1; j <= NW; j++)
                        {
                            if (A[i, k] != 0 && A[k, j] != 0)
                            {
                                A[i, j] -= A[i, k] * A[k, j];
                            }
                        }
                    }
                }    //k
                // Rozwiązanie układu trójkątnego dolnego L tj. L*Y=I
                // metodą postępowania w przód
                double a1 = 1.0;
                for (i = 1; i <= NW; i++)
                {
                    A[i, i] = a1 / A[i, i];
                    for (j = 1; j <= i - 1; j++)
                    {
                        S = 0;
                        for (k = j; k <= i - 1; k++)
                        {
                            S -= A[i, k] * A[k, j];
                        }
                        A[i, j] = S * A[i, i];
                    } //j
                }     //i;
                // Rozwiązanie układu trójkątnego górnego tj. U*X=Y metodą
                // postępowania wstecz
                for (u = 1; u <= NW - 1; u++)
                {
                    Nu = NW - u;
                    for (k = 1; k <= u; k++)
                    {
                        S   = 0;
                        Nk1 = NW - k + 1;
                        for (j = 1; j <= u; j++)
                        {
                            Nj1 = NW - j + 1;
                            S  -= A[Nu, Nj1] * A[Nj1, Nk1];
                        }
                        X[k] = S;
                    }    //k
                    for (i = 1; i <= Nu; i++)
                    {
                        S = A[Nu, i];
                        for (j = 1; j <= u; j++)
                        {
                            Nj1 = NW - j + 1; S -= A[Nu, Nj1] * A[Nj1, i];
                        }
                        A[Nu, i] = S;
                    }    //i
                    for (k = 1; k <= u; k++)
                    {
                        A[Nu, NW - k + 1] = X[k];
                    }
                }    //u
                for (i = NW; i >= 1; i--)
                {
                    k = M[i];
                    if (k != i)
                    {
                        for (j = 1; j <= NW; j++)
                        {
                            //swap(A[j,i], A[j,k]);
                            W = A[j, i]; A[j, i] = A[j, k]; A[j, k] = W;
                        }
                    }
                }    //i
                return(0);
            }
            else
            {
                return(14);
            }
        }    //OdwMacC
Пример #9
0
        }   //RozRowMacIGS

        /// <summary>
        ///  Metoda rozwiązywania równania macierzowego  A*X=B o elementach zespolonej
        ///  metodą iteracji Gaussa-Seidela dla pełnych macierzy typu  complex [,]
        /// </summary>
        /// <param name="A">macierz kwadratowa rzędu N=A.GetLength(0)-1</param>
        /// <param name="B">macierz wyrazów wolnych o N=B.GetLength(0)-1  -wierszach i
        ///                  M=B.GetLength(1)t-1  -kolumnach</param>
        /// <param name="X">macierz rozwiązania o N=X.GetLength(0)-1  -wierszach i
        ///                  M=X.GetLength(1)-1  -kolumnach</param>
        /// <param name="eps">dokładność bezwzględna iteracji (np. eps=1E-8)</param>
        /// <param name="omega">parametr relaksacji omega =1 dla metody Gaussa-Seidela </param>
        /// <param name="maxit">zadana maksymalna liczba iteracji</param>
        /// <returns>return 0 brak błędu, inna wartość = numer błędu</returns>
        public static int RozRowMacIGS(Complex.Complex[,] A, Complex.Complex[,] B, Complex.Complex[,] X,
                                       double eps, double omega, int maxit)
        {
            int    i, j, l, k, p, N, M, U, W;
            double R, R1, S, T, T1;

            Complex.Complex SZ, G;
            N = A.GetLength(0) - 1; M = A.GetLength(1) - 1;
            W = B.GetLength(0) - 1; U = B.GetLength(1) - 1;
            Complex.Complex[,] Y = new Complex.Complex[N + 1, U + 1];
            try
            {
                if (W == N && M == N)
                {     // Przekształcenie macierzy A do postaci z możliwie
                    //maksymalnymi co do modułu elementami na głównej
                    //przekątnej metodą przestawiania wierszy
                    for (i = 1; i <= N; i++)
                    {
                        T = A[i, i].Abs; k = i;
                        for (j = i + 1; j <= N; j++)
                        {
                            T1 = A[j, i].Abs;
                            if (T1 > T)
                            {
                                T = T1; k = j;
                            }
                            ;
                        }
                        if (i != k)
                        {
                            //swap(B[k],B[i]); swap(A[k],A[i]);
                            for (l = 1; l <= U; l++)
                            {
                                G = B[k, l]; B[k, l] = B[i, l]; B[i, l] = G;
                            }
                            for (l = 1; l <= N; l++)
                            {
                                G = A[k, l]; A[k, l] = A[i, l]; A[i, l] = G;
                            }
                        }
                    }
                    ;    //i
                    //MetGaussa.SkalRowMacTyp(A,B);
                    p = 0;
                    for (i = 1; i <= N; i++)
                    {
                        for (j = 1; j <= U; j++)
                        {
                            X[i, j] = B[i, j];
                        }
                    }
                    do
                    {
                        R1 = 0; p++;
                        for (i = 1; i <= N; i++)
                        {
                            for (j = 1; j <= U; j++)
                            {
                                Y[i, j] = X[i, j];
                            }
                        }
                        for (l = 1; l <= U; l++)
                        {
                            R = 0.0;
                            for (i = 1; i <= N; i++)
                            {
                                SZ = B[i, l];
                                for (j = 1; j <= i - 1; j++)
                                {
                                    SZ -= A[i, j] * X[j, l];
                                }
                                for (j = i; j <= N; j++)
                                {
                                    SZ -= A[i, j] * Y[j, l];
                                }
                                X[i, l] = Y[i, l] + omega * SZ / A[i, i];
                                S       = SZ.Abs;
                                if (S > R)
                                {
                                    R = S;
                                }
                            }   //i
                            if (R > R1)
                            {
                                R1 = R;
                            }
                        }   //l
                    }while (!(R1 < eps || p > maxit));
                    if (p > maxit)
                    {
                        throw new Exception("W metodzie iteracji Gaussa-Seidela przekroczono zadaną liczbę iteracji nie osiągają zadanej dokładności obliczeń ");              //return 23 ;
                    }
                    else
                    {
                        return(0);
                    }
                }
                else
                {
                    throw new Exception("W metodzie iteracji Gaussa-Seidela niewłaściwie utalone rozmiary macierzy");
                }
            }
            catch
            {
                throw new Exception("W metodzie iteracji Gaussa-Seidela pojawił się błąd");
                //PiszKomBladAlgeLin(20);
                //return 33;
            }
        }   //RozRowMacIGS
Пример #10
0
        }//WspolczynnikiSzereguFouriera

        //---------------------------------------------------------------------------
        //Wzorzec funkcji do wyznaczania odwrotnej transformacji Fouriera
        //Metoda - rodzaj algorytmu stosowanego do wyznaczania odwrotnej transformaty
        //p - wykładnik potęgi przy obliczaniu N dwa do potęgi p dla metod
        // Cooleya-Tukeya i Sandego-Tukeya oraz liczbę próbek dla metody Hornera
        //F - transformacja Fouriera jako egzemplarz delegata FunkcjaComplexReale
        //w0- określa przedział całkowania ze względu na zmienną w<=(-w0,+w0)
        //Ex - wektor próbek rozwiązania Ex[i] odpowiadający chwilom czasowym Tx[i]
        public static int OdwrotnaTransformacjaFouriera(int Metoda, int p,
                                                        FunkcjaComplexReale F, double w0, double[] Tx, double[] Ex)
        {
            int    N, k, N1, Blad = 0;
            double w, dw, la, dt;

            if (Metoda == 3)
            {
                N = p;
            }
            else
            {
                N = 1 << p;
            }
            if (N != (int)Tx.Length - 1 || N != (int)Ex.Length - 1)
            {
                Blad = 10;
            }
            else
            {
                //vector<complex<Typ> > Gp;
                //InicjacjaWektora(Gp,N);
                Complex.Complex[] Gp = new Complex.Complex[N + 1];
                //vector<Typ> Ep,El;
                //InicjacjaWektora(Ep,N);   InicjacjaWektora(El,N);
                //InicjacjaWektora(Tx,N);   InicjacjaWektora(Ex,N);
                double [] Ep = new double[N + 1];
                double [] El = new double[N + 1];
                //Ex= new double[N+1];
                //Tx= new double[N+1];
                N1 = N >> 1;
                dt = Math.PI / w0;
                dw = w0 / N1; la = 1 / (N * dt);
                for (k = 0; k <= N1; k++)
                {
                    Tx[N1 - k] = -k * dt; Tx[N1 + k] = k * dt;
                }
                for (k = 0; k <= N1 - 1; k++)
                {
                    w = k * dw; Gp[k] = F(w) * la;
                    if (k > 0)
                    {
                        Gp[N - k] = F(-w) * la;
                    }
                }
                w      = N1 * dw;
                Gp[N1] = F(w) * la + F(-w) * la;
                //vector<complex<Typ> > Gl(Gp);
                Complex.Complex[] Gl = new Complex.Complex[N + 1];
                for (k = 0; k <= N; k++)
                {
                    Gl[k] = Gp[k];
                }
                switch (Metoda)
                {
                case 1: Blad = FFTCooleyTukey(1, p, Gp);
                    if (Blad == 0)
                    {
                        Blad = FFTCooleyTukey(-1, p, Gl);
                    }
                    break;

                case 2:  Blad = FFTSandeTukey(1, p, Gp);
                    if (Blad == 0)
                    {
                        Blad = FFTSandeTukey(-1, p, Gl);
                    }
                    break;

                case 3:       Blad = DTFHorner(1, N, Gp);
                    if (Blad == 0)
                    {
                        Blad = DTFHorner(-1, N, Gl);
                    }
                    break;

                default: Blad = 11; break;
                }
                if (Blad == 0)
                {
                    for (k = 0; k <= N - 1; k++)
                    {
                        Ep[k] = Gp[k].Re;
                        El[k] = Gl[k].Re;
                    }
                    for (k = 0; k <= N - 1; k++)
                    {
                        if (k < N1)
                        {
                            Ex[k] = El[N1 - k];
                        }
                        else
                        {
                            Ex[k] = Ep[k - N1];
                        }
                    }
                }
            }
            return(Blad);
        }
Пример #11
0
        }//Laguerre

        //----------------------------------------------------------------------------

        /// <summary>
        /// Metoda Laguerre'a obliczania pierwiastków wielomianu(4.73) stopnia N
        /// </summary>
        /// <param name="FW">Wektor wpółczynników wielomianu inicjowany na zewnątrz klasy</param>
        /// <param name="FZ">Wektor zespolony zer wielomianu inicjowany na zewnątrz klasy</param>
        /// <param name="eps">Dokładność bezwzględna iteracji  np. eps=1E-16</param>
        /// <param name="maxit">Ustalona maksymalna liczba iteracji kończąca obliczenia</param>
        /// <returns></returns>
        public static int ZeraWielLaguerre(double[] FW, Complex.Complex[] FZ,
                                           double eps, int maxit)
        {
            int    M, Blad, N1;
            double X1, X2, delta, Y1, Y2, FP, FQ;

            Complex.Complex ZZ;
            M = FW.Length - 1;   N1 = M;
            //InicjacjaWektora(FZ,M);
            Blad = 0;
            if (FW[0] == 0)
            {
                Blad = 1;
            }
            else
            {
                while (M > 2)
                {
                    ZZ = new Complex.Complex(0, 0);
                    if (FW[M] == 0)
                    {
                        FZ[M] = new Complex.Complex(0, 0); M--;
                    }
                    else
                    {
                        Blad = Laguerre(M, FW, ref ZZ, eps, maxit);
                        if (Blad == 0)
                        {
                            Y1 = ZZ.Re; Y2 = ZZ.Im;
                            if (Math.Abs(Y2) <= 1e-38)
                            {
                                FZ[M] = new Complex.Complex(Y1, 0);
                                Blad  = Div1(FW, ref M, Y1);
                                if (Blad != 0)
                                {
                                    return(Blad);
                                }
                            }
                            else
                            {
                                FZ[M]     = ZZ;
                                FZ[M - 1] = ZZ.Conjugate;
                                FP        = 2 * Y1;
                                FQ        = Y1 * Y1 + Y2 * Y2;
                                Div2(FW, FP, FQ, ref M);
                            }
                        }
                        else
                        {
                            return(Blad);
                        }
                    }
                }
                if (M == 2)
                {
                    if (FW[M] == 0)
                    {
                        FZ[M] = new Complex.Complex(0, 0); M -= 1;
                    }
                    else
                    {
                        delta = FW[1] * FW[1] - 4 * FW[0] * FW[2];
                        if (delta < 0)
                        {
                            X1        = -0.5 * FW[1] / FW[0];
                            X2        = 0.5 * Math.Sqrt(-delta) / FW[0];
                            FZ[M]     = new Complex.Complex(X1, X2);
                            FZ[M - 1] = new Complex.Complex(X1, -X2);
                        }
                        else
                        {
                            X1        = -0.5 * FW[1] / FW[0];
                            X2        = 0.5 * Math.Sqrt(delta) / FW[0];
                            FZ[M]     = new Complex.Complex(X1 + X2, 0);
                            FZ[M - 1] = new Complex.Complex(X1 - X2, 0);
                        }
                    }
                }
                else
                {
                    FZ[1] = new Complex.Complex(-FW[1] / FW[0], 0);
                }
                //Przestawianie pierwiastków wg wzrastających modułów
                PrzestawPierwiastki(FZ, N1);
            }
            return(Blad);
        }//ZeraWielLaguerre};
Пример #12
0
        /// <summary>
        /// Wyznacza pierwiastek Z wielomianu stopnia N o współczynnikach
        /// zapisanych w wektorze FW[i]
        /// </summary>
        /// <param name="N">Stopień wielomianu </param>
        /// <param name="FW">Wektor współczynników wielomianu</param>
        /// <param name="Z">Pierwiastek wielomianu</param>
        /// <param name="eps"> dokładność bezwzględna iteracji  np. eps=1E-16</param>
        /// <param name="maxit">ustalona maksymalna liczba iteracji kończąca obliczenia</param>
        /// <returns>return - nr błędu; 0 - brak błędu.</returns>
        private static int Laguerre(int N, double[] FW, ref Complex.Complex Z, double eps, int maxit)
        {
            Complex.Complex B, C, D, S, H, M1, M2;
            double          MM1, MM2, Alfa, Nx, LL, MM;
            int             N1, i, k, Blad;

            Blad = 0;
            if (FW[0] == 0)
            {
                Blad = 1;
            }
            else
            {
                if (FW[N] == 0)
                {
                    Z = new Complex.Complex(0, 0);
                }
                else
                {
                    N1 = N - 1;   k = 0;
                    do
                    {  //Wyznaczanie wartości wielomianu i ich pochodnych pierwszego
                       // i drugiego rodzaju wg algorytmu Hornera (4.76)
                        B = new Complex.Complex(FW[0], 0);
                        C = B; D = B;
                        for (i = 1; i <= N; i++)
                        {
                            if (i <= N - 2)
                            {
                                S  = B * Z;   S += FW[i];    B = S;
                                C *= Z;  C += B;
                                D *= Z;  D += C;
                            }
                            else
                            {
                                if (i <= N - 1)
                                {
                                    S  = B * Z;  S += FW[i];  B = S;
                                    C *= Z;   C += B;
                                }
                                else
                                {
                                    S = B * Z;   S += FW[i];  B = S;
                                }
                            }
                        }
                        D *= 2.0;
                        //Konstukcja wzoru rekurencyjnego (4.74)
                        Nx = N1;
                        H  = C * C;  H *= Nx;
                        Nx = N;
                        S  = B * D; S *= Nx;
                        // H - wg wzoru (4.75)
                        Nx  = N1;
                        H  -= S;  H *= Nx;
                        H   = ComplexMath.Sqrt(H);
                        M1  = B / (C + H);  M2 = B / (C - H);
                        MM1 = ComplexMath.Abs(M1); MM2 = ComplexMath.Abs(M2); Nx = N;
                        if (MM1 > MM2)
                        {
                            H = M2 * Nx;
                        }
                        else
                        {
                            H = M1 * Nx;
                        }
                        Z   -= H;   k++;
                        LL   = ComplexMath.Abs(H); MM = ComplexMath.Abs(Z);
                        Alfa = LL / MM;
                    }while (!(Alfa < eps || k > maxit));
                    if (k > maxit)
                    {
                        Blad = 3;
                    }
                }
            }
            return(Blad);
        }//Laguerre
Пример #13
0
        /// <summary>
        /// Metoda odwracenie macierzy zespolonej i zapisanie jej
        /// na miejscu oryginalnej wg algorytmu Gaussa
        /// </summary>
        /// <param name="A">Macierz kwadratowa rzędu NW=A.GetLength(0)</param>
        /// <param name="eps">dokładność określenia zerowego elementu
        /// przy poszukiwaniu elementu głównego</param>
        /// <returns>return 0 brak błędu, inna wartość = numer błędu</returns>
        public static int OdwMacGaussa(Complex.Complex[,] A, double eps)
        {
            int    NW, NK, blad, k;
            double MmaxA, d;
            double a1 = 1;
            double a0 = 0;

            Complex.Complex f, ZS, maxA = 0;
            NW = A.GetLength(0) - 1; NK = A.GetLength(1) - 1;
            //vector<int> M(NW+1);
            int[] M = new int[NW + 1];
            //InicjacjaWektora(M,NW);
            if (NK == NW)
            {
                for (int i = 1; i <= NW; i++)
                {
                    // Częściowy wybór elementu głównego
                    MmaxA = a0; k = 1;
                    for (int j = i; j <= NW; j++)
                    {
                        d = Complex.ComplexMath.Abs(A[j, i]);
                        if (MmaxA < d)
                        {
                            MmaxA = d; maxA = A[j, i]; k = j;
                        }
                    }//j
                    if (MmaxA < eps)
                    {
                        blad = 2;
                        return(blad);
                    }
                    // Zapisywanie wskaźników wierszy występowania elementu
                    // ekstremalnego w i-tej iteracji w postaci wektora M[i]
                    M[i]    = k;
                    A[k, i] = a1;
                    // Przestawienie i-tego wiersza z k-tym
                    for (int j = 1; j <= NW; j++)
                    {
                        A[k, j] /= maxA;
                    }
                    //swap(MacA[k],MacA[i]);
                    for (int j = 1; j >= NW; j++)
                    { //Zamiana wiersza k-tego z i-tym macierzy A
                        ZS = A[k, j]; A[k, j] = A[i, j]; A[i, j] = ZS;
                    }//j
                     // Generacja ciągu macierzy

                    for (int j = 1; j <= NW; j++)
                    {
                        if (j != i)
                        {
                            f = A[j, i]; A[j, i] = 0;
                            for (int l = 1; l <= NW; l++)
                            {
                                A[j, l] -= f * A[i, l];
                            }
                        } //j
                    }
                }         //i
                // Przestawianie kolumn macierzy zgodnie z wektorem wskaźników M[i] (1.55) }
                for (int i = NW; i >= 1; i--)
                {
                    k = M[i];
                    if (k != i)
                    {
                        for (int j = 1; j <= NW; j++)
                        {
                            //swap(MacA[j,i], MacA[j,k]);
                            ZS = A[j, i]; A[j, i] = A[j, k]; A[j, k] = ZS;
                        }
                    }
                }//i
                return(0);
            }
            else
            {
                return(1);
            }
        }