There are many useful utility functions in Matlab and occassionally an important but rare (difficult to find source in the internet) algorithm such as this permutation algorithm. Hopefully there will be more Fortran version of Matlab utility functions appearing here in the future.
The one listed below is unpolished and unoptimized and not suitable for large inputs. It is a very basic implementation taken directly from the mathematical definition. It is also tested only for a small number of cases. Corrections, suggestions and comments are welcomed.
!/*
! * perms - All Possible permutations
! *
! * (C) Copyright 2010 xTechNotes.blogspot.com
! *
! * This program is free software: you can redistribute it and/or modify
! * it under the terms of the GNU General Public License as published by
! * the Free Software Foundation, either version 3 of the License, or
! * (at your option) any later version.
! *
! * This program is distributed in the hope that it will be useful,
! * but WITHOUT ANY WARRANTY; without even the implied warranty of
! * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! * GNU General Public License for more details.
! *
! * You should have received a copy of the GNU General Public License
! * along with this program. If not, see .
! */
RECURSIVE subroutine perms(n, nfact, vecIn, vecOut)
IMPLICIT NONE
INTEGER, INTENT(IN) :: n ! number of elements of original vector
INTEGER, INTENT(IN) :: nfact ! Factorial(n)
REAL, INTENT(IN) :: vecIn(n) ! original vector to be permuted
REAL, INTENT(OUT):: vecOut(nfact, n) ! Permutations of original vector
! local variables
real :: vecInTmp(n)
integer :: ii , mfact
real :: dtmp
vecOut = 0.0
if (n .le. 0) then
return
elseif ( n .eq. 1 ) then
vecOut(1,1) = vecIn(1)
elseif ( n .eq. 2 ) then
vecOut(1, :) = vecIn(:)
vecOut(2, :) = (/vecIn(2), vecIn(1)/)
else
! ii = 1
call factorial(n-1, mfact)
vecOut(1:mfact, 1) = vecIn(1)
call perms(n-1, mfact, vecIn(2:n), vecOut(1:mfact, 2:n))
do ii = 2, n
vecInTmp = VecIn
vecInTmp(1) = VecIn(ii)
vecInTmp(ii) = VecIn(1)
vecOut((ii-1)*mfact+1 : ii*mfact, 1) = vecInTmp(1)
call perms(n-1, mfact, vecInTmp(2:n), vecOut( (ii-1)*mfact+1 : ii*mfact, 2:n))
enddo
endif
end subroutine perms
No comments:
Post a Comment