- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
c_sizeof(MY_MOD_TYPE(0,0,0,0.0))
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@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>
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The default *constructor* function of the type is just the name of the type, that must be exposed as you can call it....
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The rules for constant (or intilalization in earlier revisions) expressions change in every revision of the standard. Fortran 2023 makes them even more liberal.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
A 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 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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In the Powerstation Fortran Manual there is no Constant Expressions in the index in any form, are they after Powerstation? Or just left out?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
https://wg5-fortran.org/ARCHIVE/Fortran77.html read away plenty of stuff on constant expressions to be had.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
!****************************************************************************
!
! 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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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 ..
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page