1 /*							spence.c
2  *
3  *	Dilogarithm
4  *
5  *
6  *
7  * SYNOPSIS:
8  *
9  * double x, y, spence();
10  *
11  * y = spence( x );
12  *
13  *
14  *
15  * DESCRIPTION:
16  *
17  * Computes the integral
18  *
19  *                    x
20  *                    -
21  *                   | | log t
22  * spence(x)  =  -   |   ----- dt
23  *                 | |   t - 1
24  *                  -
25  *                  1
26  *
27  * for x >= 0.  A rational approximation gives the integral in
28  * the interval (0.5, 1.5).  Transformation formulas for 1/x
29  * and 1-x are employed outside the basic expansion range.
30  *
31  *
32  *
33  * ACCURACY:
34  *
35  *                      Relative error:
36  * arithmetic   domain     # trials      peak         rms
37  *    IEEE      0,4         30000       3.9e-15     5.4e-16
38  *    DEC       0,4          3000       2.5e-16     4.5e-17
39  *
40  *
41  */
42 
43 /*							spence.c */
44 
45 
46 /*
47 Cephes Math Library Release 2.1:  January, 1989
48 Copyright 1985, 1987, 1989 by Stephen L. Moshier
49 Direct inquiries to 30 Frost Street, Cambridge, MA 02140
50 */
51 
52 #include "mconf.h"
53 #include "cephes.h"
54 
55 #ifdef UNK
56 static double A[8] = {
57   4.65128586073990045278E-5,
58   7.31589045238094711071E-3,
59   1.33847639578309018650E-1,
60   8.79691311754530315341E-1,
61   2.71149851196553469920E0,
62   4.25697156008121755724E0,
63   3.29771340985225106936E0,
64   1.00000000000000000126E0,
65 };
66 static double B[8] = {
67   6.90990488912553276999E-4,
68   2.54043763932544379113E-2,
69   2.82974860602568089943E-1,
70   1.41172597751831069617E0,
71   3.63800533345137075418E0,
72   5.03278880143316990390E0,
73   3.54771340985225096217E0,
74   9.99999999999999998740E-1,
75 };
76 #endif
77 #ifdef DEC
78 static unsigned short A[32] = {
79 0034503,0013315,0034120,0157771,
80 0036357,0135043,0016766,0150637,
81 0037411,0007533,0005212,0161475,
82 0040141,0031563,0023217,0120331,
83 0040455,0104461,0007002,0155522,
84 0040610,0034434,0065721,0120465,
85 0040523,0006674,0105671,0054427,
86 0040200,0000000,0000000,0000000,
87 };
88 static unsigned short B[32] = {
89 0035465,0021626,0032367,0144157,
90 0036720,0016326,0134431,0000406,
91 0037620,0161024,0133701,0120766,
92 0040264,0131557,0152055,0064512,
93 0040550,0152424,0051166,0034272,
94 0040641,0006233,0014672,0111572,
95 0040543,0006674,0105671,0054425,
96 0040200,0000000,0000000,0000000,
97 };
98 #endif
99 #ifdef IBMPC
100 static unsigned short A[32] = {
101 0x1bff,0xa70a,0x62d9,0x3f08,
102 0xda34,0x63be,0xf744,0x3f7d,
103 0x5c68,0x6151,0x21eb,0x3fc1,
104 0xf41b,0x64d1,0x266e,0x3fec,
105 0x5b6a,0x21c0,0xb126,0x4005,
106 0x3427,0x8d7a,0x0723,0x4011,
107 0x2b23,0x9177,0x61b7,0x400a,
108 0x0000,0x0000,0x0000,0x3ff0,
109 };
110 static unsigned short B[32] = {
111 0xf90e,0xc69e,0xa472,0x3f46,
112 0x2021,0xd723,0x039a,0x3f9a,
113 0x343f,0x96f8,0x1c42,0x3fd2,
114 0xad29,0xfa85,0x966d,0x3ff6,
115 0xc717,0x8a4e,0x1aa2,0x400d,
116 0x526f,0x6337,0x2193,0x4014,
117 0x2b23,0x9177,0x61b7,0x400c,
118 0x0000,0x0000,0x0000,0x3ff0,
119 };
120 #endif
121 #ifdef MIEEE
122 static unsigned short A[32] = {
123 0x3f08,0x62d9,0xa70a,0x1bff,
124 0x3f7d,0xf744,0x63be,0xda34,
125 0x3fc1,0x21eb,0x6151,0x5c68,
126 0x3fec,0x266e,0x64d1,0xf41b,
127 0x4005,0xb126,0x21c0,0x5b6a,
128 0x4011,0x0723,0x8d7a,0x3427,
129 0x400a,0x61b7,0x9177,0x2b23,
130 0x3ff0,0x0000,0x0000,0x0000,
131 };
132 static unsigned short B[32] = {
133 0x3f46,0xa472,0xc69e,0xf90e,
134 0x3f9a,0x039a,0xd723,0x2021,
135 0x3fd2,0x1c42,0x96f8,0x343f,
136 0x3ff6,0x966d,0xfa85,0xad29,
137 0x400d,0x1aa2,0x8a4e,0xc717,
138 0x4014,0x2193,0x6337,0x526f,
139 0x400c,0x61b7,0x9177,0x2b23,
140 0x3ff0,0x0000,0x0000,0x0000,
141 };
142 #endif
143 
144 extern double PI, MACHEP;
145 
spence(x)146 double spence(x)
147 double x;
148 {
149 double w, y, z;
150 int flag;
151 
152 if( x < 0.0 )
153 	{
154 	mtherr( "spence", DOMAIN );
155 	return(0.0);
156 	}
157 
158 if( x == 1.0 )
159 	return( 0.0 );
160 
161 if( x == 0.0 )
162 	return( PI*PI/6.0 );
163 
164 flag = 0;
165 
166 if( x > 2.0 )
167 	{
168 	x = 1.0/x;
169 	flag |= 2;
170 	}
171 
172 if( x > 1.5 )
173 	{
174 	w = (1.0/x) - 1.0;
175 	flag |= 2;
176 	}
177 
178 else if( x < 0.5 )
179 	{
180 	w = -x;
181 	flag |= 1;
182 	}
183 
184 else
185 	w = x - 1.0;
186 
187 
188 y = -w * polevl( w, A, 7) / polevl( w, B, 7 );
189 
190 if( flag & 1 )
191 	y = (PI * PI)/6.0  - log(x) * log(1.0-x) - y;
192 
193 if( flag & 2 )
194 	{
195 	z = log(x);
196 	y = -0.5 * z * z  -  y;
197 	}
198 
199 return( y );
200 }
201