#ifndef RANKER_H #define RANKER_H #include #include #include using std::vector; using std::string; #ifndef uint typedef unsigned int uint; #endif template class lt { public: static int compare(T a, T b) { return(a < b); } }; template class gt { public: static int compare(T a, T b) { return(a > b); } }; template class ranker { private: const T* p; uint sz; public: ranker(const vector& v) : p(&v[0]), sz(v.size()) { } ranker(const T* tp, uint s) : p(tp), sz(s) { } int operator()(uint i1, uint i2) const { return(C::compare(p[i1],p[i2])); } template void get_orders(vector& w) const { w.resize(sz); w.front() = 0; for (typename vector::iterator i = w.begin(); i != w.end() - 1; ++i) *(i + 1) = *i + 1; std::sort(w.begin(), w.end(), *this); } template void get_partial_orders(vector& w, uint num) const { if (num > sz) num = sz; w.resize(sz); w.front() = 0; for (typename vector::iterator i = w.begin(); i != w.end() - 1; ++i) *(i + 1) = *i + 1; std::partial_sort(w.begin(), w.begin() + num, w.end(), *this); w.resize(num); } template void get_ranks(vector& w, const string& method) const { w.resize(sz); vector tmp(w.size()); get_orders(tmp); if (method == "average") { for (uint c = 0, reps; c < w.size(); c += reps) { reps = 1; while (c + reps < w.size() && p[tmp[c]] == p[tmp[c + reps]]) ++reps; for (uint k = 0; k < reps; ++k) w[tmp[c + k]] = S(2 * c + reps - 1) / 2 + 1; } } else if (method == "min") { for (uint c = 0, reps; c < w.size(); c += reps) { reps = 1; while (c + reps < w.size() && p[tmp[c]] == p[tmp[c + reps]]) ++reps; for (uint k = 0; k < reps; ++k) w[tmp[c + k]] = c + 1; } } else if (method == "max") { for (uint c = 0, reps; c < w.size(); c += reps) { reps = 1; while (c + reps < w.size() && p[tmp[c]] == p[tmp[c + reps]]) ++reps; for (uint k = 0; k < reps; ++k) w[tmp[c + k]] = c + reps; } } else // default for (uint c = 0; c < w.size(); ++c) w[tmp[c]] = c + 1; } template void get_partial_ranks(vector& w, const string& method, uint num) const { if (num > sz) num = sz; vector tmp(sz); get_partial_orders(tmp, num); w.resize(sz); fill(w.begin(), w.end(), 0); if (method == "average") { for (uint c = 0, reps; c < num; c += reps) { reps = 1; while (c + reps < num && p[tmp[c]] == p[tmp[c + reps]]) ++reps; for (uint k = 0; k < reps; ++k) w[tmp[c + k]] = S(2 * c + reps - 1) / 2 + 1; } } else if (method == "min") { for (uint c = 0, reps; c < num; c += reps) { reps = 1; while (c + reps < num && p[tmp[c]] == p[tmp[c + reps]]) ++reps; for (uint k = 0; k < reps; ++k) w[tmp[c + k]] = c + 1; } } else if (method == "max") { for (uint c = 0, reps; c < num; c += reps) { reps = 1; while (c + reps < num && p[tmp[c]] == p[tmp[c + reps]]) ++reps; for (uint k = 0; k < reps; ++k) w[tmp[c + k]] = c + reps; } } else // default for (uint c = 0; c < num; ++c) w[tmp[c]] = c + 1; } }; template inline void rank(const vector& v, vector& w, const string& method = "average") { ranker > r(v); r.get_ranks(w, method); } template inline void rank(const T* d, uint size, vector& w, const string& method = "average") { ranker > r(d, size); r.get_ranks(w, method); } template inline void partial_rank(const vector& v, vector& w, uint num, const string& method = "average") { ranker > r(v); r.get_partial_ranks(w, method, num); } template inline void partial_rank(const T* d, uint size, vector& w, uint num, const string& method = "average") { ranker > r(d, size); r.get_partial_ranks(w, method, num); } template inline void order(const vector& v, vector& w) { ranker > r(v); r.get_orders(w); } template inline void order(const T* d, uint size, vector& w) { ranker > r(d, size); r.get_orders(w); } template inline void partial_order(const vector& v, vector& w, uint num) { ranker > r(v); r.get_partial_orders(w, num); } template inline void partial_order(const T* d, uint size, vector& w, uint num) { ranker > r(d, size); r.get_partial_orders(w, num); } template inline void rankhigh(const vector& v, vector& w, const string& method = "average") { ranker > r(v); r.get_ranks(w, method); } template inline void rankhigh(const T* d, uint size, vector& w, const string& method = "average") { ranker > r(d, size); r.get_ranks(w, method); } template inline void partial_rankhigh(const vector& v, vector& w, uint num, const string& method = "average") { ranker > r(v); r.get_partial_ranks(w, method, num); } template inline void partial_rankhigh(const T* d, uint size, vector& w, uint num, const string& method = "average") { ranker > r(d, size); r.get_partial_ranks(w, method, num); } template inline void orderhigh(const vector& v, vector& w) { ranker > r(v); r.get_orders(w); } template inline void orderhigh(const T* d, uint size, vector& w) { ranker > r(d, size); r.get_orders(w); } template inline void partial_orderhigh(const vector& v, vector& w, uint num) { ranker > r(v); r.get_partial_orders(w, num); } template inline void partial_orderhigh(const T* d, uint size, vector& w, uint num) { ranker > r(d, size); r.get_partial_orders(w, num); } template inline T quantile(const T* d, const uint size, const double q) { if (size == 0) return T(0); if (size == 1) return d[0]; if (q <= 0) return *std::min_element(d, d + size); if (q >= 1) return *std::max_element(d, d + size); double pos = (size - 1) * q; uint ind = uint(pos); double delta = pos - ind; vector w(size); std::copy(d, d + size, w.begin()); std::nth_element(w.begin(), w.begin() + ind, w.end()); T i1 = *(w.begin() + ind); T i2 = *std::min_element(w.begin() + ind + 1, w.end()); return i1 * (1.0 - delta) + i2 * delta; } template inline T quantile(const vector& v, const double q) { return quantile(&v[0], v.size(), q); } #endif