Array-valued function

2019-02-27 10:27发布

问题:

I'm new in the area of Fortran programming and after testing a few programs I already got a feeling of how to write programs. Now I was trying me on a bit harder program and I run into a problem I couldn't solve by myself. I already googled about the problem but I couldn't find an adequate answer ... So I thought maybe there are one or two Fortran programmers which can give me a hand in solving this problem.

The program is very simple it just multiplies two matrices with each other. I was trying to write a function which performs the task and returns the result matrix back to the invoker. To make the program a bit more dynamic I used dynamic arrays where the user can specify the dimension the matrices should have. The program looks like this:

program matrixMul
implicit none
integer, parameter :: ikind=selected_int_kind(18)
integer(kind=ikind), allocatable, dimension(:,:) :: m1, m2, result, mulMatrix
integer :: rows, cols, i, j

print *, 'Please enter the number of rows the matrix should have: '
read *, rows

print *, 'Please enter the number of columns the matrix should have: '
read *, cols

!allocate sufficient memory
allocate(m1(rows, cols), m2(cols, rows))

!fill matrixes with numbers entered by the user
call fillMatrix(m1, rows, cols)
call fillMatrix(m2, cols, rows)

result = mulMatrix(m1, m2, rows, cols)

!prints the result matrix to the screen
call printMatrix(result, rows, cols)

!deallocate memory
deallocate(m1, m2, mulMatrix, result)
end program matrixMul

Where the function which performs the actual multiplication looks like this:

function mulMatrix(m1, m2, r, c) result(mulMat)
implicit none
integer, parameter :: ikind=selected_int_kind(18)
integer(kind=ikind), dimension(r, c) :: m1
integer(kind=ikind), dimension(c, r) :: m2
integer(kind=ikind), allocatable, dimension(:,:) :: mulMat
integer r, c, i, j, k

allocate(mulMat(r,r))

!code which performs calculation is omitted

end function mulMatrix

My compiler reports the following error:

Error: Array index at (1) is an array of rank 2

For me it seems as the compiler would treat the variable mulMatrix as an usual array and therefore complains about it because I use it as it would have four dimensions which isn't the case. But how can I make the compiler think of this variable as a function call with four parameters instead of an array access? Any help would be appreciate.

回答1:

As IRO-bot already mentioned, use module. This will be a very good practice since you are learning a new language. With a module, you will just have to use the module instead of declaring individually the functions. It is also a good practice to not use keywords as variable names (example: result), use something else. I supposed that you understand well the trick of returning allocatable arrays as fonction return value, introduced in fortran 2003.

Your program can look like this, (the functions are contained in the program file instead of in a separate module, the result is the same)

program matrixMul
implicit none
integer, parameter :: ikind=selected_int_kind(18)
integer(kind=ikind), allocatable, dimension(:,:) :: m1, m2, m3
integer :: rows, cols, i, j

    print *, 'Please enter the number of rows the matrix should have: '
    read *, rows

    print *, 'Please enter the number of columns the matrix should have: '
    read *, cols

    !allocate sufficient memory
    allocate(m1(rows, cols), m2(cols, rows))

    !fill matrixes with numbers entered by the user
    call fillMatrix(m1, rows, cols)
    call fillMatrix(m2, cols, rows)
    m1 = 1
    m2 = 1

    m3 = mulMatrix(m1, m2, rows, cols)

    !prints the result matrix to the screen
    call printMatrix(m3, rows, cols)

    !deallocate memory
    deallocate(m1, m2, m3)

contains
    function mulMatrix(m1, m2, r, c) result(mulMat)
    implicit none
            integer, parameter :: ikind=selected_int_kind(18)
            integer(kind=ikind), dimension(r, c) :: m1
            integer(kind=ikind), dimension(c, r) :: m2
            integer(kind=ikind), allocatable, dimension(:,:) :: mulMat
            integer r, c, i, j, k

            allocate(mulMat(r,r))

            !code which performs calculation is omitted

    end function mulMatrix
end program matrixMul

Another think is: if you are performing the matrix multiplication as defined in linear algebra, the resulting matrix will be rows x rows, see the call to print the result. A caviar will be to not add the size of the matrices as parameters (see M. S. B. comment) and use the intrincsic function LBOUND and UBOUND or SIZE to get them in the function.