forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Size and 64 bits
Goto page 1, 2  Next
 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support
View previous topic :: View next topic  
Author Message
davidb



Joined: 17 Jul 2009
Posts: 526
Location: UK

PostPosted: Wed Jun 22, 2016 1:29 pm    Post subject: Size and 64 bits Reply with quote

The release notes say that a 64 bit integer is returned when the SIZE intrinsic is used with the 64 bit compiler. This non-conformance seems to be a design decision. However, it means the following legitimate code fails to compile.

Code:

module foo
contains
function find_max(a, n)
integer :: n
real :: a(n)
real :: find_max
find_max = maxval(a)
end function find_max
end module foo

program main
use foo
real a(5)
a = (/1.0,2.0,4.0,3.0,0.0/)
print *, find_max(a, size(a))
end


In Fortran 95, the Size intrinsic has an array argument and an optional DIM argument.

Code:

RESULT = SIZE(ARRAY[, DIM])


Fortran 2003 added an optional kind argument so that a result with a particular kind could be returned when necessary:

Code:

RESULT = SIZE(ARRAY[, DIM [, KIND]])


It would be wise to implement your size the same way and then it will be standard conforming. I know there is a /SIZE32 command line option to always make SIZE return a 32 bit value, but this isn't as useful as the solution that is in the standard.
_________________
Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 5042
Location: Salford, UK

PostPosted: Wed Jun 22, 2016 1:45 pm    Post subject: Reply with quote

Thank you for the feedback. I have made a note of this.
Back to top
View user's profile Send private message
John-Silver



Joined: 30 Jul 2013
Posts: 631

PostPosted: Sun Jun 26, 2016 1:11 pm    Post subject: Reply with quote

there's an interesting question here - fortran 90/95 has now been around for 25-30 years ! that's longer than between F77 and F95. So, when is F2003 going to 'hi the streets' as it were and in particular what is the foreseen future, if any, in the medium term for FTN95 to metamorphose into a 2003 standard version ? ... or is F2003 effectively dead in the water as far as it's usefulness to real scientific users are concerned at least ?
Back to top
View user's profile Send private message
davidb



Joined: 17 Jul 2009
Posts: 526
Location: UK

PostPosted: Sun Jun 26, 2016 4:18 pm    Post subject: Reply with quote

FTN95 has added some of the intrinsics from Fortran 2003 in the latest release. But it isn't claiming to be a Fortran 2003 compiler. It does, however, claim to be a Fortran 95 compiler, and so must strive to fix any non-conformances.

It needs to ensure that SIZE returns a default integer. If it is wanted to return sizes larger than HUGE(1) then changing the intrinsic to behave like the Fortran 2003 function would be a sensible move.
_________________
Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 1834
Location: Sydney

PostPosted: Tue Jun 28, 2016 1:44 pm    Post subject: Reply with quote

Davidb,

I support the present approach Silverfrost adopted for FTN95 /64 for SIZE being integer*8.
It is true you can construct cases where SIZE does not work as defined in the standard, but there are a number of areas where non-standard approaches are required with /64 to improve usability.

The requirement for default integer was not proposed when 64-bit usage was the norm. As LOC is I*8 for /64, SIZE should also be this way. I wonder how often those who object to SIZE not returning default integer do use SIZE with /64.

For F2003, I have to use : "size(profile,kind=kind(ipos))". You certainly can't use "size(profile,kind=8)". Prior to using a 64 bit environment, I never used kind= with SIZE, so to find it did not default to the expected size of the array.

FTN95 also uses INTEGER*7 for handles, which is an interesting twist. Useful as it highlights handles that differ between 32 and 64 bit usage.

With 32 bit use, LOC annoyingly returns a -ve value for memory above 2gb which has long been a hastle. There has to be a balance between usability and code conformance and I am pleased that usability won in this case. I am sure there are many who would disagree, but I am a FTN95 Fortran user.

John
Back to top
View user's profile Send private message
davidb



Joined: 17 Jul 2009
Posts: 526
Location: UK

PostPosted: Wed Jun 29, 2016 6:47 pm    Post subject: Reply with quote

When you click on the page to buy FTN95 you are told that the compiler is a full ANSI Fortran 95 compiler. But this incompatibility means it isn't for 64 bit so either they will need to remove this claim for this compiler or continue trading on the premise they will just refund when people complain. It would be rather silly to do this when fixing SIZE is so easy.

They could fix this without invoking the use of the KIND parameter (as in F2003). Array dimensions need to be limited by (-maxint to maxint) where maxint is MAXINT(0) the largest default integer.

The current default integer is 32 bits (maxint = 2**31-1) but this can be changed using the option /DEFINT_KIND if one needs larger array dimensions.

I don't quite follow your arguments about usability. Nor do I see why SIZE has to be aligned with LOC. I would be interested to see some short examples where it is deemed necessary for SIZE to return a 64 bit value when the default integer is 32 bit.
_________________
Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 1834
Location: Sydney

PostPosted: Wed Jun 29, 2016 11:08 pm    Post subject: Reply with quote

David,

"Array dimensions need to be limited by (-maxint to maxint) where maxint is MAXINT(0) the largest default integer. "

What are you saying ?

The whole point of /64, ie 64 bit addressing is that arrays will be larger than 2^31. I have a number of examples where this is the case. I have re-written my equation solver for larger arrays, now using it with a 23 gb skyline matrix by using an integer*8 index. It actually works very well.

The point I was trying to make about LOC as default integer is that even in 32 bit, it did not work for /3GB.

If I code "SIZE (profile)" I expect to get an answer that is useable. It is a generic intrinsic. I actually need a useable answer and to have an I*8 returned in /64 is a necessary outcome. If at this stage of development FTN95 /64 returned a default integer value, it would be useless.

I wonder how much consideration was given to the useability of SIZE with 64 bit in 1994 when it was defined as default integer ?

There are a number of non-standard features in FTN95, including business formatting, the use of commas in data and transparent I/O. I don't think many would ask for a refund because of the way FTN95 provides stream I/O.

John
Back to top
View user's profile Send private message
davidb



Joined: 17 Jul 2009
Posts: 526
Location: UK

PostPosted: Thu Jun 30, 2016 6:49 am    Post subject: Re: Reply with quote

JohnCampbell wrote:


"Array dimensions need to be limited by (-maxint to maxint) where maxint is MAXINT(0) the largest default integer. "

What are you saying ?


The default integer model (32 bit signed integers) has maxint equal to 2**31-1 = 2147483647. In an array or array section expression, the subscripts must be between -2147483647 and 2147483647 (inclusive), so the largest array you can declare is:

Code:

BIG_ARRAY(-2147483647:2147483647)


If you don't like non-positive indices and want the first index to be 1, the largest array is

Code:

BIG_ARRAY(2147483647)


JohnCampbell wrote:

The whole point of /64, ie 64 bit addressing is that arrays will be larger than 2^31. I have a number of examples where this is the case.


With FTN95 it isn't possible to create an array in with any one dimension bigger than 2^31-1 unless you use non-default integers for the dimensions. To do this using /64 the default integer model would have to change to allow larger integers (e.g. to 64 bit integers, maxint = 2**63-1). However, currently the compiler doesn't do this.

I would like to see an example, just a code snippet were such arrays get created.

JohnCampbell wrote:

The point I was trying to make about LOC as default integer is that even in 32 bit, it did not work for /3GB.


Yes, I understand that. LOC is about the concept of address, so it is helpful for it to be coded as a 64 bit integer on 64 bit machines. LOC is an extension and I have no problem with how it works.

JohnCampbell wrote:

If I code "SIZE (profile)" I expect to get an answer that is useable. It is a generic intrinsic. I actually need a useable answer and to have an I*8 returned in /64 is a necessary outcome. If at this stage of development FTN95 /64 returned a default integer value, it would be useless.


But SIZE isn't supposed to be generic. The kind of the integer returned by SIZE has nothing to do with the kind of the data in the array.

SIZE is an "array inquiry function". It needs to return values which are compatible with the other "array inquiry functions" UBOUND and LBOUND. However, these don't return a 64 bit value when /64 is used (I assume this is an oversight). It is necessary to maintain the identity SIZE=UBOUND - LBOUND + 1 and to allow UBOUND < LBOUND and SIZE=0.

If the compiler ensured that use of /64 also implied /DEF_INT=4 then SIZE would return a 64 bit value, which would be ANSI compliant and do what you want.

However, I suspect you would not want to change the default integers everywhere, and a much cleaner solution would be to use the Fortran 2003 mechanism of having KIND as an argument.

Here is a simple example of how this works (note the array is just 1 bigger than allowed using default integers, so integers with a larger range need to be used in the declaration of the array). Of course you should use parameters for the kind values, which I haven't done here.
Code:

program main
   real a(2147483648_4)
   print *, 'Size = ', size(a, kind=4)
end


JohnCampbell wrote:

There are a number of non-standard features in FTN95, including business formatting, the use of commas in data and transparent I/O. I don't think many would ask for a refund because of the way FTN95 provides stream I/O


The point I was making is that Silverfrost won't want to make claims that are not true. If they decide not to fix-up this issue in /64 bit mode, I would expect them to say something like "ANSI compatible 32 bit compiler, but not in 64 bit" somewhere on the web site.

Let's not forget that the 64 bit compiler is very new. Silverfrost deserve much credit for this development, which in time will prove very useful. There are a numbe
_________________
Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl


Last edited by davidb on Thu Jun 30, 2016 7:14 am; edited 2 times in total
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 1834
Location: Sydney

PostPosted: Thu Jun 30, 2016 7:10 am    Post subject: Reply with quote

Davidb,

64 bit compilers have been around for a while and I have been using a number of them.

The code that works for me is:
Code:
     integer*8 ipos                                  ! profile storage
     real*8,    allocatable, dimension(:) :: Profile
!
      if ( allocated (profile) ) deallocate ( profile )
!
      allocate ( profile(ipos), stat=status )
!
  11  format (a,i0,a,i0,a,i0)
       write (*,11) '  [Profile] allocated; status = ',status,': size = ',size(profile),': loc = ',loc(profile)
!gf    write (*,11) '  [Profile] allocated; status = ',status,': size = ',size(profile,kind=kind(ipos)),': loc = ',loc(profile)
       if (status /= 0) stop


I should also point out that with FTN95, the array PROFILE can also be placed in COMMON if the dimension ipos is known. This makes increasing the size of existing code fairly easy, although all subscripts of PROFILE must be INTEGER*8.

As I indicated, I have been using this approach for a while, as I have 32 gb memory available to run these problems. Without SIZE returning I*8, the useability would not be good enough. !gf indicates what is required for F03, although the I*4 result was not expected.

64 bit use makes the claim of default integer unusable, while FTN95 kind values are a bit of a problem also.

The real problem is that the Fortran standards were written when 64-bit was not in common use and I am finding supporters of the standard stubborn in their acceptance that some intrinsics need to support 64 bit addressing and array sizes. It might be good for them, but I want to use 64-bit and not be told I have to conform to 32-bit. Time is moving on.

John
Back to top
View user's profile Send private message
davidb



Joined: 17 Jul 2009
Posts: 526
Location: UK

PostPosted: Thu Jun 30, 2016 7:24 am    Post subject: Reply with quote

But in your code you are using integer*8 (kind=4) values to declare the dimensions in the allocate statement. This is valid, but you would need to re-state this when you invoke SIZE.

Your example shows how to change this at the !gf line (which I assume you turn on for gfortran). I am suggesting that you should be able to use the same syntax for FTN95 too.

The current approach for SIZE in FTN95 doesn't work for many other examples. I will try and post some later.
_________________
Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 1834
Location: Sydney

PostPosted: Thu Jun 30, 2016 9:48 am    Post subject: Reply with quote

David,

I know the examples; basically anywhere where size(array) is used as an argument to a routine. I don't use that in any in real programs !

My main point is that these are just one of many areas where /64 has to change to work. You have already mentioned subscripts must be I*8. Any use of memory addresses also has to change, such as LOC and more importantly API handles, which is what is required for clearwin+. This is a much more significant change than SIZE; a potential for conversion errors and you do have to convert programs for /64.

As KIND values are different in FTN95, I try to avoid any use of KIND. Specifying I*8 constants is also cumbersome, as the simple 100_4 is non-portable and easy to misread. You would probably want 100_int64, but requires more discipline.

The alternatives for FTN95 were to change SIZE to I*8, like handles, or introduce more of the F03 syntax, such as what you are describing. My preference would have been to include some of the F08 level of ISO_FORTRAN_ENV module. I also consider F03's SIZE to be awkward and actually prefer FTN95's approach.

However, what we have at the moment is a workable system for /64. My expectation is that if people don't like or understand it then they are probably not fully using /64.

John

PS: I shall post one of my large array test programs to demonstrate use of large arrays. The warning with these is make sure you have the installed memory to run them, or you get a surprise.
Back to top
View user's profile Send private message
davidb



Joined: 17 Jul 2009
Posts: 526
Location: UK

PostPosted: Thu Jun 30, 2016 1:04 pm    Post subject: Reply with quote

I really do understand the issues. I also understand the need to keep things as simple as possible.

For Fortran 95 the developers have only two choices:

(1). The current approach where SIZE returns a 64 bit integer. You then have to add /SIZE32 to the command line to get ANSI compliance (where size returns default integer kind).

(2). Have ANSI compliance as the default (size returns a default integer kind). Then you would have to add /SIZE64 to the command line to get SIZE to return a 64 bit integer.

Both of these do what you want. But (1) is ANSI compliant by default, whereas (2) requires an optional command line parameter. It is generally better to make the compiler compliant by default and then add extensions by the use of command line switches. They have done this the other way around for some reason.

For Fortran 2003 extensions the developers could adopt (2) but also add the optional KIND argument to give additional flexibility.
_________________
Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 5042
Location: Salford, UK

PostPosted: Thu Jun 30, 2016 3:20 pm    Post subject: Reply with quote

Thanks again for the feedback. The command line option /ISO is required to ensure strict Fortran 95 compliance. So I guess that we need to review how this interacts with /64 and /SIZE32 (in addition to extending the SIZE intrinsic).

What happens with other compilers when KIND is not used and the result overflows the 32 bit signed integer limit?
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 1834
Location: Sydney

PostPosted: Thu Jun 30, 2016 11:41 pm    Post subject: Reply with quote

Quote:
What happens with other compilers when KIND is not used and the result overflows the 32 bit signed integer limit?


You get integer overflow and so the wrong result. That is what standard conforming would provide !! Please don't go back to this.

The best solution would be to have the non-standard SIZEOF (x) implemented, as ifort has done. It returns the size in bytes as I*4 for /32 and I*8 for /64. The other interesting aspect of SIZEOF is that x "Can be a scalar or array. It may be of any data type. It must not be an assumed-size array." I assume that includes derived types, which would be a useful addition. At least they have some user experience when defining these functions.

The standard also gave us "file storage units" for RECL=, so the need for IOLENGTH=. We were not allowed the concept of a byte.

John
Back to top
View user's profile Send private message
davidb



Joined: 17 Jul 2009
Posts: 526
Location: UK

PostPosted: Fri Jul 01, 2016 7:00 am    Post subject: Reply with quote

John, don't worry the intention is to keep the current behaviour. What we are discussing is how to implement it.

First it is clear that one also needs UBOUND and LBOUND and SIZE to be able to return 64bits. I think this works but isn't mentioned in the release notes.

Technically it is the programmers error when one of these functions is called and gives an out of range result. Remember the programmer is responsible for creating the array and knows the array dimension.

As John says, compilers typically treat this the same way as integer overflow, so they crash. Lahey and NAG can detect the overflow and provide an error.

Paul, for option (1) you could keep the current behaviour, but make /ISO imply the use of /SIZE32. However, can I suggest you use /SIZE_ISO instead of /SIZE32. Then you will be able to make this work whatever the default integer size is - to catch uses of /DEF_INT.

Option (2) just needs /SIZE64.

Then, you can add the F2003 kind argument for additional control on top. John wouldn't have to use this though.

(SIZOF is nothing to do with SIZE. Arrays don't need to be contiguous in memory so you can't convert between the two even if you know the storage unit size. Consider an array of 1000 elements, then SIZE(a(1:999:2)) is 500 )
_________________
Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support All times are GMT + 1 Hour
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group