DTolm / VkFFT

Vulkan/CUDA/HIP/OpenCL/Level Zero/Metal Fast Fourier Transform library
MIT License
1.48k stars 88 forks source link

Orthogonal normalization #175

Open DejvBayer opened 1 month ago

DejvBayer commented 1 month ago

Hi,

I was wandering if it would be possible to extend the normalization options to include orthogonal normalization for both DFT and DTT. The behaviour should be like:

  1. DFT: multiply the output of forward or inverse transformation of size N by $\frac{1}{\sqrt{N}}$.
  2. DTT: it is a bit more compilcated as it depends on the DTT type. Before you multiply the output by $\frac{1}{\sqrt{N}}$, for each 1D subtransform:
    • DCT-I: multiply first and last input value by $\sqrt{2}$, multiply first and last output value by $\frac{1}{\sqrt{2}}$.
    • DCT-II : multiply first output value by $\frac{1}{\sqrt{2}}$.
    • DCT-III: multiply first input value by $\sqrt{2}$.
    • DCT-IV: nothing.
    • DST-I: nothing.
    • DST-II: multiply last output value by $\frac{1}{\sqrt{2}}$.
    • DST-III: multiply last input value by $\sqrt{2}$.
    • DST-IV: nothing.

I would suggest adding an enum to specify the type of the normalization:

typedef enum VkFFTNormalize
{
  VKFFT_NORMALIZE_NONE       = 0, // Do not normalize.
  VKFFT_NORMALIZE_UNITARY    = 1, // 1/N normalization applied to inverse transformation.
  VKFFT_NORMALIZE_ORTHOGONAL = 2  // 1/sqrt(N) normalization applied to both forward and inverse transformations, applies aditional operations to DTT transforms to make the transformation orthogonal.
} VkFFTNormalize;

In the VkFFTConfiguration structure I would suggest either to change the normalization member datatype to VkFFTNormalize datatype or just stick to the original pfUINT:

typedef struct {

  // ...

  pfUINT normalize; //normalize inverse transform (0 - off, 1 - on)
  // 1. -> VkFFTNormalize normalize;
  // 2. -> pfUINT normalize;

  // ...

} VkFFTConfiguration;

Both of the solutions work without warnings. See the code example.

Thanks.

David

DTolm commented 1 month ago

Hello,

I will add an option to change configuration.normalize to support orthogonal normalization (need to be careful with the real transforms there). Another thing is as there are too many ways to scale the numbers, maybe just making full support for callbacks is a good idea?

Best regards, Dmitrii

DejvBayer commented 3 weeks ago

Hi Dmitrii,

thanks for your response. The callbacks would definitely solve the problem with scaling. However I still have the feeling that when you want to do only the normalization, it would be much easier just to specify the forward/inverse scale or use the solution I proposed instead of studying and writing own callbacks. I don't mind writing callbacks myself, but I think there will be people having problems understanding them eventhough all they wanted was to run a normalized transformation.

I'm curious about your thoughts on this matter.

Thanks!

David

DTolm commented 3 weeks ago

Hello,

This is a valid point, I will try to add this before the next release.

Best regards, Dmitrii

DejvBayer commented 3 weeks ago

Perfect, thank you very much!