exam_inifcns_nstdsums.cpp: prec set to 10*pow(10,-Digits) in inifcns_test_HLi to...
[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-2022 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 'constexpr string polylogdata[] = {' > exam_inifcns_nstdsums.h
66  *    for i in `cat exam_inifcns_nstdsums_data.raw2`; do echo \"$i\",; done >> exam_inifcns_nstdsums.h
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(polylogdata[i++],symbol());
90                 if (n == ENDMARK) {
91                         break;
92                 }
93                 ex p(polylogdata[i++],symbol());
94                 ex x(polylogdata[i++],symbol());
95                 ex res(polylogdata[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         // 15.01.2022: prec set to 10*pow(10,-Digits) to avoid exam failure in sporadic cases
132         ex prec = 10 * pow(10, -(ex)Digits);
133         numeric almostone("0.999999999999999999");
134         unsigned result = 0;
135
136         lst res;
137         
138         res.append(H(lst{2,1},numeric(1)/2).hold() - (zeta(3)/8 - pow(log(2),3)/6));
139         res.append(H(lst{2,1,3},numeric(1)/3).hold() - Li(lst{2,1,3},lst{numeric(1)/3,1,1}).hold());
140         res.append(H(lst{2,1,3},numeric(98)/100).hold() - Li(lst{2,1,3},lst{numeric(98)/100,1,1}).hold());
141         res.append(H(lst{2,1,3},numeric(245)/100).hold() - Li(lst{2,1,3},lst{numeric(245)/100,1,1}).hold());
142         res.append(H(lst{4,1,1,1},numeric(1)/3).hold() - S(3,4,numeric(1)/3).hold());
143         res.append(H(lst{4,1,1,1},numeric(98)/100).hold() - S(3,4,numeric(98)/100).hold());
144         res.append(H(lst{4,1,1,1},numeric(245)/100).hold() - S(3,4,numeric(245)/100).hold());
145         res.append(H(lst{2,2,3},almostone).hold() - zeta(lst{2,2,3}));
146         res.append(H(lst{-3,-1,2,1},almostone).hold() - zeta(lst{3,1,2,1},lst{-1,1,-1,1}));
147         res.append(H(lst{-2,1,3},numeric(1)/3).hold() - -Li(lst{2,1,3},lst{-numeric(1)/3,-1,1}).hold());
148         res.append(H(lst{-2,1,3},numeric(98)/100).hold() - -Li(lst{2,1,3},lst{-numeric(98)/100,-1,1}).hold());
149         res.append(H(lst{-2,1,3},numeric(245)/100).hold() - -Li(lst{2,1,3},lst{-numeric(245)/100,-1,1}).hold());
150         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));
151         
152         for (lst::const_iterator it = res.begin(); it != res.end(); it++) {
153                 ex diff = abs((*it).evalf());
154                 if (diff > prec) {
155                         clog << *it << " seems to be wrong: " << diff << endl;
156                         result++;
157                 }
158                 cout << "." << flush;
159         }
160
161         Digits = digitsbuf;
162
163         // conjugate test
164         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));
165         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));
166         if ((cdif.real() > prec) || (cadd.imag() > prec)) {
167                 clog << "complex conjugation test of H({2,2,1},5.0-5.0*I) seems to be wrong: " << cdif << " " << cadd << endl;
168                 result++;
169         }
170
171         return result;
172 }
173
174
175 ////////////////////////////////////////////////////////////////////////////////
176 ////////////////////////////////////////////////////////////////////////////////
177 //  zeta exam
178 ////////////////////////////////////////////////////////////////////////////////
179 ////////////////////////////////////////////////////////////////////////////////
180
181
182 static unsigned inifcns_test_zeta()
183 {
184         int digitsbuf = Digits;
185         
186         unsigned result = 0;
187
188         lst res;
189         
190         res.append(zeta(lst{2,1}) - zeta(3));
191         res.append(zeta(lst{2,1,1,1,1}) - zeta(6));
192         res.append(zeta(lst{6,3}) - (zeta(9)*83/2 - zeta(2)*zeta(7)*21 - zeta(2)*zeta(2)*zeta(5)*12/5));
193         res.append(zeta(lst{4,2,3}) - (-zeta(9)*59 + zeta(2)*zeta(7)*28 + pow(zeta(2),2)*zeta(5)*4 -
194                                        pow(zeta(3),3)/3 + pow(zeta(2),3)*zeta(3)*8/21));
195         res.append(zeta(lst{3,1,3,1,3,1,3,1}) - (2*pow(Pi,16)/factorial(18)));
196         res.append(zeta(lst{2},lst{-1}) - -zeta(2)/2);
197         res.append(zeta(lst{1,2},lst{-1,1}) - (-zeta(3)/4 - zeta(lst{1},lst{-1})*zeta(2)/2));
198         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
199                                                     - zeta(lst{3,1},lst{-1,1})*3/2 - zeta(lst{1},lst{-1})*zeta(3)*21/8));
200         
201         for (lst::const_iterator it = res.begin(); it != res.end(); it++) {
202                 Digits = 17;
203                 ex prec = 5 * pow(10, -(ex)Digits);
204                 ex diff = abs((*it).evalf());
205                 if (diff > prec) {
206                         clog << *it << " seems to be wrong: " << diff << endl;
207                         clog << "Digits: " << Digits << endl;
208                         result++;
209                 }
210                 cout << "." << flush;
211                 Digits = 40;
212                 prec = 5 * pow(10, -(ex)Digits);
213                 diff = abs((*it).evalf());
214                 if (diff > prec) {
215                         clog << *it << " seems to be wrong: " << diff << endl;
216                         clog << "Digits: " << Digits << endl;
217                         result++;
218                 }
219                 cout << "." << flush;
220         }
221
222         Digits = digitsbuf;
223
224         return result;
225 }
226
227
228 ////////////////////////////////////////////////////////////////////////////////
229 ////////////////////////////////////////////////////////////////////////////////
230 //  H/Li exam
231 ////////////////////////////////////////////////////////////////////////////////
232 ////////////////////////////////////////////////////////////////////////////////
233
234
235 static unsigned inifcns_test_LiG()
236 {
237         int digitsbuf = Digits;
238         Digits = 17;
239         ex prec = 5 * pow(10, -(ex)Digits);
240         numeric almostone("0.99999999999999999999");
241         unsigned result = 0;
242
243         lst res;
244         
245         res.append(Li(lst{4}, lst{6}).hold() - Li(4, 6.0));
246         res.append(G(lst{0,0,5.0,0,2.0,0,0,0,3.0},0.5).hold()
247                    + Li(lst{3,2,4}, lst{numeric(1,10), numeric(5,2), numeric(2,3)}));
248         res.append(Li(lst{2,1,1}, lst{almostone, almostone, almostone}) - zeta(lst{2,1,1}));
249
250         // check Li_{1,1} against known expression
251         symbol x("x"), y("y");
252         ex eps = 1e-30*I;
253         ex s1 = Li(lst{1,1},lst{x,y});
254         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))
255                         - 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))
256                         - log(-1/x/y-eps)*log(1-1/x-eps) + log(-1/x/y-eps)*log(-1/x-eps);
257         res.append(s1.subs(lst{x==numeric(1)/2, y==3}) - s2.subs(lst{x==numeric(1)/2, y==3}));
258         res.append(s1.subs(lst{x==numeric(3)/2, y==numeric(1)/2}) - s2.subs(lst{x==numeric(3)/2, y==numeric(1)/2}));
259         res.append(s1.subs(lst{x==2, y==numeric(4)/5}) - s2.subs(lst{x==2, y==numeric(4)/5}));
260
261         // shuffle and quasi-shuffle identities
262         res.append(G(lst{0,0.2},1).hold() * G(lst{0.5},1).hold() - G(lst{0.5,0,0.2},1).hold()
263                  - G(lst{0,0.5,0.2},1).hold() - G(lst{0,0.2,0.5},1).hold());
264         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()
265                  - G(lst{0.6,0,0.5*0.6},1).hold() + G(lst{0,0,0.5*0.6},1).hold());
266         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()
267                  - Li(lst{3,2},lst{7,numeric(1,5)}).hold() - Li(lst{5},lst{numeric(7,5)}).hold());
268         symbol a1, a2, a3, a4;
269         res.append((G(lst{a1,a2},1) * G(lst{a3,a4},1) - G(lst{a1,a2,a3,a4},1)
270                   - G(lst{a1,a3,a2,a4},1) - G(lst{a3,a1,a2,a4},1)
271                   - G(lst{a1,a3,a4,a2},1) - G(lst{a3,a1,a4,a2},1) - G(lst{a3,a4,a1,a2},1))
272                    .subs(lst{a1==numeric(1)/10, a2==numeric(3)/10, a3==numeric(7)/10, a4==5}));
273         res.append(G(lst{-0.009},1).hold() * G(lst{-8,1.4999},1).hold() - G(lst{-0.009,-8,1.4999},1).hold()
274                  - G(lst{-8,-0.009,1.4999},1).hold() - G(lst{-8,1.4999,-0.009},1).hold());
275         res.append(G(lst{sqrt(numeric(1)/2)+I*sqrt(numeric(1)/2)},1).hold() * G(lst{1.51,-0.999},1).hold()
276                  - G(lst{sqrt(numeric(1)/2)+I*sqrt(numeric(1)/2),1.51,-0.999},1).hold()
277                  - G(lst{1.51,sqrt(numeric(1)/2)+I*sqrt(numeric(1)/2),-0.999},1).hold()
278                  - G(lst{1.51,-0.999,sqrt(numeric(1)/2)+I*sqrt(numeric(1)/2)},1).hold());
279         // checks for hoelder convolution which is used if one argument has a distance to one smaller than 0.01 
280         res.append(G(lst{0, 1.2, 1, 1.01}, 1).hold() - G(lst{0, 1.2, 1, numeric("1.009999999999999999")}, 1).hold());
281
282         for (lst::const_iterator it = res.begin(); it != res.end(); it++) {
283                 ex diff = abs((*it).evalf());
284                 if (diff > prec) {
285                         clog << *it << " seems to be wrong: " << diff << endl;
286                         result++;
287                 }
288                 cout << "." << flush;
289         }
290
291         Digits = digitsbuf;
292
293         return result;
294 }
295
296
297 ////////////////////////////////////////////////////////////////////////////////
298 ////////////////////////////////////////////////////////////////////////////////
299 //  legacy exam - checking for historical bugs
300 ////////////////////////////////////////////////////////////////////////////////
301 ////////////////////////////////////////////////////////////////////////////////
302
303
304 static unsigned inifcns_test_legacy()
305 {
306         int digitsbuf = Digits;
307         Digits = 17;
308         ex prec = 5 * pow(10, -(ex)Digits);
309
310         unsigned result = 0;
311
312         ex r1 = zeta(lst{1,1,1,1,1,1}, lst{-1,-1,-1,1,1,1});
313         if ((r1.evalf() - numeric("-0.0012588769028204890704")) > prec) {
314                 clog << "zeta({1,1,1,1,1,1},{-1,-1,-1,1,1,1}) seems to be wrong." << endl;
315                 result++;
316         }
317
318         ex x1 = exp(2*Pi*I/13).evalf();
319         ex x2 = exp(24*Pi*I/13).evalf();
320         ex r2 = Li(lst{2},lst{x1}).hold().evalf();
321         ex r3 = Li(lst{2},lst{x2}).hold().evalf();
322         if ( abs(r2-conjugate(r3)) > prec ) {
323                 clog << "Legacy test 2 seems to be wrong." << endl;
324                 result++;
325         }
326
327         ex x3 = exp(5*Pi*I/3).evalf();
328         ex r4 = Li(lst{3},lst{x3}).hold().evalf();
329         if ( abs(r4 - numeric("0.40068563438653142847-0.95698384815740185713*I")) > prec ) {
330                 clog << "Legacy test 3 seems to be wrong." << endl;
331                 result++;
332         }
333
334         Digits = 100;
335         prec = 5 * pow(10, -(ex)Digits);
336         ex x0 = 1.;
337            x1 = exp(Pi*I/3).evalf();
338            x2 = exp(2*Pi*I/3).evalf();
339            x3 = -1.;
340         ex x4 = exp(4*Pi*I/3).evalf();
341         ex x5 = exp(5*Pi*I/3).evalf();
342
343         ex r5 = Li(lst{1,1,1,1},lst{x2,x4,x3,x0}).hold().evalf();
344         ex r6 = Li(lst{1,1,1,1},lst{x4,x2,x3,x0}).hold().evalf();
345         if ( abs(r5-conjugate(r6)) > prec ) {
346                 clog << "Legacy test 4 seems to be wrong." << endl;
347                 result++;
348         }
349
350         ex r7 = Li(lst{1,2,1},lst{x3,x2,x4}).hold().evalf()
351                 +Li(lst{1,1,2},lst{x3,x2,x4}).hold().evalf()
352                 +Li(lst{1,1,1,1},lst{x3,x0,x2,x4}).hold().evalf()
353                 +Li(lst{1,1,1,1},lst{x3,x2,x0,x4}).hold().evalf()
354                 +Li(lst{1,1,1,1},lst{x3,x2,x4,x0}).hold().evalf()
355                 +Li(lst{1,2,1},lst{x2,x1,x0}).hold().evalf()
356                 +Li(lst{1,1,2},lst{x2,x3,x4}).hold().evalf()
357                 +Li(lst{1,1,1,1},lst{x2,x4,x3,x0}).hold().evalf()
358                 +Li(lst{1,1,1,1},lst{x2,x3,x4,x0}).hold().evalf()
359                 +Li(lst{1,1,1,1},lst{x2,x3,x0,x4}).hold().evalf()
360                 +Li(lst{2,2},lst{x5,x4}).hold().evalf()
361                 +Li(lst{2,1,1},lst{x5,x0,x4}).hold().evalf()
362                 +Li(lst{2,1,1},lst{x5,x4,x0}).hold().evalf()
363                 -Li(lst{1,1},lst{x3,x0}).hold().evalf()*Li(lst{1,1},lst{x2,x4}).hold().evalf();
364         if ( abs(r7) > prec ) {
365                 clog << "Legacy test 5 seems to be wrong." << endl;
366                 result++;
367         }
368
369         Digits = digitsbuf;
370
371         return result;
372 }
373
374 static unsigned check_G_y_one_bug()
375 {
376         exvector exprs;
377         exprs.push_back(G(lst{-1,-1, 1,-1, 0}, 1));
378         exprs.push_back(G(lst{-1, 0, 1,-1, 0}, 1));
379         exprs.push_back(G(lst{-1, 1,-1,-1, 0}, 1));
380         exprs.push_back(G(lst{-1, 1,-1, 0, 0}, 1));
381         exprs.push_back(G(lst{-1, 1,-1, 1, 0}, 1));
382         exprs.push_back(G(lst{-1, 1, 0,-1, 0}, 1));
383         exprs.push_back(G(lst{-1, 1, 1,-1, 0}, 1));
384         exprs.push_back(G(lst{ 0,-1, 1,-1, 0}, 1));
385         exprs.push_back(G(lst{ 0, 1, 1,-1, 0}, 1));
386         unsigned err = 0;
387         for (exvector::const_iterator ep = exprs.begin(); ep != exprs.end(); ++ep) {
388                 try {
389                         ex val = ep->evalf();
390                         if (!is_a<numeric>(val)) {
391                                 clog << "evalf(" << *ep << ") is not a number: " << val << endl;
392                                 ++err;
393                         }
394                 } catch (std::exception& oops) {
395                         clog << "evalf(" << *ep << "): got an exception" << oops.what() << endl;
396                         ++err;
397                 }
398         }
399         return err;
400 }
401
402 unsigned exam_inifcns_nstdsums(void)
403 {
404         unsigned result = 0;
405         
406         cout << "examining consistency of nestedsums functions" << flush;
407         
408         result += inifcns_test_zeta();
409         result += inifcns_test_S();
410         result += inifcns_test_HLi();
411         result += inifcns_test_LiG();
412         result += inifcns_test_legacy();
413         result += check_G_y_one_bug();
414         
415         return result;
416 }
417
418 int main(int argc, char** argv)
419 {
420         return exam_inifcns_nstdsums();
421 }