gfortran 在 libquadmath 中找不到符号 fabsq_

gfortran does not find symbol fabsq_ in libquadmath

我正在尝试获得四精度来处理我的 FORTRAN 代码。我必须用 libquadmath 中的函数替换一些内部函数,即 fabsq 的 dabs 函数。

不幸的是,如果我编译下面的测试函数

  program test
  integer dp
  parameter (dp=10)
  real(kind=dp) a
  a= -5.0_dp
  a=fabsq(a)
  write(*,*) "abs(a)", a
  end program

编译时出现一些错误

gfortran -lquadmath -o test.out  test.f
/tmp/ccwhLFWr.o: In function `MAIN__':
test.f:(.text+0x2e): undefined reference to `fabsq_'
collect2: error: ld returned 1 exit status

但是

nm /usr/lib64/gcc/x86_64-suse-linux/4.8/libquadmath.a | grep -c fabsq

给我一些大于 0 的值。这里出了什么问题?

尝试gfortran -o test.out test.f -lquadmath

一般来说,像 "dabs" 这样的东西是在类型泛型内在函数出现之前的。特别是,没有相应的 "qabs/absq" 或任何您可能想要调用它的东西,而只有类型泛型 "abs",然后在编译时解析为正确的库符号。

其次,您选择 "abs" 进行测试有点不幸,因为事实证明编译器会扩展该内联,因此您永远不会看到任何函数调用。更好的选择是例如"sin"。考虑示例代码


function my_sintest(a)
  real(16) :: a, my_sintest
  my_sintest = sin(a)
end function my_sintest

function my_abstest(a)
  real(16) :: a, my_abstest
  my_abstest = abs(a)
end function my_abstest

用 "gfortran -c -O2 -S qm.f90" 编译它,并检查生成的代码可以看到:


        .file   "qm.f90"
        .text
        .p2align 4,,15
        .globl  my_sintest_
        .type   my_sintest_, @function
my_sintest_:
.LFB0:
        .cfi_startproc
        movdqa  (%rdi), %xmm0
        jmp     sinq
        .cfi_endproc
.LFE0:
        .size   my_sintest_, .-my_sintest_
        .p2align 4,,15
        .globl  my_abstest_
        .type   my_abstest_, @function
my_abstest_:
.LFB1:
        .cfi_startproc
        movdqa  (%rdi), %xmm0
        pand    .LC0(%rip), %xmm0
        ret
        .cfi_endproc
.LFE1:
        .size   my_abstest_, .-my_abstest_
        .section        .rodata.cst16,"aM",@progbits,16
        .align 16
.LC0:
        .long   4294967295
        .long   4294967295
        .long   4294967295
        .long   2147483647
        .ident  "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
        .section        .note.GNU-stack,"",@progbits

所以可以看出对"abs"的调用是由内联代码处理的,不需要调用一些外部函数。 OTOH,对通用 "sin()" 函数的调用被解析为 "sinq" 函数,它是正弦函数的四精度版本,您可以在 libquadmath 中找到它。无需尝试显式调用 "sinq",实际上它不会起作用。

另请注意 "real(16)" 的用法,它不可移植,但却是在 gfortran 中获取四精度实数的一种快速而肮脏的方法。

PS:另一件事,对于 gfortran,无需显式 link 与 libquadmath,它会自动包含,就像 libgfortran、libm 等