|
|
||||
|
||||
|
|
|
|||
|
Gary L. Scott <garylscott@sbcglobal.net> wrote:
> If I have a sequence derived type with say two allocatable components, > does it matter the order that I allocate the components? No. > Is it > essentially "undefined" until I allocate the final component? Hmm. That's a slightly subtle point, which drove me to check some details. I'm not sure the standard is 100% consistent on this, though I didn't spend enough time to be sure of that. The standard does say that a derived type object is defined if each non-pointer component is defined. An allocatable is not a pointer (its implementation in memory might look like one, but that's irrelevant). An unallocated allocatable is undefined. Thus, that would support your statement above that the derived-type object is undefined as long as either of the allocatable components are unallocated. But you can do intrinsic assignment of a derived type object that has unallocated components. The standard explicitly describes what happens in that case (and it is the "obvious" thing - that the variable assigned to will end up with the corresponding component unallocated). Hmm. Gotta go. I think I might recall that the requirement fo rthe RHS of an assignment be defined might not apply to derived types, but I don't have time to check that. Breakfast call from wife. -- Richard Maine | Good judgment comes from experience; email: last name at domain . net | experience comes from bad judgment. domain: summertriangle | -- Mark Twain |
|
|||
|
On 3/25/2012 11:37 AM, Richard Maine wrote:
> Gary L. Scott<garylscott@sbcglobal.net> wrote: > >> If I have a sequence derived type with say two allocatable components, >> does it matter the order that I allocate the components? > > No. > >> Is it >> essentially "undefined" until I allocate the final component? I was wondering because I wanted to use the first two static components to read a file and assign to them "record type" and number of elements to be allocated. I guess I should read into static variables and not make assignment to the DT until after the allocation is complete. (just trying to reduce # of local variables). > > Hmm. That's a slightly subtle point, which drove me to check some > details. I'm not sure the standard is 100% consistent on this, though I > didn't spend enough time to be sure of that. The standard does say that > a derived type object is defined if each non-pointer component is > defined. An allocatable is not a pointer (its implementation in memory > might look like one, but that's irrelevant). An unallocated allocatable > is undefined. Thus, that would support your statement above that the > derived-type object is undefined as long as either of the allocatable > components are unallocated. > > But you can do intrinsic assignment of a derived type object that has > unallocated components. The standard explicitly describes what happens > in that case (and it is the "obvious" thing - that the variable assigned > to will end up with the corresponding component unallocated). > > Hmm. Gotta go. I think I might recall that the requirement fo rthe RHS > of an assignment be defined might not apply to derived types, but I > don't have time to check that. Breakfast call from wife. > |
|
|||
|
On 3/25/2012 2:13 PM, Gary Scott wrote:
> On 3/25/2012 11:37 AM, Richard Maine wrote: >> Gary L. Scott<garylscott@sbcglobal.net> wrote: >> >>> If I have a sequence derived type with say two allocatable components, >>> does it matter the order that I allocate the components? >> >> No. >> >>> Is it >>> essentially "undefined" until I allocate the final component? > > I was wondering because I wanted to use the first two static components > to read a file and assign to them "record type" and number of elements > to be allocated. I guess I should read into static variables and not > make assignment to the DT until after the allocation is complete. (just > trying to reduce # of local variables). It actually appears to be working as designed though... > >> >> Hmm. That's a slightly subtle point, which drove me to check some >> details. I'm not sure the standard is 100% consistent on this, though I >> didn't spend enough time to be sure of that. The standard does say that >> a derived type object is defined if each non-pointer component is >> defined. An allocatable is not a pointer (its implementation in memory >> might look like one, but that's irrelevant). An unallocated allocatable >> is undefined. Thus, that would support your statement above that the >> derived-type object is undefined as long as either of the allocatable >> components are unallocated. >> >> But you can do intrinsic assignment of a derived type object that has >> unallocated components. The standard explicitly describes what happens >> in that case (and it is the "obvious" thing - that the variable assigned >> to will end up with the corresponding component unallocated). >> >> Hmm. Gotta go. I think I might recall that the requirement fo rthe RHS >> of an assignment be defined might not apply to derived types, but I >> don't have time to check that. Breakfast call from wife. >> > |
|
|||
|
On 3/25/2012 2:14 PM, Gary Scott wrote:
> On 3/25/2012 2:13 PM, Gary Scott wrote: >> On 3/25/2012 11:37 AM, Richard Maine wrote: >>> Gary L. Scott<garylscott@sbcglobal.net> wrote: >>> >>>> If I have a sequence derived type with say two allocatable components, >>>> does it matter the order that I allocate the components? >>> >>> No. >>> >>>> Is it >>>> essentially "undefined" until I allocate the final component? >> >> I was wondering because I wanted to use the first two static components >> to read a file and assign to them "record type" and number of elements >> to be allocated. I guess I should read into static variables and not >> make assignment to the DT until after the allocation is complete. (just >> trying to reduce # of local variables). > > It actually appears to be working as designed though... except for: Error 1 error #7822: Variables containing ultimate allocatable array components are forbidden from appearing directly in input/output lists. Why this restriction if I have previously fully allocated all components to match the file content? > >> >>> >>> Hmm. That's a slightly subtle point, which drove me to check some >>> details. I'm not sure the standard is 100% consistent on this, though I >>> didn't spend enough time to be sure of that. The standard does say that >>> a derived type object is defined if each non-pointer component is >>> defined. An allocatable is not a pointer (its implementation in memory >>> might look like one, but that's irrelevant). An unallocated allocatable >>> is undefined. Thus, that would support your statement above that the >>> derived-type object is undefined as long as either of the allocatable >>> components are unallocated. >>> >>> But you can do intrinsic assignment of a derived type object that has >>> unallocated components. The standard explicitly describes what happens >>> in that case (and it is the "obvious" thing - that the variable assigned >>> to will end up with the corresponding component unallocated). >>> >>> Hmm. Gotta go. I think I might recall that the requirement fo rthe RHS >>> of an assignment be defined might not apply to derived types, but I >>> don't have time to check that. Breakfast call from wife. >>> >> > |
|
|||
|
>>
>> It actually appears to be working as designed though... > > except for: > > Error 1 error #7822: Variables containing ultimate allocatable array > components are forbidden from appearing directly in input/output lists. > > Why this restriction if I have previously fully allocated all components > to match the file content? Further testing: So it appears that I can list each component individually in the I/O statement, just not as a single object. Does that make sense? At least it appears that I don't have to massively redesign... |
|
|||
|
Gary Scott <garylscott@sbcglobal.net> wrote:
> >> > >> It actually appears to be working as designed though... > > > > except for: > > > > Error 1 error #7822: Variables containing ultimate allocatable array > > components are forbidden from appearing directly in input/output lists. > > > > Why this restriction if I have previously fully allocated all components > > to match the file content? > > Further testing: So it appears that I can list each component > individually in the I/O statement, just not as a single object. Does > that make sense? At least it appears that I don't have to massively > redesign... Yes, you can do it that way. As for why the prohibition, I'd point to exactly the distinction between reading the whole derived-type object versus reading the individual components. When you read the whole derived-type object directly, what you are reading would *INCLUDE* the allocation size, at least it would include that if it were allowed. The allocation status is part of the value object, so that would be part of what was read. When you read a single allocatable component, however, you are reading into the contents of that component, just as if you were reading into an allocatable array that wasn't a component. Consider the parallel to what happens for an INTENT(OUT) dummy argument. If it has an allocatable component, that component gets deallocated on entry. You can't allocate the component in the calling routine and expect that allocation to stick in spite of the INTENT(OUT). Again, that's because the allocation status of allocatable components is part of the value of the object. Reading a variable is much like passing it as an actual argument to an intent(out) dummy. The value is completely determined by whatever is defined from the file or the subroutine. It doesn't keep parts that might have been defined before the read or call. When you directly read an allocated allocatable variable, that's different because what you are really reading is into the contents, much like if it were a pointer and you were reading into the target. (In fact, yes, you can also read into an allocated pointer and that's what happens; you are reading into the target). -- Richard Maine | Good judgment comes from experience; email: last name at domain . net | experience comes from bad judgment. domain: summertriangle | -- Mark Twain |
|
|||
|
Richard Maine <nospam@see.signature> wrote:
> Gary Scott <garylscott@sbcglobal.net> wrote: (snip) >> > Error 1 error #7822: Variables containing ultimate allocatable array >> > components are forbidden from appearing directly in input/output >> > lists. >> > Why this restriction if I have previously fully allocated >> > all components to match the file content? >> Further testing: So it appears that I can list each component >> individually in the I/O statement, just not as a single object. Does >> that make sense? At least it appears that I don't have to massively >> redesign... > Yes, you can do it that way. As for why the prohibition, I'd point to > exactly the distinction between reading the whole derived-type object > versus reading the individual components. > When you read the whole derived-type object directly, what you are > reading would *INCLUDE* the allocation size, at least it would include > that if it were allowed. The allocation status is part of the value > object, so that would be part of what was read. When you read a single > allocatable component, however, you are reading into the contents of > that component, just as if you were reading into an allocatable array > that wasn't a component. I might believe that in the case of UNFORMATTED, but it is less convincing in the FORMATTED case. For UNFORMATTED, one might say that the internal representation includes things like allocation status and size, and that those should also be read in. That is less obvious for FORMATTED, though. > Consider the parallel to what happens for an INTENT(OUT) dummy argument. > If it has an allocatable component, that component gets deallocated on > entry. You can't allocate the component in the calling routine and > expect that allocation to stick in spite of the INTENT(OUT). Again, > that's because the allocation status of allocatable components is part > of the value of the object. > Reading a variable is much like passing it as an actual argument to an > intent(out) dummy. The value is completely determined by whatever is > defined from the file or the subroutine. It doesn't keep parts that > might have been defined before the read or call. The claim above is for I/O lists, and would also seem to include WRITE. Now, it might be that someone wants to reserve these for future definition such that the would work. That is, that one could write out allocatable data, including the allocation status and size, and later read it back in again. (Most likely as UNFORMATTED.) If that is the reason, then I probably agree with disallowing it for now. Otherwise, it would seem that the obvious way of doing it, the way the OP expected, isn't so bad. > When you directly read an allocated allocatable variable, that's > different because what you are really reading is into the contents, much > like if it were a pointer and you were reading into the target. (In > fact, yes, you can also read into an allocated pointer and that's what > happens; you are reading into the target). -- glen |
|
|||
|
Hi Gary
Objects of derived type containing allocatable components can't appear in built-in I/O regardless of definition status. As you found out, you can just write the individual components instead of the containing structure. If your compiler supports user-defined derived type I/O, you can specify your own routine that will be called to do the write operation. Your routine will most likely have to check the allocation status of each allocatable component before writing it and also decide what to write if the component is not allocated. Look up the write(formatted) and write(unformatted) generic interfaces for more information. Richard has already answered about the reasons for this constraint. Regards Rafik Visit the Fortran Cafe at http://ibm.com/rational/cafe "Gary Scott" <garylscott@sbcglobal.net> wrote in message news:jknveh$af1$1@dont-email.me... > On 3/25/2012 2:14 PM, Gary Scott wrote: >> On 3/25/2012 2:13 PM, Gary Scott wrote: >>> On 3/25/2012 11:37 AM, Richard Maine wrote: >>>> Gary L. Scott<garylscott@sbcglobal.net> wrote: >>>> >>>>> If I have a sequence derived type with say two allocatable components, >>>>> does it matter the order that I allocate the components? >>>> >>>> No. >>>> >>>>> Is it >>>>> essentially "undefined" until I allocate the final component? >>> >>> I was wondering because I wanted to use the first two static components >>> to read a file and assign to them "record type" and number of elements >>> to be allocated. I guess I should read into static variables and not >>> make assignment to the DT until after the allocation is complete. (just >>> trying to reduce # of local variables). >> >> It actually appears to be working as designed though... > > except for: > > Error 1 error #7822: Variables containing ultimate allocatable array > components are forbidden from appearing directly in input/output lists. > > Why this restriction if I have previously fully allocated all components > to match the file content? > >> >>> >>>> >>>> Hmm. That's a slightly subtle point, which drove me to check some >>>> details. I'm not sure the standard is 100% consistent on this, though I >>>> didn't spend enough time to be sure of that. The standard does say that >>>> a derived type object is defined if each non-pointer component is >>>> defined. An allocatable is not a pointer (its implementation in memory >>>> might look like one, but that's irrelevant). An unallocated allocatable >>>> is undefined. Thus, that would support your statement above that the >>>> derived-type object is undefined as long as either of the allocatable >>>> components are unallocated. >>>> >>>> But you can do intrinsic assignment of a derived type object that has >>>> unallocated components. The standard explicitly describes what happens >>>> in that case (and it is the "obvious" thing - that the variable >>>> assigned >>>> to will end up with the corresponding component unallocated). >>>> >>>> Hmm. Gotta go. I think I might recall that the requirement fo rthe RHS >>>> of an assignment be defined might not apply to derived types, but I >>>> don't have time to check that. Breakfast call from wife. >>>> >>> >> > |
|
|||
|
On 3/25/2012 4:34 PM, Richard Maine wrote:
> Gary Scott<garylscott@sbcglobal.net> wrote: > >>>> >>>> It actually appears to be working as designed though... >>> >>> except for: >>> >>> Error 1 error #7822: Variables containing ultimate allocatable array >>> components are forbidden from appearing directly in input/output lists. >>> >>> Why this restriction if I have previously fully allocated all components >>> to match the file content? >> >> Further testing: So it appears that I can list each component >> individually in the I/O statement, just not as a single object. Does >> that make sense? At least it appears that I don't have to massively >> redesign... > > Yes, you can do it that way. As for why the prohibition, I'd point to > exactly the distinction between reading the whole derived-type object > versus reading the individual components. > > When you read the whole derived-type object directly, what you are > reading would *INCLUDE* the allocation size, at least it would include > that if it were allowed. The allocation status is part of the value > object, so that would be part of what was read. When you read a single > allocatable component, however, you are reading into the contents of > that component, just as if you were reading into an allocatable array > that wasn't a component. > > Consider the parallel to what happens for an INTENT(OUT) dummy argument. > If it has an allocatable component, that component gets deallocated on > entry. You can't allocate the component in the calling routine and > expect that allocation to stick in spite of the INTENT(OUT). Again, > that's because the allocation status of allocatable components is part > of the value of the object. > > Reading a variable is much like passing it as an actual argument to an > intent(out) dummy. The value is completely determined by whatever is > defined from the file or the subroutine. It doesn't keep parts that > might have been defined before the read or call. > > When you directly read an allocated allocatable variable, that's > different because what you are really reading is into the contents, much > like if it were a pointer and you were reading into the target. (In > fact, yes, you can also read into an allocated pointer and that's what > happens; you are reading into the target). > Since it may be ambiguous as to what you might want to do in the single object case, perhaps we could add some sort of syntax modifier (future standard) that would tell the compiler that you want to treat it as if you specified the individual components without out having to write the multiple (possibly a great many) components out explicitly. It would be nice to be able to do it automatically (including the allocation size) but I'd rather not be forced to write out huge numbers of components by name in those cases where it isn't necessary (where I've done the work to pre-allocate to the correct size). |
|
|||
|
For some reason, I thought you were trying to write. The reply applies to
read as well, except the generic interfaces are read(formatted) and read(unformatted). Regards Rafik Visit the Fortran Cafe at http://ibm.com/rational/cafe |
|
|||
|
On Mar 25, 9:16*am, "Gary L. Scott" <garylsc...@sbcglobal.net> wrote:
> Hi, > > If I have a sequence derived type with say two allocatable components, > does it matter the order that I allocate the components? *Is it > essentially "undefined" until I allocate the final component? An interesting feature of allocatable components is that circular definitions are allowed. If the type of a variable includes an allocatable component and that component has a circular definition that does not involve pointers, the variable cannot become defined. Robert Corbett |
|
|||
|
Gary Scott <garylscott@sbcglobal.net> wrote:
>>>> Error 1 error #7822: Variables containing ultimate allocatable array >>>> components are forbidden from appearing directly in input/output lists. (snip) > Since it may be ambiguous as to what you might want to do in the single > object case, perhaps we could add some sort of syntax modifier (future > standard) that would tell the compiler that you want to treat it as if > you specified the individual components without out having to write the > multiple (possibly a great many) components out explicitly. It would be > nice to be able to do it automatically (including the allocation size) > but I'd rather not be forced to write out huge numbers of components by > name in those cases where it isn't necessary (where I've done the work > to pre-allocate to the correct size). Especially in the case of list-directed I/O that you might do when debugging. The whole advantage of list-directed is that you don't need to write so much to use it. I suppose I wouldn't mind having the size also printed. -- glen |
|
|||
|
Hi
Regarding formatted I/O with objects containing allocatable components: Allocatables are usually represented using descriptors. A Fortran descriptor typically contains the address of the data, allocation status, rank and bounds information (if applicable), and many other vendor-specific fields. Technically, all fields are vendor-specific since the standard does not describe or mandate Fortran descriptors, but I'd be surprised if a vendor didn't have the ones above. The upcoming Technical Specification for further interoperability with C will specify a "C descriptor" format which is basically a standard way of describing parts of the Fortran descriptor. So given this, if you have formatted I/O like this: type dt real, allocatable :: a( ![]() real, allocatable :: b( ![]() end type type(dt) :: x !... print *, x What should the output be if x%a is unallocated? What should it be if both x%a and x%b are unallocated? If the answer is that we should write nothing for unallocated allocatable components, then we'll have problems with READ. If the answer is to write something like "(unallocated)", people will be unhappy that their formatted data reports contain text about implementation details. On input, if we get 20 comma-separated real values on one line, how do we know how many of these values are part of x%a and how many are part of x%b? If x%a and x%b were not allocatable, we can tell by looking at the declared type. But since they're allocatable, the extent can be anything. As Richard explained, if you have "READ *, x", x%a and x%b will be unallocated (and if applicable finalized) before the read just like they are with INTENT(OUT) args. So all this information has to be discernable from the declared type or the data file we're reading from. The standard solves this by offloading these decisions to the user. If a type has allocatable or pointer components, objects of that type can't appear in an I/O list unless the type has a user-defined derived type I/O routine. That way, users can write output routines that write things in a format that can be read by their input routines, if they wish. Regards Rafik Visit the Fortran Cafe at http://ibm.com/rational/cafe/ "glen herrmannsfeldt" <gah@ugcs.caltech.edu> wrote in message news:jkocj2$n62$1@speranza.aioe.org... > Richard Maine <nospam@see.signature> wrote: >> Gary Scott <garylscott@sbcglobal.net> wrote: > > (snip) >>> > Error 1 error #7822: Variables containing ultimate allocatable array >>> > components are forbidden from appearing directly in input/output >>> > lists. > >>> > Why this restriction if I have previously fully allocated >>> > all components to match the file content? > >>> Further testing: So it appears that I can list each component >>> individually in the I/O statement, just not as a single object. Does >>> that make sense? At least it appears that I don't have to massively >>> redesign... > >> Yes, you can do it that way. As for why the prohibition, I'd point to >> exactly the distinction between reading the whole derived-type object >> versus reading the individual components. > >> When you read the whole derived-type object directly, what you are >> reading would *INCLUDE* the allocation size, at least it would include >> that if it were allowed. The allocation status is part of the value >> object, so that would be part of what was read. When you read a single >> allocatable component, however, you are reading into the contents of >> that component, just as if you were reading into an allocatable array >> that wasn't a component. > > I might believe that in the case of UNFORMATTED, but it is less > convincing in the FORMATTED case. > > For UNFORMATTED, one might say that the internal representation > includes things like allocation status and size, and that those > should also be read in. That is less obvious for FORMATTED, though. > >> Consider the parallel to what happens for an INTENT(OUT) dummy argument. >> If it has an allocatable component, that component gets deallocated on >> entry. You can't allocate the component in the calling routine and >> expect that allocation to stick in spite of the INTENT(OUT). Again, >> that's because the allocation status of allocatable components is part >> of the value of the object. > >> Reading a variable is much like passing it as an actual argument to an >> intent(out) dummy. The value is completely determined by whatever is >> defined from the file or the subroutine. It doesn't keep parts that >> might have been defined before the read or call. > > The claim above is for I/O lists, and would also seem to include WRITE. > > Now, it might be that someone wants to reserve these for future > definition such that the would work. That is, that one could write > out allocatable data, including the allocation status and size, > and later read it back in again. (Most likely as UNFORMATTED.) > If that is the reason, then I probably agree with disallowing > it for now. Otherwise, it would seem that the obvious way of > doing it, the way the OP expected, isn't so bad. > >> When you directly read an allocated allocatable variable, that's >> different because what you are really reading is into the contents, much >> like if it were a pointer and you were reading into the target. (In >> fact, yes, you can also read into an allocated pointer and that's what >> happens; you are reading into the target). > > -- glen |
|
|||
|
Rafik Zurob <nospam@hotmail.com> wrote:
> Regarding formatted I/O with objects containing allocatable components: > Allocatables are usually represented using descriptors. A Fortran > descriptor typically contains the address of the data, > allocation status, rank and bounds information (if applicable), > and many other vendor-specific fields. Technically, all fields > are vendor-specific since the standard does not describe or > mandate Fortran descriptors, but I'd be surprised if a vendor > didn't have the ones above. The upcoming Technical Specification > for further interoperability with C will specify a "C descriptor" > format which is basically a standard way of describing parts of > the Fortran descriptor. > So given this, if you have formatted I/O like this: > type dt > real, allocatable :: a( ![]() > real, allocatable :: b( ![]() > end type > type(dt) :: x > !... > print *, x > What should the output be if x%a is unallocated? Well, one choice is that it isn't allowed. > What should it be if both x%a and x%b are unallocated? > If the answer is that we should write nothing for unallocated > allocatable components, then we'll have problems with READ. In the case of UNFORMATTED, one would expect that whatever you wrote could also be read in with the same result. > If the answer is to write something like "(unallocated)", people > will be unhappy that their formatted data reports contain text > about implementation details. I say that "(unallocated)" isn't an implementation detail. The bit patterns that indicated it would be, though. > On input, if we get 20 comma-separated real values on one line, > how do we know how many of these values are part of x%a and how > many are part of x%b? print *,a,b (a and b are assumed shape arrays) You can't tell from what is printed how many are a and how many are b. > If x%a and x%b were not allocatable, we can tell by looking > at the declared type. But since they're allocatable, > the extent can be anything. You also can't tell from assumed shape. > As Richard explained, if you have "READ *, x", x%a and x%b will > be unallocated (and if applicable finalized) before the read > just like they are with INTENT(OUT) args. So all this > information has to be discernable from the declared type or > the data file we're reading from. That is a possible situation, but I don't know that it has to be that way. > The standard solves this by offloading these decisions to the user. > If a type has allocatable or pointer components, objects of that > type can't appear in an I/O list unless the type has a user-defined > derived type I/O routine. That way, users can write output routines > that write things in a format that can be read by their input > routines, if they wish. But they can appear without user-defined derived type I/O routines if they don't have allocatable or pointer components? -- glen |
|
|
![]() |
| Thread Tools | |
| Display Modes | |
|
|