This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
Re: Problems with SPREAD and/or scalarization.
- From: Paul Thomas <paulthomas2 at wanadoo dot fr>
- To: 20051002003643 dot GA35738 at troutmask dot apl dot washington dot edu,Thomas Koenig <Thomas dot Koenig at online dot de>
- Cc: fortran at gcc dot gnu dot org
- Date: Sun, 16 Oct 2005 12:40:44 +0200
- Subject: Re: Problems with SPREAD and/or scalarization.
- References: <20051002175200.GA5667@meiner.onlinehome.de>
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