PRINT *, VECTOR (B) ! Print out the elements of set B, in ascending order
C.9.3.7 Public entities renamed (14.2.2) 2 The following example illustrates renaming features of the USE statement.
MODULE J; REAL JX, JY, JZ; END MODULE J
MODULE K
USE J, ONLY : KX => JX, KY => JY
! KX and KY are local names to module K
REAL KZ ! KZ is local name to module K REAL JZ ! JZ is local name to module K END MODULE K
PROGRAM RENAME
USE J; USE K
! Module J’s entity JX is accessible under names JX and KX
! Module J’s entity JY is accessible under names JY and KY
! Module K’s entity KZ is accessible under name KZ
! Module J’s entity JZ and K’s entity JZ are different entities
! and cannot be referenced
...
END PROGRAM RENAME
C.9.4 Modules with submodules (14.2.3) 1 Each submodule specifies that it is the child of exactly one parent module or submodule. Therefore, a module
and all of its descendant submodules stand in a tree-like relationship one to another.2 A separate module procedure that is declared in a module to have public accessibility can be accessed by use
association even if it is defined in a submodule. No other entity in a submodule can be accessed by use association.3 By constructing taller trees, one can put entities at intermediate levels that are shared by submodules at lowerEach program unit that references a module by use association depends on it, and each submodule depends on
its ancestor module. Therefore, if one changes a separate module procedure body in a submodule but does not
⃝c ISO/IEC 2017 – All rights reserved 577
ISO/IEC DIS 1539-1:2017 (E)
change its corresponding module procedure interface, a tool for automatic program translation would not need
to reprocess program units that reference the module by use association. This is so even if the tool exploits the
relative modification times of files as opposed to comparing the result of translating the module to the result of
a previous translation.
levels; changing these entities cannot change the interpretation of anything that is accessible from the module4 The following example illustrates a module, color_points, with a submodule, color_points_a, that in turn hasby use association. Developers of modules that embody large complicated concepts can exploit this possibility
to organize components of the concept into submodules, while preserving the privacy of entities that are shared
by the submodules and that ought not to be exposed to users of the module. Putting these shared entities at an
intermediate level also prevents cascades of reprocessing and testing if some of them are changed.
a submodule, color_points_b. Public entities declared within color_points can be accessed by use association.5 The module color_points does not have a module-subprogram-part, but a module-subprogram-part is not pro-The submodules color_points_a and color_points_b can be changed without causing retranslation of program
units that reference the module color_points.
hibited. The module could be published as definitive specification of the interface, without revealing trade secrets6 The only entities within color_points_a that can be accessed by use association are the separate modulecontained within color_points_a or color_points_b. Of course, a similar module without the module prefix in
the interface bodies would serve equally well as documentation – but the procedures would be external procedures.
It would make little difference to the consumer, but the developer would forfeit all of the advantages of modules.
module color_points
type color_point
private
real :: x, y
integer :: color
end type color_point
interface ! Interfaces for procedures with separate
! bodies in the submodule color_points_a
module subroutine color_point_del ( p ) ! Destroy a color_point object
type(color_point), allocatable :: p
end subroutine color_point_del
! Distance between two color_point objects
real module function color_point_dist ( a, b )
type(color_point), intent(in) :: a, b
end function color_point_dist
module subroutine color_point_draw ( p ) ! Draw a color_point object
type(color_point), intent(in) :: p
end subroutine color_point_draw
module subroutine color_point_new ( p ) ! Create a color_point object
type(color_point), allocatable :: p
end subroutine color_point_new
end interface
end module color_points
578 ⃝c ISO/IEC 2017 – All rights reserved
ISO/IEC DIS 1539-1:2017 (E)
procedures that were declared in color_points. If the procedures are changed but their interfaces are not, the7 The variable instance_count in the following example is not accessible by use association of color_points, butinterface from program units that access them by use association is unchanged. If the module and submodule are
in separate files, utilities that examine the time of modification of a file would notice that changes in the module
could affect the translation of its submodules or of program units that reference the module by use association,
but that changes in submodules could not affect the translation of the parent module or program units that
reference it by use association.
is accessible within color_points_a, and its submodules.8 The subroutine inquire_palette is accessible within color_points_a because its interface is declared therein.submodule ( color_points ) color_points_a ! Submodule of color_points
integer :: instance_count = 0
interface ! Interface for a procedure with a separate
! body in submodule color_points_b
module subroutine inquire_palette ( pt, pal )
use palette_stuff ! palette_stuff, especially submodules thereof,
! can reference color_points by use association
! without causing a circular dependence during
! translation because this use is not in the module.
! Furthermore, changes in the module palette_stuff
! do not affect the translation of color_points.
type(color_point), intent(in) :: pt
type(palette), intent(out) :: pal
end subroutine inquire_palette
end interface
contains ! Invisible bodies for public separate module procedures
! declared in the module
module subroutine color_point_del ( p )
type(color_point), allocatable :: p
instance_count = instance_count - 1
deallocate ( p )
end subroutine color_point_del
real module function color_point_dist ( a, b ) result ( dist )
type(color_point), intent(in) :: a, b
dist = SQRT ( (b%x - a%x)**2 + (b%y - a%y)**2 )
end function color_point_dist
module subroutine color_point_new ( p )
type(color_point), allocatable :: p
instance_count = instance_count + 1
allocate ( p )
end subroutine color_point_new
end submodule color_points_a
⃝c ISO/IEC 2017 – All rights reserved 579
ISO/IEC DIS 1539-1:2017 (E)
It is not, however, accessible by use association, because its interface is not declared in the module, color_points.9 There is a use palette_stuff in color_points_a, and a use color_points in palette_stuff. The useSince the interface is not declared in the module, changes in the interface cannot affect the translation of program
units that reference the module by use association.
module palette_stuff
type :: palette ; ... ; end type palette
contains
subroutine test_palette ( p )
! Draw a color wheel using procedures from the color_points module
use color_points ! This does not cause a circular dependency because
! the "use palette_stuff" that is logically within
! color_points is in the color_points_a submodule.
type(palette), intent(in) :: p
...
end subroutine test_palette
end module palette_stuff
submodule ( color_points:color_points_a ) color_points_b ! Subsidiary**2 submodule
contains
! Invisible body for interface declared in the ancestor module
module subroutine color_point_draw ( p )
use palette_stuff, only: palette
type(color_point), intent(in) :: p
type(palette) :: MyPalette
...; call inquire_palette ( p, MyPalette ); ...
end subroutine color_point_draw
! Invisible body for interface declared in the parent submodule
module procedure inquire_palette
... implementation of inquire_palette
end procedure inquire_palette
subroutine private_stuff ! not accessible from color_points_a
...
end subroutine private_stuff
end submodule color_points_b
palette_stuff would cause a circular reference if it appeared in color_points. In this case, it does not cause10 A multilevel submodule system can be used to package and organize a large and interconnected concept withouta circular dependence because it is in a submodule. Submodules cannot be referenced by use association, and
therefore what would be a circular appearance of use palette_stuff is not accessed.
580 ⃝c ISO/IEC 2017 – All rights reserved
ISO/IEC DIS 1539-1:2017 (E)
program main
use color_points
! "instance_count" and "inquire_palette" are not accessible here
! because they are not declared in the "color_points" module.
! "color_points_a" and "color_points_b" cannot be referenced by
! use association.
interface draw ! just to demonstrate it’s possible
module procedure color_point_draw
end interface
type(color_point) :: C_1, C_2
real :: RC
...
call color_point_new (c_1) ! body in color_points_a, interface in color_points
...
call draw (c_1) ! body in color_points_b, specific interface
! in color_points, generic interface here.
...
rc = color_point_dist (c_1, c_2) ! body in color_points_a, interface in color_points
...
call color_point_del (c_1) ! body in color_points_a, interface in color_points
...
end program main
exposing entities of one subsystem to other subsystems.11 Consider a Plasma module from a Tokomak simulator. A plasma simulation requires attention at least to fluid
flow, thermodynamics, and electromagnetism. Fluid flow simulation requires simulation of subsonic, supersonic,12 Entities can be shared among the Subsonic, Supersonic, and Hypersonic submodules by putting them withinand hypersonic flow. This problem decomposition can be reflected in the submodule structure of the Plasma
module:
Plasma module
Flow submodule Thermal submodule Electromagnetics submodule
Subsonic Supersonic Hypersonic
submodule submodule submodule
the Flow submodule. One then need not worry about accidental use of these entities by use association or by theISO/IEC DIS 1539-1:2017 (E)Thermal or Electromagnetics submodules, or the development of a dependency of correct operation of those
subsystems upon the representation of entities of the Flow subsystem as a consequence of maintenance. Since
these entities are not accessible by use association, if any of them are changed, the new values cannot be accessed
in program units that reference the Plasma module by use association; the answer to the question “where are
these entities used” is therefore confined to the set of descendant submodules of the Flow submodule.
⃝c ISO/IEC 2017 – All rights reserved 581
C.10 Clause 15 notes C.10.1 Portability problems with external procedures (<IP_ADDRESS>) 1 There is a potential portability problem in a scoping unit that references an external procedure without explicitly
declaring it to have the EXTERNAL attribute (8.5.9). On a different processor, the name of that procedure1 A processor is not required to provide any means other than Fortran for defining external procedures. Among themight be the name of a nonstandard intrinsic procedure and in such a case the processor would interpret those
procedure references as references to that intrinsic procedure. (On that processor, the program would also be
viewed as not conforming to this document because of the references to the nonstandard intrinsic procedure.)
Declaration of the EXTERNAL attribute causes the references to be to the external procedure regardless of the
availability of an intrinsic procedure with the same name. Note that declaration of the type of a procedure is not
enough to make it external, even if the type is inconsistent with the type of the result of an intrinsic procedure
of the same name.
C.10.2 Procedures defined by means other than Fortran (15.6.3)
means that might be supported are the machine assembly language, other high level languages, the Fortran lan-2 A Fortran processor might limit its support of procedures defined by means other than Fortran such that theseguage extended with nonstandard features, and the Fortran language as supported by another Fortran processor
(for example, a previously existing Fortran 77 processor). The means other than Fortran for defining external
procedures, including any restrictions on the structure or organization of those procedures, are not specified by
this document.
procedures can affect entities in the Fortran environment only on the same basis as procedures written in Fortran.1 This is an example of a library module providing lists of callbacks that the user can register and invoke.For example, it might not support the value of a local variable from being changed by a procedure reference unless
that variable were one of the arguments to the procedure.
C.10.3 Abstract interfaces and procedure pointer components (15.4, 7.5)
MODULE callback_list_module!
! Type for users to extend with their own data, if they so desire
!
TYPE callback_data
END TYPE
!
! Abstract interface for the callback procedures
!
ABSTRACT INTERFACE
SUBROUTINE callback_procedure(data)
IMPORT callback_dataCLASS(callback_data),OPTIONAL :: data
END SUBROUTINE
END INTERFACE
!
582 c ISO/IEC 2017 – All rights reservedISO/IEC DIS 1539-1:2017 (E)
! The callback list type.
!
TYPE callback_list
PRIVATE
CLASS(callback_record),POINTER :: first => NULL()
END TYPE
!
! Internal: each callback registration creates one of these
!
TYPE,PRIVATE :: callback_record
PROCEDURE(callback_procedure),POINTER,NOPASS :: procCLASS(callback_record),POINTER :: next
CLASS(callback_data),POINTER :: data => NULL();
END TYPE
PRIVATE invoke,forward_invoke
CONTAINS
!
! Register a callback procedure with optional data
!
SUBROUTINE register_callback(list, entry, data)
TYPE(callback_list),INTENT(INOUT) :: listPROCEDURE(callback_procedure) :: entry
CLASS(callback_data),OPTIONAL :: data
TYPE(callback_record),POINTER :: new,last
ALLOCATE(new)
new%proc => entry
IF (PRESENT(data)) ALLOCATE(new%data,SOURCE=data)
new%next => list%first
list%first => new
END SUBROUTINE
!
!
 Call the procedures in reverse order of registration
!
⃝
c ISO/IEC 2017 – All rights reserved 583
ISO/IEC DIS 1539-1:2017 (E)SUBROUTINE invoke_callback_reverse(list)
TYPE(callback_list),INTENT(INOUT) :: list
TYPE(callback_record),POINTER :: next,current
current => list%first
NULLIFY(list%first)
DO WHILE (ASSOCIATED(current))
next => current%next
CALL invoke(current)
current => next
END DO
END SUBROUTINE
!
! Internal: Forward mode invocation
!
SUBROUTINE forward_invoke(callback)
IF (ASSOCIATED(callback%next)) CALL forward_invoke(callback%next)CALL invoke(callback)
END SUBROUTINE
!
! Call the procedures in forward order of registration
!
SUBROUTINE invoke_callback_forward(list)
TYPE(callback_list),INTENT(INOUT) :: listIF (ASSOCIATED(list%first)) CALL forward_invoke(list%first)
END SUBROUTINE
END
C.10.4 Pointers and targets as arguments (<IP_ADDRESS>, <IP_ADDRESS>, <IP_ADDRESS>) 1 If a dummy argument is declared to be a pointer, the corresponding actual argument could be a pointer or could
be a nonpointer variable or procedure. Consider the two cases separately.2 When execution of a procedure completes, any pointer that remains defined and that is associated with a dummyCase (i): The actual argument is a pointer. When procedure execution commences the pointer association
status of the dummy argument becomes the same as that of the actual argument. If the pointer
association status of the dummy argument is changed, the pointer association status of the actual
argument changes in the same way.
Case (ii): The actual argument is not a pointer. This only occurs when the actual argument has the TARGET
attribute or is a procedure, and the dummy argument has the INTENT (IN) attribute. The dummy
argument becomes pointer associated with the actual argument.
argument that has the TARGET attribute and is either a scalar or an assumed-shape array, remains associated3 For example, consider:with the corresponding actual argument if the actual argument has the TARGET attribute and is not an array
section with a vector subscript.
584 ⃝
c ISO/IEC 2017 – All rights reserved
ISO/IEC DIS 1539-1:2017 (E)
REAL, POINTER :: PBESTREAL, TARGET :: B (10000)
CALL BEST (PBEST, B) ! Upon return PBEST is associated
... ! with the ‘‘best’’ element of B
CONTAINS
SUBROUTINE BEST (P, A)
REAL, POINTER, INTENT (OUT) :: PREAL, TARGET, INTENT (IN) :: A (:)
... ! Find the ‘‘best’’ element A(I)
P => A (I)
RETURN
END SUBROUTINE BEST
END
When procedure BEST completes, the pointer PBEST is associated with an element of B.
4 An actual argument without the TARGET attribute can become associated with a dummy argument with the
TARGET attribute. This enables a pointer to become associated with the dummy argument during execution ofthe procedure that contains the dummy argument. For example:
INTEGER LARGE(100,100)
CALL SUB (LARGE)
...
CALL SUB ()
CONTAINS
SUBROUTINE SUB(ARG)
INTEGER, TARGET, OPTIONAL :: ARG(100,100)INTEGER, POINTER, DIMENSION(:,:) :: PARG
IF (PRESENT(ARG)) THEN
PARG => ARG
ELSE
ALLOCATE (PARG(100,100))
PARG = 0
ENDIF
... ! Code with lots of references to PARG
IF (.NOT. PRESENT(ARG)) DEALLOCATE(PARG)
END SUBROUTINE SUB
END
Within subroutine SUB the pointer PARG is either associated with the dummy argument ARG or it is associated
with an allocated target. The bulk of the code can reference PARG without further calls to the intrinsic function
PRESENT.
5 If a nonpointer dummy argument has the TARGET attribute and the corresponding actual argument does not,
any pointers that become associated with the dummy argument, and therefore with the actual argument, during1 The following example illustrates the polymorphic argument association rules using the derived types defined inexecution of the procedure, become undefined when execution of the procedure completes.
⃝c ISO/IEC 2017 – All rights reserved 585
ISO/IEC DIS 1539-1:2017 (E)
C.10.5 Polymorphic Argument Association (<IP_ADDRESS>)
NOTE 7.55.TYPE(POINT) :: T2
TYPE(COLOR_POINT) :: T3
CLASS(POINT) :: P2
CLASS(COLOR_POINT) :: P3
! Dummy argument is polymorphic and actual argument is of fixed type
SUBROUTINE SUB2 ( X2 ); CLASS(POINT) :: X2; ...
SUBROUTINE SUB3 ( X3 ); CLASS(COLOR_POINT) :: X3; ...
CALL SUB2 ( T2 ) ! Valid -- The declared type of T2 is the same as the
! declared type of X2.
CALL SUB2 ( T3 ) ! Valid -- The declared type of T3 is extended from
! the declared type of X2.
CALL SUB3 ( T2 ) ! Invalid -- The declared type of T2 is neither the
! same as nor extended from the declared type
! type of X3.
CALL SUB3 ( T3 ) ! Valid -- The declared type of T3 is the same as the
! declared type of X3.
! Actual argument is polymorphic and dummy argument is of fixed type
SUBROUTINE TUB2 ( D2 ); TYPE(POINT) :: D2; ...
SUBROUTINE TUB3 ( D3 ); TYPE(COLOR_POINT) :: D3; ...
CALL TUB2 ( P2 ) ! Valid -- The declared type of P2 is the same as the
! declared type of D2.
CALL TUB2 ( P3 ) ! Invalid -- The declared type of P3 differs from the
! declared type of D2.
CALL TUB2 ( P3%POINT ) ! Valid alternative to the above
CALL TUB3 ( P2 ) ! Invalid -- The declared type of P2 differs from the
! declared type of D3.
SELECT TYPE ( P2 ) ! Valid conditional alternative to the above
CLASS IS ( COLOR_POINT ) ! Works if the dynamic type of P2 is the same
CALL TUB3 ( P2 ) ! as the declared type of D3, or a type
! extended therefrom.
CLASS DEFAULT
! Cannot work if not.
END SELECT
CALL TUB3 ( P3 ) ! Valid -- The declared type of P3 is the same as the
! declared type of D3.! Both the actual and dummy arguments are of polymorphic type.
CALL SUB2 ( P2 ) ! Valid -- The declared type of P2 is the same as the
! declared type of X2.CALL SUB2 ( P3 ) ! Valid -- The declared type of P3 is extended from
! the declared type of X2.
586 ⃝c ISO/IEC 2017 – All rights reserved
ISO/IEC DIS 1539-1:2017 (E)CALL SUB3 ( P2 ) ! Invalid -- The declared type of P2 is neither the
! same as nor extended from the declaredSELECT TYPE ( P2 ) ! Valid conditional alternative to the above! type of X3.
CLASS IS ( COLOR_POINT ) ! Works if the dynamic type of P2 is the
CALL SUB3 ( P2 ) ! same as the declared type of X3, or a! type extended therefrom.
CLASS DEFAULT
! Cannot work if not.
END SELECT
CALL SUB3 ( P3 ) ! Valid -- The declared type of P3 is the same as the
! declared type of X3.
C.10.6 Rules ensuring unambiguous generics (<IP_ADDRESS>.5) 1 The rules in <IP_ADDRESS>.5 are intended to ensure
• that it is possible to reference each specific procedure or binding in the generic collection,2 Interfaces of specific procedures or bindings are distinguished by fixed properties of their arguments, specifically• that for any valid generic procedure reference, the determination of the specific procedure referenced is
unambiguous, and
• that the determination of the specific procedure or binding referenced can be made before execution of the
program begins (during compilation).
type, kind type parameters, rank, and whether the dummy argument has the POINTER or ALLOCATABLE3 Although the declared type of a data entity is a fixed property, polymorphic variables allow for a limited degreeattribute. A valid reference to one procedure in a generic collection will differ from another because it has an
argument that the other cannot accept, because it is missing an argument that the other requires, or because one
of these fixed properties is different.
of type mismatch between dummy arguments and actual arguments, so the requirement for distinguishing two4 That same limited type mismatch means that two dummy arguments that are not type incompatible can bedummy arguments is type incompatibility, not merely different types. (This is illustrated in the BAD6 example
later in this note.)
distinguished on the basis of the values of the kind type parameters they have in common; if one of them has a5 Rank is a fixed property, but some forms of array dummy arguments allow rank mismatches when a procedure iskind type parameter that the other does not, that is irrelevant in distinguishing them.
referenced by its specific name. In order to allow rank to always be usable in distinguishing generics, such rank6 For procedures referenced as operators or defined-assignment, syntactically distinguished arguments are mappedmismatches are disallowed for those arguments when the procedure is referenced as part of a generic. Additionally,
the fact that elemental procedures can accept array arguments is not taken into account when applying these rules,
so apparent ambiguity between elemental and nonelemental procedures is possible; in such cases, the reference is
interpreted as being to the nonelemental procedure.
to specific positions in the argument list, so the rule for distinguishing such procedures is that it be possible to7 For defined input/output procedures, only the dtv argument corresponds to something explicitly written in thedistinguish the arguments at one of the argument positions.
⃝c ISO/IEC 2017 – All rights reserved 587
ISO/IEC DIS 1539-1:2017 (E)
program, so it is the dtv that is required to be distinguished. Because dtv arguments are required to be scalar,8 For generic procedure names, the rules are more complicated because optional arguments can be omitted andthey cannot differ in rank. Thus this rule effectively involves only type and kind type parameters.
because arguments can be specified either positionally or by name.9 In the special case of type-bound procedures with passed-object dummy arguments, the passed-object argument
is syntactically distinguished in the reference, so rule (3) in <IP_ADDRESS>.5 can be applied. The type of passed-object10 The primary means of distinguishing named generics is rule (4). The most common application of that rule is aarguments is constrained in ways that prevent passed-object arguments in the same scoping unit from being type
incompatible. Thus this rule effectively involves only kind type parameters and rank.
single argument satisfying both (4a) and (4b):11 Whether one writes GOOD1(1.0) or GOOD1(X=1.0), the reference is to F1A because F1B would require an integerINTERFACE GOOD1
FUNCTION F1A(X)
REAL :: F1A,X
END FUNCTION F1A
FUNCTION F1B(X)
INTEGER :: F1B,X
END FUNCTION F1B
END INTERFACE GOOD1
argument whereas these references provide the real constant 1.0.12 This example and those that follow are expressed using interface bodies, with type as the distinguishing property.
This was done to make it easier to write and describe the examples. The principles being illustrated are equally13 Another common variant is the argument that satisfies (4a) and (4b) by being required in one specific andapplicable when the procedures get their explicit interfaces in some other way or when kind type parameters or
rank are the distinguishing property.
completely missing in the other:14 Whether one writes GOOD2(0.0,1.0), GOOD2(0.0,Y=1.0), or GOOD2(Y=1.0,X=0.0), the reference is to F2B,INTERFACE GOOD2
FUNCTION F2A(X)
REAL :: F2A,X
END FUNCTION F2A
FUNCTION F2B(X,Y)
COMPLEX :: F2B
REAL :: X,Y
END FUNCTION F2B
END INTERFACE GOOD2
because F2A has no argument in the second position or with the name Y. This approach is used as an alternative15 It is possible to construct cases where different arguments are used to distinguish positionally and by name:to optional arguments when one wants a function to have different result type, kind type parameters, or rank,
depending on whether the argument is present. In many of the intrinsic functions, the DIM argument works this
way.
588 ⃝c ISO/IEC 2017 – All rights reserved
ISO/IEC DIS 1539-1:2017 (E)
INTERFACE GOOD316 If one writes GOOD3(1.0,2,3.0,4) to reference S3A, then the third and fourth arguments are consistent with aSUBROUTINE S3A(W,X,Y,Z)
REAL :: W,Y
INTEGER :: X,Z
END SUBROUTINE S3A
SUBROUTINE S3B(X,W,Z,Y)
REAL :: W,Z
INTEGER :: X,Y
END SUBROUTINE S3B
END INTERFACE GOOD3
reference to S3B, but the first and second are not. If one switches to writing the first two arguments as keyword17 The ordering requirement in rule (4) is critical:arguments in order for them to be consistent with a reference to S3B, the latter two arguments will also need
to be written as keyword arguments, GOOD3(X=2,W=1.0,Z=4,Y=3.0), and the named arguments Y and Z are
distinguished.
INTERFACE BAD4 ! this interface is invalid !18 In this example, the positionally distinguished arguments are Y and Z, and it is W and X that are distinguished bySUBROUTINE S4A(W,X,Y,Z)
REAL :: W,Y
INTEGER :: X,Z
END SUBROUTINE S4A
SUBROUTINE S4B(X,W,Z,Y)
REAL :: X,Y
INTEGER :: W,Z
END SUBROUTINE S4B
END INTERFACE BAD4
name. In this order it is possible to write BAD4(1.0,2,Y=3.0,Z=4), which is a valid reference for both S4A and19 Rule (1) can be used to distinguish some cases that are not covered by rule (4):S4B.
INTERFACE GOOD520 In attempting to apply rule (4), position 2 and name Y are distinguished, but they are in the wrong order, just likeSUBROUTINE S5A(X)
REAL :: X
END SUBROUTINE S5A
SUBROUTINE S5B(Y,X)
REAL :: Y,X
END SUBROUTINE S5B
END INTERFACE GOOD5
the BAD4 example. However, when we try to construct a similarly ambiguous reference, we get GOOD5(1.0,X=2.0),21 The application of rule (1) becomes more complicated when extensible types are involved. If FRUIT is an extensible⃝c ISO/IEC 2017 – All rights reserved 589
ISO/IEC DIS 1539-1:2017 (E)
which can’t be a reference to S5A because it would be attempting to associate two different actual arguments
with the dummy argument X. Rule (4) catches this case by recognizing that S5B requires two real arguments, and
S5A cannot possibly accept more than one.
type, PEAR and APPLE are extensions of FRUIT, and BOSC is an extension of PEAR, then22 It is important to try rule (1) for each type that appears:INTERFACE BAD6 ! this interface is invalid !
SUBROUTINE S6A(X,Y)
CLASS(PEAR) :: X,Y
END SUBROUTINE S6A
SUBROUTINE S6B(X,Y)
CLASS(FRUIT) :: X
CLASS(BOSC) :: Y
END SUBROUTINE S6B
END INTERFACE BAD6
might, at first glance, seem distinguishable this way, but because of the limited type mismatching allowed,
BAD6(A_PEAR,A_BOSC) is a valid reference to both S6A and S6B.
INTERFACE GOOD723 Looking at the most general type, S7A has a minimum and maximum of 3 FRUIT arguments, while S7B has aSUBROUTINE S7A(X,Y,Z)
CLASS(PEAR) :: X,Y,Z
END SUBROUTINE S7A
SUBROUTINE S7B(X,Z,W)
CLASS(FRUIT) :: X
CLASS(BOSC) :: Z
CLASS(APPLE),OPTIONAL :: W
END SUBROUTINE S7B
END INTERFACE GOOD7
minimum of 2 and a maximum of three. Looking at the most specific, S7A has a minimum of 0 and a maximum24 In identifying the minimum number of arguments with a particular set of properties, we exclude optional argu-of 3 BOSC arguments, while S7B has a minimum of 1 and a maximum of 2. However, when we look at the
intermediate, S7A has a minimum and maximum of 3 PEAR arguments, while S7B has a minimum of 1 and a
maximum of 2. Because S7A’s minimum exceeds S7B’s maximum, they can be distinguished.
ments and test TKR compatibility, so the corresponding actual arguments are required to have those properties.25 These rules are sufficient to ensure that references to procedures that meet them are unambiguous, but thereIn identifying the maximum number of arguments with those properties, we include the optional arguments and
test not distinguishable, so we include actual arguments which could have those properties but are not required
to have them.
remain examples that fail to meet these rules but which can be shown to be unambiguous:26 This interface fails rule (4) because there are no required arguments that can be distinguished from the positionallyINTERFACE BAD8 ! this interface is invalid !
! despite the fact that it is unambiguous !
590 ⃝c ISO/IEC 2017 – All rights reserved
ISO/IEC DIS 1539-1:2017 (E)
SUBROUTINE S8A(X,Y,Z)
REAL,OPTIONAL :: X
INTEGER :: Y
REAL :: Z
END SUBROUTINE S8A
SUBROUTINE S8B(X,Z,Y)
INTEGER,OPTIONAL :: X
INTEGER :: Z
REAL :: Y
END SUBROUTINE S8B
END INTERFACE BAD8
corresponding argument, but in order for the mismatch of the optional arguments not to be relevant, the later27 If one dummy argument has the POINTER attribute and a corresponding argument in the other interface bodyarguments need to be specified as keyword arguments, so distinguishing by name does the trick. This interface is
nevertheless invalid so a standard-conforming Fortran processor is not required to do such reasoning. The rules
to cover all cases are too complicated to be useful.
has the ALLOCATABLE attribute the generic interface is not ambiguous. If one dummy argument has either the1 Parallel programs sometimes have apparently impossible behavior because data transfers and other messages canPOINTER or ALLOCATABLE attribute and a corresponding argument in the other interface body has neither
attribute, the generic interface might be ambiguous.
C.11 Clause 16 notes
C.11.1 Atomic memory consistency
C.11.1.1 Relaxed memory model
be delayed, reordered and even repeated, by hardware, communication software, and caching and other forms1 When variables are being referenced (atomically) from segments that are unordered with respect to the segmentof optimization. Requiring processors to deliver globally consistent behavior is incompatible with performance
on many systems. This document specifies that all ordered actions will be consistent (5.3.5 and 11.6), but all
consistency between unordered segments is deliberately left processor dependent. Depending on the hardware,
this can be observed even when only two images and one mechanism are involved.
C.11.1.2 Examples with atomic operations
that is atomically defining or redefining the variables, the results are processor dependent. This supports use2 The following examples assume these declarations:of so-called “relaxed memory model” architectures, which can enable more efficient execution on some hardware
implementations.
MODULE EXAMPLE
USE,INTRINSIC :: ISO_FORTRAN_ENV
INTEGER(ATOMIC_INT_KIND) :: X [*] = 0, Y [*] = 0, TMP
3 Example 1
⃝c ISO/IEC 2017 – All rights reserved 591
ISO/IEC DIS 1539-1:2017 (E)
With X [j] and Y [j] still in their initial state (both zero), image j executes the following sequence of statements:CALL ATOMIC_DEFINE (X, 1)
CALL ATOMIC_DEFINE (Y, 1)
and a different image, k, executes the following sequence of statements:
DO
CALL ATOMIC_REF (TMP, Y [j ])
IF (TMP==1) EXIT
END DO
CALL ATOMIC_REF (TMP, X [j ])
PRINT *, TMP
4 The final value of TMP on image k could be either 0 or 1. That is, even though image j thinks that it defined X
[j] before it defined Y [j], this ordering is not guaranteed to be observed on image k. There are many aspects of5 Even if image j executed the sequencehardware and software implementation that can cause this effect, but conceptually this example can be thought
of as the change in the value of Y propagating faster through the inter-image connections than the change in the
value of X.
CALL ATOMIC_DEFINE (X, 1)
SYNC MEMORY
CALL ATOMIC_DEFINE (Y, 1)
the same effect could be seen. That is because even though X and Y are defined in ordered segments, the
references from image k are both from a segment that is unordered with respect to image j.
6 Only if the reference on image k to Y [j] is in a segment that is ordered after the segment on image j that defined
Y, will TMP be guaranteed to have the value 1.7 Example 2:
With the initial state of X and Y on image j (i.e. X [j] and Y [j]) still being zero, execution of8 This can happen by such mechanisms as “load buffering”; one might imagine that what is happening is thatCALL ATOMIC_REF (TMP, X [j ])
CALL ATOMIC_DEFINE (Y [j ], 1)
PRINT *, TMP
on image k1 , and execution of
CALL ATOMIC_REF (TMP, Y [j ])
CALL ATOMIC_DEFINE (X [j ], 1)
PRINT *, TMP
on image k2 , in unordered segments, might print the value 1 both times.
the definitions (ATOMIC_DEFINE) are overtaking the references (ATOMIC_REF). On some processors it is9 Example 3:592 ⃝c ISO/IEC 2017 – All rights reserved
ISO/IEC DIS 1539-1:2017 (E)
possible that insertion of SYNC MEMORY statements between the calls to ATOMIC_REF and ATOMIC_-
DEFINE might be sufficient to make the output print the value 1 at most one time (or even exactly one time),
but this is still processor dependent unless the SYNC MEMORY statement executions cause the relevant segments
on images k1 and k2 to be ordered.
Because there are no segment boundaries implied by collective subroutines, with the initial state as before,execution of
IF (THIS_IMAGE ()==1) THEN
CALL ATOMIC_DEFINE (X [3], 23)
Y = 42
END IF
CALL CO_BROADCAST (Y, 1)
IF (THIS_IMAGE ()==2) THEN
CALL ATOMIC_REF (TMP, X [3])PRINT *, Y, TMP
END IF
could print the values 42 and 0.
10 Example 4:
Assuming the declarationsINTEGER (ATOMIC_INT_KIND) :: X [*] = 0, Z = 0
the statements
CALL ATOMIC_ADD (X [1], 1) ! (A)
IF (THIS_IMAGE() == 2) THEN
wait: DO
CALL ATOMIC_REF (Z, X [1]) ! (B)
IF (Z == NUM_IMAGES ()) EXIT wait
END DO wait ! (C)
END IF
will execute the “wait” loop on image 2 until all images have completed statement (A). The updates of X [1] are
performed by each image in the same manner, but in an arbitrary order. Because the result from the complete
set of updates will eventually become visible by execution of statement (B) for some loop iteration on image 2,
the termination condition is guaranteed to be eventually fulfilled, provided that no image failure occurs, every
image executes the above code, and no other code is executed in an unordered segment that performs an update
to X [1]. Furthermore, if two SYNC MEMORY statements are inserted in the above code before statement (A)
and after statement (C), respectively, the segment started by the second SYNC MEMORY on image 2 is ordered
after the segments on all images that end with the first SYNC MEMORY.
C.11.2 EVENT_QUERY example 1 The following example illustrates the use of events via a program in which image 1 acts as the master image,
distributing work items to the other images. Only one work item at a time can be active on a worker image, andISO/IEC DIS 1539-1:2017 (E)each deals with the result (e.g. via input/output) without directly feeding data back to the master image.
⃝c ISO/IEC 2017 – All rights reserved 593
2 Because the work items are not expected to be balanced, the master keeps cycling through all images to find one
that is waiting for work.3 An event is posted by each worker to indicate that it has completed its work item. Since the corresponding
variables are needed only on the master, we place them in an allocatable array component of a coarray. An eventon each worker is needed for the master to post the fact that it has made a work item available for it.
Example code:
PROGRAM work_share
USE, INTRINSIC :: ISO_FORTRAN_ENV, ONLY: EVENT_TYPE
USE :: mod_work, ONLY: & ! Module that creates work items
work, & ! Type for holding a work item
create_work_item, & ! Function that creates work item
process_item, & ! Function that processes an item
work_done ! Logical function that returns true
! if all work has been done.
TYPE :: worker_type
TYPE (EVENT_TYPE), ALLOCATABLE :: free (:)
END TYPE
INTEGER :: count, i, nbusy [*]
TYPE (EVENT_TYPE) :: submit [*] ! Post when work ready for a worker TYPE (worker_type) :: worker [*] ! Post when worker is free TYPE (work) :: work_item [*] ! Holds the data for a work item IF (THIS_IMAGE ()==1) THEN
! Get startedALLOCATE (worker%free (2:NUM_IMAGES ()))
nbusy = 0 ! This holds the number of workers working
DO i = 2, NUM_IMAGES () ! Start the workers working
IF (work_done ()) EXIT
nbusy = nbusy + 1
work_item [i] = create_work_item ()
EVENT POST (submit [i])
END DO
! Main work distribution loop
master: DO
image: DO i = 2, NUM_IMAGES ()CALL EVENT_QUERY (worker%free (i), count)
IF (count==0) CYCLE image ! Worker is not free
EVENT WAIT (worker%free (i))
nbusy = nbusy - 1
IF (work_done ()) CYCLE
nbusy = nbusy + 1
work_item [i] = create_work_item ()
EVENT POST (submit [i])
END DO image
594 ⃝c ISO/IEC 2017 – All rights reserved
ISO/IEC DIS 1539-1:2017 (E)IF (nbusy==0) THEN
! All done. Exit on all images.DO i = 2, NUM_IMAGES ()
EVENT POST (submit [i])
END DO
EXIT master
END IF
END DO master
ELSE
! Work processing loop
worker: DO
EVENT WAIT (submit)END DO workerIF (nbusy[1] == 0) EXIT
CALL process_item (work_item)
EVENT POST (worker [1]%free (THIS_IMAGE ()))
END IF
END PROGRAM work_share
C.11.3 Collective subroutine examples 1 The following example computes a dot product of two scalar coarrays using CO_SUM to store the result in a
noncoarray scalar variable.2 The function below demonstrates passing a noncoarray dummy argument to CO_MAX. The function uses CO_-SUBROUTINE codot (x, y, x_dot_y)
REAL :: x [*], y [*], x_dot_y
x_dot_y = x*y
CALL CO_SUM (x_dot_y)
END SUBROUTINE codot
MAX to find the maximum value of the dummy argument across all images. Then the function flags all imagesthat hold values matching the maximum. The function then returns the maximum image index for an image that
holds the maximum value.
FUNCTION find_max (j) RESULT (j_max_location)
INTEGER, INTENT (IN) :: j
INTEGER j_max, j_max_location
j_max = j
CALL CO_MAX (j_max)
! Flag images that hold the maximum j.
IF (j==j_max) THEN
j_max_location = THIS_IMAGE ()
ELSE
j_max_location = 0
END IF
! Return highest image index associated with a maximal j.
CALL CO_MAX(j_max_location)
END FUNCTION find_max
⃝c ISO/IEC 2017 – All rights reserved 595
ISO/IEC DIS 1539-1:2017 (E)
C.12 Clause 18 notes C.12.1 Runtime environments (18.1) 1 This document allows programs to contain procedures defined by means other than Fortran. That raises the
issues of initialization of and interaction between the runtime environments involved.2 Implementations are free to solve these issues as they see fit, provided that
• heap allocation/deallocation (e.g., (DE)ALLOCATE in a Fortran subprogram and malloc/free in a C func-tion) can be performed without interference,
• input/output to and from external files can be performed without interference, as long as procedures defined
by different means do not do input/output with the same external file,
• input/output preconnections exist as required by the respective standards, and
• initialized data are initialized according to the respective standards.
C Function Prototype:
C.12.2 Example of Fortran calling C (18.3)
int C_Library_Function(void* sendbuf, int sendcount, int *recvcounts);Fortran Module:
MODULE CLIBFUN_INTERFACE
INTERFACE
INTEGER (C_INT) FUNCTION C_LIBRARY_FUNCTION (SENDBUF, SENDCOUNT, RECVCOUNTS) &
BIND(C, NAME=’C_Library_Function’)USE, INTRINSIC :: ISO_C_BINDING
IMPLICIT NONE
TYPE (C_PTR), VALUE :: SENDBUF
INTEGER (C_INT), VALUE :: SENDCOUNT
INTEGER (C_INT) :: RECVCOUNTS(*)
END FUNCTION C_LIBRARY_FUNCTION
END INTERFACE
END MODULE CLIBFUN_INTERFACE
1 The module CLIBFUN_INTERFACE contains the declaration of the Fortran dummy arguments, which corres-
pond to the C formal parameters. The NAME= is used in the BIND attribute in order to handle the case-sensitive2 The first C formal parameter is the pointer to void sendbuf, which corresponds to the Fortran dummy argumentname change between Fortran and C from “c_library_function” to “C_Library_Function”.
SENDBUF, which has the type C_PTR and the VALUE attribute.3 The second C formal parameter is the int sendcount, which corresponds to the Fortran dummy argument
SENDCOUNT, which has the type INTEGER (C_INT) and the VALUE attribute.4 The third C formal parameter is the pointer to int recvcounts, which corresponds to the Fortran dummy
argument RECVCOUNTS, which is an assumed-size array of type INTEGER (C_INT).5 This example shows how C_Library_Function might be referenced in a Fortran program unit:596 ⃝c ISO/IEC 2017 – All rights reserved
ISO/IEC DIS 1539-1:2017 (E)
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_INT, C_FLOAT, C_LOC
USE CLIBFUN_INTERFACE
...
REAL (C_FLOAT), TARGET :: SEND(100)
INTEGER (C_INT), ALLOCATABLE :: RECVCOUNTS(:)
INTEGER (C_INT) :: SENDCOUNT, RET ...
ALLOCATE( RECVCOUNTS(100) )
...
RET = C_LIBRARY_FUNCTION(C_LOC(SEND), SENDCOUNT, RECVCOUNTS)
...
6 The first Fortran actual argument is a reference to the function C_LOC which returns the value of the C address
of its argument, SEND. This value becomes the value of the first formal parameter, the pointer sendbuf, in7 The second Fortran actual argument is SENDCOUNT of type INTEGER (C_INT). Its value becomes the initialC_Library_Function.
value of the second formal parameter, the int sendcount, in C_Library_Function.8 The third Fortran actual argument is the allocatable array RECVCOUNTS of type INTEGER (C_INT). The
base C address of this array becomes the value of the third formal parameter, the pointer recvcounts, inC_Library_Function. Note that interoperability is based on the characteristics of the dummy arguments in
the specified interface and not on those of the actual arguments. Thus, the fact that the actual argument is
allocatable is not relevant here.
C.12.3 Example of C calling Fortran (18.3)
Fortran Code:
SUBROUTINE SIMULATION(ALPHA, BETA, GAMMA, DELTA, ARRAYS) BIND(C)
USE, INTRINSIC :: ISO_C_BINDING
IMPLICIT NONE
REAL (C_DOUBLE),DIMENSION(*),INTENT(IN) :: DELTA
INTEGER (C_LONG), VALUE :: ALPHA REAL (C_DOUBLE), INTENT(INOUT) :: BETA INTEGER (C_LONG), INTENT(OUT) :: GAMMA TYPE, BIND(C) :: PASS
INTEGER (C_INT) :: LENC, LENFTYPE (C_PTR) :: C, F
END TYPE PASS
TYPE (PASS), INTENT(INOUT) :: ARRAYS
REAL (C_FLOAT), ALLOCATABLE, TARGET, SAVE :: ETA(:)
REAL (C_FLOAT), POINTER :: C_ARRAY(:)
...
! Associate C_ARRAY with an array allocated in C
CALL C_F_POINTER (ARRAYS%C, C_ARRAY, [ ARRAYS%LENC ])
⃝c ISO/IEC 2017 – All rights reserved 597
ISO/IEC DIS 1539-1:2017 (E)
...! Allocate an array and make it available in C
ARRAYS%LENF = 100
ALLOCATE (ETA(ARRAYS%LENF))
ARRAYS%F = C_LOC(ETA)
...
END SUBROUTINE SIMULATION
C Struct Declaration:
struct pass {C Function Prototype:int lenc, lenf;
float *c, *f;
};
void simulation(long alpha, double *beta, long *gamma, double delta[],C Calling Sequence:struct pass *arrays);
simulation(alpha, beta, gamma, delta, arrays);1 The above-listed Fortran code specifies a subroutine SIMULATION. This subroutine corresponds to the C void
function simulation.2 The Fortran subroutine references the intrinsic module ISO_C_BINDING.
3 The first Fortran dummy argument of the subroutine is ALPHA, which has the type INTEGER(C_LONG) and
the VALUE attribute. This dummy argument corresponds to the C formal parameter alpha, which is a long.4 The second Fortran dummy argument of the subroutine is BETA, which has the type REAL(C_DOUBLE) andThe C actual argument is also a long.
the INTENT (INOUT) attribute. This dummy argument corresponds to the C formal parameter beta, which is5 The third Fortran dummy argument of the subroutine is GAMMA, which has the type INTEGER(C_LONG)a pointer to double. An address is passed as the C actual argument.
and the INTENT (OUT) attribute. This dummy argument corresponds to the C formal parameter gamma, which6 The fourth Fortran dummy argument is the assumed-size array DELTA, which has the type REAL (C_DOUBLE)is a pointer to long. An address is passed as the C actual argument.
and the INTENT (IN) attribute. This dummy argument corresponds to the C formal parameter delta, which is7 The fifth Fortran dummy argument is ARRAYS, which is a structure for accessing an array allocated in C anda double array. The C actual argument is also a double array.
an array allocated in Fortran. The lengths of these arrays are held in the components LENC and LENF; their C1 Many Fortran processors support 16-byte real numbers, which might not be supported by the C processor.addresses are held in components C and F.
598 ⃝c ISO/IEC 2017 – All rights reserved
ISO/IEC DIS 1539-1:2017 (E)
C.12.4 Example of calling C functions with noninteroperable data (18.10)
Assume a Fortran programmer wants to use a C procedure from a message passing library for an array of thesereals. The C prototype of this procedure is
void ProcessBuffer(void *buffer, int n_bytes);
with the corresponding Fortran interface
USE, INTRINSIC :: ISO_C_BINDING
INTERFACE
SUBROUTINE PROCESS_BUFFER(BUFFER,N_BYTES) BIND(C,NAME="ProcessBuffer")
IMPORT :: C_PTR, C_INTTYPE(C_PTR), VALUE :: BUFFER ! The ‘‘C address’’ of the array buffer
INTEGER (C_INT), VALUE :: N_BYTES ! Number of bytes in buffer
END SUBROUTINE PROCESS_BUFFER
END INTERFACE
2 This can be done using C_LOC if the particular Fortran processor specifies that C_LOC returns an appropriate
address:1 The following example demonstrates how a Fortran processor can make a modern object-oriented random numberREAL(R_QUAD), DIMENSION(:), ALLOCATABLE, TARGET :: QUAD_ARRAY
...
CALL PROCESS_BUFFER(C_LOC(QUAD_ARRAY), INT(16*SIZE(QUAD_ARRAY),C_INT))
! One quad real takes 16 bytes on this processor
C.12.5 Example of opaque communication between C and Fortran (18.3)
generator written in Fortran available to a C program.USE, INTRINSIC :: ISO_C_BINDING
! Assume this code is inside a module
TYPE RANDOM_STREAM
! A (uniform) random number generator (URNG)
CONTAINS
PROCEDURE(RANDOM_UNIFORM), DEFERRED, PASS(STREAM) :: NEXT
! Generates the next number from the stream
END TYPE RANDOM_STREAM
ABSTRACT INTERFACE
! Abstract interface of Fortran URNG
SUBROUTINE RANDOM_UNIFORM(STREAM, NUMBER)
IMPORT :: RANDOM_STREAM, C_DOUBLECLASS(RANDOM_STREAM), INTENT(INOUT) :: STREAM
REAL(C_DOUBLE), INTENT(OUT) :: NUMBER
END SUBROUTINE RANDOM_UNIFORM
END INTERFACE
⃝c ISO/IEC 2017 – All rights reserved 599
ISO/IEC DIS 1539-1:2017 (E)2 A polymorphic object with declared type RANDOM_STREAM is not interoperable with C. However, we can
make such a random number generator available to C by packaging it inside another nonpolymorphic, nonpara-meterized derived type:
TYPE :: URNG_STATE ! No BIND(C), as this type is not interoperable
CLASS(RANDOM_STREAM), ALLOCATABLE :: STREAM
END TYPE URNG_STATE
3 The following two procedures will enable a C program to use our Fortran uniform random number generator:
! Initialize a uniform random number generator:SUBROUTINE INITIALIZE_URNG(STATE_HANDLE, METHOD) &
BIND(C, NAME="InitializeURNG")
TYPE(C_PTR), INTENT(OUT) :: STATE_HANDLE
! An opaque handle for the URNG
CHARACTER(C_CHAR), DIMENSION(*), INTENT(IN) :: METHOD
! The algorithm to be used
TYPE(URNG_STATE), POINTER :: STATE
! An actual URNG object
ALLOCATE(STATE)
! There needs to be a corresponding finalization
! procedure to avoid memory leaks, not shown in this example
! Allocate STATE%STREAM with a dynamic type depending on METHOD
...
STATE_HANDLE=C_LOC(STATE)
! Obtain an opaque handle to return to C
END SUBROUTINE INITIALIZE_URNG
! Generate a random number:
SUBROUTINE GENERATE_UNIFORM(STATE_HANDLE, NUMBER) &
BIND(C, NAME="GenerateUniform")TYPE(C_PTR), INTENT(IN), VALUE :: STATE_HANDLE
! An opaque handle: Obtained via a call to INITIALIZE_URNGREAL(C_DOUBLE), INTENT(OUT) :: NUMBER
TYPE(URNG_STATE), POINTER :: STATE
! A pointer to the actual URNGCALL C_F_POINTER(CPTR=STATE_HANDLE, FPTR=STATE)
! Convert the opaque handle into a usable pointerCALL STATE%STREAM%NEXT(NUMBER)
! Use the type-bound procedure NEXT to generate NUMBER
END SUBROUTINE GENERATE_UNIFORM
600 ⃝c ISO/IEC 2017 – All rights reserved
ISO/IEC DIS 1539-1:2017 (E)
C.12.6 Using assumed type to interoperate with C C.12.6.1 Overview 1 The mechanism for handling unlimited polymorphic entities whose dynamic type is interoperable with C is
designed to handle the following two situations:2 In the first situation, it is the programmer’s responsibility to explicitly provide any information needed on the(1) A formal parameter that is a C pointer to void. This is an address, and no further information
about the entity is provided. The formal parameter corresponds to a dummy argument that is a
nonallocatable nonpointer scalar or is an assumed-size array.
(2) A formal parameter that is the address of a C descriptor. Additional information on the status, type,
size, and shape is implicitly provided. The formal parameter corresponds to a dummy argument that
is assumed-shape or assumed-rank.
status, type, size, and shape of the entity.1 A C interface for message passing or input/output functionality could be provided in the formC.12.6.2 Mapping of interfaces with void * C parameters to Fortran
int EXAMPLE_send(const void *buffer, size_t buffer_size, const HANDLE_t *handle);where the buffer_size argument is given in units of bytes, and the handle argument (which is of a type aliased
to int) provides information about the target the buffer is to be transferred to. In this example, type resolution
is not required.
2 The first method provides a thin binding; a call to EXAMPLE_send from Fortran directly invokes the C function.
INTERFACE
INTEGER (C_INT) FUNCTION example_send(buffer, buffer_size, handle) &
BIND(C, NAME=’EXAMPLE_send’)
USE, INTRINSIC :: ISO_C_BINDINGTYPE(*), INTENT (IN) :: buffer(*)
INTEGER (C_SIZE_T), VALUE :: buffer_size
INTEGER (C_INT), INTENT (IN) :: handle
END FUNCTION
END INTERFACE
3 It is assumed that this interface is declared in the specification part of the module MOD_EXAMPLE_OLD. An
example of its use follows:USE, INTRINSIC :: ISO_C_BINDING
USE MOD_EXAMPLE_OLD
REAL(C_FLOAT) :: x(100)
INTEGER(C_INT) :: y(10,10)
REAL(C_DOUBLE) :: z
INTEGER(C_INT) :: status, handle
...
⃝c ISO/IEC 2017 – All rights reserved 601
ISO/IEC DIS 1539-1:2017 (E)
! Assign values to x, y, z and initialize handle.4 In those invocations, x and y are passed directly with sequence association, but it is necessary to make an array...
! Send values in x, y, and z using EXAMPLE_send.
status = example_send(x, C_SIZEOF(x), handle)
status = example_send(y, C_SIZEOF(y), handle)
status = example_send([ z ], C_SIZEOF(z), handle)
expression containing the value of z to pass it.5 The second method provides a Fortran interface which is easier to use, but requires writing a separate C wrapper
routine. With this method, a C descriptor is created because the buffer is assumed-rank in the Fortran interface;the use of an optional argument is also demonstrated.
INTERFACE
SUBROUTINE example_send(buffer, handle, status) BIND(C, NAME="EG_send_fortran")
USE, INTRINSIC :: ISO_C_BINDINGTYPE(*), CONTIGUOUS, INTENT (IN) :: buffer(..)
INTEGER (C_INT), INTENT (IN) :: handle
INTEGER (C_INT), INTENT(OUT), OPTIONAL :: status
END SUBROUTINE
END INTERFACE
6 It is assumed that this interface is declared in the specification part of a module MOD_EXAMPLE_NEW.
Example invocations from Fortran are thenUSE, INTRINSIC :: iso_c_binding
USE mod_example_new
TYPE, BIND(C) :: my_derived
INTEGER(C_INT) :: len_used
REAL(C_FLOAT) :: stuff(100)
END TYPE
TYPE(my_derived) :: w(3)
REAL(C_FLOAT) :: x(100)
INTEGER(C_INT) :: y(10,10)
REAL(C_DOUBLE) :: z
INTEGER(C_INT) :: status, handle
...
! Assign values to w, x, y, z and initialize handle.
...
! Send values in w, x, y, and z using example_send.
 Fifth column of y.
CALL example_send(y(1,5), handle) ! Scalar y(1,5) passed by descriptor.
1 An assumed-type dummy argument in a Fortran procedure can be used as an actual argument corresponding to an
602 c ISO/IEC 2017 – All rights reserved7 The wrapper routine can be written in C as follows.
ISO/IEC DIS 1539-1:2017 (E)
#include "ISO_Fortran_binding.h"void EXAMPLE_send_fortran(const CFI_cdesc_t *buffer, const HANDLE_t *handle,
int *status)
{
int status_local;
size_t buffer_size;
int i;
buffer_size = buffer->elem_len;
for (i=0; i<buffer->rank; i++) {
buffer_size *= buffer->dim[i].extent;
}
status_local = EXAMPLE_send(buffer->base_addr,buffer_size, handle);
if (status != NULL) *status = status_local;
}
C.12.7 Using assumed-type variables in Fortran
assumed-type dummy in a call to another procedure. In the following example, the Fortran subroutine SIMPLE_-SEND serves as a wrapper to hide the complications associated with calls to a C function named ACTUAL_Send.
Module COMM_INFO contains node and address information for the current data transfer operations.
SUBROUTINE SIMPLE_SEND(buffer, nbytes)
USE comm_info, ONLY: my_node, r_node, r_addr
USE, INTRINSIC :: ISO_C_BINDING
IMPLICIT NONE
TYPE(*), INTENT (IN) :: buffer(*)
INTEGER :: nbytes, ierr INTERFACE
SUBROUTINE actual_Send(buffer, nbytes, node, addr, ierr) &
BIND(C, NAME="ACTUAL_Send")
IMPORT :: C_SIZE_T, C_INT, C_INTPTR_TEND SUBROUTINE actual_SendTYPE(*), INTENT (IN) :: buffer(*)
INTEGER(C_SIZE_T), VALUE :: nbytes
INTEGER(C_INT), VALUE :: node
INTEGER(C_INTPTR_T), VALUE :: addr
INTEGER(C_INT), INTENT(OUT) :: ierr
END INTERFACE
CALL actual_Send(buffer, INT(nbytes, C_SIZE_T), r_node, r_addr, ierr)
⃝c ISO/IEC 2017 – All rights reserved 603
ISO/IEC DIS 1539-1:2017 (E)
IF (ierr /= 0) THENPRINT *, "Error sending from node", my_node, "to node", r_node
PRINT *, "Program Aborting" !  Omit in the recovery case
END IF
END SUBROUTINE simple_Send
C.12.8 Simplifying interfaces for arbitrary rank procedures 1 There are situations where an assumed-rank dummy argument can be useful in Fortran, although a Fortran
procedure cannot itself access its value. For example, the IEEE inquiry functions in Clause 14 could be written2 In particular, the specific procedures for the IEEE_SUPPORT_DIVIDE function could possibly be implementedusing an assumed-rank dummy argument instead of writing 16 separate specific routines, one for each possible
rank.
in Fortran as follows:1 The example shown below calculates the product of individual elements of arrays A and B and returns the resultINTERFACE ieee_support_divide
MODULE PROCEDURE ieee_support_divide_noarg, ieee_support_divide_onearg_r, &
ieee_support_divide_onearg_d
END INTERFACE ieee_support_divide
...
LOGICAL FUNCTION ieee_support_divide_noarg ()
ieee_support_divide_noarg = .TRUE.
END FUNCTION ieee_support_divide_noarg
LOGICAL FUNCTION ieee_support_divide_onearg_r (x)
REAL, INTENT (IN) :: x(..)
ieee_support_divide_onearg_r4 = .TRUE.
END FUNCTION ieee_support_divide_onearg_r
LOGICAL FUNCTION ieee_support_divide_onearg_d (x)
DOUBLE PRECISION, INTENT (IN) :: x(..)
ieee_support_divide_onearg_r8 = .TRUE.
END FUNCTION ieee_support_divide_onearg_d
C.12.9 Processing assumed-shape arrays in C
in array C. The Fortran interface of elemental_mult will accept arguments of any type and rank. However, the2 The Fortran interface is:C function will return an error code if any argument is not a two-dimensional int array. Note that the arguments
are permitted to be array sections, so the C function does not assume that any argument is contiguous.
604 ⃝
c ISO/IEC 2017 – All rights reserved
ISO/IEC DIS 1539-1:2017 (E)
INTERFACE
FUNCTION elemental_mult(a, b, c) BIND(C, NAME="elemental_mult_c") RESULT(err)
USE, INTRINSIC :: ISO_C_BINDINGEND FUNCTION elemental_multINTEGER(C_INT) :: err
TYPE(*), DIMENSION(..) :: a, b, c
END INTERFACE
3 The definition of the C function is:
#include "ISO_Fortran_binding.h"⃝int elemental_mult_c(CFI_cdesc_t * a_desc, CFI_cdesc_t * b_desc, CFI_cdesc_t * c_desc)
{
size_t i, j, ni, nj;
int err = 1; /* this error code represents all errors */
char * a_col = (char*) a_desc->base_addr;
char * b_col = (char*) b_desc->base_addr;
char * c_col = (char*) c_desc->base_addr;
char *a_elt, *b_elt, *c_elt;
/* Only support int. */
if (a_desc->type != CFI_type_int || b_desc->type != CFI_type_int ||
c_desc->type != CFI_type_int) {
return err;
}
/* Only support two dimensions. */
if (a_desc->rank != 2 || b_desc->rank != 2 || c_desc->rank != 2) {
return err;
}
ni = a_desc->dim[0].extent;
nj = a_desc->dim[1].extent;
/* Ensure the shapes conform. */
if (ni != b_desc->dim[0].extent || ni != c_desc->dim[0].extent) return err;
if (nj != b_desc->dim[1].extent || nj != c_desc->dim[1].extent) return err;
/* Multiply the elements of the two arrays. */
for (j = 0; j < nj; j++) {
a_elt = a_col;
b_elt = b_col;
c_elt = c_col;
c ISO/IEC 2017 – All rights reserved 605
ISO/IEC DIS 1539-1:2017 (E)
for (i = 0; i < ni; i++) {}*(int*)a_elt = *(int*)b_elt * *(int*)c_elt;
a_elt += a_desc->dim[0].sm;
b_elt += b_desc->dim[0].sm;
c_elt += c_desc->dim[0].sm;
}
a_col += a_desc->dim[1].sm;
b_col += b_desc->dim[1].sm;
c_col += c_desc->dim[1].sm;
return 0;
}
C.12.10 Creating a contiguous copy of an array 1 A C function might need to create a contiguous copy of an array section, for example, to pass the array section
as an actual argument corresponding to a dummy argument with the CONTIGUOUS attribute. The following2 The C functions are:example provides functions that can be used to copy an array described by a CFI_cdesc_t descriptor to a
contiguous buffer. The input array need not be contiguous.
#include "ISO_Fortran_binding.h"/* Other necessary includes omitted. */
/*
* Returns the number of elements in the object described by desc.
* If it is an array, it need not be contiguous.
* (The number of elements could be zero).
*/
size_t numElements(const CFI_cdesc_t * desc)
{
CFI_rank_t r;
size_t num = 1;
for (r = 0; r < desc->rank; r++) {
num *= desc->dim[r].extent;
}
return num;
}
/*
* Auxiliary recursive function to copy an array of a given rank.
* Recursion is useful because an array of rank n is composed of an
* ordered set of arrays of rank n-1.
*/
static void *_copyToContiguous (const CFI_cdesc_t *vald, void *output,
const void *input, CFI_rank_t rank)
606 ⃝c ISO/IEC 2017 – All rights reserved
ISO/IEC DIS 1539-1:2017 (E){
CFI_index_t e;}if (rank == 0) {
/* Copy scalar element. */
memcpy (output, input, vald->elem_len);
output = (void *)((char *)output + vald->elem_len);
}
else {
for (e = 0; e < vald->dim[rank-1].extent; e++) {
/* Recurse on subarrays of lesser rank. */
output = _copyToContiguous (vald, output, input, rank-1);
input = (void *) ((char *)input + vald->dim[rank].sm);
}
}
return output;
/*
*/
o General routine to copy the elements in the array described by vald o to buffer, as done by sequence association. The array itself can o be non-contiguous. This is not the most efficient approach. void copyToContiguous (void * buffer, const CFI_cdesc_t * vald) {
_copyToContiguous (vald, buffer, vald->base_addr, vald->rank);}
C.12.11 Changing the attributes of an array 1 A C programmer might want to call more than one Fortran procedure and the attributes of an array involved
might differ between the procedures. In this case, it is necessary to set up more than one C descriptor for the2 After invocation of the second CFI_establish, the lower bounds stored in the dim member of desc_assum willarray. For example, this code fragment initializes the first C descriptor for an allocatable entity of rank 2, calls
a procedure that allocates the array described by the first C descriptor, constructs the second C descriptor by
invoking CFI_section with the value CFI_attribute_other for the attribute parameter, then calls a procedure
that expects an assumed-shape array.
CFI_CDESC_T(2) loc_alloc, loc_assum;
CFI_cdesc_t * desc_alloc = (CFI_cdesc_t *)&loc_alloc,
* desc_assum = (CFI_cdesc_t *)&loc_assum;
CFI_index_t extents[2];
CFI_rank_t rank = 2;
int flag;
flag = CFI_establish(desc_alloc,
NULL,
CFI_attribute_allocatable,
CFI_type_double,
⃝c ISO/IEC 2017 – All rights reserved 607
ISO/IEC DIS 1539-1:2017 (E)
sizeof(double),
rank,
NULL);
Fortran_factor (desc_alloc, ...); /* Allocates array described by desc_alloc. */
/* Extract extents from descriptor. */
extents[0] = desc_alloc->dim[0].extent;
extents[1] = desc_alloc->dim[1].extent;
flag = CFI_establish(desc_assum,
desc_alloc->base_addr,
CFI_attribute_other,
CFI_type_double,
sizeof(double),
rank,
extents);
Fortran_solve (desc_assum, ...); /* Uses array allocated in Fortran_factor. */
have the value 0 even if the corresponding entries in desc_alloc have different values.1 The C function set_odd sets every second element of an array to a specific value, beginning with the first element.C.12.12 Creating an array section in C using CFI_section
If does this by making an array section descriptor for the elements to be set, and calling a Fortran subroutineSET_ALL that sets every element of an assumed-shape array to a specific value. An interface block for set_odd
permits it to be also called from Fortran.
SUBROUTINE set_all(int_array, val) BIND(C)
INTEGER(C_INT) :: int_array(:)
INTEGER(C_INT), VALUE :: val
int_array = val
END SUBROUTINE
INTERFACE
SUBROUTINE set_odd(int_array, val) BIND(C)
USE, INTRINSIC :: ISO_C_BINDING, ONLY : C_INTINTEGER(C_INT) :: int_array(:)
INTEGER(C_INT), VALUE :: val
END SUBROUTINE
END INTERFACE
#include "ISO_Fortran_binding.h"
void set_odd(CFI_cdesc_t *int_array, int val)
608 ⃝c ISO/IEC 2017 – All rights reserved
ISO/IEC DIS 1539-1:2017 (E){
CFI_index_t lower_bound[1], upper_bound[1], stride[1];}CFI_CDESC_T(1) array;
int status;
/* Create a new descriptor which will contain the section. */
status = CFI_establish((CFI_cdesc_t *)&array,
NULL,
CFI_attribute_other,
int_array->type,
int_array->elem_len,
/* rank */ 1,
/* extents is ignored */NULL);
lower_bound[0] = int_array->dim[0].lower_bound;
upper_bound[0] = lower_bound[0] + (int_array->dim[0].extent - 1);
stride[0] = 2;
status = CFI_section((CFI_cdesc_t *)&array,
int_array,
lower_bound,
upper_bound,
stride);
set_all( (CFI_cdesc_t *) &array, val);
/* Here one could make use of int_array and access all its data. */
2 The set_odd procedure can be called from Fortran as follows:
INTEGER(C_INT) :: d(5)3 This program will print something like:d = (/ 1, 2, 3, 4, 5 /)
CALL set_odd(d, -1)
PRINT *, d
-1 2 -1 4 -14 During execution of the subroutine SET_ALL, its dummy argument INT_ARRAY would have size (and upper
bound) 3.5 It is also possible to invoke set_odd() from C. However, it would be the C programmer’s responsibility to make
sure that all members of the C descriptor have the correct value on entry to the function. Inserting additional6 Following is an example C function that dynamically generates a C descriptor for an assumed-shape array andchecking into the function could alleviate this problem.
calls set_odd.1 The C function change_target modifies a pointer to an integer variable to become associated with a global⃝c ISO/IEC 2017 – All rights reserved 609
ISO/IEC DIS 1539-1:2017 (E)
#include <stdio.h>
#include <stdlib.h>
#include "ISO_Fortran_binding.h"
#define ARRAY_SIZE 5
void example_of_calling_set_odd(void)
{
CFI_CDESC_T(1) d;
CFI_index_t extent[1];
CFI_index_t subscripts[1];
void *base;
int i, status;
base = malloc(ARRAY_SIZE*sizeof(int));
extent[0] = ARRAY_SIZE;
status = CFI_establish((CFI_cdesc_t *)&d,
base,
CFI_attribute_other,
CFI_type_int,
/* element length is ignored */ 0,
/* rank */ 1,
extent);
set_odd((CFI_cdesc_t *)&d, -1);
for (i=0; i<ARRAY_SIZE; i++) {
subscripts[0] = i;
printf(" %d",*((int *)CFI_address((CFI_cdesc_t *)&d, subscripts)));
}
putc(10, stdout);
free(base);
}
The above C function will print similar output to that of the preceding Fortran program.
C.12.13 Use of CFI_setpointer
variable defined inside C:2 The restrictions on the use of CFI_establish prohibit direct modification of the incoming pointer entity ip by#include "ISO_Fortran_binding.h"
int y = 2;
void change_target(CFI_cdesc_t *ip) {
CFI_CDESC_T(0) yp;
int status;
610 ⃝c ISO/IEC 2017 – All rights reserved
ISO/IEC DIS 1539-1:2017 (E)
/* Make local yp point at y. */
status = CFI_establish((CFI_cdesc_t *)&yp,
&y,
CFI_attribute_pointer,
CFI_type_int,
/* elem_len is ignored */ sizeof(int),
/* rank */ 0,
/* extents are ignored */ NULL);
/* Pointer-associate ip with (the target of) yp. */
status = CFI_setpointer(ip, (CFI_cdesc_t *)&yp, NULL);
if (status != CFI_SUCCESS) {
... report run time error...
}
}
invoking that function on it.3 The following program illustrates the usage of change_target from Fortran.
PROGRAM change_target_exampleUSE, INTRINSIC :: ISO_C_BINDING
INTERFACE
SUBROUTINE change_target(ip) BIND(C)
IMPORT :: C_INTINTEGER(C_INT), POINTER :: ip
END SUBROUTINE
END INTERFACE
INTEGER(C_INT), TARGET :: it = 1
INTEGER(C_INT), POINTER :: it_ptr
it_ptr => it
WRITE (*,*) it_ptr
CALL change_target(it_ptr)
WRITE (*,*) it_ptr
4 This will print something similar to
1
2
C.12.14 Mapping of MPI interfaces to Fortran 1 The Message Passing Interface (MPI) specifies procedures for exchanging data between MPI processes. This
example shows the usage of MPI_Send and is similar to the second variant of EXAMPLE_Send in C.12.6.2. It also2 MPI_Send has the C prototype:shows the usage of assumed-length character dummy arguments and optional dummy arguments.
int MPI_Send(void *buf, int count, MPI_Datatype datatype, int dest, int tag,MPI_Comm comm);
⃝c ISO/IEC 2017 – All rights reserved 611
ISO/IEC DIS 1539-1:2017 (E) where MPI_Datatype and MPI_Comm are opaque handles. Most MPI C functions return an error code, which in
Fortran is the last dummy argument to the corresponding subroutine and can be made optional. Thus, the use
of a Fortran subroutine requires a wrapper function, declared as
void MPI_Send_f(CFI_cdesc_t *buf, int count, MPI_Datatype_f datatype, int dest,3 This wrapper function will convert MPI_Datatype_f and MPI_Comm_f to MPI_Datatype and MPI_Comm, and pro-int tag, MPI_Datatype_f comm, int *ierror);
duce a contiguous void * buffer from CFI_cdesc_t *buf (if necessary).4 Similarly, the wrapper function for MPI_Comm_set_name could have the C prototype:
void MPI_Comm_set_name_f(MPI_Comm comm, CFI_cdesc_t *comm_name, int *ierror);5 The Fortran handle types and interfaces are defined in the module MPI_F08. For example,
MODULE mpi_f08...
TYPE, BIND(C) :: mpi_comm
PRIVATE
INTEGER(C_INT) :: mpi_val
END TYPE mpi_comm
INTERFACE
SUBROUTINE MPI_SEND(buf,count,datatype,dest,tag,comm,ierror) &
BIND(C, NAME=’MPI_Send_f’)
USE, INTRINSIC :: ISO_C_BINDINGEND SUBROUTINE mpi_sendIMPORT :: MPI_Datatype, MPI_Comm
TYPE(*), DIMENSION(..), INTENT (IN) :: buf
INTEGER(C_INT), VALUE, INTENT (IN) :: count, dest, tag
TYPE(mpi_datatype), INTENT (IN) :: datatype
TYPE(mpi_comm), INTENT (IN) :: comm
INTEGER(C_INT), OPTIONAL, INTENT (OUT) :: ierror
SUBROUTINE mpi_comm_set_name(comm,comm_name,ierror) &
BIND(C, NAME=’MPI_Comm_set_name_f’)
USE, INTRINSIC :: ISO_C_BINDINGEND SUBROUTINE mpi_comm_set_nameIMPORT :: mpi_comm
TYPE(mpi_comm), INTENT (IN) :: comm
CHARACTER(KIND=C_CHAR, LEN=*), INTENT (IN) :: comm_name
INTEGER(C_INT), OPTIONAL, INTENT (OUT) :: ierror
END INTERFACE
...
END MODULE mpi_f08
612 ⃝c ISO/IEC 2017 – All rights reserved
ISO/IEC DIS 1539-1:2017 (E)6 Some examples of invocation from Fortran are:
USE, INTRINSIC :: ISO_C_BINDING7 The first example sends the entire array X and includes the optional error argument return value. The secondUSE :: MPI_f08
TYPE(mpi_comm) :: comm
REAL :: x(100)
INTEGER :: y(10,10)
REAL(KIND(1.0d0)) :: z
INTEGER :: dest, tag, ierror
...
! Assign values to x, y, z and initialize MPI variables.
...
! Set the name of the communicator.
CALL mpi_comm_set_name(comm, "Communicator Name", ierror)
! Send values in x, y, and z.
CALL mpi_send(x, 100, MPI_REAL, dest, tag, comm, ierror)
IF (ierror/=0) PRINT *, ’WARNING: X send error’, ierror
CALL mpi_send(y(3,:), 10, MPI_INTEGER, dest, tag, comm)
CALL mpi_send(z, 1, MPI_DOUBLE_PRECISION, dest, tag, comm)
example sends a noncontiguous subarray (the third row of Y) and the third example sends a scalar Z. Note the1 The first two examples are examples of valid host association. The third example is an example of invalid hostdifferences between the calls in this example and those in C.12.6.2.
C.13 Clause 19 notes : Examples of host association (<IP_ADDRESS>)
association.Example 1:
PROGRAM A
INTEGER I, J
...
CONTAINS
SUBROUTINE B
INTEGER I ! Declaration of I hides ! program A’s declaration of I...
I = J ! Use of variable J from program A ! through host association
END SUBROUTINE B
END PROGRAM A
⃝c ISO/IEC 2017 – All rights reserved 613
ISO/IEC DIS 1539-1:2017 (E)Example 2:
PROGRAM A
TYPE T
...
END TYPE T
...
CONTAINS
SUBROUTINE B
IMPLICIT TYPE (T) (C) ! Refers to type T declared below ! in subroutine B, not type T...! declared above in program A
TYPE T
...
END TYPE T
...
END SUBROUTINE B
END PROGRAM A
Example 3:
PROGRAM Q
REAL (KIND = 1) :: C
...
CONTAINS
SUBROUTINE R
REAL (KIND = KIND (C)) :: D ! Invalid declaration ! See belowREAL (KIND = 2) :: C
...
END SUBROUTINE R
END PROGRAM Q
2 In the declaration of D in subroutine R, the use of C would refer to the declaration of C in subroutine R, not
program Q. However, it is invalid because the declaration of C is required to occur before it is used in theIn the index, entries in italics denote BNF terms, and page numbers in bold face denote primary text ordeclaration of D (10.1.12).
614 ⃝
c ISO/IEC 2017 – All rights reserved
ISO/IEC DIS 1539-1:2017 (E)
Index
definitions.

Nemo Release 3.1 untitled () October 30, 2022


MicroPython documentation
Welcome! This is the documentation for MicroPython v1.16, last updated 08 Nov 2021.
MicroPython runs on a variety of systems and hardware platforms. Here you can read the general documentation which applies to all systems, as well as specific information about the various platforms - also known as ports - that MicroPython runs on.
General documentation for MicroPython:
|
Library Reference
MicroPython Differences |
Language Reference
License |
References and tutorials for specific platforms:
|
Quick reference for the pyboard
Quick reference for the ESP8266
Quick reference for the ESP32
Quick reference for the Raspberry Pi RP2xxx
Quick reference for the WiPy/CC3200
Quick reference for UNIX and Windows
Quick reference for the Zephyr port |
Indices and tables:
|
Module index
Full index |
Glossary
Table of contents |
External links:
|
MicroPython homepage
MicroPython forum |
MicroPython on GitHub |


Mum who drank 40 cuppas a day buried in giant box of Typhoo tea coffin
Tina Watson, laid to rest at Gilroes Crematorium in Leicester, had a 'wicked sense of humour' according to her family
by Milo Boyd, Adrian Troughton, https://www.mirror.co.uk/authors/milo-boyd/A woman who drank 40 cups of tea a day was buried in a giant box of her favourite brand.
Before Tina Watson died of heart failure she was very clear about how she wanted to be sent off.
For the whole of her life the Leicester woman had harboured an intense and enduring love of tea, Leicester Mercury reported.
At its peak she was knocking back 40 cups a day, which equated to a fresh brew every 24 minutes if she slept an average amount.
Tina first announced her intentions to be buried in a Typhoo box to her daughter Debs Donovan.
“It’s typical of mum,” said Debs, of Braunstone Town, Leicestershire.
“She had a wicked sense of humour and drank about 30 or 40 cups of tea a day, every day. She just loved having a cuppa.
“We got chatting about her coffin after the funeral of my stepdad Peter four years ago.
“She just blurted out: ‘I want to be buried in a coffin that looks like a giant box of tea bags.’
“I burst out laughing and said: ‘Okay, but it's got to be Typhoo because you only get an ‘oo’ with Typhoo.
"Mum cracked up at that and we just fell about laughing. She said she was deadly serious about the coffin so that was that.”
The curious final request was realised by funeral director Paul Pender.
He said: “It was one of our more unusual requests but we were happy to be able to make it happen.
“I got in touch with the guy that helps us with customised coffins and he produced the goods.
“It is always nice when the customer gets what the customer wants.”
Family and friends of the tea enthusiast said their final goodbyes at Gilroes Crematorium in Leicester on Friday.
Despite keeping her wicked sense of humour until the last, Tina did not have the easiest of lifes.
She was twice diagnosed with cancer and beat it both times, before having both of her legs amputated.
“She lost one leg after the bite got infected after being bitten by an insect in Spain 14 years ago,” said Debs.
“Mum then lost the other leg when the infection spread further.
"She never let anything get her down. She always saw the funny side of things even when there wasn’t a funny side.”


Hello
I have 2 EmonTH 1.4.
I test the reading closing in a tin box both EmonTH.
After some hours I can read different misures expecially for UR.
EmonTH A UR 38.2
EmonTH B UR 35.0
It's normal?
I also try a EmonTx 3.4 with a firmware for DHT22 reading. In the same condition of the two EmonTH i read only 29.5 UR.
Maybe bacause the +5 pin is always ON and there is the self-heating problem?
Thanks
Stefano
Re: 2 EmonTH > UR and Temp differente reading
Yesterday I made an experiment.
I closed in an ermetic box the two EmonTH with a little cup of salt and water. In these condition the the humidity in the box must follow this table:
T (C°) U (%) NaCl
10 75,6
15 75,6
20 75,4
25 75,2
30 75,0
35 74,8
40 74,6
45 74,5
50 74,4
The results are here:
http://www.stefanotruzzi.it/emoncms/stefano&id=2
The readings of both Emonth are a little under the value of the table, but with acceptable precision.
With other types of salt can be checked low humidity values, but NaCl is easy to find and the temperature of the test is not so important.


Ayahuasca (P. harmala & Mimosa hostilis)
Personal Experience:
Years of heavy psychedelic experiences coupled with about 100+ breakthrough DMT experiences, of which very few even provided a fraction of this experience. No stranger to many levels of hellish and divine, pleasurable and painful, confusing and clarifying, blissful and strange experiences. Experimented with traditional tryptamines, countless experiences with various compounds of Shulgin's Phikal and Tikal, a handful of intense combination experiences between ketamine and DMT, deep experiences with psychedelic levels of ketamine, the list could go on for pages. I am experienced in both recreational and ceremonial settings. I was quite certain I comprehended to some degree what I was getting myself into before the experience began, but was thoroughly unprepared from the relentless, endless, and mindboggling array of experiences which stunningly fit eternity into a couple of hours.
Setting:
Deep in the forest, near a clearing, next to a stream, underneath low lying trees
People Present at Ceremony:
Group/Session Leader and 10 others that I didn't know, as well as a close personal friend.
State of Mind:
Going through issues of isolation, confusion, lack of a 'path' in life post graduation, had not slept in over 24 hours and was initially tired and hesitant, though the tired state of mind quickly dissipated. I was dealing with, at the time, chronic disease which caused minor (and sometimes not too minor) constant discomfort/pain.
The Experience:
Ceremony opened up with a statement of intentions for the ceremony. I stated that I was looking for clarity and understanding of who I was and where I was going. We proceeded to ingest, I believe, enough Harmala extract to achieve full MAOI inhibition. We waited about 30 minutes to ingest the 2nd capsules containing the (organically, supposedly) extracted DMT compound from Mimosa Hostilis. The dosage of both the MAOI and Extracted DMT are unknown to me.
At this point my friend and I took our blankets to a far back area in this wooded clearing under low lying trees next to a small stream. We laid with the stream at our feet and our heads beneath the trees. My friend and I relaxed/meditated and quietly conversed in preparation for the experience.
After some time, maybe 30 minutes, maybe an hour, I began to doubt that I had ingested enough MAOI or perhaps enough DMT as I felt (mostly) clearheaded. But as quickly as doubt began to set in I began to experience a strange sensation. First a warmth surrounded my body and a deep lethargy settled, as if gravity itself increased and embraced me.
Translucent holograms of individual’s faces began to drift towards me.  Each hologram pressed through my head providing me with startling psychic sensations in which I experienced visions from the lives of the individuals. Each face bushed through me providing the sensation of me being pushed through a sort of gelatinous electric membrane.
A particularly noteworthy startling psychic occurrence happened when I saw the face of an ex-lover whom I was experiencing lots of jealously and lust towards. As her face pushed through mine I saw our past lovemaking sessions and then witnessed them morph into intense lovemaking sessions with other men, more competent and better endowed than I, my insecurities swelled up but were slowly quelled as my 'love' for her manifested itself as an acceptance and love for the way our paths drifted together then apart and an acceptance of her search for love and pleasure. I found myself at peace and content with her personal autonomy even if it pulled her away from me and my desires. (This experience has had long lasting impact on my perception of jealousy and possessiveness surrounding interactions with women, and relationships in general)
After this I began to receive strange visions of elaborate carnival festival settings. But not just visions, I was THERE. Giant carnival tents, jeweled and towering, vibrating with sound and energy appeared before me and I entered into them. In these bizarre constructs a multitude of interdimensional beings, along with humans, and aliens and all sorts of other archetypal beings were celebrating SOMETHING.
Typical 'Greys' (so called aliens, though psychic messages conveyed that these were actually the time travelling hyper evolved future of humankind) floated inches above the ground, though they only had rounded nubs for hands/feet and scrolling glowing alien text on their bodies. I encountered more entities which were time travelers, future versions of humanity, now totally alien in appearance. Energetic Beings glowed, their neural structures externally apparent and vibrantly pulsating with light. Networks of light and energy swung between and through all the entities. Elves, demons, goblins, faeries joined in the celebration.
All of the content and meaning I perceived, all of these entities and their identities were 'psychically' interpreted or intuited by me in this state of mind. As the festivities became clearer and more ecstatic I received the psychic intuition that this was the party celebrating the end of all time. These beings were singing, I was singing, we were all singing. Our voices were floating from our mouths and in doing so becoming strange pulsating physical objects rotating in front of us. Each object was a piece of visual art, as well as a musical instrument, and beings could sing together to 'play' and 'paint' these objects with one another, the experience was absolutely orgasmic as we constructed elaborate mandalas of sound, orgasming together with the joy of creation. It was sublimely orgiastic on a cosmic scale.
At some point I found myself face to face with my friend who I was laying next to and the festivities quieted down and I found myself floating in an absolute void with him. We placed our heads together and our minds began to 'meld' in a truly fantastic manner. Our minds merged into a singular form (he reported a similar experience to me after the fact). We were suspended in the void, we were two but we were one. Our bodies morphed into an abstract form much like the Yin/Yang form, singular/dual and all encompassing. Our minds, One mind, all minds, all of existence focused in on us, on me, on this single moment, that lasts forever, that is all that there ever was, is all there ever will be.
At this point I was hit with this realization, which I struggle to comprehend or place into words or fit into my perception of reality, that existence had reached the point where we had to accept the mortality of the universe, not just the individual, and as conscious entities had decided to collapse existence into some sort of singularity and immortal bliss to escape the entropy and pain innate in existence (I really struggle to express what exactly was going through my head at this point). At this point I realized that this obliteration was necessary and began to push this... metaphoric... big red button to end time and the universe as we know it to move on to another realm of existence.
I asked him, and he echoed back to me (this is a rough recollection as its hard to recall exactly what was said):
“Here we are”
“Here we are”
“Right now?”
“Right now” he responded.
“This is it, we have to do it”
He looked at me with fear and trepidation,
“Are you ready?” I asked.
He looked even more fearful.
“We have to let go, its going to be beautiful. We have to collapse, to be born again. We have to die. We are all going to die.”
“I’m not ready” He said, with fear and near anger in his voice.
But there was no turning back, I felt a terrible momentum pulling me towards the button.  THIS IS ALL THERE EVER WAS AND EVER WILL BE AND IT ENDS RIGHT NOW”
The words spilled from my mouth, and I wasn’t saying them, something ELSE something far beyond me was speaking through me, I felt possessed, I felt like a crazed mad prophet... There was a momentum to my words, they spilled from my mouth with confidence I had never exhibited and poetics I could never imagine repeating. I was being pulled through this experience, it was extremely pleasurable but I knew, somewhere deep inside that this orgasmic build-up was leading to something entirely different.
Words that slip my mind spilled from me, expressing the beauty awe and wonder of the world, as I screamed people in the group puked and shat noisily around me, moaned, and reacted to my words. (Later individuals felt as if my message, the words I began to scream were psychic intuitions of messages they needed to hear, and were intricately linked into their trip). I felt like I was a puppet for cosmic consciousness (perhaps my ego was somewhat bloated at this moment as well).
“HERE WE ARE AND HERE IT ENDS!” I screamed and at the point I mashed this cosmic red button with my mind and orgasmed into oblivion.
Suddenly everything shifted in a truly horrific direction which is far beyond words though I will attempt to express some fraction of this non-linear eternal experience I was hit with next.
I felt a distinct sensation of sucking, sinking, and swirling into the cosmic pit of the universe, being pulled towards a sort of black hole of absolute isolation. A shrill sound pierced the air, this void I was suspended in, painful... It resonated deep in my skull, it was ringing, shrieking, and screaming all at once. Then I realized that I was screaming, that all reality was screaming.
Unaware of what I was doing I stumbled to my feet and tumbled into the stream (I only found this out later) at this point I was thrashing in the water screaming and pulling at my hair flailing against the rocks.
Reality expanded from this singular void I was floating in, expanding into an infinite two dimensional grid-work of 8-bit Nintendo-eque Mayan patterns. The patterns pulsated and glowed and encompassed all of existence. And all of existence was suffering, I was eternal suffering, my role in the universe was to suffer for all of eternity. This was the cosmic 'Game Over' screen, all was lost forever.
As this 8-bit Mayan grid-work pulsated the pain escalated; I felt every atom in my body torn to shreds as the ringing tones rose and fell, my body was torn limb from limb, fingers pulled from my hand, finger tips pulled from my fingers, skin ripped from the flesh, each atom pulling apart, individuals crushed and subjugated to pure pain and anguish, I fell apart and was put back together ENDLESSLY. I felt my throat slit, my intestines torn from my body, my head bashed with rocks, and then it looped for ever, ever escalating. I realized I was doomed that I had sent myself to some eternal hellish painful tortuous existence. That I had to pay the price for every negative thought I had ever done. Unaware, I pissed myself, I shat myself, I screamed endlessly but in this state I had no conception that I was doing any of these things. I was utterly alone, insane, and in unending psychological and physical pain/madness.
This horrific state would begin to let up and 'deceive' me. I would have the sensation that I was lifting out from the state only to be hit once more with the shrill noise and feel myself sucked back in, deeper and more painfully than before. I was certain this was my place, my eternal place in the universe, that I was a cog in the machine, and my cog was labeled suffering, and I would always be suffering because that was WHO I WAS FOR ETERNITY.
At times I drifted slightly from this torture and imagined I had gone completely mad. That I was a schizophrenic madman wandering through the woods, lost alone, and broken, I could see my mind in its healthy state, so far away, but it had been stolen from me, I was doomed and lost, and realized that death would not be a door to escape through but rather a portal back into this torture which slowly sucked me back in...
This was a cosmic, never ending, meat grinder; obliterating, painful, and all encompassing. It was also fully conscious, aware of me; aware of what it (I?) was doing to me. I was sacrificial lamb to the universe, I was divinely doomed, I was fully deserving of this punishment, I was alone...
This apparently took about 2 hours (or 3) to settle down and I came too slowly, I drifted from this state and back into my physical form.
I was on my back splayed across rocks in an icy cold stream. The moon was high above. The trees breathed with me and crickets chirped around me.
I was scared, alone, cold, soaking wet... I cried, I yelped 'help'... My head ached; my body was bruised from thrashing on the rocks. I had a few (minor) cuts. I had pulled out a few small clumps of hair... I was scared...
As I panicked and splashed through the water on all fours I suddenly realized where I was; in a beautiful stream, in beautiful mountains, under a beautiful moon. I breathed deep and confidently. I could warm myself with my mind. I could connect with the world around me. I was NOT alone. I sang to the moon, I sang to the trees. I sang to the river and it sang back to me.
A crawfish crawled on my hand and I sang to it, its antennae rhythmically responded, playfully twitching in the air. The water began to engage me in a 'call and response' song I sang to it, it sang an altered version of my song back and we playfully interacted with one another. I began to laugh and the stream laughed back.
I struggled to my feet. My body was like that of a newborn infant, unfamiliar, alien, new, strange and beautiful. I wobbled to the side of the stream learning how to use my body once more filled with the wonderful sense of discovery and awe for my physical form. I stripped naked, taking my soaking clothes of my body and leaving them on rocks by the side of the stream. I crawled through the forest in the hopes of finding my friend. He was laying eyes closed where I left him. I crawled up to him, naked, and cold and he saw me and smiled. We hugged, cried, and expressed our gratitude for one another.
I wrapped a blanket around my body, put my boots on (and yes that was all I wore, a blanket and boots), and we wandered through the forest in wonder, in absolute awe.
The experience deeply imprinted me and I was left with severe 'shell shock' from the whole experience. I was once relatively fearless of the 'metaphysical' realm but this left me with deep doubts and fears of the 'true' nature of reality, a place where I could experience eternal pain and never ending torture. I was fearful that this 'hell' could rip through at any moment that I could be plunged into this state at death. I woke up from flashback-nightmares of this hell state for weeks afterward and I still can 'feel' it pushing through reality at times. I also became somewhat fearful of the internal states of mind from which such an experience could emerge. It’s been difficult but I find myself learning from this experience. I still have a deep fear of this eternal pain and suffering.
As a long time fan of altered states this experience has been followed by nearly a year of absolute sobriety, I can't even imagine revisiting this state, it so deeply moved me, altered me, filled me with apocalyptic visions and fears, pain, love, acceptance, and anguish.
Some central thoughts which bubbled up through the experience:
1. Eternity can be experienced from within, eternity can be encapsulated by consciousness.
2. Heaven, Hell, Bliss, Pain, all are internally emergent states of mind, and are not separate from one another.
3. Our past thoughts and actions, experiences as well, are a part of who we are and impact our daily existence in deep ways even if we no longer consciously remember these experiences/thoughts/actions.
4. Expansive awareness IS NOT sunshine and rainbows and bliss. Higher states of consciousness can force one to confront the immense pain and difficulty innate within existence.
5. Time is non-linear. Every moment is eternal.
6. We are a part of a masterfully created work of art, eternal, and crafted perhaps by ourselves.
7. And contradictory to previous statements. everything is temporary, must die, must end, and we must reach a state where the end of everything is something we can approach with celebration and love, where death, decay, entropy is a part of the beautiful existence we now inhabit.
8. We must answer for who we are, what we do, the impact we have, the love, the pain, the cruelty, the good deeds, every choice we make, Tinker around with the psychedelic realm long enough and this confrontation with the oftentimes painful nature of our true self is somewhat inevitable.
9. Transformation is and will be fantastic, beautiful, necessary AND HORRIFICALLY/UNIMAGINABLY DIFFICULT AND PAINFUL. This is the nature of purging, of evolution, of life.
10. WE MUST SAVE OURSELVES. No one can do it for us, these deep issues, states of mind, are personal and must be personally addressed.
I am not certain in these beliefs but these thoughts often run through my head.
This description is only a fraction of my experience, poorly placed into words where words are surely insufficient.
Experience Reports are the writings and opinions of the individual authors who submit them.
Some of the activities described are dangerous and/or illegal and none are recommended by Erowid.


Before Change
logger.info("Prediction done. Trial job id = %s. Predict value = %s", trial_job_id, predict_y)
if predict_y is None:
logger.info("wait for more information to predict precisely")
return AssessResult.Good
standard_performance = self.completed_best_performance * self.threshold
end_time = datetime.datetime.now()
if (end_time - start_time).seconds > 60:
After Change
predict_y = curvemodel.predict(scalar_trial_history)
log_message = "Prediction done. Trial job id = {}, Predict value = {}".format(trial_job_id, predict_y)
if predict_y is None:
logger.info("%s, wait for more information to predict precisely", log_message)
return AssessResult.Good
else:
logger.info(log_message)
standard_performance = self.completed_best_performance * self.threshold


No More Bland Chicken! 7 Days of Tasty Meals That Will Help You Shed Those Last Few Pounds
by Tarah ChieffiOne of the biggest hurdles for women who are trying to lose weight is finding recipes that taste good and keep you on track with your goals. That's why we've put together an entire week's worth of meals and snacks that will not only help you shed pounds, but also keep you satisfied.
That means you won't find boring salad after boring salad here. This meal plan is packed with fresh, flavorful smoothies, soups, chocolatey treats, and more. You'll find loads of vegetables, lean proteins, and whole grains — basically, all the healthy foods your body craves, seasoned and cooked to perfection.
Each day's menu includes breakfast, lunch, dinner, and one snack, totaling around 1,300 to 1,400 calories. That being said, everyone's calorie needs are different (you can calculate yours using this formula), and if you find that the amount of food isn't quite enough for you, you can always add an additional snack or an extra serving of fruits or veggies to your meals. Keep reading to get started!


Introduction
SHFMAAS (Say Hi As A Service) provides a modern, RESTful, scalable solution to the common problem of telling people "Hi". No longer will thousands of messages go undelivered!
Content Negotiation
SHFMAAS will respond to the following 'Accept:' values with appropriate content
- text/plain - Content will be returned as a plain string.
- application/json - Content will be returned as a JSON object { message: 'message', subtitle: 'subtitle' }
- text/html - Content will be returned as an HTML page with a twitter bootstrap hero unit, containing the message and the subtitle.
API
/hi/:from/:name
Will return content of the form ':from says Hi. - :from', e.g. /hi/Tom/Chris will return 'Tom says Hi - Chris'
/hello/:from/:name
Will return content of the form ':name says Hello. - :from', e.g. /hello/Tom/Chris will return 'Tom says Hello. - Chris'
/gday/:from/:name
Will return content of the form ':name says Hello. - :from', e.g. /hello/Tom/Chris will return 'Tom says G'day. - Chris'
Site by Callum Barker.
Forked from FOAAS


When the link from ping attribute is followed, post requests with the body ping will be sent by the browser (in the background). Typically used for tracking.


We are deidicated to give you the best output by going an extra mile.
Every author requires a second eye to spot human errors. We include proof reading with every artcile we write.
Our writers are bachelors, masters or PhD holders of Quantity Surveying. So our content is rich with experience and knowledge.
We have the highest quality:price ratio!
Disclaimer: All the services on this website is provided in good faith and for research and reference purposes only. We do not encourage submitting these papers as it is for academic credit.
Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts.
Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts.
Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts.
All the services on this website is provided in good faith and for research and reference purposes only. We do not encourage submitting these papers as it is for academic credit.


| 034:032 Khan | : |
And those who were arrogant will say to those who were deemed weak: "Did we keep you back from guidance after it had come to you? Nay, but you were Mujrimun (polytheists, sinners, criminals, disobedient to Allah, etc.). |
| 034:032 Maulana | : |
Those who were proud say to those who were deemed weak: Did we turn you away from the guidance after it had come to you? Nay, you (yourselves) were guilty. |
| 034:032 Pickthal | : |
Those who were proud say unto those who were despised: Did we drive you away from the guidance after it had come unto you? Nay, but ye were guilty. |
| 034:032 Rashad | : |
The leaders will say to those who followed them, "Are we the ones who diverted you from the guidance after it came to you? No; it is you who were wicked." |
| 034:032 Sarwar | : |
The suppressing ones will say to the oppressed ones, "Did we prevent you from having guidance after it had come to you? In fact, you yourselves were criminals." |
| 034:032 Shakir | : |
Those who were proud shall say to those who were deemed weak: Did we turn you away from the guidance after it had come to you? Nay, you (yourselves) were guilty |
| 034:032 Sherali | : |
Those who were big with pride will say to those who were considered weak, 'Was it we that kept you away from the guidance, after it had come to you? Nay, it was you yourselves who were guilty.' |
| 034:032 Yusufali | : |
The arrogant ones will say to those who had been despised: "Was it we who kept you back from Guidance after it reached you? Nay, rather, it was ye who transgressed. |
Concepts/Themes Covered: أركان الإسلام > التوحيد > الكافرون > تخلي المتبوعين عن الأتباع Pillars of Islam> Islamic> The Disbelievers> The Masters' Abandonment of the Followers الإيمان > الغيب > النار > أصحاب النار Faith> The Unseen World> Hell-Fire>Hell Fellows الإيمان > اليوم الآخر > الجزاء بالعمل Faith> The Hereafter> The Award against Action الإنسان والعلاقات الاجتماعية > المجتمعات > التفاضل بينها Man and The Social Relations>The Societies>Preference Among them
This tool uses eight English parallel translations for the Holy Quran imported from Mr. Clay Smith. You can also visit Qurany Concepts for browsing the Quran themes or topics. If you want to search the Holy Quran for keywords, please visit Qurany Keywords.


C
Main Menu
login nonprod
login prod
us-east-1
eu-west-1
ap-southeast-1
NON-Prod
PRODUCTION
EC2 Info
Alarms
details


LinkedIn
Home
What is LinkedIn?
Join Today
Sign in
Email
Password
Over 175 million professionals use LinkedIn to exchange information, ideas and opportunities
Stay informed about your contacts and industry
Find the people & knowledge you need to achieve your goals
Control you professional identity online
Join LinkedIn Today
Sign up
First name:
Last name:
Email:
Password:
6 or more characters
Already on LinkedIn?
Sign in.
Search for someone by name:
First Name
Last Name