#ifndef BINNING_H #define BINNING_H #include #include struct BinningRange { float min; float max; BinningRange(float min, float max) : min(min), max(max) {;} float getWidth() const {return max-min;} }; template class Binning { private: /** size to use for each dimension's bin */ std::vector binSizes; std::vector binRanges; std::unordered_set used; public: /** add a new dimension for binning with its corresponding size */ void setBinSizes(const std::vector binSizes) { this->binSizes = binSizes; } /** manually set min/max range for each dimension */ void setRanges(const std::vector ranges) { this->binRanges = ranges; } /** estimate each dimension's min/max from the given entry set */ void setRanges(const std::vector& entries) { clearUsed(); binRanges.clear(); // process each to-be-binned dimension const int numDimensions = binSizes.size(); for (int dim = 0; dim < numDimensions; ++dim) { // determin min and max value for the current dimension BinningRange r(+1e30, -1e30); for (const Binable& b : entries) { const float val = b.getBinValue(dim); if(val < r.min) {r.min = val;} if(val > r.max) {r.max = val;} } // remember binRanges.push_back(r); } } /** remove all tracked usages */ void clearUsed() { used.clear(); } /** does the given element relate to an used or unsed bin? */ bool isFree(const Binable& b) const { const uint64_t hash = getHash(b); return used.find(hash) == used.end(); } /** mark the bin the given element belongs to as used */ void markUsed(const Binable& b) { const uint64_t hash = getHash(b); used.insert(hash); } private: /** calculate unique-bin-hash for the given element */ uint64_t getHash(const Binable& b) const { uint64_t hash = 0; const int numDimensions = binSizes.size(); for (int dim = 0; dim < numDimensions; ++dim) { // get binable's value for the current dimension const float val = b.getBinValue(dim); // snap value to bin-number const int binNr = std::round((val-binRanges[dim].min) / binSizes[dim]); // maximum binNr const int binNrMax = binRanges[dim].getWidth() / binSizes[dim]; // sanity check //if (binNr < 0 || binNr > 255) {throw "bin index out of range!!";} // update hash hash *= (binNrMax+1); hash += binNr; } // done return hash; } }; #endif // BINNING_H