erf(x) and math.h

后端 未结 4 582
闹比i
闹比i 2021-01-13 06:46

According to this site the error function erf(x) comes from math.h. But actually looking in math.h, it isn\'t there, and gcc cannot compile the following test program while

相关标签:
4条回答
  • 2021-01-13 07:22

    You need to link the math library (libm) too:

    $ gcc mathHTest.c -lm
    

    All of the normal math library functions are actually there, and not in the standard C library (libc).

    According to my tests, g++ does include libm automatically, but gcc doesn't.

    0 讨论(0)
  • 2021-01-13 07:24

    I had the same problem using gcc from cygwin on a x86 processor. The "-lm" library include parameter (after the file list!) worked perfectly.

    0 讨论(0)
  • 2021-01-13 07:45

    'erf' is actually declared in bits/mathcalls.h, which is #included by math.h. The actual declaration is heavily obscured by macro magic to make it do the right thing for both C and C++

    0 讨论(0)
  • 2021-01-13 07:48

    I had a similar problem and needed to find the exact definition of erf so let me expand on this. As said by Chris Dodd the function is declared in bits/mathcalls.h which is included by maths.h.

    bits/mathcalls.h:

    ...
    #if defined __USE_MISC || defined __USE_XOPEN || defined __USE_ISOC99
    __BEGIN_NAMESPACE_C99
    /* Error and gamma functions.  */
    __MATHCALL (erf,, (_Mdouble_));
    __MATHCALL (erfc,, (_Mdouble_));
    __MATHCALL (lgamma,, (_Mdouble_));
    __END_NAMESPACE_C99
    #endif
    ...
    

    Macro magic expands __MATHCALL (erf,, (_Mdouble_)); to

    extern double erf (double) throw (); extern double __erf (double) throw ();
    

    The actual code is in libm.a or libm.so (gcc -lm):

    $ nm /usr/lib/libm.a
    ...
    s_erf.o:
    00000400 T __erf
    00000000 T __erfc
             U __ieee754_exp
    00000400 W erf
    00000000 W erfc
    ...
    

    The source can be obtained from the gnu libc webpage. For a rough idea on the actual implementation here a few lines of the source:

    sysdeps/ieee754/dbl-64/s_erf.c:

    /* double erf(double x)
     * double erfc(double x)
     *                           x
     *                    2      |\
     *     erf(x)  =  ---------  | exp(-t*t)dt
     *                 sqrt(pi) \|
     *                           0
     *
     *     erfc(x) =  1-erf(x)
     *  Note that
     *              erf(-x) = -erf(x)
     *              erfc(-x) = 2 - erfc(x)
     *
     * Method:
     *      1. For |x| in [0, 0.84375]
     *          erf(x)  = x + x*R(x^2)
     *          erfc(x) = 1 - erf(x)           if x in [-.84375,0.25]
     *                  = 0.5 + ((0.5-x)-x*R)  if x in [0.25,0.84375]
     *         where R = P/Q where P is an odd poly of degree 8 and
     *         Q is an odd poly of degree 10.
     *                                               -57.90
     *                      | R - (erf(x)-x)/x | <= 2
     *
     *
     *         Remark. The formula is derived by noting
     *          erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....)
     *         and that
     *          2/sqrt(pi) = 1.128379167095512573896158903121545171688
     *         is close to one. The interval is chosen because the fix
     *         point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is
     *         near 0.6174), and by some experiment, 0.84375 is chosen to
     *         guarantee the error is less than one ulp for erf.
     *
     *      2. For |x| in [0.84375,1.25], let s = |x| - 1, and     
     ...
    
    0 讨论(0)
提交回复
热议问题