DFT¶
dct_plan
dct_plan
class¶
template <typename T> dct_plan
DCT type 2 (unscaled)
Source code
template <typename T>
struct dct_plan : dft_plan<T>
{
dct_plan(size_t size) : dft_plan<T>(size) { this->temp_size += sizeof(complex<T>) * size * 2; }
[[deprecated("cpu parameter is deprecated. Runtime dispatch is used if built with "
"KFR_ENABLE_MULTIARCH")]] dct_plan(cpu_t cpu, size_t size)
: dct_plan(size)
{
}
KFR_MEM_INTRINSIC void execute(T* out, const T* in, u8* temp, bool inverse = false) const
{
const size_t size = this->size;
const size_t halfSize = size / 2;
univector_ref<complex<T>> mirrored = make_univector(
ptr_cast<complex<T>>(temp + this->temp_size - sizeof(complex<T>) * size * 2), size);
univector_ref<complex<T>> mirrored_dft =
make_univector(ptr_cast<complex<T>>(temp + this->temp_size - sizeof(complex<T>) * size), size);
auto t = counter() * c_pi<T> / (size * 2);
if (!inverse)
{
for (size_t i = 0; i < halfSize; i++)
{
mirrored[i] = in[i * 2];
mirrored[size - 1 - i] = in[i * 2 + 1];
}
if (size % 2)
{
mirrored[halfSize] = in[size - 1];
}
dft_plan<T>::execute(mirrored_dft.data(), mirrored.data(), temp, cfalse);
make_univector(out, size) = real(mirrored_dft) * cos(t) + imag(mirrored_dft) * sin(t);
}
else
{
mirrored = make_complex(make_univector(in, size) * cos(t), make_univector(in, size) * -sin(t));
mirrored[0] = mirrored[0] * T(0.5);
dft_plan<T>::execute(mirrored_dft.data(), mirrored.data(), temp, cfalse);
for (size_t i = 0; i < halfSize; i++)
{
out[i * 2 + 0] = mirrored_dft[i].real();
out[i * 2 + 1] = mirrored_dft[size - 1 - i].real();
}
if (size % 2)
{
out[size - 1] = mirrored_dft[halfSize].real();
}
}
}
template <univector_tag Tag1, univector_tag Tag2, univector_tag Tag3>
KFR_MEM_INTRINSIC void execute(univector<T, Tag1>& out, const univector<T, Tag2>& in,
univector<u8, Tag3>& temp, bool inverse = false) const
{
execute(out.data(), in.data(), temp.data(), inverse);
}
}
https://github.com/kfrlib/kfr/blob//include/kfr/dft/fft.hpp#L717
dft
function¶
template <typename T, univector_tag Tag>
univector<complex<T>>
dft(const univector<complex<T>, Tag> &input)
Performs Direct DFT using cached plan
Source code
template <typename T, univector_tag Tag>
univector<complex<T>> dft(const univector<complex<T>, Tag>& input)
{
dft_plan_ptr<T> dft = dft_cache::instance().get(ctype_t<T>(), input.size());
univector<complex<T>> output(input.size(), std::numeric_limits<T>::quiet_NaN());
univector<u8> temp(dft->temp_size);
dft->execute(output, input, temp);
return output;
}
https://github.com/kfrlib/kfr/blob//include/kfr/dft/cache.hpp#L130
dft_plan
dft_plan
class¶
template <typename T> dft_plan
1D DFT/FFT
Source code
template <typename T>
struct dft_plan
https://github.com/kfrlib/kfr/blob//include/kfr/dft/fft.hpp#L122
dft_plan
template <typename T> dft_plan
1D DFT/FFT
Source code
template <typename T>
struct dft_plan
{
size_t size;
size_t temp_size;
dft_plan()
: size(0), temp_size(0), data_size(0), arblen(false), disposition_inplace{}, disposition_outofplace{}
{
}
dft_plan(const dft_plan&) = delete;
dft_plan(dft_plan&&) = default;
dft_plan& operator=(const dft_plan&) = delete;
dft_plan& operator=(dft_plan&&) = default;
bool is_initialized() const { return size != 0; }
[[deprecated("cpu parameter is deprecated. Runtime dispatch is used if built with "
"KFR_ENABLE_MULTIARCH")]] explicit dft_plan(cpu_t cpu, size_t size,
dft_order order = dft_order::normal)
: dft_plan(size, order)
{
(void)cpu;
}
explicit dft_plan(size_t size, dft_order order = dft_order::normal)
: size(size), temp_size(0), data_size(0), arblen(false)
{
internal_generic::dft_initialize(*this);
}
void dump() const;
KFR_MEM_INTRINSIC void execute(complex<T>* out, const complex<T>* in, u8* temp,
bool inverse = false) const
{
if (inverse)
execute_dft(ctrue, out, in, temp);
else
execute_dft(cfalse, out, in, temp);
}
~dft_plan() {}
template <bool inverse>
KFR_MEM_INTRINSIC void execute(complex<T>* out, const complex<T>* in, u8* temp,
cbool_t<inverse> inv) const
{
execute_dft(inv, out, in, temp);
}
template <univector_tag Tag1, univector_tag Tag2, univector_tag Tag3>
KFR_MEM_INTRINSIC void execute(univector<complex<T>, Tag1>& out, const univector<complex<T>, Tag2>& in,
univector<u8, Tag3>& temp, bool inverse = false) const
{
if (inverse)
execute_dft(ctrue, out.data(), in.data(), temp.data());
else
execute_dft(cfalse, out.data(), in.data(), temp.data());
}
template <bool inverse, univector_tag Tag1, univector_tag Tag2, univector_tag Tag3>
KFR_MEM_INTRINSIC void execute(univector<complex<T>, Tag1>& out, const univector<complex<T>, Tag2>& in,
univector<u8, Tag3>& temp, cbool_t<inverse> inv) const
{
execute_dft(inv, out.data(), in.data(), temp.data());
}
template <univector_tag Tag1, univector_tag Tag2>
KFR_MEM_INTRINSIC void execute(univector<complex<T>, Tag1>& out, const univector<complex<T>, Tag2>& in,
u8* temp, bool inverse = false) const
{
if (inverse)
execute_dft(ctrue, out.data(), in.data(), temp);
else
execute_dft(cfalse, out.data(), in.data(), temp);
}
template <bool inverse, univector_tag Tag1, univector_tag Tag2>
KFR_MEM_INTRINSIC void execute(univector<complex<T>, Tag1>& out, const univector<complex<T>, Tag2>& in,
u8* temp, cbool_t<inverse> inv) const
{
execute_dft(inv, out.data(), in.data(), temp);
}
autofree<u8> data;
size_t data_size;
std::vector<dft_stage_ptr<T>> all_stages;
std::array<std::vector<dft_stage<T>*>, 2> stages;
bool arblen;
using bitset = std::bitset<DFT_MAX_STAGES>;
std::array<bitset, 2> disposition_inplace;
std::array<bitset, 2> disposition_outofplace;
void calc_disposition();
static bitset precompute_disposition(int num_stages, bitset can_inplace_per_stage,
bool inplace_requested);
protected:
struct noinit
{
};
explicit dft_plan(noinit, size_t size, dft_order order = dft_order::normal)
: size(size), temp_size(0), data_size(0), arblen(false)
{
}
template <bool inverse>
KFR_INTRINSIC void execute_dft(cbool_t<inverse>, complex<T>* out, const complex<T>* in, u8* temp) const
{
internal_generic::dft_execute(*this, cbool<inverse>, out, in, temp);
}
}
https://github.com/kfrlib/kfr/blob//include/kfr/dft/fft.hpp#L151
dft_plan_md
dft_plan_md
class¶
template <typename T, index_t Dims> dft_plan_md
Multidimensional DFT
Source code
template <typename T, index_t Dims>
struct dft_plan_md
{
shape<Dims> size;
size_t temp_size;
dft_plan_md(const dft_plan_md&) = delete;
dft_plan_md(dft_plan_md&&) = default;
dft_plan_md& operator=(const dft_plan_md&) = delete;
dft_plan_md& operator=(dft_plan_md&&) = default;
bool is_initialized() const { return size.product() != 0; }
void dump() const
{
for (const auto& d : dfts)
{
d.dump();
}
}
explicit dft_plan_md(shape<Dims> size) : size(std::move(size)), temp_size(0)
{
if constexpr (Dims == dynamic_shape)
{
dfts.resize(this->size.dims());
}
for (index_t i = 0; i < this->size.dims(); ++i)
{
dfts[i] = dft_plan<T>(this->size[i]);
temp_size = std::max(temp_size, dfts[i].temp_size);
}
internal_generic::dft_initialize_transpose(transpose);
}
void execute(complex<T>* out, const complex<T>* in, u8* temp, bool inverse = false) const
{
if (inverse)
execute_dft(ctrue, out, in, temp);
else
execute_dft(cfalse, out, in, temp);
}
template <index_t UDims = Dims, CMT_ENABLE_IF(UDims != dynamic_shape)>
void execute(const tensor<complex<T>, Dims>& out, const tensor<complex<T>, Dims>& in, u8* temp,
bool inverse = false) const
{
KFR_LOGIC_CHECK(in.shape() == this->size && out.shape() == this->size,
"dft_plan_md: incorrect tensor shapes");
KFR_LOGIC_CHECK(in.is_contiguous() && out.is_contiguous(), "dft_plan_md: tensors must be contiguous");
if (inverse)
execute_dft(ctrue, out.data(), in.data(), temp);
else
execute_dft(cfalse, out.data(), in.data(), temp);
}
template <bool inverse = false>
void execute(complex<T>* out, const complex<T>* in, u8* temp, cbool_t<inverse> = {}) const
{
execute_dft(cbool<inverse>, out, in, temp);
}
private:
template <bool inverse>
KFR_INTRINSIC void execute_dft(cbool_t<inverse>, complex<T>* out, const complex<T>* in, u8* temp) const
{
if (temp == nullptr && temp_size > 0)
{
return call_with_temp(temp_size, std::bind(&dft_plan_md<T, Dims>::execute_dft<inverse>, this,
cbool_t<inverse>{}, out, in, std::placeholders::_1));
}
if (size.dims() == 1)
{
dfts[0].execute(out, in, temp, cbool<inverse>);
}
else
{
execute_dim(cbool<inverse>, out, in, temp);
}
}
KFR_INTRINSIC void execute_dim(cfalse_t, complex<T>* out, const complex<T>* in, u8* temp) const
{
shape<Dims> sh = size;
index_t total = size.product();
index_t axis = size.dims() - 1;
for (;;)
{
if (size[axis] > 1)
{
for (index_t o = 0; o < total; o += sh.back())
dfts[axis].execute(out + o, in + o, temp, cfalse);
}
else
{
builtin_memcpy(out, in, sizeof(complex<T>) * total);
}
transpose(out, out, shape{ sh.remove_back().product(), sh.back() });
if (axis == 0)
break;
sh = sh.rotate_right();
in = out;
--axis;
}
}
KFR_INTRINSIC void execute_dim(ctrue_t, complex<T>* out, const complex<T>* in, u8* temp) const
{
shape<Dims> sh = size;
index_t total = size.product();
index_t axis = 0;
for (;;)
{
transpose(out, in, shape{ sh.front(), sh.remove_front().product() });
if (size[axis] > 1)
{
for (index_t o = 0; o < total; o += sh.front())
dfts[axis].execute(out + o, out + o, temp, ctrue);
}
if (axis == size.dims() - 1)
break;
sh = sh.rotate_left();
in = out;
++axis;
}
}
using dft_list =
std::conditional_t<Dims == dynamic_shape, std::vector<dft_plan<T>>, std::array<dft_plan<T>, Dims>>;
dft_list dfts;
internal_generic::fn_transpose<T> transpose;
}
https://github.com/kfrlib/kfr/blob//include/kfr/dft/fft.hpp#L358
dft_plan_md_real
dft_plan_md_real
class¶
template <typename T, index_t Dims> dft_plan_md_real
Multidimensional DFT
Source code
template <typename T, index_t Dims>
struct dft_plan_md_real
{
shape<Dims> size;
size_t temp_size;
bool real_out_is_enough;
dft_plan_md_real(const dft_plan_md_real&) = delete;
dft_plan_md_real(dft_plan_md_real&&) = default;
dft_plan_md_real& operator=(const dft_plan_md_real&) = delete;
dft_plan_md_real& operator=(dft_plan_md_real&&) = default;
bool is_initialized() const { return size.product() != 0; }
void dump() const
{
for (const auto& d : dfts)
{
d.dump();
}
dft_real.dump();
}
shape<Dims> complex_size() const { return complex_size_for(size); }
constexpr static shape<Dims> complex_size_for(shape<Dims> size)
{
if (size.dims() > 0)
size.back() = dft_plan_real<T>::complex_size_for(size.back(), dft_pack_format::CCs);
return size;
}
size_t real_out_size() const { return real_out_size_for(size); }
constexpr static size_t real_out_size_for(shape<Dims> size)
{
return complex_size_for(size).product() * 2;
}
explicit dft_plan_md_real(shape<Dims> size, bool real_out_is_enough = false)
: size(std::move(size)), temp_size(0), real_out_is_enough(real_out_is_enough)
{
if (this->size.dims() > 0)
{
if constexpr (Dims == dynamic_shape)
{
dfts.resize(this->size.dims());
}
for (index_t i = 0; i < this->size.dims() - 1; ++i)
{
dfts[i] = dft_plan<T>(this->size[i]);
temp_size = std::max(temp_size, dfts[i].temp_size);
}
dft_real = dft_plan_real<T>(this->size.back());
temp_size = std::max(temp_size, dft_real.temp_size);
}
if (!this->real_out_is_enough)
{
temp_size += complex_size().product() * sizeof(complex<T>);
}
internal_generic::dft_initialize_transpose(transpose);
}
void execute(complex<T>* out, const T* in, u8* temp, cdirect_t = {}) const
{
execute_dft(cfalse, out, in, temp);
}
void execute(T* out, const complex<T>* in, u8* temp, cinvert_t = {}) const
{
execute_dft(ctrue, out, in, temp);
}
template <index_t UDims = Dims, CMT_ENABLE_IF(UDims != dynamic_shape)>
void execute(const tensor<complex<T>, Dims>& out, const tensor<T, Dims>& in, u8* temp,
cdirect_t = {}) const
{
KFR_LOGIC_CHECK(in.shape() == this->size && out.shape() == complex_size(),
"dft_plan_md_real: incorrect tensor shapes");
KFR_LOGIC_CHECK(in.is_contiguous() && out.is_contiguous(),
"dft_plan_md_real: tensors must be contiguous");
execute_dft(cfalse, out.data(), in.data(), temp);
}
template <index_t UDims = Dims, CMT_ENABLE_IF(UDims != dynamic_shape)>
void execute(const tensor<T, Dims>& out, const tensor<complex<T>, Dims>& in, u8* temp,
cinvert_t = {}) const
{
KFR_LOGIC_CHECK(in.shape() == complex_size() && out.shape() == this->size,
"dft_plan_md_real: incorrect tensor shapes");
KFR_LOGIC_CHECK(in.is_contiguous() && out.is_contiguous(),
"dft_plan_md_real: tensors must be contiguous");
execute_dft(ctrue, out.data(), in.data(), temp);
}
void execute(complex<T>* out, const T* in, u8* temp, bool inverse) const
{
KFR_LOGIC_CHECK(inverse, "dft_plan_md_real: incorrect usage");
execute_dft(cfalse, out, in, temp);
}
void execute(T* out, const complex<T>* in, u8* temp, bool inverse) const
{
KFR_LOGIC_CHECK(!inverse, "dft_plan_md_real: incorrect usage");
execute_dft(ctrue, out, in, temp);
}
private:
template <bool inverse, typename Tout, typename Tin>
KFR_INTRINSIC void execute_dft(cbool_t<inverse>, Tout* out, const Tin* in, u8* temp) const
{
if (temp == nullptr && temp_size > 0)
{
return call_with_temp(temp_size,
std::bind(&dft_plan_md_real<T, Dims>::execute_dft<inverse, Tout, Tin>, this,
cbool_t<inverse>{}, out, in, std::placeholders::_1));
}
if (this->size.dims() == 1)
{
dft_real.execute(out, in, temp, cbool<inverse>);
}
else
{
execute_dim(cbool<inverse>, out, in, temp);
}
}
void expand(T* out, const T* in, size_t count, size_t last_axis) const
{
size_t last_axis_ex = dft_real.complex_size() * 2;
if (in != out)
{
builtin_memmove(out, in, last_axis * sizeof(T));
}
in += last_axis * (count - 1);
out += last_axis_ex * (count - 1);
for (size_t i = 1; i < count; ++i)
{
builtin_memmove(out, in, last_axis * sizeof(T));
in -= last_axis;
out -= last_axis_ex;
}
#ifdef KFR_DEBUG
for (size_t i = 0; i < count; ++i)
{
builtin_memset(out + last_axis, 0xFF, (last_axis_ex - last_axis) * sizeof(T));
out += last_axis_ex;
}
#endif
}
void contract(T* out, const T* in, size_t count, size_t last_axis) const
{
size_t last_axis_ex = dft_real.complex_size() * 2;
if (in != out)
builtin_memmove(out, in, last_axis * sizeof(T));
in += last_axis_ex;
out += last_axis;
for (size_t i = 1; i < count; ++i)
{
builtin_memmove(out, in, last_axis * sizeof(T));
in += last_axis_ex;
out += last_axis;
}
}
KFR_INTRINSIC void execute_dim(cfalse_t, complex<T>* out, const T* in_real, u8* temp) const
{
shape<Dims> sh = complex_size();
index_t total = sh.product();
index_t axis = size.dims() - 1;
expand(ptr_cast<T>(out), in_real, size.remove_back().product(), size.back());
for (;;)
{
if (size[axis] > 1)
{
if (axis == size.dims() - 1)
for (index_t o = 0; o < total; o += sh.back())
dft_real.execute(out + o, ptr_cast<T>(out + o), temp, cfalse);
else
for (index_t o = 0; o < total; o += sh.back())
dfts[axis].execute(out + o, out + o, temp, cfalse);
}
transpose(out, out, shape{ sh.remove_back().product(), sh.back() });
if (axis == 0)
break;
sh = sh.rotate_right();
--axis;
}
}
KFR_INTRINSIC void execute_dim(ctrue_t, T* out_real, const complex<T>* in, u8* temp) const
{
shape<Dims> sh = complex_size();
index_t total = sh.product();
complex<T>* out = real_out_is_enough
? ptr_cast<complex<T>>(out_real)
: ptr_cast<complex<T>>(temp + temp_size - total * sizeof(complex<T>));
index_t axis = 0;
for (;;)
{
transpose(out, in, shape{ sh.front(), sh.remove_front().product() });
if (size[axis] > 1)
{
if (axis == size.dims() - 1)
for (index_t o = 0; o < total; o += sh.front())
dft_real.execute(ptr_cast<T>(out + o), out + o, temp, ctrue);
else
for (index_t o = 0; o < total; o += sh.front())
dfts[axis].execute(out + o, out + o, temp, ctrue);
}
if (axis == size.dims() - 1)
break;
sh = sh.rotate_left();
in = out;
++axis;
}
contract(out_real, ptr_cast<T>(out), size.remove_back().product(), size.back());
}
using dft_list = std::conditional_t<Dims == dynamic_shape, std::vector<dft_plan<T>>,
std::array<dft_plan<T>, const_max(Dims, 1) - 1>>;
dft_list dfts;
dft_plan_real<T> dft_real;
internal_generic::fn_transpose<T> transpose;
}
https://github.com/kfrlib/kfr/blob//include/kfr/dft/fft.hpp#L494
dft_plan_real
dft_plan_real
class¶
template <typename T> dft_plan_real
Real-to-complex and Complex-to-real 1D DFT
Source code
template <typename T>
struct dft_plan_real
https://github.com/kfrlib/kfr/blob//include/kfr/dft/fft.hpp#L125
dft_plan_real
template <typename T> dft_plan_real
Real-to-complex and Complex-to-real 1D DFT
Source code
template <typename T>
struct dft_plan_real : dft_plan<T>
{
size_t size;
dft_pack_format fmt;
dft_plan_real() : size(0), fmt(dft_pack_format::CCs) {}
dft_plan_real(const dft_plan_real&) = delete;
dft_plan_real(dft_plan_real&&) = default;
dft_plan_real& operator=(const dft_plan_real&) = delete;
dft_plan_real& operator=(dft_plan_real&&) = default;
bool is_initialized() const { return size != 0; }
size_t complex_size() const { return complex_size_for(size, fmt); }
constexpr static size_t complex_size_for(size_t size, dft_pack_format fmt)
{
return fmt == dft_pack_format::CCs ? size / 2 + 1 : size / 2;
}
[[deprecated("cpu parameter is deprecated. Runtime dispatch is used if built with "
"KFR_ENABLE_MULTIARCH")]] explicit dft_plan_real(cpu_t cpu, size_t size,
dft_pack_format fmt = dft_pack_format::CCs)
: dft_plan_real(size, fmt)
{
(void)cpu;
}
explicit dft_plan_real(size_t size, dft_pack_format fmt = dft_pack_format::CCs)
: dft_plan<T>(typename dft_plan<T>::noinit{}, size / 2), size(size), fmt(fmt)
{
KFR_LOGIC_CHECK(is_even(size), "dft_plan_real requires size to be even");
internal_generic::dft_real_initialize(*this);
}
void execute(complex<T>*, const complex<T>*, u8*, bool = false) const = delete;
template <bool inverse>
void execute(complex<T>*, const complex<T>*, u8*, cbool_t<inverse>) const = delete;
template <univector_tag Tag1, univector_tag Tag2, univector_tag Tag3>
void execute(univector<complex<T>, Tag1>&, const univector<complex<T>, Tag2>&, univector<u8, Tag3>&,
bool = false) const = delete;
template <bool inverse, univector_tag Tag1, univector_tag Tag2, univector_tag Tag3>
void execute(univector<complex<T>, Tag1>&, const univector<complex<T>, Tag2>&, univector<u8, Tag3>&,
cbool_t<inverse>) const = delete;
template <univector_tag Tag1, univector_tag Tag2>
void execute(univector<complex<T>, Tag1>& out, const univector<complex<T>, Tag2>& in, u8* temp,
bool inverse = false) const = delete;
template <bool inverse, univector_tag Tag1, univector_tag Tag2>
void execute(univector<complex<T>, Tag1>& out, const univector<complex<T>, Tag2>& in, u8* temp,
cbool_t<inverse> inv) const = delete;
KFR_MEM_INTRINSIC void execute(complex<T>* out, const T* in, u8* temp, cdirect_t = {}) const
{
this->execute_dft(cfalse, out, ptr_cast<complex<T>>(in), temp);
}
KFR_MEM_INTRINSIC void execute(T* out, const complex<T>* in, u8* temp, cinvert_t = {}) const
{
this->execute_dft(ctrue, ptr_cast<complex<T>>(out), in, temp);
}
template <univector_tag Tag1, univector_tag Tag2, univector_tag Tag3>
KFR_MEM_INTRINSIC void execute(univector<complex<T>, Tag1>& out, const univector<T, Tag2>& in,
univector<u8, Tag3>& temp, cdirect_t = {}) const
{
this->execute_dft(cfalse, out.data(), ptr_cast<complex<T>>(in.data()), temp.data());
}
template <univector_tag Tag1, univector_tag Tag2, univector_tag Tag3>
KFR_MEM_INTRINSIC void execute(univector<T, Tag1>& out, const univector<complex<T>, Tag2>& in,
univector<u8, Tag3>& temp, cinvert_t = {}) const
{
this->execute_dft(ctrue, ptr_cast<complex<T>>(out.data()), in.data(), temp.data());
}
template <univector_tag Tag1, univector_tag Tag2>
KFR_MEM_INTRINSIC void execute(univector<complex<T>, Tag1>& out, const univector<T, Tag2>& in, u8* temp,
cdirect_t = {}) const
{
this->execute_dft(cfalse, out.data(), ptr_cast<complex<T>>(in.data()), temp);
}
template <univector_tag Tag1, univector_tag Tag2>
KFR_MEM_INTRINSIC void execute(univector<T, Tag1>& out, const univector<complex<T>, Tag2>& in, u8* temp,
cinvert_t = {}) const
{
this->execute_dft(ctrue, ptr_cast<complex<T>>(out.data()), in.data(), temp);
}
}
https://github.com/kfrlib/kfr/blob//include/kfr/dft/fft.hpp#L264
idft
function¶
template <typename T, univector_tag Tag>
univector<complex<T>>
idft(const univector<complex<T>, Tag> &input)
Performs Inverse DFT using cached plan
Source code
template <typename T, univector_tag Tag>
univector<complex<T>> idft(const univector<complex<T>, Tag>& input)
{
dft_plan_ptr<T> dft = dft_cache::instance().get(ctype_t<T>(), input.size());
univector<complex<T>> output(input.size(), std::numeric_limits<T>::quiet_NaN());
univector<u8> temp(dft->temp_size);
dft->execute(output, input, temp, ctrue);
return output;
}
https://github.com/kfrlib/kfr/blob//include/kfr/dft/cache.hpp#L141
irealdft
function¶
template <typename T, univector_tag Tag>
univector<T>
irealdft(const univector<complex<T>, Tag> &input)
Permorms Real Inverse DFT using cached plan
Source code
template <typename T, univector_tag Tag>
univector<T> irealdft(const univector<complex<T>, Tag>& input)
{
dft_plan_real_ptr<T> dft = dft_cache::instance().getreal(ctype_t<T>(), (input.size() - 1) * 2);
univector<T> output((input.size() - 1) * 2, std::numeric_limits<T>::quiet_NaN());
univector<u8> temp(dft->temp_size);
dft->execute(output, input, temp);
return output;
}
https://github.com/kfrlib/kfr/blob//include/kfr/dft/cache.hpp#L163
realdft
function¶
template <typename T, univector_tag Tag>
univector<complex<T>>
realdft(const univector<T, Tag> &input)
Performs Real Direct DFT using cached plan
Source code
template <typename T, univector_tag Tag>
univector<complex<T>> realdft(const univector<T, Tag>& input)
{
dft_plan_real_ptr<T> dft = dft_cache::instance().getreal(ctype_t<T>(), input.size());
univector<complex<T>> output(input.size() / 2 + 1, std::numeric_limits<T>::quiet_NaN());
univector<u8> temp(dft->temp_size);
dft->execute(output, input, temp);
return output;
}
https://github.com/kfrlib/kfr/blob//include/kfr/dft/cache.hpp#L152
reference_dft
function¶
template <typename T>
void reference_dft(complex<T> *out, const complex<T> *in,
size_t size, bool inversion = false,
size_t out_delta = 1,
size_t in_delta = 1)
Performs Complex DFT using reference implementation (slow, used for testing)
Source code
template <typename T>
void reference_dft(complex<T>* out, const complex<T>* in, size_t size, bool inversion = false,
size_t out_delta = 1, size_t in_delta = 1)
{
if (in == out)
{
std::vector<complex<T>> tmpin(size);
for (int i = 0; i < size; ++i)
tmpin[i] = in[i * in_delta];
return reference_dft(out, tmpin.data(), size, inversion, out_delta, 1);
}
if (is_poweroftwo(size))
{
return internal_generic::reference_dft_po2(out, in, size, inversion, out_delta, in_delta);
}
else
{
return internal_generic::reference_dft_nonpo2(out, in, size, inversion, out_delta, in_delta);
}
}
https://github.com/kfrlib/kfr/blob//include/kfr/dft/reference_dft.hpp#L118
template <typename T>
void reference_dft(complex<T> *out, const T *in,
size_t size, size_t out_delta = 1,
size_t in_delta = 1)
Performs Direct Real DFT using reference implementation (slow, used for testing)
Source code
template <typename T>
void reference_dft(complex<T>* out, const T* in, size_t size, size_t out_delta = 1, size_t in_delta = 1)
{
if (size < 1)
return;
std::vector<complex<T>> tmpin(size);
for (index_t i = 0; i < size; ++i)
tmpin[i] = in[i * in_delta];
std::vector<complex<T>> tmpout(size);
reference_dft(tmpout.data(), tmpin.data(), size, false, 1, 1);
for (index_t i = 0; i < size / 2 + 1; i++)
out[i * out_delta] = tmpout[i];
}
https://github.com/kfrlib/kfr/blob//include/kfr/dft/reference_dft.hpp#L140
reference_dft_md
function¶
template <typename T>
void reference_dft_md(complex<T> *out, const complex<T> *in,
shape<dynamic_shape> size,
bool inversion = false,
size_t out_delta = 1,
size_t in_delta = 1)
Performs Multidimensional Complex DFT using reference implementation (slow, used for testing)
Source code
template <typename T>
void reference_dft_md(complex<T>* out, const complex<T>* in, shape<dynamic_shape> size,
bool inversion = false, size_t out_delta = 1, size_t in_delta = 1)
{
index_t total = size.product();
if (total < 1)
return;
if (total == 1)
{
out[0] = in[0];
return;
}
index_t inner = 1;
index_t outer = total;
for (int axis = size.dims() - 1; axis >= 0; --axis)
{
index_t d = size[axis];
outer /= d;
for (index_t o = 0; o < outer; ++o)
{
for (index_t i = 0; i < inner; ++i)
{
reference_dft(out + (i + o * inner * d) * out_delta, in + (i + o * inner * d) * in_delta, d,
inversion, out_delta * inner, in_delta * inner);
}
}
in = out;
in_delta = out_delta;
inner *= d;
}
}
https://github.com/kfrlib/kfr/blob//include/kfr/dft/reference_dft.hpp#L155
template <typename T>
void reference_dft_md(complex<T> *out, const T *in,
shape<dynamic_shape> shape,
bool inversion = false,
size_t out_delta = 1,
size_t in_delta = 1)
Performs Multidimensional Direct Real DFT using reference implementation (slow, used for testing)
Source code
template <typename T>
void reference_dft_md(complex<T>* out, const T* in, shape<dynamic_shape> shape, bool inversion = false,
size_t out_delta = 1, size_t in_delta = 1)
{
index_t size = shape.product();
if (size < 1)
return;
std::vector<complex<T>> tmpin(size);
for (index_t i = 0; i < size; ++i)
tmpin[i] = in[i * in_delta];
std::vector<complex<T>> tmpout(size);
reference_dft_md(tmpout.data(), tmpin.data(), shape, inversion, 1, 1);
index_t last = shape.back() / 2 + 1;
for (index_t i = 0; i < std::max(index_t(1), shape.remove_back().product()); ++i)
for (index_t j = 0; j < last; j++)
out[(i * last + j) * out_delta] = tmpout[i * shape.back() + j];
}
https://github.com/kfrlib/kfr/blob//include/kfr/dft/reference_dft.hpp#L188
reference_dft_nonpo2
function¶
template <typename T>
void reference_dft_nonpo2(complex<T> *out,
const complex<T> *in, size_t size,
bool inversion,
size_t out_delta = 1,
size_t in_delta = 1)
Performs Complex FFT using reference implementation (slow, used for testing)
Source code
template <typename T>
void reference_dft_nonpo2(complex<T>* out, const complex<T>* in, size_t size, bool inversion,
size_t out_delta = 1, size_t in_delta = 1)
{
constexpr T pi2 = c_pi<T, 2>;
const complex<T> w = pi2 * complex<T>{ 0, T(inversion ? +1 : -1) };
if (size < 2)
return;
{
complex<T> sum = 0;
for (size_t j = 0; j < size; j++)
sum += in[j * in_delta];
out[0] = sum;
}
for (size_t i = 1; i < size; i++)
{
complex<T> sum = in[0];
for (size_t j = 1; j < size; j++)
{
complex<T> tw = std::exp(w * (static_cast<T>(i) * j / size));
sum += tw * in[j * in_delta];
}
out[i * out_delta] = sum;
}
}
https://github.com/kfrlib/kfr/blob//include/kfr/dft/reference_dft.hpp#L90
Auto-generated from sources, Revision , https://github.com/kfrlib/kfr/blob//include/kfr/