private void MergeCascade(int level, T[] left, T[] right) { Contract.Requires(level > 0, "level"); Contract.Requires(left != null && left.Length == (1 << (level - 1)), "left"); Contract.Requires(right != null && right.Length == (1 << (level - 1)), "right"); if (IsFree(level)) { // target level is empty if (level >= m_levels.Length) { Grow(level); } Contract.Assert(level < m_levels.Length); ColaStore.MergeSort(m_levels[level], left, right, m_comparer); } else if (IsFree(level + 1)) { // the next level is empty if (level + 1 >= m_levels.Length) { Grow(level + 1); } Contract.Assert(level + 1 < m_levels.Length); var spare = GetSpare(level); ColaStore.MergeSort(spare, left, right, m_comparer); var next = m_levels[level]; ColaStore.MergeSort(m_levels[level + 1], next, spare, m_comparer); Array.Clear(next, 0, next.Length); PutSpare(level, spare); } else { // both are full, need to do a cascade merge Contract.Assert(level < m_levels.Length); // merge N and N +1 var spare = GetSpare(level); ColaStore.MergeSort(spare, left, right, m_comparer); // and cascade to N + 2 ... var next = m_levels[level]; MergeCascade(level + 1, next, spare); Array.Clear(next, 0, next.Length); PutSpare(level, spare); } }