mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-17 07:44:09 +02:00
Initial checkin
This commit is contained in:
parent
c74712dad9
commit
078564ac9e
3242 changed files with 1616395 additions and 0 deletions
651
IDE/mintest/minlib/src/System/Collections/Generic/List.bf
Normal file
651
IDE/mintest/minlib/src/System/Collections/Generic/List.bf
Normal file
|
@ -0,0 +1,651 @@
|
|||
// This file contains portions of code released by Microsoft under the MIT license as part
|
||||
// of an open-sourcing initiative in 2014 of the C# core libraries.
|
||||
// The original source was submitted to https://github.com/Microsoft/referencesource
|
||||
|
||||
#if PARANOID
|
||||
#define VERSION_LIST
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.Runtime;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Threading;
|
||||
using System.Reflection;
|
||||
|
||||
namespace System.Collections.Generic
|
||||
{
|
||||
interface IList
|
||||
{
|
||||
Variant this[int index]
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
public class List<T> : IEnumerable<T>, IList
|
||||
{
|
||||
private const int_cosize cDefaultCapacity = 4;
|
||||
|
||||
const int_cosize SizeFlags = 0x7FFFFFFF;
|
||||
const int_cosize DynAllocFlag = (int_cosize)0x80000000;
|
||||
|
||||
#if BF_ENABLE_REALTIME_LEAK_CHECK
|
||||
static DbgRawAllocData sRawAllocData;
|
||||
public static this()
|
||||
{
|
||||
sRawAllocData.mMarkFunc = null;
|
||||
sRawAllocData.mMaxStackTrace = 1;
|
||||
sRawAllocData.mType = typeof(T);
|
||||
}
|
||||
#endif
|
||||
|
||||
private T* mItems;
|
||||
private int_cosize mSize;
|
||||
private int_cosize mAllocSizeAndFlags;
|
||||
#if VERSION_LIST
|
||||
private int32 mVersion;
|
||||
const String cVersionError = "List changed during enumeration";
|
||||
#endif
|
||||
|
||||
public int AllocSize
|
||||
{
|
||||
[Inline]
|
||||
get
|
||||
{
|
||||
return mAllocSizeAndFlags & SizeFlags;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsDynAlloc
|
||||
{
|
||||
[Inline]
|
||||
get
|
||||
{
|
||||
return (mAllocSizeAndFlags & DynAllocFlag) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
public this()
|
||||
{
|
||||
if (((int)Internal.UnsafeCastToPtr(this) & 0xFFFF) == 0x4BA0)
|
||||
{
|
||||
NOP!();
|
||||
}
|
||||
}
|
||||
|
||||
public this(IEnumerator<T> enumerator)
|
||||
{
|
||||
for (var item in enumerator)
|
||||
Add(item);
|
||||
}
|
||||
|
||||
[AllowAppend]
|
||||
public this(int capacity)
|
||||
{
|
||||
Debug.Assert((uint)capacity <= (uint)SizeFlags);
|
||||
T* items = append T[capacity]*;
|
||||
if (capacity > 0)
|
||||
{
|
||||
mItems = items;
|
||||
mAllocSizeAndFlags = (int_cosize)(capacity & SizeFlags);
|
||||
}
|
||||
}
|
||||
/*public this(int capacity)
|
||||
{
|
||||
Debug.Assert((uint)capacity <= (uint)SizeFlags);
|
||||
if (capacity > 0)
|
||||
{
|
||||
mItems = Alloc(capacity);
|
||||
mAllocSizeAndFlags = (int_cosize)(capacity | DynAllocFlag);
|
||||
}
|
||||
}*/
|
||||
|
||||
public ~this()
|
||||
{
|
||||
#if DBG
|
||||
int typeId = typeof(T).GetTypeId();
|
||||
if (typeId == sDebugTypeId)
|
||||
{
|
||||
Debug.WriteLine("Dealloc {0} {1}", scope Object[] { this, mItems } );
|
||||
}
|
||||
#endif
|
||||
|
||||
if (IsDynAlloc)
|
||||
Free(mItems);
|
||||
}
|
||||
|
||||
public T* Ptr
|
||||
{
|
||||
get
|
||||
{
|
||||
return mItems;
|
||||
}
|
||||
}
|
||||
|
||||
#if DBG
|
||||
static int_cosize sDebugTypeId = 470;
|
||||
static int_cosize sDebugIdx = 0;
|
||||
#endif
|
||||
|
||||
public int Capacity
|
||||
{
|
||||
get
|
||||
{
|
||||
return mAllocSizeAndFlags & SizeFlags;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
Debug.Assert((uint)value <= (uint)SizeFlags);
|
||||
if (value != AllocSize)
|
||||
{
|
||||
if (value > 0)
|
||||
{
|
||||
T* newItems = Alloc(value);
|
||||
|
||||
#if DBG
|
||||
int typeId = typeof(T).GetTypeId();
|
||||
if (typeId == sDebugTypeId)
|
||||
{
|
||||
Debug.WriteLine("Alloc {0} {1} {2}", scope Object[] { this, newItems, sDebugIdx } );
|
||||
sDebugIdx++;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mSize > 0)
|
||||
Internal.MemCpy(newItems, mItems, mSize * strideof(T), alignof(T));
|
||||
if (IsDynAlloc)
|
||||
Free(mItems);
|
||||
mItems = newItems;
|
||||
mAllocSizeAndFlags = (.)(value | DynAllocFlag);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsDynAlloc)
|
||||
Free(mItems);
|
||||
mItems = null;
|
||||
mAllocSizeAndFlags = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEmpty
|
||||
{
|
||||
get
|
||||
{
|
||||
return mSize == 0;
|
||||
}
|
||||
}
|
||||
|
||||
public ref T this[int index]
|
||||
{
|
||||
[Checked]
|
||||
get
|
||||
{
|
||||
Debug.Assert((uint)index < (uint)mSize);
|
||||
return ref mItems[index];
|
||||
}
|
||||
|
||||
[Checked]
|
||||
set
|
||||
{
|
||||
Debug.Assert((uint)index < (uint)mSize);
|
||||
mItems[index] = value;
|
||||
#if VERSION_LIST
|
||||
mVersion++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public ref T this[int index]
|
||||
{
|
||||
[Unchecked, Inline]
|
||||
get
|
||||
{
|
||||
return ref mItems[index];
|
||||
}
|
||||
|
||||
[Unchecked, Inline]
|
||||
set
|
||||
{
|
||||
mItems[index] = value;
|
||||
#if VERSION_LIST
|
||||
mVersion++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public ref T Back
|
||||
{
|
||||
get
|
||||
{
|
||||
Debug.Assert(mSize != 0);
|
||||
return ref mItems[mSize - 1];
|
||||
}
|
||||
}
|
||||
|
||||
Variant IList.this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
return [Unbound]Variant.Create(this[index]);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
ThrowUnimplemented();
|
||||
}
|
||||
}
|
||||
|
||||
protected T* Alloc(int size)
|
||||
{
|
||||
#if BF_ENABLE_REALTIME_LEAK_CHECK
|
||||
// We don't want to use the default mark function because it will mark the entire array,
|
||||
// whereas we have a custom marking routine because we only want to mark up to mSize
|
||||
return (T*)Internal.Dbg_RawAlloc(size * strideof(T), &sRawAllocData);
|
||||
#else
|
||||
return new T[size]*(?);
|
||||
#endif
|
||||
}
|
||||
|
||||
protected void Free(T* val)
|
||||
{
|
||||
delete val;
|
||||
}
|
||||
/*protected T[] Alloc(int size)
|
||||
{
|
||||
return new:this T[size];
|
||||
}
|
||||
|
||||
protected void Free(Object obj)
|
||||
{
|
||||
delete:this obj;
|
||||
}
|
||||
|
||||
protected virtual Object AllocObject(TypeInstance type, int size)
|
||||
{
|
||||
return Internal.ObjectAlloc(type, size);
|
||||
}
|
||||
|
||||
protected virtual void FreeObject(Object obj)
|
||||
{
|
||||
delete obj;
|
||||
}*/
|
||||
|
||||
/// Adds an item to the back of the list.
|
||||
public void Add(T item)
|
||||
{
|
||||
if (((int)Internal.UnsafeCastToPtr(this) & 0xFFFF) == 0x4BA0)
|
||||
{
|
||||
NOP!();
|
||||
}
|
||||
|
||||
if (mSize == AllocSize) EnsureCapacity(mSize + 1);
|
||||
mItems[mSize++] = item;
|
||||
#if VERSION_LIST
|
||||
mVersion++;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Returns a pointer to the start of the added uninitialized section
|
||||
public T* GrowUnitialized(int addSize)
|
||||
{
|
||||
if (mSize + addSize > AllocSize) EnsureCapacity(mSize + addSize);
|
||||
mSize += (int_cosize)addSize;
|
||||
#if VERSION_LIST
|
||||
mVersion++;
|
||||
#endif
|
||||
if (addSize == 0)
|
||||
return null;
|
||||
return &mItems[mSize - addSize];
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
if (mSize > 0)
|
||||
{
|
||||
mSize = 0;
|
||||
}
|
||||
#if VERSION_LIST
|
||||
mVersion++;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*public static void DeleteItemsAndClear<T>(List<T> list) where T : delete
|
||||
{
|
||||
foreach (var item in list)
|
||||
delete item;
|
||||
list.Clear();
|
||||
}*/
|
||||
|
||||
public bool Contains(T item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
for (int i = 0; i < mSize; i++)
|
||||
if (mItems[i] == null)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < mSize; i++)
|
||||
if (mItems[i] == item)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void CopyTo(T[] array)
|
||||
{
|
||||
CopyTo(array, 0);
|
||||
}
|
||||
|
||||
public void CopyTo(List<T> destList)
|
||||
{
|
||||
destList.EnsureCapacity(mSize);
|
||||
destList.mSize = mSize;
|
||||
if (mSize > 0)
|
||||
Internal.MemCpy(destList.mItems, mItems, mSize * strideof(T), alignof(T));
|
||||
}
|
||||
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
// Delegate rest of error checking to Array.Copy.
|
||||
for (int_cosize i = 0; i < mSize; i++)
|
||||
array[i + arrayIndex] = mItems[i];
|
||||
}
|
||||
|
||||
public void EnsureCapacity(int min)
|
||||
{
|
||||
int allocSize = AllocSize;
|
||||
if (allocSize < min)
|
||||
{
|
||||
int_cosize newCapacity = (int_cosize)(allocSize == 0 ? cDefaultCapacity : allocSize * 2);
|
||||
// Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow.
|
||||
// Note that this check works even when mItems.Length overflowed thanks to the (uint) cast
|
||||
//if ((uint)newCapacity > Array.MaxArrayLength) newCapacity = Array.MaxArrayLength;
|
||||
if (newCapacity < min) newCapacity = (int_cosize)min;
|
||||
Capacity = newCapacity;
|
||||
}
|
||||
}
|
||||
|
||||
public void Reserve(int size)
|
||||
{
|
||||
EnsureCapacity(size);
|
||||
}
|
||||
|
||||
public Enumerator GetEnumerator()
|
||||
{
|
||||
return Enumerator(this);
|
||||
}
|
||||
|
||||
public int_cosize IndexOf(T item)
|
||||
{
|
||||
//return Array.IndexOf(mItems, item, 0, mSize);
|
||||
for (int i = 0; i < mSize; i++)
|
||||
if (mItems[i] == item)
|
||||
return (int_cosize)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int_cosize IndexOf(T item, int index)
|
||||
{
|
||||
for (int i = index; i < mSize; i++)
|
||||
if (mItems[i] == item)
|
||||
return (int_cosize)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int_cosize IndexOf(T item, int index, int count)
|
||||
{
|
||||
for (int i = index; i < index + count; i++)
|
||||
if (mItems[i] == item)
|
||||
return (int_cosize)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void Insert(int index, T item)
|
||||
{
|
||||
if (mSize == AllocSize) EnsureCapacity(mSize + 1);
|
||||
if (index < mSize)
|
||||
{
|
||||
Internal.MemCpy(mItems + index + 1, mItems + index, (mSize - index) * strideof(T), alignof(T));
|
||||
}
|
||||
mItems[index] = item;
|
||||
mSize++;
|
||||
#if VERSION_LIST
|
||||
mVersion++;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
if (((int)Internal.UnsafeCastToPtr(this) & 0xFFFF) == 0x4BA0)
|
||||
{
|
||||
NOP!();
|
||||
}
|
||||
|
||||
Debug.Assert((uint)index < (uint)mSize);
|
||||
if (index < mSize - 1)
|
||||
{
|
||||
Internal.MemCpy(mItems + index, mItems + index + 1, (mSize - index - 1) * strideof(T), alignof(T));
|
||||
}
|
||||
mSize--;
|
||||
#if VERSION_LIST
|
||||
mVersion++;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void RemoveRange(int index, int count)
|
||||
{
|
||||
Debug.Assert((uint)index + (uint)count <= (uint)mSize);
|
||||
if (index + count < mSize - 1)
|
||||
{
|
||||
for (int i = index; i < mSize - count; i++)
|
||||
mItems[i] = mItems[i + count];
|
||||
}
|
||||
mSize -= (.)count;
|
||||
#if VERSION_LIST
|
||||
mVersion++;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void RemoveAtFast(int index)
|
||||
{
|
||||
Debug.Assert((uint32)index < (uint32)mSize);
|
||||
mSize--;
|
||||
if (mSize > 0)
|
||||
mItems[index] = mItems[mSize];
|
||||
#if VERSION_LIST
|
||||
mVersion++;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void Sort(Comparison<T> comp)
|
||||
{
|
||||
var sorter = Sorter<T, void>(mItems, null, mSize, comp);
|
||||
sorter.Sort(0, mSize);
|
||||
}
|
||||
|
||||
public T PopBack()
|
||||
{
|
||||
T backVal = mItems[mSize - 1];
|
||||
mSize--;
|
||||
return backVal;
|
||||
}
|
||||
|
||||
public T PopFront()
|
||||
{
|
||||
T backVal = mItems[0];
|
||||
RemoveAt(0);
|
||||
return backVal;
|
||||
}
|
||||
|
||||
public bool Remove(T item)
|
||||
{
|
||||
int_cosize index = IndexOf(item);
|
||||
if (index >= 0)
|
||||
{
|
||||
RemoveAt(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static operator Span<T>(List<T> list)
|
||||
{
|
||||
return Span<T>(list.mItems, list.mSize);
|
||||
}
|
||||
|
||||
protected override void GCMarkMembers()
|
||||
{
|
||||
for (int i < mSize)
|
||||
{
|
||||
GC.Mark_Unbound(mItems[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public struct Enumerator : IRefEnumerator<T>
|
||||
{
|
||||
private List<T> mList;
|
||||
private int mIndex;
|
||||
#if VERSION_LIST
|
||||
private int32 mVersion;
|
||||
#endif
|
||||
private T* mCurrent;
|
||||
|
||||
internal this(List<T> list)
|
||||
{
|
||||
mList = list;
|
||||
mIndex = 0;
|
||||
#if VERSION_LIST
|
||||
mVersion = list.mVersion;
|
||||
#endif
|
||||
mCurrent = null;
|
||||
}
|
||||
|
||||
#if VERSION_LIST
|
||||
void CheckVersion()
|
||||
{
|
||||
if (mVersion != mList.mVersion)
|
||||
Runtime.FatalError(cVersionError);
|
||||
}
|
||||
#endif
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public bool MoveNext() mut
|
||||
{
|
||||
List<T> localList = mList;
|
||||
if ((uint(mIndex) < uint(localList.mSize)))
|
||||
{
|
||||
mCurrent = &localList.mItems[mIndex];
|
||||
mIndex++;
|
||||
return true;
|
||||
}
|
||||
return MoveNextRare();
|
||||
}
|
||||
|
||||
private bool MoveNextRare() mut
|
||||
{
|
||||
#if VERSION_LIST
|
||||
CheckVersion();
|
||||
#endif
|
||||
mIndex = mList.mSize + 1;
|
||||
mCurrent = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public T Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return *mCurrent;
|
||||
}
|
||||
}
|
||||
|
||||
public ref T CurrentRef
|
||||
{
|
||||
get
|
||||
{
|
||||
return ref *mCurrent;
|
||||
}
|
||||
}
|
||||
|
||||
public int Index
|
||||
{
|
||||
get
|
||||
{
|
||||
return mIndex - 1;
|
||||
}
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return mList.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove() mut
|
||||
{
|
||||
int curIdx = mIndex - 1;
|
||||
mList.RemoveAt(curIdx);
|
||||
#if VERSION_LIST
|
||||
mVersion = mList.mVersion;
|
||||
#endif
|
||||
mIndex = curIdx;
|
||||
}
|
||||
|
||||
public void RemoveFast() mut
|
||||
{
|
||||
int curIdx = mIndex - 1;
|
||||
int lastIdx = mList.Count - 1;
|
||||
if (curIdx < lastIdx)
|
||||
mList[curIdx] = mList[lastIdx];
|
||||
mList.RemoveAt(lastIdx);
|
||||
#if VERSION_LIST
|
||||
mVersion = mList.mVersion;
|
||||
#endif
|
||||
mIndex = curIdx;
|
||||
}
|
||||
|
||||
public void Reset() mut
|
||||
{
|
||||
mIndex = 0;
|
||||
mCurrent = null;
|
||||
}
|
||||
|
||||
|
||||
public Result<T> GetNext() mut
|
||||
{
|
||||
if (!MoveNext())
|
||||
return .Err;
|
||||
return Current;
|
||||
}
|
||||
|
||||
public Result<T*> GetNextRef() mut
|
||||
{
|
||||
if (!MoveNext())
|
||||
return .Err;
|
||||
return &CurrentRef;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
302
IDE/mintest/minlib/src/System/Collections/Generic/Sorter.bf
Normal file
302
IDE/mintest/minlib/src/System/Collections/Generic/Sorter.bf
Normal file
|
@ -0,0 +1,302 @@
|
|||
// This file contains portions of code released by Microsoft under the MIT license as part
|
||||
// of an open-sourcing initiative in 2014 of the C# core libraries.
|
||||
// The original source was submitted to https://github.com/Microsoft/referencesource
|
||||
|
||||
namespace System.Collections.Generic
|
||||
{
|
||||
struct Sorter<T, T2>
|
||||
{
|
||||
// This is the threshold where Introspective sort switches to Insertion sort.
|
||||
// Empirically, 16 seems to speed up most cases without slowing down others, at least for integers.
|
||||
// Large value types may benefit from a smaller number.
|
||||
const int IntrosortSizeThreshold = 16;
|
||||
|
||||
private T* keys;
|
||||
private T2* items;
|
||||
private int mCount;
|
||||
private Comparison<T> comparer;
|
||||
|
||||
internal this(T* keys, T2* items, int count, Comparison<T> comparer)
|
||||
{
|
||||
this.keys = keys;
|
||||
this.items = items;
|
||||
mCount = count;
|
||||
this.comparer = comparer;
|
||||
}
|
||||
|
||||
internal static int FloorLog2(int n)
|
||||
{
|
||||
int result = 0;
|
||||
int val = n;
|
||||
while (val >= 1)
|
||||
{
|
||||
result++;
|
||||
val = val / 2;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int GetMedian(int low, int hi)
|
||||
{
|
||||
// Note both may be negative, if we are dealing with arrays w/ negative lower bounds.
|
||||
//Contract.Requires(low <= hi);
|
||||
//Contract.Assert( hi - low >= 0, "Length overflow!");
|
||||
return low + ((hi - low) >> 1);
|
||||
}
|
||||
|
||||
internal void SwapIfGreaterWithItems(int a, int b)
|
||||
{
|
||||
if (a != b)
|
||||
{
|
||||
if (comparer(keys[a], keys[b]) > 0)
|
||||
{
|
||||
T temp = keys[a];
|
||||
keys[a] = keys[b];
|
||||
keys[b] = temp;
|
||||
if ((items != null) && (sizeof(T2) != 0))
|
||||
{
|
||||
T2 item = items[a];
|
||||
items[a] = items[b];
|
||||
items[b] = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Swap(int i, int j)
|
||||
{
|
||||
T t = keys[i];
|
||||
keys[i] = keys[j];
|
||||
keys[j] = t;
|
||||
|
||||
if (items != null)
|
||||
{
|
||||
T2 item = items[i];
|
||||
items[i] = items[j];
|
||||
items[j] = item;
|
||||
}
|
||||
}
|
||||
|
||||
internal void Sort(int left, int length)
|
||||
{
|
||||
IntrospectiveSort(left, length);
|
||||
}
|
||||
|
||||
private void DepthLimitedQuickSort(int left, int right, int depthLimit)
|
||||
{
|
||||
// Can use the much faster jit helpers for array access.
|
||||
repeat
|
||||
{
|
||||
if (depthLimit == 0)
|
||||
{
|
||||
Heapsort(left, right);
|
||||
return;
|
||||
}
|
||||
|
||||
int curLeft = left;
|
||||
int curRight = right;
|
||||
int curDepthLimit = depthLimit;
|
||||
|
||||
int i = curLeft;
|
||||
int j = curRight;
|
||||
|
||||
// pre-sort the low, middle (pivot), and high values in place.
|
||||
// this improves performance in the face of already sorted data, or
|
||||
// data that is made up of multiple sorted runs appended together.
|
||||
int middle = GetMedian(i, j);
|
||||
|
||||
SwapIfGreaterWithItems(i, middle); // swap the low with the mid point
|
||||
SwapIfGreaterWithItems(i, j); // swap the low with the high
|
||||
SwapIfGreaterWithItems(middle, j); // swap the middle with the high
|
||||
|
||||
T x = keys[middle];
|
||||
repeat
|
||||
{
|
||||
while (comparer(keys[i], x) < 0) i++;
|
||||
while (comparer(x, keys[j]) < 0) j--;
|
||||
|
||||
//Contract.Assert(i >= left && j <= right, "(i>=left && j<=right) Sort failed - Is your IComparer bogus?");
|
||||
if (i > j) break;
|
||||
if (i < j)
|
||||
{
|
||||
T key = keys[i];
|
||||
keys[i] = keys[j];
|
||||
keys[j] = key;
|
||||
if (items != null)
|
||||
{
|
||||
T2 item = items[i];
|
||||
items[i] = items[j];
|
||||
items[j] = item;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
j--;
|
||||
} while (i <= j);
|
||||
|
||||
// The next iteration of the while loop is to "recursively" sort the larger half of the array and the
|
||||
// following calls recrusively sort the smaller half. So we subtrack one from depthLimit here so
|
||||
// both sorts see the new value.
|
||||
curDepthLimit--;
|
||||
|
||||
if (j - curLeft <= curRight - i)
|
||||
{
|
||||
if (curLeft < j) DepthLimitedQuickSort(curLeft, j, curDepthLimit);
|
||||
curLeft = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i < curRight) DepthLimitedQuickSort(i, curRight, curDepthLimit);
|
||||
curRight = j;
|
||||
}
|
||||
} while (left < right);
|
||||
}
|
||||
|
||||
private void IntrospectiveSort(int left, int length)
|
||||
{
|
||||
if (length < 2)
|
||||
return;
|
||||
|
||||
IntroSort(left, length + left - 1, 2 * FloorLog2(mCount));
|
||||
}
|
||||
|
||||
private void IntroSort(int lo, int hi, int depthLimit)
|
||||
{
|
||||
int curHi = hi;
|
||||
int curDepthLimit = depthLimit;
|
||||
|
||||
while (curHi > lo)
|
||||
{
|
||||
int partitionSize = curHi - lo + 1;
|
||||
if (partitionSize <= IntrosortSizeThreshold)
|
||||
{
|
||||
if (partitionSize == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (partitionSize == 2)
|
||||
{
|
||||
SwapIfGreaterWithItems(lo, curHi);
|
||||
return;
|
||||
}
|
||||
if (partitionSize == 3)
|
||||
{
|
||||
SwapIfGreaterWithItems(lo, curHi-1);
|
||||
SwapIfGreaterWithItems(lo, curHi);
|
||||
SwapIfGreaterWithItems(curHi-1, curHi);
|
||||
return;
|
||||
}
|
||||
|
||||
InsertionSort(lo, curHi);
|
||||
return;
|
||||
}
|
||||
|
||||
if (curDepthLimit == 0)
|
||||
{
|
||||
Heapsort(lo, curHi);
|
||||
return;
|
||||
}
|
||||
curDepthLimit--;
|
||||
|
||||
int p = PickPivotAndPartition(lo, curHi);
|
||||
IntroSort(p + 1, curHi, curDepthLimit);
|
||||
curHi = p - 1;
|
||||
}
|
||||
}
|
||||
|
||||
private int PickPivotAndPartition(int lo, int hi)
|
||||
{
|
||||
// Compute median-of-three. But also partition them, since we've done the comparison.
|
||||
int mid = lo + (hi - lo) / 2;
|
||||
// Sort lo, mid and hi appropriately, then pick mid as the pivot.
|
||||
SwapIfGreaterWithItems(lo, mid);
|
||||
SwapIfGreaterWithItems(lo, hi);
|
||||
SwapIfGreaterWithItems(mid, hi);
|
||||
|
||||
T pivot = keys[mid];
|
||||
Swap(mid, hi - 1);
|
||||
int left = lo, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below.
|
||||
|
||||
while (left < right)
|
||||
{
|
||||
while (comparer(keys[++left], pivot) < 0) {}
|
||||
while (comparer(pivot, keys[--right]) < 0) {}
|
||||
|
||||
if(left >= right)
|
||||
break;
|
||||
|
||||
Swap(left, right);
|
||||
}
|
||||
|
||||
// Put pivot in the right location.
|
||||
Swap(left, (hi - 1));
|
||||
return left;
|
||||
}
|
||||
|
||||
private void Heapsort(int lo, int hi)
|
||||
{
|
||||
int n = hi - lo + 1;
|
||||
for (int i = n / 2; i >= 1; i = i - 1)
|
||||
{
|
||||
DownHeap(i, n, lo);
|
||||
}
|
||||
for (int i = n; i > 1; i = i - 1)
|
||||
{
|
||||
Swap(lo, lo + i - 1);
|
||||
|
||||
DownHeap(1, i - 1, lo);
|
||||
}
|
||||
}
|
||||
|
||||
private void DownHeap(int i, int n, int lo)
|
||||
{
|
||||
int curI = i;
|
||||
|
||||
T d = keys[lo + curI - 1];
|
||||
//T dt = (items != null) ? items[lo + i - 1] : null;
|
||||
T2* dt = (items != null) ? &items[lo + curI - 1] : null;
|
||||
int child;
|
||||
while (curI <= n / 2)
|
||||
{
|
||||
child = 2 * curI;
|
||||
if (child < n && comparer(keys[lo + child - 1], keys[lo + child]) < 0)
|
||||
{
|
||||
child++;
|
||||
}
|
||||
if (!(comparer(d, keys[lo + child - 1]) < 0))
|
||||
break;
|
||||
keys[lo + curI - 1] = keys[lo + child - 1];
|
||||
if(items != null)
|
||||
items[lo + curI - 1] = items[lo + child - 1];
|
||||
curI = child;
|
||||
}
|
||||
keys[lo + curI - 1] = d;
|
||||
if (items != null)
|
||||
items[lo + curI - 1] = *dt;
|
||||
}
|
||||
|
||||
private void InsertionSort(int lo, int hi)
|
||||
{
|
||||
int i, j;
|
||||
T t;
|
||||
T2* ti = null;
|
||||
for (i = lo; i < hi; i++)
|
||||
{
|
||||
j = i;
|
||||
t = keys[i + 1];
|
||||
//ti = (items != null) ? items[i + 1] : null;
|
||||
if (items != null)
|
||||
ti = &items[i + 1];
|
||||
while (j >= lo && comparer(t, keys[j]) < 0)
|
||||
{
|
||||
keys[j + 1] = keys[j];
|
||||
if(items != null)
|
||||
items[j + 1] = items[j];
|
||||
j--;
|
||||
}
|
||||
keys[j + 1] = t;
|
||||
if (items != null)
|
||||
items[j + 1] = *ti;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
36
IDE/mintest/minlib/src/System/Collections/IEnumerator.bf
Normal file
36
IDE/mintest/minlib/src/System/Collections/IEnumerator.bf
Normal file
|
@ -0,0 +1,36 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace System.Collections
|
||||
{
|
||||
interface IEnumerator
|
||||
{
|
||||
Object Current { get; }
|
||||
bool MoveNext();
|
||||
void Reset();
|
||||
void Dispose();
|
||||
}
|
||||
|
||||
interface IEnumerable
|
||||
{
|
||||
IEnumerator GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
namespace System.Collections.Generic
|
||||
{
|
||||
interface IEnumerator<T>
|
||||
{
|
||||
Result<T> GetNext() mut;
|
||||
}
|
||||
|
||||
interface IRefEnumerator<T> : IEnumerator<T>
|
||||
{
|
||||
Result<T*> GetNextRef() mut;
|
||||
}
|
||||
|
||||
concrete interface IEnumerable<T>
|
||||
{
|
||||
concrete IEnumerator<T> GetEnumerator();
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue