Hello,
Is erf finction (integral of gaussian) available in pgf90?
Should I link it to some library?
Thanks,
Mark
Hi Mark,
erf is in libm, you can like to libm. You will need to write an interface for it.
Hongyon
Hi Hongyon,
I don’t have libm.a in
$PGI/linux86/6.2/lib
Should I have one?
Thanks,
Mark
Hi,
It is system library. Link to -lm. It is in /usr/lib,lib64/libm.a.
Hongyon
Hi again,
I added
INTERFACE
FUNCTION erf(r)
REAL:: erf,r
END FUNCTION erf
END INTERFACE
in the routine
but
PRINT *,erf(100.)
gives
0.000000000000000
What is wrong?
Thanks,
Mark
Hi,
Do you have access to GAUSSIAN source? There should be example in their source under bsd directory. I don’t think you need to write that Fortran Interface.
Hongyon
Yes, it does not make difference if I do the INTERFACE
for erf or just do REAL :: erf.
In both cases I get erf(100.)=0. and erfc(100.)=1.
There is description of erf, erfc in libm at
http://docsrv.sco.com:507/en/tools/ccs_libm.html
I can’t find the code for erf. I checked under /usr/src, don’t have dir bsd
I have to make the code compatible for different compilers and cannot reconcile pgf90 with e.g. ifort which gives correct
values.
Mark
Hi,
I am not talking about erf source. I mean GAUSSIAN source code. Are you not trying to compile GAUSSIAN? They port erf already into their source code.
Hongyon
Here is example on how to do interface for C function pass argument by value:
program testme
INTERFACE
real8 FUNCTION erfc(r)
real8 r
END FUNCTION erfc
real FUNCTION erf(r)
real r
END FUNCTION erf
END INTERFACE
print *, erf(100.)
print *, erfc(100.0d0)
end
Hongyon
Hi,
I don’t quite know what you mean by “compiling GAUSSIAN source”. I link my code with libm.a with -lm. That does not give any errors and other math functions work fine.
I need to declare erf as real as otherwise it is undeclared variable
Mark
My mistake. You first mentioned about gaussian and I thought you were trying to compile gaussian code.
Hongyon
I must apologize for the confusion. It turned out that we do have erf function in our runtime. You can just call it directly.
Please ignore my example on the interface above.
program test
print *, erf(100.0)
end
No need to link to -lm, the driver handles that already.
Hongyon
ok, thanks. Can you help with explaining that:
program test
IMPLICIT NONE
REAL :: erf,a=100.
PRINT *, erf(a)
end
pgf90 -g -C -byteswapio -Mfree -Ktrap=fp test.f90 /
-o test.x
% test.x
1.000000
pgf90 -g -C -byteswapio -Mfree -r8 -Ktrap=fp test.f90 /
-o test.x
% test.x
0.000000000000000
Mark
Hi,
erf is a float function and takes float as argument. When you compile with -r8, 100.0 in main program becomes real*8. As you know fortran passes argument address, so our erf which takes float as argument takes 32-bit only. Hence, argument becomes 0 in callee.
There are 2 ways to fix this:
1)We have derf for double precision.
Please call derf for double precision version. Example:
program test
real*8 derf
print *, derf(100.0d0)
end
2)Back to use an interface to call erf directly, I wrote a small example below.
% cat abc.f90
program testme
real*8 erfx
print , erfx(100.0d0)
end
% cat a.c
#include <math.h>
double erfx_(double a) {
return erf(*a);
}
% pgf90 abc.f90 a.c
abc.f90:
a.c:
% a.out
1.000000000000000
% pgf90 abc.f90 a.c -r8
abc.f90:
a.c:
% a.out
1.000000000000000
Hope this helps,
Hongyon