Does '==', '>', or '<' work in Fortran 90? - fortran

I recently wrote a fortran90 code after writing lots of C and C++ code. I wrote some IF and ELSE IF statements in my fortran code, but wrote them using C syntax. For example,
IF (a>b) THEN
BLAH BLAH BLAH
END IF
instead of
IF (a.gt.b) THEN
BLAH BLAH BLAH
END IF
My fortran compiled and it seemed like it was working properly My question, does this really work in fortran90?

Yes. According to the Fortran 90 Standard (ISO/IEC 1539:1991):
ftp://ftp.nag.co.uk/sc22wg5/N001-N1100/N692.pdf
7.1.1.5 relational operators rel-op:
is .EQ.
or .NE.
or .LT.
or .LE.
or .GT.
or .GE.
or ==
or /=
or <
or <=
or >
or >=

According to this http://www.cs.mtu.edu/~shene/COURSES/cs201/NOTES/F90-Basics.pdf (page 23) yes, it does.

Related

Operands of logical operator '.or.' at (!) are Logical(4)/CHARACTER(1)

I have the following code:
print*,"type s for a square and type t for a triangle"
read*,fig
if(fig =='t' .or. 'T') then
print*,"Enter the sides of the triangle"
read*,a,b,c
area=tri(a,b,c)
print*,"The area of the triangle is",area
else if (fig=='s' .or.'S') then
print*,"Enter the side of the square"
read*,s
area=sq(s)
It gives me the following error:
intro_fun.f:9:24:
if(fig == 't' .or. 'T') then
1
Error: Operands of logical operator '.or.' at (1) are LOGICAL(4)/CHARACTER(1)
intro_fun.f:14:27:
else if(fig=='s' .or. 'S') then
1
Error: Operands of logical operator '.or.' at (1) are LOGICAL(4)/CHARACTER(1)
You are using the statement:
if(fig == 't' .or. 'T')
this should be:
if(fig == 't' .or. fig == 'T')
Fortran has so many ways of doing this. My first test uses the features of intrinsic comparison to broadcast the comparison against a whole array of values then the ANY transformational intrinsic to reduce the array result to the information we are trying to extract. This is a great method for comparing against many values at once and is in my opinion more readable when there are more than two values to compare against.
The second test uses the SCAN intrinsic which is how Fortran can find out if there were any characters in the input string that matched any characters in a given string.
The third test uses VERIFY which is kind of like SCAN but with negative logic.
The fourth test uses C interoperability to access the function toupper from the C library so as to perform a case-insensitive comparison. Have to be careful, though, because that function uses integer inputs and outputs so we have to convert via IACHAR and ACHAR.
program verify_test
implicit none
character fig
integer i
! verify.txt must exist in the current directory
! and have one character on each of the first two lines.
open(10,file='verify.txt',status='old')
do i = 1, 2
read(10,'(a)') fig
write(*,'(*(g0))') "ANY(fig == ['t','T']) = ",ANY(fig == ['t','T'])
write(*,'(*(g0))') "SCAN(fig,'tT') /= 0 = ",SCAN(fig,'tT') /= 0
write(*,'(*(g0))') "VERIFY(fig,'tT') == 0 = ",VERIFY(fig,'tT') == 0
BLOCK
interface
function toupper(c) bind(C,name='toupper')
use ISO_C_BINDING
implicit none
integer(C_INT) toupper
integer(C_INT), value :: c
end function toupper
end interface
write(*,'(*(g0))') "achar(toupper(iachar(fig))) == 'T' = ",achar(toupper(iachar(fig))) == 'T'
END BLOCK
end do
end program verify_test

Reading variables from a file in fortran

I'm working with a fortran program that reads a lot of data from a file and writes it back in a different format.
The code I'm using to read the data is this:
10 read(10,*,err=11,end=20) f,time(i),(a(i,j),j=1,14)
...
goto 10
11 i=i+1
goto 10
It works, but only when the input file is correct.
But some lines are like this:
"2014-04-28 07:51:18.9",2705,-8.42144,6.623851,0.4654102,20.99942,"NAN","NAN",0,0,0,0,-9.0605,5.8855,0.4135,21.39728
When this happens I lose every value in the line after the NAN. Is there a way to read the other values?
It's possible to read every value as a string and then convert them to doubles?
I know very little about fortran and I need to fix it quickly. Rewriting everything in C could take too much time.
Yes, you can read the entire line into a string. Then parse the string and replace the "NAN" with some special numeric value such as a large negative value. The intrinsic functions can help, e.g., index. Then use an "internal read" to read from the string into the numeric variables.
See: Reading comment lines correctly in an input file using Fortran 90, Reading format in Fortran 90 and Prevent FORTRAN from closing when a character is inputed instead of a number
I got it working.
Here is the code:
10 read(10,'(a)',err=16,end=20) linha
linha=trim(adjustl(linha))
pos1=1
n2=0
DO
pos2 = INDEX(linha(pos1:), ",")
IF (pos2 == 0) THEN
n2 = n2 + 1
strings(n2) = linha(pos1:)
EXIT
END IF
n2 = n2 + 1
strings(n2) = linha(pos1:pos1+pos2-2)
pos1 = pos2+pos1
END DO
f=strings(1)
read(strings(2),*) time(i)
j=1
11 read(strings(j+2), *,err=12) a(i,j)
j=j+1
IF (j > 14) THEN
goto 13
END IF
goto 11
12 a(i,j)=9999
j=j+1
goto 11
13 IF (a(i,6)==9999) THEN
goto 14
END IF
pp=1000.
c1=0.622
c2=1.-c1
rv=461.5
e=0.001*a(i,6)*rv*(a(i,4)+273.15)
a(i,6)=1000*e*c1/(100*pp-c2*e)
14 IF (a(i,5)==9999) THEN
goto 15
END IF
mimol=a(i,5)/44
a(i,5)=mimol*83.14*(a(i,4)+273.15)/pp
15 i=i+1
n=i-1
if (i.gt.nmax) goto 20
goto 10
16 i=i+1
goto 10
Thanks for the help.

FORTRAN 77 'Error: Unclassifiable statement at (1)'

I'm a Fortran 77 learner, I'm new so don'n know much about Fortran.
Our professor gave us a homework. We suppose to write a program that calculates cos(x**2).
It has a Taylor expansion, so I tried to write some things but It gave me this error:
term = term*((-1)**i)*x**2*i)/fac(2*i)
1
Error: Unclassifiable statement at (1)
The hole program is:
PROGRAM COSX_SQUARE
IMPLICIT NONE
INTEGER x, n, i
REAL partial_sum, term
20 PRINT*, 'INPUT THE DEGREE'
READ*, x
x = x*180/3.1415
PRINT*, 'INPUT THE CORRECTION VALUE '
PRINT*, 'AS A NATURAL NUMBER'
READ*, n
i= -1
term = 1
partial_sum = term
10 i=i+1
term = term*((-1)**i)*x**2*i)/fac(2*i)
partial_sum = partial_sum + term
IF (i .LT. n) THEN
GO TO 10
ELSE
PRINT*, 'COS', x, 'SQUARE IS = ', partial_sum
END IF
GO TO 20
END
Where am I mistaking? And will this program work well? Thanks in advance.
You are missing one bracket in your expression!
It should probably read:
term = term*(((-1)**i)*x**2*i)/fac(2*i)

Is there a standard way to check for Infinite and NaN in Fortran 90/95?

I've been trying to find a standards-compliant way to check for Infinite and NaN values in Fortran 90/95 but it proved harder than I thought.
I tried to manually create Inf and NaN variables using the binary representation described in IEEE 754, but I found no such functionality.
I am aware of the intrinsic ieee_arithmetic module in Fortran 2003 with the ieee_is_nan() and ieee_is_finite() intrinsic functions. However it's not supported by all the compilers (notably gfortran as of version 4.9).
Defining infinity and NaN at the beginning like pinf = 1. / 0 and nan = 0. / 0 seems hackish to me and IMHO can raise some building problems - for example if some compilers check this in compile time one would have to provide a special flag.
Is there a way I can implement in standard Fortran 90/95?
function isinf(x)
! Returns .true. if x is infinity, .false. otherwise
...
end function isinf
and isnan()?
The simple way without using the ieee_arithmatic is to do the following.
Infinity: Define your variable infinity = HUGE(dbl_prec_var) (or, if you have it, a quad precision variable). Then you can simply check to see if your variable is infinity by if(my_var > infinity).
NAN: This is even easier. By definition, NAN is not equal to anything, even itself. Simply compare the variable to itself: if(my_var /= my_var).
I don't have enough rep to comment so I'll "answer" regarding Rick Thompson's suggestion for testing infinity.
if (A-1 .eq. A)
This will also be true if A is a very large floating point number, and 1 is below the precision of A.
A simple test:
subroutine test_inf_1(A)
real, intent(in) :: A
print*, "Test (A-1 == A)"
if (A-1 .eq. A) then
print*, " INFINITY!!!"
else
print*, " NOT infinite"
endif
end subroutine
subroutine test_inf_2(A)
real, intent(in) :: A
print*, "Test (A > HUGE(A))"
if (A > HUGE(A)) then
print*, " INFINITY!!!"
else
print*, " NOT infinite"
endif
end subroutine
program test
real :: A,B
A=10
print*, "A = ",A
call test_inf_1(A)
call test_inf_2(A)
print*, ""
A=1e20
print*, "A = ",A
call test_inf_1(A)
call test_inf_2(A)
print*, ""
B=0.0 ! B is necessary to trick gfortran into compiling this
A=1/B
print*, "A = ",A
call test_inf_1(A)
call test_inf_2(A)
print*, ""
end program test
outputs:
A = 10.0000000
Test (A-1 == A)
NOT infinite
Test (A > HUGE(A))
NOT infinite
A = 1.00000002E+20
Test (A-1 == A)
INFINITY!!!
Test (A > HUGE(A))
NOT infinite
A = Infinity
Test (A-1 == A)
INFINITY!!!
Test (A > HUGE(A))
INFINITY!!!
No.
The salient parts of IEEE_ARITHMETIC for generating/checking for NaN's are easy enough to write for gfortran for a particular architecture.
I have used:
PROGRAM MYTEST
USE, INTRINSIC :: IEEE_ARITHMETIC, ONLY: IEEE_IS_FINITE
DOUBLE PRECISION :: number, test
number = 'the expression to test'
test = number/number
IF (IEEE_IS_FINITE(test)) THEN
WRITE(*,*) 'We are OK'
ELSE
WRITE(*,*) 'Got a problem'
END IF
WRITE(*,*) number, test
END PROGRAM MYTEST
This will print 'Got a problem' for number = 0.0D0, 1.0D0/0.0D0, 0.0D0/0.0D0, SQRT(-2.0D0), and also for overflows and underflows such as number = EXP(1.0D800) or number = EXP(-1.0D800). Notice that generally, things like number = EXP(1.0D-800) will just set number = 1.0 and produce a warning at compilation time, but the program will print 'We are OK', which I find acceptable.
OL.
for testing NaN none of the things worked eg.if testing real s2p to see if it is NaN then
if(isnan(s2p))
did not work in gfortran nor did
if(s2p.ne.s2p).
The only thing that worked was
if(.not.s2p<1.and..not.s2p>1)
though to make real sure u may want to add
if(.not.s2p<1.and..not.s2p>1.and..not.s2p==1)
No.
Neither is there a standards-compliant way of checking for infinities or NaNs in Fortran 90/95, nor can there be a standards-compliant way. There is no standards-compliant way of defining either of these quasi-numbers in Fortran 90/95.
For Fortran, 1/infinity=0
thus, divide your variable by zero
i.e
program test
implicit none
real :: res
integer :: i
do i=1,1000000
res=-log((1.+(10**(-real(i))))-1.)
print*,i,res
if ((1./res)==0.) then
exit
end if
end do
end program
there's your infinity check. No complication necessary.
For Inf it seems to work that if (A-1 .eq. A) is true, then A is Inf

Why doesn't this fortran code work?

Hey, I wrote this (fortran) with the aim of finding the minimum spanning tree of a bunch of points (syscount of them). I know for a fact that this approach works, since i wrote it in javascript earlier today. js is slow though, and i wanted to see how much faster fortran would be!!
only problem is it's not working, i'm getting an annoying error;
prims.f95:72.43:
if((check == 1) .and. (path(nodesin(j))(k) < minpath)) then
1
Error: Expected a right parenthesis in expression at (1)
What the hell is that about?! the 43rd character on the line is the "h" of "path"
nodesin(1) = 1
do i = 1,syscount-1
pathstart = -1
pathend = -1
minpath = 2000
do j = 1,i
do k = 1, syscount
check = 1
do l = 1, i
if(nodesin(l) == k) then
check = 0
end if
end do
if((check == 1) .and. (path(nodesin(j))(k) < minpath)) then
minpath = path(nodesin(j))(k)
pathstart = nodesin(j)
pathend = k
end if
end do
end do
nodesin(i+1) = pathend
minpaths(i)(1) = pathstart
minpaths(i)(2) = pathend
end do
Also, i'm fairly new to fortran, so i have a few other questions;
can i use && instead of .and. ?
is there a versions of the for(object in list){} loop found in many other languages?
is there a verion of the php function in_array ? i.e. bool in_array(needle,haystack), and if there is, is there a better way of doing it than:
check = false
Asize = size(array)
do i = 1, Asize
if(array(i) == needle) then
check = true
end if
end do
then to using the check variable to see if it's there?
(I haven't posted anything on stackoverflow before. please don't get angry if i've broken loads of etiquette things!)
It looks like you have defined path and minpaths as two-dimensional arrays. Multi-dimensional arrays are accessed differently in Fortran when compared to C-like languages. In Fortran you separate the indices by commas within one set of parentheses.
I'm guessing by the use of these variables they are integer arrays. Here is how you access elements of those arrays (since you didn't share your variable declarations I am making up the shape of these arrays):
integer :: path(n1, n2)
integer :: minpaths(n3, 2)
your if statement should be:
if((check == 1) .and. (path(nodesin(j), k) < minpath)) then
your access to minpaths should be:
minpaths(i, 1) = pathstart
minpaths(i, 2) = pathend
Also, if you are not using IMPLICIT NONE I recommend you consider it. Not using it is dangerous, and you are using variable names that are close to each other (minpath and minpaths). You could save hours of hair pulling debugging by using IMPLICIT NONE.
While .EQ. can be replaced with ==, there is still only .AND.
For your code block to check whether a "variable is there", you can use "where" and have much shorter code!
In Fortran >= 90 statements and functions can operate on arrays so that explicit loops don't have to be used as frequently.
There is no for (object in list), but using the where statement can do something very similar.
Many of the intrinsic functions that act on arrays also take masks as optional arguments to selectively operate.
I suggest reading a book to learn about these features. I like the one by Metcalf, Reid and Cohen. In the meantime, the second Wikipedia article may help: http://en.wikipedia.org/wiki/Fortran_95_language_features