Fortran:數組函數詳解

聲明:本博文翻譯自:https://www.tutorialspoint.com/fortran/location.htm等相關網頁
上一篇博文講了數組的基本用法。這一篇博文着重講解關於數組內置函數的用法。

1. 向量與矩陣乘法
向量的乘法其實就是數學裏的內積運算;而矩陣乘法matmul是指數學中的矩陣乘法運算。而矩陣(向量)A*B則是兩個大小相同的矩陣對應位置元素相乘。

dot_product(vector_a,vector_b)  !.. 返回一個標量乘積,也就是兩者的內積。兩個向量長度必須一致。
matmul(matrix_a,matrix_b)  !.. 返回兩個矩陣的矩陣乘積,算法滿足數學上的運算定律

dot_product示例代碼:
Program arrayDotProduct
  implicit none
  real, dimension(5) :: a, b
  integer:: i, asize, bsize

  asize = size(a)
  bsize = size(b)

  do i = 1, asize
     a(i) = i
  end do

  do i = 1, bsize
     b(i) = i*2
  end do

  do i = 1, asize
     Print *, a(i)
  end do

  do i = 1, bsize
     Print *, b(i)
  end do

  write(*,'(1x,a)') 'Vector Multiplication: Dot Product:'
  write(*,'(1x,g0)') dot_product(a, b)

End program arrayDotProduct
用ivf,運行後結果爲:
   1.000000
   2.000000
   3.000000
   4.000000
   5.000000
   2.000000
   4.000000
   6.000000
   8.000000
   10.00000
 Vector Multiplication: Dot Product:
 110.0000

matmul示例代碼:
Program matMulProduct
  implicit none
  integer, dimension(3,3) :: a, b, c
  integer :: i, j

  do i = 1, 3
     do j = 1, 3
        a(i, j) = i+j
     end do
  end do

  print *, 'Matrix Multiplication: A Matrix'

  do i = 1, 3
        print*, a(i, :)
  end do

  do i = 1, 3
     do j = 1, 3
        b(i, j) = i*j
     end do
  end do

  Print*, 'Matrix Multiplication: B Matrix'

  do i = 1, 3
        print*, b(i, :)
  end do

  c = matmul(a, b)
  Print*, 'Matrix Multiplication: Result Matrix'

  do i = 1, 3
        print*, c(i, :)
  end do

End program matMulProduct
運行結果如下:
 Matrix Multiplication: A Matrix
           2           3           4
           3           4           5
           4           5           6
 Matrix Multiplication: B Matrix
           1           2           3
           2           4           6
           3           6           9
 Matrix Multiplication: Result Matrix
          20          40          60
          26          52          78
          32          64          96

2. Reduction函數
這一部分的函數主要包括all,any,count,maxval,minval,product,sum
。
這裏簡單介紹其使用用法
all(mask, dim); any(mask, dim); count(mask, dim)
其中,mask爲條件,dim爲指定的某一維度。
用下面的代碼體會一下三個函數的用法,示例代碼如下:
Program arrayReduction
  implicit none
  integer :: i 
  real, dimension(3,2) :: a 
  a = reshape( [5,9,6,10,8,12], [3,2] ) 

  do i = 1, size(a,dim=1)
    write(*,'(*(g0,3x))') a(i,:)
  end do

  write(*,*) all(a > 7, dim = 2)
  write(*,*) any(a > 5)
  write(*,*) count(a > 5, dim = 1)
  write(*,*) all(a >= 5 .and. a < 10)

End program arrayReduction
執行結果如下:
5.000000   10.00000
9.000000   8.000000
6.000000   12.00000
F T F
T
2           3
F

接下來講解一下maxval,minval,sum,product
基本格式如下:
maxval(array,dim,mask); minval(array,dim,mask)
product(array,dim,mask); sum(array,dim,mask)
這裏要注意一點,上面這四個函數作用的對象都是數組。dim,mask的含義與上面的相同。
還有一點就是:maxmin也是尋找最值函數。但這兩個函數作用的都是數據的集合,並不是數組。
看下面的示例代碼:
program arrayReduction
  implicit none
  integer :: i 
  real :: a(3,2) = reshape( [21.0, 12.0,33.0, 24.0, 15.0, 16.0],[3,2])

  do i = 1, size(a,dim=1)
    write(*,'(*(g0,3x))') a(i,:)
  end do

  Print *, maxval(a)
  Print *, maxval(a, dim = 1)
  Print *, minval(a)
  Print *, minval(a, dim = 2)
  Print *, sum(a)
  Print *, product(a,dim=1)
  Print *, max(1,2,3)
  Print *, min(1,2,3)

End program arrayReduction 
執行結果如下:
21.00000   24.00000
12.00000   15.00000
33.00000   16.00000
33.00000
33.00000       24.00000
12.00000
21.00000       12.00000       16.00000
121.0000
8316.000       5760.000
3
1

3. Inquiry 函數
主要包含下面幾個函數
allocate(array(m,n)) !.. 用來對可分配數組進行內存分配
lbound(array,dim) !.. 返回數組某一維的最小值
ubound(array,dim) !.. 返回數組某一維的最大值
shape(array)  !.. 返回數組聲明的形狀
size(array,dim)  !.. 返回數組某一維的大小
示例代碼如下:
Program arrayInquiry
  implicit none
  real :: a(3,2) = reshape( [5,9,6,10,8,12], [3,2] ) 

  Print *, lbound(a, dim = 1), ubound(a, dim = 1)
  Print *
  Print *, lbound(a, dim = 2), ubound(a, dim = 2)
  Print *
  Print *, shape(a)
  Print *, size(a,dim = 1), size(a,dim = 2)

end program arrayInquiry
運行結果如下:
           1           3

           1           2

           3           2
           3           2

4. Construction 函數
這一節的函數主要有merge, spread, pack, unpack
基本語法如下:
merge(tsource,fsource,mask)
spread(source,dim,ncopies)
pack(array,mask,vector)
unpack(array,mask,field)

測試merge函數
Program arrayConstruction
  implicit none 
  integer :: tsource(2,3) = reshape( [1, 4, 2, 5, 3, 6], [2, 3] )
  integer :: fsource(2,3) = reshape( [7, 0, 8, -1, 9, -2], [2, 3] )
  logical :: mask(2,3)    = reshape( [.TRUE., .FALSE., .FALSE., .TRUE., .TRUE., .FALSE.], [2,3] )
  integer :: i, ar1(2,3)

  write(*,'(1x,a)') "tsource as follow:"
  do i = 1, size(ar1, dim = 1)
    write(*,'(*(g0,3x))') tsource(i,:)
  end do

  write(*,'(1x,a)') "fsource as follow:"
  do i = 1, size(ar1, dim = 1)
    write(*,'(*(g0,3x))') fsource(i,:)
  end do

  write(*,'(1x,a)') "mask as follow:"
  do i = 1, size(ar1, dim = 1)
    write(*,'(*(g0,3x))') mask(i,:)
  end do

  ar1 = merge( tsource, fsource, mask )    

  write(*,'(1x,a)') "ar1 as follow:"
  do i = 1, size(ar1, dim = 1)
    write(*,'(*(g0,3x))') ar1(i,:)
  end do

End program arrayConstruction
執行結果如下:
tsource as follow:
1   2   3
4   5   6
fsource as follow:
7   8   9
0   -1   -2
mask as follow:
T   F   T
F   T   F
ar1 as follow:
1   8   3
0   5   -2

測試spread函數
Program arrayConstruction
  implicit none 
  integer :: i
  integer :: source(3) = [1,2,3]
  integer :: ar1(2,3), ar2(3,2)

  ar1 = spread( source, dim = 1, ncopies = 2 )
  write(*,'(1x,a)') "ar1 as follow:"
  do i = 1, size(ar1,dim=1)
    write(*,'(*(g0,3x))') ar1(i,:)
  end do

  ar2 = spread( source, dim = 2, ncopies = 2 )
  write(*,'(1x,a)') "ar2 as follow:"
  do i = 1, size(ar2,dim=1)
    write(*,'(*(g0,3x))') ar2(i,:)
  end do

End program arrayConstruction
運行結果如下:
ar1 as follow:
1   2   3
1   2   3
ar2 as follow:
1   1
2   2
3   3

測試pack函數
Program arrayConstruction
  implicit none 
  integer :: array(2, 3), vec1(2), vec2(5) 
  logical :: mask (2, 3) 

  array = reshape( [7, 0, 0, -5, 0, 0], [2, 3] ) 
  mask = array /= 0

  vec1 = pack(array, mask)   !.. returns ( 7, -5 ) 
  write(*,*) vec1
  mask = array > 0
  vec2 = pack(array, mask, vector= [1,2,3,4,5])  !..  returns ( 7, 2, 3, 4, 5 )
  write(*,*) vec2

End program arrayConstruction
執行結果如下:
7          -5
7           2           3           4           5

測試unpack函數
Program arrayConstruction
  implicit none 
  integer :: i
  logical mask (3, 3) 
  integer :: vector(6) =  [1, 2, 3, 4, 5, 6], AR1(3, 3) 

  mask = reshape( [.TRUE.,.FALSE.,.FALSE.,.TRUE.,.TRUE.,.FALSE.,.FALSE.,.TRUE.,.TRUE.], [3, 3] )
  AR1 = unpack(vector, mask, 8)

  write(*,'(1x,a)') "mask as follow:"
  do i = 1, size(mask,dim=1)
    write(*,'(*(g0,3x))') mask(i,:)
  end do

  write(*,'(1x,a)') "ar1 as follow:"
  do i = 1, size(ar1,dim=1)
    write(*,'(*(g0,3x))') ar1(i,:)
  end do

End program arrayConstruction
運行結果如下:
mask as follow:
T   T   F
F   T   T
F   F   T
ar1 as follow:
1   2   8
8   3   4
8   8   5

4. reshape函數
其基本語法如下:
reshape(source,shape,pad,order)
示例代碼如下:
Program arrayReshape
  implicit none

  interface
     subroutine write_matrix(a)
      integer :: i, j
     real, dimension(:,:) :: a
     end subroutine write_matrix
  end interface

  real, dimension (1:9) :: b = [ 21, 22, 23, 24, 25, 26, 27, 28, 29 ]
  real, dimension (1:3, 1:3) :: c, d, e
  real, dimension (1:4, 1:4) :: f, g, h

  integer, dimension (1:2) :: order1 = [ 1, 2 ]
  integer, dimension (1:2) :: order2 = [ 2, 1 ]
  real, dimension (1:16) :: pad1 = [ -1, -2, -3, -4, -5, -6, -7, -8, &
                                   & -9, -10, -11, -12, -13, -14, -15, -16 ]

  c = reshape( b, (/ 3, 3 /) )
  call write_matrix(c)

  d = reshape( b, (/ 3, 3 /), order = order1)
  call write_matrix(d)

  e = reshape( b, (/ 3, 3 /), order = order2)
  call write_matrix(e)

  f = reshape( b, (/ 4, 4 /), pad = pad1)
  call write_matrix(f)

  g = reshape( b, (/ 4, 4 /), pad = pad1, order = order1)
  call write_matrix(g)

  h = reshape( b, (/ 4, 4 /), pad = pad1, order = order2)
  call write_matrix(h)

End program arrayReshape

subroutine write_matrix(a)
  implicit none
  integer :: i, j
  real, dimension(:,:) :: a
  write(*,*)

  do i = lbound(a,1), ubound(a,1)
     write(*,*) (a(i,j), j = lbound(a,2), ubound(a,2))
  end do
End subroutine write_matrix
運行結果如下:
   21.00000       24.00000       27.00000
   22.00000       25.00000       28.00000
   23.00000       26.00000       29.00000

   21.00000       24.00000       27.00000
   22.00000       25.00000       28.00000
   23.00000       26.00000       29.00000

   21.00000       22.00000       23.00000
   24.00000       25.00000       26.00000
   27.00000       28.00000       29.00000

   21.00000       25.00000       29.00000      -4.000000
   22.00000       26.00000      -1.000000      -5.000000
   23.00000       27.00000      -2.000000      -6.000000
   24.00000       28.00000      -3.000000      -7.000000

   21.00000       25.00000       29.00000      -4.000000
   22.00000       26.00000      -1.000000      -5.000000
   23.00000       27.00000      -2.000000      -6.000000
   24.00000       28.00000      -3.000000      -7.000000

   21.00000       22.00000       23.00000       24.00000
   25.00000       26.00000       27.00000       28.00000
   29.00000      -1.000000      -2.000000      -3.000000
  -4.000000      -5.000000      -6.000000      -7.000000

6. Manipulation函數
這一節主要有cshift,eoshift,transpose內置函數
cshift與eoshift其示例代碼如下:
Program arrayShift
  implicit none
  real, dimension(1:6) :: a = (/ 21.0, 22.0, 23.0, 24.0, 25.0, 26.0 /)
  real, dimension(1:6) :: x, y

  write(*,10) a
  x = cshift ( a, shift = 2)
  write(*,10) x

  y = cshift (a, shift = -2)
  write(*,10) y

  x = eoshift ( a, shift = 2)
  write(*,10) x

  y = eoshift ( a, shift = -2)
  write(*,10) y

  10 format(1x,6f6.1)

End program arrayShift
運行結果如下:
   21.0  22.0  23.0  24.0  25.0  26.0
   23.0  24.0  25.0  26.0  21.0  22.0
   25.0  26.0  21.0  22.0  23.0  24.0
   23.0  24.0  25.0  26.0   0.0   0.0
    0.0   0.0  21.0  21.0  22.0  23.0

transpose的示例代碼如下:
program matrixTranspose
  implicit none
  interface
    subroutine write_matrix(a)
      integer :: i, j
      integer, dimension(:,:) :: a
    end subroutine write_matrix
  end interface

  integer, dimension(3,3) :: a, b
  integer :: i, j

  do i = 1, 3
    do j = 1, 3
      a(i, j) = i
    end do
  end do

  print *, 'Matrix Transpose: A Matrix'

  call write_matrix(a)
  b = transpose(a)
  print *, 'Transposed Matrix:'

  call write_matrix(b)
End program matrixTranspose


subroutine write_matrix(a)
  implicit none
  integer :: i, j
  integer, dimension(:,:) :: a
  write(*,*)

  do i = lbound(a,1), ubound(a,1)
    write(*,*) (a(i,j), j = lbound(a,2), ubound(a,2))
  end do

end subroutine write_matrix
運行結果如下:
Matrix Transpose: A Matrix
1           1           1
2           2           2
3           3           3

Transposed Matrix:
1           2           3
1           2           3
1           2           3

7. Location函數
這一節主要有maxloc與minloc函數
其基本語法如下:
maxloc(array,mask)
minloc(array,mask)
示例代碼如下:
Program arrayLocation
  implicit none
  integer :: i 
  real :: a(2,3) = reshape( [ 21.0, 12.0,33.0, 24.0, 15.0, 16.0 ], [2,3] )

  do i = 1, size(a,dim=1)
    write(*,'(*(g0,3x))') a(i,:)
  end do

  Print *, maxloc(a, dim = 1), maxloc(a, dim = 2)
  Print *, minloc(a, dim = 1), minloc(a, dim = 2)

End program arrayLocation 
運行結果如下:
21.00000   33.00000   15.00000
12.00000   24.00000   16.00000
1           1           2           2           2
2           2           1           3           1
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章