Refactor and enhance math and utility libraries
Some checks failed
Publish NuGet Packages / publish (push) Failing after 3m12s
Some checks failed
Publish NuGet Packages / publish (push) Failing after 3m12s
Refactored `sincos` usage across `quaternion` and `random` to use `out` parameters for improved performance. Enhanced `random` struct with updated random direction generation methods. Added new benchmarks in `MathematicsBenchmark` for vector operations, including SIMD-based `f4` struct. Downgraded target framework to `net9.0` for compatibility. Introduced `ReadOnlyUnsafeCollection` for low-level memory management. Added utility methods in `CollectionUtility` for span creation and optimized list operations. Renamed `MemoryUtilities` to `MemoryUtility` and updated all references. Enhanced `ObjectPool` with `Rent` and `TryRent` methods. Enabled `AllowUnsafeBlocks` and AOT compatibility in project configuration. Performed general code cleanup, including removal of unused methods, improved formatting, and alignment with modern coding practices.
This commit is contained in:
@@ -9,10 +9,10 @@ namespace Misaki.HighPerformance.LowLevel.Collections;
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This struct is designed to hold data on the stack. Every copy of this struct causes a copy of the underlying data.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 32 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedString32"/>.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 32 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedText32"/>.
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential, Size = 32)]
|
||||
public unsafe struct FixedString32
|
||||
public unsafe struct FixedText32
|
||||
{
|
||||
private ushort _length;
|
||||
private fixed byte _buffer[30];
|
||||
@@ -38,7 +38,7 @@ public unsafe struct FixedString32
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(value);
|
||||
if (maxBytes > 30)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString32.");
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText32.");
|
||||
}
|
||||
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
@@ -48,12 +48,12 @@ public unsafe struct FixedString32
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString32(ReadOnlySpan<char> input)
|
||||
public FixedText32(ReadOnlySpan<char> input)
|
||||
{
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(input);
|
||||
if (maxBytes > 30)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString32.");
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText32.");
|
||||
}
|
||||
|
||||
fixed (char* inputPtr = input)
|
||||
@@ -64,21 +64,21 @@ public unsafe struct FixedString32
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString32(string input)
|
||||
public FixedText32(string input)
|
||||
: this(input.AsSpan())
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString32(char* input, ushort length)
|
||||
public FixedText32(char* input, ushort length)
|
||||
: this(new Span<char>(input, length))
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString32(ReadOnlySpan<byte> input)
|
||||
public FixedText32(ReadOnlySpan<byte> input)
|
||||
{
|
||||
if (input.Length > 30)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedString32.");
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedText32.");
|
||||
}
|
||||
|
||||
_length = (ushort)input.Length;
|
||||
@@ -90,7 +90,7 @@ public unsafe struct FixedString32
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString32(byte* input, ushort length)
|
||||
public FixedText32(byte* input, ushort length)
|
||||
: this(new ReadOnlySpan<byte>(input, length))
|
||||
{
|
||||
}
|
||||
@@ -124,10 +124,10 @@ public unsafe struct FixedString32
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This struct is designed to hold data on the stack. Every copy of this struct causes a copy of the underlying data.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 64 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedString64"/>.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 64 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedText64"/>.
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential, Size = 64)]
|
||||
public unsafe struct FixedString64
|
||||
public unsafe struct FixedText64
|
||||
{
|
||||
private ushort _length;
|
||||
private fixed byte _buffer[62];
|
||||
@@ -153,7 +153,7 @@ public unsafe struct FixedString64
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(value);
|
||||
if (maxBytes > 62)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString64.");
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText64.");
|
||||
}
|
||||
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
@@ -163,12 +163,12 @@ public unsafe struct FixedString64
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString64(ReadOnlySpan<char> input)
|
||||
public FixedText64(ReadOnlySpan<char> input)
|
||||
{
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(input);
|
||||
if (maxBytes > 62)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString64.");
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText64.");
|
||||
}
|
||||
|
||||
fixed (char* inputPtr = input)
|
||||
@@ -179,21 +179,21 @@ public unsafe struct FixedString64
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString64(string input)
|
||||
public FixedText64(string input)
|
||||
: this(input.AsSpan())
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString64(char* input, ushort length)
|
||||
public FixedText64(char* input, ushort length)
|
||||
: this(new Span<char>(input, length))
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString64(ReadOnlySpan<byte> input)
|
||||
public FixedText64(ReadOnlySpan<byte> input)
|
||||
{
|
||||
if (input.Length > 62)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedString64.");
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedText64.");
|
||||
}
|
||||
|
||||
_length = (ushort)input.Length;
|
||||
@@ -205,7 +205,7 @@ public unsafe struct FixedString64
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString64(byte* input, ushort length)
|
||||
public FixedText64(byte* input, ushort length)
|
||||
: this(new ReadOnlySpan<byte>(input, length))
|
||||
{
|
||||
}
|
||||
@@ -239,10 +239,10 @@ public unsafe struct FixedString64
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This struct is designed to hold data on the stack. Every copy of this struct causes a copy of the underlying data.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 128 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedString128"/>.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 128 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedText128"/>.
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential, Size = 128)]
|
||||
public unsafe struct FixedString128
|
||||
public unsafe struct FixedText128
|
||||
{
|
||||
private ushort _length;
|
||||
private fixed byte _buffer[126];
|
||||
@@ -268,7 +268,7 @@ public unsafe struct FixedString128
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(value);
|
||||
if (maxBytes > 126)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString128.");
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText128.");
|
||||
}
|
||||
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
@@ -278,12 +278,12 @@ public unsafe struct FixedString128
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString128(ReadOnlySpan<char> input)
|
||||
public FixedText128(ReadOnlySpan<char> input)
|
||||
{
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(input);
|
||||
if (maxBytes > 126)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString128.");
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText128.");
|
||||
}
|
||||
|
||||
fixed (char* inputPtr = input)
|
||||
@@ -294,21 +294,21 @@ public unsafe struct FixedString128
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString128(string input)
|
||||
public FixedText128(string input)
|
||||
: this(input.AsSpan())
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString128(char* input, ushort length)
|
||||
public FixedText128(char* input, ushort length)
|
||||
: this(new Span<char>(input, length))
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString128(ReadOnlySpan<byte> input)
|
||||
public FixedText128(ReadOnlySpan<byte> input)
|
||||
{
|
||||
if (input.Length > 126)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedString128.");
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedText128.");
|
||||
}
|
||||
|
||||
_length = (ushort)input.Length;
|
||||
@@ -320,7 +320,7 @@ public unsafe struct FixedString128
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString128(byte* input, ushort length)
|
||||
public FixedText128(byte* input, ushort length)
|
||||
: this(new ReadOnlySpan<byte>(input, length))
|
||||
{
|
||||
}
|
||||
@@ -354,10 +354,10 @@ public unsafe struct FixedString128
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This struct is designed to hold data on the stack. Every copy of this struct causes a copy of the underlying data.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 256 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedString256"/>.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 256 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedText256"/>.
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential, Size = 256)]
|
||||
public unsafe struct FixedString256
|
||||
public unsafe struct FixedText256
|
||||
{
|
||||
private ushort _length;
|
||||
private fixed byte _buffer[254];
|
||||
@@ -383,7 +383,7 @@ public unsafe struct FixedString256
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(value);
|
||||
if (maxBytes > 254)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString256.");
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText256.");
|
||||
}
|
||||
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
@@ -393,12 +393,12 @@ public unsafe struct FixedString256
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString256(ReadOnlySpan<char> input)
|
||||
public FixedText256(ReadOnlySpan<char> input)
|
||||
{
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(input);
|
||||
if (maxBytes > 254)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString256.");
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText256.");
|
||||
}
|
||||
|
||||
fixed (char* inputPtr = input)
|
||||
@@ -409,21 +409,21 @@ public unsafe struct FixedString256
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString256(string input)
|
||||
public FixedText256(string input)
|
||||
: this(input.AsSpan())
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString256(char* input, ushort length)
|
||||
public FixedText256(char* input, ushort length)
|
||||
: this(new Span<char>(input, length))
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString256(ReadOnlySpan<byte> input)
|
||||
public FixedText256(ReadOnlySpan<byte> input)
|
||||
{
|
||||
if (input.Length > 254)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedString256.");
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedText256.");
|
||||
}
|
||||
|
||||
_length = (ushort)input.Length;
|
||||
@@ -435,7 +435,7 @@ public unsafe struct FixedString256
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString256(byte* input, ushort length)
|
||||
public FixedText256(byte* input, ushort length)
|
||||
: this(new ReadOnlySpan<byte>(input, length))
|
||||
{
|
||||
}
|
||||
@@ -469,10 +469,10 @@ public unsafe struct FixedString256
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This struct is designed to hold data on the stack. Every copy of this struct causes a copy of the underlying data.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 512 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedString512"/>.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 512 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedText512"/>.
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential, Size = 512)]
|
||||
public unsafe struct FixedString512
|
||||
public unsafe struct FixedText512
|
||||
{
|
||||
private ushort _length;
|
||||
private fixed byte _buffer[510];
|
||||
@@ -498,7 +498,7 @@ public unsafe struct FixedString512
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(value);
|
||||
if (maxBytes > 510)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString512.");
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText512.");
|
||||
}
|
||||
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
@@ -508,12 +508,12 @@ public unsafe struct FixedString512
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString512(ReadOnlySpan<char> input)
|
||||
public FixedText512(ReadOnlySpan<char> input)
|
||||
{
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(input);
|
||||
if (maxBytes > 510)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString512.");
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText512.");
|
||||
}
|
||||
|
||||
fixed (char* inputPtr = input)
|
||||
@@ -524,21 +524,21 @@ public unsafe struct FixedString512
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString512(string input)
|
||||
public FixedText512(string input)
|
||||
: this(input.AsSpan())
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString512(char* input, ushort length)
|
||||
public FixedText512(char* input, ushort length)
|
||||
: this(new Span<char>(input, length))
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString512(ReadOnlySpan<byte> input)
|
||||
public FixedText512(ReadOnlySpan<byte> input)
|
||||
{
|
||||
if (input.Length > 510)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedString512.");
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedText512.");
|
||||
}
|
||||
|
||||
_length = (ushort)input.Length;
|
||||
@@ -550,7 +550,7 @@ public unsafe struct FixedString512
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString512(byte* input, ushort length)
|
||||
public FixedText512(byte* input, ushort length)
|
||||
: this(new ReadOnlySpan<byte>(input, length))
|
||||
{
|
||||
}
|
||||
@@ -584,10 +584,10 @@ public unsafe struct FixedString512
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This struct is designed to hold data on the stack. Every copy of this struct causes a copy of the underlying data.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 1024 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedString1024"/>.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 1024 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedText1024"/>.
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential, Size = 1024)]
|
||||
public unsafe struct FixedString1024
|
||||
public unsafe struct FixedText1024
|
||||
{
|
||||
private ushort _length;
|
||||
private fixed byte _buffer[1022];
|
||||
@@ -613,7 +613,7 @@ public unsafe struct FixedString1024
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(value);
|
||||
if (maxBytes > 1022)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString1024.");
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText1024.");
|
||||
}
|
||||
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
@@ -623,12 +623,12 @@ public unsafe struct FixedString1024
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString1024(ReadOnlySpan<char> input)
|
||||
public FixedText1024(ReadOnlySpan<char> input)
|
||||
{
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(input);
|
||||
if (maxBytes > 1022)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString1024.");
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText1024.");
|
||||
}
|
||||
|
||||
fixed (char* inputPtr = input)
|
||||
@@ -639,21 +639,21 @@ public unsafe struct FixedString1024
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString1024(string input)
|
||||
public FixedText1024(string input)
|
||||
: this(input.AsSpan())
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString1024(char* input, ushort length)
|
||||
public FixedText1024(char* input, ushort length)
|
||||
: this(new Span<char>(input, length))
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString1024(ReadOnlySpan<byte> input)
|
||||
public FixedText1024(ReadOnlySpan<byte> input)
|
||||
{
|
||||
if (input.Length > 1022)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedString1024.");
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedText1024.");
|
||||
}
|
||||
|
||||
_length = (ushort)input.Length;
|
||||
@@ -665,7 +665,7 @@ public unsafe struct FixedString1024
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString1024(byte* input, ushort length)
|
||||
public FixedText1024(byte* input, ushort length)
|
||||
: this(new ReadOnlySpan<byte>(input, length))
|
||||
{
|
||||
}
|
||||
@@ -699,10 +699,10 @@ public unsafe struct FixedString1024
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This struct is designed to hold data on the stack. Every copy of this struct causes a copy of the underlying data.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 2048 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedString2048"/>.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 2048 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedText2048"/>.
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential, Size = 2048)]
|
||||
public unsafe struct FixedString2048
|
||||
public unsafe struct FixedText2048
|
||||
{
|
||||
private ushort _length;
|
||||
private fixed byte _buffer[2046];
|
||||
@@ -728,7 +728,7 @@ public unsafe struct FixedString2048
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(value);
|
||||
if (maxBytes > 2046)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString2048.");
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText2048.");
|
||||
}
|
||||
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
@@ -738,12 +738,12 @@ public unsafe struct FixedString2048
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString2048(ReadOnlySpan<char> input)
|
||||
public FixedText2048(ReadOnlySpan<char> input)
|
||||
{
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(input);
|
||||
if (maxBytes > 2046)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString2048.");
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText2048.");
|
||||
}
|
||||
|
||||
fixed (char* inputPtr = input)
|
||||
@@ -754,21 +754,21 @@ public unsafe struct FixedString2048
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString2048(string input)
|
||||
public FixedText2048(string input)
|
||||
: this(input.AsSpan())
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString2048(char* input, ushort length)
|
||||
public FixedText2048(char* input, ushort length)
|
||||
: this(new Span<char>(input, length))
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString2048(ReadOnlySpan<byte> input)
|
||||
public FixedText2048(ReadOnlySpan<byte> input)
|
||||
{
|
||||
if (input.Length > 2046)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedString2048.");
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedText2048.");
|
||||
}
|
||||
|
||||
_length = (ushort)input.Length;
|
||||
@@ -780,7 +780,7 @@ public unsafe struct FixedString2048
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString2048(byte* input, ushort length)
|
||||
public FixedText2048(byte* input, ushort length)
|
||||
: this(new ReadOnlySpan<byte>(input, length))
|
||||
{
|
||||
}
|
||||
@@ -814,10 +814,10 @@ public unsafe struct FixedString2048
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This struct is designed to hold data on the stack. Every copy of this struct causes a copy of the underlying data.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 4096 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedString4096"/>.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 4096 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedText4096"/>.
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential, Size = 4096)]
|
||||
public unsafe struct FixedString4096
|
||||
public unsafe struct FixedText4096
|
||||
{
|
||||
private ushort _length;
|
||||
private fixed byte _buffer[4094];
|
||||
@@ -843,7 +843,7 @@ public unsafe struct FixedString4096
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(value);
|
||||
if (maxBytes > 4094)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString4096.");
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText4096.");
|
||||
}
|
||||
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
@@ -853,12 +853,12 @@ public unsafe struct FixedString4096
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString4096(ReadOnlySpan<char> input)
|
||||
public FixedText4096(ReadOnlySpan<char> input)
|
||||
{
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(input);
|
||||
if (maxBytes > 4094)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString4096.");
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText4096.");
|
||||
}
|
||||
|
||||
fixed (char* inputPtr = input)
|
||||
@@ -869,21 +869,21 @@ public unsafe struct FixedString4096
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString4096(string input)
|
||||
public FixedText4096(string input)
|
||||
: this(input.AsSpan())
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString4096(char* input, ushort length)
|
||||
public FixedText4096(char* input, ushort length)
|
||||
: this(new Span<char>(input, length))
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString4096(ReadOnlySpan<byte> input)
|
||||
public FixedText4096(ReadOnlySpan<byte> input)
|
||||
{
|
||||
if (input.Length > 4094)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedString4096.");
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedText4096.");
|
||||
}
|
||||
|
||||
_length = (ushort)input.Length;
|
||||
@@ -895,7 +895,7 @@ public unsafe struct FixedString4096
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString4096(byte* input, ushort length)
|
||||
public FixedText4096(byte* input, ushort length)
|
||||
: this(new ReadOnlySpan<byte>(input, length))
|
||||
{
|
||||
}
|
||||
@@ -16,10 +16,10 @@ namespace Misaki.HighPerformance.LowLevel.Collections;
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This struct is designed to hold data on the stack. Every copy of this struct causes a copy of the underlying data.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length <#= i #> bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedString<#= i #>"/>.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length <#= i #> bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedText<#= i #>"/>.
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential, Size = <#= i #>)]
|
||||
public unsafe struct FixedString<#= i #>
|
||||
public unsafe struct FixedText<#= i #>
|
||||
{
|
||||
private ushort _length;
|
||||
private fixed byte _buffer[<#= i - 2 #>];
|
||||
@@ -45,7 +45,7 @@ public unsafe struct FixedString<#= i #>
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(value);
|
||||
if (maxBytes > <#= i - 2 #>)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString<#= i #>.");
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText<#= i #>.");
|
||||
}
|
||||
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
@@ -55,12 +55,12 @@ public unsafe struct FixedString<#= i #>
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString<#= i #>(ReadOnlySpan<char> input)
|
||||
public FixedText<#= i #>(ReadOnlySpan<char> input)
|
||||
{
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(input);
|
||||
if (maxBytes > <#= i - 2 #>)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString<#= i #>.");
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText<#= i #>.");
|
||||
}
|
||||
|
||||
fixed (char* inputPtr = input)
|
||||
@@ -71,21 +71,21 @@ public unsafe struct FixedString<#= i #>
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString<#= i #>(string input)
|
||||
public FixedText<#= i #>(string input)
|
||||
: this(input.AsSpan())
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString<#= i #>(char* input, ushort length)
|
||||
public FixedText<#= i #>(char* input, ushort length)
|
||||
: this(new Span<char>(input, length))
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString<#= i #>(ReadOnlySpan<byte> input)
|
||||
public FixedText<#= i #>(ReadOnlySpan<byte> input)
|
||||
{
|
||||
if (input.Length > <#= i - 2 #>)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedString<#= i #>.");
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedText<#= i #>.");
|
||||
}
|
||||
|
||||
_length = (ushort)input.Length;
|
||||
@@ -97,7 +97,7 @@ public unsafe struct FixedString<#= i #>
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString<#= i #>(byte* input, ushort length)
|
||||
public FixedText<#= i #>(byte* input, ushort length)
|
||||
: this(new ReadOnlySpan<byte>(input, length))
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||
using System.Collections;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Misaki.HighPerformance.LowLevel.Collections;
|
||||
|
||||
/// <summary>
|
||||
/// Provides a read-only, unsafe view over a contiguous region of unmanaged memory as an array of elements of type T.
|
||||
/// Enables efficient, low-level access to memory without copying or additional safety checks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This read only collection does not own the memory it points to. The user is responsible for ensuring the memory remains valid for the lifetime of this structure.
|
||||
/// The goal of this struc is similar to <see cref="ReadOnlySpan{T}"/>, but it can be used in contexts where spans are not allowed, such as fields in structs and shared across threads.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of elements in the collection. Must be an unmanaged type.</typeparam>
|
||||
public readonly unsafe struct ReadOnlyUnsafeCollection<T> : IEnumerable<T>
|
||||
where T : unmanaged
|
||||
{
|
||||
public struct Enumerator : IEnumerator<T>
|
||||
{
|
||||
private readonly ReadOnlyUnsafeCollection<T> _collection;
|
||||
private int _index;
|
||||
private T _value;
|
||||
|
||||
public readonly T Current
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _value;
|
||||
}
|
||||
|
||||
readonly object IEnumerator.Current => Current;
|
||||
|
||||
public Enumerator(ref readonly ReadOnlyUnsafeCollection<T> array)
|
||||
{
|
||||
_collection = array;
|
||||
_index = -1;
|
||||
_value = default;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool MoveNext()
|
||||
{
|
||||
_index++;
|
||||
|
||||
if (_index < _collection.Count)
|
||||
{
|
||||
_value = UnsafeUtility.ReadArrayElement<T>(_collection._buffer, _index);
|
||||
return true;
|
||||
}
|
||||
|
||||
_value = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_index = -1;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private readonly T* _buffer;
|
||||
private readonly int _count;
|
||||
|
||||
public readonly int Count => _count;
|
||||
|
||||
public readonly T this[int index]
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => UnsafeUtility.ReadArrayElement<T>(_buffer, index);
|
||||
}
|
||||
|
||||
public readonly T this[uint index]
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => UnsafeUtility.ReadArrayElement<T>(_buffer, index);
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator() => new Enumerator(in this);
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
public ReadOnlyUnsafeCollection(T* buffer, int count)
|
||||
{
|
||||
_buffer = buffer;
|
||||
_count = count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a read-only span that represents the valid elements in the underlying buffer.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="ReadOnlySpan{T}"/> containing the elements of the buffer up to the current count.</returns>
|
||||
public ReadOnlySpan<T> AsSpan()
|
||||
{
|
||||
return new ReadOnlySpan<T>(_buffer, _count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reinterprets the underlying collection as a read-only collection of a different unmanaged type without copying the data.
|
||||
/// </summary>
|
||||
/// <typeparam name="U">The unmanaged type to reinterpret the collection elements as.</typeparam>
|
||||
/// <returns>A new ReadOnlyUnsafeCollection<U> that provides a read-only view of the same memory, interpreted as elements of type U.</returns>
|
||||
/// <exception cref="InvalidOperationException">Thrown if the total size of the underlying collection is not a multiple of the size of type U, making the reinterpretation invalid.</exception>
|
||||
public ReadOnlyUnsafeCollection<U> Reinterpret<U>()
|
||||
where U : unmanaged
|
||||
{
|
||||
var totalSize = (nuint)(Count * sizeof(T));
|
||||
if (totalSize % (nuint)sizeof(U) != 0)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot reinterpret collection: size mismatch.");
|
||||
}
|
||||
|
||||
var newCount = (int)(totalSize / (nuint)sizeof(U));
|
||||
return new ReadOnlyUnsafeCollection<U>((U*)_buffer, newCount);
|
||||
}
|
||||
}
|
||||
@@ -75,7 +75,7 @@ public unsafe struct UnTypedArray : IUnTypedCollection
|
||||
public readonly ref T GetElementAt<T>(uint index)
|
||||
where T : unmanaged
|
||||
{
|
||||
return ref UnsafeUtilities.ReadArrayElementRef<T>(_buffer, index);
|
||||
return ref UnsafeUtility.ReadArrayElementRef<T>(_buffer, index);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -18,26 +18,25 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
|
||||
{
|
||||
private readonly UnsafeArray<T>* _collection;
|
||||
private int _index;
|
||||
private T _value;
|
||||
|
||||
public Enumerator(UnsafeArray<T>* collection)
|
||||
{
|
||||
_collection = collection;
|
||||
_index = -1;
|
||||
_value = default;
|
||||
Current = default;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool MoveNext()
|
||||
{
|
||||
_index++;
|
||||
if (_index < _collection->_count)
|
||||
if (_index < _collection->Count)
|
||||
{
|
||||
_value = UnsafeUtilities.ReadArrayElement<T>(_collection->_buffer, _index);
|
||||
Current = UnsafeUtility.ReadArrayElement<T>(_collection->_buffer, _index);
|
||||
return true;
|
||||
}
|
||||
|
||||
_value = default;
|
||||
Current = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -47,10 +46,10 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
|
||||
}
|
||||
|
||||
// Let NativeArray indexer check for out of range.
|
||||
public readonly T Current
|
||||
public T Current
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _value;
|
||||
get; private set;
|
||||
}
|
||||
|
||||
readonly object IEnumerator.Current
|
||||
@@ -66,7 +65,6 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
|
||||
|
||||
private T* _buffer;
|
||||
private int _count;
|
||||
|
||||
private AllocationHandle* _handle;
|
||||
|
||||
public readonly int Count => _count;
|
||||
@@ -83,7 +81,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
|
||||
}
|
||||
#endif
|
||||
|
||||
return ref UnsafeUtilities.ReadArrayElementRef<T>(_buffer, index);
|
||||
return ref UnsafeUtility.ReadArrayElementRef<T>(_buffer, index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +97,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
|
||||
}
|
||||
#endif
|
||||
|
||||
return ref UnsafeUtilities.ReadArrayElementRef<T>(_buffer, index);
|
||||
return ref UnsafeUtility.ReadArrayElementRef<T>(_buffer, index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +107,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
|
||||
get => _buffer != null;
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator() => new Enumerator((UnsafeArray<T>*)UnsafeUtilities.AddressOf(ref this));
|
||||
public IEnumerator<T> GetEnumerator() => new Enumerator((UnsafeArray<T>*)UnsafeUtility.AddressOf(ref this));
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
/// <summary>
|
||||
@@ -167,16 +165,21 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
|
||||
_count = count;
|
||||
}
|
||||
|
||||
public ReadOnlyUnsafeCollection<T> AsReadOnly()
|
||||
{
|
||||
return new ReadOnlyUnsafeCollection<T>(_buffer, _count);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Resize(int newSize, AllocationOption option = AllocationOption.None)
|
||||
{
|
||||
if (newSize == _count)
|
||||
if (newSize == Count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var elemSize = SizeOf<T>();
|
||||
_buffer = (T*)_handle->Realloc(_handle->Allocator, _buffer, (nuint)_count * elemSize, (nuint)newSize * elemSize, AlignOf<T>(), option);
|
||||
_buffer = (T*)_handle->Realloc(_handle->Allocator, _buffer, (nuint)Count * elemSize, (nuint)newSize * elemSize, AlignOf<T>(), option);
|
||||
_count = newSize;
|
||||
}
|
||||
|
||||
@@ -184,7 +187,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly void Clear()
|
||||
{
|
||||
MemClear(_buffer, (nuint)(_count * sizeof(T)));
|
||||
MemClear(_buffer, (nuint)(Count * sizeof(T)));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -194,6 +197,25 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reinterprets the underlying buffer as an array of a different unmanaged type without copying the data.
|
||||
/// </summary>
|
||||
/// <typeparam name="U">The unmanaged type to reinterpret the buffer as.</typeparam>
|
||||
/// <returns>An UnsafeArray<U> that views the same memory as the original array, but as elements of type U.</returns>
|
||||
/// <exception cref="InvalidOperationException">Thrown if the total size of the buffer in bytes is not a multiple of the size of type U.</exception>
|
||||
public readonly UnsafeArray<U> Reinterpret<U>()
|
||||
where U : unmanaged
|
||||
{
|
||||
var totalSize = (nuint)(Count * sizeof(T));
|
||||
if (totalSize % (nuint)sizeof(U) != 0)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot reinterpret array: size mismatch.");
|
||||
}
|
||||
|
||||
var newCount = (int)(totalSize / (nuint)sizeof(U));
|
||||
return new UnsafeArray<U>((U*)_buffer, newCount);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
@@ -53,25 +53,25 @@ public struct UnsafeBitSet : IDisposable
|
||||
/// </summary>
|
||||
public UnsafeBitSet()
|
||||
{
|
||||
_bits = new UnsafeArray<uint>(s_padding, Allocator.Persistent);
|
||||
_bits = new UnsafeArray<uint>(s_padding, Allocator.Persistent, AllocationOption.Clear);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UnsafeBitSet" /> class.
|
||||
/// </summary>
|
||||
public UnsafeBitSet(int minimalLength)
|
||||
public UnsafeBitSet(int minimalLength, Allocator allocator, AllocationOption option = AllocationOption.Clear)
|
||||
{
|
||||
var uints = (minimalLength >> _INDEX_SIZE) + int.Sign(minimalLength & _BIT_SIZE);
|
||||
var length = RoundToPadding(uints);
|
||||
_bits = new UnsafeArray<uint>(length, Allocator.Persistent);
|
||||
_bits = new UnsafeArray<uint>(length, allocator, option);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UnsafeBitSet" /> class.
|
||||
/// </summary>
|
||||
public UnsafeBitSet(params Span<uint> bits)
|
||||
public UnsafeBitSet(Span<uint> bits, Allocator allocator, AllocationOption option = AllocationOption.Clear)
|
||||
{
|
||||
_bits = new UnsafeArray<uint>(bits.Length, Allocator.Persistent);
|
||||
_bits = new UnsafeArray<uint>(bits.Length, allocator, option);
|
||||
_bits.CopyFrom(bits);
|
||||
|
||||
_highestBit = 0;
|
||||
@@ -109,6 +109,11 @@ public struct UnsafeBitSet : IDisposable
|
||||
get => _bits.Count;
|
||||
}
|
||||
|
||||
public bool IsCreated
|
||||
{
|
||||
get => _bits.IsCreated;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether a bit is set at the index.
|
||||
/// </summary>
|
||||
@@ -443,10 +448,88 @@ public struct UnsafeBitSet : IDisposable
|
||||
return true;
|
||||
}
|
||||
|
||||
public unsafe void AndOperation(UnsafeBitSet other)
|
||||
{
|
||||
var min = Math.Min(Length, other.Length);
|
||||
var temp = stackalloc uint[min];
|
||||
|
||||
if (!Vector.IsHardwareAccelerated || min < s_padding)
|
||||
{
|
||||
for (var i = 0; i < min; i++)
|
||||
{
|
||||
temp[i] = _bits[i] & other._bits[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < min; i += s_padding)
|
||||
{
|
||||
var vectorLeft = new Vector<uint>(_bits.AsSpan()[i..]);
|
||||
var vectorRight = new Vector<uint>(other._bits.AsSpan()[i..]);
|
||||
var resultVector = Vector.BitwiseAnd(vectorLeft, vectorRight);
|
||||
resultVector.CopyTo(new Span<uint>(temp + i, s_padding));
|
||||
}
|
||||
}
|
||||
|
||||
_bits.CopyFrom(new Span<uint>(temp, min));
|
||||
}
|
||||
|
||||
public unsafe void OrOperation(UnsafeBitSet other)
|
||||
{
|
||||
var min = Math.Min(Length, other.Length);
|
||||
var temp = stackalloc uint[min];
|
||||
|
||||
if (!Vector.IsHardwareAccelerated || min < s_padding)
|
||||
{
|
||||
for (var i = 0; i < min; i++)
|
||||
{
|
||||
temp[i] = _bits[i] | other._bits[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < min; i += s_padding)
|
||||
{
|
||||
var vectorLeft = new Vector<uint>(_bits.AsSpan()[i..]);
|
||||
var vectorRight = new Vector<uint>(other._bits.AsSpan()[i..]);
|
||||
var resultVector = Vector.BitwiseOr(vectorLeft, vectorRight);
|
||||
resultVector.CopyTo(new Span<uint>(temp + i, s_padding));
|
||||
}
|
||||
}
|
||||
|
||||
_bits.CopyFrom(new Span<uint>(temp, min));
|
||||
}
|
||||
|
||||
public unsafe void XorOperation(UnsafeBitSet other)
|
||||
{
|
||||
var min = Math.Min(Length, other.Length);
|
||||
var temp = stackalloc uint[min];
|
||||
|
||||
if (!Vector.IsHardwareAccelerated || min < s_padding)
|
||||
{
|
||||
for (var i = 0; i < min; i++)
|
||||
{
|
||||
temp[i] = _bits[i] ^ other._bits[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < min; i += s_padding)
|
||||
{
|
||||
var vectorLeft = new Vector<uint>(_bits.AsSpan()[i..]);
|
||||
var vectorRight = new Vector<uint>(other._bits.AsSpan()[i..]);
|
||||
var resultVector = Vector.Xor(vectorLeft, vectorRight);
|
||||
resultVector.CopyTo(new Span<uint>(temp + i, s_padding));
|
||||
}
|
||||
}
|
||||
|
||||
_bits.CopyFrom(new Span<uint>(temp, min));
|
||||
}
|
||||
|
||||
public static UnsafeBitSet operator &(UnsafeBitSet left, UnsafeBitSet right)
|
||||
{
|
||||
var min = Math.Min(left.Length, right.Length);
|
||||
var result = new UnsafeBitSet(min);
|
||||
var result = new UnsafeBitSet(min, Allocator.Persistent);
|
||||
if (!Vector.IsHardwareAccelerated || min < s_padding)
|
||||
{
|
||||
for (var i = 0; i < min; i++)
|
||||
@@ -470,7 +553,7 @@ public struct UnsafeBitSet : IDisposable
|
||||
public static UnsafeBitSet operator |(UnsafeBitSet left, UnsafeBitSet right)
|
||||
{
|
||||
var min = Math.Min(left.Length, right.Length);
|
||||
var result = new UnsafeBitSet(min);
|
||||
var result = new UnsafeBitSet(min, Allocator.Persistent);
|
||||
if (!Vector.IsHardwareAccelerated || min < s_padding)
|
||||
{
|
||||
for (var i = 0; i < min; i++)
|
||||
|
||||
@@ -84,7 +84,7 @@ public unsafe struct UnsafeHashMap<TKey, TValue> : IUnsafeCollection<KeyValuePai
|
||||
var idx = _hashMap.Find(key);
|
||||
if (-1 != idx)
|
||||
{
|
||||
UnsafeUtilities.WriteArrayElement(_hashMap.Buffer, idx, value);
|
||||
UnsafeUtility.WriteArrayElement(_hashMap.Buffer, idx, value);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ public unsafe struct UnsafeHashMap<TKey, TValue> : IUnsafeCollection<KeyValuePai
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => new Enumerator((HashMapHelper<TKey>*)UnsafeUtilities.AddressOf(ref _hashMap));
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => new Enumerator((HashMapHelper<TKey>*)UnsafeUtility.AddressOf(ref _hashMap));
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
/// <summary>
|
||||
@@ -125,7 +125,7 @@ public unsafe struct UnsafeHashMap<TKey, TValue> : IUnsafeCollection<KeyValuePai
|
||||
var idx = _hashMap.TryAdd(key);
|
||||
if (idx != -1)
|
||||
{
|
||||
UnsafeUtilities.WriteArrayElement(_hashMap.Buffer, idx, item);
|
||||
UnsafeUtility.WriteArrayElement(_hashMap.Buffer, idx, item);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ public unsafe struct UnsafeHashSet<T> : IUnsafeCollection<T>, IEnumerable<T>
|
||||
public readonly int Capacity => _hashMap.Capacity;
|
||||
public readonly bool IsCreated => _hashMap.IsCreated;
|
||||
|
||||
public IEnumerator<T> GetEnumerator() => new Enumerator((HashMapHelper<T>*)UnsafeUtilities.AddressOf(ref _hashMap));
|
||||
public IEnumerator<T> GetEnumerator() => new Enumerator((HashMapHelper<T>*)UnsafeUtility.AddressOf(ref _hashMap));
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -33,7 +33,7 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
|
||||
_index++;
|
||||
if (_index < _collection->_count)
|
||||
{
|
||||
_value = UnsafeUtilities.ReadArrayElement<T>(_collection->_array.GetUnsafePtr(), _index);
|
||||
_value = UnsafeUtility.ReadArrayElement<T>(_collection->_array.GetUnsafePtr(), _index);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
|
||||
{
|
||||
var idx = Interlocked.Increment(ref listData->_count) - 1;
|
||||
listData->CheckNoResizeCapacity(idx, 1);
|
||||
UnsafeUtilities.WriteArrayElement(listData->_array.GetUnsafePtr(), idx, value);
|
||||
UnsafeUtility.WriteArrayElement(listData->_array.GetUnsafePtr(), idx, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -111,7 +111,7 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
|
||||
|
||||
fixed (T* pCollection = collection)
|
||||
{
|
||||
MemCpy(UnsafeUtilities.ReadArrayElementUnsafe<T>(listData->_array.GetUnsafePtr(), index), pCollection, (uint)(count * sizeof(T)));
|
||||
MemCpy(UnsafeUtility.ReadArrayElementUnsafe<T>(listData->_array.GetUnsafePtr(), index), pCollection, (uint)(count * sizeof(T)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -136,14 +136,14 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
|
||||
get => ref _array[index];
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator() => new Enumerator((UnsafeList<T>*)UnsafeUtilities.AddressOf(ref this));
|
||||
public IEnumerator<T> GetEnumerator() => new Enumerator((UnsafeList<T>*)UnsafeUtility.AddressOf(ref this));
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
/// <summary>
|
||||
/// Provides a parallel writer for the current list, enabling thread-safe additions to the list.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="ParallelWriter"/> instance that can be used to add items to the list in a thread-safe manner.</returns>
|
||||
public ParallelWriter AsParallelWriter() => new((UnsafeList<T>*)UnsafeUtilities.AddressOf(ref this));
|
||||
public ParallelWriter AsParallelWriter() => new((UnsafeList<T>*)UnsafeUtility.AddressOf(ref this));
|
||||
|
||||
/// <summary>
|
||||
/// Converts the current list to an UnsafeArray representation.
|
||||
@@ -221,6 +221,11 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
|
||||
}
|
||||
}
|
||||
|
||||
public readonly ReadOnlyUnsafeCollection<T> AsReadOnly()
|
||||
{
|
||||
return new ReadOnlyUnsafeCollection<T>((T*)_array.GetUnsafePtr(), _count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new element to the end of the list, resizing the internal array if necessary.
|
||||
/// </summary>
|
||||
@@ -232,7 +237,7 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
|
||||
Resize(Capacity + (int)(Capacity * 0.5f));
|
||||
}
|
||||
|
||||
UnsafeUtilities.WriteArrayElement(_array.GetUnsafePtr(), _count, value);
|
||||
UnsafeUtility.WriteArrayElement(_array.GetUnsafePtr(), _count, value);
|
||||
_count++;
|
||||
}
|
||||
|
||||
@@ -244,7 +249,7 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
|
||||
{
|
||||
CheckNoResizeCapacity(1);
|
||||
|
||||
UnsafeUtilities.WriteArrayElement(_array.GetUnsafePtr(), _count, value);
|
||||
UnsafeUtility.WriteArrayElement(_array.GetUnsafePtr(), _count, value);
|
||||
_count++;
|
||||
}
|
||||
|
||||
@@ -264,7 +269,7 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
|
||||
|
||||
fixed (T* ptr = values)
|
||||
{
|
||||
MemCpy(UnsafeUtilities.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), _count), ptr, (uint)(count * sizeof(T)));
|
||||
MemCpy(UnsafeUtility.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), _count), ptr, (uint)(count * sizeof(T)));
|
||||
}
|
||||
|
||||
_count += count;
|
||||
@@ -280,7 +285,7 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
|
||||
|
||||
fixed (T* pCollection = collection)
|
||||
{
|
||||
MemCpy(UnsafeUtilities.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), _count), pCollection, (uint)(collection.Length * sizeof(T)));
|
||||
MemCpy(UnsafeUtility.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), _count), pCollection, (uint)(collection.Length * sizeof(T)));
|
||||
}
|
||||
|
||||
_count += collection.Length;
|
||||
@@ -295,7 +300,7 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
|
||||
{
|
||||
CheckNoResizeCapacity(count);
|
||||
|
||||
MemCpy(UnsafeUtilities.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), _count), ptr, (uint)(count * sizeof(T)));
|
||||
MemCpy(UnsafeUtility.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), _count), ptr, (uint)(count * sizeof(T)));
|
||||
_count += count;
|
||||
}
|
||||
|
||||
@@ -314,8 +319,8 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
|
||||
}
|
||||
|
||||
var copyFrom = Math.Min(start + length, _count);
|
||||
MemCpy(UnsafeUtilities.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), start),
|
||||
UnsafeUtilities.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), copyFrom),
|
||||
MemCpy(UnsafeUtility.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), start),
|
||||
UnsafeUtility.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), copyFrom),
|
||||
(uint)((_count - copyFrom) * sizeof(T))
|
||||
);
|
||||
_count -= length;
|
||||
@@ -345,8 +350,8 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
|
||||
}
|
||||
|
||||
var copyFrom = Math.Min(_count - length, start + length);
|
||||
MemCpy(UnsafeUtilities.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), start),
|
||||
UnsafeUtilities.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), copyFrom),
|
||||
MemCpy(UnsafeUtility.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), start),
|
||||
UnsafeUtility.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), copyFrom),
|
||||
(uint)((_count - copyFrom) * sizeof(T))
|
||||
);
|
||||
_count -= length;
|
||||
@@ -389,5 +394,4 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
|
||||
_array.Dispose();
|
||||
_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -33,7 +33,7 @@ public unsafe struct UnsafeQueue<T> : IUnsafeCollection<T>
|
||||
_index++;
|
||||
if (_index < _collection->_count)
|
||||
{
|
||||
_value = UnsafeUtilities.ReadArrayElement<T>(_collection->_array.GetUnsafePtr(), _index);
|
||||
_value = UnsafeUtility.ReadArrayElement<T>(_collection->_array.GetUnsafePtr(), _index);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ public unsafe struct UnsafeQueue<T> : IUnsafeCollection<T>
|
||||
set => _array[index] = value;
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator() => new Enumerator((UnsafeQueue<T>*)UnsafeUtilities.AddressOf(ref this));
|
||||
public IEnumerator<T> GetEnumerator() => new Enumerator((UnsafeQueue<T>*)UnsafeUtility.AddressOf(ref this));
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
/// <summary>
|
||||
@@ -115,7 +115,7 @@ public unsafe struct UnsafeQueue<T> : IUnsafeCollection<T>
|
||||
throw new InvalidOperationException("Queue is empty.");
|
||||
}
|
||||
|
||||
return ref UnsafeUtilities.ReadArrayElementRef<T>(_array.GetUnsafePtr(), _offset);
|
||||
return ref UnsafeUtility.ReadArrayElementRef<T>(_array.GetUnsafePtr(), _offset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -130,7 +130,7 @@ public unsafe struct UnsafeQueue<T> : IUnsafeCollection<T>
|
||||
Resize(Capacity + (int)(Capacity * 0.5f));
|
||||
}
|
||||
|
||||
UnsafeUtilities.WriteArrayElement(_array.GetUnsafePtr(), (_offset + _count) % Capacity, value);
|
||||
UnsafeUtility.WriteArrayElement(_array.GetUnsafePtr(), (_offset + _count) % Capacity, value);
|
||||
_count++;
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ public unsafe struct UnsafeQueue<T> : IUnsafeCollection<T>
|
||||
throw new InvalidOperationException("Queue is empty.");
|
||||
}
|
||||
|
||||
var value = UnsafeUtilities.ReadArrayElement<T>(_array.GetUnsafePtr(), _offset);
|
||||
var value = UnsafeUtility.ReadArrayElement<T>(_array.GetUnsafePtr(), _offset);
|
||||
_offset = (_offset + 1) % Capacity;
|
||||
_count--;
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ public unsafe struct UnsafeSlotMap<T> : IUnsafeCollection<T>
|
||||
|
||||
public readonly bool IsCreated => _data.IsCreated && _freeSlots.IsCreated;
|
||||
|
||||
public IEnumerator<T> GetEnumerator() => new Enumerator((UnsafeSlotMap<T>*)UnsafeUtilities.AddressOf(ref this));
|
||||
public IEnumerator<T> GetEnumerator() => new Enumerator((UnsafeSlotMap<T>*)UnsafeUtility.AddressOf(ref this));
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ public unsafe struct UnsafeSparseSet<T> : IUnsafeCollection<T>
|
||||
public readonly int Capacity => _capacity;
|
||||
public readonly bool IsCreated => _dense.IsCreated && _sparse.IsCreated && _reverse.IsCreated;
|
||||
|
||||
public IEnumerator<T> GetEnumerator() => new Enumerator((UnsafeSparseSet<T>*)UnsafeUtilities.AddressOf(ref this));
|
||||
public IEnumerator<T> GetEnumerator() => new Enumerator((UnsafeSparseSet<T>*)UnsafeUtility.AddressOf(ref this));
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -72,7 +72,7 @@ public unsafe struct UnsafeStack<T> : IUnsafeCollection<T>
|
||||
Resize(_array.Count + (int)(_array.Count * 0.5f));
|
||||
}
|
||||
|
||||
UnsafeUtilities.WriteArrayElement(_array.GetUnsafePtr(), _count, value);
|
||||
UnsafeUtility.WriteArrayElement(_array.GetUnsafePtr(), _count, value);
|
||||
_count++;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user