Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Type Declaration 1

Status
Not open for further replies.

fanta2

Technical User
Apr 10, 2005
78
CA
I have a problem I will explain it in simple terms. I have a subroutine (say) which can add two numbers. The two numbers are declared as real in the subroutine. But I want to use sometimes for real number and sometimes as integer. So I declared the actual argument as integer and VF compiler gives me a warning (conflicting argument declaration). I cann't declare the variable as real in the main program as it is very large and it takes a lot of space for computation. I thought I can write two times the subroutine once for integer and once for real and I call them depending upon the input ... but is this a good way to solve it or there is a better way? I appreciate your helps!
 
What about type conversion ?

real function add_real_numbers(a1,a2)
real a1,a2
add_real_number= a1 + a2
return
end

program test
integer i1,i2,i3
real a1,a2,a3

r3 = add_real_number(a1,a2)
i3= ifix (add_real_number( float(i1), float(i2)))
stop
end

Not the most runtime effective thing in the world but could be done. Multiple definition of the same procedure for different argument types as possible in C++ does not work in Fortran 95 (unless xwb knows better than me :)).

Norbert

 
I will give a try of type conversion in the argument itself which I haven't tried it. Thanks!
 
Check if your compiler supports typealias. If it does then there is another way of doing this.

It really depends on how you write your code. For instance, you could put the major algorithm in an include file and include it twice

eg the include file which I've called sort.inc
Code:
integer:: ii, jj, mini
do ii = 1, INmax - 1
   mini = ii
   do jj = ii + 1, INMax
      if (IOa(mini) .gt. IOa(jj)) mini = jj
   end do

   if (mini .ne. ii) then
      temp = IOa(ii)
      IOa(ii) = IOa(mini)
      IOa(mini) = temp
   end if
end do
The code which uses it. All it does is declare the routine headers, and, for completeness, the footers.
Code:
module ModReal
contains
   subroutine sortreal (IOa, INMax)
   real, dimension(:), intent(inout):: IOa
   integer, intent(in):: INMax
   real:: temp
include 'sort.inc'
   return
   end subroutine
end module

module ModInt
contains
   subroutine sortint (IOa, INmax)
   integer, dimension(:), intent(inout):: IOa
   integer, intent(in):: INMax
   integer:: temp
include 'sort.inc'
   return
   end subroutine
end module

program main
   use ModReal
   use ModInt
   integer, parameter:: MAXAA = 10
   real, dimension(MAXAA):: ar
   integer, dimension (MAXAA):: ai
   integer:: ii

   ar = (/ 7., 4., 1., 8., 5., 2., 9., 6., 3., 0. /)
   ai = (/ 3, 6, 9, 2, 5, 8, 1, 4, 7, 0/)

   print '(A,10I7)', 'before', (ai(ii), ii = 1, MAXAA)
   call sortint(ai, MAXAA)
   print '(A,10I7)', 'after ', (ai(ii), ii = 1, MAXAA)
   print '(A,10F7.2)', 'before', (ar(ii), ii = 1, MAXAA)
   call sortreal(ar, MAXAA)
   print '(A,10F7.2)', 'after ', (ar(ii), ii = 1, MAXAA)
   stop
end
 
If it supports typealias (I think Lahey and Cray do) then the program gets even shorter. You can also get around the lack of typealiases with #define, #undef and -cpp on g95. I can post an example if you need one.

If your compiler supports typealiases the include file will be
Code:
subroutine sort(IOa, INMax)
type(atype), dimension(:), intent(inout):: IOa
integer, intent(in):: INMax
type(atype):: temp
integer:: ii, jj, mini

do ii = 1, INmax - 1
   mini = ii
   do jj = ii + 1, INMax
      if (IOa(mini) .gt. IOa(jj)) mini = jj
   end do

   if (mini .ne. ii) then
      temp = IOa(ii)
      IOa(ii) = IOa(mini)
      IOa(mini) = temp
   end if
end do
return
end subroutine
And the code will be
Code:
module ModReal
   typealias:: atype=>real
contains
include 'sorta.inc'
end module

module ModInt
typealias:: atype=>integer
contains
include 'sorta.inc'
end module

program main
   use ModReal, only: sortreal=>sort
   use ModInt,  only: sortint=>sort
   integer, parameter:: MAXAA = 10
   real, dimension(MAXAA):: ar
   integer, dimension (MAXAA):: ai
   integer:: ii

   ar = (/ 7., 4., 1., 8., 5., 2., 9., 6., 3., 0. /)
   ai = (/ 3, 6, 9, 2, 5, 8, 1, 4, 7, 0/)

   print '(A,10I7)', 'before', (ai(ii), ii = 1, MAXAA)
   call sortint(ai, MAXAA)
   print '(A,10I7)', 'after ', (ai(ii), ii = 1, MAXAA)
   print '(A,10F7.2)', 'before', (ar(ii), ii = 1, MAXAA)
   call sortreal(ar, MAXAA)
   print '(A,10F7.2)', 'after ', (ar(ii), ii = 1, MAXAA)
   stop
end
 
Thanks so much it is a different approach. I will read about aliases but what will happen if I use integer and real.
 
If you look at the include file, it only uses atype: not integer or real. When included in ModReal, it becomes real. When included in ModInt, it becomes integer. It is write once, use many times. This is more about programming the compiler than programming in Fortran.

If you're using g95, you can do something similar with #defines. The top of the sort include file will look like
Code:
subroutine sort(IOa, INMax)
atype, dimension(:), intent(inout):: IOa
integer, intent(in):: INMax
atype:: temp
The module declarations will look like
Code:
module ModReal
#define atype real
contains
include 'sorta.inc'
#undef atype
end module

module ModInt
#define atype integer
contains
include 'sorta.inc'
#undef atype
end module
Build with g95 using the -cpp option. Macro are absolutely brilliant when you know how to manipulate them. The #define is a feature of g95. It may also exist in gfortran.
 
Thanks gummibaer - your approach works.

I am using Compaq Visual Fortran. I have included the inc file in the source folder. I tried to check it with the following simple example.

inlude file sort.inc

real :: x, y, z
z = x + y

Main file main.f90

Module ModInt

contains

subroutine addit(j, k, l)

integer:: j, k, l

include 'sort.inc'

end subroutine addit

End module modint


!------------------------------------------
Program addit
Use modint

implicit none
integer :: x
real:: y, z

End program addit

When I compile the whole thing it gives me the following warning. Isn't it correct?

sort.inc(2) : Warning: Variable X is used before its value has been defined

sort.inc(2) : Warning: Variable Y is used before its value has been defined


 
No it isn''t. The include file contains the independent bit: in this case
Code:
z = x + y
The module contains the declarations
Code:
Module ModInt
contains
subroutine addit(x, y, z)
real, intent(in):: x, y
real, intent(out)::z
include 'sort.inc'
end subroutine addit
End module modint
 
Thanks so much xwb! It works well.
To summarize the point. This approach puts the independent part in inc file and constructs different subroutines. It is almost similar to writing the sub two times with different declaration. I want to know your opinions about
- putting the subroutines together in module here is just to organize them.
- what is the better option - using conversion or putting it in subroutines.
 
Depends on what you are going to do, that means, how often you use this routine. 'Type Conversion Method' uses three such conversions when you use the routine with the 'wrong' type. If it is only once in a while that this routine runs with the 'wrong' type - that is the approach for you. But if this happens very often it might be felt in runtime efficiency.

In the latter case I would prefer two different subroutines for clarity and debugging.

Norbert
 
Type conversion will work in some cases but not in others. For instance, the addition routine that you experimented with would work for type conversion but the sort routine that I based my initial example on won't.

If you have a basic algorithm and are honing it, then this method would work quite well because you only need to modify the code once. If you have different algorithms for different types of number then it would make sense to keep them separate.
 
Finally, I would like to thank you so much for your help - xwb and gummibaer keep up the good things you are doing.
 
Forgot to add that type_alias is also available in Silverfrost/Salford. You have to compile it either as .net or if in win32 with the /F2K flag. Note that the syntax in Salford's help file is not correct - it is missing :: after type_alias.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top