Error: Statement Function is recursive

This is trying to solve a linear equation of 3*3 and print out the results, but it got problems in the commented lines:

I defined the module LinearSolution outside of program, should I define it inside? what's the difference?

Why it says the statement is recursive, you know, when I use these statement as normal subroutine instead of module subroutine, they are verified to be fine.

module LinearSolution
    type LAE
        integer::N
        double precision,dimension(:,:),allocatable::A
        double precision,dimension(  :),allocatable::B
    contains
        procedure,nopass::RowReduction
    end type LAE
contains
    subroutine RowReduction
        double precision::C
        do k=1,N
            do i=k+1,N
                if(A(k,k)/=0) then
                    C=A(i,k)/A(k,k)
                    B(i)=B(i)-B(k)*C       !error: Statement Function is recursive
                    do j=k+1,N
                        A(i,j)=A(i,j)-A(k,j)*C   !error: Statement Function is recursive
                    end do
                end if
            end do
        end do

        do k=N,1,-1
            do i=k-1,1,-1
                if(A(k,k)/=0) then
                    C=A(i,k)/A(k,k)
                    B(i)=B(i)-B(k)*C  !error: Statement Function is recursive
                end if
            end do
        end do

        do k=1,N
            if(A(k,k)/=0) then
                B(k)=B(k)/A(k,k)  !error: Statement Function is recursive
            end if
        end do
    end subroutine RowReduction
end module LinearSolution

program TestLAE
    use LinearSolution  !fatal error: cant open module file LinearSolution.mod for reading
    type(LAE)::LAE1
    LAE1%N=3
    allocate(LAE1%B(1:N))
    allocate(LAE1%A(1:N,1:N))
    LAE1%B=(/1,1,1/)
    LAE1%A=(/2,0,0,0,2,0,0,0,2/)
    call LAE1%RowReduction
    print*, LAE1%B(1),LAE1%B(2),LAE1%B(3)
end program

Answers


As is so often the case, implicit none is your friend.

Let's take the errors one at a time:

B(i)=B(i)-B(k)*C       !error: Statement Function is recursive

the compiler doesn't recognize B in this context; there is no variable declared B here(*), so the best it can do is assume that it's a real-valued statement function defining B as a function of I. Statement functions are space saving but confusing ways of defining a function inline, but amongst other things they can't be recursive; here you'd be defining B(i) in terms of B(i) which obviously fails.

(*) But! you cry. B is an array field in my type LAE! Yes, but we're not in the context of LAE here; and indeed, in the context of this function there are no variables of type LAE to even use the B values of. This is because the procedure was defined nopass; you need to have a variable which is the object being operated on which is of class LAE so that we can access those fields. That looks something like this:

    type LAE
        !...
    contains
        procedure::RowReduction
    end type LAE

contains
    subroutine RowReduction(self)
        class(LAE), intent(InOut) :: self
        double precision::C
        integer :: i, j, k
        do k= 1, self%N
            do i= k+1, self%N
                if( self%A(k,k) /= 0 ) then
        !....

Note that we have to define self to be of class(LAE) rather than type; class is a superset of type and is needed when dealing with extensible objects which include those with (re-)allocatable components. Note too we've added implicit none which would tell you right away that B wasn't defined, and thus specified the integer indices i,j, and k.

Once N, A, and B are being correctly referenced as fields of self, then most of the rest of the program is correct. Note that you have to reshape your LAE1%A array:

LAE1%A=reshape((/2,0,0,0,2,0,0,0,2/), (/N, N/))

But otherwise things seem fine.

module LinearSolution
implicit none

    type LAE
        integer::N
        double precision,dimension(:,:),allocatable::A
        double precision,dimension(  :),allocatable::B
    contains
        procedure::RowReduction
    end type LAE

contains
    subroutine RowReduction(self)
        class(LAE), intent(InOut) :: self
        double precision::C
        integer :: i, j, k
        do k= 1, self%N
            do i= k+1, self%N
                if( self%A(k,k) /= 0 ) then
                    C = self%A(i,k) / self%A(k,k)
                    self%B(i) = self%B(i)- self%B(k)*C
                    do j=k+1, self%N
                         self%A(i,j) = self%A(i,j) - self%A(k,j)*C
                    end do
                end if
            end do
        end do

        do k = self%N,1,-1
            do i=k-1,1,-1
                if( self%A(k,k)/=0) then
                    C= self%A(i,k)/ self%A(k,k)
                    self%B(i)= self%B(i)- self%B(k)*C
                end if
            end do
        end do

        do k=1, self%N
            if( self%A(k,k)/=0 ) then
                self%B(k) = self%B(k) / self%A(k,k)
            end if
        end do
    end subroutine RowReduction
end module LinearSolution

program TestLAE
    use LinearSolution
    implicit none

    integer, parameter :: N = 3
    type(LAE)::LAE1
    LAE1%N=N
    allocate(LAE1%B(1:N))
    allocate(LAE1%A(1:N,1:N))
    LAE1%B=(/1,1,1/)
    LAE1%A=reshape((/2,0,0,0,2,0,0,0,2/), (/N, N/))
    call LAE1%RowReduction
    print*, LAE1%B(1),LAE1%B(2),LAE1%B(3)
end program

Running gives:

$ gfortran -o lae lae.f90 -Wall -std=f2003
$ ./lae
  0.50000000000000000       0.50000000000000000       0.50000000000000000     

Need Your Help

Communicating with multiple app domains

.net wcf remoting appdomain .net-4.5

I've got an application that needs to have multiple app domains to isolate potentially unsafe modules, and also provide a level of isolation for non-thread-safe code. Each module implements a common

cocos2d iPad crash when setting

ios ipad cocos2d-iphone

I just completed a quick 1st draft prototype of a cocos2d iPad app. I have not modified the CCTextureAtlas.m file.