Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Questions about fortran constructions

Averkov__Igor
Beginner
325 Views

Hello!

Please answer some questions about fortran construction

1. I have a function:

function GetArgumentName() result(Res)
    character(250) Res 
    ...
end function

How can i use substring of first character without declaring additional variables like this:

GetArgumentName()(1:1)

Compiler don't let me so

2. I have a function:

function GetArray()  result(Res)
  integer(1:100) Res

end function

Why compiler do not let me use the following expression:

n = 5 + GetArray()(1)

where i want to add to 5 the first element of the array?

3. I have a type and a function:

type T_Point
 real X, Y
end type

function GetPoint() result(Res)
  type(T_Point) Res

end function

Why compiler do not let me use the following expression:

r = 5.0 + GetPoint() % X

Is it really necessary to declare auxiliary variables every time to execute these expressions?

 

0 Kudos
6 Replies
Steve_Lionel
Honored Contributor III
325 Views

It's the Fortran language that does not allow you to do those things, not the compiler. A function reference isn't a data object that can be itself qualified with subobjects.

0 Kudos
Averkov__Igor
Beginner
325 Views

Thank you very much Steve

0 Kudos
FortranFan
Honored Contributor II
325 Views

Averkov, Igor wrote:

..

Please answer some questions about fortran construction ..

How can i use substring of first character without declaring additional variables like this:

GetArgumentName()(1:1)

.

 .. use the following expression:

n = 5 + GetArray()(1)

r = 5.0 + GetPoint() % X.

Is it really necessary to declare auxiliary variables every time to execute these expressions?

As stated upthread, the Fortran standard does not allow your to use function references the way you want.

However look into ASSOCIATE construct: https://software.intel.com/en-us/fortran-compiler-developer-guide-and-reference-associate

ASSOCIATE can prove very valuable in situations where you need to associate objects and their subobjects or function results, see below.  While you're at it. you may want to look at BLOCK construct in Fortran also: https://software.intel.com/en-us/fortran-compiler-developer-guide-and-reference-block

   type :: T_Point
      real :: x = 0.0
      real :: y = 0.0
   end type

   blk2: block
      integer :: n
      asc2: associate ( Array => GetArray() )
         n = 5 + Array(1)
         print *, "Associate 2: n = ", n, "; expected is 47"
      end associate asc2
   end block blk2

   blk3: block
      real :: n
      asc3: associate ( Pt => GetPoint() )
         n = 5.0 + Pt%X
         print *, "Associate 3: n = ", n, "; expected is 6.0"
      end associate asc3
   end block blk3

   asc1: associate ( ArgName => GetArgumentName() )
      print *, "Associate 1: ArgName(1:1) = ", ArgName(1:1)
   end associate asc1

contains

   function GetArgumentName() result(ret)
      ! Function result
      character(len=250) :: ret
      ret = "Hello World!"
   end function

   function GetArray() result(Res)
      ! Function result
      integer :: Res(1:100)
      Res = 42
   end function

   function GetPoint() result(Res)
      ! Function result
      type(T_Point) :: Res
      Res%X = 1.0 ; Res%Y = 2.0
   end function

end

Upon execution, the first two work ok.  Intel Fortran compiler gives a compile time warning and then crashes at run-time with the CHARACTER object result from a function, both a bug me thinks:

 

C:\Temp>ifort /standard-semantics /warn:all /check:all /stand:f18 /warn:stderrors /traceback p.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64,
Version 19.1.0.056 Pre-Release Beta Build 20190321
Copyright (C) 1985-2019 Intel Corporation.  All rights reserved.

ifort: NOTE: The Beta evaluation period for this product ends on 9-oct-2019 UTC.
p.f90(23): warning #5481: Variable ARGNAME has substring ending point 1 which is
greater than the variable length of 0
      print *, "Associate 1: ArgName(1:1) = ", ArgName(1:1)
-----------------------------------------------^
Microsoft (R) Incremental Linker Version 14.16.27027.1
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:p.exe
-subsystem:console
-incremental:no
p.obj

C:\Temp>p.exe
 Associate 2: n =  47 ; expected is 47
 Associate 3: n =  6.000000 ; expected is 6.0
forrtl: severe (408): fort: (12): Variable ARGNAME has substring ending point 1 which is
greater than the variable length of 0

Image              PC                Routine            Line        Source
p.exe              00007FF606D0C611  Unknown               Unknown  Unknown
p.exe              00007FF606D014C3  MAIN__                     23  p.f90
p.exe              00007FF606D50DE2  Unknown               Unknown  Unknown
p.exe              00007FF606D517B4  Unknown               Unknown  Unknown
KERNEL32.DLL       00007FFD429B37E4  Unknown               Unknown  Unknown
ntdll.dll          00007FFD42DECB81  Unknown               Unknown  Unknown

C:\Temp>

 

0 Kudos
DataScientist
Valued Contributor I
325 Views

@FortranFan Thanks for your comment. That feature is very elegant. However, here is another question: when one associates a function with a name, and the name is used in the association block, is the function going to be called every time, or is it called only once upon entry to the associate construct?

0 Kudos
FortranFan
Honored Contributor II
325 Views

A. King wrote:

@FortranFan Thanks for your comment. That feature is very elegant. However, here is another question: when one associates a function with a name, and the name is used in the association block, is the function going to be called every time, or is it called only once upon entry to the associate construct?

In principle, the evaluation of the expression based on the function reference should only take place once during the association of the entity (e.g., Pt above) with the selector.  Note where the selector (e.g., GetPoint() above) is not a variable, as in say a function reference, or is otherwise not allowed to be in a variable definition context, the associating entity and any of its subobjects, if applicable, cannot be present in a variable definition context either, like on the left-hand side of an assignment.  Such requirements on the coder allow a compiler not to invoke a function any further during the execution of the block i.e., the instructions between "associate(..)" and "end associate".

Hope this helps,

0 Kudos
jimdempseyatthecove
Honored Contributor III
325 Views

>>In principle, the evaluation of the expression based on the function reference should only take place once during the association of the entity (e.g., Pt above) with the selector.

You also have available the now depreciated statement function.

Or you can write a Get function:

type T_Point
 real X, Y
end type

function GetPoint() result(Res)
  type(T_Point) Res

end function

function GetX(p) result(Res)
  type(T_Point) :: p
  real :: Res
  Res = p%x
end function GetX

...

something = GetX(GetPoint())

Jim Dempsey

0 Kudos
Reply