Prev: Invocation of overridden procedure on an abstract parent component
Next: 64-bit byteswapping and legacy programs
From: card on 26 Feb 2010 21:52 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 26 Feb 2010 22:05 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 26 Feb 2010 22:09 "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 26 Feb 2010 23:40 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 26 Feb 2010 23:57
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 |