114
misc/Binning.h
Normal file
114
misc/Binning.h
Normal file
@@ -0,0 +1,114 @@
|
||||
#ifndef BINNING_H
|
||||
#define BINNING_H
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
|
||||
struct BinningRange {
|
||||
float min;
|
||||
float max;
|
||||
BinningRange(float min, float max) : min(min), max(max) {;}
|
||||
float getWidth() const {return max-min;}
|
||||
};
|
||||
|
||||
template <typename Binable> class Binning {
|
||||
|
||||
private:
|
||||
|
||||
/** size to use for each dimension's bin */
|
||||
std::vector<float> binSizes;
|
||||
|
||||
std::vector<BinningRange> binRanges;
|
||||
|
||||
std::unordered_set<uint64_t> used;
|
||||
|
||||
public:
|
||||
|
||||
/** add a new dimension for binning with its corresponding size */
|
||||
void setBinSizes(const std::vector<float> binSizes) {
|
||||
this->binSizes = binSizes;
|
||||
}
|
||||
|
||||
/** manually set min/max range for each dimension */
|
||||
void setRanges(const std::vector<BinningRange> ranges) {
|
||||
this->binRanges = ranges;
|
||||
}
|
||||
|
||||
/** estimate each dimension's min/max from the given entry set */
|
||||
void setRanges(const std::vector<Binable>& 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
|
||||
Reference in New Issue
Block a user