# How to concisely declare a function result as a multi-dimensional automatic array?

**URL:** <https://fortran-lang.discourse.group/t/how-to-concisely-declare-a-function-result-as-a-multi-dimensional-automatic-array/4476>\
**Category:** Help\
**Created:** [October 7, 2022, 2:50pm UTC](https://fortran-lang.discourse.group/t/how-to-concisely-declare-a-function-result-as-a-multi-dimensional-automatic-array/4476 "2022-10-07T14:50:57Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![milancurcic](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/milancurcic/32/2_2.png) [@milancurcic](https://fortran-lang.discourse.group/u/milancurcic)\
**Post date:** [October 7, 2022, 2:50pm UTC](https://fortran-lang.discourse.group/t/how-to-concisely-declare-a-function-result-as-a-multi-dimensional-automatic-array/4476/1 "2022-10-07T14:50:57Z")

</div>

I want to declare the function result to have the same shape as the input multi-dimensional array dummy argument. For rank 2, I do this:

```fortran
function f(x)
  real, intent(in) :: x(:,:)
  real :: f(size(x,1),size(x,2)) ! <- more concise? how?

```

For higher ranks, it gets worse, as you can imagine.

Is this the best I can do?

`elemental` is not an option as I want this function to be pointed to by a procedure pointer.

---

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [October 7, 2022, 3:16pm UTC](https://fortran-lang.discourse.group/t/how-to-concisely-declare-a-function-result-as-a-multi-dimensional-automatic-array/4476/2 "2022-10-07T15:16:57Z")

</div>

> [@milancurcic](#):
>
> Is this the best I can do?

Effectively yes, with the current standard - depending on the needs, the other intrinsics `LBOUND`, `UBOUND` may come in handy.

If I recall correctly though, with the next standard revision Fortran 2023 (? 202X?), the following likely becomes an option:

```fortran
function f(x)
  real, intent(in) :: x(:,:)
  real :: f(shape(x))

```

---

<div class="post-metadata">

**Author:** ![HugoMVale](https://avatars.discourse-cdn.com/v4/letter/h/e19adc/32.png) [@HugoMVale](https://fortran-lang.discourse.group/u/HugoMVale)\
**Post date:** [October 7, 2022, 5:26pm UTC](https://fortran-lang.discourse.group/t/how-to-concisely-declare-a-function-result-as-a-multi-dimensional-automatic-array/4476/3 "2022-10-07T17:26:24Z")

</div>

I asked myself a similar question a while ago. Ultimately, I decided to change my code to have a _flattened_ array (i.e., a vector) as input and output. Of course, this approach has drawbacks, and it is not always applicable. Optionally, we can also internally reshape (and finally flatten again), to facilitate some operations.  
Of course, this is not a solution to OP’s question, rather a workaround.

---

<div class="post-metadata">

**Author:** ![certik](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/certik/32/4_2.png) [@certik](https://fortran-lang.discourse.group/u/certik)\
**Post date:** [October 7, 2022, 7:16pm UTC](https://fortran-lang.discourse.group/t/how-to-concisely-declare-a-function-result-as-a-multi-dimensional-automatic-array/4476/4 "2022-10-07T19:16:26Z")

</div>

> [@milancurcic](#):
>
> ```auto
> function f(x)
> real, intent(in) :: x(:,:)
> real :: f(size(x,1),size(x,2)) ! <- more concise? how?
> 
> ```

Fortran needs to be extended for this. I was thinking something like this:

```auto
function f(x)
  dim :: n, m
  real, intent(in) :: x(n,m)
  real :: f(n,m)

```

Which has many advantages, consider a matmul, currently:

```auto
function matmul(A, B) result(C)
  real, intent(in) :: A(:,:), B(:,:)
  real :: C(size(A,1),size(B,2))

```

Note that you can’t use `shape` easily for this and note that dimensions are not tied, so the compiler cannot check that A and B are conforming. Now after the extension:

```auto
function matmul(A, B) result(C)
  dim :: m, n, k
  real, intent(in) :: A(m,n), B(n,k)
  real :: C(m, k)

```

The `dim` behaves just like `A(:)`, in other words, the array still gets passed in with a descriptor. But you can now tie the different dimensions together and the compiler can check (at compile time and/or runtime) that the arrays A, and B are conforming with their dimensions, so you do not need to do this check by hand inside the subroutine. And it is consistent if you want to use the old fashioned arrays:

```auto
function matmul(m, n, k, A, B) result(C)
  integer, intent(in) :: m, n, k
  real, intent(in) :: A(m,n), B(n,k)
  real :: C(m, k)

```

Note 1: instead of `dim :: m, n, k`, we could use `integer, infer :: m, n, k`, to be consistent with `integer, intent(in) :: m, n, k`.

Note 2: `real, intent(in) :: A(:,:), B(:,:)` would be equivalent to `integer, infer :: m, n, k, l; real, intent(in) :: A(m, n), B(k,l)`

---

<div class="post-metadata">

**Author:** ![egio](https://avatars.discourse-cdn.com/v4/letter/e/dbc845/32.png) [@egio](https://fortran-lang.discourse.group/u/egio)\
**Post date:** [October 8, 2022, 9:55am UTC](https://fortran-lang.discourse.group/t/how-to-concisely-declare-a-function-result-as-a-multi-dimensional-automatic-array/4476/5 "2022-10-08T09:55:48Z")

</div>

A slight different syntax could be:

```auto
function matmul(A, B) result(C)
  dim :: m, n, k
  real, intent(in) :: A(m=>:, n=>:), B(n=>:,k=>:)
  real :: C(m, k)

```

That is stressing the fact that A and B are assumed shape arrays. Even though is more verbose.  
The first `dim` declaration could be even unnecessary.

There is a problem in situation like this one:

```auto
subroutine strange(a, b, c)
real :: a(n=>:), b(n=>:), c(n=>:) 

```

As the values can be inconsistent at run time.  
One possibility is to introduce a new intrinsic function, let call it `consistent` that has as argument this `dim` values and return `.TRUE.` or `.FALSE.` if they are consistent or not.  
Then then the programmer can `error stop` or do whatever he/she likes. With the assumption that, if one of the `dim` variable is inconsistent it cannot be used anywhere (almost), but the processor is not asked to report or detect it.  
Basically the following:

```auto
subroutine strange(a, b, c)
real :: a(n=>:), b(n=>:), c(n=>:)

if (.not. consistent(n)) error stop 

```

will be equivalent

```auto
subroutine strange(a, b, c)
real :: a(:), b(:), c(:)

associate(n=> size(a))
if (.not. (n==size(b) .and. n==size(c)) error stop 

end associate

```

If you like it it could be transformed in a proposal for Fortran 202z.

---

<div class="post-metadata">

**Author:** ![certik](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/certik/32/4_2.png) [@certik](https://fortran-lang.discourse.group/u/certik)\
**Post date:** [October 8, 2022, 2:51pm UTC](https://fortran-lang.discourse.group/t/how-to-concisely-declare-a-function-result-as-a-multi-dimensional-automatic-array/4476/6 "2022-10-08T14:51:32Z")

</div>

@egio excellent ideas! Thank you. I really feel there is something here. Btw, once we have something that more people (than just me 🙂 ) like, this would be easy to implement in LFortran as an optional extension (for now) and we can start using it and see if we actually like it. So that the actual proposal to the standard committee will be very robust.

Couple questions.

Does it make sense to require to define “n” to be an integer?

```auto
subroutine strange(a, b, c)
integer, dim :: n ! Possibly without the "dim"
real :: a(n=>:), b(n=>:), c(n=>:) 

```

Regarding:

```auto
subroutine strange(a, b, c)
real :: a(n=>:), b(n=>:), c(n=>:) 

```

That seems analogous to:

```auto
subroutine strange(n, a, b, c)
integer :: n
real :: a(n), b(n), c(n) 

```

The only difference is that in the first case “n” is inferred from “a”, while in the second case it is passed in.

In both cases, the compiler should check this using bounds checks at runtime automatically in Debug mode. In Release mode no checks will be done for performance.

So there is no issue from my point of view.

---

<div class="post-metadata">

**Author:** ![egio](https://avatars.discourse-cdn.com/v4/letter/e/dbc845/32.png) [@egio](https://fortran-lang.discourse.group/u/egio)\
**Post date:** [October 8, 2022, 3:11pm UTC](https://fortran-lang.discourse.group/t/how-to-concisely-declare-a-function-result-as-a-multi-dimensional-automatic-array/4476/7 "2022-10-08T15:11:05Z")

</div>

I don’t know.  
Let’s say that if not declared it will be of the kind of a standard integer, while if declared it could be of a different kind, that may be useful in some situation.

I will keep the `dim`.

Your suggestion about including it in LFortran is wonderful!  
🙂

---

<div class="post-metadata">

**Author:** ![RonShepard](https://avatars.discourse-cdn.com/v4/letter/r/a3d4f5/32.png) [@RonShepard](https://fortran-lang.discourse.group/u/RonShepard)\
**Post date:** [October 8, 2022, 3:42pm UTC](https://fortran-lang.discourse.group/t/how-to-concisely-declare-a-function-result-as-a-multi-dimensional-automatic-array/4476/8 "2022-10-08T15:42:09Z")

</div>

> [@certik](#):
>
> That seems analogous to:
> 
> ```auto
> subroutine strange(n, a, b, c)
> integer :: n
> real :: a(n), b(n), c(n) 
> 
> ```
> 
> The only difference is that in the first case “n” is inferred from “a”, while in the second case it is passed in.

With assumed shape declarations (:), the dummy argument need not be contiguous. With explicit shape arguments, the dummy argument must be contiguous. That means in some cases, copy-in/copy-out is required by the compiler. That semantic difference has performance consequences.

As for this proposal in general, as described above it is basically just syntactic sugar that achieves exactly the same thing as the currentl syntax using size(). If you want to make the proposal appeal to a wider range of programmers, you need to add some useful new capabilities. The ability to ensure/assert consistency of dimensions over several arrays, or even within a single array (e.g. square matrices), might do this. That would be most useful if it could be done at compile time. However, this assertion most likely could be done only at run time for many cases, e.g. involving separate compilation of caller and callee, in which case we are back to just syntactic sugar for what the programmer can already do in a straightforward way.

---

<div class="post-metadata">

**Author:** ![egio](https://avatars.discourse-cdn.com/v4/letter/e/dbc845/32.png) [@egio](https://fortran-lang.discourse.group/u/egio)\
**Post date:** [October 8, 2022, 4:50pm UTC](https://fortran-lang.discourse.group/t/how-to-concisely-declare-a-function-result-as-a-multi-dimensional-automatic-array/4476/9 "2022-10-08T16:50:30Z")

</div>

Most of the time when I use assumed shape array I add a comment after the array with the name of the dimension just to remind me which are:

```auto
subroutine alpha( a, b)
  real :: a(:,:) ! m, n
  real :: b(:,:,:) ! k, n, m
  integer :: m,n,k

  m = size(a,1)
  n = size(a,2)
  k = size(b,1)
  if (m/= size(b,3) .or. n /= size(b, 2) ) error stop

```

Well I think it is definitely error prone compared to my proposal

```auto
subroutine alpha( a, b)
  real :: a(m=>:,n=>:) 
  real :: b(k=>:,n=>:,m=>:)

  if (.not. consistent(m,n) ) error stop

```

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [October 8, 2022, 7:51pm UTC](https://fortran-lang.discourse.group/t/how-to-concisely-declare-a-function-result-as-a-multi-dimensional-automatic-array/4476/10 "2022-10-08T19:51:18Z")

</div>

You could make the function result `allocatable` and then write

`allocate(f,mold=x)`

---

<div class="post-metadata">

**Author:** ![nncarlson](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/nncarlson/32/1175_2.png) [@nncarlson](https://fortran-lang.discourse.group/u/nncarlson)\
**Post date:** [October 8, 2022, 8:06pm UTC](https://fortran-lang.discourse.group/t/how-to-concisely-declare-a-function-result-as-a-multi-dimensional-automatic-array/4476/11 "2022-10-08T20:06:12Z")

</div>

> [@Beliavsky](#):
>
> You could make the function result `allocatable` and then write
> 
> `allocate(f,mold=x)`

I was thinking the same thing. Is there any practical, observable difference between an automatic and allocatable function result, other than perhaps where it is allocated (stack or heap)?

---

<div class="post-metadata">

**Author:** ![certik](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/certik/32/4_2.png) [@certik](https://fortran-lang.discourse.group/u/certik)\
**Post date:** [October 8, 2022, 10:41pm UTC](https://fortran-lang.discourse.group/t/how-to-concisely-declare-a-function-result-as-a-multi-dimensional-automatic-array/4476/12 "2022-10-08T22:41:02Z")

</div>

> [@RonShepard](#):
>
> As for this proposal in general, as described above it is basically just syntactic sugar that achieves exactly the same thing as the currentl syntax using size().

Just to make it clear, the proposal above is not just syntactic sugar, the added value is that the compiler will check (at runtime) that the array sizes are compatible, which is not possible to do today, e.g. it is not possible today for the compiler to check automatically for you at runtime that the following arrays A and B are compatible with the dimension “n”:

```auto
function matmul(A, B) result(C)
  dim :: m, n, k
  real, intent(in) :: A(m,n), B(n,k)
  real :: C(m, k)

```

The other added value is that the code is self-documenting in terms of which dimensions must be compatible.

Regarding non-contiguous arrays, indeed, it would allow it.

(The code is also more readable and concise, which is just “syntactic sugar”, but that’s a good thing in my opinion.)

---

<div class="post-metadata">

**Author:** ![adenchfi](https://avatars.discourse-cdn.com/v4/letter/a/858c86/32.png) [@adenchfi](https://fortran-lang.discourse.group/u/adenchfi)\
**Post date:** [October 13, 2022, 11:40pm UTC](https://fortran-lang.discourse.group/t/how-to-concisely-declare-a-function-result-as-a-multi-dimensional-automatic-array/4476/13 "2022-10-13T23:40:34Z")

</div>

Ah, I certainly hope so! That would be so convenient.
