SGI Techpubs Library

IRIX 6.5  »  Books  »  Developer  »  
MIPSpro Fortran Language Reference Manual, Volume 1
(document number: 007-3692-006 / published: 2002-11-19)    table of contents  |  additional info  |  download
find in page

Chapter 4. Data Types

Fortran was designed to give scientists and engineers an easy way to solve problems by using computers. Statements could be presented that looked like formulas or English sentences. For example, the following statement might be performing typical numeric calculations:

X = B + A * C

As another example, the following statement could specify that a certain action is to be taken based on a logical decision:

IF (LIMIT_RESULTS .AND. X .GT. XMAX) X = XMAX

And the following statement could be used to communicate the results of a calculation to a scientist or engineer in a meaningful way:

PRINT *, "CONVERGENCE REACHED"

Each of these statements performs a task that uses a different type of data:

Task

Data Type

Calculating typical numeric results

Numeric data

Making decisions

Logical data

Explaining

Character data

The preceding list shows the commonly needed data types, and the Fortran standard provides for them.

The compiler supports additional data types. This preserves compatibility with other vendor's systems. These additional types are as follows:

  • Cray pointer

  • Boolean (or typeless)


Note: The Fortran standard does not specify Cray pointer, Cray character pointer, or Boolean data types.

Anything provided by the language is intrinsic to the language. Types that are not intrinsic to the language can be specified by a programmer. The programmer-specified types are built of (or derived from) the intrinsic types and thus are called derived types. The Fortran data types are categorized in Figure 4-1.

Figure 4-1. Fortran data types

Fortran data types

As the following list shows, the type of the data determines the operations that can be performed on it:

Data Type

Operations

Real, complex, integer, Boolean

Addition, subtraction, multiplication, division, exponentiation, negation, comparison, masking expressions

Logical

Negation, conjunction, disjunction, and equivalence

Character

Concatenation, comparison

User defined

User defined

Cray pointer, Cray character pointer

Addition, subtraction, and LOC( ) function

The intrinsic types have the appropriate built-in (intrinsic) operations. You must define the operations performed on user-defined data types.

This chapter explains the Fortran data types. It describes each of the intrinsic types, and it explains derived types and the facilities provided by the language that allow you to define types and declare and manipulate objects of these types in ways that are analogous to the ways in which objects of the intrinsic types can be manipulated.

4.1. Building the Data Environment for a Problem Solution

When envisioning a computer solution to a problem you focus on the operations that must be performed and the order in which they must be performed. It is a good idea, however, to consider the variables you will need before you determine all the computational steps that are required. The variables that are chosen, together with their types and attributes, sometimes determine the course of computation, particularly when variables of user-defined type are involved.

4.1.1. Choosing the Type and Other Attributes of a Variable

There are several decisions to make about a variable in a program. If the variable is of an intrinsic type, the intended use of the variable will readily determine its type, making this an easy decision. While type is the most important attribute of a variable, there are other attributes. Certainly it is necessary to decide very early whether the variable is to be a single data object (a scalar) or an array. Fortran provides many new facilities for manipulating arrays as objects, making it possible to specify computations as straightforward array operations.

Because Fortran provides allocatable arrays and pointers, it is not necessary to decide at the outset how big an array must be. In fact, determining sizes can be postponed until the finished program is executed, when sizes can be read in as input or calculated. Setting aside space for an array can be deferred until the appropriate size needed for a particular calculation is known.

Another decision that can be made about a variable is its accessibility. Control of accessibility is a feature available in modules. If the variable is needed only within the module, then it can be kept private or hidden from other program units. This prevents it from being corrupted inadvertently. This feature can be used to make Fortran programs safer and more reliable.

In addition to type, dimensionality, dynamic determination, and accessibility, there are other attributes that can be applied to data objects. The attributes that are permitted depend on where and how the object is to be used; for example, there are a number of attributes that can be applied only to subprogram arguments. Chapter 5, “Declarations”, describes all of the attributes of data objects.

4.1.2. Choosing the Kind of a Variable of Intrinsic Type

After the type of a variable is decided, you may need to consider which kind of the type to use. Each of the intrinsic types can be specified with a kind parameter that selects a processor-dependent representation of objects of that type and kind. If no kind parameter is specified, the default kind is assumed.


Note: : Depending on your hardware platform, the compiler may support more than one kind for each data type.

Fortran requires a processor to support at least two kinds for the real and complex types and at least one kind for the other three intrinsic types. The compiler supports several kinds of real, complex, logical, and integer data types.

The Fortran data types are as follows:

  • Real. Programs with REAL and DOUBLE PRECISION declarations are not numerically portable across machine architectures with different word sizes. The compiler chooses a representation for the real type that is efficient on the target machine. For example, a representation that fits into 32 bits is used on machines with 32-bit words, and a representation that fits into 64 bits is used on machines with 64-bit words.

    A kind parameter gives you access to and control over the use of different machine representations of real values in order to make a program more portable. For example, a kind parameter in a REAL declaration can specify a required minimum precision, as follows:

    REAL(KIND=SELECTED_REAL_KIND(10,50)) :: REAL_VALUE

    When a program is run on a 32-bit machine, it uses two words to contain variable REAL_VALUE. When the same program (without any changes) is run on a 64-bit machine, one word is used to contain variable REAL_VALUE.

    Fortran treats double-precision real as a separate kind of real. There are two ways to declare real variables: one is with a REAL statement specifying a nondefault kind and the other is with a DOUBLE PRECISION statement.

  • Complex. Fortran uses a COMPLEX attribute with a nondefault kind parameter to specify double-precision complex.

  • Character. The Fortran standard's kind type parameter values allow a single character to occupy more than one byte. The compiler supports only the ASCII character set, though, so they have no nondefault character kind.

  • Integer. Alternative representations of integer data provide an integer kind with a very large range. The compiler supports several integer kinds.

4.1.3. Choosing to Define a Type for a Variable

Sometimes it is easier to think about an essential element of a problem as several pieces of related data, not necessarily all of the same type. Arrays can be used to collect homogeneous data (all of the same type) into a single variable. A structure is a collection of nonhomogeneous data in a single variable. To declare a structure, it is first necessary to define a type that has components of the desired types. The structure is then declared as an object of this user-defined (or derived) type.

An example of objects declared to be of user-defined type was given in Section 2.3.1 in Chapter 2. It is repeated here. First a type, named PATIENT, is defined. Next, two structures, JOHN_JONES and SALLY_SMITH, are declared:

TYPE PATIENT
   INTEGER         PULSE_RATE
   REAL            TEMPERATURE
   CHARACTER *300  PROGNOSIS
END TYPE PATIENT

TYPE(PATIENT)     JOHN_JONES, SALLY_SMITH

Type PATIENT has three components, each of a different intrinsic type (integer, real, and character). In practice, a type of this nature probably would have even more components, such as the patient's name and address, insurance company, room number in the hospital, and so on. For purposes of illustration, three components are sufficient. JOHN_JONES and SALLY_SMITH are structures (or variables) of type PATIENT. A type definition indicates names, types, and attributes for its components; it does not declare any variables that have these components. Just as with the intrinsic types, a type declaration is needed to declare variables of this type. Because there is a type definition, though, any number of structures can be created that have the components specified in the type definition for PATIENT; subprogram arguments and function results can be of type PATIENT; there can be arrays of type PATIENT; and operations can be defined that manipulate objects of type PATIENT. Thus, the derived-type definition can be used merely as a way to specify a pattern for a particular collection of related but nonhomogeneous data; but, because the pattern is specified by a type definition, a number of other capabilities are available.

4.2. What Is Meant by type in Fortran

Knowing exactly what is meant by type in Fortran becomes more important now that you can define types in addition to the intrinsic types. A data type provides a means to categorize data and determine which operations can be applied to the data to get desired results. The following exist for each data type:

  • A name

  • A set of values

  • A set of operations

  • A form for constants of the intrinsic types and constructors for derived types

4.2.1. Data Type Names

Each of the intrinsic types has a name supplied by the standard. The names of derived types must be supplied in type definitions. The name of the type is used to declare entities of the type unless the programmer chooses to let the processor determine the type of an entity implicitly by the first character of its name. Chapter 5, “Declarations”, describes declarations and implicit typing.

4.2.2. Data Type Values

Each type has a set of valid values. The logical type has only two values: true and false. The integer type has a set of integral numeric values that can be positive, negative, or zero. For complex or derived types, the set of valid values is the set of all combinations of the values of the individual components.

The kind of an intrinsic type determines the set of valid values for that type and kind. For example, there is more than one integer data type: the default type and shorter integer types. The shorter integer types have values that are a subset of the default integer values. The kind of a type is referred to as a kind parameter or kind type parameter of the type. The character data type has a length parameter as well as a kind parameter. The length parameter specifies the number of characters in an object, and this determines the valid values for a particular character object. Derived types do not have parameters, even though their components may.

4.2.3. Data Type Operations

For each of the intrinsic data types, a set of operations with corresponding operators is provided by the language. These are described in Chapter 7, “Expressions and Assignments”.

You can specify new operators and define operations for the new operators. The form of a new operator is an alphabetic name of your choice delimited by periods. These new operators are analogous to intrinsic operators such as .GT., .AND., and .NEQV. . For example, you might specify and define the operations .PLUS., .REMAINDER., and .REVERSE.. In defining the operation, the types of allowable operands must be specified. Such new operations can apply to objects of intrinsic type and in these cases extend the set of operations for the type. You would more frequently be defining operations for objects of derived type.

You cannot redefine an intrinsic operation, but you can define meanings for intrinsic operator symbols when at least one operand is not of an intrinsic type or for intrinsic operands for which the intrinsic operation does not apply. For example, consider the expression A + B. If both A and B are of numeric type, the operation is defined intrinsically and cannot be redefined. However, if either A or B is of derived type or nonnumeric type, the plus operation between A and B is not defined intrinsically, and you can provide a meaning for the operation. New operations are defined by functions with the OPERATOR interface. These are described in the MIPSpro Fortran Language Reference Manual, Volume 2.

Assignment is defined intrinsically for each intrinsic and derived type. Structure assignment is component-by-component intrinsic or pointer assignment, though this can be replaced by a defined assignment. No other intrinsically defined assignment, including array assignment, can be redefined. Beyond this, any assignment between objects of different type may be defined with the ASSIGNMENT interface as described in the MIPSpro Fortran Language Reference Manual, Volume 2.

4.2.4. Forms for Constants and Constructors

The language specifies the syntactic forms for literal constants of each of the intrinsic types. Syntactic mechanisms (called derived-type constructors) specify derived-type values. As shown in Figure 4-2, the form indicates both the type and a particular member of the set of valid values for the type.

Figure 4-2. Forms of constants and constructors

Forms of constants and constructors

If a constant is not of default kind, some indication of its kind must be included in its syntactic form. This form is the default literal constant separated from the kind value by an underscore. Kind specifications follow integer, real, and logical values. Kinds are known to the compiler as integer values, but if a program is to be portable, the actual numbers should not be used because the kind values depend on the processor. Instead, a kind value should be assigned to a named constant, and you should use the name.

In the following examples, DOUBLE and HIGH are named constants for kind values:

Real 

1.3141592653589_DOUBLE

Complex 

(1.75963_HIGH, -2.0)

The kind of a complex constant is determined by the kind of its parts. Section 4.3.3.3, describes the form for complex literal constants.

4.3. Intrinsic Data Types

The default real kind, default integer kind, and default logical kind are all stored in one storage unit. Default complex (which is really two default reals) and double-precision real data is stored in two storage units.


Note: : This chapter describes each of the intrinsic types. The descriptions include a simple statement form to show how objects of these types can be declared. These simple forms are not complete. If they are used to construct statements, the statements will be correct, but other variations are permitted. Section 5.1 in Chapter 5, contains the complete formats. The kind parameter that appears in the formats is limited to a scalar integer initialization expression, which is described in Section 7.2.9.2 in Chapter 7.


4.3.1. Integer Type

The name of the integer type is INTEGER. The following format shows how integer objects can be declared:

INTEGER [ ([ KIND = ] kind_param) ] [ [ , attribute_list ] :: ] entity_list

Examples:

INTEGER :: X
INTEGER :: COUNT, K, TEMPORARY_COUNT
INTEGER(SHORT) :: PARTS
INTEGER, DIMENSION(0:9) :: SELECTORS, IX

4.3.1.1. Values

The integer data type has values that represent a subset of the mathematical integers. The intrinsic inquiry function RANGE provides the decimal exponent range for integers of the kind of its argument. Only one kind of integer is required by the standard, but the compiler supports several. Values that overflow in storage may be truncated.

If kind_param is specified, it must have one of the following values: 1, 2, 4, or 8. The default kind_param is specific to your hardware platform. These values are shown in Table 4-1. Options to the f90 (1) command allow you to change the size and storage aspects of integer values. See theMIPSpro Fortran 90 Commands and Directives Reference Manual, for information on changing default kind parameter values.

Table 4-1. Integer kind values

kind_param

Value range

Size / Storage

1

-27 n < 27

8 bits / 8 bits

2

-215 n < 215

16 bits / 16 bits

4 (default)

-231 n < 231

32 bits / 32 bits

8

-263 n < 263

64 bits / 64 bits

In Table 4-1, the Size information refers to the size according to the integer model defined on the MODELS(3i) man page.

Table 4-2, shows power-of-10 values that approximate the power-of-2 values shown in Table 4-1.

Table 4-2. Exponent equivalents

2 n

10k

27

102

215

104

231

109

245

1013

252

1015

263

1018

The RANGE(3i) intrinsic function returns the decimal exponent range of a given number. For more information on this intrinsic function, see the RANGE(3i) man page.

The KIND(3i) intrinsic function can be used to determine the kind parameter of its integer argument.

The SELECTED_INT_KIND(3i) intrinsic function returns the integer kind parameter required to represent as many decimal digits as are specified by the function argument. If there is no such integer type available on your system, -1 is returned.

The following statement declares I and J to be integer objects with a representation method that permits at least five decimal digits; that is, it includes all integers between -10 5 and 105:

INTEGER (SELECTED_INT_KIND (5)) I, J

4.3.1.2. Operators

There are both binary and unary intrinsic operators for the integer type. Binary operators have two operands and unary operators have only one. The binary arithmetic operations for the integer type are: +, -, *, /, and **. The unary arithmetic operations are + and -. The relational operations (all binary) are: .LT., <, .LE., <=, .EQ., ==, .NE., /=, .GE., >=, .GT., and >. The result of an intrinsic arithmetic operation on integer operands is an integer entity. The result of an intrinsic relational operation is a logical entity of default logical kind.

4.3.1.3. Format for Constant Values

An integer constant is a string of decimal digits, optionally preceded by a sign, and optionally followed by an underscore and a kind parameter. An integer constant that must not have a kind type parameter is defined as follows:

 

signed_digit_string

is

[ sign ] digit_string

 

digit_string

is

digit   [ digit ]...

The format of a signed integer literal constant (which may have a kind type parameter) is defined as follows:

 

signed_int_literal_constant

is

[ sign ] int_literal_constant

 

int_literal_constant

is

digit_string [ _ kind_param ]

 

kind_param

is

digit_string

 

 

or

scalar_int_constant_name

 

sign

is

+

 

 

or

-

The signed integer literal constant often takes the following format:

[ sign ] digit_string [ _ kind_param ]

In the following examples, assume that LONG and SHORT are named constants with values that are valid integer kind parameters:

42
9999999999999999999999_LONG
+64
10000000
-258_SHORT

Integer constants are interpreted as decimal values. However, in a DATA statement, it is possible to initialize an object with a value that is presented as if it had a nondecimal base. The allowed forms are unsigned binary, octal, and hexadecimal constants, and are defined as follows:

 

boz_literal_constant

is

binary_constant

 

 

or

octal_constant

 

 

or

hex_constant

The compiler supports binary, octal, and hexadecimal constants in other contexts; for more information on these forms see Section 4.3.6.

A binary_constant is defined as follows:

 

binary_constant

is

B ' digit [ digit ] ... '

 

 

or

B " digit [ digit ] ... "

You must specify 0 or 1 for digit.

An octal_constant is defined as follows:

 

octal_constant

is

O ' digit [ digit ] ... '

 

 

or

O " digit [ digit ] ... "

You must specify a value from 0 through 7 for digit.

A hex_constant is defined as follows:

 

hex_constant

is

Z' hex_digit [ hex_digit ] ...'

 

 

or

Z " hex_digit [ hex_digit ] ... "

 

hex_digit

is

digit

 

 

or

A

 

 

or

B

 

 

or

C

 

 

or

D

 

 

or

E

 

 

or

F

You must specify a value from 0 through 9 or one of the letters A through F (representing the decimal values 10 through 15) for digit. The compiler supports lowercase letters, so the hexadecimal digits A through F can be represented by their lowercase equivalents, a through f.

In these constants, the binary, octal, and hexadecimal digits are interpreted according to their respective number systems. For example, all of the following have a value equal to the decimal value 10:

B"1010"
O'12'
Z"A"

4.3.2. Real Type

The name of the real data type is REAL. The name DOUBLE PRECISION is used for another kind of the real type. You can use one of the following formats to declare objects of real type:

REAL [ ([ KIND = ] kind_param) ] [ [ , attribute_list ] :: ] entity_list
DOUBLE PRECISION [ [ , attribute_list] :: ] entity_list

Examples:

REAL X, Y
REAL(KIND = HIGH), SAVE :: XY(10, 10)
REAL, POINTER :: A, B, C
DOUBLE PRECISION DD, DXY, D

4.3.2.1. Values

The values of the real data type approximate the mathematical real numbers. The set of values varies from processor to processor. The Fortran standard requires a processor to support at least two approximation methods for the real type. The compiler provides three, so there are three kind values for the real type.

If kind_param is specified, it must have one of the following values: 4, 8, or 16. The default kind_param and the values associated with the kind values are specific to your hardware platform. These values are shown in Table 4-3. Options to the f90(1) command allow you to change the size and storage aspects of real values. See the MIPSpro Fortran 90 Commands and Directives Reference Manual for information on changing default kind parameter values.

Table 4-3. Real and complex kind values

kind_param

Value range

Size and Storage

Operating system

4 (default)

2 -125 n < 2 128

32 bits

IRIX

8

2 -1021 n < 2 1024

64 bits

IRIX

16

2 -967 n < 2 1023

128 bits

IRIX

Table 4-4, shows power-of-10 values that approximate some of the power-of-2 values shown in Table 4-3.

Table 4-4. Exponent equivalents

2 n

10k

2128

1038

21024

10308

28189

102466

216384

104932

The KIND(3i) intrinsic function can be used to determine the kind parameter of its real argument. The intrinsic functions PRECISION(3i) and RANGE(3i) return the decimal precision and exponent range of the approximation method used for the kind of the argument. The intrinsic function SELECTED_REAL_KIND(3i) returns the kind value required to represent as many digits of precision as specified by the first argument and the decimal range specified by the optional second argument.

The following statement declares X to have at least five decimal digits of precision and no specified minimum range:

REAL(SELECTED_REAL_KIND(5)) X

The following statement declares Y to have at least eight decimal digits of precision and a range that includes values between 10-70 and 1070 in magnitude:

REAL(SELECTED_REAL_KIND(8, 70)) Y

4.3.2.2. Operators

The intrinsic binary arithmetic operators for the real type are: +, -, *, /, and **. The intrinsic unary arithmetic operators are: + and -. The relational operators are: .LT., <, .LE., <=, .EQ., ==, .NE., /=, .GE., >=, .GT., >, .LG. , and <>. The result of an intrinsic arithmetic operation on real operands is a real entity. If one of the operands of an arithmetic operation is an integer entity, the result is still a real entity. The result of an intrinsic relational operation is a logical entity of default logical kind.


Note: The Fortran standard does not describe the .LG. or <> operators.


4.3.2.3. Forms for Constants

A real constant is distinguished from an integer constant by containing either a decimal point, an exponent, or both. The format for a signed_real_literal_constant is defined as follows:

 

signed_real_literal_constant

is

[ sign ] real_literal_constant

 

real_literal_constant

is

significand exponent_letter exponent [ _kind_param]

 

 

or

digit_string exponent_letter exponent [ _kind_param ]

 

significand

is

digit_string . [ digit_string ]

 

 

or

. digit_string

 

exponent_letter

is

E

 

 

or

D

 

 

or

Q

 

exponent

is

signed_digit_string

A signed real literal constant can take one of the following forms:

[ sign ] digit_string exponent_letter exponent [ _kind_param ]
[ sign ] whole_part . [ fraction_part ] [ exponent_letter exponent ]
[ _kind_param ]
[ sign ] . fraction_part [ exponent_letter exponent ] [ _kind_param ]

For whole_part, specify a digit_string . For fraction_part, specify a digit_string. For exponent, specify a signed_digit_string.

If both a kind_param and an exponent_letter are present, the exponent_letter must be E or e. If a kind_param is present, the real constant is of that kind; if a D or d exponent letter is present, the constant is of type double-precision real; if a Q exponent is present, the constant is of type quad-precision real; otherwise, the constant is of type default real.

A real constant can have more decimal digits than will be used to approximate the real number.

Examples of signed real literal constants are as follows:

-14.78
+1.6E3
2.1
-16.E4_HIGH
0.45_LOW
.123
3E4
2.718281828459045D0

In the preceding example, the parameters HIGH and LOW must have been defined, and their values must be kind parameters for the real data type permitted by the compiler.

If a real literal constant has a kind parameter, it takes precedence over an exponent letter. Consider the following specification:

1.6E4_HIGH

The example's code fragment will be represented by the method specified for HIGH, even though 1.6E4 would be represented by a different method.

4.3.3. Complex Type

The name of the complex type is COMPLEX. A format for declaring objects of this type is as follows:

COMPLEX [([ KIND = ] kind_param) ] [[ , attribute_list ] :: ] entity_list

Examples:

COMPLEX CC, DD
COMPLEX(KIND = single), POINTER :: CTEMP(:)

4.3.3.1. Values

The complex data type has values that approximate the mathematical complex numbers. A complex value is a pair of real values; the first is called the real part and the second is called the imaginary part. Each approximation method used to represent data entities of type real is available for entities of type complex with the same kind parameter values. Therefore, there are three approximation methods for complex.

When a complex entity is declared with a kind specification, this kind is used for both parts of the complex entity. There is no special double-precision complex declaration, as such. If no kind parameter is specified, the entity is of type default complex which corresponds to default real. The SELECTED_REAL_KIND(3i) intrinsic function may be used in a declaration of a complex object.

If kind_param is specified, it must have one of the following values: 4, 8, or 16. The default kind is specific to your hardware platform. The values, the ranges (for both the real and imaginary portions of the number), and the defaults supported are the same as those for type real, and these values are shown in Table 4-3. See the MIPSpro Fortran 90 Commands and Directives Reference Manual for information on changing default kind parameter values.

For information on power-of-10 and power-of-2 equivalent values, see Table 4-4.

In the following statement, CX must be represented by an approximation method with at least 8 decimal digits of precision and at least a decimal exponent range between 10-70 and 1070 in magnitude for the real and imaginary parts:

COMPLEX(SELECTED_REAL_KIND(8, 70)) CX

4.3.3.2. Operators

The intrinsic binary arithmetic operators for the complex type are: +, -, * , /, and **. The intrinsic unary arithmetic operators are: + and -. The intrinsic relational operators are: .EQ., ==, .NE., and /=. The arithmetic operators specify complex arithmetic; the relationals compare operands to produce default logical results. The result of an intrinsic arithmetic operation on complex operands is a complex entity. If one of the operands is an integer or real entity, the result is still a complex entity.

4.3.3.3. Form for Constants

A complex literal constant is written as two literal constants that are real or integer, separated by a comma, and enclosed in parentheses, as follows:

(real_part , imag_part)

The compiler allows the real and imaginary portions of a complex literal constant to be named constants.


Note: The Fortran standard does not specify the use of named constants as the real or imaginary components of a complex literal constant.

The format for a complex_literal_constant is defined as follows:

 

complex_literal_constant

is

(real_part , imag_part)

 

real_part

is

signed_int_literal_constant

 

 

or

signed_real_literal_constant

 

imag_part

is

signed_int_literal_constant

 

 

or

signed_real_literal_constant

Examples:

(3.0, -3.0)
(6, -7.6E9)
(3.0_HIGH, 1.6E9_LOW)

A real kind parameter can be specified for either one of the two real values. If a different real kind parameter is given for each of the two real values, the complex value will have the kind parameter that specifies the greater precision, unless the kind parameters specify the same precision. If both parts are integer, each part is converted to default real. If one part is of integer type and the other is of real type, the integer value is converted to the kind and type of the real value.

4.3.4. Logical Type

The name of the logical type is LOGICAL. A format for declaring objects to be of this type is as follows:

LOGICAL [([ KIND = ] kind_param) ] [[ , attribute_list ] :: ] entity_list

Examples:

LOGICAL IR, XT
LOGICAL(KIND = SMALL), SAVE :: XMASK (3000)

4.3.4.1. Values

The logical data type has two values that represent true and false. The Fortran standard requires processors to provide one logical kind, but the compiler provides other kinds. Each logical item occupies one word. (An object of default logical type must occupy the same unit of storage as an object of default real type.) The KIND(3i) intrinsic function can be used to determine the kind number of its argument. There is no intrinsic function analogous to the functions SELECTED_INT_KIND(3i) and SELECTED_REAL_KIND(3i).

If specifying a kind_param, it must have one of the following values: 1, 2, 4, or 8. The default kind_param and the values associated with the kind values are specific to your hardware platform. These values are shown in Table 4-5. See the MIPSpro Fortran 90 Commands and Directives Reference Manual for information on changing default kind parameter values.

Table 4-5. Logical kind values

kind_param

Size / Storage

Operating system

1

8 bits / 8 bits

IRIX

2

16 bits / 16 bits

IRIX

4 (default)

32 bits / 32 bits

IRIX

8

64 bits / 64 bits

IRIX


4.3.4.2. Operators

The intrinsic binary operators for the logical type are as follows: conjunction (.AND.), inclusive disjunction (.OR.), logical equivalence (.EQV.), and logical nonequivalence (.NEQV.). The intrinsic unary operation is negation (.NOT.). The exclusive disjunction operator for the compiler is .XOR.


Note: The Fortran standard does not specify the .XOR. exclusive disjunction operator.


4.3.4.3. Form for Constants

There are only two logical literal constants. They can be followed by an underscore and a kind parameter. The format for a logical_literal_constant is defined as follows:

 

logical_literal_constant

is

.TRUE. [ _kind_param ]

 

 

or

.FALSE. [ _ kind_param ]

If a kind_param is not specified, the type of the constant is default logical. Examples are as follows:

FALSE.
TRUE._WORD

If .T. and .F. are not defined operators in a compilation unit, the compiler recognizes .T. as an abbreviation for .TRUE. and .F. for .FALSE.


Note: The Fortran standard does not specify the use of .T. or .F..


4.3.5. Character Type

The name of the character type is CHARACTER. Declarations for objects of this type may take several different forms. One of these forms is as follows:

CHARACTER [ ([ LEN = ] length_parameter [, [ KIND = ] kind_param ]) ]
[ [ , attribute_list ] :: ] entity_list

The length_parameter can be an asterisk ( *) or a specification expression, which is described in Section 7.2.9.3 in Chapter 7. The various forms of the CHARACTER statement are described in Section 5.1.6 in Chapter 5, but the following examples use the form specified previously:

CHARACTER(80) LINE
CHARACTER(*) GREETING
CHARACTER(LEN = 30, KIND = ASCII), DIMENSION(10) :: C1

4.3.5.1. Values

The character data type has a set of values composed of character strings. A character string is a sequence of characters, numbered from left to right 1, 2, ..., n, where n is the length of (number of characters in) the string. Both length and kind are type parameters for the character type. If no length parameter is specified, the length is 1. A character string can have length 0. The maximum length permitted for character strings is 2, 097, 151. Although the Fortran standard permits a processor to provide more than one character kind, the compiler supports only one, ASCII. Thus, the compiler does not support any nondefault character kinds. If kind_param is specified, it must have the value 1.

The Fortran standard specifies only a partial collating sequence because it is concerned only that operations that compare character objects containing only characters from the Fortran character set will be portable across different processors. Because the compiler supports the ASCII character set, they follow the Fortran standard's collating requirements. The intrinsic functions ACHAR(3i) and IACHAR(3i) convert between numeric values and ASCII characters. The intrinsic functions LGT(3i), LGE(3i), LLE(3i), and LLT(3i) provide comparisons between strings based on the ASCII collating sequence.

4.3.5.2. Operators

The binary operation concatenation (//) is the only intrinsic operation on character entities and has a character entity as a result. A number of intrinsic functions are provided that perform character operations. These are described in the MIPSpro Fortran Language Reference Manual, Volume 2. The intrinsic relational operators on objects of type character are .LT., <, .LE., <=, .EQ., ==, .NE., /=, .GE., >=, .GT., and >. The relational operations can be used to compare character entities, but because of possible processor-dependent collating sequences, care must be taken if the results are intended to be portable.

4.3.5.3. Form for Constants

A character literal constant is written as a sequence of characters, enclosed either by apostrophes or quotation marks. The format for a char_literal_constant is as follows:

 

char_literal_constant

is

[kind_param _ ] ' [ ASCII_char ] ... '

 

 

or

[ kind_param _ ] " [ ASCII_char ] ... "

Note that, unlike the other intrinsic types, the kind parameter for the character literal constant precedes the constant.

If the string delimiter character (either an apostrophe or a quotation mark) is required as part of the constant, two consecutive such characters with no intervening blanks serve to represent a single such character in the string, for example:

"DON'T"
'DON''T'

These two examples have the value DON'T. A zero-length character constant can be written as "" or '' . The quotation marks or apostrophes are immediately adjacent to each other.

4.3.6. Boolean Type (EXTENSION)

A Boolean constant represents the literal constent of a single storage unit. There are no Boolean variables or arrays, and there is no Boolean type statement.


Note: The Fortran standard does not describe Boolean values.

Boolean type differs, depending on your platform, as follows:

  • A bitwise logical expression has an integer result, with each of its bits representing the result of one or more logical operations on the corresponding bit of the expression's operands. When an operand of a binary arithmetic or relational operator is Boolean, the operation is performed as if the Boolean operand is of type integer. If both operands are of type Boolean, the operation is performed as if they were of type integer.

    No user-specified or intrinsic functions generate Boolean results.

Boolean and logical types differ in the following ways:

  • Variables, arrays, and functions can be of logical type, and there is a LOGICAL type statement.

  • A logical variable or constant represents only one value of true or false (rather than separate bit values), and a logical expression yields one true or false value.

  • Logical entities are invalid in arithmetic, relational, or bitwise logical expressions, while Boolean entities are valid. (Note, however, that results of relational expressions are logical.)

A Boolean constant can be written as an octal, hexadecimal, or Hollerith value. There is no form for binary digits. Boolean constants can represent up to 256 bits of data. This size limit corresponds to the size of the largest numeric type, COMPLEX(KIND = 16). The ultimate size and make-up of the constant is dependent on its context. The constant is truncated or padded to match the size of the type implied by its context. These forms use the notation described in the following sections.

4.3.6.1. Octal Form

The octal form contains 1 to 86 digits (0 through 7) in either of the following two forms:

  • It can be a string of digits followed by the letter B or b, as in 177B.

  • It can be a quoted string of digits followed by the letter O or o, as in "177"O.

  • It can be a quoted string of digits preceded by the letter O or o, as in O"177".

The 86 digits in a Boolean value correspond to the internal representation of four 64-bit words or eight 32-bit words. If all 86 digits are specified, the leftmost octal digit must be only 0 or 1, representing the content of the leftmost bit position (bit 0 in the first word) of the value. Each successive octal digit specifies the contents of the next three bit positions. The last octal digit specifies the content of the rightmost three bit positions, which are bits 61, 62, and 63 of the last (fourth or eighth) word. Blanks are ignored in fixed source form. Blanks are significant in free source form for the dddB syntax. That is, 1 777B would not be treated as a single value in free source form, and it would most likely result in a syntax error message.

A Boolean value represented by fewer than 86 octal digits is right justified; that is, it represents the rightmost bits of 256 bits.

When context is taken into account, the value is truncated on the left if it is too large for the context type. It is padded with 0 on the left if it is too small for the context type.


Note: : For a literal constant, the letter B indicates octal digits; in an I/O format specification, the B descriptor indicates binary digits.

Examples:

Boolean constant 

Internal representation (octal) for a 64-bit word

0B 

0000000000000000000000

77740B 

0000000000000000077740

Statement example:

I = 1357B

4.3.6.2. Hexadecimal Form

The hexadecimal form consists of 1 to 64 hexadecimal digits consisting of 0 through 9, A through F, or a through f in either of the following two forms:

  • It can be specified as the letter X or x followed by a string of hexadecimal digits enclosed in apostrophes or quotations marks, as in X"FFF".

  • It can be specified with the X or x trailing the quoted string of digits, as in "FFF"X.

When a Boolean value contains 64 hexadecimal digits, the binary equivalents correspond to the content of each bit position in 4 64-bit words or eight 32-bit words.

A Boolean value represented by fewer than 64 hexadecimal digits is right justified; that is, it represents the rightmost bits of 256 bits.

An optional unary minus sign (-) is allowed within the quoted string.

When context is taken into account, the value is truncated on the left if it is too large for the context type. It is padded with 0 on the left if it is too small for the context type.

Examples:

Boolean constant 

Internal representation (octal) for a 64-bit word

X'ABE' 

0000000000000000005276

X"-340" 

1777777777777777776300

X'1 2 3' 

0000000000000000000443

X'FFFFFFFFFFFFFFFF' 

1777777777777777777777

Statement examples:

J = X"28FF"
K = X'-5A'

4.3.6.3. Hollerith Form

A Hollerith constant is type Boolean. When a character constant is used in a bitwise logical expression, the expression is evaluated as if the value were Hollerith. A Hollerith constant can have a maximum of 32 characters.

When context is taken into account, the truncation or padding depends on the type of Hollerith syntax used.

For Hollerith using the letter H, the value is truncated on the right if it is too large for the context type. It is padded with blanks on the right if it is too small for the context type.

For Hollerith using the letter L, the value is truncated on the right if it is too large for the context type. It is padded with 0 on the right if it is too small for the context type.

For Hollerith using the letter R, an error occurs on IRIX systems if the Hollerith constant is greater than 4 characters.

4.3.7. Cray Pointer Type (EXTENSION)

A Cray pointer is a variable whose value is the address of another entity, which is called a pointee. The Cray pointer type statement declares both the pointer and its pointee.


Note: The Fortran standard does not describe Cray pointer values.

Cray pointers are declared as follows:

POINTER (pointer, pointee)

Fortran pointers are declared as follows:

POINTER :: [ object_name ]

The two kinds of pointers cannot be mixed.

You can use pointers to access user-managed storage by dynamically associating variables and arrays to particular locations in a block of storage. Cray pointers do not provide convenient manipulation of linked lists because, for optimization purposes, it is assumed that no two pointers have the same value. Cray pointers also allow the accessing of absolute memory locations.

The range of a Cray pointer or Cray character pointer depends on the size of memory for the machine in use.

Restrictions on Cray pointers are as follows:

  • A Cray pointer cannot be pointed to by another Cray or Fortran pointer; that is, a Cray pointer cannot also be a pointee or a target.

  • A Cray pointer cannot appear in a PARAMETER statement or in a type declaration statement that includes the PARAMETER attribute.

  • A Cray pointer variable cannot be declared to be of any other data type.

  • A Cray character pointer cannot appear in a DATA statement.

  • An array of Cray pointers is not allowed.

  • A Cray pointer cannot be a component of a structure.

Restrictions on Cray pointees are as follows:

  • A Cray pointee cannot appear in a SAVE, DATA, EQUIVALENCE, COMMON, AUTOMATIC, or PARAMETER statement.

  • A Cray pointee cannot be a dummy argument; that is, it cannot appear in a FUNCTION, SUBROUTINE, or ENTRY statement.

  • A function value cannot be a Cray pointee.

  • A Cray pointee cannot be a structure component.


Note: : Cray pointees can be of type character, but their Cray pointers are different from other Cray pointers; the two kinds cannot be mixed in the same expression.

The Cray pointer is a variable of type Cray pointer and can appear in a COMMON list or be a dummy argument in a subprogram.

The Cray pointee does not have an address until the value of the Cray pointer is defined; the pointee is stored starting at the location specified by the pointer. Any change in the value of a Cray pointer causes subsequent references to the corresponding pointee to refer to the new location.

Cray pointers can be assigned values in the following ways:

  • A Cray pointer can be set as an absolute address. For example:

    Q = 0

  • Cray pointers can have integer expressions added to or subtracted from them and can be assigned to or from integer variables. For example:

    P = Q + 100

However, Cray pointers are not integers. For example, assigning a Cray pointer to a real variable is not allowed.

The (nonstandard) LOC(3i) intrinsic function generates the address of a variable and can be used to define a Cray pointer, as follows:

P = LOC(X)

The following example uses Cray pointers in the ways just described:

SUBROUTINE SUB(N)
COMMON POOL(100000), WORDS(1000)
INTEGER BLK(128), WORD64
REAL A(1000), B(N), C(100000-N-1000)
POINTER(PBLK,BLK), (IA,A), (IB,B), &
      (IC,C), (ADDRESS,WORD64)
ADDRESS = LOC(WORDS) + 64
PBLK = LOC(WORDS)
IA = LOC(POOL)
IB = IA + 1000
IC = IB + N

BLK is an array that is another name for the first 128 words of array WORDS. A is an array of length 1000; it is another name for the first 1000 elements of POOL. B follows A and is of length N. C follows B. A, B, and C are associated with POOL. WORD64 is the same as BLK(17) because Cray pointers are byte addresses and the INTEGER elements of array BLK are each 4 bytes long.

If a pointee is of a noncharacter data type that is one machine word or longer, the address stored in a pointer is a word address. If the pointee is of type character or of a data type that is less than one word, the address is a byte address. The following example also uses Cray pointers:

PROGRAM TEST
CHARACTER X(10), Y(10), A(10)
POINTER (P,X), (Q,Y)

P = LOC(A(1))
Q = LOC(A(2))
I = P
J = Q

IF ( (J-I) .NE. (Q-P) )  THEN
   PRINT *, 'Not a byte addressable machine'
ELSE
   PRINT *, 'Byte addressable machine'
ENDIF
END

For purposes of optimization, the compiler assumes that the storage of a pointee is never overlaid on the storage of another variable; that is, it assumes that a pointee is not associated with another variable or array. This kind of association occurs when a Cray pointer has two pointees, or when two Cray pointers are given the same value. Although these practices are sometimes used deliberately (such as for equivalencing arrays), results can differ depending on whether optimization is turned on or off. You are responsible for preventing such association. For example:

POINTER(P,B), (P,C)
REAL X, B, C
P = LOC(X)
B = 1.0
C = 2.0
PRINT *, B

Because B and C have the same pointer, the assignment of 2.0 to C gives the same value to B; therefore, B will print as 2.0 even though it was assigned 1.0.

As with a variable in common storage, a pointee, pointer, or argument to a LOC(3i) intrinsic function is stored in memory before a call to an external procedure and is read out of memory at its next reference. The variable is also stored before a RETURN or END statement of a subprogram.

4.4. Derived Types

Unlike the intrinsic types that are defined by the language, you must define derived types. These types have the same utility as the intrinsic types. For example, variables of these types can be declared, passed as procedure arguments, and returned as function results.

A derived-type definition specifies a name for the type; this name is used to declare objects of the type. A derived-type definition also specifies components of the type, of which there must be at least one. A component can be of intrinsic or derived type; if it is of derived type, it can be resolved into components, called ultimate components. These ultimate components are of intrinsic type and can be pointers.

The direct components of a derived type are as follows:

  • The components of the type

  • For any nonpointer component that is of a derived type, the direct components of that derived type.

If the type definition appears in a module, the type definition may contain the keywords PUBLIC or PRIVATE. Generally, entities specified in a module can be kept private to the module and will not be available outside the module. This is true of data objects, module subprograms, and type definitions. By default, entities specified in a module are available to any program unit that accesses the module; that is, they have PUBLIC accessibility by default. This default can be changed by inserting a PRIVATE statement ahead of the specifications and definitions in the module. Individual entities can be specified to have either the PUBLIC or PRIVATE attribute regardless of the default. For a type definition, this can be accomplished by a PUBLIC or PRIVATE specifier in the TYPE statement of the type definition. The keyword PRIVATE can be used in two ways in type definitions in a module. One way makes the entire type private to the module; the other way allows the type name to be known outside the module, but not the names or attributes of its components. A separate PRIVATE statement that mentions the type name or a PRIVATE specifier in the TYPE statement of the type definition provides the first of these. An optional PRIVATE statement inside the type definition provides the second. See Section 4.4.1, for examples of a private type and a public type with private components.

A type definition can contain a SEQUENCE statement. The Fortran standard allows a processor to rearrange the components of a derived type in any convenient order. However, if a SEQUENCE statement appears inside the type definition, the type is considered to be a sequence type. In this case, the processor must allocate storage for the components in the declared order so that structures declared to be of the derived type can appear in COMMON and EQUIVALENCE statements. See Section 4.4.1, for an example of a sequence type.

Default initialization is specified for a component of an object of derived type when initialization appears in the component declaration. The object is initialized as specified in the derived type definition even if the definition is private or inaccessible. Default initialization applies to dummy arguments with INTENT (OUT) and function return values. Unlike explicit initialization, default initialization does not imply that the object has the SAVE attribute. If a component has default initialization, it is not required that default initialization be specified for other components of the derived type.

A derived type has a set of values that is every combination of the permitted values for the components of the type. The language provides a syntax for constants of the intrinsic types; it provides a somewhat similar mechanism, called a structure constructor , to specify a value for a derived type. A constructor can be used in the following places:

  • In PARAMETER statements and in type declaration statements to define derived-type named constants

  • In DATA statements to specify initial values

  • As structure-valued operands in expressions

User-defined functions and subroutines must be used to define operations on entities of derived type. Thus, the four properties of the intrinsic types (possession of a name, a set of values, a set of operations, and a syntactic mechanism to specify constant values) are also provided for derived types.

4.4.1. Derived Type Definition

A derived type definition gives a derived type a name and specifies the types and attributes of its components. A derived type definition begins with a TYPE statement, ends with an END TYPE statement, and has component declarations in between. The following example defines type PATIENT:

TYPE PATIENT
   INTEGER          PULSE_RATE
   REAL             TEMPERATURE
   CHARACTER*(300)    PROGNOSIS
END TYPE PATIENT

The format of a derived_type_def is as follows:

TYPE [ [, access_spec ] :: ] type_name
[ private_sequence_stmt ] ...
component_def_stmt
[ component_def_stmt ] ...
END TYPE [ type_name ]

A derived-type definition is defined as follows:

 

derived_type_def

is

derived_type_stmt
  [ private_sequence_stmt ] ...
  component_def_stmt
  [ component_def_stmt ] ...
end_type_stmt

 

private_sequence_stmt

is

PRIVATE

 

 

or

SEQUENCE

 

derived_type_stmt

is

TYPE [ [ , access_spec ] :: ] type_name

 

end_type_stmt

is

END TYPE [ type_name ]

 

component_def_stmt

is

type_spec [ [ , component_attr_spec_list ] :: ]  component_decl_list

 

component_attr_spec

is

POINTER

 

 

or

DIMENSION (component_array_spec)

 

component_array_spec

is

explicit_shape_spec_list

 

 

or

deferred_shape_spec_list

 

component_decl

is

component_name [(component_array_spec)] [* char_length ]
   [ component_initialization ]

For access_spec, specify either PRIVATE or PUBLIC.

The component_array_spec must be a deferred-shape array if the POINTER attribute is present; otherwise, it must be an explicit-shape array.

The name of the derived type must not be the same as any intrinsic type or locally accessible name in the same class; it has the scope of local names declared in the scoping unit, which means that it is accessible by use or host association in other scoping units. A component name has the scope of the type definition only; another type definition in the same scoping unit may specify the same component name. For more information on local entities and scope, see the MIPSpro Fortran Language Reference Manual, Volume 2.

If the END TYPE statement is followed by a name, it must be the name specified in the TYPE statement.

A type can be defined only once within a scoping unit.

A PRIVATE statement must not appear more than once in a type definition.

A SEQUENCE statement must not appear more than once in a type definition

If SEQUENCE is present, all derived types specified as components must also be sequence types.

The keywords PUBLIC and PRIVATE can appear only if the definition is in the specification part of a module.

There must be at least one component definition statement in a type definition.

No component attribute can appear more than once in a specified component definition statement.

A component can be declared to have the same type as the type being defined only if it has the POINTER attribute.

An array component without the POINTER attribute must be specified with an explicit-shape specification where the bounds are integer constant expressions.

If a component is of type character with a specified length, the length must be an integer constant specification expression. If the length is not specified, it is 1.

If component_initialization is specified, a double colon separator (::) must appear before the component_decl_list.

If => appears in a component_initialization , the POINTER attribute must appear in the component_attr_spec_list. If = appears in a component_initialization, the POINTER attribute cannot appear in the component_attr_spec_list .

If initialization_expr appears for a nonpointer component, that component in any object of the type is initially defined or becomes defined as specified in MIPSpro Fortran Language Reference Manual, Volume 2 with the value determined from initialization_expr. The initialization_expr is evaluated in the scoping unit of the type definition. The evaluation rules are the same as if the component were a variable=initialization_expr . If component_name is a type for which default_initialization is specified for a component, the default_initialization specified by initialization_expr overrides the default initialization specified for that component. Explicit initialization in a type declaration statement overrides default initialization. An object of a type with default initialization must not be specified in a DATA statement.

The following example shows a derived-type definition with four components (three integer and one character):

TYPE COLOR
   INTEGER :: HUE, SHADE, INTENSITY
   CHARACTER(LEN = 30) :: NAME
END TYPE COLOR

The following is a format for declaring variables of derived type:

TYPE (type_name) [ [ , attribute_list ] :: ] entity_list

For example, variables of type COLOR can be declared as follows:

TYPE(COLOR) MY_FAVORITE
TYPE(COLOR) RAINBOW(7)
TYPE(COLOR), DIMENSION (100) :: SELECTIONS

The object MY_FAVORITE is a structure. The objects RAINBOW and SELECTIONS are arrays of structures.

Note that the initial statement of a type definition and the statement used to declare objects of derived type both begin with the keyword TYPE. The initial statement of a type definition is called a derived-type statement, and the statement used to declare objects of derived type is called a TYPE statement. The type name in a derived-type statement is not enclosed in parentheses, whereas the type name in a TYPE statement is.

A component of a structure is referenced using a percent sign, as in the following template:

parent_structure % component_name

Examples:

MY_FAVORITE % HUE
RAINBOW(3) % NAME

The following examples show definitions of derived types. Each example illustrates a different aspect of a type definition:

  • A derived type with a component of a different derived type

  • A derived type with a pointer component

  • A derived type with a pointer component of the type being defined

  • A private type definition

  • A public type definition with private components

Example 1: A derived type can have a component that is of a different derived type. Type WEATHER in the following example has a component of type TEMPERATURES.

TYPE TEMPERATURES
   INTEGER :: HIGH, LOW
END TYPE TEMPERATURES

TYPE WEATHER
   CHARACTER(LEN = 32) :: CITY
   TYPE(TEMPERATURES) :: RANGE(1950:2050)
END TYPE WEATHER

TYPE(WEATHER) WORLDWIDE(200)

WORLDWIDE is an array of type WEATHER. Components of an element of the array are referenced as follows:

WORLDWIDE(I)%CITY = "Nome"
WORLDWIDE(I)%RANGE(1990)%LOW = -83

Example 2: A derived type can have a component that is a pointer, as follows:

TYPE ABSTRACT
   CHARACTER(LEN = 50) TITLE
   INTEGER NUM_OF_PAGES
   CHARACTER, POINTER :: TEXT(:)
END TYPE ABSTRACT

Any object of type ABSTRACT will have three components: TITLE, NUM_OF_PAGES, and TEXT. TEXT is a pointer to an array of character strings, each of which is of length one. The array size is determined during program execution. The space for the target of TEXT can be allocated, or TEXT can be pointer-assigned to existing space. For information on the ALLOCATE statement, see Section 6.5.1 in Chapter 6. For information on pointer assignment, see Section 7.5.3 in Chapter 7.

Example 3: A derived type can have a pointer component that is of the type being defined. This is useful in creating linked lists and trees, as follows:

TYPE LINK
   REAL VALUE
   TYPE(LINK), POINTER :: PREVIOUS
   TYPE(LINK), POINTER :: NEXT
END TYPE LINK

Example 4: A type definition in a module can be kept private to the module, as follows:

TYPE, PRIVATE :: FILE
   INTEGER DRAWER_NO
   CHARACTER(LEN = 20) FOLDER_NAME
   CHARACTER(LEN = 5) ACCESS_LEVEL
END TYPE FILE

When a module that contains this type definition is accessed by another scoping unit, the type FILE is not available.

Example 5: A type definition can be public while its components are kept private, as follows:

MODULE COORDINATES
   TYPE POINT
      PRIVATE
      REAL X, Y
   END TYPE POINT
      ...
END MODULE COORDINATES

In a program unit that uses module COORDINATES, variables of type POINT can be declared. Values of type POINT can be passed as arguments. If the program unit is a function, a value of type POINT can be returned as the result. However, the internal structure of the type (its components) is not available. If the type POINT is changed to the following, no other program unit that uses COORDINATES will need to be changed:

TYPE POINT
   PRIVATE
   REAL RHO, THETA
END TYPE POINT

If a subprogram dummy argument is of derived type, the corresponding actual argument must be of the same type. There are two ways in which objects in different scoping units can be declared to be of the same type. Two data entities have the same type if they are declared with reference to the same type definition. The definition can appear in a module that is accessed or, in the case of an internal or module procedure, in the host scoping unit.

MODULE SHOP
   TYPE COMPONENT
      CHARACTER(LEN = 20) NAME
      INTEGER CATALOG_NUM
      REAL WEIGHT
   END TYPE COMPONENT
   TYPE(COMPONENT) PARTS(100)
CONTAINS
   SUBROUTINE GET_PART(PART, NAME)
      TYPE(COMPONENT) PART
      CHARACTER(LEN = *) NAME
      DO I = 1, 100
         IF (NAME .EQ. PARTS(I)%NAME) THEN
            PART = PARTS(I)
            RETURN
         END IF
      END DO
      PRINT *, "Part not available"
      PART%NAME = "none"
      PART%CATALOG_NUM = 0
      PART%WEIGHT = 0.0
   END SUBROUTINE GET_PART
      . . .
END MODULE SHOP

PROGRAM BUILD_MACHINE
   USE SHOP
   TYPE(COMPONENT) MOTOR(20)
   TOTAL_WEIGHT = 0.0
   CALL GET_PART(MOTOR(1), "VALVE")
   IF (MOTOR(1)%WEIGHT .NE. 0) THEN
      TOTAL_WEIGHT = TOTAL_WEIGHT + MOTOR(1)%WEIGHT
   ELSE
      . . .
   ENDIF
   . . .
END PROGRAM BUILD_MACHINE

Module procedure GET_PART has access to the type COMPONENT because the type definition appears in its host. Program BUILD_MACHINE has access to the type because it uses module SHOP. This allows a variable of the type, such as MOTOR(1) , to be passed as an actual argument.

The other way to declare data entities in different scoping units to be of the same type is provided for programmers who choose not to use a module. Instead of a single type definition in the module, a sequence type can be defined in each of the scoping units that need access to the type. Each of the type definitions must specify the same name; the SEQUENCE property; have no private components; and have components that agree in order, name, and attributes. If this is the case, data entities declared in any of these scoping units to be of the named type are considered to be of the same type. In the following, program BUILD_MACHINE is restated to illustrate the differences between the two ways:

PROGRAM BUILD_MACHINE
   TYPE COMPONENT
      SEQUENCE
      CHARACTER(LEN = 20) NAME
      INTEGER CATALOG_NUM
      REAL WEIGHT
   END TYPE COMPONENT
   TYPE(COMPONENT) PARTS, MOTOR(20)
   COMMON /WAREHOUSE/ PARTS(100)
   TOTAL_WEIGHT = 0.0
   CALL GET_PART(MOTOR(1), "VALVE")
   IF (MOTOR(1)%WEIGHT .NE. 0) THEN
      TOTAL_WEIGHT = TOTAL_WEIGHT + MOTOR(1)%WEIGHT
   ELSE
      . . .
   ENDIF
      . . .
END PROGRAM BUILD_MACHINE
SUBROUTINE GET_PART(PART, NAME)
   TYPE COMPONENT
      SEQUENCE
      CHARACTER(LEN = 20) NAME
      INTEGER CATALOG_NUM
      REAL WEIGHT
   END TYPE COMPONENT
   TYPE(COMPONENT) PART, PARTS
   CHARACTER(LEN = *) NAME
   COMMON /WAREHOUSE/ PARTS(100)
   DO I = 1, 100
      IF (NAME .EQ. PARTS(I)%NAME) THEN
         PART = PARTS(I)
         RETURN
      END IF
   END DO
   PART%NAME = "none"
   PART%CATALOG_NUM = 0
   PART%WEIGHT = 0.0
   PRINT *, "Part not available"
END SUBROUTINE GET_PART
   . . .

In this example, type COMPONENT in program BUILD_MACHINE and type COMPONENT in subroutine GET_PART are the same because they are sequence types with the same name; have no private components; and have components that agree in order, name, and attributes. This allows variables of the type to appear in COMMON and be passed as arguments. Note that this example is less concise, particularly if more procedures need to access the type definition, and therefore may be more error prone than the previous example.

Type COMPONENT is a sequence type because its definition contains a SEQUENCE statement. If all of the ultimate components of a sequence type are of type default integer, default real, double-precision real, default complex, or default logical, and are not pointers, the type is a numeric sequence type. An object of numeric sequence type can be equivalenced to default numeric objects.

If all of the ultimate components of a sequence type are of type character and are not pointers, the type is a character sequence type. An object of character sequence type may be equivalenced to character objects.

A pointer component of a derived type can have as its target an object of that derived type. The type definition can specify that in objects declared to be of this type, such a pointer is default initialized to disassociated. In the following example, type NODE is created and is used to construct linked lists of objects of type NODE:

TYPE NODE
   INTEGER :: VALUE
   TYPE (NODE), POINTER :: NEXT_NODE => NULL ( )
END TYPE

Initialization need not be specified for each component of a derived type. For example:

TYPE DATE
   INTEGER DAY
   CHARACTER (LEN = 5) MONTH
   INTEGER :: YEAR = 1994     ! PARTIAL DEFAULT INITIALIZATION
END TYPE DATE

In the following example, the default initial value for the YEAR component of TODAY is overridden by explicit initialization in the type declaration statement:

TYPE (DATE), PARAMETER :: TODAY = DATE (21, "Feb.", 1995)

4.4.2. Derived Type Values

The set of values of a derived type consists of all combinations of the possibilities for component values that are consistent with the components specified in the type definition.

4.4.3. Derived Type Operations

Any operation involving a derived-type entity must be defined explicitly by a function with an OPERATOR interface. Assignment, other than the intrinsic assignment provided for entities of the same derived type, must be defined by a subroutine with an ASSIGNMENT interface. See the MIPSpro Fortran Language Reference Manual, Volume 2, for a description.

Suppose it is desirable to determine the number of words and lines in a section of text. The information is available for each paragraph. A type named PARAGRAPH is defined as follows:

TYPE PARAGRAPH
   INTEGER NUM_WORDS, NUM_LINES
   CHARACTER(LEN = 30) SUBJECT
END TYPE PARAGRAPH

Suppose that it is now desirable to define an operator for adding the counts associated with the paragraphs. The following OPERATOR interface is required for the function that defines the addition operation for objects of type PARAGRAPH:

INTERFACE OPERATOR (+)
   MODULE PROCEDURE ADDP
END INTERFACE

The following definition of addition for objects of type PARAGRAPH adds the words and lines, but it does nothing with the component SUBJECT because that would have no useful meaning:

TYPE(PARAGRAPH) FUNCTION ADDP(P1, P2)
   TYPE(PARAGRAPH) P1, P2
   INTENT(IN) P1, P2
   ADDP%NUM_WORDS = P1%NUM_WORDS + P2%NUM_WORDS
   ADDP%NUM_LINES = P1%NUM_LINES + P2%NUM_LINES
END FUNCTION ADDP

If the following variables were declared, the expression BIRDS+BEES would be defined and could be evaluated in the module subprogram as well as any program unit accessing the module:

TYPE(PARAGRAPH) BIRDS, BEES

4.4.4. Syntax for Specifying Derived-type Constant Expressions

When a derived type is defined, a structure constructor for that type is defined automatically. The structure constructor is used to specify values of the type. It specifies a sequence of values, one for each of the components of the type. A structure constructor whose values are all constant expressions is a derived-type constant expression. (This is why a derived-type value is formed by a constructor. There is no such thing as a structure constant; there are only structure constructors, some of which may be constant expressions.) A named constant of user-defined type can be assigned such a value. Structure constructors are described in Section 4.5.

A component of a derived type can be an array. In this case a mechanism called an array constructor is used to specify that component of the type. Array constructors are described in Section 4.6, and a general discussion of arrays can be found in Section 6.4 in Chapter 6.

4.5. Structure Constructors

A structure constructor is a mechanism that is used to specify a value of a derived type by specifying a sequence of values for the components of the type. If a component is of derived type, an embedded structure constructor is required to specify the value of that component. If a component is an array, an embedded array constructor is required to specify the values for that component.

A structure constructor is the name of the type followed by a sequence of component values in parentheses. For example, a value of type COLOR (from Section 4.4.1) can be constructed with the following structure constructor:

COLOR(I, J, K, "MAGENTA")

For information on derived types, see Section 4.4.1.

The format for a structure_constructor is defined as follows:

 

structure_constructor

is

type_name (expr_list)

There must be a value in the expression list for each component.

The expressions must agree in number and order with the components of the derived type. Values may be converted (in the same way they would be for an assignment statement) to agree in type, kind, length, and, in some cases, rank, with the components. The conversions permitted are those for intrinsic assignment, in which the component is the variable on the left and the expression is the one given in the structure constructor corresponding to the component. Rank must be conformable according to the rules of assignment conformance. That is, the shapes must conform or the expression can be a scalar broadcast to an array component.

If a component is an explicit-shape array (that is, a nonpointer array), the array constructor for it in the expression list must be the same shape as the component.

If a component is a pointer, the value for it in the expression list must evaluate to an allowable target for the pointer. A constant is not an allowable target.

A structure constructor must not appear before that type is defined.

The structure constructor for a private type or a public type with private components is not available outside the module in which the type is defined.

If the values in a structure constructor are constants, you can use the structure constructor to specify a named constant, as in the following example:

PARAMETER( TEAL = COLOR(14, 7, 3, "TEAL") )
TYPE(COMPONENT), PARAMETER :: NO_PART = COMPONENT("none", 0, 0.0) )

Following are several examples of structure constructors for types with somewhat different components:

  • A type with a component that is of derived type

  • A type with an array component

  • A type with a pointer component

Example 1: A structure constructor for a type that has a derived type as a component must provide a value for each of the components. A component may be of derived type, in which case a structure constructor is required for the component. In the following example, type RING has a component of type STONE:

TYPE STONE
    REAL           CARETS
    INTEGER        SHAPE
    CHARACTER(30)  NAME
END TYPE STONE

TYPE RING
    REAL           EST_VALUE
    CHARACTER(30)  INSURER
    TYPE (STONE)   JEWEL
END TYPE RING

If OVAL is a named integer constant, an example of a structure constructor for a value of type RING is as follows:

RING (5000.00, "Lloyds", STONE(2.5, OVAL, "emerald") )

Example 2: If a type is specified with an array component, the value that corresponds to the array component in the expression list of the structure constructor must conform with the shape of the array component. For example, type ORCHARD has an array component as follows:

TYPE ORCHARD
    INTEGER               AGE, NUM_TREES
    CHARACTER(LEN = 20)   VARIETY(10)
END TYPE

Assume the following declarations:

CHARACTER(LEN = 20) CATALOG(16, 12)
PARAMETER(LEMON = 3)

A structure constructor for a value of type ORCHARD is as follows:

ORCHARD (5, ROWS * NUM_PER_ROW, CATALOG(LEMON, 1:10) )

Example 3: When a component of the type is a pointer, the corresponding structure constructor expression must evaluate to an object that would be an allowable target for such a pointer in a pointer assignment statement. Assume that the variable SYNOPSIS is declared as follows:

CHARACTER, TARGET :: SYNOPSIS(4000)

The following value of the type ABSTRACT (from Section 4.4.1) can then be constructed:

ABSTRACT("War and Peace", 1025, SYNOPSIS)

A constant expression cannot be constructed for a type with a pointer component because a constant is not an allowable target in a pointer assignment statement.

4.6. Array Constructors

An array constructor is used to specify the value of an array. More precisely, an array constructor is a mechanism that is used to specify a sequence of scalar values that is interpreted as a rank-one array. Syntactically, it is a sequence of scalar values and implied- DO specifications enclosed in parentheses and slashes. As with structures, there is no such thing as an array constant. There are only array constructors, some of which may be constant expressions, as follows:

REAL VECTOR_X(3), VECTOR_Y(2), RESULT(100)
   . . .
RESULT(1:8) = (/ 1.3, 5.6, VECTOR_X, 2.35, VECTOR_Y /)

The value of the first eight elements of RESULT is constructed from the values of VECTOR_X and VECTOR_Y and three real constants in the specified order. If a rank-two or greater array appears in the value list, the values of its elements are taken in array element order. If it is necessary to construct an array of rank greater than one, the RESHAPE(3i) intrinsic function can be applied to an array constructor.

The format for an array_constructor is as follows:

 

array_constructor

is

(/ ac_value_list /)

 

ac_value

is

expr

 

 

or

ac_implied_do

 

ac_implied_do

is

(ac_value_list , ac_implied_do_control)

 

ac_implied_do_control

is

ac_do_variable = scalar_int_expr, scalar_int_expr [, scalar_int_expr ]

 

ac_do_variable

is

scalar_int_variable

Each ac_value expression in the array constructor must have the same type, kind type, and length parameters. In particular, this means that if each ac_value is a character literal constant, each constant must have the same length.

The type and type parameters of an array constructor are those of its ac_value expressions.

If the ac_implied_do yields no values, the array is a rank one, zero-sized array.

An ac_do_variable must be a scalar integer named variable. This variable has the scope of this ac_implied_do .

If an ac_implied_do is contained within another ac_implied_do, they must not have the same ac_do_variable .

Three possibilities for an ac_value are as follows:

  • It can be a scalar expression, as is each ac_value in the following:

    (/ 1.2, 3.5, 1.1 /)

  • It can be an array expression, as is each ac_value in the following:

    (/ A(I, 1:3), A(I+1, 6:8) /)

  • It can be an implied-DO specification, as in the following:

    (/ (SQRT(REAL(I)), I = 1, 9) /)

The possibilities can be mixed in a single array constructor, as follows:

(/ 1.2, B(2:6,:), (REAL(I), I = 1, N), 3.5 /)

If an ac_value is an array expression, the values of the elements of the expression in array element order become the values of the array constructor. For example, the values that result from the example in possibility 2 are as follows:

(/ A(I,1), A(I,2), A(I,3), A(I+1,6), A(I+1,7), A(I+1,8) /)

For more information on array element order, see Section 6.4.7 in Chapter 6.

If an ac_value is an implied-DO specification, it is expanded to form a sequence of values under control of the ac_do_variable as in the DO construct. For example, the values that result from the example in possibility 3 are as follows:

(/1.0, 1.414, 1.732, 2.0, 2.236, 2.449, 2.645, 2.828, 3.0/)

For more information on the DO construct, see Section 8.5 in Chapter 8.

If every expression in an array constructor is a constant expression, the array constructor is a constant expression as in the example above. Such an array constructor can be used to assign a value to a named constant, as follows:

REAL X(3), EXTENDED_X(4)
PARAMETER(X = (/ 2.0, 4.0, 6.0 /) )
REAL, PARAMETER :: EXTENDED_X = (/ 0.0, X /) )

The following are examples of array constructors. Examples 1 and 2 demonstrate the construction of arrays; examples 3 and 4 demonstrate the construction of values of derived type when the type has an array component:

  1. A constructor for a rank two array

  2. A constructor for an array of derived type

  3. A constructor for a value of derived type with an array component

  4. A constructor for a value of derived type with a rank two array component

Example 1: To create a value for an array of rank greater than one, the RESHAPE(3i) intrinsic function must be used. With this function, a one-dimensional array may be reshaped into any allowable array shape.

Y = RESHAPE(SOURCE = (/ 2.0, (/ 4.5, 4.0 /), Z /),  &
      SHAPE = (/ 3, 2 /))

If Z has the value given in possibility 1 above, then Y is a 3 by 2 array with the following elements:

2.0     1.2
4.5     3.5
4.0     1.1

Example 2: It might be necessary to construct an array value of derived type.

TYPE PERSON
   INTEGER AGE
   CHARACTER(LEN = 40) NAME
END TYPE PERSON

TYPE(PERSON) CAR_POOL(3)

CAR_POOL = (/ PERSON(35, "SCHMITT"),  &
      PERSON(57, "LOPEZ"), PERSON(26, "YUNG") /)

Example 3: When one of the components of a derived type is an array, then an array constructor must be used in the structure constructor for the derived type. Suppose that the definition for type COLOR is as follows, which differs slightly from that stated previously:

TYPE COLOR
   INTEGER PROPERTIES(3)
   CHARACTER(LEN = 30) NAME
END TYPE COLOR

The following value of the revised type COLOR can be constructed:

COLOR((/ 5, 20, 8 /), "MAGENTA")

Example 4: A derived type might contain an array of rank two or greater, as follows:

TYPE LINE
   REAL     COORD(2, 2)
   REAL     WIDTH
   INTEGER  PATTERN
END TYPE LINE

The values of COORD are the coordinates x 1, y1 and x2, y 2 representing the end points of a line. WIDTH is the line width in centimeters. PATTERN is 1 for a solid line, 2 for a dashed line, and 3 for a dotted line. An object of type LINE is declared and given a value as follows:

TYPE(LINE) SLOPE
   . . .  
SLOPE = LINE(RESHAPE((/ 0.0, 1.0, 0.0, 2.0 /), (/ 2, 2 /)), 0.1, 1)

The RESHAPE(3i) intrinsic function is used to construct a value that represents a solid line from (0,0 ) to (1,2) of width 0.1 centimeters.

MIPSpro Fortran Language Reference Manual, Volume 1
(document number: 007-3692-006 / published: 2002-11-19)    table of contents  |  additional info  |  download

    Front Matter
    About This Guide
    Chapter 1. Introduction
    Chapter 2. Fortran Concepts and Terms
    Chapter 3. Language Elements and Source Form
    Chapter 4. Data Types
    Chapter 5. Declarations
    Chapter 6. Using Data
    Chapter 7. Expressions and Assignments
    Chapter 8. Controlling Execution
    Glossary
    Index


home/search | what's new | help