- 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
- « Previous
-
- 1
- 2
- Next »
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
totally legal! I always use:
real(dp), parameter :: pi = acos(-1.0_dp)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Constant expressions were called initialization expressions in earlier standard revisions.
Operators are described in the various sections under Expressions, broken out by numeric/logical/character/relational/defined.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
6. EXPRESSIONS This section describes the formation, interpretation, and evaluation rules for arithmetic, character, relational, and logical expressions. An expression is formed from operands, operators, and parentheses.
An expression is a combination of one or more operands, zero or more operators, and zero or more pairs of parentheses.
There are three kinds of expressions:
An arithmetic expression evaluates to a single arithmetic value.
A character expression evaluates to a single value of type character.
A logical or relational expression evaluates to a single logical value.
The operators indicate what action or operation to perform.
The operands indicate what items to apply the action to. An operand can be any of the following kinds of data items:
Constant
Variable
Array element
Function
Substring
Structured record field (if it evaluates to a scalar data item)
An expression
ok, I see the logical progression, I have never seen a elemental function in a parameter, that I remember. Using the cos of pi to define -1 introduces an error at about 1 part in a billion for my pi estimate which is the number I used for years in manual design.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The term "constant expression" becomes particularly relevant in the context of a `PARAMETER` statement (or an attribute).
ANSI X3.9-1978 document (a proxy for FORTRAN 77 standard) first added `PARAMETER` statement and that document then made use of the term constant expressions ..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I understand using the acos for pi, it is a good idea. I like the method @mecej4 showed me when we rewrote Magni from C# to Fortran. The base module
Module Base
INTEGER, PARAMETER :: dp = selected_real_kind(15, 307)
INTEGER, PARAMETER :: sw = 2 ! Output file
INTEGER, PARAMETER :: srA = 15 ! output.txt file
INTEGER, PARAMETER :: srB = 16 ! output.txt file
INTEGER, PARAMETER :: st = 14
INTEGER, PARAMETER :: sCAD = 12
INTEGER, PARAMETER :: sa = 3 ! Output file
INTEGER, PARAMETER :: smWrite = 4
INTEGER, PARAMETER :: si = 1
Integer, parameter :: slog = 9 ! Log file
Integer, parameter :: nta = 200 ! Log file
Integer, parameter :: outNode = 63 ! Log file
Integer, parameter :: inNode = 0 ! Log file
integer, parameter :: nt1 = 2000
integer, parameter :: mt1 = 2000 ! Number of members
integer, parameter :: mn1 = 2
integer, parameter :: ml1 = 3
integer, parameter :: ml30 = 3000
integer, parameter :: limit = 3
REAL (KIND=dp), PARAMETER :: gr = 9.806_DP, pi = 3.14159265_DP ! Standard parameters
REAL (KIND=dp), PARAMETER :: delta = 0.001_DP ! Error number of checking for zero
REAL (KIND=dp), PARAMETER :: ZERO = 0.0_DP
REAL (KIND=dp), PARAMETER :: ONE = 1.0_DP
REAL (KIND=dp), PARAMETER :: TWO = 2.0_DP
REAL (KIND=dp), PARAMETER :: THREE = 3.0_DP
REAL (KIND=dp), PARAMETER :: THIRTY = 30.0_DP
REAL (KIND=dp), PARAMETER :: FOUR = 4.0_DP
REAL (KIND=dp), PARAMETER :: SIX = 6.0_DP
REAL (KIND=dp), PARAMETER :: PointFIVE = 0.5_DP
REAL (KIND=dp), PARAMETER :: PointTWOFIVE = 0.25_DP
REAL (KIND=dp), PARAMETER :: OneHundred = 1.0_DP
REAL (KIND=dp), PARAMETER :: DeltaFr = 15000000.0_DP
REAL (KIND=dp), PARAMETER :: FTR = 1.0_DP
REAL (KIND=dp), PARAMETER :: FTRA = 100.0_DP
REAL (KIND=dp), PARAMETER :: SMALL_MASS = 0.0001_DP
INTEGER, PARAMETER :: mn_3 = 3,mn_9 = 9, mn_2 = 2, mn_10 = 10, mn_18 = 18, mn_6 = 6, mn_12 = 12, mn_4 = 4
contains
-- it makes life very easy. My problem is I like the 1988 Microsoft Fortran manuals and I keep them beside my desk, so they are my main Fortran read, they have great examples.
So constant expressions use the side effect from a function to set a constant. So in lisp (setq pi (acos 0))
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
REAL (KIND=dp), PARAMETER :: OneHundred = 1.0_DP ????
Some thing just jump out of the page
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Complete change of topic, why cannot Intel not use 2022.2 and then 2023.1 or 2023.0 this odd numbering is to say the least annoying, it is the same as zero indexing and what day does a contract start 0 or 1, makes a difference to the contract and is the bain of contractors. The two standard textbooks on contract scheduling one starts 0 and one starts 1 and the two people are friends.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
As Andrew says, in Fortran a structure constructor is just the type name. You can create a generic interface of the same name to serve as a constructor, and if so, you can export a specific procedure (which can also have the same name). Is gfortran really creating these on its own? That's weird.
If you're talking about default initialization of derived type components, there's nothing preventing a type with initialization being interoperable.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
My point was that if I do this, as was suggested at one point:
MODULE MY_MOD
USE, INTRINSIC :: ISO_C_BINDING
PUBLIC :: MY_MOD_TYPE
TYPE, BIND(C) :: MY_MOD_TYPE
INTEGER(KIND=C_INT32_T) :: A = -1
INTEGER(KIND=C_INT32_T) :: B = -2
INTEGER(KIND=C_INT32_T) :: C = -3
REAL(KIND=C_FLOAT) :: D = TRANSFER(Z'7FC00000', 1.0_4)
END TYPE
END MODULE
...the compiler does not export any functions that contain code. I only get the following (comments and useless assembler removed for readability):
.text
.align 32,0x90
.globl my_mod$
my_mod$:
.cfi_startproc
..___tag_value_my_mod$.1:
ret
.align 32,0x90
.cfi_endproc
.type my_mod$,@function
.size my_mod$,.-my_mod$
.data
.section .note.GNU-stack, ""
...so, you get one function defined (my_mod), but it has an empty text section. I can create an interface called my_mod_type, and attach a procedure to it, but then that is separating the default initializers from the definitions.
Now, the interesting part -- if I create a new subroutine and USE the module I previously defined:
SUBROUTINE TEST2 (A)
USE MY_MOD
TYPE(MY_MOD_TYPE) :: A
A = MY_MOD_TYPE()
END SUBROUTINE
...the generated code becomes:
.align 32,0x90
.globl test2
test2:
.cfi_startproc
movl $-1, (%rdi)
movl $-2, 4(%rdi)
movl $-3, 8(%rdi)
movl $2143289344, 12(%rdi)
ret
.align 32,0x90
.cfi_endproc
.type test2,@function
.size test2,.-test2
.data
.section .rodata, "a"
.align 4
.align 4
.long 0x7fc00000
.type .L_2il0floatpacket.0,@object
Thus, the compiler is using data apparently contained in the generated *.mod file to create inlined code that populates the default values of everything in the structure, instead of calling a constructor function. Thus, unless I'm doing something wrong, I can't call this constructor function from C. However, my OO Fortran is very poor (I'm an F77 and C programmer, and somewhat conversant in C++....OO Fortran is very alien to me), so it's possible I'm missing a special language trick to get this constructor exported.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
IEEE_VALUE is an elemental function. As it is neither an inquiry function nor transformational, it is not allowed in constant expressions.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes - if you have a procedure dummy argument of a derived type with initialization, the compiler gets the info from the module and does the initialization. There is no routine for this purpose, though you can write your own. Fortran doesn't give you constructors just for declaring a type.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@ereisch ,
Please try to NOT mix concerns. You can use the following code design principle with your threads as well:
https://en.wikipedia.org/wiki/Separation_of_concerns
Your original post was about ..
..
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?
toward which you were shown how to achieve your "sizeof" on the type at compile-time.
Then without any acknowledgement of that response, you bring up a separate concern about some "class" instantiation function unrelated to your original post.
Please strive to close out one discussion with some form of acknowledgement of the replies and then open another thread if you have other questions.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well, yes, that evolved. Someone (@FortranFan) had said it was "important" to use default initialization of components; my comment was that this was not interoperable with C. And that answer didn't address my question anyhow, since I noted that I was looking for a solution "without having to declare the variable and allocate the memory for it". The proposed solution of using a "mold" to declare a parameter ignored that part, since the mold still allocates the memory for the variable (albeit in the data section of the executable and not on the stack). However, that doesn't matter since, as I noted, the memory structure in question could be hundreds of megabytes in size, so it's still consuming memory on the target computer that it'll never use. Thus, using a "mold" would be a.) not interoperable, and b.) doesn't save the memory from being allocated for the dummy variable, just to determine the structure size.
If you don't want me pointing out an issue with your response that has nothing to do with my original question, don't post a response that has nothing to do with my original question.
That having been said, I did neglect to transcribe over the BIND(C) attributes on the INIT_MY_MOD_TYPE() function, which may have made my requirement for interoperability not as clear. My apologies for that omission.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@ereisch ,
Ok I'll make sure to never again reply to any of your posts following this one. Just note what you wrote makes no sense whatsoever technically, starting with "Someone (@FortranFan) had said it was "important" to use default initialization of components; my comment was that this was not interoperable with C." There is no connection between default initialization and interoperability with C. Also, it is unclear what "proposed solution" is being mentioned. What I had indicated is a named constant and it is a compile-time determination leading to a value - there is no run-time variable declaration and static or dynamic memory allocation coming into play. The rest of the blurb is less comprehensible.
@ereisch wrote:
Well, yes, that evolved. Someone (@FortranFan) had said it was "important" to use default initialization of components; my comment was that this was not interoperable with C. And that answer didn't address my question anyhow, since I noted that I was looking for a solution "without having to declare the variable and allocate the memory for it". The proposed solution of using a "mold" to declare a parameter ignored that part, since the mold still allocates the memory for the variable (albeit in the data section of the executable and not on the stack). ..
This is for any other readers: if the intelligible concern is to be able utilize the size of an interoperable derived type in Fortran in C code, you may consider along the following lines with an "extern" object in C which is bound to a `MODULE` entity in Fortran via bind(C):
module m
use, intrinsic :: iso_c_binding, only : c_int, c_float, c_size_t, c_sizeof
type, bind(C) :: t
integer(c_int) :: a = 0
integer(c_int) :: b = 0
integer(c_int) :: c = 0
integer(c_float) :: d = 0.0
end type
integer(c_size_t), parameter :: sz_t = c_sizeof( t() )
integer(c_size_t), bind(C, name="t_sz") :: t_sz = sz_t
end module
#include <stdio.h>
extern size_t t_sz;
int main() {
printf("sizeof(t): %d\n", (int)t_sz);
}
C:\temp>ifort /c /standard-semantics m.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.
C:\temp>cl /c /EHsc /W3 c.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.34.31937 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
c.c
C:\temp>link c.obj m.obj /subsystem:console /out:c.exe
Microsoft (R) Incremental Linker Version 14.34.31937.0
Copyright (C) Microsoft Corporation. All rights reserved.
C:\temp>c.exe
sizeof(t): 16
C:\temp>
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
UPDATE - This seems to work, and does not allocate runtime or executable memory for the structure:
MODULE MY_MOD
USE, INTRINSIC :: ISO_C_BINDING
USE, INTRINSIC :: IEEE_ARITHMETIC
REAL(KIND=C_FLOAT), PARAMETER :: SGL_NAN = TRANSFER(Z'7FC00000', 1.0_4)
TYPE, BIND(C) :: MY_MOD_TYPE
INTEGER(KIND=C_INT32_T) :: A = -1
INTEGER(KIND=C_INT32_T) :: B = -1
INTEGER(KIND=C_INT32_T) :: C = -1
REAL(KIND=C_FLOAT) :: D = SGL_NAN
END TYPE
INTEGER(KIND=C_SIZE_T), PARAMETER :: MY_MOD_TYPE_SZ = C_SIZEOF( MY_MOD_TYPE() )
CONTAINS
PURE INTEGER(KIND=C_SIZE_T) FUNCTION MY_MOD_TYPE_SIZE () BIND(C)
IMPLICIT NONE
MY_MOD_TYPE_SIZE = MY_MOD_TYPE_SZ
END FUNCTION
END MODULE MY_MOD
Thanks all for the guidance.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
PURE INTEGER(KIND=C_SIZE_T) FUNCTION MY_MOD_TYPE_SIZE ()
MY_MOD_TYPE_SIZE = 16
END FUNCTION
yes but but but I would have to work it out and what if I change the DT.....
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page
- « Previous
-
- 1
- 2
- Next »