为Fortran中的单精度数组指定双精度

时间:2016-08-30 12:36:06

标签: arrays fortran double precision fortran90

我有一些使用双精度数组的例程但是 似乎对于我的一些计算双精度算术 不是必需的,单精度算术就足够了。为了那个原因 原因,我需要将双精度数组分配给单精度 的:

real*8  :: A(100,100)
real*4  :: A_aux(100,100)

do i=1,100
      A_aux(i,1:100)=A(i,1:100)
enddo

我的问题是,这个程序完全等同于其他程序吗?

do j=1,100
    do i=1,100
         A_aux(i,j)=real(A(i,j))
    enddo
enddo

正如您在第一种情况中所看到的,我可以使用向量指令,但我不能 在第二种情况下进行,这可能导致更长的执行时间。 在我以单精度执行计算后,我需要分配 将单精度数组返回到双精度数组。

这种处理双精度的方式是否有效 - >完全单精度转换?

感谢。

1 个答案:

答案 0 :(得分:0)

您可以简单地考虑比较不同实现方案的值(包括用户d_1999评论过的方法)。

下面的代码使用一些双精度数字初始化矩阵A,然后调用将双精度转换为单精度矩阵的不同例程(B1B2B3) 。然后在它们之间逐个单元地比较这些值,如果它们不匹配,则打印不匹配并停止。

使用gfortran 4.8.5和ifort 16.0.3编译并运行代码。

    PROGRAM test
    implicit none
    integer, parameter :: sp = kind(1.0)
    integer, parameter :: dp = kind(1.0d0)
    real(dp) :: A(100,100)
    real(sp) :: B1(100,100)
    real(sp) :: B2(100,100)
    real(sp) :: B3(100,100)
    integer :: i, j

!   Fill A with some random numbers
    do j = 1, 100
     do i = 1, 100
      A(i,j) = real(i+j)
      A(i,j) = sqrt(A(i,j)/100)
     enddo
    enddo

!   Use the 3 versions and fill B1, B2 and B3
    call CopyV1(A,B1)
    call CopyV2(A,B2)
    call CopyV3(A,B3)

!   Now compare cell by cell
    do j=1,100
     do i=1,100
      if (B1(j,i) .ne. B2(j,i)) then
       write(*,*) "B1 mismatch B2 at position ", j, i
       stop
      else if (B1(j,i) .ne. B3(j,i)) then
       write(*,*) "B1 mismatch B3 at position ", j, i
       stop
      end if
     enddo
    enddo

    END

    SUBROUTINE CopyV1(A,B)
    implicit none
    integer, parameter :: sp = kind(1.0)
    integer, parameter :: dp = kind(1.0d0)
    real(dp), intent(in) :: A(100,100)
    real(sp), intent(out) :: B(100,100)
    integer :: i

    do i=1,100
     B(i,1:100)=A(i,1:100)
    enddo
    END

    SUBROUTINE CopyV2(A,B)
    implicit none
    integer, parameter :: sp = kind(1.0)
    integer, parameter :: dp = kind(1.0d0)
    real(dp), intent(in) :: A(100,100)
    real(sp), intent(out) :: B(100,100)
    integer :: i,j

    do j=1,100
     do i=1,100
      B(i,j)=real(A(i,j))
     enddo
    enddo
    END

    SUBROUTINE CopyV3(A,B)
    implicit none
    integer, parameter :: sp = kind(1.0)
    integer, parameter :: dp = kind(1.0d0)
    real(dp), intent(in) :: A(100,100)
    real(sp), intent(out) :: B(100,100)

    B = A
    END