Support more ways to binsearch in a vector.

develop
Alexander Gavrilov 2012-01-03 13:07:49 +04:00
parent 326c58f793
commit fb736a8556
2 changed files with 96 additions and 16 deletions

@ -66,36 +66,116 @@ void print_bits ( T val, DFHack::Console& out )
out.print(strs.str().c_str()); out.print(strs.str().c_str());
} }
//FIXME: Error 8 error C4519: default template arguments are only allowed on a class template /*
template <typename CT, typename FT, typename AT/* = FT*/> * Binary search in vectors.
CT *binsearch_in_vector(std::vector<CT*> &vec, FT CT::*field, AT value) */
template <typename FT>
int binsearch_index(const std::vector<FT> &vec, FT key, bool exact = true)
{
// Returns the index of the value >= the key
int min = -1, max = (int)vec.size();
const FT *p = vec.data();
for (;;)
{
int mid = (min + max)>>1;
if (mid == min)
return exact ? -1 : max;
FT midv = p[mid];
if (midv == key)
return mid;
else if (midv < key)
min = mid;
else
max = mid;
}
}
template <typename CT, typename FT>
int binsearch_index(const std::vector<CT*> &vec, FT CT::*field, FT key, bool exact = true)
{ {
// Returns the index of the value >= the key
int min = -1, max = (int)vec.size(); int min = -1, max = (int)vec.size();
CT **p = vec.data(); CT *const *p = vec.data();
FT key = (FT)value;
for (;;) for (;;)
{ {
int mid = (min + max)>>1; int mid = (min + max)>>1;
if (mid == min) if (mid == min)
{ return exact ? -1 : max;
return NULL;
}
FT midv = p[mid]->*field; FT midv = p[mid]->*field;
if (midv == key) if (midv == key)
{ return mid;
return p[mid];
}
else if (midv < key) else if (midv < key)
{
min = mid; min = mid;
}
else else
{
max = mid; max = mid;
}
} }
} }
template <typename CT>
inline int binsearch_index(const std::vector<CT*> &vec, typename CT::key_field_type key, bool exact = true)
{
return CT::binsearch_index(vec, key, exact);
}
template <typename CT>
inline int binsearch_index(const std::vector<CT*> &vec, typename CT::key_pointer_type key, bool exact = true)
{
return CT::binsearch_index(vec, key, exact);
}
template<typename FT, typename KT>
inline bool vector_contains(const std::vector<FT> &vec, KT key)
{
return binsearch_index(vec, key) >= 0;
}
template<typename CT, typename FT>
inline bool vector_contains(const std::vector<CT*> &vec, FT CT::*field, FT key)
{
return binsearch_index(vec, field, key) >= 0;
}
template<typename FT>
unsigned insert_into_vector(std::vector<FT> &vec, FT key, bool *inserted = NULL)
{
unsigned pos = (unsigned)binsearch_index(vec, key, false);
bool to_ins = (pos >= vec.size() || vec[pos] != key);
if (inserted) *inserted = to_ins;
if (to_ins)
vec.insert(vec.begin()+pos,key);
return pos;
}
template<typename CT, typename FT>
unsigned insert_into_vector(std::vector<CT*> &vec, FT CT::*field, CT *obj, bool *inserted = NULL)
{
unsigned pos = (unsigned)binsearch_index(vec, field, obj->*field, false);
bool to_ins = (pos >= vec.size() || vec[pos] != obj);
if (inserted) *inserted = to_ins;
if (to_ins)
vec.insert(vec.begin()+pos,obj);
return pos;
}
template <typename CT, typename KT>
CT *binsearch_in_vector(const std::vector<CT*> &vec, KT value)
{
int idx = binsearch_index(vec, value);
return idx < 0 ? NULL : vec[idx];
}
template <typename CT, typename FT>
CT *binsearch_in_vector(const std::vector<CT*> &vec, FT CT::*field, FT value)
{
int idx = binsearch_index(vec, field, value);
return idx < 0 ? NULL : vec[idx];
}
/*
* MISC
*/
/** /**
* Returns the amount of milliseconds elapsed since the UNIX epoch. * Returns the amount of milliseconds elapsed since the UNIX epoch.
* Works on both windows and linux. * Works on both windows and linux.

@ -1 +1 @@
Subproject commit 7b89e595811ed81b012a805131aa10a89d451e76 Subproject commit c99be2349fef32db026af7541676e2e4f24e4636