MCPcopy Create free account
hub / github.com/DeepRec-AI/DeepRec / Fft1D

Function Fft1D

tensorflow/compiler/xla/service/hlo_evaluator.cc:874–925  ·  view source on GitHub ↗

Non-recursive implementation of the Cooley-Tukey radix-2 decimation in time. Performs 1D FFT transform for the lengths, which are powers of 2. Runs in O(length * log(length)) time. Uses the same parameters as the naive implementation above, except that the preallocated buffer must be at least twice as big as the length of the transform, because the buffer is used to hold both input and output valu

Source from the content-addressed store, hash-verified

872// hold both input and output values for each stage of the transform.
873//
874void Fft1D(int64 length, int64 start, int64 stride, bool inverse,
875 bool contract_output, bool expand_input, absl::Span<complex128> data,
876 absl::Span<complex128> buffer) {
877 CHECK(IsPowerOfTwo(static_cast<uint64>(length)));
878 const bool input_is_zero =
879 GatherToBuffer(data, length, start, stride, expand_input, buffer);
880
881 if (!input_is_zero) {
882 auto generate_twiddles = [](int64 length, bool inverse) {
883 std::vector<complex128> twiddles;
884 // Need only half the twiddles.
885 for (int64 k = 0; k < length / 2; k++) {
886 twiddles.push_back(Twiddle(k, length, inverse));
887 }
888 return twiddles;
889 };
890
891 // Indices into the parts of the buffer used for input and output values.
892 int64 in_base = length;
893 int64 out_base = 0;
894
895 // At each stage, we "split" the input data into num_blocks, with block_size
896 // values in each block.
897 for (int64 num_blocks = 1; num_blocks < length; num_blocks *= 2) {
898 // Swap input and output parts of the buffer.
899 std::swap(in_base, out_base);
900 auto twiddles = generate_twiddles(num_blocks * 2, inverse);
901 const int64 block_size = length / num_blocks;
902 const int64 next_iteration_block_size = block_size / 2;
903 for (int64 block = 0; block < num_blocks; block++) {
904 const int64 in_offset = in_base + block * block_size;
905 const int64 out_offset = out_base + block * next_iteration_block_size;
906 // For each (even, odd) pair of values in the block, calculate two
907 // output values as even + twiddle * odd and even - twiddle * odd.
908 for (int64 pair = 0; pair < block_size / 2; pair++) {
909 const complex128 even = buffer[in_offset + pair];
910 const complex128 odd = buffer[in_offset + block_size / 2 + pair];
911 const complex128 twiddled_odd = twiddles[block] * odd;
912 buffer[out_offset + pair] = even + twiddled_odd;
913 buffer[out_offset + length / 2 + pair] = even - twiddled_odd;
914 }
915 }
916 }
917 // Copy computed result back to data.
918 const int64 ub = contract_output ? length / 2 + 1 : length;
919 for (int64 k = 0; k < ub; k++) {
920 complex128 value = buffer[out_base + k];
921 data[start + k * stride] =
922 inverse ? value / complex128(length, 0.0) : value;
923 }
924 }
925}
926
927// Determine, which implementation of 1D transform to use and call it.
928void Dft1D(int64 length, int64 start, int64 stride, bool inverse,

Callers 1

Dft1DFunction · 0.85

Calls 4

GatherToBufferFunction · 0.85
TwiddleFunction · 0.85
IsPowerOfTwoFunction · 0.50
push_backMethod · 0.45

Tested by

no test coverage detected