2021年12月5日 星期日

DIT FFT 範例修改

參考原始碼: https://cnx.org/contents/qAa9OhlP@2.44:zmcmahhR@7/Decimation-in-time-DIT-Radix-2-FFT 

範例修改: mfft.c

#include "math.h"
#include "stdio.h"
void mfft(double *real, double *imag, int nT) {
  int m = 0;
  for (int i = 0; i < 30; i++) if (nT == (1 << i)) {
    m = i;
    break;
  }
  if ( m < 1) return;

  const int halfT = nT >> 1;
  for (int i = 1, j = 0; i < nT - 1; i++) {// bit-reverse
    int k = halfT;
    while (j >= k) {
      j -= k;
      k >>= 1;
    }
    j += k;
    if (i < j) {
      double temp = real[i];
      real[i] = real[j];
      real[j] = temp;
      temp = imag[i];
      imag[i] = imag[j];
      imag[j] = temp;
    }
  }
  double PIx2 = - M_PI * 2;
  for (int i = 0, nx2 = 1; i < m; i++) { // radix-2 DIT FFT
    int k = nx2;
    nx2 += nx2;
    double delta = PIx2 / nx2;
    double theta = 0.0;
    for (int j = 0; j < k; j++) {
      double c = cos(theta);
      double s = sin(theta);
      theta += delta;
      for (int n = j; n < nT; n += nx2) {
        int h = n + k;
        double w1 = c * real[h] - s * imag[h];
        double w2 = s * real[h] + c * imag[h];
        real[h] = real[n] - w1;
        imag[h] = imag[n] - w2;
        real[n] += w1;
        imag[n] += w2;
      }
    }
  }
}   

int main() {
  double x[16];
  int n = sizeof(x) / sizeof(x[0]);
  double y[n];
  for (int i = 0; i < n; i++) {
    x[i] = i;
    y[i] = 0;
  }
  mfft(x, y , n);
  for (int i = 0; i < n; i++) printf("%.3f,\t %.3f\n", x[i], y[i]);
 
  return 0;
}

編譯並執行: g++ mfft.c && ./a.out

後記: 改成 Javascript 版本 mfft.js :
    mfft = (real, imag, nT) => {
        let m = 0;
        for (let i = 0; i < 30; i++) if (nT == (1 << i)) {
            m = i;
            break;
        }
        if ( m < 1) return;       
        const halfT = nT >> 1;
        for (let i = 1, j = 0; i < nT - 1; i++) {// bit-reverse
            let k = halfT;
            while (j >= k) {
                j -= k;
                k >>= 1;
            }
            j += k;
            if (i < j) {
                let temp = real[i];
                real[i] = real[j];
                real[j] = temp;
                temp = imag[i];
                imag[i] = imag[j];
                imag[j] = temp;
            }
        }
        let PIx2 = - Math.PI * 2;
        for (let i = 0, nx2 = 1; i < m; i++) { // radix-2 DIT FFT
            let k = nx2;
            nx2 += nx2;
            let delta = PIx2 / nx2;
            let theta = 0.0;
            for (let j = 0; j < k; j++) {
                let c = Math.cos(theta);
                let s = Math.sin(theta);
                theta += delta;
                for (let n = j; n < nT; n += nx2) {
                    let h = n + k;
                    let w1 = c * real[h] - s * imag[h];
                    let w2 = s * real[h] + c * imag[h];
                    real[h] = real[n] - w1;
                    imag[h] = imag[n] - w2;
                    real[n] += w1;
                    imag[n] += w2;
                }
            }
        }
    };   
    let n = 16;
    let x = new Float32Array(n);
    let y = new Float32Array(n);
    for (let i = 0; i < n; i++) {
        x[i] = i;
        y[i] = 0;
    }
    mfft(x, y , n);
    for (let i = 0; i < n; i++) console.log(`${Math.floor(x[i]*1e3 + 0.5)/1e3},\t ${Math.floor(y[i]*1e3 + 0.5)/1e3}`);
       

簡單 c 程式碼, 根據五行八卦相生相剋推斷吉凶

#include "stdio.h" // 五行: //               木2 //      水1           火3 //         金0     土4 // // 先天八卦 vs 五行 //                    ...