}// 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
}// 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
}//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
}//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
}// 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
}//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
}//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
} //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
} //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
}//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); }
}//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};
/// <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
/// <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); } }