115 lines
2.4 KiB
C++
115 lines
2.4 KiB
C++
#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
|