Automatic Differentiation
 
Loading...
Searching...
No Matches
fft.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_FWD_FUN_FFT_HPP
2#define STAN_MATH_FWD_FUN_FFT_HPP
3
11#include <complex>
12
13namespace stan {
14namespace math {
15
24template <typename V, require_eigen_vector_vt<is_complex, V>* = nullptr,
25 require_fvar_t<base_type_t<value_type_t<V>>>* = nullptr>
26inline Eigen::Matrix<scalar_type_t<V>, -1, 1> fft(V&& x) {
27 using scalar_t = scalar_type_t<V>;
28 using fvar_t = base_type_t<scalar_t>;
29 using complex_t = std::complex<partials_type_t<fvar_t>>;
30 decltype(auto) x_ref = to_ref(std::forward<V>(x));
31 if (x_ref.size() <= 1) {
32 return Eigen::Matrix<scalar_type_t<V>, -1, 1>(x_ref);
33 }
34
35 Eigen::Matrix<complex_t, -1, 1> x_val = value_of(x_ref);
36 Eigen::Matrix<complex_t, -1, 1> x_d = x_ref.unaryExpr(
37 [](const auto& z) { return complex_t(z.real().d(), z.imag().d()); });
38
39 auto y_val = fft(std::move(x_val));
40 auto y_d = fft(std::move(x_d));
41
42 using out_t = Eigen::Matrix<scalar_type_t<V>, -1, 1>;
43 out_t y
44 = y_val.binaryExpr(y_d, [](const complex_t& val, const complex_t& der) {
45 return std::complex<fvar_t>{fvar_t(val.real(), der.real()),
46 fvar_t(val.imag(), der.imag())};
47 });
48 return y;
49}
50
59template <typename V, require_eigen_vector_vt<is_complex, V>* = nullptr,
60 require_fvar_t<base_type_t<value_type_t<V>>>* = nullptr>
61inline Eigen::Matrix<scalar_type_t<V>, -1, 1> inv_fft(V&& y) {
62 using scalar_t = scalar_type_t<V>;
63 using fvar_t = base_type_t<scalar_t>;
64 using complex_t = std::complex<partials_type_t<fvar_t>>;
65 decltype(auto) y_ref = to_ref(std::forward<V>(y));
66 if (y_ref.size() <= 1) {
67 return Eigen::Matrix<scalar_type_t<V>, -1, 1>(y_ref);
68 }
69
70 Eigen::Matrix<complex_t, -1, 1> y_val = value_of(y_ref);
71 Eigen::Matrix<complex_t, -1, 1> y_d = y_ref.unaryExpr(
72 [](const auto& z) { return complex_t(z.real().d(), z.imag().d()); });
73
74 auto x_val = inv_fft(std::move(y_val));
75 auto x_d = inv_fft(std::move(y_d));
76
77 using out_t = Eigen::Matrix<scalar_type_t<V>, -1, 1>;
78 out_t x
79 = x_val.binaryExpr(x_d, [](const complex_t& val, const complex_t& der) {
80 return std::complex<fvar_t>{fvar_t(val.real(), der.real()),
81 fvar_t(val.imag(), der.imag())};
82 });
83 return x;
84}
85
94template <typename M, require_eigen_dense_dynamic_vt<is_complex, M>* = nullptr,
95 require_fvar_t<base_type_t<value_type_t<M>>>* = nullptr>
96inline Eigen::Matrix<scalar_type_t<M>, -1, -1> fft2(M&& x) {
97 using scalar_t = scalar_type_t<M>;
98 using fvar_t = base_type_t<scalar_t>;
99 using complex_t = std::complex<partials_type_t<fvar_t>>;
100 decltype(auto) x_ref = to_ref(std::forward<M>(x));
101 Eigen::Matrix<complex_t, -1, -1> x_val = value_of(x_ref);
102 Eigen::Matrix<complex_t, -1, -1> x_d = x_ref.unaryExpr(
103 [](const auto& z) { return complex_t(z.real().d(), z.imag().d()); });
104
105 auto y_val = fft2(std::move(x_val));
106 auto y_d = fft2(std::move(x_d));
107
108 using out_t = Eigen::Matrix<scalar_type_t<M>, -1, -1>;
109 out_t y
110 = y_val.binaryExpr(y_d, [](const complex_t& val, const complex_t& der) {
111 return std::complex<fvar_t>{fvar_t(val.real(), der.real()),
112 fvar_t(val.imag(), der.imag())};
113 });
114 return y;
115}
116
125template <typename M, require_eigen_dense_dynamic_vt<is_complex, M>* = nullptr,
126 require_fvar_t<base_type_t<value_type_t<M>>>* = nullptr>
127inline Eigen::Matrix<scalar_type_t<M>, -1, -1> inv_fft2(M&& y) {
128 using scalar_t = scalar_type_t<M>;
129 using fvar_t = base_type_t<scalar_t>;
130 using complex_t = std::complex<partials_type_t<fvar_t>>;
131 decltype(auto) y_ref = to_ref(std::forward<M>(y));
132 Eigen::Matrix<complex_t, -1, -1> y_val = value_of(y_ref);
133 Eigen::Matrix<complex_t, -1, -1> y_d = y_ref.unaryExpr(
134 [](const auto& z) { return complex_t(z.real().d(), z.imag().d()); });
135
136 auto x_val = inv_fft2(std::move(y_val));
137 auto x_d = inv_fft2(std::move(y_d));
138
139 using out_t = Eigen::Matrix<scalar_type_t<M>, -1, -1>;
140 out_t x
141 = x_val.binaryExpr(x_d, [](const complex_t& val, const complex_t& der) {
142 return std::complex<fvar_t>{fvar_t(val.real(), der.real()),
143 fvar_t(val.imag(), der.imag())};
144 });
145 return x;
146}
147
148} // namespace math
149} // namespace stan
150
151#endif
Eigen::Matrix< scalar_type_t< V >, -1, 1 > inv_fft(V &&y)
Return the inverse discrete Fourier transform of the specified complex vector for forward-mode autodi...
Definition fft.hpp:61
Eigen::Matrix< scalar_type_t< M >, -1, -1 > inv_fft2(M &&y)
Return the two-dimensional inverse discrete Fourier transform of the specified complex matrix for for...
Definition fft.hpp:127
T value_of(const fvar< T > &v)
Return the value of the specified variable.
Definition value_of.hpp:18
Eigen::Matrix< scalar_type_t< M >, -1, -1 > fft2(M &&x)
Return the two-dimensional discrete Fourier transform of the specified complex matrix for forward-mod...
Definition fft.hpp:96
Eigen::Matrix< scalar_type_t< V >, -1, 1 > fft(V &&x)
Return the discrete Fourier transform of the specified complex vector for forward-mode autodiff.
Definition fft.hpp:26
ref_type_t< T && > to_ref(T &&a)
This evaluates expensive Eigen expressions.
Definition to_ref.hpp:18
typename scalar_type< T >::type scalar_type_t
typename base_type< T >::type base_type_t
Definition base_type.hpp:29
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...