6#include <xtl/xcomplex.hpp>
8#include <xtensor/xarray.hpp>
9#include <xtensor/xaxis_slice_iterator.hpp>
10#include <xtensor/xbuilder.hpp>
11#include <xtensor/xcomplex.hpp>
12#include <xtensor/xmath.hpp>
13#include <xtensor/xnoalias.hpp>
14#include <xtensor/xview.hpp>
24 typename std::enable_if<xtl::is_complex<typename std::decay<E>::type::value_type>::value,
bool>::type =
true>
25 inline auto radix2(E&& e)
27 using namespace xt::placeholders;
28 using namespace std::complex_literals;
29 using value_type =
typename std::decay_t<E>::value_type;
30 using precision =
typename value_type::value_type;
32 const bool powerOfTwo = !(N == 0) && !(N & (N - 1));
34 if (!powerOfTwo || N == 0)
37 XTENSOR_THROW(std::runtime_error,
"FFT Implementation requires power of 2");
39 auto pi = xt::numeric_constants<precision>::PI;
50 oneapi::tbb::parallel_invoke(
68 auto first_half = even + t;
69 auto second_half = even - t;
71 auto spectrum = xt::xtensor<value_type, 1>::from_shape({N});
79 auto transform_bluestein(E&& data)
81 using value_type =
typename std::decay_t<E>::value_type;
82 using precision =
typename value_type::value_type;
85 const std::size_t n = data.
size();
86 size_t m = std::ceil(std::log2(n * 2 + 1));
94 auto angles =
xt::eval(precision{3.141592653589793238463} * i / n);
95 auto j = std::complex<precision>(0, 1);
96 exp_table =
xt::exp(-angles * j);
111 auto xv = radix2(av);
112 auto yv = radix2(bv);
113 auto spectrum_k = xv * yv;
114 auto complex_args =
xt::conj(spectrum_k);
115 auto fft_res = radix2(complex_args);
130 typename std::enable_if<xtl::is_complex<typename std::decay<E>::type::value_type>::value,
bool>::type =
true>
131 inline auto fft(E&& e, std::ptrdiff_t axis = -1)
133 using value_type =
typename std::decay_t<E>::value_type;
134 using precision =
typename value_type::value_type;
135 const auto saxis = xt::normalize_axis(e.dimension(), axis);
136 const size_t N = e.shape(saxis);
137 const bool powerOfTwo = !(N == 0) && !(N & (N - 1));
141 for (
auto iter = begin; iter != end; iter++)
145 xt::noalias(*iter) = detail::radix2(*iter);
149 xt::noalias(*iter) = detail::transform_bluestein(*iter);
163 typename std::enable_if<!xtl::is_complex<typename std::decay<E>::type::value_type>::value,
bool>::type =
true>
164 inline auto fft(E&& e, std::ptrdiff_t axis = -1)
166 using value_type =
typename std::decay<E>::type::value_type;
167 return fft(
xt::cast<std::complex<value_type>>(e), axis);
172 typename std::enable_if<xtl::is_complex<typename std::decay<E>::type::value_type>::value,
bool>::type =
true>
173 auto ifft(E&& e, std::ptrdiff_t axis = -1)
176 const std::size_t n = e.shape(axis);
179 XTENSOR_THROW(std::runtime_error,
"Cannot take the iFFT along an empty dimention");
182 auto fft_res = xt::fft::fft(complex_args, axis);
189 typename std::enable_if<!xtl::is_complex<typename std::decay<E>::type::value_type>::value,
bool>::type =
true>
190 inline auto ifft(E&& e, std::ptrdiff_t axis = -1)
192 using value_type =
typename std::decay<E>::type::value_type;
193 return ifft(
xt::cast<std::complex<value_type>>(e), axis);
203 template <
typename E1,
typename E2>
204 auto convolve(E1&& xvec, E2&& yvec, std::ptrdiff_t axis = -1)
207 if (xvec.dimension() != yvec.dimension())
209 XTENSOR_THROW(std::runtime_error,
"Mismatched dimentions");
212 auto saxis = xt::normalize_axis(xvec.dimension(), axis);
213 if (xvec.shape(saxis) != yvec.shape(saxis))
215 XTENSOR_THROW(std::runtime_error,
"Mismatched lengths along slice axis");
218 const std::size_t n = xvec.shape(saxis);
220 auto xv = fft(xvec, axis);
221 auto yv = fft(yvec, axis);
227 for (
auto iter = begin_x; iter != end_x; iter++)
229 (*iter) = (*iter_y++) * (*iter);
232 auto outvec = ifft(xv, axis);
size_type size() const noexcept
Returns the number of element in the container.
auto cast(E &&e) noexcept -> detail::xfunction_type_t< typename detail::cast< R >::functor, E >
Element-wise static_cast.
auto exp(E &&e) noexcept -> detail::xfunction_type_t< math::exp_fun, E >
Natural exponential function.
auto pow(E1 &&e1, E2 &&e2) noexcept -> detail::xfunction_type_t< math::pow_fun, E1, E2 >
Power function.
auto conj(E &&e) noexcept
Return an xt::xfunction evaluating to the complex conjugate of the given expression.
auto eval(T &&t) -> std::enable_if_t< detail::is_container< std::decay_t< T > >::value, T && >
Force evaluation of xexpression.
auto flip(E &&e)
Reverse the order of elements in an xexpression along every axis.
standard mathematical functions for xexpressions
auto range(A start_val, B stop_val)
Select a range from start_val to stop_val (excluded).
auto arange(T start, T stop, S step=1) noexcept
Generates numbers evenly spaced within given half-open interval [start, stop).
xarray_container< uvector< T, A >, L, xt::svector< typename uvector< T, A >::size_type, 4, SA, true > > xarray
Alias template on xarray_container with default parameters for data container type and shape / stride...
xtensor_container< uvector< T, A >, N, L > xtensor
Alias template on xtensor_container with default parameters for data container type.
auto axis_slice_begin(E &&e)
Returns an iterator to the first element of the expression for axis 0.
auto view(E &&e, S &&... slices)
Constructs and returns a view on the specified xexpression.
auto axis_slice_end(E &&e)
Returns an iterator to the element following the last element of the expression for axis 0.
xarray< T, L > empty(const S &shape)
Create a xcontainer (xarray, xtensor or xtensor_fixed) with uninitialized values of with value_type T...