FFTW: Inverse of forward fft not equal to original function

B

brrk

I'm trying to use FFTW to compute fast summations, and I've run into
an issue:

int numFreq3 = numFreq*numFreq*numFreq;

FFTW_complex* dummy_sq_fft =
(FFTW_complex*)FFTW_malloc( sizeof(FFTW_complex)*numFreq3 );

FFTW_complex* dummy_sq =
(FFTW_complex*)FFTW_malloc( sizeof(FFTW_complex)*numFreq3 );

FFTW_complex* orig =
(FFTW_complex*)FFTW_malloc( sizeof(FFTW_complex)*numFreq3 );

FFTW_plan dummyPlan = FFTW_plan_dft_3d( numFreq, numFreq, numFreq,
orig, dummy_sq_fft, FFTW_FORWARD, FFTW_MEASURE );

FFTW_plan dummyInvPlan = FFTW_plan_dft_3d( numFreq, numFreq, numFreq,
dummy_sq_fft, dummy_sq, FFTW_BACKWARD, FFTW_MEASURE );

for(int i= 0; i < numFreq3; i++) {

orig[ i ][ 0 ] = sparseProfile02[ 0 ][ i ][ 0 ];

//img. part == 0

orig[ i ][ 1 ] = sparseProfile02[ 0 ][ i ] [ 1 ];

}

FFTW_execute(dummyPlan);

FFTW_execute(dummyInvPlan);

int count = 0;

for(int i=0; i<numFreq3; i++) {

double factor;
if(sparseProfile02[ 0 ] [ i ] [ 0 ])
factor = dummy_sq[ i ][ 0 ]/sparseProfile02[ 0 ][ i ][ 0 ];

else factor = dummy_sq[ i ][ 0 ];

if(factor < 0) {

count++;

}

}

std::cout<<"Count "<<count<<"\n";

FFTW_free(dummy_sq_fft);
FFTW_free(dummy_sq);

FFTW_destroy_plan(dummyPlan);
FFTW_destroy_plan(dummyInvPlan);
(Here sparseProfile02[0] is of type FFTW_complex*, and contains only
positive real data.)

Since we have dummy_sq = IFFT(FFT(sparseProfile02[ 0 ])), we must have
dummy_sq = n^3*sparseProfile02. But this is true only some of the
time; in fact, values on the dummy_sq grid are negative whenever
corresponding values on the sparseProfile02 grid are zero (but not
vice-versa). Does anyone know why this is happening?

thanks,

rk
 
F

Francois Grieu

I'm trying to use FFTW to compute fast summations, and;;

This is grossly off topic: C++, and algorithmic.
CLC is for spliting hair about C minutiae. C++, and
almost anything involving using double to represent
an actual quantity (rather than a curios such as NaN)
is a no-no. I am NOT sarcastic.

That said, it looks at fist glance that you could have
a numerical statbility problem, similar to the well
studied one occuring in integer multiplication using
FFT with float or double.

For a start, think about what "equality" or "negative"
means for the result of a computation involving double.


Francois Grieu
 
K

Keith Thompson

Francois Grieu said:
This is grossly off topic: C++, and algorithmic.
CLC is for spliting hair about C minutiae. C++, and
almost anything involving using double to represent
an actual quantity (rather than a curios such as NaN)
is a no-no. I am NOT sarcastic.

You may not be sarcastic, but you're largely mistaken.

The only C++ content in the post was the use of "std::cout << ...".
A bit of Googling indicates that FFTW is a C library.

And we've had extensive topical discussions here regarding
floating-point data and what it represents.

Having said that, there probably are better places to discuss this
particular topic. Quesions about a third-party library will usually get
better reponses in a forum that dicusses the particular library than in
one that discusses the language it's written in. (fftw.org doesn't
appear to host discussion forums, but they do encourage e-mail feedback;
you might consider asking them.)

(And the OP's code would be much easier to read with some indentation.)
 
J

Jens Thoms Toerring

brrk said:
I'm trying to use FFTW to compute fast summations, and I've run into
an issue:

int numFreq3 = numFreq*numFreq*numFreq;
FFTW_complex* dummy_sq_fft =
(FFTW_complex*)FFTW_malloc( sizeof(FFTW_complex)*numFreq3 );
FFTW_complex* dummy_sq =
(FFTW_complex*)FFTW_malloc( sizeof(FFTW_complex)*numFreq3 );
FFTW_complex* orig =
(FFTW_complex*)FFTW_malloc( sizeof(FFTW_complex)*numFreq3 );
FFTW_plan dummyPlan =
FFTW_plan_dft_3d( numFreq, numFreq, numFreq,
orig, dummy_sq_fft, FFTW_FORWARD, FFTW_MEASURE );
FFTW_plan dummyInvPlan =
FFTW_plan_dft_3d( numFreq, numFreq, numFreq,
dummy_sq_fft, dummy_sq, FFTW_BACKWARD, FFTW_MEASURE );
for (int i= 0; i < numFreq3; i++) {
orig[ i ][ 0 ] = sparseProfile02[ 0 ][ i ][ 0 ];
//img. part == 0
orig[ i ][ 1 ] = sparseProfile02[ 0 ][ i ] [ 1 ];
}
FFTW_execute(dummyPlan);
FFTW_execute(dummyInvPlan);

int count = 0;
for (int i=0; i<numFreq3; i++) {
double factor;
if (sparseProfile02[ 0 ] [ i ] [ 0 ])
factor = dummy_sq[ i ][ 0 ]/sparseProfile02[ 0 ][ i ][ 0 ];
else
factor = dummy_sq[ i ][ 0 ];

if (factor < 0) {
count++;
}
}
std::cout<<"Count "<<count<<"\n";
FFTW_free(dummy_sq_fft);
FFTW_free(dummy_sq);
FFTW_destroy_plan(dummyPlan);
FFTW_destroy_plan(dummyInvPlan);

(Here sparseProfile02[0] is of type FFTW_complex*, and contains only
positive real data.)
Since we have dummy_sq = IFFT(FFT(sparseProfile02[ 0 ])), we must have
dummy_sq = n^3*sparseProfile02. But this is true only some of the
time; in fact, values on the dummy_sq grid are negative whenever
corresponding values on the sparseProfile02 grid are zero (but not
vice-versa). Does anyone know why this is happening?

This is C++, I hope you realize (and this is comp.lang.c, not
comp.lang.c++). And it's about the result of some library, that
might be written in C but maybe not), not about the C language.

But what do you expect? That you get back the exact same values
you started with after some rather complex computations? That's
not how it works - computations with floating point values in-
troduce rounding errors and what you see here might be just a
result of that. How far off are the elements that were 0 at the
start compared to the deviations for elements that were non-
zero? If for example an element that was 1 before the forward
and backward transformation becomes maybe 0.9999999987 (after
adjustment for the n^3 factor) and an element that was 0 before
becomes -1.27e-8 than that's absolutely normal. Only if e.g.
elements that started off with 1 remain more or less 1 but
elements that were 0 to begin with become e.g. -0.7 then that
really would be something to worry about. In that case (and
after you made sure that you got everything else right) you
probably should consider talking to the guys that developed
that library, their email address is (e-mail address removed). If you
do so better send them a complete, compilable program plus
the data you were using.
Regards, Jens
 
B

brrk

brrk said:
I'm trying to use FFTW to compute fast summations, and I've run into
an issue:

<Re-indented to improve readbility>




int numFreq3 = numFreq*numFreq*numFreq;
FFTW_complex* dummy_sq_fft =
         (FFTW_complex*)FFTW_malloc( sizeof(FFTW_complex)*numFreq3 );
FFTW_complex* dummy_sq =
         (FFTW_complex*)FFTW_malloc( sizeof(FFTW_complex)*numFreq3 );
FFTW_complex* orig =
         (FFTW_complex*)FFTW_malloc( sizeof(FFTW_complex)*numFreq3 );
FFTW_plan dummyPlan =
    FFTW_plan_dft_3d( numFreq, numFreq, numFreq,
                      orig, dummy_sq_fft, FFTW_FORWARD, FFTW_MEASURE );
FFTW_plan dummyInvPlan =
    FFTW_plan_dft_3d( numFreq, numFreq, numFreq,
                      dummy_sq_fft, dummy_sq, FFTW_BACKWARD, FFTW_MEASURE );
for (int i= 0; i < numFreq3; i++) {
    orig[ i ][ 0 ] = sparseProfile02[ 0 ][ i ][ 0 ];
    //img. part == 0
    orig[ i ][ 1 ] = sparseProfile02[ 0 ][ i ] [ 1 ];
}
FFTW_execute(dummyPlan);
FFTW_execute(dummyInvPlan);
int count = 0;
for (int i=0; i<numFreq3; i++) {
    double factor;
    if (sparseProfile02[ 0 ] [ i ] [ 0 ])
        factor = dummy_sq[ i ][ 0 ]/sparseProfile02[ 0 ][ i ][ 0 ];
    else
        factor = dummy_sq[ i ][ 0 ];
    if (factor < 0) {
        count++;
    }
}
std::cout<<"Count "<<count<<"\n";
FFTW_free(dummy_sq_fft);
FFTW_free(dummy_sq);
FFTW_destroy_plan(dummyPlan);
FFTW_destroy_plan(dummyInvPlan);
(Here sparseProfile02[0] is of type FFTW_complex*, and contains only
positive real data.)
Since we have dummy_sq = IFFT(FFT(sparseProfile02[ 0 ])), we must have
dummy_sq = n^3*sparseProfile02. But this is true only some of the
time; in fact, values on the dummy_sq grid are negative whenever
corresponding values on the sparseProfile02 grid are zero (but not
vice-versa). Does anyone know why this is happening?

This is C++, I hope you realize (and this is comp.lang.c, not
comp.lang.c++). And it's about the result of some library, that
might be written in C but maybe not), not about the C language.

But what do you expect? That you get back the exact same values
you started with after some rather complex computations? That's
not how it works - computations with floating point values in-
troduce rounding errors and what you see here might be just a
result of that. How far off are the elements that were 0 at the
start compared to the deviations for elements that were non-
zero? If for example an element that was 1 before the forward
and backward transformation becomes maybe 0.9999999987 (after
adjustment for the n^3 factor) and an element that was 0 before
becomes -1.27e-8 than that's absolutely normal. Only if e.g.
elements that started off with 1 remain more or less 1 but
elements that were 0 to begin with become e.g. -0.7 then that
really would be something to worry about. In that case (and
after you made sure that you got everything else right) you
probably should consider talking to the guys that developed
that library, their email address is (e-mail address removed). If you
do so better send them a complete, compilable program plus
the data you were using.
                              Regards, Jens


I agree that std::cout is actually c++, but as FFTW, the library in
question, is written in C, I thought I was better off posting to this
group. I apologize if I was off-topic.

In any case, the errors are too large to be ascribed to floating-point
computations alone. For example, when the input value is zero, the
output value is sometimes -256 and sometimes -345. There's definitely
a major problem here; I just wanted to know if it was an obvious one.

I'll take Jens's recommendation and email the guys at fftw.

thanks for your time,
rk
 
M

Malcolm McLean

I'm trying to use FFTW to compute fast summations, and I've run into
an issue:
I can tell ypu how to solve this type of problem generally.

1) Make sure your FFTW library is working in general. eg calculate a
forwards transformation and its inverse, in 1d. Are the results what
you expect. Move to 2d, then to 3d. Is the transform working as you
would expect on small datasets and does it scale up to large datasets.

2) Now try a trivial sum using your mathod. Do you get the right
answer?

If no, what's the simplest example that will produce the wrong answer?
If yes, do you still get the wrong answer on the test data? Can you
identify what is different about the test data that triggers the
error?

Usually this will lead you to the result, either uncover a bug in your
own code or, less likely, tell you unambigiously that the transform is
producing the wrong / insufficiently accurate result.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top