inverse_transform_power_of_2_3d (Fast-Fourier Transform)


Import

#include <archr/fft/fft.h>
#include <archr/fft/fft.hpp>
use archr_fft
import archr.fft
atomsLoads('archr')

Synopsis

 void archr_fft_inverse_transform_power_of_2_3d_f32(float *out_real, float *out_imag, const float *real, const float *imag, const archr_fft_planner_3d_f32_t *plan);
(1)
 void archr_fft_inverse_transform_power_of_2_3d_f64(double *out_real, double *out_imag, const double *real, const double *imag, const archr_fft_planner_3d_f64_t *plan);
(2)
 void archr_fft_inverse_transform_power_of_2_3d_zf32(void *output, const void *input, const archr_fft_planner_3d_zf32_t *plan);
(3)
 void archr_fft_inverse_transform_power_of_2_3d_zf64(void *output, const void *input, const archr_fft_planner_3d_zf64_t *plan);
(4)
namespace archr {
 void inverse_transform_power_of_2_3d(const float *real, const float *imag, float *out_real, float *out_imag, const planner_3d<float>& plan);
(1)
 void inverse_transform_power_of_2_3d(const double *real, const double *imag, double *out_real, double *out_imag, const planner_3d<double>& plan);
(2)
 void inverse_transform_power_of_2_3d(const std::complex<float>*input, std::complex<float>*output, const planner_3d<std::complex<float>>& plan);
(3)
 void inverse_transform_power_of_2_3d(const std::complex<double>*input, std::complex<double>*output, const planner_3d<std::complex<double>>& plan);
(4)
}
subroutine archr_fft_inverse_transform_power_of_2_3d_f32(real(4), dimension(*, *), parameter :: real, real(4), dimension(*, *), parameter :: imag, real(4), dimension(*, *) :: out_real, real(4), dimension(*, *) :: out_imag, type(archr_fft_planner_3d_f32), parameter :: plan)
(1)
subroutine archr_fft_inverse_transform_power_of_2_3d_f64(real(8), dimension(*, *), parameter :: real, real(8), dimension(*, *), parameter :: imag, real(8), dimension(*, *) :: out_real, real(8), dimension(*, *) :: out_imag, type(archr_fft_planner_3d_f64), parameter :: plan)
(2)
subroutine archr_fft_inverse_transform_power_of_2_3d_zf32(complex(4), dimension(*, *), parameter :: input, complex(4), dimension(*, *) :: output, type(archr_fft_planner_3d_zf32), parameter :: plan)
(3)
subroutine archr_fft_inverse_transform_power_of_2_3d_zf64(complex(8), dimension(*, *), parameter :: input, complex(8), dimension(*, *) :: output, type(archr_fft_planner_3d_zf64), parameter :: plan)
(4)

Description

This function calculates a 3D inverse Fourrier transform of the input data. The results from the transform are stored in-order in the output array with the zero frequency component or the DC component stored in output[0]. The best possible performance from Arch-R FFT is realized when the input and output arrays are correctly aligned.

Example

#include <archr/fft.h>

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <limits.h>
#include <complex.h>

typedef float T;

int main(){
  {
    //input and output are split complex numbers. (storage format rrrrrrr...., iiiiiiii....)
    size_t height = 256, width = 512, depth = 256;
    size_t N = height * width * depth;
    archr_fft_planner_3d_f32_t a_planner;
    archr_fft_init_planner_f32_3d(&a_planner, height, width, depth, archr_fft_planner_direction_Reverse);

    T *real = malloc(sizeof(T) * N);
    T *imag = malloc(sizeof(T) * N);
    T *out_real = malloc(sizeof(T) * N);
    T *out_imag = malloc(sizeof(T) * N);
    for(size_t i = 0; i < N; ++i){
      real[i] = (T)rand() / INT_MAX;
      imag[i] = (T)rand() / INT_MAX;
    }

    archr_fft_inverse_transform_power_of_2_3d_f32(out_real, out_imag, real, imag, &a_planner);
    T sum_real = 0, sum_imag = 0;
    for(size_t i = 0; i < N; ++i){
      sum_real += out_real[i];
      sum_imag += out_imag[i];
    }
    printf(" Sum %f +i %f\n", sum_real, sum_imag);
    free(real);
    free(imag);
    free(out_real);
    free(out_imag);
    archr_fft_destroy_planner_3d_f32(&a_planner);
  }
  {
    //input and output are interleaved complex numbers. (storage format riririri...)
    size_t height = 256, width = 512, depth = 256;
    size_t N = height * width * depth;
    archr_fft_planner_3d_zf32_t a_planner;
    archr_fft_init_planner_zf32_3d(&a_planner, height, width, depth, archr_fft_planner_direction_Reverse);

    T *input = malloc(2 * sizeof(T) * N);//times 2 as these are complex numbers
    T *output = malloc(2 * sizeof(T) * N);
    for(size_t i = 0; i < N * 2; ++i){
      input[i] = (T)rand() / INT_MAX;
    }

    archr_fft_inverse_transform_power_of_2_3d_zf32(output, input, &a_planner);
    T sum_real = 0, sum_imag = 0;
    for(size_t i = 0; i < N; ++i){
      sum_real += output[2 * i];
      sum_imag += output[2 * i + 1];
    }
    printf(" Sum %f +i %f\n", sum_real, sum_imag);
    free(input);
    free(output);
    archr_fft_destroy_planner_3d_zf32(&a_planner);
  }
}

Possible Output

#include <archr/fft.hpp>

#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>

using T = float;

int main(){
  {
    //input and output are split complex numbers. (storage format rrrrrrr...., iiiiiiii....)
    std::size_t height = 256, width = 256, depth = 256;
    std::size_t N = height * width * depth;
    archr::fft::planner_3d<T> a_planner(height, width, depth, archr::fft::Forward);

    std::vector<T> real(N), imag(N), out_real(N), out_imag(N);
    std::generate(real.begin(), real.end(),
                 [](){return (T)std::rand() / (T)std::numeric_limits<int>::max();}
                 );
    std::generate(imag.begin(), imag.end(),
                 [](){return (T)std::rand() / (T)std::numeric_limits<int>::max();}
                 );

    archr::fft::inverse_transform_power_of_2_3d( real.data(), imag.data()
                                               , out_real.data(), out_imag.data()
                                               a_planner
                                               );
    T sum_real = std::accumulate(out_real.begin(), out_real.end(), T(0));
    T sum_imag = std::accumulate(out_imag.begin(), out_imag.end(), T(0));
    std::cout<<" sum " << sum_real << " " << sum_imag  << std::endl;
  }
  {
    //input and output are interleaved complex numbers. (storage format riririri...)
    std::size_t height = 256, width = 256, depth = 256;
    std::size_t N = height * width * depth;
    archr::fft::planner_3d<std::complex<T>> a_planner(height, width, depth, archr::fft::Forward);

    std::vector<std::complex<T>> input(N), output(N);
    auto my_fill = [](){
      T r_tmp = (T)std::rand() / (T)std::numeric_limits<int>::max();
      T i_tmp = (T)std::rand() / (T)std::numeric_limits<int>::max();
      return std::complex<T>{r_tmp, i_tmp};
    };
    std::generate(input.begin(), input.end(), my_fill);

    archr::fft::inverse_transform_power_of_2_3d(input.data(), output.data(), a_planner);
    std::complex<T> sum = std::accumulate(output.begin(), output.end(), std::complex<T>(0));
    std::cout<<" sum " << sum << std::endl;
  }
}

Possible Output

program test
  use archr_fft
  integer(8), parameter    :: height = 256, width = 512, depth = 128, N = height * width * depth
  !
  real(4)   , dimension(N) :: f32_r, f32_i, f32_r_out, f32_i_out
  COMPLEX(4), dimension(N) :: f32_z, f32_z_out
  !
  real(4)                  :: r0, i0
  real(4)                  :: min0, max0, sum_real, sum_imag
  COMPLEX(4)               :: sum_z
  !
  !integer(8)               :: plan
  type(archr_fft_planner_3d_f32) :: plan_f32
  type(archr_fft_planner_3d_zf32) :: plan_zf32
  !
  ! Init:
  min0 = 0
  max0 = 1
  sum_real = 0
  sum_imag = 0
  sum_z = (0,0)
  do i=1,N
    r0 = random_in(min0, max0)
    i0 = random_in(min0, max0)
    !
    f32_r(i) = r0
    f32_i(i) = i0
    f32_z(i) = COMPLEX(r0, i0)
  end do
  ! split complex format rrrrr...., iiiiiii
  call archr_fft_init_planner_3d_f32(plan_f32, height, width, depth, 0);
  call archr_fft_inverse_transform_power_of_2_3d_f32(f32_r_out, f32_i_out, f32_r, f32_i, plan_f32)
  do i=1,N
    sum_real = sum_real + f32_r_out(i)
    sum_imag = sum_imag + f32_i_out(i)
  end do
  print *, "sum ", sum_real, " ", sum_imag
  call archr_fft_destroy_planner_3d_f32(plan_f32);
  ! interleaved complex format r, i, r, i
  call archr_fft_init_planner_3d_zf32(plan_zf32, height, width, depth, 0);
  call archr_fft_inverse_transform_power_of_2_3d_zf32(f32_z_out, f32_z, plan_zf32)
  do i=1,N
    sum_z = sum_z + f32_z_out(i)
  end do
  print *, "sum ", sum_z
contains
  ! Generate a random number within a range
  function random_in(mn, mx) result(r)
    real(4) :: r
    real(4), intent(in) :: mn, mx
    r = mn + (rand() * (mx - mn))
  end function random_in
end program

Possible Output

See Also