Prev: calling a recursive function in fortran 77 ?
Next: equivalent in fortran of the IDL "where" function
From: James Van Buskirk on 25 Mar 2010 14:35 "Richard Maine" <nospam(a)see.signature> wrote in message news:1jfwiq3.1154fi71vt5b5sN%nospam(a)see.signature... > There is currently no portable standard-conforming way. C:\gfortran\clf\sizetest>type sizetest1.f90 program sizetest1 use ISO_C_BINDING implicit none type contains_pointer integer data type(contains_pointer), pointer :: next end type contains_pointer integer, parameter :: ik1 = selected_int_kind(2) type(contains_pointer) sp type(contains_pointer), target :: ap(2) ! f90 way: write(*,'(a,i0)') 'In f90: ', size(transfer(sp,(/1_ik1/))) ! f03 way: write(*,'(a,i0)') 'In f03: ', & transfer(C_LOC(ap(2)),1_C_INTPTR_T)- & transfer(C_LOC(ap(1)),1_C_INTPTR_T) ! f08 way: write(*,'(a,i0)') 'In f08: ', C_SIZEOF(sp) end program sizetest1 C:\gfortran\clf\sizetest>gfortran -Wall sizetest1.f90 -osizetest1 C:\gfortran\clf\sizetest>sizetest1 In f90: 16 In f03: 16 In f08: 16 -- write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, & 6.0134700243160014d-154/),(/'x'/)); end
From: glen herrmannsfeldt on 25 Mar 2010 15:46 James Van Buskirk <not_valid(a)comcast.net> wrote: (snip) > ! f03 way: > write(*,'(a,i0)') 'In f03: ', & > transfer(C_LOC(ap(2)),1_C_INTPTR_T)- & > transfer(C_LOC(ap(1)),1_C_INTPTR_T) Last time this came up, I just put in 4. It would have been nice to have C_PTRDIFF. C_PTRDIFF(C_LOC(ap(2)),C_LOC(ap(1))) -- glen
From: Richard Maine on 25 Mar 2010 16:31 James Van Buskirk <not_valid(a)comcast.net> wrote: > "Richard Maine" <nospam(a)see.signature> wrote in message > news:1jfwiq3.1154fi71vt5b5sN%nospam(a)see.signature... > > > There is currently no portable standard-conforming way. > ! f90 way: > write(*,'(a,i0)') 'In f90: ', size(transfer(sp,(/1_ik1/))) I didn't think of that one. Figures that you would. :-) I agree it is standard conforming. I have used size(transfer(...)) in the past for related purposes, so I suppose I ought to have thought of it. It was a long time ago that I was doing that. I stopped it because, in addition to being horribly messy (not just that line, but all the other parts involved), it tended to crash compilers of the day. I think they have since gotten better. > ! f03 way: > write(*,'(a,i0)') 'In f03: ', & > transfer(C_LOC(ap(2)),1_C_INTPTR_T)- & > transfer(C_LOC(ap(1)),1_C_INTPTR_T) That's not standard conforming. It is highly likely to work, but is not standard conforming. It assumes things about the internal representation of C_PTR. They are things quite likely to be so, but they aren't specified in the standard. This is a plausible alternative to the option I mentioned of using a C function to do the subtraction (which is also probably not strictly standard conforming, but is also likely to work). > ! f08 way: > write(*,'(a,i0)') 'In f08: ', C_SIZEOF(sp) Why C_SIZEOF instead of just STORAGE_SIZE, which I mentioned? C_SIZEOF is mostly just a transformation of a special case. It is a transformation that is often enough used to justify a special function (at least that's my understanding of the argument for what otherwise looks like redundant functionality). Note that your version with C_SIZEOF is not actually conformant with the f2008 draft because it does not meet the special-case requirements of C_SIZEOF. In particular, sp is not interoperable. -- Richard Maine | Good judgment comes from experience; email: last name at domain . net | experience comes from bad judgment. domain: summertriangle | -- Mark Twain
From: glen herrmannsfeldt on 25 Mar 2010 19:12 Richard Maine <nospam(a)see.signature> wrote: > James Van Buskirk <not_valid(a)comcast.net> wrote: >> "Richard Maine" <nospam(a)see.signature> wrote in message >> news:1jfwiq3.1154fi71vt5b5sN%nospam(a)see.signature... >> > There is currently no portable standard-conforming way. >> ! f90 way: >> write(*,'(a,i0)') 'In f90: ', size(transfer(sp,(/1_ik1/))) > I didn't think of that one. Figures that you would. :-) I agree it is > standard conforming. I have used size(transfer(...)) in the past for > related purposes, so I suppose I ought to have thought of it. It was a > long time ago that I was doing that. I stopped it because, in addition > to being horribly messy (not just that line, but all the other parts > involved), it tended to crash compilers of the day. I think they have > since gotten better. "Standard conforming" is a complicated question in these cases. In this case, it depends on the existence of the appropriate kind. The unit for sizeof in C is the size of a char, but the main requirement on that is that it be at least 8 bits. >> ! f03 way: >> write(*,'(a,i0)') 'In f03: ', & >> transfer(C_LOC(ap(2)),1_C_INTPTR_T)- & >> transfer(C_LOC(ap(1)),1_C_INTPTR_T) > That's not standard conforming. It is highly likely to work, but is not > standard conforming. It assumes things about the internal representation > of C_PTR. They are things quite likely to be so, but they aren't > specified in the standard. This is a plausible alternative to the option > I mentioned of using a C function to do the subtraction (which is also > probably not strictly standard conforming, but is also likely to work). C only allows subtraction of pointers to different parts of the same object, such as different elements of an array. That removes some of the cases where this can fail. C also allows different representation for pointers to different types. If I understand it right, Fortran doesn't allow for that one. For example, character pointers on word addressed machines might use other bits to indicate the position in a word. I believe that C also doesn't guarantee that there is such an integer type, but only says what happens if there is such a type. It could be especially interesting in the case of 32 bit far model IA32 code, where pointers are 48 bits. (16 bit segment selector, 32 bit offset.) >> ! f08 way: >> write(*,'(a,i0)') 'In f08: ', C_SIZEOF(sp) > Why C_SIZEOF instead of just STORAGE_SIZE, which I mentioned? C_SIZEOF > is mostly just a transformation of a special case. It is a > transformation that is often enough used to justify a special function > (at least that's my understanding of the argument for what otherwise > looks like redundant functionality). Again, there could be some interesting cases on word addressed machines. C has the preprocessor macro CHAR_BIT indicating the number of bits in a (char), and so the unit for sizeof. > Note that your version with C_SIZEOF is not actually conformant with the > f2008 draft because it does not meet the special-case requirements of > C_SIZEOF. In particular, sp is not interoperable. If there is no corresponding C type, then asking for the C sizeof something doesn't make so much sense. There are some C cases that I wonder about. In C, character constants, such as 'x', have type int, and so sizeof('x')==sizeof(int). (As I understand it, that isn't true in C++.) Enumeration constants also have sizeof(int), though the appropriate variable can have a different size. C doesn't allow pointers to constants, which avoids some problems that would otherwise appear in those two cases. -- glen
From: Phred Phungus on 25 Mar 2010 21:37
James Van Buskirk wrote: > "Richard Maine" <nospam(a)see.signature> wrote in message > news:1jfwiq3.1154fi71vt5b5sN%nospam(a)see.signature... > >> There is currently no portable standard-conforming way. > > C:\gfortran\clf\sizetest>type sizetest1.f90 > program sizetest1 > use ISO_C_BINDING > implicit none > type contains_pointer > integer data > type(contains_pointer), pointer :: next > end type contains_pointer > integer, parameter :: ik1 = selected_int_kind(2) > type(contains_pointer) sp > type(contains_pointer), target :: ap(2) > > ! f90 way: > write(*,'(a,i0)') 'In f90: ', size(transfer(sp,(/1_ik1/))) > ! f03 way: > write(*,'(a,i0)') 'In f03: ', & > transfer(C_LOC(ap(2)),1_C_INTPTR_T)- & > transfer(C_LOC(ap(1)),1_C_INTPTR_T) > ! f08 way: > write(*,'(a,i0)') 'In f08: ', C_SIZEOF(sp) > end program sizetest1 > > C:\gfortran\clf\sizetest>gfortran -Wall sizetest1.f90 -osizetest1 > > C:\gfortran\clf\sizetest>sizetest1 > In f90: 16 > In f03: 16 > In f08: 16 > $ gfortran -D_GNU_SOURCE -Wall -Wextra jb1.f90 -o out jb1.f90:19.32: write(*,'(a,i0)') 'In f08: ', C_SIZEOF(sp) 1 Error: Function 'c_sizeof' at (1) has no IMPLICIT type $ cat jb1.f90 program sizetest1 use ISO_C_BINDING implicit none type contains_pointer integer data type(contains_pointer), pointer :: next end type contains_pointer integer, parameter :: ik1 = selected_int_kind(2) type(contains_pointer) sp type(contains_pointer), target :: ap(2) ! f90 way: write(*,'(a,i0)') 'In f90: ', size(transfer(sp,(/1_ik1/))) ! f03 way: write(*,'(a,i0)') 'In f03: ', & transfer(C_LOC(ap(2)),1_C_INTPTR_T)- & transfer(C_LOC(ap(1)),1_C_INTPTR_T) ! f08 way: write(*,'(a,i0)') 'In f08: ', C_SIZEOF(sp) end program sizetest1 ! gfortran -D_GNU_SOURCE -Wall -Wextra jb1.f90 -o out $ I don't see an obvious culprit for the error. -- fred |