Reputation: 1565
I have a three convert functions that convert angles, the code shown below.
The functions returns are of the same type as the input. This means that
the input angle has either to be of the type the programmer wishes the output
to be or convert it to output type required using for example
al = convert(Real(30),"deg_to_rad")
.
I would like the programmer to be able to do al = convert(30,"deg_to_rad")
.
I have the idea to use the strategy of the transfer
intrinsic to define
the output type.
Real :: al, mold
al = convert(30,"deg_to_rad", mold)
al = convert(30.0,"deg_to_rad", mold)
Double Precision :: al, mold
al = convert(30,"deg_to_rad", mold)
al = convert(30.0,"deg_to_rad", mold)
There are the functions I have. Would be good to have some ideas on ways to proceed and implement a good scheme.
Interface convert
Module Procedure convert
Module Procedure convert_real
Module Procedure convert_dble
Module Procedure convert_real128
End Interface convert
Contains
Function convert_real &
( &
qa, label &
) &
Result (qb)
Real, Intent (in) :: qa
Character (len=*), Intent (in) :: label
Real :: qb
If (label .contains. "angle:") Then
Block
Real :: pi, deg_to_rad
pi = 22.0 / 7.0
deg_to_rad = pi / 180.0
Select Case (Trim (label))
Case ("angle: deg_to_rad")
qb = deg_to_rad * qa
End Select
End Block
End If
End Function convert_real
Function convert_dble &
( &
qa, label &
) &
Result (qb)
Double Precision, Intent (in) :: qa
Character (len=*), Intent (in) :: label
Double Precision :: qb
If (label .contains. "angle:") Then
Block
Double Precision :: pi, deg_to_rad
pi = Dble(22) / Dble(7)
deg_to_rad = pi / Dble(180)
Select Case (Trim (label))
Case ("angle: deg_to_rad")
qb = deg_to_rad * qa
End Select
End Block
End If
End Function convert_dble
Function convert_real128 &
( &
qa, label &
) &
Result (qb)
Real (Real128), Intent (in) :: qa
Character (len=*), Intent (in) :: label
Real (Real128) :: qb
If (label .contains. "angle:") Then
Block
Real (Real128) :: pi, deg_to_rad
pi = Real(22,Real128) / Real(7,Real128)
deg_to_rad = pi / Real(180,Real128)
Select Case (Trim (label))
Case ("angle: deg_to_rad")
qb = deg_to_rad * qa
End Select
End Block
End If
End Function convert_real128
I am trying to use a subroutine when the input and outputs are of different types. However I get the error below
Subroutine convertor &
( &
qa, label, qb &
)
Class (*), Intent (in) :: qa
Character (len=*), Intent (in) :: label
Class (*), Intent (out) :: qb
Select Type (qb)
Type Is (Real)
qb = convert (Real(qa),label)
Type Is (Double Precision)
qb = convert (Dble(qa),label)
Type Is (Real (Real128))
qb = convert (Real(qa,Real128),label)
End Select
End Subroutine convertor
Here is the error
gfortran -o build/lib/foul.o -c -ffree-form -g -J./build/lib lib/foul.f
gfortran -o build/lib/meidum.o -c -ffree-form -g -J./build/lib lib/meidum.f
lib/meidum.f:890.26:
qb = convert (Real(qa),label)
1
Error: 'a' argument of 'real' intrinsic at (1) must be a numeric type
lib/meidum.f:893.26:
qb = convert (Dble(qa),label)
1
Error: 'a' argument of 'dble' intrinsic at (1) must be a numeric type
lib/meidum.f:896.26:
qb = convert (Real(qa,Real128),label)
1
Error: 'a' argument of 'real' intrinsic at (1) must be a numeric type
Upvotes: 2
Views: 1394
Reputation: 29401
If I understand what you are trying to do, this seems unnecessarily complicated. Instead of using transfer
as your model, use the arithmetic intrinsic functions such as sin
. Fortran (since FORTRAN 77) can automatically distinguish between the various sine functions (real, double precision, quad precision) based on their argument. Write each function, then an interface
listing them as module procedure
to make them generic. Example: Overloading functions with Fortran
EDIT: It depends on what you want:
result = convert (input)
To me, it seems most natural to have type of the function return controlled by the type of the argument input
. That is what I described and is what is shown in the example. If the type of result
is different, Fortran will convert in the assignment ... the drawback is if you have selected compiler options so that this generates a warning. So if instead you want the type of result
to control the type calculated by convert
, then this technique will have to be modified. You can't use a function because function return doesn't distinguish for this overloading. Use a subroutine instead, which will then have an argument that will distinguish:
call convert (input, result)
This will work just fine in with an interface / module procedure. I'm not sure why think this won't work. It might be a bit less elegant in usage than the assignment statement / function notation.
Upvotes: 3