text.cc (3918:1f9a98d198e8) text.cc (4078:3f73f808bbd4)
1/*
2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Nathan Binkert
29 */
30
31#if defined(__APPLE__)
32#define _GLIBCPP_USE_C99 1
33#endif
34
35#if defined(__sun)
36#include <math.h>
37#endif
38
39#include <iostream>
40#include <sstream>
41#include <fstream>
42#include <string>
43
44#include "base/misc.hh"
45#include "base/statistics.hh"
46#include "base/stats/statdb.hh"
47#include "base/stats/text.hh"
48#include "base/stats/visit.hh"
49
50using namespace std;
51
52#ifndef NAN
53float __nan();
54/** Define Not a number. */
55#define NAN (__nan())
56/** Need to define __nan() */
57#define __M5_NAN
58#endif
59
60#ifdef __M5_NAN
61float
62__nan()
63{
64 union {
65 uint32_t ui;
66 float f;
67 } nan;
68
69 nan.ui = 0x7fc00000;
70 return nan.f;
71}
72#endif
73
74namespace Stats {
75
76Text::Text()
77 : mystream(false), stream(NULL), compat(false), descriptions(false)
78{
79}
80
81Text::Text(std::ostream &stream)
82 : mystream(false), stream(NULL), compat(false), descriptions(false)
83{
84 open(stream);
85}
86
87Text::Text(const std::string &file)
88 : mystream(false), stream(NULL), compat(false), descriptions(false)
89{
90 open(file);
91}
92
93
94Text::~Text()
95{
96 if (mystream) {
97 assert(stream);
98 delete stream;
99 }
100}
101
102void
103Text::open(std::ostream &_stream)
104{
105 if (stream)
106 panic("stream already set!");
107
108 mystream = false;
109 stream = &_stream;
110 assert(valid());
111}
112
113void
114Text::open(const std::string &file)
115{
116 if (stream)
117 panic("stream already set!");
118
119 mystream = true;
120 stream = new ofstream(file.c_str(), ios::trunc);
121 assert(valid());
122}
123
124bool
125Text::valid() const
126{
127 return stream != NULL;
128}
129
130void
131Text::output()
132{
133 using namespace Database;
134
135 ccprintf(*stream, "\n---------- Begin Simulation Statistics ----------\n");
136 stat_list_t::const_iterator i, end = stats().end();
137 for (i = stats().begin(); i != end; ++i)
138 (*i)->visit(*this);
139 ccprintf(*stream, "\n---------- End Simulation Statistics ----------\n");
140 stream->flush();
141}
142
143bool
144Text::noOutput(const StatData &data)
145{
146 if (!(data.flags & print))
147 return true;
148
149 if (data.prereq && data.prereq->zero())
150 return true;
151
152 return false;
153}
154
155string
156ValueToString(Result value, int precision, bool compat)
157{
158 stringstream val;
159
160 if (!isnan(value)) {
161 if (precision != -1)
162 val.precision(precision);
163 else if (value == rint(value))
164 val.precision(0);
165
166 val.unsetf(ios::showpoint);
167 val.setf(ios::fixed);
168 val << value;
169 } else {
170 val << (compat ? "<err: div-0>" : "no value");
171 }
172
173 return val.str();
174}
175
176struct ScalarPrint
177{
178 Result value;
179 string name;
180 string desc;
181 StatFlags flags;
182 bool compat;
183 bool descriptions;
184 int precision;
185 Result pdf;
186 Result cdf;
187
188 void operator()(ostream &stream) const;
189};
190
191void
192ScalarPrint::operator()(ostream &stream) const
193{
194 if (flags & nozero && value == 0.0 ||
195 flags & nonan && isnan(value))
196 return;
197
198 stringstream pdfstr, cdfstr;
199
200 if (!isnan(pdf))
201 ccprintf(pdfstr, "%.2f%%", pdf * 100.0);
202
203 if (!isnan(cdf))
204 ccprintf(cdfstr, "%.2f%%", cdf * 100.0);
205
206 if (compat && flags & __substat) {
207 ccprintf(stream, "%32s %12s %10s %10s", name,
208 ValueToString(value, precision, compat), pdfstr, cdfstr);
209 } else {
210 ccprintf(stream, "%-40s %12s %10s %10s", name,
211 ValueToString(value, precision, compat), pdfstr, cdfstr);
212 }
213
214 if (descriptions) {
215 if (!desc.empty())
216 ccprintf(stream, " # %s", desc);
217 }
218 stream << endl;
219}
220
221struct VectorPrint
222{
223 string name;
224 string desc;
225 vector<string> subnames;
226 vector<string> subdescs;
227 StatFlags flags;
228 bool compat;
229 bool descriptions;
230 int precision;
231 VResult vec;
232 Result total;
233
234 void operator()(ostream &stream) const;
235};
236
237void
238VectorPrint::operator()(std::ostream &stream) const
239{
240 int _size = vec.size();
241 Result _total = 0.0;
242
243 if (flags & (pdf | cdf)) {
244 for (int i = 0; i < _size; ++i) {
245 _total += vec[i];
246 }
247 }
248
249 string base = name + (compat ? "_" : "::");
250
251 ScalarPrint print;
252 print.name = name;
253 print.desc = desc;
254 print.precision = precision;
255 print.descriptions = descriptions;
256 print.flags = flags;
257 print.pdf = NAN;
258 print.cdf = NAN;
259
260 bool havesub = !subnames.empty();
261
262 if (_size == 1) {
263 print.value = vec[0];
264 print(stream);
265 } else if (!compat) {
266 for (int i = 0; i < _size; ++i) {
267 if (havesub && (i >= subnames.size() || subnames[i].empty()))
268 continue;
269
270 print.name = base + (havesub ? subnames[i] : to_string(i));
271 print.desc = subdescs.empty() ? desc : subdescs[i];
272 print.value = vec[i];
273
274 if (_total && (flags & pdf)) {
275 print.pdf = vec[i] / _total;
276 print.cdf += print.pdf;
277 }
278
279 print(stream);
280 }
281
282 if (flags & ::Stats::total) {
283 print.name = base + "total";
284 print.desc = desc;
285 print.value = total;
286 print(stream);
287 }
288 } else {
289 if (flags & ::Stats::total) {
290 print.value = total;
291 print(stream);
292 }
293
294 Result _pdf = 0.0;
295 Result _cdf = 0.0;
296 if (flags & dist) {
297 ccprintf(stream, "%s.start_dist\n", name);
298 for (int i = 0; i < _size; ++i) {
299 print.name = havesub ? subnames[i] : to_string(i);
300 print.desc = subdescs.empty() ? desc : subdescs[i];
301 print.flags |= __substat;
302 print.value = vec[i];
303
304 if (_total) {
305 _pdf = vec[i] / _total;
306 _cdf += _pdf;
307 }
308
309 if (flags & pdf)
310 print.pdf = _pdf;
311 if (flags & cdf)
312 print.cdf = _cdf;
313
314 print(stream);
315 }
316 ccprintf(stream, "%s.end_dist\n", name);
317 } else {
318 for (int i = 0; i < _size; ++i) {
319 if (havesub && subnames[i].empty())
320 continue;
321
322 print.name = base;
323 print.name += havesub ? subnames[i] : to_string(i);
324 print.desc = subdescs.empty() ? desc : subdescs[i];
325 print.value = vec[i];
326
327 if (_total) {
328 _pdf = vec[i] / _total;
329 _cdf += _pdf;
330 } else {
331 _pdf = _cdf = NAN;
332 }
333
334 if (flags & pdf) {
335 print.pdf = _pdf;
336 print.cdf = _cdf;
337 }
338
339 print(stream);
340 }
341 }
342 }
343}
344
345struct DistPrint
346{
347 string name;
348 string desc;
349 StatFlags flags;
350 bool compat;
351 bool descriptions;
352 int precision;
353
354 Result min_val;
355 Result max_val;
356 Result underflow;
357 Result overflow;
358 VResult vec;
359 Result sum;
360 Result squares;
361 Result samples;
362
363 Counter min;
364 Counter max;
365 Counter bucket_size;
366 int size;
367 bool fancy;
368
369 void operator()(ostream &stream) const;
370};
371
372void
373DistPrint::operator()(ostream &stream) const
374{
375 if (fancy) {
376 ScalarPrint print;
377 string base = name + (compat ? "_" : "::");
378
379 print.precision = precision;
380 print.flags = flags;
381 print.compat = compat;
382 print.descriptions = descriptions;
383 print.desc = desc;
384 print.pdf = NAN;
385 print.cdf = NAN;
386
387 print.name = base + "mean";
388 print.value = samples ? sum / samples : NAN;
389 print(stream);
390
391 print.name = base + "stdev";
392 print.value = samples ? sqrt((samples * squares - sum * sum) /
393 (samples * (samples - 1.0))) : NAN;
394 print(stream);
395
396 print.name = "**Ignore: " + base + "TOT";
397 print.value = samples;
398 print(stream);
399 return;
400 }
401
402 assert(size == vec.size());
403
404 Result total = 0.0;
405
406 total += underflow;
407 for (int i = 0; i < size; ++i)
408 total += vec[i];
409 total += overflow;
410
411 string base = name + (compat ? "." : "::");
412
413 ScalarPrint print;
414 print.desc = compat ? "" : desc;
415 print.flags = flags;
416 print.compat = compat;
417 print.descriptions = descriptions;
418 print.precision = precision;
419 print.pdf = NAN;
420 print.cdf = NAN;
421
422 if (compat) {
423 ccprintf(stream, "%-42s", base + "start_dist");
424 if (descriptions && !desc.empty())
425 ccprintf(stream, " # %s", desc);
426 stream << endl;
427 }
428
429 print.name = base + "samples";
430 print.value = samples;
431 print(stream);
432
433 print.name = base + "min_value";
434 print.value = min_val;
435 print(stream);
436
437 if (!compat || underflow > 0.0) {
438 print.name = base + "underflows";
439 print.value = underflow;
440 if (!compat && total) {
441 print.pdf = underflow / total;
442 print.cdf += print.pdf;
443 }
444 print(stream);
445 }
446
447
448 if (!compat) {
449 for (int i = 0; i < size; ++i) {
450 stringstream namestr;
451 namestr << name;
452
453 Counter low = i * bucket_size + min;
454 Counter high = ::min(low + bucket_size, max);
455 namestr << low;
456 if (low < high)
457 namestr << "-" << high;
458
459 print.name = namestr.str();
460 print.value = vec[i];
461 if (total) {
462 print.pdf = vec[i] / total;
463 print.cdf += print.pdf;
464 }
465 print(stream);
466 }
467
468 } else {
469 Counter _min;
470 Result _pdf;
471 Result _cdf = 0.0;
472
473 print.flags = flags | __substat;
474
475 for (int i = 0; i < size; ++i) {
476 if (flags & nozero && vec[i] == 0.0 ||
477 flags & nonan && isnan(vec[i]))
478 continue;
479
480 _min = i * bucket_size + min;
481 _pdf = vec[i] / total * 100.0;
482 _cdf += _pdf;
483
484
485 print.name = ValueToString(_min, 0, compat);
486 print.value = vec[i];
487 print.pdf = (flags & pdf) ? _pdf : NAN;
488 print.cdf = (flags & cdf) ? _cdf : NAN;
489 print(stream);
490 }
491
492 print.flags = flags;
493 }
494
495 if (!compat || overflow > 0.0) {
496 print.name = base + "overflows";
497 print.value = overflow;
498 if (!compat && total) {
499 print.pdf = overflow / total;
500 print.cdf += print.pdf;
501 } else {
502 print.pdf = NAN;
503 print.cdf = NAN;
504 }
505 print(stream);
506 }
507
508 print.pdf = NAN;
509 print.cdf = NAN;
510
511 if (!compat) {
512 print.name = base + "total";
513 print.value = total;
514 print(stream);
515 }
516
517 print.name = base + "max_value";
518 print.value = max_val;
519 print(stream);
520
521 if (!compat && samples != 0) {
522 print.name = base + "mean";
523 print.value = sum / samples;
524 print(stream);
525
526 print.name = base + "stdev";
527 print.value = sqrt((samples * squares - sum * sum) /
528 (samples * (samples - 1.0)));
529 print(stream);
530 }
531
532 if (compat)
533 ccprintf(stream, "%send_dist\n\n", base);
534}
535
536void
537Text::visit(const ScalarData &data)
538{
539 if (noOutput(data))
540 return;
541
542 ScalarPrint print;
543 print.value = data.result();
544 print.name = data.name;
545 print.desc = data.desc;
546 print.flags = data.flags;
547 print.compat = compat;
548 print.descriptions = descriptions;
549 print.precision = data.precision;
550 print.pdf = NAN;
551 print.cdf = NAN;
552
553 print(*stream);
554}
555
556void
557Text::visit(const VectorData &data)
558{
559 if (noOutput(data))
560 return;
561
562 int size = data.size();
563 VectorPrint print;
564
565 print.name = data.name;
566 print.desc = data.desc;
567 print.flags = data.flags;
568 print.compat = compat;
569 print.descriptions = descriptions;
570 print.precision = data.precision;
571 print.vec = data.result();
572 print.total = data.total();
573
574 if (!data.subnames.empty()) {
575 for (int i = 0; i < size; ++i) {
576 if (!data.subnames[i].empty()) {
577 print.subnames = data.subnames;
578 print.subnames.resize(size);
579 for (int i = 0; i < size; ++i) {
580 if (!data.subnames[i].empty() &&
581 !data.subdescs[i].empty()) {
582 print.subdescs = data.subdescs;
583 print.subdescs.resize(size);
584 break;
585 }
586 }
587 break;
588 }
589 }
590 }
591
592 print(*stream);
593}
594
595void
596Text::visit(const Vector2dData &data)
597{
598 if (noOutput(data))
599 return;
600
601 bool havesub = false;
602 VectorPrint print;
603
604 print.subnames = data.y_subnames;
605 print.flags = data.flags;
606 print.compat = compat;
607 print.descriptions = descriptions;
608 print.precision = data.precision;
609
610 if (!data.subnames.empty()) {
611 for (int i = 0; i < data.x; ++i)
612 if (!data.subnames[i].empty())
613 havesub = true;
614 }
615
616 VResult tot_vec(data.y);
617 Result super_total = 0.0;
618 for (int i = 0; i < data.x; ++i) {
619 if (havesub && (i >= data.subnames.size() || data.subnames[i].empty()))
620 continue;
621
622 int iy = i * data.y;
623 VResult yvec(data.y);
624
625 Result total = 0.0;
626 for (int j = 0; j < data.y; ++j) {
627 yvec[j] = data.cvec[iy + j];
628 tot_vec[j] += yvec[j];
629 total += yvec[j];
630 super_total += yvec[j];
631 }
632
633 print.name = data.name + "_" + (havesub ? data.subnames[i] : to_string(i));
634 print.desc = data.desc;
635 print.vec = yvec;
636 print.total = total;
637 print(*stream);
638 }
639
640 if ((data.flags & ::Stats::total) && (data.x > 1)) {
641 print.name = data.name;
642 print.desc = data.desc;
643 print.vec = tot_vec;
644 print.total = super_total;
645 print(*stream);
646 }
647}
648
649void
650Text::visit(const DistData &data)
651{
652 if (noOutput(data))
653 return;
654
655 DistPrint print;
656
657 print.name = data.name;
658 print.desc = data.desc;
659 print.flags = data.flags;
660 print.compat = compat;
661 print.descriptions = descriptions;
662 print.precision = data.precision;
663
664 print.min_val = data.data.min_val;
665 print.max_val = data.data.max_val;
666 print.underflow = data.data.underflow;
667 print.overflow = data.data.overflow;
668 print.vec.resize(data.data.cvec.size());
669 for (int i = 0; i < print.vec.size(); ++i)
670 print.vec[i] = (Result)data.data.cvec[i];
671 print.sum = data.data.sum;
672 print.squares = data.data.squares;
673 print.samples = data.data.samples;
674
675 print.min = data.data.min;
676 print.max = data.data.max;
677 print.bucket_size = data.data.bucket_size;
678 print.size = data.data.size;
679 print.fancy = data.data.fancy;
680
681 print(*stream);
682}
683
684void
685Text::visit(const VectorDistData &data)
686{
687 if (noOutput(data))
688 return;
689
690 for (int i = 0; i < data.size(); ++i) {
691 DistPrint print;
692
693 print.name = data.name +
694 (data.subnames[i].empty() ? ("_" + to_string(i)) : data.subnames[i]);
695 print.desc = data.subdescs[i].empty() ? data.desc : data.subdescs[i];
696 print.flags = data.flags;
697 print.compat = compat;
698 print.descriptions = descriptions;
699 print.precision = data.precision;
700
701 print.min_val = data.data[i].min_val;
702 print.max_val = data.data[i].max_val;
703 print.underflow = data.data[i].underflow;
704 print.overflow = data.data[i].overflow;
705 print.vec.resize(data.data[i].cvec.size());
706 for (int j = 0; j < print.vec.size(); ++j)
707 print.vec[j] = (Result)data.data[i].cvec[j];
708 print.sum = data.data[i].sum;
709 print.squares = data.data[i].squares;
710 print.samples = data.data[i].samples;
711
712 print.min = data.data[i].min;
713 print.max = data.data[i].max;
714 print.bucket_size = data.data[i].bucket_size;
715 print.size = data.data[i].size;
716 print.fancy = data.data[i].fancy;
717
718 print(*stream);
719 }
720}
721
722void
723Text::visit(const FormulaData &data)
724{
725 visit((const VectorData &)data);
726}
727
1/*
2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Nathan Binkert
29 */
30
31#if defined(__APPLE__)
32#define _GLIBCPP_USE_C99 1
33#endif
34
35#if defined(__sun)
36#include <math.h>
37#endif
38
39#include <iostream>
40#include <sstream>
41#include <fstream>
42#include <string>
43
44#include "base/misc.hh"
45#include "base/statistics.hh"
46#include "base/stats/statdb.hh"
47#include "base/stats/text.hh"
48#include "base/stats/visit.hh"
49
50using namespace std;
51
52#ifndef NAN
53float __nan();
54/** Define Not a number. */
55#define NAN (__nan())
56/** Need to define __nan() */
57#define __M5_NAN
58#endif
59
60#ifdef __M5_NAN
61float
62__nan()
63{
64 union {
65 uint32_t ui;
66 float f;
67 } nan;
68
69 nan.ui = 0x7fc00000;
70 return nan.f;
71}
72#endif
73
74namespace Stats {
75
76Text::Text()
77 : mystream(false), stream(NULL), compat(false), descriptions(false)
78{
79}
80
81Text::Text(std::ostream &stream)
82 : mystream(false), stream(NULL), compat(false), descriptions(false)
83{
84 open(stream);
85}
86
87Text::Text(const std::string &file)
88 : mystream(false), stream(NULL), compat(false), descriptions(false)
89{
90 open(file);
91}
92
93
94Text::~Text()
95{
96 if (mystream) {
97 assert(stream);
98 delete stream;
99 }
100}
101
102void
103Text::open(std::ostream &_stream)
104{
105 if (stream)
106 panic("stream already set!");
107
108 mystream = false;
109 stream = &_stream;
110 assert(valid());
111}
112
113void
114Text::open(const std::string &file)
115{
116 if (stream)
117 panic("stream already set!");
118
119 mystream = true;
120 stream = new ofstream(file.c_str(), ios::trunc);
121 assert(valid());
122}
123
124bool
125Text::valid() const
126{
127 return stream != NULL;
128}
129
130void
131Text::output()
132{
133 using namespace Database;
134
135 ccprintf(*stream, "\n---------- Begin Simulation Statistics ----------\n");
136 stat_list_t::const_iterator i, end = stats().end();
137 for (i = stats().begin(); i != end; ++i)
138 (*i)->visit(*this);
139 ccprintf(*stream, "\n---------- End Simulation Statistics ----------\n");
140 stream->flush();
141}
142
143bool
144Text::noOutput(const StatData &data)
145{
146 if (!(data.flags & print))
147 return true;
148
149 if (data.prereq && data.prereq->zero())
150 return true;
151
152 return false;
153}
154
155string
156ValueToString(Result value, int precision, bool compat)
157{
158 stringstream val;
159
160 if (!isnan(value)) {
161 if (precision != -1)
162 val.precision(precision);
163 else if (value == rint(value))
164 val.precision(0);
165
166 val.unsetf(ios::showpoint);
167 val.setf(ios::fixed);
168 val << value;
169 } else {
170 val << (compat ? "<err: div-0>" : "no value");
171 }
172
173 return val.str();
174}
175
176struct ScalarPrint
177{
178 Result value;
179 string name;
180 string desc;
181 StatFlags flags;
182 bool compat;
183 bool descriptions;
184 int precision;
185 Result pdf;
186 Result cdf;
187
188 void operator()(ostream &stream) const;
189};
190
191void
192ScalarPrint::operator()(ostream &stream) const
193{
194 if (flags & nozero && value == 0.0 ||
195 flags & nonan && isnan(value))
196 return;
197
198 stringstream pdfstr, cdfstr;
199
200 if (!isnan(pdf))
201 ccprintf(pdfstr, "%.2f%%", pdf * 100.0);
202
203 if (!isnan(cdf))
204 ccprintf(cdfstr, "%.2f%%", cdf * 100.0);
205
206 if (compat && flags & __substat) {
207 ccprintf(stream, "%32s %12s %10s %10s", name,
208 ValueToString(value, precision, compat), pdfstr, cdfstr);
209 } else {
210 ccprintf(stream, "%-40s %12s %10s %10s", name,
211 ValueToString(value, precision, compat), pdfstr, cdfstr);
212 }
213
214 if (descriptions) {
215 if (!desc.empty())
216 ccprintf(stream, " # %s", desc);
217 }
218 stream << endl;
219}
220
221struct VectorPrint
222{
223 string name;
224 string desc;
225 vector<string> subnames;
226 vector<string> subdescs;
227 StatFlags flags;
228 bool compat;
229 bool descriptions;
230 int precision;
231 VResult vec;
232 Result total;
233
234 void operator()(ostream &stream) const;
235};
236
237void
238VectorPrint::operator()(std::ostream &stream) const
239{
240 int _size = vec.size();
241 Result _total = 0.0;
242
243 if (flags & (pdf | cdf)) {
244 for (int i = 0; i < _size; ++i) {
245 _total += vec[i];
246 }
247 }
248
249 string base = name + (compat ? "_" : "::");
250
251 ScalarPrint print;
252 print.name = name;
253 print.desc = desc;
254 print.precision = precision;
255 print.descriptions = descriptions;
256 print.flags = flags;
257 print.pdf = NAN;
258 print.cdf = NAN;
259
260 bool havesub = !subnames.empty();
261
262 if (_size == 1) {
263 print.value = vec[0];
264 print(stream);
265 } else if (!compat) {
266 for (int i = 0; i < _size; ++i) {
267 if (havesub && (i >= subnames.size() || subnames[i].empty()))
268 continue;
269
270 print.name = base + (havesub ? subnames[i] : to_string(i));
271 print.desc = subdescs.empty() ? desc : subdescs[i];
272 print.value = vec[i];
273
274 if (_total && (flags & pdf)) {
275 print.pdf = vec[i] / _total;
276 print.cdf += print.pdf;
277 }
278
279 print(stream);
280 }
281
282 if (flags & ::Stats::total) {
283 print.name = base + "total";
284 print.desc = desc;
285 print.value = total;
286 print(stream);
287 }
288 } else {
289 if (flags & ::Stats::total) {
290 print.value = total;
291 print(stream);
292 }
293
294 Result _pdf = 0.0;
295 Result _cdf = 0.0;
296 if (flags & dist) {
297 ccprintf(stream, "%s.start_dist\n", name);
298 for (int i = 0; i < _size; ++i) {
299 print.name = havesub ? subnames[i] : to_string(i);
300 print.desc = subdescs.empty() ? desc : subdescs[i];
301 print.flags |= __substat;
302 print.value = vec[i];
303
304 if (_total) {
305 _pdf = vec[i] / _total;
306 _cdf += _pdf;
307 }
308
309 if (flags & pdf)
310 print.pdf = _pdf;
311 if (flags & cdf)
312 print.cdf = _cdf;
313
314 print(stream);
315 }
316 ccprintf(stream, "%s.end_dist\n", name);
317 } else {
318 for (int i = 0; i < _size; ++i) {
319 if (havesub && subnames[i].empty())
320 continue;
321
322 print.name = base;
323 print.name += havesub ? subnames[i] : to_string(i);
324 print.desc = subdescs.empty() ? desc : subdescs[i];
325 print.value = vec[i];
326
327 if (_total) {
328 _pdf = vec[i] / _total;
329 _cdf += _pdf;
330 } else {
331 _pdf = _cdf = NAN;
332 }
333
334 if (flags & pdf) {
335 print.pdf = _pdf;
336 print.cdf = _cdf;
337 }
338
339 print(stream);
340 }
341 }
342 }
343}
344
345struct DistPrint
346{
347 string name;
348 string desc;
349 StatFlags flags;
350 bool compat;
351 bool descriptions;
352 int precision;
353
354 Result min_val;
355 Result max_val;
356 Result underflow;
357 Result overflow;
358 VResult vec;
359 Result sum;
360 Result squares;
361 Result samples;
362
363 Counter min;
364 Counter max;
365 Counter bucket_size;
366 int size;
367 bool fancy;
368
369 void operator()(ostream &stream) const;
370};
371
372void
373DistPrint::operator()(ostream &stream) const
374{
375 if (fancy) {
376 ScalarPrint print;
377 string base = name + (compat ? "_" : "::");
378
379 print.precision = precision;
380 print.flags = flags;
381 print.compat = compat;
382 print.descriptions = descriptions;
383 print.desc = desc;
384 print.pdf = NAN;
385 print.cdf = NAN;
386
387 print.name = base + "mean";
388 print.value = samples ? sum / samples : NAN;
389 print(stream);
390
391 print.name = base + "stdev";
392 print.value = samples ? sqrt((samples * squares - sum * sum) /
393 (samples * (samples - 1.0))) : NAN;
394 print(stream);
395
396 print.name = "**Ignore: " + base + "TOT";
397 print.value = samples;
398 print(stream);
399 return;
400 }
401
402 assert(size == vec.size());
403
404 Result total = 0.0;
405
406 total += underflow;
407 for (int i = 0; i < size; ++i)
408 total += vec[i];
409 total += overflow;
410
411 string base = name + (compat ? "." : "::");
412
413 ScalarPrint print;
414 print.desc = compat ? "" : desc;
415 print.flags = flags;
416 print.compat = compat;
417 print.descriptions = descriptions;
418 print.precision = precision;
419 print.pdf = NAN;
420 print.cdf = NAN;
421
422 if (compat) {
423 ccprintf(stream, "%-42s", base + "start_dist");
424 if (descriptions && !desc.empty())
425 ccprintf(stream, " # %s", desc);
426 stream << endl;
427 }
428
429 print.name = base + "samples";
430 print.value = samples;
431 print(stream);
432
433 print.name = base + "min_value";
434 print.value = min_val;
435 print(stream);
436
437 if (!compat || underflow > 0.0) {
438 print.name = base + "underflows";
439 print.value = underflow;
440 if (!compat && total) {
441 print.pdf = underflow / total;
442 print.cdf += print.pdf;
443 }
444 print(stream);
445 }
446
447
448 if (!compat) {
449 for (int i = 0; i < size; ++i) {
450 stringstream namestr;
451 namestr << name;
452
453 Counter low = i * bucket_size + min;
454 Counter high = ::min(low + bucket_size, max);
455 namestr << low;
456 if (low < high)
457 namestr << "-" << high;
458
459 print.name = namestr.str();
460 print.value = vec[i];
461 if (total) {
462 print.pdf = vec[i] / total;
463 print.cdf += print.pdf;
464 }
465 print(stream);
466 }
467
468 } else {
469 Counter _min;
470 Result _pdf;
471 Result _cdf = 0.0;
472
473 print.flags = flags | __substat;
474
475 for (int i = 0; i < size; ++i) {
476 if (flags & nozero && vec[i] == 0.0 ||
477 flags & nonan && isnan(vec[i]))
478 continue;
479
480 _min = i * bucket_size + min;
481 _pdf = vec[i] / total * 100.0;
482 _cdf += _pdf;
483
484
485 print.name = ValueToString(_min, 0, compat);
486 print.value = vec[i];
487 print.pdf = (flags & pdf) ? _pdf : NAN;
488 print.cdf = (flags & cdf) ? _cdf : NAN;
489 print(stream);
490 }
491
492 print.flags = flags;
493 }
494
495 if (!compat || overflow > 0.0) {
496 print.name = base + "overflows";
497 print.value = overflow;
498 if (!compat && total) {
499 print.pdf = overflow / total;
500 print.cdf += print.pdf;
501 } else {
502 print.pdf = NAN;
503 print.cdf = NAN;
504 }
505 print(stream);
506 }
507
508 print.pdf = NAN;
509 print.cdf = NAN;
510
511 if (!compat) {
512 print.name = base + "total";
513 print.value = total;
514 print(stream);
515 }
516
517 print.name = base + "max_value";
518 print.value = max_val;
519 print(stream);
520
521 if (!compat && samples != 0) {
522 print.name = base + "mean";
523 print.value = sum / samples;
524 print(stream);
525
526 print.name = base + "stdev";
527 print.value = sqrt((samples * squares - sum * sum) /
528 (samples * (samples - 1.0)));
529 print(stream);
530 }
531
532 if (compat)
533 ccprintf(stream, "%send_dist\n\n", base);
534}
535
536void
537Text::visit(const ScalarData &data)
538{
539 if (noOutput(data))
540 return;
541
542 ScalarPrint print;
543 print.value = data.result();
544 print.name = data.name;
545 print.desc = data.desc;
546 print.flags = data.flags;
547 print.compat = compat;
548 print.descriptions = descriptions;
549 print.precision = data.precision;
550 print.pdf = NAN;
551 print.cdf = NAN;
552
553 print(*stream);
554}
555
556void
557Text::visit(const VectorData &data)
558{
559 if (noOutput(data))
560 return;
561
562 int size = data.size();
563 VectorPrint print;
564
565 print.name = data.name;
566 print.desc = data.desc;
567 print.flags = data.flags;
568 print.compat = compat;
569 print.descriptions = descriptions;
570 print.precision = data.precision;
571 print.vec = data.result();
572 print.total = data.total();
573
574 if (!data.subnames.empty()) {
575 for (int i = 0; i < size; ++i) {
576 if (!data.subnames[i].empty()) {
577 print.subnames = data.subnames;
578 print.subnames.resize(size);
579 for (int i = 0; i < size; ++i) {
580 if (!data.subnames[i].empty() &&
581 !data.subdescs[i].empty()) {
582 print.subdescs = data.subdescs;
583 print.subdescs.resize(size);
584 break;
585 }
586 }
587 break;
588 }
589 }
590 }
591
592 print(*stream);
593}
594
595void
596Text::visit(const Vector2dData &data)
597{
598 if (noOutput(data))
599 return;
600
601 bool havesub = false;
602 VectorPrint print;
603
604 print.subnames = data.y_subnames;
605 print.flags = data.flags;
606 print.compat = compat;
607 print.descriptions = descriptions;
608 print.precision = data.precision;
609
610 if (!data.subnames.empty()) {
611 for (int i = 0; i < data.x; ++i)
612 if (!data.subnames[i].empty())
613 havesub = true;
614 }
615
616 VResult tot_vec(data.y);
617 Result super_total = 0.0;
618 for (int i = 0; i < data.x; ++i) {
619 if (havesub && (i >= data.subnames.size() || data.subnames[i].empty()))
620 continue;
621
622 int iy = i * data.y;
623 VResult yvec(data.y);
624
625 Result total = 0.0;
626 for (int j = 0; j < data.y; ++j) {
627 yvec[j] = data.cvec[iy + j];
628 tot_vec[j] += yvec[j];
629 total += yvec[j];
630 super_total += yvec[j];
631 }
632
633 print.name = data.name + "_" + (havesub ? data.subnames[i] : to_string(i));
634 print.desc = data.desc;
635 print.vec = yvec;
636 print.total = total;
637 print(*stream);
638 }
639
640 if ((data.flags & ::Stats::total) && (data.x > 1)) {
641 print.name = data.name;
642 print.desc = data.desc;
643 print.vec = tot_vec;
644 print.total = super_total;
645 print(*stream);
646 }
647}
648
649void
650Text::visit(const DistData &data)
651{
652 if (noOutput(data))
653 return;
654
655 DistPrint print;
656
657 print.name = data.name;
658 print.desc = data.desc;
659 print.flags = data.flags;
660 print.compat = compat;
661 print.descriptions = descriptions;
662 print.precision = data.precision;
663
664 print.min_val = data.data.min_val;
665 print.max_val = data.data.max_val;
666 print.underflow = data.data.underflow;
667 print.overflow = data.data.overflow;
668 print.vec.resize(data.data.cvec.size());
669 for (int i = 0; i < print.vec.size(); ++i)
670 print.vec[i] = (Result)data.data.cvec[i];
671 print.sum = data.data.sum;
672 print.squares = data.data.squares;
673 print.samples = data.data.samples;
674
675 print.min = data.data.min;
676 print.max = data.data.max;
677 print.bucket_size = data.data.bucket_size;
678 print.size = data.data.size;
679 print.fancy = data.data.fancy;
680
681 print(*stream);
682}
683
684void
685Text::visit(const VectorDistData &data)
686{
687 if (noOutput(data))
688 return;
689
690 for (int i = 0; i < data.size(); ++i) {
691 DistPrint print;
692
693 print.name = data.name +
694 (data.subnames[i].empty() ? ("_" + to_string(i)) : data.subnames[i]);
695 print.desc = data.subdescs[i].empty() ? data.desc : data.subdescs[i];
696 print.flags = data.flags;
697 print.compat = compat;
698 print.descriptions = descriptions;
699 print.precision = data.precision;
700
701 print.min_val = data.data[i].min_val;
702 print.max_val = data.data[i].max_val;
703 print.underflow = data.data[i].underflow;
704 print.overflow = data.data[i].overflow;
705 print.vec.resize(data.data[i].cvec.size());
706 for (int j = 0; j < print.vec.size(); ++j)
707 print.vec[j] = (Result)data.data[i].cvec[j];
708 print.sum = data.data[i].sum;
709 print.squares = data.data[i].squares;
710 print.samples = data.data[i].samples;
711
712 print.min = data.data[i].min;
713 print.max = data.data[i].max;
714 print.bucket_size = data.data[i].bucket_size;
715 print.size = data.data[i].size;
716 print.fancy = data.data[i].fancy;
717
718 print(*stream);
719 }
720}
721
722void
723Text::visit(const FormulaData &data)
724{
725 visit((const VectorData &)data);
726}
727
728bool
729initText(const string &filename, bool desc, bool compat)
730{
731 static Text text;
732 static bool connected = false;
733
734 if (connected)
735 return false;
736
737 extern list<Output *> OutputList;
738
739 text.open(*simout.find(filename));
740 text.descriptions = desc;
741 text.compat = compat;
742 OutputList.push_back(&text);
743 connected = true;
744
745 return true;
746}
747
748
728/* namespace Stats */ }
749/* namespace Stats */ }