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
  • 11
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值