Line data Source code
1 : #include <fas/testing.hpp>
2 : #include <wrtstat/reducer.hpp>
3 : #include <numeric>
4 :
5 :
6 : namespace {
7 :
8 : template< int Limit, int Levels, typename T>
9 3 : void empty_reducer(T& t)
10 : {
11 : using namespace fas::testing;
12 : using namespace wrtstat;
13 3 : reducer_options ro;
14 3 : ro.reducer_limit = Limit;
15 3 : ro.reducer_levels = Levels;
16 3 : reducer r(ro);
17 3 : r.add(1,1);
18 : // Заполнили все доступные массивы в первой итерации i3
19 3 : t << is_true<expect>( r.filled() ) << FAS_FL;
20 : // Суммарный размер массивов при полном заполнении = limit*levels
21 3 : t << equal<expect, size_t>( r.size(), 0 ) << FAS_FL;
22 : // Суммарный вызов add * 2 (передавали count == 2 )
23 3 : t << equal<expect, size_t>( r.total_count(), 1 ) << FAS_FL;
24 : // Расчетное количество выброшенных значений при прореживании (останется только массив длиной ro.limit)
25 3 : t << equal<expect, size_t>( r.lossy_count(), 1 ) << FAS_FL;
26 : // Минимальное значение
27 3 : t << equal<expect, size_t>( r.min(), 1 ) << FAS_FL;
28 : // Текущее максимальное значение
29 3 : t << equal<expect, size_t>( r.max(), 1 ) << FAS_FL;
30 :
31 6 : auto res = r.detach();
32 3 : t << is_true<assert>( res!=nullptr ) << FAS_FL;
33 3 : t << stop;
34 3 : t << equal<expect, size_t>( res->count, 1 ) << FAS_FL;
35 3 : t << equal<expect, size_t>( res->lossy, 1 ) << FAS_FL;
36 3 : t << equal<expect, size_t>( res->lossy, 1 ) << FAS_FL;
37 3 : t << equal<expect, size_t>( res->min, 1) << FAS_FL;
38 3 : t << equal<expect, size_t>( res->max, 1) << FAS_FL;
39 6 : t << equal<expect, size_t>( res->avg, 1) << FAS_FL;
40 3 : }
41 :
42 3 : UNIT(empty_reducer_0_0, "")
43 : {
44 1 : empty_reducer<0,0>(t);
45 1 : }
46 :
47 3 : UNIT(empty_reducer_0_1, "")
48 : {
49 1 : empty_reducer<0,1>(t);
50 1 : }
51 :
52 3 : UNIT(empty_reducer_1_0, "")
53 : {
54 1 : empty_reducer<1,0>(t);
55 1 : }
56 :
57 : template< int Limit, int Levels, typename T>
58 6 : void filled_reducer(T& t)
59 : {
60 : using namespace fas::testing;
61 : using namespace wrtstat;
62 6 : reducer_options ro;
63 6 : ro.reducer_limit = Limit;
64 6 : ro.reducer_levels = Levels;
65 6 : reducer r(ro);
66 6 : t << is_false<expect>( r.filled() ) << FAS_FL;
67 6 : int value = 0;
68 12 : std::vector<int> values;
69 :
70 18 : for (int i3=0; i3 < 2; ++i3)
71 : {
72 52 : for (int i2=0; i2 < Levels; ++i2)
73 : {
74 242 : for (int i1=0; i1 < Limit; ++i1)
75 : {
76 202 : r.add( ++value, 2 );
77 202 : values.push_back(value);
78 : //avg = (avg + value)/2;
79 : }
80 : }
81 : }
82 :
83 6 : int avg = std::accumulate(values.begin(), values.end(), 0 ) / static_cast<int>( values.size() );
84 :
85 : // Заполнили все доступные массивы в первой итерации i3
86 6 : t << is_true<expect>( r.filled() ) << FAS_FL;
87 : // Суммарный размер массивов при полном заполнении = limit*levels
88 6 : t << equal<expect, size_t>( r.size(), ro.reducer_limit*ro.reducer_levels ) << FAS_FL;
89 : // Суммарный вызов add * 2 (передавали count == 2 )
90 6 : t << equal<expect, size_t>( r.total_count(), value*2 ) << FAS_FL;
91 6 : t << message("values.size=") << values.size() << " r.total_count()=" << r.total_count();
92 : // Расчетное количество выброшенных значений при прореживании (останется только массив длиной ro.limit)
93 6 : t << equal<expect, size_t>( r.lossy_count(), r.total_count() - ro.reducer_limit ) << FAS_FL;
94 : // Минимальное значение
95 6 : t << equal<expect, size_t>( r.min(), 1 ) << FAS_FL;
96 : // Текущее максимальное значение
97 6 : t << equal<expect, size_t>( r.max(), value ) << FAS_FL;
98 :
99 12 : auto res = r.detach();
100 6 : t << is_true<assert>( res!=nullptr ) << FAS_FL;
101 6 : t << stop;
102 :
103 6 : t << equal<expect, long>( res->min, 1 ) << FAS_FL;
104 6 : t << equal<expect, long>( res->max, value ) << FAS_FL;
105 6 : t << equal<expect, long>( res->count, value*2 ) << FAS_FL;
106 6 : t << equal<expect, long>( res->lossy, size_t(value)*2 - ro.reducer_limit ) << FAS_FL;
107 6 : t << equal<expect, long>( res->avg, avg ) << FAS_FL;
108 6 : t << equal<expect, long>( res->data.size(), ro.reducer_limit ) << FAS_FL;
109 : /*for ( auto i : res->data)
110 : t << message("A: ") << i;*/
111 6 : r.clear();
112 6 : t << is_false<expect>( r.filled() ) << FAS_FL;
113 6 : t << equal<expect, size_t>( r.size(), 0 ) << FAS_FL;
114 6 : t << equal<expect, size_t>( r.total_count(), 0 ) << FAS_FL;
115 6 : t << equal<expect, size_t>( r.lossy_count(), 0 ) << FAS_FL;
116 6 : t << equal<expect, size_t>( r.min(), 0 ) << FAS_FL;
117 6 : t << equal<expect, size_t>( r.max(), 0 ) << FAS_FL;
118 6 : res = r.detach();
119 6 : t << is_true<assert>( res==nullptr ) << FAS_FL;
120 6 : t << stop;
121 :
122 : // count == 0
123 6 : value = 0;
124 6 : values.clear();
125 : //avg = 0;
126 :
127 18 : for (int i3=0; i3 < 2; ++i3)
128 : {
129 52 : for (int i2=0; i2 < Levels; ++i2)
130 : {
131 242 : for (int i1=0; i1 < Limit; ++i1)
132 : {
133 202 : r.add( ++value, 0 );
134 : //avg = (avg + value)/2;
135 202 : values.push_back(value);
136 : }
137 : }
138 : }
139 :
140 6 : avg = std::accumulate(values.begin(), values.end(), 0 ) / static_cast<int>( values.size() );
141 :
142 6 : t << is_true<expect>( r.filled() ) << FAS_FL;
143 6 : t << equal<expect, size_t>( r.size(), ro.reducer_limit*ro.reducer_levels ) << FAS_FL;
144 6 : t << equal<expect, size_t>( r.total_count(), 0 ) << FAS_FL;
145 6 : t << equal<expect, size_t>( r.lossy_count(), size_t(value) - ro.reducer_limit ) << FAS_FL;
146 6 : t << equal<expect, size_t>( r.min(), 1 ) << FAS_FL;
147 6 : t << equal<expect, size_t>( r.max(), value ) << FAS_FL;
148 :
149 6 : res = r.detach();
150 6 : t << is_true<assert>( res!=nullptr ) << FAS_FL;
151 6 : t << stop;
152 :
153 6 : t << equal<expect, int>( res->min, 1 ) << FAS_FL;
154 6 : t << equal<expect, int>( res->max, value ) << FAS_FL;
155 6 : t << equal<expect, int>( res->count, 0 ) << FAS_FL;
156 6 : t << equal<expect, int>( res->lossy, size_t(value) - ro.reducer_limit ) << FAS_FL;
157 6 : t << equal<expect, int>( res->avg, avg ) << FAS_FL;
158 12 : t << equal<expect, int>( res->data.size(), ro.reducer_limit ) << FAS_FL;
159 : /*for ( auto i : res->data)
160 : t << message("B: ") << i;*/
161 6 : }
162 :
163 3 : UNIT(reducer_1_1, "")
164 : {
165 1 : filled_reducer<1,1>(t);
166 1 : }
167 :
168 3 : UNIT(reducer_1_2, "")
169 : {
170 1 : filled_reducer<1,2>(t);
171 1 : }
172 :
173 3 : UNIT(reducer_2_1, "")
174 : {
175 1 : filled_reducer<2,1>(t);
176 1 : }
177 :
178 3 : UNIT(reducer_4_8, "")
179 : {
180 1 : filled_reducer<4,8>(t);
181 1 : }
182 :
183 3 : UNIT(reducer_8_4, "")
184 : {
185 1 : filled_reducer<8,4>(t);
186 1 : }
187 :
188 : template< int Limit, int Levels, typename T>
189 4 : void filled_reducer_reducer(T& t)
190 : {
191 : using namespace fas::testing;
192 : using namespace wrtstat;
193 4 : reducer_options ro;
194 4 : ro.reducer_limit = Limit;
195 4 : ro.reducer_levels = Levels;
196 4 : reducer r0(ro);
197 8 : reducer r(ro);
198 4 : t << is_false<expect>( r.filled() ) << FAS_FL;
199 4 : int value = 0;
200 8 : std::vector<int> values;
201 8 : std::vector<int> values_avg;
202 :
203 16 : for (int i3=0; i3 < Levels; ++i3)
204 : {
205 82 : for (int i2=0; i2 < Levels; ++i2)
206 : {
207 333 : for (int i1=0; i1 < Limit; ++i1)
208 : {
209 263 : r0.add( ++value, 2 );
210 263 : values.push_back(value);
211 : //avg = (avg + value)/2;
212 : }
213 : };
214 24 : if ( auto p = r0.detach() )
215 : {
216 : /*for ( int i = 0 ; i < Levels; ++i)
217 : values_avg.push_back( static_cast<int>(p->avg));
218 : */
219 12 : std::copy(p->data.begin(), p->data.end(), std::back_inserter(values_avg));
220 :
221 12 : t << message("current lossy=") << p->lossy << " count=" << p->count << " size=" << p->data.size() << " avg=" << p->avg;
222 12 : r.add(*p);
223 : }
224 : else
225 0 : t << error("empty detach") << FAS_FL;
226 12 : r0.clear();
227 : }
228 :
229 4 : int avg_real = std::accumulate(values.begin(), values.end(), 0 ) / static_cast<int>( values.size() );
230 4 : int avg = std::accumulate(values_avg.begin(), values_avg.end(), 0 ) / static_cast<int>( values_avg.size() );
231 4 : t << message("avg=") << avg << " true avg=" << avg_real;
232 : // Заполнили все доступные массивы в первой итерации i3
233 4 : t << is_true<expect>( r.filled() ) << FAS_FL;
234 : // Суммарный размер массивов при полном заполнении = limit*levels
235 4 : t << equal<expect, size_t>( r.size(), ro.reducer_limit*ro.reducer_levels ) << FAS_FL;
236 : // Суммарный вызов add * 2 (передавали count == 2 )
237 4 : t << equal<expect, size_t>( r.total_count(), value*2 ) << FAS_FL;
238 4 : t << message("values.size=") << values.size() << " r.total_count()=" << r.total_count();
239 : // Расчетное количество выброшенных значений при прореживании (останется только массив длиной ro.limit)
240 4 : t << equal<expect, size_t>( r.lossy_count(), r.total_count() - ro.reducer_limit ) << FAS_FL;
241 : // Минимальное значение
242 4 : t << equal<expect, size_t>( r.min(), 1 ) << FAS_FL;
243 : // Текущее максимальное значение
244 4 : t << equal<expect, size_t>( r.max(), value ) << FAS_FL;
245 :
246 8 : auto res = r.detach();
247 4 : t << is_true<assert>( res!=nullptr ) << FAS_FL;
248 4 : t << stop;
249 :
250 4 : t << equal<expect, long>( res->min, 1 ) << FAS_FL;
251 4 : t << equal<expect, long>( res->max, value ) << FAS_FL;
252 4 : t << equal<expect, long>( res->count, value*2 ) << FAS_FL;
253 4 : t << equal<expect, long>( res->lossy, size_t(value)*2 - ro.reducer_limit ) << FAS_FL;
254 4 : t << equal<expect, long>( res->avg, avg ) << FAS_FL;
255 4 : t << equal<expect, long>( res->data.size(), ro.reducer_limit ) << FAS_FL;
256 : /*for ( auto i : res->data)
257 : t << message("A: ") << i;*/
258 4 : r.clear();
259 4 : t << is_false<expect>( r.filled() ) << FAS_FL;
260 4 : t << equal<expect, size_t>( r.size(), 0 ) << FAS_FL;
261 4 : t << equal<expect, size_t>( r.total_count(), 0 ) << FAS_FL;
262 4 : t << equal<expect, size_t>( r.lossy_count(), 0 ) << FAS_FL;
263 4 : t << equal<expect, size_t>( r.min(), 0 ) << FAS_FL;
264 4 : t << equal<expect, size_t>( r.max(), 0 ) << FAS_FL;
265 4 : res = r.detach();
266 4 : t << is_true<assert>( res==nullptr ) << FAS_FL;
267 4 : t << stop;
268 :
269 : // count == 0
270 4 : value = 0;
271 4 : values.clear();
272 : //avg = 0;
273 :
274 12 : for (int i3=0; i3 < 2; ++i3)
275 : {
276 32 : for (int i2=0; i2 < Levels; ++i2)
277 : {
278 98 : for (int i1=0; i1 < Limit; ++i1)
279 : {
280 74 : r.add( ++value, 0 );
281 : //avg = (avg + value)/2;
282 74 : values.push_back(value);
283 : }
284 : }
285 : }
286 :
287 4 : avg = std::accumulate(values.begin(), values.end(), 0 ) / static_cast<int>( values.size() );
288 :
289 4 : t << is_true<expect>( r.filled() ) << FAS_FL;
290 4 : t << equal<expect, size_t>( r.size(), ro.reducer_limit*ro.reducer_levels ) << FAS_FL;
291 4 : t << equal<expect, size_t>( r.total_count(), 0 ) << FAS_FL;
292 4 : t << equal<expect, size_t>( r.lossy_count(), size_t(value) - ro.reducer_limit ) << FAS_FL;
293 4 : t << equal<expect, size_t>( r.min(), 1 ) << FAS_FL;
294 4 : t << equal<expect, size_t>( r.max(), value ) << FAS_FL;
295 :
296 4 : res = r.detach();
297 4 : t << is_true<assert>( res!=nullptr ) << FAS_FL;
298 4 : t << stop;
299 :
300 4 : t << equal<expect, int>( res->min, 1 ) << FAS_FL;
301 4 : t << equal<expect, int>( res->max, value ) << FAS_FL;
302 4 : t << equal<expect, int>( res->count, 0 ) << FAS_FL;
303 4 : t << equal<expect, int>( res->lossy, size_t(value) - ro.reducer_limit ) << FAS_FL;
304 4 : t << equal<expect, int>( res->avg, avg ) << FAS_FL;
305 8 : t << equal<expect, int>( res->data.size(), ro.reducer_limit ) << FAS_FL;
306 : /*for ( auto i : res->data)
307 : t << message("B: ") << i;*/
308 4 : }
309 :
310 3 : UNIT(reducer_reducer_1_1, "")
311 : {
312 1 : filled_reducer_reducer<1,1>(t);
313 1 : }
314 :
315 3 : UNIT(reducer_reducer_1_2, "")
316 : {
317 1 : filled_reducer_reducer<1,2>(t);
318 1 : }
319 :
320 3 : UNIT(reducer_reducer_2_1, "")
321 : {
322 1 : filled_reducer_reducer<2,1>(t);
323 1 : }
324 :
325 3 : UNIT(reducer_reducer_4_8, "")
326 : {
327 1 : filled_reducer_reducer<4,8>(t);
328 1 : }
329 :
330 3 : UNIT(reducer_reducer_8_4, "")
331 : {
332 1 : filled_reducer<8,4>(t);
333 1 : }
334 :
335 : template< int Limit, int Levels, int Tail, typename T>
336 4 : void non_filled_reducer(T& t)
337 : {
338 : using namespace fas::testing;
339 : using namespace wrtstat;
340 4 : reducer_options ro;
341 4 : ro.reducer_limit = Limit;
342 4 : ro.reducer_levels = Levels;
343 4 : reducer r(ro);
344 4 : int value = 0;
345 8 : std::vector<int> values;
346 :
347 82 : for (int i2=0; i2 < Levels - 1; ++i2)
348 : {
349 4128 : for (int i1=0; i1 < Limit; ++i1)
350 : {
351 4050 : r.add( ++value, 1 );
352 4050 : values.push_back(value);
353 : }
354 : }
355 :
356 1520 : for (int i3=0; i3 < Tail; ++i3)
357 : {
358 1516 : r.add( ++value, 1 );
359 1516 : values.push_back(value);
360 : }
361 :
362 4 : int avg = std::accumulate(values.begin(), values.end(), 0 ) / static_cast<int>( values.size() );
363 :
364 : // Заполнили все доступные массивы в первой итерации i3
365 4 : t << is_false<expect>( r.filled() ) << FAS_FL;
366 : // Суммарный размер массивов при полном заполнении = limit*levels
367 4 : t << equal<expect, size_t>( r.size(), ro.reducer_limit*(ro.reducer_levels-1) + Tail ) << FAS_FL;
368 : // Суммарный вызов add * 2 (передавали count == 2 )
369 4 : t << equal<expect, size_t>( r.total_count(), value ) << FAS_FL;
370 : // Расчетное количество выброшенных значений при прореживании (останется только массив длиной ro.limit)
371 4 : t << equal<expect, size_t>( r.lossy_count(), r.total_count() - ro.reducer_limit ) << FAS_FL;
372 : // Минимальное значение
373 4 : t << equal<expect, size_t>( r.min(), 1 ) << FAS_FL;
374 : // Текущее максимальное значение
375 4 : t << equal<expect, size_t>( r.max(), value ) << FAS_FL;
376 :
377 8 : auto res = r.detach();
378 4 : t << is_true<assert>( res!=nullptr ) << FAS_FL;
379 4 : t << stop;
380 :
381 4 : t << equal<expect, int>( res->min, 1 ) << FAS_FL;
382 4 : t << equal<expect, int>( res->max, value ) << FAS_FL;
383 4 : t << equal<expect, int>( res->count, value ) << FAS_FL;
384 4 : t << equal<expect, int>( res->lossy, size_t(value) - ro.reducer_limit ) << FAS_FL;
385 4 : t << equal<expect, int>( res->avg, avg ) << FAS_FL;
386 8 : t << equal<expect, int>( res->data.size(), ro.reducer_limit ) << FAS_FL;
387 4 : }
388 :
389 3 : UNIT(nf_reducer_4_8_2, "")
390 : {
391 1 : non_filled_reducer<4,8,2>(t);
392 1 : }
393 :
394 3 : UNIT(nf_reducer_43_29_13, "")
395 : {
396 1 : non_filled_reducer<43,29,13>(t);
397 1 : }
398 :
399 3 : UNIT(nf_reducer_29_43_1, "")
400 : {
401 1 : non_filled_reducer<29,43,1>(t);
402 1 : }
403 :
404 3 : UNIT(nf_reducer_1600_2_1500, "")
405 : {
406 1 : non_filled_reducer<1600,2,1500>(t);
407 1 : }
408 :
409 : template< int Limit, int Levels, int Size, typename T>
410 4 : void array_reducer(T& t)
411 : {
412 : using namespace fas::testing;
413 : using namespace wrtstat;
414 4 : reducer_options ro;
415 4 : ro.reducer_limit = Limit;
416 4 : ro.reducer_levels = Levels;
417 4 : reducer r(ro);
418 4 : int value = 0;
419 8 : std::vector<int> values;
420 :
421 8 : data_type data;
422 1497 : for (int i=0; i < Size; ++i)
423 : {
424 1493 : data.push_back( ++value );
425 1493 : values.push_back(value);
426 : }
427 4 : r.add( data );
428 4 : int avg = std::accumulate(values.begin(), values.end(), 0 ) / static_cast<int>( values.size() );
429 : // Заполнили все доступные массивы в первой итерации i3
430 : if ( Size < Limit*Levels )
431 1 : t << is_false<expect>( r.filled() ) << FAS_FL;
432 : else
433 3 : t << is_true<expect>( r.filled() ) << FAS_FL;
434 : // Суммарный размер массивов при полном заполнении = limit*levels
435 4 : int size = Levels*Limit < Size ? Levels*Limit : Size ;
436 4 : t << equal<expect, size_t>( r.size(), size ) << FAS_FL;
437 : // Суммарный вызов add * 2 (передавали count == 2 )
438 4 : t << equal<expect, size_t>( r.total_count(), value ) << FAS_FL;
439 : // Расчетное количество выброшенных значений при прореживании (останется только массив длиной ro.limit)
440 4 : int lossy = Limit < Size ? Size - Limit : 0;
441 4 : t << equal<expect, size_t>( r.lossy_count(), lossy ) << "[" << Limit << "," << Levels << "," << Size << "]" << FAS_FL;
442 : // Минимальное значение
443 4 : t << equal<expect, size_t>( r.min(), 1 ) << FAS_FL;
444 : // Текущее максимальное значение
445 4 : t << equal<expect, size_t>( r.max(), value ) << FAS_FL;
446 :
447 8 : auto res = r.detach();
448 4 : t << is_true<assert>( res!=nullptr ) << FAS_FL;
449 4 : t << stop;
450 :
451 4 : t << equal<expect, int>( res->min, 1 ) << FAS_FL;
452 4 : t << equal<expect, int>( res->max, value ) << FAS_FL;
453 4 : t << equal<expect, int>( res->count, value ) << FAS_FL;
454 4 : t << equal<expect, int>( res->lossy, lossy ) << FAS_FL;
455 4 : t << equal<expect, int>( res->avg, avg ) << FAS_FL;
456 4 : int data_size = Size < Limit ? Size : Limit;
457 8 : t << equal<expect, int>( res->data.size(), data_size ) << FAS_FL;
458 4 : }
459 :
460 3 : UNIT(array_reducer_1_2_3, "")
461 : {
462 1 : array_reducer<1,2,3>(t);
463 1 : }
464 :
465 3 : UNIT(array_reducer_1_2_144, "")
466 : {
467 1 : array_reducer<1,2,144>(t);
468 1 : }
469 :
470 3 : UNIT(array_reducer_43_29_13, "")
471 : {
472 1 : array_reducer<43,29,13>(t);
473 1 : }
474 :
475 3 : UNIT(array_reducer_33_11_1333, "")
476 : {
477 1 : array_reducer<33,11,1333>(t);
478 1 : }
479 :
480 : }
481 :
482 1 : BEGIN_SUITE(reducer, "")
483 : ADD_UNIT(empty_reducer_0_0)
484 : ADD_UNIT(empty_reducer_0_1)
485 : ADD_UNIT(empty_reducer_1_0)
486 : ADD_UNIT(reducer_1_1)
487 : ADD_UNIT(reducer_1_2)
488 : ADD_UNIT(reducer_2_1)
489 : ADD_UNIT(reducer_4_8)
490 : ADD_UNIT(reducer_8_4)
491 : ADD_UNIT(reducer_reducer_1_1)
492 : ADD_UNIT(reducer_reducer_1_2)
493 : ADD_UNIT(reducer_reducer_2_1)
494 : ADD_UNIT(reducer_reducer_4_8)
495 : ADD_UNIT(reducer_reducer_8_4)
496 : ADD_UNIT(nf_reducer_4_8_2)
497 : ADD_UNIT(nf_reducer_43_29_13)
498 : ADD_UNIT(nf_reducer_29_43_1)
499 : ADD_UNIT(nf_reducer_1600_2_1500)
500 : ADD_UNIT(array_reducer_1_2_3)
501 : ADD_UNIT(array_reducer_1_2_144)
502 : ADD_UNIT(array_reducer_43_29_13)
503 : ADD_UNIT(array_reducer_33_11_1333)
504 7 : END_SUITE(reducer)
505 :
|