-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathmain.cpp
More file actions
239 lines (207 loc) · 9.91 KB
/
Copy pathmain.cpp
File metadata and controls
239 lines (207 loc) · 9.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
// Александр Шашков cracecrunch@gmail.com
// Дмитрий Балашов dimabalash0v@yandex.ru
#include "headers/framework.h"
#include "headers/Polynomial.h"
#include "headers/Laguerre.h"
#include "headers/Laguerre13m.h"
#include "headers/Laguerre18m.h"
#include <fstream>
#define PR_NUMBERS_OF_ROOTS_EQUAL 0
#define PR_AT_LEAST_ONE_ROOT_LOST -1
#define PR_AT_LEAST_ONE_ROOT_IS_FAKE -2
#define PR_2_INFINITE_ROOTS -3
#ifndef SOLVER
#define SOLVER 2
// 0 - Original
// 1 - 2013 mod
// 2 - 2018 mod
#endif
#ifndef NUMBER
#define NUMBER double
#endif
// Exponent and mantissa for root generation
// You can check recommended precision for ttmath on https://www.ttmath.org/online_calculator/
// lets use big precision
// FOR 64-bit
// mantissa = 2048 bits / 64 bits per word = 32 words
// exponent = 256 bits / 64 bits per word = 4 words
// FOR 32-bit
// mantissa = 2048 bits / 32 bits per word = 64 words
// exponent = 256 bits / 32 bits per word = 8 words
#ifndef EXPONENT
#define EXPONENT 4 // Exponent for bignum notation
#endif
#ifndef MANTISSA
#define MANTISSA 32 // Mantissa for bignum notation
#endif
#ifndef DEGREE
#define DEGREE 100 // polynomial degree
#endif
#ifndef N_TESTS
#define N_TESTS 10000 // count of tests
#endif
// Generator params. If all N_*_ROOTS are zero, then generator will create only simple roots
#ifndef N_PAIRS_OF_COMPLEX_ROOTS
#define N_PAIRS_OF_COMPLEX_ROOTS 0
#endif
#ifndef N_CLUSTERED_ROOTS
#define N_CLUSTERED_ROOTS 0
#endif
#ifndef N_MULTIPLE_ROOTS
#define N_MULTIPLE_ROOTS 0
#endif
// Used only for clustered roots
#ifndef MAX_DISTANCE_BETWEEN_CLUSTERED
#define MAX_DISTANCE_BETWEEN_CLUSTERED 1e-5
#endif
#ifndef ROOT_SWEEP_LOW
#define ROOT_SWEEP_LOW -1
#endif
#ifndef ROOT_SWEEP_HIGH
#define ROOT_SWEEP_HIGH 1
#endif
#ifndef TRIES
#define TRIES 80 // For how many iterations Laguerre should try to solve polynomial
#endif
using std::cout;
using std::vector;
using std::complex;
using std::for_each;
using std::fill;
using std::exception;
using std::invalid_argument;
using std::endl;
using std::cerr;
int main(){
using Laguerre::Polynomial;
// Laguerre solvers
#if SOLVER == 0
cout << "Using original version of Laguerre\n";
Laguerre::Original<NUMBER>* solver = new Laguerre::Original<NUMBER>();
#elif SOLVER == 1
cout << "Using modified version of Laguerre, 2013\n";
Laguerre::ModifiedLaguerre13<NUMBER>* solver = new Laguerre::ModifiedLaguerre13<NUMBER>();
#elif SOLVER == 2
cout << "Using modified version of Laguerre, 2018\n";
Laguerre::ModifiedLaguerre18<NUMBER>* solver = new Laguerre::ModifiedLaguerre18<NUMBER>();
#endif
// Generator stuff
int rv, // status of comparing roots
N_roots_found_this_test, N_roots_gt_this_test, // amount of found roots in each test & gt roots
N_true_roots_lost=0, N_fake_roots_added=0, // total counters of {lost, fake} roots aover all tests
N_roots_gt_all_tests_ae_worst=0, N_roots_found_all_tests_ae_worst=0, // {ground truth, found} NUMBER of roots of the worst polynomial for absolute error
N_roots_gt_all_tests_re_worst=0, N_roots_found_all_tests_re_worst=0; // {ground truth, found} NUMBER of roots of the worst polynomial for relative error
vector<NUMBER> roots(DEGREE, 0.0), roots_found_this_test(DEGREE), a(DEGREE+1, 0.0), // current polynomial
roots_gt_all_tests_ae_worst(DEGREE), roots_found_all_tests_ae_worst(DEGREE), coefficients_all_tests_ae_worst(DEGREE+1), // {gt roots, found roots, coefficients} of the worst polynomial for absolute error
roots_gt_all_tests_re_worst(DEGREE), roots_found_all_tests_re_worst(DEGREE), coefficients_all_tests_re_worst(DEGREE+1); // {gt roots, found roots, coefficients} of the worst polynomial for relative error
NUMBER ae_this_test_worst, ae_all_tests_worst=static_cast<NUMBER>(-1.0L), // absolute error: an impossible value that will be updated for sure
re_this_test_worst, re_all_tests_worst=static_cast<NUMBER>(-1.0L); // relative error: an impossible value that will be updated for sure
Polynomial<NUMBER> pol;
try{
pol.setSolver(solver);
for(int i=0; i < N_TESTS; ++i){
roots_found_this_test.clear();
N_roots_gt_this_test = generate_polynomial<NUMBER, EXPONENT, MANTISSA>(DEGREE, N_PAIRS_OF_COMPLEX_ROOTS, N_CLUSTERED_ROOTS,
N_MULTIPLE_ROOTS, MAX_DISTANCE_BETWEEN_CLUSTERED, ROOT_SWEEP_LOW, ROOT_SWEEP_HIGH, roots, a);
cout << "GENERATED POLY & ROOTS:\n";
Laguerre::printVec(a);
Laguerre::printVec(roots);
pol.setCoeffs(a);
vector<complex<NUMBER>> solved_roots(DEGREE);
vector<int> conv(DEGREE);
pol.solve(solved_roots, conv, TRIES);
cout << "found roots: ";
for_each(solved_roots.begin(), solved_roots.end(), [&roots_found_this_test](complex<NUMBER> x){ // solved_roots = b_roots
cout << x.real() << "; ";
roots_found_this_test.push_back(x.real());
});
N_roots_found_this_test = roots_found_this_test.size();
rv=compare_roots<NUMBER>(N_roots_found_this_test, N_roots_gt_this_test, roots_found_this_test, roots,
ae_this_test_worst, re_this_test_worst);
cout << endl << "P=" << DEGREE << ", test No " << i << " out of " << N_TESTS << endl
<< "comparison return value=" << (rv==PR_NUMBERS_OF_ROOTS_EQUAL ? "PR_NUMBERS_OF_ROOTS_EQUAL" :
(rv==PR_AT_LEAST_ONE_ROOT_LOST ? "PR_AT_LEAST_ONE_ROOT_LOST" :
(rv==PR_AT_LEAST_ONE_ROOT_IS_FAKE ? "PR_AT_LEAST_ONE_ROOT_IS_FAKE" : "UNKNOWN VALUE")))
<< ", N_roots_gt_this_test=" << N_roots_gt_this_test << ", N_roots_found_this_test=" << N_roots_found_this_test
<< ", N_roots_verified_this_test=" << DEGREE
<< "ae_this_test_worst=" << ae_this_test_worst
<< ", re_this_test_worst=" << re_this_test_worst << " ------------------------------" << endl;
N_true_roots_lost+=(N_roots_found_this_test<N_roots_gt_this_test)*(N_roots_gt_this_test-N_roots_found_this_test);
N_fake_roots_added+=(N_roots_found_this_test>N_roots_gt_this_test)*(N_roots_found_this_test-N_roots_gt_this_test);
if (ae_this_test_worst>ae_all_tests_worst && ( N_roots_found_this_test>=N_roots_gt_this_test))
{
roots_gt_all_tests_ae_worst=roots; N_roots_gt_all_tests_ae_worst=N_roots_gt_this_test;
roots_found_all_tests_ae_worst=roots_found_this_test; N_roots_found_all_tests_ae_worst=N_roots_found_this_test;
coefficients_all_tests_ae_worst=a; ae_all_tests_worst=ae_this_test_worst;
}
if (re_this_test_worst>re_all_tests_worst && (N_roots_found_this_test>=N_roots_gt_this_test))
{
roots_gt_all_tests_re_worst=roots; N_roots_gt_all_tests_re_worst=N_roots_gt_this_test;
roots_found_all_tests_re_worst=roots_found_this_test; N_roots_found_all_tests_re_worst=N_roots_found_this_test;
coefficients_all_tests_re_worst=a; re_all_tests_worst=re_this_test_worst;
}
if(Laguerre::anynotfinite<NUMBER>(roots_found_this_test)){
cout << "\nNOT FINITE ROOTS!!!\n";
delete solver;
return 1;
}
if(Laguerre::anynotfinite<NUMBER>(a)){
cout << "NOT FINITE COEFFS!!!\n";
delete solver;
return 1;
}
fill(roots.begin(), roots.end(), 0.0);
fill(a.begin(), a.end(), 0.0);
cout << "\n=======================\n";
}
}
catch (const invalid_argument &exc)
{
cerr << "Bad argument: " << exc.what();
}
catch (const exception &exc)
{
cerr << exc.what();
}
cout << "\nDONE!\n";
cout << endl << "--------------- settings ----------------" << endl
<< "P=" << DEGREE << ", N_tests=" << N_TESTS;
cout << endl << endl << "--------------- statistics ----------------" << endl
<< ", N_true_roots_lost=" << N_true_roots_lost << ", N_fake_roots_added=" << N_fake_roots_added
<< endl;
// output the worst cases
cout << endl << "--------------- worst case: absolute error: ----------------" << endl
<< "ae_all_tests_worst=" << ae_all_tests_worst
<< ", N_roots_gt_all_tests_ae_worst=" << N_roots_gt_all_tests_ae_worst
<< ", N_roots_found_all_tests_ae_worst=" << N_roots_found_all_tests_ae_worst << endl;
cout << endl << "--------------- worst case: relative error: ----------------" << endl
<< "re_all_tests_worst=" << re_all_tests_worst
<< ", N_roots_gt_all_tests_re_worst=" << N_roots_gt_all_tests_re_worst
<< ", N_roots_found_all_tests_re_worst=" << N_roots_found_all_tests_re_worst << endl;
cout << "\nWorst case method results ae: ";
for (auto &root : roots_found_all_tests_ae_worst){
cout << root << " ";
}
cout << "\nGround truth worst ae: {";
for (auto &root : roots_gt_all_tests_ae_worst){
cout << root << ", ";
}
cout << "}\nCoeffs worst ae: {";
for (auto &root : coefficients_all_tests_ae_worst){
cout << root << ", ";
}
cout << "}\nWorst case method results re: ";
for (auto &root : roots_found_all_tests_re_worst){
cout << root << " ";
}
cout << "\nGround truth worst re: {";
for (auto &root : roots_gt_all_tests_re_worst){
cout << root << ", ";
}
cout << "}\nCoeffs worst re: {";
for (auto &root : coefficients_all_tests_re_worst){
cout << root << ", ";
}
delete solver;
return 0;
}