C++ C+中的任意长度FFT+;

C++ C+中的任意长度FFT+;,c++,fft,C++,Fft,我试图从这个网页运行C++ FFT代码: < C++ >很新,所以不知道如何运行它。本质上,我想把一个实向量和一个IMAG向量传递给程序,并生成一个实向量和IMAG向量的输出 说我的真实向量={1,2,3,4,5} 说我的IMAG_VEC={0,1,0,1,0} 我正在粘贴我拥有的代码及其编译。但是在哪里输入以及如何获得输出(对于上述向量) //FftRealPairTest.cpp #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括“FftRealPair.hpp” 使用std

我试图从这个网页运行C++ FFT代码:

< C++ >很新,所以不知道如何运行它。本质上,我想把一个实向量和一个IMAG向量传递给程序,并生成一个实向量和IMAG向量的输出

说我的真实向量={1,2,3,4,5}

说我的IMAG_VEC={0,1,0,1,0}

我正在粘贴我拥有的代码及其编译。但是在哪里输入以及如何获得输出(对于上述向量)


//FftRealPairTest.cpp
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括“FftRealPair.hpp”
使用std::cout;
使用std::endl;
使用std::vector;
//私有函数原型
静态孔隙测试FFT(int n);
静态向量随机数(int n);
//可变全局变量
静态双maxLogError=-无穷大;
//随机数生成
std::default_random_引擎randGen((std::random_device())());
int main(){
//测试不同尺寸的FFT
for(int i=0,prev=0;i prev){
testFft(n);
prev=n;
}
}
cout如果您查看发布的,第一个函数
transform()
接受两个输入:实向量和虚向量。FFT是“就地”完成的,因此结果以相同的向量返回

如果您想尝试一下,可以查看
testFft()
并初始化
inputReal
inputImag
使用您的数据。然后将向量复制到
actualOutReal
actualOutImag
(以避免覆盖原始数据)并传递给transform


之后,您的输出应该是相同的向量(
actualOutReal
actualOutImag
)。

此代码正是您想要的(需要C++11):

#包括
#包括
#包括“FftRealPair.hpp”
int main(){
//声明输入
向量实{1,2,3,4,5};
向量imag{0,1,0,1,0};
//做FFT
Fft::变换(实、imag);
//打印结果
对于(std::size_t i=0;istd::cout非常感谢Tost的指导!我试过了,但无法以矢量形式打印正确的输出。int main(){vector inputreal({1,2,3,4,5});vector inputimag({0,1,0,1,0});vector actualoutreal(inputreal);vector actualoutimag(inputimag);Fft::transform(actualoutreal,actualoutimag)我现在可以打印结果了吗?谢谢!std::谢谢Nayuki-我的下一个挑战是在SWIFT中调用它。。
//FftRealPairTest.cpp
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <random>
#include <vector>
#include "FftRealPair.hpp"

using std::cout;
using std::endl;
using std::vector;


// Private function prototypes
static void testFft(int n);

static vector<double> randomReals(int n);

// Mutable global variable
static double maxLogError = -INFINITY;

// Random number generation
std::default_random_engine randGen((std::random_device())());


int main() {
    // Test diverse size FFTs
    for (int i = 0, prev = 0; i <= 4; i++) {
        int n = static_cast<int>(std::lround(std::pow(1500.0, i / 100.0)));
        if (n > prev) {
            testFft(n);
            prev = n;

        }

    }

    cout << endl;
    cout << "Max log err = " << std::setprecision(3) << maxLogError << endl;
    cout << "Test " << (maxLogError < -10 ? "passed" : "failed") << endl;
    return EXIT_SUCCESS;
}


static void testFft(int n) {
    vector<double> inputreal(randomReals(n));
    vector<double> inputimag(randomReals(n));

    vector<double> actualoutreal(inputreal);
    vector<double> actualoutimag(inputimag);
    Fft::transform(actualoutreal, actualoutimag);
}


static vector<double> randomReals(int n) {
    std::uniform_real_distribution<double> valueDist(-1.0, 1.0);
    vector<double> result;
    for (int i = 0; i < n; i++)
        result.push_back(valueDist(randGen));
    return result;
}

/////////////////

//FftRealPair.cpp
/*
 * Free FFT and convolution (C++)
 *
 * Copyright (c) 2017 Project Nayuki. (MIT License)
 * https://www.nayuki.io/page/free-small-fft-in-multiple-languages
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 * - The above copyright notice and this permission notice shall be included in
 *   all copies or substantial portions of the Software.
 * - The Software is provided "as is", without warranty of any kind, express or
 *   implied, including but not limited to the warranties of merchantability,
 *   fitness for a particular purpose and noninfringement. In no event shall the
 *   authors or copyright holders be liable for any claim, damages or other
 *   liability, whether in an action of contract, tort or otherwise, arising from,
 *   out of or in connection with the Software or the use or other dealings in the
 *   Software.
 */

#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include "FftRealPair.hpp"

using std::size_t;
using std::vector;


// Private function prototypes
static size_t reverseBits(size_t x, int n);


void Fft::transform(vector<double> &real, vector<double> &imag) {
    size_t n = real.size();
    if (n != imag.size())
        throw "Mismatched lengths";
    if (n == 0)
        return;
    else if ((n & (n - 1)) == 0)  // Is power of 2
        transformRadix2(real, imag);
    else  // More complicated algorithm for arbitrary sizes
        transformBluestein(real, imag);
}


void Fft::inverseTransform(vector<double> &real, vector<double> &imag) {
    transform(imag, real);
}


void Fft::transformRadix2(vector<double> &real, vector<double> &imag) {
    // Length variables
    size_t n = real.size();
    if (n != imag.size())
        throw "Mismatched lengths";
    int levels = 0;  // Compute levels = floor(log2(n))
    for (size_t temp = n; temp > 1U; temp >>= 1)
        levels++;
    if (static_cast<size_t>(1U) << levels != n)
        throw "Length is not a power of 2";

    // Trignometric tables
    vector<double> cosTable(n / 2);
    vector<double> sinTable(n / 2);
    for (size_t i = 0; i < n / 2; i++) {
        cosTable[i] = std::cos(2 * M_PI * i / n);
        sinTable[i] = std::sin(2 * M_PI * i / n);
    }

    // Bit-reversed addressing permutation
    for (size_t i = 0; i < n; i++) {
        size_t j = reverseBits(i, levels);
        if (j > i) {
            std::swap(real[i], real[j]);
            std::swap(imag[i], imag[j]);
        }
    }

    // Cooley-Tukey decimation-in-time radix-2 FFT
    for (size_t size = 2; size <= n; size *= 2) {
        size_t halfsize = size / 2;
        size_t tablestep = n / size;
        for (size_t i = 0; i < n; i += size) {
            for (size_t j = i, k = 0; j < i + halfsize; j++, k += tablestep) {
                size_t l = j + halfsize;
                double tpre =  real[l] * cosTable[k] + imag[l] * sinTable[k];
                double tpim = -real[l] * sinTable[k] + imag[l] * cosTable[k];
                real[l] = real[j] - tpre;
                imag[l] = imag[j] - tpim;
                real[j] += tpre;
                imag[j] += tpim;
            }
        }
        if (size == n)  // Prevent overflow in 'size *= 2'
            break;
    }
}


void Fft::transformBluestein(vector<double> &real, vector<double> &imag) {
    // Find a power-of-2 convolution length m such that m >= n * 2 + 1
    size_t n = real.size();
    if (n != imag.size())
        throw "Mismatched lengths";
    size_t m = 1;
    while (m / 2 <= n) {
        if (m > SIZE_MAX / 2)
            throw "Vector too large";
        m *= 2;
    }

    // Trignometric tables
    vector<double> cosTable(n), sinTable(n);
    for (size_t i = 0; i < n; i++) {
        unsigned long long temp = static_cast<unsigned long long>(i) * i;
        temp %= static_cast<unsigned long long>(n) * 2;
        double angle = M_PI * temp / n;
        // Less accurate alternative if long long is unavailable: double angle = M_PI * i * i / n;
        cosTable[i] = std::cos(angle);
        sinTable[i] = std::sin(angle);
    }

    // Temporary vectors and preprocessing
    vector<double> areal(m), aimag(m);
    for (size_t i = 0; i < n; i++) {
        areal[i] =  real[i] * cosTable[i] + imag[i] * sinTable[i];
        aimag[i] = -real[i] * sinTable[i] + imag[i] * cosTable[i];
    }
    vector<double> breal(m), bimag(m);
    breal[0] = cosTable[0];
    bimag[0] = sinTable[0];
    for (size_t i = 1; i < n; i++) {
        breal[i] = breal[m - i] = cosTable[i];
        bimag[i] = bimag[m - i] = sinTable[i];
    }

    // Convolution
    vector<double> creal(m), cimag(m);
    convolve(areal, aimag, breal, bimag, creal, cimag);

    // Postprocessing
    for (size_t i = 0; i < n; i++) {
        real[i] =  creal[i] * cosTable[i] + cimag[i] * sinTable[i];
        imag[i] = -creal[i] * sinTable[i] + cimag[i] * cosTable[i];
    }
}


void Fft::convolve(const vector<double> &x, const vector<double> &y, vector<double> &out) {
    size_t n = x.size();
    if (n != y.size() || n != out.size())
        throw "Mismatched lengths";
    vector<double> outimag(n);
    convolve(x, vector<double>(n), y, vector<double>(n), out, outimag);
}


void Fft::convolve(
                   const vector<double> &xreal, const vector<double> &ximag,
                   const vector<double> &yreal, const vector<double> &yimag,
                   vector<double> &outreal, vector<double> &outimag) {

    size_t n = xreal.size();
    if (n != ximag.size() || n != yreal.size() || n != yimag.size()
        || n != outreal.size() || n != outimag.size())
        throw "Mismatched lengths";

    vector<double> xr(xreal);
    vector<double> xi(ximag);
    vector<double> yr(yreal);
    vector<double> yi(yimag);
    transform(xr, xi);
    transform(yr, yi);

    for (size_t i = 0; i < n; i++) {
        double temp = xr[i] * yr[i] - xi[i] * yi[i];
        xi[i] = xi[i] * yr[i] + xr[i] * yi[i];
        xr[i] = temp;
    }
    inverseTransform(xr, xi);

    for (size_t i = 0; i < n; i++) {  // Scaling (because this FFT implementation omits it)
        outreal[i] = xr[i] / n;
        outimag[i] = xi[i] / n;
    }
}


static size_t reverseBits(size_t x, int n) {
    size_t result = 0;
    for (int i = 0; i < n; i++, x >>= 1)
        result = (result << 1) | (x & 1U);
    return result;
}



///////////



//FftRealPair.hpp
/*
 * Free FFT and convolution (C++)
 *
 * Copyright (c) 2017 Project Nayuki. (MIT License)
 * https://www.nayuki.io/page/free-small-fft-in-multiple-languages
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 * - The above copyright notice and this permission notice shall be included in
 *   all copies or substantial portions of the Software.
 * - The Software is provided "as is", without warranty of any kind, express or
 *   implied, including but not limited to the warranties of merchantability,
 *   fitness for a particular purpose and noninfringement. In no event shall the
 *   authors or copyright holders be liable for any claim, damages or other
 *   liability, whether in an action of contract, tort or otherwise, arising from,
 *   out of or in connection with the Software or the use or other dealings in the
 *   Software.
 */

#pragma once

#include <vector>


namespace Fft {

    /*
     * Computes the discrete Fourier transform (DFT) of the given complex vector, storing the result back into the vector.
     * The vector can have any length. This is a wrapper function.
     */
    void transform(std::vector<double> &real, std::vector<double> &imag);


    /*
     * Computes the inverse discrete Fourier transform (IDFT) of the given complex vector, storing the result back into the vector.
     * The vector can have any length. This is a wrapper function. This transform does not perform scaling, so the inverse is not a true inverse.
     */
    void inverseTransform(std::vector<double> &real, std::vector<double> &imag);





    /*
     * Computes the discrete Fourier transform (DFT) of the given complex vector, storing the result back into the vector.
     * The vector's length must be a power of 2. Uses the Cooley-Tukey decimation-in-time radix-2 algorithm.
     */
    void transformRadix2(std::vector<double> &real, std::vector<double> &imag);


    /*
     * Computes the discrete Fourier transform (DFT) of the given complex vector, storing the result back into the vector.
     * The vector can have any length. This requires the convolution function, which in turn requires the radix-2 FFT function.
     * Uses Bluestein's chirp z-transform algorithm.
     */
    void transformBluestein(std::vector<double> &real, std::vector<double> &imag);


    /*
     * Computes the circular convolution of the given real vectors. Each vector's length must be the same.
     */
    void convolve(const std::vector<double> &x, const std::vector<double> &y, std::vector<double> &out);


    /*
     * Computes the circular convolution of the given complex vectors. Each vector's length must be the same.
     */
    void convolve(
                  const std::vector<double> &xreal, const std::vector<double> &ximag,
                  const std::vector<double> &yreal, const std::vector<double> &yimag,
                  std::vector<double> &outreal, std::vector<double> &outimag);
}
#include <cstddef>
#include <vector>
#include "FftRealPair.hpp"

int main() {
    // Declare input
    std::vector<double> real{1, 2, 3, 4, 5};
    std::vector<double> imag{0, 1, 0, 1, 0};

    // Do FFT
    Fft::transform(real, imag);

    // Print result
    for (std::size_t i = 0; i < real.size(); i++) {
        std::cout << real[i] << "    " << imag[i] << std::endl;
    }

    return 0;
}