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:
|Calculating typical numeric results|
The preceding list shows the commonly needed data types, and the Fortran standard provides for them.
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.
As the following list shows, the type of the data determines the operations that can be performed on it:
|Real, complex, integer, Boolean|
Addition, subtraction, multiplication, division, exponentiation, negation, comparison, masking expressions
Negation, conjunction, disjunction, and equivalence
|Cray pointer, Cray character pointer|
Addition, subtraction, and LOC( ) function
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.
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.
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.
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.
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 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.
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 set of values
A set of operations
A form for constants of the intrinsic types and constructors for derived types
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.
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.
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.
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.
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:
The kind of a complex constant is determined by the kind of its parts. Section 126.96.36.199, describes the form for complex literal constants.
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 188.8.131.52 in Chapter 7.|
INTEGER [ ([ KIND = ] kind_param) ] [ [ , attribute_list ] :: ] entity_list
INTEGER :: X INTEGER :: COUNT, K, TEMPORARY_COUNT INTEGER(SHORT) :: PARTS INTEGER, DIMENSION(0:9) :: SELECTORS, IX
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.
Size / Storage
-27 ≤ n < 27
8 bits / 8 bits
-215 ≤ n < 215
16 bits / 16 bits
-231 ≤ n < 231
32 bits / 32 bits
-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.
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
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.
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:
The format of a signed integer literal constant (which may have a kind type parameter) is defined as follows:
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:
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:
You must specify 0 or 1 for digit.
An octal_constant is defined as follows:
You must specify a value from 0 through 7 for digit.
A hex_constant is defined as follows:
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"
REAL X, Y REAL(KIND = HIGH), SAVE :: XY(10, 10) REAL, POINTER :: A, B, C DOUBLE PRECISION DD, DXY, D
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.
Size and Storage
2 -125 ≤ n < 2 128
2 -1021 ≤ n < 2 1024
2 -967 ≤ n < 2 1023
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:
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
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.|
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:
significand exponent_letter exponent [ _kind_param]
digit_string exponent_letter exponent [ _kind_param ]
A signed real literal constant can take one of the following forms:
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:
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.
COMPLEX [([ KIND = ] kind_param) ] [[ , attribute_list ] :: ] entity_list
COMPLEX CC, DD COMPLEX(KIND = single), POINTER :: CTEMP(:)
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
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.
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:
(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.
LOGICAL [([ KIND = ] kind_param) ] [[ , attribute_list ] :: ] entity_list
LOGICAL IR, XT LOGICAL(KIND = SMALL), SAVE :: XMASK (3000)
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.
Size / Storage
8 bits / 8 bits
16 bits / 16 bits
32 bits / 32 bits
64 bits / 64 bits
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.|
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:
If a kind_param is not specified, the type of the constant is default logical. Examples are as follows:
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..|
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 184.108.40.206 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
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.
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.
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:
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:
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.
|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.
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.|
Internal representation (octal) for a 64-bit word
I = 1357B
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.
Internal representation (octal) for a 64-bit word
|X'1 2 3'|
J = X"28FF" K = X'-5A'
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.
|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.
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.
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:
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
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
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
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(I)%CITY = "Nome" WORLDWIDE(I)%RANGE(1990)%LOW = -83
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.
TYPE LINK REAL VALUE TYPE(LINK), POINTER :: PREVIOUS TYPE(LINK), POINTER :: NEXT END TYPE LINK
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.
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)
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
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.
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:
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.
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:
(/ ac_value_list /)
(ac_value_list , ac_implied_do_control)
ac_do_variable = scalar_int_expr, scalar_int_expr [, scalar_int_expr ]
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) /)
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/)
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:
A constructor for a rank two array
A constructor for an array of derived type
A constructor for a value of derived type with an array component
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.