# Select kind of assumed rank array

**URL:** <https://fortran-lang.discourse.group/t/select-kind-of-assumed-rank-array/4121>\
**Category:** Uncategorized\
**Created:** [August 4, 2022, 4:52pm UTC](https://fortran-lang.discourse.group/t/select-kind-of-assumed-rank-array/4121 "2022-08-04T16:52:19Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![pcosta](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pcosta/32/5504_2.png) [@pcosta](https://fortran-lang.discourse.group/u/pcosta)\
**Post date:** [August 4, 2022, 4:52pm UTC](https://fortran-lang.discourse.group/t/select-kind-of-assumed-rank-array/4121/1 "2022-08-04T16:52:19Z")

</div>

Dear all,

I was wondering if the following program is conforming to the latest standard? It compiles with `nvfortran` and produces the results I aimed at getting, but not with `ifort` or `gfortran`.

Thank you!

```fortran
program test
  implicit none
  integer, parameter :: n = 150
  real, allocatable :: p1d(:),p(:,:,:)
  integer :: i,j,k
  allocate(p1d(n))
  allocate(p(n,n,n))
  call print_size(p)
  call print_size(p1d)
contains 
  subroutine print_size(var)
  class(*), intent(in) :: var(..)
  select type(var)
  type is (real)
    print*, 'Size is:', size(var)
  end select
  end subroutine
end

```

---

<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:** [August 4, 2022, 5:24pm UTC](https://fortran-lang.discourse.group/t/select-kind-of-assumed-rank-array/4121/2 "2022-08-04T17:24:52Z")

</div>

> [@pcosta](#):
>
> if the following program is conforming to the latest standard?

No, the current standard does not allow a reference to an assumed-rank dummy object in a `select type` construct.

The practical workaround to the approach, which I do **not** recommend, is a cascaded `select rank` with enclosed `select type` in order to achieve what is presumably the use of unlimited polymorphism as a substitute for generics.

For the case shown in the original post, `select rank` will suffice where in each `rank` statement, the `associate-name` is of that rank i.e., it’s **not** assumed rank. But again it is rather silly; generic interfaces generally work better with current processors and can provide more readable code albeit with all the code duplication.

You can try this:

```fortran
   integer :: x, y(1), z(2,3)
   call sub( x )
   call sub( y )
   call sub( z )
contains
   subroutine sub( a )
      class(*), intent(in) :: a(..)
      select rank ( v => a )
         rank ( 0 )
            print *, "arg is rank-0"
         rank ( 1 )
            print *, "arg is rank-1 of size ", size(v)
         rank ( 2 )
            print *, "arg is rank-2 of size ", size(v)
         rank default
            print *, "arg is of rank other than 0 thru' 2"
      end select
   end subroutine
end 

```

---

<div class="post-metadata">

**Author:** ![pcosta](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pcosta/32/5504_2.png) [@pcosta](https://fortran-lang.discourse.group/u/pcosta)\
**Post date:** [August 4, 2022, 6:31pm UTC](https://fortran-lang.discourse.group/t/select-kind-of-assumed-rank-array/4121/3 "2022-08-04T18:31:34Z")

</div>

Thank you!

> [@FortranFan](#):
>
> The practical workaround to the approach, which I do **not** recommend, is a cascaded `select rank` with enclosed `select type` in order to achieve what is presumably the use of unlimited polymorphism as a substitute for generics.

Funny… The non-conforming example compiled with `nvfortran` but not with `gfortran` and `ifort`. This conforming workaround one compiles with `gfortran` and `ifort` but not with `nvfortran` (because it does not support yet select rank).

The conforming example:

```fortran
 program test
   implicit none
   integer, parameter :: n = 150
   real, allocatable :: p1d(:),p(:,:,:)
   integer :: i,j,k
   allocate(p1d(n))
   allocate(p(n,n,n))
   call print_size(p)
   call print_size(p1d)
 contains
   subroutine print_size(var)
   class(*), intent(in) :: var(..)
   select rank(var)
   rank (1)
     select type(var)
     type is (real)
       print*,'Size is:',size(var)
     end select
   rank (2)
     select type(var)
     type is (real)
       print*,'Size is:',size(var)
     end select
   rank (3)
     select type(var)
     type is (real)
       print*,'Size is:',size(var)
     end select
   end select
   end subroutine
 end

```

---

<div class="post-metadata">

**Author:** ![septc](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/septc/32/77_2.png) [@septc](https://fortran-lang.discourse.group/u/septc)\
**Post date:** [August 8, 2022, 8:02pm UTC](https://fortran-lang.discourse.group/t/select-kind-of-assumed-rank-array/4121/4 "2022-08-08T20:02:48Z")

</div>

I’ve never used assumed-rank arrays up to now, but isn’t it possible (in principle) to get the number of the total array elements via `size(arr)` because it is independent of the rank? Or, is the restriction related to the case where the dummy argument is possibly a scalar (i.e. not an array)?

---

<div class="post-metadata">

**Author:** ![pcosta](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pcosta/32/5504_2.png) [@pcosta](https://fortran-lang.discourse.group/u/pcosta)\
**Post date:** [August 8, 2022, 8:33pm UTC](https://fortran-lang.discourse.group/t/select-kind-of-assumed-rank-array/4121/5 "2022-08-08T20:33:45Z")

</div>

Thanks!

I think my example is not very illustrative. In addition to getting the array size, I wanted to do some other operations which depend on the type (actually, on the kind), of the argument.

---

<div class="post-metadata">

**Author:** ![septc](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/septc/32/77_2.png) [@septc](https://fortran-lang.discourse.group/u/septc)\
**Post date:** [August 8, 2022, 9:06pm UTC](https://fortran-lang.discourse.group/t/select-kind-of-assumed-rank-array/4121/6 "2022-08-08T21:06:03Z")

</div>

Ah… sorry, I was not writing about the “code design” (of your actual code), but simply interested in why the Fortran standard forbids us to use `size(arr)` on an assumed-rank dummy array (when there is no `dim` keyword).

I imagined that the assumed-rank array is implemented in a way similar to the usual array (with internal metadata for ranks, bounds, strides, etc), so I thought `size(arr)` can be used because the total element size should be independent of “how the user accesses (views) the actual data”.

Anyway, just a minor question for someone interested… 🏖

---

<div class="post-metadata">

**Author:** ![pcosta](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pcosta/32/5504_2.png) [@pcosta](https://fortran-lang.discourse.group/u/pcosta)\
**Post date:** [August 8, 2022, 9:15pm UTC](https://fortran-lang.discourse.group/t/select-kind-of-assumed-rank-array/4121/7 "2022-08-08T21:15:03Z")

</div>

Ah! Sorry, I misread your comment. I have the same curiosity… I guess there has to be some strong reason for this not to be allowed, as it would seem like a really neat thing to be able to write…

---

<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:** [August 8, 2022, 9:43pm UTC](https://fortran-lang.discourse.group/t/select-kind-of-assumed-rank-array/4121/8 "2022-08-08T21:43:30Z")

</div>

> [@septc](#):
>
> … simply interested in why the Fortran standard forbids us to use `size(arr)` on an assumed-rank dummy array (when there is no `dim` keyword) …

@septc, there is **no** prohibition in the standard against the use of an `assumed-rank` object with the `SIZE` intrinsic. In fact, the `SIZE` intrinsic description in the standard starting with Fortran 2018 states that the first parameter “shall be assumed-rank or an array.”

Note the prohibition that comes into play with OP’s code in the original post is with the use in a `SELECT TYPE` construct where OP was intending to include other instructions.

---

<div class="post-metadata">

**Author:** ![pcosta](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pcosta/32/5504_2.png) [@pcosta](https://fortran-lang.discourse.group/u/pcosta)\
**Post date:** [August 8, 2022, 9:55pm UTC](https://fortran-lang.discourse.group/t/select-kind-of-assumed-rank-array/4121/9 "2022-08-08T21:55:35Z")

</div>

Thank you. Exactly… Do you know the reason why this is not allowed?

---

<div class="post-metadata">

**Author:** ![septc](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/septc/32/77_2.png) [@septc](https://fortran-lang.discourse.group/u/septc)\
**Post date:** [August 9, 2022, 10:13pm UTC](https://fortran-lang.discourse.group/t/select-kind-of-assumed-rank-array/4121/10 "2022-08-09T22:13:58Z")

</div>

> [@FortranFan](#):
>
> Note the prohibition that comes into play with OP’s code in the original post is with the use in a `SELECT TYPE` construct where OP was intending to include other instructions.

Thanks! I see… I completely misunderstood that the error comes from the use of `size` 😵‍💫

Now I’ve tried this code, which works as I expected (with Gfortran-10).

```auto
program test
    implicit none
    real :: x
    real, allocatable :: A(:,:), B(:,:,:)
    allocate( A(2,3), B(4,5,6) )
    call print_size( A )
    call print_size( B )
    call print_size( x )
contains 

subroutine print_size( arr )
    class(*), intent(in) :: arr(..)
    integer :: d
    print *, "rank =", rank(arr), &
             "size =", size(arr), &
             "shape =", shape(arr)
    print *, all( shape(arr) == [( size(arr,d), d = 1, rank(arr) )] )
end subroutine
end program

$ gfortran-10 test.f90 && ./a.out
 rank = 2 size = 6 shape = 2 3
 T
 rank = 3 size = 120 shape = 4 5 6
 T
 rank = 0 size = 1 shape =
 T

```
