From: card on
Hi All,

I ran into an interesting situation that took my surprise. To
explain, I created this contrived example:

module slice

implicit none

type myType
integer :: first
integer :: second
end type myType

interface assignment(=)
module procedure equals
end interface

contains

subroutine equals(this, other)
type (myType), intent(inout) :: this
type (myType), intent(in) :: other

this % first = other % first + 1
this % second = other % second + 1
end subroutine equals

end module slice


program testslice

use slice
implicit none

type (myType), dimension(10) :: t, u
type (myType) :: x, y

integer :: i

y % first = 1
y % second = 2

x = y

print *, 'This is y'
print *, y
print *, 'This is x after assignment to y'
print *, x

do i = 1, 10
t(i) % first = i
t(i) % second = i + 1
enddo

u(1:10) = t(1:10)

print *, 'This is t'
do i = 1, 10
print *, t(i)
enddo

print *, 'This is u after assignment to t using slice'
do i = 1, 10
print *, u(i)
enddo

end program testslice

Compiling and running gives me:

This is y
1 2
This is x after assignment to y
2 3
This is t
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11
This is u after assignment to t using slice
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11

What caught me by surprise was the assignment of the array u to the
array t via the slicing did not invoke my overrided assignment
subroutine as was done with assigning x to y. In all my readings, I
never ran across that this would be the case. Is this the correct
behaviour when assigning via an array slice of derived types with the
overrided assignment? Many thanks in advance.

-David
From: Richard Maine on
card <david.car7(a)gmail.com> wrote:
....
> interface assignment(=)
> module procedure equals
> end interface
>
> contains
>
> subroutine equals(this, other)
[rest elided]


> What caught me by surprise was the assignment of the array u to the
> array t via the slicing did not invoke my overrided assignment
> subroutine as was done with assigning x to y. In all my readings, I
> never ran across that this would be the case. Is this the correct
> behaviour when assigning via an array slice of derived types with the
> overrided assignment? Many thanks in advance.

This has nothing to do with slices in particular. The same thing would
happen with whole arrays.

The problem is that your subroutine is defined only to operate on
scalars. You have thus overridden the defined assignment only for
scalars.

If you want your defined assignment to apply to each element of an array
assignment, then you need to declare it as elemental. That's exactly
what the elemental attribute means - apply something to each element of
arrays. If you don't declare it that way, it won't work that way. Do
note that elementals come with a *LOT* of restrictions. Your example
meets them, but I can't say about the real code that I don't see.

Alternatively, you can define assignment for each specific rank. Just
declare the arguments to the subroutine to have the appropriate rank.
That does mean you need a separate subroutine for each rank that you
want to work with.

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
From: James Van Buskirk on
"card" <david.car7(a)gmail.com> wrote in message
news:e21a48fa-29b9-44b9-90b4-d9812e51b297(a)o3g2000yqb.googlegroups.com...

> What caught me by surprise was the assignment of the array u to the
> array t via the slicing did not invoke my overrided assignment
> subroutine as was done with assigning x to y. In all my readings, I
> never ran across that this would be the case. Is this the correct
> behaviour when assigning via an array slice of derived types with the
> overrided assignment? Many thanks in advance.

No surprise. Think about how defined assignment maps into a
subroutine call. Your subroutine's dummy arguments are scalar so
it can't be invoked with array actual arguments as you seem to be
hoping for.

Declare subroutine equals to be elemental and see what happens.
For bonus points, what does the standard say should happen if
you do so and then try the assignment:

u([(i,i=1,10)]) = t(1:10)

Since an array section with a vector subscript is not definable,
invoking subroutine equals is nonconforming. Does the standard
say somehow that the compiler should be able to figure that out
and compile intrinsic assignment, or is this still invalid code
where the compiler can refuse to compile, compile intrinsic
assignment, or go ahead and invoke subroutine equals as an
extension?

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


From: card on
On Feb 26, 10:05 pm, nos...(a)see.signature (Richard Maine) wrote:
> card <david.c...(a)gmail.com> wrote:
>
> ...>   interface assignment(=)
> >      module procedure equals
> >   end interface
>
> > contains
>
> >   subroutine equals(this, other)
>
> [rest elided]
>
> > What caught me by surprise was the assignment of the array u to the
> > array t via the slicing did not invoke my overrided assignment
> > subroutine as was done with assigning x to y.  In all my readings, I
> > never ran across that this would be the case.  Is this the correct
> > behaviour when assigning via an array slice of derived types with the
> > overrided assignment?  Many thanks in advance.
>
> This has nothing to do with slices in particular. The same thing would
> happen with whole arrays.
>
> The problem is that your subroutine is defined only to operate on
> scalars. You have thus overridden the defined assignment only for
> scalars.
>
> If you want your defined assignment to apply to each element of an array
> assignment, then you need to declare it as elemental. That's exactly
> what the elemental attribute means - apply something to each element of
> arrays. If you don't declare it that way, it won't work that way. Do
> note that elementals come with a *LOT* of restrictions. Your example
> meets them, but I can't say about the real code that I don't see.
>
> Alternatively, you can define assignment for each specific rank. Just
> declare the arguments to the subroutine to have the appropriate rank.
> That does mean you need a separate subroutine for each rank that you
> want to work with.
>
> --
> Richard Maine                    | Good judgment comes from experience;
> email: last name at domain . net | experience comes from bad judgment.
> domain: summertriangle           |  -- Mark Twain

Thanks as always for the detailed explanation. I need to review the
standard in detail as I missed this. I just assumed that even though
the equal subroutine was for a scalar that the slicing assignment
would be equivalent to a loop over each element and an assignment,
thereby invoking the scalar version of the assignment. Many thanks.

-David
From: Richard Maine on
card <david.car7(a)gmail.com> wrote:

> I just assumed that even though
> the equal subroutine was for a scalar that the slicing assignment
> would be equivalent to a loop over each element and an assignment,
> thereby invoking the scalar version of the assignment.

Nope. Assignment is just like everything else that way. If you define
scalar addition, that won't apply elementally to arrays either... unless
you define it to be elemental. That's *EXACTLY* what elemental means.

It would be strangely inconsistent for assignment to be different from
operations on this. I almost said "other operations", except that
assignment isn't an operator in Fortran. But it has a lot in common with
operators, including this.

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