LoginSignup
0
0

More than 3 years have passed since last update.

FFTWを使う

Last updated at Posted at 2019-05-27

はじめに

FFTWの使い方を説明します。
DFT (discrete fourier transform) や DCT (discrete cosine transform) が計算できます。

download & make

FFTWをdownload / makeします。

console
mkdir fftw
cd fftw/
wget http://www.fftw.org/fftw-3.3.8.tar.gz
tar xzvf fftw-3.3.8.tar.gz 
cd fftw-3.3.8/
./configure
make
sudo make install

code example

FFTWを使ってDCT IVを計算する例を示します。

次の関数でDCTのplanを作成します。
 fftw_plan_r2r_1d

引数fftw_r2r_kindでDCT typeが指定できます。DCT IVは次を指定します。
 FFTW_REDFT11 (DCT IV)

DCT IV の式は次の通りです。

X_k = 2 \sum^{N-1}_{n=0}{x_n \cos \frac{(2n+1)(2k+1)}{4N}} \\

DCTの実行はfftw_executeで行います。

DCT IVを2度実行して復元できることを確認します。
ただ定義式そのままでは復元できないため計算後に2Nで割ります。

makefile
CFLAGS=-I. -Wall -Werror -O2
INCS=
OBJS=test.o
LIBS=-lfftw3 -lm
TARGET=test

%.o: %.c $(INCS)
    $(CC) $(CFLAGS) -c -o $@ $<

$(TARGET): $(OBJS)
    $(CC) $(CFLAGS) -o $@ $^ $(LIBS)

clean:
    rm -rf $(TARGET) *.o
test.c
#include <stdio.h>
#include <inttypes.h>
#include <fftw3.h>

inline uint64_t RDTSCP()
{
    uint32_t hi, lo, aux=0;
    __asm__ volatile("rdtscp" : "=a" (lo), "=d" (hi), "=c" (aux));
    return ((uint64_t)hi << 32) | lo;
}

uint64_t _rdtscp_start, _rdtscp_end;
inline void tic()
{
  _rdtscp_start = RDTSCP();
}

inline void toc(const char* str)
{
  _rdtscp_end = RDTSCP();
  printf("profile:%s %" PRIu64 " clock\n", str, _rdtscp_end-_rdtscp_start);
}

int main(int argc, char* argv[])
{
  int i, w=32, len=1024;
  fftw_plan p;
  static double in[1024], out[1024];

  for (i=0; i<1024; i++) {
    in[i] = i;
  }
  printf("input\n");
  for (i=0; i<len; i++) {
    printf("%+05.3e ", in[i]);
    if ((i+1)%32 == 0) {
      printf("\n");
    }
  }

  p = fftw_plan_r2r_1d(len/*int n*/, in, out,
    FFTW_REDFT11 /* fftw_r2r_kind */, FFTW_ESTIMATE /* flags */);
  tic();
  fftw_execute(p);
  toc("");

  printf("output forward\n");
  for (i=0; i<len; i++) {
    printf("%+05.3e ", out[i]);
    if ((i+1)%w == 0) {
      printf("\n");
    }
  }

  p = fftw_plan_r2r_1d(len/*int n*/, out, in,
    FFTW_REDFT11 /* fftw_r2r_kind */, FFTW_ESTIMATE /* flags */);
  tic();
  fftw_execute(p);
  toc("");

  printf("output inverse\n");
  for (i=0; i<len; i++) {
    printf("%+05.3e ", in[i]/2048.0);
    if ((i+1)%w == 0) {
      printf("\n");
    }
  }

  return 0;
}

実行結果

console
input
+0.000e+00 +1.000e+00 +2.000e+00 +3.000e+00 +4.000e+00 +5.000e+00 +6.000e+00 +7.000e+00 +8.000e+00 +9.000e+00 +1.000e+01 +1.100e+01 +1.200e+01 +1.300e+01 +1.400e+01 +1.500e+01 +1.600e+01 +1.700e+01 +1.800e+01 +1.900e+01 +2.000e+01 +2.100e+01 +2.200e+01 +2.300e+01 +2.400e+01 +2.500e+01 +2.600e+01 +2.700e+01 +2.800e+01 +2.900e+01 +3.000e+01 +3.100e+01 
...
+9.920e+02 +9.930e+02 +9.940e+02 +9.950e+02 +9.960e+02 +9.970e+02 +9.980e+02 +9.990e+02 +1.000e+03 +1.001e+03 +1.002e+03 +1.003e+03 +1.004e+03 +1.005e+03 +1.006e+03 +1.007e+03 +1.008e+03 +1.009e+03 +1.010e+03 +1.011e+03 +1.012e+03 +1.013e+03 +1.014e+03 +1.015e+03 +1.016e+03 +1.017e+03 +1.018e+03 +1.019e+03 +1.020e+03 +1.021e+03 +1.022e+03 +1.023e+03 
profile: 130306 clock
output forward
+4.845e+05 -5.393e+05 +2.329e+05 -2.080e+05 +1.378e+05 -1.283e+05 +9.762e+04 -9.274e+04 +7.556e+04 -7.259e+04 +6.162e+04 -5.963e+04 +5.202e+04 -5.059e+04 +4.501e+04 -4.393e+04 +3.966e+04 -3.883e+04 +3.545e+04 -3.478e+04 +3.205e+04 -3.150e+04 +2.924e+04 -2.878e+04 +2.689e+04 -2.650e+04 +2.488e+04 -2.455e+04 +2.316e+04 -2.287e+04 +2.166e+04 -2.140e+04 
...
+1.025e+03 -1.025e+03 +1.025e+03 -1.025e+03 +1.024e+03 -1.024e+03 +1.024e+03 -1.024e+03 +1.024e+03 -1.024e+03 +1.024e+03 -1.024e+03 +1.024e+03 -1.024e+03 +1.024e+03 -1.024e+03 +1.024e+03 -1.024e+03 +1.024e+03 -1.024e+03 +1.024e+03 -1.024e+03 +1.024e+03 -1.024e+03 +1.024e+03 -1.024e+03 +1.024e+03 -1.024e+03 +1.024e+03 -1.024e+03 +1.024e+03 -1.024e+03 
profile: 144551 clock
output inverse
+1.081e-13 +1.000e+00 +2.000e+00 +3.000e+00 +4.000e+00 +5.000e+00 +6.000e+00 +7.000e+00 +8.000e+00 +9.000e+00 +1.000e+01 +1.100e+01 +1.200e+01 +1.300e+01 +1.400e+01 +1.500e+01 +1.600e+01 +1.700e+01 +1.800e+01 +1.900e+01 +2.000e+01 +2.100e+01 +2.200e+01 +2.300e+01 +2.400e+01 +2.500e+01 +2.600e+01 +2.700e+01 +2.800e+01 +2.900e+01 +3.000e+01 +3.100e+01 
...
+9.920e+02 +9.930e+02 +9.940e+02 +9.950e+02 +9.960e+02 +9.970e+02 +9.980e+02 +9.990e+02 +1.000e+03 +1.001e+03 +1.002e+03 +1.003e+03 +1.004e+03 +1.005e+03 +1.006e+03 +1.007e+03 +1.008e+03 +1.009e+03 +1.010e+03 +1.011e+03 +1.012e+03 +1.013e+03 +1.014e+03 +1.015e+03 +1.016e+03 +1.017e+03 +1.018e+03 +1.019e+03 +1.020e+03 +1.021e+03 +1.022e+03 +1.023e+03 
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0