【问题标题】:Returning a quad precision variable from fortran从 fortran 返回四精度变量
【发布时间】:2020-05-23 20:21:49
【问题描述】:

所以我试图从 fortran 返回一个四精度(128 位)值并在 python 中对其进行操作。但我得到的返回值似乎与我的预期不符。

Fortran 代码:

module testquad

    implicit none

    integer, parameter :: qp = selected_real_kind(p=30)

    contains

    real(qp) function func_quad()
        real(qp) :: x

        x = 5_qp

        write(*,*) x,sizeof(x)
        write(*,'(B128)') x

        func_quad = x

    end function func_quad

end module testquad

编译:

gfortran -fpic -shared -fdump-tree-all -o libtestquad.so testQuad.f90

Python 方面我使用 c_ubyte*16 数组来保存返回值(因为 ctypes 不公开 128 位四元类型)

import ctypes

lib = ctypes.CDLL('./libtestquad.so')

f = getattr(lib, '__testquad_MOD_func_quad')

f.argtypes = []
f.restype = ctypes.c_ubyte*16

result = f()

bb=[]
for i in bytearray(result)[::-1]:
    bb.append(bin(i)[2:].rjust(8,'0'))

bb=''.join(bb)
print(bb)

运行代码调用fortran函数的输出是:

5.00000000000000000000000000000000000                         16
 1000000000000010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

所以我们得到了 5,我们看到大小是 16(所以我得到一个四边形数)

gfortran 似乎跳过了打印符号位的第一个 0/​​1。但是我们可以看到它在位模式中有 3 个 1,其余都是 0。

按照quad上的wikipedia page然后我们有

sign = 0 (gfortran misses this)
exponent = 100000000000001
significand = 0100....

将其转换为:

a = 2**(int('100000000000001',base=2)-16383) # 4
b = 1 + 0/2**1 + 1/2**2 + 0/2**3 .... # 1.25
print(a * b)
5

所以 gfortran 正如预期的那样打印数字 5 的正确位模式。

但是,在 python 中为结果打印出一个位模式:

00000000000000000111111110110001001111101010010111111001001010000000000000000000000000000000000000000000000000000000000000000000

这显然是不同的。

我搞砸了打印位模式吗?

gfortran 如何返回 __float128 是否有什么特别之处,这意味着我不能将其解释为 16 个字节?

ctypes 处理返回的 c_bytes 数组是否有什么特别之处?

还有什么?

附加:

使用 -fdump-tree-all 并查看我们看到的 .original 文件:

func_quad ()
{
  real(kind=16) x;
  real(kind=16) __result_func_quad;

  x = 5.0e+0;
  // snip write statement code
  __result_func_quad = x;
  return __result_func_quad;
}

所以似乎没有什么“特别”发生,变量没有被分配给结构/指针/数组来处理四边形类型。

【问题讨论】:

  • 当然,gfortran 不打印 +5 的符号位。根据 Fortran 2018 标准:Bw、Ow 和 Zw 描述符的输出字段由零个或多个前导空格组成,后跟内部值,其形式与二进制、八进制或十六进制常量的数字相同,分别指定相同的位序列,但没有前导零位。 只需打印 -5 的位模式即可显示符号位的前导 1

标签: python fortran ctypes gfortran


【解决方案1】:

看起来我遇到了这个https://stackoverflow.com/a/423479/2270574 答案。这指出您不能将字节数组用于浮点数,因为它未存储在正常的 %eax 寄存器中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-14
    • 2010-12-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多