Google グループは Usenet の新規の投稿と購読のサポートを終了しました。過去のコンテンツは引き続き閲覧できます。
Dismiss

Sourced allocation - how is the value copied?

閲覧: 35 回
最初の未読メッセージにスキップ

Rich Townsend

未読、
2011/01/31 17:38:082011/01/31
To:
Hi all --

In a sourced allocation of an allocatable polymorphic, how is the
value copied across from the source? For instance, consider this
example, where bar_t is an extension of foo_t:

type(bar_t) :: b
class(foo_t), allocatable :: f

allocate(f, source=b)

This will allocate f, give it a dynamic type of bar_t, and set its
value equal to b. But how is this value setting done? Is it an
intrinsic assignment? Or, is a defined assignment done (assuming bar_t
has an ASSIGNMENT(=) type-bound procedure)?

If the former, then is it possible to set up f with b's type, but
without any value setting taking place via intrinsic assignment? This
would be useful, for instance, if foo_t and bar_t were linked lists --
for which intrinsic assignment is not the right thing to do.

cheers,

Rich


steve

未読、
2011/01/31 18:13:442011/01/31
To:

I believe that that it is an intrinsic assignment. EBNF
has

SOURCE=source-expr

source-expr is expr
expr is [ expr defined-binary-op ] level-5-expr
defined-binary-op is . letter [ letter ] ... .

A defined assignment is not a level-5-expr.

--
steve

Richard Maine

未読、
2011/01/31 19:13:212011/01/31
To:
steve <kar...@comcast.net> wrote:

That's pretty much a non-sequitur. You are just talking about the syntax
of the expression. The syntax is, not surprisingly, that of any other
expression. That has nothing to do with what happens after the
expression is evaluated. Defined assignment is not part of the
expression; it is something that might happen with an expression. Heck,
I could generalize your argument to say that there is no such thing as
defined assignment because the syntax of assignment has the same expr on
its right-hand side and "defined asignment is not a level-5-expr."

I don't actually see that the standard uses the word "assignment" at all
in the context of SOURCE= in the allocate statement. It just says that
"the value of allocate-object becomes that of source-expr". (And I see
that f2008 has some different wording - possibly a bug fix, but the
differences have to do only with array vs scalar issues; it still just
talks about "values becoming.") That "value becomes" bit sounds a lot
like the same thing as intrinsic assignment does for cases where the
type and type parameters agree, but I'm not going to go out on a limb
and say that it actually is intrinsic assignment because maybe I've
missed something. I'll waffle and say that it seems to do the same thing
as intrinsic assignment even if it doesn't use that name for it. I
certainly see no justification at all for it being defined assignment.

Sounds to me like what you want is the MOLD= that got added in f2008.
Umm. Anyway I think that is what MOLD= is supposed to do. I sure can't
deduce that from the words of the standard, though. The standard appears
to say nothing at all about what the MOLD= actually does. The complete
and entire description of MOLD, other than just its syntax, appears to
be

"If MOLD= appears and source-expr is a variable, its value need not be
defined."

which I find less than edifying. Even the syntax is confused in that the
restrictions talk about source-expr as though there is only one of them,
even though the BNF shows source-expr in both SOURCE= and MOLD=. I'm
guessing that you aren't supposed to be allowed to specify both SOURCE=
and MOLD=, but I see nothing that quite says that - just words that
don't make much sense if you have both of them. Well, maybe the
"At most one of source-expr and type-spec shall appear" does it, though
my first reading of that was just that you could not specify both
source-expr and type-spec. I suppose maybe it also says that you can't
specify source-expr in two different spots, but I'm sure not impressed
with its clarity.

But even if I grant the syntax as ok, I'm still left completely guessing
as to what the source-expr does when it is in MOLD=. All its description
is in the para that begins with "If SOURCE= appears." I think someone
meant paarts of that to also apply to MOLD=. You just have to figure out
which parts don't make sense if the value might not be defined; that
would be the bit about the "value becoming that of source-expr." I think
that's a pretty good guess, but it would be nice if the standard said
that instead of leaving one to guess.

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain

Rich Townsend

未読、
2011/02/01 0:59:152011/02/01
To:

Thanks for the analysis. It seems that MOLD is what I want here -- at least,
going by what is written in John Reid's "The new features of Fortran 2008"
document. Is the standard truly as vague as you say?

cheers,

Rich


Wolfgang Kilian

未読、
2011/02/01 3:21:292011/02/01
To:
On 02/01/2011 06:59 AM, Rich Townsend wrote:
> nos...@see.signature (Richard Maine) wrote:
>
>> steve <kar...@comcast.net> wrote:
>>
>>> On Jan 31, 2:38 pm, Rich Townsend <mylastn...@astro.wisc.edu> wrote:
>>
>>>> In a sourced allocation of an allocatable polymorphic, how is the
>>>> value copied across from the source? For instance, consider this
>>>> example, where bar_t is an extension of foo_t:
>>>>
>>>> type(bar_t) :: b
>>>> class(foo_t), allocatable :: f
>>>>
>>>> allocate(f, source=b)
>>>> [...]

>> Sounds to me like what you want is the MOLD= that got added in f2008.
>> Umm. Anyway I think that is what MOLD= is supposed to do. I sure can't
>> deduce that from the words of the standard, though. The standard appears
>> to say nothing at all about what the MOLD= actually does. The complete
>> and entire description of MOLD, other than just its syntax, appears to
>> be
>>
>> "If MOLD= appears and source-expr is a variable, its value need not be
>> defined."
>>

I have a related problem: suppose that there is an allocated array with
polymorphic type, and I want to expand (reallocate) that array. Here is
some code that realizes the task:

---
module realloc
implicit none

type :: base_type
integer :: i
contains
procedure :: assign
generic :: assignment(=) => assign ! define generic assignment
end type base_type

type, extends(base_type) :: extended_type
integer :: j
end type extended_type

contains

elemental subroutine assign (a, b)
class(base_type), intent(out) :: a
type(base_type), intent(in) :: b
a%i = b%i
end subroutine assign

subroutine reallocate (a)
class(base_type), dimension(:), allocatable, intent(inout) :: a
class(base_type), dimension(:), allocatable :: tmp
allocate (tmp (2 * size (a))) ! how to alloc b with same type as a ?
call print_type ("tmp", tmp)
tmp(:size(a)) = a ! polymorphic l.h.s.
call move_alloc (from=tmp, to=a)
end subroutine reallocate

subroutine print_type (name, a)
character(*), intent(in) :: name
class(base_type), dimension(:), intent(in) :: a
select type (a)
type is (base_type); print *, name // " is base_type"
type is (extended_type); print *, name // " is extended_type"
end select
end subroutine print_type

end module realloc

program main
use realloc
implicit none
class(base_type), dimension(:), allocatable :: a

allocate (extended_type :: a(10))
call print_type ("a", a)
call reallocate (a)
call print_type ("a", a)
end program main

----
This compiles and runs with NAG Fortran 5.2, and the output is:

a is extended_type
tmp is base_type
a is base_type

So the type is not preserved. To remedy this, I could write

allocate (extended_type :: tmp (2 * size (a)))

but this requires a specific 'reallocate' for each extension of
base_type. A single 'reallocate' containing a 'select type' clause is
not a complete solution since extensions of base_type might be defined
in any module which uses module 'realloc'.

The SOURCE argument of ALLOCATE is not allowed here.

Furthermore, it looks like I need a separate specific defined assignment
for each extension of base_type; there may be many such extensions. I
rather would have intrinsic assignment in this situation, but this is
forbidden in F2003.

My questions:

1) Is there a simpler solution in Fortran 2003?

2) Does Fortran 2008 give a solution? Apparently, it would remove the
need for defined assignment. If I use MOLD, does it specify the
allocate shape? Can I use allocate-shape-list together with MOLD to
override this setting (cf. C633)?

-- Wolfgang


--
E-mail: firstnameini...@domain.de
Domain: yahoo

Tobias Burnus

未読、
2011/02/01 4:36:372011/02/01
To:
On 02/01/2011 09:21 AM, Wolfgang Kilian wrote:
>>> Sounds to me like what you want is the MOLD= that got added in f2008.

I concur with Richard.

>>> Umm. Anyway I think that is what MOLD= is supposed to do. I sure can't
>>> deduce that from the words of the standard, though. The standard appears
>>> to say nothing at all about what the MOLD= actually does. The complete
>>> and entire description of MOLD, other than just its syntax, appears to
>>> be
>>> "If MOLD= appears and source-expr is a variable, its value need not be
>>> defined."

I think one can deduce it from the standard, though it is not well
written. My understanding is that is allocates the variable based on the
effective type of the source-expr in MOLD= and "assigns" the default
initializer (if existing) to it.

> subroutine reallocate (a)
> class(base_type), dimension(:), allocatable, intent(inout) :: a
> class(base_type), dimension(:), allocatable :: tmp
> allocate (tmp (2 * size (a))) ! how to alloc b with same type as a ?

Fortran 2008: MOLD=a; Fortran 2003: SOURCE=a.
The 2003 version has the disadvantage that for deeply nested derived
types with allocatable components, all those are copied/initialized as
well, while the MOLD= version matches
allocate(effective-type-of-a :: tmp(...))


> allocate (extended_type :: tmp (2 * size (a)))
>
> but this requires a specific 'reallocate' for each extension of
> base_type. A single 'reallocate' containing a 'select type' clause is
> not a complete solution since extensions of base_type might be defined
> in any module which uses module 'realloc'.
>
> The SOURCE argument of ALLOCATE is not allowed here.

Sorry, I do not understand this. What prevents the use of SOURCE=a?


> Furthermore, it looks like I need a separate specific defined assignment
> for each extension of base_type; there may be many such extensions. I
> rather would have intrinsic assignment in this situation, but this is
> forbidden in F2003.

Fortran 2008 allows an intrinsic assignment, if the LHS is allocatable.
Thus, for "tmp(:size(a)) = a" it would not work either - thus the
intrinsic assignment does not work if one wants to resize the array.

You could use a defined assignment, defined for every type extension
which adds a new component.

Otherwise, your defined assignment should work, though you could
consider to use CLASS instead of TYPE for the RHS dummy argument "b".


> 2) Does Fortran 2008 give a solution? Apparently, it would remove the
> need for defined assignment. If I use MOLD, does it specify the
> allocate shape? Can I use allocate-shape-list together with MOLD to
> override this setting (cf. C633)?

I think C633 uses an inclusive or:

"C633 (R631) If allocate-object is an array either
allocate-shape-spec-list shall appear or source-expr shall appear and
have the same rank as allocate-object. If allocate-object is scalar,
allocate-shape-spec-list shall not appear."

"When an ALLOCATE statement is executed for an array for which
allocate-shape-spec-list is specified, the values of the lower bound and
upper bound expressions determine the bounds of the array. [...]"
"When an ALLOCATE statement is executed for an array with no
allocate-shape-spec-list, the bounds of source-expr determine the bounds
of the array."

Tobias

PS: I had to use an array-free version to test with gfortran as support
for polymorphic arrays is still rather incomplete [1]. Additionally,
gfortran does not like [2] if a polymorphic actual is passed to a
nonpolymorphic dummy; thus I had to change "assign". Afterwards using
SOURCE= and using MOLD= gave always the correct effective type: "is
extended_type".
[1] http://gcc.gnu.org/wiki/OOP
[2] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46990
Regarding [1]: The plan was to add array support for GCC 4.6 but too
many other OOP bugs/omissions had to be fixed (cf. bottom of [1]), thus
fixing OOP array support has been deferred to 4.7.

Wolfgang Kilian

未読、
2011/02/01 4:53:582011/02/01
To:

Oops -- if it was allowed, there would be no problem at all (and no need
for MOLD or defined assignment). Actually, NAG accepts

allocate (tmp (2 * size (a)), source=a)


call print_type ("tmp", tmp)

call move_alloc (from=tmp, to=a)

and both tmp and a get the correct dynamic type. This is what I wanted
to do in the first place, I just didn't dare ...

However, is this really standard-conforming? The F2003 draft, p.112 l.7
says

If SOURCE= appears, source-expr shall be conformable (2.4.5) with
allocation.

My understanding is that a and tmp are not conformable if I double the
size. Maybe this is a misinterpretation? However, is it obvious where
the source is to be copied in the enlarged array? Will the remaining
part be default-initialized correctly? What if the allocated size is
smaller than a?

Wolfgang Kilian

未読、
2011/02/01 5:04:522011/02/01
To:
On 02/01/2011 10:53 AM, Wolfgang Kilian wrote:
>
> allocate (tmp (2 * size (a)), source=a)
> call print_type ("tmp", tmp)
> call move_alloc (from=tmp, to=a)
>
> and both tmp and a get the correct dynamic type. This is what I wanted
> to do in the first place, I just didn't dare ...
>
> However, is this really standard-conforming? The F2003 draft, p.112 l.7
> says
>
> If SOURCE= appears, source-expr shall be conformable (2.4.5) with
> allocation.

Note added: When I turn on bounds checking in nagfor, I get a runtime
error. This is what I expected. I don't think this use of SOURCE can
possibly be conforming ...

Wolfgang Kilian

未読、
2011/02/01 5:08:242011/02/01
To:
On 02/01/2011 10:36 AM, Tobias Burnus wrote:
> On 02/01/2011 09:21 AM, Wolfgang Kilian wrote:
>>>> Sounds to me like what you want is the MOLD= that got added in f2008.
>
> You could use a defined assignment, defined for every type extension
> which adds a new component.
>
> Otherwise, your defined assignment should work, though you could
> consider to use CLASS instead of TYPE for the RHS dummy argument "b".

That was my first attempt, but it didn't work (NAG didn't accept it),
once I wrote specifics for both base_type and extended_type. I guess
because the specific procedures for the generic assignment can't be
distinguished unambiguously.

新着メール 0 件