Reputation: 493
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?
Upvotes: 1
Views: 697
Reputation: 37228
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.
Upvotes: 1