Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Using user defined type in Fortan 77 subroutines

5 views
Skip to first unread message

Hifi-Comp

unread,
Sep 15, 2009, 4:53:28 PM9/15/09
to
A Fortran program is mainly written using F90/95. However a few pieces
of codes are written using F77 in separte files. I want to use user
defined type data in F77 codes. Using Compaq Visual Fortran IDE on a
PC, I just need to add all the files into the project, and add use the
module where the user defined type defined right after subroutine or
function statements. The code compiles nicely and does what is
supposed to. However, when I use gfortran in Linux system, I don't
know how to achieve this. I hope I just need to add a few flags for
compiling instead of wrapping f77 codes with F90/95 trickes such as
put them into a module. Thanks in advance for your help!

Richard Maine

unread,
Sep 15, 2009, 5:12:28 PM9/15/09
to
Hifi-Comp <wenbiny...@gmail.com> wrote:

I'm a little confused as to what you are talking about. First, let us be
clear, that your "F77" codes are not f77 codes if you have USE
statements and derived types in them; not even close. Period. Not even
by the most sloppy of definitions. There are some f90 features that are
also common as extensions in f77 compilers and thus might plausibly stil
be considered as variations on f77. But not USE and derived types. That
would make them f90/f95 codes.

Almost all f77 codes are also already valid f90/f95 codes. The
exceptions in the standard are obscure enough not to likely be at issue.
After you add USE statements and derived types in them, they loose all
pretext of being anything like f77 codes.

I can't tell from the post what you are having problems with.

1. It almost sounds like perhaps you don't know how to compile a program
with gfortran at all, independent of any f77 vs f90 issues. I can't tell
for sure, but I almost see a hint of that.

2. The allegedly f77 code might not actually be f77, but rather f77 plus
a lot of nonstandard features. If that's the case, then *MUCH* more
detail is needed (and you might be all but out of luck depending on the
particular features in question).

3. You might be mistakenly equating f77 with fixed source form. If so,
that one is easy.

But I can't see trying to answer all possible variants of all of the
above questions. I think more detail is needed on what you are talking
about, what you have tried, and what happened when you tried it.

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain

Hifi-Comp

unread,
Sep 15, 2009, 9:04:13 PM9/15/09
to
On Sep 15, 5:12 pm, nos...@see.signature (Richard Maine) wrote:


Thanks a lot for your quick response. I suspect it might because I
don't know how to use gfortran. I basically only knows gfortran -c
inputfile and gfortran -o *.o to generate an executable. By F77 codes,
I mean the original code is F77, I replaced the declaration of real
numbers with my derived type. All the other codes remain the same.

Having said that, I am providing more details. Supposing I have two
files: DNAD.f90, blas.for, as follows:

blas.for
TYPE (DN) FUNCTION DDOT(N,DX,INCX,DY,
+INCY)
USE TEST
C
C FORMS THE DOT PRODUCT OF TWO VECTORS.
C USES UNROLLED LOOPS FOR INCREMENTS EQUAL TO ONE.
C JACK DONGARRA, LINPACK, 3/11/78.
C
TYPE (DN) DX(*),DY(*),DTEMP
INTEGER I,INCX,INCY,IX,IY,M,MP1,N
60 DDOT = DTEMP
RETURN
END

DNAD.f90
MODULE TEST
TYPE,PUBLIC:: DN
REAL(8)::x
REAL(8)::xp
END TYPE DN
END MODULE TEST


Using CVF IDE on a PC, I can simply create a project containing these
two files. Both files can be compiled without any problem. Howeve, to


use gfortran in Linux system,

I do the following
gfortran -c DNAD.f90
DNAD.o and test.mod are generated.

Hower, when I compile blas.for using

gfortran -c blas.for

I got the following error messages:
In file blas.for:9

TYPE (DN) DX(*),DY(*),DTEMP
1
Error: Type name 'dn' at (1) is ambiguous
In file blas.for:11

60 DDOT = DTEMP
1
Error: Derived type 'dn' at (1) is being used before it is defined
In file blas.for:1

TYPE (DN) FUNCTION DDOT(N,DX,INCX,DY,
1
Error: The derived type 'ddot' at (1) is of type 'dn', which has not
been defined.

Jim Xia

unread,
Sep 15, 2009, 9:24:50 PM9/15/09
to

> I got the following error messages:
> In file blas.for:9
>
>       TYPE (DN) DX(*),DY(*),DTEMP
>               1
> Error: Type name 'dn' at (1) is ambiguous
>  In file blas.for:11
>
>    60 DDOT = DTEMP
>          1
> Error: Derived type 'dn' at (1) is being used before it is defined
>  In file blas.for:1
>
>       TYPE (DN) FUNCTION DDOT(N,DX,INCX,DY,
>                             1
> Error: The derived type 'ddot' at (1) is of type 'dn', which has not
> been defined.- Hide quoted text -
>

It seems a prefix issue. The source code is not strictly conforming
to the standard, but there are compiler accept this. Guess gfortran
does not

Try the following

FUNCTION DDOT(N,DX,INCX,DY,
+INCY)
USE TEST

TYPE (DN) DDOT
C
...


Cheers,

Jim

Steve Lionel

unread,
Sep 15, 2009, 9:28:50 PM9/15/09
to
Hifi-Comp wrote:

> Hower, when I compile blas.for using
>
> gfortran -c blas.for
>
> I got the following error messages:
> In file blas.for:9
>
> TYPE (DN) DX(*),DY(*),DTEMP
> 1
> Error: Type name 'dn' at (1) is ambiguous
> In file blas.for:11

Try replacing this:

TYPE (DN) FUNCTION DDOT(N,DX,INCX,DY,
+INCY)
USE TEST

with this:

FUNCTION DDOT(N,DX,INCX,DY,
+INCY)
USE TEST

TYPE(DN) DDOT

gfortran (perhaps an old version?) evidently has trouble with the first
form.
--
Steve Lionel
Developer Products Division
Intel Corporation
Nashua, NH

For email address, replace "invalid" with "com"

User communities for Intel Software Development Products
http://software.intel.com/en-us/forums/
Intel Software Development Products Support
http://software.intel.com/sites/support/
My Fortran blog
http://www.intel.com/software/drfortran

Richard Maine

unread,
Sep 15, 2009, 9:39:41 PM9/15/09
to
Hifi-Comp <wenbiny...@gmail.com> wrote:

Doesn't look to me like this has anything at all to do with f77-related
issues, or for that matter with how you do the compilation. No wonder I
couldn't figure out what you were asking about. This is simply failure
of the code to compile and has nothing to do with it being originally
f77 or with any of the other issues that you mentioned.

Looks to me like the main problem is that you use the type DN prior to
the USE statement that makes it available. Apparently the CVF compiler
allows this, but gfortran does not.

To tell the truth, I forget whether the standard allows this case or
not. If it does allow it, then you have a bug report against gfortran.
I'll allow others to figure out whether or not such a bug report is
needed.

But my recommendation, regardless of whether the standard allows the
practice, is not to do it. It just asks for problems. If the standard
does allow it, then it is as a special-case exception to the general
rule. I know there are at least some such special-case exceptions, but I
have never bothered to memorize what cases they cover and what cases
they omit. I find it preferable to avoid their use.

Instead, I recommend taking the TYPE(DN) off of the function statement.
Replace it with a type declaration statement (after the USE) as in

type(dn) :: ddot

As I said, I don't recall whether the standard says that your original
code should work, but this change is "safer" anyway.

P.S. This is about example 42 billion of probably the most universal
advice on posting problem reports here. Don't try to describe the
problem. Odds are the description will be wrong anyway. Instead, show us
the problem. There is simply no way anyone could have figured this out
from the description in the original post. Some of us do occasionally
get flashes of vision in our crystal balls, but I don't think anyone has
a crystal ball that would have been up to that.

I'm not 100% sure that we have the problem completely solved yet. Some
of those error messages slightly puzzled me, but I'm hoping that they
were just fallout from the issue that I do see. In any case, I think we
can make progress from here.

Hifi-Comp

unread,
Sep 15, 2009, 9:51:46 PM9/15/09
to
On Sep 15, 9:28 pm, Steve Lionel <steve.lio...@intel.invalid> wrote:
> Hifi-Comp wrote:
> > Hower, when I compile blas.for using
>
> > gfortran -c blas.for
>
> > I got the following error messages:
> > In file blas.for:9
>
> >       TYPE (DN) DX(*),DY(*),DTEMP
> >               1
> > Error: Type name 'dn' at (1) is ambiguous
> >  In file blas.for:11
>
> Try replacing this:
>
>     TYPE (DN) FUNCTION DDOT(N,DX,INCX,DY,
>       +INCY)
>         USE TEST
>
> with this:
>
>     FUNCTION DDOT(N,DX,INCX,DY,
>       +INCY)
>         USE TEST
>          TYPE(DN) DDOT
>
> gfortran (perhaps an old version?) evidently has trouble with the first
> form.

Is there a newer version of gfortran can deal with the first form? Two
gfortran compilers I tried one different linux machines have the same
problem.

Hifi-Comp

unread,
Sep 15, 2009, 10:05:22 PM9/15/09
to
On Sep 15, 9:39 pm, nos...@see.signature (Richard Maine) wrote:
> domain: summertriangle           |  -- Mark Twain- Hide quoted text -
>
> - Show quoted text -

Thanks a lot. I will remember later to show the problem instead of
descriping the problem. The suggested change works. However, my
intention is to overload existing codes to perform calculation in a
new data structure. I need to minimize the changes to existing codes.

It seems
REAL(8) FUNCTION DDOT(....)
is perfect alright with gfortran. I don't understand why derived data
becomes unsafe for such statement.

Richard Maine

unread,
Sep 15, 2009, 10:20:54 PM9/15/09
to
Hifi-Comp <wenbiny...@gmail.com> wrote:

> It seems
> REAL(8) FUNCTION DDOT(....)
> is perfect alright with gfortran. I don't understand why derived data
> becomes unsafe for such statement.

Because the derived type isn;t defined until later (when the compiler
sees the USE statement), while the compiler knows about real(8) all
along. For most purposes, you can't can't use a type until after its
definition; this is an exception.

I just checked, and the standard does alow it, so a bug report seems
appropriate. But I still think it dangerous.

Jim Xia

unread,
Sep 15, 2009, 10:21:04 PM9/15/09
to
> Thanks a lot. I will remember later to show the problem instead of
> descriping the problem. The suggested change works. However, my
> intention is to overload existing codes to perform calculation in a
> new data structure. I need to minimize the changes to existing codes.
>
> It seems
> REAL(8) FUNCTION DDOT(....)
> is perfect alright with gfortran. I don't understand why derived data
> becomes unsafe for such statement.- Hide quoted text -

The intrinsic data types are language "built-in" types, and they're
understood everywhere. User defined types are not. Function prefix
was and still is a gray area that can trick compilers into trouble.
For entities that haven't been seen, it's usually hard enough to know
what data type or how to evaluate the expression. I was asked to
interp this example not very long ago


integer n
n = 30

print *, string(10)

contains

character(n) function string(n)
integer, intent(in) :: n

string = 'what value should it have'
end function
end

The program looks illegal to me and it chocked on a few compilers, and
others that compiles it interp the results differently. But I have
trouble to pin-pointing exactly where the standard says this is
illegal :-(

So I'd echo what Richard has advised: avoid this. It wouldn't be long
before you'll find yourself in trouble.

Cheers,

Jim

Hifi-Comp

unread,
Sep 15, 2009, 10:27:56 PM9/15/09
to

Jim,

Are you saying that even for intrinic types, it is better to define
the type of the function after the FUNCTION statement? Or using the
RESULT keyword. Thanks.

Hifi-Comp

unread,
Sep 15, 2009, 10:39:35 PM9/15/09
to
> RESULT keyword. Thanks.- Hide quoted text -

>
> - Show quoted text -

If I wrap these functions with
Module IsolatedRoutines
USE TEST

CONTAINS


TYPE (DN) FUNCTION DDOT(N,DX,INCX,DY,
+INCY)

....
END Module

we should be able to avoid the danger, right? This way, I can dump all
the functions/subroutines not contained in a module into a module and
insert use IsolatedRoutines in other units which might call these
functions/subroutines. Will any side effects be generated by doing
this?

Jim Xia

unread,
Sep 15, 2009, 10:59:51 PM9/15/09
to

>
> >   integer n
> >   n = 30
>
> >   print *, string(10)
>
> >   contains
>
> >   character(n) function string(n)
> >      integer, intent(in) :: n
>
> >      string = 'what value should it have'
> >   end function
> >   end
>
> > The program looks illegal to me and it chocked on a few compilers, and
> > others that compiles it interp the results differently.  But I have
> > trouble to pin-pointing exactly where the standard says this is
> > illegal :-(
>
> > So I'd echo what Richard has advised: avoid this.  It wouldn't be long
> > before you'll find yourself in trouble.
>
> > Cheers,
>
> > Jim
>
> Jim,
>
> Are you saying that even for intrinic types, it is better to define
> the type of the function after the FUNCTION statement? Or using the
> RESULT keyword. Thanks.- Hide quoted text -


I'd recommend to put the type declarations after the FUNCTION
statement EVEN for intrinsic types. This can be done regardless of
using RESULT keyword. For recursive functions, RESULT is recommended
because you may have to (ask if you don't know :-). The following
examples are some what I've encountered and as you can see some of
them are really challenging (to anyone)


1.) declare function results in multiple statements. I found them not
readable

integer function foo (...)
allocatable foo (:,:)

or more suprising

real function foo (n, ...)
integer, intent(in) :: n
dimension (n) foo


2.) refers to data components before the declaration is brought into
scope. This is very challenging to compilers. Don't just take my
words, try it on different compilers to see what you'll get :-). For
a twister, declare t%len as allocatable or pointer.

character(t%len) function foo (t) !<-- t is a derived type with a
component len to store the length of a string
type(x), intent(in) :: t

3.) Most wonderful stuff. The length type parameters of a dummy

character(str%len) function foo (str)
character(*), intent(in) :: str

For even more fun, try this

character (str%len) function foo (str)
type(X(*)), intent(in) :: str !<-- type X is a parameterized
derived type with a length type parameter len. Here its value is
assumed


4.) deferred length type parameter used in the prefix. This is
actually OK to me since it tells me the function must either be
allocatable or pointer. I don't claim this as not readable, but that
could just be me.

character(:) function foo (...)
allocatable foo


There are still more I can think of. But the examples are enough to
deter most users from trying. -- I hope.

Cheers,

Jim

James Van Buskirk

unread,
Sep 16, 2009, 12:59:55 AM9/16/09
to
"Hifi-Comp" <wenbiny...@gmail.com> wrote in message
news:b0f12239-fc57-4e4c...@g6g2000vbr.googlegroups.com...

> If I wrap these functions with
> Module IsolatedRoutines
> USE TEST

> CONTAINS
> TYPE (DN) FUNCTION DDOT(N,DX,INCX,DY,
> +INCY)
> ....
> END Module

> we should be able to avoid the danger, right? This way, I can dump all
> the functions/subroutines not contained in a module into a module and
> insert use IsolatedRoutines in other units which might call these
> functions/subroutines. Will any side effects be generated by doing
> this?

You might be better off with template functions. I have a couple of
starting points:

http://home.comcast.net/~kmbtib/Fortran_stuff/GENERIC_BLAS.ZIP

is an example of how to make a generic version of BLAS. It has two
problems: invocation via sequence association doesn't work for
generics in Fortran (so you can't do that) and it doesn't help you
in the case where you have TYPE(DN) rather than a KIND of REAL.
You can fix this by declaring the variable or function result
implicitly. That way it can pick up its type from the module it
is defined in. I thought I had an example of this on my website
somewhere, but I can't see it.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


Richard Maine

unread,
Sep 16, 2009, 2:25:14 AM9/16/09
to
Hifi-Comp <wenbiny...@gmail.com> wrote:

> Are you saying that even for intrinic types, it is better to define
> the type of the function after the FUNCTION statement? Or using the
> RESULT keyword.

That's what I think. I like the consistency of declaring the type in a
separate type declaration statement. You can always do that. The
function statement is just too early in the scoping unit (by definition,
it is always the first statement), which leads to problems.

For example, although your derived-type case is standard conforming, the
following case, which uses only intrinsic types is not. It doesn't have
the same kind of special-case exception as your derived-type one does

module precision
integer, parameter :: dp = selected_real_kind(12)
end module precision

real(dp) function foo(x)
use precision
....

Tobias Burnus

unread,
Sep 16, 2009, 3:30:01 AM9/16/09
to
On 16 Sep., 04:20, nos...@see.signature (Richard Maine) wrote:
> I just checked, and the standard does alow it, so a bug report seems
> appropriate. But I still think it dangerous.

I do not think that it would be appropriate ... It works at least with
GCC/gfortran 4.3.x, 4.4.x and 4.5(experimental), which are the only
supported GCC versions.

There are several possibilities: (a) get a newer Linux, (b) find newer
pre-build GCC packages for your Linux distribution, (c) download the
following GCC 4.5 build, (d) compile the source yourself (or ask
someone to do it for you).

Regarding option (c): Have a look at http://gcc.gnu.org/wiki/GFortranBinaries

Tobias

Hifi-Comp

unread,
Sep 16, 2009, 7:07:22 AM9/16/09
to

Thanks. I just downloaded the •mingw build (2009-04-21) for windows.
It has no complains for
TYPE (DN) DDOT(....)
I will ask my system administrator for the linux servers to install a
newer version of gfortran.

Richard Maine

unread,
Sep 16, 2009, 10:52:20 AM9/16/09
to
Tobias Burnus <bur...@net-b.de> wrote:

> On 16 Sep., 04:20, nos...@see.signature (Richard Maine) wrote:
> > I just checked, and the standard does alow it, so a bug report seems
> > appropriate. But I still think it dangerous.
>
> I do not think that it would be appropriate ... It works at least with
> GCC/gfortran 4.3.x, 4.4.x and 4.5(experimental), which are the only
> supported GCC versions.

Ah. I hadn't realized this was all based on old versions; I don't recall
that having been mentioned. Thanks.

James Van Buskirk

unread,
Sep 16, 2009, 10:56:49 AM9/16/09
to
"Richard Maine" <nos...@see.signature> wrote in message
news:1j63xn9.1378sbv19dnesmN%nos...@see.signature...

> That's what I think. I like the consistency of declaring the type in a
> separate type declaration statement. You can always do that. The
> function statement is just too early in the scoping unit (by definition,
> it is always the first statement), which leads to problems.

> For example, although your derived-type case is standard conforming, the
> following case, which uses only intrinsic types is not. It doesn't have
> the same kind of special-case exception as your derived-type one does

> module precision
> integer, parameter :: dp = selected_real_kind(12)
> end module precision

> real(dp) function foo(x)
> use precision
> ....

But

function foo(x)
use precision
implicit real(dp) (f)
...

is OK :)

An issue I have is that you might want to write an interface block
such as

interface
function GetLastError() &
bind(C,name=trim( &
merge('GetLastError ', &
'_GetLastError@0', &
bit_size(0_c_intptr_t) == 64)))
use ISO_C_BINDING
implicit none
integer(c_int32_t) GetLastError
end function GetLastError
end interface

Since it is alleged that you can't put the bind(C) clause in the
specification part of the function, you have to diddle the binding
name right up there at the top. Does the binding name have access
to the specification part of the function, or is this an
insurmountable problem?

Craig Powers

unread,
Sep 16, 2009, 1:53:05 PM9/16/09
to
Hifi-Comp wrote:
>
> Is there a newer version of gfortran can deal with the first form? Two
> gfortran compilers I tried one different linux machines have the same
> problem.

Most likely there is a newer version of gfortran (which I would imagine
would handle the first form, but I don't know for a certainty); I
believe most linuces distribute gfortran 4.1 as the default version.
The current release is 4.4, the development version is 4.5. You can
check the version using 'gfortran -v'.

Craig Powers

unread,
Sep 16, 2009, 1:55:07 PM9/16/09
to
Richard Maine wrote:
> Tobias Burnus <bur...@net-b.de> wrote:
>
>> On 16 Sep., 04:20, nos...@see.signature (Richard Maine) wrote:
>>> I just checked, and the standard does alow it, so a bug report seems
>>> appropriate. But I still think it dangerous.
>> I do not think that it would be appropriate ... It works at least with
>> GCC/gfortran 4.3.x, 4.4.x and 4.5(experimental), which are the only
>> supported GCC versions.
>
> Ah. I hadn't realized this was all based on old versions; I don't recall
> that having been mentioned. Thanks.

It's natural to assume someone is using an old version of gfortran
absent specific information to the contrary. There are a lot of linuces
that distribute version 4.1, I don't know offhand which (if any)
distribute any newer version.

0 new messages