1
votes

In order to increase the accuracy, I have been trying to upgrade a program from double to long double. However, I got the following error.

haread.cpp:178:43: error: no match for ‘operator*’ in ‘2.0e+0 * std::operator+ [with _Tp = long double](((((const std::complex)KEp) + ((long unsigned int)(((long unsigned int)i) * 32ul)))), ((const std::complex)(& energia)

The line was

phicheb[1][i] = (2.0*(KEp[i] + energia)/dE)-phistate[is][i] ;

The arrays were dynamically defines using 'new'. All the variables are long double. The problem was obtained for all the cases when some number is multiplying the complex array. So, I changed 2.0 to 2.0L and all the similar cases. So, now the compilation is successful. However, my program does not work properly anymore. Do I need to suffix L all the long doubles that I have defined? I have defined them as follows:

long double xmin = 1.6 ; long double xmax = 7.0 ;

I am not even sure from where to start. Any suggestions? The compiler is gcc version 4.6.2 (SUSE Linux). EDIT:

for ( int is = 0 ; is < nstates ; is++ ){
        for ( int i = 0 ; i < xgrid ; i++ ) phi[i] = phistate[is][i];
        fft(&phi[0], &kphi[0], -1);
        for ( int i = 0 ; i < xgrid ; i++ ){
                kphi[i] = akx2[i]*kphi[i]*ixgrid; //calculates the KE using Fourier transform
        }
        fft(&kphi[0],&KEp[0],1);
        for ( int i = 0 ; i < xgrid ; i++ ){
                x = xmin + (i*dx) ;
                energia = complex<long double>(0.0,0.0);
                energia = hmatrix[is][is][i]*phistate[is][i] ; //Potential energy
                phicheb[0][i] = phistate[is][i];
                phicheb[1][i] = (2.0L*(KEp[i] + energia)/dE)-phistate[is][i] ;
        }
        for ( int j = 2 ; j < ncheb ; j++ ){ //this is a recursion relation
                for ( int i = 0 ; i < xgrid ; i++ ) phi[i] = phicheb[j-1][i];
                fft(&phi[0], &kphi[0], -1);
                for ( int i = 0 ; i < xgrid ; i++ ){
                        kphi[i] = akx2[i]*kphi[i]*ixgrid;
                }
                fft(&kphi[0],&KEp[0],1) ;
                for ( int i = 0 ; i < xgrid ; i++ ){
                        x = xmin + (i*dx) ;
                        energia = complex<long double>(0.0,0.0);
                        energia = hmatrix[is][is][i]*phi[i];
                        phicheb[j][i] = (2.0L*((2.0L*(KEp[i] + energia)/dE) - phicheb[j-1][i])) - phicheb[j-2][i]; //recursion
                }
        }
        for ( int i = 0 ; i < xgrid ; i++){
                for ( int j = 0 ; j < ncheb ; j++ ){
                        phistate_new[is][i] += chebc[j]*phicheb[j][i] ;
                }
        }
}

This is the core of the code. It is used for the propagation of wavefuction on a grid. I will try to explain the code as less technical as possible. I have the values of phistate[0][i], which is the wavefunction corresponding to a ground state (the rest of the states are all zero). Then I calculate the energy of the system (the Kinetic Energy using Fourier transform and the Potential Energy is already given). Now, using a particular method (the Chebychev method), I propagate the wavefunction in time. This method is based on a recursion relation. In this recursion, the propagation is calculated using a polynomial expansion. Chebc are long double coefficients, the values of which are well defined. All the variables whose definition are not shown, are long double.

When I use just double instead of long double, I have no problem getting results. When using long double, phistate_new, my result, has all it's values given by NaN.

1
Provide a minimal, compilable code that reproduces the problem? - coyotte508
Could you be more specific than "does not work properly"? - molbdnilo
I am sorry for being vague. But the main problem is that the phistate 2d array givens NaN. The core of the code is little bit complicated. I am trying to shorten it. I also have to use fftw3. However, I cannot compile with -lfftw3l. Could that be the problem? - Population Xplosive
long double and double can be the same accuracy. I would check they are different in your compiler first. - Neil Kirk
Debug your code yourself. You could track where the NaN or Inf first appear (if need be using print outs or asserts). - Walter

1 Answers

2
votes

Well, yes, a literal value of type long double needs to have an L postfix. So use 2.0L rather than 2.0 (of type double) or 2.0f (of type float).

However, from the error message, your claim that all variables are long double is false.

At least one of the variables is of type std::complex<long double> and the error message indicates that an operation involving one or more of your variables does not exist.

That means you're not understanding what the code does. Which means there will be more to getting it working correctly than changing all things of type double to long double, and fixing type of literal values.

It is not possible to provide more specific advice, as you have not provided enough information. In particular, you would need to supply a small and complete sample of code that illustrates your problem(s).