// histogram.hpp // // Copyright (C) 2004-2020 MicroNeil Research Corporation. // // This software is released under the MIT license. See LICENSE.TXT. #pragma once #include namespace codedweller { /** The Histogram class is managed set of HistogramRecords. *** We play some naughty tricks with pointers to break the rules and *** directly manipulate the counts of HistogramRecords stored in the *** set - thus saving space, complexity, and cycles. The set allows us *** to add new records as needed and locate existing records quickly. *** At any point in time, the set contains all of the event (hit) counts *** ordered by key. **/ class HistogramRecord { // A record to assocate a key and count. public: int Key; // Here is the key. mutable int Count; // Here is the count. HistogramRecord(const int NewKey) : // We must have a key to make one. Key(NewKey), Count(0) {} // and a new one starts at count 0. bool operator<(const HistogramRecord& Right) const { // To live in a set we need to < return (Key < Right.Key); // properly based on the key. } }; class Histogram : public std::set { // A Histogram is a set of HistogramRecords private: // and a private hit counter... int HitCount; public: Histogram() : HitCount(0) {} // with a few extra public functions. The int hit(const int EventKey, const int Adjustment = 1) { // hit() method increments a specific count. HistogramRecord E(EventKey); // First, make a record for the event key. insert(E); // Insert the new record (if it's not there). std::set::iterator iE = // Find either the pre-existing or the new find(E); // record for this key. int* C; // Play naughty pointer games to access C = const_cast(&((*iE).Count)); // the Count for this record inside the (*C) += Adjustment; // set and add our Adjustment to it. HitCount += Adjustment; // Accumulate the adjustments overall. return(*C); // Return the count for this key. } int Hits() { return HitCount; } // Return the sum of hits so far. void reset() { // Reset the histogram to zero. HitCount = 0; // That means no counts, and clear(); // an empty set of records. } }; } // End namespace codedweller