This is the mail archive of the fortran@gcc.gnu.org mailing list for the GNU Fortran project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Problems with SPREAD and/or scalarization.


Steve and Thomas,


No, I didn't see this before. Will you open a PR?


Thomas

I did a bit of investigation on this:

program bug
implicit none
integer, parameter :: nx=4,ny=4
real, dimension(nx,ny) :: f, g
real, dimension(nx) :: x
integer :: i

! these work
! f = spread(cshift((/ (2*i, i = 1, nx) /), nx/2), 2, ny)
! f = spread((/ (i, i = 1, nx) /) * 2, 2, ny)

! but not (note two calls to gfc_resolve_cshift)
! f = spread(my_cshift((/ (i, i = 1, nx) /), nx/2) * 2.0, 2, ny)
! nor (which produces three calls to gfc_resolve_cshift)
! f = spread(cshift((/ (2*i, i = 1, nx) /), nx/2) * 2, 2, ny)

! equally, this produces the same error
! f = spread(spread(2, 1, 4) * 2, 2, ny)
! as does this
! f = spread(merge(1, 0, (/ (i, i = 1, nx) /) > 2) * 2, 2, ny)

! This produces a revealing error
! x = cshift(cshift((/ (2*i, i = 1, nx) /), nx/2) * 2, nx/2)
! Error: 'array' argument of 'cshift' intrinsic at (1) must be an array


! This compiles but produces nonsense x = spread(cshift((/ (2.0*i, i = 1, nx) /), nx/2) * 2.0, 1, ny)

! print *, x
contains
function my_cshift (source, shift) result (ret)
 real, dimension(nx) :: source, ret
 integer shift
 ret = cshift (source, shift)
end function my_cshift
end program bug

Part ofthe code for this last is:


.....snip.....


   parm.4.dtype = 281;
   parm.4.dim[0].lbound = 1;
   parm.4.dim[0].ubound = 4;
   parm.4.dim[0].stride = 1;
   parm.4.data = (void *) (real4[0:] *) &x[0];
   parm.4.offset = 0;

.....snip.....

   atmp.14.dtype = 281;
   atmp.14.dim[0].stride = 1;
   atmp.14.dim[0].lbound = 0;
   atmp.14.dim[0].ubound = 3;
   atmp.14.data = (void *) &A.15;
   atmp.14.offset = 0;
   {
     int4 S.16;

S.16 = 0;
while (1)
{
if (S.16 > 3) goto L.2; else (void) 0;
(*(real4[0:] *) atmp.14.data)[NON_LVALUE_EXPR <S.16>] = (*(real4[0:] *) atmp.12.data)[NON_LVALUE_EXPR <S.16>] * 2.0e+0;
S.16 = S.16 + 1;
}
L.2:;
}
atmp.14.dim[0].stride = 0;
_gfortran_spread_scalar (&parm.4, &atmp.14, &C.595, &C.596);
}
}


Thus, SPREAD has a vector source but is calling spread_scalar. This choice is made in iresolve.c(gfc_resolve_spread) on the basis of the value of the rank or the expression. Clearly, this is a mistake when the expression is something other than a variable, function or constant. Some expression walking needs to be done....

Paul


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]