Developer Reference for Intel® oneAPI Math Kernel Library for C

ID 766684
Date 12/16/2022
Public

A newer version of this document is available. Customers should click here to go to the newest version.

Document Table of Contents

DFTI_PACKED_FORMAT

The result of the forward transform of real data is a conjugate-even sequence. Due to the symmetry property, only a part of the complex-valued sequence is stored in memory. The DFTI_PACKED_FORMAT configuration parameter defines how the data is packed. Possible values of DFTI_PACKED_FORMAT depend on the values of the DFTI_CONJUGATE_EVEN_STORAGE configuration parameter:

  • DFTI_CONJUGATE_EVEN_STORAGE=DFTI_COMPLEX_COMPLEX.

    The only value of DFTI_PACKED_FORMAT can be DFTI_CCE_FORMAT. You can use this value with transforms of any dimension. For a description of the corresponding packed format, see DFTI_CONJUGATE_EVEN_STORAGE.

  • DFTI_CONJUGATE_EVEN_STORAGE=DFTI_COMPLEX_REAL.

    DFTI_PACKED_FORMAT can be DFTI_CCS_FORMAT, DFTI_PACK_FORMAT, or DFTI_PERM_FORMAT. You can use these values with one- and two-dimensional transforms only. The corresponding packed formats are described below.

NOTE:

Although DFTI_CONJUGATE_EVEN_STORAGE=DFTI_COMPLEX_REAL is the default setting for the DFTI_REAL forward domain, avoid using this storage scheme because it is supported only for one- and two-dimensional transforms, is incompatible with storage schemes of other FFT libraries, and will be deprecated in future.

DFTI_CCS_FORMAT for One-dimensional Transforms

The following figure illustrates the storage of a one-dimensional (1D) size-N conjugate-even sequence in a real array for the CCS, PACK, and PERM packed formats. The CCS format requires an array of size N+2, while the other formats require an array of size N. Zero-based indexing is used.

Storage of a 1D Size-N Conjugate-even Sequence in a Real Array

NOTE:
For storage of a one-dimensional conjugate-even sequence in a real array, CCS is in the same format as CCE.

The real and imaginary parts of the complex-valued conjugate-even sequence Zk are located in a real-valued array AC as illustrated by figure "Storage of a 1D Size-N Conjugate-even Sequence in a Real Array" and can be used to reconstruct the whole conjugate-even sequence as follows:

float *AR; // malloc( sizeof(float)*N )
float *AC; // malloc( sizeof(float)*(N+2) )
...
status = DftiSetValue( desc, DFTI_PACKED_FORMAT, DFTI_CCS_FORMAT );
...
// on input:  R{k} = AR[k]  
status = DftiComputeForward( desc, AR, AC );  // real-to-complex FFT
// on output:
// for k=0…N/2:     Z{k} =   AC[2*k+0]         + I*AC[2*k+1]
// for k=N/2+1…N-1: Z{k} =   AC[2*(N-k)%N + 0] - I*AC[2*(N-k)%N + 1] 

DFTI_CCS_FORMAT for Two-dimensional Transforms

NOTE:
The storage of a two-dimensional (2D) sequence in a packed format is deprecated.

The following figure illustrates the storage of a two-dimensional (2D) M-by-N conjugate-even sequence in a real array for the CCS packed format. This format requires an array of size (M+2)-by-(N+2). Row-major layout and zero-based indexing are used. Different colors mark logically separate parts of the result. "n/u" means "not used".

Storage of a 2D M-by-N Conjugate-even Sequence in a Real Array for the CCS Format



The real and imaginary parts of the complex-valued conjugate-even sequence Zk1,k2 are located in a real-valued array AC as illustrated by figure "Storage of a 2D M-by-N Conjugate-even Sequence in a Real Array for the CCS Format" and can be used to reconstruct the whole sequence as follows:

float *AR; // malloc( sizeof(float)*N1*N2 )
float *AC; // malloc( sizeof(float)*(N1+2)*(N2+2) )
...
status = DftiSetValue( desc, DFTI_PACKED_FORMAT, DFTI_CCS_FORMAT );
...
// on input:  R{k1,k2} = AR[N2*k1 + k2]  
status = DftiComputeForward( desc, AR, AC );  // real-to-complex FFT
// on output: Z{k1,k2} = re + I*im, where
//  if (k1==0) {
//     if (k2 <= N2/2) {
//          re =  AC[2*k2+0];
//          im =  AC[2*k2+1];
//      } else {
//          re =  AC[2*(N2-k2)+0];
//          im = -AC[2*(N2-k2)+1];
//      }}
//  else if (k2==0){
//      if (k1 <= N1/2) {
//          re =  AC[(2*k1+0)*(N2+2)];
//          im =  AC[(2*k1+1)*(N2+2)];
//      } else {
//          re =  AC[(2*(N1-k1)+0)*(N2+2)];
//          im = -AC[(2*(N1-k1)+1)*(N2+2)];
//      }}
//  else if (k2 == N2-k2) {
//      if (k1 <= N1/2) {
//          re =  AC[(2*k1+0)*(N2+2) + 2*(N2/2)];
//          im =  AC[(2*k1+1)*(N2+2) + 2*(N2/2)];
//      } else{
//          re =  AC[(2*(N1-k1)+0)*(N2+2) + 2*(N2/2)];
//          im = -AC[(2*(N1-k1)+1)*(N2+2) + 2*(N2/2)];
//      }}
//  else if (k2 <= N2/2) {
//      re =  AC[k1*(N2+2)+2*k2+0];
//      im =  AC[k1*(N2+2)+2*k2+1];
//  } else {
//      re =  AC[(N1-k1)*(N2+2)+2*(N2-k2)+0];
//      im = -AC[(N1-k1)*(N2+2)+2*(N2-k2)+1];
//  }

DFTI_PACK_FORMAT for One-dimensional Transforms

The real and imaginary parts of the complex-valued conjugate-even sequence Zk are located in a real-valued array AC as illustrated by figure "Storage of a 1D Size-N Conjugate-even Sequence in a Real Array" and can be used to reconstruct the whole conjugate-even sequence as follows:

float *AR; // malloc( sizeof(float)*N )
float *AC; // malloc( sizeof(float)*N )
...
status = DftiSetValue( desc, DFTI_PACKED_FORMAT, DFTI_PACK_FORMAT );
...
// on input:  R{k} = AR[k]  
status = DftiComputeForward( desc, AR, AC );  // real-to-complex FFT
// on output: Z{k} = re + I*im, where
// if (k == 0) {
//     re =  AC[0];
//     im =  0;
// } else if (k == N-k) {
//     re =  AC[2*k-1];
//     im =  0;
// } else if (k <= N/2) {
//     re =  AC[2*k-1];
//     im =  AC[2*k-0];
// } else {
//     re =  AC[2*(N-k)-1];
//     im = -AC[2*(N-k)-0];
// }

DFTI_PACK_FORMAT for Two-dimensional Transforms

The following figure illustrates the storage of a 2D M-by-N conjugate-even sequence in a real array for the PACK packed format. This format requires an array of size M-by-N. Row-major layout and zero-based indexing are used. Different colors mark logically separate parts of the result.

Storage of a 2D M-by-N Conjugate-even Sequence in a Real Array for the PACK Format

The real and imaginary parts of the complex-valued conjugate-even sequence Zk1,k2 are located in a real-valued array AC as illustrated by figure "Storage of a 2D M-by-N Conjugate-even Sequence in a Real Array for the PACK Format" and can be used to reconstruct the whole sequence as follows:

float *AR; // malloc( sizeof(float)*N1*N2 )
float *AC; // malloc( sizeof(float)*N1*N2 )
...
status = DftiSetValue( desc, DFTI_PACKED_FORMAT, DFTI_PACK_FORMAT );
...
// on input:  R{k1,k2} = AR[N2*k1 + k2]  
status = DftiComputeForward( desc, AR, AC );  // real-to-complex FFT
// on output: Z{k1,k2} = re + I*im, where
//  if (k1==0) {
//      if (k2 == 0) {
//          re =  AC[0];
//          im =  0;
//      } else if (k2 == N2-k2) {
//          re =  AC[2*k2-1];
//          im =  0;
//      } else if (k2 <= N2/2) {
//          re =  AC[2*k2-1];
//          im =  AC[2*k2-0];
//      } else {
//          re =  AC[2*(N2-k2)-1];
//          im = -AC[2*(N2-k2)-0];
//      }}
//  else if (k2==0) {
//      if (k1 == N1-k1) {
//          re =  AC[(N1-1)*N2];
//          im =  0;
//      } else if (k1 <= N1/2) {
//          re =  AC[(2*k1-1)*N2];
//          im =  AC[(2*k1-0)*N2];
//      } else {
//          re =  AC[(2*(N1-k1)-1)*N2];
//          im = -AC[(2*(N1-k1)-0)*N2];
//      }}
//  else if (k2 == N2-k2) {
//      if (k1 == N1-k1) {
//          re =  AC[N1*N2 - 1];
//          im =  0;
//      } else if (k1 <= N1/2) {
//          re =  AC[(2*k1 - 1)*N2 + N2-1];
//          im =  AC[(2*k1 - 0)*N2 + N2-1];
//      } else {
//          re =  AC[(2*(N1-k1) - 1)*N2 + N2-1];
//          im = -AC[(2*(N1-k1) - 0)*N2 + N2-1];
//      }}
//  else if (k2 <= N2/2) {
//      re =  AC[k1*N2+2*k2-1];
//      im =  AC[k1*N2+2*k2-0];
//  } else {
//      re =  AC[(N1-k1)*N2+2*(N2-k2) - 1];
//      im = -AC[(N1-k1)*N2+2*(N2-k2) - 0];
//  }

DFTI_PERM_FORMAT for One-dimensional Transforms

The real and imaginary parts of the complex-valued conjugate-even sequence Zk are located in real-valued array AC as illustrated by figure "Storage of a 1D Size-N Conjugate-even Sequence in a Real Array" and can be used to reconstruct the whole conjugate-even sequence as follows:

float *AR; // malloc( sizeof(float)*N )
float *AC; // malloc( sizeof(float)*N )
...
status = DftiSetValue( desc, DFTI_PACKED_FORMAT, DFTI_PERM_FORMAT );
...
// on input:  R{k} = AR[k]  
status = DftiComputeForward( desc, AR, AC );  // real-to-complex FFT
// on output: Z{k} = re + I*im, where
// if (k == 0) {
//     re =  AC[0];
//     im =  0;
// } else if (k == N-k) {
//     re =  AC[1];
//     im =  0;
// } else if (k <= N/2) {
//     re =  AC[2*k+0 - N%2];
//     im =  AC[2*k+1 - N%2];
// } else {
//     re =  AC[2*(N-k)+0 - N%2];
//     im = -AC[2*(N-k)+1 - N%2];
// }

DFTI_PERM_FORMAT for Two-dimensional Transforms

The following figure illustrates the storage of a 2D M-by-N conjugate-even sequence in a real array for the PERM packed format. This format requires an array of size M-by-N. Row-major layout and zero-based indexing are used. Different colors mark logically separate parts of the result.

Storage of a 2D M-by-N Conjugate-Even Sequence in a Real Array for the PERM Format

The real and imaginary parts of the complex-valued conjugate-even sequence Zk1,k2 are located in real-valued array AC as illustrated by figure "Storage of a 2D M-by-N Conjugate-even Sequence in a Real Array for the PERM Format" and can be used to reconstruct the whole sequence as follows:

float *AR; // malloc( sizeof(float)*N1*N2 )
float *AC; // malloc( sizeof(float)*N1*N2 )
...
status = DftiSetValue( desc, DFTI_PACKED_FORMAT, DFTI_PERM_FORMAT );
...
// on input:  R{k1,k2} = AR[N2*k1 + k2]  
status = DftiComputeForward( desc, AR, AC );  // real-to-complex FFT
// on output: Z{k1,k2} = re + I*im, where
//  if (k1==0) {
//      if (k2 == 0) {
//          re =  AC[0];
//          im =  0;
//      } else if (k2 == N2-k2) {
//          re =  AC[1];
//          im =  0;
//      } else if (k2 <= N2/2) {
//          re =  AC[2*k2+0 - N2%2];
//          im =  AC[2*k2+1 - N2%2];
//      } else {
//          re =  AC[2*(N2-k2)+0 - N2%2];
//          im = -AC[2*(N2-k2)+1 - N2%2];
//      }}
//  else if (k2==0) {
//      if (k1 == N1-k1) {
//          re =  AC[N2];
//          im =  0;
//      } else if (k1 <= N1/2) {
//          re =  AC[(2*k1+0 - N1%2)*N2];
//          im =  AC[(2*k1+1 - N1%2)*N2];
//      } else {
//          re =  AC[(2*(N1-k1)+0 - N1%2)*N2];
//          im = -AC[(2*(N1-k1)+1 - N1%2)*N2];
//      }}
//  else if (k2 == N2-k2) {
//      if (k1 == N1-k1) {
//          re =  AC[N2 + 1];
//          im =  0;
//      } else if (k1 <= N1/2) {
//          re =  AC[(2*k1+0 - N1%2)*N2 + 1];
//          im =  AC[(2*k1+1 - N1%2)*N2 + 1];
//      } else {
//          re =  AC[(2*(N1-k1)+0 - N1%2)*N2 + 1];
//          im = -AC[(2*(N1-k1)+1 - N1%2)*N2 + 1];
//      }}
//  else if (k2 <= N2/2) {
//      re =  AC[k1*N2+2*k2+0 - N2%2];
//      im =  AC[k1*N2+2*k2+1 - N2%2];
//  } else {
//      re =  AC[(N1-k1)*N2+2*(N2-k2)+0 - N2%2];
//      im = -AC[(N1-k1)*N2+2*(N2-k2)+1 - N2%2];
//  }

See Also