gfortran does not find symbol fabsq_ in libquadmath

641 views Asked by At

I'm trying to get quad precision to work with my FORTRAN code. I have to replace some intrinsic functions by those in libquadmath, i.e. the dabs function by fabsq.

Unfortunately, if I compile the following test function

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

I obtain some error at compile time

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

but

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

gives me some value greater than 0. What's going wrong here?

2

There are 2 answers

1
janneb On BEST ANSWER

In general, things like "dabs" were from the days before type-generic intrinsics. In particular, there is no corresponding "qabs/absq" or whatever you might want to call it, but rather only the type-generic "abs" which is then resolved to the correct library symbol at compile time.

Secondly, your choice of "abs" to test with is a bit unfortunate, since it turns out the compiler expands that inline so you'll never see any function calls. A better choice is e.g. "sin". Consider the example code


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

Compiling this with "gfortran -c -O2 -S qm.f90", and inspecting the generated code one sees:


        .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

So one sees that the call to "abs" is handled by inline code, no need to call some external function. OTOH, the call to the generic "sin()" function is resolved to the "sinq" function, which is a quad precision version of the sine function that you can find in libquadmath. No need to try to call "sinq" explicitly, in fact it wouldn't work.

Note also the usage of "real(16)", which is unportable, but a quick-and-dirty way of getting quad precision reals in gfortran.

PS: Another thing, with gfortran there is no need to explicitly link with libquadmath, it's automatically included, just like libgfortran, libm, etc.

1
lhf On

Try gfortran -o test.out test.f -lquadmath.