next up previous index
Next: Control Statements Up: Fortran 90 Tutorial Previous: Language Elements

Expressions and Assignments

 

%The rules for scalar numeric expresions and assignments, as known from FORTRAN 77, are extended to accommodate the non-default kinds we encountered in chapter gif. Thus, the mixed-mode numeric expression and assignment rules incorporate different kind type parameters in an expected way:

             real2 = integer + real1
converts integer 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.

For scalar relational operations, there is a set of new, alternative operators:

             <   <=   ==   /=   >   >=
so we can write expressions such as
        IF (a < b .AND. i /= j) THEN ! for numeric variables
        flag = a == b                ! for logical variable flag

In the case of scalar characters, two old restrictions are lifted. Given

        CHARACTER(8) result
it is now legal to write
        result(3:5) = result(1:3)    ! overlap allowed
        result(3:3) = result(3:2)    ! no assignment of null string

For an operation between derived-data types, or between a derived type and an intrinsic type, we must define the meaning of the operator  . (Between intrinsic types, there are intrinsic operations only.) Given

             TYPE string
                INTEGER       length
                CHARACTER(80) value
             END TYPE string
             CHARACTER    char1, char2, char3
             TYPE(string) str1,  str2,  str3
we can write
             str3  = str1//str2       ! must define operation
             str3  = str1.concat.str2 ! must dedine operation
             char3 = char2//char3     ! intrinsic operator only
             str3  = char1            ! must define assignment
For the first three cases, assignment  applies on a component-by-component basis (but can be overridden), and the first two cases require us to define the exact meaning of the // symbol. We see here the use both of an intrinsic symbol and of a named operator, .concat. . A difference is that, for an intrinsic operator token, the usual precedence rules apply, whereas for named operators  their 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 expresions are equivalent only if appropriate parentheses 

are added as shown. In each case, we have to provide, in a module, procedures defining the operator and assignment, and make the association by an interface  block, also in the module (we shall return to this later).

For the moment, here is an example of an interface for string concatenation

             INTERFACE OPERATOR(//)
                MODULE PROCEDURE string_concat
             END INTERFACE
and an example of part of a module  containing the definitions of character-to-string and string to character assignment. The string concatenation function was shown already in part gif.

MODULE string_type
   TYPE string
      INTEGER length
      CHARACTER(LEN=80)   :: string_data
   END TYPE string
   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 (string), 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 (string), INTENT(IN)     :: s
    CHARACTER(LEN=*), INTENT(OUT) :: c
    c = s%string_data(1:s%length)
    END SUBROUTINE s_to_c_assign
    FUNCTION string_concat(s1, s2)
        :
  END FUNCTION string_concat
END MODULE string_type
 

Defined operators  such as these are required for the expressions that are allowed too in structure constructors (see chapter gif):

 str1 = string(2, char1//char2)  ! structure constructor

So far we have discussed scalar variables. In the case of arrays, 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

   REAL, DIMENSION(10, 20) :: a, b, c
   REAL, DIMENSION(5)      :: v, w
   LOGICAL                    flag(10, 20)
can write
   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.

There are some new real intrinsic functions  that are useful for numeric computations:

        CEILING         FLOOR         MODULO (also integer)
        EXPONENT        FRACTION
        NEAREST         RRSPACING     SPACING
        SCALE           SET_EXPONENT
Like all FORTRAN 77 functions (SIN, ABS, etc., but not LEN), these are array valued for array arguments (i.e. are elemental  ).



next up previous index
Next: Control Statements Up: Fortran 90 Tutorial Previous: Language Elements


Michel Goossens Mon Dec 18 12:34:22 MET 1995