반응형
FFT(Fast Fourier Transform) 및 IFFT(Inverse Fast Fourier Transform)를 수행하는 클래스
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // This file is part of MatSeis 1.8 // Copyright (c) 2003 Sandia National Laboratories. All rights reserved. // // John Merchant, bjmerch@sandia.gov //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ package spis.app.anp.com; /** * FFT(Fast Fourier Transform) 및 IFFT(Inverse Fast Fourier Transform)를 수행하는 클래스 */ public class FFT { /** 임시 변수 */ static int _n = 0; /** 임시 변수 */ static int[] le = new int[0]; /** 임시 변수 */ static int[] le1 = new int[0]; /** 임시 변수 */ static double[] w_r = new double[0]; /** 임시 변수 */ static double[] w_i = new double[0]; /** * FFT변환시 수치를 조정하는 메소드. * @param n * 입력값 */ static private void compTwiddles( int n ) { if ( _n == n ) return; _n = n; int ln = (int) ( Math.log( (double)n )/Math.log(2) + 0.5 ); le = new int[ln+1]; le1 = new int[ln+1]; w_r = new double[ln+1]; w_i = new double[ln+1]; for (int l = 0; l <= ln; l++) { le[l] = (int) (Math.exp( (double)l * Math.log(2) ) + 0.5 ); le1[l] = le[l] / 2; w_r[l] = Math.cos( Math.PI / (double)le1[l] ); w_i[l] = Math.sin( Math.PI / (double)le1[l] ); } } /** * FFT(Fast Fourier Transform)변환을 수행하는 메소드. 원본 보존이 됨. * @param f * 원본값 * @param N * FFT변환 길이 * @return * FFT변환의 결과값. 2차 더블형 배열로 구성되며, 0번째 행은 실수부값을 1번째 행에는 허수부값을 보관함. */ public static double[][] fft_1d( double[] f, int N ) { // 2의 배수여부를 체크 N = NumberSummary.nextPow2(N); int n = f.length; double[][] Z = new double[2][N]; /* 배열 초기화. */ /*for (int i = 0; i < Z.length; i++) { for (int j = 0; j < Z[i].length; j++) { Z[i][j] = 0; } }*/ for (int i=0; i<n; i++) Z[0][i] = f[i]; return fft_1d( Z ); } /** * 실제적으로 FFT변환을 수행하는 메소드. 원본 보존이 되지 않음. * @param array * 2차 더블형 배열로 구성되며, 0번째 행은 실수부값을 1번째 행에는 허수부값을 보관함. * @return * FFT변환의 결과값 */ public static double[][] fft_1d( double[][] array ) { if ( !NumberSummary.isPowerOf2(array[0].length) ) throw new IllegalArgumentException("Array length must be power of 2"); double u_r,u_i, t_r,t_i; int ln, nv2, k, l, j, ip, i, n; n = array[0].length; compTwiddles( n ); ln = (int)( Math.log( (double)n )/Math.log(2) + 0.5 ); nv2 = n / 2; j = 1; for (i = 1; i < n; i++ ) { if (i < j) { t_r = array[0][i - 1]; t_i = array[1][i - 1]; array[0][i - 1] = array[0][j - 1]; array[1][i - 1] = array[1][j - 1]; array[0][j - 1] = t_r; array[1][j - 1] = t_i; } k = nv2; while (k < j) { j = j - k; k = k / 2; } j = j + k; } for (l = 1; l <= ln; l++) /* loops thru stages */ { u_r = 1.0; u_i = 0.0; for (j = 1; j <= le1[l]; j++) /* loops thru 1/2 twiddle values per stage */ { for (i = j; i <= n; i += le[l]) /* loops thru points per 1/2 twiddle */ { ip = i + le1[l]; t_r = array[0][ip - 1] * u_r - u_i * array[1][ip - 1]; t_i = array[1][ip - 1] * u_r + u_i * array[0][ip - 1]; array[0][ip - 1] = array[0][i - 1] - t_r; array[1][ip - 1] = array[1][i - 1] - t_i; array[0][i - 1] = array[0][i - 1] + t_r; array[1][i - 1] = array[1][i - 1] + t_i; } t_r = u_r * w_r[l] + w_i[l] * u_i; u_i = w_r[l] * u_i - w_i[l] * u_r; u_r = t_r; } } return array; } /* end of FFT_1d */ /** * FFT역변환을 수행함. 원본 보존이 되지 않음. * @param array * 2차 더블형 배열 구조 이며, 0번째 행은 실수부값을 1번째 행에는 허수부값을 보관함. * @return * FFT역변환의 결과. */ public static double[][] ifft_1d( double[][] array ) { double u_r,u_i, t_r,t_i; int ln, nv2, k, l, j, ip, i, n; n = array[0].length; compTwiddles(n); ln = (int)( Math.log( (double)n )/Math.log(2) + 0.5 ); nv2 = n / 2; j = 1; for (i = 1; i < n; i++ ) { if (i < j) { t_r = array[0][i - 1]; t_i = array[1][i - 1]; array[0][i - 1] = array[0][j - 1]; array[1][i - 1] = array[1][j - 1]; array[0][j - 1] = t_r; array[1][j - 1] = t_i; } k = nv2; while (k < j) { j = j - k; k = k / 2; } j = j + k; } for (l = 1; l <= ln; l++) /* loops thru stages */ { u_r = 1.0; u_i = 0.0; for (j = 1; j <= le1[l]; j++) /* loops thru 1/2 twiddle values per stage */ { for (i = j; i <= n; i += le[l]) /* loops thru points per 1/2 twiddle */ { ip = i + le1[l]; t_r = array[0][ip - 1] * u_r - u_i * array[1][ip - 1]; t_i = array[1][ip - 1] * u_r + u_i * array[0][ip - 1]; array[0][ip - 1] = array[0][i - 1] - t_r; array[1][ip - 1] = array[1][i - 1] - t_i; array[0][i - 1] = array[0][i - 1] + t_r; array[1][i - 1] = array[1][i - 1] + t_i; } t_r = u_r * w_r[l] - w_i[l] * u_i; u_i = w_r[l] * u_i + w_i[l] * u_r; u_r = t_r; } } return array; } /* end of ifft_1d */ /** * FFT역변환을 수행함. 다만, 역변환시 FFT변환전의 원본값과 일치할수 있도록 값을 보정함. 원본 보존이 되지 않음. * @param array * 2차 더블형 배열 구조 이며, 0번째 행은 실수부값을 1번째 행에는 허수부값을 보관함. * @return * FFT역변환의 결과. */ public static double[][] ifft_1d_n( double[][] array ) { ifft_1d(array); int length = array[0].length; // Normalize for (int i = 0; i < length; i++) { array[0][i] = array[0][i] / (double)length; array[1][i] = 0; } return array; } }
반응형
'개발자 > Java' 카테고리의 다른 글
이클립스 폰트, 글자크기, 글꼴 바꾸기 (1) | 2014.09.12 |
---|---|
배열로부터 평균, 중간, 최소, 최대, 편차, 표준편차값 등을 계산하는 클래스 (0) | 2013.03.26 |
더욱 좋은 정보를 제공하겠습니다.~ ^^