mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 06:05:58 -06:00
1567 lines
42 KiB
C++
1567 lines
42 KiB
C++
template <class T>
|
|
inline int sgn(T a) { return a > 0 ? 1 : a < 0 ? -1 : 0; }
|
|
|
|
template <class T>
|
|
inline T tabs(T a) { return (a >= 0 ? a : -a); }
|
|
|
|
template <class T>
|
|
inline int cmp(const T& a, const T& b) { return a > b ? 1 : a < b ? -1 : 0; }
|
|
|
|
template <class I>
|
|
void Reverse(I start, I end)
|
|
{
|
|
if(start != end && --end != start)
|
|
do
|
|
IterSwap(start, end);
|
|
while(++start != end && --end != start);
|
|
}
|
|
|
|
template <class C>
|
|
void Reverse(C& container)
|
|
{
|
|
Reverse(container.Begin(), container.End());
|
|
}
|
|
|
|
template <class T, class V>
|
|
void Sum(V& sum, T ptr, T end)
|
|
|
|
{
|
|
while(ptr != end)
|
|
sum += *ptr++;
|
|
}
|
|
|
|
template <class T>
|
|
typename T::ValueType Sum(const T& c, const typename T::ValueType& init = typename T::ValueType())
|
|
{
|
|
typename T::ValueType sum = init;
|
|
Sum(sum, c.Begin(), c.End());
|
|
return sum;
|
|
}
|
|
|
|
template <class T>
|
|
typename T::ValueType Sum0(const T& c)
|
|
{
|
|
typename T::ValueType sum = 0;
|
|
Sum(sum, c.Begin(), c.End());
|
|
return sum;
|
|
}
|
|
|
|
template <class T>
|
|
T MinElement(T ptr, T end)
|
|
{
|
|
ASSERT(ptr != end);
|
|
T min = ptr;
|
|
while(++ptr != end)
|
|
if(*ptr < *min) min = ptr;
|
|
return min;
|
|
}
|
|
|
|
template <class C>
|
|
int MinIndex(const C& c)
|
|
{
|
|
if(c.GetCount() == 0)
|
|
return -1;
|
|
typename C::ValueType m = c[0];
|
|
int mi = 0;
|
|
for(int i = 1; i < c.GetCount(); i++)
|
|
if(c[i] < m) {
|
|
m = c[i];
|
|
mi = i;
|
|
}
|
|
return mi;
|
|
}
|
|
|
|
template <class C>
|
|
int MaxIndex(const C& c)
|
|
{
|
|
if(c.GetCount() == 0)
|
|
return -1;
|
|
typename C::ValueType m = c[0];
|
|
int mi = 0;
|
|
for(int i = 1; i < c.GetCount(); i++)
|
|
if(c[i] > m) {
|
|
m = c[i];
|
|
mi = i;
|
|
}
|
|
return mi;
|
|
}
|
|
|
|
template <class T>
|
|
const typename T::ValueType& Min(const T& c)
|
|
{
|
|
return *MinElement(c.Begin(), c.End());
|
|
}
|
|
|
|
template <class T>
|
|
T MaxElement(T ptr, T end)
|
|
{
|
|
ASSERT(ptr != end);
|
|
T max = ptr;
|
|
while(++ptr != end)
|
|
if(*max < *ptr) max = ptr;
|
|
return max;
|
|
}
|
|
|
|
template <class T>
|
|
const typename T::ValueType& Max(const T& c)
|
|
{
|
|
return *MaxElement(c.Begin(), c.End());
|
|
}
|
|
|
|
template<class T>
|
|
struct StdEqual
|
|
{
|
|
bool operator () (const T& a, const T& b) const { return a == b; }
|
|
};
|
|
|
|
template<class T>
|
|
struct StdLess {
|
|
bool operator () (const T& a, const T& b) const { return a < b; }
|
|
};
|
|
|
|
template<class T>
|
|
struct StdGreater
|
|
{
|
|
bool operator () (const T& a, const T& b) const { return a > b; }
|
|
};
|
|
|
|
/*
|
|
template <class T, class C>
|
|
bool Compare(T ptr1, T end1, T ptr2, T end2, const C& compare)
|
|
{
|
|
for(; ptr1 != end1 && ptr2 != end2; ++ptr1, ++ptr2)
|
|
if(!compare(*ptr1, *ptr2)) return false;
|
|
return ptr1 == end1 && ptr2 == end2;
|
|
}
|
|
|
|
template <class T, class C>
|
|
bool Compare(const T& c1, const T& c2, const C& compare)
|
|
{
|
|
return Compare(c1.Begin(), c1.End(), c2.Begin(), c2.End(), compare);
|
|
}
|
|
|
|
template <class T>
|
|
bool Compare(const T& c1, const T& c2)
|
|
{
|
|
typedef typename T::ValueType VT;
|
|
return Compare(c1, c2, StdEqual<VT>());
|
|
}
|
|
*/
|
|
|
|
template <class T, class C>
|
|
bool IsEqual(T ptr1, T end1, T ptr2, T end2, const C& equal)
|
|
{
|
|
for(; ptr1 != end1 && ptr2 != end2; ++ptr1, ++ptr2)
|
|
if(!equal(*ptr1, *ptr2)) return false;
|
|
return ptr1 == end1 && ptr2 == end2;
|
|
}
|
|
|
|
template <class T, class C>
|
|
bool IsEqual(const T& c1, const T& c2, const C& equal)
|
|
{
|
|
return IsEqual(c1.Begin(), c1.End(), c2.Begin(), c2.End(), equal);
|
|
}
|
|
|
|
template <class T>
|
|
bool IsEqual(const T& c1, const T& c2)
|
|
{
|
|
typedef typename T::ValueType VT;
|
|
return IsEqual(c1, c2, StdEqual<VT>());
|
|
}
|
|
|
|
template <class T, class V, class C>
|
|
T Find(T ptr, T end, const V& value, const C& equal)
|
|
{
|
|
while(ptr != end) {
|
|
if(equal(*ptr, value)) return ptr;
|
|
ptr++;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
template <class T, class V>
|
|
T Find(T ptr, T end, const V& value)
|
|
{
|
|
return Find(ptr, end, value, StdEqual<T>());
|
|
}
|
|
|
|
template <class T, class V, class C>
|
|
int FindIndex(const T& cont, const V& value, const C& equal)
|
|
{
|
|
for(int i = 0; i < cont.GetCount(); i++)
|
|
if(equal(cont[i], value)) return i;
|
|
return -1;
|
|
}
|
|
|
|
template <class T, class V>
|
|
int FindIndex(const T& cont, const V& value)
|
|
{
|
|
for(int i = 0; i < cont.GetCount(); i++)
|
|
if(cont[i] == value) return i;
|
|
return -1;
|
|
}
|
|
|
|
template <class I, class K, class L>
|
|
int BinFindIndex(I begin, I end, const K& key, const L& less)
|
|
{
|
|
if(begin == end)
|
|
return 0;
|
|
int min = 0;
|
|
int max = end - begin;
|
|
|
|
while(min < max)
|
|
{
|
|
int mid = (max + min) >> 1;
|
|
if(less(*(begin + mid), key))
|
|
min = mid + 1;
|
|
else
|
|
max = mid;
|
|
}
|
|
return min;
|
|
}
|
|
|
|
template <class C, class K, class L>
|
|
inline int BinFindIndex(const C& container, const K& key, const L& less)
|
|
{
|
|
return BinFindIndex(container.Begin(), container.End(), key, less);
|
|
}
|
|
|
|
template <class C, class K>
|
|
inline int BinFindIndex(const C& container, const K& key)
|
|
{
|
|
typedef typename C::ValueType VT;
|
|
return BinFindIndex(container, key, StdLess<VT>());
|
|
}
|
|
|
|
template <class I, class K, class L>
|
|
inline I BinFind(I begin, I end, const K& key, const L& less)
|
|
{
|
|
return begin + BinFindIndex(begin, end, key, less);
|
|
}
|
|
|
|
template <class C, class K, class L>
|
|
inline typename C::ConstIterator BinFind(const C& container, const K& key, const L& less)
|
|
{
|
|
return BinFind(container.Begin(), container.End(), key, less);
|
|
}
|
|
|
|
template <class C, class K>
|
|
inline typename C::ConstIterator BinFind(const C& container, const K& key)
|
|
{
|
|
typedef typename C::ValueType VT;
|
|
return BinFind(container, key, StdLess<VT>());
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
template <class I, class C>
|
|
int IterCompare(I a, I a_end, I b, I b_end, const C& compare)
|
|
{
|
|
for(;;) {
|
|
if(a >= a_end)
|
|
return b < b_end ? -1 : 0;
|
|
if(b >= b_end)
|
|
return a < a_end ? 1 : 0;
|
|
int q = compare(*a++, *b++);
|
|
if(q)
|
|
return q;
|
|
}
|
|
}
|
|
|
|
template <class C, class T, class L>
|
|
int FindLowerBound(const C& v, int pos, int count, const T& val, const L& less)
|
|
{
|
|
while(count > 0) {
|
|
int half = count >> 1;
|
|
int m = pos + half;
|
|
if(less(v[m], val)) {
|
|
pos = m + 1;
|
|
count = count - half - 1;
|
|
}
|
|
else
|
|
count = half;
|
|
}
|
|
return pos;
|
|
}
|
|
|
|
template <class I, class T, class L>
|
|
I FindLowerBoundIter(I begin, I end, const T& val, const L& less)
|
|
{
|
|
return begin + FindLowerBound(begin, 0, end - begin, val, less);
|
|
}
|
|
|
|
template <class I, class T>
|
|
I FindLowerBoundIter(I begin, I end, const T& val)
|
|
{
|
|
return begin + FindLowerBound(begin, 0, end - begin, val, StdLess<T>());
|
|
}
|
|
|
|
template <class C, class T, class L>
|
|
int FindLowerBound(const C& v, const T& val, const L& less)
|
|
{
|
|
return FindLowerBound(v, 0, v.GetCount(), val, less);
|
|
}
|
|
|
|
template <class C, class T>
|
|
int FindLowerBound(const C& v, const T& val)
|
|
{
|
|
return FindLowerBound(v, val, StdLess<typename C::ValueType>());
|
|
}
|
|
|
|
template <class C, class T, class L>
|
|
int FindUpperBound(const C& v, int pos, int count, const T& val, const L& less)
|
|
{
|
|
while(count > 0) {
|
|
int half = count >> 1;
|
|
int m = pos + half;
|
|
if(less(val, v[m]))
|
|
count = half;
|
|
else {
|
|
pos = m + 1;
|
|
count = count - half - 1;
|
|
}
|
|
}
|
|
return pos;
|
|
}
|
|
|
|
template <class I, class T, class L>
|
|
I FindUpperBoundIter(I begin, I end, const T& val, const L& less)
|
|
{
|
|
return begin + FindUpperBound(begin, 0, end - begin, val, less);
|
|
}
|
|
|
|
template <class I, class T>
|
|
I FindUpperBoundIter(I begin, I end, const T& val)
|
|
{
|
|
return begin + FindUpperBound(begin, 0, (int)(end - begin), val, StdLess<T>());
|
|
}
|
|
|
|
template <class C, class T, class L>
|
|
int FindUpperBound(const C& v, const T& val, const L& less)
|
|
{
|
|
return FindUpperBound(v, 0, v.GetCount(), val, less);
|
|
}
|
|
|
|
template <class C, class T>
|
|
int FindUpperBound(const C& v, const T& val)
|
|
{
|
|
return FindUpperBound(v, val, StdLess<typename C::ValueType>());
|
|
}
|
|
|
|
template <class C, class T, class L>
|
|
int FindBinary(const C& v, const T& val, int pos, int count, const L& less)
|
|
{
|
|
int i = FindLowerBound(v, pos, count, val, less);
|
|
return i < count && !less(val, v[i]) ? i : -1;
|
|
}
|
|
|
|
template <class I, class T, class L>
|
|
I FindBinaryIter(I begin, I end, const T& val, const L& less)
|
|
{
|
|
int q = FindUpperBound(begin, begin, end, val, less);
|
|
return q < 0 ? NULL : begin + q;
|
|
}
|
|
|
|
template <class I, class T>
|
|
I FindBinaryIter(I begin, I end, const T& val)
|
|
{
|
|
return FindBinaryIter(begin, end, val, StdLess<T>());
|
|
}
|
|
|
|
template <class C, class T, class L>
|
|
int FindBinary(const C& v, const T& val, const L& less)
|
|
{
|
|
return FindBinary(v, val, 0, v.GetCount(), less);
|
|
}
|
|
|
|
template <class C, class T>
|
|
int FindBinary(const C& v, const T& val)
|
|
{
|
|
return FindBinary(v, val, StdLess<typename C::ValueType>());
|
|
}
|
|
|
|
template <class I, class K, class X>
|
|
int BinFindCompIndex(I begin, I end, const K& key, const X& comp)
|
|
{
|
|
if(begin == end) // empty array
|
|
return 0;
|
|
int min = 0;
|
|
int max = end - begin;
|
|
while(min < max)
|
|
{
|
|
int mid = (max + min) >> 1;
|
|
if(comp.Compare(key, *(begin + mid)) > 0)
|
|
min = mid + 1;
|
|
else
|
|
max = mid;
|
|
}
|
|
return min;
|
|
}
|
|
|
|
template <class C, class K, class X>
|
|
inline int BinFindCompIndex(const C& container, const K& key, const X& comp)
|
|
{
|
|
return BinFindCompIndex(container.Begin(), container.End(), key, comp);
|
|
}
|
|
|
|
template <class I, class K, class X>
|
|
inline I BinFindComp(I begin, I end, const K& key, const X& comp)
|
|
{
|
|
return begin + BinFindCompIndex(begin, end, key, comp);
|
|
}
|
|
|
|
template <class C, class K, class X>
|
|
inline typename C::ConstIterator BinFindComp(const C& container, const K& key, const X& comp)
|
|
{
|
|
return BinFindComp(container.Begin(), container.End(), key, comp);
|
|
}
|
|
|
|
template <class T, class V>
|
|
void Append(T& dst, V ptr, V end)
|
|
{
|
|
for(; ptr != end; ++ptr)
|
|
dst.Add(*ptr);
|
|
}
|
|
|
|
template <class T, class V>
|
|
void Append(T& dst, V ptr, int n)
|
|
{
|
|
for(; n--; ++ptr)
|
|
dst.Add(*ptr);
|
|
}
|
|
|
|
template <class T, class V>
|
|
void Append(T& dst, const V& src)
|
|
{
|
|
Append(dst, src.Begin(), src.End());
|
|
}
|
|
|
|
template <class C, class I>
|
|
C& FindAppend(C& dest, I begin, I end)
|
|
{
|
|
for(; begin != end; ++begin)
|
|
dest.FindAdd(*begin);
|
|
return dest;
|
|
}
|
|
|
|
template <class C, class S>
|
|
inline C& FindAppend(C& dest, const S& source)
|
|
{
|
|
return FindAppend(dest, source.Begin(), source.End());
|
|
}
|
|
|
|
template <class C, class L>
|
|
C& AppendSorted(C& dest, const C& src, const L& less)
|
|
{
|
|
if(src.IsEmpty())
|
|
return dest;
|
|
if(dest.IsEmpty())
|
|
{
|
|
dest <<= src;
|
|
return dest;
|
|
}
|
|
if(!less(*src, dest.Top()))
|
|
{
|
|
dest.Append(src);
|
|
return dest;
|
|
}
|
|
if(!less(*dest, src.Top()))
|
|
{
|
|
dest.Insert(0, src);
|
|
return dest;
|
|
}
|
|
int dc = dest.GetCount();
|
|
int sc = src.GetCount();
|
|
dest.SetCount(dc + sc);
|
|
typename C::Iterator de = dest.End();
|
|
typename C::ConstIterator se = src.End(), pe = dest.GetIter(dc);
|
|
--se;
|
|
--pe;
|
|
for(;;)
|
|
{
|
|
if(less(*se, *pe))
|
|
{
|
|
*--de = *pe;
|
|
if(pe == dest.Begin())
|
|
{ // dest items are finished
|
|
*--de = *se;
|
|
while(se != src.Begin())
|
|
*--de = *--se;
|
|
return dest;
|
|
}
|
|
--pe;
|
|
}
|
|
else
|
|
{
|
|
*--de = *se;
|
|
if(se == src.Begin())
|
|
return dest; // src items are finished, dest items are in place
|
|
--se;
|
|
}
|
|
}
|
|
return dest;
|
|
}
|
|
|
|
template <class C>
|
|
C& AppendSorted(C& dest, const C& src)
|
|
{
|
|
typedef typename C::ValueType VT;
|
|
return AppendSorted(dest, src, StdLess<VT>());
|
|
}
|
|
|
|
template <class C, class L>
|
|
C& UnionSorted(C& dest, const C& src, const L& less)
|
|
{
|
|
if(src.IsEmpty())
|
|
return dest;
|
|
if(dest.IsEmpty())
|
|
{
|
|
dest <<= src;
|
|
return dest;
|
|
}
|
|
if(less(dest.Top(), *src))
|
|
{
|
|
dest.Append(src);
|
|
return dest;
|
|
}
|
|
if(less(src.Top(), *dest))
|
|
{
|
|
dest.Insert(0, src);
|
|
return dest;
|
|
}
|
|
int dc = dest.GetCount();
|
|
int sc = src.GetCount();
|
|
dest.SetCount(dc + sc);
|
|
typename C::Iterator de = dest.End();
|
|
typename C::ConstIterator se = src.End(), pe = dest.GetIter(dc);
|
|
--se;
|
|
--pe;
|
|
for(;;)
|
|
{
|
|
if(less(*se, *pe))
|
|
{
|
|
*--de = *pe;
|
|
if(pe == dest.Begin())
|
|
{ // dest items are finished
|
|
*--de = *se;
|
|
while(se != src.Begin())
|
|
*--de = *--se;
|
|
dest.Remove(0, dest.GetIndex(*de));
|
|
return dest;
|
|
}
|
|
--pe;
|
|
}
|
|
else
|
|
{
|
|
*--de = *se;
|
|
if(!less(*pe, *se))
|
|
{
|
|
if(pe == dest.Begin())
|
|
{
|
|
while(se != src.Begin())
|
|
*--de = *--se;
|
|
dest.Remove(0, dest.GetIndex(*de));
|
|
return dest;
|
|
}
|
|
--pe;
|
|
}
|
|
if(se == src.Begin())
|
|
{
|
|
int pi = (pe - dest.Begin()) + 1;
|
|
dest.Remove(pi, (de - dest.Begin()) - pi);
|
|
return dest; // src items are finished, dest items are in place
|
|
}
|
|
--se;
|
|
}
|
|
}
|
|
return dest;
|
|
}
|
|
|
|
template <class C>
|
|
C& UnionSorted(C& dest, const C& src)
|
|
{
|
|
typedef typename C::ValueType VT;
|
|
return UnionSorted(dest, src, StdLess<VT>());
|
|
}
|
|
|
|
template <class C, class L>
|
|
C& RemoveSorted(C& from, const C& what, const L& less)
|
|
{
|
|
if(from.IsEmpty() || what.IsEmpty() ||
|
|
less(from.Top(), *what.Begin()) || less(what.Top(), *from.Begin()))
|
|
return from;
|
|
typename C::ConstIterator we = what.End(), wp = BinFind(what, from[0], less);
|
|
if(wp == we)
|
|
return from;
|
|
typename C::Iterator fp = from.Begin() + BinFindIndex(from, *wp), fe = from.End(), fd = fp;
|
|
if(fp == fe)
|
|
{
|
|
from.Clear();
|
|
return from;
|
|
}
|
|
for(;;)
|
|
{
|
|
while(less(*fp, *wp))
|
|
{
|
|
*fd = *fp;
|
|
++fd;
|
|
if(++fp == fe)
|
|
{
|
|
from.SetCount(fd - from.Begin());
|
|
return from;
|
|
}
|
|
}
|
|
if(less(*wp, *fp))
|
|
{
|
|
do
|
|
if(++wp == we)
|
|
{
|
|
Copy(fd, fp, fe);
|
|
fd += (fe - fp);
|
|
from.SetCount(fd - from.Begin());
|
|
return from;
|
|
}
|
|
while(less(*wp, *fp));
|
|
}
|
|
else
|
|
{
|
|
const typename C::ValueType& value = *fp;
|
|
while(!less(value, *fp))
|
|
if(++fp == fe)
|
|
{
|
|
from.SetCount(fd - from.Begin());
|
|
return from;
|
|
}
|
|
do
|
|
if(++wp == we)
|
|
{
|
|
Copy(fd, fp, fe);
|
|
fd += (fe - fp);
|
|
from.SetCount(fd - from.Begin());
|
|
return from;
|
|
}
|
|
while(!less(value, *wp));
|
|
}
|
|
}
|
|
}
|
|
|
|
template <class C>
|
|
C& RemoveSorted(C& from, const C& what)
|
|
{
|
|
typedef typename C::ValueType VT;
|
|
return RemoveSorted(from, what, StdLess<VT>());
|
|
}
|
|
|
|
template <class D, class S, class L>
|
|
D& IntersectSorted(D& dest, const S& src, const L& less)
|
|
{
|
|
if(dest.IsEmpty())
|
|
return dest;
|
|
if(src.IsEmpty() || less(dest.Top(), src[0]) || less(src.Top(), dest[0]))
|
|
{ // empty source set or disjunct intervals
|
|
dest.Clear();
|
|
return dest;
|
|
}
|
|
typename S::ConstIterator ss = BinFind(src, dest[0], less), se = src.End();
|
|
if(ss == se)
|
|
{
|
|
dest.Clear();
|
|
return dest;
|
|
}
|
|
typename D::ConstIterator ds = BinFind(dest, src[0], less), de = dest.End();
|
|
if(ds == de)
|
|
{
|
|
dest.Clear();
|
|
return dest;
|
|
}
|
|
typename D::Iterator d = dest.Begin();
|
|
int count = 0;
|
|
for(;;)
|
|
{
|
|
if(less(*ss, *ds))
|
|
{
|
|
if(++ss == se)
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if(!less(*ds, *ss))
|
|
{
|
|
*d = *ds;
|
|
++d;
|
|
count++;
|
|
}
|
|
if(++ds == de)
|
|
break;
|
|
}
|
|
}
|
|
dest.SetCount(count);
|
|
return dest;
|
|
}
|
|
|
|
template <class D, class S>
|
|
D& IntersectSorted(D& dest, const S& src)
|
|
{
|
|
typedef typename D::ValueType VT;
|
|
return IntersectSorted(dest, src, StdLess<VT>());
|
|
}
|
|
|
|
#ifdef UPP
|
|
template <class T>
|
|
void StreamContainer(Stream& s, T& cont)
|
|
{
|
|
int n = cont.GetCount();
|
|
s / n;
|
|
if(n < 0) {
|
|
s.LoadError();
|
|
return;
|
|
}
|
|
if(s.IsLoading())
|
|
{
|
|
cont.Clear();
|
|
while(n--)
|
|
s % cont.Add();
|
|
}
|
|
else
|
|
{
|
|
for(typename T::Iterator ptr = cont.Begin(); n--; ++ptr)
|
|
s % *ptr;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
template <class I, class Less>
|
|
void ForwardSort(I begin, I end, const Less& less)
|
|
{
|
|
if(begin == end)
|
|
return;
|
|
I limit = end;
|
|
--limit;
|
|
while(!(begin == limit))
|
|
{
|
|
for(I best = limit, next = limit, ptr = limit;; best = ptr)
|
|
if(!less(*best, *--ptr))
|
|
{
|
|
if(ptr == begin)
|
|
{
|
|
begin = next;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
do
|
|
{
|
|
if(ptr == begin)
|
|
{
|
|
IterSwap(begin, best);
|
|
++begin;
|
|
goto NEXT_ITEM;
|
|
}
|
|
}
|
|
while(less(*best, *--ptr));
|
|
if(ptr == begin)
|
|
{
|
|
IterSwap(++begin, best);
|
|
++begin;
|
|
break;
|
|
}
|
|
next = ptr;
|
|
++next;
|
|
}
|
|
NEXT_ITEM:
|
|
;
|
|
}
|
|
}
|
|
|
|
template <class T, class Less>
|
|
void ForwardSort(T& c, const Less& less)
|
|
{
|
|
ForwardSort(c.Begin(), c.End(), less);
|
|
}
|
|
|
|
template <class T>
|
|
void ForwardSort(T& c)
|
|
{
|
|
typedef typename T::ValueType VT;
|
|
ForwardSort(c.Begin(), c.End(), StdLess<VT>());
|
|
}
|
|
|
|
enum
|
|
{
|
|
__SORT_THRESHOLD = 16,
|
|
__SORT_MEDIAN_PASSES = 2,
|
|
};
|
|
|
|
template <class I, class Less>
|
|
void Sort(I begin, I end, const Less& less)
|
|
{
|
|
int count;
|
|
while((count = (int)(end - begin)) > __SORT_THRESHOLD) {
|
|
int expected = count >> 1, deviation = expected - (expected >> 8);
|
|
I b = begin, e = end, m = b + expected;
|
|
for(int pass = 1;; pass++) {
|
|
for(;; ++b) {
|
|
while(less(*m, *--e))
|
|
;
|
|
while(less(*b, *m))
|
|
++b;
|
|
if(!(b < e))
|
|
break;
|
|
if(m == b) m = e;
|
|
else if(m == e) m = b;
|
|
IterSwap(b, e);
|
|
}
|
|
if(pass >= __SORT_MEDIAN_PASSES)
|
|
break;
|
|
int pos = (int)(b - begin);
|
|
if(pos <= expected - deviation)
|
|
e = end;
|
|
else if(pos >= expected + deviation) {
|
|
e = b;
|
|
b = begin;
|
|
}
|
|
else
|
|
break;
|
|
m = b + 1 + (int)((unsigned)rand() % (e - b - 2));
|
|
}
|
|
if(b - begin < end - e) {
|
|
Sort(begin, b, less);
|
|
begin = b;
|
|
}
|
|
else {
|
|
Sort(b, end, less);
|
|
end = b;
|
|
}
|
|
}
|
|
if(count >= 2)
|
|
ForwardSort(begin, end, less);
|
|
}
|
|
|
|
template <class T, class Less>
|
|
void Sort(T& c, const Less& less)
|
|
{
|
|
Sort(c.Begin(), c.End(), less);
|
|
}
|
|
|
|
template <class T>
|
|
void Sort(T& c)
|
|
{
|
|
typedef typename T::ValueType VT;
|
|
Sort(c.Begin(), c.End(), StdLess<VT>());
|
|
}
|
|
|
|
template <class T>
|
|
struct StableSortItem {
|
|
const T& value;
|
|
int index;
|
|
|
|
StableSortItem(const T& value, int index) : value(value), index(index) {}
|
|
};
|
|
|
|
template <class II, class T>
|
|
struct StableSortIterator {
|
|
II ii;
|
|
int *vi;
|
|
|
|
typedef StableSortIterator<II, T> Iter;
|
|
|
|
Iter& operator ++ () { ++ii; ++vi; return *this; }
|
|
Iter& operator -- () { --ii; --vi; return *this; }
|
|
Iter operator + (int i) const { return Iter(ii + i, vi + i); }
|
|
Iter operator - (int i) const { return Iter(ii - i, vi - i); }
|
|
int operator - (Iter b) const { return (int)(ii - b.ii); }
|
|
bool operator == (Iter b) const { return ii == b.ii; }
|
|
bool operator != (Iter b) const { return ii != b.ii; }
|
|
bool operator < (Iter b) const { return ii < b.ii; }
|
|
|
|
StableSortItem<T> operator*() const { return StableSortItem<T>(*ii, *vi); }
|
|
|
|
friend void IterSwap(Iter a, Iter b) { IterSwap(a.ii, b.ii); IterSwap(a.vi, b.vi); }
|
|
|
|
StableSortIterator(II ii, int *vi) : ii(ii), vi(vi) {}
|
|
};
|
|
|
|
template <class T, class Less>
|
|
struct StableSortLess_ {
|
|
const Less& less;
|
|
|
|
bool operator()(const StableSortItem<T>& a, const StableSortItem<T>& b) const {
|
|
if(less(a.value, b.value)) return true;
|
|
return less(b.value, a.value) ? false : a.index < b.index;
|
|
}
|
|
|
|
StableSortLess_(const Less& less) : less(less) {}
|
|
};
|
|
|
|
template <class I, class Less, class T>
|
|
void StableSort_(I begin, I end, const Less& less, const T *)
|
|
{
|
|
int count = (int)(uintptr_t)(end - begin);
|
|
Buffer<int> h(count);
|
|
for(int i = 0; i < count; i++)
|
|
h[i] = i;
|
|
Sort(StableSortIterator<I, T>(begin, ~h),
|
|
StableSortIterator<I, T>(end, ~h + count),
|
|
StableSortLess_<T, Less>(less));
|
|
}
|
|
|
|
template <class I, class Less>
|
|
void StableSort(I begin, I end, const Less& less)
|
|
{
|
|
if(begin != end)
|
|
StableSort_(begin, end, less, &*begin);
|
|
}
|
|
|
|
template <class T, class Less>
|
|
void StableSort(T& c, const Less& less)
|
|
{
|
|
StableSort(c.Begin(), c.End(), less);
|
|
}
|
|
|
|
template <class T>
|
|
void StableSort(T& c)
|
|
{
|
|
StableSort(c.Begin(), c.End(), StdLess<typename T::ValueType>());
|
|
}
|
|
|
|
template <class T, class Cmp>
|
|
struct StableSortLessCmp_ {
|
|
const Cmp& cmp;
|
|
bool operator()(const StableSortItem<T>& a, const StableSortItem<T>& b) const {
|
|
int q = SgnCompare(a.value, b.value);
|
|
return q ? q < 0 : a.index < b.index;
|
|
}
|
|
|
|
StableSortLessCmp_(const Cmp& cmp) : cmp(cmp) {}
|
|
};
|
|
|
|
template <class I, class Cmp, class T>
|
|
void StableSortCmp_(I begin, I end, const Cmp& cmp, const T *)
|
|
{
|
|
int count = end - begin;
|
|
Buffer<int> h(count);
|
|
for(int i = 0; i < count; i++)
|
|
h[i] = i;
|
|
Sort(StableSortIterator<I, T>(begin, ~h),
|
|
StableSortIterator<I, T>(end, ~h + count),
|
|
StableSortLessCmp_<T, Cmp>(cmp));
|
|
}
|
|
|
|
template <class I, class Cmp>
|
|
void StableSortCmp(I begin, I end, const Cmp& cmp)
|
|
{
|
|
if(begin != end)
|
|
StableSortCmp_(begin, end, cmp, &*begin);
|
|
}
|
|
|
|
template <class T, class Cmp>
|
|
void StableSortCmp(T& c, const Cmp& cmp)
|
|
{
|
|
StableSortCmp(c.Begin(), c.End(), cmp);
|
|
}
|
|
|
|
template <class T>
|
|
struct StdCmp {
|
|
int operator()(const T& a, const T& b) const {
|
|
return SgnCompare(a, b);
|
|
}
|
|
};
|
|
|
|
template <class T>
|
|
void StableSortCmp(T& c)
|
|
{
|
|
StableSort(c.Begin(), c.End(), StdCmp<typename T::ValueType>());
|
|
}
|
|
|
|
template <class II, class VI, class K>
|
|
struct IndexSortIterator
|
|
{
|
|
typedef IndexSortIterator<II, VI, K> Iter;
|
|
|
|
IndexSortIterator(II ii, VI vi) : ii(ii), vi(vi) {}
|
|
|
|
Iter& operator ++ () { ++ii; ++vi; return *this; }
|
|
Iter& operator -- () { --ii; --vi; return *this; }
|
|
const K& operator * () const { return *ii; }
|
|
Iter operator + (int i) const { return Iter(ii + i, vi + i); }
|
|
Iter operator - (int i) const { return Iter(ii - i, vi - i); }
|
|
int operator - (Iter b) const { return (int)(ii - b.ii); }
|
|
bool operator == (Iter b) const { return ii == b.ii; }
|
|
bool operator != (Iter b) const { return ii != b.ii; }
|
|
bool operator < (Iter b) const { return ii < b.ii; }
|
|
friend void IterSwap (Iter a, Iter b) { IterSwap(a.ii, b.ii); IterSwap(a.vi, b.vi); }
|
|
|
|
II ii;
|
|
VI vi;
|
|
};
|
|
|
|
template <class II, class VI, class K, class Less>
|
|
inline void __IndexSort(II begin, II end, VI pair, const Less& less, const K *)
|
|
{
|
|
Sort(IndexSortIterator<II, VI, K>(begin, pair),
|
|
IndexSortIterator<II, VI, K>(end, pair + (end - begin)),
|
|
less);
|
|
}
|
|
|
|
template <class II, class VI, class Less>
|
|
inline void IndexSort(II begin, II end, VI pair, const Less& less)
|
|
{
|
|
if(begin != end)
|
|
__IndexSort(begin, end, pair, less, &*begin);
|
|
}
|
|
|
|
template <class KC, class VC, class Less>
|
|
inline void IndexSort(KC& keys, VC& values, const Less& less)
|
|
{
|
|
typedef typename KC::ValueType KT;
|
|
ASSERT(keys.GetCount() == values.GetCount());
|
|
if(keys.GetCount() >= 2)
|
|
__IndexSort(keys.Begin(), keys.End(), values.Begin(), less, (KT *)0);
|
|
}
|
|
|
|
template <class KC, class VC>
|
|
inline void IndexSort(KC& keys, VC& values)
|
|
{
|
|
typedef typename KC::ValueType KT;
|
|
if(keys.GetCount() >= 2)
|
|
__IndexSort(keys.Begin(), keys.End(), values.Begin(), StdLess<KT>(), (KT *)0);
|
|
}
|
|
|
|
template <class II, class VI, class K, class Less>
|
|
inline void __StableIndexSort(II begin, II end, VI pair, const Less& less, const K *)
|
|
{
|
|
StableSort(IndexSortIterator<II, VI, K>(begin, pair),
|
|
IndexSortIterator<II, VI, K>(end, pair + (end - begin)),
|
|
less);
|
|
}
|
|
|
|
template <class II, class VI, class Less>
|
|
inline void StableIndexSort(II begin, II end, VI pair, const Less& less)
|
|
{
|
|
if(begin != end)
|
|
__StableIndexSort(begin, end, pair, less, &*begin);
|
|
}
|
|
|
|
template <class KC, class VC, class Less>
|
|
inline void StableIndexSort(KC& keys, VC& values, const Less& less)
|
|
{
|
|
typedef typename KC::ValueType KT;
|
|
ASSERT(keys.GetCount() == values.GetCount());
|
|
if(keys.GetCount() >= 2)
|
|
__StableIndexSort(keys.Begin(), keys.End(), values.Begin(), less, (KT *)0);
|
|
}
|
|
|
|
template <class KC, class VC>
|
|
inline void StableIndexSort(KC& keys, VC& values)
|
|
{
|
|
typedef typename KC::ValueType KT;
|
|
if(keys.GetCount() >= 2)
|
|
__StableIndexSort(keys.Begin(), keys.End(), values.Begin(), StdLess<KT>(), (KT *)0);
|
|
}
|
|
|
|
template <class II, class VI, class K, class Cmp>
|
|
inline void __StableIndexSortCmp(II begin, II end, VI pair, const Cmp& cmp, const K *)
|
|
{
|
|
StableSortCmp(IndexSortIterator<II, VI, K>(begin, pair),
|
|
IndexSortIterator<II, VI, K>(end, pair + (end - begin)),
|
|
cmp);
|
|
}
|
|
|
|
template <class II, class VI, class Cmp>
|
|
inline void StableIndexSortCmp(II begin, II end, VI pair, const Cmp& cmp)
|
|
{
|
|
if(begin != end)
|
|
__StableIndexSortCmp(begin, end, pair, cmp, &*begin);
|
|
}
|
|
|
|
template <class KC, class VC, class Cmp>
|
|
inline void StableIndexSortCmp(KC& keys, VC& values, const Cmp& cmp)
|
|
{
|
|
typedef typename KC::ValueType KT;
|
|
ASSERT(keys.GetCount() == values.GetCount());
|
|
if(keys.GetCount() >= 2)
|
|
__StableIndexSortCmp(keys.Begin(), keys.End(), values.Begin(), cmp, (KT *)0);
|
|
}
|
|
|
|
template <class KC, class VC>
|
|
inline void StableIndexSortCmp(KC& keys, VC& values)
|
|
{
|
|
typedef typename KC::ValueType KT;
|
|
if(keys.GetCount() >= 2)
|
|
__StableIndexSortCmp(keys.Begin(), keys.End(), values.Begin(), StdCmp<KT>(), (KT *)0);
|
|
}
|
|
|
|
template <class II, class VI, class WI, class K>
|
|
struct IndexSort2Iterator
|
|
{
|
|
typedef IndexSort2Iterator<II, VI, WI, K> Iter;
|
|
|
|
IndexSort2Iterator(II ii, VI vi, WI wi) : ii(ii), vi(vi), wi(wi) {}
|
|
|
|
Iter& operator ++ () { ++ii; ++vi; ++wi; return *this; }
|
|
Iter& operator -- () { --ii; --vi; --wi; return *this; }
|
|
const K& operator * () const { return *ii; }
|
|
Iter operator + (int i) const { return Iter(ii + i, vi + i, wi + i); }
|
|
Iter operator - (int i) const { return Iter(ii - i, vi - i, wi - i); }
|
|
int operator - (Iter b) const { return (int)(ii - b.ii); }
|
|
bool operator == (Iter b) const { return ii == b.ii; }
|
|
bool operator != (Iter b) const { return ii != b.ii; }
|
|
bool operator < (Iter b) const { return ii < b.ii; }
|
|
friend void IterSwap (Iter a, Iter b) { IterSwap(a.ii, b.ii); IterSwap(a.vi, b.vi); IterSwap(a.wi, b.wi); }
|
|
|
|
II ii;
|
|
VI vi;
|
|
WI wi;
|
|
};
|
|
|
|
template <class II, class VI, class WI, class K, class Less>
|
|
inline void __IndexSort2(II begin, II end, VI pair1, WI pair2, const Less& less, const K *)
|
|
{
|
|
int count = end - begin;
|
|
Sort(IndexSort2Iterator<II, VI, WI, K>(begin, pair1, pair2),
|
|
IndexSort2Iterator<II, VI, WI, K>(end, pair1 + count, pair2 + count),
|
|
less);
|
|
}
|
|
|
|
template <class II, class VI, class WI, class Less>
|
|
inline void IndexSort2(II begin, II end, VI pair1, WI pair2, const Less& less)
|
|
{
|
|
if(begin != end)
|
|
__IndexSort2(begin, end, pair1, pair2, less, &*begin);
|
|
}
|
|
|
|
template <class KC, class VC, class WC, class Less>
|
|
inline void IndexSort2(KC& keys, VC& values1, WC& values2, const Less& less)
|
|
{
|
|
typedef typename KC::ValueType KT;
|
|
ASSERT(keys.GetCount() == values1.GetCount() && keys.GetCount() == values2.GetCount());
|
|
if(keys.GetCount() >= 2)
|
|
__IndexSort2(keys.Begin(), keys.End(), values1.Begin(), values2.Begin(), less, (KT *)0);
|
|
}
|
|
|
|
template <class KC, class VC, class WC>
|
|
inline void IndexSort2(KC& keys, VC& values1, WC& values2)
|
|
{
|
|
typedef typename KC::ValueType KT;
|
|
if(keys.GetCount() >= 2)
|
|
__IndexSort2(keys.Begin(), keys.End(), values1.Begin(), values2.Begin(), StdLess<KT>(), (KT *)0);
|
|
}
|
|
|
|
template <class II, class VI, class WI, class K, class Less>
|
|
inline void __StableIndexSort2(II begin, II end, VI pair1, WI pair2, const Less& less, const K *)
|
|
{
|
|
int count = end - begin;
|
|
StableSort(IndexSort2Iterator<II, VI, WI, K>(begin, pair1, pair2),
|
|
IndexSort2Iterator<II, VI, WI, K>(end, pair1 + count, pair2 + count),
|
|
less);
|
|
}
|
|
|
|
template <class II, class VI, class WI, class Less>
|
|
inline void StableIndexSort2(II begin, II end, VI pair1, WI pair2, const Less& less)
|
|
{
|
|
if(begin != end)
|
|
__StableIndexSort2(begin, end, pair1, pair2, less, &*begin);
|
|
}
|
|
|
|
template <class KC, class VC, class WC, class Less>
|
|
inline void StableIndexSort2(KC& keys, VC& values1, WC& values2, const Less& less)
|
|
{
|
|
typedef typename KC::ValueType KT;
|
|
ASSERT(keys.GetCount() == values1.GetCount() && keys.GetCount() == values2.GetCount());
|
|
if(keys.GetCount() >= 2)
|
|
__StableIndexSort2(keys.Begin(), keys.End(), values1.Begin(), values2.Begin(), less, (KT *)0);
|
|
}
|
|
|
|
template <class KC, class VC, class WC>
|
|
inline void StableIndexSort2(KC& keys, VC& values1, WC& values2)
|
|
{
|
|
typedef typename KC::ValueType KT;
|
|
if(keys.GetCount() >= 2)
|
|
__StableIndexSort2(keys.Begin(), keys.End(), values1.Begin(), values2.Begin(), StdLess<KT>(), (KT *)0);
|
|
}
|
|
|
|
template <class II, class VI, class WI, class K, class Cmp>
|
|
inline void __StableIndexSort2Cmp(II begin, II end, VI pair1, WI pair2, const Cmp& cmp, const K *)
|
|
{
|
|
int count = end - begin;
|
|
StableSortCmp(IndexSort2Iterator<II, VI, WI, K>(begin, pair1, pair2),
|
|
IndexSort2Iterator<II, VI, WI, K>(end, pair1 + count, pair2 + count),
|
|
cmp);
|
|
}
|
|
|
|
template <class II, class VI, class WI, class Cmp>
|
|
inline void StableIndexSort2Cmp(II begin, II end, VI pair1, WI pair2, const Cmp& cmp)
|
|
{
|
|
if(begin != end)
|
|
__StableIndexSort2Cmp(begin, end, pair1, pair2, cmp, &*begin);
|
|
}
|
|
|
|
template <class KC, class VC, class WC, class Cmp>
|
|
inline void StableIndexSort2Cmp(KC& keys, VC& values1, WC& values2, const Cmp& cmp)
|
|
{
|
|
typedef typename KC::ValueType KT;
|
|
ASSERT(keys.GetCount() == values1.GetCount() && keys.GetCount() == values2.GetCount());
|
|
if(keys.GetCount() >= 2)
|
|
__StableIndexSort2Cmp(keys.Begin(), keys.End(), values1.Begin(), values2.Begin(), cmp, (KT *)0);
|
|
}
|
|
|
|
template <class KC, class VC, class WC>
|
|
inline void StableIndexSort2Cmp(KC& keys, VC& values1, WC& values2)
|
|
{
|
|
typedef typename KC::ValueType KT;
|
|
if(keys.GetCount() >= 2)
|
|
__StableIndexSort2Cmp(keys.Begin(), keys.End(), values1.Begin(), values2.Begin(), StdCmp<KT>(), (KT *)0);
|
|
}
|
|
|
|
template <class II, class VI, class WI, class XI, class K>
|
|
struct IndexSort3Iterator
|
|
{
|
|
typedef IndexSort3Iterator<II, VI, WI, XI, K> Iter;
|
|
|
|
IndexSort3Iterator(II ii, VI vi, WI wi, XI xi) : ii(ii), vi(vi), wi(wi), xi(xi) {}
|
|
|
|
Iter& operator ++ () { ++ii; ++vi; ++wi; ++xi; return *this; }
|
|
Iter& operator -- () { --ii; --vi; --wi; --xi; return *this; }
|
|
const K& operator * () const { return *ii; }
|
|
Iter operator + (int i) const { return Iter(ii + i, vi + i, wi + i, xi + i); }
|
|
Iter operator - (int i) const { return Iter(ii - i, vi - i, wi - i, xi - i); }
|
|
int operator - (Iter b) const { return (int)(ii - b.ii); }
|
|
bool operator == (Iter b) const { return ii == b.ii; }
|
|
bool operator != (Iter b) const { return ii != b.ii; }
|
|
bool operator < (Iter b) const { return ii < b.ii; }
|
|
friend void IterSwap (Iter a, Iter b) { IterSwap(a.ii, b.ii); IterSwap(a.vi, b.vi); IterSwap(a.wi, b.wi); IterSwap(a.xi, b.xi); }
|
|
|
|
II ii;
|
|
VI vi;
|
|
WI wi;
|
|
XI xi;
|
|
};
|
|
|
|
template <class II, class VI, class WI, class XI, class K, class Less>
|
|
inline void __IndexSort3(II begin, II end, VI pair1, WI pair2, XI pair3, const Less& less, const K *)
|
|
{
|
|
int count = end - begin;
|
|
Sort(IndexSort3Iterator<II, VI, WI, XI, K>(begin, pair1, pair2, pair3),
|
|
IndexSort3Iterator<II, VI, WI, XI, K>(end, pair1 + count, pair2 + count, pair3 + count),
|
|
less);
|
|
}
|
|
|
|
template <class II, class VI, class WI, class XI, class Less>
|
|
inline void IndexSort3(II begin, II end, VI pair1, WI pair2, XI pair3, const Less& less)
|
|
{
|
|
if(begin != end)
|
|
__IndexSort3(begin, end, pair1, pair2, pair3, less, &*begin);
|
|
}
|
|
|
|
template <class KC, class VC, class WC, class XC, class Less>
|
|
inline void IndexSort3(KC& keys, VC& values1, WC& values2, XC& values3, const Less& less)
|
|
{
|
|
typedef typename KC::ValueType KT;
|
|
ASSERT(keys.GetCount() == values1.GetCount() && keys.GetCount() == values2.GetCount()
|
|
&& keys.GetCount() == values3.GetCount());
|
|
if(keys.GetCount() >= 2)
|
|
__IndexSort3(keys.Begin(), keys.End(), values1.Begin(), values2.Begin(), values3.Begin(), less, (KT *)0);
|
|
}
|
|
|
|
template <class KC, class VC, class WC, class XC>
|
|
inline void IndexSort3(KC& keys, VC& values1, WC& values2, XC& values3)
|
|
{
|
|
typedef typename KC::ValueType KT;
|
|
if(keys.GetCount() >= 2)
|
|
__IndexSort3(keys.Begin(), keys.End(), values1.Begin(), values2.Begin(), values3.Begin(), StdLess<KT>(), (KT *)0);
|
|
}
|
|
|
|
template <class II, class VI, class WI, class XI, class K, class Less>
|
|
inline void __StableIndexSort3(II begin, II end, VI pair1, WI pair2, XI pair3, const Less& less, const K *)
|
|
{
|
|
int count = end - begin;
|
|
StableSort(IndexSort3Iterator<II, VI, WI, XI, K>(begin, pair1, pair2, pair3),
|
|
IndexSort3Iterator<II, VI, WI, XI, K>(end, pair1 + count, pair2 + count, pair3 + count),
|
|
less);
|
|
}
|
|
|
|
template <class II, class VI, class WI, class XI, class Less>
|
|
inline void StableIndexSort3(II begin, II end, VI pair1, WI pair2, XI pair3, const Less& less)
|
|
{
|
|
if(begin != end)
|
|
__StableIndexSort3(begin, end, pair1, pair2, pair3, less, &*begin);
|
|
}
|
|
|
|
template <class KC, class VC, class WC, class XC, class Less>
|
|
inline void StableIndexSort3(KC& keys, VC& values1, WC& values2, XC& values3, const Less& less)
|
|
{
|
|
typedef typename KC::ValueType KT;
|
|
ASSERT(keys.GetCount() == values1.GetCount() && keys.GetCount() == values2.GetCount()
|
|
&& keys.GetCount() == values3.GetCount());
|
|
if(keys.GetCount() >= 2)
|
|
__StableIndexSort3(keys.Begin(), keys.End(), values1.Begin(), values2.Begin(), values3.Begin(), less, (KT *)0);
|
|
}
|
|
|
|
template <class KC, class VC, class WC, class XC>
|
|
inline void StableIndexSort3(KC& keys, VC& values1, WC& values2, XC& values3)
|
|
{
|
|
typedef typename KC::ValueType KT;
|
|
if(keys.GetCount() >= 2)
|
|
__StableIndexSort3(keys.Begin(), keys.End(), values1.Begin(), values2.Begin(), values3.Begin(), StdLess<KT>(), (KT *)0);
|
|
}
|
|
|
|
template <class II, class VI, class WI, class XI, class K, class Cmp>
|
|
inline void __StableIndexSort3Cmp(II begin, II end, VI pair1, WI pair2, XI pair3, const Cmp& cmp, const K *)
|
|
{
|
|
int count = end - begin;
|
|
StableSortCmp(IndexSort3Iterator<II, VI, WI, XI, K>(begin, pair1, pair2, pair3),
|
|
IndexSort3Iterator<II, VI, WI, XI, K>(end, pair1 + count, pair2 + count, pair3 + count),
|
|
cmp);
|
|
}
|
|
|
|
template <class II, class VI, class WI, class XI, class Cmp>
|
|
inline void StableIndexSort3Cmp(II begin, II end, VI pair1, WI pair2, XI pair3, const Cmp& cmp)
|
|
{
|
|
if(begin != end)
|
|
__StableIndexSort3Cmp(begin, end, pair1, pair2, pair3, cmp, &*begin);
|
|
}
|
|
|
|
template <class KC, class VC, class WC, class XC, class Cmp>
|
|
inline void StableIndexSort3Cmp(KC& keys, VC& values1, WC& values2, XC& values3, const Cmp& cmp)
|
|
{
|
|
typedef typename KC::ValueType KT;
|
|
ASSERT(keys.GetCount() == values1.GetCount() && keys.GetCount() == values2.GetCount()
|
|
&& keys.GetCount() == values3.GetCount());
|
|
if(keys.GetCount() >= 2)
|
|
__StableIndexSort3Cmp(keys.Begin(), keys.End(), values1.Begin(), values2.Begin(), values3.Begin(), cmp, (KT *)0);
|
|
}
|
|
|
|
template <class KC, class VC, class WC, class XC>
|
|
inline void StableIndexSort3Cmp(KC& keys, VC& values1, WC& values2, XC& values3)
|
|
{
|
|
typedef typename KC::ValueType KT;
|
|
if(keys.GetCount() >= 2)
|
|
__StableIndexSort3Cmp(keys.Begin(), keys.End(), values1.Begin(), values2.Begin(), values3.Begin(), StdCmp<KT>(), (KT *)0);
|
|
}
|
|
|
|
|
|
template <class I, class V>
|
|
struct SortOrderIterator : PostfixOps< SortOrderIterator<I, V> >
|
|
{
|
|
typedef SortOrderIterator<I, V> Iter;
|
|
|
|
SortOrderIterator(int *ii, I vi) : ii(ii), vi(vi) {}
|
|
|
|
Iter& operator ++ () { ++ii; return *this; }
|
|
Iter& operator -- () { --ii; return *this; }
|
|
const V& operator * () const { return *(vi + *ii); }
|
|
Iter operator + (int i) const { return Iter(ii + i, vi); }
|
|
Iter operator - (int i) const { return Iter(ii - i, vi); }
|
|
int operator - (Iter b) const { return int(ii - b.ii); }
|
|
bool operator == (Iter b) const { return ii == b.ii; }
|
|
bool operator != (Iter b) const { return ii != b.ii; }
|
|
bool operator < (Iter b) const { return ii < b.ii; }
|
|
friend void IterSwap (Iter a, Iter b) { IterSwap(a.ii, b.ii); }
|
|
|
|
int *ii;
|
|
I vi;
|
|
};
|
|
|
|
template <class I, class V, class Less>
|
|
inline void __SortOrder(int *begin, int *end, I data, const Less& less, const V *)
|
|
{
|
|
Sort(SortOrderIterator<I, V>(begin, data), SortOrderIterator<I, V>(end, data), less);
|
|
}
|
|
|
|
template <class I, class Less>
|
|
inline Vector<int> GetSortOrder(I begin, I end, const Less& less)
|
|
{
|
|
Vector<int> index;
|
|
index.SetCount((int)(end - begin));
|
|
for(int i = index.GetCount(); --i >= 0; index[i] = i)
|
|
;
|
|
if(begin != end)
|
|
__SortOrder(index.Begin(), index.End(), begin, less, &*begin);
|
|
return index;
|
|
}
|
|
|
|
template <class C, class Less>
|
|
inline Vector<int> GetSortOrder(const C& container, const Less& less)
|
|
{
|
|
return GetSortOrder(container.Begin(), container.End(), less);
|
|
}
|
|
|
|
template <class C>
|
|
inline Vector<int> GetSortOrder(const C& container)
|
|
{
|
|
typedef typename C::ValueType V;
|
|
return GetSortOrder(container.Begin(), container.End(), StdLess<V>());
|
|
}
|
|
|
|
template <class I, class T>
|
|
struct StableSortOrderIterator : PostfixOps< StableSortOrderIterator<I, T> >
|
|
{
|
|
typedef StableSortOrderIterator<I, T> Iter;
|
|
|
|
StableSortOrderIterator(int *ii, I vi) : ii(ii), vi(vi) {}
|
|
|
|
Iter& operator ++ () { ++ii; return *this; }
|
|
Iter& operator -- () { --ii; return *this; }
|
|
Iter operator + (int i) const { return Iter(ii + i, vi); }
|
|
Iter operator - (int i) const { return Iter(ii - i, vi); }
|
|
int operator - (Iter b) const { return int(ii - b.ii); }
|
|
bool operator == (Iter b) const { return ii == b.ii; }
|
|
bool operator != (Iter b) const { return ii != b.ii; }
|
|
bool operator < (Iter b) const { return ii < b.ii; }
|
|
friend void IterSwap (Iter a, Iter b) { IterSwap(a.ii, b.ii); }
|
|
|
|
StableSortItem<T> operator*() const { return StableSortItem<T>(*(vi + *ii), *ii); }
|
|
|
|
int *ii;
|
|
I vi;
|
|
};
|
|
|
|
template <class I, class T, class Less>
|
|
inline void __StableSortOrder(int *ibegin, int *iend, I data, const Less& less, const T *)
|
|
{
|
|
Sort(StableSortOrderIterator<I, T>(ibegin, data),
|
|
StableSortOrderIterator<I, T>(iend, data),
|
|
StableSortLess_<T, Less>(less));
|
|
}
|
|
|
|
template <class I, class Less>
|
|
inline Vector<int> GetStableSortOrder(I begin, I end, const Less& less)
|
|
{
|
|
Vector<int> index;
|
|
index.SetCount((int)(end - begin));
|
|
for(int i = index.GetCount(); --i >= 0; index[i] = i)
|
|
;
|
|
if(begin != end)
|
|
__StableSortOrder(index.Begin(), index.End(), begin, less, &*begin);
|
|
return index;
|
|
}
|
|
|
|
template <class C, class Less>
|
|
inline Vector<int> GetStableSortOrder(const C& container, const Less& less)
|
|
{
|
|
return GetStableSortOrder(container.Begin(), container.End(), less);
|
|
}
|
|
|
|
template <class C>
|
|
inline Vector<int> GetStableSortOrder(const C& container)
|
|
{
|
|
typedef typename C::ValueType V;
|
|
return GetStableSortOrder(container.Begin(), container.End(), StdLess<V>());
|
|
}
|
|
|
|
template <class I, class T, class Cmp>
|
|
inline void __StableSortOrderCmp(int *ibegin, int *iend, I data, const Cmp& cmp, const T *)
|
|
{
|
|
Sort(StableSortOrderIterator<I, T>(ibegin, data),
|
|
StableSortOrderIterator<I, T>(iend, data),
|
|
StableSortLessCmp_<T, Cmp>(cmp));
|
|
}
|
|
|
|
template <class I, class Cmp>
|
|
inline Vector<int> GetStableSortOrderCmp(I begin, I end, const Cmp& cmp)
|
|
{
|
|
Vector<int> index;
|
|
index.SetCount((int)(end - begin));
|
|
for(int i = index.GetCount(); --i >= 0; index[i] = i)
|
|
;
|
|
if(begin != end)
|
|
__StableSortOrderCmp(index.Begin(), index.End(), begin, cmp, &*begin);
|
|
return index;
|
|
}
|
|
|
|
template <class C, class Cmp>
|
|
inline Vector<int> GetStableSortOrderCmp(const C& container, const Cmp& cmp)
|
|
{
|
|
return GetStableSortOrderCmp(container.Begin(), container.End(), cmp);
|
|
}
|
|
|
|
template <class C>
|
|
inline Vector<int> GetStableSortOrderCmp(const C& container)
|
|
{
|
|
typedef typename C::ValueType V;
|
|
return GetStableSortOrderCmp(container.Begin(), container.End(), StdCmp<V>());
|
|
}
|
|
|
|
template <class DC, class I, class F>
|
|
void GetFieldContainer(DC& dest, I begin, I end, F field)
|
|
{
|
|
for(; begin != end; ++begin)
|
|
dest.Add((*begin).*field);
|
|
}
|
|
|
|
template <class DC, class SC, class F>
|
|
void GetFieldContainer(DC& dest, const SC& src, F field)
|
|
{ GetFieldContainer<DC, typename SC::ConstIterator, F>(dest, src.Begin(), src.End(), field); }
|
|
|
|
template <class I, class F, class O, class E>
|
|
I FindField(I begin, I end, F field, const O& object, const E& equal)
|
|
{
|
|
for(; begin != end && !equal((*begin).*field, object); ++begin)
|
|
;
|
|
return begin;
|
|
}
|
|
|
|
template <class I, class F, class O>
|
|
I FindField(I begin, I end, F field, const O& object)
|
|
{ return FindField(begin, end, field, object, StdEqual<O>()); }
|
|
|
|
template <class C, class F, class O, class E>
|
|
int FindFieldIndex(const C& container, F field, const O& object, const E& equal)
|
|
{
|
|
int i = 0;
|
|
for(typename C::ConstIterator b = container.Begin(), e = container.End(); b != e; ++b, ++i)
|
|
if(equal((*b).*field, object))
|
|
return i;
|
|
return -1;
|
|
}
|
|
|
|
template <class C, class F, class O>
|
|
int FindFieldIndex(const C& container, F field, const O& object)
|
|
{ return FindFieldIndex(container, field, object, StdEqual<O>()); }
|
|
|
|
template <class O, class T, class R>
|
|
class FieldRelationCls {
|
|
O T::*member;
|
|
const R& relation;
|
|
|
|
public:
|
|
FieldRelationCls(O (T::*member), const R& relation) : member(member), relation(relation) {}
|
|
bool operator () (const T& t1, const T& t2) const { return relation(t1.*member, t2.*member); }
|
|
};
|
|
|
|
template <class O, class T, class R>
|
|
inline FieldRelationCls<O, T, R> FieldRelation(O (T::*member), const R& relation)
|
|
{ return FieldRelationCls<O, T, R>(member, relation); }
|
|
|
|
template <class M, class T, class R>
|
|
class MethodRelationCls {
|
|
M method;
|
|
const R& relation;
|
|
|
|
public:
|
|
MethodRelationCls(M method, const R& relation) : method(method), relation(relation) {}
|
|
bool operator () (const T& t1, const T& t2) const {
|
|
return relation((t1.*method)(), (t2.*method)());
|
|
}
|
|
};
|
|
|
|
template <class O, class T, class R>
|
|
inline MethodRelationCls<O (T::*)(), T, R>
|
|
MethodRelation(O (T::*method)(), const R& relation)
|
|
{ return MethodRelationCls<O (T::*)(), T, R>(method, relation); }
|
|
|
|
template <class O, class T, class R>
|
|
inline MethodRelationCls<O (T::*)() const, T, R>
|
|
MethodRelation(O (T::*method)() const, const R& relation)
|
|
{ return MethodRelationCls<O (T::*)() const, T, R>(method, relation); }
|
|
|
|
template <class C, class T>
|
|
void LruAdd(C& lru, T value, int limit = 10) {
|
|
int q = FindIndex(lru, value);
|
|
if(q >= 0)
|
|
lru.Remove(q);
|
|
lru.Insert(0, value);
|
|
if(lru.GetCount() > limit)
|
|
lru.SetCount(limit);
|
|
}
|