Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
This community is designed for sharing of public information. Please do not share Intel or third-party confidential information here.
27159 Discussions

Problem with reshape in bound procedure

jkrzz
Beginner
630 Views

Compiler: Compiling with Intel® Fortran Compiler Classic 2021.2.0 [Intel(R) 64], Visual Studio

I have following method (bound procedure) which assigns a constant array to a matrix:

subroutine copy_matrix2(me,a)
  implicit none type(matrix(*,*)), intent(inout) :: me
  real, dimension(:), intent(in) :: a
  integer(int64) :: i
  integer, dimension(1:2) ::s
  if(me%r*me%c /= size(a)) then
   stop 'dimension mismatch'
 end if
! s=shape(me%x)
me%x=transpose(reshape(a,shape(me%x)))
end subroutine copy_matrix2

The assignment works correctly if I use the variable s, but it fails to work correctly if I use  directy shape(me%x) in the reshape function. It takes only the first two element of a and fills the matrix.
If I use this same statement, me%x=transpose(reshape(a,shape(me%x))),outside the method it works correctly.


The matrix type is defined as follows:
! matrix
type matrix (r,c,k)
integer(int64),len::r,c=r
integer,kind:: k=real32
real(k), dimension(1:r,1:c)::x

contains
private

generic,public :: assignment(=) => copy_matrix1 ,copy_matrix2
procedure :: copy_matrix1
procedure :: copy_matrix2
end type matrix

0 Kudos
1 Solution
FortranFan
Honored Contributor II
536 Views
@jkrzz wrote:
I just wanted to create a matrix class, as you would do in C++.  Declarations are shorter and operator overloading and methods can be bound to the type. I just was surprised about the unexpected behavior of the reshape function occurring in a procedure bound method. So I want to know what is causing this weird behavior. 

@jkrzz ,

It's good to see you are trying out the parameterized derived type (PDT) facility introduced starting Fortran 2003 back in 2004.  A few quick comments:

  1. Please do post a reproducer of your code either at Intel OSC or here, as suggested by @Barbara_P_Intel .
  2. If you intend to spend some time with Fortran, please take a look at https://fortran-lang.org/ and also the Discourse there for all matters generally related to Fortran: https://fortran-lang.discourse.group/.  See also some recent discussions involving matrix computations and a PDT example toward a simple-minded exponential operation in this thread.
  3.  Toward your copy_matrix2 assignment, another workaround you can consider in case your source "data" in 'a' is contiguous is to make use of rank transformation using a local pointer:
subroutine copy_matrix2(me,a)
  type(matrix(r=*,c=*,k=..)), intent(inout) :: me
  real, contiguous, intent(in), target :: a(:)
  integer(int64) :: i
  real, contiguous, pointer :: x(:,:)
  if (me%r*me%c /= size(a)) then
     stop 'dimension mismatch'
  end if
  x(1:me%r,1:me%c) => a
  me%x = x
end subroutine copy_matrix2

 

View solution in original post

10 Replies
jimdempseyatthecove
Black Belt
614 Views

Why are you using a user defined type "matrix" that abstracts an array descriptor when Fortran's arrays are implemented using an array descriptor? IOW you can use SIZE(me,DIM=1), SIZE(me,DIM=2), LBOUND and UBOUND to obtain the particulars of the array.

Jim Dempsey

jkrzz
Beginner
608 Views

I just wanted to create a matrix class, as you would do in C++.  Declarations are shorter and operator overloading and methods can be bound to the type. I just was surprised about the unexpected behavior of the reshape function occurring in a procedure bound method. So I want to know what is causing this weird behavior. 

FortranFan
Honored Contributor II
537 Views
@jkrzz wrote:
I just wanted to create a matrix class, as you would do in C++.  Declarations are shorter and operator overloading and methods can be bound to the type. I just was surprised about the unexpected behavior of the reshape function occurring in a procedure bound method. So I want to know what is causing this weird behavior. 

@jkrzz ,

It's good to see you are trying out the parameterized derived type (PDT) facility introduced starting Fortran 2003 back in 2004.  A few quick comments:

  1. Please do post a reproducer of your code either at Intel OSC or here, as suggested by @Barbara_P_Intel .
  2. If you intend to spend some time with Fortran, please take a look at https://fortran-lang.org/ and also the Discourse there for all matters generally related to Fortran: https://fortran-lang.discourse.group/.  See also some recent discussions involving matrix computations and a PDT example toward a simple-minded exponential operation in this thread.
  3.  Toward your copy_matrix2 assignment, another workaround you can consider in case your source "data" in 'a' is contiguous is to make use of rank transformation using a local pointer:
subroutine copy_matrix2(me,a)
  type(matrix(r=*,c=*,k=..)), intent(inout) :: me
  real, contiguous, intent(in), target :: a(:)
  integer(int64) :: i
  real, contiguous, pointer :: x(:,:)
  if (me%r*me%c /= size(a)) then
     stop 'dimension mismatch'
  end if
  x(1:me%r,1:me%c) => a
  me%x = x
end subroutine copy_matrix2

 

jkrzz
Beginner
518 Views

Thanks for your comments. I didn't know that an assignment of a pointer to an array results in a copy. Is a much better solution than 3 function calls. In the argument declaration for matrix I leave k out.

jkrzz
Beginner
603 Views

I found that when I put shape(me%x) between () in the reshape function, reshape(a,(shape(me%x))), it works correctly. This seems that the compiler has problems with interpreting the syntax without (), but only in a procedure bound function. 

Barbara_P_Intel
Moderator
546 Views

Do you have a complete reproducer?  If you have paid support, submit the reproducer as a bug.  Otherwise, post that complete reproducer here.

 

jkrzz
Beginner
516 Views

I attach two files main.f90 and lina2.f90. I main I assign 1,2,3,4 to a square matrix and the result printed is 1,2\n1,2. Putting shape between () in copy_matrix2 gives the correct result. In the answer of @FortranFan I found a better solution for assignment. But I am still curious to learn why shape behaves as it did in the bound procedure.

Barbara_P_Intel
Moderator
464 Views

Thank you for the simple reproducer!  I filed a bug report, CMPLRIL0-34043.  I'll let you know its progress to a fix.

 

IanH
Black Belt
500 Views

Probably separate to the observed issue, note that:

  • Type bound procedures of extensible types are required to have the passed argument be polymorphic.  This requirement is a constraint in the standard - the compiler should have issued a diagnostic.
  • The expression that specifies the default value for a type parameter of a type definition (the optional expression after the equals in a type-param-decl) is required to be a constant expression - again this is by constraint and a diagnostic should have been issued.
Devorah_H_Intel
Moderator
26 Views

This was fixed and the fix will be available in the next release of the Intel Fortran Compiler 2021.7 

Reply