G_numeric: fix evaluation with y == 1
[ginac.git] / check / exam_inifcns_nstdsums.cpp
1 /** @file exam_inifcns_nstdsums.cpp
2  *
3  *  This test routine applies assorted tests on initially known higher level
4  *  functions. */
5
6 /*
7  *  GiNaC Copyright (C) 1999-2011 Johannes Gutenberg University Mainz, Germany
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  */
23
24 #include "ginac.h"
25 using namespace GiNaC;
26
27 #include <iostream>
28 #include <fstream>
29 using namespace std;
30
31
32 ////////////////////////////////////////////////////////////////////////////////
33 ////////////////////////////////////////////////////////////////////////////////
34 //  S exam
35 ////////////////////////////////////////////////////////////////////////////////
36 ////////////////////////////////////////////////////////////////////////////////
37
38
39 /*
40  * The data in the following include file has been produced by the following
41  * Mathematica (V4.1) script:
42  *
43  *
44  *    x={2/10,1,14/10,30/10}
45  *    y={0,3/10,-14/10}
46  *    st = OpenAppend["exam_inifcns_nstdsums_data.raw"]
47  *    $NumberMarks = False
48  *    Do[
49  *      Do[
50  *        Do[Write[st, i]; Write[st,j]; Write[st,x[[k]]+I*y[[l]]];
51  *          Write[st,Chop[N[PolyLog[i,j,x[[k]]+I*y[[l]]],25]]],{i,3},{j,3}], {k,4}],{l,3}]
52  *    Do[
53  *      Do[
54  *        Do[Write[st, i]; Write[st,j]; Write[st,-x[[k]]+I*y[[l]]];
55  *          Write[st,Chop[N[PolyLog[i,j,-x[[k]]+I*y[[l]]],25]]],{i,3},{j,3}], {k,4}], {l,3}]
56  *    Close[st]
57  *
58  *    
59  * and postprocessed by the following shell script
60  *
61  *
62  *    #/bin/sh
63  *    IFS=$'\n'
64  *    cat exam_inifcns_nstdsums_data.raw | sed -e 's/\*\^/E/g' > exam_inifcns_nstdsums_data.raw2
65  *    echo 'const char *data[] = {' > exam_inifcns_nstdsums_data.raw3
66  *    for i in `cat exam_inifcns_nstdsums_data.raw2`; do echo \"$i\",; done >> exam_inifcns_nstdsums_data.raw3
67  *    echo '"-999"};' >> exam_inifcns_nstdsums.h
68  *
69  *
70  */
71 #include "exam_inifcns_nstdsums.h"
72
73
74 // signals end of data
75 const int ENDMARK = -999;
76
77
78 static unsigned inifcns_test_S()
79 {
80         int digitsbuf = Digits;
81         // precision of data
82         Digits = 22;
83         ex prec = 5 * pow(10, -(ex)Digits);
84         
85         unsigned result = 0;
86         
87         int i = 0;
88         while (true) {
89                 ex n(data[i++],symbol());
90                 if (n == ENDMARK) {
91                         break;
92                 }
93                 ex p(data[i++],symbol());
94                 ex x(data[i++],symbol());
95                 ex res(data[i++],symbol());
96                 ex res2 = S(n, p, x).evalf();
97                 if (abs(res-res2) > prec) {
98                         clog << "S(" << n << "," << p << "," << x << ") seems to be wrong:" << endl;
99                         clog << "GiNaC           : " << res2 << endl;
100                         clog << "Reference       : " << res << endl;
101                         clog << "Abs. Difference : " << res2-res << endl;
102                         if (res2 != 0) {
103                                 ex reldiff = abs((res2-res)/res2);
104                                 clog << "Rel. Difference : " << reldiff << endl;
105                         }
106                         result++;
107                 }
108                 if (i % 80) {
109                         cout << "." << flush;
110                 }
111         }
112
113         Digits = digitsbuf;
114
115         return result;
116 }
117
118
119 ////////////////////////////////////////////////////////////////////////////////
120 ////////////////////////////////////////////////////////////////////////////////
121 //  H/Li exam
122 ////////////////////////////////////////////////////////////////////////////////
123 ////////////////////////////////////////////////////////////////////////////////
124
125
126 static unsigned inifcns_test_HLi()
127 {
128         using GiNaC::log;
129         int digitsbuf = Digits;
130         Digits = 17;
131         ex prec = 5 * pow(10, -(ex)Digits);
132         numeric almostone("0.999999999999999999");
133         unsigned result = 0;
134
135         lst res;
136         
137         res.append(H(lst(2,1),numeric(1)/2).hold() - (zeta(3)/8 - pow(log(2),3)/6));
138         res.append(H(lst(2,1,3),numeric(1)/3).hold() - Li(lst(2,1,3),lst(numeric(1)/3,1,1)).hold());
139         res.append(H(lst(2,1,3),numeric(98)/100).hold() - Li(lst(2,1,3),lst(numeric(98)/100,1,1)).hold());
140         res.append(H(lst(2,1,3),numeric(245)/100).hold() - Li(lst(2,1,3),lst(numeric(245)/100,1,1)).hold());
141         res.append(H(lst(4,1,1,1),numeric(1)/3).hold() - S(3,4,numeric(1)/3).hold());
142         res.append(H(lst(4,1,1,1),numeric(98)/100).hold() - S(3,4,numeric(98)/100).hold());
143         res.append(H(lst(4,1,1,1),numeric(245)/100).hold() - S(3,4,numeric(245)/100).hold());
144         res.append(H(lst(2,2,3),almostone).hold() - zeta(lst(2,2,3)));
145         res.append(H(lst(-3,-1,2,1),almostone).hold() - zeta(lst(3,1,2,1),lst(-1,1,-1,1)));
146         res.append(H(lst(-2,1,3),numeric(1)/3).hold() - -Li(lst(2,1,3),lst(-numeric(1)/3,-1,1)).hold());
147         res.append(H(lst(-2,1,3),numeric(98)/100).hold() - -Li(lst(2,1,3),lst(-numeric(98)/100,-1,1)).hold());
148         res.append(H(lst(-2,1,3),numeric(245)/100).hold() - -Li(lst(2,1,3),lst(-numeric(245)/100,-1,1)).hold());
149         res.append(H(lst(-3,1,-2,0,0),numeric(3)/10).hold() - convert_H_to_Li(lst(-3,1,-2,0,0),numeric(3)/10).eval());
150         
151         for (lst::const_iterator it = res.begin(); it != res.end(); it++) {
152                 ex diff = abs((*it).evalf());
153                 if (diff > prec) {
154                         clog << *it << " seems to be wrong: " << diff << endl;
155                         result++;
156                 }
157                 cout << "." << flush;
158         }
159
160         Digits = digitsbuf;
161
162         // conjugate test
163         numeric cdif = ex_to<numeric>(H(lst(2,2,1),5.0-5.0*I) - H(lst(2,2,1),5.0+5.0*I));
164         numeric cadd = ex_to<numeric>(H(lst(2,2,1),5.0-5.0*I) + H(lst(2,2,1),5.0+5.0*I));
165         if ((cdif.real() > prec) || (cadd.imag() > prec)) {
166                 clog << "complex conjugation test of H({2,2,1},5.0-5.0*I) seems to be wrong: " << cdif << " " << cadd << endl;
167                 result++;
168         }
169
170         return result;
171 }
172
173
174 ////////////////////////////////////////////////////////////////////////////////
175 ////////////////////////////////////////////////////////////////////////////////
176 //  zeta exam
177 ////////////////////////////////////////////////////////////////////////////////
178 ////////////////////////////////////////////////////////////////////////////////
179
180
181 static unsigned inifcns_test_zeta()
182 {
183         int digitsbuf = Digits;
184         
185         unsigned result = 0;
186
187         lst res;
188         
189         res.append(zeta(lst(2,1)) - zeta(3));
190         res.append(zeta(lst(2,1,1,1,1)) - zeta(6));
191         res.append(zeta(lst(6,3)) - (zeta(9)*83/2 - zeta(2)*zeta(7)*21 - zeta(2)*zeta(2)*zeta(5)*12/5));
192         res.append(zeta(lst(4,2,3)) - (-zeta(9)*59 + zeta(2)*zeta(7)*28 + pow(zeta(2),2)*zeta(5)*4 -
193                                        pow(zeta(3),3)/3 + pow(zeta(2),3)*zeta(3)*8/21));
194         res.append(zeta(lst(3,1,3,1,3,1,3,1)) - (2*pow(Pi,16)/factorial(18)));
195         res.append(zeta(lst(2),lst(-1)) - -zeta(2)/2);
196         res.append(zeta(lst(1,2),lst(-1,1)) - (-zeta(3)/4 - zeta(lst(1),lst(-1))*zeta(2)/2));
197         res.append(zeta(lst(2,1,1),lst(-1,-1,1)) - (-pow(zeta(2),2)*23/40 - pow(zeta(lst(1),lst(-1)),2)*zeta(2)*3/4
198                                                     - zeta(lst(3,1),lst(-1,1))*3/2 - zeta(lst(1),lst(-1))*zeta(3)*21/8));
199         
200         for (lst::const_iterator it = res.begin(); it != res.end(); it++) {
201                 Digits = 17;
202                 ex prec = 5 * pow(10, -(ex)Digits);
203                 ex diff = abs((*it).evalf());
204                 if (diff > prec) {
205                         clog << *it << " seems to be wrong: " << diff << endl;
206                         clog << "Digits: " << Digits << endl;
207                         result++;
208                 }
209                 cout << "." << flush;
210                 Digits = 40;
211                 prec = 5 * pow(10, -(ex)Digits);
212                 diff = abs((*it).evalf());
213                 if (diff > prec) {
214                         clog << *it << " seems to be wrong: " << diff << endl;
215                         clog << "Digits: " << Digits << endl;
216                         result++;
217                 }
218                 cout << "." << flush;
219         }
220
221         Digits = digitsbuf;
222
223         return result;
224 }
225
226
227 ////////////////////////////////////////////////////////////////////////////////
228 ////////////////////////////////////////////////////////////////////////////////
229 //  H/Li exam
230 ////////////////////////////////////////////////////////////////////////////////
231 ////////////////////////////////////////////////////////////////////////////////
232
233
234 static unsigned inifcns_test_LiG()
235 {
236         int digitsbuf = Digits;
237         Digits = 17;
238         ex prec = 5 * pow(10, -(ex)Digits);
239         numeric almostone("0.99999999999999999999");
240         unsigned result = 0;
241
242         lst res;
243         
244         res.append(Li(lst(4), lst(6)).hold() - Li(4, 6.0));
245         res.append(G(lst(0,0,5.0,0,2.0,0,0,0,3.0),0.5).hold()
246                    + Li(lst(3,2,4), lst(numeric(1,10), numeric(5,2), numeric(2,3))));
247         res.append(Li(lst(2,1,1), lst(almostone, almostone, almostone)) - zeta(lst(2,1,1)));
248
249         // check Li_{1,1} against known expression
250         symbol x("x"), y("y");
251         ex eps = 1e-30*I;
252         ex s1 = Li(lst(1,1),lst(x,y));
253         ex s2 = log(1-1/x/y-eps)*log((1-1/x-eps)/(1/x/y-1/x)) + Li(2,(1-1/x/y-eps)/(1/x-1/x/y))
254                         - log(-1/x/y-eps)*log((-1/x-eps)/(1/x/y-1/x)) - Li(2,(-1/x/y-eps)/(1/x-1/x/y))
255                         - log(-1/x/y-eps)*log(1-1/x-eps) + log(-1/x/y-eps)*log(-1/x-eps);
256         res.append(s1.subs(lst(x==numeric(1)/2, y==3)) - s2.subs(lst(x==numeric(1)/2, y==3)));
257         res.append(s1.subs(lst(x==numeric(3)/2, y==numeric(1)/2)) - s2.subs(lst(x==numeric(3)/2, y==numeric(1)/2)));
258         res.append(s1.subs(lst(x==2, y==numeric(4)/5)) - s2.subs(lst(x==2, y==numeric(4)/5)));
259
260         // shuffle and quasi-shuffle identities
261         res.append(G(lst(0,0.2),1).hold() * G(lst(0.5),1).hold() - G(lst(0.5,0,0.2),1).hold()
262                         - G(lst(0,0.5,0.2),1).hold() - G(lst(0,0.2,0.5),1).hold());
263         res.append(G(lst(0,0.5),1).hold() * G(lst(0.6),1).hold() - G(lst(0,0.5,0.5*0.6),1).hold()
264                         - G(lst(0.6,0,0.5*0.6),1).hold() + G(lst(0,0,0.5*0.6),1).hold());
265         res.append(Li(lst(2),lst(numeric(1,5))).hold() * Li(lst(3),lst(7)).hold() - Li(lst(2,3),lst(numeric(1,5),7)).hold()
266                         - Li(lst(3,2),lst(7,numeric(1,5))).hold() - Li(lst(5),lst(numeric(7,5))).hold());
267         symbol a1, a2, a3, a4;
268         res.append((G(lst(a1,a2),1) * G(lst(a3,a4),1) - G(lst(a1,a2,a3,a4),1)
269                         - G(lst(a1,a3,a2,a4),1) - G(lst(a3,a1,a2,a4),1)
270                         - G(lst(a1,a3,a4,a2),1) - G(lst(a3,a1,a4,a2),1) - G(lst(a3,a4,a1,a2),1))
271                                 .subs(lst(a1==numeric(1)/10, a2==numeric(3)/10, a3==numeric(7)/10, a4==5)));
272         res.append(G(lst(-0.009),1).hold() * G(lst(-8,1.4999),1).hold() - G(lst(-0.009,-8,1.4999),1).hold()
273                         - G(lst(-8,-0.009,1.4999),1).hold() - G(lst(-8,1.4999,-0.009),1).hold());
274         res.append(G(lst(sqrt(numeric(1)/2)+I*sqrt(numeric(1)/2)),1).hold() * G(lst(1.51,-0.999),1).hold()
275                         - G(lst(sqrt(numeric(1)/2)+I*sqrt(numeric(1)/2),1.51,-0.999),1).hold()
276                         - G(lst(1.51,sqrt(numeric(1)/2)+I*sqrt(numeric(1)/2),-0.999),1).hold()
277                         - G(lst(1.51,-0.999,sqrt(numeric(1)/2)+I*sqrt(numeric(1)/2)),1).hold());
278         // checks for hoelder convolution which is used if one argument has a distance to one smaller than 0.01 
279         res.append(G(lst(0, 1.2, 1, 1.01), 1).hold() - G(lst(0, 1.2, 1, numeric("1.009999999999999999")), 1).hold());
280
281         for (lst::const_iterator it = res.begin(); it != res.end(); it++) {
282                 ex diff = abs((*it).evalf());
283                 if (diff > prec) {
284                         clog << *it << " seems to be wrong: " << diff << endl;
285                         result++;
286                 }
287                 cout << "." << flush;
288         }
289
290         return result;
291 }
292
293
294 ////////////////////////////////////////////////////////////////////////////////
295 ////////////////////////////////////////////////////////////////////////////////
296 //  legacy exam - checking for historical bugs
297 ////////////////////////////////////////////////////////////////////////////////
298 ////////////////////////////////////////////////////////////////////////////////
299
300
301 static unsigned inifcns_test_legacy()
302 {
303         Digits = 17;
304         ex prec = 5 * pow(10, -(ex)Digits);
305
306         unsigned result = 0;
307
308         ex r1 = zeta(lst(1,1,1,1,1,1),lst(-1,-1,-1,1,1,1));
309         if ((r1.evalf() - numeric("-0.0012588769028204890704")) > prec) {
310                 clog << "zeta({1,1,1,1,1,1},{-1,-1,-1,1,1,1}) seems to be wrong." << endl;
311                 result++;
312         }
313
314         ex x1 = exp(2*Pi*I/13).evalf();
315         ex x2 = exp(24*Pi*I/13).evalf();
316         ex r2 = Li(lst(2),lst(x1)).hold().evalf();
317         ex r3 = Li(lst(2),lst(x2)).hold().evalf();
318         if ( abs(r2-conjugate(r3)) > prec ) {
319                 clog << "Legacy test 2 seems to be wrong." << endl;
320                 result++;
321         }
322
323         ex x3 = exp(5*Pi*I/3).evalf();
324         ex r4 = Li(lst(3),lst(x3)).hold().evalf();
325         if ( abs(r4 - numeric("0.40068563438653142847-0.95698384815740185713*I")) > prec ) {
326                 clog << "Legacy test 3 seems to be wrong." << endl;
327                 result++;
328         }
329
330         Digits = 100;
331         prec = 5 * pow(10, -(ex)Digits);
332         ex x0 = 1.;
333            x1 = exp(Pi*I/3).evalf();
334            x2 = exp(2*Pi*I/3).evalf();
335            x3 = -1.;
336         ex x4 = exp(4*Pi*I/3).evalf();
337         ex x5 = exp(5*Pi*I/3).evalf();
338
339         ex r5 = Li(lst(1,1,1,1),lst(x2,x4,x3,x0)).hold().evalf();
340         ex r6 = Li(lst(1,1,1,1),lst(x4,x2,x3,x0)).hold().evalf();
341         if ( abs(r5-conjugate(r6)) > prec ) {
342                 clog << "Legacy test 4 seems to be wrong." << endl;
343                 result++;
344         }
345
346         ex r7 = Li(lst(1,2,1),lst(x3,x2,x4)).hold().evalf()
347                 +Li(lst(1,1,2),lst(x3,x2,x4)).hold().evalf()
348                 +Li(lst(1,1,1,1),lst(x3,x0,x2,x4)).hold().evalf()
349                 +Li(lst(1,1,1,1),lst(x3,x2,x0,x4)).hold().evalf()
350                 +Li(lst(1,1,1,1),lst(x3,x2,x4,x0)).hold().evalf()
351                 +Li(lst(1,2,1),lst(x2,x1,x0)).hold().evalf()
352                 +Li(lst(1,1,2),lst(x2,x3,x4)).hold().evalf()
353                 +Li(lst(1,1,1,1),lst(x2,x4,x3,x0)).hold().evalf()
354                 +Li(lst(1,1,1,1),lst(x2,x3,x4,x0)).hold().evalf()
355                 +Li(lst(1,1,1,1),lst(x2,x3,x0,x4)).hold().evalf()
356                 +Li(lst(2,2),lst(x5,x4)).hold().evalf()
357                 +Li(lst(2,1,1),lst(x5,x0,x4)).hold().evalf()
358                 +Li(lst(2,1,1),lst(x5,x4,x0)).hold().evalf()
359                 -Li(lst(1,1),lst(x3,x0)).hold().evalf()*Li(lst(1,1),lst(x2,x4)).hold().evalf();
360         if ( abs(r7) > prec ) {
361                 clog << "Legacy test 5 seems to be wrong." << endl;
362                 result++;
363         }
364
365         return result;
366 }
367
368 static unsigned check_G_y_one_bug()
369 {
370         exvector exprs;
371         exprs.push_back(G(lst(-1,-1, 1,-1, 0), 1));
372         exprs.push_back(G(lst(-1, 0, 1,-1, 0), 1));
373         exprs.push_back(G(lst(-1, 1,-1,-1, 0), 1));
374         exprs.push_back(G(lst(-1, 1,-1, 0, 0), 1));
375         exprs.push_back(G(lst(-1, 1,-1, 1, 0), 1));
376         exprs.push_back(G(lst(-1, 1, 0,-1, 0), 1));
377         exprs.push_back(G(lst(-1, 1, 1,-1, 0), 1));
378         exprs.push_back(G(lst( 0,-1, 1,-1, 0), 1));
379         exprs.push_back(G(lst( 0, 1, 1,-1, 0), 1));
380         unsigned err = 0;
381         for (exvector::const_iterator ep = exprs.begin(); ep != exprs.end(); ++ep) {
382                 try {
383                         ex val = ep->evalf();
384                         if (!is_a<numeric>(val)) {
385                                 clog << "evalf(" << *ep << ") is not a number: " << val << endl;
386                                 ++err;
387                         }
388                 } catch (std::exception& oops) {
389                         clog << "evalf(" << *ep << "): got an exception" << oops.what() << endl;
390                         ++err;
391                 }
392         }
393         return err;
394 }
395
396 unsigned exam_inifcns_nstdsums(void)
397 {
398         unsigned result = 0;
399         
400         cout << "examining consistency of nestedsums functions" << flush;
401         
402         result += inifcns_test_zeta();
403         result += inifcns_test_S();
404         result += inifcns_test_HLi();
405         result += inifcns_test_LiG();
406         result += inifcns_test_legacy();
407         result += check_G_y_one_bug();
408         
409         return result;
410 }
411
412 int main(int argc, char** argv)
413 {
414         return exam_inifcns_nstdsums();
415 }