Search code examples
c++gccc++17fftwstrict-aliasing

Calling FFTW's in-place real-to-complex transform without violating strict aliasing rules


I wish to call fftw's in-place real-to-complex transform function, which has the following signature:

fftw_plan fftw_plan_dft_r2c_1d(
    int n,             // transform length
    double* in,        // pointer to input array
    fftw_complex* out, // pointer to output array
    unsigned flags     // flags
);

The documentation says that I should indicate that I wish to perform an in-place transform by passing in aliasing pointers for the in and out parameters.


QUESTION: How can in and out alias without violating strict aliasing rules?


I am open to GCC-specific extensions (i.e., using unions to do type-punning, even though the standard declares this to be undefined behavior). Even if this extension is permitted, a union cannot contain dynamically-sized arrays (which is a must in this applications - I do not know the transform length in advance). Does anyone have any ideas? Thanks in advance.


Solution

  • According to this link fftw_complex is the following typedef:

    typedef double fftw_complex[2];
    

    And by the pre-C++20 rules fftw_complex* may alias double* because of this ([basic.lval]p8.6):

    If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:
    ...
    — an aggregate or union type that includes one of the aforementioned types among its elements or nonstatic data members (including, recursively, an element or non-static data member of a subaggregate or contained union)

    Array is an aggregate and our array contains doubles thus it is allowed to alias a double pointer. Hence, no strict aliasing rule violation happens in the fftw_plan_dft_r2c_1d function and you can safely use it.

    Note, however, that this paragraph is removed from the C++20 standard and it is debated that it should be removed from the C standard as well. But since it is not removed yet and GCC & clang actually respect it I guess it is safe to assume that the behavior won't change with C++20 implementation. And MSVC, to my knowledge, doesn't take advantage of SAR at all.