SLATEC - compilation Error - fortran

I want to compile the slatec library downloaded at netlike.org.
I wrote a simple Makefile to compile all routines. However, I get an error when compiling the **mach.f files like d1mach.f that contain the machine specific values.
The error occurs only when I (as I should, if I understand the description correctly) uncomment the values for my machine (intel). If I don't do this, the compilation doesn't create an error, but the routine dsos doesn't work, i.e. the iteration doesn't start but instead it always evaluated the test function at the starting point.
The error message:
src/d1mach.f:85:37:
EQUIVALENCE (DMACH(5),LOG10(1))
1
Error: Expecting a comma in EQUIVALENCE at (1)
make: *** [obj/d1mach.o] Error 1
I guess the reason is If a variable name is also a function name (15.5.1), that name must not appear in the list. what I found under point 8.2.1 in the Fortran77 Standard.
Anyone, ever had this issue and solved it?
EDIT:
The short version of d1mach.f is:
DOUBLE PRECISION FUNCTION D1MACH (I)
C
INTEGER SMALL(4)
INTEGER LARGE(4)
INTEGER RIGHT(4)
INTEGER DIVER(4)
INTEGER LOG10(4)
C
DOUBLE PRECISION DMACH(5)
SAVE DMACH
C
EQUIVALENCE (DMACH(1),SMALL(1))
EQUIVALENCE (DMACH(2),LARGE(1))
EQUIVALENCE (DMACH(3),RIGHT(1))
EQUIVALENCE (DMACH(4),DIVER(1))
EQUIVALENCE (DMACH(5),LOG10(1))
C
C
DATA DMACH(1) / Z'0010000000000000' /
DATA DMACH(2) / Z'7FEFFFFFFFFFFFFF' /
DATA DMACH(3) / Z'3CA0000000000000' /
DATA DMACH(4) / Z'3CB0000000000000' /
DATA DMACH(5) / Z'3FD34413509F79FF' /
C
C
IF (I .LT. 1 .OR. I .GT. 5) CALL XERMSG ('SLATEC', 'D1MACH',
+ 'I OUT OF BOUNDS', 1, 2)
C
D1MACH = DMACH(I)
RETURN
C
END

Related

How to translate from EQUIVALENCE to index offset [duplicate]

This question already has answers here:
Syntax error in call statement in Fortran
(1 answer)
Incompatible ranks 0 and 2 in assignment [duplicate]
(1 answer)
Closed 4 years ago.
I am trying to modernize a Fortran 77 codebase which makes heavy use of common blocks in include files. One of my goals is to translate the codebase so it uses modules instead of this common/include construction. However, the code also uses equivalence statements here and there, referring to common variables. It is not allowed to equivalence to/from module variables, so this is a problem.
Now, luckily, the equivalence statements are only used to alias (parts of) arrays and never for 'magic' between different variables types. Therefore I have tried to translate the code by simply calculating index offsets and referring to the original arrays instead of equivalenc-ing them. However, this has lead to some unexpected compilation errors and runtime crashes.
For example, consider the change from
IF(RLX*ABS(DXT/(X2-X1)) .GT. 0.05) RLX = 0.05*ABS((X2-X1)/DXT)
to
IF(RLX*ABS(DXT/(COM2(1)-COM1(1))) .GT. 0.05) RLX = 0.05*ABS((COM2(1)-COM1(1))/DXT)
, which is supposed to change the include file code from
REAL COM1(NCOM), COM2(NCOM)
COMMON/V_VAR1/ X1
COMMON/V_VAR2/ X2
EQUIVALENCE (X1, COM1(1)), (X2, COM2(1))
to simply
COMMON COM1(NCOM), COM2(NCOM)
, but leads to the following compilation error:
IF(RLX*ABS(DXT/(COM2(1)-COM1(1))) .GT. 0.05) RLX = 0.05*ABS((COM2(1)-COM1(1))/DXT)
1
Error: Missing ')' in statement at or before (1)
This statement seems correct to me, though. So what am I missing here?
If I alleviate the above problem by changing the code to
DX = COM2(1) - COM1(1)
IF(RLX*ABS(DXT/DX) .GT. 0.05) RLX = 0.05*ABS(DX/DXT)
I do not get compilation errors. However, then I run into Signal: SIGFPE (Arithmetic exception)'s at runtime, because for some reason the change from X1 to COM1(1) and X2 to COM2(1) leads to seemingly unrelated variables to not get proper initial values (which leads to division by zero, and consequently to the addition of nan's, and therefore to the arithmetic exception).
Obviously, I am missing something crucial here, so I tried to find a good reference for doing this sort of translation. Does anyone know of something like that? Or has anyone run into this problem before and found a solution? Any help would be greatly appreciated.
As pointed in the comments, the error arises after refactoring the code probably because you are working in fixed-form and the source line cannot go beyond 72 characters (all the remaining characters are ignored).
If you are modernizing the code, you should left fixed-form behind and write in free-form. Sometimes compilers assume source-form based on file extension. If this is the case, you can change the file extension from .f to .f90. Or else, you can pass the desired format as a compiler flag (-ffree-form in gfortran, -free in Intel Fortran).
If by any case you are stuck into fixed-form, you'd better do a line-continuation by putting an arbitrary non-blank character at column 6 of the continued line.

Hollerith data statements

The below refers to fortran 66 code. Trying to recompile very old programs. Cannot understand the reason for the error. Need work around recommendations. trying not to recode in updated fortran.
DATA NPOP/6HPOPS-I,6HPOPS-D,6HPOPS-C,6HPOPS-A,6HPOPS-E,6HPOP-S /
^
Truncating characters on right side of hollerith constant at (^) azthree.for:24:
DATA NPOP/6HPOPS-I,6HPOPS-D,6HPOPS-C,6HPOPS-A,6HPOPS-E,6HPOP-S /
^
Truncating characters on right side of hollerith constant at (^) azthree.for:24:
DATA NPOP/6HPOPS-I,6HPOPS-D,6HPOPS-C,6HPOPS-A,6HPOPS-E,6HPOP-S /
^
I've never used Fortran66, but Hollerith constants declare the next characters as data, not code. So 6H would mean something like: The 6 characters after the H are supposed to be data, not code.
In essence, I would think that 6HPOPS-I would be the same as "POPS-I".
Maybe if you could give us the declaration of NPOP that would help to understand the issue.
I have kind of recreated the error message with this code:
PROGRAM holl
IMPLICIT NONE
CHARACTER*1 NPOP(6)
INTEGER i
DATA NPOP / 6HPOPS-I,6HPOPS-D,6HPOPS-C,
+ 6HPOPS-A,6HPOPS-E,6HPOP-S /
DO 100 i = 1, 6
PRINT *, NPOP(i)
100 CONTINUE
END PROGRAM
This gives the compiler warnings:
$ gfortran -o holl holl.f
holl.f:6.38:
+ 6HPOPS-A,6HPOPS-E,6HPOP-S /
1
Warning: Legacy Extension: Hollerith constant at (1)
holl.f:5.20:
DATA NPOP / 6HPOPS-I,6HPOPS-D,6HPOPS-C,
1
Warning: Initialization string starting at (1) was truncated to fit the variable (1/6)
holl.f:5.29:
DATA NPOP / 6HPOPS-I,6HPOPS-D,6HPOPS-C,
1
Warning: Initialization string starting at (1) was truncated to fit the variable (1/6)
But it's not quite your errors. I don't know which compiler you use, and in your case, the marker for the truncation seems to point to the H itself.
So we really need more info from you:
More code, specifically the declaration of NPOP
Compiler version and -options

Fortran DO loop, warning to use integer only

I installed gfortran on my Ubuntu 15.04 system. While compiling Fortran code, the DO loop asks to take integer parameters only and not real values or variables. That includes the loop variable and the step expression. Why can't it take real values too?
The following is a program taken from here, exercise 3.5 of the section nested do loops.
program xytab
implicit none
!constructs a table of z=x/y for values of x from 1 to 2 and
!y from 1 to 4 in steps of .5
real :: x, y, z
print *, ' x y z'
do x = 1,2
do y = 1,4,0.5
z = x/y
print *, x,y,z
end do
end do
end program xytab
The error shown after compiling is:
xytab.f95:8.4:
do y = 1,4,0.5
1
Warning: Deleted feature: Loop variable at (1) must be integer
xytab.f95:8.12:
do y = 1,4,0.5
1
Warning: Deleted feature: Step expression in DO loop at (1) must be integer
xytab.f95:7.3:
do x = 1,2
1
Warning: Deleted feature: Loop variable at (1) must be integer
The Fortran standard now requires that a do construct's loop control is given by (scalar) integer expressions and that the loop variable is a (scalar) integer variable. The loop control consists of the start, step, and stop expressions (your step expression is 0.5). See R818 and R819 (8.1.6.2) of the Fortran 2008 document. That, then, is the short and simple answer: the standard says so.
It's a little more complicated than that, as the messages from the compiler suggest. Using other forms for loop control was present in Fortran up until Fortran 95. That is, from Fortran 95 onward using real expressions is a deleted feature.
What harm is there in using real expressions? Used correctly, one could imagine, there is no harm. But there's real difficulty in portability with them.
Consider
do x=0., 1., 0.1
...
end do
How many iterations? That would be (under the rules of Fortran 90) MAX(INT((m2 – m1 + m3) / m3), 0) where (m1 is the start value (0.), m2 the stop value (1.) and m3 the step value (0.1)). Is that 10 or 11 (or even 9)? It depends entirely on your numeric representation: we recall that 0.1 may not be exactly representable as a real number and INT truncates in converting to integer. You'd also have to worry about repeated addition of real numbers.
So, use integers and do some arithmetic inside the loop
do y_loop = 0, 6
y = 1 + y_loop/2.
...
end do
or
y = 1
do
if (y>4) exit
...
y = y+0.5
end do
Finally, you mention .f90 and .f95 file suffixes. gfortran doesn't take the first to mean that the source code follows the Fortran 90 standard (where the code would be fine). Further, the messages from the compiler are merely warnings, and these can be suppressed using the -std=legacy option. Conversely, using -std=f95 (or later standards) these become errors.
As a bonus fun fact consider the following piece of Fortran 90 code.
real y
integer i
loop_real: do y=1, 4, 0.5
end do loop_real
loop_integer: do i=1, 4, 0.5
end do loop_integer
While the loop named loop_real is valid, that named loop_integer isn't. In the calculation of the iteration count the three expressions are converted to the kind, with kind parameters, of the loop variable. INT(0.5) is 0.

Trying to use netlib code (QUADPACK). What is xerror?

I'm trying to figure out how to use quadpack.
In a single folder, I located the contents of "qag.f plus dependencies" and the code blow as qag_test.f:
(maybe this code itself is not very important. This is in fact just a snippet from the quadpack document)
REAL A,ABSERR,B,EPSABS,EPSREL,F,RESULT,WORK
INTEGER IER,IWORK,KEY,LAST,LENW,LIMIT,NEVAL
DIMENSION IWORK(100),WORK(400)
EXTERNAL F
A = 0.0E0
B = 1.0E0
EPSABS = 0.0E0
EPSREL = 1.0E-3
KEY = 6
LIMIT = 100
LENW = LIMIT*4
CALL QAG(F,A,B,EPSABS,EPSREL,KEY,RESULT,ABSERR,NEVAL,
* IER,LIMIT,LENW,LAST,IWORK,WORK)
C INCLUDE WRITE STATEMENTS
STOP
END
C
REAL FUNCTION F(X)
REAL X
F = 2.0E0/(2.0E0+SIN(31.41592653589793E0*X))
RETURN
END
Using gfortran *.f (installed as MinGW 64bit), I got:
C:\Users\username\AppData\Local\Temp\ccIQwFEt.o:qag.f:(.text+0x1e0): undefined re
ference to `xerror_'
C:\Users\username\AppData\Local\Temp\cc6XR3D0.o:qage.f:(.text+0x83): undefined re
ference to `r1mach_'
(and a lot more of the same r1mach_ error)
It seems r1mach is a part of BLAS (and I don't know why it's not packaged in here but obtained as "auxiliary"), but what is xerror?
How do I properly compile this snippet in my environment, Win7 64bit (hopefully without Cygwin)?
Your help is very much appreciated.
xerror is an error reporting routine. Looking at the way it is called, it appears to use Hollerith constants (the ones where "foo" is written as 3hfoo).
if(ier.ne.0) call xerror(26habnormal return from qag ,
* 26,ier,lvl)
xerror in turn calls xerrwv, passing along the arguments (plus a few more).
This was definitely written before Fortran 77 became widespread.
Your best bet would be to use a compiler which still supports Hollerith constants, pull in all the dependencies (xeerwv has a few more, I don't know why you didn't get them from netlib) and run it through the compiler of your choice. Most compilers, including gfortran, support Hollerith; just ignore the warnings :-)
You will possibly need to modify one routine, that is xerprt. With gfortran, you could write this one as
subroutine xerprt(c,n)
character(len=1), dimension(n) :: c
write (*,'(500A)') c
end subroutine xerprt
and put this one into a separate file so that the compiler doesn't catch the rank violation (I know, I know...)

Weird fortran numeric behavior when comparing to a constant

So I have this code in Fortran:
REAL*8 DELTA,XI,SO,S
SO=0.273333328465621
S=0.323333333556851
XI=0.01
DELTA =SO-S ! DELTA = -0.0500000050912297
IF(DELTA.GE.0.0)XI=XI/10
This code with those values always end up evaluating the IF as true and executes the XI division (i.e. XI=0.001 after. I think this is a weird behavior, but my job is to replicate that behavior in C#.
Compiled with intel fortran, no optimizations and and full debug information as part of a 32 bit DLL
Any ideas why this happens?
The following doesn't execute the IF statement. Both with gfortran and ifort.
program test_delta
double precision DELTA
DELTA = -0.0500001
IF (DELTA .GE. 0.0) then
write (*, *) "IF-statement executed"
ENDIF
end program test_delta
One change is that I added the expected "then" to the IF statement. Otherwise both compilers issued error messages.