template inline int sgn(T a) { return a > 0 ? 1 : a < 0 ? -1 : 0; } template inline T tabs(T a) { return (a >= 0 ? a : -a); } // there is a general mess about abs, this is not ideal but best we can do now... as long as we // do not want abs(1.1) == 1 surprise in GCC template inline T abs(T a) { return (a >= 0 ? a : -a); } template inline int cmp(const T& a, const T& b) { return a > b ? 1 : a < b ? -1 : 0; } template void Reverse(Range& r) { auto start = r.begin(); auto end = r.end(); if(start != end && --end != start) do IterSwap(start, end); while(++start != end && --end != start); } template void Reverse(Range&& r) { Reverse(r); } template void Accumulate(const Range& r, Accumulator& a) { for(const auto& e : r) a(e); } template ValueTypeOf Sum(const Range& r, const ValueTypeOf& zero) { ValueTypeOf sum = zero; for(const auto& e : r) sum += e; return sum; } template ValueTypeOf Sum(const T& c) { return Sum(c, (ValueTypeOf)0); } template int Count(const Range& r, const V& val) { int count = 0; for(const auto& x : r) if(x == val) count++; return count; } template int CountIf(const Range& r, const Predicate& p) { int count = 0; for(const auto& x : r) if(p(x)) count++; return count; } template int FindBest(const Range& r, const Pred& pred) { int count = r.GetCount(); if(count == 0) return -1; auto *m = &r[0]; int mi = 0; for(int i = 1; i < count; i++) if(pred(r[i], *m)) { m = &r[i]; mi = i; } return mi; } template int FindMin(const Range& r) { return FindBest(r, std::less>()); } template const ValueTypeOf& Min(const Range& r) { return r[FindMin(r)]; } template const ValueTypeOf& Min(const Range& r, const ValueTypeOf& def) { int q = FindMin(r); return q < 0 ? def : r[q]; } template int FindMax(const Range& r) { return FindBest(r, std::greater>()); } template const ValueTypeOf& Max(const Range& r) { return r[FindMax(r)]; } template const ValueTypeOf& Max(const Range& r, const ValueTypeOf& def) { int q = FindMax(r); return q < 0 ? def : r[q]; } template bool IsEqualRange(const Range1& a, const Range2& b) { if(a.GetCount() != b.GetCount()) return false; for(int i = 0; i < a.GetCount(); i++) if(!(a[i] == b[i])) return false; return true; } template int CompareRanges(const Range1& a, const Range2& b) { int n = min(a.GetCount(), b.GetCount()); for(int i = 0; i < n; i++) { int q = SgnCompare(a[i], b[i]); if(q) return q; } return SgnCompare(a.GetCount(), b.GetCount()); } template int FindMatch(const Range& r, const C& match, int from = 0) { for(int i = from; i < r.GetCount(); i++) if(match(r[i])) return i; return -1; } template int FindIndex(const Range& r, const V& value, int from = 0) { for(int i = from; i < r.GetCount(); i++) if(r[i] == value) return i; return -1; } template Vector FindAll(const Range& r, Predicate match, int from = 0) { Vector ndx; for(int i = from; i < r.GetCount(); i++) if(match(r[i])) ndx.Add(i); return ndx; } template int FindLowerBound(const Range& r, const T& val, const Less& less) { int pos = 0; int count = r.GetCount(); while(count > 0) { int half = count >> 1; int m = pos + half; if(less(r[m], val)) { pos = m + 1; count = count - half - 1; } else count = half; } return pos; } template int FindLowerBound(const Range& r, const T& val) { return FindLowerBound(r, val, std::less()); } template int FindUpperBound(const Range& r, const T& val, const L& less) { int pos = 0; int count = r.GetCount(); while(count > 0) { int half = count >> 1; int m = pos + half; if(less(val, r[m])) count = half; else { pos = m + 1; count = count - half - 1; } } return pos; } template int FindUpperBound(const Range& r, const T& val) { return FindUpperBound(r, val, std::less()); } template int FindBinary(const Range& r, const T& val, const L& less) { int i = FindLowerBound(r, val, less); return i < r.GetCount() && !less(val, r[i]) ? i : -1; } template int FindBinary(const Range& r, const T& val) { return FindBinary(r, val, std::less()); } template void LruAdd(Container& 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); }