1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-16 15:24:10 +02:00
Beef/IDE/mintest/minlib/src/System/Array.bf

609 lines
13 KiB
Beef

// 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
using System.Collections;
using System.Diagnostics;
namespace System
{
#if BF_LARGE_COLLECTIONS
typealias int_arsize = int64;
#else
typealias int_arsize = int32;
#endif
class Array
{
protected int_arsize mLength;
public int Count
{
[Inline]
set
{
// We only allow reducing the length - consider using System.Collections.List<T> when dynamic sizing is required
Runtime.Assert(value <= mLength);
mLength = (.)value;
}
[Inline]
get
{
return mLength;
}
}
public bool IsEmpty
{
get
{
return mLength == 0;
}
}
public static int BinarySearch<T>(T* arr, int idx, int length, T value) where T : IComparable<T>
{
int lo = idx;
int hi = idx + length - 1;
while (lo <= hi)
{
int i = (lo + hi) / 2;
T midVal = arr[i];
int c = midVal.CompareTo(value);
if (c == 0) return i;
if (c < 0)
lo = i + 1;
else
hi = i - 1;
}
return ~lo;
}
public static int BinarySearch<T>(T* arr, int idx, int length, T value, IComparer<T> comp)
{
int lo = idx;
int hi = idx + length - 1;
while (lo <= hi)
{
int i = (lo + hi) / 2;
T midVal = arr[i];
int c = comp.Compare(midVal, value);
if (c == 0) return i;
if (c < 0)
lo = i + 1;
else
hi = i - 1;
}
return ~lo;
}
public static void Clear<T>(T[] arr, int idx, int length)
{
for (int i = idx; i < idx + length; i++)
arr[i] = default(T);
}
public static void Copy<T, T2>(T[] arrayFrom, int srcOffset, T2[] arrayTo, int dstOffset, int length) where T : var where T2 : var
{
if (((Object)arrayTo == (Object)arrayFrom) && (dstOffset > srcOffset))
{
for (int i = length - 1; i >= 0; i--)
arrayTo.getRef(i + dstOffset) = (T2)arrayFrom.getRef(i + srcOffset);
return;
}
for (int i = 0; i < length; i++)
arrayTo.getRef(i + dstOffset) = (T2)arrayFrom.getRef(i + srcOffset);
}
public static void Sort<T>(T[] array, Comparison<T> comp)
{
var sorter = Sorter<T, void>(&array.[Friend]mFirstElement, null, array.[Friend]mLength, comp);
sorter.Sort(0, array.[Friend]mLength);
}
public static void Sort<T, T2>(T[] keys, T2[] items, Comparison<T> comp)
{
var sorter = Sorter<T, T2>(&keys.[Friend]mFirstElement, &items.[Friend]mFirstElement, keys.[Friend]mLength, comp);
sorter.Sort(0, keys.[Friend]mLength);
}
public static void Sort<T>(T[] array, int index, int count, Comparison<T> comp)
{
var sorter = Sorter<T, void>(&array.[Friend]mFirstElement, null, array.[Friend]mLength, comp);
sorter.Sort(index, count);
}
// Reverses the elements in a range of an array. Following a call to this
// method, an element in the range given by index and count
// which was previously located at index i will now be located at
// index index + (index + count - i - 1).
// Reliability note: This may fail because it may have to box objects.
[DisableChecks]
public static void Reverse<T>(T[] arr, int index, int length)
{
Debug.Assert(arr != null);
Debug.Assert(index >= 0);
Debug.Assert(length >= 0);
Debug.Assert(length >= arr.Count - index);
int i = index;
int j = index + length - 1;
while (i < j)
{
let temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
}
// Reverses the elements in a range of an array. Following a call to this
// method, an element in the range given by index and count
// which was previously located at index i will now be located at
// index index + (index + count - i - 1).
// Reliability note: This may fail because it may have to box objects.
public static void SlowReverse<T>(T[] arr, int index, int length)
{
Debug.Assert(arr != null);
Debug.Assert(index >= 0);
Debug.Assert(length >= 0);
Debug.Assert(length >= arr.Count - index);
int i = index;
int j = index + length - 1;
while (i < j)
{
let temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
}
}
[Ordered]
class Array1<T> : Array
{
T mFirstElement;
public this()
{
}
[Inline]
public ref T getRef(int idx)
{
return ref (&mFirstElement)[idx];
}
[Inline]
public ref T getRefChecked(int idx)
{
if ((uint)idx >= (uint)mLength)
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
public ref T this[int idx]
{
[Unchecked, Inline]
get
{
return ref (&mFirstElement)[idx];
}
}
public ref T this[int idx]
{
[Checked, Inline]
get
{
if ((uint)idx >= (uint)mLength)
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
}
[Inline]
public T* CArray()
{
return &mFirstElement;
}
public void CopyTo(T[] arrayTo)
{
Debug.Assert(arrayTo.mLength >= mLength);
Internal.MemCpy(&arrayTo.getRef(0), &getRef(0), strideof(T) * mLength, alignof(T));
}
public void CopyTo(T[] arrayTo, int srcOffset, int dstOffset, int length)
{
Debug.Assert(length >= 0);
Debug.Assert((uint)srcOffset + (uint)length <= (uint)mLength);
Debug.Assert((uint)dstOffset + (uint)length <= (uint)arrayTo.mLength);
Internal.MemCpy(&arrayTo.getRef(dstOffset), &getRef(srcOffset), strideof(T) * length, alignof(T));
}
public void CopyTo<T2>(T2[] arrayTo, int srcOffset, int dstOffset, int length) where T2 : var
{
Debug.Assert(length >= 0);
Debug.Assert((uint)srcOffset + (uint)length <= (uint)mLength);
Debug.Assert((uint)dstOffset + (uint)length <= (uint)arrayTo.[Friend]mLength);
if (((Object)arrayTo == (Object)this) && (dstOffset > srcOffset))
{
for (int i = length - 1; i >= 0; i--)
arrayTo.getRef(i + dstOffset) = (T2)getRef(i + srcOffset);
return;
}
for (int i = 0; i < length; i++)
arrayTo.getRef(i + dstOffset) = (T2)getRef(i + srcOffset);
}
protected override void GCMarkMembers()
{
let type = typeof(T);
if ((type.[Friend]mTypeFlags & .WantsMark) == 0)
return;
for (int i = 0; i < mLength; i++)
{
GC.Mark((&mFirstElement)[i]);
}
}
}
[Ordered]
class Array2<T> : Array
{
int_arsize mLength1;
T mFirstElement;
Array GetSelf()
{
return this;
}
public this()
{
}
public int GetLength(int dim)
{
if (dim == 0)
return mLength / mLength1;
else if (dim == 1)
return mLength1;
Runtime.FatalError();
}
[Inline]
public ref T getRef(int idx)
{
return ref (&mFirstElement)[idx];
}
[Inline]
public ref T getRef(int idx0, int idx1)
{
return ref (&mFirstElement)[idx0*mLength1 + idx1];
}
[Inline]
public ref T getRefChecked(int idx)
{
if ((uint)idx >= (uint)mLength)
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
[Inline]
public ref T getRefChecked(int idx0, int idx1)
{
int idx = idx0*mLength1 + idx1;
if (((uint)idx >= (uint)mLength) ||
((uint)idx1 >= (uint)mLength1))
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
public ref T this[int idx]
{
[Unchecked, Inline]
get
{
return ref (&mFirstElement)[idx];
}
}
public ref T this[int idx0, int idx1]
{
[Unchecked, Inline]
get
{
return ref (&mFirstElement)[idx0*mLength1 + idx1];
}
}
public ref T this[int idx]
{
[Checked]
get
{
if ((uint)idx >= (uint)mLength)
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
}
public ref T this[int idx0, int idx1]
{
[Checked]
get
{
int idx = idx0*mLength1 + idx1;
if (((uint)idx >= (uint)mLength) ||
((uint)idx1 >= (uint)mLength1))
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
}
[Inline]
public T* CArray()
{
return &mFirstElement;
}
protected override void GCMarkMembers()
{
for (int i = 0; i < mLength; i++)
{
GC.Mark_Unbound((&mFirstElement)[i]);
}
}
}
[Ordered]
class Array3<T> : Array
{
int_arsize mLength1;
int_arsize mLength2;
T mFirstElement;
Array GetSelf()
{
return this;
}
public this()
{
}
public int GetLength(int dim)
{
if (dim == 0)
return mLength / (mLength1*mLength2);
else if (dim == 1)
return mLength1;
else if (dim == 2)
return mLength2;
Runtime.FatalError();
}
[Inline]
public ref T getRef(int idx)
{
return ref (&mFirstElement)[idx];
}
[Inline]
public ref T getRef(int idx0, int idx1, int idx2)
{
return ref (&mFirstElement)[(idx0*mLength1 + idx1)*mLength2 + idx2];
}
[Inline]
public ref T getRefChecked(int idx)
{
if ((uint)idx >= (uint)mLength)
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
[Inline]
public ref T getRefChecked(int idx0, int idx1, int idx2)
{
int idx = (idx0*mLength1 + idx1)*mLength2 + idx2;
if (((uint)idx >= (uint)mLength) ||
((uint)idx1 >= (uint)mLength1) ||
((uint)idx2 >= (uint)mLength2))
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
public ref T this[int idx]
{
[Unchecked, Inline]
get
{
return ref (&mFirstElement)[idx];
}
}
public ref T this[int idx0, int idx1, int idx2]
{
[Unchecked, Inline]
get
{
return ref (&mFirstElement)[(idx0*mLength1 + idx1)*mLength2 + idx2];
}
}
public ref T this[int idx]
{
[Checked]
get
{
if ((uint)idx >= (uint)mLength)
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
}
public ref T this[int idx0, int idx1, int idx2]
{
[Checked]
get
{
int idx = (idx0*mLength1 + idx1)*mLength2 + idx2;
if (((uint)idx >= (uint)mLength) ||
((uint)idx1 >= (uint)mLength1) ||
((uint)idx2 >= (uint)mLength2))
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
}
[Inline]
public T* CArray()
{
return &mFirstElement;
}
protected override void GCMarkMembers()
{
for (int i = 0; i < mLength; i++)
{
GC.Mark_Unbound((&mFirstElement)[i]);
}
}
}
[Ordered]
class Array4<T> : Array
{
int_arsize mLength1;
int_arsize mLength2;
int_arsize mLength3;
T mFirstElement;
Array GetSelf()
{
return this;
}
public this()
{
}
public int GetLength(int dim)
{
if (dim == 0)
return mLength / (mLength1*mLength2*mLength3);
else if (dim == 1)
return mLength1;
else if (dim == 2)
return mLength2;
else if (dim == 3)
return mLength3;
Runtime.FatalError();
}
[Inline]
public ref T getRef(int idx)
{
return ref (&mFirstElement)[idx];
}
[Inline]
public ref T getRef(int idx0, int idx1, int idx2, int idx3)
{
return ref (&mFirstElement)[((idx0*mLength1 + idx1)*mLength2 + idx2)*mLength3 + idx3];
}
[Inline]
public ref T getRefChecked(int idx)
{
if ((uint)idx >= (uint)mLength)
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
[Inline]
public ref T getRefChecked(int idx0, int idx1, int idx2, int idx3)
{
int idx = ((idx0*mLength1 + idx1)*mLength2 + idx2)*mLength3 + idx3;
if (((uint)idx >= (uint)mLength) ||
((uint)idx1 >= (uint)mLength1) ||
((uint)idx2 >= (uint)mLength2) ||
((uint)idx3 >= (uint)mLength3))
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
public ref T this[int idx]
{
[Unchecked, Inline]
get
{
return ref (&mFirstElement)[idx];
}
}
public ref T this[int idx0, int idx1, int idx2, int idx3]
{
[Unchecked, Inline]
get
{
return ref (&mFirstElement)[((idx0*mLength1 + idx1)*mLength2 + idx2)*mLength3 + idx3];
}
}
public ref T this[int idx]
{
[Checked]
get
{
if ((uint)idx >= (uint)mLength)
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
}
public ref T this[int idx0, int idx1, int idx2, int idx3]
{
[Checked]
get
{
int idx = ((idx0*mLength1 + idx1)*mLength2 + idx2)*mLength3 + idx3;
if (((uint)idx >= (uint)mLength) ||
((uint)idx1 >= (uint)mLength1) ||
((uint)idx2 >= (uint)mLength2) ||
((uint)idx3 >= (uint)mLength3))
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
}
[Inline]
public T* CArray()
{
return &mFirstElement;
}
protected override void GCMarkMembers()
{
for (int i = 0; i < mLength; i++)
{
GC.Mark_Unbound((&mFirstElement)[i]);
}
}
}
}