我有一个Fortran函数,我想在编译时初始化一个大数组。下面是一个简化的工作示例,其中coeff
in的参数fill_coefficients
已大大减小。
如何在coeff
不超过255个连续行或每行最多132个字符的情况下编写类似的代码?这fill_coefficients
实际上应该是PURE
,这可能使得它coeff
在运行时无法一次读取文件,然后存储结果。
文件“ main.f03”:
PROGRAM main
USE coefficients
IMPLICIT NONE
REAL(dp), ALLOCATABLE, DIMENSION(:,:) :: matrix
CALL fill_coefficients(matrix,2)
PRINT *, "The first row of 'matrix':"
PRINT *, matrix(1,:)
END PROGRAM main
文件“ coefficients.f03”:
MODULE coefficients
USE iso_fortran_env
IMPLICIT NONE
INTEGER, PARAMETER :: dp = REAL64
CONTAINS
PURE SUBROUTINE fill_coefficients(my_coefficients, n)
IMPLICIT NONE
REAL(dp), ALLOCATABLE, DIMENSION(:,:), INTENT(OUT) :: my_coefficients
INTEGER, INTENT(IN) :: n
! The size of the following array would be roughly 200 x 200 = 40.000.
REAL(dp), DIMENSION(3,3), PARAMETER :: coeff = &
RESHAPE ( &
[ + 10.6770782520313112108115239655957106_dp, &
- 854.166260162504896864921917247656850_dp, &
- 85.4166260162504896864921917247656850_dp, &
+ 16250.5130995916556628551394756366716_dp, &
+ 6747.91345528378868523288314625648912_dp, &
+ 106.770782520313112108115239655957106_dp, &
- 123256.191341449456617608232658836883_dp, &
- 8328.12103658442274443298869316465429_dp, &
+ 500381.272281447399894682070647642979_dp ], &
[3,3] )
IF (ALLOCATED(my_coefficients)) DEALLOCATE(my_coefficients)
ALLOCATE(my_coefficients(n,n))
my_coefficients = coeff(1:n,1:n)
END SUBROUTINE fill_coefficients
END MODULE coefficients
输出:
The first row of 'matrix': 10.677078252031311 16250.513099591655
从维护的角度(也许是在注释中建议的),我会将数据读入一个单独的非纯子例程中的模块变量中,该例程在程序启动时被调用一次。fill_coefficients
然后成为该模块变量的简单赋值,并且仍然可以是PURE。
MODULE coefficients
IMPLICIT NONE
...
! Could be PUBLIC, PROTECTED, then you could directly
! assign from it and dispense with fill_coefficients
! altogether.
REAL(dp), PRIVATE :: coeff(200,200)
CONTAINS
SUBROUTINE init
INTEGER :: unit
OPEN( NEWUNIT=unit, &
FILE='lots-of-numbers.bin', &
FORM='UNFORMATTED', &
! ACCESS='STREAM', & ! Maybe - depending on how you write it.
STATUS='OLD' )
READ (unit) coeff
CLOSE(unit)
END SUBROUTINE init
PURE SUBROUTINE fill_coefficients(my_coefficients, n)
! implicit none already in force due to the statement in
! the specification part of the host module.
! IMPLICIT NONE
REAL(dp), ALLOCATABLE, DIMENSION(:,:), INTENT(OUT) :: my_coefficients
INTEGER, INTENT(IN) :: n
! This test is redundant - my_coefficients is INTENT(OUT) so
! it must be not allocated at this point.
! IF (ALLOCATED(my_coefficients)) DEALLOCATE(my_coefficients)
! This allocate statement is redundant - allocation will
! happen automatically under F2003 with the assignment.
! ALLOCATE(my_coefficients(n,n))
my_coefficients = coeff(1:n,1:n)
END SUBROUTINE fill_coefficients
END MODULE coefficients
如果必须将其coeff
作为编译时参数,则将其组装为源代码可管理的块-也许逐列。每个声明的限制是行长(132)和连续行数(255)。
REAL(dp), PARAMETER :: column_1(200) = [ &
+ 10.6770782520313112108115239655957106_dp, &
- 854.166260162504896864921917247656850_dp, &
- 85.4166260162504896864921917247656850_dp, &
... ]
REAL(dp), PARAMETER :: column_2(200) = [ ... ]
...
REAL(dp), PARAMETER :: column_200(200) = [ ... ]
REAL(dp), PARAMETER :: coeff(200,200) = RESHAPE( [ &
column_1, column_2, ..., column_200 ], &
SHAPE=[200,200] )
用PARAMETER声明的事物称为常量。从概念上讲,它们仅在编译时存在-取决于您对命名常量所做的操作,编译器可能会或可能不会在可执行映像中为常量预留存储空间。
大的命名常量可能会导致编译器在编译文件时遇到问题。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句