Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

How can I lie to FORTRAN?

carlls
Beginner
647 Views

Greetings

Here is my dilemma.... I have converted a lot of old f77 code to modularized F90 code. Now when people try to compile "the roaches come out of the wood work" which is both good and bad.

You know what the questions is then .... is there a way to lie to FORTRAN like I can in C via casting.

So maybe something like ...

INTEGER (KIND=4) i

call fred( (REAL , KIND=4) i )

where fred takes in a floating point number.

And yes I know this is "wrong" but the real examples are too complicated to use. And yes I will take full responsibility for turning off the safety features.

This is a get the job done apporach.

Regards
Carl

0 Kudos
9 Replies
jimdempseyatthecove
Honored Contributor III
647 Views

You might be able to use

call fred(TRANSFER(i,0.0_4))

Be careful, run test. You may have issues of portability.

Jim Dempsey
0 Kudos
Steven_L_Intel1
Employee
647 Views
If you have certain routines where you want to disable type checking for selected arguments, add in those routines (or in the interface block if you have one):

!DEC$ ATTRIBUTES NO_ARG_CHECK :: argument_name

This will disable all type and rank checking for that argument. As Jim suggests, lying to the compiler can be dangerous.

Be especially careful of passing integers to something declared as REAL. Some integer values will be changed when loaded as "REAL" by the processor, and others may trigger floating point errors.
0 Kudos
jarvusluntatintel
647 Views
I inherited a lot of legacy code that was a bit on the dodgy side even by f77 standards. I have no idea what othersort of issues/problems you may have, but Idiscovered that my legacy coderan much betterwhen all of the various optimizations were turned off.

good luck

0 Kudos
John4
Valued Contributor I
647 Views

You might be able to use

call fred(TRANSFER(i,0.0_4))

Be careful, run test. You may have issues of portability.

Jim Dempsey

Sorry if my advice is redundant, but isn't the REAL intrinsic a better option than TRANSFER? As in:


call fred (REAL(i, KIND = 4))

0 Kudos
Steven_L_Intel1
Employee
647 Views

It depends on what you want. If you want to convert an integer to a real, then yes, REAL is correct. But if you are passing an integer to something that wants to interpret the exact same bits as if it were a real, then TRANSFER is the ticket. As I note, though, the latter is fraught with peril. I have seen old code that does an "array copy" with a routine that declares the arguments as arrays of reals, but allow any datatype to be passed. Surprises ensue when the values change because of things such as SNaNs changing to QNaNs, denorms getting flushed to zero, etc.

Let me point out that any "F77" code that requires such tricks is not standard F77 ((nor F66).
0 Kudos
jimdempseyatthecove
Honored Contributor III
647 Views

John,

You requested an equivilent to cast operator, not a conversion operator. REAL is a conversion operator, TRANSFER (as written in post) is equivilent to the cast operator.

Steve's comment regarding method to ignore type checking might be an easierroute however, this may introduce headaches for you later on as you get further into your conversion of your program.

An alternative you can use is to declare a cast-like function which can be inlined

cDEC$ ATTRIBUTES INLINE :: asREAL4
pure real function asREAL4(i4)
integer(4) :: i4
return TRANSFER(i,0.0_4)
end function asREAL4

...

call fred(asREAL4(i))

A different alternative is to declare fred as a generic interfacefunction with one set of argument(s) as integer(4) and a second set of argument(s) as real(4). Using generic interface you will have no source code edits to existing munged up function/subroutine calls. You will have to add the interface and conversion function in only one place in your code. Also, this makes it handy to insert break point for use later in code clean-up.

Jim Dempsey
0 Kudos
John_N_2
Beginner
647 Views

John,

You requested an equivilent to cast operator, not a conversion operator. REAL is a conversion operator, TRANSFER (as written in post) is equivilent to the cast operator.

Steve's comment regarding method to ignore type checking might be an easierroute however, this may introduce headaches for you later on as you get further into your conversion of your program.

An alternative you can use is to declare a cast-like function which can be inlined

cDEC$ ATTRIBUTES INLINE :: asREAL4
pure real function asREAL4(i4)
integer(4) :: i4
return TRANSFER(i,0.0_4)
end function asREAL4

...

call fred(asREAL4(i))

A different alternative is to declare fred as a generic interfacefunction with one set of argument(s) as integer(4) and a second set of argument(s) as real(4). Using generic interface you will have no source code edits to existing munged up function/subroutine calls. You will have to add the interface and conversion function in only one place in your code. Also, this makes it handy to insert break point for use later in code clean-up.

Jim Dempsey


Dear Carl:

Lying to Fortran is like lying to your wife or the IRS, one day you are gunna get caught with your pants down and it is not going to be funny. Divorce is expensive as well.

I have about 100,000 lines of code I am slowly porting, operative word slow, including some stuff from 1972 written by a UCB grad student, which required some fixing. The fact that the '72 code is the best structural inversion program ever written made it worth while.

I had some problems recently reading C strings of a very awful nature into Fortran, I found part of my problem could be solved by a write to a file then a read.

Good hunting.

JMN

0 Kudos
sarma_amras
New Contributor I
647 Views
Hi,
Currently I am involved in a similar migration of code written in F66 to 2003.
Hope I can help you some way.Can you please provide your exact problem...I just confused with these many posts.
Regards
Kameswara Sarma

0 Kudos
carlls
Beginner
647 Views
Thank you for the prompt response. My take-away is:

Simply turning off checking i.e

!DEC$ ATTRIBUTES NO_ARG_CHECK :: argument_name

Let me say I agree that lieing in general is a bad thing, but this code has run on 8~10 hardware platforms, survived for ~30 years, and seen 20 developers, it even has it's own namelist standard before F90 decided to make one.

So at this point getting 80% of the code to be modularized, and run successfully with bounds checking on is an accomplishment.

This solution is about compromise.

Thanks for you help.

Regards
Carl


0 Kudos
Reply