LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   A compile time error in GFortran I don't understand (https://www.linuxquestions.org/questions/linux-newbie-8/a-compile-time-error-in-gfortran-i-dont-understand-4175527637/)

AlexBB 12-07-2014 08:02 PM

A compile time error in GFortran I don't understand
 
It is a Ubuntu VM. I am trying to use a Fast Fourier Transform module given here. I get an error which is in this code block:

Code:

!    COMPUTE THE TRANSFORM
!    ---------------------
i = 1
IF (ip > 0) THEN
  CALL gpfa2f(a, b, trigs, inc, jump, n, ip, lot, ISIGN)
  i = i + 2 * ( 2**ip)
END IF
IF (iq > 0) THEN
  CALL gpfa3f(a, b, trigs(i), inc, jump, n, iq, lot, ISIGN)
  i = i + 2 * (3**iq)
END IF
IF (ir > 0) THEN
  CALL gpfa5f(a, b, trigs(i), inc, jump, n, ir, lot, ISIGN)
END IF

The second call gpfa3f is actually the line #201. I get this error:

Quote:

four3.f08:201.20:

CALL gpfa3f(a, b, trigs(i), inc, jump, n, iq, lot, ISIGN)
1
Error: Element of assumed-shaped or pointer array passed to array dummy argument 'trigs' at (1)
four3.f08:205.20:

CALL gpfa5f(a, b, trigs(i), inc, jump, n, ir, lot, ISIGN)
1
Error: Element of assumed-shaped or pointer array passed to array dummy argument 'trigs' at (1)
The file name is four3.f08.

Could anybody explain what is wrong? Thanks, - A.

John VV 12-07-2014 10:04 PM

i tend to use a fair amount of old code

so the first is that this f90 is from 2002
so i would expect a issue with the current gfortran 4.8 or 4.9


now the legacy gcc33 or 34 has g77

i would first see if it builds using the gfortran from gcc 4.0 or 4.1


getting 12 year old code to build on modern 64 bit hardware in a modern OS is -- lets just say " fun"

you will want to use the 32 bit compiler and build a 32 bit program

knudfl 12-08-2014 04:32 AM

64bits g77 for Ubuntu 12* and later :

compat-gcc34-g77-3.4.6-ubuntu12-1_amd64.deb
https://drive.google.com/file/d/0B7S...ew?usp=sharing

Depends on compat-gcc34-3.4.6-ubuntu1204-1_amd64.deb
https://drive.google.com/file/d/0B7S...ew?usp=sharing

And compat-libf2c-3.4.6-ubuntu12-2_amd64.deb
https://drive.google.com/file/d/0B7S...ew?usp=sharing

-

Toadbrooks 12-08-2014 09:49 AM

Quote:

Originally Posted by AlexBB (Post 5281116)
Code:

!    COMPUTE THE TRANSFORM
!    ---------------------
i = 1
IF (ip > 0) THEN
  CALL gpfa2f(a, b, trigs, inc, jump, n, ip, lot, ISIGN)
  i = i + 2 * ( 2**ip)
END IF
IF (iq > 0) THEN
  CALL gpfa3f(a, b, trigs(i), inc, jump, n, iq, lot, ISIGN)
  i = i + 2 * (3**iq)
END IF
IF (ir > 0) THEN
  CALL gpfa5f(a, b, trigs(i), inc, jump, n, ir, lot, ISIGN)
END IF


First, I have no experience with GFORTRAN, and it looks nothing like the fortran I used back in the '70s. But one thing that sticks out the me is the variables in the calls. In the first, you are passing 'trigs' which is apparently an array, and passed by pointer to an array. In the second two calls, you are passing an element from the array 'trigs', which would be passed as the value itself rather than as a pointer to a cell.

Of course, they are different functions, and your calls could be correct. But that's where I would start, confirming the type of each of the variables in the calls.

AlexBB 12-08-2014 03:55 PM

I will try to answer a couple of issues raised here. First, it is a 32 bit Ubuntu. For some reason I could not install a 64 bit on my 64 bit machine, now I don't recall why. Secondly, answering Toadbrooks: it is not my code. I provided a link to the source code I copied exactly. I also noticed that an array is passed in the first call and an array's member, a number, is passed in the second two calls. I deliberately included the first call for comparison. Still I don't have a good answer. I kind of afraid to change the code but perhaps I will have to. Thanks.

suicidaleggroll 12-08-2014 04:36 PM

That's just a block of subroutines. What does your driver look like? How have you declared trigs?

AlexBB 12-08-2014 09:24 PM

What do you mean driver? I drive myself to work, :-) Just kidding. I posted a link to that software. I copied the whole package faithfully but I cannot answer any questions, because I do not understand that part of the code, I do not understand the error message. Thanks, suicidaleggroll.

Toadbrooks 12-08-2014 10:20 PM

Alex, your code or not, you are going to have to look for the definition of the 3 CALLed procedures. There should be a type definition somewhere near the top of the code for each of those routines. That will help you determine if what you are passing is the correct type or not, especially given that is what the error message seems to mean to me.

If you can't, you can't. But I can't offer much more help than that.

MANY years ago, I came across an Integer Programming model in Fortran. I wanted it, but all I had in 1978 was a machine that spoke BASIC. I managed to convert it from Fortran to Basic, and got it working. Took weeks and I couldn't have done it if I wasn't skilled in both languages. You may be attempting the impossible. (Which doesn't mean you shouldn't try, but the point at which you can't determine the type of the variables you are passing versus the type the routines require might be as far as you will get.)

suicidaleggroll 12-09-2014 09:18 AM

Quote:

Originally Posted by AlexBB (Post 5281685)
What do you mean driver? I drive myself to work, :-) Just kidding. I posted a link to that software. I copied the whole package faithfully but I cannot answer any questions, because I do not understand that part of the code, I do not understand the error message. Thanks, suicidaleggroll.

I thought you had a full program that was calling one or more of these subroutines, in which case you would have needed to define trigs in that driver.

However, I see now you're just trying to compile the module by itself. In that case, it looks like an error in the code. I REALLY don't like the way this is written. They're passing a single element of the array into the function, and then accessing it as if the entire array was passed in.

Code:

CALL gpfa3f(a, b, trigs(i), inc, jump, n, iq, lot, ISIGN)
and then gpfa3f:
Code:

SUBROUTINE gpfa3f(a, b, trigs, inc, jump, n, mm, lot, ISIGN)
...
REAL (dp), INTENT(IN)      :: trigs(*)
...
DO  k = ink, jstep-ink, ink
      co1 = trigs(kk+1)
      ...
      kk = kk + 2*la
END DO

Just because fortran is pass by reference, that doesn't mean you can treat EVERYTHING as a pointer.

I deal a lot with fortran, and I've seen a lot of really bad code, but I've never seen somebody do this. I would start by modifying the call and declaration for gpfa3f and gpfa5f. Pass "i" in as a separate parameter, so the call would look like:
Code:

CALL gpfa3f(a, b, trigs, i, inc, jump, n, mm, log, ISIGN)
And the function declaration would look like:
Code:

SUBROUTINE gpfa3f(a, b, trigs, trigidx, inc, jump, n, mm, lot, ISIGN)
Then change the declaration of trigs in gpfa3f and gpfa5f from:
Code:

REAL (dp), INTENT(IN)      :: trigs(*)
to:
Code:

REAL (dp), INTENT(IN)      :: trigs(:)
to match the other subroutines getting the full copy

and finally, every time trigs is accessed inside gpfa3f and gpfa5f, add trigidx (or whatever you want to call it) to the index, for example change this:
co1 = trigs(kk+1)
to this
co1 = trigs(trigidx+kk+1)

At least I assume that's what the original developer is intending to do.


Fortran is usually very portable, AS LONG AS people write it properly. I deal a lot with old code, and running something from 2002 on a modern compiler rarely takes much effort UNLESS the original developer took a bunch of shortcuts and assumptions. For example, I have one HUGE code that can't be built using any compiler more recent than 2005 because they did crap like this all of the place:
Code:

real :: a(50), b(50)
do i=1,100
  a(i) = 0
enddo

purposefully overflowing a with the assumption that a and b will be contiguous in memory and it will overflow into b, instead of just doing it properly:
Code:

real :: a(50), b(50)
do i=1,50
  a(i) = 0
  b(i) = 0
enddo

or
Code:

real :: a(100)
do i=1,100
  a(i) = 0
enddo


AlexBB 12-09-2014 10:48 AM

Thank you both. It is quite a bit of specific information. I will start modifying the code tonight after work.

suicidaleggroll 12-09-2014 10:58 AM

Quote:

Originally Posted by Toadbrooks (Post 5281709)
Alex, your code or not, you are going to have to look for the definition of the 3 CALLed procedures. There should be a type definition somewhere near the top of the code for each of those routines. That will help you determine if what you are passing is the correct type or not, especially given that is what the error message seems to mean to me.

If you can't, you can't. But I can't offer much more help than that.

MANY years ago, I came across an Integer Programming model in Fortran. I wanted it, but all I had in 1978 was a machine that spoke BASIC. I managed to convert it from Fortran to Basic, and got it working. Took weeks and I couldn't have done it if I wasn't skilled in both languages. You may be attempting the impossible. (Which doesn't mean you shouldn't try, but the point at which you can't determine the type of the variables you are passing versus the type the routines require might be as far as you will get.)

The subroutine definitions are in the linked code:
Code:

SUBROUTINE gpfa(a, b, trigs, inc, jump, n, lot, ISIGN)

IMPLICIT NONE
REAL (dp), INTENT(IN OUT)  :: a(:)
REAL (dp), INTENT(IN OUT)  :: b(:)
REAL (dp), INTENT(IN)      :: trigs(:)
INTEGER, INTENT(IN)        :: inc
INTEGER, INTENT(IN)        :: jump
INTEGER, INTENT(IN)        :: n
INTEGER, INTENT(IN OUT)    :: lot
INTEGER, INTENT(IN)        :: ISIGN

Code:

SUBROUTINE gpfa2f(a, b, trigs, inc, jump, n, mm, lot, ISIGN)

IMPLICIT NONE
REAL (dp), INTENT(IN OUT)  :: a(*)
REAL (dp), INTENT(IN OUT)  :: b(*)
REAL (dp), INTENT(IN)      :: trigs(*)
INTEGER, INTENT(IN)        :: inc
INTEGER, INTENT(IN)        :: jump
INTEGER, INTENT(IN)        :: n
INTEGER, INTENT(IN)        :: mm
INTEGER, INTENT(IN)        :: lot
INTEGER, INTENT(IN)        :: ISIGN

Code:

SUBROUTINE gpfa3f(a, b, trigs, inc, jump, n, mm, lot, ISIGN)

REAL (dp), INTENT(IN OUT)  :: a(*)
REAL (dp), INTENT(IN OUT)  :: b(*)
REAL (dp), INTENT(IN)      :: trigs(*)
INTEGER, INTENT(IN)        :: inc
INTEGER, INTENT(IN)        :: jump
INTEGER, INTENT(IN)        :: n
INTEGER, INTENT(IN)        :: mm
INTEGER, INTENT(IN)        :: lot
INTEGER, INTENT(IN)        :: ISIGN

Code:

SUBROUTINE gpfa5f(a, b, trigs, inc, jump, n, mm, lot, ISIGN)
IMPLICIT NONE

REAL (dp), INTENT(IN OUT)  :: a(*)
REAL (dp), INTENT(IN OUT)  :: b(*)
REAL (dp), INTENT(IN)      :: trigs(*)
INTEGER, INTENT(IN)        :: inc
INTEGER, INTENT(IN)        :: jump
INTEGER, INTENT(IN)        :: n
INTEGER, INTENT(IN)        :: mm
INTEGER, INTENT(IN)        :: lot
INTEGER, INTENT(IN)        :: ISIGN


AlexBB 12-09-2014 08:28 PM

Thank you, everyone who helped. I marked all the posts as helpful and they really are. On a practical side, I simply removed the index (i) but did not pass it separately to the subroutines. I want to try it without doing it and should I run into trouble, hopefully, I can always do it later. Many thanks, - A.

suicidaleggroll 12-10-2014 09:40 AM

While I'm sure it compiles and runs now, I highly doubt the answers will be correct. You should be VERY suspicious of your results.

Toadbrooks 12-10-2014 07:02 PM

Quote:

Originally Posted by suicidaleggroll (Post 5282507)
While I'm sure it compiles and runs now, I highly doubt the answers will be correct. You should be VERY suspicious of your results.

VERY good point. If you have access to known results, I'd run them through as verification that you got it right.

AlexBB 12-11-2014 07:24 PM

With Fast Fourier Transform there is a simple way to verify if the process is correct. You do a reverse transform and if everything is proper, you should get approximately the original result.

suicidaleggroll 12-11-2014 08:21 PM

Unless the forward and reverse algorithms are corrupted in the same way. You should do an independent verification using another set of tools. Most languages have an FFT library of some kind, you could even write a quick C wrapper for fftw3, I've used it before and it's pretty straight forward. You could probably even use GDL or Octave (free "approximations" of IDL and Matlab respectively), or python, etc.

The only reason I'm harping on this so much is because I'm about 99% sure that your solution for the compilation problem will break the code. Not programatically, but mathematically. It seems to me that the original developer was probably a C programmer who was branching out into Fortran, and wrote those function calls like he would have in C, which means passing the memory location of the index in the array at which you want to start, and letting the function increment from there. Fortran doesn't work that way, at least not naturally. He probably kluged together some syntax that let his specific compiler behave as he wanted, but it was not ANSI, and of course breaks as soon as the compiler changes. The focus here isn't to get your compiler to build the code without complaint, it's to get your compiler to build the code in the way that the original developer intended, and simply removing the index offset in the function calls is almost certainly not the right answer.

AlexBB 12-13-2014 10:46 AM

Thank you for your intricate analysis. I am alert to all options, including to what you are saying. It is a huge task for me to wade through so much code with variants of FFT methods. Might take time but I will crack it. My task is even more complicated by the fact that I need to do 2-D transform and the other dimension is not FFT, although the variables are separatable. I truly value your contributions. Thanks, - A.


All times are GMT -5. The time now is 07:39 AM.