0

I just started learning Fortran and I have this function called matrix_power But I'm having difficulty trying to call the function. The file extension I'm using is .f and my compiler is gfortran.

Here is my code

function transpose_matrix(mat) result(mat_t)
    implicit none
    real, dimension(:,:), intent(in) :: mat
    real, dimension(size(mat,2),size(mat,1)) :: mat_t
    integer :: i, j
    do i = 1, size(mat,1)
    do j = 1, size(mat,2)
        mat_t(j,i) = mat(i,j)
    end do
    end do
end function transpose_matrix

function matrix_power(mat, p) result(mat_p)
    implicit none
    integer, intent(in) :: p
    real, dimension(:,:), intent(in) :: mat
    real, dimension(size(mat,1),size(mat,2)) :: mat_p
    integer :: i
    mat_p = mat
    do i = 2, p
    mat_p = matmul(mat_p, mat)
    end do
end function matrix_power


program matrix
implicit none

real, dimension(5, 5) :: matrix1 = reshape([2.0, 0.0, 0.0, 0.0, 0.0, &
                                            0.0, 2.0, 0.0, 0.0, 0.0, &
                                            0.0, 0.0, 2.0, 0.0, 0.0, &
                                            0.0, 0.0, 0.0, 2.0, 0.0, &
                                            2.0, 0.0, 0.0, 0.0, 2.0], (5, 5))

real, dimension(5, 5) :: mat_t, mat_p
integer :: i

mat_t = transpose_matrix(matrix1)

mat_p = matrix_power(matrix1, 3)
! Print the results
print *, "Matrix 1:"
print *, matrix1
print *, "Matrix 1 Transposed:"
print *, mat_t
print *, "Matrix 1 to the power of 3:"
print *, mat_p

end program matrix

I know that it's saying that there is a mismatch but it doesn't even make sense This is my definition of the mat_p

  real, dimension(m,n) :: mat_t, mat_p

Here is the error I'm receiving enter image description here

here is a text based error

   Return type mismatch of function 'matrix_power' at (1) (UNKNOWN/REAL(4))
Function 'matrix_power' at (1) has no IMPLICIT type
JasDj
  • 31
  • 4
  • We need more code than this, see [mcve]. Functions that return arrays must have explicit interface https://stackoverflow.com/questions/24910843/defining-a-function-returning-an-array https://stackoverflow.com/questions/26347090/how-to-declare-the-type-of-a-function-that-returns-an-array-in-fortran Also, your code certainly is not Fortran 77, but at least 90. – Vladimir F Героям слава Feb 12 '23 at 07:23
  • The posted code compiles without a problem with gfortran. You need to post a complete MRE. – steve Feb 12 '23 at 07:27
  • @steve I just added my MRE, thank you again much appreciated! – JasDj Feb 12 '23 at 07:45
  • @VladimirFГероямслава I just added my MRE, thank you again much appreciated! – JasDj Feb 12 '23 at 07:45
  • 1
    About the first rule of modern Fortran: Put **all** subroutines and functions in modules and use the modules. Following this simple rule will save you much grief - here you haven't told the main program what `matrix_power` is so how can it know what to do with it? Putting it in a module and using that module provides the important information required; namely that `matrix_power` returns a rank 2 real array. – Ian Bush Feb 12 '23 at 07:59
  • 1
    Please do not completely destroy the content of your question. What remained made very little sense. – Vladimir F Героям слава Feb 12 '23 at 09:19

1 Answers1

1

As suspected by @VladimirFГероямслава in the comments, functions returning arrays must have explicit interfaces. Routines/functions with assumed shapes dummy arguments, or intent() attributes for the arguments, do also require explicit interfaces.

First of all , because you are using implicit none (which is a good practice) in the main program, you have to define the return type of all the non-intrinsic functions you are using. For instance if you had this function:

function matrix_trace(mat,n) result(t)
    implicit none
    real :: mat(n,n)
    real :: t
    integer :: i
    t = 0.0
    do i = 1, n
        t = t + mat(i,i)
    end do
end function

You would simply have to insert in your main program:

real, external :: matrix_trace

This is an implicit interface, because you don't describe how arguments are passed. The implicit interface is the legacy pre-Fortran 90 way.

In your case your have to define explicit interfaces, with two possibilities.

Interface blocks:

In your main program you insert this code:

INTERFACE
    function transpose_matrix(mat) result(mat_t)
        implicit none
        real, dimension(:,:), intent(in) :: mat
        real, dimension(size(mat,2),size(mat,1)) :: mat_t
    end function transpose_matrix

    function matrix_power(mat, p) result(mat_p)
        implicit none
        integer, intent(in) :: p
        real, dimension(:,:), intent(in) :: mat
        real, dimension(size(mat,1),size(mat,2)) :: mat_p
    end function matrix_power
END INTERFACE

Modules

Much better, use modules to encapsulate your functions:

!*****************************************
MODULE mymatfuncs

CONTAINS

function transpose_matrix(mat) result(mat_t)
    implicit none
    real, dimension(:,:), intent(in) :: mat
    real, dimension(size(mat,2),size(mat,1)) :: mat_t
    integer :: i, j
    do i = 1, size(mat,1)
    do j = 1, size(mat,2)
        mat_t(j,i) = mat(i,j)
    end do
    end do
end function transpose_matrix

function matrix_power(mat, p) result(mat_p)
    implicit none
    integer, intent(in) :: p
    real, dimension(:,:), intent(in) :: mat
    real, dimension(size(mat,1),size(mat,2)) :: mat_p
    integer :: i
    mat_p = mat
    do i = 2, p
    mat_p = matmul(mat_p, mat)
    end do
end function matrix_power

END MODULE mymatfuncs
!*****************************************




program matrix
USE mymatfuncs, only: matrix_power, transpose_matrix
implicit none

real, dimension(5, 5) :: matrix1 = reshape([2.0, 0.0, 0.0, 0.0, 0.0, &
                                            0.0, 2.0, 0.0, 0.0, 0.0, &
                                            0.0, 0.0, 2.0, 0.0, 0.0, &
                                            0.0, 0.0, 0.0, 2.0, 0.0, &
                                            2.0, 0.0, 0.0, 0.0, 2.0], (5, 5))

real, dimension(5, 5) :: mat_t, mat_p
integer :: i

mat_t = transpose_matrix(matrix1)

mat_p = matrix_power(matrix1, 3)
! Print the results
print *, "Matrix 1:"
print *, matrix1
print *, "Matrix 1 Transposed:"
print *, mat_t
print *, "Matrix 1 to the power of 3:"
print *, mat_p

end program matrix
PierU
  • 1,391
  • 3
  • 15
  • Thanks a lot! I'm getting ordered to close the question but thanks again for the help! – JasDj Feb 12 '23 at 08:53
  • 1
    @JasDj This site works differently. Questions that were already answered elsewhere get closed. That does not mean you should delete it or even worse destroy the content inside. It just means they get linked to tje previous answered questions and cannot receive answers.This is to avoid repeating the same, sometimes unknowingly, sometimes just harvesting the rep. Sometimes a point can be missing in the original answers but new answers can always be added to those original questions. PierU managed to answer this one a minute before the closure. – Vladimir F Героям слава Feb 12 '23 at 09:21