////////////////////////////////////////////////////////////////////////////// private static int SortHashcodeRangeUnique(ulong[] keysIdxs, int start, int end, Obj[] objs, IdxSorter sorter) { int writeIdx = start; int hashStartIdx = start; do { uint hashcode = MostSignificant(keysIdxs[hashStartIdx]); int hashEndIdx = hashStartIdx + 1; while (hashEndIdx < end && MostSignificant(keysIdxs[hashStartIdx]) == hashcode) { hashEndIdx++; } if (hashEndIdx - hashStartIdx > 1) { sorter.Sort(keysIdxs, hashStartIdx, hashEndIdx); int idx = hashStartIdx; do { if (idx != writeIdx) { keysIdxs[writeIdx] = keysIdxs[idx]; } writeIdx++; Obj obj = objs[LeastSignificant(keysIdxs[idx++])]; while (idx < hashEndIdx && obj.IsEq(objs[LeastSignificant(keysIdxs[idx])])) { idx++; } } while (idx < hashEndIdx); } else { if (hashStartIdx != writeIdx) { keysIdxs[writeIdx] = keysIdxs[hashStartIdx]; } writeIdx++; } hashStartIdx = hashEndIdx; } while (hashStartIdx < end); return(writeIdx); }
///////////////////////////////////////////////////////////////////////////// public static NeBinRelObj Create(Obj[] col1, Obj[] col2, int count) { Debug.Assert(count > 0); IdxSorter sorter1 = null; IdxSorter sorter2 = null; ulong[] keysIdxs = IndexesSortedByHashcode(col1, count); bool isMap = true; int writeIdx = 0; int hashStartIdx = 0; do { uint hashcode = MostSignificant(keysIdxs[hashStartIdx]); int hashEndIdx = hashStartIdx + 1; while (hashEndIdx < count && MostSignificant(keysIdxs[hashEndIdx]) == hashcode) { hashEndIdx++; } if (hashEndIdx - hashStartIdx > 1) { if (sorter1 == null) { sorter1 = new IdxSorter(col1); } sorter1.Sort(keysIdxs, hashStartIdx, hashEndIdx); int keyStartIdx = hashStartIdx; do { Obj key = col1[LeastSignificant(keysIdxs[keyStartIdx])]; int keyEndIdx = keyStartIdx + 1; while (keyEndIdx < hashEndIdx && key.IsEq(col1[LeastSignificant(keysIdxs[keyEndIdx])])) { keyEndIdx++; } int uniqueKeyEndIdx = keyEndIdx; if (keyEndIdx - keyStartIdx > 1) { for (int i = keyStartIdx; i < keyEndIdx; i++) { uint idx = LeastSignificant(keysIdxs[i]); keysIdxs[i] = (((ulong)col2[idx].Hashcode()) << 32) | idx; } Array.Sort(keysIdxs, keyStartIdx, keyEndIdx); if (sorter2 == null) { sorter2 = new IdxSorter(col2); } uniqueKeyEndIdx = SortHashcodeRangeUnique(keysIdxs, keyStartIdx, keyEndIdx, col2, sorter2); if (uniqueKeyEndIdx != keyStartIdx + 1) { isMap = false; } for (int i = keyStartIdx; i < uniqueKeyEndIdx; i++) { keysIdxs[i] = (((ulong)hashcode) << 32) | LeastSignificant(keysIdxs[i]); } } if (keyStartIdx != writeIdx) { for (int i = keyStartIdx; i < uniqueKeyEndIdx; i++) { keysIdxs[writeIdx++] = keysIdxs[i]; } } else { writeIdx += uniqueKeyEndIdx - keyStartIdx; } keyStartIdx = keyEndIdx; } while (keyStartIdx < hashEndIdx); } else { if (hashStartIdx != writeIdx) { keysIdxs[writeIdx] = keysIdxs[hashStartIdx]; } writeIdx++; } hashStartIdx = hashEndIdx; } while (hashStartIdx < count); uint[] hashcodes = new uint[writeIdx]; Obj[] sortedCol1 = new Obj[writeIdx]; Obj[] sortedCol2 = new Obj[writeIdx]; for (int i = 0; i < writeIdx; i++) { ulong keyIdx = keysIdxs[i]; hashcodes[i] = MostSignificant(keyIdx); uint idx = LeastSignificant(keyIdx); sortedCol1[i] = col1[idx]; sortedCol2[i] = col2[idx]; } NeBinRelObj relObj = new NeBinRelObj(sortedCol1, sortedCol2, hashcodes, isMap); // relObj.SelfCheck(col1, col2, count); return(relObj); }