How can I get a unique value from a fortran pointer - fortran

I have a fortran pointer, referring to some allocated memory. I want to "hash" it so that I get a unique number referring to that memory. In C, I would convert the pointer location to an integer.

In Fortran 95 I don't believe this is possible in a strictly standard conforming way. You would need to use vendor extensions - the necessary capability is often available via an intrinsic called LOC or similar.
In Fortran 2003, depending on the nature of the object being pointed to by the Fortran pointer, you could convert the C address of the object (its memory location) to an integer.
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_LOC, C_INTPTR_T
TYPE(thing), POINTER :: object
INTEGER(C_INTPTR_T) :: an_integer
!****
ALLOCATE(object)
an_integer = TRANSFER(C_LOC(object), an_integer)

Related

What shall be used in Modern Fortran to specify a 8 bytes real variable if iso_fortran_env is not supported?

I want to specify as type of a subroutine a floating point value (real) of 8 bytes precision.
I have read here that the modern way to do it would be:
real(real64), intent(out) :: price_open(length)
However, iso_fortran_env is not supported by f2py (same as it does not support iso_c_bindings either).
I get errors of this type:
94 | real(kind=real64) price_open(length)
| 1
Error: Parameter 'real64' at (1) has not been declared or is a variable, which does not reduce to a constant expression
The link referenced before states that using kind would be the proper way if iso_fortran_env is not available and that real*8 shall be avoided.
I have been using real(8) is that equivalent to using kinds? If not, what shall I use?
What is wrong with real*8 if I want to always enforce 8 bytes floating point values?
You say you are specifically interested in interoperability with C. However, iso_c_binding, nor iso_fortran_env are supported. These modules have constants that help you to set the right kind constant for a given purpose. The one from iso_fortran_env would NOT be the right one to choose anyway, it would be c_double.
If these constants meant to help you in your choice are not available, you are on your own. Now you can choose any other method freely.
It is completely legitimate to use just kind(1.d0) and just check that the connection to C works. Automake had been doing that for ages.
Or use selected_real_kind(), it does not matter, it is really up to you. Just check that double in C ended up being the same numeric type.
The traditional thing in automatic build processes was to do many tests about which (mainly C) constant ended up having which value. You just need to check that double precision in Fortran does indeed correspond to double in C. It is very likely, but just check it. You can have a macro that changes the choice if not, but probably it is a needless work untill you actually meet such a system.

What is the need for a C_INT fortran type? Are C and Fortran integers so different?

If I declare an integer in fortran as:
INTEGER(C_INT) :: i then, if I understand correctly, it's safe to be passed to a C function. Now disregarding the added headache of always declaring integers this way, is there any reasons not to always declare your variables as C-interoperable? Is there any downside to doing so?
Also, in the case of something as simple a an integer, what exactly does the C_INT change from a traditional Fortran integer? Are Fortran and C integers actually different?
The C integer size is usually fixed because the OS is compiled using C and the system bindings are published as C headers. The operating system designers choose one of the common models like LLP64, LP64, ILP64 (for 64-bit pointer OS's) and the C compilers then follow this choice.
But Fortran compilers are more free. You can set them to a different configuration. Fortran compiler set to use 8-byte default integers and 8-byte default reals are still perfectly standard conforming! (C would be as well but the choice is fixed in the operating system.)
And because the integers in C and in Fortran do not have to match you need a mechanism to portably select the C interoperable kind, whatever the default kind is.
This is not just academic. you can find libraries like MKL compiled with 8-byte integers (the ILP64 model, which is not used by common operating systems for C).
So when you call some API, some function whose interface is defined in C, you want to call it properly, not depending on the settings of the Fortran compiler. That is the use case for the C-interoperable types. If a C function requires an int, you give it an integer(c_int) and you do not care if the Fortran default integer is the same or not.
Basically there is no fundamental downside and on the same compiler there is no fundamental benefit.
Even in icc a long int is different on 32 and 64 bit OS, so you need to know (or define what you want on the c-side of things).
The only one that is clearly 4-bytes is the C_INT32_T, and hence it is that one that I generally use. And it more of a "future proofing" endeavour to use C_INT32_T , to define it as you want it to be in a fixed numbers of bits sizing.
These all give a 4 byte integer on iFort.
USE ISO_C_BINDING, ONLY : C_INT, C_INT32_T
Integer ::
INTEGER(KIND=4) :: !"B" At least on iFort
INTEGER*4 !"A"
INTEGER(KIND=C_INT) ::
INTEGER(KIND=C_INT32_T) :: !"C"
Usually one finds older code with the style of "A".
I routinely use the style of "B", but even though this is a "defacto standard" it is not conforming to "the standard".
Then when I become concerned with portability I run-through and change the "B" style to "C" style and then I have less heartburn considering others who may be later compiling with the gfortran compiler... Or even some other compiler.
The single byte:
BYTE :: !Good
INTEGER(KIND=1) ::
INTEGER(KIND=C_SIGNED_CHAR) ::
INTEGER(KIND=C_INT8_T) :: !Best
The two byte:
INTEGER(KIND=2) ::
INTEGER(KIND=C_INT16_T) :: !Best
INTEGER(KIND=C_SHORT) ::
The 8 byte:
INTEGER(KIND=8) ::
INTEGER(KIND=C_INT64_T) :: !Best
INTEGER(KIND=C_LONG_LONG) ::
While this looks somewhat fishy... One can also say:
LOGICAL(KIND=4) ::
LOGICAL(KIND=C_INT32_T) :: !Best here may be C_bool and using 1-byte logical in fortran...? Assuming that there is no benefit with the size of the logical being the same as some float vector
LOGICAL(KIND=C_FLOAT) ::

Reinterpret a Fortran array as bytes

I would like to interpret a Fortran (real*8, say) array as an array of bytes, so that it can be sent to a function to process things on the byte level. What's a simple (preferably no-copy) way to accomplish this?
First, it is not clear what is a function working on byte level. Does it use Fortran characters? Or 1-byte integers? They are different beasts in Fortran.
You could try to lie about the signature of your function and just pass the array as it is. Likely to work, not strictly standard conforming.
Transfer() is the best modern tool for similar purposes, but it may indeed involve temporaries.
If the size of the array is fixed (it is not allocatable or pointer or dummy argument) you could use equivalence which is quite similar to union in C.
But you must be careful about what is allowed, this is a notoriously dodgy area. Even the C union rules differ from the C++ rules. Fortran equivalence has its own rules and more strict, I am afraid. Type punning is not allowed, but a lot of code in the wild does it.
Doing tricks with C pointers and pointing to the same array from different pointers with different types is definitely not standard conforming and may give you expected results in some cases and wrong results in others (undefined behaviour as they call it in C and C++).
A "NO_COPY" way...but relies on DEC extensions:
USE ISO_C_BINDING
IMPLICIT NONE
UNION
MAP
REAL(KIND=C_DOUBLE) , DIMENSION(N) :: R8_Data
END MAP
MAP
BTYE , DIMENSION(N*8) :: B_Data
END MAP
MAP
CHARACTER(LEN=1) , DIMENSION(N*8) :: C_Data
END MAP
MAP
INTEGER(KIND=C_Int16_T), DIMENSION(N*4) :: I2_Data
END MAP
MAP
INTEGER(KIND=C_Int32_T), DIMENSION(N*2) :: I4_Data
END MAP
END UNION
#Valdimir equivalence also works if one does not have access to the DEC extensions.
There is a slated upgrade to gfortran to add in the MAP and UNION DEC extensions, so in time it will be there too.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56226
My appreciation of the difference is back on track...
One can use UNION/MAP inside of a structure. Outside a structure/TYPE then EQUIVALENCE does all one needs.
So As Vladimir mentioned this also is a "no copy"...
REAL(KIND=C_DOUBLE) , DIMENSION(N) :: R8_Data
BTYE , DIMENSION(N*8) :: B_Data
CHARACTER(LEN=1) , DIMENSION(N*8) :: C_Data
INTEGER(KIND=C_Int16_T), DIMENSION(N*4) :: I2_Data
INTEGER(KIND=C_Int32_T), DIMENSION(N*2) :: I4_Data
EQUIVALENCE(R8_Data, I4_Data)
It is almost more dangerous than it is worth, unless one has a specific problem.

fortran fgldrawpixels character*8 pointer to data

I am trying to visualize a 2D real array in fortran95 using opengl with intel parallel studio in msvs. For this I have found (trying to understand) fglDrawPixels on http://polarhome.com/service/man/?qf=fgldrawpixels&tf=2&of=IRIX&sf=3
In the explanation of the subroutine
SUBROUTINE fglDrawPixels( INTEGER*4 width,
INTEGER*4 height,
INTEGER*4 format,
INTEGER*4 type,
CHARACTER*8 pixels )
it says that pixels
Specifies a pointer to the pixel data.
I don't fully understand this, since the data I whant to show is real(4) (or GL_FLOAT) How do I declare a pointer that I can use??? (character*8 to a pointer to real(4) data) - I thought this would be declared as real(4), pointer, dimension(:,:) :: pixels but that does not seem to be what fglDrawPixels expects...
Any help or hint on this is much appreciated
That description of the routine's interface is incorrect. The pixels argument is of type integer(K_GLvoid), or in other words, an address-sized integer. It is NOT a Fortran pointer. Typically you would use LOC(buffer) here where buffer is whatever variable you're using to hold the pixel data. All these arguments are passed by value, and the calling convention is STDCALL.
If you are using Intel Visual Fortran, module IFOPNGL declares this with the correct interface.

Pointers in Fortran

Im unsure how the below 2 in C can be represented in Fortran.
*VariableOne (Could be used possibly by using 'inout intent' in functions?
&VariableOne (No clue about how I could do this though)
Could someone tell me how I might be able to replicate this in Fortran? I looked up Pointers in Fortran but couldnt clearly understand what relates to the above two. I was hoping someone here would show me an equivalent to help me understand.
You seem to be confusing two different concepts. Values in Fortran act as though they're passed by reference so you can modify a variable within a function and have its change reflected outside. The intent statements are there to specify what you're going to do with that dummy variable. intent(in) doesn't allow you to change that variable, intent(out) you use it to pass data out of a function and its value is undefined on entry, and intent(inout) means that it can both provide data to the function (not undefined on entry) and write to it as well.
But there are also explicit pointers you can use to dynamically allocate memory and act similarly to pointers in C.
Pointers in Fortran can't point to just anything. What they point to must have the target attribute or be a pointer. You also don't need to explicitly dereference a pointer to access its value. Here's a short example of what you can do with pointers and how they work:
real, pointer :: ptr(:) => null() !Can point to an array of reals or be allocated
real, target, allocatable :: trgt(:) !Array of reals
real, allocatable :: array(:)
real, pointer :: scalar => null() !Initially points to null to signify that it's not associated
!I can check if the pointer currently points to anything by using the associated function
!Be careful: the initial associaton status is undefined so you must set it to null or nullify it first
if (associated(ptr)) then
nullify(ptr) !Redundant in this example, same as setting it equal to null()
end if
allocate(ptr(3)) !I can allocate a pointer directly with memory for 3 elements
allocate(trgt(5)) !Allocate the target with 5 elements
allocate(array(6)) !Allocate array
!Assign values to my freshly allocated variables
ptr = 1.0
trgt = 3.0
array = 5.0
deallocate(ptr) !Avoid memory leaks by deallocating memory before pointing to something else
ptr => trgt !Pointer now points to the data stored in trgt. No need to use anything like '&' to reference trgt
ptr => array !Error because array does not have target attribute
scalar => ptr(1) !Both are pointers so no error, now points to a value of 3.0
print *, scalar + 5.0 !I can use this value directly without dereferencing it and prints 8.0