Problems with SPREAD and/or scalarization.

Paul Thomas paulthomas2@wanadoo.fr
Sun Oct 16 10:54:00 GMT 2005


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



More information about the Fortran mailing list