/* psi.c
*
* Psi ( digamma ) function
*
*
* SYNOPSIS :
*
* double x , y , psi ( ) ;
*
* y = psi ( x ) ;
*
*
* DESCRIPTION :
*
* d -
* psi ( x ) = - - ln | ( x )
* dx
*
* is the logarithmic derivative of the gamma function .
* For integer x ,
* n - 1
* -
* psi ( n ) = - EUL + > 1 / k .
* -
* k = 1
*
* This formula is used for 0 < n < = 10 . If x is negative , it
* is transformed to a positive argument by the reflection
* formula psi ( 1 - x ) = psi ( x ) + pi cot ( pi x ) .
* For general positive x , the argument is made greater than 10
* using the recurrence psi ( x + 1 ) = psi ( x ) + 1 / x .
* Then the following asymptotic expansion is applied :
*
* inf . B
* - 2 k
* psi ( x ) = log ( x ) - 1 / 2 x - > - - - - - - -
* - 2 k
* k = 1 2 k x
*
* where the B2k are Bernoulli numbers .
*
* ACCURACY :
* Relative error ( except absolute when | psi | < 1 ) :
* arithmetic domain # trials peak rms
* DEC 0 , 30 2500 1 . 7 e - 16 2 . 0 e - 17
* IEEE 0 , 30 30000 1 . 3 e - 15 1 . 4 e - 16
* IEEE - 30 , 0 40000 1 . 5 e - 15 2 . 2 e - 16
*
* ERROR MESSAGES :
* message condition value returned
* psi singularity x integer < = 0 MAXNUM
*/
/*
Cephes Math Library Release 2 . 8 : June , 2000
Copyright 1984 , 1987 , 1992 , 2000 by Stephen L . Moshier
*/
#include "mconf.h"
#ifdef UNK
static double A[] = {
8 .33333333333333333333 E-2 ,
-2 .10927960927960927961 E-2 ,
7 .57575757575757575758 E-3 ,
-4 .16666666666666666667 E-3 ,
3 .96825396825396825397 E-3 ,
-8 .33333333333333333333 E-3 ,
8 .33333333333333333333 E-2
};
#endif
#ifdef DEC
static unsigned short A[] = {
0037252 ,0125252 ,0125252 ,0125253 ,
0136654 ,0145314 ,0126312 ,0146255 ,
0036370 ,0037017 ,0101740 ,0174076 ,
0136210 ,0104210 ,0104210 ,0104211 ,
0036202 ,0004040 ,0101010 ,0020202 ,
0136410 ,0104210 ,0104210 ,0104211 ,
0037252 ,0125252 ,0125252 ,0125253
};
#endif
#ifdef IBMPC
static unsigned short A[] = {
0 x5555,0 x5555,0 x5555,0 x3fb5,
0 x5996,0 x9599,0 x9959,0 xbf95,
0 x1f08,0 xf07c,0 x07c1,0 x3f7f,
0 x1111,0 x1111,0 x1111,0 xbf71,
0 x0410,0 x1041,0 x4104,0 x3f70,
0 x1111,0 x1111,0 x1111,0 xbf81,
0 x5555,0 x5555,0 x5555,0 x3fb5
};
#endif
#ifdef MIEEE
static unsigned short A[] = {
0 x3fb5,0 x5555,0 x5555,0 x5555,
0 xbf95,0 x9959,0 x9599,0 x5996,
0 x3f7f,0 x07c1,0 xf07c,0 x1f08,
0 xbf71,0 x1111,0 x1111,0 x1111,
0 x3f70,0 x4104,0 x1041,0 x0410,
0 xbf81,0 x1111,0 x1111,0 x1111,
0 x3fb5,0 x5555,0 x5555,0 x5555
};
#endif
#define EUL 0 .57721566490153286061
#ifdef ANSIPROT
extern double floor ( double );
extern double log ( double );
extern double tan ( double );
extern double polevl ( double , void *, int );
#else
double floor(), log(), tan(), polevl();
#endif
extern double PI, MAXNUM;
double psi(x)
double x;
{
double p, q, nz, s, w, y, z;
int i, n, negative;
negative = 0 ;
nz = 0 .0 ;
if ( x <= 0 .0 )
{
negative = 1 ;
q = x;
p = floor(q);
if ( p == q )
{
mtherr( "psi" , SING );
return ( MAXNUM );
}
/* Remove the zeros of tan(PI x)
* by subtracting the nearest integer from x
*/
nz = q - p;
if ( nz != 0 .5 )
{
if ( nz > 0 .5 )
{
p += 1 .0 ;
nz = q - p;
}
nz = PI/tan(PI*nz);
}
else
{
nz = 0 .0 ;
}
x = 1 .0 - x;
}
/* check for positive integer up to 10 */
if ( (x <= 10 .0 ) && (x == floor(x)) )
{
y = 0 .0 ;
n = x;
for ( i=1 ; i<n; i++ )
{
w = i;
y += 1 .0 /w;
}
y -= EUL;
goto done;
}
s = x;
w = 0 .0 ;
while ( s < 10 .0 )
{
w += 1 .0 /s;
s += 1 .0 ;
}
if ( s < 1 .0 e17 )
{
z = 1 .0 /(s * s);
y = z * polevl( z, A, 6 );
}
else
y = 0 .0 ;
y = log(s) - (0 .5 /s) - y - w;
done:
if ( negative )
{
y -= nz;
}
return (y);
}
Messung V0.5 in Prozent C=99 H=87 G=93
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-18)
¤
*© Formatika GbR, Deutschland