1

I am using a API in Fortran which provides a routine for writing data. Let's say its name is api_write_data. This routine expects an array as argument which can be of dimension 1, 2 or 3.

I want to write a subroutine which works as wrapper for this API routine. But therefore it is necessary for me to write a routine which can handle 1D, 2D or 3D arrays and can pass them correctly to the API routine. How can I do that? Can I do that at all?

My approach was something like this, but it does not work:

subroutine write_data(array)
implicit none
integer, dimension(:,:,:), intent(in):: array

call api_write_data(array)

end subroutine write_data

However when I call this routine with for example an 1D array, I get the known error:

Error: Rank mismatch in argument 'array' at (1) (rank-3 and rank-1)

Is there any way to do that kind of thing in Fortran? For me it is necessary to pass the Array as a 1D, 2D or 3D array to the write_data routine. However, I could pass the array as 1D array to api_write_data.

Do you have any idea how I could do that?

2 Answers 2

1

An alternative to the reshape function might be to have a 1D pointer towards the multi-dimensional array:

p(1:size(c)) => c(:,:,:)

You can pass the pointer as a one-dimensional array without making a copy. In fact, it should be as fast as passing the array itself. Of course, you need some way of telling the subroutine which shape the array has:

module test_mod
contains
  subroutine print_arr( arr, dimX, dimY, dimZ )
    integer,intent(in)  :: arr(:)
    integer,intent(in)  :: dimX, dimY, dimZ

    if ( dimZ == 0 ) then
      if ( dimY == 0 ) then
        ! 1D
        print *, "1D array provided"
        print *, "a(4) =", arr(4)
      else
        ! 2D
        print *, "2D array provided"
        print *, "a(1,2) =", arr((2-1)*dimX+1)
      endif
    else
      ! 3D
      print *, "3D array provided"
      print *, "a(1,2,1) =", arr( ((1-1)*dimY + (2-1))*dimX+1)
    endif
  end subroutine
end module

program test
use test_mod
  integer :: i
  integer, target   :: a(8)
  integer, target   :: b(4,2) 
  integer, target   :: c(2,2,2)
  integer, pointer  :: p(:)

  a = [ (i,i=1,8) ]
  b = reshape( a, [4,2] )
  c = reshape( a, [2,2,2] )

  p(1:size(a)) => a(:)
  call print_arr( p, 8, 0, 0 )

  p(1:size(b)) => b(:,:)
  call print_arr( p, 4, 2, 0 )

  p(1:size(c)) => c(:,:,:)
  call print_arr( p, 2, 2, 2 )
end program

This also works the other way round... You can map a 1D array to a 3D pointer:

integer, pointer  :: p2(:,:,:)
!...
p2(1:4,1:2,1:1) => a
Sign up to request clarification or add additional context in comments.

1 Comment

without the restriction on fortran 90, would there be another possibility? Maybe with new language features, which can also be compiled by ifort and gfort for .f90 files
1

You may use Fortran interface to define several versions of your routines:

interface write_data
  module procedure write_data_1d
  module procedure write_data_2d
  module procedure write_data_3d
end interface write_data

Then these procedures can handle different types of input. Then inside these procedures you may use the RESHAPE function to convert the input into a convenient shape so that all three can call a common subroutine that implements the logic of whatever you do.

5 Comments

A reshape, though, does give the possibility of a copy.
This would be one option, but this would lead to much code. Because I have have 6 different versions of this routines, which would give me 18 routines in total.
@francescalus what do you mean with that?
@francescalus means that function RESHAPE might make a copy of the original data which can hit the performance a bit. That may or may not happen. If your store data in a 1D array in such a way that its storage is the same as how multiple dimensional data would be stored, then a good-enough compiler might see that and generate optimised code.
@Skyy2010 Yes, I meant as the previous comment. That is, reshape returns a result and only if a compiler can be absolutely certain that that result and the original are not modified during the joint lifespan can any non-copy optimizations be made. And many wouldn't bother even trying to determine that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.