list - Fortran:作为函数参数的矩阵列表
问题描述
我需要实现一个对矩阵列表进行操作的算法。事先不知道矩阵的数量及其大小 - 用户可以自由地将算法应用于任何有限数量的任意大小的矩阵。如何在 Fortran 代码中实现这种行为?是否有适当的数据结构可以做到这一点?我正在寻找一种行之有效的 Fortran 编程模式。
使用列表数据结构和numpy矩阵的组合在 Python 中实现这样的算法相对容易,但它的运行速度很慢。
解决方案
注意我假设你所有的矩阵都有相同数据类型的元素。
这是我将要做的简化(并且通过那个非常老式的)示例
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_matrices 类型来保存矩阵数组,但这完全取决于你在做什么。
事实上,我目前正在研究的东西本质上是一个更复杂的版本 - 在矩阵列表上执行线性代数的例程,其中这些矩阵可能是实数或复数,并且这些矩阵中的数据可以分布在多个过程。刚刚斥责了某人要求我们下载未知文件,我对此感到有些内疚,但如果有兴趣,您可以在 github 上找到它:
git clone https://github.com/drijbush/dmat2.git
推荐阅读
- windows - 为什么调用内存密集型 Rust 函数会导致 Windows 上的 main 堆栈溢出,而不是在测试中?
- vue.js - Vue jsx,渲染函数中的h已定义但从未使用过
- java - 为什么我的简单数组只在 java 中打印零?
- php - MySQL cronjob 脚本到 MySQLi cronjob 脚本
- bash - 使用 sed 命令搜索一个单词并替换下一个单词
- python-3.x - 如何运行处理 s3 存储桶内容的脚本?
- postgresql - 从另一个查询调用时,返回 SETOF 记录丢失记录类型
- javascript - 使用 mkdirsync 时节点中的异常
- jenkins - 将 Terraform Plan 输出集成到 Jenkins
- android - 如何在 Flutter 中连接 onPressed 和 onTap?