#pragma once
#include <complex>
#include <vector>
class Transform
{
public:
static void VandermondeDFT(
int n,
std::vector<std::complex<double>>& a,
std::vector<std::complex<double>>& y);
static void InverseVandermondeDFT(
int n,
std::vector<std::complex<double>>& a,
std::vector<std::complex<double>>& y);
static std::vector<std::complex<double>> DFT(
std::vector<double>& x, std::vector<double>& f);
static std::vector<double> InverseDFT(
std::vector<double>& f,
std::vector<std::complex<double>>& X);
/*
* Reference: "Elementary Numerical Analysis:
* An Algorithmic Approach Third Edition" (c)
* 1980 by S. D. Conte and Carl de Boor
* Section 6.5 pages 268 - 277 and Section 6.6
* pages 277 - 283
* Input to FFT
* Z1, Z2 complex n-vectors
* n the length of the vectors
* inzee
* = 1 transform in Z1
* = 2 transform in Z2
* Constructs the discrete Fourier transform in the Cooley-
* Tukey way, but with a twist.
*/
static void FFT(
std::vector<std::complex<double>>& Z1,
int& after, int& now, int& before, int& inzee,
std::vector<std::complex<double>>& Z2);
/*
* This computes an in - place complex - to - complex FFT
* x and y are the real and imaginary arrays of 2^m points.
* dir = 1 gives forward transform
* dir = -1 gives reverse transform
* see http://astronomy.swin.edu.au/~pbourke/analysis/dft/
*/
static void FFT(short dir, int m,
std::vector<double>& x, std::vector<double>& y);
/*
* Reference: "Introduction to Algorithms" by
* Thomas H. Cormen, Charles E. Leiserson, and
* Ronald L. Rivest, pages 794 - 795
*/
static void IterativeFFT(
std::vector<std::complex<double>>& a,
std::vector<std::complex<double>>& A);
/*
* Reference: "Introduction to Algorithms" by
* Thomas H. Cormen, Charles E. Leiserson, and
* Ronald L. Rivest, page 788
*/
static std::vector<std::complex<double>> RecursiveFFT(
std::vector<std::complex<double>>& a);
};
#include "Transform.h"
void Transform::VandermondeDFT(
int n,
std::vector<std::complex<double>>& a,
std::vector<std::complex<double>>& y)
{
double pi = 4.0 * atan(1.0);
std::complex<double> z(0.0, 2.0 * pi / n);
std::complex<double> omegaN = exp(z);
std::vector<std::vector<std::complex<double>>> V(n);
for (int k = 0; k < n; k++)
{
V[k].resize(n);
for (int j = 0; j < n; j++)
{
V[k][j] = std::pow(omegaN, k * j);
}
}
for (int k = 0; k < n; k++)
{
std::complex<double> sum = 0.0;
for (int j = 0; j < n; j++)
{
sum += V[k][j] * a[j];
}
y[k] = sum;
}
}
void Transform::InverseVandermondeDFT(
int n,
std::vector<std::complex<double>>& a,
std::vector<std::complex<double>>& y)
{
double pi = 4.0 * atan(1.0);
std::complex<double> nc = { static_cast<double>(n), 0.0 };
std::complex<double> z(0.0, 2.0 * pi / n);
std::complex<double> omegaN = exp(z);
std::vector<std::vector<std::complex<double>>> invV(n);
for (int k = 0; k < n; k++)
{
invV[k].resize(n);
for (int j = 0; j < n; j++)
{
invV[k][j] = std::pow(omegaN, -k * j);
}
}
for (int k = 0; k < n; k++)
{
std::complex<double> sum = 0.0;
for (int j = 0; j < n; j++)
{
sum += invV[k][j] * y[j];
}
a[k] = sum / nc;
}
}
std::vector<std::complex<double>> Transform::DFT(
std::vector<double>& x, std::vector<double>& f)
{
int length = static_cast<int>(x.size());
double pi = 4.0 * atan(1.0);
double pi2oN = 2.0 * pi / length;
int k, n;
std::vector<double> X(length);
std::vector<double> Y(length);
std::vector<std::complex<double>> Z(length);
f.resize(length);
for (k = 0; k < length; k++)
{
X[k] = Y[k] = 0;
for (n = 0; n < length; n++)
{
X[k] += x[n] * cos(pi2oN * k * n);
Y[k] -= x[n] * sin(pi2oN * k * n);
}
f[k] = pi2oN * k;
X[k] /= length;
Y[k] /= length;
Z[k] = { X[k], Y[k] };
}
return Z;
}
std::vector<double> Transform::InverseDFT(
std::vector<double>& f,
std::vector<std::complex<double>>& X)
{
double imag = 0.0;
int length = static_cast<int>(X.size());
std::vector<double> x(length);
for (int n = 0; n < length; n++)
{
imag = x[n] = 0.0;
for (int k = 0; k < length; k++)
{
x[n] += X[k]._Val[0] * cos(f[k] * n)
- X[k]._Val[1] * sin(f[k] * n);
imag += X[k]._Val[0] * sin(f[k] * n)
+ X[k]._Val[1] * cos(f[k] * n);
}
}
return x;
}
static void FFTStep(
std::vector<std::complex<double>>& Zinp,
int after, int now, int before,
std::vector<std::complex<double>>& Zout)
{
double angle = 0.0, ratio = 0.0;
double twoPi = 2.0 * 4.0 * atan(1.0);
int ia = 0, ib = 0, inp = 0, j = 0;
std::complex<double> arg = 1.0, omega = 0, value = 0;
angle = twoPi / ((now + 1) * (after + 1));
omega = std::complex<double>(cos(angle), -sin(angle));
int address = 1;
for (int i = 1; i <= now; i++)
{
for (int j = 1; j <= after; j++)
{
for (int k = 1; k <= before; k++)
{
address = i * j * k;
if (address < Zout.size())
Zout[address] = { 0.0, 0.0 };
}
}
}
address = 1;
for (int j = 1; j <= now; j++)
{
for (ia = 1; ia <= after; ia++)
{
for (ib = 1; ib <= before; ib++)
{
int address = j * ia * ib;
if (address < Zinp.size())
value = Zinp[address];
for (inp = now - 1; inp >= 1; inp--)
{
address = ia * ib * inp;
if (address < Zinp.size())
value = value * arg + Zinp[address];
}
address = ia * j * ib;
if (address < Zout.size())
Zout[address] = value;
}
arg *= omega;
}
}
}
void Transform::FFT(
std::vector<std::complex<double>>& Z1,
int& after, int& now, int& before, int& inzee,
std::vector<std::complex<double>>& Z2)
{
std::vector<int> prime =
{ 0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97 };
int next = 1, nextmx = 25;
after = 1;
before = (int)Z1.size();
now = 1;
Label10:
if (before / prime[next] * prime[next] < before)
{
next++;
if (next <= nextmx)
goto Label10;
else
{
now = before;
before = 1;
}
}
else
{
now = prime[next];
before /= prime[next];
}
if (inzee == 1)
FFTStep(Z1, after, now, before, Z2);
else
FFTStep(Z2, after, now, before, Z1);
inzee = 3 - inzee;
if (before == 1)
return;
after *= now;
goto Label10;
}
void Transform::FFT(short dir, int m,
std::vector<double>& x, std::vector<double>& y)
{
int n, i, i1, j, k, i2, l, l1, l2;
double c1, c2, tx, ty, t1, t2, u1, u2, z;
// Calculate the number of points
n = 1;
for (i = 0; i < m; i++)
n *= 2;
// Do the bit reversal
i2 = n >> 1;
j = 0;
for (i = 0; i < n - 1; i++)
{
if (i < j)
{
tx = x[i];
ty = y[i];
x[i] = x[j];
y[i] = y[j];
x[j] = tx;
y[j] = ty;
}
k = i2;
while (k <= j)
{
j -= k;
k >>= 1;
}
j += k;
}
// Compute the FFT
c1 = -1.0;
c2 = 0.0;
l2 = 1;
for (l = 0; l < m; l++)
{
l1 = l2;
l2 <<= 1;
u1 = 1.0;
u2 = 0.0;
for (j = 0; j < l1; j++)
{
for (i = j; i < n; i += l2)
{
i1 = i + l1;
t1 = u1 * x[i1] - u2 * y[i1];
t2 = u1 * y[i1] + u2 * x[i1];
x[i1] = x[i] - t1;
y[i1] = y[i] - t2;
x[i] += t1;
y[i] += t2;
}
z = u1 * c1 - u2 * c2;
u2 = u1 * c2 + u2 * c1;
u1 = z;
}
c2 = sqrt((1.0 - c1) / 2.0);
if (dir == 1)
c2 = -c2;
c1 = sqrt((1.0 + c1) / 2.0);
}
// Scaling for forward transform
if (dir == 1)
{
for (i = 0; i < n; i++)
{
x[i] /= n;
y[i] /= n;
}
}
}
static void FFTBase(
std::vector<std::complex<double>> a,
std::vector<std::complex<double>> A)
{
double pi = 4.0 * atan(1.0);
int n = static_cast<int>(a.size());
for (int s = 1; s <= log2(n); s++)
{
int m = static_cast<int>(pow(2, s));
std::complex<double> z(0.0, 2.0 * pi / m);
std::complex<double> omegaM = exp(z);
for (int k = 0; k <= n - 1; k += m)
{
std::complex<double> omega = { 1.0, 0.0 };
for (int j = 0; j <= m / 2 - 1; j++)
{
std::complex<double> t = omega * A[k + j + m / 2];
std::complex<double> u = A[k + j];
std::complex<double> jc = { static_cast<double>(j), 0.0 };
A[k + j] = u + jc;
A[k + j + m / 2] = u - t;
omega *= omegaM;
}
}
}
}
static int Reverse(int k)
{
int digits[32] = { 0 }, i = 0;
while (k > 0)
{
int digit = k & 1;
k >>= 1;
digits[i++] = digit;
}
int result = digits[0];
for (int j = 1; j < i; j++)
result = result * 2 + digits[j];
return result;
}
static void BitReverseCopy(
std::vector<std::complex<double>>& a,
std::vector<std::complex<double>>& A)
{
int n = static_cast<int>(a.size());
for (int k = 0; k <= n - 1; k++)
A[Reverse(k)] = a[k];
}
void Transform::IterativeFFT(
std::vector<std::complex<double>>& a,
std::vector<std::complex<double>>& A)
{
BitReverseCopy(a, A);
double pi = 4.0 * atan(1.0);
int n = static_cast<int>(a.size());
for (int s = 1; s <= static_cast<int>(log2(n)); s++)
{
int m = static_cast<int>(pow(2.0, s));
std::complex<double> z(0.0, 2.0 * pi / m);
std::complex<double> omegaM = exp(z);
std::complex<double> omega = { 1.0, 0.0 };
for (int j = 0; j <= m / 2 - 1; j++)
{
for (int k = j; k <= n - 1; k += m)
{
std::complex<double> t = omega * A[k + m / 2];
std::complex<double> u = A[k];
A[k] = u + t;
A[k + m / 2] = u - t;
omega *= omegaM;
}
}
}
}
std::vector<std::complex<double>> Transform::RecursiveFFT(
std::vector<std::complex<double>>& a)
{
int n = static_cast<int>(a.size());
if (n == 1)
return a;
std::vector<std::complex<double>> a0;
std::vector<std::complex<double>> a1;
std::vector<std::complex<double>> y0;
std::vector<std::complex<double>> y1;
for (int i = 0; i <= n - 2; i++)
a0.push_back(a[i]);
for (int i = 1; i <= n - 1; i++)
a1.push_back(a[i]);
y0 = RecursiveFFT(a0);
y1 = RecursiveFFT(a1);
double pi = 4.0 * atan(1.0);
std::complex<double> z(0.0, 2.0 * pi / n);
std::complex<double> omegaN = exp(z);
std::complex<double> omega(1.0, 0.0);
std::vector<std::complex<double>> y(n, 0.0);
for (int k = 0; k <= n / 2 - 1; k++)
{
y[k] = y0[k] + omega * y1[k];
y[(long long)k + n / 2] = y0[k] - omega * y1[k];
omega *= omegaN;
}
return y;
}
// CooleyTukeyConsole.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <algorithm>
#include <complex>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>
#include "Transform.h"
int M = 0, N = 0, Sn = 2048;
static double SimpsonsRule(
double a, double b, int n,
double (*f)(double))
{
double h = (b - a) / n;
double h2 = 2.0 * h;
double s = 0.0;
double t = 0.0;
double x = a + h;
for (int i = 1; i < n; i += 2)
{
s += f(x);
x += h2;
}
x = a + h2;
for (int i = 2; i < n; i += 2)
{
t += f(x);
x += h2;
}
return h * (f(a) + 4 * s + 2 * t + f(b)) / 3.0;
}
static double f(double x)
{
return x * x * sin(x);
}
static double AMf(double x)
{
return f(x) * cos(M * x);
}
static double BMf(double x)
{
return f(x) * sin(M * x);
}
static double AM(int m)
{
M = m;
double pi = 4.0 * atan(1.0), twoPi = pi + pi;
double integ = SimpsonsRule(-pi, pi, Sn, AMf);
double value = integ / twoPi;
if (m == 0)
return value;
else
return 2.0 * value;
}
static double BM(int m)
{
M = m;
double pi = 4.0 * atan(1.0), twoPi = pi + pi;
double integ = SimpsonsRule(-pi, pi, Sn, BMf);
return 2.0 * integ / twoPi;
}
static void FormatPrint(double x)
{
if (fabs(x) < 1.0e-12)
x = 0.0;
std::cout << std::setw(13);
std::cout << std::setfill(' ');
std::cout << std::setprecision(10);
std::cout << x << '\t';
}
static void FormatPrint(std::complex<double> z)
{
std::cout << std::setw(13);
std::cout << std::setfill(' ');
std::cout << std::setprecision(10);
std::cout << z << '\t';
}
static void GetCooleyTukeyData(
int n0, int n1, int n2, int n3,
std::vector<double>& a,
std::vector<double>& b,
std::vector<double>& p,
std::vector<double>& x,
std::vector<double>& fx)
{
double pi = 4.0 * atan(1.0), twoPi = pi + pi;
x[0] = fx[0] = 0.0;
for (int i = 1; i <= n0; i++)
{
x[i] = twoPi * i / n0;
fx[i] = f(x[i]);
}
a[0] = AM(0);
for (int m = 1; m <= n0; m++)
{
a[m] = AM(m);
b[m] = BM(m);
}
for (int n = 0; n <= n0; n++)
{
double asum = 0.0;
for (int m = 1; m < n0; m++)
asum += a[m] * cos(m * x[n]);
double bsum = 0.0;
for (int m = 1; m <= n0; m++)
bsum += b[m] * sin(m * x[n]);
p[n] = a[0] / 2.0 + asum + bsum;
}
}
static void GetData(
int n0,
std::vector<double>& a,
std::vector<double>& b,
std::vector<double>& p,
std::vector<double>& x,
std::vector<double>& fx)
{
double pi = 4.0 * atan(1.0), twoPi = pi + pi;
for (int i = 0; i < n0; i++)
{
x[i] = twoPi * i / n0;
fx[i] = f(x[i]);
}
a[0] = AM(0);
for (int m = 1; m < n0; m++)
{
a[m] = AM(m);
b[m] = BM(m);
}
for (int n = 0; n < n0; n++)
{
double asum = 0.0;
for (int m = 1; m < n0; m++)
asum += a[m] * cos(m * x[n]);
double bsum = 0.0;
for (int m = 1; m < n0; m++)
bsum += b[m] * sin(m * x[n]);
p[n] = a[0] / 2.0 + asum + bsum;
}
}
static void TestCooleyTukey(
int n0, int n1, int n2, int n3)
{
int n01 = n0 + 1;
std::vector<double> a(n01), b(n01), p(n01), x(n01), fx(n01);
GetCooleyTukeyData(n0, n1, n2, n3, a, b, p, x, fx);
double pi = 4.0 * atan(1.0), twoPi = pi + pi;
int index1 = 1, inzee = 1;
std::vector<std::complex<double>> pp(n01);
std::vector<std::complex<double>> Z1 = { {0, 0} };
std::vector<std::complex<double>> Z2 = { {0, 0} };
Z1.resize(n01, 0.0);
Z2.resize(n01, 0.0);
for (int i = 1; i <= n0; i++)
Z1[i] = fx[i];
int after = 0, now = 0, before = 0;
Transform::FFT(Z1, after, now, before, inzee, Z2);
std::cout << "Forward Transform" << std::endl;
for (int i = 1; index1 < n01 && i <= after; i++)
{
for (int j = 1; index1 < n01 && j <= now; j++)
{
for (int k = 1; index1 < n01 && k <= before; k++)
{
std::cout << std::setw(5);
std::cout << std::setfill(' ');
std::cout << index1 << '\t';
FormatPrint(x[index1]);
FormatPrint(fx[index1]);
FormatPrint(Z1[index1]);
FormatPrint(Z2[index1]);
std::cout << std::endl;
index1++;
}
}
}
}
static void TestFFT(int n0)
{
int m = static_cast<int>(log2(n0));
std::vector<double> a(n0), b(n0), p(n0), x(n0), fx(n0);
GetData(n0, a, b, p, x, fx);
std::vector<double> xx(n0), yy(n0);
for (int i = 0; i < n0; i++)
xx[i] = fx[i];
Transform::FFT(+1, m, xx, yy);
std::cout << "Forward Transform" << std::endl;
for (int i = 0; i < n0; i++)
{
std::cout << std::setw(5);
std::cout << std::setfill(' ');
std::cout << i << '\t';
FormatPrint(x[i]);
FormatPrint(fx[i]);
FormatPrint(p[i]);
FormatPrint(xx[i]);
FormatPrint(yy[i]);
std::cout << std::endl;
if (i == n0 / 2)
break;
}
Transform::FFT(-1, m, xx, yy);
std::cout << "Backward Transform" << std::endl;
for (int i = 0; i < n0; i++)
{
std::cout << std::setw(5);
std::cout << std::setfill(' ');
std::cout << i << '\t';
FormatPrint(x[i]);
FormatPrint(fx[i]);
FormatPrint(p[i]);
FormatPrint(xx[i]);
FormatPrint(yy[i]);
std::cout << std::endl;
if (i == n0 / 2)
break;
}
}
static void TestIterativeFFT(int n0)
{
std::vector<double> a(n0), b(n0), p(n0), x(n0), fx(n0);
GetData(n0, a, b, p, x, fx);
double pi = 4.0 * atan(1.0), twoPi = pi + pi;
std::vector<std::complex<double>> AA(n0);
std::vector<std::complex<double>> aa(n0);
std::vector<std::complex<double>> yy(n0);
for (int i = 0; i < n0; i++)
aa[i] = fx[i];
Transform::IterativeFFT(aa, AA);
std::cout << "Forward Transform" << std::endl;
for (int i = 0; i < n0; i++)
{
std::cout << std::setw(5);
std::cout << std::setfill(' ');
std::cout << i << '\t';
FormatPrint(x[i]);
FormatPrint(fx[i]);
FormatPrint(AA[i]);
std::cout << std::endl;
}
}
static void TestRecursiveFFT(int n0)
{
std::vector<double> a(n0), b(n0), p(n0), x(n0), fx(n0);
std::vector<double> xx(n0), yy(n0);
GetData(n0, a, b, p, x, fx);
double pi = 4.0 * atan(1.0), twoPi = pi + pi;
std::vector<std::complex<double>> A = { {0, 0} };
std::vector<std::complex<double>> Y = { {0, 0} };
A.resize(n0);
for (int i = 0; i < n0; i++)
A[i] = fx[i];
Y = Transform::RecursiveFFT(A);
std::cout << "Forward Transform" << std::endl;
for (int i = 0; i < n0; i++)
{
std::cout << std::setw(5);
std::cout << std::setfill(' ');
std::cout << i << '\t';
FormatPrint(x[i]);
FormatPrint(fx[i]);
FormatPrint(A[i]);
FormatPrint(Y[i]);
std::cout << std::endl;
}
}
static void TestDFT(int n0)
{
std::vector<double> a(n0), b(n0), p(n0), x(n0), fx(n0), ff(n0);
GetData(n0, a, b, p, x, fx);
std::vector<std::complex<double>> zz = Transform::DFT(fx, ff);
std::cout << "Forward Transform" << std::endl;
for (int i = 0; i < n0; i++)
{
std::cout << std::setw(5);
std::cout << std::setfill(' ');
std::cout << i << '\t';
FormatPrint(x[i]);
FormatPrint(fx[i]);
FormatPrint(ff[i]);
FormatPrint(zz[i]);
std::cout << std::endl;
}
std::cout << "Inverse Transform" << std::endl;
std::vector<double> inv = Transform::InverseDFT(ff, zz);
for (int i = 0; i < n0; i++)
{
std::cout << std::setw(5);
std::cout << std::setfill(' ');
std::cout << i << '\t';
FormatPrint(x[i]);
FormatPrint(fx[i]);
FormatPrint(ff[i]);
FormatPrint(inv[i]);
std::cout << std::endl;
}
}
static void TestVandermondeDFT(int n0)
{
std::vector<double> a(n0), b(n0), p(n0), x(n0), fx(n0);
GetData(n0, a, b, p, x, fx);
std::vector<std::complex<double>> aa(n0);
std::vector<std::complex<double>> yy(n0);
for (int i = 0; i < n0; i++)
aa[i] = fx[i];
Transform::VandermondeDFT(n0, aa, yy);
std::cout << "Vandermonde DFT" << std::endl;
for (int i = 0; i < n0; i++)
{
std::cout << std::setw(5);
std::cout << std::setfill(' ');
std::cout << i << '\t';
FormatPrint(x[i]);
FormatPrint(fx[i]);
FormatPrint(p[i]);
FormatPrint(yy[i]);
std::cout << std::endl;
}
Transform::InverseVandermondeDFT(n0, aa, yy);
std::cout << "Inverse Vandermonde DFT" << std::endl;
for (int i = 0; i < n0; i++)
{
std::cout << std::setw(5);
std::cout << std::setfill(' ');
std::cout << i << '\t';
FormatPrint(x[i]);
FormatPrint(fx[i]);
FormatPrint(p[i]);
FormatPrint(aa[i]);
std::cout << std::endl;
}
}
static int Horner(char line[])
{
int length = static_cast<int>(strlen(line));
int sum = line[0] - '0';
for (int i = 1; i < length; i++)
sum = sum * 10 + line[i] - '0';
return sum;
}
int main()
{
char line[128];
while (true)
{
std::cout << "== Menu ==" << std::endl;
std::cout << "1 Cooley-Tukey" << std::endl;
std::cout << "2 FFT" << std::endl;
std::cout << "3 Iterative FFT" << std::endl;
std::cout << "4 Recursive FFT" << std::endl;
std::cout << "5 DFT" << std::endl;
std::cout << "6 Vandermonde DFT" << std::endl;
std::cout << "7 Exit" << std::endl;
std::cout << "Option 1 - 7 = ";
std::cin.getline(line, 128);
int option = Horner(line);
if (option == 7)
break;
if (option < 1 || option > 7)
{
std::cout << "Unknown Option Number" << std::endl;
continue;
}
if (option == 1)
{
int n0 = 0, n1 = 0, n2 = 0, n3 = 0;
std::cout << "n1 = ";
std::cin.getline(line, 128);
n1 = Horner(line);
std::cout << "n2 = ";
std::cin.getline(line, 128);
n2 = Horner(line);
std::cout << "n3 = ";
std::cin.getline(line, 128);
n3 = Horner(line);
n0 = n1 * n2 * n3;
TestCooleyTukey(n0, n1, n2, n3);
}
else if (option == 2)
{
std::cout << "n0 = ";
std::cin.getline(line, 128);
int n0 = Horner(line);
if (n0 % 2 != 0)
{
std::cout << "n0 must be a power of 2";
std::cout << std::endl;
continue;
}
TestFFT(n0);
}
else if (option == 3)
{
std::cout << "n0 = ";
std::cin.getline(line, 128);
int n0 = Horner(line);
if (n0 % 2 != 0)
{
std::cout << "n0 must be a power of 2";
std::cout << std::endl;
continue;
}
TestIterativeFFT(n0);
}
else if (option == 4)
{
std::cout << "n0 = ";
std::cin.getline(line, 128);
int n0 = Horner(line);
if (n0 % 2 != 0)
{
std::cout << "n0 must be a power of 2";
std::cout << std::endl;
continue;
}
TestRecursiveFFT(n0);
}
else if (option == 5)
{
std::cout << "n0 = ";
std::cin.getline(line, 128);
int n0 = Horner(line);
if (n0 % 2 != 0)
{
std::cout << "n0 must be a power of 2";
std::cout << std::endl;
continue;
}
TestDFT(n0);
}
else if (option == 6)
{
std::cout << "n0 = ";
std::cin.getline(line, 128);
int n0 = Horner(line);
if (n0 % 2 != 0)
{
std::cout << "n0 must be a power of 2";
std::cout << std::endl;
continue;
}
TestVandermondeDFT(n0);
}
}
return 0;
}