module conversion
implicit none
public binary_representation
private
contains
pure function binary_representation(n_decimal)
integer, intent(in) :: n_decimal
integer :: binary_representation(8)
integer :: pos
integer :: n
binary_representation = 0
pos = 8
n = n_decimal
do while (n > 0)
binary_representation(pos) = mod(n, 2)
n = (n - binary_representation(pos))/2
pos = pos - 1
end do
end function
end module
module evolution
implicit none
public evolve
private
contains
subroutine not_visible()
! no-op call to demonstrate private/public visibility
call empty_subroutine_no_interface()
end subroutine
pure subroutine evolve(row, rule_binary)
use ancestors, only: compute_ancestors
integer, intent(inout) :: row(:)
integer, intent(in) :: rule_binary(8)
integer :: i
integer :: left, center, right
integer :: ancestry
integer, allocatable :: new_row(:)
allocate(new_row(size(row)))
do i = 1, size(row)
left = i - 1
center = i
right = i + 1
if (left < 1) left = left + size(row)
if (right > size(row)) right = right - size(row)
ancestry = compute_ancestors(row, left, center, right)
new_row(i) = rule_binary(ancestry)
end do
row = new_row
deallocate(new_row)
end subroutine
end module
祖先计算是在src/evolution/ancestors.f90:
module ancestors
implicit none
public compute_ancestors
private
contains
pure integer function compute_ancestors(row, left, center, right) result(i)
integer, intent(in) :: row(:)
integer, intent(in) :: left, center, right
i = 4*row(left) + 2*row(center) + 1*row(right)
i = 8 - i
end function
end module
还有一个“空”模块在src/evolution/empty.f90中:
module empty
implicit none
public empty_subroutine
private
contains
subroutine empty_subroutine()
end subroutine
end module
subroutine
empty_subroutine_no_interface()
use empty, only: empty_subroutine
call empty_subroutine()
end subroutine
启动条件的代码位于src/initial/initial.f90:
module initial
implicit none
public initial_distribution
private
contains
pure subroutine initial_distribution(row)
integer, intent(out) :: row(:)
row = 0
row(size(row)/2) = 1
end subroutine
end module
src/io/io.f90包含一个打印输出:
module io
implicit none
public print_row
private
contains
subroutine print_row(row)
integer, intent(in) :: row(:)
character(size(row)) :: line
integer :: i
do i = 1, size(row)
if (row(i) == 1) then
line(i:i) = '*'
else
line(i:i) = ' '
end if
end do
print *, line
end subroutine
end module
src/parser/parser.f90用于解析命令行参数:
module parser
implicit none
public get_arg_as_int
private
contains
integer function get_arg_as_int(n) result(i)
integer, intent(in) :: n
character(len=32) :: arg
call get_command_argument(n, arg)
read(arg , *) i
end function
end module
最后,使用tests/test.f90对上面的实现进行测试:
program test
use evolution, only: evolve
implicit none
integer :: row(9)
integer :: expected_result(9)
integer :: rule_binary(8)
integer :: i
! test rule 90
row = (/0, 1, 0, 1, 0, 1, 0, 1, 0/)
rule_binary = (/0, 1, 0, 1, 1, 0, 1, 0/)
call evolve(row, rule_binary)
expected_result = (/1, 0, 0, 0, 0, 0, 0, 0, 1/)
do i = 1, 9
if (row(i) /= expected_result(i)) then
print *, 'ERROR: test for rule 90 failed'
call exit(1)
end if
end do
! test rule 222
row = (/0, 0, 0, 0, 1, 0, 0, 0, 0/)
rule_binary = (/1, 1, 0, 1, 1, 1, 1, 0/)
call evolve(row, rule_binary)
expected_result = (/0, 0, 0, 1, 1, 1, 0, 0, 0/)
do i = 1, 9
if (row(i) /= expected_result(i)) then
print *, 'ERROR: test for rule 222 failed'
call exit(1)
end if
end do
end program
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(recipe-09 LANGUAGES Fortran)
include(GNUInstallDirs)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY
${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY
${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY
${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
# defines targets and sources
add_subdirectory(src)
# contains an "external" library we will link to
add_subdirectory(external)
# enable testing and define tests
enable_testing()
add_subdirectory(tests)