erf function

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®

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®
real
8 r

END FUNCTION erfc

real FUNCTION erf®
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