diff --git a/src/common/utility/tarray.h b/src/common/utility/tarray.h index a420b078a8..f849e9cca5 100644 --- a/src/common/utility/tarray.h +++ b/src/common/utility/tarray.h @@ -355,6 +355,105 @@ public: return i; } + // !!! THIS REQUIRES AN ELEMENT TYPE THAT'S COMPARABLE WITH THE LT OPERATOR !!! + bool IsSorted() + { + for(unsigned i = 1; i < Count; i++) + { + if(Array[i] < Array[i-1]) return false; + } + return true; + } + + template + bool IsSorted(Func lt) + { + for(unsigned i = 1; i < Count; i++) + { + if(lt(Array[i], Array[i-1])) return false; + } + return true; + } + + // !!! THIS REQUIRES A SORTED OR EMPTY ARRAY !!! + // !!! AND AN ELEMENT TYPE THAT'S COMPARABLE WITH THE LT OPERATOR !!! + // + // exact = false returns the closest match, to be used for, ex., insertions, exact = true returns Size() when no match, like Find does + unsigned int SortedFind(const T& item, bool exact = true) const + { + if(Count == 0) return 0; + if(Count == 1) return (item < Array[0]) ? 0 : 1; + + unsigned int lo = 0; + unsigned int hi = Count - 1; + + while(lo <= hi) + { + int mid = lo + ((hi - lo) / 2); + + if(Array[mid] < item) + { + lo = mid + 1; + } + else if(item < Array[mid]) + { + hi = mid - 1; + } + else + { + return mid; + } + } + if(exact) + { + return Count; + } + else + { + return (lo == Count || (item < Array[lo])) ? lo : lo + 1; + } + } + + // !!! THIS REQUIRES A SORTED OR EMPTY ARRAY !!! + // + // exact = false returns the closest match, to be used for, ex., insertions, exact = true returns Size() when no match, like Find does + template + unsigned int SortedFind(const T& item, Func lt, bool exact = true) const + { + if(Count == 0) return 0; + if(Count == 1) return lt(item, Array[0]) ? 0 : 1; + + unsigned int lo = 0; + unsigned int hi = Count - 1; + + while(lo <= hi) + { + int mid = lo + ((hi - lo) / 2); + + if(lt(Array[mid], item)) + { + lo = mid + 1; + } + else if(lt(item, Array[mid])) + { + if(mid == 0) break; // prevent negative overflow due to unsigned numbers + hi = mid - 1; + } + else + { + return mid; + } + } + if(exact) + { + return Count; + } + else + { + return (lo == Count || lt(item, Array[lo])) ? lo : lo + 1; + } + } + bool Contains(const T& item) const { unsigned int i; @@ -462,6 +561,21 @@ public: return f; } + unsigned SortedAddUnique(const T& obj) + { + auto f = SortedFind(obj, true); + if (f == Size()) Push(obj); + return f; + } + + template + unsigned SortedAddUnique(const T& obj, Func lt) + { + auto f = SortedFind(obj, lt, true); + if (f == Size()) Push(obj); + return f; + } + bool Pop () { if (Count > 0) @@ -542,6 +656,17 @@ public: } } + void SortedInsert (const T &item) + { + Insert (SortedFind (item, false), item); + } + + template + void SortedInsert (const T &item, Func lt) + { + Insert (SortedFind (item, lt, false), item); + } + void ShrinkToFit () { if (Most > Count)