代码之家  ›  专栏  ›  技术社区  ›  freude

Fortran:作为函数参数的矩阵列表

  •  0
  • freude  · 技术社区  · 5 年前

    我需要实现一个对矩阵列表进行操作的算法。矩阵的数量和大小是事先不知道的-用户可以自由地将算法应用于任何有限个数目的任何大小的矩阵。如何在Fortran代码中实现这种行为?有没有合适的数据结构可以做到这一点?我正在寻找一个成熟的Fortran编程模式。

    在Python中使用 列表 numpy公司 矩阵,但它的工作方式慢。

    0 回复  |  直到 5 年前
        1
  •  3
  •   Ian Bush    5 年前

    注意,我假设所有矩阵都有相同数据类型的元素。

    这里有一个简化的(通过非常老式的)例子来说明我会怎么做

    ian@eris:~/work/stack$ cat list_of_matrices.f90 
    Module numbers_module
    
      Implicit None
    
      Integer, Parameter, Public :: wp = Selected_real_kind( 12, 70 )
    
      Private
    
    End Module numbers_module
    
    Module matrix_module
    
      Use numbers_module, Only : wp
    
      Implicit None
    
      Type, Public :: matrix
         Real( wp ), Dimension( :, : ), Allocatable, Public :: data
      End type matrix
    
      Public :: matrix_allocate
      Public :: matrix_free
      Public :: matrix_set_with_random
      Public :: matrix_print
    
      Private
    
    Contains
    
      Subroutine matrix_allocate( A, m, n )
    
        Type( matrix ), Intent(   Out ) :: A
        Integer       , Intent( In    ) :: m
        Integer       , Intent( In    ) :: n
    
        Allocate( A%data( 1:m, 1:n ) )
    
      End Subroutine matrix_allocate
    
      Subroutine matrix_free( A )
    
        Type( matrix ), Intent( InOut ) :: A
    
        Deallocate( A%data )
    
      End Subroutine matrix_free
    
      Subroutine matrix_set_with_random( A )
    
        Type( matrix ), Intent( InOut ) :: A
    
        Call Random_number( A%data )
    
      End Subroutine matrix_set_with_random
    
      Subroutine matrix_print( A, format )
    
        Type( matrix )      , Intent( In ) :: A
        Character( Len = * ), Intent( In ) :: format
    
        Integer :: i
    
        Write( *, * ) 'The matrix has the shape: ', Shape( A%data )
        Do i = 1, Size( A%data, Dim = 1 )
           Write( *, format ) A%data( i, : )
        End Do
    
      End Subroutine matrix_print
    
    End Module matrix_module
    
    Program test_matrix
    
      Use matrix_module, Only : matrix, matrix_allocate, matrix_free, &
           matrix_set_with_random, matrix_print
    
      Implicit None
    
      Type( matrix ), Dimension( : ), Allocatable :: list_of_matrices
    
      Integer :: n_mats
      Integer :: n, m
      Integer :: i_mat
    
      Write( *, * ) 'How many matrices'
      Read ( *, * ) n_mats
    
      Allocate( list_of_matrices( 1:n_mats ) )
    
      Do i_mat = 1, n_mats
         Write( *, * ) 'Dimensions for matrix ', i_mat
         Read ( *, * ) m, n
         Call matrix_allocate( list_of_matrices( i_mat ), m, n )
         Call matrix_set_with_random( list_of_matrices( i_mat ) )
      End Do
    
      Do i_mat = 1, n_mats
         Write( *, * ) 'Data for matrix ', i_mat
         Call matrix_print( list_of_matrices( i_mat ), '( 20( f5.2, 1x ) )' )
      End Do
    
      Do i_mat = n_mats, 1, -1
         Call matrix_free( list_of_matrices( i_mat ) )
      End Do
      Deallocate( list_of_matrices )
    
    End Program test_matrix
    ian@eris:~/work/stack$ gfortran -std=f2008 -Wall -Wextra -Wuse-without-only -Wsurprising -Wimplicit-interface -Werror -fcheck=all list_of_matrices.f90 -o list_of_matrices
    ian@eris:~/work/stack$ ./list_of_matrices 
     How many matrices
    3
     Dimensions for matrix            1
    2 1
     Dimensions for matrix            2
    4 3
     Dimensions for matrix            3
    5 6
     Data for matrix            1
     The matrix has the shape:            2           1
     0.06
     0.31
     Data for matrix            2
     The matrix has the shape:            4           3
     0.02  0.63  0.08
     0.26  0.84  0.75
     0.85  0.67  0.34
     0.85  0.91  0.33
     Data for matrix            3
     The matrix has the shape:            5           6
     0.35  0.58  0.01  0.93  0.74  0.46
     0.43  0.38  0.89  0.83  0.51  0.26
     0.33  0.03  0.73  0.26  0.40  0.58
     0.48  0.87  0.15  0.62  0.13  0.79
     0.59  0.97  0.15  0.09  0.05  0.37
    ian@eris:~/work/stack$ 
    

    实际上,我会让派生类型的内容保持私有,并且只由模块过程访问,现在我将在矩阵类型中使用类型绑定过程,但是对于这个问题,我认为这会分散注意力,因此采用了稍微旧一些的方法。在生产代码中,我可能还需要一个单独的list-of-matrix类型来保存矩阵数组,但这完全取决于您在做什么。

    git clone https://github.com/drijbush/dmat2.git