반응형
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 |
취업, 창업의 막막함, 외주 관리, 제품 부재!
당신의 고민은 무엇입니까? 현실과 동떨어진 교육, 실패만 반복하는 외주 계약,
아이디어는 있지만 구현할 기술이 없는 막막함.
우리는 알고 있습니다. 문제의 원인은 '명확한 학습, 실전 경험과 신뢰할 수 있는 기술력의 부재'에서 시작됩니다.
이제 고민을 멈추고, 캐어랩을 만나세요!
코딩(펌웨어), 전자부품과 디지털 회로설계, PCB 설계 제작, 고객(시장/수출) 발굴과 마케팅 전략으로 당신을 지원합니다.
제품 설계의 고수는 성공이 만든 게 아니라 실패가 만듭니다. 아이디어를 양산 가능한 제품으로!
귀사의 제품을 만드세요. 교육과 개발 실적으로 신뢰할 수 있는 파트너를 확보하세요.
지난 30년 여정, 캐어랩이 얻은 모든 것을 함께 나누고 싶습니다.
귀사가 성공하기까지의 긴 고난의 시간을 캐어랩과 함께 하세요.
캐어랩