statistics.cc revision 2
112853Sgabeblack@google.com/*
212853Sgabeblack@google.com * Copyright (c) 2003 The Regents of The University of Michigan
312853Sgabeblack@google.com * All rights reserved.
412853Sgabeblack@google.com *
512853Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
612853Sgabeblack@google.com * modification, are permitted provided that the following conditions are
712853Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
812853Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
912853Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
1012853Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
1112853Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
1212853Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
1312853Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
1412853Sgabeblack@google.com * this software without specific prior written permission.
1512853Sgabeblack@google.com *
1612853Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1712853Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1812853Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1912853Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2012853Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2112853Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2212853Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312853Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412853Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512853Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2612853Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712853Sgabeblack@google.com */
2812853Sgabeblack@google.com
2912853Sgabeblack@google.com#include <iomanip>
3012853Sgabeblack@google.com#include <iostream>
3112853Sgabeblack@google.com#include <list>
3212853Sgabeblack@google.com#include <map>
3312853Sgabeblack@google.com#include <string>
3412853Sgabeblack@google.com#include <sstream>
3512853Sgabeblack@google.com
3612853Sgabeblack@google.com#include <math.h>
3712853Sgabeblack@google.com
3812853Sgabeblack@google.com#include "cprintf.hh"
3912853Sgabeblack@google.com#include "intmath.h"
4012853Sgabeblack@google.com#include "misc.hh"
4112853Sgabeblack@google.com#include "statistics.hh"
4212853Sgabeblack@google.com#include "str.hh"
4312853Sgabeblack@google.com#include "universe.hh"
4412853Sgabeblack@google.com
4512853Sgabeblack@google.com#ifdef __M5_NAN
4612853Sgabeblack@google.comfloat
4712853Sgabeblack@google.com__nan()
4812853Sgabeblack@google.com{
4912853Sgabeblack@google.com    union {
5012853Sgabeblack@google.com        uint32_t ui;
5112853Sgabeblack@google.com        float f;
5212853Sgabeblack@google.com    } nan;
5312853Sgabeblack@google.com
5412853Sgabeblack@google.com    nan.ui = 0x7fc00000;
5512853Sgabeblack@google.com    return nan.f;
5612853Sgabeblack@google.com}
5712853Sgabeblack@google.com#endif
5812853Sgabeblack@google.com
5912853Sgabeblack@google.com#ifdef STAT_DEBUG
6012853Sgabeblack@google.comstatic int total_stats = 0;
6112853Sgabeblack@google.com#endif
6212853Sgabeblack@google.com
6312853Sgabeblack@google.comusing namespace std;
6412853Sgabeblack@google.com
6512853Sgabeblack@google.com// This is a hack to get this parameter from the old stats package.
6612853Sgabeblack@google.comnamespace Statistics {
6712853Sgabeblack@google.combool PrintDescriptions = true;
6812853Sgabeblack@google.com
6912853Sgabeblack@google.comnamespace Detail {
7012853Sgabeblack@google.comstruct SubData
7112853Sgabeblack@google.com{
7212853Sgabeblack@google.com    string name;
7312853Sgabeblack@google.com    string desc;
7412853Sgabeblack@google.com};
7512853Sgabeblack@google.com
7612853Sgabeblack@google.comstruct StatData
7712853Sgabeblack@google.com{
7812853Sgabeblack@google.com    StatData();
7912853Sgabeblack@google.com    ~StatData();
8012853Sgabeblack@google.com
8112853Sgabeblack@google.com    bool init;
8212853Sgabeblack@google.com    bool print;
8312853Sgabeblack@google.com    string name;
8412853Sgabeblack@google.com    vector<SubData> *subdata;
8512853Sgabeblack@google.com    string desc;
8612853Sgabeblack@google.com    int precision;
8712853Sgabeblack@google.com    FormatFlags flags;
8812853Sgabeblack@google.com    const Stat *prereq;
8912853Sgabeblack@google.com};
9012853Sgabeblack@google.com
9112853Sgabeblack@google.comStatData::StatData()
9212853Sgabeblack@google.com    : init(false), print(false), subdata(NULL), precision(-1), flags(none),
9312853Sgabeblack@google.com      prereq(NULL)
9412853Sgabeblack@google.com{
9512853Sgabeblack@google.com}
9612853Sgabeblack@google.com
9712853Sgabeblack@google.comStatData::~StatData()
9812853Sgabeblack@google.com{
9912853Sgabeblack@google.com    if (subdata)
10012853Sgabeblack@google.com        delete subdata;
10112853Sgabeblack@google.com}
10212853Sgabeblack@google.com
10312853Sgabeblack@google.comclass Database
10412853Sgabeblack@google.com{
10512853Sgabeblack@google.com  private:
10612853Sgabeblack@google.com    Database(const Database &) {}
10712853Sgabeblack@google.com
10812853Sgabeblack@google.com  private:
10912853Sgabeblack@google.com    typedef list<Stat *> list_t;
11012853Sgabeblack@google.com    typedef map<const Stat *, StatData *> map_t;
11112853Sgabeblack@google.com
11212853Sgabeblack@google.com    list_t allStats;
11312853Sgabeblack@google.com    list_t printStats;
11412853Sgabeblack@google.com    map_t map;
11512853Sgabeblack@google.com
11612853Sgabeblack@google.com  public:
11712853Sgabeblack@google.com    Database();
11812853Sgabeblack@google.com    ~Database();
11912853Sgabeblack@google.com
12012853Sgabeblack@google.com    void dump(ostream &stream);
12112853Sgabeblack@google.com
12212853Sgabeblack@google.com    StatData *find(const Stat *stat);
12312853Sgabeblack@google.com    void check();
12412853Sgabeblack@google.com    void regStat(Stat *stat);
12512853Sgabeblack@google.com    StatData *print(Stat *stat);
12612853Sgabeblack@google.com};
12712853Sgabeblack@google.com
12812853Sgabeblack@google.comDatabase::Database()
12912853Sgabeblack@google.com{}
13012853Sgabeblack@google.com
13112853Sgabeblack@google.comDatabase::~Database()
13212853Sgabeblack@google.com{}
13312853Sgabeblack@google.com
13412853Sgabeblack@google.comvoid
13512853Sgabeblack@google.comDatabase::dump(ostream &stream)
13612853Sgabeblack@google.com{
13712853Sgabeblack@google.com    list_t::iterator i = printStats.begin();
13812853Sgabeblack@google.com    list_t::iterator end = printStats.end();
13912853Sgabeblack@google.com
14012853Sgabeblack@google.com    while (i != end) {
14112853Sgabeblack@google.com        Stat *stat = *i;
14212853Sgabeblack@google.com        if (stat->dodisplay())
14312853Sgabeblack@google.com            stat->display(stream);
14412853Sgabeblack@google.com        ++i;
14512853Sgabeblack@google.com    }
14612853Sgabeblack@google.com}
14712853Sgabeblack@google.com
14812853Sgabeblack@google.comStatData *
14912853Sgabeblack@google.comDatabase::find(const Stat *stat)
15012853Sgabeblack@google.com{
15112853Sgabeblack@google.com    map_t::const_iterator i = map.find(stat);
15212853Sgabeblack@google.com
15312853Sgabeblack@google.com    if (i == map.end())
15412853Sgabeblack@google.com        return NULL;
15512853Sgabeblack@google.com
15612853Sgabeblack@google.com    return (*i).second;
15712853Sgabeblack@google.com}
15812853Sgabeblack@google.com
15912853Sgabeblack@google.comvoid
16012853Sgabeblack@google.comDatabase::check()
16112853Sgabeblack@google.com{
16212853Sgabeblack@google.com    list_t::iterator i = allStats.begin();
16312853Sgabeblack@google.com    list_t::iterator end = allStats.end();
16412853Sgabeblack@google.com
16512853Sgabeblack@google.com    while (i != end) {
16612853Sgabeblack@google.com        Stat *stat = *i;
16712853Sgabeblack@google.com        StatData *data = find(stat);
16812853Sgabeblack@google.com        if (!data || !data->init) {
16912853Sgabeblack@google.com#ifdef STAT_DEBUG
17012853Sgabeblack@google.com            cprintf("this is stat number %d\n",(*i)->number);
17112853Sgabeblack@google.com#endif
17212853Sgabeblack@google.com            panic("Not all stats have been initialized");
17312853Sgabeblack@google.com        }
17412853Sgabeblack@google.com
17512853Sgabeblack@google.com        if (data->print) {
17612853Sgabeblack@google.com            if (data->name.empty())
17712853Sgabeblack@google.com                panic("all printable stats must be named");
17812853Sgabeblack@google.com
17912853Sgabeblack@google.com            list_t::iterator j = printStats.insert(printStats.end(), *i);
18012853Sgabeblack@google.com            inplace_merge(printStats.begin(), j,
18112853Sgabeblack@google.com                          printStats.end(), Stat::less);
18212853Sgabeblack@google.com        }
18312853Sgabeblack@google.com
18412853Sgabeblack@google.com        ++i;
18512853Sgabeblack@google.com    }
18612853Sgabeblack@google.com}
18712853Sgabeblack@google.com
18812853Sgabeblack@google.comvoid
18912853Sgabeblack@google.comDatabase::regStat(Stat *stat)
19012853Sgabeblack@google.com{
19112853Sgabeblack@google.com    if (map.find(stat) != map.end())
19212853Sgabeblack@google.com        panic("shouldn't register stat twice!");
19312853Sgabeblack@google.com
19412853Sgabeblack@google.com    allStats.push_back(stat);
19512853Sgabeblack@google.com
19612853Sgabeblack@google.com    StatData *data = new StatData;
19712853Sgabeblack@google.com    bool success = (map.insert(make_pair(stat, data))).second;
19812853Sgabeblack@google.com    assert(map.find(stat) != map.end());
19912853Sgabeblack@google.com    assert(success && "this should never fail");
20012853Sgabeblack@google.com}
20112853Sgabeblack@google.com
20212853Sgabeblack@google.combool
20312853Sgabeblack@google.comStat::less(Stat *stat1, Stat *stat2)
20412853Sgabeblack@google.com{
20512853Sgabeblack@google.com    const string &name1 = stat1->myname();
20612853Sgabeblack@google.com    const string &name2 = stat2->myname();
20712853Sgabeblack@google.com
20812853Sgabeblack@google.com    vector<string> v1;
209    vector<string> v2;
210
211    tokenize(v1, name1, '.');
212    tokenize(v2, name2, '.');
213
214    int last = min(v1.size(), v2.size()) - 1;
215    for (int i = 0; i < last; ++i)
216        if (v1[i] != v2[i])
217            return v1[i] < v2[i];
218
219    // Special compare for last element.
220    if (v1[last] == v2[last])
221        return v1.size() < v2.size();
222    else
223        return v1[last] < v2[last];
224
225    return false;
226}
227
228StatData *
229Database::print(Stat *stat)
230{
231    StatData *data = find(stat);
232    assert(data);
233
234    data->print = true;
235
236    return data;
237}
238
239Database &
240StatDB()
241{
242    static Database db;
243    return db;
244}
245
246Stat::Stat(bool reg)
247{
248#if 0
249    // This assert can help you find that pesky stat.
250    assert(this != (void *)0xbffff5c0);
251#endif
252
253    if (reg)
254        StatDB().regStat(this);
255#ifdef STAT_DEBUG
256    number = ++total_stats;
257    cprintf("I'm stat number %d\n",number);
258#endif
259}
260
261void
262Stat::setInit()
263{ mydata()->init = true; }
264
265StatData *
266Stat::mydata()
267{
268    StatData *data = StatDB().find(this);
269    assert(data);
270
271    return data;
272}
273
274const StatData *
275Stat::mydata() const
276{
277    StatData *data = StatDB().find(this);
278    assert(data);
279
280    return data;
281}
282
283const SubData *
284Stat::mysubdata(int index) const
285{
286    assert(index >= 0);
287    if (index >= size())
288        return NULL;
289
290    const StatData *data = this->mydata();
291    if (!data->subdata || data->subdata->size() <= index)
292        return NULL;
293
294    return &(*data->subdata)[index];
295}
296
297SubData *
298Stat::mysubdata_create(int index)
299{
300    int size = this->size();
301    assert(index >= 0 && (size == 0 || size > 0 && index < size));
302
303    StatData *data = this->mydata();
304    if (!data->subdata) {
305        if (!data->subdata) {
306            if (size == 0)
307                size = index + 1;
308
309            data->subdata = new vector<SubData>(size);
310        }
311    } else if (data->subdata->size() <= index)
312            data->subdata->resize(index + 1);
313
314    SubData *sd = &(*data->subdata)[index];
315    assert(sd);
316
317    return sd;
318}
319
320string
321Stat::myname() const
322{ return mydata()->name; }
323
324string
325Stat::mysubname(int index) const
326{
327    const SubData *sd = mysubdata(index);
328    return sd ? sd->name : "";
329}
330
331string
332Stat::mydesc() const
333{ return mydata()->desc; }
334
335string
336Stat::mysubdesc(int index) const
337{
338    const SubData *sd = mysubdata(index);
339    return sd ? sd->desc : "";
340}
341
342int
343Stat::myprecision() const
344{ return mydata()->precision; }
345
346FormatFlags
347Stat::myflags() const
348{ return mydata()->flags; }
349
350bool
351Stat::dodisplay() const
352{ return !mydata()->prereq || !mydata()->prereq->zero(); }
353
354StatData *
355Stat::print()
356{
357    StatData *data = StatDB().print(this);
358    assert(data && data->init);
359
360    return data;
361}
362
363Stat &
364Stat::name(const string &name)
365{
366    print()->name = name;
367    return *this;
368}
369
370Stat &
371Stat::desc(const string &desc)
372{
373    print()->desc = desc;
374    return *this;
375}
376
377Stat &
378Stat::precision(int precision)
379{
380    print()->precision = precision;
381    return *this;
382}
383
384Stat &
385Stat::flags(FormatFlags flags)
386{
387    if (flags & __reserved)
388        panic("Cannot set reserved flags!\n");
389
390    print()->flags |= flags;
391    return *this;
392}
393
394Stat &
395Stat::prereq(const Stat &prereq)
396{
397    print()->prereq = &prereq;
398    return *this;
399}
400
401Stat &
402Stat::subname(int index, const string &name)
403{
404    print();
405    mysubdata_create(index)->name = name;
406    return *this;
407}
408Stat &
409Stat::subdesc(int index, const string &desc)
410{
411    print();
412    mysubdata_create(index)->desc = desc;
413    return *this;
414}
415
416bool
417ScalarStat::zero() const
418{
419    return val() == 0.0;
420}
421
422bool
423VectorStat::zero() const
424{
425    return val()[0] == 0.0;
426}
427
428string
429ValueToString(result_t value, int precision)
430{
431    stringstream val;
432
433    if (!isnan(value)) {
434        if (precision != -1)
435            val.precision(precision);
436        else if (value == rint(value))
437            val.precision(0);
438
439        val.unsetf(ios::showpoint);
440        val.setf(ios::fixed);
441        val << value;
442    } else {
443#ifndef STAT_DISPLAY_COMPAT
444        val << "no value";
445#else
446        val << "<err: div-0>";
447#endif
448    }
449
450    return val.str();
451}
452
453void
454PrintOne(ostream &stream, result_t value,
455         const string &name, const string &desc, int precision,
456         FormatFlags flags, result_t pdf = NAN, result_t cdf = NAN)
457{
458    if (flags & nozero && value == 0.0 ||
459        flags & nonan && isnan(value))
460        return;
461
462    stringstream pdfstr, cdfstr;
463
464    if (!isnan(pdf))
465        ccprintf(pdfstr, "%.2f%%", pdf * 100.0);
466
467    if (!isnan(cdf))
468        ccprintf(cdfstr, "%.2f%%", cdf * 100.0);
469
470#ifdef STAT_DISPLAY_COMPAT
471    if (flags & __substat) {
472        ccprintf(stream, "%32s%12s%10s%10s", name,
473                 ValueToString(value, precision),
474                 pdfstr, cdfstr);
475    } else
476#endif
477    {
478        ccprintf(stream, "%-40s%12s%10s%10s", name,
479                 ValueToString(value, precision), pdfstr, cdfstr);
480    }
481
482    if (PrintDescriptions) {
483        if (!desc.empty())
484            ccprintf(stream, " # %s", desc);
485    }
486    stream << endl;
487}
488
489void
490ScalarStat::display(ostream &stream) const
491{
492    PrintOne(stream, val(), myname(), mydesc(), myprecision(), myflags());
493}
494
495void
496VectorStat::display(ostream &stream) const
497{
498    bool have_subname = false;
499    bool have_subdesc = false;
500    int size = this->size();
501    for (int i = 0; i < size; ++i) {
502        if (!mysubname(i).empty())
503            have_subname = true;
504        if (!mysubdesc(i).empty())
505            have_subdesc = true;
506    }
507
508    vector<string> *subnames = 0;
509    vector<string> *subdescs = 0;
510    if (have_subname) {
511        subnames = new vector<string>(size);
512        for (int i = 0; i < size; ++i)
513            (*subnames)[i] = mysubname(i);
514    }
515    if (have_subdesc) {
516        subdescs = new vector<string>(size);
517        for (int i = 0; i < size; ++i)
518            (*subdescs)[i] = mysubdesc(i);
519    }
520
521    VectorDisplay(stream, myname(), subnames, mydesc(), subdescs,
522                  myprecision(), myflags(), val(), total());
523}
524
525#ifndef STAT_DISPLAY_COMPAT
526#define NAMESEP "::"
527#else
528#define NAMESEP "_"
529#endif
530
531#ifndef STAT_DISPLAY_COMPAT
532void
533VectorDisplay(std::ostream &stream,
534              const std::string &myname,
535              const std::vector<std::string> *mysubnames,
536              const std::string &mydesc,
537              const std::vector<std::string> *mysubdescs,
538              int myprecision, FormatFlags myflags,
539              const rvec_t &vec, result_t mytotal)
540{
541    int _size = vec.size();
542    result_t _total = 0.0;
543    result_t _pdf, _cdf = 0.0;
544
545    if (myflags & (pdf | cdf)) {
546        for (int i = 0; i < _size; ++i) {
547            _total += vec[i];
548        }
549    }
550
551    if (_size == 1) {
552        PrintOne(stream, vec[0], myname, mydesc, myprecision, myflags);
553    } else {
554        for (int i = 0; i < _size; ++i) {
555            string subname;
556            if (mysubnames) {
557                subname = (*mysubnames)[i];
558                if (subname.empty())
559                    continue;
560            } else {
561                subname = to_string(i);
562            }
563
564            string name = myname + NAMESEP + subname;
565            if (!(myflags & pdf))
566                PrintOne(stream, vec[i], name, mydesc, myprecision, myflags);
567            else {
568                _pdf = vec[i] / _total;
569                _cdf += _pdf;
570                PrintOne(stream, vec[i], name, mydesc, myprecision, myflags,
571                         _pdf, _cdf);
572            }
573        }
574
575        if (myflags & total)
576            PrintOne(stream, mytotal, myname + NAMESEP + "total",
577                     mydesc, myprecision, myflags);
578    }
579}
580#else
581void
582VectorDisplay(std::ostream &stream,
583              const std::string &myname,
584              const std::vector<std::string> *mysubnames,
585              const std::string &mydesc,
586              const std::vector<std::string> *mysubdescs,
587              int myprecision, FormatFlags myflags,
588              const rvec_t &vec, result_t mytotal)
589{
590    int _size = vec.size();
591    result_t _total = 0.0;
592    result_t _pdf, _cdf = 0.0;
593
594    if (myflags & (pdf | cdf)) {
595        for (int i = 0; i < _size; ++i) {
596            _total += vec[i];
597        }
598    }
599
600    if (_size == 1) {
601        PrintOne(stream, vec[0], myname, mydesc, myprecision, myflags);
602    } else {
603        if (myflags & total)
604            PrintOne(stream, mytotal, myname, mydesc, myprecision, myflags);
605
606        if (myflags & dist) {
607            ccprintf(stream, "%s.start_dist\n", myname);
608            for (int i = 0; i < _size; ++i) {
609                string subname, subdesc;
610                subname = to_string(i);
611                if (mysubnames) {
612                    if (!subname.empty()) {
613                        subname = (*mysubnames)[i];
614                    }
615                }
616                if (mysubdescs) {
617                    subdesc = (*mysubdescs)[i];
618                }
619                if (!(myflags & (pdf | cdf))) {
620                    PrintOne(stream, vec[i], subname, subdesc, myprecision,
621                             myflags | __substat);
622                } else {
623                    if (_total) {
624                        _pdf = vec[i] / _total;
625                        _cdf += _pdf;
626                    } else {
627                        _pdf = _cdf = 0.0;
628                    }
629                    if (!(myflags & cdf)) {
630                        PrintOne(stream, vec[i], subname, subdesc, myprecision,
631                                 myflags | __substat, _pdf);
632                    } else {
633                        PrintOne(stream, vec[i], subname, subdesc, myprecision,
634                                 myflags | __substat, _pdf, _cdf);
635                    }
636                }
637            }
638            ccprintf(stream, "%s.end_dist\n", myname);
639        } else {
640            for (int i = 0; i < _size; ++i) {
641                string subname;
642                if (mysubnames) {
643                    subname = (*mysubnames)[i];
644                    if (subname.empty())
645                        continue;
646                } else {
647                    subname = to_string(i);
648                }
649
650                string name = myname + NAMESEP + subname;
651                if (!(myflags & pdf)) {
652                    PrintOne(stream, vec[i], name, mydesc, myprecision,
653                             myflags);
654                } else {
655                    if (_total) {
656                        _pdf = vec[i] / _total;
657                        _cdf += _pdf;
658                    } else {
659                        _pdf = _cdf = 0.0;
660                    }
661                    _pdf = vec[i] / _total;
662                    _cdf += _pdf;
663                    PrintOne(stream, vec[i], name, mydesc, myprecision,
664                             myflags, _pdf, _cdf);
665                }
666            }
667        }
668    }
669}
670#endif
671
672#ifndef STAT_DISPLAY_COMPAT
673void
674DistDisplay(ostream &stream, const string &name, const string &desc,
675            int precision, FormatFlags flags,
676            result_t min_val, result_t max_val,
677            result_t underflow, result_t overflow,
678            const rvec_t &vec, int min, int max, int bucket_size, int size);
679{
680    assert(size == vec.size());
681
682    result_t total = 0.0;
683    result_t pdf, cdf = 0.0;
684
685    total += underflow;
686    for (int i = 0; i < size; ++i)
687        total += vec[i];
688    total += overflow;
689
690    pdf = underflow / total;
691    cdf += pdf;
692
693    PrintOne(stream, underflow, name + NAMESEP + "underflow", desc,
694             precision, myflags, pdf, cdf);
695
696    for (int i = 0; i < size; ++i) {
697        stringstream namestr;
698        namestr << name;
699
700        int low = i * bucket_size + min;
701        int high = ::std::min((i + 1) * bucket_size + min - 1, max);
702        namestr << low;
703        if (low < high)
704            namestr << "-" << high;
705
706        pdf = vec[i] / total;
707        cdf += pdf;
708        PrintOne(stream, vec[i], namestr.str(), desc, precision, myflags,
709                 pdf, cdf);
710    }
711
712    pdf = overflow / total;
713    cdf += pdf;
714    PrintOne(stream, overflow, name + NAMESEP + "overflow", desc,
715             precision, myflags, pdf, cdf);
716    PrintOne(stream, total, name + NAMESEP + "total", desc,
717             precision, myflags);
718}
719#else
720void
721DistDisplay(ostream &stream, const string &name, const string &desc,
722            int precision, FormatFlags flags,
723            result_t min_val, result_t max_val,
724            result_t underflow, result_t overflow,
725            const rvec_t &vec, int min, int max, int bucket_size, int size)
726{
727    assert(size == vec.size());
728    string blank;
729
730    result_t total = 0.0;
731
732    total += underflow;
733    for (int i = 0; i < size; ++i)
734        total += vec[i];
735    total += overflow;
736
737    ccprintf(stream, "%-42s", name + ".start_dist");
738    if (PrintDescriptions && !desc.empty())
739        ccprintf(stream, "                     # %s", desc);
740    stream << endl;
741
742    PrintOne(stream, total, name + ".samples", blank, precision, flags);
743    PrintOne(stream, min_val, name + ".min_value", blank, precision, flags);
744
745    if (underflow > 0)
746        PrintOne(stream, min_val, name + ".underflows", blank, precision,
747                 flags);
748
749    int _min;
750    result_t _pdf, _cdf, mypdf, mycdf;
751
752    _cdf = 0.0;
753    for (int i = 0; i < size; ++i) {
754        if (flags & nozero && vec[i] == 0.0 ||
755            flags & nonan && isnan(vec[i]))
756            return;
757
758        _min = i * bucket_size + min;
759        _pdf = vec[i] / total * 100.0;
760        _cdf += _pdf;
761
762        mypdf = (flags & pdf) ? _pdf : NAN;
763        mycdf = (flags & cdf) ? _cdf : NAN;
764
765        PrintOne(stream, vec[i], ValueToString(_min, 0), blank, precision,
766                 flags | __substat, mypdf, mycdf);
767    }
768
769    if (overflow > 0)
770        PrintOne(stream, overflow, name + ".overflows", blank, precision,
771                 flags);
772    PrintOne(stream, max_val, name + ".max_value", blank, precision, flags);
773    ccprintf(stream, "%s.end_dist\n\n", name);
774}
775#endif
776
777void
778FancyDisplay(ostream &stream, const string &name, const string &desc,
779             int precision, FormatFlags flags, result_t mean,
780             result_t variance)
781{
782    result_t stdev = isnan(variance) ? NAN : sqrt(variance);
783    PrintOne(stream, mean, name + NAMESEP + "mean", desc, precision, flags);
784    PrintOne(stream, stdev, name + NAMESEP + "stdev", desc, precision, flags);
785}
786
787BinBase::BinBase(size_t size)
788    : memsize(CeilPow2(size)), mem(NULL)
789{
790}
791
792BinBase::~BinBase()
793{
794    if (mem)
795        delete [] mem;
796}
797
798char *
799BinBase::memory()
800{
801    if (!mem) {
802        mem = new char[memsize];
803        memset(mem, 0, memsize);
804    }
805
806    return mem;
807}
808
809} // namespace Detail
810
811void
812check()
813{
814    Detail::StatDB().check();
815}
816
817void
818dump(ostream &stream)
819{
820    Detail::StatDB().dump(stream);
821}
822
823} // namespace Statistics
824