FORTRAN error - undefined reference to 'jfix' - fortran

I am newbie to FORTRAN. I have some FORTRAN programs written in Intel FORTRAN and now I am compiling them using gfortran.
One of the subroutines uses the JFIX() function. When I complie the following error is thrown.
undefined reference to 'jfix_'
The subroutine has reference to this intrinsic function on the top like External::JFIX
Can anyone help me resolve this?

JFIX is an Intel extension to FORTRAN. It converts its argument to INTEGER(4).
There may be a GNU FORTRAN equivalent, or you may have to provide it yourself.
The Intel FORTRAN Language Reference is available from various places on the web. Here's one.

JFIX may be the one you need, but you should be careful as JFIX not only converts real to integers (as INT does), but also all other kinds of stuff to integer(4).
From the Intel Fortran Language Reference found here, it converts
INTEGER(1), INTEGER(2), INTEGER(4), INTEGER(8),
REAL(4), REAL(8), REAL(16), COMPLEX(4),
COMPLEX(8), COMPLEX(16)
to
INTEGER(4)
That was just to say to you and future readers: while it's the equivalent of INT in your case here, it is not the case everywhere.
As you're new to Fortran let me just give one more precision: the number between parenthesis is the precision kind of the variable. For instance, REAL(4) is simple precision on a "conventional" architecture, REAL(8) double precision.

Related

What shall be used in Modern Fortran to specify a 8 bytes real variable if iso_fortran_env is not supported?

I want to specify as type of a subroutine a floating point value (real) of 8 bytes precision.
I have read here that the modern way to do it would be:
real(real64), intent(out) :: price_open(length)
However, iso_fortran_env is not supported by f2py (same as it does not support iso_c_bindings either).
I get errors of this type:
94 | real(kind=real64) price_open(length)
| 1
Error: Parameter 'real64' at (1) has not been declared or is a variable, which does not reduce to a constant expression
The link referenced before states that using kind would be the proper way if iso_fortran_env is not available and that real*8 shall be avoided.
I have been using real(8) is that equivalent to using kinds? If not, what shall I use?
What is wrong with real*8 if I want to always enforce 8 bytes floating point values?
You say you are specifically interested in interoperability with C. However, iso_c_binding, nor iso_fortran_env are supported. These modules have constants that help you to set the right kind constant for a given purpose. The one from iso_fortran_env would NOT be the right one to choose anyway, it would be c_double.
If these constants meant to help you in your choice are not available, you are on your own. Now you can choose any other method freely.
It is completely legitimate to use just kind(1.d0) and just check that the connection to C works. Automake had been doing that for ages.
Or use selected_real_kind(), it does not matter, it is really up to you. Just check that double in C ended up being the same numeric type.
The traditional thing in automatic build processes was to do many tests about which (mainly C) constant ended up having which value. You just need to check that double precision in Fortran does indeed correspond to double in C. It is very likely, but just check it. You can have a macro that changes the choice if not, but probably it is a needless work untill you actually meet such a system.

Error: Old-style type declaration REAL*16 not supported

I was given some legacy code to compile. Unfortunately I only have access to a f95 compiler and have 0 knowledge of Fortran. Some modules compiled but others I was getting this error:
Error: Old-style type declaration REAL*16 not supported at (1)
My plan is to at least try to fix this error and see what else happens. So here are my 2 questions.
How likely will it be that my code written for Fortran 75 is compatible in the Fortran 95 compiler? (In /usr/bin my compiler is f95 - so I assume it is Fortran 95)
How do I fix this error that I am getting? I tried googling it but cannot see to find a clear crisp answer.
The error you are seeing is due to an old declaration style that was frequent before Fortran 90, but never became standard. Thus, the compiler does not accept the (formally incorrect) code.
In the olden days before Fortran 90, you had only two types of real numbers: REAL and DOUBLE PRECISION. These types were platform dependent, but most compilers nowadays map them to the IEEE754 formats binary32 and binary64.
However, some machines offered different formats, often with extra precision. In order to make them accessible to Fortran code, the type REAL*n was invented, with n an integer literal from a set of compiler-dependent values. This syntax was never standard, so you cannot be sure of what it will mean to a given compiler without reading its documentation.
In the real world, most compilers that have not been asked to be strictly standards-compliant (with some option like -std=f95) will recognize at least REAL*4 and REAL*8, mapping them to the binary32/64 formats mentioned before, but everything else is completely platform dependent. Your compiler may have a REAL*10 type for the 80-bit arithmetic used by the x86 387 FPU, or a REAL*16 type for some 128-bit floating point math. However, it is important to stress that since the syntax is not standard, the meaning of that type could change from compiler to compiler.
Finally, in Fortran 90 a way to refer to different kinds of real and integer types was made standard. The new syntax is REAL(n) or REAL(kind=n) and is supported by all standard-compliant compilers. However, The values of n are still compiler-dependent, but the standard provides three ways to obtain specific, repeatable results:
The SELECTED_REAL_KIND function, which allows you to query the system for the value of n to specify if you want a real type with certain precision and range requirements. Usually, what you do is ask for it once and store the result in an INTEGER, PARAMETER variable that you use when declaring the real variables in question. For example, you would declare a type with at least 15 digits of precision (decimal) and exponent range of at least 100 like this:
INTEGER, PARAMETER :: rk = SELECTED_REAL_KIND(15, 100)
REAL(rk) :: v
In Fortran 2003 and onwards, the ISO_C_BINDING module contains a series of constants that are meant to give you types guaranteed to be equivalent to the C types of the same compiler family (e.g. gcc for gfortran, icc for ifort, etc.). They are called C_FLOAT, C_DOUBLE and C_LONG_DOUBLE. Thus, you could declare a variable equivalent to a C double as REAL(C_DOUBLE) :: d.
In Fortran 2008 and onwards, the ISO_FORTRAN_ENV module contains a different series of constants REAL32, REAL64 and REAL128 that will give you a floating point type of the appropriate width - if some platform does not support one of those types, the constant will be a negative number. Thus, you can declare a 128-bit float as REAL(real128) :: q.
Javier has given an excellent answer to your immediate problem. However I'd just briefly like to address "How likely will it be that my code written for Fortran 77 is compatible in the Fortran 95 compiler?", with the obvious typo corrected.
Fortran, if the programmer adheres to the standard, is amazingly backward compatible. With very, very few exceptions standard conforming Fortran 77 is Fortran 2008 conforming. The problem is that it appears in your case the original programmer has not adhered to the international standard: real*8 and similar is not, and has never been part of any such standard and the problems you are seeing are precisely why such forms should never be, and should never have been used. That said if the original programmer only made this one mistake it may well be that the rest of the code will be OK, however without the detail it is impossible to tell
TL;DR: International standards are important, stick to them!
When we are at guessing instead of requesting proper code and full details I will venture to say that the other two answers are not correct.
The error message
Error: Old-style type declaration REAL*16 not supported at (1)
DOES NOT mean that the REAL*n syntax is not supported.
The error message is misleading. It actually means that the 16-byte reals are no supported. Had the OP requested the same real by the kind notation (in any of the many ways which return the gfortran's kind 16) the error message would be:
Error: Kind 16 not supported for type REAL at (1)
That can happen in some gfortran versions. Especially in MS Windows.
This explanation can be found with just a very quick google search for the error message: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56850#c1
It does not not complain that the old syntax is the problem, it just mentions it, because mentioning kinds might be confusing even more (especially for COMPLEX*32 which is kind 16).
The main message is: We really should be closing these kinds of questions and wait for proper details instead of guessing and upvoting the question where the OP can't even copy the full message the compiler has spit.
If you are using GNU gfortran, try "real(kind=10)", which will give you 10 bytes (80-bits) extended precision. I'm converting some older F77 code to run floating point math tests - it has a quad-precision ( the real*16 you mention) defined, but not used, as the other answers provided correctly point out (extended precision formats tend to be machine/compiler specific). The gfortran 5.2 I am using does not support real(kind=16), surprisingly. But gfortran (available for 64-bit MacOS and 64-bit Linux machines), does have the "real(kind=10)" which will give you precision beyond the typical real*8 or "double precision" as it was called in some Fortran compilers.
Be careful if your old Fortran code is calling C programs and/or maybe making assumptions about how precision is handled and floating point numbers are represented. You may have to get deep into exactly what is happening, and check the code carefully, to ensure things are working as expected, especially if fortran and C routines are calling each other. Here is url for the GNU gfortran info on quad-precision: https://people.sc.fsu.edu/~jburkardt/f77_src/gfortran_quadmath/gfortran_quadmath.html
Hope this helps.

Using underscores to define kind/precision

I've been using using an underscore to define an integer as a specific kind in fortran.
Here is a snippet of code to demonstrate what 1_8 means, for example:
program main
implicit none
integer(2) :: tiny
integer(4) :: short
integer(8) :: long
tiny = 1
short = 1
long = 1
print*, huge(tiny)
print*, huge(1_2)
print*, huge(short)
print*, huge(1_4)
print*, huge(long)
print*, huge(1_8)
end program main
Which returns (with PGI or gfortran):
32767
32767
2147483647
2147483647
9223372036854775807
9223372036854775807
I'm using the huge intrinsic function to return largest number of the given kind. So 1_8 is clearly the same kind as integer(8). This works for real numbers also, although I haven't shown it here.
However, I've been unable to find any documentation of this functionality and I don't remember where I learned it. My question is:
Is using _KIND standard fortran? Does anybody have a source for this?
Edit: It's been pointed out that the kind values I've used (2,4,8) are not portable - different compilers/machines may give different values for huge(1_4), for example.
It is standard Fortran, as of Fortran 90, though the set of valid kind values for each type and the meaning of a kind value is processor dependent.
The Fortran standard is the definitive source for what is "standard" Fortran. ISO/IEC 1539-1:2010 is the current edition, which you can buy, or pre-publication drafts of that document are available from various places. https://gcc.gnu.org/wiki/GFortranStandards has a collection of useful links.
I would expect that many compiler manuals (e.g - see section 2.2 of the current PGI Fortran reference manual) and all reasonable textbooks on modern Fortran would also describe this feature.
As already answered, this notation is standard fortran, but using these specific numeric values for kinds is not portable. Previous answers have described compilers that use other schemes. There are several other approaches that are portable.
First, use the kind scheme to define symbols, then use those symbols for numeric constants:
integer, parameter :: RegInt_K = selected_int_kind (8)
write (*, *) huge (1_RegInt_K)
Or use the kind definitions that are provided in the ISO_FORTRAN_ENV module, e.g.,
write (*, *) huge (1_int32)
The kinds of this module are specified in the number of bits used for storage. Some of the kinds are only available with Fortran 2008. If those are missing in your compiler, you can use the kind definitions provided with the ISO_C_BINDING, which is older.
To add to IanH's answer the specification for an integer literal constant in Fortran 2008 is given in 4.4.2.2. Something like 1_8 fits in with R407 and R408 (for the obvious digit-string):
int-literal-constant is digit-string [_kind-param]
kind-param is digit-string or scalar-int-constant-name
You can find similar for other data types (although note that for characters the kind parameter is at the front of the literal constant).

Implicit real error

I have written program with implicit real*8. The program is working fine but as soon as i inserted another data file that contains the data of long and double precision digits than the results i found were not appropriate. Experts and the program developers adviced me to change implicit real*16. But it is not working in my fortran power station 4.0 and giving implicit error. How to convert or upgrade the power station so that it can work with implicit real*16 or more?
Powerstation is too old. Not every compiler supports real*16 even now. Consider to obtain a new compiler. I suggest to begin with gfortran, that does support quad precision for sure.
Also I am worried that with that implicit things there might be many other problems hidden. Consider also explicit typing for your variables and using implicit none.
What are the values in your file? integers and double precision floating point values? Then it seems very unlikely that the problem is caused by your not reading them into quad-precision real variables. Only rarely do calculations need quad-precision. Are you reading the integer values into integer variables and the floats into Fortran reals? As the others have written, implicit typing is the worst approach ... it is still part of Fortran only to support legacy code. Best practice is to use "implicit none" and explicitly type all of your variables. This will allow the compiler to catch mistakes such as typos in variable names. For more about variable typing see Fortran: integer*4 vs integer(4) vs integer(kind=4) and Extended double precision

fortran compiler 4 vs 11

I am porting an application from fortran older version (4.0) to new version (11.0). While porting I am facing some problems with real*4 variables:
real*4 a,b,c
a=0.9876875
b=0.6754345
c=a*b
value for c in old compiler 0.667118, which is correct value. But with new compiler I am getting a small variation from the output(c variable) like 0.667120. Though it is a small variation, I am using these values in some other calculation. So the overall output has a huge difference. How to overcome this issue?
You are, I'm assuming, going from Microsoft Fortran Powerstation 4 to Intel Visual Fortran 11.xx ?
Anyways, try this:
program test32
integer, parameter :: iwp = selected_real_kind(15,300)
real(iwp) :: a,b,c
a=0.9876875
b=0.6754345
c=a*b
write(*,'(3f12.8)')a,b,c
end program test32
which gives out:
0.98768753 0.67543453 0.66711826
I will not explain selected_real_kind, not because I do not wish, but because the help will probably do it much better. But, do ask if something in here is not clear.
p.s. The representation of real*4, or any type of real is processor dependent, and compiler dependent and that is one of the reasons why you're getting different results.
Discussion of changes in Intel visual Fortran compiler version 11 here:
http://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/68587/
The upshot is that older versions of the Fortran compiler would implicitly promote single-precision values to double-precision before performing an operation. The default behavior in version 11 is to perform the operation with single-precision. There are compiler options (/arch:ia32) to enable the old behavior in the new compiler.
I assume you are using Intel. Try to compile without optimization..