|
|
 |
 |
 |
 |
Fortran Programming Language
|
 |
 |
 |
 |
 |
 |
 |
 |
Question about KIND
I am writing a program with potentially very large arrays and I am currently developing extensible vectors as objects (so I can re- allocate if necessary). The current array bounds are stored with the object (as integers). However, I am not clear as to what I should do about the KIND of these pointers. Specifically: TYPE extensible_vector integer (kind=selected_int_kind(16)) :: lb, allocated_ub, currently_used_ub real (kind=selected_real_kind(15), allocatable, dimension (:) :: vec end TYPE extensible_vector may fail to compile if selected_int_kind(16) is not available (e.g., lahey fortran 7.1 would return -1, and the compiler stops with an error). Is there any way to switch between 4-byte and 8-byte pointers at run-time? Or even just to allocate pointers as 8-byte objects when available and use 4-byte storage plus an error otherwise? I have started to look at "run-time polymorphism" and found a paper by Decyk, Norton and Szymanski on the subject (Computer Physics Commuications 1998). I can't say I have fully digested it. Does my problem have anything to do with run-time polymorphism? Is the mechanism described in that paper still the state of the art? Any feedback would be greatly appreciated. gus gassmann
On Apr 30, 9:39 am, Gus Gassmann <Horand.Gassm@dal.ca> wrote:
> I am writing a program with potentially very large arrays and I am > currently developing extensible vectors as objects (so I can re- > allocate if necessary). The current array bounds are stored with the > object (as integers). However, I am not clear as to what I should do > about the KIND of these pointers. Specifically: > TYPE extensible_vector > integer (kind=selected_int_kind(16)) :: lb, allocated_ub, > currently_used_ub > real (kind=selected_real_kind(15), allocatable, dimension (:) :: > vec > end TYPE extensible_vector > may fail to compile if selected_int_kind(16) is not available (e.g., > lahey fortran 7.1 would return -1, and the compiler stops with an > error). Is there any way to switch between 4-byte and 8-byte pointers > at run-time? Or even just to allocate pointers as 8-byte objects when > available and use 4-byte storage plus an error otherwise? > I have started to look at "run-time polymorphism" and found a paper by > Decyk, Norton and Szymanski on the subject (Computer Physics > Commuications 1998). I can't say I have fully digested it. Does my > problem have anything to do with run-time polymorphism? Is the > mechanism described in that paper still the state of the art? > Any feedback would be greatly appreciated. > gus gassmann
Could SELECTED_INT_KIND() be a solution to your problem?
On Apr 30, 9:50 am, Mark Morss <mfmo@aep.com> wrote:
> On Apr 30, 9:39 am, Gus Gassmann <Horand.Gassm @dal.ca> wrote: > > I am writing a program with potentially very large arrays and I am > > currently developing extensible vectors as objects (so I can re- > > allocate if necessary). The current array bounds are stored with the > > object (as integers). However, I am not clear as to what I should do > > about the KIND of these pointers. Specifically: > > TYPE extensible_vector > > integer (kind=selected_int_kind(16)) :: lb, allocated_ub, > > currently_used_ub > > real (kind=selected_real_kind(15), allocatable, dimension (:) :: > > vec > > end TYPE extensible_vector > > may fail to compile if selected_int_kind(16) is not available (e.g., > > lahey fortran 7.1 would return -1, and the compiler stops with an > > error). Is there any way to switch between 4-byte and 8-byte pointers > > at run-time? Or even just to allocate pointers as 8-byte objects when > > available and use 4-byte storage plus an error otherwise? > > I have started to look at "run-time polymorphism" and found a paper by > > Decyk, Norton and Szymanski on the subject (Computer Physics > > Commuications 1998). I can't say I have fully digested it. Does my > > problem have anything to do with run-time polymorphism? Is the > > mechanism described in that paper still the state of the art? > > Any feedback would be greatly appreciated. > > gus gassmann > Could SELECTED_INT_KIND() be a solution to your problem?
Oh sorry, I see that you're already using that.
On Apr 30, 9:39 am, Gus Gassmann <Horand.Gassm@dal.ca> wrote: > I am writing a program with potentially very large arrays and I am > currently developing extensible vectors as objects (so I can re- > allocate if necessary). The current array bounds are stored with the > object (as integers). However, I am not clear as to what I should do > about the KIND of these pointers.
Are these really "pointers"? It seems to me that you want pointer- sized integers for storing lengths. There isn't an F95-conformant way to do this but I have a couple of suggestions. 1) If all you want is to use a 64-bit integer type if available, then do this: integer, parameter :: k_bigint = max(selected_int_kind(15), kind(0)) Note that this will give you a 64-bit integer kind if the compiler supports it regardless of the size of an address. 2) If you want to know the kind of an address-sized integer, using a common extension, this may work: pointer (pdummy, dummy) ! Extension integer, parameter :: k_bigint = kind(pdummy) If your compiler supports the F2003 ISO_C_BINDING intrinsic module, you can use the constant C_SIZE_T. Steve
Gus Gassmann wrote: > I am writing a program with potentially very large arrays and I am > currently developing extensible vectors as objects (so I can re- > allocate if necessary). The current array bounds are stored with the > object (as integers). However, I am not clear as to what I should do > about the KIND of these pointers. Specifically: > TYPE extensible_vector > integer (kind=selected_int_kind(16)) :: lb, allocated_ub, > currently_used_ub > real (kind=selected_real_kind(15), allocatable, dimension (:) :: > vec > end TYPE extensible_vector > may fail to compile if selected_int_kind(16) is not available (e.g., > lahey fortran 7.1 would return -1, and the compiler stops with an > error). Is there any way to switch between 4-byte and 8-byte pointers > at run-time? Or even just to allocate pointers as 8-byte objects when > available and use 4-byte storage plus an error otherwise? > I have started to look at "run-time polymorphism" and found a paper by > Decyk, Norton and Szymanski on the subject (Computer Physics > Commuications 1998). I can't say I have fully digested it. Does my > problem have anything to do with run-time polymorphism? Is the > mechanism described in that paper still the state of the art? > Any feedback would be greatly appreciated. > gus gassmann
There's no portable way to do this. Compilers aren't required to provide "double precision" integers. They only have to provide an integer that is the same byte size as single precision reals. Are you sure you need 16 digit indexes into your arrays? 32 bit integers are pretty big, won't they work? As an aside, those things aren't "pointers" in the way Fortran uses the word. You'll confuse people (maybe including yourself ;) ) if you call them "pointers". It's relatively easy to use "8 bytes" if it's available and "4 bytes" otherwise. Something like integer, parameter :: double_int = selected_int_kind(16) integer, parameter :: single_int = selected_int_kind(7) integer, parameter :: working_int = max(double_int, single_int) integer (kind=working_int) :: lb, allocated_ub, currently_used_ub ... IF(double_int < 0) print *, "whoops" Most people would put the initial parameters in a module and USE that as a way to save a few trees. Dick Hendrickson
On Apr 30, 12:20 pm, Dick Hendrickson <dick.hendrick@att.net> wrote:
> Gus Gassmann wrote: > > I am writing a program with potentially very large arrays and I am > > currently developing extensible vectors as objects (so I can re- > > allocate if necessary). The current array bounds are stored with the > > object (as integers). However, I am not clear as to what I should do > > about the KIND of these pointers. Specifically: > > TYPE extensible_vector > > integer (kind=selected_int_kind(16)) :: lb, allocated_ub, > > currently_used_ub > > real (kind=selected_real_kind(15), allocatable, dimension (:) :: > > vec > > end TYPE extensible_vector > > may fail to compile if selected_int_kind(16) is not available (e.g., > > lahey fortran 7.1 would return -1, and the compiler stops with an > > error). Is there any way to switch between 4-byte and 8-byte pointers > > at run-time? Or even just to allocate pointers as 8-byte objects when > > available and use 4-byte storage plus an error otherwise? > > I have started to look at "run-time polymorphism" and found a paper by > > Decyk, Norton and Szymanski on the subject (Computer Physics > > Commuications 1998). I can't say I have fully digested it. Does my > > problem have anything to do with run-time polymorphism? Is the > > mechanism described in that paper still the state of the art? > > Any feedback would be greatly appreciated. > > gus gassmann > There's no portable way to do this. Compilers aren't required to > provide "double precision" integers. They only have to provide an > integer that is the same byte size as single precision reals. > Are you sure you need 16 digit indexes into your arrays? 32 bit > integers are pretty big, won't they work? > As an aside, those things aren't "pointers" in the way Fortran uses > the word. You'll confuse people (maybe including yourself ;) ) if > you call them "pointers". > It's relatively easy to use "8 bytes" if it's available and "4 bytes" > otherwise. Something like > integer, parameter :: double_int = selected_int_kind(16) > integer, parameter :: single_int = selected_int_kind(7) > integer, parameter :: working_int = max(double_int, single_int) > integer (kind=working_int) :: lb, allocated_ub, currently_used_ub > ... > IF(double_int < 0) print *, "whoops" > Most people would put the initial parameters in a module and USE that > as a way to save a few trees. > Dick Hendrickson- Hide quoted text - >
Thanks for your suggestions (and to Steve Lionel as well).It turned out to be much easier than I thought. And I promise to try not to use the term 'pointers' again to describe my usage variables. B)
I do have a follow-up question: What does the standard say about the minimum range of integers that must be supported? Is it safe (portable) to assume that selected_int_kind(2000000000) [or 2**31 -1 if you prefer] will return a positive value?
On Apr 30, 12:05 pm, Gus Gassmann <Horand.Gassm@dal.ca> wrote: > I do have a follow-up question: What does the standard say about the > minimum range of integers that must be supported? Is it safe > (portable) to assume that selected_int_kind(2000000000) [or 2**31 -1 > if you prefer] will return a positive value?
The standard does not say. And selected_int_kind takes a number of decimal digits as the argument. You could have a standard-conforming implementation with 8-bit integers. .. or even decimal arithmetic. Steve
"Dick Hendrickson" <dick.hendrick @att.net> wrote in message news:EOnZh.91094$VU4.52168@bgtnsc05-news.ops.worldnet.att.net...
> Gus Gassmann wrote: >> I am writing a program with potentially very large arrays and I am >> currently developing extensible vectors as objects (so I can re- >> allocate if necessary). The current array bounds are stored with the >> object (as integers). However, I am not clear as to what I should do >> about the KIND of these pointers. Specifically: >> TYPE extensible_vector >> integer (kind=selected_int_kind(16)) :: lb, allocated_ub, >> currently_used_ub >> real (kind=selected_real_kind(15), allocatable, dimension (:) :: >> vec >> end TYPE extensible_vector >> may fail to compile if selected_int_kind(16) is not available (e.g., >> lahey fortran 7.1 would return -1, and the compiler stops with an >> error). Is there any way to switch between 4-byte and 8-byte pointers >> at run-time? Or even just to allocate pointers as 8-byte objects when >> available and use 4-byte storage plus an error otherwise? >> I have started to look at "run-time polymorphism" and found a paper by >> Decyk, Norton and Szymanski on the subject (Computer Physics >> Commuications 1998). I can't say I have fully digested it. Does my >> problem have anything to do with run-time polymorphism? Is the >> mechanism described in that paper still the state of the art? >> Any feedback would be greatly appreciated. >> gus gassmann > There's no portable way to do this. Compilers aren't required to > provide "double precision" integers. They only have to provide an > integer that is the same byte size as single precision reals. > Are you sure you need 16 digit indexes into your arrays? 32 bit > integers are pretty big, won't they work? > As an aside, those things aren't "pointers" in the way Fortran uses > the word. You'll confuse people (maybe including yourself ;) ) if > you call them "pointers". > It's relatively easy to use "8 bytes" if it's available and "4 bytes" > otherwise. Something like > integer, parameter :: double_int = selected_int_kind(16) > integer, parameter :: single_int = selected_int_kind(7) > integer, parameter :: working_int = max(double_int, single_int) > integer (kind=working_int) :: lb, allocated_ub, currently_used_ub > ... > IF(double_int < 0) print *, "whoops" > Most people would put the initial parameters in a module and USE that > as a way to save a few trees.
Both you and Steve use the max function when getting the behavior that OP is looking for. I don't quite see what the if statement tells you about double versus single int. My compiler sees the same lack of distinction: comment 1031 - This IF statement is redundant as it will never succeed What gives? -- WW
In article <1177946393.722211.60@n59g2000hsh.googlegroups.com>, Steve Lionel <steve.lio@intel.com> wrote: > 1) If all you want is to use a 64-bit integer type if available, then > do this: > integer, parameter :: k_bigint = max(selected_int_kind(15), kind(0)) > Note that this will give you a 64-bit integer kind if the compiler > supports it regardless of the size of an address.
This works only if the 64-bit kind value happens to be larger than the 32-bit kind value. That might be a reasonable assumption, but it is not mandated by the standard. What you really want is something like: k_bigint = selected_int_kind(15) ! the desired precision if ( k_bigint .lt. 0) k_bigint = kind(0) ! fall back. but you cannot do this with a specification expression to define the parameter value. There are standard ways to achieve this using the MERGE() intrinsic or using the SIGN() intrinsic. Here is a SIGN() based version: integer, parameter :: ip_default = kind(0) integer, parameter :: ip_preferred = selected_int_kind(15) integer, parameter :: ip = & & (1+sign(1,ip_preferred))/2*ip_preferred + & & (1-sign(1,ip_preferred))/2*ip_default You can then use the parameter ip in integer declarations. This is a complicated expression, and you probably don't want to see it scattered throughout your code, so I recommend that you place it in a separate module and USE that module wherever it is necessary. $.02 -Ron Shepard
Steve Lionel wrote: > On Apr 30, 12:05 pm, Gus Gassmann <Horand.Gassm @dal.ca> wrote: >>I do have a follow-up question: What does the standard say about the >>minimum range of integers that must be supported? Is it safe >>(portable) to assume that selected_int_kind(2000000000) [or 2**31 -1 >>if you prefer] will return a positive value? > The standard does not say. And selected_int_kind takes a number of > decimal digits as the argument. You could have a standard-conforming > implementation with 8-bit integers. .. or even decimal arithmetic. The standard requires the default INTEGER and REAL to take the same amount of storage, but it doesn't require that all bits be used. In the 16 bit minicomputer days there were many systems with 16 bit integers and 32 bit and 64 bit floating point types. I believe by default most did not store those 16 bit integers in 32 bits, but most likely would with the appropriate compilation options. C requires INT_MAX to be at least 32767, and suggests that it should be the natural size for the processor. C implementations for 8 bit processors that I know of all use 16 bits for int. I would be surprised to see a Fortran system with a default INTEGER less than 16 bits, but 16 bits doesn't seem too unusual. -- glen
Ron Shepard <ron-shep @NOSPAM.comcast.net> wrote: > but you cannot do this with a specification expression to define the > parameter value. Just to make a picky correction to the terminology... What you mean is initialization expression instead of specification expression. Probably just a slip of the mind on your part, as you ohave the substance correct. Parameters must be defined with initialization expressions. In my own words (the standard doesn't say anything so simple; my version doesn't cover all the fine points, but it is a lot simpler and gives the fundasmental ideas): Initialization expressions must be evaluatable at compile time. Specification expressions must be evaluatable on entry to a procedure. -- Richard Maine | Good judgement comes from experience; email: last name at domain . net | experience comes from bad judgement. domain: summertriangle | -- Mark Twain
Wade Ward <inva @invalid.net> wrote: > "Dick Hendrickson" <dick.hendrick @att.net> wrote in message > news:EOnZh.91094$VU4.52168@bgtnsc05-news.ops.worldnet.att.net... > > It's relatively easy to use "8 bytes" if it's available and "4 bytes" > > otherwise. Something like > > integer, parameter :: double_int = selected_int_kind(16) > > integer, parameter :: single_int = selected_int_kind(7) > > integer, parameter :: working_int = max(double_int, single_int) > > integer (kind=working_int) :: lb, allocated_ub, currently_used_ub > > ... > > IF(double_int < 0) print *, "whoops" > > Most people would put the initial parameters in a module and USE that > > as a way to save a few trees. > Both you and Steve use the max function when getting the behavior that OP is > looking for. I don't quite see what the if statement tells you about double > versus single int. My compiler sees the same lack of distinction: > comment 1031 - This IF statement is redundant as it will never succeed > What gives?
What gives is that the IF statement seems redundant for any particular compiler, insomuch as the expression in it is an initialization expression and thus can be evaluated at compile time. For your compiler, apparently it reduces to if (.false.) print *, "whoops" which, in turn, could be reduced to just continue But it will get different results for different compilers, so in fact, it is not really redundant. On some other compiler, it would reduce to if (.true.) print *, "whoops" which could be further reduced to print *, "whoops" -- Richard Maine | Good judgement comes from experience; email: last name at domain . net | experience comes from bad judgement. domain: summertriangle | -- Mark Twain
In article <1hxdp07.1ic6q3pslmb1bN%nos@see.signature>, nos@see.signature (Richard Maine) wrote: > What you mean is initialization expression instead of specification > expression.
Yes, that is the right term. Thanks. $.02 -Ron Shepard
|
 |
 |
 |
 |
|