2021-10-07 22:46:31 +08:00
/**
2021-10-18 03:31:41 +08:00
* @ file
2021-10-19 02:25:35 +08:00
* @ brief [ A fast Fourier transform ( FFT ) ] ( https : //medium.com/@aiswaryamathur/understanding-fast-fouriertransform-from-scratch-to-solve-polynomial-multiplication-8018d511162f) is an algorithm that computes the
2021-10-18 01:42:52 +08:00
* discrete Fourier transform ( DFT ) of a sequence , or its inverse ( IDFT ) , this algorithm
* has application in use case scenario where a user wants to find points of a function
* in short period time by just using the coefficents of the polynomial function .
2021-10-07 22:46:31 +08:00
* @ details
* https : //medium.com/@aiswaryamathur/understanding-fast-fourier-transform-from-scratch-to
- solve - polynomial - multiplication - 8018 d511162f
* @ author [ Ameya Chawla ] ( https : //github.com/ameyachawlaggsipu)
*/
2021-10-19 01:13:57 +08:00
# include <iostream> /// for IO operations
2021-10-18 03:31:56 +08:00
# include<cmath> /// for mathematical-related functions
2021-10-19 01:13:57 +08:00
# include <complex> /// for storing points and coefficents
2021-10-18 03:31:56 +08:00
# include <cassert> /// for assert
2021-10-19 01:13:57 +08:00
# include <vector> /// for storing test cases
2021-10-18 11:10:00 +08:00
2021-10-07 22:46:31 +08:00
/**
* @ brief FastFourierTransform is a recursive function which returns list of complex numbers
* @ param p List of Coefficents in form of complex numbers
* @ param n Count of elements in list p
* @ returns p if n = = 1
* @ returns y if n ! = 1
*/
2021-10-19 01:14:18 +08:00
std : : complex < double > * FastFourierTransform ( std : : complex < double > * p , uint64_t n )
2021-10-07 22:46:31 +08:00
{
2021-10-18 11:10:00 +08:00
double pi = 2 * asin ( 1.0 ) ; ///Declaring value of pi
2021-10-07 22:46:31 +08:00
if ( n = = 1 ) return p ; ///Base Case To return
2021-10-18 01:51:23 +08:00
std : : complex < double > om = std : : complex < double > ( cos ( 2 * pi / n ) , sin ( 2 * pi / n ) ) ; ///Calculating value of omega
2021-10-07 22:46:31 +08:00
2021-10-18 01:51:23 +08:00
std : : complex < double > * pe = new std : : complex < double > [ n / 2 ] ; /// Coefficents of even power
2021-10-07 22:46:31 +08:00
2021-10-18 01:51:23 +08:00
std : : complex < double > * po = new std : : complex < double > [ n / 2 ] ; ///Coefficents of odd power
2021-10-07 22:46:31 +08:00
2021-10-18 03:47:11 +08:00
uint64_t k1 = 0 , k2 = 0 ;
for ( uint64_t j = 0 ; j < n ; j + + )
2021-10-07 22:46:31 +08:00
{
if ( j % 2 = = 0 ) {
pe [ k1 + + ] = p [ j ] ; ///Assigning values of even coefficents
}
else po [ k2 + + ] = p [ j ] ; ///Assigning value of odd coefficents
}
2021-10-18 01:51:23 +08:00
std : : complex < double > * ye = FastFourierTransform ( pe , n / 2 ) ; ///Recursive Call
2021-10-07 22:46:31 +08:00
2021-10-18 01:51:23 +08:00
std : : complex < double > * yo = FastFourierTransform ( po , n / 2 ) ; ///Recursive Call
2021-10-07 22:46:31 +08:00
2021-10-18 01:51:23 +08:00
std : : complex < double > * y = new std : : complex < double > [ n ] ; ///Final value representation list
2021-10-07 22:46:31 +08:00
2021-10-18 03:47:11 +08:00
for ( uint64_t i = 0 ; i < n / 2 ; i + + )
2021-10-07 22:46:31 +08:00
{
2021-10-07 22:48:08 +08:00
y [ i ] = ye [ i ] + pow ( om , i ) * yo [ i ] ; ///Updating the first n/2 elements
y [ i + n / 2 ] = ye [ i ] - pow ( om , i ) * yo [ i ] ; ///Updating the last n/2 elements
2021-10-07 22:46:31 +08:00
}
2021-10-18 12:30:36 +08:00
delete [ ] ye ;
delete [ ] yo ;
2021-10-18 12:35:57 +08:00
delete [ ] pe ;
delete [ ] po ;
2021-10-18 04:32:52 +08:00
return y ; ///Returns the list
2021-10-07 22:46:31 +08:00
}
/**
* @ brief Self - test implementations
2021-10-18 03:32:28 +08:00
* declaring two test cases and checking for the error
* in predicted and true value is less than 0.000000000001 .
2021-10-07 22:46:31 +08:00
* @ returns void
*/
static void test ( ) {
/* descriptions of the following test */
2021-10-18 11:39:04 +08:00
std : : complex < double > * t1 = new std : : complex < double > [ 2 ] ; ///Test case 1
t1 [ 0 ] = { 1 , 0 } ;
t1 [ 1 ] = { 2 , 0 } ;
2021-10-07 22:46:31 +08:00
2021-10-18 11:39:04 +08:00
std : : complex < double > * t2 = new std : : complex < double > [ 4 ] ; ///Test case 2
t2 [ 0 ] = { 1 , 0 } ;
t2 [ 1 ] = { 2 , 0 } ;
t2 [ 2 ] = { 3 , 0 } ;
t2 [ 3 ] = { 4 , 0 } ;
2021-10-07 22:46:31 +08:00
2021-10-18 03:47:11 +08:00
uint8_t n1 = sizeof ( t1 ) / sizeof ( std : : complex < double > ) ;
uint8_t n2 = sizeof ( t2 ) / sizeof ( std : : complex < double > ) ;
2021-10-07 22:46:31 +08:00
2021-10-18 11:10:00 +08:00
std : : vector < std : : complex < double > > r1 = { { 3 , 0 } , { - 1 , 0 } } ; ///True Answer for test case 1
2021-10-07 22:46:31 +08:00
2021-10-18 11:10:00 +08:00
std : : vector < std : : complex < double > > r2 = { { 10 , 0 } , { - 2 , - 2 } , { - 2 , 0 } , { - 2 , 2 } } ; ///True Answer for test case 2
2021-10-07 22:46:31 +08:00
2021-10-18 01:51:23 +08:00
std : : complex < double > * o1 = FastFourierTransform ( t1 , n1 ) ;
std : : complex < double > * o2 = FastFourierTransform ( t2 , n2 ) ;
2021-10-07 22:46:31 +08:00
2021-10-18 03:47:11 +08:00
for ( uint8_t i = 0 ; i < n1 ; i + + )
2021-10-07 22:46:31 +08:00
{
2021-10-18 04:25:36 +08:00
assert ( ( r1 [ i ] . real ( ) - o1 - > real ( ) < 0.000000000001 ) & & ( r1 [ i ] . imag ( ) - o1 - > imag ( ) < 0.000000000001 ) ) ; /// Comparing for both real and imaginary values for test case 1
2021-10-07 22:46:31 +08:00
o1 + + ;
}
2021-10-18 03:47:11 +08:00
for ( uint8_t i = 0 ; i < n2 ; i + + )
2021-10-07 22:46:31 +08:00
{
2021-10-18 04:25:36 +08:00
assert ( ( r2 [ i ] . real ( ) - o2 - > real ( ) < 0.000000000001 ) & & ( r2 [ i ] . imag ( ) - o2 - > imag ( ) < 0.000000000001 ) ) ; /// Comparing for both real and imaginary values for test case 2
2021-10-07 22:46:31 +08:00
o2 + + ;
}
2021-10-18 12:30:36 +08:00
delete [ ] o1 ;
delete [ ] o2 ;
2021-10-18 12:35:57 +08:00
delete [ ] t1 ;
delete [ ] t2 ;
2021-10-07 22:46:31 +08:00
}
/**
* @ brief Main function
* @ param argc commandline argument count ( ignored )
* @ param argv commandline array of arguments ( ignored )
2021-10-18 01:42:52 +08:00
* calls automated test function to test the working of fast fourier transform .
2021-10-07 22:46:31 +08:00
* @ returns 0 on exit
*/
int main ( int argc , char const * argv [ ] )
{
2021-10-18 03:32:17 +08:00
test ( ) ; // run self-test implementations
2021-10-18 01:42:52 +08:00
return 0 ;
2021-10-07 22:48:08 +08:00
}