Expressions and assignments#
Scalar numeric#
The usual arithmetic operators are available +, -, *, /, and
** (given here in increasing order of precedence).
Parentheses are used to indicate the order of evaluation where necessary:
a*b + c ! * first
a*(b + c) ! + first
The rules for scalar numeric expressions and assignments accommodate the non-default kinds. Thus, the mixed-mode numeric expression and assignment rules incorporate different kind type parameters in an expected way:
real2 = integer0 + real1
converts integer0 to a real value of the same kind as real1; the
result is of same kind, and is converted to the kind of real2 for
assignment.
These functions are available for controlled rounding of real numbers to integers:
nint: round to nearest integer, return integer resultanint: round to nearest integer, return real resultint: truncate (round towards zero), return integer resultaint: truncate (round towards zero), return real resultceiling: smallest integral value not less than argument (round up) (Fortran-90)floor: largest integral value not greater than argument (round down) (Fortran-90)
Scalar relational operations#
For scalar relational operations of numeric types, there is a set of built-in operators:
< <= == /= > >=
.lt. .le. .eq. .ne. .gt. .ge.
(the forms above are new to Fortran-90, and older equivalent forms are given below them). Example expressions:
a < b .and. i /= j ! for numeric variables
flag = a == b ! for logical variable flags
Scalar characters#
In the case of scalar characters and given character(8) result
it is legal to write
result(3:5) = result(1:3) ! overlap allowed
result(3:3) = result(3:2) ! no assignment of null string
Concatenation is performed by the operator //.
result = 'abcde'//'123'
filename = result//'.dat'
Derived-data types#
No built-in operations (except assignment, defined on component-by component basis) exist between derived data types mutually or with intrinsic types. The meaning of existing or user-specified operators can be (re)defined though:
type string80
integer :: length
character(80) :: value
end type string80
character :: char1, char2, char3
type(string80) :: str1, str2, str3
we can write
str3 = str1//str2 ! must define operation
str3 = str1.concat.str2 ! must define operation
char3 = char2//char3 ! intrinsic operator only
str3 = char1 ! must define assignment
Notice the
"overloaded"
use of the intrinsic symbol // and
the named operator, .concat. . A difference between the two cases is
that, for an intrinsic operator token, the usual precedence rules apply,
whereas for named operators, precedence is the highest as a unary
operator or the lowest as a binary one. In
vector3 = matrix * vector1 + vector2
vector3 =(matrix .times. vector1) + vector2
the two expressions are equivalent only if appropriate parentheses are added as shown. In each case there must be defined, in a module, procedures defining the operator and assignment, and corresponding operator-procedure association, as follows:
interface operator(//) ! Overloads the // operator as
! invoking string_concat procedure
module procedure string_concat
end interface
The string concatenation function is a more elaborated version of that shown already in Basics. Note that in order to handle the error condition that arises when the two strings together exceed the preset 80-character limit, it would be safer to use a subroutine to perform the concatenation (in this case operator-overloading would not be applicable.)
module string_type
implicit none
type string80
integer length
character(len=80) :: string_data
end type string80
interface assignment(=)
module procedure c_to_s_assign, s_to_c_assign
end interface
interface operator(//)
module procedure string_concat
end interface
contains
subroutine c_to_s_assign(s, c)
type(string80), intent(out) :: s
character(LEN=*), intent(in) :: c
s%string_data = c
s%length = len(c)
end subroutine c_to_s_assign
subroutine s_to_c_assign(c, s)
type(string80), intent(in) :: s
character(len=*), intent(out) :: c
c = s%string_data(1:s%length)
end subroutine s_to_c_assign
type(string80) function string_concat(s1, s2)
type(string80), intent(in) :: s1, s2
type(string80) :: s
integer :: n1, n2
character(160) :: ctot
n1 = len_trim(s1%string_data)
n2 = len_trim(s2%string_data)
if (n1 + n2 <= 80) then
s%string_data = s1%string_data(1:n1)//s2%string_data(1:n2)
else ! This is an error condition which should be handled - for now just truncate
ctot = s1%string_data(1:n1)//s2%string_data(1:n2)
s%string_data = ctot(1:80)
end if
s%length = len_trim(s%string_data)
string_concat = s
end function string_concat
end module string_type
program main
use string_type
type(string80) :: s1, s2, s3
call c_to_s_assign(s1, 'My name is')
call c_to_s_assign(s2, ' Linus Torvalds')
s3 = s1//s2
write (*, *) 'Result: ', s3%string_data
write (*, *) 'Length: ', s3%length
end program
Defined operators such as these are required for the expressions that are allowed also in structure constructors (see Derived-data types):
str1 = string(2, char1//char2) ! structure constructor
Arrays#
In the case of arrays then, as long as they are of the same shape (conformable), operations and assignments are extended in an obvious way, on an element-by-element basis. For example, given declarations of
real, dimension(10, 20) :: a, b, c
real, dimension(5) :: v, w
logical :: flag(10, 20)
it can be written:
a = b ! whole array assignment
c = a/b ! whole array division and assignment
c = 0. ! whole array assignment of scalar value
w = v + 1. ! whole array addition to scalar value
w = 5/v + a(1:5, 5) ! array division, and addition to section
flag = a==b ! whole array relational test and assignment
c(1:8, 5:10) = a(2:9, 5:10) + b(1:8, 15:20) ! array section addition and assignment
v(2:5) = v(1:4) ! overlapping section assignment
The order of expression evaluation is not specified in order to allow for optimization on parallel and vector machines. Of course, any operators for arrays of derived type must be defined.
Some real intrinsic functions that are useful for numeric computations are
ceilingfloormodulo(also integer)exponentfractionnearestrrspacingspacingscaleset_exponent
These are array valued for array arguments (elemental), like all
FORTRAN 77
functions (except len):
intrealcmplxaintanintnintabsmodsigndimmaxmin
Powers, logarithms, and trigonometric functions:
sqrtexploglog10sincostanasinacosatanatan2sinhcoshtanh
Complex numbers:
aimagconjg
The following are for characters:
lgelgtllellticharcharindex