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

SIZEOF() on derived type

ereisch
New Contributor II
5,486 Views

Does anyone know of a way to get a compile-time sizeof() on a generic type?  Let's say I'm declaring a module that handles all operations on a derived type:

MODULE MY_MOD
  USE, INTRINSIC :: ISO_C_BINDING
  USE, INTRINSIC :: IEEE_ARITHMETIC
  TYPE, BIND(C) :: MY_MOD_TYPE
    INTEGER(KIND=C_INT32_T) :: A
    INTEGER(KIND=C_INT32_T) :: B
    INTEGER(KIND=C_INT32_T) :: C
    REAL(KIND=C_FLOAT)      :: D
  END TYPE
  INTERFACE MY_MOD_TYPE
     MODULE PROCEDURE INIT_MY_MOD_TYPE
  END INTERFACE
CONTAINS
  PURE TYPE(MY_MOD_TYPE) FUNCTION INIT_MY_MOD_TYPE() RESULT(RET)
    RET%A = -1
    RET%B = -1
    RET%C = -1
    RET%D = IEEE_VALUE( 1.0, IEEE_QUIET_NAN )
  END FUNCTION

  PURE INTEGER(KIND=C_SIZE_T) FUNCTION MY_MOD_TYPE_SIZE ()
    TYPE(MY_MOD_TYPE) :: A
    MY_MOD_TYPE_SIZE = SIZEOF(A)
  END FUNCTION
END MODULE

So, in the above, I have an initializer function for the type, and something that will return the size of the type.  However, if I'm trying to write memory-optimized code, the my_mod_type_size() function is very wasteful -- I'm declaring an entire type (which could be dozens or even hundreds of megabytes in size) to just be able to do a sizeof() on the type, and then throw away the memory after the function exits.  It appears as though it's illegal to do a sizeof(type(my_mod_type)) -- is there any way to get this (preferably at compile-time, as can be done in C) without having to declare the variable and allocate the memory for it?

0 Kudos
37 Replies
andrew_4619
Honored Contributor II
3,622 Views

First sizeof is not standard Fortran but for bind(c) types you can use c_sizeof which is. bind(c) derived types are of fixed size, so you could set as a parameter constant, not elegant buy hey ho.

0 Kudos
Steve_Lionel
Honored Contributor III
3,612 Views
c_sizeof(MY_MOD_TYPE(0,0,0,0.0))
0 Kudos
andrew_4619
Honored Contributor II
3,602 Views

Yes I tried that as a parameter decl but it objects to it not being a constant expression which I think is wrong. I also thought c_sizeof(MY_MOD_TYPE()) might work but it gives uninitialised variable errors for the components.

0 Kudos
Steve_Lionel
Honored Contributor III
3,588 Views

Right - C_SIZEOF isn't allowed in a constant expression. This, though nonstandard, works:

integer, parameter :: s = sizeof(my_mod_type(0,0,0,0.0))

 

Edit: see below.

0 Kudos
andrew_4619
Honored Contributor II
3,580 Views

Hmmm ok in my understanding C_SIZEOF  can only be used on a derived type that has bind(c) which precludes allocable and pointer components etc so you would think C_SIZEOF of is in-fact  a constant expression that can be determined as compile time for but non-bind(c) DT this may not be true. The example above with the defualt constructor is however a constant....

To cut to the chase I am thus not sure why C_SIZEOF isn't allowed in a constant expression is that a specific constraint?

 

0 Kudos
FortranFan
Honored Contributor II
3,568 Views

@ereisch ,

Re: "is there any way to get this (preferably at compile-time, as can be done in C) without having to declare the variable and allocate the memory for it?,"

  • consider default initialization of components of the interoperable derived types, this is important
  • consider a named constant "mold" of such types - basically a compile-time thingy with throw away value,
  • and use the mold for the size generation.
   use, intrinsic :: iso_c_binding, only : c_int32_t, c_float, c_sizeof, c_size_t
   type, bind(C) :: t
      integer(kind=c_int32_t) :: a = 0_c_int32_t
      integer(kind=c_int32_t) :: b = 0_c_int32_t
      integer(kind=c_int32_t) :: c = 0_c_int32_t
      real(kind=c_float)      :: d = 0.0_c_float
   end type
   type(t), parameter :: mold_t = t()
   integer(c_size_t), parameter :: t_sz = c_sizeof( mold_t )
   print *, "t_sz = ", t_sz
end

 

C:\temp>ifort /standard-semantics p.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.8.0 Build 20221119_000000
Copyright (C) 1985-2022 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 14.34.31937.0
Copyright (C) Microsoft Corporation.  All rights reserved.

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

C:\temp>p.exe
 t_sz =  16

C:\temp>gfortran p.f90 -o p.exe

C:\temp>p.exe
 t_sz =                    16

C:\temp>
0 Kudos
ereisch
New Contributor II
3,295 Views

How does default initialization of structure members work with C-interoperability?  When it's defined as a module prototype, a function is exposed (my_mod_mp_init_my_mod_type(), though note the actual name of the function varies across compilers.....for example, gfortran generates __my_mod_MOD_init_my_mod_type()) that can be called from any language to populate the structure with its default values.

When I use default initialization, no function seems to be exposed that would set the members to their default values.  Though I suppose I could memcpy() the "mold", that's a somewhat more clunky and less-portable method.

0 Kudos
andrew_4619
Honored Contributor II
3,275 Views

The default *constructor* function of the type is just the name of the type, that must be exposed as you can call it....

0 Kudos
ereisch
New Contributor II
3,294 Views

P.S. -- Default initializers don't seem to work with the IEEE_VALUE function, which is strange, because that function returns a constant value that can be determined at compile-time.  It also appears as though this function is called at runtime rather than the compiler replacing it with the equivalent constant value.  Is this expected behavior?  Is there a standard-compliant IEEE parameter value predefined with the NAN bitstream?  Looking at ieee_arithmetic.f90 in the Intel compiler's folder, I see some functions that define the bitstreams of NANs as parameters, but they're all local to the functions in question.

If I fall back to a BOZ constant and use the hex value of NAN, that works.  But it wouldn't be entirely clear what I would be doing to the casual observer, whereas IEEE_VALUE( 1.0, IEEE_QUIET_NAN ) is pretty explicit.

0 Kudos
Steve_Lionel
Honored Contributor III
3,565 Views

Constant expressions have restrictions on which functions may appear. Most intrinsic functions are OK if all their arguments are constant expressions, but only selected functions from intrinsic modules are allowed. 

However...

C_SIZEOF is one that is explicitly allowed - I forgot that. There is a known bug in ifort that it does not allow a "specification inquiry" in a constant expression, and this is where C_SIZEOF and some other intrinsic module functions such as COMPILER_VERSION are permitted.

0 Kudos
JohnNichols
Valued Contributor III
3,551 Views

If I read the Fortran 77 manual, I get one definition of constant expressions and if I read modern IFORT I get a second, when did they change?

0 Kudos
Steve_Lionel
Honored Contributor III
3,546 Views

The rules for constant (or intilalization in earlier revisions) expressions change in every revision of the standard. Fortran 2023 makes them even more liberal.

0 Kudos
JohnNichols
Valued Contributor III
3,513 Views

constant expression is made up of explicit constants and parameters and the FORTRAN operators. Each operand is either itself another constant expression, a constant, a symbolic name of a constant, or one of the intrinsic functions called with constant arguments.

 

from 

https://docs.oracle.com/cd/E19957-01/805-4939/6j4m0vn76/index.html#:~:text=A%20constant%20expression%20is%20made,functions%20called%20with%20constant%20arguments.

2010 at Oracle 

 

 But from Intel, manual,  there is no reference to Fortran operators, is this just implied.  

 

 

A constant expression is an expression that you can use as a kind type parameter, a named constant, or to specify an initial value for an entity. It is evaluated when a program is compiled.
In a constant expression, each operation is intrinsic and each primary is one of the following:

 

  • A constant or subobject of a constant
  • A specification inquiry where each designator or function argument is one of the following:
     
  • A constant expression
  •  
  • A variable whose properties inquired about are not assumed, deferred, or defined by an expression that is not a constant expression
  •  
  • A reference to the transformational function IEEE_SELECTED_REAL_KIND from the intrinsic module IEEE_ARITHMETIC, where each argument is a constant expression
  • A kind type parameter of the derived type being defined
  • A DO variable within an array constructor where each scalar integer expression of the corresponding DO loop is an constant expression
  • Another constant expression enclosed in parentheses, where each subscript, section subscript, substring starting and ending point, and type parameter value is a constant expression

    If a constant expression invokes an inquiry function for a type parameter or an array bound of an object, the type parameter or array bound must be specified in a prior specification statement (or to the left of the inquiry function in the same statement). The previous specification cannot be in the same entity declaration.
    If a reference to a generic entity is included in a constant expression that is in the specification part of a module or submodule, that generic entity shall have no specific procedures defined subsequent to the constant expression in the module or submodule.
    0 Kudos
    Steve_Lionel
    Honored Contributor III
    3,501 Views

    Operators are implied by "expression". The Intel documentation is mainly quoting the standard but has left out parts. (Why are you referencing some document from Oracle? The Intel page for this is here.)

    0 Kudos
    JohnNichols
    Valued Contributor III
    3,496 Views

    When the post listed constant expressions, I wondered what they meant, never heard the term, I found the Oracle site and it explained it.  I then went a found the Intel site and compared them, but I wondered if it was implied as the difference, so I asked.  

    It would help if the Intel did list operators for someone like me, who only rarely reads the manual or worries about such fine detail.  

    I listed the stuff from the two sites, because I knew you would knew. 

    0 Kudos
    JohnNichols
    Valued Contributor III
    3,490 Views

    In the Powerstation Fortran Manual there is no Constant Expressions in the index in any form, are they after Powerstation?  Or just left out?

    0 Kudos
    andrew_4619
    Honored Contributor II
    3,478 Views

    https://wg5-fortran.org/ARCHIVE/Fortran77.html read away plenty of stuff on constant expressions to be had.

    0 Kudos
    JohnNichols
    Valued Contributor III
    3,450 Views
    6.7  Constant_Expressions
    
              A  constant  expression  is  an   arithmetic   constant
              expression  (6.1.3),  a  character  constant expression
              (6.2.3), or a logical constant expression (6.4.4).
    

    This definition from the Fortran 77 manual essentially matches the Intel one, as far as I can see, but they are not the same as the Oracle\, which is or one of the intrinsic functions called with constant arguments could be argued is in the standard but could be missed.

    Interesting you can see where confusion comes in when writer knows what is meant and so do the committee, but some poor person misses the implied.  

     

    0 Kudos
    JohnNichols
    Valued Contributor III
    3,446 Views
    !****************************************************************************
    !
    !  PROGRAM: Console2
    !
    !  PURPOSE:  Entry point for the console application.
    !
    !****************************************************************************
    
        program Console2
    
        implicit none
        
        real, parameter :: pi = 3.142
        
        real, parameter :: zero = cos(pi)
    
        ! Variables
    
        ! Body of Console2
        print *, 'Constant Expression :: ', zero
    
        end program Console2
    
    

    It is the use of cos that I find interesting, I understand, but it is not 100% clear if it is Intel legal, it works. 

     

    0 Kudos
    FortranFan
    Honored Contributor II
    3,433 Views

    Is "zero = cos(pi)" the new math they talk about .. my kid's school introduced yet another version of "new math" this year, it's not 100% clear  ..


    @JohnNichols wrote:
    ..
        real, parameter :: zero = cos(pi)
    ..
    

    It is the use of cos that I find interesting, I understand, but it is not 100% clear ..


     

    0 Kudos
    Reply