2929
3030#include < complex>
3131
32+ #include " NumCpp/Core/Constants.hpp"
3233#include " NumCpp/Core/Internal/StaticAsserts.hpp"
34+ #include " NumCpp/Core/Internal/StlAlgorithms.hpp"
3335#include " NumCpp/Core/Types.hpp"
36+ #include " NumCpp/Functions/complex.hpp"
3437#include " NumCpp/NdArray.hpp"
3538
3639namespace nc
3740{
41+ namespace detail
42+ {
43+ // ===========================================================================
44+ // Method Description:
45+ // / Fast Fourier Transform
46+ // /
47+ // / @param x the data
48+ // / @param n Length of the transformed axis of the output.
49+ // /
50+ NdArray<std::complex <double >> fft (const NdArray<std::complex <double >>& x, uint32 n)
51+ {
52+ if (n == 0 )
53+ {
54+ return {};
55+ }
56+
57+ auto result = NdArray<std::complex <double >>(1 , n);
58+
59+ stl_algorithms::for_each (result.begin (),
60+ result.end (),
61+ [n, &x, &result](auto & resultElement)
62+ {
63+ const auto k = static_cast <double >(&resultElement - result.data ());
64+ const auto minusTwoPiKOverN = -constants::twoPi * k / static_cast <double >(n);
65+ resultElement = std::complex <double >{ 0 ., 0 . };
66+ std::for_each (x.begin (),
67+ x.begin () + std::min (n, x.size ()),
68+ [minusTwoPiKOverN, &resultElement, &x, n](const auto & value)
69+ {
70+ const auto m = static_cast <double >(&value - x.data ());
71+ const auto angle = minusTwoPiKOverN * m;
72+ resultElement += (value * std::polar (1 ., angle));
73+ });
74+ });
75+
76+ return result;
77+ }
78+ } // namespace detail
79+
3880 // ===========================================================================
3981 // Method Description:
4082 // / Compute the one-dimensional discrete Fourier Transform.
@@ -56,15 +98,29 @@ namespace nc
5698 {
5799 case Axis::NONE:
58100 {
59- return {};
101+ const auto data = nc::complex <dtype, double >(inArray);
102+ return detail::fft (data, inN);
60103 }
61104 case Axis::COL:
62105 {
63- return {};
106+ auto data = nc::complex <dtype, double >(inArray);
107+ const auto & shape = inArray.shape ();
108+ auto result = NdArray<std::complex <double >>(shape.rows , inN);
109+ const auto dataColSlice = data.cSlice ();
110+ const auto resultColSlice = result.cSlice ();
111+
112+ for (uint32 row = 0 ; row < data.numRows (); ++row)
113+ {
114+ const auto rowData = data (row, dataColSlice);
115+ const auto rowResult = detail::fft (rowData, inN);
116+ result.put (row, resultColSlice, rowResult);
117+ }
118+
119+ return result;
64120 }
65121 case Axis::ROW:
66122 {
67- return fft (inArray.transpose (), inN, Axis::COL);
123+ return fft (inArray.transpose (), inN, Axis::COL). transpose () ;
68124 }
69125 default :
70126 {
@@ -133,15 +189,29 @@ namespace nc
133189 {
134190 case Axis::NONE:
135191 {
136- return {};
192+ const auto data = nc::complex <dtype, double >(inArray);
193+ return detail::fft (data, inN);
137194 }
138195 case Axis::COL:
139196 {
140- return {};
197+ const auto data = nc::complex <dtype, double >(inArray);
198+ const auto & shape = inArray.shape ();
199+ auto result = NdArray<std::complex <double >>(shape.rows , inN);
200+ const auto dataColSlice = data.cSlice ();
201+ const auto resultColSlice = result.cSlice ();
202+
203+ for (uint32 row = 0 ; row < data.numRows (); ++row)
204+ {
205+ const auto rowData = data (row, dataColSlice);
206+ const auto rowResult = detail::fft (rowData, inN);
207+ result.put (row, resultColSlice, rowResult);
208+ }
209+
210+ return result;
141211 }
142212 case Axis::ROW:
143213 {
144- return fft (inArray.transpose (), inN, Axis::COL);
214+ return fft (inArray.transpose (), inN, Axis::COL). transpose () ;
145215 }
146216 default :
147217 {
0 commit comments