fortran66のブログ

fortran について書きます。

move_alloc を用いた整数の分割

昨日のバージョンでは、整数の分割は画面出力されるだけで、データとして値を返していませんでした。これを配列の配列として返すことを考えます。整数配列を要素として持つ構造体を返すことにします。
返り値となる割り付け配列の大きさを増加させていくために、Fortran2003 で導入された組み込みサブルーチン move_alloc を用いました。この方法では、サイズを増やす毎に、要素の全コピーによる移動が行われるので無駄な事をすることになりますが、データ量が小さいので良しとします。(追記2012-07-27 記述が混乱していますが、move_alloc 自体は allocatable 配列のポインタ移動を実現する機能として導入されれた命令と思われますので、この命令では全コピーは行われないと思います。)

また割り付け配列の再割り付け機能も用いています。intel fortran の場合、この機能を利用するにはコンパイラのオプションで文法を Fortran2003 解釈に従うようにする必要があります。

実行結果



参考27までの分割数

ソース・プログラム

module m_partition
    implicit none
    type :: t_part
      integer, allocatable :: l(:)  
    end type t_part
contains
    function partition(n) 
      integer, intent(in) :: n
      type (t_part), allocatable :: pl(:), partition(:)
      call parti([integer::], n, n, pl) ! [] zero-sized integer array 
      partition = pl
      return
    end function partition

    recursive subroutine parti(list, n, n0, pl)
      integer, intent(in) :: list(:), n, n0
      type (t_part), allocatable, intent(in out) :: pl(:)
      type (t_part), allocatable :: tmp(:)
      integer :: i
      if (n == 0) then
        call move_alloc(pl, tmp)
        pl = [tmp, t_part(list)]
      else 
        do i = n - n0, n - 1
          call parti([list, n - i], i, min(i, n - i), pl)
        end do
      end if
      return
    end subroutine parti
end module m_partition
    
program part
    use m_partition
    implicit none
    type (t_part), allocatable :: q(:)
    integer :: k, i
    do k = 1, 7
      q = partition(k)
      print *, 'the number of partitons of ', k, ' = ', size(q)
      do i = 1, size(q)
        print '(25i3)', q(i)%l  
      end do
    end do
    stop
end program part