j3-fortran / fortran_proposals

Proposals for the Fortran Standard Committee
175 stars 14 forks source link

Allow subarray indexing as input to pure and elemental functions #282

Open perazz opened 1 year ago

perazz commented 1 year ago

It would be useful if elemental pure functions could be used with subarray indexing inputs. I think that could have two major benefits:

Imagine something like:

! This is a dumb integer power
elemental function int_power(x,i) result(x_pow_i)
   real, intent(in) :: x
   integer, intent(in) :: i 
   real :: x2,x_pow_i
   select case (i)
      case (0); x_pow_i = 0.0
      case (1); x_pow_i = x
      case (2); x_pow_i = x*x
      case (3); x_pow_i = x*x*x
      case (4); x2 = x*x; x_pow_i = x2*x2
      case default;  x_pow_i = x**i
   end select 
end function int_power

Now, if you want several powers you need to do

integer, allocatable :: even(:)
real, allocatable :: powers(:)

even = [0,2,4,6,8]
powers = int_power(2.0,even)

! or
powers = int_power(2.0,[(j,j=0,8,2)])

While with subarray-index-enabled functions, it would be simply

powers = int_power(2.0,0:8:2)

Simple, optimizeable, readable, concise. I would use that a lot.

The simplest usage would be to return an array with those same indices

elemental integer function self(i) result(j)
   integer, intent(in) :: i
   j = i
end function self

which could be used like:

integer, allocatable :: i(:)
i = self(-53:103:2)
print *, i ! -53 -51 -49 -47 .....

I guess the same restrictions as to working with elemental functions would apply, that probably wouldn’t be hard to implement in current compilers. Thoughts?

certik commented 1 year ago

Here is a corresponding fortran-lang Discourse thread that first introduced this issue: https://fortran-lang.discourse.group/t/allow-subarray-indexing-as-input-to-pure-and-elemental-functions/4048

klausler commented 1 year ago

Is this just new syntax for an implied DO loop in an array constructor?

perazz commented 1 year ago

Well, most of the syntax in any compiled languages is literally wrappers over pointers, gotos, and loops. So in that sense yes, I agree it's "just new syntax". IMHO it would be a step forward for the language UX. But maybe not. As a compiler developer, it would be great to have your opinion as to whether any better/further optimization would be possible (for example, whenever those array slices are passed by value instead of by reference).

I also think that would pave the way for modern loop constructors (such as partially covered in do concurrent):

! Use array slicing syntax
do I = -32:18:4
end do

! Use array
do I = [-3,425,9999]
end do

! Use array
do I = my_array
end do