I see how one could, say, do an in-place real to complex transform or vice-versa by casting pointers to the appropriate type, eg.,
cufftExecZ2D(plan, complexArray, (cufftReal *)complexArray);
where complexArray is an array of cufftDoubleComplex’s. However, I am unable to do something similar outside of a cufft call, i.e., I would like to access complexArray linearly as if it were a real array. Or the opposite: I would like to access an array of cufftDoubleReal’s as if it were a cufftDoubleComplex. I am confused about data formatting here; whereas the complex format for FFTW is just an array of length-2 double arrays (array[numComplex]) which can easily be accessed as a 1-D array, in CUFFT complex numbers are double2’s accessed via .x and .y.
The motivation here is to be able to do complex-to-complex, complex-to-real, and real-to-complex transforms with the minimum allocated storage. I’d be fine with two arrays storing 2 * N doubles (for N complex numbers). I’d be interested in trying in-place transforms (so, one 2 * N length array of doubles), but would rather allocate two arrays if there will be a speed penalty. I just don’t know how to cast properly.
Okay, I’m not really sure what I was doing wrong when I tried this earlier, but this code works:
((cufftDoubleReal*)x) = 15;
This prints 15 twice. So I suppose that is my answer.
As far as I understand the C++ standard (relevant because CUDA is a language in the C++ family and uses standard C++ compiler technology), you are skating on thin ice here: Type punning through pointer casting results in undefined behavior. But given that the underlying elemental type is the same (‘double’) in this case the risk may be minimized. Just be aware of the risk.
Fortunately I am not actually doing this. In-place transforms won’t work this way (even where out-of-place transforms between two identically structured/allocated arrays work). I had to use the advanced data layout, set the inner stride to be 2 when using a complex array for real data, and refer only to the real (__.x) components.
Hopefully this evades the issue you mention. It seems to be the only proper way to use CUFFT for in-place real to complex (and vice-versa) transfers.
Your first example was using cufftReal, the second one was using cufftDoubleReal
They are not the same thing. attempting to cast elements of a cufftDoubleComplex array to cufftReal doesn’t make any sense. casting elements of a cufftDoubleComplex array to cufftDoubleReal sort of makes sense, with the caveats pointed out by njuffa
That’s not the issue, I was just careless when I typed that out. I’ve only been using the double precision types.