fortran 如何定义 unsigned short integer

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了fortran 如何定义 unsigned short integer相关的知识,希望对你有一定的参考价值。

请教高手,在fortran 里面如何定义unsigned short integer; short integer; unsigned long integer; signed long integer

unsigned short integer; short integer 变量在fortran中对应的定义方法是:
integer(kind=2):: a
unsigned long integer; signed long integer变量在fortran中对应的定义方法是:
integer(kind=4):: a

necrohan指出我的回答有误,从某个方面来说,他是对的。
但是,我相信楼主提问的目的是混合编程,比如vc调用fortran,这个时候存在数据传递的问题,也就衍生出定义的对应问题。我要回答是就是这个。上面我给的对应的定义在数据传递时应该不会有问题的。

至于要实现类型的“定义域”相同,这个如necrohan所说,无符号类型在fortran中是做不到的,但是我们可以做到放宽定义,并在编写程序时注意数据范围就行了。
参考技术A 实际上Fortran里没有unsigned short和unsigned long类型数据!!!
fortran里的数据都是有符号的
楼上回答部分是正确的,但是无符号类型数据范围正数部分扩大了,在fortran里只能用更长字节的数据表示,否则可能会出错。
C或C++里short是2字节,long是4字节
fortran里用integer(n)的形式,integer(2)和integer(4)分别表示2字节和4字节,只能对应signed类型数据,不能对应unsigned类型数据。本回答被提问者采纳

使用 MPI 和 Fortran 90 发送自定义类型

【中文标题】使用 MPI 和 Fortran 90 发送自定义类型【英文标题】:Send custom type using MPI and Fortran 90 【发布时间】:2015-01-21 16:15:00 【问题描述】:

在我的程序中,我让每个处理器计算一个自定义类型“点”的数组,该数组由 4 个双精度值和 3 个双精度值组成。我现在希望每个处理器将其“点”类型数组发送到主处理器。

我无法理解如何使用 MPI_type 命令发送自定义类型。尤其是“点”类型中的双复精度。据我了解,MPI 没有 MPI_DOUBLE_COMPLEX 类型。

PROGRAM hello
  use mpi
  IMPLICIT NONE
  INTEGER, PARAMETER :: dp = REAL(KIND(0.0D0))
  type point
    sequence
    real(kind=dp) :: x, y, z, w
    double complex :: ex, ey, ez
  end type point
  type(point), dimension(:), allocatable :: my_points
  ...

  if(rank .ne. master) then
    call MPI_SEND(my_points, count, [point?], master, 7, MPI_COMM_WORLD, ierror)
  end if

  ....
END

【问题讨论】:

值得注意的是 DOUBLE COMPLEX 是一个非标准的供应商扩展,而不是标准的 Fortran。我推荐complex(dp) 【参考方案1】:

MPI 标准规定(MPI 2.2 规范中的第 3.2.2 节):

MPI 需要支持这些数据类型,这些数据类型与 Fortran 和 ISO C 的基本数据类型匹配。如果宿主语言具有其他数据类型,则应提供其他 MPI 数据类型: MPI_DOUBLE_COMPLEX 用于声明为 @987654321 类型的 Fortran 中的双精度复数@; ...

至于数据类型的构造,它是这样工作的。首先,声明一个类型为或(只需使用已分配的)的伪二元数组并结合MPI_GET_ADDRESS获取每个字段的地址:

type(point) :: dummy(2)
integer(kind=MPI_ADDRESS_KIND) :: offsets(7)
integer :: ierr

call MPI_GET_ADDRESS(dummy(1)%x,  offsets(1), ierr)
call MPI_GET_ADDRESS(dummy(1)%y,  offsets(2), ierr)
call MPI_GET_ADDRESS(dummy(1)%z,  offsets(3), ierr)
call MPI_GET_ADDRESS(dummy(1)%w,  offsets(4), ierr)
call MPI_GET_ADDRESS(dummy(1)%ex, offsets(5), ierr)
call MPI_GET_ADDRESS(dummy(1)%ey, offsets(6), ierr)
call MPI_GET_ADDRESS(dummy(1)%ez, offsets(7), ierr)

offsets 现在包含绝对地址,因此将它们转换为相对于dummy%x 的偏移量:

integer :: i

do i = 2,7
  offsets(i) = offsets(i) - offsets(1)
end do
! dummy%x serves as base address, therefore set the offset to 0
offsets(1) = 0

下一步是自己构造 MPI 数据类型:

integer :: oldtypes(7), lengths(7)
integer :: point_type0

! dummy%x
oldtypes(1) = MPI_DOUBLE_PRECISION
lengths(1) = 1
! dummy%y
oldtypes(2) = MPI_DOUBLE_PRECISION
lengths(2) = 1
! dummy%z
oldtypes(3) = MPI_DOUBLE_PRECISION
lengths(3) = 1
! dummy%w
oldtypes(4) = MPI_DOUBLE_PRECISION
lengths(4) = 1
! dummy%ex
oldtypes(5) = MPI_DOUBLE_COMPLEX
lengths(5) = 1
! dummy%ey
oldtypes(6) = MPI_DOUBLE_COMPLEX
lengths(6) = 1
! dummy%ez
oldtypes(7) = MPI_DOUBLE_COMPLEX
lengths(7) = 1

call MPI_TYPE_CREATE_STRUCT(7, lengths, offsets, oldtypes, point_type0, ierr)

(注意:此代码假定real(kind=KIND(0.0D0)) 实际上是DOUBLE PRECISION

那时你几乎准备好了。 point_type0 可以提交,然后用于发送自定义类型的单个元素,但它可能不适用于数组。原因是编译器可能会在类型的末尾或开头添加填充。 MPI 允许显式设置数据类型的范围。为此,首先确定应该存在的实际范围:

integer(kind=MPI_ADDRESS_KIND) :: extent

! Reuse the offsets array
call MPI_GET_ADDRESS(dummy(1)%x, offsets(1), ierr)
call MPI_GET_ADDRESS(dummy(2)%x, offsets(2), ierr)

extent = offsets(2) - offsets(1)

(这应该清楚为什么需要一个二元素虚拟数组)

现在将点数据类型“调整”到真实范围并提交结果数据类型:

integer :: point_type

call MPI_TYPE_CREATE_RESIZED(point_type0, 0_MPI_ADDRESS_KIND, extent, &
                             point_type, ierr)
call MPI_TYPE_COMMIT(point_type, ierr)

现在你可以使用新注册的类型了:

if(rank .ne. master) then
  call MPI_SEND(my_points(1)%x, count, point_type, &
                master, 7, MPI_COMM_WORLD, ierror)
end if

请注意,第一个数组元素的x 字段是明确给出的。这样做是因为在计算偏移量时使用dummy%x 作为基础。

在您的情况下,上述某些步骤可能不是绝对必要的,因为您有一个序列类型,这可能会阻止编译器对齐字段。尽管如此,始终按照所示方式执行它是一个好主意,因为它既适用于打包类型,也适用于非打包类型。如果类型定义中缺少sequence 语句,则允许编译器以它认为合适的任何顺序存储组件。这没有任何改变,因为即使 dummy%x 不是第一个组件,它之前的组件也只会有负偏移。

【讨论】:

不错。 real(kind=KIND (0.0D0)) 不是按标准保证是DOUBLE PRECISION 吗? 它似乎也可以与call MPI_SEND(my_points, count, point_type, master, 7, MPI_COMM_WORLD, ierror)call MPI_RECV(my_points, count, point_type, from, 7, MPI_COMM_WORLD, status, ierror)一起工作 它可以工作,因为x 是第一个字段,它是一个序列类型。但在一般情况下,如果只给出数组的名称,即如果字段被编译器重新排列,它将不起作用。 @VladimirF,老实说,我对 Fortran 标准的了解非常有限。 MPI 标准规定两者应该是等价的。 MPI 标准中有一些规定可以构建便携式类型,例如MPI_TYPE_CREATE_F90_REAL,但这在实践中似乎没有得到很好的支持。 很好的答案;我们应该指出类似的问题作为 fortran 中 mpi_type_create_struct 的规范答案。

以上是关于fortran 如何定义 unsigned short integer的主要内容,如果未能解决你的问题,请参考以下文章

c++中定义一个buff为unsigned char 型,如何初始化全为0

FORTRAN中如何定义全局变量

fortran 定义全局变量

在Fortran中,在扩展定义中,如何将公共过程设置为私有?

fortran程序如何将两个数组中的元素,放入一个数组?

(C语言)unsigned long类型变量输出时,格式转换说明符应如何定义?